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" |
11 #include "core/layout/LayoutPart.h" | 11 #include "core/layout/LayoutPart.h" |
12 #include "core/layout/svg/LayoutSVGRoot.h" | 12 #include "core/layout/svg/LayoutSVGRoot.h" |
13 #include "core/paint/ObjectPaintProperties.h" | 13 #include "core/paint/ObjectPaintProperties.h" |
14 #include "core/paint/PaintLayer.h" | 14 #include "core/paint/PaintLayer.h" |
15 #include "core/paint/SVGRootPainter.h" | 15 #include "core/paint/SVGRootPainter.h" |
16 #include "platform/transforms/TransformationMatrix.h" | 16 #include "platform/transforms/TransformationMatrix.h" |
17 #include "wtf/PtrUtil.h" | 17 #include "wtf/PtrUtil.h" |
18 #include <memory> | 18 #include <memory> |
19 | 19 |
20 namespace blink { | 20 namespace blink { |
21 | 21 |
22 void PaintPropertyTreeBuilder::buildTreeRootNodes(FrameView& rootFrame, PaintPro
pertyTreeBuilderContext& context) | 22 void PaintPropertyTreeBuilder::buildTreeRootNodes(FrameView& rootFrame, PaintPro
pertyTreeBuilderContext& context) |
23 { | 23 { |
24 RefPtr<TransformPaintPropertyNode> transformRoot = TransformPaintPropertyNod
e::create(TransformationMatrix(), FloatPoint3D(), nullptr); | 24 RefPtr<TransformPaintPropertyNode> transformRoot = TransformPaintPropertyNod
e::create(TransformationMatrix(), FloatPoint3D(), nullptr); |
25 context.currentTransform = context.transformForAbsolutePosition = context.tr
ansformForFixedPosition = transformRoot.get(); | 25 context.current.transform = context.absolutePosition.transform = context.fix
edPosition.transform = transformRoot.get(); |
26 rootFrame.setRootTransform(std::move(transformRoot)); | 26 rootFrame.setRootTransform(std::move(transformRoot)); |
27 | 27 |
28 RefPtr<ClipPaintPropertyNode> clipRoot = ClipPaintPropertyNode::create(trans
formRoot, FloatRoundedRect(LayoutRect::infiniteIntRect()), nullptr); | 28 RefPtr<ClipPaintPropertyNode> clipRoot = ClipPaintPropertyNode::create(trans
formRoot, FloatRoundedRect(LayoutRect::infiniteIntRect()), nullptr); |
29 context.currentClip = context.clipForAbsolutePosition = context.clipForFixed
Position = clipRoot.get(); | 29 context.current.clip = context.absolutePosition.clip = context.fixedPosition
.clip = clipRoot.get(); |
30 rootFrame.setRootClip(std::move(clipRoot)); | 30 rootFrame.setRootClip(std::move(clipRoot)); |
31 | 31 |
32 RefPtr<EffectPaintPropertyNode> effectRoot = EffectPaintPropertyNode::create
(1.0, nullptr); | 32 RefPtr<EffectPaintPropertyNode> effectRoot = EffectPaintPropertyNode::create
(1.0, nullptr); |
33 context.currentEffect = effectRoot.get(); | 33 context.currentEffect = effectRoot.get(); |
34 rootFrame.setRootEffect(std::move(effectRoot)); | 34 rootFrame.setRootEffect(std::move(effectRoot)); |
35 } | 35 } |
36 | 36 |
37 void PaintPropertyTreeBuilder::buildTreeNodes(FrameView& frameView, PaintPropert
yTreeBuilderContext& context) | 37 void PaintPropertyTreeBuilder::buildTreeNodes(FrameView& frameView, PaintPropert
yTreeBuilderContext& context) |
38 { | 38 { |
39 // TODO(pdr): Creating paint properties for FrameView here will not be | 39 // TODO(pdr): Creating paint properties for FrameView here will not be |
40 // needed once settings()->rootLayerScrolls() is enabled. | 40 // needed once settings()->rootLayerScrolls() is enabled. |
41 // TODO(pdr): Make this conditional on the rootLayerScrolls setting. | 41 // TODO(pdr): Make this conditional on the rootLayerScrolls setting. |
42 | 42 |
43 TransformationMatrix frameTranslate; | 43 TransformationMatrix frameTranslate; |
44 frameTranslate.translate(frameView.x() + context.paintOffset.x(), frameView.
y() + context.paintOffset.y()); | 44 frameTranslate.translate(frameView.x() + context.current.paintOffset.x(), fr
ameView.y() + context.current.paintOffset.y()); |
45 RefPtr<TransformPaintPropertyNode> newTransformNodeForPreTranslation = Trans
formPaintPropertyNode::create(frameTranslate, FloatPoint3D(), context.currentTra
nsform); | 45 RefPtr<TransformPaintPropertyNode> newTransformNodeForPreTranslation = Trans
formPaintPropertyNode::create(frameTranslate, FloatPoint3D(), context.current.tr
ansform); |
46 context.transformForFixedPosition = newTransformNodeForPreTranslation.get(); | |
47 context.paintOffsetForFixedPosition = LayoutPoint(); | |
48 | 46 |
49 FloatRoundedRect contentClip(IntRect(IntPoint(), frameView.visibleContentSiz
e())); | 47 FloatRoundedRect contentClip(IntRect(IntPoint(), frameView.visibleContentSiz
e())); |
50 RefPtr<ClipPaintPropertyNode> newClipNodeForContentClip = ClipPaintPropertyN
ode::create(newTransformNodeForPreTranslation.get(), contentClip, context.curren
tClip); | 48 RefPtr<ClipPaintPropertyNode> newClipNodeForContentClip = ClipPaintPropertyN
ode::create(newTransformNodeForPreTranslation.get(), contentClip, context.curren
t.clip); |
51 context.currentClip = context.clipForAbsolutePosition = context.clipForFixed
Position = newClipNodeForContentClip.get(); | |
52 | 49 |
53 DoubleSize scrollOffset = frameView.scrollOffsetDouble(); | 50 DoubleSize scrollOffset = frameView.scrollOffsetDouble(); |
54 TransformationMatrix frameScroll; | 51 TransformationMatrix frameScroll; |
55 frameScroll.translate(-scrollOffset.width(), -scrollOffset.height()); | 52 frameScroll.translate(-scrollOffset.width(), -scrollOffset.height()); |
56 RefPtr<TransformPaintPropertyNode> newTransformNodeForScrollTranslation = Tr
ansformPaintPropertyNode::create(frameScroll, FloatPoint3D(), newTransformNodeFo
rPreTranslation); | 53 RefPtr<TransformPaintPropertyNode> newTransformNodeForScrollTranslation = Tr
ansformPaintPropertyNode::create(frameScroll, FloatPoint3D(), newTransformNodeFo
rPreTranslation); |
57 context.currentTransform = context.transformForAbsolutePosition = newTransfo
rmNodeForScrollTranslation.get(); | 54 |
58 context.paintOffset = LayoutPoint(); | 55 // Initialize the context for current, absolute and fixed position cases. |
59 context.paintOffsetForAbsolutePosition = LayoutPoint(); | 56 // They are the same, except that scroll translation does not apply to |
| 57 // fixed position descendants. |
| 58 context.current.transform = newTransformNodeForScrollTranslation.get(); |
| 59 context.current.paintOffset = LayoutPoint(); |
| 60 context.current.clip = newClipNodeForContentClip.get(); |
| 61 context.absolutePosition = context.current; |
60 context.containerForAbsolutePosition = nullptr; | 62 context.containerForAbsolutePosition = nullptr; |
| 63 context.fixedPosition = context.current; |
| 64 context.fixedPosition.transform = newTransformNodeForPreTranslation.get(); |
61 | 65 |
62 frameView.setPreTranslation(newTransformNodeForPreTranslation.release()); | 66 frameView.setPreTranslation(newTransformNodeForPreTranslation.release()); |
63 frameView.setScrollTranslation(newTransformNodeForScrollTranslation.release(
)); | 67 frameView.setScrollTranslation(newTransformNodeForScrollTranslation.release(
)); |
64 frameView.setContentClip(newClipNodeForContentClip.release()); | 68 frameView.setContentClip(newClipNodeForContentClip.release()); |
65 } | 69 } |
66 | 70 |
67 void PaintPropertyTreeBuilder::updatePaintOffsetTranslation(const LayoutObject&
object, PaintPropertyTreeBuilderContext& context) | 71 void PaintPropertyTreeBuilder::updatePaintOffsetTranslation(const LayoutObject&
object, PaintPropertyTreeBuilderContext& context) |
68 { | 72 { |
69 if (object.isBoxModelObject()) { | 73 if (object.isBoxModelObject()) { |
70 // TODO(trchen): Eliminate PaintLayer dependency. | 74 // TODO(trchen): Eliminate PaintLayer dependency. |
71 PaintLayer* layer = toLayoutBoxModelObject(object).layer(); | 75 PaintLayer* layer = toLayoutBoxModelObject(object).layer(); |
72 if (!layer || !layer->paintsWithTransform(GlobalPaintNormalPhase)) | 76 if (!layer || !layer->paintsWithTransform(GlobalPaintNormalPhase)) |
73 return; | 77 return; |
74 } | 78 } |
75 | 79 |
76 if (context.paintOffset == LayoutPoint()) | 80 if (context.current.paintOffset == LayoutPoint()) |
77 return; | 81 return; |
78 | 82 |
79 // We should use the same subpixel paint offset values for snapping regardle
ss of whether a | 83 // We should use the same subpixel paint offset values for snapping regardle
ss of whether a |
80 // transform is present. If there is a transform we round the paint offset b
ut keep around | 84 // transform is present. If there is a transform we round the paint offset b
ut keep around |
81 // the residual fractional component for the transformed content to paint wi
th. | 85 // the residual fractional component for the transformed content to paint wi
th. |
82 // In spv1 this was called "subpixel accumulation". For more information, se
e | 86 // In spv1 this was called "subpixel accumulation". For more information, se
e |
83 // PaintLayer::subpixelAccumulation() and PaintLayerPainter::paintFragmentBy
ApplyingTransform. | 87 // PaintLayer::subpixelAccumulation() and PaintLayerPainter::paintFragmentBy
ApplyingTransform. |
84 IntPoint roundedPaintOffset = roundedIntPoint(context.paintOffset); | 88 IntPoint roundedPaintOffset = roundedIntPoint(context.current.paintOffset); |
85 LayoutPoint fractionalPaintOffset = LayoutPoint(context.paintOffset - rounde
dPaintOffset); | 89 LayoutPoint fractionalPaintOffset = LayoutPoint(context.current.paintOffset
- roundedPaintOffset); |
86 | 90 |
87 RefPtr<TransformPaintPropertyNode> paintOffsetTranslation = TransformPaintPr
opertyNode::create( | 91 RefPtr<TransformPaintPropertyNode> paintOffsetTranslation = TransformPaintPr
opertyNode::create( |
88 TransformationMatrix().translate(roundedPaintOffset.x(), roundedPaintOff
set.y()), | 92 TransformationMatrix().translate(roundedPaintOffset.x(), roundedPaintOff
set.y()), |
89 FloatPoint3D(), context.currentTransform); | 93 FloatPoint3D(), context.current.transform); |
90 context.currentTransform = paintOffsetTranslation.get(); | 94 context.current.transform = paintOffsetTranslation.get(); |
91 context.paintOffset = fractionalPaintOffset; | 95 context.current.paintOffset = fractionalPaintOffset; |
92 object.getMutableForPainting().ensureObjectPaintProperties().setPaintOffsetT
ranslation(paintOffsetTranslation.release()); | 96 object.getMutableForPainting().ensureObjectPaintProperties().setPaintOffsetT
ranslation(paintOffsetTranslation.release()); |
93 } | 97 } |
94 | 98 |
95 static FloatPoint3D transformOrigin(const LayoutBox& box) | 99 static FloatPoint3D transformOrigin(const LayoutBox& box) |
96 { | 100 { |
97 const ComputedStyle& style = box.styleRef(); | 101 const ComputedStyle& style = box.styleRef(); |
98 FloatSize borderBoxSize(box.size()); | 102 FloatSize borderBoxSize(box.size()); |
99 return FloatPoint3D( | 103 return FloatPoint3D( |
100 floatValueForLength(style.transformOriginX(), borderBoxSize.width()), | 104 floatValueForLength(style.transformOriginX(), borderBoxSize.width()), |
101 floatValueForLength(style.transformOriginY(), borderBoxSize.height()), | 105 floatValueForLength(style.transformOriginY(), borderBoxSize.height()), |
102 style.transformOriginZ()); | 106 style.transformOriginZ()); |
103 } | 107 } |
104 | 108 |
105 void PaintPropertyTreeBuilder::updateTransform(const LayoutObject& object, Paint
PropertyTreeBuilderContext& context) | 109 void PaintPropertyTreeBuilder::updateTransform(const LayoutObject& object, Paint
PropertyTreeBuilderContext& context) |
106 { | 110 { |
107 if (object.isSVG() && !object.isSVGRoot()) { | 111 if (object.isSVG() && !object.isSVGRoot()) { |
108 // SVG does not use paint offset internally. | 112 // SVG does not use paint offset internally. |
109 DCHECK(context.paintOffset == LayoutPoint()); | 113 DCHECK(context.current.paintOffset == LayoutPoint()); |
110 | 114 |
111 // FIXME(pdr): Check for the presence of a transform instead of the valu
e. Checking for an | 115 // FIXME(pdr): Check for the presence of a transform instead of the valu
e. Checking for an |
112 // identity matrix will cause the property tree structure to change duri
ng animations if | 116 // identity matrix will cause the property tree structure to change duri
ng animations if |
113 // the animation passes through the identity matrix. | 117 // the animation passes through the identity matrix. |
114 // FIXME(pdr): Refactor this so all non-root SVG objects use the same tr
ansform function. | 118 // FIXME(pdr): Refactor this so all non-root SVG objects use the same tr
ansform function. |
115 const AffineTransform& transform = object.isSVGForeignObject() ? object.
localSVGTransform() : object.localToSVGParentTransform(); | 119 const AffineTransform& transform = object.isSVGForeignObject() ? object.
localSVGTransform() : object.localToSVGParentTransform(); |
116 if (transform.isIdentity()) | 120 if (transform.isIdentity()) |
117 return; | 121 return; |
118 | 122 |
119 // The origin is included in the local transform, so use an empty origin
. | 123 // The origin is included in the local transform, so use an empty origin
. |
120 RefPtr<TransformPaintPropertyNode> svgTransform = TransformPaintProperty
Node::create( | 124 RefPtr<TransformPaintPropertyNode> svgTransform = TransformPaintProperty
Node::create( |
121 transform, FloatPoint3D(0, 0, 0), context.currentTransform); | 125 transform, FloatPoint3D(0, 0, 0), context.current.transform); |
122 context.currentTransform = svgTransform.get(); | 126 context.current.transform = svgTransform.get(); |
123 object.getMutableForPainting().ensureObjectPaintProperties().setTransfor
m(svgTransform.release()); | 127 object.getMutableForPainting().ensureObjectPaintProperties().setTransfor
m(svgTransform.release()); |
124 return; | 128 return; |
125 } | 129 } |
126 | 130 |
127 const ComputedStyle& style = object.styleRef(); | 131 const ComputedStyle& style = object.styleRef(); |
128 if (!object.isBox() || !style.hasTransform()) | 132 if (!object.isBox() || !style.hasTransform()) |
129 return; | 133 return; |
130 | 134 |
131 TransformationMatrix matrix; | 135 TransformationMatrix matrix; |
132 style.applyTransform(matrix, toLayoutBox(object).size(), ComputedStyle::Excl
udeTransformOrigin, | 136 style.applyTransform(matrix, toLayoutBox(object).size(), ComputedStyle::Excl
udeTransformOrigin, |
133 ComputedStyle::IncludeMotionPath, ComputedStyle::IncludeIndependentTrans
formProperties); | 137 ComputedStyle::IncludeMotionPath, ComputedStyle::IncludeIndependentTrans
formProperties); |
134 RefPtr<TransformPaintPropertyNode> transformNode = TransformPaintPropertyNod
e::create( | 138 RefPtr<TransformPaintPropertyNode> transformNode = TransformPaintPropertyNod
e::create( |
135 matrix, transformOrigin(toLayoutBox(object)), context.currentTransform); | 139 matrix, transformOrigin(toLayoutBox(object)), context.current.transform)
; |
136 context.currentTransform = transformNode.get(); | 140 context.current.transform = transformNode.get(); |
137 object.getMutableForPainting().ensureObjectPaintProperties().setTransform(tr
ansformNode.release()); | 141 object.getMutableForPainting().ensureObjectPaintProperties().setTransform(tr
ansformNode.release()); |
138 } | 142 } |
139 | 143 |
140 void PaintPropertyTreeBuilder::updateEffect(const LayoutObject& object, PaintPro
pertyTreeBuilderContext& context) | 144 void PaintPropertyTreeBuilder::updateEffect(const LayoutObject& object, PaintPro
pertyTreeBuilderContext& context) |
141 { | 145 { |
142 if (!object.styleRef().hasOpacity()) | 146 if (!object.styleRef().hasOpacity()) |
143 return; | 147 return; |
144 RefPtr<EffectPaintPropertyNode> effectNode = EffectPaintPropertyNode::create
(object.styleRef().opacity(), context.currentEffect); | 148 RefPtr<EffectPaintPropertyNode> effectNode = EffectPaintPropertyNode::create
(object.styleRef().opacity(), context.currentEffect); |
145 context.currentEffect = effectNode.get(); | 149 context.currentEffect = effectNode.get(); |
146 object.getMutableForPainting().ensureObjectPaintProperties().setEffect(effec
tNode.release()); | 150 object.getMutableForPainting().ensureObjectPaintProperties().setEffect(effec
tNode.release()); |
147 } | 151 } |
148 | 152 |
149 void PaintPropertyTreeBuilder::updateCssClip(const LayoutObject& object, PaintPr
opertyTreeBuilderContext& context) | 153 void PaintPropertyTreeBuilder::updateCssClip(const LayoutObject& object, PaintPr
opertyTreeBuilderContext& context) |
150 { | 154 { |
151 if (!object.hasClip()) | 155 if (!object.hasClip()) |
152 return; | 156 return; |
153 ASSERT(object.canContainAbsolutePositionObjects()); | 157 ASSERT(object.canContainAbsolutePositionObjects()); |
154 | 158 |
155 // Create clip node for descendants that are not fixed position. | 159 // Create clip node for descendants that are not fixed position. |
156 // We don't have to setup context.clipForAbsolutePosition here because this
object must be | 160 // We don't have to setup context.absolutePosition.clip here because this ob
ject must be |
157 // a container for absolute position descendants, and will copy from in-flow
context later | 161 // a container for absolute position descendants, and will copy from in-flow
context later |
158 // at updateOutOfFlowContext() step. | 162 // at updateOutOfFlowContext() step. |
159 LayoutRect clipRect = toLayoutBox(object).clipRect(context.paintOffset); | 163 LayoutRect clipRect = toLayoutBox(object).clipRect(context.current.paintOffs
et); |
160 RefPtr<ClipPaintPropertyNode> clipNode = ClipPaintPropertyNode::create( | 164 RefPtr<ClipPaintPropertyNode> clipNode = ClipPaintPropertyNode::create( |
161 context.currentTransform, | 165 context.current.transform, |
162 FloatRoundedRect(FloatRect(clipRect)), | 166 FloatRoundedRect(FloatRect(clipRect)), |
163 context.currentClip); | 167 context.current.clip); |
164 context.currentClip = clipNode.get(); | 168 context.current.clip = clipNode.get(); |
165 object.getMutableForPainting().ensureObjectPaintProperties().setCssClip(clip
Node.release()); | 169 object.getMutableForPainting().ensureObjectPaintProperties().setCssClip(clip
Node.release()); |
166 } | 170 } |
167 | 171 |
168 void PaintPropertyTreeBuilder::updateLocalBorderBoxContext(const LayoutObject& o
bject, const PaintPropertyTreeBuilderContext& context) | 172 void PaintPropertyTreeBuilder::updateLocalBorderBoxContext(const LayoutObject& o
bject, const PaintPropertyTreeBuilderContext& context) |
169 { | 173 { |
170 // Avoid adding an ObjectPaintProperties for non-boxes to save memory, since
we don't need them at the moment. | 174 // Avoid adding an ObjectPaintProperties for non-boxes to save memory, since
we don't need them at the moment. |
171 if (!object.isBox() && !object.hasLayer()) | 175 if (!object.isBox() && !object.hasLayer()) |
172 return; | 176 return; |
173 | 177 |
174 std::unique_ptr<ObjectPaintProperties::LocalBorderBoxProperties> borderBoxCo
ntext = | 178 std::unique_ptr<ObjectPaintProperties::LocalBorderBoxProperties> borderBoxCo
ntext = |
175 wrapUnique(new ObjectPaintProperties::LocalBorderBoxProperties); | 179 wrapUnique(new ObjectPaintProperties::LocalBorderBoxProperties); |
176 borderBoxContext->paintOffset = context.paintOffset; | 180 borderBoxContext->paintOffset = context.current.paintOffset; |
177 borderBoxContext->propertyTreeState = PropertyTreeState(context.currentTrans
form, context.currentClip, context.currentEffect); | 181 borderBoxContext->propertyTreeState = PropertyTreeState(context.current.tran
sform, context.current.clip, context.currentEffect); |
178 object.getMutableForPainting().ensureObjectPaintProperties().setLocalBorderB
oxProperties(std::move(borderBoxContext)); | 182 object.getMutableForPainting().ensureObjectPaintProperties().setLocalBorderB
oxProperties(std::move(borderBoxContext)); |
179 } | 183 } |
180 | 184 |
181 // TODO(trchen): Remove this once we bake the paint offset into frameRect. | 185 // TODO(trchen): Remove this once we bake the paint offset into frameRect. |
182 void PaintPropertyTreeBuilder::updateScrollbarPaintOffset(const LayoutObject& ob
ject, const PaintPropertyTreeBuilderContext& context) | 186 void PaintPropertyTreeBuilder::updateScrollbarPaintOffset(const LayoutObject& ob
ject, const PaintPropertyTreeBuilderContext& context) |
183 { | 187 { |
184 IntPoint roundedPaintOffset = roundedIntPoint(context.paintOffset); | 188 IntPoint roundedPaintOffset = roundedIntPoint(context.current.paintOffset); |
185 if (roundedPaintOffset == IntPoint()) | 189 if (roundedPaintOffset == IntPoint()) |
186 return; | 190 return; |
187 | 191 |
188 if (!object.isBoxModelObject()) | 192 if (!object.isBoxModelObject()) |
189 return; | 193 return; |
190 PaintLayerScrollableArea* scrollableArea = toLayoutBoxModelObject(object).ge
tScrollableArea(); | 194 PaintLayerScrollableArea* scrollableArea = toLayoutBoxModelObject(object).ge
tScrollableArea(); |
191 if (!scrollableArea) | 195 if (!scrollableArea) |
192 return; | 196 return; |
193 if (!scrollableArea->horizontalScrollbar() && !scrollableArea->verticalScrol
lbar()) | 197 if (!scrollableArea->horizontalScrollbar() && !scrollableArea->verticalScrol
lbar()) |
194 return; | 198 return; |
195 | 199 |
196 auto paintOffset = TransformationMatrix().translate(roundedPaintOffset.x(),
roundedPaintOffset.y()); | 200 auto paintOffset = TransformationMatrix().translate(roundedPaintOffset.x(),
roundedPaintOffset.y()); |
197 object.getMutableForPainting().ensureObjectPaintProperties().setScrollbarPai
ntOffset( | 201 object.getMutableForPainting().ensureObjectPaintProperties().setScrollbarPai
ntOffset( |
198 TransformPaintPropertyNode::create(paintOffset, FloatPoint3D(), context.
currentTransform)); | 202 TransformPaintPropertyNode::create(paintOffset, FloatPoint3D(), context.
current.transform)); |
199 } | 203 } |
200 | 204 |
201 void PaintPropertyTreeBuilder::updateOverflowClip(const LayoutObject& object, Pa
intPropertyTreeBuilderContext& context) | 205 void PaintPropertyTreeBuilder::updateOverflowClip(const LayoutObject& object, Pa
intPropertyTreeBuilderContext& context) |
202 { | 206 { |
203 if (!object.isBox()) | 207 if (!object.isBox()) |
204 return; | 208 return; |
205 const LayoutBox& box = toLayoutBox(object); | 209 const LayoutBox& box = toLayoutBox(object); |
206 | 210 |
207 // The <input> elements can't have contents thus CSS overflow property doesn
't apply. | 211 // The <input> elements can't have contents thus CSS overflow property doesn
't apply. |
208 // However for layout purposes we do generate child layout objects for them,
e.g. button label. | 212 // However for layout purposes we do generate child layout objects for them,
e.g. button label. |
209 // We should clip the overflow from those children. This is called control c
lip and we | 213 // We should clip the overflow from those children. This is called control c
lip and we |
210 // technically treat them like overflow clip. | 214 // technically treat them like overflow clip. |
211 LayoutRect clipRect; | 215 LayoutRect clipRect; |
212 if (box.hasControlClip()) | 216 if (box.hasControlClip()) |
213 clipRect = box.controlClipRect(context.paintOffset); | 217 clipRect = box.controlClipRect(context.current.paintOffset); |
214 else if (box.hasOverflowClip()) | 218 else if (box.hasOverflowClip()) |
215 clipRect = box.overflowClipRect(context.paintOffset); | 219 clipRect = box.overflowClipRect(context.current.paintOffset); |
216 else | 220 else |
217 return; | 221 return; |
218 | 222 |
219 RefPtr<ClipPaintPropertyNode> borderRadiusClip; | 223 RefPtr<ClipPaintPropertyNode> borderRadiusClip; |
220 if (box.styleRef().hasBorderRadius()) { | 224 if (box.styleRef().hasBorderRadius()) { |
221 auto innerBorder = box.styleRef().getRoundedInnerBorderFor( | 225 auto innerBorder = box.styleRef().getRoundedInnerBorderFor( |
222 LayoutRect(context.paintOffset, box.size())); | 226 LayoutRect(context.current.paintOffset, box.size())); |
223 borderRadiusClip = ClipPaintPropertyNode::create( | 227 borderRadiusClip = ClipPaintPropertyNode::create( |
224 context.currentTransform, innerBorder, context.currentClip); | 228 context.current.transform, innerBorder, context.current.clip); |
225 } | 229 } |
226 | 230 |
227 RefPtr<ClipPaintPropertyNode> overflowClip = ClipPaintPropertyNode::create( | 231 RefPtr<ClipPaintPropertyNode> overflowClip = ClipPaintPropertyNode::create( |
228 context.currentTransform, | 232 context.current.transform, |
229 FloatRoundedRect(FloatRect(clipRect)), | 233 FloatRoundedRect(FloatRect(clipRect)), |
230 borderRadiusClip ? borderRadiusClip.release() : context.currentClip); | 234 borderRadiusClip ? borderRadiusClip.release() : context.current.clip); |
231 context.currentClip = overflowClip.get(); | 235 context.current.clip = overflowClip.get(); |
232 object.getMutableForPainting().ensureObjectPaintProperties().setOverflowClip
(overflowClip.release()); | 236 object.getMutableForPainting().ensureObjectPaintProperties().setOverflowClip
(overflowClip.release()); |
233 } | 237 } |
234 | 238 |
235 static FloatPoint perspectiveOrigin(const LayoutBox& box) | 239 static FloatPoint perspectiveOrigin(const LayoutBox& box) |
236 { | 240 { |
237 const ComputedStyle& style = box.styleRef(); | 241 const ComputedStyle& style = box.styleRef(); |
238 FloatSize borderBoxSize(box.size()); | 242 FloatSize borderBoxSize(box.size()); |
239 return FloatPoint( | 243 return FloatPoint( |
240 floatValueForLength(style.perspectiveOriginX(), borderBoxSize.width()), | 244 floatValueForLength(style.perspectiveOriginX(), borderBoxSize.width()), |
241 floatValueForLength(style.perspectiveOriginY(), borderBoxSize.height()))
; | 245 floatValueForLength(style.perspectiveOriginY(), borderBoxSize.height()))
; |
242 } | 246 } |
243 | 247 |
244 void PaintPropertyTreeBuilder::updatePerspective(const LayoutObject& object, Pai
ntPropertyTreeBuilderContext& context) | 248 void PaintPropertyTreeBuilder::updatePerspective(const LayoutObject& object, Pai
ntPropertyTreeBuilderContext& context) |
245 { | 249 { |
246 const ComputedStyle& style = object.styleRef(); | 250 const ComputedStyle& style = object.styleRef(); |
247 if (!object.isBox() || !style.hasPerspective()) | 251 if (!object.isBox() || !style.hasPerspective()) |
248 return; | 252 return; |
249 | 253 |
250 RefPtr<TransformPaintPropertyNode> perspective = TransformPaintPropertyNode:
:create( | 254 RefPtr<TransformPaintPropertyNode> perspective = TransformPaintPropertyNode:
:create( |
251 TransformationMatrix().applyPerspective(style.perspective()), | 255 TransformationMatrix().applyPerspective(style.perspective()), |
252 perspectiveOrigin(toLayoutBox(object)) + toLayoutSize(context.paintOffse
t), | 256 perspectiveOrigin(toLayoutBox(object)) + toLayoutSize(context.current.pa
intOffset), |
253 context.currentTransform); | 257 context.current.transform); |
254 context.currentTransform = perspective.get(); | 258 context.current.transform = perspective.get(); |
255 object.getMutableForPainting().ensureObjectPaintProperties().setPerspective(
perspective.release()); | 259 object.getMutableForPainting().ensureObjectPaintProperties().setPerspective(
perspective.release()); |
256 } | 260 } |
257 | 261 |
258 void PaintPropertyTreeBuilder::updateSvgLocalToBorderBoxTransform(const LayoutOb
ject& object, PaintPropertyTreeBuilderContext& context) | 262 void PaintPropertyTreeBuilder::updateSvgLocalToBorderBoxTransform(const LayoutOb
ject& object, PaintPropertyTreeBuilderContext& context) |
259 { | 263 { |
260 if (!object.isSVGRoot()) | 264 if (!object.isSVGRoot()) |
261 return; | 265 return; |
262 | 266 |
263 AffineTransform transformToBorderBox = SVGRootPainter(toLayoutSVGRoot(object
)).transformToPixelSnappedBorderBox(context.paintOffset); | 267 AffineTransform transformToBorderBox = SVGRootPainter(toLayoutSVGRoot(object
)).transformToPixelSnappedBorderBox(context.current.paintOffset); |
264 | 268 |
265 // The paint offset is included in |transformToBorderBox| so SVG does not ne
ed to handle paint | 269 // The paint offset is included in |transformToBorderBox| so SVG does not ne
ed to handle paint |
266 // offset internally. | 270 // offset internally. |
267 context.paintOffset = LayoutPoint(); | 271 context.current.paintOffset = LayoutPoint(); |
268 | 272 |
269 if (transformToBorderBox.isIdentity()) | 273 if (transformToBorderBox.isIdentity()) |
270 return; | 274 return; |
271 | 275 |
272 RefPtr<TransformPaintPropertyNode> svgLocalToBorderBoxTransform = TransformP
aintPropertyNode::create( | 276 RefPtr<TransformPaintPropertyNode> svgLocalToBorderBoxTransform = TransformP
aintPropertyNode::create( |
273 transformToBorderBox, FloatPoint3D(0, 0, 0), context.currentTransform); | 277 transformToBorderBox, FloatPoint3D(0, 0, 0), context.current.transform); |
274 context.currentTransform = svgLocalToBorderBoxTransform.get(); | 278 context.current.transform = svgLocalToBorderBoxTransform.get(); |
275 context.paintOffset = LayoutPoint(); | 279 context.current.paintOffset = LayoutPoint(); |
276 object.getMutableForPainting().ensureObjectPaintProperties().setSvgLocalToBo
rderBoxTransform(svgLocalToBorderBoxTransform.release()); | 280 object.getMutableForPainting().ensureObjectPaintProperties().setSvgLocalToBo
rderBoxTransform(svgLocalToBorderBoxTransform.release()); |
277 } | 281 } |
278 | 282 |
279 void PaintPropertyTreeBuilder::updateScrollTranslation(const LayoutObject& objec
t, PaintPropertyTreeBuilderContext& context) | 283 void PaintPropertyTreeBuilder::updateScrollTranslation(const LayoutObject& objec
t, PaintPropertyTreeBuilderContext& context) |
280 { | 284 { |
281 if (!object.isBoxModelObject() || !object.hasOverflowClip()) | 285 if (!object.isBoxModelObject() || !object.hasOverflowClip()) |
282 return; | 286 return; |
283 | 287 |
284 PaintLayer* layer = toLayoutBoxModelObject(object).layer(); | 288 PaintLayer* layer = toLayoutBoxModelObject(object).layer(); |
285 ASSERT(layer); | 289 ASSERT(layer); |
286 DoubleSize scrollOffset = layer->getScrollableArea()->scrollOffset(); | 290 DoubleSize scrollOffset = layer->getScrollableArea()->scrollOffset(); |
287 if (scrollOffset.isZero() && !layer->scrollsOverflow()) | 291 if (scrollOffset.isZero() && !layer->scrollsOverflow()) |
288 return; | 292 return; |
289 | 293 |
290 RefPtr<TransformPaintPropertyNode> scrollTranslation = TransformPaintPropert
yNode::create( | 294 RefPtr<TransformPaintPropertyNode> scrollTranslation = TransformPaintPropert
yNode::create( |
291 TransformationMatrix().translate(-scrollOffset.width(), -scrollOffset.he
ight()), | 295 TransformationMatrix().translate(-scrollOffset.width(), -scrollOffset.he
ight()), |
292 FloatPoint3D(), | 296 FloatPoint3D(), |
293 context.currentTransform); | 297 context.current.transform); |
294 context.currentTransform = scrollTranslation.get(); | 298 context.current.transform = scrollTranslation.get(); |
295 object.getMutableForPainting().ensureObjectPaintProperties().setScrollTransl
ation(scrollTranslation.release()); | 299 object.getMutableForPainting().ensureObjectPaintProperties().setScrollTransl
ation(scrollTranslation.release()); |
296 } | 300 } |
297 | 301 |
298 void PaintPropertyTreeBuilder::updateOutOfFlowContext(const LayoutObject& object
, PaintPropertyTreeBuilderContext& context) | 302 void PaintPropertyTreeBuilder::updateOutOfFlowContext(const LayoutObject& object
, PaintPropertyTreeBuilderContext& context) |
299 { | 303 { |
300 if (object.canContainAbsolutePositionObjects()) { | 304 if (object.canContainAbsolutePositionObjects()) { |
301 context.transformForAbsolutePosition = context.currentTransform; | 305 context.absolutePosition = context.current; |
302 context.paintOffsetForAbsolutePosition = context.paintOffset; | |
303 context.clipForAbsolutePosition = context.currentClip; | |
304 context.containerForAbsolutePosition = &object; | 306 context.containerForAbsolutePosition = &object; |
305 } | 307 } |
306 | 308 |
307 // TODO(pdr): Remove the !object.isLayoutView() condition when removing Fram
eView | 309 // TODO(pdr): Remove the !object.isLayoutView() condition when removing Fram
eView |
308 // paint properties for rootLayerScrolls. | 310 // paint properties for rootLayerScrolls. |
309 if (!object.isLayoutView() && object.canContainFixedPositionObjects()) { | 311 if (!object.isLayoutView() && object.canContainFixedPositionObjects()) { |
310 context.transformForFixedPosition = context.currentTransform; | 312 context.fixedPosition = context.current; |
311 context.paintOffsetForFixedPosition = context.paintOffset; | |
312 context.clipForFixedPosition = context.currentClip; | |
313 } else if (object.objectPaintProperties() && object.objectPaintProperties()-
>cssClip()) { | 313 } else if (object.objectPaintProperties() && object.objectPaintProperties()-
>cssClip()) { |
314 // CSS clip applies to all descendants, even if this object is not a con
taining block | 314 // CSS clip applies to all descendants, even if this object is not a con
taining block |
315 // ancestor of the descendant. It is okay for absolute-position descenda
nts because | 315 // ancestor of the descendant. It is okay for absolute-position descenda
nts because |
316 // having CSS clip implies being absolute position container. However fo
r fixed-position | 316 // having CSS clip implies being absolute position container. However fo
r fixed-position |
317 // descendants we need to insert the clip here if we are not a containin
g block ancestor | 317 // descendants we need to insert the clip here if we are not a containin
g block ancestor |
318 // of them. | 318 // of them. |
319 auto* cssClip = object.objectPaintProperties()->cssClip(); | 319 auto* cssClip = object.objectPaintProperties()->cssClip(); |
320 | 320 |
321 // Before we actually create anything, check whether in-flow context and
fixed-position | 321 // Before we actually create anything, check whether in-flow context and
fixed-position |
322 // context has exactly the same clip. Reuse if possible. | 322 // context has exactly the same clip. Reuse if possible. |
323 if (context.clipForFixedPosition == cssClip->parent()) { | 323 if (context.fixedPosition.clip == cssClip->parent()) { |
324 context.clipForFixedPosition = cssClip; | 324 context.fixedPosition.clip = cssClip; |
325 return; | 325 return; |
326 } | 326 } |
327 | 327 |
328 RefPtr<ClipPaintPropertyNode> clipFixedPosition = ClipPaintPropertyNode:
:create( | 328 RefPtr<ClipPaintPropertyNode> clipFixedPosition = ClipPaintPropertyNode:
:create( |
329 const_cast<TransformPaintPropertyNode*>(cssClip->localTransformSpace
()), | 329 const_cast<TransformPaintPropertyNode*>(cssClip->localTransformSpace
()), |
330 cssClip->clipRect(), | 330 cssClip->clipRect(), |
331 context.clipForFixedPosition); | 331 context.fixedPosition.clip); |
332 context.clipForFixedPosition = clipFixedPosition.get(); | 332 context.fixedPosition.clip = clipFixedPosition.get(); |
333 object.getMutableForPainting().ensureObjectPaintProperties().setCssClipF
ixedPosition(clipFixedPosition.release()); | 333 object.getMutableForPainting().ensureObjectPaintProperties().setCssClipF
ixedPosition(clipFixedPosition.release()); |
334 } | 334 } |
335 } | 335 } |
336 | 336 |
337 static void deriveBorderBoxFromContainerContext(const LayoutObject& object, Pain
tPropertyTreeBuilderContext& context) | 337 static void deriveBorderBoxFromContainerContext(const LayoutObject& object, Pain
tPropertyTreeBuilderContext& context) |
338 { | 338 { |
339 if (!object.isBoxModelObject()) | 339 if (!object.isBoxModelObject()) |
340 return; | 340 return; |
341 | 341 |
342 const LayoutBoxModelObject& boxModelObject = toLayoutBoxModelObject(object); | 342 const LayoutBoxModelObject& boxModelObject = toLayoutBoxModelObject(object); |
343 | 343 |
344 switch (object.styleRef().position()) { | 344 switch (object.styleRef().position()) { |
345 case StaticPosition: | 345 case StaticPosition: |
346 break; | 346 break; |
347 case RelativePosition: | 347 case RelativePosition: |
348 context.paintOffset += boxModelObject.offsetForInFlowPosition(); | 348 context.current.paintOffset += boxModelObject.offsetForInFlowPosition(); |
349 break; | 349 break; |
350 case AbsolutePosition: { | 350 case AbsolutePosition: { |
351 context.currentTransform = context.transformForAbsolutePosition; | 351 context.current = context.absolutePosition; |
352 context.paintOffset = context.paintOffsetForAbsolutePosition; | |
353 | 352 |
354 // Absolutely positioned content in an inline should be positioned relat
ive to the inline. | 353 // Absolutely positioned content in an inline should be positioned relat
ive to the inline. |
355 const LayoutObject* container = context.containerForAbsolutePosition; | 354 const LayoutObject* container = context.containerForAbsolutePosition; |
356 if (container && container->isInFlowPositioned() && container->isLayoutI
nline()) { | 355 if (container && container->isInFlowPositioned() && container->isLayoutI
nline()) { |
357 DCHECK(object.isBox()); | 356 DCHECK(object.isBox()); |
358 context.paintOffset += toLayoutInline(container)->offsetForInFlowPos
itionedInline(toLayoutBox(object)); | 357 context.current.paintOffset += toLayoutInline(container)->offsetForI
nFlowPositionedInline(toLayoutBox(object)); |
359 } | 358 } |
360 | |
361 context.currentClip = context.clipForAbsolutePosition; | |
362 break; | 359 break; |
363 } | 360 } |
364 case StickyPosition: | 361 case StickyPosition: |
365 context.paintOffset += boxModelObject.offsetForInFlowPosition(); | 362 context.current.paintOffset += boxModelObject.offsetForInFlowPosition(); |
366 break; | 363 break; |
367 case FixedPosition: | 364 case FixedPosition: |
368 context.currentTransform = context.transformForFixedPosition; | 365 context.current = context.fixedPosition; |
369 context.paintOffset = context.paintOffsetForFixedPosition; | |
370 context.currentClip = context.clipForFixedPosition; | |
371 break; | 366 break; |
372 default: | 367 default: |
373 ASSERT_NOT_REACHED(); | 368 ASSERT_NOT_REACHED(); |
374 } | 369 } |
375 if (boxModelObject.isBox() && (!boxModelObject.isSVG() || boxModelObject.isS
VGRoot())) { | 370 if (boxModelObject.isBox() && (!boxModelObject.isSVG() || boxModelObject.isS
VGRoot())) { |
376 // TODO(pdr): Several calls in this function walk back up the tree to ca
lculate containers | 371 // TODO(pdr): Several calls in this function walk back up the tree to ca
lculate containers |
377 // (e.g., topLeftLocation, offsetForInFlowPosition*). The containing blo
ck and other | 372 // (e.g., topLeftLocation, offsetForInFlowPosition*). The containing blo
ck and other |
378 // containers can be stored on PaintPropertyTreeBuilderContext instead o
f recomputing them. | 373 // containers can be stored on PaintPropertyTreeBuilderContext instead o
f recomputing them. |
379 context.paintOffset.moveBy(toLayoutBox(boxModelObject).topLeftLocation()
); | 374 context.current.paintOffset.moveBy(toLayoutBox(boxModelObject).topLeftLo
cation()); |
380 // This is a weird quirk that table cells paint as children of table row
s, | 375 // This is a weird quirk that table cells paint as children of table row
s, |
381 // but their location have the row's location baked-in. | 376 // but their location have the row's location baked-in. |
382 // Similar adjustment is done in LayoutTableCell::offsetFromContainer(). | 377 // Similar adjustment is done in LayoutTableCell::offsetFromContainer(). |
383 if (boxModelObject.isTableCell()) { | 378 if (boxModelObject.isTableCell()) { |
384 LayoutObject* parentRow = boxModelObject.parent(); | 379 LayoutObject* parentRow = boxModelObject.parent(); |
385 ASSERT(parentRow && parentRow->isTableRow()); | 380 ASSERT(parentRow && parentRow->isTableRow()); |
386 context.paintOffset.moveBy(-toLayoutBox(parentRow)->topLeftLocation(
)); | 381 context.current.paintOffset.moveBy(-toLayoutBox(parentRow)->topLeftL
ocation()); |
387 } | 382 } |
388 } | 383 } |
389 } | 384 } |
390 | 385 |
391 void PaintPropertyTreeBuilder::buildTreeNodes(const LayoutObject& object, PaintP
ropertyTreeBuilderContext& context) | 386 void PaintPropertyTreeBuilder::buildTreeNodes(const LayoutObject& object, PaintP
ropertyTreeBuilderContext& context) |
392 { | 387 { |
393 object.getMutableForPainting().clearObjectPaintProperties(); | 388 object.getMutableForPainting().clearObjectPaintProperties(); |
394 | 389 |
395 if (!object.isBoxModelObject() && !object.isSVG()) | 390 if (!object.isBoxModelObject() && !object.isSVG()) |
396 return; | 391 return; |
397 | 392 |
398 deriveBorderBoxFromContainerContext(object, context); | 393 deriveBorderBoxFromContainerContext(object, context); |
399 | 394 |
400 updatePaintOffsetTranslation(object, context); | 395 updatePaintOffsetTranslation(object, context); |
401 updateTransform(object, context); | 396 updateTransform(object, context); |
402 updateEffect(object, context); | 397 updateEffect(object, context); |
403 updateCssClip(object, context); | 398 updateCssClip(object, context); |
404 updateLocalBorderBoxContext(object, context); | 399 updateLocalBorderBoxContext(object, context); |
405 updateScrollbarPaintOffset(object, context); | 400 updateScrollbarPaintOffset(object, context); |
406 updateOverflowClip(object, context); | 401 updateOverflowClip(object, context); |
407 // TODO(trchen): Insert flattening transform here, as specified by | 402 // TODO(trchen): Insert flattening transform here, as specified by |
408 // http://www.w3.org/TR/css3-transforms/#transform-style-property | 403 // http://www.w3.org/TR/css3-transforms/#transform-style-property |
409 updatePerspective(object, context); | 404 updatePerspective(object, context); |
410 updateSvgLocalToBorderBoxTransform(object, context); | 405 updateSvgLocalToBorderBoxTransform(object, context); |
411 updateScrollTranslation(object, context); | 406 updateScrollTranslation(object, context); |
412 updateOutOfFlowContext(object, context); | 407 updateOutOfFlowContext(object, context); |
413 } | 408 } |
414 | 409 |
415 } // namespace blink | 410 } // namespace blink |
OLD | NEW |