<!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>[179309] 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/179309">179309</a></dd>
<dt>Author</dt> <dd>zalan@apple.com</dd>
<dt>Date</dt> <dd>2015-01-28 15:36:46 -0800 (Wed, 28 Jan 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>Simple line layout: Drop uncommitted/committed terms from LineState.
https://bugs.webkit.org/show_bug.cgi?id=141005

Reviewed by Antti Koivisto.

Fragments form segments and segments turn into runs on the lines.
We add fragments only when they fit so they should not be in 'uncommitted' state at all.

No change in functionality.

* rendering/SimpleLineLayout.cpp:
(WebCore::SimpleLineLayout::LineState::createRun):
(WebCore::SimpleLineLayout::LineState::addFragment):
(WebCore::SimpleLineLayout::LineState::addWhitespace):
(WebCore::SimpleLineLayout::LineState::hasWhitespaceOnly):
(WebCore::SimpleLineLayout::LineState::width):
(WebCore::SimpleLineLayout::LineState::firstCharacterFits):
(WebCore::SimpleLineLayout::LineState::removeTrailingWhitespace):
(WebCore::SimpleLineLayout::removeTrailingWhitespace):
(WebCore::SimpleLineLayout::firstFragment):
(WebCore::SimpleLineLayout::createLineRuns):
(WebCore::SimpleLineLayout::closeLineEndingAndAdjustRuns):
(WebCore::SimpleLineLayout::createTextRuns): Unnecessary assert.
(WebCore::SimpleLineLayout::LineState::commitAndCreateRun): Deleted.
(WebCore::SimpleLineLayout::LineState::addUncommitted): Deleted.
(WebCore::SimpleLineLayout::LineState::addUncommittedWhitespace): Deleted.</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>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (179308 => 179309)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2015-01-28 23:20:36 UTC (rev 179308)
+++ trunk/Source/WebCore/ChangeLog        2015-01-28 23:36:46 UTC (rev 179309)
</span><span class="lines">@@ -1,3 +1,32 @@
</span><ins>+2015-01-28  Zalan Bujtas  &lt;zalan@apple.com&gt;
+
+        Simple line layout: Drop uncommitted/committed terms from LineState.
+        https://bugs.webkit.org/show_bug.cgi?id=141005
+
+        Reviewed by Antti Koivisto.
+
+        Fragments form segments and segments turn into runs on the lines.
+        We add fragments only when they fit so they should not be in 'uncommitted' state at all.
+
+        No change in functionality.
+
+        * rendering/SimpleLineLayout.cpp:
+        (WebCore::SimpleLineLayout::LineState::createRun):
+        (WebCore::SimpleLineLayout::LineState::addFragment):
+        (WebCore::SimpleLineLayout::LineState::addWhitespace):
+        (WebCore::SimpleLineLayout::LineState::hasWhitespaceOnly):
+        (WebCore::SimpleLineLayout::LineState::width):
+        (WebCore::SimpleLineLayout::LineState::firstCharacterFits):
+        (WebCore::SimpleLineLayout::LineState::removeTrailingWhitespace):
+        (WebCore::SimpleLineLayout::removeTrailingWhitespace):
+        (WebCore::SimpleLineLayout::firstFragment):
+        (WebCore::SimpleLineLayout::createLineRuns):
+        (WebCore::SimpleLineLayout::closeLineEndingAndAdjustRuns):
+        (WebCore::SimpleLineLayout::createTextRuns): Unnecessary assert.
+        (WebCore::SimpleLineLayout::LineState::commitAndCreateRun): Deleted.
+        (WebCore::SimpleLineLayout::LineState::addUncommitted): Deleted.
+        (WebCore::SimpleLineLayout::LineState::addUncommittedWhitespace): Deleted.
+
</ins><span class="cx"> 2015-01-28  Chris Dumez  &lt;cdumez@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Regression(r177494): Bad cast to WebKitCSSResourceValue in StyleBuilderConverter::convertMaskImageOperations()
</span></span></pre></div>
<a id="trunkSourceWebCorerenderingSimpleLineLayoutcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/rendering/SimpleLineLayout.cpp (179308 => 179309)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/SimpleLineLayout.cpp        2015-01-28 23:20:36 UTC (rev 179308)
+++ trunk/Source/WebCore/rendering/SimpleLineLayout.cpp        2015-01-28 23:36:46 UTC (rev 179309)
</span><span class="lines">@@ -228,52 +228,52 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> struct LineState {
</span><del>-    void commitAndCreateRun(Layout::RunVector&amp; lineRuns)
</del><ins>+    void createRun(Layout::RunVector&amp; lineRuns)
</ins><span class="cx">     {
</span><del>-        if (uncommittedStart == uncommittedEnd)
</del><ins>+        if (segmentStart == segmentEnd)
</ins><span class="cx">             return;
</span><span class="cx"> 
</span><del>-        lineRuns.append(Run(uncommittedStart, uncommittedEnd, committedWidth, committedWidth + uncommittedWidth, false));
</del><ins>+        lineRuns.append(Run(segmentStart, segmentEnd, runsWidth, runsWidth + segmentWidth, false));
</ins><span class="cx">         // Move uncommitted to committed.
</span><del>-        committedWidth += uncommittedWidth;
-        committedTrailingWhitespaceWidth = uncomittedTrailingWhitespaceWidth;
-        committedTrailingWhitespaceLength = uncomittedTrailingWhitespaceLength;
</del><ins>+        runsWidth += segmentWidth;
+        lastRunTrailingWhitespaceWidth = segmentTrailingWhitespaceWidth;
+        lastRunTrailingWhitespaceLength = segmentTrailingWhitespaceLength;
</ins><span class="cx">         if (!m_firstCharacterFits)
</span><del>-            m_firstCharacterFits = uncommittedStart + 1 &gt; uncommittedEnd || committedWidth &lt;= availableWidth;
</del><ins>+            m_firstCharacterFits = segmentStart + 1 &gt; segmentEnd || runsWidth &lt;= availableWidth;
</ins><span class="cx"> 
</span><del>-        uncommittedStart = uncommittedEnd;
-        uncommittedWidth = 0;
-        uncomittedTrailingWhitespaceWidth = 0;
-        uncomittedTrailingWhitespaceLength = 0;
-        m_newUncommittedSegment = true;
</del><ins>+        segmentStart = segmentEnd;
+        segmentWidth = 0;
+        segmentTrailingWhitespaceWidth = 0;
+        segmentTrailingWhitespaceLength = 0;
+        m_newSegment = true;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    void addUncommitted(const FlowContentsIterator::TextFragment&amp; fragment)
</del><ins>+    void addFragment(const FlowContentsIterator::TextFragment&amp; fragment)
</ins><span class="cx">     {
</span><span class="cx">         // Start a new uncommitted segment.
</span><del>-        if (m_newUncommittedSegment) {
-            uncommittedStart = fragment.start;
-            m_newUncommittedSegment = false;
</del><ins>+        if (m_newSegment) {
+            segmentStart = fragment.start;
+            m_newSegment = false;
</ins><span class="cx">         }
</span><del>-        uncommittedWidth += fragment.width;
-        uncommittedEnd = fragment.end;
-        uncomittedTrailingWhitespaceWidth = fragment.type == FlowContentsIterator::TextFragment::Whitespace ? fragment.width : 0;
-        uncomittedTrailingWhitespaceLength = fragment.type == FlowContentsIterator::TextFragment::Whitespace ? fragment.end - fragment.start  : 0;
</del><ins>+        segmentWidth += fragment.width;
+        segmentEnd = fragment.end;
+        segmentTrailingWhitespaceWidth = fragment.type == FlowContentsIterator::TextFragment::Whitespace ? fragment.width : 0;
+        segmentTrailingWhitespaceLength = fragment.type == FlowContentsIterator::TextFragment::Whitespace ? fragment.end - fragment.start  : 0;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    void addUncommittedWhitespace(float whitespaceWidth)
</del><ins>+    void addWhitespace(float whitespaceWidth)
</ins><span class="cx">     {
</span><del>-        addUncommitted(FlowContentsIterator::TextFragment(uncommittedEnd, uncommittedEnd + 1, whitespaceWidth, true));
</del><ins>+        addFragment(FlowContentsIterator::TextFragment(segmentEnd, segmentEnd + 1, whitespaceWidth, true));
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     bool hasWhitespaceOnly() const
</span><span class="cx">     {
</span><del>-        return committedTrailingWhitespaceWidth &amp;&amp; committedWidth == committedTrailingWhitespaceWidth;
</del><ins>+        return lastRunTrailingWhitespaceWidth &amp;&amp; runsWidth == lastRunTrailingWhitespaceWidth;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     float width() const
</span><span class="cx">     {
</span><del>-        return committedWidth + uncommittedWidth;
</del><ins>+        return runsWidth + segmentWidth;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     bool fits(float extra) const
</span><span class="lines">@@ -281,32 +281,32 @@
</span><span class="cx">         return availableWidth &gt;= width() + extra;
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    bool firstCharacterFits() const { return m_firstCharacterFits; }
+
</ins><span class="cx">     void removeTrailingWhitespace()
</span><span class="cx">     {
</span><del>-        committedWidth -= committedTrailingWhitespaceWidth;
-        committedTrailingWhitespaceWidth = 0;
-        committedTrailingWhitespaceLength = 0;
</del><ins>+        runsWidth -= lastRunTrailingWhitespaceWidth;
+        lastRunTrailingWhitespaceWidth = 0;
+        lastRunTrailingWhitespaceLength = 0;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     float availableWidth { 0 };
</span><span class="cx">     float logicalLeftOffset { 0 };
</span><ins>+    float runsWidth { 0 };
+    float lastRunTrailingWhitespaceWidth { 0 }; // Use this to remove trailing whitespace without re-mesuring the text.
+    unsigned lastRunTrailingWhitespaceLength { 0 };
+    FlowContentsIterator::TextFragment overflowedFragment;
</ins><span class="cx"> 
</span><del>-    unsigned uncommittedStart { 0 };
-    unsigned uncommittedEnd { 0 };
-    float uncommittedWidth { 0 };
-    float committedWidth { 0 };
-    float committedTrailingWhitespaceWidth { 0 }; // Use this to remove trailing whitespace without re-mesuring the text.
-    unsigned committedTrailingWhitespaceLength { 0 };
</del><ins>+private:
+    unsigned segmentStart { 0 };
+    unsigned segmentEnd { 0 };
+    float segmentWidth { 0 };
+    float segmentTrailingWhitespaceWidth { 0 };
+    unsigned segmentTrailingWhitespaceLength { 0 };
</ins><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><del>-    bool m_newUncommittedSegment { true };
-
-    FlowContentsIterator::TextFragment overflowedFragment;
-
-private:
-    float uncomittedTrailingWhitespaceWidth { 0 };
-    unsigned uncomittedTrailingWhitespaceLength { 0 };
</del><ins>+    bool m_newSegment { true };
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> static bool preWrap(const FlowContentsIterator::Style&amp; style)
</span><span class="lines">@@ -316,7 +316,7 @@
</span><span class="cx">     
</span><span class="cx"> static void removeTrailingWhitespace(LineState&amp; lineState, Layout::RunVector&amp; lineRuns, const FlowContentsIterator&amp; flowContentsIterator)
</span><span class="cx"> {
</span><del>-    if (!lineState.committedTrailingWhitespaceLength)
</del><ins>+    if (!lineState.lastRunTrailingWhitespaceLength)
</ins><span class="cx">         return;
</span><span class="cx">     
</span><span class="cx">     // Remove collapsed whitespace, or non-collapsed pre-wrap whitespace, unless it's the only content on the line -so removing the whitesapce would produce an empty line.
</span><span class="lines">@@ -330,8 +330,8 @@
</span><span class="cx"> 
</span><span class="cx">     ASSERT(lineRuns.size());
</span><span class="cx">     Run&amp; lastRun = lineRuns.last();
</span><del>-    lastRun.logicalRight -= lineState.committedTrailingWhitespaceWidth;
-    lastRun.end -= lineState.committedTrailingWhitespaceLength;
</del><ins>+    lastRun.logicalRight -= lineState.lastRunTrailingWhitespaceWidth;
+    lastRun.end -= lineState.lastRunTrailingWhitespaceLength;
</ins><span class="cx">     if (lastRun.start == lastRun.end)
</span><span class="cx">         lineRuns.removeLast();
</span><span class="cx">     lineState.removeTrailingWhitespace();
</span><span class="lines">@@ -398,7 +398,7 @@
</span><span class="cx">     else {
</span><span class="cx">         // Special overflow pre-wrap whitespace handling: ignore the overflowed whitespace if we managed to fit at least one character on the previous line.
</span><span class="cx">         // 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.
</span><del>-        if (firstFragment.type == FlowContentsIterator::TextFragment::Whitespace &amp;&amp; preWrap(style) &amp;&amp; previousLine.m_firstCharacterFits) {
</del><ins>+        if (firstFragment.type == FlowContentsIterator::TextFragment::Whitespace &amp;&amp; preWrap(style) &amp;&amp; previousLine.firstCharacterFits()) {
</ins><span class="cx">             firstFragment = flowContentsIterator.nextTextFragment();
</span><span class="cx">             // If skipping the whitespace puts us on a hard newline, skip the newline too as we already wrapped the line.
</span><span class="cx">             if (firstFragment.type == FlowContentsIterator::TextFragment::LineBreak)
</span><span class="lines">@@ -422,7 +422,7 @@
</span><span class="cx">         if (fragment.type == FlowContentsIterator::TextFragment::LineBreak) {
</span><span class="cx">             // 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.)
</span><span class="cx">             if (!line.width())
</span><del>-                line.addUncommitted(fragment);
</del><ins>+                line.addFragment(fragment);
</ins><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx">         if (lineCanBeWrapped &amp;&amp; !line.fits(fragment.width)) {
</span><span class="lines">@@ -437,7 +437,7 @@
</span><span class="cx">                 if (!style.collapseWhitespace) {
</span><span class="cx">                     // Split the fragment; (modified)fragment stays on this line, overflowedFragment is pushed to next line.
</span><span class="cx">                     line.overflowedFragment = splitFragmentToFitLine(fragment, line.availableWidth - line.width(), emptyLine, flowContentsIterator);
</span><del>-                    line.addUncommitted(fragment);
</del><ins>+                    line.addFragment(fragment);
</ins><span class="cx">                 }
</span><span class="cx">                 // When whitespace collapse is on, whitespace that doesn't fit is simply skipped.
</span><span class="cx">                 break;
</span><span class="lines">@@ -446,12 +446,12 @@
</span><span class="cx">             if ((emptyLine &amp;&amp; style.breakWordOnOverflow) || !style.wrapLines) {
</span><span class="cx">                 // Split the fragment; (modified)fragment stays on this line, overflowedFragment is pushed to next line.
</span><span class="cx">                 line.overflowedFragment = splitFragmentToFitLine(fragment, line.availableWidth - line.width(), emptyLine, flowContentsIterator);
</span><del>-                line.addUncommitted(fragment);
</del><ins>+                line.addFragment(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>-                line.addUncommitted(fragment);
</del><ins>+                line.addFragment(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><span class="lines">@@ -461,14 +461,14 @@
</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>-            line.addUncommittedWhitespace(style.spaceWidth);
-            line.commitAndCreateRun(lineRuns);
</del><ins>+            line.addWhitespace(style.spaceWidth);
+            line.createRun(lineRuns);
</ins><span class="cx">         } else
</span><del>-            line.addUncommitted(fragment);
</del><ins>+            line.addFragment(fragment);
</ins><span class="cx">         // Find the next text fragment.
</span><span class="cx">         fragment = flowContentsIterator.nextTextFragment(line.width());
</span><span class="cx">     }
</span><del>-    line.commitAndCreateRun(lineRuns);
</del><ins>+    line.createRun(lineRuns);
</ins><span class="cx">     return fragment.isEmpty() &amp;&amp; line.overflowedFragment.isEmpty();
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -481,7 +481,7 @@
</span><span class="cx">     if (!runs.size())
</span><span class="cx">         return;
</span><span class="cx">     // Adjust runs' position by taking line's alignment into account.
</span><del>-    if (float lineLogicalLeft = computeLineLeft(flowContentsIterator.style().textAlign, line.availableWidth, line.committedWidth, line.logicalLeftOffset)) {
</del><ins>+    if (float lineLogicalLeft = computeLineLeft(flowContentsIterator.style().textAlign, line.availableWidth, line.runsWidth, line.logicalLeftOffset)) {
</ins><span class="cx">         for (unsigned i = previousRunCount; i &lt; runs.size(); ++i) {
</span><span class="cx">             runs[i].logicalLeft += lineLogicalLeft;
</span><span class="cx">             runs[i].logicalRight += lineLogicalLeft;
</span><span class="lines">@@ -533,7 +533,6 @@
</span><span class="cx"> 
</span><span class="cx">     if (flow.firstChild() != flow.lastChild())
</span><span class="cx">         splitRunsAtRendererBoundary(runs, flowContentsIterator);
</span><del>-    ASSERT(!line.uncommittedWidth);
</del><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>
</div>

</body>
</html>