<!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>[186858] 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/186858">186858</a></dd>
<dt>Author</dt> <dd>timothy_horton@apple.com</dd>
<dt>Date</dt> <dd>2015-07-15 14:19:29 -0700 (Wed, 15 Jul 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>Factor rect shrink-wrapping code out of RenderThemeMac for future reuse
https://bugs.webkit.org/show_bug.cgi?id=146973
&lt;rdar://problem/21643094&gt;

Reviewed by Anders Carlsson.

Test: fast/shrink-wrap/rect-shrink-wrap.html

* WebCore.xcodeproj/project.pbxproj:
Add DOMPath.cpp and PathUtilities.{h, cpp}.

* bindings/js/JSDOMBinding.h:
(WebCore::NativeValueTraits&lt;double&gt;::nativeValue):
Make it possible to use sequence&lt;double&gt; in IDL files.

* bindings/scripts/CodeGeneratorJS.pm:
Export JSDOMPath for use in Internals.

* html/canvas/DOMPath.cpp: Added.
(WebCore::DOMPath::~DOMPath):
* html/canvas/DOMPath.h:
Out-of-line the DOMPath destructor so as not to anger the bindings
integrity checker (otherwise, the address of the DOMPath destructor
is different in WebCoreTestSupport and WebCore, causing us to fail
the vtable equality test).

* platform/graphics/Path.h:
Forward declare FloatRect instead of including it unnecessarily.
Export ensurePlatformPath().

* platform/graphics/PathUtilities.cpp: Added.
(WebCore::addShrinkWrapRightCorner):
(WebCore::addShrinkWrapLeftCorner):
(WebCore::addShrinkWrappedPathForRects):
These parts are extracted from RenderThemeMac, with two changes:
    + support for arbitrarily-aligned rects
      (the other version assumed they were horizontally center-aligned)
    + support for overlapping rects
      (the other version assumed they touched but did not overlap)

There are still things missing:
    + support for a fallback when the shape is too hard to shrink-wrap

And things broken:
    + if the distance between two edges is smaller than the corner radius,
      we'll end up with a sharp edge in the path

Both of these cases are covered in the layout test and can be improved.

(WebCore::rectsIntersectOrTouch):
Rect intersection with &lt;= instead of &lt;.

(WebCore::contiguousRectGroupsFromRects):
Given a set of rects, find all of the contiguous regions. We'll
shrink-wrap each region independently.

(WebCore::PathUtilities::pathWithShrinkWrappedRects):
* platform/graphics/PathUtilities.h: Added.
Add PathUtilities, where the shrink-wrapping code lives.

* rendering/RenderThemeMac.mm:
(WebCore::paintAttachmentTitleBackground):
(WebCore::addAttachmentTitleBackgroundRightCorner): Deleted.
(WebCore::addAttachmentTitleBackgroundLeftCorner): Deleted.
Remove shrink-wrapping implementation and make use of the one in PathUtilities.

* testing/Internals.cpp:
(WebCore::Internals::pathWithShrinkWrappedRects):
* testing/Internals.h:
* testing/Internals.idl:
Expose pathWithShrinkWrappedRects to tests via Internals.
It takes a sequence&lt;double&gt; where every four values are the x, y, w, h
of a rect, and returns a DOMPath which can be used with Canvas.

* fast/shrink-wrap/rect-shrink-wrap-expected.png: Added.
* fast/shrink-wrap/rect-shrink-wrap-expected.txt: Added.
* fast/shrink-wrap/rect-shrink-wrap.html: Added.
Add a test of both working and broken (indicated by comments in the test)
shrink-wrapping cases.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreCMakeListstxt">trunk/Source/WebCore/CMakeLists.txt</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreWebCorexcodeprojprojectpbxproj">trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkSourceWebCorebindingsjsJSDOMBindingh">trunk/Source/WebCore/bindings/js/JSDOMBinding.h</a></li>
<li><a href="#trunkSourceWebCorebindingsscriptsCodeGeneratorJSpm">trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm</a></li>
<li><a href="#trunkSourceWebCorehtmlcanvasDOMPathh">trunk/Source/WebCore/html/canvas/DOMPath.h</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsPathh">trunk/Source/WebCore/platform/graphics/Path.h</a></li>
<li><a href="#trunkSourceWebCorerenderingRenderThemeMacmm">trunk/Source/WebCore/rendering/RenderThemeMac.mm</a></li>
<li><a href="#trunkSourceWebCoretestingInternalscpp">trunk/Source/WebCore/testing/Internals.cpp</a></li>
<li><a href="#trunkSourceWebCoretestingInternalsh">trunk/Source/WebCore/testing/Internals.h</a></li>
<li><a href="#trunkSourceWebCoretestingInternalsidl">trunk/Source/WebCore/testing/Internals.idl</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li>trunk/LayoutTests/fast/shrink-wrap/</li>
<li><a href="#trunkLayoutTestsfastshrinkwraprectshrinkwrapexpectedpng">trunk/LayoutTests/fast/shrink-wrap/rect-shrink-wrap-expected.png</a></li>
<li><a href="#trunkLayoutTestsfastshrinkwraprectshrinkwrapexpectedtxt">trunk/LayoutTests/fast/shrink-wrap/rect-shrink-wrap-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfastshrinkwraprectshrinkwraphtml">trunk/LayoutTests/fast/shrink-wrap/rect-shrink-wrap.html</a></li>
<li><a href="#trunkSourceWebCorehtmlcanvasDOMPathcpp">trunk/Source/WebCore/html/canvas/DOMPath.cpp</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>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (186857 => 186858)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2015-07-15 21:07:01 UTC (rev 186857)
+++ trunk/LayoutTests/ChangeLog        2015-07-15 21:19:29 UTC (rev 186858)
</span><span class="lines">@@ -1,3 +1,17 @@
</span><ins>+2015-07-15  Tim Horton  &lt;timothy_horton@apple.com&gt;
+
+        Factor rect shrink-wrapping code out of RenderThemeMac for future reuse
+        https://bugs.webkit.org/show_bug.cgi?id=146973
+        &lt;rdar://problem/21643094&gt;
+
+        Reviewed by Anders Carlsson.
+
+        * fast/shrink-wrap/rect-shrink-wrap-expected.png: Added.
+        * fast/shrink-wrap/rect-shrink-wrap-expected.txt: Added.
+        * fast/shrink-wrap/rect-shrink-wrap.html: Added.
+        Add a test of both working and broken (indicated by comments in the test)
+        shrink-wrapping cases.
+
</ins><span class="cx"> 2015-07-15  Wenson Hsieh  &lt;wenson_hsieh@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Negative scroll snap repeat values cause web process to hang indefinitely
</span></span></pre></div>
<a id="trunkLayoutTestsfastshrinkwraprectshrinkwrapexpectedpng"></a>
<div class="binary"><h4>Added: trunk/LayoutTests/fast/shrink-wrap/rect-shrink-wrap-expected.png</h4>
<pre class="diff"><span>
<span class="cx">(Binary files differ)
</span></span></pre></div>
<span class="cx">Property changes on: trunk/LayoutTests/fast/shrink-wrap/rect-shrink-wrap-expected.png
</span><span class="cx">___________________________________________________________________
</span><a id="svnmimetype"></a>
<div class="addfile"><h4>Added: svn:mime-type</h4></div>
<a id="trunkLayoutTestsfastshrinkwraprectshrinkwrapexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/shrink-wrap/rect-shrink-wrap-expected.txt (0 => 186858)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/shrink-wrap/rect-shrink-wrap-expected.txt                                (rev 0)
+++ trunk/LayoutTests/fast/shrink-wrap/rect-shrink-wrap-expected.txt        2015-07-15 21:19:29 UTC (rev 186858)
</span><span class="lines">@@ -0,0 +1,8 @@
</span><ins>+layer at (0,0) size 800x600
+  RenderView at (0,0) size 800x600
+layer at (0,0) size 800x600
+  RenderBlock {HTML} at (0,0) size 800x600
+    RenderBody {BODY} at (0,0) size 800x600
+      RenderText {#text} at (0,0) size 0x0
+layer at (0,0) size 800x600
+  RenderHTMLCanvas {CANVAS} at (0,0) size 800x600
</ins></span></pre></div>
<a id="trunkLayoutTestsfastshrinkwraprectshrinkwraphtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/shrink-wrap/rect-shrink-wrap.html (0 => 186858)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/shrink-wrap/rect-shrink-wrap.html                                (rev 0)
+++ trunk/LayoutTests/fast/shrink-wrap/rect-shrink-wrap.html        2015-07-15 21:19:29 UTC (rev 186858)
</span><span class="lines">@@ -0,0 +1,154 @@
</span><ins>+&lt;script&gt;
+
+function testRects(rects) {
+    if (!window.internals)
+        document.write(&quot;This test must be run in a test runner.&quot;)
+
+    var concatRects = [];
+    for (var i in rects)
+        Array.prototype.push.apply(concatRects, rects[i]);
+
+    var path = undefined;
+    if (window.internals)
+        path = window.internals.pathWithShrinkWrappedRects(concatRects);
+
+    var canvas = document.getElementById(&quot;shrink&quot;);
+    var ctx = canvas.getContext(&quot;2d&quot;);
+
+    ctx.fillStyle = &quot;rgba(0,0,0,0.2)&quot;;
+
+    for (var i in rects)
+        ctx.fillRect.apply(ctx, rects[i]);
+
+    ctx.strokeStyle = &quot;rgba(0,0,0,0.5)&quot;;
+    ctx.lineWidth = 1;
+    for (var i in rects)
+        ctx.strokeRect.apply(ctx, rects[i]);
+
+    ctx.strokeStyle = &quot;blue&quot;;
+    ctx.lineWidth = 3;
+    if (path)
+        ctx.stroke(path);
+}
+
+window.onload = function () {
+    // Right and left aligned, touching:
+
+    testRects([
+        [20, 20, 50, 20],
+        [20, 40, 35, 20],
+        [20, 60, 20, 20]]);
+
+    testRects([
+        [20, 90, 20, 20],
+        [20, 110, 35, 20],
+        [20, 130, 50, 20]]);
+
+    testRects([
+        [80, 20, 50, 20],
+        [95, 40, 35, 20],
+        [110, 60, 20, 20]]);
+
+    testRects([
+        [110, 90, 20, 20],
+        [95, 110, 35, 20],
+        [80, 130, 50, 20]]);
+
+    // Center aligned, touching:
+
+    testRects([
+        [170, 20, 100, 40],
+        [190, 60, 60, 40],
+        [205, 100, 30, 40]]);
+
+    testRects([
+        [305, 20, 30, 40],
+        [290, 60, 60, 40],
+        [270, 100, 100, 40]]);
+
+    testRects([
+        [370, 20, 100, 40],
+        [405, 60, 30, 40],
+        [390, 100, 60, 40]]);
+
+    // Other:
+
+    testRects([
+        [20, 200, 40, 40],
+        [40, 220, 40, 40],
+        [60, 240, 40, 40]]);
+
+    testRects([
+        [120, 200, 40, 40],
+        [120, 240, 40, 40],
+        [120, 280, 40, 40]]);
+
+    // Non-touching:
+
+    testRects([
+        [180, 200, 40, 60],
+        [180, 280, 40, 40]]);
+
+    // Combination of touching and non-touching:
+
+    testRects([
+        [280, 200, 30, 40],
+        [280, 280, 50, 40],
+        [340, 200, 40, 40],
+        [360, 240, 80, 40],
+        [380, 280, 40, 40],
+        [430, 200, 40, 20],
+        [450, 215, 40, 20],
+        [470, 230, 40, 20]]);
+
+    // Incorrectly sorted:
+
+    testRects([
+        [20, 380, 40, 40],
+        [40, 360, 40, 40],
+        [60, 340, 40, 40]]);
+
+    // Broken:
+
+    testRects([
+        [600+100, 90, 20, 20],
+        [600+95, 110, 35, 20],
+        [600+80, 130, 50, 20]]);
+
+    testRects([
+        [230+340, 20, 40, 40],
+        [230+360, 60, 65, 40],
+        [230+380, 100, 40, 40]]);
+
+    // These should fallback to a rounded bounding rect:
+
+    testRects([
+        [600+100, 190, 20, 20],
+        [600+95, 210, 35, 20],
+        [600+80, 210, 50, 20]]);
+
+    testRects([
+        [600+0, 250, 40, 40],
+        [600+40, 250, 40, 40],
+        [600+80, 250, 40, 40]]);
+
+    testRects([
+        [600, 300, 20, 40],
+        [600+20, 320, 20, 40],
+        [600, 340, 20, 40]]);
+
+    testRects([
+        [700, 300, 20, 40],
+        [700+20, 320, 20, 40],
+        [700+40, 300, 20, 40]]);
+}
+
+&lt;/script&gt;
+
+&lt;style&gt;
+body {
+    margin: 0;
+}
+&lt;/style&gt;
+
+&lt;canvas id=&quot;shrink&quot; width=&quot;800&quot; height=&quot;600&quot;&gt;&lt;/canvas&gt;
</ins></span></pre></div>
<a id="trunkSourceWebCoreCMakeListstxt"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/CMakeLists.txt (186857 => 186858)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/CMakeLists.txt        2015-07-15 21:07:01 UTC (rev 186857)
+++ trunk/Source/WebCore/CMakeLists.txt        2015-07-15 21:19:29 UTC (rev 186858)
</span><span class="lines">@@ -1742,6 +1742,7 @@
</span><span class="cx">     html/canvas/CanvasRenderingContext.cpp
</span><span class="cx">     html/canvas/CanvasRenderingContext2D.cpp
</span><span class="cx">     html/canvas/CanvasStyle.cpp
</span><ins>+    html/canvas/DOMPath.cpp
</ins><span class="cx">     html/canvas/EXTBlendMinMax.cpp
</span><span class="cx">     html/canvas/EXTFragDepth.cpp
</span><span class="cx">     html/canvas/EXTShaderTextureLOD.cpp
</span><span class="lines">@@ -2171,6 +2172,7 @@
</span><span class="cx">     platform/graphics/NamedImageGeneratedImage.cpp
</span><span class="cx">     platform/graphics/Path.cpp
</span><span class="cx">     platform/graphics/PathTraversalState.cpp
</span><ins>+    platform/graphics/PathUtilities.cpp
</ins><span class="cx">     platform/graphics/Pattern.cpp
</span><span class="cx">     platform/graphics/PlatformTimeRanges.cpp
</span><span class="cx">     platform/graphics/Region.cpp
</span></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (186857 => 186858)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2015-07-15 21:07:01 UTC (rev 186857)
+++ trunk/Source/WebCore/ChangeLog        2015-07-15 21:19:29 UTC (rev 186858)
</span><span class="lines">@@ -1,3 +1,79 @@
</span><ins>+2015-07-15  Tim Horton  &lt;timothy_horton@apple.com&gt;
+
+        Factor rect shrink-wrapping code out of RenderThemeMac for future reuse
+        https://bugs.webkit.org/show_bug.cgi?id=146973
+        &lt;rdar://problem/21643094&gt;
+
+        Reviewed by Anders Carlsson.
+
+        Test: fast/shrink-wrap/rect-shrink-wrap.html
+
+        * WebCore.xcodeproj/project.pbxproj:
+        Add DOMPath.cpp and PathUtilities.{h, cpp}.
+
+        * bindings/js/JSDOMBinding.h:
+        (WebCore::NativeValueTraits&lt;double&gt;::nativeValue):
+        Make it possible to use sequence&lt;double&gt; in IDL files.
+
+        * bindings/scripts/CodeGeneratorJS.pm:
+        Export JSDOMPath for use in Internals.
+
+        * html/canvas/DOMPath.cpp: Added.
+        (WebCore::DOMPath::~DOMPath):
+        * html/canvas/DOMPath.h:
+        Out-of-line the DOMPath destructor so as not to anger the bindings
+        integrity checker (otherwise, the address of the DOMPath destructor
+        is different in WebCoreTestSupport and WebCore, causing us to fail
+        the vtable equality test).
+
+        * platform/graphics/Path.h:
+        Forward declare FloatRect instead of including it unnecessarily.
+        Export ensurePlatformPath().
+
+        * platform/graphics/PathUtilities.cpp: Added.
+        (WebCore::addShrinkWrapRightCorner):
+        (WebCore::addShrinkWrapLeftCorner):
+        (WebCore::addShrinkWrappedPathForRects):
+        These parts are extracted from RenderThemeMac, with two changes:
+            + support for arbitrarily-aligned rects
+              (the other version assumed they were horizontally center-aligned)
+            + support for overlapping rects
+              (the other version assumed they touched but did not overlap)
+
+        There are still things missing:
+            + support for a fallback when the shape is too hard to shrink-wrap
+
+        And things broken:
+            + if the distance between two edges is smaller than the corner radius,
+              we'll end up with a sharp edge in the path
+
+        Both of these cases are covered in the layout test and can be improved.
+
+        (WebCore::rectsIntersectOrTouch):
+        Rect intersection with &lt;= instead of &lt;.
+
+        (WebCore::contiguousRectGroupsFromRects):
+        Given a set of rects, find all of the contiguous regions. We'll
+        shrink-wrap each region independently.
+
+        (WebCore::PathUtilities::pathWithShrinkWrappedRects):
+        * platform/graphics/PathUtilities.h: Added.
+        Add PathUtilities, where the shrink-wrapping code lives.
+
+        * rendering/RenderThemeMac.mm:
+        (WebCore::paintAttachmentTitleBackground):
+        (WebCore::addAttachmentTitleBackgroundRightCorner): Deleted.
+        (WebCore::addAttachmentTitleBackgroundLeftCorner): Deleted.
+        Remove shrink-wrapping implementation and make use of the one in PathUtilities.
+
+        * testing/Internals.cpp:
+        (WebCore::Internals::pathWithShrinkWrappedRects):
+        * testing/Internals.h:
+        * testing/Internals.idl:
+        Expose pathWithShrinkWrappedRects to tests via Internals.
+        It takes a sequence&lt;double&gt; where every four values are the x, y, w, h
+        of a rect, and returns a DOMPath which can be used with Canvas.
+
</ins><span class="cx"> 2015-07-15  Enrica Casucci  &lt;enrica@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [iOS] Should look for RTF and RTFD pasteboard types before plain text.
</span></span></pre></div>
<a id="trunkSourceWebCoreWebCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (186857 => 186858)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj        2015-07-15 21:07:01 UTC (rev 186857)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj        2015-07-15 21:19:29 UTC (rev 186858)
</span><span class="lines">@@ -1124,6 +1124,9 @@
</span><span class="cx">                 2D4F96F61A1ECC240098BF88 /* TextIndicator.h in Headers */ = {isa = PBXBuildFile; fileRef = 2D4F96F21A1ECC240098BF88 /* TextIndicator.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 2D4F96F71A1ECC240098BF88 /* TextIndicatorWindow.h in Headers */ = {isa = PBXBuildFile; fileRef = 2D4F96F31A1ECC240098BF88 /* TextIndicatorWindow.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 2D4F96F81A1ECC240098BF88 /* TextIndicatorWindow.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2D4F96F41A1ECC240098BF88 /* TextIndicatorWindow.mm */; };
</span><ins>+                2D5002F81B56D7810020AAF7 /* DOMPath.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2D5002F71B56D7810020AAF7 /* DOMPath.cpp */; };
+                2D5002FB1B56D7990020AAF7 /* PathUtilities.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2D5002F91B56D7990020AAF7 /* PathUtilities.cpp */; };
+                2D5002FC1B56D7990020AAF7 /* PathUtilities.h in Headers */ = {isa = PBXBuildFile; fileRef = 2D5002FA1B56D7990020AAF7 /* PathUtilities.h */; };
</ins><span class="cx">                 2D58D8551A15F65F00A5F726 /* DataDetection.h in Headers */ = {isa = PBXBuildFile; fileRef = 2D58D8531A15F65F00A5F726 /* DataDetection.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 2D58D8561A15F65F00A5F726 /* DataDetection.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2D58D8541A15F65F00A5F726 /* DataDetection.mm */; };
</span><span class="cx">                 2D59F1BF1A0044C6001F3D29 /* DataDetectorsSPI.h in Headers */ = {isa = PBXBuildFile; fileRef = 2D59F1BE1A0044C6001F3D29 /* DataDetectorsSPI.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="lines">@@ -8301,6 +8304,9 @@
</span><span class="cx">                 2D4F96F21A1ECC240098BF88 /* TextIndicator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TextIndicator.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 2D4F96F31A1ECC240098BF88 /* TextIndicatorWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TextIndicatorWindow.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 2D4F96F41A1ECC240098BF88 /* TextIndicatorWindow.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = TextIndicatorWindow.mm; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                2D5002F71B56D7810020AAF7 /* DOMPath.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DOMPath.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
+                2D5002F91B56D7990020AAF7 /* PathUtilities.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PathUtilities.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
+                2D5002FA1B56D7990020AAF7 /* PathUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PathUtilities.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 2D58D8531A15F65F00A5F726 /* DataDetection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DataDetection.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 2D58D8541A15F65F00A5F726 /* DataDetection.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = DataDetection.mm; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 2D59F1BE1A0044C6001F3D29 /* DataDetectorsSPI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DataDetectorsSPI.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -16178,6 +16184,7 @@
</span><span class="cx">                                 49484FBE102CF23C00187DD3 /* CanvasRenderingContext2D.idl */,
</span><span class="cx">                                 49484FBF102CF23C00187DD3 /* CanvasStyle.cpp */,
</span><span class="cx">                                 49484FC0102CF23C00187DD3 /* CanvasStyle.h */,
</span><ins>+                                2D5002F71B56D7810020AAF7 /* DOMPath.cpp */,
</ins><span class="cx">                                 FB91392016AE4B0B001FE682 /* DOMPath.h */,
</span><span class="cx">                                 FB91392116AE4B0B001FE682 /* DOMPath.idl */,
</span><span class="cx">                                 724ED3291A3A7E5400F5F13C /* EXTBlendMinMax.cpp */,
</span><span class="lines">@@ -21029,6 +21036,8 @@
</span><span class="cx">                                 B27535530B053814002CE64F /* Path.h */,
</span><span class="cx">                                 A88DD4880B4629B000C02990 /* PathTraversalState.cpp */,
</span><span class="cx">                                 A88DD4860B4629A300C02990 /* PathTraversalState.h */,
</span><ins>+                                2D5002F91B56D7990020AAF7 /* PathUtilities.cpp */,
+                                2D5002FA1B56D7990020AAF7 /* PathUtilities.h */,
</ins><span class="cx">                                 A8FA6E5C0E4CFDED00D5CF49 /* Pattern.cpp */,
</span><span class="cx">                                 A8FA6E5B0E4CFDED00D5CF49 /* Pattern.h */,
</span><span class="cx">                                 0562F9601573F88F0031CA16 /* PlatformLayer.h */,
</span><span class="lines">@@ -24145,6 +24154,7 @@
</span><span class="cx">                                 065AD4F70B0C2EDA005A2B1D /* ContextMenuController.h in Headers */,
</span><span class="cx">                                 06027CAD0B1CBFC000884B2D /* ContextMenuItem.h in Headers */,
</span><span class="cx">                                 7ADE722610CBBB9B006B3B3A /* ContextMenuProvider.h in Headers */,
</span><ins>+                                2D5002FC1B56D7990020AAF7 /* PathUtilities.h in Headers */,
</ins><span class="cx">                                 759CB837192DA9190012BC64 /* ControlStates.h in Headers */,
</span><span class="cx">                                 FD31602912B0267600C1A359 /* ConvolverNode.h in Headers */,
</span><span class="cx">                                 D8B6152F1032495100C8554A /* Cookie.h in Headers */,
</span><span class="lines">@@ -29739,6 +29749,7 @@
</span><span class="cx">                                 297BE3DA16C043D8003316BD /* PlatformSpeechSynthesizer.cpp in Sources */,
</span><span class="cx">                                 AA12DF491743DF83004DAFDF /* PlatformSpeechSynthesizerIOS.mm in Sources */,
</span><span class="cx">                                 297BE3D816C03CCE003316BD /* PlatformSpeechSynthesizerMac.mm in Sources */,
</span><ins>+                                2D5002FB1B56D7990020AAF7 /* PathUtilities.cpp in Sources */,
</ins><span class="cx">                                 1AD8F81C11CAB9E900E93E54 /* PlatformStrategies.cpp in Sources */,
</span><span class="cx">                                 074E82BA18A69F0E007EF54C /* PlatformTimeRanges.cpp in Sources */,
</span><span class="cx">                                 A9C6E4F30D745E48006442E9 /* PluginData.cpp in Sources */,
</span><span class="lines">@@ -30512,6 +30523,7 @@
</span><span class="cx">                                 7AF9B20518CFB2DF00C64BEF /* VTTRegionList.cpp in Sources */,
</span><span class="cx">                                 7A93868518DCC14500B8263D /* VTTScanner.cpp in Sources */,
</span><span class="cx">                                 A14832B1187F61E100DA63A6 /* WAKAppKitStubs.m in Sources */,
</span><ins>+                                2D5002F81B56D7810020AAF7 /* DOMPath.cpp in Sources */,
</ins><span class="cx">                                 A14832B3187F629100DA63A6 /* WAKClipView.m in Sources */,
</span><span class="cx">                                 A14832B5187F62FC00DA63A6 /* WAKResponder.m in Sources */,
</span><span class="cx">                                 A14832B7187F636C00DA63A6 /* WAKScrollView.mm in Sources */,
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsjsJSDOMBindingh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/js/JSDOMBinding.h (186857 => 186858)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/js/JSDOMBinding.h        2015-07-15 21:07:01 UTC (rev 186857)
+++ trunk/Source/WebCore/bindings/js/JSDOMBinding.h        2015-07-15 21:19:29 UTC (rev 186858)
</span><span class="lines">@@ -507,6 +507,14 @@
</span><span class="cx">     }
</span><span class="cx"> };
</span><span class="cx"> 
</span><ins>+template&lt;&gt; struct NativeValueTraits&lt;double&gt; {
+    static inline bool nativeValue(JSC::ExecState* exec, JSC::JSValue jsValue, double&amp; indexedValue)
+    {
+        indexedValue = jsValue.toNumber(exec);
+        return !exec-&gt;hadException();
+    }
+};
+
</ins><span class="cx"> template&lt;typename T, typename JST&gt; Vector&lt;RefPtr&lt;T&gt;&gt; toRefPtrNativeArray(JSC::ExecState* exec, JSC::JSValue value, T* (*toT)(JSC::JSValue value))
</span><span class="cx"> {
</span><span class="cx">     if (!isJSArray(value))
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsscriptsCodeGeneratorJSpm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm (186857 => 186858)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm        2015-07-15 21:07:01 UTC (rev 186857)
+++ trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm        2015-07-15 21:19:29 UTC (rev 186858)
</span><span class="lines">@@ -240,6 +240,7 @@
</span><span class="cx">     &quot;JSClientRectList&quot; =&gt; 1,
</span><span class="cx">     &quot;JSCSSStyleDeclaration&quot; =&gt; 1,
</span><span class="cx">     &quot;JSDocument&quot; =&gt; 1,
</span><ins>+    &quot;JSDOMPath&quot; =&gt; 1,
</ins><span class="cx">     &quot;JSDOMWindow&quot; =&gt; 1,
</span><span class="cx">     &quot;JSElement&quot; =&gt; 1,
</span><span class="cx">     &quot;JSFile&quot; =&gt; 1,
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlcanvasDOMPathcpp"></a>
<div class="addfile"><h4>Added: trunk/Source/WebCore/html/canvas/DOMPath.cpp (0 => 186858)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/canvas/DOMPath.cpp                                (rev 0)
+++ trunk/Source/WebCore/html/canvas/DOMPath.cpp        2015-07-15 21:19:29 UTC (rev 186858)
</span><span class="lines">@@ -0,0 +1,37 @@
</span><ins>+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER &quot;AS IS&quot; AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include &quot;config.h&quot;
+#include &quot;DOMPath.h&quot;
+
+namespace WebCore {
+
+DOMPath::~DOMPath()
+{
+}
+
+}
</ins></span></pre></div>
<a id="trunkSourceWebCorehtmlcanvasDOMPathh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/canvas/DOMPath.h (186857 => 186858)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/canvas/DOMPath.h        2015-07-15 21:07:01 UTC (rev 186857)
+++ trunk/Source/WebCore/html/canvas/DOMPath.h        2015-07-15 21:19:29 UTC (rev 186858)
</span><span class="lines">@@ -35,9 +35,11 @@
</span><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><del>-class DOMPath final : public RefCounted&lt;DOMPath&gt;, public CanvasPathMethods {
</del><ins>+class WEBCORE_EXPORT DOMPath final : public RefCounted&lt;DOMPath&gt;, public CanvasPathMethods {
</ins><span class="cx">     WTF_MAKE_FAST_ALLOCATED;
</span><span class="cx"> public:
</span><ins>+    WEBCORE_EXPORT virtual ~DOMPath();
+
</ins><span class="cx">     static Ref&lt;DOMPath&gt; create() { return adoptRef(*new DOMPath); }
</span><span class="cx">     static Ref&lt;DOMPath&gt; create(const Path&amp; path) { return adoptRef(*new DOMPath(path)); }
</span><span class="cx">     static Ref&lt;DOMPath&gt; create(const DOMPath* path) { return create(path-&gt;path()); }
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsPathh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/Path.h (186857 => 186858)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/Path.h        2015-07-15 21:07:01 UTC (rev 186857)
+++ trunk/Source/WebCore/platform/graphics/Path.h        2015-07-15 21:19:29 UTC (rev 186858)
</span><span class="lines">@@ -28,6 +28,7 @@
</span><span class="cx"> #ifndef Path_h
</span><span class="cx"> #define Path_h
</span><span class="cx"> 
</span><ins>+#include &quot;FloatRect.h&quot;
</ins><span class="cx"> #include &quot;WindRule.h&quot;
</span><span class="cx"> #include &lt;wtf/FastMalloc.h&gt;
</span><span class="cx"> #include &lt;wtf/Forward.h&gt;
</span><span class="lines">@@ -56,7 +57,6 @@
</span><span class="cx"> 
</span><span class="cx">     class AffineTransform;
</span><span class="cx">     class FloatPoint;
</span><del>-    class FloatRect;
</del><span class="cx">     class FloatRoundedRect;
</span><span class="cx">     class FloatSize;
</span><span class="cx">     class GraphicsContext;
</span><span class="lines">@@ -144,7 +144,7 @@
</span><span class="cx">         // meaning Path::platformPath() can return null.
</span><span class="cx">         PlatformPathPtr platformPath() const { return m_path; }
</span><span class="cx">         // ensurePlatformPath() will allocate a PlatformPath if it has not yet been and will never return null.
</span><del>-        PlatformPathPtr ensurePlatformPath();
</del><ins>+        WEBCORE_EXPORT PlatformPathPtr ensurePlatformPath();
</ins><span class="cx"> 
</span><span class="cx">         WEBCORE_EXPORT void apply(void* info, PathApplierFunction) const;
</span><span class="cx">         void transform(const AffineTransform&amp;);
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsPathUtilitiescpp"></a>
<div class="addfile"><h4>Added: trunk/Source/WebCore/platform/graphics/PathUtilities.cpp (0 => 186858)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/PathUtilities.cpp                                (rev 0)
+++ trunk/Source/WebCore/platform/graphics/PathUtilities.cpp        2015-07-15 21:19:29 UTC (rev 186858)
</span><span class="lines">@@ -0,0 +1,263 @@
</span><ins>+/*
+ * Copyright (C) 2014-2015 Apple Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+
+#include &quot;config.h&quot;
+#include &quot;PathUtilities.h&quot;
+
+#include &quot;FloatPoint.h&quot;
+#include &quot;FloatRect.h&quot;
+#include &lt;math.h&gt;
+
+namespace WebCore {
+
+static void addShrinkWrapRightCorner(Path&amp; path, const FloatRect* fromRect, const FloatRect* toRect, float radius)
+{
+    FloatSize horizontalRadius(radius, 0);
+    FloatSize verticalRadius(0, radius);
+
+    if (!fromRect) {
+        // For the first (top) rect:
+
+        path.moveTo(toRect-&gt;minXMinYCorner() + horizontalRadius);
+
+        // Across the top, towards the right.
+        path.addLineTo(toRect-&gt;maxXMinYCorner() - horizontalRadius);
+
+        // Arc the top corner.
+        path.addArcTo(toRect-&gt;maxXMinYCorner(), toRect-&gt;maxXMinYCorner() + verticalRadius, radius);
+    } else if (!toRect) {
+        // For the last rect:
+
+        // Down the right.
+        path.addLineTo(fromRect-&gt;maxXMaxYCorner() - verticalRadius);
+
+        // Arc the bottom corner.
+        path.addArcTo(fromRect-&gt;maxXMaxYCorner(), fromRect-&gt;maxXMaxYCorner() - horizontalRadius, radius);
+    } else {
+        // For middle rects:
+
+        float rightEdgeDifference = toRect-&gt;maxX() - fromRect-&gt;maxX();
+
+        // Skip over rects with equal edges, because we can't make
+        // sensible curves between them.
+        if (fabsf(rightEdgeDifference) &lt; std::numeric_limits&lt;float&gt;::epsilon())
+            return;
+
+        if (rightEdgeDifference &lt; 0) {
+            float effectiveY = std::max(toRect-&gt;y(), fromRect-&gt;maxY());
+            FloatPoint toRectMaxXMinYCorner = FloatPoint(toRect-&gt;maxX(), effectiveY);
+
+            // Down the right.
+            path.addLineTo(FloatPoint(fromRect-&gt;maxX(), effectiveY) - verticalRadius);
+
+            // Arc the outer corner.
+            path.addArcTo(FloatPoint(fromRect-&gt;maxX(), effectiveY), FloatPoint(fromRect-&gt;maxX(), effectiveY) - horizontalRadius, radius);
+
+            // Across the bottom, towards the left.
+            path.addLineTo(toRectMaxXMinYCorner + horizontalRadius);
+
+            // Arc the inner corner.
+            path.addArcTo(toRectMaxXMinYCorner, toRectMaxXMinYCorner + verticalRadius, radius);
+        } else {
+            float effectiveY = std::min(toRect-&gt;y(), fromRect-&gt;maxY());
+            FloatPoint toRectMaxXMinYCorner = FloatPoint(toRect-&gt;maxX(), effectiveY);
+
+            // Down the right.
+            path.addLineTo(FloatPoint(fromRect-&gt;maxX(), effectiveY) - verticalRadius);
+
+            // Arc the inner corner.
+            path.addArcTo(FloatPoint(fromRect-&gt;maxX(), effectiveY), FloatPoint(fromRect-&gt;maxX(), effectiveY) + horizontalRadius, radius);
+
+            // Across the bottom, towards the right.
+            path.addLineTo(toRectMaxXMinYCorner - horizontalRadius);
+
+            // Arc the outer corner.
+            path.addArcTo(toRectMaxXMinYCorner, toRectMaxXMinYCorner + verticalRadius, radius);
+        }
+    }
+}
+
+static void addShrinkWrapLeftCorner(Path&amp; path, const FloatRect* fromRect, const FloatRect* toRect, float radius)
+{
+    FloatSize horizontalRadius(radius, 0);
+    FloatSize verticalRadius(0, radius);
+
+    if (!fromRect) {
+        // For the first (bottom) rect:
+
+        // Across the bottom, towards the left.
+        path.addLineTo(toRect-&gt;minXMaxYCorner() + horizontalRadius);
+
+        // Arc the bottom corner.
+        path.addArcTo(toRect-&gt;minXMaxYCorner(), toRect-&gt;minXMaxYCorner() - verticalRadius, radius);
+
+    } else if (!toRect) {
+        // For the last (top) rect:
+
+        // Up the left.
+        path.addLineTo(fromRect-&gt;minXMinYCorner() + verticalRadius);
+
+        // Arc the top corner.
+        path.addArcTo(fromRect-&gt;minXMinYCorner(), fromRect-&gt;minXMinYCorner() + horizontalRadius, radius);
+    } else {
+        // For middle rects:
+        float leftEdgeDifference = fromRect-&gt;x() - toRect-&gt;x();
+
+        // Skip over rects with equal edges, because we can't make
+        // sensible curves between them.
+        if (fabsf(leftEdgeDifference) &lt; std::numeric_limits&lt;float&gt;::epsilon())
+            return;
+
+        if (leftEdgeDifference &lt; 0) {
+            float effectiveY = std::min(toRect-&gt;maxY(), fromRect-&gt;y());
+            FloatPoint toRectMinXMaxYCorner = FloatPoint(toRect-&gt;x(), effectiveY);
+
+            // Up the right.
+            path.addLineTo(FloatPoint(fromRect-&gt;x(), effectiveY) + verticalRadius);
+
+            // Arc the inner corner.
+            path.addArcTo(FloatPoint(fromRect-&gt;x(), effectiveY), FloatPoint(fromRect-&gt;x(), effectiveY) + horizontalRadius, radius);
+
+            // Across the bottom, towards the right.
+            path.addLineTo(toRectMinXMaxYCorner - horizontalRadius);
+
+            // Arc the outer corner.
+            path.addArcTo(toRectMinXMaxYCorner, toRectMinXMaxYCorner - verticalRadius, radius);
+        } else {
+            float effectiveY = std::max(toRect-&gt;maxY(), fromRect-&gt;y());
+            FloatPoint toRectMinXMaxYCorner = FloatPoint(toRect-&gt;x(), effectiveY);
+
+            // Up the right.
+            path.addLineTo(FloatPoint(fromRect-&gt;x(), effectiveY) + verticalRadius);
+
+            // Arc the outer corner.
+            path.addArcTo(FloatPoint(fromRect-&gt;x(), effectiveY), FloatPoint(fromRect-&gt;x(), effectiveY) - horizontalRadius, radius);
+
+            // Across the bottom, towards the left.
+            path.addLineTo(toRectMinXMaxYCorner + horizontalRadius);
+
+            // Arc the inner corner.
+            path.addArcTo(toRectMinXMaxYCorner, toRectMinXMaxYCorner - verticalRadius, radius);
+        }
+    }
+}
+
+static void addShrinkWrappedPathForRects(Path&amp; path, Vector&lt;FloatRect&gt;&amp; rects, float radius)
+{
+    size_t rectCount = rects.size();
+
+    std::sort(rects.begin(), rects.end(), [](FloatRect a, FloatRect b) { return b.y() &gt; a.y(); });
+
+    for (size_t i = 0; i &lt;= rectCount; ++i)
+        addShrinkWrapRightCorner(path, i ? &amp;rects[i - 1] : nullptr, i &lt; rectCount ? &amp;rects[i] : nullptr, radius);
+
+    for (size_t i = 0; i &lt;= rectCount; ++i) {
+        size_t reverseIndex = rectCount - i;
+        addShrinkWrapLeftCorner(path, reverseIndex &lt; rectCount ? &amp;rects[reverseIndex] : nullptr, reverseIndex ? &amp;rects[reverseIndex - 1] : nullptr, radius);
+    }
+
+    path.closeSubpath();
+}
+
+static bool rectsIntersectOrTouch(const FloatRect&amp; a, const FloatRect&amp; b)
+{
+    return !a.isEmpty() &amp;&amp; !b.isEmpty()
+        &amp;&amp; a.x() &lt;= b.maxX() &amp;&amp; b.x() &lt;= a.maxX()
+        &amp;&amp; a.y() &lt;= b.maxY() &amp;&amp; b.y() &lt;= a.maxY();
+}
+
+static Vector&lt;FloatRect&gt;* findSetContainingRect(Vector&lt;Vector&lt;FloatRect&gt;&gt;&amp; sets, FloatRect rect)
+{
+    for (auto&amp; set : sets) {
+        if (set.contains(rect))
+            return &amp;set;
+    }
+
+    return nullptr;
+}
+
+static Vector&lt;Vector&lt;FloatRect&gt;&gt; contiguousRectGroupsFromRects(const Vector&lt;FloatRect&gt;&amp; rects)
+{
+    Vector&lt;std::pair&lt;FloatRect, FloatRect&gt;&gt; intersections;
+    Vector&lt;FloatRect&gt; soloRects = rects;
+
+    for (auto&amp; rectA : rects) {
+        for (auto&amp; rectB : rects) {
+            if (rectA == rectB)
+                continue;
+
+            if (rectsIntersectOrTouch(rectA, rectB)) {
+                intersections.append(std::make_pair(rectA, rectB));
+                soloRects.removeAllMatching([rectA, rectB](FloatRect q) { return q == rectA || q == rectB; });
+            }
+        }
+    }
+
+    Vector&lt;Vector&lt;FloatRect&gt;&gt; rectSets;
+
+    for (auto&amp; intersectingPair : intersections) {
+        if (Vector&lt;FloatRect&gt;* rectContainingFirst = findSetContainingRect(rectSets, intersectingPair.first)) {
+            if (!rectContainingFirst-&gt;contains(intersectingPair.second))
+                rectContainingFirst-&gt;append(intersectingPair.second);
+            continue;
+        }
+
+        if (Vector&lt;FloatRect&gt;* rectContainingSecond = findSetContainingRect(rectSets, intersectingPair.second)) {
+            if (!rectContainingSecond-&gt;contains(intersectingPair.first))
+                rectContainingSecond-&gt;append(intersectingPair.first);
+            continue;
+        }
+
+        // We didn't find a set including either of our rects, so start a new one.
+        rectSets.append(Vector&lt;FloatRect&gt;({intersectingPair.first, intersectingPair.second}));
+
+        continue;
+    }
+
+    for (auto&amp; rect : soloRects) {
+        ASSERT(!findSetContainingRect(rectSets, rect));
+        rectSets.append(Vector&lt;FloatRect&gt;({rect}));
+    }
+
+    return rectSets;
+}
+
+Path PathUtilities::pathWithShrinkWrappedRects(const Vector&lt;FloatRect&gt;&amp; rects, float radius)
+{
+    Path path;
+
+    if (rects.isEmpty())
+        return path;
+
+    Vector&lt;Vector&lt;FloatRect&gt;&gt; rectSets = contiguousRectGroupsFromRects(rects);
+
+    for (auto&amp; set : rectSets)
+        addShrinkWrappedPathForRects(path, set, radius);
+    
+    return path;
+}
+
+}
</ins></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsPathUtilitiesh"></a>
<div class="addfile"><h4>Added: trunk/Source/WebCore/platform/graphics/PathUtilities.h (0 => 186858)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/PathUtilities.h                                (rev 0)
+++ trunk/Source/WebCore/platform/graphics/PathUtilities.h        2015-07-15 21:19:29 UTC (rev 186858)
</span><span class="lines">@@ -0,0 +1,41 @@
</span><ins>+/*
+ * Copyright (C) 2014-2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef PathUtilities_h
+#define PathUtilities_h
+
+#include &quot;Path.h&quot;
+#include &lt;wtf/Vector.h&gt;
+
+namespace WebCore {
+
+class PathUtilities {
+public:
+    WEBCORE_EXPORT static Path pathWithShrinkWrappedRects(const Vector&lt;FloatRect&gt;&amp; rects, float radius);
+};
+
+}
+
+#endif
</ins></span></pre></div>
<a id="trunkSourceWebCorerenderingRenderThemeMacmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/rendering/RenderThemeMac.mm (186857 => 186858)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/RenderThemeMac.mm        2015-07-15 21:07:01 UTC (rev 186857)
+++ trunk/Source/WebCore/rendering/RenderThemeMac.mm        2015-07-15 21:19:29 UTC (rev 186858)
</span><span class="lines">@@ -52,6 +52,7 @@
</span><span class="cx"> #import &quot;NSSharingServicePickerSPI.h&quot;
</span><span class="cx"> #import &quot;Page.h&quot;
</span><span class="cx"> #import &quot;PaintInfo.h&quot;
</span><ins>+#import &quot;PathUtilities.h&quot;
</ins><span class="cx"> #import &quot;RenderAttachment.h&quot;
</span><span class="cx"> #import &quot;RenderLayer.h&quot;
</span><span class="cx"> #import &quot;RenderMedia.h&quot;
</span><span class="lines">@@ -2379,136 +2380,16 @@
</span><span class="cx">     icon-&gt;paint(context, layout.iconRect);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static void addAttachmentTitleBackgroundRightCorner(Path&amp; path, const FloatRect* fromRect, const FloatRect* toRect)
-{
-    FloatSize horizontalRadius(attachmentTitleBackgroundRadius, 0);
-    FloatSize verticalRadius(0, attachmentTitleBackgroundRadius);
-
-    if (!fromRect) {
-        // For the first (top) rect:
-
-        path.moveTo(toRect-&gt;minXMinYCorner() + horizontalRadius);
-
-        // Across the top, towards the right.
-        path.addLineTo(toRect-&gt;maxXMinYCorner() - horizontalRadius);
-
-        // Arc the top corner.
-        path.addArcTo(toRect-&gt;maxXMinYCorner(), toRect-&gt;maxXMinYCorner() + verticalRadius, attachmentTitleBackgroundRadius);
-
-        // Down the right.
-        path.addLineTo(toRect-&gt;maxXMaxYCorner() - verticalRadius);
-    } else if (!toRect) {
-        // For the last rect:
-
-        // Arc the bottom corner.
-        path.addArcTo(fromRect-&gt;maxXMaxYCorner(), fromRect-&gt;maxXMaxYCorner() - horizontalRadius, attachmentTitleBackgroundRadius);
-    } else {
-        // For middle rects:
-
-        float widthDifference = toRect-&gt;width() - fromRect-&gt;width();
-
-        // Skip over very similar-width rects, because we can't make
-        // sensible curves between them.
-        if (fabs(widthDifference) &lt; std::numeric_limits&lt;float&gt;::epsilon())
-            return;
-
-        if (widthDifference &lt; 0) {
-            // Arc the outer corner.
-            path.addArcTo(FloatPoint(fromRect-&gt;maxX(), toRect-&gt;y()), FloatPoint(fromRect-&gt;maxX(), toRect-&gt;y()) - horizontalRadius, attachmentTitleBackgroundRadius);
-
-            // Across the bottom, towards the left.
-            path.addLineTo(toRect-&gt;maxXMinYCorner() + horizontalRadius);
-
-            // Arc the inner corner.
-            path.addArcTo(toRect-&gt;maxXMinYCorner(), toRect-&gt;maxXMinYCorner() + verticalRadius, attachmentTitleBackgroundRadius);
-        } else {
-            // Arc the inner corner.
-            path.addArcTo(FloatPoint(fromRect-&gt;maxX(), toRect-&gt;y()), FloatPoint(fromRect-&gt;maxX(), toRect-&gt;y()) + horizontalRadius, attachmentTitleBackgroundRadius);
-
-            // Across the bottom, towards the right.
-            path.addLineTo(toRect-&gt;maxXMinYCorner() - horizontalRadius);
-
-            // Arc the outer corner.
-            path.addArcTo(toRect-&gt;maxXMinYCorner(), toRect-&gt;maxXMinYCorner() + verticalRadius, attachmentTitleBackgroundRadius);
-        }
-
-        // Down the right.
-        path.addLineTo(toRect-&gt;maxXMaxYCorner() - verticalRadius);
-    }
-}
-
-static void addAttachmentTitleBackgroundLeftCorner(Path&amp; path, const FloatRect* fromRect, const FloatRect* toRect)
-{
-    FloatSize horizontalRadius(attachmentTitleBackgroundRadius, 0);
-    FloatSize verticalRadius(0, attachmentTitleBackgroundRadius);
-
-    if (!fromRect) {
-        // For the first (bottom) rect:
-
-        // Across the bottom, towards the left.
-        path.addLineTo(toRect-&gt;minXMaxYCorner() + horizontalRadius);
-
-        // Arc the bottom corner.
-        path.addArcTo(toRect-&gt;minXMaxYCorner(), toRect-&gt;minXMaxYCorner() - verticalRadius, attachmentTitleBackgroundRadius);
-
-        // Up the left.
-        path.addLineTo(toRect-&gt;minXMinYCorner() + verticalRadius);
-    } else if (!toRect) {
-        // For the last (top) rect:
-
-        // Arc the top corner.
-        path.addArcTo(fromRect-&gt;minXMinYCorner(), fromRect-&gt;minXMinYCorner() + horizontalRadius, attachmentTitleBackgroundRadius);
-    } else {
-        // For middle rects:
-        float widthDifference = toRect-&gt;width() - fromRect-&gt;width();
-
-        // Skip over very similar-width rects, because we can't make
-        // sensible curves between them.
-        if (fabs(widthDifference) &lt; std::numeric_limits&lt;float&gt;::epsilon())
-            return;
-
-        if (widthDifference &lt; 0) {
-            // Arc the inner corner.
-            path.addArcTo(FloatPoint(fromRect-&gt;x(), toRect-&gt;maxY()), FloatPoint(fromRect-&gt;x(), toRect-&gt;maxY()) + horizontalRadius, attachmentTitleBackgroundRadius);
-
-            // Across the bottom, towards the right.
-            path.addLineTo(toRect-&gt;minXMaxYCorner() - horizontalRadius);
-
-            // Arc the outer corner.
-            path.addArcTo(toRect-&gt;minXMaxYCorner(), toRect-&gt;minXMaxYCorner() - verticalRadius, attachmentTitleBackgroundRadius);
-        } else {
-            // Arc the outer corner.
-            path.addArcTo(FloatPoint(fromRect-&gt;x(), toRect-&gt;maxY()), FloatPoint(fromRect-&gt;x(), toRect-&gt;maxY()) - horizontalRadius, attachmentTitleBackgroundRadius);
-
-            // Across the bottom, towards the left.
-            path.addLineTo(toRect-&gt;minXMaxYCorner() + horizontalRadius);
-
-            // Arc the inner corner.
-            path.addArcTo(toRect-&gt;minXMaxYCorner(), toRect-&gt;minXMaxYCorner() - verticalRadius, attachmentTitleBackgroundRadius);
-        }
-        
-        // Up the right.
-        path.addLineTo(toRect-&gt;minXMinYCorner() + verticalRadius);
-    }
-}
-
</del><span class="cx"> static void paintAttachmentTitleBackground(const RenderAttachment&amp; attachment, GraphicsContext&amp; context, AttachmentLayout&amp; layout)
</span><span class="cx"> {
</span><span class="cx">     if (layout.lines.isEmpty())
</span><span class="cx">         return;
</span><span class="cx"> 
</span><del>-    Path backgroundPath;
</del><ins>+    Vector&lt;FloatRect&gt; backgroundRects;
</ins><span class="cx"> 
</span><del>-    for (size_t i = 0; i &lt;= layout.lines.size(); ++i)
-        addAttachmentTitleBackgroundRightCorner(backgroundPath, i ? &amp;layout.lines[i - 1].backgroundRect : nullptr, i &lt; layout.lines.size() ? &amp;layout.lines[i].backgroundRect : nullptr);
</del><ins>+    for (size_t i = 0; i &lt; layout.lines.size(); ++i)
+        backgroundRects.append(layout.lines[i].backgroundRect);
</ins><span class="cx"> 
</span><del>-    for (size_t i = 0; i &lt;= layout.lines.size(); ++i) {
-        size_t reverseIndex = layout.lines.size() - i;
-        addAttachmentTitleBackgroundLeftCorner(backgroundPath, reverseIndex &lt; layout.lines.size() ? &amp;layout.lines[reverseIndex].backgroundRect : nullptr, reverseIndex ? &amp;layout.lines[reverseIndex - 1].backgroundRect : nullptr);
-    }
-
-    backgroundPath.closeSubpath();
-
</del><span class="cx">     Color backgroundColor;
</span><span class="cx">     if (attachment.frame().selection().isFocusedAndActive())
</span><span class="cx">         backgroundColor = convertNSColorToColor([NSColor alternateSelectedControlColor]);
</span><span class="lines">@@ -2516,6 +2397,8 @@
</span><span class="cx">         backgroundColor = attachmentTitleInactiveBackgroundColor();
</span><span class="cx"> 
</span><span class="cx">     context.setFillColor(backgroundColor, ColorSpaceDeviceRGB);
</span><ins>+
+    Path backgroundPath = PathUtilities::pathWithShrinkWrappedRects(backgroundRects, attachmentTitleBackgroundRadius);
</ins><span class="cx">     context.fillPath(backgroundPath);
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoretestingInternalscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/testing/Internals.cpp (186857 => 186858)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/testing/Internals.cpp        2015-07-15 21:07:01 UTC (rev 186857)
+++ trunk/Source/WebCore/testing/Internals.cpp        2015-07-15 21:19:29 UTC (rev 186858)
</span><span class="lines">@@ -39,6 +39,7 @@
</span><span class="cx"> #include &quot;ClientRectList.h&quot;
</span><span class="cx"> #include &quot;ContentDistributor.h&quot;
</span><span class="cx"> #include &quot;Cursor.h&quot;
</span><ins>+#include &quot;DOMPath.h&quot;
</ins><span class="cx"> #include &quot;DOMStringList.h&quot;
</span><span class="cx"> #include &quot;DOMWindow.h&quot;
</span><span class="cx"> #include &quot;Document.h&quot;
</span><span class="lines">@@ -87,6 +88,7 @@
</span><span class="cx"> #include &quot;Page.h&quot;
</span><span class="cx"> #include &quot;PageCache.h&quot;
</span><span class="cx"> #include &quot;PageOverlay.h&quot;
</span><ins>+#include &quot;PathUtilities.h&quot;
</ins><span class="cx"> #include &quot;PlatformMediaSessionManager.h&quot;
</span><span class="cx"> #include &quot;PrintContext.h&quot;
</span><span class="cx"> #include &quot;PseudoElement.h&quot;
</span><span class="lines">@@ -2919,4 +2921,28 @@
</span><span class="cx">     return testPreloadScannerViewportSupport(contextDocument());
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+PassRefPtr&lt;DOMPath&gt; Internals::pathWithShrinkWrappedRects(Vector&lt;double&gt; rectComponents, ExceptionCode&amp; ec)
+{
+    if (rectComponents.size() % 4) {
+        ec = INVALID_ACCESS_ERR;
+        return nullptr;
+    }
+
+    Vector&lt;FloatRect&gt; rects;
+    while (!rectComponents.isEmpty()) {
+        double height = rectComponents.takeLast();
+        double width = rectComponents.takeLast();
+        double y = rectComponents.takeLast();
+        double x = rectComponents.takeLast();
+
+        rects.append(FloatRect(x, y, width, height));
+    }
+
+    rects.reverse();
+
+    // FIXME: radius should be a parameter instead of fixed as 8.
+    Path path = PathUtilities::pathWithShrinkWrappedRects(rects, 8);
+    return DOMPath::create(path);
</ins><span class="cx"> }
</span><ins>+
+}
</ins></span></pre></div>
<a id="trunkSourceWebCoretestingInternalsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/testing/Internals.h (186857 => 186858)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/testing/Internals.h        2015-07-15 21:07:01 UTC (rev 186857)
+++ trunk/Source/WebCore/testing/Internals.h        2015-07-15 21:19:29 UTC (rev 186858)
</span><span class="lines">@@ -44,6 +44,7 @@
</span><span class="cx"> class AudioContext;
</span><span class="cx"> class ClientRect;
</span><span class="cx"> class ClientRectList;
</span><ins>+class DOMPath;
</ins><span class="cx"> class DOMStringList;
</span><span class="cx"> class DOMWindow;
</span><span class="cx"> class Document;
</span><span class="lines">@@ -414,6 +415,8 @@
</span><span class="cx">     String scrollSnapOffsets(Element*, ExceptionCode&amp;);
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+    PassRefPtr&lt;DOMPath&gt; pathWithShrinkWrappedRects(Vector&lt;double&gt;, ExceptionCode&amp;);
+
</ins><span class="cx"> private:
</span><span class="cx">     explicit Internals(Document*);
</span><span class="cx">     Document* contextDocument() const;
</span></span></pre></div>
<a id="trunkSourceWebCoretestingInternalsidl"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/testing/Internals.idl (186857 => 186858)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/testing/Internals.idl        2015-07-15 21:07:01 UTC (rev 186857)
+++ trunk/Source/WebCore/testing/Internals.idl        2015-07-15 21:19:29 UTC (rev 186858)
</span><span class="lines">@@ -375,4 +375,6 @@
</span><span class="cx"> #if defined(ENABLE_CSS_SCROLL_SNAP) &amp;&amp; ENABLE_CSS_SCROLL_SNAP
</span><span class="cx">     [RaisesException] DOMString scrollSnapOffsets(Element element);
</span><span class="cx"> #endif
</span><ins>+
+    [RaisesException] DOMPath pathWithShrinkWrappedRects(sequence&lt;double&gt; rectComponents);
</ins><span class="cx"> };
</span></span></pre>
</div>
</div>

</body>
</html>