Bug 630052, part b: Reduce code duplication between CreateImageData and GetImageData; r=bz
authorMs2ger <ms2ger@gmail.com>
Sat, 02 Apr 2011 14:18:49 -0400
changeset 64655 2676052e13a8236bff374b3c8d35e8c65b7b746f
parent 64654 8e8e6f2f737d05f45be52bff6d36171a96b927af
child 64656 c51360e5cc597c94574275e7aedf12362bdabaf8
push id19384
push userbzbarsky@mozilla.com
push dateTue, 05 Apr 2011 16:22:12 +0000
treeherdermozilla-central@385684ad7eed [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz
bugs630052
milestone2.2a1pre
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 630052, part b: Reduce code duplication between CreateImageData and GetImageData; r=bz
content/canvas/src/CustomQS_Canvas2D.h
--- a/content/canvas/src/CustomQS_Canvas2D.h
+++ b/content/canvas/src/CustomQS_Canvas2D.h
@@ -34,16 +34,17 @@
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsDOMError.h"
 #include "nsIDOMCanvasRenderingContext2D.h"
+#include "CheckedInt.h"
 
 typedef nsresult (NS_STDCALL nsIDOMCanvasRenderingContext2D::*CanvasStyleSetterType)(const nsAString &, nsISupports *);
 typedef nsresult (NS_STDCALL nsIDOMCanvasRenderingContext2D::*CanvasStyleGetterType)(nsAString &, nsISupports **, PRInt32 *);
 
 static JSBool
 Canvas2D_SetStyleHelper(JSContext *cx, JSObject *obj, jsid id, jsval *vp,
                         CanvasStyleSetterType setfunc)
 {
@@ -148,16 +149,73 @@ nsIDOMCanvasRenderingContext2D_SetFillSt
 }
 
 static JSBool
 nsIDOMCanvasRenderingContext2D_GetFillStyle(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
 {
     return Canvas2D_GetStyleHelper(cx, obj, id, vp, &nsIDOMCanvasRenderingContext2D::GetFillStyle_multi);
 }
 
+static bool
+CreateImageData(JSContext* cx,
+                uint32 w,
+                uint32 h,
+                nsIDOMCanvasRenderingContext2D* self,
+                int32 x,
+                int32 y,
+                jsval* vp)
+{
+    using mozilla::CheckedInt;
+    CheckedInt<uint32> len = CheckedInt<uint32>(w) * h * 4;
+    if (!len.valid()) {
+        return xpc_qsThrow(cx, NS_ERROR_DOM_INDEX_SIZE_ERR);
+    }
+
+    // Create the fast typed array; it's initialized to 0 by default.
+    JSObject* darray =
+      js_CreateTypedArray(cx, js::TypedArray::TYPE_UINT8_CLAMPED, len.value());
+    js::AutoObjectRooter rd(cx, darray);
+    if (!darray) {
+        return false;
+    }
+
+    if (self) {
+        js::TypedArray* tdest = js::TypedArray::fromJSObject(darray);
+
+        // make the call
+        nsresult rv =
+            self->GetImageData_explicit(x, y, w, h,
+                                        static_cast<PRUint8*>(tdest->data),
+                                        tdest->byteLength);
+        if (NS_FAILED(rv)) {
+            return xpc_qsThrowMethodFailed(cx, rv, vp);
+        }
+    }
+
+    // Do JS_NewObject after CreateTypedArray, so that gc will get
+    // triggered here if necessary
+    JSObject* result = JS_NewObject(cx, NULL, NULL, NULL);
+    js::AutoObjectRooter rr(cx, result);
+    if (!result) {
+        return false;
+    }
+
+    if (!JS_DefineProperty(cx, result, "width", INT_TO_JSVAL(w), NULL, NULL,
+                           JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT) ||
+        !JS_DefineProperty(cx, result, "height", INT_TO_JSVAL(h), NULL, NULL,
+                           JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT) ||
+        !JS_DefineProperty(cx, result, "data", OBJECT_TO_JSVAL(darray), NULL, NULL,
+                           JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT)) {
+        return false;
+    }
+
+    *vp = OBJECT_TO_JSVAL(result);
+    return true;
+}
+
 static JSBool
 nsIDOMCanvasRenderingContext2D_CreateImageData(JSContext *cx, uintN argc, jsval *vp)
 {
     XPC_QS_ASSERT_CONTEXT_OK(cx);
 
     /* Note: this doesn't need JS_THIS_OBJECT */
 
     if (argc < 2)
@@ -171,58 +229,28 @@ nsIDOMCanvasRenderingContext2D_CreateIma
         return JS_FALSE;
 
     if (wi <= 0 || hi <= 0)
         return xpc_qsThrow(cx, NS_ERROR_DOM_INDEX_SIZE_ERR);
 
     uint32 w = (uint32) wi;
     uint32 h = (uint32) hi;
 
-    /* Sanity check w * h here */
-    uint32 len0 = w * h;
-    if (len0 / w != (uint32) h)
-        return xpc_qsThrow(cx, NS_ERROR_DOM_INDEX_SIZE_ERR);
-
-    uint32 len = len0 * 4;
-    if (len / 4 != len0)
-        return xpc_qsThrow(cx, NS_ERROR_DOM_INDEX_SIZE_ERR);
-
-    // create the fast typed array; it's initialized to 0 by default
-    JSObject *darray = js_CreateTypedArray(cx, js::TypedArray::TYPE_UINT8_CLAMPED, len);
-    js::AutoObjectRooter rd(cx, darray);
-    if (!darray)
-        return JS_FALSE;
-
-    // Do JS_NewObject after CreateTypedArray, so that gc will get
-    // triggered here if necessary
-    JSObject *result = JS_NewObject(cx, NULL, NULL, NULL);
-    js::AutoObjectRooter rr(cx, result);
-    if (!result)
-        return JS_FALSE;
-
-    if (!JS_DefineProperty(cx, result, "width", INT_TO_JSVAL(w), NULL, NULL, JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT) ||
-        !JS_DefineProperty(cx, result, "height", INT_TO_JSVAL(h), NULL, NULL, JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT) ||
-        !JS_DefineProperty(cx, result, "data", OBJECT_TO_JSVAL(darray), NULL, NULL, JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT))
-        return JS_FALSE;
-
-    *vp = OBJECT_TO_JSVAL(result);
-    return JS_TRUE;
+    return CreateImageData(cx, w, h, NULL, 0, 0, vp);
 }
 
 static JSBool
 nsIDOMCanvasRenderingContext2D_GetImageData(JSContext *cx, uintN argc, jsval *vp)
 {
     XPC_QS_ASSERT_CONTEXT_OK(cx);
 
     JSObject *obj = JS_THIS_OBJECT(cx, vp);
     if (!obj)
         return JS_FALSE;
 
-    nsresult rv;
-
     nsIDOMCanvasRenderingContext2D *self;
     xpc_qsSelfRef selfref;
     js::AutoValueRooter tvr(cx);
     if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, tvr.jsval_addr(), nsnull))
         return JS_FALSE;
 
     if (argc < 4)
         return xpc_qsThrow(cx, NS_ERROR_XPC_NOT_ENOUGH_ARGS);
@@ -238,52 +266,17 @@ nsIDOMCanvasRenderingContext2D_GetImageD
         return JS_FALSE;
 
     if (wi <= 0 || hi <= 0)
         return xpc_qsThrow(cx, NS_ERROR_DOM_INDEX_SIZE_ERR);
 
     uint32 w = (uint32) wi;
     uint32 h = (uint32) hi;
 
-    // Sanity check w * h here
-    uint32 len0 = w * h;
-    if (len0 / w != (uint32) h)
-        return xpc_qsThrow(cx, NS_ERROR_DOM_INDEX_SIZE_ERR);
-
-    uint32 len = len0 * 4;
-    if (len / 4 != len0)
-        return xpc_qsThrow(cx, NS_ERROR_DOM_INDEX_SIZE_ERR);
-
-    // create the fast typed array
-    JSObject *darray = js_CreateTypedArray(cx, js::TypedArray::TYPE_UINT8_CLAMPED, len);
-    js::AutoObjectRooter rd(cx, darray);
-    if (!darray)
-        return JS_FALSE;
-
-    js::TypedArray *tdest = js::TypedArray::fromJSObject(darray);
-
-    // make the call
-    rv = self->GetImageData_explicit(x, y, w, h, (PRUint8*) tdest->data, tdest->byteLength);
-    if (NS_FAILED(rv))
-        return xpc_qsThrowMethodFailed(cx, rv, vp);
-
-    // Do JS_NewObject after CreateTypedArray, so that gc will get
-    // triggered here if necessary
-    JSObject *result = JS_NewObject(cx, NULL, NULL, NULL);
-    js::AutoObjectRooter rr(cx, result);
-    if (!result)
-        return JS_FALSE;
-
-    if (!JS_DefineProperty(cx, result, "width", INT_TO_JSVAL(w), NULL, NULL, JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT) ||
-        !JS_DefineProperty(cx, result, "height", INT_TO_JSVAL(h), NULL, NULL, JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT) ||
-        !JS_DefineProperty(cx, result, "data", OBJECT_TO_JSVAL(darray), NULL, NULL, JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT))
-        return JS_FALSE;
-
-    *vp = OBJECT_TO_JSVAL(result);
-    return JS_TRUE;
+    return CreateImageData(cx, w, h, self, x, y, vp);
 }
 
 static JSBool
 nsIDOMCanvasRenderingContext2D_PutImageData(JSContext *cx, uintN argc, jsval *vp)
 {
     XPC_QS_ASSERT_CONTEXT_OK(cx);
 
     JSObject *obj = JS_THIS_OBJECT(cx, vp);