Bug 1351440 - Part 4. Pass imgDrawingParams to nsSVGPaintServerFrame::GetPaintServerPattern. draft
authorcku <cku@mozilla.com>
Tue, 09 May 2017 02:14:08 +0800
changeset 580454 554cb17c1d70e6a34eadf2102a7d8fceda22e9e5
parent 580453 2d1c92fe56094d879542572e774b197f39f9c7a0
child 580455 1ca51700dd2c5da21e502ea370b96c7f8d487892
push id59558
push userbmo:cku@mozilla.com
push dateThu, 18 May 2017 14:49:17 +0000
bugs1351440
milestone55.0a1
Bug 1351440 - Part 4. Pass imgDrawingParams to nsSVGPaintServerFrame::GetPaintServerPattern. The reason of this change is the same as for Part 2, except that this commit fixes nsSVGPaintServerFrame::GetPaintServerPattern rather than PaintSVG. Commit-ID: 691YrKZ0Lm9 MozReview-Commit-ID: KSnFhCndFUk
gfx/thebes/gfxFont.cpp
gfx/thebes/gfxSVGGlyphs.h
layout/svg/SVGContextPaint.cpp
layout/svg/SVGContextPaint.h
layout/svg/SVGTextFrame.cpp
layout/svg/SVGTextFrame.h
layout/svg/nsFilterInstance.h
layout/svg/nsSVGClipPathFrame.cpp
layout/svg/nsSVGClipPathFrame.h
layout/svg/nsSVGDisplayableFrame.h
layout/svg/nsSVGGradientFrame.cpp
layout/svg/nsSVGGradientFrame.h
layout/svg/nsSVGIntegrationUtils.cpp
layout/svg/nsSVGIntegrationUtils.h
layout/svg/nsSVGMaskFrame.h
layout/svg/nsSVGPaintServerFrame.h
layout/svg/nsSVGPatternFrame.cpp
layout/svg/nsSVGPatternFrame.h
layout/svg/nsSVGUtils.cpp
layout/svg/nsSVGUtils.h
--- a/gfx/thebes/gfxFont.cpp
+++ b/gfx/thebes/gfxFont.cpp
@@ -1575,16 +1575,18 @@ static AntialiasMode Get2DAAMode(gfxFont
     return AntialiasMode::NONE;
   default:
     return AntialiasMode::DEFAULT;
   }
 }
 
 class GlyphBufferAzure
 {
+    typedef mozilla::image::imgDrawingParams imgDrawingParams;
+
 public:
     GlyphBufferAzure(const TextRunDrawParams& aRunParams,
                      const FontDrawParams&    aFontParams)
         : mRunParams(aRunParams)
         , mFontParams(aFontParams)
         , mNumGlyphs(0)
     {
     }
@@ -1644,23 +1646,22 @@ private:
 
         gfxContext::AzureState state = mRunParams.context->CurrentState();
         if (mRunParams.drawMode & DrawMode::GLYPH_FILL) {
             if (state.pattern || mFontParams.contextPaint) {
                 Pattern *pat;
 
                 RefPtr<gfxPattern> fillPattern;
                 if (mFontParams.contextPaint) {
-                  mozilla::image::DrawResult result = mozilla::image::DrawResult::SUCCESS;
-                  Tie(result, fillPattern) =
+                  imgDrawingParams imgParams;
+                  fillPattern =
                     mFontParams.contextPaint->GetFillPattern(
                                           mRunParams.context->GetDrawTarget(),
-                                          mRunParams.context->CurrentMatrix());
-                  // XXX cku Flush should return result to the caller?
-                  Unused << result;
+                                          mRunParams.context->CurrentMatrix(),
+                                          imgParams);
                 }
                 if (!fillPattern) {
                     if (state.pattern) {
                         pat = state.pattern->GetPattern(mRunParams.dt,
                                       state.patternTransformChanged ?
                                           &state.patternTransform : nullptr);
                     } else {
                         pat = nullptr;
--- a/gfx/thebes/gfxSVGGlyphs.h
+++ b/gfx/thebes/gfxSVGGlyphs.h
@@ -197,45 +197,45 @@ public:
                           const gfxMatrix& aCTM) :
         mFillPattern(aFillPattern ? aFillPattern : new gfxPattern(sZero)),
         mStrokePattern(aStrokePattern ? aStrokePattern : new gfxPattern(sZero))
     {
         mFillMatrix = SetupDeviceToPatternMatrix(aFillPattern, aCTM);
         mStrokeMatrix = SetupDeviceToPatternMatrix(aStrokePattern, aCTM);
     }
 
-    mozilla::Pair<DrawResult, RefPtr<gfxPattern>>
+    already_AddRefed<gfxPattern>
     GetFillPattern(const DrawTarget* aDrawTarget,
                    float aOpacity,
                    const gfxMatrix& aCTM,
-                   uint32_t aFlags) {
+                   imgDrawingParams& aImgParams) override {
         if (mFillPattern) {
             mFillPattern->SetMatrix(aCTM * mFillMatrix);
         }
         RefPtr<gfxPattern> fillPattern = mFillPattern;
-        return MakePair(DrawResult::SUCCESS, Move(fillPattern));
+        return fillPattern.forget();
     }
 
-    mozilla::Pair<DrawResult, RefPtr<gfxPattern>>
+    already_AddRefed<gfxPattern>
     GetStrokePattern(const DrawTarget* aDrawTarget,
                      float aOpacity,
                      const gfxMatrix& aCTM,
-                     uint32_t aFlags) {
+                     imgDrawingParams& aImgParams) override {
         if (mStrokePattern) {
             mStrokePattern->SetMatrix(aCTM * mStrokeMatrix);
         }
         RefPtr<gfxPattern> strokePattern = mStrokePattern;
-        return MakePair(DrawResult::SUCCESS, Move(strokePattern));
+        return strokePattern.forget();
     }
 
-    float GetFillOpacity() const {
+    float GetFillOpacity() const override {
         return mFillPattern ? 1.0f : 0.0f;
     }
 
-    float GetStrokeOpacity() const {
+    float GetStrokeOpacity() const override {
         return mStrokePattern ? 1.0f : 0.0f;
     }
 
 private:
     RefPtr<gfxPattern> mFillPattern;
     RefPtr<gfxPattern> mStrokePattern;
 
     // Device space to pattern space transforms
--- a/layout/svg/SVGContextPaint.cpp
+++ b/layout/svg/SVGContextPaint.cpp
@@ -13,16 +13,18 @@
 #include "nsSVGEffects.h"
 #include "nsSVGPaintServerFrame.h"
 
 using namespace mozilla::gfx;
 using namespace mozilla::image;
 
 namespace mozilla {
 
+using image::imgDrawingParams;
+
 /* static */ bool
 SVGContextPaint::IsAllowedForImageFromURI(nsIURI* aURI)
 {
   static bool sEnabledForContent = false;
   static bool sEnabledForContentCached = false;
 
   if (!sEnabledForContentCached) {
     Preferences::AddBoolVarCache(&sEnabledForContent,
@@ -69,120 +71,116 @@ SVGContextPaint::IsAllowedForImageFromUR
  * fill or stroke pattern. Will also set the paint opacity to transparent if
  * the paint is set to "none".
  * @param aOuterContextPaint pattern information from the outer text context
  * @param aTargetPaint where to store the current pattern information
  * @param aFillOrStroke member pointer to the paint we are setting up
  * @param aProperty the frame property descriptor of the fill or stroke paint
  *   server frame
  */
-static DrawResult
+static void
 SetupInheritablePaint(const DrawTarget* aDrawTarget,
                       const gfxMatrix& aContextMatrix,
                       nsIFrame* aFrame,
                       float& aOpacity,
                       SVGContextPaint* aOuterContextPaint,
                       SVGContextPaintImpl::Paint& aTargetPaint,
                       nsStyleSVGPaint nsStyleSVG::*aFillOrStroke,
-                      nsSVGEffects::PaintingPropertyDescriptor aProperty)
+                      nsSVGEffects::PaintingPropertyDescriptor aProperty,
+                      imgDrawingParams& aImgParams)
 {
   const nsStyleSVG *style = aFrame->StyleSVG();
   nsSVGPaintServerFrame *ps =
     nsSVGEffects::GetPaintServer(aFrame, aFillOrStroke, aProperty);
 
-  DrawResult result = DrawResult::SUCCESS;
   if (ps) {
-    RefPtr<gfxPattern> pattern;
-    Tie(result, pattern) =
+    RefPtr<gfxPattern> pattern =
       ps->GetPaintServerPattern(aFrame, aDrawTarget, aContextMatrix,
-                                aFillOrStroke, aOpacity);
+                                aFillOrStroke, aOpacity, aImgParams);
 
     if (pattern) {
       aTargetPaint.SetPaintServer(aFrame, aContextMatrix, ps);
-      return result;
+      return;
     }
   }
 
   if (aOuterContextPaint) {
     RefPtr<gfxPattern> pattern;
     switch ((style->*aFillOrStroke).Type()) {
     case eStyleSVGPaintType_ContextFill:
-      Tie(result, pattern) =
+      pattern =
         aOuterContextPaint->GetFillPattern(aDrawTarget, aOpacity,
-                                           aContextMatrix);
+                                           aContextMatrix, aImgParams);
       break;
     case eStyleSVGPaintType_ContextStroke:
-       Tie(result, pattern) =
+       pattern =
          aOuterContextPaint->GetStrokePattern(aDrawTarget, aOpacity,
-                                              aContextMatrix);
+                                              aContextMatrix, aImgParams);
       break;
     default:
       ;
     }
     if (pattern) {
       aTargetPaint.SetContextPaint(aOuterContextPaint, (style->*aFillOrStroke).Type());
-      return result;
+      return;
     }
   }
 
   nscolor color =
     nsSVGUtils::GetFallbackOrPaintColor(aFrame->StyleContext(), aFillOrStroke);
   aTargetPaint.SetColor(color);
-
-  return result;
 }
 
-mozilla::Pair<DrawResult, DrawMode>
+DrawMode
 SVGContextPaintImpl::Init(const DrawTarget* aDrawTarget,
                           const gfxMatrix& aContextMatrix,
                           nsIFrame* aFrame,
-                          SVGContextPaint* aOuterContextPaint)
+                          SVGContextPaint* aOuterContextPaint,
+                          imgDrawingParams& aImgParams)
 {
   DrawMode toDraw = DrawMode(0);
 
   const nsStyleSVG *style = aFrame->StyleSVG();
-  DrawResult result = DrawResult::SUCCESS;
 
   // fill:
   if (style->mFill.Type() == eStyleSVGPaintType_None) {
     SetFillOpacity(0.0f);
   } else {
     float opacity = nsSVGUtils::GetOpacity(style->FillOpacitySource(),
                                            style->mFillOpacity,
                                            aOuterContextPaint);
 
-    result &= SetupInheritablePaint(aDrawTarget, aContextMatrix, aFrame,
-                                    opacity, aOuterContextPaint,
-                                    mFillPaint, &nsStyleSVG::mFill,
-                                    nsSVGEffects::FillProperty());
+    SetupInheritablePaint(aDrawTarget, aContextMatrix, aFrame, opacity,
+                          aOuterContextPaint, mFillPaint, &nsStyleSVG::mFill,
+                          nsSVGEffects::FillProperty(), aImgParams);
 
     SetFillOpacity(opacity);
 
     toDraw |= DrawMode::GLYPH_FILL;
   }
 
   // stroke:
   if (style->mStroke.Type() == eStyleSVGPaintType_None) {
     SetStrokeOpacity(0.0f);
   } else {
     float opacity = nsSVGUtils::GetOpacity(style->StrokeOpacitySource(),
                                            style->mStrokeOpacity,
                                            aOuterContextPaint);
 
-    result &= SetupInheritablePaint(aDrawTarget, aContextMatrix, aFrame,
-                                    opacity, aOuterContextPaint,
-                                    mStrokePaint, &nsStyleSVG::mStroke,
-                                    nsSVGEffects::StrokeProperty());
+    SetupInheritablePaint(aDrawTarget, aContextMatrix, aFrame, opacity,
+                          aOuterContextPaint, mStrokePaint,
+                          &nsStyleSVG::mStroke, nsSVGEffects::StrokeProperty(),
+                          aImgParams);
 
     SetStrokeOpacity(opacity);
 
     toDraw |= DrawMode::GLYPH_STROKE;
   }
 
-  return MakePair(result, toDraw);
+  return toDraw;
 }
 
 void
 SVGContextPaint::InitStrokeGeometry(gfxContext* aContext,
                                     float devUnitsPerSVGUnit)
 {
   mStrokeWidth = aContext->CurrentLineWidth() / devUnitsPerSVGUnit;
   aContext->CurrentDash(mDashes, &mDashOffset);
@@ -211,107 +209,107 @@ SVGContextPaint::GetContextPaint(nsICont
   // bit of a headache so for now we punt on that, don't reapply the constness
   // to the SVGContextPaint here, and trust that no one will add code that
   // actually modifies the object.
 
   return static_cast<SVGContextPaint*>(
            ownerDoc->GetProperty(nsGkAtoms::svgContextPaint));
 }
 
-mozilla::Pair<DrawResult, RefPtr<gfxPattern>>
+already_AddRefed<gfxPattern>
 SVGContextPaintImpl::GetFillPattern(const DrawTarget* aDrawTarget,
                                     float aOpacity,
                                     const gfxMatrix& aCTM,
-                                    uint32_t aFlags)
+                                    imgDrawingParams& aImgParams)
 {
   return mFillPaint.GetPattern(aDrawTarget, aOpacity, &nsStyleSVG::mFill, aCTM,
-                               aFlags);
+                               aImgParams);
 }
 
-mozilla::Pair<DrawResult, RefPtr<gfxPattern>>
+already_AddRefed<gfxPattern>
 SVGContextPaintImpl::GetStrokePattern(const DrawTarget* aDrawTarget,
                                       float aOpacity,
                                       const gfxMatrix& aCTM,
-                                      uint32_t aFlags)
+                                      imgDrawingParams& aImgParams)
 {
   return mStrokePaint.GetPattern(aDrawTarget, aOpacity, &nsStyleSVG::mStroke,
-                                 aCTM, aFlags);
+                                 aCTM, aImgParams);
 }
 
-mozilla::Pair<DrawResult, RefPtr<gfxPattern>>
+already_AddRefed<gfxPattern>
 SVGContextPaintImpl::Paint::GetPattern(const DrawTarget* aDrawTarget,
                                        float aOpacity,
                                        nsStyleSVGPaint nsStyleSVG::*aFillOrStroke,
                                        const gfxMatrix& aCTM,
-                                       uint32_t aFlags)
+                                       imgDrawingParams& aImgParams)
 {
   RefPtr<gfxPattern> pattern;
   if (mPatternCache.Get(aOpacity, getter_AddRefs(pattern))) {
     // Set the pattern matrix just in case it was messed with by a previous
     // caller. We should get the same matrix each time a pattern is constructed
     // so this should be fine.
     pattern->SetMatrix(aCTM * mPatternMatrix);
-    return MakePair(DrawResult::SUCCESS, Move(pattern));
+    return pattern.forget();
   }
 
-  DrawResult result = DrawResult::SUCCESS;
   switch (mPaintType) {
   case eStyleSVGPaintType_None:
     pattern = new gfxPattern(Color());
     mPatternMatrix = gfxMatrix();
     break;
   case eStyleSVGPaintType_Color: {
     Color color = Color::FromABGR(mPaintDefinition.mColor);
     color.a *= aOpacity;
     pattern = new gfxPattern(color);
     mPatternMatrix = gfxMatrix();
     break;
   }
   case eStyleSVGPaintType_Server:
-    Tie(result, pattern) =
+    pattern =
       mPaintDefinition.mPaintServerFrame->GetPaintServerPattern(mFrame,
                                                                 aDrawTarget,
                                                                 mContextMatrix,
                                                                 aFillOrStroke,
                                                                 aOpacity,
-                                                                nullptr,
-                                                                aFlags);
+                                                                aImgParams);
     {
       // m maps original-user-space to pattern space
       gfxMatrix m = pattern->GetMatrix();
       gfxMatrix deviceToOriginalUserSpace = mContextMatrix;
       if (!deviceToOriginalUserSpace.Invert()) {
-        return MakePair(DrawResult::SUCCESS, RefPtr<gfxPattern>());
+        return nullptr;
       }
       // mPatternMatrix maps device space to pattern space via original user space
       mPatternMatrix = deviceToOriginalUserSpace * m;
     }
     pattern->SetMatrix(aCTM * mPatternMatrix);
     break;
   case eStyleSVGPaintType_ContextFill:
-    Tie(result, pattern) =
+    pattern =
       mPaintDefinition.mContextPaint->GetFillPattern(aDrawTarget,
-                                                     aOpacity, aCTM, aFlags);
+                                                     aOpacity, aCTM,
+                                                     aImgParams);
     // Don't cache this. mContextPaint will have cached it anyway. If we
     // cache it, we'll have to compute mPatternMatrix, which is annoying.
-    return MakePair(result, Move(pattern));
+    return pattern.forget();
   case eStyleSVGPaintType_ContextStroke:
-    Tie(result, pattern) =
+    pattern =
       mPaintDefinition.mContextPaint->GetStrokePattern(aDrawTarget,
-                                                       aOpacity, aCTM, aFlags);
+                                                       aOpacity, aCTM,
+                                                       aImgParams);
     // Don't cache this. mContextPaint will have cached it anyway. If we
     // cache it, we'll have to compute mPatternMatrix, which is annoying.
-    return MakePair(result, Move(pattern));
+    return pattern.forget();
   default:
     MOZ_ASSERT(false, "invalid paint type");
-    return MakePair(DrawResult::SUCCESS, RefPtr<gfxPattern>());
+    return nullptr;
   }
 
   mPatternCache.Put(aOpacity, pattern);
-  return MakePair(result, Move(pattern));
+  return pattern.forget();
 }
 
 AutoSetRestoreSVGContextPaint::AutoSetRestoreSVGContextPaint(
                                  const SVGContextPaint* aContextPaint,
                                  nsIDocument* aSVGDocument)
   : mSVGDocument(aSVGDocument)
   , mOuterContextPaint(aSVGDocument->GetProperty(nsGkAtoms::svgContextPaint))
 {
@@ -343,47 +341,45 @@ AutoSetRestoreSVGContextPaint::~AutoSetR
 
     NS_WARNING_ASSERTION(NS_SUCCEEDED(res), "Failed to restore context paint");
   }
 }
 
 
 // SVGEmbeddingContextPaint
 
-mozilla::Pair<DrawResult, RefPtr<gfxPattern>>
+already_AddRefed<gfxPattern>
 SVGEmbeddingContextPaint::GetFillPattern(const DrawTarget* aDrawTarget,
                                          float aFillOpacity,
                                          const gfxMatrix& aCTM,
-                                         uint32_t aFlags)
+                                         imgDrawingParams& aImgParams)
 {
   if (!mFill) {
-    return MakePair(DrawResult::SUCCESS, RefPtr<gfxPattern>());
+    return nullptr;
   }
   // The gfxPattern that we create below depends on aFillOpacity, and since
   // different elements in the SVG image may pass in different values for
   // fill opacities we don't try to cache the gfxPattern that we create.
   Color fill = *mFill;
   fill.a *= aFillOpacity;
-  RefPtr<gfxPattern> patern = new gfxPattern(fill);
-  return MakePair(DrawResult::SUCCESS, Move(patern));
+  return do_AddRef(new gfxPattern(fill));
 }
 
-mozilla::Pair<DrawResult, RefPtr<gfxPattern>>
+already_AddRefed<gfxPattern>
 SVGEmbeddingContextPaint::GetStrokePattern(const DrawTarget* aDrawTarget,
                                            float aStrokeOpacity,
                                            const gfxMatrix& aCTM,
-                                           uint32_t aFlags)
+                                           imgDrawingParams& aImgParams)
 {
   if (!mStroke) {
-    return MakePair(DrawResult::SUCCESS, RefPtr<gfxPattern>());
+    return nullptr;
   }
   Color stroke = *mStroke;
   stroke.a *= aStrokeOpacity;
-  RefPtr<gfxPattern> patern = new gfxPattern(stroke);
-  return MakePair(DrawResult::SUCCESS, Move(patern));
+  return do_AddRef(new gfxPattern(stroke));
 }
 
 uint32_t
 SVGEmbeddingContextPaint::Hash() const
 {
   uint32_t hash = 0;
 
   if (mFill) {
--- a/layout/svg/SVGContextPaint.h
+++ b/layout/svg/SVGContextPaint.h
@@ -45,52 +45,52 @@ namespace mozilla {
  * duration of a function call.
  * XXX Note: SVGImageContext doesn't actually have a SVGContextPaint member yet,
  * but it will in a later patch in the patch series that added this comment.
  */
 class SVGContextPaint : public RefCounted<SVGContextPaint>
 {
 protected:
   typedef mozilla::gfx::DrawTarget DrawTarget;
+  typedef mozilla::image::imgDrawingParams imgDrawingParams;
 
   SVGContextPaint()
     : mDashOffset(0.0f)
     , mStrokeWidth(0.0f)
   {}
 
 public:
-  typedef image::DrawResult DrawResult;
 
   MOZ_DECLARE_REFCOUNTED_TYPENAME(SVGContextPaint)
 
   virtual ~SVGContextPaint() {}
 
-  virtual mozilla::Pair<DrawResult, RefPtr<gfxPattern>>
+  virtual already_AddRefed<gfxPattern>
   GetFillPattern(const DrawTarget* aDrawTarget,
                  float aOpacity,
                  const gfxMatrix& aCTM,
-                 uint32_t aFlags = 0) = 0;
-  virtual mozilla::Pair<DrawResult, RefPtr<gfxPattern>>
+                 imgDrawingParams& aImgParams) = 0;
+  virtual already_AddRefed<gfxPattern>
   GetStrokePattern(const DrawTarget* aDrawTarget,
                    float aOpacity,
                    const gfxMatrix& aCTM,
-                   uint32_t aFlags = 0) = 0;
+                   imgDrawingParams& aImgParams) = 0;
   virtual float GetFillOpacity() const = 0;
   virtual float GetStrokeOpacity() const = 0;
 
-  mozilla::Pair<DrawResult, RefPtr<gfxPattern>>
+  already_AddRefed<gfxPattern>
   GetFillPattern(const DrawTarget* aDrawTarget, const gfxMatrix& aCTM,
-                 uint32_t aFlags = 0) {
-    return GetFillPattern(aDrawTarget, GetFillOpacity(), aCTM, aFlags);
+                 imgDrawingParams& aImgParams) {
+    return GetFillPattern(aDrawTarget, GetFillOpacity(), aCTM, aImgParams);
   }
 
-  mozilla::Pair<DrawResult, RefPtr<gfxPattern>>
+  already_AddRefed<gfxPattern>
   GetStrokePattern(const DrawTarget* aDrawTarget, const gfxMatrix& aCTM,
-                   uint32_t aFlags) {
-    return GetStrokePattern(aDrawTarget, GetStrokeOpacity(), aCTM, aFlags);
+                   imgDrawingParams& aImgParams) {
+    return GetStrokePattern(aDrawTarget, GetStrokeOpacity(), aCTM, aImgParams);
   }
 
   static SVGContextPaint* GetContextPaint(nsIContent* aContent);
 
   // XXX This gets the geometry params from the gfxContext.  We should get that
   // information from the actual paint context!
   void InitStrokeGeometry(gfxContext *aContext,
                           float devUnitsPerSVGUnit);
@@ -153,34 +153,34 @@ private:
  * other sub-class (SimpleTextContextPaint).
  */
 struct SVGContextPaintImpl : public SVGContextPaint
 {
 protected:
   typedef mozilla::gfx::DrawTarget DrawTarget;
 
 public:
-  typedef mozilla::image::DrawResult DrawResult;
 
-  mozilla::Pair<DrawResult, DrawMode>
+  DrawMode
   Init(const DrawTarget* aDrawTarget,
        const gfxMatrix& aContextMatrix,
        nsIFrame* aFrame,
-       SVGContextPaint* aOuterContextPaint);
+       SVGContextPaint* aOuterContextPaint,
+       imgDrawingParams& aImgParams);
 
-  mozilla::Pair<DrawResult, RefPtr<gfxPattern>>
+  already_AddRefed<gfxPattern>
   GetFillPattern(const DrawTarget* aDrawTarget,
                  float aOpacity,
                  const gfxMatrix& aCTM,
-                 uint32_t aFlags) override;
-  mozilla::Pair<DrawResult, RefPtr<gfxPattern>>
+                 imgDrawingParams& aImgParams) override;
+  already_AddRefed<gfxPattern>
   GetStrokePattern(const DrawTarget* aDrawTarget,
                    float aOpacity,
                    const gfxMatrix& aCTM,
-                   uint32_t aFlags) override;
+                   imgDrawingParams& aImgParams) override;
 
   void SetFillOpacity(float aOpacity) { mFillOpacity = aOpacity; }
   float GetFillOpacity() const override { return mFillOpacity; }
 
   void SetStrokeOpacity(float aOpacity) { mStrokeOpacity = aOpacity; }
   float GetStrokeOpacity() const override { return mStrokeOpacity; }
 
   struct Paint {
@@ -220,22 +220,22 @@ public:
     // CTM defining the user space for the pattern we will use.
     gfxMatrix mContextMatrix;
     nsStyleSVGPaintType mPaintType;
 
     // Device-space-to-pattern-space
     gfxMatrix mPatternMatrix;
     nsRefPtrHashtable<nsFloatHashKey, gfxPattern> mPatternCache;
 
-    mozilla::Pair<DrawResult, RefPtr<gfxPattern>>
+    already_AddRefed<gfxPattern>
     GetPattern(const DrawTarget* aDrawTarget,
                float aOpacity,
                nsStyleSVGPaint nsStyleSVG::*aFillOrStroke,
                const gfxMatrix& aCTM,
-               uint32_t aFlags);
+               imgDrawingParams& aImgParams);
   };
 
   Paint mFillPaint;
   Paint mStrokePaint;
 
   float mFillOpacity;
   float mStrokeOpacity;
 };
@@ -244,17 +244,16 @@ public:
  * This class is used to pass context paint to an SVG image when an element
  * references that image (e.g. via HTML <img> or SVG <image>, or by referencing
  * it from a CSS property such as 'background-image').  In this case we only
  * support context colors and not paint servers.
  */
 class SVGEmbeddingContextPaint : public SVGContextPaint
 {
   typedef gfx::Color Color;
-  typedef mozilla::image::DrawResult DrawResult;
 
 public:
   SVGEmbeddingContextPaint() {}
 
   bool operator==(const SVGEmbeddingContextPaint& aOther) const {
     MOZ_ASSERT(GetStrokeWidth() == aOther.GetStrokeWidth() &&
                GetStrokeDashOffset() == aOther.GetStrokeDashOffset() &&
                GetStrokeDashArray() == aOther.GetStrokeDashArray(),
@@ -268,26 +267,26 @@ public:
   }
   void SetStroke(nscolor aStroke) {
     mStroke.emplace(gfx::ToDeviceColor(aStroke));
   }
 
   /**
    * Returns a pattern of type PatternType::COLOR, or else nullptr.
    */
-  mozilla::Pair<DrawResult, RefPtr<gfxPattern>>
+  already_AddRefed<gfxPattern>
   GetFillPattern(const DrawTarget* aDrawTarget, float aFillOpacity,
-                 const gfxMatrix& aCTM, uint32_t aFlags = 0) override;
+                 const gfxMatrix& aCTM, imgDrawingParams& aImgParams) override;
 
   /**
    * Returns a pattern of type PatternType::COLOR, or else nullptr.
    */
-  mozilla::Pair<DrawResult, RefPtr<gfxPattern>>
+  already_AddRefed<gfxPattern>
   GetStrokePattern(const DrawTarget* aDrawTarget, float aStrokeOpacity,
-                   const gfxMatrix& aCTM, uint32_t aFlags = 0) override;
+                   const gfxMatrix& aCTM, imgDrawingParams& aImgParams) override;
 
   float GetFillOpacity() const override {
     // Always 1.0f since we don't currently allow 'context-fill-opacity'
     return 1.0f;
   };
 
   float GetStrokeOpacity() const override {
     // Always 1.0f since we don't currently allow 'context-stroke-opacity'
--- a/layout/svg/SVGTextFrame.cpp
+++ b/layout/svg/SVGTextFrame.cpp
@@ -3661,22 +3661,20 @@ SVGTextFrame::PaintSVG(gfxContext& aCont
     // need to ignore.
     SVGCharClipDisplayItem item(run);
 
     // Set up the fill and stroke so that SVG glyphs can get painted correctly
     // when they use context-fill etc.
     aContext.SetMatrix(initialMatrix);
 
     RefPtr<SVGContextPaintImpl> contextPaint = new SVGContextPaintImpl();
-    DrawMode drawMode;
-    DrawResult result = DrawResult::SUCCESS;
-    Tie(result, drawMode) = contextPaint->Init(&aDrawTarget,
-                                               aContext.CurrentMatrix(),
-                                               frame, outerContextPaint);
-    aImgParams.result &= result;
+    DrawMode drawMode = contextPaint->Init(&aDrawTarget,
+                                           aContext.CurrentMatrix(),
+                                           frame, outerContextPaint,
+                                           aImgParams);
     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.
--- a/layout/svg/SVGTextFrame.h
+++ b/layout/svg/SVGTextFrame.h
@@ -185,17 +185,16 @@ class SVGTextFrame final : public nsSVGD
   friend class mozilla::TextRenderedRunIterator;
   friend class MutationObserver;
   friend class nsDisplaySVGText;
 
   typedef gfxTextRun::Range Range;
   typedef mozilla::gfx::DrawTarget DrawTarget;
   typedef mozilla::gfx::Path Path;
   typedef mozilla::gfx::Point Point;
-  typedef mozilla::image::DrawResult DrawResult;
 
 protected:
   explicit SVGTextFrame(nsStyleContext* aContext)
     : nsSVGDisplayContainerFrame(aContext, mozilla::LayoutFrameType::SVGText)
     , mTrailingUndisplayedCharacters(0)
     , mFontSizeScaleFactor(1.0f)
     , mLastContextScale(1.0f)
     , mLengthAdjustScaleFactor(1.0f)
--- a/layout/svg/nsFilterInstance.h
+++ b/layout/svg/nsFilterInstance.h
@@ -50,17 +50,16 @@ class UserSpaceMetrics;
 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
--- a/layout/svg/nsSVGClipPathFrame.cpp
+++ b/layout/svg/nsSVGClipPathFrame.cpp
@@ -210,17 +210,16 @@ nsSVGClipPathFrame::PaintFrameIntoMask(n
   if (effectProperties.HasInvalidClipPath()) {
     return;
   }
   nsSVGClipPathFrame *clipPathThatClipsChild =
     effectProperties.GetClipPathFrame();
 
   nsSVGUtils::MaskUsage maskUsage;
   nsSVGUtils::DetermineMaskUsage(aFrame, true, maskUsage);
-  DrawResult result = DrawResult::SUCCESS;
   if (maskUsage.shouldApplyClipPath) {
     clipPathThatClipsChild->ApplyClipPath(aTarget, aClippedFrame, aMatrix);
   } else if (maskUsage.shouldGenerateClipMaskLayer) {
     Matrix maskTransform;
     RefPtr<SourceSurface> maskSurface =
       clipPathThatClipsChild->GetClipMask(aTarget, aClippedFrame,
                                           aMatrix, &maskTransform);
     aTarget.PushGroupForBlendBack(gfxContentType::ALPHA, 1.0,
--- a/layout/svg/nsSVGClipPathFrame.h
+++ b/layout/svg/nsSVGClipPathFrame.h
@@ -16,17 +16,16 @@ class nsSVGDisplayableFrame;
 
 class nsSVGClipPathFrame final : public nsSVGContainerFrame
 {
   friend nsIFrame*
   NS_NewSVGClipPathFrame(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 nsSVGClipPathFrame(nsStyleContext* aContext)
     : nsSVGContainerFrame(aContext, mozilla::LayoutFrameType::SVGClipPath)
     , mIsBeingProcessed(false)
   {
     AddStateBits(NS_FRAME_IS_NONDISPLAY);
--- a/layout/svg/nsSVGDisplayableFrame.h
+++ b/layout/svg/nsSVGDisplayableFrame.h
@@ -46,17 +46,16 @@ class Matrix;
 class nsSVGDisplayableFrame : public nsQueryFrame
 {
 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
--- a/layout/svg/nsSVGGradientFrame.cpp
+++ b/layout/svg/nsSVGGradientFrame.cpp
@@ -220,24 +220,24 @@ static void GetStopInformation(nsIFrame*
   static_cast<SVGStopElement*>(stopContent)->
     GetAnimatedNumberValues(aOffset, nullptr);
 
   *aOffset = mozilla::clamped(*aOffset, 0.0f, 1.0f);
   *aStopColor = aStopFrame->StyleSVGReset()->mStopColor;
   *aStopOpacity = aStopFrame->StyleSVGReset()->mStopOpacity;
 }
 
-mozilla::Pair<DrawResult, RefPtr<gfxPattern>>
+already_AddRefed<gfxPattern>
 nsSVGGradientFrame::GetPaintServerPattern(nsIFrame* aSource,
                                           const DrawTarget* aDrawTarget,
                                           const gfxMatrix& aContextMatrix,
                                           nsStyleSVGPaint nsStyleSVG::*aFillOrStroke,
                                           float aGraphicOpacity,
-                                          const gfxRect* aOverrideBounds,
-                                          uint32_t aFlags)
+                                          imgDrawingParams& aImgParams,
+                                          const gfxRect* aOverrideBounds)
 {
   uint16_t gradientUnits = GetGradientUnits();
   MOZ_ASSERT(gradientUnits == SVG_UNIT_TYPE_OBJECTBOUNDINGBOX ||
              gradientUnits == SVG_UNIT_TYPE_USERSPACEONUSE);
   if (gradientUnits == SVG_UNIT_TYPE_USERSPACEONUSE) {
     // Set mSource for this consumer.
     // If this gradient is applied to text, our caller will be the glyph, which
     // is not an element, so we need to get the parent
@@ -249,55 +249,54 @@ nsSVGGradientFrame::GetPaintServerPatter
   GetStopFrames(&stopFrames);
 
   uint32_t nStops = stopFrames.Length();
 
   // SVG specification says that no stops should be treated like
   // the corresponding fill or stroke had "none" specified.
   if (nStops == 0) {
     RefPtr<gfxPattern> pattern = new gfxPattern(Color());
-    return MakePair(DrawResult::SUCCESS, Move(pattern));
+    return do_AddRef(new gfxPattern(Color()));
   }
 
   if (nStops == 1 || GradientVectorLengthIsZero()) {
     // The gradient paints a single colour, using the stop-color of the last
     // gradient step if there are more than one.
     float stopOpacity = stopFrames[nStops-1]->StyleSVGReset()->mStopOpacity;
     nscolor stopColor = stopFrames[nStops-1]->StyleSVGReset()->mStopColor;
 
     Color stopColor2 = Color::FromABGR(stopColor);
     stopColor2.a *= stopOpacity * aGraphicOpacity;
-    RefPtr<gfxPattern> pattern = new gfxPattern(stopColor2);
-    return MakePair(DrawResult::SUCCESS, Move(pattern));
+    return do_AddRef(new gfxPattern(stopColor2));
   }
 
   // Get the transform list (if there is one). We do this after the returns
   // above since this call can be expensive when "gradientUnits" is set to
   // "objectBoundingBox" (since that requiring a GetBBox() call).
   gfxMatrix patternMatrix = GetGradientTransform(aSource, aOverrideBounds);
 
   if (patternMatrix.IsSingular()) {
-    return MakePair(DrawResult::SUCCESS, RefPtr<gfxPattern>());
+    return nullptr;
   }
 
   // revert any vector effect transform so that the gradient appears unchanged
   if (aFillOrStroke == &nsStyleSVG::mStroke) {
     gfxMatrix userToOuterSVG;
     if (nsSVGUtils::GetNonScalingStrokeTransform(aSource, &userToOuterSVG)) {
       patternMatrix *= userToOuterSVG;
     }
   }
 
   if (!patternMatrix.Invert()) {
-    return MakePair(DrawResult::SUCCESS, RefPtr<gfxPattern>());
+    return nullptr;
   }
 
   RefPtr<gfxPattern> gradient = CreateGradient();
   if (!gradient) {
-    return MakePair(DrawResult::TEMPORARY_ERROR, RefPtr<gfxPattern>());
+    return nullptr;
   }
 
   uint16_t aSpread = GetSpreadMethod();
   if (aSpread == SVG_SPREADMETHOD_PAD)
     gradient->SetExtend(ExtendMode::CLAMP);
   else if (aSpread == SVG_SPREADMETHOD_REFLECT)
     gradient->SetExtend(ExtendMode::REFLECT);
   else if (aSpread == SVG_SPREADMETHOD_REPEAT)
@@ -319,17 +318,17 @@ nsSVGGradientFrame::GetPaintServerPatter
     else
       lastOffset = offset;
 
     Color stopColor2 = Color::FromABGR(stopColor);
     stopColor2.a *= stopOpacity * aGraphicOpacity;
     gradient->AddColorStop(offset, stopColor2);
   }
 
-  return MakePair(DrawResult::SUCCESS, Move(gradient));
+  return gradient.forget();
 }
 
 // Private (helper) methods
 
 nsSVGGradientFrame *
 nsSVGGradientFrame::GetReferencedGradient()
 {
   if (mNoHRefURI)
--- a/layout/svg/nsSVGGradientFrame.h
+++ b/layout/svg/nsSVGGradientFrame.h
@@ -41,24 +41,24 @@ class nsSVGGradientFrame : public nsSVGP
 
 protected:
   nsSVGGradientFrame(nsStyleContext* aContext, mozilla::LayoutFrameType aType);
 
 public:
   NS_DECL_ABSTRACT_FRAME(nsSVGGradientFrame)
 
   // nsSVGPaintServerFrame methods:
-  virtual mozilla::Pair<DrawResult, RefPtr<gfxPattern>>
-    GetPaintServerPattern(nsIFrame* aSource,
+  virtual already_AddRefed<gfxPattern>
+    GetPaintServerPattern(nsIFrame *aSource,
                           const DrawTarget* aDrawTarget,
                           const gfxMatrix& aContextMatrix,
                           nsStyleSVGPaint nsStyleSVG::*aFillOrStroke,
-                          float aGraphicOpacity,
-                          const gfxRect* aOverrideBounds,
-                          uint32_t aFlags) override;
+                          float aOpacity,
+                          imgDrawingParams& aImgParams,
+                          const gfxRect* aOverrideBounds) override;
 
   // nsIFrame interface:
   virtual nsresult AttributeChanged(int32_t         aNameSpaceID,
                                     nsIAtom*        aAttribute,
                                     int32_t         aModType) override;
 
 #ifdef DEBUG_FRAME_DUMP
   virtual nsresult GetFrameName(nsAString& aResult) const override
--- a/layout/svg/nsSVGIntegrationUtils.cpp
+++ b/layout/svg/nsSVGIntegrationUtils.cpp
@@ -1216,22 +1216,21 @@ nsSVGIntegrationUtils::DrawableFromPaint
     // frame by default, so aPaintServerSize is the whole target background fill
     // area.
     nsSVGPaintServerFrame* server =
       static_cast<nsSVGPaintServerFrame*>(aFrame);
 
     gfxRect overrideBounds(0, 0,
                            aPaintServerSize.width, aPaintServerSize.height);
     overrideBounds.ScaleInverse(aFrame->PresContext()->AppUnitsPerDevPixel());
-    DrawResult result = DrawResult::SUCCESS;
-    RefPtr<gfxPattern> pattern;
-    Tie(result, pattern) =
+    imgDrawingParams imgParams(aFlags);
+    RefPtr<gfxPattern> pattern =
       server->GetPaintServerPattern(aTarget, aDrawTarget,
                                     aContextMatrix, &nsStyleSVG::mFill, 1.0,
-                                    &overrideBounds);
+                                    imgParams, &overrideBounds);
 
     if (!pattern)
       return nullptr;
 
     // pattern is now set up to fill aPaintServerSize. But we want it to
     // fill aRenderSize, so we need to add a scaling transform.
     // We couldn't just have set overrideBounds to aRenderSize - it would have
     // worked for gradients, but for patterns it would result in a different
--- a/layout/svg/nsSVGIntegrationUtils.h
+++ b/layout/svg/nsSVGIntegrationUtils.h
@@ -35,17 +35,16 @@ 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);
--- a/layout/svg/nsSVGMaskFrame.h
+++ b/layout/svg/nsSVGMaskFrame.h
@@ -33,17 +33,16 @@ 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/nsSVGPaintServerFrame.h
+++ b/layout/svg/nsSVGPaintServerFrame.h
@@ -51,17 +51,16 @@ private:
   nsIFrame* mFrame;
   MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
 };
 
 class nsSVGPaintServerFrame : public nsSVGContainerFrame
 {
 protected:
   typedef mozilla::gfx::DrawTarget DrawTarget;
-  typedef mozilla::image::DrawResult DrawResult;
 
   explicit nsSVGPaintServerFrame(nsStyleContext* aContext,
                                  mozilla::LayoutFrameType aType)
     : nsSVGContainerFrame(aContext, aType)
   {
     AddStateBits(NS_FRAME_IS_NONDISPLAY);
   }
 
@@ -73,24 +72,24 @@ public:
   /**
    * 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
    *   vector based, so it's not used there.)
    */
-  virtual mozilla::Pair<DrawResult, RefPtr<gfxPattern>>
+  virtual already_AddRefed<gfxPattern>
     GetPaintServerPattern(nsIFrame *aSource,
                           const DrawTarget* aDrawTarget,
                           const gfxMatrix& aContextMatrix,
                           nsStyleSVGPaint nsStyleSVG::*aFillOrStroke,
                           float aOpacity,
-                          const gfxRect *aOverrideBounds = nullptr,
-                          uint32_t aFlags = 0) = 0;
+                          imgDrawingParams& aImgParams,
+                          const gfxRect* aOverrideBounds = nullptr) = 0;
 
   // nsIFrame methods:
   virtual void BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                                 const nsRect&           aDirtyRect,
                                 const nsDisplayListSet& aLists) override {}
 
   virtual bool IsFrameOfType(uint32_t aFlags) const override
   {
--- a/layout/svg/nsSVGPatternFrame.cpp
+++ b/layout/svg/nsSVGPatternFrame.cpp
@@ -201,42 +201,42 @@ GetTargetGeometry(gfxRect *aBBox,
   float scale = MaxExpansion(aContextMatrix);
   if (scale <= 0) {
     return NS_ERROR_FAILURE;
   }
   aBBox->Scale(scale);
   return NS_OK;
 }
 
-mozilla::Pair<DrawResult, RefPtr<SourceSurface>>
+already_AddRefed<SourceSurface>
 nsSVGPatternFrame::PaintPattern(const DrawTarget* aDrawTarget,
                                 Matrix* patternMatrix,
                                 const Matrix &aContextMatrix,
                                 nsIFrame *aSource,
                                 nsStyleSVGPaint nsStyleSVG::*aFillOrStroke,
                                 float aGraphicOpacity,
                                 const gfxRect *aOverrideBounds,
-                                uint32_t aFlags)
+                                imgDrawingParams& aImgParams)
 {
   /*
    * General approach:
    *    Set the content geometry stuff
    *    Calculate our bbox (using x,y,width,height & patternUnits &
    *                        patternTransform)
    *    Create the surface
    *    Calculate the content transformation matrix
    *    Get our children (we may need to get them from another Pattern)
    *    Call SVGPaint on all of our children
    *    Return
    */
 
   nsSVGPatternFrame* patternWithChildren = GetPatternWithChildren();
   if (!patternWithChildren) {
     // Either no kids or a bad reference
-    return MakePair(DrawResult::SUCCESS, RefPtr<SourceSurface>());
+    return nullptr;
   }
   nsIFrame* firstKid = patternWithChildren->mFrames.FirstChild();
 
   const nsSVGViewBox& viewBox = GetViewBox();
 
   uint16_t patternContentUnits =
     GetEnumValue(SVGPatternElement::PATTERNCONTENTUNITS);
   uint16_t patternUnits =
@@ -265,76 +265,76 @@ nsSVGPatternFrame::PaintPattern(const Dr
   // the geometry that is being rendered with a pattern
   gfxRect callerBBox;
   if (NS_FAILED(GetTargetGeometry(&callerBBox,
                                   viewBox,
                                   patternContentUnits, patternUnits,
                                   aSource,
                                   aContextMatrix,
                                   aOverrideBounds))) {
-    return MakePair(DrawResult::SUCCESS, RefPtr<SourceSurface>());
+    return nullptr;
   }
 
   // Construct the CTM that we will provide to our children when we
   // render them into the tile.
   gfxMatrix ctm = ConstructCTM(viewBox, patternContentUnits, patternUnits,
                                callerBBox, aContextMatrix, aSource);
   if (ctm.IsSingular()) {
-    return MakePair(DrawResult::SUCCESS, RefPtr<SourceSurface>());
+    return nullptr;
   }
 
   if (patternWithChildren->mCTM) {
     *patternWithChildren->mCTM = ctm;
   } else {
     patternWithChildren->mCTM = new gfxMatrix(ctm);
   }
 
   // Get the bounding box of the pattern.  This will be used to determine
   // the size of the surface, and will also be used to define the bounding
   // box for the pattern tile.
   gfxRect bbox = GetPatternRect(patternUnits, callerBBox, aContextMatrix, aSource);
   if (bbox.Width() <= 0.0 || bbox.Height() <= 0.0) {
-    return MakePair(DrawResult::SUCCESS, RefPtr<SourceSurface>());
+    return nullptr;
   }
 
   // Get the pattern transform
   Matrix patternTransform = ToMatrix(GetPatternTransform());
 
   // revert the vector effect transform so that the pattern appears unchanged
   if (aFillOrStroke == &nsStyleSVG::mStroke) {
     gfxMatrix userToOuterSVG;
     if (nsSVGUtils::GetNonScalingStrokeTransform(aSource, &userToOuterSVG)) {
       patternTransform *= ToMatrix(userToOuterSVG);
       if (patternTransform.IsSingular()) {
         NS_WARNING("Singular matrix painting non-scaling-stroke");
-        return MakePair(DrawResult::SUCCESS, RefPtr<SourceSurface>());
+        return nullptr;
       }
     }
   }
 
   // Get the transformation matrix that we will hand to the renderer's pattern
   // routine.
   *patternMatrix = GetPatternMatrix(patternUnits, patternTransform,
                                     bbox, callerBBox, aContextMatrix);
   if (patternMatrix->IsSingular()) {
-    return MakePair(DrawResult::SUCCESS, RefPtr<SourceSurface>());
+    return nullptr;
   }
 
   // Now that we have all of the necessary geometries, we can
   // create our surface.
   gfxRect transformedBBox = ThebesRect(patternTransform.TransformBounds(ToRect(bbox)));
 
   bool resultOverflows;
   IntSize surfaceSize =
     nsSVGUtils::ConvertToSurfaceSize(
       transformedBBox.Size(), &resultOverflows);
 
   // 0 disables rendering, < 0 is an error
   if (surfaceSize.width <= 0 || surfaceSize.height <= 0) {
-    return MakePair(DrawResult::SUCCESS, RefPtr<SourceSurface>());
+    return nullptr;
   }
 
   gfxFloat patternWidth = bbox.Width();
   gfxFloat patternHeight = bbox.Height();
 
   if (resultOverflows ||
       patternWidth != surfaceSize.width ||
       patternHeight != surfaceSize.height) {
@@ -348,17 +348,17 @@ nsSVGPatternFrame::PaintPattern(const Dr
     // and rescale pattern to compensate
     patternMatrix->PreScale(patternWidth / surfaceSize.width,
                             patternHeight / surfaceSize.height);
   }
 
   RefPtr<DrawTarget> dt =
     aDrawTarget->CreateSimilarDrawTarget(surfaceSize, SurfaceFormat::B8G8R8A8);
   if (!dt || !dt->IsValid()) {
-    return MakePair(DrawResult::TEMPORARY_ERROR, RefPtr<SourceSurface>());
+    return nullptr;
   }
   dt->ClearRect(Rect(0, 0, surfaceSize.width, surfaceSize.height));
 
   RefPtr<gfxContext> ctx = gfxContext::CreateOrNull(dt);
   MOZ_ASSERT(ctx); // already checked the draw target above
 
   if (aGraphicOpacity != 1.0f) {
     ctx->Save();
@@ -371,46 +371,44 @@ 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
-  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);
       }
 
-      nsSVGUtils::PaintFrameWithEffects(kid, *ctx, tm, imgParams);
+      nsSVGUtils::PaintFrameWithEffects(kid, *ctx, tm, aImgParams);
     }
   }
 
   patternWithChildren->mSource = nullptr;
 
   if (aGraphicOpacity != 1.0f) {
     ctx->PopGroupAndBlend();
     ctx->Restore();
   }
 
   // caller now owns the surface
-  RefPtr<SourceSurface> surf = dt->Snapshot();
-  return MakePair(imgParams.result, Move(surf));
+  return dt->Snapshot();
 }
 
 /* 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()
@@ -713,50 +711,47 @@ nsSVGPatternFrame::ConstructCTM(const ns
     viewBoxRect.width, viewBoxRect.height,
     GetPreserveAspectRatio());
 
   return ThebesMatrix(tm);
 }
 
 //----------------------------------------------------------------------
 // nsSVGPaintServerFrame methods:
-mozilla::Pair<DrawResult, RefPtr<gfxPattern>>
+already_AddRefed<gfxPattern>
 nsSVGPatternFrame::GetPaintServerPattern(nsIFrame *aSource,
                                          const DrawTarget* aDrawTarget,
                                          const gfxMatrix& aContextMatrix,
                                          nsStyleSVGPaint nsStyleSVG::*aFillOrStroke,
                                          float aGraphicOpacity,
-                                         const gfxRect *aOverrideBounds,
-                                         uint32_t aFlags)
+                                         imgDrawingParams& aImgParams,
+                                         const gfxRect *aOverrideBounds)
 {
   if (aGraphicOpacity == 0.0f) {
-    RefPtr<gfxPattern> pattern = new gfxPattern(Color());
-    return MakePair(DrawResult::SUCCESS, Move(pattern));
+    return do_AddRef(new gfxPattern(Color()));
   }
 
   // Paint it!
   Matrix pMatrix;
-  RefPtr<SourceSurface> surface;
-  DrawResult result = DrawResult::SUCCESS;
-  Tie(result, surface) =
+  RefPtr<SourceSurface> surface =
     PaintPattern(aDrawTarget, &pMatrix, ToMatrix(aContextMatrix), aSource,
-                 aFillOrStroke, aGraphicOpacity, aOverrideBounds, aFlags);
+                 aFillOrStroke, aGraphicOpacity, aOverrideBounds, aImgParams);
 
   if (!surface) {
-    return MakePair(result, RefPtr<gfxPattern>());
+    return nullptr;
   }
 
   RefPtr<gfxPattern> pattern = new gfxPattern(surface, pMatrix);
 
   if (!pattern) {
-    return MakePair(DrawResult::TEMPORARY_ERROR, RefPtr<gfxPattern>());
+    return nullptr;
   }
 
   pattern->SetExtend(ExtendMode::REPEAT);
-  return MakePair(result, Move(pattern));
+  return pattern.forget();
 }
 
 // -------------------------------------------------------------------------
 // Public functions
 // -------------------------------------------------------------------------
 
 nsIFrame* NS_NewSVGPatternFrame(nsIPresShell*   aPresShell,
                                 nsStyleContext* aContext)
--- a/layout/svg/nsSVGPatternFrame.h
+++ b/layout/svg/nsSVGPatternFrame.h
@@ -35,24 +35,24 @@ public:
   NS_DECL_FRAMEARENA_HELPERS
 
   friend nsIFrame* NS_NewSVGPatternFrame(nsIPresShell* aPresShell,
                                          nsStyleContext* aContext);
 
   explicit nsSVGPatternFrame(nsStyleContext* aContext);
 
   // nsSVGPaintServerFrame methods:
-  virtual mozilla::Pair<DrawResult, RefPtr<gfxPattern>>
+  virtual already_AddRefed<gfxPattern>
     GetPaintServerPattern(nsIFrame *aSource,
                           const DrawTarget* aDrawTarget,
                           const gfxMatrix& aContextMatrix,
                           nsStyleSVGPaint nsStyleSVG::*aFillOrStroke,
                           float aOpacity,
-                          const gfxRect *aOverrideBounds,
-                          uint32_t aFlags) override;
+                          imgDrawingParams& aImgParams,
+                          const gfxRect* aOverrideBounds) override;
 
 public:
   typedef mozilla::SVGAnimatedPreserveAspectRatio SVGAnimatedPreserveAspectRatio;
 
   // nsSVGContainerFrame methods:
   virtual gfxMatrix GetCanvasTM() override;
 
   // nsIFrame interface:
@@ -95,25 +95,25 @@ protected:
     return GetPreserveAspectRatio(mContent);
   }
   const nsSVGLength2 *GetLengthValue(uint32_t aIndex, nsIContent *aDefault);
   const nsSVGLength2 *GetLengthValue(uint32_t aIndex)
   {
     return GetLengthValue(aIndex, mContent);
   }
 
-  mozilla::Pair<DrawResult, RefPtr<SourceSurface>>
+  already_AddRefed<SourceSurface>
   PaintPattern(const DrawTarget* aDrawTarget,
                Matrix *patternMatrix,
                const Matrix &aContextMatrix,
                nsIFrame *aSource,
                nsStyleSVGPaint nsStyleSVG::*aFillOrStroke,
                float aGraphicOpacity,
                const gfxRect *aOverrideBounds,
-               uint32_t aFlags);
+               imgDrawingParams& aImgParams);
 
   /**
    * A <pattern> element may reference another <pattern> element using
    * xlink:href and, if it doesn't have any child content of its own, then it
    * will "inherit" the children of the referenced pattern (which may itself be
    * inheriting its children if it references another <pattern>).  This
    * function returns this nsSVGPatternFrame or the first pattern along the
    * reference chain (if there is one) to have children.
--- a/layout/svg/nsSVGUtils.cpp
+++ b/layout/svg/nsSVGUtils.cpp
@@ -1500,42 +1500,38 @@ nsSVGUtils::MakeFillPatternFor(nsIFrame*
 
   const DrawTarget* dt = aContext->GetDrawTarget();
 
   nsSVGPaintServerFrame *ps =
     nsSVGEffects::GetPaintServer(aFrame, &nsStyleSVG::mFill,
                                  nsSVGEffects::FillProperty());
 
   if (ps) {
-    RefPtr<gfxPattern> pattern;
-    Tie(aImgParams.result, pattern) =
+    RefPtr<gfxPattern> pattern =
       ps->GetPaintServerPattern(aFrame, dt, aContext->CurrentMatrix(),
-                                &nsStyleSVG::mFill, fillOpacity, nullptr,
-                                aImgParams.imageFlags);
+                                &nsStyleSVG::mFill, fillOpacity, aImgParams);
     if (pattern) {
       pattern->CacheColorStops(dt);
       aOutPattern->Init(*pattern->GetPattern(dt));
       return;
     }
   }
 
   if (aContextPaint) {
     RefPtr<gfxPattern> pattern;
     switch (style->mFill.Type()) {
     case eStyleSVGPaintType_ContextFill:
-      Tie(aImgParams.result, pattern) =
+      pattern =
         aContextPaint->GetFillPattern(dt, fillOpacity,
-                                      aContext->CurrentMatrix(),
-                                      aImgParams.imageFlags);
+                                      aContext->CurrentMatrix(), aImgParams);
       break;
     case eStyleSVGPaintType_ContextStroke:
-      Tie(aImgParams.result, pattern) =
+      pattern =
         aContextPaint->GetStrokePattern(dt, fillOpacity,
-                                        aContext->CurrentMatrix(),
-                                        aImgParams.imageFlags);
+                                        aContext->CurrentMatrix(), aImgParams);
       break;
     default:
       ;
     }
     if (pattern) {
       aOutPattern->Init(*pattern->GetPattern(dt));
       return;
     }
@@ -1580,42 +1576,38 @@ nsSVGUtils::MakeStrokePatternFor(nsIFram
 
   const DrawTarget* dt = aContext->GetDrawTarget();
 
   nsSVGPaintServerFrame *ps =
     nsSVGEffects::GetPaintServer(aFrame, &nsStyleSVG::mStroke,
                                  nsSVGEffects::StrokeProperty());
 
   if (ps) {
-    RefPtr<gfxPattern> pattern;
-    Tie(aImgParams.result, pattern) =
+    RefPtr<gfxPattern> pattern =
       ps->GetPaintServerPattern(aFrame, dt, aContext->CurrentMatrix(),
-                                &nsStyleSVG::mStroke, strokeOpacity, nullptr,
-                                aImgParams.imageFlags);
+                                &nsStyleSVG::mStroke, strokeOpacity, aImgParams);
     if (pattern) {
       pattern->CacheColorStops(dt);
       aOutPattern->Init(*pattern->GetPattern(dt));
       return;
     }
   }
 
   if (aContextPaint) {
     RefPtr<gfxPattern> pattern;
     switch (style->mStroke.Type()) {
     case eStyleSVGPaintType_ContextFill:
-      Tie(aImgParams.result, pattern) =
+      pattern =
         aContextPaint->GetFillPattern(dt, strokeOpacity,
-                                      aContext->CurrentMatrix(),
-                                      aImgParams.imageFlags);
+                                      aContext->CurrentMatrix(), aImgParams);
       break;
     case eStyleSVGPaintType_ContextStroke:
-      Tie(aImgParams.result, pattern) =
+      pattern =
         aContextPaint->GetStrokePattern(dt, strokeOpacity,
-                                        aContext->CurrentMatrix(),
-                                        aImgParams.imageFlags);
+                                        aContext->CurrentMatrix(), aImgParams);
       break;
     default:
       ;
     }
     if (pattern) {
       aOutPattern->Init(*pattern->GetPattern(dt));
       return;
     }
--- a/layout/svg/nsSVGUtils.h
+++ b/layout/svg/nsSVGUtils.h
@@ -187,17 +187,16 @@ public:
   typedef mozilla::gfx::AntialiasMode AntialiasMode;
   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