<!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>[213603] 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/213603">213603</a></dd>
<dt>Author</dt> <dd>simon.fraser@apple.com</dd>
<dt>Date</dt> <dd>2017-03-08 15:50:43 -0800 (Wed, 08 Mar 2017)</dd>
</dl>
<h3>Log Message</h3>
<pre>Support transitions/animations of background-position with right/bottom-relative values
https://bugs.webkit.org/show_bug.cgi?id=162048
Reviewed by Dean Jackson.
Source/WebCore:
Make transitions between "background-position: 10px 20px" and "background-position: right 10px bottom 20px"
work. We do this by by converting "right 10px" to "calc(100% - 10px)" when blending.
Also improve logging of calculated lengths, and better animation logging for FillLayer properties.
Test: transitions/background-position-transitions.html
* page/animation/CSSPropertyAnimation.cpp:
(WebCore::FillLayerAnimationPropertyWrapperBase::FillLayerAnimationPropertyWrapperBase): Keep the propertyID
around so logging can use it.
(WebCore::FillLayerAnimationPropertyWrapperBase::property):
(WebCore::FillLayerPropertyWrapperGetter::FillLayerPropertyWrapperGetter):
(WebCore::FillLayerPropertyWrapperGetter::value):
(WebCore::FillLayerPropertyWrapper::FillLayerPropertyWrapper):
(WebCore::createCalculatedLength):
(WebCore::FillLayerPositionPropertyWrapper::FillLayerPositionPropertyWrapper):
(WebCore::FillLayerRefCountedPropertyWrapper::FillLayerRefCountedPropertyWrapper):
(WebCore::FillLayerStyleImagePropertyWrapper::FillLayerStyleImagePropertyWrapper):
(WebCore::FillLayersPropertyWrapper::FillLayersPropertyWrapper):
(WebCore::CSSPropertyAnimation::blendProperties): Blend then log, so that the logging
can show the result.
* platform/CalculationValue.cpp:
(WebCore::CalcExpressionNumber::dump):
(WebCore::CalcExpressionBinaryOperation::dump):
(WebCore::CalcExpressionLength::dump):
(WebCore::CalcExpressionBlendLength::dump):
(WebCore::operator<<):
* platform/CalculationValue.h:
* platform/Length.cpp:
(WebCore::operator<<):
LayoutTests:
* transitions/background-position-transitions-expected.txt: Added.
* transitions/background-position-transitions.html: Added.
* transitions/resources/transition-test-helpers.js:
* transitions/svg-transitions-expected.txt:</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestsfastshapesshapeoutsidefloatsshapeoutsideanimationexpectedtxt">trunk/LayoutTests/fast/shapes/shape-outside-floats/shape-outside-animation-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfastshapesshapeoutsidefloatsshapeoutsideanimationhtml">trunk/LayoutTests/fast/shapes/shape-outside-floats/shape-outside-animation.html</a></li>
<li><a href="#trunkLayoutTeststransitionsresourcestransitiontesthelpersjs">trunk/LayoutTests/transitions/resources/transition-test-helpers.js</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="#trunkSourceWebCoreplatformCalculationValuecpp">trunk/Source/WebCore/platform/CalculationValue.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformCalculationValueh">trunk/Source/WebCore/platform/CalculationValue.h</a></li>
<li><a href="#trunkSourceWebCoreplatformLengthcpp">trunk/Source/WebCore/platform/Length.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformLengthh">trunk/Source/WebCore/platform/Length.h</a></li>
<li><a href="#trunkSourceWebCorerenderingstyleBasicShapescpp">trunk/Source/WebCore/rendering/style/BasicShapes.cpp</a></li>
<li><a href="#trunkToolsTestWebKitAPITestsWebCoreCalculationValuecpp">trunk/Tools/TestWebKitAPI/Tests/WebCore/CalculationValue.cpp</a></li>
</ul>
<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTeststransitionsbackgroundpositiontransitionsexpectedtxt">trunk/LayoutTests/transitions/background-position-transitions-expected.txt</a></li>
<li><a href="#trunkLayoutTeststransitionsbackgroundpositiontransitionshtml">trunk/LayoutTests/transitions/background-position-transitions.html</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (213602 => 213603)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2017-03-08 23:31:24 UTC (rev 213602)
+++ trunk/LayoutTests/ChangeLog        2017-03-08 23:50:43 UTC (rev 213603)
</span><span class="lines">@@ -1,5 +1,19 @@
</span><span class="cx"> 2017-03-08 Simon Fraser <simon.fraser@apple.com>
</span><span class="cx">
</span><ins>+ Support transitions/animations of background-position with right/bottom-relative values
+ https://bugs.webkit.org/show_bug.cgi?id=162048
+
+ Reviewed by Dean Jackson.
+
+ Re-landing r206713.
+
+ * transitions/background-position-transitions-expected.txt: Added.
+ * transitions/background-position-transitions.html: Added.
+ * transitions/resources/transition-test-helpers.js:
+ * transitions/svg-transitions-expected.txt:
+
+2017-03-08 Simon Fraser <simon.fraser@apple.com>
+
</ins><span class="cx"> Change determineNonLayerDescendantsPaintedContent to max out based on renderers traversed
</span><span class="cx"> https://bugs.webkit.org/show_bug.cgi?id=169384
</span><span class="cx">
</span></span></pre></div>
<a id="trunkLayoutTestsfastshapesshapeoutsidefloatsshapeoutsideanimationexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/fast/shapes/shape-outside-floats/shape-outside-animation-expected.txt (213602 => 213603)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/shapes/shape-outside-floats/shape-outside-animation-expected.txt        2017-03-08 23:31:24 UTC (rev 213602)
+++ trunk/LayoutTests/fast/shapes/shape-outside-floats/shape-outside-animation-expected.txt        2017-03-08 23:50:43 UTC (rev 213603)
</span><span class="lines">@@ -22,6 +22,6 @@
</span><span class="cx"> PASS - "webkitShapeOutside" property for "circle-to-bottomright-using-keyword-box" element at 1s saw something close to: circle(35% at calc((50% * 0.5) + ((100% - 0px) * 0.5)) calc((50% * 0.5) + ((100% - 0px) * 0.5)))
</span><span class="cx"> PASS - "webkitShapeOutside" property for "circle-to-bottomright-using-keyword-box" element at 1s saw something close to: circle(35% at calc((50% * 0.5) + ((100% - 0px) * 0.5)) calc((50% * 0.5) + ((100% - 0px) * 0.5)))
</span><span class="cx"> PASS - "webkitShapeOutside" property for "circle-to-bottomright-extended-box" element at 1s saw something close to: circle(35% at 75% 75%)
</span><del>-PASS - "webkitShapeOutside" property for "circle-to-bottomright-extended-using-keyword-box" element at 1s saw something close to: circle(35% at calc((50% * 0.5) + ((100% - 10%) * 0.5)) calc((50% * 0.5) + ((100% - 20px) * 0.5)))
-PASS - "webkitShapeOutside" property for "circle-to-bottomright-extended-using-keyword-2-box" element at 1s saw something close to: circle(35% at calc((50% * 0.5) + ((100% - 10%) * 0.5)) calc((50% * 0.5) + ((100% - 10px) * 0.5)))
</del><ins>+PASS - "webkitShapeOutside" property for "circle-to-bottomright-extended-using-keyword-box" element at 1s saw something close to: circle(35% at 70% calc((50% * 0.5) + ((100% - 20px) * 0.5)))
+PASS - "webkitShapeOutside" property for "circle-to-bottomright-extended-using-keyword-2-box" element at 1s saw something close to: circle(35% at 70% calc((50% * 0.5) + ((100% - 10px) * 0.5)))
</ins><span class="cx">
</span></span></pre></div>
<a id="trunkLayoutTestsfastshapesshapeoutsidefloatsshapeoutsideanimationhtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/fast/shapes/shape-outside-floats/shape-outside-animation.html (213602 => 213603)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/shapes/shape-outside-floats/shape-outside-animation.html        2017-03-08 23:31:24 UTC (rev 213602)
+++ trunk/LayoutTests/fast/shapes/shape-outside-floats/shape-outside-animation.html        2017-03-08 23:50:43 UTC (rev 213603)
</span><span class="lines">@@ -146,8 +146,8 @@
</span><span class="cx"> ["circle-to-bottomright-using-keyword-anim", 1, "circle-to-bottomright-using-keyword-box", "webkitShapeOutside", "circle(35% at calc((50% * 0.5) + ((100% - 0px) * 0.5)) calc((50% * 0.5) + ((100% - 0px) * 0.5)))", 0.05],
</span><span class="cx"> ["circle-to-bottomright-using-keyword-anim", 1, "circle-to-bottomright-using-keyword-box", "webkitShapeOutside", "circle(35% at calc((50% * 0.5) + ((100% - 0px) * 0.5)) calc((50% * 0.5) + ((100% - 0px) * 0.5)))", 0.05],
</span><span class="cx"> ["circle-to-bottomright-extended-anim", 1, "circle-to-bottomright-extended-box", "webkitShapeOutside", "circle(35% at 75% 75%)", 0.05],
</span><del>- ["circle-to-bottomright-extended-using-keyword-anim", 1, "circle-to-bottomright-extended-using-keyword-box", "webkitShapeOutside", "circle(35% at calc((50% * 0.5) + ((100% - 10%) * 0.5)) calc((50% * 0.5) + ((100% - 20px) * 0.5)))", 0.01],
- ["circle-to-bottomright-extended-using-keyword-2-anim", 1, "circle-to-bottomright-extended-using-keyword-2-box", "webkitShapeOutside", "circle(35% at calc((50% * 0.5) + ((100% - 10%) * 0.5)) calc((50% * 0.5) + ((100% - 10px) * 0.5)))", 0.01],
</del><ins>+ ["circle-to-bottomright-extended-using-keyword-anim", 1, "circle-to-bottomright-extended-using-keyword-box", "webkitShapeOutside", "circle(35% at 70% calc((50% * 0.5) + ((100% - 20px) * 0.5)))", 0.01],
+ ["circle-to-bottomright-extended-using-keyword-2-anim", 1, "circle-to-bottomright-extended-using-keyword-2-box", "webkitShapeOutside", "circle(35% at 70% calc((50% * 0.5) + ((100% - 10px) * 0.5)))", 0.01],
</ins><span class="cx"> ];
</span><span class="cx">
</span><span class="cx"> runAnimationTest(expectedValues);
</span></span></pre></div>
<a id="trunkLayoutTeststransitionsbackgroundpositiontransitionsexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/transitions/background-position-transitions-expected.txt (0 => 213603)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/transitions/background-position-transitions-expected.txt         (rev 0)
+++ trunk/LayoutTests/transitions/background-position-transitions-expected.txt        2017-03-08 23:50:43 UTC (rev 213603)
</span><span class="lines">@@ -0,0 +1,4 @@
</span><ins>+PASS - "background-position" property for "box1" element at 0.5s saw something close to: 45,60
+PASS - "background-position" property for "box2" element at 0.5s saw something close to: 45,60
+PASS - "background-position" property for "box3" element at 0.5s saw something close to: 10,0.5,100,80,0,0.5,20,0.5,100,100,0,0.5
+
</ins></span></pre></div>
<a id="trunkLayoutTeststransitionsbackgroundpositiontransitionshtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/transitions/background-position-transitions.html (0 => 213603)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/transitions/background-position-transitions.html         (rev 0)
+++ trunk/LayoutTests/transitions/background-position-transitions.html        2017-03-08 23:50:43 UTC (rev 213603)
</span><span class="lines">@@ -0,0 +1,66 @@
</span><ins>+<!DOCTYPE>
+
+<html>
+<head>
+ <style>
+ .box {
+ height: 100px;
+ width: 100px;
+ margin: 10px;
+ background: url('../fast/backgrounds/repeat/resources/gradient.gif') repeat 0 0;
+ transition-duration: 1s;
+ transition-timing-function: linear;
+ transition-property: background-position;
+ }
+
+ #box1 {
+ background-position: 10px 20px;
+ }
+
+ body.final #box1 {
+ background-position: left 80px top 100px;
+ }
+
+ #box2 {
+ background-position: right 10px bottom 20px;
+ }
+
+ body.final #box2 {
+ background-position: right 80px bottom 100px;
+ }
+
+ #box3 {
+ background-position: 10px 20px;
+ }
+
+ body.final #box3 {
+ background-position: right 80px bottom 100px;
+ }
+ </style>
+ <script src="resources/transition-test-helpers.js" type="text/javascript"></script>
+ <script>
+ const expectedValues = [
+ // [time, element-id, property, expected-value, tolerance]
+ [0.5, 'box1', 'background-position', [45, 60], 2],
+ [0.5, 'box2', 'background-position', [45, 60], 2],
+ [0.5, 'box3', 'background-position', [10,0.5,100,80,0,0.5,20,0.5,100,100,0,0.5], 2], // Numbers extracted from a calc() expression.
+ ];
+
+ function setupTest()
+ {
+ document.body.classList.add('final');
+ }
+
+ runTransitionTest(expectedValues, setupTest, usePauseAPI);
+ </script>
+</head>
+<body>
+
+ <div id="box1" class="box"></div>
+ <div id="box2" class="box"></div>
+ <div id="box3" class="box"></div>
+
+ <pre id="result"></pre>
+
+</body>
+</html>
</ins></span></pre></div>
<a id="trunkLayoutTeststransitionsresourcestransitiontesthelpersjs"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/transitions/resources/transition-test-helpers.js (213602 => 213603)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/transitions/resources/transition-test-helpers.js        2017-03-08 23:31:24 UTC (rev 213602)
+++ trunk/LayoutTests/transitions/resources/transition-test-helpers.js        2017-03-08 23:50:43 UTC (rev 213603)
</span><span class="lines">@@ -110,6 +110,77 @@
</span><span class="cx"> return null;
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+function hasFloatValue(value)
+{
+ switch (value.primitiveType) {
+ case CSSPrimitiveValue.CSS_FR:
+ case CSSPrimitiveValue.CSS_NUMBER:
+ case CSSPrimitiveValue.CSS_PARSER_INTEGER:
+ case CSSPrimitiveValue.CSS_PERCENTAGE:
+ case CSSPrimitiveValue.CSS_EMS:
+ case CSSPrimitiveValue.CSS_EXS:
+ case CSSPrimitiveValue.CSS_CHS:
+ case CSSPrimitiveValue.CSS_REMS:
+ case CSSPrimitiveValue.CSS_PX:
+ case CSSPrimitiveValue.CSS_CM:
+ case CSSPrimitiveValue.CSS_MM:
+ case CSSPrimitiveValue.CSS_IN:
+ case CSSPrimitiveValue.CSS_PT:
+ case CSSPrimitiveValue.CSS_PC:
+ case CSSPrimitiveValue.CSS_DEG:
+ case CSSPrimitiveValue.CSS_RAD:
+ case CSSPrimitiveValue.CSS_GRAD:
+ case CSSPrimitiveValue.CSS_TURN:
+ case CSSPrimitiveValue.CSS_MS:
+ case CSSPrimitiveValue.CSS_S:
+ case CSSPrimitiveValue.CSS_HZ:
+ case CSSPrimitiveValue.CSS_KHZ:
+ case CSSPrimitiveValue.CSS_DIMENSION:
+ case CSSPrimitiveValue.CSS_VW:
+ case CSSPrimitiveValue.CSS_VH:
+ case CSSPrimitiveValue.CSS_VMIN:
+ case CSSPrimitiveValue.CSS_VMAX:
+ case CSSPrimitiveValue.CSS_DPPX:
+ case CSSPrimitiveValue.CSS_DPI:
+ case CSSPrimitiveValue.CSS_DPCM:
+ return true;
+ }
+ return false;
+}
+
+function getNumericValue(cssValue)
+{
+ if (hasFloatValue(cssValue.primitiveType))
+ return cssValue.getFloatValue(cssValue.primitiveType);
+
+ return -1;
+}
+
+function isCalcPrimitiveValue(value)
+{
+ switch (value.primitiveType) {
+ case 113: // CSSPrimitiveValue.CSS_CALC:
+ case 114: // CSSPrimitiveValue.CSS_CALC_PERCENTAGE_WITH_NUMBER:
+ case 115: // CSSPrimitiveValue.CSS_CALC_PERCENTAGE_WITH_LENGTH:
+ return true;
+ }
+ return false;
+}
+
+function extractNumbersFromCalcExpression(value, values)
+{
+ var calcRegexp = /^calc\((.+)\)$/;
+ var result = calcRegexp.exec(value.cssText);
+ var numberMatch = /([^\.\-0-9]*)(-?[\.0-9]+)/;
+ var remainder = result[1];
+ var match;
+ while ((match = numberMatch.exec(remainder)) !== null) {
+ var skipLength = match[1].length + match[2].length;
+ values.push(parseFloat(match[2]))
+ remainder = remainder.substr(skipLength + 1);
+ }
+}
+
</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">@@ -194,23 +265,27 @@
</span><span class="cx"> if (computedStyle.cssValueType == CSSValue.CSS_VALUE_LIST) {
</span><span class="cx"> var values = [];
</span><span class="cx"> for (var i = 0; i < computedStyle.length; ++i) {
</span><del>- switch (computedStyle[i].cssValueType) {
</del><ins>+ var styleValue = computedStyle[i];
+ switch (styleValue.cssValueType) {
</ins><span class="cx"> case CSSValue.CSS_PRIMITIVE_VALUE:
</span><del>- values.push(computedStyle[i].getFloatValue(CSSPrimitiveValue.CSS_NUMBER));
</del><ins>+ if (hasFloatValue(styleValue))
+ values.push(styleValue.getFloatValue(CSSPrimitiveValue.CSS_NUMBER));
+ else if (isCalcPrimitiveValue(styleValue))
+ extractNumbersFromCalcExpression(styleValue, values);
</ins><span class="cx"> break;
</span><span class="cx"> case CSSValue.CSS_CUSTOM:
</span><span class="cx"> // arbitrarily pick shadow-x and shadow-y
</span><span class="cx"> if (isShadow) {
</span><del>- var shadowXY = getShadowXY(computedStyle[i]);
</del><ins>+ var shadowXY = getShadowXY(styleValue);
</ins><span class="cx"> values.push(shadowXY[0]);
</span><span class="cx"> values.push(shadowXY[1]);
</span><span class="cx"> } else
</span><del>- values.push(computedStyle[i].cssText);
</del><ins>+ values.push(styleValue.cssText);
</ins><span class="cx"> break;
</span><span class="cx"> }
</span><span class="cx"> }
</span><span class="cx"> computedValue = values.join(',');
</span><del>- pass = true;
</del><ins>+ pass = values.length > 0;
</ins><span class="cx"> for (var i = 0; i < values.length; ++i)
</span><span class="cx"> pass &= isCloseEnough(values[i], expectedValue[i], tolerance);
</span><span class="cx"> } else if (computedStyle.cssValueType == CSSValue.CSS_PRIMITIVE_VALUE) {
</span></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (213602 => 213603)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2017-03-08 23:31:24 UTC (rev 213602)
+++ trunk/Source/WebCore/ChangeLog        2017-03-08 23:50:43 UTC (rev 213603)
</span><span class="lines">@@ -1,3 +1,43 @@
</span><ins>+2017-03-08 Simon Fraser <simon.fraser@apple.com>
+
+ Support transitions/animations of background-position with right/bottom-relative values
+ https://bugs.webkit.org/show_bug.cgi?id=162048
+
+ Reviewed by Dean Jackson.
+
+ Re-landing r206713.
+
+ Make transitions between "background-position: 10px 20px" and "background-position: right 10px bottom 20px"
+ work. We do this by by converting "right 10px" to "calc(100% - 10px)" when blending.
+
+ Also improve logging of calculated lengths, and better animation logging for FillLayer properties.
+
+ Test: transitions/background-position-transitions.html
+
+ * page/animation/CSSPropertyAnimation.cpp:
+ (WebCore::FillLayerAnimationPropertyWrapperBase::FillLayerAnimationPropertyWrapperBase): Keep the propertyID
+ around so logging can use it.
+ (WebCore::FillLayerAnimationPropertyWrapperBase::property):
+ (WebCore::FillLayerPropertyWrapperGetter::FillLayerPropertyWrapperGetter):
+ (WebCore::FillLayerPropertyWrapperGetter::value):
+ (WebCore::FillLayerPropertyWrapper::FillLayerPropertyWrapper):
+ (WebCore::createCalculatedLength):
+ (WebCore::FillLayerPositionPropertyWrapper::FillLayerPositionPropertyWrapper):
+ (WebCore::FillLayerRefCountedPropertyWrapper::FillLayerRefCountedPropertyWrapper):
+ (WebCore::FillLayerStyleImagePropertyWrapper::FillLayerStyleImagePropertyWrapper):
+ (WebCore::FillLayersPropertyWrapper::FillLayersPropertyWrapper):
+ (WebCore::CSSPropertyAnimation::blendProperties): Blend then log, so that the logging
+ can show the result.
+ * platform/CalculationValue.cpp:
+ (WebCore::CalcExpressionNumber::dump):
+ (WebCore::CalcExpressionBinaryOperation::dump):
+ (WebCore::CalcExpressionLength::dump):
+ (WebCore::CalcExpressionBlendLength::dump):
+ (WebCore::operator<<):
+ * platform/CalculationValue.h:
+ * platform/Length.cpp:
+ (WebCore::operator<<):
+
</ins><span class="cx"> 2017-03-08 Anders Carlsson <andersca@apple.com>
</span><span class="cx">
</span><span class="cx"> Simplify the PaymentCoordinator interface
</span></span></pre></div>
<a id="trunkSourceWebCorepageanimationCSSPropertyAnimationcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/page/animation/CSSPropertyAnimation.cpp (213602 => 213603)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/page/animation/CSSPropertyAnimation.cpp        2017-03-08 23:31:24 UTC (rev 213602)
+++ trunk/Source/WebCore/page/animation/CSSPropertyAnimation.cpp        2017-03-08 23:50:43 UTC (rev 213603)
</span><span class="lines">@@ -39,6 +39,7 @@
</span><span class="cx"> #include "CSSPrimitiveValue.h"
</span><span class="cx"> #include "CSSPropertyNames.h"
</span><span class="cx"> #include "CachedImage.h"
</span><ins>+#include "CalculationValue.h"
</ins><span class="cx"> #include "ClipPathOperation.h"
</span><span class="cx"> #include "FloatConversion.h"
</span><span class="cx"> #include "FontTaggedSettings.h"
</span><span class="lines">@@ -957,14 +958,23 @@
</span><span class="cx"> class FillLayerAnimationPropertyWrapperBase {
</span><span class="cx"> WTF_MAKE_FAST_ALLOCATED;
</span><span class="cx"> public:
</span><del>- FillLayerAnimationPropertyWrapperBase()
</del><ins>+ FillLayerAnimationPropertyWrapperBase(CSSPropertyID property)
+ : m_property(property)
</ins><span class="cx"> {
</span><span class="cx"> }
</span><ins>+
+ CSSPropertyID property() const { return m_property; }
</ins><span class="cx">
</span><span class="cx"> virtual ~FillLayerAnimationPropertyWrapperBase() { }
</span><span class="cx">
</span><span class="cx"> virtual bool equals(const FillLayer*, const FillLayer*) const = 0;
</span><span class="cx"> virtual void blend(const AnimationBase*, FillLayer*, const FillLayer*, const FillLayer*, double) const = 0;
</span><ins>+
+#if !LOG_DISABLED
+ virtual void logBlend(const FillLayer* result, const FillLayer*, const FillLayer*, double) const = 0;
+#endif
+private:
+ CSSPropertyID m_property;
</ins><span class="cx"> };
</span><span class="cx">
</span><span class="cx"> template <typename T>
</span><span class="lines">@@ -972,8 +982,9 @@
</span><span class="cx"> WTF_MAKE_FAST_ALLOCATED;
</span><span class="cx"> WTF_MAKE_NONCOPYABLE(FillLayerPropertyWrapperGetter);
</span><span class="cx"> public:
</span><del>- FillLayerPropertyWrapperGetter(T (FillLayer::*getter)() const)
- : m_getter(getter)
</del><ins>+ FillLayerPropertyWrapperGetter(CSSPropertyID property, T (FillLayer::*getter)() const)
+ : FillLayerAnimationPropertyWrapperBase(property)
+ , m_getter(getter)
</ins><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -986,6 +997,18 @@
</span><span class="cx"> return (a->*m_getter)() == (b->*m_getter)();
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+ T value(const FillLayer* layer) const
+ {
+ return (layer->*m_getter)();
+ }
+
+#if !LOG_DISABLED
+ void logBlend(const FillLayer* result, const FillLayer* a, const FillLayer* b, double progress) const override
+ {
+ LOG_WITH_STREAM(Animations, stream << " blending " << getPropertyName(property()) << " from " << value(a) << " to " << value(b) << " at " << TextStream::FormatNumberRespectingIntegers(progress) << " -> " << value(result));
+ }
+#endif
+
</ins><span class="cx"> protected:
</span><span class="cx"> T (FillLayer::*m_getter)() const;
</span><span class="cx"> };
</span><span class="lines">@@ -994,8 +1017,8 @@
</span><span class="cx"> class FillLayerPropertyWrapper : public FillLayerPropertyWrapperGetter<const T&> {
</span><span class="cx"> WTF_MAKE_FAST_ALLOCATED;
</span><span class="cx"> public:
</span><del>- FillLayerPropertyWrapper(const T& (FillLayer::*getter)() const, void (FillLayer::*setter)(T))
- : FillLayerPropertyWrapperGetter<const T&>(getter)
</del><ins>+ FillLayerPropertyWrapper(CSSPropertyID property, const T& (FillLayer::*getter)() const, void (FillLayer::*setter)(T))
+ : FillLayerPropertyWrapperGetter<const T&>(property, getter)
</ins><span class="cx"> , m_setter(setter)
</span><span class="cx"> {
</span><span class="cx"> }
</span><span class="lines">@@ -1005,16 +1028,89 @@
</span><span class="cx"> (dst->*m_setter)(blendFunc(anim, (a->*FillLayerPropertyWrapperGetter<const T&>::m_getter)(), (b->*FillLayerPropertyWrapperGetter<const T&>::m_getter)(), progress));
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+#if !LOG_DISABLED
+ void logBlend(const FillLayer* result, const FillLayer* a, const FillLayer* b, double progress) const override
+ {
+ LOG_WITH_STREAM(Animations, stream << " blending " << getPropertyName(FillLayerPropertyWrapperGetter<const T&>::property())
+ << " from " << FillLayerPropertyWrapperGetter<const T&>::value(a)
+ << " to " << FillLayerPropertyWrapperGetter<const T&>::value(b)
+ << " at " << TextStream::FormatNumberRespectingIntegers(progress) << " -> " << FillLayerPropertyWrapperGetter<const T&>::value(result));
+ }
+#endif
+
</ins><span class="cx"> protected:
</span><span class="cx"> void (FillLayer::*m_setter)(T);
</span><span class="cx"> };
</span><span class="cx">
</span><ins>+class FillLayerPositionPropertyWrapper : public FillLayerPropertyWrapperGetter<const Length&> {
+ WTF_MAKE_FAST_ALLOCATED;
+public:
+ FillLayerPositionPropertyWrapper(CSSPropertyID property, const Length& (FillLayer::*lengthGetter)() const, void (FillLayer::*lengthSetter)(Length), Edge (FillLayer::*originGetter)() const, void (FillLayer::*originSetter)(Edge), Edge farEdge)
+ : FillLayerPropertyWrapperGetter<const Length&>(property, lengthGetter)
+ , m_lengthSetter(lengthSetter)
+ , m_originGetter(originGetter)
+ , m_originSetter(originSetter)
+ , m_farEdge(farEdge)
+ {
+ }
+
+ bool equals(const FillLayer* a, const FillLayer* b) const override
+ {
+ if (a == b)
+ return true;
+ if (!a || !b)
+ return false;
+
+ Length fromLength = (a->*FillLayerPropertyWrapperGetter<const Length&>::m_getter)();
+ Length toLength = (b->*FillLayerPropertyWrapperGetter<const Length&>::m_getter)();
+
+ Edge fromEdge = (a->*m_originGetter)();
+ Edge toEdge = (b->*m_originGetter)();
+
+ return fromLength == toLength && fromEdge == toEdge;
+ }
+
+ void blend(const AnimationBase* anim, FillLayer* dst, const FillLayer* a, const FillLayer* b, double progress) const override
+ {
+ Length fromLength = (a->*FillLayerPropertyWrapperGetter<const Length&>::m_getter)();
+ Length toLength = (b->*FillLayerPropertyWrapperGetter<const Length&>::m_getter)();
+
+ Edge fromEdge = (a->*m_originGetter)();
+ Edge toEdge = (b->*m_originGetter)();
+
+ if (fromEdge != toEdge) {
+ // Convert the right/bottom into a calc expression,
+ if (fromEdge == m_farEdge)
+ fromLength = convertTo100PercentMinusLength(fromLength);
+ else if (toEdge == m_farEdge) {
+ toLength = convertTo100PercentMinusLength(toLength);
+ (dst->*m_originSetter)(fromEdge); // Now we have a calc(100% - l), it's relative to the left/top edge.
+ }
+ }
+
+ (dst->*m_lengthSetter)(blendFunc(anim, fromLength, toLength, progress));
+ }
+
+#if !LOG_DISABLED
+ void logBlend(const FillLayer* result, const FillLayer* a, const FillLayer* b, double progress) const override
+ {
+ LOG_WITH_STREAM(Animations, stream << " blending " << getPropertyName(property()) << " from " << value(a) << " to " << value(b) << " at " << TextStream::FormatNumberRespectingIntegers(progress) << " -> " << value(result));
+ }
+#endif
+
+protected:
+ void (FillLayer::*m_lengthSetter)(Length);
+ Edge (FillLayer::*m_originGetter)() const;
+ void (FillLayer::*m_originSetter)(Edge);
+ Edge m_farEdge;
+};
+
</ins><span class="cx"> template <typename T>
</span><span class="cx"> class FillLayerRefCountedPropertyWrapper : public FillLayerPropertyWrapperGetter<T*> {
</span><span class="cx"> WTF_MAKE_FAST_ALLOCATED;
</span><span class="cx"> public:
</span><del>- FillLayerRefCountedPropertyWrapper(T* (FillLayer::*getter)() const, void (FillLayer::*setter)(RefPtr<T>&&))
- : FillLayerPropertyWrapperGetter<T*>(getter)
</del><ins>+ FillLayerRefCountedPropertyWrapper(CSSPropertyID property, T* (FillLayer::*getter)() const, void (FillLayer::*setter)(RefPtr<T>&&))
+ : FillLayerPropertyWrapperGetter<T*>(property, getter)
</ins><span class="cx"> , m_setter(setter)
</span><span class="cx"> {
</span><span class="cx"> }
</span><span class="lines">@@ -1024,6 +1120,16 @@
</span><span class="cx"> (dst->*m_setter)(blendFunc(anim, (a->*FillLayerPropertyWrapperGetter<T*>::m_getter)(), (b->*FillLayerPropertyWrapperGetter<T*>::m_getter)(), progress));
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+#if !LOG_DISABLED
+ void logBlend(const FillLayer* result, const FillLayer* a, const FillLayer* b, double progress) const override
+ {
+ LOG_WITH_STREAM(Animations, stream << " blending " << getPropertyName(FillLayerPropertyWrapperGetter<T*>::property())
+ << " from " << FillLayerPropertyWrapperGetter<T*>::value(a)
+ << " to " << FillLayerPropertyWrapperGetter<T*>::value(b)
+ << " at " << TextStream::FormatNumberRespectingIntegers(progress) << " -> " << FillLayerPropertyWrapperGetter<T*>::value(result));
+ }
+#endif
+
</ins><span class="cx"> protected:
</span><span class="cx"> void (FillLayer::*m_setter)(RefPtr<T>&&);
</span><span class="cx"> };
</span><span class="lines">@@ -1031,8 +1137,8 @@
</span><span class="cx"> class FillLayerStyleImagePropertyWrapper : public FillLayerRefCountedPropertyWrapper<StyleImage> {
</span><span class="cx"> WTF_MAKE_FAST_ALLOCATED;
</span><span class="cx"> public:
</span><del>- FillLayerStyleImagePropertyWrapper(StyleImage* (FillLayer::*getter)() const, void (FillLayer::*setter)(RefPtr<StyleImage>&&))
- : FillLayerRefCountedPropertyWrapper<StyleImage>(getter, setter)
</del><ins>+ FillLayerStyleImagePropertyWrapper(CSSPropertyID property, StyleImage* (FillLayer::*getter)() const, void (FillLayer::*setter)(RefPtr<StyleImage>&&))
+ : FillLayerRefCountedPropertyWrapper<StyleImage>(property, getter, setter)
</ins><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -1047,6 +1153,13 @@
</span><span class="cx"> StyleImage* imageB = (b->*m_getter)();
</span><span class="cx"> return arePointingToEqualData(imageA, imageB);
</span><span class="cx"> }
</span><ins>+
+#if !LOG_DISABLED
+ void logBlend(const FillLayer* result, const FillLayer* a, const FillLayer* b, double progress) const override
+ {
+ LOG_WITH_STREAM(Animations, stream << " blending " << getPropertyName(property()) << " from " << value(a) << " to " << value(b) << " at " << TextStream::FormatNumberRespectingIntegers(progress) << " -> " << value(result));
+ }
+#endif
</ins><span class="cx"> };
</span><span class="cx">
</span><span class="cx"> class FillLayersPropertyWrapper : public AnimationPropertyWrapperBase {
</span><span class="lines">@@ -1055,27 +1168,27 @@
</span><span class="cx"> typedef const FillLayer& (RenderStyle::*LayersGetter)() const;
</span><span class="cx"> typedef FillLayer& (RenderStyle::*LayersAccessor)();
</span><span class="cx">
</span><del>- FillLayersPropertyWrapper(CSSPropertyID prop, LayersGetter getter, LayersAccessor accessor)
- : AnimationPropertyWrapperBase(prop)
</del><ins>+ FillLayersPropertyWrapper(CSSPropertyID property, LayersGetter getter, LayersAccessor accessor)
+ : AnimationPropertyWrapperBase(property)
</ins><span class="cx"> , m_layersGetter(getter)
</span><span class="cx"> , m_layersAccessor(accessor)
</span><span class="cx"> {
</span><del>- switch (prop) {
</del><ins>+ switch (property) {
</ins><span class="cx"> case CSSPropertyBackgroundPositionX:
</span><span class="cx"> case CSSPropertyWebkitMaskPositionX:
</span><del>- m_fillLayerPropertyWrapper = std::make_unique<FillLayerPropertyWrapper<Length>>(&FillLayer::xPosition, &FillLayer::setXPosition);
</del><ins>+ m_fillLayerPropertyWrapper = std::make_unique<FillLayerPositionPropertyWrapper>(property, &FillLayer::xPosition, &FillLayer::setXPosition, &FillLayer::backgroundXOrigin, &FillLayer::setBackgroundXOrigin, Edge::Right);
</ins><span class="cx"> break;
</span><span class="cx"> case CSSPropertyBackgroundPositionY:
</span><span class="cx"> case CSSPropertyWebkitMaskPositionY:
</span><del>- m_fillLayerPropertyWrapper = std::make_unique<FillLayerPropertyWrapper<Length>>(&FillLayer::yPosition, &FillLayer::setYPosition);
</del><ins>+ m_fillLayerPropertyWrapper = std::make_unique<FillLayerPositionPropertyWrapper>(property, &FillLayer::yPosition, &FillLayer::setYPosition, &FillLayer::backgroundYOrigin, &FillLayer::setBackgroundYOrigin, Edge::Bottom);
</ins><span class="cx"> break;
</span><span class="cx"> case CSSPropertyBackgroundSize:
</span><span class="cx"> case CSSPropertyWebkitBackgroundSize:
</span><span class="cx"> case CSSPropertyWebkitMaskSize:
</span><del>- m_fillLayerPropertyWrapper = std::make_unique<FillLayerPropertyWrapper<LengthSize>>(&FillLayer::sizeLength, &FillLayer::setSizeLength);
</del><ins>+ m_fillLayerPropertyWrapper = std::make_unique<FillLayerPropertyWrapper<LengthSize>>(property, &FillLayer::sizeLength, &FillLayer::setSizeLength);
</ins><span class="cx"> break;
</span><span class="cx"> case CSSPropertyBackgroundImage:
</span><del>- m_fillLayerPropertyWrapper = std::make_unique<FillLayerStyleImagePropertyWrapper>(&FillLayer::image, &FillLayer::setImage);
</del><ins>+ m_fillLayerPropertyWrapper = std::make_unique<FillLayerStyleImagePropertyWrapper>(property, &FillLayer::image, &FillLayer::setImage);
</ins><span class="cx"> break;
</span><span class="cx"> default:
</span><span class="cx"> break;
</span><span class="lines">@@ -1118,10 +1231,18 @@
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> #if !LOG_DISABLED
</span><del>- void logBlend(const RenderStyle*, const RenderStyle*, const RenderStyle*, double progress) const final
</del><ins>+ void logBlend(const RenderStyle* from, const RenderStyle* to, const RenderStyle* result, double progress) const final
</ins><span class="cx"> {
</span><del>- // FIXME: better logging.
- LOG_WITH_STREAM(Animations, stream << " blending FillLayers at " << TextStream::FormatNumberRespectingIntegers(progress));
</del><ins>+ auto* aLayer = &(from->*m_layersGetter)();
+ auto* bLayer = &(to->*m_layersGetter)();
+ auto* dstLayer = &(result->*m_layersGetter)();
+
+ while (aLayer && bLayer && dstLayer) {
+ m_fillLayerPropertyWrapper->logBlend(dstLayer, aLayer, bLayer, progress);
+ aLayer = aLayer->next();
+ bLayer = bLayer->next();
+ dstLayer = dstLayer->next();
+ }
</ins><span class="cx"> }
</span><span class="cx"> #endif
</span><span class="cx">
</span><span class="lines">@@ -1164,10 +1285,10 @@
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> #if !LOG_DISABLED
</span><del>- void logBlend(const RenderStyle*, const RenderStyle*, const RenderStyle*, double progress) const final
</del><ins>+ void logBlend(const RenderStyle* a, const RenderStyle* b, const RenderStyle* dst, double progress) const final
</ins><span class="cx"> {
</span><del>- // FIXME: better logging.
- LOG_WITH_STREAM(Animations, stream << " blending shorthand property " << getPropertyName(property()) << " at " << TextStream::FormatNumberRespectingIntegers(progress));
</del><ins>+ for (auto& wrapper : m_propertyWrappers)
+ wrapper->logBlend(a, b, dst, progress);
</ins><span class="cx"> }
</span><span class="cx"> #endif
</span><span class="cx">
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformCalculationValuecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/CalculationValue.cpp (213602 => 213603)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/CalculationValue.cpp        2017-03-08 23:31:24 UTC (rev 213602)
+++ trunk/Source/WebCore/platform/CalculationValue.cpp        2017-03-08 23:50:43 UTC (rev 213603)
</span><span class="lines">@@ -31,6 +31,7 @@
</span><span class="cx">
</span><span class="cx"> #include "config.h"
</span><span class="cx"> #include "CalculationValue.h"
</span><ins>+#include "TextStream.h"
</ins><span class="cx">
</span><span class="cx"> #include <limits>
</span><span class="cx">
</span><span class="lines">@@ -46,6 +47,11 @@
</span><span class="cx"> return m_value;
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+void CalcExpressionNumber::dump(TextStream& ts) const
+{
+ ts << TextStream::FormatNumberRespectingIntegers(m_value);
+}
+
</ins><span class="cx"> bool CalcExpressionNumber::operator==(const CalcExpressionNode& other) const
</span><span class="cx"> {
</span><span class="cx"> return other.type() == CalcExpressionNodeNumber && *this == toCalcExpressionNumber(other);
</span><span class="lines">@@ -86,6 +92,11 @@
</span><span class="cx"> return other.type() == CalcExpressionNodeBinaryOperation && *this == toCalcExpressionBinaryOperation(other);
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+void CalcExpressionBinaryOperation::dump(TextStream& ts) const
+{
+ ts << *m_leftSide << " " << m_operator << " " << *m_rightSide;
+}
+
</ins><span class="cx"> float CalcExpressionLength::evaluate(float maxValue) const
</span><span class="cx"> {
</span><span class="cx"> return floatValueForLength(m_length, maxValue);
</span><span class="lines">@@ -96,6 +107,11 @@
</span><span class="cx"> return other.type() == CalcExpressionNodeLength && *this == toCalcExpressionLength(other);
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+void CalcExpressionLength::dump(TextStream& ts) const
+{
+ ts << m_length;
+}
+
</ins><span class="cx"> float CalcExpressionBlendLength::evaluate(float maxValue) const
</span><span class="cx"> {
</span><span class="cx"> return (1.0f - m_progress) * floatValueForLength(m_from, maxValue) + m_progress * floatValueForLength(m_to, maxValue);
</span><span class="lines">@@ -106,4 +122,34 @@
</span><span class="cx"> return other.type() == CalcExpressionNodeBlendLength && *this == toCalcExpressionBlendLength(other);
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+void CalcExpressionBlendLength::dump(TextStream& ts) const
+{
+ ts << "blend(" << m_from << ", " << m_to << ", " << m_progress << ")";
+}
+
+TextStream& operator<<(TextStream& ts, CalcOperator op)
+{
+ switch (op) {
+ case CalcAdd: ts << "+"; break;
+ case CalcSubtract: ts << "-"; break;
+ case CalcMultiply: ts << "*"; break;
+ case CalcDivide: ts << "/"; break;
+ }
+ return ts;
+}
+
+TextStream& operator<<(TextStream& ts, const CalculationValue& value)
+{
+ ts << "calc(";
+ ts << value.expression();
+ ts << ")";
+ return ts;
+}
+
+TextStream& operator<<(TextStream& ts, const CalcExpressionNode& expressionNode)
+{
+ expressionNode.dump(ts);
+ return ts;
+}
+
</ins><span class="cx"> } // namespace WebCore
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformCalculationValueh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/CalculationValue.h (213602 => 213603)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/CalculationValue.h        2017-03-08 23:31:24 UTC (rev 213602)
+++ trunk/Source/WebCore/platform/CalculationValue.h        2017-03-08 23:50:43 UTC (rev 213603)
</span><span class="lines">@@ -39,6 +39,8 @@
</span><span class="cx">
</span><span class="cx"> namespace WebCore {
</span><span class="cx">
</span><ins>+class TextStream;
+
</ins><span class="cx"> enum CalcOperator {
</span><span class="cx"> CalcAdd = '+',
</span><span class="cx"> CalcSubtract = '-',
</span><span class="lines">@@ -64,6 +66,7 @@
</span><span class="cx">
</span><span class="cx"> virtual float evaluate(float maxValue) const = 0;
</span><span class="cx"> virtual bool operator==(const CalcExpressionNode&) const = 0;
</span><ins>+ virtual void dump(TextStream&) const = 0;
</ins><span class="cx">
</span><span class="cx"> private:
</span><span class="cx"> CalcExpressionNodeType m_type;
</span><span class="lines">@@ -78,6 +81,7 @@
</span><span class="cx"> private:
</span><span class="cx"> float evaluate(float) const override;
</span><span class="cx"> bool operator==(const CalcExpressionNode&) const override;
</span><ins>+ void dump(TextStream&) const override;
</ins><span class="cx">
</span><span class="cx"> float m_value;
</span><span class="cx"> };
</span><span class="lines">@@ -91,6 +95,7 @@
</span><span class="cx"> private:
</span><span class="cx"> float evaluate(float maxValue) const override;
</span><span class="cx"> bool operator==(const CalcExpressionNode&) const override;
</span><ins>+ void dump(TextStream&) const override;
</ins><span class="cx">
</span><span class="cx"> Length m_length;
</span><span class="cx"> };
</span><span class="lines">@@ -106,6 +111,7 @@
</span><span class="cx"> private:
</span><span class="cx"> float evaluate(float maxValue) const override;
</span><span class="cx"> bool operator==(const CalcExpressionNode&) const override;
</span><ins>+ void dump(TextStream&) const override;
</ins><span class="cx">
</span><span class="cx"> std::unique_ptr<CalcExpressionNode> m_leftSide;
</span><span class="cx"> std::unique_ptr<CalcExpressionNode> m_rightSide;
</span><span class="lines">@@ -123,6 +129,7 @@
</span><span class="cx"> private:
</span><span class="cx"> float evaluate(float maxValue) const override;
</span><span class="cx"> bool operator==(const CalcExpressionNode&) const override;
</span><ins>+ void dump(TextStream&) const override;
</ins><span class="cx">
</span><span class="cx"> Length m_from;
</span><span class="cx"> Length m_to;
</span><span class="lines">@@ -232,6 +239,10 @@
</span><span class="cx"> return static_cast<const CalcExpressionBlendLength&>(value);
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+TextStream& operator<<(TextStream&, const CalculationValue&);
+TextStream& operator<<(TextStream&, const CalcExpressionNode&);
+TextStream& operator<<(TextStream&, CalcOperator);
+
</ins><span class="cx"> } // namespace WebCore
</span><span class="cx">
</span><span class="cx"> #endif // CalculationValue_h
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformLengthcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/Length.cpp (213602 => 213603)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/Length.cpp        2017-03-08 23:31:24 UTC (rev 213602)
+++ trunk/Source/WebCore/platform/Length.cpp        2017-03-08 23:50:43 UTC (rev 213603)
</span><span class="lines">@@ -284,6 +284,18 @@
</span><span class="cx"> return calculationValue() == other.calculationValue();
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+Length convertTo100PercentMinusLength(const Length& length)
+{
+ if (length.isPercent())
+ return Length(100 - length.value(), Percent);
+
+ // Turn this into a calc expression: calc(100% - length)
+ auto lhs = std::make_unique<CalcExpressionLength>(Length(100, Percent));
+ auto rhs = std::make_unique<CalcExpressionLength>(length);
+ auto op = std::make_unique<CalcExpressionBinaryOperation>(WTFMove(lhs), WTFMove(rhs), CalcSubtract);
+ return Length(CalculationValue::create(WTFMove(op), ValueRangeAll));
+}
+
</ins><span class="cx"> static Length blendMixedTypes(const Length& from, const Length& to, double progress)
</span><span class="cx"> {
</span><span class="cx"> if (progress <= 0.0)
</span><span class="lines">@@ -370,8 +382,7 @@
</span><span class="cx"> ts << TextStream::FormatNumberRespectingIntegers(length.percent()) << "%";
</span><span class="cx"> break;
</span><span class="cx"> case Calculated:
</span><del>- // FIXME: dump CalculationValue.
- ts << "calc(...)";
</del><ins>+ ts << length.calculationValue();
</ins><span class="cx"> break;
</span><span class="cx"> }
</span><span class="cx">
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformLengthh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/Length.h (213602 => 213603)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/Length.h        2017-03-08 23:31:24 UTC (rev 213602)
+++ trunk/Source/WebCore/platform/Length.h        2017-03-08 23:50:43 UTC (rev 213603)
</span><span class="lines">@@ -415,6 +415,8 @@
</span><span class="cx"> return type() == FitContent;
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+Length convertTo100PercentMinusLength(const Length&);
+
</ins><span class="cx"> TextStream& operator<<(TextStream&, Length);
</span><span class="cx">
</span><span class="cx"> } // namespace WebCore
</span></span></pre></div>
<a id="trunkSourceWebCorerenderingstyleBasicShapescpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/rendering/style/BasicShapes.cpp (213602 => 213603)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/style/BasicShapes.cpp        2017-03-08 23:31:24 UTC (rev 213602)
+++ trunk/Source/WebCore/rendering/style/BasicShapes.cpp        2017-03-08 23:50:43 UTC (rev 213603)
</span><span class="lines">@@ -52,15 +52,13 @@
</span><span class="cx"> m_computedLength = m_length.isUndefined() ? Length(0, Fixed) : m_length;
</span><span class="cx"> return;
</span><span class="cx"> }
</span><ins>+
</ins><span class="cx"> if (m_length.isUndefined()) {
</span><span class="cx"> m_computedLength = Length(100, Percent);
</span><span class="cx"> return;
</span><span class="cx"> }
</span><del>-
- auto lhs = std::make_unique<CalcExpressionLength>(Length(100, Percent));
- auto rhs = std::make_unique<CalcExpressionLength>(m_length);
- auto op = std::make_unique<CalcExpressionBinaryOperation>(WTFMove(lhs), WTFMove(rhs), CalcSubtract);
- m_computedLength = Length(CalculationValue::create(WTFMove(op), ValueRangeAll));
</del><ins>+
+ m_computedLength = convertTo100PercentMinusLength(m_length);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> struct SVGPathTranslatedByteStream {
</span></span></pre></div>
<a id="trunkToolsTestWebKitAPITestsWebCoreCalculationValuecpp"></a>
<div class="modfile"><h4>Modified: trunk/Tools/TestWebKitAPI/Tests/WebCore/CalculationValue.cpp (213602 => 213603)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/TestWebKitAPI/Tests/WebCore/CalculationValue.cpp        2017-03-08 23:31:24 UTC (rev 213602)
+++ trunk/Tools/TestWebKitAPI/Tests/WebCore/CalculationValue.cpp        2017-03-08 23:50:43 UTC (rev 213603)
</span><span class="lines">@@ -27,6 +27,10 @@
</span><span class="cx">
</span><span class="cx"> #include <WebCore/CalculationValue.h>
</span><span class="cx">
</span><ins>+namespace WebCore {
+class TextStream;
+};
+
</ins><span class="cx"> namespace TestWebKitAPI {
</span><span class="cx">
</span><span class="cx"> static unsigned deletionCount;
</span><span class="lines">@@ -40,6 +44,9 @@
</span><span class="cx">
</span><span class="cx"> float evaluate(float) const override { return 0; }
</span><span class="cx"> bool operator==(const CalcExpressionNode&) const override { ASSERT_NOT_REACHED(); return false; }
</span><ins>+
+private:
+ void dump(WebCore::TextStream&) const override { };
</ins><span class="cx"> };
</span><span class="cx">
</span><span class="cx"> static Ref<WebCore::CalculationValue> createTestValue()
</span></span></pre>
</div>
</div>
</body>
</html>