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