<!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>[179069] 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/179069">179069</a></dd>
<dt>Author</dt> <dd>darin@apple.com</dd>
<dt>Date</dt> <dd>2015-01-24 11:55:58 -0800 (Sat, 24 Jan 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>Move height/width implementation for use element from RenderSVGViewportContainer to SVGUseElement
https://bugs.webkit.org/show_bug.cgi?id=140826

Reviewed by Anders Carlsson.

Source/WebCore:

Tests: svg/animations/use-animate-width-and-height.html
       svg/custom/use-attribute-invalidations.html
       svg/custom/use-dynamic-attribute-setting.html

This is an adaptation of work Rob Buis did in Blink:

    http://src.chromium.org/viewvc/blink?view=revision&amp;revision=173258

The goal here is to reduce use of SVGElementInstance since we are going to
remove it. The tests Rob added to Blink (which I believe I improved a bit here)
meant we had to fix quite a few bugs in the implementation of the width/height
logic rather than just moving it. Even so, this could use even more test coverage
since there is separate logic for &lt;symbol&gt; and &lt;svg&gt;, three different code paths
(animation/attribute setting, initial creation, and one other), and also
distinct issues for attributes not set at all, attributes set to values that
can't be parsed, and attributes set with different units.

* rendering/svg/RenderSVGViewportContainer.cpp:
(WebCore::RenderSVGViewportContainer::calcViewport): Removed the old logic.

* svg/SVGSVGElement.cpp:
(WebCore::SVGSVGElement::SVGSVGElement): Use ASCIILiteral to more efficiently
create strings from ASCII literals here.
(WebCore::SVGSVGElement::parseAttribute): Default to 100%, not 0, when the
width or height property are either not set or not successfully parsed. Without
this change, one of the SVG tests starts failing.

* svg/SVGUseElement.cpp:
(WebCore::updateWidthAndHeight): Added. The tricky part here is that we have
to copy width and height attributes only if they were successfully parsed, and
also we need to copy the current animating values, not the original attribute
strings. Kind of messy, but I wanted to adapt Rob's solution for the time being,
rather than inventing something new.
(WebCore::SVGUseElement::svgAttributeChanged): Call updateWidthAndHeight.
This is used both when actual attribute changes occur and also when animation
changes the current value.
(WebCore::SVGUseElement::buildShadowAndInstanceTree): Call updateWidthAndHeight.
This is used when the shadow elements are first created.
(WebCore::SVGUseElement::expandUseElementsInShadowTree): Call updateWidthAndHeight.
This was in Rob's patch, but I am not sure we have sufficient test coverage.

LayoutTests:

* platform/mac/svg/custom/relative-sized-shadow-tree-content-with-symbol-expected.png: Old test
result was expecting failure. New one expects success.
* platform/mac/svg/custom/relative-sized-shadow-tree-content-with-symbol-expected.txt: Ditto.
* svg/animations/use-animate-width-and-height-expected.txt: Added.
* svg/animations/use-animate-width-and-height.html: Added.
* svg/custom/use-attribute-invalidations-expected.html: Added.
* svg/custom/use-attribute-invalidations.html: Added.
* svg/custom/use-dynamic-attribute-setting-expected.html: Added.
* svg/custom/use-dynamic-attribute-setting.html: Added.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestsplatformmacsvgcustomrelativesizedshadowtreecontentwithsymbolexpectedpng">trunk/LayoutTests/platform/mac/svg/custom/relative-sized-shadow-tree-content-with-symbol-expected.png</a></li>
<li><a href="#trunkLayoutTestsplatformmacsvgcustomrelativesizedshadowtreecontentwithsymbolexpectedtxt">trunk/LayoutTests/platform/mac/svg/custom/relative-sized-shadow-tree-content-with-symbol-expected.txt</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCorerenderingsvgRenderSVGViewportContainercpp">trunk/Source/WebCore/rendering/svg/RenderSVGViewportContainer.cpp</a></li>
<li><a href="#trunkSourceWebCoresvgSVGSVGElementcpp">trunk/Source/WebCore/svg/SVGSVGElement.cpp</a></li>
<li><a href="#trunkSourceWebCoresvgSVGUseElementcpp">trunk/Source/WebCore/svg/SVGUseElement.cpp</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestssvganimationsuseanimatewidthandheightexpectedtxt">trunk/LayoutTests/svg/animations/use-animate-width-and-height-expected.txt</a></li>
<li><a href="#trunkLayoutTestssvganimationsuseanimatewidthandheighthtml">trunk/LayoutTests/svg/animations/use-animate-width-and-height.html</a></li>
<li><a href="#trunkLayoutTestssvgcustomuseattributeinvalidationsexpectedhtml">trunk/LayoutTests/svg/custom/use-attribute-invalidations-expected.html</a></li>
<li><a href="#trunkLayoutTestssvgcustomuseattributeinvalidationshtml">trunk/LayoutTests/svg/custom/use-attribute-invalidations.html</a></li>
<li><a href="#trunkLayoutTestssvgcustomusedynamicattributesettingexpectedhtml">trunk/LayoutTests/svg/custom/use-dynamic-attribute-setting-expected.html</a></li>
<li><a href="#trunkLayoutTestssvgcustomusedynamicattributesettinghtml">trunk/LayoutTests/svg/custom/use-dynamic-attribute-setting.html</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (179068 => 179069)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2015-01-24 19:14:44 UTC (rev 179068)
+++ trunk/LayoutTests/ChangeLog        2015-01-24 19:55:58 UTC (rev 179069)
</span><span class="lines">@@ -1,3 +1,20 @@
</span><ins>+2015-01-24  Darin Adler  &lt;darin@apple.com&gt;
+
+        Move height/width implementation for use element from RenderSVGViewportContainer to SVGUseElement
+        https://bugs.webkit.org/show_bug.cgi?id=140826
+
+        Reviewed by Anders Carlsson.
+
+        * platform/mac/svg/custom/relative-sized-shadow-tree-content-with-symbol-expected.png: Old test
+        result was expecting failure. New one expects success.
+        * platform/mac/svg/custom/relative-sized-shadow-tree-content-with-symbol-expected.txt: Ditto.
+        * svg/animations/use-animate-width-and-height-expected.txt: Added.
+        * svg/animations/use-animate-width-and-height.html: Added.
+        * svg/custom/use-attribute-invalidations-expected.html: Added.
+        * svg/custom/use-attribute-invalidations.html: Added.
+        * svg/custom/use-dynamic-attribute-setting-expected.html: Added.
+        * svg/custom/use-dynamic-attribute-setting.html: Added.
+
</ins><span class="cx"> 2015-01-23  Brent Fulgham  &lt;bfulgham@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [Win] Unreviewed gardening. Add Windows baseline for
</span></span></pre></div>
<a id="trunkLayoutTestsplatformmacsvgcustomrelativesizedshadowtreecontentwithsymbolexpectedpng"></a>
<div class="binary"><h4>Modified: trunk/LayoutTests/platform/mac/svg/custom/relative-sized-shadow-tree-content-with-symbol-expected.png</h4>
<pre class="diff"><span>
<span class="cx">(Binary files differ)
</span></span></pre></div>
<a id="trunkLayoutTestsplatformmacsvgcustomrelativesizedshadowtreecontentwithsymbolexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/platform/mac/svg/custom/relative-sized-shadow-tree-content-with-symbol-expected.txt (179068 => 179069)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/platform/mac/svg/custom/relative-sized-shadow-tree-content-with-symbol-expected.txt        2015-01-24 19:14:44 UTC (rev 179068)
+++ trunk/LayoutTests/platform/mac/svg/custom/relative-sized-shadow-tree-content-with-symbol-expected.txt        2015-01-24 19:55:58 UTC (rev 179069)
</span><span class="lines">@@ -8,13 +8,13 @@
</span><span class="cx">           text run at (0,0) width 744: &quot;The svg area contained in the div element (red box), should fill out the whole area (two green rectangles, first: (0,0)-&quot;
</span><span class="cx">           text run at (0,18) width 686: &quot;(50%,50%), second: (50%,50%)-(100%,100%)), especially after resizing the content box to a different size&quot;
</span><span class="cx">       RenderBlock {div} at (0,52) size 402x402 [border: (1px solid #FF0000)]
</span><del>-        RenderSVGRoot {svg} at (9,69) size 400x400
</del><ins>+        RenderSVGRoot {svg} at (9,69) size 200x200
</ins><span class="cx">           RenderSVGHiddenContainer {defs} at (0,0) size 0x0
</span><span class="cx">             RenderSVGHiddenContainer {symbol} at (0,0) size 0x0
</span><span class="cx">               RenderSVGRect {rect} at (9,69) size 0x0 [fill={[type=SOLID] [color=#008000]}] [x=0.00] [y=0.00] [width=0.00] [height=0.00]
</span><span class="cx">               RenderSVGRect {rect} at (9,69) size 100x100 [fill={[type=SOLID] [color=#008000]}] [x=0.00] [y=0.00] [width=100.00] [height=100.00]
</span><del>-          RenderSVGContainer {use} at (9,69) size 400x400
-            RenderSVGViewportContainer {svg} at (9,69) size 400x400
-              RenderSVGRect {rect} at (209,269) size 200x200 [fill={[type=SOLID] [color=#008000]}] [x=100.00] [y=100.00] [width=100.00] [height=100.00]
-              RenderSVGRect {rect} at (9,69) size 200x200 [fill={[type=SOLID] [color=#008000]}] [x=0.00] [y=0.00] [width=100.00] [height=100.00]
</del><ins>+          RenderSVGContainer {use} at (9,69) size 200x200
+            RenderSVGViewportContainer {svg} at (9,69) size 200x200
+              RenderSVGRect {rect} at (109,169) size 100x100 [fill={[type=SOLID] [color=#008000]}] [x=100.00] [y=100.00] [width=100.00] [height=100.00]
+              RenderSVGRect {rect} at (9,69) size 100x100 [fill={[type=SOLID] [color=#008000]}] [x=0.00] [y=0.00] [width=100.00] [height=100.00]
</ins><span class="cx">         RenderText {#text} at (0,0) size 0x0
</span></span></pre></div>
<a id="trunkLayoutTestssvganimationsuseanimatewidthandheightexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/svg/animations/use-animate-width-and-height-expected.txt (0 => 179069)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/svg/animations/use-animate-width-and-height-expected.txt                                (rev 0)
+++ trunk/LayoutTests/svg/animations/use-animate-width-and-height-expected.txt        2015-01-24 19:55:58 UTC (rev 179069)
</span><span class="lines">@@ -0,0 +1,49 @@
</span><ins>+Test animation of use element width/height
+
+On success, you will see a series of &quot;PASS&quot; messages, followed by &quot;TEST COMPLETE&quot;.
+
+
+PASS use.width.animVal.value is 100
+PASS use.width.baseVal.value is 100
+PASS use.height.animVal.value is 100
+PASS use.height.baseVal.value is 100
+PASS use.getAttribute('width') is '100'
+PASS use.getAttribute('height') is '100'
+PASS shadowRoot.firstChild.width.animVal.value is 100
+PASS shadowRoot.firstChild.height.animVal.value is 100
+PASS use.width.animVal.value is 105
+PASS use.width.baseVal.value is 100
+PASS use.height.animVal.value is 105
+PASS use.height.baseVal.value is 100
+FAIL use.getAttribute('width') should be 105. Was 100.
+FAIL use.getAttribute('height') should be 105. Was 100.
+PASS shadowRoot.firstChild.width.animVal.value is 105
+PASS shadowRoot.firstChild.height.animVal.value is 105
+PASS use.width.animVal.value is 115
+PASS use.width.baseVal.value is 100
+PASS use.height.animVal.value is 115
+PASS use.height.baseVal.value is 100
+FAIL use.getAttribute('width') should be 115. Was 100.
+FAIL use.getAttribute('height') should be 115. Was 100.
+PASS shadowRoot.firstChild.width.animVal.value is 115
+PASS shadowRoot.firstChild.height.animVal.value is 115
+PASS use.width.animVal.value is 125
+PASS use.width.baseVal.value is 100
+PASS use.height.animVal.value is 125
+PASS use.height.baseVal.value is 100
+FAIL use.getAttribute('width') should be 125. Was 100.
+FAIL use.getAttribute('height') should be 125. Was 100.
+PASS shadowRoot.firstChild.width.animVal.value is 125
+PASS shadowRoot.firstChild.height.animVal.value is 125
+PASS use.width.animVal.value is 135
+PASS use.width.baseVal.value is 100
+PASS use.height.animVal.value is 135
+PASS use.height.baseVal.value is 100
+FAIL use.getAttribute('width') should be 135. Was 100.
+FAIL use.getAttribute('height') should be 135. Was 100.
+PASS shadowRoot.firstChild.width.animVal.value is 135
+PASS shadowRoot.firstChild.height.animVal.value is 135
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins><span class="cx">Property changes on: trunk/LayoutTests/svg/animations/use-animate-width-and-height-expected.txt
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkLayoutTestssvganimationsuseanimatewidthandheighthtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/svg/animations/use-animate-width-and-height.html (0 => 179069)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/svg/animations/use-animate-width-and-height.html                                (rev 0)
+++ trunk/LayoutTests/svg/animations/use-animate-width-and-height.html        2015-01-24 19:55:58 UTC (rev 179069)
</span><span class="lines">@@ -0,0 +1,143 @@
</span><ins>+&lt;!DOCTYPE HTML&gt;
+&lt;html&gt;
+&lt;head&gt;
+&lt;script src=&quot;../../resources/js-test-pre.js&quot;&gt;&lt;/script&gt;
+&lt;script src=&quot;../dynamic-updates/resources/SVGTestCase.js&quot;&gt;&lt;/script&gt;
+&lt;script src=&quot;resources/SVGAnimationTestCase.js&quot;&gt;&lt;/script&gt;
+&lt;/head&gt;
+&lt;body onload=&quot;runSMILTest()&quot;&gt;
+&lt;p id=&quot;description&quot;&gt;&lt;/p&gt;
+&lt;div id=&quot;console&quot;&gt;&lt;/div&gt;
+&lt;script&gt;
+
+description(&quot;Test animation of use element width/height&quot;);
+createSVGTestCase();
+
+// Set up test document.
+
+var symbol = createSVGElement(&quot;symbol&quot;);
+symbol.setAttribute(&quot;id&quot;, &quot;symbol&quot;);
+
+var rect = createSVGElement(&quot;rect&quot;);
+rect.setAttribute(&quot;id&quot;, &quot;rect&quot;);
+rect.setAttribute(&quot;x&quot;, &quot;10&quot;);
+rect.setAttribute(&quot;y&quot;, &quot;10&quot;);
+rect.setAttribute(&quot;width&quot;, &quot;100%&quot;);
+rect.setAttribute(&quot;height&quot;, &quot;100%&quot;);
+rect.setAttribute(&quot;fill&quot;, &quot;green&quot;);
+rect.setAttribute(&quot;onclick&quot;, &quot;executeTest()&quot;);
+symbol.appendChild(rect);
+rootSVGElement.appendChild(symbol);
+
+var use = createSVGElement(&quot;use&quot;);
+use.setAttribute(&quot;id&quot;, &quot;use&quot;);
+use.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', '#symbol');
+use.setAttribute(&quot;x&quot;, &quot;0&quot;);
+use.setAttribute(&quot;y&quot;, &quot;0&quot;);
+use.setAttribute(&quot;width&quot;, &quot;100&quot;);
+use.setAttribute(&quot;height&quot;, &quot;100&quot;);
+rootSVGElement.appendChild(use);
+
+var animate = createSVGElement(&quot;animate&quot;);
+animate.setAttribute(&quot;id&quot;, &quot;animate&quot;);
+animate.setAttribute(&quot;attributeName&quot;, &quot;width&quot;);
+animate.setAttribute(&quot;attributeType&quot;, &quot;XML&quot;);
+animate.setAttribute(&quot;begin&quot;, &quot;1s&quot;);
+animate.setAttribute(&quot;dur&quot;, &quot;10s&quot;);
+animate.setAttribute(&quot;from&quot;, &quot;100&quot;);
+animate.setAttribute(&quot;to&quot;, &quot;200&quot;);
+use.appendChild(animate);
+
+var animate2 = createSVGElement(&quot;animate&quot;);
+animate2.setAttribute(&quot;id&quot;, &quot;animate2&quot;);
+animate2.setAttribute(&quot;attributeName&quot;, &quot;height&quot;);
+animate2.setAttribute(&quot;attributeType&quot;, &quot;XML&quot;);
+animate2.setAttribute(&quot;begin&quot;, &quot;1s&quot;);
+animate2.setAttribute(&quot;dur&quot;, &quot;10s&quot;);
+animate2.setAttribute(&quot;from&quot;, &quot;100&quot;);
+animate2.setAttribute(&quot;to&quot;, &quot;200&quot;);
+use.appendChild(animate2);
+
+var shadowRoot = internals.shadowRoot(use);
+
+function sample1()
+{
+    // Check initial/end conditions
+    shouldBe(&quot;use.width.animVal.value&quot;, &quot;100&quot;);
+    shouldBe(&quot;use.width.baseVal.value&quot;, &quot;100&quot;);
+    shouldBe(&quot;use.height.animVal.value&quot;, &quot;100&quot;);
+    shouldBe(&quot;use.height.baseVal.value&quot;, &quot;100&quot;);
+    shouldBe(&quot;use.getAttribute('width')&quot;, &quot;'100'&quot;);
+    shouldBe(&quot;use.getAttribute('height')&quot;, &quot;'100'&quot;);
+    shouldBe(&quot;shadowRoot.firstChild.width.animVal.value&quot;, &quot;100&quot;);
+    shouldBe(&quot;shadowRoot.firstChild.height.animVal.value&quot;, &quot;100&quot;);
+}
+
+function sample2()
+{
+    shouldBe(&quot;use.width.animVal.value&quot;, &quot;105&quot;);
+    shouldBe(&quot;use.width.baseVal.value&quot;, &quot;100&quot;);
+    shouldBe(&quot;use.height.animVal.value&quot;, &quot;105&quot;);
+    shouldBe(&quot;use.height.baseVal.value&quot;, &quot;100&quot;);
+    shouldBe(&quot;use.getAttribute('width')&quot;, &quot;'105'&quot;);
+    shouldBe(&quot;use.getAttribute('height')&quot;, &quot;'105'&quot;);
+    shouldBe(&quot;shadowRoot.firstChild.width.animVal.value&quot;, &quot;105&quot;);
+    shouldBe(&quot;shadowRoot.firstChild.height.animVal.value&quot;, &quot;105&quot;);
+}
+
+function sample3()
+{
+    shouldBe(&quot;use.width.animVal.value&quot;, &quot;115&quot;);
+    shouldBe(&quot;use.width.baseVal.value&quot;, &quot;100&quot;);
+    shouldBe(&quot;use.height.animVal.value&quot;, &quot;115&quot;);
+    shouldBe(&quot;use.height.baseVal.value&quot;, &quot;100&quot;);
+    shouldBe(&quot;use.getAttribute('width')&quot;, &quot;'115'&quot;);
+    shouldBe(&quot;use.getAttribute('height')&quot;, &quot;'115'&quot;);
+    shouldBe(&quot;shadowRoot.firstChild.width.animVal.value&quot;, &quot;115&quot;);
+    shouldBe(&quot;shadowRoot.firstChild.height.animVal.value&quot;, &quot;115&quot;);
+}
+
+function sample4() {
+    shouldBe(&quot;use.width.animVal.value&quot;, &quot;125&quot;);
+    shouldBe(&quot;use.width.baseVal.value&quot;, &quot;100&quot;);
+    shouldBe(&quot;use.height.animVal.value&quot;, &quot;125&quot;);
+    shouldBe(&quot;use.height.baseVal.value&quot;, &quot;100&quot;);
+    shouldBe(&quot;use.getAttribute('width')&quot;, &quot;'125'&quot;);
+    shouldBe(&quot;use.getAttribute('height')&quot;, &quot;'125'&quot;);
+    shouldBe(&quot;shadowRoot.firstChild.width.animVal.value&quot;, &quot;125&quot;);
+    shouldBe(&quot;shadowRoot.firstChild.height.animVal.value&quot;, &quot;125&quot;);
+}
+
+function sample5()
+{
+    shouldBe(&quot;use.width.animVal.value&quot;, &quot;135&quot;);
+    shouldBe(&quot;use.width.baseVal.value&quot;, &quot;100&quot;);
+    shouldBe(&quot;use.height.animVal.value&quot;, &quot;135&quot;);
+    shouldBe(&quot;use.height.baseVal.value&quot;, &quot;100&quot;);
+    shouldBe(&quot;use.getAttribute('width')&quot;, &quot;'135'&quot;);
+    shouldBe(&quot;use.getAttribute('height')&quot;, &quot;'135'&quot;);
+    shouldBe(&quot;shadowRoot.firstChild.width.animVal.value&quot;, &quot;135&quot;);
+    shouldBe(&quot;shadowRoot.firstChild.height.animVal.value&quot;, &quot;135&quot;);
+}
+
+function executeTest()
+{
+    const expectedValues = [
+        // [animationId, time, sampleCallback]
+        [&quot;animate2&quot;, 0.0,   sample1],
+        [&quot;animate2&quot;, 0.5,   sample2],
+        [&quot;animate2&quot;, 1.5,   sample3],
+        [&quot;animate2&quot;, 2.5,   sample4],
+        [&quot;animate2&quot;, 3.5,   sample5]
+    ];
+
+    runAnimationTest(expectedValues);
+}
+
+window.clickX = 50;
+window.clickY = 50;
+
+var successfullyParsed = true;
+&lt;/script&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins><span class="cx">Property changes on: trunk/LayoutTests/svg/animations/use-animate-width-and-height.html
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnmimetype"></a>
<div class="addfile"><h4>Added: svn:mime-type</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkLayoutTestssvgcustomuseattributeinvalidationsexpectedhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/svg/custom/use-attribute-invalidations-expected.html (0 => 179069)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/svg/custom/use-attribute-invalidations-expected.html                                (rev 0)
+++ trunk/LayoutTests/svg/custom/use-attribute-invalidations-expected.html        2015-01-24 19:55:58 UTC (rev 179069)
</span><span class="lines">@@ -0,0 +1,17 @@
</span><ins>+&lt;!DOCTYPE HTML&gt;
+&lt;html&gt;
+&lt;body&gt;
+&lt;p&gt;This test passes if there are three 100x100px green squares in a diagonal line below:&lt;/p&gt;
+&lt;svg width=&quot;300&quot; height=&quot;300&quot;&gt;
+    &lt;svg width=&quot;100&quot; height=&quot;100&quot;&gt;
+        &lt;rect width=&quot;100%&quot; height=&quot;100%&quot; fill=&quot;green&quot;/&gt;
+    &lt;/svg&gt;
+    &lt;svg x=&quot;100&quot; y=&quot;100&quot; width=&quot;100&quot; height=&quot;100&quot;&gt;
+        &lt;rect width=&quot;100%&quot; height=&quot;100%&quot; fill=&quot;green&quot;/&gt;
+    &lt;/svg&gt;
+    &lt;svg x=&quot;200&quot; y=&quot;200&quot; width=&quot;100&quot; height=&quot;100&quot;&gt;
+        &lt;rect width=&quot;100%&quot; height=&quot;100%&quot; fill=&quot;green&quot;/&gt;
+    &lt;/svg&gt;
+&lt;/svg&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins><span class="cx">Property changes on: trunk/LayoutTests/svg/custom/use-attribute-invalidations-expected.html
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnmimetype"></a>
<div class="addfile"><h4>Added: svn:mime-type</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkLayoutTestssvgcustomuseattributeinvalidationshtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/svg/custom/use-attribute-invalidations.html (0 => 179069)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/svg/custom/use-attribute-invalidations.html                                (rev 0)
+++ trunk/LayoutTests/svg/custom/use-attribute-invalidations.html        2015-01-24 19:55:58 UTC (rev 179069)
</span><span class="lines">@@ -0,0 +1,27 @@
</span><ins>+&lt;!DOCTYPE HTML&gt;
+&lt;html&gt;
+&lt;body&gt;
+&lt;p&gt;This test passes if there are three 100x100px green squares in a diagonal line below:&lt;/p&gt;
+&lt;svg width=&quot;300&quot; height=&quot;300&quot;&gt;
+    &lt;defs&gt;
+        &lt;symbol id=&quot;symbol&quot; width=&quot;100&quot;&gt;
+            &lt;rect width=&quot;100%&quot; height=&quot;100%&quot; fill=&quot;green&quot;/&gt;
+        &lt;/symbol&gt;
+    &lt;/defs&gt;
+    &lt;svg x=&quot;0&quot; y=&quot;0&quot; width=&quot;100&quot; height=&quot;100&quot;&gt;
+        &lt;use id=&quot;use1&quot; xlink:href=&quot;#symbol&quot;/&gt;
+    &lt;/svg&gt;
+    &lt;use id=&quot;use2&quot; xlink:href=&quot;#symbol&quot; x=&quot;100&quot; y=&quot;100&quot; width=&quot;10&quot; height=&quot;100&quot;/&gt;
+    &lt;use id=&quot;use3&quot; xlink:href=&quot;#symbol&quot; x=&quot;200&quot; y=&quot;200&quot; width=&quot;100&quot; height=&quot;10&quot;/&gt;
+&lt;/svg&gt;
+&lt;script&gt;
+    // Force layout since the intention is to test behavior of changes *after* layout has occurred.
+    // FIXME: Find a clean reliable way to do this; Blink tests were using requestAnimationFrame,
+    // which seems like it would be racy and wrong, but perhaps they have some rationale for that.
+    document.body.offsetTop;
+
+    document.getElementById('use2').removeAttribute('width');
+    document.getElementById('use3').setAttribute('height', '100');
+&lt;/script&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins><span class="cx">Property changes on: trunk/LayoutTests/svg/custom/use-attribute-invalidations.html
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnmimetype"></a>
<div class="addfile"><h4>Added: svn:mime-type</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkLayoutTestssvgcustomusedynamicattributesettingexpectedhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/svg/custom/use-dynamic-attribute-setting-expected.html (0 => 179069)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/svg/custom/use-dynamic-attribute-setting-expected.html                                (rev 0)
+++ trunk/LayoutTests/svg/custom/use-dynamic-attribute-setting-expected.html        2015-01-24 19:55:58 UTC (rev 179069)
</span><span class="lines">@@ -0,0 +1,14 @@
</span><ins>+&lt;!DOCTYPE HTML&gt;
+&lt;html&gt;
+&lt;body&gt;
+&lt;p&gt;This test passes if there are two 100x100px green squares in a diagonal line below:&lt;/p&gt;
+&lt;svg width=&quot;300&quot; height=&quot;300&quot;&gt;
+    &lt;svg width=&quot;100&quot; height=&quot;100&quot;&gt;
+        &lt;rect width=&quot;100%&quot; height=&quot;100%&quot; fill=&quot;green&quot;/&gt;
+    &lt;/svg&gt;
+    &lt;svg x=&quot;100&quot; y=&quot;100&quot; width=&quot;100&quot; height=&quot;100&quot;&gt;
+        &lt;rect width=&quot;100%&quot; height=&quot;100%&quot; fill=&quot;green&quot;/&gt;
+    &lt;/svg&gt;
+&lt;/svg&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins><span class="cx">Property changes on: trunk/LayoutTests/svg/custom/use-dynamic-attribute-setting-expected.html
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnmimetype"></a>
<div class="addfile"><h4>Added: svn:mime-type</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkLayoutTestssvgcustomusedynamicattributesettinghtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/svg/custom/use-dynamic-attribute-setting.html (0 => 179069)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/svg/custom/use-dynamic-attribute-setting.html                                (rev 0)
+++ trunk/LayoutTests/svg/custom/use-dynamic-attribute-setting.html        2015-01-24 19:55:58 UTC (rev 179069)
</span><span class="lines">@@ -0,0 +1,24 @@
</span><ins>+&lt;!DOCTYPE HTML&gt;
+&lt;html&gt;
+&lt;body&gt;
+&lt;p&gt;This test passes if there are two 100x100px green squares in a diagonal line below:&lt;/p&gt;
+&lt;svg width=&quot;300&quot; height=&quot;300&quot;&gt;
+    &lt;defs&gt;
+        &lt;svg id=&quot;svg&quot; width=&quot;10&quot; height=&quot;10&quot;&gt;
+            &lt;rect width=&quot;100%&quot; height=&quot;100%&quot; fill=&quot;green&quot;/&gt;
+        &lt;/svg&gt;
+    &lt;/defs&gt;
+    &lt;use id=&quot;use1&quot; xlink:href=&quot;#svg&quot; x=&quot;0&quot; y=&quot;0&quot; width=&quot;100&quot; height=&quot;100&quot;/&gt;
+    &lt;use id=&quot;use2&quot; xlink:href=&quot;#svg&quot; x=&quot;100&quot; y=&quot;100&quot; width=&quot;10&quot; height=&quot;10&quot;/&gt;
+&lt;/svg&gt;
+&lt;script&gt;
+    // Force layout since the intention is to test behavior of changes *after* layout has occurred.
+    // FIXME: Find a clean reliable way to do this; Blink tests were using requestAnimationFrame,
+    // which seems like it would be racy and wrong, but perhaps they have some rationale for that.
+    document.body.offsetTop;
+
+    document.getElementById('use2').setAttribute('width', '100');
+    document.getElementById('use2').setAttribute('height', '100');
+&lt;/script&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins><span class="cx">Property changes on: trunk/LayoutTests/svg/custom/use-dynamic-attribute-setting.html
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnmimetype"></a>
<div class="addfile"><h4>Added: svn:mime-type</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (179068 => 179069)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2015-01-24 19:14:44 UTC (rev 179068)
+++ trunk/Source/WebCore/ChangeLog        2015-01-24 19:55:58 UTC (rev 179069)
</span><span class="lines">@@ -1,3 +1,51 @@
</span><ins>+2015-01-24  Darin Adler  &lt;darin@apple.com&gt;
+
+        Move height/width implementation for use element from RenderSVGViewportContainer to SVGUseElement
+        https://bugs.webkit.org/show_bug.cgi?id=140826
+
+        Reviewed by Anders Carlsson.
+
+        Tests: svg/animations/use-animate-width-and-height.html
+               svg/custom/use-attribute-invalidations.html
+               svg/custom/use-dynamic-attribute-setting.html
+
+        This is an adaptation of work Rob Buis did in Blink:
+
+            http://src.chromium.org/viewvc/blink?view=revision&amp;revision=173258
+
+        The goal here is to reduce use of SVGElementInstance since we are going to
+        remove it. The tests Rob added to Blink (which I believe I improved a bit here)
+        meant we had to fix quite a few bugs in the implementation of the width/height
+        logic rather than just moving it. Even so, this could use even more test coverage
+        since there is separate logic for &lt;symbol&gt; and &lt;svg&gt;, three different code paths
+        (animation/attribute setting, initial creation, and one other), and also
+        distinct issues for attributes not set at all, attributes set to values that
+        can't be parsed, and attributes set with different units.
+
+        * rendering/svg/RenderSVGViewportContainer.cpp:
+        (WebCore::RenderSVGViewportContainer::calcViewport): Removed the old logic.
+
+        * svg/SVGSVGElement.cpp:
+        (WebCore::SVGSVGElement::SVGSVGElement): Use ASCIILiteral to more efficiently
+        create strings from ASCII literals here.
+        (WebCore::SVGSVGElement::parseAttribute): Default to 100%, not 0, when the
+        width or height property are either not set or not successfully parsed. Without
+        this change, one of the SVG tests starts failing.
+
+        * svg/SVGUseElement.cpp:
+        (WebCore::updateWidthAndHeight): Added. The tricky part here is that we have
+        to copy width and height attributes only if they were successfully parsed, and
+        also we need to copy the current animating values, not the original attribute
+        strings. Kind of messy, but I wanted to adapt Rob's solution for the time being,
+        rather than inventing something new.
+        (WebCore::SVGUseElement::svgAttributeChanged): Call updateWidthAndHeight.
+        This is used both when actual attribute changes occur and also when animation
+        changes the current value.
+        (WebCore::SVGUseElement::buildShadowAndInstanceTree): Call updateWidthAndHeight.
+        This is used when the shadow elements are first created.
+        (WebCore::SVGUseElement::expandUseElementsInShadowTree): Call updateWidthAndHeight.
+        This was in Rob's patch, but I am not sure we have sufficient test coverage.
+
</ins><span class="cx"> 2015-01-24  Chris Dumez  &lt;cdumez@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Provide implementation for WTF::DefaultHash&lt;bool&gt;
</span></span></pre></div>
<a id="trunkSourceWebCorerenderingsvgRenderSVGViewportContainercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/rendering/svg/RenderSVGViewportContainer.cpp (179068 => 179069)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/svg/RenderSVGViewportContainer.cpp        2015-01-24 19:14:44 UTC (rev 179068)
+++ trunk/Source/WebCore/rendering/svg/RenderSVGViewportContainer.cpp        2015-01-24 19:55:58 UTC (rev 179069)
</span><span class="lines">@@ -58,62 +58,17 @@
</span><span class="cx"> 
</span><span class="cx"> void RenderSVGViewportContainer::calcViewport()
</span><span class="cx"> {
</span><del>-    SVGSVGElement&amp; svg = svgSVGElement();
-    FloatRect oldViewport = m_viewport;
</del><ins>+    SVGSVGElement&amp; element = svgSVGElement();
+    SVGLengthContext lengthContext(&amp;element);
+    FloatRect newViewport(element.x().value(lengthContext), element.y().value(lengthContext), element.width().value(lengthContext), element.height().value(lengthContext));
</ins><span class="cx"> 
</span><del>-    SVGLengthContext lengthContext(&amp;svg);
-    m_viewport = FloatRect(svg.x().value(lengthContext), svg.y().value(lengthContext), svg.width().value(lengthContext), svg.height().value(lengthContext));
</del><ins>+    if (m_viewport == newViewport)
+        return;
</ins><span class="cx"> 
</span><del>-    SVGElement* correspondingElement = svg.correspondingElement();
-    if (correspondingElement &amp;&amp; svg.isInShadowTree()) {
-        const HashSet&lt;SVGElementInstance*&gt;&amp; instances = correspondingElement-&gt;instancesForElement();
-        ASSERT(!instances.isEmpty());
</del><ins>+    m_viewport = newViewport;
</ins><span class="cx"> 
</span><del>-        SVGUseElement* useElement = 0;
-        const HashSet&lt;SVGElementInstance*&gt;::const_iterator end = instances.end();
-        for (HashSet&lt;SVGElementInstance*&gt;::const_iterator it = instances.begin(); it != end; ++it) {
-            const SVGElementInstance* instance = (*it);
-            ASSERT(instance-&gt;correspondingElement()-&gt;hasTagName(SVGNames::svgTag) || instance-&gt;correspondingElement()-&gt;hasTagName(SVGNames::symbolTag));
-            if (instance-&gt;shadowTreeElement() == &amp;svg) {
-                ASSERT(correspondingElement == instance-&gt;correspondingElement());
-                useElement = instance-&gt;directUseElement();
-                if (!useElement)
-                    useElement = instance-&gt;correspondingUseElement();
-                break;
-            }
-        }
-
-        ASSERT(useElement);
-        bool isSymbolElement = correspondingElement-&gt;hasTagName(SVGNames::symbolTag);
-
-        // Spec (&lt;use&gt; on &lt;symbol&gt;): This generated 'svg' will always have explicit values for attributes width and height.
-        // If attributes width and/or height are provided on the 'use' element, then these attributes
-        // will be transferred to the generated 'svg'. If attributes width and/or height are not specified,
-        // the generated 'svg' element will use values of 100% for these attributes.
-
-        // Spec (&lt;use&gt; on &lt;svg&gt;): If attributes width and/or height are provided on the 'use' element, then these
-        // values will override the corresponding attributes on the 'svg' in the generated tree.
-
-        SVGLengthContext lengthContext(&amp;svg);
-        if (useElement-&gt;hasAttribute(SVGNames::widthAttr))
-            m_viewport.setWidth(useElement-&gt;width().value(lengthContext));
-        else if (isSymbolElement &amp;&amp; svg.hasAttribute(SVGNames::widthAttr)) {
-            SVGLength containerWidth(LengthModeWidth, &quot;100%&quot;);
-            m_viewport.setWidth(containerWidth.value(lengthContext));
-        }
-
-        if (useElement-&gt;hasAttribute(SVGNames::heightAttr))
-            m_viewport.setHeight(useElement-&gt;height().value(lengthContext));
-        else if (isSymbolElement &amp;&amp; svg.hasAttribute(SVGNames::heightAttr)) {
-            SVGLength containerHeight(LengthModeHeight, &quot;100%&quot;);
-            m_viewport.setHeight(containerHeight.value(lengthContext));
-        }
-    }
-
-    if (oldViewport != m_viewport) {
-        setNeedsBoundariesUpdate();
-        setNeedsTransformUpdate();
-    }
</del><ins>+    setNeedsBoundariesUpdate();
+    setNeedsTransformUpdate();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> bool RenderSVGViewportContainer::calculateLocalTransform() 
</span></span></pre></div>
<a id="trunkSourceWebCoresvgSVGSVGElementcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/svg/SVGSVGElement.cpp (179068 => 179069)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/svg/SVGSVGElement.cpp        2015-01-24 19:14:44 UTC (rev 179068)
+++ trunk/Source/WebCore/svg/SVGSVGElement.cpp        2015-01-24 19:55:58 UTC (rev 179069)
</span><span class="lines">@@ -84,8 +84,8 @@
</span><span class="cx">     : SVGGraphicsElement(tagName, document)
</span><span class="cx">     , m_x(LengthModeWidth)
</span><span class="cx">     , m_y(LengthModeHeight)
</span><del>-    , m_width(LengthModeWidth, &quot;100%&quot;)
-    , m_height(LengthModeHeight, &quot;100%&quot;) 
</del><ins>+    , m_width(LengthModeWidth, ASCIILiteral(&quot;100%&quot;))
+    , m_height(LengthModeHeight, ASCIILiteral(&quot;100%&quot;))
</ins><span class="cx">     , m_useCurrentView(false)
</span><span class="cx">     , m_zoomAndPan(SVGZoomAndPanMagnify)
</span><span class="cx">     , m_timeContainer(SMILTimeContainer::create(this))
</span><span class="lines">@@ -257,11 +257,23 @@
</span><span class="cx">         setXBaseValue(SVGLength::construct(LengthModeWidth, value, parseError));
</span><span class="cx">     else if (name == SVGNames::yAttr)
</span><span class="cx">         setYBaseValue(SVGLength::construct(LengthModeHeight, value, parseError));
</span><del>-    else if (name == SVGNames::widthAttr)
-        setWidthBaseValue(SVGLength::construct(LengthModeWidth, value, parseError, ForbidNegativeLengths));
-    else if (name == SVGNames::heightAttr)
-        setHeightBaseValue(SVGLength::construct(LengthModeHeight, value, parseError, ForbidNegativeLengths));
-    else if (SVGLangSpace::parseAttribute(name, value)
</del><ins>+    else if (name == SVGNames::widthAttr) {
+        SVGLength length = SVGLength::construct(LengthModeWidth, value, parseError, ForbidNegativeLengths);
+        if (parseError != NoError || value.isEmpty()) {
+            // FIXME: This is definitely the correct behavior for a missing/removed attribute.
+            // Not sure it's correct for the empty string or for something that can't be parsed.
+            length = SVGLength(LengthModeWidth, ASCIILiteral(&quot;100%&quot;));
+        }
+        setWidthBaseValue(length);
+    } else if (name == SVGNames::heightAttr) {
+        SVGLength length = SVGLength::construct(LengthModeHeight, value, parseError, ForbidNegativeLengths);
+        if (parseError != NoError || value.isEmpty()) {
+            // FIXME: This is definitely the correct behavior for a removed attribute.
+            // Not sure it's correct for the empty string or for something that can't be parsed.
+            length = SVGLength(LengthModeHeight, ASCIILiteral(&quot;100%&quot;));
+        }
+        setHeightBaseValue(length);
+    } else if (SVGLangSpace::parseAttribute(name, value)
</ins><span class="cx">                || SVGExternalResourcesRequired::parseAttribute(name, value)
</span><span class="cx">                || SVGFitToViewBox::parseAttribute(this, name, value)
</span><span class="cx">                || SVGZoomAndPan::parseAttribute(this, name, value)) {
</span></span></pre></div>
<a id="trunkSourceWebCoresvgSVGUseElementcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/svg/SVGUseElement.cpp (179068 => 179069)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/svg/SVGUseElement.cpp        2015-01-24 19:14:44 UTC (rev 179068)
+++ trunk/Source/WebCore/svg/SVGUseElement.cpp        2015-01-24 19:55:58 UTC (rev 179069)
</span><span class="lines">@@ -213,6 +213,26 @@
</span><span class="cx">     return 0;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+static void updateWidthAndHeight(SVGElement&amp; shadowElement, const SVGUseElement&amp; useElement, const SVGElement&amp; originalElement)
+{
+    // FIXME: The check for valueInSpecifiedUnits being non-zero below is a workaround for the fact
+    // that we currently have no good way to tell whether a particular animatable attribute is a value
+    // indicating it was unspecified, or specified but could not be parsed. Would be nice to fix that some day.
+    if (is&lt;SVGSymbolElement&gt;(shadowElement)) {
+        // Spec (&lt;use&gt; on &lt;symbol&gt;): This generated 'svg' will always have explicit values for attributes width and height.
+        // If attributes width and/or height are provided on the 'use' element, then these attributes
+        // will be transferred to the generated 'svg'. If attributes width and/or height are not specified,
+        // the generated 'svg' element will use values of 100% for these attributes.
+        shadowElement.setAttribute(SVGNames::widthAttr, (useElement.widthIsValid() &amp;&amp; useElement.width().valueInSpecifiedUnits()) ? AtomicString(useElement.width().valueAsString()) : &quot;100%&quot;);
+        shadowElement.setAttribute(SVGNames::heightAttr, (useElement.heightIsValid() &amp;&amp; useElement.height().valueInSpecifiedUnits()) ? AtomicString(useElement.height().valueAsString()) : &quot;100%&quot;);
+    } else if (is&lt;SVGSVGElement&gt;(shadowElement)) {
+        // Spec (&lt;use&gt; on &lt;svg&gt;): If attributes width and/or height are provided on the 'use' element, then these
+        // values will override the corresponding attributes on the 'svg' in the generated tree.
+        shadowElement.setAttribute(SVGNames::widthAttr, (useElement.widthIsValid() &amp;&amp; useElement.width().valueInSpecifiedUnits()) ? AtomicString(useElement.width().valueAsString()) : originalElement.getAttribute(SVGNames::widthAttr));
+        shadowElement.setAttribute(SVGNames::heightAttr, (useElement.heightIsValid() &amp;&amp; useElement.height().valueInSpecifiedUnits()) ? AtomicString(useElement.height().valueAsString()) : originalElement.getAttribute(SVGNames::heightAttr));
+    }
+}
+
</ins><span class="cx"> void SVGUseElement::svgAttributeChanged(const QualifiedName&amp; attrName)
</span><span class="cx"> {
</span><span class="cx">     if (!isSupportedAttribute(attrName)) {
</span><span class="lines">@@ -222,13 +242,16 @@
</span><span class="cx"> 
</span><span class="cx">     SVGElementInstance::InvalidationGuard invalidationGuard(this);
</span><span class="cx"> 
</span><del>-    auto renderer = this-&gt;renderer();
-    if (attrName == SVGNames::xAttr
-        || attrName == SVGNames::yAttr
-        || attrName == SVGNames::widthAttr
-        || attrName == SVGNames::heightAttr) {
</del><ins>+    if (attrName == SVGNames::xAttr || attrName == SVGNames::yAttr || attrName == SVGNames::widthAttr || attrName == SVGNames::heightAttr) {
</ins><span class="cx">         updateRelativeLengthsInformation();
</span><del>-        if (renderer)
</del><ins>+        if (m_targetElementInstance) {
+            // FIXME: It's unnecessarily inefficient to do this work any time we change &quot;x&quot; or &quot;y&quot;.
+            // FIXME: It's unnecessarily inefficient to update both width and height each time either is changed.
+            ASSERT(m_targetElementInstance-&gt;shadowTreeElement());
+            ASSERT(m_targetElementInstance-&gt;correspondingElement());
+            updateWidthAndHeight(*m_targetElementInstance-&gt;shadowTreeElement(), *this, *m_targetElementInstance-&gt;correspondingElement());
+        }
+        if (auto* renderer = this-&gt;renderer())
</ins><span class="cx">             RenderSVGResource::markForLayoutAndParentResourceInvalidation(*renderer);
</span><span class="cx">         return;
</span><span class="cx">     }
</span><span class="lines">@@ -429,6 +452,10 @@
</span><span class="cx">     // shadow tree elements &lt;-&gt; instances in the instance tree.
</span><span class="cx">     associateInstancesWithShadowTreeElements(shadowTreeRootElement-&gt;firstChild(), m_targetElementInstance.get());
</span><span class="cx"> 
</span><ins>+    ASSERT(m_targetElementInstance-&gt;shadowTreeElement());
+    ASSERT(m_targetElementInstance-&gt;correspondingElement() == target);
+    updateWidthAndHeight(*m_targetElementInstance-&gt;shadowTreeElement(), *this, *target);
+
</ins><span class="cx">     // If no shadow tree element is present, this means that the reference root
</span><span class="cx">     // element was removed, as it is disallowed (ie. &lt;use&gt; on &lt;foreignObject&gt;)
</span><span class="cx">     // Do NOT leave an inconsistent instance tree around, instead destruct it.
</span><span class="lines">@@ -651,7 +678,7 @@
</span><span class="cx"> 
</span><span class="cx">         if (target &amp;&amp; !isDisallowedElement(*target)) {
</span><span class="cx">             RefPtr&lt;Element&gt; newChild = target-&gt;cloneElementWithChildren(document());
</span><del>-            ASSERT(newChild-&gt;isSVGElement());
</del><ins>+            updateWidthAndHeight(downcast&lt;SVGElement&gt;(*newChild), use, *target);
</ins><span class="cx">             cloneParent-&gt;appendChild(newChild.release());
</span><span class="cx">         }
</span><span class="cx"> 
</span></span></pre>
</div>
</div>

</body>
</html>