| 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 <memory> | 7 #include <memory> |
| 8 #include "core/dom/DOMNodeIds.h" | 8 #include "core/dom/DOMNodeIds.h" |
| 9 #include "core/frame/FrameView.h" | 9 #include "core/frame/FrameView.h" |
| 10 #include "core/frame/LocalFrame.h" | 10 #include "core/frame/LocalFrame.h" |
| 11 #include "core/frame/Settings.h" | 11 #include "core/frame/Settings.h" |
| 12 #include "core/layout/LayoutInline.h" | 12 #include "core/layout/LayoutInline.h" |
| 13 #include "core/layout/LayoutView.h" | 13 #include "core/layout/LayoutView.h" |
| 14 #include "core/layout/compositing/CompositingReasonFinder.h" | 14 #include "core/layout/compositing/CompositingReasonFinder.h" |
| 15 #include "core/layout/svg/LayoutSVGResourceMasker.h" | 15 #include "core/layout/svg/LayoutSVGResourceMasker.h" |
| 16 #include "core/layout/svg/LayoutSVGRoot.h" | 16 #include "core/layout/svg/LayoutSVGRoot.h" |
| 17 #include "core/layout/svg/SVGLayoutSupport.h" | 17 #include "core/layout/svg/SVGLayoutSupport.h" |
| 18 #include "core/layout/svg/SVGResources.h" | 18 #include "core/layout/svg/SVGResources.h" |
| 19 #include "core/layout/svg/SVGResourcesCache.h" | 19 #include "core/layout/svg/SVGResourcesCache.h" |
| 20 #include "core/paint/FindPaintOffsetAndVisualRectNeedingUpdate.h" | 20 #include "core/paint/FindPaintOffsetAndVisualRectNeedingUpdate.h" |
| 21 #include "core/paint/FindPropertiesNeedingUpdate.h" | 21 #include "core/paint/FindPropertiesNeedingUpdate.h" |
| 22 #include "core/paint/ObjectPaintProperties.h" | 22 #include "core/paint/ObjectPaintProperties.h" |
| 23 #include "core/paint/PaintLayer.h" | 23 #include "core/paint/PaintLayer.h" |
| 24 #include "core/paint/SVGRootPainter.h" | 24 #include "core/paint/SVGRootPainter.h" |
| 25 #include "platform/transforms/TransformationMatrix.h" | 25 #include "platform/transforms/TransformationMatrix.h" |
| 26 #include "platform/wtf/PtrUtil.h" | 26 #include "platform/wtf/PtrUtil.h" |
| 27 | 27 |
| 28 namespace blink { | 28 namespace blink { |
| 29 | 29 |
| 30 PaintPropertyTreeBuilderContext::PaintPropertyTreeBuilderContext() | 30 PaintPropertyTreeBuilderFragmentContext:: |
| 31 : container_for_absolute_position(nullptr), | 31 PaintPropertyTreeBuilderFragmentContext() |
| 32 current_effect(EffectPaintPropertyNode::Root()), | 32 : current_effect(EffectPaintPropertyNode::Root()), |
| 33 input_clip_of_current_effect(ClipPaintPropertyNode::Root()), | 33 input_clip_of_current_effect(ClipPaintPropertyNode::Root()) { |
| 34 force_subtree_update(false) { | |
| 35 current.clip = absolute_position.clip = fixed_position.clip = | 34 current.clip = absolute_position.clip = fixed_position.clip = |
| 36 ClipPaintPropertyNode::Root(); | 35 ClipPaintPropertyNode::Root(); |
| 37 current.transform = absolute_position.transform = fixed_position.transform = | 36 current.transform = absolute_position.transform = fixed_position.transform = |
| 38 TransformPaintPropertyNode::Root(); | 37 TransformPaintPropertyNode::Root(); |
| 39 current.scroll = absolute_position.scroll = fixed_position.scroll = | 38 current.scroll = absolute_position.scroll = fixed_position.scroll = |
| 40 ScrollPaintPropertyNode::Root(); | 39 ScrollPaintPropertyNode::Root(); |
| 41 } | 40 } |
| 42 | 41 |
| 43 // True if a new property was created, false if an existing one was updated. | 42 // True if a new property was created, false if an existing one was updated. |
| 44 static bool UpdatePreTranslation( | 43 static bool UpdatePreTranslation( |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 123 auto reasons = ancestor_reasons; | 122 auto reasons = ancestor_reasons; |
| 124 if (!frame_view.GetFrame().GetSettings()->GetThreadedScrollingEnabled()) | 123 if (!frame_view.GetFrame().GetSettings()->GetThreadedScrollingEnabled()) |
| 125 reasons |= MainThreadScrollingReason::kThreadedScrollingDisabled; | 124 reasons |= MainThreadScrollingReason::kThreadedScrollingDisabled; |
| 126 if (frame_view.HasBackgroundAttachmentFixedObjects()) | 125 if (frame_view.HasBackgroundAttachmentFixedObjects()) |
| 127 reasons |= MainThreadScrollingReason::kHasBackgroundAttachmentFixedObjects; | 126 reasons |= MainThreadScrollingReason::kHasBackgroundAttachmentFixedObjects; |
| 128 return reasons; | 127 return reasons; |
| 129 } | 128 } |
| 130 | 129 |
| 131 void PaintPropertyTreeBuilder::UpdateProperties( | 130 void PaintPropertyTreeBuilder::UpdateProperties( |
| 132 FrameView& frame_view, | 131 FrameView& frame_view, |
| 133 PaintPropertyTreeBuilderContext& context) { | 132 PaintPropertyTreeBuilderContext& full_context) { |
| 133 if (full_context.fragments.IsEmpty()) |
| 134 full_context.fragments.push_back(PaintPropertyTreeBuilderFragmentContext()); |
| 135 |
| 136 PaintPropertyTreeBuilderFragmentContext& context = full_context.fragments[0]; |
| 134 if (RuntimeEnabledFeatures::rootLayerScrollingEnabled()) { | 137 if (RuntimeEnabledFeatures::rootLayerScrollingEnabled()) { |
| 135 // With root layer scrolling, the LayoutView (a LayoutObject) properties are | 138 // With root layer scrolling, the LayoutView (a LayoutObject) properties are |
| 136 // updated like other objects (see updatePropertiesAndContextForSelf and | 139 // updated like other objects (see updatePropertiesAndContextForSelf and |
| 137 // updatePropertiesAndContextForChildren) instead of needing LayoutView- | 140 // updatePropertiesAndContextForChildren) instead of needing LayoutView- |
| 138 // specific property updates here. | 141 // specific property updates here. |
| 139 context.current.paint_offset.MoveBy(frame_view.Location()); | 142 context.current.paint_offset.MoveBy(frame_view.Location()); |
| 140 context.current.rendering_context_id = 0; | 143 context.current.rendering_context_id = 0; |
| 141 context.current.should_flatten_inherited_transform = true; | 144 context.current.should_flatten_inherited_transform = true; |
| 142 context.absolute_position = context.current; | 145 context.absolute_position = context.current; |
| 143 context.container_for_absolute_position = nullptr; | 146 full_context.container_for_absolute_position = nullptr; |
| 144 context.fixed_position = context.current; | 147 context.fixed_position = context.current; |
| 145 return; | 148 return; |
| 146 } | 149 } |
| 147 | 150 |
| 148 #if DCHECK_IS_ON() | 151 #if DCHECK_IS_ON() |
| 149 FindFrameViewPropertiesNeedingUpdateScope check_scope(&frame_view, context); | 152 FindFrameViewPropertiesNeedingUpdateScope check_scope( |
| 153 &frame_view, full_context.is_actually_needed); |
| 150 #endif | 154 #endif |
| 151 | 155 |
| 152 if (frame_view.NeedsPaintPropertyUpdate() || context.force_subtree_update) { | 156 if (frame_view.NeedsPaintPropertyUpdate() || |
| 157 full_context.force_subtree_update) { |
| 153 TransformationMatrix frame_translate; | 158 TransformationMatrix frame_translate; |
| 154 frame_translate.Translate( | 159 frame_translate.Translate( |
| 155 frame_view.X() + context.current.paint_offset.X(), | 160 frame_view.X() + context.current.paint_offset.X(), |
| 156 frame_view.Y() + context.current.paint_offset.Y()); | 161 frame_view.Y() + context.current.paint_offset.Y()); |
| 157 context.force_subtree_update |= UpdatePreTranslation( | 162 full_context.force_subtree_update |= UpdatePreTranslation( |
| 158 frame_view, context.current.transform, frame_translate, FloatPoint3D()); | 163 frame_view, context.current.transform, frame_translate, FloatPoint3D()); |
| 159 | 164 |
| 160 FloatRoundedRect content_clip( | 165 FloatRoundedRect content_clip( |
| 161 IntRect(IntPoint(), frame_view.VisibleContentSize())); | 166 IntRect(IntPoint(), frame_view.VisibleContentSize())); |
| 162 context.force_subtree_update |= | 167 full_context.force_subtree_update |= |
| 163 UpdateContentClip(frame_view, context.current.clip, | 168 UpdateContentClip(frame_view, context.current.clip, |
| 164 frame_view.PreTranslation(), content_clip); | 169 frame_view.PreTranslation(), content_clip); |
| 165 | 170 |
| 166 ScrollOffset scroll_offset = frame_view.GetScrollOffset(); | 171 ScrollOffset scroll_offset = frame_view.GetScrollOffset(); |
| 167 if (frame_view.IsScrollable() || !scroll_offset.IsZero()) { | 172 if (frame_view.IsScrollable() || !scroll_offset.IsZero()) { |
| 168 TransformationMatrix frame_scroll; | 173 TransformationMatrix frame_scroll; |
| 169 frame_scroll.Translate(-scroll_offset.Width(), -scroll_offset.Height()); | 174 frame_scroll.Translate(-scroll_offset.Width(), -scroll_offset.Height()); |
| 170 | 175 |
| 171 IntSize scroll_clip = frame_view.VisibleContentSize(); | 176 IntSize scroll_clip = frame_view.VisibleContentSize(); |
| 172 IntSize scroll_bounds = frame_view.ContentsSize(); | 177 IntSize scroll_bounds = frame_view.ContentsSize(); |
| 173 bool user_scrollable_horizontal = | 178 bool user_scrollable_horizontal = |
| 174 frame_view.UserInputScrollable(kHorizontalScrollbar); | 179 frame_view.UserInputScrollable(kHorizontalScrollbar); |
| 175 bool user_scrollable_vertical = | 180 bool user_scrollable_vertical = |
| 176 frame_view.UserInputScrollable(kVerticalScrollbar); | 181 frame_view.UserInputScrollable(kVerticalScrollbar); |
| 177 | 182 |
| 178 auto ancestor_reasons = | 183 auto ancestor_reasons = |
| 179 context.current.scroll->GetMainThreadScrollingReasons(); | 184 context.current.scroll->GetMainThreadScrollingReasons(); |
| 180 auto reasons = | 185 auto reasons = |
| 181 GetMainThreadScrollingReasons(frame_view, ancestor_reasons); | 186 GetMainThreadScrollingReasons(frame_view, ancestor_reasons); |
| 182 | 187 |
| 183 context.force_subtree_update |= UpdateScrollTranslation( | 188 full_context.force_subtree_update |= UpdateScrollTranslation( |
| 184 frame_view, frame_view.PreTranslation(), frame_scroll, FloatPoint3D(), | 189 frame_view, frame_view.PreTranslation(), frame_scroll, FloatPoint3D(), |
| 185 context.current.scroll, scroll_clip, scroll_bounds, | 190 context.current.scroll, scroll_clip, scroll_bounds, |
| 186 user_scrollable_horizontal, user_scrollable_vertical, reasons, | 191 user_scrollable_horizontal, user_scrollable_vertical, reasons, |
| 187 frame_view.GetScrollableArea()); | 192 frame_view.GetScrollableArea()); |
| 188 } else { | 193 } else { |
| 189 if (frame_view.ScrollTranslation()) { | 194 if (frame_view.ScrollTranslation()) { |
| 190 // Ensure pre-existing properties are cleared if there is no scrolling. | 195 // Ensure pre-existing properties are cleared if there is no scrolling. |
| 191 frame_view.SetScrollTranslation(nullptr); | 196 frame_view.SetScrollTranslation(nullptr); |
| 192 // Rebuild all descendant properties because a property was removed. | 197 // Rebuild all descendant properties because a property was removed. |
| 193 context.force_subtree_update = true; | 198 full_context.force_subtree_update = true; |
| 194 } | 199 } |
| 195 } | 200 } |
| 196 } | 201 } |
| 197 | 202 |
| 198 // Initialize the context for current, absolute and fixed position cases. | 203 // Initialize the context for current, absolute and fixed position cases. |
| 199 // They are the same, except that scroll translation does not apply to | 204 // They are the same, except that scroll translation does not apply to |
| 200 // fixed position descendants. | 205 // fixed position descendants. |
| 201 const auto* fixed_transform_node = frame_view.PreTranslation() | 206 const auto* fixed_transform_node = frame_view.PreTranslation() |
| 202 ? frame_view.PreTranslation() | 207 ? frame_view.PreTranslation() |
| 203 : context.current.transform; | 208 : context.current.transform; |
| 204 auto* fixed_scroll_node = context.current.scroll; | 209 auto* fixed_scroll_node = context.current.scroll; |
| 205 DCHECK(frame_view.PreTranslation()); | 210 DCHECK(frame_view.PreTranslation()); |
| 206 context.current.transform = frame_view.PreTranslation(); | 211 context.current.transform = frame_view.PreTranslation(); |
| 207 DCHECK(frame_view.ContentClip()); | 212 DCHECK(frame_view.ContentClip()); |
| 208 context.current.clip = frame_view.ContentClip(); | 213 context.current.clip = frame_view.ContentClip(); |
| 209 if (const auto* scroll_translation = frame_view.ScrollTranslation()) { | 214 if (const auto* scroll_translation = frame_view.ScrollTranslation()) { |
| 210 context.current.transform = scroll_translation; | 215 context.current.transform = scroll_translation; |
| 211 context.current.scroll = scroll_translation->ScrollNode(); | 216 context.current.scroll = scroll_translation->ScrollNode(); |
| 212 } | 217 } |
| 213 context.current.paint_offset = LayoutPoint(); | 218 context.current.paint_offset = LayoutPoint(); |
| 214 context.current.rendering_context_id = 0; | 219 context.current.rendering_context_id = 0; |
| 215 context.current.should_flatten_inherited_transform = true; | 220 context.current.should_flatten_inherited_transform = true; |
| 216 context.absolute_position = context.current; | 221 context.absolute_position = context.current; |
| 217 context.container_for_absolute_position = nullptr; | 222 full_context.container_for_absolute_position = nullptr; |
| 218 context.fixed_position = context.current; | 223 context.fixed_position = context.current; |
| 219 context.fixed_position.transform = fixed_transform_node; | 224 context.fixed_position.transform = fixed_transform_node; |
| 220 context.fixed_position.scroll = fixed_scroll_node; | 225 context.fixed_position.scroll = fixed_scroll_node; |
| 221 | 226 |
| 222 std::unique_ptr<PropertyTreeState> contents_state(new PropertyTreeState( | 227 std::unique_ptr<PropertyTreeState> contents_state(new PropertyTreeState( |
| 223 context.current.transform, context.current.clip, context.current_effect)); | 228 context.current.transform, context.current.clip, context.current_effect)); |
| 224 frame_view.SetTotalPropertyTreeStateForContents(std::move(contents_state)); | 229 frame_view.SetTotalPropertyTreeStateForContents(std::move(contents_state)); |
| 225 } | 230 } |
| 226 | 231 |
| 227 static bool NeedsPaintOffsetTranslation(const LayoutObject& object) { | 232 static bool NeedsPaintOffsetTranslation(const LayoutObject& object) { |
| 228 if (!object.IsBoxModelObject()) | 233 if (!object.IsBoxModelObject()) |
| 229 return false; | 234 return false; |
| 230 const LayoutBoxModelObject& box_model = ToLayoutBoxModelObject(object); | 235 const LayoutBoxModelObject& box_model = ToLayoutBoxModelObject(object); |
| 231 if (RuntimeEnabledFeatures::rootLayerScrollingEnabled() && | 236 if (RuntimeEnabledFeatures::rootLayerScrollingEnabled() && |
| 232 box_model.IsLayoutView()) { | 237 box_model.IsLayoutView()) { |
| 233 // Root layer scrolling always creates a translation node for LayoutView to | 238 // Root layer scrolling always creates a translation node for LayoutView to |
| 234 // ensure fixed and absolute contexts use the correct transform space. | 239 // ensure fixed and absolute contexts use the correct transform space. |
| 235 return true; | 240 return true; |
| 236 } else if (box_model.HasLayer() && | 241 } else if (box_model.HasLayer() && |
| 237 box_model.Layer()->PaintsWithTransform( | 242 box_model.Layer()->PaintsWithTransform( |
| 238 kGlobalPaintFlattenCompositingLayers)) { | 243 kGlobalPaintFlattenCompositingLayers)) { |
| 239 return true; | 244 return true; |
| 240 } | 245 } |
| 241 return false; | 246 return false; |
| 242 } | 247 } |
| 243 | 248 |
| 244 void PaintPropertyTreeBuilder::UpdatePaintOffsetTranslation( | 249 void PaintPropertyTreeBuilder::UpdatePaintOffsetTranslation( |
| 245 const LayoutBoxModelObject& object, | 250 const LayoutBoxModelObject& object, |
| 246 PaintPropertyTreeBuilderContext& context) { | 251 PaintPropertyTreeBuilderFragmentContext& context, |
| 252 bool& force_subtree_update) { |
| 247 if (NeedsPaintOffsetTranslation(object) && | 253 if (NeedsPaintOffsetTranslation(object) && |
| 248 // As an optimization, skip these paint offset translation nodes when | 254 // As an optimization, skip these paint offset translation nodes when |
| 249 // the offset is an identity. An exception is the layout view because root | 255 // the offset is an identity. An exception is the layout view because root |
| 250 // layer scrolling needs a transform node to ensure fixed and absolute | 256 // layer scrolling needs a transform node to ensure fixed and absolute |
| 251 // descendants use the correct transform space. | 257 // descendants use the correct transform space. |
| 252 (object.IsLayoutView() || | 258 (object.IsLayoutView() || |
| 253 context.current.paint_offset != LayoutPoint())) { | 259 context.current.paint_offset != LayoutPoint())) { |
| 254 auto& properties = *object.GetMutableForPainting().PaintProperties(); | 260 auto& properties = *object.GetMutableForPainting().PaintProperties(); |
| 255 // We should use the same subpixel paint offset values for snapping | 261 // We should use the same subpixel paint offset values for snapping |
| 256 // regardless of whether a transform is present. If there is a transform | 262 // regardless of whether a transform is present. If there is a transform |
| 257 // we round the paint offset but keep around the residual fractional | 263 // we round the paint offset but keep around the residual fractional |
| 258 // component for the transformed content to paint with. In spv1 this was | 264 // component for the transformed content to paint with. In spv1 this was |
| 259 // called "subpixel accumulation". For more information, see | 265 // called "subpixel accumulation". For more information, see |
| 260 // PaintLayer::subpixelAccumulation() and | 266 // PaintLayer::subpixelAccumulation() and |
| 261 // PaintLayerPainter::paintFragmentByApplyingTransform. | 267 // PaintLayerPainter::paintFragmentByApplyingTransform. |
| 262 IntPoint rounded_paint_offset = | 268 IntPoint rounded_paint_offset = |
| 263 RoundedIntPoint(context.current.paint_offset); | 269 RoundedIntPoint(context.current.paint_offset); |
| 264 LayoutPoint fractional_paint_offset = | 270 LayoutPoint fractional_paint_offset = |
| 265 LayoutPoint(context.current.paint_offset - rounded_paint_offset); | 271 LayoutPoint(context.current.paint_offset - rounded_paint_offset); |
| 266 | 272 |
| 267 context.force_subtree_update |= properties.UpdatePaintOffsetTranslation( | 273 force_subtree_update |= properties.UpdatePaintOffsetTranslation( |
| 268 context.current.transform, | 274 context.current.transform, |
| 269 TransformationMatrix().Translate(rounded_paint_offset.X(), | 275 TransformationMatrix().Translate(rounded_paint_offset.X(), |
| 270 rounded_paint_offset.Y()), | 276 rounded_paint_offset.Y()), |
| 271 FloatPoint3D(), context.current.should_flatten_inherited_transform, | 277 FloatPoint3D(), context.current.should_flatten_inherited_transform, |
| 272 context.current.rendering_context_id); | 278 context.current.rendering_context_id); |
| 273 | 279 |
| 274 context.current.transform = properties.PaintOffsetTranslation(); | 280 context.current.transform = properties.PaintOffsetTranslation(); |
| 275 context.current.paint_offset = fractional_paint_offset; | 281 context.current.paint_offset = fractional_paint_offset; |
| 276 if (RuntimeEnabledFeatures::rootLayerScrollingEnabled() && | 282 if (RuntimeEnabledFeatures::rootLayerScrollingEnabled() && |
| 277 object.IsLayoutView()) { | 283 object.IsLayoutView()) { |
| 278 context.absolute_position.transform = properties.PaintOffsetTranslation(); | 284 context.absolute_position.transform = properties.PaintOffsetTranslation(); |
| 279 context.fixed_position.transform = properties.PaintOffsetTranslation(); | 285 context.fixed_position.transform = properties.PaintOffsetTranslation(); |
| 280 context.absolute_position.paint_offset = LayoutPoint(); | 286 context.absolute_position.paint_offset = LayoutPoint(); |
| 281 context.fixed_position.paint_offset = LayoutPoint(); | 287 context.fixed_position.paint_offset = LayoutPoint(); |
| 282 } | 288 } |
| 283 } else { | 289 } else { |
| 284 if (auto* properties = object.GetMutableForPainting().PaintProperties()) | 290 if (auto* properties = object.GetMutableForPainting().PaintProperties()) |
| 285 context.force_subtree_update |= properties->ClearPaintOffsetTranslation(); | 291 force_subtree_update |= properties->ClearPaintOffsetTranslation(); |
| 286 } | 292 } |
| 287 } | 293 } |
| 288 | 294 |
| 289 static bool NeedsTransformForNonRootSVG(const LayoutObject& object) { | 295 static bool NeedsTransformForNonRootSVG(const LayoutObject& object) { |
| 290 // TODO(pdr): Check for the presence of a transform instead of the value. | 296 // TODO(pdr): Check for the presence of a transform instead of the value. |
| 291 // Checking for an identity matrix will cause the property tree structure | 297 // Checking for an identity matrix will cause the property tree structure |
| 292 // to change during animations if the animation passes through the | 298 // to change during animations if the animation passes through the |
| 293 // identity matrix. | 299 // identity matrix. |
| 294 return object.IsSVGChild() && | 300 return object.IsSVGChild() && |
| 295 !object.LocalToSVGParentTransform().IsIdentity(); | 301 !object.LocalToSVGParentTransform().IsIdentity(); |
| 296 } | 302 } |
| 297 | 303 |
| 298 // SVG does not use the general transform update of |updateTransform|, instead | 304 // SVG does not use the general transform update of |updateTransform|, instead |
| 299 // creating a transform node for SVG-specific transforms without 3D. | 305 // creating a transform node for SVG-specific transforms without 3D. |
| 300 void PaintPropertyTreeBuilder::UpdateTransformForNonRootSVG( | 306 void PaintPropertyTreeBuilder::UpdateTransformForNonRootSVG( |
| 301 const LayoutObject& object, | 307 const LayoutObject& object, |
| 302 PaintPropertyTreeBuilderContext& context) { | 308 PaintPropertyTreeBuilderFragmentContext& context, |
| 309 bool& force_subtree_update) { |
| 303 DCHECK(object.IsSVGChild()); | 310 DCHECK(object.IsSVGChild()); |
| 304 // SVG does not use paint offset internally, except for SVGForeignObject which | 311 // SVG does not use paint offset internally, except for SVGForeignObject which |
| 305 // has different SVG and HTML coordinate spaces. | 312 // has different SVG and HTML coordinate spaces. |
| 306 DCHECK(object.IsSVGForeignObject() || | 313 DCHECK(object.IsSVGForeignObject() || |
| 307 context.current.paint_offset == LayoutPoint()); | 314 context.current.paint_offset == LayoutPoint()); |
| 308 | 315 |
| 309 if (object.NeedsPaintPropertyUpdate() || context.force_subtree_update) { | 316 if (object.NeedsPaintPropertyUpdate() || force_subtree_update) { |
| 310 AffineTransform transform = object.LocalToSVGParentTransform(); | 317 AffineTransform transform = object.LocalToSVGParentTransform(); |
| 311 if (NeedsTransformForNonRootSVG(object)) { | 318 if (NeedsTransformForNonRootSVG(object)) { |
| 312 // The origin is included in the local transform, so leave origin empty. | 319 // The origin is included in the local transform, so leave origin empty. |
| 313 auto& properties = *object.GetMutableForPainting().PaintProperties(); | 320 auto& properties = *object.GetMutableForPainting().PaintProperties(); |
| 314 context.force_subtree_update |= properties.UpdateTransform( | 321 force_subtree_update |= properties.UpdateTransform( |
| 315 context.current.transform, TransformationMatrix(transform), | 322 context.current.transform, TransformationMatrix(transform), |
| 316 FloatPoint3D()); | 323 FloatPoint3D()); |
| 317 } else { | 324 } else { |
| 318 if (auto* properties = object.GetMutableForPainting().PaintProperties()) | 325 if (auto* properties = object.GetMutableForPainting().PaintProperties()) |
| 319 context.force_subtree_update |= properties->ClearTransform(); | 326 force_subtree_update |= properties->ClearTransform(); |
| 320 } | 327 } |
| 321 } | 328 } |
| 322 | 329 |
| 323 if (object.PaintProperties() && object.PaintProperties()->Transform()) { | 330 if (object.PaintProperties() && object.PaintProperties()->Transform()) { |
| 324 context.current.transform = object.PaintProperties()->Transform(); | 331 context.current.transform = object.PaintProperties()->Transform(); |
| 325 context.current.should_flatten_inherited_transform = false; | 332 context.current.should_flatten_inherited_transform = false; |
| 326 context.current.rendering_context_id = 0; | 333 context.current.rendering_context_id = 0; |
| 327 } | 334 } |
| 328 } | 335 } |
| 329 | 336 |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 365 static bool NeedsTransform(const LayoutObject& object) { | 372 static bool NeedsTransform(const LayoutObject& object) { |
| 366 if (!object.IsBox()) | 373 if (!object.IsBox()) |
| 367 return false; | 374 return false; |
| 368 return object.StyleRef().HasTransform() || object.StyleRef().Preserves3D() || | 375 return object.StyleRef().HasTransform() || object.StyleRef().Preserves3D() || |
| 369 CompositingReasonsForTransform(ToLayoutBox(object)) != | 376 CompositingReasonsForTransform(ToLayoutBox(object)) != |
| 370 kCompositingReasonNone; | 377 kCompositingReasonNone; |
| 371 } | 378 } |
| 372 | 379 |
| 373 void PaintPropertyTreeBuilder::UpdateTransform( | 380 void PaintPropertyTreeBuilder::UpdateTransform( |
| 374 const LayoutObject& object, | 381 const LayoutObject& object, |
| 375 PaintPropertyTreeBuilderContext& context) { | 382 PaintPropertyTreeBuilderFragmentContext& context, |
| 383 bool& force_subtree_update) { |
| 376 if (object.IsSVGChild()) { | 384 if (object.IsSVGChild()) { |
| 377 UpdateTransformForNonRootSVG(object, context); | 385 UpdateTransformForNonRootSVG(object, context, force_subtree_update); |
| 378 return; | 386 return; |
| 379 } | 387 } |
| 380 | 388 |
| 381 if (object.NeedsPaintPropertyUpdate() || context.force_subtree_update) { | 389 if (object.NeedsPaintPropertyUpdate() || force_subtree_update) { |
| 382 const ComputedStyle& style = object.StyleRef(); | 390 const ComputedStyle& style = object.StyleRef(); |
| 383 | 391 |
| 384 // A transform node is allocated for transforms, preserves-3d and any | 392 // A transform node is allocated for transforms, preserves-3d and any |
| 385 // direct compositing reason. The latter is required because this is the | 393 // direct compositing reason. The latter is required because this is the |
| 386 // only way to represent compositing both an element and its stacking | 394 // only way to represent compositing both an element and its stacking |
| 387 // descendants. | 395 // descendants. |
| 388 if (NeedsTransform(object)) { | 396 if (NeedsTransform(object)) { |
| 389 auto& box = ToLayoutBox(object); | 397 auto& box = ToLayoutBox(object); |
| 390 | 398 |
| 391 CompositingReasons compositing_reasons = | 399 CompositingReasons compositing_reasons = |
| (...skipping 12 matching lines...) Expand all Loading... |
| 404 unsigned rendering_context_id = context.current.rendering_context_id; | 412 unsigned rendering_context_id = context.current.rendering_context_id; |
| 405 if (style.Preserves3D() && !rendering_context_id) | 413 if (style.Preserves3D() && !rendering_context_id) |
| 406 rendering_context_id = PtrHash<const LayoutObject>::GetHash(&object); | 414 rendering_context_id = PtrHash<const LayoutObject>::GetHash(&object); |
| 407 | 415 |
| 408 CompositorElementId compositor_element_id = | 416 CompositorElementId compositor_element_id = |
| 409 style.HasCurrentTransformAnimation() | 417 style.HasCurrentTransformAnimation() |
| 410 ? CreateDomNodeBasedCompositorElementId(object) | 418 ? CreateDomNodeBasedCompositorElementId(object) |
| 411 : CompositorElementId(); | 419 : CompositorElementId(); |
| 412 | 420 |
| 413 auto& properties = *object.GetMutableForPainting().PaintProperties(); | 421 auto& properties = *object.GetMutableForPainting().PaintProperties(); |
| 414 context.force_subtree_update |= properties.UpdateTransform( | 422 force_subtree_update |= properties.UpdateTransform( |
| 415 context.current.transform, matrix, TransformOrigin(box), | 423 context.current.transform, matrix, TransformOrigin(box), |
| 416 context.current.should_flatten_inherited_transform, | 424 context.current.should_flatten_inherited_transform, |
| 417 rendering_context_id, compositing_reasons, compositor_element_id); | 425 rendering_context_id, compositing_reasons, compositor_element_id); |
| 418 } else { | 426 } else { |
| 419 if (auto* properties = object.GetMutableForPainting().PaintProperties()) | 427 if (auto* properties = object.GetMutableForPainting().PaintProperties()) |
| 420 context.force_subtree_update |= properties->ClearTransform(); | 428 force_subtree_update |= properties->ClearTransform(); |
| 421 } | 429 } |
| 422 } | 430 } |
| 423 | 431 |
| 424 const auto* properties = object.PaintProperties(); | 432 const auto* properties = object.PaintProperties(); |
| 425 if (properties && properties->Transform()) { | 433 if (properties && properties->Transform()) { |
| 426 context.current.transform = properties->Transform(); | 434 context.current.transform = properties->Transform(); |
| 427 if (object.StyleRef().Preserves3D()) { | 435 if (object.StyleRef().Preserves3D()) { |
| 428 context.current.rendering_context_id = | 436 context.current.rendering_context_id = |
| 429 properties->Transform()->RenderingContextId(); | 437 properties->Transform()->RenderingContextId(); |
| 430 context.current.should_flatten_inherited_transform = false; | 438 context.current.should_flatten_inherited_transform = false; |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 522 } | 530 } |
| 523 | 531 |
| 524 if (object.StyleRef().HasMask()) | 532 if (object.StyleRef().HasMask()) |
| 525 return true; | 533 return true; |
| 526 | 534 |
| 527 return false; | 535 return false; |
| 528 } | 536 } |
| 529 | 537 |
| 530 void PaintPropertyTreeBuilder::UpdateEffect( | 538 void PaintPropertyTreeBuilder::UpdateEffect( |
| 531 const LayoutObject& object, | 539 const LayoutObject& object, |
| 532 PaintPropertyTreeBuilderContext& context) { | 540 PaintPropertyTreeBuilderFragmentContext& context, |
| 541 bool& force_subtree_update) { |
| 533 const ComputedStyle& style = object.StyleRef(); | 542 const ComputedStyle& style = object.StyleRef(); |
| 534 | 543 |
| 535 // TODO(trchen): Can't omit effect node if we have 3D children. | 544 // TODO(trchen): Can't omit effect node if we have 3D children. |
| 536 if (object.NeedsPaintPropertyUpdate() || context.force_subtree_update) { | 545 if (object.NeedsPaintPropertyUpdate() || force_subtree_update) { |
| 537 const ClipPaintPropertyNode* output_clip = | 546 const ClipPaintPropertyNode* output_clip = |
| 538 context.input_clip_of_current_effect; | 547 context.input_clip_of_current_effect; |
| 539 | 548 |
| 540 if (NeedsEffect(object)) { | 549 if (NeedsEffect(object)) { |
| 541 auto& properties = *object.GetMutableForPainting().PaintProperties(); | 550 auto& properties = *object.GetMutableForPainting().PaintProperties(); |
| 542 | 551 |
| 543 // We may begin to composite our subtree prior to an animation starts, | 552 // We may begin to composite our subtree prior to an animation starts, |
| 544 // but a compositor element ID is only needed when an animation is | 553 // but a compositor element ID is only needed when an animation is |
| 545 // current. | 554 // current. |
| 546 CompositingReasons compositing_reasons = kCompositingReasonNone; | 555 CompositingReasons compositing_reasons = kCompositingReasonNone; |
| 547 if (CompositingReasonFinder::RequiresCompositingForOpacityAnimation( | 556 if (CompositingReasonFinder::RequiresCompositingForOpacityAnimation( |
| 548 style)) { | 557 style)) { |
| 549 compositing_reasons = kCompositingReasonActiveAnimation; | 558 compositing_reasons = kCompositingReasonActiveAnimation; |
| 550 } | 559 } |
| 551 | 560 |
| 552 IntRect mask_clip; | 561 IntRect mask_clip; |
| 553 ColorFilter mask_color_filter; | 562 ColorFilter mask_color_filter; |
| 554 bool has_mask = ComputeMaskParameters( | 563 bool has_mask = ComputeMaskParameters( |
| 555 mask_clip, mask_color_filter, object, context.current.paint_offset); | 564 mask_clip, mask_color_filter, object, context.current.paint_offset); |
| 556 if (has_mask) { | 565 if (has_mask) { |
| 557 context.force_subtree_update |= properties.UpdateMaskClip( | 566 force_subtree_update |= properties.UpdateMaskClip( |
| 558 context.current.clip, context.current.transform, | 567 context.current.clip, context.current.transform, |
| 559 FloatRoundedRect(mask_clip)); | 568 FloatRoundedRect(mask_clip)); |
| 560 output_clip = properties.MaskClip(); | 569 output_clip = properties.MaskClip(); |
| 561 | 570 |
| 562 // TODO(crbug.com/683425): PaintArtifactCompositor does not handle | 571 // TODO(crbug.com/683425): PaintArtifactCompositor does not handle |
| 563 // grouping (i.e. descendant-dependent compositing reason) properly | 572 // grouping (i.e. descendant-dependent compositing reason) properly |
| 564 // yet. This forces masked subtree always create a layer for now. | 573 // yet. This forces masked subtree always create a layer for now. |
| 565 compositing_reasons |= kCompositingReasonIsolateCompositedDescendants; | 574 compositing_reasons |= kCompositingReasonIsolateCompositedDescendants; |
| 566 } else { | 575 } else { |
| 567 if (auto* properties = object.GetMutableForPainting().PaintProperties()) | 576 if (auto* properties = object.GetMutableForPainting().PaintProperties()) |
| 568 context.force_subtree_update |= properties->ClearMaskClip(); | 577 force_subtree_update |= properties->ClearMaskClip(); |
| 569 } | 578 } |
| 570 | 579 |
| 571 SkBlendMode blend_mode = | 580 SkBlendMode blend_mode = |
| 572 object.IsBlendingAllowed() | 581 object.IsBlendingAllowed() |
| 573 ? WebCoreCompositeToSkiaComposite(kCompositeSourceOver, | 582 ? WebCoreCompositeToSkiaComposite(kCompositeSourceOver, |
| 574 style.BlendMode()) | 583 style.BlendMode()) |
| 575 : SkBlendMode::kSrcOver; | 584 : SkBlendMode::kSrcOver; |
| 576 | 585 |
| 577 CompositorElementId compositor_element_id = | 586 CompositorElementId compositor_element_id = |
| 578 style.HasCurrentOpacityAnimation() | 587 style.HasCurrentOpacityAnimation() |
| 579 ? CreateDomNodeBasedCompositorElementId(object) | 588 ? CreateDomNodeBasedCompositorElementId(object) |
| 580 : CompositorElementId(); | 589 : CompositorElementId(); |
| 581 | 590 |
| 582 DCHECK(!style.HasCurrentOpacityAnimation() || | 591 DCHECK(!style.HasCurrentOpacityAnimation() || |
| 583 compositing_reasons != kCompositingReasonNone); | 592 compositing_reasons != kCompositingReasonNone); |
| 584 | 593 |
| 585 context.force_subtree_update |= properties.UpdateEffect( | 594 force_subtree_update |= properties.UpdateEffect( |
| 586 context.current_effect, context.current.transform, output_clip, | 595 context.current_effect, context.current.transform, output_clip, |
| 587 kColorFilterNone, CompositorFilterOperations(), style.Opacity(), | 596 kColorFilterNone, CompositorFilterOperations(), style.Opacity(), |
| 588 blend_mode, compositing_reasons, compositor_element_id); | 597 blend_mode, compositing_reasons, compositor_element_id); |
| 589 if (has_mask) { | 598 if (has_mask) { |
| 590 // TODO(crbug.com/683425): PaintArtifactCompositor does not handle | 599 // TODO(crbug.com/683425): PaintArtifactCompositor does not handle |
| 591 // grouping (i.e. descendant-dependent compositing reason) properly | 600 // grouping (i.e. descendant-dependent compositing reason) properly |
| 592 // yet. Adding CompositingReasonSquashingDisallowed forces mask not | 601 // yet. Adding CompositingReasonSquashingDisallowed forces mask not |
| 593 // getting squashed into a child effect. Have no compositing reason | 602 // getting squashed into a child effect. Have no compositing reason |
| 594 // otherwise. | 603 // otherwise. |
| 595 context.force_subtree_update |= properties.UpdateMask( | 604 force_subtree_update |= properties.UpdateMask( |
| 596 properties.Effect(), context.current.transform, output_clip, | 605 properties.Effect(), context.current.transform, output_clip, |
| 597 mask_color_filter, CompositorFilterOperations(), 1.f, | 606 mask_color_filter, CompositorFilterOperations(), 1.f, |
| 598 SkBlendMode::kDstIn, kCompositingReasonSquashingDisallowed, | 607 SkBlendMode::kDstIn, kCompositingReasonSquashingDisallowed, |
| 599 CompositorElementId()); | 608 CompositorElementId()); |
| 600 } else { | 609 } else { |
| 601 context.force_subtree_update |= properties.ClearMask(); | 610 force_subtree_update |= properties.ClearMask(); |
| 602 } | 611 } |
| 603 } else { | 612 } else { |
| 604 if (auto* properties = object.GetMutableForPainting().PaintProperties()) { | 613 if (auto* properties = object.GetMutableForPainting().PaintProperties()) { |
| 605 context.force_subtree_update |= properties->ClearEffect(); | 614 force_subtree_update |= properties->ClearEffect(); |
| 606 context.force_subtree_update |= properties->ClearMask(); | 615 force_subtree_update |= properties->ClearMask(); |
| 607 context.force_subtree_update |= properties->ClearMaskClip(); | 616 force_subtree_update |= properties->ClearMaskClip(); |
| 608 } | 617 } |
| 609 } | 618 } |
| 610 } | 619 } |
| 611 | 620 |
| 612 const auto* properties = object.PaintProperties(); | 621 const auto* properties = object.PaintProperties(); |
| 613 if (properties && properties->Effect()) { | 622 if (properties && properties->Effect()) { |
| 614 context.current_effect = properties->Effect(); | 623 context.current_effect = properties->Effect(); |
| 615 if (properties->MaskClip()) { | 624 if (properties->MaskClip()) { |
| 616 context.input_clip_of_current_effect = context.current.clip = | 625 context.input_clip_of_current_effect = context.current.clip = |
| 617 context.absolute_position.clip = context.fixed_position.clip = | 626 context.absolute_position.clip = context.fixed_position.clip = |
| 618 properties->MaskClip(); | 627 properties->MaskClip(); |
| 619 } | 628 } |
| 620 } | 629 } |
| 621 } | 630 } |
| 622 | 631 |
| 623 static bool NeedsFilter(const LayoutObject& object) { | 632 static bool NeedsFilter(const LayoutObject& object) { |
| 624 // TODO(trchen): SVG caches filters in SVGResources. Implement it. | 633 // TODO(trchen): SVG caches filters in SVGResources. Implement it. |
| 625 return object.IsBoxModelObject() && ToLayoutBoxModelObject(object).Layer() && | 634 return object.IsBoxModelObject() && ToLayoutBoxModelObject(object).Layer() && |
| 626 (object.StyleRef().HasFilter() || object.HasReflection()); | 635 (object.StyleRef().HasFilter() || object.HasReflection()); |
| 627 } | 636 } |
| 628 | 637 |
| 629 void PaintPropertyTreeBuilder::UpdateFilter( | 638 void PaintPropertyTreeBuilder::UpdateFilter( |
| 630 const LayoutObject& object, | 639 const LayoutObject& object, |
| 631 PaintPropertyTreeBuilderContext& context) { | 640 PaintPropertyTreeBuilderFragmentContext& context, |
| 641 bool& force_subtree_update) { |
| 632 const ComputedStyle& style = object.StyleRef(); | 642 const ComputedStyle& style = object.StyleRef(); |
| 633 | 643 |
| 634 if (object.NeedsPaintPropertyUpdate() || context.force_subtree_update) { | 644 if (object.NeedsPaintPropertyUpdate() || force_subtree_update) { |
| 635 if (NeedsFilter(object)) { | 645 if (NeedsFilter(object)) { |
| 636 CompositorFilterOperations filter = | 646 CompositorFilterOperations filter = |
| 637 ToLayoutBoxModelObject(object) | 647 ToLayoutBoxModelObject(object) |
| 638 .Layer() | 648 .Layer() |
| 639 ->CreateCompositorFilterOperationsForFilter(style); | 649 ->CreateCompositorFilterOperationsForFilter(style); |
| 640 | 650 |
| 641 // The CSS filter spec didn't specify how filters interact with overflow | 651 // The CSS filter spec didn't specify how filters interact with overflow |
| 642 // clips. The implementation here mimics the old Blink/WebKit behavior for | 652 // clips. The implementation here mimics the old Blink/WebKit behavior for |
| 643 // backward compatibility. | 653 // backward compatibility. |
| 644 // Basically the output of the filter will be affected by clips that | 654 // Basically the output of the filter will be affected by clips that |
| (...skipping 25 matching lines...) Expand all Loading... |
| 670 ? CreateDomNodeBasedCompositorElementId(object) | 680 ? CreateDomNodeBasedCompositorElementId(object) |
| 671 : CompositorElementId(); | 681 : CompositorElementId(); |
| 672 CompositingReasons compositing_reasons = | 682 CompositingReasons compositing_reasons = |
| 673 CompositingReasonFinder::RequiresCompositingForFilterAnimation(style) | 683 CompositingReasonFinder::RequiresCompositingForFilterAnimation(style) |
| 674 ? kCompositingReasonActiveAnimation | 684 ? kCompositingReasonActiveAnimation |
| 675 : kCompositingReasonNone; | 685 : kCompositingReasonNone; |
| 676 DCHECK(!style.HasCurrentFilterAnimation() || | 686 DCHECK(!style.HasCurrentFilterAnimation() || |
| 677 compositing_reasons != kCompositingReasonNone); | 687 compositing_reasons != kCompositingReasonNone); |
| 678 | 688 |
| 679 auto& properties = *object.GetMutableForPainting().PaintProperties(); | 689 auto& properties = *object.GetMutableForPainting().PaintProperties(); |
| 680 context.force_subtree_update |= properties.UpdateFilter( | 690 force_subtree_update |= properties.UpdateFilter( |
| 681 context.current_effect, context.current.transform, output_clip, | 691 context.current_effect, context.current.transform, output_clip, |
| 682 kColorFilterNone, std::move(filter), 1.f, SkBlendMode::kSrcOver, | 692 kColorFilterNone, std::move(filter), 1.f, SkBlendMode::kSrcOver, |
| 683 compositing_reasons, compositor_element_id); | 693 compositing_reasons, compositor_element_id); |
| 684 } else { | 694 } else { |
| 685 if (auto* properties = object.GetMutableForPainting().PaintProperties()) | 695 if (auto* properties = object.GetMutableForPainting().PaintProperties()) |
| 686 context.force_subtree_update |= properties->ClearFilter(); | 696 force_subtree_update |= properties->ClearFilter(); |
| 687 } | 697 } |
| 688 } | 698 } |
| 689 | 699 |
| 690 const auto* properties = object.PaintProperties(); | 700 const auto* properties = object.PaintProperties(); |
| 691 if (properties && properties->Filter()) { | 701 if (properties && properties->Filter()) { |
| 692 context.current_effect = properties->Filter(); | 702 context.current_effect = properties->Filter(); |
| 693 // TODO(trchen): Change input clip to expansion hint once implemented. | 703 // TODO(trchen): Change input clip to expansion hint once implemented. |
| 694 const ClipPaintPropertyNode* input_clip = | 704 const ClipPaintPropertyNode* input_clip = |
| 695 properties->Filter()->OutputClip(); | 705 properties->Filter()->OutputClip(); |
| 696 context.input_clip_of_current_effect = context.current.clip = | 706 context.input_clip_of_current_effect = context.current.clip = |
| 697 context.absolute_position.clip = context.fixed_position.clip = | 707 context.absolute_position.clip = context.fixed_position.clip = |
| 698 input_clip; | 708 input_clip; |
| 699 } | 709 } |
| 700 } | 710 } |
| 701 | 711 |
| 702 static bool NeedsCssClip(const LayoutObject& object) { | 712 static bool NeedsCssClip(const LayoutObject& object) { |
| 703 return object.HasClip(); | 713 return object.HasClip(); |
| 704 } | 714 } |
| 705 | 715 |
| 706 void PaintPropertyTreeBuilder::UpdateCssClip( | 716 void PaintPropertyTreeBuilder::UpdateCssClip( |
| 707 const LayoutObject& object, | 717 const LayoutObject& object, |
| 708 PaintPropertyTreeBuilderContext& context) { | 718 PaintPropertyTreeBuilderFragmentContext& context, |
| 709 if (object.NeedsPaintPropertyUpdate() || context.force_subtree_update) { | 719 bool& force_subtree_update) { |
| 720 if (object.NeedsPaintPropertyUpdate() || force_subtree_update) { |
| 710 if (NeedsCssClip(object)) { | 721 if (NeedsCssClip(object)) { |
| 711 // Create clip node for descendants that are not fixed position. | 722 // Create clip node for descendants that are not fixed position. |
| 712 // We don't have to setup context.absolutePosition.clip here because this | 723 // We don't have to setup context.absolutePosition.clip here because this |
| 713 // object must be a container for absolute position descendants, and will | 724 // object must be a container for absolute position descendants, and will |
| 714 // copy from in-flow context later at updateOutOfFlowContext() step. | 725 // copy from in-flow context later at updateOutOfFlowContext() step. |
| 715 DCHECK(object.CanContainAbsolutePositionObjects()); | 726 DCHECK(object.CanContainAbsolutePositionObjects()); |
| 716 LayoutRect clip_rect = | 727 LayoutRect clip_rect = |
| 717 ToLayoutBox(object).ClipRect(context.current.paint_offset); | 728 ToLayoutBox(object).ClipRect(context.current.paint_offset); |
| 718 auto& properties = *object.GetMutableForPainting().PaintProperties(); | 729 auto& properties = *object.GetMutableForPainting().PaintProperties(); |
| 719 context.force_subtree_update |= properties.UpdateCssClip( | 730 force_subtree_update |= properties.UpdateCssClip( |
| 720 context.current.clip, context.current.transform, | 731 context.current.clip, context.current.transform, |
| 721 FloatRoundedRect(FloatRect(clip_rect))); | 732 FloatRoundedRect(FloatRect(clip_rect))); |
| 722 } else { | 733 } else { |
| 723 if (auto* properties = object.GetMutableForPainting().PaintProperties()) | 734 if (auto* properties = object.GetMutableForPainting().PaintProperties()) |
| 724 context.force_subtree_update |= properties->ClearCssClip(); | 735 force_subtree_update |= properties->ClearCssClip(); |
| 725 } | 736 } |
| 726 } | 737 } |
| 727 | 738 |
| 728 const auto* properties = object.PaintProperties(); | 739 const auto* properties = object.PaintProperties(); |
| 729 if (properties && properties->CssClip()) | 740 if (properties && properties->CssClip()) |
| 730 context.current.clip = properties->CssClip(); | 741 context.current.clip = properties->CssClip(); |
| 731 } | 742 } |
| 732 | 743 |
| 733 void PaintPropertyTreeBuilder::UpdateLocalBorderBoxContext( | 744 void PaintPropertyTreeBuilder::UpdateLocalBorderBoxContext( |
| 734 const LayoutObject& object, | 745 const LayoutObject& object, |
| 735 PaintPropertyTreeBuilderContext& context) { | 746 PaintPropertyTreeBuilderFragmentContext& context, |
| 736 if (!object.NeedsPaintPropertyUpdate() && !context.force_subtree_update) | 747 bool& force_subtree_update) { |
| 748 if (!object.NeedsPaintPropertyUpdate() && !force_subtree_update) |
| 737 return; | 749 return; |
| 738 | 750 |
| 739 // We only need to cache the local border box properties for layered objects. | 751 // We only need to cache the local border box properties for layered objects. |
| 740 if (!object.HasLayer()) { | 752 if (!object.HasLayer()) { |
| 741 object.GetMutableForPainting().ClearLocalBorderBoxProperties(); | 753 object.GetMutableForPainting().ClearLocalBorderBoxProperties(); |
| 742 } else { | 754 } else { |
| 743 PropertyTreeState local_border_box = | 755 PropertyTreeState local_border_box = |
| 744 PropertyTreeState(context.current.transform, context.current.clip, | 756 PropertyTreeState(context.current.transform, context.current.clip, |
| 745 context.current_effect); | 757 context.current_effect); |
| 746 object.GetMutableForPainting().SetLocalBorderBoxProperties( | 758 object.GetMutableForPainting().SetLocalBorderBoxProperties( |
| 747 local_border_box); | 759 local_border_box); |
| 748 } | 760 } |
| 749 } | 761 } |
| 750 | 762 |
| 751 static bool NeedsScrollbarPaintOffset(const LayoutObject& object) { | 763 static bool NeedsScrollbarPaintOffset(const LayoutObject& object) { |
| 752 if (object.IsBoxModelObject()) { | 764 if (object.IsBoxModelObject()) { |
| 753 if (auto* area = ToLayoutBoxModelObject(object).GetScrollableArea()) { | 765 if (auto* area = ToLayoutBoxModelObject(object).GetScrollableArea()) { |
| 754 if (area->HorizontalScrollbar() || area->VerticalScrollbar()) | 766 if (area->HorizontalScrollbar() || area->VerticalScrollbar()) |
| 755 return true; | 767 return true; |
| 756 } | 768 } |
| 757 } | 769 } |
| 758 return false; | 770 return false; |
| 759 } | 771 } |
| 760 | 772 |
| 761 // TODO(trchen): Remove this once we bake the paint offset into frameRect. | 773 // TODO(trchen): Remove this once we bake the paint offset into frameRect. |
| 762 void PaintPropertyTreeBuilder::UpdateScrollbarPaintOffset( | 774 void PaintPropertyTreeBuilder::UpdateScrollbarPaintOffset( |
| 763 const LayoutObject& object, | 775 const LayoutObject& object, |
| 764 PaintPropertyTreeBuilderContext& context) { | 776 PaintPropertyTreeBuilderFragmentContext& context, |
| 765 if (!object.NeedsPaintPropertyUpdate() && !context.force_subtree_update) | 777 bool& force_subtree_update) { |
| 778 if (!object.NeedsPaintPropertyUpdate() && !force_subtree_update) |
| 766 return; | 779 return; |
| 767 | 780 |
| 768 if (NeedsScrollbarPaintOffset(object)) { | 781 if (NeedsScrollbarPaintOffset(object)) { |
| 769 IntPoint rounded_paint_offset = | 782 IntPoint rounded_paint_offset = |
| 770 RoundedIntPoint(context.current.paint_offset); | 783 RoundedIntPoint(context.current.paint_offset); |
| 771 auto paint_offset = TransformationMatrix().Translate( | 784 auto paint_offset = TransformationMatrix().Translate( |
| 772 rounded_paint_offset.X(), rounded_paint_offset.Y()); | 785 rounded_paint_offset.X(), rounded_paint_offset.Y()); |
| 773 auto& properties = *object.GetMutableForPainting().PaintProperties(); | 786 auto& properties = *object.GetMutableForPainting().PaintProperties(); |
| 774 context.force_subtree_update |= properties.UpdateScrollbarPaintOffset( | 787 force_subtree_update |= properties.UpdateScrollbarPaintOffset( |
| 775 context.current.transform, paint_offset, FloatPoint3D()); | 788 context.current.transform, paint_offset, FloatPoint3D()); |
| 776 } else { | 789 } else { |
| 777 if (auto* properties = object.GetMutableForPainting().PaintProperties()) | 790 if (auto* properties = object.GetMutableForPainting().PaintProperties()) |
| 778 context.force_subtree_update |= properties->ClearScrollbarPaintOffset(); | 791 force_subtree_update |= properties->ClearScrollbarPaintOffset(); |
| 779 } | 792 } |
| 780 } | 793 } |
| 781 | 794 |
| 782 static bool NeedsOverflowScroll(const LayoutObject& object) { | 795 static bool NeedsOverflowScroll(const LayoutObject& object) { |
| 783 return object.IsBox() && ToLayoutBox(object).ShouldClipOverflow(); | 796 return object.IsBox() && ToLayoutBox(object).ShouldClipOverflow(); |
| 784 } | 797 } |
| 785 | 798 |
| 786 void PaintPropertyTreeBuilder::UpdateOverflowClip( | 799 void PaintPropertyTreeBuilder::UpdateOverflowClip( |
| 787 const LayoutObject& object, | 800 const LayoutObject& object, |
| 788 PaintPropertyTreeBuilderContext& context) { | 801 PaintPropertyTreeBuilderFragmentContext& context, |
| 789 if (object.NeedsPaintPropertyUpdate() || context.force_subtree_update) { | 802 bool& force_subtree_update) { |
| 803 if (object.NeedsPaintPropertyUpdate() || force_subtree_update) { |
| 790 if (NeedsOverflowScroll(object)) { | 804 if (NeedsOverflowScroll(object)) { |
| 791 const LayoutBox& box = ToLayoutBox(object); | 805 const LayoutBox& box = ToLayoutBox(object); |
| 792 LayoutRect clip_rect; | 806 LayoutRect clip_rect; |
| 793 clip_rect = | 807 clip_rect = |
| 794 LayoutRect(box.OverflowClipRect(context.current.paint_offset)); | 808 LayoutRect(box.OverflowClipRect(context.current.paint_offset)); |
| 795 | 809 |
| 796 auto& properties = *object.GetMutableForPainting().PaintProperties(); | 810 auto& properties = *object.GetMutableForPainting().PaintProperties(); |
| 797 const auto* current_clip = context.current.clip; | 811 const auto* current_clip = context.current.clip; |
| 798 if (box.StyleRef().HasBorderRadius()) { | 812 if (box.StyleRef().HasBorderRadius()) { |
| 799 auto inner_border = box.StyleRef().GetRoundedInnerBorderFor( | 813 auto inner_border = box.StyleRef().GetRoundedInnerBorderFor( |
| 800 LayoutRect(context.current.paint_offset, box.Size())); | 814 LayoutRect(context.current.paint_offset, box.Size())); |
| 801 context.force_subtree_update |= properties.UpdateInnerBorderRadiusClip( | 815 force_subtree_update |= properties.UpdateInnerBorderRadiusClip( |
| 802 context.current.clip, context.current.transform, inner_border); | 816 context.current.clip, context.current.transform, inner_border); |
| 803 current_clip = properties.InnerBorderRadiusClip(); | 817 current_clip = properties.InnerBorderRadiusClip(); |
| 804 } else { | 818 } else { |
| 805 context.force_subtree_update |= properties.ClearInnerBorderRadiusClip(); | 819 force_subtree_update |= properties.ClearInnerBorderRadiusClip(); |
| 806 } | 820 } |
| 807 | 821 |
| 808 context.force_subtree_update |= | 822 force_subtree_update |= |
| 809 properties.UpdateOverflowClip(current_clip, context.current.transform, | 823 properties.UpdateOverflowClip(current_clip, context.current.transform, |
| 810 FloatRoundedRect(FloatRect(clip_rect))); | 824 FloatRoundedRect(FloatRect(clip_rect))); |
| 811 } else { | 825 } else { |
| 812 if (auto* properties = object.GetMutableForPainting().PaintProperties()) { | 826 if (auto* properties = object.GetMutableForPainting().PaintProperties()) { |
| 813 context.force_subtree_update |= | 827 force_subtree_update |= properties->ClearInnerBorderRadiusClip(); |
| 814 properties->ClearInnerBorderRadiusClip(); | 828 force_subtree_update |= properties->ClearOverflowClip(); |
| 815 context.force_subtree_update |= properties->ClearOverflowClip(); | |
| 816 } | 829 } |
| 817 return; | 830 return; |
| 818 } | 831 } |
| 819 } | 832 } |
| 820 | 833 |
| 821 const auto* properties = object.PaintProperties(); | 834 const auto* properties = object.PaintProperties(); |
| 822 if (properties && properties->OverflowClip()) | 835 if (properties && properties->OverflowClip()) |
| 823 context.current.clip = properties->OverflowClip(); | 836 context.current.clip = properties->OverflowClip(); |
| 824 } | 837 } |
| 825 | 838 |
| 826 static FloatPoint PerspectiveOrigin(const LayoutBox& box) { | 839 static FloatPoint PerspectiveOrigin(const LayoutBox& box) { |
| 827 const ComputedStyle& style = box.StyleRef(); | 840 const ComputedStyle& style = box.StyleRef(); |
| 828 // Perspective origin has no effect without perspective. | 841 // Perspective origin has no effect without perspective. |
| 829 DCHECK(style.HasPerspective()); | 842 DCHECK(style.HasPerspective()); |
| 830 FloatSize border_box_size(box.Size()); | 843 FloatSize border_box_size(box.Size()); |
| 831 return FloatPoint( | 844 return FloatPoint( |
| 832 FloatValueForLength(style.PerspectiveOriginX(), border_box_size.Width()), | 845 FloatValueForLength(style.PerspectiveOriginX(), border_box_size.Width()), |
| 833 FloatValueForLength(style.PerspectiveOriginY(), | 846 FloatValueForLength(style.PerspectiveOriginY(), |
| 834 border_box_size.Height())); | 847 border_box_size.Height())); |
| 835 } | 848 } |
| 836 | 849 |
| 837 static bool NeedsPerspective(const LayoutObject& object) { | 850 static bool NeedsPerspective(const LayoutObject& object) { |
| 838 return object.IsBox() && object.StyleRef().HasPerspective(); | 851 return object.IsBox() && object.StyleRef().HasPerspective(); |
| 839 } | 852 } |
| 840 | 853 |
| 841 void PaintPropertyTreeBuilder::UpdatePerspective( | 854 void PaintPropertyTreeBuilder::UpdatePerspective( |
| 842 const LayoutObject& object, | 855 const LayoutObject& object, |
| 843 PaintPropertyTreeBuilderContext& context) { | 856 PaintPropertyTreeBuilderFragmentContext& context, |
| 844 if (object.NeedsPaintPropertyUpdate() || context.force_subtree_update) { | 857 bool& force_subtree_update) { |
| 858 if (object.NeedsPaintPropertyUpdate() || force_subtree_update) { |
| 845 if (NeedsPerspective(object)) { | 859 if (NeedsPerspective(object)) { |
| 846 const ComputedStyle& style = object.StyleRef(); | 860 const ComputedStyle& style = object.StyleRef(); |
| 847 // The perspective node must not flatten (else nothing will get | 861 // The perspective node must not flatten (else nothing will get |
| 848 // perspective), but it should still extend the rendering context as | 862 // perspective), but it should still extend the rendering context as |
| 849 // most transform nodes do. | 863 // most transform nodes do. |
| 850 TransformationMatrix matrix = | 864 TransformationMatrix matrix = |
| 851 TransformationMatrix().ApplyPerspective(style.Perspective()); | 865 TransformationMatrix().ApplyPerspective(style.Perspective()); |
| 852 FloatPoint3D origin = PerspectiveOrigin(ToLayoutBox(object)) + | 866 FloatPoint3D origin = PerspectiveOrigin(ToLayoutBox(object)) + |
| 853 ToLayoutSize(context.current.paint_offset); | 867 ToLayoutSize(context.current.paint_offset); |
| 854 auto& properties = *object.GetMutableForPainting().PaintProperties(); | 868 auto& properties = *object.GetMutableForPainting().PaintProperties(); |
| 855 context.force_subtree_update |= properties.UpdatePerspective( | 869 force_subtree_update |= properties.UpdatePerspective( |
| 856 context.current.transform, matrix, origin, | 870 context.current.transform, matrix, origin, |
| 857 context.current.should_flatten_inherited_transform, | 871 context.current.should_flatten_inherited_transform, |
| 858 context.current.rendering_context_id); | 872 context.current.rendering_context_id); |
| 859 } else { | 873 } else { |
| 860 if (auto* properties = object.GetMutableForPainting().PaintProperties()) | 874 if (auto* properties = object.GetMutableForPainting().PaintProperties()) |
| 861 context.force_subtree_update |= properties->ClearPerspective(); | 875 force_subtree_update |= properties->ClearPerspective(); |
| 862 } | 876 } |
| 863 } | 877 } |
| 864 | 878 |
| 865 const auto* properties = object.PaintProperties(); | 879 const auto* properties = object.PaintProperties(); |
| 866 if (properties && properties->Perspective()) { | 880 if (properties && properties->Perspective()) { |
| 867 context.current.transform = properties->Perspective(); | 881 context.current.transform = properties->Perspective(); |
| 868 context.current.should_flatten_inherited_transform = false; | 882 context.current.should_flatten_inherited_transform = false; |
| 869 } | 883 } |
| 870 } | 884 } |
| 871 | 885 |
| 872 static bool NeedsSVGLocalToBorderBoxTransform(const LayoutObject& object) { | 886 static bool NeedsSVGLocalToBorderBoxTransform(const LayoutObject& object) { |
| 873 return object.IsSVGRoot(); | 887 return object.IsSVGRoot(); |
| 874 } | 888 } |
| 875 | 889 |
| 876 void PaintPropertyTreeBuilder::UpdateSvgLocalToBorderBoxTransform( | 890 void PaintPropertyTreeBuilder::UpdateSvgLocalToBorderBoxTransform( |
| 877 const LayoutObject& object, | 891 const LayoutObject& object, |
| 878 PaintPropertyTreeBuilderContext& context) { | 892 PaintPropertyTreeBuilderFragmentContext& context, |
| 893 bool& force_subtree_update) { |
| 879 if (!object.IsSVGRoot()) | 894 if (!object.IsSVGRoot()) |
| 880 return; | 895 return; |
| 881 | 896 |
| 882 if (object.NeedsPaintPropertyUpdate() || context.force_subtree_update) { | 897 if (object.NeedsPaintPropertyUpdate() || force_subtree_update) { |
| 883 AffineTransform transform_to_border_box = | 898 AffineTransform transform_to_border_box = |
| 884 SVGRootPainter(ToLayoutSVGRoot(object)) | 899 SVGRootPainter(ToLayoutSVGRoot(object)) |
| 885 .TransformToPixelSnappedBorderBox(context.current.paint_offset); | 900 .TransformToPixelSnappedBorderBox(context.current.paint_offset); |
| 886 if (!transform_to_border_box.IsIdentity() && | 901 if (!transform_to_border_box.IsIdentity() && |
| 887 NeedsSVGLocalToBorderBoxTransform(object)) { | 902 NeedsSVGLocalToBorderBoxTransform(object)) { |
| 888 auto& properties = *object.GetMutableForPainting().PaintProperties(); | 903 auto& properties = *object.GetMutableForPainting().PaintProperties(); |
| 889 context.force_subtree_update |= | 904 force_subtree_update |= properties.UpdateSvgLocalToBorderBoxTransform( |
| 890 properties.UpdateSvgLocalToBorderBoxTransform( | 905 context.current.transform, transform_to_border_box, FloatPoint3D()); |
| 891 context.current.transform, transform_to_border_box, | |
| 892 FloatPoint3D()); | |
| 893 } else { | 906 } else { |
| 894 if (auto* properties = object.GetMutableForPainting().PaintProperties()) { | 907 if (auto* properties = object.GetMutableForPainting().PaintProperties()) { |
| 895 context.force_subtree_update |= | 908 force_subtree_update |= properties->ClearSvgLocalToBorderBoxTransform(); |
| 896 properties->ClearSvgLocalToBorderBoxTransform(); | |
| 897 } | 909 } |
| 898 } | 910 } |
| 899 } | 911 } |
| 900 | 912 |
| 901 const auto* properties = object.PaintProperties(); | 913 const auto* properties = object.PaintProperties(); |
| 902 if (properties && properties->SvgLocalToBorderBoxTransform()) { | 914 if (properties && properties->SvgLocalToBorderBoxTransform()) { |
| 903 context.current.transform = properties->SvgLocalToBorderBoxTransform(); | 915 context.current.transform = properties->SvgLocalToBorderBoxTransform(); |
| 904 context.current.should_flatten_inherited_transform = false; | 916 context.current.should_flatten_inherited_transform = false; |
| 905 context.current.rendering_context_id = 0; | 917 context.current.rendering_context_id = 0; |
| 906 } | 918 } |
| (...skipping 21 matching lines...) Expand all Loading... |
| 928 auto* scrollable_area = box.GetScrollableArea(); | 940 auto* scrollable_area = box.GetScrollableArea(); |
| 929 IntSize scroll_offset = box.ScrolledContentOffset(); | 941 IntSize scroll_offset = box.ScrolledContentOffset(); |
| 930 if (!scroll_offset.IsZero() || scrollable_area->ScrollsOverflow()) | 942 if (!scroll_offset.IsZero() || scrollable_area->ScrollsOverflow()) |
| 931 return true; | 943 return true; |
| 932 } | 944 } |
| 933 return false; | 945 return false; |
| 934 } | 946 } |
| 935 | 947 |
| 936 void PaintPropertyTreeBuilder::UpdateScrollAndScrollTranslation( | 948 void PaintPropertyTreeBuilder::UpdateScrollAndScrollTranslation( |
| 937 const LayoutObject& object, | 949 const LayoutObject& object, |
| 938 PaintPropertyTreeBuilderContext& context) { | 950 PaintPropertyTreeBuilderFragmentContext& context, |
| 939 if (object.NeedsPaintPropertyUpdate() || context.force_subtree_update) { | 951 bool& force_subtree_update) { |
| 952 if (object.NeedsPaintPropertyUpdate() || force_subtree_update) { |
| 940 if (NeedsScrollTranslation(object)) { | 953 if (NeedsScrollTranslation(object)) { |
| 941 const LayoutBox& box = ToLayoutBox(object); | 954 const LayoutBox& box = ToLayoutBox(object); |
| 942 auto* scrollable_area = box.GetScrollableArea(); | 955 auto* scrollable_area = box.GetScrollableArea(); |
| 943 IntSize scroll_offset = box.ScrolledContentOffset(); | 956 IntSize scroll_offset = box.ScrolledContentOffset(); |
| 944 auto& properties = *object.GetMutableForPainting().PaintProperties(); | 957 auto& properties = *object.GetMutableForPainting().PaintProperties(); |
| 945 | 958 |
| 946 IntSize scroll_clip = scrollable_area->VisibleContentRect().Size(); | 959 IntSize scroll_clip = scrollable_area->VisibleContentRect().Size(); |
| 947 IntSize scroll_bounds = scrollable_area->ContentsSize(); | 960 IntSize scroll_bounds = scrollable_area->ContentsSize(); |
| 948 bool user_scrollable_horizontal = | 961 bool user_scrollable_horizontal = |
| 949 scrollable_area->UserInputScrollable(kHorizontalScrollbar); | 962 scrollable_area->UserInputScrollable(kHorizontalScrollbar); |
| 950 bool user_scrollable_vertical = | 963 bool user_scrollable_vertical = |
| 951 scrollable_area->UserInputScrollable(kVerticalScrollbar); | 964 scrollable_area->UserInputScrollable(kVerticalScrollbar); |
| 952 | 965 |
| 953 auto ancestor_reasons = | 966 auto ancestor_reasons = |
| 954 context.current.scroll->GetMainThreadScrollingReasons(); | 967 context.current.scroll->GetMainThreadScrollingReasons(); |
| 955 auto reasons = GetMainThreadScrollingReasons(object, ancestor_reasons); | 968 auto reasons = GetMainThreadScrollingReasons(object, ancestor_reasons); |
| 956 | 969 |
| 957 // Main thread scrolling reasons depend on their ancestor's reasons | 970 // Main thread scrolling reasons depend on their ancestor's reasons |
| 958 // so ensure the entire subtree is updated when reasons change. | 971 // so ensure the entire subtree is updated when reasons change. |
| 959 if (auto* existing_scroll_translation = properties.ScrollTranslation()) { | 972 if (auto* existing_scroll_translation = properties.ScrollTranslation()) { |
| 960 auto* existing_scroll_node = existing_scroll_translation->ScrollNode(); | 973 auto* existing_scroll_node = existing_scroll_translation->ScrollNode(); |
| 961 if (existing_scroll_node->GetMainThreadScrollingReasons() != reasons) | 974 if (existing_scroll_node->GetMainThreadScrollingReasons() != reasons) |
| 962 context.force_subtree_update = true; | 975 force_subtree_update = true; |
| 963 } | 976 } |
| 964 | 977 |
| 965 CompositorElementId compositor_element_id = | 978 CompositorElementId compositor_element_id = |
| 966 CreateDomNodeBasedCompositorElementId(object); | 979 CreateDomNodeBasedCompositorElementId(object); |
| 967 TransformationMatrix matrix = TransformationMatrix().Translate( | 980 TransformationMatrix matrix = TransformationMatrix().Translate( |
| 968 -scroll_offset.Width(), -scroll_offset.Height()); | 981 -scroll_offset.Width(), -scroll_offset.Height()); |
| 969 context.force_subtree_update |= properties.UpdateScrollTranslation( | 982 force_subtree_update |= properties.UpdateScrollTranslation( |
| 970 context.current.transform, matrix, FloatPoint3D(), | 983 context.current.transform, matrix, FloatPoint3D(), |
| 971 context.current.should_flatten_inherited_transform, | 984 context.current.should_flatten_inherited_transform, |
| 972 context.current.rendering_context_id, kCompositingReasonNone, | 985 context.current.rendering_context_id, kCompositingReasonNone, |
| 973 compositor_element_id, context.current.scroll, scroll_clip, | 986 compositor_element_id, context.current.scroll, scroll_clip, |
| 974 scroll_bounds, user_scrollable_horizontal, user_scrollable_vertical, | 987 scroll_bounds, user_scrollable_horizontal, user_scrollable_vertical, |
| 975 reasons, scrollable_area); | 988 reasons, scrollable_area); |
| 976 } else { | 989 } else { |
| 977 // Ensure pre-existing properties are cleared. | 990 // Ensure pre-existing properties are cleared. |
| 978 if (auto* properties = object.GetMutableForPainting().PaintProperties()) | 991 if (auto* properties = object.GetMutableForPainting().PaintProperties()) |
| 979 context.force_subtree_update |= properties->ClearScrollTranslation(); | 992 force_subtree_update |= properties->ClearScrollTranslation(); |
| 980 } | 993 } |
| 981 } | 994 } |
| 982 | 995 |
| 983 if (object.PaintProperties() && | 996 if (object.PaintProperties() && |
| 984 object.PaintProperties()->ScrollTranslation()) { | 997 object.PaintProperties()->ScrollTranslation()) { |
| 985 context.current.transform = object.PaintProperties()->ScrollTranslation(); | 998 context.current.transform = object.PaintProperties()->ScrollTranslation(); |
| 986 context.current.scroll = context.current.transform->ScrollNode(); | 999 context.current.scroll = context.current.transform->ScrollNode(); |
| 987 context.current.should_flatten_inherited_transform = false; | 1000 context.current.should_flatten_inherited_transform = false; |
| 988 } | 1001 } |
| 989 } | 1002 } |
| 990 | 1003 |
| 991 static bool NeedsCssClipFixedPosition(const LayoutObject& object) { | 1004 static bool NeedsCssClipFixedPosition(const LayoutObject& object) { |
| 992 return !object.IsLayoutView() && !object.CanContainFixedPositionObjects() && | 1005 return !object.IsLayoutView() && !object.CanContainFixedPositionObjects() && |
| 993 NeedsCssClip(object); | 1006 NeedsCssClip(object); |
| 994 } | 1007 } |
| 995 | 1008 |
| 996 void PaintPropertyTreeBuilder::UpdateOutOfFlowContext( | 1009 void PaintPropertyTreeBuilder::UpdateOutOfFlowContext( |
| 997 const LayoutObject& object, | 1010 const LayoutObject& object, |
| 998 PaintPropertyTreeBuilderContext& context) { | 1011 PaintPropertyTreeBuilderFragmentContext& context, |
| 1012 bool& force_subtree_update) { |
| 999 if (object.IsLayoutBlock()) | 1013 if (object.IsLayoutBlock()) |
| 1000 context.paint_offset_for_float = context.current.paint_offset; | 1014 context.paint_offset_for_float = context.current.paint_offset; |
| 1001 | 1015 |
| 1002 if (object.CanContainAbsolutePositionObjects()) { | 1016 if (object.CanContainAbsolutePositionObjects()) |
| 1003 context.absolute_position = context.current; | 1017 context.absolute_position = context.current; |
| 1004 context.container_for_absolute_position = &object; | |
| 1005 } | |
| 1006 | 1018 |
| 1007 if (object.IsLayoutView()) { | 1019 if (object.IsLayoutView()) { |
| 1008 if (RuntimeEnabledFeatures::rootLayerScrollingEnabled()) { | 1020 if (RuntimeEnabledFeatures::rootLayerScrollingEnabled()) { |
| 1009 const auto* initial_fixed_transform = context.fixed_position.transform; | 1021 const auto* initial_fixed_transform = context.fixed_position.transform; |
| 1010 const auto* initial_fixed_scroll = context.fixed_position.scroll; | 1022 const auto* initial_fixed_scroll = context.fixed_position.scroll; |
| 1011 | 1023 |
| 1012 context.fixed_position = context.current; | 1024 context.fixed_position = context.current; |
| 1013 | 1025 |
| 1014 // Fixed position transform and scroll nodes should not be affected. | 1026 // Fixed position transform and scroll nodes should not be affected. |
| 1015 context.fixed_position.transform = initial_fixed_transform; | 1027 context.fixed_position.transform = initial_fixed_transform; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1026 // need to insert the clip here if we are not a containing block ancestor of | 1038 // need to insert the clip here if we are not a containing block ancestor of |
| 1027 // them. | 1039 // them. |
| 1028 auto& properties = *object.GetMutableForPainting().PaintProperties(); | 1040 auto& properties = *object.GetMutableForPainting().PaintProperties(); |
| 1029 auto* css_clip = properties.CssClip(); | 1041 auto* css_clip = properties.CssClip(); |
| 1030 | 1042 |
| 1031 // Before we actually create anything, check whether in-flow context and | 1043 // Before we actually create anything, check whether in-flow context and |
| 1032 // fixed-position context has exactly the same clip. Reuse if possible. | 1044 // fixed-position context has exactly the same clip. Reuse if possible. |
| 1033 if (context.fixed_position.clip == css_clip->Parent()) { | 1045 if (context.fixed_position.clip == css_clip->Parent()) { |
| 1034 context.fixed_position.clip = css_clip; | 1046 context.fixed_position.clip = css_clip; |
| 1035 } else { | 1047 } else { |
| 1036 if (object.NeedsPaintPropertyUpdate() || context.force_subtree_update) { | 1048 if (object.NeedsPaintPropertyUpdate() || force_subtree_update) { |
| 1037 context.force_subtree_update |= properties.UpdateCssClipFixedPosition( | 1049 force_subtree_update |= properties.UpdateCssClipFixedPosition( |
| 1038 context.fixed_position.clip, | 1050 context.fixed_position.clip, |
| 1039 const_cast<TransformPaintPropertyNode*>( | 1051 const_cast<TransformPaintPropertyNode*>( |
| 1040 css_clip->LocalTransformSpace()), | 1052 css_clip->LocalTransformSpace()), |
| 1041 css_clip->ClipRect()); | 1053 css_clip->ClipRect()); |
| 1042 } | 1054 } |
| 1043 if (properties.CssClipFixedPosition()) | 1055 if (properties.CssClipFixedPosition()) |
| 1044 context.fixed_position.clip = properties.CssClipFixedPosition(); | 1056 context.fixed_position.clip = properties.CssClipFixedPosition(); |
| 1045 return; | 1057 return; |
| 1046 } | 1058 } |
| 1047 } | 1059 } |
| 1048 | 1060 |
| 1049 if (object.NeedsPaintPropertyUpdate() || context.force_subtree_update) { | 1061 if (object.NeedsPaintPropertyUpdate() || force_subtree_update) { |
| 1050 if (auto* properties = object.GetMutableForPainting().PaintProperties()) | 1062 if (auto* properties = object.GetMutableForPainting().PaintProperties()) |
| 1051 context.force_subtree_update |= properties->ClearCssClipFixedPosition(); | 1063 force_subtree_update |= properties->ClearCssClipFixedPosition(); |
| 1052 } | 1064 } |
| 1053 } | 1065 } |
| 1054 | 1066 |
| 1055 void PaintPropertyTreeBuilder::UpdatePaintOffset( | 1067 void PaintPropertyTreeBuilder::UpdatePaintOffset( |
| 1056 const LayoutBoxModelObject& object, | 1068 const LayoutBoxModelObject& object, |
| 1057 PaintPropertyTreeBuilderContext& context) { | 1069 PaintPropertyTreeBuilderFragmentContext& context, |
| 1070 const LayoutObject* container_for_absolute_position) { |
| 1058 if (object.IsFloating()) | 1071 if (object.IsFloating()) |
| 1059 context.current.paint_offset = context.paint_offset_for_float; | 1072 context.current.paint_offset = context.paint_offset_for_float; |
| 1060 | 1073 |
| 1061 // Multicolumn spanners are painted starting at the multicolumn container (but | 1074 // Multicolumn spanners are painted starting at the multicolumn container (but |
| 1062 // still inherit properties in layout-tree order) so reset the paint offset. | 1075 // still inherit properties in layout-tree order) so reset the paint offset. |
| 1063 if (object.IsColumnSpanAll()) | 1076 if (object.IsColumnSpanAll()) |
| 1064 context.current.paint_offset = object.Container()->PaintOffset(); | 1077 context.current.paint_offset = object.Container()->PaintOffset(); |
| 1065 | 1078 |
| 1066 switch (object.StyleRef().GetPosition()) { | 1079 switch (object.StyleRef().GetPosition()) { |
| 1067 case EPosition::kStatic: | 1080 case EPosition::kStatic: |
| 1068 break; | 1081 break; |
| 1069 case EPosition::kRelative: | 1082 case EPosition::kRelative: |
| 1070 context.current.paint_offset += object.OffsetForInFlowPosition(); | 1083 context.current.paint_offset += object.OffsetForInFlowPosition(); |
| 1071 break; | 1084 break; |
| 1072 case EPosition::kAbsolute: { | 1085 case EPosition::kAbsolute: { |
| 1073 DCHECK(context.container_for_absolute_position == object.Container()); | 1086 DCHECK(container_for_absolute_position == object.Container()); |
| 1074 context.current = context.absolute_position; | 1087 context.current = context.absolute_position; |
| 1075 | 1088 |
| 1076 // Absolutely positioned content in an inline should be positioned | 1089 // Absolutely positioned content in an inline should be positioned |
| 1077 // relative to the inline. | 1090 // relative to the inline. |
| 1078 const LayoutObject* container = context.container_for_absolute_position; | 1091 const LayoutObject* container = container_for_absolute_position; |
| 1079 if (container && container->IsInFlowPositioned() && | 1092 if (container && container->IsInFlowPositioned() && |
| 1080 container->IsLayoutInline()) { | 1093 container->IsLayoutInline()) { |
| 1081 DCHECK(object.IsBox()); | 1094 DCHECK(object.IsBox()); |
| 1082 context.current.paint_offset += | 1095 context.current.paint_offset += |
| 1083 ToLayoutInline(container)->OffsetForInFlowPositionedInline( | 1096 ToLayoutInline(container)->OffsetForInFlowPositionedInline( |
| 1084 ToLayoutBox(object)); | 1097 ToLayoutBox(object)); |
| 1085 } | 1098 } |
| 1086 break; | 1099 break; |
| 1087 } | 1100 } |
| 1088 case EPosition::kSticky: | 1101 case EPosition::kSticky: |
| 1089 context.current.paint_offset += object.OffsetForInFlowPosition(); | 1102 context.current.paint_offset += object.OffsetForInFlowPosition(); |
| 1090 break; | 1103 break; |
| 1091 case EPosition::kFixed: | 1104 case EPosition::kFixed: |
| 1092 context.current = context.fixed_position; | 1105 context.current = context.fixed_position; |
| 1093 break; | 1106 break; |
| 1094 default: | 1107 default: |
| 1095 ASSERT_NOT_REACHED(); | 1108 ASSERT_NOT_REACHED(); |
| 1096 } | 1109 } |
| 1097 | 1110 |
| 1098 if (object.IsBox()) { | 1111 if (object.IsBox()) { |
| 1099 // TODO(pdr): Several calls in this function walk back up the tree to | 1112 // TODO(pdr): Several calls in this function walk back up the tree to |
| 1100 // calculate containers (e.g., physicalLocation, offsetForInFlowPosition*). | 1113 // calculate containers (e.g., physicalLocation, offsetForInFlowPosition*). |
| 1101 // The containing block and other containers can be stored on | 1114 // The containing block and other containers can be stored on |
| 1102 // PaintPropertyTreeBuilderContext instead of recomputing them. | 1115 // PaintPropertyTreeBuilderFragmentContext instead of recomputing them. |
| 1103 context.current.paint_offset.MoveBy(ToLayoutBox(object).PhysicalLocation()); | 1116 context.current.paint_offset.MoveBy(ToLayoutBox(object).PhysicalLocation()); |
| 1104 // This is a weird quirk that table cells paint as children of table rows, | 1117 // This is a weird quirk that table cells paint as children of table rows, |
| 1105 // but their location have the row's location baked-in. | 1118 // but their location have the row's location baked-in. |
| 1106 // Similar adjustment is done in LayoutTableCell::offsetFromContainer(). | 1119 // Similar adjustment is done in LayoutTableCell::offsetFromContainer(). |
| 1107 if (object.IsTableCell()) { | 1120 if (object.IsTableCell()) { |
| 1108 LayoutObject* parent_row = object.Parent(); | 1121 LayoutObject* parent_row = object.Parent(); |
| 1109 DCHECK(parent_row && parent_row->IsTableRow()); | 1122 DCHECK(parent_row && parent_row->IsTableRow()); |
| 1110 context.current.paint_offset.MoveBy( | 1123 context.current.paint_offset.MoveBy( |
| 1111 -ToLayoutBox(parent_row)->PhysicalLocation()); | 1124 -ToLayoutBox(parent_row)->PhysicalLocation()); |
| 1112 } | 1125 } |
| 1113 } | 1126 } |
| 1114 } | 1127 } |
| 1115 | 1128 |
| 1116 void PaintPropertyTreeBuilder::UpdateForObjectLocationAndSize( | 1129 void PaintPropertyTreeBuilder::UpdateForObjectLocationAndSize( |
| 1117 const LayoutObject& object, | 1130 const LayoutObject& object, |
| 1118 PaintPropertyTreeBuilderContext& context) { | 1131 const LayoutObject* container_for_absolute_position, |
| 1132 bool& is_actually_needed, |
| 1133 PaintPropertyTreeBuilderFragmentContext& context, |
| 1134 bool& force_subtree_update) { |
| 1119 #if DCHECK_IS_ON() | 1135 #if DCHECK_IS_ON() |
| 1120 FindPaintOffsetNeedingUpdateScope check_scope(object, context); | 1136 FindPaintOffsetNeedingUpdateScope check_scope(object, is_actually_needed); |
| 1121 #endif | 1137 #endif |
| 1122 | 1138 |
| 1123 if (object.IsBoxModelObject()) { | 1139 if (object.IsBoxModelObject()) { |
| 1124 UpdatePaintOffset(ToLayoutBoxModelObject(object), context); | 1140 UpdatePaintOffset(ToLayoutBoxModelObject(object), context, |
| 1125 UpdatePaintOffsetTranslation(ToLayoutBoxModelObject(object), context); | 1141 container_for_absolute_position); |
| 1142 UpdatePaintOffsetTranslation(ToLayoutBoxModelObject(object), context, |
| 1143 force_subtree_update); |
| 1126 } | 1144 } |
| 1127 | 1145 |
| 1128 if (object.PaintOffset() != context.current.paint_offset) { | 1146 if (object.PaintOffset() != context.current.paint_offset) { |
| 1129 // Many paint properties depend on paint offset so we force an update of | 1147 // Many paint properties depend on paint offset so we force an update of |
| 1130 // the entire subtree on paint offset changes. | 1148 // the entire subtree on paint offset changes. |
| 1131 context.force_subtree_update = true; | 1149 force_subtree_update = true; |
| 1132 | 1150 |
| 1133 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) { | 1151 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) { |
| 1134 object.GetMutableForPainting().SetShouldDoFullPaintInvalidation( | 1152 object.GetMutableForPainting().SetShouldDoFullPaintInvalidation( |
| 1135 kPaintInvalidationLocationChange); | 1153 kPaintInvalidationLocationChange); |
| 1136 } | 1154 } |
| 1137 object.GetMutableForPainting().SetPaintOffset(context.current.paint_offset); | 1155 object.GetMutableForPainting().SetPaintOffset(context.current.paint_offset); |
| 1138 } | 1156 } |
| 1139 | 1157 |
| 1140 if (!object.IsBox()) | 1158 if (!object.IsBox()) |
| 1141 return; | 1159 return; |
| (...skipping 17 matching lines...) Expand all Loading... |
| 1159 // transform-origin, and perspective-origin can depend on the size of the | 1177 // transform-origin, and perspective-origin can depend on the size of the |
| 1160 // frame rect, so force a property update if it changes. TODO(pdr): We | 1178 // frame rect, so force a property update if it changes. TODO(pdr): We |
| 1161 // only need to update properties if there are relative lengths. | 1179 // only need to update properties if there are relative lengths. |
| 1162 box.StyleRef().HasTransform() || box.StyleRef().HasPerspective() || | 1180 box.StyleRef().HasTransform() || box.StyleRef().HasPerspective() || |
| 1163 box_generates_property_nodes_for_mask_and_clip_path) | 1181 box_generates_property_nodes_for_mask_and_clip_path) |
| 1164 box.GetMutableForPainting().SetNeedsPaintPropertyUpdate(); | 1182 box.GetMutableForPainting().SetNeedsPaintPropertyUpdate(); |
| 1165 } | 1183 } |
| 1166 | 1184 |
| 1167 void PaintPropertyTreeBuilder::UpdatePaintProperties( | 1185 void PaintPropertyTreeBuilder::UpdatePaintProperties( |
| 1168 const LayoutObject& object, | 1186 const LayoutObject& object, |
| 1169 PaintPropertyTreeBuilderContext& context) { | 1187 PaintPropertyTreeBuilderContext& full_context) { |
| 1170 bool needs_paint_properties = | 1188 bool needs_paint_properties = |
| 1171 NeedsPaintOffsetTranslation(object) || NeedsTransform(object) || | 1189 NeedsPaintOffsetTranslation(object) || NeedsTransform(object) || |
| 1172 NeedsEffect(object) || NeedsTransformForNonRootSVG(object) || | 1190 NeedsEffect(object) || NeedsTransformForNonRootSVG(object) || |
| 1173 NeedsFilter(object) || NeedsCssClip(object) || | 1191 NeedsFilter(object) || NeedsCssClip(object) || |
| 1174 NeedsScrollbarPaintOffset(object) || NeedsOverflowScroll(object) || | 1192 NeedsScrollbarPaintOffset(object) || NeedsOverflowScroll(object) || |
| 1175 NeedsPerspective(object) || NeedsSVGLocalToBorderBoxTransform(object) || | 1193 NeedsPerspective(object) || NeedsSVGLocalToBorderBoxTransform(object) || |
| 1176 NeedsScrollTranslation(object) || NeedsCssClipFixedPosition(object); | 1194 NeedsScrollTranslation(object) || NeedsCssClipFixedPosition(object); |
| 1177 | 1195 |
| 1178 bool had_paint_properties = object.PaintProperties(); | 1196 bool had_paint_properties = object.PaintProperties(); |
| 1179 | 1197 |
| 1180 if (needs_paint_properties) { | 1198 if (needs_paint_properties) { |
| 1181 object.GetMutableForPainting().EnsurePaintProperties(); | 1199 object.GetMutableForPainting().EnsurePaintProperties(); |
| 1182 } else { | 1200 } else { |
| 1183 object.GetMutableForPainting().ClearPaintProperties(); | 1201 object.GetMutableForPainting().ClearPaintProperties(); |
| 1184 if (had_paint_properties) | 1202 if (had_paint_properties) |
| 1185 context.force_subtree_update = true; | 1203 full_context.force_subtree_update = true; |
| 1186 } | 1204 } |
| 1187 } | 1205 } |
| 1188 | 1206 |
| 1189 void PaintPropertyTreeBuilder::UpdatePropertiesForSelf( | 1207 void PaintPropertyTreeBuilder::UpdatePropertiesForSelf( |
| 1190 const LayoutObject& object, | 1208 const LayoutObject& object, |
| 1191 PaintPropertyTreeBuilderContext& context) { | 1209 PaintPropertyTreeBuilderContext& full_context) { |
| 1210 PaintPropertyTreeBuilderFragmentContext& context = full_context.fragments[0]; |
| 1192 if (object.IsSVGHiddenContainer()) { | 1211 if (object.IsSVGHiddenContainer()) { |
| 1193 // SVG resources are painted within one or more other locations in the | 1212 // SVG resources are painted within one or more other locations in the |
| 1194 // SVG during paint, and hence have their own independent paint property | 1213 // SVG during paint, and hence have their own independent paint property |
| 1195 // trees, paint offset, etc. | 1214 // trees, paint offset, etc. |
| 1196 context = PaintPropertyTreeBuilderContext(); | 1215 context = PaintPropertyTreeBuilderFragmentContext(); |
| 1197 } | 1216 } |
| 1198 | 1217 |
| 1199 UpdatePaintProperties(object, context); | 1218 UpdatePaintProperties(object, full_context); |
| 1219 |
| 1220 bool is_actually_needed = false; |
| 1221 #if DCHECK_IS_ON() |
| 1222 is_actually_needed = full_context.is_actually_needed; |
| 1223 #endif |
| 1200 | 1224 |
| 1201 // This is not in FindObjectPropertiesNeedingUpdateScope because paint offset | 1225 // This is not in FindObjectPropertiesNeedingUpdateScope because paint offset |
| 1202 // can change without needsPaintPropertyUpdate. | 1226 // can change without needsPaintPropertyUpdate. |
| 1203 UpdateForObjectLocationAndSize(object, context); | 1227 UpdateForObjectLocationAndSize( |
| 1228 object, full_context.container_for_absolute_position, is_actually_needed, |
| 1229 context, full_context.force_subtree_update); |
| 1204 | 1230 |
| 1205 #if DCHECK_IS_ON() | 1231 #if DCHECK_IS_ON() |
| 1206 FindObjectPropertiesNeedingUpdateScope check_needs_update_scope(object, | 1232 FindObjectPropertiesNeedingUpdateScope check_needs_update_scope( |
| 1207 context); | 1233 object, full_context.force_subtree_update); |
| 1208 #endif | 1234 #endif |
| 1209 | 1235 |
| 1210 if (object.IsBoxModelObject() || object.IsSVG()) { | 1236 if (object.IsBoxModelObject() || object.IsSVG()) { |
| 1211 UpdateTransform(object, context); | 1237 UpdateTransform(object, context, full_context.force_subtree_update); |
| 1212 UpdateCssClip(object, context); | 1238 UpdateCssClip(object, context, full_context.force_subtree_update); |
| 1213 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) { | 1239 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) { |
| 1214 UpdateEffect(object, context); | 1240 UpdateEffect(object, context, full_context.force_subtree_update); |
| 1215 UpdateFilter(object, context); | 1241 UpdateFilter(object, context, full_context.force_subtree_update); |
| 1216 } | 1242 } |
| 1217 UpdateLocalBorderBoxContext(object, context); | 1243 UpdateLocalBorderBoxContext(object, context, |
| 1218 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) | 1244 full_context.force_subtree_update); |
| 1219 UpdateScrollbarPaintOffset(object, context); | 1245 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) { |
| 1246 UpdateScrollbarPaintOffset(object, context, |
| 1247 full_context.force_subtree_update); |
| 1248 } |
| 1220 } | 1249 } |
| 1221 } | 1250 } |
| 1222 | 1251 |
| 1223 void PaintPropertyTreeBuilder::UpdatePropertiesForChildren( | 1252 void PaintPropertyTreeBuilder::UpdatePropertiesForChildren( |
| 1224 const LayoutObject& object, | 1253 const LayoutObject& object, |
| 1225 PaintPropertyTreeBuilderContext& context) { | 1254 PaintPropertyTreeBuilderContext& context) { |
| 1226 #if DCHECK_IS_ON() | |
| 1227 FindObjectPropertiesNeedingUpdateScope check_needs_update_scope(object, | |
| 1228 context); | |
| 1229 #endif | |
| 1230 | |
| 1231 if (!object.IsBoxModelObject() && !object.IsSVG()) | 1255 if (!object.IsBoxModelObject() && !object.IsSVG()) |
| 1232 return; | 1256 return; |
| 1233 | 1257 |
| 1234 UpdateOverflowClip(object, context); | 1258 for (auto& fragment_context : context.fragments) { |
| 1235 UpdatePerspective(object, context); | 1259 #if DCHECK_IS_ON() |
| 1236 UpdateSvgLocalToBorderBoxTransform(object, context); | 1260 FindObjectPropertiesNeedingUpdateScope check_needs_update_scope( |
| 1237 UpdateScrollAndScrollTranslation(object, context); | 1261 object, context.force_subtree_update); |
| 1238 UpdateOutOfFlowContext(object, context); | 1262 #endif |
| 1263 UpdateOverflowClip(object, fragment_context, context.force_subtree_update); |
| 1264 UpdatePerspective(object, fragment_context, context.force_subtree_update); |
| 1265 UpdateSvgLocalToBorderBoxTransform(object, fragment_context, |
| 1266 context.force_subtree_update); |
| 1267 UpdateScrollAndScrollTranslation(object, fragment_context, |
| 1268 context.force_subtree_update); |
| 1269 UpdateOutOfFlowContext(object, fragment_context, |
| 1270 context.force_subtree_update); |
| 1239 | 1271 |
| 1240 context.force_subtree_update |= object.SubtreeNeedsPaintPropertyUpdate(); | 1272 context.force_subtree_update |= object.SubtreeNeedsPaintPropertyUpdate(); |
| 1273 } |
| 1274 |
| 1275 if (object.CanContainAbsolutePositionObjects()) |
| 1276 context.container_for_absolute_position = &object; |
| 1241 } | 1277 } |
| 1242 | 1278 |
| 1243 } // namespace blink | 1279 } // namespace blink |
| OLD | NEW |