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/PrePaintTreeWalk.h" |
| 6 | 6 |
| 7 #include "core/frame/FrameView.h" | 7 #include "core/frame/FrameView.h" |
| 8 #include "core/layout/LayoutPart.h" | 8 #include "core/layout/LayoutPart.h" |
| 9 #include "core/layout/LayoutView.h" | 9 #include "core/layout/LayoutView.h" |
| 10 #include "core/paint/ObjectPaintProperties.h" | 10 #include "core/paint/ObjectPaintProperties.h" |
| 11 #include "core/paint/PaintLayer.h" | 11 #include "core/paint/PaintLayer.h" |
| 12 #include "platform/graphics/paint/ClipPaintPropertyNode.h" | 12 #include "platform/graphics/paint/ClipPaintPropertyNode.h" |
| 13 #include "platform/graphics/paint/TransformPaintPropertyNode.h" | 13 #include "platform/graphics/paint/TransformPaintPropertyNode.h" |
| 14 #include "platform/transforms/TransformationMatrix.h" | 14 #include "platform/transforms/TransformationMatrix.h" |
| 15 | 15 |
| 16 namespace blink { | 16 namespace blink { |
| 17 | 17 |
| 18 // The context for layout tree walk. | 18 // The context for layout tree walk. |
| 19 // The walk will be done in the primary tree order (= DOM order), thus the conte xt will also be | 19 // The walk will be done in the primary tree order (= DOM order), thus the conte xt will also be |
| 20 // responsible for bookkeeping tree state in other order, for example, the most recent position | 20 // responsible for bookkeeping tree state in other order, for example, the most recent position |
| 21 // container seen. | 21 // container seen. |
| 22 struct PaintPropertyTreeBuilderContext { | 22 struct PrePaintTreeWalkContext { |
| 23 PaintPropertyTreeBuilderContext() | 23 PrePaintTreeWalkContext() |
| 24 : currentTransform(nullptr) | 24 : paintInvalidationContainer(nullptr) |
| 25 , currentClip(nullptr) | 25 , paintInvalidationContainerForOutOfFlowPositioned(nullptr) |
|
trchen
2016/03/11 23:09:39
The name of the variable isn't accurate. Paint inv
| |
| 26 , transformForAbsolutePosition(nullptr) | 26 { } |
| 27 , clipForAbsolutePosition(nullptr) | 27 |
| 28 , transformForFixedPosition(nullptr) | 28 // TODO(wangxianzhu): The RefPtrs are needed for SPv1 which doesn't save the properties |
| 29 , clipForFixedPosition(nullptr) | 29 // into LayoutObjects. Change them to normal pointers for SPv2. |
| 30 , currentEffect(nullptr) { } | |
| 31 | 30 |
| 32 // The combination of a transform and paint offset describes a linear space. | 31 // The combination of a transform and paint offset describes a linear space. |
| 33 // When a layout object recur to its children, the main context is expected to refer | 32 // When a layout object recur to its children, the main context is expected to refer |
| 34 // the object's border box, then the callee will derive its own border box b y translating | 33 // the object's border box, then the callee will derive its own border box b y translating |
| 35 // the space with its own layout location. | 34 // the space with its own layout location. |
| 36 TransformPaintPropertyNode* currentTransform; | 35 RefPtr<TransformPaintPropertyNode> currentTransform; |
| 37 LayoutPoint paintOffset; | 36 LayoutPoint paintOffset; |
| 38 // The clip node describes the accumulated raster clip for the current subtr ee. | 37 // The clip node describes the accumulated raster clip for the current subtr ee. |
| 39 // Note that the computed raster region in canvas space for a clip node is i ndependent from | 38 // Note that the computed raster region in canvas space for a clip node is i ndependent from |
| 40 // the transform and paint offset above. Also the actual raster region may b e affected | 39 // the transform and paint offset above. Also the actual raster region may b e affected |
| 41 // by layerization and occlusion tracking. | 40 // by layerization and occlusion tracking. |
| 42 ClipPaintPropertyNode* currentClip; | 41 RefPtr<ClipPaintPropertyNode> currentClip; |
| 43 | 42 |
| 44 // Separate context for out-of-flow positioned and fixed positioned elements are needed | 43 // Separate context for out-of-flow positioned and fixed positioned elements are needed |
| 45 // because they don't use DOM parent as their containing block. | 44 // because they don't use DOM parent as their containing block. |
| 46 // These additional contexts normally pass through untouched, and are only c opied from | 45 // These additional contexts normally pass through untouched, and are only c opied from |
| 47 // the main context when the current element serves as the containing block of corresponding | 46 // the main context when the current element serves as the containing block of corresponding |
| 48 // positioned descendants. | 47 // positioned descendants. |
| 49 // Overflow clips are also inherited by containing block tree instead of DOM tree, thus they | 48 // Overflow clips are also inherited by containing block tree instead of DOM tree, thus they |
| 50 // are included in the additional context too. | 49 // are included in the additional context too. |
| 51 TransformPaintPropertyNode* transformForAbsolutePosition; | 50 RefPtr<TransformPaintPropertyNode> transformForAbsolutePosition; |
| 52 LayoutPoint paintOffsetForAbsolutePosition; | 51 LayoutPoint paintOffsetForAbsolutePosition; |
| 53 ClipPaintPropertyNode* clipForAbsolutePosition; | 52 RefPtr<ClipPaintPropertyNode> clipForAbsolutePosition; |
| 54 | 53 |
| 55 TransformPaintPropertyNode* transformForFixedPosition; | 54 RefPtr<TransformPaintPropertyNode> transformForFixedPosition; |
| 56 LayoutPoint paintOffsetForFixedPosition; | 55 LayoutPoint paintOffsetForFixedPosition; |
| 57 ClipPaintPropertyNode* clipForFixedPosition; | 56 RefPtr<ClipPaintPropertyNode> clipForFixedPosition; |
| 58 | 57 |
| 59 // The effect hierarchy is applied by the stacking context tree. It is guara nteed that every | 58 // The effect hierarchy is applied by the stacking context tree. It is guara nteed that every |
| 60 // DOM descendant is also a stacking context descendant. Therefore, we don't need extra | 59 // DOM descendant is also a stacking context descendant. Therefore, we don't need extra |
| 61 // bookkeeping for effect nodes and can generate the effect tree from a DOM- order traversal. | 60 // bookkeeping for effect nodes and can generate the effect tree from a DOM- order traversal. |
| 62 EffectPaintPropertyNode* currentEffect; | 61 RefPtr<EffectPaintPropertyNode> currentEffect; |
| 62 | |
| 63 // For SPv1 only. | |
| 64 const LayoutBoxModelObject* paintInvalidationContainer; | |
| 65 const LayoutBoxModelObject* paintInvalidationContainerForOutOfFlowPositioned ; | |
| 63 }; | 66 }; |
| 64 | 67 |
| 65 void PaintPropertyTreeBuilder::buildPropertyTrees(FrameView& rootFrame) | 68 void PrePaintTreeWalk::buildPropertyTreesAndInvalidatePaint(FrameView& rootFrame ) |
| 66 { | 69 { |
| 67 walk(rootFrame, PaintPropertyTreeBuilderContext()); | 70 walk(rootFrame, PrePaintTreeWalkContext(), nullptr); |
| 68 } | 71 } |
| 69 | 72 |
| 70 void PaintPropertyTreeBuilder::walk(FrameView& frameView, const PaintPropertyTre eBuilderContext& context) | 73 void PrePaintTreeWalk::walk(FrameView& frameView, const PrePaintTreeWalkContext& context, const PaintInvalidationState* paintInvalidationState) |
| 71 { | 74 { |
| 72 PaintPropertyTreeBuilderContext localContext(context); | 75 PrePaintTreeWalkContext localContext(context); |
| 73 | 76 |
| 74 // TODO(pdr): Creating paint properties for FrameView here will not be | 77 // TODO(pdr): Creating paint properties for FrameView here will not be |
| 75 // needed once settings()->rootLayerScrolls() is enabled. | 78 // needed once settings()->rootLayerScrolls() is enabled. |
| 76 // TODO(pdr): Make this conditional on the rootLayerScrolls setting. | 79 // TODO(pdr): Make this conditional on the rootLayerScrolls setting. |
| 77 | 80 |
| 78 TransformationMatrix frameTranslate; | 81 TransformationMatrix frameTranslate; |
| 79 frameTranslate.translate(frameView.x() + context.paintOffset.x(), frameView. y() + context.paintOffset.y()); | 82 frameTranslate.translate(frameView.x() + context.paintOffset.x(), frameView. y() + context.paintOffset.y()); |
| 80 RefPtr<TransformPaintPropertyNode> newTransformNodeForPreTranslation = Trans formPaintPropertyNode::create(frameTranslate, FloatPoint3D(), context.currentTra nsform); | 83 RefPtr<TransformPaintPropertyNode> newTransformNodeForPreTranslation = Trans formPaintPropertyNode::create(frameTranslate, FloatPoint3D(), context.currentTra nsform); |
| 81 localContext.transformForFixedPosition = newTransformNodeForPreTranslation.g et(); | 84 localContext.transformForFixedPosition = newTransformNodeForPreTranslation.g et(); |
| 82 localContext.paintOffsetForFixedPosition = LayoutPoint(); | 85 localContext.paintOffsetForFixedPosition = LayoutPoint(); |
| 83 | 86 |
| 84 FloatRoundedRect contentClip(IntRect(IntPoint(), frameView.visibleContentSiz e())); | 87 FloatRoundedRect contentClip(IntRect(IntPoint(), frameView.visibleContentSiz e())); |
| 85 RefPtr<ClipPaintPropertyNode> newClipNodeForContentClip = ClipPaintPropertyN ode::create(newTransformNodeForPreTranslation.get(), contentClip, localContext.c urrentClip); | 88 RefPtr<ClipPaintPropertyNode> newClipNodeForContentClip = ClipPaintPropertyN ode::create(newTransformNodeForPreTranslation.get(), contentClip, localContext.c urrentClip); |
| 86 localContext.currentClip = localContext.clipForAbsolutePosition = localConte xt.clipForFixedPosition = newClipNodeForContentClip.get(); | 89 localContext.currentClip = localContext.clipForAbsolutePosition = localConte xt.clipForFixedPosition = newClipNodeForContentClip.get(); |
| 87 | 90 |
| 88 DoubleSize scrollOffset = frameView.scrollOffsetDouble(); | 91 DoubleSize scrollOffset = frameView.scrollOffsetDouble(); |
| 89 TransformationMatrix frameScroll; | 92 TransformationMatrix frameScroll; |
| 90 frameScroll.translate(-scrollOffset.width(), -scrollOffset.height()); | 93 frameScroll.translate(-scrollOffset.width(), -scrollOffset.height()); |
| 91 RefPtr<TransformPaintPropertyNode> newTransformNodeForScrollTranslation = Tr ansformPaintPropertyNode::create(frameScroll, FloatPoint3D(), newTransformNodeFo rPreTranslation); | 94 RefPtr<TransformPaintPropertyNode> newTransformNodeForScrollTranslation = Tr ansformPaintPropertyNode::create(frameScroll, FloatPoint3D(), newTransformNodeFo rPreTranslation); |
| 92 localContext.currentTransform = localContext.transformForAbsolutePosition = newTransformNodeForScrollTranslation.get(); | 95 localContext.currentTransform = localContext.transformForAbsolutePosition = newTransformNodeForScrollTranslation.get(); |
| 93 localContext.paintOffset = localContext.paintOffsetForAbsolutePosition = Lay outPoint(); | 96 localContext.paintOffset = localContext.paintOffsetForAbsolutePosition = Lay outPoint(); |
| 94 | 97 |
| 95 frameView.setPreTranslation(newTransformNodeForPreTranslation.release()); | 98 frameView.setPreTranslation(newTransformNodeForPreTranslation.release()); |
| 96 frameView.setScrollTranslation(newTransformNodeForScrollTranslation.release( )); | 99 frameView.setScrollTranslation(newTransformNodeForScrollTranslation.release( )); |
| 97 frameView.setContentClip(newClipNodeForContentClip.release()); | 100 frameView.setContentClip(newClipNodeForContentClip.release()); |
| 98 | 101 |
| 99 if (LayoutView* layoutView = frameView.layoutView()) | 102 if (LayoutView* layoutView = frameView.layoutView()) |
| 100 walk(*layoutView, localContext); | 103 walk(*layoutView, localContext, paintInvalidationState); |
| 101 } | 104 } |
| 102 | 105 |
| 103 static void deriveBorderBoxFromContainerContext(const LayoutObject& object, Pain tPropertyTreeBuilderContext& context) | 106 static void adjustContainerContextForPosition(const LayoutObject& object, PrePai ntTreeWalkContext& context) |
| 107 { | |
| 108 switch (object.styleRef().position()) { | |
| 109 case AbsolutePosition: | |
| 110 context.currentTransform = context.transformForAbsolutePosition; | |
| 111 context.paintOffset = context.paintOffsetForAbsolutePosition; | |
| 112 context.currentClip = context.clipForAbsolutePosition; | |
| 113 context.paintInvalidationContainer = context.paintInvalidationContainerF orOutOfFlowPositioned; | |
|
trchen
2016/03/11 23:36:19
Per the previous comment, it is not the right plac
| |
| 114 break; | |
| 115 case FixedPosition: | |
| 116 context.currentTransform = context.transformForFixedPosition; | |
| 117 context.paintOffset = context.paintOffsetForFixedPosition; | |
| 118 context.currentClip = context.clipForFixedPosition; | |
| 119 context.paintInvalidationContainer = context.paintInvalidationContainerF orOutOfFlowPositioned; | |
|
trchen
2016/03/11 23:36:19
Ditto.
| |
| 120 break; | |
| 121 default: | |
| 122 break; | |
| 123 } | |
| 124 } | |
| 125 | |
| 126 static void deriveBorderBoxFromContainerContext(const LayoutObject& object, PreP aintTreeWalkContext& context) | |
| 104 { | 127 { |
| 105 if (!object.isBoxModelObject()) | 128 if (!object.isBoxModelObject()) |
| 106 return; | 129 return; |
| 107 | 130 |
| 108 const LayoutBoxModelObject& boxModelObject = toLayoutBoxModelObject(object); | 131 const LayoutBoxModelObject& boxModelObject = toLayoutBoxModelObject(object); |
| 109 | 132 |
| 110 // TODO(trchen): There is some insanity going on with tables. Double check r esults. | 133 // TODO(trchen): There is some insanity going on with tables. Double check r esults. |
| 111 switch (object.styleRef().position()) { | 134 if (object.isInFlowPositioned()) |
|
trchen
2016/03/11 23:36:19
While this refactoring is appreciated, can we do t
| |
| 112 case StaticPosition: | |
| 113 break; | |
| 114 case RelativePosition: | |
| 115 context.paintOffset += boxModelObject.offsetForInFlowPosition(); | 135 context.paintOffset += boxModelObject.offsetForInFlowPosition(); |
| 116 break; | 136 |
| 117 case AbsolutePosition: | |
| 118 context.currentTransform = context.transformForAbsolutePosition; | |
| 119 context.paintOffset = context.paintOffsetForAbsolutePosition; | |
| 120 context.currentClip = context.clipForAbsolutePosition; | |
| 121 break; | |
| 122 case StickyPosition: | |
| 123 context.paintOffset += boxModelObject.offsetForInFlowPosition(); | |
| 124 break; | |
| 125 case FixedPosition: | |
| 126 context.currentTransform = context.transformForFixedPosition; | |
| 127 context.paintOffset = context.paintOffsetForFixedPosition; | |
| 128 context.currentClip = context.clipForFixedPosition; | |
| 129 break; | |
| 130 default: | |
| 131 ASSERT_NOT_REACHED(); | |
| 132 } | |
| 133 if (boxModelObject.isBox()) | 137 if (boxModelObject.isBox()) |
| 134 context.paintOffset += toLayoutBox(boxModelObject).locationOffset(); | 138 context.paintOffset += toLayoutBox(boxModelObject).locationOffset(); |
| 135 } | 139 } |
| 136 | 140 |
| 137 static PassRefPtr<TransformPaintPropertyNode> createPaintOffsetTranslationIfNeed ed(const LayoutObject& object, PaintPropertyTreeBuilderContext& context) | 141 static PassRefPtr<TransformPaintPropertyNode> createPaintOffsetTranslationIfNeed ed(const LayoutObject& object, PrePaintTreeWalkContext& context) |
| 138 { | 142 { |
| 139 bool shouldCreatePaintOffsetTranslationNode = false; | 143 bool shouldCreatePaintOffsetTranslationNode = false; |
| 140 if (object.isSVGRoot()) { | 144 if (object.isSVGRoot()) { |
| 141 // SVG doesn't use paint offset internally so emit a paint offset at the html->svg boundary. | 145 // SVG doesn't use paint offset internally so emit a paint offset at the html->svg boundary. |
| 142 shouldCreatePaintOffsetTranslationNode = true; | 146 shouldCreatePaintOffsetTranslationNode = true; |
| 143 } else if (object.isBoxModelObject()) { | 147 } else if (object.isBoxModelObject()) { |
| 144 // TODO(trchen): Eliminate PaintLayer dependency. | 148 // TODO(trchen): Eliminate PaintLayer dependency. |
| 145 PaintLayer* layer = toLayoutBoxModelObject(object).layer(); | 149 PaintLayer* layer = toLayoutBoxModelObject(object).layer(); |
| 146 shouldCreatePaintOffsetTranslationNode = layer && layer->paintsWithTrans form(GlobalPaintNormalPhase); | 150 shouldCreatePaintOffsetTranslationNode = layer && layer->paintsWithTrans form(GlobalPaintNormalPhase); |
| 147 } | 151 } |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 160 static FloatPoint3D transformOrigin(const LayoutBox& box) | 164 static FloatPoint3D transformOrigin(const LayoutBox& box) |
| 161 { | 165 { |
| 162 const ComputedStyle& style = box.styleRef(); | 166 const ComputedStyle& style = box.styleRef(); |
| 163 FloatSize borderBoxSize(box.size()); | 167 FloatSize borderBoxSize(box.size()); |
| 164 return FloatPoint3D( | 168 return FloatPoint3D( |
| 165 floatValueForLength(style.transformOriginX(), borderBoxSize.width()), | 169 floatValueForLength(style.transformOriginX(), borderBoxSize.width()), |
| 166 floatValueForLength(style.transformOriginY(), borderBoxSize.height()), | 170 floatValueForLength(style.transformOriginY(), borderBoxSize.height()), |
| 167 style.transformOriginZ()); | 171 style.transformOriginZ()); |
| 168 } | 172 } |
| 169 | 173 |
| 170 static PassRefPtr<TransformPaintPropertyNode> createTransformIfNeeded(const Layo utObject& object, PaintPropertyTreeBuilderContext& context) | 174 static PassRefPtr<TransformPaintPropertyNode> createTransformIfNeeded(const Layo utObject& object, PrePaintTreeWalkContext& context) |
| 171 { | 175 { |
| 172 if (object.isSVG() && !object.isSVGRoot()) { | 176 if (object.isSVG() && !object.isSVGRoot()) { |
| 173 const AffineTransform& transform = object.localToParentTransform(); | 177 const AffineTransform& transform = object.localToParentTransform(); |
| 174 if (transform.isIdentity()) | 178 if (transform.isIdentity()) |
| 175 return nullptr; | 179 return nullptr; |
| 176 | 180 |
| 177 // SVG's transform origin is baked into the localToParentTransform. | 181 // SVG's transform origin is baked into the localToParentTransform. |
| 178 RefPtr<TransformPaintPropertyNode> newTransformNodeForTransform = Transf ormPaintPropertyNode::create( | 182 RefPtr<TransformPaintPropertyNode> newTransformNodeForTransform = Transf ormPaintPropertyNode::create( |
| 179 transform, FloatPoint3D(0, 0, 0), context.currentTransform); | 183 transform, FloatPoint3D(0, 0, 0), context.currentTransform); |
| 180 context.currentTransform = newTransformNodeForTransform.get(); | 184 context.currentTransform = newTransformNodeForTransform.get(); |
| 181 return newTransformNodeForTransform.release(); | 185 return newTransformNodeForTransform.release(); |
| 182 } | 186 } |
| 183 | 187 |
| 184 const ComputedStyle& style = object.styleRef(); | 188 const ComputedStyle& style = object.styleRef(); |
| 185 if (!object.isBox() || !style.hasTransform()) | 189 if (!object.isBox() || !style.hasTransform()) |
| 186 return nullptr; | 190 return nullptr; |
| 187 | 191 |
| 188 ASSERT(context.paintOffset == LayoutPoint()); | 192 ASSERT(context.paintOffset == LayoutPoint()); |
| 189 | 193 |
| 190 TransformationMatrix matrix; | 194 TransformationMatrix matrix; |
| 191 style.applyTransform(matrix, toLayoutBox(object).size(), ComputedStyle::Excl udeTransformOrigin, | 195 style.applyTransform(matrix, toLayoutBox(object).size(), ComputedStyle::Excl udeTransformOrigin, |
| 192 ComputedStyle::IncludeMotionPath, ComputedStyle::IncludeIndependentTrans formProperties); | 196 ComputedStyle::IncludeMotionPath, ComputedStyle::IncludeIndependentTrans formProperties); |
| 193 RefPtr<TransformPaintPropertyNode> newTransformNodeForTransform = TransformP aintPropertyNode::create( | 197 RefPtr<TransformPaintPropertyNode> newTransformNodeForTransform = TransformP aintPropertyNode::create( |
| 194 matrix, transformOrigin(toLayoutBox(object)), context.currentTransform); | 198 matrix, transformOrigin(toLayoutBox(object)), context.currentTransform); |
| 195 context.currentTransform = newTransformNodeForTransform.get(); | 199 context.currentTransform = newTransformNodeForTransform.get(); |
| 196 return newTransformNodeForTransform.release(); | 200 return newTransformNodeForTransform.release(); |
| 197 } | 201 } |
| 198 | 202 |
| 199 static PassRefPtr<EffectPaintPropertyNode> createEffectIfNeeded(const LayoutObje ct& object, PaintPropertyTreeBuilderContext& context) | 203 static PassRefPtr<EffectPaintPropertyNode> createEffectIfNeeded(const LayoutObje ct& object, PrePaintTreeWalkContext& context) |
| 200 { | 204 { |
| 201 const ComputedStyle& style = object.styleRef(); | 205 const ComputedStyle& style = object.styleRef(); |
| 202 if (!style.hasOpacity()) | 206 if (!style.hasOpacity()) |
| 203 return nullptr; | 207 return nullptr; |
| 204 RefPtr<EffectPaintPropertyNode> newEffectNode = EffectPaintPropertyNode::cre ate(style.opacity(), context.currentEffect); | 208 RefPtr<EffectPaintPropertyNode> newEffectNode = EffectPaintPropertyNode::cre ate(style.opacity(), context.currentEffect); |
| 205 context.currentEffect = newEffectNode.get(); | 209 context.currentEffect = newEffectNode.get(); |
| 206 return newEffectNode.release(); | 210 return newEffectNode.release(); |
| 207 } | 211 } |
| 208 | 212 |
| 209 static PassRefPtr<ClipPaintPropertyNode> createOverflowClipIfNeeded(const Layout Object& object, PaintPropertyTreeBuilderContext& context) | 213 static PassRefPtr<ClipPaintPropertyNode> createOverflowClipIfNeeded(const Layout Object& object, PrePaintTreeWalkContext& context) |
| 210 { | 214 { |
| 211 if (!object.isBox()) | 215 if (!object.isBox()) |
| 212 return nullptr; | 216 return nullptr; |
| 213 const LayoutBox& box = toLayoutBox(object); | 217 const LayoutBox& box = toLayoutBox(object); |
| 214 | 218 |
| 215 // The <input> elements can't have contents thus CSS overflow property doesn 't apply. | 219 // The <input> elements can't have contents thus CSS overflow property doesn 't apply. |
| 216 // However for layout purposes we do generate child layout objects for them, e.g. button label. | 220 // However for layout purposes we do generate child layout objects for them, e.g. button label. |
| 217 // We should clip the overflow from those children. This is called control c lip and we | 221 // We should clip the overflow from those children. This is called control c lip and we |
| 218 // technically treat them like overflow clip. | 222 // technically treat them like overflow clip. |
| 219 LayoutRect clipRect; | 223 LayoutRect clipRect; |
| 220 if (box.hasControlClip()) | 224 if (box.hasControlClip()) |
| 221 clipRect = box.controlClipRect(context.paintOffset); | 225 clipRect = box.controlClipRect(context.paintOffset); |
| 222 else if (box.hasOverflowClip()) | 226 else if (box.hasOverflowClip()) |
| 223 clipRect = box.overflowClipRect(context.paintOffset); | 227 clipRect = box.overflowClipRect(context.paintOffset); |
| 224 else | 228 else |
| 225 return nullptr; | 229 return nullptr; |
| 226 | 230 |
| 227 RefPtr<ClipPaintPropertyNode> newClipNodeForBorderRadiusClip; | 231 RefPtr<ClipPaintPropertyNode> newClipNodeForBorderRadiusClip; |
| 228 const ComputedStyle& style = box.styleRef(); | 232 const ComputedStyle& style = box.styleRef(); |
| 229 if (style.hasBorderRadius()) { | 233 if (style.hasBorderRadius()) { |
| 230 newClipNodeForBorderRadiusClip = ClipPaintPropertyNode::create( | 234 newClipNodeForBorderRadiusClip = ClipPaintPropertyNode::create( |
| 231 context.currentTransform, | 235 context.currentTransform, |
| 232 style.getRoundedInnerBorderFor(LayoutRect(context.paintOffset, box.s ize())), | 236 style.getRoundedInnerBorderFor(LayoutRect(context.paintOffset, box.s ize())), |
| 233 context.currentClip); | 237 context.currentClip); |
| 234 } | 238 } |
| 235 | 239 |
| 236 RefPtr<ClipPaintPropertyNode> newClipNodeForOverflowClip = ClipPaintProperty Node::create( | 240 RefPtr<ClipPaintPropertyNode> newClipNodeForOverflowClip = ClipPaintProperty Node::create( |
| 237 context.currentTransform, | 241 context.currentTransform, |
| 238 FloatRoundedRect(FloatRect(clipRect)), | 242 FloatRoundedRect(FloatRect(clipRect)), |
| 239 newClipNodeForBorderRadiusClip ? newClipNodeForBorderRadiusClip.release( ) : context.currentClip); | 243 newClipNodeForBorderRadiusClip ? newClipNodeForBorderRadiusClip.release( ) : PassRefPtr<ClipPaintPropertyNode>(context.currentClip)); |
| 240 context.currentClip = newClipNodeForOverflowClip.get(); | 244 context.currentClip = newClipNodeForOverflowClip.get(); |
| 241 return newClipNodeForOverflowClip.release(); | 245 return newClipNodeForOverflowClip.release(); |
| 242 } | 246 } |
| 243 | 247 |
| 244 static FloatPoint perspectiveOrigin(const LayoutBox& box) | 248 static FloatPoint perspectiveOrigin(const LayoutBox& box) |
| 245 { | 249 { |
| 246 const ComputedStyle& style = box.styleRef(); | 250 const ComputedStyle& style = box.styleRef(); |
| 247 FloatSize borderBoxSize(box.size()); | 251 FloatSize borderBoxSize(box.size()); |
| 248 return FloatPoint( | 252 return FloatPoint( |
| 249 floatValueForLength(style.perspectiveOriginX(), borderBoxSize.width()), | 253 floatValueForLength(style.perspectiveOriginX(), borderBoxSize.width()), |
| 250 floatValueForLength(style.perspectiveOriginY(), borderBoxSize.height())) ; | 254 floatValueForLength(style.perspectiveOriginY(), borderBoxSize.height())) ; |
| 251 } | 255 } |
| 252 | 256 |
| 253 static PassRefPtr<TransformPaintPropertyNode> createPerspectiveIfNeeded(const La youtObject& object, PaintPropertyTreeBuilderContext& context) | 257 static PassRefPtr<TransformPaintPropertyNode> createPerspectiveIfNeeded(const La youtObject& object, PrePaintTreeWalkContext& context) |
| 254 { | 258 { |
| 255 const ComputedStyle& style = object.styleRef(); | 259 const ComputedStyle& style = object.styleRef(); |
| 256 if (!object.isBox() || !style.hasPerspective()) | 260 if (!object.isBox() || !style.hasPerspective()) |
| 257 return nullptr; | 261 return nullptr; |
| 258 | 262 |
| 259 RefPtr<TransformPaintPropertyNode> newTransformNodeForPerspective = Transfor mPaintPropertyNode::create( | 263 RefPtr<TransformPaintPropertyNode> newTransformNodeForPerspective = Transfor mPaintPropertyNode::create( |
| 260 TransformationMatrix().applyPerspective(style.perspective()), | 264 TransformationMatrix().applyPerspective(style.perspective()), |
| 261 perspectiveOrigin(toLayoutBox(object)) + toLayoutSize(context.paintOffse t), context.currentTransform); | 265 perspectiveOrigin(toLayoutBox(object)) + toLayoutSize(context.paintOffse t), context.currentTransform); |
| 262 context.currentTransform = newTransformNodeForPerspective.get(); | 266 context.currentTransform = newTransformNodeForPerspective.get(); |
| 263 return newTransformNodeForPerspective.release(); | 267 return newTransformNodeForPerspective.release(); |
| 264 } | 268 } |
| 265 | 269 |
| 266 static PassRefPtr<TransformPaintPropertyNode> createScrollTranslationIfNeeded(co nst LayoutObject& object, PaintPropertyTreeBuilderContext& context) | 270 static PassRefPtr<TransformPaintPropertyNode> createScrollTranslationIfNeeded(co nst LayoutObject& object, PrePaintTreeWalkContext& context) |
| 267 { | 271 { |
| 268 if (!object.isBoxModelObject() || !object.hasOverflowClip()) | 272 if (!object.isBoxModelObject() || !object.hasOverflowClip()) |
| 269 return nullptr; | 273 return nullptr; |
| 270 | 274 |
| 271 PaintLayer* layer = toLayoutBoxModelObject(object).layer(); | 275 PaintLayer* layer = toLayoutBoxModelObject(object).layer(); |
| 272 ASSERT(layer); | 276 ASSERT(layer); |
| 273 DoubleSize scrollOffset = layer->getScrollableArea()->scrollOffset(); | 277 DoubleSize scrollOffset = layer->getScrollableArea()->scrollOffset(); |
| 274 if (scrollOffset.isZero() && !layer->scrollsOverflow()) | 278 if (scrollOffset.isZero() && !layer->scrollsOverflow()) |
| 275 return nullptr; | 279 return nullptr; |
| 276 | 280 |
| 277 RefPtr<TransformPaintPropertyNode> newTransformNodeForScrollTranslation = Tr ansformPaintPropertyNode::create( | 281 RefPtr<TransformPaintPropertyNode> newTransformNodeForScrollTranslation = Tr ansformPaintPropertyNode::create( |
| 278 TransformationMatrix().translate(-scrollOffset.width(), -scrollOffset.he ight()), | 282 TransformationMatrix().translate(-scrollOffset.width(), -scrollOffset.he ight()), |
| 279 FloatPoint3D(), context.currentTransform); | 283 FloatPoint3D(), context.currentTransform); |
| 280 context.currentTransform = newTransformNodeForScrollTranslation.get(); | 284 context.currentTransform = newTransformNodeForScrollTranslation.get(); |
| 281 return newTransformNodeForScrollTranslation.release(); | 285 return newTransformNodeForScrollTranslation.release(); |
| 282 } | 286 } |
| 283 | 287 |
| 284 static void updateOutOfFlowContext(const LayoutObject& object, PaintPropertyTree BuilderContext& context) | 288 static void updateOutOfFlowContext(const LayoutObject& object, PrePaintTreeWalkC ontext& context) |
| 285 { | 289 { |
| 286 // At the html->svg boundary (see: createPaintOffsetTranslationIfNeeded) the currentTransform is | 290 // At the html->svg boundary (see: createPaintOffsetTranslationIfNeeded) the currentTransform is |
| 287 // up-to-date for all children of the svg root element. Additionally, inside SVG, all positioning | 291 // up-to-date for all children of the svg root element. Additionally, inside SVG, all positioning |
| 288 // uses transforms. Therefore, we only need to check createdNewTransform and isSVGRoot() to | 292 // uses transforms. Therefore, we only need to check createdNewTransform and isSVGRoot() to |
| 289 // ensure out-of-flow and fixed positioning is correct at the svg->html boun dary. | 293 // ensure out-of-flow and fixed positioning is correct at the svg->html boun dary. |
| 290 | 294 |
| 291 if (object.canContainAbsolutePositionObjects()) { | 295 if (object.canContainAbsolutePositionObjects()) { |
| 292 context.transformForAbsolutePosition = context.currentTransform; | 296 context.transformForAbsolutePosition = context.currentTransform; |
| 293 context.paintOffsetForAbsolutePosition = context.paintOffset; | 297 context.paintOffsetForAbsolutePosition = context.paintOffset; |
| 294 context.clipForAbsolutePosition = context.currentClip; | 298 context.clipForAbsolutePosition = context.currentClip; |
| 295 } | 299 } |
| 296 | 300 |
| 297 // TODO(pdr): Remove the !object.isLayoutView() condition when removing Fram eView | 301 // TODO(pdr): Remove the !object.isLayoutView() condition when removing Fram eView |
| 298 // paint properties for rootLayerScrolls. | 302 // paint properties for rootLayerScrolls. |
| 299 if (!object.isLayoutView() && object.canContainFixedPositionObjects()) { | 303 if (!object.isLayoutView() && object.canContainFixedPositionObjects()) { |
| 300 context.transformForFixedPosition = context.currentTransform; | 304 context.transformForFixedPosition = context.currentTransform; |
| 301 context.paintOffsetForFixedPosition = context.paintOffset; | 305 context.paintOffsetForFixedPosition = context.paintOffset; |
| 302 context.clipForFixedPosition = context.currentClip; | 306 context.clipForFixedPosition = context.currentClip; |
| 303 } | 307 } |
| 304 } | 308 } |
| 305 | 309 |
| 306 static PassOwnPtr<ObjectPaintProperties::LocalBorderBoxProperties> recordTreeCon textIfNeeded(LayoutObject& object, const PaintPropertyTreeBuilderContext& contex t) | 310 static PassOwnPtr<ObjectPaintProperties::LocalBorderBoxProperties> recordTreeCon textIfNeeded(const LayoutObject& object, const PrePaintTreeWalkContext& context) |
| 307 { | 311 { |
| 308 // Note: Currently only layer painter makes use of the pre-computed context. | 312 // Note: Currently only layer painter makes use of the pre-computed context. |
| 309 // This condition may be loosened with no adverse effects beside memory use. | 313 // This condition may be loosened with no adverse effects beside memory use. |
| 310 if (!object.hasLayer()) | 314 if (!object.hasLayer()) |
| 311 return nullptr; | 315 return nullptr; |
| 312 | 316 |
| 313 OwnPtr<ObjectPaintProperties::LocalBorderBoxProperties> recordedContext = ad optPtr(new ObjectPaintProperties::LocalBorderBoxProperties); | 317 OwnPtr<ObjectPaintProperties::LocalBorderBoxProperties> recordedContext = ad optPtr(new ObjectPaintProperties::LocalBorderBoxProperties); |
| 314 recordedContext->paintOffset = context.paintOffset; | 318 recordedContext->paintOffset = context.paintOffset; |
| 315 recordedContext->transform = context.currentTransform; | 319 recordedContext->transform = context.currentTransform; |
| 316 recordedContext->clip = context.currentClip; | 320 recordedContext->clip = context.currentClip; |
| 317 recordedContext->effect = context.currentEffect; | 321 recordedContext->effect = context.currentEffect; |
| 318 return recordedContext.release(); | 322 return recordedContext.release(); |
| 319 } | 323 } |
| 320 | 324 |
| 321 void PaintPropertyTreeBuilder::walk(LayoutObject& object, const PaintPropertyTre eBuilderContext& context) | 325 static void updatePaintInvalidationContainer(const LayoutObject& object, PrePain tTreeWalkContext& context) |
| 322 { | 326 { |
| 323 PaintPropertyTreeBuilderContext localContext(context); | 327 // Paint invalidation container is a SPv1-only concept. |
| 328 ASSERT(!RuntimeEnabledFeatures::slimmingPaintV2Enabled()); | |
| 324 | 329 |
| 325 deriveBorderBoxFromContainerContext(object, localContext); | 330 if (!object.isPaintInvalidationContainer()) { |
|
trchen
2016/03/11 23:36:19
This doesn't look right. I think it should be
if
| |
| 326 RefPtr<TransformPaintPropertyNode> newTransformNodeForPaintOffsetTranslation = createPaintOffsetTranslationIfNeeded(object, localContext); | 331 if (context.paintInvalidationContainer) |
| 327 RefPtr<TransformPaintPropertyNode> newTransformNodeForTransform = createTran sformIfNeeded(object, localContext); | 332 return; |
| 328 RefPtr<EffectPaintPropertyNode> newEffectNode = createEffectIfNeeded(object, localContext); | 333 ASSERT(object.isLayoutView()); |
| 329 OwnPtr<ObjectPaintProperties::LocalBorderBoxProperties> newRecordedContext = recordTreeContextIfNeeded(object, localContext); | |
| 330 RefPtr<ClipPaintPropertyNode> newClipNodeForOverflowClip = createOverflowCli pIfNeeded(object, localContext); | |
| 331 // TODO(trchen): Insert flattening transform here, as specified by | |
| 332 // http://www.w3.org/TR/css3-transforms/#transform-style-property | |
| 333 RefPtr<TransformPaintPropertyNode> newTransformNodeForPerspective = createPe rspectiveIfNeeded(object, localContext); | |
| 334 RefPtr<TransformPaintPropertyNode> newTransformNodeForScrollTranslation = cr eateScrollTranslationIfNeeded(object, localContext); | |
| 335 updateOutOfFlowContext(object, localContext); | |
| 336 | |
| 337 if (newTransformNodeForPaintOffsetTranslation || newTransformNodeForTransfor m || newEffectNode || newClipNodeForOverflowClip || newTransformNodeForPerspecti ve || newTransformNodeForScrollTranslation || newRecordedContext) { | |
| 338 OwnPtr<ObjectPaintProperties> updatedPaintProperties = ObjectPaintProper ties::create( | |
| 339 newTransformNodeForPaintOffsetTranslation.release(), | |
| 340 newTransformNodeForTransform.release(), | |
| 341 newEffectNode.release(), | |
| 342 newClipNodeForOverflowClip.release(), | |
| 343 newTransformNodeForPerspective.release(), | |
| 344 newTransformNodeForScrollTranslation.release(), | |
| 345 newRecordedContext.release()); | |
| 346 object.setObjectPaintProperties(updatedPaintProperties.release()); | |
| 347 } else { | |
| 348 object.clearObjectPaintProperties(); | |
| 349 } | 334 } |
| 350 | 335 |
| 351 for (LayoutObject* child = object.slowFirstChild(); child; child = child->ne xtSibling()) { | 336 context.currentTransform = nullptr; |
| 352 if (child->isBoxModelObject() || child->isSVG()) | 337 context.paintOffset = LayoutPoint(); |
| 353 walk(*child, localContext); | 338 context.currentClip = nullptr; |
| 339 context.paintInvalidationContainer = &toLayoutBoxModelObject(object); | |
| 340 | |
| 341 // A composited stacking context establishes new paint invalidation containe r for | |
| 342 // out-of-flow-positioned descendants. | |
| 343 if (object.styleRef().isStackingContext() || !context.paintInvalidationConta inerForOutOfFlowPositioned) { | |
| 344 // TODO(wangxianzhu): The following may be incorrect for some complex ca ses. Investigate if we could | |
| 345 // make it correct for all cases or have to use ForceHorriblySlowRectMap ping. | |
|
trchen
2016/03/11 23:36:19
As pdr@ already pointed out, I don't think it make
| |
| 346 context.transformForAbsolutePosition = nullptr; | |
| 347 context.paintOffsetForAbsolutePosition = LayoutPoint(); | |
| 348 context.clipForAbsolutePosition = nullptr; | |
| 349 context.transformForFixedPosition = nullptr; | |
| 350 context.paintOffsetForFixedPosition = LayoutPoint(); | |
| 351 context.clipForFixedPosition = nullptr; | |
| 352 context.paintInvalidationContainerForOutOfFlowPositioned = &toLayoutBoxM odelObject(object); | |
| 353 } | |
| 354 } | |
| 355 | |
| 356 void PrePaintTreeWalk::walk(const LayoutObject& object, const PrePaintTreeWalkCo ntext& context, const PaintInvalidationState* parentPaintInvalidationState) | |
| 357 { | |
| 358 PrePaintTreeWalkContext localContext(context); | |
| 359 adjustContainerContextForPosition(object, localContext); | |
| 360 | |
| 361 Optional<PaintInvalidationState> paintInvalidationState; | |
| 362 if (RuntimeEnabledFeatures::slimmingPaintInvalidationEnabled()) { | |
| 363 if (!RuntimeEnabledFeatures::slimmingPaintV2Enabled()) | |
| 364 updatePaintInvalidationContainer(object, localContext); | |
| 365 paintInvalidationState.emplace(parentPaintInvalidationState, object, *lo calContext.paintInvalidationContainer, localContext.paintOffset); | |
| 366 if (!RuntimeEnabledFeatures::slimmingPaintV2Enabled() && !object.shouldC heckForPaintInvalidation(*paintInvalidationState)) | |
| 367 return; | |
|
trchen
2016/03/11 23:36:19
The early return check is too late, and the semant
| |
| 368 | |
| 369 PaintInvalidationReason reason = object.getMutableForPainting().invalida tePaintIfNeeded(*paintInvalidationState, *localContext.paintInvalidationContaine r); | |
| 370 object.getMutableForPainting().clearPaintInvalidationState(*paintInvalid ationState); | |
| 371 if (reason == PaintInvalidationDelayedFull) | |
| 372 m_pendingDelayedPaintInvalidations.append(const_cast<LayoutObject*>( &object)); | |
| 373 } | |
| 374 | |
| 375 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled() || !object.isPaintInval idationContainer()) { | |
| 376 deriveBorderBoxFromContainerContext(object, localContext); | |
| 377 RefPtr<TransformPaintPropertyNode> newTransformNodeForPaintOffsetTransla tion = createPaintOffsetTranslationIfNeeded(object, localContext); | |
| 378 RefPtr<TransformPaintPropertyNode> newTransformNodeForTransform = create TransformIfNeeded(object, localContext); | |
| 379 RefPtr<EffectPaintPropertyNode> newEffectNode = createEffectIfNeeded(obj ect, localContext); | |
| 380 OwnPtr<ObjectPaintProperties::LocalBorderBoxProperties> newRecordedConte xt = recordTreeContextIfNeeded(object, localContext); | |
| 381 RefPtr<ClipPaintPropertyNode> newClipNodeForOverflowClip = createOverflo wClipIfNeeded(object, localContext); | |
| 382 // TODO(trchen): Insert flattening transform here, as specified by | |
| 383 // http://www.w3.org/TR/css3-transforms/#transform-style-property | |
| 384 RefPtr<TransformPaintPropertyNode> newTransformNodeForPerspective = crea tePerspectiveIfNeeded(object, localContext); | |
| 385 RefPtr<TransformPaintPropertyNode> newTransformNodeForScrollTranslation = createScrollTranslationIfNeeded(object, localContext); | |
| 386 updateOutOfFlowContext(object, localContext); | |
| 387 | |
| 388 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) { | |
| 389 if (newTransformNodeForPaintOffsetTranslation || newTransformNodeFor Transform || newEffectNode || newClipNodeForOverflowClip || newTransformNodeForP erspective || newTransformNodeForScrollTranslation || newRecordedContext) { | |
| 390 OwnPtr<ObjectPaintProperties> updatedPaintProperties = ObjectPai ntProperties::create( | |
| 391 newTransformNodeForPaintOffsetTranslation.release(), | |
| 392 newTransformNodeForTransform.release(), | |
| 393 newEffectNode.release(), | |
| 394 newClipNodeForOverflowClip.release(), | |
| 395 newTransformNodeForPerspective.release(), | |
| 396 newTransformNodeForScrollTranslation.release(), | |
| 397 newRecordedContext.release()); | |
| 398 object.getMutableForPainting().setObjectPaintProperties(updatedP aintProperties.release()); | |
| 399 } else { | |
| 400 object.getMutableForPainting().clearObjectPaintProperties(); | |
| 401 } | |
| 402 } | |
| 403 } | |
| 404 | |
| 405 for (const LayoutObject* child = object.slowFirstChild(); child; child = chi ld->nextSibling()) { | |
| 406 if (child->isBoxModelObject() || child->isSVG()) { | |
| 407 walk(*child, localContext, paintInvalidationState.get()); | |
| 408 } else if (RuntimeEnabledFeatures::slimmingPaintInvalidationEnabled() && child->shouldCheckForPaintInvalidation(*paintInvalidationState)) { | |
| 409 child->getMutableForPainting().invalidatePaintIfNeeded(*paintInvalid ationState, *localContext.paintInvalidationContainer); | |
| 410 child->getMutableForPainting().clearPaintInvalidationState(*paintInv alidationState); | |
| 411 } | |
| 354 } | 412 } |
| 355 | 413 |
| 356 if (object.isLayoutPart()) { | 414 if (object.isLayoutPart()) { |
| 357 Widget* widget = toLayoutPart(object).widget(); | 415 Widget* widget = toLayoutPart(object).widget(); |
| 358 if (widget && widget->isFrameView()) | 416 if (widget && widget->isFrameView()) |
| 359 walk(*toFrameView(widget), localContext); | 417 walk(*toFrameView(widget), localContext, paintInvalidationState.get( )); |
| 360 // TODO(pdr): Investigate RemoteFrameView (crbug.com/579281). | 418 // TODO(pdr): Investigate RemoteFrameView (crbug.com/579281). |
| 361 } | 419 } |
| 362 } | 420 } |
| 363 | 421 |
| 364 } // namespace blink | 422 } // namespace blink |
| OLD | NEW |