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

Side by Side Diff: Source/WebCore/rendering/svg/RenderSVGText.cpp

Issue 10443073: Merge 117225 (Closed) Base URL: http://svn.webkit.org/repository/webkit/branches/chromium/1132/
Patch Set: Created 8 years, 6 months 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 /* 1 /*
2 * Copyright (C) 2006 Apple Computer, Inc. 2 * Copyright (C) 2006 Apple Computer, Inc.
3 * Copyright (C) 2006 Alexander Kellett <lypanov@kde.org> 3 * Copyright (C) 2006 Alexander Kellett <lypanov@kde.org>
4 * Copyright (C) 2006 Oliver Hunt <ojh16@student.canterbury.ac.nz> 4 * Copyright (C) 2006 Oliver Hunt <ojh16@student.canterbury.ac.nz>
5 * Copyright (C) 2007 Nikolas Zimmermann <zimmermann@kde.org> 5 * Copyright (C) 2007 Nikolas Zimmermann <zimmermann@kde.org>
6 * Copyright (C) 2008 Rob Buis <buis@kde.org> 6 * Copyright (C) 2008 Rob Buis <buis@kde.org>
7 * Copyright (C) 2009 Dirk Schulze <krit@webkit.org> 7 * Copyright (C) 2009 Dirk Schulze <krit@webkit.org>
8 * Copyright (C) Research In Motion Limited 2010-2012. All rights reserved. 8 * Copyright (C) Research In Motion Limited 2010-2012. All rights reserved.
9 * Copyright (C) 2012 Google Inc. 9 * Copyright (C) 2012 Google Inc.
10 * 10 *
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
50 #include "SVGURIReference.h" 50 #include "SVGURIReference.h"
51 #include "SimpleFontData.h" 51 #include "SimpleFontData.h"
52 #include "TransformState.h" 52 #include "TransformState.h"
53 #include "VisiblePosition.h" 53 #include "VisiblePosition.h"
54 54
55 namespace WebCore { 55 namespace WebCore {
56 56
57 RenderSVGText::RenderSVGText(SVGTextElement* node) 57 RenderSVGText::RenderSVGText(SVGTextElement* node)
58 : RenderSVGBlock(node) 58 : RenderSVGBlock(node)
59 , m_needsReordering(false) 59 , m_needsReordering(false)
60 , m_needsPositioningValuesUpdate(true) 60 , m_needsPositioningValuesUpdate(false)
61 , m_needsTransformUpdate(true) 61 , m_needsTransformUpdate(true)
62 , m_needsTextMetricsUpdate(true) 62 , m_needsTextMetricsUpdate(false)
63 { 63 {
64 } 64 }
65 65
66 RenderSVGText::~RenderSVGText()
67 {
68 ASSERT(m_layoutAttributes.isEmpty());
69 }
70
66 bool RenderSVGText::isChildAllowed(RenderObject* child, RenderStyle*) const 71 bool RenderSVGText::isChildAllowed(RenderObject* child, RenderStyle*) const
67 { 72 {
68 return child->isInline(); 73 return child->isInline();
69 } 74 }
70 75
71 RenderSVGText* RenderSVGText::locateRenderSVGTextAncestor(RenderObject* start) 76 RenderSVGText* RenderSVGText::locateRenderSVGTextAncestor(RenderObject* start)
72 { 77 {
73 ASSERT(start); 78 ASSERT(start);
74 while (start && !start->isSVGText()) 79 while (start && !start->isSVGText())
75 start = start->parent(); 80 start = start->parent();
(...skipping 27 matching lines...) Expand all
103 void RenderSVGText::computeFloatRectForRepaint(RenderBoxModelObject* repaintCont ainer, FloatRect& repaintRect, bool fixed) const 108 void RenderSVGText::computeFloatRectForRepaint(RenderBoxModelObject* repaintCont ainer, FloatRect& repaintRect, bool fixed) const
104 { 109 {
105 SVGRenderSupport::computeFloatRectForRepaint(this, repaintContainer, repaint Rect, fixed); 110 SVGRenderSupport::computeFloatRectForRepaint(this, repaintContainer, repaint Rect, fixed);
106 } 111 }
107 112
108 void RenderSVGText::mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool /* fixed */, bool /* useTransforms */, TransformState& transformState, Appl yContainerFlipOrNot, bool* wasFixed) const 113 void RenderSVGText::mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool /* fixed */, bool /* useTransforms */, TransformState& transformState, Appl yContainerFlipOrNot, bool* wasFixed) const
109 { 114 {
110 SVGRenderSupport::mapLocalToContainer(this, repaintContainer, transformState , wasFixed); 115 SVGRenderSupport::mapLocalToContainer(this, repaintContainer, transformState , wasFixed);
111 } 116 }
112 117
113 static inline void recursiveUpdateLayoutAttributes(RenderObject* start, SVGTextL ayoutAttributesBuilder& builder) 118 static inline void collectLayoutAttributes(RenderObject* text, Vector<SVGTextLay outAttributes*>& attributes)
114 { 119 {
115 if (start->isSVGInlineText()) { 120 for (RenderObject* descendant = text; descendant; descendant = descendant->n extInPreOrder(text)) {
116 builder.buildLayoutAttributesForTextRenderer(toRenderSVGInlineText(start )); 121 if (descendant->isSVGInlineText())
117 return; 122 attributes.append(toRenderSVGInlineText(descendant)->layoutAttribute s());
118 } 123 }
119
120 for (RenderObject* child = start->firstChild(); child; child = child->nextSi bling())
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();
132 } 124 }
133 125
134 static inline bool findPreviousAndNextAttributes(RenderObject* start, RenderSVGI nlineText* locateElement, bool& stopAfterNext, SVGTextLayoutAttributes*& previou s, SVGTextLayoutAttributes*& next) 126 static inline bool findPreviousAndNextAttributes(RenderObject* start, RenderSVGI nlineText* locateElement, bool& stopAfterNext, SVGTextLayoutAttributes*& previou s, SVGTextLayoutAttributes*& next)
135 { 127 {
136 ASSERT(start); 128 ASSERT(start);
137 ASSERT(locateElement); 129 ASSERT(locateElement);
130 // FIXME: Make this iterative.
138 for (RenderObject* child = start->firstChild(); child; child = child->nextSi bling()) { 131 for (RenderObject* child = start->firstChild(); child; child = child->nextSi bling()) {
139 if (child->isSVGInlineText()) { 132 if (child->isSVGInlineText()) {
140 RenderSVGInlineText* text = toRenderSVGInlineText(child); 133 RenderSVGInlineText* text = toRenderSVGInlineText(child);
141 if (locateElement != text) { 134 if (locateElement != text) {
142 if (stopAfterNext) { 135 if (stopAfterNext) {
143 next = text->layoutAttributes(); 136 next = text->layoutAttributes();
144 return true; 137 return true;
145 } 138 }
146 139
147 previous = text->layoutAttributes(); 140 previous = text->layoutAttributes();
148 continue; 141 continue;
149 } 142 }
150 143
151 stopAfterNext = true; 144 stopAfterNext = true;
152 continue; 145 continue;
153 } 146 }
154 147
155 if (!child->isSVGInline()) 148 if (!child->isSVGInline())
156 continue; 149 continue;
157 150
158 if (findPreviousAndNextAttributes(child, locateElement, stopAfterNext, p revious, next)) 151 if (findPreviousAndNextAttributes(child, locateElement, stopAfterNext, p revious, next))
159 return true; 152 return true;
160 } 153 }
161 154
162 return false; 155 return false;
163 } 156 }
164 157
165 void RenderSVGText::layoutAttributesWillBeDestroyed(RenderSVGInlineText* text, V ector<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 i t.
176 m_layoutAttributesBuilder.clearTextPositioningElements();
177
178 // Detect changes in layout attributes and only measure those text parts tha t 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 a ttribute 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 th e 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(), stopAfter Next, previous, next);
198
199 if (previous)
200 m_layoutAttributesBuilder.buildLayoutAttributesForTextRenderer(p revious->context());
201 m_layoutAttributesBuilder.buildLayoutAttributesForTextRenderer(attri butes->context());
202 if (next)
203 m_layoutAttributesBuilder.buildLayoutAttributesForTextRenderer(n ext->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 || ne wLayoutAttributes[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 ASSERT(text); 239 ASSERT(text);
168 if (m_needsPositioningValuesUpdate) 240 if (!shouldHandleSubtreeMutations())
169 return; 241 return;
170 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 bool stopAfterNext = false; 252 bool stopAfterNext = false;
172 SVGTextLayoutAttributes* previous = 0; 253 SVGTextLayoutAttributes* previous = 0;
173 SVGTextLayoutAttributes* next = 0; 254 SVGTextLayoutAttributes* next = 0;
174 findPreviousAndNextAttributes(this, text, stopAfterNext, previous, next); 255 if (!documentBeingDestroyed())
256 findPreviousAndNextAttributes(this, text, stopAfterNext, previous, next) ;
257
175 if (previous) 258 if (previous)
176 affectedAttributes.append(previous); 259 affectedAttributes.append(previous);
177 if (next) 260 if (next)
178 affectedAttributes.append(next); 261 affectedAttributes.append(next);
262
263 size_t position = m_layoutAttributes.find(text->layoutAttributes());
264 ASSERT(position != notFound);
265 m_layoutAttributes.remove(position);
179 } 266 }
180 267
181 void RenderSVGText::invalidateTextPositioningElements() 268 void RenderSVGText::subtreeChildWasRemoved(const Vector<SVGTextLayoutAttributes* , 2>& affectedAttributes)
182 { 269 {
183 // Clear the text positioning elements. This should be called when either th e children 270 if (!shouldHandleSubtreeMutations() || documentBeingDestroyed()) {
184 // of a DOM text element have changed, or the length of the text in any chil d element 271 ASSERT(affectedAttributes.isEmpty());
185 // has changed. Failure to clear may leave us with invalid elements, as othe r code paths 272 return;
186 // do not always cause the position elements to be marked invalid before use . 273 }
187 m_layoutAttributesBuilder.clearTextPositioningElements(); 274
275 // This is called immediately after subtreeChildWillBeDestroyed, once the Re nderSVGInlineText::willBeDestroyed() method
276 // passes on to the base class, which removes us from the render tree. At th is point we can update the layout attributes.
277 unsigned size = affectedAttributes.size();
278 for (unsigned i = 0; i < size; ++i)
279 m_layoutAttributesBuilder.buildLayoutAttributesForTextRenderer(affectedA ttributes[i]->context());
188 } 280 }
189 281
190 static inline void recursiveUpdateScaledFont(RenderObject* start) 282 void RenderSVGText::subtreeStyleDidChange(RenderSVGInlineText* text)
191 { 283 {
192 for (RenderObject* child = start->firstChild(); child; child = child->nextSi bling()) { 284 ASSERT(text);
193 if (child->isSVGInlineText()) { 285 if (!shouldHandleSubtreeMutations() || documentBeingDestroyed())
194 toRenderSVGInlineText(child)->updateScaledFont(); 286 return;
195 continue;
196 }
197 287
198 recursiveUpdateScaledFont(child); 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->n extInPreOrder(text)) {
294 if (descendant->isSVGInlineText())
295 m_layoutAttributesBuilder.rebuildMetricsForTextRenderer(toRenderSVGI nlineText(descendant));
199 } 296 }
200 } 297 }
201 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 .
311 m_layoutAttributesBuilder.clearTextPositioningElements();
312
313 checkLayoutAttributesConsistency(this, m_layoutAttributes);
314 for (RenderObject* descendant = text; descendant; descendant = descendant->n extInPreOrder(text)) {
315 if (descendant->isSVGInlineText())
316 m_layoutAttributesBuilder.buildLayoutAttributesForTextRenderer(toRen derSVGInlineText(descendant));
317 }
318 }
319
320 static inline void updateFontInAllDescendants(RenderObject* start, SVGTextLayout AttributesBuilder* builder = 0)
321 {
322 for (RenderObject* descendant = start; descendant; descendant = descendant-> nextInPreOrder(start)) {
323 if (!descendant->isSVGInlineText())
324 continue;
325 RenderSVGInlineText* text = toRenderSVGInlineText(descendant);
326 text->updateScaledFont();
327 if (builder)
328 builder->rebuildMetricsForTextRenderer(text);
329 }
330 }
331
202 void RenderSVGText::layout() 332 void RenderSVGText::layout()
203 { 333 {
204 ASSERT(needsLayout()); 334 ASSERT(needsLayout());
205 LayoutRepainter repainter(*this, checkForRepaintDuringLayout()); 335 LayoutRepainter repainter(*this, checkForRepaintDuringLayout());
206 336
207 bool updateCachedBoundariesInParents = false; 337 bool updateCachedBoundariesInParents = false;
208 if (m_needsTransformUpdate) { 338 if (m_needsTransformUpdate) {
209 SVGTextElement* text = static_cast<SVGTextElement*>(node()); 339 SVGTextElement* text = static_cast<SVGTextElement*>(node());
210 m_localTransform = text->animatedLocalTransform(); 340 m_localTransform = text->animatedLocalTransform();
211 m_needsTransformUpdate = false; 341 m_needsTransformUpdate = false;
212 updateCachedBoundariesInParents = true; 342 updateCachedBoundariesInParents = true;
213 } 343 }
214 344
215 // If the root layout size changed (eg. window size changes) or the position ing values change 345 if (!everHadLayout()) {
216 // or the transform to the root context has changed then recompute the on-sc reen font size. 346 // When laying out initially, collect all layout attributes, build the c haracter data map,
217 if (m_needsTextMetricsUpdate || SVGRenderSupport::findTreeRootObject(this)-> isLayoutSizeChanged()) { 347 // and propogate resulting SVGLayoutAttributes to all RenderSVGInlineTex t children in the subtree.
218 recursiveUpdateScaledFont(this); 348 ASSERT(m_layoutAttributes.isEmpty());
219 rebuildLayoutAttributes(true); 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 updateCachedBoundariesInParents = true; 356 updateCachedBoundariesInParents = true;
221 m_needsTextMetricsUpdate = false; 357 } else if (m_needsPositioningValuesUpdate) {
222 } 358 // When the x/y/dx/dy/rotate lists change, recompute the layout attribut es, 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 }
223 364
224 if (m_needsPositioningValuesUpdate) { 365 m_layoutAttributesBuilder.buildLayoutAttributesForForSubtree(this);
225 // Perform SVG text layout phase one (see SVGTextLayoutAttributesBuilder for details).
226 m_layoutAttributesBuilder.buildLayoutAttributesForWholeTree(this);
227 m_needsReordering = true; 366 m_needsReordering = true;
228 m_needsPositioningValuesUpdate = false; 367 m_needsPositioningValuesUpdate = false;
229 updateCachedBoundariesInParents = true; 368 updateCachedBoundariesInParents = true;
369 } else if (m_needsTextMetricsUpdate || SVGRenderSupport::findTreeRootObject( this)->isLayoutSizeChanged()) {
370 // If the root layout size changed (eg. window size changes) or the tran sform 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;
230 } 378 }
231 379
380 checkLayoutAttributesConsistency(this, m_layoutAttributes);
381
232 // Reduced version of RenderBlock::layoutBlock(), which only takes care of S VG text. 382 // Reduced version of RenderBlock::layoutBlock(), which only takes care of S VG text.
233 // All if branches that could cause early exit in RenderBlocks layoutBlock() method are turned into assertions. 383 // All if branches that could cause early exit in RenderBlocks layoutBlock() method are turned into assertions.
234 ASSERT(!isInline()); 384 ASSERT(!isInline());
235 ASSERT(!simplifiedLayout()); 385 ASSERT(!simplifiedLayout());
236 ASSERT(!scrollsOverflow()); 386 ASSERT(!scrollsOverflow());
237 ASSERT(!hasControlClip()); 387 ASSERT(!hasControlClip());
238 ASSERT(!hasColumns()); 388 ASSERT(!hasColumns());
239 ASSERT(!positionedObjects()); 389 ASSERT(!positionedObjects());
240 ASSERT(!m_overflow); 390 ASSERT(!m_overflow);
241 ASSERT(!isAnonymousBlock()); 391 ASSERT(!isAnonymousBlock());
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
357 507
358 if (const ShadowData* textShadow = style()->textShadow()) 508 if (const ShadowData* textShadow = style()->textShadow())
359 textShadow->adjustRectForShadow(repaintRect); 509 textShadow->adjustRectForShadow(repaintRect);
360 510
361 return repaintRect; 511 return repaintRect;
362 } 512 }
363 513
364 void RenderSVGText::addChild(RenderObject* child, RenderObject* beforeChild) 514 void RenderSVGText::addChild(RenderObject* child, RenderObject* beforeChild)
365 { 515 {
366 RenderSVGBlock::addChild(child, beforeChild); 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
370 // Fix for <rdar://problem/8048875>. We should not render :first-line CSS Style 534 // Fix for <rdar://problem/8048875>. We should not render :first-line CSS Style
371 // in a SVG text element context. 535 // in a SVG text element context.
372 RenderBlock* RenderSVGText::firstLineBlock() const 536 RenderBlock* RenderSVGText::firstLineBlock() const
373 { 537 {
374 return 0; 538 return 0;
375 } 539 }
376 540
377 // Fix for <rdar://problem/8048875>. We should not render :first-letter CSS Styl e 541 // Fix for <rdar://problem/8048875>. We should not render :first-letter CSS Styl e
378 // in a SVG text element context. 542 // in a SVG text element context.
379 void RenderSVGText::updateFirstLetter() 543 void RenderSVGText::updateFirstLetter()
380 { 544 {
381 } 545 }
382 546
383 static inline void recursiveCollectLayoutAttributes(RenderObject* start, Vector< SVGTextLayoutAttributes*>& attributes)
384 {
385 for (RenderObject* child = start->firstChild(); child; child = child->nextSi bling()) {
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*>& af fectedAttributes)
414 {
415 // Detect changes in layout attributes and only measure those text parts tha t 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 a ttributes 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(affectedAttribut es[i]->context());
434
435 m_layoutAttributes = newLayoutAttributes;
436 }
437
438 } 547 }
439 548
440 #endif // ENABLE(SVG) 549 #endif // ENABLE(SVG)
OLDNEW
« no previous file with comments | « Source/WebCore/rendering/svg/RenderSVGText.h ('k') | Source/WebCore/rendering/svg/SVGRenderSupport.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698