Bug 1351440 - Part 2. Encapsulate DrawResult and imgIContainer::FLAG_* into imgDrawingParams, and pass it to PaintSVG. draft
authorcku <cku@mozilla.com>
Fri, 05 May 2017 17:19:43 +0800
changeset 580452 e70b5243b3cd61e8844f22bfdf2098202f90450c
parent 580415 c1a7eac91cb4439d74d9488ec0d58f80e9cd912b
child 580453 2d1c92fe56094d879542572e774b197f39f9c7a0
push id59558
push userbmo:cku@mozilla.com
push dateThu, 18 May 2017 14:49:17 +0000
bugs1351440
milestone55.0a1
Bug 1351440 - Part 2. Encapsulate DrawResult and imgIContainer::FLAG_* into imgDrawingParams, and pass it to PaintSVG. The DrawResult return was not in fact anything to do with the success or failure of that method, but was actually passing out a very specific piece of information about the success or failure of any imagelib drawing that may not have occurred under the various PaintSVG calls. The signature of PaintSVG is changed from DrawResult PaintSVG(...., uint32 flags); to void PaintSVG(...., imgDrawingParams& aPackage); imgDrawingParams wraps DrawResult and imgIContainer::FLAG_* as a pack, pass through PaintSVG to imagelib draw calls under beneath. MozReview-Commit-ID: IOq2evUAOQF
gfx/thebes/gfxFont.cpp
gfx/thebes/gfxFontEntry.cpp
gfx/thebes/gfxFontEntry.h
gfx/thebes/gfxSVGGlyphs.cpp
gfx/thebes/gfxSVGGlyphs.h
layout/painting/nsDisplayList.cpp
layout/painting/nsDisplayList.h
layout/svg/SVGGeometryFrame.cpp
layout/svg/SVGGeometryFrame.h
layout/svg/SVGTextFrame.cpp
layout/svg/SVGTextFrame.h
layout/svg/nsFilterInstance.cpp
layout/svg/nsFilterInstance.h
layout/svg/nsSVGClipPathFrame.cpp
layout/svg/nsSVGClipPathFrame.h
layout/svg/nsSVGContainerFrame.cpp
layout/svg/nsSVGContainerFrame.h
layout/svg/nsSVGDisplayableFrame.h
layout/svg/nsSVGFilterPaintCallback.h
layout/svg/nsSVGForeignObjectFrame.cpp
layout/svg/nsSVGForeignObjectFrame.h
layout/svg/nsSVGImageFrame.cpp
layout/svg/nsSVGInnerSVGFrame.cpp
layout/svg/nsSVGInnerSVGFrame.h
layout/svg/nsSVGIntegrationUtils.cpp
layout/svg/nsSVGIntegrationUtils.h
layout/svg/nsSVGMarkerFrame.cpp
layout/svg/nsSVGMarkerFrame.h
layout/svg/nsSVGMaskFrame.cpp
layout/svg/nsSVGMaskFrame.h
layout/svg/nsSVGOuterSVGFrame.cpp
layout/svg/nsSVGOuterSVGFrame.h
layout/svg/nsSVGPaintServerFrame.h
layout/svg/nsSVGPatternFrame.cpp
layout/svg/nsSVGSwitchFrame.cpp
layout/svg/nsSVGUtils.cpp
layout/svg/nsSVGUtils.h
--- a/gfx/thebes/gfxFont.cpp
+++ b/gfx/thebes/gfxFont.cpp
@@ -2222,21 +2222,20 @@ gfxFont::RenderSVGGlyph(gfxContext *aCon
 
     aContext->Save();
     aContext->SetMatrix(
       aContext->CurrentMatrix().Translate(aPoint.x, aPoint.y).
                                 Scale(devUnitsPerSVGUnit, devUnitsPerSVGUnit));
 
     aContextPaint->InitStrokeGeometry(aContext, devUnitsPerSVGUnit);
 
-    bool rv = GetFontEntry()->RenderSVGGlyph(aContext, aGlyphId,
-                                             aContextPaint);
+    GetFontEntry()->RenderSVGGlyph(aContext, aGlyphId, aContextPaint);
     aContext->Restore();
     aContext->NewPath();
-    return rv;
+    return true;
 }
 
 bool
 gfxFont::RenderSVGGlyph(gfxContext *aContext, gfxPoint aPoint,
                         uint32_t aGlyphId, SVGContextPaint* aContextPaint,
                         gfxTextRunDrawCallbacks *aCallbacks,
                         bool& aEmittedGlyphs) const
 {
--- a/gfx/thebes/gfxFontEntry.cpp
+++ b/gfx/thebes/gfxFontEntry.cpp
@@ -343,22 +343,22 @@ gfxFontEntry::GetSVGGlyphExtents(DrawTar
     gfxMatrix svgToAppSpace(fontMatrix.xx, fontMatrix.yx,
                             fontMatrix.xy, fontMatrix.yy,
                             fontMatrix.x0, fontMatrix.y0);
     svgToAppSpace.Scale(1.0f / mUnitsPerEm, 1.0f / mUnitsPerEm);
 
     return mSVGGlyphs->GetGlyphExtents(aGlyphId, svgToAppSpace, aResult);
 }
 
-bool
+void
 gfxFontEntry::RenderSVGGlyph(gfxContext *aContext, uint32_t aGlyphId,
                              SVGContextPaint* aContextPaint)
 {
     NS_ASSERTION(mSVGInitialized, "SVG data has not yet been loaded. TryGetSVGData() first.");
-    return mSVGGlyphs->RenderGlyph(aContext, aGlyphId, aContextPaint);
+    mSVGGlyphs->RenderGlyph(aContext, aGlyphId, aContextPaint);
 }
 
 bool
 gfxFontEntry::TryGetSVGData(gfxFont* aFont)
 {
     if (!gfxPlatform::GetPlatform()->OpenTypeSVGEnabled()) {
         return false;
     }
--- a/gfx/thebes/gfxFontEntry.h
+++ b/gfx/thebes/gfxFontEntry.h
@@ -184,17 +184,17 @@ public:
     // gfxCharacterMap, even if empty, as other code assumes this pointer
     // can be safely dereferenced.
     virtual nsresult ReadCMAP(FontInfoData *aFontInfoData = nullptr);
 
     bool TryGetSVGData(gfxFont* aFont);
     bool HasSVGGlyph(uint32_t aGlyphId);
     bool GetSVGGlyphExtents(DrawTarget* aDrawTarget, uint32_t aGlyphId,
                             gfxRect *aResult);
-    bool RenderSVGGlyph(gfxContext *aContext, uint32_t aGlyphId,
+    void RenderSVGGlyph(gfxContext *aContext, uint32_t aGlyphId,
                         mozilla::SVGContextPaint* aContextPaint);
     // Call this when glyph geometry or rendering has changed
     // (e.g. animated SVG glyphs)
     void NotifyGlyphsChanged();
 
     bool     TryGetColorGlyphs();
     bool     GetColorLayersInfo(uint32_t aGlyphId,
                                 const mozilla::gfx::Color& aDefaultColor,
--- a/gfx/thebes/gfxSVGGlyphs.cpp
+++ b/gfx/thebes/gfxSVGGlyphs.cpp
@@ -207,28 +207,28 @@ gfxSVGGlyphsDocument::FindGlyphElements(
 
 /**
  * If there exists an SVG glyph with the specified glyph id, render it and return true
  * If no such glyph exists, or in the case of an error return false
  * @param aContext The thebes aContext to draw to
  * @param aGlyphId The glyph id
  * @return true iff rendering succeeded
  */
-bool
+void
 gfxSVGGlyphs::RenderGlyph(gfxContext *aContext, uint32_t aGlyphId,
                           SVGContextPaint* aContextPaint)
 {
     gfxContextAutoSaveRestore aContextRestorer(aContext);
 
     Element *glyph = mGlyphIdMap.Get(aGlyphId);
-    NS_ASSERTION(glyph, "No glyph element. Should check with HasSVGGlyph() first!");
+    MOZ_ASSERT(glyph, "No glyph element. Should check with HasSVGGlyph() first!");
 
     AutoSetRestoreSVGContextPaint autoSetRestore(aContextPaint, glyph->OwnerDoc());
 
-    return nsSVGUtils::PaintSVGGlyph(glyph, aContext);
+    nsSVGUtils::PaintSVGGlyph(glyph, aContext);
 }
 
 bool
 gfxSVGGlyphs::GetGlyphExtents(uint32_t aGlyphId, const gfxMatrix& aSVGToAppSpace,
                               gfxRect *aResult)
 {
     Element *glyph = mGlyphIdMap.Get(aGlyphId);
     NS_ASSERTION(glyph, "No glyph element. Should check with HasSVGGlyph() first!");
--- a/gfx/thebes/gfxSVGGlyphs.h
+++ b/gfx/thebes/gfxSVGGlyphs.h
@@ -115,17 +115,17 @@ public:
      */
     bool HasSVGGlyph(uint32_t aGlyphId);
 
     /**
      * Render the SVG glyph for |aGlyphId|
      * @param aContextPaint Information on text context paints.
      *   See |SVGContextPaint|.
      */
-    bool RenderGlyph(gfxContext *aContext, uint32_t aGlyphId,
+    void RenderGlyph(gfxContext *aContext, uint32_t aGlyphId,
                      mozilla::SVGContextPaint* aContextPaint);
 
     /**
      * Get the extents for the SVG glyph associated with |aGlyphId|
      * @param aSVGToAppSpace The matrix mapping the SVG glyph space to the
      *   target context space
      */
     bool GetGlyphExtents(uint32_t aGlyphId, const gfxMatrix& aSVGToAppSpace,
--- a/layout/painting/nsDisplayList.cpp
+++ b/layout/painting/nsDisplayList.cpp
@@ -8729,19 +8729,19 @@ nsDisplayFilter::PaintAsLayer(nsDisplayL
                   ? imgIContainer::FLAG_SYNC_DECODE
                   : imgIContainer::FLAG_SYNC_DECODE_IF_FAST;
   nsRect borderArea = nsRect(ToReferenceFrame(), mFrame->GetSize());
   nsSVGIntegrationUtils::PaintFramesParams params(*aCtx->ThebesContext(),
                                                   mFrame,  mVisibleRect,
                                                   borderArea, aBuilder,
                                                   aManager,
                                                   mHandleOpacity, flags);
-
-  image::DrawResult result = nsSVGIntegrationUtils::PaintFilter(params);
-  nsDisplayFilterGeometry::UpdateDrawResult(this, result);
+  imgDrawingParams imgParams(flags);
+  nsSVGIntegrationUtils::PaintFilter(params, imgParams);
+  nsDisplayFilterGeometry::UpdateDrawResult(this, imgParams.result);
 }
 
 #ifdef MOZ_DUMP_PAINTING
 void
 nsDisplayFilter::PrintEffects(nsACString& aTo)
 {
   nsIFrame* firstFrame =
     nsLayoutUtils::FirstContinuationOrIBSplitSibling(mFrame);
--- a/layout/painting/nsDisplayList.h
+++ b/layout/painting/nsDisplayList.h
@@ -1609,16 +1609,17 @@ public:
   typedef mozilla::layers::FrameMetrics::ViewID ViewID;
   typedef mozilla::layers::Layer Layer;
   typedef mozilla::layers::LayerManager LayerManager;
   typedef mozilla::layers::StackingContextHelper StackingContextHelper;
   typedef mozilla::layers::WebRenderCommand WebRenderCommand;
   typedef mozilla::layers::WebRenderParentCommand WebRenderParentCommand;
   typedef mozilla::layers::WebRenderDisplayItemLayer WebRenderDisplayItemLayer;
   typedef mozilla::LayerState LayerState;
+  typedef mozilla::image::imgDrawingParams imgDrawingParams;
   typedef class mozilla::gfx::DrawTarget DrawTarget;
 
   // This is never instantiated directly (it has pure virtual methods), so no
   // need to count constructors and destructors.
   nsDisplayItem(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame);
   nsDisplayItem(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
                 const ActiveScrolledRoot* aActiveScrolledRoot);
   /**
--- a/layout/svg/SVGGeometryFrame.cpp
+++ b/layout/svg/SVGGeometryFrame.cpp
@@ -53,16 +53,18 @@ NS_QUERYFRAME_HEAD(SVGGeometryFrame)
   NS_QUERYFRAME_ENTRY(nsSVGDisplayableFrame)
   NS_QUERYFRAME_ENTRY(SVGGeometryFrame)
 NS_QUERYFRAME_TAIL_INHERITING(nsFrame)
 
 //----------------------------------------------------------------------
 // Display list item:
 
 class nsDisplaySVGGeometry : public nsDisplayItem {
+  typedef mozilla::image::imgDrawingParams imgDrawingParams;
+
 public:
   nsDisplaySVGGeometry(nsDisplayListBuilder* aBuilder,
                        SVGGeometryFrame* aFrame)
     : nsDisplayItem(aBuilder, aFrame)
   {
     MOZ_COUNT_CTOR(nsDisplaySVGGeometry);
     MOZ_ASSERT(aFrame, "Must have a frame!");
   }
@@ -117,26 +119,24 @@ nsDisplaySVGGeometry::Paint(nsDisplayLis
   // here.
   nsPoint offset = ToReferenceFrame() - mFrame->GetPosition();
 
   gfxPoint devPixelOffset =
     nsLayoutUtils::PointToGfxPoint(offset, appUnitsPerDevPixel);
 
   gfxMatrix tm = nsSVGUtils::GetCSSPxToDevPxMatrix(mFrame) *
                    gfxMatrix::Translation(devPixelOffset);
-
-  uint32_t flag = aBuilder->ShouldSyncDecodeImages()
-                  ? imgIContainer::FLAG_SYNC_DECODE
-                  : imgIContainer::FLAG_SYNC_DECODE_IF_FAST;
+  imgDrawingParams imgParams(aBuilder->ShouldSyncDecodeImages()
+                             ? imgIContainer::FLAG_SYNC_DECODE
+                             : imgIContainer::FLAG_SYNC_DECODE_IF_FAST);
 
-  DrawResult result =
-    static_cast<SVGGeometryFrame*>(mFrame)->PaintSVG(*aCtx->ThebesContext(),
-                                                     tm, nullptr, flag);
+  static_cast<SVGGeometryFrame*>(mFrame)->PaintSVG(*aCtx->ThebesContext(),
+                                                   tm, imgParams);
 
-  nsDisplayItemGenericImageGeometry::UpdateDrawResult(this, result);
+  nsDisplayItemGenericImageGeometry::UpdateDrawResult(this, imgParams.result);
 }
 
 void
 nsDisplaySVGGeometry::ComputeInvalidationRegion(
   nsDisplayListBuilder* aBuilder,
   const nsDisplayItemGeometry* aGeometry,
   nsRegion* aInvalidRegion)
 {
@@ -272,58 +272,55 @@ SVGGeometryFrame::BuildDisplayList(nsDis
   DisplayOutline(aBuilder, aLists);
   aLists.Content()->AppendNewToTop(
     new (aBuilder) nsDisplaySVGGeometry(aBuilder, this));
 }
 
 //----------------------------------------------------------------------
 // nsSVGDisplayableFrame methods
 
-DrawResult
+void
 SVGGeometryFrame::PaintSVG(gfxContext& aContext,
                            const gfxMatrix& aTransform,
-                           const nsIntRect* aDirtyRect,
-                           uint32_t aFlags)
+                           imgDrawingParams& aImgParams,
+                           const nsIntRect* aDirtyRect)
 {
   if (!StyleVisibility()->IsVisible())
-    return DrawResult::SUCCESS;
+    return;
 
   // Matrix to the geometry's user space:
   gfxMatrix newMatrix =
     aContext.CurrentMatrix().PreMultiply(aTransform).NudgeToIntegers();
   if (newMatrix.IsSingular()) {
-    return DrawResult::SUCCESS;
+    return;
   }
 
   uint32_t paintOrder = StyleSVG()->mPaintOrder;
-  DrawResult result = DrawResult::SUCCESS;
 
   if (paintOrder == NS_STYLE_PAINT_ORDER_NORMAL) {
-    result = Render(&aContext, eRenderFill | eRenderStroke, newMatrix, aFlags);
-    result &= PaintMarkers(aContext, aTransform, aFlags);
+    Render(&aContext, eRenderFill | eRenderStroke, newMatrix, aImgParams);
+    PaintMarkers(aContext, aTransform, aImgParams);
   } else {
     while (paintOrder) {
       uint32_t component =
         paintOrder & ((1 << NS_STYLE_PAINT_ORDER_BITWIDTH) - 1);
       switch (component) {
         case NS_STYLE_PAINT_ORDER_FILL:
-          result &= Render(&aContext, eRenderFill, newMatrix, aFlags);
+          Render(&aContext, eRenderFill, newMatrix, aImgParams);
           break;
         case NS_STYLE_PAINT_ORDER_STROKE:
-          result &= Render(&aContext, eRenderStroke, newMatrix, aFlags);
+          Render(&aContext, eRenderStroke, newMatrix, aImgParams);
           break;
         case NS_STYLE_PAINT_ORDER_MARKERS:
-          result &= PaintMarkers(aContext, aTransform, aFlags);
+          PaintMarkers(aContext, aTransform, aImgParams);
           break;
       }
       paintOrder >>= NS_STYLE_PAINT_ORDER_BITWIDTH;
     }
   }
-
-  return result;
 }
 
 nsIFrame*
 SVGGeometryFrame::GetFrameForPoint(const gfxPoint& aPoint)
 {
   FillRule fillRule;
   uint16_t hitTestFlags;
   if (GetStateBits() & NS_STATE_SVG_CLIPPATH_CHILD) {
@@ -747,21 +744,21 @@ nsSVGMarkerFrame *
 SVGGeometryFrame::MarkerProperties::GetMarkerEndFrame()
 {
   if (!mMarkerEnd)
     return nullptr;
   return static_cast<nsSVGMarkerFrame*>(
     mMarkerEnd->GetReferencedFrame(LayoutFrameType::SVGMarker, nullptr));
 }
 
-DrawResult
+void
 SVGGeometryFrame::Render(gfxContext* aContext,
                          uint32_t aRenderComponents,
                          const gfxMatrix& aNewTransform,
-                         uint32_t aFlags)
+                         imgDrawingParams& aImgParams)
 {
   MOZ_ASSERT(!aNewTransform.IsSingular());
 
   DrawTarget* drawTarget = aContext->GetDrawTarget();
 
   FillRule fillRule =
     nsSVGUtils::ToFillRule((GetStateBits() & NS_STATE_SVG_CLIPPATH_CHILD) ?
                              StyleSVG()->mClipRule : StyleSVG()->mFillRule);
@@ -784,37 +781,36 @@ SVGGeometryFrame::Render(gfxContext* aCo
     // We don't complicate this code with GetAsSimplePath since the cost of
     // masking will dwarf Path creation overhead anyway.
     RefPtr<Path> path = element->GetOrBuildPath(*drawTarget, fillRule);
     if (path) {
       ColorPattern white(ToDeviceColor(Color(1.0f, 1.0f, 1.0f, 1.0f)));
       drawTarget->Fill(path, white,
                        DrawOptions(1.0f, CompositionOp::OP_OVER, aaMode));
     }
-    return DrawResult::SUCCESS;
+    return;
   }
 
   SVGGeometryElement::SimplePath simplePath;
   RefPtr<Path> path;
 
   element->GetAsSimplePath(&simplePath);
   if (!simplePath.IsPath()) {
     path = element->GetOrBuildPath(*drawTarget, fillRule);
     if (!path) {
-      return DrawResult::SUCCESS;
+      return;
     }
   }
 
   SVGContextPaint* contextPaint = SVGContextPaint::GetContextPaint(mContent);
-  DrawResult result = DrawResult::SUCCESS;
 
   if (aRenderComponents & eRenderFill) {
     GeneralPattern fillPattern;
-    result = nsSVGUtils::MakeFillPatternFor(this, aContext, &fillPattern,
-                                            contextPaint, aFlags);
+    nsSVGUtils::MakeFillPatternFor(this, aContext, &fillPattern, aImgParams,
+                                   contextPaint);
 
     if (fillPattern.GetPattern()) {
       DrawOptions drawOptions(1.0f, CompositionOp::OP_OVER, aaMode);
       if (simplePath.IsRect()) {
         drawTarget->FillRect(simplePath.AsRect(), fillPattern, drawOptions);
       } else if (path) {
         drawTarget->Fill(path, fillPattern, drawOptions);
       }
@@ -826,67 +822,63 @@ SVGGeometryFrame::Render(gfxContext* aCo
     // Account for vector-effect:non-scaling-stroke:
     gfxMatrix userToOuterSVG;
     if (nsSVGUtils::GetNonScalingStrokeTransform(this, &userToOuterSVG)) {
       // A simple Rect can't be transformed with rotate/skew, so let's switch
       // to using a real path:
       if (!path) {
         path = element->GetOrBuildPath(*drawTarget, fillRule);
         if (!path) {
-          return DrawResult::SUCCESS;
+          return;
         }
         simplePath.Reset();
       }
       // We need to transform the path back into the appropriate ancestor
       // coordinate system, and paint it it that coordinate system, in order
       // for non-scaled stroke to paint correctly.
       gfxMatrix outerSVGToUser = userToOuterSVG;
       outerSVGToUser.Invert();
       aContext->Multiply(outerSVGToUser);
       RefPtr<PathBuilder> builder =
         path->TransformedCopyToBuilder(ToMatrix(userToOuterSVG), fillRule);
       path = builder->Finish();
     }
     GeneralPattern strokePattern;
-    result &=
-      nsSVGUtils::MakeStrokePatternFor(this, aContext, &strokePattern,
-                                       contextPaint, aFlags);
+    nsSVGUtils::MakeStrokePatternFor(this, aContext, &strokePattern,
+                                     aImgParams, contextPaint);
 
     if (strokePattern.GetPattern()) {
       SVGContentUtils::AutoStrokeOptions strokeOptions;
       SVGContentUtils::GetStrokeOptions(&strokeOptions,
                                         static_cast<nsSVGElement*>(mContent),
                                         StyleContext(), contextPaint);
       // GetStrokeOptions may set the line width to zero as an optimization
       if (strokeOptions.mLineWidth <= 0) {
-        return DrawResult::SUCCESS;
+        return;
       }
       DrawOptions drawOptions(1.0f, CompositionOp::OP_OVER, aaMode);
       if (simplePath.IsRect()) {
         drawTarget->StrokeRect(simplePath.AsRect(), strokePattern,
                                strokeOptions, drawOptions);
       } else if (simplePath.IsLine()) {
         drawTarget->StrokeLine(simplePath.Point1(), simplePath.Point2(),
                                strokePattern, strokeOptions, drawOptions);
       } else {
         drawTarget->Stroke(path, strokePattern, strokeOptions, drawOptions);
       }
     }
   }
-
-  return result;
 }
 
-DrawResult
+void
 SVGGeometryFrame::PaintMarkers(gfxContext& aContext,
                                const gfxMatrix& aTransform,
-                               uint32_t aFlags)
+                               imgDrawingParams& aImgParams)
 {
   SVGContextPaint* contextPaint = SVGContextPaint::GetContextPaint(mContent);
-  DrawResult result = DrawResult::SUCCESS;
   if (static_cast<SVGGeometryElement*>(mContent)->IsMarkable()) {
     MarkerProperties properties = GetMarkerProperties(this);
 
     if (properties.MarkersExist()) {
       float strokeWidth = nsSVGUtils::GetStrokeWidth(this, contextPaint);
 
       nsTArray<nsSVGMark> marks;
       static_cast<SVGGeometryElement*>
@@ -902,25 +894,23 @@ SVGGeometryFrame::PaintMarkers(gfxContex
         };
         static_assert(MOZ_ARRAY_LENGTH(markerFrames) == nsSVGMark::eTypeCount,
                       "Number of Marker frames should be equal to eTypeCount");
 
         for (uint32_t i = 0; i < num; i++) {
           nsSVGMark& mark = marks[i];
           nsSVGMarkerFrame* frame = markerFrames[mark.type];
           if (frame) {
-            result &= frame->PaintMark(aContext, aTransform, this, &mark,
-                                       strokeWidth, aFlags);
+            frame->PaintMark(aContext, aTransform, this, &mark, strokeWidth,
+                             aImgParams);
           }
         }
       }
     }
   }
-
-  return result;
 }
 
 uint16_t
 SVGGeometryFrame::GetHitTestFlags()
 {
   return nsSVGUtils::GetGeometryHitTestFlags(this);
 }
 } // namespace mozilla
--- a/layout/svg/SVGGeometryFrame.h
+++ b/layout/svg/SVGGeometryFrame.h
@@ -93,45 +93,45 @@ public:
   virtual void BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                                 const nsRect&           aDirtyRect,
                                 const nsDisplayListSet& aLists) override;
 
   // SVGGeometryFrame methods
   gfxMatrix GetCanvasTM();
 protected:
   // nsSVGDisplayableFrame interface:
-  virtual DrawResult PaintSVG(gfxContext& aContext,
-                              const gfxMatrix& aTransform,
-                              const nsIntRect* aDirtyRect = nullptr,
-                              uint32_t aFlags = 0) override;
+  virtual void PaintSVG(gfxContext& aContext,
+                        const gfxMatrix& aTransform,
+                        imgDrawingParams& aImgParams,
+                        const nsIntRect* aDirtyRect = nullptr) override;
   virtual nsIFrame* GetFrameForPoint(const gfxPoint& aPoint) override;
   virtual void ReflowSVG() override;
   virtual void NotifySVGChanged(uint32_t aFlags) override;
   virtual SVGBBox GetBBoxContribution(const Matrix &aToBBoxUserspace,
                                       uint32_t aFlags) override;
   virtual bool IsDisplayContainer() override { return false; }
 
   /**
    * This function returns a set of bit flags indicating which parts of the
    * element (fill, stroke, bounds) should intercept pointer events. It takes
    * into account the type of element and the value of the 'pointer-events'
    * property on the element.
    */
   virtual uint16_t GetHitTestFlags();
 private:
   enum { eRenderFill = 1, eRenderStroke = 2 };
-  DrawResult Render(gfxContext* aContext, uint32_t aRenderComponents,
-                    const gfxMatrix& aTransform, uint32_t aFlags);
+  void Render(gfxContext* aContext, uint32_t aRenderComponents,
+              const gfxMatrix& aTransform, imgDrawingParams& aImgParams);
 
   /**
    * @param aMatrix The transform that must be multiplied onto aContext to
    *   establish this frame's SVG user space.
    */
-  DrawResult PaintMarkers(gfxContext& aContext, const gfxMatrix& aMatrix,
-                          uint32_t aFlags);
+  void PaintMarkers(gfxContext& aContext, const gfxMatrix& aMatrix,
+                    imgDrawingParams& aImgParams);
 
   struct MarkerProperties {
     nsSVGMarkerProperty* mMarkerStart;
     nsSVGMarkerProperty* mMarkerMid;
     nsSVGMarkerProperty* mMarkerEnd;
 
     bool MarkersExist() const {
       return mMarkerStart || mMarkerMid || mMarkerEnd;
--- a/layout/svg/SVGTextFrame.cpp
+++ b/layout/svg/SVGTextFrame.cpp
@@ -2728,16 +2728,18 @@ public:
  * and decorations as they would normally.
  *
  * An instance of this class is passed to nsTextFrame::PaintText if painting
  * cannot be done directly (e.g. if we are using an SVG pattern fill, stroking
  * the text, etc.).
  */
 class SVGTextDrawPathCallbacks : public nsTextFrame::DrawPathCallbacks
 {
+  typedef mozilla::image::imgDrawingParams imgDrawingParams;
+
 public:
   /**
    * Constructs an SVGTextDrawPathCallbacks.
    *
    * @param aContext The context to use for painting.
    * @param aFrame The nsTextFrame to paint.
    * @param aCanvasTM The transformation matrix to set when painting; this
    *   should be the FOR_OUTERSVG_TM canvas TM of the text, so that
@@ -2778,17 +2780,18 @@ private:
    * or text decorations have been emitted to the gfxContext.
    */
   void HandleTextGeometry();
 
   /**
    * Sets the gfxContext paint to the appropriate color or pattern
    * for filling text geometry.
    */
-  void MakeFillPattern(GeneralPattern* aOutPattern);
+  void MakeFillPattern(GeneralPattern* aOutPattern,
+                       imgDrawingParams& aImgParams);
 
   /**
    * Fills and strokes a piece of text geometry, using group opacity
    * if the selection style requires it.
    */
   void FillAndStrokeGeometry();
 
   /**
@@ -2823,17 +2826,19 @@ SVGTextDrawPathCallbacks::NotifySelectio
   if (IsClipPathChild()) {
     // Don't paint selection backgrounds when in a clip path.
     return;
   }
 
   mColor = aColor; // currently needed by MakeFillPattern
 
   GeneralPattern fillPattern;
-  MakeFillPattern(&fillPattern);
+  // XXX cku Bug 1362417 we should pass imgDrawingParams from nsTextFrame.
+  imgDrawingParams imgParams;
+  MakeFillPattern(&fillPattern, imgParams);
   if (fillPattern.GetPattern()) {
     DrawOptions drawOptions(aColor == NS_40PERCENT_FOREGROUND_COLOR ? 0.4 : 1.0);
     aDrawTarget.FillRect(aBackgroundRect, fillPattern, drawOptions);
   }
 }
 
 void
 SVGTextDrawPathCallbacks::NotifyBeforeText(nscolor aColor)
@@ -2920,21 +2925,22 @@ SVGTextDrawPathCallbacks::HandleTextGeom
     gfxContextMatrixAutoSaveRestore saveMatrix(gfx);
     gfx->SetMatrix(mCanvasTM);
 
     FillAndStrokeGeometry();
   }
 }
 
 void
-SVGTextDrawPathCallbacks::MakeFillPattern(GeneralPattern* aOutPattern)
+SVGTextDrawPathCallbacks::MakeFillPattern(GeneralPattern* aOutPattern,
+                                          imgDrawingParams& aImgParams)
 {
   if (mColor == NS_SAME_AS_FOREGROUND_COLOR ||
       mColor == NS_40PERCENT_FOREGROUND_COLOR) {
-    Unused << nsSVGUtils::MakeFillPatternFor(mFrame, gfx, aOutPattern);
+    nsSVGUtils::MakeFillPatternFor(mFrame, gfx, aOutPattern, aImgParams);
     return;
   }
 
   if (mColor == NS_TRANSPARENT) {
     return;
   }
 
   aOutPattern->InitColorPattern(ToDeviceColor(mColor));
@@ -2973,17 +2979,19 @@ SVGTextDrawPathCallbacks::FillAndStrokeG
     gfx->PopGroupAndBlend();
   }
 }
 
 void
 SVGTextDrawPathCallbacks::FillGeometry()
 {
   GeneralPattern fillPattern;
-  MakeFillPattern(&fillPattern);
+  // XXX cku Bug 1362417 we should pass imgDrawingParams from nsTextFrame.
+  imgDrawingParams imgParams;
+  MakeFillPattern(&fillPattern, imgParams);
   if (fillPattern.GetPattern()) {
     RefPtr<Path> path = gfx->GetPath();
     FillRule fillRule = nsSVGUtils::ToFillRule(IsClipPathChild() ?
                           mFrame->StyleSVG()->mClipRule :
                           mFrame->StyleSVG()->mFillRule);
     if (fillRule != path->GetFillRule()) {
       RefPtr<PathBuilder> builder = path->CopyToBuilder(fillRule);
       path = builder->Finish();
@@ -2995,18 +3003,20 @@ SVGTextDrawPathCallbacks::FillGeometry()
 void
 SVGTextDrawPathCallbacks::StrokeGeometry()
 {
   // We don't paint the stroke when we are filling with a selection color.
   if (mColor == NS_SAME_AS_FOREGROUND_COLOR ||
       mColor == NS_40PERCENT_FOREGROUND_COLOR) {
     if (nsSVGUtils::HasStroke(mFrame, /*aContextPaint*/ nullptr)) {
       GeneralPattern strokePattern;
-      Unused << nsSVGUtils::MakeStrokePatternFor(mFrame, gfx, &strokePattern,
-                                                 /*aContextPaint*/ nullptr);
+      // XXX cku Bug 1362417 we should pass imgDrawingParams from nsTextFrame.
+      imgDrawingParams imgParams;
+      nsSVGUtils::MakeStrokePatternFor(mFrame, gfx, &strokePattern, imgParams,
+                                       /*aContextPaint*/ nullptr);
       if (strokePattern.GetPattern()) {
         if (!mFrame->GetParent()->GetContent()->IsSVGElement()) {
           // The cast that follows would be unsafe
           MOZ_ASSERT(false, "Our nsTextFrame's parent's content should be SVG");
           return;
         }
         nsSVGElement* svgOwner =
           static_cast<nsSVGElement*>(mFrame->GetParent()->GetContent());
@@ -3116,18 +3126,21 @@ nsDisplaySVGText::Paint(nsDisplayListBui
   gfxPoint devPixelOffset =
     nsLayoutUtils::PointToGfxPoint(offset, appUnitsPerDevPixel);
 
   gfxMatrix tm = nsSVGUtils::GetCSSPxToDevPxMatrix(mFrame) *
                    gfxMatrix::Translation(devPixelOffset);
 
   gfxContext* ctx = aCtx->ThebesContext();
   ctx->Save();
-  DrawResult result = static_cast<SVGTextFrame*>(mFrame)->PaintSVG(*ctx, tm);
-  nsDisplayItemGenericImageGeometry::UpdateDrawResult(this, result);
+  imgDrawingParams imgParams(aBuilder->ShouldSyncDecodeImages()
+                             ? imgIContainer::FLAG_SYNC_DECODE
+                             : imgIContainer::FLAG_SYNC_DECODE_IF_FAST);
+  static_cast<SVGTextFrame*>(mFrame)->PaintSVG(*ctx, tm, imgParams);
+  nsDisplayItemGenericImageGeometry::UpdateDrawResult(this, imgParams.result);
   ctx->Restore();
 }
 
 // ---------------------------------------------------------------------
 // nsQueryFrame methods
 
 NS_QUERYFRAME_HEAD(SVGTextFrame)
   NS_QUERYFRAME_ENTRY(SVGTextFrame)
@@ -3548,54 +3561,54 @@ ShouldPaintCaret(const TextRenderedRun& 
       uint32_t(caretOffset) < aThisRun.mTextFrameContentOffset +
                                 aThisRun.mTextFrameContentLength) {
     return true;
   }
 
   return false;
 }
 
-DrawResult
+void
 SVGTextFrame::PaintSVG(gfxContext& aContext,
                        const gfxMatrix& aTransform,
-                       const nsIntRect *aDirtyRect,
-                       uint32_t aFlags)
+                       imgDrawingParams& aImgParams,
+                       const nsIntRect *aDirtyRect)
 {
   DrawTarget& aDrawTarget = *aContext.GetDrawTarget();
-
   nsIFrame* kid = PrincipalChildList().FirstChild();
-  if (!kid)
-    return DrawResult::SUCCESS;
+  if (!kid) {
+    return;
+  }
 
   nsPresContext* presContext = PresContext();
 
   gfxMatrix initialMatrix = aContext.CurrentMatrix();
 
   if (mState & NS_FRAME_IS_NONDISPLAY) {
     // If we are in a canvas DrawWindow call that used the
     // DRAWWINDOW_DO_NOT_FLUSH flag, then we may still have out
     // of date frames.  Just don't paint anything if they are
     // dirty.
     if (presContext->PresShell()->InDrawWindowNotFlushing() &&
         NS_SUBTREE_DIRTY(this)) {
-      return DrawResult::SUCCESS;
+      return;
     }
     // Text frames inside <clipPath>, <mask>, etc. will never have had
     // ReflowSVG called on them, so call UpdateGlyphPositioning to do this now.
     UpdateGlyphPositioning();
   } else if (NS_SUBTREE_DIRTY(this)) {
     // If we are asked to paint before reflow has recomputed mPositions etc.
     // directly via PaintSVG, rather than via a display list, then we need
     // to bail out here too.
-    return DrawResult::SUCCESS;
+    return;
   }
 
   if (aTransform.IsSingular()) {
     NS_WARNING("Can't render text element!");
-    return DrawResult::SUCCESS;
+    return;
   }
 
   gfxMatrix matrixForPaintServers = aTransform * initialMatrix;
 
   // Check if we need to draw anything.
   if (aDirtyRect) {
     NS_ASSERTION(!NS_SVGDisplayListPaintingEnabled() ||
                  (mState & NS_FRAME_IS_NONDISPLAY),
@@ -3607,17 +3620,17 @@ SVGTextFrame::PaintSVG(gfxContext& aCont
     gfxRect frameRect(mRect.x / appUnitsPerDevPixel,
                       mRect.y / appUnitsPerDevPixel,
                       mRect.width / appUnitsPerDevPixel,
                       mRect.height / appUnitsPerDevPixel);
 
     nsRect canvasRect = nsLayoutUtils::RoundGfxRectToAppRect(
         GetCanvasTM().TransformBounds(frameRect), 1);
     if (!canvasRect.Intersects(dirtyRect)) {
-      return DrawResult::SUCCESS;
+      return;
     }
   }
 
   // SVG frames' PaintSVG methods paint in CSS px, but normally frames paint in
   // dev pixels. Here we multiply a CSS-px-to-dev-pixel factor onto aTransform
   // so our non-SVG nsTextFrame children paint correctly.
   auto auPerDevPx = presContext->AppUnitsPerDevPixel();
   float cssPxPerDevPx = presContext->AppUnitsToFloatCSSPixels(auPerDevPx);
@@ -3636,17 +3649,16 @@ SVGTextFrame::PaintSVG(gfxContext& aCont
 
   TextRenderedRunIterator it(this, TextRenderedRunIterator::eVisibleFrames);
   TextRenderedRun run = it.Current();
 
   SVGContextPaint* outerContextPaint =
     SVGContextPaint::GetContextPaint(mContent);
 
   nsRenderingContext rendCtx(&aContext);
-  DrawResult finalResult = DrawResult::SUCCESS;
   while (run.mFrame) {
     nsTextFrame* frame = run.mFrame;
 
     // Determine how much of the left and right edges of the text frame we
     // need to ignore.
     SVGCharClipDisplayItem item(run);
 
     // Set up the fill and stroke so that SVG glyphs can get painted correctly
@@ -3654,17 +3666,17 @@ SVGTextFrame::PaintSVG(gfxContext& aCont
     aContext.SetMatrix(initialMatrix);
 
     RefPtr<SVGContextPaintImpl> contextPaint = new SVGContextPaintImpl();
     DrawMode drawMode;
     DrawResult result = DrawResult::SUCCESS;
     Tie(result, drawMode) = contextPaint->Init(&aDrawTarget,
                                                aContext.CurrentMatrix(),
                                                frame, outerContextPaint);
-    finalResult &= result;
+    aImgParams.result &= result;
     if (drawMode & DrawMode::GLYPH_STROKE) {
       // This may change the gfxContext's transform (for non-scaling stroke),
       // in which case this needs to happen before we call SetMatrix() below.
       nsSVGUtils::SetupCairoStrokeGeometry(frame, &aContext, outerContextPaint);
     }
 
     // Set up the transform for painting the text frame for the substring
     // indicated by the run.
@@ -3695,18 +3707,16 @@ SVGTextFrame::PaintSVG(gfxContext& aCont
       // XXX Should we be looking at the fill/stroke colours to paint the
       // caret with, rather than using the color property?
       caret->PaintCaret(aDrawTarget, frame, nsPoint());
       aContext.NewPath();
     }
 
     run = it.Next();
   }
-
-  return finalResult;
 }
 
 nsIFrame*
 SVGTextFrame::GetFrameForPoint(const gfxPoint& aPoint)
 {
   NS_ASSERTION(PrincipalChildList().FirstChild(), "must have a child frame");
 
   if (mState & NS_FRAME_IS_NONDISPLAY) {
--- a/layout/svg/SVGTextFrame.h
+++ b/layout/svg/SVGTextFrame.h
@@ -242,20 +242,20 @@ public:
    */
   virtual void FindCloserFrameForSelection(nsPoint aPoint,
                                           FrameWithDistance* aCurrentBestFrame) override;
 
 
 
   // nsSVGDisplayableFrame interface:
   virtual void NotifySVGChanged(uint32_t aFlags) override;
-  virtual DrawResult PaintSVG(gfxContext& aContext,
-                              const gfxMatrix& aTransform,
-                              const nsIntRect* aDirtyRect = nullptr,
-                              uint32_t aFlags = 0) override;
+  virtual void PaintSVG(gfxContext& aContext,
+                        const gfxMatrix& aTransform,
+                        imgDrawingParams& aImgParams,
+                        const nsIntRect* aDirtyRect = nullptr) override;
   virtual nsIFrame* GetFrameForPoint(const gfxPoint& aPoint) override;
   virtual void ReflowSVG() override;
   virtual SVGBBox GetBBoxContribution(const Matrix& aToBBoxUserspace,
                                       uint32_t aFlags) override;
 
   // nsSVGContainerFrame methods:
   virtual gfxMatrix GetCanvasTM() override;
   
--- a/layout/svg/nsFilterInstance.cpp
+++ b/layout/svg/nsFilterInstance.cpp
@@ -54,36 +54,35 @@ UserSpaceMetricsForFrame(nsIFrame* aFram
 {
   if (aFrame->GetContent()->IsSVGElement()) {
     nsSVGElement* element = static_cast<nsSVGElement*>(aFrame->GetContent());
     return MakeUnique<SVGElementMetrics>(element);
   }
   return MakeUnique<NonSVGFrameUserSpaceMetrics>(aFrame);
 }
 
-DrawResult
+void
 nsFilterInstance::PaintFilteredFrame(nsIFrame *aFilteredFrame,
                                      DrawTarget* aDrawTarget,
                                      const gfxMatrix& aTransform,
                                      nsSVGFilterPaintCallback *aPaintCallback,
-                                     const nsRegion *aDirtyArea)
+                                     const nsRegion *aDirtyArea,
+                                     imgDrawingParams& aImgParams)
 {
   auto& filterChain = aFilteredFrame->StyleEffects()->mFilters;
   UniquePtr<UserSpaceMetrics> metrics = UserSpaceMetricsForFrame(aFilteredFrame);
   // Hardcode InputIsTainted to true because we don't want JS to be able to
   // read the rendered contents of aFilteredFrame.
   nsFilterInstance instance(aFilteredFrame, aFilteredFrame->GetContent(),
                             *metrics, filterChain, /* InputIsTainted */ true,
                             aPaintCallback, aTransform, aDirtyArea, nullptr,
                             nullptr, nullptr);
-  if (!instance.IsInitialized()) {
-    return DrawResult::BAD_IMAGE;
+  if (instance.IsInitialized()) {
+    instance.Render(aDrawTarget, aImgParams);
   }
-
-  return instance.Render(aDrawTarget);
 }
 
 nsRegion
 nsFilterInstance::GetPostFilterDirtyArea(nsIFrame *aFilteredFrame,
                                          const nsRegion& aPreFilterDirtyRegion)
 {
   if (aPreFilterDirtyRegion.IsEmpty()) {
     return nsRegion();
@@ -368,99 +367,89 @@ nsFilterInstance::ComputeNeededBoxes()
 
   sourceGraphicNeededRegion.And(sourceGraphicNeededRegion, mTargetBounds);
 
   UpdateNeededBounds(sourceGraphicNeededRegion, mSourceGraphic.mNeededBounds);
   UpdateNeededBounds(fillPaintNeededRegion, mFillPaint.mNeededBounds);
   UpdateNeededBounds(strokePaintNeededRegion, mStrokePaint.mNeededBounds);
 }
 
-DrawResult
-nsFilterInstance::BuildSourcePaint(SourceInfo *aSource)
+void
+nsFilterInstance::BuildSourcePaint(SourceInfo *aSource,
+                                   imgDrawingParams& aImgParams)
 {
   MOZ_ASSERT(mTargetFrame);
   nsIntRect neededRect = aSource->mNeededBounds;
   if (neededRect.IsEmpty()) {
-    return DrawResult::SUCCESS;
+    return;
   }
 
   RefPtr<DrawTarget> offscreenDT =
     gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget(
       neededRect.Size(), SurfaceFormat::B8G8R8A8);
   if (!offscreenDT || !offscreenDT->IsValid()) {
-    return DrawResult::TEMPORARY_ERROR;
+    return;
   }
 
   RefPtr<gfxContext> ctx = gfxContext::CreateOrNull(offscreenDT);
   MOZ_ASSERT(ctx); // already checked the draw target above
   gfxContextAutoSaveRestore saver(ctx);
 
   ctx->SetMatrix(mPaintTransform *
                  gfxMatrix::Translation(-neededRect.TopLeft()));
   GeneralPattern pattern;
-  DrawResult result = DrawResult::SUCCESS;
   if (aSource == &mFillPaint) {
-    result = nsSVGUtils::MakeFillPatternFor(mTargetFrame, ctx, &pattern);
+    nsSVGUtils::MakeFillPatternFor(mTargetFrame, ctx, &pattern, aImgParams);
   } else if (aSource == &mStrokePaint) {
-    result = nsSVGUtils::MakeStrokePatternFor(mTargetFrame, ctx, &pattern);
+    nsSVGUtils::MakeStrokePatternFor(mTargetFrame, ctx, &pattern, aImgParams);
   }
 
   if (pattern.GetPattern()) {
     offscreenDT->FillRect(ToRect(FilterSpaceToUserSpace(ThebesRect(neededRect))),
                           pattern);
   }
 
   aSource->mSourceSurface = offscreenDT->Snapshot();
   aSource->mSurfaceRect = neededRect;
-
-  return result;
 }
 
-DrawResult
-nsFilterInstance::BuildSourcePaints()
+void
+nsFilterInstance::BuildSourcePaints(imgDrawingParams& aImgParams)
 {
   if (!mFillPaint.mNeededBounds.IsEmpty()) {
-    DrawResult result = BuildSourcePaint(&mFillPaint);
-    if (result != DrawResult::SUCCESS) {
-      return result;
-    }
+    BuildSourcePaint(&mFillPaint, aImgParams);
   }
 
   if (!mStrokePaint.mNeededBounds.IsEmpty()) {
-    DrawResult result = BuildSourcePaint(&mStrokePaint);
-    if (result != DrawResult::SUCCESS) {
-      return result;
-    }
+    BuildSourcePaint(&mStrokePaint, aImgParams);
   }
-
-  return  DrawResult::SUCCESS;
 }
 
-DrawResult
-nsFilterInstance::BuildSourceImage()
+void
+nsFilterInstance::BuildSourceImage(imgDrawingParams& aImgParams)
 {
   MOZ_ASSERT(mTargetFrame);
 
   nsIntRect neededRect = mSourceGraphic.mNeededBounds;
   if (neededRect.IsEmpty()) {
-    return DrawResult::SUCCESS;
+    return;
   }
 
   RefPtr<DrawTarget> offscreenDT =
     gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget(
       neededRect.Size(), SurfaceFormat::B8G8R8A8);
   if (!offscreenDT || !offscreenDT->IsValid()) {
-    return DrawResult::TEMPORARY_ERROR;
+    return;
   }
 
   gfxRect r = FilterSpaceToUserSpace(ThebesRect(neededRect));
   r.RoundOut();
   nsIntRect dirty;
   if (!gfxUtils::GfxRectToIntRect(r, &dirty)){
-    return DrawResult::SUCCESS;
+    return;
   }
 
   // SVG graphics paint to device space, so we need to set an initial device
   // space to filter space transform on the gfxContext that SourceGraphic
   // and SourceAlpha will paint to.
   //
   // (In theory it would be better to minimize error by having filtered SVG
   // graphics temporarily paint to user space when painting the sources and
@@ -472,65 +461,54 @@ nsFilterInstance::BuildSourceImage()
   RefPtr<gfxContext> ctx = gfxContext::CreateOrNull(offscreenDT);
   MOZ_ASSERT(ctx); // already checked the draw target above
   gfxMatrix devPxToCssPxTM = nsSVGUtils::GetCSSPxToDevPxMatrix(mTargetFrame);
   DebugOnly<bool> invertible = devPxToCssPxTM.Invert();
   MOZ_ASSERT(invertible);
   ctx->SetMatrix(devPxToCssPxTM * mPaintTransform *
                  gfxMatrix::Translation(-neededRect.TopLeft()));
 
-  DrawResult result =
-    mPaintCallback->Paint(*ctx, mTargetFrame, mPaintTransform, &dirty);
+  mPaintCallback->Paint(*ctx, mTargetFrame, mPaintTransform, &dirty, aImgParams);
 
   mSourceGraphic.mSourceSurface = offscreenDT->Snapshot();
   mSourceGraphic.mSurfaceRect = neededRect;
-
-  return result;
 }
 
-DrawResult
-nsFilterInstance::Render(DrawTarget* aDrawTarget)
+void
+nsFilterInstance::Render(DrawTarget* aDrawTarget, imgDrawingParams& aImgParams)
 {
   MOZ_ASSERT(mTargetFrame, "Need a frame for rendering");
 
   if (mPrimitiveDescriptions.IsEmpty()) {
     // An filter without any primitive. Treat it as success and paint nothing.
-    return DrawResult::SUCCESS;
+    return;
   }
 
   nsIntRect filterRect =
     mPostFilterDirtyRegion.GetBounds().Intersect(OutputFilterSpaceBounds());
   if (filterRect.IsEmpty() || mPaintTransform.IsSingular()) {
-    return DrawResult::SUCCESS;
+    return;
   }
 
   AutoRestoreTransform autoRestoreTransform(aDrawTarget);
   Matrix newTM =
     aDrawTarget->GetTransform().PreTranslate(filterRect.x, filterRect.y);
   aDrawTarget->SetTransform(newTM);
 
   ComputeNeededBoxes();
 
-  DrawResult result = BuildSourceImage();
-  if (result != DrawResult::SUCCESS){
-    return result;
-  }
-  result = BuildSourcePaints();
-  if (result != DrawResult::SUCCESS){
-    return result;
-  }
+  BuildSourceImage(aImgParams);
+  BuildSourcePaints(aImgParams);
 
   FilterSupport::RenderFilterDescription(
     aDrawTarget, mFilterDescription, IntRectToRect(filterRect),
     mSourceGraphic.mSourceSurface, mSourceGraphic.mSurfaceRect,
     mFillPaint.mSourceSurface, mFillPaint.mSurfaceRect,
     mStrokePaint.mSourceSurface, mStrokePaint.mSurfaceRect,
     mInputImages, Point(0, 0));
-
-  return DrawResult::SUCCESS;
 }
 
 nsRegion
 nsFilterInstance::ComputePostFilterDirtyRegion()
 {
   if (mPreFilterDirtyRegion.IsEmpty() || mPrimitiveDescriptions.IsEmpty()) {
     return nsRegion();
   }
--- a/layout/svg/nsFilterInstance.h
+++ b/layout/svg/nsFilterInstance.h
@@ -51,16 +51,17 @@ class nsFilterInstance
 {
   typedef mozilla::gfx::IntRect IntRect;
   typedef mozilla::gfx::SourceSurface SourceSurface;
   typedef mozilla::gfx::DrawTarget DrawTarget;
   typedef mozilla::gfx::FilterPrimitiveDescription FilterPrimitiveDescription;
   typedef mozilla::gfx::FilterDescription FilterDescription;
   typedef mozilla::dom::UserSpaceMetrics UserSpaceMetrics;
   typedef mozilla::image::DrawResult DrawResult;
+  typedef mozilla::image::imgDrawingParams imgDrawingParams;
 public:
   /**
    * Create a FilterDescription for the supplied filter. All coordinates in
    * the description are in filter space.
    * @param aFilterInputIsTainted Describes whether the SourceImage / SourceAlpha
    *   input is tainted. This affects whether feDisplacementMap will respect
    *   the filter input as its map input, and it affects the IsTainted() state
    *   on the filter primitives in the FilterDescription. "Tainted" is a term
@@ -78,21 +79,22 @@ public:
                                                 nsTArray<RefPtr<SourceSurface>>& aOutAdditionalImages);
 
   /**
    * Paint the given filtered frame.
    * @param aDirtyArea The area than needs to be painted, in aFilteredFrame's
    *   frame space (i.e. relative to its origin, the top-left corner of its
    *   border box).
    */
-  static DrawResult PaintFilteredFrame(nsIFrame *aFilteredFrame,
-                                       DrawTarget* aDrawTarget,
-                                       const gfxMatrix& aTransform,
-                                       nsSVGFilterPaintCallback *aPaintCallback,
-                                       const nsRegion* aDirtyArea);
+  static void PaintFilteredFrame(nsIFrame *aFilteredFrame,
+                                 DrawTarget* aDrawTarget,
+                                 const gfxMatrix& aTransform,
+                                 nsSVGFilterPaintCallback *aPaintCallback,
+                                 const nsRegion* aDirtyArea,
+                                 imgDrawingParams& aImgParams);
 
   /**
    * Returns the post-filter area that could be dirtied when the given
    * pre-filter area of aFilteredFrame changes.
    * @param aPreFilterDirtyRegion The pre-filter area of aFilteredFrame that has
    *   changed, relative to aFilteredFrame, in app units.
    */
   static nsRegion GetPostFilterDirtyArea(nsIFrame *aFilteredFrame,
@@ -162,17 +164,17 @@ private:
   bool IsInitialized() const { return mInitialized; }
 
   /**
    * Draws the filter output into aDrawTarget. The area that
    * needs to be painted must have been specified before calling this method
    * by passing it as the aPostFilterDirtyRegion argument to the
    * nsFilterInstance constructor.
    */
-  DrawResult Render(DrawTarget* aDrawTarget);
+  void Render(DrawTarget* aDrawTarget, imgDrawingParams& aImgParams);
 
   const FilterDescription& ExtractDescriptionAndAdditionalImages(nsTArray<RefPtr<SourceSurface>>& aOutAdditionalImages)
   {
     mInputImages.SwapElements(aOutAdditionalImages);
     return mFilterDescription;
   }
 
   /**
@@ -215,30 +217,30 @@ private:
     // Set by BuildSourceImage / BuildSourcePaint.
     IntRect mSurfaceRect;
   };
 
   /**
    * Creates a SourceSurface for either the FillPaint or StrokePaint graph
    * nodes
    */
-  DrawResult BuildSourcePaint(SourceInfo *aPrimitive);
+  void BuildSourcePaint(SourceInfo *aPrimitive, imgDrawingParams& aImgParams);
 
   /**
    * Creates a SourceSurface for either the FillPaint and StrokePaint graph
    * nodes, fills its contents and assigns it to mFillPaint.mSourceSurface and
    * mStrokePaint.mSourceSurface respectively.
    */
-  DrawResult BuildSourcePaints();
+  void BuildSourcePaints(imgDrawingParams& aImgParams);
 
   /**
    * Creates the SourceSurface for the SourceGraphic graph node, paints its
    * contents, and assigns it to mSourceGraphic.mSourceSurface.
    */
-  DrawResult BuildSourceImage();
+  void BuildSourceImage(imgDrawingParams& aImgParams);
 
   /**
    * Build the list of FilterPrimitiveDescriptions that describes the filter's
    * filter primitives and their connections. This populates
    * mPrimitiveDescriptions and mInputImages. aFilterInputIsTainted describes
    * whether the SourceGraphic is tainted.
    */
   nsresult BuildPrimitives(const nsTArray<nsStyleFilter>& aFilterChain,
--- a/layout/svg/nsSVGClipPathFrame.cpp
+++ b/layout/svg/nsSVGClipPathFrame.cpp
@@ -167,17 +167,17 @@ nsSVGClipPathFrame::PaintClipMask(gfxCon
                                        maskSurface, maskTransform);
     // The corresponding PopGroupAndBlend call below will mask the
     // blend using |maskSurface|.
   }
 
   // Paint our children into the mask:
   for (nsIFrame* kid = mFrames.FirstChild(); kid;
        kid = kid->GetNextSibling()) {
-    result &= PaintFrameIntoMask(kid, aClippedFrame, aMaskContext, aMatrix);
+    PaintFrameIntoMask(kid, aClippedFrame, aMaskContext, aMatrix);
   }
 
   if (maskUsage.shouldGenerateClipMaskLayer) {
     aMaskContext.PopGroupAndBlend();
   } else if (maskUsage.shouldApplyClipPath) {
     aMaskContext.PopClip();
   }
 
@@ -188,35 +188,35 @@ nsSVGClipPathFrame::PaintClipMask(gfxCon
   if (aExtraMask) {
     ComposeExtraMask(maskDT, maskTransfrom, aExtraMask, aExtraMasksTransform);
   }
 
   *aMaskTransform = ToMatrix(maskTransfrom);
   return result;
 }
 
-DrawResult
+void
 nsSVGClipPathFrame::PaintFrameIntoMask(nsIFrame *aFrame,
                                        nsIFrame* aClippedFrame,
                                        gfxContext& aTarget,
                                        const gfxMatrix& aMatrix)
 {
   nsSVGDisplayableFrame* frame = do_QueryFrame(aFrame);
   if (!frame) {
-    return DrawResult::SUCCESS;
+    return;
   }
 
   // The CTM of each frame referencing us can be different.
   frame->NotifySVGChanged(nsSVGDisplayableFrame::TRANSFORM_CHANGED);
 
   // Children of this clipPath may themselves be clipped.
   nsSVGEffects::EffectProperties effectProperties =
     nsSVGEffects::GetEffectProperties(aFrame);
   if (effectProperties.HasInvalidClipPath()) {
-    return DrawResult::SUCCESS;
+    return;
   }
   nsSVGClipPathFrame *clipPathThatClipsChild =
     effectProperties.GetClipPathFrame();
 
   nsSVGUtils::MaskUsage maskUsage;
   nsSVGUtils::DetermineMaskUsage(aFrame, true, maskUsage);
   DrawResult result = DrawResult::SUCCESS;
   if (maskUsage.shouldApplyClipPath) {
@@ -237,28 +237,30 @@ nsSVGClipPathFrame::PaintFrameIntoMask(n
   nsIFrame* child = do_QueryFrame(frame);
   nsIContent* childContent = child->GetContent();
   if (childContent->IsSVGElement()) {
     toChildsUserSpace =
       static_cast<const nsSVGElement*>(childContent)->
         PrependLocalTransformsTo(mMatrixForChildren, eUserSpaceToParent);
   }
 
+  // clipPath does not result in any image rendering, so we just use a dummy
+  // imgDrawingParams instead of requiring our caller to pass one.
+  image::imgDrawingParams imgParams;
+
   // Our children have NS_STATE_SVG_CLIPPATH_CHILD set on them, and
   // SVGGeometryFrame::Render checks for that state bit and paints
   // only the geometry (opaque black) if set.
-  result &= frame->PaintSVG(aTarget, toChildsUserSpace);
+  frame->PaintSVG(aTarget, toChildsUserSpace, imgParams);
 
   if (maskUsage.shouldGenerateClipMaskLayer) {
     aTarget.PopGroupAndBlend();
   } else if (maskUsage.shouldApplyClipPath) {
     aTarget.PopClip();
   }
-
-  return result;
 }
 
 mozilla::Pair<DrawResult, RefPtr<SourceSurface>>
 nsSVGClipPathFrame::GetClipMask(gfxContext& aReferenceContext,
                                 nsIFrame* aClippedFrame,
                                 const gfxMatrix& aMatrix,
                                 Matrix* aMaskTransform,
                                 SourceSurface* aExtraMask,
--- a/layout/svg/nsSVGClipPathFrame.h
+++ b/layout/svg/nsSVGClipPathFrame.h
@@ -145,18 +145,18 @@ public:
 private:
 
   // nsSVGContainerFrame methods:
   virtual gfxMatrix GetCanvasTM() override;
 
   already_AddRefed<DrawTarget> CreateClipMask(gfxContext& aReferenceContext,
                                               mozilla::gfx::IntPoint& aOffset);
 
-  DrawResult PaintFrameIntoMask(nsIFrame *aFrame, nsIFrame* aClippedFrame,
-                                gfxContext& aTarget, const gfxMatrix& aMatrix);
+  void PaintFrameIntoMask(nsIFrame *aFrame, nsIFrame* aClippedFrame,
+                          gfxContext& aTarget, const gfxMatrix& aMatrix);
 
   // Set, during a GetClipMask() call, to the transform that still needs to be
   // concatenated to the transform of the DrawTarget that was passed to
   // GetClipMask in order to establish the coordinate space that the clipPath
   // establishes for its contents (i.e. including applying 'clipPathUnits' and
   // any 'transform' attribute set on the clipPath) specifically for clipping
   // the frame that was passed to GetClipMask at that moment in time.  This is
   // set so that if our GetCanvasTM method is called while GetClipMask is
--- a/layout/svg/nsSVGContainerFrame.cpp
+++ b/layout/svg/nsSVGContainerFrame.cpp
@@ -247,66 +247,59 @@ nsSVGDisplayContainerFrame::IsSVGTransfo
     }
   }
   return foundTransform;
 }
 
 //----------------------------------------------------------------------
 // nsSVGDisplayableFrame methods
 
-DrawResult
+void
 nsSVGDisplayContainerFrame::PaintSVG(gfxContext& aContext,
                                      const gfxMatrix& aTransform,
-                                     const nsIntRect *aDirtyRect,
-                                     uint32_t aFlags)
+                                     imgDrawingParams& aImgParams,
+                                     const nsIntRect *aDirtyRect)
 {
   NS_ASSERTION(!NS_SVGDisplayListPaintingEnabled() ||
                (mState & NS_FRAME_IS_NONDISPLAY) ||
                PresContext()->IsGlyph(),
                "If display lists are enabled, only painting of non-display "
                "SVG should take this code path");
 
   if (StyleEffects()->mOpacity == 0.0) {
-    return DrawResult::SUCCESS;
+    return;
   }
 
   gfxMatrix matrix = aTransform;
   if (GetContent()->IsSVGElement()) { // must check before cast
     matrix = static_cast<const nsSVGElement*>(GetContent())->
                PrependLocalTransformsTo(matrix, eChildToUserSpace);
     if (matrix.IsSingular()) {
-      return DrawResult::SUCCESS;
+      return;
     }
   }
 
-  DrawResult result = DrawResult::SUCCESS;
   for (nsIFrame* kid = mFrames.FirstChild(); kid;
        kid = kid->GetNextSibling()) {
     gfxMatrix m = matrix;
     // PaintFrameWithEffects() expects the transform that is passed to it to
     // include the transform to the passed frame's user space, so add it:
     const nsIContent* content = kid->GetContent();
     if (content->IsSVGElement()) { // must check before cast
       const nsSVGElement* element = static_cast<const nsSVGElement*>(content);
       if (!element->HasValidDimensions()) {
         continue; // nothing to paint for kid
       }
       m = element->PrependLocalTransformsTo(m, eUserSpaceToParent);
       if (m.IsSingular()) {
         continue;
       }
     }
-    result = nsSVGUtils::PaintFrameWithEffects(kid, aContext, m, aDirtyRect,
-                                               aFlags);
-    if (result != DrawResult::SUCCESS) {
-      return result;
-    }
+    nsSVGUtils::PaintFrameWithEffects(kid, aContext, m, aImgParams, aDirtyRect);
   }
-
-  return result;
 }
 
 nsIFrame*
 nsSVGDisplayContainerFrame::GetFrameForPoint(const gfxPoint& aPoint)
 {
   NS_ASSERTION(!NS_SVGDisplayListHitTestingEnabled() ||
                (mState & NS_FRAME_IS_NONDISPLAY),
                "If display lists are enabled, only hit-testing of a "
--- a/layout/svg/nsSVGContainerFrame.h
+++ b/layout/svg/nsSVGContainerFrame.h
@@ -136,20 +136,20 @@ public:
   virtual void BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                                 const nsRect&           aDirtyRect,
                                 const nsDisplayListSet& aLists) override;
 
   virtual bool IsSVGTransformed(Matrix *aOwnTransform = nullptr,
                                 Matrix *aFromParentTransform = nullptr) const override;
 
   // nsSVGDisplayableFrame interface:
-  virtual DrawResult PaintSVG(gfxContext& aContext,
-                              const gfxMatrix& aTransform,
-                              const nsIntRect *aDirtyRect = nullptr,
-                              uint32_t aFlags = 0) override;
+  virtual void PaintSVG(gfxContext& aContext,
+                        const gfxMatrix& aTransform,
+                        imgDrawingParams& aImgParams,
+                        const nsIntRect* aDirtyRect = nullptr) override;
   virtual nsIFrame* GetFrameForPoint(const gfxPoint& aPoint) override;
   virtual void ReflowSVG() override;
   virtual void NotifySVGChanged(uint32_t aFlags) override;
   virtual SVGBBox GetBBoxContribution(const Matrix &aToBBoxUserspace,
                                       uint32_t aFlags) override;
   virtual bool IsDisplayContainer() override { return true; }
 };
 
--- a/layout/svg/nsSVGDisplayableFrame.h
+++ b/layout/svg/nsSVGDisplayableFrame.h
@@ -47,16 +47,17 @@ class nsSVGDisplayableFrame : public nsQ
 {
 public:
   typedef mozilla::SVGAnimatedNumberList SVGAnimatedNumberList;
   typedef mozilla::SVGNumberList SVGNumberList;
   typedef mozilla::SVGAnimatedLengthList SVGAnimatedLengthList;
   typedef mozilla::SVGLengthList SVGLengthList;
   typedef mozilla::SVGUserUnitList SVGUserUnitList;
   typedef mozilla::image::DrawResult DrawResult;
+  typedef mozilla::image::imgDrawingParams imgDrawingParams;
 
   NS_DECL_QUERYFRAME_TARGET(nsSVGDisplayableFrame)
 
   /**
    * Paint this frame.
    *
    * SVG is painted using a combination of display lists (trees of
    * nsDisplayItem built by BuildDisplayList() implementations) and recursive
@@ -74,25 +75,26 @@ public:
    * @param aTransform The transform that has to be multiplied onto the
    *   DrawTarget in order for drawing to be in this frame's SVG user space.
    *   Implementations of this method should avoid multiplying aTransform onto
    *   the DrawTarget when possible and instead just pass a transform down to
    *   their children.  This is preferable because changing the transform is
    *   very expensive for certain DrawTarget backends so it is best to minimize
    *   the number of transform changes.
    *
+   * @param aImgParams imagelib parameters that may be used when painting
+   *   feImage.
+   *
    * @param aDirtyRect The area being redrawn, in frame offset pixel
    *   coordinates.
-   *
-   * @param aFlags Image flags of the imgIContainer::FLAG_* variety.
    */
-  virtual DrawResult PaintSVG(gfxContext& aContext,
-                              const gfxMatrix& aTransform,
-                              const nsIntRect* aDirtyRect = nullptr,
-                              uint32_t aFlags = 0) = 0;
+  virtual void PaintSVG(gfxContext& aContext,
+                        const gfxMatrix& aTransform,
+                        imgDrawingParams& aImgParams,
+                        const nsIntRect* aDirtyRect = nullptr) = 0;
 
   /**
    * Returns the frame that should handle pointer events at aPoint.  aPoint is
    * expected to be in the SVG user space of the frame on which this method is
    * called.  The frame returned may be the frame on which this method is
    * called, any of its descendants or else nullptr.
    */
   virtual nsIFrame* GetFrameForPoint(const gfxPoint& aPoint) = 0;
--- a/layout/svg/nsSVGFilterPaintCallback.h
+++ b/layout/svg/nsSVGFilterPaintCallback.h
@@ -8,28 +8,28 @@
 
 #include "nsRect.h"
 
 class nsIFrame;
 class gfxContext;
 
 class nsSVGFilterPaintCallback {
 public:
-  typedef mozilla::image::DrawResult DrawResult;
+  typedef mozilla::image::imgDrawingParams imgDrawingParams;
 
   /**
    * Paint the frame contents.
    * SVG frames will have had matrix propagation set to false already.
    * Non-SVG frames have to do their own thing.
    * The caller will do a Save()/Restore() as necessary so feel free
    * to mess with context state.
    * The context will be configured to use the "user space" coordinate
    * system.
    * @param aDirtyRect the dirty rect *in user space pixels*
    * @param aTransformRoot the outermost frame whose transform should be taken
    *                       into account when painting an SVG glyph
    */
-  virtual DrawResult Paint(gfxContext& aContext, nsIFrame *aTarget,
-                           const gfxMatrix& aTransform,
-                           const nsIntRect *aDirtyRect) = 0;
+  virtual void Paint(gfxContext& aContext, nsIFrame *aTarget,
+                    const gfxMatrix& aTransform, const nsIntRect *aDirtyRect,
+                    imgDrawingParams& aImgParams) = 0;
 };
 
 #endif
--- a/layout/svg/nsSVGForeignObjectFrame.cpp
+++ b/layout/svg/nsSVGForeignObjectFrame.cpp
@@ -191,37 +191,39 @@ nsSVGForeignObjectFrame::IsSVGTransforme
                                        gfxMatrix(),
                                        eUserSpaceToParent));
     }
     foundTransform = true;
   }
   return foundTransform;
 }
 
-DrawResult
+void
 nsSVGForeignObjectFrame::PaintSVG(gfxContext& aContext,
                                   const gfxMatrix& aTransform,
-                                  const nsIntRect* aDirtyRect,
-                                  uint32_t aFlags)
+                                  imgDrawingParams& aImgParams,
+                                  const nsIntRect* aDirtyRect)
 {
   NS_ASSERTION(!NS_SVGDisplayListPaintingEnabled() ||
                (mState & NS_FRAME_IS_NONDISPLAY),
                "If display lists are enabled, only painting of non-display "
                "SVG should take this code path");
 
-  if (IsDisabled())
-    return DrawResult::SUCCESS;
+  if (IsDisabled()) {
+    return;
+  }
 
   nsIFrame* kid = PrincipalChildList().FirstChild();
-  if (!kid)
-    return DrawResult::SUCCESS;
+  if (!kid) {
+    return;
+  }
 
   if (aTransform.IsSingular()) {
     NS_WARNING("Can't render foreignObject element!");
-    return DrawResult::SUCCESS;
+    return;
   }
 
   nsRect kidDirtyRect = kid->GetVisualOverflowRect();
 
   /* Check if we need to draw anything. */
   if (aDirtyRect) {
     NS_ASSERTION(!NS_SVGDisplayListPaintingEnabled() ||
                  (mState & NS_FRAME_IS_NONDISPLAY),
@@ -239,17 +241,17 @@ nsSVGForeignObjectFrame::PaintSVG(gfxCon
       nsLayoutUtils::RoundGfxRectToAppRect(transDirtyRect,
                        PresContext()->AppUnitsPerCSSPixel()));
 
     // XXX after bug 614732 is fixed, we will compare mRect with aDirtyRect,
     // not with kidDirtyRect. I.e.
     // int32_t appUnitsPerDevPx = PresContext()->AppUnitsPerDevPixel();
     // mRect.ToOutsidePixels(appUnitsPerDevPx).Intersects(*aDirtyRect)
     if (kidDirtyRect.IsEmpty())
-      return DrawResult::SUCCESS;
+      return;
   }
 
   aContext.Save();
 
   if (StyleDisplay()->IsScrollableOverflow()) {
     float x, y, width, height;
     static_cast<nsSVGElement*>(mContent)->
       GetAnimatedLengthValues(&x, &y, &width, &height, nullptr);
@@ -269,25 +271,26 @@ nsSVGForeignObjectFrame::PaintSVG(gfxCon
 
   aContext.Multiply(canvasTMForChildren);
 
   using PaintFrameFlags = nsLayoutUtils::PaintFrameFlags;
   PaintFrameFlags flags = PaintFrameFlags::PAINT_IN_TRANSFORM;
   if (SVGAutoRenderState::IsPaintingToWindow(aContext.GetDrawTarget())) {
     flags |= PaintFrameFlags::PAINT_TO_WINDOW;
   }
+  if (aImgParams.imageFlags & imgIContainer::FLAG_SYNC_DECODE) {
+    flags |= PaintFrameFlags::PAINT_SYNC_DECODE_IMAGES;
+  }
   nsRenderingContext rendCtx(&aContext);
-  nsresult rv = nsLayoutUtils::PaintFrame(&rendCtx, kid, nsRegion(kidDirtyRect),
-                                         NS_RGBA(0,0,0,0),
-                                         nsDisplayListBuilderMode::PAINTING,
-                                         flags);
+  Unused << nsLayoutUtils::PaintFrame(&rendCtx, kid, nsRegion(kidDirtyRect),
+                                      NS_RGBA(0,0,0,0),
+                                      nsDisplayListBuilderMode::PAINTING,
+                                      flags);
 
   aContext.Restore();
-
-  return NS_FAILED(rv) ? DrawResult::BAD_ARGS : DrawResult::SUCCESS;
 }
 
 nsIFrame*
 nsSVGForeignObjectFrame::GetFrameForPoint(const gfxPoint& aPoint)
 {
   NS_ASSERTION(!NS_SVGDisplayListHitTestingEnabled() ||
                (mState & NS_FRAME_IS_NONDISPLAY),
                "If display lists are enabled, only hit-testing of a "
--- a/layout/svg/nsSVGForeignObjectFrame.h
+++ b/layout/svg/nsSVGForeignObjectFrame.h
@@ -62,20 +62,20 @@ public:
 #ifdef DEBUG_FRAME_DUMP
   virtual nsresult GetFrameName(nsAString& aResult) const override
   {
     return MakeFrameName(NS_LITERAL_STRING("SVGForeignObject"), aResult);
   }
 #endif
 
   // nsSVGDisplayableFrame interface:
-  virtual DrawResult PaintSVG(gfxContext& aContext,
-                              const gfxMatrix& aTransform,
-                              const nsIntRect* aDirtyRect = nullptr,
-                              uint32_t aFlags = 0) override;
+  virtual void PaintSVG(gfxContext& aContext,
+                        const gfxMatrix& aTransform,
+                        imgDrawingParams& aImgParams,
+                        const nsIntRect* aDirtyRect = nullptr) override;
   virtual nsIFrame* GetFrameForPoint(const gfxPoint& aPoint) override;
   virtual void ReflowSVG() override;
   virtual void NotifySVGChanged(uint32_t aFlags) override;
   virtual SVGBBox GetBBoxContribution(const Matrix &aToBBoxUserspace,
                                       uint32_t aFlags) override;
   virtual bool IsDisplayContainer() override { return true; }
 
   gfxMatrix GetCanvasTM();
--- a/layout/svg/nsSVGImageFrame.cpp
+++ b/layout/svg/nsSVGImageFrame.cpp
@@ -63,20 +63,20 @@ protected:
   }
 
   virtual ~nsSVGImageFrame();
 
 public:
   NS_DECL_FRAMEARENA_HELPERS
 
   // nsSVGDisplayableFrame interface:
-  virtual DrawResult PaintSVG(gfxContext& aContext,
-                              const gfxMatrix& aTransform,
-                              const nsIntRect* aDirtyRect = nullptr,
-                              uint32_t aFlags = 0) override;
+  virtual void PaintSVG(gfxContext& aContext,
+                        const gfxMatrix& aTransform,
+                        imgDrawingParams& aImgParams,
+                        const nsIntRect* aDirtyRect = nullptr) override;
   virtual nsIFrame* GetFrameForPoint(const gfxPoint& aPoint) override;
   virtual void ReflowSVG() override;
 
   // SVGGeometryFrame methods:
   virtual uint16_t GetHitTestFlags() override;
 
   // nsIFrame interface:
   virtual nsresult  AttributeChanged(int32_t         aNameSpaceID,
@@ -326,24 +326,25 @@ nsSVGImageFrame::TransformContextForPain
   }
 
   aGfxContext->Multiply(ThebesMatrix(imageTransform));
   return true;
 }
 
 //----------------------------------------------------------------------
 // nsSVGDisplayableFrame methods:
-DrawResult
+void
 nsSVGImageFrame::PaintSVG(gfxContext& aContext,
                           const gfxMatrix& aTransform,
-                          const nsIntRect *aDirtyRect,
-                          uint32_t aFlags)
+                          imgDrawingParams& aImgParams,
+                          const nsIntRect *aDirtyRect)
 {
-  if (!StyleVisibility()->IsVisible())
-    return DrawResult::SUCCESS;
+  if (!StyleVisibility()->IsVisible()) {
+    return;
+  }
 
   float x, y, width, height;
   SVGImageElement *imgElem = static_cast<SVGImageElement*>(mContent);
   imgElem->GetAnimatedLengthValues(&x, &y, &width, &height, nullptr);
   NS_ASSERTION(width > 0 && height > 0,
                "Should only be painting things with valid width/height");
 
   if (!mImageContainer) {
@@ -352,28 +353,27 @@ nsSVGImageFrame::PaintSVG(gfxContext& aC
     if (imageLoader)
       imageLoader->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST,
                               getter_AddRefs(currentRequest));
 
     if (currentRequest)
       currentRequest->GetImage(getter_AddRefs(mImageContainer));
   }
 
-  DrawResult result = DrawResult::SUCCESS;
   if (mImageContainer) {
     gfxContextAutoSaveRestore autoRestorer(&aContext);
 
     if (StyleDisplay()->IsScrollableOverflow()) {
       gfxRect clipRect = nsSVGUtils::GetClipRectForFrame(this, x, y,
                                                          width, height);
       nsSVGUtils::SetClipRect(&aContext, aTransform, clipRect);
     }
 
     if (!TransformContextForPainting(&aContext, aTransform)) {
-      return DrawResult::SUCCESS;
+      return ;
     }
 
     // fill-opacity doesn't affect <image>, so if we're allowed to
     // optimize group opacity, the opacity used for compositing the
     // image into the current canvas is just the group opacity.
     float opacity = 1.0f;
     if (nsSVGUtils::CanOptimizeOpacity(this)) {
       opacity = StyleEffects()->mOpacity;
@@ -413,43 +413,41 @@ nsSVGImageFrame::PaintSVG(gfxContext& aC
       LayoutDeviceSize devPxSize(width, height);
       nsRect destRect(nsPoint(),
                       LayoutDevicePixel::ToAppUnits(devPxSize,
                                                     appUnitsPerDevPx));
 
       // Note: Can't use DrawSingleUnscaledImage for the TYPE_VECTOR case.
       // That method needs our image to have a fixed native width & height,
       // and that's not always true for TYPE_VECTOR images.
-      result = nsLayoutUtils::DrawSingleImage(
+      aImgParams.result &= nsLayoutUtils::DrawSingleImage(
         aContext,
         PresContext(),
         mImageContainer,
         nsLayoutUtils::GetSamplingFilterForFrame(this),
         destRect,
         aDirtyRect ? dirtyRect : destRect,
         context,
-        aFlags);
+        aImgParams.imageFlags);
     } else { // mImageContainer->GetType() == TYPE_RASTER
-      result = nsLayoutUtils::DrawSingleUnscaledImage(
+      aImgParams.result &= nsLayoutUtils::DrawSingleUnscaledImage(
         aContext,
         PresContext(),
         mImageContainer,
         nsLayoutUtils::GetSamplingFilterForFrame(this),
         nsPoint(0, 0),
         aDirtyRect ? &dirtyRect : nullptr,
-        aFlags);
+        aImgParams.imageFlags);
     }
 
     if (opacity != 1.0f || StyleEffects()->mMixBlendMode != NS_STYLE_BLEND_NORMAL) {
       aContext.PopGroupAndBlend();
     }
     // gfxContextAutoSaveRestore goes out of scope & cleans up our gfxContext
   }
-
-  return result;
 }
 
 nsIFrame*
 nsSVGImageFrame::GetFrameForPoint(const gfxPoint& aPoint)
 {
   if (!(GetStateBits() & NS_STATE_SVG_CLIPPATH_CHILD) && !GetHitTestFlags()) {
     return nullptr;
   }
--- a/layout/svg/nsSVGInnerSVGFrame.cpp
+++ b/layout/svg/nsSVGInnerSVGFrame.cpp
@@ -47,45 +47,46 @@ nsSVGInnerSVGFrame::Init(nsIContent*    
 
   nsSVGDisplayContainerFrame::Init(aContent, aParent, aPrevInFlow);
 }
 #endif /* DEBUG */
 
 //----------------------------------------------------------------------
 // nsSVGDisplayableFrame methods
 
-DrawResult
+void
 nsSVGInnerSVGFrame::PaintSVG(gfxContext& aContext,
                              const gfxMatrix& aTransform,
-                             const nsIntRect *aDirtyRect,
-                             uint32_t aFlags)
+                             imgDrawingParams& aImgParams,
+                             const nsIntRect *aDirtyRect)
 {
   NS_ASSERTION(!NS_SVGDisplayListPaintingEnabled() ||
                (mState & NS_FRAME_IS_NONDISPLAY),
                "If display lists are enabled, only painting of non-display "
                "SVG should take this code path");
 
   gfxContextAutoSaveRestore autoSR;
 
   if (StyleDisplay()->IsScrollableOverflow()) {
     float x, y, width, height;
     static_cast<SVGSVGElement*>(mContent)->
       GetAnimatedLengthValues(&x, &y, &width, &height, nullptr);
 
     if (width <= 0 || height <= 0) {
-      return DrawResult::SUCCESS;
+      return;
     }
 
     autoSR.SetContext(&aContext);
     gfxRect clipRect =
       nsSVGUtils::GetClipRectForFrame(this, x, y, width, height);
     nsSVGUtils::SetClipRect(&aContext, aTransform, clipRect);
   }
 
-  return nsSVGDisplayContainerFrame::PaintSVG(aContext, aTransform, aDirtyRect, aFlags);
+  nsSVGDisplayContainerFrame::PaintSVG(aContext, aTransform, aImgParams,
+                                       aDirtyRect);
 }
 
 void
 nsSVGInnerSVGFrame::ReflowSVG()
 {
   // mRect must be set before FinishAndStoreOverflow is called in order
   // for our overflow areas to be clipped correctly.
   float x, y, width, height;
--- a/layout/svg/nsSVGInnerSVGFrame.h
+++ b/layout/svg/nsSVGInnerSVGFrame.h
@@ -44,20 +44,20 @@ public:
   }
 #endif
 
   virtual nsresult  AttributeChanged(int32_t         aNameSpaceID,
                                      nsIAtom*        aAttribute,
                                      int32_t         aModType) override;
 
   // nsSVGDisplayableFrame interface:
-  virtual DrawResult PaintSVG(gfxContext& aContext,
-                              const gfxMatrix& aTransform,
-                              const nsIntRect *aDirtyRect = nullptr,
-                              uint32_t aFlags = 0) override;
+  virtual void PaintSVG(gfxContext& aContext,
+                        const gfxMatrix& aTransform,
+                        imgDrawingParams& aImgParams,
+                        const nsIntRect* aDirtyRect = nullptr) override;
   virtual void ReflowSVG() override;
   virtual void NotifySVGChanged(uint32_t aFlags) override;
   SVGBBox GetBBoxContribution(const Matrix &aToBBoxUserspace,
                               uint32_t aFlags) override;
   virtual nsIFrame* GetFrameForPoint(const gfxPoint& aPoint) override;
 
   // nsSVGContainerFrame methods:
   virtual gfxMatrix GetCanvasTM() override;
--- a/layout/svg/nsSVGIntegrationUtils.cpp
+++ b/layout/svg/nsSVGIntegrationUtils.cpp
@@ -379,30 +379,30 @@ class RegularFramePaintCallback : public
 {
 public:
   RegularFramePaintCallback(nsDisplayListBuilder* aBuilder,
                             LayerManager* aManager,
                             const gfxPoint& aUserSpaceToFrameSpaceOffset)
     : mBuilder(aBuilder), mLayerManager(aManager),
       mUserSpaceToFrameSpaceOffset(aUserSpaceToFrameSpaceOffset) {}
 
-  virtual DrawResult Paint(gfxContext& aContext, nsIFrame *aTarget,
-                           const gfxMatrix& aTransform,
-                           const nsIntRect* aDirtyRect) override
+  virtual void Paint(gfxContext& aContext, nsIFrame *aTarget,
+                     const gfxMatrix& aTransform,
+                     const nsIntRect* aDirtyRect,
+                     imgDrawingParams& aImgParams) override
   {
     BasicLayerManager* basic = mLayerManager->AsBasicLayerManager();
     RefPtr<gfxContext> oldCtx = basic->GetTarget();
     basic->SetTarget(&aContext);
 
     gfxContextMatrixAutoSaveRestore autoSR(&aContext);
     aContext.SetMatrix(aContext.CurrentMatrix().Translate(-mUserSpaceToFrameSpaceOffset));
 
     mLayerManager->EndTransaction(FrameLayerBuilder::DrawPaintedLayer, mBuilder);
     basic->SetTarget(oldCtx);
-    return DrawResult::SUCCESS;
   }
 
 private:
   nsDisplayListBuilder* mBuilder;
   LayerManager* mLayerManager;
   gfxPoint mUserSpaceToFrameSpaceOffset;
 };
 
@@ -1053,43 +1053,44 @@ nsSVGIntegrationUtils::PaintMaskAndClipP
 
   if (shouldPushMask) {
     context.PopGroupAndBlend();
   }
 
   return result;
 }
 
-DrawResult
-nsSVGIntegrationUtils::PaintFilter(const PaintFramesParams& aParams)
+void
+nsSVGIntegrationUtils::PaintFilter(const PaintFramesParams& aParams,
+                                   imgDrawingParams& aImgParams)
 {
   MOZ_ASSERT(!aParams.builder->IsForGenerateGlyphMask(),
              "Filter effect is discarded while generating glyph mask.");
   MOZ_ASSERT(aParams.frame->StyleEffects()->HasFilters(),
              "Should not use this method when no filter effect on this frame");
 
   nsIFrame* frame = aParams.frame;
   if (!ValidateSVGFrame(frame)) {
-    return DrawResult::SUCCESS;
+    return;
   }
 
   float opacity = nsSVGUtils::ComputeOpacity(frame, aParams.handleOpacity);
   if (opacity == 0.0f) {
-    return DrawResult::SUCCESS;
+    return;
   }
 
   /* Properties are added lazily and may have been removed by a restyle,
      so make sure all applicable ones are set again. */
   nsIFrame* firstFrame =
     nsLayoutUtils::FirstContinuationOrIBSplitSibling(frame);
   nsSVGEffects::EffectProperties effectProperties =
     nsSVGEffects::GetEffectProperties(firstFrame);
 
   if (effectProperties.HasInvalidFilter()) {
-    return DrawResult::NOT_READY;
+    return;
   }
 
   gfxContext& context = aParams.ctx;
 
   gfxContextAutoSaveRestore autoSR(&context);
   EffectOffsets offsets = MoveContextOriginToUserSpace(firstFrame, aParams);
 
   if (opacity != 1.0f) {
@@ -1107,25 +1108,23 @@ nsSVGIntegrationUtils::PaintFilter(const
                         0.0f, 0.0f);
   gfxMatrix reverseScaleMatrix = scaleMatrix;
   DebugOnly<bool> invertible = reverseScaleMatrix.Invert();
   MOZ_ASSERT(invertible);
   context.SetMatrix(reverseScaleMatrix * context.CurrentMatrix());
 
   gfxMatrix tm =
     scaleMatrix * nsSVGUtils::GetCSSPxToDevPxMatrix(frame);
-  DrawResult result =
-    nsFilterInstance::PaintFilteredFrame(frame, context.GetDrawTarget(),
-                                         tm, &callback, &dirtyRegion);
+  nsFilterInstance::PaintFilteredFrame(frame, context.GetDrawTarget(),
+                                       tm, &callback, &dirtyRegion,
+                                       aImgParams);
 
   if (opacity != 1.0f) {
     context.PopGroupAndBlend();
   }
-
-  return result;
 }
 
 class PaintFrameCallback : public gfxDrawingCallback {
 public:
   PaintFrameCallback(nsIFrame* aFrame,
                      const nsSize aPaintServerSize,
                      const IntSize aRenderSize,
                      uint32_t aFlags)
--- a/layout/svg/nsSVGIntegrationUtils.h
+++ b/layout/svg/nsSVGIntegrationUtils.h
@@ -36,16 +36,17 @@ struct nsSize;
  * Integration of SVG effects (clipPath clipping, masking and filters) into
  * regular display list based painting and hit-testing.
  */
 class nsSVGIntegrationUtils final
 {
   typedef mozilla::gfx::DrawTarget DrawTarget;
   typedef mozilla::gfx::IntRect IntRect;
   typedef mozilla::image::DrawResult DrawResult;
+  typedef mozilla::image::imgDrawingParams imgDrawingParams;
 
 public:
   /**
    * Returns true if SVG effects are currently applied to this frame.
    */
   static bool
   UsingEffectsForFrame(const nsIFrame* aFrame);
 
@@ -147,18 +148,17 @@ public:
     explicit PaintFramesParams(gfxContext& aCtx, nsIFrame* aFrame,
                                const nsRect& aDirtyRect,
                                const nsRect& aBorderArea,
                                nsDisplayListBuilder* aBuilder,
                                mozilla::layers::LayerManager* aLayerManager,
                                bool aHandleOpacity, uint32_t aFlags)
       : ctx(aCtx), frame(aFrame), dirtyRect(aDirtyRect),
         borderArea(aBorderArea), builder(aBuilder),
-        layerManager(aLayerManager), handleOpacity(aHandleOpacity),
-        flags(aFlags)
+        layerManager(aLayerManager), handleOpacity(aHandleOpacity)
     { }
   };
 
   /**
    * Paint non-SVG frame with mask, clipPath and opacity effect.
    */
   static DrawResult
   PaintMaskAndClipPath(const PaintFramesParams& aParams);
@@ -174,18 +174,18 @@ public:
    * Return true if all the mask resource of aFrame are ready.
    */
   static bool
   IsMaskResourceReady(nsIFrame* aFrame);
 
   /**
    * Paint non-SVG frame with filter and opacity effect.
    */
-  static DrawResult
-  PaintFilter(const PaintFramesParams& aParams);
+  static void
+  PaintFilter(const PaintFramesParams& aParams, imgDrawingParams& aImgParams);
 
   /**
    * @param aRenderingContext the target rendering context in which the paint
    * server will be rendered
    * @param aTarget the target frame onto which the paint server will be
    * rendered
    * @param aPaintServer a first-continuation frame to use as the source
    * @param aFilter a filter to be applied when scaling
--- a/layout/svg/nsSVGMarkerFrame.cpp
+++ b/layout/svg/nsSVGMarkerFrame.cpp
@@ -91,42 +91,42 @@ static nsIFrame*
 GetAnonymousChildFrame(nsIFrame* aFrame)
 {
   nsIFrame* kid = aFrame->PrincipalChildList().FirstChild();
   MOZ_ASSERT(kid && kid->IsSVGMarkerAnonChildFrame(),
              "expected to find anonymous child of marker frame");
   return kid;
 }
 
-DrawResult
+void
 nsSVGMarkerFrame::PaintMark(gfxContext& aContext,
                             const gfxMatrix& aToMarkedFrameUserSpace,
                             SVGGeometryFrame *aMarkedFrame,
                             nsSVGMark *aMark, float aStrokeWidth,
-                            uint32_t aFlags)
+                            imgDrawingParams& aImgParams)
 {
   // If the flag is set when we get here, it means this marker frame
   // has already been used painting the current mark, and the document
   // has a marker reference loop.
   if (mInUse) {
-    return DrawResult::SUCCESS;
+    return;
   }
 
   AutoMarkerReferencer markerRef(this, aMarkedFrame);
 
   SVGMarkerElement *marker = static_cast<SVGMarkerElement*>(mContent);
   if (!marker->HasValidDimensions()) {
-    return DrawResult::SUCCESS;
+    return;
   }
 
   const nsSVGViewBoxRect viewBox = marker->GetViewBoxRect();
 
   if (viewBox.width <= 0.0f || viewBox.height <= 0.0f) {
     // We must disable rendering if the viewBox width or height are zero.
-    return DrawResult::SUCCESS;
+    return;
   }
 
   mStrokeWidth = aStrokeWidth;
   mX = aMark->x;
   mY = aMark->y;
   mAutoAngle = aMark->angle;
   mIsStart = aMark->type == nsSVGMark::eStart;
 
@@ -146,23 +146,20 @@ nsSVGMarkerFrame::PaintMark(gfxContext& 
     nsSVGUtils::SetClipRect(&aContext, markTM, clipRect);
   }
 
 
   nsIFrame* kid = GetAnonymousChildFrame(this);
   nsSVGDisplayableFrame* SVGFrame = do_QueryFrame(kid);
   // The CTM of each frame referencing us may be different.
   SVGFrame->NotifySVGChanged(nsSVGDisplayableFrame::TRANSFORM_CHANGED);
-  DrawResult result = nsSVGUtils::PaintFrameWithEffects(kid, aContext, markTM,
-                                                        nullptr, aFlags);
+  nsSVGUtils::PaintFrameWithEffects(kid, aContext, markTM, aImgParams);
 
   if (StyleDisplay()->IsScrollableOverflow())
     aContext.Restore();
-
-  return result;
 }
 
 SVGBBox
 nsSVGMarkerFrame::GetMarkBBoxContribution(const Matrix &aToBBoxUserspace,
                                           uint32_t aFlags,
                                           SVGGeometryFrame *aMarkedFrame,
                                           const nsSVGMark *aMark,
                                           float aStrokeWidth)
--- a/layout/svg/nsSVGMarkerFrame.h
+++ b/layout/svg/nsSVGMarkerFrame.h
@@ -23,16 +23,18 @@ namespace dom {
 class SVGSVGElement;
 } // namespace dom
 } // namespace mozilla
 
 struct nsSVGMark;
 
 class nsSVGMarkerFrame final : public nsSVGContainerFrame
 {
+  typedef mozilla::image::imgDrawingParams imgDrawingParams;
+
   friend class nsSVGMarkerAnonChildFrame;
   friend nsContainerFrame*
   NS_NewSVGMarkerFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
 protected:
   explicit nsSVGMarkerFrame(nsStyleContext* aContext)
     : nsSVGContainerFrame(aContext, mozilla::LayoutFrameType::SVGMarker)
     , mMarkedFrame(nullptr)
     , mInUse(false)
@@ -70,22 +72,22 @@ public:
     // Any children must be added to our single anonymous inner frame kid.
     MOZ_ASSERT(PrincipalChildList().FirstChild() &&
                PrincipalChildList().FirstChild()->IsSVGMarkerAnonChildFrame(),
                "Where is our anonymous child?");
     return PrincipalChildList().FirstChild()->GetContentInsertionFrame();
   }
 
   // nsSVGMarkerFrame methods:
-  DrawResult PaintMark(gfxContext& aContext,
-                      const gfxMatrix& aToMarkedFrameUserSpace,
-                      mozilla::SVGGeometryFrame *aMarkedFrame,
-                      nsSVGMark *aMark,
-                      float aStrokeWidth,
-                      uint32_t aFlags);
+  void PaintMark(gfxContext& aContext,
+                 const gfxMatrix& aToMarkedFrameUserSpace,
+                 mozilla::SVGGeometryFrame *aMarkedFrame,
+                 nsSVGMark *aMark,
+                 float aStrokeWidth,
+                 imgDrawingParams& aImgParams);
 
   SVGBBox GetMarkBBoxContribution(const Matrix &aToBBoxUserspace,
                                   uint32_t aFlags,
                                   mozilla::SVGGeometryFrame *aMarkedFrame,
                                   const nsSVGMark *aMark,
                                   float aStrokeWidth);
 
   // Update the style on our anonymous box child.
--- a/layout/svg/nsSVGMaskFrame.cpp
+++ b/layout/svg/nsSVGMaskFrame.cpp
@@ -248,32 +248,31 @@ nsSVGMaskFrame::GetMaskForMaskedFrame(Ma
     context->CurrentMatrix() * gfxMatrix::Translation(-maskSurfaceRect.TopLeft());
 
   RefPtr<gfxContext> tmpCtx = gfxContext::CreateOrNull(maskDT);
   MOZ_ASSERT(tmpCtx); // already checked the draw target above
   tmpCtx->SetMatrix(maskSurfaceMatrix);
 
   mMatrixForChildren = GetMaskTransform(aParams.maskedFrame) *
                        aParams.toUserSpace;
-  DrawResult result = DrawResult::SUCCESS;
+  imgDrawingParams imgParams(aParams.flags);
 
   for (nsIFrame* kid = mFrames.FirstChild(); kid;
        kid = kid->GetNextSibling()) {
     // The CTM of each frame referencing us can be different
     nsSVGDisplayableFrame* SVGFrame = do_QueryFrame(kid);
     if (SVGFrame) {
       SVGFrame->NotifySVGChanged(nsSVGDisplayableFrame::TRANSFORM_CHANGED);
     }
     gfxMatrix m = mMatrixForChildren;
     if (kid->GetContent()->IsSVGElement()) {
       m = static_cast<nsSVGElement*>(kid->GetContent())->
             PrependLocalTransformsTo(m, eUserSpaceToParent);
     }
-    result &= nsSVGUtils::PaintFrameWithEffects(kid, *tmpCtx, m, nullptr,
-                                                aParams.flags);
+    nsSVGUtils::PaintFrameWithEffects(kid, *tmpCtx, m, imgParams);
   }
 
   RefPtr<SourceSurface> maskSnapshot = maskDT->Snapshot();
   if (!maskSnapshot) {
     return MakePair(DrawResult::TEMPORARY_ERROR, RefPtr<SourceSurface>());
   }
   RefPtr<DataSourceSurface> maskSurface = maskSnapshot->GetDataSurface();
   DataSourceSurface::MappedSurface map;
@@ -323,17 +322,17 @@ nsSVGMaskFrame::GetMaskForMaskedFrame(Ma
 
   // Moz2D transforms in the opposite direction to Thebes
   if (!maskSurfaceMatrix.Invert()) {
     return MakePair(DrawResult::SUCCESS, RefPtr<SourceSurface>());
   }
 
   *aParams.maskTransform = ToMatrix(maskSurfaceMatrix);
   RefPtr<SourceSurface> surface = destMaskSurface.forget();
-  return MakePair(result, Move(surface));
+  return MakePair(imgParams.result, Move(surface));
 }
 
 gfxRect
 nsSVGMaskFrame::GetMaskArea(nsIFrame* aMaskedFrame)
 {
   SVGMaskElement *maskElem = static_cast<SVGMaskElement*>(mContent);
 
   uint16_t units =
--- a/layout/svg/nsSVGMaskFrame.h
+++ b/layout/svg/nsSVGMaskFrame.h
@@ -35,16 +35,17 @@ class gfxContext;
 class nsSVGMaskFrame final : public nsSVGContainerFrame
 {
   friend nsIFrame*
   NS_NewSVGMaskFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
 
   typedef mozilla::gfx::Matrix Matrix;
   typedef mozilla::gfx::SourceSurface SourceSurface;
   typedef mozilla::image::DrawResult DrawResult;
+  typedef mozilla::image::imgDrawingParams imgDrawingParams;
 
 protected:
   explicit nsSVGMaskFrame(nsStyleContext* aContext)
     : nsSVGContainerFrame(aContext, mozilla::LayoutFrameType::SVGMask)
     , mInUse(false)
   {
     AddStateBits(NS_FRAME_IS_NONDISPLAY);
   }
--- a/layout/svg/nsSVGOuterSVGFrame.cpp
+++ b/layout/svg/nsSVGOuterSVGFrame.cpp
@@ -620,27 +620,26 @@ nsDisplayOuterSVG::Paint(nsDisplayListBu
   nsIntRect contentAreaDirtyRect =
     (clipRect - viewportRect.TopLeft()).
       ToOutsidePixels(appUnitsPerDevPixel);
 
   gfxPoint devPixelOffset =
     nsLayoutUtils::PointToGfxPoint(viewportRect.TopLeft(), appUnitsPerDevPixel);
 
   aContext->ThebesContext()->Save();
-  uint32_t flags = aBuilder->ShouldSyncDecodeImages()
-                  ? imgIContainer::FLAG_SYNC_DECODE
-                  : imgIContainer::FLAG_SYNC_DECODE_IF_FAST;
+  imgDrawingParams imgParams(aBuilder->ShouldSyncDecodeImages()
+                             ? imgIContainer::FLAG_SYNC_DECODE
+                             : imgIContainer::FLAG_SYNC_DECODE_IF_FAST);
   // We include the offset of our frame and a scale from device pixels to user
   // units (i.e. CSS px) in the matrix that we pass to our children):
   gfxMatrix tm = nsSVGUtils::GetCSSPxToDevPxMatrix(mFrame) *
                    gfxMatrix::Translation(devPixelOffset);
-  DrawResult result =
-    nsSVGUtils::PaintFrameWithEffects(mFrame, *aContext->ThebesContext(), tm,
-                                      &contentAreaDirtyRect, flags);
-  nsDisplayItemGenericImageGeometry::UpdateDrawResult(this, result);
+  nsSVGUtils::PaintFrameWithEffects(mFrame, *aContext->ThebesContext(), tm,
+                                    imgParams, &contentAreaDirtyRect);
+  nsDisplayItemGenericImageGeometry::UpdateDrawResult(this, imgParams.result);
   aContext->ThebesContext()->Restore();
 
 #if defined(DEBUG) && defined(SVG_DEBUG_PAINT_TIMING)
   PRTime end = PR_Now();
   printf("SVG Paint Timing: %f ms\n", (end-start)/1000.0);
 #endif
 }
 
@@ -858,28 +857,28 @@ nsSVGOuterSVGFrame::NotifyViewportOrTran
   }
 
   nsSVGUtils::NotifyChildrenOfSVGChange(PrincipalChildList().FirstChild(), aFlags);
 }
 
 //----------------------------------------------------------------------
 // nsSVGDisplayableFrame methods:
 
-DrawResult
+void
 nsSVGOuterSVGFrame::PaintSVG(gfxContext& aContext,
                              const gfxMatrix& aTransform,
-                             const nsIntRect* aDirtyRect,
-                             uint32_t aFlags)
+                             imgDrawingParams& aImgParams,
+                             const nsIntRect* aDirtyRect)
 {
   NS_ASSERTION(PrincipalChildList().FirstChild()->IsSVGOuterSVGAnonChildFrame() &&
                !PrincipalChildList().FirstChild()->GetNextSibling(),
                "We should have a single, anonymous, child");
   nsSVGOuterSVGAnonChildFrame *anonKid =
     static_cast<nsSVGOuterSVGAnonChildFrame*>(PrincipalChildList().FirstChild());
-  return anonKid->PaintSVG(aContext, aTransform, aDirtyRect, aFlags);
+  anonKid->PaintSVG(aContext, aTransform, aImgParams, aDirtyRect);
 }
 
 SVGBBox
 nsSVGOuterSVGFrame::GetBBoxContribution(const gfx::Matrix &aToBBoxUserspace,
                                         uint32_t aFlags)
 {
   NS_ASSERTION(PrincipalChildList().FirstChild()->IsSVGOuterSVGAnonChildFrame() &&
                !PrincipalChildList().FirstChild()->GetNextSibling(),
--- a/layout/svg/nsSVGOuterSVGFrame.h
+++ b/layout/svg/nsSVGOuterSVGFrame.h
@@ -16,16 +16,18 @@ class gfxContext;
 class nsSVGForeignObjectFrame;
 
 ////////////////////////////////////////////////////////////////////////
 // nsSVGOuterSVGFrame class
 
 class nsSVGOuterSVGFrame final : public nsSVGDisplayContainerFrame
                                , public nsISVGSVGFrame
 {
+  typedef mozilla::image::imgDrawingParams imgDrawingParams;
+
   friend nsContainerFrame*
   NS_NewSVGOuterSVGFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
 protected:
   explicit nsSVGOuterSVGFrame(nsStyleContext* aContext);
 
 public:
   NS_DECL_QUERYFRAME
   NS_DECL_FRAMEARENA_HELPERS
@@ -101,20 +103,20 @@ public:
   void DoUpdateStyleOfOwnedAnonBoxes(mozilla::ServoStyleSet& aStyleSet,
                                      nsStyleChangeList& aChangeList,
                                      nsChangeHint aHintForThisFrame) override;
 
   // nsISVGSVGFrame interface:
   virtual void NotifyViewportOrTransformChanged(uint32_t aFlags) override;
 
   // nsSVGDisplayableFrame methods:
-  virtual DrawResult PaintSVG(gfxContext& aContext,
-                              const gfxMatrix& aTransform,
-                              const nsIntRect* aDirtyRect = nullptr,
-                              uint32_t aFlags = 0) override;
+  virtual void PaintSVG(gfxContext& aContext,
+                        const gfxMatrix& aTransform,
+                        imgDrawingParams& aImgParams,
+                        const nsIntRect* aDirtyRect = nullptr) override;
   virtual SVGBBox GetBBoxContribution(const Matrix &aToBBoxUserspace,
                                       uint32_t aFlags) override;
 
   // nsSVGContainerFrame methods:
   virtual gfxMatrix GetCanvasTM() override;
 
   /* Methods to allow descendant nsSVGForeignObjectFrame frames to register and
    * unregister themselves with their nearest nsSVGOuterSVGFrame ancestor. This
--- a/layout/svg/nsSVGPaintServerFrame.h
+++ b/layout/svg/nsSVGPaintServerFrame.h
@@ -61,16 +61,18 @@ protected:
   explicit nsSVGPaintServerFrame(nsStyleContext* aContext,
                                  mozilla::LayoutFrameType aType)
     : nsSVGContainerFrame(aContext, aType)
   {
     AddStateBits(NS_FRAME_IS_NONDISPLAY);
   }
 
 public:
+  typedef mozilla::image::imgDrawingParams imgDrawingParams;
+
   NS_DECL_ABSTRACT_FRAME(nsSVGPaintServerFrame)
 
   /**
    * Constructs a gfxPattern of the paint server rendering.
    *
    * @param aContextMatrix The transform matrix that is currently applied to
    *   the gfxContext that is being drawn to. This is needed by SVG patterns so
    *   that surfaces of the correct size can be created. (SVG gradients are
--- a/layout/svg/nsSVGPatternFrame.cpp
+++ b/layout/svg/nsSVGPatternFrame.cpp
@@ -371,47 +371,46 @@ nsSVGPatternFrame::PaintPattern(const Dr
 
   if (aSource->IsFrameOfType(nsIFrame::eSVGGeometry)) {
     // Set the geometrical parent of the pattern we are rendering
     patternWithChildren->mSource = static_cast<SVGGeometryFrame*>(aSource);
   }
 
   // Delay checking NS_FRAME_DRAWING_AS_PAINTSERVER bit until here so we can
   // give back a clear surface if there's a loop
-  DrawResult result = DrawResult::SUCCESS;
+  imgDrawingParams imgParams(aFlags);
   if (!(patternWithChildren->GetStateBits() & NS_FRAME_DRAWING_AS_PAINTSERVER)) {
     AutoSetRestorePaintServerState paintServer(patternWithChildren);
     for (nsIFrame* kid = firstKid; kid;
          kid = kid->GetNextSibling()) {
       // The CTM of each frame referencing us can be different
       nsSVGDisplayableFrame* SVGFrame = do_QueryFrame(kid);
       if (SVGFrame) {
         SVGFrame->NotifySVGChanged(nsSVGDisplayableFrame::TRANSFORM_CHANGED);
       }
       gfxMatrix tm = *(patternWithChildren->mCTM);
       if (kid->GetContent()->IsSVGElement()) {
         tm = static_cast<nsSVGElement*>(kid->GetContent())->
                PrependLocalTransformsTo(tm, eUserSpaceToParent);
       }
 
-      result &= nsSVGUtils::PaintFrameWithEffects(kid, *ctx, tm, nullptr,
-                                                  aFlags);
+      nsSVGUtils::PaintFrameWithEffects(kid, *ctx, tm, imgParams);
     }
   }
 
   patternWithChildren->mSource = nullptr;
 
   if (aGraphicOpacity != 1.0f) {
     ctx->PopGroupAndBlend();
     ctx->Restore();
   }
 
   // caller now owns the surface
   RefPtr<SourceSurface> surf = dt->Snapshot();
-  return MakePair(result, Move(surf));
+  return MakePair(imgParams.result, Move(surf));
 }
 
 /* Will probably need something like this... */
 // How do we handle the insertion of a new frame?
 // We really don't want to rerender this every time,
 // do we?
 nsSVGPatternFrame*
 nsSVGPatternFrame::GetPatternWithChildren()
--- a/layout/svg/nsSVGSwitchFrame.cpp
+++ b/layout/svg/nsSVGSwitchFrame.cpp
@@ -38,20 +38,20 @@ public:
   }
 #endif
 
   virtual void BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                                 const nsRect&           aDirtyRect,
                                 const nsDisplayListSet& aLists) override;
 
   // nsSVGDisplayableFrame interface:
-  virtual DrawResult PaintSVG(gfxContext& aContext,
-                              const gfxMatrix& aTransform,
-                              const nsIntRect* aDirtyRect = nullptr,
-                              uint32_t aFlags = 0) override;
+  virtual void PaintSVG(gfxContext& aContext,
+                        const gfxMatrix& aTransform,
+                        imgDrawingParams& aPackage,
+                        const nsIntRect* aDirtyRect = nullptr) override;
   nsIFrame* GetFrameForPoint(const gfxPoint& aPoint) override;
   virtual void ReflowSVG() override;
   virtual SVGBBox GetBBoxContribution(const Matrix &aToBBoxUserspace,
                                       uint32_t aFlags) override;
 
 private:
   nsIFrame *GetActiveChildFrame();
 };
@@ -86,41 +86,40 @@ nsSVGSwitchFrame::BuildDisplayList(nsDis
                                    const nsDisplayListSet& aLists)
 {
   nsIFrame* kid = GetActiveChildFrame();
   if (kid) {
     BuildDisplayListForChild(aBuilder, kid, aDirtyRect, aLists);
   }
 }
 
-DrawResult
+void
 nsSVGSwitchFrame::PaintSVG(gfxContext& aContext,
                            const gfxMatrix& aTransform,
-                           const nsIntRect* aDirtyRect,
-                           uint32_t aFlags)
+                           imgDrawingParams& aImgParams,
+                           const nsIntRect* aDirtyRect)
 {
   NS_ASSERTION(!NS_SVGDisplayListPaintingEnabled() ||
                (mState & NS_FRAME_IS_NONDISPLAY),
                "If display lists are enabled, only painting of non-display "
                "SVG should take this code path");
 
-  if (StyleEffects()->mOpacity == 0.0)
-    return DrawResult::SUCCESS;
+  if (StyleEffects()->mOpacity == 0.0){
+    return;
+  }
 
-  DrawResult result = DrawResult::SUCCESS;
   nsIFrame *kid = GetActiveChildFrame();
   if (kid) {
     gfxMatrix tm = aTransform;
     if (kid->GetContent()->IsSVGElement()) {
       tm = static_cast<nsSVGElement*>(kid->GetContent())->
              PrependLocalTransformsTo(tm, eUserSpaceToParent);
     }
-    result = nsSVGUtils::PaintFrameWithEffects(kid, aContext, tm, aDirtyRect);
+    nsSVGUtils::PaintFrameWithEffects(kid, aContext, tm, aImgParams, aDirtyRect);
   }
-  return result;
 }
 
 
 nsIFrame*
 nsSVGSwitchFrame::GetFrameForPoint(const gfxPoint& aPoint)
 {
   NS_ASSERTION(!NS_SVGDisplayListHitTestingEnabled() ||
                (mState & NS_FRAME_IS_NONDISPLAY),
--- a/layout/svg/nsSVGUtils.cpp
+++ b/layout/svg/nsSVGUtils.cpp
@@ -464,52 +464,45 @@ nsSVGUtils::NotifyChildrenOfSVGChange(ns
   }
 }
 
 // ************************************************************
 
 class SVGPaintCallback : public nsSVGFilterPaintCallback
 {
 public:
-  explicit SVGPaintCallback(uint32_t aFlags)
-    : mFlags(aFlags)
-  { }
-
-  virtual DrawResult Paint(gfxContext& aContext, nsIFrame *aTarget,
+  virtual void Paint(gfxContext& aContext, nsIFrame *aTarget,
                            const gfxMatrix& aTransform,
-                           const nsIntRect* aDirtyRect) override
+                           const nsIntRect* aDirtyRect,
+                           imgDrawingParams& aImgParams) override
   {
     nsSVGDisplayableFrame* svgFrame = do_QueryFrame(aTarget);
     NS_ASSERTION(svgFrame, "Expected SVG frame here");
 
     nsIntRect* dirtyRect = nullptr;
     nsIntRect tmpDirtyRect;
 
     // aDirtyRect is in user-space pixels, we need to convert to
     // outer-SVG-frame-relative device pixels.
     if (aDirtyRect) {
       gfxMatrix userToDeviceSpace = aTransform;
       if (userToDeviceSpace.IsSingular()) {
-        return DrawResult::SUCCESS;
+        return;
       }
       gfxRect dirtyBounds = userToDeviceSpace.TransformBounds(
         gfxRect(aDirtyRect->x, aDirtyRect->y, aDirtyRect->width, aDirtyRect->height));
       dirtyBounds.RoundOut();
       if (gfxUtils::GfxRectToIntRect(dirtyBounds, &tmpDirtyRect)) {
         dirtyRect = &tmpDirtyRect;
       }
     }
 
-    return svgFrame->PaintSVG(aContext,
-                              nsSVGUtils::GetCSSPxToDevPxMatrix(aTarget),
-                              dirtyRect, mFlags);
+    svgFrame->PaintSVG(aContext, nsSVGUtils::GetCSSPxToDevPxMatrix(aTarget),
+                       aImgParams, dirtyRect);
   }
-
-private:
-  uint32_t mFlags;
 };
 
 float
 nsSVGUtils::ComputeOpacity(nsIFrame* aFrame, bool aHandleOpacity)
 {
   float opacity = aFrame->StyleEffects()->mOpacity;
 
   if (opacity != 1.0f &&
@@ -673,43 +666,43 @@ private:
   }
 
   nsIFrame* mFrame;
   gfxContext* mSourceCtx;
   RefPtr<gfxContext> mTargetCtx;
   IntPoint mTargetOffset;
 };
 
-DrawResult
+void
 nsSVGUtils::PaintFrameWithEffects(nsIFrame *aFrame,
                                   gfxContext& aContext,
                                   const gfxMatrix& aTransform,
-                                  const nsIntRect *aDirtyRect,
-                                  uint32_t aFlags)
+                                  imgDrawingParams& aImgParams,
+                                  const nsIntRect *aDirtyRect)
 {
   NS_ASSERTION(!NS_SVGDisplayListPaintingEnabled() ||
                (aFrame->GetStateBits() & NS_FRAME_IS_NONDISPLAY) ||
                aFrame->PresContext()->IsGlyph(),
                "If display lists are enabled, only painting of non-display "
                "SVG should take this code path");
 
   nsSVGDisplayableFrame* svgFrame = do_QueryFrame(aFrame);
   if (!svgFrame)
-    return DrawResult::SUCCESS;
+    return;
 
   MaskUsage maskUsage;
   DetermineMaskUsage(aFrame, true, maskUsage);
   if (maskUsage.opacity == 0.0f) {
-    return DrawResult::SUCCESS;
+    return;
   }
 
   const nsIContent* content = aFrame->GetContent();
   if (content->IsSVGElement() &&
       !static_cast<const nsSVGElement*>(content)->HasValidDimensions()) {
-    return DrawResult::SUCCESS;
+    return;
   }
 
   if (aDirtyRect &&
       !(aFrame->GetStateBits() & NS_FRAME_IS_NONDISPLAY)) {
     // Here we convert aFrame's paint bounds to outer-<svg> device space,
     // compare it to aDirtyRect, and return early if they don't intersect.
     // We don't do this optimization for nondisplay SVG since nondisplay
     // SVG doesn't maintain bounds/overflow rects.
@@ -723,26 +716,26 @@ nsSVGUtils::PaintFrameWithEffects(nsIFra
     int32_t appUnitsPerDevPx = aFrame->PresContext()->AppUnitsPerDevPixel();
     gfxMatrix tm = aTransform;
     if (aFrame->IsFrameOfType(nsIFrame::eSVG | nsIFrame::eSVGContainer)) {
       gfx::Matrix childrenOnlyTM;
       if (static_cast<nsSVGContainerFrame*>(aFrame)->
             HasChildrenOnlyTransform(&childrenOnlyTM)) {
         // Undo the children-only transform:
         if (!childrenOnlyTM.Invert()) {
-          return DrawResult::SUCCESS;
+          return;
         }
         tm = ThebesMatrix(childrenOnlyTM) * tm;
       }
     }
     nsIntRect bounds = TransformFrameRectToOuterSVG(overflowRect,
                          tm, aFrame->PresContext()).
                            ToOutsidePixels(appUnitsPerDevPx);
     if (!aDirtyRect->Intersects(bounds)) {
-      return DrawResult::SUCCESS;
+      return;
     }
   }
 
   /* SVG defines the following rendering model:
    *
    *  1. Render fill
    *  2. Render stroke
    *  3. Render markers
@@ -758,33 +751,31 @@ nsSVGUtils::PaintFrameWithEffects(nsIFra
    */
 
   /* Properties are added lazily and may have been removed by a restyle,
      so make sure all applicable ones are set again. */
   nsSVGEffects::EffectProperties effectProperties =
     nsSVGEffects::GetEffectProperties(aFrame);
   if (effectProperties.HasInvalidEffects()) {
     // Some resource is invalid. We shouldn't paint anything.
-    return DrawResult::SUCCESS;
+    return;
   }
 
   nsSVGClipPathFrame *clipPathFrame = effectProperties.GetClipPathFrame();
   nsTArray<nsSVGMaskFrame*> masks = effectProperties.GetMaskFrames();
   nsSVGMaskFrame *maskFrame = masks.IsEmpty() ? nullptr : masks[0];
 
   MixModeBlender blender(aFrame, &aContext);
   gfxContext* target = blender.ShouldCreateDrawTargetForBlend()
                        ? blender.CreateBlendTarget(aTransform) : &aContext;
 
   if (!target) {
-    return DrawResult::TEMPORARY_ERROR;
+    return;
   }
 
-  DrawResult result = DrawResult::SUCCESS;
-
   /* Check if we need to do additional operations on this child's
    * rendering, which necessitates rendering into another surface. */
   bool shouldGenerateMask = (maskUsage.opacity != 1.0f ||
                              maskUsage.shouldGenerateClipMaskLayer ||
                              maskUsage.shouldGenerateMaskLayer);
   bool shouldPushMask = false;
 
   if (shouldGenerateMask) {
@@ -797,43 +788,44 @@ nsSVGUtils::PaintFrameWithEffects(nsIFra
     //   mask:url(#id-which-does-not-exist)
     // Since we only uses nsSVGUtils with SVG elements, not like mask on an
     // HTML element, we should treat an unresolvable mask as no-mask here.
     if (maskUsage.shouldGenerateMaskLayer && maskFrame) {
       uint8_t maskMode =
         aFrame->StyleSVGReset()->mMask.mLayers[0].mMaskMode;
       nsSVGMaskFrame::MaskParams params(&aContext, aFrame, aTransform,
                                         maskUsage.opacity, &maskTransform,
-                                        maskMode, aFlags);
-      Tie(result, maskSurface) = maskFrame->GetMaskForMaskedFrame(params);
+                                        maskMode, aImgParams.imageFlags);
+      Tie(aImgParams.result, maskSurface) =
+        maskFrame->GetMaskForMaskedFrame(params);
 
       if (!maskSurface) {
         // Either entire surface is clipped out, or gfx buffer allocation
         // failure in nsSVGMaskFrame::GetMaskForMaskedFrame.
-        return result;
+        return;
       }
       shouldPushMask = true;
     }
 
     if (maskUsage.shouldGenerateClipMaskLayer) {
       Matrix clippedMaskTransform;
       DrawResult clipMaskResult;
       RefPtr<SourceSurface> clipMaskSurface;
       Tie(clipMaskResult, clipMaskSurface) =
         clipPathFrame->GetClipMask(aContext, aFrame, aTransform,
                                    &clippedMaskTransform, maskSurface,
                                    maskTransform);
-      result &= clipMaskResult;
+      aImgParams.result &= clipMaskResult;
       if (clipMaskSurface) {
         maskSurface = clipMaskSurface;
         maskTransform = clippedMaskTransform;
       } else {
         // Either entire surface is clipped out, or gfx buffer allocation
         // failure in nsSVGClipPathFrame::GetClipMask.
-        return result;
+        return;
       }
       shouldPushMask = true;
     }
 
     if (!maskUsage.shouldGenerateClipMaskLayer &&
         !maskUsage.shouldGenerateMaskLayer) {
       shouldPushMask = true;
     }
@@ -862,53 +854,50 @@ nsSVGUtils::PaintFrameWithEffects(nsIFra
   if (effectProperties.HasValidFilter()) {
     nsRegion* dirtyRegion = nullptr;
     nsRegion tmpDirtyRegion;
     if (aDirtyRect) {
       // aDirtyRect is in outer-<svg> device pixels, but the filter code needs
       // it in frame space.
       gfxMatrix userToDeviceSpace = aTransform;
       if (userToDeviceSpace.IsSingular()) {
-        return DrawResult::SUCCESS;
+        return;
       }
       gfxMatrix deviceToUserSpace = userToDeviceSpace;
       deviceToUserSpace.Invert();
       gfxRect dirtyBounds = deviceToUserSpace.TransformBounds(
                               gfxRect(aDirtyRect->x, aDirtyRect->y,
                                       aDirtyRect->width, aDirtyRect->height));
       tmpDirtyRegion =
         nsLayoutUtils::RoundGfxRectToAppRect(
           dirtyBounds, aFrame->PresContext()->AppUnitsPerCSSPixel()) -
         aFrame->GetPosition();
       dirtyRegion = &tmpDirtyRegion;
     }
 
-    SVGPaintCallback paintCallback(aFlags);
-    result =
-      nsFilterInstance::PaintFilteredFrame(aFrame, target->GetDrawTarget(),
-                                           aTransform, &paintCallback,
-                                           dirtyRegion);
+    SVGPaintCallback paintCallback;
+    nsFilterInstance::PaintFilteredFrame(aFrame, target->GetDrawTarget(),
+                                         aTransform, &paintCallback,
+                                         dirtyRegion, aImgParams);
   } else {
-    result = svgFrame->PaintSVG(*target, aTransform, aDirtyRect, aFlags);
+     svgFrame->PaintSVG(*target, aTransform, aImgParams, aDirtyRect);
   }
 
   if (maskUsage.shouldApplyClipPath || maskUsage.shouldApplyBasicShape) {
     aContext.PopClip();
   }
 
   if (shouldPushMask) {
     target->PopGroupAndBlend();
   }
 
   if (blender.ShouldCreateDrawTargetForBlend()) {
     MOZ_ASSERT(target != &aContext);
     blender.BlendToTarget();
   }
-
-  return result;
 }
 
 bool
 nsSVGUtils::HitTestClip(nsIFrame *aFrame, const gfxPoint &aPoint)
 {
   nsSVGEffects::EffectProperties props =
     nsSVGEffects::GetEffectProperties(aFrame);
   if (!props.mClipPath) {
@@ -1484,26 +1473,26 @@ nsSVGUtils::GetFallbackOrPaintColor(nsSt
       nscolor colors[2] = { color, paintIfVisited.GetColor() };
       return nsStyleContext::CombineVisitedColors(
                colors, aStyleContext->RelevantLinkVisited());
     }
   }
   return color;
 }
 
-/* static */ DrawResult
+/* static */ void
 nsSVGUtils::MakeFillPatternFor(nsIFrame* aFrame,
                                gfxContext* aContext,
                                GeneralPattern* aOutPattern,
-                               SVGContextPaint* aContextPaint,
-                               uint32_t aFlags)
+                               imgDrawingParams& aImgParams,
+                               SVGContextPaint* aContextPaint)
 {
   const nsStyleSVG* style = aFrame->StyleSVG();
   if (style->mFill.Type() == eStyleSVGPaintType_None) {
-    return DrawResult::SUCCESS;
+    return;
   }
 
   const float opacity = aFrame->StyleEffects()->mOpacity;
 
   float fillOpacity = GetOpacity(style->FillOpacitySource(),
                                  style->mFillOpacity,
                                  aContextPaint);
   if (opacity < 1.0f &&
@@ -1513,77 +1502,77 @@ nsSVGUtils::MakeFillPatternFor(nsIFrame*
     fillOpacity *= opacity;
   }
 
   const DrawTarget* dt = aContext->GetDrawTarget();
 
   nsSVGPaintServerFrame *ps =
     nsSVGEffects::GetPaintServer(aFrame, &nsStyleSVG::mFill,
                                  nsSVGEffects::FillProperty());
-  DrawResult result = DrawResult::SUCCESS;
+
   if (ps) {
     RefPtr<gfxPattern> pattern;
-    Tie(result, pattern) =
+    Tie(aImgParams.result, pattern) =
       ps->GetPaintServerPattern(aFrame, dt, aContext->CurrentMatrix(),
                                 &nsStyleSVG::mFill, fillOpacity, nullptr,
-                                aFlags);
+                                aImgParams.imageFlags);
     if (pattern) {
       pattern->CacheColorStops(dt);
       aOutPattern->Init(*pattern->GetPattern(dt));
-      return result;
+      return;
     }
   }
 
   if (aContextPaint) {
     RefPtr<gfxPattern> pattern;
     switch (style->mFill.Type()) {
     case eStyleSVGPaintType_ContextFill:
-      Tie(result, pattern) =
+      Tie(aImgParams.result, pattern) =
         aContextPaint->GetFillPattern(dt, fillOpacity,
-                                      aContext->CurrentMatrix(), aFlags);
+                                      aContext->CurrentMatrix(),
+                                      aImgParams.imageFlags);
       break;
     case eStyleSVGPaintType_ContextStroke:
-      Tie(result, pattern) =
+      Tie(aImgParams.result, pattern) =
         aContextPaint->GetStrokePattern(dt, fillOpacity,
-                                        aContext->CurrentMatrix(), aFlags);
+                                        aContext->CurrentMatrix(),
+                                        aImgParams.imageFlags);
       break;
     default:
       ;
     }
     if (pattern) {
       aOutPattern->Init(*pattern->GetPattern(dt));
-      return result;
+      return;
     }
   }
 
   if (style->mFill.GetFallbackType() == eStyleSVGFallbackType_None) {
-    return DrawResult::SUCCESS;
+    return;
   }
 
   // On failure, use the fallback colour in case we have an
   // objectBoundingBox where the width or height of the object is zero.
   // See http://www.w3.org/TR/SVG11/coords.html#ObjectBoundingBox
   Color color(Color::FromABGR(GetFallbackOrPaintColor(aFrame->StyleContext(),
                                                       &nsStyleSVG::mFill)));
   color.a *= fillOpacity;
   aOutPattern->InitColorPattern(ToDeviceColor(color));
-
-  return result;
 }
 
-/* static */ DrawResult
+/* static */ void
 nsSVGUtils::MakeStrokePatternFor(nsIFrame* aFrame,
                                  gfxContext* aContext,
                                  GeneralPattern* aOutPattern,
-                                 SVGContextPaint* aContextPaint,
-                                 uint32_t aFlags)
+                                 imgDrawingParams& aImgParams,
+                                 SVGContextPaint* aContextPaint)
 {
   const nsStyleSVG* style = aFrame->StyleSVG();
   if (style->mStroke.Type() == eStyleSVGPaintType_None) {
-    return DrawResult::SUCCESS;
+    return;
   }
 
   const float opacity = aFrame->StyleEffects()->mOpacity;
 
   float strokeOpacity = GetOpacity(style->StrokeOpacitySource(),
                                    style->mStrokeOpacity,
                                    aContextPaint);
   if (opacity < 1.0f &&
@@ -1593,65 +1582,65 @@ nsSVGUtils::MakeStrokePatternFor(nsIFram
     strokeOpacity *= opacity;
   }
 
   const DrawTarget* dt = aContext->GetDrawTarget();
 
   nsSVGPaintServerFrame *ps =
     nsSVGEffects::GetPaintServer(aFrame, &nsStyleSVG::mStroke,
                                  nsSVGEffects::StrokeProperty());
-  DrawResult result = DrawResult::SUCCESS;
+
   if (ps) {
     RefPtr<gfxPattern> pattern;
-    Tie(result, pattern) =
+    Tie(aImgParams.result, pattern) =
       ps->GetPaintServerPattern(aFrame, dt, aContext->CurrentMatrix(),
                                 &nsStyleSVG::mStroke, strokeOpacity, nullptr,
-                                aFlags);
+                                aImgParams.imageFlags);
     if (pattern) {
       pattern->CacheColorStops(dt);
       aOutPattern->Init(*pattern->GetPattern(dt));
-      return result;
+      return;
     }
   }
 
   if (aContextPaint) {
     RefPtr<gfxPattern> pattern;
     switch (style->mStroke.Type()) {
     case eStyleSVGPaintType_ContextFill:
-      Tie(result, pattern) =
+      Tie(aImgParams.result, pattern) =
         aContextPaint->GetFillPattern(dt, strokeOpacity,
-                                      aContext->CurrentMatrix(), aFlags);
+                                      aContext->CurrentMatrix(),
+                                      aImgParams.imageFlags);
       break;
     case eStyleSVGPaintType_ContextStroke:
-      Tie(result, pattern) =
+      Tie(aImgParams.result, pattern) =
         aContextPaint->GetStrokePattern(dt, strokeOpacity,
-                                        aContext->CurrentMatrix(), aFlags);
+                                        aContext->CurrentMatrix(),
+                                        aImgParams.imageFlags);
       break;
     default:
       ;
     }
     if (pattern) {
       aOutPattern->Init(*pattern->GetPattern(dt));
-      return result;
+      return;
     }
   }
 
   if (style->mStroke.GetFallbackType() == eStyleSVGFallbackType_None) {
-    return DrawResult::SUCCESS;
+    return;
   }
 
   // On failure, use the fallback colour in case we have an
   // objectBoundingBox where the width or height of the object is zero.
   // See http://www.w3.org/TR/SVG11/coords.html#ObjectBoundingBox
   Color color(Color::FromABGR(GetFallbackOrPaintColor(aFrame->StyleContext(),
                                                       &nsStyleSVG::mStroke)));
   color.a *= strokeOpacity;
   aOutPattern->InitColorPattern(ToDeviceColor(color));
-
-  return DrawResult::SUCCESS;
 }
 
 /* static */ float
 nsSVGUtils::GetOpacity(nsStyleSVGOpacitySource aOpacityType,
                        const float& aOpacity,
                        SVGContextPaint *aContextPaint)
 {
   float opacity = 1.0f;
@@ -1871,33 +1860,36 @@ nsSVGUtils::GetGeometryHitTestFlags(nsIF
   default:
     NS_ERROR("not reached");
     break;
   }
 
   return flags;
 }
 
-bool
+void
 nsSVGUtils::PaintSVGGlyph(Element* aElement, gfxContext* aContext)
 {
   nsIFrame* frame = aElement->GetPrimaryFrame();
   nsSVGDisplayableFrame* svgFrame = do_QueryFrame(frame);
   if (!svgFrame) {
-    return false;
+    return;
   }
   gfxMatrix m;
   if (frame->GetContent()->IsSVGElement()) {
     // PaintSVG() expects the passed transform to be the transform to its own
     // SVG user space, so we need to account for any 'transform' attribute:
     m = static_cast<nsSVGElement*>(frame->GetContent())->
           PrependLocalTransformsTo(gfxMatrix(), eUserSpaceToParent);
   }
-  DrawResult result = svgFrame->PaintSVG(*aContext, m);
-  return (result == DrawResult::SUCCESS);
+
+  // SVG-in-OpenType is not allowed to paint exteral resources, so we can
+  // just pass a dummy params into PatintSVG.
+  imgDrawingParams dummy;
+  svgFrame->PaintSVG(*aContext, m, dummy);
 }
 
 bool
 nsSVGUtils::GetSVGGlyphExtents(Element* aElement,
                                const gfxMatrix& aSVGToAppSpace,
                                gfxRect* aResult)
 {
   nsIFrame* frame = aElement->GetPrimaryFrame();
--- a/layout/svg/nsSVGUtils.h
+++ b/layout/svg/nsSVGUtils.h
@@ -188,16 +188,17 @@ public:
   typedef mozilla::gfx::DrawTarget DrawTarget;
   typedef mozilla::gfx::FillRule FillRule;
   typedef mozilla::gfx::GeneralPattern GeneralPattern;
   typedef mozilla::gfx::Size Size;
   typedef mozilla::SVGContextPaint SVGContextPaint;
   typedef mozilla::SVGContextPaintImpl SVGContextPaintImpl;
   typedef mozilla::SVGGeometryFrame SVGGeometryFrame;
   typedef mozilla::image::DrawResult DrawResult;
+  typedef mozilla::image::imgDrawingParams imgDrawingParams;
 
   static void Init();
 
   NS_DECLARE_FRAME_PROPERTY_DELETABLE(ObjectBoundingBoxProperty, gfxRect)
 
   /**
    * Gets the nearest nsSVGInnerSVGFrame or nsSVGOuterSVGFrame frame. aFrame
    * must be an SVG frame.
@@ -285,21 +286,21 @@ public:
    * @param aRect gets a rectangle in app units
    * @return the outer SVG frame which aRect is relative to
    */
   static nsIFrame* GetOuterSVGFrameAndCoveredRegion(nsIFrame* aFrame,
                                                     nsRect* aRect);
 
   /* Paint SVG frame with SVG effects - aDirtyRect is the area being
    * redrawn, in device pixel coordinates relative to the outer svg */
-  static DrawResult PaintFrameWithEffects(nsIFrame *aFrame,
-                                          gfxContext& aContext,
-                                          const gfxMatrix& aTransform,
-                                          const nsIntRect *aDirtyRect = nullptr,
-                                          uint32_t aFlags = 0);
+  static void PaintFrameWithEffects(nsIFrame *aFrame,
+                                    gfxContext& aContext,
+                                    const gfxMatrix& aTransform,
+                                    imgDrawingParams& aImgParams,
+                                    const nsIntRect *aDirtyRect = nullptr);
 
   /* Hit testing - check if point hits the clipPath of indicated
    * frame.  Returns true if no clipPath set. */
   static bool HitTestClip(nsIFrame *aFrame, const gfxPoint &aPoint);
 
   /**
    * Hit testing - check if point hits any children of aFrame.  aPoint is
    * expected to be in the coordinate space established by aFrame for its
@@ -505,28 +506,29 @@ public:
   {
     return NS_lround(std::max(double(INT32_MIN),
                             std::min(double(INT32_MAX), aVal)));
   }
 
   static nscolor GetFallbackOrPaintColor(nsStyleContext *aStyleContext,
                                          nsStyleSVGPaint nsStyleSVG::*aFillOrStroke);
 
-  static DrawResult MakeFillPatternFor(nsIFrame *aFrame,
-                                       gfxContext* aContext,
-                                       GeneralPattern* aOutPattern,
-                                       SVGContextPaint* aContextPaint = nullptr,
-                                       uint32_t aFlags = 0);
+  static void
+  MakeFillPatternFor(nsIFrame *aFrame,
+                     gfxContext* aContext,
+                     GeneralPattern* aOutPattern,
+                     imgDrawingParams& aImgParams,
+                     SVGContextPaint* aContextPaint = nullptr);
 
-  static DrawResult
+  static void
   MakeStrokePatternFor(nsIFrame* aFrame,
                        gfxContext* aContext,
                        GeneralPattern* aOutPattern,
-                       SVGContextPaint* aContextPaint = nullptr,
-                       uint32_t aFlags = 0);
+                       imgDrawingParams& aImgParams,
+                       SVGContextPaint* aContextPaint = nullptr);
 
   static float GetOpacity(nsStyleSVGOpacitySource aOpacityType,
                           const float& aOpacity,
                           SVGContextPaint* aContextPaint);
 
   /*
    * @return false if there is no stroke
    */
@@ -562,17 +564,17 @@ public:
   }
 
   /**
    * Render a SVG glyph.
    * @param aElement the SVG glyph element to render
    * @param aContext the thebes aContext to draw to
    * @return true if rendering succeeded
    */
-  static bool PaintSVGGlyph(Element* aElement, gfxContext* aContext);
+  static void PaintSVGGlyph(Element* aElement, gfxContext* aContext);
 
   /**
    * Get the extents of a SVG glyph.
    * @param aElement the SVG glyph element
    * @param aSVGToAppSpace the matrix mapping the SVG glyph space to the
    *   target context space
    * @param aResult the result (valid when true is returned)
    * @return true if calculating the extents succeeded