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

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

Issue 1774193002: New paint invalidation using paint property tree walk (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 9 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
deleted file mode 100644
index 224f99c3872452f09416b9b52931a5de571633fb..0000000000000000000000000000000000000000
--- a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp
+++ /dev/null
@@ -1,364 +0,0 @@
-// 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 "core/paint/PaintPropertyTreeBuilder.h"
-
-#include "core/frame/FrameView.h"
-#include "core/layout/LayoutPart.h"
-#include "core/layout/LayoutView.h"
-#include "core/paint/ObjectPaintProperties.h"
-#include "core/paint/PaintLayer.h"
-#include "platform/graphics/paint/ClipPaintPropertyNode.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)
- , currentClip(nullptr)
- , transformForAbsolutePosition(nullptr)
- , clipForAbsolutePosition(nullptr)
- , transformForFixedPosition(nullptr)
- , clipForFixedPosition(nullptr)
- , currentEffect(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;
- // The clip node describes the accumulated raster clip for the current subtree.
- // Note that the computed raster region in canvas space for a clip node is independent from
- // the transform and paint offset above. Also the actual raster region may be affected
- // by layerization and occlusion tracking.
- ClipPaintPropertyNode* currentClip;
-
- // Separate context for out-of-flow positioned and fixed positioned elements are needed
- // because they don't use DOM parent as their containing block.
- // These additional contexts normally pass through untouched, and are only copied from
- // the main context when the current element serves as the containing block of corresponding
- // positioned descendants.
- // Overflow clips are also inherited by containing block tree instead of DOM tree, thus they
- // are included in the additional context too.
- TransformPaintPropertyNode* transformForAbsolutePosition;
- LayoutPoint paintOffsetForAbsolutePosition;
- ClipPaintPropertyNode* clipForAbsolutePosition;
-
- TransformPaintPropertyNode* transformForFixedPosition;
- LayoutPoint paintOffsetForFixedPosition;
- ClipPaintPropertyNode* clipForFixedPosition;
-
- // The effect hierarchy is applied by the stacking context tree. It is guaranteed that every
- // DOM descendant is also a stacking context descendant. Therefore, we don't need extra
- // bookkeeping for effect nodes and can generate the effect tree from a DOM-order traversal.
- EffectPaintPropertyNode* currentEffect;
-};
-
-void PaintPropertyTreeBuilder::buildPropertyTrees(FrameView& rootFrame)
-{
- walk(rootFrame, PaintPropertyTreeBuilderContext());
-}
-
-void PaintPropertyTreeBuilder::walk(FrameView& frameView, const PaintPropertyTreeBuilderContext& context)
-{
- PaintPropertyTreeBuilderContext localContext(context);
-
- // TODO(pdr): Creating paint properties for FrameView here will not be
- // needed once settings()->rootLayerScrolls() is enabled.
- // TODO(pdr): Make this conditional on the rootLayerScrolls setting.
-
- TransformationMatrix frameTranslate;
- frameTranslate.translate(frameView.x() + context.paintOffset.x(), frameView.y() + context.paintOffset.y());
- RefPtr<TransformPaintPropertyNode> newTransformNodeForPreTranslation = TransformPaintPropertyNode::create(frameTranslate, FloatPoint3D(), context.currentTransform);
- localContext.transformForFixedPosition = newTransformNodeForPreTranslation.get();
- localContext.paintOffsetForFixedPosition = LayoutPoint();
-
- FloatRoundedRect contentClip(IntRect(IntPoint(), frameView.visibleContentSize()));
- RefPtr<ClipPaintPropertyNode> newClipNodeForContentClip = ClipPaintPropertyNode::create(newTransformNodeForPreTranslation.get(), contentClip, localContext.currentClip);
- localContext.currentClip = localContext.clipForAbsolutePosition = localContext.clipForFixedPosition = newClipNodeForContentClip.get();
-
- DoubleSize scrollOffset = frameView.scrollOffsetDouble();
- TransformationMatrix frameScroll;
- frameScroll.translate(-scrollOffset.width(), -scrollOffset.height());
- RefPtr<TransformPaintPropertyNode> newTransformNodeForScrollTranslation = TransformPaintPropertyNode::create(frameScroll, FloatPoint3D(), newTransformNodeForPreTranslation);
- localContext.currentTransform = localContext.transformForAbsolutePosition = newTransformNodeForScrollTranslation.get();
- localContext.paintOffset = localContext.paintOffsetForAbsolutePosition = LayoutPoint();
-
- frameView.setPreTranslation(newTransformNodeForPreTranslation.release());
- frameView.setScrollTranslation(newTransformNodeForScrollTranslation.release());
- frameView.setContentClip(newClipNodeForContentClip.release());
-
- if (LayoutView* layoutView = frameView.layoutView())
- walk(*layoutView, localContext);
-}
-
-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 += boxModelObject.offsetForInFlowPosition();
- break;
- case AbsolutePosition:
- context.currentTransform = context.transformForAbsolutePosition;
- context.paintOffset = context.paintOffsetForAbsolutePosition;
- context.currentClip = context.clipForAbsolutePosition;
- break;
- case StickyPosition:
- context.paintOffset += boxModelObject.offsetForInFlowPosition();
- break;
- case FixedPosition:
- context.currentTransform = context.transformForFixedPosition;
- context.paintOffset = context.paintOffsetForFixedPosition;
- context.currentClip = context.clipForFixedPosition;
- break;
- default:
- ASSERT_NOT_REACHED();
- }
- if (boxModelObject.isBox())
- context.paintOffset += toLayoutBox(boxModelObject).locationOffset();
-}
-
-static PassRefPtr<TransformPaintPropertyNode> createPaintOffsetTranslationIfNeeded(const LayoutObject& object, PaintPropertyTreeBuilderContext& context)
-{
- 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;
-
- 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 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;
-
- 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 PassRefPtr<EffectPaintPropertyNode> createEffectIfNeeded(const LayoutObject& object, PaintPropertyTreeBuilderContext& context)
-{
- const ComputedStyle& style = object.styleRef();
- if (!style.hasOpacity())
- return nullptr;
- RefPtr<EffectPaintPropertyNode> newEffectNode = EffectPaintPropertyNode::create(style.opacity(), context.currentEffect);
- context.currentEffect = newEffectNode.get();
- return newEffectNode.release();
-}
-
-static PassRefPtr<ClipPaintPropertyNode> createOverflowClipIfNeeded(const LayoutObject& object, PaintPropertyTreeBuilderContext& context)
-{
- if (!object.isBox())
- return nullptr;
- const LayoutBox& box = toLayoutBox(object);
-
- // The <input> elements can't have contents thus CSS overflow property doesn't apply.
- // However for layout purposes we do generate child layout objects for them, e.g. button label.
- // We should clip the overflow from those children. This is called control clip and we
- // technically treat them like overflow clip.
- LayoutRect clipRect;
- if (box.hasControlClip())
- clipRect = box.controlClipRect(context.paintOffset);
- else if (box.hasOverflowClip())
- clipRect = box.overflowClipRect(context.paintOffset);
- else
- return nullptr;
-
- RefPtr<ClipPaintPropertyNode> newClipNodeForBorderRadiusClip;
- const ComputedStyle& style = box.styleRef();
- if (style.hasBorderRadius()) {
- newClipNodeForBorderRadiusClip = ClipPaintPropertyNode::create(
- context.currentTransform,
- style.getRoundedInnerBorderFor(LayoutRect(context.paintOffset, box.size())),
- context.currentClip);
- }
-
- RefPtr<ClipPaintPropertyNode> newClipNodeForOverflowClip = ClipPaintPropertyNode::create(
- context.currentTransform,
- FloatRoundedRect(FloatRect(clipRect)),
- newClipNodeForBorderRadiusClip ? newClipNodeForBorderRadiusClip.release() : context.currentClip);
- context.currentClip = newClipNodeForOverflowClip.get();
- return newClipNodeForOverflowClip.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 LayoutObject& 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 LayoutObject& object, PaintPropertyTreeBuilderContext& context)
-{
- if (!object.isBoxModelObject() || !object.hasOverflowClip())
- return nullptr;
-
- PaintLayer* layer = toLayoutBoxModelObject(object).layer();
- ASSERT(layer);
- DoubleSize scrollOffset = layer->getScrollableArea()->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 LayoutObject& object, PaintPropertyTreeBuilderContext& context)
-{
- // 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.canContainAbsolutePositionObjects()) {
- context.transformForAbsolutePosition = context.currentTransform;
- context.paintOffsetForAbsolutePosition = context.paintOffset;
- context.clipForAbsolutePosition = context.currentClip;
- }
-
- // TODO(pdr): Remove the !object.isLayoutView() condition when removing FrameView
- // paint properties for rootLayerScrolls.
- if (!object.isLayoutView() && object.canContainFixedPositionObjects()) {
- context.transformForFixedPosition = context.currentTransform;
- context.paintOffsetForFixedPosition = context.paintOffset;
- context.clipForFixedPosition = context.currentClip;
- }
-}
-
-static PassOwnPtr<ObjectPaintProperties::LocalBorderBoxProperties> recordTreeContextIfNeeded(LayoutObject& object, const PaintPropertyTreeBuilderContext& context)
-{
- // Note: Currently only layer painter makes use of the pre-computed context.
- // This condition may be loosened with no adverse effects beside memory use.
- if (!object.hasLayer())
- return nullptr;
-
- OwnPtr<ObjectPaintProperties::LocalBorderBoxProperties> recordedContext = adoptPtr(new ObjectPaintProperties::LocalBorderBoxProperties);
- recordedContext->paintOffset = context.paintOffset;
- recordedContext->transform = context.currentTransform;
- recordedContext->clip = context.currentClip;
- recordedContext->effect = context.currentEffect;
- return recordedContext.release();
-}
-
-void PaintPropertyTreeBuilder::walk(LayoutObject& object, const PaintPropertyTreeBuilderContext& context)
-{
- PaintPropertyTreeBuilderContext localContext(context);
-
- deriveBorderBoxFromContainerContext(object, localContext);
- RefPtr<TransformPaintPropertyNode> newTransformNodeForPaintOffsetTranslation = createPaintOffsetTranslationIfNeeded(object, localContext);
- RefPtr<TransformPaintPropertyNode> newTransformNodeForTransform = createTransformIfNeeded(object, localContext);
- RefPtr<EffectPaintPropertyNode> newEffectNode = createEffectIfNeeded(object, localContext);
- OwnPtr<ObjectPaintProperties::LocalBorderBoxProperties> newRecordedContext = recordTreeContextIfNeeded(object, localContext);
- RefPtr<ClipPaintPropertyNode> newClipNodeForOverflowClip = createOverflowClipIfNeeded(object, localContext);
- // TODO(trchen): Insert flattening transform here, as specified by
- // http://www.w3.org/TR/css3-transforms/#transform-style-property
- RefPtr<TransformPaintPropertyNode> newTransformNodeForPerspective = createPerspectiveIfNeeded(object, localContext);
- RefPtr<TransformPaintPropertyNode> newTransformNodeForScrollTranslation = createScrollTranslationIfNeeded(object, localContext);
- updateOutOfFlowContext(object, localContext);
-
- if (newTransformNodeForPaintOffsetTranslation || newTransformNodeForTransform || newEffectNode || newClipNodeForOverflowClip || newTransformNodeForPerspective || newTransformNodeForScrollTranslation || newRecordedContext) {
- OwnPtr<ObjectPaintProperties> updatedPaintProperties = ObjectPaintProperties::create(
- newTransformNodeForPaintOffsetTranslation.release(),
- newTransformNodeForTransform.release(),
- newEffectNode.release(),
- newClipNodeForOverflowClip.release(),
- newTransformNodeForPerspective.release(),
- newTransformNodeForScrollTranslation.release(),
- newRecordedContext.release());
- object.setObjectPaintProperties(updatedPaintProperties.release());
- } else {
- object.clearObjectPaintProperties();
- }
-
- for (LayoutObject* child = object.slowFirstChild(); child; child = child->nextSibling()) {
- if (child->isBoxModelObject() || child->isSVG())
- walk(*child, localContext);
- }
-
- if (object.isLayoutPart()) {
- Widget* widget = toLayoutPart(object).widget();
- if (widget && widget->isFrameView())
- walk(*toFrameView(widget), localContext);
- // TODO(pdr): Investigate RemoteFrameView (crbug.com/579281).
- }
-}
-
-} // namespace blink

Powered by Google App Engine
This is Rietveld 408576698