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 |