<!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>[169715] trunk</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/169715">169715</a></dd>
<dt>Author</dt> <dd>mmaxfield@apple.com</dd>
<dt>Date</dt> <dd>2014-06-09 14:18:07 -0700 (Mon, 09 Jun 2014)</dd>
</dl>

<h3>Log Message</h3>
<pre>REGRESSION: missing underline under CJK text
https://bugs.webkit.org/show_bug.cgi?id=128145

Reviewed by Darin Adler.

Source/WebCore:
This patch refactors the GlyphToPathTranslator which is used to find intersections of
glyphs and underlines. It was modified to allow for querying these pieces of
information:
1) The extents of the glyph. This can be used to make the underlines skip an entire
glyph, wholesale
2) What kind of skipping behavior should be used
3) The Path which represents the glyph
There are three skipping behaviors:
1) (SkipDescenders) The previous behavior
2) (SkipGlyph) Make the underline skip over the entire glyph, using the extents() function
3) (DrawOverGlyph) Make the underline plow through the glyph, ignoring any descenders

Calculating which underlining behavior to use depends on what the base codepoint that
originated that glyph is. This means that we have to map from glyphs to characters,
something which is nontrivial to do. In order to solve this problem, this patch adds
an optional vector to GlyphBuffer which represents the location in the original string
from which a particular glyph originated. Then, when our WidthIterator code adds
glyphs to the GlyphBuffer, we can include the extra information about where we are
in the input string. Once this data is available, the GlyphPathTranslator can look up
the base codepoint from which this glyph originates, and can run ICU functions on that
codepoint.

We can use the ICU ublock_getCode() function to find which Unicode block a particular
codepoint comes from. If the codepoint comes from a CJK block, we will use
DrawOverGlyph; otherwise, we will use SkipDescenders.

Test: fast/css3-text/css3-text-decoration/text-decoration-skip/text-decoration-skip-ink-cjk.html

* platform/graphics/Font.cpp:
(WebCore::sharedUnderlineType): Look up the base codepoint from which this glyph
originates, call ublock_getCode to get its Unicode block, then return
a GlyphUnderlineType accordingly. This code is shared between SVG and non-SVG.
* platform/graphics/Font.h: New virtual functions in GlyphToPathTranslator, as well as
function signatures for the above two functions.
* platform/graphics/GlyphBuffer.h: Add an optional instance member for the location
from within the original string from which a particular glyph originates.
(WebCore::GlyphBuffer::clear): Updated for new member.
(WebCore::GlyphBuffer::add): Ditto.
(WebCore::GlyphBuffer::saveOffsetsInString): Opt-in to using the new variable
(WebCore::GlyphBuffer::offsetInString): New variable accessor.
* platform/graphics/TextRun.h: SVG needs the TextRun to use sharedUnderlineType.
* platform/graphics/WidthIterator.cpp:
(WebCore::WidthIterator::advanceInternal): Use GlyphBuffer's new variable (if present).
* platform/graphics/mac/ComplexTextController.cpp:
(WebCore::ComplexTextController::advance): Use GlyphBuffer's new variable (if present).
* platform/graphics/mac/FontMac.mm: Implement new GlyphToPathTranslator functions.
(WebCore::MacGlyphToPathTranslator::path):
(WebCore::MacGlyphToPathTranslator::extents):
(WebCore::MacGlyphToPathTranslator::underlineType): Calls sharedUnderlineType().
(WebCore::MacGlyphToPathTranslator::moveToNextValidGlyph):
(WebCore::MacGlyphToPathTranslator::increment):
(WebCore::Font::dashesForIntersectionsWithRect): Ask the translator what kind of underline
behavior should be used. React accordingly.
(WebCore::MacGlyphToPathTranslator::nextPath): Deleted.
(WebCore::MacGlyphToPathTranslator::incrementIndex): Deleted.
* platform/graphics/win/UniscribeController.cpp:
(WebCore::UniscribeController::shapeAndPlaceItem): Update to new signature of GlyphBuffer::add()
* rendering/svg/SVGTextRunRenderingContext.cpp: Implement new GlyphToPathTranslator functions.
(WebCore::SVGGlyphToPathTranslator::SVGGlyphToPathTranslator):
(WebCore::SVGGlyphToPathTranslator::getCurrentTransform):
(WebCore::SVGGlyphToPathTranslator::path):
(WebCore::SVGGlyphToPathTranslator::extents):
(WebCore::MacGlyphToPathTranslator::underlineType): Calls sharedUnderlineType().
(WebCore::SVGGlyphToPathTranslator::moveToNextValidGlyph):
(WebCore::SVGGlyphToPathTranslator::increment):
(WebCore::SVGTextRunRenderingContext::createGlyphToPathTranslator):
(WebCore::SVGTextRunRenderingContext::drawSVGGlyphs):
(WebCore::SVGGlyphToPathTranslator::nextPath): Deleted.
(WebCore::SVGGlyphToPathTranslator::incrementIndex): Deleted.
* rendering/svg/SVGTextRunRenderingContext.h: SVG needs the TextRun to use sharedUnderlineType.

LayoutTests:
This test makes sure that underlines under CJK text don't skip over descenders.

* fast/css3-text/css3-text-decoration/text-decoration-skip/text-decoration-skip-ink-cjk-expected.html: Added.
* fast/css3-text/css3-text-decoration/text-decoration-skip/text-decoration-skip-ink-cjk.html: Added.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestsfastcss3textcss3textdecorationtextdecorationskipresourcesLitherumsvg">trunk/LayoutTests/fast/css3-text/css3-text-decoration/text-decoration-skip/resources/Litherum.svg</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsFontcpp">trunk/Source/WebCore/platform/graphics/Font.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsFonth">trunk/Source/WebCore/platform/graphics/Font.h</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsGlyphBufferh">trunk/Source/WebCore/platform/graphics/GlyphBuffer.h</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsTextRunh">trunk/Source/WebCore/platform/graphics/TextRun.h</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsWidthIteratorcpp">trunk/Source/WebCore/platform/graphics/WidthIterator.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsmacComplexTextControllercpp">trunk/Source/WebCore/platform/graphics/mac/ComplexTextController.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsmacFontMacmm">trunk/Source/WebCore/platform/graphics/mac/FontMac.mm</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicswinUniscribeControllercpp">trunk/Source/WebCore/platform/graphics/win/UniscribeController.cpp</a></li>
<li><a href="#trunkSourceWebCorerenderingsvgSVGTextRunRenderingContextcpp">trunk/Source/WebCore/rendering/svg/SVGTextRunRenderingContext.cpp</a></li>
<li><a href="#trunkSourceWebCorerenderingsvgSVGTextRunRenderingContexth">trunk/Source/WebCore/rendering/svg/SVGTextRunRenderingContext.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsfastcss3textcss3textdecorationtextdecorationskiptextdecorationskipinkcjkexpectedhtml">trunk/LayoutTests/fast/css3-text/css3-text-decoration/text-decoration-skip/text-decoration-skip-ink-cjk-expected.html</a></li>
<li><a href="#trunkLayoutTestsfastcss3textcss3textdecorationtextdecorationskiptextdecorationskipinkcjkhtml">trunk/LayoutTests/fast/css3-text/css3-text-decoration/text-decoration-skip/text-decoration-skip-ink-cjk.html</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (169714 => 169715)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2014-06-09 21:09:09 UTC (rev 169714)
+++ trunk/LayoutTests/ChangeLog        2014-06-09 21:18:07 UTC (rev 169715)
</span><span class="lines">@@ -1,3 +1,15 @@
</span><ins>+2014-05-21  Myles C. Maxfield  &lt;mmaxfield@apple.com&gt;
+
+        REGRESSION: missing underline under CJK text
+        https://bugs.webkit.org/show_bug.cgi?id=128145
+
+        Reviewed by Darin Adler.
+
+        This test makes sure that underlines under CJK text don't skip over descenders.
+
+        * fast/css3-text/css3-text-decoration/text-decoration-skip/text-decoration-skip-ink-cjk-expected.html: Added.
+        * fast/css3-text/css3-text-decoration/text-decoration-skip/text-decoration-skip-ink-cjk.html: Added.
+
</ins><span class="cx"> 2014-06-09  Daniel Bates  &lt;dabates@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [iOS] Amazon app: Cannot interact with product page after tapping on product image
</span></span></pre></div>
<a id="trunkLayoutTestsfastcss3textcss3textdecorationtextdecorationskipresourcesLitherumsvg"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/fast/css3-text/css3-text-decoration/text-decoration-skip/resources/Litherum.svg (169714 => 169715)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/css3-text/css3-text-decoration/text-decoration-skip/resources/Litherum.svg        2014-06-09 21:09:09 UTC (rev 169714)
+++ trunk/LayoutTests/fast/css3-text/css3-text-decoration/text-decoration-skip/resources/Litherum.svg        2014-06-09 21:18:07 UTC (rev 169715)
</span><span class="lines">@@ -7,6 +7,15 @@
</span><span class="cx"> &lt;font-face units-per-em=&quot;56&quot; ascent=&quot;56&quot; descent=&quot;-28&quot;/&gt;
</span><span class="cx"> &lt;glyph unicode=&quot;|&quot; horiz-adv-x=&quot;56&quot; d=&quot;M20 -28v84h16v-84z&quot;/&gt;
</span><span class="cx"> &lt;glyph unicode=&quot;_&quot; horiz-adv-x=&quot;56&quot; d=&quot;M1 -5v1h54v-1z&quot;/&gt;
</span><ins>+&lt;glyph unicode=&quot;體&quot; horiz-adv-x=&quot;56&quot; d=&quot;M20 -28v84h16v-84z&quot;/&gt;
+&lt;glyph unicode=&quot;現&quot; horiz-adv-x=&quot;56&quot; d=&quot;M20 -28v84h16v-84z&quot;/&gt;
+&lt;glyph unicode=&quot;浪&quot; horiz-adv-x=&quot;56&quot; d=&quot;M20 -28v84h16v-84z&quot;/&gt;
+&lt;glyph unicode=&quot;外&quot; horiz-adv-x=&quot;56&quot; d=&quot;M20 -28v84h16v-84z&quot;/&gt;
+&lt;glyph unicode=&quot;装&quot; horiz-adv-x=&quot;56&quot; d=&quot;M20 -28v84h16v-84z&quot;/&gt;
+&lt;glyph unicode=&quot;に&quot; horiz-adv-x=&quot;56&quot; d=&quot;M20 -28v84h16v-84z&quot;/&gt;
+&lt;glyph unicode=&quot;일&quot; horiz-adv-x=&quot;56&quot; d=&quot;M20 -28v84h16v-84z&quot;/&gt;
+&lt;glyph unicode=&quot;서&quot; horiz-adv-x=&quot;56&quot; d=&quot;M20 -28v84h16v-84z&quot;/&gt;
+&lt;glyph unicode=&quot;공&quot; horiz-adv-x=&quot;56&quot; d=&quot;M20 -28v84h16v-84z&quot;/&gt;
</ins><span class="cx"> &lt;/font&gt;
</span><span class="cx"> &lt;/defs&gt;
</span><span class="cx"> &lt;/svg&gt;
</span></span></pre></div>
<a id="trunkLayoutTestsfastcss3textcss3textdecorationtextdecorationskiptextdecorationskipinkcjkexpectedhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/css3-text/css3-text-decoration/text-decoration-skip/text-decoration-skip-ink-cjk-expected.html (0 => 169715)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/css3-text/css3-text-decoration/text-decoration-skip/text-decoration-skip-ink-cjk-expected.html                                (rev 0)
+++ trunk/LayoutTests/fast/css3-text/css3-text-decoration/text-decoration-skip/text-decoration-skip-ink-cjk-expected.html        2014-06-09 21:18:07 UTC (rev 169715)
</span><span class="lines">@@ -0,0 +1,18 @@
</span><ins>+&lt;style&gt;
+@font-face {
+    font-family: 'Litherum';
+    src: url(&quot;./resources/Litherum.svg&quot;) format(svg)
+}
+&lt;/style&gt;
+&lt;meta charset=&quot;utf-8&quot;&gt;
+This test makes sure that underlines under CJK text do not skip over low-hanging curves in the glyphs.
+&lt;div style=&quot;text-decoration: underline; -webkit-text-decoration-skip: none&quot;&gt;
+&lt;p&gt;體現浪漫愛情見證永恆承諾踢走包包面面收毛孔認識世界著名瑞士腕錶品牌美白抗老最強組合即看推介&lt;/p&gt;
+&lt;p&gt;外装に目立つ傷は感じられませんがあくまで中古品ですので新品と比べれば使用感はあると思います&lt;/p&gt;
+&lt;p&gt;일서울올림픽공원올림픽홀에서펼쳐지는을통해신곡그런너를첫공개할예정이어서새로운음악으로관객&lt;/p&gt;
+&lt;div style=&quot;font-family: Litherum&quot;&gt;
+&lt;p&gt;體現浪&lt;/p&gt;
+&lt;p&gt;外装に&lt;/p&gt;
+&lt;p&gt;일서공&lt;/p&gt;
+&lt;/div&gt;
+&lt;/div&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsfastcss3textcss3textdecorationtextdecorationskiptextdecorationskipinkcjkhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/css3-text/css3-text-decoration/text-decoration-skip/text-decoration-skip-ink-cjk.html (0 => 169715)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/css3-text/css3-text-decoration/text-decoration-skip/text-decoration-skip-ink-cjk.html                                (rev 0)
+++ trunk/LayoutTests/fast/css3-text/css3-text-decoration/text-decoration-skip/text-decoration-skip-ink-cjk.html        2014-06-09 21:18:07 UTC (rev 169715)
</span><span class="lines">@@ -0,0 +1,18 @@
</span><ins>+&lt;style&gt;
+@font-face {
+    font-family: 'Litherum';
+    src: url(&quot;./resources/Litherum.svg&quot;) format(svg)
+}
+&lt;/style&gt;
+&lt;meta charset=&quot;utf-8&quot;&gt;
+This test makes sure that underlines under CJK text do not skip over low-hanging curves in the glyphs.
+&lt;div style=&quot;text-decoration: underline;&quot;&gt;
+&lt;p&gt;體現浪漫愛情見證永恆承諾踢走包包面面收毛孔認識世界著名瑞士腕錶品牌美白抗老最強組合即看推介&lt;/p&gt;
+&lt;p&gt;外装に目立つ傷は感じられませんがあくまで中古品ですので新品と比べれば使用感はあると思います&lt;/p&gt;
+&lt;p&gt;일서울올림픽공원올림픽홀에서펼쳐지는을통해신곡그런너를첫공개할예정이어서새로운음악으로관객&lt;/p&gt;
+&lt;div style=&quot;font-family: Litherum&quot;&gt;
+&lt;p&gt;體現浪&lt;/p&gt;
+&lt;p&gt;外装に&lt;/p&gt;
+&lt;p&gt;일서공&lt;/p&gt;
+&lt;/div&gt;
+&lt;/div&gt;
</ins></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (169714 => 169715)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2014-06-09 21:09:09 UTC (rev 169714)
+++ trunk/Source/WebCore/ChangeLog        2014-06-09 21:18:07 UTC (rev 169715)
</span><span class="lines">@@ -1,3 +1,81 @@
</span><ins>+2014-05-21  Myles C. Maxfield  &lt;mmaxfield@apple.com&gt;
+
+        REGRESSION: missing underline under CJK text
+        https://bugs.webkit.org/show_bug.cgi?id=128145
+
+        Reviewed by Darin Adler.
+
+        This patch refactors the GlyphToPathTranslator which is used to find intersections of
+        glyphs and underlines. It was modified to allow for querying these pieces of
+        information:
+        1) The extents of the glyph. This can be used to make the underlines skip an entire
+        glyph, wholesale
+        2) What kind of skipping behavior should be used
+        3) The Path which represents the glyph
+        There are three skipping behaviors:
+        1) (SkipDescenders) The previous behavior
+        2) (SkipGlyph) Make the underline skip over the entire glyph, using the extents() function
+        3) (DrawOverGlyph) Make the underline plow through the glyph, ignoring any descenders
+
+        Calculating which underlining behavior to use depends on what the base codepoint that
+        originated that glyph is. This means that we have to map from glyphs to characters,
+        something which is nontrivial to do. In order to solve this problem, this patch adds
+        an optional vector to GlyphBuffer which represents the location in the original string
+        from which a particular glyph originated. Then, when our WidthIterator code adds
+        glyphs to the GlyphBuffer, we can include the extra information about where we are
+        in the input string. Once this data is available, the GlyphPathTranslator can look up
+        the base codepoint from which this glyph originates, and can run ICU functions on that
+        codepoint.
+
+        We can use the ICU ublock_getCode() function to find which Unicode block a particular
+        codepoint comes from. If the codepoint comes from a CJK block, we will use
+        DrawOverGlyph; otherwise, we will use SkipDescenders.
+
+        Test: fast/css3-text/css3-text-decoration/text-decoration-skip/text-decoration-skip-ink-cjk.html
+
+        * platform/graphics/Font.cpp:
+        (WebCore::sharedUnderlineType): Look up the base codepoint from which this glyph
+        originates, call ublock_getCode to get its Unicode block, then return
+        a GlyphUnderlineType accordingly. This code is shared between SVG and non-SVG.
+        * platform/graphics/Font.h: New virtual functions in GlyphToPathTranslator, as well as
+        function signatures for the above two functions.
+        * platform/graphics/GlyphBuffer.h: Add an optional instance member for the location
+        from within the original string from which a particular glyph originates.
+        (WebCore::GlyphBuffer::clear): Updated for new member.
+        (WebCore::GlyphBuffer::add): Ditto.
+        (WebCore::GlyphBuffer::saveOffsetsInString): Opt-in to using the new variable
+        (WebCore::GlyphBuffer::offsetInString): New variable accessor.
+        * platform/graphics/TextRun.h: SVG needs the TextRun to use sharedUnderlineType.
+        * platform/graphics/WidthIterator.cpp:
+        (WebCore::WidthIterator::advanceInternal): Use GlyphBuffer's new variable (if present).
+        * platform/graphics/mac/ComplexTextController.cpp:
+        (WebCore::ComplexTextController::advance): Use GlyphBuffer's new variable (if present).
+        * platform/graphics/mac/FontMac.mm: Implement new GlyphToPathTranslator functions.
+        (WebCore::MacGlyphToPathTranslator::path):
+        (WebCore::MacGlyphToPathTranslator::extents):
+        (WebCore::MacGlyphToPathTranslator::underlineType): Calls sharedUnderlineType().
+        (WebCore::MacGlyphToPathTranslator::moveToNextValidGlyph):
+        (WebCore::MacGlyphToPathTranslator::increment):
+        (WebCore::Font::dashesForIntersectionsWithRect): Ask the translator what kind of underline
+        behavior should be used. React accordingly.
+        (WebCore::MacGlyphToPathTranslator::nextPath): Deleted.
+        (WebCore::MacGlyphToPathTranslator::incrementIndex): Deleted.
+        * platform/graphics/win/UniscribeController.cpp:
+        (WebCore::UniscribeController::shapeAndPlaceItem): Update to new signature of GlyphBuffer::add()
+        * rendering/svg/SVGTextRunRenderingContext.cpp: Implement new GlyphToPathTranslator functions.
+        (WebCore::SVGGlyphToPathTranslator::SVGGlyphToPathTranslator):
+        (WebCore::SVGGlyphToPathTranslator::getCurrentTransform):
+        (WebCore::SVGGlyphToPathTranslator::path):
+        (WebCore::SVGGlyphToPathTranslator::extents):
+        (WebCore::MacGlyphToPathTranslator::underlineType): Calls sharedUnderlineType().
+        (WebCore::SVGGlyphToPathTranslator::moveToNextValidGlyph):
+        (WebCore::SVGGlyphToPathTranslator::increment):
+        (WebCore::SVGTextRunRenderingContext::createGlyphToPathTranslator):
+        (WebCore::SVGTextRunRenderingContext::drawSVGGlyphs):
+        (WebCore::SVGGlyphToPathTranslator::nextPath): Deleted.
+        (WebCore::SVGGlyphToPathTranslator::incrementIndex): Deleted.
+        * rendering/svg/SVGTextRunRenderingContext.h: SVG needs the TextRun to use sharedUnderlineType.
+
</ins><span class="cx"> 2014-06-09  Alex Christensen  &lt;achristensen@webkit.org&gt;
</span><span class="cx"> 
</span><span class="cx">         [iOS WebGL] Implement OES_vertex_array_object for iOS.
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsFontcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/Font.cpp (169714 => 169715)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/Font.cpp        2014-06-09 21:09:09 UTC (rev 169714)
+++ trunk/Source/WebCore/platform/graphics/Font.cpp        2014-06-09 21:18:07 UTC (rev 169715)
</span><span class="lines">@@ -1053,5 +1053,58 @@
</span><span class="cx"> 
</span><span class="cx">     return true;
</span><span class="cx"> }
</span><ins>+    
+GlyphToPathTranslator::GlyphUnderlineType computeUnderlineType(const TextRun&amp; textRun, const GlyphBuffer&amp; glyphBuffer, int index)
+{
+    // In general, we want to skip descenders. However, skipping descenders on CJK characters leads to undesirable renderings,
+    // so we want to draw through CJK characters (on a character-by-character basis).
+    UChar32 baseCharacter;
+    int offsetInString = glyphBuffer.offsetInString(index);
</ins><span class="cx"> 
</span><ins>+    if (offsetInString == GlyphBuffer::kNoOffset) {
+        // We have no idea which character spawned this glyph. Bail.
+        return GlyphToPathTranslator::GlyphUnderlineType::DrawOverGlyph;
+    }
+    
+    if (textRun.is8Bit())
+        baseCharacter = textRun.characters8()[offsetInString];
+    else {
+        U16_NEXT(textRun.characters16(), offsetInString, textRun.length(), baseCharacter);
+    }
+    
+    // u_getIntPropertyValue with UCHAR_IDEOGRAPHIC doesn't return true for Japanese or Korean codepoints.
+    // Instead, we can use the &quot;Unicode allocation block&quot; for the character.
+    UBlockCode blockCode = ublock_getCode(baseCharacter);
+    switch (blockCode) {
+    case UBLOCK_CJK_RADICALS_SUPPLEMENT:
+    case UBLOCK_CJK_SYMBOLS_AND_PUNCTUATION:
+    case UBLOCK_ENCLOSED_CJK_LETTERS_AND_MONTHS:
+    case UBLOCK_CJK_COMPATIBILITY:
+    case UBLOCK_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A:
+    case UBLOCK_CJK_UNIFIED_IDEOGRAPHS:
+    case UBLOCK_CJK_COMPATIBILITY_IDEOGRAPHS:
+    case UBLOCK_CJK_COMPATIBILITY_FORMS:
+    case UBLOCK_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B:
+    case UBLOCK_CJK_COMPATIBILITY_IDEOGRAPHS_SUPPLEMENT:
+    case UBLOCK_CJK_STROKES:
+    case UBLOCK_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_C:
+    case UBLOCK_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_D:
+    case UBLOCK_IDEOGRAPHIC_DESCRIPTION_CHARACTERS:
+    case UBLOCK_LINEAR_B_IDEOGRAMS:
+    case UBLOCK_ENCLOSED_IDEOGRAPHIC_SUPPLEMENT:
+    case UBLOCK_HIRAGANA:
+    case UBLOCK_KATAKANA:
+    case UBLOCK_BOPOMOFO:
+    case UBLOCK_BOPOMOFO_EXTENDED:
+    case UBLOCK_HANGUL_JAMO:
+    case UBLOCK_HANGUL_COMPATIBILITY_JAMO:
+    case UBLOCK_HANGUL_SYLLABLES:
+    case UBLOCK_HANGUL_JAMO_EXTENDED_A:
+    case UBLOCK_HANGUL_JAMO_EXTENDED_B:
+        return GlyphToPathTranslator::GlyphUnderlineType::DrawOverGlyph;
+    default:
+        return GlyphToPathTranslator::GlyphUnderlineType::SkipDescenders;
+    }
</ins><span class="cx"> }
</span><ins>+
+}
</ins></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsFonth"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/Font.h (169714 => 169715)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/Font.h        2014-06-09 21:09:09 UTC (rev 169714)
+++ trunk/Source/WebCore/platform/graphics/Font.h        2014-06-09 21:18:07 UTC (rev 169715)
</span><span class="lines">@@ -96,10 +96,15 @@
</span><span class="cx"> 
</span><span class="cx"> class GlyphToPathTranslator {
</span><span class="cx"> public:
</span><ins>+    enum class GlyphUnderlineType {SkipDescenders, SkipGlyph, DrawOverGlyph};
</ins><span class="cx">     virtual bool containsMorePaths() = 0;
</span><del>-    virtual Path nextPath() = 0;
</del><ins>+    virtual Path path() = 0;
+    virtual std::pair&lt;float, float&gt; extents() = 0;
+    virtual GlyphUnderlineType underlineType() = 0;
+    virtual void advance() = 0;
</ins><span class="cx">     virtual ~GlyphToPathTranslator() { }
</span><span class="cx"> };
</span><ins>+GlyphToPathTranslator::GlyphUnderlineType computeUnderlineType(const TextRun&amp;, const GlyphBuffer&amp;, int index);
</ins><span class="cx"> 
</span><span class="cx"> class Font {
</span><span class="cx"> public:
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsGlyphBufferh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/GlyphBuffer.h (169714 => 169715)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/GlyphBuffer.h        2014-06-09 21:09:09 UTC (rev 169714)
+++ trunk/Source/WebCore/platform/graphics/GlyphBuffer.h        2014-06-09 21:18:07 UTC (rev 169715)
</span><span class="lines">@@ -83,6 +83,8 @@
</span><span class="cx">         m_fontData.clear();
</span><span class="cx">         m_glyphs.clear();
</span><span class="cx">         m_advances.clear();
</span><ins>+        if (m_offsetsInString)
+            m_offsetsInString-&gt;clear();
</ins><span class="cx"> #if PLATFORM(WIN)
</span><span class="cx">         m_offsets.clear();
</span><span class="cx"> #endif
</span><span class="lines">@@ -121,8 +123,9 @@
</span><span class="cx">         return FloatSize();
</span><span class="cx"> #endif
</span><span class="cx">     }
</span><del>-
-    void add(Glyph glyph, const SimpleFontData* font, float width, const FloatSize* offset = 0)
</del><ins>+    
+    static const int kNoOffset = -1;
+    void add(Glyph glyph, const SimpleFontData* font, float width, int offsetInString = kNoOffset, const FloatSize* offset = 0)
</ins><span class="cx">     {
</span><span class="cx">         m_fontData.append(font);
</span><span class="cx"> 
</span><span class="lines">@@ -149,10 +152,13 @@
</span><span class="cx"> #else
</span><span class="cx">         UNUSED_PARAM(offset);
</span><span class="cx"> #endif
</span><ins>+        
+        if (offsetInString != kNoOffset &amp;&amp; m_offsetsInString)
+            m_offsetsInString-&gt;append(offsetInString);
</ins><span class="cx">     }
</span><span class="cx">     
</span><span class="cx"> #if !USE(WINGDI)
</span><del>-    void add(Glyph glyph, const SimpleFontData* font, GlyphBufferAdvance advance)
</del><ins>+    void add(Glyph glyph, const SimpleFontData* font, GlyphBufferAdvance advance, int offsetInString = kNoOffset)
</ins><span class="cx">     {
</span><span class="cx">         m_fontData.append(font);
</span><span class="cx"> #if USE(CAIRO)
</span><span class="lines">@@ -164,6 +170,9 @@
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx">         m_advances.append(advance);
</span><ins>+        
+        if (offsetInString != kNoOffset &amp;&amp; m_offsetsInString)
+            m_offsetsInString-&gt;append(offsetInString);
</ins><span class="cx">     }
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="lines">@@ -179,6 +188,17 @@
</span><span class="cx">         GlyphBufferAdvance&amp; lastAdvance = m_advances.last();
</span><span class="cx">         lastAdvance.setWidth(lastAdvance.width() + width);
</span><span class="cx">     }
</span><ins>+    
+    void saveOffsetsInString()
+    {
+        m_offsetsInString.reset(new Vector&lt;int, 2048&gt;());
+    }
+    
+    int offsetInString(int index) const
+    {
+        ASSERT(m_offsetsInString);
+        return (*m_offsetsInString)[index];
+    }
</ins><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx">     void swap(int index1, int index2)
</span><span class="lines">@@ -206,6 +226,7 @@
</span><span class="cx">     Vector&lt;GlyphBufferGlyph, 2048&gt; m_glyphs;
</span><span class="cx">     Vector&lt;GlyphBufferAdvance, 2048&gt; m_advances;
</span><span class="cx">     GlyphBufferAdvance m_initialAdvance;
</span><ins>+    std::unique_ptr&lt;Vector&lt;int, 2048&gt;&gt; m_offsetsInString;
</ins><span class="cx"> #if PLATFORM(WIN)
</span><span class="cx">     Vector&lt;FloatSize, 2048&gt; m_offsets;
</span><span class="cx"> #endif
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsTextRunh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/TextRun.h (169714 => 169715)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/TextRun.h        2014-06-09 21:09:09 UTC (rev 169714)
+++ trunk/Source/WebCore/platform/graphics/TextRun.h        2014-06-09 21:18:07 UTC (rev 169715)
</span><span class="lines">@@ -221,7 +221,7 @@
</span><span class="cx">         virtual void drawSVGGlyphs(GraphicsContext*, const SimpleFontData*, const GlyphBuffer&amp;, int from, int to, const FloatPoint&amp;) const = 0;
</span><span class="cx">         virtual float floatWidthUsingSVGFont(const Font&amp;, const TextRun&amp;, int&amp; charsConsumed, String&amp; glyphName) const = 0;
</span><span class="cx">         virtual bool applySVGKerning(const SimpleFontData*, WidthIterator&amp;, GlyphBuffer*, int from) const = 0;
</span><del>-        virtual std::unique_ptr&lt;GlyphToPathTranslator&gt; createGlyphToPathTranslator(const SimpleFontData&amp;, const GlyphBuffer&amp;, int from, int numGlyphs, const FloatPoint&amp;) const = 0;
</del><ins>+        virtual std::unique_ptr&lt;GlyphToPathTranslator&gt; createGlyphToPathTranslator(const SimpleFontData&amp;, const TextRun*, const GlyphBuffer&amp;, int from, int numGlyphs, const FloatPoint&amp;) const = 0;
</ins><span class="cx"> #endif
</span><span class="cx">     };
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsWidthIteratorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/WidthIterator.cpp (169714 => 169715)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/WidthIterator.cpp        2014-06-09 21:09:09 UTC (rev 169714)
+++ trunk/Source/WebCore/platform/graphics/WidthIterator.cpp        2014-06-09 21:18:07 UTC (rev 169715)
</span><span class="lines">@@ -172,7 +172,8 @@
</span><span class="cx">     CharactersTreatedAsSpace charactersTreatedAsSpace;
</span><span class="cx">     while (textIterator.consume(character, clusterLength)) {
</span><span class="cx">         unsigned advanceLength = clusterLength;
</span><del>-        const GlyphData&amp; glyphData = glyphDataForCharacter(character, rtl, textIterator.currentCharacter(), advanceLength);
</del><ins>+        int currentCharacter = textIterator.currentCharacter();
+        const GlyphData&amp; glyphData = glyphDataForCharacter(character, rtl, currentCharacter, advanceLength);
</ins><span class="cx">         Glyph glyph = glyphData.glyph;
</span><span class="cx">         const SimpleFontData* fontData = glyphData.fontData;
</span><span class="cx"> 
</span><span class="lines">@@ -235,16 +236,16 @@
</span><span class="cx">                         if (glyphBuffer) {
</span><span class="cx">                             if (glyphBuffer-&gt;isEmpty()) {
</span><span class="cx">                                 if (m_forTextEmphasis)
</span><del>-                                    glyphBuffer-&gt;add(fontData-&gt;zeroWidthSpaceGlyph(), fontData, m_expansionPerOpportunity);
</del><ins>+                                    glyphBuffer-&gt;add(fontData-&gt;zeroWidthSpaceGlyph(), fontData, m_expansionPerOpportunity, currentCharacter);
</ins><span class="cx">                                 else
</span><del>-                                    glyphBuffer-&gt;add(fontData-&gt;spaceGlyph(), fontData, expansionAtThisOpportunity);
</del><ins>+                                    glyphBuffer-&gt;add(fontData-&gt;spaceGlyph(), fontData, expansionAtThisOpportunity, currentCharacter);
</ins><span class="cx">                             } else
</span><span class="cx">                                 glyphBuffer-&gt;expandLastAdvance(expansionAtThisOpportunity);
</span><span class="cx">                         }
</span><span class="cx">                         previousExpansion = m_expansion;
</span><span class="cx">                     }
</span><del>-                    if (m_run.allowsTrailingExpansion() || (m_run.ltr() &amp;&amp; textIterator.currentCharacter() + advanceLength &lt; static_cast&lt;size_t&gt;(m_run.length()))
-                        || (m_run.rtl() &amp;&amp; textIterator.currentCharacter())) {
</del><ins>+                    if (m_run.allowsTrailingExpansion() || (m_run.ltr() &amp;&amp; currentCharacter + advanceLength &lt; static_cast&lt;size_t&gt;(m_run.length()))
+                        || (m_run.rtl() &amp;&amp; currentCharacter)) {
</ins><span class="cx">                         m_expansion -= m_expansionPerOpportunity;
</span><span class="cx">                         width += !m_run.applyWordRounding() ? m_expansionPerOpportunity : roundf(previousExpansion) - roundf(m_expansion);
</span><span class="cx">                         m_isAfterExpansion = true;
</span><span class="lines">@@ -254,7 +255,7 @@
</span><span class="cx"> 
</span><span class="cx">                 // Account for word spacing.
</span><span class="cx">                 // We apply additional space between &quot;words&quot; by adding width to the space character.
</span><del>-                if (treatAsSpace &amp;&amp; (character != '\t' || !m_run.allowTabs()) &amp;&amp; (textIterator.currentCharacter() || character == noBreakSpace) &amp;&amp; m_font-&gt;wordSpacing())
</del><ins>+                if (treatAsSpace &amp;&amp; (character != '\t' || !m_run.allowTabs()) &amp;&amp; (currentCharacter || character == noBreakSpace) &amp;&amp; m_font-&gt;wordSpacing())
</ins><span class="cx">                     width += m_font-&gt;wordSpacing();
</span><span class="cx">             } else
</span><span class="cx">                 m_isAfterExpansion = false;
</span><span class="lines">@@ -266,7 +267,7 @@
</span><span class="cx"> 
</span><span class="cx">         if (m_accountForGlyphBounds) {
</span><span class="cx">             bounds = fontData-&gt;boundsForGlyph(glyph);
</span><del>-            if (!textIterator.currentCharacter())
</del><ins>+            if (!currentCharacter)
</ins><span class="cx">                 m_firstGlyphOverflow = std::max&lt;float&gt;(0, -bounds.x());
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="lines">@@ -305,7 +306,7 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         if (glyphBuffer)
</span><del>-            glyphBuffer-&gt;add(glyph, fontData, (rtl ? oldWidth + lastRoundingWidth : width));
</del><ins>+            glyphBuffer-&gt;add(glyph, fontData, (rtl ? oldWidth + lastRoundingWidth : width), currentCharacter);
</ins><span class="cx"> 
</span><span class="cx">         lastRoundingWidth = width - oldWidth;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsmacComplexTextControllercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/mac/ComplexTextController.cpp (169714 => 169715)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/mac/ComplexTextController.cpp        2014-06-09 21:09:09 UTC (rev 169714)
+++ trunk/Source/WebCore/platform/graphics/mac/ComplexTextController.cpp        2014-06-09 21:18:07 UTC (rev 169715)
</span><span class="lines">@@ -529,7 +529,7 @@
</span><span class="cx">                 return;
</span><span class="cx"> 
</span><span class="cx">             if (glyphBuffer &amp;&amp; !m_characterInCurrentGlyph)
</span><del>-                glyphBuffer-&gt;add(m_adjustedGlyphs[k], complexTextRun.fontData(), adjustedAdvance);
</del><ins>+                glyphBuffer-&gt;add(m_adjustedGlyphs[k], complexTextRun.fontData(), adjustedAdvance, complexTextRun.indexAt(m_glyphInCurrentRun));
</ins><span class="cx"> 
</span><span class="cx">             unsigned oldCharacterInCurrentGlyph = m_characterInCurrentGlyph;
</span><span class="cx">             m_characterInCurrentGlyph = std::min(m_currentCharacter - complexTextRun.stringLocation(), glyphEndOffset) - glyphStartOffset;
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsmacFontMacmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/mac/FontMac.mm (169714 => 169715)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/mac/FontMac.mm        2014-06-09 21:09:09 UTC (rev 169714)
+++ trunk/Source/WebCore/platform/graphics/mac/FontMac.mm        2014-06-09 21:18:07 UTC (rev 169715)
</span><span class="lines">@@ -448,8 +448,9 @@
</span><span class="cx"> 
</span><span class="cx"> class MacGlyphToPathTranslator final : public GlyphToPathTranslator {
</span><span class="cx"> public:
</span><del>-    MacGlyphToPathTranslator(const GlyphBuffer&amp; glyphBuffer, const FloatPoint&amp; textOrigin)
</del><ins>+    MacGlyphToPathTranslator(const TextRun&amp; textRun, const GlyphBuffer&amp; glyphBuffer, const FloatPoint&amp; textOrigin)
</ins><span class="cx">         : m_index(0)
</span><ins>+        , m_textRun(textRun)
</ins><span class="cx">         , m_glyphBuffer(glyphBuffer)
</span><span class="cx">         , m_fontData(glyphBuffer.fontDataAt(m_index))
</span><span class="cx">         , m_translation(CGAffineTransformScale(CGAffineTransformMakeTranslation(textOrigin.x(), textOrigin.y()), 1, -1))
</span><span class="lines">@@ -461,31 +462,45 @@
</span><span class="cx">     {
</span><span class="cx">         return m_index != m_glyphBuffer.size();
</span><span class="cx">     }
</span><del>-    virtual Path nextPath() override;
</del><ins>+    virtual Path path() override;
+    virtual std::pair&lt;float, float&gt; extents() override;
+    virtual GlyphUnderlineType underlineType() override;
+    virtual void advance() override;
</ins><span class="cx">     void moveToNextValidGlyph();
</span><del>-    void incrementIndex();
</del><span class="cx"> 
</span><span class="cx">     int m_index;
</span><ins>+    const TextRun&amp; m_textRun;
</ins><span class="cx">     const GlyphBuffer&amp; m_glyphBuffer;
</span><span class="cx">     const SimpleFontData* m_fontData;
</span><span class="cx">     CGAffineTransform m_translation;
</span><span class="cx"> };
</span><span class="cx"> 
</span><del>-Path MacGlyphToPathTranslator::nextPath()
</del><ins>+Path MacGlyphToPathTranslator::path()
</ins><span class="cx"> {
</span><span class="cx">     RetainPtr&lt;CGPathRef&gt; result = adoptCF(CTFontCreatePathForGlyph(m_fontData-&gt;platformData().ctFont(), m_glyphBuffer.glyphAt(m_index), &amp;m_translation));
</span><del>-    incrementIndex();
</del><span class="cx">     return adoptCF(CGPathCreateMutableCopy(result.get()));
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+std::pair&lt;float, float&gt; MacGlyphToPathTranslator::extents()
+{
+    CGPoint beginning = CGPointApplyAffineTransform(CGPointMake(0, 0), m_translation);
+    CGSize end = CGSizeApplyAffineTransform(m_glyphBuffer.advanceAt(m_index), m_translation);
+    return std::make_pair(static_cast&lt;float&gt;(beginning.x), static_cast&lt;float&gt;(beginning.x + end.width));
+}
+
+auto MacGlyphToPathTranslator::underlineType() -&gt; GlyphUnderlineType
+{
+    return computeUnderlineType(m_textRun, m_glyphBuffer, m_index);
+}
+
</ins><span class="cx"> void MacGlyphToPathTranslator::moveToNextValidGlyph()
</span><span class="cx"> {
</span><span class="cx">     if (!m_fontData-&gt;isSVGFont())
</span><span class="cx">         return;
</span><del>-    incrementIndex();
</del><ins>+    advance();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void MacGlyphToPathTranslator::incrementIndex()
</del><ins>+void MacGlyphToPathTranslator::advance()
</ins><span class="cx"> {
</span><span class="cx">     do {
</span><span class="cx">         GlyphBufferAdvance advance = m_glyphBuffer.advanceAt(m_index);
</span><span class="lines">@@ -503,6 +518,7 @@
</span><span class="cx">         return DashArray();
</span><span class="cx"> 
</span><span class="cx">     GlyphBuffer glyphBuffer;
</span><ins>+    glyphBuffer.saveOffsetsInString();
</ins><span class="cx">     float deltaX;
</span><span class="cx">     if (codePath(run) != Font::Complex)
</span><span class="cx">         deltaX = getGlyphsAndAdvancesForSimpleText(run, 0, run.length(), glyphBuffer);
</span><span class="lines">@@ -518,23 +534,37 @@
</span><span class="cx">     bool isSVG = false;
</span><span class="cx">     FloatPoint origin = FloatPoint(textOrigin.x() + deltaX, textOrigin.y());
</span><span class="cx">     if (!fontData-&gt;isSVGFont())
</span><del>-        translator = std::move(std::make_unique&lt;MacGlyphToPathTranslator&gt;(glyphBuffer, origin));
</del><ins>+        translator = std::move(std::make_unique&lt;MacGlyphToPathTranslator&gt;(run, glyphBuffer, origin));
</ins><span class="cx">     else {
</span><del>-        translator = std::move(run.renderingContext()-&gt;createGlyphToPathTranslator(*fontData, glyphBuffer, 0, glyphBuffer.size(), origin));
</del><ins>+        translator = std::move(run.renderingContext()-&gt;createGlyphToPathTranslator(*fontData, &amp;run, glyphBuffer, 0, glyphBuffer.size(), origin));
</ins><span class="cx">         isSVG = true;
</span><span class="cx">     }
</span><span class="cx">     DashArray result;
</span><del>-    for (int index = 0; translator-&gt;containsMorePaths(); ++index) {
</del><ins>+    for (int index = 0; translator-&gt;containsMorePaths(); ++index, translator-&gt;advance()) {
</ins><span class="cx">         GlyphIterationState info = GlyphIterationState(CGPointMake(0, 0), CGPointMake(0, 0), lineExtents.y(), lineExtents.y() + lineExtents.height(), lineExtents.x() + lineExtents.width(), lineExtents.x());
</span><span class="cx">         const SimpleFontData* localFontData = glyphBuffer.fontDataAt(index);
</span><span class="cx">         if (!localFontData || (!isSVG &amp;&amp; localFontData-&gt;isSVGFont()) || (isSVG &amp;&amp; localFontData != fontData))
</span><span class="cx">             break; // The advances will get all messed up if we do anything other than bail here.
</span><del>-        Path path = translator-&gt;nextPath();
-        CGPathApply(path.platformPath(), &amp;info, &amp;findPathIntersections);
-        if (info.minX &lt; info.maxX) {
-            result.append(info.minX - lineExtents.x());
-            result.append(info.maxX - lineExtents.x());
</del><ins>+        switch (translator-&gt;underlineType()) {
+        case GlyphToPathTranslator::GlyphUnderlineType::SkipDescenders: {
+            Path path = translator-&gt;path();
+            CGPathApply(path.platformPath(), &amp;info, &amp;findPathIntersections);
+            if (info.minX &lt; info.maxX) {
+                result.append(info.minX - lineExtents.x());
+                result.append(info.maxX - lineExtents.x());
+            }
+            break;
</ins><span class="cx">         }
</span><ins>+        case GlyphToPathTranslator::GlyphUnderlineType::SkipGlyph: {
+            std::pair&lt;float, float&gt; extents = translator-&gt;extents();
+            result.append(extents.first - lineExtents.x());
+            result.append(extents.second - lineExtents.x());
+            break;
+        }
+        case GlyphToPathTranslator::GlyphUnderlineType::DrawOverGlyph:
+            // Nothing to do
+            break;
+        }
</ins><span class="cx">     }
</span><span class="cx">     return result;
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicswinUniscribeControllercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/win/UniscribeController.cpp (169714 => 169715)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/win/UniscribeController.cpp        2014-06-09 21:09:09 UTC (rev 169714)
+++ trunk/Source/WebCore/platform/graphics/win/UniscribeController.cpp        2014-06-09 21:18:07 UTC (rev 169715)
</span><span class="lines">@@ -359,7 +359,7 @@
</span><span class="cx">         // translation.
</span><span class="cx">         if (glyphBuffer) {
</span><span class="cx">             FloatSize size(offsetX, -offsetY);
</span><del>-            glyphBuffer-&gt;add(glyph, fontData, advance, &amp;size);
</del><ins>+            glyphBuffer-&gt;add(glyph, fontData, advance, GlyphBuffer::kNoOffset, &amp;size);
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         FloatRect glyphBounds = fontData-&gt;boundsForGlyph(glyph);
</span></span></pre></div>
<a id="trunkSourceWebCorerenderingsvgSVGTextRunRenderingContextcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/rendering/svg/SVGTextRunRenderingContext.cpp (169714 => 169715)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/svg/SVGTextRunRenderingContext.cpp        2014-06-09 21:09:09 UTC (rev 169714)
+++ trunk/Source/WebCore/rendering/svg/SVGTextRunRenderingContext.cpp        2014-06-09 21:18:07 UTC (rev 169715)
</span><span class="lines">@@ -103,16 +103,21 @@
</span><span class="cx"> 
</span><span class="cx"> class SVGGlyphToPathTranslator final : public GlyphToPathTranslator {
</span><span class="cx"> public:
</span><del>-    SVGGlyphToPathTranslator(const GlyphBuffer&amp; glyphBuffer, const FloatPoint&amp; point, const SVGFontData&amp; svgFontData, SVGFontElement&amp; fontElement, const int from, const int numGlyphs, float scale, bool isVerticalText);
</del><ins>+    SVGGlyphToPathTranslator(const TextRun* const, const GlyphBuffer&amp;, const FloatPoint&amp;, const SVGFontData&amp;, SVGFontElement&amp;, const int from, const int numGlyphs, float scale, bool isVerticalText);
</ins><span class="cx"> private:
</span><span class="cx">     virtual bool containsMorePaths() override
</span><span class="cx">     {
</span><span class="cx">         return m_index != m_stoppingPoint;
</span><span class="cx">     }
</span><del>-    virtual Path nextPath() override;
</del><ins>+
+    virtual Path path() override;
+    virtual std::pair&lt;float, float&gt; extents() override;
+    virtual GlyphUnderlineType underlineType() override;
+    virtual void advance() override;
</ins><span class="cx">     void moveToNextValidGlyph();
</span><del>-    void incrementIndex();
</del><ins>+    AffineTransform transform();
</ins><span class="cx"> 
</span><ins>+    const TextRun* const m_textRun;
</ins><span class="cx">     const GlyphBuffer&amp; m_glyphBuffer;
</span><span class="cx">     const SVGFontData&amp; m_svgFontData;
</span><span class="cx">     FloatPoint m_currentPoint;
</span><span class="lines">@@ -126,8 +131,9 @@
</span><span class="cx">     const bool m_isVerticalText;
</span><span class="cx"> };
</span><span class="cx"> 
</span><del>-SVGGlyphToPathTranslator::SVGGlyphToPathTranslator(const GlyphBuffer&amp; glyphBuffer, const FloatPoint&amp; point, const SVGFontData&amp; svgFontData, SVGFontElement&amp; fontElement, const int from, const int numGlyphs, float scale, bool isVerticalText)
-    : m_glyphBuffer(glyphBuffer)
</del><ins>+SVGGlyphToPathTranslator::SVGGlyphToPathTranslator(const TextRun* const textRun, const GlyphBuffer&amp; glyphBuffer, const FloatPoint&amp; point, const SVGFontData&amp; svgFontData, SVGFontElement&amp; fontElement, const int from, const int numGlyphs, float scale, bool isVerticalText)
+    : m_textRun(textRun)
+    , m_glyphBuffer(glyphBuffer)
</ins><span class="cx">     , m_svgFontData(svgFontData)
</span><span class="cx">     , m_currentPoint(point)
</span><span class="cx">     , m_glyphOrigin(m_svgFontData.horizontalOriginX() * scale, m_svgFontData.horizontalOriginY() * scale)
</span><span class="lines">@@ -148,31 +154,43 @@
</span><span class="cx">     moveToNextValidGlyph();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-Path SVGGlyphToPathTranslator::nextPath()
</del><ins>+AffineTransform SVGGlyphToPathTranslator::transform()
</ins><span class="cx"> {
</span><del>-    if (m_isVerticalText) {
-        m_glyphOrigin.setX(m_svgGlyph.verticalOriginX * m_scale);
-        m_glyphOrigin.setY(m_svgGlyph.verticalOriginY * m_scale);
-    }
-
</del><span class="cx">     AffineTransform glyphPathTransform;
</span><span class="cx">     glyphPathTransform.translate(m_currentPoint.x() + m_glyphOrigin.x(), m_currentPoint.y() + m_glyphOrigin.y());
</span><span class="cx">     glyphPathTransform.scale(m_scale, -m_scale);
</span><ins>+    return glyphPathTransform;
+}
</ins><span class="cx"> 
</span><ins>+Path SVGGlyphToPathTranslator::path()
+{
</ins><span class="cx">     Path glyphPath = m_svgGlyph.pathData;
</span><del>-    glyphPath.transform(glyphPathTransform);
-    incrementIndex();
</del><ins>+    glyphPath.transform(transform());
</ins><span class="cx">     return glyphPath;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+std::pair&lt;float, float&gt; SVGGlyphToPathTranslator::extents()
+{
+    AffineTransform glyphPathTransform = transform();
+    FloatPoint beginning = glyphPathTransform.mapPoint(m_currentPoint);
+    FloatSize end = glyphPathTransform.mapSize(FloatSize(m_glyphBuffer.advanceAt(m_index)));
+    return std::make_pair(beginning.x(), beginning.x() + end.width());
+}
+
+auto SVGGlyphToPathTranslator::underlineType() -&gt; GlyphUnderlineType
+{
+    ASSERT(m_textRun);
+    return computeUnderlineType(*m_textRun, m_glyphBuffer, m_index);
+}
+
</ins><span class="cx"> void SVGGlyphToPathTranslator::moveToNextValidGlyph()
</span><span class="cx"> {
</span><span class="cx">     if (m_glyph &amp;&amp; !m_svgGlyph.pathData.isEmpty())
</span><span class="cx">         return;
</span><del>-    incrementIndex();
</del><ins>+    advance();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void SVGGlyphToPathTranslator::incrementIndex()
</del><ins>+void SVGGlyphToPathTranslator::advance()
</ins><span class="cx"> {
</span><span class="cx">     do {
</span><span class="cx">         if (m_glyph) {
</span><span class="lines">@@ -194,6 +212,11 @@
</span><span class="cx">         ASSERT(m_svgGlyph.tableEntry == m_glyph);
</span><span class="cx">         SVGGlyphElement::inheritUnspecifiedAttributes(m_svgGlyph, &amp;m_svgFontData);
</span><span class="cx">     } while ((!m_glyph || m_svgGlyph.pathData.isEmpty()) &amp;&amp; m_index &lt; m_stoppingPoint);
</span><ins>+
+    if (containsMorePaths() &amp;&amp; m_isVerticalText) {
+        m_glyphOrigin.setX(m_svgGlyph.verticalOriginX * m_scale);
+        m_glyphOrigin.setY(m_svgGlyph.verticalOriginY * m_scale);
+    }
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> class DummyGlyphToPathTranslator final : public GlyphToPathTranslator {
</span><span class="lines">@@ -201,13 +224,24 @@
</span><span class="cx">     {
</span><span class="cx">         return false;
</span><span class="cx">     }
</span><del>-    virtual Path nextPath() override
</del><ins>+    virtual Path path() override
</ins><span class="cx">     {
</span><span class="cx">         return Path();
</span><span class="cx">     }
</span><ins>+    virtual std::pair&lt;float, float&gt; extents() override
+    {
+        return std::make_pair(0.f, 0.f);
+    }
+    virtual GlyphUnderlineType underlineType() override
+    {
+        return GlyphUnderlineType::DrawOverGlyph;
+    }
+    virtual void advance() override
+    {
+    }
</ins><span class="cx"> };
</span><span class="cx"> 
</span><del>-std::unique_ptr&lt;GlyphToPathTranslator&gt; SVGTextRunRenderingContext::createGlyphToPathTranslator(const SimpleFontData&amp; fontData, const GlyphBuffer&amp; glyphBuffer, int from, int numGlyphs, const FloatPoint&amp; point) const
</del><ins>+std::unique_ptr&lt;GlyphToPathTranslator&gt; SVGTextRunRenderingContext::createGlyphToPathTranslator(const SimpleFontData&amp; fontData, const TextRun* textRun, const GlyphBuffer&amp; glyphBuffer, int from, int numGlyphs, const FloatPoint&amp; point) const
</ins><span class="cx"> {
</span><span class="cx">     SVGFontElement* fontElement = 0;
</span><span class="cx">     SVGFontFaceElement* fontFaceElement = 0;
</span><span class="lines">@@ -222,7 +256,7 @@
</span><span class="cx"> 
</span><span class="cx">     float scale = scaleEmToUnits(fontData.platformData().size(), fontFaceElement-&gt;unitsPerEm());
</span><span class="cx"> 
</span><del>-    return std::make_unique&lt;SVGGlyphToPathTranslator&gt;(glyphBuffer, point, *svgFontData, *fontElement, from, numGlyphs, scale, isVerticalText);
</del><ins>+    return std::make_unique&lt;SVGGlyphToPathTranslator&gt;(textRun, glyphBuffer, point, *svgFontData, *fontElement, from, numGlyphs, scale, isVerticalText);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void SVGTextRunRenderingContext::drawSVGGlyphs(GraphicsContext* context, const SimpleFontData* fontData, const GlyphBuffer&amp; glyphBuffer, int from, int numGlyphs, const FloatPoint&amp; point) const
</span><span class="lines">@@ -241,9 +275,8 @@
</span><span class="cx">     ASSERT(activePaintingResource);
</span><span class="cx"> 
</span><span class="cx">     RenderSVGResourceMode resourceMode = context-&gt;textDrawingMode() == TextModeStroke ? ApplyToStrokeMode : ApplyToFillMode;
</span><del>-    auto translator(createGlyphToPathTranslator(*fontData, glyphBuffer, from, numGlyphs, point));
-    while (translator-&gt;containsMorePaths()) {
-        Path glyphPath = translator-&gt;nextPath();
</del><ins>+    for (auto translator = createGlyphToPathTranslator(*fontData, nullptr, glyphBuffer, from, numGlyphs, point); translator-&gt;containsMorePaths(); translator-&gt;advance()) {
+        Path glyphPath = translator-&gt;path();
</ins><span class="cx">         if (activePaintingResource-&gt;applyResource(elementRenderer, style, context, resourceMode)) {
</span><span class="cx">             float strokeThickness = context-&gt;strokeThickness();
</span><span class="cx">             if (renderer().isSVGInlineText())
</span></span></pre></div>
<a id="trunkSourceWebCorerenderingsvgSVGTextRunRenderingContexth"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/rendering/svg/SVGTextRunRenderingContext.h (169714 => 169715)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/svg/SVGTextRunRenderingContext.h        2014-06-09 21:09:09 UTC (rev 169714)
+++ trunk/Source/WebCore/rendering/svg/SVGTextRunRenderingContext.h        2014-06-09 21:18:07 UTC (rev 169715)
</span><span class="lines">@@ -60,7 +60,7 @@
</span><span class="cx">     virtual ~SVGTextRunRenderingContext() { }
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(SVG_FONTS)
</span><del>-    virtual std::unique_ptr&lt;GlyphToPathTranslator&gt; createGlyphToPathTranslator(const SimpleFontData&amp;, const GlyphBuffer&amp;, int from, int numGlyphs, const FloatPoint&amp;) const override;
</del><ins>+    virtual std::unique_ptr&lt;GlyphToPathTranslator&gt; createGlyphToPathTranslator(const SimpleFontData&amp;, const TextRun*, const GlyphBuffer&amp;, int from, int numGlyphs, const FloatPoint&amp;) const override;
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx">     RenderObject&amp; m_renderer;
</span></span></pre>
</div>
</div>

</body>
</html>