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

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(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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698