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