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

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

Issue 2404213004: Implement incremental paint property tree rebuilding (Closed)
Patch Set: Fix bug in how svg local to border box was updated, no longer crash in tests Created 4 years, 1 month 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/LayoutView.h" 12 #include "core/layout/LayoutView.h"
13 #include "core/layout/svg/LayoutSVGRoot.h" 13 #include "core/layout/svg/LayoutSVGRoot.h"
14 #include "core/paint/ObjectPaintProperties.h" 14 #include "core/paint/ObjectPaintProperties.h"
15 #include "core/paint/PaintLayer.h" 15 #include "core/paint/PaintLayer.h"
16 #include "core/paint/PaintPropertyUnderInvalidationChecks.h"
16 #include "core/paint/SVGRootPainter.h" 17 #include "core/paint/SVGRootPainter.h"
17 #include "platform/transforms/TransformationMatrix.h" 18 #include "platform/transforms/TransformationMatrix.h"
18 #include "wtf/PtrUtil.h" 19 #include "wtf/PtrUtil.h"
19 #include <memory> 20 #include <memory>
20 21
21 namespace blink { 22 namespace blink {
22 23
23 namespace { 24 namespace {
24 TransformPaintPropertyNode* rootTransformNode() { 25 TransformPaintPropertyNode* rootTransformNode() {
25 DEFINE_STATIC_REF(TransformPaintPropertyNode, rootTransform, 26 DEFINE_STATIC_REF(TransformPaintPropertyNode, rootTransform,
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
128 existingScroll->update(std::move(parent), std::move(scrollOffset), clip, 129 existingScroll->update(std::move(parent), std::move(scrollOffset), clip,
129 bounds, userScrollableHorizontal, 130 bounds, userScrollableHorizontal,
130 userScrollableVertical); 131 userScrollableVertical);
131 else 132 else
132 frameView.setScroll(ScrollPaintPropertyNode::create( 133 frameView.setScroll(ScrollPaintPropertyNode::create(
133 std::move(parent), std::move(scrollOffset), clip, bounds, 134 std::move(parent), std::move(scrollOffset), clip, bounds,
134 userScrollableHorizontal, userScrollableVertical)); 135 userScrollableHorizontal, userScrollableVertical));
135 return frameView.scroll(); 136 return frameView.scroll();
136 } 137 }
137 138
138 void PaintPropertyTreeBuilder::buildTreeNodes( 139 void PaintPropertyTreeBuilder::updateProperties(
139 FrameView& frameView, 140 FrameView& frameView,
140 PaintPropertyTreeBuilderContext& context) { 141 PaintPropertyTreeBuilderContext& context) {
141 if (RuntimeEnabledFeatures::rootLayerScrollingEnabled()) { 142 if (RuntimeEnabledFeatures::rootLayerScrollingEnabled()) {
142 LayoutView* layoutView = frameView.layoutView(); 143 LayoutView* layoutView = frameView.layoutView();
143 if (!layoutView) 144 if (!layoutView)
144 return; 145 return;
145 146
146 TransformationMatrix frameTranslate; 147 #ifndef NDEBUG
chrishtr 2016/10/21 22:03:09 #if DCHECK_IS_ON
pdr. 2016/10/26 03:10:48 Done
147 frameTranslate.translate(frameView.x() + layoutView->location().x() + 148 auto underInvalidationChecker =
148 context.current.paintOffset.x(), 149 ObjectUnderInvalidationCheckScope::createIfNeeded(*layoutView);
149 frameView.y() + layoutView->location().y() + 150 #endif
150 context.current.paintOffset.y()); 151
151 context.current.transform = 152 if (layoutView->paintPropertiesValid()) {
152 layoutView->getMutableForPainting() 153 // No invalidation so update the context using existing properties.
153 .ensurePaintProperties() 154 const auto* properties = layoutView->paintProperties();
154 .updatePaintOffsetTranslation(context.current.transform, 155 if (properties && properties->paintOffsetTranslation())
chrishtr 2016/10/21 22:03:09 This conditional is not needed, and therefore line
pdr. 2016/10/26 03:10:48 This approach is very nice. Done.
155 frameTranslate, FloatPoint3D()); 156 context.current.transform = properties->paintOffsetTranslation();
157 } else {
158 TransformationMatrix frameTranslate;
159 frameTranslate.translate(frameView.x() + layoutView->location().x() +
160 context.current.paintOffset.x(),
161 frameView.y() + layoutView->location().y() +
162 context.current.paintOffset.y());
163 context.current.transform =
164 layoutView->getMutableForPainting()
165 .ensurePaintProperties()
166 .updatePaintOffsetTranslation(context.current.transform,
167 frameTranslate, FloatPoint3D());
168 }
156 context.current.paintOffset = LayoutPoint(); 169 context.current.paintOffset = LayoutPoint();
157 context.current.renderingContextID = 0; 170 context.current.renderingContextID = 0;
158 context.current.shouldFlattenInheritedTransform = true; 171 context.current.shouldFlattenInheritedTransform = true;
159 context.absolutePosition = context.current; 172 context.absolutePosition = context.current;
160 context.containerForAbsolutePosition = 173 context.containerForAbsolutePosition =
161 nullptr; // This will get set in updateOutOfFlowContext(). 174 nullptr; // This will get set in updateOutOfFlowContext().
162 context.fixedPosition = context.current; 175 context.fixedPosition = context.current;
163 return; 176 return;
164 } 177 }
165 178
166 TransformationMatrix frameTranslate; 179 #ifndef NDEBUG
167 frameTranslate.translate(frameView.x() + context.current.paintOffset.x(), 180 auto underInvalidationChecker =
168 frameView.y() + context.current.paintOffset.y()); 181 FrameViewUnderInvalidationCheckScope::createIfNeeded(&frameView);
169 context.current.transform = updateFrameViewPreTranslation( 182 #endif
170 frameView, context.current.transform, frameTranslate, FloatPoint3D());
171 183
172 FloatRoundedRect contentClip( 184 const auto* initialTransformNode = context.current.transform;
173 IntRect(IntPoint(), frameView.visibleContentSize())); 185 auto* initialScrollNode = context.current.scroll;
174 context.current.clip = updateFrameViewContentClip(
175 frameView, context.current.clip, frameView.preTranslation(), contentClip);
176 186
177 // Record the fixed properties before any scrolling occurs. 187 if (frameView.paintPropertiesValid()) {
178 const auto* fixedTransformNode = context.current.transform; 188 // No invalidation so update the context using existing properties.
179 auto* fixedScrollNode = context.current.scroll; 189 if (const auto* preTranslation = frameView.preTranslation())
190 context.current.transform = preTranslation;
191 if (const auto* clip = frameView.contentClip())
192 context.current.clip = clip;
193 if (const auto* scrollTranslation = frameView.scrollTranslation())
194 context.current.transform = scrollTranslation;
195 if (auto* scroll = frameView.scroll())
196 context.current.scroll = scroll;
197 } else {
198 TransformationMatrix frameTranslate;
199 frameTranslate.translate(frameView.x() + context.current.paintOffset.x(),
200 frameView.y() + context.current.paintOffset.y());
201 context.current.transform = updateFrameViewPreTranslation(
202 frameView, context.current.transform, frameTranslate, FloatPoint3D());
180 203
181 ScrollOffset scrollOffset = frameView.scrollOffset(); 204 FloatRoundedRect contentClip(
182 if (frameView.isScrollable() || !scrollOffset.isZero()) { 205 IntRect(IntPoint(), frameView.visibleContentSize()));
183 TransformationMatrix frameScroll; 206 context.current.clip =
184 frameScroll.translate(-scrollOffset.width(), -scrollOffset.height()); 207 updateFrameViewContentClip(frameView, context.current.clip,
185 context.current.transform = updateFrameViewScrollTranslation( 208 frameView.preTranslation(), contentClip);
186 frameView, frameView.preTranslation(), frameScroll, FloatPoint3D());
187 209
188 IntSize scrollClip = frameView.visibleContentSize(); 210 ScrollOffset scrollOffset = frameView.scrollOffset();
189 IntSize scrollBounds = frameView.contentsSize(); 211 if (frameView.isScrollable() || !scrollOffset.isZero()) {
190 bool userScrollableHorizontal = 212 TransformationMatrix frameScroll;
191 frameView.userInputScrollable(HorizontalScrollbar); 213 frameScroll.translate(-scrollOffset.width(), -scrollOffset.height());
192 bool userScrollableVertical = 214 context.current.transform = updateFrameViewScrollTranslation(
193 frameView.userInputScrollable(VerticalScrollbar); 215 frameView, frameView.preTranslation(), frameScroll, FloatPoint3D());
194 context.current.scroll = updateFrameViewScroll( 216
195 frameView, context.current.scroll, frameView.scrollTranslation(), 217 IntSize scrollClip = frameView.visibleContentSize();
196 scrollClip, scrollBounds, userScrollableHorizontal, 218 IntSize scrollBounds = frameView.contentsSize();
197 userScrollableVertical); 219 bool userScrollableHorizontal =
198 } else { 220 frameView.userInputScrollable(HorizontalScrollbar);
199 // Ensure pre-existing properties are cleared when there is no scrolling. 221 bool userScrollableVertical =
200 frameView.setScrollTranslation(nullptr); 222 frameView.userInputScrollable(VerticalScrollbar);
201 frameView.setScroll(nullptr); 223 context.current.scroll = updateFrameViewScroll(
224 frameView, context.current.scroll, frameView.scrollTranslation(),
225 scrollClip, scrollBounds, userScrollableHorizontal,
226 userScrollableVertical);
227 } else {
228 // Ensure pre-existing properties are cleared when there is no scrolling.
229 frameView.setScrollTranslation(nullptr);
230 frameView.setScroll(nullptr);
231 }
202 } 232 }
203 233
204 // Initialize the context for current, absolute and fixed position cases. 234 // Initialize the context for current, absolute and fixed position cases.
205 // They are the same, except that scroll translation does not apply to 235 // They are the same, except that scroll translation does not apply to
206 // fixed position descendants. 236 // fixed position descendants.
207 context.current.paintOffset = LayoutPoint(); 237 context.current.paintOffset = LayoutPoint();
208 context.current.renderingContextID = 0; 238 context.current.renderingContextID = 0;
209 context.current.shouldFlattenInheritedTransform = true; 239 context.current.shouldFlattenInheritedTransform = true;
210 context.absolutePosition = context.current; 240 context.absolutePosition = context.current;
211 context.containerForAbsolutePosition = nullptr; 241 context.containerForAbsolutePosition = nullptr;
212 context.fixedPosition = context.current; 242 context.fixedPosition = context.current;
213 context.fixedPosition.transform = fixedTransformNode; 243 context.fixedPosition.transform = frameView.preTranslation()
214 context.fixedPosition.scroll = fixedScrollNode; 244 ? frameView.preTranslation()
245 : initialTransformNode;
246 context.fixedPosition.scroll = initialScrollNode;
215 247
216 std::unique_ptr<PropertyTreeState> contentsState( 248 std::unique_ptr<PropertyTreeState> contentsState(
217 new PropertyTreeState(context.current.transform, context.current.clip, 249 new PropertyTreeState(context.current.transform, context.current.clip,
218 context.currentEffect, context.current.scroll)); 250 context.currentEffect, context.current.scroll));
219 frameView.setTotalPropertyTreeStateForContents(std::move(contentsState)); 251 frameView.setTotalPropertyTreeStateForContents(std::move(contentsState));
220 } 252 }
221 253
222 void PaintPropertyTreeBuilder::updatePaintOffsetTranslation( 254 void PaintPropertyTreeBuilder::updatePaintOffsetTranslation(
223 const LayoutObject& object, 255 const LayoutObject& object,
224 PaintPropertyTreeBuilderContext& context) { 256 PaintPropertyTreeBuilderContext& context) {
225 if (object.isBoxModelObject() && 257 if (object.isBoxModelObject() &&
226 context.current.paintOffset != LayoutPoint()) { 258 context.current.paintOffset != LayoutPoint()) {
227 // TODO(trchen): Eliminate PaintLayer dependency. 259 // TODO(trchen): Eliminate PaintLayer dependency.
228 PaintLayer* layer = toLayoutBoxModelObject(object).layer(); 260 PaintLayer* layer = toLayoutBoxModelObject(object).layer();
229 if (layer && layer->paintsWithTransform(GlobalPaintNormalPhase)) { 261 if (layer && layer->paintsWithTransform(GlobalPaintNormalPhase)) {
230 // We should use the same subpixel paint offset values for snapping 262 // We should use the same subpixel paint offset values for snapping
231 // regardless of whether a transform is present. If there is a transform 263 // regardless of whether a transform is present. If there is a transform
232 // we round the paint offset but keep around the residual fractional 264 // we round the paint offset but keep around the residual fractional
233 // component for the transformed content to paint with. In spv1 this was 265 // component for the transformed content to paint with. In spv1 this was
234 // called "subpixel accumulation". For more information, see 266 // called "subpixel accumulation". For more information, see
235 // PaintLayer::subpixelAccumulation() and 267 // PaintLayer::subpixelAccumulation() and
236 // PaintLayerPainter::paintFragmentByApplyingTransform. 268 // PaintLayerPainter::paintFragmentByApplyingTransform.
237 IntPoint roundedPaintOffset = 269 IntPoint roundedPaintOffset =
238 roundedIntPoint(context.current.paintOffset); 270 roundedIntPoint(context.current.paintOffset);
239 LayoutPoint fractionalPaintOffset = 271 LayoutPoint fractionalPaintOffset =
240 LayoutPoint(context.current.paintOffset - roundedPaintOffset); 272 LayoutPoint(context.current.paintOffset - roundedPaintOffset);
241 273
242 context.current.transform = 274 // TODO(pdr): Refactor this check to be higher so the layer and
243 object.getMutableForPainting() 275 // paintsWithTransform checks can be skipped if there's no invalidation.
244 .ensurePaintProperties() 276 if (object.paintPropertiesValid()) {
245 .updatePaintOffsetTranslation( 277 // No invalidation so update the context using existing properties.
246 context.current.transform, 278 const auto* properties = object.paintProperties();
247 TransformationMatrix().translate(roundedPaintOffset.x(), 279 if (properties && properties->paintOffsetTranslation())
248 roundedPaintOffset.y()), 280 context.current.transform = properties->paintOffsetTranslation();
249 FloatPoint3D(), 281 } else {
250 context.current.shouldFlattenInheritedTransform, 282 context.current.transform =
251 context.current.renderingContextID); 283 object.getMutableForPainting()
284 .ensurePaintProperties()
285 .updatePaintOffsetTranslation(
286 context.current.transform,
287 TransformationMatrix().translate(roundedPaintOffset.x(),
288 roundedPaintOffset.y()),
289 FloatPoint3D(),
290 context.current.shouldFlattenInheritedTransform,
291 context.current.renderingContextID);
292 }
252 context.current.paintOffset = fractionalPaintOffset; 293 context.current.paintOffset = fractionalPaintOffset;
253 return; 294 return;
254 } 295 }
255 } 296 }
256 297
257 if (object.isLayoutView()) 298 if (object.isLayoutView())
258 return; 299 return;
259 300
260 if (auto* properties = object.getMutableForPainting().paintProperties()) 301 if (!object.paintPropertiesValid()) {
261 properties->clearPaintOffsetTranslation(); 302 if (auto* properties = object.getMutableForPainting().paintProperties())
303 properties->clearPaintOffsetTranslation();
304 }
262 } 305 }
263 306
264 static FloatPoint3D transformOrigin(const LayoutBox& box) { 307 static FloatPoint3D transformOrigin(const LayoutBox& box) {
chrishtr 2016/10/21 22:03:09 This method is now getting very long, refactor it?
pdr. 2016/10/26 03:10:48 Done. Split out the svg-specific code into its own
265 const ComputedStyle& style = box.styleRef(); 308 const ComputedStyle& style = box.styleRef();
266 FloatSize borderBoxSize(box.size()); 309 FloatSize borderBoxSize(box.size());
267 return FloatPoint3D( 310 return FloatPoint3D(
268 floatValueForLength(style.transformOriginX(), borderBoxSize.width()), 311 floatValueForLength(style.transformOriginX(), borderBoxSize.width()),
269 floatValueForLength(style.transformOriginY(), borderBoxSize.height()), 312 floatValueForLength(style.transformOriginY(), borderBoxSize.height()),
270 style.transformOriginZ()); 313 style.transformOriginZ());
271 } 314 }
272 315
273 void PaintPropertyTreeBuilder::updateTransform( 316 void PaintPropertyTreeBuilder::updateTransform(
274 const LayoutObject& object, 317 const LayoutObject& object,
275 PaintPropertyTreeBuilderContext& context) { 318 PaintPropertyTreeBuilderContext& context) {
276 if (object.isSVG() && !object.isSVGRoot()) { 319 if (object.isSVG() && !object.isSVGRoot()) {
277 // SVG (other than SVGForeignObject) does not use paint offset internally. 320 // SVG (other than SVGForeignObject) does not use paint offset internally.
278 DCHECK(object.isSVGForeignObject() || 321 DCHECK(object.isSVGForeignObject() ||
279 context.current.paintOffset == LayoutPoint()); 322 context.current.paintOffset == LayoutPoint());
280 323
281 // FIXME(pdr): Check for the presence of a transform instead of the value. 324 if (object.paintPropertiesValid()) {
282 // Checking for an identity matrix will cause the property tree structure to 325 // No invalidation so update the context using existing properties.
283 // change during animations if the animation passes through the identity 326 if (object.paintProperties() && object.paintProperties()->transform()) {
284 // matrix. 327 context.current.transform = object.paintProperties()->transform();
285 // FIXME(pdr): Refactor this so all non-root SVG objects use the same 328 context.current.shouldFlattenInheritedTransform = false;
286 // transform function. 329 context.current.renderingContextID = 0;
287 const AffineTransform& transform = object.isSVGForeignObject() 330 }
288 ? object.localSVGTransform() 331 } else {
289 : object.localToSVGParentTransform(); 332 // FIXME(pdr): Check for the presence of a transform instead of the value.
290 if (!transform.isIdentity()) { 333 // Checking for an identity matrix will cause the property tree structure
291 // The origin is included in the local transform, so leave origin empty. 334 // to change during animations if the animation passes through the
292 context.current.transform = 335 // identity matrix.
293 object.getMutableForPainting() 336 // FIXME(pdr): Refactor this so all non-root SVG objects use the same
294 .ensurePaintProperties() 337 // transform function.
295 .updateTransform(context.current.transform, 338 const AffineTransform& transform =
296 TransformationMatrix(transform), FloatPoint3D()); 339 object.isSVGForeignObject() ? object.localSVGTransform()
297 context.current.renderingContextID = 0; 340 : object.localToSVGParentTransform();
298 context.current.shouldFlattenInheritedTransform = false; 341 if (!transform.isIdentity()) {
299 return; 342 // The origin is included in the local transform, so leave origin empty.
343 context.current.transform =
344 object.getMutableForPainting()
345 .ensurePaintProperties()
346 .updateTransform(context.current.transform,
347 TransformationMatrix(transform),
348 FloatPoint3D());
349 context.current.shouldFlattenInheritedTransform = false;
350 context.current.renderingContextID = 0;
351 } else {
352 if (auto* properties = object.getMutableForPainting().paintProperties())
353 properties->clearTransform();
354 }
300 } 355 }
301 } else { 356 return;
302 const ComputedStyle& style = object.styleRef(); 357 }
303 if (object.isBox() && (style.hasTransform() || style.preserves3D())) { 358
359 const ComputedStyle& style = object.styleRef();
360 if (object.isBox() && (style.hasTransform() || style.preserves3D())) {
361 unsigned renderingContextID = context.current.renderingContextID;
362 unsigned renderingContextIDForChildren = 0;
363 bool flattensInheritedTransform =
364 context.current.shouldFlattenInheritedTransform;
365 bool childrenFlattenInheritedTransform = true;
366
367 // TODO(trchen): transform-style should only be respected if a PaintLayer
368 // is created.
369 if (style.preserves3D()) {
370 // If a node with transform-style: preserve-3d does not exist in an
371 // existing rendering context, it establishes a new one.
372 if (!renderingContextID)
373 renderingContextID = PtrHash<const LayoutObject>::hash(&object);
374 renderingContextIDForChildren = renderingContextID;
375 childrenFlattenInheritedTransform = false;
376 }
377 context.current.renderingContextID = renderingContextIDForChildren;
378 context.current.shouldFlattenInheritedTransform =
379 childrenFlattenInheritedTransform;
380
381 if (object.paintPropertiesValid()) {
382 // No invalidation so update the context using existing properties.
383 if (object.paintProperties() && object.paintProperties()->transform())
384 context.current.transform = object.paintProperties()->transform();
385 } else {
304 TransformationMatrix matrix; 386 TransformationMatrix matrix;
305 style.applyTransform( 387 style.applyTransform(
306 matrix, toLayoutBox(object).size(), 388 matrix, toLayoutBox(object).size(),
307 ComputedStyle::ExcludeTransformOrigin, 389 ComputedStyle::ExcludeTransformOrigin,
308 ComputedStyle::IncludeMotionPath, 390 ComputedStyle::IncludeMotionPath,
309 ComputedStyle::IncludeIndependentTransformProperties); 391 ComputedStyle::IncludeIndependentTransformProperties);
310 FloatPoint3D origin = transformOrigin(toLayoutBox(object)); 392 FloatPoint3D origin = transformOrigin(toLayoutBox(object));
311
312 unsigned renderingContextID = context.current.renderingContextID;
313 unsigned renderingContextIDForChildren = 0;
314 bool flattensInheritedTransform =
315 context.current.shouldFlattenInheritedTransform;
316 bool childrenFlattenInheritedTransform = true;
317
318 // TODO(trchen): transform-style should only be respected if a PaintLayer
319 // is created.
320 if (style.preserves3D()) {
321 // If a node with transform-style: preserve-3d does not exist in an
322 // existing rendering context, it establishes a new one.
323 if (!renderingContextID)
324 renderingContextID = PtrHash<const LayoutObject>::hash(&object);
325 renderingContextIDForChildren = renderingContextID;
326 childrenFlattenInheritedTransform = false;
327 }
328
329 context.current.transform = 393 context.current.transform =
330 object.getMutableForPainting() 394 object.getMutableForPainting()
331 .ensurePaintProperties() 395 .ensurePaintProperties()
332 .updateTransform(context.current.transform, matrix, origin, 396 .updateTransform(context.current.transform, matrix, origin,
333 flattensInheritedTransform, renderingContextID); 397 flattensInheritedTransform, renderingContextID);
334 context.current.renderingContextID = renderingContextIDForChildren; 398 }
335 context.current.shouldFlattenInheritedTransform = 399 } else {
336 childrenFlattenInheritedTransform; 400 if (!object.paintPropertiesValid()) {
337 return; 401 if (auto* properties = object.getMutableForPainting().paintProperties())
402 properties->clearTransform();
338 } 403 }
339 } 404 }
340
341 if (auto* properties = object.getMutableForPainting().paintProperties())
342 properties->clearTransform();
343 } 405 }
344 406
345 void PaintPropertyTreeBuilder::updateEffect( 407 void PaintPropertyTreeBuilder::updateEffect(
346 const LayoutObject& object, 408 const LayoutObject& object,
347 PaintPropertyTreeBuilderContext& context) { 409 PaintPropertyTreeBuilderContext& context) {
348 if (!object.styleRef().hasOpacity()) { 410 if (object.paintPropertiesValid()) {
349 if (auto* properties = object.getMutableForPainting().paintProperties()) 411 // No invalidation so update the context using existing properties.
350 properties->clearEffect(); 412 if (object.paintProperties() && object.paintProperties()->effect())
351 return; 413 context.currentEffect = object.paintProperties()->effect();
414 } else {
415 if (object.styleRef().hasOpacity()) {
416 context.currentEffect =
417 object.getMutableForPainting().ensurePaintProperties().updateEffect(
418 context.currentEffect, object.styleRef().opacity());
419 } else {
420 if (auto* properties = object.getMutableForPainting().paintProperties())
421 properties->clearEffect();
422 }
352 } 423 }
353
354 context.currentEffect =
355 object.getMutableForPainting().ensurePaintProperties().updateEffect(
356 context.currentEffect, object.styleRef().opacity());
357 } 424 }
358 425
359 void PaintPropertyTreeBuilder::updateCssClip( 426 void PaintPropertyTreeBuilder::updateCssClip(
360 const LayoutObject& object, 427 const LayoutObject& object,
361 PaintPropertyTreeBuilderContext& context) { 428 PaintPropertyTreeBuilderContext& context) {
362 if (object.hasClip()) { 429 if (object.paintPropertiesValid()) {
363 // Create clip node for descendants that are not fixed position. 430 // No invalidation so update the context using existing properties.
364 // We don't have to setup context.absolutePosition.clip here because this 431 if (object.paintProperties() && object.paintProperties()->cssClip())
365 // object must be a container for absolute position descendants, and will 432 context.current.clip = object.paintProperties()->cssClip();
366 // copy from in-flow context later at updateOutOfFlowContext() step. 433 } else {
367 DCHECK(object.canContainAbsolutePositionObjects()); 434 if (object.hasClip()) {
368 LayoutRect clipRect = 435 // Create clip node for descendants that are not fixed position.
369 toLayoutBox(object).clipRect(context.current.paintOffset); 436 // We don't have to setup context.absolutePosition.clip here because this
370 context.current.clip = 437 // object must be a container for absolute position descendants, and will
371 object.getMutableForPainting().ensurePaintProperties().updateCssClip( 438 // copy from in-flow context later at updateOutOfFlowContext() step.
372 context.current.clip, context.current.transform, 439 DCHECK(object.canContainAbsolutePositionObjects());
373 FloatRoundedRect(FloatRect(clipRect))); 440 LayoutRect clipRect =
374 return; 441 toLayoutBox(object).clipRect(context.current.paintOffset);
442 context.current.clip =
443 object.getMutableForPainting().ensurePaintProperties().updateCssClip(
444 context.current.clip, context.current.transform,
445 FloatRoundedRect(FloatRect(clipRect)));
446 } else {
447 if (auto* properties = object.getMutableForPainting().paintProperties())
448 properties->clearCssClip();
449 }
375 } 450 }
376
377 if (auto* properties = object.getMutableForPainting().paintProperties())
378 properties->clearCssClip();
379 } 451 }
380 452
381 void PaintPropertyTreeBuilder::updateLocalBorderBoxContext( 453 void PaintPropertyTreeBuilder::updateLocalBorderBoxContext(
382 const LayoutObject& object, 454 const LayoutObject& object,
383 PaintPropertyTreeBuilderContext& context) { 455 PaintPropertyTreeBuilderContext& context) {
456 if (object.paintPropertiesValid())
457 return;
458
384 // Avoid adding an ObjectPaintProperties for non-boxes to save memory, since 459 // Avoid adding an ObjectPaintProperties for non-boxes to save memory, since
385 // we don't need them at the moment. 460 // we don't need them at the moment.
386 if (!object.isBox() && !object.hasLayer()) 461 if (!object.isBox() && !object.hasLayer()) {
462 if (auto* properties = object.getMutableForPainting().paintProperties())
463 properties->clearLocalBorderBoxProperties();
chrishtr 2016/10/21 22:03:09 Why is this change needed but wasn't in the old co
pdr. 2016/10/26 03:10:48 This is just a cleanup so we don't leave unnecessa
387 return; 464 return;
465 }
388 466
389 std::unique_ptr<ObjectPaintProperties::PropertyTreeStateWithOffset> 467 std::unique_ptr<ObjectPaintProperties::PropertyTreeStateWithOffset>
390 borderBoxContext = 468 borderBoxContext =
391 wrapUnique(new ObjectPaintProperties::PropertyTreeStateWithOffset( 469 wrapUnique(new ObjectPaintProperties::PropertyTreeStateWithOffset(
392 context.current.paintOffset, 470 context.current.paintOffset,
393 PropertyTreeState(context.current.transform, context.current.clip, 471 PropertyTreeState(context.current.transform, context.current.clip,
394 context.currentEffect, 472 context.currentEffect,
395 context.current.scroll))); 473 context.current.scroll)));
396 object.getMutableForPainting() 474 object.getMutableForPainting()
397 .ensurePaintProperties() 475 .ensurePaintProperties()
398 .setLocalBorderBoxProperties(std::move(borderBoxContext)); 476 .setLocalBorderBoxProperties(std::move(borderBoxContext));
399 } 477 }
400 478
401 // TODO(trchen): Remove this once we bake the paint offset into frameRect. 479 // TODO(trchen): Remove this once we bake the paint offset into frameRect.
402 void PaintPropertyTreeBuilder::updateScrollbarPaintOffset( 480 void PaintPropertyTreeBuilder::updateScrollbarPaintOffset(
403 const LayoutObject& object, 481 const LayoutObject& object,
404 const PaintPropertyTreeBuilderContext& context) { 482 const PaintPropertyTreeBuilderContext& context) {
483 if (object.paintPropertiesValid())
484 return;
485
405 IntPoint roundedPaintOffset = roundedIntPoint(context.current.paintOffset); 486 IntPoint roundedPaintOffset = roundedIntPoint(context.current.paintOffset);
406 if (roundedPaintOffset != IntPoint() && object.isBoxModelObject()) { 487 if (roundedPaintOffset != IntPoint() && object.isBoxModelObject()) {
407 if (PaintLayerScrollableArea* scrollableArea = 488 if (PaintLayerScrollableArea* scrollableArea =
408 toLayoutBoxModelObject(object).getScrollableArea()) { 489 toLayoutBoxModelObject(object).getScrollableArea()) {
409 if (scrollableArea->horizontalScrollbar() || 490 if (scrollableArea->horizontalScrollbar() ||
410 scrollableArea->verticalScrollbar()) { 491 scrollableArea->verticalScrollbar()) {
411 auto paintOffset = TransformationMatrix().translate( 492 auto paintOffset = TransformationMatrix().translate(
412 roundedPaintOffset.x(), roundedPaintOffset.y()); 493 roundedPaintOffset.x(), roundedPaintOffset.y());
413 object.getMutableForPainting() 494 object.getMutableForPainting()
414 .ensurePaintProperties() 495 .ensurePaintProperties()
415 .updateScrollbarPaintOffset(context.current.transform, paintOffset, 496 .updateScrollbarPaintOffset(context.current.transform, paintOffset,
416 FloatPoint3D()); 497 FloatPoint3D());
417 return; 498 return;
418 } 499 }
419 } 500 }
420 } 501 }
421 502
422 if (auto* properties = object.getMutableForPainting().paintProperties()) 503 if (auto* properties = object.getMutableForPainting().paintProperties())
423 properties->clearScrollbarPaintOffset(); 504 properties->clearScrollbarPaintOffset();
424 } 505 }
425 506
426 void PaintPropertyTreeBuilder::updateMainThreadScrollingReasons( 507 void PaintPropertyTreeBuilder::updateMainThreadScrollingReasons(
427 const LayoutObject& object, 508 const LayoutObject& object,
428 PaintPropertyTreeBuilderContext& context) { 509 PaintPropertyTreeBuilderContext& context) {
510 // TODO(pdr): Add property under-invalidation checking for main thread scroll
511 // reasons and ensure reason changes invalidate property trees.
429 if (context.current.scroll && 512 if (context.current.scroll &&
430 !object.document().settings()->threadedScrollingEnabled()) 513 !object.document().settings()->threadedScrollingEnabled()) {
431 context.current.scroll->addMainThreadScrollingReasons( 514 context.current.scroll->addMainThreadScrollingReasons(
432 MainThreadScrollingReason::kThreadedScrollingDisabled); 515 MainThreadScrollingReason::kThreadedScrollingDisabled);
516 }
433 517
434 if (object.isBackgroundAttachmentFixedObject()) { 518 if (object.isBackgroundAttachmentFixedObject()) {
435 auto* scrollNode = context.current.scroll; 519 auto* scrollNode = context.current.scroll;
436 while ( 520 while (
437 scrollNode && 521 scrollNode &&
438 !scrollNode->hasMainThreadScrollingReasons( 522 !scrollNode->hasMainThreadScrollingReasons(
439 MainThreadScrollingReason::kHasBackgroundAttachmentFixedObjects)) { 523 MainThreadScrollingReason::kHasBackgroundAttachmentFixedObjects)) {
440 scrollNode->addMainThreadScrollingReasons( 524 scrollNode->addMainThreadScrollingReasons(
441 MainThreadScrollingReason::kHasBackgroundAttachmentFixedObjects); 525 MainThreadScrollingReason::kHasBackgroundAttachmentFixedObjects);
442 scrollNode = scrollNode->parent(); 526 scrollNode = scrollNode->parent();
443 } 527 }
444 } 528 }
445 } 529 }
446 530
447 void PaintPropertyTreeBuilder::updateOverflowClip( 531 void PaintPropertyTreeBuilder::updateOverflowClip(
448 const LayoutObject& object, 532 const LayoutObject& object,
449 PaintPropertyTreeBuilderContext& context) { 533 PaintPropertyTreeBuilderContext& context) {
450 if (!object.isBox()) 534 if (!object.isBox())
451 return; 535 return;
452 const LayoutBox& box = toLayoutBox(object); 536 const LayoutBox& box = toLayoutBox(object);
453 537
538 if (object.paintPropertiesValid()) {
539 // No invalidation so update the context using existing properties.
540 const auto* properties = object.paintProperties();
541 if (properties && properties->overflowClip())
542 context.current.clip = properties->overflowClip();
543 return;
544 }
545
454 // The <input> elements can't have contents thus CSS overflow property doesn't 546 // The <input> elements can't have contents thus CSS overflow property doesn't
455 // apply. However for layout purposes we do generate child layout objects for 547 // apply. However for layout purposes we do generate child layout objects for
456 // them, e.g. button label. We should clip the overflow from those children. 548 // them, e.g. button label. We should clip the overflow from those children.
457 // This is called control clip and we technically treat them like overflow 549 // This is called control clip and we technically treat them like overflow
458 // clip. 550 // clip.
459 LayoutRect clipRect; 551 LayoutRect clipRect;
460 if (box.hasControlClip()) { 552 if (box.hasControlClip()) {
461 clipRect = box.controlClipRect(context.current.paintOffset); 553 clipRect = box.controlClipRect(context.current.paintOffset);
462 } else if (box.hasOverflowClip() || box.styleRef().containsPaint() || 554 } else if (box.hasOverflowClip() || box.styleRef().containsPaint() ||
463 (box.isSVGRoot() && 555 (box.isSVGRoot() &&
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
496 return FloatPoint( 588 return FloatPoint(
497 floatValueForLength(style.perspectiveOriginX(), borderBoxSize.width()), 589 floatValueForLength(style.perspectiveOriginX(), borderBoxSize.width()),
498 floatValueForLength(style.perspectiveOriginY(), borderBoxSize.height())); 590 floatValueForLength(style.perspectiveOriginY(), borderBoxSize.height()));
499 } 591 }
500 592
501 void PaintPropertyTreeBuilder::updatePerspective( 593 void PaintPropertyTreeBuilder::updatePerspective(
502 const LayoutObject& object, 594 const LayoutObject& object,
503 PaintPropertyTreeBuilderContext& context) { 595 PaintPropertyTreeBuilderContext& context) {
504 const ComputedStyle& style = object.styleRef(); 596 const ComputedStyle& style = object.styleRef();
505 if (!object.isBox() || !style.hasPerspective()) { 597 if (!object.isBox() || !style.hasPerspective()) {
506 if (auto* properties = object.getMutableForPainting().paintProperties()) 598 if (!object.paintPropertiesValid()) {
507 properties->clearPerspective(); 599 if (auto* properties = object.getMutableForPainting().paintProperties())
600 properties->clearPerspective();
601 }
508 return; 602 return;
509 } 603 }
510 604
511 // The perspective node must not flatten (else nothing will get 605 if (object.paintPropertiesValid()) {
512 // perspective), but it should still extend the rendering context as most 606 // No invalidation so update the context using existing properties.
513 // transform nodes do. 607 if (object.paintProperties() && object.paintProperties()->perspective())
514 TransformationMatrix matrix = 608 context.current.transform = object.paintProperties()->perspective();
515 TransformationMatrix().applyPerspective(style.perspective()); 609 } else {
516 FloatPoint3D origin = perspectiveOrigin(toLayoutBox(object)) + 610 // The perspective node must not flatten (else nothing will get
517 toLayoutSize(context.current.paintOffset); 611 // perspective), but it should still extend the rendering context as most
518 context.current.transform = 612 // transform nodes do.
519 object.getMutableForPainting().ensurePaintProperties().updatePerspective( 613 TransformationMatrix matrix =
520 context.current.transform, matrix, origin, 614 TransformationMatrix().applyPerspective(style.perspective());
521 context.current.shouldFlattenInheritedTransform, 615 FloatPoint3D origin = perspectiveOrigin(toLayoutBox(object)) +
522 context.current.renderingContextID); 616 toLayoutSize(context.current.paintOffset);
617 context.current.transform =
618 object.getMutableForPainting()
619 .ensurePaintProperties()
620 .updatePerspective(context.current.transform, matrix, origin,
621 context.current.shouldFlattenInheritedTransform,
622 context.current.renderingContextID);
623 }
523 context.current.shouldFlattenInheritedTransform = false; 624 context.current.shouldFlattenInheritedTransform = false;
524 } 625 }
525 626
526 void PaintPropertyTreeBuilder::updateSvgLocalToBorderBoxTransform( 627 void PaintPropertyTreeBuilder::updateSvgLocalToBorderBoxTransform(
527 const LayoutObject& object, 628 const LayoutObject& object,
528 PaintPropertyTreeBuilderContext& context) { 629 PaintPropertyTreeBuilderContext& context) {
529 if (!object.isSVGRoot()) 630 if (!object.isSVGRoot())
530 return; 631 return;
531 632
532 AffineTransform transformToBorderBox = 633 if (object.paintPropertiesValid()) {
533 SVGRootPainter(toLayoutSVGRoot(object)) 634 // No invalidation so update the context using existing properties.
534 .transformToPixelSnappedBorderBox(context.current.paintOffset); 635 const auto* properties = object.paintProperties();
636 if (properties && properties->svgLocalToBorderBoxTransform()) {
637 context.current.transform = properties->svgLocalToBorderBoxTransform();
638 context.current.shouldFlattenInheritedTransform = false;
639 context.current.renderingContextID = 0;
640 }
641 } else {
642 AffineTransform transformToBorderBox =
643 SVGRootPainter(toLayoutSVGRoot(object))
644 .transformToPixelSnappedBorderBox(context.current.paintOffset);
645
646 if (transformToBorderBox.isIdentity()) {
647 if (auto* properties = object.getMutableForPainting().paintProperties())
648 properties->clearSvgLocalToBorderBoxTransform();
649 } else {
650 context.current.transform = object.getMutableForPainting()
651 .ensurePaintProperties()
652 .updateSvgLocalToBorderBoxTransform(
653 context.current.transform,
654 transformToBorderBox, FloatPoint3D());
655 context.current.shouldFlattenInheritedTransform = false;
656 context.current.renderingContextID = 0;
657 }
658 }
535 659
536 // The paint offset is included in |transformToBorderBox| so SVG does not need 660 // The paint offset is included in |transformToBorderBox| so SVG does not need
537 // to handle paint offset internally. 661 // to handle paint offset internally.
538 context.current.paintOffset = LayoutPoint(); 662 context.current.paintOffset = LayoutPoint();
539
540 if (transformToBorderBox.isIdentity()) {
541 if (auto* properties = object.getMutableForPainting().paintProperties())
542 properties->clearSvgLocalToBorderBoxTransform();
543 return;
544 }
545
546 context.current.transform =
547 object.getMutableForPainting()
548 .ensurePaintProperties()
549 .updateSvgLocalToBorderBoxTransform(
550 context.current.transform, transformToBorderBox, FloatPoint3D());
551 context.current.shouldFlattenInheritedTransform = false;
552 context.current.renderingContextID = 0;
553 } 663 }
554 664
555 void PaintPropertyTreeBuilder::updateScrollAndScrollTranslation( 665 void PaintPropertyTreeBuilder::updateScrollAndScrollTranslation(
556 const LayoutObject& object, 666 const LayoutObject& object,
557 PaintPropertyTreeBuilderContext& context) { 667 PaintPropertyTreeBuilderContext& context) {
668 if (object.paintPropertiesValid()) {
669 // No invalidation so update the context using existing properties.
670 if (object.paintProperties() && object.paintProperties()->scroll()) {
671 context.current.transform = object.paintProperties()->transform();
672 const auto* scroll = object.paintProperties()->scroll();
673 // TODO(pdr): Remove this const cast.
674 context.current.scroll = const_cast<ScrollPaintPropertyNode*>(scroll);
675 context.current.shouldFlattenInheritedTransform = false;
676 }
677 return;
678 }
679
558 if (object.hasOverflowClip()) { 680 if (object.hasOverflowClip()) {
559 const LayoutBox& box = toLayoutBox(object); 681 const LayoutBox& box = toLayoutBox(object);
560 const PaintLayerScrollableArea* scrollableArea = box.getScrollableArea(); 682 const PaintLayerScrollableArea* scrollableArea = box.getScrollableArea();
561 IntSize scrollOffset = box.scrolledContentOffset(); 683 IntSize scrollOffset = box.scrolledContentOffset();
562 if (!scrollOffset.isZero() || scrollableArea->scrollsOverflow()) { 684 if (!scrollOffset.isZero() || scrollableArea->scrollsOverflow()) {
563 TransformationMatrix matrix = TransformationMatrix().translate( 685 TransformationMatrix matrix = TransformationMatrix().translate(
564 -scrollOffset.width(), -scrollOffset.height()); 686 -scrollOffset.width(), -scrollOffset.height());
565 context.current.transform = 687 context.current.transform =
566 object.getMutableForPainting() 688 object.getMutableForPainting()
567 .ensurePaintProperties() 689 .ensurePaintProperties()
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
621 // absolute position container. However for fixed-position descendants we 743 // absolute position container. However for fixed-position descendants we
622 // need to insert the clip here if we are not a containing block ancestor of 744 // need to insert the clip here if we are not a containing block ancestor of
623 // them. 745 // them.
624 auto* cssClip = object.getMutableForPainting().paintProperties()->cssClip(); 746 auto* cssClip = object.getMutableForPainting().paintProperties()->cssClip();
625 747
626 // Before we actually create anything, check whether in-flow context and 748 // Before we actually create anything, check whether in-flow context and
627 // fixed-position context has exactly the same clip. Reuse if possible. 749 // fixed-position context has exactly the same clip. Reuse if possible.
628 if (context.fixedPosition.clip == cssClip->parent()) { 750 if (context.fixedPosition.clip == cssClip->parent()) {
629 context.fixedPosition.clip = cssClip; 751 context.fixedPosition.clip = cssClip;
630 } else { 752 } else {
631 context.fixedPosition.clip = 753 if (object.paintPropertiesValid()) {
632 object.getMutableForPainting() 754 // No invalidation so update the context using existing properties.
633 .ensurePaintProperties() 755 const auto* properties = object.paintProperties();
634 .updateCssClipFixedPosition( 756 if (properties && properties->cssClipFixedPosition())
635 context.fixedPosition.clip, 757 context.fixedPosition.clip = properties->cssClipFixedPosition();
636 const_cast<TransformPaintPropertyNode*>( 758 } else {
637 cssClip->localTransformSpace()), 759 context.fixedPosition.clip =
638 cssClip->clipRect()); 760 object.getMutableForPainting()
761 .ensurePaintProperties()
762 .updateCssClipFixedPosition(
763 context.fixedPosition.clip,
764 const_cast<TransformPaintPropertyNode*>(
765 cssClip->localTransformSpace()),
766 cssClip->clipRect());
767 }
639 return; 768 return;
640 } 769 }
641 } 770 }
642 771
643 if (auto* properties = object.getMutableForPainting().paintProperties()) 772 if (!object.paintPropertiesValid()) {
644 properties->clearCssClipFixedPosition(); 773 if (auto* properties = object.getMutableForPainting().paintProperties())
774 properties->clearCssClipFixedPosition();
775 }
645 } 776 }
646 777
647 // Override ContainingBlockContext based on the properties of a containing block 778 // Override ContainingBlockContext based on the properties of a containing block
648 // that was previously walked in a subtree other than the current subtree being 779 // that was previously walked in a subtree other than the current subtree being
649 // walked. Used for out-of-flow positioned descendants of multi-column spanner 780 // walked. Used for out-of-flow positioned descendants of multi-column spanner
650 // when the containing block is not in the normal tree walk order. 781 // when the containing block is not in the normal tree walk order.
651 // For example: 782 // For example:
652 // <div id="columns" style="columns: 2"> 783 // <div id="columns" style="columns: 2">
653 // <div id="relative" style="position: relative"> 784 // <div id="relative" style="position: relative">
654 // <div id="spanner" style="column-span: all"> 785 // <div id="spanner" style="column-span: all">
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
759 // Similar adjustment is done in LayoutTableCell::offsetFromContainer(). 890 // Similar adjustment is done in LayoutTableCell::offsetFromContainer().
760 if (boxModelObject.isTableCell()) { 891 if (boxModelObject.isTableCell()) {
761 LayoutObject* parentRow = boxModelObject.parent(); 892 LayoutObject* parentRow = boxModelObject.parent();
762 ASSERT(parentRow && parentRow->isTableRow()); 893 ASSERT(parentRow && parentRow->isTableRow());
763 context.current.paintOffset.moveBy( 894 context.current.paintOffset.moveBy(
764 -toLayoutBox(parentRow)->topLeftLocation()); 895 -toLayoutBox(parentRow)->topLeftLocation());
765 } 896 }
766 } 897 }
767 } 898 }
768 899
769 void PaintPropertyTreeBuilder::buildTreeNodesForSelf( 900 void PaintPropertyTreeBuilder::updatePropertiesForSelf(
770 const LayoutObject& object, 901 const LayoutObject& object,
771 PaintPropertyTreeBuilderContext& context) { 902 PaintPropertyTreeBuilderContext& context) {
772 if (!object.isBoxModelObject() && !object.isSVG()) 903 if (!object.isBoxModelObject() && !object.isSVG())
773 return; 904 return;
774 905
906 #ifndef NDEBUG
907 auto underInvalidationChecker =
908 ObjectUnderInvalidationCheckScope::createIfNeeded(object);
909 #endif
910
775 deriveBorderBoxFromContainerContext(object, context); 911 deriveBorderBoxFromContainerContext(object, context);
776 912
777 updatePaintOffsetTranslation(object, context); 913 updatePaintOffsetTranslation(object, context);
778 updateTransform(object, context); 914 updateTransform(object, context);
779 updateEffect(object, context); 915 updateEffect(object, context);
780 updateCssClip(object, context); 916 updateCssClip(object, context);
781 updateLocalBorderBoxContext(object, context); 917 updateLocalBorderBoxContext(object, context);
782 updateScrollbarPaintOffset(object, context); 918 updateScrollbarPaintOffset(object, context);
783 updateMainThreadScrollingReasons(object, context); 919 updateMainThreadScrollingReasons(object, context);
784 } 920 }
785 921
786 void PaintPropertyTreeBuilder::buildTreeNodesForChildren( 922 void PaintPropertyTreeBuilder::updatePropertiesForChildren(
787 const LayoutObject& object, 923 const LayoutObject& object,
788 PaintPropertyTreeBuilderContext& context) { 924 PaintPropertyTreeBuilderContext& context) {
789 if (!object.isBoxModelObject() && !object.isSVG()) 925 if (!object.isBoxModelObject() && !object.isSVG())
790 return; 926 return;
791 927
928 #ifndef NDEBUG
929 auto underInvalidationChecker =
930 ObjectUnderInvalidationCheckScope::createIfNeeded(object);
931 #endif
932
792 updateOverflowClip(object, context); 933 updateOverflowClip(object, context);
793 updatePerspective(object, context); 934 updatePerspective(object, context);
794 updateSvgLocalToBorderBoxTransform(object, context); 935 updateSvgLocalToBorderBoxTransform(object, context);
795 updateScrollAndScrollTranslation(object, context); 936 updateScrollAndScrollTranslation(object, context);
796 updateOutOfFlowContext(object, context); 937 updateOutOfFlowContext(object, context);
797 } 938 }
798 939
799 } // namespace blink 940 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698