Bug 687340 - Make dynamic changes to mask, clipPath and marker attributes work. r=roc
authorRobert Longson <longsonr@gmail.com>
Mon, 19 Sep 2011 13:59:52 +0100
changeset 77562 c6d4e5bce80b58d9544405f88b2d9292a75c1ec1
parent 77561 75086668aebb002726a7e9dd27739bf5cd8b1177
child 77563 19518187d2e8051bddb81c2fc7a5f99ae4053e16
push idunknown
push userunknown
push dateunknown
reviewersroc
bugs687340
milestone9.0a1
Bug 687340 - Make dynamic changes to mask, clipPath and marker attributes work. r=roc
content/svg/content/src/SVGAnimatedPreserveAspectRatio.cpp
content/svg/content/src/nsSVGSVGElement.cpp
content/svg/content/src/nsSVGSVGElement.h
layout/reftests/svg/dynamic-clipPath-02.svg
layout/reftests/svg/dynamic-marker-01.svg
layout/reftests/svg/dynamic-marker-03.svg
layout/reftests/svg/dynamic-mask-01.svg
layout/reftests/svg/reftest.list
layout/svg/base/src/nsSVGClipPathFrame.cpp
layout/svg/base/src/nsSVGMaskFrame.cpp
layout/svg/base/src/nsSVGMaskFrame.h
--- a/content/svg/content/src/SVGAnimatedPreserveAspectRatio.cpp
+++ b/content/svg/content/src/SVGAnimatedPreserveAspectRatio.cpp
@@ -242,19 +242,17 @@ SVGAnimatedPreserveAspectRatio::SetBaseV
     mAnimVal = mBaseVal;
   }
 #ifdef MOZ_SMIL
   else {
     aSVGElement->AnimationNeedsResample();
   }
 #endif
 
-  // We don't need to call DidChange* here - we're only called by
-  // nsSVGElement::ParseAttribute under nsGenericElement::SetAttr,
-  // which takes care of notifying.
+  aSVGElement->DidChangePreserveAspectRatio(aDoSetAttr);
   return NS_OK;
 }
 
 void
 SVGAnimatedPreserveAspectRatio::GetBaseValueString(nsAString & aValueAsString)
 {
   nsAutoString tmpString;
 
--- a/content/svg/content/src/nsSVGSVGElement.cpp
+++ b/content/svg/content/src/nsSVGSVGElement.cpp
@@ -1208,24 +1208,16 @@ nsSVGSVGElement::DidChangeLength(PRUint8
 
 nsSVGElement::LengthAttributesInfo
 nsSVGSVGElement::GetLengthInfo()
 {
   return LengthAttributesInfo(mLengthAttributes, sLengthInfo,
                               NS_ARRAY_LENGTH(sLengthInfo));
 }
 
-void
-nsSVGSVGElement::DidChangeEnum(PRUint8 aAttrEnum, PRBool aDoSetAttr)
-{
-  nsSVGSVGElementBase::DidChangeEnum(aAttrEnum, aDoSetAttr);
-
-  InvalidateTransformNotifyFrame();
-}
-
 nsSVGElement::EnumAttributesInfo
 nsSVGSVGElement::GetEnumInfo()
 {
   return EnumAttributesInfo(mEnumAttributes, sEnumInfo,
                             NS_ARRAY_LENGTH(sEnumInfo));
 }
 
 void
--- a/content/svg/content/src/nsSVGSVGElement.h
+++ b/content/svg/content/src/nsSVGSVGElement.h
@@ -189,17 +189,16 @@ public:
   NS_IMETHOD_(PRBool) IsAttributeMapped(const nsIAtom* aAttribute) const;
 #ifdef MOZ_SMIL
   virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor);
 #endif // MOZ_SMIL
 
   // nsSVGElement specializations:
   virtual gfxMatrix PrependLocalTransformTo(const gfxMatrix &aMatrix) const;
   virtual void DidChangeLength(PRUint8 aAttrEnum, PRBool aDoSetAttr);
-  virtual void DidChangeEnum(PRUint8 aAttrEnum, PRBool aDoSetAttr);
   virtual void DidChangeViewBox(PRBool aDoSetAttr);
   virtual void DidChangePreserveAspectRatio(PRBool aDoSetAttr);
 
   virtual void DidAnimateViewBox();
   virtual void DidAnimatePreserveAspectRatio();
   
   // nsSVGSVGElement methods:
   float GetLength(PRUint8 mCtxType);
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/dynamic-clipPath-02.svg
@@ -0,0 +1,37 @@
+<!--
+     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.1"
+     class="reftest-wait"
+     onload="startTest()"
+     xmlns:xlink="http://www.w3.org/1999/xlink">
+  <title>Testing that dynamic changes to the clipPathUnits are reflected in the clipPath</title>
+
+  <defs>
+    <clipPath id="clip1" clipPathUnits="objectBoundingBox">
+      <rect width=".1" height=".1"/>
+    </clipPath>
+  </defs>
+
+  <rect width="100%" height="100%" fill="lime"/>
+
+  <g transform="scale(1000)">
+    <rect x=".2" y=".2" width=".6" height=".6" fill="red" clip-path="url(#clip1)"/>
+  </g>
+
+  <script>
+    function startTest() {
+      document.addEventListener("MozReftestInvalidate", doTest, false);
+      // in case we're not gecko
+      setTimeout(doTest, 5000);
+    }
+
+    function doTest() {
+      var clip1 = document.getElementById("clip1");
+      clip1.setAttribute("clipPathUnits", "userSpaceOnUse");
+
+      document.documentElement.removeAttribute("class");
+    }
+  </script>
+</svg>
--- a/layout/reftests/svg/dynamic-marker-01.svg
+++ b/layout/reftests/svg/dynamic-marker-01.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" version="1.1" class="reftest-wait" onload="startTest()" xmlns:xlink="http://www.w3.org/1999/xlink">
   <title>Testing that dynamic changes to the element for a given ID are reflected in marker</title>
   <!-- From https://bugzilla.mozilla.org/show_bug.cgi?id=309220 -->
   <defs>
-	  <marker id="x" style="overflow: visible;" orient="auto" markerUnits="strokeWidth">
-		  <rect width="100%" height="100%" fill="lime"/>
-	  </marker>
+    <marker id="x" style="overflow: visible;" orient="auto" markerUnits="strokeWidth">
+      <rect width="100%" height="100%" fill="lime"/>
+    </marker>
   </defs>
 	
   <rect width="100%" height="100%" fill="red"/>
 	
   <line id="l1" x1="0" x2="0" y1="0" y2="0" fill="none" stroke="black" stroke-width="1" marker-end="url(#m1)"/>
 
   <script>
   function startTest() {
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/dynamic-marker-03.svg
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<svg xmlns="http://www.w3.org/2000/svg" class="reftest-wait"
+  onload="startTest()">
+
+  <title>Testing that dynamic changes to preserveAspectRatio are reflected in the marker</title>
+  <script>
+<![CDATA[
+
+function startTest() {
+  document.addEventListener("MozReftestInvalidate", doTest, false);
+  // in case we're not gecko
+  setTimeout(doTest, 5000);
+}
+
+function doTest() {
+  m = document.getElementById("m1");
+  m.preserveAspectRatio.baseVal.align =
+    SVGPreserveAspectRatio.SVG_PRESERVEASPECTRATIO_NONE;
+  document.documentElement.removeAttribute("class");
+}
+
+]]>
+  </script>
+
+  <defs>
+    <marker id="m1" orient="auto" markerUnits="userSpaceOnUse"
+      preserveAspectRatio="xMidYMid slice" viewBox="0 0 30 40" markerWidth="60" markerHeight="30">
+      <rect width="30" height="40" fill="red"/>
+    </marker>
+  </defs>
+	
+  <rect width="100%" height="100%" fill="lime"/>
+	
+  <line x1="30" x2="30" y1="10" y2="10" stroke="red" stroke-width="3" marker-end="url(#m1)"/>
+
+  <rect x="30" y="10" width="60" height="30" fill="lime"/>
+</svg>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/dynamic-mask-01.svg
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<!--
+     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.1"
+     class="reftest-wait"
+     onload="startTest()"
+     xmlns:xlink="http://www.w3.org/1999/xlink">
+  <title>Testing that dynamic changes to mask attributes are reflected in the mask</title>
+
+  <defs>
+    <mask id="mask1" width="1" height="1">
+      <rect width="1" height="1" fill="white"/>
+    </mask>
+  </defs>
+
+  <rect width="100%" height="100%" fill="lime"/>
+
+  <g transform="scale(500)">
+    <rect x=".2" y=".2" width=".2" height=".2" fill="red" mask="url(#mask1)"/>
+  </g>
+
+  <script>
+    function startTest() {
+      document.addEventListener("MozReftestInvalidate", doTest, false);
+      // in case we're not gecko
+      setTimeout(doTest, 5000);
+    }
+
+    function doTest() {
+      var mask1 = document.getElementById("mask1");
+      mask1.maskUnits.baseVal = SVGUnitTypes.SVG_UNIT_TYPE_USERSPACEONUSE;
+
+      document.documentElement.removeAttribute("class");
+    }
+  </script>
+</svg>
--- a/layout/reftests/svg/reftest.list
+++ b/layout/reftests/svg/reftest.list
@@ -57,26 +57,29 @@ fails-if(Android) == dynamic-conditions-
 == dynamic-conditions-07.svg pass.svg
 == dynamic-conditions-08.svg pass.svg
 == dynamic-conditions-09.svg about:blank
 == dynamic-conditions-10.svg about:blank
 == dynamic-conditions-11.svg pass.svg
 == dynamic-conditions-12.svg pass.svg
 == dynamic-conditions-13.svg about:blank
 == dynamic-clipPath-01.svg pass.svg
+== dynamic-clipPath-02.svg pass.svg
 == dynamic-feFlood-01.svg pass.svg
 == dynamic-feImage-01.svg pass.svg
 == dynamic-filter-contents-01a.svg dynamic-filter-contents-01-ref.svg
 == dynamic-filter-contents-01b.svg dynamic-filter-contents-01-ref.svg
 == dynamic-gradient-contents-01.svg pass.svg
 == dynamic-gradient-contents-02.svg pass.svg
 == dynamic-inner-svg-01.svg pass.svg
 == dynamic-link-style-01.svg pass.svg
 == dynamic-marker-01.svg pass.svg
 == dynamic-marker-02.svg dynamic-marker-02-ref.svg
+== dynamic-marker-03.svg pass.svg
+== dynamic-mask-01.svg pass.svg
 == dynamic-mask-contents-01.svg pass.svg
 == dynamic-pattern-01.svg pass.svg
 == dynamic-pattern-02.svg pass.svg
 == dynamic-pattern-contents-01.svg pass.svg
 == dynamic-pattern-contents-02.svg pass.svg
 == dynamic-rect-01.svg dynamic-rect-01-ref.svg
 == dynamic-rect-02.svg dynamic-rect-02-ref.svg
 == dynamic-rect-03.svg dynamic-rect-03-ref.svg
--- a/layout/svg/base/src/nsSVGClipPathFrame.cpp
+++ b/layout/svg/base/src/nsSVGClipPathFrame.cpp
@@ -275,20 +275,24 @@ nsSVGClipPathFrame::IsValid()
   return PR_TRUE;
 }
 
 NS_IMETHODIMP
 nsSVGClipPathFrame::AttributeChanged(PRInt32         aNameSpaceID,
                                      nsIAtom*        aAttribute,
                                      PRInt32         aModType)
 {
-  if (aNameSpaceID == kNameSpaceID_None &&
-      aAttribute == nsGkAtoms::transform) {
-    nsSVGUtils::NotifyChildrenOfSVGChange(this,
-                                          nsISVGChildFrame::TRANSFORM_CHANGED);
+  if (aNameSpaceID == kNameSpaceID_None) {
+    if (aAttribute == nsGkAtoms::transform) {
+      nsSVGUtils::NotifyChildrenOfSVGChange(this,
+                                            nsISVGChildFrame::TRANSFORM_CHANGED);
+    }
+    if (aAttribute == nsGkAtoms::clipPathUnits) {
+      nsSVGEffects::InvalidateRenderingObservers(this);
+    }
   }
 
   return nsSVGClipPathFrameBase::AttributeChanged(aNameSpaceID,
                                                   aAttribute, aModType);
 }
 
 NS_IMETHODIMP
 nsSVGClipPathFrame::Init(nsIContent* aContent,
--- a/layout/svg/base/src/nsSVGMaskFrame.cpp
+++ b/layout/svg/base/src/nsSVGMaskFrame.cpp
@@ -33,16 +33,17 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsIDocument.h"
 #include "nsSVGMaskFrame.h"
 #include "nsSVGContainerFrame.h"
 #include "nsSVGMaskElement.h"
+#include "nsSVGEffects.h"
 #include "nsIDOMSVGMatrix.h"
 #include "gfxContext.h"
 #include "gfxImageSurface.h"
 #include "nsSVGMatrix.h"
 
 //----------------------------------------------------------------------
 // Implementation
 
@@ -152,16 +153,35 @@ nsSVGMaskFrame::ComputeMaskAlpha(nsSVGRe
       memset(pixel, alpha, 4);
     }
 
   gfxPattern *retval = new gfxPattern(image);
   NS_IF_ADDREF(retval);
   return retval;
 }
 
+NS_IMETHODIMP
+nsSVGMaskFrame::AttributeChanged(PRInt32  aNameSpaceID,
+                                 nsIAtom* aAttribute,
+                                 PRInt32  aModType)
+{
+  if (aNameSpaceID == kNameSpaceID_None &&
+      (aAttribute == nsGkAtoms::x ||
+       aAttribute == nsGkAtoms::y ||
+       aAttribute == nsGkAtoms::width ||
+       aAttribute == nsGkAtoms::height||
+       aAttribute == nsGkAtoms::maskUnits ||
+       aAttribute == nsGkAtoms::maskContentUnits)) {
+    nsSVGEffects::InvalidateRenderingObservers(this);
+  }
+
+  return nsSVGMaskFrameBase::AttributeChanged(aNameSpaceID,
+                                              aAttribute, aModType);
+}
+
 #ifdef DEBUG
 NS_IMETHODIMP
 nsSVGMaskFrame::Init(nsIContent* aContent,
                      nsIFrame* aParent,
                      nsIFrame* aPrevInFlow)
 {
   nsCOMPtr<nsIDOMSVGMaskElement> mask = do_QueryInterface(aContent);
   NS_ASSERTION(mask, "Content is not an SVG mask");
--- a/layout/svg/base/src/nsSVGMaskFrame.h
+++ b/layout/svg/base/src/nsSVGMaskFrame.h
@@ -59,16 +59,20 @@ public:
   NS_DECL_FRAMEARENA_HELPERS
 
   // nsSVGMaskFrame method:
   already_AddRefed<gfxPattern> ComputeMaskAlpha(nsSVGRenderState *aContext,
                                                 nsIFrame* aParent,
                                                 const gfxMatrix &aMatrix,
                                                 float aOpacity = 1.0f);
 
+  NS_IMETHOD AttributeChanged(PRInt32         aNameSpaceID,
+                              nsIAtom*        aAttribute,
+                              PRInt32         aModType);
+
 #ifdef DEBUG
   NS_IMETHOD Init(nsIContent*      aContent,
                   nsIFrame*        aParent,
                   nsIFrame*        aPrevInFlow);
 #endif
 
   /**
    * Get the "type" of the frame