Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 29 matching lines...) Expand all Loading... | |
| 40 #include "core/layout/svg/SVGLayoutSupport.h" | 40 #include "core/layout/svg/SVGLayoutSupport.h" |
| 41 #include "core/layout/svg/SVGResourcesCache.h" | 41 #include "core/layout/svg/SVGResourcesCache.h" |
| 42 #include "core/layout/svg/line/SVGRootInlineBox.h" | 42 #include "core/layout/svg/line/SVGRootInlineBox.h" |
| 43 #include "core/paint/SVGTextPainter.h" | 43 #include "core/paint/SVGTextPainter.h" |
| 44 #include "core/style/ShadowList.h" | 44 #include "core/style/ShadowList.h" |
| 45 #include "core/svg/SVGLengthList.h" | 45 #include "core/svg/SVGLengthList.h" |
| 46 #include "core/svg/SVGTextElement.h" | 46 #include "core/svg/SVGTextElement.h" |
| 47 #include "core/svg/SVGTransformList.h" | 47 #include "core/svg/SVGTransformList.h" |
| 48 #include "core/svg/SVGURIReference.h" | 48 #include "core/svg/SVGURIReference.h" |
| 49 #include "platform/FloatConversion.h" | 49 #include "platform/FloatConversion.h" |
| 50 #include "platform/fonts/FontCache.h" | |
| 51 #include "platform/fonts/SimpleFontData.h" | |
| 52 #include "platform/geometry/FloatQuad.h" | 50 #include "platform/geometry/FloatQuad.h" |
| 53 #include "platform/geometry/TransformState.h" | |
| 54 | 51 |
| 55 namespace blink { | 52 namespace blink { |
| 56 | 53 |
| 57 namespace { | 54 namespace { |
| 58 | 55 |
| 59 const LayoutSVGText* findTextRoot(const LayoutObject* start) | 56 const LayoutSVGText* findTextRoot(const LayoutObject* start) |
| 60 { | 57 { |
| 61 ASSERT(start); | 58 ASSERT(start); |
| 62 for (; start; start = start->parent()) { | 59 for (; start; start = start->parent()) { |
| 63 if (start->isSVGText()) | 60 if (start->isSVGText()) |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 98 } | 95 } |
| 99 | 96 |
| 100 static inline void collectLayoutAttributes(LayoutObject* text, Vector<SVGTextLay outAttributes*>& attributes) | 97 static inline void collectLayoutAttributes(LayoutObject* text, Vector<SVGTextLay outAttributes*>& attributes) |
| 101 { | 98 { |
| 102 for (LayoutObject* descendant = text; descendant; descendant = descendant->n extInPreOrder(text)) { | 99 for (LayoutObject* descendant = text; descendant; descendant = descendant->n extInPreOrder(text)) { |
| 103 if (descendant->isSVGInlineText()) | 100 if (descendant->isSVGInlineText()) |
| 104 attributes.append(toLayoutSVGInlineText(descendant)->layoutAttribute s()); | 101 attributes.append(toLayoutSVGInlineText(descendant)->layoutAttribute s()); |
| 105 } | 102 } |
| 106 } | 103 } |
| 107 | 104 |
| 108 static inline bool findPreviousAndNextAttributes(LayoutSVGText* root, LayoutSVGI nlineText* locateElement, SVGTextLayoutAttributes*& previous, SVGTextLayoutAttri butes*& next) | |
| 109 { | |
| 110 ASSERT(root); | |
| 111 ASSERT(locateElement); | |
| 112 bool stopAfterNext = false; | |
| 113 LayoutObject* current = root->firstChild(); | |
| 114 while (current) { | |
| 115 if (current->isSVGInlineText()) { | |
| 116 LayoutSVGInlineText* text = toLayoutSVGInlineText(current); | |
| 117 if (locateElement != text) { | |
| 118 if (stopAfterNext) { | |
| 119 next = text->layoutAttributes(); | |
| 120 return true; | |
| 121 } | |
| 122 | |
| 123 previous = text->layoutAttributes(); | |
| 124 } else { | |
| 125 stopAfterNext = true; | |
| 126 } | |
| 127 } else if (current->isSVGInline()) { | |
| 128 // Descend into text content (if possible). | |
| 129 if (LayoutObject* child = toLayoutSVGInline(current)->firstChild()) { | |
| 130 current = child; | |
| 131 continue; | |
| 132 } | |
| 133 } | |
| 134 | |
| 135 current = current->nextInPreOrderAfterChildren(root); | |
| 136 } | |
| 137 return false; | |
| 138 } | |
| 139 | |
| 140 inline bool LayoutSVGText::shouldHandleSubtreeMutations() const | 105 inline bool LayoutSVGText::shouldHandleSubtreeMutations() const |
| 141 { | 106 { |
| 142 if (beingDestroyed() || !everHadLayout()) { | 107 if (beingDestroyed() || !everHadLayout()) { |
| 143 ASSERT(m_layoutAttributes.isEmpty()); | 108 ASSERT(m_layoutAttributes.isEmpty()); |
| 144 ASSERT(!m_layoutAttributesBuilder.numberOfTextPositioningElements()); | 109 ASSERT(!m_layoutAttributesBuilder.numberOfTextPositioningElements()); |
| 145 return false; | 110 return false; |
| 146 } | 111 } |
| 147 return true; | 112 return true; |
| 148 } | 113 } |
| 149 | 114 |
| 150 void LayoutSVGText::subtreeChildWasAdded(LayoutObject* child) | 115 void LayoutSVGText::subtreeChildWasAdded(LayoutObject*) |
| 151 { | 116 { |
| 152 ASSERT(child); | |
| 153 if (!shouldHandleSubtreeMutations() || documentBeingDestroyed()) | 117 if (!shouldHandleSubtreeMutations() || documentBeingDestroyed()) |
| 154 return; | 118 return; |
| 155 | 119 |
| 156 // Always protect the cache before clearing text positioning elements when t he cache will subsequently be rebuilt. | |
| 157 FontCachePurgePreventer fontCachePurgePreventer; | |
| 158 | |
| 159 // The positioning elements cache doesn't include the new 'child' yet. Clear the | 120 // The positioning elements cache doesn't include the new 'child' yet. Clear the |
| 160 // cache, as the next buildLayoutAttributesForText() call rebuilds it. | 121 // cache, as the next buildLayoutAttributesForText() call rebuilds it. |
| 161 m_layoutAttributesBuilder.clearTextPositioningElements(); | 122 m_layoutAttributesBuilder.clearTextPositioningElements(); |
| 162 | 123 setNeedsPositioningValuesUpdate(); |
| 163 if (!child->isSVGInlineText() && !child->isSVGInline()) | 124 setNeedsLayoutAndFullPaintInvalidation(LayoutInvalidationReason::ChildChange d); |
| 164 return; | |
| 165 | |
| 166 // Detect changes in layout attributes and only measure those text parts tha t have changed! | |
| 167 Vector<SVGTextLayoutAttributes*> newLayoutAttributes; | |
| 168 collectLayoutAttributes(this, newLayoutAttributes); | |
| 169 if (newLayoutAttributes.isEmpty()) { | |
| 170 ASSERT(m_layoutAttributes.isEmpty()); | |
| 171 return; | |
| 172 } | |
| 173 | |
| 174 // Compare m_layoutAttributes with newLayoutAttributes to figure out which a ttribute got added. | |
| 175 size_t size = newLayoutAttributes.size(); | |
| 176 SVGTextLayoutAttributes* attributes = nullptr; | |
| 177 for (size_t i = 0; i < size; ++i) { | |
| 178 attributes = newLayoutAttributes[i]; | |
| 179 if (m_layoutAttributes.find(attributes) == kNotFound) { | |
| 180 // Every time this is invoked, there's only a single new entry in th e newLayoutAttributes list, compared to the old in m_layoutAttributes. | |
| 181 SVGTextLayoutAttributes* previous = nullptr; | |
| 182 SVGTextLayoutAttributes* next = nullptr; | |
| 183 ASSERT_UNUSED(child, attributes->context() == child); | |
| 184 findPreviousAndNextAttributes(this, attributes->context(), previous, next); | |
| 185 | |
| 186 if (previous) | |
| 187 m_layoutAttributesBuilder.buildLayoutAttributesForText(previous- >context()); | |
| 188 m_layoutAttributesBuilder.buildLayoutAttributesForText(attributes->c ontext()); | |
| 189 if (next) | |
| 190 m_layoutAttributesBuilder.buildLayoutAttributesForText(next->con text()); | |
| 191 break; | |
| 192 } | |
| 193 } | |
| 194 | |
| 195 #if ENABLE(ASSERT) | |
| 196 // Verify that m_layoutAttributes only differs by a maximum of one entry. | |
| 197 for (size_t i = 0; i < size; ++i) | |
| 198 ASSERT(m_layoutAttributes.find(newLayoutAttributes[i]) != kNotFound || n ewLayoutAttributes[i] == attributes); | |
| 199 #endif | |
| 200 | |
| 201 m_layoutAttributes = newLayoutAttributes; | |
| 202 } | |
| 203 | |
| 204 static inline void checkLayoutAttributesConsistency(LayoutSVGText* text, Vector< SVGTextLayoutAttributes*>& expectedLayoutAttributes) | |
| 205 { | |
| 206 #if ENABLE(ASSERT) | |
| 207 Vector<SVGTextLayoutAttributes*> newLayoutAttributes; | |
| 208 collectLayoutAttributes(text, newLayoutAttributes); | |
| 209 ASSERT(newLayoutAttributes == expectedLayoutAttributes); | |
| 210 #endif | |
| 211 } | 125 } |
| 212 | 126 |
| 213 void LayoutSVGText::willBeDestroyed() | 127 void LayoutSVGText::willBeDestroyed() |
| 214 { | 128 { |
| 215 m_layoutAttributes.clear(); | 129 m_layoutAttributes.clear(); |
| 216 m_layoutAttributesBuilder.clearTextPositioningElements(); | 130 m_layoutAttributesBuilder.clearTextPositioningElements(); |
| 217 | 131 |
| 218 LayoutSVGBlock::willBeDestroyed(); | 132 LayoutSVGBlock::willBeDestroyed(); |
| 219 } | 133 } |
| 220 | 134 |
| 221 void LayoutSVGText::subtreeChildWillBeRemoved(LayoutObject* child, Vector<SVGTex tLayoutAttributes*, 2>& affectedAttributes) | 135 void LayoutSVGText::subtreeChildWillBeRemoved(LayoutObject* child) |
| 222 { | 136 { |
| 223 ASSERT(child); | 137 ASSERT(child); |
| 224 if (!shouldHandleSubtreeMutations()) | 138 if (!shouldHandleSubtreeMutations()) |
| 225 return; | 139 return; |
| 226 | 140 |
| 227 checkLayoutAttributesConsistency(this, m_layoutAttributes); | 141 // The positioning elements cache depends on the size of each text layoutObj ect in the |
| 142 // subtree. If this changes, clear the cache. It will be rebuilt below on th e next layout. | |
| 143 m_layoutAttributesBuilder.clearTextPositioningElements(); | |
| 144 setNeedsPositioningValuesUpdate(); | |
| 145 setNeedsLayoutAndFullPaintInvalidation(LayoutInvalidationReason::ChildChange d); | |
| 228 | 146 |
| 229 // The positioning elements cache depends on the size of each text layoutObj ect in the | |
| 230 // subtree. If this changes, clear the cache. It's going to be rebuilt below . | |
| 231 m_layoutAttributesBuilder.clearTextPositioningElements(); | |
| 232 if (m_layoutAttributes.isEmpty() || !child->isSVGInlineText()) | 147 if (m_layoutAttributes.isEmpty() || !child->isSVGInlineText()) |
| 233 return; | 148 return; |
| 234 | 149 |
| 235 // This logic requires that the 'text' child is still inserted in the tree. | 150 // Make sure that a text node (layout attribute) reference is not left |
| 236 LayoutSVGInlineText* text = toLayoutSVGInlineText(child); | 151 // dangling in |m_layoutAttributes|. |
| 237 SVGTextLayoutAttributes* previous = nullptr; | 152 size_t position = m_layoutAttributes.find(toLayoutSVGInlineText(child)->layo utAttributes()); |
| 238 SVGTextLayoutAttributes* next = nullptr; | |
| 239 if (!documentBeingDestroyed()) | |
| 240 findPreviousAndNextAttributes(this, text, previous, next); | |
| 241 | |
| 242 if (previous) | |
| 243 affectedAttributes.append(previous); | |
| 244 if (next) | |
| 245 affectedAttributes.append(next); | |
| 246 | |
| 247 size_t position = m_layoutAttributes.find(text->layoutAttributes()); | |
| 248 ASSERT(position != kNotFound); | 153 ASSERT(position != kNotFound); |
| 249 m_layoutAttributes.remove(position); | 154 m_layoutAttributes.remove(position); |
| 250 } | 155 } |
| 251 | 156 |
| 252 void LayoutSVGText::subtreeChildWasRemoved(const Vector<SVGTextLayoutAttributes* , 2>& affectedAttributes) | |
| 253 { | |
| 254 if (!shouldHandleSubtreeMutations() || documentBeingDestroyed()) { | |
| 255 ASSERT(affectedAttributes.isEmpty()); | |
| 256 return; | |
| 257 } | |
| 258 | |
| 259 // This is called immediately after subtreeChildWillBeDestroyed, once the La youtSVGInlineText::willBeDestroyed() method | |
| 260 // passes on to the base class, which removes us from the layout tree. At th is point we can update the layout attributes. | |
| 261 unsigned size = affectedAttributes.size(); | |
| 262 for (unsigned i = 0; i < size; ++i) | |
| 263 m_layoutAttributesBuilder.buildLayoutAttributesForText(affectedAttribute s[i]->context()); | |
| 264 } | |
| 265 | |
| 266 void LayoutSVGText::subtreeTextDidChange(LayoutSVGInlineText* text) | 157 void LayoutSVGText::subtreeTextDidChange(LayoutSVGInlineText* text) |
| 267 { | 158 { |
| 268 ASSERT(text); | 159 ASSERT(text); |
| 269 ASSERT(!beingDestroyed()); | 160 ASSERT(!beingDestroyed()); |
| 270 if (!everHadLayout()) { | 161 if (!everHadLayout()) { |
| 271 ASSERT(m_layoutAttributes.isEmpty()); | 162 ASSERT(m_layoutAttributes.isEmpty()); |
| 272 ASSERT(!m_layoutAttributesBuilder.numberOfTextPositioningElements()); | 163 ASSERT(!m_layoutAttributesBuilder.numberOfTextPositioningElements()); |
| 273 return; | 164 return; |
| 274 } | 165 } |
| 275 | 166 |
| 276 // The positioning elements cache depends on the size of each text object in | 167 // The positioning elements cache depends on the size of each text object in |
| 277 // the subtree. If this changes, clear the cache and mark it for rebuilding | 168 // the subtree. If this changes, clear the cache and mark it for rebuilding |
| 278 // in the next layout. | 169 // in the next layout. |
| 279 m_layoutAttributesBuilder.clearTextPositioningElements(); | 170 m_layoutAttributesBuilder.clearTextPositioningElements(); |
| 280 setNeedsPositioningValuesUpdate(); | 171 setNeedsPositioningValuesUpdate(); |
| 281 setNeedsLayoutAndFullPaintInvalidation(LayoutInvalidationReason::TextChanged ); | 172 setNeedsLayoutAndFullPaintInvalidation(LayoutInvalidationReason::TextChanged ); |
| 282 } | 173 } |
| 283 | 174 |
| 284 static inline void updateFontInAllDescendants(LayoutObject* start, SVGTextLayout AttributesBuilder* builder = nullptr) | 175 static inline void updateFontInAllDescendants(LayoutSVGText& textRoot, SVGTextLa youtAttributesBuilder* builder = nullptr) |
| 285 { | 176 { |
| 286 for (LayoutObject* descendant = start; descendant; descendant = descendant-> nextInPreOrder(start)) { | 177 for (LayoutObject* descendant = &textRoot; descendant; descendant = descenda nt->nextInPreOrder(&textRoot)) { |
| 287 if (!descendant->isSVGInlineText()) | 178 if (!descendant->isSVGInlineText()) |
| 288 continue; | 179 continue; |
| 289 LayoutSVGInlineText* text = toLayoutSVGInlineText(descendant); | 180 LayoutSVGInlineText* text = toLayoutSVGInlineText(descendant); |
| 290 text->updateScaledFont(); | 181 text->updateScaledFont(); |
| 291 if (builder) | 182 if (builder) |
| 292 builder->rebuildMetricsForTextLayoutObject(text); | 183 builder->rebuildMetricsForTextLayoutObject(textRoot, *text); |
| 293 } | 184 } |
| 294 } | 185 } |
| 295 | 186 |
| 187 static inline void checkLayoutAttributesConsistency(LayoutSVGText* text, Vector< SVGTextLayoutAttributes*>& expectedLayoutAttributes) | |
| 188 { | |
| 189 #if ENABLE(ASSERT) | |
| 190 Vector<SVGTextLayoutAttributes*> newLayoutAttributes; | |
| 191 collectLayoutAttributes(text, newLayoutAttributes); | |
| 192 ASSERT(newLayoutAttributes == expectedLayoutAttributes); | |
| 193 #endif | |
| 194 } | |
| 195 | |
| 296 void LayoutSVGText::layout() | 196 void LayoutSVGText::layout() |
| 297 { | 197 { |
| 298 ASSERT(needsLayout()); | 198 ASSERT(needsLayout()); |
| 299 LayoutAnalyzer::Scope analyzer(*this); | 199 LayoutAnalyzer::Scope analyzer(*this); |
| 300 | 200 |
| 301 bool updateCachedBoundariesInParents = false; | 201 bool updateCachedBoundariesInParents = false; |
| 302 if (m_needsTransformUpdate) { | 202 if (m_needsTransformUpdate) { |
| 303 m_localTransform = toSVGTextElement(node())->calculateAnimatedLocalTrans form(); | 203 m_localTransform = toSVGTextElement(node())->calculateAnimatedLocalTrans form(); |
| 304 m_needsTransformUpdate = false; | 204 m_needsTransformUpdate = false; |
| 305 updateCachedBoundariesInParents = true; | 205 updateCachedBoundariesInParents = true; |
| 306 } | 206 } |
| 307 | 207 |
| 308 if (!everHadLayout()) { | 208 if (!everHadLayout()) { |
| 309 // When laying out initially, collect all layout attributes, build the c haracter data map, | 209 // When laying out initially, collect all layout attributes, build the c haracter data map, |
| 310 // and propogate resulting SVGLayoutAttributes to all LayoutSVGInlineTex t children in the subtree. | 210 // and propogate resulting SVGLayoutAttributes to all LayoutSVGInlineTex t children in the subtree. |
| 311 ASSERT(m_layoutAttributes.isEmpty()); | 211 ASSERT(m_layoutAttributes.isEmpty()); |
| 312 collectLayoutAttributes(this, m_layoutAttributes); | 212 collectLayoutAttributes(this, m_layoutAttributes); |
| 313 updateFontInAllDescendants(this); | 213 updateFontInAllDescendants(*this); |
| 314 m_layoutAttributesBuilder.buildLayoutAttributesForForSubtree(*this); | 214 m_layoutAttributesBuilder.buildLayoutAttributesForForSubtree(*this); |
| 315 | 215 |
| 316 m_needsReordering = true; | 216 m_needsReordering = true; |
| 317 m_needsTextMetricsUpdate = false; | 217 m_needsTextMetricsUpdate = false; |
| 318 m_needsPositioningValuesUpdate = false; | 218 m_needsPositioningValuesUpdate = false; |
| 319 updateCachedBoundariesInParents = true; | 219 updateCachedBoundariesInParents = true; |
| 320 } else if (m_needsPositioningValuesUpdate) { | 220 } else if (m_needsPositioningValuesUpdate) { |
| 321 // When the x/y/dx/dy/rotate lists change, recompute the layout attribut es, and eventually | 221 // When the x/y/dx/dy/rotate lists change, recompute the layout attribut es, and eventually |
| 322 // update the on-screen font objects as well in all descendants. | 222 // update the on-screen font objects as well in all descendants. |
| 323 if (m_needsTextMetricsUpdate) { | 223 if (m_needsTextMetricsUpdate) { |
| 324 updateFontInAllDescendants(this); | 224 updateFontInAllDescendants(*this); |
| 325 m_needsTextMetricsUpdate = false; | 225 m_needsTextMetricsUpdate = false; |
| 326 } | 226 } |
| 327 | 227 |
| 228 m_layoutAttributes.clear(); | |
|
fs
2016/04/04 20:04:13
Should probably just do this directly "on invalida
pdr.
2016/04/04 22:33:13
Followup sounds great
| |
| 229 collectLayoutAttributes(this, m_layoutAttributes); | |
| 328 m_layoutAttributesBuilder.buildLayoutAttributesForForSubtree(*this); | 230 m_layoutAttributesBuilder.buildLayoutAttributesForForSubtree(*this); |
| 329 m_needsReordering = true; | 231 m_needsReordering = true; |
| 330 m_needsPositioningValuesUpdate = false; | 232 m_needsPositioningValuesUpdate = false; |
| 331 updateCachedBoundariesInParents = true; | 233 updateCachedBoundariesInParents = true; |
| 332 } else if (m_needsTextMetricsUpdate || SVGLayoutSupport::findTreeRootObject( this)->isLayoutSizeChanged()) { | 234 } else if (m_needsTextMetricsUpdate || SVGLayoutSupport::findTreeRootObject( this)->isLayoutSizeChanged()) { |
| 333 // If the root layout size changed (eg. window size changes) or the tran sform to the root | 235 // If the root layout size changed (eg. window size changes) or the tran sform to the root |
| 334 // context has changed then recompute the on-screen font size. | 236 // context has changed then recompute the on-screen font size. |
| 335 updateFontInAllDescendants(this, &m_layoutAttributesBuilder); | 237 updateFontInAllDescendants(*this, &m_layoutAttributesBuilder); |
| 336 | 238 |
| 337 ASSERT(!m_needsReordering); | 239 ASSERT(!m_needsReordering); |
| 338 ASSERT(!m_needsPositioningValuesUpdate); | 240 ASSERT(!m_needsPositioningValuesUpdate); |
| 339 m_needsTextMetricsUpdate = false; | 241 m_needsTextMetricsUpdate = false; |
| 340 updateCachedBoundariesInParents = true; | 242 updateCachedBoundariesInParents = true; |
| 341 } | 243 } |
| 342 | 244 |
| 343 checkLayoutAttributesConsistency(this, m_layoutAttributes); | 245 checkLayoutAttributesConsistency(this, m_layoutAttributes); |
| 344 | 246 |
| 345 // Reduced version of LayoutBlock::layoutBlock(), which only takes care of S VG text. | 247 // Reduced version of LayoutBlock::layoutBlock(), which only takes care of S VG text. |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 487 { | 389 { |
| 488 LayoutSVGBlock::addChild(child, beforeChild); | 390 LayoutSVGBlock::addChild(child, beforeChild); |
| 489 | 391 |
| 490 SVGResourcesCache::clientWasAddedToTree(child, child->styleRef()); | 392 SVGResourcesCache::clientWasAddedToTree(child, child->styleRef()); |
| 491 subtreeChildWasAdded(child); | 393 subtreeChildWasAdded(child); |
| 492 } | 394 } |
| 493 | 395 |
| 494 void LayoutSVGText::removeChild(LayoutObject* child) | 396 void LayoutSVGText::removeChild(LayoutObject* child) |
| 495 { | 397 { |
| 496 SVGResourcesCache::clientWillBeRemovedFromTree(child); | 398 SVGResourcesCache::clientWillBeRemovedFromTree(child); |
| 399 subtreeChildWillBeRemoved(child); | |
| 497 | 400 |
| 498 Vector<SVGTextLayoutAttributes*, 2> affectedAttributes; | |
| 499 FontCachePurgePreventer fontCachePurgePreventer; | |
| 500 subtreeChildWillBeRemoved(child, affectedAttributes); | |
| 501 LayoutSVGBlock::removeChild(child); | 401 LayoutSVGBlock::removeChild(child); |
| 502 subtreeChildWasRemoved(affectedAttributes); | |
| 503 } | 402 } |
| 504 | 403 |
| 505 void LayoutSVGText::invalidateTreeIfNeeded(const PaintInvalidationState& paintIn validationState) | 404 void LayoutSVGText::invalidateTreeIfNeeded(const PaintInvalidationState& paintIn validationState) |
| 506 { | 405 { |
| 507 ASSERT(!needsLayout()); | 406 ASSERT(!needsLayout()); |
| 508 | 407 |
| 509 if (!shouldCheckForPaintInvalidation(paintInvalidationState)) | 408 if (!shouldCheckForPaintInvalidation(paintInvalidationState)) |
| 510 return; | 409 return; |
| 511 | 410 |
| 512 PaintInvalidationState newPaintInvalidationState(paintInvalidationState, *th is); | 411 PaintInvalidationState newPaintInvalidationState(paintInvalidationState, *th is); |
| 513 PaintInvalidationReason reason = invalidatePaintIfNeeded(newPaintInvalidatio nState); | 412 PaintInvalidationReason reason = invalidatePaintIfNeeded(newPaintInvalidatio nState); |
| 514 clearPaintInvalidationFlags(newPaintInvalidationState); | 413 clearPaintInvalidationFlags(newPaintInvalidationState); |
| 515 | 414 |
| 516 if (reason == PaintInvalidationDelayedFull) | 415 if (reason == PaintInvalidationDelayedFull) |
| 517 paintInvalidationState.pushDelayedPaintInvalidationTarget(*this); | 416 paintInvalidationState.pushDelayedPaintInvalidationTarget(*this); |
| 518 | 417 |
| 519 // TODO(wangxianzhu): Move this to fast path if possible. crbug.com/391054. | 418 // TODO(wangxianzhu): Move this to fast path if possible. crbug.com/391054. |
| 520 ForceHorriblySlowRectMapping slowRectMapping(&newPaintInvalidationState); | 419 ForceHorriblySlowRectMapping slowRectMapping(&newPaintInvalidationState); |
| 521 if (reason == PaintInvalidationSVGResourceChange) | 420 if (reason == PaintInvalidationSVGResourceChange) |
| 522 newPaintInvalidationState.setForceSubtreeInvalidationWithinContainer(); | 421 newPaintInvalidationState.setForceSubtreeInvalidationWithinContainer(); |
| 523 | 422 |
| 524 newPaintInvalidationState.updateForChildren(); | 423 newPaintInvalidationState.updateForChildren(); |
| 525 invalidatePaintOfSubtreesIfNeeded(newPaintInvalidationState); | 424 invalidatePaintOfSubtreesIfNeeded(newPaintInvalidationState); |
| 526 } | 425 } |
| 527 | 426 |
| 528 } // namespace blink | 427 } // namespace blink |
| OLD | NEW |