Bug 1323962 - PaintSVG for container should consider CSS transform for its children r=longsonr
authorviolet <violet.bugreport@gmail.com>
Tue, 23 Apr 2019 00:03:00 +0000
changeset 470454 03ea838144b57003bee53950ae138e23bf0f8066
parent 470453 29ad5178399d2ae1743ff24838818e4f77ccfe39
child 470455 0d0d5b67b2cc524045672b67a13401cd0dbf939e
push id35906
push useraciure@mozilla.com
push dateTue, 23 Apr 2019 22:14:56 +0000
treeherdermozilla-central@0ce3633f8b80 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerslongsonr
bugs1323962
milestone68.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1323962 - PaintSVG for container should consider CSS transform for its children r=longsonr Container manages SVG/CSS transform of its children, thus PaintSVG of container should take children's CSS transform into account. Differential Revision: https://phabricator.services.mozilla.com/D28273
layout/reftests/svg/clipPath-css-transform-ref.html
layout/reftests/svg/clipPath-css-transform.html
layout/reftests/svg/marker-css-transform-ref.html
layout/reftests/svg/marker-css-transform.html
layout/reftests/svg/mask-css-transform-ref.html
layout/reftests/svg/mask-css-transform.html
layout/reftests/svg/non-scaling-stroke-css-transform-ref.html
layout/reftests/svg/non-scaling-stroke-css-transform.html
layout/reftests/svg/pattern-css-transform-ref.html
layout/reftests/svg/pattern-css-transform.html
layout/reftests/svg/reftest.list
layout/reftests/svg/test_bug1247218-ref.html
layout/reftests/svg/test_bug1247218.html
layout/reftests/svg/test_bug1323962-2-ref.html
layout/reftests/svg/test_bug1323962-2.html
layout/reftests/svg/test_bug1323962-3-ref.html
layout/reftests/svg/test_bug1323962-3.html
layout/reftests/svg/test_bug1323962-ref.html
layout/reftests/svg/test_bug1323962.html
layout/svg/nsSVGContainerFrame.cpp
layout/svg/nsSVGSwitchFrame.cpp
layout/svg/nsSVGUtils.cpp
rename from layout/reftests/svg/test_bug1323962-3-ref.html
rename to layout/reftests/svg/clipPath-css-transform-ref.html
rename from layout/reftests/svg/test_bug1323962-3.html
rename to layout/reftests/svg/clipPath-css-transform.html
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/marker-css-transform-ref.html
@@ -0,0 +1,12 @@
+<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
+  <defs>
+    <marker id="arrow" viewBox="0 0 10 10" refX="5" refY="5"
+        markerWidth="6" markerHeight="6"
+        orient="auto-start-reverse">
+      <path id="ap" transform="scale(2,2)" d="M 0 0 L 5 2.5 L 0 5 z" />
+    </marker>
+  </defs>
+
+  <polyline points="10,30 90,30" fill="none" stroke="black"
+   marker-start="url(#arrow)" marker-end="url(#arrow)"  />
+</svg>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/marker-css-transform.html
@@ -0,0 +1,17 @@
+<style>
+#ap {
+  transform: scale(2,2);
+}
+</style>
+<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
+  <defs>
+    <marker id="arrow" viewBox="0 0 10 10" refX="5" refY="5"
+        markerWidth="6" markerHeight="6"
+        orient="auto-start-reverse">
+      <path id="ap" d="M 0 0 L 5 2.5 L 0 5 z" />
+    </marker>
+  </defs>
+
+  <polyline points="10,30 90,30" fill="none" stroke="black"
+   marker-start="url(#arrow)" marker-end="url(#arrow)"  />
+</svg>
rename from layout/reftests/svg/test_bug1323962-ref.html
rename to layout/reftests/svg/mask-css-transform-ref.html
rename from layout/reftests/svg/test_bug1323962.html
rename to layout/reftests/svg/mask-css-transform.html
rename from layout/reftests/svg/test_bug1247218-ref.html
rename to layout/reftests/svg/non-scaling-stroke-css-transform-ref.html
rename from layout/reftests/svg/test_bug1247218.html
rename to layout/reftests/svg/non-scaling-stroke-css-transform.html
rename from layout/reftests/svg/test_bug1323962-2-ref.html
rename to layout/reftests/svg/pattern-css-transform-ref.html
--- a/layout/reftests/svg/test_bug1323962-2-ref.html
+++ b/layout/reftests/svg/pattern-css-transform-ref.html
@@ -1,9 +1,10 @@
 <svg width="200" height="200">
   <defs>
     <pattern id="Pattern" x="0" y="0" width=".25" height=".25">
-      <rect id="rec" x="0" y="0" width="30" height="30" fill="skyblue"/>
+      <rect x="0" y="0" width="30" height="30" fill="skyblue"/>
+      <rect x="40" y="40" width="10" height="10" fill="skyblue" />
     </pattern>
   </defs>
 
   <rect fill="url(#Pattern)" stroke="black" width="200" height="200"/>
 </svg>
rename from layout/reftests/svg/test_bug1323962-2.html
rename to layout/reftests/svg/pattern-css-transform.html
--- a/layout/reftests/svg/test_bug1323962-2.html
+++ b/layout/reftests/svg/pattern-css-transform.html
@@ -1,14 +1,20 @@
 <style>
-#rec {
+#rec1 {
   transform: scale(.6,.6);
 }
+#rec2 {
+  transform: translate(40px,40px) scale(.2,.2);
+}
 </style>
 <svg width="200" height="200">
   <defs>
     <pattern id="Pattern" x="0" y="0" width=".25" height=".25">
-      <rect id="rec" x="0" y="0" width="50" height="50" fill="skyblue"/>
+      <rect id="rec1" x="0" y="0" width="50" height="50" fill="skyblue"/>
+      <g>
+        <rect id="rec2" x="0" y="0" width="50" height="50" fill="skyblue"/>
+      </g>
     </pattern>
   </defs>
 
   <rect fill="url(#Pattern)" stroke="black" width="200" height="200"/>
 </svg>
--- a/layout/reftests/svg/reftest.list
+++ b/layout/reftests/svg/reftest.list
@@ -74,16 +74,17 @@ fuzzy-if(/^Windows\x20NT\x2010\.0/.test(
 == clipPath-basic-01.svg pass.svg
 == clipPath-basic-02.svg pass.svg
 == clipPath-basic-03.svg pass.svg
 == clipPath-basic-04.svg pass.svg
 == clipPath-basic-05.svg pass.svg
 == clipPath-basic-06.svg pass.svg
 == clipPath-basic-07.svg pass.svg
 == clipPath-basic-08.svg pass.svg
+== clipPath-css-transform.html clipPath-css-transform-ref.html
 == clipPath-on-outflowElement-01a.html clipPath-on-outflowElement-01-ref.html
 == clipPath-on-outflowElement-01b.html clipPath-on-outflowElement-01-ref.html
 fuzzy(0-1,0-32400) == clipPath-on-outflowElement-02a.html clipPath-on-outflowElement-02-ref.html
 fuzzy(0-1,0-32400) == clipPath-on-outflowElement-02b.html clipPath-on-outflowElement-02-ref.html
 == clipPath-polygon-01.svg pass.svg
 == clipPath-polygon-elementFromPoint-01.svg pass.svg
 != clipPath-on-thin-object.svg about:blank
 == clipPath-winding-01.svg pass.svg
@@ -139,36 +140,32 @@ fuzzy-if(d2d||skiaContent,0-1,0-10000) =
 == dynamic-inner-svg-01.svg pass.svg
 == dynamic-link-style-01.svg pass.svg
 == dynamic-marker-01.svg pass.svg
 == dynamic-marker-02.svg dynamic-marker-02-ref.svg
 == dynamic-marker-03.svg pass.svg
 == dynamic-mask-01.svg pass.svg
 == dynamic-mask-contents-01.svg pass.svg
 == dynamic-mask-pre-effects-bbox.html dynamic-mask-pre-effects-bbox-ref.html
-== test_bug1323962.html test_bug1323962-ref.html
-== test_bug1323962-2.html test_bug1323962-2-ref.html
-== test_bug1323962-3.html test_bug1323962-3-ref.html
 == dynamic-opacity-property-01.svg pass.svg
 == dynamic-pattern-01.svg pass.svg
 == dynamic-pattern-02.svg pass.svg
 == dynamic-pattern-contents-01.svg pass.svg
 == dynamic-pattern-contents-02.svg pass.svg
 == dynamic-rect-01.svg dynamic-rect-01-ref.svg
 fuzzy-if(d2d&&layersGPUAccelerated,0-3,0-1200) == dynamic-rect-02.svg dynamic-rect-02-ref.svg # bug 776038 for Win7, Win8
 == dynamic-rect-03.svg dynamic-rect-03-ref.svg
 == dynamic-rect-04.xhtml pass.svg
 == dynamic-rect-05.svg pass.svg
 == dynamic-reflow-01.svg dynamic-reflow-01-ref.svg
 == dynamic-small-object-scaled-up-01.svg pass.svg
 == dynamic-small-object-scaled-up-02.svg pass.svg
 == dynamic-stroke-01.svg pass.svg
 == dynamic-stroke-opacity-01.svg pass.svg
 == dynamic-stroke-width-01.svg pass.svg
-== test_bug1247218.html test_bug1247218-ref.html
 == dynamic-switch-01.svg pass.svg
 random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == dynamic-text-01.svg dynamic-text-01-ref.svg # bug 1392106
 fuzzy-if(d2d&&layersGPUAccelerated,0-3,0-12739) == dynamic-text-02.svg dynamic-text-02-ref.svg # bug 776038 for Win7, Win8
 fuzzy-if(d2d&&layersGPUAccelerated,0-2,0-10539) == dynamic-text-03.svg dynamic-text-03-ref.svg # bug 776038 for Win7
 random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == dynamic-text-04.svg dynamic-text-04-ref.svg # bug 776038 for Win7 # bug 1392106
 random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == dynamic-text-05.svg pass.svg # bug 1392106
 random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == dynamic-text-06.svg pass.svg # bug 1392106
 random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == dynamic-text-07.svg dynamic-text-07-ref.svg # bug 1392106
@@ -263,16 +260,17 @@ fuzzy-if(skiaContent,0-1,0-550) == impor
 fuzzy-if(cocoaWidget,0-15,0-19679) fuzzy-if(winWidget,0-1,0-8800) fuzzy-if(!cocoaWidget&&!winWidget,0-1,0-4000) fuzzy-if(skiaContent,0-1,0-5000) == linearGradient-basic-03.svg linearGradient-basic-03-ref.svg
 
 == linked-filter-01.svg pass.svg
 == linked-pattern-01.svg pass.svg
 
 fuzzy-if(/^Windows\x20NT\x2010\.0/.test(http.oscpu)||skiaContent,0-1,0-800000) == markers-and-group-opacity-01.svg markers-and-group-opacity-01-ref.svg
 == marker-attribute-01.svg pass.svg
 fuzzy-if(skiaContent,0-1,0-1) == marker-dynamic-opacity.html marker-dynamic-opacity-ref.html
+== marker-css-transform.html marker-css-transform-ref.html
 == marker-effects-01.svg marker-effects-01-ref.svg
 fuzzy-if(skiaContent,0-1,0-100) == marker-viewBox-01.svg marker-viewBox-01-ref.svg
 fuzzy-if(skiaContent,0-1,0-100) == marker-orientation-01.svg marker-orientation-01-ref.svg
 fuzzy-if(skiaContent,0-1,0-5) == marker-orientation-02.svg marker-orientation-02-ref.svg
 == marker-orientation-03.svg pass.svg
 == marker-orientation-04.svg pass.svg
 == marker-orientation-05.svg pass.svg
 
@@ -282,16 +280,17 @@ fuzzy(0-28,0-28) == mask-and-clipPath.ht
 == mask-basic-01.svg pass.svg
 fuzzy-if(skiaContent,0-1,0-10000) == mask-basic-02.svg mask-basic-02-ref.svg
 == mask-basic-03.svg pass.svg
 == mask-basic-04.svg pass.svg
 == mask-basic-05.svg pass.svg
 == mask-containing-masked-content-01.svg pass.svg
 == mask-contains-inner-svg-01.svg pass.svg
 == mask-contains-inner-svg-02.svg pass.svg
+== mask-css-transform.html mask-css-transform-ref.html
 == mask-empty-size.svg about:blank
 == mask-extref-dataURI-01.svg pass.svg
 fuzzy(0-128,0-141) == mask-img.html mask-img-ref.html
 == mask-on-outflowElement-01a.html clipPath-on-outflowElement-01-ref.html
 == mask-on-outflowElement-01b.html clipPath-on-outflowElement-01-ref.html
 fuzzy(0-1,0-5000) == mask-opacity-01.svg mask-opacity-01-ref.svg
 != mask-root-svg.svg about:blank
 == mask-transformed-01.svg mask-transformed-01-ref.svg
@@ -301,16 +300,18 @@ fuzzy(0-1,0-5000) == mask-opacity-01.svg
 fuzzy-if(d2d||skiaContent,0-1,0-6400) == mask-type-01.svg mask-type-01-ref.svg
 fuzzy-if(d2d||skiaContent,0-1,0-6400) == mask-type-02.svg mask-type-01-ref.svg
 fuzzy-if(d2d||skiaContent,0-1,0-6400) == mask-type-03.svg mask-type-01-ref.svg
 fuzzy-if(d2d||skiaContent,0-1,0-6400) == mask-type-04.svg mask-type-01-ref.svg
 == mask-use-element-01.svg pass.svg
 
 != nested-mask-mode.svg about:blank
 == nested-viewBox-01.svg pass.svg
+== non-scaling-stroke-css-transform.html non-scaling-stroke-css-transform-ref.html
+
 fuzzy-if(skiaContent,0-3,0-448000) == nesting-invalid-01.svg nesting-invalid-01-ref.svg
 
 fuzzy-if(d2d&&/^Windows\x20NT\x20(6\.1|10\.0)/.test(http.oscpu),0-63,0-168) fuzzy-if(cocoaWidget,0-1,0-122) fuzzy-if(skiaContent,0-2,0-1000) == non-scaling-stroke-01.svg non-scaling-stroke-01-ref.svg # bug 1074161 for Win7 and OSX 10.8
 fuzzy-if(gtkWidget,0-1,0-99) fuzzy-if(!contentSameGfxBackendAsCanvas,0-9,0-99) fuzzy-if(Android,0-9,0-586) == non-scaling-stroke-02.svg non-scaling-stroke-02-ref.svg
 == non-scaling-stroke-03.svg non-scaling-stroke-03-ref.svg
 
 == objectBoundingBox-and-clipPath.svg pass.svg
 # Bug 588684
@@ -356,16 +357,17 @@ fuzzy-if(skiaContent,0-1,0-400) == path-
 == path-07.svg path-07-ref.svg
 == path-08.svg pass.svg
 
 == pathLength-01.svg pass.svg
 == pathLength-02.svg pass.svg
 
 == pattern-basic-01.svg pass.svg
 fuzzy(0-1,0-5) skip-if(Android) == pattern-big-image.html pattern-big-image-ref.html
+== pattern-css-transform.html pattern-css-transform-ref.html
 == pattern-invalid-01.svg pattern-invalid-01-ref.svg
 fuzzy-if(skiaContent,0-1,0-5) == pattern-live-01a.svg pattern-live-01-ref.svg
 fuzzy-if(skiaContent,0-1,0-5) == pattern-live-01b.svg pattern-live-01-ref.svg
 fuzzy-if(skiaContent,0-1,0-5) == pattern-live-01c.svg pattern-live-01-ref.svg
 fuzzy-if(skiaContent,0-1,0-5) == pattern-scale-01a.svg pattern-scale-01-ref.svg
 == pattern-scale-01b.svg pattern-scale-01-ref.svg
 fuzzy-if(skiaContent,0-3,0-5) == pattern-scale-01c.svg pattern-scale-01-ref.svg
 fuzzy-if(webrender,0-2,0-227) == pattern-transform-presence-01.svg pattern-transform-presence-01-ref.svg
--- a/layout/svg/nsSVGContainerFrame.cpp
+++ b/layout/svg/nsSVGContainerFrame.cpp
@@ -255,17 +255,18 @@ void nsSVGDisplayContainerFrame::PaintSV
     // PaintFrameWithEffects() expects the transform that is passed to it to
     // include the transform to the passed frame's user space, so add it:
     const nsIContent* content = kid->GetContent();
     if (content->IsSVGElement()) {  // must check before cast
       const SVGElement* element = static_cast<const SVGElement*>(content);
       if (!element->HasValidDimensions()) {
         continue;  // nothing to paint for kid
       }
-      m = element->PrependLocalTransformsTo(m, eUserSpaceToParent);
+
+      m = nsSVGUtils::GetTransformMatrixInUserSpace(kid, this) * m;
       if (m.IsSingular()) {
         continue;
       }
     }
     nsSVGUtils::PaintFrameWithEffects(kid, aContext, m, aImgParams, aDirtyRect);
   }
 }
 
@@ -385,17 +386,19 @@ SVGBBox nsSVGDisplayContainerFrame::GetB
     nsSVGDisplayableFrame* svgKid = do_QueryFrame(kid);
     // content could be a XUL element so check for an SVG element before casting
     if (svgKid &&
         (!content->IsSVGElement() ||
          static_cast<const SVGElement*>(content)->HasValidDimensions())) {
       gfxMatrix transform = gfx::ThebesMatrix(aToBBoxUserspace);
       if (content->IsSVGElement()) {
         transform = static_cast<SVGElement*>(content)->PrependLocalTransformsTo(
-            transform);
+                        {}, eChildToUserSpace) *
+                    nsSVGUtils::GetTransformMatrixInUserSpace(kid, this) *
+                    transform;
       }
       // We need to include zero width/height vertical/horizontal lines, so we
       // have to use UnionEdges.
       bboxUnion.UnionEdges(
           svgKid->GetBBoxContribution(gfx::ToMatrix(transform), aFlags));
     }
     kid = kid->GetNextSibling();
   }
--- a/layout/svg/nsSVGSwitchFrame.cpp
+++ b/layout/svg/nsSVGSwitchFrame.cpp
@@ -98,18 +98,17 @@ void nsSVGSwitchFrame::PaintSVG(gfxConte
   if (StyleEffects()->mOpacity == 0.0) {
     return;
   }
 
   nsIFrame* kid = GetActiveChildFrame();
   if (kid) {
     gfxMatrix tm = aTransform;
     if (kid->GetContent()->IsSVGElement()) {
-      tm = static_cast<SVGElement*>(kid->GetContent())
-               ->PrependLocalTransformsTo(tm, eUserSpaceToParent);
+      tm = nsSVGUtils::GetTransformMatrixInUserSpace(kid, this) * tm;
     }
     nsSVGUtils::PaintFrameWithEffects(kid, aContext, tm, aImgParams,
                                       aDirtyRect);
   }
 }
 
 nsIFrame* nsSVGSwitchFrame::GetFrameForPoint(const gfxPoint& aPoint) {
   NS_ASSERTION(!NS_SVGDisplayListHitTestingEnabled() ||
@@ -250,17 +249,19 @@ SVGBBox nsSVGSwitchFrame::GetBBoxContrib
                                               uint32_t aFlags) {
   nsIFrame* kid = GetActiveChildFrame();
   nsSVGDisplayableFrame* svgKid = do_QueryFrame(kid);
   if (svgKid) {
     nsIContent* content = kid->GetContent();
     gfxMatrix transform = ThebesMatrix(aToBBoxUserspace);
     if (content->IsSVGElement()) {
       transform = static_cast<SVGElement*>(content)->PrependLocalTransformsTo(
-          transform);
+                      {}, eChildToUserSpace) *
+                  nsSVGUtils::GetTransformMatrixInUserSpace(kid, this) *
+                  transform;
     }
     return svgKid->GetBBoxContribution(ToMatrix(transform), aFlags);
   }
   return SVGBBox();
 }
 
 nsIFrame* nsSVGSwitchFrame::GetActiveChildFrame() {
   nsIContent* activeChild =
--- a/layout/svg/nsSVGUtils.cpp
+++ b/layout/svg/nsSVGUtils.cpp
@@ -1636,18 +1636,17 @@ void nsSVGUtils::PaintSVGGlyph(Element* 
   nsSVGDisplayableFrame* svgFrame = do_QueryFrame(frame);
   if (!svgFrame) {
     return;
   }
   gfxMatrix m;
   if (frame->GetContent()->IsSVGElement()) {
     // PaintSVG() expects the passed transform to be the transform to its own
     // SVG user space, so we need to account for any 'transform' attribute:
-    m = static_cast<SVGElement*>(frame->GetContent())
-            ->PrependLocalTransformsTo(gfxMatrix(), eUserSpaceToParent);
+    m = nsSVGUtils::GetTransformMatrixInUserSpace(frame, frame->GetParent());
   }
 
   // SVG-in-OpenType is not allowed to paint external resources, so we can
   // just pass a dummy params into PatintSVG.
   imgDrawingParams dummy;
   svgFrame->PaintSVG(*aContext, m, dummy);
 }