<!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>[206466] 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/206466">206466</a></dd>
<dt>Author</dt> <dd>mmaxfield@apple.com</dd>
<dt>Date</dt> <dd>2016-09-27 14:58:56 -0700 (Tue, 27 Sep 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>[Cocoa] Improve performance of complex text codepath
https://bugs.webkit.org/show_bug.cgi?id=161936

Reviewed by Simon Fraser.

CoreText exposes a bit on the CTRunStatus which represents whether
the run actually uses the glyph origins concept introduced in
<a href="http://trac.webkit.org/projects/webkit/changeset/205396">r205396</a>. If this bit is not set, we can use the (slightly faster)
call to CTRunGetAdvances() instead of
CTRunGetBaseAdvancesAndOrigins(). In addition, if none of the runs
have this bit set, we don't need to allocate storage for the vector
of origins at all, thereby using less memory.

No new tests because there is no behavior change.

* platform/graphics/mac/ComplexTextController.cpp:
(WebCore::ComplexTextController::advance):
(WebCore::ComplexTextController::adjustGlyphsAndAdvances):
* platform/graphics/mac/ComplexTextController.h:
(WebCore::ComplexTextController::ComplexTextRun::glyphOrigins):
(WebCore::ComplexTextController::glyphOrigin):
* platform/graphics/mac/ComplexTextControllerCoreText.mm:
(WebCore::ComplexTextController::ComplexTextRun::ComplexTextRun):
* platform/spi/cocoa/CoreTextSPI.h:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsmacComplexTextControllercpp">trunk/Source/WebCore/platform/graphics/mac/ComplexTextController.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsmacComplexTextControllerh">trunk/Source/WebCore/platform/graphics/mac/ComplexTextController.h</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsmacComplexTextControllerCoreTextmm">trunk/Source/WebCore/platform/graphics/mac/ComplexTextControllerCoreText.mm</a></li>
<li><a href="#trunkSourceWebCoreplatformspicocoaCoreTextSPIh">trunk/Source/WebCore/platform/spi/cocoa/CoreTextSPI.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (206465 => 206466)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2016-09-27 21:54:38 UTC (rev 206465)
+++ trunk/Source/WebCore/ChangeLog        2016-09-27 21:58:56 UTC (rev 206466)
</span><span class="lines">@@ -1,3 +1,30 @@
</span><ins>+2016-09-26  Myles C. Maxfield  &lt;mmaxfield@apple.com&gt;
+
+        [Cocoa] Improve performance of complex text codepath
+        https://bugs.webkit.org/show_bug.cgi?id=161936
+
+        Reviewed by Simon Fraser.
+
+        CoreText exposes a bit on the CTRunStatus which represents whether
+        the run actually uses the glyph origins concept introduced in
+        r205396. If this bit is not set, we can use the (slightly faster)
+        call to CTRunGetAdvances() instead of
+        CTRunGetBaseAdvancesAndOrigins(). In addition, if none of the runs
+        have this bit set, we don't need to allocate storage for the vector
+        of origins at all, thereby using less memory.
+
+        No new tests because there is no behavior change.
+
+        * platform/graphics/mac/ComplexTextController.cpp:
+        (WebCore::ComplexTextController::advance):
+        (WebCore::ComplexTextController::adjustGlyphsAndAdvances):
+        * platform/graphics/mac/ComplexTextController.h:
+        (WebCore::ComplexTextController::ComplexTextRun::glyphOrigins):
+        (WebCore::ComplexTextController::glyphOrigin):
+        * platform/graphics/mac/ComplexTextControllerCoreText.mm:
+        (WebCore::ComplexTextController::ComplexTextRun::ComplexTextRun):
+        * platform/spi/cocoa/CoreTextSPI.h:
+
</ins><span class="cx"> 2016-09-27  Ryosuke Niwa  &lt;rniwa@webkit.org&gt;
</span><span class="cx"> 
</span><span class="cx">         Import w3c shadow DOM tests and fix one assertion
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsmacComplexTextControllercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/mac/ComplexTextController.cpp (206465 => 206466)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/mac/ComplexTextController.cpp        2016-09-27 21:54:38 UTC (rev 206465)
+++ trunk/Source/WebCore/platform/graphics/mac/ComplexTextController.cpp        2016-09-27 21:58:56 UTC (rev 206466)
</span><span class="lines">@@ -568,9 +568,9 @@
</span><span class="cx">         if (glyphBuffer &amp;&amp; !leftmostGlyph) {
</span><span class="cx">             CGSize initialAdvance = complexTextRun.initialAdvance();
</span><span class="cx"> #if USE_LAYOUT_SPECIFIC_ADVANCES
</span><del>-            unsigned index = ltr ? 0 : m_glyphOrigins.size() - 1;
-            initialAdvance.width += m_glyphOrigins[index].x;
-            initialAdvance.height += m_glyphOrigins[index].y;
</del><ins>+            unsigned index = ltr ? 0 : m_adjustedBaseAdvances.size() - 1;
+            initialAdvance.width += glyphOrigin(index).x;
+            initialAdvance.height += glyphOrigin(index).y;
</ins><span class="cx"> #endif
</span><span class="cx">             glyphBuffer-&gt;setInitialAdvance(initialAdvance);
</span><span class="cx"> 
</span><span class="lines">@@ -597,8 +597,8 @@
</span><span class="cx">                 GlyphBufferAdvance paintAdvance = adjustedBaseAdvance;
</span><span class="cx"> #if USE_LAYOUT_SPECIFIC_ADVANCES
</span><span class="cx">                 if (k + 1 &lt; m_adjustedBaseAdvances.size()) {
</span><del>-                    paintAdvance.setWidth(paintAdvance.width() + m_glyphOrigins[k + 1].x - m_glyphOrigins[k].x);
-                    paintAdvance.setHeight(paintAdvance.height() - m_glyphOrigins[k + 1].y + m_glyphOrigins[k].y);
</del><ins>+                    paintAdvance.setWidth(paintAdvance.width() + glyphOrigin(k + 1).x - glyphOrigin(k).x);
+                    paintAdvance.setHeight(paintAdvance.height() - glyphOrigin(k + 1).y + glyphOrigin(k).y);
</ins><span class="cx">                 }
</span><span class="cx"> #endif
</span><span class="cx">                 glyphBuffer-&gt;add(m_adjustedGlyphs[k], &amp;complexTextRun.font(), paintAdvance, complexTextRun.indexAt(m_glyphInCurrentRun));
</span><span class="lines">@@ -786,7 +786,12 @@
</span><span class="cx">             advance.height *= -1;
</span><span class="cx">             m_adjustedBaseAdvances.append(advance);
</span><span class="cx"> #if USE_LAYOUT_SPECIFIC_ADVANCES
</span><del>-            m_glyphOrigins.append(complexTextRun.glyphOrigins()[i]);
</del><ins>+            if (auto* origins = complexTextRun.glyphOrigins()) {
+                ASSERT(m_glyphOrigins.size() &lt; m_adjustedBaseAdvances.size());
+                m_glyphOrigins.grow(m_adjustedBaseAdvances.size());
+                m_glyphOrigins[m_glyphOrigins.size() - 1] = origins[i];
+                ASSERT(m_glyphOrigins.size() == m_adjustedBaseAdvances.size());
+            }
</ins><span class="cx"> #endif
</span><span class="cx">             m_adjustedGlyphs.append(glyph);
</span><span class="cx">             
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsmacComplexTextControllerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/mac/ComplexTextController.h (206465 => 206466)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/mac/ComplexTextController.h        2016-09-27 21:54:38 UTC (rev 206465)
+++ trunk/Source/WebCore/platform/graphics/mac/ComplexTextController.h        2016-09-27 21:58:56 UTC (rev 206466)
</span><span class="lines">@@ -39,6 +39,10 @@
</span><span class="cx"> typedef const struct __CTRun * CTRunRef;
</span><span class="cx"> typedef const struct __CTLine * CTLineRef;
</span><span class="cx"> 
</span><ins>+namespace WTF {
+template&lt;&gt; struct VectorTraits&lt;CGPoint&gt; : SimpleClassVectorTraits { };
+}
+
</ins><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><span class="cx"> class FontCascade;
</span><span class="lines">@@ -48,7 +52,7 @@
</span><span class="cx"> enum GlyphIterationStyle { IncludePartialGlyphs, ByWholeGlyphs };
</span><span class="cx"> 
</span><span class="cx"> // ComplexTextController is responsible for rendering and measuring glyphs for
</span><del>-// complex scripts on OS X.
</del><ins>+// complex scripts on macOS and iOS.
</ins><span class="cx"> class ComplexTextController {
</span><span class="cx">     WTF_MAKE_FAST_ALLOCATED;
</span><span class="cx"> public:
</span><span class="lines">@@ -108,7 +112,7 @@
</span><span class="cx">          */
</span><span class="cx">         CGSize initialAdvance() const { return m_initialAdvance; }
</span><span class="cx">         const CGSize* baseAdvances() const { return m_baseAdvances; }
</span><del>-        const CGPoint* glyphOrigins() const { return m_glyphOrigins.data(); }
</del><ins>+        const CGPoint* glyphOrigins() const { return m_glyphOrigins.size() == glyphCount() ? m_glyphOrigins.data() : nullptr; }
</ins><span class="cx">         bool isLTR() const { return m_isLTR; }
</span><span class="cx">         bool isMonotonic() const { return m_isMonotonic; }
</span><span class="cx">         void setIsNonMonotonic();
</span><span class="lines">@@ -150,6 +154,8 @@
</span><span class="cx"> 
</span><span class="cx">     float runWidthSoFarFraction(unsigned glyphStartOffset, unsigned glyphEndOffset, unsigned oldCharacterInCurrentGlyph, GlyphIterationStyle) const;
</span><span class="cx"> 
</span><ins>+    CGPoint glyphOrigin(unsigned index) const { return index &lt; m_glyphOrigins.size() ? m_glyphOrigins[index] : CGPointZero; }
+
</ins><span class="cx">     Vector&lt;CGSize, 256&gt; m_adjustedBaseAdvances;
</span><span class="cx">     Vector&lt;CGPoint, 256&gt; m_glyphOrigins;
</span><span class="cx">     Vector&lt;CGGlyph, 256&gt; m_adjustedGlyphs;
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsmacComplexTextControllerCoreTextmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/mac/ComplexTextControllerCoreText.mm (206465 => 206466)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/mac/ComplexTextControllerCoreText.mm        2016-09-27 21:54:38 UTC (rev 206465)
+++ trunk/Source/WebCore/platform/graphics/mac/ComplexTextControllerCoreText.mm        2016-09-27 21:58:56 UTC (rev 206466)
</span><span class="lines">@@ -133,18 +133,21 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx"> #if USE_LAYOUT_SPECIFIC_ADVANCES
</span><del>-    m_baseAdvancesVector.grow(m_glyphCount);
-    m_glyphOrigins.grow(m_glyphCount);
-    CTRunGetBaseAdvancesAndOrigins(ctRun, CFRangeMake(0, 0), m_baseAdvancesVector.data(), m_glyphOrigins.data());
-    m_baseAdvances = m_baseAdvancesVector.data();
-#else
-    m_baseAdvances = CTRunGetAdvancesPtr(ctRun);
-    if (!m_baseAdvances) {
</del><ins>+    if (CTRunGetStatus(ctRun) &amp; kCTRunStatusHasOrigins) {
</ins><span class="cx">         m_baseAdvancesVector.grow(m_glyphCount);
</span><del>-        CTRunGetAdvances(ctRun, CFRangeMake(0, 0), m_baseAdvancesVector.data());
</del><ins>+        m_glyphOrigins.grow(m_glyphCount);
+        CTRunGetBaseAdvancesAndOrigins(ctRun, CFRangeMake(0, 0), m_baseAdvancesVector.data(), m_glyphOrigins.data());
</ins><span class="cx">         m_baseAdvances = m_baseAdvancesVector.data();
</span><ins>+    } else
+#endif
+    {
+        m_baseAdvances = CTRunGetAdvancesPtr(ctRun);
+        if (!m_baseAdvances) {
+            m_baseAdvancesVector.grow(m_glyphCount);
+            CTRunGetAdvances(ctRun, CFRangeMake(0, 0), m_baseAdvancesVector.data());
+            m_baseAdvances = m_baseAdvancesVector.data();
+        }
</ins><span class="cx">     }
</span><del>-#endif
</del><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> // Missing glyphs run constructor. Core Text will not generate a run of missing glyphs, instead falling back on
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformspicocoaCoreTextSPIh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/spi/cocoa/CoreTextSPI.h (206465 => 206466)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/spi/cocoa/CoreTextSPI.h        2016-09-27 21:54:38 UTC (rev 206465)
+++ trunk/Source/WebCore/platform/spi/cocoa/CoreTextSPI.h        2016-09-27 21:58:56 UTC (rev 206466)
</span><span class="lines">@@ -54,6 +54,10 @@
</span><span class="cx">     kCTFontDescriptorOptionPreferAppleSystemFont = kCTFontOptionsPreferSystemFont
</span><span class="cx"> };
</span><span class="cx"> 
</span><ins>+enum {
+    kCTRunStatusHasOrigins = (1 &lt;&lt; 4),
+};
+
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx"> WTF_EXTERN_C_BEGIN
</span></span></pre>
</div>
</div>

</body>
</html>