Back out bug 746883, bug 764125, bug 761895, bug 746883, bug 748116
authorNicholas Cameron <ncameron@mozilla.com>
Thu, 26 Jul 2012 18:48:24 +1200
changeset 100554 ff7d09c5c94590102341c9e7932a1a866c7ce837
parent 100553 eb4f2872a6ca9294d642e798b202699eef9443b2
child 100555 20db7c6d82cc5bcb0e916bfe72d1ab04d3c3be2d
child 100561 a6ec0c6749bb6a8d4aff8980c1be2aa8243b731b
push id23182
push useremorley@mozilla.com
push dateThu, 26 Jul 2012 12:04:56 +0000
treeherdermozilla-central@20db7c6d82cc [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs746883, 764125, 761895, 748116
milestone17.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
Back out bug 746883, bug 764125, bug 761895, bug 746883, bug 748116
content/canvas/src/nsCanvasRenderingContext2DAzure.cpp
content/canvas/src/nsCanvasRenderingContext2DAzure.h
content/canvas/test/Makefile.in
content/canvas/test/test_bug764125.html
content/canvas/test/test_canvas.html
gfx/2d/2D.h
gfx/2d/DrawTargetCairo.cpp
gfx/2d/DrawTargetCairo.h
gfx/2d/Factory.cpp
gfx/2d/HelpersSkia.h
gfx/2d/PathCairo.cpp
gfx/2d/PathCairo.h
gfx/2d/SourceSurfaceCairo.cpp
gfx/2d/Types.h
gfx/layers/d3d10/LayerManagerD3D10.cpp
gfx/layers/d3d9/CanvasLayerD3D9.cpp
gfx/layers/opengl/CanvasLayerOGL.cpp
gfx/thebes/gfxAndroidPlatform.cpp
gfx/thebes/gfxAndroidPlatform.h
gfx/thebes/gfxFont.cpp
gfx/thebes/gfxFont.h
gfx/thebes/gfxPlatform.cpp
gfx/thebes/gfxPlatform.h
gfx/thebes/gfxPlatformGtk.cpp
gfx/thebes/gfxPlatformGtk.h
gfx/thebes/gfxPlatformMac.cpp
gfx/thebes/gfxPlatformMac.h
gfx/thebes/gfxQtPlatform.cpp
gfx/thebes/gfxQtPlatform.h
gfx/thebes/gfxWindowsPlatform.cpp
gfx/thebes/gfxWindowsPlatform.h
modules/libpref/src/init/all.js
widget/android/GfxInfo.cpp
widget/android/GfxInfo.h
widget/cocoa/GfxInfo.h
widget/cocoa/GfxInfo.mm
widget/nsIGfxInfo.idl
widget/windows/GfxInfo.cpp
widget/windows/GfxInfo.h
widget/windows/TaskbarPreview.cpp
widget/xpwidgets/GfxInfoX11.cpp
widget/xpwidgets/GfxInfoX11.h
--- a/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp
+++ b/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp
@@ -544,32 +544,56 @@ NS_INTERFACE_MAP_END
 // Initialize our static variables.
 PRUint32 nsCanvasRenderingContext2DAzure::sNumLivingContexts = 0;
 PRUint8 (*nsCanvasRenderingContext2DAzure::sUnpremultiplyTable)[256] = nsnull;
 PRUint8 (*nsCanvasRenderingContext2DAzure::sPremultiplyTable)[256] = nsnull;
 
 namespace mozilla {
 namespace dom {
 
+static bool
+AzureCanvasEnabledOnPlatform()
+{
+#ifdef XP_WIN
+  if (gfxWindowsPlatform::GetPlatform()->GetRenderMode() !=
+      gfxWindowsPlatform::RENDER_DIRECT2D ||
+      !gfxWindowsPlatform::GetPlatform()->DWriteEnabled()) {
+    static bool checkedPref = false;
+    static bool preferSkia;
+    if (!checkedPref) {
+      preferSkia = Preferences::GetBool("gfx.canvas.azure.prefer-skia", false);
+      checkedPref = true;
+    }
+    return preferSkia;
+  }
+#elif !defined(XP_MACOSX) && !defined(ANDROID) && !defined(LINUX)
+  return false;
+#endif
+  return true;
+}
+
 bool
 AzureCanvasEnabled()
 {
-  BackendType dontCare;
-  return gfxPlatform::GetPlatform()->SupportsAzureCanvas(dontCare);
+  static bool checkedPref = false;
+  static bool azureEnabled;
+  if (!checkedPref) {
+    azureEnabled = Preferences::GetBool("gfx.canvas.azure.enabled", false);
+    checkedPref = true;
+  }
+  return azureEnabled && AzureCanvasEnabledOnPlatform();
 }
 
 }
 }
 
 nsresult
 NS_NewCanvasRenderingContext2DAzure(nsIDOMCanvasRenderingContext2D** aResult)
 {
-  // XXX[nrc] remove this check when Thebes canvas is removed
-  // (because we will always support Azure)
-  if (!AzureCanvasEnabled()) {
+  if (!AzureCanvasEnabledOnPlatform()) {
     return NS_ERROR_NOT_AVAILABLE;
   }
 
   nsRefPtr<nsIDOMCanvasRenderingContext2D> ctx = new nsCanvasRenderingContext2DAzure();
   if (!ctx)
     return NS_ERROR_OUT_OF_MEMORY;
 
   *aResult = ctx.forget().get();
@@ -885,22 +909,40 @@ nsCanvasRenderingContext2DAzure::SetDime
       JS_updateMallocCounter(context, width * height * 4);
     }
   }
 
   return InitializeWithTarget(target, width, height);
 }
 
 nsresult
-nsCanvasRenderingContext2DAzure::Initialize(PRInt32 width, PRInt32 height)
+nsCanvasRenderingContext2DAzure::InitializeWithTarget(DrawTarget *target, PRInt32 width, PRInt32 height)
 {
+  Reset();
+
+  NS_ASSERTION(mCanvasElement, "Must have a canvas element!");
+  mDocShell = nsnull;
+
   mWidth = width;
   mHeight = height;
 
-  if (!mValid) {
+  // This first time this is called on this object is via
+  // nsHTMLCanvasElement::GetContext. If target was non-null then mTarget is
+  // non-null, otherwise we'll return an error here and GetContext won't
+  // return this context object and we'll never enter this code again.
+  // All other times this method is called, if target is null then
+  // mTarget won't be changed, i.e. it will remain non-null, or else it
+  // will be set to non-null.
+  // In all cases, any usable canvas context will have non-null mTarget.
+
+  if (target) {
+    mValid = true;
+    mTarget = target;
+  } else {
+    mValid = false;
     // Create a dummy target in the hopes that it will help us deal with users
     // calling into us after having changed the size where the size resulted
     // in an inability to create a correct DrawTarget.
     mTarget = gfxPlatform::GetPlatform()->CreateOffscreenDrawTarget(IntSize(1, 1), FORMAT_B8G8R8A8);
   }
 
   mResetLayer = true;
 
@@ -922,55 +964,16 @@ nsCanvasRenderingContext2DAzure::Initial
     // always force a redraw, because if the surface dimensions were reset
     // then the surface became cleared, and we need to redraw everything.
     Redraw();
   }
 
   return mValid ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
 }
 
-nsresult
-nsCanvasRenderingContext2DAzure::InitializeWithTarget(DrawTarget *target, PRInt32 width, PRInt32 height)
-{
-  Reset();
-
-  NS_ASSERTION(mCanvasElement, "Must have a canvas element!");
-  mDocShell = nsnull;
-
-  // This first time this is called on this object is via
-  // nsHTMLCanvasElement::GetContext. If target was non-null then mTarget is
-  // non-null, otherwise we'll return an error here and GetContext won't
-  // return this context object and we'll never enter this code again.
-  // All other times this method is called, if target is null then
-  // mTarget won't be changed, i.e. it will remain non-null, or else it
-  // will be set to non-null.
-  // In all cases, any usable canvas context will have non-null mTarget.
-
-  if (target) {
-    mValid = true;
-    mTarget = target;
-  } else {
-    mValid = false;
-  }
-
-  return Initialize(width, height);
-}
-
-NS_IMETHODIMP
-nsCanvasRenderingContext2DAzure::InitializeWithSurface(nsIDocShell *shell, gfxASurface *surface, PRInt32 width, PRInt32 height)
-{
-  mDocShell = shell;
-  mThebesSurface = surface;
-
-  mTarget = gfxPlatform::GetPlatform()->CreateDrawTargetForSurface(surface, IntSize(width, height));
-  mValid = mTarget != nsnull;
-
-  return Initialize(width, height);
-}
-
 NS_IMETHODIMP
 nsCanvasRenderingContext2DAzure::SetIsOpaque(bool isOpaque)
 {
   if (isOpaque == mOpaque)
     return NS_OK;
 
   mOpaque = isOpaque;
 
@@ -2485,73 +2488,67 @@ nsCanvasRenderingContext2DAzure::EnsureW
       mPath = nsnull;
       mPathBuilder = nsnull;
       mPathTransformWillUpdate = false;
     }
     return;
   }
 
   if (!mPath) {
-    NS_ASSERTION(!mPathTransformWillUpdate, "mPathTransformWillUpdate should be false, if all paths are null");
     mPathBuilder = mTarget->CreatePathBuilder(fillRule);
   } else if (!mPathTransformWillUpdate) {
     mPathBuilder = mPath->CopyToBuilder(fillRule);
   } else {
     mDSPathBuilder =
       mPath->TransformedCopyToBuilder(mPathToDS, fillRule);
     mPathTransformWillUpdate = false;
   }
 }
 
 void
-nsCanvasRenderingContext2DAzure::EnsureUserSpacePath(bool aCommitTransform /* = true */)
+nsCanvasRenderingContext2DAzure::EnsureUserSpacePath()
 {
   FillRule fillRule = CurrentState().fillRule;
 
   if (!mPath && !mPathBuilder && !mDSPathBuilder) {
     mPathBuilder = mTarget->CreatePathBuilder(fillRule);
   }
 
   if (mPathBuilder) {
     mPath = mPathBuilder->Finish();
     mPathBuilder = nsnull;
   }
 
-  if (aCommitTransform &&
-      mPath &&
-      mPathTransformWillUpdate) {
+  if (mPath && mPathTransformWillUpdate) {
     mDSPathBuilder =
       mPath->TransformedCopyToBuilder(mPathToDS, fillRule);
     mPath = nsnull;
     mPathTransformWillUpdate = false;
   }
 
   if (mDSPathBuilder) {
     RefPtr<Path> dsPath;
     dsPath = mDSPathBuilder->Finish();
     mDSPathBuilder = nsnull;
 
     Matrix inverse = mTarget->GetTransform();
     if (!inverse.Invert()) {
-      NS_WARNING("Could not invert transform");
       return;
     }
 
     mPathBuilder =
       dsPath->TransformedCopyToBuilder(inverse, fillRule);
     mPath = mPathBuilder->Finish();
     mPathBuilder = nsnull;
   }
 
   if (mPath && mPath->GetFillRule() != fillRule) {
     mPathBuilder = mPath->CopyToBuilder(fillRule);
     mPath = mPathBuilder->Finish();
   }
-
-  NS_ASSERTION(mPath, "mPath should exist");
 }
 
 void
 nsCanvasRenderingContext2DAzure::TransformWillUpdate()
 {
   // Store the matrix that would transform the current path to device
   // space.
   if (mPath || mPathBuilder) {
@@ -3042,17 +3039,17 @@ struct NS_STACK_CLASS nsCanvasBidiProces
         endRun = runs[c + 1].mCharacterOffset;
       } else {
         endRun = mTextRun->GetLength();
       }
 
       const gfxTextRun::CompressedGlyph *glyphs = mTextRun->GetCharacterGlyphs();
 
       RefPtr<ScaledFont> scaledFont =
-        gfxPlatform::GetPlatform()->GetScaledFontForFont(mCtx->mTarget, font);
+        gfxPlatform::GetPlatform()->GetScaledFontForFont(font);
 
       if (!scaledFont) {
         // This can occur when something switched DirectWrite off.
         return;
       }
 
       GlyphBuffer buffer;
 
@@ -3102,31 +3099,31 @@ struct NS_STACK_CLASS nsCanvasBidiProces
 
       buffer.mGlyphs = &glyphBuf.front();
       buffer.mNumGlyphs = glyphBuf.size();
 
       if (mOp == nsCanvasRenderingContext2DAzure::TEXT_DRAW_OPERATION_FILL) {
         AdjustedTarget(mCtx)->
           FillGlyphs(scaledFont, buffer,
                      CanvasGeneralPattern().
-                       ForStyle(mCtx, nsCanvasRenderingContext2DAzure::STYLE_FILL, mCtx->mTarget),
-                     DrawOptions(mState->globalAlpha, mCtx->UsedOperation()));
+                        ForStyle(mCtx, nsCanvasRenderingContext2DAzure::STYLE_FILL, mCtx->mTarget),
+                      DrawOptions(mState->globalAlpha, mCtx->UsedOperation()));
       } else if (mOp == nsCanvasRenderingContext2DAzure::TEXT_DRAW_OPERATION_STROKE) {
         RefPtr<Path> path = scaledFont->GetPathForGlyphs(buffer, mCtx->mTarget);
 
         const ContextState& state = *mState;
         AdjustedTarget(mCtx)->
           Stroke(path, CanvasGeneralPattern().
-                   ForStyle(mCtx, nsCanvasRenderingContext2DAzure::STYLE_STROKE, mCtx->mTarget),
-                 StrokeOptions(state.lineWidth, state.lineJoin,
-                               state.lineCap, state.miterLimit,
-                               state.dash.Length(),
-                               state.dash.Elements(),
-                               state.dashOffset),
-                 DrawOptions(state.globalAlpha, mCtx->UsedOperation()));
+                    ForStyle(mCtx, nsCanvasRenderingContext2DAzure::STYLE_STROKE, mCtx->mTarget),
+                  StrokeOptions(state.lineWidth, state.lineJoin,
+                                state.lineCap, state.miterLimit,
+                                state.dash.Length(),
+                                state.dash.Elements(),
+                                state.dashOffset),
+                  DrawOptions(state.globalAlpha, mCtx->UsedOperation()));
 
       }
     }
   }
 
   // current text run
   nsAutoPtr<gfxTextRun> mTextRun;
 
@@ -3605,24 +3602,19 @@ nsCanvasRenderingContext2DAzure::GetMozD
 
 bool
 nsCanvasRenderingContext2DAzure::IsPointInPath(double x, double y)
 {
   if (!FloatValidate(x,y)) {
     return false;
   }
 
-  EnsureUserSpacePath(false);
-  if (!mPath) {
-    return false;
-  }
-  if (mPathTransformWillUpdate) {
-    return mPath->ContainsPoint(Point(x, y), mPathToDS);
-  }
-  return mPath->ContainsPoint(Point(x, y), mTarget->GetTransform());
+  EnsureUserSpacePath();
+
+  return mPath && mPath->ContainsPoint(Point(x, y), mTarget->GetTransform());
 }
 
 NS_IMETHODIMP
 nsCanvasRenderingContext2DAzure::IsPointInPath(float x, float y, bool *retVal)
 {
   *retVal = IsPointInPath(x, y);
   return NS_OK;
 }
@@ -3671,24 +3663,22 @@ nsCanvasRenderingContext2DAzure::DrawIma
     if (srcCanvas == this) {
       // Self-copy.
       srcSurf = mTarget->Snapshot();
       imgSize = gfxIntSize(mWidth, mHeight);
     } else if (srcCanvas) {
       // This might not be an Azure canvas!
       srcSurf = srcCanvas->GetSurfaceSnapshot();
 
-      if (srcSurf) {
-        if (mCanvasElement) {
-          // Do security check here.
-          CanvasUtils::DoDrawImageSecurityCheck(mCanvasElement,
-                                                element->NodePrincipal(),
-                                               canvas->IsWriteOnly(),
-                                                false);
-        }
+      if (srcSurf && mCanvasElement) {
+        // Do security check here.
+        CanvasUtils::DoDrawImageSecurityCheck(mCanvasElement,
+                                              element->NodePrincipal(),
+                                              canvas->IsWriteOnly(),
+                                              false);
         imgSize = gfxIntSize(srcSurf->GetSize().width, srcSurf->GetSize().height);
       }
     }
   } else {
     if (image.IsHTMLImageElement()) {
       nsHTMLImageElement* img = image.GetAsHTMLImageElement();
       element = img;
     } else {
@@ -4260,31 +4250,28 @@ nsCanvasRenderingContext2DAzure::GetImag
   dstWriteRect.MoveBy(-aX, -aY);
 
   uint8_t* src = data;
   uint32_t srcStride = aWidth * 4;
   
   RefPtr<DataSourceSurface> readback;
   if (!srcReadRect.IsEmpty()) {
     RefPtr<SourceSurface> snapshot = mTarget->Snapshot();
-    if (snapshot) {
-      readback = snapshot->GetDataSurface();
-
-      srcStride = readback->Stride();
-      src = readback->GetData() + srcReadRect.y * srcStride + srcReadRect.x * 4;
-    }
+
+    readback = snapshot->GetDataSurface();
+
+    srcStride = readback->Stride();
+    src = readback->GetData() + srcReadRect.y * srcStride + srcReadRect.x * 4;
   }
 
   // make sure sUnpremultiplyTable has been created
   EnsureUnpremultiplyTable();
 
   // NOTE! dst is the same as src, and this relies on reading
   // from src and advancing that ptr before writing to dst.
-  // NOTE! I'm not sure that it is, I think this comment might have been
-  // inherited from Thebes canvas and is no longer true
   uint8_t* dst = data + dstWriteRect.y * (aWidth * 4) + dstWriteRect.x * 4;
 
   for (int32_t j = 0; j < dstWriteRect.height; ++j) {
     for (int32_t i = 0; i < dstWriteRect.width; ++i) {
       // XXX Is there some useful swizzle MMX we can use here?
 #ifdef IS_LITTLE_ENDIAN
       PRUint8 b = *src++;
       PRUint8 g = *src++;
@@ -4606,18 +4593,18 @@ nsCanvasRenderingContext2DAzure::SetMozI
   SetImageSmoothingEnabled(val);
   return NS_OK;
 }
 
 static PRUint8 g2DContextLayerUserData;
 
 already_AddRefed<CanvasLayer>
 nsCanvasRenderingContext2DAzure::GetCanvasLayer(nsDisplayListBuilder* aBuilder,
-                                                CanvasLayer *aOldLayer,
-                                                LayerManager *aManager)
+                                           CanvasLayer *aOldLayer,
+                                           LayerManager *aManager)
 {
   if (!mValid) {
     return nsnull;
   }
 
   if (mTarget) {
     mTarget->Flush();
   }
@@ -4677,14 +4664,8 @@ nsCanvasRenderingContext2DAzure::MarkCon
 {
   if (mInvalidateCount > 0) {
     mPredictManyRedrawCalls = mInvalidateCount > kCanvasMaxInvalidateCount;
   }
   mIsEntireFrameInvalid = false;
   mInvalidateCount = 0;
 }
 
-
-bool
-nsCanvasRenderingContext2DAzure::ShouldForceInactiveLayer(LayerManager *aManager)
-{
-    return !aManager->CanUseCanvasLayerForSize(gfxIntSize(mWidth, mHeight));
-}
--- a/content/canvas/src/nsCanvasRenderingContext2DAzure.h
+++ b/content/canvas/src/nsCanvasRenderingContext2DAzure.h
@@ -459,17 +459,18 @@ public:
   void AsyncDrawXULElement(nsIDOMXULElement* elem, double x, double y, double w,
                            double h, const nsAString& bgColor, uint32_t flags,
                            mozilla::ErrorResult& error);
 
   nsresult Redraw();
 
   // nsICanvasRenderingContextInternal
   NS_IMETHOD SetDimensions(PRInt32 width, PRInt32 height);
-  NS_IMETHOD InitializeWithSurface(nsIDocShell *shell, gfxASurface *surface, PRInt32 width, PRInt32 height);
+  NS_IMETHOD InitializeWithSurface(nsIDocShell *shell, gfxASurface *surface, PRInt32 width, PRInt32 height)
+  { return NS_ERROR_NOT_IMPLEMENTED; }
 
   NS_IMETHOD Render(gfxContext *ctx,
                     gfxPattern::GraphicsFilter aFilter,
                     PRUint32 aFlags = RenderFlagPremultAlpha);
   NS_IMETHOD GetInputStream(const char* aMimeType,
                             const PRUnichar* aEncoderOptions,
                             nsIInputStream **aStream);
   NS_IMETHOD GetThebesSurface(gfxASurface **surface);
@@ -477,17 +478,16 @@ public:
   mozilla::TemporaryRef<mozilla::gfx::SourceSurface> GetSurfaceSnapshot()
   { return mTarget ? mTarget->Snapshot() : nsnull; }
 
   NS_IMETHOD SetIsOpaque(bool isOpaque);
   NS_IMETHOD Reset();
   already_AddRefed<CanvasLayer> GetCanvasLayer(nsDisplayListBuilder* aBuilder,
                                                 CanvasLayer *aOldLayer,
                                                 LayerManager *aManager);
-  virtual bool ShouldForceInactiveLayer(LayerManager *aManager);
   void MarkContextClean();
   NS_IMETHOD SetIsIPC(bool isIPC);
   // this rect is in canvas device space
   void Redraw(const mozilla::gfx::Rect &r);
   NS_IMETHOD Redraw(const gfxRect &r) { Redraw(ToRect(r)); return NS_OK; }
 
   // this rect is in mTarget's current user space
   void RedrawUser(const gfxRect &r);
@@ -537,21 +537,16 @@ public:
 
   friend class CanvasRenderingContext2DUserDataAzure;
 
 protected:
   nsresult GetImageDataArray(JSContext* aCx, int32_t aX, int32_t aY,
                              uint32_t aWidth, uint32_t aHeight,
                              JSObject** aRetval);
 
-  /**
-   * Internal method to complete initialisation, expects mTarget to have been set
-   */
-  nsresult Initialize(PRInt32 width, PRInt32 height);
-
   nsresult InitializeWithTarget(mozilla::gfx::DrawTarget *surface,
                                 PRInt32 width, PRInt32 height);
 
   /**
     * The number of living nsCanvasRenderingContexts.  When this goes down to
     * 0, we free the premultiply and unpremultiply tables, if they exist.
     */
   static PRUint32 sNumLivingContexts;
@@ -596,24 +591,21 @@ protected:
   /**
     * Creates the premultiply lookup table, if it doesn't exist.
     */
   void EnsurePremultiplyTable();
 
   /* This function ensures there is a writable pathbuilder available, this
    * pathbuilder may be working in user space or in device space or
    * device space.
-   * After calling this function mPathTransformWillUpdate will be false
    */
   void EnsureWritablePath();
 
   // Ensures a path in UserSpace is available.
-  // If aCommitTransform is true, then any transform on the context will be
-  // used for the path.
-  void EnsureUserSpacePath(bool aCommitTransform = true);
+  void EnsureUserSpacePath();
 
   void TransformWillUpdate();
 
   // Report the fillRule has changed.
   void FillRuleChanged();
 
   /**
     * Returns the surface format this canvas should be allocated using. Takes
--- a/content/canvas/test/Makefile.in
+++ b/content/canvas/test/Makefile.in
@@ -50,17 +50,16 @@ MOCHITEST_FILES = \
 	test_2d.strokeRect.zero.5.html \
 	test_toDataURL_alpha.html \
 	test_toDataURL_lowercase_ascii.html \
 	test_toDataURL_parameters.html \
 	test_mozGetAsFile.html \
 	test_canvas_strokeStyle_getter.html \
 	test_bug613794.html \
 	test_bug753758.html \
-	test_bug764125.html \
 	test_drawImage_edge_cases.html \
 	$(NULL)
 
 ifneq (1_Linux,$(MOZ_SUITE)_$(OS_ARCH))
 # This test fails in Suite on Linux for some reason, disable it there
 MOCHITEST_FILES += test_2d.composite.uncovered.image.destination-atop.html
 endif
 
deleted file mode 100644
--- a/content/canvas/test/test_bug764125.html
+++ /dev/null
@@ -1,36 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=764125
-
-Test the correct behaviour for isPointInPath in the presence of multiple transforms,
-where only one tranform ought to be applied.
--->
-<head>
-  <title>Test for Bug 764125</title>
-  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
-  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=764125">Mozilla Bug 764125</a>
-<p id="display"></p>
-<div id="content" style="display: none">
-  
-</div>
-<pre id="test">
-<script>
-/** Test for Bug 764125 **/
-
-var c = document.createElement("canvas");
-
-var ctx = c.getContext("2d");
-ctx.translate(50, 0);
-ctx.rect(50, 0, 20, 20);
-ctx.translate(0, 50);
-ok(ctx.isPointInPath(60, 10) === false, "ctx.isPointInPath(60, 10) === false");
-ok(ctx.isPointInPath(110, 10) === true, "ctx.isPointInPath(110, 10) === true");
-ok(ctx.isPointInPath(110, 60) === false, "ctx.isPointInPath(110, 60) === false");
-</script>
-</pre>
-</body>
-</html>
--- a/content/canvas/test/test_canvas.html
+++ b/content/canvas/test/test_canvas.html
@@ -13,20 +13,16 @@ function IsD2DEnabled() {
     try {
         netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
         enabled = Components.classes["@mozilla.org/gfx/info;1"].getService(Components.interfaces.nsIGfxInfo).D2DEnabled;
     } catch(e) {}
     
     return enabled;
 }
 
-function IsLinux() {
-    return navigator.platform.indexOf("Linux") == 0;
-}
-
 function IsMacOSX10_5orOlder() {
     var is105orOlder = false;
 
     if (navigator.platform.indexOf("Mac") == 0) {
         netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
         var version = Components.classes["@mozilla.org/system-info;1"]
                             .getService(Components.interfaces.nsIPropertyBag2)
                             .getProperty("version");
@@ -39,18 +35,17 @@ function IsMacOSX10_5orOlder() {
 }
 
 
 function IsAzureEnabled() {
   var enabled = false;
 
   try {
     netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
-    var backend = Components.classes["@mozilla.org/gfx/info;1"].getService(Components.interfaces.nsIGfxInfo).getInfo().AzureBackend;
-    enabled = (backend != "none");
+    enabled = Components.classes["@mozilla.org/gfx/info;1"].getService(Components.interfaces.nsIGfxInfo).AzureEnabled;
   } catch (e) { }
 
   return enabled;
 }
 
 function IsAzureSkia() {
   var enabled = false;
   
@@ -58,28 +53,16 @@ function IsAzureSkia() {
     netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
     var backend = Components.classes["@mozilla.org/gfx/info;1"].getService(Components.interfaces.nsIGfxInfo).getInfo().AzureBackend;
     enabled = (backend == "skia");
   } catch (e) { }
 
   return enabled;
 }
 
-function IsAzureCairo() {
-  var enabled = false;
-  
-  try {
-    netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
-    var backend = Components.classes["@mozilla.org/gfx/info;1"].getService(Components.interfaces.nsIGfxInfo).getInfo().AzureBackend;
-    enabled = (backend == "cairo");
-  } catch (e) { }
-
-  return enabled;
-}
-
 </script>
 <!-- Includes all the tests in the content/canvas/tests except for test_bug397524.html -->
 
 <!-- [[[ test_2d.canvas.readonly.html ]]] -->
 
 <p>Canvas test: 2d.canvas.readonly</p>
 <!-- Testing: CanvasRenderingContext2D.canvas is readonly -->
 <canvas id="c1" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
@@ -11307,33 +11290,19 @@ ctx.lineWidth = 50;
 ctx.strokeStyle = '#f00';
 ctx.beginPath();
 ctx.arc(50, 50, 50, 0, Math.PI, false);
 ctx.stroke();
 isPixel(ctx, 50,25, 0,255,0,255, 0);
 isPixel(ctx, 1,1, 0,255,0,255, 0);
 isPixel(ctx, 98,1, 0,255,0,255, 0);
 isPixel(ctx, 1,48, 0,255,0,255, 0);
-// Fails on Linux with Azure/Cairo only
-// The arc is drawn badly due to Cairo limitations, the error only becomes
-// apparent on Linux because of anti-aliasing, probably due to X.
-// The limitation is that Cairo draws arcs by stroking perpendicular to the arc,
-// and at very large stroke thicknesses, this becomes a fan. Where exactly the
-// 'blades' of the fan appear seems to depend on exactly how the arc is defined
-// and the platform. So if the blades of the fan are where pixels are tested it
-// passes the test, if the testing pixels fall in between the blades, then we fail.
-// With Thebes/Cairo, we were rendering wrong, but got lucky with the test, now
-// we are not so lucky.
-// Bug 764125
-if (IsAzureCairo() && IsLinux()) {
-    todo_isPixel(ctx, 20,48, 0,255,0,255, 0);
-} else {
-    isPixel(ctx, 20,48, 0,255,0,255, 0);
-}
-isPixel(ctx, 98,48, 0,255,0,255, 0);
+isPixel(ctx, 20,48, 0,255,0,255, 0);
+isPixel(ctx, 98,48, 0,255,0,255, 0);
+
 
 }
 </script>
 
 <!-- [[[ test_2d.path.arc.shape.2.html ]]] -->
 
 <p>Canvas test: 2d.path.arc.shape.2</p>
 <!-- Testing: arc() from 0 to pi draws stuff in the right half -->
@@ -14683,24 +14652,19 @@ ctx.restore();
 
 isPixel(ctx, 0,0, 0,255,0,255, 0);
 isPixel(ctx, 50,0, 0,255,0,255, 0);
 isPixel(ctx, 99,0, 0,255,0,255, 0);
 isPixel(ctx, 0,25, 0,255,0,255, 0);
 isPixel(ctx, 50,25, 0,255,0,255, 0);
 isPixel(ctx, 99,25, 0,255,0,255, 0);
 isPixel(ctx, 0,49, 0,255,0,255, 0);
-if (IsAzureEnabled() && IsAzureCairo()) {
-  // Bug 764108
-  todo_isPixel(ctx, 50,49, 0,255,0,255, 0);
-  todo_isPixel(ctx, 99,49, 0,255,0,255, 0);
-} else {
-  isPixel(ctx, 50,49, 0,255,0,255, 0);
-  isPixel(ctx, 99,49, 0,255,0,255, 0);
-}
+isPixel(ctx, 50,49, 0,255,0,255, 0);
+isPixel(ctx, 99,49, 0,255,0,255, 0);
+
 
 }
 </script>
 
 <!-- [[[ test_2d.path.stroke.unaffected.html ]]] -->
 
 <p>Canvas test: 2d.path.stroke.unaffected</p>
 <!-- Testing: Stroking does not start a new path or subpath -->
--- a/gfx/2d/2D.h
+++ b/gfx/2d/2D.h
@@ -797,17 +797,17 @@ protected:
   SurfaceFormat mFormat;
 };
 
 class GFX2D_API Factory
 {
 public:
   static bool HasSSE2();
 
-  static TemporaryRef<DrawTarget> CreateDrawTargetForCairoSurface(cairo_surface_t* aSurface, const IntSize& aSize);
+  static TemporaryRef<DrawTarget> CreateDrawTargetForCairoSurface(cairo_surface_t* aSurface);
 
   static TemporaryRef<DrawTarget>
     CreateDrawTarget(BackendType aBackend, const IntSize &aSize, SurfaceFormat aFormat);
   
   static TemporaryRef<DrawTarget>
     CreateDrawTargetForData(BackendType aBackend, unsigned char* aData, const IntSize &aSize, int32_t aStride, SurfaceFormat aFormat);
 
   static TemporaryRef<ScaledFont>
--- a/gfx/2d/DrawTargetCairo.cpp
+++ b/gfx/2d/DrawTargetCairo.cpp
@@ -8,18 +8,16 @@
 #include "SourceSurfaceCairo.h"
 #include "PathCairo.h"
 #include "HelpersCairo.h"
 #include "ScaledFontBase.h"
 
 #include "cairo.h"
 
 #include "Blur.h"
-#include "Logging.h"
-#include "Tools.h"
 
 #ifdef CAIRO_HAS_QUARTZ_SURFACE
 #include "cairo-quartz.h"
 #include <ApplicationServices/ApplicationServices.h>
 #endif
 
 #ifdef CAIRO_HAS_XLIB_SURFACE
 #include "cairo-xlib.h"
@@ -113,61 +111,16 @@ PatternIsCompatible(const Pattern& aPatt
       const RadialGradientPattern& pattern = static_cast<const RadialGradientPattern&>(aPattern);
       return pattern.mStops->GetBackendType() == BACKEND_CAIRO;
     }
     default:
       return true;
   }
 }
 
-static cairo_user_data_key_t surfaceDataKey;
-
-void
-ReleaseData(void* aData)
-{
-  static_cast<DataSourceSurface*>(aData)->Release();
-}
-
-/**
- * Returns cairo surface for the given SourceSurface.
- * If possible, it will use the cairo_surface associated with aSurface,
- * otherwise, it will create a new cairo_surface.
- * In either case, the caller must call cairo_surface_destroy on the
- * result when it is done with it.
- */
-cairo_surface_t*
-GetCairoSurfaceForSourceSurface(SourceSurface *aSurface)
-{
-  if (aSurface->GetType() == SURFACE_CAIRO) {
-    cairo_surface_t* surf = static_cast<SourceSurfaceCairo*>(aSurface)->GetSurface();
-    cairo_surface_reference(surf);
-    return surf;
-  }
-
-  if (aSurface->GetType() == SURFACE_CAIRO_IMAGE) {
-    cairo_surface_t* surf =
-      static_cast<const DataSourceSurfaceCairo*>(aSurface)->GetSurface();
-    cairo_surface_reference(surf);
-    return surf;
-  }
-
-  RefPtr<DataSourceSurface> data = aSurface->GetDataSurface();
-  cairo_surface_t* surf =
-    cairo_image_surface_create_for_data(data->GetData(),
-                                        GfxFormatToCairoFormat(data->GetFormat()),
-                                        data->GetSize().width,
-                                        data->GetSize().height,
-                                        data->Stride());
-  cairo_surface_set_user_data(surf,
- 				                      &surfaceDataKey,
- 				                      data.forget().drop(),
- 				                      ReleaseData);
-  return surf;
-}
-
 // Never returns NULL. As such, you must always pass in Cairo-compatible
 // patterns, most notably gradients with a GradientStopCairo.
 // The pattern returned must have cairo_pattern_destroy() called on it by the
 // caller.
 // As the cairo_pattern_t returned may depend on the Pattern passed in, the
 // lifetime of the cairo_pattern_t returned must not exceed the lifetime of the
 // Pattern passed in.
 static cairo_pattern_t*
@@ -182,17 +135,38 @@ GfxPatternToCairoPattern(const Pattern& 
       Color color = static_cast<const ColorPattern&>(aPattern).mColor;
       pat = cairo_pattern_create_rgba(color.r, color.g, color.b, color.a * aAlpha);
       break;
     }
 
     case PATTERN_SURFACE:
     {
       const SurfacePattern& pattern = static_cast<const SurfacePattern&>(aPattern);
-      cairo_surface_t* surf = GetCairoSurfaceForSourceSurface(pattern.mSurface);
+      cairo_surface_t* surf;
+
+      // After this block, |surf| always has an extra cairo reference to be
+      // destroyed. This makes creating new surfaces or reusing old ones more
+      // uniform.
+      if (pattern.mSurface->GetType() == SURFACE_CAIRO) {
+        const SourceSurfaceCairo* source = static_cast<const SourceSurfaceCairo*>(pattern.mSurface.get());
+        surf = source->GetSurface();
+        cairo_surface_reference(surf);
+      } else if (pattern.mSurface->GetType() == SURFACE_CAIRO_IMAGE) {
+        const DataSourceSurfaceCairo* source =
+          static_cast<const DataSourceSurfaceCairo*>(pattern.mSurface.get());
+        surf = source->GetSurface();
+        cairo_surface_reference(surf);
+      } else {
+        RefPtr<DataSourceSurface> source = pattern.mSurface->GetDataSurface();
+        surf = cairo_image_surface_create_for_data(source->GetData(),
+                                                   GfxFormatToCairoFormat(source->GetFormat()),
+                                                   source->GetSize().width,
+                                                   source->GetSize().height,
+                                                   source->Stride());
+      }
 
       pat = cairo_pattern_create_for_surface(surf);
       cairo_pattern_set_filter(pat, GfxFilterToCairoFilter(pattern.mFilter));
       cairo_pattern_set_extend(pat, GfxExtendToCairoExtend(pattern.mExtendMode));
 
       cairo_surface_destroy(surf);
 
       break;
@@ -239,31 +213,16 @@ GfxPatternToCairoPattern(const Pattern& 
       // We should support all pattern types!
       MOZ_ASSERT(false);
     }
   }
 
   return pat;
 }
 
-/**
- * Returns true iff the the given operator should affect areas of the
- * destination where the source is transparent. Among other things, this
- * implies that a fully transparent source would still affect the canvas.
- */
-static bool
-OperatorAffectsUncoveredAreas(CompositionOp op)
-{
-  return op == OP_IN ||
-         op == OP_OUT ||
-         op == OP_DEST_IN ||
-         op == OP_DEST_ATOP ||
-         op == OP_DEST_OUT;
-}
-
 static bool
 NeedIntermediateSurface(const Pattern& aPattern, const DrawOptions& aOptions)
 {
   // We pre-multiply colours' alpha by the global alpha, so we don't need to
   // use an intermediate surface for them.
   if (aPattern.GetType() == PATTERN_COLOR)
     return false;
 
@@ -280,38 +239,39 @@ DrawTargetCairo::DrawTargetCairo()
 
 DrawTargetCairo::~DrawTargetCairo()
 {
   MarkSnapshotsIndependent();
   if (mPathObserver) {
     mPathObserver->ForgetDrawTarget();
   }
   cairo_destroy(mContext);
-  if (mSurface) {
-    cairo_surface_destroy(mSurface);
-  }
 }
 
 IntSize
 DrawTargetCairo::GetSize()
 {
-  return mSize;
+  return IntSize();
 }
 
 TemporaryRef<SourceSurface>
 DrawTargetCairo::Snapshot()
 {
-  IntSize size = GetSize();
+  cairo_surface_t* csurf = cairo_get_target(mContext);
+  IntSize size;
+  if (GetCairoSurfaceSize(csurf, size)) {
+    cairo_content_t content = cairo_surface_get_content(csurf);
+    RefPtr<SourceSurfaceCairo> surf = new SourceSurfaceCairo(csurf, size,
+                                                             CairoContentToGfxFormat(content),
+                                                             this);
+    AppendSnapshot(surf);
+    return surf;
+  }
 
-  cairo_content_t content = cairo_surface_get_content(mSurface);
-  RefPtr<SourceSurfaceCairo> surf = new SourceSurfaceCairo(mSurface, size,
-                                                           CairoContentToGfxFormat(content),
-                                                           this);
-  AppendSnapshot(surf);
-  return surf;
+  return NULL;
 }
 
 void
 DrawTargetCairo::Flush()
 {
   cairo_surface_t* surf = cairo_get_target(mContext);
   cairo_surface_flush(surf);
 }
@@ -330,145 +290,120 @@ DrawTargetCairo::DrawSurface(SourceSurfa
                              const DrawOptions &aOptions)
 {
   AutoPrepareForDrawing prep(this, mContext);
 
   float sx = aSource.Width() / aDest.Width();
   float sy = aSource.Height() / aDest.Height();
 
   cairo_matrix_t src_mat;
-  cairo_matrix_init_translate(&src_mat, aSource.X(), aSource.Y());
-  cairo_matrix_scale(&src_mat, sx, sy);
+  cairo_matrix_init_scale(&src_mat, sx, sy);
+  cairo_matrix_translate(&src_mat, aSource.X(), aSource.Y());
 
-  cairo_surface_t* surf = GetCairoSurfaceForSourceSurface(aSurface);
+  cairo_surface_t* surf = NULL;
+  if (aSurface->GetType() == SURFACE_CAIRO) {
+    surf = static_cast<SourceSurfaceCairo*>(aSurface)->GetSurface();
+  }
+
   cairo_pattern_t* pat = cairo_pattern_create_for_surface(surf);
-  cairo_surface_destroy(surf);
-
   cairo_pattern_set_matrix(pat, &src_mat);
   cairo_pattern_set_filter(pat, GfxFilterToCairoFilter(aSurfOptions.mFilter));
-  cairo_pattern_set_extend(pat, CAIRO_EXTEND_PAD);
 
   cairo_save(mContext);
-  cairo_translate(mContext, aDest.X(), aDest.Y());
-
-  if (OperatorAffectsUncoveredAreas(aOptions.mCompositionOp) ||
-      aOptions.mCompositionOp == OP_SOURCE) {
-    cairo_push_group(mContext);
-      cairo_new_path(mContext);
-      cairo_rectangle(mContext, 0, 0, aDest.Width(), aDest.Height());
-      //TODO[nrc] remove comments if test ok
-      //cairo_clip(mContext);
-      cairo_set_source(mContext, pat);
-      //cairo_paint(mContext);
-      cairo_fill(mContext);
-    cairo_pop_group_to_source(mContext);
-  } else {
-    cairo_new_path(mContext);
-    cairo_rectangle(mContext, 0, 0, aDest.Width(), aDest.Height());
-    cairo_clip(mContext);
-    cairo_set_source(mContext, pat);
-  }
 
   cairo_set_operator(mContext, GfxOpToCairoOp(aOptions.mCompositionOp));
 
+  cairo_translate(mContext, aDest.X(), aDest.Y());
+
+  cairo_set_source(mContext, pat);
+
+  cairo_new_path(mContext);
+  cairo_rectangle(mContext, 0, 0, aDest.Width(), aDest.Height());
+  cairo_clip(mContext);
   cairo_paint_with_alpha(mContext, aOptions.mAlpha);
 
   cairo_restore(mContext);
 
   cairo_pattern_destroy(pat);
 }
 
 void
 DrawTargetCairo::DrawSurfaceWithShadow(SourceSurface *aSurface,
                                        const Point &aDest,
                                        const Color &aColor,
                                        const Point &aOffset,
                                        Float aSigma,
                                        CompositionOp aOperator)
 {
+  WillChange();
+
   if (aSurface->GetType() != SURFACE_CAIRO) {
     return;
   }
 
-  WillChange();
+  SourceSurfaceCairo* source = static_cast<SourceSurfaceCairo*>(aSurface);
 
   Float width = aSurface->GetSize().width;
   Float height = aSurface->GetSize().height;
   Rect extents(0, 0, width, height);
 
   AlphaBoxBlur blur(extents, IntSize(0, 0),
                     AlphaBoxBlur::CalculateBlurRadius(Point(aSigma, aSigma)),
                     NULL, NULL);
   if (!blur.GetData()) {
     return;
   }
 
   IntSize blursize = blur.GetSize();
+
   cairo_surface_t* blursurf = cairo_image_surface_create_for_data(blur.GetData(),
                                                                   CAIRO_FORMAT_A8,
                                                                   blursize.width,
                                                                   blursize.height,
                                                                   blur.GetStride());
 
-  ClearSurfaceForUnboundedSource(aOperator);
-  
   // Draw the source surface into the surface we're going to blur.
-  SourceSurfaceCairo* source = static_cast<SourceSurfaceCairo*>(aSurface);
   cairo_surface_t* surf = source->GetSurface();
   cairo_pattern_t* pat = cairo_pattern_create_for_surface(surf);
-  cairo_pattern_set_extend(pat, CAIRO_EXTEND_PAD);
 
   cairo_t* ctx = cairo_create(blursurf);
 
   cairo_set_source(ctx, pat);
 
   IntRect blurrect = blur.GetRect();
   cairo_new_path(ctx);
   cairo_rectangle(ctx, blurrect.x, blurrect.y, blurrect.width, blurrect.height);
   cairo_clip(ctx);
   cairo_paint(ctx);
 
   cairo_destroy(ctx);
 
   // Blur the result, then use that blurred result as a mask to draw the shadow
   // colour to the surface.
   blur.Blur();
+
   cairo_save(mContext);
-  cairo_set_operator(mContext, GfxOpToCairoOp(aOperator));
+
+  cairo_set_operator(mContext, CAIRO_OPERATOR_OVER);
+  cairo_set_source_rgba(mContext, aColor.r, aColor.g, aColor.b, aColor.a);
+
   cairo_identity_matrix(mContext);
   cairo_translate(mContext, aDest.x, aDest.y);
 
-  if (OperatorAffectsUncoveredAreas(aOperator) ||
-      aOperator == OP_SOURCE){
-    cairo_push_group(mContext);
-      cairo_set_source_rgba(mContext, aColor.r, aColor.g, aColor.b, aColor.a);
-      cairo_mask_surface(mContext, blursurf, aOffset.x, aOffset.y);
-    cairo_pop_group_to_source(mContext);
-    cairo_paint(mContext);
+  cairo_mask_surface(mContext, blursurf, aOffset.x, aOffset.y);
+
+  // Now that the shadow has been drawn, we can draw the surface on top.
+
+  cairo_set_operator(mContext, GfxOpToCairoOp(aOperator));
 
-    // Now that the shadow has been drawn, we can draw the surface on top.
-    cairo_push_group(mContext);
-      cairo_new_path(mContext);
-      cairo_rectangle(mContext, 0, 0, width, height);
-      //TODO[nrc] remove comments if test ok
-      //cairo_clip(mContext);
-      cairo_set_source(mContext, pat);
-      //cairo_paint(mContext);
-      cairo_fill(mContext);
-    cairo_pop_group_to_source(mContext);
-  } else {
-    cairo_set_source_rgba(mContext, aColor.r, aColor.g, aColor.b, aColor.a);
-    cairo_mask_surface(mContext, blursurf, aOffset.x, aOffset.y);
+  cairo_set_source(mContext, pat);
 
-    // Now that the shadow has been drawn, we can draw the surface on top.
-    cairo_set_source(mContext, pat);
-    cairo_new_path(mContext);
-    cairo_rectangle(mContext, 0, 0, width, height);
-    cairo_clip(mContext);
-  }
+  cairo_new_path(mContext);
+  cairo_rectangle(mContext, 0, 0, width, height);
+  cairo_clip(mContext);
 
   cairo_paint(mContext);
 
   cairo_restore(mContext);
 
   cairo_pattern_destroy(pat);
 }
 
@@ -480,39 +415,35 @@ DrawTargetCairo::DrawPattern(const Patte
 {
   if (!PatternIsCompatible(aPattern)) {
     return;
   }
 
   cairo_pattern_t* pat = GfxPatternToCairoPattern(aPattern, aOptions.mAlpha);
   cairo_set_source(mContext, pat);
 
-  if (NeedIntermediateSurface(aPattern, aOptions) ||
-      OperatorAffectsUncoveredAreas(aOptions.mCompositionOp)) {
+  if (NeedIntermediateSurface(aPattern, aOptions)) {
     cairo_push_group_with_content(mContext, CAIRO_CONTENT_COLOR_ALPHA);
 
-    ClearSurfaceForUnboundedSource(aOptions.mCompositionOp);
-
     // Don't want operators to be applied twice
     cairo_set_operator(mContext, CAIRO_OPERATOR_OVER);
 
     if (aDrawType == DRAW_STROKE) {
       SetCairoStrokeOptions(mContext, aStrokeOptions);
       cairo_stroke_preserve(mContext);
     } else {
       cairo_fill_preserve(mContext);
     }
 
     cairo_pop_group_to_source(mContext);
 
     // Now draw the content using the desired operator
     cairo_set_operator(mContext, GfxOpToCairoOp(aOptions.mCompositionOp));
     cairo_paint_with_alpha(mContext, aOptions.mAlpha);
   } else {
-    ClearSurfaceForUnboundedSource(aOptions.mCompositionOp);
     cairo_set_operator(mContext, GfxOpToCairoOp(aOptions.mCompositionOp));
 
     if (aDrawType == DRAW_STROKE) {
       SetCairoStrokeOptions(mContext, aStrokeOptions);
       cairo_stroke_preserve(mContext);
     } else {
       cairo_fill_preserve(mContext);
     }
@@ -531,41 +462,20 @@ DrawTargetCairo::FillRect(const Rect &aR
   cairo_new_path(mContext);
   cairo_rectangle(mContext, aRect.x, aRect.y, aRect.Width(), aRect.Height());
 
   DrawPattern(aPattern, StrokeOptions(), aOptions, DRAW_FILL);
 }
 
 void
 DrawTargetCairo::CopySurface(SourceSurface *aSurface,
-                             const IntRect &aSource,
-                             const IntPoint &aDest)
+                             const IntRect &aSourceRect,
+                             const IntPoint &aDestination)
 {
   AutoPrepareForDrawing prep(this, mContext);
-
-  if (!aSurface || aSurface->GetType() != SURFACE_CAIRO) {
-    gfxWarning() << "Unsupported surface type specified";
-    return;
-  }
-
-  cairo_surface_t* surf = static_cast<SourceSurfaceCairo*>(aSurface)->GetSurface();
-
-  cairo_save(mContext);
-
-  cairo_identity_matrix(mContext);
-
-  cairo_set_source_surface(mContext, surf, aDest.x - aSource.x, aDest.y - aSource.y);
-  cairo_set_operator(mContext, CAIRO_OPERATOR_SOURCE);
-
-  cairo_reset_clip(mContext);
-  cairo_new_path(mContext);
-  cairo_rectangle(mContext, aDest.x, aDest.y, aSource.width, aSource.height);
-  cairo_fill(mContext);
-
-  cairo_restore(mContext);
 }
 
 void
 DrawTargetCairo::ClearRect(const Rect& aRect)
 {
   AutoPrepareForDrawing prep(this, mContext);
 
   cairo_save(mContext);
@@ -721,70 +631,36 @@ DrawTargetCairo::CreatePathBuilder(FillR
   // Creating a PathBuilder implicitly resets our mPathObserver, as it calls
   // SetPathObserver() on us. Since this guarantees our old path is saved off,
   // it's safe to reset the path here.
   cairo_new_path(mContext);
 
   return builder;
 }
 
-void
-DrawTargetCairo::ClearSurfaceForUnboundedSource(const CompositionOp &aOperator)
-{
-  if (aOperator != OP_SOURCE)
-    return;
-  cairo_set_operator(mContext, CAIRO_OPERATOR_CLEAR);
-  // It doesn't really matter what the source is here, since Paint
-  // isn't bounded by the source and the mask covers the entire clip
-  // region.
-  cairo_paint(mContext);
-}
-
-
 TemporaryRef<GradientStops>
 DrawTargetCairo::CreateGradientStops(GradientStop *aStops, uint32_t aNumStops, ExtendMode aExtendMode) const
 {
   RefPtr<GradientStopsCairo> stops = new GradientStopsCairo(aStops, aNumStops);
   return stops;
 }
 
-/**
- * Copies pixel data from aData into aSurface; aData must have the dimensions
- * given in aSize, with a stride of aStride bytes and aPixelWidth bytes per pixel
- */
-static void
-CopyDataToCairoSurface(cairo_surface_t* aSurface,
-                       unsigned char *aData,
-                       const IntSize &aSize,
-                       int32_t aStride,
-                       int32_t aPixelWidth)
-{
-  unsigned char* surfData = cairo_image_surface_get_data(aSurface);
-  for (int32_t y = 0; y < aSize.height; ++y) {
-    memcpy(surfData + y * aSize.width * aPixelWidth,
-           aData + y * aStride,
-           aSize.width * aPixelWidth);
-  }
-  cairo_surface_mark_dirty(aSurface);
-}
-
 TemporaryRef<SourceSurface>
 DrawTargetCairo::CreateSourceSurfaceFromData(unsigned char *aData,
                                              const IntSize &aSize,
                                              int32_t aStride,
                                              SurfaceFormat aFormat) const
 {
-  cairo_surface_t* surf = cairo_image_surface_create(GfxFormatToCairoFormat(aFormat),
-                                                     aSize.width,
-                                                     aSize.height);
-  CopyDataToCairoSurface(surf, aData, aSize, aStride, BytesPerPixel(aFormat));
-    
+  cairo_surface_t* surf = cairo_image_surface_create_for_data(aData,
+                                                              GfxFormatToCairoFormat(aFormat),
+                                                              aSize.width,
+                                                              aSize.height,
+                                                              aStride);
   RefPtr<SourceSurfaceCairo> source_surf = new SourceSurfaceCairo(surf, aSize, aFormat);
   cairo_surface_destroy(surf);
-
   return source_surf;
 }
 
 TemporaryRef<SourceSurface>
 DrawTargetCairo::OptimizeSourceSurface(SourceSurface *aSurface) const
 {
   return aSurface;
 }
@@ -809,31 +685,27 @@ TemporaryRef<DrawTarget>
 DrawTargetCairo::CreateSimilarDrawTarget(const IntSize &aSize, SurfaceFormat aFormat) const
 {
   cairo_surface_t* similar = cairo_surface_create_similar(cairo_get_target(mContext),
                                                           GfxFormatToCairoContent(aFormat),
                                                           aSize.width, aSize.height);
 
   if (!cairo_surface_status(similar)) {
     RefPtr<DrawTargetCairo> target = new DrawTargetCairo();
-    target->Init(similar, aSize);
+    target->Init(similar);
     return target;
   }
 
   return NULL;
 }
 
 bool
-DrawTargetCairo::Init(cairo_surface_t* aSurface, const IntSize& aSize)
+DrawTargetCairo::Init(cairo_surface_t* aSurface)
 {
   mContext = cairo_create(aSurface);
-  mSurface = aSurface;
-  cairo_surface_reference(mSurface);
-  mSize = aSize;
-  mFormat = CairoContentToGfxFormat(cairo_surface_get_content(aSurface));
 
   return true;
 }
 
 void *
 DrawTargetCairo::GetNativeSurface(NativeSurfaceType aType)
 {
   if (aType == NATIVE_SURFACE_CAIRO_SURFACE) {
--- a/gfx/2d/DrawTargetCairo.h
+++ b/gfx/2d/DrawTargetCairo.h
@@ -118,17 +118,17 @@ public:
 
   virtual TemporaryRef<GradientStops>
     CreateGradientStops(GradientStop *aStops,
                         uint32_t aNumStops,
                         ExtendMode aExtendMode = EXTEND_CLAMP) const;
 
   virtual void *GetNativeSurface(NativeSurfaceType aType);
 
-  bool Init(cairo_surface_t* aSurface, const IntSize& aSize);
+  bool Init(cairo_surface_t* aSurface);
 
   void SetPathObserver(CairoPathContext* aPathObserver);
 
   virtual void SetTransform(const Matrix& aTransform);
 
   // Call to set up aContext for drawing (with the current transform, etc).
   // Pass the path you're going to be using if you have one.
   // Implicitly calls WillChange(aPath).
@@ -150,23 +150,18 @@ private: // methods
   // context is associated. Pass the path you're going to be using if you have
   // one.
   void WillChange(const Path* aPath = NULL);
 
   // Call if there is any reason to disassociate all snapshots from this draw
   // target; for example, because we're going to be destroyed.
   void MarkSnapshotsIndependent();
 
-  // If the current operator is "source" then clear the destination before we
-  // draw into it, to simulate the effect of an unbounded source operator.
-  void ClearSurfaceForUnboundedSource(const CompositionOp &aOperator);
 private: // data
   cairo_t* mContext;
-  cairo_surface_t* mSurface;
-  IntSize mSize;
   std::vector<SourceSurfaceCairo*> mSnapshots;
   mutable RefPtr<CairoPathContext> mPathObserver;
 };
 
 }
 }
 
 #endif // _MOZILLA_GFX_DRAWTARGET_CAIRO_H_
--- a/gfx/2d/Factory.cpp
+++ b/gfx/2d/Factory.cpp
@@ -234,41 +234,41 @@ TemporaryRef<ScaledFont>
 Factory::CreateScaledFontForNativeFont(const NativeFont &aNativeFont, Float aSize)
 {
   switch (aNativeFont.mType) {
 #ifdef WIN32
   case NATIVE_FONT_DWRITE_FONT_FACE:
     {
       return new ScaledFontDWrite(static_cast<IDWriteFontFace*>(aNativeFont.mFont), aSize);
     }
-  case NATIVE_FONT_GDI_FONT_FACE:
-    {
-      return new ScaledFontWin(static_cast<LOGFONT*>(aNativeFont.mFont), aSize);
-    }
 #endif
 #ifdef XP_MACOSX
   case NATIVE_FONT_MAC_FONT_FACE:
     {
       return new ScaledFontMac(static_cast<CGFontRef>(aNativeFont.mFont), aSize);
     }
 #endif
 #ifdef USE_SKIA
+#ifdef WIN32
+  case NATIVE_FONT_GDI_FONT_FACE:
+    {
+      return new ScaledFontWin(static_cast<LOGFONT*>(aNativeFont.mFont), aSize);
+    }
+#endif
 #ifdef MOZ_ENABLE_FREETYPE
   case NATIVE_FONT_SKIA_FONT_FACE:
     {
       return new ScaledFontFreetype(static_cast<FontOptions*>(aNativeFont.mFont), aSize);
     }
 #endif
 #endif
 #ifdef USE_CAIRO
   case NATIVE_FONT_CAIRO_FONT_FACE:
     {
-      ScaledFontBase* fontBase = new ScaledFontBase(aSize);
-      fontBase->SetCairoScaledFont(static_cast<cairo_scaled_font_t*>(aNativeFont.mFont));
-      return fontBase;
+      return new ScaledFontBase(aSize);
     }
 #endif
   default:
     gfxWarning() << "Invalid native font type specified.";
     return NULL;
   }
 }
 
@@ -362,21 +362,21 @@ uint64_t
 Factory::GetD2DVRAMUsageSourceSurface()
 {
   return DrawTargetD2D::mVRAMUsageSS;
 }
 
 #endif // XP_WIN
 
 TemporaryRef<DrawTarget>
-Factory::CreateDrawTargetForCairoSurface(cairo_surface_t* aSurface, const IntSize& aSize)
+Factory::CreateDrawTargetForCairoSurface(cairo_surface_t* aSurface)
 {
 #ifdef USE_CAIRO
   RefPtr<DrawTargetCairo> newTarget = new DrawTargetCairo();
-  if (newTarget->Init(aSurface, aSize)) {
+  if (newTarget->Init(aSurface)) {
     return newTarget;
   }
 
 #endif
   return NULL;
 }
 
 TemporaryRef<DataSourceSurface>
--- a/gfx/2d/HelpersSkia.h
+++ b/gfx/2d/HelpersSkia.h
@@ -71,17 +71,17 @@ JoinStyleToSkiaJoin(JoinStyle aJoin)
       return SkPaint::kMiter_Join;
   }
   return SkPaint::kDefault_Join;
 }
 
 static inline bool
 StrokeOptionsToPaint(SkPaint& aPaint, const StrokeOptions &aOptions)
 {
-  // Skia renders 0 width strokes with a width of 1 (and in black),
+  // Skia rendewrs 0 width strokes with a width of 1 (and in black),
   // so we should just skip the draw call entirely.
   if (!aOptions.mLineWidth) {
     return false;
   }
   aPaint.setStrokeWidth(SkFloatToScalar(aOptions.mLineWidth));
   aPaint.setStrokeMiter(SkFloatToScalar(aOptions.mMiterLimit));
   aPaint.setStrokeCap(CapStyleToSkiaCap(aOptions.mLineCap));
   aPaint.setStrokeJoin(JoinStyleToSkiaJoin(aOptions.mLineJoin));
--- a/gfx/2d/PathCairo.cpp
+++ b/gfx/2d/PathCairo.cpp
@@ -40,38 +40,16 @@ CairoPathContext::~CairoPathContext()
 {
   if (mDrawTarget) {
     mDrawTarget->SetPathObserver(NULL);
   }
   cairo_destroy(mContext);
 }
 
 void
-CairoPathContext::ObserveTarget(DrawTargetCairo* aDrawTarget)
-{
-  if (!aDrawTarget) {
-    return;
-  }
-
-  if (mDrawTarget) {
-    mDrawTarget->SetPathObserver(NULL);
-  }
-  mDrawTarget = aDrawTarget;
-
-  // If there is a transform on the path, then we must have a separate context
-  // from the draw target, so we cannot be its observer
-  if (!mTransform.IsIdentity()) {
-    ForgetDrawTarget();
-    return;
-  }
-
-  mDrawTarget->SetPathObserver(this);
-}
-
-void
 CairoPathContext::DuplicateContextAndPath(const Matrix& aMatrix /* = Matrix() */)
 {
   // Duplicate the path.
   cairo_path_t* path = cairo_copy_path(mContext);
   cairo_fill_rule_t rule = cairo_get_fill_rule(mContext);
 
   // Duplicate the context.
   cairo_surface_t* surf = cairo_get_target(mContext);
@@ -337,14 +315,18 @@ PathCairo::GetPathContext()
 void
 PathCairo::CopyPathTo(cairo_t* aContext, DrawTargetCairo* aDrawTarget)
 {
   if (mPathContext->GetContext() != aContext) {
     mPathContext->CopyPathTo(aContext);
 
     // Since aDrawTarget wants us to be the current path on its context, we
     // should also listen to it for updates to that path (as an optimization).
-    mPathContext->ObserveTarget(aDrawTarget);
+    // The easiest way to do this is to just recreate mPathContext, since it
+    // registers with aDrawTarget for updates.
+    mPathContext = new CairoPathContext(aContext, aDrawTarget,
+                                        mPathContext->GetFillRule(),
+                                        mPathContext->GetTransform());
   }
 }
 
 }
 }
--- a/gfx/2d/PathCairo.h
+++ b/gfx/2d/PathCairo.h
@@ -63,20 +63,16 @@ public:
 
   // Create a duplicate context, and copy this path to that context. Optionally,
   // the new context can be transformed.
   void DuplicateContextAndPath(const Matrix& aMatrix = Matrix());
 
   // Returns true if this CairoPathContext represents path.
   bool ContainsPath(const Path* path);
 
-  // add ourselves as an observer of aDrawTarget, if possible
-  // if we succeed, then mDrawTarget is set to aDrawTarget
-  void ObserveTarget(DrawTargetCairo* aDrawTarget);
-
   cairo_t* GetContext() const { return mContext; }
   DrawTargetCairo* GetDrawTarget() const { return mDrawTarget; }
   Matrix GetTransform() const { return mTransform; }
   FillRule GetFillRule() const { return mFillRule; }
 
   operator cairo_t* () const { return mContext; }
 
 private: // methods
--- a/gfx/2d/SourceSurfaceCairo.cpp
+++ b/gfx/2d/SourceSurfaceCairo.cpp
@@ -98,17 +98,16 @@ SourceSurfaceCairo::DrawTargetWillChange
     cairo_surface_t* surface = cairo_surface_create_similar(mSurface,
                                                             GfxFormatToCairoContent(mFormat),
                                                             mSize.width, mSize.height);
     cairo_t* ctx = cairo_create(surface);
     cairo_pattern_t* pat = cairo_pattern_create_for_surface(mSurface);
     cairo_set_source(ctx, pat);
     cairo_paint(ctx);
     cairo_destroy(ctx);
-    cairo_pattern_destroy(pat);
 
     // Swap in this new surface.
     cairo_surface_destroy(mSurface);
     mSurface = surface;
   }
 }
 
 void
--- a/gfx/2d/Types.h
+++ b/gfx/2d/Types.h
@@ -33,17 +33,17 @@ enum SurfaceFormat
   FORMAT_B8G8R8A8,
   FORMAT_B8G8R8X8,
   FORMAT_R5G6B5,
   FORMAT_A8
 };
 
 enum BackendType
 {
-  BACKEND_NONE = 0,
+  BACKEND_NONE,
   BACKEND_DIRECT2D,
   BACKEND_COREGRAPHICS,
   BACKEND_CAIRO,
   BACKEND_SKIA
 };
 
 enum FontType
 {
--- a/gfx/layers/d3d10/LayerManagerD3D10.cpp
+++ b/gfx/layers/d3d10/LayerManagerD3D10.cpp
@@ -479,21 +479,18 @@ LayerManagerD3D10::CreateOptimalMaskSurf
   return CreateOptimalSurface(aSize, gfxASurface::ImageFormatARGB32);
 }
 
 
 TemporaryRef<DrawTarget>
 LayerManagerD3D10::CreateDrawTarget(const IntSize &aSize,
                                     SurfaceFormat aFormat)
 {
-  BackendType backend;
   if ((aFormat != FORMAT_B8G8R8A8 &&
-       aFormat != FORMAT_B8G8R8X8) ||
-       !gfxPlatform::GetPlatform()->SupportsAzureCanvas(backend) ||
-       backend != BACKEND_DIRECT2D) {
+       aFormat != FORMAT_B8G8R8X8)) {
     return LayerManager::CreateDrawTarget(aSize, aFormat);
   }
 
   nsRefPtr<ID3D10Texture2D> texture;
   
   CD3D10_TEXTURE2D_DESC desc(DXGI_FORMAT_B8G8R8A8_UNORM, aSize.width, aSize.height, 1, 1);
   desc.BindFlags = D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE;
   
--- a/gfx/layers/d3d9/CanvasLayerD3D9.cpp
+++ b/gfx/layers/d3d9/CanvasLayerD3D9.cpp
@@ -27,17 +27,16 @@ CanvasLayerD3D9::~CanvasLayerD3D9()
 
 void
 CanvasLayerD3D9::Initialize(const Data& aData)
 {
   NS_ASSERTION(mSurface == nsnull, "BasicCanvasLayer::Initialize called twice!");
 
   if (aData.mDrawTarget) {
     mDrawTarget = aData.mDrawTarget;
-    mSurface = gfxPlatform::GetPlatform()->GetThebesSurfaceForDrawTarget(mDrawTarget);
     mNeedsYFlip = false;
     mDataIsPremultiplied = true;
   } else if (aData.mSurface) {
     mSurface = aData.mSurface;
     NS_ASSERTION(aData.mGLContext == nsnull,
                  "CanvasLayer can't have both surface and GLContext");
     mNeedsYFlip = false;
     mDataIsPremultiplied = true;
@@ -135,32 +134,39 @@ CanvasLayerD3D9::UpdateSurface()
     if (!textureLock.HasLock()) {
       NS_WARNING("Failed to lock CanvasLayer texture.");
       return;
     }
 
     D3DLOCKED_RECT lockedRect = textureLock.GetLockRect();
 
     nsRefPtr<gfxImageSurface> sourceSurface;
+    nsRefPtr<gfxASurface> tempSurface;
+    if (mDrawTarget) {
+      tempSurface = gfxPlatform::GetPlatform()->GetThebesSurfaceForDrawTarget(mDrawTarget);
+    }
+    else {
+      tempSurface = mSurface;
+    }
 
-    if (mSurface->GetType() == gfxASurface::SurfaceTypeWin32) {
-      sourceSurface = mSurface->GetAsImageSurface();
-    } else if (mSurface->GetType() == gfxASurface::SurfaceTypeImage) {
-      sourceSurface = static_cast<gfxImageSurface*>(mSurface.get());
+    if (tempSurface->GetType() == gfxASurface::SurfaceTypeWin32) {
+      sourceSurface = tempSurface->GetAsImageSurface();
+    } else if (tempSurface->GetType() == gfxASurface::SurfaceTypeImage) {
+      sourceSurface = static_cast<gfxImageSurface*>(tempSurface.get());
       if (sourceSurface->Format() != gfxASurface::ImageFormatARGB32 &&
           sourceSurface->Format() != gfxASurface::ImageFormatRGB24)
       {
         return;
       }
     } else {
       sourceSurface = new gfxImageSurface(gfxIntSize(mBounds.width, mBounds.height),
                                           gfxASurface::ImageFormatARGB32);
       nsRefPtr<gfxContext> ctx = new gfxContext(sourceSurface);
       ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
-      ctx->SetSource(mSurface);
+      ctx->SetSource(tempSurface);
       ctx->Paint();
     }
 
     PRUint8 *startBits = sourceSurface->Data();
     PRUint32 sourceStride = sourceSurface->Stride();
 
     if (sourceSurface->Format() != gfxASurface::ImageFormatARGB32) {
       mHasAlpha = false;
--- a/gfx/layers/opengl/CanvasLayerOGL.cpp
+++ b/gfx/layers/opengl/CanvasLayerOGL.cpp
@@ -70,17 +70,16 @@ CanvasLayerOGL::Initialize(const Data& a
     NS_WARNING("CanvasLayerOGL can't have both surface and GLContext");
     return;
   }
 
   mOGLManager->MakeCurrent();
 
   if (aData.mDrawTarget) {
     mDrawTarget = aData.mDrawTarget;
-    mCanvasSurface = gfxPlatform::GetPlatform()->GetThebesSurfaceForDrawTarget(mDrawTarget);
     mNeedsYFlip = false;
   } else if (aData.mSurface) {
     mCanvasSurface = aData.mSurface;
     mNeedsYFlip = false;
 #if defined(MOZ_WIDGET_GTK2) && !defined(MOZ_PLATFORM_MAEMO)
     if (aData.mSurface->GetType() == gfxASurface::SurfaceTypeXlib) {
         gfxXlibSurface *xsurf = static_cast<gfxXlibSurface*>(aData.mSurface);
         mPixmap = xsurf->GetGLXPixmap();
@@ -158,17 +157,21 @@ CanvasLayerOGL::UpdateSurface()
         mTexture == 0)
     {
       mOGLManager->MakeCurrent();
       MakeTextureIfNeeded(gl(), mTexture);
     }
   } else {
     nsRefPtr<gfxASurface> updatedAreaSurface;
 
-    if (mCanvasSurface) {
+    if (mDrawTarget) {
+      // TODO: This is suboptimal - We should have direct handling for the surface types instead of
+      // going via a gfxASurface.
+      updatedAreaSurface = gfxPlatform::GetPlatform()->GetThebesSurfaceForDrawTarget(mDrawTarget);
+    } else if (mCanvasSurface) {
       updatedAreaSurface = mCanvasSurface;
     } else if (mCanvasGLContext) {
       gfxIntSize size(mBounds.width, mBounds.height);
       nsRefPtr<gfxImageSurface> updatedAreaImageSurface =
         GetTempSurface(size, gfxASurface::ImageFormatARGB32);
 
       mCanvasGLContext->ReadPixelsIntoImageSurface(0, 0,
                                                    mBounds.width,
@@ -218,18 +221,23 @@ CanvasLayerOGL::RenderLayer(int aPreviou
     program = mOGLManager->GetBasicLayerProgram(CanUseOpaqueSurface(),
                                                 true,
                                                 GetMaskLayer() ? Mask2d : MaskNone);
   } else if (mDelayedUpdates) {
     NS_ABORT_IF_FALSE(mCanvasSurface || mDrawTarget, "WebGL canvases should always be using full texture upload");
     
     drawRect.IntersectRect(drawRect, GetEffectiveVisibleRegion().GetBounds());
 
+    nsRefPtr<gfxASurface> surf = mCanvasSurface;
+    if (mDrawTarget) {
+      surf = gfxPlatform::GetPlatform()->GetThebesSurfaceForDrawTarget(mDrawTarget);
+    }
+
     mLayerProgram =
-      gl()->UploadSurfaceToTexture(mCanvasSurface,
+      gl()->UploadSurfaceToTexture(surf,
                                    nsIntRect(0, 0, drawRect.width, drawRect.height),
                                    mTexture,
                                    true,
                                    drawRect.TopLeft());
   }
 
   if (!program) {
     program = mOGLManager->GetProgram(mLayerProgram, GetMaskLayer());
--- a/gfx/thebes/gfxAndroidPlatform.cpp
+++ b/gfx/thebes/gfxAndroidPlatform.cpp
@@ -156,29 +156,26 @@ gfxAndroidPlatform::MakePlatformFont(con
                                      const PRUint8 *aFontData, PRUint32 aLength)
 {
     return gfxPlatformFontList::PlatformFontList()->MakePlatformFont(aProxyEntry,
                                                                      aFontData,
                                                                      aLength);
 }
 
 RefPtr<ScaledFont>
-gfxAndroidPlatform::GetScaledFontForFont(DrawTarget* aTarget, gfxFont *aFont)
+gfxAndroidPlatform::GetScaledFontForFont(gfxFont *aFont)
 {
+    NS_ASSERTION(aFont->GetType() == gfxFont::FONT_TYPE_FT2, "Expecting Freetype font");
     NativeFont nativeFont;
-    if (aTarget->GetType() == BACKEND_CAIRO) {
-        nativeFont.mType = NATIVE_FONT_CAIRO_FONT_FACE;
-        nativeFont.mFont = NULL;
-        return Factory::CreateScaledFontWithCairo(nativeFont, aFont->GetAdjustedSize(), aFont->GetCairoScaledFont());
-    }
- 
-    NS_ASSERTION(aFont->GetType() == gfxFont::FONT_TYPE_FT2, "Expecting Freetype font");
     nativeFont.mType = NATIVE_FONT_SKIA_FONT_FACE;
     nativeFont.mFont = static_cast<gfxFT2FontBase*>(aFont)->GetFontOptions();
-    return Factory::CreateScaledFontForNativeFont(nativeFont, aFont->GetAdjustedSize());
+    RefPtr<ScaledFont> scaledFont =
+      Factory::CreateScaledFontForNativeFont(nativeFont, aFont->GetAdjustedSize());
+
+    return scaledFont;
 }
 
 bool
 gfxAndroidPlatform::FontHintingEnabled()
 {
     // In "mobile" builds, we sometimes use non-reflow-zoom, so we
     // might not want hinting.  Let's see.
 #ifdef MOZ_USING_ANDROID_JAVA_WIDGETS
--- a/gfx/thebes/gfxAndroidPlatform.h
+++ b/gfx/thebes/gfxAndroidPlatform.h
@@ -28,20 +28,22 @@ public:
     static gfxAndroidPlatform *GetPlatform() {
         return (gfxAndroidPlatform*) gfxPlatform::GetPlatform();
     }
 
     virtual already_AddRefed<gfxASurface>
     CreateOffscreenSurface(const gfxIntSize& size,
                            gfxASurface::gfxContentType contentType);
     
+    virtual bool SupportsAzure(mozilla::gfx::BackendType& aBackend) { aBackend = mozilla::gfx::BACKEND_SKIA; return true; }
+
     virtual gfxImageFormat GetOffscreenFormat() { return mOffscreenFormat; }
     
     mozilla::RefPtr<mozilla::gfx::ScaledFont>
-      GetScaledFontForFont(mozilla::gfx::DrawTarget* aTarget, gfxFont *aFont);
+      GetScaledFontForFont(gfxFont *aFont);
 
     // to support IPC font list (sharing between chrome and content)
     void GetFontList(InfallibleTArray<FontListEntry>* retValue);
 
     // platform implementations of font functions
     virtual bool IsFontFormatSupported(nsIURI *aFontURI, PRUint32 aFormatFlags);
     virtual gfxPlatformFontList* CreatePlatformFontList();
     virtual gfxFontEntry* MakePlatformFont(const gfxProxyFontEntry *aProxyEntry,
--- a/gfx/thebes/gfxFont.cpp
+++ b/gfx/thebes/gfxFont.cpp
@@ -1778,17 +1778,17 @@ gfxFont::Draw(gfxTextRun *aTextRun, PRUi
                                                     glyphs.mNumGlyphs);
       }
 
       // draw any remaining glyphs
       glyphs.Flush(cr, strokePattern, aDrawMode, isRTL, true);
 
     } else {
       RefPtr<ScaledFont> scaledFont =
-        gfxPlatform::GetPlatform()->GetScaledFontForFont(dt, this);
+        gfxPlatform::GetPlatform()->GetScaledFontForFont(this);
       
       if (!scaledFont) {
         return;
       }
 
       bool oldSubpixelAA = dt->GetPermitSubpixelAA();
 
       if (!AllowSubpixelAA()) {
--- a/gfx/thebes/gfxFont.h
+++ b/gfx/thebes/gfxFont.h
@@ -1542,18 +1542,17 @@ public:
     virtual void SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf,
                                      FontCacheSizes*   aSizes) const;
 
     typedef enum {
         FONT_TYPE_DWRITE,
         FONT_TYPE_GDI,
         FONT_TYPE_FT2,
         FONT_TYPE_MAC,
-        FONT_TYPE_OS2,
-        FONT_TYPE_CAIRO
+        FONT_TYPE_OS2
     } FontType;
 
     virtual FontType GetType() const = 0;
 
 protected:
     // Call the appropriate shaper to generate glyphs for aText and store
     // them into aShapedWord.
     // The length of the text is aShapedWord->Length().
--- a/gfx/thebes/gfxPlatform.cpp
+++ b/gfx/thebes/gfxPlatform.cpp
@@ -43,17 +43,16 @@
 #include "gfxGraphiteShaper.h"
 #endif
 
 #include "nsUnicodeRange.h"
 #include "nsServiceManagerUtils.h"
 #include "nsTArray.h"
 #include "nsUnicharUtilCIID.h"
 #include "nsILocaleService.h"
-#include "nsReadableUtils.h"
 
 #include "nsWeakReference.h"
 
 #include "cairo.h"
 #include "qcms.h"
 
 #include "plstr.h"
 #include "nsCRT.h"
@@ -71,17 +70,16 @@
 
 #include "nsIGfxInfo.h"
 
 using namespace mozilla;
 using namespace mozilla::layers;
 
 gfxPlatform *gPlatform = nsnull;
 static bool gEverInitialized = false;
-static nsTArray<nsCString>* gBackendList = nsnull;
 
 // These two may point to the same profile
 static qcms_profile *gCMSOutputProfile = nsnull;
 static qcms_profile *gCMSsRGBProfile = nsnull;
 
 static qcms_transform *gCMSRGBTransform = nsnull;
 static qcms_transform *gCMSInverseRGBTransform = nsnull;
 static qcms_transform *gCMSRGBATransform = nsnull;
@@ -208,30 +206,33 @@ static const char *gPrefLangNames[] = {
     "x-knda",
     "x-sinh",
     "x-tibt",
     "x-unicode",
     "x-user-def"
 };
 
 gfxPlatform::gfxPlatform()
-  : mAzureCanvasBackendCollector(this, &gfxPlatform::GetAzureCanvasBackendInfo)
+  : mAzureBackendCollector(this, &gfxPlatform::GetAzureBackendInfo)
 {
     mUseHarfBuzzScripts = UNINITIALIZED_VALUE;
     mAllowDownloadableFonts = UNINITIALIZED_VALUE;
     mDownloadableFontsSanitize = UNINITIALIZED_VALUE;
     mFallbackUsesCmaps = UNINITIALIZED_VALUE;
 
 #ifdef MOZ_GRAPHITE
     mGraphiteShapingEnabled = UNINITIALIZED_VALUE;
 #endif
     mBidiNumeralOption = UNINITIALIZED_VALUE;
 
-    PRUint32 backendMask = (1 << BACKEND_CAIRO) | (1 << BACKEND_SKIA);
-    InitCanvasBackend(backendMask);
+    if (Preferences::GetBool("gfx.canvas.azure.prefer-skia", false)) {
+        mPreferredDrawTargetBackend = BACKEND_SKIA;
+    } else {
+        mPreferredDrawTargetBackend = BACKEND_NONE;
+    }
 }
 
 gfxPlatform*
 gfxPlatform::GetPlatform()
 {
     if (!gPlatform) {
         Init();
     }
@@ -401,19 +402,16 @@ gfxPlatform::Shutdown()
 #endif
 
     // This will block this thread untill the ImageBridge protocol is completely
     // deleted.
     ImageBridgeChild::ShutDown();
 
     CompositorParent::ShutDown();
 
-    delete gBackendList;
-    gBackendList = nsnull;
-
     delete gPlatform;
     gPlatform = nsnull;
 }
 
 gfxPlatform::~gfxPlatform()
 {
     mScreenReferenceSurface = nsnull;
 
@@ -470,19 +468,19 @@ gfxPlatform::OptimizeImage(gfxImageSurfa
     gfxASurface *ret = optSurface;
     NS_ADDREF(ret);
     return ret;
 }
 
 cairo_user_data_key_t kDrawTarget;
 
 RefPtr<DrawTarget>
-gfxPlatform::CreateDrawTargetForSurface(gfxASurface *aSurface, const IntSize& aSize)
+gfxPlatform::CreateDrawTargetForSurface(gfxASurface *aSurface)
 {
-  RefPtr<DrawTarget> drawTarget = Factory::CreateDrawTargetForCairoSurface(aSurface->CairoSurface(), aSize);
+  RefPtr<DrawTarget> drawTarget = Factory::CreateDrawTargetForCairoSurface(aSurface->CairoSurface());
   aSurface->SetData(&kDrawTarget, drawTarget, NULL);
   return drawTarget;
 }
 
 cairo_user_data_key_t kSourceSurface;
 
 void SourceBufferDestroy(void *srcBuffer)
 {
@@ -529,18 +527,21 @@ gfxPlatform::GetSourceSurfaceForSurface(
     }
     srcBuffer = aTarget->CreateSourceSurfaceFromNativeSurface(surf);
   }
 #endif
 
   if (!srcBuffer) {
     nsRefPtr<gfxImageSurface> imgSurface = aSurface->GetAsImageSurface();
 
-    bool isWin32ImageSurf = imgSurface &&
-                            aSurface->GetType() == gfxASurface::SurfaceTypeWin32;
+    bool isWin32ImageSurf = false;
+
+    if (imgSurface && aSurface->GetType() != gfxASurface::SurfaceTypeWin32) {
+      isWin32ImageSurf = true;
+    }
 
     if (!imgSurface) {
       imgSurface = new gfxImageSurface(aSurface->GetSize(), OptimalFormatForContent(aSurface->GetContentType()));
       nsRefPtr<gfxContext> ctx = new gfxContext(imgSurface);
       ctx->SetSource(aSurface);
       ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
       ctx->Paint();
     }
@@ -566,18 +567,18 @@ gfxPlatform::GetSourceSurfaceForSurface(
     IntSize size = IntSize(imgSurface->GetSize().width, imgSurface->GetSize().height);
     srcBuffer = aTarget->CreateSourceSurfaceFromData(imgSurface->Data(),
                                                      size,
                                                      imgSurface->Stride(),
                                                      format);
 
     if (!srcBuffer) {
       // We need to check if our gfxASurface will keep the underlying data
-      // alive. This is true if gfxASurface actually -is- an ImageSurface or
-      // if it is a gfxWindowsSurface which supports GetAsImageSurface.
+      // alive! This is true if gfxASurface actually -is- an ImageSurface or
+      // if it is a gfxWindowsSurface which supportes GetAsImageSurface.
       if (imgSurface != aSurface && !isWin32ImageSurf) {
         // This shouldn't happen for now, it can be easily supported by making
         // a copy. For now let's just abort.
         NS_RUNTIMEABORT("Attempt to create unsupported SourceSurface from"
             "non-image surface.");
         return nsnull;
       }
 
@@ -599,158 +600,118 @@ gfxPlatform::GetSourceSurfaceForSurface(
 
   srcBuffer->AddRef();
   aSurface->SetData(&kSourceSurface, srcBuffer, SourceBufferDestroy);
 
   return srcBuffer;
 }
 
 RefPtr<ScaledFont>
-gfxPlatform::GetScaledFontForFont(DrawTarget* aTarget, gfxFont *aFont)
+gfxPlatform::GetScaledFontForFont(gfxFont *aFont)
 {
   NativeFont nativeFont;
   nativeFont.mType = NATIVE_FONT_CAIRO_FONT_FACE;
-  nativeFont.mFont = aFont->GetCairoScaledFont();
+  nativeFont.mFont = aFont;
   RefPtr<ScaledFont> scaledFont =
     Factory::CreateScaledFontForNativeFont(nativeFont,
                                            aFont->GetAdjustedSize());
   return scaledFont;
 }
 
-cairo_user_data_key_t kDrawSourceSurface;
-static void
-DataSourceSurfaceDestroy(void *dataSourceSurface)
+UserDataKey kThebesSurfaceKey;
+void
+DestroyThebesSurface(void *data)
 {
-  static_cast<DataSourceSurface*>(dataSourceSurface)->Release();
-}
-
-cairo_user_data_key_t kDrawTargetForSurface;
-static void
-DataDrawTargetDestroy(void *aTarget)
-{
-  static_cast<DrawTarget*>(aTarget)->Release();
+  gfxASurface *surface = static_cast<gfxASurface*>(data);
+  surface->Release();
 }
 
 already_AddRefed<gfxASurface>
 gfxPlatform::GetThebesSurfaceForDrawTarget(DrawTarget *aTarget)
 {
+  // If we have already created a thebes surface, we can just return it.
+  void *surface = aTarget->GetUserData(&kThebesSurfaceKey);
+  if (surface) {
+    nsRefPtr<gfxASurface> surf = static_cast<gfxASurface*>(surface);
+    return surf.forget();
+  }
+
+  nsRefPtr<gfxASurface> surf;
   if (aTarget->GetType() == BACKEND_CAIRO) {
     cairo_surface_t* csurf =
       static_cast<cairo_surface_t*>(aTarget->GetNativeSurface(NATIVE_SURFACE_CAIRO_SURFACE));
-    return gfxASurface::Wrap(csurf);
+    surf = gfxASurface::Wrap(csurf);
+  } else {
+    // The semantics of this part of the function are sort of weird. If we
+    // don't have direct support for the backend, we snapshot the first time
+    // and then return the snapshotted surface for the lifetime of the draw
+    // target. Sometimes it seems like this works out, but it seems like it
+    // might result in no updates ever.
+    RefPtr<SourceSurface> source = aTarget->Snapshot();
+    RefPtr<DataSourceSurface> data = source->GetDataSurface();
+
+    if (!data) {
+      return NULL;
+    }
+
+    IntSize size = data->GetSize();
+    gfxASurface::gfxImageFormat format = OptimalFormatForContent(ContentForFormat(data->GetFormat()));
+
+    // We need to make a copy here because data might change its data under us
+    nsRefPtr<gfxImageSurface> imageSurf = new gfxImageSurface(gfxIntSize(size.width, size.height), format, false);
+ 
+    bool resultOfCopy = imageSurf->CopyFrom(source);
+    NS_ASSERTION(resultOfCopy, "Failed to copy surface.");
+    surf = imageSurf;
   }
 
-  // The semantics of this part of the function are sort of weird. If we
-  // don't have direct support for the backend, we snapshot the first time
-  // and then return the snapshotted surface for the lifetime of the draw
-  // target. Sometimes it seems like this works out, but it seems like it
-  // might result in no updates ever.
-  RefPtr<SourceSurface> source = aTarget->Snapshot();
-  RefPtr<DataSourceSurface> data = source->GetDataSurface();
-
-  if (!data) {
-    return NULL;
-  }
-
-  IntSize size = data->GetSize();
-  gfxASurface::gfxImageFormat format = OptimalFormatForContent(ContentForFormat(data->GetFormat()));
-
-
-  nsRefPtr<gfxASurface> surf =
-    new gfxImageSurface(data->GetData(), gfxIntSize(size.width, size.height),
-                        data->Stride(), format);
-
-  surf->SetData(&kDrawSourceSurface, data.forget().drop(), DataSourceSurfaceDestroy);
-  // keep the draw target alive as long as we need its data
-  aTarget->AddRef();
-  surf->SetData(&kDrawTargetForSurface, aTarget, DataDrawTargetDestroy);
+  // add a reference to be held by the drawTarget
+  // careful, the reference graph is getting complicated here
+  surf->AddRef();
+  aTarget->AddUserData(&kThebesSurfaceKey, surf.get(), DestroyThebesSurface);
 
   return surf.forget();
 }
 
 RefPtr<DrawTarget>
-gfxPlatform::CreateDrawTargetForBackend(BackendType aBackend, const IntSize& aSize, SurfaceFormat aFormat)
+gfxPlatform::CreateOffscreenDrawTarget(const IntSize& aSize, SurfaceFormat aFormat)
 {
   BackendType backend;
-  if (!SupportsAzureCanvas(backend)) {
+  if (!SupportsAzure(backend)) {
     return NULL;
   }
 
   // There is a bunch of knowledge in the gfxPlatform heirarchy about how to
   // create the best offscreen surface for the current system and situation. We
   // can easily take advantage of this for the Cairo backend, so that's what we
   // do.
   // mozilla::gfx::Factory can get away without having all this knowledge for
   // now, but this might need to change in the future (using
   // CreateOffscreenSurface() and CreateDrawTargetForSurface() for all
   // backends).
-  if (aBackend == BACKEND_CAIRO) {
+  if (backend == BACKEND_CAIRO) {
     nsRefPtr<gfxASurface> surf = CreateOffscreenSurface(ThebesIntSize(aSize),
                                                         ContentForFormat(aFormat));
-    if (!surf) {
-      return NULL;
-    }
 
-    return CreateDrawTargetForSurface(surf, aSize);
+    return CreateDrawTargetForSurface(surf);
   } else {
-    return Factory::CreateDrawTarget(aBackend, aSize, aFormat);
+    return Factory::CreateDrawTarget(backend, aSize, aFormat);
   }
 }
 
 RefPtr<DrawTarget>
-gfxPlatform::CreateOffscreenDrawTarget(const IntSize& aSize, SurfaceFormat aFormat)
-{
-  BackendType backend;
-  if (!SupportsAzureCanvas(backend)) {
-    return NULL;
-  }
-
-  RefPtr<DrawTarget> target = CreateDrawTargetForBackend(backend, aSize, aFormat);
-  if (target ||
-      mFallbackCanvasBackend == BACKEND_NONE) {
-    return target;
-  }
-
-  return CreateDrawTargetForBackend(mFallbackCanvasBackend, aSize, aFormat);
-}
-
-
-RefPtr<DrawTarget>
 gfxPlatform::CreateDrawTargetForData(unsigned char* aData, const IntSize& aSize, int32_t aStride, SurfaceFormat aFormat)
 {
   BackendType backend;
-  if (!SupportsAzureCanvas(backend)) {
+  if (!SupportsAzure(backend)) {
     return NULL;
   }
   return Factory::CreateDrawTargetForData(backend, aData, aSize, aStride, aFormat); 
 }
 
-bool
-gfxPlatform::SupportsAzureCanvas(BackendType& aBackend)
-{
-  NS_ASSERTION(mFallbackCanvasBackend == BACKEND_NONE || mPreferredCanvasBackend != BACKEND_NONE,
-               "fallback backend with no preferred backend");
-  aBackend = mPreferredCanvasBackend;
-  return mPreferredCanvasBackend != BACKEND_NONE;
-}
-
-/* static */ BackendType
-gfxPlatform::BackendTypeForName(const nsCString& aName)
-{
-  if (aName.EqualsLiteral("cairo"))
-    return BACKEND_CAIRO;
-  if (aName.EqualsLiteral("skia"))
-    return BACKEND_SKIA;
-  if (aName.EqualsLiteral("direct2d"))
-    return BACKEND_DIRECT2D;
-  if (aName.EqualsLiteral("cg"))
-    return BACKEND_COREGRAPHICS;
-  return BACKEND_NONE;
-}
-
 nsresult
 gfxPlatform::GetFontList(nsIAtom *aLangGroup,
                          const nsACString& aGenericFamily,
                          nsTArray<nsString>& aListOfFonts)
 {
     return NS_ERROR_NOT_IMPLEMENTED;
 }
 
@@ -1161,63 +1122,30 @@ gfxPlatform::AppendPrefLang(eFontPrefLan
     }
     
     if (i == aLen) {
         aPrefLangs[aLen] = aAddLang;
         aLen++;
     }
 }
 
-void
-gfxPlatform::InitCanvasBackend(PRUint32 aBackendBitmask)
-{
-    if (!Preferences::GetBool("gfx.canvas.azure.enabled", false)) {
-        mPreferredCanvasBackend = BACKEND_NONE;
-        mFallbackCanvasBackend = BACKEND_NONE;
-        return;
-    }
-
-    mPreferredCanvasBackend = GetCanvasBackendPref(aBackendBitmask);
-    mFallbackCanvasBackend = GetCanvasBackendPref(aBackendBitmask & ~(1 << mPreferredCanvasBackend));
-}
-
-/* static */ BackendType
-gfxPlatform::GetCanvasBackendPref(PRUint32 aBackendBitmask)
-{
-    if (!gBackendList) {
-        gBackendList = new nsTArray<nsCString>();
-        nsCString prefString;
-        if (NS_SUCCEEDED(Preferences::GetCString("gfx.canvas.azure.backends", &prefString))) {
-            ParseString(prefString, ',', *gBackendList);
-        }
-    }
-
-    for (PRUint32 i = 0; i < gBackendList->Length(); ++i) {
-        BackendType result = BackendTypeForName((*gBackendList)[i]);
-        if ((1 << result) & aBackendBitmask) {
-            return result;
-        }
-    }
-    return BACKEND_NONE;
-}
-
 bool
 gfxPlatform::UseProgressiveTilePainting()
 {
-    static bool sUseProgressiveTilePainting;
-    static bool sUseProgressiveTilePaintingPrefCached = false;
+  static bool sUseProgressiveTilePainting;
+  static bool sUseProgressiveTilePaintingPrefCached = false;
 
-    if (!sUseProgressiveTilePaintingPrefCached) {
-        sUseProgressiveTilePaintingPrefCached = true;
-        mozilla::Preferences::AddBoolVarCache(&sUseProgressiveTilePainting,
-                                              "layers.progressive-paint",
-                                              false);
-    }
+  if (!sUseProgressiveTilePaintingPrefCached) {
+    sUseProgressiveTilePaintingPrefCached = true;
+    mozilla::Preferences::AddBoolVarCache(&sUseProgressiveTilePainting,
+                                          "layers.progressive-paint",
+                                          false);
+  }
 
-    return sUseProgressiveTilePainting;
+  return sUseProgressiveTilePainting;
 }
 
 bool
 gfxPlatform::UseAzureContentDrawing()
 {
   static bool sAzureContentDrawingEnabled;
   static bool sAzureContentDrawingPrefCached = false;
 
--- a/gfx/thebes/gfxPlatform.h
+++ b/gfx/thebes/gfxPlatform.h
@@ -33,16 +33,19 @@ struct gfxFontStyle;
 class gfxUserFontSet;
 class gfxFontEntry;
 class gfxProxyFontEntry;
 class gfxPlatformFontList;
 class gfxTextRun;
 class nsIURI;
 class nsIAtom;
 
+extern mozilla::gfx::UserDataKey kThebesSurfaceKey;
+void DestroyThebesSurface(void *data);
+
 extern cairo_user_data_key_t kDrawTarget;
 
 // pref lang id's for font prefs
 // !!! needs to match the list of pref font.default.xx entries listed in all.js !!!
 // !!! don't use as bit mask, this may grow larger !!!
 
 enum eFontPrefLang {
     eFontPrefLang_Western     =  0,
@@ -122,17 +125,17 @@ GetBackendName(mozilla::gfx::BackendType
         return "quartz";
       case mozilla::gfx::BACKEND_CAIRO:
         return "cairo";
       case mozilla::gfx::BACKEND_SKIA:
         return "skia";
       case mozilla::gfx::BACKEND_NONE:
         return "none";
   }
-  MOZ_NOT_REACHED("Incomplete switch");
+  MOZ_NOT_REACHED("Incomplet switch");
 }
 
 class THEBES_API gfxPlatform {
 public:
     /**
      * Return a pointer to the current active platform.
      * This is a singleton; it contains mostly convenience
      * functions to obtain platform-specific objects.
@@ -164,48 +167,46 @@ public:
     virtual already_AddRefed<gfxASurface>
       CreateOffscreenImageSurface(const gfxIntSize& aSize,
                                   gfxASurface::gfxContentType aContentType);
 
     virtual already_AddRefed<gfxASurface> OptimizeImage(gfxImageSurface *aSurface,
                                                         gfxASurface::gfxImageFormat format);
 
     virtual mozilla::RefPtr<mozilla::gfx::DrawTarget>
-      CreateDrawTargetForSurface(gfxASurface *aSurface, const mozilla::gfx::IntSize& aSize);
+      CreateDrawTargetForSurface(gfxASurface *aSurface);
 
     /*
-     * Creates a SourceSurface for a gfxASurface. This function does no caching,
-     * so the caller should cache the gfxASurface if it will be used frequently.
-     * The returned surface keeps a reference to aTarget, so it is OK to keep the
-     * surface, even if aTarget changes.
-     * aTarget should not keep a reference to the returned surface because that
-     * will cause a cycle.
+     * Creates a SourceSurface for a gfxASurface. This surface should -not- be
+     * held around by the user after the underlying gfxASurface has been
+     * destroyed as a copy of the data is not guaranteed.
      */
     virtual mozilla::RefPtr<mozilla::gfx::SourceSurface>
       GetSourceSurfaceForSurface(mozilla::gfx::DrawTarget *aTarget, gfxASurface *aSurface);
 
     virtual mozilla::RefPtr<mozilla::gfx::ScaledFont>
-      GetScaledFontForFont(mozilla::gfx::DrawTarget* aTarget, gfxFont *aFont);
+      GetScaledFontForFont(gfxFont *aFont);
 
     virtual already_AddRefed<gfxASurface>
       GetThebesSurfaceForDrawTarget(mozilla::gfx::DrawTarget *aTarget);
 
     virtual mozilla::RefPtr<mozilla::gfx::DrawTarget>
       CreateOffscreenDrawTarget(const mozilla::gfx::IntSize& aSize, mozilla::gfx::SurfaceFormat aFormat);
 
     virtual mozilla::RefPtr<mozilla::gfx::DrawTarget>
       CreateDrawTargetForData(unsigned char* aData, const mozilla::gfx::IntSize& aSize, 
                               int32_t aStride, mozilla::gfx::SurfaceFormat aFormat);
 
-    // aBackend will be set to the preferred backend for Azure canvas
-    bool SupportsAzureCanvas(mozilla::gfx::BackendType& aBackend);
+    virtual bool SupportsAzure(mozilla::gfx::BackendType& aBackend) { return false; }
 
-    // aObj will contain the preferred backend for Azure canvas
-    void GetAzureCanvasBackendInfo(mozilla::widget::InfoObject &aObj) {
-      aObj.DefineProperty("AzureBackend", GetBackendName(mPreferredCanvasBackend));
+    void GetAzureBackendInfo(mozilla::widget::InfoObject &aObj) {
+      mozilla::gfx::BackendType backend;
+      if (SupportsAzure(backend)) {
+        aObj.DefineProperty("AzureBackend", GetBackendName(backend)); 
+      }
     }
 
     /*
      * Font bits
      */
 
     virtual void SetupClusterBoundaries(gfxTextRun *aTextRun, const PRUnichar *aString);
 
@@ -449,70 +450,44 @@ public:
     virtual int GetScreenDepth() const;
 
 protected:
     gfxPlatform();
     virtual ~gfxPlatform();
 
     void AppendCJKPrefLangs(eFontPrefLang aPrefLangs[], PRUint32 &aLen, 
                             eFontPrefLang aCharLang, eFontPrefLang aPageLang);
-
-    /**
-     * Helper method, creates a draw target for a specific Azure backend.
-     * Used by CreateOffscreenDrawTarget.
-     */
-    mozilla::RefPtr<mozilla::gfx::DrawTarget>
-      CreateDrawTargetForBackend(mozilla::gfx::BackendType aBackend,
-                                 const mozilla::gfx::IntSize& aSize,
-                                 mozilla::gfx::SurfaceFormat aFormat);
-
-    /**
-     * Initialise the preferred and fallback canvas backends
-     * aBackendBitmask specifies the backends which are acceptable to the caller.
-     * The backend used is determined by aBackendBitmask and the order specified
-     * by the gfx.canvas.azure.backends pref.
-     */
-    void InitCanvasBackend(PRUint32 aBackendBitmask);
-    /**
-     * returns the first backend named in the pref gfx.canvas.azure.backends
-     * which is a component of aBackendBitmask, a bitmask of backend types
-     */
-    static mozilla::gfx::BackendType GetCanvasBackendPref(PRUint32 aBackendBitmask);
-    static mozilla::gfx::BackendType BackendTypeForName(const nsCString& aName);
-
+                                               
     PRInt8  mAllowDownloadableFonts;
     PRInt8  mDownloadableFontsSanitize;
 #ifdef MOZ_GRAPHITE
     PRInt8  mGraphiteShapingEnabled;
 #endif
 
     PRInt8  mBidiNumeralOption;
 
     // whether to always search font cmaps globally 
     // when doing system font fallback
     PRInt8  mFallbackUsesCmaps;
 
     // which scripts should be shaped with harfbuzz
     PRInt32 mUseHarfBuzzScripts;
 
+    // The preferred draw target backend to use
+    mozilla::gfx::BackendType mPreferredDrawTargetBackend;
+
 private:
     /**
      * Start up Thebes.
      */
     static void Init();
 
     virtual qcms_profile* GetPlatformCMSOutputProfile();
 
     nsRefPtr<gfxASurface> mScreenReferenceSurface;
     nsTArray<PRUint32> mCJKPrefLangs;
     nsCOMPtr<nsIObserver> mSRGBOverrideObserver;
     nsCOMPtr<nsIObserver> mFontPrefsObserver;
-
-    // The preferred draw target backend to use for canvas
-    mozilla::gfx::BackendType mPreferredCanvasBackend;
-    // The fallback draw target backend to use for canvas, if the preferred backend fails
-    mozilla::gfx::BackendType mFallbackCanvasBackend;
-
-    mozilla::widget::GfxInfoCollector<gfxPlatform> mAzureCanvasBackendCollector;
+    mozilla::widget::GfxInfoCollector<gfxPlatform> mAzureBackendCollector;
     bool mWorkAroundDriverBugs;
 };
 
 #endif /* GFX_PLATFORM_H */
--- a/gfx/thebes/gfxPlatformGtk.cpp
+++ b/gfx/thebes/gfxPlatformGtk.cpp
@@ -725,21 +725,27 @@ gfxPlatformGtk::GetGdkDrawable(gfxASurfa
     }
 #endif
 
     return NULL;
 }
 #endif
 
 RefPtr<ScaledFont>
-gfxPlatformGtk::GetScaledFontForFont(DrawTarget* aTarget, gfxFont *aFont)
+gfxPlatformGtk::GetScaledFontForFont(gfxFont *aFont)
 {
+    NS_ASSERTION(aFont->GetType() == gfxFont::FONT_TYPE_FT2, "Expecting Freetype font");
     NativeFont nativeFont;
-    if (aTarget->GetType() == BACKEND_CAIRO) {
-        nativeFont.mType = NATIVE_FONT_CAIRO_FONT_FACE;
-        nativeFont.mFont = NULL;
-        return Factory::CreateScaledFontWithCairo(nativeFont, aFont->GetAdjustedSize(), aFont->GetCairoScaledFont());
-    }
-    NS_ASSERTION(aFont->GetType() == gfxFont::FONT_TYPE_FT2, "Expecting Freetype font");
     nativeFont.mType = NATIVE_FONT_SKIA_FONT_FACE;
     nativeFont.mFont = static_cast<gfxFT2FontBase*>(aFont)->GetFontOptions();
-    return Factory::CreateScaledFontForNativeFont(nativeFont, aFont->GetAdjustedSize());
+    RefPtr<ScaledFont> scaledFont =
+      Factory::CreateScaledFontForNativeFont(nativeFont, aFont->GetAdjustedSize());
+
+    return scaledFont;
 }
+
+bool
+gfxPlatformGtk::SupportsAzure(BackendType& aBackend)
+{
+    aBackend = BACKEND_SKIA;
+    return true;
+}
+
--- a/gfx/thebes/gfxPlatformGtk.h
+++ b/gfx/thebes/gfxPlatformGtk.h
@@ -31,17 +31,19 @@ public:
     static gfxPlatformGtk *GetPlatform() {
         return (gfxPlatformGtk*) gfxPlatform::GetPlatform();
     }
 
     already_AddRefed<gfxASurface> CreateOffscreenSurface(const gfxIntSize& size,
                                                          gfxASurface::gfxContentType contentType);
 
     mozilla::RefPtr<mozilla::gfx::ScaledFont>
-      GetScaledFontForFont(mozilla::gfx::DrawTarget* aTarget, gfxFont *aFont);
+      GetScaledFontForFont(gfxFont *aFont);
+
+    virtual bool SupportsAzure(mozilla::gfx::BackendType& aBackend);
 
     nsresult GetFontList(nsIAtom *aLangGroup,
                          const nsACString& aGenericFamily,
                          nsTArray<nsString>& aListOfFonts);
 
     nsresult UpdateFontList();
 
     nsresult ResolveFontName(const nsAString& aFontName,
--- a/gfx/thebes/gfxPlatformMac.cpp
+++ b/gfx/thebes/gfxPlatformMac.cpp
@@ -64,19 +64,16 @@ DisableFontActivation()
 gfxPlatformMac::gfxPlatformMac()
 {
     mOSXVersion = 0;
     OSXVersion();
     if (mOSXVersion >= MAC_OS_X_VERSION_10_6_HEX) {
         DisableFontActivation();
     }
     mFontAntiAliasingThreshold = ReadAntiAliasingThreshold();
-
-    PRUint32 backendMask = (1 << BACKEND_CAIRO) | (1 << BACKEND_SKIA) | (1 << BACKEND_COREGRAPHICS);
-    InitCanvasBackend(backendMask);
 }
 
 gfxPlatformMac::~gfxPlatformMac()
 {
     gfxCoreTextShaper::Shutdown();
 }
 
 gfxPlatformFontList*
@@ -131,22 +128,34 @@ gfxPlatformMac::OptimizeImage(gfxImageSu
         }
     }
 
     nsRefPtr<gfxASurface> ret = new gfxQuartzImageSurface(isurf);
     return ret.forget();
 }
 
 RefPtr<ScaledFont>
-gfxPlatformMac::GetScaledFontForFont(DrawTarget* aTarget, gfxFont *aFont)
+gfxPlatformMac::GetScaledFontForFont(gfxFont *aFont)
 {
     gfxMacFont *font = static_cast<gfxMacFont*>(aFont);
     return font->GetScaledFont();
 }
 
+bool
+gfxPlatformMac::SupportsAzure(BackendType& aBackend)
+{
+  if (mPreferredDrawTargetBackend != BACKEND_NONE) {
+    aBackend = mPreferredDrawTargetBackend;
+  } else {
+    aBackend = BACKEND_COREGRAPHICS;
+  }
+
+  return true;
+}
+
 nsresult
 gfxPlatformMac::ResolveFontName(const nsAString& aFontName,
                                 FontResolverCallback aCallback,
                                 void *aClosure, bool& aAborted)
 {
     nsAutoString resolvedName;
     if (!gfxPlatformFontList::PlatformFontList()->
              ResolveFontName(aFontName, resolvedName)) {
@@ -375,26 +384,36 @@ gfxPlatformMac::ReadAntiAliasingThreshol
 
     return threshold;
 }
 
 already_AddRefed<gfxASurface>
 gfxPlatformMac::GetThebesSurfaceForDrawTarget(DrawTarget *aTarget)
 {
   if (aTarget->GetType() == BACKEND_COREGRAPHICS) {
-    CGContextRef cg = static_cast<CGContextRef>(aTarget->GetNativeSurface(NATIVE_SURFACE_CGCONTEXT));
+    void *surface = aTarget->GetUserData(&kThebesSurfaceKey);
+    if (surface) {
+      nsRefPtr<gfxASurface> surf = static_cast<gfxQuartzSurface*>(surface);
+      return surf.forget();
+    } else {
+      CGContextRef cg = static_cast<CGContextRef>(aTarget->GetNativeSurface(NATIVE_SURFACE_CGCONTEXT));
 
-    //XXX: it would be nice to have an implicit conversion from IntSize to gfxIntSize
-    IntSize intSize = aTarget->GetSize();
-    gfxIntSize size(intSize.width, intSize.height);
+      //XXX: it would be nice to have an implicit conversion from IntSize to gfxIntSize
+      IntSize intSize = aTarget->GetSize();
+      gfxIntSize size(intSize.width, intSize.height);
+
+      nsRefPtr<gfxASurface> surf =
+        new gfxQuartzSurface(cg, size);
 
-    nsRefPtr<gfxASurface> surf =
-      new gfxQuartzSurface(cg, size);
+      // add a reference to be held by the drawTarget
+      surf->AddRef();
+      aTarget->AddUserData(&kThebesSurfaceKey, surf.get(), DestroyThebesSurface);
 
-    return surf.forget();
+      return surf.forget();
+    }
   }
 
   return gfxPlatform::GetThebesSurfaceForDrawTarget(aTarget);
 }
 
 
 qcms_profile *
 gfxPlatformMac::GetPlatformCMSOutputProfile()
--- a/gfx/thebes/gfxPlatformMac.h
+++ b/gfx/thebes/gfxPlatformMac.h
@@ -34,17 +34,19 @@ public:
     virtual already_AddRefed<gfxASurface>
       CreateOffscreenImageSurface(const gfxIntSize& aSize,
                                   gfxASurface::gfxContentType aContentType);
     
     already_AddRefed<gfxASurface> OptimizeImage(gfxImageSurface *aSurface,
                                                 gfxASurface::gfxImageFormat format);
     
     mozilla::RefPtr<mozilla::gfx::ScaledFont>
-      GetScaledFontForFont(mozilla::gfx::DrawTarget* aTarget, gfxFont *aFont);
+      GetScaledFontForFont(gfxFont *aFont);
+
+    virtual bool SupportsAzure(mozilla::gfx::BackendType& aBackend);
 
     nsresult ResolveFontName(const nsAString& aFontName,
                              FontResolverCallback aCallback,
                              void *aClosure, bool& aAborted);
 
     nsresult GetStandardFamilyName(const nsAString& aFontName, nsAString& aFamilyName);
 
     gfxFontGroup *CreateFontGroup(const nsAString &aFamilies,
--- a/gfx/thebes/gfxQtPlatform.cpp
+++ b/gfx/thebes/gfxQtPlatform.cpp
@@ -601,8 +601,15 @@ gfxQtPlatform::GetDPI()
 }
 
 gfxImageFormat
 gfxQtPlatform::GetOffscreenFormat()
 {
     return sOffscreenFormat;
 }
 
+bool
+gfxQtPlatform::SupportsAzure(BackendType& aBackend)
+{
+  aBackend = BACKEND_SKIA;
+  return true;
+}
+
--- a/gfx/thebes/gfxQtPlatform.h
+++ b/gfx/thebes/gfxQtPlatform.h
@@ -42,16 +42,18 @@ public:
 
     static gfxQtPlatform *GetPlatform() {
         return (gfxQtPlatform*) gfxPlatform::GetPlatform();
     }
 
     already_AddRefed<gfxASurface> CreateOffscreenSurface(const gfxIntSize& size,
                                                          gfxASurface::gfxContentType contentType);
 
+    virtual bool SupportsAzure(mozilla::gfx::BackendType& aBackend);
+
     nsresult GetFontList(nsIAtom *aLangGroup,
                          const nsACString& aGenericFamily,
                          nsTArray<nsString>& aListOfFonts);
 
     nsresult UpdateFontList();
 
     nsresult ResolveFontName(const nsAString& aFontName,
                              FontResolverCallback aCallback,
--- a/gfx/thebes/gfxWindowsPlatform.cpp
+++ b/gfx/thebes/gfxWindowsPlatform.cpp
@@ -510,24 +510,16 @@ gfxWindowsPlatform::UpdateRenderMode()
 
             SetupClearTypeParams();
 
             if (hr == S_OK)
               reporter.SetSuccessful();
         }
     }
 #endif
-
-    PRUint32 backendMask = 1 << BACKEND_CAIRO;
-    if (mRenderMode == RENDER_DIRECT2D) {
-      backendMask |= 1 << BACKEND_DIRECT2D;
-    } else {
-      backendMask |= 1 << BACKEND_SKIA;
-    }
-    InitCanvasBackend(backendMask);
 }
 
 void
 gfxWindowsPlatform::VerifyD2DDevice(bool aAttemptForce)
 {
 #ifdef CAIRO_HAS_D2D_SURFACE
     if (mD2DDevice) {
         ID3D10Device1 *device = cairo_d2d_device_get_device(mD2DDevice);
@@ -767,17 +759,17 @@ gfxWindowsPlatform::CreateOffscreenImage
 #ifdef DEBUG
     nsRefPtr<gfxImageSurface> imageSurface = surface->GetAsImageSurface();
     NS_ASSERTION(imageSurface, "Surface cannot be converted to a gfxImageSurface");
 #endif
     return surface.forget();
 }
 
 RefPtr<ScaledFont>
-gfxWindowsPlatform::GetScaledFontForFont(DrawTarget* aTarget, gfxFont *aFont)
+gfxWindowsPlatform::GetScaledFontForFont(gfxFont *aFont)
 {
     if (aFont->GetType() == gfxFont::FONT_TYPE_DWRITE) {
         gfxDWriteFont *font = static_cast<gfxDWriteFont*>(aFont);
 
         NativeFont nativeFont;
         nativeFont.mType = NATIVE_FONT_DWRITE_FONT_FACE;
         nativeFont.mFont = font->GetFontFace();
         RefPtr<ScaledFont> scaledFont =
@@ -789,57 +781,85 @@ gfxWindowsPlatform::GetScaledFontForFont
     NS_ASSERTION(aFont->GetType() == gfxFont::FONT_TYPE_GDI,
         "Fonts on windows should be GDI or DWrite!");
 
     NativeFont nativeFont;
     nativeFont.mType = NATIVE_FONT_GDI_FONT_FACE;
     LOGFONT lf;
     GetObject(static_cast<gfxGDIFont*>(aFont)->GetHFONT(), sizeof(LOGFONT), &lf);
     nativeFont.mFont = &lf;
+    RefPtr<ScaledFont> scaledFont =
+    Factory::CreateScaledFontForNativeFont(nativeFont, aFont->GetAdjustedSize());
 
-    if (aTarget->GetType() == BACKEND_CAIRO) {
-      return Factory::CreateScaledFontWithCairo(nativeFont,
-                                                aFont->GetAdjustedSize(),
-                                                aFont->GetCairoScaledFont());
-    }
-
-    return Factory::CreateScaledFontForNativeFont(nativeFont, aFont->GetAdjustedSize());
+    return scaledFont;
 }
 
 already_AddRefed<gfxASurface>
 gfxWindowsPlatform::GetThebesSurfaceForDrawTarget(DrawTarget *aTarget)
 {
 #ifdef XP_WIN
   if (aTarget->GetType() == BACKEND_DIRECT2D) {
-    if (!GetD2DDevice()) {
-      // We no longer have a D2D device, can't do this.
-      return NULL;
-    }
+    void *surface = aTarget->GetUserData(&kThebesSurfaceKey);
+    if (surface) {
+      nsRefPtr<gfxASurface> surf = static_cast<gfxASurface*>(surface);
+      return surf.forget();
+    } else {
+      if (!GetD2DDevice()) {
+        // We no longer have a D2D device, can't do this.
+        return NULL;
+      }
 
-    RefPtr<ID3D10Texture2D> texture =
-      static_cast<ID3D10Texture2D*>(aTarget->GetNativeSurface(NATIVE_SURFACE_D3D10_TEXTURE));
+      RefPtr<ID3D10Texture2D> texture =
+        static_cast<ID3D10Texture2D*>(aTarget->GetNativeSurface(NATIVE_SURFACE_D3D10_TEXTURE));
+
+      if (!texture) {
+        return gfxPlatform::GetThebesSurfaceForDrawTarget(aTarget);
+      }
 
-    if (!texture) {
-      return gfxPlatform::GetThebesSurfaceForDrawTarget(aTarget);
-    }
+      aTarget->Flush();
 
-    aTarget->Flush();
+      nsRefPtr<gfxASurface> surf =
+        new gfxD2DSurface(texture, ContentForFormat(aTarget->GetFormat()));
 
-    nsRefPtr<gfxASurface> surf =
-      new gfxD2DSurface(texture, ContentForFormat(aTarget->GetFormat()));
+      // add a reference to be held by the drawTarget
+      surf->AddRef();
+      aTarget->AddUserData(&kThebesSurfaceKey, surf.get(), DestroyThebesSurface);
+      /* "It might be worth it to clear cairo surfaces associated with a drawtarget.
+	  The strong reference means for example for D2D that cairo's scratch surface
+	  will be kept alive (well after a user being done) and consume extra VRAM.
+	  We can deal with this in a follow-up though." */
 
-    // shouldn't this hold a reference?
-    surf->SetData(&kDrawTarget, aTarget, NULL);
-    return surf.forget();
+      // shouldn't this hold a reference?
+      surf->SetData(&kDrawTarget, aTarget, NULL);
+      return surf.forget();
+    }
   }
 #endif
 
   return gfxPlatform::GetThebesSurfaceForDrawTarget(aTarget);
 }
 
+bool
+gfxWindowsPlatform::SupportsAzure(BackendType& aBackend)
+{
+#ifdef CAIRO_HAS_D2D_SURFACE
+  if (mRenderMode == RENDER_DIRECT2D) {
+      aBackend = BACKEND_DIRECT2D;
+      return true;
+  }
+#endif
+  
+  if (mPreferredDrawTargetBackend != BACKEND_NONE) {
+    aBackend = mPreferredDrawTargetBackend;
+    return true;
+  }
+
+  return false;
+}
+
 nsresult
 gfxWindowsPlatform::GetFontList(nsIAtom *aLangGroup,
                                 const nsACString& aGenericFamily,
                                 nsTArray<nsString>& aListOfFonts)
 {
     gfxPlatformFontList::PlatformFontList()->GetFontList(aLangGroup, aGenericFamily, aListOfFonts);
 
     return NS_OK;
--- a/gfx/thebes/gfxWindowsPlatform.h
+++ b/gfx/thebes/gfxWindowsPlatform.h
@@ -103,19 +103,21 @@ public:
 
     already_AddRefed<gfxASurface> CreateOffscreenSurface(const gfxIntSize& size,
                                                          gfxASurface::gfxContentType contentType);
     virtual already_AddRefed<gfxASurface>
       CreateOffscreenImageSurface(const gfxIntSize& aSize,
                                   gfxASurface::gfxContentType aContentType);
 
     virtual mozilla::RefPtr<mozilla::gfx::ScaledFont>
-      GetScaledFontForFont(mozilla::gfx::DrawTarget* aTarget, gfxFont *aFont);
+      GetScaledFontForFont(gfxFont *aFont);
     virtual already_AddRefed<gfxASurface>
       GetThebesSurfaceForDrawTarget(mozilla::gfx::DrawTarget *aTarget);
+    
+    virtual bool SupportsAzure(mozilla::gfx::BackendType& aBackend);
 
     enum RenderMode {
         /* Use GDI and windows surfaces */
         RENDER_GDI = 0,
 
         /* Use 32bpp image surfaces and call StretchDIBits */
         RENDER_IMAGE_STRETCH32,
 
--- a/modules/libpref/src/init/all.js
+++ b/modules/libpref/src/init/all.js
@@ -220,27 +220,20 @@ pref("gfx.font_rendering.harfbuzz.script
 
 #ifdef XP_WIN
 pref("gfx.font_rendering.directwrite.enabled", false);
 pref("gfx.font_rendering.directwrite.use_gdi_table_loading", true);
 #endif
 
 #ifdef XP_WIN
 pref("gfx.canvas.azure.enabled", true);
-// comma separated list of backends to use in order of preference
-// e.g., pref("gfx.canvas.azure.backends", "direct2d,skia,cairo");
-pref("gfx.canvas.azure.backends", "direct2d");
 pref("gfx.content.azure.enabled", true);
 #else
 #ifdef XP_MACOSX
 pref("gfx.canvas.azure.enabled", true);
-pref("gfx.canvas.azure.backends", "cg");
-#else
-pref("gfx.canvas.azure.enabled", false);
-pref("gfx.canvas.azure.backends", "cairo,skia");
 #endif
 #endif
 
 #ifdef ANDROID
 pref("gfx.textures.poweroftwo.force-enabled", false);
 #endif
 
 pref("gfx.work-around-driver-bugs", true);
--- a/widget/android/GfxInfo.cpp
+++ b/widget/android/GfxInfo.cpp
@@ -38,16 +38,22 @@ GfxInfo::GetD2DEnabled(bool *aEnabled)
 }
 
 nsresult
 GfxInfo::GetDWriteEnabled(bool *aEnabled)
 {
   return NS_ERROR_FAILURE;
 }
 
+nsresult
+GfxInfo::GetAzureEnabled(bool *aEnabled)
+{
+  return NS_ERROR_FAILURE;
+}
+
 /* readonly attribute DOMString DWriteVersion; */
 NS_IMETHODIMP
 GfxInfo::GetDWriteVersion(nsAString & aDwriteVersion)
 {
   return NS_ERROR_FAILURE;
 }
 
 /* readonly attribute DOMString cleartypeParameters; */
--- a/widget/android/GfxInfo.h
+++ b/widget/android/GfxInfo.h
@@ -20,16 +20,17 @@ class GfxInfo : public GfxInfoBase
 {
 public:
   GfxInfo();
 
   // We only declare the subset of nsIGfxInfo that we actually implement. The
   // rest is brought forward from GfxInfoBase.
   NS_IMETHOD GetD2DEnabled(bool *aD2DEnabled);
   NS_IMETHOD GetDWriteEnabled(bool *aDWriteEnabled);
+  NS_IMETHOD GetAzureEnabled(bool *aAzureEnabled);
   NS_IMETHOD GetDWriteVersion(nsAString & aDwriteVersion);
   NS_IMETHOD GetCleartypeParameters(nsAString & aCleartypeParams);
   NS_IMETHOD GetAdapterDescription(nsAString & aAdapterDescription);
   NS_IMETHOD GetAdapterDriver(nsAString & aAdapterDriver);
   NS_IMETHOD GetAdapterVendorID(nsAString & aAdapterVendorID);
   NS_IMETHOD GetAdapterDeviceID(nsAString & aAdapterDeviceID);
   NS_IMETHOD GetAdapterRAM(nsAString & aAdapterRAM);
   NS_IMETHOD GetAdapterDriverVersion(nsAString & aAdapterDriverVersion);
--- a/widget/cocoa/GfxInfo.h
+++ b/widget/cocoa/GfxInfo.h
@@ -19,16 +19,17 @@ class GfxInfo : public GfxInfoBase
 {
 public:
 
   GfxInfo();
   // We only declare the subset of nsIGfxInfo that we actually implement. The
   // rest is brought forward from GfxInfoBase.
   NS_IMETHOD GetD2DEnabled(bool *aD2DEnabled);
   NS_IMETHOD GetDWriteEnabled(bool *aDWriteEnabled);
+  NS_IMETHOD GetAzureEnabled(bool *aAzureEnabled);
   NS_IMETHOD GetDWriteVersion(nsAString & aDwriteVersion);
   NS_IMETHOD GetCleartypeParameters(nsAString & aCleartypeParams);
   NS_IMETHOD GetAdapterDescription(nsAString & aAdapterDescription);
   NS_IMETHOD GetAdapterDriver(nsAString & aAdapterDriver);
   NS_IMETHOD GetAdapterVendorID(nsAString & aAdapterVendorID);
   NS_IMETHOD GetAdapterDeviceID(nsAString & aAdapterDeviceID);
   NS_IMETHOD GetAdapterRAM(nsAString & aAdapterRAM);
   NS_IMETHOD GetAdapterDriverVersion(nsAString & aAdapterDriverVersion);
--- a/widget/cocoa/GfxInfo.mm
+++ b/widget/cocoa/GfxInfo.mm
@@ -150,16 +150,30 @@ GfxInfo::Init()
 
 NS_IMETHODIMP
 GfxInfo::GetD2DEnabled(bool *aEnabled)
 {
   return NS_ERROR_FAILURE;
 }
 
 NS_IMETHODIMP
+GfxInfo::GetAzureEnabled(bool *aEnabled)
+{
+  bool azure = false;
+  nsresult rv = mozilla::Preferences::GetBool("gfx.canvas.azure.enabled", &azure);
+  
+  if (NS_SUCCEEDED(rv) && azure) {
+    *aEnabled = true;
+  } else {
+    *aEnabled = false;
+  }
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 GfxInfo::GetDWriteEnabled(bool *aEnabled)
 {
   return NS_ERROR_FAILURE;
 }
 
 /* readonly attribute DOMString DWriteVersion; */
 NS_IMETHODIMP
 GfxInfo::GetDWriteVersion(nsAString & aDwriteVersion)
--- a/widget/nsIGfxInfo.idl
+++ b/widget/nsIGfxInfo.idl
@@ -11,16 +11,17 @@
 [scriptable, uuid(a67c77af-2952-4028-93ab-e7bc3b43cf81)]
 interface nsIGfxInfo : nsISupports
 {
   /*
    * These are win32-specific
    */
   readonly attribute boolean D2DEnabled;
   readonly attribute boolean DWriteEnabled;
+  readonly attribute boolean AzureEnabled;
   readonly attribute DOMString DWriteVersion;
   readonly attribute DOMString cleartypeParameters;
 
   // XXX: Switch to a list of devices, rather than explicitly numbering them. 
 
   /**
    * The name of the display adapter.
    */
--- a/widget/windows/GfxInfo.cpp
+++ b/widget/windows/GfxInfo.cpp
@@ -54,16 +54,36 @@ GfxInfo::GetD2DEnabled(bool *aEnabled)
 
 nsresult
 GfxInfo::GetDWriteEnabled(bool *aEnabled)
 {
   *aEnabled = gfxWindowsPlatform::GetPlatform()->DWriteEnabled();
   return NS_OK;
 }
 
+nsresult
+GfxInfo::GetAzureEnabled(bool *aEnabled)
+{
+  *aEnabled = false;
+
+  bool d2dEnabled = 
+    gfxWindowsPlatform::GetPlatform()->GetRenderMode() == gfxWindowsPlatform::RENDER_DIRECT2D;
+
+  if (d2dEnabled) {
+    bool azure = false;
+    nsresult rv = mozilla::Preferences::GetBool("gfx.canvas.azure.enabled", &azure);
+
+    if (NS_SUCCEEDED(rv) && azure) {
+      *aEnabled = true;
+    }
+  }
+
+  return NS_OK;
+}
+
 /* readonly attribute DOMString DWriteVersion; */
 NS_IMETHODIMP
 GfxInfo::GetDWriteVersion(nsAString & aDwriteVersion)
 {
   gfxWindowsPlatform::GetDLLVersion(L"dwrite.dll", aDwriteVersion);
   return NS_OK;
 }
 
--- a/widget/windows/GfxInfo.h
+++ b/widget/windows/GfxInfo.h
@@ -17,16 +17,17 @@ class GfxInfo : public GfxInfoBase
 {
 public:
   GfxInfo();
 
   // We only declare the subset of nsIGfxInfo that we actually implement. The
   // rest is brought forward from GfxInfoBase.
   NS_IMETHOD GetD2DEnabled(bool *aD2DEnabled);
   NS_IMETHOD GetDWriteEnabled(bool *aDWriteEnabled);
+  NS_IMETHOD GetAzureEnabled(bool *aAzureEnabled);
   NS_IMETHOD GetDWriteVersion(nsAString & aDwriteVersion);
   NS_IMETHOD GetCleartypeParameters(nsAString & aCleartypeParams);
   NS_IMETHOD GetAdapterDescription(nsAString & aAdapterDescription);
   NS_IMETHOD GetAdapterDriver(nsAString & aAdapterDriver);
   NS_IMETHOD GetAdapterVendorID(nsAString & aAdapterVendorID);
   NS_IMETHOD GetAdapterDeviceID(nsAString & aAdapterDeviceID);
   NS_IMETHOD GetAdapterRAM(nsAString & aAdapterRAM);
   NS_IMETHOD GetAdapterDriverVersion(nsAString & aAdapterDriverVersion);
--- a/widget/windows/TaskbarPreview.cpp
+++ b/widget/windows/TaskbarPreview.cpp
@@ -56,17 +56,17 @@ PRUint32 gInstCount = 0;
 nsresult
 GetRenderingContext(nsIDocShell *shell, gfxASurface *surface,
                     PRUint32 width, PRUint32 height) {
   nsresult rv;
   nsCOMPtr<nsIDOMCanvasRenderingContext2D> ctx = gCtx;
 
   if (!ctx) {
     // create the canvas rendering context
-    ctx = do_CreateInstance("@mozilla.org/content/canvas-rendering-context;1?id=2d", &rv);
+    ctx = do_CreateInstance("@mozilla.org/content/2dthebes-canvas-rendering-context;1", &rv);
     if (NS_FAILED(rv)) {
       NS_WARNING("Could not create nsICanvasRenderingContext2D for tab previews!");
       return rv;
     }
     gCtx = ctx;
     NS_ADDREF(gCtx);
   }
 
--- a/widget/xpwidgets/GfxInfoX11.cpp
+++ b/widget/xpwidgets/GfxInfoX11.cpp
@@ -365,16 +365,22 @@ GfxInfo::GetD2DEnabled(bool *aEnabled)
 }
 
 NS_IMETHODIMP
 GfxInfo::GetDWriteEnabled(bool *aEnabled)
 {
   return NS_ERROR_FAILURE;
 }
 
+NS_IMETHODIMP
+GfxInfo::GetAzureEnabled(bool *aEnabled)
+{
+  return NS_ERROR_FAILURE;
+}
+
 /* readonly attribute DOMString DWriteVersion; */
 NS_IMETHODIMP
 GfxInfo::GetDWriteVersion(nsAString & aDwriteVersion)
 {
   return NS_ERROR_FAILURE;
 }
 
 /* readonly attribute DOMString cleartypeParameters; */
--- a/widget/xpwidgets/GfxInfoX11.h
+++ b/widget/xpwidgets/GfxInfoX11.h
@@ -16,16 +16,17 @@ namespace widget {
 class GfxInfo : public GfxInfoBase
 {
 public:
 
   // We only declare the subset of nsIGfxInfo that we actually implement. The
   // rest is brought forward from GfxInfoBase.
   NS_IMETHOD GetD2DEnabled(bool *aD2DEnabled);
   NS_IMETHOD GetDWriteEnabled(bool *aDWriteEnabled);
+  NS_IMETHOD GetAzureEnabled(bool *aAzureEnabled);
   NS_IMETHOD GetDWriteVersion(nsAString & aDwriteVersion);
   NS_IMETHOD GetCleartypeParameters(nsAString & aCleartypeParams);
   NS_IMETHOD GetAdapterDescription(nsAString & aAdapterDescription);
   NS_IMETHOD GetAdapterDriver(nsAString & aAdapterDriver);
   NS_IMETHOD GetAdapterVendorID(nsAString & aAdapterVendorID);
   NS_IMETHOD GetAdapterDeviceID(nsAString & aAdapterDeviceID);
   NS_IMETHOD GetAdapterRAM(nsAString & aAdapterRAM);
   NS_IMETHOD GetAdapterDriverVersion(nsAString & aAdapterDriverVersion);