<!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>[198062] 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/198062">198062</a></dd>
<dt>Author</dt> <dd>zalan@apple.com</dd>
<dt>Date</dt> <dd>2016-03-12 09:24:21 -0800 (Sat, 12 Mar 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>[Forms: focus] focus rings around text fields do not follow contour (border-radius)
https://bugs.webkit.org/show_bug.cgi?id=154099
rdar://problem/9988429

Reviewed by Tim Horton.

Source/WebCore:

This patch enables outline-style: auto to follow the curve of border-radius.
When both border-radius and outline-style: auto are set, the native focusring painting will take the border-radius values
into account. This is only for outline-style: auto, other non-auto outline styles paint as if there
was no border-radius set.
It supports both single and multiline content with joint rectangles.
However in case of disjoint rectangles, we fallback to the non-radius drawing.

Tests: fast/inline/hidpi-outline-auto-with-border-radius-horizontal-ltr.html
       fast/inline/hidpi-outline-auto-with-border-radius-horizontal-rtl.html
       fast/inline/hidpi-outline-auto-with-border-radius-vertical-ltr.html
       fast/inline/hidpi-outline-auto-with-border-radius-vertical-rtl.html

* platform/graphics/GraphicsContext.h:
* platform/graphics/Path.cpp:
(WebCore::Path::addBeziersForRoundedRect):
* platform/graphics/Path.h:
(WebCore::Path::circleControlPoint):
* platform/graphics/PathUtilities.cpp:
(WebCore::polygonsForRect):
(WebCore::PathUtilities::pathsWithShrinkWrappedRects):
(WebCore::startAndEndPointsForCorner):
(WebCore::cornerType):
(WebCore::controlPointsForBezierCurve):
(WebCore::adjustedtRadiiForHuggingCurve):
(WebCore::PathUtilities::pathWithShrinkWrappedRectsForOutline):
* platform/graphics/PathUtilities.h:
* platform/graphics/mac/GraphicsContextMac.mm:
(WebCore::GraphicsContext::drawFocusRing):
* rendering/RenderElement.cpp:
(WebCore::RenderElement::paintFocusRing):

LayoutTests:

Unfortunately there's no proper way to test native focusring drawing.
These tests attempt to verify that we don't end up painting sharp corners.

* fast/inline/hidpi-outline-auto-with-border-radius-horizontal-ltr-expected.html: Added.
* fast/inline/hidpi-outline-auto-with-border-radius-horizontal-ltr.html: Added.
* fast/inline/hidpi-outline-auto-with-border-radius-horizontal-rtl-expected.html: Added.
* fast/inline/hidpi-outline-auto-with-border-radius-horizontal-rtl.html: Added.
* fast/inline/hidpi-outline-auto-with-border-radius-vertical-ltr-expected.html: Added.
* fast/inline/hidpi-outline-auto-with-border-radius-vertical-ltr.html: Added.
* fast/inline/hidpi-outline-auto-with-border-radius-vertical-rtl-expected.html: Added.
* fast/inline/hidpi-outline-auto-with-border-radius-vertical-rtl.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="#trunkSourceWebCoreplatformgraphicsGraphicsContexth">trunk/Source/WebCore/platform/graphics/GraphicsContext.h</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsPathcpp">trunk/Source/WebCore/platform/graphics/Path.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsPathh">trunk/Source/WebCore/platform/graphics/Path.h</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsPathUtilitiescpp">trunk/Source/WebCore/platform/graphics/PathUtilities.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsPathUtilitiesh">trunk/Source/WebCore/platform/graphics/PathUtilities.h</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsmacGraphicsContextMacmm">trunk/Source/WebCore/platform/graphics/mac/GraphicsContextMac.mm</a></li>
<li><a href="#trunkSourceWebCorerenderingRenderElementcpp">trunk/Source/WebCore/rendering/RenderElement.cpp</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsfastinlinehidpioutlineautowithborderradiushorizontalltrexpectedhtml">trunk/LayoutTests/fast/inline/hidpi-outline-auto-with-border-radius-horizontal-ltr-expected.html</a></li>
<li><a href="#trunkLayoutTestsfastinlinehidpioutlineautowithborderradiushorizontalltrhtml">trunk/LayoutTests/fast/inline/hidpi-outline-auto-with-border-radius-horizontal-ltr.html</a></li>
<li><a href="#trunkLayoutTestsfastinlinehidpioutlineautowithborderradiushorizontalrtlexpectedhtml">trunk/LayoutTests/fast/inline/hidpi-outline-auto-with-border-radius-horizontal-rtl-expected.html</a></li>
<li><a href="#trunkLayoutTestsfastinlinehidpioutlineautowithborderradiushorizontalrtlhtml">trunk/LayoutTests/fast/inline/hidpi-outline-auto-with-border-radius-horizontal-rtl.html</a></li>
<li><a href="#trunkLayoutTestsfastinlinehidpioutlineautowithborderradiusverticalltrexpectedhtml">trunk/LayoutTests/fast/inline/hidpi-outline-auto-with-border-radius-vertical-ltr-expected.html</a></li>
<li><a href="#trunkLayoutTestsfastinlinehidpioutlineautowithborderradiusverticalltrhtml">trunk/LayoutTests/fast/inline/hidpi-outline-auto-with-border-radius-vertical-ltr.html</a></li>
<li><a href="#trunkLayoutTestsfastinlinehidpioutlineautowithborderradiusverticalrtlexpectedhtml">trunk/LayoutTests/fast/inline/hidpi-outline-auto-with-border-radius-vertical-rtl-expected.html</a></li>
<li><a href="#trunkLayoutTestsfastinlinehidpioutlineautowithborderradiusverticalrtlhtml">trunk/LayoutTests/fast/inline/hidpi-outline-auto-with-border-radius-vertical-rtl.html</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (198061 => 198062)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2016-03-12 10:51:02 UTC (rev 198061)
+++ trunk/LayoutTests/ChangeLog        2016-03-12 17:24:21 UTC (rev 198062)
</span><span class="lines">@@ -1,3 +1,23 @@
</span><ins>+2016-03-12  Zalan Bujtas  &lt;zalan@apple.com&gt;
+
+        [Forms: focus] focus rings around text fields do not follow contour (border-radius)
+        https://bugs.webkit.org/show_bug.cgi?id=154099
+        rdar://problem/9988429
+
+        Reviewed by Tim Horton.
+
+        Unfortunately there's no proper way to test native focusring drawing.
+        These tests attempt to verify that we don't end up painting sharp corners.
+
+        * fast/inline/hidpi-outline-auto-with-border-radius-horizontal-ltr-expected.html: Added.
+        * fast/inline/hidpi-outline-auto-with-border-radius-horizontal-ltr.html: Added.
+        * fast/inline/hidpi-outline-auto-with-border-radius-horizontal-rtl-expected.html: Added.
+        * fast/inline/hidpi-outline-auto-with-border-radius-horizontal-rtl.html: Added.
+        * fast/inline/hidpi-outline-auto-with-border-radius-vertical-ltr-expected.html: Added.
+        * fast/inline/hidpi-outline-auto-with-border-radius-vertical-ltr.html: Added.
+        * fast/inline/hidpi-outline-auto-with-border-radius-vertical-rtl-expected.html: Added.
+        * fast/inline/hidpi-outline-auto-with-border-radius-vertical-rtl.html: Added.
+
</ins><span class="cx"> 2016-03-11  Ryosuke Niwa  &lt;rniwa@webkit.org&gt;
</span><span class="cx"> 
</span><span class="cx">         Add Event.deepPath() and Event.scoped
</span></span></pre></div>
<a id="trunkLayoutTestsfastinlinehidpioutlineautowithborderradiushorizontalltrexpectedhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/inline/hidpi-outline-auto-with-border-radius-horizontal-ltr-expected.html (0 => 198062)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/inline/hidpi-outline-auto-with-border-radius-horizontal-ltr-expected.html                                (rev 0)
+++ trunk/LayoutTests/fast/inline/hidpi-outline-auto-with-border-radius-horizontal-ltr-expected.html        2016-03-12 17:24:21 UTC (rev 198062)
</span><span class="lines">@@ -0,0 +1,7 @@
</span><ins>+&lt;!DOCTYPE html&gt;
+&lt;html&gt;
+&lt;head&gt;
+&lt;title&gt;This tests hugging outlines for multiline horizontal ltr content.&lt;/title&gt;
+&lt;/head&gt;
+&lt;body&gt;&lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsfastinlinehidpioutlineautowithborderradiushorizontalltrhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/inline/hidpi-outline-auto-with-border-radius-horizontal-ltr.html (0 => 198062)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/inline/hidpi-outline-auto-with-border-radius-horizontal-ltr.html                                (rev 0)
+++ trunk/LayoutTests/fast/inline/hidpi-outline-auto-with-border-radius-horizontal-ltr.html        2016-03-12 17:24:21 UTC (rev 198062)
</span><span class="lines">@@ -0,0 +1,51 @@
</span><ins>+&lt;!DOCTYPE html&gt;
+&lt;html&gt;
+&lt;head&gt;
+&lt;title&gt;This tests hugging outlines for multiline horizontal ltr content.&lt;/title&gt;
+&lt;style&gt;
+body {
+    font-size: 20px;
+    font-family: ahem;
+    color: rgba(0, 0, 0, 0);
+}
+
+.container {
+    margin-bottom: 20px;
+}
+
+span {
+    border-radius: 15px 10px 8px 5px;
+    outline-offset: 0px;
+    outline: auto;
+}
+
+.cover {
+    position: absolute;
+    border-radius: 15px 4px 8px 5px;
+    border: 7px solid white;
+}
+&lt;/style&gt;
+&lt;/head&gt;
+&lt;body&gt;
+&lt;div class=cover style=&quot;top: 3px; left: 3px; width: 56px; height: 56px; border-radius: 20px 3px 0px 3px;&quot;&gt;&lt;/div&gt;
+&lt;div class=cover style=&quot;top: 23px; left: 66px; width: 53px; height: 36px; border-radius: 0px 3px 0px 0px;&quot;&gt;&lt;/div&gt;
+&lt;div class=cover style=&quot;top: 43px; left: 126px; width: 133px; height: 16px; border-radius: 0px 18px 18px 0px;&quot;&gt;&lt;/div&gt;
+
+&lt;div class=cover style=&quot;top: 83px; left: 3px; width: 256px; height: 16px; border-radius: 20px 3px 3px 0px;&quot;&gt;&lt;/div&gt;
+&lt;div class=cover style=&quot;top: 106px; left: 3px; width: 196px; height: 13px; border-radius: 0px 0px 3px 0px;&quot;&gt;&lt;/div&gt;
+&lt;div class=cover style=&quot;top: 126px; left: 3px; width: 116px; height: 13px; border-radius: 0px 0px 14px 3px;&quot;&gt;&lt;/div&gt;
+
+&lt;div class=cover style=&quot;top: 163px; left: 3px; width: 116px; height: 13px; border-radius: 20px 3px 0px 0px;&quot;&gt;&lt;/div&gt;
+&lt;div class=cover style=&quot;top: 183px; left: 3px; width: 256px; height: 16px; border-radius: 0px 3px 3px 0px;&quot;&gt;&lt;/div&gt;
+&lt;div class=cover style=&quot;top: 206px; left: 3px; width: 116px; height: 13px; border-radius: 0px 0px 14px 3px;&quot;&gt;&lt;/div&gt;
+
+&lt;div class=cover style=&quot;top: 243px; left: 3px; width: 256px; height: 15px; border-radius: 20px 3px 3px 0px;&quot;&gt;&lt;/div&gt;
+&lt;div class=cover style=&quot;top: 265px; left: 3px; width: 116px; height: 13px; border-radius: 0px 0px 0px 0px;&quot;&gt;&lt;/div&gt;
+&lt;div class=cover style=&quot;top: 284px; left: 3px; width: 256px; height: 14px; border-radius: 0px 18px 18px 3px;&quot;&gt;&lt;/div&gt;
+
+&lt;div class=container&gt;&lt;span&gt;foo&lt;br&gt;foobar&lt;br&gt;foobar foobar&lt;/span&gt;&lt;/div&gt;
+&lt;div class=container&gt;&lt;span&gt;foobar foobar&lt;br&gt;foobar foo&lt;br&gt;foobar&lt;/span&gt;&lt;/div&gt;
+&lt;div class=container&gt;&lt;span&gt;foobar&lt;br&gt;foobar foobar&lt;br&gt;foobar&lt;/span&gt;&lt;/div&gt;
+&lt;div class=container&gt;&lt;span&gt;foobar foobar&lt;br&gt;foobar&lt;br&gt;foobar foobar&lt;/span&gt;&lt;/div&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsfastinlinehidpioutlineautowithborderradiushorizontalrtlexpectedhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/inline/hidpi-outline-auto-with-border-radius-horizontal-rtl-expected.html (0 => 198062)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/inline/hidpi-outline-auto-with-border-radius-horizontal-rtl-expected.html                                (rev 0)
+++ trunk/LayoutTests/fast/inline/hidpi-outline-auto-with-border-radius-horizontal-rtl-expected.html        2016-03-12 17:24:21 UTC (rev 198062)
</span><span class="lines">@@ -0,0 +1,7 @@
</span><ins>+&lt;!DOCTYPE html&gt;
+&lt;html&gt;
+&lt;head&gt;
+&lt;title&gt;This tests hugging outlines for multiline horizontal rtl content.&lt;/title&gt;
+&lt;/head&gt;
+&lt;body&gt;&lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsfastinlinehidpioutlineautowithborderradiushorizontalrtlhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/inline/hidpi-outline-auto-with-border-radius-horizontal-rtl.html (0 => 198062)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/inline/hidpi-outline-auto-with-border-radius-horizontal-rtl.html                                (rev 0)
+++ trunk/LayoutTests/fast/inline/hidpi-outline-auto-with-border-radius-horizontal-rtl.html        2016-03-12 17:24:21 UTC (rev 198062)
</span><span class="lines">@@ -0,0 +1,52 @@
</span><ins>+&lt;!DOCTYPE html&gt;
+&lt;html&gt;
+&lt;head&gt;
+&lt;title&gt;This tests hugging outlines for multiline horizontal rtl content.&lt;/title&gt;
+&lt;style&gt;
+body {
+    direction: rtl;
+    font-size: 20px;
+    font-family: ahem;
+    color: rgba(0, 0, 0, 0);
+}

+.container {
+    margin-bottom: 20px;
+}
+
+span {
+    border-radius: 15px 10px 8px 5px;
+    outline-offset: 0px;
+    outline: auto;
+}
+
+.cover {
+    position: absolute;
+    border-radius: 15px 4px 8px 5px;
+    border: 7px solid white;
+}
+&lt;/style&gt;
+&lt;/head&gt;
+&lt;body&gt;
+&lt;div class=cover style=&quot;top: 3px; right: 3px; width: 56px; height: 56px; border-radius: 3px 16px 3px 0px;&quot;&gt;&lt;/div&gt;
+&lt;div class=cover style=&quot;top: 23px; right: 66px; width: 53px; height: 36px; border-radius: 3px 0px 0px 0px;&quot;&gt;&lt;/div&gt;
+&lt;div class=cover style=&quot;top: 43px; right: 126px; width: 133px; height: 16px; border-radius: 21px 0px 0px 11px;&quot;&gt;&lt;/div&gt;
+
+&lt;div class=cover style=&quot;top: 83px; right: 3px; width: 256px; height: 16px; border-radius: 3px 16px 0px 3px;&quot;&gt;&lt;/div&gt;
+&lt;div class=cover style=&quot;top: 106px; right: 3px; width: 196px; height: 13px; border-radius: 0px 0px 0px 3px;&quot;&gt;&lt;/div&gt;
+&lt;div class=cover style=&quot;top: 126px; right: 3px; width: 116px; height: 13px; border-radius: 0px 0px 3px 12px;&quot;&gt;&lt;/div&gt;
+
+&lt;div class=cover style=&quot;top: 163px; right: 3px; width: 116px; height: 13px; border-radius: 3px 16px 0px 0px;&quot;&gt;&lt;/div&gt;
+&lt;div class=cover style=&quot;top: 183px; right: 3px; width: 256px; height: 16px; border-radius: 3px 0px 0px 3px;&quot;&gt;&lt;/div&gt;
+&lt;div class=cover style=&quot;top: 206px; right: 3px; width: 116px; height: 13px; border-radius: 0px 0px 3px 12px;&quot;&gt;&lt;/div&gt;
+
+&lt;div class=cover style=&quot;top: 243px; right: 3px; width: 256px; height: 15px; border-radius: 3px 16px 0px 3px;&quot;&gt;&lt;/div&gt;
+&lt;div class=cover style=&quot;top: 265px; right: 3px; width: 116px; height: 13px; border-radius: 0px 0px 0px 0px;&quot;&gt;&lt;/div&gt;
+&lt;div class=cover style=&quot;top: 284px; right: 3px; width: 256px; height: 14px; border-radius: 21px 0px 3px 11px;&quot;&gt;&lt;/div&gt;
+
+&lt;div class=container&gt;&lt;span&gt;foo&lt;br&gt;foobar&lt;br&gt;foobar foobar&lt;/span&gt;&lt;/div&gt;
+&lt;div class=container&gt;&lt;span&gt;foobar foobar&lt;br&gt;foobar foo&lt;br&gt;foobar&lt;/span&gt;&lt;/div&gt;
+&lt;div class=container&gt;&lt;span&gt;foobar&lt;br&gt;foobar foobar&lt;br&gt;foobar&lt;/span&gt;&lt;/div&gt;
+&lt;div class=container&gt;&lt;span&gt;foobar foobar&lt;br&gt;foobar&lt;br&gt;foobar foobar&lt;/span&gt;&lt;/div&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsfastinlinehidpioutlineautowithborderradiusverticalltrexpectedhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/inline/hidpi-outline-auto-with-border-radius-vertical-ltr-expected.html (0 => 198062)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/inline/hidpi-outline-auto-with-border-radius-vertical-ltr-expected.html                                (rev 0)
+++ trunk/LayoutTests/fast/inline/hidpi-outline-auto-with-border-radius-vertical-ltr-expected.html        2016-03-12 17:24:21 UTC (rev 198062)
</span><span class="lines">@@ -0,0 +1,7 @@
</span><ins>+&lt;!DOCTYPE html&gt;
+&lt;html&gt;
+&lt;head&gt;
+&lt;title&gt;This tests hugging outlines for multiline vertical ltr content.&lt;/title&gt;
+&lt;/head&gt;
+&lt;body&gt;&lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsfastinlinehidpioutlineautowithborderradiusverticalltrhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/inline/hidpi-outline-auto-with-border-radius-vertical-ltr.html (0 => 198062)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/inline/hidpi-outline-auto-with-border-radius-vertical-ltr.html                                (rev 0)
+++ trunk/LayoutTests/fast/inline/hidpi-outline-auto-with-border-radius-vertical-ltr.html        2016-03-12 17:24:21 UTC (rev 198062)
</span><span class="lines">@@ -0,0 +1,53 @@
</span><ins>+&lt;!DOCTYPE html&gt;
+&lt;html&gt;
+&lt;head&gt;
+&lt;title&gt;This tests hugging outlines for multiline vertical ltr content.&lt;/title&gt;
+&lt;style&gt;
+body {
+    font-size: 20px;
+    font-family: ahem;
+    color: rgba(0, 0, 0, 0);
+}

+.container {
+    -webkit-writing-mode: vertical-lr;
+    margin-left: 20px;
+    display: inline-block;
+}
+
+span {
+    border-radius: 15px 10px 8px 5px;
+    outline-offset: 0px;
+    outline: auto;
+}
+
+.cover {
+    position: absolute;
+    border-radius: 15px 4px 8px 5px;
+    border: 7px solid white;
+}
+&lt;/style&gt;
+&lt;/head&gt;
+&lt;body&gt;
+&lt;div class=cover style=&quot;top: 4px; left: 24px; width: 12px; height: 54px; border-radius: 15px 0px 0px 3px;&quot;&gt;&lt;/div&gt;
+&lt;div class=cover style=&quot;top: 4px; left: 43px; width: 13px; height: 114px; border-radius: 0px 0px 0px 3px;&quot;&gt;&lt;/div&gt;
+&lt;div class=cover style=&quot;top: 4px; left: 63px; width: 16px; height: 255px; border-radius: 0px 3px 12px 12px;&quot;&gt;&lt;/div&gt;
+
+&lt;div class=cover style=&quot;top: 4px; left: 124px; width: 15px; height: 255px; border-radius: 15px 0px 3px 3px;&quot;&gt;&lt;/div&gt;
+&lt;div class=cover style=&quot;top: 4px; left: 147px; width: 12px; height: 195px; border-radius: 0px 0px 3px 0px;&quot;&gt;&lt;/div&gt;
+&lt;div class=cover style=&quot;top: 4px; left: 166px; width: 13px; height: 114px; border-radius: 0px 3px 11px 0px;&quot;&gt;&lt;/div&gt;
+
+&lt;div class=cover style=&quot;top: 4px; left: 223px; width: 13px; height: 114px; border-radius: 15px 0px 0px 3px;&quot;&gt;&lt;/div&gt;
+&lt;div class=cover style=&quot;top: 4px; left: 243px; width: 16px; height: 255px; border-radius: 0px 0px 3px 3px;&quot;&gt;&lt;/div&gt;
+&lt;div class=cover style=&quot;top: 4px; left: 266px; width: 13px; height: 114px; border-radius: 0px 3px 11px 0px;&quot;&gt;&lt;/div&gt;
+
+&lt;div class=cover style=&quot;top: 4px; left: 323px; width: 16px; height: 255px; border-radius: 15px 0px 3px 3px;&quot;&gt;&lt;/div&gt;
+&lt;div class=cover style=&quot;top: 4px; left: 346px; width: 10px; height: 114px; border-radius: 0px 0px 0px 0px;&quot;&gt;&lt;/div&gt;
+&lt;div class=cover style=&quot;top: 4px; left: 363px; width: 16px; height: 255px; border-radius: 0px 3px 12px 12px;&quot;&gt;&lt;/div&gt;
+
+&lt;div class=container&gt;&lt;span&gt;foo&lt;br&gt;foobar&lt;br&gt;foobar foobar&lt;/span&gt;&lt;/div&gt;
+&lt;div class=container&gt;&lt;span&gt;foobar foobar&lt;br&gt;foobar foo&lt;br&gt;foobar&lt;/span&gt;&lt;/div&gt;
+&lt;div class=container&gt;&lt;span&gt;foobar&lt;br&gt;foobar foobar&lt;br&gt;foobar&lt;/span&gt;&lt;/div&gt;
+&lt;div class=container&gt;&lt;span&gt;foobar foobar&lt;br&gt;foobar&lt;br&gt;foobar foobar&lt;/span&gt;&lt;/div&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsfastinlinehidpioutlineautowithborderradiusverticalrtlexpectedhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/inline/hidpi-outline-auto-with-border-radius-vertical-rtl-expected.html (0 => 198062)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/inline/hidpi-outline-auto-with-border-radius-vertical-rtl-expected.html                                (rev 0)
+++ trunk/LayoutTests/fast/inline/hidpi-outline-auto-with-border-radius-vertical-rtl-expected.html        2016-03-12 17:24:21 UTC (rev 198062)
</span><span class="lines">@@ -0,0 +1,7 @@
</span><ins>+&lt;!DOCTYPE html&gt;
+&lt;html&gt;
+&lt;head&gt;
+&lt;title&gt;This tests hugging outlines for multiline vertical rtl content.&lt;/title&gt;
+&lt;/head&gt;
+&lt;body&gt;&lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsfastinlinehidpioutlineautowithborderradiusverticalrtlhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/inline/hidpi-outline-auto-with-border-radius-vertical-rtl.html (0 => 198062)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/inline/hidpi-outline-auto-with-border-radius-vertical-rtl.html                                (rev 0)
+++ trunk/LayoutTests/fast/inline/hidpi-outline-auto-with-border-radius-vertical-rtl.html        2016-03-12 17:24:21 UTC (rev 198062)
</span><span class="lines">@@ -0,0 +1,54 @@
</span><ins>+&lt;!DOCTYPE html&gt;
+&lt;html&gt;
+&lt;head&gt;
+&lt;title&gt;This tests hugging outlines for multiline vertical rtl content.&lt;/title&gt;
+&lt;style&gt;
+body {
+    direction: rtl;
+    font-size: 20px;
+    font-family: ahem;
+    color: rgba(0, 0, 0, 0);
+}

+.container {
+    -webkit-writing-mode: vertical-lr;
+    margin-left: 20px;
+    display: inline-block;
+}
+
+span {
+    border-radius: 15px 10px 8px 5px;
+    outline-offset: 0px;
+    outline: auto;
+}
+
+.cover {
+    position: absolute;
+    border-radius: 15px 4px 8px 5px;
+    border: 7px solid white;
+}
+&lt;/style&gt;
+&lt;/head&gt;
+&lt;body&gt;
+&lt;div class=cover style=&quot;top: 204px; right: 46px; width: 12px; height: 55px; border-radius: 3px 0px 0px 8px&quot;&gt;&lt;/div&gt;
+&lt;div class=cover style=&quot;top: 143px; right: 26px; width: 13px; height: 116px; border-radius: 3px 0px 0px 0px;&quot;&gt;&lt;/div&gt;
+&lt;div class=cover style=&quot;top: 4px; right: 3px; width: 16px; height: 255px; border-radius: 16px 11px 3px 0px;&quot;&gt;&lt;/div&gt;
+
+&lt;div class=cover style=&quot;top: 3px; right: 143px; width: 16px; height: 255px; border-radius: 3px 3px 0px 8px;&quot;&gt;&lt;/div&gt;
+&lt;div class=cover style=&quot;top: 63px; right: 123px; width: 13px; height: 195px; border-radius: 0px 3px 0px 0px;&quot;&gt;&lt;/div&gt;
+&lt;div class=cover style=&quot;top: 143px; right: 103px; width: 13px; height: 115px; border-radius: 0px 12px 3px 0px;&quot;&gt;&lt;/div&gt;
+
+&lt;div class=cover style=&quot;top: 143px; right: 203px; width: 13px; height: 115px; border-radius: 0px 12px 3px 0px;&quot;&gt;&lt;/div&gt;
+&lt;div class=cover style=&quot;top: 3px; right: 223px; width: 16px; height: 255px; border-radius: 3px 3px 0px 0px;&quot;&gt;&lt;/div&gt;
+&lt;div class=cover style=&quot;top: 143px; right: 246px; width: 13px; height: 115px; border-radius: 3px 0px 0px 3px;&quot;&gt;&lt;/div&gt;
+
+&lt;div class=cover style=&quot;top: 3px; right: 303px; width: 16px; height: 255px; border-radius: 16px 12px 3px 0px;&quot;&gt;&lt;/div&gt;
+&lt;div class=cover style=&quot;top: 144px; right: 326px; width: 10px; height: 114px; border-radius: 0px 0px 0px 0px;&quot;&gt;&lt;/div&gt;
+&lt;div class=cover style=&quot;top: 3px; right: 343px; width: 16px; height: 255px; border-radius: 3px 3px 0px 3px;&quot;&gt;&lt;/div&gt;
+
+&lt;div class=container&gt;&lt;span&gt;foo&lt;br&gt;foobar&lt;br&gt;foobar foobar&lt;/span&gt;&lt;/div&gt;
+&lt;div class=container&gt;&lt;span&gt;foobar foobar&lt;br&gt;foobar foo&lt;br&gt;foobar&lt;/span&gt;&lt;/div&gt;
+&lt;div class=container&gt;&lt;span&gt;foobar&lt;br&gt;foobar foobar&lt;br&gt;foobar&lt;/span&gt;&lt;/div&gt;
+&lt;div class=container&gt;&lt;span&gt;foobar foobar&lt;br&gt;foobar&lt;br&gt;foobar foobar&lt;/span&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 (198061 => 198062)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2016-03-12 10:51:02 UTC (rev 198061)
+++ trunk/Source/WebCore/ChangeLog        2016-03-12 17:24:21 UTC (rev 198062)
</span><span class="lines">@@ -1,3 +1,42 @@
</span><ins>+2016-03-12  Zalan Bujtas  &lt;zalan@apple.com&gt;
+
+        [Forms: focus] focus rings around text fields do not follow contour (border-radius)
+        https://bugs.webkit.org/show_bug.cgi?id=154099
+        rdar://problem/9988429
+
+        Reviewed by Tim Horton.
+
+        This patch enables outline-style: auto to follow the curve of border-radius.
+        When both border-radius and outline-style: auto are set, the native focusring painting will take the border-radius values
+        into account. This is only for outline-style: auto, other non-auto outline styles paint as if there
+        was no border-radius set.
+        It supports both single and multiline content with joint rectangles.
+        However in case of disjoint rectangles, we fallback to the non-radius drawing.
+
+        Tests: fast/inline/hidpi-outline-auto-with-border-radius-horizontal-ltr.html
+               fast/inline/hidpi-outline-auto-with-border-radius-horizontal-rtl.html
+               fast/inline/hidpi-outline-auto-with-border-radius-vertical-ltr.html
+               fast/inline/hidpi-outline-auto-with-border-radius-vertical-rtl.html
+
+        * platform/graphics/GraphicsContext.h:
+        * platform/graphics/Path.cpp:
+        (WebCore::Path::addBeziersForRoundedRect):
+        * platform/graphics/Path.h:
+        (WebCore::Path::circleControlPoint):
+        * platform/graphics/PathUtilities.cpp:
+        (WebCore::polygonsForRect):
+        (WebCore::PathUtilities::pathsWithShrinkWrappedRects):
+        (WebCore::startAndEndPointsForCorner):
+        (WebCore::cornerType):
+        (WebCore::controlPointsForBezierCurve):
+        (WebCore::adjustedtRadiiForHuggingCurve):
+        (WebCore::PathUtilities::pathWithShrinkWrappedRectsForOutline):
+        * platform/graphics/PathUtilities.h:
+        * platform/graphics/mac/GraphicsContextMac.mm:
+        (WebCore::GraphicsContext::drawFocusRing):
+        * rendering/RenderElement.cpp:
+        (WebCore::RenderElement::paintFocusRing):
+
</ins><span class="cx"> 2016-03-11  Ryosuke Niwa  &lt;rniwa@webkit.org&gt;
</span><span class="cx"> 
</span><span class="cx">         Add Event.deepPath() and Event.scoped
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsGraphicsContexth"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/GraphicsContext.h (198061 => 198062)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/GraphicsContext.h        2016-03-12 10:51:02 UTC (rev 198061)
+++ trunk/Source/WebCore/platform/graphics/GraphicsContext.h        2016-03-12 17:24:21 UTC (rev 198062)
</span><span class="lines">@@ -433,7 +433,8 @@
</span><span class="cx">     void drawFocusRing(const Vector&lt;FloatRect&gt;&amp;, float width, float offset, const Color&amp;);
</span><span class="cx">     void drawFocusRing(const Path&amp;, float width, float offset, const Color&amp;);
</span><span class="cx"> #if PLATFORM(MAC)
</span><del>-    void drawFocusRing(const Vector&lt;FloatRect&gt;&amp;, float offset, double timeOffset, bool&amp; needsRedraw);
</del><ins>+    void drawFocusRing(const Path&amp;, double timeOffset, bool&amp; needsRedraw);
+    void drawFocusRing(const Vector&lt;FloatRect&gt;&amp;, double timeOffset, bool&amp; needsRedraw);
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx">     void setLineCap(LineCap);
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsPathcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/Path.cpp (198061 => 198062)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/Path.cpp        2016-03-12 10:51:02 UTC (rev 198061)
+++ trunk/Source/WebCore/platform/graphics/Path.cpp        2016-03-12 17:24:21 UTC (rev 198062)
</span><span class="lines">@@ -130,33 +130,29 @@
</span><span class="cx">     addRoundedRect(FloatRoundedRect(r));
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-// Approximation of control point positions on a bezier to simulate a quarter of a circle.
-// This is 1-kappa, where kappa = 4 * (sqrt(2) - 1) / 3
-static const float gCircleControlPoint = 0.447715f;
-
</del><span class="cx"> void Path::addBeziersForRoundedRect(const FloatRect&amp; rect, const FloatSize&amp; topLeftRadius, const FloatSize&amp; topRightRadius, const FloatSize&amp; bottomLeftRadius, const FloatSize&amp; bottomRightRadius)
</span><span class="cx"> {
</span><span class="cx">     moveTo(FloatPoint(rect.x() + topLeftRadius.width(), rect.y()));
</span><span class="cx"> 
</span><span class="cx">     addLineTo(FloatPoint(rect.maxX() - topRightRadius.width(), rect.y()));
</span><span class="cx">     if (topRightRadius.width() &gt; 0 || topRightRadius.height() &gt; 0)
</span><del>-        addBezierCurveTo(FloatPoint(rect.maxX() - topRightRadius.width() * gCircleControlPoint, rect.y()),
-            FloatPoint(rect.maxX(), rect.y() + topRightRadius.height() * gCircleControlPoint),
</del><ins>+        addBezierCurveTo(FloatPoint(rect.maxX() - topRightRadius.width() * circleControlPoint(), rect.y()),
+            FloatPoint(rect.maxX(), rect.y() + topRightRadius.height() * circleControlPoint()),
</ins><span class="cx">             FloatPoint(rect.maxX(), rect.y() + topRightRadius.height()));
</span><span class="cx">     addLineTo(FloatPoint(rect.maxX(), rect.maxY() - bottomRightRadius.height()));
</span><span class="cx">     if (bottomRightRadius.width() &gt; 0 || bottomRightRadius.height() &gt; 0)
</span><del>-        addBezierCurveTo(FloatPoint(rect.maxX(), rect.maxY() - bottomRightRadius.height() * gCircleControlPoint),
-            FloatPoint(rect.maxX() - bottomRightRadius.width() * gCircleControlPoint, rect.maxY()),
</del><ins>+        addBezierCurveTo(FloatPoint(rect.maxX(), rect.maxY() - bottomRightRadius.height() * circleControlPoint()),
+            FloatPoint(rect.maxX() - bottomRightRadius.width() * circleControlPoint(), rect.maxY()),
</ins><span class="cx">             FloatPoint(rect.maxX() - bottomRightRadius.width(), rect.maxY()));
</span><span class="cx">     addLineTo(FloatPoint(rect.x() + bottomLeftRadius.width(), rect.maxY()));
</span><span class="cx">     if (bottomLeftRadius.width() &gt; 0 || bottomLeftRadius.height() &gt; 0)
</span><del>-        addBezierCurveTo(FloatPoint(rect.x() + bottomLeftRadius.width() * gCircleControlPoint, rect.maxY()),
-            FloatPoint(rect.x(), rect.maxY() - bottomLeftRadius.height() * gCircleControlPoint),
</del><ins>+        addBezierCurveTo(FloatPoint(rect.x() + bottomLeftRadius.width() * circleControlPoint(), rect.maxY()),
+            FloatPoint(rect.x(), rect.maxY() - bottomLeftRadius.height() * circleControlPoint()),
</ins><span class="cx">             FloatPoint(rect.x(), rect.maxY() - bottomLeftRadius.height()));
</span><span class="cx">     addLineTo(FloatPoint(rect.x(), rect.y() + topLeftRadius.height()));
</span><span class="cx">     if (topLeftRadius.width() &gt; 0 || topLeftRadius.height() &gt; 0)
</span><del>-        addBezierCurveTo(FloatPoint(rect.x(), rect.y() + topLeftRadius.height() * gCircleControlPoint),
-            FloatPoint(rect.x() + topLeftRadius.width() * gCircleControlPoint, rect.y()),
</del><ins>+        addBezierCurveTo(FloatPoint(rect.x(), rect.y() + topLeftRadius.height() * circleControlPoint()),
+            FloatPoint(rect.x() + topLeftRadius.width() * circleControlPoint(), rect.y()),
</ins><span class="cx">             FloatPoint(rect.x() + topLeftRadius.width(), rect.y()));
</span><span class="cx"> 
</span><span class="cx">     closeSubpath();
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsPathh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/Path.h (198061 => 198062)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/Path.h        2016-03-12 10:51:02 UTC (rev 198061)
+++ trunk/Source/WebCore/platform/graphics/Path.h        2016-03-12 17:24:21 UTC (rev 198062)
</span><span class="lines">@@ -162,6 +162,13 @@
</span><span class="cx">         WEBCORE_EXPORT void apply(const PathApplierFunction&amp;) const;
</span><span class="cx">         void transform(const AffineTransform&amp;);
</span><span class="cx"> 
</span><ins>+        static float circleControlPoint()
+        {
+            // Approximation of control point positions on a bezier to simulate a quarter of a circle.
+            // This is 1-kappa, where kappa = 4 * (sqrt(2) - 1) / 3
+            return 0.447715;
+        }
+
</ins><span class="cx">         void addBeziersForRoundedRect(const FloatRect&amp;, const FloatSize&amp; topLeftRadius, const FloatSize&amp; topRightRadius, const FloatSize&amp; bottomLeftRadius, const FloatSize&amp; bottomRightRadius);
</span><span class="cx"> 
</span><span class="cx"> #if USE(CG)
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsPathUtilitiescpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/PathUtilities.cpp (198061 => 198062)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/PathUtilities.cpp        2016-03-12 10:51:02 UTC (rev 198061)
+++ trunk/Source/WebCore/platform/graphics/PathUtilities.cpp        2016-03-12 17:24:21 UTC (rev 198062)
</span><span class="lines">@@ -28,8 +28,10 @@
</span><span class="cx"> #include &quot;PathUtilities.h&quot;
</span><span class="cx"> 
</span><span class="cx"> #include &quot;AffineTransform.h&quot;
</span><ins>+#include &quot;BorderData.h&quot;
</ins><span class="cx"> #include &quot;FloatPoint.h&quot;
</span><span class="cx"> #include &quot;FloatRect.h&quot;
</span><ins>+#include &quot;FloatRoundedRect.h&quot;
</ins><span class="cx"> #include &quot;GeometryUtilities.h&quot;
</span><span class="cx"> #include &lt;math.h&gt;
</span><span class="cx"> #include &lt;wtf/MathExtras.h&gt;
</span><span class="lines">@@ -255,25 +257,11 @@
</span><span class="cx">     });
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-Vector&lt;Path&gt; PathUtilities::pathsWithShrinkWrappedRects(const Vector&lt;FloatRect&gt;&amp; rects, float radius)
</del><ins>+static Vector&lt;FloatPointGraph::Polygon&gt; polygonsForRect(const Vector&lt;FloatRect&gt;&amp; rects, FloatPointGraph&amp; graph)
</ins><span class="cx"> {
</span><del>-    Vector&lt;Path&gt; paths;
-
-    if (rects.isEmpty())
-        return paths;
-
-    if (rects.size() &gt; 20) {
-        Path path;
-        path.addRoundedRect(unionRect(rects), FloatSize(radius, radius));
-        paths.append(path);
-        return paths;
-    }
-
</del><span class="cx">     Vector&lt;FloatRect&gt; sortedRects = rects;
</span><del>-
</del><span class="cx">     std::sort(sortedRects.begin(), sortedRects.end(), [](FloatRect a, FloatRect b) { return b.y() &gt; a.y(); });
</span><span class="cx"> 
</span><del>-    FloatPointGraph graph;
</del><span class="cx">     Vector&lt;FloatPointGraph::Polygon&gt; rectPolygons;
</span><span class="cx">     rectPolygons.reserveInitialCapacity(sortedRects.size());
</span><span class="cx"> 
</span><span class="lines">@@ -291,12 +279,28 @@
</span><span class="cx">         if (!isContained)
</span><span class="cx">             rectPolygons.append(edgesForRect(rect, graph));
</span><span class="cx">     }
</span><ins>+    return unitePolygons(rectPolygons, graph);
+}
</ins><span class="cx"> 
</span><del>-    Vector&lt;FloatPointGraph::Polygon&gt; polys = unitePolygons(rectPolygons, graph);
</del><ins>+Vector&lt;Path&gt; PathUtilities::pathsWithShrinkWrappedRects(const Vector&lt;FloatRect&gt;&amp; rects, float radius)
+{
+    Vector&lt;Path&gt; paths;
</ins><span class="cx"> 
</span><ins>+    if (rects.isEmpty())
+        return paths;
+
+    if (rects.size() &gt; 20) {
+        Path path;
+        path.addRoundedRect(unionRect(rects), FloatSize(radius, radius));
+        paths.append(path);
+        return paths;
+    }
+
+    FloatPointGraph graph;
+    Vector&lt;FloatPointGraph::Polygon&gt; polys = polygonsForRect(rects, graph);
</ins><span class="cx">     if (polys.isEmpty()) {
</span><span class="cx">         Path path;
</span><del>-        path.addRoundedRect(unionRect(sortedRects), FloatSize(radius, radius));
</del><ins>+        path.addRoundedRect(unionRect(rects), FloatSize(radius, radius));
</ins><span class="cx">         paths.append(path);
</span><span class="cx">         return paths;
</span><span class="cx">     }
</span><span class="lines">@@ -331,11 +335,9 @@
</span><span class="cx">                 path.addLineTo(*fromEdge.second - fromOffset);
</span><span class="cx">             path.addArcTo(*fromEdge.second, *toEdge.first + toOffset, clampedRadius);
</span><span class="cx">         }
</span><del>-
</del><span class="cx">         path.closeSubpath();
</span><span class="cx">         paths.append(path);
</span><span class="cx">     }
</span><del>-
</del><span class="cx">     return paths;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -350,4 +352,193 @@
</span><span class="cx">     return unionPath;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+static std::pair&lt;FloatPoint, FloatPoint&gt; startAndEndPointsForCorner(const FloatPointGraph::Edge&amp; fromEdge, const FloatPointGraph::Edge&amp; toEdge, const FloatSize&amp; radius)
+{
+    FloatPoint startPoint;
+    FloatPoint endPoint;
+    
+    FloatSize fromEdgeVector = *fromEdge.second - *fromEdge.first;
+    FloatSize toEdgeVector = *toEdge.second - *toEdge.first;
+
+    FloatPoint fromEdgeNorm = toFloatPoint(fromEdgeVector);
+    fromEdgeNorm.normalize();
+    FloatSize fromOffset = FloatSize(radius.width() * fromEdgeNorm.x(), radius.height() * fromEdgeNorm.y());
+    startPoint = *fromEdge.second - fromOffset;
+
+    FloatPoint toEdgeNorm = toFloatPoint(toEdgeVector);
+    toEdgeNorm.normalize();
+    FloatSize toOffset = FloatSize(radius.width() * toEdgeNorm.x(), radius.height() * toEdgeNorm.y());
+    endPoint = *toEdge.first + toOffset;
+    return std::make_pair(startPoint, endPoint);
</ins><span class="cx"> }
</span><ins>+
+enum class CornerType { TopLeft, TopRight, BottomRight, BottomLeft, Other };
+static CornerType cornerType(const FloatPointGraph::Edge&amp; fromEdge, const FloatPointGraph::Edge&amp; toEdge, const Vector&lt;FloatPoint&gt;&amp; corners)
+{
+    auto fromEdgeVector = *fromEdge.second - *fromEdge.first;
+    auto toEdgeVector = *toEdge.second - *toEdge.first;
+
+    if (fromEdgeVector.height() &lt; 0 &amp;&amp; toEdgeVector.width() &gt; 0 &amp;&amp; corners.at(0) == *fromEdge.second)
+        return CornerType::TopLeft;
+    if (fromEdgeVector.width() &gt; 0 &amp;&amp; toEdgeVector.height() &gt; 0 &amp;&amp; corners.at(1) == *fromEdge.second)
+        return CornerType::TopRight;
+    if (fromEdgeVector.height() &gt; 0 &amp;&amp; toEdgeVector.width() &lt; 0 &amp;&amp; corners.at(2) == *fromEdge.second)
+        return CornerType::BottomRight;
+    if (fromEdgeVector.width() &lt; 0 &amp;&amp; toEdgeVector.height() &lt; 0 &amp;&amp; corners.at(3) == *fromEdge.second)
+        return CornerType::BottomLeft;
+    return CornerType::Other;
+}
+
+static std::pair&lt;FloatPoint, FloatPoint&gt; controlPointsForBezierCurve(CornerType cornerType, const FloatPointGraph::Edge&amp; fromEdge,
+    const FloatPointGraph::Edge&amp; toEdge, const FloatSize&amp; radius)
+{
+    FloatPoint cp1;
+    FloatPoint cp2;
+    switch (cornerType) {
+    case CornerType::TopLeft: {
+        cp1 = FloatPoint(fromEdge.second-&gt;x(), fromEdge.second-&gt;y() + radius.height() * Path::circleControlPoint());
+        cp2 = FloatPoint(toEdge.first-&gt;x() + radius.width() * Path::circleControlPoint(), toEdge.first-&gt;y());
+        break;
+    }
+    case CornerType::TopRight: {
+        cp1 = FloatPoint(fromEdge.second-&gt;x() - radius.width() * Path::circleControlPoint(), fromEdge.second-&gt;y());
+        cp2 = FloatPoint(toEdge.first-&gt;x(), toEdge.first-&gt;y() + radius.height() * Path::circleControlPoint());
+        break;
+    }
+    case CornerType::BottomRight: {
+        cp1 = FloatPoint(fromEdge.second-&gt;x(), fromEdge.second-&gt;y() - radius.height() * Path::circleControlPoint());
+        cp2 = FloatPoint(toEdge.first-&gt;x() - radius.width() * Path::circleControlPoint(), toEdge.first-&gt;y());
+        break;
+    }
+    case CornerType::BottomLeft: {
+        cp1 = FloatPoint(fromEdge.second-&gt;x() + radius.width() * Path::circleControlPoint(), fromEdge.second-&gt;y());
+        cp2 = FloatPoint(toEdge.first-&gt;x(), toEdge.first-&gt;y() - radius.height() * Path::circleControlPoint());
+        break;
+    }
+    case CornerType::Other: {
+        ASSERT_NOT_REACHED();
+        break;
+    }
+    }
+    return std::make_pair(cp1, cp2);
+}
+
+static FloatRoundedRect::Radii adjustedtRadiiForHuggingCurve(const FloatSize&amp; topLeftRadius, const FloatSize&amp; topRightRadius,
+    const FloatSize&amp; bottomLeftRadius, const FloatSize&amp; bottomRightRadius, float outlineOffset)
+{
+    FloatRoundedRect::Radii radii;
+    // This adjusts the radius so that it follows the border curve even when offset is present.
+    auto adjustedRadius = [outlineOffset](const FloatSize&amp; radius)
+    {
+        FloatSize adjustedRadius = radius;
+        if (radius.width() &gt; outlineOffset)
+            adjustedRadius.expand(std::min(outlineOffset, radius.width() - outlineOffset), 0);
+        if (radius.height() &gt; outlineOffset)
+            adjustedRadius.expand(0, std::min(outlineOffset, radius.height() - outlineOffset));
+        return adjustedRadius;
+    };
+
+    radii.setTopLeft(adjustedRadius(topLeftRadius));
+    radii.setTopRight(adjustedRadius(topRightRadius));
+    radii.setBottomRight(adjustedRadius(bottomRightRadius));
+    radii.setBottomLeft(adjustedRadius(bottomLeftRadius));
+    return radii;
+}
+    
+Path PathUtilities::pathWithShrinkWrappedRectsForOutline(const Vector&lt;FloatRect&gt;&amp; rects, const BorderData&amp; borderData, float outlineOffset, TextDirection direction,
+    WritingMode writingMode)
+{
+    ASSERT(borderData.hasBorderRadius());
+    FloatSize topLeftRadius = FloatSize(borderData.topLeft().width().value(), borderData.topLeft().height().value());
+    FloatSize topRightRadius = FloatSize(borderData.topRight().width().value(), borderData.topRight().height().value());
+    FloatSize bottomRightRadius = FloatSize(borderData.bottomRight().width().value(), borderData.bottomRight().height().value());
+    FloatSize bottomLeftRadius = FloatSize(borderData.bottomLeft().width().value(), borderData.bottomLeft().height().value());
+    if (rects.size() == 1) {
+        FloatRect rect = rects.at(0);
+        auto radii = adjustedtRadiiForHuggingCurve(topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius, outlineOffset);
+        radii.scale(calcBorderRadiiConstraintScaleFor(rect, radii));
+
+        Path path;
+        path.addRoundedRect(FloatRoundedRect(rect, radii));
+        return path;
+    }
+
+    FloatPointGraph graph;
+    const auto polys = polygonsForRect(rects, graph);
+    // Fall back to corner painting with no radius for empty and disjoint rectangles.
+    if (!polys.size() || polys.size() &gt; 1)
+        return Path();
+    Path path;
+    // Multiline outline needs to match multiline border painting. Only first and last lines are getting rounded borders.
+    auto isLeftToRight = isLeftToRightDirection(direction);
+    auto firstLineRect = isLeftToRight ? rects.at(0) : rects.at(rects.size() - 1);
+    auto lastLineRect = isLeftToRight ? rects.at(rects.size() - 1) : rects.at(0);
+    // Adjust radius so that it matches the box border.
+    auto firstLineRadii = FloatRoundedRect::Radii(topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius);
+    auto lastLineRadii = FloatRoundedRect::Radii(topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius);
+    firstLineRadii.scale(calcBorderRadiiConstraintScaleFor(firstLineRect, firstLineRadii));
+    lastLineRadii.scale(calcBorderRadiiConstraintScaleFor(lastLineRect, lastLineRadii));
+    topLeftRadius = firstLineRadii.topLeft();
+    bottomLeftRadius = firstLineRadii.bottomLeft();
+    topRightRadius = lastLineRadii.topRight();
+    bottomRightRadius = lastLineRadii.bottomRight();
+    Vector&lt;FloatPoint&gt; corners;
+    // physical topLeft/topRight/bottomRight/bottomLeft
+    auto isHorizontal = isHorizontalWritingMode(writingMode);
+    corners.append(firstLineRect.minXMinYCorner());
+    corners.append(isHorizontal ? lastLineRect.maxXMinYCorner() : firstLineRect.maxXMinYCorner());
+    corners.append(lastLineRect.maxXMaxYCorner());
+    corners.append(isHorizontal ? firstLineRect.minXMaxYCorner() : lastLineRect.minXMaxYCorner());
+
+    const auto&amp; poly = polys.at(0);
+    for (unsigned i = 0; i &lt; poly.size(); i++) {
+        auto moveOrAddLineTo = [i, &amp;path] (const FloatPoint&amp; startPoint)
+        {
+            if (!i)
+                path.moveTo(startPoint);
+            else
+                path.addLineTo(startPoint);
+        };
+        const auto&amp; toEdge = poly[i];
+        const auto&amp; fromEdge = (i &gt; 0) ? poly[i - 1] : poly[poly.size() - 1];
+        FloatSize radius;
+        auto corner = cornerType(fromEdge, toEdge, corners);
+        switch (corner) {
+        case CornerType::TopLeft: {
+            radius = topLeftRadius;
+            break;
+        }
+        case CornerType::TopRight: {
+            radius = topRightRadius;
+            break;
+        }
+        case CornerType::BottomRight: {
+            radius = bottomRightRadius;
+            break;
+        }
+        case CornerType::BottomLeft: {
+            radius = bottomLeftRadius;
+            break;
+        }
+        case CornerType::Other: {
+            // Do not apply border radius on corners that normal border painting skips. (multiline content)
+            moveOrAddLineTo(*fromEdge.second);
+            continue;
+        }
+        }
+        FloatPoint startPoint;
+        FloatPoint endPoint;
+        std::tie(startPoint, endPoint) = startAndEndPointsForCorner(fromEdge, toEdge, radius);
+        moveOrAddLineTo(startPoint);
+
+        FloatPoint cp1;
+        FloatPoint cp2;
+        std::tie(cp1, cp2) = controlPointsForBezierCurve(corner, fromEdge, toEdge, radius);
+        path.addBezierCurveTo(cp1, cp2, endPoint);
+    }
+    path.closeSubpath();
+    return path;
+}
+
+
+}
</ins></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsPathUtilitiesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/PathUtilities.h (198061 => 198062)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/PathUtilities.h        2016-03-12 10:51:02 UTC (rev 198061)
+++ trunk/Source/WebCore/platform/graphics/PathUtilities.h        2016-03-12 17:24:21 UTC (rev 198062)
</span><span class="lines">@@ -27,14 +27,18 @@
</span><span class="cx"> #define PathUtilities_h
</span><span class="cx"> 
</span><span class="cx"> #include &quot;Path.h&quot;
</span><ins>+#include &quot;WritingMode.h&quot;
</ins><span class="cx"> #include &lt;wtf/Vector.h&gt;
</span><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><del>-
</del><ins>+class BorderData;
+    
</ins><span class="cx"> class PathUtilities {
</span><span class="cx"> public:
</span><span class="cx">     WEBCORE_EXPORT static Path pathWithShrinkWrappedRects(const Vector&lt;FloatRect&gt;&amp; rects, float radius);
</span><span class="cx">     WEBCORE_EXPORT static Vector&lt;Path&gt; pathsWithShrinkWrappedRects(const Vector&lt;FloatRect&gt;&amp; rects, float radius);
</span><ins>+
+    static Path pathWithShrinkWrappedRectsForOutline(const Vector&lt;FloatRect&gt;&amp;, const BorderData&amp;, float outlineOffset, TextDirection, WritingMode);
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsmacGraphicsContextMacmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/mac/GraphicsContextMac.mm (198061 => 198062)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/mac/GraphicsContextMac.mm        2016-03-12 10:51:02 UTC (rev 198061)
+++ trunk/Source/WebCore/platform/graphics/mac/GraphicsContextMac.mm        2016-03-12 17:24:21 UTC (rev 198062)
</span><span class="lines">@@ -85,14 +85,22 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> #if PLATFORM(MAC)
</span><del>-void GraphicsContext::drawFocusRing(const Vector&lt;FloatRect&gt;&amp; rects, float offset, double timeOffset, bool&amp; needsRedraw)
</del><ins>+void GraphicsContext::drawFocusRing(const Path&amp; path, double timeOffset, bool&amp; needsRedraw)
</ins><span class="cx"> {
</span><ins>+    if (paintingDisabled() || path.isNull())
+        return;
+    
+    needsRedraw = drawFocusRingToContextAtTime(platformContext(), path.platformPath(), timeOffset);
+}
+
+void GraphicsContext::drawFocusRing(const Vector&lt;FloatRect&gt;&amp; rects, double timeOffset, bool&amp; needsRedraw)
+{
</ins><span class="cx">     if (paintingDisabled())
</span><span class="cx">         return;
</span><span class="cx"> 
</span><span class="cx">     RetainPtr&lt;CGMutablePathRef&gt; focusRingPath = adoptCF(CGPathCreateMutable());
</span><del>-    for (auto&amp; rect : rects)
-        CGPathAddRect(focusRingPath.get(), 0, CGRectInset(rect, -offset, -offset));
</del><ins>+    for (const auto&amp; rect : rects)
+        CGPathAddRect(focusRingPath.get(), 0, CGRect(rect));
</ins><span class="cx"> 
</span><span class="cx">     needsRedraw = drawFocusRingToContextAtTime(platformContext(), focusRingPath.get(), timeOffset);
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebCorerenderingRenderElementcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/rendering/RenderElement.cpp (198061 => 198062)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/RenderElement.cpp        2016-03-12 10:51:02 UTC (rev 198061)
+++ trunk/Source/WebCore/rendering/RenderElement.cpp        2016-03-12 17:24:21 UTC (rev 198062)
</span><span class="lines">@@ -38,6 +38,7 @@
</span><span class="cx"> #include &quot;HTMLHtmlElement.h&quot;
</span><span class="cx"> #include &quot;HTMLNames.h&quot;
</span><span class="cx"> #include &quot;FlowThreadController.h&quot;
</span><ins>+#include &quot;PathUtilities.h&quot;
</ins><span class="cx"> #include &quot;RenderBlock.h&quot;
</span><span class="cx"> #include &quot;RenderCounter.h&quot;
</span><span class="cx"> #include &quot;RenderDeprecatedFlexibleBox.h&quot;
</span><span class="lines">@@ -2087,13 +2088,24 @@
</span><span class="cx"> 
</span><span class="cx">     Vector&lt;LayoutRect&gt; focusRingRects;
</span><span class="cx">     addFocusRingRects(focusRingRects, paintOffset, paintInfo.paintContainer);
</span><ins>+    float outlineOffset = style.outlineOffset();
</ins><span class="cx">     Vector&lt;FloatRect&gt; pixelSnappedFocusRingRects;
</span><span class="cx">     float deviceScaleFactor = document().deviceScaleFactor();
</span><del>-    for (const auto&amp; rect : focusRingRects)
</del><ins>+    for (auto rect : focusRingRects) {
+        rect.inflate(outlineOffset);
</ins><span class="cx">         pixelSnappedFocusRingRects.append(snapRectToDevicePixels(rect, deviceScaleFactor));
</span><ins>+    }
</ins><span class="cx"> #if PLATFORM(MAC)
</span><span class="cx">     bool needsRepaint;
</span><del>-    paintInfo.context().drawFocusRing(pixelSnappedFocusRingRects, style.outlineOffset(), document().page()-&gt;focusController().timeSinceFocusWasSet(), needsRepaint);
</del><ins>+    if (style.hasBorderRadius()) {
+        Path path = PathUtilities::pathWithShrinkWrappedRectsForOutline(pixelSnappedFocusRingRects, style.border(), outlineOffset, style.direction(), style.writingMode());
+        if (path.isEmpty()) {
+            for (auto rect : pixelSnappedFocusRingRects)
+                path.addRect(rect);
+        }
+        paintInfo.context().drawFocusRing(path, document().page()-&gt;focusController().timeSinceFocusWasSet(), needsRepaint);
+    } else
+        paintInfo.context().drawFocusRing(pixelSnappedFocusRingRects, document().page()-&gt;focusController().timeSinceFocusWasSet(), needsRepaint);
</ins><span class="cx">     if (needsRepaint)
</span><span class="cx">         document().page()-&gt;focusController().setFocusedElementNeedsRepaint();
</span><span class="cx"> #else
</span></span></pre>
</div>
</div>

</body>
</html>