<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[179185] trunk/Source/WebCore</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/179185">179185</a></dd>
<dt>Author</dt> <dd>zalan@apple.com</dd>
<dt>Date</dt> <dd>2015-01-27 09:01:07 -0800 (Tue, 27 Jan 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>Simple line layout: Make FlowContents an iterator class.
https://bugs.webkit.org/show_bug.cgi?id=140909

Reviewed by Antti Koivisto.

This patch transfers content position handling from createLineRuns()/LineState to
FlowContents. FlowContents becomes a real iterator class.
It tightens content and position information so that we can start supporting
no textual content such as &lt;br&gt;.

No change in functionality.

* rendering/SimpleLineLayout.cpp:
(WebCore::SimpleLineLayout::LineState::commitAndCreateRun): Remove redundant committedLogicalRight.
(WebCore::SimpleLineLayout::LineState::addUncommitted): Now that we don't have current
positon in LineState, we need to be able to figure out where we start the uncommitted content.
This is mainly relevant after collapsed whitespace, when we start a new uncommitted segment.
It was previously achieved through LineState::jumpTo().
(WebCore::SimpleLineLayout::LineState::removeTrailingWhitespace):
(WebCore::SimpleLineLayout::firstFragment): Return the first fragment for this line.
(WebCore::SimpleLineLayout::createLineRuns): Renaming and removing position handling.
(WebCore::SimpleLineLayout::closeLineEndingAndAdjustRuns): Renaming.
(WebCore::SimpleLineLayout::createTextRuns):
(WebCore::SimpleLineLayout::LineState::jumpTo): Deleted.
(WebCore::SimpleLineLayout::initializeNewLine): Deleted. : Move overflow fragment functionality
to firstFragment().
* rendering/SimpleLineLayoutFlowContents.cpp:
(WebCore::SimpleLineLayout::FlowContents::nextTextFragment):
* rendering/SimpleLineLayoutFlowContents.h:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCorerenderingSimpleLineLayoutcpp">trunk/Source/WebCore/rendering/SimpleLineLayout.cpp</a></li>
<li><a href="#trunkSourceWebCorerenderingSimpleLineLayoutFlowContentscpp">trunk/Source/WebCore/rendering/SimpleLineLayoutFlowContents.cpp</a></li>
<li><a href="#trunkSourceWebCorerenderingSimpleLineLayoutFlowContentsh">trunk/Source/WebCore/rendering/SimpleLineLayoutFlowContents.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (179184 => 179185)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2015-01-27 17:00:08 UTC (rev 179184)
+++ trunk/Source/WebCore/ChangeLog        2015-01-27 17:01:07 UTC (rev 179185)
</span><span class="lines">@@ -1,3 +1,35 @@
</span><ins>+2015-01-27  Zalan Bujtas  &lt;zalan@apple.com&gt;
+
+        Simple line layout: Make FlowContents an iterator class.
+        https://bugs.webkit.org/show_bug.cgi?id=140909
+
+        Reviewed by Antti Koivisto.
+
+        This patch transfers content position handling from createLineRuns()/LineState to
+        FlowContents. FlowContents becomes a real iterator class.
+        It tightens content and position information so that we can start supporting
+        no textual content such as &lt;br&gt;.
+
+        No change in functionality.
+
+        * rendering/SimpleLineLayout.cpp:
+        (WebCore::SimpleLineLayout::LineState::commitAndCreateRun): Remove redundant committedLogicalRight.
+        (WebCore::SimpleLineLayout::LineState::addUncommitted): Now that we don't have current
+        positon in LineState, we need to be able to figure out where we start the uncommitted content.
+        This is mainly relevant after collapsed whitespace, when we start a new uncommitted segment.
+        It was previously achieved through LineState::jumpTo().
+        (WebCore::SimpleLineLayout::LineState::removeTrailingWhitespace):
+        (WebCore::SimpleLineLayout::firstFragment): Return the first fragment for this line.
+        (WebCore::SimpleLineLayout::createLineRuns): Renaming and removing position handling.
+        (WebCore::SimpleLineLayout::closeLineEndingAndAdjustRuns): Renaming.
+        (WebCore::SimpleLineLayout::createTextRuns):
+        (WebCore::SimpleLineLayout::LineState::jumpTo): Deleted.
+        (WebCore::SimpleLineLayout::initializeNewLine): Deleted. : Move overflow fragment functionality
+        to firstFragment().
+        * rendering/SimpleLineLayoutFlowContents.cpp:
+        (WebCore::SimpleLineLayout::FlowContents::nextTextFragment):
+        * rendering/SimpleLineLayoutFlowContents.h:
+
</ins><span class="cx"> 2015-01-27  Chris Dumez  &lt;cdumez@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         HTMLElement.dir should only return known values
</span></span></pre></div>
<a id="trunkSourceWebCorerenderingSimpleLineLayoutcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/rendering/SimpleLineLayout.cpp (179184 => 179185)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/SimpleLineLayout.cpp        2015-01-27 17:00:08 UTC (rev 179184)
+++ trunk/Source/WebCore/rendering/SimpleLineLayout.cpp        2015-01-27 17:01:07 UTC (rev 179185)
</span><span class="lines">@@ -232,10 +232,9 @@
</span><span class="cx">         if (uncommittedStart == uncommittedEnd)
</span><span class="cx">             return;
</span><span class="cx"> 
</span><del>-        lineRuns.append(Run(uncommittedStart, uncommittedEnd, committedLogicalRight, committedLogicalRight + uncommittedWidth, false));
</del><ins>+        lineRuns.append(Run(uncommittedStart, uncommittedEnd, committedWidth, committedWidth + uncommittedWidth, false));
</ins><span class="cx">         // Move uncommitted to committed.
</span><span class="cx">         committedWidth += uncommittedWidth;
</span><del>-        committedLogicalRight += committedWidth;
</del><span class="cx">         committedTrailingWhitespaceWidth = uncomittedTrailingWhitespaceWidth;
</span><span class="cx">         committedTrailingWhitespaceLength = uncomittedTrailingWhitespaceLength;
</span><span class="cx">         if (!m_firstCharacterFits)
</span><span class="lines">@@ -245,16 +244,20 @@
</span><span class="cx">         uncommittedWidth = 0;
</span><span class="cx">         uncomittedTrailingWhitespaceWidth = 0;
</span><span class="cx">         uncomittedTrailingWhitespaceLength = 0;
</span><ins>+        m_newUncommittedSegment = true;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     void addUncommitted(const FlowContents::TextFragment&amp; fragment)
</span><span class="cx">     {
</span><del>-        unsigned uncomittedFragmentLength = fragment.end - uncommittedEnd;
</del><ins>+        // Start a new uncommitted segment.
+        if (m_newUncommittedSegment) {
+            uncommittedStart = fragment.start;
+            m_newUncommittedSegment = false;
+        }
</ins><span class="cx">         uncommittedWidth += fragment.width;
</span><span class="cx">         uncommittedEnd = fragment.end;
</span><del>-        position = uncommittedEnd;
</del><span class="cx">         uncomittedTrailingWhitespaceWidth = fragment.type == FlowContents::TextFragment::Whitespace ? fragment.width : 0;
</span><del>-        uncomittedTrailingWhitespaceLength = fragment.type == FlowContents::TextFragment::Whitespace ? uncomittedFragmentLength  : 0;
</del><ins>+        uncomittedTrailingWhitespaceLength = fragment.type == FlowContents::TextFragment::Whitespace ? fragment.end - fragment.start  : 0;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     void addUncommittedWhitespace(float whitespaceWidth)
</span><span class="lines">@@ -262,16 +265,6 @@
</span><span class="cx">         addUncommitted(FlowContents::TextFragment(uncommittedEnd, uncommittedEnd + 1, whitespaceWidth, true));
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    void jumpTo(unsigned newPositon, float logicalRight)
-    {
-        position = newPositon;
-
-        uncommittedStart = newPositon;
-        uncommittedEnd = newPositon;
-        uncommittedWidth = 0;
-        committedLogicalRight = logicalRight;
-    }
-
</del><span class="cx">     bool hasWhitespaceOnly() const
</span><span class="cx">     {
</span><span class="cx">         return committedTrailingWhitespaceWidth &amp;&amp; committedWidth == committedTrailingWhitespaceWidth;
</span><span class="lines">@@ -290,29 +283,25 @@
</span><span class="cx">     void removeTrailingWhitespace()
</span><span class="cx">     {
</span><span class="cx">         committedWidth -= committedTrailingWhitespaceWidth;
</span><del>-        committedLogicalRight -= committedTrailingWhitespaceWidth;
</del><span class="cx">         committedTrailingWhitespaceWidth = 0;
</span><span class="cx">         committedTrailingWhitespaceLength = 0;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     float availableWidth { 0 };
</span><span class="cx">     float logicalLeftOffset { 0 };
</span><del>-    unsigned lineStartRunIndex { 0 }; // The run that the line starts with.
-    unsigned position { 0 };
</del><span class="cx"> 
</span><span class="cx">     unsigned uncommittedStart { 0 };
</span><span class="cx">     unsigned uncommittedEnd { 0 };
</span><span class="cx">     float uncommittedWidth { 0 };
</span><span class="cx">     float committedWidth { 0 };
</span><del>-
-    float committedLogicalRight { 0 }; // Last committed X (coordinate) position.
</del><span class="cx">     float committedTrailingWhitespaceWidth { 0 }; // Use this to remove trailing whitespace without re-mesuring the text.
</span><span class="cx">     unsigned committedTrailingWhitespaceLength { 0 };
</span><span class="cx">     // Having one character on the line does not necessarily mean it actually fits.
</span><span class="cx">     // First character of the first fragment might be forced on to the current line even if it does not fit.
</span><span class="cx">     bool m_firstCharacterFits { false };
</span><ins>+    bool m_newUncommittedSegment { true };
</ins><span class="cx"> 
</span><del>-    FlowContents::TextFragment oveflowedFragment;
</del><ins>+    FlowContents::TextFragment overflowedFragment;
</ins><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx">     float uncomittedTrailingWhitespaceWidth { 0 };
</span><span class="lines">@@ -356,47 +345,6 @@
</span><span class="cx">     availableWidth = std::max&lt;float&gt;(0, logicalRightOffset - logicalLeftOffset);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static LineState initializeNewLine(const LineState&amp; previousLine, const RenderBlockFlow&amp; flow, const FlowContents&amp; flowContents, unsigned lineStartRunIndex)
-{
-    LineState lineState;
-    lineState.jumpTo(previousLine.position, 0);
-    lineState.lineStartRunIndex = lineStartRunIndex;
-    updateLineConstrains(flow, lineState.availableWidth, lineState.logicalLeftOffset);
-
-    // Handle overflowed fragment from previous line.
-    auto overflowedFragment = previousLine.oveflowedFragment;
-    unsigned linePositon = previousLine.position;
-    // Special overflow pre-wrap whitespace handling: ignore the overflowed whitespace if we managed to fit at least one character on the previous line.
-    // When the line is too short to fit one character (thought it still stays on the line) we continue with the overflow whitespace content on this line.
-    const auto&amp; style = flowContents.style();
-    if (overflowedFragment.type == FlowContents::TextFragment::Whitespace &amp;&amp; preWrap(style) &amp;&amp; previousLine.m_firstCharacterFits) {
-        linePositon = overflowedFragment.end;
-        overflowedFragment = FlowContents::TextFragment();
-        // If skipping the whitespace puts us on a hard newline, skip the newline too as we already wrapped the line.
-        if (flowContents.isLineBreak(linePositon))
-            ++linePositon;
-    }
-
-    if (overflowedFragment.isEmpty()) {
-        if (style.collapseWhitespace) {
-            auto firstFragment = flowContents.nextTextFragment(linePositon, 0);
-            if (firstFragment.type == FlowContents::TextFragment::Whitespace)
-                linePositon = firstFragment.end;
-        }
-        lineState.jumpTo(linePositon, 0);
-        return lineState;
-    }
-
-    if (lineState.fits(overflowedFragment.width)) {
-        lineState.addUncommitted(overflowedFragment);
-        return lineState;
-    }
-
-    // Start over with this fragment.
-    lineState.jumpTo(overflowedFragment.start, 0);
-    return lineState;
-}
-
</del><span class="cx"> static FlowContents::TextFragment splitFragmentToFitLine(FlowContents::TextFragment&amp; fragmentToSplit, float availableWidth, bool keepAtLeastOneCharacter, const FlowContents&amp; flowContents)
</span><span class="cx"> {
</span><span class="cx">     // Fast path for single char fragments.
</span><span class="lines">@@ -438,88 +386,107 @@
</span><span class="cx">     return fragmentForNextLine;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static bool createLineRuns(LineState&amp; lineState, Layout::RunVector&amp; lineRuns, const FlowContents&amp; flowContents)
</del><ins>+static FlowContents::TextFragment firstFragment(FlowContents&amp; flowContents, const LineState&amp; previousLine)
</ins><span class="cx"> {
</span><ins>+    // Handle overflowed fragment from previous line.
+    FlowContents::TextFragment firstFragment = previousLine.overflowedFragment;
</ins><span class="cx">     const auto&amp; style = flowContents.style();
</span><ins>+
+    if (firstFragment.isEmpty())
+        firstFragment = flowContents.nextTextFragment();
+    else {
+        // Special overflow pre-wrap whitespace handling: ignore the overflowed whitespace if we managed to fit at least one character on the previous line.
+        // When the line is too short to fit one character (thought it still stays on the line) we continue with the overflow whitespace content on this line.
+        if (firstFragment.type == FlowContents::TextFragment::Whitespace &amp;&amp; preWrap(style) &amp;&amp; previousLine.m_firstCharacterFits) {
+            firstFragment = flowContents.nextTextFragment();
+            // If skipping the whitespace puts us on a hard newline, skip the newline too as we already wrapped the line.
+            if (firstFragment.type == FlowContents::TextFragment::LineBreak)
+                firstFragment = flowContents.nextTextFragment();
+        }
+    }
+
+    // Check if we need to skip the leading whitespace.
+    if (style.collapseWhitespace &amp;&amp; firstFragment.type == FlowContents::TextFragment::Whitespace)
+        firstFragment = flowContents.nextTextFragment();
+    return firstFragment;
+}
+
+static bool createLineRuns(LineState&amp; line, const LineState&amp; previousLine, Layout::RunVector&amp; lineRuns, FlowContents&amp; flowContents)
+{
+    const auto&amp; style = flowContents.style();
</ins><span class="cx">     bool lineCanBeWrapped = style.wrapLines || style.breakWordOnOverflow;
</span><del>-    while (!flowContents.isEnd(lineState.position)) {
-        // Find the next text fragment.
-        auto fragment = flowContents.nextTextFragment(lineState.position, lineState.width());
</del><ins>+    auto fragment = firstFragment(flowContents, previousLine);
+    while (!fragment.isEmpty()) {
</ins><span class="cx">         // Hard linebreak.
</span><span class="cx">         if (fragment.type == FlowContents::TextFragment::LineBreak) {
</span><del>-            if (lineState.width()) {
-                // No need to add the new line fragment if there's already content on the line. We are about to close this line anyway.
-                ++lineState.position;
-            } else
-                lineState.addUncommitted(fragment);
</del><ins>+            // Add the new line fragment only if there's nothing on the line. (otherwise the extra new line character would show up at the end of the content.)
+            if (!line.width())
+                line.addUncommitted(fragment);
</ins><span class="cx">             break;
</span><span class="cx">         }
</span><del>-        if (lineCanBeWrapped &amp;&amp; !lineState.fits(fragment.width)) {
</del><ins>+        if (lineCanBeWrapped &amp;&amp; !line.fits(fragment.width)) {
</ins><span class="cx">             // Overflow wrapping behaviour:
</span><span class="cx">             // 1. Whitesapce collapse on: whitespace is skipped. Jump to next line.
</span><span class="cx">             // 2. Whitespace collapse off: whitespace is wrapped.
</span><span class="cx">             // 3. First, non-whitespace fragment is either wrapped or kept on the line. (depends on overflow-wrap)
</span><span class="cx">             // 4. Non-whitespace fragment when there's already another fragment on the line gets pushed to the next line.
</span><del>-            bool emptyLine = !lineState.width();
</del><ins>+            bool emptyLine = !line.width();
</ins><span class="cx">             // Whitespace fragment.
</span><span class="cx">             if (fragment.type == FlowContents::TextFragment::Whitespace) {
</span><del>-                if (style.collapseWhitespace) {
-                    // Whitespace collapse is on: whitespace that doesn't fit is simply skipped.
-                    lineState.position = fragment.end;
-                    break;
</del><ins>+                if (!style.collapseWhitespace) {
+                    // Split the fragment; (modified)fragment stays on this line, overflowedFragment is pushed to next line.
+                    line.overflowedFragment = splitFragmentToFitLine(fragment, line.availableWidth - line.width(), emptyLine, flowContents);
+                    line.addUncommitted(fragment);
</ins><span class="cx">                 }
</span><del>-                // Split the fragment; (modified)fragment stays on this line, oveflowedFragment is pushed to next line.
-                lineState.oveflowedFragment = splitFragmentToFitLine(fragment, lineState.availableWidth - lineState.width(), emptyLine, flowContents);
-                lineState.addUncommitted(fragment);
</del><ins>+                // When whitespace collapse is on, whitespace that doesn't fit is simply skipped.
</ins><span class="cx">                 break;
</span><span class="cx">             }
</span><span class="cx">             // Non-whitespace fragment. (!style.wrapLines: bug138102(preserve existing behavior)
</span><span class="cx">             if ((emptyLine &amp;&amp; style.breakWordOnOverflow) || !style.wrapLines) {
</span><del>-                // Split the fragment; (modified)fragment stays on this line, oveflowedFragment is pushed to next line.
-                lineState.oveflowedFragment = splitFragmentToFitLine(fragment, lineState.availableWidth - lineState.width(), emptyLine, flowContents);
-                lineState.addUncommitted(fragment);
</del><ins>+                // Split the fragment; (modified)fragment stays on this line, overflowedFragment is pushed to next line.
+                line.overflowedFragment = splitFragmentToFitLine(fragment, line.availableWidth - line.width(), emptyLine, flowContents);
+                line.addUncommitted(fragment);
</ins><span class="cx">                 break;
</span><span class="cx">             }
</span><span class="cx">             // Non-breakable non-whitespace first fragment. Add it to the current line. -it overflows though.
</span><span class="cx">             if (emptyLine) {
</span><del>-                lineState.addUncommitted(fragment);
</del><ins>+                line.addUncommitted(fragment);
</ins><span class="cx">                 break;
</span><span class="cx">             }
</span><span class="cx">             // Non-breakable non-whitespace fragment when there's already content on the line. Push it to the next line.
</span><del>-            lineState.oveflowedFragment = fragment;
</del><ins>+            line.overflowedFragment = fragment;
</ins><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx">         // When the current fragment is collapsed whitespace, we need to create a run for what we've processed so far.
</span><span class="cx">         if (fragment.isCollapsed) {
</span><span class="cx">             // One trailing whitespace to preserve.
</span><del>-            lineState.addUncommittedWhitespace(style.spaceWidth);
-            lineState.commitAndCreateRun(lineRuns);
-            // And skip the collapsed whitespace.
-            lineState.jumpTo(fragment.end, lineState.width() + fragment.width - style.spaceWidth);
</del><ins>+            line.addUncommittedWhitespace(style.spaceWidth);
+            line.commitAndCreateRun(lineRuns);
</ins><span class="cx">         } else
</span><del>-            lineState.addUncommitted(fragment);
</del><ins>+            line.addUncommitted(fragment);
+        // Find the next text fragment.
+        fragment = flowContents.nextTextFragment(line.width());
</ins><span class="cx">     }
</span><del>-    lineState.commitAndCreateRun(lineRuns);
-    return flowContents.isEnd(lineState.position) &amp;&amp; lineState.oveflowedFragment.isEmpty();
</del><ins>+    line.commitAndCreateRun(lineRuns);
+    return fragment.isEmpty() &amp;&amp; line.overflowedFragment.isEmpty();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-static void closeLineEndingAndAdjustRuns(LineState&amp; lineState, Layout::RunVector&amp; lineRuns, unsigned&amp; lineCount, const FlowContents&amp; flowContents)
</del><ins>+static void closeLineEndingAndAdjustRuns(LineState&amp; line, Layout::RunVector&amp; runs, unsigned previousRunCount, unsigned&amp; lineCount, const FlowContents&amp; flowContents)
</ins><span class="cx"> {
</span><del>-    if (lineState.lineStartRunIndex == lineRuns.size())
</del><ins>+    if (previousRunCount == runs.size())
</ins><span class="cx">         return;
</span><del>-
-    ASSERT(lineRuns.size());
-    removeTrailingWhitespace(lineState, lineRuns, flowContents);
</del><ins>+    ASSERT(runs.size());
+    removeTrailingWhitespace(line, runs, flowContents);
+    if (!runs.size())
+        return;
</ins><span class="cx">     // Adjust runs' position by taking line's alignment into account.
</span><del>-    if (float lineLogicalLeft = computeLineLeft(flowContents.style().textAlign, lineState.availableWidth, lineState.committedWidth, lineState.logicalLeftOffset)) {
-        for (unsigned i = lineState.lineStartRunIndex; i &lt; lineRuns.size(); ++i) {
-            lineRuns[i].logicalLeft += lineLogicalLeft;
-            lineRuns[i].logicalRight += lineLogicalLeft;
</del><ins>+    if (float lineLogicalLeft = computeLineLeft(flowContents.style().textAlign, line.availableWidth, line.committedWidth, line.logicalLeftOffset)) {
+        for (unsigned i = previousRunCount; i &lt; runs.size(); ++i) {
+            runs[i].logicalLeft += lineLogicalLeft;
+            runs[i].logicalRight += lineLogicalLeft;
</ins><span class="cx">         }
</span><span class="cx">     }
</span><del>-    lineRuns.last().isEndOfLine = true;
-    lineState.committedWidth = 0;
-    lineState.committedLogicalRight = 0;
</del><ins>+    runs.last().isEndOfLine = true;
</ins><span class="cx">     ++lineCount;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -552,19 +519,22 @@
</span><span class="cx"> {
</span><span class="cx">     LayoutUnit borderAndPaddingBefore = flow.borderAndPaddingBefore();
</span><span class="cx">     LayoutUnit lineHeight = lineHeightFromFlow(flow);
</span><del>-    LineState lineState;
</del><ins>+    LineState line;
</ins><span class="cx">     bool isEndOfContent = false;
</span><span class="cx">     FlowContents flowContents = FlowContents(flow);
</span><span class="cx"> 
</span><span class="cx">     do {
</span><span class="cx">         flow.setLogicalHeight(lineHeight * lineCount + borderAndPaddingBefore);
</span><del>-        lineState = initializeNewLine(lineState, flow, flowContents, runs.size());
-        isEndOfContent = createLineRuns(lineState, runs, flowContents);
-        closeLineEndingAndAdjustRuns(lineState, runs, lineCount, flowContents);
</del><ins>+        LineState previousLine = line;
+        unsigned previousRunCount = runs.size();
+        line = LineState();
+        updateLineConstrains(flow, line.availableWidth, line.logicalLeftOffset);
+        isEndOfContent = createLineRuns(line, previousLine, runs, flowContents);
+        closeLineEndingAndAdjustRuns(line, runs, previousRunCount, lineCount, flowContents);
</ins><span class="cx">     } while (!isEndOfContent);
</span><span class="cx"> 
</span><span class="cx">     splitRunsAtRendererBoundary(runs, flowContents);
</span><del>-    ASSERT(!lineState.uncommittedWidth);
</del><ins>+    ASSERT(!line.uncommittedWidth);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> std::unique_ptr&lt;Layout&gt; create(RenderBlockFlow&amp; flow)
</span></span></pre></div>
<a id="trunkSourceWebCorerenderingSimpleLineLayoutFlowContentscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/rendering/SimpleLineLayoutFlowContents.cpp (179184 => 179185)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/SimpleLineLayoutFlowContents.cpp        2015-01-27 17:00:08 UTC (rev 179184)
+++ trunk/Source/WebCore/rendering/SimpleLineLayoutFlowContents.cpp        2015-01-27 17:01:07 UTC (rev 179185)
</span><span class="lines">@@ -66,17 +66,23 @@
</span><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-FlowContents::TextFragment FlowContents::nextTextFragment(unsigned position, float xPosition) const
</del><ins>+FlowContents::TextFragment FlowContents::nextTextFragment(float xPosition)
</ins><span class="cx"> {
</span><span class="cx">     // A fragment can either be
</span><span class="cx">     // 1. new line character when preserveNewline is on (not considered as whitespace) or
</span><span class="cx">     // 2. whitespace (collasped, non-collapsed multi or single) or
</span><span class="cx">     // 3. non-whitespace characters.
</span><ins>+    // 4. empty, indicating content end.
</ins><span class="cx">     TextFragment fragment;
</span><del>-    fragment.start = position;
</del><ins>+    fragment.start = m_position;
+    if (isEnd(fragment.start)) {
+        fragment.end = fragment.start;
+        return fragment;
+    }
</ins><span class="cx">     if (isLineBreak(fragment.start)) {
</span><span class="cx">         fragment.type = TextFragment::LineBreak;
</span><span class="cx">         fragment.end = fragment.start + 1;
</span><ins>+        m_position = fragment.end;
</ins><span class="cx">         return fragment;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -98,6 +104,7 @@
</span><span class="cx">             else
</span><span class="cx">                 fragment.width = textWidth(fragment.start, fragment.end, xPosition);
</span><span class="cx">         }
</span><ins>+        m_position = fragment.end;
</ins><span class="cx">         return fragment;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -105,6 +112,7 @@
</span><span class="cx">     fragment.isBreakable = m_style.breakWordOnOverflow;
</span><span class="cx">     fragment.end = findNextBreakablePosition(fragment.start + 1);
</span><span class="cx">     fragment.width = textWidth(fragment.start, fragment.end, xPosition);
</span><ins>+    m_position = fragment.end;
</ins><span class="cx">     return fragment;
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCorerenderingSimpleLineLayoutFlowContentsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/rendering/SimpleLineLayoutFlowContents.h (179184 => 179185)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/SimpleLineLayoutFlowContents.h        2015-01-27 17:00:08 UTC (rev 179184)
+++ trunk/Source/WebCore/rendering/SimpleLineLayoutFlowContents.h        2015-01-27 17:01:07 UTC (rev 179185)
</span><span class="lines">@@ -63,10 +63,8 @@
</span><span class="cx">         bool isBreakable = false;
</span><span class="cx">         float width = 0;
</span><span class="cx">     };
</span><del>-    TextFragment nextTextFragment(unsigned position, float xPosition) const;
</del><ins>+    TextFragment nextTextFragment(float xPosition = 0);
</ins><span class="cx">     float textWidth(unsigned from, unsigned to, float xPosition) const;
</span><del>-    bool isLineBreak(unsigned position) const;
-    bool isEnd(unsigned position) const;
</del><span class="cx"> 
</span><span class="cx">     struct Segment {
</span><span class="cx">         unsigned start;
</span><span class="lines">@@ -98,6 +96,8 @@
</span><span class="cx"> private:
</span><span class="cx">     unsigned findNextNonWhitespacePosition(unsigned position, unsigned&amp; spaceCount) const;
</span><span class="cx">     unsigned findNextBreakablePosition(unsigned position) const;
</span><ins>+    bool isLineBreak(unsigned position) const;
+    bool isEnd(unsigned position) const;
</ins><span class="cx">     unsigned segmentIndexForPosition(unsigned position) const;
</span><span class="cx">     unsigned segmentIndexForPositionSlow(unsigned position) const;
</span><span class="cx"> 
</span><span class="lines">@@ -109,6 +109,7 @@
</span><span class="cx"> 
</span><span class="cx">     mutable LazyLineBreakIterator m_lineBreakIterator;
</span><span class="cx">     mutable unsigned m_lastSegmentIndex;
</span><ins>+    unsigned m_position { 0 };
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> inline UChar FlowContents::characterAt(unsigned position) const
</span></span></pre>
</div>
</div>

</body>
</html>