Bug 652991 - Part 4. using FragmentURL in SVG clippath and filter. draft
authorcku <cku@mozilla.com>
Fri, 17 Jun 2016 17:07:59 +0100
changeset 379829 04ba076d549b3eca1efe03f5901aee37209d68f5
parent 379828 2cedbd4da78d2f9388363ce5e98839795777e072
child 379830 9748d6e912a179b841d5355ef18df1047b225197
push id21069
push usercku@mozilla.com
push dateSat, 18 Jun 2016 00:34:28 +0000
bugs652991
milestone50.0a1
Bug 652991 - Part 4. using FragmentURL in SVG clippath and filter. MozReview-Commit-ID: JJMNAwyYgBN
layout/style/StyleAnimationValue.cpp
layout/style/nsComputedDOMStyle.cpp
layout/style/nsRuleNode.cpp
layout/style/nsStyleStruct.cpp
layout/style/nsStyleStruct.h
layout/svg/nsSVGEffects.cpp
layout/svg/nsSVGFilterInstance.cpp
--- a/layout/style/StyleAnimationValue.cpp
+++ b/layout/style/StyleAnimationValue.cpp
@@ -3951,20 +3951,21 @@ StyleAnimationValue::ExtractComputedValu
         case eCSSProperty_clip_path: {
           const nsStyleSVGReset* svgReset =
             static_cast<const nsStyleSVGReset*>(styleStruct);
           const nsStyleClipPath& clipPath = svgReset->mClipPath;
           const int32_t type = clipPath.GetType();
 
           if (type == NS_STYLE_CLIP_PATH_URL) {
             nsIDocument* doc = aStyleContext->PresContext()->Document();
+            nsCOMPtr<nsIURI> pathURI = clipPath.GetURL(doc);
             RefPtr<nsStringBuffer> uriAsStringBuffer =
-              GetURIAsUtf16StringBuffer(clipPath.GetURL());
+              GetURIAsUtf16StringBuffer(pathURI);
             RefPtr<mozilla::css::URLValue> url =
-              new mozilla::css::URLValue(clipPath.GetURL(),
+              new mozilla::css::URLValue(pathURI,
                                          uriAsStringBuffer,
                                          doc->GetDocumentURI(),
                                          doc->NodePrincipal());
             auto result = MakeUnique<nsCSSValue>();
             result->SetURLValue(url);
             aComputedValue.SetAndAdoptCSSValueValue(result.release(), eUnit_URL);
           } else if (type == NS_STYLE_CLIP_PATH_BOX) {
             aComputedValue.SetIntValue(clipPath.GetSizingBox(), eUnit_Enumerated);
@@ -3991,20 +3992,21 @@ StyleAnimationValue::ExtractComputedValu
           for (uint32_t i = 0; i < filters.Length(); ++i) {
             nsCSSValueList *item = new nsCSSValueList;
             *resultTail = item;
             resultTail = &item->mNext;
             const nsStyleFilter& filter = filters[i];
             int32_t type = filter.GetType();
             if (type == NS_STYLE_FILTER_URL) {
               nsIDocument* doc = aStyleContext->PresContext()->Document();
+              nsCOMPtr<nsIURI> filterURI = filter.GetURL(doc);
               RefPtr<nsStringBuffer> uriAsStringBuffer =
-                GetURIAsUtf16StringBuffer(filter.GetURL());
+                GetURIAsUtf16StringBuffer(filterURI);
               RefPtr<mozilla::css::URLValue> url =
-                new mozilla::css::URLValue(filter.GetURL(),
+                new mozilla::css::URLValue(filterURI,
                                            uriAsStringBuffer,
                                            doc->GetDocumentURI(),
                                            doc->NodePrincipal());
               item->mValue.SetURLValue(url);
             } else {
               nsCSSKeyword functionName =
                 nsCSSProps::ValueToKeywordEnum(type,
                   nsCSSProps::kFilterFunctionKTable);
--- a/layout/style/nsComputedDOMStyle.cpp
+++ b/layout/style/nsComputedDOMStyle.cpp
@@ -6002,18 +6002,21 @@ nsComputedDOMStyle::DoGetClipPath()
   switch (svg->mClipPath.GetType()) {
     case NS_STYLE_CLIP_PATH_SHAPE:
       return CreatePrimitiveValueForClipPath(svg->mClipPath.GetBasicShape(),
                                              svg->mClipPath.GetSizingBox());
     case NS_STYLE_CLIP_PATH_BOX:
       return CreatePrimitiveValueForClipPath(nullptr,
                                              svg->mClipPath.GetSizingBox());
     case NS_STYLE_CLIP_PATH_URL: {
+      nsIDocument* doc = mStyleContext->PresContext()->Document();
+      nsCOMPtr<nsIURI> pathURI = svg->mClipPath.GetURL(doc);
+
       RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
-      val->SetURI(svg->mClipPath.GetURL());
+      val->SetURI(pathURI);
       return val.forget();
     }
     case NS_STYLE_CLIP_PATH_NONE: {
       RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
       val->SetIdent(eCSSKeyword_none);
       return val.forget();
     }
     default:
@@ -6034,17 +6037,19 @@ nsComputedDOMStyle::SetCssTextToCoord(ns
 
 already_AddRefed<CSSValue>
 nsComputedDOMStyle::CreatePrimitiveValueForStyleFilter(
   const nsStyleFilter& aStyleFilter)
 {
   RefPtr<nsROCSSPrimitiveValue> value = new nsROCSSPrimitiveValue;
   // Handle url().
   if (aStyleFilter.GetType() == NS_STYLE_FILTER_URL) {
-    value->SetURI(aStyleFilter.GetURL());
+    nsIDocument* doc = mStyleContext->PresContext()->Document();
+    nsCOMPtr<nsIURI> filterURI = aStyleFilter.GetURL(doc);
+    value->SetURI(filterURI);
     return value.forget();
   }
 
   // Filter function name and opening parenthesis.
   nsAutoString filterFunctionString;
   AppendASCIItoUTF16(
     nsCSSProps::ValueToKeyword(aStyleFilter.GetType(),
                                nsCSSProps::kFilterFunctionKTable),
--- a/layout/style/nsRuleNode.cpp
+++ b/layout/style/nsRuleNode.cpp
@@ -9733,21 +9733,17 @@ bool
 nsRuleNode::SetStyleFilterToCSSValue(nsStyleFilter* aStyleFilter,
                                      const nsCSSValue& aValue,
                                      nsStyleContext* aStyleContext,
                                      nsPresContext* aPresContext,
                                      RuleNodeCacheConditions& aConditions)
 {
   nsCSSUnit unit = aValue.GetUnit();
   if (unit == eCSSUnit_URL) {
-    nsIURI* url = aValue.GetURLValue();
-    if (!url)
-      return false;
-    aStyleFilter->SetURL(url);
-    return true;
+    return aStyleFilter->SetURL(&aValue);
   }
 
   MOZ_ASSERT(unit == eCSSUnit_Function, "expected a filter function");
 
   nsCSSValue::Array* filterFunction = aValue.GetArrayValue();
   nsCSSKeyword functionName =
     (nsCSSKeyword)filterFunction->Item(0).GetIntValue();
 
@@ -9842,20 +9838,17 @@ nsRuleNode::ComputeSVGResetData(void* aS
       svgReset->mClipPath = nsStyleClipPath();
       break;
     case eCSSUnit_Inherit:
       conditions.SetUncacheable();
       svgReset->mClipPath = parentSVGReset->mClipPath;
       break;
     case eCSSUnit_URL: {
       svgReset->mClipPath = nsStyleClipPath();
-      nsIURI* url = clipPathValue->GetURLValue();
-      if (url) {
-        svgReset->mClipPath.SetURL(url);
-      }
+      svgReset->mClipPath.SetURL(clipPathValue);
       break;
     }
     case eCSSUnit_Array: {
       svgReset->mClipPath = nsStyleClipPath();
       SetStyleClipPathToCSSValue(&svgReset->mClipPath, clipPathValue, aContext,
                                  mPresContext, conditions);
       break;
     }
--- a/layout/style/nsStyleStruct.cpp
+++ b/layout/style/nsStyleStruct.cpp
@@ -1086,28 +1086,27 @@ FragmentURL::ReleaseRef()
   }
 }
 
 // --------------------
 // nsStyleClipPath
 //
 nsStyleClipPath::nsStyleClipPath()
   : mType(NS_STYLE_CLIP_PATH_NONE)
-  , mURL(nullptr)
   , mSizingBox(NS_STYLE_CLIP_SHAPE_SIZING_NOBOX)
 {
 }
 
 nsStyleClipPath::nsStyleClipPath(const nsStyleClipPath& aSource)
   : mType(NS_STYLE_CLIP_PATH_NONE)
-  , mURL(nullptr)
   , mSizingBox(NS_STYLE_CLIP_SHAPE_SIZING_NOBOX)
 {
   if (aSource.mType == NS_STYLE_CLIP_PATH_URL) {
-    SetURL(aSource.mURL);
+    mURL = aSource.mURL;
+    mType = NS_STYLE_CLIP_PATH_URL;
   } else if (aSource.mType == NS_STYLE_CLIP_PATH_SHAPE) {
     SetBasicShape(aSource.mBasicShape, aSource.mSizingBox);
   } else if (aSource.mType == NS_STYLE_CLIP_PATH_BOX) {
     SetSizingBox(aSource.mSizingBox);
   }
 }
 
 nsStyleClipPath::~nsStyleClipPath()
@@ -1118,17 +1117,18 @@ nsStyleClipPath::~nsStyleClipPath()
 nsStyleClipPath&
 nsStyleClipPath::operator=(const nsStyleClipPath& aOther)
 {
   if (this == &aOther) {
     return *this;
   }
 
   if (aOther.mType == NS_STYLE_CLIP_PATH_URL) {
-    SetURL(aOther.mURL);
+    mURL = aOther.mURL;
+    mType = NS_STYLE_CLIP_PATH_URL;
   } else if (aOther.mType == NS_STYLE_CLIP_PATH_SHAPE) {
     SetBasicShape(aOther.mBasicShape, aOther.mSizingBox);
   } else if (aOther.mType == NS_STYLE_CLIP_PATH_BOX) {
     SetSizingBox(aOther.mSizingBox);
   } else {
     ReleaseRef();
     mSizingBox = NS_STYLE_CLIP_SHAPE_SIZING_NOBOX;
     mType = NS_STYLE_CLIP_PATH_NONE;
@@ -1139,50 +1139,51 @@ nsStyleClipPath::operator=(const nsStyle
 bool
 nsStyleClipPath::operator==(const nsStyleClipPath& aOther) const
 {
   if (mType != aOther.mType) {
     return false;
   }
 
   if (mType == NS_STYLE_CLIP_PATH_URL) {
-    return EqualURIs(mURL, aOther.mURL);
+    return aOther.mURL == mURL;
   } else if (mType == NS_STYLE_CLIP_PATH_SHAPE) {
     return *mBasicShape == *aOther.mBasicShape &&
            mSizingBox == aOther.mSizingBox;
   } else if (mType == NS_STYLE_CLIP_PATH_BOX) {
     return mSizingBox == aOther.mSizingBox;
   }
 
   return true;
 }
 
 void
 nsStyleClipPath::ReleaseRef()
 {
   if (mType == NS_STYLE_CLIP_PATH_SHAPE) {
     NS_ASSERTION(mBasicShape, "expected pointer");
     mBasicShape->Release();
+    mBasicShape = nullptr;
   } else if (mType == NS_STYLE_CLIP_PATH_URL) {
-    NS_ASSERTION(mURL, "expected pointer");
-    mURL->Release();
+    mURL.ReleaseRef();
   }
-  // mBasicShap, mURL, etc. are all pointers in a union of pointers. Nulling
-  // one of them nulls all of them:
-  mURL = nullptr;
 }
 
-void
-nsStyleClipPath::SetURL(nsIURI* aURL)
+bool
+nsStyleClipPath::SetURL(const nsCSSValue* aValue)
 {
-  NS_ASSERTION(aURL, "expected pointer");
+  if (!aValue->GetURLValue()) {
+    return false;
+  }
+
   ReleaseRef();
-  mURL = aURL;
-  mURL->AddRef();
+
+  mURL.SetURL(aValue);
   mType = NS_STYLE_CLIP_PATH_URL;
+  return true;
 }
 
 void
 nsStyleClipPath::SetBasicShape(nsStyleBasicShape* aBasicShape, uint8_t aSizingBox)
 {
   NS_ASSERTION(aBasicShape, "expected pointer");
   ReleaseRef();
   mBasicShape = aBasicShape;
@@ -1210,17 +1211,17 @@ nsStyleFilter::nsStyleFilter()
 }
 
 nsStyleFilter::nsStyleFilter(const nsStyleFilter& aSource)
   : mType(NS_STYLE_FILTER_NONE)
   , mDropShadow(nullptr)
 {
   MOZ_COUNT_CTOR(nsStyleFilter);
   if (aSource.mType == NS_STYLE_FILTER_URL) {
-    SetURL(aSource.mURL);
+    mURL = aSource.mURL;
   } else if (aSource.mType == NS_STYLE_FILTER_DROP_SHADOW) {
     SetDropShadow(aSource.mDropShadow);
   } else if (aSource.mType != NS_STYLE_FILTER_NONE) {
     SetFilterParameter(aSource.mFilterParameter, aSource.mType);
   }
 }
 
 nsStyleFilter::~nsStyleFilter()
@@ -1231,17 +1232,17 @@ nsStyleFilter::~nsStyleFilter()
 
 nsStyleFilter&
 nsStyleFilter::operator=(const nsStyleFilter& aOther)
 {
   if (this == &aOther)
     return *this;
 
   if (aOther.mType == NS_STYLE_FILTER_URL) {
-    SetURL(aOther.mURL);
+    mURL = aOther.mURL;
   } else if (aOther.mType == NS_STYLE_FILTER_DROP_SHADOW) {
     SetDropShadow(aOther.mDropShadow);
   } else if (aOther.mType != NS_STYLE_FILTER_NONE) {
     SetFilterParameter(aOther.mFilterParameter, aOther.mType);
   } else {
     ReleaseRef();
     mType = NS_STYLE_FILTER_NONE;
   }
@@ -1252,56 +1253,59 @@ nsStyleFilter::operator=(const nsStyleFi
 bool
 nsStyleFilter::operator==(const nsStyleFilter& aOther) const
 {
   if (mType != aOther.mType) {
       return false;
   }
 
   if (mType == NS_STYLE_FILTER_URL) {
-    return EqualURIs(mURL, aOther.mURL);
+    return aOther.mURL == mURL;
   } else if (mType == NS_STYLE_FILTER_DROP_SHADOW) {
     return *mDropShadow == *aOther.mDropShadow;
   } else if (mType != NS_STYLE_FILTER_NONE) {
     return mFilterParameter == aOther.mFilterParameter;
   }
 
   return true;
 }
 
 void
 nsStyleFilter::ReleaseRef()
 {
   if (mType == NS_STYLE_FILTER_DROP_SHADOW) {
     NS_ASSERTION(mDropShadow, "expected pointer");
     mDropShadow->Release();
+    mDropShadow = nullptr;
   } else if (mType == NS_STYLE_FILTER_URL) {
-    NS_ASSERTION(mURL, "expected pointer");
-    mURL->Release();
+    mURL.ReleaseRef();
   }
-  mURL = nullptr;
 }
 
 void
 nsStyleFilter::SetFilterParameter(const nsStyleCoord& aFilterParameter,
                                   int32_t aType)
 {
   ReleaseRef();
   mFilterParameter = aFilterParameter;
   mType = aType;
 }
 
-void
-nsStyleFilter::SetURL(nsIURI* aURL)
+bool
+nsStyleFilter::SetURL(const nsCSSValue* aValue)
 {
-  NS_ASSERTION(aURL, "expected pointer");
+  if (!aValue->GetURLValue()) {
+    return false;
+  }
+
   ReleaseRef();
-  mURL = aURL;
-  mURL->AddRef();
+
+  mURL.SetURL(aValue);
   mType = NS_STYLE_FILTER_URL;
+  return true;
 }
 
 void
 nsStyleFilter::SetDropShadow(nsCSSShadowArray* aDropShadow)
 {
   NS_ASSERTION(aDropShadow, "expected pointer");
   ReleaseRef();
   mDropShadow = aDropShadow;
--- a/layout/style/nsStyleStruct.h
+++ b/layout/style/nsStyleStruct.h
@@ -3502,41 +3502,40 @@ struct nsStyleClipPath
   bool operator!=(const nsStyleClipPath& aOther) const {
     return !(*this == aOther);
   }
 
   int32_t GetType() const {
     return mType;
   }
 
-  nsIURI* GetURL() const {
+  already_AddRefed<nsIURI> GetURL(nsIDocument* aCurrentDoc) const {
     NS_ASSERTION(mType == NS_STYLE_CLIP_PATH_URL, "wrong clip-path type");
-    return mURL;
-  }
-  void SetURL(nsIURI* aURL);
+    return mURL.Resolve(aCurrentDoc);
+  }
+  bool SetURL(const nsCSSValue* aValue);
 
   nsStyleBasicShape* GetBasicShape() const {
     NS_ASSERTION(mType == NS_STYLE_CLIP_PATH_SHAPE, "wrong clip-path type");
     return mBasicShape;
   }
 
   void SetBasicShape(nsStyleBasicShape* mBasicShape,
                      uint8_t aSizingBox = NS_STYLE_CLIP_SHAPE_SIZING_NOBOX);
 
   uint8_t GetSizingBox() const { return mSizingBox; }
   void SetSizingBox(uint8_t aSizingBox);
 
 private:
   void ReleaseRef();
   void* operator new(size_t) = delete;
-
   int32_t mType; // see NS_STYLE_CLIP_PATH_* constants in nsStyleConsts.h
   union {
     nsStyleBasicShape* mBasicShape;
-    nsIURI* mURL;
+    FragmentURL mURL;
   };
   uint8_t mSizingBox; // see NS_STYLE_CLIP_SHAPE_SIZING_* constants in nsStyleConsts.h
 };
 
 struct nsStyleFilter
 {
   nsStyleFilter();
   nsStyleFilter(const nsStyleFilter& aSource);
@@ -3557,35 +3556,35 @@ struct nsStyleFilter
     NS_ASSERTION(mType != NS_STYLE_FILTER_DROP_SHADOW &&
                  mType != NS_STYLE_FILTER_URL &&
                  mType != NS_STYLE_FILTER_NONE, "wrong filter type");
     return mFilterParameter;
   }
   void SetFilterParameter(const nsStyleCoord& aFilterParameter,
                           int32_t aType);
 
-  nsIURI* GetURL() const {
+  already_AddRefed<nsIURI> GetURL(nsIDocument* aCurrentDoc) const {
     NS_ASSERTION(mType == NS_STYLE_FILTER_URL, "wrong filter type");
-    return mURL;
-  }
-  void SetURL(nsIURI* aURL);
+    return mURL.Resolve(aCurrentDoc);
+  }
+  bool SetURL(const nsCSSValue* aValue);
 
   nsCSSShadowArray* GetDropShadow() const {
     NS_ASSERTION(mType == NS_STYLE_FILTER_DROP_SHADOW, "wrong filter type");
     return mDropShadow;
   }
   void SetDropShadow(nsCSSShadowArray* aDropShadow);
 
 private:
   void ReleaseRef();
 
   int32_t mType; // see NS_STYLE_FILTER_* constants in nsStyleConsts.h
   nsStyleCoord mFilterParameter; // coord, percent, factor, angle
   union {
-    nsIURI* mURL;
+    FragmentURL mURL;
     nsCSSShadowArray* mDropShadow;
   };
 };
 
 template<>
 struct nsTArray_CopyChooser<nsStyleFilter>
 {
   typedef nsTArray_CopyWithConstructors<nsStyleFilter> Type;
--- a/layout/svg/nsSVGEffects.cpp
+++ b/layout/svg/nsSVGEffects.cpp
@@ -273,19 +273,19 @@ NS_INTERFACE_MAP_END
 NS_IMPL_CYCLE_COLLECTION(nsSVGFilterChainObserver, mReferences)
 
 nsSVGFilterChainObserver::nsSVGFilterChainObserver(const nsTArray<nsStyleFilter>& aFilters,
                                                    nsIContent* aFilteredElement)
 {
   for (uint32_t i = 0; i < aFilters.Length(); i++) {
     if (aFilters[i].GetType() != NS_STYLE_FILTER_URL)
       continue;
-
+    nsCOMPtr<nsIURI> filterURL = aFilters[i].GetURL(aFilteredElement->OwnerDoc());
     RefPtr<nsSVGFilterReference> reference =
-      new nsSVGFilterReference(aFilters[i].GetURL(), aFilteredElement, this);
+      new nsSVGFilterReference(filterURL, aFilteredElement, this);
     mReferences.AppendElement(reference);
   }
 }
 
 nsSVGFilterChainObserver::~nsSVGFilterChainObserver()
 {
   for (uint32_t i = 0; i < mReferences.Length(); i++) {
     mReferences[i]->DetachFromChainObserver();
@@ -576,18 +576,21 @@ nsSVGEffects::GetEffectProperties(nsIFra
   NS_ASSERTION(!aFrame->GetPrevContinuation(), "aFrame should be first continuation");
 
   EffectProperties result;
   const nsStyleSVGReset *style = aFrame->StyleSVGReset();
 
   result.mFilter = GetOrCreateFilterProperty(aFrame);
 
   if (style->mClipPath.GetType() == NS_STYLE_CLIP_PATH_URL) {
+    nsIDocument* doc = aFrame->StyleContext()->PresContext()->Document();
+    nsCOMPtr<nsIURI> pathURI = style->mClipPath.GetURL(doc);
+
     result.mClipPath =
-      GetPaintingProperty(style->mClipPath.GetURL(), aFrame, ClipPathProperty());
+      GetPaintingProperty(pathURI, aFrame, ClipPathProperty());
   } else {
     result.mClipPath = nullptr;
   }
 
   MOZ_ASSERT(style->mMask.mImageCount > 0);
   result.mMask = style->mMask.HasLayerWithImage()
                  ? GetOrCreateMaskProperty(aFrame) : nullptr;
 
--- a/layout/svg/nsSVGFilterInstance.cpp
+++ b/layout/svg/nsSVGFilterInstance.cpp
@@ -115,25 +115,25 @@ nsSVGFilterInstance::ComputeBounds()
 nsSVGFilterFrame*
 nsSVGFilterInstance::GetFilterFrame()
 {
   if (mFilter.GetType() != NS_STYLE_FILTER_URL) {
     // The filter is not an SVG reference filter.
     return nullptr;
   }
 
-  nsIURI* url = mFilter.GetURL();
-  if (!url) {
-    NS_NOTREACHED("an nsStyleFilter of type URL should have a non-null URL");
+  // Get the target element to use as a point of reference for looking up the
+  // filter element.
+  if (!mTargetContent) {
     return nullptr;
   }
 
-  // Get the target element to use as a point of reference for looking up the
-  // filter element.
-  if (!mTargetContent) {
+  nsCOMPtr<nsIURI> url = mFilter.GetURL(mTargetContent->OwnerDoc());
+  if (!url) {
+    NS_NOTREACHED("an nsStyleFilter of type URL should have a non-null URL");
     return nullptr;
   }
 
   // Look up the filter element by URL.
   nsReferencedElement filterElement;
   bool watch = false;
   filterElement.Reset(mTargetContent, url, watch);
   Element* element = filterElement.get();