<!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>[212072] branches/safari-603-branch</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/212072">212072</a></dd>
<dt>Author</dt> <dd>matthew_hanson@apple.com</dd>
<dt>Date</dt> <dd>2017-02-09 22:37:27 -0800 (Thu, 09 Feb 2017)</dd>
</dl>

<h3>Log Message</h3>
<pre>Merge <a href="http://trac.webkit.org/projects/webkit/changeset/211382">r211382</a>. rdar://problem/29738514</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#branchessafari603branchSourceWebCoreChangeLog">branches/safari-603-branch/Source/WebCore/ChangeLog</a></li>
<li><a href="#branchessafari603branchSourceWebCoreplatformgraphicsGlyphBufferh">branches/safari-603-branch/Source/WebCore/platform/graphics/GlyphBuffer.h</a></li>
<li><a href="#branchessafari603branchSourceWebCoreplatformgraphicscocoaFontCascadeCocoamm">branches/safari-603-branch/Source/WebCore/platform/graphics/cocoa/FontCascadeCocoa.mm</a></li>
<li><a href="#branchessafari603branchSourceWebCoreplatformgraphicsmacComplexTextControllercpp">branches/safari-603-branch/Source/WebCore/platform/graphics/mac/ComplexTextController.cpp</a></li>
<li><a href="#branchessafari603branchSourceWebCoreplatformgraphicsmacComplexTextControllerh">branches/safari-603-branch/Source/WebCore/platform/graphics/mac/ComplexTextController.h</a></li>
<li><a href="#branchessafari603branchToolsChangeLog">branches/safari-603-branch/Tools/ChangeLog</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="branchessafari603branchSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: branches/safari-603-branch/Source/WebCore/ChangeLog (212071 => 212072)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-603-branch/Source/WebCore/ChangeLog        2017-02-10 06:37:23 UTC (rev 212071)
+++ branches/safari-603-branch/Source/WebCore/ChangeLog        2017-02-10 06:37:27 UTC (rev 212072)
</span><span class="lines">@@ -1,5 +1,84 @@
</span><span class="cx"> 2017-02-09  Matthew Hanson  &lt;matthew_hanson@apple.com&gt;
</span><span class="cx"> 
</span><ins>+        Merge r211382. rdar://problem/29738514
+
+    2017-01-30  Myles C. Maxfield  &lt;mmaxfield@apple.com&gt;
+
+            Correct spacing regression on inter-element complex path shaping on some fonts
+            https://bugs.webkit.org/show_bug.cgi?id=166013
+
+            Reviewed by Simon Fraser.
+
+            This patch brings the implementation of ComplexTextController in-line with the
+            design at https://trac.webkit.org/wiki/ComplexTextController. Previously,
+            ComplexTextController had a few problems:
+            - The total width computed by ComplexTextController didn't match the width if
+            you iterated over the entire string and added up the advances
+            - FontCascade::getGlyphsAndAdvancesForComplexText() tried to compensate for
+            the above by construing the concepts of paint advances as distinct from layout
+            advances
+            - Initial advances were considered part of layout sometimes and part of painting
+            other times, depending on which function reports the information
+            - For RTL runs, the wrong origin was added to the initial advance, and the origin
+            should have been subtracted instead of added
+
+            This patch exhaustively updates every function in ComplexTextController to be
+            consistent with the design linked to above. This design solves all of these
+            problems.
+
+            Tests: ComplexTextControllerTest.InitialAdvanceWithLeftRunInRTL
+                   ComplexTextControllerTest.InitialAdvanceInRTL
+                   ComplexTextControllerTest.InitialAdvanceWithLeftRunInLTR
+                   ComplexTextControllerTest.InitialAdvanceInLTR
+                   ComplexTextControllerTest.InitialAdvanceInRTLNoOrigins
+                   ComplexTextControllerTest.LeadingExpansion
+                   ComplexTextControllerTest.VerticalAdvances
+
+            * platform/graphics/GlyphBuffer.h:
+            (WebCore::GlyphBuffer::setLeadingExpansion): Deleted. No longer necessary.
+            (WebCore::GlyphBuffer::leadingExpansion): Deleted. Ditto.
+            * platform/graphics/cocoa/FontCascadeCocoa.mm:
+            (WebCore::FontCascade::adjustSelectionRectForComplexText): Removed use of
+            unnecessary leadingExpansion().
+            (WebCore::FontCascade::getGlyphsAndAdvancesForComplexText): This function needs
+            to compute paint advances, which means that it can't base this information off
+            of layout advances. This function uses the trick mentioned at the end of the
+            above link to compute the paint offset of an arbitrary glyph in the middle of
+            an RTL run.
+            * platform/graphics/mac/ComplexTextController.cpp:
+            (WebCore::ComplexTextController::computeExpansionOpportunity): Refactored for
+            testing.
+            (WebCore::ComplexTextController::ComplexTextController): Ditto.
+            (WebCore::ComplexTextController::finishConstruction): Ditto.
+            (WebCore::ComplexTextController::offsetForPosition): This function operates on
+            layout advances, and the initial layout advance is already added into the
+            m_adjustedBaseAdvances vector by adjustGlyphsAndAdvances(). Therefore, there is
+            no need to add it again here.
+            (WebCore::ComplexTextController::advance): This function had completely busted
+            logic about the relationship between initial advances and the first origin in
+            each run. Because of the fortunate choice of only representing layout advances
+            in m_adjustedBaseAdvances, this entire block can be removed and the raw paint
+            initial advance can be reported to the GlyphBuffer. Later in the function, we
+            have to update the logic about how to compute a paint advance given a layout
+            advance and some origins. In particular, there are two tricky pieces here: 1.
+            The layout advance for the first glyph is equal to (initial advance - first
+            origin + first Core Text advance, so computing the paint offset must cancel out
+            the initial layout offset, and 2. the last paint advance in a run must actually
+            end up at the position of the first glyph in the next run, so the next run's
+            initial advance must be queried.
+            (WebCore::ComplexTextController::adjustGlyphsAndAdvances): Previously, we
+            represented an initial advance of a successive run by just adding it to the
+            previous run's last advance. However, this is incompatible with the new model
+            presented in the link above, so we remove this section. We also have to add in
+            the logic that the layout advance for the first glyph is equal to the formula
+            presented above.
+            * platform/graphics/mac/ComplexTextController.h:
+            (WebCore::ComplexTextController::ComplexTextRun::initialAdvance): Adjust comment
+            to reflect reality.
+            (WebCore::ComplexTextController::leadingExpansion): Deleted.
+
+2017-02-09  Matthew Hanson  &lt;matthew_hanson@apple.com&gt;
+
</ins><span class="cx">         Merge r211957. rdar://problem/30029354
</span><span class="cx"> 
</span><span class="cx">     2017-02-09  Antti Koivisto  &lt;antti@apple.com&gt;
</span></span></pre></div>
<a id="branchessafari603branchSourceWebCoreplatformgraphicsGlyphBufferh"></a>
<div class="modfile"><h4>Modified: branches/safari-603-branch/Source/WebCore/platform/graphics/GlyphBuffer.h (212071 => 212072)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-603-branch/Source/WebCore/platform/graphics/GlyphBuffer.h        2017-02-10 06:37:23 UTC (rev 212071)
+++ branches/safari-603-branch/Source/WebCore/platform/graphics/GlyphBuffer.h        2017-02-10 06:37:27 UTC (rev 212072)
</span><span class="lines">@@ -102,9 +102,6 @@
</span><span class="cx"> 
</span><span class="cx">     void setInitialAdvance(GlyphBufferAdvance initialAdvance) { m_initialAdvance = initialAdvance; }
</span><span class="cx">     const GlyphBufferAdvance&amp; initialAdvance() const { return m_initialAdvance; }
</span><del>-
-    void setLeadingExpansion(float leadingExpansion) { m_leadingExpansion = leadingExpansion; }
-    float leadingExpansion() const { return m_leadingExpansion; }
</del><span class="cx">     
</span><span class="cx">     Glyph glyphAt(unsigned index) const
</span><span class="cx">     {
</span><span class="lines">@@ -248,7 +245,6 @@
</span><span class="cx"> #if PLATFORM(WIN)
</span><span class="cx">     Vector&lt;FloatSize, 2048&gt; m_offsets;
</span><span class="cx"> #endif
</span><del>-    float m_leadingExpansion;
</del><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> }
</span></span></pre></div>
<a id="branchessafari603branchSourceWebCoreplatformgraphicscocoaFontCascadeCocoamm"></a>
<div class="modfile"><h4>Modified: branches/safari-603-branch/Source/WebCore/platform/graphics/cocoa/FontCascadeCocoa.mm (212071 => 212072)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-603-branch/Source/WebCore/platform/graphics/cocoa/FontCascadeCocoa.mm        2017-02-10 06:37:23 UTC (rev 212071)
+++ branches/safari-603-branch/Source/WebCore/platform/graphics/cocoa/FontCascadeCocoa.mm        2017-02-10 06:37:27 UTC (rev 212072)
</span><span class="lines">@@ -497,7 +497,7 @@
</span><span class="cx">     float afterWidth = controller.runWidthSoFar();
</span><span class="cx"> 
</span><span class="cx">     if (run.rtl())
</span><del>-        selectionRect.move(controller.totalWidth() - afterWidth + controller.leadingExpansion(), 0);
</del><ins>+        selectionRect.move(controller.totalWidth() - afterWidth, 0);
</ins><span class="cx">     else
</span><span class="cx">         selectionRect.move(beforeWidth, 0);
</span><span class="cx">     selectionRect.setWidth(LayoutUnit::fromFloatCeil(afterWidth - beforeWidth));
</span><span class="lines">@@ -508,20 +508,25 @@
</span><span class="cx">     float initialAdvance;
</span><span class="cx"> 
</span><span class="cx">     ComplexTextController controller(*this, run, false, 0, forTextEmphasis);
</span><del>-    controller.advance(from);
-    float beforeWidth = controller.runWidthSoFar();
</del><ins>+    GlyphBuffer dummyGlyphBuffer;
+    controller.advance(from, &amp;dummyGlyphBuffer);
</ins><span class="cx">     controller.advance(to, &amp;glyphBuffer);
</span><span class="cx"> 
</span><span class="cx">     if (glyphBuffer.isEmpty())
</span><span class="cx">         return 0;
</span><span class="cx"> 
</span><del>-    float afterWidth = controller.runWidthSoFar();
-
</del><span class="cx">     if (run.rtl()) {
</span><del>-        initialAdvance = controller.totalWidth() - afterWidth + controller.leadingExpansion();
</del><ins>+        // Exploit the fact that the sum of the paint advances is equal to
+        // the sum of the layout advances.
+        initialAdvance = controller.totalWidth();
+        for (unsigned i = 0; i &lt; glyphBuffer.size(); ++i)
+            initialAdvance -= glyphBuffer.advanceAt(i).width();
</ins><span class="cx">         glyphBuffer.reverse(0, glyphBuffer.size());
</span><del>-    } else
-        initialAdvance = beforeWidth;
</del><ins>+    } else {
+        initialAdvance = dummyGlyphBuffer.initialAdvance().width();
+        for (unsigned i = 0; i &lt; dummyGlyphBuffer.size(); ++i)
+            initialAdvance += dummyGlyphBuffer.advanceAt(i).width();
+    }
</ins><span class="cx"> 
</span><span class="cx">     return initialAdvance;
</span><span class="cx"> }
</span></span></pre></div>
<a id="branchessafari603branchSourceWebCoreplatformgraphicsmacComplexTextControllercpp"></a>
<div class="modfile"><h4>Modified: branches/safari-603-branch/Source/WebCore/platform/graphics/mac/ComplexTextController.cpp (212071 => 212072)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-603-branch/Source/WebCore/platform/graphics/mac/ComplexTextController.cpp        2017-02-10 06:37:23 UTC (rev 212071)
+++ branches/safari-603-branch/Source/WebCore/platform/graphics/mac/ComplexTextController.cpp        2017-02-10 06:37:27 UTC (rev 212072)
</span><span class="lines">@@ -107,19 +107,12 @@
</span><span class="cx">     return layout.width(from, len, fallbackFonts);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-ComplexTextController::ComplexTextController(const FontCascade&amp; font, const TextRun&amp; run, bool mayUseNaturalWritingDirection, HashSet&lt;const Font*&gt;* fallbackFonts, bool forTextEmphasis)
-    : m_fallbackFonts(fallbackFonts)
-    , m_font(font)
-    , m_run(run)
-    , m_end(run.length())
-    , m_expansion(run.expansion())
-    , m_mayUseNaturalWritingDirection(mayUseNaturalWritingDirection)
-    , m_forTextEmphasis(forTextEmphasis)
</del><ins>+void ComplexTextController::computeExpansionOpportunity()
</ins><span class="cx"> {
</span><span class="cx">     if (!m_expansion)
</span><span class="cx">         m_expansionPerOpportunity = 0;
</span><span class="cx">     else {
</span><del>-        unsigned expansionOpportunityCount = FontCascade::expansionOpportunityCount(m_run.text(), m_run.ltr() ? LTR : RTL, run.expansionBehavior()).first;
</del><ins>+        unsigned expansionOpportunityCount = FontCascade::expansionOpportunityCount(m_run.text(), m_run.ltr() ? LTR : RTL, m_run.expansionBehavior()).first;
</ins><span class="cx"> 
</span><span class="cx">         if (!expansionOpportunityCount)
</span><span class="cx">             m_expansionPerOpportunity = 0;
</span><span class="lines">@@ -126,7 +119,19 @@
</span><span class="cx">         else
</span><span class="cx">             m_expansionPerOpportunity = m_expansion / expansionOpportunityCount;
</span><span class="cx">     }
</span><ins>+}
</ins><span class="cx"> 
</span><ins>+ComplexTextController::ComplexTextController(const FontCascade&amp; font, const TextRun&amp; run, bool mayUseNaturalWritingDirection, HashSet&lt;const Font*&gt;* fallbackFonts, bool forTextEmphasis)
+    : m_fallbackFonts(fallbackFonts)
+    , m_font(font)
+    , m_run(run)
+    , m_end(run.length())
+    , m_expansion(run.expansion())
+    , m_mayUseNaturalWritingDirection(mayUseNaturalWritingDirection)
+    , m_forTextEmphasis(forTextEmphasis)
+{
+    computeExpansionOpportunity();
+
</ins><span class="cx">     collectComplexTextRuns();
</span><span class="cx">     adjustGlyphsAndAdvances();
</span><span class="cx"> 
</span><span class="lines">@@ -140,8 +145,6 @@
</span><span class="cx">             glyphCountSoFar += m_complexTextRuns[i]-&gt;glyphCount();
</span><span class="cx">         }
</span><span class="cx">     }
</span><del>-
-    m_runWidthSoFar = m_leadingExpansion;
</del><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> unsigned ComplexTextController::offsetForPosition(float h, bool includePartialGlyphs)
</span><span class="lines">@@ -149,7 +152,6 @@
</span><span class="cx">     if (h &gt;= m_totalWidth)
</span><span class="cx">         return m_run.ltr() ? m_end : 0;
</span><span class="cx"> 
</span><del>-    h -= m_leadingExpansion;
</del><span class="cx">     if (h &lt; 0)
</span><span class="cx">         return m_run.ltr() ? 0 : m_end;
</span><span class="cx"> 
</span><span class="lines">@@ -163,8 +165,6 @@
</span><span class="cx">         for (unsigned j = 0; j &lt; complexTextRun.glyphCount(); ++j) {
</span><span class="cx">             size_t index = offsetIntoAdjustedGlyphs + j;
</span><span class="cx">             CGFloat adjustedAdvance = m_adjustedBaseAdvances[index].width;
</span><del>-            if (!index)
-                adjustedAdvance += complexTextRun.initialAdvance().width;
</del><span class="cx">             if (x &lt; adjustedAdvance) {
</span><span class="cx">                 CFIndex hitGlyphStart = complexTextRun.indexAt(j);
</span><span class="cx">                 CFIndex hitGlyphEnd;
</span><span class="lines">@@ -544,7 +544,7 @@
</span><span class="cx">         offset = m_end;
</span><span class="cx"> 
</span><span class="cx">     if (offset &lt;= m_currentCharacter) {
</span><del>-        m_runWidthSoFar = m_leadingExpansion;
</del><ins>+        m_runWidthSoFar = 0;
</ins><span class="cx">         m_numGlyphsSoFar = 0;
</span><span class="cx">         m_currentRun = 0;
</span><span class="cx">         m_glyphInCurrentRun = 0;
</span><span class="lines">@@ -555,14 +555,14 @@
</span><span class="cx"> 
</span><span class="cx">     size_t runCount = m_complexTextRuns.size();
</span><span class="cx"> 
</span><del>-    unsigned leftmostGlyph = 0;
-    unsigned currentRunIndex = indexOfCurrentRun(leftmostGlyph);
</del><ins>+    unsigned indexOfLeftmostGlyphInCurrentRun = 0; // Relative to the beginning of ComplexTextController.
+    unsigned currentRunIndex = indexOfCurrentRun(indexOfLeftmostGlyphInCurrentRun);
</ins><span class="cx">     while (m_currentRun &lt; runCount) {
</span><span class="cx">         const ComplexTextRun&amp; complexTextRun = *m_complexTextRuns[currentRunIndex];
</span><span class="cx">         bool ltr = complexTextRun.isLTR();
</span><span class="cx">         size_t glyphCount = complexTextRun.glyphCount();
</span><del>-        unsigned g = ltr ? m_glyphInCurrentRun : glyphCount - 1 - m_glyphInCurrentRun;
-        unsigned k = leftmostGlyph + g;
</del><ins>+        unsigned glyphIndexIntoCurrentRun = ltr ? m_glyphInCurrentRun : glyphCount - 1 - m_glyphInCurrentRun;
+        unsigned glyphIndexIntoComplexTextController = indexOfLeftmostGlyphInCurrentRun + glyphIndexIntoCurrentRun;
</ins><span class="cx">         if (fallbackFonts &amp;&amp; &amp;complexTextRun.font() != &amp;m_font.primaryFont())
</span><span class="cx">             fallbackFonts-&gt;add(&amp;complexTextRun.font());
</span><span class="cx"> 
</span><span class="lines">@@ -569,43 +569,45 @@
</span><span class="cx">         // We must store the initial advance for the first glyph we are going to draw.
</span><span class="cx">         // When leftmostGlyph is 0, it represents the first glyph to draw, taking into
</span><span class="cx">         // account the text direction.
</span><del>-        if (glyphBuffer &amp;&amp; !leftmostGlyph) {
-            CGSize initialAdvance = complexTextRun.initialAdvance();
-#if USE_LAYOUT_SPECIFIC_ADVANCES
-            unsigned index = ltr ? 0 : m_adjustedBaseAdvances.size() - 1;
-            initialAdvance.width += glyphOrigin(index).x;
-            initialAdvance.height += glyphOrigin(index).y;
-#endif
-            glyphBuffer-&gt;setInitialAdvance(initialAdvance);
</del><ins>+        if (!indexOfLeftmostGlyphInCurrentRun &amp;&amp; glyphBuffer)
+            glyphBuffer-&gt;setInitialAdvance(complexTextRun.initialAdvance());
</ins><span class="cx"> 
</span><del>-            glyphBuffer-&gt;setLeadingExpansion(m_leadingExpansion);
-        }
-
</del><span class="cx">         while (m_glyphInCurrentRun &lt; glyphCount) {
</span><del>-            unsigned glyphStartOffset = complexTextRun.indexAt(g);
</del><ins>+            unsigned glyphStartOffset = complexTextRun.indexAt(glyphIndexIntoCurrentRun);
</ins><span class="cx">             unsigned glyphEndOffset;
</span><span class="cx">             if (complexTextRun.isMonotonic()) {
</span><span class="cx">                 if (ltr)
</span><del>-                    glyphEndOffset = std::max&lt;unsigned&gt;(glyphStartOffset, static_cast&lt;unsigned&gt;(g + 1 &lt; glyphCount ? complexTextRun.indexAt(g + 1) : complexTextRun.indexEnd()));
</del><ins>+                    glyphEndOffset = std::max&lt;unsigned&gt;(glyphStartOffset, static_cast&lt;unsigned&gt;(glyphIndexIntoCurrentRun + 1 &lt; glyphCount ? complexTextRun.indexAt(glyphIndexIntoCurrentRun + 1) : complexTextRun.indexEnd()));
</ins><span class="cx">                 else
</span><del>-                    glyphEndOffset = std::max&lt;unsigned&gt;(glyphStartOffset, static_cast&lt;unsigned&gt;(g &gt; 0 ? complexTextRun.indexAt(g - 1) : complexTextRun.indexEnd()));
</del><ins>+                    glyphEndOffset = std::max&lt;unsigned&gt;(glyphStartOffset, static_cast&lt;unsigned&gt;(glyphIndexIntoCurrentRun &gt; 0 ? complexTextRun.indexAt(glyphIndexIntoCurrentRun - 1) : complexTextRun.indexEnd()));
</ins><span class="cx">             } else
</span><del>-                glyphEndOffset = complexTextRun.endOffsetAt(g);
</del><ins>+                glyphEndOffset = complexTextRun.endOffsetAt(glyphIndexIntoCurrentRun);
</ins><span class="cx"> 
</span><del>-            CGSize adjustedBaseAdvance = m_adjustedBaseAdvances[k];
</del><ins>+            CGSize adjustedBaseAdvance = m_adjustedBaseAdvances[glyphIndexIntoComplexTextController];
</ins><span class="cx"> 
</span><span class="cx">             if (glyphStartOffset + complexTextRun.stringLocation() &gt;= m_currentCharacter)
</span><span class="cx">                 return;
</span><span class="cx"> 
</span><span class="cx">             if (glyphBuffer &amp;&amp; !m_characterInCurrentGlyph) {
</span><ins>+                auto currentGlyphOrigin = glyphOrigin(glyphIndexIntoComplexTextController);
</ins><span class="cx">                 GlyphBufferAdvance paintAdvance = adjustedBaseAdvance;
</span><del>-#if USE_LAYOUT_SPECIFIC_ADVANCES
-                if (k + 1 &lt; m_adjustedBaseAdvances.size()) {
-                    paintAdvance.setWidth(paintAdvance.width() + glyphOrigin(k + 1).x - glyphOrigin(k).x);
-                    paintAdvance.setHeight(paintAdvance.height() - glyphOrigin(k + 1).y + glyphOrigin(k).y);
</del><ins>+                if (!glyphIndexIntoCurrentRun) {
+                    // The first layout advance of every run includes the &quot;initial layout advance.&quot; However, here, we need
+                    // paint advances, so subtract it out before transforming the layout advance into a paint advance.
+                    paintAdvance.setWidth(paintAdvance.width() - (complexTextRun.initialAdvance().width - currentGlyphOrigin.x));
+                    paintAdvance.setHeight(paintAdvance.height() - (complexTextRun.initialAdvance().height - currentGlyphOrigin.y));
</ins><span class="cx">                 }
</span><del>-#endif
-                glyphBuffer-&gt;add(m_adjustedGlyphs[k], &amp;complexTextRun.font(), paintAdvance, complexTextRun.indexAt(m_glyphInCurrentRun));
</del><ins>+                paintAdvance.setWidth(paintAdvance.width() + glyphOrigin(glyphIndexIntoComplexTextController + 1).x - currentGlyphOrigin.x);
+                paintAdvance.setHeight(paintAdvance.height() + glyphOrigin(glyphIndexIntoComplexTextController + 1).y - currentGlyphOrigin.y);
+                if (glyphIndexIntoCurrentRun == glyphCount - 1 &amp;&amp; currentRunIndex + 1 &lt; runCount) {
+                    // Our paint advance points to the end of the run. However, the next run may have an
+                    // initial advance, and our paint advance needs to point to the location of the next
+                    // glyph. So, we need to add in the next run's initial advance.
+                    paintAdvance.setWidth(paintAdvance.width() - glyphOrigin(glyphIndexIntoComplexTextController + 1).x + m_complexTextRuns[currentRunIndex + 1]-&gt;initialAdvance().width);
+                    paintAdvance.setHeight(paintAdvance.height() - glyphOrigin(glyphIndexIntoComplexTextController + 1).y + m_complexTextRuns[currentRunIndex + 1]-&gt;initialAdvance().height);
+                }
+                paintAdvance.setHeight(-paintAdvance.height()); // Increasing y points down
+                glyphBuffer-&gt;add(m_adjustedGlyphs[glyphIndexIntoComplexTextController], &amp;complexTextRun.font(), paintAdvance, complexTextRun.indexAt(m_glyphInCurrentRun));
</ins><span class="cx">             }
</span><span class="cx"> 
</span><span class="cx">             unsigned oldCharacterInCurrentGlyph = m_characterInCurrentGlyph;
</span><span class="lines">@@ -619,14 +621,14 @@
</span><span class="cx">             m_glyphInCurrentRun++;
</span><span class="cx">             m_characterInCurrentGlyph = 0;
</span><span class="cx">             if (ltr) {
</span><del>-                g++;
-                k++;
</del><ins>+                glyphIndexIntoCurrentRun++;
+                glyphIndexIntoComplexTextController++;
</ins><span class="cx">             } else {
</span><del>-                g--;
-                k--;
</del><ins>+                glyphIndexIntoCurrentRun--;
+                glyphIndexIntoComplexTextController--;
</ins><span class="cx">             }
</span><span class="cx">         }
</span><del>-        currentRunIndex = incrementCurrentRun(leftmostGlyph);
</del><ins>+        currentRunIndex = incrementCurrentRun(indexOfLeftmostGlyphInCurrentRun);
</ins><span class="cx">         m_glyphInCurrentRun = 0;
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="lines">@@ -673,16 +675,6 @@
</span><span class="cx">         unsigned glyphCount = complexTextRun.glyphCount();
</span><span class="cx">         const Font&amp; font = complexTextRun.font();
</span><span class="cx"> 
</span><del>-        // Represent the initial advance for a text run by adjusting the advance
-        // of the last glyph of the previous text run in the glyph buffer.
-        if (!complexTextRun.glyphOrigins() &amp;&amp; runIndex &amp;&amp; m_adjustedBaseAdvances.size()) {
-            CGSize previousAdvance = m_adjustedBaseAdvances.last();
-            previousAdvance.width += complexTextRun.initialAdvance().width;
-            previousAdvance.height -= complexTextRun.initialAdvance().height;
-            m_adjustedBaseAdvances[m_adjustedBaseAdvances.size() - 1] = previousAdvance;
-        }
-        widthSinceLastCommit += complexTextRun.initialAdvance().width;
-
</del><span class="cx">         if (!complexTextRun.isLTR())
</span><span class="cx">             m_isLTROnly = false;
</span><span class="cx"> 
</span><span class="lines">@@ -726,6 +718,15 @@
</span><span class="cx">                 glyph = font.spaceGlyph();
</span><span class="cx">             }
</span><span class="cx"> 
</span><ins>+            if (!i) {
+                advance.width += complexTextRun.initialAdvance().width;
+                advance.height += complexTextRun.initialAdvance().height;
+                if (auto* origins = complexTextRun.glyphOrigins()) {
+                    advance.width -= origins[0].x;
+                    advance.height -= origins[0].y;
+                }
+            }
+
</ins><span class="cx">             advance.width += font.syntheticBoldOffset();
</span><span class="cx"> 
</span><span class="cx">             if (hasExtraSpacing) {
</span><span class="lines">@@ -757,20 +758,17 @@
</span><span class="cx">                     if (m_expansion) {
</span><span class="cx">                         bool expandLeft, expandRight;
</span><span class="cx">                         std::tie(expandLeft, expandRight) = expansionLocation(ideograph, treatAsSpace, m_run.ltr(), afterExpansion, forbidLeadingExpansion, forbidTrailingExpansion, forceLeadingExpansion, forceTrailingExpansion);
</span><ins>+                        m_expansion -= m_expansionPerOpportunity;
+                        advance.width += m_expansionPerOpportunity;
</ins><span class="cx">                         if (expandLeft) {
</span><span class="cx">                             // Increase previous width
</span><del>-                            m_expansion -= m_expansionPerOpportunity;
-                            m_totalWidth += m_expansionPerOpportunity;
</del><span class="cx">                             if (m_adjustedBaseAdvances.isEmpty())
</span><del>-                                m_leadingExpansion = m_expansionPerOpportunity;
</del><ins>+                                complexTextRun.growInitialAdvanceHorizontally(m_expansionPerOpportunity);
</ins><span class="cx">                             else
</span><span class="cx">                                 m_adjustedBaseAdvances.last().width += m_expansionPerOpportunity;
</span><span class="cx">                         }
</span><del>-                        if (expandRight) {
-                            m_expansion -= m_expansionPerOpportunity;
-                            advance.width += m_expansionPerOpportunity;
</del><ins>+                        if (expandRight)
</ins><span class="cx">                             afterExpansion = true;
</span><del>-                        }
</del><span class="cx">                     } else
</span><span class="cx">                         afterExpansion = false;
</span><span class="cx"> 
</span><span class="lines">@@ -787,9 +785,7 @@
</span><span class="cx">             if (m_forTextEmphasis &amp;&amp; (!FontCascade::canReceiveTextEmphasis(ch) || (U_GET_GC_MASK(ch) &amp; U_GC_M_MASK)))
</span><span class="cx">                 glyph = 0;
</span><span class="cx"> 
</span><del>-            advance.height *= -1;
</del><span class="cx">             m_adjustedBaseAdvances.append(advance);
</span><del>-#if USE_LAYOUT_SPECIFIC_ADVANCES
</del><span class="cx">             if (auto* origins = complexTextRun.glyphOrigins()) {
</span><span class="cx">                 ASSERT(m_glyphOrigins.size() &lt; m_adjustedBaseAdvances.size());
</span><span class="cx">                 m_glyphOrigins.grow(m_adjustedBaseAdvances.size());
</span><span class="lines">@@ -796,7 +792,6 @@
</span><span class="cx">                 m_glyphOrigins[m_glyphOrigins.size() - 1] = origins[i];
</span><span class="cx">                 ASSERT(m_glyphOrigins.size() == m_adjustedBaseAdvances.size());
</span><span class="cx">             }
</span><del>-#endif
</del><span class="cx">             m_adjustedGlyphs.append(glyph);
</span><span class="cx">             
</span><span class="cx">             FloatRect glyphBounds = font.boundsForGlyph(glyph);
</span></span></pre></div>
<a id="branchessafari603branchSourceWebCoreplatformgraphicsmacComplexTextControllerh"></a>
<div class="modfile"><h4>Modified: branches/safari-603-branch/Source/WebCore/platform/graphics/mac/ComplexTextController.h (212071 => 212072)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-603-branch/Source/WebCore/platform/graphics/mac/ComplexTextController.h        2017-02-10 06:37:23 UTC (rev 212071)
+++ branches/safari-603-branch/Source/WebCore/platform/graphics/mac/ComplexTextController.h        2017-02-10 06:37:27 UTC (rev 212072)
</span><span class="lines">@@ -51,8 +51,7 @@
</span><span class="cx"> 
</span><span class="cx"> enum GlyphIterationStyle { IncludePartialGlyphs, ByWholeGlyphs };
</span><span class="cx"> 
</span><del>-// ComplexTextController is responsible for rendering and measuring glyphs for
-// complex scripts on macOS and iOS.
</del><ins>+// See https://trac.webkit.org/wiki/ComplexTextController for more information about ComplexTextController.
</ins><span class="cx"> class ComplexTextController {
</span><span class="cx">     WTF_MAKE_FAST_ALLOCATED;
</span><span class="cx"> public:
</span><span class="lines">@@ -74,7 +73,6 @@
</span><span class="cx">     float minGlyphBoundingBoxY() const { return m_minGlyphBoundingBoxY; }
</span><span class="cx">     float maxGlyphBoundingBoxY() const { return m_maxGlyphBoundingBoxY; }
</span><span class="cx"> 
</span><del>-    float leadingExpansion() const { return m_leadingExpansion; }
</del><span class="cx">     
</span><span class="cx"> private:
</span><span class="cx">     class ComplexTextRun : public RefCounted&lt;ComplexTextRun&gt; {
</span><span class="lines">@@ -101,15 +99,33 @@
</span><span class="cx">         const CGGlyph* glyphs() const { return m_glyphs; }
</span><span class="cx"> 
</span><span class="cx">         /*
</span><del>-         *                                              X (Paint glyph position)   X (Paint glyph position)   X (Paint glyph position)
-         *                                             7                          7                          7
-         *                                            /                          /                          /
-         *                                           / (Glyph origin)           / (Glyph origin)           / (Glyph origin)
-         *                                          /                          /                          /
-         *                                         /                          /                          /
-         *                X-----------------------X--------------------------X--------------------------X----&gt;...
-         * (text position ^)  (initial advance)          (base advance)             (base advance)
</del><ins>+         * This is the format of the information CoreText gives us about each run:
+         *
+         *                                        -----&gt;X (Paint glyph position)   X (Paint glyph position)   X (Paint glyph position)
+         *                                       /     7                          7                          7
+         *                                      /     /                          /                          /
+         *                   (Initial advance) /     / (Glyph origin)           / (Glyph origin)           / (Glyph origin)
+         *                  -------------------     /                          /                          /
+         *                 /                       /                          /                          /
+         *                X                       X--------------------------X--------------------------X--------------------------X
+         * (text position ^)                             (base advance)             (base advance)             (base advance)
+         *
+         *
+         *
+         *
+         *
+         * And here is the output we transform this into (for each run):
+         *
+         *                                        -----&gt;X-------------------------&gt;X-------------------------&gt;X
+         *                                       /            (Paint advance)            (Paint advance)       \
+         *                                      /                                                               \
+         *                   (Initial advance) /                                                                 \ (Paint advance)
+         *                  -------------------                                                                   ----------------
+         *                 /                                                                                                      \
+         *                X--------------------------------------------------X--------------------------X--------------------------X
+         * (text position ^)                (layout advance)                       (layout advance)           (layout advance)
</ins><span class="cx">          */
</span><ins>+        void growInitialAdvanceHorizontally(CGFloat delta) { m_initialAdvance.width += delta; }
</ins><span class="cx">         CGSize initialAdvance() const { return m_initialAdvance; }
</span><span class="cx">         const CGSize* baseAdvances() const { return m_baseAdvances; }
</span><span class="cx">         const CGPoint* glyphOrigins() const { return m_glyphOrigins.size() == glyphCount() ? m_glyphOrigins.data() : nullptr; }
</span><span class="lines">@@ -140,6 +156,7 @@
</span><span class="cx">         bool m_isLTR;
</span><span class="cx">         bool m_isMonotonic;
</span><span class="cx">     };
</span><ins>+    void computeExpansionOpportunity();
</ins><span class="cx">     
</span><span class="cx">     static unsigned stringBegin(const ComplexTextRun&amp; run) { return run.stringLocation() + run.indexBegin(); }
</span><span class="cx">     static unsigned stringEnd(const ComplexTextRun&amp; run) { return run.stringLocation() + run.indexEnd(); }
</span><span class="lines">@@ -196,7 +213,6 @@
</span><span class="cx">     unsigned m_characterInCurrentGlyph { 0 };
</span><span class="cx">     float m_expansion { 0 };
</span><span class="cx">     float m_expansionPerOpportunity { 0 };
</span><del>-    float m_leadingExpansion { 0 };
</del><span class="cx"> 
</span><span class="cx">     float m_minGlyphBoundingBoxX { std::numeric_limits&lt;float&gt;::max() };
</span><span class="cx">     float m_maxGlyphBoundingBoxX { std::numeric_limits&lt;float&gt;::min() };
</span></span></pre></div>
<a id="branchessafari603branchToolsChangeLog"></a>
<div class="modfile"><h4>Modified: branches/safari-603-branch/Tools/ChangeLog (212071 => 212072)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-603-branch/Tools/ChangeLog        2017-02-10 06:37:23 UTC (rev 212071)
+++ branches/safari-603-branch/Tools/ChangeLog        2017-02-10 06:37:27 UTC (rev 212072)
</span><span class="lines">@@ -1,5 +1,24 @@
</span><span class="cx"> 2017-02-09  Matthew Hanson  &lt;matthew_hanson@apple.com&gt;
</span><span class="cx"> 
</span><ins>+        Merge r211382. rdar://problem/29738514
+
+    2017-01-30  Myles C. Maxfield  &lt;mmaxfield@apple.com&gt;
+
+            Correct spacing regression on inter-element complex path shaping on some fonts
+            https://bugs.webkit.org/show_bug.cgi?id=166013
+
+            Reviewed by Simon Fraser.
+
+            Unskip existing tests and make some new tests:
+            - Testing complex text with no origins
+            - Testing initial expansions
+            - Testing the sign of vertical advances
+
+            * TestWebKitAPI/Tests/WebCore/ComplexTextController.cpp:
+            (TestWebKitAPI::TEST_F):
+
+2017-02-09  Matthew Hanson  &lt;matthew_hanson@apple.com&gt;
+
</ins><span class="cx">         Merge r211915. rdar://problem/27607520
</span><span class="cx"> 
</span><span class="cx">     2017-02-08  Andy Estes  &lt;aestes@apple.com&gt;
</span></span></pre>
</div>
</div>

</body>
</html>