| 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 |