| 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..3da9c48fabb821874793a69e7aa0dfe8a6207fce
|
| --- /dev/null
|
| +++ b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp
|
| @@ -0,0 +1,179 @@
|
| +// 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 {
|
| +
|
| +struct PaintPropertyTreeBuilder::Context {
|
| + Context() : transformForOutOfFlowPositioned(nullptr), transformForFixedPositioned(nullptr) { }
|
| +
|
| + TransformPaintPropertyNode* currentTransform;
|
| + LayoutPoint paintOffset;
|
| +
|
| + TransformPaintPropertyNode* transformForOutOfFlowPositioned;
|
| + LayoutPoint paintOffsetForOutOfFlowPositioned;
|
| +
|
| + TransformPaintPropertyNode* transformForFixedPositioned;
|
| + LayoutPoint paintOffsetForFixedPositioned;
|
| +};
|
| +
|
| +void PaintPropertyTreeBuilder::buildPropertyTrees(FrameView& rootFrame)
|
| +{
|
| + walk(rootFrame, Context());
|
| +}
|
| +
|
| +void PaintPropertyTreeBuilder::walk(FrameView& frameView, const Context& context)
|
| +{
|
| + Context localContext(context);
|
| + ObjectPaintProperties& properties = frameView.ensureObjectPaintProperties();
|
| +
|
| + 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());
|
| + TransformPaintPropertyNode* transformNodeForSelf = new TransformPaintPropertyNode(frameTranslate, FloatPoint3D(), context.currentTransform);
|
| + properties.setTransformNodeForSelf(adoptRef(transformNodeForSelf));
|
| + localContext.transformForFixedPositioned = transformNodeForSelf;
|
| + localContext.paintOffsetForFixedPositioned = LayoutPoint();
|
| +
|
| + TransformationMatrix frameScroll;
|
| + frameScroll.translate(-frameView.scrollX(), -frameView.scrollY());
|
| + TransformPaintPropertyNode* transformNodeForDescendants = new TransformPaintPropertyNode(frameScroll, FloatPoint3D(), transformNodeForSelf);
|
| + properties.setTransformNodeForDescendants(adoptRef(transformNodeForDescendants));
|
| + localContext.currentTransform = localContext.transformForOutOfFlowPositioned = transformNodeForDescendants;
|
| + localContext.paintOffset = localContext.paintOffsetForOutOfFlowPositioned = LayoutPoint();
|
| +
|
| + if (LayoutView* layoutView = frameView.layoutView())
|
| + walk(*layoutView, localContext);
|
| +}
|
| +
|
| +static bool shouldCreateTransformNodeForSelf(LayoutBoxModelObject& object)
|
| +{
|
| + // TODO(trchen): Eliminate PaintLayer dependency.
|
| + PaintLayer* layer = object.layer();
|
| + if (!layer)
|
| + return false;
|
| +
|
| + return layer->paintsWithTransform(GlobalPaintNormalPhase);
|
| +}
|
| +
|
| +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()));
|
| +}
|
| +
|
| +void PaintPropertyTreeBuilder::walk(LayoutBoxModelObject& object, const Context& context)
|
| +{
|
| + ASSERT(object.isBox() != object.isLayoutInline()); // Either or.
|
| +
|
| + Context localContext(context);
|
| + RefPtr<TransformPaintPropertyNode> newTransformNodeForSelf;
|
| + RefPtr<TransformPaintPropertyNode> newTransformNodeForDescendants;
|
| +
|
| + const ComputedStyle& style = object.styleRef();
|
| + // TODO(trchen): There is some insanity going on with tables. Double check results.
|
| + switch (style.position()) {
|
| + case StaticPosition:
|
| + break;
|
| + case RelativePosition:
|
| + localContext.paintOffset += object.offsetForInFlowPosition();
|
| + break;
|
| + case AbsolutePosition:
|
| + localContext.currentTransform = context.transformForOutOfFlowPositioned;
|
| + localContext.paintOffset = context.paintOffsetForOutOfFlowPositioned;
|
| + break;
|
| + case StickyPosition:
|
| + localContext.paintOffset += object.offsetForInFlowPosition();
|
| + break;
|
| + case FixedPosition:
|
| + localContext.currentTransform = context.transformForFixedPositioned;
|
| + localContext.paintOffset = context.paintOffsetForFixedPositioned;
|
| + break;
|
| + default:
|
| + ASSERT_NOT_REACHED();
|
| + }
|
| + if (object.isBox())
|
| + localContext.paintOffset += toLayoutBox(object).locationOffset();
|
| +
|
| + bool hasTransform = object.isBox() && style.hasTransform();
|
| + if (shouldCreateTransformNodeForSelf(object)) {
|
| + TransformationMatrix matrix;
|
| + if (hasTransform)
|
| + style.applyTransform(matrix, toLayoutBox(object).size(), ComputedStyle::IncludeTransformOrigin, ComputedStyle::IncludeMotionPath, ComputedStyle::IncludeIndependentTransformProperties);
|
| + matrix.translateRight(localContext.paintOffset.x(), localContext.paintOffset.y());
|
| + // TODO(jbroman): Put the real transform origin here, instead of using a
|
| + // matrix with the origin baked in.
|
| + newTransformNodeForSelf = adoptRef(new TransformPaintPropertyNode(matrix, FloatPoint3D(), localContext.currentTransform));
|
| + localContext.currentTransform = newTransformNodeForSelf.get();
|
| + localContext.paintOffset = LayoutPoint();
|
| + } else {
|
| + ASSERT(!hasTransform);
|
| + }
|
| +
|
| + if (object.isBox() && style.hasPerspective()) {
|
| + TransformationMatrix matrix;
|
| + matrix.applyPerspective(style.perspective());
|
| + // Perspective forces an element to paint with transform today.
|
| + // The assumption may change in the future.
|
| + ASSERT(localContext.paintOffset == LayoutPoint());
|
| + newTransformNodeForDescendants = adoptRef(new TransformPaintPropertyNode(matrix, perspectiveOrigin(toLayoutBox(object)), localContext.currentTransform));
|
| + localContext.currentTransform = newTransformNodeForDescendants.get();
|
| + }
|
| +
|
| + if (style.position() != StaticPosition || hasTransform) {
|
| + localContext.transformForOutOfFlowPositioned = localContext.currentTransform;
|
| + localContext.paintOffsetForOutOfFlowPositioned = localContext.paintOffset;
|
| + }
|
| +
|
| + if (hasTransform) {
|
| + localContext.transformForFixedPositioned = localContext.currentTransform;
|
| + localContext.paintOffsetForFixedPositioned = localContext.paintOffset;
|
| + }
|
| +
|
| + if (object.hasOverflowClip()) {
|
| + PaintLayer* layer = object.layer();
|
| + ASSERT(layer);
|
| + DoubleSize scrollOffset = layer->scrollableArea()->scrollOffset();
|
| + if (!scrollOffset.isZero() || layer->scrollsOverflow()) {
|
| + TransformationMatrix matrix;
|
| + matrix.translate(-scrollOffset.width(), -scrollOffset.height());
|
| + newTransformNodeForDescendants = adoptRef(new TransformPaintPropertyNode(matrix, FloatPoint3D(), localContext.currentTransform));
|
| + localContext.currentTransform = newTransformNodeForDescendants.get();
|
| + }
|
| + }
|
| +
|
| + if (newTransformNodeForSelf || newTransformNodeForDescendants) {
|
| + ObjectPaintProperties& properties = object.ensureObjectPaintProperties();
|
| + properties.setTransformNodeForSelf(newTransformNodeForSelf.release());
|
| + properties.setTransformNodeForDescendants(newTransformNodeForDescendants.release());
|
| + } else {
|
| + object.clearObjectPaintProperties();
|
| + }
|
| +
|
| + if (object.isSVGRoot()) {
|
| + // TODO(trchen): Implement SVG walk.
|
| + return;
|
| + }
|
| +
|
| + for (LayoutObject* child = object.slowFirstChild(); child; child = child->nextSibling()) {
|
| + if (child->isText())
|
| + continue;
|
| + walk(toLayoutBoxModelObject(*child), localContext);
|
| + }
|
| +}
|
| +
|
| +} // namespace blink
|
|
|