| Index: Source/WebCore/rendering/TextAutosizer.cpp
|
| ===================================================================
|
| --- Source/WebCore/rendering/TextAutosizer.cpp (revision 139472)
|
| +++ Source/WebCore/rendering/TextAutosizer.cpp (working copy)
|
| @@ -26,6 +26,7 @@
|
|
|
| #include "Document.h"
|
| #include "InspectorInstrumentation.h"
|
| +#include "IntSize.h"
|
| #include "RenderObject.h"
|
| #include "RenderStyle.h"
|
| #include "RenderText.h"
|
| @@ -85,7 +86,7 @@
|
| container = container->containingBlock();
|
|
|
| RenderBlock* cluster = container;
|
| - while (cluster && (!isAutosizingContainer(cluster) || !isAutosizingCluster(cluster)))
|
| + while (cluster && !isAutosizingCluster(cluster))
|
| cluster = cluster->containingBlock();
|
|
|
| processCluster(cluster, container, layoutRoot, windowInfo);
|
| @@ -94,36 +95,34 @@
|
|
|
| void TextAutosizer::processCluster(RenderBlock* cluster, RenderBlock* container, RenderObject* subtreeRoot, const TextAutosizingWindowInfo& windowInfo)
|
| {
|
| - ASSERT(isAutosizingCluster(cluster));
|
| -
|
| // Many pages set a max-width on their content. So especially for the
|
| // RenderView, instead of just taking the width of |cluster| we find
|
| // the lowest common ancestor of the first and last descendant text node of
|
| // the cluster (i.e. the deepest wrapper block that contains all the text),
|
| // and use its width instead.
|
| - const RenderBlock* lowestCommonAncestor = findDeepestBlockContainingAllText(cluster);
|
| - float commonAncestorWidth = lowestCommonAncestor->contentLogicalWidth();
|
| + const RenderBlock* blockContainingAllText = findDeepestBlockContainingAllText(cluster);
|
| + float textWidth = blockContainingAllText->contentLogicalWidth();
|
|
|
| float multiplier = 1;
|
| - if (clusterShouldBeAutosized(lowestCommonAncestor, commonAncestorWidth)) {
|
| + if (clusterShouldBeAutosized(blockContainingAllText, textWidth)) {
|
| int logicalWindowWidth = cluster->isHorizontalWritingMode() ? windowInfo.windowSize.width() : windowInfo.windowSize.height();
|
| int logicalLayoutWidth = cluster->isHorizontalWritingMode() ? windowInfo.minLayoutSize.width() : windowInfo.minLayoutSize.height();
|
| // Ignore box width in excess of the layout width, to avoid extreme multipliers.
|
| - float logicalClusterWidth = std::min<float>(commonAncestorWidth, logicalLayoutWidth);
|
| + float logicalClusterWidth = std::min<float>(textWidth, logicalLayoutWidth);
|
|
|
| multiplier = logicalClusterWidth / logicalWindowWidth;
|
| multiplier *= m_document->settings()->textAutosizingFontScaleFactor();
|
| multiplier = std::max(1.0f, multiplier);
|
| }
|
|
|
| - processContainer(multiplier, container, subtreeRoot, windowInfo);
|
| + processContainer(multiplier, container, blockContainingAllText, subtreeRoot, windowInfo);
|
| }
|
|
|
| -void TextAutosizer::processContainer(float multiplier, RenderBlock* container, RenderObject* subtreeRoot, const TextAutosizingWindowInfo& windowInfo)
|
| +void TextAutosizer::processContainer(float multiplier, RenderBlock* container, const RenderBlock* blockContainingAllText, RenderObject* subtreeRoot, const TextAutosizingWindowInfo& windowInfo)
|
| {
|
| ASSERT(isAutosizingContainer(container));
|
|
|
| - float localMultiplier = containerShouldbeAutosized(container) ? multiplier: 1;
|
| + float localMultiplier = containerShouldBeAutosized(container) ? multiplier: 1;
|
|
|
| RenderObject* descendant = nextInPreOrderSkippingDescendantsOfContainers(subtreeRoot, subtreeRoot);
|
| while (descendant) {
|
| @@ -135,10 +134,10 @@
|
| // FIXME: Increase list marker size proportionately.
|
| } else if (isAutosizingContainer(descendant)) {
|
| RenderBlock* descendantBlock = toRenderBlock(descendant);
|
| - if (isAutosizingCluster(descendantBlock))
|
| + if (isAutosizingCluster(descendantBlock, blockContainingAllText))
|
| processCluster(descendantBlock, descendantBlock, descendantBlock, windowInfo);
|
| else
|
| - processContainer(multiplier, descendantBlock, descendantBlock, windowInfo);
|
| + processContainer(multiplier, descendantBlock, blockContainingAllText, descendantBlock, windowInfo);
|
| }
|
| descendant = nextInPreOrderSkippingDescendantsOfContainers(descendant, subtreeRoot);
|
| }
|
| @@ -196,14 +195,14 @@
|
| return true;
|
| }
|
|
|
| -bool TextAutosizer::isAutosizingCluster(const RenderBlock* renderer)
|
| +bool TextAutosizer::isAutosizingCluster(const RenderBlock* renderer, const RenderBlock* parentBlockContainingAllText)
|
| {
|
| // "Autosizing clusters" are special autosizing containers within which we
|
| // want to enforce a uniform text size multiplier, in the hopes of making
|
| // the major sections of the page look internally consistent.
|
| - // All their descendents (including other autosizing containers) must share
|
| + // All their descendants (including other autosizing containers) must share
|
| // the same multiplier, except for subtrees which are themselves clusters,
|
| - // and some of their descendent containers might not be autosized at all
|
| + // and some of their descendant containers might not be autosized at all
|
| // (for example if their height is constrained).
|
| // Additionally, clusterShouldBeAutosized requires each cluster to contain a
|
| // minimum amount of text, without which it won't be autosized.
|
| @@ -212,11 +211,14 @@
|
| // block formatting contexts (http://w3.org/TR/css3-box/#flow-root), since
|
| // flow roots correspond to box containers that behave somewhat
|
| // independently from their parent (for example they don't overlap floats).
|
| - // The definition of a flow flow root also conveniently includes most of the
|
| + // The definition of a flow root also conveniently includes most of the
|
| // ways that a box and its children can have significantly different width
|
| // from the box's parent (we want to avoid having significantly different
|
| // width blocks within a cluster, since the narrower blocks would end up
|
| // larger than would otherwise be necessary).
|
| + // Additionally, any containers that are wider than the |blockContainingAllText|
|
| + // of their enclosing cluster also become clusters, since they need special
|
| + // treatment due to their width.
|
| ASSERT(isAutosizingContainer(renderer));
|
|
|
| return renderer->isRenderView()
|
| @@ -227,12 +229,19 @@
|
| || renderer->isFlexibleBoxIncludingDeprecated()
|
| || renderer->hasColumns()
|
| || renderer->containingBlock()->isHorizontalWritingMode() != renderer->isHorizontalWritingMode()
|
| - || renderer->style()->isDisplayReplacedType();
|
| + || renderer->style()->isDisplayReplacedType()
|
| + || (parentBlockContainingAllText
|
| + && renderer->contentLogicalWidth() > parentBlockContainingAllText->contentLogicalWidth());
|
| // FIXME: Tables need special handling to multiply all their columns by
|
| // the same amount even if they're different widths; so do hasColumns()
|
| // containers, and probably flexboxes...
|
| }
|
|
|
| +bool TextAutosizer::isAutosizingCluster(const RenderObject* object)
|
| +{
|
| + return isAutosizingContainer(object) && isAutosizingCluster(toRenderBlock(object), 0);
|
| +}
|
| +
|
| static bool contentHeightIsConstrained(const RenderBlock* container)
|
| {
|
| // FIXME: Propagate constrainedness down the tree, to avoid inefficiently walking back up from each box.
|
| @@ -253,7 +262,7 @@
|
| return false;
|
| }
|
|
|
| -bool TextAutosizer::containerShouldbeAutosized(const RenderBlock* container)
|
| +bool TextAutosizer::containerShouldBeAutosized(const RenderBlock* container)
|
| {
|
| // Don't autosize block-level text that can't wrap (as it's likely to
|
| // expand sideways and break the page's layout).
|
| @@ -263,7 +272,7 @@
|
| return !contentHeightIsConstrained(container);
|
| }
|
|
|
| -bool TextAutosizer::clusterShouldBeAutosized(const RenderBlock* lowestCommonAncestor, float commonAncestorWidth)
|
| +bool TextAutosizer::clusterShouldBeAutosized(const RenderBlock* blockContainingAllText, float blockWidth)
|
| {
|
| // Don't autosize clusters that contain less than 4 lines of text (in
|
| // practice less lines are required, since measureDescendantTextWidth
|
| @@ -276,17 +285,17 @@
|
| // in and pan from side to side to read each line, since if there are very
|
| // few lines of text you'll only need to pan across once or twice.
|
| const float minLinesOfText = 4;
|
| - float minTextWidth = commonAncestorWidth * minLinesOfText;
|
| + float minTextWidth = blockWidth * minLinesOfText;
|
| float textWidth = 0;
|
| - measureDescendantTextWidth(lowestCommonAncestor, minTextWidth, textWidth);
|
| + measureDescendantTextWidth(blockContainingAllText, blockContainingAllText, minTextWidth, textWidth);
|
| if (textWidth >= minTextWidth)
|
| return true;
|
| return false;
|
| }
|
|
|
| -void TextAutosizer::measureDescendantTextWidth(const RenderBlock* container, float minTextWidth, float& textWidth)
|
| +void TextAutosizer::measureDescendantTextWidth(const RenderBlock* container, const RenderBlock* blockContainingAllText, float minTextWidth, float& textWidth)
|
| {
|
| - bool skipLocalText = !containerShouldbeAutosized(container);
|
| + bool skipLocalText = !containerShouldBeAutosized(container);
|
|
|
| RenderObject* descendant = nextInPreOrderSkippingDescendantsOfContainers(container, container);
|
| while (descendant) {
|
| @@ -294,8 +303,8 @@
|
| textWidth += toRenderText(descendant)->renderedTextLength() * descendant->style()->specifiedFontSize();
|
| } else if (isAutosizingContainer(descendant)) {
|
| RenderBlock* descendantBlock = toRenderBlock(descendant);
|
| - if (!isAutosizingCluster(descendantBlock))
|
| - measureDescendantTextWidth(descendantBlock, minTextWidth, textWidth);
|
| + if (!isAutosizingCluster(descendantBlock, blockContainingAllText))
|
| + measureDescendantTextWidth(descendantBlock, blockContainingAllText, minTextWidth, textWidth);
|
| }
|
| if (textWidth >= minTextWidth)
|
| return;
|
| @@ -321,8 +330,6 @@
|
|
|
| const RenderBlock* TextAutosizer::findDeepestBlockContainingAllText(const RenderBlock* cluster)
|
| {
|
| - ASSERT(isAutosizingCluster(cluster));
|
| -
|
| size_t firstDepth = 0;
|
| const RenderObject* firstTextLeaf = findFirstTextLeafNotInCluster(cluster, firstDepth, FirstToLast);
|
| if (!firstTextLeaf)
|
| @@ -371,7 +378,7 @@
|
| ++depth;
|
| const RenderObject* child = (direction == FirstToLast) ? parent->firstChild() : parent->lastChild();
|
| while (child) {
|
| - if (!isAutosizingContainer(child) || !isAutosizingCluster(toRenderBlock(child))) {
|
| + if (!isAutosizingCluster(child)) {
|
| const RenderObject* leaf = findFirstTextLeafNotInCluster(child, depth, direction);
|
| if (leaf)
|
| return leaf;
|
|
|