Bug 1486252 - Resolve mask-image url value as an image even if it contains reference. r=heycam
authorXidorn Quan <me@upsuper.org>
Tue, 04 Sep 2018 09:35:56 +1000
changeset 482863 c8c93f1fc5b226724c1e11584febee0e0fe9e85c
parent 482862 d630bee3155a4f3d6a0919cab6edf5ee84cbe1ab
child 482864 588887c7c597d2c7c84e6934768846351c04373c
child 482872 a00e7a0a9f19c7844a63163f94e082fe0c3166d5
push id232
push userfmarier@mozilla.com
push dateWed, 05 Sep 2018 20:45:54 +0000
reviewersheycam
bugs1486252
milestone63.0a1
Bug 1486252 - Resolve mask-image url value as an image even if it contains reference. r=heycam The corresponding handling code in the old style system can be found in: https://dxr.mozilla.org/mozilla-esr60/rev/dd52b41d2b775e5c7261ce52795268b7670635fc/layout/style/nsCSSDataBlock.cpp#65-106 mask-iage-url-hash.html is the test that don't pass without this change. Differential Revision: https://phabricator.services.mozilla.com/D4831
layout/style/nsStyleStruct.cpp
testing/web-platform/meta/MANIFEST.json
testing/web-platform/tests/css/css-masking/mask-image/mask-image-url-image-hash.html
testing/web-platform/tests/css/css-masking/mask-image/mask-image-url-image.html
testing/web-platform/tests/css/css-masking/mask-image/mask-image-url-local-mask.html
testing/web-platform/tests/css/css-masking/mask-image/mask-image-url-remote-mask.html
testing/web-platform/tests/css/css-masking/mask-image/reference/mask-image-ref.html
testing/web-platform/tests/css/css-masking/mask-image/support/image-with-ref.svg
testing/web-platform/tests/css/css-masking/mask-image/support/image.svg
testing/web-platform/tests/css/css-masking/mask-image/support/mask.svg
--- a/layout/style/nsStyleStruct.cpp
+++ b/layout/style/nsStyleStruct.cpp
@@ -1315,28 +1315,40 @@ nsStyleSVGReset::nsStyleSVGReset(const n
 void
 nsStyleSVGReset::FinishStyle(nsPresContext* aPresContext, const nsStyleSVGReset* aOldStyle)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   NS_FOR_VISIBLE_IMAGE_LAYERS_BACK_TO_FRONT(i, mMask) {
     nsStyleImage& image = mMask.mLayers[i].mImage;
     if (image.GetType() == eStyleImageType_Image) {
-      // If the url of mask resource contains a reference('#'), it should be a
-      // <mask-source>, mostly. For a <mask-source>, there is no need to
-      // resolve this style image, since we do not depend on it to get the
-      // SVG mask resource.
-      if (!image.GetURLValue()->HasRef()) {
-        const nsStyleImage* oldImage =
-          (aOldStyle && aOldStyle->mMask.mLayers.Length() > i)
-          ? &aOldStyle->mMask.mLayers[i].mImage
-          : nullptr;
-
-        image.ResolveImage(aPresContext, oldImage);
+      URLValueData* url = image.GetURLValue();
+      // If the url is a local ref, it must be a <mask-resource>, so we don't
+      // need to resolve the style image.
+      if (url->IsLocalRef()) {
+        continue;
       }
+#if 0
+      // XXX The old style system also checks whether this is a reference to
+      // the current document with reference, but it doesn't seem to be a
+      // behavior mentioned anywhere, so we comment out the code for now.
+      nsIURI* docURI = aPresContext->Document()->GetDocumentURI();
+      if (url->EqualsExceptRef(docURI)) {
+        continue;
+      }
+#endif
+
+      // Otherwise, we may need the image even if it has a reference, in case
+      // the referenced element isn't a valid SVG <mask> element.
+      const nsStyleImage* oldImage =
+        (aOldStyle && aOldStyle->mMask.mLayers.Length() > i)
+        ? &aOldStyle->mMask.mLayers[i].mImage
+        : nullptr;
+
+      image.ResolveImage(aPresContext, oldImage);
     }
   }
 }
 
 nsChangeHint
 nsStyleSVGReset::CalcDifference(const nsStyleSVGReset& aNewData) const
 {
   nsChangeHint hint = nsChangeHint(0);
--- a/testing/web-platform/meta/MANIFEST.json
+++ b/testing/web-platform/meta/MANIFEST.json
@@ -125338,16 +125338,64 @@
       [
        "/css/css-masking/clip/reference/clip-no-clipping-ref.html",
        "=="
       ]
      ],
      {}
     ]
    ],
+   "css/css-masking/mask-image/mask-image-url-image-hash.html": [
+    [
+     "/css/css-masking/mask-image/mask-image-url-image-hash.html",
+     [
+      [
+       "/css/css-masking/mask-image/reference/mask-image-ref.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-masking/mask-image/mask-image-url-image.html": [
+    [
+     "/css/css-masking/mask-image/mask-image-url-image.html",
+     [
+      [
+       "/css/css-masking/mask-image/reference/mask-image-ref.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-masking/mask-image/mask-image-url-local-mask.html": [
+    [
+     "/css/css-masking/mask-image/mask-image-url-local-mask.html",
+     [
+      [
+       "/css/css-masking/mask-image/reference/mask-image-ref.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-masking/mask-image/mask-image-url-remote-mask.html": [
+    [
+     "/css/css-masking/mask-image/mask-image-url-remote-mask.html",
+     [
+      [
+       "/css/css-masking/mask-image/reference/mask-image-ref.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
    "css/css-masking/test-mask.html": [
     [
      "/css/css-masking/test-mask.html",
      [
       [
        "/css/css-masking/test-mask-ref.html",
        "=="
       ]
@@ -256691,16 +256739,36 @@
      {}
     ]
    ],
    "css/css-masking/clip/reference/clip-vertical-stripe-ref.html": [
     [
      {}
     ]
    ],
+   "css/css-masking/mask-image/reference/mask-image-ref.html": [
+    [
+     {}
+    ]
+   ],
+   "css/css-masking/mask-image/support/image-with-ref.svg": [
+    [
+     {}
+    ]
+   ],
+   "css/css-masking/mask-image/support/image.svg": [
+    [
+     {}
+    ]
+   ],
+   "css/css-masking/mask-image/support/mask.svg": [
+    [
+     {}
+    ]
+   ],
    "css/css-masking/parsing/support/parsing-testcommon.js": [
     [
      {}
     ]
    ],
    "css/css-masking/test-mask-ref.html": [
     [
      {}
@@ -540547,16 +540615,48 @@
   "css/css-masking/clip/reference/clip-vertical-stripe-ref.html": [
    "96ccc2c19c428ddf3717c641db07bce710bb6690",
    "support"
   ],
   "css/css-masking/idlharness.html": [
    "c415eaaa67a2bc9a4b621700049eb0c0b60ec0a3",
    "testharness"
   ],
+  "css/css-masking/mask-image/mask-image-url-image-hash.html": [
+   "b1efc90818bec85d5022a9b908a14c2e0c35ff3b",
+   "reftest"
+  ],
+  "css/css-masking/mask-image/mask-image-url-image.html": [
+   "40a1ff9b281647a03cd90046cb62a088c0ed7081",
+   "reftest"
+  ],
+  "css/css-masking/mask-image/mask-image-url-local-mask.html": [
+   "18abc54f85eb4bfd93962dbef92dd5cffe5ba62b",
+   "reftest"
+  ],
+  "css/css-masking/mask-image/mask-image-url-remote-mask.html": [
+   "cfa3a6166cdcb41b2feaab2ffd5c087a568771f5",
+   "reftest"
+  ],
+  "css/css-masking/mask-image/reference/mask-image-ref.html": [
+   "4e121163f9d093b468e710882cb164bb965d9aa8",
+   "support"
+  ],
+  "css/css-masking/mask-image/support/image-with-ref.svg": [
+   "fe77fb37ac60a8a503d849d019c9ca391d9cf523",
+   "support"
+  ],
+  "css/css-masking/mask-image/support/image.svg": [
+   "28dbaa0238353b47b0d7877cac054d002352078a",
+   "support"
+  ],
+  "css/css-masking/mask-image/support/mask.svg": [
+   "30e601c87c32a08912e261dab22734033df1ef8e",
+   "support"
+  ],
   "css/css-masking/parsing/clip-invalid.html": [
    "18ae8b552a5904097a4b9f0f639b3d0ca123242b",
    "testharness"
   ],
   "css/css-masking/parsing/clip-path-invalid.html": [
    "3d33de251f6c046a6cd15a6cb84416563e2dc293",
    "testharness"
   ],
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-masking/mask-image/mask-image-url-image-hash.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<title>CSS Test: mask-image: url(image.svg#hash)</title>
+<link rel="author" title="Xidorn Quan" href="https://www.upsuper.org">
+<link rel="author" title="Mozilla" href="https://www.mozilla.org">
+<link rel="help" href="https://drafts.fxtf.org/css-masking-1/#mask-layer-image">
+<link rel="match" href="reference/mask-image-ref.html">
+<meta name="assert" content="mask-image can use an SVG file as an image with element reference">
+<style>
+#back {
+  position: absolute;
+  box-sizing: border-box;
+  width: 200px;
+  height: 200px;
+  border: 60px solid green;
+  background: red;
+}
+#front {
+  position: absolute;
+  box-sizing: border-box;
+  width: 200px;
+  height: 200px;
+  border: 40px solid red;
+  background: green;
+  mask-image: url(support/image-with-ref.svg#ref);
+}
+</style>
+<p>The test passes if there is a green square and no red below.</p>
+<div id="back"></div><div id="front"></div>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-masking/mask-image/mask-image-url-image.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<title>CSS Test: mask-image: url(image.svg)</title>
+<link rel="author" title="Xidorn Quan" href="https://www.upsuper.org">
+<link rel="author" title="Mozilla" href="https://www.mozilla.org">
+<link rel="help" href="https://drafts.fxtf.org/css-masking-1/#mask-layer-image">
+<link rel="match" href="reference/mask-image-ref.html">
+<meta name="assert" content="mask-image can use an SVG file as an image">
+<style>
+#back {
+  position: absolute;
+  box-sizing: border-box;
+  width: 200px;
+  height: 200px;
+  border: 60px solid green;
+  background: red;
+}
+#front {
+  position: absolute;
+  box-sizing: border-box;
+  width: 200px;
+  height: 200px;
+  border: 40px solid red;
+  background: green;
+  mask-image: url(support/image.svg);
+}
+</style>
+<p>The test passes if there is a green square and no red below.</p>
+<div id="back"></div><div id="front"></div>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-masking/mask-image/mask-image-url-local-mask.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<title>CSS Test: mask-image: url(#local-mask)</title>
+<link rel="author" title="Xidorn Quan" href="https://www.upsuper.org">
+<link rel="author" title="Mozilla" href="https://www.mozilla.org">
+<link rel="help" href="https://drafts.fxtf.org/css-masking-1/#mask-layer-image">
+<link rel="match" href="reference/mask-image-ref.html">
+<meta name="assert" content="mask-image can use local reference to a &lt;mask&gt; element">
+<style>
+#back {
+  position: absolute;
+  box-sizing: border-box;
+  width: 200px;
+  height: 200px;
+  border: 60px solid green;
+  background: red;
+}
+#front {
+  position: absolute;
+  box-sizing: border-box;
+  width: 200px;
+  height: 200px;
+  border: 40px solid red;
+  background: green;
+  mask-image: url(#localmask);
+}
+</style>
+<p>The test passes if there is a green square and no red below.</p>
+<div id="back"></div><div id="front"></div>
+<svg viewBox="0 0 200 200" style="width: 0; height: 0">
+  <mask id="localmask">
+    <rect x="50" y="50" width="100" height="100" fill="white">
+  </mask>
+</svg>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-masking/mask-image/mask-image-url-remote-mask.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<title>CSS Test: mask-image: url(remote.svg#mask)</title>
+<link rel="author" title="Xidorn Quan" href="https://www.upsuper.org">
+<link rel="author" title="Mozilla" href="https://www.mozilla.org">
+<link rel="help" href="https://drafts.fxtf.org/css-masking-1/#mask-layer-image">
+<link rel="match" href="reference/mask-image-ref.html">
+<meta name="assert" content="mask-image can use reference to a &lt;mask&gt; element from a remote SVG document">
+<style>
+#back {
+  position: absolute;
+  box-sizing: border-box;
+  width: 200px;
+  height: 200px;
+  border: 60px solid green;
+  background: red;
+}
+#front {
+  position: absolute;
+  box-sizing: border-box;
+  width: 200px;
+  height: 200px;
+  border: 40px solid red;
+  background: green;
+  mask-image: url(support/mask.svg#mask);
+}
+</style>
+<p>The test passes if there is a green square and no red below.</p>
+<div id="back"></div><div id="front"></div>
+<svg>
+  <!-- mask-image doesn't block onload, so we use an empty g here to
+       force mask.svg to load before onload. -->
+  <use href="support/mask.svg#empty"/>
+</svg>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-masking/mask-image/reference/mask-image-ref.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<title>CSS Reference: mask-image</title>
+<link rel="author" title="Xidorn Quan" href="https://www.upsuper.org">
+<link rel="author" title="Mozilla" href="https://www.mozilla.org">
+<style>
+#ref {
+  position: absolute;
+  width: 200px;
+  height: 200px;
+  background: green;
+}
+</style>
+<p>The test passes if there is a green square and no red below.</p>
+<div id="ref"></div>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-masking/mask-image/support/image-with-ref.svg
@@ -0,0 +1,9 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200">
+  <style>
+    g { display: none; }
+    g:target { display: inline; }
+  </style>
+  <g id="ref">
+    <rect x="50" y="50" width="100" height="100" fill="black"/>
+  </g>
+</svg>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-masking/mask-image/support/image.svg
@@ -0,0 +1,3 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200">
+  <rect x="50" y="50" width="100" height="100" fill="black"/>
+</svg>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-masking/mask-image/support/mask.svg
@@ -0,0 +1,6 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200">
+  <mask id="mask">
+    <rect x="50" y="50" width="100" height="100" fill="white"/>
+  </mask>
+  <g id="empty"/>
+</svg>