<!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>[200807] 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/200807">200807</a></dd>
<dt>Author</dt> <dd>mmaxfield@apple.com</dd>
<dt>Date</dt> <dd>2016-05-12 18:55:40 -0700 (Thu, 12 May 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>Source/WebCore:
[Cocoa] Text shadow sometimes clipped unexpectedly
https://bugs.webkit.org/show_bug.cgi?id=108929

Reviewed by Dean Jackson.

CoreGraphics can only draw one text shadow at a time. We work around that by drawing
the text multiple times, one for each shadow. However, we want to make sure that the
original text isn't also drawn multiple times, so we bump up the shadow offsets so
the text and the shadow don't intersect, and then we clip out the original text (so
only the shadow remains).

Unfortunately, this clipping requires knowing where the visual extent of the text is,
which WebKit currently has trouble with. In particular, we often use layout extents
in lieu of visual extents, which is a problem when the glyphs draw outside of their
layout boxes. In this case, it causes us to think the text shadow is much smaller
than it really is, so our clipping operation clips to an area which is too small.

A quick solution to this is to inflate the clip rect by an amount proportional to the
font size, and offset the text shadow accordingly. If this amount is large enough,
this bug will occur on few enough sites that it is reasonable to consider this bug
fixed without the real solution of educating WebKit properly about the difference
between text layout rects and text visual extent rects.

Test: fast/text/multiple-text-shadow-overflow-layout-rect.html

* rendering/TextPainter.cpp:
(WebCore::ShadowApplier::ShadowApplier):

LayoutTests:
Text shadow sometimes clipped unexpectedly
https://bugs.webkit.org/show_bug.cgi?id=108929

Reviewed by Dean Jackson.

Add a font which draws dramatically far outside of its layout rect.

* fast/text/multiple-text-shadow-overflow-layout-rect-expected.html: Added.
* fast/text/multiple-text-shadow-overflow-layout-rect.html: Added.
* fast/text/resources/font-overflow-layout-rect.svg: 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="#trunkSourceWebCorerenderingTextPaintercpp">trunk/Source/WebCore/rendering/TextPainter.cpp</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsfasttextmultipletextshadowoverflowlayoutrectexpectedhtml">trunk/LayoutTests/fast/text/multiple-text-shadow-overflow-layout-rect-expected.html</a></li>
<li><a href="#trunkLayoutTestsfasttextmultipletextshadowoverflowlayoutrecthtml">trunk/LayoutTests/fast/text/multiple-text-shadow-overflow-layout-rect.html</a></li>
<li><a href="#trunkLayoutTestsfasttextresourcesfontoverflowlayoutrectsvg">trunk/LayoutTests/fast/text/resources/font-overflow-layout-rect.svg</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (200806 => 200807)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2016-05-13 01:24:50 UTC (rev 200806)
+++ trunk/LayoutTests/ChangeLog        2016-05-13 01:55:40 UTC (rev 200807)
</span><span class="lines">@@ -1,3 +1,16 @@
</span><ins>+2016-05-12  Myles C. Maxfield  &lt;mmaxfield@apple.com&gt;
+
+        Text shadow sometimes clipped unexpectedly
+        https://bugs.webkit.org/show_bug.cgi?id=108929
+
+        Reviewed by Dean Jackson.
+
+        Add a font which draws dramatically far outside of its layout rect.
+
+        * fast/text/multiple-text-shadow-overflow-layout-rect-expected.html: Added.
+        * fast/text/multiple-text-shadow-overflow-layout-rect.html: Added.
+        * fast/text/resources/font-overflow-layout-rect.svg: Added.
+
</ins><span class="cx"> 2016-05-12  Ryan Haddad  &lt;ryanhaddad@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Marking inspector/debugger/command-line-api-exception-nested-catch.html as a flaky timeout on mac
</span></span></pre></div>
<a id="trunkLayoutTestsfasttextmultipletextshadowoverflowlayoutrectexpectedhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/text/multiple-text-shadow-overflow-layout-rect-expected.html (0 => 200807)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/text/multiple-text-shadow-overflow-layout-rect-expected.html                                (rev 0)
+++ trunk/LayoutTests/fast/text/multiple-text-shadow-overflow-layout-rect-expected.html        2016-05-13 01:55:40 UTC (rev 200807)
</span><span class="lines">@@ -0,0 +1,18 @@
</span><ins>+&lt;!DOCTYPE html&gt;
+&lt;html&gt;
+&lt;head&gt;
+&lt;style&gt;
+@font-face {
+        font-family: fontoverfowlayoutrect;
+        src: url(&quot;resources/font-overflow-layout-rect.svg&quot;) format(&quot;svg&quot;);
+}
+&lt;/style&gt;
+&lt;/head&gt;
+&lt;body&gt;
+This test makes sure that shadows on text which draws far outside its layout box don't get clipped.
+&lt;div style=&quot;position: relative&quot;&gt;
+&lt;span style=&quot;position: absolute; left: 109px; top: 109px; font: 100px fontoverfowlayoutrect; color: rgb(0, 255, 0)&quot;&gt;a&lt;/span&gt;
+&lt;span style=&quot;position: absolute; left: 100px; top: 100px; font: 100px fontoverfowlayoutrect;&quot;&gt;a&lt;/span&gt;
+&lt;/div&gt;
+&lt;/body&gt;
+&lt;html&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsfasttextmultipletextshadowoverflowlayoutrecthtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/text/multiple-text-shadow-overflow-layout-rect.html (0 => 200807)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/text/multiple-text-shadow-overflow-layout-rect.html                                (rev 0)
+++ trunk/LayoutTests/fast/text/multiple-text-shadow-overflow-layout-rect.html        2016-05-13 01:55:40 UTC (rev 200807)
</span><span class="lines">@@ -0,0 +1,17 @@
</span><ins>+&lt;!DOCTYPE html&gt;
+&lt;html&gt;
+&lt;head&gt;
+&lt;style&gt;
+@font-face {
+        font-family: fontoverfowlayoutrect;
+        src: url(&quot;resources/font-overflow-layout-rect.svg&quot;) format(&quot;svg&quot;);
+}
+&lt;/style&gt;
+&lt;/head&gt;
+&lt;body&gt;
+This test makes sure that shadows on text which draws far outside its layout box don't get clipped.
+&lt;div style=&quot;position: relative&quot;&gt;
+&lt;span style=&quot;position: absolute; left: 100px; top: 100px; font: 100px fontoverfowlayoutrect; text-shadow: rgb(128, 128, 128) -500px 0px 0px, rgb(0, 255, 0) 9px 9px 0px;&quot;&gt;a&lt;/span&gt;
+&lt;/div&gt;
+&lt;/body&gt;
+&lt;html&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsfasttextresourcesfontoverflowlayoutrectsvg"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/text/resources/font-overflow-layout-rect.svg (0 => 200807)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/text/resources/font-overflow-layout-rect.svg                                (rev 0)
+++ trunk/LayoutTests/fast/text/resources/font-overflow-layout-rect.svg        2016-05-13 01:55:40 UTC (rev 200807)
</span><span class="lines">@@ -0,0 +1,14 @@
</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;font-overflow-layout-rect&quot; horiz-adv-x=&quot;1024&quot;&gt;
+&lt;font-face font-family=&quot;font-overflow-layout-rect&quot; units-per-em=&quot;1024&quot; ascent=&quot;1024&quot; descent=&quot;1&quot;/&gt;
+&lt;glyph unicode=&quot;a&quot; horiz-adv-x=&quot;1024&quot; d=&quot;M0 341L-1024 512L0 682L341 1024L512 2048L682 1024L1024 682L2048 512L1024 341L682 0L512 -1024L341 0z&quot;/&gt;
+&lt;/font&gt;
+&lt;/defs&gt;
+&lt;text x=&quot;8&quot; y=&quot;24&quot; font-size=&quot;16&quot;&gt;The green box represents the layout rect of the 'a' glyph.&lt;/text&gt;
+&lt;text x=&quot;100&quot; y=&quot;200&quot; font-size=&quot;100&quot; font-family=&quot;font-overflow-layout-rect&quot;&gt;a&lt;/text&gt;
+&lt;rect x=&quot;100&quot; y=&quot;100&quot; width=&quot;100&quot; height=&quot;100&quot; fill=&quot;none&quot; stroke=&quot;green&quot;/&gt;
+&lt;/svg&gt;
</ins></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (200806 => 200807)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2016-05-13 01:24:50 UTC (rev 200806)
+++ trunk/Source/WebCore/ChangeLog        2016-05-13 01:55:40 UTC (rev 200807)
</span><span class="lines">@@ -1,5 +1,35 @@
</span><span class="cx"> 2016-05-12  Myles C. Maxfield  &lt;mmaxfield@apple.com&gt;
</span><span class="cx"> 
</span><ins>+        [Cocoa] Text shadow sometimes clipped unexpectedly
+        https://bugs.webkit.org/show_bug.cgi?id=108929
+
+        Reviewed by Dean Jackson.
+
+        CoreGraphics can only draw one text shadow at a time. We work around that by drawing
+        the text multiple times, one for each shadow. However, we want to make sure that the
+        original text isn't also drawn multiple times, so we bump up the shadow offsets so
+        the text and the shadow don't intersect, and then we clip out the original text (so
+        only the shadow remains).
+
+        Unfortunately, this clipping requires knowing where the visual extent of the text is,
+        which WebKit currently has trouble with. In particular, we often use layout extents
+        in lieu of visual extents, which is a problem when the glyphs draw outside of their
+        layout boxes. In this case, it causes us to think the text shadow is much smaller
+        than it really is, so our clipping operation clips to an area which is too small.
+
+        A quick solution to this is to inflate the clip rect by an amount proportional to the
+        font size, and offset the text shadow accordingly. If this amount is large enough,
+        this bug will occur on few enough sites that it is reasonable to consider this bug
+        fixed without the real solution of educating WebKit properly about the difference
+        between text layout rects and text visual extent rects.
+
+        Test: fast/text/multiple-text-shadow-overflow-layout-rect.html
+
+        * rendering/TextPainter.cpp:
+        (WebCore::ShadowApplier::ShadowApplier):
+
+2016-05-12  Myles C. Maxfield  &lt;mmaxfield@apple.com&gt;
+
</ins><span class="cx">         REGRESSION(r200601): Crash when using local() and unicode-range in @font-face blocks
</span><span class="cx">         https://bugs.webkit.org/show_bug.cgi?id=157646
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCorerenderingTextPaintercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/rendering/TextPainter.cpp (200806 => 200807)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/TextPainter.cpp        2016-05-13 01:24:50 UTC (rev 200806)
+++ trunk/Source/WebCore/rendering/TextPainter.cpp        2016-05-13 01:55:40 UTC (rev 200807)
</span><span class="lines">@@ -54,13 +54,13 @@
</span><span class="cx">     // often draw the *last* shadow and the text itself in a single call.
</span><span class="cx">     if (m_onlyDrawsShadow) {
</span><span class="cx">         FloatRect shadowRect(textRect);
</span><del>-        shadowRect.inflate(shadow-&gt;paintingExtent());
</del><ins>+        shadowRect.inflate(shadow-&gt;paintingExtent() + 3 * textRect.height());
</ins><span class="cx">         shadowRect.move(shadowOffset);
</span><span class="cx">         context.save();
</span><span class="cx">         context.clip(shadowRect);
</span><span class="cx"> 
</span><span class="cx">         m_didSaveContext = true;
</span><del>-        m_extraOffset = FloatSize(0, 2 * textRect.height() + std::max(0.0f, shadowOffset.height()) + shadowRadius);
</del><ins>+        m_extraOffset = FloatSize(0, 2 * shadowRect.height() + std::max(0.0f, shadowOffset.height()) + shadowRadius);
</ins><span class="cx">         shadowOffset -= m_extraOffset;
</span><span class="cx">     }
</span><span class="cx"> 
</span></span></pre>
</div>
</div>

</body>
</html>