Chromium Code Reviews| Index: third_party/WebKit/Source/core/layout/svg/LayoutSVGText.cpp |
| diff --git a/third_party/WebKit/Source/core/layout/svg/LayoutSVGText.cpp b/third_party/WebKit/Source/core/layout/svg/LayoutSVGText.cpp |
| index c8244fcb47e728b76a02ad87140e5b886a25d57c..586b36a93fb9c5cf50f58b158ab2bd3d9d988cf4 100644 |
| --- a/third_party/WebKit/Source/core/layout/svg/LayoutSVGText.cpp |
| +++ b/third_party/WebKit/Source/core/layout/svg/LayoutSVGText.cpp |
| @@ -47,10 +47,7 @@ |
| #include "core/svg/SVGTransformList.h" |
| #include "core/svg/SVGURIReference.h" |
| #include "platform/FloatConversion.h" |
| -#include "platform/fonts/FontCache.h" |
| -#include "platform/fonts/SimpleFontData.h" |
| #include "platform/geometry/FloatQuad.h" |
| -#include "platform/geometry/TransformState.h" |
| namespace blink { |
| @@ -105,38 +102,6 @@ static inline void collectLayoutAttributes(LayoutObject* text, Vector<SVGTextLay |
| } |
| } |
| -static inline bool findPreviousAndNextAttributes(LayoutSVGText* root, LayoutSVGInlineText* locateElement, SVGTextLayoutAttributes*& previous, SVGTextLayoutAttributes*& next) |
| -{ |
| - ASSERT(root); |
| - ASSERT(locateElement); |
| - bool stopAfterNext = false; |
| - LayoutObject* current = root->firstChild(); |
| - while (current) { |
| - if (current->isSVGInlineText()) { |
| - LayoutSVGInlineText* text = toLayoutSVGInlineText(current); |
| - if (locateElement != text) { |
| - if (stopAfterNext) { |
| - next = text->layoutAttributes(); |
| - return true; |
| - } |
| - |
| - previous = text->layoutAttributes(); |
| - } else { |
| - stopAfterNext = true; |
| - } |
| - } else if (current->isSVGInline()) { |
| - // Descend into text content (if possible). |
| - if (LayoutObject* child = toLayoutSVGInline(current)->firstChild()) { |
| - current = child; |
| - continue; |
| - } |
| - } |
| - |
| - current = current->nextInPreOrderAfterChildren(root); |
| - } |
| - return false; |
| -} |
| - |
| inline bool LayoutSVGText::shouldHandleSubtreeMutations() const |
| { |
| if (beingDestroyed() || !everHadLayout()) { |
| @@ -147,67 +112,16 @@ inline bool LayoutSVGText::shouldHandleSubtreeMutations() const |
| return true; |
| } |
| -void LayoutSVGText::subtreeChildWasAdded(LayoutObject* child) |
| +void LayoutSVGText::subtreeChildWasAdded(LayoutObject*) |
| { |
| - ASSERT(child); |
| if (!shouldHandleSubtreeMutations() || documentBeingDestroyed()) |
| return; |
| - // Always protect the cache before clearing text positioning elements when the cache will subsequently be rebuilt. |
| - FontCachePurgePreventer fontCachePurgePreventer; |
| - |
| // The positioning elements cache doesn't include the new 'child' yet. Clear the |
| // cache, as the next buildLayoutAttributesForText() call rebuilds it. |
| m_layoutAttributesBuilder.clearTextPositioningElements(); |
| - |
| - if (!child->isSVGInlineText() && !child->isSVGInline()) |
| - return; |
| - |
| - // Detect changes in layout attributes and only measure those text parts that have changed! |
| - Vector<SVGTextLayoutAttributes*> newLayoutAttributes; |
| - collectLayoutAttributes(this, newLayoutAttributes); |
| - if (newLayoutAttributes.isEmpty()) { |
| - ASSERT(m_layoutAttributes.isEmpty()); |
| - return; |
| - } |
| - |
| - // Compare m_layoutAttributes with newLayoutAttributes to figure out which attribute got added. |
| - size_t size = newLayoutAttributes.size(); |
| - SVGTextLayoutAttributes* attributes = nullptr; |
| - for (size_t i = 0; i < size; ++i) { |
| - attributes = newLayoutAttributes[i]; |
| - if (m_layoutAttributes.find(attributes) == kNotFound) { |
| - // Every time this is invoked, there's only a single new entry in the newLayoutAttributes list, compared to the old in m_layoutAttributes. |
| - SVGTextLayoutAttributes* previous = nullptr; |
| - SVGTextLayoutAttributes* next = nullptr; |
| - ASSERT_UNUSED(child, attributes->context() == child); |
| - findPreviousAndNextAttributes(this, attributes->context(), previous, next); |
| - |
| - if (previous) |
| - m_layoutAttributesBuilder.buildLayoutAttributesForText(previous->context()); |
| - m_layoutAttributesBuilder.buildLayoutAttributesForText(attributes->context()); |
| - if (next) |
| - m_layoutAttributesBuilder.buildLayoutAttributesForText(next->context()); |
| - break; |
| - } |
| - } |
| - |
| -#if ENABLE(ASSERT) |
| - // Verify that m_layoutAttributes only differs by a maximum of one entry. |
| - for (size_t i = 0; i < size; ++i) |
| - ASSERT(m_layoutAttributes.find(newLayoutAttributes[i]) != kNotFound || newLayoutAttributes[i] == attributes); |
| -#endif |
| - |
| - m_layoutAttributes = newLayoutAttributes; |
| -} |
| - |
| -static inline void checkLayoutAttributesConsistency(LayoutSVGText* text, Vector<SVGTextLayoutAttributes*>& expectedLayoutAttributes) |
| -{ |
| -#if ENABLE(ASSERT) |
| - Vector<SVGTextLayoutAttributes*> newLayoutAttributes; |
| - collectLayoutAttributes(text, newLayoutAttributes); |
| - ASSERT(newLayoutAttributes == expectedLayoutAttributes); |
| -#endif |
| + setNeedsPositioningValuesUpdate(); |
| + setNeedsLayoutAndFullPaintInvalidation(LayoutInvalidationReason::ChildChanged); |
| } |
| void LayoutSVGText::willBeDestroyed() |
| @@ -218,51 +132,28 @@ void LayoutSVGText::willBeDestroyed() |
| LayoutSVGBlock::willBeDestroyed(); |
| } |
| -void LayoutSVGText::subtreeChildWillBeRemoved(LayoutObject* child, Vector<SVGTextLayoutAttributes*, 2>& affectedAttributes) |
| +void LayoutSVGText::subtreeChildWillBeRemoved(LayoutObject* child) |
| { |
| ASSERT(child); |
| if (!shouldHandleSubtreeMutations()) |
| return; |
| - checkLayoutAttributesConsistency(this, m_layoutAttributes); |
| - |
| // The positioning elements cache depends on the size of each text layoutObject in the |
| - // subtree. If this changes, clear the cache. It's going to be rebuilt below. |
| + // subtree. If this changes, clear the cache. It will be rebuilt below on the next layout. |
| m_layoutAttributesBuilder.clearTextPositioningElements(); |
| + setNeedsPositioningValuesUpdate(); |
| + setNeedsLayoutAndFullPaintInvalidation(LayoutInvalidationReason::ChildChanged); |
| + |
| if (m_layoutAttributes.isEmpty() || !child->isSVGInlineText()) |
| return; |
| - // This logic requires that the 'text' child is still inserted in the tree. |
| - LayoutSVGInlineText* text = toLayoutSVGInlineText(child); |
| - SVGTextLayoutAttributes* previous = nullptr; |
| - SVGTextLayoutAttributes* next = nullptr; |
| - if (!documentBeingDestroyed()) |
| - findPreviousAndNextAttributes(this, text, previous, next); |
| - |
| - if (previous) |
| - affectedAttributes.append(previous); |
| - if (next) |
| - affectedAttributes.append(next); |
| - |
| - size_t position = m_layoutAttributes.find(text->layoutAttributes()); |
| + // Make sure that a text node (layout attribute) reference is not left |
| + // dangling in |m_layoutAttributes|. |
| + size_t position = m_layoutAttributes.find(toLayoutSVGInlineText(child)->layoutAttributes()); |
| ASSERT(position != kNotFound); |
| m_layoutAttributes.remove(position); |
| } |
| -void LayoutSVGText::subtreeChildWasRemoved(const Vector<SVGTextLayoutAttributes*, 2>& affectedAttributes) |
| -{ |
| - if (!shouldHandleSubtreeMutations() || documentBeingDestroyed()) { |
| - ASSERT(affectedAttributes.isEmpty()); |
| - return; |
| - } |
| - |
| - // This is called immediately after subtreeChildWillBeDestroyed, once the LayoutSVGInlineText::willBeDestroyed() method |
| - // passes on to the base class, which removes us from the layout tree. At this point we can update the layout attributes. |
| - unsigned size = affectedAttributes.size(); |
| - for (unsigned i = 0; i < size; ++i) |
| - m_layoutAttributesBuilder.buildLayoutAttributesForText(affectedAttributes[i]->context()); |
| -} |
| - |
| void LayoutSVGText::subtreeTextDidChange(LayoutSVGInlineText* text) |
| { |
| ASSERT(text); |
| @@ -281,18 +172,27 @@ void LayoutSVGText::subtreeTextDidChange(LayoutSVGInlineText* text) |
| setNeedsLayoutAndFullPaintInvalidation(LayoutInvalidationReason::TextChanged); |
| } |
| -static inline void updateFontInAllDescendants(LayoutObject* start, SVGTextLayoutAttributesBuilder* builder = nullptr) |
| +static inline void updateFontInAllDescendants(LayoutSVGText& textRoot, SVGTextLayoutAttributesBuilder* builder = nullptr) |
| { |
| - for (LayoutObject* descendant = start; descendant; descendant = descendant->nextInPreOrder(start)) { |
| + for (LayoutObject* descendant = &textRoot; descendant; descendant = descendant->nextInPreOrder(&textRoot)) { |
| if (!descendant->isSVGInlineText()) |
| continue; |
| LayoutSVGInlineText* text = toLayoutSVGInlineText(descendant); |
| text->updateScaledFont(); |
| if (builder) |
| - builder->rebuildMetricsForTextLayoutObject(text); |
| + builder->rebuildMetricsForTextLayoutObject(textRoot, *text); |
| } |
| } |
| +static inline void checkLayoutAttributesConsistency(LayoutSVGText* text, Vector<SVGTextLayoutAttributes*>& expectedLayoutAttributes) |
| +{ |
| +#if ENABLE(ASSERT) |
| + Vector<SVGTextLayoutAttributes*> newLayoutAttributes; |
| + collectLayoutAttributes(text, newLayoutAttributes); |
| + ASSERT(newLayoutAttributes == expectedLayoutAttributes); |
| +#endif |
| +} |
| + |
| void LayoutSVGText::layout() |
| { |
| ASSERT(needsLayout()); |
| @@ -310,7 +210,7 @@ void LayoutSVGText::layout() |
| // and propogate resulting SVGLayoutAttributes to all LayoutSVGInlineText children in the subtree. |
| ASSERT(m_layoutAttributes.isEmpty()); |
| collectLayoutAttributes(this, m_layoutAttributes); |
| - updateFontInAllDescendants(this); |
| + updateFontInAllDescendants(*this); |
| m_layoutAttributesBuilder.buildLayoutAttributesForForSubtree(*this); |
| m_needsReordering = true; |
| @@ -321,10 +221,12 @@ void LayoutSVGText::layout() |
| // When the x/y/dx/dy/rotate lists change, recompute the layout attributes, and eventually |
| // update the on-screen font objects as well in all descendants. |
| if (m_needsTextMetricsUpdate) { |
| - updateFontInAllDescendants(this); |
| + updateFontInAllDescendants(*this); |
| m_needsTextMetricsUpdate = false; |
| } |
| + 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
|
| + collectLayoutAttributes(this, m_layoutAttributes); |
| m_layoutAttributesBuilder.buildLayoutAttributesForForSubtree(*this); |
| m_needsReordering = true; |
| m_needsPositioningValuesUpdate = false; |
| @@ -332,7 +234,7 @@ void LayoutSVGText::layout() |
| } else if (m_needsTextMetricsUpdate || SVGLayoutSupport::findTreeRootObject(this)->isLayoutSizeChanged()) { |
| // If the root layout size changed (eg. window size changes) or the transform to the root |
| // context has changed then recompute the on-screen font size. |
| - updateFontInAllDescendants(this, &m_layoutAttributesBuilder); |
| + updateFontInAllDescendants(*this, &m_layoutAttributesBuilder); |
| ASSERT(!m_needsReordering); |
| ASSERT(!m_needsPositioningValuesUpdate); |
| @@ -494,12 +396,9 @@ void LayoutSVGText::addChild(LayoutObject* child, LayoutObject* beforeChild) |
| void LayoutSVGText::removeChild(LayoutObject* child) |
| { |
| SVGResourcesCache::clientWillBeRemovedFromTree(child); |
| + subtreeChildWillBeRemoved(child); |
| - Vector<SVGTextLayoutAttributes*, 2> affectedAttributes; |
| - FontCachePurgePreventer fontCachePurgePreventer; |
| - subtreeChildWillBeRemoved(child, affectedAttributes); |
| LayoutSVGBlock::removeChild(child); |
| - subtreeChildWasRemoved(affectedAttributes); |
| } |
| void LayoutSVGText::invalidateTreeIfNeeded(const PaintInvalidationState& paintInvalidationState) |