Chromium Code Reviews| Index: third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp |
| diff --git a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp |
| index d7c0c390bc432ea475bd9a54edbce2318900eca1..4e626a960beedbf2ae1737c7a22df453fe17175e 100644 |
| --- a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp |
| +++ b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp |
| @@ -430,6 +430,75 @@ void PaintPropertyTreeBuilder::updateTransform( |
| } |
| } |
| +void PaintPropertyTreeBuilder::updateMask( |
| + const LayoutObject& object, |
| + PaintPropertyTreeBuilderContext& context) { |
| + DCHECK(object.isBoxModelObject() || object.isSVGChild()); |
| + const ComputedStyle& style = object.styleRef(); |
| + |
| + bool hasMask = false; |
| + IntRect maskClip; |
| + if (object.isSVGChild()) { |
| + // TODO(trchen): Figure out what to do with SVG. SVG may use object |
| + // bounding box for mask sizing, but computing it requires property |
| + // tree to be built. |
| + } else if (style.hasMask()) { |
| + // For HTML/CSS objects, the extent of the mask is known as "mask |
| + // painting area", which is determined by CSS mask-clip property. |
| + // We don't implement mask-clip:margin-box or no-clip currently, |
| + // so the maximum we can get is border-box. |
| + LayoutRect maximumMaskRegion; |
| + if (object.isBox()) { |
| + maximumMaskRegion = toLayoutBox(object).borderBoxRect(); |
| + } else { |
| + // For inline elements, depends on the value of box-decoration-break |
| + // there could be one box in multiple fragments or multiple boxes. |
| + // Either way here we are only interested in the bounding box of them. |
| + DCHECK(object.isLayoutInline()); |
| + maximumMaskRegion = toLayoutInline(object).linesBoundingBox(); |
| + } |
| + maximumMaskRegion.moveBy(context.current.paintOffset); |
| + maskClip = enclosingIntRect(maximumMaskRegion); |
| + hasMask = true; |
| + } |
| + |
| + if (object.needsPaintPropertyUpdate() || context.forceSubtreeUpdate) { |
| + if (hasMask) { |
| + SkBlendMode blendMode = object.isBlendingAllowed() |
| + ? WebCoreCompositeToSkiaComposite( |
| + CompositeSourceOver, style.blendMode()) |
| + : SkBlendMode::kSrcOver; |
| + float opacity = style.opacity(); |
| + |
| + auto& properties = object.getMutableForPainting().ensurePaintProperties(); |
| + context.forceSubtreeUpdate |= properties.updateMaskClip( |
| + context.current.clip, context.current.transform, |
| + FloatRoundedRect(maskClip)); |
| + context.forceSubtreeUpdate |= properties.updateMaskIsolation( |
| + context.currentEffect, context.current.transform, |
| + properties.maskClip(), CompositorFilterOperations(), opacity, |
| + blendMode, CompositingReasonNone, CompositorElementId()); |
| + context.forceSubtreeUpdate |= properties.updateMaskContent( |
| + properties.maskIsolation(), context.current.transform, |
| + properties.maskClip(), CompositorFilterOperations(), 1.f, |
| + SkBlendMode::kDstIn, CompositingReasonNone, CompositorElementId()); |
| + } else if (auto* properties = |
| + object.getMutableForPainting().paintProperties()) { |
| + context.forceSubtreeUpdate |= properties->clearMaskClip(); |
| + context.forceSubtreeUpdate |= properties->clearMaskIsolation(); |
| + context.forceSubtreeUpdate |= properties->clearMaskContent(); |
| + } |
| + } |
| + |
| + if (hasMask) { |
| + auto& properties = *object.getMutableForPainting().paintProperties(); |
| + context.inputClipOfCurrentEffect = context.current.clip = |
| + context.absolutePosition.clip = context.fixedPosition.clip = |
| + properties.maskClip(); |
| + context.currentEffect = properties.maskIsolation(); |
| + } |
| +} |
| + |
| void PaintPropertyTreeBuilder::updateEffect( |
| const LayoutObject& object, |
| PaintPropertyTreeBuilderContext& context) { |
| @@ -447,10 +516,16 @@ void PaintPropertyTreeBuilder::updateEffect( |
| // TODO(trchen): Can't omit effect node if we have 3D children. |
| if (object.needsPaintPropertyUpdate() || context.forceSubtreeUpdate) { |
| + bool blendModeAndOpacityAlreadyApplied = false; |
|
trchen
2017/01/21 01:27:08
I feel this blend mode & opacity juggling will mak
chrishtr
2017/01/24 01:16:28
How about just making different nodes for all of t
trchen
2017/02/11 02:35:45
As discussed offline. Kick filter out is the most
|
| + if (auto* properties = object.getMutableForPainting().paintProperties()) |
| + blendModeAndOpacityAlreadyApplied = !!properties->maskIsolation(); |
| + |
| bool effectNodeNeeded = false; |
| // Can't omit effect node if we have paint children with exotic blending. |
| - if (object.isSVG()) { |
| + if (blendModeAndOpacityAlreadyApplied) { |
| + // No-op. The current effect node already isolated for us. |
| + } else if (object.isSVG()) { |
| // Yes, including LayoutSVGRoot, because SVG layout objects don't create |
| // PaintLayer so PaintLayer::hasNonIsolatedDescendantWithBlendMode() |
| // doesn't catch SVG descendants. |
| @@ -461,14 +536,15 @@ void PaintPropertyTreeBuilder::updateEffect( |
| effectNodeNeeded = true; |
| } |
| - SkBlendMode blendMode = object.isBlendingAllowed() |
| - ? WebCoreCompositeToSkiaComposite( |
| - CompositeSourceOver, style.blendMode()) |
| - : SkBlendMode::kSrcOver; |
| + SkBlendMode blendMode = |
| + (!blendModeAndOpacityAlreadyApplied && object.isBlendingAllowed()) |
| + ? WebCoreCompositeToSkiaComposite(CompositeSourceOver, |
| + style.blendMode()) |
| + : SkBlendMode::kSrcOver; |
| if (blendMode != SkBlendMode::kSrcOver) |
| effectNodeNeeded = true; |
| - float opacity = style.opacity(); |
| + float opacity = blendModeAndOpacityAlreadyApplied ? 1.0f : style.opacity(); |
| if (opacity != 1.0f) |
| effectNodeNeeded = true; |
| @@ -962,6 +1038,7 @@ void PaintPropertyTreeBuilder::updatePropertiesForSelf( |
| if (object.isBoxModelObject() || object.isSVG()) { |
| updatePaintOffsetTranslation(object, context); |
| updateTransform(object, context); |
| + updateMask(object, context); |
| updateEffect(object, context); |
| updateCssClip(object, context); |
| updateLocalBorderBoxContext(object, context); |