<!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>[195970] trunk/Source</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/195970">195970</a></dd>
<dt>Author</dt> <dd>commit-queue@webkit.org</dd>
<dt>Date</dt> <dd>2016-02-01 11:45:18 -0800 (Mon, 01 Feb 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>Cache the Path instead of creating it every time it is required
https://bugs.webkit.org/show_bug.cgi?id=152939

Patch by Said Abou-Hallawa &lt;sabouhallawa@apple.com&gt; on 2016-02-01
Reviewed by Darin Adler.

Source/WebCore:

Instead of creating the Path object every time it is required, we should
cache it in an LRU cache. TinyLRUCache returns a reference to the cached
entry so we do not have to pay the cost of copying it either.

* platform/graphics/FloatRoundedRect.h:
(WebCore::operator!=):
Implement the inequality operator for FloatRoundedRect since it is
called by TinyLRUCache.

* rendering/ClipPathOperation.h:
Return a reference to the path in the cache since instead of creating a
new copy.

* rendering/style/BasicShapes.cpp:
(WebCore::SVGPathTranslatedByteStream::SVGPathTranslatedByteStream):
(WebCore::SVGPathTranslatedByteStream::operator==):
(WebCore::SVGPathTranslatedByteStream::operator!=):
(WebCore::SVGPathTranslatedByteStream::isEmpty):
(WebCore::SVGPathTranslatedByteStream::path):
This struct holds an offset and an SVGPathByteStream. It is the key of
the LRU cache for the the translated SVGPathByteStream.

(WebCore::EllipsePathPolicy::isKeyNull):
(WebCore::EllipsePathPolicy::createValueForKey):
(WebCore::RoundedRectPathPolicy::isKeyNull):
(WebCore::RoundedRectPathPolicy::createValueForKey):
(WebCore::PolygonPathPolicy::isKeyNull):
(WebCore::PolygonPathPolicy::createValueForKey):
(WebCore::TranslatedByteStreamPathPolicy::isKeyNull):
(WebCore::TranslatedByteStreamPathPolicy::createValueForKey):
Inherit from the LRU cache policy template, so have a specific name for
the desired path contents and pass this class explicitly to the LRU cache
template.

(WebCore::cachedEllipsePath):
(WebCore::cachedRoundedRectPath):
(WebCore::cachedPolygonPath):
(WebCore::cachedTranslatedByteStreamPath):
Return a cached path object for specific path contents.

(WebCore::BasicShapeCircle::path):
(WebCore::BasicShapeEllipse::path):
(WebCore::BasicShapePolygon::path):
(WebCore::BasicShapePath::path):
(WebCore::BasicShapeInset::path):
Get the Path object from the cache; create a new one if it does not exist.

* rendering/style/BasicShapes.h:
Change the prototype of the path() function to return a reference to the
path in the cache instead of a having to copying it.

* svg/SVGPathByteStream.h:
(WebCore::SVGPathByteStream::operator!=):
Implement the inequality operator for SVGPathByteStream because it is
called by TinyLRUCache.

Source/WTF:

If the key type of an LRU cache can't to be strongly tided to a specific
data type; e.g. FloatRect -&gt; Path, we need to be able to pass the policy
type to the TinyLRUCache template instead of just specializing it. This
will make the code more readable and will allow different caches for the
same key type.

* wtf/TinyLRUCache.h:
(WebCore::TinyLRUCache::get):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWTFChangeLog">trunk/Source/WTF/ChangeLog</a></li>
<li><a href="#trunkSourceWTFwtfTinyLRUCacheh">trunk/Source/WTF/wtf/TinyLRUCache.h</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsFloatRoundedRecth">trunk/Source/WebCore/platform/graphics/FloatRoundedRect.h</a></li>
<li><a href="#trunkSourceWebCorerenderingClipPathOperationh">trunk/Source/WebCore/rendering/ClipPathOperation.h</a></li>
<li><a href="#trunkSourceWebCorerenderingstyleBasicShapescpp">trunk/Source/WebCore/rendering/style/BasicShapes.cpp</a></li>
<li><a href="#trunkSourceWebCorerenderingstyleBasicShapesh">trunk/Source/WebCore/rendering/style/BasicShapes.h</a></li>
<li><a href="#trunkSourceWebCoresvgSVGPathByteStreamh">trunk/Source/WebCore/svg/SVGPathByteStream.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWTFChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/ChangeLog (195969 => 195970)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/ChangeLog        2016-02-01 19:42:14 UTC (rev 195969)
+++ trunk/Source/WTF/ChangeLog        2016-02-01 19:45:18 UTC (rev 195970)
</span><span class="lines">@@ -1,3 +1,19 @@
</span><ins>+2016-02-01  Said Abou-Hallawa  &lt;sabouhallawa@apple.com&gt;
+
+        Cache the Path instead of creating it every time it is required
+        https://bugs.webkit.org/show_bug.cgi?id=152939
+
+        Reviewed by Darin Adler.
+
+        If the key type of an LRU cache can't to be strongly tided to a specific
+        data type; e.g. FloatRect -&gt; Path, we need to be able to pass the policy
+        type to the TinyLRUCache template instead of just specializing it. This
+        will make the code more readable and will allow different caches for the
+        same key type.
+
+        * wtf/TinyLRUCache.h:
+        (WebCore::TinyLRUCache::get):
+
</ins><span class="cx"> 2016-02-01  Alex Christensen  &lt;achristensen@webkit.org&gt;
</span><span class="cx"> 
</span><span class="cx">         [Win] WTFHeaderDetection.h no longer needed
</span></span></pre></div>
<a id="trunkSourceWTFwtfTinyLRUCacheh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/TinyLRUCache.h (195969 => 195970)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/TinyLRUCache.h        2016-02-01 19:42:14 UTC (rev 195969)
+++ trunk/Source/WTF/wtf/TinyLRUCache.h        2016-02-01 19:45:18 UTC (rev 195970)
</span><span class="lines">@@ -38,13 +38,13 @@
</span><span class="cx">     static ValueType createValueForKey(const KeyType&amp;) { return { }; }
</span><span class="cx"> };
</span><span class="cx"> 
</span><del>-template&lt;typename KeyType, typename ValueType, size_t capacity = 4&gt;
</del><ins>+template&lt;typename KeyType, typename ValueType, size_t capacity = 4, typename Policy = TinyLRUCachePolicy&lt;KeyType, ValueType&gt;&gt;
</ins><span class="cx"> class TinyLRUCache {
</span><span class="cx"> public:
</span><span class="cx">     const ValueType&amp; get(const KeyType&amp; key)
</span><span class="cx">     {
</span><del>-        if (TinyLRUCachePolicy&lt;KeyType, ValueType&gt;::isKeyNull(key)) {
-            static NeverDestroyed&lt;ValueType&gt; valueForNull = TinyLRUCachePolicy&lt;KeyType, ValueType&gt;::createValueForNullKey();
</del><ins>+        if (Policy::isKeyNull(key)) {
+            static NeverDestroyed&lt;ValueType&gt; valueForNull = Policy::createValueForNullKey();
</ins><span class="cx">             return valueForNull;
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="lines">@@ -66,7 +66,7 @@
</span><span class="cx">         if (m_cache.size() == capacity)
</span><span class="cx">             m_cache.remove(0);
</span><span class="cx"> 
</span><del>-        m_cache.append(std::make_pair(key, TinyLRUCachePolicy&lt;KeyType, ValueType&gt;::createValueForKey(key)));
</del><ins>+        m_cache.append(std::make_pair(key, Policy::createValueForKey(key)));
</ins><span class="cx">         return m_cache.last().second;
</span><span class="cx">     }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (195969 => 195970)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2016-02-01 19:42:14 UTC (rev 195969)
+++ trunk/Source/WebCore/ChangeLog        2016-02-01 19:45:18 UTC (rev 195970)
</span><span class="lines">@@ -1,3 +1,66 @@
</span><ins>+2016-02-01  Said Abou-Hallawa  &lt;sabouhallawa@apple.com&gt;
+
+        Cache the Path instead of creating it every time it is required
+        https://bugs.webkit.org/show_bug.cgi?id=152939
+
+        Reviewed by Darin Adler.
+
+        Instead of creating the Path object every time it is required, we should 
+        cache it in an LRU cache. TinyLRUCache returns a reference to the cached
+        entry so we do not have to pay the cost of copying it either.
+
+        * platform/graphics/FloatRoundedRect.h:
+        (WebCore::operator!=):
+        Implement the inequality operator for FloatRoundedRect since it is
+        called by TinyLRUCache.
+        
+        * rendering/ClipPathOperation.h:
+        Return a reference to the path in the cache since instead of creating a
+        new copy.
+        
+        * rendering/style/BasicShapes.cpp:
+        (WebCore::SVGPathTranslatedByteStream::SVGPathTranslatedByteStream):
+        (WebCore::SVGPathTranslatedByteStream::operator==):
+        (WebCore::SVGPathTranslatedByteStream::operator!=):
+        (WebCore::SVGPathTranslatedByteStream::isEmpty):
+        (WebCore::SVGPathTranslatedByteStream::path):
+        This struct holds an offset and an SVGPathByteStream. It is the key of 
+        the LRU cache for the the translated SVGPathByteStream.
+        
+        (WebCore::EllipsePathPolicy::isKeyNull):
+        (WebCore::EllipsePathPolicy::createValueForKey):
+        (WebCore::RoundedRectPathPolicy::isKeyNull):
+        (WebCore::RoundedRectPathPolicy::createValueForKey):
+        (WebCore::PolygonPathPolicy::isKeyNull):
+        (WebCore::PolygonPathPolicy::createValueForKey):
+        (WebCore::TranslatedByteStreamPathPolicy::isKeyNull):
+        (WebCore::TranslatedByteStreamPathPolicy::createValueForKey):
+        Inherit from the LRU cache policy template, so have a specific name for
+        the desired path contents and pass this class explicitly to the LRU cache
+        template.
+        
+        (WebCore::cachedEllipsePath):
+        (WebCore::cachedRoundedRectPath):
+        (WebCore::cachedPolygonPath):
+        (WebCore::cachedTranslatedByteStreamPath):
+        Return a cached path object for specific path contents.
+        
+        (WebCore::BasicShapeCircle::path):
+        (WebCore::BasicShapeEllipse::path):
+        (WebCore::BasicShapePolygon::path):
+        (WebCore::BasicShapePath::path):
+        (WebCore::BasicShapeInset::path):
+        Get the Path object from the cache; create a new one if it does not exist.
+        
+        * rendering/style/BasicShapes.h:
+        Change the prototype of the path() function to return a reference to the
+        path in the cache instead of a having to copying it.
+        
+        * svg/SVGPathByteStream.h:
+        (WebCore::SVGPathByteStream::operator!=):
+        Implement the inequality operator for SVGPathByteStream because it is
+        called by TinyLRUCache.
+
</ins><span class="cx"> 2016-02-01  Chris Dumez  &lt;cdumez@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Move properties that use custom bindings to the prototype
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsFloatRoundedRecth"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/FloatRoundedRect.h (195969 => 195970)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/FloatRoundedRect.h        2016-02-01 19:42:14 UTC (rev 195969)
+++ trunk/Source/WebCore/platform/graphics/FloatRoundedRect.h        2016-02-01 19:45:18 UTC (rev 195970)
</span><span class="lines">@@ -141,11 +141,21 @@
</span><span class="cx">     return a.topLeft() == b.topLeft() &amp;&amp; a.topRight() == b.topRight() &amp;&amp; a.bottomLeft() == b.bottomLeft() &amp;&amp; a.bottomRight() == b.bottomRight();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+inline bool operator!=(const FloatRoundedRect::Radii&amp; a, const FloatRoundedRect::Radii&amp; b)
+{
+    return !(a == b);
+}
+
</ins><span class="cx"> inline bool operator==(const FloatRoundedRect&amp; a, const FloatRoundedRect&amp; b)
</span><span class="cx"> {
</span><span class="cx">     return a.rect() == b.rect() &amp;&amp; a.radii() == b.radii();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+inline bool operator!=(const FloatRoundedRect&amp; a, const FloatRoundedRect&amp; b)
+{
+    return !(a == b);
+}
+
</ins><span class="cx"> inline float calcBorderRadiiConstraintScaleFor(const FloatRect&amp; rect, const FloatRoundedRect::Radii&amp; radii)
</span><span class="cx"> {
</span><span class="cx">     // Constrain corner radii using CSS3 rules:
</span></span></pre></div>
<a id="trunkSourceWebCorerenderingClipPathOperationh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/rendering/ClipPathOperation.h (195969 => 195970)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/ClipPathOperation.h        2016-02-01 19:42:14 UTC (rev 195969)
+++ trunk/Source/WebCore/rendering/ClipPathOperation.h        2016-02-01 19:45:18 UTC (rev 195970)
</span><span class="lines">@@ -103,12 +103,7 @@
</span><span class="cx"> 
</span><span class="cx">     const BasicShape&amp; basicShape() const { return m_shape; }
</span><span class="cx">     WindRule windRule() const { return m_shape.get().windRule(); }
</span><del>-    const Path pathForReferenceRect(const FloatRect&amp; boundingRect)
-    {
-        Path path;
-        m_shape.get().path(path, boundingRect);
-        return path;
-    }
</del><ins>+    const Path&amp; pathForReferenceRect(const FloatRect&amp; boundingRect) { return m_shape.get().path(boundingRect); }
</ins><span class="cx"> 
</span><span class="cx">     void setReferenceBox(CSSBoxType referenceBox) { m_referenceBox = referenceBox; }
</span><span class="cx">     CSSBoxType referenceBox() const { return m_referenceBox; }
</span></span></pre></div>
<a id="trunkSourceWebCorerenderingstyleBasicShapescpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/rendering/style/BasicShapes.cpp (195969 => 195970)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/style/BasicShapes.cpp        2016-02-01 19:42:14 UTC (rev 195969)
+++ trunk/Source/WebCore/rendering/style/BasicShapes.cpp        2016-02-01 19:45:18 UTC (rev 195970)
</span><span class="lines">@@ -41,6 +41,9 @@
</span><span class="cx"> #include &quot;SVGPathByteStream.h&quot;
</span><span class="cx"> #include &quot;SVGPathUtilities.h&quot;
</span><span class="cx"> 
</span><ins>+#include &lt;wtf/NeverDestroyed.h&gt;
+#include &lt;wtf/TinyLRUCache.h&gt;
+
</ins><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><span class="cx"> void BasicShapeCenterCoordinate::updateComputedLength()
</span><span class="lines">@@ -60,6 +63,90 @@
</span><span class="cx">     m_computedLength = Length(CalculationValue::create(WTFMove(op), CalculationRangeAll));
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+struct SVGPathTranslatedByteStream {
+    SVGPathTranslatedByteStream(const FloatPoint&amp; offset, const SVGPathByteStream&amp; rawStream)
+        : m_offset(offset)
+        , m_rawStream(rawStream)
+    { }
+
+    bool operator==(const SVGPathTranslatedByteStream&amp; other) const { return other.m_offset == m_offset &amp;&amp; other.m_rawStream == m_rawStream; }
+    bool operator!=(const SVGPathTranslatedByteStream&amp; other) const { return !(*this == other); }
+    bool isEmpty() const { return m_rawStream.isEmpty(); }
+
+    Path path() const
+    {
+        Path path;
+        buildPathFromByteStream(m_rawStream, path);
+        path.translate(toFloatSize(m_offset));
+        return path;
+    }
+    
+    FloatPoint m_offset;
+    SVGPathByteStream m_rawStream;
+};
+
+struct EllipsePathPolicy : public TinyLRUCachePolicy&lt;FloatRect, Path&gt; {
+public:
+    static bool isKeyNull(const FloatRect&amp; rect) { return rect.isEmpty(); }
+
+    static Path createValueForKey(const FloatRect&amp; rect)
+    {
+        Path path;
+        path.addEllipse(rect);
+        return path;
+    }
+};
+
+struct RoundedRectPathPolicy : public TinyLRUCachePolicy&lt;FloatRoundedRect, Path&gt; {
+public:
+    static bool isKeyNull(const FloatRoundedRect&amp; rect) { return rect.isEmpty(); }
+
+    static Path createValueForKey(const FloatRoundedRect&amp; rect)
+    {
+        Path path;
+        path.addRoundedRect(rect);
+        return path;
+    }
+};
+
+struct PolygonPathPolicy : public TinyLRUCachePolicy&lt;Vector&lt;FloatPoint&gt;, Path&gt; {
+public:
+    static bool isKeyNull(const Vector&lt;FloatPoint&gt;&amp; points) { return !points.size(); }
+
+    static Path createValueForKey(const Vector&lt;FloatPoint&gt;&amp; points) { return Path::polygonPathFromPoints(points); }
+};
+
+struct TranslatedByteStreamPathPolicy : public TinyLRUCachePolicy&lt;SVGPathTranslatedByteStream, Path&gt; {
+public:
+    static bool isKeyNull(const SVGPathTranslatedByteStream&amp; stream) { return stream.isEmpty(); }
+
+    static Path createValueForKey(const SVGPathTranslatedByteStream&amp; stream) { return stream.path(); }
+};
+
+static const Path&amp; cachedEllipsePath(const FloatRect&amp; rect)
+{
+    static NeverDestroyed&lt;TinyLRUCache&lt;FloatRect, Path, 4, EllipsePathPolicy&gt;&gt; cache;
+    return cache.get().get(rect);
+}
+
+static const Path&amp; cachedRoundedRectPath(const FloatRoundedRect&amp; rect)
+{
+    static NeverDestroyed&lt;TinyLRUCache&lt;FloatRoundedRect, Path, 4, RoundedRectPathPolicy&gt;&gt; cache;
+    return cache.get().get(rect);
+}
+
+static const Path&amp; cachedPolygonPath(const Vector&lt;FloatPoint&gt;&amp; points)
+{
+    static NeverDestroyed&lt;TinyLRUCache&lt;Vector&lt;FloatPoint&gt;, Path, 4, PolygonPathPolicy&gt;&gt; cache;
+    return cache.get().get(points);
+}
+
+static const Path&amp; cachedTranslatedByteStreamPath(const SVGPathByteStream&amp; stream, const FloatPoint&amp; offset)
+{
+    static NeverDestroyed&lt;TinyLRUCache&lt;SVGPathTranslatedByteStream, Path, 4, TranslatedByteStreamPathPolicy&gt;&gt; cache;
+    return cache.get().get(SVGPathTranslatedByteStream(offset, stream));
+}
+
</ins><span class="cx"> bool BasicShapeCircle::operator==(const BasicShape&amp; other) const
</span><span class="cx"> {
</span><span class="cx">     if (type() != other.type())
</span><span class="lines">@@ -88,19 +175,13 @@
</span><span class="cx">     return std::max(std::max(std::abs(centerX), widthDelta), std::max(std::abs(centerY), heightDelta));
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void BasicShapeCircle::path(Path&amp; path, const FloatRect&amp; boundingBox)
</del><ins>+const Path&amp; BasicShapeCircle::path(const FloatRect&amp; boundingBox)
</ins><span class="cx"> {
</span><del>-    ASSERT(path.isEmpty());
-
</del><span class="cx">     float centerX = floatValueForCenterCoordinate(m_centerX, boundingBox.width());
</span><span class="cx">     float centerY = floatValueForCenterCoordinate(m_centerY, boundingBox.height());
</span><span class="cx">     float radius = floatValueForRadiusInBox(boundingBox.width(), boundingBox.height());
</span><del>-    path.addEllipse(FloatRect(
-        centerX - radius + boundingBox.x(),
-        centerY - radius + boundingBox.y(),
-        radius * 2,
-        radius * 2
-    ));
</del><ins>+
+    return cachedEllipsePath(FloatRect(centerX - radius + boundingBox.x(), centerY - radius + boundingBox.y(), radius * 2, radius * 2));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> bool BasicShapeCircle::canBlend(const BasicShape&amp; other) const
</span><span class="lines">@@ -148,19 +229,14 @@
</span><span class="cx">     return std::max(std::abs(center), widthOrHeightDelta);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void BasicShapeEllipse::path(Path&amp; path, const FloatRect&amp; boundingBox)
</del><ins>+const Path&amp; BasicShapeEllipse::path(const FloatRect&amp; boundingBox)
</ins><span class="cx"> {
</span><del>-    ASSERT(path.isEmpty());
-
</del><span class="cx">     float centerX = floatValueForCenterCoordinate(m_centerX, boundingBox.width());
</span><span class="cx">     float centerY = floatValueForCenterCoordinate(m_centerY, boundingBox.height());
</span><span class="cx">     float radiusX = floatValueForRadiusInBox(m_radiusX, centerX, boundingBox.width());
</span><span class="cx">     float radiusY = floatValueForRadiusInBox(m_radiusY, centerY, boundingBox.height());
</span><del>-    path.addEllipse(FloatRect(
-        centerX - radiusX + boundingBox.x(),
-        centerY - radiusY + boundingBox.y(),
-        radiusX * 2,
-        radiusY * 2));
</del><ins>+
+    return cachedEllipsePath(FloatRect(centerX - radiusX + boundingBox.x(), centerY - radiusY + boundingBox.y(), radiusX * 2, radiusY * 2));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> bool BasicShapeEllipse::canBlend(const BasicShape&amp; other) const
</span><span class="lines">@@ -204,22 +280,18 @@
</span><span class="cx">         &amp;&amp; m_values == otherPolygon.m_values;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void BasicShapePolygon::path(Path&amp; path, const FloatRect&amp; boundingBox)
</del><ins>+const Path&amp; BasicShapePolygon::path(const FloatRect&amp; boundingBox)
</ins><span class="cx"> {
</span><del>-    ASSERT(path.isEmpty());
</del><span class="cx">     ASSERT(!(m_values.size() % 2));
</span><span class="cx">     size_t length = m_values.size();
</span><del>-    
-    if (!length)
-        return;
</del><span class="cx"> 
</span><del>-    path.moveTo(FloatPoint(floatValueForLength(m_values.at(0), boundingBox.width()) + boundingBox.x(),
-        floatValueForLength(m_values.at(1), boundingBox.height()) + boundingBox.y()));
-    for (size_t i = 2; i &lt; length; i = i + 2) {
-        path.addLineTo(FloatPoint(floatValueForLength(m_values.at(i), boundingBox.width()) + boundingBox.x(),
-            floatValueForLength(m_values.at(i + 1), boundingBox.height()) + boundingBox.y()));
</del><ins>+    Vector&lt;FloatPoint&gt; points(length / 2);
+    for (size_t i = 0; i &lt; points.size(); ++i) {
+        points[i].setX(floatValueForLength(m_values.at(i * 2), boundingBox.width()) + boundingBox.x());
+        points[i].setY(floatValueForLength(m_values.at(i * 2 + 1), boundingBox.height()) + boundingBox.y());
</ins><span class="cx">     }
</span><del>-    path.closeSubpath();
</del><ins>+
+    return cachedPolygonPath(points);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> bool BasicShapePolygon::canBlend(const BasicShape&amp; other) const
</span><span class="lines">@@ -259,11 +331,9 @@
</span><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void BasicShapePath::path(Path&amp; path, const FloatRect&amp; boundingBox)
</del><ins>+const Path&amp; BasicShapePath::path(const FloatRect&amp; boundingBox)
</ins><span class="cx"> {
</span><del>-    ASSERT(path.isEmpty());
-    buildPathFromByteStream(*m_byteStream, path);
-    path.translate(toFloatSize(boundingBox.location()));
</del><ins>+    return cachedTranslatedByteStreamPath(*m_byteStream, boundingBox.location());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> bool BasicShapePath::operator==(const BasicShape&amp; other) const
</span><span class="lines">@@ -320,9 +390,8 @@
</span><span class="cx">         floatValueForLength(lengthSize.height(), boundingBox.height()));
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void BasicShapeInset::path(Path&amp; path, const FloatRect&amp; boundingBox)
</del><ins>+const Path&amp; BasicShapeInset::path(const FloatRect&amp; boundingBox)
</ins><span class="cx"> {
</span><del>-    ASSERT(path.isEmpty());
</del><span class="cx">     float left = floatValueForLength(m_left, boundingBox.width());
</span><span class="cx">     float top = floatValueForLength(m_top, boundingBox.height());
</span><span class="cx">     auto rect = FloatRect(left + boundingBox.x(), top + boundingBox.y(),
</span><span class="lines">@@ -333,7 +402,8 @@
</span><span class="cx">         floatSizeForLengthSize(m_bottomLeftRadius, boundingBox),
</span><span class="cx">         floatSizeForLengthSize(m_bottomRightRadius, boundingBox));
</span><span class="cx">     radii.scale(calcBorderRadiiConstraintScaleFor(rect, radii));
</span><del>-    path.addRoundedRect(FloatRoundedRect(rect, radii));
</del><ins>+
+    return cachedRoundedRectPath(FloatRoundedRect(rect, radii));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> bool BasicShapeInset::canBlend(const BasicShape&amp; other) const
</span></span></pre></div>
<a id="trunkSourceWebCorerenderingstyleBasicShapesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/rendering/style/BasicShapes.h (195969 => 195970)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/style/BasicShapes.h        2016-02-01 19:42:14 UTC (rev 195969)
+++ trunk/Source/WebCore/rendering/style/BasicShapes.h        2016-02-01 19:45:18 UTC (rev 195970)
</span><span class="lines">@@ -60,7 +60,7 @@
</span><span class="cx"> 
</span><span class="cx">     virtual Type type() const = 0;
</span><span class="cx"> 
</span><del>-    virtual void path(Path&amp;, const FloatRect&amp;) = 0;
</del><ins>+    virtual const Path&amp; path(const FloatRect&amp;) = 0;
</ins><span class="cx">     virtual WindRule windRule() const { return RULE_NONZERO; }
</span><span class="cx"> 
</span><span class="cx">     virtual bool canBlend(const BasicShape&amp;) const = 0;
</span><span class="lines">@@ -192,7 +192,7 @@
</span><span class="cx"> 
</span><span class="cx">     virtual Type type() const override { return BasicShapeCircleType; }
</span><span class="cx"> 
</span><del>-    virtual void path(Path&amp;, const FloatRect&amp;) override;
</del><ins>+    virtual const Path&amp; path(const FloatRect&amp;) override;
</ins><span class="cx"> 
</span><span class="cx">     virtual bool canBlend(const BasicShape&amp;) const override;
</span><span class="cx">     virtual Ref&lt;BasicShape&gt; blend(const BasicShape&amp;, double) const override;
</span><span class="lines">@@ -224,7 +224,7 @@
</span><span class="cx"> 
</span><span class="cx">     virtual Type type() const override { return BasicShapeEllipseType; }
</span><span class="cx"> 
</span><del>-    virtual void path(Path&amp;, const FloatRect&amp;) override;
</del><ins>+    virtual const Path&amp; path(const FloatRect&amp;) override;
</ins><span class="cx"> 
</span><span class="cx">     virtual bool canBlend(const BasicShape&amp;) const override;
</span><span class="cx">     virtual Ref&lt;BasicShape&gt; blend(const BasicShape&amp;, double) const override;
</span><span class="lines">@@ -255,7 +255,7 @@
</span><span class="cx"> 
</span><span class="cx">     virtual Type type() const override { return BasicShapePolygonType; }
</span><span class="cx"> 
</span><del>-    virtual void path(Path&amp;, const FloatRect&amp;) override;
</del><ins>+    virtual const Path&amp; path(const FloatRect&amp;) override;
</ins><span class="cx"> 
</span><span class="cx">     virtual bool canBlend(const BasicShape&amp;) const override;
</span><span class="cx">     virtual Ref&lt;BasicShape&gt; blend(const BasicShape&amp;, double) const override;
</span><span class="lines">@@ -283,7 +283,7 @@
</span><span class="cx"> 
</span><span class="cx">     virtual Type type() const override { return BasicShapePathType; }
</span><span class="cx"> 
</span><del>-    virtual void path(Path&amp;, const FloatRect&amp;) override;
</del><ins>+    virtual const Path&amp; path(const FloatRect&amp;) override;
</ins><span class="cx"> 
</span><span class="cx">     virtual bool canBlend(const BasicShape&amp;) const override;
</span><span class="cx">     virtual Ref&lt;BasicShape&gt; blend(const BasicShape&amp;, double) const override;
</span><span class="lines">@@ -323,7 +323,7 @@
</span><span class="cx"> 
</span><span class="cx">     virtual Type type() const override { return BasicShapeInsetType; }
</span><span class="cx"> 
</span><del>-    virtual void path(Path&amp;, const FloatRect&amp;) override;
</del><ins>+    virtual const Path&amp; path(const FloatRect&amp;) override;
</ins><span class="cx"> 
</span><span class="cx">     virtual bool canBlend(const BasicShape&amp;) const override;
</span><span class="cx">     virtual Ref&lt;BasicShape&gt; blend(const BasicShape&amp;, double) const override;
</span></span></pre></div>
<a id="trunkSourceWebCoresvgSVGPathByteStreamh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/svg/SVGPathByteStream.h (195969 => 195970)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/svg/SVGPathByteStream.h        2016-02-01 19:42:14 UTC (rev 195969)
+++ trunk/Source/WebCore/svg/SVGPathByteStream.h        2016-02-01 19:45:18 UTC (rev 195970)
</span><span class="lines">@@ -55,6 +55,11 @@
</span><span class="cx">         return m_data == other.m_data;
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    bool operator!=(const SVGPathByteStream&amp; other) const
+    {
+        return !(*this == other);
+    }
+
</ins><span class="cx">     std::unique_ptr&lt;SVGPathByteStream&gt; copy() const
</span><span class="cx">     {
</span><span class="cx">         return std::make_unique&lt;SVGPathByteStream&gt;(m_data);
</span></span></pre>
</div>
</div>

</body>
</html>