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

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

Issue 2539693002: Early-out from the prepaint tree walk (Closed)
Patch Set: Address chrishtrs comments Created 4 years 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"
(...skipping 16 matching lines...) Expand all
27 context.fixedPosition.clip = ClipPaintPropertyNode::root(); 27 context.fixedPosition.clip = ClipPaintPropertyNode::root();
28 context.currentEffect = EffectPaintPropertyNode::root(); 28 context.currentEffect = EffectPaintPropertyNode::root();
29 context.inputClipOfCurrentEffect = ClipPaintPropertyNode::root(); 29 context.inputClipOfCurrentEffect = ClipPaintPropertyNode::root();
30 context.current.transform = context.absolutePosition.transform = 30 context.current.transform = context.absolutePosition.transform =
31 context.fixedPosition.transform = TransformPaintPropertyNode::root(); 31 context.fixedPosition.transform = TransformPaintPropertyNode::root();
32 context.current.scroll = context.absolutePosition.scroll = 32 context.current.scroll = context.absolutePosition.scroll =
33 context.fixedPosition.scroll = ScrollPaintPropertyNode::root(); 33 context.fixedPosition.scroll = ScrollPaintPropertyNode::root();
34 return context; 34 return context;
35 } 35 }
36 36
37 void updateFrameViewPreTranslation( 37 // True if a new property was created, false if an existing one was updated.
38 FrameView& frameView, 38 bool updatePreTranslation(FrameView& frameView,
39 PassRefPtr<const TransformPaintPropertyNode> parent, 39 PassRefPtr<const TransformPaintPropertyNode> parent,
40 const TransformationMatrix& matrix, 40 const TransformationMatrix& matrix,
41 const FloatPoint3D& origin) { 41 const FloatPoint3D& origin) {
42 DCHECK(!RuntimeEnabledFeatures::rootLayerScrollingEnabled()); 42 DCHECK(!RuntimeEnabledFeatures::rootLayerScrollingEnabled());
43 if (auto* existingPreTranslation = frameView.preTranslation()) { 43 if (auto* existingPreTranslation = frameView.preTranslation()) {
44 existingPreTranslation->update(std::move(parent), matrix, origin); 44 existingPreTranslation->update(std::move(parent), matrix, origin);
45 } else { 45 return false;
46 frameView.setPreTranslation(
47 TransformPaintPropertyNode::create(std::move(parent), matrix, origin));
48 } 46 }
47 frameView.setPreTranslation(
48 TransformPaintPropertyNode::create(std::move(parent), matrix, origin));
49 return true;
49 } 50 }
50 51
51 void updateFrameViewContentClip( 52 // True if a new property was created, false if an existing one was updated.
53 bool updateContentClip(
52 FrameView& frameView, 54 FrameView& frameView,
53 PassRefPtr<const ClipPaintPropertyNode> parent, 55 PassRefPtr<const ClipPaintPropertyNode> parent,
54 PassRefPtr<const TransformPaintPropertyNode> localTransformSpace, 56 PassRefPtr<const TransformPaintPropertyNode> localTransformSpace,
55 const FloatRoundedRect& clipRect) { 57 const FloatRoundedRect& clipRect) {
56 DCHECK(!RuntimeEnabledFeatures::rootLayerScrollingEnabled()); 58 DCHECK(!RuntimeEnabledFeatures::rootLayerScrollingEnabled());
57 if (auto* existingContentClip = frameView.contentClip()) { 59 if (auto* existingContentClip = frameView.contentClip()) {
58 existingContentClip->update(std::move(parent), 60 existingContentClip->update(std::move(parent),
59 std::move(localTransformSpace), clipRect); 61 std::move(localTransformSpace), clipRect);
60 } else { 62 return false;
61 frameView.setContentClip(ClipPaintPropertyNode::create(
62 std::move(parent), std::move(localTransformSpace), clipRect));
63 } 63 }
64 frameView.setContentClip(ClipPaintPropertyNode::create(
65 std::move(parent), std::move(localTransformSpace), clipRect));
66 return true;
64 } 67 }
65 68
66 void updateFrameViewScrollTranslation( 69 // True if a new property was created, false if an existing one was updated.
70 bool updateScrollTranslation(
67 FrameView& frameView, 71 FrameView& frameView,
68 PassRefPtr<const TransformPaintPropertyNode> parent, 72 PassRefPtr<const TransformPaintPropertyNode> parent,
69 const TransformationMatrix& matrix, 73 const TransformationMatrix& matrix,
70 const FloatPoint3D& origin) { 74 const FloatPoint3D& origin) {
71 DCHECK(!RuntimeEnabledFeatures::rootLayerScrollingEnabled()); 75 DCHECK(!RuntimeEnabledFeatures::rootLayerScrollingEnabled());
72 if (auto* existingScrollTranslation = frameView.scrollTranslation()) { 76 if (auto* existingScrollTranslation = frameView.scrollTranslation()) {
73 existingScrollTranslation->update(std::move(parent), matrix, origin); 77 existingScrollTranslation->update(std::move(parent), matrix, origin);
74 } else { 78 return false;
75 frameView.setScrollTranslation(
76 TransformPaintPropertyNode::create(std::move(parent), matrix, origin));
77 } 79 }
80 frameView.setScrollTranslation(
81 TransformPaintPropertyNode::create(std::move(parent), matrix, origin));
82 return true;
78 } 83 }
79 84
80 void updateFrameViewScroll( 85 // True if a new property was created, false if an existing one was updated.
81 FrameView& frameView, 86 bool updateScroll(FrameView& frameView,
82 PassRefPtr<const ScrollPaintPropertyNode> parent, 87 PassRefPtr<const ScrollPaintPropertyNode> parent,
83 PassRefPtr<const TransformPaintPropertyNode> scrollOffset, 88 PassRefPtr<const TransformPaintPropertyNode> scrollOffset,
84 const IntSize& clip, 89 const IntSize& clip,
85 const IntSize& bounds, 90 const IntSize& bounds,
86 bool userScrollableHorizontal, 91 bool userScrollableHorizontal,
87 bool userScrollableVertical, 92 bool userScrollableVertical,
88 MainThreadScrollingReasons mainThreadScrollingReasons) { 93 MainThreadScrollingReasons mainThreadScrollingReasons) {
89 DCHECK(!RuntimeEnabledFeatures::rootLayerScrollingEnabled()); 94 DCHECK(!RuntimeEnabledFeatures::rootLayerScrollingEnabled());
90 if (auto* existingScroll = frameView.scroll()) { 95 if (auto* existingScroll = frameView.scroll()) {
91 existingScroll->update(std::move(parent), std::move(scrollOffset), clip, 96 existingScroll->update(std::move(parent), std::move(scrollOffset), clip,
92 bounds, userScrollableHorizontal, 97 bounds, userScrollableHorizontal,
93 userScrollableVertical, mainThreadScrollingReasons); 98 userScrollableVertical, mainThreadScrollingReasons);
94 } else { 99 return false;
95 frameView.setScroll(ScrollPaintPropertyNode::create(
96 std::move(parent), std::move(scrollOffset), clip, bounds,
97 userScrollableHorizontal, userScrollableVertical,
98 mainThreadScrollingReasons));
99 } 100 }
101 frameView.setScroll(ScrollPaintPropertyNode::create(
102 std::move(parent), std::move(scrollOffset), clip, bounds,
103 userScrollableHorizontal, userScrollableVertical,
104 mainThreadScrollingReasons));
105 return true;
100 } 106 }
101 107
102 void PaintPropertyTreeBuilder::updateProperties( 108 void PaintPropertyTreeBuilder::updateProperties(
103 FrameView& frameView, 109 FrameView& frameView,
104 PaintPropertyTreeBuilderContext& context) { 110 PaintPropertyTreeBuilderContext& context) {
105 if (RuntimeEnabledFeatures::rootLayerScrollingEnabled()) { 111 if (RuntimeEnabledFeatures::rootLayerScrollingEnabled()) {
106 // With root layer scrolling, the LayoutView (a LayoutObject) properties are 112 // With root layer scrolling, the LayoutView (a LayoutObject) properties are
107 // updated like other objects (see updatePropertiesAndContextForSelf and 113 // updated like other objects (see updatePropertiesAndContextForSelf and
108 // updatePropertiesAndContextForChildren) instead of needing LayoutView- 114 // updatePropertiesAndContextForChildren) instead of needing LayoutView-
109 // specific property updates here. 115 // specific property updates here.
110 context.current.paintOffset.moveBy(frameView.location()); 116 context.current.paintOffset.moveBy(frameView.location());
111 context.current.renderingContextID = 0; 117 context.current.renderingContextID = 0;
112 context.current.shouldFlattenInheritedTransform = true; 118 context.current.shouldFlattenInheritedTransform = true;
113 context.absolutePosition = context.current; 119 context.absolutePosition = context.current;
114 context.containerForAbsolutePosition = nullptr; 120 context.containerForAbsolutePosition = nullptr;
115 context.fixedPosition = context.current; 121 context.fixedPosition = context.current;
116 return; 122 return;
117 } 123 }
118 124
119 #if DCHECK_IS_ON() 125 #if DCHECK_IS_ON()
120 FindFrameViewPropertiesNeedingUpdateScope checkNeedsUpdateScope(&frameView); 126 FindFrameViewPropertiesNeedingUpdateScope checkScope(&frameView, context);
121 #endif 127 #endif
122 128
123 if (frameView.needsPaintPropertyUpdate()) { 129 if (frameView.needsPaintPropertyUpdate() || context.forceSubtreeUpdate) {
124 TransformationMatrix frameTranslate; 130 TransformationMatrix frameTranslate;
125 frameTranslate.translate(frameView.x() + context.current.paintOffset.x(), 131 frameTranslate.translate(frameView.x() + context.current.paintOffset.x(),
126 frameView.y() + context.current.paintOffset.y()); 132 frameView.y() + context.current.paintOffset.y());
127 updateFrameViewPreTranslation(frameView, context.current.transform, 133 context.forceSubtreeUpdate |= updatePreTranslation(
128 frameTranslate, FloatPoint3D()); 134 frameView, context.current.transform, frameTranslate, FloatPoint3D());
129 135
130 FloatRoundedRect contentClip( 136 FloatRoundedRect contentClip(
131 IntRect(IntPoint(), frameView.visibleContentSize())); 137 IntRect(IntPoint(), frameView.visibleContentSize()));
132 updateFrameViewContentClip(frameView, context.current.clip, 138 context.forceSubtreeUpdate |=
133 frameView.preTranslation(), contentClip); 139 updateContentClip(frameView, context.current.clip,
140 frameView.preTranslation(), contentClip);
134 141
135 ScrollOffset scrollOffset = frameView.scrollOffset(); 142 ScrollOffset scrollOffset = frameView.scrollOffset();
136 if (frameView.isScrollable() || !scrollOffset.isZero()) { 143 if (frameView.isScrollable() || !scrollOffset.isZero()) {
137 TransformationMatrix frameScroll; 144 TransformationMatrix frameScroll;
138 frameScroll.translate(-scrollOffset.width(), -scrollOffset.height()); 145 frameScroll.translate(-scrollOffset.width(), -scrollOffset.height());
139 updateFrameViewScrollTranslation(frameView, frameView.preTranslation(), 146 context.forceSubtreeUpdate |= updateScrollTranslation(
140 frameScroll, FloatPoint3D()); 147 frameView, frameView.preTranslation(), frameScroll, FloatPoint3D());
141 148
142 IntSize scrollClip = frameView.visibleContentSize(); 149 IntSize scrollClip = frameView.visibleContentSize();
143 IntSize scrollBounds = frameView.contentsSize(); 150 IntSize scrollBounds = frameView.contentsSize();
144 bool userScrollableHorizontal = 151 bool userScrollableHorizontal =
145 frameView.userInputScrollable(HorizontalScrollbar); 152 frameView.userInputScrollable(HorizontalScrollbar);
146 bool userScrollableVertical = 153 bool userScrollableVertical =
147 frameView.userInputScrollable(VerticalScrollbar); 154 frameView.userInputScrollable(VerticalScrollbar);
148 155
149 MainThreadScrollingReasons reasons = 0; 156 MainThreadScrollingReasons reasons = 0;
150 if (!frameView.frame().settings()->threadedScrollingEnabled()) 157 if (!frameView.frame().settings()->threadedScrollingEnabled())
151 reasons |= MainThreadScrollingReason::kThreadedScrollingDisabled; 158 reasons |= MainThreadScrollingReason::kThreadedScrollingDisabled;
152 if (frameView.hasBackgroundAttachmentFixedObjects()) { 159 if (frameView.hasBackgroundAttachmentFixedObjects()) {
153 reasons |= 160 reasons |=
154 MainThreadScrollingReason::kHasBackgroundAttachmentFixedObjects; 161 MainThreadScrollingReason::kHasBackgroundAttachmentFixedObjects;
155 } 162 }
156 updateFrameViewScroll(frameView, context.current.scroll, 163 context.forceSubtreeUpdate |= updateScroll(
157 frameView.scrollTranslation(), scrollClip, 164 frameView, context.current.scroll, frameView.scrollTranslation(),
158 scrollBounds, userScrollableHorizontal, 165 scrollClip, scrollBounds, userScrollableHorizontal,
159 userScrollableVertical, reasons); 166 userScrollableVertical, reasons);
160 } else { 167 } else {
161 // Ensure pre-existing properties are cleared when there is no scrolling. 168 if (frameView.scrollTranslation() || frameView.scroll()) {
162 frameView.setScrollTranslation(nullptr); 169 // Ensure pre-existing properties are cleared if there is no scrolling.
163 frameView.setScroll(nullptr); 170 frameView.setScrollTranslation(nullptr);
171 frameView.setScroll(nullptr);
172
173 // Rebuild all descendant properties because a property was removed.
174 context.forceSubtreeUpdate = true;
175 }
164 } 176 }
165 } 177 }
166 178
167 // Initialize the context for current, absolute and fixed position cases. 179 // Initialize the context for current, absolute and fixed position cases.
168 // They are the same, except that scroll translation does not apply to 180 // They are the same, except that scroll translation does not apply to
169 // fixed position descendants. 181 // fixed position descendants.
170 const auto* fixedTransformNode = frameView.preTranslation() 182 const auto* fixedTransformNode = frameView.preTranslation()
171 ? frameView.preTranslation() 183 ? frameView.preTranslation()
172 : context.current.transform; 184 : context.current.transform;
173 auto* fixedScrollNode = context.current.scroll; 185 auto* fixedScrollNode = context.current.scroll;
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
215 // regardless of whether a transform is present. If there is a transform 227 // regardless of whether a transform is present. If there is a transform
216 // we round the paint offset but keep around the residual fractional 228 // we round the paint offset but keep around the residual fractional
217 // component for the transformed content to paint with. In spv1 this was 229 // component for the transformed content to paint with. In spv1 this was
218 // called "subpixel accumulation". For more information, see 230 // called "subpixel accumulation". For more information, see
219 // PaintLayer::subpixelAccumulation() and 231 // PaintLayer::subpixelAccumulation() and
220 // PaintLayerPainter::paintFragmentByApplyingTransform. 232 // PaintLayerPainter::paintFragmentByApplyingTransform.
221 IntPoint roundedPaintOffset = roundedIntPoint(context.current.paintOffset); 233 IntPoint roundedPaintOffset = roundedIntPoint(context.current.paintOffset);
222 LayoutPoint fractionalPaintOffset = 234 LayoutPoint fractionalPaintOffset =
223 LayoutPoint(context.current.paintOffset - roundedPaintOffset); 235 LayoutPoint(context.current.paintOffset - roundedPaintOffset);
224 236
225 if (object.needsPaintPropertyUpdate()) { 237 if (object.needsPaintPropertyUpdate() || context.forceSubtreeUpdate) {
226 if (usesPaintOffsetTranslation) { 238 if (usesPaintOffsetTranslation) {
227 object.getMutableForPainting() 239 auto& properties = object.getMutableForPainting().ensurePaintProperties();
228 .ensurePaintProperties() 240 context.forceSubtreeUpdate |= properties.updatePaintOffsetTranslation(
229 .updatePaintOffsetTranslation( 241 context.current.transform,
230 context.current.transform, 242 TransformationMatrix().translate(roundedPaintOffset.x(),
231 TransformationMatrix().translate(roundedPaintOffset.x(), 243 roundedPaintOffset.y()),
232 roundedPaintOffset.y()), 244 FloatPoint3D(), context.current.shouldFlattenInheritedTransform,
233 FloatPoint3D(), context.current.shouldFlattenInheritedTransform, 245 context.current.renderingContextID);
234 context.current.renderingContextID);
235 } else { 246 } else {
236 if (auto* properties = object.getMutableForPainting().paintProperties()) 247 if (auto* properties = object.getMutableForPainting().paintProperties())
237 properties->clearPaintOffsetTranslation(); 248 context.forceSubtreeUpdate |= properties->clearPaintOffsetTranslation();
238 } 249 }
239 } 250 }
240 251
241 const auto* properties = object.paintProperties(); 252 const auto* properties = object.paintProperties();
242 if (properties && properties->paintOffsetTranslation()) { 253 if (properties && properties->paintOffsetTranslation()) {
243 context.current.transform = properties->paintOffsetTranslation(); 254 context.current.transform = properties->paintOffsetTranslation();
244 context.current.paintOffset = fractionalPaintOffset; 255 context.current.paintOffset = fractionalPaintOffset;
245 if (RuntimeEnabledFeatures::rootLayerScrollingEnabled() && 256 if (RuntimeEnabledFeatures::rootLayerScrollingEnabled() &&
246 object.isLayoutView()) { 257 object.isLayoutView()) {
247 context.absolutePosition.transform = properties->paintOffsetTranslation(); 258 context.absolutePosition.transform = properties->paintOffsetTranslation();
(...skipping 17 matching lines...) Expand all
265 // creating a transform node for SVG-specific transforms without 3D. 276 // creating a transform node for SVG-specific transforms without 3D.
266 void PaintPropertyTreeBuilder::updateTransformForNonRootSVG( 277 void PaintPropertyTreeBuilder::updateTransformForNonRootSVG(
267 const LayoutObject& object, 278 const LayoutObject& object,
268 PaintPropertyTreeBuilderContext& context) { 279 PaintPropertyTreeBuilderContext& context) {
269 DCHECK(object.isSVG() && !object.isSVGRoot()); 280 DCHECK(object.isSVG() && !object.isSVGRoot());
270 // SVG does not use paint offset internally, except for SVGForeignObject which 281 // SVG does not use paint offset internally, except for SVGForeignObject which
271 // has different SVG and HTML coordinate spaces. 282 // has different SVG and HTML coordinate spaces.
272 DCHECK(object.isSVGForeignObject() || 283 DCHECK(object.isSVGForeignObject() ||
273 context.current.paintOffset == LayoutPoint()); 284 context.current.paintOffset == LayoutPoint());
274 285
275 if (object.needsPaintPropertyUpdate()) { 286 if (object.needsPaintPropertyUpdate() || context.forceSubtreeUpdate) {
276 AffineTransform transform = object.localToSVGParentTransform(); 287 AffineTransform transform = object.localToSVGParentTransform();
277 // TODO(pdr): Check for the presence of a transform instead of the value. 288 // TODO(pdr): Check for the presence of a transform instead of the value.
278 // Checking for an identity matrix will cause the property tree structure 289 // Checking for an identity matrix will cause the property tree structure
279 // to change during animations if the animation passes through the 290 // to change during animations if the animation passes through the
280 // identity matrix. 291 // identity matrix.
281 if (!transform.isIdentity()) { 292 if (!transform.isIdentity()) {
282 // The origin is included in the local transform, so leave origin empty. 293 // The origin is included in the local transform, so leave origin empty.
283 object.getMutableForPainting().ensurePaintProperties().updateTransform( 294 auto& properties = object.getMutableForPainting().ensurePaintProperties();
295 context.forceSubtreeUpdate |= properties.updateTransform(
284 context.current.transform, TransformationMatrix(transform), 296 context.current.transform, TransformationMatrix(transform),
285 FloatPoint3D()); 297 FloatPoint3D());
286 } else { 298 } else {
287 if (auto* properties = object.getMutableForPainting().paintProperties()) 299 if (auto* properties = object.getMutableForPainting().paintProperties())
288 properties->clearTransform(); 300 context.forceSubtreeUpdate |= properties->clearTransform();
289 } 301 }
290 } 302 }
291 303
292 if (object.paintProperties() && object.paintProperties()->transform()) { 304 if (object.paintProperties() && object.paintProperties()->transform()) {
293 context.current.transform = object.paintProperties()->transform(); 305 context.current.transform = object.paintProperties()->transform();
294 context.current.shouldFlattenInheritedTransform = false; 306 context.current.shouldFlattenInheritedTransform = false;
295 context.current.renderingContextID = 0; 307 context.current.renderingContextID = 0;
296 } 308 }
297 } 309 }
298 310
299 void PaintPropertyTreeBuilder::updateTransform( 311 void PaintPropertyTreeBuilder::updateTransform(
300 const LayoutObject& object, 312 const LayoutObject& object,
301 PaintPropertyTreeBuilderContext& context) { 313 PaintPropertyTreeBuilderContext& context) {
302 if (object.isSVG() && !object.isSVGRoot()) { 314 if (object.isSVG() && !object.isSVGRoot()) {
303 updateTransformForNonRootSVG(object, context); 315 updateTransformForNonRootSVG(object, context);
304 return; 316 return;
305 } 317 }
306 318
307 if (object.needsPaintPropertyUpdate()) { 319 if (object.needsPaintPropertyUpdate() || context.forceSubtreeUpdate) {
308 const ComputedStyle& style = object.styleRef(); 320 const ComputedStyle& style = object.styleRef();
309 if (object.isBox() && (style.hasTransform() || style.preserves3D())) { 321 if (object.isBox() && (style.hasTransform() || style.preserves3D())) {
310 TransformationMatrix matrix; 322 TransformationMatrix matrix;
311 style.applyTransform( 323 style.applyTransform(
312 matrix, toLayoutBox(object).size(), 324 matrix, toLayoutBox(object).size(),
313 ComputedStyle::ExcludeTransformOrigin, 325 ComputedStyle::ExcludeTransformOrigin,
314 ComputedStyle::IncludeMotionPath, 326 ComputedStyle::IncludeMotionPath,
315 ComputedStyle::IncludeIndependentTransformProperties); 327 ComputedStyle::IncludeIndependentTransformProperties);
316 328
317 // TODO(trchen): transform-style should only be respected if a PaintLayer 329 // TODO(trchen): transform-style should only be respected if a PaintLayer
318 // is created. 330 // is created.
319 // If a node with transform-style: preserve-3d does not exist in an 331 // If a node with transform-style: preserve-3d does not exist in an
320 // existing rendering context, it establishes a new one. 332 // existing rendering context, it establishes a new one.
321 unsigned renderingContextID = context.current.renderingContextID; 333 unsigned renderingContextID = context.current.renderingContextID;
322 if (style.preserves3D() && !renderingContextID) 334 if (style.preserves3D() && !renderingContextID)
323 renderingContextID = PtrHash<const LayoutObject>::hash(&object); 335 renderingContextID = PtrHash<const LayoutObject>::hash(&object);
324 336
325 object.getMutableForPainting().ensurePaintProperties().updateTransform( 337 auto& properties = object.getMutableForPainting().ensurePaintProperties();
338 context.forceSubtreeUpdate |= properties.updateTransform(
326 context.current.transform, matrix, 339 context.current.transform, matrix,
327 transformOrigin(toLayoutBox(object)), 340 transformOrigin(toLayoutBox(object)),
328 context.current.shouldFlattenInheritedTransform, renderingContextID); 341 context.current.shouldFlattenInheritedTransform, renderingContextID);
329 } else { 342 } else {
330 if (auto* properties = object.getMutableForPainting().paintProperties()) 343 if (auto* properties = object.getMutableForPainting().paintProperties())
331 properties->clearTransform(); 344 context.forceSubtreeUpdate |= properties->clearTransform();
332 } 345 }
333 } 346 }
334 347
335 const auto* properties = object.paintProperties(); 348 const auto* properties = object.paintProperties();
336 if (properties && properties->transform()) { 349 if (properties && properties->transform()) {
337 context.current.transform = properties->transform(); 350 context.current.transform = properties->transform();
338 if (object.styleRef().preserves3D()) { 351 if (object.styleRef().preserves3D()) {
339 context.current.renderingContextID = 352 context.current.renderingContextID =
340 properties->transform()->renderingContextID(); 353 properties->transform()->renderingContextID();
341 context.current.shouldFlattenInheritedTransform = false; 354 context.current.shouldFlattenInheritedTransform = false;
342 } else { 355 } else {
343 context.current.renderingContextID = 0; 356 context.current.renderingContextID = 0;
344 context.current.shouldFlattenInheritedTransform = true; 357 context.current.shouldFlattenInheritedTransform = true;
345 } 358 }
346 } 359 }
347 } 360 }
348 361
349 void PaintPropertyTreeBuilder::updateEffect( 362 void PaintPropertyTreeBuilder::updateEffect(
350 const LayoutObject& object, 363 const LayoutObject& object,
351 PaintPropertyTreeBuilderContext& context) { 364 PaintPropertyTreeBuilderContext& context) {
352 const ComputedStyle& style = object.styleRef(); 365 const ComputedStyle& style = object.styleRef();
353 366
354 if (!style.isStackingContext()) { 367 if (!style.isStackingContext()) {
355 if (object.needsPaintPropertyUpdate()) { 368 if (object.needsPaintPropertyUpdate() || context.forceSubtreeUpdate) {
356 if (auto* properties = object.getMutableForPainting().paintProperties()) 369 if (auto* properties = object.getMutableForPainting().paintProperties())
357 properties->clearEffect(); 370 context.forceSubtreeUpdate |= properties->clearEffect();
358 } 371 }
359 return; 372 return;
360 } 373 }
361 374
362 // TODO(trchen): Can't omit effect node if we have 3D children. 375 // TODO(trchen): Can't omit effect node if we have 3D children.
363 // TODO(trchen): Can't omit effect node if we have blending children. 376 // TODO(trchen): Can't omit effect node if we have blending children.
364 if (object.needsPaintPropertyUpdate()) { 377 if (object.needsPaintPropertyUpdate() || context.forceSubtreeUpdate) {
365 bool effectNodeNeeded = false; 378 bool effectNodeNeeded = false;
366 379
367 float opacity = style.opacity(); 380 float opacity = style.opacity();
368 if (opacity != 1.0f) 381 if (opacity != 1.0f)
369 effectNodeNeeded = true; 382 effectNodeNeeded = true;
370 383
371 CompositorFilterOperations filter; 384 CompositorFilterOperations filter;
372 if (object.isSVG() && !object.isSVGRoot()) { 385 if (object.isSVG() && !object.isSVGRoot()) {
373 // TODO(trchen): SVG caches filters in SVGResources. Implement it. 386 // TODO(trchen): SVG caches filters in SVGResources. Implement it.
374 } else if (PaintLayer* layer = toLayoutBoxModelObject(object).layer()) { 387 } else if (PaintLayer* layer = toLayoutBoxModelObject(object).layer()) {
(...skipping 23 matching lines...) Expand all
398 if (!filter.isEmpty()) { 411 if (!filter.isEmpty()) {
399 effectNodeNeeded = true; 412 effectNodeNeeded = true;
400 outputClip = context.current.clip; 413 outputClip = context.current.clip;
401 414
402 // TODO(trchen): A filter may contain spatial operations such that an 415 // TODO(trchen): A filter may contain spatial operations such that an
403 // output pixel may depend on an input pixel outside of the output clip. 416 // output pixel may depend on an input pixel outside of the output clip.
404 // We should generate a special clip node to represent this expansion. 417 // We should generate a special clip node to represent this expansion.
405 } 418 }
406 419
407 if (effectNodeNeeded) { 420 if (effectNodeNeeded) {
408 object.getMutableForPainting().ensurePaintProperties().updateEffect( 421 auto& properties = object.getMutableForPainting().ensurePaintProperties();
422 context.forceSubtreeUpdate |= properties.updateEffect(
409 context.currentEffect, context.current.transform, outputClip, 423 context.currentEffect, context.current.transform, outputClip,
410 std::move(filter), opacity); 424 std::move(filter), opacity);
411 } else { 425 } else {
412 if (auto* properties = object.getMutableForPainting().paintProperties()) 426 if (auto* properties = object.getMutableForPainting().paintProperties())
413 properties->clearEffect(); 427 context.forceSubtreeUpdate |= properties->clearEffect();
414 } 428 }
415 } 429 }
416 430
417 const auto* properties = object.paintProperties(); 431 const auto* properties = object.paintProperties();
418 if (properties && properties->effect()) { 432 if (properties && properties->effect()) {
419 context.currentEffect = properties->effect(); 433 context.currentEffect = properties->effect();
420 if (!properties->effect()->filter().isEmpty()) { 434 if (!properties->effect()->filter().isEmpty()) {
421 // TODO(trchen): Change input clip to expansion hint once implemented. 435 // TODO(trchen): Change input clip to expansion hint once implemented.
422 const ClipPaintPropertyNode* inputClip = 436 const ClipPaintPropertyNode* inputClip =
423 properties->effect()->outputClip(); 437 properties->effect()->outputClip();
424 context.inputClipOfCurrentEffect = context.current.clip = 438 context.inputClipOfCurrentEffect = context.current.clip =
425 context.absolutePosition.clip = context.fixedPosition.clip = 439 context.absolutePosition.clip = context.fixedPosition.clip =
426 inputClip; 440 inputClip;
427 } 441 }
428 } 442 }
429 } 443 }
430 444
431 void PaintPropertyTreeBuilder::updateCssClip( 445 void PaintPropertyTreeBuilder::updateCssClip(
432 const LayoutObject& object, 446 const LayoutObject& object,
433 PaintPropertyTreeBuilderContext& context) { 447 PaintPropertyTreeBuilderContext& context) {
434 if (object.needsPaintPropertyUpdate()) { 448 if (object.needsPaintPropertyUpdate() || context.forceSubtreeUpdate) {
435 if (object.hasClip()) { 449 if (object.hasClip()) {
436 // Create clip node for descendants that are not fixed position. 450 // Create clip node for descendants that are not fixed position.
437 // We don't have to setup context.absolutePosition.clip here because this 451 // We don't have to setup context.absolutePosition.clip here because this
438 // object must be a container for absolute position descendants, and will 452 // object must be a container for absolute position descendants, and will
439 // copy from in-flow context later at updateOutOfFlowContext() step. 453 // copy from in-flow context later at updateOutOfFlowContext() step.
440 DCHECK(object.canContainAbsolutePositionObjects()); 454 DCHECK(object.canContainAbsolutePositionObjects());
441 LayoutRect clipRect = 455 LayoutRect clipRect =
442 toLayoutBox(object).clipRect(context.current.paintOffset); 456 toLayoutBox(object).clipRect(context.current.paintOffset);
443 object.getMutableForPainting().ensurePaintProperties().updateCssClip( 457 auto& properties = object.getMutableForPainting().ensurePaintProperties();
458 context.forceSubtreeUpdate |= properties.updateCssClip(
444 context.current.clip, context.current.transform, 459 context.current.clip, context.current.transform,
445 FloatRoundedRect(FloatRect(clipRect))); 460 FloatRoundedRect(FloatRect(clipRect)));
446 } else { 461 } else {
447 if (auto* properties = object.getMutableForPainting().paintProperties()) 462 if (auto* properties = object.getMutableForPainting().paintProperties())
448 properties->clearCssClip(); 463 context.forceSubtreeUpdate |= properties->clearCssClip();
449 } 464 }
450 } 465 }
451 466
452 const auto* properties = object.paintProperties(); 467 const auto* properties = object.paintProperties();
453 if (properties && properties->cssClip()) 468 if (properties && properties->cssClip())
454 context.current.clip = properties->cssClip(); 469 context.current.clip = properties->cssClip();
455 } 470 }
456 471
457 void PaintPropertyTreeBuilder::updateLocalBorderBoxContext( 472 void PaintPropertyTreeBuilder::updateLocalBorderBoxContext(
458 const LayoutObject& object, 473 const LayoutObject& object,
459 PaintPropertyTreeBuilderContext& context) { 474 PaintPropertyTreeBuilderContext& context) {
460 if (!object.needsPaintPropertyUpdate()) 475 if (!object.needsPaintPropertyUpdate() && !context.forceSubtreeUpdate)
461 return; 476 return;
462 477
463 // Avoid adding an ObjectPaintProperties for non-boxes to save memory, since 478 // Avoid adding an ObjectPaintProperties for non-boxes to save memory, since
464 // we don't need them at the moment. 479 // we don't need them at the moment.
465 if (!object.isBox() && !object.hasLayer()) { 480 if (!object.isBox() && !object.hasLayer()) {
466 if (auto* properties = object.getMutableForPainting().paintProperties()) 481 if (auto* properties = object.getMutableForPainting().paintProperties())
467 properties->clearLocalBorderBoxProperties(); 482 properties->clearLocalBorderBoxProperties();
468 } else { 483 } else {
469 auto& properties = object.getMutableForPainting().ensurePaintProperties(); 484 auto& properties = object.getMutableForPainting().ensurePaintProperties();
470 properties.updateLocalBorderBoxProperties( 485 properties.updateLocalBorderBoxProperties(
471 context.current.paintOffset, context.current.transform, 486 context.current.paintOffset, context.current.transform,
472 context.current.clip, context.currentEffect, context.current.scroll); 487 context.current.clip, context.currentEffect, context.current.scroll);
473 } 488 }
474 } 489 }
475 490
476 // TODO(trchen): Remove this once we bake the paint offset into frameRect. 491 // TODO(trchen): Remove this once we bake the paint offset into frameRect.
477 void PaintPropertyTreeBuilder::updateScrollbarPaintOffset( 492 void PaintPropertyTreeBuilder::updateScrollbarPaintOffset(
478 const LayoutObject& object, 493 const LayoutObject& object,
479 const PaintPropertyTreeBuilderContext& context) { 494 PaintPropertyTreeBuilderContext& context) {
480 if (!object.needsPaintPropertyUpdate()) 495 if (!object.needsPaintPropertyUpdate() && !context.forceSubtreeUpdate)
481 return; 496 return;
482 497
483 bool needsScrollbarPaintOffset = false; 498 bool needsScrollbarPaintOffset = false;
484 IntPoint roundedPaintOffset = roundedIntPoint(context.current.paintOffset); 499 IntPoint roundedPaintOffset = roundedIntPoint(context.current.paintOffset);
485 if (roundedPaintOffset != IntPoint() && object.isBoxModelObject()) { 500 if (roundedPaintOffset != IntPoint() && object.isBoxModelObject()) {
486 if (auto* area = toLayoutBoxModelObject(object).getScrollableArea()) { 501 if (auto* area = toLayoutBoxModelObject(object).getScrollableArea()) {
487 if (area->horizontalScrollbar() || area->verticalScrollbar()) { 502 if (area->horizontalScrollbar() || area->verticalScrollbar()) {
488 auto paintOffset = TransformationMatrix().translate( 503 auto paintOffset = TransformationMatrix().translate(
489 roundedPaintOffset.x(), roundedPaintOffset.y()); 504 roundedPaintOffset.x(), roundedPaintOffset.y());
490 object.getMutableForPainting() 505 auto& properties =
491 .ensurePaintProperties() 506 object.getMutableForPainting().ensurePaintProperties();
492 .updateScrollbarPaintOffset(context.current.transform, paintOffset, 507 context.forceSubtreeUpdate |= properties.updateScrollbarPaintOffset(
493 FloatPoint3D()); 508 context.current.transform, paintOffset, FloatPoint3D());
494 needsScrollbarPaintOffset = true; 509 needsScrollbarPaintOffset = true;
495 } 510 }
496 } 511 }
497 } 512 }
498 513
499 auto* properties = object.getMutableForPainting().paintProperties(); 514 auto* properties = object.getMutableForPainting().paintProperties();
500 if (!needsScrollbarPaintOffset && properties) 515 if (!needsScrollbarPaintOffset && properties)
501 properties->clearScrollbarPaintOffset(); 516 context.forceSubtreeUpdate |= properties->clearScrollbarPaintOffset();
502 } 517 }
503 518
504 void PaintPropertyTreeBuilder::updateOverflowClip( 519 void PaintPropertyTreeBuilder::updateOverflowClip(
505 const LayoutObject& object, 520 const LayoutObject& object,
506 PaintPropertyTreeBuilderContext& context) { 521 PaintPropertyTreeBuilderContext& context) {
507 if (!object.isBox()) 522 if (!object.isBox())
508 return; 523 return;
509 524
510 if (object.needsPaintPropertyUpdate()) { 525 if (object.needsPaintPropertyUpdate() || context.forceSubtreeUpdate) {
511 const LayoutBox& box = toLayoutBox(object); 526 const LayoutBox& box = toLayoutBox(object);
512 // The <input> elements can't have contents thus CSS overflow property 527 // The <input> elements can't have contents thus CSS overflow property
513 // doesn't apply. However for layout purposes we do generate child layout 528 // doesn't apply. However for layout purposes we do generate child layout
514 // objects for them, e.g. button label. We should clip the overflow from 529 // objects for them, e.g. button label. We should clip the overflow from
515 // those children. This is called control clip and we technically treat them 530 // those children. This is called control clip and we technically treat them
516 // like overflow clip. 531 // like overflow clip.
517 LayoutRect clipRect; 532 LayoutRect clipRect;
518 if (box.hasControlClip()) { 533 if (box.hasControlClip()) {
519 clipRect = box.controlClipRect(context.current.paintOffset); 534 clipRect = box.controlClipRect(context.current.paintOffset);
520 } else if (box.hasOverflowClip() || box.styleRef().containsPaint() || 535 } else if (box.hasOverflowClip() || box.styleRef().containsPaint() ||
521 (box.isSVGRoot() && 536 (box.isSVGRoot() &&
522 toLayoutSVGRoot(box).shouldApplyViewportClip())) { 537 toLayoutSVGRoot(box).shouldApplyViewportClip())) {
523 clipRect = LayoutRect(pixelSnappedIntRect( 538 clipRect = LayoutRect(pixelSnappedIntRect(
524 box.overflowClipRect(context.current.paintOffset))); 539 box.overflowClipRect(context.current.paintOffset)));
525 } else { 540 } else {
526 if (auto* properties = object.getMutableForPainting().paintProperties()) { 541 if (auto* properties = object.getMutableForPainting().paintProperties()) {
527 properties->clearInnerBorderRadiusClip(); 542 context.forceSubtreeUpdate |= properties->clearInnerBorderRadiusClip();
528 properties->clearOverflowClip(); 543 context.forceSubtreeUpdate |= properties->clearOverflowClip();
529 } 544 }
530 return; 545 return;
531 } 546 }
532 547
548 auto& properties = object.getMutableForPainting().ensurePaintProperties();
533 const auto* currentClip = context.current.clip; 549 const auto* currentClip = context.current.clip;
534 if (box.styleRef().hasBorderRadius()) { 550 if (box.styleRef().hasBorderRadius()) {
535 auto innerBorder = box.styleRef().getRoundedInnerBorderFor( 551 auto innerBorder = box.styleRef().getRoundedInnerBorderFor(
536 LayoutRect(context.current.paintOffset, box.size())); 552 LayoutRect(context.current.paintOffset, box.size()));
537 object.getMutableForPainting() 553 context.forceSubtreeUpdate |= properties.updateInnerBorderRadiusClip(
538 .ensurePaintProperties() 554 context.current.clip, context.current.transform, innerBorder);
539 .updateInnerBorderRadiusClip(context.current.clip, 555 currentClip = properties.innerBorderRadiusClip();
540 context.current.transform, innerBorder); 556 } else {
541 currentClip = object.paintProperties()->innerBorderRadiusClip(); 557 context.forceSubtreeUpdate |= properties.clearInnerBorderRadiusClip();
542 } else if (auto* properties =
543 object.getMutableForPainting().paintProperties()) {
544 properties->clearInnerBorderRadiusClip();
545 } 558 }
546 559
547 object.getMutableForPainting().ensurePaintProperties().updateOverflowClip( 560 context.forceSubtreeUpdate |=
548 currentClip, context.current.transform, 561 properties.updateOverflowClip(currentClip, context.current.transform,
549 FloatRoundedRect(FloatRect(clipRect))); 562 FloatRoundedRect(FloatRect(clipRect)));
550 } 563 }
551 564
552 const auto* properties = object.paintProperties(); 565 const auto* properties = object.paintProperties();
553 if (properties && properties->overflowClip()) 566 if (properties && properties->overflowClip())
554 context.current.clip = properties->overflowClip(); 567 context.current.clip = properties->overflowClip();
555 } 568 }
556 569
557 static FloatPoint perspectiveOrigin(const LayoutBox& box) { 570 static FloatPoint perspectiveOrigin(const LayoutBox& box) {
558 const ComputedStyle& style = box.styleRef(); 571 const ComputedStyle& style = box.styleRef();
559 FloatSize borderBoxSize(box.size()); 572 FloatSize borderBoxSize(box.size());
560 return FloatPoint( 573 return FloatPoint(
561 floatValueForLength(style.perspectiveOriginX(), borderBoxSize.width()), 574 floatValueForLength(style.perspectiveOriginX(), borderBoxSize.width()),
562 floatValueForLength(style.perspectiveOriginY(), borderBoxSize.height())); 575 floatValueForLength(style.perspectiveOriginY(), borderBoxSize.height()));
563 } 576 }
564 577
565 void PaintPropertyTreeBuilder::updatePerspective( 578 void PaintPropertyTreeBuilder::updatePerspective(
566 const LayoutObject& object, 579 const LayoutObject& object,
567 PaintPropertyTreeBuilderContext& context) { 580 PaintPropertyTreeBuilderContext& context) {
568 if (object.needsPaintPropertyUpdate()) { 581 if (object.needsPaintPropertyUpdate() || context.forceSubtreeUpdate) {
569 const ComputedStyle& style = object.styleRef(); 582 const ComputedStyle& style = object.styleRef();
570 if (object.isBox() && style.hasPerspective()) { 583 if (object.isBox() && style.hasPerspective()) {
571 // The perspective node must not flatten (else nothing will get 584 // The perspective node must not flatten (else nothing will get
572 // perspective), but it should still extend the rendering context as 585 // perspective), but it should still extend the rendering context as
573 // most transform nodes do. 586 // most transform nodes do.
574 TransformationMatrix matrix = 587 TransformationMatrix matrix =
575 TransformationMatrix().applyPerspective(style.perspective()); 588 TransformationMatrix().applyPerspective(style.perspective());
576 FloatPoint3D origin = perspectiveOrigin(toLayoutBox(object)) + 589 FloatPoint3D origin = perspectiveOrigin(toLayoutBox(object)) +
577 toLayoutSize(context.current.paintOffset); 590 toLayoutSize(context.current.paintOffset);
578 object.getMutableForPainting().ensurePaintProperties().updatePerspective( 591 auto& properties = object.getMutableForPainting().ensurePaintProperties();
592 context.forceSubtreeUpdate |= properties.updatePerspective(
579 context.current.transform, matrix, origin, 593 context.current.transform, matrix, origin,
580 context.current.shouldFlattenInheritedTransform, 594 context.current.shouldFlattenInheritedTransform,
581 context.current.renderingContextID); 595 context.current.renderingContextID);
582 } else { 596 } else {
583 if (auto* properties = object.getMutableForPainting().paintProperties()) 597 if (auto* properties = object.getMutableForPainting().paintProperties())
584 properties->clearPerspective(); 598 context.forceSubtreeUpdate |= properties->clearPerspective();
585 } 599 }
586 } 600 }
587 601
588 const auto* properties = object.paintProperties(); 602 const auto* properties = object.paintProperties();
589 if (properties && properties->perspective()) { 603 if (properties && properties->perspective()) {
590 context.current.transform = properties->perspective(); 604 context.current.transform = properties->perspective();
591 context.current.shouldFlattenInheritedTransform = false; 605 context.current.shouldFlattenInheritedTransform = false;
592 } 606 }
593 } 607 }
594 608
595 void PaintPropertyTreeBuilder::updateSvgLocalToBorderBoxTransform( 609 void PaintPropertyTreeBuilder::updateSvgLocalToBorderBoxTransform(
596 const LayoutObject& object, 610 const LayoutObject& object,
597 PaintPropertyTreeBuilderContext& context) { 611 PaintPropertyTreeBuilderContext& context) {
598 if (!object.isSVGRoot()) 612 if (!object.isSVGRoot())
599 return; 613 return;
600 614
601 if (object.needsPaintPropertyUpdate()) { 615 if (object.needsPaintPropertyUpdate() || context.forceSubtreeUpdate) {
602 AffineTransform transformToBorderBox = 616 AffineTransform transformToBorderBox =
603 SVGRootPainter(toLayoutSVGRoot(object)) 617 SVGRootPainter(toLayoutSVGRoot(object))
604 .transformToPixelSnappedBorderBox(context.current.paintOffset); 618 .transformToPixelSnappedBorderBox(context.current.paintOffset);
605 if (!transformToBorderBox.isIdentity()) { 619 if (!transformToBorderBox.isIdentity()) {
606 object.getMutableForPainting() 620 auto& properties = object.getMutableForPainting().ensurePaintProperties();
607 .ensurePaintProperties() 621 context.forceSubtreeUpdate |=
608 .updateSvgLocalToBorderBoxTransform( 622 properties.updateSvgLocalToBorderBoxTransform(
609 context.current.transform, transformToBorderBox, FloatPoint3D()); 623 context.current.transform, transformToBorderBox, FloatPoint3D());
610 } else { 624 } else {
611 if (auto* properties = object.getMutableForPainting().paintProperties()) 625 if (auto* properties = object.getMutableForPainting().paintProperties()) {
612 properties->clearSvgLocalToBorderBoxTransform(); 626 context.forceSubtreeUpdate |=
627 properties->clearSvgLocalToBorderBoxTransform();
628 }
613 } 629 }
614 } 630 }
615 631
616 const auto* properties = object.paintProperties(); 632 const auto* properties = object.paintProperties();
617 if (properties && properties->svgLocalToBorderBoxTransform()) { 633 if (properties && properties->svgLocalToBorderBoxTransform()) {
618 context.current.transform = properties->svgLocalToBorderBoxTransform(); 634 context.current.transform = properties->svgLocalToBorderBoxTransform();
619 context.current.shouldFlattenInheritedTransform = false; 635 context.current.shouldFlattenInheritedTransform = false;
620 context.current.renderingContextID = 0; 636 context.current.renderingContextID = 0;
621 } 637 }
622 // The paint offset is included in |transformToBorderBox| so SVG does not need 638 // The paint offset is included in |transformToBorderBox| so SVG does not need
623 // to handle paint offset internally. 639 // to handle paint offset internally.
624 context.current.paintOffset = LayoutPoint(); 640 context.current.paintOffset = LayoutPoint();
625 } 641 }
626 642
627 void PaintPropertyTreeBuilder::updateScrollAndScrollTranslation( 643 void PaintPropertyTreeBuilder::updateScrollAndScrollTranslation(
628 const LayoutObject& object, 644 const LayoutObject& object,
629 PaintPropertyTreeBuilderContext& context) { 645 PaintPropertyTreeBuilderContext& context) {
630 if (object.needsPaintPropertyUpdate()) { 646 if (object.needsPaintPropertyUpdate() || context.forceSubtreeUpdate) {
631 if (object.hasOverflowClip()) { 647 if (object.hasOverflowClip()) {
632 const LayoutBox& box = toLayoutBox(object); 648 const LayoutBox& box = toLayoutBox(object);
633 const PaintLayerScrollableArea* scrollableArea = box.getScrollableArea(); 649 const PaintLayerScrollableArea* scrollableArea = box.getScrollableArea();
634 IntSize scrollOffset = box.scrolledContentOffset(); 650 IntSize scrollOffset = box.scrolledContentOffset();
635 if (!scrollOffset.isZero() || scrollableArea->scrollsOverflow()) { 651 if (!scrollOffset.isZero() || scrollableArea->scrollsOverflow()) {
652 auto& properties =
653 object.getMutableForPainting().ensurePaintProperties();
636 TransformationMatrix matrix = TransformationMatrix().translate( 654 TransformationMatrix matrix = TransformationMatrix().translate(
637 -scrollOffset.width(), -scrollOffset.height()); 655 -scrollOffset.width(), -scrollOffset.height());
638 object.getMutableForPainting() 656 context.forceSubtreeUpdate |= properties.updateScrollTranslation(
639 .ensurePaintProperties() 657 context.current.transform, matrix, FloatPoint3D(),
640 .updateScrollTranslation( 658 context.current.shouldFlattenInheritedTransform,
641 context.current.transform, matrix, FloatPoint3D(), 659 context.current.renderingContextID);
642 context.current.shouldFlattenInheritedTransform,
643 context.current.renderingContextID);
644 660
645 IntSize scrollClip = scrollableArea->visibleContentRect().size(); 661 IntSize scrollClip = scrollableArea->visibleContentRect().size();
646 IntSize scrollBounds = scrollableArea->contentsSize(); 662 IntSize scrollBounds = scrollableArea->contentsSize();
647 bool userScrollableHorizontal = 663 bool userScrollableHorizontal =
648 scrollableArea->userInputScrollable(HorizontalScrollbar); 664 scrollableArea->userInputScrollable(HorizontalScrollbar);
649 bool userScrollableVertical = 665 bool userScrollableVertical =
650 scrollableArea->userInputScrollable(VerticalScrollbar); 666 scrollableArea->userInputScrollable(VerticalScrollbar);
651 MainThreadScrollingReasons reasons = 0; 667 MainThreadScrollingReasons reasons = 0;
652 if (!object.document().settings()->threadedScrollingEnabled()) 668 if (!object.document().settings()->threadedScrollingEnabled())
653 reasons |= MainThreadScrollingReason::kThreadedScrollingDisabled; 669 reasons |= MainThreadScrollingReason::kThreadedScrollingDisabled;
654 // Checking for descendants in the layout tree has two downsides: 670 // Checking for descendants in the layout tree has two downsides:
655 // 1) There can be more descendants in layout order than in paint 671 // 1) There can be more descendants in layout order than in paint
656 // order (e.g., fixed position objects). 672 // order (e.g., fixed position objects).
657 // 2) Iterating overall all background attachment fixed objects for 673 // 2) Iterating overall all background attachment fixed objects for
658 // every scroll node can be slow, though there will be no objects 674 // every scroll node can be slow, though there will be no objects
659 // in the common case. 675 // in the common case.
660 const FrameView& frameView = *object.frameView(); 676 const FrameView& frameView = *object.frameView();
661 if (frameView.hasBackgroundAttachmentFixedDescendants(object)) { 677 if (frameView.hasBackgroundAttachmentFixedDescendants(object)) {
662 reasons |= 678 reasons |=
663 MainThreadScrollingReason::kHasBackgroundAttachmentFixedObjects; 679 MainThreadScrollingReason::kHasBackgroundAttachmentFixedObjects;
664 } 680 }
665 object.getMutableForPainting().ensurePaintProperties().updateScroll( 681 context.forceSubtreeUpdate |= properties.updateScroll(
666 context.current.scroll, 682 context.current.scroll, properties.scrollTranslation(), scrollClip,
667 object.paintProperties()->scrollTranslation(), scrollClip,
668 scrollBounds, userScrollableHorizontal, userScrollableVertical, 683 scrollBounds, userScrollableHorizontal, userScrollableVertical,
669 reasons); 684 reasons);
670 } else { 685 } else {
671 // Ensure pre-existing properties are cleared when there is no 686 // Ensure pre-existing properties are cleared when there is no
672 // scrolling. 687 // scrolling.
673 auto* properties = object.getMutableForPainting().paintProperties(); 688 auto* properties = object.getMutableForPainting().paintProperties();
674 if (properties) { 689 if (properties) {
675 properties->clearScrollTranslation(); 690 context.forceSubtreeUpdate |= properties->clearScrollTranslation();
676 properties->clearScroll(); 691 context.forceSubtreeUpdate |= properties->clearScroll();
677 } 692 }
678 } 693 }
679 } 694 }
680 } 695 }
681 696
682 if (object.paintProperties() && object.paintProperties()->scroll()) { 697 if (object.paintProperties() && object.paintProperties()->scroll()) {
683 context.current.transform = object.paintProperties()->scrollTranslation(); 698 context.current.transform = object.paintProperties()->scrollTranslation();
684 context.current.scroll = object.paintProperties()->scroll(); 699 context.current.scroll = object.paintProperties()->scroll();
685 context.current.shouldFlattenInheritedTransform = false; 700 context.current.shouldFlattenInheritedTransform = false;
686 } 701 }
(...skipping 28 matching lines...) Expand all
715 // absolute position container. However for fixed-position descendants we 730 // absolute position container. However for fixed-position descendants we
716 // need to insert the clip here if we are not a containing block ancestor of 731 // need to insert the clip here if we are not a containing block ancestor of
717 // them. 732 // them.
718 auto* cssClip = object.getMutableForPainting().paintProperties()->cssClip(); 733 auto* cssClip = object.getMutableForPainting().paintProperties()->cssClip();
719 734
720 // Before we actually create anything, check whether in-flow context and 735 // Before we actually create anything, check whether in-flow context and
721 // fixed-position context has exactly the same clip. Reuse if possible. 736 // fixed-position context has exactly the same clip. Reuse if possible.
722 if (context.fixedPosition.clip == cssClip->parent()) { 737 if (context.fixedPosition.clip == cssClip->parent()) {
723 context.fixedPosition.clip = cssClip; 738 context.fixedPosition.clip = cssClip;
724 } else { 739 } else {
725 if (object.needsPaintPropertyUpdate()) { 740 if (object.needsPaintPropertyUpdate() || context.forceSubtreeUpdate) {
726 object.getMutableForPainting() 741 auto& properties =
727 .ensurePaintProperties() 742 object.getMutableForPainting().ensurePaintProperties();
728 .updateCssClipFixedPosition(context.fixedPosition.clip, 743 context.forceSubtreeUpdate |= properties.updateCssClipFixedPosition(
729 const_cast<TransformPaintPropertyNode*>( 744 context.fixedPosition.clip, const_cast<TransformPaintPropertyNode*>(
730 cssClip->localTransformSpace()), 745 cssClip->localTransformSpace()),
731 cssClip->clipRect()); 746 cssClip->clipRect());
732 } 747 }
733 const auto* properties = object.paintProperties(); 748 const auto* properties = object.paintProperties();
734 if (properties && properties->cssClipFixedPosition()) 749 if (properties && properties->cssClipFixedPosition())
735 context.fixedPosition.clip = properties->cssClipFixedPosition(); 750 context.fixedPosition.clip = properties->cssClipFixedPosition();
736 return; 751 return;
737 } 752 }
738 } 753 }
739 754
740 if (object.needsPaintPropertyUpdate()) { 755 if (object.needsPaintPropertyUpdate() || context.forceSubtreeUpdate) {
741 if (auto* properties = object.getMutableForPainting().paintProperties()) 756 if (auto* properties = object.getMutableForPainting().paintProperties())
742 properties->clearCssClipFixedPosition(); 757 context.forceSubtreeUpdate |= properties->clearCssClipFixedPosition();
743 } 758 }
744 } 759 }
745 760
746 // Override ContainingBlockContext based on the properties of a containing block 761 // Override ContainingBlockContext based on the properties of a containing block
747 // that was previously walked in a subtree other than the current subtree being 762 // that was previously walked in a subtree other than the current subtree being
748 // walked. Used for out-of-flow positioned descendants of multi-column spanner 763 // walked. Used for out-of-flow positioned descendants of multi-column spanner
749 // when the containing block is not in the normal tree walk order. 764 // when the containing block is not in the normal tree walk order.
750 // For example: 765 // For example:
751 // <div id="columns" style="columns: 2"> 766 // <div id="columns" style="columns: 2">
752 // <div id="relative" style="position: relative"> 767 // <div id="relative" style="position: relative">
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
859 } 874 }
860 } 875 }
861 876
862 void PaintPropertyTreeBuilder::updatePropertiesForSelf( 877 void PaintPropertyTreeBuilder::updatePropertiesForSelf(
863 const LayoutObject& object, 878 const LayoutObject& object,
864 PaintPropertyTreeBuilderContext& context) { 879 PaintPropertyTreeBuilderContext& context) {
865 if (!object.isBoxModelObject() && !object.isSVG()) 880 if (!object.isBoxModelObject() && !object.isSVG())
866 return; 881 return;
867 882
868 #if DCHECK_IS_ON() 883 #if DCHECK_IS_ON()
869 FindObjectPropertiesNeedingUpdateScope checkNeedsUpdateScope(object); 884 FindObjectPropertiesNeedingUpdateScope checkNeedsUpdateScope(object, context);
870 #endif 885 #endif
871 886
872 deriveBorderBoxFromContainerContext(object, context); 887 deriveBorderBoxFromContainerContext(object, context);
873 888
874 updatePaintOffsetTranslation(object, context); 889 updatePaintOffsetTranslation(object, context);
875 updateTransform(object, context); 890 updateTransform(object, context);
876 updateEffect(object, context); 891 updateEffect(object, context);
877 updateCssClip(object, context); 892 updateCssClip(object, context);
878 updateLocalBorderBoxContext(object, context); 893 updateLocalBorderBoxContext(object, context);
879 updateScrollbarPaintOffset(object, context); 894 updateScrollbarPaintOffset(object, context);
880 } 895 }
881 896
882 void PaintPropertyTreeBuilder::updatePropertiesForChildren( 897 void PaintPropertyTreeBuilder::updatePropertiesForChildren(
883 const LayoutObject& object, 898 const LayoutObject& object,
884 PaintPropertyTreeBuilderContext& context) { 899 PaintPropertyTreeBuilderContext& context) {
885 if (!object.isBoxModelObject() && !object.isSVG()) 900 if (!object.isBoxModelObject() && !object.isSVG())
886 return; 901 return;
887 902
888 #if DCHECK_IS_ON() 903 #if DCHECK_IS_ON()
889 FindObjectPropertiesNeedingUpdateScope checkNeedsUpdateScope(object); 904 FindObjectPropertiesNeedingUpdateScope checkNeedsUpdateScope(object, context);
890 #endif 905 #endif
891 906
892 updateOverflowClip(object, context); 907 updateOverflowClip(object, context);
893 updatePerspective(object, context); 908 updatePerspective(object, context);
894 updateSvgLocalToBorderBoxTransform(object, context); 909 updateSvgLocalToBorderBoxTransform(object, context);
895 updateScrollAndScrollTranslation(object, context); 910 updateScrollAndScrollTranslation(object, context);
896 updateOutOfFlowContext(object, context); 911 updateOutOfFlowContext(object, context);
897 } 912 }
898 913
899 } // namespace blink 914 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698