Bug 652991 - Part 5. Using FragmentOrURL to represent SVG clippath. draft
authorcku <cku@mozilla.com>
Tue, 05 Jul 2016 00:59:57 +0800
changeset 395500 80be67a595c095ee233097306d37eb915a021991
parent 395499 d73aaf717522406a38ac65f4d520e81b8f1dbda5
child 395501 75cf8f04b020151b2b53fccef4a6a224aed505ea
push id24801
push usercku@mozilla.com
push dateTue, 02 Aug 2016 14:45:11 +0000
bugs652991
milestone51.0a1
Bug 652991 - Part 5. Using FragmentOrURL to represent SVG clippath. MozReview-Commit-ID: BErpWUQ5iQ1
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/nsSVGEffects.h
--- a/layout/style/StyleAnimationValue.cpp
+++ b/layout/style/StyleAnimationValue.cpp
@@ -3950,20 +3950,23 @@ StyleAnimationValue::ExtractComputedValu
         case eCSSProperty_clip_path: {
           const nsStyleSVGReset* svgReset =
             static_cast<const nsStyleSVGReset*>(styleStruct);
           const nsStyleClipPath& clipPath = svgReset->mClipPath;
           const StyleClipPathType type = clipPath.GetType();
 
           if (type == StyleClipPathType::URL) {
             nsIDocument* doc = aStyleContext->PresContext()->Document();
+            nsString pathString;
+            clipPath.GetURL()->GetSourceString(pathString);
             RefPtr<nsStringBuffer> uriAsStringBuffer =
-              GetURIAsUtf16StringBuffer(clipPath.GetURL());
+              nsCSSValue::BufferFromString(pathString);
+
             RefPtr<mozilla::css::URLValue> url =
-              new mozilla::css::URLValue(clipPath.GetURL(),
+              new mozilla::css::URLValue(clipPath.GetURL()->GetSourceURL(),
                                          uriAsStringBuffer,
                                          doc->GetDocumentURI(),
                                          doc->NodePrincipal());
             auto result = MakeUnique<nsCSSValue>();
             result->SetURLValue(url);
             aComputedValue.SetAndAdoptCSSValueValue(result.release(), eUnit_URL);
           } else if (type == StyleClipPathType::Box) {
             aComputedValue.SetIntValue(clipPath.GetSizingBox(),
--- a/layout/style/nsComputedDOMStyle.cpp
+++ b/layout/style/nsComputedDOMStyle.cpp
@@ -6027,18 +6027,20 @@ nsComputedDOMStyle::DoGetClipPath()
   switch (svg->mClipPath.GetType()) {
     case StyleClipPathType::Shape:
       return CreatePrimitiveValueForClipPath(svg->mClipPath.GetBasicShape(),
                                              svg->mClipPath.GetSizingBox());
     case StyleClipPathType::Box:
       return CreatePrimitiveValueForClipPath(nullptr,
                                              svg->mClipPath.GetSizingBox());
     case StyleClipPathType::URL: {
+      // Bug 1288812 - we should only serialize fragment for local-ref URL.
+      nsCOMPtr<nsIURI> pathURI = svg->mClipPath.GetURL()->GetSourceURL();
       RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
-      val->SetURI(svg->mClipPath.GetURL());
+      val->SetURI(pathURI);
       return val.forget();
     }
     case StyleClipPathType::None_: {
       RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
       val->SetIdent(eCSSKeyword_none);
       return val.forget();
     }
     default:
--- a/layout/style/nsRuleNode.cpp
+++ b/layout/style/nsRuleNode.cpp
@@ -9880,20 +9880,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
@@ -1117,17 +1117,17 @@ nsStyleClipPath::nsStyleClipPath()
 }
 
 nsStyleClipPath::nsStyleClipPath(const nsStyleClipPath& aSource)
   : mURL(nullptr)
   , mType(StyleClipPathType::None_)
   , mSizingBox(StyleClipShapeSizing::NoBox)
 {
   if (aSource.mType == StyleClipPathType::URL) {
-    SetURL(aSource.mURL);
+    CopyURL(aSource);
   } else if (aSource.mType == StyleClipPathType::Shape) {
     SetBasicShape(aSource.mBasicShape, aSource.mSizingBox);
   } else if (aSource.mType == StyleClipPathType::Box) {
     SetSizingBox(aSource.mSizingBox);
   }
 }
 
 nsStyleClipPath::~nsStyleClipPath()
@@ -1138,17 +1138,17 @@ nsStyleClipPath::~nsStyleClipPath()
 nsStyleClipPath&
 nsStyleClipPath::operator=(const nsStyleClipPath& aOther)
 {
   if (this == &aOther) {
     return *this;
   }
 
   if (aOther.mType == StyleClipPathType::URL) {
-    SetURL(aOther.mURL);
+    CopyURL(aOther);
   } else if (aOther.mType == StyleClipPathType::Shape) {
     SetBasicShape(aOther.mBasicShape, aOther.mSizingBox);
   } else if (aOther.mType == StyleClipPathType::Box) {
     SetSizingBox(aOther.mSizingBox);
   } else {
     ReleaseRef();
     mSizingBox = StyleClipShapeSizing::NoBox;
     mType = StyleClipPathType::None_;
@@ -1178,33 +1178,47 @@ nsStyleClipPath::operator==(const nsStyl
 void
 nsStyleClipPath::ReleaseRef()
 {
   if (mType == StyleClipPathType::Shape) {
     NS_ASSERTION(mBasicShape, "expected pointer");
     mBasicShape->Release();
   } else if (mType == StyleClipPathType::URL) {
     NS_ASSERTION(mURL, "expected pointer");
-    mURL->Release();
+    delete mURL;
   }
   // 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)
+nsStyleClipPath::CopyURL(const nsStyleClipPath& aOther)
 {
-  NS_ASSERTION(aURL, "expected pointer");
   ReleaseRef();
-  mURL = aURL;
-  mURL->AddRef();
+
+  mURL = new FragmentOrURL(*aOther.mURL);
   mType = StyleClipPathType::URL;
 }
 
+bool
+nsStyleClipPath::SetURL(const nsCSSValue* aValue)
+{
+  if (!aValue->GetURLValue()) {
+    return false;
+  }
+
+  ReleaseRef();
+
+  mURL = new FragmentOrURL();
+  mURL->SetValue(aValue);
+  mType = StyleClipPathType::URL;
+  return true;
+}
+
 void
 nsStyleClipPath::SetBasicShape(nsStyleBasicShape* aBasicShape,
                                StyleClipShapeSizing aSizingBox)
 {
   NS_ASSERTION(aBasicShape, "expected pointer");
   ReleaseRef();
   mBasicShape = aBasicShape;
   mBasicShape->AddRef();
--- a/layout/style/nsStyleStruct.h
+++ b/layout/style/nsStyleStruct.h
@@ -3522,41 +3522,43 @@ struct nsStyleClipPath
   bool operator!=(const nsStyleClipPath& aOther) const {
     return !(*this == aOther);
   }
 
   mozilla::StyleClipPathType GetType() const {
     return mType;
   }
 
-  nsIURI* GetURL() const {
+  FragmentOrURL* GetURL() const {
     NS_ASSERTION(mType == mozilla::StyleClipPathType::URL, "wrong clip-path type");
     return mURL;
   }
-  void SetURL(nsIURI* aURL);
+  bool SetURL(const nsCSSValue* aValue);
 
   nsStyleBasicShape* GetBasicShape() const {
     NS_ASSERTION(mType == mozilla::StyleClipPathType::Shape, "wrong clip-path type");
     return mBasicShape;
   }
 
   void SetBasicShape(nsStyleBasicShape* mBasicShape,
                      mozilla::StyleClipShapeSizing aSizingBox =
                      mozilla::StyleClipShapeSizing::NoBox);
 
   mozilla::StyleClipShapeSizing GetSizingBox() const { return mSizingBox; }
   void SetSizingBox(mozilla::StyleClipShapeSizing aSizingBox);
 
 private:
   void ReleaseRef();
+  void CopyURL(const nsStyleClipPath& aOther);
+
   void* operator new(size_t) = delete;
 
   union {
     nsStyleBasicShape* mBasicShape;
-    nsIURI* mURL;
+    FragmentOrURL* mURL;
   };
   mozilla::StyleClipPathType    mType;
   mozilla::StyleClipShapeSizing mSizingBox;
 };
 
 struct nsStyleFilter
 {
   nsStyleFilter();
--- a/layout/svg/nsSVGEffects.cpp
+++ b/layout/svg/nsSVGEffects.cpp
@@ -568,18 +568,19 @@ 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() == StyleClipPathType::URL) {
+    nsCOMPtr<nsIURI> pathURI = nsSVGEffects::GetClipPathURI(aFrame);
     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;
 
@@ -905,8 +906,18 @@ ResolveFragmentOrURL(nsIFrame* aFrame, c
 }
 
 already_AddRefed<nsIURI>
 nsSVGEffects::GetMarkerURI(nsIFrame* aFrame,
                            FragmentOrURL nsStyleSVG::* aMarker)
 {
   return ResolveFragmentOrURL(aFrame, &(aFrame->StyleSVG()->*aMarker));
 }
+
+already_AddRefed<nsIURI>
+nsSVGEffects::GetClipPathURI(nsIFrame *aFrame)
+{
+  const nsStyleSVGReset* svgResetStyle = aFrame->StyleSVGReset();
+  MOZ_ASSERT(svgResetStyle->mClipPath.GetType() == NS_STYLE_CLIP_PATH_URL);
+
+  FragmentOrURL* url = svgResetStyle->mClipPath.GetURL();
+  return ResolveFragmentOrURL(aFrame, url);
+}
--- a/layout/svg/nsSVGEffects.h
+++ b/layout/svg/nsSVGEffects.h
@@ -593,11 +593,17 @@ public:
   GetPaintingPropertyForURI(nsIURI *aURI, nsIFrame *aFrame,
                             URIObserverHashtablePropertyDescriptor aProp);
 
   /**
    * A helper function to resolve marker's URL.
    */
   static already_AddRefed<nsIURI>
   GetMarkerURI(nsIFrame* aFrame, FragmentOrURL nsStyleSVG::* aMarker);
+
+  /**
+   * A helper function to resolve clip-path URL.
+   */
+  static already_AddRefed<nsIURI>
+  GetClipPathURI(nsIFrame* aFrame);
 };
 
 #endif /*NSSVGEFFECTS_H_*/