Bug 1531890 - Take objectBoundingBox into account when a clipPath's child has its own clip-path. r=longsonr
authorCameron McCormack <cam@mcc.id.au>
Tue, 19 Mar 2019 01:18:21 +0000
changeset 464911 88a8be92d7ae625c67fb3023c690cf5ae82a0214
parent 464910 787bf156ee91f2cd9a986dfcdae97ce32b15fe21
child 464912 7517b9beb5e6ee204af8bd1f829fe9d578cc8123
push id35727
push userdvarga@mozilla.com
push dateTue, 19 Mar 2019 09:48:59 +0000
treeherdermozilla-central@70baa37ae1eb [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerslongsonr
bugs1531890
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 1531890 - Take objectBoundingBox into account when a clipPath's child has its own clip-path. r=longsonr Differential Revision: https://phabricator.services.mozilla.com/D23612
layout/svg/nsSVGClipPathFrame.cpp
layout/svg/nsSVGClipPathFrame.h
testing/web-platform/tests/css/css-masking/clip-path-svg-content/clip-path-content-clip-004.svg
testing/web-platform/tests/css/css-masking/clip-path-svg-content/reference/clip-path-content-clip-004-ref.svg
--- a/layout/svg/nsSVGClipPathFrame.cpp
+++ b/layout/svg/nsSVGClipPathFrame.cpp
@@ -152,17 +152,17 @@ void nsSVGClipPathFrame::PaintClipMask(g
     aMaskContext.PushGroupForBlendBack(gfxContentType::ALPHA, 1.0, maskSurface,
                                        maskTransform);
     // The corresponding PopGroupAndBlend call below will mask the
     // blend using |maskSurface|.
   }
 
   // Paint our children into the mask:
   for (nsIFrame* kid = mFrames.FirstChild(); kid; kid = kid->GetNextSibling()) {
-    PaintFrameIntoMask(kid, aClippedFrame, aMaskContext, aMatrix);
+    PaintFrameIntoMask(kid, aClippedFrame, aMaskContext);
   }
 
   if (maskUsage.shouldGenerateClipMaskLayer) {
     aMaskContext.PopGroupAndBlend();
   } else if (maskUsage.shouldApplyClipPath) {
     aMaskContext.PopClip();
   }
 
@@ -174,18 +174,17 @@ void nsSVGClipPathFrame::PaintClipMask(g
     ComposeExtraMask(maskDT, aExtraMask, aExtraMasksTransform);
   }
 
   *aMaskTransform = maskTransfrom;
 }
 
 void nsSVGClipPathFrame::PaintFrameIntoMask(nsIFrame* aFrame,
                                             nsIFrame* aClippedFrame,
-                                            gfxContext& aTarget,
-                                            const gfxMatrix& aMatrix) {
+                                            gfxContext& aTarget) {
   nsSVGDisplayableFrame* frame = do_QueryFrame(aFrame);
   if (!frame) {
     return;
   }
 
   // The CTM of each frame referencing us can be different.
   frame->NotifySVGChanged(nsSVGDisplayableFrame::TRANSFORM_CHANGED);
 
@@ -196,21 +195,22 @@ void nsSVGClipPathFrame::PaintFrameIntoM
                                               &clipPathThatClipsChild) ==
       SVGObserverUtils::eHasRefsSomeInvalid) {
     return;
   }
 
   nsSVGUtils::MaskUsage maskUsage;
   nsSVGUtils::DetermineMaskUsage(aFrame, true, maskUsage);
   if (maskUsage.shouldApplyClipPath) {
-    clipPathThatClipsChild->ApplyClipPath(aTarget, aClippedFrame, aMatrix);
+    clipPathThatClipsChild->ApplyClipPath(aTarget, aClippedFrame,
+                                          mMatrixForChildren);
   } else if (maskUsage.shouldGenerateClipMaskLayer) {
     Matrix maskTransform;
     RefPtr<SourceSurface> maskSurface = clipPathThatClipsChild->GetClipMask(
-        aTarget, aClippedFrame, aMatrix, &maskTransform);
+        aTarget, aClippedFrame, mMatrixForChildren, &maskTransform);
     aTarget.PushGroupForBlendBack(gfxContentType::ALPHA, 1.0, maskSurface,
                                   maskTransform);
     // The corresponding PopGroupAndBlend call below will mask the
     // blend using |maskSurface|.
   }
 
   gfxMatrix toChildsUserSpace = mMatrixForChildren;
   nsIFrame* child = do_QueryFrame(frame);
--- a/layout/svg/nsSVGClipPathFrame.h
+++ b/layout/svg/nsSVGClipPathFrame.h
@@ -140,17 +140,17 @@ class nsSVGClipPathFrame final : public 
  private:
   // nsSVGContainerFrame methods:
   virtual gfxMatrix GetCanvasTM() override;
 
   already_AddRefed<DrawTarget> CreateClipMask(gfxContext& aReferenceContext,
                                               mozilla::gfx::IntPoint& aOffset);
 
   void PaintFrameIntoMask(nsIFrame* aFrame, nsIFrame* aClippedFrame,
-                          gfxContext& aTarget, const gfxMatrix& aMatrix);
+                          gfxContext& aTarget);
 
   // Set, during a GetClipMask() call, to the transform that still needs to be
   // concatenated to the transform of the DrawTarget that was passed to
   // GetClipMask in order to establish the coordinate space that the clipPath
   // establishes for its contents (i.e. including applying 'clipPathUnits' and
   // any 'transform' attribute set on the clipPath) specifically for clipping
   // the frame that was passed to GetClipMask at that moment in time.  This is
   // set so that if our GetCanvasTM method is called while GetClipMask is
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-masking/clip-path-svg-content/clip-path-content-clip-004.svg
@@ -0,0 +1,29 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:html="http://www.w3.org/1999/xhtml">
+  <g id="testmeta">
+    <title>CSS Masking: clip-path applied to an element in a clipPath with objectBoundingBox units</title>
+    <html:link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"/>
+    <html:link rel="help" href="http://www.w3.org/TR/css-masking-1/#svg-clipping-paths"/>
+    <html:link rel="help" href="http://www.w3.org/TR/css-masking-1/#ClipPathElement"/>
+    <html:link rel="match" href="reference/clip-path-content-clip-004-ref.svg" />
+    <metadata class="flags">svg</metadata>
+    <desc class="assert">
+      When a clipPath establishes a coordinate system using objectBoundingBox
+      units, any other clipPath referenced through the clip-path property on
+      the first clipPath's children must use that same coordinate system if
+      it is using userSpaceOnUse units.
+    </desc>
+  </g>
+  <defs>
+    <clipPath id="inner">
+      <rect width="0.25" height="0.25"/>
+    </clipPath>
+    <clipPath id="outer" clipPathUnits="objectBoundingBox">
+      <rect width="0.5" height="0.5" clip-path="url(#inner)"/>
+    </clipPath>
+  </defs>
+  <rect width="100" height="100" fill="red"/>
+  <g clip-path="url(#outer)">
+    <rect width="400" height="400" fill="red"/>
+    <rect width="100" height="100" fill="green"/>
+  </g>
+</svg>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-masking/clip-path-svg-content/reference/clip-path-content-clip-004-ref.svg
@@ -0,0 +1,8 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:html="http://www.w3.org/1999/xhtml">
+  <g id="testmeta">
+    <title>CSS Reference</title>
+    <html:link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"/>
+    <metadata class="flags">svg</metadata>
+  </g>
+  <rect width="100" height="100" fill="green"/>
+</svg>