Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "core/paint/PaintPropertyTreeBuilder.h" | 5 #include "core/paint/PaintPropertyTreeBuilder.h" |
| 6 | 6 |
| 7 #include "core/frame/FrameView.h" | 7 #include "core/frame/FrameView.h" |
| 8 #include "core/frame/LocalFrame.h" | 8 #include "core/frame/LocalFrame.h" |
| 9 #include "core/frame/Settings.h" | 9 #include "core/frame/Settings.h" |
| 10 #include "core/layout/LayoutInline.h" | 10 #include "core/layout/LayoutInline.h" |
| 11 #include "core/layout/LayoutPart.h" | 11 #include "core/layout/LayoutPart.h" |
| 12 #include "core/layout/svg/LayoutSVGRoot.h" | 12 #include "core/layout/svg/LayoutSVGRoot.h" |
| 13 #include "core/paint/ObjectPaintProperties.h" | 13 #include "core/paint/ObjectPaintProperties.h" |
| 14 #include "core/paint/PaintLayer.h" | 14 #include "core/paint/PaintLayer.h" |
| 15 #include "core/paint/SVGRootPainter.h" | 15 #include "core/paint/SVGRootPainter.h" |
| 16 #include "platform/transforms/TransformationMatrix.h" | 16 #include "platform/transforms/TransformationMatrix.h" |
| 17 #include "wtf/PtrUtil.h" | 17 #include "wtf/PtrUtil.h" |
| 18 #include <memory> | 18 #include <memory> |
| 19 | 19 |
| 20 namespace blink { | 20 namespace blink { |
| 21 | 21 |
| 22 void PaintPropertyTreeBuilder::buildTreeRootNodes(FrameView& rootFrame, PaintPro pertyTreeBuilderContext& context) | 22 void PaintPropertyTreeBuilder::buildTreeRootNodes(FrameView& rootFrame, PaintPro pertyTreeBuilderContext& context) |
| 23 { | 23 { |
| 24 RefPtr<TransformPaintPropertyNode> transformRoot = TransformPaintPropertyNod e::create(TransformationMatrix(), FloatPoint3D(), nullptr); | 24 if (!rootFrame.rootTransform() || rootFrame.rootTransform()->parent()) { |
| 25 context.current.transform = context.absolutePosition.transform = context.fix edPosition.transform = transformRoot.get(); | 25 rootFrame.setRootTransform(TransformPaintPropertyNode::create(nullptr, T ransformationMatrix(), FloatPoint3D())); |
| 26 rootFrame.setRootTransform(std::move(transformRoot)); | 26 rootFrame.setRootClip(ClipPaintPropertyNode::create(nullptr, rootFrame.r ootTransform(), FloatRoundedRect(LayoutRect::infiniteIntRect()))); |
| 27 rootFrame.setRootEffect(EffectPaintPropertyNode::create(nullptr, 1.0)); | |
| 28 } else { | |
| 29 DCHECK(rootFrame.rootClip() && !rootFrame.rootClip()->parent()); | |
| 30 DCHECK(rootFrame.rootEffect() && !rootFrame.rootEffect()->parent()); | |
| 31 } | |
| 27 | 32 |
| 28 RefPtr<ClipPaintPropertyNode> clipRoot = ClipPaintPropertyNode::create(trans formRoot, FloatRoundedRect(LayoutRect::infiniteIntRect()), nullptr); | 33 context.current.transform = context.absolutePosition.transform = context.fix edPosition.transform = rootFrame.rootTransform(); |
| 29 context.current.clip = context.absolutePosition.clip = context.fixedPosition .clip = clipRoot.get(); | 34 context.current.clip = context.absolutePosition.clip = context.fixedPosition .clip = rootFrame.rootClip(); |
| 30 rootFrame.setRootClip(std::move(clipRoot)); | 35 context.currentEffect = rootFrame.rootEffect(); |
| 31 | |
| 32 RefPtr<EffectPaintPropertyNode> effectRoot = EffectPaintPropertyNode::create (1.0, nullptr); | |
| 33 context.currentEffect = effectRoot.get(); | |
| 34 rootFrame.setRootEffect(std::move(effectRoot)); | |
| 35 } | 36 } |
| 36 | 37 |
| 37 void PaintPropertyTreeBuilder::buildTreeNodes(FrameView& frameView, PaintPropert yTreeBuilderContext& context) | 38 void PaintPropertyTreeBuilder::buildTreeNodes(FrameView& frameView, PaintPropert yTreeBuilderContext& context) |
| 38 { | 39 { |
| 39 // TODO(pdr): Creating paint properties for FrameView here will not be | 40 // TODO(pdr): Creating paint properties for FrameView here will not be |
| 40 // needed once settings()->rootLayerScrolls() is enabled. | 41 // needed once settings()->rootLayerScrolls() is enabled. |
| 41 // TODO(pdr): Make this conditional on the rootLayerScrolls setting. | 42 // TODO(pdr): Make this conditional on the rootLayerScrolls setting. |
| 42 | 43 |
| 43 TransformationMatrix frameTranslate; | 44 TransformationMatrix frameTranslate; |
| 44 frameTranslate.translate(frameView.x() + context.current.paintOffset.x(), fr ameView.y() + context.current.paintOffset.y()); | 45 frameTranslate.translate(frameView.x() + context.current.paintOffset.x(), fr ameView.y() + context.current.paintOffset.y()); |
| 45 RefPtr<TransformPaintPropertyNode> newTransformNodeForPreTranslation = Trans formPaintPropertyNode::create(frameTranslate, FloatPoint3D(), context.current.tr ansform); | 46 if (TransformPaintPropertyNode* existingPreTranslation = frameView.preTransl ation()) |
| 47 existingPreTranslation->update(context.current.transform, frameTranslate , FloatPoint3D()); | |
| 48 else | |
| 49 frameView.setPreTranslation(TransformPaintPropertyNode::create(context.c urrent.transform, frameTranslate, FloatPoint3D())); | |
| 46 | 50 |
| 47 FloatRoundedRect contentClip(IntRect(IntPoint(), frameView.visibleContentSiz e())); | 51 FloatRoundedRect contentClip(IntRect(IntPoint(), frameView.visibleContentSiz e())); |
| 48 RefPtr<ClipPaintPropertyNode> newClipNodeForContentClip = ClipPaintPropertyN ode::create(newTransformNodeForPreTranslation.get(), contentClip, context.curren t.clip); | 52 if (ClipPaintPropertyNode* existingContentClip = frameView.contentClip()) |
| 53 existingContentClip->update(context.current.clip, frameView.preTranslati on(), contentClip); | |
| 54 else | |
| 55 frameView.setContentClip(ClipPaintPropertyNode::create(context.current.c lip, frameView.preTranslation(), contentClip)); | |
| 49 | 56 |
| 50 DoubleSize scrollOffset = frameView.scrollOffsetDouble(); | 57 DoubleSize scrollOffset = frameView.scrollOffsetDouble(); |
| 51 TransformationMatrix frameScroll; | 58 TransformationMatrix frameScroll; |
| 52 frameScroll.translate(-scrollOffset.width(), -scrollOffset.height()); | 59 frameScroll.translate(-scrollOffset.width(), -scrollOffset.height()); |
| 53 RefPtr<TransformPaintPropertyNode> newTransformNodeForScrollTranslation = Tr ansformPaintPropertyNode::create(frameScroll, FloatPoint3D(), newTransformNodeFo rPreTranslation); | 60 if (TransformPaintPropertyNode* existingScrollTranslation = frameView.scroll Translation()) |
| 61 existingScrollTranslation->update(frameView.preTranslation(), frameScrol l, FloatPoint3D()); | |
| 62 else | |
| 63 frameView.setScrollTranslation(TransformPaintPropertyNode::create(frameV iew.preTranslation(), frameScroll, FloatPoint3D())); | |
| 54 | 64 |
| 55 // Initialize the context for current, absolute and fixed position cases. | 65 // Initialize the context for current, absolute and fixed position cases. |
| 56 // They are the same, except that scroll translation does not apply to | 66 // They are the same, except that scroll translation does not apply to |
| 57 // fixed position descendants. | 67 // fixed position descendants. |
| 58 context.current.transform = newTransformNodeForScrollTranslation.get(); | 68 context.current.transform = frameView.scrollTranslation(); |
| 59 context.current.paintOffset = LayoutPoint(); | 69 context.current.paintOffset = LayoutPoint(); |
| 60 context.current.clip = newClipNodeForContentClip.get(); | 70 context.current.clip = frameView.contentClip(); |
| 61 context.absolutePosition = context.current; | 71 context.absolutePosition = context.current; |
| 62 context.containerForAbsolutePosition = nullptr; | 72 context.containerForAbsolutePosition = nullptr; |
| 63 context.fixedPosition = context.current; | 73 context.fixedPosition = context.current; |
| 64 context.fixedPosition.transform = newTransformNodeForPreTranslation.get(); | 74 context.fixedPosition.transform = frameView.preTranslation(); |
| 75 } | |
| 65 | 76 |
| 66 frameView.setPreTranslation(newTransformNodeForPreTranslation.release()); | 77 template <typename PropertyNode, void (ObjectPaintProperties::*Setter)(PassRefPt r<PropertyNode>)> |
| 67 frameView.setScrollTranslation(newTransformNodeForScrollTranslation.release( )); | 78 void PaintPropertyTreeBuilder::clearPaintProperty(const LayoutObject& object) |
| 68 frameView.setContentClip(newClipNodeForContentClip.release()); | 79 { |
| 80 if (ObjectPaintProperties* existingProperties = object.objectPaintProperties ()) | |
| 81 (existingProperties->*Setter)(nullptr); | |
| 82 } | |
| 83 | |
| 84 template < | |
| 85 typename PropertyNode, | |
| 86 PropertyNode* (ObjectPaintProperties::*Getter)() const, | |
| 87 void (ObjectPaintProperties::*Setter)(PassRefPtr<PropertyNode>), | |
| 88 typename... Args> | |
| 89 void PaintPropertyTreeBuilder::updateOrCreatePaintProperty(const LayoutObject& o bject, const PaintPropertyTreeBuilderContext& context, PropertyNode*& contextPro perty, const Args&... args) | |
| 90 { | |
| 91 ObjectPaintProperties* existingProperties = object.objectPaintProperties(); | |
| 92 PropertyNode* existingPropertyNode = existingProperties ? (existingPropertie s->*Getter)() : nullptr; | |
| 93 if (existingPropertyNode) { | |
|
pdr.
2016/07/22 01:29:50
In the previous patch you checked that the propert
Xianzhu
2016/07/22 04:21:03
I don't think we there is requirement to create a
| |
| 94 existingPropertyNode->update(contextProperty, args...); | |
| 95 contextProperty = existingPropertyNode; | |
| 96 } else { | |
| 97 RefPtr<PropertyNode> newPropertyNode = PropertyNode::create(contextPrope rty, args...); | |
| 98 contextProperty = newPropertyNode.get(); | |
| 99 (object.getMutableForPainting().ensureObjectPaintProperties().*Setter)(n ewPropertyNode.release()); | |
| 100 } | |
| 69 } | 101 } |
| 70 | 102 |
| 71 void PaintPropertyTreeBuilder::updatePaintOffsetTranslation(const LayoutObject& object, PaintPropertyTreeBuilderContext& context) | 103 void PaintPropertyTreeBuilder::updatePaintOffsetTranslation(const LayoutObject& object, PaintPropertyTreeBuilderContext& context) |
| 72 { | 104 { |
| 73 if (object.isBoxModelObject()) { | 105 if (object.isBoxModelObject() && context.current.paintOffset != LayoutPoint( )) { |
| 74 // TODO(trchen): Eliminate PaintLayer dependency. | 106 // TODO(trchen): Eliminate PaintLayer dependency. |
| 75 PaintLayer* layer = toLayoutBoxModelObject(object).layer(); | 107 PaintLayer* layer = toLayoutBoxModelObject(object).layer(); |
| 76 if (!layer || !layer->paintsWithTransform(GlobalPaintNormalPhase)) | 108 if (layer && layer->paintsWithTransform(GlobalPaintNormalPhase)) { |
| 109 // We should use the same subpixel paint offset values for snapping regardless of whether a | |
| 110 // transform is present. If there is a transform we round the paint offset but keep around | |
| 111 // the residual fractional component for the transformed content to paint with. | |
| 112 // In spv1 this was called "subpixel accumulation". For more informa tion, see | |
| 113 // PaintLayer::subpixelAccumulation() and PaintLayerPainter::paintFr agmentByApplyingTransform. | |
| 114 IntPoint roundedPaintOffset = roundedIntPoint(context.current.paintO ffset); | |
| 115 LayoutPoint fractionalPaintOffset = LayoutPoint(context.current.pain tOffset - roundedPaintOffset); | |
| 116 | |
| 117 updateOrCreatePaintProperty<TransformPaintPropertyNode, &ObjectPaint Properties::paintOffsetTranslation, &ObjectPaintProperties::setPaintOffsetTransl ation>( | |
| 118 object, context, context.current.transform, TransformationMatrix ().translate(roundedPaintOffset.x(), roundedPaintOffset.y()), FloatPoint3D()); | |
| 119 context.current.paintOffset = fractionalPaintOffset; | |
| 77 return; | 120 return; |
| 121 } | |
| 78 } | 122 } |
| 79 | 123 clearPaintProperty<TransformPaintPropertyNode, &ObjectPaintProperties::setPa intOffsetTranslation>(object); |
| 80 if (context.current.paintOffset == LayoutPoint()) | |
| 81 return; | |
| 82 | |
| 83 // We should use the same subpixel paint offset values for snapping regardle ss of whether a | |
| 84 // transform is present. If there is a transform we round the paint offset b ut keep around | |
| 85 // the residual fractional component for the transformed content to paint wi th. | |
| 86 // In spv1 this was called "subpixel accumulation". For more information, se e | |
| 87 // PaintLayer::subpixelAccumulation() and PaintLayerPainter::paintFragmentBy ApplyingTransform. | |
| 88 IntPoint roundedPaintOffset = roundedIntPoint(context.current.paintOffset); | |
| 89 LayoutPoint fractionalPaintOffset = LayoutPoint(context.current.paintOffset - roundedPaintOffset); | |
| 90 | |
| 91 RefPtr<TransformPaintPropertyNode> paintOffsetTranslation = TransformPaintPr opertyNode::create( | |
| 92 TransformationMatrix().translate(roundedPaintOffset.x(), roundedPaintOff set.y()), | |
| 93 FloatPoint3D(), context.current.transform); | |
| 94 context.current.transform = paintOffsetTranslation.get(); | |
| 95 context.current.paintOffset = fractionalPaintOffset; | |
| 96 object.getMutableForPainting().ensureObjectPaintProperties().setPaintOffsetT ranslation(paintOffsetTranslation.release()); | |
| 97 } | 124 } |
| 98 | 125 |
| 99 static FloatPoint3D transformOrigin(const LayoutBox& box) | 126 static FloatPoint3D transformOrigin(const LayoutBox& box) |
| 100 { | 127 { |
| 101 const ComputedStyle& style = box.styleRef(); | 128 const ComputedStyle& style = box.styleRef(); |
| 102 FloatSize borderBoxSize(box.size()); | 129 FloatSize borderBoxSize(box.size()); |
| 103 return FloatPoint3D( | 130 return FloatPoint3D( |
| 104 floatValueForLength(style.transformOriginX(), borderBoxSize.width()), | 131 floatValueForLength(style.transformOriginX(), borderBoxSize.width()), |
| 105 floatValueForLength(style.transformOriginY(), borderBoxSize.height()), | 132 floatValueForLength(style.transformOriginY(), borderBoxSize.height()), |
| 106 style.transformOriginZ()); | 133 style.transformOriginZ()); |
| 107 } | 134 } |
| 108 | 135 |
| 109 void PaintPropertyTreeBuilder::updateTransform(const LayoutObject& object, Paint PropertyTreeBuilderContext& context) | 136 void PaintPropertyTreeBuilder::updateTransform(const LayoutObject& object, Paint PropertyTreeBuilderContext& context) |
| 110 { | 137 { |
| 111 if (object.isSVG() && !object.isSVGRoot()) { | 138 if (object.isSVG() && !object.isSVGRoot()) { |
| 112 // SVG does not use paint offset internally. | 139 // SVG does not use paint offset internally. |
| 113 DCHECK(context.current.paintOffset == LayoutPoint()); | 140 DCHECK(context.current.paintOffset == LayoutPoint()); |
| 114 | 141 |
| 115 // FIXME(pdr): Check for the presence of a transform instead of the valu e. Checking for an | 142 // FIXME(pdr): Check for the presence of a transform instead of the valu e. Checking for an |
| 116 // identity matrix will cause the property tree structure to change duri ng animations if | 143 // identity matrix will cause the property tree structure to change duri ng animations if |
| 117 // the animation passes through the identity matrix. | 144 // the animation passes through the identity matrix. |
| 118 // FIXME(pdr): Refactor this so all non-root SVG objects use the same tr ansform function. | 145 // FIXME(pdr): Refactor this so all non-root SVG objects use the same tr ansform function. |
| 119 const AffineTransform& transform = object.isSVGForeignObject() ? object. localSVGTransform() : object.localToSVGParentTransform(); | 146 const AffineTransform& transform = object.isSVGForeignObject() ? object. localSVGTransform() : object.localToSVGParentTransform(); |
| 120 if (transform.isIdentity()) | 147 if (!transform.isIdentity()) { |
| 148 // The origin is included in the local transform, so leave origin em pty. | |
| 149 updateOrCreatePaintProperty<TransformPaintPropertyNode, &ObjectPaint Properties::transform, &ObjectPaintProperties::setTransform>( | |
| 150 object, context, context.current.transform, TransformationMatrix (transform), FloatPoint3D()); | |
| 121 return; | 151 return; |
| 122 | 152 } |
| 123 // The origin is included in the local transform, so use an empty origin . | 153 } else { |
| 124 RefPtr<TransformPaintPropertyNode> svgTransform = TransformPaintProperty Node::create( | 154 const ComputedStyle& style = object.styleRef(); |
| 125 transform, FloatPoint3D(0, 0, 0), context.current.transform); | 155 if (object.isBox() && style.hasTransform()) { |
| 126 context.current.transform = svgTransform.get(); | 156 TransformationMatrix matrix; |
| 127 object.getMutableForPainting().ensureObjectPaintProperties().setTransfor m(svgTransform.release()); | 157 style.applyTransform(matrix, toLayoutBox(object).size(), ComputedSty le::ExcludeTransformOrigin, |
| 128 return; | 158 ComputedStyle::IncludeMotionPath, ComputedStyle::IncludeIndepend entTransformProperties); |
| 159 FloatPoint3D origin = transformOrigin(toLayoutBox(object)); | |
| 160 updateOrCreatePaintProperty<TransformPaintPropertyNode, &ObjectPaint Properties::transform, &ObjectPaintProperties::setTransform>( | |
| 161 object, context, context.current.transform, matrix, origin); | |
| 162 return; | |
| 163 } | |
| 129 } | 164 } |
| 130 | 165 clearPaintProperty<TransformPaintPropertyNode, &ObjectPaintProperties::setTr ansform>(object); |
| 131 const ComputedStyle& style = object.styleRef(); | |
| 132 if (!object.isBox() || !style.hasTransform()) | |
| 133 return; | |
| 134 | |
| 135 TransformationMatrix matrix; | |
| 136 style.applyTransform(matrix, toLayoutBox(object).size(), ComputedStyle::Excl udeTransformOrigin, | |
| 137 ComputedStyle::IncludeMotionPath, ComputedStyle::IncludeIndependentTrans formProperties); | |
| 138 RefPtr<TransformPaintPropertyNode> transformNode = TransformPaintPropertyNod e::create( | |
| 139 matrix, transformOrigin(toLayoutBox(object)), context.current.transform) ; | |
| 140 context.current.transform = transformNode.get(); | |
| 141 object.getMutableForPainting().ensureObjectPaintProperties().setTransform(tr ansformNode.release()); | |
| 142 } | 166 } |
| 143 | 167 |
| 144 void PaintPropertyTreeBuilder::updateEffect(const LayoutObject& object, PaintPro pertyTreeBuilderContext& context) | 168 void PaintPropertyTreeBuilder::updateEffect(const LayoutObject& object, PaintPro pertyTreeBuilderContext& context) |
| 145 { | 169 { |
| 146 if (!object.styleRef().hasOpacity()) | 170 if (!object.styleRef().hasOpacity()) { |
| 171 clearPaintProperty<EffectPaintPropertyNode, &ObjectPaintProperties::setE ffect>(object); | |
| 147 return; | 172 return; |
| 148 RefPtr<EffectPaintPropertyNode> effectNode = EffectPaintPropertyNode::create (object.styleRef().opacity(), context.currentEffect); | 173 } |
| 149 context.currentEffect = effectNode.get(); | 174 |
| 150 object.getMutableForPainting().ensureObjectPaintProperties().setEffect(effec tNode.release()); | 175 updateOrCreatePaintProperty<EffectPaintPropertyNode, &ObjectPaintProperties: :effect, &ObjectPaintProperties::setEffect>( |
| 176 object, context, context.currentEffect, object.styleRef().opacity()); | |
| 151 } | 177 } |
| 152 | 178 |
| 153 void PaintPropertyTreeBuilder::updateCssClip(const LayoutObject& object, PaintPr opertyTreeBuilderContext& context) | 179 void PaintPropertyTreeBuilder::updateCssClip(const LayoutObject& object, PaintPr opertyTreeBuilderContext& context) |
| 154 { | 180 { |
| 155 if (!object.hasClip()) | 181 if (object.hasClip()) { |
| 182 // Create clip node for descendants that are not fixed position. | |
| 183 // We don't have to setup context.absolutePosition.clip here because thi s object must be | |
| 184 // a container for absolute position descendants, and will copy from in- flow context later | |
| 185 // at updateOutOfFlowContext() step. | |
| 186 DCHECK(object.canContainAbsolutePositionObjects()); | |
| 187 LayoutRect clipRect = toLayoutBox(object).clipRect(context.current.paint Offset); | |
| 188 updateOrCreatePaintProperty<ClipPaintPropertyNode, &ObjectPaintPropertie s::cssClip, &ObjectPaintProperties::setCssClip>( | |
| 189 object, context, context.current.clip, context.current.transform, Fl oatRoundedRect(LayoutRect(clipRect))); | |
| 156 return; | 190 return; |
| 157 ASSERT(object.canContainAbsolutePositionObjects()); | 191 } |
| 158 | 192 clearPaintProperty<ClipPaintPropertyNode, &ObjectPaintProperties::setCssClip >(object); |
| 159 // Create clip node for descendants that are not fixed position. | |
| 160 // We don't have to setup context.absolutePosition.clip here because this ob ject must be | |
| 161 // a container for absolute position descendants, and will copy from in-flow context later | |
| 162 // at updateOutOfFlowContext() step. | |
| 163 LayoutRect clipRect = toLayoutBox(object).clipRect(context.current.paintOffs et); | |
| 164 RefPtr<ClipPaintPropertyNode> clipNode = ClipPaintPropertyNode::create( | |
| 165 context.current.transform, | |
| 166 FloatRoundedRect(FloatRect(clipRect)), | |
| 167 context.current.clip); | |
| 168 context.current.clip = clipNode.get(); | |
| 169 object.getMutableForPainting().ensureObjectPaintProperties().setCssClip(clip Node.release()); | |
| 170 } | 193 } |
| 171 | 194 |
| 172 void PaintPropertyTreeBuilder::updateLocalBorderBoxContext(const LayoutObject& o bject, const PaintPropertyTreeBuilderContext& context) | 195 void PaintPropertyTreeBuilder::updateLocalBorderBoxContext(const LayoutObject& o bject, const PaintPropertyTreeBuilderContext& context) |
| 173 { | 196 { |
| 174 // Avoid adding an ObjectPaintProperties for non-boxes to save memory, since we don't need them at the moment. | 197 // Avoid adding an ObjectPaintProperties for non-boxes to save memory, since we don't need them at the moment. |
| 175 if (!object.isBox() && !object.hasLayer()) | 198 if (!object.isBox() && !object.hasLayer()) |
| 176 return; | 199 return; |
| 177 | 200 |
| 178 std::unique_ptr<ObjectPaintProperties::LocalBorderBoxProperties> borderBoxCo ntext = | 201 std::unique_ptr<ObjectPaintProperties::LocalBorderBoxProperties> borderBoxCo ntext = |
| 179 wrapUnique(new ObjectPaintProperties::LocalBorderBoxProperties); | 202 wrapUnique(new ObjectPaintProperties::LocalBorderBoxProperties); |
| 180 borderBoxContext->paintOffset = context.current.paintOffset; | 203 borderBoxContext->paintOffset = context.current.paintOffset; |
| 181 borderBoxContext->propertyTreeState = PropertyTreeState(context.current.tran sform, context.current.clip, context.currentEffect); | 204 borderBoxContext->propertyTreeState = PropertyTreeState(context.current.tran sform, context.current.clip, context.currentEffect); |
| 182 object.getMutableForPainting().ensureObjectPaintProperties().setLocalBorderB oxProperties(std::move(borderBoxContext)); | 205 object.getMutableForPainting().ensureObjectPaintProperties().setLocalBorderB oxProperties(std::move(borderBoxContext)); |
| 183 } | 206 } |
| 184 | 207 |
| 185 // TODO(trchen): Remove this once we bake the paint offset into frameRect. | 208 // TODO(trchen): Remove this once we bake the paint offset into frameRect. |
| 186 void PaintPropertyTreeBuilder::updateScrollbarPaintOffset(const LayoutObject& ob ject, const PaintPropertyTreeBuilderContext& context) | 209 void PaintPropertyTreeBuilder::updateScrollbarPaintOffset(const LayoutObject& ob ject, const PaintPropertyTreeBuilderContext& context) |
| 187 { | 210 { |
| 188 IntPoint roundedPaintOffset = roundedIntPoint(context.current.paintOffset); | 211 IntPoint roundedPaintOffset = roundedIntPoint(context.current.paintOffset); |
| 189 if (roundedPaintOffset == IntPoint()) | 212 if (roundedPaintOffset != IntPoint() && object.isBoxModelObject()) { |
| 190 return; | 213 if (PaintLayerScrollableArea* scrollableArea = toLayoutBoxModelObject(ob ject).getScrollableArea()) { |
| 191 | 214 if (scrollableArea->horizontalScrollbar() || scrollableArea->vertica lScrollbar()) { |
| 192 if (!object.isBoxModelObject()) | 215 auto paintOffset = TransformationMatrix().translate(roundedPaint Offset.x(), roundedPaintOffset.y()); |
| 193 return; | 216 // Make a copy of context.current.transform because we don't wan t to set the scrollbarPaintOffset node |
| 194 PaintLayerScrollableArea* scrollableArea = toLayoutBoxModelObject(object).ge tScrollableArea(); | 217 // as the current transform. |
| 195 if (!scrollableArea) | 218 TransformPaintPropertyNode* parentTransform = context.current.tr ansform; |
| 196 return; | 219 updateOrCreatePaintProperty<TransformPaintPropertyNode, &ObjectP aintProperties::scrollbarPaintOffset, &ObjectPaintProperties::setScrollbarPaintO ffset>( |
| 197 if (!scrollableArea->horizontalScrollbar() && !scrollableArea->verticalScrol lbar()) | 220 object, context, parentTransform, paintOffset, FloatPoint3D( )); |
| 198 return; | 221 return; |
| 199 | 222 } |
| 200 auto paintOffset = TransformationMatrix().translate(roundedPaintOffset.x(), roundedPaintOffset.y()); | 223 } |
| 201 object.getMutableForPainting().ensureObjectPaintProperties().setScrollbarPai ntOffset( | 224 } |
| 202 TransformPaintPropertyNode::create(paintOffset, FloatPoint3D(), context. current.transform)); | 225 clearPaintProperty<TransformPaintPropertyNode, &ObjectPaintProperties::setSc rollbarPaintOffset>(object); |
| 203 } | 226 } |
| 204 | 227 |
| 205 void PaintPropertyTreeBuilder::updateOverflowClip(const LayoutObject& object, Pa intPropertyTreeBuilderContext& context) | 228 void PaintPropertyTreeBuilder::updateOverflowClip(const LayoutObject& object, Pa intPropertyTreeBuilderContext& context) |
| 206 { | 229 { |
| 207 if (!object.isBox()) | 230 if (!object.isBox()) |
| 208 return; | 231 return; |
| 209 const LayoutBox& box = toLayoutBox(object); | 232 const LayoutBox& box = toLayoutBox(object); |
| 210 | 233 |
| 211 // The <input> elements can't have contents thus CSS overflow property doesn 't apply. | 234 // The <input> elements can't have contents thus CSS overflow property doesn 't apply. |
| 212 // However for layout purposes we do generate child layout objects for them, e.g. button label. | 235 // However for layout purposes we do generate child layout objects for them, e.g. button label. |
| 213 // We should clip the overflow from those children. This is called control c lip and we | 236 // We should clip the overflow from those children. This is called control c lip and we |
| 214 // technically treat them like overflow clip. | 237 // technically treat them like overflow clip. |
| 215 LayoutRect clipRect; | 238 LayoutRect clipRect; |
| 216 if (box.hasControlClip()) | 239 if (box.hasControlClip()) { |
| 217 clipRect = box.controlClipRect(context.current.paintOffset); | 240 clipRect = box.controlClipRect(context.current.paintOffset); |
| 218 else if (box.hasOverflowClip()) | 241 } else if (box.hasOverflowClip()) { |
| 219 clipRect = box.overflowClipRect(context.current.paintOffset); | 242 clipRect = box.overflowClipRect(context.current.paintOffset); |
| 220 else | 243 } else { |
| 244 clearPaintProperty<ClipPaintPropertyNode, &ObjectPaintProperties::setOve rflowClip>(object); | |
| 221 return; | 245 return; |
| 246 } | |
| 222 | 247 |
| 248 // This need to be in top-level block to hold the reference until we finish creating the normal clip node. | |
| 223 RefPtr<ClipPaintPropertyNode> borderRadiusClip; | 249 RefPtr<ClipPaintPropertyNode> borderRadiusClip; |
| 224 if (box.styleRef().hasBorderRadius()) { | 250 if (box.styleRef().hasBorderRadius()) { |
| 225 auto innerBorder = box.styleRef().getRoundedInnerBorderFor( | 251 auto innerBorder = box.styleRef().getRoundedInnerBorderFor( |
| 226 LayoutRect(context.current.paintOffset, box.size())); | 252 LayoutRect(context.current.paintOffset, box.size())); |
| 227 borderRadiusClip = ClipPaintPropertyNode::create( | 253 borderRadiusClip = ClipPaintPropertyNode::create(context.current.clip, c ontext.current.transform, innerBorder); |
| 228 context.current.transform, innerBorder, context.current.clip); | 254 context.current.clip = borderRadiusClip.get(); |
| 229 } | 255 } |
| 230 | 256 |
| 231 RefPtr<ClipPaintPropertyNode> overflowClip = ClipPaintPropertyNode::create( | 257 updateOrCreatePaintProperty<ClipPaintPropertyNode, &ObjectPaintProperties::o verflowClip, &ObjectPaintProperties::setOverflowClip>( |
| 232 context.current.transform, | 258 object, context, context.current.clip, context.current.transform, FloatR oundedRect(FloatRect(clipRect))); |
| 233 FloatRoundedRect(FloatRect(clipRect)), | |
| 234 borderRadiusClip ? borderRadiusClip.release() : context.current.clip); | |
| 235 context.current.clip = overflowClip.get(); | |
| 236 object.getMutableForPainting().ensureObjectPaintProperties().setOverflowClip (overflowClip.release()); | |
| 237 } | 259 } |
| 238 | 260 |
| 239 static FloatPoint perspectiveOrigin(const LayoutBox& box) | 261 static FloatPoint perspectiveOrigin(const LayoutBox& box) |
| 240 { | 262 { |
| 241 const ComputedStyle& style = box.styleRef(); | 263 const ComputedStyle& style = box.styleRef(); |
| 242 FloatSize borderBoxSize(box.size()); | 264 FloatSize borderBoxSize(box.size()); |
| 243 return FloatPoint( | 265 return FloatPoint( |
| 244 floatValueForLength(style.perspectiveOriginX(), borderBoxSize.width()), | 266 floatValueForLength(style.perspectiveOriginX(), borderBoxSize.width()), |
| 245 floatValueForLength(style.perspectiveOriginY(), borderBoxSize.height())) ; | 267 floatValueForLength(style.perspectiveOriginY(), borderBoxSize.height())) ; |
| 246 } | 268 } |
| 247 | 269 |
| 248 void PaintPropertyTreeBuilder::updatePerspective(const LayoutObject& object, Pai ntPropertyTreeBuilderContext& context) | 270 void PaintPropertyTreeBuilder::updatePerspective(const LayoutObject& object, Pai ntPropertyTreeBuilderContext& context) |
| 249 { | 271 { |
| 250 const ComputedStyle& style = object.styleRef(); | 272 const ComputedStyle& style = object.styleRef(); |
| 251 if (!object.isBox() || !style.hasPerspective()) | 273 if (!object.isBox() || !style.hasPerspective()) { |
| 274 clearPaintProperty<TransformPaintPropertyNode, &ObjectPaintProperties::s etPerspective>(object); | |
| 252 return; | 275 return; |
| 276 } | |
| 253 | 277 |
| 254 RefPtr<TransformPaintPropertyNode> perspective = TransformPaintPropertyNode: :create( | 278 FloatPoint3D origin = perspectiveOrigin(toLayoutBox(object)) + toLayoutSize( context.current.paintOffset); |
| 255 TransformationMatrix().applyPerspective(style.perspective()), | 279 updateOrCreatePaintProperty<TransformPaintPropertyNode, &ObjectPaintProperti es::perspective, &ObjectPaintProperties::setPerspective>( |
| 256 perspectiveOrigin(toLayoutBox(object)) + toLayoutSize(context.current.pa intOffset), | 280 object, context, context.current.transform, TransformationMatrix().apply Perspective(style.perspective()), origin); |
| 257 context.current.transform); | |
| 258 context.current.transform = perspective.get(); | |
| 259 object.getMutableForPainting().ensureObjectPaintProperties().setPerspective( perspective.release()); | |
| 260 } | 281 } |
| 261 | 282 |
| 262 void PaintPropertyTreeBuilder::updateSvgLocalToBorderBoxTransform(const LayoutOb ject& object, PaintPropertyTreeBuilderContext& context) | 283 void PaintPropertyTreeBuilder::updateSvgLocalToBorderBoxTransform(const LayoutOb ject& object, PaintPropertyTreeBuilderContext& context) |
| 263 { | 284 { |
| 264 if (!object.isSVGRoot()) | 285 if (!object.isSVGRoot()) |
| 265 return; | 286 return; |
| 266 | 287 |
| 267 AffineTransform transformToBorderBox = SVGRootPainter(toLayoutSVGRoot(object )).transformToPixelSnappedBorderBox(context.current.paintOffset); | 288 AffineTransform transformToBorderBox = SVGRootPainter(toLayoutSVGRoot(object )).transformToPixelSnappedBorderBox(context.current.paintOffset); |
| 268 | 289 |
| 269 // The paint offset is included in |transformToBorderBox| so SVG does not ne ed to handle paint | 290 // The paint offset is included in |transformToBorderBox| so SVG does not ne ed to handle paint |
| 270 // offset internally. | 291 // offset internally. |
| 271 context.current.paintOffset = LayoutPoint(); | 292 context.current.paintOffset = LayoutPoint(); |
| 272 | 293 |
| 273 if (transformToBorderBox.isIdentity()) | 294 if (transformToBorderBox.isIdentity()) { |
| 295 clearPaintProperty<TransformPaintPropertyNode, &ObjectPaintProperties::s etSvgLocalToBorderBoxTransform>(object); | |
| 274 return; | 296 return; |
| 297 } | |
| 275 | 298 |
| 276 RefPtr<TransformPaintPropertyNode> svgLocalToBorderBoxTransform = TransformP aintPropertyNode::create( | 299 updateOrCreatePaintProperty<TransformPaintPropertyNode, &ObjectPaintProperti es::svgLocalToBorderBoxTransform, &ObjectPaintProperties::setSvgLocalToBorderBox Transform>( |
| 277 transformToBorderBox, FloatPoint3D(0, 0, 0), context.current.transform); | 300 object, context, context.current.transform, transformToBorderBox, FloatP oint3D()); |
| 278 context.current.transform = svgLocalToBorderBoxTransform.get(); | |
| 279 context.current.paintOffset = LayoutPoint(); | |
| 280 object.getMutableForPainting().ensureObjectPaintProperties().setSvgLocalToBo rderBoxTransform(svgLocalToBorderBoxTransform.release()); | |
| 281 } | 301 } |
| 282 | 302 |
| 283 void PaintPropertyTreeBuilder::updateScrollTranslation(const LayoutObject& objec t, PaintPropertyTreeBuilderContext& context) | 303 void PaintPropertyTreeBuilder::updateScrollTranslation(const LayoutObject& objec t, PaintPropertyTreeBuilderContext& context) |
| 284 { | 304 { |
| 285 if (!object.isBoxModelObject() || !object.hasOverflowClip()) | 305 if (object.isBoxModelObject() && object.hasOverflowClip()) { |
| 286 return; | 306 PaintLayer* layer = toLayoutBoxModelObject(object).layer(); |
| 307 DCHECK(layer); | |
| 308 DoubleSize scrollOffset = layer->getScrollableArea()->scrollOffset(); | |
| 287 | 309 |
| 288 PaintLayer* layer = toLayoutBoxModelObject(object).layer(); | 310 if (!scrollOffset.isZero() || layer->scrollsOverflow()) { |
| 289 ASSERT(layer); | 311 TransformationMatrix matrix = TransformationMatrix().translate(-scro llOffset.width(), -scrollOffset.height()); |
| 290 DoubleSize scrollOffset = layer->getScrollableArea()->scrollOffset(); | 312 updateOrCreatePaintProperty<TransformPaintPropertyNode, &ObjectPaint Properties::scrollTranslation, &ObjectPaintProperties::setScrollTranslation>( |
| 291 if (scrollOffset.isZero() && !layer->scrollsOverflow()) | 313 object, context, context.current.transform, matrix, FloatPoint3D ()); |
| 292 return; | 314 return; |
| 293 | 315 } |
| 294 RefPtr<TransformPaintPropertyNode> scrollTranslation = TransformPaintPropert yNode::create( | 316 } |
| 295 TransformationMatrix().translate(-scrollOffset.width(), -scrollOffset.he ight()), | 317 clearPaintProperty<TransformPaintPropertyNode, &ObjectPaintProperties::setSc rollTranslation>(object); |
| 296 FloatPoint3D(), | |
| 297 context.current.transform); | |
| 298 context.current.transform = scrollTranslation.get(); | |
| 299 object.getMutableForPainting().ensureObjectPaintProperties().setScrollTransl ation(scrollTranslation.release()); | |
| 300 } | 318 } |
| 301 | 319 |
| 302 void PaintPropertyTreeBuilder::updateOutOfFlowContext(const LayoutObject& object , PaintPropertyTreeBuilderContext& context) | 320 void PaintPropertyTreeBuilder::updateOutOfFlowContext(const LayoutObject& object , PaintPropertyTreeBuilderContext& context) |
| 303 { | 321 { |
| 304 if (object.canContainAbsolutePositionObjects()) { | 322 if (object.canContainAbsolutePositionObjects()) { |
| 305 context.absolutePosition = context.current; | 323 context.absolutePosition = context.current; |
| 306 context.containerForAbsolutePosition = &object; | 324 context.containerForAbsolutePosition = &object; |
| 307 } | 325 } |
| 308 | 326 |
| 309 // TODO(pdr): Remove the !object.isLayoutView() condition when removing Fram eView | 327 // TODO(pdr): Remove the !object.isLayoutView() condition when removing Fram eView |
| 310 // paint properties for rootLayerScrolls. | 328 // paint properties for rootLayerScrolls. |
| 311 if (!object.isLayoutView() && object.canContainFixedPositionObjects()) { | 329 if (!object.isLayoutView() && object.canContainFixedPositionObjects()) { |
| 312 context.fixedPosition = context.current; | 330 context.fixedPosition = context.current; |
| 313 } else if (object.objectPaintProperties() && object.objectPaintProperties()- >cssClip()) { | 331 } else if (object.objectPaintProperties() && object.objectPaintProperties()- >cssClip()) { |
| 314 // CSS clip applies to all descendants, even if this object is not a con taining block | 332 // CSS clip applies to all descendants, even if this object is not a con taining block |
| 315 // ancestor of the descendant. It is okay for absolute-position descenda nts because | 333 // ancestor of the descendant. It is okay for absolute-position descenda nts because |
| 316 // having CSS clip implies being absolute position container. However fo r fixed-position | 334 // having CSS clip implies being absolute position container. However fo r fixed-position |
| 317 // descendants we need to insert the clip here if we are not a containin g block ancestor | 335 // descendants we need to insert the clip here if we are not a containin g block ancestor |
| 318 // of them. | 336 // of them. |
| 319 auto* cssClip = object.objectPaintProperties()->cssClip(); | 337 auto* cssClip = object.objectPaintProperties()->cssClip(); |
| 320 | 338 |
| 321 // Before we actually create anything, check whether in-flow context and fixed-position | 339 // Before we actually create anything, check whether in-flow context and fixed-position |
| 322 // context has exactly the same clip. Reuse if possible. | 340 // context has exactly the same clip. Reuse if possible. |
| 323 if (context.fixedPosition.clip == cssClip->parent()) { | 341 if (context.fixedPosition.clip == cssClip->parent()) { |
| 324 context.fixedPosition.clip = cssClip; | 342 context.fixedPosition.clip = cssClip; |
| 343 } else { | |
| 344 updateOrCreatePaintProperty<ClipPaintPropertyNode, &ObjectPaintPrope rties::cssClipFixedPosition, &ObjectPaintProperties::setCssClipFixedPosition>( | |
| 345 object, context, context.fixedPosition.clip, const_cast<Transfor mPaintPropertyNode*>(cssClip->localTransformSpace()), cssClip->clipRect()); | |
| 325 return; | 346 return; |
| 326 } | 347 } |
| 327 | |
| 328 RefPtr<ClipPaintPropertyNode> clipFixedPosition = ClipPaintPropertyNode: :create( | |
| 329 const_cast<TransformPaintPropertyNode*>(cssClip->localTransformSpace ()), | |
| 330 cssClip->clipRect(), | |
| 331 context.fixedPosition.clip); | |
| 332 context.fixedPosition.clip = clipFixedPosition.get(); | |
| 333 object.getMutableForPainting().ensureObjectPaintProperties().setCssClipF ixedPosition(clipFixedPosition.release()); | |
| 334 } | 348 } |
| 349 clearPaintProperty<ClipPaintPropertyNode, &ObjectPaintProperties::setCssClip FixedPosition>(object); | |
| 335 } | 350 } |
| 336 | 351 |
| 337 static void deriveBorderBoxFromContainerContext(const LayoutObject& object, Pain tPropertyTreeBuilderContext& context) | 352 static void deriveBorderBoxFromContainerContext(const LayoutObject& object, Pain tPropertyTreeBuilderContext& context) |
| 338 { | 353 { |
| 339 if (!object.isBoxModelObject()) | 354 if (!object.isBoxModelObject()) |
| 340 return; | 355 return; |
| 341 | 356 |
| 342 const LayoutBoxModelObject& boxModelObject = toLayoutBoxModelObject(object); | 357 const LayoutBoxModelObject& boxModelObject = toLayoutBoxModelObject(object); |
| 343 | 358 |
| 344 switch (object.styleRef().position()) { | 359 switch (object.styleRef().position()) { |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 378 if (boxModelObject.isTableCell()) { | 393 if (boxModelObject.isTableCell()) { |
| 379 LayoutObject* parentRow = boxModelObject.parent(); | 394 LayoutObject* parentRow = boxModelObject.parent(); |
| 380 ASSERT(parentRow && parentRow->isTableRow()); | 395 ASSERT(parentRow && parentRow->isTableRow()); |
| 381 context.current.paintOffset.moveBy(-toLayoutBox(parentRow)->topLeftL ocation()); | 396 context.current.paintOffset.moveBy(-toLayoutBox(parentRow)->topLeftL ocation()); |
| 382 } | 397 } |
| 383 } | 398 } |
| 384 } | 399 } |
| 385 | 400 |
| 386 void PaintPropertyTreeBuilder::buildTreeNodes(const LayoutObject& object, PaintP ropertyTreeBuilderContext& context) | 401 void PaintPropertyTreeBuilder::buildTreeNodes(const LayoutObject& object, PaintP ropertyTreeBuilderContext& context) |
| 387 { | 402 { |
| 388 object.getMutableForPainting().clearObjectPaintProperties(); | |
| 389 | |
| 390 if (!object.isBoxModelObject() && !object.isSVG()) | 403 if (!object.isBoxModelObject() && !object.isSVG()) |
| 391 return; | 404 return; |
| 392 | 405 |
| 393 deriveBorderBoxFromContainerContext(object, context); | 406 deriveBorderBoxFromContainerContext(object, context); |
| 394 | 407 |
| 395 updatePaintOffsetTranslation(object, context); | 408 updatePaintOffsetTranslation(object, context); |
| 396 updateTransform(object, context); | 409 updateTransform(object, context); |
| 397 updateEffect(object, context); | 410 updateEffect(object, context); |
| 398 updateCssClip(object, context); | 411 updateCssClip(object, context); |
| 399 updateLocalBorderBoxContext(object, context); | 412 updateLocalBorderBoxContext(object, context); |
| 400 updateScrollbarPaintOffset(object, context); | 413 updateScrollbarPaintOffset(object, context); |
| 401 updateOverflowClip(object, context); | 414 updateOverflowClip(object, context); |
| 402 // TODO(trchen): Insert flattening transform here, as specified by | 415 // TODO(trchen): Insert flattening transform here, as specified by |
| 403 // http://www.w3.org/TR/css3-transforms/#transform-style-property | 416 // http://www.w3.org/TR/css3-transforms/#transform-style-property |
| 404 updatePerspective(object, context); | 417 updatePerspective(object, context); |
| 405 updateSvgLocalToBorderBoxTransform(object, context); | 418 updateSvgLocalToBorderBoxTransform(object, context); |
| 406 updateScrollTranslation(object, context); | 419 updateScrollTranslation(object, context); |
| 407 updateOutOfFlowContext(object, context); | 420 updateOutOfFlowContext(object, context); |
| 408 } | 421 } |
| 409 | 422 |
| 410 } // namespace blink | 423 } // namespace blink |
| OLD | NEW |