OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2007, 2008 Rob Buis <buis@kde.org> | 2 * Copyright (C) 2007, 2008 Rob Buis <buis@kde.org> |
3 * Copyright (C) 2007 Nikolas Zimmermann <zimmermann@kde.org> | 3 * Copyright (C) 2007 Nikolas Zimmermann <zimmermann@kde.org> |
4 * Copyright (C) 2007 Eric Seidel <eric@webkit.org> | 4 * Copyright (C) 2007 Eric Seidel <eric@webkit.org> |
5 * Copyright (C) 2009 Google, Inc. All rights reserved. | 5 * Copyright (C) 2009 Google, Inc. All rights reserved. |
6 * Copyright (C) 2009 Dirk Schulze <krit@webkit.org> | 6 * Copyright (C) 2009 Dirk Schulze <krit@webkit.org> |
7 * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved. | 7 * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved. |
8 * | 8 * |
9 * This library is free software; you can redistribute it and/or | 9 * This library is free software; you can redistribute it and/or |
10 * modify it under the terms of the GNU Library General Public | 10 * modify it under the terms of the GNU Library General Public |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
150 const RenderSVGRoot* SVGRenderSupport::findTreeRootObject(const RenderObject* st
art) | 150 const RenderSVGRoot* SVGRenderSupport::findTreeRootObject(const RenderObject* st
art) |
151 { | 151 { |
152 while (start && !start->isSVGRoot()) | 152 while (start && !start->isSVGRoot()) |
153 start = start->parent(); | 153 start = start->parent(); |
154 | 154 |
155 ASSERT(start); | 155 ASSERT(start); |
156 ASSERT(start->isSVGRoot()); | 156 ASSERT(start->isSVGRoot()); |
157 return toRenderSVGRoot(start); | 157 return toRenderSVGRoot(start); |
158 } | 158 } |
159 | 159 |
160 inline void SVGRenderSupport::invalidateResourcesOfChildren(RenderObject* start) | |
161 { | |
162 ASSERT(!start->needsLayout()); | |
163 if (SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObj
ect(start)) | |
164 resources->removeClientFromCache(start, false); | |
165 | |
166 for (RenderObject* child = start->slowFirstChild(); child; child = child->ne
xtSibling()) | |
167 invalidateResourcesOfChildren(child); | |
168 } | |
169 | |
170 inline bool SVGRenderSupport::layoutSizeOfNearestViewportChanged(const RenderObj
ect* start) | 160 inline bool SVGRenderSupport::layoutSizeOfNearestViewportChanged(const RenderObj
ect* start) |
171 { | 161 { |
172 while (start && !start->isSVGRoot() && !start->isSVGViewportContainer()) | 162 while (start && !start->isSVGRoot() && !start->isSVGViewportContainer()) |
173 start = start->parent(); | 163 start = start->parent(); |
174 | 164 |
175 ASSERT(start); | 165 ASSERT(start); |
176 ASSERT(start->isSVGRoot() || start->isSVGViewportContainer()); | 166 ASSERT(start->isSVGRoot() || start->isSVGViewportContainer()); |
177 if (start->isSVGViewportContainer()) | 167 if (start->isSVGViewportContainer()) |
178 return toRenderSVGViewportContainer(start)->isLayoutSizeChanged(); | 168 return toRenderSVGViewportContainer(start)->isLayoutSizeChanged(); |
179 | 169 |
180 return toRenderSVGRoot(start)->isLayoutSizeChanged(); | 170 return toRenderSVGRoot(start)->isLayoutSizeChanged(); |
181 } | 171 } |
182 | 172 |
183 bool SVGRenderSupport::transformToRootChanged(RenderObject* ancestor) | 173 bool SVGRenderSupport::transformToRootChanged(RenderObject* ancestor) |
184 { | 174 { |
185 while (ancestor && !ancestor->isSVGRoot()) { | 175 while (ancestor && !ancestor->isSVGRoot()) { |
186 if (ancestor->isSVGTransformableContainer()) | 176 if (ancestor->isSVGTransformableContainer()) |
187 return toRenderSVGContainer(ancestor)->didTransformToRootUpdate(); | 177 return toRenderSVGContainer(ancestor)->didTransformToRootUpdate(); |
188 if (ancestor->isSVGViewportContainer()) | 178 if (ancestor->isSVGViewportContainer()) |
189 return toRenderSVGViewportContainer(ancestor)->didTransformToRootUpd
ate(); | 179 return toRenderSVGViewportContainer(ancestor)->didTransformToRootUpd
ate(); |
190 ancestor = ancestor->parent(); | 180 ancestor = ancestor->parent(); |
191 } | 181 } |
192 | 182 |
193 return false; | 183 return false; |
194 } | 184 } |
195 | 185 |
196 void SVGRenderSupport::layoutChildren(RenderObject* start, bool selfNeedsLayout) | 186 void SVGRenderSupport::layoutChildren(RenderObject* start, bool selfNeedsLayout) |
197 { | 187 { |
198 bool layoutSizeChanged = layoutSizeOfNearestViewportChanged(start); | 188 // When hasRelativeLengths() is false, no descendants have relative lengths |
| 189 // (hence no one is interested in viewport size changes). |
| 190 bool layoutSizeChanged = toSVGElement(start->node())->hasRelativeLengths() |
| 191 && layoutSizeOfNearestViewportChanged(start); |
199 bool transformChanged = transformToRootChanged(start); | 192 bool transformChanged = transformToRootChanged(start); |
200 HashSet<RenderObject*> notlayoutedObjects; | |
201 | 193 |
202 for (RenderObject* child = start->slowFirstChild(); child; child = child->ne
xtSibling()) { | 194 for (RenderObject* child = start->slowFirstChild(); child; child = child->ne
xtSibling()) { |
203 bool needsLayout = selfNeedsLayout; | 195 bool forceLayout = selfNeedsLayout; |
204 | 196 |
205 if (transformChanged) { | 197 if (transformChanged) { |
206 // If the transform changed we need to update the text metrics (note
: this also happens for layoutSizeChanged=true). | 198 // If the transform changed we need to update the text metrics (note
: this also happens for layoutSizeChanged=true). |
207 if (child->isSVGText()) | 199 if (child->isSVGText()) |
208 toRenderSVGText(child)->setNeedsTextMetricsUpdate(); | 200 toRenderSVGText(child)->setNeedsTextMetricsUpdate(); |
209 needsLayout = true; | 201 forceLayout = true; |
210 } | 202 } |
211 | 203 |
212 if (layoutSizeChanged) { | 204 if (layoutSizeChanged) { |
213 // When selfNeedsLayout is false and the layout size changed, we hav
e to check whether this child uses relative lengths | 205 // When selfNeedsLayout is false and the layout size changed, we hav
e to check whether this child uses relative lengths |
214 if (SVGElement* element = child->node()->isSVGElement() ? toSVGEleme
nt(child->node()) : 0) { | 206 if (SVGElement* element = child->node()->isSVGElement() ? toSVGEleme
nt(child->node()) : 0) { |
215 if (element->hasRelativeLengths()) { | 207 if (element->hasRelativeLengths()) { |
| 208 // FIXME: this should be done on invalidation, not during la
yout. |
216 // When the layout size changed and when using relative valu
es tell the RenderSVGShape to update its shape object | 209 // When the layout size changed and when using relative valu
es tell the RenderSVGShape to update its shape object |
217 if (child->isSVGShape()) { | 210 if (child->isSVGShape()) { |
218 toRenderSVGShape(child)->setNeedsShapeUpdate(); | 211 toRenderSVGShape(child)->setNeedsShapeUpdate(); |
219 } else if (child->isSVGText()) { | 212 } else if (child->isSVGText()) { |
220 toRenderSVGText(child)->setNeedsTextMetricsUpdate(); | 213 toRenderSVGText(child)->setNeedsTextMetricsUpdate(); |
221 toRenderSVGText(child)->setNeedsPositioningValuesUpdate(
); | 214 toRenderSVGText(child)->setNeedsPositioningValuesUpdate(
); |
222 } | 215 } |
223 | 216 |
224 needsLayout = true; | 217 forceLayout = true; |
225 } | 218 } |
226 } | 219 } |
227 } | 220 } |
228 | 221 |
229 SubtreeLayoutScope layoutScope(*child); | 222 SubtreeLayoutScope layoutScope(*child); |
230 // Resource containers are nasty: they can invalidate clients outside th
e current SubtreeLayoutScope. | 223 // Resource containers are nasty: they can invalidate clients outside th
e current SubtreeLayoutScope. |
231 // Since they only care about viewport size changes (to resolve their re
lative lengths), we trigger | 224 // Since they only care about viewport size changes (to resolve their re
lative lengths), we trigger |
232 // their invalidation directly from SVGSVGElement::svgAttributeChange()
or at a higher | 225 // their invalidation directly from SVGSVGElement::svgAttributeChange()
or at a higher |
233 // SubtreeLayoutScope (in RenderView::layout()). | 226 // SubtreeLayoutScope (in RenderView::layout()). |
234 if (needsLayout && !child->isSVGResourceContainer()) | 227 if (forceLayout && !child->isSVGResourceContainer()) |
235 layoutScope.setNeedsLayout(child); | 228 layoutScope.setNeedsLayout(child); |
236 | 229 |
| 230 // Lay out any referenced resources before the child. |
237 layoutResourcesIfNeeded(child); | 231 layoutResourcesIfNeeded(child); |
238 | 232 child->layoutIfNeeded(); |
239 if (child->needsLayout()) { | |
240 child->layout(); | |
241 } else if (layoutSizeChanged) { | |
242 notlayoutedObjects.add(child); | |
243 } | |
244 } | 233 } |
245 | |
246 if (!layoutSizeChanged) { | |
247 ASSERT(notlayoutedObjects.isEmpty()); | |
248 return; | |
249 } | |
250 | |
251 // If the layout size changed, invalidate all resources of all children that
didn't go through the layout() code path. | |
252 HashSet<RenderObject*>::iterator end = notlayoutedObjects.end(); | |
253 for (HashSet<RenderObject*>::iterator it = notlayoutedObjects.begin(); it !=
end; ++it) | |
254 invalidateResourcesOfChildren(*it); | |
255 } | 234 } |
256 | 235 |
257 void SVGRenderSupport::layoutResourcesIfNeeded(const RenderObject* object) | 236 void SVGRenderSupport::layoutResourcesIfNeeded(const RenderObject* object) |
258 { | 237 { |
259 ASSERT(object); | 238 ASSERT(object); |
260 | 239 |
261 SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(
object); | 240 SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(
object); |
262 if (resources) | 241 if (resources) |
263 resources->layoutIfNeeded(); | 242 resources->layoutIfNeeded(); |
264 } | 243 } |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
385 } | 364 } |
386 | 365 |
387 bool SVGRenderSupport::isRenderableTextNode(const RenderObject* object) | 366 bool SVGRenderSupport::isRenderableTextNode(const RenderObject* object) |
388 { | 367 { |
389 ASSERT(object->isText()); | 368 ASSERT(object->isText()); |
390 // <br> is marked as text, but is not handled by the SVG rendering code-path
. | 369 // <br> is marked as text, but is not handled by the SVG rendering code-path
. |
391 return object->isSVGInlineText() && !toRenderSVGInlineText(object)->hasEmpty
Text(); | 370 return object->isSVGInlineText() && !toRenderSVGInlineText(object)->hasEmpty
Text(); |
392 } | 371 } |
393 | 372 |
394 } | 373 } |
OLD | NEW |