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

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

Issue 1407543003: Preliminary paint property walk implementation for SPv2 (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: revert forAllFrameViews change in FrameView.cpp. I don't know what I was thinking. Created 5 years, 2 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
new file mode 100644
index 0000000000000000000000000000000000000000..35e4e56bcf07d328d80b13c22998aa914494df75
--- /dev/null
+++ b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp
@@ -0,0 +1,240 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "config.h"
+#include "core/paint/PaintPropertyTreeBuilder.h"
+
+#include "core/frame/FrameView.h"
+#include "core/layout/LayoutView.h"
+#include "core/paint/ObjectPaintProperties.h"
+#include "core/paint/PaintLayer.h"
+#include "platform/graphics/paint/TransformPaintPropertyNode.h"
+#include "platform/transforms/TransformationMatrix.h"
+
+namespace blink {
+
+// The context for layout tree walk.
+// The walk will be done in the primary tree order (= DOM order), thus the context will also be
+// responsible for bookkeeping tree state in other order, for example, the most recent position
+// container seen.
+struct PaintPropertyTreeBuilderContext {
+ PaintPropertyTreeBuilderContext() : currentTransform(nullptr), transformForOutOfFlowPositioned(nullptr), transformForFixedPositioned(nullptr) { }
+
+ // The combination of a transform and paint offset describes a linear space.
+ // When a layout object recur to its children, the main context is expected to refer
+ // the object's border box, then the callee will derive its own border box by translating
+ // the space with its own layout location.
+ TransformPaintPropertyNode* currentTransform;
+ LayoutPoint paintOffset;
+
+ // Separate context for out-of-flow positioned and fixed positioned elements are needed
+ // because they don't use DOM parent as their positioning parent (i.e. containing block).
+ // These additional contexts normally pass through untouched, and are only copied from
+ // the main context when the current element serves as the positioning parent of corresponding
+ // positioned descendants.
+ TransformPaintPropertyNode* transformForOutOfFlowPositioned;
+ LayoutPoint paintOffsetForOutOfFlowPositioned;
+
+ TransformPaintPropertyNode* transformForFixedPositioned;
+ LayoutPoint paintOffsetForFixedPositioned;
+};
+
+void PaintPropertyTreeBuilder::buildPropertyTrees(FrameView& rootFrame)
+{
+ walk(rootFrame, PaintPropertyTreeBuilderContext());
+}
+
+void PaintPropertyTreeBuilder::walk(FrameView& frameView, const PaintPropertyTreeBuilderContext& context)
+{
+ PaintPropertyTreeBuilderContext localContext(context);
+
+ TransformationMatrix frameTranslate;
+ frameTranslate.translate(frameView.x(), frameView.y());
+ // The frame owner applies paint offset already.
+ // This assumption may change in the future.
+ ASSERT(context.paintOffset == LayoutPoint());
+ RefPtr<TransformPaintPropertyNode> newTransformNodeForPreTranslation = TransformPaintPropertyNode::create(frameTranslate, FloatPoint3D(), context.currentTransform);
+ localContext.transformForFixedPositioned = newTransformNodeForPreTranslation.get();
+ localContext.paintOffsetForFixedPositioned = LayoutPoint();
+
+ // This is going away in favor of Settings::rootLayerScrolls.
+ DoubleSize scrollOffset = frameView.scrollOffsetDouble();
+ TransformationMatrix frameScroll;
+ frameScroll.translate(-scrollOffset.width(), -scrollOffset.height());
+ RefPtr<TransformPaintPropertyNode> newTransformNodeForScrollTranslation = TransformPaintPropertyNode::create(frameScroll, FloatPoint3D(), newTransformNodeForPreTranslation);
+ localContext.currentTransform = localContext.transformForOutOfFlowPositioned = newTransformNodeForScrollTranslation.get();
+ localContext.paintOffset = localContext.paintOffsetForOutOfFlowPositioned = LayoutPoint();
+
+ frameView.setPreTranslation(newTransformNodeForPreTranslation.release());
+ frameView.setScrollTranslation(newTransformNodeForScrollTranslation.release());
+
+ if (LayoutView* layoutView = frameView.layoutView())
+ walk(*layoutView, localContext);
+}
+
+static void deriveBorderBoxFromContainerContext(const LayoutBoxModelObject& object, PaintPropertyTreeBuilderContext& context)
+{
+ // 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();
+ break;
+ case AbsolutePosition:
+ context.currentTransform = context.transformForOutOfFlowPositioned;
+ context.paintOffset = context.paintOffsetForOutOfFlowPositioned;
+ break;
+ case StickyPosition:
+ context.paintOffset += object.offsetForInFlowPosition();
+ break;
+ case FixedPosition:
+ context.currentTransform = context.transformForFixedPositioned;
+ context.paintOffset = context.paintOffsetForFixedPositioned;
+ break;
+ default:
+ ASSERT_NOT_REACHED();
+ }
+ if (object.isBox())
+ context.paintOffset += toLayoutBox(object).locationOffset();
+}
+
+static PassRefPtr<TransformPaintPropertyNode> createPaintOffsetTranslationIfNeeded(const LayoutBoxModelObject& object, PaintPropertyTreeBuilderContext& context)
+{
+ // TODO(trchen): Eliminate PaintLayer dependency.
+ bool shouldCreatePaintOffsetTranslationNode = object.layer() && object.layer()->paintsWithTransform(GlobalPaintNormalPhase);
+
+ if (context.paintOffset == LayoutPoint() || !shouldCreatePaintOffsetTranslationNode)
+ return nullptr;
+
+ TransformationMatrix matrix;
+ matrix.translate(context.paintOffset.x(), context.paintOffset.y());
+ RefPtr<TransformPaintPropertyNode> newTransformNodeForPaintOffsetTranslation = TransformPaintPropertyNode::create(
+ TransformationMatrix().translate(context.paintOffset.x(), context.paintOffset.y()),
+ FloatPoint3D(), context.currentTransform);
+ context.currentTransform = newTransformNodeForPaintOffsetTranslation.get();
+ context.paintOffset = LayoutPoint();
+ return newTransformNodeForPaintOffsetTranslation.release();
+}
+
+static FloatPoint3D transformOrigin(const LayoutBox& box)
+{
+ const ComputedStyle& style = box.styleRef();
+ FloatSize borderBoxSize(box.size());
+ return FloatPoint3D(
+ floatValueForLength(style.transformOriginX(), borderBoxSize.width()),
+ floatValueForLength(style.transformOriginY(), borderBoxSize.height()),
+ style.transformOriginZ());
+}
+
+static PassRefPtr<TransformPaintPropertyNode> createTransformIfNeeded(const LayoutBoxModelObject& object, PaintPropertyTreeBuilderContext& context)
+{
+ const ComputedStyle& style = object.styleRef();
+ if (!object.isBox() || !style.hasTransform())
+ return nullptr;
+
+ ASSERT(context.paintOffset == LayoutPoint());
+
+ TransformationMatrix matrix;
+ style.applyTransform(matrix, toLayoutBox(object).size(), ComputedStyle::ExcludeTransformOrigin,
+ ComputedStyle::IncludeMotionPath, ComputedStyle::IncludeIndependentTransformProperties);
+ RefPtr<TransformPaintPropertyNode> newTransformNodeForTransform = TransformPaintPropertyNode::create(
+ matrix, transformOrigin(toLayoutBox(object)), context.currentTransform);
+ context.currentTransform = newTransformNodeForTransform.get();
+ return newTransformNodeForTransform.release();
+}
+
+static FloatPoint perspectiveOrigin(const LayoutBox& box)
+{
+ const ComputedStyle& style = box.styleRef();
+ FloatSize borderBoxSize(box.size());
+ return FloatPoint(
+ floatValueForLength(style.perspectiveOriginX(), borderBoxSize.width()),
+ floatValueForLength(style.perspectiveOriginY(), borderBoxSize.height()));
+}
+
+static PassRefPtr<TransformPaintPropertyNode> createPerspectiveIfNeeded(const LayoutBoxModelObject& object, PaintPropertyTreeBuilderContext& context)
+{
+ const ComputedStyle& style = object.styleRef();
+ if (!object.isBox() || !style.hasPerspective())
+ return nullptr;
+
+ RefPtr<TransformPaintPropertyNode> newTransformNodeForPerspective = TransformPaintPropertyNode::create(
+ TransformationMatrix().applyPerspective(style.perspective()),
+ perspectiveOrigin(toLayoutBox(object)) + toLayoutSize(context.paintOffset), context.currentTransform);
+ context.currentTransform = newTransformNodeForPerspective.get();
+
+ return newTransformNodeForPerspective.release();
+}
+
+static PassRefPtr<TransformPaintPropertyNode> createScrollTranslationIfNeeded(const LayoutBoxModelObject& object, PaintPropertyTreeBuilderContext& context)
+{
+ if (!object.hasOverflowClip())
+ return nullptr;
+
+ PaintLayer* layer = object.layer();
+ ASSERT(layer);
+ DoubleSize scrollOffset = layer->scrollableArea()->scrollOffset();
+ if (scrollOffset.isZero() && !layer->scrollsOverflow())
+ return nullptr;
+
+ RefPtr<TransformPaintPropertyNode> newTransformNodeForScrollTranslation = TransformPaintPropertyNode::create(
+ TransformationMatrix().translate(-scrollOffset.width(), -scrollOffset.height()),
+ FloatPoint3D(), context.currentTransform);
+ context.currentTransform = newTransformNodeForScrollTranslation.get();
+ return newTransformNodeForScrollTranslation.release();
+}
+
+static void updateOutOfFlowContext(const LayoutBoxModelObject& object, PaintPropertyTreeBuilderContext& context)
+{
+ const ComputedStyle& style = object.styleRef();
+ bool hasTransform = object.isBox() && style.hasTransform();
+ if (style.position() != StaticPosition || hasTransform) {
+ context.transformForOutOfFlowPositioned = context.currentTransform;
+ context.paintOffsetForOutOfFlowPositioned = context.paintOffset;
+ }
+ if (hasTransform) {
+ context.transformForFixedPositioned = context.currentTransform;
+ context.paintOffsetForFixedPositioned = context.paintOffset;
+ }
+}
+
+void PaintPropertyTreeBuilder::walk(LayoutBoxModelObject& object, const PaintPropertyTreeBuilderContext& context)
+{
+ ASSERT(object.isBox() != object.isLayoutInline()); // Either or.
+
+ PaintPropertyTreeBuilderContext localContext(context);
+
+ deriveBorderBoxFromContainerContext(object, localContext);
+ RefPtr<TransformPaintPropertyNode> newTransformNodeForPaintOffsetTranslation = createPaintOffsetTranslationIfNeeded(object, localContext);
+ RefPtr<TransformPaintPropertyNode> newTransformNodeForTransform = createTransformIfNeeded(object, localContext);
+ RefPtr<TransformPaintPropertyNode> newTransformNodeForPerspective = createPerspectiveIfNeeded(object, localContext);
+ RefPtr<TransformPaintPropertyNode> newTransformNodeForScrollTranslation = createScrollTranslationIfNeeded(object, localContext);
+ updateOutOfFlowContext(object, localContext);
+
+ if (newTransformNodeForPaintOffsetTranslation || newTransformNodeForTransform || newTransformNodeForPerspective || newTransformNodeForScrollTranslation) {
+ ObjectPaintProperties& properties = object.ensureObjectPaintProperties();
+ properties.setPaintOffsetTranslation(newTransformNodeForPaintOffsetTranslation.release());
+ properties.setTransform(newTransformNodeForTransform.release());
+ properties.setPerspective(newTransformNodeForPerspective.release());
+ properties.setScrollTranslation(newTransformNodeForScrollTranslation.release());
+ } else {
+ object.clearObjectPaintProperties();
+ }
+
+ // 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);
+ }
+}
+
+} // namespace blink

Powered by Google App Engine
This is Rietveld 408576698