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); |
} |