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

Unified Diff: third_party/WebKit/Source/core/layout/TextAutosizer.cpp

Issue 2299213003: Fix the inconsistent problem while the content of textNodes is changed (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: add layout test cases and fix format issues Created 4 years, 1 month 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 side-by-side diff with in-line comments
Download patch
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);
}

Powered by Google App Engine
This is Rietveld 408576698