Bug 1351440 - Return DrawResult by an out paramenter of PaintSVG. draft
authorcku <cku@mozilla.com>
Sat, 22 Apr 2017 01:26:57 +0800
changeset 566502 ebdbb7e76d54c177394344e98b3ee0bfbf251020
parent 566473 0b1d1dfe7055a8568e1cc7ea5f74c6fd63ada14c
child 625335 93bd4384aa4cbde4109ea0b28fd5e0f910126625
push id55239
push userbmo:cku@mozilla.com
push dateFri, 21 Apr 2017 17:43:01 +0000
bugs1351440
milestone55.0a1
Bug 1351440 - Return DrawResult by an out paramenter of PaintSVG. MozReview-Commit-ID: AF6I1Iwj4jk
layout/svg/SVGGeometryFrame.cpp
layout/svg/SVGGeometryFrame.h
layout/svg/SVGTextFrame.cpp
layout/svg/SVGTextFrame.h
layout/svg/nsSVGClipPathFrame.cpp
layout/svg/nsSVGContainerFrame.cpp
layout/svg/nsSVGContainerFrame.h
layout/svg/nsSVGDisplayableFrame.h
layout/svg/nsSVGForeignObjectFrame.cpp
layout/svg/nsSVGForeignObjectFrame.h
layout/svg/nsSVGImageFrame.cpp
layout/svg/nsSVGInnerSVGFrame.cpp
layout/svg/nsSVGInnerSVGFrame.h
layout/svg/nsSVGOuterSVGFrame.cpp
layout/svg/nsSVGOuterSVGFrame.h
layout/svg/nsSVGSwitchFrame.cpp
layout/svg/nsSVGUtils.cpp
--- a/layout/svg/SVGGeometryFrame.cpp
+++ b/layout/svg/SVGGeometryFrame.cpp
@@ -122,19 +122,21 @@ nsDisplaySVGGeometry::Paint(nsDisplayLis
 
   gfxMatrix tm = nsSVGUtils::GetCSSPxToDevPxMatrix(mFrame) *
                    gfxMatrix::Translation(devPixelOffset);
 
   uint32_t flag = aBuilder->ShouldSyncDecodeImages()
                   ? imgIContainer::FLAG_SYNC_DECODE
                   : imgIContainer::FLAG_SYNC_DECODE_IF_FAST;
 
-  DrawResult result =
-    static_cast<SVGGeometryFrame*>(mFrame)->PaintSVG(*aCtx->ThebesContext(),
-                                                     tm, nullptr, flag);
+  DrawResult result = DrawResult::SUCCESS;
+  nsSVGDisplayableFrame::PaintSVGParam param(*aCtx->ThebesContext(),
+                                             tm, result, nullptr, flag);
+
+  static_cast<SVGGeometryFrame*>(mFrame)->PaintSVG(param);
 
   nsDisplayItemGenericImageGeometry::UpdateDrawResult(this, result);
 }
 
 void
 nsDisplaySVGGeometry::ComputeInvalidationRegion(
   nsDisplayListBuilder* aBuilder,
   const nsDisplayItemGeometry* aGeometry,
@@ -278,58 +280,59 @@ SVGGeometryFrame::BuildDisplayList(nsDis
   DisplayOutline(aBuilder, aLists);
   aLists.Content()->AppendNewToTop(
     new (aBuilder) nsDisplaySVGGeometry(aBuilder, this));
 }
 
 //----------------------------------------------------------------------
 // nsSVGDisplayableFrame methods
 
-DrawResult
-SVGGeometryFrame::PaintSVG(gfxContext& aContext,
-                           const gfxMatrix& aTransform,
-                           const nsIntRect* aDirtyRect,
-                           uint32_t aFlags)
+void
+SVGGeometryFrame::PaintSVG(PaintSVGParam& aParam)
 {
-  if (!StyleVisibility()->IsVisible())
-    return DrawResult::SUCCESS;
+  if (!StyleVisibility()->IsVisible()) {
+    return;
+  }
+
+  gfxContext& context = aParam.context;
+  uint32_t imageFlags = aParam.imageFlags;
 
   // Matrix to the geometry's user space:
   gfxMatrix newMatrix =
-    aContext.CurrentMatrix().PreMultiply(aTransform).NudgeToIntegers();
+    context.CurrentMatrix().PreMultiply(aParam.transform).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);
+    result = Render(&context, eRenderFill | eRenderStroke, newMatrix, imageFlags);
+    result &= PaintMarkers(context, aParam.transform, imageFlags);
   } 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);
+          result &= Render(&context, eRenderFill, newMatrix, imageFlags);
           break;
         case NS_STYLE_PAINT_ORDER_STROKE:
-          result &= Render(&aContext, eRenderStroke, newMatrix, aFlags);
+          result &= Render(&context, eRenderStroke, newMatrix, imageFlags);
           break;
         case NS_STYLE_PAINT_ORDER_MARKERS:
-          result &= PaintMarkers(aContext, aTransform, aFlags);
+          result &= PaintMarkers(context, aParam.transform, imageFlags);
           break;
       }
       paintOrder >>= NS_STYLE_PAINT_ORDER_BITWIDTH;
     }
   }
 
-  return result;
+  aParam.result = result;
 }
 
 nsIFrame*
 SVGGeometryFrame::GetFrameForPoint(const gfxPoint& aPoint)
 {
   FillRule fillRule;
   uint16_t hitTestFlags;
   if (GetStateBits() & NS_STATE_SVG_CLIPPATH_CHILD) {
--- a/layout/svg/SVGGeometryFrame.h
+++ b/layout/svg/SVGGeometryFrame.h
@@ -95,21 +95,17 @@ 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(PaintSVGParam& aParam) 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; }
 
   /**
--- a/layout/svg/SVGTextFrame.cpp
+++ b/layout/svg/SVGTextFrame.cpp
@@ -3114,20 +3114,28 @@ nsDisplaySVGText::Paint(nsDisplayListBui
   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;
+
   gfxContext* ctx = aCtx->ThebesContext();
   ctx->Save();
-  DrawResult result = static_cast<SVGTextFrame*>(mFrame)->PaintSVG(*ctx, tm);
+
+  DrawResult result = DrawResult::SUCCESS;
+  nsSVGDisplayableFrame::PaintSVGParam param(*ctx, tm, result, nullptr, flag);
+  static_cast<SVGTextFrame*>(mFrame)->PaintSVG(param);
   nsDisplayItemGenericImageGeometry::UpdateDrawResult(this, result);
+
   ctx->Restore();
 }
 
 // ---------------------------------------------------------------------
 // nsQueryFrame methods
 
 NS_QUERYFRAME_HEAD(SVGTextFrame)
   NS_QUERYFRAME_ENTRY(SVGTextFrame)
@@ -3554,135 +3562,138 @@ ShouldPaintCaret(const TextRenderedRun& 
       uint32_t(caretOffset) < aThisRun.mTextFrameContentOffset +
                                 aThisRun.mTextFrameContentLength) {
     return true;
   }
 
   return false;
 }
 
-DrawResult
-SVGTextFrame::PaintSVG(gfxContext& aContext,
-                       const gfxMatrix& aTransform,
-                       const nsIntRect *aDirtyRect,
-                       uint32_t aFlags)
+void
+SVGTextFrame::PaintSVG(PaintSVGParam& aParam)
 {
-  DrawTarget& aDrawTarget = *aContext.GetDrawTarget();
+  gfxContext& context = aParam.context;
+  uint32_t imageFlags = aParam.imageFlags;
+  const gfxMatrix& transform = aParam.transform;
+
+  DrawTarget& aDrawTarget = *context.GetDrawTarget();
+  aParam.result = DrawResult::SUCCESS;
 
   nsIFrame* kid = PrincipalChildList().FirstChild();
-  if (!kid)
-    return DrawResult::SUCCESS;
+  if (!kid) {
+    return;
+  }
 
   nsPresContext* presContext = PresContext();
 
-  gfxMatrix initialMatrix = aContext.CurrentMatrix();
+  gfxMatrix initialMatrix = context.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;
-  }
-
-  if (aTransform.IsSingular()) {
+    return;
+  }
+
+  if (transform.IsSingular()) {
     NS_WARNING("Can't render text element!");
-    return DrawResult::SUCCESS;
-  }
-
-  gfxMatrix matrixForPaintServers = aTransform * initialMatrix;
+    return;
+  }
+
+  gfxMatrix matrixForPaintServers = transform * initialMatrix;
 
   // Check if we need to draw anything.
-  if (aDirtyRect) {
+  if (aParam.dirtyRect) {
     NS_ASSERTION(!NS_SVGDisplayListPaintingEnabled() ||
                  (mState & NS_FRAME_IS_NONDISPLAY),
                  "Display lists handle dirty rect intersection test");
-    nsRect dirtyRect(aDirtyRect->x, aDirtyRect->y,
-                     aDirtyRect->width, aDirtyRect->height);
+    nsRect dirtyRect(aParam.dirtyRect->x, aParam.dirtyRect->y,
+                     aParam.dirtyRect->width, aParam.dirtyRect->height);
 
     gfxFloat appUnitsPerDevPixel = presContext->AppUnitsPerDevPixel();
     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
+  // dev pixels. Here we multiply a CSS-px-to-dev-pixel factor onto transform
   // so our non-SVG nsTextFrame children paint correctly.
   auto auPerDevPx = presContext->AppUnitsPerDevPixel();
   float cssPxPerDevPx = presContext->AppUnitsToFloatCSSPixels(auPerDevPx);
-  gfxMatrix canvasTMForChildren = aTransform;
+  gfxMatrix canvasTMForChildren = transform;
   canvasTMForChildren.Scale(cssPxPerDevPx, cssPxPerDevPx);
   initialMatrix.Scale(1 / cssPxPerDevPx, 1 / cssPxPerDevPx);
 
-  gfxContextAutoSaveRestore save(&aContext);
-  aContext.NewPath();
-  aContext.Multiply(canvasTMForChildren);
-  gfxMatrix currentMatrix = aContext.CurrentMatrix();
+  gfxContextAutoSaveRestore save(&context);
+  context.NewPath();
+  context.Multiply(canvasTMForChildren);
+  gfxMatrix currentMatrix = context.CurrentMatrix();
 
   RefPtr<nsCaret> caret = presContext->PresShell()->GetCaret();
   nsRect caretRect;
   nsIFrame* caretFrame = caret->GetPaintGeometry(&caretRect);
 
   TextRenderedRunIterator it(this, TextRenderedRunIterator::eVisibleFrames);
   TextRenderedRun run = it.Current();
 
   SVGContextPaint* outerContextPaint =
     SVGContextPaint::GetContextPaint(mContent);
 
-  nsRenderingContext rendCtx(&aContext);
+  nsRenderingContext rendCtx(&context);
   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
     // when they use context-fill etc.
-    aContext.SetMatrix(initialMatrix);
+    context.SetMatrix(initialMatrix);
 
     RefPtr<SVGContextPaintImpl> contextPaint = new SVGContextPaintImpl();
     DrawMode drawMode;
     DrawResult result = DrawResult::SUCCESS;
     Tie(result, drawMode) = contextPaint->Init(&aDrawTarget,
-                                               aContext.CurrentMatrix(),
+                                               context.CurrentMatrix(),
                                                frame, outerContextPaint);
     finalResult &= 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);
+      nsSVGUtils::SetupCairoStrokeGeometry(frame, &context, outerContextPaint);
     }
 
     // Set up the transform for painting the text frame for the substring
     // indicated by the run.
     gfxMatrix runTransform =
       run.GetTransformFromUserSpaceForPainting(presContext, item) *
       currentMatrix;
-    aContext.SetMatrix(runTransform);
+    context.SetMatrix(runTransform);
 
     if (drawMode != DrawMode(0)) {
       bool paintSVGGlyphs;
       nsTextFrame::PaintTextParams params(rendCtx.ThebesContext());
       params.framePt = gfxPoint();
       params.dirtyRect = LayoutDevicePixel::
         FromAppUnits(frame->GetVisualOverflowRect(), auPerDevPx);
       params.contextPaint = contextPaint;
@@ -3696,23 +3707,23 @@ SVGTextFrame::PaintSVG(gfxContext& aCont
         frame->PaintText(params, item);
       }
     }
 
     if (frame == caretFrame && ShouldPaintCaret(run, caret)) {
       // 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();
+      context.NewPath();
     }
 
     run = it.Next();
   }
 
-  return finalResult;
+  aParam.result = 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
@@ -249,20 +249,17 @@ 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(PaintSVGParam& aParam) 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/nsSVGClipPathFrame.cpp
+++ b/layout/svg/nsSVGClipPathFrame.cpp
@@ -240,25 +240,25 @@ nsSVGClipPathFrame::PaintFrameIntoMask(n
     toChildsUserSpace =
       static_cast<const nsSVGElement*>(childContent)->
         PrependLocalTransformsTo(mMatrixForChildren, eUserSpaceToParent);
   }
 
   // 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);
+  nsSVGDisplayableFrame::PaintSVGParam param(aTarget, toChildsUserSpace,
+                                             result);
+  frame->PaintSVG(param);
 
   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/nsSVGContainerFrame.cpp
+++ b/layout/svg/nsSVGContainerFrame.cpp
@@ -246,66 +246,58 @@ nsSVGDisplayContainerFrame::IsSVGTransfo
     }
   }
   return foundTransform;
 }
 
 //----------------------------------------------------------------------
 // nsSVGDisplayableFrame methods
 
-DrawResult
-nsSVGDisplayContainerFrame::PaintSVG(gfxContext& aContext,
-                                     const gfxMatrix& aTransform,
-                                     const nsIntRect *aDirtyRect,
-                                     uint32_t aFlags)
+void
+nsSVGDisplayContainerFrame::PaintSVG(PaintSVGParam& aParam)
 {
   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;
+  gfxMatrix matrix = aParam.transform;
   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;
-    }
+    aParam.result &= nsSVGUtils::PaintFrameWithEffects(kid, aParam.context, m,
+                                                       aParam.dirtyRect,
+                                                       aParam.imageFlags);
   }
-
-  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
@@ -135,20 +135,17 @@ 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(PaintSVGParam& aParam) 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
@@ -50,49 +50,62 @@ public:
   typedef mozilla::SVGNumberList SVGNumberList;
   typedef mozilla::SVGAnimatedLengthList SVGAnimatedLengthList;
   typedef mozilla::SVGLengthList SVGLengthList;
   typedef mozilla::SVGUserUnitList SVGUserUnitList;
   typedef mozilla::image::DrawResult DrawResult;
 
   NS_DECL_QUERYFRAME_TARGET(nsSVGDisplayableFrame)
 
+  struct PaintSVGParam {
+    gfxContext& context;
+    DrawResult& result;         // Return painting resultl from image library.
+    const gfxMatrix& transform; // 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.
+    const nsIntRect* dirtyRect; // The area being redrawn, in frame  offset
+                                // pixel coordinates.
+    uint32_t imageFlags;        // Image flags of the
+                                // imgIContainer::FLAG_* variety.
+
+    PaintSVGParam(gfxContext& aContext,
+                  const gfxMatrix& aTransform,
+                  DrawResult& aResult,
+                  const nsIntRect* aDirtyRect = nullptr,
+                  uint32_t aImageFlags = 0)
+      : context(aContext), result(aResult), transform(aTransform),
+        dirtyRect(aDirtyRect), imageFlags(aImageFlags)
+      {}
+  };
+
   /**
    * Paint this frame.
    *
    * SVG is painted using a combination of display lists (trees of
    * nsDisplayItem built by BuildDisplayList() implementations) and recursive
    * PaintSVG calls.  SVG frames with the NS_FRAME_IS_NONDISPLAY bit set are
    * always painted using recursive PaintSVG calls since display list painting
    * would provide no advantages (they wouldn't be retained for invalidation).
    * Displayed SVG is normally painted via a display list tree created under
    * nsSVGOuterSVGFrame::BuildDisplayList, unless the
    * svg.display-lists.painting.enabled pref has been set to false by the user
    * in which case it is done via an nsSVGOuterSVGFrame::PaintSVG() call that
    * recurses over the entire SVG frame tree.  In future we may use PaintSVG()
    * calls on SVG container frames to avoid display list construction when it
    * is expensive and unnecessary (see bug 934411).
-   *
-   * @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 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(PaintSVGParam& aParam) = 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/nsSVGForeignObjectFrame.cpp
+++ b/layout/svg/nsSVGForeignObjectFrame.cpp
@@ -197,103 +197,105 @@ nsSVGForeignObjectFrame::IsSVGTransforme
                                        gfxMatrix(),
                                        eUserSpaceToParent));
     }
     foundTransform = true;
   }
   return foundTransform;
 }
 
-DrawResult
-nsSVGForeignObjectFrame::PaintSVG(gfxContext& aContext,
-                                  const gfxMatrix& aTransform,
-                                  const nsIntRect* aDirtyRect,
-                                  uint32_t aFlags)
+void
+nsSVGForeignObjectFrame::PaintSVG(PaintSVGParam& aParam)
 {
   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()) {
+  const gfxMatrix& transform = aParam.transform;
+  if (transform.IsSingular()) {
     NS_WARNING("Can't render foreignObject element!");
-    return DrawResult::SUCCESS;
+    return;
   }
 
   nsRect kidDirtyRect = kid->GetVisualOverflowRect();
-
+  const nsIntRect* dirtyRect = aParam.dirtyRect;
   /* Check if we need to draw anything. */
-  if (aDirtyRect) {
+  if (dirtyRect) {
     NS_ASSERTION(!NS_SVGDisplayListPaintingEnabled() ||
                  (mState & NS_FRAME_IS_NONDISPLAY),
                  "Display lists handle dirty rect intersection test");
     // Transform the dirty rect into app units in our userspace.
-    gfxMatrix invmatrix = aTransform;
+    gfxMatrix invmatrix = transform;
     DebugOnly<bool> ok = invmatrix.Invert();
     NS_ASSERTION(ok, "inverse of non-singular matrix should be non-singular");
 
-    gfxRect transDirtyRect = gfxRect(aDirtyRect->x, aDirtyRect->y,
-                                     aDirtyRect->width, aDirtyRect->height);
+    gfxRect transDirtyRect = gfxRect(dirtyRect->x, dirtyRect->y,
+                                     dirtyRect->width, dirtyRect->height);
     transDirtyRect = invmatrix.TransformBounds(transDirtyRect);
 
     kidDirtyRect.IntersectRect(kidDirtyRect,
       nsLayoutUtils::RoundGfxRectToAppRect(transDirtyRect,
                        PresContext()->AppUnitsPerCSSPixel()));
 
-    // XXX after bug 614732 is fixed, we will compare mRect with aDirtyRect,
+    // XXX after bug 614732 is fixed, we will compare mRect with dirtyRect,
     // not with kidDirtyRect. I.e.
     // int32_t appUnitsPerDevPx = PresContext()->AppUnitsPerDevPixel();
-    // mRect.ToOutsidePixels(appUnitsPerDevPx).Intersects(*aDirtyRect)
-    if (kidDirtyRect.IsEmpty())
-      return DrawResult::SUCCESS;
+    // mRect.ToOutsidePixels(appUnitsPerDevPx).Intersects(*dirtyRect)
+    if (kidDirtyRect.IsEmpty()) {
+      return;
+    }
   }
 
-  aContext.Save();
+  gfxContext& context = aParam.context;
+  context.Save();
 
   if (StyleDisplay()->IsScrollableOverflow()) {
     float x, y, width, height;
     static_cast<nsSVGElement*>(mContent)->
       GetAnimatedLengthValues(&x, &y, &width, &height, nullptr);
 
     gfxRect clipRect =
       nsSVGUtils::GetClipRectForFrame(this, 0.0f, 0.0f, width, height);
-    nsSVGUtils::SetClipRect(&aContext, aTransform, clipRect);
+    nsSVGUtils::SetClipRect(&context, transform, clipRect);
   }
 
   // SVG paints in CSS px, but normally frames paint in dev pixels. Here we
-  // multiply a CSS-px-to-dev-pixel factor onto aTransform so our children
+  // multiply a CSS-px-to-dev-pixel factor onto transform so our children
   // paint correctly.
   float cssPxPerDevPx = PresContext()->
     AppUnitsToFloatCSSPixels(PresContext()->AppUnitsPerDevPixel());
-  gfxMatrix canvasTMForChildren = aTransform;
+  gfxMatrix canvasTMForChildren = transform;
   canvasTMForChildren.Scale(cssPxPerDevPx, cssPxPerDevPx);
 
-  aContext.Multiply(canvasTMForChildren);
+  context.Multiply(canvasTMForChildren);
 
   using PaintFrameFlags = nsLayoutUtils::PaintFrameFlags;
   PaintFrameFlags flags = PaintFrameFlags::PAINT_IN_TRANSFORM;
-  if (SVGAutoRenderState::IsPaintingToWindow(aContext.GetDrawTarget())) {
+  if (SVGAutoRenderState::IsPaintingToWindow(context.GetDrawTarget())) {
     flags |= PaintFrameFlags::PAINT_TO_WINDOW;
   }
-  nsRenderingContext rendCtx(&aContext);
+  nsRenderingContext rendCtx(&context);
   nsresult rv = nsLayoutUtils::PaintFrame(&rendCtx, kid, nsRegion(kidDirtyRect),
                                          NS_RGBA(0,0,0,0),
                                          nsDisplayListBuilderMode::PAINTING,
                                          flags);
 
-  aContext.Restore();
+  context.Restore();
 
-  return NS_FAILED(rv) ? DrawResult::BAD_ARGS : DrawResult::SUCCESS;
+  aParam.result = 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
@@ -69,20 +69,17 @@ 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(PaintSVGParam& aParam) 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
@@ -61,20 +61,17 @@ 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(PaintSVGParam& aParam) 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 +323,23 @@ nsSVGImageFrame::TransformContextForPain
   }
 
   aGfxContext->Multiply(ThebesMatrix(imageTransform));
   return true;
 }
 
 //----------------------------------------------------------------------
 // nsSVGDisplayableFrame methods:
-DrawResult
-nsSVGImageFrame::PaintSVG(gfxContext& aContext,
-                          const gfxMatrix& aTransform,
-                          const nsIntRect *aDirtyRect,
-                          uint32_t aFlags)
+
+void
+nsSVGImageFrame::PaintSVG(PaintSVGParam& aParam)
 {
-  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) {
@@ -353,104 +349,106 @@ nsSVGImageFrame::PaintSVG(gfxContext& aC
       imageLoader->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST,
                               getter_AddRefs(currentRequest));
 
     if (currentRequest)
       currentRequest->GetImage(getter_AddRefs(mImageContainer));
   }
 
   DrawResult result = DrawResult::SUCCESS;
+  gfxContext& context = aParam.context;
+  const gfxMatrix& transform = aParam.transform;
   if (mImageContainer) {
-    gfxContextAutoSaveRestore autoRestorer(&aContext);
+    gfxContextAutoSaveRestore autoRestorer(&context);
 
     if (StyleDisplay()->IsScrollableOverflow()) {
       gfxRect clipRect = nsSVGUtils::GetClipRectForFrame(this, x, y,
                                                          width, height);
-      nsSVGUtils::SetClipRect(&aContext, aTransform, clipRect);
+      nsSVGUtils::SetClipRect(&context, transform, clipRect);
     }
 
-    if (!TransformContextForPainting(&aContext, aTransform)) {
-      return DrawResult::SUCCESS;
+    if (!TransformContextForPainting(&context, transform)) {
+      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;
     }
 
     if (opacity != 1.0f || StyleEffects()->mMixBlendMode != NS_STYLE_BLEND_NORMAL) {
-      aContext.PushGroupForBlendBack(gfxContentType::COLOR_ALPHA, opacity);
+      context.PushGroupForBlendBack(gfxContentType::COLOR_ALPHA, opacity);
     }
 
     nscoord appUnitsPerDevPx = PresContext()->AppUnitsPerDevPixel();
-    nsRect dirtyRect; // only used if aDirtyRect is non-null
-    if (aDirtyRect) {
+    nsRect dirtyRect; // only used if aParam.dirtyRec is non-null
+    if (aParam.dirtyRect) {
       NS_ASSERTION(!NS_SVGDisplayListPaintingEnabled() ||
                    (mState & NS_FRAME_IS_NONDISPLAY),
                    "Display lists handle dirty rect intersection test");
-      dirtyRect = ToAppUnits(*aDirtyRect, appUnitsPerDevPx);
+      dirtyRect = ToAppUnits(*aParam.dirtyRect, appUnitsPerDevPx);
       // Adjust dirtyRect to match our local coordinate system.
       nsRect rootRect =
-        nsSVGUtils::TransformFrameRectToOuterSVG(mRect, aTransform,
+        nsSVGUtils::TransformFrameRectToOuterSVG(mRect, transform,
                                                  PresContext());
       dirtyRect.MoveBy(-rootRect.TopLeft());
     }
 
     if (mImageContainer->GetType() == imgIContainer::TYPE_VECTOR) {
       // Package up the attributes of this image element which can override the
       // attributes of mImageContainer's internal SVG document.  The 'width' &
       // 'height' values we're passing in here are in CSS units (though they
       // come from width/height *attributes* in SVG). They influence the region
       // of the SVG image's internal document that is visible, in combination
       // with preserveAspectRatio and viewBox.
-      const Maybe<SVGImageContext> context(
+      const Maybe<SVGImageContext> svgContext(
         Some(SVGImageContext(Some(CSSIntSize::Truncate(width, height)),
                              Some(imgElem->mPreserveAspectRatio.GetAnimValue()),
                              /* aIsPaintingSVGImageElement */ true)));
 
       // For the actual draw operation to draw crisply (and at the right size),
       // our destination rect needs to be |width|x|height|, *in dev pixels*.
       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(
-        aContext,
+        context,
         PresContext(),
         mImageContainer,
         nsLayoutUtils::GetSamplingFilterForFrame(this),
         destRect,
-        aDirtyRect ? dirtyRect : destRect,
-        context,
-        aFlags);
+        aParam.dirtyRect ? dirtyRect : destRect,
+        svgContext,
+        aParam.imageFlags);
     } else { // mImageContainer->GetType() == TYPE_RASTER
       result = nsLayoutUtils::DrawSingleUnscaledImage(
-        aContext,
+        context,
         PresContext(),
         mImageContainer,
         nsLayoutUtils::GetSamplingFilterForFrame(this),
         nsPoint(0, 0),
-        aDirtyRect ? &dirtyRect : nullptr,
-        aFlags);
+        aParam.dirtyRect ? &dirtyRect : nullptr,
+        aParam.imageFlags);
     }
 
     if (opacity != 1.0f || StyleEffects()->mMixBlendMode != NS_STYLE_BLEND_NORMAL) {
-      aContext.PopGroupAndBlend();
+      context.PopGroupAndBlend();
     }
     // gfxContextAutoSaveRestore goes out of scope & cleans up our gfxContext
   }
 
-  return result;
+  aParam.result = 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
@@ -53,45 +53,42 @@ nsIAtom *
 nsSVGInnerSVGFrame::GetType() const
 {
   return nsGkAtoms::svgInnerSVGFrame;
 }
 
 //----------------------------------------------------------------------
 // nsSVGDisplayableFrame methods
 
-DrawResult
-nsSVGInnerSVGFrame::PaintSVG(gfxContext& aContext,
-                             const gfxMatrix& aTransform,
-                             const nsIntRect *aDirtyRect,
-                             uint32_t aFlags)
+void
+nsSVGInnerSVGFrame::PaintSVG(PaintSVGParam& aParam)
 {
   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);
+    autoSR.SetContext(&aParam.context);
     gfxRect clipRect =
       nsSVGUtils::GetClipRectForFrame(this, x, y, width, height);
-    nsSVGUtils::SetClipRect(&aContext, aTransform, clipRect);
+    nsSVGUtils::SetClipRect(&aParam.context, aParam.transform, clipRect);
   }
 
-  return nsSVGDisplayContainerFrame::PaintSVG(aContext, aTransform, aDirtyRect, aFlags);
+  nsSVGDisplayContainerFrame::PaintSVG(aParam);
 }
 
 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
@@ -47,20 +47,17 @@ 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(PaintSVGParam& aParam) 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/nsSVGOuterSVGFrame.cpp
+++ b/layout/svg/nsSVGOuterSVGFrame.cpp
@@ -864,29 +864,27 @@ nsSVGOuterSVGFrame::NotifyViewportOrTran
   }
 
   nsSVGUtils::NotifyChildrenOfSVGChange(PrincipalChildList().FirstChild(), aFlags);
 }
 
 //----------------------------------------------------------------------
 // nsSVGDisplayableFrame methods:
 
-DrawResult
-nsSVGOuterSVGFrame::PaintSVG(gfxContext& aContext,
-                             const gfxMatrix& aTransform,
-                             const nsIntRect* aDirtyRect,
-                             uint32_t aFlags)
+void
+nsSVGOuterSVGFrame::PaintSVG(PaintSVGParam& aParam)
 {
   NS_ASSERTION(PrincipalChildList().FirstChild()->GetType() ==
                  nsGkAtoms::svgOuterSVGAnonChildFrame &&
                !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(aParam);
 }
 
 SVGBBox
 nsSVGOuterSVGFrame::GetBBoxContribution(const gfx::Matrix &aToBBoxUserspace,
                                         uint32_t aFlags)
 {
   NS_ASSERTION(PrincipalChildList().FirstChild()->GetType() ==
                  nsGkAtoms::svgOuterSVGAnonChildFrame &&
--- a/layout/svg/nsSVGOuterSVGFrame.h
+++ b/layout/svg/nsSVGOuterSVGFrame.h
@@ -109,20 +109,17 @@ 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(PaintSVGParam& aParam) 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/nsSVGSwitchFrame.cpp
+++ b/layout/svg/nsSVGSwitchFrame.cpp
@@ -44,20 +44,17 @@ 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(PaintSVGParam& aParam) override;
   nsIFrame* GetFrameForPoint(const gfxPoint& aPoint) override;
   virtual void ReflowSVG() override;
   virtual SVGBBox GetBBoxContribution(const Matrix &aToBBoxUserspace,
                                       uint32_t aFlags) override;
 
 private:
   nsIFrame *GetActiveChildFrame();
 };
@@ -98,41 +95,37 @@ nsSVGSwitchFrame::BuildDisplayList(nsDis
                                    const nsDisplayListSet& aLists)
 {
   nsIFrame* kid = GetActiveChildFrame();
   if (kid) {
     BuildDisplayListForChild(aBuilder, kid, aDirtyRect, aLists);
   }
 }
 
-DrawResult
-nsSVGSwitchFrame::PaintSVG(gfxContext& aContext,
-                           const gfxMatrix& aTransform,
-                           const nsIntRect* aDirtyRect,
-                           uint32_t aFlags)
+void
+nsSVGSwitchFrame::PaintSVG(PaintSVGParam& aParam)
 {
   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;
+    gfxMatrix tm = aParam.transform;
     if (kid->GetContent()->IsSVGElement()) {
       tm = static_cast<nsSVGElement*>(kid->GetContent())->
              PrependLocalTransformsTo(tm, eUserSpaceToParent);
     }
-    result = nsSVGUtils::PaintFrameWithEffects(kid, aContext, tm, aDirtyRect);
+    aParam.result = nsSVGUtils::PaintFrameWithEffects(kid, aParam.context, tm,                                                aParam.dirtyRect);
   }
-  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
@@ -495,19 +495,23 @@ public:
       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);
+    DrawResult result = DrawResult::SUCCESS;
+    nsSVGDisplayableFrame::PaintSVGParam
+      param(aContext, nsSVGUtils::GetCSSPxToDevPxMatrix(aTarget), result,
+            dirtyRect, mFlags);
+
+    svgFrame->PaintSVG(param);
+    return result;
   }
 
 private:
   uint32_t mFlags;
 };
 
 float
 nsSVGUtils::ComputeOpacity(nsIFrame* aFrame, bool aHandleOpacity)
@@ -884,17 +888,20 @@ nsSVGUtils::PaintFrameWithEffects(nsIFra
     }
 
     SVGPaintCallback paintCallback(aFlags);
     result =
       nsFilterInstance::PaintFilteredFrame(aFrame, target->GetDrawTarget(),
                                            aTransform, &paintCallback,
                                            dirtyRegion);
   } else {
-    result = svgFrame->PaintSVG(*target, aTransform, aDirtyRect, aFlags);
+    nsSVGDisplayableFrame::PaintSVGParam param(*target, aTransform, result,
+                                               aDirtyRect, aFlags);
+
+    svgFrame->PaintSVG(param);
   }
 
   if (maskUsage.shouldApplyClipPath || maskUsage.shouldApplyBasicShape) {
     aContext.PopClip();
   }
 
   if (shouldPushMask) {
     target->PopGroupAndBlend();
@@ -1870,18 +1877,26 @@ nsSVGUtils::PaintSVGGlyph(Element* aElem
   }
   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);
+
+  // XXX cku: Bug 1358555 The caller should pass imageFlags to
+  // nsSVGUtils::PaintSVGGlyph.
+  DrawResult result = DrawResult::SUCCESS;
+  nsSVGDisplayableFrame::PaintSVGParam param(*aContext, m, result);
+  svgFrame->PaintSVG(param);
+
+  // XXX cku: PaintSVGGlyph should return DrawResult to the caller by an
+  // out param.
+  return true;
 }
 
 bool
 nsSVGUtils::GetSVGGlyphExtents(Element* aElement,
                                const gfxMatrix& aSVGToAppSpace,
                                gfxRect* aResult)
 {
   nsIFrame* frame = aElement->GetPrimaryFrame();