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

Side by Side Diff: third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp

Issue 2144823006: Reuse existing paint property node is possible (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: - Created 4 years, 5 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 unified diff | Download patch
OLDNEW
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(Transforma tionMatrix(), FloatPoint3D(), nullptr));
26 rootFrame.setRootTransform(std::move(transformRoot)); 26 rootFrame.setRootClip(ClipPaintPropertyNode::create(rootFrame.rootTransf orm(), FloatRoundedRect(LayoutRect::infiniteIntRect()), nullptr));
27 rootFrame.setRootEffect(EffectPaintPropertyNode::create(1.0, nullptr));
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 (!frameView.preTranslation() || frameView.preTranslation()->matrix() != f rameTranslate)
47 frameView.setPreTranslation(TransformPaintPropertyNode::create(frameTran slate, FloatPoint3D(), context.current.transform));
46 48
47 FloatRoundedRect contentClip(IntRect(IntPoint(), frameView.visibleContentSiz e())); 49 FloatRoundedRect contentClip(IntRect(IntPoint(), frameView.visibleContentSiz e()));
48 RefPtr<ClipPaintPropertyNode> newClipNodeForContentClip = ClipPaintPropertyN ode::create(newTransformNodeForPreTranslation.get(), contentClip, context.curren t.clip); 50 if (!frameView.contentClip() || frameView.contentClip()->clipRect() != conte ntClip)
51 frameView.setContentClip(ClipPaintPropertyNode::create(frameView.preTran slation(), contentClip, context.current.clip));
49 52
50 DoubleSize scrollOffset = frameView.scrollOffsetDouble(); 53 DoubleSize scrollOffset = frameView.scrollOffsetDouble();
51 TransformationMatrix frameScroll; 54 TransformationMatrix frameScroll;
52 frameScroll.translate(-scrollOffset.width(), -scrollOffset.height()); 55 frameScroll.translate(-scrollOffset.width(), -scrollOffset.height());
53 RefPtr<TransformPaintPropertyNode> newTransformNodeForScrollTranslation = Tr ansformPaintPropertyNode::create(frameScroll, FloatPoint3D(), newTransformNodeFo rPreTranslation); 56 if (!frameView.scrollTranslation() || frameView.scrollTranslation()->matrix( ) != frameScroll)
57 frameView.setScrollTranslation(TransformPaintPropertyNode::create(frameS croll, FloatPoint3D(), frameView.preTranslation()));
54 58
55 // Initialize the context for current, absolute and fixed position cases. 59 // Initialize the context for current, absolute and fixed position cases.
56 // They are the same, except that scroll translation does not apply to 60 // They are the same, except that scroll translation does not apply to
57 // fixed position descendants. 61 // fixed position descendants.
58 context.current.transform = newTransformNodeForScrollTranslation.get(); 62 context.current.transform = frameView.scrollTranslation();
59 context.current.paintOffset = LayoutPoint(); 63 context.current.paintOffset = LayoutPoint();
60 context.current.clip = newClipNodeForContentClip.get(); 64 context.current.clip = frameView.contentClip();
61 context.absolutePosition = context.current; 65 context.absolutePosition = context.current;
62 context.containerForAbsolutePosition = nullptr; 66 context.containerForAbsolutePosition = nullptr;
63 context.fixedPosition = context.current; 67 context.fixedPosition = context.current;
64 context.fixedPosition.transform = newTransformNodeForPreTranslation.get(); 68 context.fixedPosition.transform = frameView.preTranslation();
65
66 frameView.setPreTranslation(newTransformNodeForPreTranslation.release());
67 frameView.setScrollTranslation(newTransformNodeForScrollTranslation.release( ));
68 frameView.setContentClip(newClipNodeForContentClip.release());
69 } 69 }
70 70
71 void PaintPropertyTreeBuilder::updatePaintOffsetTranslation(const LayoutObject& object, PaintPropertyTreeBuilderContext& context) 71 template <
72 typename PropertyNode,
73 PropertyNode* (ObjectPaintProperties::*Getter)() const,
74 void (ObjectPaintProperties::*Setter)(PassRefPtr<PropertyNode>),
75 bool (*ComputeProperty)(const LayoutObject&, PaintPropertyTreeBuilderContext &, typename PropertyNode::Value&)>
76 PropertyNode* PaintPropertyTreeBuilder::updateObjectPaintProperty(const LayoutOb ject& object, PaintPropertyTreeBuilderContext& context, PropertyNode*& contextPr operty)
pdr. 2016/07/21 21:34:06 This template approach is very clever. WDYT of thi
Xianzhu 2016/07/22 01:14:05 Many thanks for the sample CL. Mixed your code int
72 { 77 {
73 if (object.isBoxModelObject()) { 78 ObjectPaintProperties* previousProperties = object.objectPaintProperties();
74 // TODO(trchen): Eliminate PaintLayer dependency. 79 typename PropertyNode::Value newPropertyValue;
75 PaintLayer* layer = toLayoutBoxModelObject(object).layer(); 80 if (!ComputeProperty(object, context, newPropertyValue)) {
76 if (!layer || !layer->paintsWithTransform(GlobalPaintNormalPhase)) 81 if (previousProperties)
77 return; 82 (previousProperties->*Setter)(nullptr);
83 return nullptr;
78 } 84 }
79 85
86 PropertyNode* previousPropertyNode = previousProperties ? (previousPropertie s->*Getter)() : nullptr;
87 if (previousPropertyNode && previousPropertyNode->value() == newPropertyValu e) {
88 previousPropertyNode->setParent(contextProperty);
89 contextProperty = previousPropertyNode;
90 return previousPropertyNode;
91 }
92
93 RefPtr<PropertyNode> newPropertyNode = PropertyNode::create(newPropertyValue , contextProperty);
94 contextProperty = newPropertyNode.get();
95 (object.getMutableForPainting().ensureObjectPaintProperties().*Setter)(newPr opertyNode.release());
96 return contextProperty;
97 }
98
99 bool PaintPropertyTreeBuilder::computePaintOffsetTranslation(const LayoutObject& object, PaintPropertyTreeBuilderContext& context, TransformPaintPropertyNode::V alue& value)
100 {
101 if (!object.isBoxModelObject())
102 return false;
103
104 // TODO(trchen): Eliminate PaintLayer dependency.
105 PaintLayer* layer = toLayoutBoxModelObject(object).layer();
106 if (!layer || !layer->paintsWithTransform(GlobalPaintNormalPhase))
107 return false;
108
80 if (context.current.paintOffset == LayoutPoint()) 109 if (context.current.paintOffset == LayoutPoint())
81 return; 110 return false;
82 111
83 // We should use the same subpixel paint offset values for snapping regardle ss of whether a 112 // 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 113 // 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. 114 // 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 115 // In spv1 this was called "subpixel accumulation". For more information, se e
87 // PaintLayer::subpixelAccumulation() and PaintLayerPainter::paintFragmentBy ApplyingTransform. 116 // PaintLayer::subpixelAccumulation() and PaintLayerPainter::paintFragmentBy ApplyingTransform.
88 IntPoint roundedPaintOffset = roundedIntPoint(context.current.paintOffset); 117 IntPoint roundedPaintOffset = roundedIntPoint(context.current.paintOffset);
89 LayoutPoint fractionalPaintOffset = LayoutPoint(context.current.paintOffset - roundedPaintOffset); 118 LayoutPoint fractionalPaintOffset = LayoutPoint(context.current.paintOffset - roundedPaintOffset);
90 119
91 RefPtr<TransformPaintPropertyNode> paintOffsetTranslation = TransformPaintPr opertyNode::create( 120 value.matrix.translate(roundedPaintOffset.x(), roundedPaintOffset.y());
92 TransformationMatrix().translate(roundedPaintOffset.x(), roundedPaintOff set.y()),
93 FloatPoint3D(), context.current.transform);
94 context.current.transform = paintOffsetTranslation.get();
95 context.current.paintOffset = fractionalPaintOffset; 121 context.current.paintOffset = fractionalPaintOffset;
96 object.getMutableForPainting().ensureObjectPaintProperties().setPaintOffsetT ranslation(paintOffsetTranslation.release()); 122 return true;
123 }
124
125 void PaintPropertyTreeBuilder::updatePaintOffsetTranslation(const LayoutObject& object, PaintPropertyTreeBuilderContext& context)
126 {
127 updateObjectPaintProperty<
128 TransformPaintPropertyNode,
129 &ObjectPaintProperties::paintOffsetTranslation,
130 &ObjectPaintProperties::setPaintOffsetTranslation,
131 &computePaintOffsetTranslation>(object, context, context.current.transfo rm);
97 } 132 }
98 133
99 static FloatPoint3D transformOrigin(const LayoutBox& box) 134 static FloatPoint3D transformOrigin(const LayoutBox& box)
100 { 135 {
101 const ComputedStyle& style = box.styleRef(); 136 const ComputedStyle& style = box.styleRef();
102 FloatSize borderBoxSize(box.size()); 137 FloatSize borderBoxSize(box.size());
103 return FloatPoint3D( 138 return FloatPoint3D(
104 floatValueForLength(style.transformOriginX(), borderBoxSize.width()), 139 floatValueForLength(style.transformOriginX(), borderBoxSize.width()),
105 floatValueForLength(style.transformOriginY(), borderBoxSize.height()), 140 floatValueForLength(style.transformOriginY(), borderBoxSize.height()),
106 style.transformOriginZ()); 141 style.transformOriginZ());
107 } 142 }
108 143
109 void PaintPropertyTreeBuilder::updateTransform(const LayoutObject& object, Paint PropertyTreeBuilderContext& context) 144 bool PaintPropertyTreeBuilder::computeTransform(const LayoutObject& object, Pain tPropertyTreeBuilderContext& context, TransformPaintPropertyNode::Value& value)
110 { 145 {
111 if (object.isSVG() && !object.isSVGRoot()) { 146 if (object.isSVG() && !object.isSVGRoot()) {
112 // SVG does not use paint offset internally. 147 // SVG does not use paint offset internally.
113 DCHECK(context.current.paintOffset == LayoutPoint()); 148 DCHECK(context.current.paintOffset == LayoutPoint());
114 149
115 // FIXME(pdr): Check for the presence of a transform instead of the valu e. Checking for an 150 // 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 151 // identity matrix will cause the property tree structure to change duri ng animations if
117 // the animation passes through the identity matrix. 152 // the animation passes through the identity matrix.
118 // FIXME(pdr): Refactor this so all non-root SVG objects use the same tr ansform function. 153 // 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(); 154 const AffineTransform& transform = object.isSVGForeignObject() ? object. localSVGTransform() : object.localToSVGParentTransform();
120 if (transform.isIdentity()) 155 if (transform.isIdentity())
121 return; 156 return false;
122 157
123 // The origin is included in the local transform, so use an empty origin . 158 value.matrix = transform;
124 RefPtr<TransformPaintPropertyNode> svgTransform = TransformPaintProperty Node::create( 159 // The origin is included in the local transform, so leave origin empty.
125 transform, FloatPoint3D(0, 0, 0), context.current.transform); 160 return true;
126 context.current.transform = svgTransform.get();
127 object.getMutableForPainting().ensureObjectPaintProperties().setTransfor m(svgTransform.release());
128 return;
129 } 161 }
130 162
131 const ComputedStyle& style = object.styleRef(); 163 const ComputedStyle& style = object.styleRef();
132 if (!object.isBox() || !style.hasTransform()) 164 if (!object.isBox() || !style.hasTransform())
133 return; 165 return false;
134 166
135 TransformationMatrix matrix; 167 style.applyTransform(value.matrix, toLayoutBox(object).size(), ComputedStyle ::ExcludeTransformOrigin,
136 style.applyTransform(matrix, toLayoutBox(object).size(), ComputedStyle::Excl udeTransformOrigin,
137 ComputedStyle::IncludeMotionPath, ComputedStyle::IncludeIndependentTrans formProperties); 168 ComputedStyle::IncludeMotionPath, ComputedStyle::IncludeIndependentTrans formProperties);
138 RefPtr<TransformPaintPropertyNode> transformNode = TransformPaintPropertyNod e::create( 169 value.origin = transformOrigin(toLayoutBox(object));
139 matrix, transformOrigin(toLayoutBox(object)), context.current.transform) ; 170 return true;
140 context.current.transform = transformNode.get(); 171 }
141 object.getMutableForPainting().ensureObjectPaintProperties().setTransform(tr ansformNode.release()); 172
173 void PaintPropertyTreeBuilder::updateTransform(const LayoutObject& object, Paint PropertyTreeBuilderContext& context)
174 {
175 updateObjectPaintProperty<
176 TransformPaintPropertyNode,
177 &ObjectPaintProperties::transform,
178 &ObjectPaintProperties::setTransform,
179 &computeTransform>(object, context, context.current.transform);
180 }
181
182 bool PaintPropertyTreeBuilder::computeEffect(const LayoutObject& object, PaintPr opertyTreeBuilderContext& context, EffectPaintPropertyNode::Value& value)
183 {
184 if (!object.styleRef().hasOpacity())
185 return false;
186
187 value = object.styleRef().opacity();
188 return true;
142 } 189 }
143 190
144 void PaintPropertyTreeBuilder::updateEffect(const LayoutObject& object, PaintPro pertyTreeBuilderContext& context) 191 void PaintPropertyTreeBuilder::updateEffect(const LayoutObject& object, PaintPro pertyTreeBuilderContext& context)
145 { 192 {
146 if (!object.styleRef().hasOpacity()) 193 updateObjectPaintProperty<
147 return; 194 EffectPaintPropertyNode,
148 RefPtr<EffectPaintPropertyNode> effectNode = EffectPaintPropertyNode::create (object.styleRef().opacity(), context.currentEffect); 195 &ObjectPaintProperties::effect,
149 context.currentEffect = effectNode.get(); 196 &ObjectPaintProperties::setEffect,
150 object.getMutableForPainting().ensureObjectPaintProperties().setEffect(effec tNode.release()); 197 &computeEffect>(object, context, context.currentEffect);
151 } 198 }
152 199
153 void PaintPropertyTreeBuilder::updateCssClip(const LayoutObject& object, PaintPr opertyTreeBuilderContext& context) 200 bool PaintPropertyTreeBuilder::computeCssClip(const LayoutObject& object, PaintP ropertyTreeBuilderContext& context, ClipPaintPropertyNode::Value& value)
154 { 201 {
155 if (!object.hasClip()) 202 if (!object.hasClip())
156 return; 203 return false;
157 ASSERT(object.canContainAbsolutePositionObjects()); 204 DCHECK(object.canContainAbsolutePositionObjects());
158 205
159 // Create clip node for descendants that are not fixed position. 206 // 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 207 // 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 208 // a container for absolute position descendants, and will copy from in-flow context later
162 // at updateOutOfFlowContext() step. 209 // at updateOutOfFlowContext() step.
163 LayoutRect clipRect = toLayoutBox(object).clipRect(context.current.paintOffs et); 210 LayoutRect clipRect = toLayoutBox(object).clipRect(context.current.paintOffs et);
164 RefPtr<ClipPaintPropertyNode> clipNode = ClipPaintPropertyNode::create( 211 value = FloatRoundedRect(FloatRect(clipRect));
165 context.current.transform, 212 return true;
166 FloatRoundedRect(FloatRect(clipRect)), 213 }
167 context.current.clip); 214
168 context.current.clip = clipNode.get(); 215 void PaintPropertyTreeBuilder::updateCssClip(const LayoutObject& object, PaintPr opertyTreeBuilderContext& context)
169 object.getMutableForPainting().ensureObjectPaintProperties().setCssClip(clip Node.release()); 216 {
217 if (ClipPaintPropertyNode* node = updateObjectPaintProperty<
218 ClipPaintPropertyNode,
219 &ObjectPaintProperties::cssClip,
220 &ObjectPaintProperties::setCssClip,
221 &computeCssClip>(object, context, context.current.clip))
222 node->setLocalTransformSpace(context.current.transform);
170 } 223 }
171 224
172 void PaintPropertyTreeBuilder::updateLocalBorderBoxContext(const LayoutObject& o bject, const PaintPropertyTreeBuilderContext& context) 225 void PaintPropertyTreeBuilder::updateLocalBorderBoxContext(const LayoutObject& o bject, const PaintPropertyTreeBuilderContext& context)
173 { 226 {
174 // Avoid adding an ObjectPaintProperties for non-boxes to save memory, since we don't need them at the moment. 227 // 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()) 228 if (!object.isBox() && !object.hasLayer())
176 return; 229 return;
177 230
178 std::unique_ptr<ObjectPaintProperties::LocalBorderBoxProperties> borderBoxCo ntext = 231 std::unique_ptr<ObjectPaintProperties::LocalBorderBoxProperties> borderBoxCo ntext =
179 wrapUnique(new ObjectPaintProperties::LocalBorderBoxProperties); 232 wrapUnique(new ObjectPaintProperties::LocalBorderBoxProperties);
180 borderBoxContext->paintOffset = context.current.paintOffset; 233 borderBoxContext->paintOffset = context.current.paintOffset;
181 borderBoxContext->propertyTreeState = PropertyTreeState(context.current.tran sform, context.current.clip, context.currentEffect); 234 borderBoxContext->propertyTreeState = PropertyTreeState(context.current.tran sform, context.current.clip, context.currentEffect);
182 object.getMutableForPainting().ensureObjectPaintProperties().setLocalBorderB oxProperties(std::move(borderBoxContext)); 235 object.getMutableForPainting().ensureObjectPaintProperties().setLocalBorderB oxProperties(std::move(borderBoxContext));
183 } 236 }
184 237
185 // TODO(trchen): Remove this once we bake the paint offset into frameRect. 238 // TODO(trchen): Remove this once we bake the paint offset into frameRect.
239 bool PaintPropertyTreeBuilder::computeScrollbarPaintOffset(const LayoutObject& o bject, const PaintPropertyTreeBuilderContext& context, TransformPaintPropertyNod e::Value& value)
240 {
241 IntPoint roundedPaintOffset = roundedIntPoint(context.current.paintOffset);
242 if (roundedPaintOffset == IntPoint())
243 return false;
244
245 if (!object.isBoxModelObject())
246 return false;
247 PaintLayerScrollableArea* scrollableArea = toLayoutBoxModelObject(object).ge tScrollableArea();
248 if (!scrollableArea)
249 return false;
250 if (!scrollableArea->horizontalScrollbar() && !scrollableArea->verticalScrol lbar())
251 return false;
252
253 value.matrix.translate(roundedPaintOffset.x(), roundedPaintOffset.y());
254 return true;
255 }
256
257 // TODO(trchen): Remove this once we bake the paint offset into frameRect.
186 void PaintPropertyTreeBuilder::updateScrollbarPaintOffset(const LayoutObject& ob ject, const PaintPropertyTreeBuilderContext& context) 258 void PaintPropertyTreeBuilder::updateScrollbarPaintOffset(const LayoutObject& ob ject, const PaintPropertyTreeBuilderContext& context)
187 { 259 {
188 IntPoint roundedPaintOffset = roundedIntPoint(context.current.paintOffset); 260 // This method is almost the same as updateObjectPaintProperty template, exc ept that it doesn't
pdr. 2016/07/21 21:34:06 Can you think of a way to use the same update obje
Xianzhu 2016/07/22 01:14:04 Done.
189 if (roundedPaintOffset == IntPoint()) 261 // update any context property.
262 ObjectPaintProperties* previousProperties = object.objectPaintProperties();
263 TransformPaintPropertyNode::Value paintOffset;
264 if (!computeScrollbarPaintOffset(object, context, paintOffset)) {
265 if (previousProperties)
266 (previousProperties->setScrollbarPaintOffset(nullptr));
190 return; 267 return;
268 }
191 269
192 if (!object.isBoxModelObject()) 270 TransformPaintPropertyNode* previousScrollbarPaintOffsetNode = previousPrope rties ? previousProperties->scrollbarPaintOffset() : nullptr;
271 if (previousScrollbarPaintOffsetNode && previousScrollbarPaintOffsetNode->va lue() == paintOffset) {
272 previousScrollbarPaintOffsetNode->setParent(context.current.transform);
193 return; 273 return;
194 PaintLayerScrollableArea* scrollableArea = toLayoutBoxModelObject(object).ge tScrollableArea(); 274 }
195 if (!scrollableArea)
196 return;
197 if (!scrollableArea->horizontalScrollbar() && !scrollableArea->verticalScrol lbar())
198 return;
199 275
200 auto paintOffset = TransformationMatrix().translate(roundedPaintOffset.x(), roundedPaintOffset.y());
201 object.getMutableForPainting().ensureObjectPaintProperties().setScrollbarPai ntOffset( 276 object.getMutableForPainting().ensureObjectPaintProperties().setScrollbarPai ntOffset(
202 TransformPaintPropertyNode::create(paintOffset, FloatPoint3D(), context. current.transform)); 277 TransformPaintPropertyNode::create(paintOffset, context.current.transfor m));
203 } 278 }
204 279
205 void PaintPropertyTreeBuilder::updateOverflowClip(const LayoutObject& object, Pa intPropertyTreeBuilderContext& context) 280 bool PaintPropertyTreeBuilder::computeOverflowClip(const LayoutObject& object, P aintPropertyTreeBuilderContext& context, ClipPaintPropertyNode::Value& value)
206 { 281 {
207 if (!object.isBox())
208 return;
209 const LayoutBox& box = toLayoutBox(object); 282 const LayoutBox& box = toLayoutBox(object);
210 283
211 // The <input> elements can't have contents thus CSS overflow property doesn 't apply. 284 // 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. 285 // 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 286 // We should clip the overflow from those children. This is called control c lip and we
214 // technically treat them like overflow clip. 287 // technically treat them like overflow clip.
215 LayoutRect clipRect; 288 LayoutRect clipRect;
216 if (box.hasControlClip()) 289 if (box.hasControlClip())
217 clipRect = box.controlClipRect(context.current.paintOffset); 290 clipRect = box.controlClipRect(context.current.paintOffset);
218 else if (box.hasOverflowClip()) 291 else if (box.hasOverflowClip())
219 clipRect = box.overflowClipRect(context.current.paintOffset); 292 clipRect = box.overflowClipRect(context.current.paintOffset);
220 else 293 else
294 return false;
295
296 value = FloatRoundedRect(FloatRect(clipRect));
297 return true;
298 }
299
300 void PaintPropertyTreeBuilder::updateOverflowClip(const LayoutObject& object, Pa intPropertyTreeBuilderContext& context)
301 {
302 if (!object.isBox())
221 return; 303 return;
304 const LayoutBox& box = toLayoutBox(object);
222 305
306 // This need to be in top-level block to hold the reference until we finish creating the normal clip node.
223 RefPtr<ClipPaintPropertyNode> borderRadiusClip; 307 RefPtr<ClipPaintPropertyNode> borderRadiusClip;
224 if (box.styleRef().hasBorderRadius()) { 308 if ((box.hasControlClip() || box.hasOverflowClip()) && box.styleRef().hasBor derRadius()) {
225 auto innerBorder = box.styleRef().getRoundedInnerBorderFor( 309 auto innerBorder = box.styleRef().getRoundedInnerBorderFor(
226 LayoutRect(context.current.paintOffset, box.size())); 310 LayoutRect(context.current.paintOffset, box.size()));
227 borderRadiusClip = ClipPaintPropertyNode::create( 311 borderRadiusClip = ClipPaintPropertyNode::create(context.current.transfo rm, innerBorder, context.current.clip);
228 context.current.transform, innerBorder, context.current.clip); 312 context.current.clip = borderRadiusClip.get();
229 } 313 }
230 314
231 RefPtr<ClipPaintPropertyNode> overflowClip = ClipPaintPropertyNode::create( 315 if (ClipPaintPropertyNode* node = updateObjectPaintProperty<
232 context.current.transform, 316 ClipPaintPropertyNode,
233 FloatRoundedRect(FloatRect(clipRect)), 317 &ObjectPaintProperties::overflowClip,
234 borderRadiusClip ? borderRadiusClip.release() : context.current.clip); 318 &ObjectPaintProperties::setOverflowClip,
235 context.current.clip = overflowClip.get(); 319 &computeOverflowClip>(object, context, context.current.clip))
236 object.getMutableForPainting().ensureObjectPaintProperties().setOverflowClip (overflowClip.release()); 320 node->setLocalTransformSpace(context.current.transform);
237 } 321 }
238 322
239 static FloatPoint perspectiveOrigin(const LayoutBox& box) 323 static FloatPoint perspectiveOrigin(const LayoutBox& box)
240 { 324 {
241 const ComputedStyle& style = box.styleRef(); 325 const ComputedStyle& style = box.styleRef();
242 FloatSize borderBoxSize(box.size()); 326 FloatSize borderBoxSize(box.size());
243 return FloatPoint( 327 return FloatPoint(
244 floatValueForLength(style.perspectiveOriginX(), borderBoxSize.width()), 328 floatValueForLength(style.perspectiveOriginX(), borderBoxSize.width()),
245 floatValueForLength(style.perspectiveOriginY(), borderBoxSize.height())) ; 329 floatValueForLength(style.perspectiveOriginY(), borderBoxSize.height())) ;
246 } 330 }
247 331
332 bool PaintPropertyTreeBuilder::computePerspective(const LayoutObject& object, Pa intPropertyTreeBuilderContext& context, TransformPaintPropertyNode::Value& value )
333 {
334 const ComputedStyle& style = object.styleRef();
335 if (!object.isBox() || !style.hasPerspective())
336 return false;
337
338 value.matrix.applyPerspective(style.perspective());
339 value.origin = perspectiveOrigin(toLayoutBox(object)) + toLayoutSize(context .current.paintOffset);
340 return true;
341 }
342
248 void PaintPropertyTreeBuilder::updatePerspective(const LayoutObject& object, Pai ntPropertyTreeBuilderContext& context) 343 void PaintPropertyTreeBuilder::updatePerspective(const LayoutObject& object, Pai ntPropertyTreeBuilderContext& context)
249 { 344 {
250 const ComputedStyle& style = object.styleRef(); 345 updateObjectPaintProperty<
251 if (!object.isBox() || !style.hasPerspective()) 346 TransformPaintPropertyNode,
252 return; 347 &ObjectPaintProperties::perspective,
253 348 &ObjectPaintProperties::setPerspective,
254 RefPtr<TransformPaintPropertyNode> perspective = TransformPaintPropertyNode: :create( 349 &computePerspective>(object, context, context.current.transform);
255 TransformationMatrix().applyPerspective(style.perspective()),
256 perspectiveOrigin(toLayoutBox(object)) + toLayoutSize(context.current.pa intOffset),
257 context.current.transform);
258 context.current.transform = perspective.get();
259 object.getMutableForPainting().ensureObjectPaintProperties().setPerspective( perspective.release());
260 } 350 }
261 351
262 void PaintPropertyTreeBuilder::updateSvgLocalToBorderBoxTransform(const LayoutOb ject& object, PaintPropertyTreeBuilderContext& context) 352 bool PaintPropertyTreeBuilder::computeSvgLocalToBorderBoxTransform(const LayoutO bject& object, PaintPropertyTreeBuilderContext& context, TransformPaintPropertyN ode::Value& value)
263 { 353 {
264 if (!object.isSVGRoot()) 354 if (!object.isSVGRoot())
265 return; 355 return false;
266 356
267 AffineTransform transformToBorderBox = SVGRootPainter(toLayoutSVGRoot(object )).transformToPixelSnappedBorderBox(context.current.paintOffset); 357 AffineTransform transformToBorderBox = SVGRootPainter(toLayoutSVGRoot(object )).transformToPixelSnappedBorderBox(context.current.paintOffset);
268 358
269 // The paint offset is included in |transformToBorderBox| so SVG does not ne ed to handle paint 359 // The paint offset is included in |transformToBorderBox| so SVG does not ne ed to handle paint
270 // offset internally. 360 // offset internally.
271 context.current.paintOffset = LayoutPoint(); 361 context.current.paintOffset = LayoutPoint();
272 362
273 if (transformToBorderBox.isIdentity()) 363 if (transformToBorderBox.isIdentity())
274 return; 364 return false;
275 365
276 RefPtr<TransformPaintPropertyNode> svgLocalToBorderBoxTransform = TransformP aintPropertyNode::create( 366 value.matrix = transformToBorderBox;
277 transformToBorderBox, FloatPoint3D(0, 0, 0), context.current.transform);
278 context.current.transform = svgLocalToBorderBoxTransform.get();
279 context.current.paintOffset = LayoutPoint(); 367 context.current.paintOffset = LayoutPoint();
280 object.getMutableForPainting().ensureObjectPaintProperties().setSvgLocalToBo rderBoxTransform(svgLocalToBorderBoxTransform.release()); 368 return true;
281 } 369 }
282 370
283 void PaintPropertyTreeBuilder::updateScrollTranslation(const LayoutObject& objec t, PaintPropertyTreeBuilderContext& context) 371 void PaintPropertyTreeBuilder::updateSvgLocalToBorderBoxTransform(const LayoutOb ject& object, PaintPropertyTreeBuilderContext& context)
372 {
373 updateObjectPaintProperty<
374 TransformPaintPropertyNode,
375 &ObjectPaintProperties::svgLocalToBorderBoxTransform,
376 &ObjectPaintProperties::setSvgLocalToBorderBoxTransform,
377 &computeSvgLocalToBorderBoxTransform>(object, context, context.current.t ransform);
378 }
379
380 bool PaintPropertyTreeBuilder::computeScrollTranslation(const LayoutObject& obje ct, PaintPropertyTreeBuilderContext& context, TransformPaintPropertyNode::Value& value)
284 { 381 {
285 if (!object.isBoxModelObject() || !object.hasOverflowClip()) 382 if (!object.isBoxModelObject() || !object.hasOverflowClip())
286 return; 383 return false;
287 384
288 PaintLayer* layer = toLayoutBoxModelObject(object).layer(); 385 PaintLayer* layer = toLayoutBoxModelObject(object).layer();
289 ASSERT(layer); 386 ASSERT(layer);
290 DoubleSize scrollOffset = layer->getScrollableArea()->scrollOffset(); 387 DoubleSize scrollOffset = layer->getScrollableArea()->scrollOffset();
291 if (scrollOffset.isZero() && !layer->scrollsOverflow()) 388 if (scrollOffset.isZero() && !layer->scrollsOverflow())
292 return; 389 return false;
293 390
294 RefPtr<TransformPaintPropertyNode> scrollTranslation = TransformPaintPropert yNode::create( 391 value.matrix.translate(-scrollOffset.width(), -scrollOffset.height());
295 TransformationMatrix().translate(-scrollOffset.width(), -scrollOffset.he ight()), 392 return true;
296 FloatPoint3D(),
297 context.current.transform);
298 context.current.transform = scrollTranslation.get();
299 object.getMutableForPainting().ensureObjectPaintProperties().setScrollTransl ation(scrollTranslation.release());
300 } 393 }
301 394
302 void PaintPropertyTreeBuilder::updateOutOfFlowContext(const LayoutObject& object , PaintPropertyTreeBuilderContext& context) 395 void PaintPropertyTreeBuilder::updateScrollTranslation(const LayoutObject& objec t, PaintPropertyTreeBuilderContext& context)
396 {
397 updateObjectPaintProperty<
398 TransformPaintPropertyNode,
399 &ObjectPaintProperties::scrollTranslation,
400 &ObjectPaintProperties::setScrollTranslation,
401 &computeScrollTranslation>(object, context, context.current.transform);
402 }
403
404 // Returns true if we need to create a cssClip node for fixed position.
405 bool PaintPropertyTreeBuilder::computeOutOfFlowContext(const LayoutObject& objec t, PaintPropertyTreeBuilderContext& context, ClipPaintPropertyNode::Value& value )
303 { 406 {
304 if (object.canContainAbsolutePositionObjects()) { 407 if (object.canContainAbsolutePositionObjects()) {
305 context.absolutePosition = context.current; 408 context.absolutePosition = context.current;
306 context.containerForAbsolutePosition = &object; 409 context.containerForAbsolutePosition = &object;
307 } 410 }
308 411
309 // TODO(pdr): Remove the !object.isLayoutView() condition when removing Fram eView 412 // TODO(pdr): Remove the !object.isLayoutView() condition when removing Fram eView
310 // paint properties for rootLayerScrolls. 413 // paint properties for rootLayerScrolls.
311 if (!object.isLayoutView() && object.canContainFixedPositionObjects()) { 414 if (!object.isLayoutView() && object.canContainFixedPositionObjects()) {
312 context.fixedPosition = context.current; 415 context.fixedPosition = context.current;
313 } else if (object.objectPaintProperties() && object.objectPaintProperties()- >cssClip()) { 416 return false;
314 // CSS clip applies to all descendants, even if this object is not a con taining block 417 }
315 // 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
317 // descendants we need to insert the clip here if we are not a containin g block ancestor
318 // of them.
319 auto* cssClip = object.objectPaintProperties()->cssClip();
320 418
321 // Before we actually create anything, check whether in-flow context and fixed-position 419 if (!object.objectPaintProperties() || !object.objectPaintProperties()->cssC lip())
322 // context has exactly the same clip. Reuse if possible. 420 return false;
323 if (context.fixedPosition.clip == cssClip->parent()) {
324 context.fixedPosition.clip = cssClip;
325 return;
326 }
327 421
328 RefPtr<ClipPaintPropertyNode> clipFixedPosition = ClipPaintPropertyNode: :create( 422 // CSS clip applies to all descendants, even if this object is not a contain ing block
329 const_cast<TransformPaintPropertyNode*>(cssClip->localTransformSpace ()), 423 // ancestor of the descendant. It is okay for absolute-position descendants because
330 cssClip->clipRect(), 424 // having CSS clip implies being absolute position container. However for fi xed-position
331 context.fixedPosition.clip); 425 // descendants we need to insert the clip here if we are not a containing bl ock ancestor
332 context.fixedPosition.clip = clipFixedPosition.get(); 426 // of them.
333 object.getMutableForPainting().ensureObjectPaintProperties().setCssClipF ixedPosition(clipFixedPosition.release()); 427 auto* cssClip = object.objectPaintProperties()->cssClip();
428
429 // Before we actually create anything, check whether in-flow context and fix ed-position
430 // context has exactly the same clip. Reuse if possible.
431 if (context.fixedPosition.clip == cssClip->parent()) {
432 context.fixedPosition.clip = cssClip;
433 return false;
334 } 434 }
435
436 value = cssClip->clipRect();
437 return true;
438 }
439
440 void PaintPropertyTreeBuilder::updateOutOfFlowContext(const LayoutObject& object , PaintPropertyTreeBuilderContext& context)
441 {
442 if (ClipPaintPropertyNode* node = updateObjectPaintProperty<
443 ClipPaintPropertyNode,
444 &ObjectPaintProperties::cssClipFixedPosition,
445 &ObjectPaintProperties::setCssClipFixedPosition,
446 &computeOutOfFlowContext>(object, context, context.fixedPosition.clip))
447 node->setLocalTransformSpace(const_cast<TransformPaintPropertyNode*>(obj ect.objectPaintProperties()->cssClip()->localTransformSpace()));
335 } 448 }
336 449
337 static void deriveBorderBoxFromContainerContext(const LayoutObject& object, Pain tPropertyTreeBuilderContext& context) 450 static void deriveBorderBoxFromContainerContext(const LayoutObject& object, Pain tPropertyTreeBuilderContext& context)
338 { 451 {
339 if (!object.isBoxModelObject()) 452 if (!object.isBoxModelObject())
340 return; 453 return;
341 454
342 const LayoutBoxModelObject& boxModelObject = toLayoutBoxModelObject(object); 455 const LayoutBoxModelObject& boxModelObject = toLayoutBoxModelObject(object);
343 456
344 switch (object.styleRef().position()) { 457 switch (object.styleRef().position()) {
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
378 if (boxModelObject.isTableCell()) { 491 if (boxModelObject.isTableCell()) {
379 LayoutObject* parentRow = boxModelObject.parent(); 492 LayoutObject* parentRow = boxModelObject.parent();
380 ASSERT(parentRow && parentRow->isTableRow()); 493 ASSERT(parentRow && parentRow->isTableRow());
381 context.current.paintOffset.moveBy(-toLayoutBox(parentRow)->topLeftL ocation()); 494 context.current.paintOffset.moveBy(-toLayoutBox(parentRow)->topLeftL ocation());
382 } 495 }
383 } 496 }
384 } 497 }
385 498
386 void PaintPropertyTreeBuilder::buildTreeNodes(const LayoutObject& object, PaintP ropertyTreeBuilderContext& context) 499 void PaintPropertyTreeBuilder::buildTreeNodes(const LayoutObject& object, PaintP ropertyTreeBuilderContext& context)
387 { 500 {
388 object.getMutableForPainting().clearObjectPaintProperties();
389
390 if (!object.isBoxModelObject() && !object.isSVG()) 501 if (!object.isBoxModelObject() && !object.isSVG())
391 return; 502 return;
392 503
393 deriveBorderBoxFromContainerContext(object, context); 504 deriveBorderBoxFromContainerContext(object, context);
394 505
395 updatePaintOffsetTranslation(object, context); 506 updatePaintOffsetTranslation(object, context);
396 updateTransform(object, context); 507 updateTransform(object, context);
397 updateEffect(object, context); 508 updateEffect(object, context);
398 updateCssClip(object, context); 509 updateCssClip(object, context);
399 updateLocalBorderBoxContext(object, context); 510 updateLocalBorderBoxContext(object, context);
400 updateScrollbarPaintOffset(object, context); 511 updateScrollbarPaintOffset(object, context);
401 updateOverflowClip(object, context); 512 updateOverflowClip(object, context);
402 // TODO(trchen): Insert flattening transform here, as specified by 513 // TODO(trchen): Insert flattening transform here, as specified by
403 // http://www.w3.org/TR/css3-transforms/#transform-style-property 514 // http://www.w3.org/TR/css3-transforms/#transform-style-property
404 updatePerspective(object, context); 515 updatePerspective(object, context);
405 updateSvgLocalToBorderBoxTransform(object, context); 516 updateSvgLocalToBorderBoxTransform(object, context);
406 updateScrollTranslation(object, context); 517 updateScrollTranslation(object, context);
407 updateOutOfFlowContext(object, context); 518 updateOutOfFlowContext(object, context);
408 } 519 }
409 520
410 } // namespace blink 521 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698