Chromium Code Reviews| OLD | NEW | 
|---|---|
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be | 
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. | 
| 4 | 4 | 
| 5 #include "core/paint/PaintPropertyTreeBuilder.h" | 5 #include "core/paint/PaintPropertyTreeBuilder.h" | 
| 6 | 6 | 
| 7 #include "core/frame/FrameView.h" | 7 #include "core/frame/FrameView.h" | 
| 8 #include "core/frame/LocalFrame.h" | 8 #include "core/frame/LocalFrame.h" | 
| 9 #include "core/frame/Settings.h" | 9 #include "core/frame/Settings.h" | 
| 10 #include "core/layout/LayoutInline.h" | 10 #include "core/layout/LayoutInline.h" | 
| (...skipping 16 matching lines...) Expand all Loading... | |
| 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 | 
| 125 if (context.forceSubtreeUpdate) | |
| 126 frameView.setNeedsPaintPropertyUpdateWithoutMarkingAncestors(); | |
| 127 | |
| 119 #if DCHECK_IS_ON() | 128 #if DCHECK_IS_ON() | 
| 120 FindFrameViewPropertiesNeedingUpdateScope checkNeedsUpdateScope(&frameView); | 129 FindFrameViewPropertiesNeedingUpdateScope checkScope(&frameView, context); | 
| 121 #endif | 130 #endif | 
| 122 | 131 | 
| 123 if (frameView.needsPaintPropertyUpdate()) { | 132 if (frameView.needsPaintPropertyUpdate()) { | 
| 124 TransformationMatrix frameTranslate; | 133 TransformationMatrix frameTranslate; | 
| 125 frameTranslate.translate(frameView.x() + context.current.paintOffset.x(), | 134 frameTranslate.translate(frameView.x() + context.current.paintOffset.x(), | 
| 126 frameView.y() + context.current.paintOffset.y()); | 135 frameView.y() + context.current.paintOffset.y()); | 
| 127 updateFrameViewPreTranslation(frameView, context.current.transform, | 136 context.forceSubtreeUpdate |= updatePreTranslation( | 
| 128 frameTranslate, FloatPoint3D()); | 137 frameView, context.current.transform, frameTranslate, FloatPoint3D()); | 
| 129 | 138 | 
| 130 FloatRoundedRect contentClip( | 139 FloatRoundedRect contentClip( | 
| 131 IntRect(IntPoint(), frameView.visibleContentSize())); | 140 IntRect(IntPoint(), frameView.visibleContentSize())); | 
| 132 updateFrameViewContentClip(frameView, context.current.clip, | 141 context.forceSubtreeUpdate |= | 
| 133 frameView.preTranslation(), contentClip); | 142 updateContentClip(frameView, context.current.clip, | 
| 143 frameView.preTranslation(), contentClip); | |
| 134 | 144 | 
| 135 ScrollOffset scrollOffset = frameView.scrollOffset(); | 145 ScrollOffset scrollOffset = frameView.scrollOffset(); | 
| 136 if (frameView.isScrollable() || !scrollOffset.isZero()) { | 146 if (frameView.isScrollable() || !scrollOffset.isZero()) { | 
| 137 TransformationMatrix frameScroll; | 147 TransformationMatrix frameScroll; | 
| 138 frameScroll.translate(-scrollOffset.width(), -scrollOffset.height()); | 148 frameScroll.translate(-scrollOffset.width(), -scrollOffset.height()); | 
| 139 updateFrameViewScrollTranslation(frameView, frameView.preTranslation(), | 149 context.forceSubtreeUpdate |= updateScrollTranslation( | 
| 140 frameScroll, FloatPoint3D()); | 150 frameView, frameView.preTranslation(), frameScroll, FloatPoint3D()); | 
| 141 | 151 | 
| 142 IntSize scrollClip = frameView.visibleContentSize(); | 152 IntSize scrollClip = frameView.visibleContentSize(); | 
| 143 IntSize scrollBounds = frameView.contentsSize(); | 153 IntSize scrollBounds = frameView.contentsSize(); | 
| 144 bool userScrollableHorizontal = | 154 bool userScrollableHorizontal = | 
| 145 frameView.userInputScrollable(HorizontalScrollbar); | 155 frameView.userInputScrollable(HorizontalScrollbar); | 
| 146 bool userScrollableVertical = | 156 bool userScrollableVertical = | 
| 147 frameView.userInputScrollable(VerticalScrollbar); | 157 frameView.userInputScrollable(VerticalScrollbar); | 
| 148 | 158 | 
| 149 MainThreadScrollingReasons reasons = 0; | 159 MainThreadScrollingReasons reasons = 0; | 
| 150 if (!frameView.frame().settings()->threadedScrollingEnabled()) | 160 if (!frameView.frame().settings()->threadedScrollingEnabled()) | 
| 151 reasons |= MainThreadScrollingReason::kThreadedScrollingDisabled; | 161 reasons |= MainThreadScrollingReason::kThreadedScrollingDisabled; | 
| 152 if (frameView.hasBackgroundAttachmentFixedObjects()) { | 162 if (frameView.hasBackgroundAttachmentFixedObjects()) { | 
| 153 reasons |= | 163 reasons |= | 
| 154 MainThreadScrollingReason::kHasBackgroundAttachmentFixedObjects; | 164 MainThreadScrollingReason::kHasBackgroundAttachmentFixedObjects; | 
| 155 } | 165 } | 
| 156 updateFrameViewScroll(frameView, context.current.scroll, | 166 context.forceSubtreeUpdate |= updateScroll( | 
| 157 frameView.scrollTranslation(), scrollClip, | 167 frameView, context.current.scroll, frameView.scrollTranslation(), | 
| 158 scrollBounds, userScrollableHorizontal, | 168 scrollClip, scrollBounds, userScrollableHorizontal, | 
| 159 userScrollableVertical, reasons); | 169 userScrollableVertical, reasons); | 
| 160 } else { | 170 } else { | 
| 161 // Ensure pre-existing properties are cleared when there is no scrolling. | 171 if (frameView.scrollTranslation() || frameView.scroll()) { | 
| 162 frameView.setScrollTranslation(nullptr); | 172 // Ensure pre-existing properties are cleared if there is no scrolling. | 
| 163 frameView.setScroll(nullptr); | 173 frameView.setScrollTranslation(nullptr); | 
| 174 frameView.setScroll(nullptr); | |
| 175 | |
| 176 // Rebuild all descendant properties because a property was removed. | |
| 177 context.forceSubtreeUpdate = true; | |
| 178 } | |
| 164 } | 179 } | 
| 165 } | 180 } | 
| 166 | 181 | 
| 167 // Initialize the context for current, absolute and fixed position cases. | 182 // Initialize the context for current, absolute and fixed position cases. | 
| 168 // They are the same, except that scroll translation does not apply to | 183 // They are the same, except that scroll translation does not apply to | 
| 169 // fixed position descendants. | 184 // fixed position descendants. | 
| 170 const auto* fixedTransformNode = frameView.preTranslation() | 185 const auto* fixedTransformNode = frameView.preTranslation() | 
| 171 ? frameView.preTranslation() | 186 ? frameView.preTranslation() | 
| 172 : context.current.transform; | 187 : context.current.transform; | 
| 173 auto* fixedScrollNode = context.current.scroll; | 188 auto* fixedScrollNode = context.current.scroll; | 
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 217 // component for the transformed content to paint with. In spv1 this was | 232 // component for the transformed content to paint with. In spv1 this was | 
| 218 // called "subpixel accumulation". For more information, see | 233 // called "subpixel accumulation". For more information, see | 
| 219 // PaintLayer::subpixelAccumulation() and | 234 // PaintLayer::subpixelAccumulation() and | 
| 220 // PaintLayerPainter::paintFragmentByApplyingTransform. | 235 // PaintLayerPainter::paintFragmentByApplyingTransform. | 
| 221 IntPoint roundedPaintOffset = roundedIntPoint(context.current.paintOffset); | 236 IntPoint roundedPaintOffset = roundedIntPoint(context.current.paintOffset); | 
| 222 LayoutPoint fractionalPaintOffset = | 237 LayoutPoint fractionalPaintOffset = | 
| 223 LayoutPoint(context.current.paintOffset - roundedPaintOffset); | 238 LayoutPoint(context.current.paintOffset - roundedPaintOffset); | 
| 224 | 239 | 
| 225 if (object.needsPaintPropertyUpdate()) { | 240 if (object.needsPaintPropertyUpdate()) { | 
| 226 if (usesPaintOffsetTranslation) { | 241 if (usesPaintOffsetTranslation) { | 
| 227 object.getMutableForPainting() | 242 auto& properties = object.getMutableForPainting().ensurePaintProperties(); | 
| 228 .ensurePaintProperties() | 243 context.forceSubtreeUpdate |= properties.updatePaintOffsetTranslation( | 
| 229 .updatePaintOffsetTranslation( | 244 context.current.transform, | 
| 230 context.current.transform, | 245 TransformationMatrix().translate(roundedPaintOffset.x(), | 
| 231 TransformationMatrix().translate(roundedPaintOffset.x(), | 246 roundedPaintOffset.y()), | 
| 232 roundedPaintOffset.y()), | 247 FloatPoint3D(), context.current.shouldFlattenInheritedTransform, | 
| 233 FloatPoint3D(), context.current.shouldFlattenInheritedTransform, | 248 context.current.renderingContextID); | 
| 234 context.current.renderingContextID); | |
| 235 } else { | 249 } else { | 
| 236 if (auto* properties = object.getMutableForPainting().paintProperties()) | 250 if (auto* properties = object.getMutableForPainting().paintProperties()) | 
| 237 properties->clearPaintOffsetTranslation(); | 251 context.forceSubtreeUpdate |= properties->clearPaintOffsetTranslation(); | 
| 238 } | 252 } | 
| 239 } | 253 } | 
| 240 | 254 | 
| 241 const auto* properties = object.paintProperties(); | 255 const auto* properties = object.paintProperties(); | 
| 242 if (properties && properties->paintOffsetTranslation()) { | 256 if (properties && properties->paintOffsetTranslation()) { | 
| 243 context.current.transform = properties->paintOffsetTranslation(); | 257 context.current.transform = properties->paintOffsetTranslation(); | 
| 244 context.current.paintOffset = fractionalPaintOffset; | 258 context.current.paintOffset = fractionalPaintOffset; | 
| 245 if (RuntimeEnabledFeatures::rootLayerScrollingEnabled() && | 259 if (RuntimeEnabledFeatures::rootLayerScrollingEnabled() && | 
| 246 object.isLayoutView()) { | 260 object.isLayoutView()) { | 
| 247 context.absolutePosition.transform = properties->paintOffsetTranslation(); | 261 context.absolutePosition.transform = properties->paintOffsetTranslation(); | 
| (...skipping 24 matching lines...) Expand all Loading... | |
| 272 context.current.paintOffset == LayoutPoint()); | 286 context.current.paintOffset == LayoutPoint()); | 
| 273 | 287 | 
| 274 if (object.needsPaintPropertyUpdate()) { | 288 if (object.needsPaintPropertyUpdate()) { | 
| 275 AffineTransform transform = object.localToSVGParentTransform(); | 289 AffineTransform transform = object.localToSVGParentTransform(); | 
| 276 // TODO(pdr): Check for the presence of a transform instead of the value. | 290 // TODO(pdr): Check for the presence of a transform instead of the value. | 
| 277 // Checking for an identity matrix will cause the property tree structure | 291 // Checking for an identity matrix will cause the property tree structure | 
| 278 // to change during animations if the animation passes through the | 292 // to change during animations if the animation passes through the | 
| 279 // identity matrix. | 293 // identity matrix. | 
| 280 if (!transform.isIdentity()) { | 294 if (!transform.isIdentity()) { | 
| 281 // The origin is included in the local transform, so leave origin empty. | 295 // The origin is included in the local transform, so leave origin empty. | 
| 282 object.getMutableForPainting().ensurePaintProperties().updateTransform( | 296 auto& properties = object.getMutableForPainting().ensurePaintProperties(); | 
| 297 context.forceSubtreeUpdate |= properties.updateTransform( | |
| 283 context.current.transform, TransformationMatrix(transform), | 298 context.current.transform, TransformationMatrix(transform), | 
| 284 FloatPoint3D()); | 299 FloatPoint3D()); | 
| 285 } else { | 300 } else { | 
| 286 if (auto* properties = object.getMutableForPainting().paintProperties()) | 301 if (auto* properties = object.getMutableForPainting().paintProperties()) | 
| 287 properties->clearTransform(); | 302 context.forceSubtreeUpdate |= properties->clearTransform(); | 
| 288 } | 303 } | 
| 289 } | 304 } | 
| 290 | 305 | 
| 291 if (object.paintProperties() && object.paintProperties()->transform()) { | 306 if (object.paintProperties() && object.paintProperties()->transform()) { | 
| 292 context.current.transform = object.paintProperties()->transform(); | 307 context.current.transform = object.paintProperties()->transform(); | 
| 293 context.current.shouldFlattenInheritedTransform = false; | 308 context.current.shouldFlattenInheritedTransform = false; | 
| 294 context.current.renderingContextID = 0; | 309 context.current.renderingContextID = 0; | 
| 295 } | 310 } | 
| 296 } | 311 } | 
| 297 | 312 | 
| (...skipping 16 matching lines...) Expand all Loading... | |
| 314 ComputedStyle::IncludeIndependentTransformProperties); | 329 ComputedStyle::IncludeIndependentTransformProperties); | 
| 315 | 330 | 
| 316 // TODO(trchen): transform-style should only be respected if a PaintLayer | 331 // TODO(trchen): transform-style should only be respected if a PaintLayer | 
| 317 // is created. | 332 // is created. | 
| 318 // If a node with transform-style: preserve-3d does not exist in an | 333 // If a node with transform-style: preserve-3d does not exist in an | 
| 319 // existing rendering context, it establishes a new one. | 334 // existing rendering context, it establishes a new one. | 
| 320 unsigned renderingContextID = context.current.renderingContextID; | 335 unsigned renderingContextID = context.current.renderingContextID; | 
| 321 if (style.preserves3D() && !renderingContextID) | 336 if (style.preserves3D() && !renderingContextID) | 
| 322 renderingContextID = PtrHash<const LayoutObject>::hash(&object); | 337 renderingContextID = PtrHash<const LayoutObject>::hash(&object); | 
| 323 | 338 | 
| 324 object.getMutableForPainting().ensurePaintProperties().updateTransform( | 339 auto& properties = object.getMutableForPainting().ensurePaintProperties(); | 
| 340 context.forceSubtreeUpdate |= properties.updateTransform( | |
| 325 context.current.transform, matrix, | 341 context.current.transform, matrix, | 
| 326 transformOrigin(toLayoutBox(object)), | 342 transformOrigin(toLayoutBox(object)), | 
| 327 context.current.shouldFlattenInheritedTransform, renderingContextID); | 343 context.current.shouldFlattenInheritedTransform, renderingContextID); | 
| 328 } else { | 344 } else { | 
| 329 if (auto* properties = object.getMutableForPainting().paintProperties()) | 345 if (auto* properties = object.getMutableForPainting().paintProperties()) | 
| 330 properties->clearTransform(); | 346 context.forceSubtreeUpdate |= properties->clearTransform(); | 
| 331 } | 347 } | 
| 332 } | 348 } | 
| 333 | 349 | 
| 334 const auto* properties = object.paintProperties(); | 350 const auto* properties = object.paintProperties(); | 
| 335 if (properties && properties->transform()) { | 351 if (properties && properties->transform()) { | 
| 336 context.current.transform = properties->transform(); | 352 context.current.transform = properties->transform(); | 
| 337 if (object.styleRef().preserves3D()) { | 353 if (object.styleRef().preserves3D()) { | 
| 338 context.current.renderingContextID = | 354 context.current.renderingContextID = | 
| 339 properties->transform()->renderingContextID(); | 355 properties->transform()->renderingContextID(); | 
| 340 context.current.shouldFlattenInheritedTransform = false; | 356 context.current.shouldFlattenInheritedTransform = false; | 
| 341 } else { | 357 } else { | 
| 342 context.current.renderingContextID = 0; | 358 context.current.renderingContextID = 0; | 
| 343 context.current.shouldFlattenInheritedTransform = true; | 359 context.current.shouldFlattenInheritedTransform = true; | 
| 344 } | 360 } | 
| 345 } | 361 } | 
| 346 } | 362 } | 
| 347 | 363 | 
| 348 void PaintPropertyTreeBuilder::updateEffect( | 364 void PaintPropertyTreeBuilder::updateEffect( | 
| 349 const LayoutObject& object, | 365 const LayoutObject& object, | 
| 350 PaintPropertyTreeBuilderContext& context) { | 366 PaintPropertyTreeBuilderContext& context) { | 
| 351 const ComputedStyle& style = object.styleRef(); | 367 const ComputedStyle& style = object.styleRef(); | 
| 352 | 368 | 
| 353 if (!style.isStackingContext()) { | 369 if (!style.isStackingContext()) { | 
| 354 if (object.needsPaintPropertyUpdate()) { | 370 if (object.needsPaintPropertyUpdate()) { | 
| 355 if (auto* properties = object.getMutableForPainting().paintProperties()) | 371 if (auto* properties = object.getMutableForPainting().paintProperties()) | 
| 356 properties->clearEffect(); | 372 context.forceSubtreeUpdate |= properties->clearEffect(); | 
| 357 } | 373 } | 
| 358 return; | 374 return; | 
| 359 } | 375 } | 
| 360 | 376 | 
| 361 // TODO(trchen): Can't omit effect node if we have 3D children. | 377 // TODO(trchen): Can't omit effect node if we have 3D children. | 
| 362 // TODO(trchen): Can't omit effect node if we have blending children. | 378 // TODO(trchen): Can't omit effect node if we have blending children. | 
| 363 if (object.needsPaintPropertyUpdate()) { | 379 if (object.needsPaintPropertyUpdate()) { | 
| 364 bool effectNodeNeeded = false; | 380 bool effectNodeNeeded = false; | 
| 365 | 381 | 
| 366 float opacity = style.opacity(); | 382 float opacity = style.opacity(); | 
| (...skipping 30 matching lines...) Expand all Loading... | |
| 397 if (!filter.isEmpty()) { | 413 if (!filter.isEmpty()) { | 
| 398 effectNodeNeeded = true; | 414 effectNodeNeeded = true; | 
| 399 outputClip = context.current.clip; | 415 outputClip = context.current.clip; | 
| 400 | 416 | 
| 401 // TODO(trchen): A filter may contain spatial operations such that an | 417 // TODO(trchen): A filter may contain spatial operations such that an | 
| 402 // output pixel may depend on an input pixel outside of the output clip. | 418 // output pixel may depend on an input pixel outside of the output clip. | 
| 403 // We should generate a special clip node to represent this expansion. | 419 // We should generate a special clip node to represent this expansion. | 
| 404 } | 420 } | 
| 405 | 421 | 
| 406 if (effectNodeNeeded) { | 422 if (effectNodeNeeded) { | 
| 407 object.getMutableForPainting().ensurePaintProperties().updateEffect( | 423 auto& properties = object.getMutableForPainting().ensurePaintProperties(); | 
| 424 context.forceSubtreeUpdate |= properties.updateEffect( | |
| 408 context.currentEffect, context.current.transform, outputClip, | 425 context.currentEffect, context.current.transform, outputClip, | 
| 409 std::move(filter), opacity); | 426 std::move(filter), opacity); | 
| 410 } else { | 427 } else { | 
| 411 if (auto* properties = object.getMutableForPainting().paintProperties()) | 428 if (auto* properties = object.getMutableForPainting().paintProperties()) | 
| 412 properties->clearEffect(); | 429 context.forceSubtreeUpdate |= properties->clearEffect(); | 
| 413 } | 430 } | 
| 414 } | 431 } | 
| 415 | 432 | 
| 416 const auto* properties = object.paintProperties(); | 433 const auto* properties = object.paintProperties(); | 
| 417 if (properties && properties->effect()) { | 434 if (properties && properties->effect()) { | 
| 418 context.currentEffect = properties->effect(); | 435 context.currentEffect = properties->effect(); | 
| 419 if (!properties->effect()->filter().isEmpty()) { | 436 if (!properties->effect()->filter().isEmpty()) { | 
| 420 // TODO(trchen): Change input clip to expansion hint once implemented. | 437 // TODO(trchen): Change input clip to expansion hint once implemented. | 
| 421 const ClipPaintPropertyNode* inputClip = | 438 const ClipPaintPropertyNode* inputClip = | 
| 422 properties->effect()->outputClip(); | 439 properties->effect()->outputClip(); | 
| 423 context.inputClipOfCurrentEffect = context.current.clip = | 440 context.inputClipOfCurrentEffect = context.current.clip = | 
| 424 context.absolutePosition.clip = context.fixedPosition.clip = | 441 context.absolutePosition.clip = context.fixedPosition.clip = | 
| 425 inputClip; | 442 inputClip; | 
| 426 } | 443 } | 
| 427 } | 444 } | 
| 428 } | 445 } | 
| 429 | 446 | 
| 430 void PaintPropertyTreeBuilder::updateCssClip( | 447 void PaintPropertyTreeBuilder::updateCssClip( | 
| 431 const LayoutObject& object, | 448 const LayoutObject& object, | 
| 432 PaintPropertyTreeBuilderContext& context) { | 449 PaintPropertyTreeBuilderContext& context) { | 
| 433 if (object.needsPaintPropertyUpdate()) { | 450 if (object.needsPaintPropertyUpdate()) { | 
| 434 if (object.hasClip()) { | 451 if (object.hasClip()) { | 
| 435 // Create clip node for descendants that are not fixed position. | 452 // Create clip node for descendants that are not fixed position. | 
| 436 // We don't have to setup context.absolutePosition.clip here because this | 453 // We don't have to setup context.absolutePosition.clip here because this | 
| 437 // object must be a container for absolute position descendants, and will | 454 // object must be a container for absolute position descendants, and will | 
| 438 // copy from in-flow context later at updateOutOfFlowContext() step. | 455 // copy from in-flow context later at updateOutOfFlowContext() step. | 
| 439 DCHECK(object.canContainAbsolutePositionObjects()); | 456 DCHECK(object.canContainAbsolutePositionObjects()); | 
| 440 LayoutRect clipRect = | 457 LayoutRect clipRect = | 
| 441 toLayoutBox(object).clipRect(context.current.paintOffset); | 458 toLayoutBox(object).clipRect(context.current.paintOffset); | 
| 442 object.getMutableForPainting().ensurePaintProperties().updateCssClip( | 459 auto& properties = object.getMutableForPainting().ensurePaintProperties(); | 
| 460 context.forceSubtreeUpdate |= properties.updateCssClip( | |
| 443 context.current.clip, context.current.transform, | 461 context.current.clip, context.current.transform, | 
| 444 FloatRoundedRect(FloatRect(clipRect))); | 462 FloatRoundedRect(FloatRect(clipRect))); | 
| 445 } else { | 463 } else { | 
| 446 if (auto* properties = object.getMutableForPainting().paintProperties()) | 464 if (auto* properties = object.getMutableForPainting().paintProperties()) | 
| 447 properties->clearCssClip(); | 465 context.forceSubtreeUpdate |= properties->clearCssClip(); | 
| 448 } | 466 } | 
| 449 } | 467 } | 
| 450 | 468 | 
| 451 const auto* properties = object.paintProperties(); | 469 const auto* properties = object.paintProperties(); | 
| 452 if (properties && properties->cssClip()) | 470 if (properties && properties->cssClip()) | 
| 453 context.current.clip = properties->cssClip(); | 471 context.current.clip = properties->cssClip(); | 
| 454 } | 472 } | 
| 455 | 473 | 
| 456 void PaintPropertyTreeBuilder::updateLocalBorderBoxContext( | 474 void PaintPropertyTreeBuilder::updateLocalBorderBoxContext( | 
| 457 const LayoutObject& object, | 475 const LayoutObject& object, | 
| (...skipping 16 matching lines...) Expand all Loading... | |
| 474 context.current.scroll))); | 492 context.current.scroll))); | 
| 475 object.getMutableForPainting() | 493 object.getMutableForPainting() | 
| 476 .ensurePaintProperties() | 494 .ensurePaintProperties() | 
| 477 .setLocalBorderBoxProperties(std::move(borderBoxContext)); | 495 .setLocalBorderBoxProperties(std::move(borderBoxContext)); | 
| 478 } | 496 } | 
| 479 } | 497 } | 
| 480 | 498 | 
| 481 // TODO(trchen): Remove this once we bake the paint offset into frameRect. | 499 // TODO(trchen): Remove this once we bake the paint offset into frameRect. | 
| 482 void PaintPropertyTreeBuilder::updateScrollbarPaintOffset( | 500 void PaintPropertyTreeBuilder::updateScrollbarPaintOffset( | 
| 483 const LayoutObject& object, | 501 const LayoutObject& object, | 
| 484 const PaintPropertyTreeBuilderContext& context) { | 502 PaintPropertyTreeBuilderContext& context) { | 
| 485 if (!object.needsPaintPropertyUpdate()) | 503 if (!object.needsPaintPropertyUpdate()) | 
| 486 return; | 504 return; | 
| 487 | 505 | 
| 488 bool needsScrollbarPaintOffset = false; | 506 bool needsScrollbarPaintOffset = false; | 
| 489 IntPoint roundedPaintOffset = roundedIntPoint(context.current.paintOffset); | 507 IntPoint roundedPaintOffset = roundedIntPoint(context.current.paintOffset); | 
| 490 if (roundedPaintOffset != IntPoint() && object.isBoxModelObject()) { | 508 if (roundedPaintOffset != IntPoint() && object.isBoxModelObject()) { | 
| 491 if (auto* area = toLayoutBoxModelObject(object).getScrollableArea()) { | 509 if (auto* area = toLayoutBoxModelObject(object).getScrollableArea()) { | 
| 492 if (area->horizontalScrollbar() || area->verticalScrollbar()) { | 510 if (area->horizontalScrollbar() || area->verticalScrollbar()) { | 
| 493 auto paintOffset = TransformationMatrix().translate( | 511 auto paintOffset = TransformationMatrix().translate( | 
| 494 roundedPaintOffset.x(), roundedPaintOffset.y()); | 512 roundedPaintOffset.x(), roundedPaintOffset.y()); | 
| 495 object.getMutableForPainting() | 513 auto& properties = | 
| 496 .ensurePaintProperties() | 514 object.getMutableForPainting().ensurePaintProperties(); | 
| 497 .updateScrollbarPaintOffset(context.current.transform, paintOffset, | 515 context.forceSubtreeUpdate |= properties.updateScrollbarPaintOffset( | 
| 498 FloatPoint3D()); | 516 context.current.transform, paintOffset, FloatPoint3D()); | 
| 499 needsScrollbarPaintOffset = true; | 517 needsScrollbarPaintOffset = true; | 
| 500 } | 518 } | 
| 501 } | 519 } | 
| 502 } | 520 } | 
| 503 | 521 | 
| 504 auto* properties = object.getMutableForPainting().paintProperties(); | 522 auto* properties = object.getMutableForPainting().paintProperties(); | 
| 505 if (!needsScrollbarPaintOffset && properties) | 523 if (!needsScrollbarPaintOffset && properties) | 
| 506 properties->clearScrollbarPaintOffset(); | 524 context.forceSubtreeUpdate |= properties->clearScrollbarPaintOffset(); | 
| 507 } | 525 } | 
| 508 | 526 | 
| 509 void PaintPropertyTreeBuilder::updateOverflowClip( | 527 void PaintPropertyTreeBuilder::updateOverflowClip( | 
| 510 const LayoutObject& object, | 528 const LayoutObject& object, | 
| 511 PaintPropertyTreeBuilderContext& context) { | 529 PaintPropertyTreeBuilderContext& context) { | 
| 512 if (!object.isBox()) | 530 if (!object.isBox()) | 
| 513 return; | 531 return; | 
| 514 | 532 | 
| 515 if (object.needsPaintPropertyUpdate()) { | 533 if (object.needsPaintPropertyUpdate()) { | 
| 516 const LayoutBox& box = toLayoutBox(object); | 534 const LayoutBox& box = toLayoutBox(object); | 
| 517 // The <input> elements can't have contents thus CSS overflow property | 535 // The <input> elements can't have contents thus CSS overflow property | 
| 518 // doesn't apply. However for layout purposes we do generate child layout | 536 // doesn't apply. However for layout purposes we do generate child layout | 
| 519 // objects for them, e.g. button label. We should clip the overflow from | 537 // objects for them, e.g. button label. We should clip the overflow from | 
| 520 // those children. This is called control clip and we technically treat them | 538 // those children. This is called control clip and we technically treat them | 
| 521 // like overflow clip. | 539 // like overflow clip. | 
| 522 LayoutRect clipRect; | 540 LayoutRect clipRect; | 
| 523 if (box.hasControlClip()) { | 541 if (box.hasControlClip()) { | 
| 524 clipRect = box.controlClipRect(context.current.paintOffset); | 542 clipRect = box.controlClipRect(context.current.paintOffset); | 
| 525 } else if (box.hasOverflowClip() || box.styleRef().containsPaint() || | 543 } else if (box.hasOverflowClip() || box.styleRef().containsPaint() || | 
| 526 (box.isSVGRoot() && | 544 (box.isSVGRoot() && | 
| 527 toLayoutSVGRoot(box).shouldApplyViewportClip())) { | 545 toLayoutSVGRoot(box).shouldApplyViewportClip())) { | 
| 528 clipRect = LayoutRect(pixelSnappedIntRect( | 546 clipRect = LayoutRect(pixelSnappedIntRect( | 
| 529 box.overflowClipRect(context.current.paintOffset))); | 547 box.overflowClipRect(context.current.paintOffset))); | 
| 530 } else { | 548 } else { | 
| 531 if (auto* properties = object.getMutableForPainting().paintProperties()) { | 549 if (auto* properties = object.getMutableForPainting().paintProperties()) { | 
| 532 properties->clearInnerBorderRadiusClip(); | 550 context.forceSubtreeUpdate |= properties->clearInnerBorderRadiusClip(); | 
| 533 properties->clearOverflowClip(); | 551 context.forceSubtreeUpdate |= properties->clearOverflowClip(); | 
| 534 } | 552 } | 
| 535 return; | 553 return; | 
| 536 } | 554 } | 
| 537 | 555 | 
| 556 auto& properties = object.getMutableForPainting().ensurePaintProperties(); | |
| 538 const auto* currentClip = context.current.clip; | 557 const auto* currentClip = context.current.clip; | 
| 539 if (box.styleRef().hasBorderRadius()) { | 558 if (box.styleRef().hasBorderRadius()) { | 
| 540 auto innerBorder = box.styleRef().getRoundedInnerBorderFor( | 559 auto innerBorder = box.styleRef().getRoundedInnerBorderFor( | 
| 541 LayoutRect(context.current.paintOffset, box.size())); | 560 LayoutRect(context.current.paintOffset, box.size())); | 
| 542 object.getMutableForPainting() | 561 context.forceSubtreeUpdate |= properties.updateInnerBorderRadiusClip( | 
| 543 .ensurePaintProperties() | 562 context.current.clip, context.current.transform, innerBorder); | 
| 544 .updateInnerBorderRadiusClip(context.current.clip, | 563 currentClip = properties.innerBorderRadiusClip(); | 
| 545 context.current.transform, innerBorder); | 564 } else { | 
| 546 currentClip = object.paintProperties()->innerBorderRadiusClip(); | 565 context.forceSubtreeUpdate |= properties.clearInnerBorderRadiusClip(); | 
| 547 } else if (auto* properties = | |
| 548 object.getMutableForPainting().paintProperties()) { | |
| 549 properties->clearInnerBorderRadiusClip(); | |
| 550 } | 566 } | 
| 551 | 567 | 
| 552 object.getMutableForPainting().ensurePaintProperties().updateOverflowClip( | 568 context.forceSubtreeUpdate |= | 
| 553 currentClip, context.current.transform, | 569 properties.updateOverflowClip(currentClip, context.current.transform, | 
| 554 FloatRoundedRect(FloatRect(clipRect))); | 570 FloatRoundedRect(FloatRect(clipRect))); | 
| 555 } | 571 } | 
| 556 | 572 | 
| 557 const auto* properties = object.paintProperties(); | 573 const auto* properties = object.paintProperties(); | 
| 558 if (properties && properties->overflowClip()) | 574 if (properties && properties->overflowClip()) | 
| 559 context.current.clip = properties->overflowClip(); | 575 context.current.clip = properties->overflowClip(); | 
| 560 } | 576 } | 
| 561 | 577 | 
| 562 static FloatPoint perspectiveOrigin(const LayoutBox& box) { | 578 static FloatPoint perspectiveOrigin(const LayoutBox& box) { | 
| 563 const ComputedStyle& style = box.styleRef(); | 579 const ComputedStyle& style = box.styleRef(); | 
| 564 FloatSize borderBoxSize(box.size()); | 580 FloatSize borderBoxSize(box.size()); | 
| 565 return FloatPoint( | 581 return FloatPoint( | 
| 566 floatValueForLength(style.perspectiveOriginX(), borderBoxSize.width()), | 582 floatValueForLength(style.perspectiveOriginX(), borderBoxSize.width()), | 
| 567 floatValueForLength(style.perspectiveOriginY(), borderBoxSize.height())); | 583 floatValueForLength(style.perspectiveOriginY(), borderBoxSize.height())); | 
| 568 } | 584 } | 
| 569 | 585 | 
| 570 void PaintPropertyTreeBuilder::updatePerspective( | 586 void PaintPropertyTreeBuilder::updatePerspective( | 
| 571 const LayoutObject& object, | 587 const LayoutObject& object, | 
| 572 PaintPropertyTreeBuilderContext& context) { | 588 PaintPropertyTreeBuilderContext& context) { | 
| 573 if (object.needsPaintPropertyUpdate()) { | 589 if (object.needsPaintPropertyUpdate()) { | 
| 574 const ComputedStyle& style = object.styleRef(); | 590 const ComputedStyle& style = object.styleRef(); | 
| 575 if (object.isBox() && style.hasPerspective()) { | 591 if (object.isBox() && style.hasPerspective()) { | 
| 576 // The perspective node must not flatten (else nothing will get | 592 // The perspective node must not flatten (else nothing will get | 
| 577 // perspective), but it should still extend the rendering context as | 593 // perspective), but it should still extend the rendering context as | 
| 578 // most transform nodes do. | 594 // most transform nodes do. | 
| 579 TransformationMatrix matrix = | 595 TransformationMatrix matrix = | 
| 580 TransformationMatrix().applyPerspective(style.perspective()); | 596 TransformationMatrix().applyPerspective(style.perspective()); | 
| 581 FloatPoint3D origin = perspectiveOrigin(toLayoutBox(object)) + | 597 FloatPoint3D origin = perspectiveOrigin(toLayoutBox(object)) + | 
| 582 toLayoutSize(context.current.paintOffset); | 598 toLayoutSize(context.current.paintOffset); | 
| 583 object.getMutableForPainting().ensurePaintProperties().updatePerspective( | 599 auto& properties = object.getMutableForPainting().ensurePaintProperties(); | 
| 600 context.forceSubtreeUpdate |= properties.updatePerspective( | |
| 584 context.current.transform, matrix, origin, | 601 context.current.transform, matrix, origin, | 
| 585 context.current.shouldFlattenInheritedTransform, | 602 context.current.shouldFlattenInheritedTransform, | 
| 586 context.current.renderingContextID); | 603 context.current.renderingContextID); | 
| 587 } else { | 604 } else { | 
| 588 if (auto* properties = object.getMutableForPainting().paintProperties()) | 605 if (auto* properties = object.getMutableForPainting().paintProperties()) | 
| 589 properties->clearPerspective(); | 606 context.forceSubtreeUpdate |= properties->clearPerspective(); | 
| 590 } | 607 } | 
| 591 } | 608 } | 
| 592 | 609 | 
| 593 const auto* properties = object.paintProperties(); | 610 const auto* properties = object.paintProperties(); | 
| 594 if (properties && properties->perspective()) { | 611 if (properties && properties->perspective()) { | 
| 595 context.current.transform = properties->perspective(); | 612 context.current.transform = properties->perspective(); | 
| 596 context.current.shouldFlattenInheritedTransform = false; | 613 context.current.shouldFlattenInheritedTransform = false; | 
| 597 } | 614 } | 
| 598 } | 615 } | 
| 599 | 616 | 
| 600 void PaintPropertyTreeBuilder::updateSvgLocalToBorderBoxTransform( | 617 void PaintPropertyTreeBuilder::updateSvgLocalToBorderBoxTransform( | 
| 601 const LayoutObject& object, | 618 const LayoutObject& object, | 
| 602 PaintPropertyTreeBuilderContext& context) { | 619 PaintPropertyTreeBuilderContext& context) { | 
| 603 if (!object.isSVGRoot()) | 620 if (!object.isSVGRoot()) | 
| 604 return; | 621 return; | 
| 605 | 622 | 
| 606 if (object.needsPaintPropertyUpdate()) { | 623 if (object.needsPaintPropertyUpdate()) { | 
| 607 AffineTransform transformToBorderBox = | 624 AffineTransform transformToBorderBox = | 
| 608 SVGRootPainter(toLayoutSVGRoot(object)) | 625 SVGRootPainter(toLayoutSVGRoot(object)) | 
| 609 .transformToPixelSnappedBorderBox(context.current.paintOffset); | 626 .transformToPixelSnappedBorderBox(context.current.paintOffset); | 
| 610 if (!transformToBorderBox.isIdentity()) { | 627 if (!transformToBorderBox.isIdentity()) { | 
| 611 object.getMutableForPainting() | 628 auto& properties = object.getMutableForPainting().ensurePaintProperties(); | 
| 612 .ensurePaintProperties() | 629 context.forceSubtreeUpdate |= | 
| 613 .updateSvgLocalToBorderBoxTransform( | 630 properties.updateSvgLocalToBorderBoxTransform( | 
| 614 context.current.transform, transformToBorderBox, FloatPoint3D()); | 631 context.current.transform, transformToBorderBox, FloatPoint3D()); | 
| 615 } else { | 632 } else { | 
| 616 if (auto* properties = object.getMutableForPainting().paintProperties()) | 633 if (auto* properties = object.getMutableForPainting().paintProperties()) { | 
| 617 properties->clearSvgLocalToBorderBoxTransform(); | 634 context.forceSubtreeUpdate |= | 
| 635 properties->clearSvgLocalToBorderBoxTransform(); | |
| 636 } | |
| 618 } | 637 } | 
| 619 } | 638 } | 
| 620 | 639 | 
| 621 const auto* properties = object.paintProperties(); | 640 const auto* properties = object.paintProperties(); | 
| 622 if (properties && properties->svgLocalToBorderBoxTransform()) { | 641 if (properties && properties->svgLocalToBorderBoxTransform()) { | 
| 623 context.current.transform = properties->svgLocalToBorderBoxTransform(); | 642 context.current.transform = properties->svgLocalToBorderBoxTransform(); | 
| 624 context.current.shouldFlattenInheritedTransform = false; | 643 context.current.shouldFlattenInheritedTransform = false; | 
| 625 context.current.renderingContextID = 0; | 644 context.current.renderingContextID = 0; | 
| 626 } | 645 } | 
| 627 // The paint offset is included in |transformToBorderBox| so SVG does not need | 646 // The paint offset is included in |transformToBorderBox| so SVG does not need | 
| 628 // to handle paint offset internally. | 647 // to handle paint offset internally. | 
| 629 context.current.paintOffset = LayoutPoint(); | 648 context.current.paintOffset = LayoutPoint(); | 
| 630 } | 649 } | 
| 631 | 650 | 
| 632 void PaintPropertyTreeBuilder::updateScrollAndScrollTranslation( | 651 void PaintPropertyTreeBuilder::updateScrollAndScrollTranslation( | 
| 633 const LayoutObject& object, | 652 const LayoutObject& object, | 
| 634 PaintPropertyTreeBuilderContext& context) { | 653 PaintPropertyTreeBuilderContext& context) { | 
| 635 if (object.needsPaintPropertyUpdate()) { | 654 if (object.needsPaintPropertyUpdate()) { | 
| 636 if (object.hasOverflowClip()) { | 655 if (object.hasOverflowClip()) { | 
| 637 const LayoutBox& box = toLayoutBox(object); | 656 const LayoutBox& box = toLayoutBox(object); | 
| 638 const PaintLayerScrollableArea* scrollableArea = box.getScrollableArea(); | 657 const PaintLayerScrollableArea* scrollableArea = box.getScrollableArea(); | 
| 639 IntSize scrollOffset = box.scrolledContentOffset(); | 658 IntSize scrollOffset = box.scrolledContentOffset(); | 
| 640 if (!scrollOffset.isZero() || scrollableArea->scrollsOverflow()) { | 659 if (!scrollOffset.isZero() || scrollableArea->scrollsOverflow()) { | 
| 660 auto& properties = | |
| 661 object.getMutableForPainting().ensurePaintProperties(); | |
| 641 TransformationMatrix matrix = TransformationMatrix().translate( | 662 TransformationMatrix matrix = TransformationMatrix().translate( | 
| 642 -scrollOffset.width(), -scrollOffset.height()); | 663 -scrollOffset.width(), -scrollOffset.height()); | 
| 643 object.getMutableForPainting() | 664 context.forceSubtreeUpdate |= properties.updateScrollTranslation( | 
| 644 .ensurePaintProperties() | 665 context.current.transform, matrix, FloatPoint3D(), | 
| 645 .updateScrollTranslation( | 666 context.current.shouldFlattenInheritedTransform, | 
| 646 context.current.transform, matrix, FloatPoint3D(), | 667 context.current.renderingContextID); | 
| 647 context.current.shouldFlattenInheritedTransform, | |
| 648 context.current.renderingContextID); | |
| 649 | 668 | 
| 650 IntSize scrollClip = scrollableArea->visibleContentRect().size(); | 669 IntSize scrollClip = scrollableArea->visibleContentRect().size(); | 
| 651 IntSize scrollBounds = scrollableArea->contentsSize(); | 670 IntSize scrollBounds = scrollableArea->contentsSize(); | 
| 652 bool userScrollableHorizontal = | 671 bool userScrollableHorizontal = | 
| 653 scrollableArea->userInputScrollable(HorizontalScrollbar); | 672 scrollableArea->userInputScrollable(HorizontalScrollbar); | 
| 654 bool userScrollableVertical = | 673 bool userScrollableVertical = | 
| 655 scrollableArea->userInputScrollable(VerticalScrollbar); | 674 scrollableArea->userInputScrollable(VerticalScrollbar); | 
| 656 MainThreadScrollingReasons reasons = 0; | 675 MainThreadScrollingReasons reasons = 0; | 
| 657 if (!object.document().settings()->threadedScrollingEnabled()) | 676 if (!object.document().settings()->threadedScrollingEnabled()) | 
| 658 reasons |= MainThreadScrollingReason::kThreadedScrollingDisabled; | 677 reasons |= MainThreadScrollingReason::kThreadedScrollingDisabled; | 
| 659 // Checking for descendants in the layout tree has two downsides: | 678 // Checking for descendants in the layout tree has two downsides: | 
| 660 // 1) There can be more descendants in layout order than in paint | 679 // 1) There can be more descendants in layout order than in paint | 
| 661 // order (e.g., fixed position objects). | 680 // order (e.g., fixed position objects). | 
| 662 // 2) Iterating overall all background attachment fixed objects for | 681 // 2) Iterating overall all background attachment fixed objects for | 
| 663 // every scroll node can be slow, though there will be no objects | 682 // every scroll node can be slow, though there will be no objects | 
| 664 // in the common case. | 683 // in the common case. | 
| 665 const FrameView& frameView = *object.frameView(); | 684 const FrameView& frameView = *object.frameView(); | 
| 666 if (frameView.hasBackgroundAttachmentFixedDescendants(object)) { | 685 if (frameView.hasBackgroundAttachmentFixedDescendants(object)) { | 
| 667 reasons |= | 686 reasons |= | 
| 668 MainThreadScrollingReason::kHasBackgroundAttachmentFixedObjects; | 687 MainThreadScrollingReason::kHasBackgroundAttachmentFixedObjects; | 
| 669 } | 688 } | 
| 670 object.getMutableForPainting().ensurePaintProperties().updateScroll( | 689 context.forceSubtreeUpdate |= properties.updateScroll( | 
| 671 context.current.scroll, | 690 context.current.scroll, properties.scrollTranslation(), scrollClip, | 
| 672 object.paintProperties()->scrollTranslation(), scrollClip, | |
| 673 scrollBounds, userScrollableHorizontal, userScrollableVertical, | 691 scrollBounds, userScrollableHorizontal, userScrollableVertical, | 
| 674 reasons); | 692 reasons); | 
| 675 } else { | 693 } else { | 
| 676 // Ensure pre-existing properties are cleared when there is no | 694 // Ensure pre-existing properties are cleared when there is no | 
| 677 // scrolling. | 695 // scrolling. | 
| 678 auto* properties = object.getMutableForPainting().paintProperties(); | 696 auto* properties = object.getMutableForPainting().paintProperties(); | 
| 679 if (properties) { | 697 if (properties) { | 
| 680 properties->clearScrollTranslation(); | 698 context.forceSubtreeUpdate |= properties->clearScrollTranslation(); | 
| 681 properties->clearScroll(); | 699 context.forceSubtreeUpdate |= properties->clearScroll(); | 
| 682 } | 700 } | 
| 683 } | 701 } | 
| 684 } | 702 } | 
| 685 } | 703 } | 
| 686 | 704 | 
| 687 if (object.paintProperties() && object.paintProperties()->scroll()) { | 705 if (object.paintProperties() && object.paintProperties()->scroll()) { | 
| 688 context.current.transform = object.paintProperties()->scrollTranslation(); | 706 context.current.transform = object.paintProperties()->scrollTranslation(); | 
| 689 context.current.scroll = object.paintProperties()->scroll(); | 707 context.current.scroll = object.paintProperties()->scroll(); | 
| 690 context.current.shouldFlattenInheritedTransform = false; | 708 context.current.shouldFlattenInheritedTransform = false; | 
| 691 } | 709 } | 
| (...skipping 29 matching lines...) Expand all Loading... | |
| 721 // need to insert the clip here if we are not a containing block ancestor of | 739 // need to insert the clip here if we are not a containing block ancestor of | 
| 722 // them. | 740 // them. | 
| 723 auto* cssClip = object.getMutableForPainting().paintProperties()->cssClip(); | 741 auto* cssClip = object.getMutableForPainting().paintProperties()->cssClip(); | 
| 724 | 742 | 
| 725 // Before we actually create anything, check whether in-flow context and | 743 // Before we actually create anything, check whether in-flow context and | 
| 726 // fixed-position context has exactly the same clip. Reuse if possible. | 744 // fixed-position context has exactly the same clip. Reuse if possible. | 
| 727 if (context.fixedPosition.clip == cssClip->parent()) { | 745 if (context.fixedPosition.clip == cssClip->parent()) { | 
| 728 context.fixedPosition.clip = cssClip; | 746 context.fixedPosition.clip = cssClip; | 
| 729 } else { | 747 } else { | 
| 730 if (object.needsPaintPropertyUpdate()) { | 748 if (object.needsPaintPropertyUpdate()) { | 
| 731 object.getMutableForPainting() | 749 auto& properties = | 
| 732 .ensurePaintProperties() | 750 object.getMutableForPainting().ensurePaintProperties(); | 
| 733 .updateCssClipFixedPosition(context.fixedPosition.clip, | 751 context.forceSubtreeUpdate |= properties.updateCssClipFixedPosition( | 
| 734 const_cast<TransformPaintPropertyNode*>( | 752 context.fixedPosition.clip, const_cast<TransformPaintPropertyNode*>( | 
| 735 cssClip->localTransformSpace()), | 753 cssClip->localTransformSpace()), | 
| 736 cssClip->clipRect()); | 754 cssClip->clipRect()); | 
| 737 } | 755 } | 
| 738 const auto* properties = object.paintProperties(); | 756 const auto* properties = object.paintProperties(); | 
| 739 if (properties && properties->cssClipFixedPosition()) | 757 if (properties && properties->cssClipFixedPosition()) | 
| 740 context.fixedPosition.clip = properties->cssClipFixedPosition(); | 758 context.fixedPosition.clip = properties->cssClipFixedPosition(); | 
| 741 return; | 759 return; | 
| 742 } | 760 } | 
| 743 } | 761 } | 
| 744 | 762 | 
| 745 if (object.needsPaintPropertyUpdate()) { | 763 if (object.needsPaintPropertyUpdate()) { | 
| 746 if (auto* properties = object.getMutableForPainting().paintProperties()) | 764 if (auto* properties = object.getMutableForPainting().paintProperties()) | 
| 747 properties->clearCssClipFixedPosition(); | 765 context.forceSubtreeUpdate |= properties->clearCssClipFixedPosition(); | 
| 748 } | 766 } | 
| 749 } | 767 } | 
| 750 | 768 | 
| 751 // Override ContainingBlockContext based on the properties of a containing block | 769 // Override ContainingBlockContext based on the properties of a containing block | 
| 752 // that was previously walked in a subtree other than the current subtree being | 770 // that was previously walked in a subtree other than the current subtree being | 
| 753 // walked. Used for out-of-flow positioned descendants of multi-column spanner | 771 // walked. Used for out-of-flow positioned descendants of multi-column spanner | 
| 754 // when the containing block is not in the normal tree walk order. | 772 // when the containing block is not in the normal tree walk order. | 
| 755 // For example: | 773 // For example: | 
| 756 // <div id="columns" style="columns: 2"> | 774 // <div id="columns" style="columns: 2"> | 
| 757 // <div id="relative" style="position: relative"> | 775 // <div id="relative" style="position: relative"> | 
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 868 } | 886 } | 
| 869 } | 887 } | 
| 870 } | 888 } | 
| 871 | 889 | 
| 872 void PaintPropertyTreeBuilder::updatePropertiesForSelf( | 890 void PaintPropertyTreeBuilder::updatePropertiesForSelf( | 
| 873 const LayoutObject& object, | 891 const LayoutObject& object, | 
| 874 PaintPropertyTreeBuilderContext& context) { | 892 PaintPropertyTreeBuilderContext& context) { | 
| 875 if (!object.isBoxModelObject() && !object.isSVG()) | 893 if (!object.isBoxModelObject() && !object.isSVG()) | 
| 876 return; | 894 return; | 
| 877 | 895 | 
| 896 if (context.forceSubtreeUpdate) { | |
| 897 object.getMutableForPainting() | |
| 898 .setNeedsPaintPropertyUpdateWithoutMarkingAncestors(); | |
| 
 
chrishtr
2016/12/01 02:36:35
This is kind of an odd way to do forced subtree up
 
pdr.
2016/12/01 09:35:35
This is a great idea. Done.
 
 | |
| 899 } | |
| 900 | |
| 878 #if DCHECK_IS_ON() | 901 #if DCHECK_IS_ON() | 
| 879 FindObjectPropertiesNeedingUpdateScope checkNeedsUpdateScope(object); | 902 FindObjectPropertiesNeedingUpdateScope checkNeedsUpdateScope(object, context); | 
| 880 #endif | 903 #endif | 
| 881 | 904 | 
| 882 deriveBorderBoxFromContainerContext(object, context); | 905 deriveBorderBoxFromContainerContext(object, context); | 
| 883 | 906 | 
| 884 updatePaintOffsetTranslation(object, context); | 907 updatePaintOffsetTranslation(object, context); | 
| 885 updateTransform(object, context); | 908 updateTransform(object, context); | 
| 886 updateEffect(object, context); | 909 updateEffect(object, context); | 
| 887 updateCssClip(object, context); | 910 updateCssClip(object, context); | 
| 888 updateLocalBorderBoxContext(object, context); | 911 updateLocalBorderBoxContext(object, context); | 
| 889 updateScrollbarPaintOffset(object, context); | 912 updateScrollbarPaintOffset(object, context); | 
| 890 } | 913 } | 
| 891 | 914 | 
| 892 void PaintPropertyTreeBuilder::updatePropertiesForChildren( | 915 void PaintPropertyTreeBuilder::updatePropertiesForChildren( | 
| 893 const LayoutObject& object, | 916 const LayoutObject& object, | 
| 894 PaintPropertyTreeBuilderContext& context) { | 917 PaintPropertyTreeBuilderContext& context) { | 
| 895 if (!object.isBoxModelObject() && !object.isSVG()) | 918 if (!object.isBoxModelObject() && !object.isSVG()) | 
| 896 return; | 919 return; | 
| 897 | 920 | 
| 921 if (context.forceSubtreeUpdate) { | |
| 922 // This should have been set by |updatePropertiesForSelf|. | |
| 923 DCHECK(object.needsPaintPropertyUpdate()); | |
| 924 } | |
| 925 | |
| 898 #if DCHECK_IS_ON() | 926 #if DCHECK_IS_ON() | 
| 899 FindObjectPropertiesNeedingUpdateScope checkNeedsUpdateScope(object); | 927 FindObjectPropertiesNeedingUpdateScope checkNeedsUpdateScope(object, context); | 
| 900 #endif | 928 #endif | 
| 901 | 929 | 
| 902 updateOverflowClip(object, context); | 930 updateOverflowClip(object, context); | 
| 903 updatePerspective(object, context); | 931 updatePerspective(object, context); | 
| 904 updateSvgLocalToBorderBoxTransform(object, context); | 932 updateSvgLocalToBorderBoxTransform(object, context); | 
| 905 updateScrollAndScrollTranslation(object, context); | 933 updateScrollAndScrollTranslation(object, context); | 
| 906 updateOutOfFlowContext(object, context); | 934 updateOutOfFlowContext(object, context); | 
| 907 } | 935 } | 
| 908 | 936 | 
| 909 } // namespace blink | 937 } // namespace blink | 
| OLD | NEW |