Bug 1073964 - Pass a const DrawTarget* through to nsSVGPaintServerFrame::GetPaintServerPattern so that it can create a pattern of the appropriate type. r=Bas
authorJonathan Watt <jwatt@jwatt.org>
Mon, 29 Sep 2014 14:15:19 +0100
changeset 207690 ece627b5e46a3b66e6af9df6017921789209a7d3
parent 207689 5805c4e57d56dde75d4a8bfa5dd72fe146a9fffd
child 207691 621ac0d4d8c91d0d4992c0ecd7e8821c411cc7ad
push id27564
push userryanvm@gmail.com
push dateMon, 29 Sep 2014 18:57:04 +0000
treeherdermozilla-central@ce9a0b34225e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersBas
bugs1073964
milestone35.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1073964 - Pass a const DrawTarget* through to nsSVGPaintServerFrame::GetPaintServerPattern so that it can create a pattern of the appropriate type. r=Bas
gfx/thebes/gfxFont.cpp
gfx/thebes/gfxGradientCache.cpp
gfx/thebes/gfxGradientCache.h
gfx/thebes/gfxPattern.cpp
gfx/thebes/gfxPattern.h
gfx/thebes/gfxSVGGlyphs.h
layout/base/nsCSSRendering.cpp
layout/svg/SVGTextFrame.cpp
layout/svg/SVGTextFrame.h
layout/svg/nsSVGGradientFrame.cpp
layout/svg/nsSVGGradientFrame.h
layout/svg/nsSVGIntegrationUtils.cpp
layout/svg/nsSVGIntegrationUtils.h
layout/svg/nsSVGPaintServerFrame.h
layout/svg/nsSVGPatternFrame.cpp
layout/svg/nsSVGPatternFrame.h
layout/svg/nsSVGUtils.cpp
--- a/gfx/thebes/gfxFont.cpp
+++ b/gfx/thebes/gfxFont.cpp
@@ -1543,16 +1543,17 @@ private:
         }
         if (int(mRunParams.drawMode) & int(DrawMode::GLYPH_FILL)) {
             if (state.pattern || mFontParams.contextPaint) {
                 Pattern *pat;
 
                 nsRefPtr<gfxPattern> fillPattern;
                 if (!mFontParams.contextPaint ||
                     !(fillPattern = mFontParams.contextPaint->GetFillPattern(
+                                        mRunParams.context->GetDrawTarget(),
                                         mRunParams.context->CurrentMatrix()))) {
                     if (state.pattern) {
                         pat = state.pattern->GetPattern(mRunParams.dt,
                                       state.patternTransformChanged ?
                                           &state.patternTransform : nullptr);
                     } else {
                         pat = nullptr;
                     }
@@ -1625,16 +1626,17 @@ private:
 
     void FlushStroke(gfx::GlyphBuffer& aBuf, gfxContext::AzureState& aState)
     {
         RefPtr<Path> path =
             mFontParams.scaledFont->GetPathForGlyphs(aBuf, mRunParams.dt);
         if (mFontParams.contextPaint) {
             nsRefPtr<gfxPattern> strokePattern =
                 mFontParams.contextPaint->GetStrokePattern(
+                    mRunParams.context->GetDrawTarget(),
                     mRunParams.context->CurrentMatrix());
             if (strokePattern) {
                 mRunParams.dt->Stroke(path,
                                       *strokePattern->GetPattern(mRunParams.dt),
                                       aState.strokeOptions);
             }
         }
     }
--- a/gfx/thebes/gfxGradientCache.cpp
+++ b/gfx/thebes/gfxGradientCache.cpp
@@ -173,28 +173,28 @@ class GradientCache MOZ_FINAL : public n
      * https://bugzilla.mozilla.org/show_bug.cgi?id=761393#c47
      */
     nsClassHashtable<GradientCacheKey, GradientCacheData> mHashEntries;
 };
 
 static GradientCache* gGradientCache = nullptr;
 
 GradientStops *
-gfxGradientCache::GetGradientStops(DrawTarget *aDT, nsTArray<GradientStop>& aStops, ExtendMode aExtend)
+gfxGradientCache::GetGradientStops(const DrawTarget *aDT, nsTArray<GradientStop>& aStops, ExtendMode aExtend)
 {
   if (!gGradientCache) {
     gGradientCache = new GradientCache();
   }
   GradientCacheData* cached =
     gGradientCache->Lookup(aStops, aExtend, aDT->GetBackendType());
   return cached ? cached->mStops : nullptr;
 }
 
 GradientStops *
-gfxGradientCache::GetOrCreateGradientStops(DrawTarget *aDT, nsTArray<GradientStop>& aStops, ExtendMode aExtend)
+gfxGradientCache::GetOrCreateGradientStops(const DrawTarget *aDT, nsTArray<GradientStop>& aStops, ExtendMode aExtend)
 {
   RefPtr<GradientStops> gs = GetGradientStops(aDT, aStops, aExtend);
   if (!gs) {
     gs = aDT->CreateGradientStops(aStops.Elements(), aStops.Length(), aExtend);
     if (!gs) {
       return nullptr;
     }
     GradientCacheData *cached =
--- a/gfx/thebes/gfxGradientCache.h
+++ b/gfx/thebes/gfxGradientCache.h
@@ -12,22 +12,22 @@
 #include "mozilla/gfx/2D.h"
 
 namespace mozilla {
 namespace gfx {
 
 class gfxGradientCache {
 public:
     static gfx::GradientStops*
-    GetGradientStops(gfx::DrawTarget *aDT,
+    GetGradientStops(const gfx::DrawTarget *aDT,
                      nsTArray<gfx::GradientStop>& aStops,
                      gfx::ExtendMode aExtend);
 
     static gfx::GradientStops*
-    GetOrCreateGradientStops(gfx::DrawTarget *aDT,
+    GetOrCreateGradientStops(const gfx::DrawTarget *aDT,
                              nsTArray<gfx::GradientStop>& aStops,
                              gfx::ExtendMode aExtend);
 
     static void PurgeAllCaches();
     static void Shutdown();
 };
 
 }
--- a/gfx/thebes/gfxPattern.cpp
+++ b/gfx/thebes/gfxPattern.cpp
@@ -73,17 +73,17 @@ gfxPattern::AddColorStop(gfxFloat offset
 
 void
 gfxPattern::SetColorStops(GradientStops* aStops)
 {
   mStops = aStops;
 }
 
 void
-gfxPattern::CacheColorStops(DrawTarget *aDT)
+gfxPattern::CacheColorStops(const DrawTarget *aDT)
 {
   mStops = gfxGradientCache::GetOrCreateGradientStops(aDT, mStopsList,
                                                       ToExtendMode(mExtend));
 }
 
 void
 gfxPattern::SetMatrix(const gfxMatrix& aPatternToUserSpace)
 {
--- a/gfx/thebes/gfxPattern.h
+++ b/gfx/thebes/gfxPattern.h
@@ -36,17 +36,17 @@ public:
                const mozilla::gfx::Matrix &aPatternToUserSpace);
 
     void AddColorStop(gfxFloat offset, const gfxRGBA& c);
     void SetColorStops(mozilla::gfx::GradientStops* aStops);
 
     // This should only be called on a cairo pattern that we want to use with
     // Azure. We will read back the color stops from cairo and try to look
     // them up in the cache.
-    void CacheColorStops(mozilla::gfx::DrawTarget *aDT);
+    void CacheColorStops(const mozilla::gfx::DrawTarget *aDT);
 
     void SetMatrix(const gfxMatrix& matrix);
     gfxMatrix GetMatrix() const;
     gfxMatrix GetInverseMatrix() const;
 
     /* Get an Azure Pattern for the current Cairo pattern. aPattern transform
      * specifies the transform that was set on the DrawTarget when the pattern
      * was set. When this is nullptr it is assumed the transform is identical
--- a/gfx/thebes/gfxSVGGlyphs.h
+++ b/gfx/thebes/gfxSVGGlyphs.h
@@ -1,16 +1,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef GFX_SVG_GLYPHS_WRAPPER_H
 #define GFX_SVG_GLYPHS_WRAPPER_H
 
 #include "gfxFontUtils.h"
+#include "mozilla/gfx/2D.h"
 #include "nsString.h"
 #include "nsAutoPtr.h"
 #include "nsClassHashtable.h"
 #include "nsBaseHashtable.h"
 #include "nsHashKeys.h"
 #include "gfxPattern.h"
 #include "mozilla/gfx/UserData.h"
 #include "nsRefreshDriver.h"
@@ -161,29 +162,33 @@ private:
 };
 
 /**
  * Used for trickling down paint information through to SVG glyphs.
  */
 class gfxTextContextPaint
 {
 protected:
+    typedef mozilla::gfx::DrawTarget DrawTarget;
+
     gfxTextContextPaint() { }
 
 public:
     static mozilla::gfx::UserDataKey sUserDataKey;
 
     /*
      * Get text context pattern with the specified opacity value.
      * This lets us inherit paints and paint opacities (i.e. fill/stroke and
      * fill-opacity/stroke-opacity) separately.
      */
-    virtual already_AddRefed<gfxPattern> GetFillPattern(float aOpacity,
+    virtual already_AddRefed<gfxPattern> GetFillPattern(const DrawTarget* aDrawTarget,
+                                                        float aOpacity,
                                                         const gfxMatrix& aCTM) = 0;
-    virtual already_AddRefed<gfxPattern> GetStrokePattern(float aOpacity,
+    virtual already_AddRefed<gfxPattern> GetStrokePattern(const DrawTarget* aDrawTarget,
+                                                          float aOpacity,
                                                           const gfxMatrix& aCTM) = 0;
 
     virtual float GetFillOpacity() { return 1.0f; }
     virtual float GetStrokeOpacity() { return 1.0f; }
 
     void InitStrokeGeometry(gfxContext *aContext,
                             float devUnitsPerSVGUnit);
 
@@ -194,22 +199,24 @@ public:
     gfxFloat GetStrokeDashOffset() {
         return mDashOffset;
     }
 
     gfxFloat GetStrokeWidth() {
         return mStrokeWidth;
     }
 
-    already_AddRefed<gfxPattern> GetFillPattern(const gfxMatrix& aCTM) {
-        return GetFillPattern(GetFillOpacity(), aCTM);
+    already_AddRefed<gfxPattern> GetFillPattern(const DrawTarget* aDrawTarget,
+                                                const gfxMatrix& aCTM) {
+        return GetFillPattern(aDrawTarget, GetFillOpacity(), aCTM);
     }
 
-    already_AddRefed<gfxPattern> GetStrokePattern(const gfxMatrix& aCTM) {
-        return GetStrokePattern(GetStrokeOpacity(), aCTM);
+    already_AddRefed<gfxPattern> GetStrokePattern(const DrawTarget* aDrawTarget,
+                                                  const gfxMatrix& aCTM) {
+        return GetStrokePattern(aDrawTarget, GetStrokeOpacity(), aCTM);
     }
 
     virtual ~gfxTextContextPaint() { }
 
 private:
     FallibleTArray<gfxFloat> mDashes;
     gfxFloat mDashOffset;
     gfxFloat mStrokeWidth;
@@ -242,26 +249,28 @@ public:
                           const gfxMatrix& aCTM) :
         mFillPattern(aFillPattern ? aFillPattern : new gfxPattern(sZero)),
         mStrokePattern(aStrokePattern ? aStrokePattern : new gfxPattern(sZero))
     {
         mFillMatrix = SetupDeviceToPatternMatrix(aFillPattern, aCTM);
         mStrokeMatrix = SetupDeviceToPatternMatrix(aStrokePattern, aCTM);
     }
 
-    already_AddRefed<gfxPattern> GetFillPattern(float aOpacity,
+    already_AddRefed<gfxPattern> GetFillPattern(const DrawTarget* aDrawTarget,
+                                                float aOpacity,
                                                 const gfxMatrix& aCTM) {
         if (mFillPattern) {
             mFillPattern->SetMatrix(aCTM * mFillMatrix);
         }
         nsRefPtr<gfxPattern> fillPattern = mFillPattern;
         return fillPattern.forget();
     }
 
-    already_AddRefed<gfxPattern> GetStrokePattern(float aOpacity,
+    already_AddRefed<gfxPattern> GetStrokePattern(const DrawTarget* aDrawTarget,
+                                                  float aOpacity,
                                                   const gfxMatrix& aCTM) {
         if (mStrokePattern) {
             mStrokePattern->SetMatrix(aCTM * mStrokeMatrix);
         }
         nsRefPtr<gfxPattern> strokePattern = mStrokePattern;
         return strokePattern.forget();
     }
 
--- a/layout/base/nsCSSRendering.cpp
+++ b/layout/base/nsCSSRendering.cpp
@@ -4694,16 +4694,17 @@ nsImageRenderer::DrawableForElement(cons
   if (mPaintServerFrame) {
     int32_t appUnitsPerDevPixel = mForFrame->PresContext()->AppUnitsPerDevPixel();
     nsRect destRect = aImageRect - aImageRect.TopLeft();
     nsIntSize roundedOut = destRect.ToOutsidePixels(appUnitsPerDevPixel).Size();
     gfxIntSize imageSize(roundedOut.width, roundedOut.height);
     nsRefPtr<gfxDrawable> drawable =
       nsSVGIntegrationUtils::DrawableFromPaintServer(
         mPaintServerFrame, mForFrame, mSize, imageSize,
+        aRenderingContext.GetDrawTarget(),
         aRenderingContext.ThebesContext()->CurrentMatrix(),
         mFlags & FLAG_SYNC_DECODE_IMAGES
           ? nsSVGIntegrationUtils::FLAG_SYNC_DECODE_IMAGES
           : 0);
 
     return drawable.forget();
   }
   NS_ASSERTION(mImageElementSurface.mSourceSurface, "Surface should be ready.");
--- a/layout/svg/SVGTextFrame.cpp
+++ b/layout/svg/SVGTextFrame.cpp
@@ -2988,31 +2988,34 @@ SVGTextDrawPathCallbacks::StrokeGeometry
     }
   }
 }
 
 //----------------------------------------------------------------------
 // SVGTextContextPaint methods:
 
 already_AddRefed<gfxPattern>
-SVGTextContextPaint::GetFillPattern(float aOpacity,
+SVGTextContextPaint::GetFillPattern(const DrawTarget* aDrawTarget,
+                                    float aOpacity,
                                     const gfxMatrix& aCTM)
 {
-  return mFillPaint.GetPattern(aOpacity, &nsStyleSVG::mFill, aCTM);
+  return mFillPaint.GetPattern(aDrawTarget, aOpacity, &nsStyleSVG::mFill, aCTM);
 }
 
 already_AddRefed<gfxPattern>
-SVGTextContextPaint::GetStrokePattern(float aOpacity,
+SVGTextContextPaint::GetStrokePattern(const DrawTarget* aDrawTarget,
+                                      float aOpacity,
                                       const gfxMatrix& aCTM)
 {
-  return mStrokePaint.GetPattern(aOpacity, &nsStyleSVG::mStroke, aCTM);
+  return mStrokePaint.GetPattern(aDrawTarget, aOpacity, &nsStyleSVG::mStroke, aCTM);
 }
 
 already_AddRefed<gfxPattern>
-SVGTextContextPaint::Paint::GetPattern(float aOpacity,
+SVGTextContextPaint::Paint::GetPattern(const DrawTarget* aDrawTarget,
+                                       float aOpacity,
                                        nsStyleSVGPaint nsStyleSVG::*aFillOrStroke,
                                        const gfxMatrix& aCTM)
 {
   nsRefPtr<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.
@@ -3029,38 +3032,41 @@ SVGTextContextPaint::Paint::GetPattern(f
     pattern = new gfxPattern(gfxRGBA(NS_GET_R(mPaintDefinition.mColor) / 255.0,
                                      NS_GET_G(mPaintDefinition.mColor) / 255.0,
                                      NS_GET_B(mPaintDefinition.mColor) / 255.0,
                                      NS_GET_A(mPaintDefinition.mColor) / 255.0 * aOpacity));
     mPatternMatrix = gfxMatrix();
     break;
   case eStyleSVGPaintType_Server:
     pattern = mPaintDefinition.mPaintServerFrame->GetPaintServerPattern(mFrame,
+                                                                        aDrawTarget,
                                                                         mContextMatrix,
                                                                         aFillOrStroke,
                                                                         aOpacity);
     {
       // m maps original-user-space to pattern space
       gfxMatrix m = pattern->GetMatrix();
       gfxMatrix deviceToOriginalUserSpace = mContextMatrix;
       if (!deviceToOriginalUserSpace.Invert()) {
         return nullptr;
       }
       // mPatternMatrix maps device space to pattern space via original user space
       mPatternMatrix = deviceToOriginalUserSpace * m;
     }
     pattern->SetMatrix(aCTM * mPatternMatrix);
     break;
   case eStyleSVGPaintType_ContextFill:
-    pattern = mPaintDefinition.mContextPaint->GetFillPattern(aOpacity, aCTM);
+    pattern = mPaintDefinition.mContextPaint->GetFillPattern(aDrawTarget,
+                                                             aOpacity, aCTM);
     // Don't cache this. mContextPaint will have cached it anyway. If we
     // cache it, we'll have to compute mPatternMatrix, which is annoying.
     return pattern.forget();
   case eStyleSVGPaintType_ContextStroke:
-    pattern = mPaintDefinition.mContextPaint->GetStrokePattern(aOpacity, aCTM);
+    pattern = mPaintDefinition.mContextPaint->GetStrokePattern(aDrawTarget,
+                                                               aOpacity, aCTM);
     // Don't cache this. mContextPaint will have cached it anyway. If we
     // cache it, we'll have to compute mPatternMatrix, which is annoying.
     return pattern.forget();
   default:
     MOZ_ASSERT(false, "invalid paint type");
     return nullptr;
   }
 
@@ -3672,18 +3678,18 @@ SVGTextFrame::PaintSVG(nsRenderingContex
     // Set up the fill and stroke so that SVG glyphs can get painted correctly
     // when they use context-fill etc.
     gfx->SetMatrix(initialMatrix);
     gfxTextContextPaint *outerContextPaint =
       (gfxTextContextPaint*)aContext->GetDrawTarget()->GetUserData(&gfxTextContextPaint::sUserDataKey);
 
     SVGTextContextPaint contextPaint;
     DrawMode drawMode =
-      SetupContextPaint(gfx->CurrentMatrix(), frame, outerContextPaint,
-                        &contextPaint);
+      SetupContextPaint(gfx->GetDrawTarget(), gfx->CurrentMatrix(),
+                        frame, outerContextPaint, &contextPaint);
 
     if (int(drawMode) & int(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, gfx, outerContextPaint);
     }
 
     // Set up the transform for painting the text frame for the substring
@@ -5582,94 +5588,101 @@ SVGTextFrame::TransformFrameRectFromText
  * 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 void
-SetupInheritablePaint(const gfxMatrix& aContextMatrix,
+SetupInheritablePaint(const DrawTarget* aDrawTarget,
+                      const gfxMatrix& aContextMatrix,
                       nsIFrame* aFrame,
                       float& aOpacity,
                       gfxTextContextPaint* aOuterContextPaint,
                       SVGTextContextPaint::Paint& aTargetPaint,
                       nsStyleSVGPaint nsStyleSVG::*aFillOrStroke,
                       const FramePropertyDescriptor* aProperty)
 {
   const nsStyleSVG *style = aFrame->StyleSVG();
   nsSVGPaintServerFrame *ps =
     nsSVGEffects::GetPaintServer(aFrame, &(style->*aFillOrStroke), aProperty);
 
   if (ps) {
     nsRefPtr<gfxPattern> pattern =
-      ps->GetPaintServerPattern(aFrame, aContextMatrix, aFillOrStroke, aOpacity);
+      ps->GetPaintServerPattern(aFrame, aDrawTarget, aContextMatrix,
+                                aFillOrStroke, aOpacity);
     if (pattern) {
       aTargetPaint.SetPaintServer(aFrame, aContextMatrix, ps);
       return;
     }
   }
   if (aOuterContextPaint) {
     nsRefPtr<gfxPattern> pattern;
     switch ((style->*aFillOrStroke).mType) {
     case eStyleSVGPaintType_ContextFill:
-      pattern = aOuterContextPaint->GetFillPattern(aOpacity, aContextMatrix);
+      pattern = aOuterContextPaint->GetFillPattern(aDrawTarget, aOpacity,
+                                                   aContextMatrix);
       break;
     case eStyleSVGPaintType_ContextStroke:
-      pattern = aOuterContextPaint->GetStrokePattern(aOpacity, aContextMatrix);
+      pattern = aOuterContextPaint->GetStrokePattern(aDrawTarget, aOpacity,
+                                                     aContextMatrix);
       break;
     default:
       ;
     }
     if (pattern) {
       aTargetPaint.SetContextPaint(aOuterContextPaint, (style->*aFillOrStroke).mType);
       return;
     }
   }
   nscolor color =
     nsSVGUtils::GetFallbackOrPaintColor(aFrame->StyleContext(), aFillOrStroke);
   aTargetPaint.SetColor(color);
 }
 
 DrawMode
-SVGTextFrame::SetupContextPaint(const gfxMatrix& aContextMatrix,
+SVGTextFrame::SetupContextPaint(const DrawTarget* aDrawTarget,
+                                const gfxMatrix& aContextMatrix,
                                 nsIFrame* aFrame,
                                 gfxTextContextPaint* aOuterContextPaint,
                                 SVGTextContextPaint* aThisContextPaint)
 {
   DrawMode toDraw = DrawMode(0);
 
   const nsStyleSVG *style = aFrame->StyleSVG();
 
   // fill:
   if (style->mFill.mType == eStyleSVGPaintType_None) {
     aThisContextPaint->SetFillOpacity(0.0f);
   } else {
     float opacity = nsSVGUtils::GetOpacity(style->mFillOpacitySource,
                                            style->mFillOpacity,
                                            aOuterContextPaint);
 
-    SetupInheritablePaint(aContextMatrix, aFrame, opacity, aOuterContextPaint,
+    SetupInheritablePaint(aDrawTarget, aContextMatrix, aFrame,
+                          opacity, aOuterContextPaint,
                           aThisContextPaint->mFillPaint, &nsStyleSVG::mFill,
                           nsSVGEffects::FillProperty());
 
     aThisContextPaint->SetFillOpacity(opacity);
 
     toDraw = DrawMode(int(toDraw) | int(DrawMode::GLYPH_FILL));
   }
 
   // stroke:
   if (style->mStroke.mType == eStyleSVGPaintType_None) {
     aThisContextPaint->SetStrokeOpacity(0.0f);
   } else {
     float opacity = nsSVGUtils::GetOpacity(style->mStrokeOpacitySource,
                                            style->mStrokeOpacity,
                                            aOuterContextPaint);
 
-    SetupInheritablePaint(aContextMatrix, aFrame, opacity, aOuterContextPaint,
+    SetupInheritablePaint(aDrawTarget, aContextMatrix, aFrame,
+                          opacity, aOuterContextPaint,
                           aThisContextPaint->mStrokePaint, &nsStyleSVG::mStroke,
                           nsSVGEffects::StrokeProperty());
 
     aThisContextPaint->SetStrokeOpacity(opacity);
 
     toDraw = DrawMode(int(toDraw) | int(DrawMode::GLYPH_STROKE));
   }
 
--- a/layout/svg/SVGTextFrame.h
+++ b/layout/svg/SVGTextFrame.h
@@ -134,19 +134,24 @@ public:
   static void Run(SVGTextFrame* aFrame);
   void Revoke() { mFrame = nullptr; }
 private:
   SVGTextFrame* mFrame;
 };
 
 // Slightly horrible callback for deferring application of opacity
 struct SVGTextContextPaint : public gfxTextContextPaint {
-  already_AddRefed<gfxPattern> GetFillPattern(float aOpacity,
+protected:
+  typedef mozilla::gfx::DrawTarget DrawTarget;
+public:
+  already_AddRefed<gfxPattern> GetFillPattern(const DrawTarget* aDrawTarget,
+                                              float aOpacity,
                                               const gfxMatrix& aCTM) MOZ_OVERRIDE;
-  already_AddRefed<gfxPattern> GetStrokePattern(float aOpacity,
+  already_AddRefed<gfxPattern> GetStrokePattern(const DrawTarget* aDrawTarget,
+                                                float aOpacity,
                                                 const gfxMatrix& aCTM) MOZ_OVERRIDE;
 
   void SetFillOpacity(float aOpacity) { mFillOpacity = aOpacity; }
   float GetFillOpacity() MOZ_OVERRIDE { return mFillOpacity; }
 
   void SetStrokeOpacity(float aOpacity) { mStrokeOpacity = aOpacity; }
   float GetStrokeOpacity() MOZ_OVERRIDE { return mStrokeOpacity; }
 
@@ -185,17 +190,18 @@ struct SVGTextContextPaint : public gfxT
     // 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;
 
-    already_AddRefed<gfxPattern> GetPattern(float aOpacity,
+    already_AddRefed<gfxPattern> GetPattern(const DrawTarget* aDrawTarget,
+                                            float aOpacity,
                                             nsStyleSVGPaint nsStyleSVG::*aFillOrStroke,
                                             const gfxMatrix& aCTM);
   };
 
   Paint mFillPaint;
   Paint mStrokePaint;
 
   float mFillOpacity;
@@ -247,16 +253,17 @@ class SVGTextFrame MOZ_FINAL : public SV
   friend class mozilla::GlyphMetricsUpdater;
   friend class mozilla::TextFrameIterator;
   friend class mozilla::TextNodeCorrespondenceRecorder;
   friend struct mozilla::TextRenderedRun;
   friend class mozilla::TextRenderedRunIterator;
   friend class MutationObserver;
   friend class nsDisplaySVGText;
 
+  typedef mozilla::gfx::DrawTarget DrawTarget;
   typedef mozilla::gfx::Path Path;
   typedef mozilla::gfx::Point Point;
   typedef mozilla::SVGTextContextPaint SVGTextContextPaint;
 
 protected:
   explicit SVGTextFrame(nsStyleContext* aContext)
     : SVGTextFrameBase(aContext),
       mFontSizeScaleFactor(1.0f),
@@ -589,17 +596,18 @@ private:
                           bool& aShouldPaintSVGGlyphs);
 
   // Methods to get information for a <textPath> frame.
   nsIFrame* GetTextPathPathFrame(nsIFrame* aTextPathFrame);
   mozilla::TemporaryRef<Path> GetTextPath(nsIFrame* aTextPathFrame);
   gfxFloat GetOffsetScale(nsIFrame* aTextPathFrame);
   gfxFloat GetStartOffset(nsIFrame* aTextPathFrame);
 
-  DrawMode SetupContextPaint(const gfxMatrix& aContextMatrix,
+  DrawMode SetupContextPaint(const DrawTarget* aDrawTarget,
+                             const gfxMatrix& aContextMatrix,
                              nsIFrame* aFrame,
                              gfxTextContextPaint* aOuterContextPaint,
                              SVGTextContextPaint* aThisContextPaint);
 
   /**
    * The MutationObserver we have registered for the <text> element subtree.
    */
   nsRefPtr<MutationObserver> mMutationObserver;
--- a/layout/svg/nsSVGGradientFrame.cpp
+++ b/layout/svg/nsSVGGradientFrame.cpp
@@ -204,21 +204,22 @@ static void GetStopInformation(nsIFrame*
     GetAnimatedNumberValues(aOffset, nullptr);
 
   *aOffset = mozilla::clamped(*aOffset, 0.0f, 1.0f);
   *aStopColor = aStopFrame->StyleSVGReset()->mStopColor;
   *aStopOpacity = aStopFrame->StyleSVGReset()->mStopOpacity;
 }
 
 already_AddRefed<gfxPattern>
-nsSVGGradientFrame::GetPaintServerPattern(nsIFrame *aSource,
+nsSVGGradientFrame::GetPaintServerPattern(nsIFrame* aSource,
+                                          const DrawTarget* aDrawTarget,
                                           const gfxMatrix& aContextMatrix,
                                           nsStyleSVGPaint nsStyleSVG::*aFillOrStroke,
                                           float aGraphicOpacity,
-                                          const gfxRect *aOverrideBounds)
+                                          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
--- a/layout/svg/nsSVGGradientFrame.h
+++ b/layout/svg/nsSVGGradientFrame.h
@@ -42,21 +42,22 @@ class nsSVGGradientFrame : public nsSVGG
 protected:
   explicit nsSVGGradientFrame(nsStyleContext* aContext);
 
 public:
   NS_DECL_FRAMEARENA_HELPERS
 
   // nsSVGPaintServerFrame methods:
   virtual already_AddRefed<gfxPattern>
-    GetPaintServerPattern(nsIFrame *aSource,
+    GetPaintServerPattern(nsIFrame* aSource,
+                          const DrawTarget* aDrawTarget,
                           const gfxMatrix& aContextMatrix,
                           nsStyleSVGPaint nsStyleSVG::*aFillOrStroke,
                           float aGraphicOpacity,
-                          const gfxRect *aOverrideBounds) MOZ_OVERRIDE;
+                          const gfxRect* aOverrideBounds) MOZ_OVERRIDE;
 
   // nsIFrame interface:
   virtual nsresult AttributeChanged(int32_t         aNameSpaceID,
                                     nsIAtom*        aAttribute,
                                     int32_t         aModType) MOZ_OVERRIDE;
 
 #ifdef DEBUG_FRAME_DUMP
   virtual nsresult GetFrameName(nsAString& aResult) const MOZ_OVERRIDE
--- a/layout/svg/nsSVGIntegrationUtils.cpp
+++ b/layout/svg/nsSVGIntegrationUtils.cpp
@@ -690,16 +690,17 @@ PaintFrameCallback::operator()(gfxContex
   return true;
 }
 
 /* static */ already_AddRefed<gfxDrawable>
 nsSVGIntegrationUtils::DrawableFromPaintServer(nsIFrame*         aFrame,
                                                nsIFrame*         aTarget,
                                                const nsSize&     aPaintServerSize,
                                                const gfxIntSize& aRenderSize,
+                                               const DrawTarget* aDrawTarget,
                                                const gfxMatrix&  aContextMatrix,
                                                uint32_t          aFlags)
 {
   // aPaintServerSize is the size that would be filled when using
   // background-repeat:no-repeat and background-size:auto. For normal background
   // images, this would be the intrinsic size of the image; for gradients and
   // patterns this would be the whole target frame fill area.
   // aRenderSize is what we will be actually filling after accounting for
@@ -710,18 +711,19 @@ nsSVGIntegrationUtils::DrawableFromPaint
     // area.
     nsSVGPaintServerFrame* server =
       static_cast<nsSVGPaintServerFrame*>(aFrame);
 
     gfxRect overrideBounds(0, 0,
                            aPaintServerSize.width, aPaintServerSize.height);
     overrideBounds.ScaleInverse(aFrame->PresContext()->AppUnitsPerDevPixel());
     nsRefPtr<gfxPattern> pattern =
-      server->GetPaintServerPattern(aTarget, aContextMatrix,
-                                    &nsStyleSVG::mFill, 1.0, &overrideBounds);
+    server->GetPaintServerPattern(aTarget, aDrawTarget,
+                                  aContextMatrix, &nsStyleSVG::mFill, 1.0,
+                                  &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
@@ -17,30 +17,35 @@ class nsDisplayListBuilder;
 class nsIFrame;
 class nsRenderingContext;
 class nsIntRegion;
 
 struct nsRect;
 struct nsIntRect;
 
 namespace mozilla {
+namespace gfx {
+class DrawTarget;
+}
 namespace layers {
 class LayerManager;
 }
 }
 
 struct nsPoint;
 struct nsSize;
 
 /**
  * Integration of SVG effects (clipPath clipping, masking and filters) into
  * regular display list based painting and hit-testing.
  */
 class nsSVGIntegrationUtils MOZ_FINAL
 {
+  typedef mozilla::gfx::DrawTarget DrawTarget;
+
 public:
   /**
    * Returns true if SVG effects are currently applied to this frame.
    */
   static bool
   UsingEffectsForFrame(const nsIFrame* aFrame);
 
   /**
@@ -161,13 +166,14 @@ public:
     FLAG_SYNC_DECODE_IMAGES = 0x01,
   };
 
   static already_AddRefed<gfxDrawable>
   DrawableFromPaintServer(nsIFrame*         aFrame,
                           nsIFrame*         aTarget,
                           const nsSize&     aPaintServerSize,
                           const gfxIntSize& aRenderSize,
+                          const DrawTarget* aDrawTarget,
                           const gfxMatrix&  aContextMatrix,
                           uint32_t          aFlags);
 };
 
 #endif /*NSSVGINTEGRATIONUTILS_H_*/
--- a/layout/svg/nsSVGPaintServerFrame.h
+++ b/layout/svg/nsSVGPaintServerFrame.h
@@ -9,27 +9,35 @@
 #include "mozilla/Attributes.h"
 #include "nsCOMPtr.h"
 #include "nsFrame.h"
 #include "nsIFrame.h"
 #include "nsQueryFrame.h"
 #include "nsSVGContainerFrame.h"
 #include "nsSVGUtils.h"
 
+namespace mozilla {
+namespace gfx {
+class DrawTarget;
+}
+}
+
 class gfxContext;
 class gfxPattern;
 class nsStyleContext;
 
 struct gfxRect;
 
 typedef nsSVGContainerFrame nsSVGPaintServerFrameBase;
 
 class nsSVGPaintServerFrame : public nsSVGPaintServerFrameBase
 {
 protected:
+  typedef mozilla::gfx::DrawTarget DrawTarget;
+
   explicit nsSVGPaintServerFrame(nsStyleContext* aContext)
     : nsSVGPaintServerFrameBase(aContext)
   {
     AddStateBits(NS_FRAME_IS_NONDISPLAY);
   }
 
 public:
   NS_DECL_FRAMEARENA_HELPERS
@@ -39,16 +47,17 @@ public:
    *
    * @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 already_AddRefed<gfxPattern>
     GetPaintServerPattern(nsIFrame *aSource,
+                          const DrawTarget* aDrawTarget,
                           const gfxMatrix& aContextMatrix,
                           nsStyleSVGPaint nsStyleSVG::*aFillOrStroke,
                           float aOpacity,
                           const gfxRect *aOverrideBounds = nullptr) = 0;
 
   // nsIFrame methods:
   virtual void BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                                 const nsRect&           aDirtyRect,
--- a/layout/svg/nsSVGPatternFrame.cpp
+++ b/layout/svg/nsSVGPatternFrame.cpp
@@ -226,17 +226,18 @@ GetTargetGeometry(gfxRect *aBBox,
   if (scale <= 0) {
     return NS_ERROR_FAILURE;
   }
   aBBox->Scale(scale);
   return NS_OK;
 }
 
 TemporaryRef<SourceSurface>
-nsSVGPatternFrame::PaintPattern(Matrix* patternMatrix,
+nsSVGPatternFrame::PaintPattern(const DrawTarget* aDrawTarget,
+                                Matrix* patternMatrix,
                                 const Matrix &aContextMatrix,
                                 nsIFrame *aSource,
                                 nsStyleSVGPaint nsStyleSVG::*aFillOrStroke,
                                 float aGraphicOpacity,
                                 const gfxRect *aOverrideBounds)
 {
   /*
    * General approach:
@@ -368,18 +369,17 @@ nsSVGPatternFrame::PaintPattern(Matrix* 
     patternFrame->mCTM->PreMultiply(tempTM);
 
     // and rescale pattern to compensate
     patternMatrix->PreScale(patternWidth / surfaceSize.width,
                             patternHeight / surfaceSize.height);
   }
 
   RefPtr<DrawTarget> dt =
-    gfxPlatform::GetPlatform()->
-      CreateOffscreenContentDrawTarget(surfaceSize,  SurfaceFormat::B8G8R8A8);
+    aDrawTarget->CreateSimilarDrawTarget(surfaceSize, SurfaceFormat::B8G8R8A8);
   if (!dt) {
     return nullptr;
   }
 
   nsRefPtr<nsRenderingContext> context(new nsRenderingContext());
   context->Init(aSource->PresContext()->DeviceContext(), dt);
   gfxContext* gfx = context->ThebesContext();
 
@@ -702,31 +702,32 @@ nsSVGPatternFrame::ConstructCTM(const ns
   return ThebesMatrix(tm) * tCTM;
 }
 
 //----------------------------------------------------------------------
 // nsSVGPaintServerFrame methods:
 
 already_AddRefed<gfxPattern>
 nsSVGPatternFrame::GetPaintServerPattern(nsIFrame *aSource,
+                                         const DrawTarget* aDrawTarget,
                                          const gfxMatrix& aContextMatrix,
                                          nsStyleSVGPaint nsStyleSVG::*aFillOrStroke,
                                          float aGraphicOpacity,
                                          const gfxRect *aOverrideBounds)
 {
   if (aGraphicOpacity == 0.0f) {
     nsRefPtr<gfxPattern> pattern = new gfxPattern(gfxRGBA(0, 0, 0, 0));
     return pattern.forget();
   }
 
   // Paint it!
   Matrix pMatrix;
   RefPtr<SourceSurface> surface =
-    PaintPattern(&pMatrix, ToMatrix(aContextMatrix), aSource, aFillOrStroke,
-                 aGraphicOpacity, aOverrideBounds);
+    PaintPattern(aDrawTarget, &pMatrix, ToMatrix(aContextMatrix), aSource,
+                 aFillOrStroke, aGraphicOpacity, aOverrideBounds);
 
   if (!surface) {
     return nullptr;
   }
 
   nsRefPtr<gfxPattern> pattern = new gfxPattern(surface, pMatrix);
 
   if (!pattern || pattern->CairoStatus())
--- a/layout/svg/nsSVGPatternFrame.h
+++ b/layout/svg/nsSVGPatternFrame.h
@@ -41,16 +41,17 @@ public:
   friend nsIFrame* NS_NewSVGPatternFrame(nsIPresShell* aPresShell,
                                          nsStyleContext* aContext);
 
   explicit nsSVGPatternFrame(nsStyleContext* aContext);
 
   // nsSVGPaintServerFrame methods:
   virtual already_AddRefed<gfxPattern>
     GetPaintServerPattern(nsIFrame *aSource,
+                          const DrawTarget* aDrawTarget,
                           const gfxMatrix& aContextMatrix,
                           nsStyleSVGPaint nsStyleSVG::*aFillOrStroke,
                           float aOpacity,
                           const gfxRect *aOverrideBounds) MOZ_OVERRIDE;
 
 public:
   typedef mozilla::SVGAnimatedPreserveAspectRatio SVGAnimatedPreserveAspectRatio;
 
@@ -107,17 +108,18 @@ protected:
   }
   const nsSVGLength2 *GetLengthValue(uint32_t aIndex, nsIContent *aDefault);
   const nsSVGLength2 *GetLengthValue(uint32_t aIndex)
   {
     return GetLengthValue(aIndex, mContent);
   }
 
   mozilla::TemporaryRef<SourceSurface>
-  PaintPattern(Matrix *patternMatrix,
+  PaintPattern(const DrawTarget* aDrawTarget,
+               Matrix *patternMatrix,
                const Matrix &aContextMatrix,
                nsIFrame *aSource,
                nsStyleSVGPaint nsStyleSVG::*aFillOrStroke,
                float aGraphicOpacity,
                const gfxRect *aOverrideBounds);
   nsIFrame*  GetPatternFirstChild();
   gfxRect    GetPatternRect(uint16_t aPatternUnits,
                             const gfxRect &bbox,
--- a/layout/svg/nsSVGUtils.cpp
+++ b/layout/svg/nsSVGUtils.cpp
@@ -1252,37 +1252,41 @@ nsSVGUtils::MakeFillPatternFor(nsIFrame 
   if (style->mFill.mType == eStyleSVGPaintType_None) {
     return nullptr;
   }
 
   float opacity = MaybeOptimizeOpacity(aFrame,
                                        GetOpacity(style->mFillOpacitySource,
                                                   style->mFillOpacity,
                                                   aContextPaint));
+  const DrawTarget* dt = aContext->GetDrawTarget();
+
   nsRefPtr<gfxPattern> pattern;
 
   nsSVGPaintServerFrame *ps =
     nsSVGEffects::GetPaintServer(aFrame, &style->mFill,
                                  nsSVGEffects::FillProperty());
   if (ps) {
-    pattern = ps->GetPaintServerPattern(aFrame, aContext->CurrentMatrix(),
+    pattern = ps->GetPaintServerPattern(aFrame, dt, aContext->CurrentMatrix(),
                                         &nsStyleSVG::mFill, opacity);
     if (pattern) {
-      pattern->CacheColorStops(aContext->GetDrawTarget());
+      pattern->CacheColorStops(dt);
       return pattern.forget();
     }
   }
 
   if (aContextPaint) {
     switch (style->mFill.mType) {
     case eStyleSVGPaintType_ContextFill:
-      pattern = aContextPaint->GetFillPattern(opacity, aContext->CurrentMatrix());
+      pattern = aContextPaint->GetFillPattern(dt, opacity,
+                                              aContext->CurrentMatrix());
       break;
     case eStyleSVGPaintType_ContextStroke:
-      pattern = aContextPaint->GetStrokePattern(opacity, aContext->CurrentMatrix());
+      pattern = aContextPaint->GetStrokePattern(dt, opacity,
+                                                aContext->CurrentMatrix());
       break;
     default:
       ;
     }
     if (pattern) {
       return pattern.forget();
     }
   }
@@ -1308,37 +1312,42 @@ nsSVGUtils::MakeStrokePatternFor(nsIFram
   if (style->mStroke.mType == eStyleSVGPaintType_None) {
     return nullptr;
   }
 
   float opacity = MaybeOptimizeOpacity(aFrame,
                                        GetOpacity(style->mStrokeOpacitySource,
                                                   style->mStrokeOpacity,
                                                   aContextPaint));
+
+  const DrawTarget* dt = aContext->GetDrawTarget();
+
   nsRefPtr<gfxPattern> pattern;
 
   nsSVGPaintServerFrame *ps =
     nsSVGEffects::GetPaintServer(aFrame, &style->mStroke,
                                  nsSVGEffects::StrokeProperty());
   if (ps) {
-    pattern = ps->GetPaintServerPattern(aFrame, aContext->CurrentMatrix(),
+    pattern = ps->GetPaintServerPattern(aFrame, dt, aContext->CurrentMatrix(),
                                         &nsStyleSVG::mStroke, opacity);
     if (pattern) {
-      pattern->CacheColorStops(aContext->GetDrawTarget());
+      pattern->CacheColorStops(dt);
       return pattern.forget();
     }
   }
 
   if (aContextPaint) {
     switch (style->mStroke.mType) {
     case eStyleSVGPaintType_ContextFill:
-      pattern = aContextPaint->GetFillPattern(opacity, aContext->CurrentMatrix());
+      pattern = aContextPaint->GetFillPattern(dt, opacity,
+                                              aContext->CurrentMatrix());
       break;
     case eStyleSVGPaintType_ContextStroke:
-      pattern = aContextPaint->GetStrokePattern(opacity, aContext->CurrentMatrix());
+      pattern = aContextPaint->GetStrokePattern(dt, opacity,
+                                                aContext->CurrentMatrix());
       break;
     default:
       ;
     }
     if (pattern) {
       return pattern.forget();
     }
   }