Bug 948265 - Fix user space to filter space transformation and example in nsSVGFilterInstance. r=mstange
authorMax Vujovic <mvujovic@adobe.com>
Sat, 15 Mar 2014 17:08:04 -0400
changeset 173785 82ac69ed8a52467dd69b8836013bc0a17963484d
parent 173784 55a2f006e3aa6c88b97cf6448e8ebf3a50787a89
child 173786 ef86012710e8c29cdf58a0a64f93d285ebf304c9
push id26420
push userkhuey@mozilla.com
push dateSun, 16 Mar 2014 00:40:14 +0000
treeherdermozilla-central@e182de48f628 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmstange
bugs948265
milestone30.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 948265 - Fix user space to filter space transformation and example in nsSVGFilterInstance. r=mstange
layout/reftests/svg/filters/fePointLight-zoomed-page-ref.svg
layout/reftests/svg/filters/fePointLight-zoomed-page.svg
layout/reftests/svg/filters/reftest.list
layout/svg/nsSVGFilterInstance.cpp
layout/svg/nsSVGFilterInstance.h
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/filters/fePointLight-zoomed-page-ref.svg
@@ -0,0 +1,15 @@
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <defs>
+        <filter id="illuminate-center">
+            <feDiffuseLighting in="SourceGraphic" result="light" lighting-color="white">
+                <fePointLight x="100" y="100" z="100"/>
+            </feDiffuseLighting>
+            <feComposite in="SourceGraphic" in2="light" operator="arithmetic" k1="1" k2="0" k3="0" k4="0"/>
+        </filter>
+    </defs>
+    <rect width="200" height="200" fill="green" filter="url(#illuminate-center)"/>
+</svg>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/filters/fePointLight-zoomed-page.svg
@@ -0,0 +1,29 @@
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!--
+     This test verifies that fePointLight stays in the right place when the user
+     zooms the page.
+
+     If the test passes, you should see a green box with its center illuminated
+     by a point light. If the test fails, the illumination will be off-center.
+
+     This test checks that SVG filters transform points in user space to points
+     in filter space correctly.
+
+     The root SVG element specifies a width and height to prevent scrollbars
+     from appearing when the page is zoomed.
+-->
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
+     reftest-zoom="2.0" width="100" height="100">
+    <defs>
+        <filter id="illuminate-center">
+            <feDiffuseLighting in="SourceGraphic" result="light" lighting-color="white">
+                <fePointLight x="50" y="50" z="50"/>
+            </feDiffuseLighting>
+            <feComposite in="SourceGraphic" in2="light" operator="arithmetic" k1="1" k2="0" k3="0" k4="0"/>
+        </filter>
+    </defs>
+    <rect width="100" height="100" fill="green" filter="url(#illuminate-center)"/>
+</svg>
--- a/layout/reftests/svg/filters/reftest.list
+++ b/layout/reftests/svg/filters/reftest.list
@@ -94,12 +94,14 @@ skip-if(B2G) == feDisplacementMap-scale-
 == feTile-large-01.svg pass.svg
 == feTile-large-02.svg feTile-large-02-ref.svg
 == feTile-outside-01.svg feTile-outside-01-ref.svg
 
 fuzzy(1,119) == feDiffuseLighting-1.svg feDiffuseLighting-1-ref.svg
 
 fuzzy(2,2659) skip-if(d2d) == feSpecularLighting-1.svg feSpecularLighting-1-ref.svg
 
+== fePointLight-zoomed-page.svg fePointLight-zoomed-page-ref.svg
+
 pref(layout.css.filters.enabled,true) == multiple-svg-filters.svg multiple-svg-filters-ref.svg
 pref(layout.css.filters.enabled,true) == multiple-svg-filters-long-chain.svg multiple-svg-filters-ref.svg
 pref(layout.css.filters.enabled,true) == multiple-svg-filters-second-uses-SourceGraphic.svg multiple-svg-filters-ref.svg
 pref(layout.css.filters.enabled,true) == multiple-svg-filters-with-multiple-primitives.svg multiple-svg-filters-ref.svg
--- a/layout/svg/nsSVGFilterInstance.cpp
+++ b/layout/svg/nsSVGFilterInstance.cpp
@@ -218,17 +218,17 @@ nsSVGFilterInstance::ConvertLocation(con
     val, mTargetBBox, mTargetFrame);
   gfxRect r = UserSpaceToFilterSpace(feArea);
   return Point3D(r.x, r.y, GetPrimitiveNumber(SVGContentUtils::XY, aPoint.z));
 }
 
 gfxRect
 nsSVGFilterInstance::UserSpaceToFilterSpace(const gfxRect& aUserSpaceRect) const
 {
-  return IntermediateSpaceToUserSpace(aUserSpaceRect - mUserSpaceBounds.TopLeft());
+  return UserSpaceToIntermediateSpace(aUserSpaceRect - mUserSpaceBounds.TopLeft());
 }
 
 gfxRect
 nsSVGFilterInstance::UserSpaceToIntermediateSpace(const gfxRect& aUserSpaceRect) const
 {
   gfxRect intermediateSpaceRect = aUserSpaceRect;
   intermediateSpaceRect.Scale(mUserSpaceToIntermediateSpaceScale.width,
                               mUserSpaceToIntermediateSpaceScale.height);
--- a/layout/svg/nsSVGFilterInstance.h
+++ b/layout/svg/nsSVGFilterInstance.h
@@ -54,20 +54,37 @@ class SVGFilterElement;
  * filter region:
  *   <filter id="f" x="-15" y="-15" width="130" height="130">...</filter>
  *
  * And apply the filter to a div element:
  *   <div style="filter: url(#f); ...">...</div>
  *
  * And let's say there are 2 device pixels for every 1 CSS pixel.
  *
- * Then:
- *   "user space" = the CSS pixel space of the <div>
- *   "intermediate space" = "user space" * 2
- *   "filter space" = "intermediate space" + 15
+ * Finally, let's define an arbitrary point in user space:
+ *   "user space point" = (10, 10)
+ *
+ * The point will be inset 10 CSS pixels from both the top and left edges of the
+ * div element's border box.
+ *
+ * Now, let's transform the point from user space to intermediate space:
+ *   "intermediate space point" = "user space point" * "device pixels per CSS pixel"
+ *   "intermediate space point" = (10, 10) * 2
+ *   "intermediate space point" = (20, 20)
+ *
+ * Next, let's transform the point from user space to filter space:
+ *   "filter space point" = ("user space point" - "filter region position in user space") * "device pixels per CSS pixel"
+ *   "filter space point" = ((10, 10) - (-15, -15)) * 2
+ *   "filter space point" = (50, 50)
+ *
+ * Similarly, we can convert the point from intermediate space to filter space:
+ *   "filter space point" = "intermediate space point" - "filter region position in intermediate space"
+ *   "filter space point" = "intermediate space point" - ("filter region position in user space" * "device pixels per CSS pixel")
+ *   "filter space point" = (20, 20) - ((-15, -15) * 2)
+ *   "filter space point" = (50, 50)
  */
 class nsSVGFilterInstance
 {
   typedef mozilla::gfx::Point3D Point3D;
   typedef mozilla::gfx::IntRect IntRect;
   typedef mozilla::gfx::SourceSurface SourceSurface;
   typedef mozilla::gfx::FilterPrimitiveDescription FilterPrimitiveDescription;