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) { | |
94 existingPropertyNode->update(contextProperty, args...); | |
95 contextProperty = existingPropertyNode; | |
jbroman
2016/07/24 01:08:23
Ex-post-facto: this was extremely confusing to me
Xianzhu
2016/07/24 22:18:42
Thanks for the suggestions. Addressed them in http
| |
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(FloatRect(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 |