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 "config.h" | 5 #include "config.h" |
| 6 #include "core/paint/PaintPropertyTreeBuilder.h" | 6 #include "core/paint/PaintPropertyTreeBuilder.h" |
| 7 | 7 |
| 8 #include "core/frame/FrameView.h" | 8 #include "core/frame/FrameView.h" |
| 9 #include "core/layout/LayoutView.h" | 9 #include "core/layout/LayoutView.h" |
| 10 #include "core/paint/ObjectPaintProperties.h" | 10 #include "core/paint/ObjectPaintProperties.h" |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 72 localContext.currentTransform = localContext.transformForOutOfFlowPositioned = newTransformNodeForScrollTranslation.get(); | 72 localContext.currentTransform = localContext.transformForOutOfFlowPositioned = newTransformNodeForScrollTranslation.get(); |
| 73 localContext.paintOffset = localContext.paintOffsetForOutOfFlowPositioned = LayoutPoint(); | 73 localContext.paintOffset = localContext.paintOffsetForOutOfFlowPositioned = LayoutPoint(); |
| 74 | 74 |
| 75 frameView.setPreTranslation(newTransformNodeForPreTranslation.release()); | 75 frameView.setPreTranslation(newTransformNodeForPreTranslation.release()); |
| 76 frameView.setScrollTranslation(newTransformNodeForScrollTranslation.release( )); | 76 frameView.setScrollTranslation(newTransformNodeForScrollTranslation.release( )); |
| 77 | 77 |
| 78 if (LayoutView* layoutView = frameView.layoutView()) | 78 if (LayoutView* layoutView = frameView.layoutView()) |
| 79 walk(*layoutView, localContext); | 79 walk(*layoutView, localContext); |
| 80 } | 80 } |
| 81 | 81 |
| 82 static void deriveBorderBoxFromContainerContext(const LayoutBoxModelObject& obje ct, PaintPropertyTreeBuilderContext& context) | 82 static void deriveBorderBoxFromContainerContext(const LayoutObject& object, Pain tPropertyTreeBuilderContext& context) |
| 83 { | 83 { |
| 84 if (!object.isBoxModelObject()) | |
| 85 return; | |
| 86 | |
| 87 const LayoutBoxModelObject& boxModelObject = toLayoutBoxModelObject(object); | |
| 88 | |
| 84 // TODO(trchen): There is some insanity going on with tables. Double check r esults. | 89 // TODO(trchen): There is some insanity going on with tables. Double check r esults. |
| 85 switch (object.styleRef().position()) { | 90 switch (object.styleRef().position()) { |
| 86 case StaticPosition: | 91 case StaticPosition: |
| 87 break; | 92 break; |
| 88 case RelativePosition: | 93 case RelativePosition: |
| 89 context.paintOffset += object.offsetForInFlowPosition(); | 94 context.paintOffset += boxModelObject.offsetForInFlowPosition(); |
| 90 break; | 95 break; |
| 91 case AbsolutePosition: | 96 case AbsolutePosition: |
| 92 context.currentTransform = context.transformForOutOfFlowPositioned; | 97 context.currentTransform = context.transformForOutOfFlowPositioned; |
| 93 context.paintOffset = context.paintOffsetForOutOfFlowPositioned; | 98 context.paintOffset = context.paintOffsetForOutOfFlowPositioned; |
| 94 break; | 99 break; |
| 95 case StickyPosition: | 100 case StickyPosition: |
| 96 context.paintOffset += object.offsetForInFlowPosition(); | 101 context.paintOffset += boxModelObject.offsetForInFlowPosition(); |
| 97 break; | 102 break; |
| 98 case FixedPosition: | 103 case FixedPosition: |
| 99 context.currentTransform = context.transformForFixedPositioned; | 104 context.currentTransform = context.transformForFixedPositioned; |
| 100 context.paintOffset = context.paintOffsetForFixedPositioned; | 105 context.paintOffset = context.paintOffsetForFixedPositioned; |
| 101 break; | 106 break; |
| 102 default: | 107 default: |
| 103 ASSERT_NOT_REACHED(); | 108 ASSERT_NOT_REACHED(); |
| 104 } | 109 } |
| 105 if (object.isBox()) | 110 if (boxModelObject.isBox()) |
| 106 context.paintOffset += toLayoutBox(object).locationOffset(); | 111 context.paintOffset += toLayoutBox(boxModelObject).locationOffset(); |
| 107 } | 112 } |
| 108 | 113 |
| 109 static PassRefPtr<TransformPaintPropertyNode> createPaintOffsetTranslationIfNeed ed(const LayoutBoxModelObject& object, PaintPropertyTreeBuilderContext& context) | 114 static PassRefPtr<TransformPaintPropertyNode> createPaintOffsetTranslationIfNeed ed(const LayoutObject& object, PaintPropertyTreeBuilderContext& context) |
| 110 { | 115 { |
| 111 // TODO(trchen): Eliminate PaintLayer dependency. | 116 bool shouldCreatePaintOffsetTranslationNode = false; |
| 112 bool shouldCreatePaintOffsetTranslationNode = object.layer() && object.layer ()->paintsWithTransform(GlobalPaintNormalPhase); | 117 if (object.isSVGRoot()) { |
| 118 // SVG doesn't use paint offset internally so emit a paint offset at the html->svg boundary. | |
| 119 shouldCreatePaintOffsetTranslationNode = true; | |
| 120 } else if (object.isBoxModelObject()) { | |
| 121 // TODO(trchen): Eliminate PaintLayer dependency. | |
| 122 PaintLayer* layer = toLayoutBoxModelObject(object).layer(); | |
| 123 shouldCreatePaintOffsetTranslationNode = layer && layer->paintsWithTrans form(GlobalPaintNormalPhase); | |
| 124 } | |
| 113 | 125 |
| 114 if (context.paintOffset == LayoutPoint() || !shouldCreatePaintOffsetTranslat ionNode) | 126 if (context.paintOffset == LayoutPoint() || !shouldCreatePaintOffsetTranslat ionNode) |
| 115 return nullptr; | 127 return nullptr; |
| 116 | 128 |
| 117 TransformationMatrix matrix; | 129 TransformationMatrix matrix; |
| 118 matrix.translate(context.paintOffset.x(), context.paintOffset.y()); | 130 matrix.translate(context.paintOffset.x(), context.paintOffset.y()); |
| 119 RefPtr<TransformPaintPropertyNode> newTransformNodeForPaintOffsetTranslation = TransformPaintPropertyNode::create( | 131 RefPtr<TransformPaintPropertyNode> newTransformNodeForPaintOffsetTranslation = TransformPaintPropertyNode::create( |
| 120 TransformationMatrix().translate(context.paintOffset.x(), context.paintO ffset.y()), | 132 TransformationMatrix().translate(context.paintOffset.x(), context.paintO ffset.y()), |
| 121 FloatPoint3D(), context.currentTransform); | 133 FloatPoint3D(), context.currentTransform); |
| 122 context.currentTransform = newTransformNodeForPaintOffsetTranslation.get(); | 134 context.currentTransform = newTransformNodeForPaintOffsetTranslation.get(); |
| 123 context.paintOffset = LayoutPoint(); | 135 context.paintOffset = LayoutPoint(); |
| 124 return newTransformNodeForPaintOffsetTranslation.release(); | 136 return newTransformNodeForPaintOffsetTranslation.release(); |
| 125 } | 137 } |
| 126 | 138 |
| 127 static FloatPoint3D transformOrigin(const LayoutBox& box) | 139 static FloatPoint3D transformOrigin(const LayoutBox& box) |
| 128 { | 140 { |
| 129 const ComputedStyle& style = box.styleRef(); | 141 const ComputedStyle& style = box.styleRef(); |
| 130 FloatSize borderBoxSize(box.size()); | 142 FloatSize borderBoxSize(box.size()); |
| 131 return FloatPoint3D( | 143 return FloatPoint3D( |
| 132 floatValueForLength(style.transformOriginX(), borderBoxSize.width()), | 144 floatValueForLength(style.transformOriginX(), borderBoxSize.width()), |
| 133 floatValueForLength(style.transformOriginY(), borderBoxSize.height()), | 145 floatValueForLength(style.transformOriginY(), borderBoxSize.height()), |
| 134 style.transformOriginZ()); | 146 style.transformOriginZ()); |
| 135 } | 147 } |
| 136 | 148 |
| 137 static PassRefPtr<TransformPaintPropertyNode> createTransformIfNeeded(const Layo utBoxModelObject& object, PaintPropertyTreeBuilderContext& context) | 149 static PassRefPtr<TransformPaintPropertyNode> createTransformIfNeeded(const Layo utObject& object, PaintPropertyTreeBuilderContext& context) |
| 138 { | 150 { |
| 151 if (object.isSVG() && !object.isSVGRoot()) { | |
| 152 const AffineTransform& transform = object.localToParentTransform(); | |
| 153 if (transform.isIdentity()) | |
| 154 return nullptr; | |
| 155 | |
| 156 // SVG's transform origin is baked into the localToParentTransform. | |
| 157 RefPtr<TransformPaintPropertyNode> newTransformNodeForTransform = Transf ormPaintPropertyNode::create( | |
| 158 transform, FloatPoint3D(0, 0, 0), context.currentTransform); | |
| 159 context.currentTransform = newTransformNodeForTransform.get(); | |
| 160 return newTransformNodeForTransform.release(); | |
| 161 } | |
| 162 | |
| 139 const ComputedStyle& style = object.styleRef(); | 163 const ComputedStyle& style = object.styleRef(); |
| 140 if (!object.isBox() || !style.hasTransform()) | 164 if (!object.isBox() || !style.hasTransform()) |
| 141 return nullptr; | 165 return nullptr; |
| 142 | 166 |
| 143 ASSERT(context.paintOffset == LayoutPoint()); | 167 ASSERT(context.paintOffset == LayoutPoint()); |
| 144 | 168 |
| 145 TransformationMatrix matrix; | 169 TransformationMatrix matrix; |
| 146 style.applyTransform(matrix, toLayoutBox(object).size(), ComputedStyle::Excl udeTransformOrigin, | 170 style.applyTransform(matrix, toLayoutBox(object).size(), ComputedStyle::Excl udeTransformOrigin, |
| 147 ComputedStyle::IncludeMotionPath, ComputedStyle::IncludeIndependentTrans formProperties); | 171 ComputedStyle::IncludeMotionPath, ComputedStyle::IncludeIndependentTrans formProperties); |
| 148 RefPtr<TransformPaintPropertyNode> newTransformNodeForTransform = TransformP aintPropertyNode::create( | 172 RefPtr<TransformPaintPropertyNode> newTransformNodeForTransform = TransformP aintPropertyNode::create( |
| 149 matrix, transformOrigin(toLayoutBox(object)), context.currentTransform); | 173 matrix, transformOrigin(toLayoutBox(object)), context.currentTransform); |
| 150 context.currentTransform = newTransformNodeForTransform.get(); | 174 context.currentTransform = newTransformNodeForTransform.get(); |
| 151 return newTransformNodeForTransform.release(); | 175 return newTransformNodeForTransform.release(); |
| 152 } | 176 } |
| 153 | 177 |
| 154 static PassRefPtr<EffectPaintPropertyNode> createEffectIfNeeded(const LayoutBoxM odelObject& object, PaintPropertyTreeBuilderContext& context) | 178 static PassRefPtr<EffectPaintPropertyNode> createEffectIfNeeded(const LayoutObje ct& object, PaintPropertyTreeBuilderContext& context) |
| 155 { | 179 { |
| 156 const ComputedStyle& style = object.styleRef(); | 180 const ComputedStyle& style = object.styleRef(); |
| 157 if (!object.isBox() || !style.hasOpacity()) | 181 if (!style.hasOpacity()) |
| 158 return nullptr; | 182 return nullptr; |
| 159 RefPtr<EffectPaintPropertyNode> newEffectNode = EffectPaintPropertyNode::cre ate(style.opacity(), context.currentEffect); | 183 RefPtr<EffectPaintPropertyNode> newEffectNode = EffectPaintPropertyNode::cre ate(style.opacity(), context.currentEffect); |
| 160 context.currentEffect = newEffectNode.get(); | 184 context.currentEffect = newEffectNode.get(); |
| 161 return newEffectNode.release(); | 185 return newEffectNode.release(); |
| 162 } | 186 } |
| 163 | 187 |
| 164 static FloatPoint perspectiveOrigin(const LayoutBox& box) | 188 static FloatPoint perspectiveOrigin(const LayoutBox& box) |
| 165 { | 189 { |
| 166 const ComputedStyle& style = box.styleRef(); | 190 const ComputedStyle& style = box.styleRef(); |
| 167 FloatSize borderBoxSize(box.size()); | 191 FloatSize borderBoxSize(box.size()); |
| 168 return FloatPoint( | 192 return FloatPoint( |
| 169 floatValueForLength(style.perspectiveOriginX(), borderBoxSize.width()), | 193 floatValueForLength(style.perspectiveOriginX(), borderBoxSize.width()), |
| 170 floatValueForLength(style.perspectiveOriginY(), borderBoxSize.height())) ; | 194 floatValueForLength(style.perspectiveOriginY(), borderBoxSize.height())) ; |
| 171 } | 195 } |
| 172 | 196 |
| 173 static PassRefPtr<TransformPaintPropertyNode> createPerspectiveIfNeeded(const La youtBoxModelObject& object, PaintPropertyTreeBuilderContext& context) | 197 static PassRefPtr<TransformPaintPropertyNode> createPerspectiveIfNeeded(const La youtObject& object, PaintPropertyTreeBuilderContext& context) |
| 174 { | 198 { |
| 175 const ComputedStyle& style = object.styleRef(); | 199 const ComputedStyle& style = object.styleRef(); |
| 176 if (!object.isBox() || !style.hasPerspective()) | 200 if (!object.isBox() || !style.hasPerspective()) |
| 177 return nullptr; | 201 return nullptr; |
| 178 | 202 |
| 179 RefPtr<TransformPaintPropertyNode> newTransformNodeForPerspective = Transfor mPaintPropertyNode::create( | 203 RefPtr<TransformPaintPropertyNode> newTransformNodeForPerspective = Transfor mPaintPropertyNode::create( |
| 180 TransformationMatrix().applyPerspective(style.perspective()), | 204 TransformationMatrix().applyPerspective(style.perspective()), |
| 181 perspectiveOrigin(toLayoutBox(object)) + toLayoutSize(context.paintOffse t), context.currentTransform); | 205 perspectiveOrigin(toLayoutBox(object)) + toLayoutSize(context.paintOffse t), context.currentTransform); |
| 182 context.currentTransform = newTransformNodeForPerspective.get(); | 206 context.currentTransform = newTransformNodeForPerspective.get(); |
| 183 return newTransformNodeForPerspective.release(); | 207 return newTransformNodeForPerspective.release(); |
| 184 } | 208 } |
| 185 | 209 |
| 186 static PassRefPtr<TransformPaintPropertyNode> createScrollTranslationIfNeeded(co nst LayoutBoxModelObject& object, PaintPropertyTreeBuilderContext& context) | 210 static PassRefPtr<TransformPaintPropertyNode> createScrollTranslationIfNeeded(co nst LayoutObject& object, PaintPropertyTreeBuilderContext& context) |
| 187 { | 211 { |
| 188 if (!object.hasOverflowClip()) | 212 if (!object.isBoxModelObject() || !object.hasOverflowClip()) |
| 189 return nullptr; | 213 return nullptr; |
| 190 | 214 |
| 191 PaintLayer* layer = object.layer(); | 215 PaintLayer* layer = toLayoutBoxModelObject(object).layer(); |
| 192 ASSERT(layer); | 216 ASSERT(layer); |
| 193 DoubleSize scrollOffset = layer->scrollableArea()->scrollOffset(); | 217 DoubleSize scrollOffset = layer->scrollableArea()->scrollOffset(); |
| 194 if (scrollOffset.isZero() && !layer->scrollsOverflow()) | 218 if (scrollOffset.isZero() && !layer->scrollsOverflow()) |
| 195 return nullptr; | 219 return nullptr; |
| 196 | 220 |
| 197 RefPtr<TransformPaintPropertyNode> newTransformNodeForScrollTranslation = Tr ansformPaintPropertyNode::create( | 221 RefPtr<TransformPaintPropertyNode> newTransformNodeForScrollTranslation = Tr ansformPaintPropertyNode::create( |
| 198 TransformationMatrix().translate(-scrollOffset.width(), -scrollOffset.he ight()), | 222 TransformationMatrix().translate(-scrollOffset.width(), -scrollOffset.he ight()), |
| 199 FloatPoint3D(), context.currentTransform); | 223 FloatPoint3D(), context.currentTransform); |
| 200 context.currentTransform = newTransformNodeForScrollTranslation.get(); | 224 context.currentTransform = newTransformNodeForScrollTranslation.get(); |
| 201 return newTransformNodeForScrollTranslation.release(); | 225 return newTransformNodeForScrollTranslation.release(); |
| 202 } | 226 } |
| 203 | 227 |
| 204 static void updateOutOfFlowContext(const LayoutBoxModelObject& object, PaintProp ertyTreeBuilderContext& context) | 228 static void updateOutOfFlowContext(const LayoutObject& object, PaintPropertyTree BuilderContext& context) |
| 205 { | 229 { |
| 206 const ComputedStyle& style = object.styleRef(); | 230 const ComputedStyle& style = object.styleRef(); |
| 207 bool hasTransform = object.isBox() && style.hasTransform(); | 231 bool hasTransform = object.isBox() && style.hasTransform(); |
| 208 if (style.position() != StaticPosition || hasTransform) { | 232 if (style.position() != StaticPosition || hasTransform) { |
|
trchen
2015/11/20 22:52:09
|| object.isSVGForeignObject()
| |
| 209 context.transformForOutOfFlowPositioned = context.currentTransform; | 233 context.transformForOutOfFlowPositioned = context.currentTransform; |
| 210 context.paintOffsetForOutOfFlowPositioned = context.paintOffset; | 234 context.paintOffsetForOutOfFlowPositioned = context.paintOffset; |
| 211 } | 235 } |
| 212 if (hasTransform) { | 236 if (hasTransform) { |
|
trchen
2015/11/20 22:52:09
ditto
| |
| 213 context.transformForFixedPositioned = context.currentTransform; | 237 context.transformForFixedPositioned = context.currentTransform; |
| 214 context.paintOffsetForFixedPositioned = context.paintOffset; | 238 context.paintOffsetForFixedPositioned = context.paintOffset; |
| 215 } | 239 } |
| 216 } | 240 } |
| 217 | 241 |
| 218 void PaintPropertyTreeBuilder::walk(LayoutBoxModelObject& object, const PaintPro pertyTreeBuilderContext& context) | 242 void PaintPropertyTreeBuilder::walk(LayoutObject& object, const PaintPropertyTre eBuilderContext& context) |
| 219 { | 243 { |
| 220 ASSERT(object.isBox() != object.isLayoutInline()); // Either or. | |
| 221 | |
| 222 PaintPropertyTreeBuilderContext localContext(context); | 244 PaintPropertyTreeBuilderContext localContext(context); |
| 223 | 245 |
| 224 deriveBorderBoxFromContainerContext(object, localContext); | 246 deriveBorderBoxFromContainerContext(object, localContext); |
| 225 RefPtr<TransformPaintPropertyNode> newTransformNodeForPaintOffsetTranslation = createPaintOffsetTranslationIfNeeded(object, localContext); | 247 RefPtr<TransformPaintPropertyNode> newTransformNodeForPaintOffsetTranslation = createPaintOffsetTranslationIfNeeded(object, localContext); |
| 226 RefPtr<TransformPaintPropertyNode> newTransformNodeForTransform = createTran sformIfNeeded(object, localContext); | 248 RefPtr<TransformPaintPropertyNode> newTransformNodeForTransform = createTran sformIfNeeded(object, localContext); |
| 227 RefPtr<EffectPaintPropertyNode> newEffectNode = createEffectIfNeeded(object, localContext); | 249 RefPtr<EffectPaintPropertyNode> newEffectNode = createEffectIfNeeded(object, localContext); |
| 228 RefPtr<TransformPaintPropertyNode> newTransformNodeForPerspective = createPe rspectiveIfNeeded(object, localContext); | 250 RefPtr<TransformPaintPropertyNode> newTransformNodeForPerspective = createPe rspectiveIfNeeded(object, localContext); |
| 229 RefPtr<TransformPaintPropertyNode> newTransformNodeForScrollTranslation = cr eateScrollTranslationIfNeeded(object, localContext); | 251 RefPtr<TransformPaintPropertyNode> newTransformNodeForScrollTranslation = cr eateScrollTranslationIfNeeded(object, localContext); |
| 230 updateOutOfFlowContext(object, localContext); | 252 updateOutOfFlowContext(object, localContext); |
| 231 | 253 |
| 232 if (newTransformNodeForPaintOffsetTranslation || newTransformNodeForTransfor m || newEffectNode || newTransformNodeForPerspective || newTransformNodeForScrol lTranslation) { | 254 if (newTransformNodeForPaintOffsetTranslation || newTransformNodeForTransfor m || newEffectNode || newTransformNodeForPerspective || newTransformNodeForScrol lTranslation) { |
| 233 OwnPtr<ObjectPaintProperties> updatedPaintProperties = ObjectPaintProper ties::create( | 255 OwnPtr<ObjectPaintProperties> updatedPaintProperties = ObjectPaintProper ties::create( |
| 234 newTransformNodeForPaintOffsetTranslation.release(), | 256 newTransformNodeForPaintOffsetTranslation.release(), |
| 235 newTransformNodeForTransform.release(), | 257 newTransformNodeForTransform.release(), |
| 236 newEffectNode.release(), | 258 newEffectNode.release(), |
| 237 newTransformNodeForPerspective.release(), | 259 newTransformNodeForPerspective.release(), |
| 238 newTransformNodeForScrollTranslation.release()); | 260 newTransformNodeForScrollTranslation.release()); |
| 239 object.setObjectPaintProperties(updatedPaintProperties.release()); | 261 object.setObjectPaintProperties(updatedPaintProperties.release()); |
| 240 } else { | 262 } else { |
| 241 object.clearObjectPaintProperties(); | 263 object.clearObjectPaintProperties(); |
| 242 } | 264 } |
| 243 | 265 |
| 244 // TODO(trchen): Walk subframes for LayoutFrame. | 266 // TODO(trchen): Walk subframes for LayoutFrame. |
| 245 | 267 |
| 246 // TODO(trchen): Implement SVG walk. | |
| 247 if (object.isSVGRoot()) { | |
| 248 return; | |
| 249 } | |
| 250 | |
| 251 for (LayoutObject* child = object.slowFirstChild(); child; child = child->ne xtSibling()) { | 268 for (LayoutObject* child = object.slowFirstChild(); child; child = child->ne xtSibling()) { |
| 252 if (child->isText()) | 269 if (child->isBoxModelObject() || child->isSVG()) |
| 253 continue; | 270 walk(*child, localContext); |
| 254 walk(toLayoutBoxModelObject(*child), localContext); | |
| 255 } | 271 } |
| 256 } | 272 } |
| 257 | 273 |
| 258 } // namespace blink | 274 } // namespace blink |
| OLD | NEW |