[Text Autosizing] Process narrow descendants with the same multiplier for the font...
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 14 Feb 2013 12:09:18 +0000 (12:09 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 14 Feb 2013 12:09:18 +0000 (12:09 +0000)
https://bugs.webkit.org/show_bug.cgi?id=109573

Source/WebCore:

Patch by Anton Vayvod <avayvod@chromium.org> on 2013-02-14
Reviewed by Julien Chaffraix.

Combine narrow descendants of the same autosizing cluster into a group that is autosized
with the same multiplier.

For example, on sites with a sidebar, sometimes the paragraphs next to the sidebar will have
a large margin individually applied (via a CSS selector), causing them all to individually
appear narrower than their enclosing blockContainingAllText. Rather than making each of
these paragraphs into a separate cluster, we want them all to share the same multiplier, as
if they were a single cluster.

Test: fast/text-autosizing/narrow-descendants-combined.html

* rendering/TextAutosizer.cpp:
(WebCore::TextAutosizer::processClusterInternal):

    Common implementation for processCluster() and processCompositeCluster that accepts the
    text width and whether the cluster should be autosized as parameters instead of
    calculating it inline.

(WebCore::TextAutosizer::processCluster):

    Calculates the text width for a single cluster and whether it should be autosized, then
    calls processClusterInternal() to apply the multiplier and process the cluster's
    descendants.

(WebCore::TextAutosizer::processCompositeCluster):

    Calculates the text width for a group of renderers and if the group should be autosized,
    then calls processClusterInternal() repeatedly with the same multiplier to apply it and
    process all the descendants of the group.

(WebCore::TextAutosizer::clusterShouldBeAutosized):

    Calls the multiple renderers version to avoid code duplication.

(WebCore::TextAutosizer::compositeClusterShouldBeAutosized):

    The multiple renderers version of clusterShouldBeAutosized.

* rendering/TextAutosizer.h:

    Updated method declarations.

LayoutTests:

Test to verify that all narrow descendants of a cluster are autosized with the same
multiplier.

Patch by Anton Vayvod <avayvod@chromium.org> on 2013-02-14
Reviewed by Julien Chaffraix.

* fast/text-autosizing/narrow-descendants-combined-expected.html: Added.
* fast/text-autosizing/narrow-descendants-combined.html: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@142866 268f45cc-cd09-0410-ab3c-d52691b4dbfc

LayoutTests/ChangeLog
LayoutTests/fast/text-autosizing/narrow-descendants-combined-expected.html [new file with mode: 0644]
LayoutTests/fast/text-autosizing/narrow-descendants-combined.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/rendering/TextAutosizer.cpp
Source/WebCore/rendering/TextAutosizer.h

index 1f1f3ce..c8b27a0 100644 (file)
@@ -1,3 +1,16 @@
+2013-02-14  Anton Vayvod  <avayvod@chromium.org>
+
+        [Text Autosizing] Process narrow descendants with the same multiplier for the font size.
+        https://bugs.webkit.org/show_bug.cgi?id=109573
+
+        Test to verify that all narrow descendants of a cluster are autosized with the same
+        multiplier.
+
+        Reviewed by Julien Chaffraix.
+
+        * fast/text-autosizing/narrow-descendants-combined-expected.html: Added.
+        * fast/text-autosizing/narrow-descendants-combined.html: Added.
+
 2013-02-14  Aivo Paas  <aivopaas@gmail.com>
 
         Updating mouse cursor on style changes without emitting fake mousemove event
diff --git a/LayoutTests/fast/text-autosizing/narrow-descendants-combined-expected.html b/LayoutTests/fast/text-autosizing/narrow-descendants-combined-expected.html
new file mode 100644 (file)
index 0000000..48fc24b
--- /dev/null
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html>
+<head>
+
+<meta name="viewport" content="width=800">
+<style>
+html { font-size: 16px; }
+body { width: 800px; margin: 0; overflow-y: hidden; }
+</style>
+
+</head>
+<body>
+
+<div style="font-size: 1.25rem">
+    <div style="width: 320px">
+        This text should be autosized to 20px computed font-size as it is combined with its narrow siblings and the maximum width is 400px.
+    </div>
+    <div style="width: 400px">
+        This text should be autosized to 20px computed font-size as it is combined with its narrow siblings and the maximum width is 400px.
+    </div>
+    <div style="width: 240px">
+        This text should be autosized to 20px computed font-size as it is combined with its narrow siblings and the maximum width is 400px.
+    </div>
+</div>
+
+</body>
+</html>
diff --git a/LayoutTests/fast/text-autosizing/narrow-descendants-combined.html b/LayoutTests/fast/text-autosizing/narrow-descendants-combined.html
new file mode 100644 (file)
index 0000000..5aac36b
--- /dev/null
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html>
+<head>
+
+<meta name="viewport" content="width=800">
+<style>
+html { font-size: 16px; }
+body { width: 800px; margin: 0; overflow-y: hidden; }
+</style>
+
+<script>
+if (window.internals) {
+    window.internals.settings.setTextAutosizingEnabled(true);
+    window.internals.settings.setTextAutosizingWindowSizeOverride(320, 480);
+} else if (window.console && console.warn) {
+    console.warn("This test depends on the Text Autosizing setting being true, so run it in DumpRenderTree, or manually enable Text Autosizing, and either use a mobile device with 320px device-width (like Nexus S or iPhone), or define HACK_FORCE_TEXT_AUTOSIZING_ON_DESKTOP.");
+}
+</script>
+
+</head>
+<body>
+
+<div>
+    <div style="width: 320px">
+        This text should be autosized to 20px computed font-size as it is combined with its narrow siblings and the maximum width is 400px.
+    </div>
+    <div style="width: 400px">
+        This text should be autosized to 20px computed font-size as it is combined with its narrow siblings and the maximum width is 400px.
+    </div>
+    <div style="width: 240px">
+        This text should be autosized to 20px computed font-size as it is combined with its narrow siblings and the maximum width is 400px.
+    </div>
+</div>
+
+</body>
+</html>
index 3001a59..9289308 100644 (file)
@@ -1,3 +1,52 @@
+2013-02-14  Anton Vayvod  <avayvod@chromium.org>
+
+        [Text Autosizing] Process narrow descendants with the same multiplier for the font size.
+        https://bugs.webkit.org/show_bug.cgi?id=109573
+
+        Reviewed by Julien Chaffraix.
+
+        Combine narrow descendants of the same autosizing cluster into a group that is autosized
+        with the same multiplier.
+
+        For example, on sites with a sidebar, sometimes the paragraphs next to the sidebar will have
+        a large margin individually applied (via a CSS selector), causing them all to individually
+        appear narrower than their enclosing blockContainingAllText. Rather than making each of
+        these paragraphs into a separate cluster, we want them all to share the same multiplier, as
+        if they were a single cluster.
+
+        Test: fast/text-autosizing/narrow-descendants-combined.html
+
+        * rendering/TextAutosizer.cpp:
+        (WebCore::TextAutosizer::processClusterInternal):
+
+            Common implementation for processCluster() and processCompositeCluster that accepts the
+            text width and whether the cluster should be autosized as parameters instead of
+            calculating it inline.
+
+        (WebCore::TextAutosizer::processCluster):
+
+            Calculates the text width for a single cluster and whether it should be autosized, then
+            calls processClusterInternal() to apply the multiplier and process the cluster's
+            descendants.
+
+        (WebCore::TextAutosizer::processCompositeCluster):
+
+            Calculates the text width for a group of renderers and if the group should be autosized,
+            then calls processClusterInternal() repeatedly with the same multiplier to apply it and
+            process all the descendants of the group.
+
+        (WebCore::TextAutosizer::clusterShouldBeAutosized):
+
+            Calls the multiple renderers version to avoid code duplication.
+
+        (WebCore::TextAutosizer::compositeClusterShouldBeAutosized):
+
+            The multiple renderers version of clusterShouldBeAutosized.
+
+        * rendering/TextAutosizer.h:
+
+            Updated method declarations.
+
 2013-02-14  Andrey Adaikin  <aandrey@chromium.org>
 
         Look into possibilities of typedef in webkit idl files
index b7f3718..342637a 100644 (file)
@@ -133,18 +133,10 @@ bool TextAutosizer::processSubtree(RenderObject* layoutRoot)
     return true;
 }
 
-void TextAutosizer::processCluster(TextAutosizingClusterInfo& clusterInfo, RenderBlock* container, RenderObject* subtreeRoot, const TextAutosizingWindowInfo& windowInfo)
+void TextAutosizer::processClusterInternal(TextAutosizingClusterInfo& clusterInfo, RenderBlock* container, RenderObject* subtreeRoot, const TextAutosizingWindowInfo& windowInfo, float textWidth, bool shouldBeAutosized)
 {
-    // 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.
-    clusterInfo.blockContainingAllText = findDeepestBlockContainingAllText(clusterInfo.root);
-    float textWidth = clusterInfo.blockContainingAllText->contentLogicalWidth();
-
     float multiplier = 1;
-    if (clusterShouldBeAutosized(clusterInfo, textWidth)) {
+    if (shouldBeAutosized) {
         int logicalWindowWidth = clusterInfo.root->isHorizontalWritingMode() ? windowInfo.windowSize.width() : windowInfo.windowSize.height();
         int logicalLayoutWidth = clusterInfo.root->isHorizontalWritingMode() ? windowInfo.minLayoutSize.width() : windowInfo.minLayoutSize.height();
         // Ignore box width in excess of the layout width, to avoid extreme multipliers.
@@ -157,11 +149,32 @@ void TextAutosizer::processCluster(TextAutosizingClusterInfo& clusterInfo, Rende
 
     processContainer(multiplier, container, clusterInfo, subtreeRoot, windowInfo);
 
-    Vector<TextAutosizingClusterInfo>& narrowDescendants = clusterInfo.narrowDescendants;
-    for (size_t i = 0; i < narrowDescendants.size(); ++i) {
-        TextAutosizingClusterInfo& descendantClusterInfo = narrowDescendants[i];
-        processCluster(descendantClusterInfo, descendantClusterInfo.root, descendantClusterInfo.root, windowInfo);
+    processCompositeCluster(clusterInfo.narrowDescendants, windowInfo);
+}
+
+void TextAutosizer::processCluster(TextAutosizingClusterInfo& clusterInfo, RenderBlock* container, RenderObject* subtreeRoot, const TextAutosizingWindowInfo& windowInfo)
+{
+    // 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.
+    clusterInfo.blockContainingAllText = findDeepestBlockContainingAllText(clusterInfo.root);
+    float textWidth = clusterInfo.blockContainingAllText->contentLogicalWidth();
+    processClusterInternal(clusterInfo, container, subtreeRoot, windowInfo, textWidth, clusterShouldBeAutosized(clusterInfo, textWidth));
+}
+
+void TextAutosizer::processCompositeCluster(Vector<TextAutosizingClusterInfo>& clusterInfos, const TextAutosizingWindowInfo& windowInfo)
+{
+    float maxTextWidth = 0;
+    for (size_t i = 0; i < clusterInfos.size(); ++i) {
+        TextAutosizingClusterInfo& clusterInfo = clusterInfos[i];
+        clusterInfo.blockContainingAllText = findDeepestBlockContainingAllText(clusterInfo.root);
+        maxTextWidth = max<float>(maxTextWidth, clusterInfo.blockContainingAllText->contentLogicalWidth());
     }
+
+    bool shouldBeAutosized = compositeClusterShouldBeAutosized(clusterInfos, maxTextWidth);
+    for (size_t i = 0; i < clusterInfos.size(); ++i)
+        processClusterInternal(clusterInfos[i], clusterInfos[i].root, clusterInfos[i].root, windowInfo, maxTextWidth, shouldBeAutosized);
 }
 
 void TextAutosizer::processContainer(float multiplier, RenderBlock* container, TextAutosizingClusterInfo& clusterInfo, RenderObject* subtreeRoot, const TextAutosizingWindowInfo& windowInfo)
@@ -428,6 +441,12 @@ bool TextAutosizer::contentHeightIsConstrained(const RenderBlock* container)
 
 bool TextAutosizer::clusterShouldBeAutosized(TextAutosizingClusterInfo& clusterInfo, float blockWidth)
 {
+    Vector<TextAutosizingClusterInfo> clusterInfos(1, clusterInfo);
+    return compositeClusterShouldBeAutosized(clusterInfos, blockWidth);
+}
+
+bool TextAutosizer::compositeClusterShouldBeAutosized(Vector<TextAutosizingClusterInfo>& clusterInfos, float blockWidth)
+{
     // Don't autosize clusters that contain less than 4 lines of text (in
     // practice less lines are required, since measureDescendantTextWidth
     // assumes that characters are 1em wide, but most characters are narrower
@@ -438,12 +457,14 @@ bool TextAutosizer::clusterShouldBeAutosized(TextAutosizingClusterInfo& clusterI
     // if a cluster contains very few lines of text then it's ok to have to zoom
     // 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.
+    float totalTextWidth = 0;
     const float minLinesOfText = 4;
     float minTextWidth = blockWidth * minLinesOfText;
-    float textWidth = 0;
-    measureDescendantTextWidth(clusterInfo.blockContainingAllText, clusterInfo, minTextWidth, textWidth);
-    if (textWidth >= minTextWidth)
-        return true;
+    for (size_t i = 0; i < clusterInfos.size(); ++i) {
+        measureDescendantTextWidth(clusterInfos[i].blockContainingAllText, clusterInfos[i], minTextWidth, totalTextWidth);
+        if (totalTextWidth >= minTextWidth)
+            return true;
+    }
     return false;
 }
 
index 537157e..6495a30 100644 (file)
@@ -61,7 +61,9 @@ private:
 
     explicit TextAutosizer(Document*);
 
+    void processClusterInternal(TextAutosizingClusterInfo&, RenderBlock* container, RenderObject* subtreeRoot, const TextAutosizingWindowInfo&, float textWidth, bool shouldBeAutosized);
     void processCluster(TextAutosizingClusterInfo&, RenderBlock* container, RenderObject* subtreeRoot, const TextAutosizingWindowInfo&);
+    void processCompositeCluster(Vector<TextAutosizingClusterInfo>&, const TextAutosizingWindowInfo&);
     void processContainer(float multiplier, RenderBlock* container, TextAutosizingClusterInfo&, RenderObject* subtreeRoot, const TextAutosizingWindowInfo&);
 
     void setMultiplier(RenderObject*, float);
@@ -77,6 +79,7 @@ private:
     static bool containerIsRowOfLinks(const RenderObject* container);
     static bool contentHeightIsConstrained(const RenderBlock* container);
     static bool clusterShouldBeAutosized(TextAutosizingClusterInfo&, float blockWidth);
+    static bool compositeClusterShouldBeAutosized(Vector<TextAutosizingClusterInfo>&, float blockWidth);
     static void measureDescendantTextWidth(const RenderBlock* container, TextAutosizingClusterInfo&, float minTextWidth, float& textWidth);
 
     // Use to traverse the tree of descendants, excluding descendants of containers (but returning the containers themselves).