Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(93)

Unified Diff: third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp

Issue 2641173008: [SPv2] Add CSS mask support (Closed)
Patch Set: Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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);

Powered by Google App Engine
This is Rietveld 408576698