Bug 1074012, part 3 - Make nsSVGUtils::MakeFillPatternFor/MakeStrokePatternFor return using a Moz2D GeneralPattern out-param rather than a Thebes gfxPattern. r=Bas
authorJonathan Watt <jwatt@jwatt.org>
Mon, 29 Sep 2014 14:26:15 +0100
changeset 207698 6fa1aac2d4138e0e514d252be15778422a77af2d
parent 207697 d98720aace71fa7c15c0966e2fc8bf07a9f1fef4
child 207699 0627cc72985f03237631c047ff13cef5f88bdd19
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
bugs1074012
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 1074012, part 3 - Make nsSVGUtils::MakeFillPatternFor/MakeStrokePatternFor return using a Moz2D GeneralPattern out-param rather than a Thebes gfxPattern. r=Bas
layout/svg/SVGTextFrame.cpp
layout/svg/nsFilterInstance.cpp
layout/svg/nsSVGPathGeometryFrame.cpp
layout/svg/nsSVGUtils.cpp
layout/svg/nsSVGUtils.h
--- a/layout/svg/SVGTextFrame.cpp
+++ b/layout/svg/SVGTextFrame.cpp
@@ -9,16 +9,17 @@
 // Keep others in (case-insensitive) order:
 #include "DOMSVGPoint.h"
 #include "gfx2DGlue.h"
 #include "gfxFont.h"
 #include "gfxSkipChars.h"
 #include "gfxTypes.h"
 #include "LookAndFeel.h"
 #include "mozilla/gfx/2D.h"
+#include "mozilla/gfx/PatternHelpers.h"
 #include "nsAlgorithm.h"
 #include "nsBlockFrame.h"
 #include "nsCaret.h"
 #include "nsContentUtils.h"
 #include "nsGkAtoms.h"
 #include "nsIDOMSVGLength.h"
 #include "nsISelection.h"
 #include "nsQuickSort.h"
@@ -2734,17 +2735,17 @@ private:
    * or text decorations have been emitted to the gfxContext.
    */
   void HandleTextGeometry();
 
   /**
    * Sets the gfxContext paint to the appropriate color or pattern
    * for filling text geometry.
    */
-  already_AddRefed<gfxPattern> MakeFillPattern();
+  void MakeFillPattern(GeneralPattern* aOutPattern);
 
   /**
    * Fills and strokes a piece of text geometry, using group opacity
    * if the selection style requires it.
    */
   void FillAndStrokeGeometry();
 
   /**
@@ -2820,21 +2821,22 @@ SVGTextDrawPathCallbacks::NotifyBeforeSe
 void
 SVGTextDrawPathCallbacks::NotifySelectionBackgroundPathEmitted()
 {
   if (mRenderMode != SVGAutoRenderState::NORMAL) {
     // Don't paint selection backgrounds when in a clip path.
     return;
   }
 
-  nsRefPtr<gfxPattern> fillPattern = MakeFillPattern();
-  if (fillPattern) {
-    gfx->SetPattern(fillPattern);
+  GeneralPattern fillPattern;
+  MakeFillPattern(&fillPattern);
+  if (fillPattern.GetPattern()) {
     gfx->SetFillRule(nsSVGUtils::ToFillRule(mFrame->StyleSVG()->mFillRule));
-    gfx->FillWithOpacity(mColor == NS_40PERCENT_FOREGROUND_COLOR ? 0.4 : 1.0);
+    gfx->FillWithOpacity(fillPattern,
+                         mColor == NS_40PERCENT_FOREGROUND_COLOR ? 0.4 : 1.0);
   }
   gfx->Restore();
 }
 
 void
 SVGTextDrawPathCallbacks::NotifyBeforeDecorationLine(nscolor aColor)
 {
   mColor = aColor;
@@ -2901,30 +2903,30 @@ SVGTextDrawPathCallbacks::HandleTextGeom
     // Normal painting.
     gfxContextMatrixAutoSaveRestore saveMatrix(gfx);
     gfx->SetMatrix(mCanvasTM);
 
     FillAndStrokeGeometry();
   }
 }
 
-already_AddRefed<gfxPattern>
-SVGTextDrawPathCallbacks::MakeFillPattern()
+void
+SVGTextDrawPathCallbacks::MakeFillPattern(GeneralPattern* aOutPattern)
 {
   if (mColor == NS_SAME_AS_FOREGROUND_COLOR ||
       mColor == NS_40PERCENT_FOREGROUND_COLOR) {
-    return nsSVGUtils::MakeFillPatternFor(mFrame, gfx);
+    nsSVGUtils::MakeFillPatternFor(mFrame, gfx, aOutPattern);
+    return;
   }
 
   if (mColor == NS_TRANSPARENT) {
-    return nullptr;
-  }
-
-  nsRefPtr<gfxPattern> pattern = new gfxPattern(gfxRGBA(mColor));
-  return pattern.forget();
+    return;
+  }
+
+  aOutPattern->InitColorPattern(ToColor(gfxRGBA(mColor)));
 }
 
 void
 SVGTextDrawPathCallbacks::FillAndStrokeGeometry()
 {
   bool pushedGroup = false;
   if (mColor == NS_40PERCENT_FOREGROUND_COLOR) {
     pushedGroup = true;
@@ -2955,37 +2957,36 @@ SVGTextDrawPathCallbacks::FillAndStrokeG
     gfx->PopGroupToSource();
     gfx->Paint(0.4);
   }
 }
 
 void
 SVGTextDrawPathCallbacks::FillGeometry()
 {
-  nsRefPtr<gfxPattern> fillPattern = MakeFillPattern();
-  if (fillPattern) {
-    gfx->SetPattern(fillPattern);
+  GeneralPattern fillPattern;
+  MakeFillPattern(&fillPattern);
+  if (fillPattern.GetPattern()) {
     gfx->SetFillRule(nsSVGUtils::ToFillRule(mFrame->StyleSVG()->mFillRule));
-    gfx->Fill();
+    gfx->Fill(fillPattern);
   }
 }
 
 void
 SVGTextDrawPathCallbacks::StrokeGeometry()
 {
   // We don't paint the stroke when we are filling with a selection color.
   if (mColor == NS_SAME_AS_FOREGROUND_COLOR ||
       mColor == NS_40PERCENT_FOREGROUND_COLOR) {
     if (nsSVGUtils::HasStroke(mFrame, /*aContextPaint*/ nullptr)) {
-      nsRefPtr<gfxPattern> strokePattern =
-        nsSVGUtils::MakeStrokePatternFor(mFrame, gfx, /*aContextPaint*/ nullptr);
-      if (strokePattern) {
+      GeneralPattern strokePattern;
+      nsSVGUtils::MakeStrokePatternFor(mFrame, gfx, &strokePattern, /*aContextPaint*/ nullptr);
+      if (strokePattern.GetPattern()) {
         nsSVGUtils::SetupCairoStrokeGeometry(mFrame, gfx, /*aContextPaint*/ nullptr);
-        gfx->SetPattern(strokePattern);
-        gfx->Stroke();
+        gfx->Stroke(strokePattern);
       }
     }
   }
 }
 
 //----------------------------------------------------------------------
 // SVGTextContextPaint methods:
 
--- a/layout/svg/nsFilterInstance.cpp
+++ b/layout/svg/nsFilterInstance.cpp
@@ -9,16 +9,17 @@
 // MFBT headers next:
 #include "mozilla/UniquePtr.h"
 
 // Keep others in (case-insensitive) order:
 #include "gfx2DGlue.h"
 #include "gfxPlatform.h"
 #include "gfxUtils.h"
 #include "mozilla/gfx/Helpers.h"
+#include "mozilla/gfx/PatternHelpers.h"
 #include "nsISVGChildFrame.h"
 #include "nsRenderingContext.h"
 #include "nsCSSFilterInstance.h"
 #include "nsSVGFilterInstance.h"
 #include "nsSVGFilterPaintCallback.h"
 #include "nsSVGUtils.h"
 #include "SVGContentUtils.h"
 #include "FilterSupport.h"
@@ -363,25 +364,25 @@ nsFilterInstance::BuildSourcePaint(Sourc
   }
 
   if (!mPaintTransform.IsSingular()) {
     nsRefPtr<gfxContext> gfx = new gfxContext(offscreenDT);
     gfx->Save();
     gfx->Multiply(mPaintTransform *
                   deviceToFilterSpace *
                   gfxMatrix::Translation(-neededRect.TopLeft()));
-    nsRefPtr<gfxPattern> pattern;
+    GeneralPattern pattern;
     if (aSource == &mFillPaint) {
-      pattern = nsSVGUtils::MakeFillPatternFor(mTargetFrame, gfx);
+      nsSVGUtils::MakeFillPatternFor(mTargetFrame, gfx, &pattern);
     } else if (aSource == &mStrokePaint) {
-      pattern = nsSVGUtils::MakeStrokePatternFor(mTargetFrame, gfx);
+      nsSVGUtils::MakeStrokePatternFor(mTargetFrame, gfx, &pattern);
     }
-    if (pattern) {
+    if (pattern.GetPattern()) {
       offscreenDT->FillRect(ToRect(FilterSpaceToUserSpace(neededRect)),
-                            *pattern->GetPattern(offscreenDT));
+                            pattern);
     }
     gfx->Restore();
   }
 
   aSource->mSourceSurface = offscreenDT->Snapshot();
   aSource->mSurfaceRect = ToIntRect(neededRect);
 
   return NS_OK;
--- a/layout/svg/nsSVGPathGeometryFrame.cpp
+++ b/layout/svg/nsSVGPathGeometryFrame.cpp
@@ -667,35 +667,33 @@ nsSVGPathGeometryFrame::Render(nsRenderi
 
   gfxContextAutoSaveRestore autoSaveRestore(gfx);
   gfx->SetMatrix(newMatrix);
 
   gfxTextContextPaint *contextPaint =
     (gfxTextContextPaint*)aContext->GetDrawTarget()->GetUserData(&gfxTextContextPaint::sUserDataKey);
 
   if ((aRenderComponents & eRenderFill)) {
-    nsRefPtr<gfxPattern> fillPattern =
-      nsSVGUtils::MakeFillPatternFor(this, gfx, contextPaint);
-    if (fillPattern) {
+    GeneralPattern fillPattern;
+    nsSVGUtils::MakeFillPatternFor(this, gfx, &fillPattern, contextPaint);
+    if (fillPattern.GetPattern()) {
       gfx->SetPath(path);
-      gfx->SetPattern(fillPattern);
       gfx->SetFillRule(fillRule);
-      gfx->Fill();
+      gfx->Fill(fillPattern);
     }
   }
 
   if ((aRenderComponents & eRenderStroke) &&
       nsSVGUtils::HasStroke(this, contextPaint)) {
-    nsRefPtr<gfxPattern> strokePattern =
-      nsSVGUtils::MakeStrokePatternFor(this, gfx, contextPaint);
-    if (strokePattern) {
+    GeneralPattern strokePattern;
+    nsSVGUtils::MakeStrokePatternFor(this, gfx, &strokePattern, contextPaint);
+    if (strokePattern.GetPattern()) {
       gfx->SetPath(path);
       nsSVGUtils::SetupCairoStrokeGeometry(this, gfx, contextPaint);
-      gfx->SetPattern(strokePattern);
-      gfx->Stroke();
+      gfx->Stroke(strokePattern);
     }
   }
 
   gfx->NewPath();
 }
 
 void
 nsSVGPathGeometryFrame::GeneratePath(gfxContext* aContext,
--- a/layout/svg/nsSVGUtils.cpp
+++ b/layout/svg/nsSVGUtils.cpp
@@ -11,16 +11,17 @@
 // Keep others in (case-insensitive) order:
 #include "gfx2DGlue.h"
 #include "gfxContext.h"
 #include "gfxMatrix.h"
 #include "gfxPlatform.h"
 #include "gfxRect.h"
 #include "gfxUtils.h"
 #include "mozilla/gfx/2D.h"
+#include "mozilla/gfx/PatternHelpers.h"
 #include "mozilla/Preferences.h"
 #include "nsCSSFrameConstructor.h"
 #include "nsDisplayList.h"
 #include "nsFilterInstance.h"
 #include "nsFrameList.h"
 #include "nsGkAtoms.h"
 #include "nsIContent.h"
 #include "nsIDocument.h"
@@ -1238,135 +1239,139 @@ MaybeOptimizeOpacity(nsIFrame *aFrame, f
 {
   float opacity = aFrame->StyleDisplay()->mOpacity;
   if (opacity < 1 && nsSVGUtils::CanOptimizeOpacity(aFrame)) {
     return aFillOrStrokeOpacity * opacity;
   }
   return aFillOrStrokeOpacity;
 }
 
-/* static */ already_AddRefed<gfxPattern>
-nsSVGUtils::MakeFillPatternFor(nsIFrame *aFrame,
+/* static */ void
+nsSVGUtils::MakeFillPatternFor(nsIFrame* aFrame,
                                gfxContext* aContext,
-                               gfxTextContextPaint *aContextPaint)
+                               GeneralPattern* aOutPattern,
+                               gfxTextContextPaint* aContextPaint)
 {
   const nsStyleSVG* style = aFrame->StyleSVG();
   if (style->mFill.mType == eStyleSVGPaintType_None) {
-    return nullptr;
+    return;
   }
 
   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, dt, aContext->CurrentMatrix(),
-                                        &nsStyleSVG::mFill, opacity);
+    nsRefPtr<gfxPattern> pattern =
+      ps->GetPaintServerPattern(aFrame, dt, aContext->CurrentMatrix(),
+                                &nsStyleSVG::mFill, opacity);
     if (pattern) {
       pattern->CacheColorStops(dt);
-      return pattern.forget();
+      aOutPattern->Init(*pattern->GetPattern(dt));
+      return;
     }
   }
 
   if (aContextPaint) {
+    nsRefPtr<gfxPattern> pattern;
     switch (style->mFill.mType) {
     case eStyleSVGPaintType_ContextFill:
       pattern = aContextPaint->GetFillPattern(dt, opacity,
                                               aContext->CurrentMatrix());
       break;
     case eStyleSVGPaintType_ContextStroke:
       pattern = aContextPaint->GetStrokePattern(dt, opacity,
                                                 aContext->CurrentMatrix());
       break;
     default:
       ;
     }
     if (pattern) {
-      return pattern.forget();
+      aOutPattern->Init(*pattern->GetPattern(dt));
+      return;
     }
   }
 
   // On failure, use the fallback colour in case we have an
   // objectBoundingBox where the width or height of the object is zero.
   // See http://www.w3.org/TR/SVG11/coords.html#ObjectBoundingBox
   nscolor color = GetFallbackOrPaintColor(aFrame->StyleContext(),
                                           &nsStyleSVG::mFill);
-  pattern = new gfxPattern(gfxRGBA(NS_GET_R(color)/255.0,
-                                   NS_GET_G(color)/255.0,
-                                   NS_GET_B(color)/255.0,
-                                   NS_GET_A(color)/255.0 * opacity));
-  return pattern.forget();
+  aOutPattern->InitColorPattern(Color(NS_GET_R(color)/255.0,
+                                      NS_GET_G(color)/255.0,
+                                      NS_GET_B(color)/255.0,
+                                      NS_GET_A(color)/255.0 * opacity));
 }
 
-/* static */ already_AddRefed<gfxPattern>
-nsSVGUtils::MakeStrokePatternFor(nsIFrame *aFrame,
+/* static */ void
+nsSVGUtils::MakeStrokePatternFor(nsIFrame* aFrame,
                                  gfxContext* aContext,
-                                 gfxTextContextPaint *aContextPaint)
+                                 GeneralPattern* aOutPattern,
+                                 gfxTextContextPaint* aContextPaint)
 {
   const nsStyleSVG* style = aFrame->StyleSVG();
   if (style->mStroke.mType == eStyleSVGPaintType_None) {
-    return nullptr;
+    return;
   }
 
   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, dt, aContext->CurrentMatrix(),
-                                        &nsStyleSVG::mStroke, opacity);
+    nsRefPtr<gfxPattern> pattern =
+      ps->GetPaintServerPattern(aFrame, dt, aContext->CurrentMatrix(),
+                                &nsStyleSVG::mStroke, opacity);
     if (pattern) {
       pattern->CacheColorStops(dt);
-      return pattern.forget();
+      aOutPattern->Init(*pattern->GetPattern(dt));
+      return;
     }
   }
 
   if (aContextPaint) {
+    nsRefPtr<gfxPattern> pattern;
     switch (style->mStroke.mType) {
     case eStyleSVGPaintType_ContextFill:
       pattern = aContextPaint->GetFillPattern(dt, opacity,
                                               aContext->CurrentMatrix());
       break;
     case eStyleSVGPaintType_ContextStroke:
       pattern = aContextPaint->GetStrokePattern(dt, opacity,
                                                 aContext->CurrentMatrix());
       break;
     default:
       ;
     }
     if (pattern) {
-      return pattern.forget();
+      aOutPattern->Init(*pattern->GetPattern(dt));
+      return;
     }
   }
 
   // On failure, use the fallback colour in case we have an
   // objectBoundingBox where the width or height of the object is zero.
   // See http://www.w3.org/TR/SVG11/coords.html#ObjectBoundingBox
   nscolor color = GetFallbackOrPaintColor(aFrame->StyleContext(),
                                           &nsStyleSVG::mStroke);
-  pattern = new gfxPattern(gfxRGBA(NS_GET_R(color)/255.0,
-                                   NS_GET_G(color)/255.0,
-                                   NS_GET_B(color)/255.0,
-                                   NS_GET_A(color)/255.0 * opacity));
-  return pattern.forget();
+  aOutPattern->InitColorPattern(Color(NS_GET_R(color)/255.0,
+                                      NS_GET_G(color)/255.0,
+                                      NS_GET_B(color)/255.0,
+                                      NS_GET_A(color)/255.0 * opacity));
 }
 
 /* static */ float
 nsSVGUtils::GetOpacity(nsStyleSVGOpacitySource aOpacityType,
                        const float& aOpacity,
                        gfxTextContextPaint *aOuterContextPaint)
 {
   float opacity = 1.0f;
--- a/layout/svg/nsSVGUtils.h
+++ b/layout/svg/nsSVGUtils.h
@@ -56,16 +56,17 @@ struct nsPoint;
 namespace mozilla {
 class SVGAnimatedPreserveAspectRatio;
 class SVGPreserveAspectRatio;
 namespace dom {
 class Element;
 class UserSpaceMetrics;
 } // namespace dom
 namespace gfx {
+class GeneralPattern;
 class SourceSurface;
 }
 } // namespace mozilla
 
 // maximum dimension of an offscreen surface - choose so that
 // the surface size doesn't overflow a 32-bit signed int using
 // 4 bytes per pixel; in line with gfxASurface::CheckSurfaceSize
 // In fact Macs can't even manage that
@@ -195,16 +196,17 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsISVGFilt
  * If a method is used by content and depends only on other content methods
  * it should go in SVGContentUtils instead.
  */
 class nsSVGUtils
 {
 public:
   typedef mozilla::dom::Element Element;
   typedef mozilla::gfx::FillRule FillRule;
+  typedef mozilla::gfx::GeneralPattern GeneralPattern;
 
   static void Init();
 
   /**
    * Gets the nearest nsSVGInnerSVGFrame or nsSVGOuterSVGFrame frame. aFrame
    * must be an SVG frame. If aFrame is of type nsGkAtoms::svgOuterSVGFrame,
    * returns nullptr.
    */
@@ -496,24 +498,26 @@ public:
   {
     return NS_lround(std::max(double(INT32_MIN),
                             std::min(double(INT32_MAX), aVal)));
   }
 
   static nscolor GetFallbackOrPaintColor(nsStyleContext *aStyleContext,
                                          nsStyleSVGPaint nsStyleSVG::*aFillOrStroke);
 
-  static already_AddRefed<gfxPattern>
+  static void
   MakeFillPatternFor(nsIFrame *aFrame,
                      gfxContext* aContext,
+                     GeneralPattern* aOutPattern,
                      gfxTextContextPaint *aContextPaint = nullptr);
 
-  static already_AddRefed<gfxPattern>
+  static void
   MakeStrokePatternFor(nsIFrame* aFrame,
                        gfxContext* aContext,
+                       GeneralPattern* aOutPattern,
                        gfxTextContextPaint *aContextPaint = nullptr);
 
   static float GetOpacity(nsStyleSVGOpacitySource aOpacityType,
                           const float& aOpacity,
                           gfxTextContextPaint *aOuterContextPaint);
 
   /*
    * @return false if there is no stroke