Backed out changeset c14980a16210 (bug 948265) so it can address review comments first, despite the CLOSED TREE
authorWes Kocher <wkocher@mozilla.com>
Fri, 28 Feb 2014 14:48:31 -0800
changeset 171695 57cd2113f04409db47f71fa5f4f43a675e8d25a0
parent 171694 b8c1ff82160e557b0d08f75abd4161fa309df22d
child 171696 49d61a8f1e5c40e16d599a055e14f6371472e813
push id270
push userpvanderbeken@mozilla.com
push dateThu, 06 Mar 2014 09:24:21 +0000
bugs948265
milestone30.0a1
backs outc14980a16210e7240183b2387938577314d6ce64
Backed out changeset c14980a16210 (bug 948265) so it can address review comments first, despite the CLOSED TREE
content/base/src/nsGkAtomList.h
content/base/src/nsTreeSanitizer.cpp
content/svg/content/src/SVGFilterElement.cpp
content/svg/content/src/SVGFilterElement.h
content/svg/content/test/dataTypes-helper.svg
content/svg/content/test/test_dataTypes.html
content/svg/content/test/test_dataTypesModEvents.html
dom/webidl/SVGFilterElement.webidl
layout/reftests/svg/filters/feDiffuseLighting-1.svg
layout/reftests/svg/filters/feDisplacementMap-scale-01.svg
layout/reftests/svg/filters/feDistantLight-filterRes-01-ref.svg
layout/reftests/svg/filters/feDistantLight-filterRes-01.svg
layout/reftests/svg/filters/feSpecularLighting-1.svg
layout/reftests/svg/filters/filter-filterRes-high-01.svg
layout/reftests/svg/filters/filter-filterRes-high-02.svg
layout/reftests/svg/filters/filter-filterRes-low-01.svg
layout/reftests/svg/filters/reftest.list
layout/reftests/svg/smil/anim-feGaussianBlur-01.svg
layout/reftests/svg/smil/anim-filter-filterRes-01.svg
layout/reftests/svg/smil/reftest.list
layout/svg/crashtests/453754-1.svg
layout/svg/crashtests/474700-1.svg
layout/svg/nsSVGFilterFrame.cpp
layout/svg/nsSVGFilterFrame.h
layout/svg/nsSVGFilterInstance.cpp
layout/svg/nsSVGFilterInstance.h
parser/html/javasrc/AttributeName.java
parser/html/nsHtml5AtomList.h
parser/html/nsHtml5AttributeName.cpp
parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests11.dat
--- a/content/base/src/nsGkAtomList.h
+++ b/content/base/src/nsGkAtomList.h
@@ -1270,16 +1270,17 @@ GK_ATOM(fePointLight, "fePointLight")
 GK_ATOM(feSpecularLighting, "feSpecularLighting")
 GK_ATOM(feSpotLight, "feSpotLight")
 GK_ATOM(feTile, "feTile")
 GK_ATOM(feTurbulence, "feTurbulence")
 GK_ATOM(fill, "fill")
 GK_ATOM(fill_opacity, "fill-opacity")
 GK_ATOM(fill_rule, "fill-rule")
 GK_ATOM(filter, "filter")
+GK_ATOM(filterRes, "filterRes")
 GK_ATOM(filterUnits, "filterUnits")
 GK_ATOM(flood_color, "flood-color")
 GK_ATOM(flood_opacity, "flood-opacity")
 GK_ATOM(font_face, "font-face")
 GK_ATOM(font_face_format, "font-face-format")
 GK_ATOM(font_face_name, "font-face-name")
 GK_ATOM(font_face_src, "font-face-src")
 GK_ATOM(font_face_uri, "font-face-uri")
--- a/content/base/src/nsTreeSanitizer.cpp
+++ b/content/base/src/nsTreeSanitizer.cpp
@@ -411,16 +411,17 @@ nsIAtom** const kAttributesSVG[] = {
   &nsGkAtoms::edgeMode, // edgeMode
   &nsGkAtoms::elevation, // elevation
   // enable-background
   &nsGkAtoms::end, // end
   &nsGkAtoms::fill, // fill
   &nsGkAtoms::fill_opacity, // fill-opacity
   &nsGkAtoms::fill_rule, // fill-rule
   &nsGkAtoms::filter, // filter
+  &nsGkAtoms::filterRes, // filterRes
   &nsGkAtoms::filterUnits, // filterUnits
   &nsGkAtoms::flood_color, // flood-color
   &nsGkAtoms::flood_opacity, // flood-opacity
   // XXX focusable
   &nsGkAtoms::font, // font
   &nsGkAtoms::font_family, // font-family
   &nsGkAtoms::font_size, // font-size
   &nsGkAtoms::font_size_adjust, // font-size-adjust
--- a/content/svg/content/src/SVGFilterElement.cpp
+++ b/content/svg/content/src/SVGFilterElement.cpp
@@ -25,16 +25,21 @@ SVGFilterElement::WrapNode(JSContext *aC
 nsSVGElement::LengthInfo SVGFilterElement::sLengthInfo[4] =
 {
   { &nsGkAtoms::x, -10, nsIDOMSVGLength::SVG_LENGTHTYPE_PERCENTAGE, SVGContentUtils::X },
   { &nsGkAtoms::y, -10, nsIDOMSVGLength::SVG_LENGTHTYPE_PERCENTAGE, SVGContentUtils::Y },
   { &nsGkAtoms::width, 120, nsIDOMSVGLength::SVG_LENGTHTYPE_PERCENTAGE, SVGContentUtils::X },
   { &nsGkAtoms::height, 120, nsIDOMSVGLength::SVG_LENGTHTYPE_PERCENTAGE, SVGContentUtils::Y },
 };
 
+nsSVGElement::IntegerPairInfo SVGFilterElement::sIntegerPairInfo[1] =
+{
+  { &nsGkAtoms::filterRes, 0 }
+};
+
 nsSVGElement::EnumInfo SVGFilterElement::sEnumInfo[2] =
 {
   { &nsGkAtoms::filterUnits,
     sSVGUnitTypesMap,
     SVG_UNIT_TYPE_OBJECTBOUNDINGBOX
   },
   { &nsGkAtoms::primitiveUnits,
     sSVGUnitTypesMap,
@@ -95,16 +100,36 @@ SVGFilterElement::FilterUnits()
 }
 
 already_AddRefed<SVGAnimatedEnumeration>
 SVGFilterElement::PrimitiveUnits()
 {
   return mEnumAttributes[PRIMITIVEUNITS].ToDOMAnimatedEnum(this);
 }
 
+already_AddRefed<SVGAnimatedInteger>
+SVGFilterElement::FilterResX()
+{
+  return mIntegerPairAttributes[FILTERRES].ToDOMAnimatedInteger(nsSVGIntegerPair::eFirst,
+                                                                this);
+}
+
+already_AddRefed<SVGAnimatedInteger>
+SVGFilterElement::FilterResY()
+{
+  return mIntegerPairAttributes[FILTERRES].ToDOMAnimatedInteger(nsSVGIntegerPair::eSecond,
+                                                                this);
+}
+
+void
+SVGFilterElement::SetFilterRes(uint32_t filterResX, uint32_t filterResY)
+{
+  mIntegerPairAttributes[FILTERRES].SetBaseValues(filterResX, filterResY, this);
+}
+
 already_AddRefed<SVGAnimatedString>
 SVGFilterElement::Href()
 {
   return mStringAttributes[HREF].ToDOMAnimatedString(this);
 }
 
 //----------------------------------------------------------------------
 // nsIContent methods
@@ -156,16 +181,23 @@ SVGFilterElement::HasValidDimensions() c
 
 nsSVGElement::LengthAttributesInfo
 SVGFilterElement::GetLengthInfo()
 {
   return LengthAttributesInfo(mLengthAttributes, sLengthInfo,
                               ArrayLength(sLengthInfo));
 }
 
+nsSVGElement::IntegerPairAttributesInfo
+SVGFilterElement::GetIntegerPairInfo()
+{
+  return IntegerPairAttributesInfo(mIntegerPairAttributes, sIntegerPairInfo,
+                                   ArrayLength(sIntegerPairInfo));
+}
+
 nsSVGElement::EnumAttributesInfo
 SVGFilterElement::GetEnumInfo()
 {
   return EnumAttributesInfo(mEnumAttributes, sEnumInfo,
                             ArrayLength(sEnumInfo));
 }
 
 nsSVGElement::StringAttributesInfo
--- a/content/svg/content/src/SVGFilterElement.h
+++ b/content/svg/content/src/SVGFilterElement.h
@@ -49,28 +49,36 @@ public:
 
   // WebIDL
   already_AddRefed<SVGAnimatedLength> X();
   already_AddRefed<SVGAnimatedLength> Y();
   already_AddRefed<SVGAnimatedLength> Width();
   already_AddRefed<SVGAnimatedLength> Height();
   already_AddRefed<SVGAnimatedEnumeration> FilterUnits();
   already_AddRefed<SVGAnimatedEnumeration> PrimitiveUnits();
+  already_AddRefed<SVGAnimatedInteger> FilterResX();
+  already_AddRefed<SVGAnimatedInteger> FilterResY();
+  void SetFilterRes(uint32_t filterResX, uint32_t filterResY);
   already_AddRefed<SVGAnimatedString> Href();
 
 protected:
 
   virtual LengthAttributesInfo GetLengthInfo() MOZ_OVERRIDE;
+  virtual IntegerPairAttributesInfo GetIntegerPairInfo() MOZ_OVERRIDE;
   virtual EnumAttributesInfo GetEnumInfo() MOZ_OVERRIDE;
   virtual StringAttributesInfo GetStringInfo() MOZ_OVERRIDE;
 
   enum { ATTR_X, ATTR_Y, ATTR_WIDTH, ATTR_HEIGHT };
   nsSVGLength2 mLengthAttributes[4];
   static LengthInfo sLengthInfo[4];
 
+  enum { FILTERRES };
+  nsSVGIntegerPair mIntegerPairAttributes[1];
+  static IntegerPairInfo sIntegerPairInfo[1];
+
   enum { FILTERUNITS, PRIMITIVEUNITS };
   nsSVGEnum mEnumAttributes[2];
   static EnumInfo sEnumInfo[2];
 
   enum { HREF };
   nsSVGString mStringAttributes[1];
   static StringInfo sStringInfo[1];
 };
--- a/content/svg/content/test/dataTypes-helper.svg
+++ b/content/svg/content/test/dataTypes-helper.svg
@@ -1,11 +1,12 @@
 <?xml version="1.0"?>
 <svg xmlns="http://www.w3.org/2000/svg" width="750">
   <defs>
+    <!-- <integer-optional-integer> (filterRes) -->
     <filter id="filter">
       <!-- <boolean> (preserveAlpha) -->
       <!-- <enum> (edgeMode) -->
       <!-- <number> (divisor) -->
       <!-- <integer> (targetX) -->
       <!-- <string> (result) -->
       <feConvolveMatrix id="convolve"/>
       <!-- <number-optional-number> (stdDeviation) -->
--- a/content/svg/content/test/test_dataTypes.html
+++ b/content/svg/content/test/test_dataTypes.html
@@ -117,16 +117,66 @@ function runTests()
   convolve.targetX.baseVal = 7;
   is(convolve.targetX.animVal, 7, "integer animVal");
   is(convolve.getAttribute("targetX"), "7", "integer attribute");
   convolve.setAttribute("targetX", "");
   ok(convolve.getAttribute("targetX") === "", "empty integer attribute");
   convolve.removeAttribute("targetX");
   ok(convolve.getAttribute("targetX") === null, "removed integer attribute");
 
+  // integer-optional-integer attribute
+
+  filter.setAttribute("filterRes", "100");
+  is(filter.filterResX.baseVal, 100, "integer-optional-integer first baseVal");
+  is(filter.filterResX.animVal, 100, "integer-optional-integer first animVal");
+  is(filter.filterResY.baseVal, 100, "integer-optional-integer second baseVal");
+  is(filter.filterResY.animVal, 100, "integer-optional-integer second animVal");
+
+  filter.filterResX.baseVal = 50;
+  is(filter.filterResX.animVal, 50, "integer-optional-integer first animVal");
+  is(filter.filterResY.animVal, 100, "integer-optional-integer second animVal");
+  is(filter.getAttribute("filterRes"), "50, 100", "integer-optional-integer attribute");
+
+  filter.filterResY.baseVal = 50;
+  is(filter.getAttribute("filterRes"), "50", "integer-optional-integer attribute");
+
+  filter.setFilterRes(80, 90);
+  is(filter.filterResX.baseVal, 80, "integer-optional-integer first baseVal");
+  is(filter.filterResX.animVal, 80, "integer-optional-integer first animVal");
+  is(filter.filterResY.baseVal, 90, "integer-optional-integer second baseVal");
+  is(filter.filterResY.animVal, 90, "integer-optional-integer second animVal");
+
+  // 32 bit integer range
+  filter.setFilterRes(-2147483648, 2147483647);
+  is(filter.filterResX.baseVal, -2147483648, "integer-optional-integer first baseVal");
+  is(filter.filterResX.animVal, -2147483648, "integer-optional-integer first animVal");
+  is(filter.filterResY.baseVal, 2147483647, "integer-optional-integer second baseVal");
+  is(filter.filterResY.animVal, 2147483647, "integer-optional-integer second animVal");
+
+  // too big, clamp
+  filter.setAttribute("filterRes", "-2147483649, 2147483648");
+  is(filter.filterResX.baseVal, -2147483648, "integer-optional-integer first baseVal");
+  is(filter.filterResX.animVal, -2147483648, "integer-optional-integer first animVal");
+  is(filter.filterResY.baseVal, 2147483647, "integer-optional-integer second baseVal");
+  is(filter.filterResY.animVal, 2147483647, "integer-optional-integer second animVal");
+
+  // invalid
+  filter.setAttribute("filterRes", "-00000000000invalid, 214748364720invalid");
+  is(filter.filterResX.baseVal, 0, "integer-optional-integer first baseVal");
+  is(filter.filterResX.animVal, 0, "integer-optional-integer first animVal");
+  is(filter.filterResY.baseVal, 0, "integer-optional-integer second baseVal");
+  is(filter.filterResY.animVal, 0, "integer-optional-integer second animVal");
+
+  filter.setAttribute("filterRes", "");
+  ok(filter.getAttribute("filterRes") === "",
+     "empty integer-optional-integer attribute");
+  filter.removeAttribute("filterRes");
+  ok(filter.getAttribute("filterRes") === null,
+     "removed integer-optional-integer attribute");
+
   // angle attribute
 
   marker.setAttribute("orient", "90deg");
   is(marker.orientAngle.baseVal.value, 90, "angle baseVal");
   is(marker.orientAngle.animVal.value, 90, "angle animVal");
 
   var baseAngle = marker.orientAngle.baseVal;
   var animAngle = marker.orientAngle.animVal;
--- a/content/svg/content/test/test_dataTypesModEvents.html
+++ b/content/svg/content/test/test_dataTypesModEvents.html
@@ -122,16 +122,31 @@ function runTests()
   eventChecker.expect("");
   convolve.setAttribute("targetX", "8");
   // Check redundant change when comparing attribute value to typed value
   eventChecker.expect("remove add");
   convolve.removeAttribute("targetX");
   convolve.setAttribute("targetX", "8");
   convolve.targetX.baseVal = 8;
 
+  // integer-optional-integer attribute
+
+  eventChecker.watchAttr(filter, "filterRes");
+  eventChecker.expect("add modify remove add");
+  filter.setAttribute("filterRes", "60, 70");
+  filter.filterResX.baseVal = 50;
+  filter.removeAttribute("filterRes");
+  filter.removeAttributeNS(null, "filterRes");
+  filter.setAttribute("filterRes", "50, 60");
+
+  eventChecker.expect("");
+  filter.filterResX.baseVal = 50;
+  filter.setAttribute("filterRes", "50, 60");
+  filter.filterResY.baseVal = 60;
+
   // angle attribute
 
   eventChecker.watchAttr(marker, "orient");
   eventChecker.expect("add modify modify modify modify modify remove add");
   marker.setAttribute("orient", "90deg");
   marker.orientAngle.baseVal.value = 12;
   marker.orientAngle.baseVal.valueInSpecifiedUnits = 23;
   marker.orientAngle.baseVal.valueAsString = "34";
--- a/dom/webidl/SVGFilterElement.webidl
+++ b/dom/webidl/SVGFilterElement.webidl
@@ -12,15 +12,18 @@
 
 interface SVGFilterElement : SVGElement {
   readonly attribute SVGAnimatedEnumeration filterUnits;
   readonly attribute SVGAnimatedEnumeration primitiveUnits;
   readonly attribute SVGAnimatedLength x;
   readonly attribute SVGAnimatedLength y;
   readonly attribute SVGAnimatedLength width;
   readonly attribute SVGAnimatedLength height;
+  readonly attribute SVGAnimatedInteger filterResX;
+  readonly attribute SVGAnimatedInteger filterResY;
 
+  void setFilterRes(unsigned long filterResX, unsigned long filterResY);
   // ImageData apply(ImageData source);
 };
 
 SVGFilterElement implements SVGURIReference;
 SVGFilterElement implements SVGUnitTypes;
 
--- a/layout/reftests/svg/filters/feDiffuseLighting-1.svg
+++ b/layout/reftests/svg/filters/feDiffuseLighting-1.svg
@@ -1,17 +1,17 @@
 <!--
      Any copyright is dedicated to the Public Domain.
      http://creativecommons.org/publicdomain/zero/1.0/
 -->
 <svg xmlns='http://www.w3.org/2000/svg' width='100px' height='100px'>
   <!--
     A basic test for the <feDiffuseLighting> filter primitive.
-    Setting kernelUnitLength on the <feDiffuseLighting> should allow us to
-    assume pixel perfection.
+    Setting filterRes on the <filter> and kernelUnitLength on the
+    <feDiffuseLighting> should allow us to assume pixel perfection.
     -->
-  <filter id='f' x='0' y='0' width='1' height='1'>
+  <filter id='f' x='0' y='0' width='1' height='1' filterRes='100 100'>
     <feDiffuseLighting kernelUnitLength='1'>
       <feDistantLight/>
     </feDiffuseLighting>
   </filter>
   <path d='M0,0 h100 v100 h-100 z M20,20 v60 h60 v-60 z' filter='url(#f)'/>
 </svg>
--- a/layout/reftests/svg/filters/feDisplacementMap-scale-01.svg
+++ b/layout/reftests/svg/filters/feDisplacementMap-scale-01.svg
@@ -1,15 +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">
   <title>Test that directionless filter primitive attributes are resolved to user units correctly</title>
   <!-- https://bugzilla.mozilla.org/show_bug.cgi?id=619967 -->
-  <filter id="f" filterUnits="userSpaceOnUse" x="0" y="0" width="400" height="200" color-interpolation-filters="sRGB">
+  <filter id="f" filterUnits="userSpaceOnUse" x="0" y="0" width="400" height="200" filterRes="400 100" color-interpolation-filters="sRGB">
     <feFlood flood-color="#800" result="map"/>
     <feDisplacementMap in="SourceGraphic" in2="map" xChannelSelector="R" yChannelSelector="G" scale="100"/>
   </filter>
   <rect width="100%" height="100%" fill="lime"/>
   <rect y="82" width="300" height="8" fill="red"/>
   <rect width="400" height="200" fill="lime" filter="url(#f)"/>
 </svg>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/filters/feDistantLight-filterRes-01-ref.svg
@@ -0,0 +1,19 @@
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<svg xmlns="http://www.w3.org/2000/svg">
+  <title>Reference for feDistantLight with filterRes larger than filter region</title>
+
+  <!-- From https://bugzilla.mozilla.org/show_bug.cgi?id=610466 -->
+  <defs>
+    <filter id="f" x="0" y="0" width="0.5" height="0.5" filterRes="50 50">
+      <feDiffuseLighting kernelUnitLength="1" lighting-color="lime">
+        <feDistantLight elevation="100"/>
+      </feDiffuseLighting>
+    </filter>
+  </defs>
+  <svg clip="rect(1px 48px 48px 1px)">
+    <path d="M0,0 h100 v100 h-100 z" filter="url(#f)"/>
+  </svg>
+</svg>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/filters/feDistantLight-filterRes-01.svg
@@ -0,0 +1,19 @@
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<svg xmlns="http://www.w3.org/2000/svg">
+  <title>Testcase for feDistantLight with filterRes larger than filter region</title>
+
+  <!-- From https://bugzilla.mozilla.org/show_bug.cgi?id=610466 -->
+  <defs>
+    <filter id="f" x="0" y="0" width="0.5" height="0.5" filterRes="60 60">
+      <feDiffuseLighting kernelUnitLength="1" lighting-color="lime">
+        <feDistantLight elevation="100"/>
+      </feDiffuseLighting>
+    </filter>
+  </defs>
+  <svg clip="rect(1px 48px 48px 1px)">
+    <path d="M0,0 h100 v100 h-100 z" filter="url(#f)"/>
+  </svg>
+</svg>
--- a/layout/reftests/svg/filters/feSpecularLighting-1.svg
+++ b/layout/reftests/svg/filters/feSpecularLighting-1.svg
@@ -1,19 +1,19 @@
 <!--
      Any copyright is dedicated to the Public Domain.
      http://creativecommons.org/publicdomain/zero/1.0/
 -->
 <svg xmlns='http://www.w3.org/2000/svg'>
   <!--
     A basic test for the <feSpecularLighting> filter primitive.
-    Setting kernelUnitLength on the <feSpecularLighting> should allow us to
-    assume pixel perfection.
+    Setting filterRes on the <filter> and kernelUnitLength on the
+    <feSpecularLighting> should allow us to assume pixel perfection.
     -->
-  <filter id='f' x='0' y='0' width='1' height='1' color-interpolation-filters='sRGB'>
+  <filter id='f' x='0' y='0' width='1' height='1' filterRes='100 100' color-interpolation-filters='sRGB'>
     <feSpecularLighting kernelUnitLength='1' result='a'>
       <feDistantLight azimuth='45'/>
     </feSpecularLighting>
     <feComposite in='a' in2='SourceAlpha' operator='in' result='b'/>
     <feComposite in='SourceGraphic' in2='b' operator='arithmetic' k1='0' k2='1' k3='1' k4='0' x='10' y='10' width='80' height='80'/>
   </filter>
   <rect width='100' height='100' fill='blue'/>
   <path d='M0,0 h100 v100 h-100 z M20,20 v60 h60 v-60 z' filter='url(#f)'/>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/filters/filter-filterRes-high-01.svg
@@ -0,0 +1,20 @@
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<svg xmlns="http://www.w3.org/2000/svg" version="1.0">
+  <desc>
+    This test checks that the implicit offscreen surface scaling implied by
+    a high 'filterRes' interacts correctly with other transforms. Specifically
+    you should see no red if the red filtered circle paints only on the pixels
+    that it should paint on.
+  </desc>
+  <filter id="filter" x="0" y="0" width="1" height="1" filterRes="1000 1000">
+    <feGaussianBlur stdDeviation="0.001"/>
+  </filter>
+  <rect width="100%" height="100%" fill="lime"/>
+  <g transform="translate(50, 0)">
+    <circle fill="red" cx="100" cy="100" r="98" transform="translate(50, 0)" filter="url(#filter)"/>
+  </g>
+  <circle fill="lime" cx="200" cy="100" r="100"/>
+</svg>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/filters/filter-filterRes-high-02.svg
@@ -0,0 +1,20 @@
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<svg xmlns="http://www.w3.org/2000/svg" version="1.0">
+  <desc>
+    This test checks that the implicit offscreen surface scaling implied by
+    a high 'filterRes' interacts correctly with other transforms. Specifically
+    you should see no red if the lime filtered circle paints on all the pixels
+    that it should paint on.
+  </desc>
+  <filter id="filter" x="0" y="0" width="1" height="1" filterRes="1000 1000">
+    <feGaussianBlur stdDeviation="0.001"/>
+  </filter>
+  <rect width="100%" height="100%" fill="lime"/>
+  <circle fill="red" cx="200" cy="100" r="98"/>
+  <g transform="translate(50, 0)">
+    <circle fill="lime" cx="100" cy="100" r="100" transform="translate(50, 0)" filter="url(#filter)"/>
+  </g>
+</svg>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/filters/filter-filterRes-low-01.svg
@@ -0,0 +1,22 @@
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<svg xmlns="http://www.w3.org/2000/svg" version="1.0">
+  <desc>
+    This test checks that the implicit offscreen surface scaling implied by
+    a high 'filterRes' interacts correctly with other transforms. Specifically
+    you should see only green if the red filtered circle paints only on
+    the pixels that it should paint on.
+  </desc>
+  <filter id="filter" x="0" y="0" width="1" height="1" filterRes="50 50">
+    <feGaussianBlur stdDeviation="0.001"/>
+  </filter>
+  <rect width="100%" height="100%" fill="lime"/>
+  <g transform="translate(50, 0)">
+    <!-- The filterRes is quartered, so we need r to be 5 pixels less, plus
+         one less for antialiasing, otherwise the circle will get fringe effects. -->
+    <circle fill="red" cx="100" cy="100" r="94" transform="translate(50, 0)" filter="url(#filter)"/>
+  </g>
+  <circle fill="lime" cx="200" cy="100" r="100"/>
+</svg>
--- a/layout/reftests/svg/filters/reftest.list
+++ b/layout/reftests/svg/filters/reftest.list
@@ -46,16 +46,19 @@ fuzzy(1,6400) == feGaussianBlur-1.svg fe
 == feOffset-2.svg feOffset-2-ref.svg
 
 == feTile-1.svg feTile-1-ref.svg
 == feTile-2.svg feTile-2-ref.svg
 
 # no tests for feTurbulence
 
 == filter-clipped-rect-01.svg pass.svg
+== filter-filterRes-high-01.svg pass.svg
+== filter-filterRes-high-02.svg pass.svg
+random-if(d2d) == filter-filterRes-low-01.svg pass.svg
 == filter-inner-svg-01.svg pass.svg
 == filter-inner-svg-02.svg pass.svg
 == filter-inner-svg-03.svg pass.svg
 fails == filter-marked-line-01.svg pass.svg # bug 477704
 == filter-kernelUnitLength-01.svg filter-kernelUnitLength-01-ref.svg
 == filter-marked-line-02.svg pass.svg
 == filter-marked-line-03.svg pass.svg
 == filter-marked-line-04.svg pass.svg
@@ -77,16 +80,18 @@ fails == filter-marked-line-01.svg pass.
 skip-if(B2G) fuzzy(1,26732) == feComposite-paint-01.svg feComposite-paint-01-ref.svg
 fuzzy(1,10000) == feConvolveMatrix-bias-01.svg feConvolveMatrix-bias-01-ref.svg
 == feConvolveMatrix-order-01.svg feConvolveMatrix-order-01-ref.svg
 
 == feDisplacementMap-alpha-01.svg pass.svg
 fuzzy(2,500) == feDisplacementMap-colour-01.svg feDisplacementMap-colour-01-ref.svg
 skip-if(B2G) == feDisplacementMap-scale-01.svg pass.svg
 
+skip-if(B2G) fuzzy-if(cocoaWidget,4,184) == feDistantLight-filterRes-01.svg feDistantLight-filterRes-01-ref.svg
+
 == feDropShadow-01.svg feDropShadow-01-ref.svg
 
 == feGaussianBlur-alpha-01.svg feGaussianBlur-alpha-01-ref.svg
 
 == feMorphology-radius-negative-01.svg pass.svg
 == feMorphology-radius-negative-02.svg pass.svg
 == feMorphology-radius-zero-01.svg pass.svg
 == feMorphology-radius-zero-02.svg pass.svg
--- a/layout/reftests/svg/smil/anim-feGaussianBlur-01.svg
+++ b/layout/reftests/svg/smil/anim-feGaussianBlur-01.svg
@@ -3,17 +3,17 @@
      http://creativecommons.org/publicdomain/zero/1.0/
 -->
 <svg xmlns="http://www.w3.org/2000/svg"
      xmlns:xlink="http://www.w3.org/1999/xlink"
      class="reftest-wait"
      onload="setTimeAndSnapshot(1.9999, true)">
   <title>Test animation of the "stdDeviation" &lt;number-optional-number&gt; attribute on "feGaussianBlur" elements</title>
   <script xlink:href="smil-util.js" type="text/javascript"/>
-  <filter id="filter" x="0" y="0" width="1" height="1">
+  <filter id="filter" x="0" y="0" width="1" height="1" filterRes="1000">
     <feGaussianBlur stdDeviation="50">
       <animate attributeName="stdDeviation"
                calcMode="linear"
                begin="0s" dur="2s"
                from="100,100" to="0"
                fill="freeze"/>
     </feGaussianBlur>
   </filter>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/smil/anim-filter-filterRes-01.svg
@@ -0,0 +1,24 @@
+<!--
+     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"
+     class="reftest-wait"
+     onload="setTimeAndSnapshot(101, true)">
+  <title>Test animation of the "filterRes" &lt;integer-optional-integer&gt; attribute on "filter" elements</title>
+  <script xlink:href="smil-util.js" type="text/javascript"/>
+  <filter id="filter" x="0" y="0" width="1" height="1" filterRes="10 10">
+    <animate attributeName="filterRes"
+             calcMode="linear"
+             begin="100s" dur="2s"
+             from="0" to="2000 2000"
+             fill="freeze"/>
+    <feGaussianBlur stdDeviation="0.001"/>
+  </filter>
+  <rect width="100%" height="100%" fill="lime"/>
+  <g transform="translate(50, 0)">
+    <circle fill="red" cx="100" cy="100" r="98" transform="translate(50, 0)" filter="url(#filter)"/>
+  </g>
+  <circle fill="lime" cx="200" cy="100" r="100"/>
+</svg>
--- a/layout/reftests/svg/smil/reftest.list
+++ b/layout/reftests/svg/smil/reftest.list
@@ -110,16 +110,19 @@ skip-if(B2G) == anim-offset-01.svg lime.
 == anim-pathLength-01.svg anim-pathLength-01-ref.svg
 
 # animate some <number-optional-number> attributes:
 == anim-feGaussianBlur-01.svg lime.svg
 
 # animate some <integer> attributes:
 skip-if(B2G) == anim-feTurbulence-numOctaves-01.svg anim-feTurbulence-numOctaves-01-ref.svg # bug 773482
 
+# animate some <integer-optional-integer> attributes:
+skip-if(B2G) random-if(/^Windows\x20NT\x205\.1/.test(http.oscpu)) == anim-filter-filterRes-01.svg lime.svg # bug 818177
+
 # animate some <angle> attributes:
 skip-if(B2G) == anim-marker-orient-01.svg lime.svg # bug 773482
 skip-if(B2G) == anim-marker-orient-02.svg lime.svg # bug 773482
 
 #animate points list:
 skip-if(B2G) == anim-polygon-points-01.svg anim-polygon-points-01-ref.svg
 == anim-polyline-points-01.svg anim-polyline-points-01-ref.svg
 
--- a/layout/svg/crashtests/453754-1.svg
+++ b/layout/svg/crashtests/453754-1.svg
@@ -1,7 +1,7 @@
 <svg xmlns="http://www.w3.org/2000/svg">
 
-  <filter id="f" height="-1"/>
+  <filter id="f" height="-1" filterRes="1"/>
 
   <rect filter="url(#f)" />
 
 </svg>
--- a/layout/svg/crashtests/474700-1.svg
+++ b/layout/svg/crashtests/474700-1.svg
@@ -1,1 +1,1 @@
-<svg xmlns="http://www.w3.org/2000/svg"><filter id="f1" height="-2"/><rect width="50" height="100" filter="url(#f1)"/></svg>
+<svg xmlns="http://www.w3.org/2000/svg"><filter id="f1" filterRes="10 20" height="-2"/><rect width="50" height="100" filter="url(#f1)"/></svg>
--- a/layout/svg/nsSVGFilterFrame.cpp
+++ b/layout/svg/nsSVGFilterFrame.cpp
@@ -62,16 +62,32 @@ nsSVGFilterFrame::GetEnumValue(uint32_t 
   AutoFilterReferencer filterRef(this);
 
   nsSVGFilterFrame *next = GetReferencedFilterIfNotInUse();
   return next ? next->GetEnumValue(aIndex, aDefault) :
     static_cast<SVGFilterElement *>(aDefault)->
       mEnumAttributes[aIndex].GetAnimValue();
 }
 
+const nsSVGIntegerPair *
+nsSVGFilterFrame::GetIntegerPairValue(uint32_t aIndex, nsIContent *aDefault)
+{
+  const nsSVGIntegerPair *thisIntegerPair =
+    &static_cast<SVGFilterElement *>(mContent)->mIntegerPairAttributes[aIndex];
+
+  if (thisIntegerPair->IsExplicitlySet())
+    return thisIntegerPair;
+
+  AutoFilterReferencer filterRef(this);
+
+  nsSVGFilterFrame *next = GetReferencedFilterIfNotInUse();
+  return next ? next->GetIntegerPairValue(aIndex, aDefault) :
+    &static_cast<SVGFilterElement *>(aDefault)->mIntegerPairAttributes[aIndex];
+}
+
 const nsSVGLength2 *
 nsSVGFilterFrame::GetLengthValue(uint32_t aIndex, nsIContent *aDefault)
 {
   const nsSVGLength2 *thisLength =
     &static_cast<SVGFilterElement *>(mContent)->mLengthAttributes[aIndex];
 
   if (thisLength->IsExplicitlySet())
     return thisLength;
@@ -166,16 +182,17 @@ nsSVGFilterFrame::AttributeChanged(int32
                                    nsIAtom* aAttribute,
                                    int32_t  aModType)
 {
   if (aNameSpaceID == kNameSpaceID_None &&
       (aAttribute == nsGkAtoms::x ||
        aAttribute == nsGkAtoms::y ||
        aAttribute == nsGkAtoms::width ||
        aAttribute == nsGkAtoms::height ||
+       aAttribute == nsGkAtoms::filterRes ||
        aAttribute == nsGkAtoms::filterUnits ||
        aAttribute == nsGkAtoms::primitiveUnits)) {
     nsSVGEffects::InvalidateDirectRenderingObservers(this);
   } else if (aNameSpaceID == kNameSpaceID_XLink &&
              aAttribute == nsGkAtoms::href) {
     // Blow away our reference, if any
     Properties().Delete(nsSVGEffects::HrefProperty());
     mNoHRefURI = false;
--- a/layout/svg/nsSVGFilterFrame.h
+++ b/layout/svg/nsSVGFilterFrame.h
@@ -80,16 +80,21 @@ private:
   nsSVGFilterFrame* GetReferencedFilterIfNotInUse();
 
   // Accessors to lookup filter attributes
   uint16_t GetEnumValue(uint32_t aIndex, nsIContent *aDefault);
   uint16_t GetEnumValue(uint32_t aIndex)
   {
     return GetEnumValue(aIndex, mContent);
   }
+  const nsSVGIntegerPair *GetIntegerPairValue(uint32_t aIndex, nsIContent *aDefault);
+  const nsSVGIntegerPair *GetIntegerPairValue(uint32_t aIndex)
+  {
+    return GetIntegerPairValue(aIndex, mContent);
+  }
   const nsSVGLength2 *GetLengthValue(uint32_t aIndex, nsIContent *aDefault);
   const nsSVGLength2 *GetLengthValue(uint32_t aIndex)
   {
     return GetLengthValue(aIndex, mContent);
   }
   const mozilla::dom::SVGFilterElement *GetFilterContent(nsIContent *aDefault);
   const mozilla::dom::SVGFilterElement *GetFilterContent()
   {
--- a/layout/svg/nsSVGFilterInstance.cpp
+++ b/layout/svg/nsSVGFilterInstance.cpp
@@ -47,19 +47,19 @@ nsSVGFilterInstance::nsSVGFilterInstance
 
   mPrimitiveUnits =
     mFilterFrame->GetEnumValue(SVGFilterElement::PRIMITIVEUNITS);
 
   // Get the filter region (in the filtered element's user space):
 
   // XXX if filterUnits is set (or has defaulted) to objectBoundingBox, we
   // should send a warning to the error console if the author has used lengths
-  // with units. This is a common mistake and can result in the filter region
-  // being *massive* below (because we ignore the units and interpret the number
-  // as a factor of the bbox width/height). We should also send a warning if the
+  // with units. This is a common mistake and can result in filterRes being
+  // *massive* below (because we ignore the units and interpret the number as
+  // a factor of the bbox width/height). We should also send a warning if the
   // user uses a number without units (a future SVG spec should really
   // deprecate that, since it's too confusing for a bare number to be sometimes
   // interpreted as a fraction of the bounding box and sometimes as user-space
   // units). So really only percentage values should be used in this case.
   
   nsSVGLength2 XYWH[4];
   NS_ABORT_IF_FALSE(sizeof(mFilterElement->mLengthAttributes) == sizeof(XYWH),
                     "XYWH size incorrect");
@@ -76,41 +76,66 @@ nsSVGFilterInstance::nsSVGFilterInstance
     XYWH, mTargetBBox, mTargetFrame);
 
   if (mFilterRegion.Width() <= 0 || mFilterRegion.Height() <= 0) {
     // 0 disables rendering, < 0 is error. dispatch error console warning
     // or error as appropriate.
     return;
   }
 
-  // Calculate the width and height of the pixel buffer of the
+  // Calculate filterRes (the width and height of the pixel buffer of the
   // temporary offscreen surface that we would/will create to paint into when
-  // painting the entire filtered element and, if necessary, adjust
+  // painting the entire filtered element) and, if necessary, adjust
   // mFilterRegion out slightly so that it aligns with pixel boundaries of this
   // buffer:
 
-  // Match filter space as closely as possible to the pixel density of the
-  // nearest outer 'svg' device space:
-  gfxMatrix canvasTM =
-    nsSVGUtils::GetCanvasTM(mTargetFrame, nsISVGChildFrame::FOR_OUTERSVG_TM);
-  if (canvasTM.IsSingular()) {
-    // nothing to draw
-    return;
+  gfxIntSize filterRes;
+  const nsSVGIntegerPair* filterResAttrs =
+    mFilterFrame->GetIntegerPairValue(SVGFilterElement::FILTERRES);
+  if (filterResAttrs->IsExplicitlySet()) {
+    int32_t filterResX = filterResAttrs->GetAnimValue(nsSVGIntegerPair::eFirst);
+    int32_t filterResY = filterResAttrs->GetAnimValue(nsSVGIntegerPair::eSecond);
+    if (filterResX <= 0 || filterResY <= 0) {
+      // 0 disables rendering, < 0 is error. dispatch error console warning?
+      return;
+    }
+
+    mFilterRegion.Scale(filterResX, filterResY);
+    mFilterRegion.RoundOut();
+    mFilterRegion.Scale(1.0 / filterResX, 1.0 / filterResY);
+    // We don't care if this overflows, because we can handle upscaling/
+    // downscaling to filterRes
+    bool overflow;
+    filterRes =
+      nsSVGUtils::ConvertToSurfaceSize(gfxSize(filterResX, filterResY),
+                                       &overflow);
+    // XXX we could send a warning to the error console if the author specified
+    // filterRes doesn't align well with our outer 'svg' device space.
+  } else {
+    // Match filterRes as closely as possible to the pixel density of the nearest
+    // outer 'svg' device space:
+    gfxMatrix canvasTM =
+      nsSVGUtils::GetCanvasTM(mTargetFrame, nsISVGChildFrame::FOR_OUTERSVG_TM);
+    if (canvasTM.IsSingular()) {
+      // nothing to draw
+      return;
+    }
+
+    gfxSize scale = canvasTM.ScaleFactors(true);
+    mFilterRegion.Scale(scale.width, scale.height);
+    mFilterRegion.RoundOut();
+    // We don't care if this overflows, because we can handle upscaling/
+    // downscaling to filterRes
+    bool overflow;
+    filterRes = nsSVGUtils::ConvertToSurfaceSize(mFilterRegion.Size(),
+                                                 &overflow);
+    mFilterRegion.Scale(1.0 / scale.width, 1.0 / scale.height);
   }
 
-  gfxSize scale = canvasTM.ScaleFactors(true);
-  mFilterRegion.Scale(scale.width, scale.height);
-  mFilterRegion.RoundOut();
-
-  // We don't care if this overflows, because we can handle upscaling/
-  // downscaling to filter space.
-  bool overflow;
-  mFilterSpaceBounds.SetRect(nsIntPoint(0, 0),
-    nsSVGUtils::ConvertToSurfaceSize(mFilterRegion.Size(), &overflow));
-  mFilterRegion.Scale(1.0 / scale.width, 1.0 / scale.height);
+  mFilterSpaceBounds.SetRect(nsIntPoint(0, 0), filterRes);
 
   mInitialized = true;
 }
 
 nsSVGFilterFrame*
 nsSVGFilterInstance::GetFilterFrame()
 {
   if (mFilter.GetType() != NS_STYLE_FILTER_URL) {
--- a/layout/svg/nsSVGFilterInstance.h
+++ b/layout/svg/nsSVGFilterInstance.h
@@ -69,16 +69,19 @@ public:
    * space, after it has been adjusted out (if necessary) so that its edges
    * coincide with pixel boundaries of the offscreen surface into which the
    * filtered output would/will be painted.
    */
   gfxRect GetFilterRegion() const { return mFilterRegion; }
 
   /**
    * Returns the size of the user specified "filter region", in filter space.
+   * The size will be {filterRes.x by filterRes.y}, whether the user specified
+   * the filter's filterRes attribute explicitly, or the implementation chose
+   * the filterRes values.
    */
   nsIntRect GetFilterSpaceBounds() const { return mFilterSpaceBounds; }
 
   float GetPrimitiveNumber(uint8_t aCtxType, const nsSVGNumber2 *aNumber) const
   {
     return GetPrimitiveNumber(aCtxType, aNumber->GetAnimValue());
   }
   float GetPrimitiveNumber(uint8_t aCtxType, const nsSVGNumberPair *aNumberPair,
--- a/parser/html/javasrc/AttributeName.java
+++ b/parser/html/javasrc/AttributeName.java
@@ -1003,16 +1003,17 @@ public final class AttributeName
     public static final AttributeName AMPLITUDE = new AttributeName(ALL_NO_NS, SAME_LOCAL("amplitude"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
     public static final AttributeName ARIA_LIVE = new AttributeName(ALL_NO_NS, SAME_LOCAL("aria-live"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
     public static final AttributeName CLIP_RULE = new AttributeName(ALL_NO_NS, SAME_LOCAL("clip-rule"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
     public static final AttributeName CLIP_PATH = new AttributeName(ALL_NO_NS, SAME_LOCAL("clip-path"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
     public static final AttributeName EQUALROWS = new AttributeName(ALL_NO_NS, SAME_LOCAL("equalrows"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
     public static final AttributeName ELEVATION = new AttributeName(ALL_NO_NS, SAME_LOCAL("elevation"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
     public static final AttributeName DIRECTION = new AttributeName(ALL_NO_NS, SAME_LOCAL("direction"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
     public static final AttributeName DRAGGABLE = new AttributeName(ALL_NO_NS, SAME_LOCAL("draggable"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+    public static final AttributeName FILTERRES = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("filterres", "filterRes"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
     public static final AttributeName FILL_RULE = new AttributeName(ALL_NO_NS, SAME_LOCAL("fill-rule"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
     public static final AttributeName FONTSTYLE = new AttributeName(ALL_NO_NS, SAME_LOCAL("fontstyle"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
     public static final AttributeName FONT_SIZE = new AttributeName(ALL_NO_NS, SAME_LOCAL("font-size"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
     public static final AttributeName KEYPOINTS = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("keypoints", "keyPoints"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
     public static final AttributeName HIDEFOCUS = new AttributeName(ALL_NO_NS, SAME_LOCAL("hidefocus"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
     public static final AttributeName ONMESSAGE = new AttributeName(ALL_NO_NS, SAME_LOCAL("onmessage"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
     public static final AttributeName INTERCEPT = new AttributeName(ALL_NO_NS, SAME_LOCAL("intercept"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
     public static final AttributeName ONDRAGEND = new AttributeName(ALL_NO_NS, SAME_LOCAL("ondragend"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
@@ -1584,16 +1585,17 @@ public final class AttributeName
     AMPLITUDE,
     ARIA_LIVE,
     CLIP_RULE,
     CLIP_PATH,
     EQUALROWS,
     ELEVATION,
     DIRECTION,
     DRAGGABLE,
+    FILTERRES,
     FILL_RULE,
     FONTSTYLE,
     FONT_SIZE,
     KEYPOINTS,
     HIDEFOCUS,
     ONMESSAGE,
     INTERCEPT,
     ONDRAGEND,
--- a/parser/html/nsHtml5AtomList.h
+++ b/parser/html/nsHtml5AtomList.h
@@ -353,16 +353,18 @@ HTML5_ATOM(aria_grab, "aria-grab")
 HTML5_ATOM(amplitude, "amplitude")
 HTML5_ATOM(aria_live, "aria-live")
 HTML5_ATOM(clip_rule, "clip-rule")
 HTML5_ATOM(clip_path, "clip-path")
 HTML5_ATOM(equalrows, "equalrows")
 HTML5_ATOM(elevation, "elevation")
 HTML5_ATOM(direction, "direction")
 HTML5_ATOM(draggable, "draggable")
+HTML5_ATOM(filterres, "filterres")
+HTML5_ATOM(filterRes, "filterRes")
 HTML5_ATOM(fill_rule, "fill-rule")
 HTML5_ATOM(fontstyle, "fontstyle")
 HTML5_ATOM(font_size, "font-size")
 HTML5_ATOM(keypoints, "keypoints")
 HTML5_ATOM(keyPoints, "keyPoints")
 HTML5_ATOM(hidefocus, "hidefocus")
 HTML5_ATOM(onmessage, "onmessage")
 HTML5_ATOM(intercept, "intercept")
--- a/parser/html/nsHtml5AttributeName.cpp
+++ b/parser/html/nsHtml5AttributeName.cpp
@@ -1099,16 +1099,17 @@ nsHtml5AttributeName::initializeStatics(
   ATTR_AMPLITUDE = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsHtml5Atoms::amplitude), ALL_NO_PREFIX);
   ATTR_ARIA_LIVE = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsHtml5Atoms::aria_live), ALL_NO_PREFIX);
   ATTR_CLIP_RULE = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsHtml5Atoms::clip_rule), ALL_NO_PREFIX);
   ATTR_CLIP_PATH = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsHtml5Atoms::clip_path), ALL_NO_PREFIX);
   ATTR_EQUALROWS = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsHtml5Atoms::equalrows), ALL_NO_PREFIX);
   ATTR_ELEVATION = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsHtml5Atoms::elevation), ALL_NO_PREFIX);
   ATTR_DIRECTION = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsHtml5Atoms::direction), ALL_NO_PREFIX);
   ATTR_DRAGGABLE = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsHtml5Atoms::draggable), ALL_NO_PREFIX);
+  ATTR_FILTERRES = new nsHtml5AttributeName(ALL_NO_NS, SVG_DIFFERENT(nsHtml5Atoms::filterres, nsHtml5Atoms::filterRes), ALL_NO_PREFIX);
   ATTR_FILL_RULE = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsHtml5Atoms::fill_rule), ALL_NO_PREFIX);
   ATTR_FONTSTYLE = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsHtml5Atoms::fontstyle), ALL_NO_PREFIX);
   ATTR_FONT_SIZE = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsHtml5Atoms::font_size), ALL_NO_PREFIX);
   ATTR_KEYPOINTS = new nsHtml5AttributeName(ALL_NO_NS, SVG_DIFFERENT(nsHtml5Atoms::keypoints, nsHtml5Atoms::keyPoints), ALL_NO_PREFIX);
   ATTR_HIDEFOCUS = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsHtml5Atoms::hidefocus), ALL_NO_PREFIX);
   ATTR_ONMESSAGE = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsHtml5Atoms::onmessage), ALL_NO_PREFIX);
   ATTR_INTERCEPT = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsHtml5Atoms::intercept), ALL_NO_PREFIX);
   ATTR_ONDRAGEND = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsHtml5Atoms::ondragend), ALL_NO_PREFIX);
--- a/parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests11.dat
+++ b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests11.dat
@@ -1,10 +1,10 @@
 #data
-<!DOCTYPE html><body><svg attributeName='' attributeType='' baseFrequency='' baseProfile='' calcMode='' clipPathUnits='' contentScriptType='' contentStyleType='' diffuseConstant='' edgeMode='' externalResourcesRequired='' filterUnits='' glyphRef='' gradientTransform='' gradientUnits='' kernelMatrix='' kernelUnitLength='' keyPoints='' keySplines='' keyTimes='' lengthAdjust='' limitingConeAngle='' markerHeight='' markerUnits='' markerWidth='' maskContentUnits='' maskUnits='' numOctaves='' pathLength='' patternContentUnits='' patternTransform='' patternUnits='' pointsAtX='' pointsAtY='' pointsAtZ='' preserveAlpha='' preserveAspectRatio='' primitiveUnits='' refX='' refY='' repeatCount='' repeatDur='' requiredExtensions='' requiredFeatures='' specularConstant='' specularExponent='' spreadMethod='' startOffset='' stdDeviation='' stitchTiles='' surfaceScale='' systemLanguage='' tableValues='' targetX='' targetY='' textLength='' viewBox='' viewTarget='' xChannelSelector='' yChannelSelector='' zoomAndPan=''></svg>
+<!DOCTYPE html><body><svg attributeName='' attributeType='' baseFrequency='' baseProfile='' calcMode='' clipPathUnits='' contentScriptType='' contentStyleType='' diffuseConstant='' edgeMode='' externalResourcesRequired='' filterRes='' filterUnits='' glyphRef='' gradientTransform='' gradientUnits='' kernelMatrix='' kernelUnitLength='' keyPoints='' keySplines='' keyTimes='' lengthAdjust='' limitingConeAngle='' markerHeight='' markerUnits='' markerWidth='' maskContentUnits='' maskUnits='' numOctaves='' pathLength='' patternContentUnits='' patternTransform='' patternUnits='' pointsAtX='' pointsAtY='' pointsAtZ='' preserveAlpha='' preserveAspectRatio='' primitiveUnits='' refX='' refY='' repeatCount='' repeatDur='' requiredExtensions='' requiredFeatures='' specularConstant='' specularExponent='' spreadMethod='' startOffset='' stdDeviation='' stitchTiles='' surfaceScale='' systemLanguage='' tableValues='' targetX='' targetY='' textLength='' viewBox='' viewTarget='' xChannelSelector='' yChannelSelector='' zoomAndPan=''></svg>
 #errors
 #document
 | <!DOCTYPE html>
 | <html>
 |   <head>
 |   <body>
 |     <svg svg>
 |       attributeName=""
@@ -13,16 +13,17 @@
 |       baseProfile=""
 |       calcMode=""
 |       clipPathUnits=""
 |       contentScriptType=""
 |       contentStyleType=""
 |       diffuseConstant=""
 |       edgeMode=""
 |       externalResourcesRequired=""
+|       filterRes=""
 |       filterUnits=""
 |       glyphRef=""
 |       gradientTransform=""
 |       gradientUnits=""
 |       kernelMatrix=""
 |       kernelUnitLength=""
 |       keyPoints=""
 |       keySplines=""
@@ -65,17 +66,17 @@
 |       textLength=""
 |       viewBox=""
 |       viewTarget=""
 |       xChannelSelector=""
 |       yChannelSelector=""
 |       zoomAndPan=""
 
 #data
-<!DOCTYPE html><BODY><SVG ATTRIBUTENAME='' ATTRIBUTETYPE='' BASEFREQUENCY='' BASEPROFILE='' CALCMODE='' CLIPPATHUNITS='' CONTENTSCRIPTTYPE='' CONTENTSTYLETYPE='' DIFFUSECONSTANT='' EDGEMODE='' EXTERNALRESOURCESREQUIRED='' FILTERUNITS='' GLYPHREF='' GRADIENTTRANSFORM='' GRADIENTUNITS='' KERNELMATRIX='' KERNELUNITLENGTH='' KEYPOINTS='' KEYSPLINES='' KEYTIMES='' LENGTHADJUST='' LIMITINGCONEANGLE='' MARKERHEIGHT='' MARKERUNITS='' MARKERWIDTH='' MASKCONTENTUNITS='' MASKUNITS='' NUMOCTAVES='' PATHLENGTH='' PATTERNCONTENTUNITS='' PATTERNTRANSFORM='' PATTERNUNITS='' POINTSATX='' POINTSATY='' POINTSATZ='' PRESERVEALPHA='' PRESERVEASPECTRATIO='' PRIMITIVEUNITS='' REFX='' REFY='' REPEATCOUNT='' REPEATDUR='' REQUIREDEXTENSIONS='' REQUIREDFEATURES='' SPECULARCONSTANT='' SPECULAREXPONENT='' SPREADMETHOD='' STARTOFFSET='' STDDEVIATION='' STITCHTILES='' SURFACESCALE='' SYSTEMLANGUAGE='' TABLEVALUES='' TARGETX='' TARGETY='' TEXTLENGTH='' VIEWBOX='' VIEWTARGET='' XCHANNELSELECTOR='' YCHANNELSELECTOR='' ZOOMANDPAN=''></SVG>
+<!DOCTYPE html><BODY><SVG ATTRIBUTENAME='' ATTRIBUTETYPE='' BASEFREQUENCY='' BASEPROFILE='' CALCMODE='' CLIPPATHUNITS='' CONTENTSCRIPTTYPE='' CONTENTSTYLETYPE='' DIFFUSECONSTANT='' EDGEMODE='' EXTERNALRESOURCESREQUIRED='' FILTERRES='' FILTERUNITS='' GLYPHREF='' GRADIENTTRANSFORM='' GRADIENTUNITS='' KERNELMATRIX='' KERNELUNITLENGTH='' KEYPOINTS='' KEYSPLINES='' KEYTIMES='' LENGTHADJUST='' LIMITINGCONEANGLE='' MARKERHEIGHT='' MARKERUNITS='' MARKERWIDTH='' MASKCONTENTUNITS='' MASKUNITS='' NUMOCTAVES='' PATHLENGTH='' PATTERNCONTENTUNITS='' PATTERNTRANSFORM='' PATTERNUNITS='' POINTSATX='' POINTSATY='' POINTSATZ='' PRESERVEALPHA='' PRESERVEASPECTRATIO='' PRIMITIVEUNITS='' REFX='' REFY='' REPEATCOUNT='' REPEATDUR='' REQUIREDEXTENSIONS='' REQUIREDFEATURES='' SPECULARCONSTANT='' SPECULAREXPONENT='' SPREADMETHOD='' STARTOFFSET='' STDDEVIATION='' STITCHTILES='' SURFACESCALE='' SYSTEMLANGUAGE='' TABLEVALUES='' TARGETX='' TARGETY='' TEXTLENGTH='' VIEWBOX='' VIEWTARGET='' XCHANNELSELECTOR='' YCHANNELSELECTOR='' ZOOMANDPAN=''></SVG>
 #errors
 #document
 | <!DOCTYPE html>
 | <html>
 |   <head>
 |   <body>
 |     <svg svg>
 |       attributeName=""
@@ -84,16 +85,17 @@
 |       baseProfile=""
 |       calcMode=""
 |       clipPathUnits=""
 |       contentScriptType=""
 |       contentStyleType=""
 |       diffuseConstant=""
 |       edgeMode=""
 |       externalResourcesRequired=""
+|       filterRes=""
 |       filterUnits=""
 |       glyphRef=""
 |       gradientTransform=""
 |       gradientUnits=""
 |       kernelMatrix=""
 |       kernelUnitLength=""
 |       keyPoints=""
 |       keySplines=""
@@ -136,17 +138,17 @@
 |       textLength=""
 |       viewBox=""
 |       viewTarget=""
 |       xChannelSelector=""
 |       yChannelSelector=""
 |       zoomAndPan=""
 
 #data
-<!DOCTYPE html><body><svg attributename='' attributetype='' basefrequency='' baseprofile='' calcmode='' clippathunits='' contentscripttype='' contentstyletype='' diffuseconstant='' edgemode='' externalresourcesrequired='' filterunits='' glyphref='' gradienttransform='' gradientunits='' kernelmatrix='' kernelunitlength='' keypoints='' keysplines='' keytimes='' lengthadjust='' limitingconeangle='' markerheight='' markerunits='' markerwidth='' maskcontentunits='' maskunits='' numoctaves='' pathlength='' patterncontentunits='' patterntransform='' patternunits='' pointsatx='' pointsaty='' pointsatz='' preservealpha='' preserveaspectratio='' primitiveunits='' refx='' refy='' repeatcount='' repeatdur='' requiredextensions='' requiredfeatures='' specularconstant='' specularexponent='' spreadmethod='' startoffset='' stddeviation='' stitchtiles='' surfacescale='' systemlanguage='' tablevalues='' targetx='' targety='' textlength='' viewbox='' viewtarget='' xchannelselector='' ychannelselector='' zoomandpan=''></svg>
+<!DOCTYPE html><body><svg attributename='' attributetype='' basefrequency='' baseprofile='' calcmode='' clippathunits='' contentscripttype='' contentstyletype='' diffuseconstant='' edgemode='' externalresourcesrequired='' filterres='' filterunits='' glyphref='' gradienttransform='' gradientunits='' kernelmatrix='' kernelunitlength='' keypoints='' keysplines='' keytimes='' lengthadjust='' limitingconeangle='' markerheight='' markerunits='' markerwidth='' maskcontentunits='' maskunits='' numoctaves='' pathlength='' patterncontentunits='' patterntransform='' patternunits='' pointsatx='' pointsaty='' pointsatz='' preservealpha='' preserveaspectratio='' primitiveunits='' refx='' refy='' repeatcount='' repeatdur='' requiredextensions='' requiredfeatures='' specularconstant='' specularexponent='' spreadmethod='' startoffset='' stddeviation='' stitchtiles='' surfacescale='' systemlanguage='' tablevalues='' targetx='' targety='' textlength='' viewbox='' viewtarget='' xchannelselector='' ychannelselector='' zoomandpan=''></svg>
 #errors
 #document
 | <!DOCTYPE html>
 | <html>
 |   <head>
 |   <body>
 |     <svg svg>
 |       attributeName=""
@@ -155,16 +157,17 @@
 |       baseProfile=""
 |       calcMode=""
 |       clipPathUnits=""
 |       contentScriptType=""
 |       contentStyleType=""
 |       diffuseConstant=""
 |       edgeMode=""
 |       externalResourcesRequired=""
+|       filterRes=""
 |       filterUnits=""
 |       glyphRef=""
 |       gradientTransform=""
 |       gradientUnits=""
 |       kernelMatrix=""
 |       kernelUnitLength=""
 |       keyPoints=""
 |       keySplines=""
@@ -207,17 +210,17 @@
 |       textLength=""
 |       viewBox=""
 |       viewTarget=""
 |       xChannelSelector=""
 |       yChannelSelector=""
 |       zoomAndPan=""
 
 #data
-<!DOCTYPE html><body><math attributeName='' attributeType='' baseFrequency='' baseProfile='' calcMode='' clipPathUnits='' contentScriptType='' contentStyleType='' diffuseConstant='' edgeMode='' externalResourcesRequired='' filterUnits='' glyphRef='' gradientTransform='' gradientUnits='' kernelMatrix='' kernelUnitLength='' keyPoints='' keySplines='' keyTimes='' lengthAdjust='' limitingConeAngle='' markerHeight='' markerUnits='' markerWidth='' maskContentUnits='' maskUnits='' numOctaves='' pathLength='' patternContentUnits='' patternTransform='' patternUnits='' pointsAtX='' pointsAtY='' pointsAtZ='' preserveAlpha='' preserveAspectRatio='' primitiveUnits='' refX='' refY='' repeatCount='' repeatDur='' requiredExtensions='' requiredFeatures='' specularConstant='' specularExponent='' spreadMethod='' startOffset='' stdDeviation='' stitchTiles='' surfaceScale='' systemLanguage='' tableValues='' targetX='' targetY='' textLength='' viewBox='' viewTarget='' xChannelSelector='' yChannelSelector='' zoomAndPan=''></math>
+<!DOCTYPE html><body><math attributeName='' attributeType='' baseFrequency='' baseProfile='' calcMode='' clipPathUnits='' contentScriptType='' contentStyleType='' diffuseConstant='' edgeMode='' externalResourcesRequired='' filterRes='' filterUnits='' glyphRef='' gradientTransform='' gradientUnits='' kernelMatrix='' kernelUnitLength='' keyPoints='' keySplines='' keyTimes='' lengthAdjust='' limitingConeAngle='' markerHeight='' markerUnits='' markerWidth='' maskContentUnits='' maskUnits='' numOctaves='' pathLength='' patternContentUnits='' patternTransform='' patternUnits='' pointsAtX='' pointsAtY='' pointsAtZ='' preserveAlpha='' preserveAspectRatio='' primitiveUnits='' refX='' refY='' repeatCount='' repeatDur='' requiredExtensions='' requiredFeatures='' specularConstant='' specularExponent='' spreadMethod='' startOffset='' stdDeviation='' stitchTiles='' surfaceScale='' systemLanguage='' tableValues='' targetX='' targetY='' textLength='' viewBox='' viewTarget='' xChannelSelector='' yChannelSelector='' zoomAndPan=''></math>
 #errors
 #document
 | <!DOCTYPE html>
 | <html>
 |   <head>
 |   <body>
 |     <math math>
 |       attributename=""
@@ -226,16 +229,17 @@
 |       baseprofile=""
 |       calcmode=""
 |       clippathunits=""
 |       contentscripttype=""
 |       contentstyletype=""
 |       diffuseconstant=""
 |       edgemode=""
 |       externalresourcesrequired=""
+|       filterres=""
 |       filterunits=""
 |       glyphref=""
 |       gradienttransform=""
 |       gradientunits=""
 |       kernelmatrix=""
 |       kernelunitlength=""
 |       keypoints=""
 |       keysplines=""