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