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/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 if (!rootFrame.rootTransform() || rootFrame.rootTransform()->parent()) { |
| 25 context.current.transform = context.absolutePosition.transform = context.fix edPosition.transform = transformRoot.get(); | 25 rootFrame.setRootTransform(TransformPaintPropertyNode::create(Transforma tionMatrix(), FloatPoint3D(), nullptr)); |
| 26 rootFrame.setRootTransform(std::move(transformRoot)); | 26 rootFrame.setRootClip(ClipPaintPropertyNode::create(rootFrame.rootTransf orm(), FloatRoundedRect(LayoutRect::infiniteIntRect()), nullptr)); |
| 27 rootFrame.setRootEffect(EffectPaintPropertyNode::create(1.0, nullptr)); | |
| 28 } else { | |
| 29 DCHECK(rootFrame.rootClip() && !rootFrame.rootClip()->parent()); | |
| 30 DCHECK(rootFrame.rootEffect() && !rootFrame.rootEffect()->parent()); | |
| 31 } | |
| 27 | 32 |
| 28 RefPtr<ClipPaintPropertyNode> clipRoot = ClipPaintPropertyNode::create(trans formRoot, FloatRoundedRect(LayoutRect::infiniteIntRect()), nullptr); | 33 context.current.transform = context.absolutePosition.transform = context.fix edPosition.transform = rootFrame.rootTransform(); |
| 29 context.current.clip = context.absolutePosition.clip = context.fixedPosition .clip = clipRoot.get(); | 34 context.current.clip = context.absolutePosition.clip = context.fixedPosition .clip = rootFrame.rootClip(); |
| 30 rootFrame.setRootClip(std::move(clipRoot)); | 35 context.currentEffect = rootFrame.rootEffect(); |
| 31 | |
| 32 RefPtr<EffectPaintPropertyNode> effectRoot = EffectPaintPropertyNode::create (1.0, nullptr); | |
| 33 context.currentEffect = effectRoot.get(); | |
| 34 rootFrame.setRootEffect(std::move(effectRoot)); | |
| 35 } | 36 } |
| 36 | 37 |
| 37 void PaintPropertyTreeBuilder::buildTreeNodes(FrameView& frameView, PaintPropert yTreeBuilderContext& context) | 38 void PaintPropertyTreeBuilder::buildTreeNodes(FrameView& frameView, PaintPropert yTreeBuilderContext& context) |
| 38 { | 39 { |
| 39 // TODO(pdr): Creating paint properties for FrameView here will not be | 40 // TODO(pdr): Creating paint properties for FrameView here will not be |
| 40 // needed once settings()->rootLayerScrolls() is enabled. | 41 // needed once settings()->rootLayerScrolls() is enabled. |
| 41 // TODO(pdr): Make this conditional on the rootLayerScrolls setting. | 42 // TODO(pdr): Make this conditional on the rootLayerScrolls setting. |
| 42 | 43 |
| 43 TransformationMatrix frameTranslate; | 44 TransformationMatrix frameTranslate; |
| 44 frameTranslate.translate(frameView.x() + context.current.paintOffset.x(), fr ameView.y() + context.current.paintOffset.y()); | 45 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.current.tr ansform); | 46 if (!frameView.preTranslation() || frameView.preTranslation()->matrix() != f rameTranslate) |
| 47 frameView.setPreTranslation(TransformPaintPropertyNode::create(frameTran slate, FloatPoint3D(), context.current.transform)); | |
| 46 | 48 |
| 47 FloatRoundedRect contentClip(IntRect(IntPoint(), frameView.visibleContentSiz e())); | 49 FloatRoundedRect contentClip(IntRect(IntPoint(), frameView.visibleContentSiz e())); |
| 48 RefPtr<ClipPaintPropertyNode> newClipNodeForContentClip = ClipPaintPropertyN ode::create(newTransformNodeForPreTranslation.get(), contentClip, context.curren t.clip); | 50 if (!frameView.contentClip() || frameView.contentClip()->clipRect() != conte ntClip) |
| 51 frameView.setContentClip(ClipPaintPropertyNode::create(frameView.preTran slation(), contentClip, context.current.clip)); | |
| 49 | 52 |
| 50 DoubleSize scrollOffset = frameView.scrollOffsetDouble(); | 53 DoubleSize scrollOffset = frameView.scrollOffsetDouble(); |
| 51 TransformationMatrix frameScroll; | 54 TransformationMatrix frameScroll; |
| 52 frameScroll.translate(-scrollOffset.width(), -scrollOffset.height()); | 55 frameScroll.translate(-scrollOffset.width(), -scrollOffset.height()); |
| 53 RefPtr<TransformPaintPropertyNode> newTransformNodeForScrollTranslation = Tr ansformPaintPropertyNode::create(frameScroll, FloatPoint3D(), newTransformNodeFo rPreTranslation); | 56 if (!frameView.scrollTranslation() || frameView.scrollTranslation()->matrix( ) != frameScroll) |
| 57 frameView.setScrollTranslation(TransformPaintPropertyNode::create(frameS croll, FloatPoint3D(), frameView.preTranslation())); | |
| 54 | 58 |
| 55 // Initialize the context for current, absolute and fixed position cases. | 59 // Initialize the context for current, absolute and fixed position cases. |
| 56 // They are the same, except that scroll translation does not apply to | 60 // They are the same, except that scroll translation does not apply to |
| 57 // fixed position descendants. | 61 // fixed position descendants. |
| 58 context.current.transform = newTransformNodeForScrollTranslation.get(); | 62 context.current.transform = frameView.scrollTranslation(); |
| 59 context.current.paintOffset = LayoutPoint(); | 63 context.current.paintOffset = LayoutPoint(); |
| 60 context.current.clip = newClipNodeForContentClip.get(); | 64 context.current.clip = frameView.contentClip(); |
| 61 context.absolutePosition = context.current; | 65 context.absolutePosition = context.current; |
| 62 context.containerForAbsolutePosition = nullptr; | 66 context.containerForAbsolutePosition = nullptr; |
| 63 context.fixedPosition = context.current; | 67 context.fixedPosition = context.current; |
| 64 context.fixedPosition.transform = newTransformNodeForPreTranslation.get(); | 68 context.fixedPosition.transform = frameView.preTranslation(); |
| 65 | |
| 66 frameView.setPreTranslation(newTransformNodeForPreTranslation.release()); | |
| 67 frameView.setScrollTranslation(newTransformNodeForScrollTranslation.release( )); | |
| 68 frameView.setContentClip(newClipNodeForContentClip.release()); | |
| 69 } | 69 } |
| 70 | 70 |
| 71 void PaintPropertyTreeBuilder::updatePaintOffsetTranslation(const LayoutObject& object, PaintPropertyTreeBuilderContext& context) | 71 template < |
| 72 typename PropertyNode, | |
| 73 PropertyNode* (ObjectPaintProperties::*Getter)() const, | |
| 74 void (ObjectPaintProperties::*Setter)(PassRefPtr<PropertyNode>), | |
| 75 bool (*ComputeProperty)(const LayoutObject&, PaintPropertyTreeBuilderContext &, typename PropertyNode::Value&)> | |
| 76 PropertyNode* PaintPropertyTreeBuilder::updateObjectPaintProperty(const LayoutOb ject& object, PaintPropertyTreeBuilderContext& context, PropertyNode*& contextPr operty) | |
|
pdr.
2016/07/21 21:34:06
This template approach is very clever. WDYT of thi
Xianzhu
2016/07/22 01:14:05
Many thanks for the sample CL. Mixed your code int
| |
| 72 { | 77 { |
| 73 if (object.isBoxModelObject()) { | 78 ObjectPaintProperties* previousProperties = object.objectPaintProperties(); |
| 74 // TODO(trchen): Eliminate PaintLayer dependency. | 79 typename PropertyNode::Value newPropertyValue; |
| 75 PaintLayer* layer = toLayoutBoxModelObject(object).layer(); | 80 if (!ComputeProperty(object, context, newPropertyValue)) { |
| 76 if (!layer || !layer->paintsWithTransform(GlobalPaintNormalPhase)) | 81 if (previousProperties) |
| 77 return; | 82 (previousProperties->*Setter)(nullptr); |
| 83 return nullptr; | |
| 78 } | 84 } |
| 79 | 85 |
| 86 PropertyNode* previousPropertyNode = previousProperties ? (previousPropertie s->*Getter)() : nullptr; | |
| 87 if (previousPropertyNode && previousPropertyNode->value() == newPropertyValu e) { | |
| 88 previousPropertyNode->setParent(contextProperty); | |
| 89 contextProperty = previousPropertyNode; | |
| 90 return previousPropertyNode; | |
| 91 } | |
| 92 | |
| 93 RefPtr<PropertyNode> newPropertyNode = PropertyNode::create(newPropertyValue , contextProperty); | |
| 94 contextProperty = newPropertyNode.get(); | |
| 95 (object.getMutableForPainting().ensureObjectPaintProperties().*Setter)(newPr opertyNode.release()); | |
| 96 return contextProperty; | |
| 97 } | |
| 98 | |
| 99 bool PaintPropertyTreeBuilder::computePaintOffsetTranslation(const LayoutObject& object, PaintPropertyTreeBuilderContext& context, TransformPaintPropertyNode::V alue& value) | |
| 100 { | |
| 101 if (!object.isBoxModelObject()) | |
| 102 return false; | |
| 103 | |
| 104 // TODO(trchen): Eliminate PaintLayer dependency. | |
| 105 PaintLayer* layer = toLayoutBoxModelObject(object).layer(); | |
| 106 if (!layer || !layer->paintsWithTransform(GlobalPaintNormalPhase)) | |
| 107 return false; | |
| 108 | |
| 80 if (context.current.paintOffset == LayoutPoint()) | 109 if (context.current.paintOffset == LayoutPoint()) |
| 81 return; | 110 return false; |
| 82 | 111 |
| 83 // We should use the same subpixel paint offset values for snapping regardle ss of whether a | 112 // We should use the same subpixel paint offset values for snapping regardle ss of whether a |
| 84 // transform is present. If there is a transform we round the paint offset b ut keep around | 113 // transform is present. If there is a transform we round the paint offset b ut keep around |
| 85 // the residual fractional component for the transformed content to paint wi th. | 114 // the residual fractional component for the transformed content to paint wi th. |
| 86 // In spv1 this was called "subpixel accumulation". For more information, se e | 115 // In spv1 this was called "subpixel accumulation". For more information, se e |
| 87 // PaintLayer::subpixelAccumulation() and PaintLayerPainter::paintFragmentBy ApplyingTransform. | 116 // PaintLayer::subpixelAccumulation() and PaintLayerPainter::paintFragmentBy ApplyingTransform. |
| 88 IntPoint roundedPaintOffset = roundedIntPoint(context.current.paintOffset); | 117 IntPoint roundedPaintOffset = roundedIntPoint(context.current.paintOffset); |
| 89 LayoutPoint fractionalPaintOffset = LayoutPoint(context.current.paintOffset - roundedPaintOffset); | 118 LayoutPoint fractionalPaintOffset = LayoutPoint(context.current.paintOffset - roundedPaintOffset); |
| 90 | 119 |
| 91 RefPtr<TransformPaintPropertyNode> paintOffsetTranslation = TransformPaintPr opertyNode::create( | 120 value.matrix.translate(roundedPaintOffset.x(), roundedPaintOffset.y()); |
| 92 TransformationMatrix().translate(roundedPaintOffset.x(), roundedPaintOff set.y()), | |
| 93 FloatPoint3D(), context.current.transform); | |
| 94 context.current.transform = paintOffsetTranslation.get(); | |
| 95 context.current.paintOffset = fractionalPaintOffset; | 121 context.current.paintOffset = fractionalPaintOffset; |
| 96 object.getMutableForPainting().ensureObjectPaintProperties().setPaintOffsetT ranslation(paintOffsetTranslation.release()); | 122 return true; |
| 123 } | |
| 124 | |
| 125 void PaintPropertyTreeBuilder::updatePaintOffsetTranslation(const LayoutObject& object, PaintPropertyTreeBuilderContext& context) | |
| 126 { | |
| 127 updateObjectPaintProperty< | |
| 128 TransformPaintPropertyNode, | |
| 129 &ObjectPaintProperties::paintOffsetTranslation, | |
| 130 &ObjectPaintProperties::setPaintOffsetTranslation, | |
| 131 &computePaintOffsetTranslation>(object, context, context.current.transfo rm); | |
| 97 } | 132 } |
| 98 | 133 |
| 99 static FloatPoint3D transformOrigin(const LayoutBox& box) | 134 static FloatPoint3D transformOrigin(const LayoutBox& box) |
| 100 { | 135 { |
| 101 const ComputedStyle& style = box.styleRef(); | 136 const ComputedStyle& style = box.styleRef(); |
| 102 FloatSize borderBoxSize(box.size()); | 137 FloatSize borderBoxSize(box.size()); |
| 103 return FloatPoint3D( | 138 return FloatPoint3D( |
| 104 floatValueForLength(style.transformOriginX(), borderBoxSize.width()), | 139 floatValueForLength(style.transformOriginX(), borderBoxSize.width()), |
| 105 floatValueForLength(style.transformOriginY(), borderBoxSize.height()), | 140 floatValueForLength(style.transformOriginY(), borderBoxSize.height()), |
| 106 style.transformOriginZ()); | 141 style.transformOriginZ()); |
| 107 } | 142 } |
| 108 | 143 |
| 109 void PaintPropertyTreeBuilder::updateTransform(const LayoutObject& object, Paint PropertyTreeBuilderContext& context) | 144 bool PaintPropertyTreeBuilder::computeTransform(const LayoutObject& object, Pain tPropertyTreeBuilderContext& context, TransformPaintPropertyNode::Value& value) |
| 110 { | 145 { |
| 111 if (object.isSVG() && !object.isSVGRoot()) { | 146 if (object.isSVG() && !object.isSVGRoot()) { |
| 112 // SVG does not use paint offset internally. | 147 // SVG does not use paint offset internally. |
| 113 DCHECK(context.current.paintOffset == LayoutPoint()); | 148 DCHECK(context.current.paintOffset == LayoutPoint()); |
| 114 | 149 |
| 115 // FIXME(pdr): Check for the presence of a transform instead of the valu e. Checking for an | 150 // FIXME(pdr): Check for the presence of a transform instead of the valu e. Checking for an |
| 116 // identity matrix will cause the property tree structure to change duri ng animations if | 151 // identity matrix will cause the property tree structure to change duri ng animations if |
| 117 // the animation passes through the identity matrix. | 152 // the animation passes through the identity matrix. |
| 118 // FIXME(pdr): Refactor this so all non-root SVG objects use the same tr ansform function. | 153 // FIXME(pdr): Refactor this so all non-root SVG objects use the same tr ansform function. |
| 119 const AffineTransform& transform = object.isSVGForeignObject() ? object. localSVGTransform() : object.localToSVGParentTransform(); | 154 const AffineTransform& transform = object.isSVGForeignObject() ? object. localSVGTransform() : object.localToSVGParentTransform(); |
| 120 if (transform.isIdentity()) | 155 if (transform.isIdentity()) |
| 121 return; | 156 return false; |
| 122 | 157 |
| 123 // The origin is included in the local transform, so use an empty origin . | 158 value.matrix = transform; |
| 124 RefPtr<TransformPaintPropertyNode> svgTransform = TransformPaintProperty Node::create( | 159 // The origin is included in the local transform, so leave origin empty. |
| 125 transform, FloatPoint3D(0, 0, 0), context.current.transform); | 160 return true; |
| 126 context.current.transform = svgTransform.get(); | |
| 127 object.getMutableForPainting().ensureObjectPaintProperties().setTransfor m(svgTransform.release()); | |
| 128 return; | |
| 129 } | 161 } |
| 130 | 162 |
| 131 const ComputedStyle& style = object.styleRef(); | 163 const ComputedStyle& style = object.styleRef(); |
| 132 if (!object.isBox() || !style.hasTransform()) | 164 if (!object.isBox() || !style.hasTransform()) |
| 133 return; | 165 return false; |
| 134 | 166 |
| 135 TransformationMatrix matrix; | 167 style.applyTransform(value.matrix, toLayoutBox(object).size(), ComputedStyle ::ExcludeTransformOrigin, |
| 136 style.applyTransform(matrix, toLayoutBox(object).size(), ComputedStyle::Excl udeTransformOrigin, | |
| 137 ComputedStyle::IncludeMotionPath, ComputedStyle::IncludeIndependentTrans formProperties); | 168 ComputedStyle::IncludeMotionPath, ComputedStyle::IncludeIndependentTrans formProperties); |
| 138 RefPtr<TransformPaintPropertyNode> transformNode = TransformPaintPropertyNod e::create( | 169 value.origin = transformOrigin(toLayoutBox(object)); |
| 139 matrix, transformOrigin(toLayoutBox(object)), context.current.transform) ; | 170 return true; |
| 140 context.current.transform = transformNode.get(); | 171 } |
| 141 object.getMutableForPainting().ensureObjectPaintProperties().setTransform(tr ansformNode.release()); | 172 |
| 173 void PaintPropertyTreeBuilder::updateTransform(const LayoutObject& object, Paint PropertyTreeBuilderContext& context) | |
| 174 { | |
| 175 updateObjectPaintProperty< | |
| 176 TransformPaintPropertyNode, | |
| 177 &ObjectPaintProperties::transform, | |
| 178 &ObjectPaintProperties::setTransform, | |
| 179 &computeTransform>(object, context, context.current.transform); | |
| 180 } | |
| 181 | |
| 182 bool PaintPropertyTreeBuilder::computeEffect(const LayoutObject& object, PaintPr opertyTreeBuilderContext& context, EffectPaintPropertyNode::Value& value) | |
| 183 { | |
| 184 if (!object.styleRef().hasOpacity()) | |
| 185 return false; | |
| 186 | |
| 187 value = object.styleRef().opacity(); | |
| 188 return true; | |
| 142 } | 189 } |
| 143 | 190 |
| 144 void PaintPropertyTreeBuilder::updateEffect(const LayoutObject& object, PaintPro pertyTreeBuilderContext& context) | 191 void PaintPropertyTreeBuilder::updateEffect(const LayoutObject& object, PaintPro pertyTreeBuilderContext& context) |
| 145 { | 192 { |
| 146 if (!object.styleRef().hasOpacity()) | 193 updateObjectPaintProperty< |
| 147 return; | 194 EffectPaintPropertyNode, |
| 148 RefPtr<EffectPaintPropertyNode> effectNode = EffectPaintPropertyNode::create (object.styleRef().opacity(), context.currentEffect); | 195 &ObjectPaintProperties::effect, |
| 149 context.currentEffect = effectNode.get(); | 196 &ObjectPaintProperties::setEffect, |
| 150 object.getMutableForPainting().ensureObjectPaintProperties().setEffect(effec tNode.release()); | 197 &computeEffect>(object, context, context.currentEffect); |
| 151 } | 198 } |
| 152 | 199 |
| 153 void PaintPropertyTreeBuilder::updateCssClip(const LayoutObject& object, PaintPr opertyTreeBuilderContext& context) | 200 bool PaintPropertyTreeBuilder::computeCssClip(const LayoutObject& object, PaintP ropertyTreeBuilderContext& context, ClipPaintPropertyNode::Value& value) |
| 154 { | 201 { |
| 155 if (!object.hasClip()) | 202 if (!object.hasClip()) |
| 156 return; | 203 return false; |
| 157 ASSERT(object.canContainAbsolutePositionObjects()); | 204 DCHECK(object.canContainAbsolutePositionObjects()); |
| 158 | 205 |
| 159 // Create clip node for descendants that are not fixed position. | 206 // Create clip node for descendants that are not fixed position. |
| 160 // We don't have to setup context.absolutePosition.clip here because this ob ject must be | 207 // We don't have to setup context.absolutePosition.clip here because this ob ject must be |
| 161 // a container for absolute position descendants, and will copy from in-flow context later | 208 // a container for absolute position descendants, and will copy from in-flow context later |
| 162 // at updateOutOfFlowContext() step. | 209 // at updateOutOfFlowContext() step. |
| 163 LayoutRect clipRect = toLayoutBox(object).clipRect(context.current.paintOffs et); | 210 LayoutRect clipRect = toLayoutBox(object).clipRect(context.current.paintOffs et); |
| 164 RefPtr<ClipPaintPropertyNode> clipNode = ClipPaintPropertyNode::create( | 211 value = FloatRoundedRect(FloatRect(clipRect)); |
| 165 context.current.transform, | 212 return true; |
| 166 FloatRoundedRect(FloatRect(clipRect)), | 213 } |
| 167 context.current.clip); | 214 |
| 168 context.current.clip = clipNode.get(); | 215 void PaintPropertyTreeBuilder::updateCssClip(const LayoutObject& object, PaintPr opertyTreeBuilderContext& context) |
| 169 object.getMutableForPainting().ensureObjectPaintProperties().setCssClip(clip Node.release()); | 216 { |
| 217 if (ClipPaintPropertyNode* node = updateObjectPaintProperty< | |
| 218 ClipPaintPropertyNode, | |
| 219 &ObjectPaintProperties::cssClip, | |
| 220 &ObjectPaintProperties::setCssClip, | |
| 221 &computeCssClip>(object, context, context.current.clip)) | |
| 222 node->setLocalTransformSpace(context.current.transform); | |
| 170 } | 223 } |
| 171 | 224 |
| 172 void PaintPropertyTreeBuilder::updateLocalBorderBoxContext(const LayoutObject& o bject, const PaintPropertyTreeBuilderContext& context) | 225 void PaintPropertyTreeBuilder::updateLocalBorderBoxContext(const LayoutObject& o bject, const PaintPropertyTreeBuilderContext& context) |
| 173 { | 226 { |
| 174 // Avoid adding an ObjectPaintProperties for non-boxes to save memory, since we don't need them at the moment. | 227 // Avoid adding an ObjectPaintProperties for non-boxes to save memory, since we don't need them at the moment. |
| 175 if (!object.isBox() && !object.hasLayer()) | 228 if (!object.isBox() && !object.hasLayer()) |
| 176 return; | 229 return; |
| 177 | 230 |
| 178 std::unique_ptr<ObjectPaintProperties::LocalBorderBoxProperties> borderBoxCo ntext = | 231 std::unique_ptr<ObjectPaintProperties::LocalBorderBoxProperties> borderBoxCo ntext = |
| 179 wrapUnique(new ObjectPaintProperties::LocalBorderBoxProperties); | 232 wrapUnique(new ObjectPaintProperties::LocalBorderBoxProperties); |
| 180 borderBoxContext->paintOffset = context.current.paintOffset; | 233 borderBoxContext->paintOffset = context.current.paintOffset; |
| 181 borderBoxContext->propertyTreeState = PropertyTreeState(context.current.tran sform, context.current.clip, context.currentEffect); | 234 borderBoxContext->propertyTreeState = PropertyTreeState(context.current.tran sform, context.current.clip, context.currentEffect); |
| 182 object.getMutableForPainting().ensureObjectPaintProperties().setLocalBorderB oxProperties(std::move(borderBoxContext)); | 235 object.getMutableForPainting().ensureObjectPaintProperties().setLocalBorderB oxProperties(std::move(borderBoxContext)); |
| 183 } | 236 } |
| 184 | 237 |
| 185 // TODO(trchen): Remove this once we bake the paint offset into frameRect. | 238 // TODO(trchen): Remove this once we bake the paint offset into frameRect. |
| 239 bool PaintPropertyTreeBuilder::computeScrollbarPaintOffset(const LayoutObject& o bject, const PaintPropertyTreeBuilderContext& context, TransformPaintPropertyNod e::Value& value) | |
| 240 { | |
| 241 IntPoint roundedPaintOffset = roundedIntPoint(context.current.paintOffset); | |
| 242 if (roundedPaintOffset == IntPoint()) | |
| 243 return false; | |
| 244 | |
| 245 if (!object.isBoxModelObject()) | |
| 246 return false; | |
| 247 PaintLayerScrollableArea* scrollableArea = toLayoutBoxModelObject(object).ge tScrollableArea(); | |
| 248 if (!scrollableArea) | |
| 249 return false; | |
| 250 if (!scrollableArea->horizontalScrollbar() && !scrollableArea->verticalScrol lbar()) | |
| 251 return false; | |
| 252 | |
| 253 value.matrix.translate(roundedPaintOffset.x(), roundedPaintOffset.y()); | |
| 254 return true; | |
| 255 } | |
| 256 | |
| 257 // TODO(trchen): Remove this once we bake the paint offset into frameRect. | |
| 186 void PaintPropertyTreeBuilder::updateScrollbarPaintOffset(const LayoutObject& ob ject, const PaintPropertyTreeBuilderContext& context) | 258 void PaintPropertyTreeBuilder::updateScrollbarPaintOffset(const LayoutObject& ob ject, const PaintPropertyTreeBuilderContext& context) |
| 187 { | 259 { |
| 188 IntPoint roundedPaintOffset = roundedIntPoint(context.current.paintOffset); | 260 // This method is almost the same as updateObjectPaintProperty template, exc ept that it doesn't |
|
pdr.
2016/07/21 21:34:06
Can you think of a way to use the same update obje
Xianzhu
2016/07/22 01:14:04
Done.
| |
| 189 if (roundedPaintOffset == IntPoint()) | 261 // update any context property. |
| 262 ObjectPaintProperties* previousProperties = object.objectPaintProperties(); | |
| 263 TransformPaintPropertyNode::Value paintOffset; | |
| 264 if (!computeScrollbarPaintOffset(object, context, paintOffset)) { | |
| 265 if (previousProperties) | |
| 266 (previousProperties->setScrollbarPaintOffset(nullptr)); | |
| 190 return; | 267 return; |
| 268 } | |
| 191 | 269 |
| 192 if (!object.isBoxModelObject()) | 270 TransformPaintPropertyNode* previousScrollbarPaintOffsetNode = previousPrope rties ? previousProperties->scrollbarPaintOffset() : nullptr; |
| 271 if (previousScrollbarPaintOffsetNode && previousScrollbarPaintOffsetNode->va lue() == paintOffset) { | |
| 272 previousScrollbarPaintOffsetNode->setParent(context.current.transform); | |
| 193 return; | 273 return; |
| 194 PaintLayerScrollableArea* scrollableArea = toLayoutBoxModelObject(object).ge tScrollableArea(); | 274 } |
| 195 if (!scrollableArea) | |
| 196 return; | |
| 197 if (!scrollableArea->horizontalScrollbar() && !scrollableArea->verticalScrol lbar()) | |
| 198 return; | |
| 199 | 275 |
| 200 auto paintOffset = TransformationMatrix().translate(roundedPaintOffset.x(), roundedPaintOffset.y()); | |
| 201 object.getMutableForPainting().ensureObjectPaintProperties().setScrollbarPai ntOffset( | 276 object.getMutableForPainting().ensureObjectPaintProperties().setScrollbarPai ntOffset( |
| 202 TransformPaintPropertyNode::create(paintOffset, FloatPoint3D(), context. current.transform)); | 277 TransformPaintPropertyNode::create(paintOffset, context.current.transfor m)); |
| 203 } | 278 } |
| 204 | 279 |
| 205 void PaintPropertyTreeBuilder::updateOverflowClip(const LayoutObject& object, Pa intPropertyTreeBuilderContext& context) | 280 bool PaintPropertyTreeBuilder::computeOverflowClip(const LayoutObject& object, P aintPropertyTreeBuilderContext& context, ClipPaintPropertyNode::Value& value) |
| 206 { | 281 { |
| 207 if (!object.isBox()) | |
| 208 return; | |
| 209 const LayoutBox& box = toLayoutBox(object); | 282 const LayoutBox& box = toLayoutBox(object); |
| 210 | 283 |
| 211 // The <input> elements can't have contents thus CSS overflow property doesn 't apply. | 284 // The <input> elements can't have contents thus CSS overflow property doesn 't apply. |
| 212 // However for layout purposes we do generate child layout objects for them, e.g. button label. | 285 // However for layout purposes we do generate child layout objects for them, e.g. button label. |
| 213 // We should clip the overflow from those children. This is called control c lip and we | 286 // We should clip the overflow from those children. This is called control c lip and we |
| 214 // technically treat them like overflow clip. | 287 // technically treat them like overflow clip. |
| 215 LayoutRect clipRect; | 288 LayoutRect clipRect; |
| 216 if (box.hasControlClip()) | 289 if (box.hasControlClip()) |
| 217 clipRect = box.controlClipRect(context.current.paintOffset); | 290 clipRect = box.controlClipRect(context.current.paintOffset); |
| 218 else if (box.hasOverflowClip()) | 291 else if (box.hasOverflowClip()) |
| 219 clipRect = box.overflowClipRect(context.current.paintOffset); | 292 clipRect = box.overflowClipRect(context.current.paintOffset); |
| 220 else | 293 else |
| 294 return false; | |
| 295 | |
| 296 value = FloatRoundedRect(FloatRect(clipRect)); | |
| 297 return true; | |
| 298 } | |
| 299 | |
| 300 void PaintPropertyTreeBuilder::updateOverflowClip(const LayoutObject& object, Pa intPropertyTreeBuilderContext& context) | |
| 301 { | |
| 302 if (!object.isBox()) | |
| 221 return; | 303 return; |
| 304 const LayoutBox& box = toLayoutBox(object); | |
| 222 | 305 |
| 306 // This need to be in top-level block to hold the reference until we finish creating the normal clip node. | |
| 223 RefPtr<ClipPaintPropertyNode> borderRadiusClip; | 307 RefPtr<ClipPaintPropertyNode> borderRadiusClip; |
| 224 if (box.styleRef().hasBorderRadius()) { | 308 if ((box.hasControlClip() || box.hasOverflowClip()) && box.styleRef().hasBor derRadius()) { |
| 225 auto innerBorder = box.styleRef().getRoundedInnerBorderFor( | 309 auto innerBorder = box.styleRef().getRoundedInnerBorderFor( |
| 226 LayoutRect(context.current.paintOffset, box.size())); | 310 LayoutRect(context.current.paintOffset, box.size())); |
| 227 borderRadiusClip = ClipPaintPropertyNode::create( | 311 borderRadiusClip = ClipPaintPropertyNode::create(context.current.transfo rm, innerBorder, context.current.clip); |
| 228 context.current.transform, innerBorder, context.current.clip); | 312 context.current.clip = borderRadiusClip.get(); |
| 229 } | 313 } |
| 230 | 314 |
| 231 RefPtr<ClipPaintPropertyNode> overflowClip = ClipPaintPropertyNode::create( | 315 if (ClipPaintPropertyNode* node = updateObjectPaintProperty< |
| 232 context.current.transform, | 316 ClipPaintPropertyNode, |
| 233 FloatRoundedRect(FloatRect(clipRect)), | 317 &ObjectPaintProperties::overflowClip, |
| 234 borderRadiusClip ? borderRadiusClip.release() : context.current.clip); | 318 &ObjectPaintProperties::setOverflowClip, |
| 235 context.current.clip = overflowClip.get(); | 319 &computeOverflowClip>(object, context, context.current.clip)) |
| 236 object.getMutableForPainting().ensureObjectPaintProperties().setOverflowClip (overflowClip.release()); | 320 node->setLocalTransformSpace(context.current.transform); |
| 237 } | 321 } |
| 238 | 322 |
| 239 static FloatPoint perspectiveOrigin(const LayoutBox& box) | 323 static FloatPoint perspectiveOrigin(const LayoutBox& box) |
| 240 { | 324 { |
| 241 const ComputedStyle& style = box.styleRef(); | 325 const ComputedStyle& style = box.styleRef(); |
| 242 FloatSize borderBoxSize(box.size()); | 326 FloatSize borderBoxSize(box.size()); |
| 243 return FloatPoint( | 327 return FloatPoint( |
| 244 floatValueForLength(style.perspectiveOriginX(), borderBoxSize.width()), | 328 floatValueForLength(style.perspectiveOriginX(), borderBoxSize.width()), |
| 245 floatValueForLength(style.perspectiveOriginY(), borderBoxSize.height())) ; | 329 floatValueForLength(style.perspectiveOriginY(), borderBoxSize.height())) ; |
| 246 } | 330 } |
| 247 | 331 |
| 332 bool PaintPropertyTreeBuilder::computePerspective(const LayoutObject& object, Pa intPropertyTreeBuilderContext& context, TransformPaintPropertyNode::Value& value ) | |
| 333 { | |
| 334 const ComputedStyle& style = object.styleRef(); | |
| 335 if (!object.isBox() || !style.hasPerspective()) | |
| 336 return false; | |
| 337 | |
| 338 value.matrix.applyPerspective(style.perspective()); | |
| 339 value.origin = perspectiveOrigin(toLayoutBox(object)) + toLayoutSize(context .current.paintOffset); | |
| 340 return true; | |
| 341 } | |
| 342 | |
| 248 void PaintPropertyTreeBuilder::updatePerspective(const LayoutObject& object, Pai ntPropertyTreeBuilderContext& context) | 343 void PaintPropertyTreeBuilder::updatePerspective(const LayoutObject& object, Pai ntPropertyTreeBuilderContext& context) |
| 249 { | 344 { |
| 250 const ComputedStyle& style = object.styleRef(); | 345 updateObjectPaintProperty< |
| 251 if (!object.isBox() || !style.hasPerspective()) | 346 TransformPaintPropertyNode, |
| 252 return; | 347 &ObjectPaintProperties::perspective, |
| 253 | 348 &ObjectPaintProperties::setPerspective, |
| 254 RefPtr<TransformPaintPropertyNode> perspective = TransformPaintPropertyNode: :create( | 349 &computePerspective>(object, context, context.current.transform); |
| 255 TransformationMatrix().applyPerspective(style.perspective()), | |
| 256 perspectiveOrigin(toLayoutBox(object)) + toLayoutSize(context.current.pa intOffset), | |
| 257 context.current.transform); | |
| 258 context.current.transform = perspective.get(); | |
| 259 object.getMutableForPainting().ensureObjectPaintProperties().setPerspective( perspective.release()); | |
| 260 } | 350 } |
| 261 | 351 |
| 262 void PaintPropertyTreeBuilder::updateSvgLocalToBorderBoxTransform(const LayoutOb ject& object, PaintPropertyTreeBuilderContext& context) | 352 bool PaintPropertyTreeBuilder::computeSvgLocalToBorderBoxTransform(const LayoutO bject& object, PaintPropertyTreeBuilderContext& context, TransformPaintPropertyN ode::Value& value) |
| 263 { | 353 { |
| 264 if (!object.isSVGRoot()) | 354 if (!object.isSVGRoot()) |
| 265 return; | 355 return false; |
| 266 | 356 |
| 267 AffineTransform transformToBorderBox = SVGRootPainter(toLayoutSVGRoot(object )).transformToPixelSnappedBorderBox(context.current.paintOffset); | 357 AffineTransform transformToBorderBox = SVGRootPainter(toLayoutSVGRoot(object )).transformToPixelSnappedBorderBox(context.current.paintOffset); |
| 268 | 358 |
| 269 // The paint offset is included in |transformToBorderBox| so SVG does not ne ed to handle paint | 359 // The paint offset is included in |transformToBorderBox| so SVG does not ne ed to handle paint |
| 270 // offset internally. | 360 // offset internally. |
| 271 context.current.paintOffset = LayoutPoint(); | 361 context.current.paintOffset = LayoutPoint(); |
| 272 | 362 |
| 273 if (transformToBorderBox.isIdentity()) | 363 if (transformToBorderBox.isIdentity()) |
| 274 return; | 364 return false; |
| 275 | 365 |
| 276 RefPtr<TransformPaintPropertyNode> svgLocalToBorderBoxTransform = TransformP aintPropertyNode::create( | 366 value.matrix = transformToBorderBox; |
| 277 transformToBorderBox, FloatPoint3D(0, 0, 0), context.current.transform); | |
| 278 context.current.transform = svgLocalToBorderBoxTransform.get(); | |
| 279 context.current.paintOffset = LayoutPoint(); | 367 context.current.paintOffset = LayoutPoint(); |
| 280 object.getMutableForPainting().ensureObjectPaintProperties().setSvgLocalToBo rderBoxTransform(svgLocalToBorderBoxTransform.release()); | 368 return true; |
| 281 } | 369 } |
| 282 | 370 |
| 283 void PaintPropertyTreeBuilder::updateScrollTranslation(const LayoutObject& objec t, PaintPropertyTreeBuilderContext& context) | 371 void PaintPropertyTreeBuilder::updateSvgLocalToBorderBoxTransform(const LayoutOb ject& object, PaintPropertyTreeBuilderContext& context) |
| 372 { | |
| 373 updateObjectPaintProperty< | |
| 374 TransformPaintPropertyNode, | |
| 375 &ObjectPaintProperties::svgLocalToBorderBoxTransform, | |
| 376 &ObjectPaintProperties::setSvgLocalToBorderBoxTransform, | |
| 377 &computeSvgLocalToBorderBoxTransform>(object, context, context.current.t ransform); | |
| 378 } | |
| 379 | |
| 380 bool PaintPropertyTreeBuilder::computeScrollTranslation(const LayoutObject& obje ct, PaintPropertyTreeBuilderContext& context, TransformPaintPropertyNode::Value& value) | |
| 284 { | 381 { |
| 285 if (!object.isBoxModelObject() || !object.hasOverflowClip()) | 382 if (!object.isBoxModelObject() || !object.hasOverflowClip()) |
| 286 return; | 383 return false; |
| 287 | 384 |
| 288 PaintLayer* layer = toLayoutBoxModelObject(object).layer(); | 385 PaintLayer* layer = toLayoutBoxModelObject(object).layer(); |
| 289 ASSERT(layer); | 386 ASSERT(layer); |
| 290 DoubleSize scrollOffset = layer->getScrollableArea()->scrollOffset(); | 387 DoubleSize scrollOffset = layer->getScrollableArea()->scrollOffset(); |
| 291 if (scrollOffset.isZero() && !layer->scrollsOverflow()) | 388 if (scrollOffset.isZero() && !layer->scrollsOverflow()) |
| 292 return; | 389 return false; |
| 293 | 390 |
| 294 RefPtr<TransformPaintPropertyNode> scrollTranslation = TransformPaintPropert yNode::create( | 391 value.matrix.translate(-scrollOffset.width(), -scrollOffset.height()); |
| 295 TransformationMatrix().translate(-scrollOffset.width(), -scrollOffset.he ight()), | 392 return true; |
| 296 FloatPoint3D(), | |
| 297 context.current.transform); | |
| 298 context.current.transform = scrollTranslation.get(); | |
| 299 object.getMutableForPainting().ensureObjectPaintProperties().setScrollTransl ation(scrollTranslation.release()); | |
| 300 } | 393 } |
| 301 | 394 |
| 302 void PaintPropertyTreeBuilder::updateOutOfFlowContext(const LayoutObject& object , PaintPropertyTreeBuilderContext& context) | 395 void PaintPropertyTreeBuilder::updateScrollTranslation(const LayoutObject& objec t, PaintPropertyTreeBuilderContext& context) |
| 396 { | |
| 397 updateObjectPaintProperty< | |
| 398 TransformPaintPropertyNode, | |
| 399 &ObjectPaintProperties::scrollTranslation, | |
| 400 &ObjectPaintProperties::setScrollTranslation, | |
| 401 &computeScrollTranslation>(object, context, context.current.transform); | |
| 402 } | |
| 403 | |
| 404 // Returns true if we need to create a cssClip node for fixed position. | |
| 405 bool PaintPropertyTreeBuilder::computeOutOfFlowContext(const LayoutObject& objec t, PaintPropertyTreeBuilderContext& context, ClipPaintPropertyNode::Value& value ) | |
| 303 { | 406 { |
| 304 if (object.canContainAbsolutePositionObjects()) { | 407 if (object.canContainAbsolutePositionObjects()) { |
| 305 context.absolutePosition = context.current; | 408 context.absolutePosition = context.current; |
| 306 context.containerForAbsolutePosition = &object; | 409 context.containerForAbsolutePosition = &object; |
| 307 } | 410 } |
| 308 | 411 |
| 309 // TODO(pdr): Remove the !object.isLayoutView() condition when removing Fram eView | 412 // TODO(pdr): Remove the !object.isLayoutView() condition when removing Fram eView |
| 310 // paint properties for rootLayerScrolls. | 413 // paint properties for rootLayerScrolls. |
| 311 if (!object.isLayoutView() && object.canContainFixedPositionObjects()) { | 414 if (!object.isLayoutView() && object.canContainFixedPositionObjects()) { |
| 312 context.fixedPosition = context.current; | 415 context.fixedPosition = context.current; |
| 313 } else if (object.objectPaintProperties() && object.objectPaintProperties()- >cssClip()) { | 416 return false; |
| 314 // CSS clip applies to all descendants, even if this object is not a con taining block | 417 } |
| 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 | |
| 317 // descendants we need to insert the clip here if we are not a containin g block ancestor | |
| 318 // of them. | |
| 319 auto* cssClip = object.objectPaintProperties()->cssClip(); | |
| 320 | 418 |
| 321 // Before we actually create anything, check whether in-flow context and fixed-position | 419 if (!object.objectPaintProperties() || !object.objectPaintProperties()->cssC lip()) |
| 322 // context has exactly the same clip. Reuse if possible. | 420 return false; |
| 323 if (context.fixedPosition.clip == cssClip->parent()) { | |
| 324 context.fixedPosition.clip = cssClip; | |
| 325 return; | |
| 326 } | |
| 327 | 421 |
| 328 RefPtr<ClipPaintPropertyNode> clipFixedPosition = ClipPaintPropertyNode: :create( | 422 // CSS clip applies to all descendants, even if this object is not a contain ing block |
| 329 const_cast<TransformPaintPropertyNode*>(cssClip->localTransformSpace ()), | 423 // ancestor of the descendant. It is okay for absolute-position descendants because |
| 330 cssClip->clipRect(), | 424 // having CSS clip implies being absolute position container. However for fi xed-position |
| 331 context.fixedPosition.clip); | 425 // descendants we need to insert the clip here if we are not a containing bl ock ancestor |
| 332 context.fixedPosition.clip = clipFixedPosition.get(); | 426 // of them. |
| 333 object.getMutableForPainting().ensureObjectPaintProperties().setCssClipF ixedPosition(clipFixedPosition.release()); | 427 auto* cssClip = object.objectPaintProperties()->cssClip(); |
| 428 | |
| 429 // Before we actually create anything, check whether in-flow context and fix ed-position | |
| 430 // context has exactly the same clip. Reuse if possible. | |
| 431 if (context.fixedPosition.clip == cssClip->parent()) { | |
| 432 context.fixedPosition.clip = cssClip; | |
| 433 return false; | |
| 334 } | 434 } |
| 435 | |
| 436 value = cssClip->clipRect(); | |
| 437 return true; | |
| 438 } | |
| 439 | |
| 440 void PaintPropertyTreeBuilder::updateOutOfFlowContext(const LayoutObject& object , PaintPropertyTreeBuilderContext& context) | |
| 441 { | |
| 442 if (ClipPaintPropertyNode* node = updateObjectPaintProperty< | |
| 443 ClipPaintPropertyNode, | |
| 444 &ObjectPaintProperties::cssClipFixedPosition, | |
| 445 &ObjectPaintProperties::setCssClipFixedPosition, | |
| 446 &computeOutOfFlowContext>(object, context, context.fixedPosition.clip)) | |
| 447 node->setLocalTransformSpace(const_cast<TransformPaintPropertyNode*>(obj ect.objectPaintProperties()->cssClip()->localTransformSpace())); | |
| 335 } | 448 } |
| 336 | 449 |
| 337 static void deriveBorderBoxFromContainerContext(const LayoutObject& object, Pain tPropertyTreeBuilderContext& context) | 450 static void deriveBorderBoxFromContainerContext(const LayoutObject& object, Pain tPropertyTreeBuilderContext& context) |
| 338 { | 451 { |
| 339 if (!object.isBoxModelObject()) | 452 if (!object.isBoxModelObject()) |
| 340 return; | 453 return; |
| 341 | 454 |
| 342 const LayoutBoxModelObject& boxModelObject = toLayoutBoxModelObject(object); | 455 const LayoutBoxModelObject& boxModelObject = toLayoutBoxModelObject(object); |
| 343 | 456 |
| 344 switch (object.styleRef().position()) { | 457 switch (object.styleRef().position()) { |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 378 if (boxModelObject.isTableCell()) { | 491 if (boxModelObject.isTableCell()) { |
| 379 LayoutObject* parentRow = boxModelObject.parent(); | 492 LayoutObject* parentRow = boxModelObject.parent(); |
| 380 ASSERT(parentRow && parentRow->isTableRow()); | 493 ASSERT(parentRow && parentRow->isTableRow()); |
| 381 context.current.paintOffset.moveBy(-toLayoutBox(parentRow)->topLeftL ocation()); | 494 context.current.paintOffset.moveBy(-toLayoutBox(parentRow)->topLeftL ocation()); |
| 382 } | 495 } |
| 383 } | 496 } |
| 384 } | 497 } |
| 385 | 498 |
| 386 void PaintPropertyTreeBuilder::buildTreeNodes(const LayoutObject& object, PaintP ropertyTreeBuilderContext& context) | 499 void PaintPropertyTreeBuilder::buildTreeNodes(const LayoutObject& object, PaintP ropertyTreeBuilderContext& context) |
| 387 { | 500 { |
| 388 object.getMutableForPainting().clearObjectPaintProperties(); | |
| 389 | |
| 390 if (!object.isBoxModelObject() && !object.isSVG()) | 501 if (!object.isBoxModelObject() && !object.isSVG()) |
| 391 return; | 502 return; |
| 392 | 503 |
| 393 deriveBorderBoxFromContainerContext(object, context); | 504 deriveBorderBoxFromContainerContext(object, context); |
| 394 | 505 |
| 395 updatePaintOffsetTranslation(object, context); | 506 updatePaintOffsetTranslation(object, context); |
| 396 updateTransform(object, context); | 507 updateTransform(object, context); |
| 397 updateEffect(object, context); | 508 updateEffect(object, context); |
| 398 updateCssClip(object, context); | 509 updateCssClip(object, context); |
| 399 updateLocalBorderBoxContext(object, context); | 510 updateLocalBorderBoxContext(object, context); |
| 400 updateScrollbarPaintOffset(object, context); | 511 updateScrollbarPaintOffset(object, context); |
| 401 updateOverflowClip(object, context); | 512 updateOverflowClip(object, context); |
| 402 // TODO(trchen): Insert flattening transform here, as specified by | 513 // TODO(trchen): Insert flattening transform here, as specified by |
| 403 // http://www.w3.org/TR/css3-transforms/#transform-style-property | 514 // http://www.w3.org/TR/css3-transforms/#transform-style-property |
| 404 updatePerspective(object, context); | 515 updatePerspective(object, context); |
| 405 updateSvgLocalToBorderBoxTransform(object, context); | 516 updateSvgLocalToBorderBoxTransform(object, context); |
| 406 updateScrollTranslation(object, context); | 517 updateScrollTranslation(object, context); |
| 407 updateOutOfFlowContext(object, context); | 518 updateOutOfFlowContext(object, context); |
| 408 } | 519 } |
| 409 | 520 |
| 410 } // namespace blink | 521 } // namespace blink |
| OLD | NEW |