Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "core/paint/PaintPropertyTreeBuilder.h" | 5 #include "core/paint/PaintPropertyTreeBuilder.h" |
| 6 | 6 |
| 7 #include "core/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; | |
| 233 } | 232 } |
| 234 | 233 |
| 235 // We should use the same subpixel paint offset values for snapping | 234 // We should use the same subpixel paint offset values for snapping |
| 236 // regardless of whether a transform is present. If there is a transform | 235 // regardless of whether a transform is present. If there is a transform |
| 237 // we round the paint offset but keep around the residual fractional | 236 // we round the paint offset but keep around the residual fractional |
| 238 // component for the transformed content to paint with. In spv1 this was | 237 // component for the transformed content to paint with. In spv1 this was |
| 239 // called "subpixel accumulation". For more information, see | 238 // called "subpixel accumulation". For more information, see |
| 240 // PaintLayer::subpixelAccumulation() and | 239 // PaintLayer::subpixelAccumulation() and |
| 241 // PaintLayerPainter::paintFragmentByApplyingTransform. | 240 // PaintLayerPainter::paintFragmentByApplyingTransform. |
| 242 IntPoint roundedPaintOffset = roundedIntPoint(context.current.paintOffset); | 241 IntPoint roundedPaintOffset = roundedIntPoint(context.current.paintOffset); |
| 243 LayoutPoint fractionalPaintOffset = | 242 LayoutPoint fractionalPaintOffset = |
| 244 LayoutPoint(context.current.paintOffset - roundedPaintOffset); | 243 LayoutPoint(context.current.paintOffset - roundedPaintOffset); |
| 245 | 244 |
| 246 if (object.needsPaintPropertyUpdate() || context.forceSubtreeUpdate) { | 245 if (usesPaintOffsetTranslation) { |
|
pdr.
2017/02/14 05:18:41
Do we need to still early-out here if !(object.nee
Xianzhu
2017/02/14 19:23:34
No, because paint offset can change without needsP
| |
| 247 if (usesPaintOffsetTranslation) { | 246 auto& properties = object.getMutableForPainting().ensurePaintProperties(); |
| 248 auto& properties = object.getMutableForPainting().ensurePaintProperties(); | 247 context.forceSubtreeUpdate |= properties.updatePaintOffsetTranslation( |
| 249 context.forceSubtreeUpdate |= properties.updatePaintOffsetTranslation( | 248 context.current.transform, |
| 250 context.current.transform, | 249 TransformationMatrix().translate(roundedPaintOffset.x(), |
| 251 TransformationMatrix().translate(roundedPaintOffset.x(), | 250 roundedPaintOffset.y()), |
| 252 roundedPaintOffset.y()), | 251 FloatPoint3D(), context.current.shouldFlattenInheritedTransform, |
| 253 FloatPoint3D(), context.current.shouldFlattenInheritedTransform, | 252 context.current.renderingContextId); |
| 254 context.current.renderingContextId); | 253 } else { |
| 255 } else { | 254 if (auto* properties = object.getMutableForPainting().paintProperties()) |
| 256 if (auto* properties = object.getMutableForPainting().paintProperties()) | 255 context.forceSubtreeUpdate |= properties->clearPaintOffsetTranslation(); |
| 257 context.forceSubtreeUpdate |= properties->clearPaintOffsetTranslation(); | |
| 258 } | |
| 259 } | 256 } |
| 260 | 257 |
| 261 const auto* properties = object.paintProperties(); | 258 const auto* properties = object.paintProperties(); |
| 262 if (properties && properties->paintOffsetTranslation()) { | 259 if (properties && properties->paintOffsetTranslation()) { |
| 263 context.current.transform = properties->paintOffsetTranslation(); | 260 context.current.transform = properties->paintOffsetTranslation(); |
| 264 context.current.paintOffset = fractionalPaintOffset; | 261 context.current.paintOffset = fractionalPaintOffset; |
| 265 if (RuntimeEnabledFeatures::rootLayerScrollingEnabled() && | 262 if (RuntimeEnabledFeatures::rootLayerScrollingEnabled() && |
| 266 object.isLayoutView()) { | 263 object.isLayoutView()) { |
| 267 context.absolutePosition.transform = properties->paintOffsetTranslation(); | 264 context.absolutePosition.transform = properties->paintOffsetTranslation(); |
| 268 context.fixedPosition.transform = properties->paintOffsetTranslation(); | 265 context.fixedPosition.transform = properties->paintOffsetTranslation(); |
| (...skipping 587 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 856 return; | 853 return; |
| 857 } | 854 } |
| 858 } | 855 } |
| 859 | 856 |
| 860 if (object.needsPaintPropertyUpdate() || context.forceSubtreeUpdate) { | 857 if (object.needsPaintPropertyUpdate() || context.forceSubtreeUpdate) { |
| 861 if (auto* properties = object.getMutableForPainting().paintProperties()) | 858 if (auto* properties = object.getMutableForPainting().paintProperties()) |
| 862 context.forceSubtreeUpdate |= properties->clearCssClipFixedPosition(); | 859 context.forceSubtreeUpdate |= properties->clearCssClipFixedPosition(); |
| 863 } | 860 } |
| 864 } | 861 } |
| 865 | 862 |
| 866 void PaintPropertyTreeBuilder::updateContextForBoxPosition( | 863 void PaintPropertyTreeBuilder::updatePaintOffset( |
| 867 const LayoutObject& object, | 864 const LayoutBoxModelObject& object, |
| 868 PaintPropertyTreeBuilderContext& context) { | 865 PaintPropertyTreeBuilderContext& context) { |
| 869 if (!object.isBoxModelObject()) | 866 if (object.isFloating()) |
| 870 return; | |
| 871 | |
| 872 const LayoutBoxModelObject& boxModelObject = toLayoutBoxModelObject(object); | |
| 873 | |
| 874 if (boxModelObject.isFloating()) | |
| 875 context.current.paintOffset = context.paintOffsetForFloat; | 867 context.current.paintOffset = context.paintOffsetForFloat; |
| 876 | 868 |
| 877 // Multicolumn spanners are painted starting at the multicolumn container (but | 869 // Multicolumn spanners are painted starting at the multicolumn container (but |
| 878 // still inherit properties in layout-tree order) so reset the paint offset. | 870 // still inherit properties in layout-tree order) so reset the paint offset. |
| 879 if (boxModelObject.isColumnSpanAll()) | 871 if (object.isColumnSpanAll()) |
| 880 context.current.paintOffset = boxModelObject.container()->paintOffset(); | 872 context.current.paintOffset = object.container()->paintOffset(); |
| 881 | 873 |
| 882 switch (object.styleRef().position()) { | 874 switch (object.styleRef().position()) { |
| 883 case EPosition::kStatic: | 875 case EPosition::kStatic: |
| 884 break; | 876 break; |
| 885 case EPosition::kRelative: | 877 case EPosition::kRelative: |
| 886 context.current.paintOffset += boxModelObject.offsetForInFlowPosition(); | 878 context.current.paintOffset += object.offsetForInFlowPosition(); |
| 887 break; | 879 break; |
| 888 case EPosition::kAbsolute: { | 880 case EPosition::kAbsolute: { |
| 889 DCHECK(context.containerForAbsolutePosition == | 881 DCHECK(context.containerForAbsolutePosition == object.container()); |
| 890 boxModelObject.container()); | |
| 891 context.current = context.absolutePosition; | 882 context.current = context.absolutePosition; |
| 892 | 883 |
| 893 // Absolutely positioned content in an inline should be positioned | 884 // Absolutely positioned content in an inline should be positioned |
| 894 // relative to the inline. | 885 // relative to the inline. |
| 895 const LayoutObject* container = context.containerForAbsolutePosition; | 886 const LayoutObject* container = context.containerForAbsolutePosition; |
| 896 if (container && container->isInFlowPositioned() && | 887 if (container && container->isInFlowPositioned() && |
| 897 container->isLayoutInline()) { | 888 container->isLayoutInline()) { |
| 898 DCHECK(object.isBox()); | 889 DCHECK(object.isBox()); |
| 899 context.current.paintOffset += | 890 context.current.paintOffset += |
| 900 toLayoutInline(container)->offsetForInFlowPositionedInline( | 891 toLayoutInline(container)->offsetForInFlowPositionedInline( |
| 901 toLayoutBox(object)); | 892 toLayoutBox(object)); |
| 902 } | 893 } |
| 903 break; | 894 break; |
| 904 } | 895 } |
| 905 case EPosition::kSticky: | 896 case EPosition::kSticky: |
| 906 context.current.paintOffset += boxModelObject.offsetForInFlowPosition(); | 897 context.current.paintOffset += object.offsetForInFlowPosition(); |
| 907 break; | 898 break; |
| 908 case EPosition::kFixed: | 899 case EPosition::kFixed: |
| 909 context.current = context.fixedPosition; | 900 context.current = context.fixedPosition; |
| 910 break; | 901 break; |
| 911 default: | 902 default: |
| 912 ASSERT_NOT_REACHED(); | 903 ASSERT_NOT_REACHED(); |
| 913 } | 904 } |
| 914 | 905 |
| 915 if (boxModelObject.isBox()) { | 906 if (object.isBox()) { |
| 916 // TODO(pdr): Several calls in this function walk back up the tree to | 907 // TODO(pdr): Several calls in this function walk back up the tree to |
| 917 // calculate containers (e.g., physicalLocation, offsetForInFlowPosition*). | 908 // calculate containers (e.g., physicalLocation, offsetForInFlowPosition*). |
| 918 // The containing block and other containers can be stored on | 909 // The containing block and other containers can be stored on |
| 919 // PaintPropertyTreeBuilderContext instead of recomputing them. | 910 // PaintPropertyTreeBuilderContext instead of recomputing them. |
| 920 context.current.paintOffset.moveBy( | 911 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, | 912 // 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. | 913 // but their location have the row's location baked-in. |
| 924 // Similar adjustment is done in LayoutTableCell::offsetFromContainer(). | 914 // Similar adjustment is done in LayoutTableCell::offsetFromContainer(). |
| 925 if (boxModelObject.isTableCell()) { | 915 if (object.isTableCell()) { |
| 926 LayoutObject* parentRow = boxModelObject.parent(); | 916 LayoutObject* parentRow = object.parent(); |
| 927 DCHECK(parentRow && parentRow->isTableRow()); | 917 DCHECK(parentRow && parentRow->isTableRow()); |
| 928 context.current.paintOffset.moveBy( | 918 context.current.paintOffset.moveBy( |
| 929 -toLayoutBox(parentRow)->physicalLocation()); | 919 -toLayoutBox(parentRow)->physicalLocation()); |
| 930 } | 920 } |
| 931 } | 921 } |
| 922 } | |
| 923 | |
| 924 void PaintPropertyTreeBuilder::updateContextForBoxPosition( | |
| 925 const LayoutObject& object, | |
| 926 PaintPropertyTreeBuilderContext& context) { | |
| 927 if (!object.isBoxModelObject()) { | |
| 928 object.getMutableForPainting().setPaintOffset(context.current.paintOffset); | |
| 929 return; | |
| 930 } | |
| 931 | |
| 932 updatePaintOffset(toLayoutBoxModelObject(object), context); | |
| 933 updatePaintOffsetTranslation(toLayoutBoxModelObject(object), context); | |
| 934 | |
| 935 if (object.paintOffset() == context.current.paintOffset) | |
| 936 return; | |
| 932 | 937 |
| 933 // Many paint properties depend on paint offset so we force an update of | 938 // Many paint properties depend on paint offset so we force an update of |
| 934 // the entire subtree on paint offset changes. | 939 // the entire subtree on paint offset changes. |
| 935 if (object.paintOffset() != context.current.paintOffset) | 940 context.forceSubtreeUpdate = true; |
| 936 context.forceSubtreeUpdate = true; | 941 |
| 942 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) { | |
| 943 object.getMutableForPainting().setShouldDoFullPaintInvalidation( | |
| 944 PaintInvalidationLocationChange); | |
| 945 } | |
| 946 object.getMutableForPainting().setPaintOffset(context.current.paintOffset); | |
| 937 } | 947 } |
| 938 | 948 |
| 939 void PaintPropertyTreeBuilder::updatePropertiesForSelf( | 949 void PaintPropertyTreeBuilder::updatePropertiesForSelf( |
| 940 const LayoutObject& object, | 950 const LayoutObject& object, |
| 941 PaintPropertyTreeBuilderContext& context) { | 951 PaintPropertyTreeBuilderContext& context) { |
| 942 #if DCHECK_IS_ON() | 952 #if DCHECK_IS_ON() |
| 943 FindObjectPropertiesNeedingUpdateScope checkNeedsUpdateScope(object, context); | 953 FindObjectPropertiesNeedingUpdateScope checkNeedsUpdateScope(object, context); |
| 944 #endif | 954 #endif |
| 945 | 955 |
| 946 if (object.isBoxModelObject() || object.isSVG()) { | 956 if (object.isBoxModelObject() || object.isSVG()) { |
| 947 updatePaintOffsetTranslation(object, context); | |
| 948 updateTransform(object, context); | 957 updateTransform(object, context); |
| 949 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) | 958 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) |
| 950 updateEffect(object, context); | 959 updateEffect(object, context); |
| 951 updateCssClip(object, context); | 960 updateCssClip(object, context); |
| 952 updateLocalBorderBoxContext(object, context); | 961 updateLocalBorderBoxContext(object, context); |
| 953 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) | 962 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) |
| 954 updateScrollbarPaintOffset(object, context); | 963 updateScrollbarPaintOffset(object, context); |
| 955 } | 964 } |
| 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 } | 965 } |
| 966 | 966 |
| 967 void PaintPropertyTreeBuilder::updatePropertiesForChildren( | 967 void PaintPropertyTreeBuilder::updatePropertiesForChildren( |
| 968 const LayoutObject& object, | 968 const LayoutObject& object, |
| 969 PaintPropertyTreeBuilderContext& context) { | 969 PaintPropertyTreeBuilderContext& context) { |
| 970 #if DCHECK_IS_ON() | 970 #if DCHECK_IS_ON() |
| 971 FindObjectPropertiesNeedingUpdateScope checkNeedsUpdateScope(object, context); | 971 FindObjectPropertiesNeedingUpdateScope checkNeedsUpdateScope(object, context); |
| 972 #endif | 972 #endif |
| 973 | 973 |
| 974 if (!object.isBoxModelObject() && !object.isSVG()) | 974 if (!object.isBoxModelObject() && !object.isSVG()) |
| 975 return; | 975 return; |
| 976 | 976 |
| 977 updateOverflowClip(object, context); | 977 updateOverflowClip(object, context); |
| 978 updatePerspective(object, context); | 978 updatePerspective(object, context); |
| 979 updateSvgLocalToBorderBoxTransform(object, context); | 979 updateSvgLocalToBorderBoxTransform(object, context); |
| 980 updateScrollAndScrollTranslation(object, context); | 980 updateScrollAndScrollTranslation(object, context); |
| 981 updateOutOfFlowContext(object, context); | 981 updateOutOfFlowContext(object, context); |
| 982 | 982 |
| 983 context.forceSubtreeUpdate |= object.subtreeNeedsPaintPropertyUpdate(); | 983 context.forceSubtreeUpdate |= object.subtreeNeedsPaintPropertyUpdate(); |
| 984 } | 984 } |
| 985 | 985 |
| 986 } // namespace blink | 986 } // namespace blink |
| OLD | NEW |