From cb268beaa9b159c19478d3b30a6504ca181dfabc Mon Sep 17 00:00:00 2001 From: Niklas von Hertzen Date: Tue, 29 Dec 2020 12:29:00 +0800 Subject: [PATCH] fix: opacity with overflow hidden (#2450) --- src/render/canvas/canvas-renderer.ts | 7 +++++-- src/render/effects.ts | 23 ++++++++++++++++------- src/render/stacking-context.ts | 6 +++++- tests/reftests/overflow/overflow.html | 1 + 4 files changed, 27 insertions(+), 10 deletions(-) diff --git a/src/render/canvas/canvas-renderer.ts b/src/render/canvas/canvas-renderer.ts index 93ca92340..f6d3a4af1 100644 --- a/src/render/canvas/canvas-renderer.ts +++ b/src/render/canvas/canvas-renderer.ts @@ -22,7 +22,7 @@ import {contentBox} from '../box-sizing'; import {CanvasElementContainer} from '../../dom/replaced-elements/canvas-element-container'; import {SVGElementContainer} from '../../dom/replaced-elements/svg-element-container'; import {ReplacedElementContainer} from '../../dom/replaced-elements/index'; -import {EffectTarget, IElementEffect, isClipEffect, isTransformEffect} from '../effects'; +import {EffectTarget, IElementEffect, isClipEffect, isOpacityEffect, isTransformEffect} from '../effects'; import {contains} from '../../core/bitwise'; import {calculateGradientDirection, calculateRadius, processColorStops} from '../../css/types/functions/gradient'; import {FIFTY_PERCENT, getAbsoluteValue} from '../../css/types/length-percentage'; @@ -99,6 +99,10 @@ export class CanvasRenderer { applyEffect(effect: IElementEffect) { this.ctx.save(); + if (isOpacityEffect(effect)) { + this.ctx.globalAlpha = effect.opacity; + } + if (isTransformEffect(effect)) { this.ctx.translate(effect.offsetX, effect.offsetY); this.ctx.transform( @@ -128,7 +132,6 @@ export class CanvasRenderer { async renderStack(stack: StackingContext) { const styles = stack.element.container.styles; if (styles.isVisible()) { - this.ctx.globalAlpha = styles.opacity; await this.renderStackContent(stack); } } diff --git a/src/render/effects.ts b/src/render/effects.ts index f9df190df..1bb428349 100644 --- a/src/render/effects.ts +++ b/src/render/effects.ts @@ -3,7 +3,8 @@ import {Path} from './path'; export const enum EffectType { TRANSFORM = 0, - CLIP = 1 + CLIP = 1, + OPACITY = 2 } export const enum EffectTarget { @@ -17,33 +18,41 @@ export interface IElementEffect { } export class TransformEffect implements IElementEffect { - readonly type: EffectType; - readonly target: number; + readonly type: EffectType = EffectType.TRANSFORM; + readonly target: number = EffectTarget.BACKGROUND_BORDERS | EffectTarget.CONTENT; readonly offsetX: number; readonly offsetY: number; readonly matrix: Matrix; constructor(offsetX: number, offsetY: number, matrix: Matrix) { - this.type = EffectType.TRANSFORM; this.offsetX = offsetX; this.offsetY = offsetY; this.matrix = matrix; - this.target = EffectTarget.BACKGROUND_BORDERS | EffectTarget.CONTENT; } } export class ClipEffect implements IElementEffect { - readonly type: EffectType; + readonly type: EffectType = EffectType.CLIP; readonly target: number; readonly path: Path[]; constructor(path: Path[], target: EffectTarget) { - this.type = EffectType.CLIP; this.target = target; this.path = path; } } +export class OpacityEffect implements IElementEffect { + readonly type: EffectType = EffectType.OPACITY; + readonly target: number = EffectTarget.BACKGROUND_BORDERS | EffectTarget.CONTENT; + readonly opacity: number; + + constructor(opacity: number) { + this.opacity = opacity; + } +} + export const isTransformEffect = (effect: IElementEffect): effect is TransformEffect => effect.type === EffectType.TRANSFORM; export const isClipEffect = (effect: IElementEffect): effect is ClipEffect => effect.type === EffectType.CLIP; +export const isOpacityEffect = (effect: IElementEffect): effect is OpacityEffect => effect.type === EffectType.OPACITY; diff --git a/src/render/stacking-context.ts b/src/render/stacking-context.ts index 27787b619..5cba00bfd 100644 --- a/src/render/stacking-context.ts +++ b/src/render/stacking-context.ts @@ -1,7 +1,7 @@ import {ElementContainer, FLAGS} from '../dom/element-container'; import {contains} from '../core/bitwise'; import {BoundCurves, calculateBorderBoxPath, calculatePaddingBoxPath} from './bound-curves'; -import {ClipEffect, EffectTarget, IElementEffect, TransformEffect} from './effects'; +import {ClipEffect, EffectTarget, IElementEffect, OpacityEffect, TransformEffect} from './effects'; import {OVERFLOW} from '../css/property-descriptors/overflow'; import {equalPath} from './path'; import {DISPLAY} from '../css/property-descriptors/display'; @@ -41,6 +41,10 @@ export class ElementPaint { this.container = element; this.effects = parentStack.slice(0); this.curves = new BoundCurves(element); + if (element.styles.opacity < 1) { + this.effects.push(new OpacityEffect(element.styles.opacity)); + } + if (element.styles.transform !== null) { const offsetX = element.bounds.left + element.styles.transformOrigin[0].number; const offsetY = element.bounds.top + element.styles.transformOrigin[1].number; diff --git a/tests/reftests/overflow/overflow.html b/tests/reftests/overflow/overflow.html index 43618a56c..6a9f0e9a6 100644 --- a/tests/reftests/overflow/overflow.html +++ b/tests/reftests/overflow/overflow.html @@ -128,5 +128,6 @@

Overflow: hidden

+