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..47325aedfbcccb62cf6529cea86789d6beb46080 100644 |
--- a/third_party/WebKit/Source/core/layout/TextAutosizer.cpp |
+++ b/third_party/WebKit/Source/core/layout/TextAutosizer.cpp |
@@ -88,7 +88,8 @@ void TextAutosizer::writeClusterDebugInfo(Cluster* cluster) { |
String explanation = ""; |
if (cluster->m_flags & SUPPRESSING) { |
explanation = "[suppressed]"; |
- } else if (!(cluster->m_flags & (INDEPENDENT | WIDER_OR_NARROWER))) { |
+ } else if ((!(cluster->m_flags & (INDEPENDENT | WIDER_OR_NARROWER))) && |
+ isParentClusterReliable(cluster->m_parent)) { |
explanation = "[inherited]"; |
} else if (cluster->m_supercluster) { |
explanation = "[supercluster]"; |
@@ -123,7 +124,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,29 +296,32 @@ 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; |
ASSERT(!m_blocksThatHaveBegunLayout.contains(block)); |
- |
- if (!classifyBlock(block, INDEPENDENT | EXPLICIT_WIDTH)) |
+ if (!classifyBlock(block, INDEPENDENT | EXPLICIT_WIDTH)) { |
+ newNodeAdded(block); |
pdr.
2016/11/20 06:38:13
Are these calls (newNodeAdded and needCheckConsist
cathiechentx
2016/11/22 08:14:47
Yes, it's necessary. Here is to find the nearest-c
|
return; |
+ } |
if (Fingerprint fingerprint = computeFingerprint(block)) |
m_fingerprintMapper.addTentativeClusterRoot(block, fingerprint); |
+ |
+ needCheckConsistent(block); |
cathiechentx
2016/11/22 08:14:48
Add block to hashset. So block's children don't ha
|
} |
-void TextAutosizer::destroy(const LayoutBlock* block) { |
+void TextAutosizer::destroy(LayoutBlock* block) { |
if (!m_pageInfo.m_settingEnabled && !m_fingerprintMapper.hasFingerprints()) |
return; |
@@ -329,12 +333,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 +345,8 @@ TextAutosizer::BeginLayoutBehavior TextAutosizer::prepareForLayout( |
if (!m_firstBlockToBeginLayout) { |
m_firstBlockToBeginLayout = block; |
prepareClusterStack(block->parent()); |
+ if (block->isLayoutView()) |
pdr.
2016/11/20 06:38:13
Is this isLayoutView check needed?
cathiechentx
2016/11/22 08:14:48
Yes, it is necessary. CheckConsistent might change
|
+ checkConsistent(); |
} else if (block == currentCluster()->m_root) { |
// Ignore beginLayout on the same block twice. |
// This can happen with paginated overflow. |
@@ -351,13 +356,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 +429,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 +517,65 @@ bool TextAutosizer::pageNeedsAutosizing() const { |
return m_pageInfo.m_pageNeedsAutosizing; |
} |
+void TextAutosizer::newNodeAdded(LayoutObject* object) { |
+ if (!object || !shouldHandleLayout()) |
+ return; |
+ |
+ LayoutObject* parent = object->parent(); |
+ // Sometimes layoutObject haven't added to layout tree yet |
+ if (!parent && object->node() && object->node()->parentNode()) |
+ parent = object->node()->parentNode()->layoutObject(); |
+ // !everHadLayout() means the object hasn't layout yet |
+ // which means this object is new added. If parent is new added, |
+ // no need to checkConsistent its children |
+ if (!parent || !parent->everHadLayout()) |
cathiechentx
2016/11/22 08:14:47
The descendants of a new node will return from her
|
+ return; |
+ |
+ // Find the nearest LayoutBlock. |
+ LayoutBlock* block = nullptr; |
+ if (object->isLayoutBlock()) { |
+ // Only deal with the !everHadLayout LayoutBlock |
+ if (object->everHadLayout()) |
+ return; |
+ block = toLayoutBlock(object); |
+ } else { |
+ if (parent->isLayoutBlock()) |
+ block = toLayoutBlock(parent); |
+ else |
+ block = parent->containingBlock(); |
+ } |
+ if (!block) |
+ return; |
+ |
+ // Find the nearest block which choud be a cluster root |
+ while (block && !block->isTableCell() && |
+ !classifyBlock(block, INDEPENDENT | EXPLICIT_WIDTH)) { |
+ if (!block->parent()) |
+ return; |
+ if (block->parent()->isLayoutBlock()) |
+ block = toLayoutBlock(block->parent()); |
+ else |
+ block = block->containingBlock(); |
+ } |
+ if (!block) |
+ return; |
+ |
+ needCheckConsistent(block); |
+} |
+ |
+void TextAutosizer::needCheckConsistent(LayoutBlock* block) { |
+ if (!block || !shouldHandleLayout()) |
+ return; |
+ |
+ if (Fingerprint fingerprint = computeFingerprint(block)) { |
+ // If the supercluster hasn't be created yet, create the supercluster. |
+ Supercluster* supercluster = m_fingerprintMapper.getSupercluster(block); |
+ if (supercluster && |
+ supercluster->m_hasEnoughTextToAutosize != HasEnoughText) |
+ m_fingerprintsNeedCheckConsistent.add(fingerprint); |
pdr.
2016/11/20 06:38:13
Instead of storing a set of fingerprints, could we
cathiechentx
2016/11/22 08:14:48
Done.
|
+ } |
+} |
+ |
void TextAutosizer::updatePageInfoInAllFrames() { |
ASSERT(!m_document->frame() || m_document->frame()->isMainFrame()); |
@@ -723,7 +787,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 +803,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 = |
@@ -771,8 +835,7 @@ TextAutosizer::Fingerprint TextAutosizer::computeFingerprint( |
sizeof data / sizeof(UChar)); |
} |
-TextAutosizer::Cluster* TextAutosizer::maybeCreateCluster( |
- const LayoutBlock* block) { |
+TextAutosizer::Cluster* TextAutosizer::maybeCreateCluster(LayoutBlock* block) { |
BlockFlags flags = classifyBlock(block); |
if (!(flags & POTENTIAL_ROOT)) |
return nullptr; |
@@ -789,8 +852,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 +862,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 +882,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 +911,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 +935,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 +957,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 +976,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 +997,6 @@ const LayoutBlock* TextAutosizer::maxClusterWidthProvider( |
result = widthProvider; |
} |
} |
- RELEASE_ASSERT(result); |
return result; |
} |
@@ -1166,7 +1259,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 +1270,7 @@ void TextAutosizer::FingerprintMapper::add(const LayoutObject* layoutObject, |
} |
void TextAutosizer::FingerprintMapper::addTentativeClusterRoot( |
- const LayoutBlock* block, |
+ LayoutBlock* block, |
Fingerprint fingerprint) { |
add(block, fingerprint); |
@@ -1191,8 +1284,7 @@ void TextAutosizer::FingerprintMapper::addTentativeClusterRoot( |
#endif |
} |
-bool TextAutosizer::FingerprintMapper::remove( |
- const LayoutObject* layoutObject) { |
+bool TextAutosizer::FingerprintMapper::remove(LayoutObject* layoutObject) { |
Fingerprint fingerprint = m_fingerprints.take(layoutObject); |
if (!fingerprint || !layoutObject->isLayoutBlock()) |
return false; |
@@ -1204,8 +1296,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 +1395,58 @@ 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; |
+ |
+ if (HasEnoughText == 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); |
} |