Fix for bug 762654 (Switch the Azure 2d canvas context to new DOM bindings). r=bz.
authorPeter Van der Beken <peterv@propagandism.org>
Mon, 21 May 2012 23:30:07 +0200
changeset 100496 d6f341e77b68172e828f23701e1e32ae6768ee97
parent 100495 195ffaea56ea8e81374201abf1c15c6f5aa11fcf
child 100497 6a386d638a1ac6e7f911b3908b1987e4be6b0b46
push id1729
push userlsblakk@mozilla.com
push dateMon, 16 Jul 2012 20:02:43 +0000
treeherdermozilla-aurora@f4e75e148951 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz
bugs762654
milestone16.0a1
Fix for bug 762654 (Switch the Azure 2d canvas context to new DOM bindings). r=bz.
content/canvas/public/nsICanvasRenderingContextInternal.h
content/canvas/src/nsCanvasRenderingContext2DAzure.cpp
content/canvas/src/nsCanvasRenderingContext2DAzure.h
content/canvas/test/test_canvas.html
content/html/content/src/nsHTMLCanvasElement.cpp
dom/base/nsDOMClassInfo.cpp
--- a/content/canvas/public/nsICanvasRenderingContextInternal.h
+++ b/content/canvas/public/nsICanvasRenderingContextInternal.h
@@ -124,12 +124,20 @@ public:
   // anything into this canvas before changing the shmem state, it will be
   // lost.
   NS_IMETHOD SetIsIPC(bool isIPC) = 0;
 
 protected:
   nsRefPtr<nsHTMLCanvasElement> mCanvasElement;
 };
 
+namespace mozilla {
+namespace dom {
+
+extern bool AzureCanvasEnabled();
+
+}
+}
+
 NS_DEFINE_STATIC_IID_ACCESSOR(nsICanvasRenderingContextInternal,
                               NS_ICANVASRENDERINGCONTEXTINTERNAL_IID)
 
 #endif /* nsICanvasRenderingContextInternal_h___ */
--- a/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp
+++ b/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp
@@ -90,16 +90,17 @@
 #include "mozilla/unused.h"
 #include "nsCCUncollectableMarker.h"
 #include "nsWrapperCacheInlines.h"
 #include "nsJSUtils.h"
 #include "XPCQuickStubs.h"
 #include "mozilla/dom/BindingUtils.h"
 #include "nsHTMLImageElement.h"
 #include "nsHTMLVideoElement.h"
+#include "mozilla/dom/CanvasRenderingContext2DBinding.h"
 
 #ifdef XP_WIN
 #include "gfxWindowsPlatform.h"
 #endif
 
 // windows.h (included by chromium code) defines this, in its infinite wisdom
 #undef DrawText
 
@@ -536,29 +537,61 @@ 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()
+{
+  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)
 {
-#ifdef XP_WIN
-  if ((gfxWindowsPlatform::GetPlatform()->GetRenderMode() !=
-      gfxWindowsPlatform::RENDER_DIRECT2D ||
-      !gfxWindowsPlatform::GetPlatform()->DWriteEnabled()) &&
-      !Preferences::GetBool("gfx.canvas.azure.prefer-skia", false)) {
+  if (!AzureCanvasEnabledOnPlatform()) {
     return NS_ERROR_NOT_AVAILABLE;
   }
-#elif !defined(XP_MACOSX) && !defined(ANDROID) && !defined(LINUX)
-  return NS_ERROR_NOT_AVAILABLE;
-#endif
 
   nsRefPtr<nsIDOMCanvasRenderingContext2D> ctx = new nsCanvasRenderingContext2DAzure();
   if (!ctx)
     return NS_ERROR_OUT_OF_MEMORY;
 
   *aResult = ctx.forget().get();
   return NS_OK;
 }
@@ -566,16 +599,17 @@ NS_NewCanvasRenderingContext2DAzure(nsID
 nsCanvasRenderingContext2DAzure::nsCanvasRenderingContext2DAzure()
   : mValid(false), mZero(false), mOpaque(false), mResetLayer(true)
   , mIPC(false)
   , mIsEntireFrameInvalid(false)
   , mPredictManyRedrawCalls(false), mPathTransformWillUpdate(false)
   , mInvalidateCount(0)
 {
   sNumLivingContexts++;
+  SetIsDOMBinding();
 }
 
 nsCanvasRenderingContext2DAzure::~nsCanvasRenderingContext2DAzure()
 {
   Reset();
   // Drop references from all CanvasRenderingContext2DUserDataAzure to this context
   for (PRUint32 i = 0; i < mUserDatas.Length(); ++i) {
     mUserDatas[i]->Forget();
@@ -584,16 +618,23 @@ nsCanvasRenderingContext2DAzure::~nsCanv
   if (!sNumLivingContexts) {
     delete[] sUnpremultiplyTable;
     delete[] sPremultiplyTable;
     sUnpremultiplyTable = nsnull;
     sPremultiplyTable = nsnull;
   }
 }
 
+JSObject*
+nsCanvasRenderingContext2DAzure::WrapObject(JSContext *cx, JSObject *scope,
+                                            bool *triedToWrap)
+{
+  return CanvasRenderingContext2DBinding::Wrap(cx, scope, this, triedToWrap);
+}
+
 bool
 nsCanvasRenderingContext2DAzure::ParseColor(const nsAString& aString,
                                             nscolor* aColor)
 {
   nsIDocument* document = mCanvasElement
                           ? mCanvasElement->OwnerDoc()
                           : nsnull;
 
--- a/content/canvas/src/nsCanvasRenderingContext2DAzure.h
+++ b/content/canvas/src/nsCanvasRenderingContext2DAzure.h
@@ -133,16 +133,19 @@ class nsCanvasRenderingContext2DAzure :
 {
 typedef mozilla::dom::HTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement
   HTMLImageOrCanvasOrVideoElement;
 
 public:
   nsCanvasRenderingContext2DAzure();
   virtual ~nsCanvasRenderingContext2DAzure();
 
+  virtual JSObject* WrapObject(JSContext *cx, JSObject *scope,
+                               bool *triedToWrap);
+
   nsHTMLCanvasElement* GetCanvas() const
   {
     return mCanvasElement;
   }
 
   void Save();
   void Restore();
   void Scale(double x, double y, mozilla::ErrorResult& error);
--- a/content/canvas/test/test_canvas.html
+++ b/content/canvas/test/test_canvas.html
@@ -19543,17 +19543,21 @@ ok(window.CanvasRenderingContext2D.proto
 ok(window.CanvasRenderingContext2D.prototype.fill, "window.CanvasRenderingContext2D.prototype.fill");
 window.CanvasRenderingContext2D.prototype = null;
 ok(window.CanvasRenderingContext2D.prototype, "window.CanvasRenderingContext2D.prototype");
 delete window.CanvasRenderingContext2D.prototype;
 ok(window.CanvasRenderingContext2D.prototype, "window.CanvasRenderingContext2D.prototype");
 window.CanvasRenderingContext2D.prototype.fill = 1;
 ok(window.CanvasRenderingContext2D.prototype.fill === 1, "window.CanvasRenderingContext2D.prototype.fill === 1");
 delete window.CanvasRenderingContext2D.prototype.fill;
-todo(window.CanvasRenderingContext2D.prototype.fill === undefined, "window.CanvasRenderingContext2D.prototype.fill === undefined");
+if (IsAzureEnabled()) {
+  ok(window.CanvasRenderingContext2D.prototype.fill === undefined, "window.CanvasRenderingContext2D.prototype.fill === undefined");
+} else {
+  todo(window.CanvasRenderingContext2D.prototype.fill === undefined, "window.CanvasRenderingContext2D.prototype.fill === undefined");
+}
 
 //restore the original method to ensure that other tests can run successfully
 window.CanvasRenderingContext2D.prototype.fill = fill;
 }
 </script>
 
 <!-- [[[ test_2d.type.replace.html ]]] -->
 
--- a/content/html/content/src/nsHTMLCanvasElement.cpp
+++ b/content/html/content/src/nsHTMLCanvasElement.cpp
@@ -760,18 +760,14 @@ nsHTMLCanvasElement::RenderContextsExter
 
 nsresult NS_NewCanvasRenderingContext2DThebes(nsIDOMCanvasRenderingContext2D** aResult);
 nsresult NS_NewCanvasRenderingContext2DAzure(nsIDOMCanvasRenderingContext2D** aResult);
 
 nsresult
 NS_NewCanvasRenderingContext2D(nsIDOMCanvasRenderingContext2D** aResult)
 {
   Telemetry::Accumulate(Telemetry::CANVAS_2D_USED, 1);
-  if (Preferences::GetBool("gfx.canvas.azure.enabled", false)) {
-    nsresult rv = NS_NewCanvasRenderingContext2DAzure(aResult);
-    // If Azure fails, fall back to a classic canvas.
-    if (NS_SUCCEEDED(rv)) {
-      return rv;
-    }
+  if (AzureCanvasEnabled()) {
+    return NS_NewCanvasRenderingContext2DAzure(aResult);
   }
 
   return NS_NewCanvasRenderingContext2DThebes(aResult);
 }
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -529,16 +529,17 @@ using mozilla::dom::indexedDB::IDBWrappe
 #include "DOMFileHandle.h"
 #include "FileRequest.h"
 #include "LockedFile.h"
 
 #include "mozilla/Likely.h"
 
 #undef None // something included above defines this preprocessor symbol, maybe Xlib headers
 #include "WebGLContext.h"
+#include "nsICanvasRenderingContextInternal.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 static NS_DEFINE_CID(kDOMSOF_CID, NS_DOM_SCRIPT_OBJECT_FACTORY_CID);
 
 static const char kDOMStringBundleURL[] =
   "chrome://global/locale/dom/dom.properties";
@@ -4585,16 +4586,20 @@ nsDOMClassInfo::Init()
     Preferences::GetBool("browser.dom.global_scope_pollution.disabled");
 
   // Proxy bindings
   mozilla::dom::binding::Register(nameSpaceManager);
 
   // Non-proxy bindings
   mozilla::dom::Register(nameSpaceManager);
 
+  if (!AzureCanvasEnabled()) {
+    nameSpaceManager->RegisterDefineDOMInterface(NS_LITERAL_STRING("CanvasRenderingContext2D"), NULL);
+  }
+
   sIsInitialized = true;
 
   return NS_OK;
 }
 
 // static
 PRInt32
 nsDOMClassInfo::GetArrayIndexFromId(JSContext *cx, jsid id, bool *aIsNumber)