Changeset 117225 in webkit
- Timestamp:
- May 16, 2012 12:21:07 AM (12 years ago)
- Location:
- trunk
- Files:
-
- 6 added
- 17 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r117224 r117225 1 2012-05-16 Nikolas Zimmermann <nzimmermann@rim.com> 2 3 REGRESSION(r105057): Infinite loop inside SVGTextLayoutEngine::currentLogicalCharacterMetrics 4 https://bugs.webkit.org/show_bug.cgi?id=83405 5 6 Reviewed by Darin Adler. 7 8 Add three new testcases covering the problem. 9 10 * svg/text/add-tspan-position-bug-expected.html: Added. 11 * svg/text/add-tspan-position-bug.html: Added. 12 * svg/text/highcharts-assertion-expected.txt: Added. 13 * svg/text/highcharts-assertion.html: Added. 14 * svg/text/modify-tspan-position-bug-expected.html: Added. 15 * svg/text/modify-tspan-position-bug.html: Added. 16 1 17 2012-05-15 Abhishek Arya <inferno@chromium.org> 2 18 -
trunk/Source/WebCore/ChangeLog
r117224 r117225 1 2012-05-16 Nikolas Zimmermann <nzimmermann@rim.com> 2 3 REGRESSION(r105057): Infinite loop inside SVGTextLayoutEngine::currentLogicalCharacterMetrics 4 https://bugs.webkit.org/show_bug.cgi?id=83405 5 6 Reviewed by Darin Adler. 7 8 Dynamically adding tspans carrying position information in the x/y/dx/dy/rotate lists is broken. 9 To avoid mistakes like this in future, simplify the calling code in RenderSVGInlineText and centralize 10 the management of all caches (text positioning element cache / metrics map / layout attributes) in 11 RenderSVGText. This avoids the hack in SVGRootInlineBox::computePerCharacterLayoutInformation() which 12 called textRoot->rebuildLayoutAttributes(), which was used to fix previous security issues with this code. 13 Instead correctly handle destruction of RenderSVGInlineText in RenderSVGText, keeping the m_layoutAttributes 14 synchronized with the current state of the render tree. Fixes highcharts problems. 15 16 Tests: svg/text/add-tspan-position-bug.html 17 svg/text/highcharts-assertion.html 18 svg/text/modify-tspan-position-bug.html 19 20 * rendering/svg/RenderSVGBlock.h: 21 (RenderSVGBlock): 22 * rendering/svg/RenderSVGInline.cpp: 23 (WebCore::RenderSVGInline::addChild): 24 (WebCore::RenderSVGInline::removeChild): 25 * rendering/svg/RenderSVGInline.h: 26 (RenderSVGInline): 27 * rendering/svg/RenderSVGInlineText.cpp: 28 (WebCore::RenderSVGInlineText::setTextInternal): 29 (WebCore::RenderSVGInlineText::styleDidChange): 30 * rendering/svg/RenderSVGInlineText.h: 31 * rendering/svg/RenderSVGText.cpp: 32 (WebCore::RenderSVGText::RenderSVGText): 33 (WebCore::RenderSVGText::~RenderSVGText): 34 (WebCore::collectLayoutAttributes): 35 (WebCore::RenderSVGText::subtreeChildWasAdded): 36 (WebCore::findPreviousAndNextAttributes): 37 (WebCore::checkLayoutAttributesConsistency): 38 (WebCore::RenderSVGText::willBeDestroyed): 39 (WebCore::RenderSVGText::subtreeChildWillBeRemoved): 40 (WebCore::RenderSVGText::subtreeChildWasRemoved): 41 (WebCore::RenderSVGText::subtreeStyleDidChange): 42 (WebCore::RenderSVGText::subtreeTextDidChange): 43 (WebCore::updateFontInAllDescendants): 44 (WebCore::RenderSVGText::layout): 45 (WebCore::RenderSVGText::addChild): 46 (WebCore::RenderSVGText::removeChild): 47 * rendering/svg/RenderSVGText.h: 48 (RenderSVGText): 49 * rendering/svg/SVGRenderSupport.cpp: 50 (WebCore::SVGRenderSupport::layoutChildren): 51 * rendering/svg/SVGRootInlineBox.cpp: 52 (WebCore::SVGRootInlineBox::computePerCharacterLayoutInformation): 53 * rendering/svg/SVGTextLayoutAttributesBuilder.cpp: 54 (WebCore::SVGTextLayoutAttributesBuilder::buildLayoutAttributesForTextRenderer): 55 (WebCore::SVGTextLayoutAttributesBuilder::buildLayoutAttributesForWholeTree): 56 (WebCore::SVGTextLayoutAttributesBuilder::rebuildMetricsForTextRenderer): 57 (WebCore::SVGTextLayoutAttributesBuilder::buildCharacterDataMap): 58 * rendering/svg/SVGTextLayoutAttributesBuilder.h: 59 (SVGTextLayoutAttributesBuilder): 60 (WebCore::SVGTextLayoutAttributesBuilder::numberOfTextPositioningElements): 61 * svg/SVGAElement.cpp: 62 * svg/SVGAElement.h: 63 (SVGAElement): 64 * svg/SVGTextContentElement.cpp: 65 * svg/SVGTextContentElement.h: 66 (SVGTextContentElement): 67 1 68 2012-05-15 Abhishek Arya <inferno@chromium.org> 2 69 -
trunk/Source/WebCore/rendering/svg/RenderSVGBlock.h
r110224 r117225 35 35 virtual LayoutRect visualOverflowRect() const; 36 36 37 protected: 38 virtual void willBeDestroyed() OVERRIDE; 39 37 40 private: 38 41 virtual void setStyle(PassRefPtr<RenderStyle>); … … 41 44 virtual void absoluteRects(Vector<IntRect>&, const LayoutPoint& accumulatedOffset) const; 42 45 43 virtual void willBeDestroyed();44 46 virtual void styleWillChange(StyleDifference, const RenderStyle* newStyle); 45 47 virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle); -
trunk/Source/WebCore/rendering/svg/RenderSVGInline.cpp
r116801 r117225 125 125 RenderInline::addChild(child, beforeChild); 126 126 if (RenderSVGText* textRenderer = RenderSVGText::locateRenderSVGTextAncestor(this)) 127 textRenderer->layoutAttributesChanged(child); 127 textRenderer->subtreeChildWasAdded(child); 128 } 129 130 void RenderSVGInline::removeChild(RenderObject* child) 131 { 132 RenderSVGText* textRenderer = child->isSVGInlineText() ? RenderSVGText::locateRenderSVGTextAncestor(this) : 0; 133 if (!textRenderer) { 134 RenderInline::removeChild(child); 135 return; 136 } 137 138 RenderSVGInlineText* text = toRenderSVGInlineText(child); 139 Vector<SVGTextLayoutAttributes*, 2> affectedAttributes; 140 textRenderer->subtreeChildWillBeRemoved(text, affectedAttributes); 141 RenderInline::removeChild(child); 142 textRenderer->subtreeChildWasRemoved(affectedAttributes); 128 143 } 129 144 -
trunk/Source/WebCore/rendering/svg/RenderSVGInline.h
r115981 r117225 58 58 virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle); 59 59 virtual void updateFromElement(); 60 60 61 virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0); 62 virtual void removeChild(RenderObject*) OVERRIDE; 61 63 }; 62 64 -
trunk/Source/WebCore/rendering/svg/RenderSVGInlineText.cpp
r116801 r117225 73 73 } 74 74 75 void RenderSVGInlineText::willBeDestroyed()76 {77 RenderSVGText* textRenderer = RenderSVGText::locateRenderSVGTextAncestor(this);78 if (!textRenderer) {79 RenderText::willBeDestroyed();80 return;81 }82 83 Vector<SVGTextLayoutAttributes*> affectedAttributes;84 textRenderer->layoutAttributesWillBeDestroyed(this, affectedAttributes);85 86 RenderText::willBeDestroyed();87 if (affectedAttributes.isEmpty())88 return;89 90 if (!documentBeingDestroyed())91 textRenderer->rebuildLayoutAttributes(affectedAttributes);92 }93 94 75 void RenderSVGInlineText::setTextInternal(PassRefPtr<StringImpl> text) 95 76 { 96 77 RenderText::setTextInternal(text); 97 98 // When the underlying text content changes, call both textDOMChanged() & layoutAttributesChanged() 99 // The former will clear the SVGTextPositioningElement cache, which depends on the textLength() of 100 // the RenderSVGInlineText objects, and thus needs to be rebuild. The latter will assure that the 101 // SVGTextLayoutAttributes associated with the RenderSVGInlineText will be updated. 102 if (RenderSVGText* textRenderer = RenderSVGText::locateRenderSVGTextAncestor(this)) { 103 textRenderer->invalidateTextPositioningElements(); 104 textRenderer->layoutAttributesChanged(this); 105 } 78 if (RenderSVGText* textRenderer = RenderSVGText::locateRenderSVGTextAncestor(this)) 79 textRenderer->subtreeTextDidChange(this); 106 80 } 107 81 … … 128 102 // The text metrics may be influenced by style changes. 129 103 if (RenderSVGText* textRenderer = RenderSVGText::locateRenderSVGTextAncestor(this)) 130 textRenderer-> layoutAttributesChanged(this);104 textRenderer->subtreeStyleDidChange(this); 131 105 } 132 106 -
trunk/Source/WebCore/rendering/svg/RenderSVGInlineText.h
r112237 r117225 49 49 virtual const char* renderName() const { return "RenderSVGInlineText"; } 50 50 51 virtual void willBeDestroyed();52 51 virtual void setTextInternal(PassRefPtr<StringImpl>); 53 52 virtual void styleDidChange(StyleDifference, const RenderStyle*); -
trunk/Source/WebCore/rendering/svg/RenderSVGText.cpp
r116801 r117225 58 58 : RenderSVGBlock(node) 59 59 , m_needsReordering(false) 60 , m_needsPositioningValuesUpdate( true)60 , m_needsPositioningValuesUpdate(false) 61 61 , m_needsTransformUpdate(true) 62 , m_needsTextMetricsUpdate(true) 63 { 62 , m_needsTextMetricsUpdate(false) 63 { 64 } 65 66 RenderSVGText::~RenderSVGText() 67 { 68 ASSERT(m_layoutAttributes.isEmpty()); 64 69 } 65 70 … … 111 116 } 112 117 113 static inline void recursiveUpdateLayoutAttributes(RenderObject* start, SVGTextLayoutAttributesBuilder& builder) 114 { 115 if (start->isSVGInlineText()) { 116 builder.buildLayoutAttributesForTextRenderer(toRenderSVGInlineText(start)); 117 return; 118 } 119 120 for (RenderObject* child = start->firstChild(); child; child = child->nextSibling()) 121 recursiveUpdateLayoutAttributes(child, builder); 122 } 123 124 void RenderSVGText::layoutAttributesChanged(RenderObject* child) 125 { 126 ASSERT(child); 127 if (m_needsPositioningValuesUpdate) 128 return; 129 FontCachePurgePreventer fontCachePurgePreventer; 130 recursiveUpdateLayoutAttributes(child, m_layoutAttributesBuilder); 131 rebuildLayoutAttributes(); 118 static inline void collectLayoutAttributes(RenderObject* text, Vector<SVGTextLayoutAttributes*>& attributes) 119 { 120 for (RenderObject* descendant = text; descendant; descendant = descendant->nextInPreOrder(text)) { 121 if (descendant->isSVGInlineText()) 122 attributes.append(toRenderSVGInlineText(descendant)->layoutAttributes()); 123 } 132 124 } 133 125 … … 136 128 ASSERT(start); 137 129 ASSERT(locateElement); 130 // FIXME: Make this iterative. 138 131 for (RenderObject* child = start->firstChild(); child; child = child->nextSibling()) { 139 132 if (child->isSVGInlineText()) { … … 163 156 } 164 157 165 void RenderSVGText::layoutAttributesWillBeDestroyed(RenderSVGInlineText* text, Vector<SVGTextLayoutAttributes*>& affectedAttributes) 158 inline bool RenderSVGText::shouldHandleSubtreeMutations() const 159 { 160 if (beingDestroyed() || !everHadLayout()) { 161 ASSERT(m_layoutAttributes.isEmpty()); 162 ASSERT(!m_layoutAttributesBuilder.numberOfTextPositioningElements()); 163 return false; 164 } 165 return true; 166 } 167 168 void RenderSVGText::subtreeChildWasAdded(RenderObject* child) 169 { 170 ASSERT(child); 171 if (!shouldHandleSubtreeMutations() || documentBeingDestroyed()) 172 return; 173 174 // The positioning elements cache doesn't include the new 'child' yet. Clear the 175 // cache, as the next buildLayoutAttributesForTextRenderer() call rebuilds it. 176 m_layoutAttributesBuilder.clearTextPositioningElements(); 177 178 // Detect changes in layout attributes and only measure those text parts that have changed! 179 Vector<SVGTextLayoutAttributes*> newLayoutAttributes; 180 collectLayoutAttributes(this, newLayoutAttributes); 181 if (newLayoutAttributes.isEmpty()) { 182 ASSERT(m_layoutAttributes.isEmpty()); 183 return; 184 } 185 186 // Compare m_layoutAttributes with newLayoutAttributes to figure out which attribute got added. 187 size_t size = newLayoutAttributes.size(); 188 SVGTextLayoutAttributes* attributes = 0; 189 for (size_t i = 0; i < size; ++i) { 190 attributes = newLayoutAttributes[i]; 191 if (m_layoutAttributes.find(attributes) == notFound) { 192 // Every time this is invoked, there's only a single new entry in the newLayoutAttributes list, compared to the old in m_layoutAttributes. 193 bool stopAfterNext = false; 194 SVGTextLayoutAttributes* previous = 0; 195 SVGTextLayoutAttributes* next = 0; 196 ASSERT_UNUSED(child, attributes->context() == child); 197 findPreviousAndNextAttributes(this, attributes->context(), stopAfterNext, previous, next); 198 199 if (previous) 200 m_layoutAttributesBuilder.buildLayoutAttributesForTextRenderer(previous->context()); 201 m_layoutAttributesBuilder.buildLayoutAttributesForTextRenderer(attributes->context()); 202 if (next) 203 m_layoutAttributesBuilder.buildLayoutAttributesForTextRenderer(next->context()); 204 break; 205 } 206 } 207 208 #ifndef NDEBUG 209 // Verify that m_layoutAttributes only differs by a maximum of one entry. 210 for (size_t i = 0; i < size; ++i) 211 ASSERT(m_layoutAttributes.find(newLayoutAttributes[i]) != notFound || newLayoutAttributes[i] == attributes); 212 #endif 213 214 m_layoutAttributes = newLayoutAttributes; 215 } 216 217 static inline void checkLayoutAttributesConsistency(RenderSVGText* text, Vector<SVGTextLayoutAttributes*>& expectedLayoutAttributes) 218 { 219 #ifndef NDEBUG 220 Vector<SVGTextLayoutAttributes*> newLayoutAttributes; 221 collectLayoutAttributes(text, newLayoutAttributes); 222 ASSERT(newLayoutAttributes == expectedLayoutAttributes); 223 #else 224 UNUSED_PARAM(text); 225 UNUSED_PARAM(expectedLayoutAttributes); 226 #endif 227 } 228 229 void RenderSVGText::willBeDestroyed() 230 { 231 m_layoutAttributes.clear(); 232 m_layoutAttributesBuilder.clearTextPositioningElements(); 233 234 RenderSVGBlock::willBeDestroyed(); 235 } 236 237 void RenderSVGText::subtreeChildWillBeRemoved(RenderSVGInlineText* text, Vector<SVGTextLayoutAttributes*, 2>& affectedAttributes) 166 238 { 167 239 ASSERT(text); 168 if (m_needsPositioningValuesUpdate) 169 return; 170 240 if (!shouldHandleSubtreeMutations()) 241 return; 242 243 checkLayoutAttributesConsistency(this, m_layoutAttributes); 244 245 // The positioning elements cache depends on the size of each text renderer in the 246 // subtree. If this changes, clear the cache. It's going to be rebuilt below. 247 m_layoutAttributesBuilder.clearTextPositioningElements(); 248 if (m_layoutAttributes.isEmpty()) 249 return; 250 251 // This logic requires that the 'text' child is still inserted in the tree. 171 252 bool stopAfterNext = false; 172 253 SVGTextLayoutAttributes* previous = 0; 173 254 SVGTextLayoutAttributes* next = 0; 174 findPreviousAndNextAttributes(this, text, stopAfterNext, previous, next); 255 if (!documentBeingDestroyed()) 256 findPreviousAndNextAttributes(this, text, stopAfterNext, previous, next); 257 175 258 if (previous) 176 259 affectedAttributes.append(previous); 177 260 if (next) 178 261 affectedAttributes.append(next); 179 } 180 181 void RenderSVGText::invalidateTextPositioningElements() 182 { 183 // Clear the text positioning elements. This should be called when either the children 184 // of a DOM text element have changed, or the length of the text in any child element 185 // has changed. Failure to clear may leave us with invalid elements, as other code paths 186 // do not always cause the position elements to be marked invalid before use. 262 263 size_t position = m_layoutAttributes.find(text->layoutAttributes()); 264 ASSERT(position != notFound); 265 m_layoutAttributes.remove(position); 266 } 267 268 void RenderSVGText::subtreeChildWasRemoved(const Vector<SVGTextLayoutAttributes*, 2>& affectedAttributes) 269 { 270 if (!shouldHandleSubtreeMutations() || documentBeingDestroyed()) { 271 ASSERT(affectedAttributes.isEmpty()); 272 return; 273 } 274 275 // This is called immediately after subtreeChildWillBeDestroyed, once the RenderSVGInlineText::willBeDestroyed() method 276 // passes on to the base class, which removes us from the render tree. At this point we can update the layout attributes. 277 unsigned size = affectedAttributes.size(); 278 for (unsigned i = 0; i < size; ++i) 279 m_layoutAttributesBuilder.buildLayoutAttributesForTextRenderer(affectedAttributes[i]->context()); 280 } 281 282 void RenderSVGText::subtreeStyleDidChange(RenderSVGInlineText* text) 283 { 284 ASSERT(text); 285 if (!shouldHandleSubtreeMutations() || documentBeingDestroyed()) 286 return; 287 288 checkLayoutAttributesConsistency(this, m_layoutAttributes); 289 290 // Only update the metrics cache, but not the text positioning element cache 291 // nor the layout attributes cached in the leaf #text renderers. 292 FontCachePurgePreventer fontCachePurgePreventer; 293 for (RenderObject* descendant = text; descendant; descendant = descendant->nextInPreOrder(text)) { 294 if (descendant->isSVGInlineText()) 295 m_layoutAttributesBuilder.rebuildMetricsForTextRenderer(toRenderSVGInlineText(descendant)); 296 } 297 } 298 299 void RenderSVGText::subtreeTextDidChange(RenderSVGInlineText* text) 300 { 301 ASSERT(text); 302 ASSERT(!beingDestroyed()); 303 if (!everHadLayout()) { 304 ASSERT(m_layoutAttributes.isEmpty()); 305 ASSERT(!m_layoutAttributesBuilder.numberOfTextPositioningElements()); 306 return; 307 } 308 309 // The positioning elements cache depends on the size of each text renderer in the 310 // subtree. If this changes, clear the cache. It's going to be rebuilt below. 187 311 m_layoutAttributesBuilder.clearTextPositioningElements(); 188 } 189 190 static inline void recursiveUpdateScaledFont(RenderObject* start) 191 { 192 for (RenderObject* child = start->firstChild(); child; child = child->nextSibling()) { 193 if (child->isSVGInlineText()) { 194 toRenderSVGInlineText(child)->updateScaledFont(); 312 313 checkLayoutAttributesConsistency(this, m_layoutAttributes); 314 for (RenderObject* descendant = text; descendant; descendant = descendant->nextInPreOrder(text)) { 315 if (descendant->isSVGInlineText()) 316 m_layoutAttributesBuilder.buildLayoutAttributesForTextRenderer(toRenderSVGInlineText(descendant)); 317 } 318 } 319 320 static inline void updateFontInAllDescendants(RenderObject* start, SVGTextLayoutAttributesBuilder* builder = 0) 321 { 322 for (RenderObject* descendant = start; descendant; descendant = descendant->nextInPreOrder(start)) { 323 if (!descendant->isSVGInlineText()) 195 324 continue; 196 } 197 198 recursiveUpdateScaledFont(child); 325 RenderSVGInlineText* text = toRenderSVGInlineText(descendant); 326 text->updateScaledFont(); 327 if (builder) 328 builder->rebuildMetricsForTextRenderer(text); 199 329 } 200 330 } … … 213 343 } 214 344 215 // If the root layout size changed (eg. window size changes) or the positioning values change 216 // or the transform to the root context has changed then recompute the on-screen font size. 217 if (m_needsTextMetricsUpdate || SVGRenderSupport::findTreeRootObject(this)->isLayoutSizeChanged()) { 218 recursiveUpdateScaledFont(this); 219 rebuildLayoutAttributes(true); 345 if (!everHadLayout()) { 346 // When laying out initially, collect all layout attributes, build the character data map, 347 // and propogate resulting SVGLayoutAttributes to all RenderSVGInlineText children in the subtree. 348 ASSERT(m_layoutAttributes.isEmpty()); 349 collectLayoutAttributes(this, m_layoutAttributes); 350 updateFontInAllDescendants(this); 351 m_layoutAttributesBuilder.buildLayoutAttributesForForSubtree(this); 352 353 m_needsReordering = true; 354 m_needsTextMetricsUpdate = false; 355 m_needsPositioningValuesUpdate = false; 220 356 updateCachedBoundariesInParents = true; 221 m_needsTextMetricsUpdate = false; 222 } 223 224 if (m_needsPositioningValuesUpdate) { 225 // Perform SVG text layout phase one (see SVGTextLayoutAttributesBuilder for details). 226 m_layoutAttributesBuilder.buildLayoutAttributesForWholeTree(this); 357 } else if (m_needsPositioningValuesUpdate) { 358 // When the x/y/dx/dy/rotate lists change, recompute the layout attributes, and eventually 359 // update the on-screen font objects as well in all descendants. 360 if (m_needsTextMetricsUpdate) { 361 updateFontInAllDescendants(this); 362 m_needsTextMetricsUpdate = false; 363 } 364 365 m_layoutAttributesBuilder.buildLayoutAttributesForForSubtree(this); 227 366 m_needsReordering = true; 228 367 m_needsPositioningValuesUpdate = false; 229 368 updateCachedBoundariesInParents = true; 230 } 369 } else if (m_needsTextMetricsUpdate || SVGRenderSupport::findTreeRootObject(this)->isLayoutSizeChanged()) { 370 // If the root layout size changed (eg. window size changes) or the transform to the root 371 // context has changed then recompute the on-screen font size. 372 updateFontInAllDescendants(this, &m_layoutAttributesBuilder); 373 374 ASSERT(!m_needsReordering); 375 ASSERT(!m_needsPositioningValuesUpdate); 376 m_needsTextMetricsUpdate = false; 377 updateCachedBoundariesInParents = true; 378 } 379 380 checkLayoutAttributesConsistency(this, m_layoutAttributes); 231 381 232 382 // Reduced version of RenderBlock::layoutBlock(), which only takes care of SVG text. … … 365 515 { 366 516 RenderSVGBlock::addChild(child, beforeChild); 367 layoutAttributesChanged(child); 517 subtreeChildWasAdded(child); 518 } 519 520 void RenderSVGText::removeChild(RenderObject* child) 521 { 522 if (!child->isSVGInlineText()) { 523 RenderSVGBlock::removeChild(child); 524 return; 525 } 526 527 RenderSVGInlineText* text = toRenderSVGInlineText(child); 528 Vector<SVGTextLayoutAttributes*, 2> affectedAttributes; 529 subtreeChildWillBeRemoved(text, affectedAttributes); 530 RenderSVGBlock::removeChild(child); 531 subtreeChildWasRemoved(affectedAttributes); 368 532 } 369 533 … … 381 545 } 382 546 383 static inline void recursiveCollectLayoutAttributes(RenderObject* start, Vector<SVGTextLayoutAttributes*>& attributes)384 {385 for (RenderObject* child = start->firstChild(); child; child = child->nextSibling()) {386 if (child->isSVGInlineText()) {387 attributes.append(toRenderSVGInlineText(child)->layoutAttributes());388 continue;389 }390 391 recursiveCollectLayoutAttributes(child, attributes);392 }393 }394 395 void RenderSVGText::rebuildLayoutAttributes(bool performFullRebuild)396 {397 if (performFullRebuild)398 m_layoutAttributes.clear();399 400 if (m_layoutAttributes.isEmpty()) {401 recursiveCollectLayoutAttributes(this, m_layoutAttributes);402 if (m_layoutAttributes.isEmpty() || !performFullRebuild)403 return;404 405 m_layoutAttributesBuilder.rebuildMetricsForWholeTree(this);406 return;407 }408 409 Vector<SVGTextLayoutAttributes*> affectedAttributes;410 rebuildLayoutAttributes(affectedAttributes);411 }412 413 void RenderSVGText::rebuildLayoutAttributes(Vector<SVGTextLayoutAttributes*>& affectedAttributes)414 {415 // Detect changes in layout attributes and only measure those text parts that have changed!416 Vector<SVGTextLayoutAttributes*> newLayoutAttributes;417 recursiveCollectLayoutAttributes(this, newLayoutAttributes);418 if (newLayoutAttributes.isEmpty()) {419 m_layoutAttributes.clear();420 return;421 }422 423 // Compare m_layoutAttributes with newLayoutAttributes to figure out which attributes got added/removed.424 size_t size = newLayoutAttributes.size();425 for (size_t i = 0; i < size; ++i) {426 SVGTextLayoutAttributes* attributes = newLayoutAttributes[i];427 if (m_layoutAttributes.find(attributes) == notFound)428 m_layoutAttributesBuilder.rebuildMetricsForTextRenderer(attributes->context());429 }430 431 size = affectedAttributes.size();432 for (size_t i = 0; i < size; ++i)433 m_layoutAttributesBuilder.rebuildMetricsForTextRenderer(affectedAttributes[i]->context());434 435 m_layoutAttributes = newLayoutAttributes;436 }437 438 547 } 439 548 -
trunk/Source/WebCore/rendering/svg/RenderSVGText.h
r116801 r117225 37 37 public: 38 38 RenderSVGText(SVGTextElement*); 39 virtual ~RenderSVGText(); 39 40 40 41 virtual bool isChildAllowed(RenderObject*, RenderStyle*) const; … … 49 50 50 51 bool needsReordering() const { return m_needsReordering; } 52 Vector<SVGTextLayoutAttributes*>& layoutAttributes() { return m_layoutAttributes; } 51 53 52 // Call this method when either the children of a DOM text element have changed, or the length of 53 // the text in any child element has changed. 54 void invalidateTextPositioningElements(); 55 56 void layoutAttributesChanged(RenderObject*); 57 void layoutAttributesWillBeDestroyed(RenderSVGInlineText*, Vector<SVGTextLayoutAttributes*>& affectedAttributes); 58 void rebuildLayoutAttributes(bool performFullRebuild = false); 59 void rebuildLayoutAttributes(Vector<SVGTextLayoutAttributes*>& affectedAttributes); 60 61 Vector<SVGTextLayoutAttributes*>& layoutAttributes() { return m_layoutAttributes; } 54 void subtreeChildWasAdded(RenderObject*); 55 void subtreeChildWillBeRemoved(RenderSVGInlineText*, Vector<SVGTextLayoutAttributes*, 2>& affectedAttributes); 56 void subtreeChildWasRemoved(const Vector<SVGTextLayoutAttributes*, 2>& affectedAttributes); 57 void subtreeStyleDidChange(RenderSVGInlineText*); 58 void subtreeTextDidChange(RenderSVGInlineText*); 62 59 63 60 private: … … 81 78 virtual void mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool useTransforms, bool fixed, TransformState&, ApplyContainerFlipOrNot = ApplyContainerFlip, bool* wasFixed = 0) const; 82 79 virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0); 80 virtual void removeChild(RenderObject*) OVERRIDE; 81 virtual void willBeDestroyed() OVERRIDE; 83 82 84 83 virtual FloatRect objectBoundingBox() const { return frameRect(); } … … 91 90 virtual RenderBlock* firstLineBlock() const; 92 91 virtual void updateFirstLetter(); 92 93 bool shouldHandleSubtreeMutations() const; 93 94 94 95 bool m_needsReordering : 1; -
trunk/Source/WebCore/rendering/svg/SVGRenderSupport.cpp
r115981 r117225 198 198 if (child->isSVGShape()) 199 199 toRenderSVGShape(child)->setNeedsShapeUpdate(); 200 else if (child->isSVGText()) 200 else if (child->isSVGText()) { 201 toRenderSVGText(child)->setNeedsTextMetricsUpdate(); 201 202 toRenderSVGText(child)->setNeedsPositioningValuesUpdate(); 203 } 202 204 203 205 needsLayout = true; -
trunk/Source/WebCore/rendering/svg/SVGRootInlineBox.cpp
r116801 r117225 74 74 ASSERT(textRoot); 75 75 76 textRoot->rebuildLayoutAttributes();77 76 Vector<SVGTextLayoutAttributes*>& layoutAttributes = textRoot->layoutAttributes(); 78 77 if (layoutAttributes.isEmpty()) -
trunk/Source/WebCore/rendering/svg/SVGTextLayoutAttributesBuilder.cpp
r116801 r117225 27 27 #include "SVGTextPositioningElement.h" 28 28 29 // Set to a value > 0 to dump the text layout attributes30 #define DUMP_TEXT_LAYOUT_ATTRIBUTES 031 32 29 namespace WebCore { 33 30 … … 45 42 return; 46 43 47 if (!buildLayoutAttributesIfNeeded(textRoot)) 48 return; 44 if (m_textPositions.isEmpty()) { 45 m_characterDataMap.clear(); 46 47 m_textLength = 0; 48 const UChar* lastCharacter = 0; 49 collectTextPositioningElements(textRoot, lastCharacter); 50 51 if (!m_textLength) 52 return; 53 54 buildCharacterDataMap(textRoot); 55 } 49 56 50 57 m_metricsBuilder.buildMetricsAndLayoutAttributes(textRoot, text, m_characterDataMap); 51 58 } 52 59 53 void SVGTextLayoutAttributesBuilder::buildLayoutAttributesForWholeTree(RenderSVGText* textRoot)60 bool SVGTextLayoutAttributesBuilder::buildLayoutAttributesForForSubtree(RenderSVGText* textRoot) 54 61 { 55 62 ASSERT(textRoot); 56 63 57 if (!buildLayoutAttributesIfNeeded(textRoot)) 58 return; 59 60 m_metricsBuilder.buildMetricsAndLayoutAttributes(textRoot, 0, m_characterDataMap); 61 } 62 63 void SVGTextLayoutAttributesBuilder::rebuildMetricsForTextRenderer(RenderSVGInlineText* text) 64 { 65 ASSERT(text); 66 m_metricsBuilder.measureTextRenderer(text); 67 } 68 69 void SVGTextLayoutAttributesBuilder::rebuildMetricsForWholeTree(RenderSVGText* textRoot) 70 { 71 ASSERT(textRoot); 72 Vector<SVGTextLayoutAttributes*>& layoutAttributes = textRoot->layoutAttributes(); 73 74 size_t layoutAttributesSize = layoutAttributes.size(); 75 for (size_t i = 0; i < layoutAttributesSize; ++i) 76 m_metricsBuilder.measureTextRenderer(layoutAttributes[i]->context()); 77 } 78 79 bool SVGTextLayoutAttributesBuilder::buildLayoutAttributesIfNeeded(RenderSVGText* textRoot) 80 { 81 ASSERT(textRoot); 64 m_characterDataMap.clear(); 82 65 83 66 if (m_textPositions.isEmpty()) { … … 87 70 } 88 71 89 m_characterDataMap.clear();90 72 if (!m_textLength) 91 73 return false; 92 74 93 buildLayoutAttributes(textRoot); 75 buildCharacterDataMap(textRoot); 76 m_metricsBuilder.buildMetricsAndLayoutAttributes(textRoot, 0, m_characterDataMap); 94 77 return true; 78 } 79 80 void SVGTextLayoutAttributesBuilder::rebuildMetricsForTextRenderer(RenderSVGInlineText* text) 81 { 82 ASSERT(text); 83 m_metricsBuilder.measureTextRenderer(text); 95 84 } 96 85 … … 144 133 } 145 134 146 void SVGTextLayoutAttributesBuilder::buildLayoutAttributes(RenderSVGText* textRoot) 147 { 148 ASSERT(m_textLength); 149 135 void SVGTextLayoutAttributesBuilder::buildCharacterDataMap(RenderSVGText* textRoot) 136 { 150 137 SVGTextPositioningElement* outermostTextElement = SVGTextPositioningElement::elementFromRenderer(textRoot); 151 138 ASSERT(outermostTextElement); … … 174 161 for (unsigned i = 0; i < size; ++i) 175 162 fillCharacterDataMap(m_textPositions[i]); 176 177 #if DUMP_TEXT_LAYOUT_ATTRIBUTES > 0178 fprintf(stderr, "\nDumping ALL layout attributes for RenderSVGText, renderer=%p, node=%p (m_textLength: %i)\n", textRoot, textRoot->node(), m_textLength);179 m_characterDataMap.dump();180 #endif181 163 } 182 164 -
trunk/Source/WebCore/rendering/svg/SVGTextLayoutAttributesBuilder.h
r105057 r117225 44 44 public: 45 45 SVGTextLayoutAttributesBuilder(); 46 void buildLayoutAttributesForWholeTree(RenderSVGText*);46 bool buildLayoutAttributesForForSubtree(RenderSVGText*); 47 47 void buildLayoutAttributesForTextRenderer(RenderSVGInlineText*); 48 48 49 void rebuildMetricsForWholeTree(RenderSVGText*);50 49 void rebuildMetricsForTextRenderer(RenderSVGInlineText*); 51 50 52 51 // Invoked whenever the underlying DOM tree changes, so that m_textPositions is rebuild. 53 52 void clearTextPositioningElements() { m_textPositions.clear(); } 53 unsigned numberOfTextPositioningElements() const { return m_textPositions.size(); } 54 54 55 55 private: … … 67 67 }; 68 68 69 bool buildLayoutAttributesIfNeeded(RenderSVGText*);69 void buildCharacterDataMap(RenderSVGText*); 70 70 void collectTextPositioningElements(RenderObject*, const UChar*& lastCharacter); 71 void buildLayoutAttributes(RenderSVGText*);72 71 void fillCharacterDataMap(const TextPosition&); 73 72 -
trunk/Source/WebCore/svg/SVGAElement.cpp
r117195 r117225 239 239 } 240 240 241 void SVGAElement::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta)242 {243 SVGStyledTransformableElement::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta);244 245 if (changedByParser || !renderer())246 return;247 248 // Invalidate the TextPosition cache in SVGTextLayoutAttributesBuilder as it may now point249 // to no-longer existing SVGTextPositioningElements and thus needs to be rebuilt.250 if (RenderSVGText* textRenderer = RenderSVGText::locateRenderSVGTextAncestor(renderer()))251 textRenderer->invalidateTextPositioningElements();252 }253 254 241 } // namespace WebCore 255 242 -
trunk/Source/WebCore/svg/SVGAElement.h
r117195 r117225 41 41 static PassRefPtr<SVGAElement> create(const QualifiedName&, Document*); 42 42 43 protected:44 virtual void childrenChanged(bool changedByParser = false, Node* beforeChange = 0, Node* afterChange = 0, int childCountDelta = 0) OVERRIDE;45 46 43 private: 47 44 SVGAElement(const QualifiedName&, Document*); -
trunk/Source/WebCore/svg/SVGTextContentElement.cpp
r117195 r117225 322 322 } 323 323 324 void SVGTextContentElement::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta)325 {326 SVGStyledElement::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta);327 328 if (changedByParser || !renderer())329 return;330 331 // Invalidate the TextPosition cache in SVGTextLayoutAttributesBuilder as it may now point332 // to no-longer existing SVGTextPositioningElements and thus needs to be rebuilt.333 if (RenderSVGText* textRenderer = RenderSVGText::locateRenderSVGTextAncestor(renderer()))334 textRenderer->invalidateTextPositioningElements();335 }336 337 324 } 338 325 -
trunk/Source/WebCore/svg/SVGTextContentElement.h
r117195 r117225 110 110 111 111 virtual bool selfHasRelativeLengths() const; 112 virtual void childrenChanged(bool changedByParser = false, Node* beforeChange = 0, Node* afterChange = 0, int childCountDelta = 0);113 112 114 113 private:
Note: See TracChangeset
for help on using the changeset viewer.