<!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>[190879] 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/190879">190879</a></dd>
<dt>Author</dt> <dd>simon.fraser@apple.com</dd>
<dt>Date</dt> <dd>2015-10-12 12:15:28 -0700 (Mon, 12 Oct 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>Clip-path transitions sometimes trigger endless animation timers
https://bugs.webkit.org/show_bug.cgi?id=150018

Reviewed by Tim Horton.

Source/WebCore:

Transitioning -webkit-clip-path could trigger endless animation
timers, because when CompositeAnimation::updateTransitions() calls
isTargetPropertyEqual(), a false negative answer triggers canceling the
current transition and starting a new one over and over.

This happened because StyleRareNonInheritedData simply tested pointer
equality for m_clipPath and m_shapeOutside. Both of these need to do deep
equality testing, requiring the implementation of operator== in BasicShapes
classes.

In addition, the PropertyWrappers in CSSPropertyAnimation need equals()
implementations that also do more than pointer equality testing.

Tests: transitions/clip-path-transitions.html
       transitions/shape-outside-transitions.html

* page/animation/CSSPropertyAnimation.cpp:
(WebCore::PropertyWrapperClipPath::equals):
(WebCore::PropertyWrapperShape::equals):
* rendering/ClipPathOperation.h:
* rendering/style/BasicShapes.cpp:
(WebCore::BasicShapeCircle::operator==):
(WebCore::BasicShapeEllipse::operator==):
(WebCore::BasicShapePolygon::operator==):
(WebCore::BasicShapeInset::operator==):
* rendering/style/BasicShapes.h:
(WebCore::BasicShapeCenterCoordinate::operator==):
(WebCore::BasicShapeRadius::operator==):
* rendering/style/ShapeValue.cpp:
(WebCore::pointersOrValuesEqual):
(WebCore::ShapeValue::operator==):
* rendering/style/ShapeValue.h:
(WebCore::ShapeValue::operator!=):
(WebCore::ShapeValue::operator==): Deleted.
(WebCore::ShapeValue::ShapeValue): Deleted.
* rendering/style/StyleRareNonInheritedData.cpp:
(WebCore::StyleRareNonInheritedData::operator==):
(WebCore::StyleRareNonInheritedData::clipPathOperationsEquivalent):
(WebCore::StyleRareNonInheritedData::shapeOutsideDataEquivalent):
* rendering/style/StyleRareNonInheritedData.h:

LayoutTests:

New tests for transitions of clip-path and shape-outside.

* transitions/clip-path-transitions-expected.txt: Added.
* transitions/clip-path-transitions.html: Added.
* transitions/resources/transition-test-helpers.js:
(parseClipPath):
(checkExpectedValue):
* transitions/shape-outside-transitions-expected.txt: Added.
* transitions/shape-outside-transitions.html: Added.
* transitions/svg-transitions-expected.txt:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTeststransitionsresourcestransitiontesthelpersjs">trunk/LayoutTests/transitions/resources/transition-test-helpers.js</a></li>
<li><a href="#trunkLayoutTeststransitionssvgtransitionsexpectedtxt">trunk/LayoutTests/transitions/svg-transitions-expected.txt</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCorepageanimationCSSPropertyAnimationcpp">trunk/Source/WebCore/page/animation/CSSPropertyAnimation.cpp</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="#trunkSourceWebCorerenderingstyleShapeValuecpp">trunk/Source/WebCore/rendering/style/ShapeValue.cpp</a></li>
<li><a href="#trunkSourceWebCorerenderingstyleShapeValueh">trunk/Source/WebCore/rendering/style/ShapeValue.h</a></li>
<li><a href="#trunkSourceWebCorerenderingstyleStyleRareNonInheritedDatacpp">trunk/Source/WebCore/rendering/style/StyleRareNonInheritedData.cpp</a></li>
<li><a href="#trunkSourceWebCorerenderingstyleStyleRareNonInheritedDatah">trunk/Source/WebCore/rendering/style/StyleRareNonInheritedData.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTeststransitionsclippathtransitionsexpectedtxt">trunk/LayoutTests/transitions/clip-path-transitions-expected.txt</a></li>
<li><a href="#trunkLayoutTeststransitionsclippathtransitionshtml">trunk/LayoutTests/transitions/clip-path-transitions.html</a></li>
<li><a href="#trunkLayoutTeststransitionsshapeoutsidetransitionsexpectedtxt">trunk/LayoutTests/transitions/shape-outside-transitions-expected.txt</a></li>
<li><a href="#trunkLayoutTeststransitionsshapeoutsidetransitionshtml">trunk/LayoutTests/transitions/shape-outside-transitions.html</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (190878 => 190879)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2015-10-12 19:15:17 UTC (rev 190878)
+++ trunk/LayoutTests/ChangeLog        2015-10-12 19:15:28 UTC (rev 190879)
</span><span class="lines">@@ -1,3 +1,21 @@
</span><ins>+2015-10-12  Simon Fraser  &lt;simon.fraser@apple.com&gt;
+
+        Clip-path transitions sometimes trigger endless animation timers
+        https://bugs.webkit.org/show_bug.cgi?id=150018
+
+        Reviewed by Tim Horton.
+        
+        New tests for transitions of clip-path and shape-outside.
+
+        * transitions/clip-path-transitions-expected.txt: Added.
+        * transitions/clip-path-transitions.html: Added.
+        * transitions/resources/transition-test-helpers.js:
+        (parseClipPath):
+        (checkExpectedValue):
+        * transitions/shape-outside-transitions-expected.txt: Added.
+        * transitions/shape-outside-transitions.html: Added.
+        * transitions/svg-transitions-expected.txt:
+
</ins><span class="cx"> 2015-10-12  Ryan Haddad  &lt;ryanhaddad@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Marking storage/domstorage/events/basic-body-attribute.html as flaky
</span></span></pre></div>
<a id="trunkLayoutTeststransitionsclippathtransitionsexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/transitions/clip-path-transitions-expected.txt (0 => 190879)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/transitions/clip-path-transitions-expected.txt                                (rev 0)
+++ trunk/LayoutTests/transitions/clip-path-transitions-expected.txt        2015-10-12 19:15:28 UTC (rev 190879)
</span><span class="lines">@@ -0,0 +1,5 @@
</span><ins>+PASS - &quot;-webkit-clip-path&quot; property for &quot;circle&quot; element at 0.5s saw something close to: circle(60px at 50px 40px)
+PASS - &quot;-webkit-clip-path&quot; property for &quot;ellipse&quot; element at 0.5s saw something close to: ellipse(15px 30px at 50px 40px)
+PASS - &quot;-webkit-clip-path&quot; property for &quot;inset&quot; element at 0.5s saw something close to: inset(15px 22px)
+PASS - &quot;-webkit-clip-path&quot; property for &quot;polygon&quot; element at 0.5s saw something close to: polygon(15px 0px, 75px 0, 60px 45px, 0 45px)
+
</ins></span></pre></div>
<a id="trunkLayoutTeststransitionsclippathtransitionshtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/transitions/clip-path-transitions.html (0 => 190879)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/transitions/clip-path-transitions.html                                (rev 0)
+++ trunk/LayoutTests/transitions/clip-path-transitions.html        2015-10-12 19:15:28 UTC (rev 190879)
</span><span class="lines">@@ -0,0 +1,76 @@
</span><ins>+&lt;!DOCTYPE html&gt;
+
+&lt;html&gt;
+&lt;head&gt;
+  &lt;style&gt;
+    .box {
+        height: 100px;
+        width: 100px;
+        margin: 50px;
+        background-color: gray;
+        -webkit-transition-duration: 1s;
+        -webkit-transition-timing-function: linear;
+        -webkit-transition-property: -webkit-clip-path;
+    }
+    
+    #circle {
+        -webkit-clip-path: circle(100px at 50px 30px);
+    }
+    
+    body.final #circle {
+        -webkit-clip-path: circle(20px at 50px 50px);
+    }
+
+    #ellipse {
+        -webkit-clip-path: ellipse(10px 20px at 50px 30px);
+    }
+    
+    body.final #ellipse {
+        -webkit-clip-path: ellipse(20px 40px at 50px 50px);
+    }
+
+    #inset {
+        -webkit-clip-path: inset(10px 20px);
+    }
+    
+    body.final #inset {
+        -webkit-clip-path: inset(20px 24px);
+    }
+
+    #polygon {
+        -webkit-clip-path: polygon(20px 0px, 100px 0, 100px 50px, 0 50px);
+    }
+    
+    body.final #polygon {
+        -webkit-clip-path: polygon(10px 0px, 50px 0, 20px 40px, 0 40px);
+    }
+  &lt;/style&gt;
+  &lt;script src=&quot;resources/transition-test-helpers.js&quot;&gt;&lt;/script&gt;
+  &lt;script type=&quot;text/javascript&quot;&gt;
+
+    const expectedValues = [
+      // [time, element-id, property, expected-value, tolerance]
+      [0.5, 'circle', '-webkit-clip-path', 'circle(60px at 50px 40px)', 1],
+      [0.5, 'ellipse', '-webkit-clip-path', 'ellipse(15px 30px at 50px 40px)', 1],
+      [0.5, 'inset', '-webkit-clip-path', 'inset(15px 22px)', 1],
+      [0.5, 'polygon', '-webkit-clip-path', 'polygon(15px 0px, 75px 0, 60px 45px, 0 45px)', 1],
+    ];
+  
+    function setupTest()
+    {
+        document.body.classList.add('final');
+    }
+    
+    runTransitionTest(expectedValues, setupTest, usePauseAPI);
+  &lt;/script&gt;
+&lt;/head&gt;
+&lt;body&gt;
+  &lt;div id=&quot;circle&quot; class=&quot;box&quot;&gt;&lt;/div&gt;
+  &lt;div id=&quot;ellipse&quot; class=&quot;box&quot;&gt;&lt;/div&gt;
+  &lt;div id=&quot;inset&quot; class=&quot;box&quot;&gt;&lt;/div&gt;
+  &lt;div id=&quot;polygon&quot; class=&quot;box&quot;&gt;&lt;/div&gt;
+
+  &lt;div id=&quot;result&quot;&gt;&lt;/div&gt;
+
+&lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkLayoutTeststransitionsresourcestransitiontesthelpersjs"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/transitions/resources/transition-test-helpers.js (190878 => 190879)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/transitions/resources/transition-test-helpers.js        2015-10-12 19:15:17 UTC (rev 190878)
+++ trunk/LayoutTests/transitions/resources/transition-test-helpers.js        2015-10-12 19:15:28 UTC (rev 190879)
</span><span class="lines">@@ -69,6 +69,29 @@
</span><span class="cx">     return {&quot;from&quot;: matches[1], &quot;to&quot;: matches[2], &quot;percent&quot;: parseFloat(matches[3])}
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+function parseClipPath(s)
+{
+    // FIXME: This only matches a subset of the shape syntax, and the polygon expects 4 points.
+    var patterns = [
+        /inset\(([\d.]+)\w+ ([\d.]+)\w+\)/,
+        /circle\(([\d.]+)\w+ at ([\d.]+)\w+ ([\d.]+)\w+\)/,
+        /ellipse\(([\d.]+)\w+ ([\d.]+)\w+ at ([\d.]+)\w+ ([\d.]+)\w+\)/,
+        /polygon\(([\d.]+)\w* ([\d.]+)\w*\, ([\d.]+)\w* ([\d.]+)\w*\, ([\d.]+)\w* ([\d.]+)\w*\, ([\d.]+)\w* ([\d.]+)\w*\)/
+    ];
+    
+    for (pattern of patterns) {
+        if (matchResult = s.match(pattern)) {
+            var result = [];
+            for (var i = 1; i &lt; matchResult.length; ++i)
+                result.push(parseFloat(matchResult[i]));
+            return result;
+        }
+    }
+
+    window.console.log('failed to match ' + s);
+    return null;
+}
+
</ins><span class="cx"> function checkExpectedValue(expected, index)
</span><span class="cx"> {
</span><span class="cx">     var time = expected[index][0];
</span><span class="lines">@@ -136,6 +159,18 @@
</span><span class="cx">         } else {
</span><span class="cx">             pass = isCloseEnough(computedCrossFade.percent, expectedValue, tolerance);
</span><span class="cx">         }
</span><ins>+    } else if (property == &quot;-webkit-clip-path&quot; || property == &quot;-webkit-shape-outside&quot;) {
+        computedValue = window.getComputedStyle(document.getElementById(elementId)).getPropertyCSSValue(property).cssText;
+
+        var expectedValues = parseClipPath(expectedValue);
+        var values = parseClipPath(computedValue);
+        
+        pass = false;
+        if (values &amp;&amp; values.length == expectedValues.length) {
+            pass = true
+            for (var i = 0; i &lt; values.length; ++i)
+                pass &amp;= isCloseEnough(values[i], expectedValues[i], tolerance);
+        }
</ins><span class="cx">     } else {
</span><span class="cx">         var computedStyle = window.getComputedStyle(document.getElementById(elementId)).getPropertyCSSValue(property);
</span><span class="cx">         if (computedStyle.cssValueType == CSSValue.CSS_VALUE_LIST) {
</span></span></pre></div>
<a id="trunkLayoutTeststransitionsshapeoutsidetransitionsexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/transitions/shape-outside-transitions-expected.txt (0 => 190879)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/transitions/shape-outside-transitions-expected.txt                                (rev 0)
+++ trunk/LayoutTests/transitions/shape-outside-transitions-expected.txt        2015-10-12 19:15:28 UTC (rev 190879)
</span><span class="lines">@@ -0,0 +1,37 @@
</span><ins>+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+PASS - &quot;-webkit-shape-outside&quot; property for &quot;circle&quot; element at 0.5s saw something close to: circle(60px at 50px 40px)
+PASS - &quot;-webkit-shape-outside&quot; property for &quot;ellipse&quot; element at 0.5s saw something close to: ellipse(15px 30px at 50px 40px)
+PASS - &quot;-webkit-shape-outside&quot; property for &quot;inset&quot; element at 0.5s saw something close to: inset(15px 22px)
+PASS - &quot;-webkit-shape-outside&quot; property for &quot;polygon&quot; element at 0.5s saw something close to: polygon(15px 0px, 75px 0, 60px 45px, 0 45px)
+
</ins></span></pre></div>
<a id="trunkLayoutTeststransitionsshapeoutsidetransitionshtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/transitions/shape-outside-transitions.html (0 => 190879)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/transitions/shape-outside-transitions.html                                (rev 0)
+++ trunk/LayoutTests/transitions/shape-outside-transitions.html        2015-10-12 19:15:28 UTC (rev 190879)
</span><span class="lines">@@ -0,0 +1,97 @@
</span><ins>+&lt;!DOCTYPE html&gt;
+
+&lt;html&gt;
+&lt;head&gt;
+  &lt;style&gt;
+    .container {
+        width: 150px;
+        height: 150px;
+        border: 1px solid black;
+    }
+    .box {
+        height: 100px;
+        width: 100px;
+        margin: 10px;
+        background-color: silver;
+        -webkit-transition-duration: 1s;
+        -webkit-transition-timing-function: linear;
+        -webkit-transition-property: -webkit-shape-outside;
+        float: left;
+    }
+    
+    #circle {
+        -webkit-shape-outside: circle(100px at 50px 30px);
+    }
+    
+    body.final #circle {
+        -webkit-shape-outside: circle(20px at 50px 50px);
+    }
+
+    #ellipse {
+        -webkit-shape-outside: ellipse(10px 20px at 50px 30px);
+    }
+    
+    body.final #ellipse {
+        -webkit-shape-outside: ellipse(20px 40px at 50px 50px);
+    }
+
+    #inset {
+        -webkit-shape-outside: inset(10px 20px);
+    }
+    
+    body.final #inset {
+        -webkit-shape-outside: inset(20px 24px);
+    }
+
+    #polygon {
+        -webkit-shape-outside: polygon(20px 0px, 100px 0, 100px 50px, 0 50px);
+    }
+    
+    body.final #polygon {
+        -webkit-shape-outside: polygon(10px 0px, 50px 0, 20px 40px, 0 40px);
+    }
+  &lt;/style&gt;
+  &lt;script src=&quot;resources/transition-test-helpers.js&quot;&gt;&lt;/script&gt;
+  &lt;script type=&quot;text/javascript&quot;&gt;
+
+    const expectedValues = [
+      // [time, element-id, property, expected-value, tolerance]
+      [0.5, 'circle', '-webkit-shape-outside', 'circle(60px at 50px 40px)', 1],
+      [0.5, 'ellipse', '-webkit-shape-outside', 'ellipse(15px 30px at 50px 40px)', 1],
+      [0.5, 'inset', '-webkit-shape-outside', 'inset(15px 22px)', 1],
+      [0.5, 'polygon', '-webkit-shape-outside', 'polygon(15px 0px, 75px 0, 60px 45px, 0 45px)', 1],
+    ];
+  
+    function setupTest()
+    {
+        document.body.classList.add('final');
+    }
+    
+    runTransitionTest(expectedValues, setupTest, usePauseAPI);
+  &lt;/script&gt;
+&lt;/head&gt;
+&lt;body&gt;
+    &lt;div class=&quot;container&quot;&gt;
+        &lt;div id=&quot;circle&quot; class=&quot;box&quot;&gt;&lt;/div&gt;
+        x&lt;br&gt;x&lt;br&gt;x&lt;br&gt;x&lt;br&gt;x&lt;br&gt;x&lt;br&gt;x&lt;br&gt;x&lt;br&gt;
+    &lt;/div&gt;
+
+    &lt;div class=&quot;container&quot;&gt;
+        &lt;div id=&quot;ellipse&quot; class=&quot;box&quot;&gt;&lt;/div&gt;
+        x&lt;br&gt;x&lt;br&gt;x&lt;br&gt;x&lt;br&gt;x&lt;br&gt;x&lt;br&gt;x&lt;br&gt;x&lt;br&gt;
+    &lt;/div&gt;
+
+    &lt;div class=&quot;container&quot;&gt;
+        &lt;div id=&quot;inset&quot; class=&quot;box&quot;&gt;&lt;/div&gt;
+        x&lt;br&gt;x&lt;br&gt;x&lt;br&gt;x&lt;br&gt;x&lt;br&gt;x&lt;br&gt;x&lt;br&gt;x&lt;br&gt;
+    &lt;/div&gt;
+
+    &lt;div class=&quot;container&quot;&gt;
+        &lt;div id=&quot;polygon&quot; class=&quot;box&quot;&gt;&lt;/div&gt;
+        x&lt;br&gt;x&lt;br&gt;x&lt;br&gt;x&lt;br&gt;x&lt;br&gt;x&lt;br&gt;x&lt;br&gt;x&lt;br&gt;
+    &lt;/div&gt;
+
+    &lt;div id=&quot;result&quot;&gt;&lt;/div&gt;
+
+&lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkLayoutTeststransitionssvgtransitionsexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/transitions/svg-transitions-expected.txt (190878 => 190879)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/transitions/svg-transitions-expected.txt        2015-10-12 19:15:17 UTC (rev 190878)
+++ trunk/LayoutTests/transitions/svg-transitions-expected.txt        2015-10-12 19:15:28 UTC (rev 190879)
</span><span class="lines">@@ -1,4 +1,4 @@
</span><del>-CONSOLE MESSAGE: line 240: Failed to pause 'fill' transition on element 'rect7'
</del><ins>+CONSOLE MESSAGE: line 275: Failed to pause 'fill' transition on element 'rect7'
</ins><span class="cx"> Example
</span><span class="cx"> PASS - &quot;fill-opacity&quot; property for &quot;rect1&quot; element at 1s saw something close to: 0.6
</span><span class="cx"> PASS - &quot;stroke-width&quot; property for &quot;rect1&quot; element at 1s saw something close to: 3
</span></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (190878 => 190879)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2015-10-12 19:15:17 UTC (rev 190878)
+++ trunk/Source/WebCore/ChangeLog        2015-10-12 19:15:28 UTC (rev 190879)
</span><span class="lines">@@ -1,3 +1,51 @@
</span><ins>+2015-10-12  Simon Fraser  &lt;simon.fraser@apple.com&gt;
+
+        Clip-path transitions sometimes trigger endless animation timers
+        https://bugs.webkit.org/show_bug.cgi?id=150018
+
+        Reviewed by Tim Horton.
+        
+        Transitioning -webkit-clip-path could trigger endless animation
+        timers, because when CompositeAnimation::updateTransitions() calls
+        isTargetPropertyEqual(), a false negative answer triggers canceling the
+        current transition and starting a new one over and over.
+        
+        This happened because StyleRareNonInheritedData simply tested pointer
+        equality for m_clipPath and m_shapeOutside. Both of these need to do deep
+        equality testing, requiring the implementation of operator== in BasicShapes
+        classes.
+        
+        In addition, the PropertyWrappers in CSSPropertyAnimation need equals()
+        implementations that also do more than pointer equality testing.
+
+        Tests: transitions/clip-path-transitions.html
+               transitions/shape-outside-transitions.html
+
+        * page/animation/CSSPropertyAnimation.cpp:
+        (WebCore::PropertyWrapperClipPath::equals):
+        (WebCore::PropertyWrapperShape::equals):
+        * rendering/ClipPathOperation.h:
+        * rendering/style/BasicShapes.cpp:
+        (WebCore::BasicShapeCircle::operator==):
+        (WebCore::BasicShapeEllipse::operator==):
+        (WebCore::BasicShapePolygon::operator==):
+        (WebCore::BasicShapeInset::operator==):
+        * rendering/style/BasicShapes.h:
+        (WebCore::BasicShapeCenterCoordinate::operator==):
+        (WebCore::BasicShapeRadius::operator==):
+        * rendering/style/ShapeValue.cpp:
+        (WebCore::pointersOrValuesEqual):
+        (WebCore::ShapeValue::operator==):
+        * rendering/style/ShapeValue.h:
+        (WebCore::ShapeValue::operator!=):
+        (WebCore::ShapeValue::operator==): Deleted.
+        (WebCore::ShapeValue::ShapeValue): Deleted.
+        * rendering/style/StyleRareNonInheritedData.cpp:
+        (WebCore::StyleRareNonInheritedData::operator==):
+        (WebCore::StyleRareNonInheritedData::clipPathOperationsEquivalent):
+        (WebCore::StyleRareNonInheritedData::shapeOutsideDataEquivalent):
+        * rendering/style/StyleRareNonInheritedData.h:
+
</ins><span class="cx"> 2015-10-12  Myles C. Maxfield  &lt;mmaxfield@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Test font-variant-* and font-feature-settings on Yosemite and Mavericks
</span></span></pre></div>
<a id="trunkSourceWebCorepageanimationCSSPropertyAnimationcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/page/animation/CSSPropertyAnimation.cpp (190878 => 190879)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/page/animation/CSSPropertyAnimation.cpp        2015-10-12 19:15:17 UTC (rev 190878)
+++ trunk/Source/WebCore/page/animation/CSSPropertyAnimation.cpp        2015-10-12 19:15:28 UTC (rev 190879)
</span><span class="lines">@@ -477,6 +477,24 @@
</span><span class="cx">         : RefCountedPropertyWrapper&lt;ClipPathOperation&gt;(prop, getter, setter)
</span><span class="cx">     {
</span><span class="cx">     }
</span><ins>+
+    virtual bool equals(const RenderStyle* a, const RenderStyle* b) const
+    {
+        // If the style pointers are the same, don't bother doing the test.
+        // If either is null, return false. If both are null, return true.
+        if (a == b)
+            return true;
+        if (!a || !b)
+            return false;
+
+        ClipPathOperation* clipPathA = (a-&gt;*m_getter)();
+        ClipPathOperation* clipPathB = (b-&gt;*m_getter)();
+        if (clipPathA == clipPathB)
+            return true;
+        if (!clipPathA || !clipPathB)
+            return false;
+        return *clipPathA == *clipPathB;
+    }
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(CSS_SHAPES)
</span><span class="lines">@@ -487,6 +505,24 @@
</span><span class="cx">         : RefCountedPropertyWrapper&lt;ShapeValue&gt;(prop, getter, setter)
</span><span class="cx">     {
</span><span class="cx">     }
</span><ins>+
+    virtual bool equals(const RenderStyle* a, const RenderStyle* b) const
+    {
+        // If the style pointers are the same, don't bother doing the test.
+        // If either is null, return false. If both are null, return true.
+        if (a == b)
+            return true;
+        if (!a || !b)
+            return false;
+
+        ShapeValue* shapeA = (a-&gt;*m_getter)();
+        ShapeValue* shapeB = (b-&gt;*m_getter)();
+        if (shapeA == shapeB)
+            return true;
+        if (!shapeA || !shapeB)
+            return false;
+        return *shapeA == *shapeB;
+    }
</ins><span class="cx"> };
</span><span class="cx"> #endif
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCorerenderingClipPathOperationh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/rendering/ClipPathOperation.h (190878 => 190879)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/ClipPathOperation.h        2015-10-12 19:15:17 UTC (rev 190878)
+++ trunk/Source/WebCore/rendering/ClipPathOperation.h        2015-10-12 19:15:28 UTC (rev 190879)
</span><span class="lines">@@ -75,12 +75,12 @@
</span><span class="cx">     const String&amp; fragment() const { return m_fragment; }
</span><span class="cx"> 
</span><span class="cx"> private:
</span><del>-    virtual bool operator==(const ClipPathOperation&amp; o) const override
</del><ins>+    virtual bool operator==(const ClipPathOperation&amp; other) const override
</ins><span class="cx">     {
</span><del>-        if (!isSameType(o))
</del><ins>+        if (!isSameType(other))
</ins><span class="cx">             return false;
</span><del>-        const ReferenceClipPathOperation* other = static_cast&lt;const ReferenceClipPathOperation*&gt;(&amp;o);
-        return m_url == other-&gt;m_url;
</del><ins>+        auto&amp; referenceClip = downcast&lt;ReferenceClipPathOperation&gt;(other);
+        return m_url == referenceClip.m_url;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     ReferenceClipPathOperation(const String&amp; url, const String&amp; fragment)
</span><span class="lines">@@ -118,8 +118,9 @@
</span><span class="cx">     {
</span><span class="cx">         if (!isSameType(other))
</span><span class="cx">             return false;
</span><del>-        const auto&amp; shapeClip = downcast&lt;ShapeClipPathOperation&gt;(other);
-        return m_shape.ptr() == shapeClip.m_shape.ptr();
</del><ins>+        auto&amp; shapeClip = downcast&lt;ShapeClipPathOperation&gt;(other);
+        return m_referenceBox == shapeClip.referenceBox()
+            &amp;&amp; (m_shape.ptr() == shapeClip.m_shape.ptr() || m_shape.get() == shapeClip.m_shape.get());
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     explicit ShapeClipPathOperation(Ref&lt;BasicShape&gt;&amp;&amp; shape)
</span><span class="lines">@@ -149,12 +150,12 @@
</span><span class="cx">     CSSBoxType referenceBox() const { return m_referenceBox; }
</span><span class="cx"> 
</span><span class="cx"> private:
</span><del>-    virtual bool operator==(const ClipPathOperation&amp; o) const override
</del><ins>+    virtual bool operator==(const ClipPathOperation&amp; other) const override
</ins><span class="cx">     {
</span><del>-        if (!isSameType(o))
</del><ins>+        if (!isSameType(other))
</ins><span class="cx">             return false;
</span><del>-        const BoxClipPathOperation* other = static_cast&lt;const BoxClipPathOperation*&gt;(&amp;o);
-        return m_referenceBox == other-&gt;m_referenceBox;
</del><ins>+        auto&amp; boxClip = downcast&lt;BoxClipPathOperation&gt;(other);
+        return m_referenceBox == boxClip.m_referenceBox;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     explicit BoxClipPathOperation(CSSBoxType referenceBox)
</span></span></pre></div>
<a id="trunkSourceWebCorerenderingstyleBasicShapescpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/rendering/style/BasicShapes.cpp (190878 => 190879)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/style/BasicShapes.cpp        2015-10-12 19:15:17 UTC (rev 190878)
+++ trunk/Source/WebCore/rendering/style/BasicShapes.cpp        2015-10-12 19:15:28 UTC (rev 190879)
</span><span class="lines">@@ -88,6 +88,18 @@
</span><span class="cx">         &amp;&amp; thisEllipse.radiusY().canBlend(otherEllipse.radiusY()));
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+
+bool BasicShapeCircle::operator==(const BasicShape&amp; other) const
+{
+    if (type() != other.type())
+        return false;
+
+    const auto&amp; otherCircle = downcast&lt;BasicShapeCircle&gt;(other);
+    return m_centerX == otherCircle.m_centerX
+        &amp;&amp; m_centerY == otherCircle.m_centerY
+        &amp;&amp; m_radius == otherCircle.m_radius;
+}
+
</ins><span class="cx"> float BasicShapeCircle::floatValueForRadiusInBox(float boxWidth, float boxHeight) const
</span><span class="cx"> {
</span><span class="cx">     if (m_radius.type() == BasicShapeRadius::Value)
</span><span class="lines">@@ -132,6 +144,18 @@
</span><span class="cx">     return result.releaseNonNull();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+bool BasicShapeEllipse::operator==(const BasicShape&amp; other) const
+{
+    if (type() != other.type())
+        return false;
+
+    const auto&amp; otherEllipse = downcast&lt;BasicShapeEllipse&gt;(other);
+    return m_centerX == otherEllipse.m_centerX
+        &amp;&amp; m_centerY == otherEllipse.m_centerY
+        &amp;&amp; m_radiusX == otherEllipse.m_radiusX
+        &amp;&amp; m_radiusY == otherEllipse.m_radiusY;
+}
+
</ins><span class="cx"> float BasicShapeEllipse::floatValueForRadiusInBox(const BasicShapeRadius&amp; radius, float center, float boxWidthOrHeight) const
</span><span class="cx"> {
</span><span class="cx">     if (radius.type() == BasicShapeRadius::Value)
</span><span class="lines">@@ -182,6 +206,16 @@
</span><span class="cx">     return result.releaseNonNull();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+bool BasicShapePolygon::operator==(const BasicShape&amp; other) const
+{
+    if (type() != other.type())
+        return false;
+
+    const auto&amp; otherPolygon = downcast&lt;BasicShapePolygon&gt;(other);
+    return m_windRule == otherPolygon.m_windRule
+        &amp;&amp; m_values == otherPolygon.m_values;
+}
+
</ins><span class="cx"> void BasicShapePolygon::path(Path&amp; path, const FloatRect&amp; boundingBox)
</span><span class="cx"> {
</span><span class="cx">     ASSERT(path.isEmpty());
</span><span class="lines">@@ -223,6 +257,22 @@
</span><span class="cx">     return result.releaseNonNull();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+bool BasicShapeInset::operator==(const BasicShape&amp; other) const
+{
+    if (type() != other.type())
+        return false;
+
+    const auto&amp; otherInset = downcast&lt;BasicShapeInset&gt;(other);
+    return m_right == otherInset.m_right
+        &amp;&amp; m_top == otherInset.m_top
+        &amp;&amp; m_bottom == otherInset.m_bottom
+        &amp;&amp; m_left == otherInset.m_left
+        &amp;&amp; m_topLeftRadius == otherInset.m_topLeftRadius
+        &amp;&amp; m_topRightRadius == otherInset.m_topRightRadius
+        &amp;&amp; m_bottomRightRadius == otherInset.m_bottomRightRadius
+        &amp;&amp; m_bottomLeftRadius == otherInset.m_bottomLeftRadius;
+}
+
</ins><span class="cx"> static FloatSize floatSizeForLengthSize(const LengthSize&amp; lengthSize, const FloatRect&amp; boundingBox)
</span><span class="cx"> {
</span><span class="cx">     return FloatSize(floatValueForLength(lengthSize.width(), boundingBox.width()),
</span></span></pre></div>
<a id="trunkSourceWebCorerenderingstyleBasicShapesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/rendering/style/BasicShapes.h (190878 => 190879)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/style/BasicShapes.h        2015-10-12 19:15:17 UTC (rev 190878)
+++ trunk/Source/WebCore/rendering/style/BasicShapes.h        2015-10-12 19:15:28 UTC (rev 190879)
</span><span class="lines">@@ -63,6 +63,7 @@
</span><span class="cx">     virtual Ref&lt;BasicShape&gt; blend(const BasicShape&amp;, double) const = 0;
</span><span class="cx"> 
</span><span class="cx">     virtual Type type() const = 0;
</span><ins>+    virtual bool operator==(const BasicShape&amp;) const = 0;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> class BasicShapeCenterCoordinate {
</span><span class="lines">@@ -101,6 +102,13 @@
</span><span class="cx">     {
</span><span class="cx">         return BasicShapeCenterCoordinate(TopLeft, m_computedLength.blend(other.m_computedLength, progress));
</span><span class="cx">     }
</span><ins>+    
+    bool operator==(const BasicShapeCenterCoordinate&amp; other) const
+    {
+        return m_direction == other.m_direction
+            &amp;&amp; m_length == other.m_length
+            &amp;&amp; m_computedLength == other.m_computedLength;
+    }
</ins><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx">     Direction m_direction;
</span><span class="lines">@@ -138,6 +146,11 @@
</span><span class="cx"> 
</span><span class="cx">         return BasicShapeRadius(m_value.blend(other.value(), progress));
</span><span class="cx">     }
</span><ins>+    
+    bool operator==(const BasicShapeRadius&amp; other) const
+    {
+        return m_value == other.m_value &amp;&amp; m_type == other.m_type;
+    }
</ins><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx">     Length m_value;
</span><span class="lines">@@ -162,6 +175,8 @@
</span><span class="cx">     virtual Ref&lt;BasicShape&gt; blend(const BasicShape&amp;, double) const override;
</span><span class="cx"> 
</span><span class="cx">     virtual Type type() const override { return BasicShapeCircleType; }
</span><ins>+    virtual bool operator==(const BasicShape&amp;) const override;
+
</ins><span class="cx"> private:
</span><span class="cx">     BasicShapeCircle() { }
</span><span class="cx"> 
</span><span class="lines">@@ -189,6 +204,8 @@
</span><span class="cx">     virtual Ref&lt;BasicShape&gt; blend(const BasicShape&amp;, double) const override;
</span><span class="cx"> 
</span><span class="cx">     virtual Type type() const override { return BasicShapeEllipseType; }
</span><ins>+    virtual bool operator==(const BasicShape&amp;) const override;
+
</ins><span class="cx"> private:
</span><span class="cx">     BasicShapeEllipse() { }
</span><span class="cx"> 
</span><span class="lines">@@ -215,6 +232,8 @@
</span><span class="cx">     virtual WindRule windRule() const override { return m_windRule; }
</span><span class="cx"> 
</span><span class="cx">     virtual Type type() const override { return BasicShapePolygonType; }
</span><ins>+    virtual bool operator==(const BasicShape&amp;) const override;
+
</ins><span class="cx"> private:
</span><span class="cx">     BasicShapePolygon()
</span><span class="cx">         : m_windRule(RULE_NONZERO)
</span><span class="lines">@@ -252,6 +271,8 @@
</span><span class="cx">     virtual Ref&lt;BasicShape&gt; blend(const BasicShape&amp;, double) const override;
</span><span class="cx"> 
</span><span class="cx">     virtual Type type() const override { return BasicShapeInsetType; }
</span><ins>+    virtual bool operator==(const BasicShape&amp;) const override;
+
</ins><span class="cx"> private:
</span><span class="cx">     BasicShapeInset() { }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCorerenderingstyleShapeValuecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/rendering/style/ShapeValue.cpp (190878 => 190879)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/style/ShapeValue.cpp        2015-10-12 19:15:17 UTC (rev 190878)
+++ trunk/Source/WebCore/rendering/style/ShapeValue.cpp        2015-10-12 19:15:28 UTC (rev 190879)
</span><span class="lines">@@ -39,4 +39,26 @@
</span><span class="cx">     return image()-&gt;isGeneratedImage();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+template &lt;typename T&gt;
+bool pointersOrValuesEqual(T p1, T p2)
+{
+    if (p1 == p2)
+        return true;
+    
+    if (!p1 || !p2)
+        return false;
+    
+    return *p1 == *p2;
+}
+
+bool ShapeValue::operator==(const ShapeValue&amp; other) const
+{
+    if (m_type != other.m_type || m_cssBox != other.m_cssBox)
+        return false;
+
+    return pointersOrValuesEqual(m_shape.get(), other.m_shape.get())
+        &amp;&amp; pointersOrValuesEqual(m_image.get(), other.m_image.get());
+}
+
+
</ins><span class="cx"> } // namespace WebCore
</span></span></pre></div>
<a id="trunkSourceWebCorerenderingstyleShapeValueh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/rendering/style/ShapeValue.h (190878 => 190879)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/style/ShapeValue.h        2015-10-12 19:15:17 UTC (rev 190878)
+++ trunk/Source/WebCore/rendering/style/ShapeValue.h        2015-10-12 19:15:28 UTC (rev 190879)
</span><span class="lines">@@ -76,7 +76,11 @@
</span><span class="cx">             m_image = image;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    bool operator==(const ShapeValue&amp; other) const { return type() == other.type(); }
</del><ins>+    bool operator==(const ShapeValue&amp;) const;
+    bool operator!=(const ShapeValue&amp; other) const
+    {
+        return !(*this == other);
+    }
</ins><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx">     ShapeValue(PassRefPtr&lt;BasicShape&gt; shape, CSSBoxType cssBox)
</span><span class="lines">@@ -87,13 +91,11 @@
</span><span class="cx">     }
</span><span class="cx">     ShapeValue(Type type)
</span><span class="cx">         : m_type(type)
</span><del>-        , m_cssBox(BoxMissing)
</del><span class="cx">     {
</span><span class="cx">     }
</span><span class="cx">     ShapeValue(PassRefPtr&lt;StyleImage&gt; image)
</span><span class="cx">         : m_type(Type::Image)
</span><span class="cx">         , m_image(image)
</span><del>-        , m_cssBox(BoxMissing)
</del><span class="cx">     {
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -106,7 +108,7 @@
</span><span class="cx">     Type m_type;
</span><span class="cx">     RefPtr&lt;BasicShape&gt; m_shape;
</span><span class="cx">     RefPtr&lt;StyleImage&gt; m_image;
</span><del>-    CSSBoxType m_cssBox;
</del><ins>+    CSSBoxType m_cssBox { BoxMissing };
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebCorerenderingstyleStyleRareNonInheritedDatacpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/rendering/style/StyleRareNonInheritedData.cpp (190878 => 190879)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/style/StyleRareNonInheritedData.cpp        2015-10-12 19:15:17 UTC (rev 190878)
+++ trunk/Source/WebCore/rendering/style/StyleRareNonInheritedData.cpp        2015-10-12 19:15:28 UTC (rev 190879)
</span><span class="lines">@@ -243,11 +243,11 @@
</span><span class="cx">         &amp;&amp; m_maskBoxImage == o.m_maskBoxImage
</span><span class="cx">         &amp;&amp; m_pageSize == o.m_pageSize
</span><span class="cx"> #if ENABLE(CSS_SHAPES)
</span><del>-        &amp;&amp; m_shapeOutside == o.m_shapeOutside
</del><ins>+        &amp;&amp; shapeOutsideDataEquivalent(o)
</ins><span class="cx">         &amp;&amp; m_shapeMargin == o.m_shapeMargin
</span><span class="cx">         &amp;&amp; m_shapeImageThreshold == o.m_shapeImageThreshold
</span><span class="cx"> #endif
</span><del>-        &amp;&amp; m_clipPath == o.m_clipPath // FIXME: This needs to compare values.
</del><ins>+        &amp;&amp; clipPathOperationsEquivalent(o)
</ins><span class="cx">         &amp;&amp; m_textDecorationColor == o.m_textDecorationColor
</span><span class="cx">         &amp;&amp; m_visitedLinkTextDecorationColor == o.m_visitedLinkTextDecorationColor
</span><span class="cx">         &amp;&amp; m_visitedLinkBackgroundColor == o.m_visitedLinkBackgroundColor
</span><span class="lines">@@ -363,6 +363,26 @@
</span><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+bool StyleRareNonInheritedData::clipPathOperationsEquivalent(const StyleRareNonInheritedData&amp; o) const
+{
+    if ((!m_clipPath &amp;&amp; o.m_clipPath) || (m_clipPath &amp;&amp; !o.m_clipPath))
+        return false;
+    if (m_clipPath &amp;&amp; o.m_clipPath &amp;&amp; (*m_clipPath != *o.m_clipPath))
+        return false;
+    return true;
+}
+
+#if ENABLE(CSS_SHAPES)
+bool StyleRareNonInheritedData::shapeOutsideDataEquivalent(const StyleRareNonInheritedData&amp; o) const
+{
+    if ((!m_shapeOutside &amp;&amp; o.m_shapeOutside) || (m_shapeOutside &amp;&amp; !o.m_shapeOutside))
+        return false;
+    if (m_shapeOutside &amp;&amp; o.m_shapeOutside &amp;&amp; (*m_shapeOutside != *o.m_shapeOutside))
+        return false;
+    return true;
+}
+#endif
+
</ins><span class="cx"> bool StyleRareNonInheritedData::hasFilters() const
</span><span class="cx"> {
</span><span class="cx">     return m_filter.get() &amp;&amp; !m_filter-&gt;m_operations.isEmpty();
</span></span></pre></div>
<a id="trunkSourceWebCorerenderingstyleStyleRareNonInheritedDatah"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/rendering/style/StyleRareNonInheritedData.h (190878 => 190879)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/style/StyleRareNonInheritedData.h        2015-10-12 19:15:17 UTC (rev 190878)
+++ trunk/Source/WebCore/rendering/style/StyleRareNonInheritedData.h        2015-10-12 19:15:28 UTC (rev 190879)
</span><span class="lines">@@ -98,6 +98,10 @@
</span><span class="cx">     bool reflectionDataEquivalent(const StyleRareNonInheritedData&amp;) const;
</span><span class="cx">     bool animationDataEquivalent(const StyleRareNonInheritedData&amp;) const;
</span><span class="cx">     bool transitionDataEquivalent(const StyleRareNonInheritedData&amp;) const;
</span><ins>+    bool clipPathOperationsEquivalent(const StyleRareNonInheritedData&amp;) const;
+#if ENABLE(CSS_SHAPES)
+    bool shapeOutsideDataEquivalent(const StyleRareNonInheritedData&amp;) const;
+#endif
</ins><span class="cx">     bool hasFilters() const;
</span><span class="cx"> #if ENABLE(FILTERS_LEVEL_2)
</span><span class="cx">     bool hasBackdropFilters() const;
</span></span></pre>
</div>
</div>

</body>
</html>