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