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

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

Issue 1461223002: Implement SVG's transform and effect paint property nodes (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix fixed position bug discovered by TienRen Created 5 years, 1 month 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 e226295a57f2bfc10dd57946c898c49f5e5e9119..39690996f9051510878485d11b25efe7527025d7 100644
--- a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp
+++ b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp
@@ -79,21 +79,26 @@ void PaintPropertyTreeBuilder::walk(FrameView& frameView, const PaintPropertyTre
walk(*layoutView, localContext);
}
-static void deriveBorderBoxFromContainerContext(const LayoutBoxModelObject& object, PaintPropertyTreeBuilderContext& context)
+static void deriveBorderBoxFromContainerContext(const LayoutObject& object, PaintPropertyTreeBuilderContext& context)
{
+ if (!object.isBoxModelObject())
+ return;
+
+ const LayoutBoxModelObject& boxModelObject = toLayoutBoxModelObject(object);
+
// TODO(trchen): There is some insanity going on with tables. Double check results.
switch (object.styleRef().position()) {
case StaticPosition:
break;
case RelativePosition:
- context.paintOffset += object.offsetForInFlowPosition();
+ context.paintOffset += boxModelObject.offsetForInFlowPosition();
break;
case AbsolutePosition:
context.currentTransform = context.transformForOutOfFlowPositioned;
context.paintOffset = context.paintOffsetForOutOfFlowPositioned;
break;
case StickyPosition:
- context.paintOffset += object.offsetForInFlowPosition();
+ context.paintOffset += boxModelObject.offsetForInFlowPosition();
break;
case FixedPosition:
context.currentTransform = context.transformForFixedPositioned;
@@ -102,14 +107,21 @@ static void deriveBorderBoxFromContainerContext(const LayoutBoxModelObject& obje
default:
ASSERT_NOT_REACHED();
}
- if (object.isBox())
- context.paintOffset += toLayoutBox(object).locationOffset();
+ if (boxModelObject.isBox())
+ context.paintOffset += toLayoutBox(boxModelObject).locationOffset();
}
-static PassRefPtr<TransformPaintPropertyNode> createPaintOffsetTranslationIfNeeded(const LayoutBoxModelObject& object, PaintPropertyTreeBuilderContext& context)
+static PassRefPtr<TransformPaintPropertyNode> createPaintOffsetTranslationIfNeeded(const LayoutObject& object, PaintPropertyTreeBuilderContext& context)
{
- // TODO(trchen): Eliminate PaintLayer dependency.
- bool shouldCreatePaintOffsetTranslationNode = object.layer() && object.layer()->paintsWithTransform(GlobalPaintNormalPhase);
+ bool shouldCreatePaintOffsetTranslationNode = false;
+ if (object.isSVGRoot()) {
+ // SVG doesn't use paint offset internally so emit a paint offset at the html->svg boundary.
+ shouldCreatePaintOffsetTranslationNode = true;
+ } else if (object.isBoxModelObject()) {
+ // TODO(trchen): Eliminate PaintLayer dependency.
+ PaintLayer* layer = toLayoutBoxModelObject(object).layer();
+ shouldCreatePaintOffsetTranslationNode = layer && layer->paintsWithTransform(GlobalPaintNormalPhase);
+ }
if (context.paintOffset == LayoutPoint() || !shouldCreatePaintOffsetTranslationNode)
return nullptr;
@@ -132,8 +144,20 @@ static FloatPoint3D transformOrigin(const LayoutBox& box)
style.transformOriginZ());
}
-static PassRefPtr<TransformPaintPropertyNode> createTransformIfNeeded(const LayoutBoxModelObject& object, PaintPropertyTreeBuilderContext& context)
+static PassRefPtr<TransformPaintPropertyNode> createTransformIfNeeded(const LayoutObject& object, PaintPropertyTreeBuilderContext& context)
{
+ if (object.isSVG() && !object.isSVGRoot()) {
+ const AffineTransform& transform = object.localToParentTransform();
+ if (transform.isIdentity())
+ return nullptr;
+
+ // SVG's transform origin is baked into the localToParentTransform.
+ RefPtr<TransformPaintPropertyNode> newTransformNodeForTransform = TransformPaintPropertyNode::create(
+ transform, FloatPoint3D(0, 0, 0), context.currentTransform);
+ context.currentTransform = newTransformNodeForTransform.get();
+ return newTransformNodeForTransform.release();
+ }
+
const ComputedStyle& style = object.styleRef();
if (!object.isBox() || !style.hasTransform())
return nullptr;
@@ -149,10 +173,10 @@ static PassRefPtr<TransformPaintPropertyNode> createTransformIfNeeded(const Layo
return newTransformNodeForTransform.release();
}
-static PassRefPtr<EffectPaintPropertyNode> createEffectIfNeeded(const LayoutBoxModelObject& object, PaintPropertyTreeBuilderContext& context)
+static PassRefPtr<EffectPaintPropertyNode> createEffectIfNeeded(const LayoutObject& object, PaintPropertyTreeBuilderContext& context)
{
const ComputedStyle& style = object.styleRef();
- if (!object.isBox() || !style.hasOpacity())
+ if (!style.hasOpacity())
return nullptr;
RefPtr<EffectPaintPropertyNode> newEffectNode = EffectPaintPropertyNode::create(style.opacity(), context.currentEffect);
context.currentEffect = newEffectNode.get();
@@ -168,7 +192,7 @@ static FloatPoint perspectiveOrigin(const LayoutBox& box)
floatValueForLength(style.perspectiveOriginY(), borderBoxSize.height()));
}
-static PassRefPtr<TransformPaintPropertyNode> createPerspectiveIfNeeded(const LayoutBoxModelObject& object, PaintPropertyTreeBuilderContext& context)
+static PassRefPtr<TransformPaintPropertyNode> createPerspectiveIfNeeded(const LayoutObject& object, PaintPropertyTreeBuilderContext& context)
{
const ComputedStyle& style = object.styleRef();
if (!object.isBox() || !style.hasPerspective())
@@ -181,12 +205,12 @@ static PassRefPtr<TransformPaintPropertyNode> createPerspectiveIfNeeded(const La
return newTransformNodeForPerspective.release();
}
-static PassRefPtr<TransformPaintPropertyNode> createScrollTranslationIfNeeded(const LayoutBoxModelObject& object, PaintPropertyTreeBuilderContext& context)
+static PassRefPtr<TransformPaintPropertyNode> createScrollTranslationIfNeeded(const LayoutObject& object, PaintPropertyTreeBuilderContext& context)
{
- if (!object.hasOverflowClip())
+ if (!object.isBoxModelObject() || !object.hasOverflowClip())
return nullptr;
- PaintLayer* layer = object.layer();
+ PaintLayer* layer = toLayoutBoxModelObject(object).layer();
ASSERT(layer);
DoubleSize scrollOffset = layer->scrollableArea()->scrollOffset();
if (scrollOffset.isZero() && !layer->scrollsOverflow())
@@ -199,24 +223,26 @@ static PassRefPtr<TransformPaintPropertyNode> createScrollTranslationIfNeeded(co
return newTransformNodeForScrollTranslation.release();
}
-static void updateOutOfFlowContext(const LayoutBoxModelObject& object, PaintPropertyTreeBuilderContext& context)
+static void updateOutOfFlowContext(const LayoutObject& object, bool createdNewTransform, PaintPropertyTreeBuilderContext& context)
{
- const ComputedStyle& style = object.styleRef();
- bool hasTransform = object.isBox() && style.hasTransform();
- if (style.position() != StaticPosition || hasTransform) {
+ // At the html->svg boundary (see: createPaintOffsetTranslationIfNeeded) the currentTransform is
+ // up-to-date for all children of the svg root element. Additionally, inside SVG, all positioning
+ // uses transforms. Therefore, we only need to check createdNewTransform and isSVGRoot() to
+ // ensure out-of-flow and fixed positioning is correct at the svg->html boundary.
+
+ if (object.styleRef().position() != StaticPosition || createdNewTransform || object.isSVGRoot()) {
jbroman 2015/11/23 17:51:00 Out of curiosity (arguably out of scope for this p
trchen 2015/11/23 19:28:29 I think yes. Looks like it's pretty safe to use.
context.transformForOutOfFlowPositioned = context.currentTransform;
context.paintOffsetForOutOfFlowPositioned = context.paintOffset;
}
- if (hasTransform) {
+
+ if (createdNewTransform || object.isSVGRoot()) {
context.transformForFixedPositioned = context.currentTransform;
context.paintOffsetForFixedPositioned = context.paintOffset;
}
}
-void PaintPropertyTreeBuilder::walk(LayoutBoxModelObject& object, const PaintPropertyTreeBuilderContext& context)
+void PaintPropertyTreeBuilder::walk(LayoutObject& object, const PaintPropertyTreeBuilderContext& context)
{
- ASSERT(object.isBox() != object.isLayoutInline()); // Either or.
-
PaintPropertyTreeBuilderContext localContext(context);
deriveBorderBoxFromContainerContext(object, localContext);
@@ -225,7 +251,7 @@ void PaintPropertyTreeBuilder::walk(LayoutBoxModelObject& object, const PaintPro
RefPtr<EffectPaintPropertyNode> newEffectNode = createEffectIfNeeded(object, localContext);
RefPtr<TransformPaintPropertyNode> newTransformNodeForPerspective = createPerspectiveIfNeeded(object, localContext);
RefPtr<TransformPaintPropertyNode> newTransformNodeForScrollTranslation = createScrollTranslationIfNeeded(object, localContext);
- updateOutOfFlowContext(object, localContext);
+ updateOutOfFlowContext(object, newTransformNodeForTransform, localContext);
if (newTransformNodeForPaintOffsetTranslation || newTransformNodeForTransform || newEffectNode || newTransformNodeForPerspective || newTransformNodeForScrollTranslation) {
OwnPtr<ObjectPaintProperties> updatedPaintProperties = ObjectPaintProperties::create(
@@ -241,15 +267,9 @@ void PaintPropertyTreeBuilder::walk(LayoutBoxModelObject& object, const PaintPro
// TODO(trchen): Walk subframes for LayoutFrame.
- // TODO(trchen): Implement SVG walk.
- if (object.isSVGRoot()) {
- return;
- }
-
for (LayoutObject* child = object.slowFirstChild(); child; child = child->nextSibling()) {
- if (child->isText())
- continue;
- walk(toLayoutBoxModelObject(*child), localContext);
+ if (child->isBoxModelObject() || child->isSVG())
+ walk(*child, localContext);
}
}

Powered by Google App Engine
This is Rietveld 408576698