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

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: 1. change 'FingerPrint' to 'Fingerprint' 2. remove const from BlockSet 3. change 'textAutosizingNew… 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..28097be9bf9f2776cfdcd9d687b5664434bae82e 100644
--- a/third_party/WebKit/Source/core/layout/TextAutosizer.cpp
+++ b/third_party/WebKit/Source/core/layout/TextAutosizer.cpp
@@ -123,7 +123,7 @@ void TextAutosizer::writeClusterDebugInfo(Cluster* cluster) {
}
#endif
-static const LayoutObject* parentElementLayoutObject(
+static LayoutObject* parentElementLayoutObject(
const LayoutObject* layoutObject) {
// At style recalc, the layoutObject's parent may not be attached,
// so we need to obtain this from the DOM tree.
@@ -295,16 +295,16 @@ TextAutosizer::TextAutosizer(const Document* document)
#if ENABLE(ASSERT)
m_blocksThatHaveBegunLayout(),
#endif
- m_superclusters(),
m_clusterStack(),
m_fingerprintMapper(),
+ m_fingerprintsNeedCheckConsistent(),
m_pageInfo(),
m_updatePageInfoDeferred(false) {
}
TextAutosizer::~TextAutosizer() {}
-void TextAutosizer::record(const LayoutBlock* block) {
+void TextAutosizer::record(LayoutBlock* block) {
if (!m_pageInfo.m_settingEnabled)
return;
@@ -317,7 +317,7 @@ void TextAutosizer::record(const LayoutBlock* block) {
m_fingerprintMapper.addTentativeClusterRoot(block, fingerprint);
}
-void TextAutosizer::destroy(const LayoutBlock* block) {
+void TextAutosizer::destroy(LayoutBlock* block) {
if (!m_pageInfo.m_settingEnabled && !m_fingerprintMapper.hasFingerprints())
return;
@@ -329,12 +329,11 @@ void TextAutosizer::destroy(const LayoutBlock* block) {
// Speculative fix for http://crbug.com/369485.
m_firstBlockToBeginLayout = nullptr;
m_clusterStack.clear();
- m_superclusters.clear();
}
}
TextAutosizer::BeginLayoutBehavior TextAutosizer::prepareForLayout(
- const LayoutBlock* block) {
+ LayoutBlock* block) {
#if ENABLE(ASSERT)
m_blocksThatHaveBegunLayout.add(block);
#endif
@@ -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.
@@ -351,13 +352,13 @@ TextAutosizer::BeginLayoutBehavior TextAutosizer::prepareForLayout(
return ContinueLayout;
}
-void TextAutosizer::prepareClusterStack(const LayoutObject* layoutObject) {
+void TextAutosizer::prepareClusterStack(LayoutObject* layoutObject) {
if (!layoutObject)
return;
prepareClusterStack(layoutObject->parent());
if (layoutObject->isLayoutBlock()) {
- const LayoutBlock* block = toLayoutBlock(layoutObject);
+ LayoutBlock* block = toLayoutBlock(layoutObject);
#if ENABLE(ASSERT)
m_blocksThatHaveBegunLayout.add(block);
#endif
@@ -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::newTextAdded(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());
@@ -723,7 +745,7 @@ bool TextAutosizer::clusterHasEnoughTextToAutosize(
}
TextAutosizer::Fingerprint TextAutosizer::getFingerprint(
- const LayoutObject* layoutObject) {
+ LayoutObject* layoutObject) {
Fingerprint result = m_fingerprintMapper.get(layoutObject);
if (!result) {
result = computeFingerprint(layoutObject);
@@ -739,7 +761,7 @@ TextAutosizer::Fingerprint TextAutosizer::computeFingerprint(
return 0;
FingerprintSourceData data;
- if (const LayoutObject* parent = parentElementLayoutObject(layoutObject))
+ if (LayoutObject* parent = parentElementLayoutObject(layoutObject))
data.m_parentHash = getFingerprint(parent);
data.m_qualifiedNameHash =
@@ -772,7 +794,7 @@ TextAutosizer::Fingerprint TextAutosizer::computeFingerprint(
}
TextAutosizer::Cluster* TextAutosizer::maybeCreateCluster(
- const LayoutBlock* block) {
+ LayoutBlock* block) {
BlockFlags flags = classifyBlock(block);
if (!(flags & POTENTIAL_ROOT))
return nullptr;
@@ -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(
- const LayoutBlock* block) {
- Fingerprint fingerprint = m_fingerprintMapper.get(block);
+TextAutosizer::Supercluster* TextAutosizer::FingerprintMapper::getSupercluster(
+ LayoutBlock* 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();
+ }
+
return result;
}
@@ -1166,7 +1224,7 @@ void TextAutosizer::FingerprintMapper::assertMapsAreConsistent() {
}
#endif
-void TextAutosizer::FingerprintMapper::add(const LayoutObject* layoutObject,
+void TextAutosizer::FingerprintMapper::add(LayoutObject* layoutObject,
Fingerprint fingerprint) {
remove(layoutObject);
@@ -1177,7 +1235,7 @@ void TextAutosizer::FingerprintMapper::add(const LayoutObject* layoutObject,
}
void TextAutosizer::FingerprintMapper::addTentativeClusterRoot(
- const LayoutBlock* block,
+ LayoutBlock* block,
Fingerprint fingerprint) {
add(block, fingerprint);
@@ -1186,13 +1244,14 @@ 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
}
bool TextAutosizer::FingerprintMapper::remove(
- const LayoutObject* layoutObject) {
+ LayoutObject* layoutObject) {
Fingerprint fingerprint = m_fingerprints.take(layoutObject);
if (!fingerprint || !layoutObject->isLayoutBlock())
return false;
@@ -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,59 @@ 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) {
+ for (auto* root : *supercluster->m_roots) {
+ if (root->normalChildNeedsLayout())
+ continue;
+
+ DCHECK(root);
+ setAllTextInsideContainerNeedsLayout(root);
+ }
+ } else {
+ supercluster->m_multiplier = oldMultipiler;
+ }
+ }
+}
+
DEFINE_TRACE(TextAutosizer) {
visitor->trace(m_document);
}

Powered by Google App Engine
This is Rietveld 408576698