Preserve explicit dimensions on <use>'d <symbol>

Per [1], 'width' and/or 'height' on a <use> override the corresponding
values on a referenced <svg> or <symbol>. If no 'width' or 'height' is
specified on the <use>, the values set on the referenced elements are
retained.
Previously we would always set 'width' / 'height' on a referenced
<symbol> to '100%' if the <use> did not have any overriding values.
Change this to follow the specification and copy the values from the
original element as needed - much like what was previously done for
referenced <svg> elements.

[1] https://svgwg.org/svg2-draft/struct.html#UseLayout

Bug: 806289
Change-Id: Iaf595ff88af2865a080f95ccc414e283828c195e
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1530883
Reviewed-by: Stephen Chenney <schenney@chromium.org>
Commit-Queue: Fredrik Söderquist <fs@opera.com>
Cr-Commit-Position: refs/heads/master@{#642150}
diff --git a/third_party/blink/renderer/core/svg/svg_use_element.cc b/third_party/blink/renderer/core/svg/svg_use_element.cc
index 94f3e09a..dfb672c 100644
--- a/third_party/blink/renderer/core/svg/svg_use_element.cc
+++ b/third_party/blink/renderer/core/svg/svg_use_element.cc
@@ -139,41 +139,31 @@
     const SVGUseElement& use,
     SVGElement& shadow_element,
     const SVGElement& original_element) {
-  DEFINE_STATIC_LOCAL(const AtomicString, hundred_percent_string, ("100%"));
-  // Use |originalElement| for checking the element type, because we will
+  // Use |original_element| for checking the element type, because we will
   // have replaced a <symbol> with an <svg> in the instance tree.
-  if (IsSVGSymbolElement(original_element)) {
-    // Spec (<use> on <symbol>): 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.
-    shadow_element.setAttribute(
-        svg_names::kWidthAttr,
-        use.width()->IsSpecified()
-            ? AtomicString(use.width()->CurrentValue()->ValueAsString())
-            : hundred_percent_string);
-    shadow_element.setAttribute(
-        svg_names::kHeightAttr,
-        use.height()->IsSpecified()
-            ? AtomicString(use.height()->CurrentValue()->ValueAsString())
-            : hundred_percent_string);
-  } else if (IsSVGSVGElement(original_element)) {
-    // Spec (<use> on <svg>): 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.
-    shadow_element.setAttribute(
-        svg_names::kWidthAttr,
-        use.width()->IsSpecified()
-            ? AtomicString(use.width()->CurrentValue()->ValueAsString())
-            : original_element.getAttribute(svg_names::kWidthAttr));
-    shadow_element.setAttribute(
-        svg_names::kHeightAttr,
-        use.height()->IsSpecified()
-            ? AtomicString(use.height()->CurrentValue()->ValueAsString())
-            : original_element.getAttribute(svg_names::kHeightAttr));
-  }
+  if (!IsSVGSymbolElement(original_element) &&
+      !IsSVGSVGElement(original_element))
+    return;
+
+  // "The width and height properties on the 'use' element override the values
+  // for the corresponding properties on a referenced 'svg' or 'symbol' element
+  // when determining the used value for that property on the instance root
+  // element. However, if the computed value for the property on the 'use'
+  // element is auto, then the property is computed as normal for the element
+  // instance. ... Because auto is the initial value, if dimensions are not
+  // explicitly set on the 'use' element, the values set on the 'svg' or
+  // 'symbol' will be used as defaults."
+  // (https://svgwg.org/svg2-draft/struct.html#UseElement)
+  AtomicString width_value(
+      use.width()->IsSpecified()
+          ? use.width()->CurrentValue()->ValueAsString()
+          : original_element.getAttribute(svg_names::kWidthAttr));
+  shadow_element.setAttribute(svg_names::kWidthAttr, width_value);
+  AtomicString height_value(
+      use.height()->IsSpecified()
+          ? use.height()->CurrentValue()->ValueAsString()
+          : original_element.getAttribute(svg_names::kHeightAttr));
+  shadow_element.setAttribute(svg_names::kHeightAttr, height_value);
 }
 
 void SVGUseElement::CollectStyleForPresentationAttribute(
diff --git a/third_party/blink/web_tests/external/wpt/svg/struct/reftests/reference/green-100x100.svg b/third_party/blink/web_tests/external/wpt/svg/struct/reftests/reference/green-100x100.svg
new file mode 100644
index 0000000..1209414
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/svg/struct/reftests/reference/green-100x100.svg
@@ -0,0 +1,3 @@
+<svg xmlns="http://www.w3.org/2000/svg">
+  <rect width="100" height="100" fill="green"/>
+</svg>
diff --git a/third_party/blink/web_tests/external/wpt/svg/struct/reftests/use-svg-dimensions-override-001.svg b/third_party/blink/web_tests/external/wpt/svg/struct/reftests/use-svg-dimensions-override-001.svg
new file mode 100644
index 0000000..c658adc
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/svg/struct/reftests/use-svg-dimensions-override-001.svg
@@ -0,0 +1,18 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
+     xmlns:h="http://www.w3.org/1999/xhtml" width="800" height="600">
+  <title>'width' and 'height' from &#x3c;use&#x3e; overrides values on referenced &#x3c;svg&#x3e;</title>
+  <h:link rel="help" href="https://svgwg.org/svg2-draft/struct.html#UseLayout"/>
+  <h:link rel="match" href="reference/green-100x100.svg"/>
+  <defs>
+    <svg id="s" width="10" height="10">
+      <rect width="100%" height="100%" fill="green"/>
+    </svg>
+  </defs>
+  <rect width="100" height="100" fill="red"/>
+  <svg width="1" height="1" overflow="visible">
+    <use xlink:href="#s" x="90" y="90"/>
+    <use xlink:href="#s" y="90" width="90"/>
+    <use xlink:href="#s" x="90" height="90"/>
+    <use xlink:href="#s" width="90" height="90"/>
+  </svg>
+</svg>
diff --git a/third_party/blink/web_tests/external/wpt/svg/struct/reftests/use-svg-dimensions-override-002.svg b/third_party/blink/web_tests/external/wpt/svg/struct/reftests/use-svg-dimensions-override-002.svg
new file mode 100644
index 0000000..6c3f97b8
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/svg/struct/reftests/use-svg-dimensions-override-002.svg
@@ -0,0 +1,18 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
+     xmlns:h="http://www.w3.org/1999/xhtml" width="800" height="600">
+  <title>'width' and 'height' from &#x3c;use&#x3e; overrides values on referenced &#x3c;svg&#x3e;</title>
+  <h:link rel="help" href="https://svgwg.org/svg2-draft/struct.html#UseLayout"/>
+  <h:link rel="match" href="reference/green-100x100.svg"/>
+  <defs>
+    <svg id="s">
+      <rect width="100%" height="100%" fill="green"/>
+    </svg>
+  </defs>
+  <rect width="100" height="100" fill="red"/>
+  <svg width="10" height="10" overflow="visible">
+    <use xlink:href="#s" x="90" y="90"/>
+    <use xlink:href="#s" y="90" width="90"/>
+    <use xlink:href="#s" x="90" height="90"/>
+    <use xlink:href="#s" width="90" height="90"/>
+  </svg>
+</svg>
diff --git a/third_party/blink/web_tests/external/wpt/svg/struct/reftests/use-symbol-dimensions-override-001.svg b/third_party/blink/web_tests/external/wpt/svg/struct/reftests/use-symbol-dimensions-override-001.svg
new file mode 100644
index 0000000..1f8f714
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/svg/struct/reftests/use-symbol-dimensions-override-001.svg
@@ -0,0 +1,18 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
+     xmlns:h="http://www.w3.org/1999/xhtml" width="800" height="600">
+  <title>'width' and 'height' from &#x3c;use&#x3e; overrides values on referenced &#x3c;symbol&#x3e;</title>
+  <h:link rel="help" href="https://svgwg.org/svg2-draft/struct.html#UseLayout"/>
+  <h:link rel="match" href="reference/green-100x100.svg"/>
+  <defs>
+    <symbol id="s" width="10" height="10">
+      <rect width="100%" height="100%" fill="green"/>
+    </symbol>
+  </defs>
+  <rect width="100" height="100" fill="red"/>
+  <svg width="1" height="1" overflow="visible">
+    <use xlink:href="#s" x="90" y="90"/>
+    <use xlink:href="#s" y="90" width="90"/>
+    <use xlink:href="#s" x="90" height="90"/>
+    <use xlink:href="#s" width="90" height="90"/>
+  </svg>
+</svg>
diff --git a/third_party/blink/web_tests/external/wpt/svg/struct/reftests/use-symbol-dimensions-override-002.svg b/third_party/blink/web_tests/external/wpt/svg/struct/reftests/use-symbol-dimensions-override-002.svg
new file mode 100644
index 0000000..9c1fd49
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/svg/struct/reftests/use-symbol-dimensions-override-002.svg
@@ -0,0 +1,18 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
+     xmlns:h="http://www.w3.org/1999/xhtml" width="800" height="600">
+  <title>'width' and 'height' from &#x3c;use&#x3e; overrides values on referenced &#x3c;symbol&#x3e;</title>
+  <h:link rel="help" href="https://svgwg.org/svg2-draft/struct.html#UseLayout"/>
+  <h:link rel="match" href="reference/green-100x100.svg"/>
+  <defs>
+    <symbol id="s">
+      <rect width="100%" height="100%" fill="green"/>
+    </symbol>
+  </defs>
+  <rect width="100" height="100" fill="red"/>
+  <svg width="10" height="10" overflow="visible">
+    <use xlink:href="#s" x="90" y="90"/>
+    <use xlink:href="#s" y="90" width="90"/>
+    <use xlink:href="#s" x="90" height="90"/>
+    <use xlink:href="#s" width="90" height="90"/>
+  </svg>
+</svg>
diff --git a/third_party/blink/web_tests/paint/invalidation/svg/relative-sized-shadow-tree-content-with-symbol.xhtml b/third_party/blink/web_tests/paint/invalidation/svg/relative-sized-shadow-tree-content-with-symbol.xhtml
index 663ebcd8..bce218c7 100644
--- a/third_party/blink/web_tests/paint/invalidation/svg/relative-sized-shadow-tree-content-with-symbol.xhtml
+++ b/third_party/blink/web_tests/paint/invalidation/svg/relative-sized-shadow-tree-content-with-symbol.xhtml
@@ -7,7 +7,7 @@
     <div id="contentBox" style="width: 100px; height: 400px; border: 1px solid red;">
         <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="100%" height="100%">
             <defs>
-                <symbol id="targetSymbol" viewBox="0 0 200 200" width="50%" height="50%">
+                <symbol id="targetSymbol" viewBox="0 0 200 200">
                     <rect x="50%" y="50%" width="50%" height="50%" fill="green"/>
                     <rect width="100" height="100" fill="green"/>
                 </symbol>
diff --git a/third_party/blink/web_tests/svg/custom/use-symbol-initial-width-height-expected.html b/third_party/blink/web_tests/svg/custom/use-symbol-initial-width-height-expected.html
deleted file mode 100644
index f718ea6..0000000
--- a/third_party/blink/web_tests/svg/custom/use-symbol-initial-width-height-expected.html
+++ /dev/null
@@ -1,2 +0,0 @@
-<!DOCTYPE html>
-<div style="width: 100px; height: 100px; background-color: green"></div>
diff --git a/third_party/blink/web_tests/svg/custom/use-symbol-initial-width-height.html b/third_party/blink/web_tests/svg/custom/use-symbol-initial-width-height.html
deleted file mode 100644
index 7b4267d..0000000
--- a/third_party/blink/web_tests/svg/custom/use-symbol-initial-width-height.html
+++ /dev/null
@@ -1,8 +0,0 @@
-<!DOCTYPE html>
-<svg width="100" height="100">
-  <symbol id="s" width="0">
-    <rect width="100%" height="100%" fill="green"/>
-  </symbol>
-  <rect width="100%" height="100%" fill="red"/>
-  <use xlink:href="#s"/>
-</svg>