Backed out changeset 1672d4c79e82

This commit is contained in:
Robert O'Callahan 2010-03-04 17:50:28 +13:00
Родитель 90b432f3ea
Коммит ed427979f2
6 изменённых файлов: 340 добавлений и 322 удалений

Просмотреть файл

@ -1,6 +1,5 @@
/* -*- Mode: C++; tab-width: 40; indent-tabs-mode: nil; c-basic-offset: 4 -*- /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
* /* ***** BEGIN LICENSE BLOCK *****
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
* *
* The contents of this file are subject to the Mozilla Public License Version * The contents of this file are subject to the Mozilla Public License Version
@ -13,10 +12,10 @@
* for the specific language governing rights and limitations under the * for the specific language governing rights and limitations under the
* License. * License.
* *
* The Original Code is Gecko code. * The Original Code is mozilla.org code.
* *
* The Initial Developer of the Original Code is * The Initial Developer of the Original Code is
* Mozilla Corporation * Mozilla Corporation.
* Portions created by the Initial Developer are Copyright (C) 2010 * Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved. * the Initial Developer. All Rights Reserved.
* *
@ -24,8 +23,8 @@
* Vladimir Vukicevic <vladimir@pobox.com> (original author) * Vladimir Vukicevic <vladimir@pobox.com> (original author)
* *
* Alternatively, the contents of this file may be used under the terms of * Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"), * either the GNU General Public License Version 2 or later (the "GPL"), or
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead * in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only * of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to * under the terms of either the GPL or the LGPL, and not to allow others to
@ -37,7 +36,6 @@
* *
* ***** END LICENSE BLOCK ***** */ * ***** END LICENSE BLOCK ***** */
#include "nsDOMError.h"
#include "nsIDOMCanvasRenderingContext2D.h" #include "nsIDOMCanvasRenderingContext2D.h"
typedef nsresult (NS_STDCALL nsIDOMCanvasRenderingContext2D::*CanvasStyleSetterType)(const nsAString &, nsISupports *); typedef nsresult (NS_STDCALL nsIDOMCanvasRenderingContext2D::*CanvasStyleSetterType)(const nsAString &, nsISupports *);
@ -144,216 +142,3 @@ nsIDOMCanvasRenderingContext2D_GetFillStyle(JSContext *cx, JSObject *obj, jsval
{ {
return Canvas2D_GetStyleHelper(cx, obj, id, vp, &nsIDOMCanvasRenderingContext2D::GetFillStyle_multi); return Canvas2D_GetStyleHelper(cx, obj, id, vp, &nsIDOMCanvasRenderingContext2D::GetFillStyle_multi);
} }
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)
return xpc_qsThrow(cx, NS_ERROR_XPC_NOT_ENOUGH_ARGS);
jsval *argv = JS_ARGV(cx, vp);
int32 wi, hi;
if (!JS_ValueToECMAInt32(cx, argv[0], &wi) ||
!JS_ValueToECMAInt32(cx, argv[1], &hi))
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);
JSAutoTempValueRooter 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);
JSAutoTempValueRooter 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;
}
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;
JSAutoTempValueRooter tvr(cx);
if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, tvr.addr(), nsnull))
return JS_FALSE;
if (argc < 4)
return xpc_qsThrow(cx, NS_ERROR_XPC_NOT_ENOUGH_ARGS);
jsval *argv = JS_ARGV(cx, vp);
int32 x, y;
int32 wi, hi;
if (!JS_ValueToECMAInt32(cx, argv[0], &x) ||
!JS_ValueToECMAInt32(cx, argv[1], &y) ||
!JS_ValueToECMAInt32(cx, argv[2], &wi) ||
!JS_ValueToECMAInt32(cx, argv[3], &hi))
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);
JSAutoTempValueRooter 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);
JSAutoTempValueRooter 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;
}
static JSBool
nsIDOMCanvasRenderingContext2D_PutImageData(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;
JSAutoTempValueRooter tvr(cx);
if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, tvr.addr(), nsnull))
return JS_FALSE;
if (argc < 3)
return xpc_qsThrow(cx, NS_ERROR_XPC_NOT_ENOUGH_ARGS);
jsval *argv = JS_ARGV(cx, vp);
if (JSVAL_IS_PRIMITIVE(argv[0]))
return xpc_qsThrow(cx, NS_ERROR_DOM_TYPE_MISMATCH_ERR);
JSObject *dataObject = JSVAL_TO_OBJECT(argv[0]);
int32 x, y;
if (!JS_ValueToECMAInt32(cx, argv[1], &x) ||
!JS_ValueToECMAInt32(cx, argv[2], &y))
return JS_FALSE;
int32 wi, hi;
JSObject *darray;
// grab width, height, and the dense array from the dataObject
JSAutoTempValueRooter tv(cx);
if (!JS_GetProperty(cx, dataObject, "width", tv.addr()) ||
!JS_ValueToECMAInt32(cx, tv.value(), &wi))
return JS_FALSE;
if (!JS_GetProperty(cx, dataObject, "height", tv.addr()) ||
!JS_ValueToECMAInt32(cx, tv.value(), &hi))
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;
if (!JS_GetProperty(cx, dataObject, "data", tv.addr()) ||
JSVAL_IS_PRIMITIVE(tv.value()))
return JS_FALSE;
darray = JSVAL_TO_OBJECT(tv.value());
JSAutoTempValueRooter tsrc_tvr(cx);
js::TypedArray *tsrc = NULL;
if (darray->getClass() == &js::TypedArray::fastClasses[js::TypedArray::TYPE_UINT8] ||
darray->getClass() == &js::TypedArray::fastClasses[js::TypedArray::TYPE_UINT8_CLAMPED])
{
tsrc = js::TypedArray::fromJSObject(darray);
} else if (JS_IsArrayObject(cx, darray) || js_IsTypedArray(darray)) {
// ugh, this isn't a uint8 typed array, someone made their own object; convert it to a typed array
JSObject *nobj = js_CreateTypedArrayWithArray(cx, js::TypedArray::TYPE_UINT8, darray);
if (!nobj)
return JS_FALSE;
*tsrc_tvr.addr() = OBJECT_TO_JSVAL(nobj);
tsrc = js::TypedArray::fromJSObject(nobj);
} else {
// yeah, no.
return xpc_qsThrow(cx, NS_ERROR_DOM_TYPE_MISMATCH_ERR);
}
// make the call
rv = self->PutImageData_explicit(x, y, w, h, (PRUint8*) tsrc->data, tsrc->byteLength);
if (NS_FAILED(rv))
return xpc_qsThrowMethodFailed(cx, rv, vp);
*vp = JSVAL_VOID;
return JS_TRUE;
}

Просмотреть файл

@ -3426,16 +3426,9 @@ nsCanvasRenderingContext2D::EnsureUnpremultiplyTable() {
} }
// ImageData getImageData (in float x, in float y, in float width, in float height);
NS_IMETHODIMP NS_IMETHODIMP
nsCanvasRenderingContext2D::GetImageData() nsCanvasRenderingContext2D::GetImageData()
{
/* Should never be called -- GetImageData_explicit is the QS entry point */
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsCanvasRenderingContext2D::GetImageData_explicit(PRInt32 x, PRInt32 y, PRUint32 w, PRUint32 h,
PRUint8 *aData, PRUint32 aDataLen)
{ {
if (!mValid) if (!mValid)
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
@ -3445,15 +3438,42 @@ nsCanvasRenderingContext2D::GetImageData_explicit(PRInt32 x, PRInt32 y, PRUint32
return NS_ERROR_DOM_SECURITY_ERR; return NS_ERROR_DOM_SECURITY_ERR;
} }
nsAXPCNativeCallContext *ncc = nsnull;
nsresult rv = nsContentUtils::XPConnect()->
GetCurrentNativeCallContext(&ncc);
NS_ENSURE_SUCCESS(rv, rv);
if (!ncc)
return NS_ERROR_FAILURE;
JSContext *ctx = nsnull;
rv = ncc->GetJSContext(&ctx);
NS_ENSURE_SUCCESS(rv, rv);
PRUint32 argc;
jsval *argv = nsnull;
ncc->GetArgc(&argc);
ncc->GetArgvPtr(&argv);
JSAutoRequest ar(ctx);
int32 x, y, w, h;
if (!JS_ConvertArguments (ctx, argc, argv, "jjjj", &x, &y, &w, &h))
return NS_ERROR_DOM_SYNTAX_ERR;
if (!CanvasUtils::CheckSaneSubrectSize (x, y, w, h, mWidth, mHeight)) if (!CanvasUtils::CheckSaneSubrectSize (x, y, w, h, mWidth, mHeight))
return NS_ERROR_DOM_SYNTAX_ERR; return NS_ERROR_DOM_SYNTAX_ERR;
PRUint32 len = w * h * 4; nsAutoArrayPtr<PRUint8> surfaceData (new (std::nothrow) PRUint8[w * h * 4]);
if (aDataLen != len) int surfaceDataStride = w*4;
return NS_ERROR_DOM_SYNTAX_ERR; int surfaceDataOffset = 0;
/* Copy the surface contents to the buffer */ if (!surfaceData)
nsRefPtr<gfxImageSurface> tmpsurf = new gfxImageSurface(aData, return NS_ERROR_OUT_OF_MEMORY;
nsRefPtr<gfxImageSurface> tmpsurf = new gfxImageSurface(surfaceData,
gfxIntSize(w, h), gfxIntSize(w, h),
w * 4, w * 4,
gfxASurface::ImageFormatARGB32); gfxASurface::ImageFormatARGB32);
@ -3469,39 +3489,99 @@ nsCanvasRenderingContext2D::GetImageData_explicit(PRInt32 x, PRInt32 y, PRUint32
tmpctx->SetSource(mSurface, gfxPoint(-(int)x, -(int)y)); tmpctx->SetSource(mSurface, gfxPoint(-(int)x, -(int)y));
tmpctx->Paint(); tmpctx->Paint();
// make sure sUnpremultiplyTable has been created tmpctx = nsnull;
tmpsurf = nsnull;
PRUint32 len = w * h * 4;
if (len > (((PRUint32)0xfff00000)/sizeof(jsval)))
return NS_ERROR_INVALID_ARG;
jsval *dest;
JSObject *dataArray = js_NewArrayObjectWithCapacity(ctx, len, &dest);
if (!dataArray)
return NS_ERROR_OUT_OF_MEMORY;
nsAutoGCRoot arrayGCRoot(&dataArray, &rv);
NS_ENSURE_SUCCESS(rv, rv);
EnsureUnpremultiplyTable(); EnsureUnpremultiplyTable();
// NOTE! dst is the same as src, and this relies on reading PRUint8 *row;
// from src and advancing that ptr before writing to dst.
PRUint8 *src = aData;
PRUint8 *dst = aData;
for (int j = 0; j < h; j++) { for (int j = 0; j < h; j++) {
row = surfaceData + surfaceDataOffset + (surfaceDataStride * j);
for (int i = 0; i < w; i++) { for (int i = 0; i < w; i++) {
// XXX Is there some useful swizzle MMX we can use here?
#ifdef IS_LITTLE_ENDIAN #ifdef IS_LITTLE_ENDIAN
PRUint8 b = *src++; PRUint8 b = *row++;
PRUint8 g = *src++; PRUint8 g = *row++;
PRUint8 r = *src++; PRUint8 r = *row++;
PRUint8 a = *src++; PRUint8 a = *row++;
#else #else
PRUint8 a = *src++; PRUint8 a = *row++;
PRUint8 r = *src++; PRUint8 r = *row++;
PRUint8 g = *src++; PRUint8 g = *row++;
PRUint8 b = *src++; PRUint8 b = *row++;
#endif #endif
// Convert to non-premultiplied color // Convert to non-premultiplied color
*dst++ = sUnpremultiplyTable[a][r];
*dst++ = sUnpremultiplyTable[a][g]; *dest++ = INT_TO_JSVAL(sUnpremultiplyTable[a][r]);
*dst++ = sUnpremultiplyTable[a][b]; *dest++ = INT_TO_JSVAL(sUnpremultiplyTable[a][g]);
*dst++ = a; *dest++ = INT_TO_JSVAL(sUnpremultiplyTable[a][b]);
*dest++ = INT_TO_JSVAL(a);
} }
} }
// Allocate result object after array, so if we have to trigger gc
// we do it now.
JSObject *result = JS_NewObject(ctx, NULL, NULL, NULL);
if (!result)
return NS_ERROR_OUT_OF_MEMORY;
nsAutoGCRoot resultGCRoot(&result, &rv);
NS_ENSURE_SUCCESS(rv, rv);
if (!JS_DefineProperty(ctx, result, "width", INT_TO_JSVAL(w), NULL, NULL, 0) ||
!JS_DefineProperty(ctx, result, "height", INT_TO_JSVAL(h), NULL, NULL, 0) ||
!JS_DefineProperty(ctx, result, "data", OBJECT_TO_JSVAL(dataArray), NULL, NULL, 0))
return NS_ERROR_FAILURE;
jsval *retvalPtr;
ncc->GetRetValPtr(&retvalPtr);
*retvalPtr = OBJECT_TO_JSVAL(result);
ncc->SetReturnValueWasSet(PR_TRUE);
return NS_OK; return NS_OK;
} }
static inline PRUint8 ToUint8(jsint aInput)
{
if (PRUint32(aInput) > 255)
return (aInput < 0) ? 0 : 255;
return PRUint8(aInput);
}
static inline PRUint8 ToUint8(double aInput)
{
if (!(aInput >= 0)) /* Not < so that NaN coerces to 0 */
return 0;
if (aInput > 255)
return 255;
double toTruncate = aInput + 0.5;
PRUint8 retval = PRUint8(toTruncate);
// now retval is rounded to nearest, ties rounded up. We want
// rounded to nearest ties to even, so check whether we had a tie.
if (retval == toTruncate) {
// It was a tie (since adding 0.5 gave us the exact integer we want).
// Since we rounded up, we either already have an even number or we
// have an odd number but the number we want is one less. So just
// unconditionally masking out the ones bit should do the trick to get
// us the value we want.
return (retval & ~1);
}
return retval;
}
void void
nsCanvasRenderingContext2D::EnsurePremultiplyTable() { nsCanvasRenderingContext2D::EnsurePremultiplyTable() {
if (sPremultiplyTable) if (sPremultiplyTable)
@ -3524,60 +3604,163 @@ nsCanvasRenderingContext2D::EnsurePremultiplyTable() {
// void putImageData (in ImageData d, in float x, in float y); // void putImageData (in ImageData d, in float x, in float y);
NS_IMETHODIMP NS_IMETHODIMP
nsCanvasRenderingContext2D::PutImageData() nsCanvasRenderingContext2D::PutImageData()
{
/* Should never be called -- PutImageData_explicit is the QS entry point */
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsCanvasRenderingContext2D::PutImageData_explicit(PRInt32 x, PRInt32 y, PRUint32 w, PRUint32 h,
unsigned char *aData, PRUint32 aDataLen)
{ {
nsresult rv; nsresult rv;
if (!mValid) if (!mValid)
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
nsAXPCNativeCallContext *ncc = nsnull;
rv = nsContentUtils::XPConnect()->
GetCurrentNativeCallContext(&ncc);
NS_ENSURE_SUCCESS(rv, rv);
if (!ncc)
return NS_ERROR_FAILURE;
JSContext *ctx = nsnull;
rv = ncc->GetJSContext(&ctx);
NS_ENSURE_SUCCESS(rv, rv);
PRUint32 argc;
jsval *argv = nsnull;
ncc->GetArgc(&argc);
ncc->GetArgvPtr(&argv);
JSAutoRequest ar(ctx);
JSObject *dataObject;
int32 x, y;
if (!JS_ConvertArguments (ctx, argc, argv, "ojj", &dataObject, &x, &y))
return NS_ERROR_DOM_SYNTAX_ERR;
if (!dataObject)
return NS_ERROR_DOM_SYNTAX_ERR;
int32 w, h;
JSObject *dataArray;
jsval v;
if (!JS_GetProperty(ctx, dataObject, "width", &v) ||
!JS_ValueToInt32(ctx, v, &w))
return NS_ERROR_DOM_SYNTAX_ERR;
if (!JS_GetProperty(ctx, dataObject, "height", &v) ||
!JS_ValueToInt32(ctx, v, &h))
return NS_ERROR_DOM_SYNTAX_ERR;
if (!JS_GetProperty(ctx, dataObject, "data", &v) ||
!JSVAL_IS_OBJECT(v))
return NS_ERROR_DOM_SYNTAX_ERR;
dataArray = JSVAL_TO_OBJECT(v);
if (!CanvasUtils::CheckSaneSubrectSize (x, y, w, h, mWidth, mHeight)) if (!CanvasUtils::CheckSaneSubrectSize (x, y, w, h, mWidth, mHeight))
return NS_ERROR_DOM_SYNTAX_ERR; return NS_ERROR_DOM_SYNTAX_ERR;
PRUint32 len = w * h * 4; jsuint arrayLen;
if (aDataLen != len) if (!JS_IsArrayObject(ctx, dataArray) ||
!JS_GetArrayLength(ctx, dataArray, &arrayLen) ||
arrayLen < (jsuint)(w * h * 4))
return NS_ERROR_DOM_SYNTAX_ERR; return NS_ERROR_DOM_SYNTAX_ERR;
nsRefPtr<gfxImageSurface> imgsurf = new gfxImageSurface(gfxIntSize(w, h), nsAutoArrayPtr<PRUint8> imageBuffer(new (std::nothrow) PRUint8[w * h * 4]);
if (!imageBuffer)
return NS_ERROR_OUT_OF_MEMORY;
PRUint8 *imgPtr = imageBuffer.get();
EnsurePremultiplyTable();
JSBool canFastPath =
js_CoerceArrayToCanvasImageData(dataArray, 0, w*h*4, imageBuffer);
// no fast path? go slow. We sadly need this for now, instead of just
// throwing, because dataArray might not be dense in case someone stuck
// their own array on the imageData.
// FIXME: it'd be awfully nice if we could prevent such modification of
// imageData objects, since it's likely the spec won't allow it anyway.
// Bug 497110 covers this.
if (!canFastPath) {
jsval vr, vg, vb, va;
PRUint8 ir, ig, ib, ia;
for (int32 j = 0; j < h; j++) {
int32 lineOffset = (j*w*4);
for (int32 i = 0; i < w; i++) {
int32 pixelOffset = lineOffset + i*4;
if (!JS_GetElement(ctx, dataArray, pixelOffset + 0, &vr) ||
!JS_GetElement(ctx, dataArray, pixelOffset + 1, &vg) ||
!JS_GetElement(ctx, dataArray, pixelOffset + 2, &vb) ||
!JS_GetElement(ctx, dataArray, pixelOffset + 3, &va))
return NS_ERROR_DOM_SYNTAX_ERR;
if (JSVAL_IS_INT(vr)) ir = ToUint8(JSVAL_TO_INT(vr));
else if (JSVAL_IS_DOUBLE(vr)) ir = ToUint8(*JSVAL_TO_DOUBLE(vr));
else return NS_ERROR_DOM_SYNTAX_ERR;
if (JSVAL_IS_INT(vg)) ig = ToUint8(JSVAL_TO_INT(vg));
else if (JSVAL_IS_DOUBLE(vg)) ig = ToUint8(*JSVAL_TO_DOUBLE(vg));
else return NS_ERROR_DOM_SYNTAX_ERR;
if (JSVAL_IS_INT(vb)) ib = ToUint8(JSVAL_TO_INT(vb));
else if (JSVAL_IS_DOUBLE(vb)) ib = ToUint8(*JSVAL_TO_DOUBLE(vb));
else return NS_ERROR_DOM_SYNTAX_ERR;
if (JSVAL_IS_INT(va)) ia = ToUint8(JSVAL_TO_INT(va));
else if (JSVAL_IS_DOUBLE(va)) ia = ToUint8(*JSVAL_TO_DOUBLE(va));
else return NS_ERROR_DOM_SYNTAX_ERR;
// Convert to premultiplied color (losslessly if the input came from getImageData)
ir = sPremultiplyTable[ia][ir];
ig = sPremultiplyTable[ia][ig];
ib = sPremultiplyTable[ia][ib];
#ifdef IS_LITTLE_ENDIAN
*imgPtr++ = ib;
*imgPtr++ = ig;
*imgPtr++ = ir;
*imgPtr++ = ia;
#else
*imgPtr++ = ia;
*imgPtr++ = ir;
*imgPtr++ = ig;
*imgPtr++ = ib;
#endif
}
}
} else {
/* Walk through and premultiply and swap rgba */
PRUint8 ir, ig, ib, ia;
PRUint8 *ptr = imgPtr;
for (int32 i = 0; i < w*h; i++) {
ir = ptr[0];
ig = ptr[1];
ib = ptr[2];
ia = ptr[3];
#ifdef IS_LITTLE_ENDIAN
ptr[0] = sPremultiplyTable[ia][ib];
ptr[1] = sPremultiplyTable[ia][ig];
ptr[2] = sPremultiplyTable[ia][ir];
#else
ptr[0] = ia;
ptr[1] = sPremultiplyTable[ia][ir];
ptr[2] = sPremultiplyTable[ia][ig];
ptr[3] = sPremultiplyTable[ia][ib];
#endif
ptr += 4;
}
}
nsRefPtr<gfxImageSurface> imgsurf = new gfxImageSurface(imageBuffer.get(),
gfxIntSize(w, h),
w * 4,
gfxASurface::ImageFormatARGB32); gfxASurface::ImageFormatARGB32);
if (!imgsurf || imgsurf->CairoStatus()) if (!imgsurf || imgsurf->CairoStatus())
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
// ensure premultiply table has been created
EnsurePremultiplyTable();
PRUint8 *src = aData;
PRUint8 *dst = imgsurf->Data();
for (int j = 0; j < h; j++) {
for (int i = 0; i < w; i++) {
PRUint8 r = *src++;
PRUint8 g = *src++;
PRUint8 b = *src++;
PRUint8 a = *src++;
// Convert to premultiplied color (losslessly if the input came from getImageData)
#ifdef IS_LITTLE_ENDIAN
*dst++ = sPremultiplyTable[a][b];
*dst++ = sPremultiplyTable[a][g];
*dst++ = sPremultiplyTable[a][r];
*dst++ = a;
#else
*dst++ = a;
*dst++ = sPremultiplyTable[a][r];
*dst++ = sPremultiplyTable[a][g];
*dst++ = sPremultiplyTable[a][b];
#endif
}
}
gfxContextPathAutoSaveRestore pathSR(mThebes); gfxContextPathAutoSaveRestore pathSR(mThebes);
gfxContextAutoSaveRestore autoSR(mThebes); gfxContextAutoSaveRestore autoSR(mThebes);
@ -3592,7 +3775,7 @@ nsCanvasRenderingContext2D::PutImageData_explicit(PRInt32 x, PRInt32 y, PRUint32
mThebes->SetOperator(gfxContext::OPERATOR_SOURCE); mThebes->SetOperator(gfxContext::OPERATOR_SOURCE);
mThebes->Fill(); mThebes->Fill();
return Redraw(gfxRect(x, y, w, h)); return Redraw();
} }
NS_IMETHODIMP NS_IMETHODIMP
@ -3612,8 +3795,79 @@ nsCanvasRenderingContext2D::GetThebesSurface(gfxASurface **surface)
NS_IMETHODIMP NS_IMETHODIMP
nsCanvasRenderingContext2D::CreateImageData() nsCanvasRenderingContext2D::CreateImageData()
{ {
/* Should never be called; handled entirely in the quickstub */ if (!mValid)
return NS_ERROR_NOT_IMPLEMENTED; return NS_ERROR_FAILURE;
nsAXPCNativeCallContext *ncc = nsnull;
nsresult rv = nsContentUtils::XPConnect()->
GetCurrentNativeCallContext(&ncc);
NS_ENSURE_SUCCESS(rv, rv);
if (!ncc)
return NS_ERROR_FAILURE;
JSContext *ctx = nsnull;
rv = ncc->GetJSContext(&ctx);
NS_ENSURE_SUCCESS(rv, rv);
PRUint32 argc;
jsval *argv = nsnull;
ncc->GetArgc(&argc);
ncc->GetArgvPtr(&argv);
JSAutoRequest ar(ctx);
int32 width, height;
if (!JS_ConvertArguments (ctx, argc, argv, "jj", &width, &height))
return NS_ERROR_DOM_SYNTAX_ERR;
if (width <= 0 || height <= 0)
return NS_ERROR_DOM_INDEX_SIZE_ERR;
PRUint32 w = (PRUint32) width;
PRUint32 h = (PRUint32) height;
// check for overflow when calculating len
PRUint32 len0 = w * h;
if (len0 / w != (PRUint32) h)
return NS_ERROR_DOM_INDEX_SIZE_ERR;
PRUint32 len = len0 * 4;
if (len / 4 != len0)
return NS_ERROR_DOM_INDEX_SIZE_ERR;
jsval *dest;
JSObject *dataArray = js_NewArrayObjectWithCapacity(ctx, len, &dest);
if (!dataArray)
return NS_ERROR_OUT_OF_MEMORY;
nsAutoGCRoot arrayGCRoot(&dataArray, &rv);
NS_ENSURE_SUCCESS(rv, rv);
for (PRUint32 i = 0; i < len; i++)
*dest++ = JSVAL_ZERO;
// Allocate result object after array, so if we have to trigger gc
// we do it now.
JSObject *result = JS_NewObject(ctx, NULL, NULL, NULL);
if (!result)
return NS_ERROR_OUT_OF_MEMORY;
nsAutoGCRoot resultGCRoot(&result, &rv);
NS_ENSURE_SUCCESS(rv, rv);
if (!JS_DefineProperty(ctx, result, "width", INT_TO_JSVAL(w), NULL, NULL, 0) ||
!JS_DefineProperty(ctx, result, "height", INT_TO_JSVAL(h), NULL, NULL, 0) ||
!JS_DefineProperty(ctx, result, "data", OBJECT_TO_JSVAL(dataArray), NULL, NULL, 0))
return NS_ERROR_FAILURE;
jsval *retvalPtr;
ncc->GetRetValPtr(&retvalPtr);
*retvalPtr = OBJECT_TO_JSVAL(result);
ncc->SetReturnValueWasSet(PR_TRUE);
return NS_OK;
} }
NS_IMETHODIMP NS_IMETHODIMP

Просмотреть файл

@ -182,22 +182,10 @@ enum CanvasMultiGetterType {
// void putImageData (in ImageData d, in float x, in float y); // void putImageData (in ImageData d, in float x, in float y);
// ImageData = { width: #, height: #, data: [r, g, b, a, ...] } // ImageData = { width: #, height: #, data: [r, g, b, a, ...] }
// These are just dummy functions; for JS, they are implemented as quickstubs
// that call the _explicit methods below. Native callers should use the _explit
// methods directly.
void getImageData(); void getImageData();
void putImageData(); void putImageData();
// dataLen must be == width*height*4 in both of these calls
[noscript] void getImageData_explicit(in long x, in long y, in unsigned long width, in unsigned long height,
[array, size_is(dataLen)] in octet dataPtr, in unsigned long dataLen);
[noscript] void putImageData_explicit(in long x, in long y, in unsigned long width, in unsigned long height,
[array, size_is(dataLen)] in octet dataPtr, in unsigned long dataLen);
// ImageData createImageData(in float w, in float h); // ImageData createImageData(in float w, in float h);
// Note: this is basically script-only (and really, quickstub-only). Native callers
// should just use the noscript 'explicit' get/put methods above, instead of using
// a separate ImageData object.
void createImageData(); void createImageData();
// image smoothing mode -- if disabled, images won't be smoothed // image smoothing mode -- if disabled, images won't be smoothed

Просмотреть файл

@ -12089,7 +12089,6 @@ TraceRecorder::setElem(int lval_spindex, int idx_spindex, int v_spindex)
case js::TypedArray::TYPE_UINT8_CLAMPED: case js::TypedArray::TYPE_UINT8_CLAMPED:
addr_ins = lir->ins2(LIR_piadd, data_ins, pidx_ins); addr_ins = lir->ins2(LIR_piadd, data_ins, pidx_ins);
lir->insStore(LIR_stb, lir->insCall(&js_TypedArray_uint8_clamp_double_ci, &v_ins), addr_ins, 0); lir->insStore(LIR_stb, lir->insCall(&js_TypedArray_uint8_clamp_double_ci, &v_ins), addr_ins, 0);
break;
default: default:
JS_NOT_REACHED("Unknown typed array type in tracer"); JS_NOT_REACHED("Unknown typed array type in tracer");
} }

Просмотреть файл

@ -520,18 +520,9 @@ class TypedArrayTemplate
jsuint index; jsuint index;
// We can't just chain to js_SetProperty, because we're not a normal object. // We can't just chain to js_SetProperty, because we're not a normal object.
if (!tarray->isArrayIndex(cx, id, &index)) { if (!tarray->isArrayIndex(cx, id, &index)) {
#if 0
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
JSMSG_TYPED_ARRAY_BAD_INDEX); JSMSG_TYPED_ARRAY_BAD_INDEX);
return false; return false;
#endif
// Silent ignore is better than an exception here, because
// at some point we may want to support other properties on
// these objects. This is especially true when these arrays
// are used to implement HTML Canvas 2D's PixelArray objects,
// which used to be plain old arrays.
*vp = JSVAL_VOID;
return true;
} }
if (JSVAL_IS_INT(*vp)) { if (JSVAL_IS_INT(*vp)) {

Просмотреть файл

@ -92,6 +92,11 @@ members = [
'nsIDOMTextMetrics.*', 'nsIDOMTextMetrics.*',
'nsIDOMCanvasGradient.*', 'nsIDOMCanvasGradient.*',
'nsIDOMCanvasPattern.*', 'nsIDOMCanvasPattern.*',
# NOTE: createImageDate(), getImageData(), and putImageData() use
# GetCurrentNativeCallContext
'-nsIDOMCanvasRenderingContext2D.createImageData',
'-nsIDOMCanvasRenderingContext2D.getImageData',
'-nsIDOMCanvasRenderingContext2D.putImageData',
# dom/interfaces/core # dom/interfaces/core
'nsIDOMCharacterData.data', 'nsIDOMCharacterData.data',
@ -620,10 +625,6 @@ customMethodCalls = {
'nsICanvasRenderingContextWebGL_VertexAttrib1fv': CUSTOM_QS, 'nsICanvasRenderingContextWebGL_VertexAttrib1fv': CUSTOM_QS,
'nsICanvasRenderingContextWebGL_VertexAttrib2fv': CUSTOM_QS, 'nsICanvasRenderingContextWebGL_VertexAttrib2fv': CUSTOM_QS,
'nsICanvasRenderingContextWebGL_VertexAttrib3fv': CUSTOM_QS, 'nsICanvasRenderingContextWebGL_VertexAttrib3fv': CUSTOM_QS,
'nsICanvasRenderingContextWebGL_VertexAttrib4fv': CUSTOM_QS, 'nsICanvasRenderingContextWebGL_VertexAttrib4fv': CUSTOM_QS
# Canvas 2D
'nsIDOMCanvasRenderingContext2D_CreateImageData': CUSTOM_QS,
'nsIDOMCanvasRenderingContext2D_GetImageData': CUSTOM_QS,
'nsIDOMCanvasRenderingContext2D_PutImageData': CUSTOM_QS,
} }