<!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 <zalan@apple.com>
+
+ [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 <rniwa@webkit.org>
</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>+<!DOCTYPE html>
+<html>
+<head>
+<title>This tests hugging outlines for multiline horizontal ltr content.</title>
+</head>
+<body></body>
+</html>
</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>+<!DOCTYPE html>
+<html>
+<head>
+<title>This tests hugging outlines for multiline horizontal ltr content.</title>
+<style>
+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;
+}
+</style>
+</head>
+<body>
+<div class=cover style="top: 3px; left: 3px; width: 56px; height: 56px; border-radius: 20px 3px 0px 3px;"></div>
+<div class=cover style="top: 23px; left: 66px; width: 53px; height: 36px; border-radius: 0px 3px 0px 0px;"></div>
+<div class=cover style="top: 43px; left: 126px; width: 133px; height: 16px; border-radius: 0px 18px 18px 0px;"></div>
+
+<div class=cover style="top: 83px; left: 3px; width: 256px; height: 16px; border-radius: 20px 3px 3px 0px;"></div>
+<div class=cover style="top: 106px; left: 3px; width: 196px; height: 13px; border-radius: 0px 0px 3px 0px;"></div>
+<div class=cover style="top: 126px; left: 3px; width: 116px; height: 13px; border-radius: 0px 0px 14px 3px;"></div>
+
+<div class=cover style="top: 163px; left: 3px; width: 116px; height: 13px; border-radius: 20px 3px 0px 0px;"></div>
+<div class=cover style="top: 183px; left: 3px; width: 256px; height: 16px; border-radius: 0px 3px 3px 0px;"></div>
+<div class=cover style="top: 206px; left: 3px; width: 116px; height: 13px; border-radius: 0px 0px 14px 3px;"></div>
+
+<div class=cover style="top: 243px; left: 3px; width: 256px; height: 15px; border-radius: 20px 3px 3px 0px;"></div>
+<div class=cover style="top: 265px; left: 3px; width: 116px; height: 13px; border-radius: 0px 0px 0px 0px;"></div>
+<div class=cover style="top: 284px; left: 3px; width: 256px; height: 14px; border-radius: 0px 18px 18px 3px;"></div>
+
+<div class=container><span>foo<br>foobar<br>foobar foobar</span></div>
+<div class=container><span>foobar foobar<br>foobar foo<br>foobar</span></div>
+<div class=container><span>foobar<br>foobar foobar<br>foobar</span></div>
+<div class=container><span>foobar foobar<br>foobar<br>foobar foobar</span></div>
+</body>
+</html>
</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>+<!DOCTYPE html>
+<html>
+<head>
+<title>This tests hugging outlines for multiline horizontal rtl content.</title>
+</head>
+<body></body>
+</html>
</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>+<!DOCTYPE html>
+<html>
+<head>
+<title>This tests hugging outlines for multiline horizontal rtl content.</title>
+<style>
+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;
+}
+</style>
+</head>
+<body>
+<div class=cover style="top: 3px; right: 3px; width: 56px; height: 56px; border-radius: 3px 16px 3px 0px;"></div>
+<div class=cover style="top: 23px; right: 66px; width: 53px; height: 36px; border-radius: 3px 0px 0px 0px;"></div>
+<div class=cover style="top: 43px; right: 126px; width: 133px; height: 16px; border-radius: 21px 0px 0px 11px;"></div>
+
+<div class=cover style="top: 83px; right: 3px; width: 256px; height: 16px; border-radius: 3px 16px 0px 3px;"></div>
+<div class=cover style="top: 106px; right: 3px; width: 196px; height: 13px; border-radius: 0px 0px 0px 3px;"></div>
+<div class=cover style="top: 126px; right: 3px; width: 116px; height: 13px; border-radius: 0px 0px 3px 12px;"></div>
+
+<div class=cover style="top: 163px; right: 3px; width: 116px; height: 13px; border-radius: 3px 16px 0px 0px;"></div>
+<div class=cover style="top: 183px; right: 3px; width: 256px; height: 16px; border-radius: 3px 0px 0px 3px;"></div>
+<div class=cover style="top: 206px; right: 3px; width: 116px; height: 13px; border-radius: 0px 0px 3px 12px;"></div>
+
+<div class=cover style="top: 243px; right: 3px; width: 256px; height: 15px; border-radius: 3px 16px 0px 3px;"></div>
+<div class=cover style="top: 265px; right: 3px; width: 116px; height: 13px; border-radius: 0px 0px 0px 0px;"></div>
+<div class=cover style="top: 284px; right: 3px; width: 256px; height: 14px; border-radius: 21px 0px 3px 11px;"></div>
+
+<div class=container><span>foo<br>foobar<br>foobar foobar</span></div>
+<div class=container><span>foobar foobar<br>foobar foo<br>foobar</span></div>
+<div class=container><span>foobar<br>foobar foobar<br>foobar</span></div>
+<div class=container><span>foobar foobar<br>foobar<br>foobar foobar</span></div>
+</body>
+</html>
</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>+<!DOCTYPE html>
+<html>
+<head>
+<title>This tests hugging outlines for multiline vertical ltr content.</title>
+</head>
+<body></body>
+</html>
</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>+<!DOCTYPE html>
+<html>
+<head>
+<title>This tests hugging outlines for multiline vertical ltr content.</title>
+<style>
+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;
+}
+</style>
+</head>
+<body>
+<div class=cover style="top: 4px; left: 24px; width: 12px; height: 54px; border-radius: 15px 0px 0px 3px;"></div>
+<div class=cover style="top: 4px; left: 43px; width: 13px; height: 114px; border-radius: 0px 0px 0px 3px;"></div>
+<div class=cover style="top: 4px; left: 63px; width: 16px; height: 255px; border-radius: 0px 3px 12px 12px;"></div>
+
+<div class=cover style="top: 4px; left: 124px; width: 15px; height: 255px; border-radius: 15px 0px 3px 3px;"></div>
+<div class=cover style="top: 4px; left: 147px; width: 12px; height: 195px; border-radius: 0px 0px 3px 0px;"></div>
+<div class=cover style="top: 4px; left: 166px; width: 13px; height: 114px; border-radius: 0px 3px 11px 0px;"></div>
+
+<div class=cover style="top: 4px; left: 223px; width: 13px; height: 114px; border-radius: 15px 0px 0px 3px;"></div>
+<div class=cover style="top: 4px; left: 243px; width: 16px; height: 255px; border-radius: 0px 0px 3px 3px;"></div>
+<div class=cover style="top: 4px; left: 266px; width: 13px; height: 114px; border-radius: 0px 3px 11px 0px;"></div>
+
+<div class=cover style="top: 4px; left: 323px; width: 16px; height: 255px; border-radius: 15px 0px 3px 3px;"></div>
+<div class=cover style="top: 4px; left: 346px; width: 10px; height: 114px; border-radius: 0px 0px 0px 0px;"></div>
+<div class=cover style="top: 4px; left: 363px; width: 16px; height: 255px; border-radius: 0px 3px 12px 12px;"></div>
+
+<div class=container><span>foo<br>foobar<br>foobar foobar</span></div>
+<div class=container><span>foobar foobar<br>foobar foo<br>foobar</span></div>
+<div class=container><span>foobar<br>foobar foobar<br>foobar</span></div>
+<div class=container><span>foobar foobar<br>foobar<br>foobar foobar</span></div>
+</body>
+</html>
</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>+<!DOCTYPE html>
+<html>
+<head>
+<title>This tests hugging outlines for multiline vertical rtl content.</title>
+</head>
+<body></body>
+</html>
</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>+<!DOCTYPE html>
+<html>
+<head>
+<title>This tests hugging outlines for multiline vertical rtl content.</title>
+<style>
+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;
+}
+</style>
+</head>
+<body>
+<div class=cover style="top: 204px; right: 46px; width: 12px; height: 55px; border-radius: 3px 0px 0px 8px"></div>
+<div class=cover style="top: 143px; right: 26px; width: 13px; height: 116px; border-radius: 3px 0px 0px 0px;"></div>
+<div class=cover style="top: 4px; right: 3px; width: 16px; height: 255px; border-radius: 16px 11px 3px 0px;"></div>
+
+<div class=cover style="top: 3px; right: 143px; width: 16px; height: 255px; border-radius: 3px 3px 0px 8px;"></div>
+<div class=cover style="top: 63px; right: 123px; width: 13px; height: 195px; border-radius: 0px 3px 0px 0px;"></div>
+<div class=cover style="top: 143px; right: 103px; width: 13px; height: 115px; border-radius: 0px 12px 3px 0px;"></div>
+
+<div class=cover style="top: 143px; right: 203px; width: 13px; height: 115px; border-radius: 0px 12px 3px 0px;"></div>
+<div class=cover style="top: 3px; right: 223px; width: 16px; height: 255px; border-radius: 3px 3px 0px 0px;"></div>
+<div class=cover style="top: 143px; right: 246px; width: 13px; height: 115px; border-radius: 3px 0px 0px 3px;"></div>
+
+<div class=cover style="top: 3px; right: 303px; width: 16px; height: 255px; border-radius: 16px 12px 3px 0px;"></div>
+<div class=cover style="top: 144px; right: 326px; width: 10px; height: 114px; border-radius: 0px 0px 0px 0px;"></div>
+<div class=cover style="top: 3px; right: 343px; width: 16px; height: 255px; border-radius: 3px 3px 0px 3px;"></div>
+
+<div class=container><span>foo<br>foobar<br>foobar foobar</span></div>
+<div class=container><span>foobar foobar<br>foobar foo<br>foobar</span></div>
+<div class=container><span>foobar<br>foobar foobar<br>foobar</span></div>
+<div class=container><span>foobar foobar<br>foobar<br>foobar foobar</span></div>
+</body>
+</html>
</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 <zalan@apple.com>
+
+ [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 <rniwa@webkit.org>
</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<FloatRect>&, float width, float offset, const Color&);
</span><span class="cx"> void drawFocusRing(const Path&, float width, float offset, const Color&);
</span><span class="cx"> #if PLATFORM(MAC)
</span><del>- void drawFocusRing(const Vector<FloatRect>&, float offset, double timeOffset, bool& needsRedraw);
</del><ins>+ void drawFocusRing(const Path&, double timeOffset, bool& needsRedraw);
+ void drawFocusRing(const Vector<FloatRect>&, double timeOffset, bool& 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& rect, const FloatSize& topLeftRadius, const FloatSize& topRightRadius, const FloatSize& bottomLeftRadius, const FloatSize& 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() > 0 || topRightRadius.height() > 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() > 0 || bottomRightRadius.height() > 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() > 0 || bottomLeftRadius.height() > 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() > 0 || topLeftRadius.height() > 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&) const;
</span><span class="cx"> void transform(const AffineTransform&);
</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&, const FloatSize& topLeftRadius, const FloatSize& topRightRadius, const FloatSize& bottomLeftRadius, const FloatSize& 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 "PathUtilities.h"
</span><span class="cx">
</span><span class="cx"> #include "AffineTransform.h"
</span><ins>+#include "BorderData.h"
</ins><span class="cx"> #include "FloatPoint.h"
</span><span class="cx"> #include "FloatRect.h"
</span><ins>+#include "FloatRoundedRect.h"
</ins><span class="cx"> #include "GeometryUtilities.h"
</span><span class="cx"> #include <math.h>
</span><span class="cx"> #include <wtf/MathExtras.h>
</span><span class="lines">@@ -255,25 +257,11 @@
</span><span class="cx"> });
</span><span class="cx"> }
</span><span class="cx">
</span><del>-Vector<Path> PathUtilities::pathsWithShrinkWrappedRects(const Vector<FloatRect>& rects, float radius)
</del><ins>+static Vector<FloatPointGraph::Polygon> polygonsForRect(const Vector<FloatRect>& rects, FloatPointGraph& graph)
</ins><span class="cx"> {
</span><del>- Vector<Path> paths;
-
- if (rects.isEmpty())
- return paths;
-
- if (rects.size() > 20) {
- Path path;
- path.addRoundedRect(unionRect(rects), FloatSize(radius, radius));
- paths.append(path);
- return paths;
- }
-
</del><span class="cx"> Vector<FloatRect> sortedRects = rects;
</span><del>-
</del><span class="cx"> std::sort(sortedRects.begin(), sortedRects.end(), [](FloatRect a, FloatRect b) { return b.y() > a.y(); });
</span><span class="cx">
</span><del>- FloatPointGraph graph;
</del><span class="cx"> Vector<FloatPointGraph::Polygon> 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<FloatPointGraph::Polygon> polys = unitePolygons(rectPolygons, graph);
</del><ins>+Vector<Path> PathUtilities::pathsWithShrinkWrappedRects(const Vector<FloatRect>& rects, float radius)
+{
+ Vector<Path> paths;
</ins><span class="cx">
</span><ins>+ if (rects.isEmpty())
+ return paths;
+
+ if (rects.size() > 20) {
+ Path path;
+ path.addRoundedRect(unionRect(rects), FloatSize(radius, radius));
+ paths.append(path);
+ return paths;
+ }
+
+ FloatPointGraph graph;
+ Vector<FloatPointGraph::Polygon> 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<FloatPoint, FloatPoint> startAndEndPointsForCorner(const FloatPointGraph::Edge& fromEdge, const FloatPointGraph::Edge& toEdge, const FloatSize& 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& fromEdge, const FloatPointGraph::Edge& toEdge, const Vector<FloatPoint>& corners)
+{
+ auto fromEdgeVector = *fromEdge.second - *fromEdge.first;
+ auto toEdgeVector = *toEdge.second - *toEdge.first;
+
+ if (fromEdgeVector.height() < 0 && toEdgeVector.width() > 0 && corners.at(0) == *fromEdge.second)
+ return CornerType::TopLeft;
+ if (fromEdgeVector.width() > 0 && toEdgeVector.height() > 0 && corners.at(1) == *fromEdge.second)
+ return CornerType::TopRight;
+ if (fromEdgeVector.height() > 0 && toEdgeVector.width() < 0 && corners.at(2) == *fromEdge.second)
+ return CornerType::BottomRight;
+ if (fromEdgeVector.width() < 0 && toEdgeVector.height() < 0 && corners.at(3) == *fromEdge.second)
+ return CornerType::BottomLeft;
+ return CornerType::Other;
+}
+
+static std::pair<FloatPoint, FloatPoint> controlPointsForBezierCurve(CornerType cornerType, const FloatPointGraph::Edge& fromEdge,
+ const FloatPointGraph::Edge& toEdge, const FloatSize& radius)
+{
+ FloatPoint cp1;
+ FloatPoint cp2;
+ switch (cornerType) {
+ case CornerType::TopLeft: {
+ cp1 = FloatPoint(fromEdge.second->x(), fromEdge.second->y() + radius.height() * Path::circleControlPoint());
+ cp2 = FloatPoint(toEdge.first->x() + radius.width() * Path::circleControlPoint(), toEdge.first->y());
+ break;
+ }
+ case CornerType::TopRight: {
+ cp1 = FloatPoint(fromEdge.second->x() - radius.width() * Path::circleControlPoint(), fromEdge.second->y());
+ cp2 = FloatPoint(toEdge.first->x(), toEdge.first->y() + radius.height() * Path::circleControlPoint());
+ break;
+ }
+ case CornerType::BottomRight: {
+ cp1 = FloatPoint(fromEdge.second->x(), fromEdge.second->y() - radius.height() * Path::circleControlPoint());
+ cp2 = FloatPoint(toEdge.first->x() - radius.width() * Path::circleControlPoint(), toEdge.first->y());
+ break;
+ }
+ case CornerType::BottomLeft: {
+ cp1 = FloatPoint(fromEdge.second->x() + radius.width() * Path::circleControlPoint(), fromEdge.second->y());
+ cp2 = FloatPoint(toEdge.first->x(), toEdge.first->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& topLeftRadius, const FloatSize& topRightRadius,
+ const FloatSize& bottomLeftRadius, const FloatSize& 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& radius)
+ {
+ FloatSize adjustedRadius = radius;
+ if (radius.width() > outlineOffset)
+ adjustedRadius.expand(std::min(outlineOffset, radius.width() - outlineOffset), 0);
+ if (radius.height() > 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<FloatRect>& rects, const BorderData& 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() > 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<FloatPoint> 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& poly = polys.at(0);
+ for (unsigned i = 0; i < poly.size(); i++) {
+ auto moveOrAddLineTo = [i, &path] (const FloatPoint& startPoint)
+ {
+ if (!i)
+ path.moveTo(startPoint);
+ else
+ path.addLineTo(startPoint);
+ };
+ const auto& toEdge = poly[i];
+ const auto& fromEdge = (i > 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 "Path.h"
</span><ins>+#include "WritingMode.h"
</ins><span class="cx"> #include <wtf/Vector.h>
</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<FloatRect>& rects, float radius);
</span><span class="cx"> WEBCORE_EXPORT static Vector<Path> pathsWithShrinkWrappedRects(const Vector<FloatRect>& rects, float radius);
</span><ins>+
+ static Path pathWithShrinkWrappedRectsForOutline(const Vector<FloatRect>&, const BorderData&, 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<FloatRect>& rects, float offset, double timeOffset, bool& needsRedraw)
</del><ins>+void GraphicsContext::drawFocusRing(const Path& path, double timeOffset, bool& needsRedraw)
</ins><span class="cx"> {
</span><ins>+ if (paintingDisabled() || path.isNull())
+ return;
+
+ needsRedraw = drawFocusRingToContextAtTime(platformContext(), path.platformPath(), timeOffset);
+}
+
+void GraphicsContext::drawFocusRing(const Vector<FloatRect>& rects, double timeOffset, bool& needsRedraw)
+{
</ins><span class="cx"> if (paintingDisabled())
</span><span class="cx"> return;
</span><span class="cx">
</span><span class="cx"> RetainPtr<CGMutablePathRef> focusRingPath = adoptCF(CGPathCreateMutable());
</span><del>- for (auto& rect : rects)
- CGPathAddRect(focusRingPath.get(), 0, CGRectInset(rect, -offset, -offset));
</del><ins>+ for (const auto& 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 "HTMLHtmlElement.h"
</span><span class="cx"> #include "HTMLNames.h"
</span><span class="cx"> #include "FlowThreadController.h"
</span><ins>+#include "PathUtilities.h"
</ins><span class="cx"> #include "RenderBlock.h"
</span><span class="cx"> #include "RenderCounter.h"
</span><span class="cx"> #include "RenderDeprecatedFlexibleBox.h"
</span><span class="lines">@@ -2087,13 +2088,24 @@
</span><span class="cx">
</span><span class="cx"> Vector<LayoutRect> focusRingRects;
</span><span class="cx"> addFocusRingRects(focusRingRects, paintOffset, paintInfo.paintContainer);
</span><ins>+ float outlineOffset = style.outlineOffset();
</ins><span class="cx"> Vector<FloatRect> pixelSnappedFocusRingRects;
</span><span class="cx"> float deviceScaleFactor = document().deviceScaleFactor();
</span><del>- for (const auto& 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()->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()->focusController().timeSinceFocusWasSet(), needsRepaint);
+ } else
+ paintInfo.context().drawFocusRing(pixelSnappedFocusRingRects, document().page()->focusController().timeSinceFocusWasSet(), needsRepaint);
</ins><span class="cx"> if (needsRepaint)
</span><span class="cx"> document().page()->focusController().setFocusedElementNeedsRepaint();
</span><span class="cx"> #else
</span></span></pre>
</div>
</div>
</body>
</html>