<!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>[164842] 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/164842">164842</a></dd>
<dt>Author</dt> <dd>mmaxfield@apple.com</dd>
<dt>Date</dt> <dd>2014-02-27 16:22:32 -0800 (Thu, 27 Feb 2014)</dd>
</dl>

<h3>Log Message</h3>
<pre>text-decoration-skip: ink does not skip over SVG fonts
https://bugs.webkit.org/show_bug.cgi?id=128936

Reviewed by Darin Adler.

Source/WebCore:

When drawing glyphs in an SVG font, the glyphs are converted to paths and then filled. This patch moves
the glyph -&gt; path conversion into a helper class, GlyphToPathTranslator, and creates an implementation
for the SVG drawing code. Once this helper class is created, it can be used to trace paths in order
to make underlines skip over SVG glyphs. This helper class also has an implementation for non-SVG glyphs,
which allows for the glyph tracing code to be paramaterized over the implementation of the helper class
rather than if the FontData itself is SVG or not.

Tests: fast/css3-text/css3-text-decoration/text-decoration-skip/text-decoration-skip-ink-svg.html

* platform/graphics/Font.h:
(WebCore::GlyphToPathTranslator::~GlyphToPathTranslator): Virtual implementation of helper class
* platform/graphics/cg/PathCG.cpp:
(WebCore::Path::Path): Created constructor that takes a RefPtr&lt;CGMutablePathRef&gt;
* platform/graphics/Path.h:
* platform/graphics/TextRun.h: Give RenderingContext a factory function to create the helper class
instance
* platform/graphics/mac/FontMac.mm: Implementation of helper class used for skipping underlines on
regular (CoreText) glyphs
(WebCore::MacGlyphToPathTranslator::MacGlyphToPathTranslator):
(WebCore::MacGlyphToPathTranslator::moveToNextValidGlyph):
(WebCore::MacGlyphToPathTranslator::incrementIndex):
(WebCore::Font::dashesForIntersectionsWithRect): Call the relevant factory function, and use it
to successively generate Paths
* rendering/svg/SVGTextRunRenderingContext.cpp: Implementation of helper class used for SVG fonts
(WebCore::SVGGlyphToPathTranslator::SVGGlyphToPathTranslator):
(WebCore::SVGGlyphToPathTranslator::moveToNextValidGlyph):
(WebCore::SVGGlyphToPathTranslator::incrementIndex):
(WebCore::SVGTextRunRenderingContext::createGlyphToPathTranslator):
(WebCore::SVGTextRunRenderingContext::drawSVGGlyphs): Use the above implementation
* rendering/svg/SVGTextRunRenderingContext.h: Factory function declaration

LayoutTests:

This font simply draws some underlined text with a SVG font and makes sure the underline skips.

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

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsFonth">trunk/Source/WebCore/platform/graphics/Font.h</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsPathh">trunk/Source/WebCore/platform/graphics/Path.h</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsTextRunh">trunk/Source/WebCore/platform/graphics/TextRun.h</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicscgPathCGcpp">trunk/Source/WebCore/platform/graphics/cg/PathCG.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsmacFontMacmm">trunk/Source/WebCore/platform/graphics/mac/FontMac.mm</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>trunk/LayoutTests/fast/css3-text/css3-text-decoration/text-decoration-skip/resources/</li>
<li><a href="#trunkLayoutTestsfastcss3textcss3textdecorationtextdecorationskipresourcesLitherumsvg">trunk/LayoutTests/fast/css3-text/css3-text-decoration/text-decoration-skip/resources/Litherum.svg</a></li>
<li><a href="#trunkLayoutTestsfastcss3textcss3textdecorationtextdecorationskiptextdecorationskipinksvgexpectedhtml">trunk/LayoutTests/fast/css3-text/css3-text-decoration/text-decoration-skip/text-decoration-skip-ink-svg-expected.html</a></li>
<li><a href="#trunkLayoutTestsfastcss3textcss3textdecorationtextdecorationskiptextdecorationskipinksvghtml">trunk/LayoutTests/fast/css3-text/css3-text-decoration/text-decoration-skip/text-decoration-skip-ink-svg.html</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (164841 => 164842)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2014-02-28 00:09:40 UTC (rev 164841)
+++ trunk/LayoutTests/ChangeLog        2014-02-28 00:22:32 UTC (rev 164842)
</span><span class="lines">@@ -1,3 +1,16 @@
</span><ins>+2014-02-17  Myles C. Maxfield  &lt;mmaxfield@apple.com&gt;
+
+        text-decoration-skip: ink does not skip over SVG fonts
+        https://bugs.webkit.org/show_bug.cgi?id=128936
+
+        Reviewed by Darin Adler.
+
+        This font simply draws some underlined text with a SVG font and makes sure the underline skips.
+
+        * fast/css3-text/css3-text-decoration/text-decoration-skip/resources/Litherum.svg: Added.
+        * fast/css3-text/css3-text-decoration/text-decoration-skip/text-decoration-skip-ink-svg-expected.html: Added.
+        * fast/css3-text/css3-text-decoration/text-decoration-skip/text-decoration-skip-ink-svg.html: Added.
+
</ins><span class="cx"> 2014-02-27  Thiago de Barros Lacerda  &lt;thiago.lacerda@openbossa.org&gt;
</span><span class="cx"> 
</span><span class="cx">         [WebRTC] Removing MediaConstraints argument from RTCPeerConnection addStream, updateIce methods and constructor
</span></span></pre></div>
<a id="trunkLayoutTestsfastcss3textcss3textdecorationtextdecorationskipresourcesLitherumsvg"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/css3-text/css3-text-decoration/text-decoration-skip/resources/Litherum.svg (0 => 164842)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/css3-text/css3-text-decoration/text-decoration-skip/resources/Litherum.svg                                (rev 0)
+++ trunk/LayoutTests/fast/css3-text/css3-text-decoration/text-decoration-skip/resources/Litherum.svg        2014-02-28 00:22:32 UTC (rev 164842)
</span><span class="lines">@@ -0,0 +1,11 @@
</span><ins>+&lt;?xml version=&quot;1.0&quot; standalone=&quot;no&quot;?&gt;
+&lt;!DOCTYPE svg PUBLIC &quot;-//W3C//DTD SVG 1.1//EN&quot; &quot;http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd&quot; &gt;
+&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;
+&lt;metadata&gt;&lt;/metadata&gt;
+&lt;defs&gt;
+&lt;font id=&quot;Litherum&quot; horiz-adv-x=&quot;1024&quot;&gt;
+&lt;font-face units-per-em=&quot;14&quot; ascent=&quot;14&quot; descent=&quot;-7&quot;/&gt;
+&lt;glyph unicode=&quot;|&quot; horiz-adv-x=&quot;14&quot; d=&quot;M5 -7v21h4v-21z&quot;/&gt;
+&lt;/font&gt;
+&lt;/defs&gt;
+&lt;/svg&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsfastcss3textcss3textdecorationtextdecorationskiptextdecorationskipinksvgexpectedhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/css3-text/css3-text-decoration/text-decoration-skip/text-decoration-skip-ink-svg-expected.html (0 => 164842)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/css3-text/css3-text-decoration/text-decoration-skip/text-decoration-skip-ink-svg-expected.html                                (rev 0)
+++ trunk/LayoutTests/fast/css3-text/css3-text-decoration/text-decoration-skip/text-decoration-skip-ink-svg-expected.html        2014-02-28 00:22:32 UTC (rev 164842)
</span><span class="lines">@@ -0,0 +1,10 @@
</span><ins>+&lt;!DOCTYPE html&gt;
+&lt;html&gt;
+&lt;head&gt;
+&lt;/head&gt;
+&lt;body&gt;
+This test draws a giant character with an SVG font and positions the viewport
+in the gap where the underline should be skipping over the character. It should appear
+white.
+&lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsfastcss3textcss3textdecorationtextdecorationskiptextdecorationskipinksvghtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/css3-text/css3-text-decoration/text-decoration-skip/text-decoration-skip-ink-svg.html (0 => 164842)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/css3-text/css3-text-decoration/text-decoration-skip/text-decoration-skip-ink-svg.html                                (rev 0)
+++ trunk/LayoutTests/fast/css3-text/css3-text-decoration/text-decoration-skip/text-decoration-skip-ink-svg.html        2014-02-28 00:22:32 UTC (rev 164842)
</span><span class="lines">@@ -0,0 +1,25 @@
</span><ins>+&lt;!DOCTYPE html&gt;
+&lt;html&gt;
+&lt;head&gt;
+&lt;style&gt;
+@font-face {
+    font-family: 'Litherum';
+    src: url(&quot;./resources/Litherum.svg&quot;) format(svg)
+}
+#p {
+    font: 1000px 'Litherum';
+    text-decoration: underline;
+}
+&lt;/style&gt;
+&lt;/head&gt;
+&lt;body&gt;
+This test draws a giant character with an SVG font and positions the viewport
+in the gap where the underline should be skipping over the character. It should appear
+white.
+&lt;div style=&quot;position: absolute; width: 62px; height: 100px; overflow: hidden;&quot;&gt;
+&lt;div style=&quot;position: absolute; left: -295px; top: -1100px;&quot;&gt;
+&lt;div id=&quot;p&quot;&gt;|&lt;/div&gt;
+&lt;/div&gt;
+&lt;/div&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (164841 => 164842)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2014-02-28 00:09:40 UTC (rev 164841)
+++ trunk/Source/WebCore/ChangeLog        2014-02-28 00:22:32 UTC (rev 164842)
</span><span class="lines">@@ -1,3 +1,41 @@
</span><ins>+2014-02-17  Myles C. Maxfield  &lt;mmaxfield@apple.com&gt;
+
+        text-decoration-skip: ink does not skip over SVG fonts
+        https://bugs.webkit.org/show_bug.cgi?id=128936
+
+        Reviewed by Darin Adler.
+
+        When drawing glyphs in an SVG font, the glyphs are converted to paths and then filled. This patch moves
+        the glyph -&gt; path conversion into a helper class, GlyphToPathTranslator, and creates an implementation
+        for the SVG drawing code. Once this helper class is created, it can be used to trace paths in order
+        to make underlines skip over SVG glyphs. This helper class also has an implementation for non-SVG glyphs,
+        which allows for the glyph tracing code to be paramaterized over the implementation of the helper class
+        rather than if the FontData itself is SVG or not.
+
+        Tests: fast/css3-text/css3-text-decoration/text-decoration-skip/text-decoration-skip-ink-svg.html
+
+        * platform/graphics/Font.h:
+        (WebCore::GlyphToPathTranslator::~GlyphToPathTranslator): Virtual implementation of helper class
+        * platform/graphics/cg/PathCG.cpp:
+        (WebCore::Path::Path): Created constructor that takes a RefPtr&lt;CGMutablePathRef&gt;
+        * platform/graphics/Path.h:
+        * platform/graphics/TextRun.h: Give RenderingContext a factory function to create the helper class
+        instance
+        * platform/graphics/mac/FontMac.mm: Implementation of helper class used for skipping underlines on
+        regular (CoreText) glyphs
+        (WebCore::MacGlyphToPathTranslator::MacGlyphToPathTranslator):
+        (WebCore::MacGlyphToPathTranslator::moveToNextValidGlyph):
+        (WebCore::MacGlyphToPathTranslator::incrementIndex):
+        (WebCore::Font::dashesForIntersectionsWithRect): Call the relevant factory function, and use it
+        to successively generate Paths
+        * rendering/svg/SVGTextRunRenderingContext.cpp: Implementation of helper class used for SVG fonts
+        (WebCore::SVGGlyphToPathTranslator::SVGGlyphToPathTranslator):
+        (WebCore::SVGGlyphToPathTranslator::moveToNextValidGlyph):
+        (WebCore::SVGGlyphToPathTranslator::incrementIndex):
+        (WebCore::SVGTextRunRenderingContext::createGlyphToPathTranslator):
+        (WebCore::SVGTextRunRenderingContext::drawSVGGlyphs): Use the above implementation
+        * rendering/svg/SVGTextRunRenderingContext.h: Factory function declaration
+
</ins><span class="cx"> 2014-02-27  Thiago de Barros Lacerda  &lt;thiago.lacerda@openbossa.org&gt;
</span><span class="cx"> 
</span><span class="cx">         [WebRTC] Removing MediaConstraints argument from RTCPeerConnection addStream, updateIce methods and constructor
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsFonth"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/Font.h (164841 => 164842)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/Font.h        2014-02-28 00:09:40 UTC (rev 164841)
+++ trunk/Source/WebCore/platform/graphics/Font.h        2014-02-28 00:22:32 UTC (rev 164842)
</span><span class="lines">@@ -28,6 +28,7 @@
</span><span class="cx"> #include &quot;DashArray.h&quot;
</span><span class="cx"> #include &quot;FontDescription.h&quot;
</span><span class="cx"> #include &quot;FontGlyphs.h&quot;
</span><ins>+#include &quot;Path.h&quot;
</ins><span class="cx"> #include &quot;SimpleFontData.h&quot;
</span><span class="cx"> #include &quot;TextDirection.h&quot;
</span><span class="cx"> #include &quot;TypesettingFeatures.h&quot;
</span><span class="lines">@@ -75,6 +76,12 @@
</span><span class="cx">     bool computeBounds;
</span><span class="cx"> };
</span><span class="cx"> 
</span><ins>+class GlyphToPathTranslator {
+public:
+    virtual bool containsMorePaths() = 0;
+    virtual Path nextPath() = 0;
+    virtual ~GlyphToPathTranslator() { }
+};
</ins><span class="cx"> 
</span><span class="cx"> class Font {
</span><span class="cx"> public:
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsPathh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/Path.h (164841 => 164842)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/Path.h        2014-02-28 00:09:40 UTC (rev 164841)
+++ trunk/Source/WebCore/platform/graphics/Path.h        2014-02-28 00:22:32 UTC (rev 164842)
</span><span class="lines">@@ -33,6 +33,8 @@
</span><span class="cx"> #include &lt;wtf/Forward.h&gt;
</span><span class="cx"> 
</span><span class="cx"> #if USE(CG)
</span><ins>+#include &lt;wtf/RetainPtr.h&gt;
+#include &lt;CoreGraphics/CGPath.h&gt;
</ins><span class="cx"> typedef struct CGPath PlatformPath;
</span><span class="cx"> #elif USE(CAIRO)
</span><span class="cx"> namespace WebCore {
</span><span class="lines">@@ -82,6 +84,9 @@
</span><span class="cx">         WTF_MAKE_FAST_ALLOCATED;
</span><span class="cx">     public:
</span><span class="cx">         Path();
</span><ins>+#if USE(CG)
+        Path(RetainPtr&lt;CGMutablePathRef&gt;);
+#endif
</ins><span class="cx">         ~Path();
</span><span class="cx"> 
</span><span class="cx">         Path(const Path&amp;);
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsTextRunh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/TextRun.h (164841 => 164842)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/TextRun.h        2014-02-28 00:09:40 UTC (rev 164841)
+++ trunk/Source/WebCore/platform/graphics/TextRun.h        2014-02-28 00:22:32 UTC (rev 164842)
</span><span class="lines">@@ -35,6 +35,7 @@
</span><span class="cx"> class Font;
</span><span class="cx"> class GraphicsContext;
</span><span class="cx"> class GlyphBuffer;
</span><ins>+class GlyphToPathTranslator;
</ins><span class="cx"> class SimpleFontData;
</span><span class="cx"> struct GlyphData;
</span><span class="cx"> struct WidthIterator;
</span><span class="lines">@@ -188,6 +189,7 @@
</span><span class="cx"> 
</span><span class="cx">     class RenderingContext : public RefCounted&lt;RenderingContext&gt; {
</span><span class="cx">     public:
</span><ins>+        virtual std::unique_ptr&lt;GlyphToPathTranslator&gt; createGlyphToPathTranslator(const SimpleFontData&amp;, const GlyphBuffer&amp;, int from, int numGlyphs, const FloatPoint&amp;) const = 0;
</ins><span class="cx">         virtual ~RenderingContext() { }
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(SVG_FONTS)
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicscgPathCGcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/cg/PathCG.cpp (164841 => 164842)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/cg/PathCG.cpp        2014-02-28 00:09:40 UTC (rev 164841)
+++ trunk/Source/WebCore/platform/graphics/cg/PathCG.cpp        2014-02-28 00:22:32 UTC (rev 164842)
</span><span class="lines">@@ -78,6 +78,11 @@
</span><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+Path::Path(RetainPtr&lt;CGMutablePathRef&gt; p)
+    : m_path(p.leakRef())
+{
+}
+
</ins><span class="cx"> Path::~Path()
</span><span class="cx"> {
</span><span class="cx">     if (m_path)
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsmacFontMacmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/mac/FontMac.mm (164841 => 164842)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/mac/FontMac.mm        2014-02-28 00:09:40 UTC (rev 164841)
+++ trunk/Source/WebCore/platform/graphics/mac/FontMac.mm        2014-02-28 00:22:32 UTC (rev 164842)
</span><span class="lines">@@ -436,33 +436,95 @@
</span><span class="cx">     state.currentPoint = point;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+class MacGlyphToPathTranslator final : public GlyphToPathTranslator {
+public:
+    MacGlyphToPathTranslator(const GlyphBuffer&amp; glyphBuffer, const FloatPoint&amp; textOrigin)
+        : m_index(0)
+        , m_glyphBuffer(glyphBuffer)
+        , m_fontData(glyphBuffer.fontDataAt(m_index))
+        , m_translation(CGAffineTransformScale(CGAffineTransformMakeTranslation(textOrigin.x(), textOrigin.y()), 1, -1))
+    {
+        moveToNextValidGlyph();
+    }
+private:
+    virtual bool containsMorePaths() override
+    {
+        return m_index != m_glyphBuffer.size();
+    }
+    virtual Path nextPath() override;
+    void moveToNextValidGlyph();
+    void incrementIndex();
+
+    int m_index;
+    const GlyphBuffer&amp; m_glyphBuffer;
+    const SimpleFontData* m_fontData;
+    CGAffineTransform m_translation;
+};
+
+Path MacGlyphToPathTranslator::nextPath()
+{
+    RetainPtr&lt;CGPathRef&gt; result = adoptCF(CTFontCreatePathForGlyph(m_fontData-&gt;platformData().ctFont(), m_glyphBuffer.glyphAt(m_index), &amp;m_translation));
+    incrementIndex();
+    return adoptCF(CGPathCreateMutableCopy(result.get()));
+}
+
+void MacGlyphToPathTranslator::moveToNextValidGlyph()
+{
+    if (!m_fontData-&gt;isSVGFont())
+        return;
+    incrementIndex();
+}
+
+void MacGlyphToPathTranslator::incrementIndex()
+{
+    do {
+        GlyphBufferAdvance advance = m_glyphBuffer.advanceAt(m_index);
+        m_translation = CGAffineTransformTranslate(m_translation, advance.width(), advance.height());
+        ++m_index;
+        if (m_index &gt;= m_glyphBuffer.size())
+            break;
+        m_fontData = m_glyphBuffer.fontDataAt(m_index);
+    } while (m_fontData-&gt;isSVGFont() &amp;&amp; m_index &lt; m_glyphBuffer.size());
+}
+
</ins><span class="cx"> DashArray Font::dashesForIntersectionsWithRect(const TextRun&amp; run, const FloatPoint&amp; textOrigin, const FloatRect&amp; lineExtents) const
</span><span class="cx"> {
</span><span class="cx">     if (loadingCustomFonts())
</span><span class="cx">         return DashArray();
</span><span class="cx"> 
</span><ins>+    GlyphBuffer glyphBuffer;
</ins><span class="cx">     float deltaX;
</span><del>-    GlyphBuffer glyphBuffer;
-    if (codePath(run) != Complex)
</del><ins>+    if (codePath(run) != Font::Complex)
</ins><span class="cx">         deltaX = getGlyphsAndAdvancesForSimpleText(run, 0, run.length(), glyphBuffer);
</span><span class="cx">     else
</span><span class="cx">         deltaX = getGlyphsAndAdvancesForComplexText(run, 0, run.length(), glyphBuffer);
</span><del>-    CGAffineTransform translation = CGAffineTransformMakeTranslation(textOrigin.x() + deltaX, textOrigin.y());
-    translation = CGAffineTransformScale(translation, 1, -1);
</del><ins>+
+    if (!glyphBuffer.size())
+        return DashArray();
+    
+    // FIXME: Handle SVG + non-SVG interleaved runs
+    const SimpleFontData* fontData = glyphBuffer.fontDataAt(0);
+    std::unique_ptr&lt;GlyphToPathTranslator&gt; translator;
+    bool isSVG = false;
+    FloatPoint origin = FloatPoint(textOrigin.x() + deltaX, textOrigin.y());
+    if (!fontData-&gt;isSVGFont())
+        translator = std::move(std::make_unique&lt;MacGlyphToPathTranslator&gt;(glyphBuffer, origin));
+    else {
+        translator = std::move(run.renderingContext()-&gt;createGlyphToPathTranslator(*fontData, glyphBuffer, 0, run.length(), origin));
+        isSVG = true;
+    }
</ins><span class="cx">     DashArray result;
</span><del>-    for (int i = 0; i &lt; glyphBuffer.size(); ++i) {
</del><ins>+    for (int index = 0; translator-&gt;containsMorePaths(); ++index) {
</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><del>-        const SimpleFontData* fontData = glyphBuffer.fontDataAt(i);
-        if (fontData-&gt;isSVGFont())
-            continue;
-        RetainPtr&lt;CGPathRef&gt; path = adoptCF(CTFontCreatePathForGlyph(fontData-&gt;platformData().ctFont(), glyphBuffer.glyphAt(i), &amp;translation));
-        CGPathApply(path.get(), &amp;info, &amp;findPathIntersections);
</del><ins>+        const SimpleFontData* localFontData = glyphBuffer.fontDataAt(index);
+        if (!localFontData || (!isSVG &amp;&amp; localFontData-&gt;isSVGFont()) || (isSVG &amp;&amp; localFontData != fontData))
+            break; // The advances will get all messed up if we do anything other than bail here.
+        Path path = translator-&gt;nextPath();
+        CGPathApply(path.platformPath(), &amp;info, &amp;findPathIntersections);
</ins><span class="cx">         if (info.minX &lt; info.maxX) {
</span><span class="cx">             result.append(info.minX - lineExtents.x());
</span><span class="cx">             result.append(info.maxX - lineExtents.x());
</span><span class="cx">         }
</span><del>-        GlyphBufferAdvance advance = glyphBuffer.advanceAt(i);
-        translation = CGAffineTransformTranslate(translation, advance.width(), advance.height());
</del><span class="cx">     }
</span><span class="cx">     return result;
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebCorerenderingsvgSVGTextRunRenderingContextcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/rendering/svg/SVGTextRunRenderingContext.cpp (164841 => 164842)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/svg/SVGTextRunRenderingContext.cpp        2014-02-28 00:09:40 UTC (rev 164841)
+++ trunk/Source/WebCore/rendering/svg/SVGTextRunRenderingContext.cpp        2014-02-28 00:22:32 UTC (rev 164842)
</span><span class="lines">@@ -101,15 +101,132 @@
</span><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void SVGTextRunRenderingContext::drawSVGGlyphs(GraphicsContext* context, const SimpleFontData* fontData, const GlyphBuffer&amp; glyphBuffer, int from, int numGlyphs, const FloatPoint&amp; point) const
</del><ins>+class SVGGlyphToPathTranslator final : public GlyphToPathTranslator {
+public:
+    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);
+private:
+    virtual bool containsMorePaths() override
+    {
+        return m_index != m_stoppingPoint;
+    }
+    virtual Path nextPath() override;
+    void moveToNextValidGlyph();
+    void incrementIndex();
+
+    const GlyphBuffer&amp; m_glyphBuffer;
+    const SVGFontData&amp; m_svgFontData;
+    FloatPoint m_currentPoint;
+    FloatPoint m_glyphOrigin;
+    SVGGlyph m_svgGlyph;
+    int m_index;
+    Glyph m_glyph;
+    SVGFontElement&amp; m_fontElement;
+    const float m_stoppingPoint;
+    const float m_scale;
+    const bool m_isVerticalText;
+};
+
+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)
+    , m_svgFontData(svgFontData)
+    , m_currentPoint(point)
+    , m_glyphOrigin(m_svgFontData.horizontalOriginX() * scale, m_svgFontData.horizontalOriginY() * scale)
+    , m_index(from)
+    , m_glyph(glyphBuffer.glyphAt(m_index))
+    , m_fontElement(fontElement)
+    , m_stoppingPoint(numGlyphs + from)
+    , m_scale(scale)
+    , m_isVerticalText(isVerticalText)
</ins><span class="cx"> {
</span><ins>+    ASSERT(glyphBuffer.size() &gt; m_index);
+    if (m_glyph) {
+        m_svgGlyph = m_fontElement.svgGlyphForGlyph(m_glyph);
+        ASSERT(!m_svgGlyph.isPartOfLigature);
+        ASSERT(m_svgGlyph.tableEntry == m_glyph);
+        SVGGlyphElement::inheritUnspecifiedAttributes(m_svgGlyph, &amp;m_svgFontData);
+    }
+    moveToNextValidGlyph();
+}
+
+Path SVGGlyphToPathTranslator::nextPath()
+{
+    if (m_isVerticalText) {
+        m_glyphOrigin.setX(m_svgGlyph.verticalOriginX * m_scale);
+        m_glyphOrigin.setY(m_svgGlyph.verticalOriginY * m_scale);
+    }
+
+    AffineTransform glyphPathTransform;
+    glyphPathTransform.translate(m_currentPoint.x() + m_glyphOrigin.x(), m_currentPoint.y() + m_glyphOrigin.y());
+    glyphPathTransform.scale(m_scale, -m_scale);
+
+    Path glyphPath = m_svgGlyph.pathData;
+    glyphPath.transform(glyphPathTransform);
+    incrementIndex();
+    return glyphPath;
+}
+
+void SVGGlyphToPathTranslator::moveToNextValidGlyph()
+{
+    if (m_glyph &amp;&amp; !m_svgGlyph.pathData.isEmpty())
+        return;
+    incrementIndex();
+}
+
+void SVGGlyphToPathTranslator::incrementIndex()
+{
+    do {
+        if (m_glyph) {
+            float advance = m_glyphBuffer.advanceAt(m_index).width();
+            if (m_isVerticalText)
+                m_currentPoint.move(0, advance);
+            else
+                m_currentPoint.move(advance, 0);
+        }
+
+        ++m_index;
+        if (m_index &gt;= m_stoppingPoint)
+            break;
+        m_glyph = m_glyphBuffer.glyphAt(m_index);
+        if (!m_glyph)
+            continue;
+        m_svgGlyph = m_fontElement.svgGlyphForGlyph(m_glyph);
+        ASSERT(!m_svgGlyph.isPartOfLigature);
+        ASSERT(m_svgGlyph.tableEntry == m_glyph);
+        SVGGlyphElement::inheritUnspecifiedAttributes(m_svgGlyph, &amp;m_svgFontData);
+    } while ((!m_glyph || m_svgGlyph.pathData.isEmpty()) &amp;&amp; m_index &lt; m_stoppingPoint);
+}
+
+class DummyGlyphToPathTranslator final : public GlyphToPathTranslator {
+    virtual bool containsMorePaths() override
+    {
+        return false;
+    }
+    virtual Path nextPath() override
+    {
+        return Path();
+    }
+};
+
+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
+{
</ins><span class="cx">     SVGFontElement* fontElement = 0;
</span><span class="cx">     SVGFontFaceElement* fontFaceElement = 0;
</span><span class="cx"> 
</span><del>-    const SVGFontData* svgFontData = svgFontAndFontFaceElementForFontData(fontData, fontFaceElement, fontElement);
</del><ins>+    const SVGFontData* svgFontData = svgFontAndFontFaceElementForFontData(&amp;fontData, fontFaceElement, fontElement);
</ins><span class="cx">     if (!fontElement || !fontFaceElement)
</span><del>-        return;
</del><ins>+        return std::make_unique&lt;DummyGlyphToPathTranslator&gt;();
</ins><span class="cx"> 
</span><ins>+    auto&amp; elementRenderer = renderer().isRenderElement() ? toRenderElement(renderer()) : *renderer().parent();
+    RenderStyle&amp; style = elementRenderer.style();
+    bool isVerticalText = style.svgStyle().isVerticalWritingMode();
+
+    float scale = scaleEmToUnits(fontData.platformData().size(), fontFaceElement-&gt;unitsPerEm());
+
+    return std::make_unique&lt;SVGGlyphToPathTranslator&gt;(glyphBuffer, point, *svgFontData, *fontElement, from, numGlyphs, scale, isVerticalText);
+}
+
+void SVGTextRunRenderingContext::drawSVGGlyphs(GraphicsContext* context, const SimpleFontData* fontData, const GlyphBuffer&amp; glyphBuffer, int from, int numGlyphs, const FloatPoint&amp; point) const
+{
</ins><span class="cx">     auto activePaintingResource = this-&gt;activePaintingResource();
</span><span class="cx">     if (!activePaintingResource) {
</span><span class="cx">         // TODO: We're only supporting simple filled HTML text so far.
</span><span class="lines">@@ -120,50 +237,13 @@
</span><span class="cx"> 
</span><span class="cx">     auto&amp; elementRenderer = renderer().isRenderElement() ? toRenderElement(renderer()) : *renderer().parent();
</span><span class="cx">     RenderStyle&amp; style = elementRenderer.style();
</span><del>-    bool isVerticalText = style.svgStyle().isVerticalWritingMode();
</del><span class="cx"> 
</span><del>-    float scale = scaleEmToUnits(fontData-&gt;platformData().size(), fontFaceElement-&gt;unitsPerEm());
</del><span class="cx">     ASSERT(activePaintingResource);
</span><span class="cx"> 
</span><del>-    FloatPoint glyphOrigin;
-    glyphOrigin.setX(svgFontData-&gt;horizontalOriginX() * scale);
-    glyphOrigin.setY(svgFontData-&gt;horizontalOriginY() * scale);
-
-    FloatPoint currentPoint = point;
</del><span class="cx">     RenderSVGResourceMode resourceMode = context-&gt;textDrawingMode() == TextModeStroke ? ApplyToStrokeMode : ApplyToFillMode;
</span><del>-    for (int i = 0; i &lt; numGlyphs; ++i) {
-        Glyph glyph = glyphBuffer.glyphAt(from + i);
-        if (!glyph)
-            continue;
-
-        float advance = glyphBuffer.advanceAt(from + i).width();
-        SVGGlyph svgGlyph = fontElement-&gt;svgGlyphForGlyph(glyph);
-        ASSERT(!svgGlyph.isPartOfLigature);
-        ASSERT(svgGlyph.tableEntry == glyph);
-
-        SVGGlyphElement::inheritUnspecifiedAttributes(svgGlyph, svgFontData);
-
-        // FIXME: Support arbitary SVG content as glyph (currently limited to &lt;glyph d=&quot;...&quot;&gt; situations).
-        if (svgGlyph.pathData.isEmpty()) {
-            if (isVerticalText)
-                currentPoint.move(0, advance);
-            else
-                currentPoint.move(advance, 0);
-            continue;
-         }
-
-        if (isVerticalText) {
-            glyphOrigin.setX(svgGlyph.verticalOriginX * scale);
-            glyphOrigin.setY(svgGlyph.verticalOriginY * scale);
-         }
-
-        AffineTransform glyphPathTransform;
-        glyphPathTransform.translate(currentPoint.x() + glyphOrigin.x(), currentPoint.y() + glyphOrigin.y());
-        glyphPathTransform.scale(scale, -scale);
-
-        Path glyphPath = svgGlyph.pathData;
-        glyphPath.transform(glyphPathTransform);
-
</del><ins>+    auto translator(createGlyphToPathTranslator(*fontData, glyphBuffer, from, numGlyphs, point));
+    while (translator-&gt;containsMorePaths()) {
+        Path glyphPath = translator-&gt;nextPath();
</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 class="lines">@@ -171,11 +251,6 @@
</span><span class="cx">             activePaintingResource-&gt;postApplyResource(elementRenderer, context, resourceMode, &amp;glyphPath, 0);
</span><span class="cx">             context-&gt;setStrokeThickness(strokeThickness);
</span><span class="cx">         }
</span><del>-
-        if (isVerticalText)
-            currentPoint.move(0, advance);
-        else
-            currentPoint.move(advance, 0);
</del><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCorerenderingsvgSVGTextRunRenderingContexth"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/rendering/svg/SVGTextRunRenderingContext.h (164841 => 164842)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/svg/SVGTextRunRenderingContext.h        2014-02-28 00:09:40 UTC (rev 164841)
+++ trunk/Source/WebCore/rendering/svg/SVGTextRunRenderingContext.h        2014-02-28 00:22:32 UTC (rev 164842)
</span><span class="lines">@@ -59,6 +59,8 @@
</span><span class="cx"> 
</span><span class="cx">     virtual ~SVGTextRunRenderingContext() { }
</span><span class="cx"> 
</span><ins>+    virtual std::unique_ptr&lt;GlyphToPathTranslator&gt; createGlyphToPathTranslator(const SimpleFontData&amp;, const GlyphBuffer&amp;, int from, int numGlyphs, const FloatPoint&amp;) const override;
+
</ins><span class="cx">     RenderObject&amp; m_renderer;
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(SVG_FONTS)
</span></span></pre>
</div>
</div>

</body>
</html>