Bug 1301245 - Part 3. Resolve a style image if nsSVGPaintingProperty can not handle it. draft
authorcku <cku@mozilla.com>
Wed, 26 Jul 2017 12:02:44 +0800
changeset 615789 9d0993da476d08f1425d1e7fba2c57031c7049ac
parent 615788 5dec40d18494f9b62f12147c032d87b70727c74f
child 639277 9952e940df2e713013ef27daa0fd781b14e90d1f
push id70472
push userbmo:cku@mozilla.com
push dateWed, 26 Jul 2017 09:57:39 +0000
bugs1301245
milestone56.0a1
Bug 1301245 - Part 3. Resolve a style image if nsSVGPaintingProperty can not handle it. MozReview-Commit-ID: 9m7yJ4CgCvr
layout/svg/nsSVGEffects.cpp
layout/svg/nsSVGEffects.h
--- a/layout/svg/nsSVGEffects.cpp
+++ b/layout/svg/nsSVGEffects.cpp
@@ -14,16 +14,17 @@
 #include "nsSVGClipPathFrame.h"
 #include "nsSVGPaintServerFrame.h"
 #include "nsSVGFilterFrame.h"
 #include "nsSVGMaskFrame.h"
 #include "nsIReflowCallback.h"
 #include "nsCycleCollectionParticipant.h"
 #include "SVGGeometryElement.h"
 #include "SVGUseElement.h"
+#include "ImageLoader.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 void
 nsSVGRenderingObserver::StartListening()
 {
   Element* target = GetTarget();
@@ -387,16 +388,17 @@ nsSVGMarkerProperty::DoUpdate()
   }
   frame->PresContext()->RestyleManager()->PostRestyleEvent(
     frame->GetContent()->AsElement(), nsRestyleHint(0), changeHint);
 }
 
 NS_IMPL_ISUPPORTS(nsSVGMaskProperty, nsISupports)
 
 nsSVGMaskProperty::nsSVGMaskProperty(nsIFrame* aFrame)
+ : mFrame(aFrame)
 {
   const nsStyleSVGReset *svgReset = aFrame->StyleSVGReset();
 
   for (uint32_t i = 0; i < svgReset->mMask.mImageCount; i++) {
     nsCOMPtr<nsIURI> maskUri = nsSVGEffects::GetMaskURI(aFrame, i);
     bool hasRef = false;
     if (maskUri) {
       maskUri->GetHasRef(&hasRef);
@@ -410,16 +412,37 @@ nsSVGMaskProperty::nsSVGMaskProperty(nsI
     // a fragment.
     nsSVGPaintingProperty* prop =
       new nsSVGPaintingProperty(hasRef ? maskUri.get() : nullptr,
                                 aFrame, false);
     mProperties.AppendElement(prop);
   }
 }
 
+void
+nsSVGMaskProperty::ResolveImage(uint32_t aIndex)
+{
+  const nsStyleSVGReset* svgReset = mFrame->StyleSVGReset();
+  MOZ_ASSERT(aIndex < svgReset->mMask.mImageCount);
+
+  nsStyleImage& image =
+    const_cast<nsStyleImage&>(svgReset->mMask.mLayers[aIndex].mImage);
+
+  if (!image.IsResolved()) {
+    MOZ_ASSERT(image.GetType() == nsStyleImageType::eStyleImageType_Image);
+    image.ResolveImage(mFrame->PresContext());
+
+    mozilla::css::ImageLoader* imageLoader =
+      mFrame->PresContext()->Document()->StyleImageLoader();
+    if (imgRequestProxy* req = image.GetImageData()) {
+      imageLoader->AssociateRequestToFrame(req, mFrame);
+    }
+  }
+}
+
 bool
 nsSVGTextPathProperty::TargetIsValid()
 {
   Element* target = GetTarget();
   return target && target->IsSVGElement(nsGkAtoms::path);
 }
 
 void
@@ -666,16 +689,25 @@ nsSVGEffects::EffectProperties::GetMaskF
     return result;
 
   bool ok = true;
   const nsTArray<RefPtr<nsSVGPaintingProperty>>& props = mMask->GetProps();
   for (size_t i = 0; i < props.Length(); i++) {
     nsSVGMaskFrame* maskFrame = static_cast<nsSVGMaskFrame*>(
       props[i]->GetReferencedFrame(LayoutFrameType::SVGMask, &ok));
     MOZ_ASSERT(!maskFrame || ok);
+    if (!ok) {
+      // We can not find the specific SVG mask resource in the downloaded SVG
+      // document. There are two possibilities:
+      // 1. The given resource id is invalid.
+      // 2. The given resource id refers to a viewbox.
+      //
+      // Hand it over to the style image.
+      mMask->ResolveImage(i);
+    }
     result.AppendElement(maskFrame);
   }
 
   return result;
 }
 
 bool
 nsSVGEffects::EffectProperties::HasNoOrValidEffects()
--- a/layout/svg/nsSVGEffects.h
+++ b/layout/svg/nsSVGEffects.h
@@ -350,19 +350,22 @@ public:
   // nsISupports
   NS_DECL_ISUPPORTS
 
   const nsTArray<RefPtr<nsSVGPaintingProperty>>& GetProps() const
   {
     return mProperties;
   }
 
+  void ResolveImage(uint32_t aIndex);
+
 private:
   virtual ~nsSVGMaskProperty() {}
   nsTArray<RefPtr<nsSVGPaintingProperty>> mProperties;
+  nsIFrame* mFrame;
 };
 
 /**
  * A manager for one-shot nsSVGRenderingObserver tracking.
  * nsSVGRenderingObservers can be added or removed. They are not strongly
  * referenced so an observer must be removed before it dies.
  * When InvalidateAll is called, all outstanding references get
  * InvalidateViaReferencedElement()