Chromium Code Reviews| Index: third_party/WebKit/Source/core/layout/TextAutosizer.cpp |
| diff --git a/third_party/WebKit/Source/core/layout/TextAutosizer.cpp b/third_party/WebKit/Source/core/layout/TextAutosizer.cpp |
| index 44838fff84911253c0d28db3d383ab59970e5af8..d94acf78cec8d6e9c5f26a6a27f147248c958def 100644 |
| --- a/third_party/WebKit/Source/core/layout/TextAutosizer.cpp |
| +++ b/third_party/WebKit/Source/core/layout/TextAutosizer.cpp |
| @@ -295,9 +295,9 @@ TextAutosizer::TextAutosizer(const Document* document) |
| #if ENABLE(ASSERT) |
| m_blocksThatHaveBegunLayout(), |
| #endif |
| - m_superclusters(), |
| m_clusterStack(), |
| m_fingerprintMapper(), |
| + m_fingerprintsNeedCheckConsistent(), |
| m_pageInfo(), |
| m_updatePageInfoDeferred(false) { |
| } |
| @@ -329,7 +329,6 @@ void TextAutosizer::destroy(const LayoutBlock* block) { |
| // Speculative fix for http://crbug.com/369485. |
| m_firstBlockToBeginLayout = nullptr; |
| m_clusterStack.clear(); |
| - m_superclusters.clear(); |
| } |
| } |
| @@ -342,6 +341,8 @@ TextAutosizer::BeginLayoutBehavior TextAutosizer::prepareForLayout( |
| if (!m_firstBlockToBeginLayout) { |
| m_firstBlockToBeginLayout = block; |
| prepareClusterStack(block->parent()); |
| + if (block->isLayoutView()) |
| + checkConsistent(); |
| } else if (block == currentCluster()->m_root) { |
| // Ignore beginLayout on the same block twice. |
| // This can happen with paginated overflow. |
| @@ -424,11 +425,11 @@ void TextAutosizer::endLayout(LayoutBlock* block) { |
| if (block == m_firstBlockToBeginLayout) { |
| m_firstBlockToBeginLayout = nullptr; |
| m_clusterStack.clear(); |
| - m_superclusters.clear(); |
| m_stylesRetainedDuringLayout.clear(); |
| #if ENABLE(ASSERT) |
| m_blocksThatHaveBegunLayout.clear(); |
| #endif |
| + m_fingerprintsNeedCheckConsistent.clear(); |
| // Tables can create two layout scopes for the same block so the isEmpty |
| // check below is needed to guard against endLayout being called twice. |
| } else if (!m_clusterStack.isEmpty() && currentCluster()->m_root == block) { |
| @@ -512,6 +513,27 @@ bool TextAutosizer::pageNeedsAutosizing() const { |
| return m_pageInfo.m_pageNeedsAutosizing; |
| } |
| +void TextAutosizer::textAutosizingNewTextAdded(unsigned fingerprint, |
| + unsigned newAddedLen) { |
| + if (fingerprint == 0 || !shouldHandleLayout()) |
| + return; |
| + |
| + Supercluster* supercluster = |
| + m_fingerprintMapper.getSuperclusterByFingerprint(fingerprint); |
| + if (!supercluster) |
| + return; |
| + |
| + if (supercluster->m_hasEnoughTextToAutosize == NotEnoughText) { |
| + supercluster->m_containingTextlength += newAddedLen; |
| + if (!supercluster->m_hasAddedToCheckSet && |
| + supercluster->m_containingTextlength > |
| + supercluster->m_minTextLengthToAutosize) { |
| + m_fingerprintsNeedCheckConsistent.add(fingerprint); |
| + supercluster->m_hasAddedToCheckSet = true; |
| + } |
| + } |
| +} |
| + |
| void TextAutosizer::updatePageInfoInAllFrames() { |
| ASSERT(!m_document->frame() || m_document->frame()->isMainFrame()); |
| @@ -789,8 +811,8 @@ TextAutosizer::Cluster* TextAutosizer::maybeCreateCluster( |
| !!(flags & SUPPRESSING) == parentSuppresses) |
| return nullptr; |
| - Cluster* cluster = |
| - new Cluster(block, flags, parentCluster, getSupercluster(block)); |
| + Cluster* cluster = new Cluster(block, flags, parentCluster, |
| + m_fingerprintMapper.getSupercluster(block)); |
| #ifdef AUTOSIZING_DOM_DEBUG_INFO |
| // Non-SUPPRESSING clusters are annotated in clusterMultiplier. |
| if (flags & SUPPRESSING) |
| @@ -799,13 +821,13 @@ TextAutosizer::Cluster* TextAutosizer::maybeCreateCluster( |
| return cluster; |
| } |
| -TextAutosizer::Supercluster* TextAutosizer::getSupercluster( |
| +TextAutosizer::Supercluster* TextAutosizer::FingerprintMapper::getSupercluster( |
| const LayoutBlock* block) { |
| - Fingerprint fingerprint = m_fingerprintMapper.get(block); |
| + Fingerprint fingerprint = get(block); |
| if (!fingerprint) |
| return nullptr; |
| - BlockSet* roots = m_fingerprintMapper.getTentativeClusterRoots(fingerprint); |
| + BlockSet* roots = getTentativeClusterRoots(fingerprint); |
| if (!roots || roots->size() < 2 || !roots->contains(block)) |
| return nullptr; |
| @@ -819,6 +841,27 @@ TextAutosizer::Supercluster* TextAutosizer::getSupercluster( |
| return supercluster; |
| } |
| +TextAutosizer::Supercluster* |
| +TextAutosizer::FingerprintMapper::getSuperclusterByFingerprint( |
| + const Fingerprint fingerprint) { |
| + Supercluster* supercluster = nullptr; |
| + SuperclusterMap::iterator superclusterIter = |
| + m_superclusters.find(fingerprint); |
| + if (superclusterIter != m_superclusters.end()) { |
| + supercluster = superclusterIter->value.get(); |
| + } |
| + return supercluster; |
| +} |
| + |
| +bool TextAutosizer::isParentClusterReliable(Cluster* cluster) { |
| + if (!cluster) |
| + return true; |
| + // Cause cluster is changed, m_supercluster's "NotEnoughText" is not reliable |
| + // now. |
| + return !(cluster->m_supercluster && |
| + cluster->m_supercluster->m_hasEnoughTextToAutosize == NotEnoughText); |
| +} |
| + |
| float TextAutosizer::clusterMultiplier(Cluster* cluster) { |
| if (cluster->m_multiplier) |
| return cluster->m_multiplier; |
| @@ -827,7 +870,8 @@ float TextAutosizer::clusterMultiplier(Cluster* cluster) { |
| if (!(cluster->m_flags & INDEPENDENT) && isWiderOrNarrowerDescendant(cluster)) |
| cluster->m_flags |= WIDER_OR_NARROWER; |
| - if (cluster->m_flags & (INDEPENDENT | WIDER_OR_NARROWER)) { |
| + if ((cluster->m_flags & (INDEPENDENT | WIDER_OR_NARROWER)) || |
| + !isParentClusterReliable(cluster->m_parent)) { |
| if (cluster->m_supercluster) |
| cluster->m_multiplier = superclusterMultiplier(cluster); |
| else if (clusterHasEnoughTextToAutosize(cluster)) |
| @@ -850,11 +894,14 @@ float TextAutosizer::clusterMultiplier(Cluster* cluster) { |
| bool TextAutosizer::superclusterHasEnoughTextToAutosize( |
| Supercluster* supercluster, |
| - const LayoutBlock* widthProvider) { |
| + const LayoutBlock* widthProvider, |
| + const bool skipLayoutedNodes) { |
| if (supercluster->m_hasEnoughTextToAutosize != UnknownAmountOfText) |
| return supercluster->m_hasEnoughTextToAutosize == HasEnoughText; |
| for (auto* root : *supercluster->m_roots) { |
| + if (skipLayoutedNodes && !root->normalChildNeedsLayout()) |
| + continue; |
| if (clusterWouldHaveEnoughTextToAutosize(root, widthProvider)) { |
| supercluster->m_hasEnoughTextToAutosize = HasEnoughText; |
| return true; |
| @@ -869,8 +916,9 @@ float TextAutosizer::superclusterMultiplier(Cluster* cluster) { |
| if (!supercluster->m_multiplier) { |
| const LayoutBlock* widthProvider = |
| maxClusterWidthProvider(cluster->m_supercluster, cluster->m_root); |
| + RELEASE_ASSERT(widthProvider); |
| supercluster->m_multiplier = |
| - superclusterHasEnoughTextToAutosize(supercluster, widthProvider) |
| + superclusterHasEnoughTextToAutosize(supercluster, widthProvider, false) |
| ? multiplierFromBlock(widthProvider) |
| : 1.0f; |
| } |
| @@ -887,10 +935,15 @@ const LayoutBlock* TextAutosizer::clusterWidthProvider( |
| } |
| const LayoutBlock* TextAutosizer::maxClusterWidthProvider( |
| - const Supercluster* supercluster, |
| + Supercluster* supercluster, |
| const LayoutBlock* currentRoot) const { |
| - const LayoutBlock* result = clusterWidthProvider(currentRoot); |
| - float maxWidth = widthFromBlock(result); |
| + const LayoutBlock* result = nullptr; |
| + if (currentRoot) |
| + result = clusterWidthProvider(currentRoot); |
| + |
| + float maxWidth = 0; |
| + if (result) |
| + maxWidth = widthFromBlock(result); |
| const BlockSet* roots = supercluster->m_roots; |
| for (const auto* root : *roots) { |
| @@ -903,7 +956,12 @@ const LayoutBlock* TextAutosizer::maxClusterWidthProvider( |
| result = widthProvider; |
| } |
| } |
| - RELEASE_ASSERT(result); |
| + |
| + if (result && result->style() && result->style()->specifiedFontSize() > 0) { |
| + supercluster->m_minTextLengthToAutosize = |
| + maxWidth * 4 / result->style()->specifiedFontSize(); |
|
skobes
2016/11/09 03:11:39
This is duplicating logic in TextAutosizer::cluste
cathiechentx
2016/11/09 12:58:46
There is a subtle distinction between them. m_minT
|
| + } |
| + |
| return result; |
| } |
| @@ -1186,6 +1244,7 @@ void TextAutosizer::FingerprintMapper::addTentativeClusterRoot( |
| if (addResult.isNewEntry) |
| addResult.storedValue->value = wrapUnique(new BlockSet); |
| addResult.storedValue->value->add(block); |
| + block->mutableStyle()->setTextAutosizingFingerPrint(fingerprint); |
| #if ENABLE(ASSERT) |
| assertMapsAreConsistent(); |
| #endif |
| @@ -1204,8 +1263,14 @@ bool TextAutosizer::FingerprintMapper::remove( |
| BlockSet& blocks = *blocksIter->value; |
| blocks.remove(toLayoutBlock(layoutObject)); |
| - if (blocks.isEmpty()) |
| + if (blocks.isEmpty()) { |
| m_blocksForFingerprint.remove(blocksIter); |
| + |
| + SuperclusterMap::iterator superclusterIter = |
| + m_superclusters.find(fingerprint); |
| + if (superclusterIter != m_superclusters.end()) |
| + m_superclusters.remove(superclusterIter); |
| + } |
| #if ENABLE(ASSERT) |
| assertMapsAreConsistent(); |
| #endif |
| @@ -1297,6 +1362,61 @@ float TextAutosizer::computeAutosizedFontSize(float specifiedSize, |
| return computedSize; |
| } |
| +void setAllTextInsideContainerNeedsLayout(LayoutBlock* container) { |
| + DCHECK(container); |
| + LayoutObject* layoutObject = container; |
| + while (layoutObject) { |
| + if (layoutObject->isText()) { |
| + layoutObject->setNeedsLayoutAndFullPaintInvalidation( |
| + LayoutInvalidationReason::TextAutosizing); |
| + } |
| + layoutObject = layoutObject->nextInPreOrder(container); |
| + } |
| +} |
| + |
| +void TextAutosizer::checkConsistent() { |
| + if (m_fingerprintsNeedCheckConsistent.isEmpty()) |
| + return; |
| + |
| + FingerprintSet::iterator end = m_fingerprintsNeedCheckConsistent.end(); |
| + for (FingerprintSet::iterator it = m_fingerprintsNeedCheckConsistent.begin(); |
| + it != end; ++it) { |
| + const Fingerprint fingerprint = *it; |
| + Supercluster* supercluster = |
| + m_fingerprintMapper.getSuperclusterByFingerprint(fingerprint); |
| + if (!supercluster) |
| + continue; |
| + |
| + supercluster->m_hasAddedToCheckSet = false; |
| + if (NotEnoughText != supercluster->m_hasEnoughTextToAutosize) |
| + continue; |
| + |
| + float oldMultipiler = supercluster->m_multiplier; |
| + supercluster->m_multiplier = 0; |
| + supercluster->m_hasEnoughTextToAutosize = UnknownAmountOfText; |
| + const LayoutBlock* widthProvider = |
| + maxClusterWidthProvider(supercluster, nullptr); |
| + if (!widthProvider) |
| + continue; |
| + |
| + superclusterHasEnoughTextToAutosize(supercluster, widthProvider, true); |
| + |
| + if (HasEnoughText == supercluster->m_hasEnoughTextToAutosize) { |
| + LayoutBlock* block = nullptr; |
| + for (auto* root : *supercluster->m_roots) { |
| + if (root->normalChildNeedsLayout()) |
| + continue; |
| + |
| + block = const_cast<LayoutBlock*>(root); |
|
skobes
2016/11/09 03:11:39
Remove const from the BlockSet typedef instead of
cathiechentx
2016/11/09 12:58:46
Done.
|
| + DCHECK(block); |
| + setAllTextInsideContainerNeedsLayout(block); |
| + } |
| + } else { |
| + supercluster->m_multiplier = oldMultipiler; |
| + } |
| + } |
| +} |
| + |
| DEFINE_TRACE(TextAutosizer) { |
| visitor->trace(m_document); |
| } |