Bug 1301245 - Part 1. Implement nsStyleImage::SetURL and GetURLValueData. draft
authorcku <cku@mozilla.com>
Thu, 30 Mar 2017 19:51:03 +0800
changeset 553707 72049d97a156fa522862b59890799baea23e654b
parent 553706 e69ff5d7308dd14eeafc7ad102b3bcc4861b4709
child 553708 349712551c4d8d033ce3b7993842d5fe4c50fcd1
push id51730
push userbmo:cku@mozilla.com
push dateThu, 30 Mar 2017 14:08:11 +0000
bugs1301245
milestone55.0a1
Bug 1301245 - Part 1. Implement nsStyleImage::SetURL and GetURLValueData. Prerequisites of removing Layer::mSourceURI. MozReview-Commit-ID: E20MEzXv8cg
layout/style/nsRuleNode.cpp
layout/style/nsStyleStruct.cpp
layout/style/nsStyleStruct.h
--- a/layout/style/nsRuleNode.cpp
+++ b/layout/style/nsRuleNode.cpp
@@ -1406,17 +1406,17 @@ static void SetStyleImage(nsStyleContext
         nsIURI* imageURI = aValue.GetURLValue();
         imageURI->EqualsExceptRef(docURI, &isEqualExceptRef);
       }
 
       MOZ_ASSERT(aStyleContext->IsStyleIfVisited() || isEqualExceptRef ||
                  isLocalRef,
                  "unexpected unit; maybe nsCSSValue::Image::Image() failed?");
 #endif
-
+      aResult.SetURL(do_AddRef(aValue.GetURLStructValue()));
       break;
     }
     default:
       MOZ_ASSERT_UNREACHABLE("Unexpected Unit type.");
       break;
   }
 }
 
--- a/layout/style/nsStyleStruct.cpp
+++ b/layout/style/nsStyleStruct.cpp
@@ -2192,16 +2192,18 @@ nsStyleImage::DoCopy(const nsStyleImage&
   SetNull();
 
   if (aOther.mType == eStyleImageType_Image) {
     SetImageRequest(do_AddRef(aOther.mImage));
   } else if (aOther.mType == eStyleImageType_Gradient) {
     SetGradientData(aOther.mGradient);
   } else if (aOther.mType == eStyleImageType_Element) {
     SetElementId(aOther.mElementId);
+  } else if (mType == eStyleImageType_Url) {
+    SetURL(do_AddRef(aOther.mUrlData));
   }
 
   UniquePtr<nsStyleSides> cropRectCopy;
   if (aOther.mCropRect) {
     cropRectCopy = MakeUnique<nsStyleSides>(*aOther.mCropRect.get());
   }
   SetCropRect(Move(cropRectCopy));
 }
@@ -2210,16 +2212,18 @@ void
 nsStyleImage::SetNull()
 {
   if (mType == eStyleImageType_Gradient) {
     mGradient->Release();
   } else if (mType == eStyleImageType_Image) {
     NS_RELEASE(mImage);
   } else if (mType == eStyleImageType_Element) {
     free(mElementId);
+  } else if (mType == eStyleImageType_Url) {
+    NS_RELEASE(mUrlData);
   }
 
   mType = eStyleImageType_Null;
   mCropRect = nullptr;
 }
 
 void
 nsStyleImage::SetImageRequest(already_AddRefed<nsStyleImageRequest> aImage)
@@ -2270,16 +2274,31 @@ nsStyleImage::SetElementId(const char16_
 }
 
 void
 nsStyleImage::SetCropRect(UniquePtr<nsStyleSides> aCropRect)
 {
     mCropRect = Move(aCropRect);
 }
 
+void
+nsStyleImage::SetURL(already_AddRefed<URLValueData> aData)
+{
+  RefPtr<URLValueData> data = aData;
+
+  if (mType != eStyleImageType_Null) {
+    SetNull();
+  }
+
+  if (data) {
+    mUrlData = data.forget().take();
+    mType = eStyleImageType_Url;
+  }
+}
+
 static int32_t
 ConvertToPixelCoord(const nsStyleCoord& aCoord, int32_t aPercentScale)
 {
   double pixelValue;
   switch (aCoord.GetUnit()) {
     case eStyleUnit_Percent:
       pixelValue = aCoord.GetPercentValue() * aPercentScale;
       break;
@@ -2415,16 +2434,17 @@ nsStyleImage::IsOpaque() const
 bool
 nsStyleImage::IsComplete() const
 {
   switch (mType) {
     case eStyleImageType_Null:
       return false;
     case eStyleImageType_Gradient:
     case eStyleImageType_Element:
+    case eStyleImageType_Url:
       return true;
     case eStyleImageType_Image: {
       imgRequestProxy* req = GetImageData();
       if (!req) {
         return false;
       }
       uint32_t status = imgIRequest::STATUS_ERROR;
       return NS_SUCCEEDED(req->GetImageStatus(&status)) &&
@@ -2521,16 +2541,28 @@ nsStyleImage::GetImageURI() const
   if (mType != eStyleImageType_Image) {
     return nullptr;
   }
 
   nsCOMPtr<nsIURI> uri = mImage->GetImageURI();
   return uri.forget();
 }
 
+css::URLValueData*
+nsStyleImage::GetURLValueData() const
+{
+  if (mType == eStyleImageType_Image) {
+    return mImage->GetURLValueData();
+  } else if (mType == eStyleImageType_Url) {
+    return mUrlData;
+  }
+
+  return nullptr;
+}
+
 // --------------------
 // nsStyleImageLayers
 //
 
 const nsCSSPropertyID nsStyleImageLayers::kBackgroundLayerTable[] = {
   eCSSProperty_background,                // shorthand
   eCSSProperty_background_color,          // color
   eCSSProperty_background_image,          // image
--- a/layout/style/nsStyleStruct.h
+++ b/layout/style/nsStyleStruct.h
@@ -300,16 +300,18 @@ private:
  * creates a new css::ImageValue to represent the url() information passed
  * to the constructor.  This ImageValue is held on to for the comparisons done
  * in DefinitelyEquals(), so that we don't need to call into the non-OMT-safe
  * Equals() on the nsIURI objects returned from imgRequestProxy::GetURI().
  */
 class nsStyleImageRequest
 {
 public:
+  typedef mozilla::css::URLValueData URLValueData;
+
   // Flags describing whether the imgRequestProxy must be tracked in the
   // ImageTracker, whether LockImage/UnlockImage calls will be made
   // when obtaining and releasing the imgRequestProxy, and whether
   // RequestDiscard will be called on release.
   enum class Mode : uint8_t {
     // The imgRequestProxy will be added to the ImageTracker when resolved
     // Without this flag, the nsStyleImageRequest itself will call LockImage/
     // UnlockImage on the imgRequestProxy, rather than leaving locking to the
@@ -357,17 +359,19 @@ public:
 
   // Returns whether the ImageValue objects in the two nsStyleImageRequests
   // return true from URLValueData::DefinitelyEqualURIs.
   bool DefinitelyEquals(const nsStyleImageRequest& aOther) const;
 
   mozilla::css::ImageValue* GetImageValue() const { return mImageValue; }
 
   already_AddRefed<nsIURI> GetImageURI() const;
-
+  URLValueData* GetURLValueData() const {
+    return mImageValue;
+  }
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(nsStyleImageRequest);
 
 private:
   ~nsStyleImageRequest();
   nsStyleImageRequest& operator=(const nsStyleImageRequest& aOther) = delete;
 
   void MaybeTrackAndLock();
 
@@ -383,17 +387,18 @@ private:
 };
 
 MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(nsStyleImageRequest::Mode)
 
 enum nsStyleImageType {
   eStyleImageType_Null,
   eStyleImageType_Image,
   eStyleImageType_Gradient,
-  eStyleImageType_Element
+  eStyleImageType_Element,
+  eStyleImageType_Url
 };
 
 struct CachedBorderImageData
 {
   // Caller are expected to ensure that the value of aSVGViewportSize is
   // different from the cached one since the method won't do the check.
   void SetCachedSVGViewportSize(const mozilla::Maybe<nsSize>& aSVGViewportSize);
   const mozilla::Maybe<nsSize>& GetCachedSVGViewportSize();
@@ -416,26 +421,29 @@ private:
  * (3) An element within a document, or an <img>, <video>, or <canvas> element
  *     not in a document.
  * (*) Optionally a crop rect can be set to paint a partial (rectangular)
  * region of an image. (Currently, this feature is only supported with an
  * image of type (1)).
  */
 struct nsStyleImage
 {
+  typedef mozilla::css::URLValueData URLValueData;
+
   nsStyleImage();
   ~nsStyleImage();
   nsStyleImage(const nsStyleImage& aOther);
   nsStyleImage& operator=(const nsStyleImage& aOther);
 
   void SetNull();
   void SetImageRequest(already_AddRefed<nsStyleImageRequest> aImage);
   void SetGradientData(nsStyleGradient* aGradient);
   void SetElementId(const char16_t* aElementId);
   void SetCropRect(mozilla::UniquePtr<nsStyleSides> aCropRect);
+  void SetURL(already_AddRefed<URLValueData> aData);
 
   void ResolveImage(nsPresContext* aContext) {
     MOZ_ASSERT(mType != eStyleImageType_Image || mImage);
     if (mType == eStyleImageType_Image && !mImage->IsResolved()) {
       mImage->Resolve(aContext);
     }
   }
 
@@ -461,16 +469,18 @@ struct nsStyleImage
   const mozilla::UniquePtr<nsStyleSides>& GetCropRect() const {
     NS_ASSERTION(mType == eStyleImageType_Image,
                  "Only image data can have a crop rect");
     return mCropRect;
   }
 
   already_AddRefed<nsIURI> GetImageURI() const;
 
+  URLValueData* GetURLValueData() const;
+
   /**
    * Compute the actual crop rect in pixels, using the source image bounds.
    * The computation involves converting percentage unit to pixel unit and
    * clamping each side value to fit in the source image bounds.
    * @param aActualCropRect the computed actual crop rect.
    * @param aIsEntireImage true iff |aActualCropRect| is identical to the
    * source image bounds.
    * @return true iff |aActualCropRect| holds a meaningful value.
@@ -544,16 +554,19 @@ private:
   // This variable keeps some cache data for border image and is lazily
   // allocated since it is only used in border image case.
   mozilla::UniquePtr<CachedBorderImageData> mCachedBIData;
 
   nsStyleImageType mType;
   union {
     nsStyleImageRequest* mImage;
     nsStyleGradient* mGradient;
+    URLValueData* mUrlData; // See the comment in SetStyleImage's 'case
+                            // eCSSUnit_URL' section to know why we need to
+                            // keep url other then mImage.
     char16_t* mElementId;
   };
 
   // This is _currently_ used only in conjunction with eStyleImageType_Image.
   mozilla::UniquePtr<nsStyleSides> mCropRect;
 };
 
 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleColor