Bug 1258650. Properly use aExtraMasksTransform when combining masks. r=Bas,a=kwierso
authorJeff Muizelaar <jmuizelaar@mozilla.com>
Thu, 31 Mar 2016 14:08:02 -0400
changeset 291098 afb08f0036485e6840155eb3104327345670cd63
parent 291097 165538409c04d972fd977d2ef26dcb1daa466983
child 291099 2204c405d07c203a32bad351200e81b43ac062c4
push id19656
push usergwagner@mozilla.com
push dateMon, 04 Apr 2016 13:43:23 +0000
treeherderb2g-inbound@e99061fde28a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersBas, kwierso
bugs1258650
milestone48.0a1
Bug 1258650. Properly use aExtraMasksTransform when combining masks. r=Bas,a=kwierso Previously we were ignoring the scale.
layout/reftests/svg/mask-and-clipPath-ref.html
layout/reftests/svg/mask-and-clipPath.html
layout/reftests/svg/reftest.list
layout/svg/nsSVGClipPathFrame.cpp
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/mask-and-clipPath-ref.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html>
+ <head>
+  <meta content="text/html; charset=utf-8" http-equiv="content-type"/>
+ </head>
+ <body>
+   <svg height="100%" preserveAspectRatio="none meet" viewBox="0 0 1070 462" width="100%">
+    <g height="462" width="1070">
+     <g mask="url(#mask-1)"  transform="translate(0,10)">
+      <g>
+       <path class="data-line" d="M30,260L61,266.5L900,266.5" fill="none" stroke="#cc0000" stroke-width="20" visibility="visible">
+       </path>
+      </g>
+     </g>
+    </g>
+    <g>
+     <g>
+      <mask id="mask-1">
+       <rect fill="#000" height="100%" width="100%" x="0" y="0">
+       </rect>
+       <rect fill="#fff" height="462" width="400" x="40" y="-10">
+       </rect>
+       <rect fill="#fff" height="460" width="100" x="800" y="-10">
+       </rect>
+       <rect fill="#000" height="447" offset="164" width="60" x="164" y="0">
+       </rect>
+       <rect fill="#000" height="447" offset="376" width="56" x="376" y="0">
+       </rect>
+      </mask>
+     </g>
+    </g>
+   </svg>
+ </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/mask-and-clipPath.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html>
+ <head>
+  <meta content="text/html; charset=utf-8" http-equiv="content-type"/>
+ </head>
+ <body>
+   <svg height="100%" preserveAspectRatio="none meet" viewBox="0 0 1070 462" width="100%">
+    <g height="462" width="1070">
+     <g clip-path="url(#clip-1)" mask="url(#mask-1)"  transform="translate(0,10)">
+      <g>
+       <path class="data-line" d="M30,260L61,266.5L900,266.5" fill="none" stroke="#cc0000" stroke-width="20" visibility="visible">
+       </path>
+      </g>
+     </g>
+    </g>
+    <g>
+     <clipPath id="clip-1">
+      <rect height="462" width="400" x="40" y="-10">
+      </rect>
+      <rect height="460" width="100" x="800" y="-10">
+      </rect>
+     </clipPath>
+     <g>
+      <mask id="mask-1">
+       <rect fill="#fff" height="100%" width="100%" x="0" y="0">
+       </rect>
+       <rect fill="#000" height="447" offset="164" width="60" x="164" y="0">
+       </rect>
+       <rect fill="#000" height="447" offset="376" width="56" x="376" y="0">
+       </rect>
+      </mask>
+     </g>
+    </g>
+   </svg>
+ </body>
+</html>
--- a/layout/reftests/svg/reftest.list
+++ b/layout/reftests/svg/reftest.list
@@ -211,16 +211,18 @@ fuzzy-if(skiaContent,1,5) pref(svg.marke
 == mask-basic-02.svg mask-basic-02-ref.svg
 == mask-basic-03.svg pass.svg
 == mask-basic-04.svg pass.svg
 == mask-extref-dataURI-01.svg pass.svg
 == mask-containing-masked-content-01.svg pass.svg
 == mask-transformed-01.svg mask-transformed-01-ref.svg
 == mask-transformed-02.svg pass.svg
 == mask-transformed-child-01.svg mask-transformed-child-01-ref.svg
+# fuzzy because of the differences between clipPath and mask clipping
+fuzzy(27,28) == mask-and-clipPath.html mask-and-clipPath-ref.html
 pref(layout.css.masking.enabled,true) fuzzy-if(d2d||skiaContent,1,6400) == mask-type-01.svg mask-type-01-ref.svg
 pref(layout.css.masking.enabled,true) fuzzy-if(d2d||skiaContent,1,6400) == mask-type-02.svg mask-type-01-ref.svg
 pref(layout.css.masking.enabled,true) fuzzy-if(d2d||skiaContent,1,6400) == mask-type-03.svg mask-type-01-ref.svg
 pref(layout.css.masking.enabled,true) fuzzy-if(d2d||skiaContent,1,6400) == mask-type-04.svg mask-type-01-ref.svg
 == nested-viewBox-01.svg pass.svg
 fuzzy-if(skiaContent,3,448000) == nesting-invalid-01.svg nesting-invalid-01-ref.svg
 fuzzy-if(d2d&&/^Windows\x20NT\x20(6\.1|10\.0)/.test(http.oscpu),63,168) fuzzy-if(cocoaWidget,1,122) fuzzy-if(skiaContent,2,1000) == non-scaling-stroke-01.svg non-scaling-stroke-01-ref.svg # bug 1074161 for Win7 and OSX 10.8
 fuzzy-if(gtkWidget,1,99) fuzzy-if(!contentSameGfxBackendAsCanvas,9,99) fuzzy-if(Android||B2G,9,586) == non-scaling-stroke-02.svg non-scaling-stroke-02-ref.svg
--- a/layout/svg/nsSVGClipPathFrame.cpp
+++ b/layout/svg/nsSVGClipPathFrame.cpp
@@ -227,26 +227,30 @@ nsSVGClipPathFrame::GetClipMask(gfxConte
       ctx->Restore();
     }
   }
 
   // Moz2D transforms in the opposite direction to Thebes
   mat.Invert();
 
   if (aExtraMask) {
-    MOZ_ASSERT(!aExtraMasksTransform.HasNonTranslation());
-
+    // We could potentially due this more efficiently with OPERATOR_IN
+    // but that operator does not work well on CG or D2D
     RefPtr<SourceSurface> currentMask = maskDT->Snapshot();
+    Matrix transform = maskDT->GetTransform();
     maskDT->SetTransform(Matrix());
     maskDT->ClearRect(Rect(0, 0,
                            devSpaceClipExtents.width,
                            devSpaceClipExtents.height));
-    maskDT->MaskSurface(SurfacePattern(currentMask, ExtendMode::CLAMP),
+    maskDT->SetTransform(aExtraMasksTransform * transform);
+    // draw currentMask with the inverse of the transform that we just so that
+    // it ends up in the same spot with aExtraMask transformed by aExtraMasksTransform
+    maskDT->MaskSurface(SurfacePattern(currentMask, ExtendMode::CLAMP, aExtraMasksTransform.Inverse() * ToMatrix(mat)),
                         aExtraMask,
-                        Point(aExtraMasksTransform._31, aExtraMasksTransform._32));
+                        Point(0, 0));
   }
 
   *aMaskTransform = ToMatrix(mat);
   return maskDT->Snapshot();
 }
 
 bool
 nsSVGClipPathFrame::PointIsInsideClipPath(nsIFrame* aClippedFrame,