Title: [176396] trunk
Revision
176396
Author
[email protected]
Date
2014-11-20 07:22:02 -0800 (Thu, 20 Nov 2014)

Log Message

Simple line layout: Introduce text fragment continuation.
https://bugs.webkit.org/show_bug.cgi?id=138274

Source/WebCore:

This patch extends simple line layout coverage to multiple text renderers.
When a particular render flow has multiple text renderers (but not any other type)
then we use simple line layout to process and paint the content. -other, existing requirements still apply
so that for example if the content requires decoration, we bail out of simple line layout.

FlowContent now supports multiple renderes. It continuously reads content from sibling renderers
so that the simple line layout parser sees it as one monolithic block of content. Run positions
are all relative to the block and they get resolved to renderer's positions on demand.
(painting, computing bounding rects etc)

Reviewed by Antti Koivisto.

Performance test already been added for the multiple rendere use case,
correctness is covered by existing test cases.
Test: fast/text/simple-lines-mutliple-renderers.html

* rendering/SimpleLineLayout.cpp:
(WebCore::SimpleLineLayout::canUseFor): Check if children are all 8bit RenderTexts.
(WebCore::SimpleLineLayout::removeTrailingWhitespace): Move the endofline check right before where we might overflow using end position.
(WebCore::SimpleLineLayout::initializeNewLine):
(WebCore::SimpleLineLayout::closeLineEndingAndAdjustRuns):
(WebCore::SimpleLineLayout::splitRunsAtRendererBoundary): Split runs at renderers' boundary to be in sync with inline text renderering.
(WebCore::SimpleLineLayout::createTextRuns):
(WebCore::SimpleLineLayout::create):
* rendering/SimpleLineLayoutFlowContents.cpp:
(WebCore::SimpleLineLayout::FlowContents::FlowContents):
(WebCore::SimpleLineLayout::FlowContents::findNextBreakablePosition):
(WebCore::SimpleLineLayout::FlowContents::findNextNonWhitespacePosition):
(WebCore::SimpleLineLayout::FlowContents::textWidth): Do not measure text across renderers. It could produce different width value due to
ligature which later can produce unexpected line breaks and out sync renderering in general.
(WebCore::SimpleLineLayout::FlowContents::renderer):
(WebCore::SimpleLineLayout::FlowContents::resolveRendererPositions):
(WebCore::SimpleLineLayout::FlowContents::appendNextRendererContentIfNeeded): Read the next renderer content if needed.
(WebCore::SimpleLineLayout::FlowContents::nextNonWhitespacePosition):
(WebCore::SimpleLineLayout::FlowContents::runWidth):
* rendering/SimpleLineLayoutFlowContents.h:
(WebCore::SimpleLineLayout::FlowContents::isNewlineCharacter):
(WebCore::SimpleLineLayout::FlowContents::isEndOfContent):
* rendering/SimpleLineLayoutResolver.cpp:
(WebCore::SimpleLineLayout::RunResolver::Run::text):

LayoutTests:

Rebaseline for simple line layout's multiple rendere support.

Reviewed by Antti Koivisto.

* fast/text/simple-lines-multiple-renderers-expected.html: Added.
* fast/text/simple-lines-multiple-renderers.html: Added.
* fast/tokenizer/script_extra_close-expected.txt: Multiple tab characters should collapse into a single whitespace. This
needs fixing in complex line layout.
* tables/mozilla/bugs/bug157890-expected.txt: no-op endofline run is added by complex inline layout
when multiple text content is injected through JS into a <pre>. This requires fixing complex line layout.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (176395 => 176396)


--- trunk/LayoutTests/ChangeLog	2014-11-20 15:20:37 UTC (rev 176395)
+++ trunk/LayoutTests/ChangeLog	2014-11-20 15:22:02 UTC (rev 176396)
@@ -1,3 +1,19 @@
+2014-11-20  Zalan Bujtas  <[email protected]>
+
+        Simple line layout: Introduce text fragment continuation.
+        https://bugs.webkit.org/show_bug.cgi?id=138274
+
+        Rebaseline for simple line layout's multiple rendere support.
+
+        Reviewed by Antti Koivisto.
+
+        * fast/text/simple-lines-multiple-renderers-expected.html: Added.
+        * fast/text/simple-lines-multiple-renderers.html: Added.
+        * fast/tokenizer/script_extra_close-expected.txt: Multiple tab characters should collapse into a single whitespace. This
+        needs fixing in complex line layout.
+        * tables/mozilla/bugs/bug157890-expected.txt: no-op endofline run is added by complex inline layout
+        when multiple text content is injected through JS into a <pre>. This requires fixing complex line layout.
+
 2014-11-19  Myles C. Maxfield  <[email protected]>
 
         [OS X] Upright vertical text is completely broken for multi-code-unit codepoints

Added: trunk/LayoutTests/fast/text/simple-lines-multiple-renderers-expected.html (0 => 176396)


--- trunk/LayoutTests/fast/text/simple-lines-multiple-renderers-expected.html	                        (rev 0)
+++ trunk/LayoutTests/fast/text/simple-lines-multiple-renderers-expected.html	2014-11-20 15:22:02 UTC (rev 176396)
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>This tests that simple line layout is applied on multiple sibling text renderers.</title>
+<script>
+  if (window.internals)
+    internals.settings.setSimpleLineLayoutDebugBordersEnabled(true);
+</script>
+</head>
+<body>
+<div id=container>
+</div>
+<script>
+  var container = document.getElementById("container");
+  container.appendChild(document.createTextNode("Quo usque tandem abutere, Catilina, patientia nostra?  quam diu etiam\n"));
+  container.appendChild(document.createTextNode("furor iste tuus nos eludet?  quem ad finem sese effrenata iactabit\n"));
+  container.appendChild(document.createTextNode("audacia?  Nihilne te nocturnum praesidium Palati, nihil urbis vigiliae,\n"));
+  container.appendChild(document.createTextNode("nihil timor populi, nihil concursus bonorum omnium, nihil hic munitissimus\n"));
+  container.appendChild(document.createTextNode("habendi senatus locus, nihil horum ora voltusque moverunt?  Patere tua\n"));
+  container.appendChild(document.createTextNode("consilia non sentis, constrictam iam horum omnium scientia teneri\n"));
+  container.appendChild(document.createTextNode("coniurationem tuam non vides?  Quid proxima, quid superiore nocte egeris,\n"));
+  container.appendChild(document.createTextNode("ubi fueris, quos convocaveris, quid consilii ceperis, quem nostrum\n"));
+  container.appendChild(document.createTextNode("ignorare arbitraris?  O tempora, o mores!\n"));
+</script>
+</body>
+</html>

Added: trunk/LayoutTests/fast/text/simple-lines-multiple-renderers.html (0 => 176396)


--- trunk/LayoutTests/fast/text/simple-lines-multiple-renderers.html	                        (rev 0)
+++ trunk/LayoutTests/fast/text/simple-lines-multiple-renderers.html	2014-11-20 15:22:02 UTC (rev 176396)
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>This tests that simple line layout is applied on multiple sibling text renderers.</title>
+<script>
+  if (window.internals)
+    internals.settings.setSimpleLineLayoutDebugBordersEnabled(true);
+</script>
+</head>
+<body>
+<div>
+  Quo usque tandem abutere, Catilina, patientia nostra?  quam diu etiam
+  furor iste tuus nos eludet?  quem ad finem sese effrenata iactabit
+  audacia?  Nihilne te nocturnum praesidium Palati, nihil urbis vigiliae,
+  nihil timor populi, nihil concursus bonorum omnium, nihil hic munitissimus
+  habendi senatus locus, nihil horum ora voltusque moverunt?  Patere tua
+  consilia non sentis, constrictam iam horum omnium scientia teneri
+  coniurationem tuam non vides?  Quid proxima, quid superiore nocte egeris,
+  ubi fueris, quos convocaveris, quid consilii ceperis, quem nostrum
+  ignorare arbitraris?  O tempora, o mores!
+</div>
+</body>
+</html>

Modified: trunk/LayoutTests/fast/tokenizer/script_extra_close-expected.txt (176395 => 176396)


--- trunk/LayoutTests/fast/tokenizer/script_extra_close-expected.txt	2014-11-20 15:20:37 UTC (rev 176395)
+++ trunk/LayoutTests/fast/tokenizer/script_extra_close-expected.txt	2014-11-20 15:22:02 UTC (rev 176396)
@@ -1 +1 @@
-TEST...	PASSED. This text should show up.
+TEST... PASSED. This text should show up.

Modified: trunk/LayoutTests/tables/mozilla/bugs/bug157890-expected.txt (176395 => 176396)


--- trunk/LayoutTests/tables/mozilla/bugs/bug157890-expected.txt	2014-11-20 15:20:37 UTC (rev 176395)
+++ trunk/LayoutTests/tables/mozilla/bugs/bug157890-expected.txt	2014-11-20 15:22:02 UTC (rev 176396)
@@ -71,10 +71,8 @@
       RenderBlock {PRE} at (0,13) size 784x450
         RenderText {#text} at (0,0) size 216x15
           text run at (0,0) width 216: "Specified table width: 25px"
-          text run at (216,0) width 0: " "
         RenderText {#text} at (0,15) size 216x15
           text run at (0,15) width 216: "Actual table width:    25px"
-          text run at (216,15) width 0: " "
         RenderText {#text} at (0,30) size 168x15
           text run at (0,30) width 168: "Specified TD widths: "
         RenderText {#text} at (168,30) size 32x15
@@ -111,8 +109,7 @@
           text run at (648,30) width 32: "1px "
         RenderText {#text} at (680,30) size 32x15
           text run at (680,30) width 32: "8px "
-        RenderText {#text} at (712,30) size 0x15
-          text run at (712,30) width 0: " "
+        RenderText {#text} at (0,0) size 0x0
         RenderText {#text} at (0,45) size 168x15
           text run at (0,45) width 168: "Actual TD widths:    "
         RenderText {#text} at (168,45) size 32x15
@@ -149,15 +146,12 @@
           text run at (648,45) width 32: "1px "
         RenderText {#text} at (680,45) size 32x15
           text run at (680,45) width 32: "8px "
-        RenderText {#text} at (712,45) size 712x30
-          text run at (712,45) width 0: " "
+        RenderText {#text} at (0,60) size 0x15
           text run at (0,60) width 0: " "
         RenderText {#text} at (0,75) size 216x15
           text run at (0,75) width 216: "Specified table width: 12px"
-          text run at (216,75) width 0: " "
         RenderText {#text} at (0,90) size 216x15
           text run at (0,90) width 216: "Actual table width:    12px"
-          text run at (216,90) width 0: " "
         RenderText {#text} at (0,105) size 168x15
           text run at (0,105) width 168: "Specified TD widths: "
         RenderText {#text} at (168,105) size 32x15
@@ -170,8 +164,7 @@
           text run at (264,105) width 32: "1px "
         RenderText {#text} at (296,105) size 32x15
           text run at (296,105) width 32: "8px "
-        RenderText {#text} at (328,105) size 0x15
-          text run at (328,105) width 0: " "
+        RenderText {#text} at (0,0) size 0x0
         RenderText {#text} at (0,120) size 168x15
           text run at (0,120) width 168: "Actual TD widths:    "
         RenderText {#text} at (168,120) size 32x15
@@ -184,15 +177,12 @@
           text run at (264,120) width 32: "1px "
         RenderText {#text} at (296,120) size 32x15
           text run at (296,120) width 32: "8px "
-        RenderText {#text} at (328,120) size 328x30
-          text run at (328,120) width 0: " "
+        RenderText {#text} at (0,135) size 0x15
           text run at (0,135) width 0: " "
         RenderText {#text} at (0,150) size 216x15
           text run at (0,150) width 216: "Specified table width: 13px"
-          text run at (216,150) width 0: " "
         RenderText {#text} at (0,165) size 216x15
           text run at (0,165) width 216: "Actual table width:    13px"
-          text run at (216,165) width 0: " "
         RenderText {#text} at (0,180) size 168x15
           text run at (0,180) width 168: "Specified TD widths: "
         RenderText {#text} at (168,180) size 32x15
@@ -205,8 +195,7 @@
           text run at (264,180) width 32: "1px "
         RenderText {#text} at (296,180) size 32x15
           text run at (296,180) width 32: "8px "
-        RenderText {#text} at (328,180) size 0x15
-          text run at (328,180) width 0: " "
+        RenderText {#text} at (0,0) size 0x0
         RenderText {#text} at (0,195) size 168x15
           text run at (0,195) width 168: "Actual TD widths:    "
         RenderText {#text} at (168,195) size 32x15
@@ -219,15 +208,12 @@
           text run at (264,195) width 32: "1px "
         RenderText {#text} at (296,195) size 32x15
           text run at (296,195) width 32: "8px "
-        RenderText {#text} at (328,195) size 328x30
-          text run at (328,195) width 0: " "
+        RenderText {#text} at (0,210) size 0x15
           text run at (0,210) width 0: " "
         RenderText {#text} at (0,225) size 216x15
           text run at (0,225) width 216: "Specified table width: 24px"
-          text run at (216,225) width 0: " "
         RenderText {#text} at (0,240) size 216x15
           text run at (0,240) width 216: "Actual table width:    24px"
-          text run at (216,240) width 0: " "
         RenderText {#text} at (0,255) size 168x15
           text run at (0,255) width 168: "Specified TD widths: "
         RenderText {#text} at (168,255) size 32x15
@@ -240,8 +226,7 @@
           text run at (264,255) width 32: "1px "
         RenderText {#text} at (296,255) size 32x15
           text run at (296,255) width 32: "8px "
-        RenderText {#text} at (328,255) size 0x15
-          text run at (328,255) width 0: " "
+        RenderText {#text} at (0,0) size 0x0
         RenderText {#text} at (0,270) size 168x15
           text run at (0,270) width 168: "Actual TD widths:    "
         RenderText {#text} at (168,270) size 32x15
@@ -254,15 +239,12 @@
           text run at (264,270) width 32: "2px "
         RenderText {#text} at (296,270) size 40x15
           text run at (296,270) width 40: "16px "
-        RenderText {#text} at (336,270) size 336x30
-          text run at (336,270) width 0: " "
+        RenderText {#text} at (0,285) size 0x15
           text run at (0,285) width 0: " "
         RenderText {#text} at (0,300) size 216x15
           text run at (0,300) width 216: "Specified table width: 25px"
-          text run at (216,300) width 0: " "
         RenderText {#text} at (0,315) size 216x15
           text run at (0,315) width 216: "Actual table width:    25px"
-          text run at (216,315) width 0: " "
         RenderText {#text} at (0,330) size 168x15
           text run at (0,330) width 168: "Specified TD widths: "
         RenderText {#text} at (168,330) size 32x15
@@ -275,8 +257,7 @@
           text run at (264,330) width 32: "1px "
         RenderText {#text} at (296,330) size 32x15
           text run at (296,330) width 32: "8px "
-        RenderText {#text} at (328,330) size 0x15
-          text run at (328,330) width 0: " "
+        RenderText {#text} at (0,0) size 0x0
         RenderText {#text} at (0,345) size 168x15
           text run at (0,345) width 168: "Actual TD widths:    "
         RenderText {#text} at (168,345) size 32x15
@@ -289,15 +270,12 @@
           text run at (264,345) width 32: "2px "
         RenderText {#text} at (296,345) size 40x15
           text run at (296,345) width 40: "16px "
-        RenderText {#text} at (336,345) size 336x30
-          text run at (336,345) width 0: " "
+        RenderText {#text} at (0,360) size 0x15
           text run at (0,360) width 0: " "
         RenderText {#text} at (0,375) size 216x15
           text run at (0,375) width 216: "Specified table width: 17px"
-          text run at (216,375) width 0: " "
         RenderText {#text} at (0,390) size 216x15
           text run at (0,390) width 216: "Actual table width:    17px"
-          text run at (216,390) width 0: " "
         RenderText {#text} at (0,405) size 168x15
           text run at (0,405) width 168: "Specified TD widths: "
         RenderText {#text} at (168,405) size 32x15
@@ -320,8 +298,7 @@
           text run at (424,405) width 32: "10% "
         RenderText {#text} at (456,405) size 32x15
           text run at (456,405) width 32: "10% "
-        RenderText {#text} at (488,405) size 0x15
-          text run at (488,405) width 0: " "
+        RenderText {#text} at (0,0) size 0x0
         RenderText {#text} at (0,420) size 168x15
           text run at (0,420) width 168: "Actual TD widths:    "
         RenderText {#text} at (168,420) size 32x15
@@ -344,6 +321,5 @@
           text run at (424,420) width 32: "1px "
         RenderText {#text} at (456,420) size 32x15
           text run at (456,420) width 32: "1px "
-        RenderText {#text} at (488,420) size 488x30
-          text run at (488,420) width 0: " "
+        RenderText {#text} at (0,435) size 0x15
           text run at (0,435) width 0: " "

Modified: trunk/Source/WebCore/ChangeLog (176395 => 176396)


--- trunk/Source/WebCore/ChangeLog	2014-11-20 15:20:37 UTC (rev 176395)
+++ trunk/Source/WebCore/ChangeLog	2014-11-20 15:22:02 UTC (rev 176396)
@@ -1,3 +1,49 @@
+2014-11-20  Zalan Bujtas  <[email protected]>
+
+        Simple line layout: Introduce text fragment continuation.
+        https://bugs.webkit.org/show_bug.cgi?id=138274
+
+        This patch extends simple line layout coverage to multiple text renderers.
+        When a particular render flow has multiple text renderers (but not any other type)
+        then we use simple line layout to process and paint the content. -other, existing requirements still apply
+        so that for example if the content requires decoration, we bail out of simple line layout.
+
+        FlowContent now supports multiple renderes. It continuously reads content from sibling renderers
+        so that the simple line layout parser sees it as one monolithic block of content. Run positions
+        are all relative to the block and they get resolved to renderer's positions on demand.
+        (painting, computing bounding rects etc)
+
+        Reviewed by Antti Koivisto.
+
+        Performance test already been added for the multiple rendere use case,
+        correctness is covered by existing test cases.
+        Test: fast/text/simple-lines-mutliple-renderers.html
+
+        * rendering/SimpleLineLayout.cpp:
+        (WebCore::SimpleLineLayout::canUseFor): Check if children are all 8bit RenderTexts.
+        (WebCore::SimpleLineLayout::removeTrailingWhitespace): Move the endofline check right before where we might overflow using end position.
+        (WebCore::SimpleLineLayout::initializeNewLine):
+        (WebCore::SimpleLineLayout::closeLineEndingAndAdjustRuns):
+        (WebCore::SimpleLineLayout::splitRunsAtRendererBoundary): Split runs at renderers' boundary to be in sync with inline text renderering.
+        (WebCore::SimpleLineLayout::createTextRuns):
+        (WebCore::SimpleLineLayout::create):
+        * rendering/SimpleLineLayoutFlowContents.cpp:
+        (WebCore::SimpleLineLayout::FlowContents::FlowContents):
+        (WebCore::SimpleLineLayout::FlowContents::findNextBreakablePosition):
+        (WebCore::SimpleLineLayout::FlowContents::findNextNonWhitespacePosition):
+        (WebCore::SimpleLineLayout::FlowContents::textWidth): Do not measure text across renderers. It could produce different width value due to
+        ligature which later can produce unexpected line breaks and out sync renderering in general.
+        (WebCore::SimpleLineLayout::FlowContents::renderer): 
+        (WebCore::SimpleLineLayout::FlowContents::resolveRendererPositions):
+        (WebCore::SimpleLineLayout::FlowContents::appendNextRendererContentIfNeeded): Read the next renderer content if needed.
+        (WebCore::SimpleLineLayout::FlowContents::nextNonWhitespacePosition):
+        (WebCore::SimpleLineLayout::FlowContents::runWidth):
+        * rendering/SimpleLineLayoutFlowContents.h:
+        (WebCore::SimpleLineLayout::FlowContents::isNewlineCharacter):
+        (WebCore::SimpleLineLayout::FlowContents::isEndOfContent):
+        * rendering/SimpleLineLayoutResolver.cpp:
+        (WebCore::SimpleLineLayout::RunResolver::Run::text):
+
 2014-11-20  [email protected]  <[email protected]>
 
         [WinCairo] Compile error when GStreamer is enabled.

Modified: trunk/Source/WebCore/rendering/SimpleLineLayout.cpp (176395 => 176396)


--- trunk/Source/WebCore/rendering/SimpleLineLayout.cpp	2014-11-20 15:20:37 UTC (rev 176395)
+++ trunk/Source/WebCore/rendering/SimpleLineLayout.cpp	2014-11-20 15:22:02 UTC (rev 176396)
@@ -37,6 +37,7 @@
 #include "LineWidth.h"
 #include "PaintInfo.h"
 #include "RenderBlockFlow.h"
+#include "RenderChildIterator.h"
 #include "RenderStyle.h"
 #include "RenderText.h"
 #include "RenderTextControl.h"
@@ -93,14 +94,12 @@
         return false;
     if (!flow.firstChild())
         return false;
-    // This currently covers <blockflow>#text</blockflow> case.
+    // This currently covers <blockflow>#text</blockflow> and mutiple (sibling) RenderText cases.
     // The <blockflow><inline>#text</inline></blockflow> case is also popular and should be relatively easy to cover.
-    if (flow.firstChild() != flow.lastChild())
-        return false;
-    if (!is<RenderText>(flow.firstChild()))
-        return false;
-    if (!downcast<RenderText>(*flow.firstChild()).text()->is8Bit())
-        return false;
+    for (const auto& renderer : childrenOfType<RenderObject>(flow)) {
+        if (!is<RenderText>(renderer) || !downcast<RenderText>(renderer).text()->is8Bit())
+            return false;
+    }
     if (!flow.isHorizontalWritingMode())
         return false;
     if (flow.flowThreadState() != RenderObject::NotInsideFlowThread)
@@ -406,10 +405,8 @@
         lineState.removeCommittedTrailingWhitespace();
     }
 
-    if (flowContents.isEndOfContent(lineState.position))
-        return;
     // If we skipped any whitespace and now the line end is a "preserved" newline, skip the newline too as we are wrapping the line here already.
-    if (lastPosition != lineState.position && style.preserveNewline && flowContents.isNewlineCharacter(lineState.position))
+    if (lastPosition != lineState.position && style.preserveNewline && !flowContents.isEndOfContent(lineState.position) && flowContents.isNewlineCharacter(lineState.position))
         ++lineState.position;
 }
 
@@ -471,7 +468,7 @@
     return fragmentForNextLine;
 }
 
-static TextFragment nextFragment(unsigned previousFragmentEnd, FlowContents& flowContents, float xPosition)
+static TextFragment nextFragment(unsigned previousFragmentEnd, const FlowContents& flowContents, float xPosition)
 {
     // A fragment can have
     // 1. new line character when preserveNewline is on (not considered as whitespace) or
@@ -510,7 +507,7 @@
     return fragment;
 }
 
-static bool createLineRuns(LineState& lineState, Layout::RunVector& lineRuns, FlowContents& flowContents)
+static bool createLineRuns(LineState& lineState, Layout::RunVector& lineRuns, const FlowContents& flowContents)
 {
     const auto& style = flowContents.style();
     bool lineCanBeWrapped = style.wrapLines || style.breakWordOnOverflow;
@@ -586,6 +583,34 @@
     ++lineCount;
 }
 
+static void splitRunsAtRendererBoundary(Layout::RunVector& lineRuns, const FlowContents& flowContents)
+{
+    if (!lineRuns.size())
+        return;
+
+    unsigned runIndex = 0;
+    do {
+        const Run& run = lineRuns.at(runIndex);
+        ASSERT(run.start != run.end);
+        const RenderText* startRenderer = flowContents.renderer(run.start);
+        const RenderText* endRenderer = flowContents.renderer(run.end - 1);
+        if (startRenderer == endRenderer)
+            continue;
+        // This run overlaps multiple renderers. Split it up.
+        unsigned rendererStartPosition = 0;
+        unsigned rendererEndPosition = 0;
+        bool found = flowContents.resolveRendererPositions(*startRenderer, rendererStartPosition, rendererEndPosition);
+        ASSERT_UNUSED(found, found);
+
+        // Split run at the renderer's boundary and create a new run for the left side, while use the current run as the right side.
+        float logicalRightOfLeftRun = run.logicalLeft + flowContents.textWidth(run.start, rendererEndPosition, run.logicalLeft);
+        lineRuns.insert(runIndex, Run(run.start, rendererEndPosition, run.logicalLeft, logicalRightOfLeftRun, false));
+        Run& rightSideRun = lineRuns.at(runIndex + 1);
+        rightSideRun.start = rendererEndPosition;
+        rightSideRun.logicalLeft = logicalRightOfLeftRun;
+    } while (++runIndex < lineRuns.size());
+}
+
 static void updateLineConstrains(const RenderBlockFlow& flow, float& availableWidth, float& logicalLeftOffset)
 {
     LayoutUnit height = flow.logicalHeight();
@@ -610,6 +635,9 @@
         isEndOfContent = createLineRuns(lineState, runs, flowContents);
         closeLineEndingAndAdjustRuns(lineState, runs, lineCount, flowContents);
     } while (!isEndOfContent);
+
+    if (flow.firstChild() != flow.lastChild())
+        splitRunsAtRendererBoundary(runs, flowContents);
     ASSERT(!lineState.uncommittedWidth);
 }
 
@@ -617,11 +645,12 @@
 {
     unsigned lineCount = 0;
     Layout::RunVector runs;
-    RenderText& textRenderer = downcast<RenderText>(*flow.firstChild());
-    ASSERT(!textRenderer.firstTextBox());
 
     createTextRuns(runs, flow, lineCount);
-    textRenderer.clearNeedsLayout();
+    for (auto& renderer : childrenOfType<RenderObject>(flow)) {
+        ASSERT(is<RenderText>(renderer));
+        renderer.clearNeedsLayout();
+    }
     return Layout::create(runs, lineCount);
 }
 

Modified: trunk/Source/WebCore/rendering/SimpleLineLayoutFlowContents.cpp (176395 => 176396)


--- trunk/Source/WebCore/rendering/SimpleLineLayoutFlowContents.cpp	2014-11-20 15:20:37 UTC (rev 176395)
+++ trunk/Source/WebCore/rendering/SimpleLineLayoutFlowContents.cpp	2014-11-20 15:22:02 UTC (rev 176396)
@@ -27,6 +27,8 @@
 #include "SimpleLineLayoutFlowContents.h"
 
 #include "RenderBlockFlow.h"
+#include "RenderChildIterator.h"
+#include "RenderText.h"
 
 namespace WebCore {
 namespace SimpleLineLayout {
@@ -35,21 +37,135 @@
     : m_flow(flow)
     , m_style(flow.style())
     , m_lineBreakIterator(downcast<RenderText>(*flow.firstChild()).text(), flow.style().locale())
+    , m_lastRendererIndex(0)
 {
+    unsigned startPosition = 0;
+    for (const RenderText* textRenderer = downcast<RenderText>(m_flow.firstChild()); textRenderer; textRenderer = downcast<RenderText>(textRenderer->nextSibling())) {
+        unsigned contentLength = textRenderer->text()->length();
+        m_textRanges.append(std::make_pair(startPosition, textRenderer));
+        startPosition += contentLength;
+    }
+    // End item.
+    const RenderText* closingNullItem = nullptr;
+    m_textRanges.append(std::make_pair(startPosition, closingNullItem));
 }
 
-unsigned FlowContents::findNextBreakablePosition(unsigned position)
+unsigned FlowContents::findNextBreakablePosition(unsigned position) const
 {
     String string = m_lineBreakIterator.string();
-    return nextBreakablePosition<LChar, false>(m_lineBreakIterator, string.characters8(), string.length(), position);
+    unsigned breakablePosition = nextBreakablePosition<LChar, false>(m_lineBreakIterator, string.characters8(), string.length(), position);
+    if (appendNextRendererContentIfNeeded(breakablePosition))
+        return findNextBreakablePosition(position);
+    ASSERT(breakablePosition >= position);
+    return breakablePosition;
 }
 
 unsigned FlowContents::findNextNonWhitespacePosition(unsigned position, unsigned& spaceCount) const
 {
+    unsigned nonWhitespacePosition = nextNonWhitespacePosition(position, spaceCount);
+    if (appendNextRendererContentIfNeeded(nonWhitespacePosition))
+        return findNextNonWhitespacePosition(position, spaceCount);
+    ASSERT(nonWhitespacePosition >= position);
+    return nonWhitespacePosition;
+}
+
+float FlowContents::textWidth(unsigned from, unsigned to, float xPosition) const
+{
+    unsigned rendererStart = 0;
+    const RenderText* textRenderer = renderer(from, &rendererStart);
+    ASSERT(textRenderer);
+    // Resolved positions are relative to the renderers.
+    unsigned absoluteStart = from - rendererStart;
+    unsigned absoluteEnd = to - rendererStart;
+    if ((m_style.font.isFixedPitch() && textRenderer == renderer(to)) || (!absoluteStart && absoluteEnd == textRenderer->text()->length()))
+        return textRenderer->width(absoluteStart, to - from, m_style.font, xPosition, nullptr, nullptr);
+
+    // We need to split up the text and measure renderers individually due to ligature.
+    float textWidth = 0;
+    unsigned fragmentEnd = 0;
+    do {
+        fragmentEnd = std::min(to, rendererStart + textRenderer->text()->length());
+        unsigned absoluteFragmentEnd = fragmentEnd - rendererStart;
+        absoluteStart = from - rendererStart;
+        textWidth += runWidth(*textRenderer, absoluteStart, absoluteFragmentEnd, xPosition + textWidth);
+        from = fragmentEnd;
+        if (fragmentEnd < to)
+            textRenderer = renderer(fragmentEnd, &rendererStart);
+    } while (fragmentEnd < to && textRenderer);
+    return textWidth;
+}
+
+const RenderText* FlowContents::renderer(unsigned position, unsigned* rendererStartPosition) const
+{
+    unsigned arraySize = m_textRanges.size();
+    // Take advantage of the usage pattern.
+    if (position >= m_textRanges.at(m_lastRendererIndex).first && m_lastRendererIndex + 1 < arraySize && position < m_textRanges.at(m_lastRendererIndex + 1).first) {
+        if (rendererStartPosition)
+            *rendererStartPosition = m_textRanges.at(m_lastRendererIndex).first;
+        return m_textRanges.at(m_lastRendererIndex).second;
+    }
+    unsigned left = 0;
+    unsigned right = arraySize - 1;
+    ASSERT(arraySize);
+    ASSERT(position >= 0);
+    while (left < right) {
+        unsigned middle = (left + right) / 2;
+        unsigned endPosition = m_textRanges.at(middle + 1).first;
+        if (position > endPosition)
+            left = middle + 1;
+        else if (position < endPosition)
+            right = middle;
+        else {
+            right = middle + 1;
+            break;
+        }
+    }
+    if (rendererStartPosition)
+        *rendererStartPosition = m_textRanges.at(right).first;
+    return m_textRanges.at(right).second;
+}
+
+bool FlowContents::resolveRendererPositions(const RenderText& renderer, unsigned& startPosition, unsigned& endPosition) const
+{
+    unsigned arraySize = m_textRanges.size();
+    if (!arraySize)
+        return false;
+
+    unsigned index = 0;
+    do {
+        auto range = m_textRanges.at(index);
+        if (range.second == &renderer) {
+            startPosition = range.first;
+            ASSERT(index + 1 < arraySize);
+            endPosition = m_textRanges.at(index + 1).first;
+            return true;
+        }
+    } while (++index < arraySize);
+    return false;
+}
+
+bool FlowContents::appendNextRendererContentIfNeeded(unsigned position) const
+{
     String string = m_lineBreakIterator.string();
+    if (position < string.length())
+        return false;
+
+    // Content needs to be requested sequentially.
+    ASSERT(position == string.length());
+    const RenderText* nextRenderer = renderer(position);
+    if (!nextRenderer)
+        return false;
+
+    ++m_lastRendererIndex;
+    m_lineBreakIterator.resetStringAndReleaseIterator(string + String(nextRenderer->text()), m_flow.style().locale());
+    return true;
+}
+
+unsigned FlowContents::nextNonWhitespacePosition(unsigned position, unsigned& spaceCount) const
+{
+    String string = m_lineBreakIterator.string();
     unsigned length = string.length();
     const LChar* text = string.characters8();
-    spaceCount = 0;
     for (; position < length; ++position) {
         bool isSpace = text[position] == ' ';
         if (!(isSpace || text[position] == '\t' || (!m_style.preserveNewline && text[position] == '\n')))
@@ -60,35 +176,15 @@
     return length;
 }
 
-float FlowContents::textWidth(unsigned from, unsigned to, float xPosition) const
+float FlowContents::runWidth(const RenderText& renderer, unsigned from, unsigned to, float xPosition) const
 {
-    String string = m_lineBreakIterator.string();
-    unsigned length = string.length();
-    if (m_style.font.isFixedPitch() || (!from && to == length)) {
-        const RenderText& renderer = downcast<RenderText>(*m_flow.firstChild());
-        return renderer.width(from, to - from, m_style.font, xPosition, nullptr, nullptr);
-    }
-
+    ASSERT(from < to);
+    String string = renderer.text();
     TextRun run(string.characters8() + from, to - from);
     run.setXPos(xPosition);
-    run.setCharactersLength(length - from);
     run.setTabSize(!!m_style.tabWidth, m_style.tabWidth);
-    ASSERT(run.charactersLength() >= run.length());
     return m_style.font.width(run);
 }
 
-bool FlowContents::resolveRendererPositions(const RenderText& renderer, unsigned& startPosition, unsigned& endPosition) const
-{
-    ASSERT(&renderer == downcast<RenderText>(m_flow.firstChild()));
-    startPosition = 0;
-    endPosition = renderer.text()->length();
-    return true;
 }
-
-const RenderText& FlowContents::renderer(unsigned) const
-{
-    return downcast<RenderText>(*m_flow.firstChild());
 }
-
-}
-}

Modified: trunk/Source/WebCore/rendering/SimpleLineLayoutFlowContents.h (176395 => 176396)


--- trunk/Source/WebCore/rendering/SimpleLineLayoutFlowContents.h	2014-11-20 15:20:37 UTC (rev 176395)
+++ trunk/Source/WebCore/rendering/SimpleLineLayoutFlowContents.h	2014-11-20 15:22:02 UTC (rev 176396)
@@ -40,7 +40,7 @@
 public:
     FlowContents(const RenderBlockFlow&);
 
-    unsigned findNextBreakablePosition(unsigned position);
+    unsigned findNextBreakablePosition(unsigned position) const;
     unsigned findNextNonWhitespacePosition(unsigned position, unsigned& spaceCount) const;
 
     float textWidth(unsigned from, unsigned to, float xPosition) const;
@@ -49,7 +49,7 @@
     bool isEndOfContent(unsigned position) const;
 
     bool resolveRendererPositions(const RenderText&, unsigned& startPosition, unsigned& endPosition) const;
-    const RenderText& renderer(unsigned position) const;
+    const RenderText* renderer(unsigned position, unsigned* startPosition = nullptr) const;
 
     class Style {
     public:
@@ -77,23 +77,27 @@
     const Style& style() const { return m_style; }
 
 private:
+    bool appendNextRendererContentIfNeeded(unsigned position) const;
     unsigned nextNonWhitespacePosition(unsigned position, unsigned& spaceCount) const;
-    float runWidth(unsigned from, unsigned to, float xPosition) const;
+    float runWidth(const RenderText&, unsigned from, unsigned to, float xPosition) const;
 
     const RenderBlockFlow& m_flow;
-    Style m_style;
-    LazyLineBreakIterator m_lineBreakIterator;
+    const Style m_style;
+    mutable LazyLineBreakIterator m_lineBreakIterator;
+    Vector<std::pair<unsigned, const RenderText*>> m_textRanges;
+    mutable unsigned m_lastRendererIndex;
 };
 
 inline bool FlowContents::isNewlineCharacter(unsigned position) const
 {
-    ASSERT(m_lineBreakIterator.string().length() > position);
+    appendNextRendererContentIfNeeded(position);
+    ASSERT(position < m_lineBreakIterator.string().length());
     return m_lineBreakIterator.string().at(position) == '\n';
 }
 
 inline bool FlowContents::isEndOfContent(unsigned position) const
 {
-    return position >= m_lineBreakIterator.string().length();
+    return position >= m_lineBreakIterator.string().length() && !renderer(position);
 }
 
 }

Modified: trunk/Source/WebCore/rendering/SimpleLineLayoutResolver.cpp (176395 => 176396)


--- trunk/Source/WebCore/rendering/SimpleLineLayoutResolver.cpp	2014-11-20 15:20:37 UTC (rev 176395)
+++ trunk/Source/WebCore/rendering/SimpleLineLayoutResolver.cpp	2014-11-20 15:22:02 UTC (rev 176396)
@@ -76,9 +76,11 @@
 {
     auto& resolver = m_iterator.resolver();
     auto& run = m_iterator.simpleRun();
-    const auto& renderer = resolver.m_flowContents.renderer(run.start);
-    ASSERT(renderer.is8Bit());
-    return StringView(renderer.characters8(), renderer.textLength()).substring(run.start, run.end - run.start);
+    unsigned rendererOffset = 0;
+    const auto* renderer = resolver.m_flowContents.renderer(run.start, &rendererOffset);
+    ASSERT(renderer);
+    ASSERT(renderer->is8Bit());
+    return StringView(renderer->characters8(), renderer->textLength()).substring(run.start - rendererOffset, run.end - run.start);
 }
 
 RunResolver::Iterator::Iterator(const RunResolver& resolver, unsigned runIndex, unsigned lineIndex)
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to