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/dom/DOMNodeIds.h" | 7 #include "core/dom/DOMNodeIds.h" |
8 #include "core/frame/FrameView.h" | 8 #include "core/frame/FrameView.h" |
9 #include "core/frame/LocalFrame.h" | 9 #include "core/frame/LocalFrame.h" |
10 #include "core/frame/Settings.h" | 10 #include "core/frame/Settings.h" |
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
209 context.fixedPosition = context.current; | 209 context.fixedPosition = context.current; |
210 context.fixedPosition.transform = fixedTransformNode; | 210 context.fixedPosition.transform = fixedTransformNode; |
211 context.fixedPosition.scroll = fixedScrollNode; | 211 context.fixedPosition.scroll = fixedScrollNode; |
212 | 212 |
213 std::unique_ptr<PropertyTreeState> contentsState(new PropertyTreeState( | 213 std::unique_ptr<PropertyTreeState> contentsState(new PropertyTreeState( |
214 context.current.transform, context.current.clip, context.currentEffect)); | 214 context.current.transform, context.current.clip, context.currentEffect)); |
215 frameView.setTotalPropertyTreeStateForContents(std::move(contentsState)); | 215 frameView.setTotalPropertyTreeStateForContents(std::move(contentsState)); |
216 } | 216 } |
217 | 217 |
218 void PaintPropertyTreeBuilder::updatePaintOffsetTranslation( | 218 void PaintPropertyTreeBuilder::updatePaintOffsetTranslation( |
219 const LayoutObject& object, | 219 const LayoutBoxModelObject& object, |
220 PaintPropertyTreeBuilderContext& context) { | 220 PaintPropertyTreeBuilderContext& context) { |
221 bool usesPaintOffsetTranslation = false; | 221 bool usesPaintOffsetTranslation = false; |
222 if (RuntimeEnabledFeatures::rootLayerScrollingEnabled() && | 222 if (RuntimeEnabledFeatures::rootLayerScrollingEnabled() && |
223 object.isLayoutView()) { | 223 object.isLayoutView()) { |
224 // Root layer scrolling always creates a translation node for LayoutView to | 224 // Root layer scrolling always creates a translation node for LayoutView to |
225 // ensure fixed and absolute contexts use the correct transform space. | 225 // ensure fixed and absolute contexts use the correct transform space. |
226 usesPaintOffsetTranslation = true; | 226 usesPaintOffsetTranslation = true; |
227 } else if (object.isBoxModelObject() && | 227 } else if (object.hasLayer() && |
228 context.current.paintOffset != LayoutPoint()) { | 228 context.current.paintOffset != LayoutPoint() && |
229 PaintLayer* layer = toLayoutBoxModelObject(object).layer(); | 229 object.layer()->paintsWithTransform( |
230 if (layer && | 230 GlobalPaintFlattenCompositingLayers)) { |
231 layer->paintsWithTransform(GlobalPaintFlattenCompositingLayers)) | 231 usesPaintOffsetTranslation = true; |
232 usesPaintOffsetTranslation = true; | 232 } |
| 233 |
| 234 if (!usesPaintOffsetTranslation) { |
| 235 if (auto* properties = object.getMutableForPainting().paintProperties()) |
| 236 context.forceSubtreeUpdate |= properties->clearPaintOffsetTranslation(); |
| 237 return; |
233 } | 238 } |
234 | 239 |
235 // We should use the same subpixel paint offset values for snapping | 240 // We should use the same subpixel paint offset values for snapping |
236 // regardless of whether a transform is present. If there is a transform | 241 // regardless of whether a transform is present. If there is a transform |
237 // we round the paint offset but keep around the residual fractional | 242 // we round the paint offset but keep around the residual fractional |
238 // component for the transformed content to paint with. In spv1 this was | 243 // component for the transformed content to paint with. In spv1 this was |
239 // called "subpixel accumulation". For more information, see | 244 // called "subpixel accumulation". For more information, see |
240 // PaintLayer::subpixelAccumulation() and | 245 // PaintLayer::subpixelAccumulation() and |
241 // PaintLayerPainter::paintFragmentByApplyingTransform. | 246 // PaintLayerPainter::paintFragmentByApplyingTransform. |
242 IntPoint roundedPaintOffset = roundedIntPoint(context.current.paintOffset); | 247 IntPoint roundedPaintOffset = roundedIntPoint(context.current.paintOffset); |
243 LayoutPoint fractionalPaintOffset = | 248 LayoutPoint fractionalPaintOffset = |
244 LayoutPoint(context.current.paintOffset - roundedPaintOffset); | 249 LayoutPoint(context.current.paintOffset - roundedPaintOffset); |
245 | 250 |
246 if (object.needsPaintPropertyUpdate() || context.forceSubtreeUpdate) { | 251 auto& properties = object.getMutableForPainting().ensurePaintProperties(); |
247 if (usesPaintOffsetTranslation) { | 252 context.forceSubtreeUpdate |= properties.updatePaintOffsetTranslation( |
248 auto& properties = object.getMutableForPainting().ensurePaintProperties(); | 253 context.current.transform, |
249 context.forceSubtreeUpdate |= properties.updatePaintOffsetTranslation( | 254 TransformationMatrix().translate(roundedPaintOffset.x(), |
250 context.current.transform, | 255 roundedPaintOffset.y()), |
251 TransformationMatrix().translate(roundedPaintOffset.x(), | 256 FloatPoint3D(), context.current.shouldFlattenInheritedTransform, |
252 roundedPaintOffset.y()), | 257 context.current.renderingContextId); |
253 FloatPoint3D(), context.current.shouldFlattenInheritedTransform, | |
254 context.current.renderingContextId); | |
255 } else { | |
256 if (auto* properties = object.getMutableForPainting().paintProperties()) | |
257 context.forceSubtreeUpdate |= properties->clearPaintOffsetTranslation(); | |
258 } | |
259 } | |
260 | 258 |
261 const auto* properties = object.paintProperties(); | 259 context.current.transform = properties.paintOffsetTranslation(); |
262 if (properties && properties->paintOffsetTranslation()) { | 260 context.current.paintOffset = fractionalPaintOffset; |
263 context.current.transform = properties->paintOffsetTranslation(); | 261 if (RuntimeEnabledFeatures::rootLayerScrollingEnabled() && |
264 context.current.paintOffset = fractionalPaintOffset; | 262 object.isLayoutView()) { |
265 if (RuntimeEnabledFeatures::rootLayerScrollingEnabled() && | 263 context.absolutePosition.transform = properties.paintOffsetTranslation(); |
266 object.isLayoutView()) { | 264 context.fixedPosition.transform = properties.paintOffsetTranslation(); |
267 context.absolutePosition.transform = properties->paintOffsetTranslation(); | 265 context.absolutePosition.paintOffset = LayoutPoint(); |
268 context.fixedPosition.transform = properties->paintOffsetTranslation(); | 266 context.fixedPosition.paintOffset = LayoutPoint(); |
269 context.absolutePosition.paintOffset = LayoutPoint(); | |
270 context.fixedPosition.paintOffset = LayoutPoint(); | |
271 } | |
272 } | 267 } |
273 } | 268 } |
274 | 269 |
275 // SVG does not use the general transform update of |updateTransform|, instead | 270 // SVG does not use the general transform update of |updateTransform|, instead |
276 // creating a transform node for SVG-specific transforms without 3D. | 271 // creating a transform node for SVG-specific transforms without 3D. |
277 void PaintPropertyTreeBuilder::updateTransformForNonRootSVG( | 272 void PaintPropertyTreeBuilder::updateTransformForNonRootSVG( |
278 const LayoutObject& object, | 273 const LayoutObject& object, |
279 PaintPropertyTreeBuilderContext& context) { | 274 PaintPropertyTreeBuilderContext& context) { |
280 DCHECK(object.isSVGChild()); | 275 DCHECK(object.isSVGChild()); |
281 // SVG does not use paint offset internally, except for SVGForeignObject which | 276 // SVG does not use paint offset internally, except for SVGForeignObject which |
(...skipping 574 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
856 return; | 851 return; |
857 } | 852 } |
858 } | 853 } |
859 | 854 |
860 if (object.needsPaintPropertyUpdate() || context.forceSubtreeUpdate) { | 855 if (object.needsPaintPropertyUpdate() || context.forceSubtreeUpdate) { |
861 if (auto* properties = object.getMutableForPainting().paintProperties()) | 856 if (auto* properties = object.getMutableForPainting().paintProperties()) |
862 context.forceSubtreeUpdate |= properties->clearCssClipFixedPosition(); | 857 context.forceSubtreeUpdate |= properties->clearCssClipFixedPosition(); |
863 } | 858 } |
864 } | 859 } |
865 | 860 |
866 void PaintPropertyTreeBuilder::updateContextForBoxPosition( | 861 void PaintPropertyTreeBuilder::updatePaintOffset( |
867 const LayoutObject& object, | 862 const LayoutBoxModelObject& object, |
868 PaintPropertyTreeBuilderContext& context) { | 863 PaintPropertyTreeBuilderContext& context) { |
869 if (!object.isBoxModelObject()) | 864 if (object.isFloating()) |
870 return; | |
871 | |
872 const LayoutBoxModelObject& boxModelObject = toLayoutBoxModelObject(object); | |
873 | |
874 if (boxModelObject.isFloating()) | |
875 context.current.paintOffset = context.paintOffsetForFloat; | 865 context.current.paintOffset = context.paintOffsetForFloat; |
876 | 866 |
877 // Multicolumn spanners are painted starting at the multicolumn container (but | 867 // Multicolumn spanners are painted starting at the multicolumn container (but |
878 // still inherit properties in layout-tree order) so reset the paint offset. | 868 // still inherit properties in layout-tree order) so reset the paint offset. |
879 if (boxModelObject.isColumnSpanAll()) | 869 if (object.isColumnSpanAll()) |
880 context.current.paintOffset = boxModelObject.container()->paintOffset(); | 870 context.current.paintOffset = object.container()->paintOffset(); |
881 | 871 |
882 switch (object.styleRef().position()) { | 872 switch (object.styleRef().position()) { |
883 case EPosition::kStatic: | 873 case EPosition::kStatic: |
884 break; | 874 break; |
885 case EPosition::kRelative: | 875 case EPosition::kRelative: |
886 context.current.paintOffset += boxModelObject.offsetForInFlowPosition(); | 876 context.current.paintOffset += object.offsetForInFlowPosition(); |
887 break; | 877 break; |
888 case EPosition::kAbsolute: { | 878 case EPosition::kAbsolute: { |
889 DCHECK(context.containerForAbsolutePosition == | 879 DCHECK(context.containerForAbsolutePosition == object.container()); |
890 boxModelObject.container()); | |
891 context.current = context.absolutePosition; | 880 context.current = context.absolutePosition; |
892 | 881 |
893 // Absolutely positioned content in an inline should be positioned | 882 // Absolutely positioned content in an inline should be positioned |
894 // relative to the inline. | 883 // relative to the inline. |
895 const LayoutObject* container = context.containerForAbsolutePosition; | 884 const LayoutObject* container = context.containerForAbsolutePosition; |
896 if (container && container->isInFlowPositioned() && | 885 if (container && container->isInFlowPositioned() && |
897 container->isLayoutInline()) { | 886 container->isLayoutInline()) { |
898 DCHECK(object.isBox()); | 887 DCHECK(object.isBox()); |
899 context.current.paintOffset += | 888 context.current.paintOffset += |
900 toLayoutInline(container)->offsetForInFlowPositionedInline( | 889 toLayoutInline(container)->offsetForInFlowPositionedInline( |
901 toLayoutBox(object)); | 890 toLayoutBox(object)); |
902 } | 891 } |
903 break; | 892 break; |
904 } | 893 } |
905 case EPosition::kSticky: | 894 case EPosition::kSticky: |
906 context.current.paintOffset += boxModelObject.offsetForInFlowPosition(); | 895 context.current.paintOffset += object.offsetForInFlowPosition(); |
907 break; | 896 break; |
908 case EPosition::kFixed: | 897 case EPosition::kFixed: |
909 context.current = context.fixedPosition; | 898 context.current = context.fixedPosition; |
910 break; | 899 break; |
911 default: | 900 default: |
912 ASSERT_NOT_REACHED(); | 901 ASSERT_NOT_REACHED(); |
913 } | 902 } |
914 | 903 |
915 if (boxModelObject.isBox()) { | 904 if (object.isBox()) { |
916 // TODO(pdr): Several calls in this function walk back up the tree to | 905 // TODO(pdr): Several calls in this function walk back up the tree to |
917 // calculate containers (e.g., physicalLocation, offsetForInFlowPosition*). | 906 // calculate containers (e.g., physicalLocation, offsetForInFlowPosition*). |
918 // The containing block and other containers can be stored on | 907 // The containing block and other containers can be stored on |
919 // PaintPropertyTreeBuilderContext instead of recomputing them. | 908 // PaintPropertyTreeBuilderContext instead of recomputing them. |
920 context.current.paintOffset.moveBy( | 909 context.current.paintOffset.moveBy(toLayoutBox(object).physicalLocation()); |
921 toLayoutBox(boxModelObject).physicalLocation()); | |
922 // This is a weird quirk that table cells paint as children of table rows, | 910 // This is a weird quirk that table cells paint as children of table rows, |
923 // but their location have the row's location baked-in. | 911 // but their location have the row's location baked-in. |
924 // Similar adjustment is done in LayoutTableCell::offsetFromContainer(). | 912 // Similar adjustment is done in LayoutTableCell::offsetFromContainer(). |
925 if (boxModelObject.isTableCell()) { | 913 if (object.isTableCell()) { |
926 LayoutObject* parentRow = boxModelObject.parent(); | 914 LayoutObject* parentRow = object.parent(); |
927 DCHECK(parentRow && parentRow->isTableRow()); | 915 DCHECK(parentRow && parentRow->isTableRow()); |
928 context.current.paintOffset.moveBy( | 916 context.current.paintOffset.moveBy( |
929 -toLayoutBox(parentRow)->physicalLocation()); | 917 -toLayoutBox(parentRow)->physicalLocation()); |
930 } | 918 } |
931 } | 919 } |
| 920 } |
| 921 |
| 922 void PaintPropertyTreeBuilder::updateContextForBoxPosition( |
| 923 const LayoutObject& object, |
| 924 PaintPropertyTreeBuilderContext& context) { |
| 925 if (object.isBoxModelObject()) { |
| 926 updatePaintOffset(toLayoutBoxModelObject(object), context); |
| 927 updatePaintOffsetTranslation(toLayoutBoxModelObject(object), context); |
| 928 } |
| 929 |
| 930 if (object.paintOffset() == context.current.paintOffset) |
| 931 return; |
932 | 932 |
933 // Many paint properties depend on paint offset so we force an update of | 933 // Many paint properties depend on paint offset so we force an update of |
934 // the entire subtree on paint offset changes. | 934 // the entire subtree on paint offset changes. |
935 if (object.paintOffset() != context.current.paintOffset) | 935 context.forceSubtreeUpdate = true; |
936 context.forceSubtreeUpdate = true; | 936 |
| 937 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) { |
| 938 object.getMutableForPainting().setShouldDoFullPaintInvalidation( |
| 939 PaintInvalidationLocationChange); |
| 940 } |
| 941 object.getMutableForPainting().setPaintOffset(context.current.paintOffset); |
937 } | 942 } |
938 | 943 |
939 void PaintPropertyTreeBuilder::updatePropertiesForSelf( | 944 void PaintPropertyTreeBuilder::updatePropertiesForSelf( |
940 const LayoutObject& object, | 945 const LayoutObject& object, |
941 PaintPropertyTreeBuilderContext& context) { | 946 PaintPropertyTreeBuilderContext& context) { |
942 #if DCHECK_IS_ON() | 947 #if DCHECK_IS_ON() |
943 FindObjectPropertiesNeedingUpdateScope checkNeedsUpdateScope(object, context); | 948 FindObjectPropertiesNeedingUpdateScope checkNeedsUpdateScope(object, context); |
944 #endif | 949 #endif |
945 | 950 |
946 if (object.isBoxModelObject() || object.isSVG()) { | 951 if (object.isBoxModelObject() || object.isSVG()) { |
947 updatePaintOffsetTranslation(object, context); | |
948 updateTransform(object, context); | 952 updateTransform(object, context); |
949 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) | 953 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) |
950 updateEffect(object, context); | 954 updateEffect(object, context); |
951 updateCssClip(object, context); | 955 updateCssClip(object, context); |
952 updateLocalBorderBoxContext(object, context); | 956 updateLocalBorderBoxContext(object, context); |
953 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) | 957 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) |
954 updateScrollbarPaintOffset(object, context); | 958 updateScrollbarPaintOffset(object, context); |
955 } | 959 } |
956 | |
957 if (object.needsPaintPropertyUpdate() || context.forceSubtreeUpdate) { | |
958 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled() && | |
959 object.paintOffset() != context.current.paintOffset) { | |
960 object.getMutableForPainting().setShouldDoFullPaintInvalidation( | |
961 PaintInvalidationLocationChange); | |
962 } | |
963 object.getMutableForPainting().setPaintOffset(context.current.paintOffset); | |
964 } | |
965 } | 960 } |
966 | 961 |
967 void PaintPropertyTreeBuilder::updatePropertiesForChildren( | 962 void PaintPropertyTreeBuilder::updatePropertiesForChildren( |
968 const LayoutObject& object, | 963 const LayoutObject& object, |
969 PaintPropertyTreeBuilderContext& context) { | 964 PaintPropertyTreeBuilderContext& context) { |
970 #if DCHECK_IS_ON() | 965 #if DCHECK_IS_ON() |
971 FindObjectPropertiesNeedingUpdateScope checkNeedsUpdateScope(object, context); | 966 FindObjectPropertiesNeedingUpdateScope checkNeedsUpdateScope(object, context); |
972 #endif | 967 #endif |
973 | 968 |
974 if (!object.isBoxModelObject() && !object.isSVG()) | 969 if (!object.isBoxModelObject() && !object.isSVG()) |
975 return; | 970 return; |
976 | 971 |
977 updateOverflowClip(object, context); | 972 updateOverflowClip(object, context); |
978 updatePerspective(object, context); | 973 updatePerspective(object, context); |
979 updateSvgLocalToBorderBoxTransform(object, context); | 974 updateSvgLocalToBorderBoxTransform(object, context); |
980 updateScrollAndScrollTranslation(object, context); | 975 updateScrollAndScrollTranslation(object, context); |
981 updateOutOfFlowContext(object, context); | 976 updateOutOfFlowContext(object, context); |
982 | 977 |
983 context.forceSubtreeUpdate |= object.subtreeNeedsPaintPropertyUpdate(); | 978 context.forceSubtreeUpdate |= object.subtreeNeedsPaintPropertyUpdate(); |
984 } | 979 } |
985 | 980 |
986 } // namespace blink | 981 } // namespace blink |
OLD | NEW |