Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(132)

Side by Side Diff: third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp

Issue 1461223002: Implement SVG's transform and effect paint property nodes (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix fixed position bug discovered by TienRen Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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 RefPtr<TransformPaintPropertyNode> newTransformNodeForPaintOffsetTranslation = TransformPaintPropertyNode::create( 129 RefPtr<TransformPaintPropertyNode> newTransformNodeForPaintOffsetTranslation = TransformPaintPropertyNode::create(
118 TransformationMatrix().translate(context.paintOffset.x(), context.paintO ffset.y()), 130 TransformationMatrix().translate(context.paintOffset.x(), context.paintO ffset.y()),
119 FloatPoint3D(), context.currentTransform); 131 FloatPoint3D(), context.currentTransform);
120 context.currentTransform = newTransformNodeForPaintOffsetTranslation.get(); 132 context.currentTransform = newTransformNodeForPaintOffsetTranslation.get();
121 context.paintOffset = LayoutPoint(); 133 context.paintOffset = LayoutPoint();
122 return newTransformNodeForPaintOffsetTranslation.release(); 134 return newTransformNodeForPaintOffsetTranslation.release();
123 } 135 }
124 136
125 static FloatPoint3D transformOrigin(const LayoutBox& box) 137 static FloatPoint3D transformOrigin(const LayoutBox& box)
126 { 138 {
127 const ComputedStyle& style = box.styleRef(); 139 const ComputedStyle& style = box.styleRef();
128 FloatSize borderBoxSize(box.size()); 140 FloatSize borderBoxSize(box.size());
129 return FloatPoint3D( 141 return FloatPoint3D(
130 floatValueForLength(style.transformOriginX(), borderBoxSize.width()), 142 floatValueForLength(style.transformOriginX(), borderBoxSize.width()),
131 floatValueForLength(style.transformOriginY(), borderBoxSize.height()), 143 floatValueForLength(style.transformOriginY(), borderBoxSize.height()),
132 style.transformOriginZ()); 144 style.transformOriginZ());
133 } 145 }
134 146
135 static PassRefPtr<TransformPaintPropertyNode> createTransformIfNeeded(const Layo utBoxModelObject& object, PaintPropertyTreeBuilderContext& context) 147 static PassRefPtr<TransformPaintPropertyNode> createTransformIfNeeded(const Layo utObject& object, PaintPropertyTreeBuilderContext& context)
136 { 148 {
149 if (object.isSVG() && !object.isSVGRoot()) {
150 const AffineTransform& transform = object.localToParentTransform();
151 if (transform.isIdentity())
152 return nullptr;
153
154 // SVG's transform origin is baked into the localToParentTransform.
155 RefPtr<TransformPaintPropertyNode> newTransformNodeForTransform = Transf ormPaintPropertyNode::create(
156 transform, FloatPoint3D(0, 0, 0), context.currentTransform);
157 context.currentTransform = newTransformNodeForTransform.get();
158 return newTransformNodeForTransform.release();
159 }
160
137 const ComputedStyle& style = object.styleRef(); 161 const ComputedStyle& style = object.styleRef();
138 if (!object.isBox() || !style.hasTransform()) 162 if (!object.isBox() || !style.hasTransform())
139 return nullptr; 163 return nullptr;
140 164
141 ASSERT(context.paintOffset == LayoutPoint()); 165 ASSERT(context.paintOffset == LayoutPoint());
142 166
143 TransformationMatrix matrix; 167 TransformationMatrix matrix;
144 style.applyTransform(matrix, toLayoutBox(object).size(), ComputedStyle::Excl udeTransformOrigin, 168 style.applyTransform(matrix, toLayoutBox(object).size(), ComputedStyle::Excl udeTransformOrigin,
145 ComputedStyle::IncludeMotionPath, ComputedStyle::IncludeIndependentTrans formProperties); 169 ComputedStyle::IncludeMotionPath, ComputedStyle::IncludeIndependentTrans formProperties);
146 RefPtr<TransformPaintPropertyNode> newTransformNodeForTransform = TransformP aintPropertyNode::create( 170 RefPtr<TransformPaintPropertyNode> newTransformNodeForTransform = TransformP aintPropertyNode::create(
147 matrix, transformOrigin(toLayoutBox(object)), context.currentTransform); 171 matrix, transformOrigin(toLayoutBox(object)), context.currentTransform);
148 context.currentTransform = newTransformNodeForTransform.get(); 172 context.currentTransform = newTransformNodeForTransform.get();
149 return newTransformNodeForTransform.release(); 173 return newTransformNodeForTransform.release();
150 } 174 }
151 175
152 static PassRefPtr<EffectPaintPropertyNode> createEffectIfNeeded(const LayoutBoxM odelObject& object, PaintPropertyTreeBuilderContext& context) 176 static PassRefPtr<EffectPaintPropertyNode> createEffectIfNeeded(const LayoutObje ct& object, PaintPropertyTreeBuilderContext& context)
153 { 177 {
154 const ComputedStyle& style = object.styleRef(); 178 const ComputedStyle& style = object.styleRef();
155 if (!object.isBox() || !style.hasOpacity()) 179 if (!style.hasOpacity())
156 return nullptr; 180 return nullptr;
157 RefPtr<EffectPaintPropertyNode> newEffectNode = EffectPaintPropertyNode::cre ate(style.opacity(), context.currentEffect); 181 RefPtr<EffectPaintPropertyNode> newEffectNode = EffectPaintPropertyNode::cre ate(style.opacity(), context.currentEffect);
158 context.currentEffect = newEffectNode.get(); 182 context.currentEffect = newEffectNode.get();
159 return newEffectNode.release(); 183 return newEffectNode.release();
160 } 184 }
161 185
162 static FloatPoint perspectiveOrigin(const LayoutBox& box) 186 static FloatPoint perspectiveOrigin(const LayoutBox& box)
163 { 187 {
164 const ComputedStyle& style = box.styleRef(); 188 const ComputedStyle& style = box.styleRef();
165 FloatSize borderBoxSize(box.size()); 189 FloatSize borderBoxSize(box.size());
166 return FloatPoint( 190 return FloatPoint(
167 floatValueForLength(style.perspectiveOriginX(), borderBoxSize.width()), 191 floatValueForLength(style.perspectiveOriginX(), borderBoxSize.width()),
168 floatValueForLength(style.perspectiveOriginY(), borderBoxSize.height())) ; 192 floatValueForLength(style.perspectiveOriginY(), borderBoxSize.height())) ;
169 } 193 }
170 194
171 static PassRefPtr<TransformPaintPropertyNode> createPerspectiveIfNeeded(const La youtBoxModelObject& object, PaintPropertyTreeBuilderContext& context) 195 static PassRefPtr<TransformPaintPropertyNode> createPerspectiveIfNeeded(const La youtObject& object, PaintPropertyTreeBuilderContext& context)
172 { 196 {
173 const ComputedStyle& style = object.styleRef(); 197 const ComputedStyle& style = object.styleRef();
174 if (!object.isBox() || !style.hasPerspective()) 198 if (!object.isBox() || !style.hasPerspective())
175 return nullptr; 199 return nullptr;
176 200
177 RefPtr<TransformPaintPropertyNode> newTransformNodeForPerspective = Transfor mPaintPropertyNode::create( 201 RefPtr<TransformPaintPropertyNode> newTransformNodeForPerspective = Transfor mPaintPropertyNode::create(
178 TransformationMatrix().applyPerspective(style.perspective()), 202 TransformationMatrix().applyPerspective(style.perspective()),
179 perspectiveOrigin(toLayoutBox(object)) + toLayoutSize(context.paintOffse t), context.currentTransform); 203 perspectiveOrigin(toLayoutBox(object)) + toLayoutSize(context.paintOffse t), context.currentTransform);
180 context.currentTransform = newTransformNodeForPerspective.get(); 204 context.currentTransform = newTransformNodeForPerspective.get();
181 return newTransformNodeForPerspective.release(); 205 return newTransformNodeForPerspective.release();
182 } 206 }
183 207
184 static PassRefPtr<TransformPaintPropertyNode> createScrollTranslationIfNeeded(co nst LayoutBoxModelObject& object, PaintPropertyTreeBuilderContext& context) 208 static PassRefPtr<TransformPaintPropertyNode> createScrollTranslationIfNeeded(co nst LayoutObject& object, PaintPropertyTreeBuilderContext& context)
185 { 209 {
186 if (!object.hasOverflowClip()) 210 if (!object.isBoxModelObject() || !object.hasOverflowClip())
187 return nullptr; 211 return nullptr;
188 212
189 PaintLayer* layer = object.layer(); 213 PaintLayer* layer = toLayoutBoxModelObject(object).layer();
190 ASSERT(layer); 214 ASSERT(layer);
191 DoubleSize scrollOffset = layer->scrollableArea()->scrollOffset(); 215 DoubleSize scrollOffset = layer->scrollableArea()->scrollOffset();
192 if (scrollOffset.isZero() && !layer->scrollsOverflow()) 216 if (scrollOffset.isZero() && !layer->scrollsOverflow())
193 return nullptr; 217 return nullptr;
194 218
195 RefPtr<TransformPaintPropertyNode> newTransformNodeForScrollTranslation = Tr ansformPaintPropertyNode::create( 219 RefPtr<TransformPaintPropertyNode> newTransformNodeForScrollTranslation = Tr ansformPaintPropertyNode::create(
196 TransformationMatrix().translate(-scrollOffset.width(), -scrollOffset.he ight()), 220 TransformationMatrix().translate(-scrollOffset.width(), -scrollOffset.he ight()),
197 FloatPoint3D(), context.currentTransform); 221 FloatPoint3D(), context.currentTransform);
198 context.currentTransform = newTransformNodeForScrollTranslation.get(); 222 context.currentTransform = newTransformNodeForScrollTranslation.get();
199 return newTransformNodeForScrollTranslation.release(); 223 return newTransformNodeForScrollTranslation.release();
200 } 224 }
201 225
202 static void updateOutOfFlowContext(const LayoutBoxModelObject& object, PaintProp ertyTreeBuilderContext& context) 226 static void updateOutOfFlowContext(const LayoutObject& object, bool createdNewTr ansform, PaintPropertyTreeBuilderContext& context)
203 { 227 {
204 const ComputedStyle& style = object.styleRef(); 228 // At the html->svg boundary (see: createPaintOffsetTranslationIfNeeded) the currentTransform is
205 bool hasTransform = object.isBox() && style.hasTransform(); 229 // up-to-date for all children of the svg root element. Additionally, inside SVG, all positioning
206 if (style.position() != StaticPosition || hasTransform) { 230 // uses transforms. Therefore, we only need to check createdNewTransform and isSVGRoot() to
231 // ensure out-of-flow and fixed positioning is correct at the svg->html boun dary.
232
233 if (object.styleRef().position() != StaticPosition || createdNewTransform || object.isSVGRoot()) {
jbroman 2015/11/23 17:51:00 Out of curiosity (arguably out of scope for this p
trchen 2015/11/23 19:28:29 I think yes. Looks like it's pretty safe to use.
207 context.transformForOutOfFlowPositioned = context.currentTransform; 234 context.transformForOutOfFlowPositioned = context.currentTransform;
208 context.paintOffsetForOutOfFlowPositioned = context.paintOffset; 235 context.paintOffsetForOutOfFlowPositioned = context.paintOffset;
209 } 236 }
210 if (hasTransform) { 237
238 if (createdNewTransform || object.isSVGRoot()) {
211 context.transformForFixedPositioned = context.currentTransform; 239 context.transformForFixedPositioned = context.currentTransform;
212 context.paintOffsetForFixedPositioned = context.paintOffset; 240 context.paintOffsetForFixedPositioned = context.paintOffset;
213 } 241 }
214 } 242 }
215 243
216 void PaintPropertyTreeBuilder::walk(LayoutBoxModelObject& object, const PaintPro pertyTreeBuilderContext& context) 244 void PaintPropertyTreeBuilder::walk(LayoutObject& object, const PaintPropertyTre eBuilderContext& context)
217 { 245 {
218 ASSERT(object.isBox() != object.isLayoutInline()); // Either or.
219
220 PaintPropertyTreeBuilderContext localContext(context); 246 PaintPropertyTreeBuilderContext localContext(context);
221 247
222 deriveBorderBoxFromContainerContext(object, localContext); 248 deriveBorderBoxFromContainerContext(object, localContext);
223 RefPtr<TransformPaintPropertyNode> newTransformNodeForPaintOffsetTranslation = createPaintOffsetTranslationIfNeeded(object, localContext); 249 RefPtr<TransformPaintPropertyNode> newTransformNodeForPaintOffsetTranslation = createPaintOffsetTranslationIfNeeded(object, localContext);
224 RefPtr<TransformPaintPropertyNode> newTransformNodeForTransform = createTran sformIfNeeded(object, localContext); 250 RefPtr<TransformPaintPropertyNode> newTransformNodeForTransform = createTran sformIfNeeded(object, localContext);
225 RefPtr<EffectPaintPropertyNode> newEffectNode = createEffectIfNeeded(object, localContext); 251 RefPtr<EffectPaintPropertyNode> newEffectNode = createEffectIfNeeded(object, localContext);
226 RefPtr<TransformPaintPropertyNode> newTransformNodeForPerspective = createPe rspectiveIfNeeded(object, localContext); 252 RefPtr<TransformPaintPropertyNode> newTransformNodeForPerspective = createPe rspectiveIfNeeded(object, localContext);
227 RefPtr<TransformPaintPropertyNode> newTransformNodeForScrollTranslation = cr eateScrollTranslationIfNeeded(object, localContext); 253 RefPtr<TransformPaintPropertyNode> newTransformNodeForScrollTranslation = cr eateScrollTranslationIfNeeded(object, localContext);
228 updateOutOfFlowContext(object, localContext); 254 updateOutOfFlowContext(object, newTransformNodeForTransform, localContext);
229 255
230 if (newTransformNodeForPaintOffsetTranslation || newTransformNodeForTransfor m || newEffectNode || newTransformNodeForPerspective || newTransformNodeForScrol lTranslation) { 256 if (newTransformNodeForPaintOffsetTranslation || newTransformNodeForTransfor m || newEffectNode || newTransformNodeForPerspective || newTransformNodeForScrol lTranslation) {
231 OwnPtr<ObjectPaintProperties> updatedPaintProperties = ObjectPaintProper ties::create( 257 OwnPtr<ObjectPaintProperties> updatedPaintProperties = ObjectPaintProper ties::create(
232 newTransformNodeForPaintOffsetTranslation.release(), 258 newTransformNodeForPaintOffsetTranslation.release(),
233 newTransformNodeForTransform.release(), 259 newTransformNodeForTransform.release(),
234 newEffectNode.release(), 260 newEffectNode.release(),
235 newTransformNodeForPerspective.release(), 261 newTransformNodeForPerspective.release(),
236 newTransformNodeForScrollTranslation.release()); 262 newTransformNodeForScrollTranslation.release());
237 object.setObjectPaintProperties(updatedPaintProperties.release()); 263 object.setObjectPaintProperties(updatedPaintProperties.release());
238 } else { 264 } else {
239 object.clearObjectPaintProperties(); 265 object.clearObjectPaintProperties();
240 } 266 }
241 267
242 // TODO(trchen): Walk subframes for LayoutFrame. 268 // TODO(trchen): Walk subframes for LayoutFrame.
243 269
244 // TODO(trchen): Implement SVG walk.
245 if (object.isSVGRoot()) {
246 return;
247 }
248
249 for (LayoutObject* child = object.slowFirstChild(); child; child = child->ne xtSibling()) { 270 for (LayoutObject* child = object.slowFirstChild(); child; child = child->ne xtSibling()) {
250 if (child->isText()) 271 if (child->isBoxModelObject() || child->isSVG())
251 continue; 272 walk(*child, localContext);
252 walk(toLayoutBoxModelObject(*child), localContext);
253 } 273 }
254 } 274 }
255 275
256 } // namespace blink 276 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698