From 2354d9bb8c7d030ea85796541f0ff82d2207a611 Mon Sep 17 00:00:00 2001 From: Rod Vagg Date: Sun, 21 Jul 2013 17:14:57 +1000 Subject: [PATCH] 0.11.4+ compatibility using NAN See https://github.com/rvagg/nan --- src/Canvas.cc | 199 ++++----- src/Canvas.h | 20 +- src/CanvasGradient.cc | 41 +- src/CanvasGradient.h | 5 +- src/CanvasPattern.cc | 31 +- src/CanvasPattern.h | 3 +- src/CanvasRenderingContext2d.cc | 727 ++++++++++++++------------------ src/CanvasRenderingContext2d.h | 136 +++--- src/FontFace.cc | 32 +- src/FontFace.h | 2 +- src/Image.cc | 265 ++++++------ src/Image.h | 29 +- src/ImageData.cc | 50 +-- src/ImageData.h | 6 +- src/JPEGStream.h | 29 +- src/PixelArray.cc | 41 +- src/PixelArray.h | 4 +- src/closure.h | 4 +- src/nan.h | 344 +++++++++++++++ 19 files changed, 1069 insertions(+), 899 deletions(-) create mode 100644 src/nan.h diff --git a/src/Canvas.cc b/src/Canvas.cc index 1a9e6e7..63c6ad4 100644 --- a/src/Canvas.cc +++ b/src/Canvas.cc @@ -26,37 +26,33 @@ Persistent Canvas::constructor; void Canvas::Initialize(Handle target) { - HandleScope scope; + NanScope(); // Constructor - #if NODE_VERSION_AT_LEAST(0, 11, 3) - constructor = Persistent::New(Isolate::GetCurrent(), FunctionTemplate::New(Canvas::New)); - #else - constructor = Persistent::New(FunctionTemplate::New(Canvas::New)); - #endif - constructor->InstanceTemplate()->SetInternalFieldCount(1); - constructor->SetClassName(String::NewSymbol("Canvas")); + Local ctor = FunctionTemplate::New(Canvas::New); + NanAssignPersistent(FunctionTemplate, constructor, ctor); + ctor->InstanceTemplate()->SetInternalFieldCount(1); + ctor->SetClassName(NanSymbol("Canvas")); // Prototype - Local proto = constructor->PrototypeTemplate(); - NODE_SET_PROTOTYPE_METHOD(constructor, "toBuffer", ToBuffer); - NODE_SET_PROTOTYPE_METHOD(constructor, "streamPNGSync", StreamPNGSync); + Local proto = ctor->PrototypeTemplate(); + NODE_SET_PROTOTYPE_METHOD(ctor, "toBuffer", ToBuffer); + NODE_SET_PROTOTYPE_METHOD(ctor, "streamPNGSync", StreamPNGSync); #ifdef HAVE_JPEG - NODE_SET_PROTOTYPE_METHOD(constructor, "streamJPEGSync", StreamJPEGSync); + NODE_SET_PROTOTYPE_METHOD(ctor, "streamJPEGSync", StreamJPEGSync); #endif - proto->SetAccessor(String::NewSymbol("type"), GetType); - proto->SetAccessor(String::NewSymbol("width"), GetWidth, SetWidth); - proto->SetAccessor(String::NewSymbol("height"), GetHeight, SetHeight); - target->Set(String::NewSymbol("Canvas"), constructor->GetFunction()); + proto->SetAccessor(NanSymbol("type"), GetType); + proto->SetAccessor(NanSymbol("width"), GetWidth, SetWidth); + proto->SetAccessor(NanSymbol("height"), GetHeight, SetHeight); + target->Set(NanSymbol("Canvas"), ctor->GetFunction()); } /* * Initialize a Canvas with the given width and height. */ -Handle -Canvas::New(const Arguments &args) { - HandleScope scope; +NAN_METHOD(Canvas::New) { + NanScope(); int width = 0, height = 0; canvas_type_t type = CANVAS_TYPE_IMAGE; if (args[0]->IsNumber()) width = args[0]->Uint32Value(); @@ -66,41 +62,39 @@ Canvas::New(const Arguments &args) { : CANVAS_TYPE_IMAGE; Canvas *canvas = new Canvas(width, height, type); canvas->Wrap(args.This()); - return args.This(); + NanReturnValue(args.This()); } /* * Get type string. */ -Handle -Canvas::GetType(Local prop, const AccessorInfo &info) { - HandleScope scope; - Canvas *canvas = ObjectWrap::Unwrap(info.This()); - return scope.Close(String::New(canvas->isPDF() ? "pdf" : "image")); +NAN_GETTER(Canvas::GetType) { + NanScope(); + Canvas *canvas = ObjectWrap::Unwrap(args.This()); + NanReturnValue(String::New(canvas->isPDF() ? "pdf" : "image")); } /* * Get width. */ -Handle -Canvas::GetWidth(Local prop, const AccessorInfo &info) { - HandleScope scope; - Canvas *canvas = ObjectWrap::Unwrap(info.This()); - return scope.Close(Number::New(canvas->width)); +NAN_GETTER(Canvas::GetWidth) { + NanScope(); + Canvas *canvas = ObjectWrap::Unwrap(args.This()); + NanReturnValue(Number::New(canvas->width)); } /* * Set width. */ -void -Canvas::SetWidth(Local prop, Local val, const AccessorInfo &info) { - if (val->IsNumber()) { - Canvas *canvas = ObjectWrap::Unwrap(info.This()); - canvas->width = val->Uint32Value(); - canvas->resurface(info.This()); +NAN_SETTER(Canvas::SetWidth) { + NanScope(); + if (value->IsNumber()) { + Canvas *canvas = ObjectWrap::Unwrap(args.This()); + canvas->width = value->Uint32Value(); + canvas->resurface(args.This()); } } @@ -108,23 +102,22 @@ Canvas::SetWidth(Local prop, Local val, const AccessorInfo &info) * Get height. */ -Handle -Canvas::GetHeight(Local prop, const AccessorInfo &info) { - HandleScope scope; - Canvas *canvas = ObjectWrap::Unwrap(info.This()); - return scope.Close(Number::New(canvas->height)); +NAN_GETTER(Canvas::GetHeight) { + NanScope(); + Canvas *canvas = ObjectWrap::Unwrap(args.This()); + NanReturnValue(Number::New(canvas->height)); } /* * Set height. */ -void -Canvas::SetHeight(Local prop, Local val, const AccessorInfo &info) { - if (val->IsNumber()) { - Canvas *canvas = ObjectWrap::Unwrap(info.This()); - canvas->height = val->Uint32Value(); - canvas->resurface(info.This()); +NAN_SETTER(Canvas::SetHeight) { + NanScope(); + if (value->IsNumber()) { + Canvas *canvas = ObjectWrap::Unwrap(args.This()); + canvas->height = value->Uint32Value(); + canvas->resurface(args.This()); } } @@ -194,7 +187,7 @@ int Canvas::EIO_AfterToBuffer(eio_req *req) { #endif - HandleScope scope; + NanScope(); closure_t *closure = (closure_t *) req->data; #if NODE_VERSION_AT_LEAST(0, 6, 0) delete req; @@ -204,24 +197,16 @@ Canvas::EIO_AfterToBuffer(eio_req *req) { if (closure->status) { Local argv[1] = { Canvas::Error(closure->status) }; - closure->pfn->Call(Context::GetCurrent()->Global(), 1, argv); + closure->pfn->Call(1, argv); } else { - #if NODE_VERSION_AT_LEAST(0, 11, 3) - Local buf = Buffer::New(closure->len); - #else - Buffer *buf = Buffer::New(closure->len); - #endif + Local buf = NanNewBufferHandle((char*)closure->data, closure->len); memcpy(Buffer::Data(buf), closure->data, closure->len); - #if NODE_VERSION_AT_LEAST(0, 11, 3) - Local argv[2] = { Local::New(Null()), Local::New(buf) }; - #else - Local argv[2] = { Local::New(Null()), Local::New(buf->handle_) }; - #endif - closure->pfn->Call(Context::GetCurrent()->Global(), 2, argv); + Local argv[2] = { Local::New(Null()), buf }; + closure->pfn->Call(2, argv); } closure->canvas->Unref(); - closure->pfn.Dispose(); + delete closure->pfn; closure_destroy(closure); free(closure); @@ -235,9 +220,8 @@ Canvas::EIO_AfterToBuffer(eio_req *req) { * callback function is passed. */ -Handle -Canvas::ToBuffer(const Arguments &args) { - HandleScope scope; +NAN_METHOD(Canvas::ToBuffer) { + NanScope(); cairo_status_t status; Canvas *canvas = ObjectWrap::Unwrap(args.This()); @@ -246,19 +230,8 @@ Canvas::ToBuffer(const Arguments &args) { cairo_surface_finish(canvas->surface()); closure_t *closure = (closure_t *) canvas->closure(); - #if NODE_VERSION_AT_LEAST(0, 11, 3) - Local buf = Buffer::New(closure->len); - #else - Buffer *buf = Buffer::New(closure->len); - #endif - - memcpy(Buffer::Data(buf), closure->data, closure->len); - - #if NODE_VERSION_AT_LEAST(0, 11, 3) - return buf; - #else - return buf->handle_; - #endif + Local buf = NanNewBufferHandle((char*) closure->data, closure->len); + NanReturnValue(buf); } // Async @@ -270,16 +243,12 @@ Canvas::ToBuffer(const Arguments &args) { if (status) { closure_destroy(closure); free(closure); - return Canvas::Error(status); + return NanThrowError(Canvas::Error(status)); } // TODO: only one callback fn in closure canvas->Ref(); - #if NODE_VERSION_AT_LEAST(0, 11, 3) - closure->pfn = Persistent::New(Isolate::GetCurrent(), Handle::Cast(args[0])); - #else - closure->pfn = Persistent::New(Handle::Cast(args[0])); - #endif + closure->pfn = new NanCallback(args[0].As()); #if NODE_VERSION_AT_LEAST(0, 6, 0) uv_work_t* req = new uv_work_t; @@ -290,7 +259,7 @@ Canvas::ToBuffer(const Arguments &args) { ev_ref(EV_DEFAULT_UC); #endif - return Undefined(); + NanReturnUndefined(); // Sync } else { closure_t closure; @@ -299,7 +268,7 @@ Canvas::ToBuffer(const Arguments &args) { // ensure closure is ok if (status) { closure_destroy(&closure); - return Canvas::Error(status); + return NanThrowError(Canvas::Error(status)); } TryCatch try_catch; @@ -307,23 +276,14 @@ Canvas::ToBuffer(const Arguments &args) { if (try_catch.HasCaught()) { closure_destroy(&closure); - return try_catch.ReThrow(); + NanReturnValue(try_catch.ReThrow()); } else if (status) { closure_destroy(&closure); - return ThrowException(Canvas::Error(status)); + return NanThrowError(Canvas::Error(status)); } else { - #if NODE_VERSION_AT_LEAST(0, 11, 3) - Local buf = Buffer::New(closure.len); - #else - Buffer *buf = Buffer::New(closure.len); - #endif - memcpy(Buffer::Data(buf), closure.data, closure.len); + Local buf = NanNewBufferHandle((char *)closure.data, closure.len); closure_destroy(&closure); - #if NODE_VERSION_AT_LEAST(0, 11, 3) - return buf; - #else - return buf->handle_; - #endif + NanReturnValue(buf); } } } @@ -334,22 +294,12 @@ Canvas::ToBuffer(const Arguments &args) { static cairo_status_t streamPNG(void *c, const uint8_t *data, unsigned len) { - HandleScope scope; + NanScope(); closure_t *closure = (closure_t *) c; - #if NODE_VERSION_AT_LEAST(0, 11, 3) - Local buf = Buffer::New(len); - memcpy(Buffer::Data(buf), data, len); - #else - Local buf = Buffer::New(len); - memcpy(Buffer::Data(buf->handle_), data, len); - #endif + Local buf = NanNewBufferHandle((char *)data, len); Local argv[3] = { Local::New(Null()) - #if NODE_VERSION_AT_LEAST(0, 11, 3) - , Local::New(buf) - #else - , Local::New(buf->handle_) - #endif + , buf , Integer::New(len) }; closure->fn->Call(Context::GetCurrent()->Global(), 3, argv); return CAIRO_STATUS_SUCCESS; @@ -359,12 +309,11 @@ streamPNG(void *c, const uint8_t *data, unsigned len) { * Stream PNG data synchronously. */ -Handle -Canvas::StreamPNGSync(const Arguments &args) { - HandleScope scope; +NAN_METHOD(Canvas::StreamPNGSync) { + NanScope(); // TODO: async as well if (!args[0]->IsFunction()) - return ThrowException(Exception::TypeError(String::New("callback function required"))); + return NanThrowTypeError("callback function required"); Canvas *canvas = ObjectWrap::Unwrap(args.This()); closure_t closure; @@ -374,7 +323,7 @@ Canvas::StreamPNGSync(const Arguments &args) { cairo_status_t status = cairo_surface_write_to_png_stream(canvas->surface(), streamPNG, &closure); if (try_catch.HasCaught()) { - return try_catch.ReThrow(); + NanReturnValue(try_catch.ReThrow()); } else if (status) { Local argv[1] = { Canvas::Error(status) }; closure.fn->Call(Context::GetCurrent()->Global(), 1, argv); @@ -385,7 +334,7 @@ Canvas::StreamPNGSync(const Arguments &args) { , Integer::New(0) }; closure.fn->Call(Context::GetCurrent()->Global(), 3, argv); } - return Undefined(); + NanReturnUndefined(); } /* @@ -394,16 +343,15 @@ Canvas::StreamPNGSync(const Arguments &args) { #ifdef HAVE_JPEG -Handle -Canvas::StreamJPEGSync(const Arguments &args) { - HandleScope scope; +NAN_METHOD(Canvas::StreamJPEGSync) { + NanScope(); // TODO: async as well if (!args[0]->IsNumber()) - return ThrowException(Exception::TypeError(String::New("buffer size required"))); + return NanThrowTypeError("buffer size required"); if (!args[1]->IsNumber()) - return ThrowException(Exception::TypeError(String::New("quality setting required"))); + return NanThrowTypeError("quality setting required"); if (!args[2]->IsFunction()) - return ThrowException(Exception::TypeError(String::New("callback function required"))); + return NanThrowTypeError("callback function required"); Canvas *canvas = ObjectWrap::Unwrap(args.This()); closure_t closure; @@ -412,8 +360,9 @@ Canvas::StreamJPEGSync(const Arguments &args) { TryCatch try_catch; write_to_jpeg_stream(canvas->surface(), args[0]->NumberValue(), args[1]->NumberValue(), &closure); - if (try_catch.HasCaught()) return try_catch.ReThrow(); - return Undefined(); + if (try_catch.HasCaught()) + NanReturnValue(try_catch.ReThrow()); + NanReturnUndefined(); } #endif diff --git a/src/Canvas.h b/src/Canvas.h index 66895fb..912d2e2 100644 --- a/src/Canvas.h +++ b/src/Canvas.h @@ -19,6 +19,8 @@ #include #endif +#include "nan.h" + using namespace v8; using namespace node; @@ -51,15 +53,15 @@ class Canvas: public node::ObjectWrap { canvas_type_t type; static Persistent constructor; static void Initialize(Handle target); - static Handle New(const Arguments &args); - static Handle ToBuffer(const Arguments &args); - static Handle GetType(Local prop, const AccessorInfo &info); - static Handle GetWidth(Local prop, const AccessorInfo &info); - static Handle GetHeight(Local prop, const AccessorInfo &info); - static void SetWidth(Local prop, Local val, const AccessorInfo &info); - static void SetHeight(Local prop, Local val, const AccessorInfo &info); - static Handle StreamPNGSync(const Arguments &args); - static Handle StreamJPEGSync(const Arguments &args); + static NAN_METHOD(New); + static NAN_METHOD(ToBuffer); + static NAN_GETTER(GetType); + static NAN_GETTER(GetWidth); + static NAN_GETTER(GetHeight); + static NAN_SETTER(SetWidth); + static NAN_SETTER(SetHeight); + static NAN_METHOD(StreamPNGSync); + static NAN_METHOD(StreamJPEGSync); static Local Error(cairo_status_t status); #if NODE_VERSION_AT_LEAST(0, 6, 0) static void ToBufferAsync(uv_work_t *req); diff --git a/src/CanvasGradient.cc b/src/CanvasGradient.cc index dbb7ad6..802224e 100644 --- a/src/CanvasGradient.cc +++ b/src/CanvasGradient.cc @@ -17,29 +17,25 @@ Persistent Gradient::constructor; void Gradient::Initialize(Handle target) { - HandleScope scope; + NanScope(); // Constructor - #if NODE_VERSION_AT_LEAST(0, 11, 3) - constructor = Persistent::New(Isolate::GetCurrent(), FunctionTemplate::New(Gradient::New)); - #else - constructor = Persistent::New(FunctionTemplate::New(Gradient::New)); - #endif - constructor->InstanceTemplate()->SetInternalFieldCount(1); - constructor->SetClassName(String::NewSymbol("CanvasGradient")); + Local ctor = FunctionTemplate::New(Gradient::New); + NanAssignPersistent(FunctionTemplate, constructor, ctor); + ctor->InstanceTemplate()->SetInternalFieldCount(1); + ctor->SetClassName(NanSymbol("CanvasGradient")); // Prototype - NODE_SET_PROTOTYPE_METHOD(constructor, "addColorStop", AddColorStop); - target->Set(String::NewSymbol("CanvasGradient"), constructor->GetFunction()); + NODE_SET_PROTOTYPE_METHOD(ctor, "addColorStop", AddColorStop); + target->Set(NanSymbol("CanvasGradient"), ctor->GetFunction()); } /* * Initialize a new CanvasGradient. */ -Handle -Gradient::New(const Arguments &args) { - HandleScope scope; +NAN_METHOD(Gradient::New) { + NanScope(); // Linear if (4 == args.Length()) { @@ -49,7 +45,7 @@ Gradient::New(const Arguments &args) { , args[2]->NumberValue() , args[3]->NumberValue()); grad->Wrap(args.This()); - return args.This(); + NanReturnValue(args.This()); } // Radial @@ -62,23 +58,22 @@ Gradient::New(const Arguments &args) { , args[4]->NumberValue() , args[5]->NumberValue()); grad->Wrap(args.This()); - return args.This(); + NanReturnValue(args.This()); } - return ThrowException(Exception::TypeError(String::New("invalid arguments"))); + return NanThrowTypeError("invalid arguments"); } /* * Add color stop. */ -Handle -Gradient::AddColorStop(const Arguments &args) { - HandleScope scope; +NAN_METHOD(Gradient::AddColorStop) { + NanScope(); if (!args[0]->IsNumber()) - return ThrowException(Exception::TypeError(String::New("offset required"))); + return NanThrowTypeError("offset required"); if (!args[1]->IsString()) - return ThrowException(Exception::TypeError(String::New("color string required"))); + return NanThrowTypeError("color string required"); Gradient *grad = ObjectWrap::Unwrap(args.This()); short ok; @@ -95,10 +90,10 @@ Gradient::AddColorStop(const Arguments &args) { , color.b , color.a); } else { - return ThrowException(Exception::TypeError(String::New("parse color failed"))); + return NanThrowTypeError("parse color failed"); } - return Undefined(); + NanReturnUndefined(); } /* diff --git a/src/CanvasGradient.h b/src/CanvasGradient.h index 79791f2..69808e5 100644 --- a/src/CanvasGradient.h +++ b/src/CanvasGradient.h @@ -8,14 +8,15 @@ #ifndef __NODE_GRADIENT_H__ #define __NODE_GRADIENT_H__ +#include "nan.h" #include "Canvas.h" class Gradient: public node::ObjectWrap { public: static Persistent constructor; static void Initialize(Handle target); - static Handle New(const Arguments &args); - static Handle AddColorStop(const Arguments &args); + static NAN_METHOD(New); + static NAN_METHOD(AddColorStop); Gradient(double x0, double y0, double x1, double y1); Gradient(double x0, double y0, double r0, double x1, double y1, double r1); inline cairo_pattern_t *pattern(){ return _pattern; } diff --git a/src/CanvasPattern.cc b/src/CanvasPattern.cc index 77f8cc3..1a42557 100644 --- a/src/CanvasPattern.cc +++ b/src/CanvasPattern.cc @@ -20,25 +20,24 @@ Pattern::Initialize(Handle target) { HandleScope scope; // Constructor - #if NODE_VERSION_AT_LEAST(0, 11, 3) - constructor = Persistent::New(Isolate::GetCurrent(), FunctionTemplate::New(Pattern::New)); - #else - constructor = Persistent::New(FunctionTemplate::New(Pattern::New)); - #endif - constructor->InstanceTemplate()->SetInternalFieldCount(1); - constructor->SetClassName(String::NewSymbol("CanvasPattern")); + Local ctor = FunctionTemplate::New(Pattern::New); + NanAssignPersistent(FunctionTemplate, constructor, ctor); + ctor->InstanceTemplate()->SetInternalFieldCount(1); + ctor->SetClassName(NanSymbol("CanvasPattern")); + + ctor->InstanceTemplate()->SetInternalFieldCount(1); + ctor->SetClassName(NanSymbol("CanvasPattern")); // Prototype - target->Set(String::NewSymbol("CanvasPattern"), constructor->GetFunction()); + target->Set(NanSymbol("CanvasPattern"), ctor->GetFunction()); } /* * Initialize a new CanvasPattern. */ -Handle -Pattern::New(const Arguments &args) { - HandleScope scope; +NAN_METHOD(Pattern::New) { + NanScope(); int w = 0 , h = 0; @@ -47,17 +46,17 @@ Pattern::New(const Arguments &args) { Local obj = args[0]->ToObject(); // Image - if (Image::constructor->HasInstance(obj)) { + if (NanHasInstance(Image::constructor, obj)) { Image *img = ObjectWrap::Unwrap(obj); if (!img->isComplete()) { - return ThrowException(Exception::Error(String::New("Image given has not completed loading"))); + return NanThrowError("Image given has not completed loading"); } w = img->width; h = img->height; surface = img->surface(); // Canvas - } else if (Canvas::constructor->HasInstance(obj)) { + } else if (NanHasInstance(Canvas::constructor, obj)) { Canvas *canvas = ObjectWrap::Unwrap(obj); w = canvas->width; h = canvas->height; @@ -65,12 +64,12 @@ Pattern::New(const Arguments &args) { // Invalid } else { - return ThrowException(Exception::TypeError(String::New("Image or Canvas expected"))); + return NanThrowTypeError("Image or Canvas expected"); } Pattern *pattern = new Pattern(surface,w,h); pattern->Wrap(args.This()); - return args.This(); + NanReturnValue(args.This()); } diff --git a/src/CanvasPattern.h b/src/CanvasPattern.h index 7020d69..2cc3ecc 100644 --- a/src/CanvasPattern.h +++ b/src/CanvasPattern.h @@ -8,13 +8,14 @@ #ifndef __NODE_PATTERN_H__ #define __NODE_PATTERN_H__ +#include "nan.h" #include "Canvas.h" class Pattern: public node::ObjectWrap { public: static Persistent constructor; static void Initialize(Handle target); - static Handle New(const Arguments &args); + static NAN_METHOD(New); Pattern(cairo_surface_t *surface, int w, int h); inline cairo_pattern_t *pattern(){ return _pattern; } diff --git a/src/CanvasRenderingContext2d.cc b/src/CanvasRenderingContext2d.cc index 7f9016d..a6c1621 100644 --- a/src/CanvasRenderingContext2d.cc +++ b/src/CanvasRenderingContext2d.cc @@ -30,7 +30,7 @@ Persistent Context2d::constructor; if (!args[0]->IsNumber() \ ||!args[1]->IsNumber() \ ||!args[2]->IsNumber() \ - ||!args[3]->IsNumber()) return Undefined(); \ + ||!args[3]->IsNumber()) NanReturnUndefined(); \ double x = args[0]->NumberValue(); \ double y = args[1]->NumberValue(); \ double width = args[2]->NumberValue(); \ @@ -78,75 +78,72 @@ void state_assign_fontFamily(canvas_state_t *state, const char *str) { void Context2d::Initialize(Handle target) { - HandleScope scope; + NanScope(); // Constructor - #if NODE_VERSION_AT_LEAST(0, 11, 3) - constructor = Persistent::New(Isolate::GetCurrent(), FunctionTemplate::New(Context2d::New)); - #else - constructor = Persistent::New(FunctionTemplate::New(Context2d::New)); - #endif - constructor->InstanceTemplate()->SetInternalFieldCount(1); - constructor->SetClassName(String::NewSymbol("CanvasRenderingContext2d")); + Local ctor = FunctionTemplate::New(Context2d::New); + NanAssignPersistent(FunctionTemplate, constructor, ctor); + ctor->InstanceTemplate()->SetInternalFieldCount(1); + ctor->SetClassName(NanSymbol("CanvasRenderingContext2d")); // Prototype - Local proto = constructor->PrototypeTemplate(); - NODE_SET_PROTOTYPE_METHOD(constructor, "drawImage", DrawImage); - NODE_SET_PROTOTYPE_METHOD(constructor, "putImageData", PutImageData); - NODE_SET_PROTOTYPE_METHOD(constructor, "addPage", AddPage); - NODE_SET_PROTOTYPE_METHOD(constructor, "save", Save); - NODE_SET_PROTOTYPE_METHOD(constructor, "restore", Restore); - NODE_SET_PROTOTYPE_METHOD(constructor, "rotate", Rotate); - NODE_SET_PROTOTYPE_METHOD(constructor, "translate", Translate); - NODE_SET_PROTOTYPE_METHOD(constructor, "transform", Transform); - NODE_SET_PROTOTYPE_METHOD(constructor, "resetTransform", ResetTransform); - NODE_SET_PROTOTYPE_METHOD(constructor, "isPointInPath", IsPointInPath); - NODE_SET_PROTOTYPE_METHOD(constructor, "scale", Scale); - NODE_SET_PROTOTYPE_METHOD(constructor, "clip", Clip); - NODE_SET_PROTOTYPE_METHOD(constructor, "fill", Fill); - NODE_SET_PROTOTYPE_METHOD(constructor, "stroke", Stroke); - NODE_SET_PROTOTYPE_METHOD(constructor, "fillText", FillText); - NODE_SET_PROTOTYPE_METHOD(constructor, "strokeText", StrokeText); - NODE_SET_PROTOTYPE_METHOD(constructor, "fillRect", FillRect); - NODE_SET_PROTOTYPE_METHOD(constructor, "strokeRect", StrokeRect); - NODE_SET_PROTOTYPE_METHOD(constructor, "clearRect", ClearRect); - NODE_SET_PROTOTYPE_METHOD(constructor, "rect", Rect); - NODE_SET_PROTOTYPE_METHOD(constructor, "measureText", MeasureText); - NODE_SET_PROTOTYPE_METHOD(constructor, "moveTo", MoveTo); - NODE_SET_PROTOTYPE_METHOD(constructor, "lineTo", LineTo); - NODE_SET_PROTOTYPE_METHOD(constructor, "bezierCurveTo", BezierCurveTo); - NODE_SET_PROTOTYPE_METHOD(constructor, "quadraticCurveTo", QuadraticCurveTo); - NODE_SET_PROTOTYPE_METHOD(constructor, "beginPath", BeginPath); - NODE_SET_PROTOTYPE_METHOD(constructor, "closePath", ClosePath); - NODE_SET_PROTOTYPE_METHOD(constructor, "arc", Arc); - NODE_SET_PROTOTYPE_METHOD(constructor, "arcTo", ArcTo); - NODE_SET_PROTOTYPE_METHOD(constructor, "_setFont", SetFont); + Local proto = ctor->PrototypeTemplate(); + NODE_SET_PROTOTYPE_METHOD(ctor, "drawImage", DrawImage); + NODE_SET_PROTOTYPE_METHOD(ctor, "putImageData", PutImageData); + NODE_SET_PROTOTYPE_METHOD(ctor, "addPage", AddPage); + NODE_SET_PROTOTYPE_METHOD(ctor, "save", Save); + NODE_SET_PROTOTYPE_METHOD(ctor, "restore", Restore); + NODE_SET_PROTOTYPE_METHOD(ctor, "rotate", Rotate); + NODE_SET_PROTOTYPE_METHOD(ctor, "translate", Translate); + NODE_SET_PROTOTYPE_METHOD(ctor, "transform", Transform); + NODE_SET_PROTOTYPE_METHOD(ctor, "resetTransform", ResetTransform); + NODE_SET_PROTOTYPE_METHOD(ctor, "isPointInPath", IsPointInPath); + NODE_SET_PROTOTYPE_METHOD(ctor, "scale", Scale); + NODE_SET_PROTOTYPE_METHOD(ctor, "clip", Clip); + NODE_SET_PROTOTYPE_METHOD(ctor, "fill", Fill); + NODE_SET_PROTOTYPE_METHOD(ctor, "stroke", Stroke); + NODE_SET_PROTOTYPE_METHOD(ctor, "fillText", FillText); + NODE_SET_PROTOTYPE_METHOD(ctor, "strokeText", StrokeText); + NODE_SET_PROTOTYPE_METHOD(ctor, "fillRect", FillRect); + NODE_SET_PROTOTYPE_METHOD(ctor, "strokeRect", StrokeRect); + NODE_SET_PROTOTYPE_METHOD(ctor, "clearRect", ClearRect); + NODE_SET_PROTOTYPE_METHOD(ctor, "rect", Rect); + NODE_SET_PROTOTYPE_METHOD(ctor, "measureText", MeasureText); + NODE_SET_PROTOTYPE_METHOD(ctor, "moveTo", MoveTo); + NODE_SET_PROTOTYPE_METHOD(ctor, "lineTo", LineTo); + NODE_SET_PROTOTYPE_METHOD(ctor, "bezierCurveTo", BezierCurveTo); + NODE_SET_PROTOTYPE_METHOD(ctor, "quadraticCurveTo", QuadraticCurveTo); + NODE_SET_PROTOTYPE_METHOD(ctor, "beginPath", BeginPath); + NODE_SET_PROTOTYPE_METHOD(ctor, "closePath", ClosePath); + NODE_SET_PROTOTYPE_METHOD(ctor, "arc", Arc); + NODE_SET_PROTOTYPE_METHOD(ctor, "arcTo", ArcTo); + NODE_SET_PROTOTYPE_METHOD(ctor, "_setFont", SetFont); #ifdef HAVE_FREETYPE - NODE_SET_PROTOTYPE_METHOD(constructor, "_setFontFace", SetFontFace); + NODE_SET_PROTOTYPE_METHOD(ctor, "_setFontFace", SetFontFace); #endif - NODE_SET_PROTOTYPE_METHOD(constructor, "_setFillColor", SetFillColor); - NODE_SET_PROTOTYPE_METHOD(constructor, "_setStrokeColor", SetStrokeColor); - NODE_SET_PROTOTYPE_METHOD(constructor, "_setFillPattern", SetFillPattern); - NODE_SET_PROTOTYPE_METHOD(constructor, "_setStrokePattern", SetStrokePattern); - NODE_SET_PROTOTYPE_METHOD(constructor, "_setTextBaseline", SetTextBaseline); - NODE_SET_PROTOTYPE_METHOD(constructor, "_setTextAlignment", SetTextAlignment); - proto->SetAccessor(String::NewSymbol("patternQuality"), GetPatternQuality, SetPatternQuality); - proto->SetAccessor(String::NewSymbol("globalCompositeOperation"), GetGlobalCompositeOperation, SetGlobalCompositeOperation); - proto->SetAccessor(String::NewSymbol("globalAlpha"), GetGlobalAlpha, SetGlobalAlpha); - proto->SetAccessor(String::NewSymbol("shadowColor"), GetShadowColor, SetShadowColor); - proto->SetAccessor(String::NewSymbol("fillColor"), GetFillColor); - proto->SetAccessor(String::NewSymbol("strokeColor"), GetStrokeColor); - proto->SetAccessor(String::NewSymbol("miterLimit"), GetMiterLimit, SetMiterLimit); - proto->SetAccessor(String::NewSymbol("lineWidth"), GetLineWidth, SetLineWidth); - proto->SetAccessor(String::NewSymbol("lineCap"), GetLineCap, SetLineCap); - proto->SetAccessor(String::NewSymbol("lineJoin"), GetLineJoin, SetLineJoin); - proto->SetAccessor(String::NewSymbol("shadowOffsetX"), GetShadowOffsetX, SetShadowOffsetX); - proto->SetAccessor(String::NewSymbol("shadowOffsetY"), GetShadowOffsetY, SetShadowOffsetY); - proto->SetAccessor(String::NewSymbol("shadowBlur"), GetShadowBlur, SetShadowBlur); - proto->SetAccessor(String::NewSymbol("antialias"), GetAntiAlias, SetAntiAlias); - proto->SetAccessor(String::NewSymbol("textDrawingMode"), GetTextDrawingMode, SetTextDrawingMode); - proto->SetAccessor(String::NewSymbol("filter"), GetFilter, SetFilter); - target->Set(String::NewSymbol("CanvasRenderingContext2d"), constructor->GetFunction()); + NODE_SET_PROTOTYPE_METHOD(ctor, "_setFillColor", SetFillColor); + NODE_SET_PROTOTYPE_METHOD(ctor, "_setStrokeColor", SetStrokeColor); + NODE_SET_PROTOTYPE_METHOD(ctor, "_setFillPattern", SetFillPattern); + NODE_SET_PROTOTYPE_METHOD(ctor, "_setStrokePattern", SetStrokePattern); + NODE_SET_PROTOTYPE_METHOD(ctor, "_setTextBaseline", SetTextBaseline); + NODE_SET_PROTOTYPE_METHOD(ctor, "_setTextAlignment", SetTextAlignment); + proto->SetAccessor(NanSymbol("patternQuality"), GetPatternQuality, SetPatternQuality); + proto->SetAccessor(NanSymbol("globalCompositeOperation"), GetGlobalCompositeOperation, SetGlobalCompositeOperation); + proto->SetAccessor(NanSymbol("globalAlpha"), GetGlobalAlpha, SetGlobalAlpha); + proto->SetAccessor(NanSymbol("shadowColor"), GetShadowColor, SetShadowColor); + proto->SetAccessor(NanSymbol("fillColor"), GetFillColor); + proto->SetAccessor(NanSymbol("strokeColor"), GetStrokeColor); + proto->SetAccessor(NanSymbol("miterLimit"), GetMiterLimit, SetMiterLimit); + proto->SetAccessor(NanSymbol("lineWidth"), GetLineWidth, SetLineWidth); + proto->SetAccessor(NanSymbol("lineCap"), GetLineCap, SetLineCap); + proto->SetAccessor(NanSymbol("lineJoin"), GetLineJoin, SetLineJoin); + proto->SetAccessor(NanSymbol("shadowOffsetX"), GetShadowOffsetX, SetShadowOffsetX); + proto->SetAccessor(NanSymbol("shadowOffsetY"), GetShadowOffsetY, SetShadowOffsetY); + proto->SetAccessor(NanSymbol("shadowBlur"), GetShadowBlur, SetShadowBlur); + proto->SetAccessor(NanSymbol("antialias"), GetAntiAlias, SetAntiAlias); + proto->SetAccessor(NanSymbol("textDrawingMode"), GetTextDrawingMode, SetTextDrawingMode); + proto->SetAccessor(NanSymbol("filter"), GetFilter, SetFilter); + target->Set(NanSymbol("CanvasRenderingContext2d"), ctor->GetFunction()); } /* @@ -464,31 +461,29 @@ Context2d::blur(cairo_surface_t *surface, int radius) { * Initialize a new Context2d with the given canvas. */ -Handle -Context2d::New(const Arguments &args) { - HandleScope scope; +NAN_METHOD(Context2d::New) { + NanScope(); Local obj = args[0]->ToObject(); - if (!Canvas::constructor->HasInstance(obj)) - return ThrowException(Exception::TypeError(String::New("Canvas expected"))); + if (!NanHasInstance(Canvas::constructor, obj)) + return NanThrowTypeError("Canvas expected"); Canvas *canvas = ObjectWrap::Unwrap(obj); Context2d *context = new Context2d(canvas); context->Wrap(args.This()); - return args.This(); + NanReturnValue(args.This()); } /* * Create a new page. */ -Handle -Context2d::AddPage(const Arguments &args) { - HandleScope scope; +NAN_METHOD(Context2d::AddPage) { + NanScope(); Context2d *context = ObjectWrap::Unwrap(args.This()); if (!context->canvas()->isPDF()) { - return ThrowException(Exception::Error(String::New("only PDF canvases support .nextPage()"))); + return NanThrowError("only PDF canvases support .nextPage()"); } cairo_show_page(context->context()); - return Undefined(); + NanReturnUndefined(); } /* @@ -499,13 +494,12 @@ Context2d::AddPage(const Arguments &args) { * */ -Handle -Context2d::PutImageData(const Arguments &args) { - HandleScope scope; +NAN_METHOD(Context2d::PutImageData) { + NanScope(); Local obj = args[0]->ToObject(); - if (!ImageData::constructor->HasInstance(obj)) - return ThrowException(Exception::TypeError(String::New("ImageData expected"))); + if (!NanHasInstance(ImageData::constructor, obj)) + return NanThrowTypeError("ImageData expected"); Context2d *context = ObjectWrap::Unwrap(args.This()); ImageData *imageData = ObjectWrap::Unwrap(obj); @@ -542,14 +536,14 @@ Context2d::PutImageData(const Arguments &args) { if (sy < 0) sh += sy, sy = 0; if (sx + sw > arr->width()) sw = arr->width() - sx; if (sy + sh > arr->height()) sh = arr->height() - sy; - if (sw <= 0 || sh <= 0) return Undefined(); + if (sw <= 0 || sh <= 0) NanReturnUndefined(); cols = sw; rows = sh; dx += sx; dy += sy; break; default: - return ThrowException(Exception::Error(String::New("invalid arguments"))); + return NanThrowError("invalid arguments"); } uint8_t *srcRows = src + sy * srcStride + sx * 4; @@ -582,7 +576,7 @@ Context2d::PutImageData(const Arguments &args) { , cols , rows); - return Undefined(); + NanReturnUndefined(); } /* @@ -594,12 +588,11 @@ Context2d::PutImageData(const Arguments &args) { * */ -Handle -Context2d::DrawImage(const Arguments &args) { - HandleScope scope; +NAN_METHOD(Context2d::DrawImage) { + NanScope(); if (args.Length() < 3) - return ThrowException(Exception::TypeError(String::New("invalid arguments"))); + return NanThrowTypeError("invalid arguments"); int sx = 0 , sy = 0 @@ -612,17 +605,17 @@ Context2d::DrawImage(const Arguments &args) { Local obj = args[0]->ToObject(); // Image - if (Image::constructor->HasInstance(obj)) { + if (NanHasInstance(Image::constructor, obj)) { Image *img = ObjectWrap::Unwrap(obj); if (!img->isComplete()) { - return ThrowException(Exception::Error(String::New("Image given has not completed loading"))); + return NanThrowError("Image given has not completed loading"); } sw = img->width; sh = img->height; surface = img->surface(); // Canvas - } else if (Canvas::constructor->HasInstance(obj)) { + } else if (NanHasInstance(Canvas::constructor, obj)) { Canvas *canvas = ObjectWrap::Unwrap(obj); sw = canvas->width; sh = canvas->height; @@ -630,7 +623,7 @@ Context2d::DrawImage(const Arguments &args) { // Invalid } else { - return ThrowException(Exception::TypeError(String::New("Image or Canvas expected"))); + return NanThrowTypeError("Image or Canvas expected"); } Context2d *context = ObjectWrap::Unwrap(args.This()); @@ -664,7 +657,7 @@ Context2d::DrawImage(const Arguments &args) { dh = sh; break; default: - return ThrowException(Exception::TypeError(String::New("invalid arguments"))); + return NanThrowTypeError("invalid arguments"); } // Start draw @@ -691,29 +684,27 @@ Context2d::DrawImage(const Arguments &args) { cairo_restore(ctx); - return Undefined(); + NanReturnUndefined(); } /* * Get global alpha. */ -Handle -Context2d::GetGlobalAlpha(Local prop, const AccessorInfo &info) { - HandleScope scope; - Context2d *context = ObjectWrap::Unwrap(info.This()); - return scope.Close(Number::New(context->state->globalAlpha)); +NAN_GETTER(Context2d::GetGlobalAlpha) { + NanScope(); + Context2d *context = ObjectWrap::Unwrap(args.This()); + NanReturnValue(Number::New(context->state->globalAlpha)); } /* * Set global alpha. */ -void -Context2d::SetGlobalAlpha(Local prop, Local val, const AccessorInfo &info) { - double n = val->NumberValue(); +NAN_SETTER(Context2d::SetGlobalAlpha) { + double n = value->NumberValue(); if (n >= 0 && n <= 1) { - Context2d *context = ObjectWrap::Unwrap(info.This()); + Context2d *context = ObjectWrap::Unwrap(args.This()); context->state->globalAlpha = n; } } @@ -722,10 +713,9 @@ Context2d::SetGlobalAlpha(Local prop, Local val, const AccessorIn * Get global composite operation. */ -Handle -Context2d::GetGlobalCompositeOperation(Local prop, const AccessorInfo &info) { - HandleScope scope; - Context2d *context = ObjectWrap::Unwrap(info.This()); +NAN_GETTER(Context2d::GetGlobalCompositeOperation) { + NanScope(); + Context2d *context = ObjectWrap::Unwrap(args.This()); cairo_t *ctx = context->context(); const char *op = "source-over"; @@ -765,17 +755,16 @@ Context2d::GetGlobalCompositeOperation(Local prop, const AccessorInfo &i #endif } - return scope.Close(String::NewSymbol(op)); + NanReturnValue(NanSymbol(op)); } /* * Set pattern quality. */ -void -Context2d::SetPatternQuality(Local prop, Local val, const AccessorInfo &info) { - Context2d *context = ObjectWrap::Unwrap(info.This()); - String::AsciiValue quality(val->ToString()); +NAN_SETTER(Context2d::SetPatternQuality) { + Context2d *context = ObjectWrap::Unwrap(args.This()); + String::AsciiValue quality(value->ToString()); if (0 == strcmp("fast", *quality)) { context->state->patternQuality = CAIRO_FILTER_FAST; } else if (0 == strcmp("good", *quality)) { @@ -793,10 +782,9 @@ Context2d::SetPatternQuality(Local prop, Local val, const Accesso * Get pattern quality. */ -Handle -Context2d::GetPatternQuality(Local prop, const AccessorInfo &info) { - HandleScope scope; - Context2d *context = ObjectWrap::Unwrap(info.This()); +NAN_GETTER(Context2d::GetPatternQuality) { + NanScope(); + Context2d *context = ObjectWrap::Unwrap(args.This()); const char *quality; switch (context->state->patternQuality) { case CAIRO_FILTER_FAST: quality = "fast"; break; @@ -805,18 +793,17 @@ Context2d::GetPatternQuality(Local prop, const AccessorInfo &info) { case CAIRO_FILTER_BILINEAR: quality = "bilinear"; break; default: quality = "good"; } - return scope.Close(String::NewSymbol(quality)); + NanReturnValue(NanSymbol(quality)); } /* * Set global composite operation. */ -void -Context2d::SetGlobalCompositeOperation(Local prop, Local val, const AccessorInfo &info) { - Context2d *context = ObjectWrap::Unwrap(info.This()); +NAN_SETTER(Context2d::SetGlobalCompositeOperation) { + Context2d *context = ObjectWrap::Unwrap(args.This()); cairo_t *ctx = context->context(); - String::AsciiValue type(val->ToString()); + String::AsciiValue type(value->ToString()); if (0 == strcmp("xor", *type)) { cairo_set_operator(ctx, CAIRO_OPERATOR_XOR); } else if (0 == strcmp("source-atop", *type)) { @@ -888,64 +875,58 @@ Context2d::SetGlobalCompositeOperation(Local prop, Local val, con * Get shadow offset x. */ -Handle -Context2d::GetShadowOffsetX(Local prop, const AccessorInfo &info) { - HandleScope scope; - Context2d *context = ObjectWrap::Unwrap(info.This()); - return scope.Close(Number::New(context->state->shadowOffsetX)); +NAN_GETTER(Context2d::GetShadowOffsetX) { + NanScope(); + Context2d *context = ObjectWrap::Unwrap(args.This()); + NanReturnValue(Number::New(context->state->shadowOffsetX)); } /* * Set shadow offset x. */ -void -Context2d::SetShadowOffsetX(Local prop, Local val, const AccessorInfo &info) { - Context2d *context = ObjectWrap::Unwrap(info.This()); - context->state->shadowOffsetX = val->NumberValue(); +NAN_SETTER(Context2d::SetShadowOffsetX) { + Context2d *context = ObjectWrap::Unwrap(args.This()); + context->state->shadowOffsetX = value->NumberValue(); } /* * Get shadow offset y. */ -Handle -Context2d::GetShadowOffsetY(Local prop, const AccessorInfo &info) { - HandleScope scope; - Context2d *context = ObjectWrap::Unwrap(info.This()); - return scope.Close(Number::New(context->state->shadowOffsetY)); +NAN_GETTER(Context2d::GetShadowOffsetY) { + NanScope(); + Context2d *context = ObjectWrap::Unwrap(args.This()); + NanReturnValue(Number::New(context->state->shadowOffsetY)); } /* * Set shadow offset y. */ -void -Context2d::SetShadowOffsetY(Local prop, Local val, const AccessorInfo &info) { - Context2d *context = ObjectWrap::Unwrap(info.This()); - context->state->shadowOffsetY = val->NumberValue(); +NAN_SETTER(Context2d::SetShadowOffsetY) { + Context2d *context = ObjectWrap::Unwrap(args.This()); + context->state->shadowOffsetY = value->NumberValue(); } /* * Get shadow blur. */ -Handle -Context2d::GetShadowBlur(Local prop, const AccessorInfo &info) { - HandleScope scope; - Context2d *context = ObjectWrap::Unwrap(info.This()); - return scope.Close(Number::New(context->state->shadowBlur)); +NAN_GETTER(Context2d::GetShadowBlur) { + NanScope(); + Context2d *context = ObjectWrap::Unwrap(args.This()); + NanReturnValue(Number::New(context->state->shadowBlur)); } /* * Set shadow blur. */ -void -Context2d::SetShadowBlur(Local prop, Local val, const AccessorInfo &info) { - int n = val->NumberValue(); +NAN_SETTER(Context2d::SetShadowBlur) { + int n = value->NumberValue(); if (n >= 0) { - Context2d *context = ObjectWrap::Unwrap(info.This()); + Context2d *context = ObjectWrap::Unwrap(args.This()); context->state->shadowBlur = n; } } @@ -954,10 +935,9 @@ Context2d::SetShadowBlur(Local prop, Local val, const AccessorInf * Get current antialiasing setting. */ -Handle -Context2d::GetAntiAlias(Local prop, const AccessorInfo &info) { - HandleScope scope; - Context2d *context = ObjectWrap::Unwrap(info.This()); +NAN_GETTER(Context2d::GetAntiAlias) { + NanScope(); + Context2d *context = ObjectWrap::Unwrap(args.This()); const char *aa; switch (cairo_get_antialias(context->context())) { case CAIRO_ANTIALIAS_NONE: aa = "none"; break; @@ -965,17 +945,16 @@ Context2d::GetAntiAlias(Local prop, const AccessorInfo &info) { case CAIRO_ANTIALIAS_SUBPIXEL: aa = "subpixel"; break; default: aa = "default"; } - return scope.Close(String::NewSymbol(aa)); + NanReturnValue(NanSymbol(aa)); } /* * Set antialiasing. */ -void -Context2d::SetAntiAlias(Local prop, Local val, const AccessorInfo &info) { - String::AsciiValue str(val->ToString()); - Context2d *context = ObjectWrap::Unwrap(info.This()); +NAN_SETTER(Context2d::SetAntiAlias) { + String::AsciiValue str(value->ToString()); + Context2d *context = ObjectWrap::Unwrap(args.This()); cairo_t *ctx = context->context(); cairo_antialias_t a; if (0 == strcmp("none", *str)) { @@ -996,10 +975,9 @@ Context2d::SetAntiAlias(Local prop, Local val, const AccessorInfo * Get text drawing mode. */ -Handle -Context2d::GetTextDrawingMode(Local prop, const AccessorInfo &info) { - HandleScope scope; - Context2d *context = ObjectWrap::Unwrap(info.This()); +NAN_GETTER(Context2d::GetTextDrawingMode) { + NanScope(); + Context2d *context = ObjectWrap::Unwrap(args.This()); const char *mode; if (context->state->textDrawingMode == TEXT_DRAW_PATHS) { mode = "path"; @@ -1008,17 +986,16 @@ Context2d::GetTextDrawingMode(Local prop, const AccessorInfo &info) { } else { mode = "unknown"; } - return scope.Close(String::NewSymbol(mode)); + NanReturnValue(NanSymbol(mode)); } /* * Set text drawing mode. */ -void -Context2d::SetTextDrawingMode(Local prop, Local val, const AccessorInfo &info) { - String::AsciiValue str(val->ToString()); - Context2d *context = ObjectWrap::Unwrap(info.This()); +NAN_SETTER(Context2d::SetTextDrawingMode) { + String::AsciiValue str(value->ToString()); + Context2d *context = ObjectWrap::Unwrap(args.This()); if (0 == strcmp("path", *str)) { context->state->textDrawingMode = TEXT_DRAW_PATHS; } else if (0 == strcmp("glyph", *str)) { @@ -1030,10 +1007,9 @@ Context2d::SetTextDrawingMode(Local prop, Local val, const Access * Get filter. */ -Handle -Context2d::GetFilter(Local prop, const AccessorInfo &info) { - HandleScope scope; - Context2d *context = ObjectWrap::Unwrap(info.This()); +NAN_GETTER(Context2d::GetFilter) { + NanScope(); + Context2d *context = ObjectWrap::Unwrap(args.This()); const char *filter; switch (cairo_pattern_get_filter(cairo_get_source(context->context()))) { case CAIRO_FILTER_FAST: filter = "fast"; break; @@ -1042,17 +1018,16 @@ Context2d::GetFilter(Local prop, const AccessorInfo &info) { case CAIRO_FILTER_BILINEAR: filter = "bilinear"; break; default: filter = "good"; } - return scope.Close(String::NewSymbol(filter)); + NanReturnValue(NanSymbol(filter)); } /* * Set filter. */ -void -Context2d::SetFilter(Local prop, Local val, const AccessorInfo &info) { - String::AsciiValue str(val->ToString()); - Context2d *context = ObjectWrap::Unwrap(info.This()); +NAN_SETTER(Context2d::SetFilter) { + String::AsciiValue str(value->ToString()); + Context2d *context = ObjectWrap::Unwrap(args.This()); cairo_filter_t filter; if (0 == strcmp("fast", *str)) { filter = CAIRO_FILTER_FAST; @@ -1072,22 +1047,20 @@ Context2d::SetFilter(Local prop, Local val, const AccessorInfo &i * Get miter limit. */ -Handle -Context2d::GetMiterLimit(Local prop, const AccessorInfo &info) { - HandleScope scope; - Context2d *context = ObjectWrap::Unwrap(info.This()); - return scope.Close(Number::New(cairo_get_miter_limit(context->context()))); +NAN_GETTER(Context2d::GetMiterLimit) { + NanScope(); + Context2d *context = ObjectWrap::Unwrap(args.This()); + NanReturnValue(Number::New(cairo_get_miter_limit(context->context()))); } /* * Set miter limit. */ -void -Context2d::SetMiterLimit(Local prop, Local val, const AccessorInfo &info) { - double n = val->NumberValue(); +NAN_SETTER(Context2d::SetMiterLimit) { + double n = value->NumberValue(); if (n > 0) { - Context2d *context = ObjectWrap::Unwrap(info.This()); + Context2d *context = ObjectWrap::Unwrap(args.This()); cairo_set_miter_limit(context->context(), n); } } @@ -1096,22 +1069,20 @@ Context2d::SetMiterLimit(Local prop, Local val, const AccessorInf * Get line width. */ -Handle -Context2d::GetLineWidth(Local prop, const AccessorInfo &info) { - HandleScope scope; - Context2d *context = ObjectWrap::Unwrap(info.This()); - return scope.Close(Number::New(cairo_get_line_width(context->context()))); +NAN_GETTER(Context2d::GetLineWidth) { + NanScope(); + Context2d *context = ObjectWrap::Unwrap(args.This()); + NanReturnValue(Number::New(cairo_get_line_width(context->context()))); } /* * Set line width. */ -void -Context2d::SetLineWidth(Local prop, Local val, const AccessorInfo &info) { - double n = val->NumberValue(); +NAN_SETTER(Context2d::SetLineWidth) { + double n = value->NumberValue(); if (n > 0) { - Context2d *context = ObjectWrap::Unwrap(info.This()); + Context2d *context = ObjectWrap::Unwrap(args.This()); cairo_set_line_width(context->context(), n); } } @@ -1120,28 +1091,26 @@ Context2d::SetLineWidth(Local prop, Local val, const AccessorInfo * Get line join. */ -Handle -Context2d::GetLineJoin(Local prop, const AccessorInfo &info) { - HandleScope scope; - Context2d *context = ObjectWrap::Unwrap(info.This()); +NAN_GETTER(Context2d::GetLineJoin) { + NanScope(); + Context2d *context = ObjectWrap::Unwrap(args.This()); const char *join; switch (cairo_get_line_join(context->context())) { case CAIRO_LINE_JOIN_BEVEL: join = "bevel"; break; case CAIRO_LINE_JOIN_ROUND: join = "round"; break; default: join = "miter"; } - return scope.Close(String::NewSymbol(join)); + NanReturnValue(NanSymbol(join)); } /* * Set line join. */ -void -Context2d::SetLineJoin(Local prop, Local val, const AccessorInfo &info) { - Context2d *context = ObjectWrap::Unwrap(info.This()); +NAN_SETTER(Context2d::SetLineJoin) { + Context2d *context = ObjectWrap::Unwrap(args.This()); cairo_t *ctx = context->context(); - String::AsciiValue type(val->ToString()); + String::AsciiValue type(value->ToString()); if (0 == strcmp("round", *type)) { cairo_set_line_join(ctx, CAIRO_LINE_JOIN_ROUND); } else if (0 == strcmp("bevel", *type)) { @@ -1155,28 +1124,26 @@ Context2d::SetLineJoin(Local prop, Local val, const AccessorInfo * Get line cap. */ -Handle -Context2d::GetLineCap(Local prop, const AccessorInfo &info) { - HandleScope scope; - Context2d *context = ObjectWrap::Unwrap(info.This()); +NAN_GETTER(Context2d::GetLineCap) { + NanScope(); + Context2d *context = ObjectWrap::Unwrap(args.This()); const char *cap; switch (cairo_get_line_cap(context->context())) { case CAIRO_LINE_CAP_ROUND: cap = "round"; break; case CAIRO_LINE_CAP_SQUARE: cap = "square"; break; default: cap = "butt"; } - return scope.Close(String::NewSymbol(cap)); + NanReturnValue(NanSymbol(cap)); } /* * Set line cap. */ -void -Context2d::SetLineCap(Local prop, Local val, const AccessorInfo &info) { - Context2d *context = ObjectWrap::Unwrap(info.This()); +NAN_SETTER(Context2d::SetLineCap) { + Context2d *context = ObjectWrap::Unwrap(args.This()); cairo_t *ctx = context->context(); - String::AsciiValue type(val->ToString()); + String::AsciiValue type(value->ToString()); if (0 == strcmp("round", *type)) { cairo_set_line_cap(ctx, CAIRO_LINE_CAP_ROUND); } else if (0 == strcmp("square", *type)) { @@ -1190,77 +1157,73 @@ Context2d::SetLineCap(Local prop, Local val, const AccessorInfo & * Check if the given point is within the current path. */ -Handle -Context2d::IsPointInPath(const Arguments &args) { - HandleScope scope; +NAN_METHOD(Context2d::IsPointInPath) { + NanScope(); if (args[0]->IsNumber() && args[1]->IsNumber()) { Context2d *context = ObjectWrap::Unwrap(args.This()); cairo_t *ctx = context->context(); double x = args[0]->NumberValue() , y = args[1]->NumberValue(); - return scope.Close(Boolean::New(cairo_in_fill(ctx, x, y) || cairo_in_stroke(ctx, x, y))); + NanReturnValue(Boolean::New(cairo_in_fill(ctx, x, y) || cairo_in_stroke(ctx, x, y))); } - return False(); + NanReturnValue(False()); } /* - * Set fill pattern, used internally for fillStyle= + * Set fill pattern, useV internally for fillStyle= */ -Handle -Context2d::SetFillPattern(const Arguments &args) { - HandleScope scope; +NAN_METHOD(Context2d::SetFillPattern) { + NanScope(); Local obj = args[0]->ToObject(); - if (Gradient::constructor->HasInstance(obj)){ + if (NanHasInstance(Gradient::constructor, obj)){ Context2d *context = ObjectWrap::Unwrap(args.This()); Gradient *grad = ObjectWrap::Unwrap(obj); context->state->fillGradient = grad->pattern(); - } else if(Pattern::constructor->HasInstance(obj)){ + } else if(NanHasInstance(Pattern::constructor, obj)){ Context2d *context = ObjectWrap::Unwrap(args.This()); Pattern *pattern = ObjectWrap::Unwrap(obj); context->state->fillPattern = pattern->pattern(); } else { - return ThrowException(Exception::TypeError(String::New("Gradient or Pattern expected"))); + return NanThrowTypeError("Gradient or Pattern expected"); } - return Undefined(); + NanReturnUndefined(); } /* * Set stroke pattern, used internally for strokeStyle= */ -Handle -Context2d::SetStrokePattern(const Arguments &args) { - HandleScope scope; +NAN_METHOD(Context2d::SetStrokePattern) { + NanScope(); Local obj = args[0]->ToObject(); - if (Gradient::constructor->HasInstance(obj)){ + if (NanHasInstance(Gradient::constructor, obj)){ Context2d *context = ObjectWrap::Unwrap(args.This()); Gradient *grad = ObjectWrap::Unwrap(obj); context->state->strokeGradient = grad->pattern(); - } else if(Pattern::constructor->HasInstance(obj)){ + } else if(NanHasInstance(Pattern::constructor, obj)){ Context2d *context = ObjectWrap::Unwrap(args.This()); Pattern *pattern = ObjectWrap::Unwrap(obj); context->state->strokePattern = pattern->pattern(); } else { - return ThrowException(Exception::TypeError(String::New("Gradient or Pattern expected"))); + return NanThrowTypeError("Gradient or Pattern expected"); } - return Undefined(); + NanReturnUndefined(); } /* * Set shadow color. */ -void -Context2d::SetShadowColor(Local prop, Local val, const AccessorInfo &info) { +NAN_SETTER(Context2d::SetShadowColor) { short ok; - String::AsciiValue str(val->ToString()); + String::AsciiValue str(value->ToString()); uint32_t rgba = rgba_from_string(*str, &ok); if (ok) { - Context2d *context = ObjectWrap::Unwrap(info.This()); + Context2d *context = ObjectWrap::Unwrap(args.This()); context->state->shadow = rgba_create(rgba); } } @@ -1269,91 +1232,85 @@ Context2d::SetShadowColor(Local prop, Local val, const AccessorIn * Get shadow color. */ -Handle -Context2d::GetShadowColor(Local prop, const AccessorInfo &info) { - HandleScope scope; +NAN_GETTER(Context2d::GetShadowColor) { + NanScope(); char buf[64]; - Context2d *context = ObjectWrap::Unwrap(info.This()); + Context2d *context = ObjectWrap::Unwrap(args.This()); rgba_to_string(context->state->shadow, buf, sizeof(buf)); - return scope.Close(String::New(buf)); + NanReturnValue(String::New(buf)); } /* * Set fill color, used internally for fillStyle= */ -Handle -Context2d::SetFillColor(const Arguments &args) { - HandleScope scope; +NAN_METHOD(Context2d::SetFillColor) { + NanScope(); short ok; - if (!args[0]->IsString()) return Undefined(); + if (!args[0]->IsString()) NanReturnUndefined(); String::AsciiValue str(args[0]); uint32_t rgba = rgba_from_string(*str, &ok); - if (!ok) return Undefined(); + if (!ok) NanReturnUndefined(); Context2d *context = ObjectWrap::Unwrap(args.This()); context->state->fillPattern = context->state->fillGradient = NULL; context->state->fill = rgba_create(rgba); - return Undefined(); + NanReturnUndefined(); } /* * Get fill color. */ -Handle -Context2d::GetFillColor(Local prop, const AccessorInfo &info) { - HandleScope scope; +NAN_GETTER(Context2d::GetFillColor) { + NanScope(); char buf[64]; - Context2d *context = ObjectWrap::Unwrap(info.This()); + Context2d *context = ObjectWrap::Unwrap(args.This()); rgba_to_string(context->state->fill, buf, sizeof(buf)); - return scope.Close(String::New(buf)); + NanReturnValue(String::New(buf)); } /* * Set stroke color, used internally for strokeStyle= */ -Handle -Context2d::SetStrokeColor(const Arguments &args) { - HandleScope scope; +NAN_METHOD(Context2d::SetStrokeColor) { + NanScope(); short ok; - if (!args[0]->IsString()) return Undefined(); + if (!args[0]->IsString()) NanReturnUndefined(); String::AsciiValue str(args[0]); uint32_t rgba = rgba_from_string(*str, &ok); - if (!ok) return Undefined(); + if (!ok) NanReturnUndefined(); Context2d *context = ObjectWrap::Unwrap(args.This()); context->state->strokePattern = context->state->strokeGradient = NULL; context->state->stroke = rgba_create(rgba); - return Undefined(); + NanReturnUndefined(); } /* * Get stroke color. */ -Handle -Context2d::GetStrokeColor(Local prop, const AccessorInfo &info) { - HandleScope scope; +NAN_GETTER(Context2d::GetStrokeColor) { + NanScope(); char buf[64]; - Context2d *context = ObjectWrap::Unwrap(info.This()); + Context2d *context = ObjectWrap::Unwrap(args.This()); rgba_to_string(context->state->stroke, buf, sizeof(buf)); - return scope.Close(String::New(buf)); + NanReturnValue(String::New(buf)); } /* * Bezier curve. */ -Handle -Context2d::BezierCurveTo(const Arguments &args) { - HandleScope scope; +NAN_METHOD(Context2d::BezierCurveTo) { + NanScope(); if (!args[0]->IsNumber() ||!args[1]->IsNumber() ||!args[2]->IsNumber() ||!args[3]->IsNumber() ||!args[4]->IsNumber() - ||!args[5]->IsNumber()) return Undefined(); + ||!args[5]->IsNumber()) NanReturnUndefined(); Context2d *context = ObjectWrap::Unwrap(args.This()); cairo_curve_to(context->context() @@ -1364,21 +1321,20 @@ Context2d::BezierCurveTo(const Arguments &args) { , args[4]->NumberValue() , args[5]->NumberValue()); - return Undefined(); + NanReturnUndefined(); } /* * Quadratic curve approximation from libsvg-cairo. */ -Handle -Context2d::QuadraticCurveTo(const Arguments &args) { - HandleScope scope; +NAN_METHOD(Context2d::QuadraticCurveTo) { + NanScope(); if (!args[0]->IsNumber() ||!args[1]->IsNumber() ||!args[2]->IsNumber() - ||!args[3]->IsNumber()) return Undefined(); + ||!args[3]->IsNumber()) NanReturnUndefined(); Context2d *context = ObjectWrap::Unwrap(args.This()); cairo_t *ctx = context->context(); @@ -1402,77 +1358,71 @@ Context2d::QuadraticCurveTo(const Arguments &args) { , x2 , y2); - return Undefined(); + NanReturnUndefined(); } /* * Save state. */ -Handle -Context2d::Save(const Arguments &args) { - HandleScope scope; +NAN_METHOD(Context2d::Save) { + NanScope(); Context2d *context = ObjectWrap::Unwrap(args.This()); context->save(); - return Undefined(); + NanReturnUndefined(); } /* * Restore state. */ -Handle -Context2d::Restore(const Arguments &args) { - HandleScope scope; +NAN_METHOD(Context2d::Restore) { + NanScope(); Context2d *context = ObjectWrap::Unwrap(args.This()); context->restore(); - return Undefined(); + NanReturnUndefined(); } /* * Creates a new subpath. */ -Handle -Context2d::BeginPath(const Arguments &args) { - HandleScope scope; +NAN_METHOD(Context2d::BeginPath) { + NanScope(); Context2d *context = ObjectWrap::Unwrap(args.This()); cairo_new_path(context->context()); - return Undefined(); + NanReturnUndefined(); } /* * Marks the subpath as closed. */ -Handle -Context2d::ClosePath(const Arguments &args) { - HandleScope scope; +NAN_METHOD(Context2d::ClosePath) { + NanScope(); Context2d *context = ObjectWrap::Unwrap(args.This()); cairo_close_path(context->context()); - return Undefined(); + NanReturnUndefined(); } /* * Rotate transformation. */ -Handle -Context2d::Rotate(const Arguments &args) { - HandleScope scope; +NAN_METHOD(Context2d::Rotate) { + NanScope(); Context2d *context = ObjectWrap::Unwrap(args.This()); cairo_rotate(context->context() , args[0]->IsNumber() ? args[0]->NumberValue() : 0); - return Undefined(); + NanReturnUndefined(); } /* * Modify the CTM. */ -Handle -Context2d::Transform(const Arguments &args) { - HandleScope scope; +NAN_METHOD(Context2d::Transform) { + NanScope(); cairo_matrix_t matrix; cairo_matrix_init(&matrix @@ -1486,96 +1436,89 @@ Context2d::Transform(const Arguments &args) { Context2d *context = ObjectWrap::Unwrap(args.This()); cairo_transform(context->context(), &matrix); - return Undefined(); + NanReturnUndefined(); } /* * Reset the CTM, used internally by setTransform(). */ -Handle -Context2d::ResetTransform(const Arguments &args) { - HandleScope scope; +NAN_METHOD(Context2d::ResetTransform) { + NanScope(); Context2d *context = ObjectWrap::Unwrap(args.This()); cairo_identity_matrix(context->context()); - return Undefined(); + NanReturnUndefined(); } /* * Translate transformation. */ -Handle -Context2d::Translate(const Arguments &args) { - HandleScope scope; +NAN_METHOD(Context2d::Translate) { + NanScope(); Context2d *context = ObjectWrap::Unwrap(args.This()); cairo_translate(context->context() , args[0]->IsNumber() ? args[0]->NumberValue() : 0 , args[1]->IsNumber() ? args[1]->NumberValue() : 0); - return Undefined(); + NanReturnUndefined(); } /* * Scale transformation. */ -Handle -Context2d::Scale(const Arguments &args) { - HandleScope scope; +NAN_METHOD(Context2d::Scale) { + NanScope(); Context2d *context = ObjectWrap::Unwrap(args.This()); cairo_scale(context->context() , args[0]->IsNumber() ? args[0]->NumberValue() : 0 , args[1]->IsNumber() ? args[1]->NumberValue() : 0); - return Undefined(); + NanReturnUndefined(); } /* * Use path as clipping region. */ -Handle -Context2d::Clip(const Arguments &args) { - HandleScope scope; +NAN_METHOD(Context2d::Clip) { + NanScope(); Context2d *context = ObjectWrap::Unwrap(args.This()); cairo_t *ctx = context->context(); cairo_clip_preserve(ctx); - return Undefined(); + NanReturnUndefined(); } /* * Fill the path. */ -Handle -Context2d::Fill(const Arguments &args) { - HandleScope scope; +NAN_METHOD(Context2d::Fill) { + NanScope(); Context2d *context = ObjectWrap::Unwrap(args.This()); context->fill(true); - return Undefined(); + NanReturnUndefined(); } /* * Stroke the path. */ -Handle -Context2d::Stroke(const Arguments &args) { - HandleScope scope; +NAN_METHOD(Context2d::Stroke) { + NanScope(); Context2d *context = ObjectWrap::Unwrap(args.This()); context->stroke(true); - return Undefined(); + NanReturnUndefined(); } /* * Fill text at (x, y). */ -Handle -Context2d::FillText(const Arguments &args) { - HandleScope scope; +NAN_METHOD(Context2d::FillText) { + NanScope(); if (!args[1]->IsNumber() - || !args[2]->IsNumber()) return Undefined(); + || !args[2]->IsNumber()) NanReturnUndefined(); String::Utf8Value str(args[0]->ToString()); double x = args[1]->NumberValue(); @@ -1593,19 +1536,18 @@ Context2d::FillText(const Arguments &args) { } context->restorePath(); - return Undefined(); + NanReturnUndefined(); } /* * Stroke text at (x ,y). */ -Handle -Context2d::StrokeText(const Arguments &args) { - HandleScope scope; +NAN_METHOD(Context2d::StrokeText) { + NanScope(); if (!args[1]->IsNumber() - || !args[2]->IsNumber()) return Undefined(); + || !args[2]->IsNumber()) NanReturnUndefined(); String::Utf8Value str(args[0]->ToString()); double x = args[1]->NumberValue(); @@ -1623,7 +1565,7 @@ Context2d::StrokeText(const Arguments &args) { } context->restorePath(); - return Undefined(); + NanReturnUndefined(); } /* @@ -1735,42 +1677,40 @@ Context2d::setTextPath(const char *str, double x, double y) { * Adds a point to the current subpath. */ -Handle -Context2d::LineTo(const Arguments &args) { - HandleScope scope; +NAN_METHOD(Context2d::LineTo) { + NanScope(); if (!args[0]->IsNumber()) - return ThrowException(Exception::TypeError(String::New("lineTo() x must be a number"))); + return NanThrowTypeError("lineTo() x must be a number"); if (!args[1]->IsNumber()) - return ThrowException(Exception::TypeError(String::New("lineTo() y must be a number"))); + return NanThrowTypeError("lineTo() y must be a number"); Context2d *context = ObjectWrap::Unwrap(args.This()); cairo_line_to(context->context() , args[0]->NumberValue() , args[1]->NumberValue()); - return Undefined(); + NanReturnUndefined(); } /* * Creates a new subpath at the given point. */ -Handle -Context2d::MoveTo(const Arguments &args) { - HandleScope scope; +NAN_METHOD(Context2d::MoveTo) { + NanScope(); if (!args[0]->IsNumber()) - return ThrowException(Exception::TypeError(String::New("moveTo() x must be a number"))); + return NanThrowTypeError("moveTo() x must be a number"); if (!args[1]->IsNumber()) - return ThrowException(Exception::TypeError(String::New("moveTo() y must be a number"))); + return NanThrowTypeError("moveTo() y must be a number"); Context2d *context = ObjectWrap::Unwrap(args.This()); cairo_move_to(context->context() , args[0]->NumberValue() , args[1]->NumberValue()); - return Undefined(); + NanReturnUndefined(); } /* @@ -1778,19 +1718,18 @@ Context2d::MoveTo(const Arguments &args) { */ #ifdef HAVE_FREETYPE -Handle -Context2d::SetFontFace(const Arguments &args) { - HandleScope scope; +NAN_METHOD(Context2d::SetFontFace) { + NanScope(); // Ignore invalid args if (!args[0]->IsObject() || !args[1]->IsNumber()) - return ThrowException(Exception::TypeError(String::New("Expected object and number"))); + return NanThrowTypeError("Expected object and number"); Local obj = args[0]->ToObject(); - if (!FontFace::constructor->HasInstance(obj)) - return ThrowException(Exception::TypeError(String::New("FontFace expected"))); + if (!NanHasInstance(FontFace::constructor, obj)) + return NanThrowTypeError("FontFace expected"); FontFace *face = ObjectWrap::Unwrap(obj); double size = args[1]->NumberValue(); @@ -1801,7 +1740,7 @@ Context2d::SetFontFace(const Arguments &args) { cairo_set_font_size(ctx, size); cairo_set_font_face(ctx, face->cairoFace()); - return Undefined(); + NanReturnUndefined(); } #endif @@ -1814,16 +1753,15 @@ Context2d::SetFontFace(const Arguments &args) { * - family */ -Handle -Context2d::SetFont(const Arguments &args) { - HandleScope scope; +NAN_METHOD(Context2d::SetFont) { + NanScope(); // Ignore invalid args if (!args[0]->IsString() || !args[1]->IsString() || !args[2]->IsNumber() || !args[3]->IsString() - || !args[4]->IsString()) return Undefined(); + || !args[4]->IsString()) NanReturnUndefined(); String::AsciiValue weight(args[0]); String::AsciiValue style(args[1]); @@ -1900,7 +1838,7 @@ Context2d::SetFont(const Arguments &args) { #endif - return Undefined(); + NanReturnUndefined(); } #if HAVE_PANGO @@ -1931,9 +1869,8 @@ Context2d::setFontFromState() { * fontBoundingBoxAscent, fontBoundingBoxDescent */ -Handle -Context2d::MeasureText(const Arguments &args) { - HandleScope scope; +NAN_METHOD(Context2d::MeasureText) { + NanScope(); Context2d *context = ObjectWrap::Unwrap(args.This()); cairo_t *ctx = context->context(); @@ -2050,84 +1987,79 @@ Context2d::MeasureText(const Arguments &args) { #endif - return scope.Close(obj); + NanReturnValue(obj); } /* * Set text baseline. */ -Handle -Context2d::SetTextBaseline(const Arguments &args) { - HandleScope scope; +NAN_METHOD(Context2d::SetTextBaseline) { + NanScope(); - if (!args[0]->IsInt32()) return Undefined(); + if (!args[0]->IsInt32()) NanReturnUndefined(); Context2d *context = ObjectWrap::Unwrap(args.This()); context->state->textBaseline = args[0]->Int32Value(); - return Undefined(); + NanReturnUndefined(); } /* * Set text alignment. -1 0 1 */ -Handle -Context2d::SetTextAlignment(const Arguments &args) { - HandleScope scope; +NAN_METHOD(Context2d::SetTextAlignment) { + NanScope(); - if (!args[0]->IsInt32()) return Undefined(); + if (!args[0]->IsInt32()) NanReturnUndefined(); Context2d *context = ObjectWrap::Unwrap(args.This()); context->state->textAlignment = args[0]->Int32Value(); - return Undefined(); + NanReturnUndefined(); } /* * Fill the rectangle defined by x, y, width and height. */ -Handle -Context2d::FillRect(const Arguments &args) { - HandleScope scope; +NAN_METHOD(Context2d::FillRect) { + NanScope(); RECT_ARGS; - if (0 == width || 0 == height) return Undefined(); + if (0 == width || 0 == height) NanReturnUndefined(); Context2d *context = ObjectWrap::Unwrap(args.This()); cairo_t *ctx = context->context(); context->savePath(); cairo_rectangle(ctx, x, y, width, height); context->fill(); context->restorePath(); - return Undefined(); + NanReturnUndefined(); } /* * Stroke the rectangle defined by x, y, width and height. */ -Handle -Context2d::StrokeRect(const Arguments &args) { - HandleScope scope; +NAN_METHOD(Context2d::StrokeRect) { + NanScope(); RECT_ARGS; - if (0 == width && 0 == height) return Undefined(); + if (0 == width && 0 == height) NanReturnUndefined(); Context2d *context = ObjectWrap::Unwrap(args.This()); cairo_t *ctx = context->context(); context->savePath(); cairo_rectangle(ctx, x, y, width, height); context->stroke(); context->restorePath(); - return Undefined(); + NanReturnUndefined(); } /* * Clears all pixels defined by x, y, width and height. */ -Handle -Context2d::ClearRect(const Arguments &args) { - HandleScope scope; +NAN_METHOD(Context2d::ClearRect) { + NanScope(); RECT_ARGS; - if (0 == width || 0 == height) return Undefined(); + if (0 == width || 0 == height) NanReturnUndefined(); Context2d *context = ObjectWrap::Unwrap(args.This()); cairo_t *ctx = context->context(); cairo_save(ctx); @@ -2137,16 +2069,15 @@ Context2d::ClearRect(const Arguments &args) { cairo_fill(ctx); context->restorePath(); cairo_restore(ctx); - return Undefined(); + NanReturnUndefined(); } /* * Adds a rectangle subpath. */ -Handle -Context2d::Rect(const Arguments &args) { - HandleScope scope; +NAN_METHOD(Context2d::Rect) { + NanScope(); RECT_ARGS; Context2d *context = ObjectWrap::Unwrap(args.This()); cairo_t *ctx = context->context(); @@ -2159,22 +2090,21 @@ Context2d::Rect(const Arguments &args) { } else { cairo_rectangle(ctx, x, y, width, height); } - return Undefined(); + NanReturnUndefined(); } /* * Adds an arc at x, y with the given radis and start/end angles. */ -Handle -Context2d::Arc(const Arguments &args) { - HandleScope scope; +NAN_METHOD(Context2d::Arc) { + NanScope(); if (!args[0]->IsNumber() || !args[1]->IsNumber() || !args[2]->IsNumber() || !args[3]->IsNumber() - || !args[4]->IsNumber()) return Undefined(); + || !args[4]->IsNumber()) NanReturnUndefined(); bool anticlockwise = args[5]->BooleanValue(); @@ -2197,7 +2127,7 @@ Context2d::Arc(const Arguments &args) { , args[4]->NumberValue()); } - return Undefined(); + NanReturnUndefined(); } /* @@ -2206,15 +2136,14 @@ Context2d::Arc(const Arguments &args) { * Implementation influenced by WebKit. */ -Handle -Context2d::ArcTo(const Arguments &args) { - HandleScope scope; +NAN_METHOD(Context2d::ArcTo) { + NanScope(); if (!args[0]->IsNumber() || !args[1]->IsNumber() || !args[2]->IsNumber() || !args[3]->IsNumber() - || !args[4]->IsNumber()) return Undefined(); + || !args[4]->IsNumber()) NanReturnUndefined(); Context2d *context = ObjectWrap::Unwrap(args.This()); cairo_t *ctx = context->context(); @@ -2236,7 +2165,7 @@ Context2d::ArcTo(const Arguments &args) { || (p1.x == p2.x && p1.y == p2.y) || radius == 0.f) { cairo_line_to(ctx, p1.x, p1.y); - return Undefined(); + NanReturnUndefined(); } Point p1p0((p0.x - p1.x),(p0.y - p1.y)); @@ -2248,7 +2177,7 @@ Context2d::ArcTo(const Arguments &args) { // all points on a line logic if (-1 == cos_phi) { cairo_line_to(ctx, p1.x, p1.y); - return Undefined(); + NanReturnUndefined(); } if (1 == cos_phi) { @@ -2257,7 +2186,7 @@ Context2d::ArcTo(const Arguments &args) { double factor_max = max_length / p1p0_length; Point ep((p0.x + factor_max * p1p0.x), (p0.y + factor_max * p1p0.y)); cairo_line_to(ctx, ep.x, ep.y); - return Undefined(); + NanReturnUndefined(); } float tangent = radius / tan(acos(cos_phi) / 2); @@ -2309,5 +2238,5 @@ Context2d::ArcTo(const Arguments &args) { , ea); } - return Undefined(); + NanReturnUndefined(); } diff --git a/src/CanvasRenderingContext2d.h b/src/CanvasRenderingContext2d.h index f280cfe..086b816 100644 --- a/src/CanvasRenderingContext2d.h +++ b/src/CanvasRenderingContext2d.h @@ -71,76 +71,76 @@ class Context2d: public node::ObjectWrap { Context2d(Canvas *canvas); static Persistent constructor; static void Initialize(Handle target); - static Handle New(const Arguments &args); - static Handle DrawImage(const Arguments &args); - static Handle PutImageData(const Arguments &args); - static Handle Save(const Arguments &args); - static Handle Restore(const Arguments &args); - static Handle Rotate(const Arguments &args); - static Handle Translate(const Arguments &args); - static Handle Scale(const Arguments &args); - static Handle Transform(const Arguments &args); - static Handle ResetTransform(const Arguments &args); - static Handle IsPointInPath(const Arguments &args); - static Handle BeginPath(const Arguments &args); - static Handle ClosePath(const Arguments &args); - static Handle AddPage(const Arguments &args); - static Handle Clip(const Arguments &args); - static Handle Fill(const Arguments &args); - static Handle Stroke(const Arguments &args); - static Handle FillText(const Arguments &args); - static Handle StrokeText(const Arguments &args); - static Handle SetFont(const Arguments &args); + static NAN_METHOD(New); + static NAN_METHOD(DrawImage); + static NAN_METHOD(PutImageData); + static NAN_METHOD(Save); + static NAN_METHOD(Restore); + static NAN_METHOD(Rotate); + static NAN_METHOD(Translate); + static NAN_METHOD(Scale); + static NAN_METHOD(Transform); + static NAN_METHOD(ResetTransform); + static NAN_METHOD(IsPointInPath); + static NAN_METHOD(BeginPath); + static NAN_METHOD(ClosePath); + static NAN_METHOD(AddPage); + static NAN_METHOD(Clip); + static NAN_METHOD(Fill); + static NAN_METHOD(Stroke); + static NAN_METHOD(FillText); + static NAN_METHOD(StrokeText); + static NAN_METHOD(SetFont); #ifdef HAVE_FREETYPE - static Handle SetFontFace(const Arguments &args); + static NAN_METHOD(SetFontFace); #endif - static Handle SetFillColor(const Arguments &args); - static Handle SetStrokeColor(const Arguments &args); - static Handle SetFillPattern(const Arguments &args); - static Handle SetStrokePattern(const Arguments &args); - static Handle SetTextBaseline(const Arguments &args); - static Handle SetTextAlignment(const Arguments &args); - static Handle MeasureText(const Arguments &args); - static Handle BezierCurveTo(const Arguments &args); - static Handle QuadraticCurveTo(const Arguments &args); - static Handle LineTo(const Arguments &args); - static Handle MoveTo(const Arguments &args); - static Handle FillRect(const Arguments &args); - static Handle StrokeRect(const Arguments &args); - static Handle ClearRect(const Arguments &args); - static Handle Rect(const Arguments &args); - static Handle Arc(const Arguments &args); - static Handle ArcTo(const Arguments &args); - static Handle GetPatternQuality(Local prop, const AccessorInfo &info); - static Handle GetGlobalCompositeOperation(Local prop, const AccessorInfo &info); - static Handle GetGlobalAlpha(Local prop, const AccessorInfo &info); - static Handle GetShadowColor(Local prop, const AccessorInfo &info); - static Handle GetFillColor(Local prop, const AccessorInfo &info); - static Handle GetStrokeColor(Local prop, const AccessorInfo &info); - static Handle GetMiterLimit(Local prop, const AccessorInfo &info); - static Handle GetLineCap(Local prop, const AccessorInfo &info); - static Handle GetLineJoin(Local prop, const AccessorInfo &info); - static Handle GetLineWidth(Local prop, const AccessorInfo &info); - static Handle GetShadowOffsetX(Local prop, const AccessorInfo &info); - static Handle GetShadowOffsetY(Local prop, const AccessorInfo &info); - static Handle GetShadowBlur(Local prop, const AccessorInfo &info); - static Handle GetAntiAlias(Local prop, const AccessorInfo &info); - static Handle GetTextDrawingMode(Local prop, const AccessorInfo &info); - static Handle GetFilter(Local prop, const AccessorInfo &info); - static void SetPatternQuality(Local prop, Local val, const AccessorInfo &info); - static void SetGlobalCompositeOperation(Local prop, Local val, const AccessorInfo &info); - static void SetGlobalAlpha(Local prop, Local val, const AccessorInfo &info); - static void SetShadowColor(Local prop, Local val, const AccessorInfo &info); - static void SetMiterLimit(Local prop, Local val, const AccessorInfo &info); - static void SetLineCap(Local prop, Local val, const AccessorInfo &info); - static void SetLineJoin(Local prop, Local val, const AccessorInfo &info); - static void SetLineWidth(Local prop, Local val, const AccessorInfo &info); - static void SetShadowOffsetX(Local prop, Local val, const AccessorInfo &info); - static void SetShadowOffsetY(Local prop, Local val, const AccessorInfo &info); - static void SetShadowBlur(Local prop, Local val, const AccessorInfo &info); - static void SetAntiAlias(Local prop, Local val, const AccessorInfo &info); - static void SetTextDrawingMode(Local prop, Local val, const AccessorInfo &info); - static void SetFilter(Local prop, Local val, const AccessorInfo &info); + static NAN_METHOD(SetFillColor); + static NAN_METHOD(SetStrokeColor); + static NAN_METHOD(SetFillPattern); + static NAN_METHOD(SetStrokePattern); + static NAN_METHOD(SetTextBaseline); + static NAN_METHOD(SetTextAlignment); + static NAN_METHOD(MeasureText); + static NAN_METHOD(BezierCurveTo); + static NAN_METHOD(QuadraticCurveTo); + static NAN_METHOD(LineTo); + static NAN_METHOD(MoveTo); + static NAN_METHOD(FillRect); + static NAN_METHOD(StrokeRect); + static NAN_METHOD(ClearRect); + static NAN_METHOD(Rect); + static NAN_METHOD(Arc); + static NAN_METHOD(ArcTo); + static NAN_GETTER(GetPatternQuality); + static NAN_GETTER(GetGlobalCompositeOperation); + static NAN_GETTER(GetGlobalAlpha); + static NAN_GETTER(GetShadowColor); + static NAN_GETTER(GetFillColor); + static NAN_GETTER(GetStrokeColor); + static NAN_GETTER(GetMiterLimit); + static NAN_GETTER(GetLineCap); + static NAN_GETTER(GetLineJoin); + static NAN_GETTER(GetLineWidth); + static NAN_GETTER(GetShadowOffsetX); + static NAN_GETTER(GetShadowOffsetY); + static NAN_GETTER(GetShadowBlur); + static NAN_GETTER(GetAntiAlias); + static NAN_GETTER(GetTextDrawingMode); + static NAN_GETTER(GetFilter); + static NAN_SETTER(SetPatternQuality); + static NAN_SETTER(SetGlobalCompositeOperation); + static NAN_SETTER(SetGlobalAlpha); + static NAN_SETTER(SetShadowColor); + static NAN_SETTER(SetMiterLimit); + static NAN_SETTER(SetLineCap); + static NAN_SETTER(SetLineJoin); + static NAN_SETTER(SetLineWidth); + static NAN_SETTER(SetShadowOffsetX); + static NAN_SETTER(SetShadowOffsetY); + static NAN_SETTER(SetShadowBlur); + static NAN_SETTER(SetAntiAlias); + static NAN_SETTER(SetTextDrawingMode); + static NAN_SETTER(SetFilter); inline void setContext(cairo_t *ctx) { _context = ctx; } inline cairo_t *context(){ return _context; } inline Canvas *canvas(){ return _canvas; } diff --git a/src/FontFace.cc b/src/FontFace.cc index 37cce02..af867a8 100644 --- a/src/FontFace.cc +++ b/src/FontFace.cc @@ -6,6 +6,8 @@ #include "FontFace.h" +#include "nan.h" + Persistent FontFace::constructor; /* @@ -25,19 +27,16 @@ FontFace::~FontFace() { void FontFace::Initialize(Handle target) { - HandleScope scope; + NanScope(); // Constructor - #if NODE_VERSION_AT_LEAST(0, 11, 3) - constructor = Persistent::New(Isolate::GetCurrent(), FunctionTemplate::New(FontFace::New)); - #else - constructor = Persistent::New(FunctionTemplate::New(FontFace::New)); - #endif - constructor->InstanceTemplate()->SetInternalFieldCount(1); - constructor->SetClassName(String::NewSymbol("FontFace")); + Local ctor = FunctionTemplate::New(FontFace::New); + NanAssignPersistent(FunctionTemplate, constructor, ctor); + ctor->InstanceTemplate()->SetInternalFieldCount(1); + ctor->SetClassName(NanSymbol("FontFace")); // Prototype - target->Set(String::NewSymbol("FontFace"), constructor->GetFunction()); + target->Set(NanSymbol("FontFace"), ctor->GetFunction()); } /* @@ -53,13 +52,12 @@ static cairo_user_data_key_t key; * Initialize a new FontFace. */ -Handle -FontFace::New(const Arguments &args) { - HandleScope scope; +NAN_METHOD(FontFace::New) { + NanScope(); if (!args[0]->IsString() || !args[1]->IsNumber()) { - return ThrowException(Exception::Error(String::New("Wrong argument types passed to FontFace constructor"))); + return NanThrowError("Wrong argument types passed to FontFace constructor"); } String::AsciiValue filePath(args[0]); @@ -73,14 +71,14 @@ FontFace::New(const Arguments &args) { _initLibrary = false; ftError = FT_Init_FreeType(&library); if (ftError) { - return ThrowException(Exception::Error(String::New("Could not load library"))); + return NanThrowError("Could not load library"); } } // Create new freetype font face. ftError = FT_New_Face(library, *filePath, faceIdx, &ftFace); if (ftError) { - return ThrowException(Exception::Error(String::New("Could not load font file"))); + return NanThrowError("Could not load font file"); } // Create new cairo font face. @@ -92,7 +90,7 @@ FontFace::New(const Arguments &args) { if (status) { cairo_font_face_destroy (crFace); FT_Done_Face (ftFace); - return ThrowException(Exception::Error(String::New("Failed to setup cairo font face user data"))); + return NanThrowError("Failed to setup cairo font face user data"); } // Explicit reference count the cairo font face. Otherwise the font face might @@ -101,6 +99,6 @@ FontFace::New(const Arguments &args) { FontFace *face = new FontFace(ftFace, crFace); face->Wrap(args.This()); - return args.This(); + NanReturnValue(args.This()); } diff --git a/src/FontFace.h b/src/FontFace.h index be8bbcc..b1e13e4 100644 --- a/src/FontFace.h +++ b/src/FontFace.h @@ -17,7 +17,7 @@ class FontFace: public node::ObjectWrap { public: static Persistent constructor; static void Initialize(Handle target); - static Handle New(const Arguments &args); + static NAN_METHOD(New); FontFace(FT_Face ftFace, cairo_font_face_t *crFace) :_ftFace(ftFace), _crFace(crFace) {} diff --git a/src/Image.cc b/src/Image.cc index 0aef93a..d96ca8b 100644 --- a/src/Image.cc +++ b/src/Image.cc @@ -19,8 +19,6 @@ typedef struct { } gif_data_t; #endif -Persistent Image::constructor; - /* * Read closure used by loadFromBuffer. */ @@ -30,61 +28,60 @@ typedef struct { uint8_t *buf; } read_closure_t; +Persistent Image::constructor; + /* * Initialize Image. */ void Image::Initialize(Handle target) { - HandleScope scope; + NanScope(); + + Local ctor = FunctionTemplate::New(Image::New); + NanAssignPersistent(FunctionTemplate, constructor, ctor); + ctor->InstanceTemplate()->SetInternalFieldCount(1); + ctor->SetClassName(NanSymbol("Image")); - // Constructor - #if NODE_VERSION_AT_LEAST(0, 11, 3) - constructor = Persistent::New(Isolate::GetCurrent(), FunctionTemplate::New(Image::New)); - #else - constructor = Persistent::New(FunctionTemplate::New(Image::New)); - #endif - constructor->InstanceTemplate()->SetInternalFieldCount(1); - constructor->SetClassName(String::NewSymbol("Image")); + ctor->InstanceTemplate()->SetInternalFieldCount(1); + ctor->SetClassName(NanSymbol("Image")); // Prototype - Local proto = constructor->PrototypeTemplate(); - proto->SetAccessor(String::NewSymbol("source"), GetSource, SetSource); - proto->SetAccessor(String::NewSymbol("complete"), GetComplete); - proto->SetAccessor(String::NewSymbol("width"), GetWidth); - proto->SetAccessor(String::NewSymbol("height"), GetHeight); - proto->SetAccessor(String::NewSymbol("onload"), GetOnload, SetOnload); - proto->SetAccessor(String::NewSymbol("onerror"), GetOnerror, SetOnerror); + Local proto = ctor->PrototypeTemplate(); + proto->SetAccessor(NanSymbol("source"), GetSource, SetSource); + proto->SetAccessor(NanSymbol("complete"), GetComplete); + proto->SetAccessor(NanSymbol("width"), GetWidth); + proto->SetAccessor(NanSymbol("height"), GetHeight); + proto->SetAccessor(NanSymbol("onload"), GetOnload, SetOnload); + proto->SetAccessor(NanSymbol("onerror"), GetOnerror, SetOnerror); #if CAIRO_VERSION_MINOR >= 10 - proto->SetAccessor(String::NewSymbol("dataMode"), GetDataMode, SetDataMode); - constructor->Set(String::NewSymbol("MODE_IMAGE"), Number::New(DATA_IMAGE)); - constructor->Set(String::NewSymbol("MODE_MIME"), Number::New(DATA_MIME)); + proto->SetAccessor(NanSymbol("dataMode"), GetDataMode, SetDataMode); + ctor->Set(NanSymbol("MODE_IMAGE"), Number::New(DATA_IMAGE)); + ctor->Set(NanSymbol("MODE_MIME"), Number::New(DATA_MIME)); #endif - target->Set(String::NewSymbol("Image"), constructor->GetFunction()); + target->Set(NanSymbol("Image"), ctor->GetFunction()); } /* * Initialize a new Image. */ -Handle -Image::New(const Arguments &args) { - HandleScope scope; +NAN_METHOD(Image::New) { + NanScope(); Image *img = new Image; img->data_mode = DATA_IMAGE; img->Wrap(args.This()); - return args.This(); + NanReturnValue(args.This()); } /* * Get complete boolean. */ -Handle -Image::GetComplete(Local, const AccessorInfo &info) { - HandleScope scope; - Image *img = ObjectWrap::Unwrap(info.This()); - return scope.Close(Boolean::New(Image::COMPLETE == img->state)); +NAN_GETTER(Image::GetComplete) { + NanScope(); + Image *img = ObjectWrap::Unwrap(args.This()); + NanReturnValue(Boolean::New(Image::COMPLETE == img->state)); } #if CAIRO_VERSION_MINOR >= 10 @@ -93,22 +90,20 @@ Image::GetComplete(Local, const AccessorInfo &info) { * Get dataMode. */ -Handle -Image::GetDataMode(Local, const AccessorInfo &info) { - HandleScope scope; - Image *img = ObjectWrap::Unwrap(info.This()); - return scope.Close(Number::New(img->data_mode)); +NAN_GETTER(Image::GetDataMode) { + NanScope(); + Image *img = ObjectWrap::Unwrap(args.This()); + NanReturnValue(Number::New(img->data_mode)); } /* * Set dataMode. */ -void -Image::SetDataMode(Local, Local val, const AccessorInfo &info) { - if (val->IsNumber()) { - Image *img = ObjectWrap::Unwrap(info.This()); - int mode = val->Uint32Value(); +NAN_SETTER(Image::SetDataMode) { + if (value->IsNumber()) { + Image *img = ObjectWrap::Unwrap(args.This()); + int mode = value->Uint32Value(); img->data_mode = (data_mode_t) mode; } } @@ -119,32 +114,29 @@ Image::SetDataMode(Local, Local val, const AccessorInfo &info) { * Get width. */ -Handle -Image::GetWidth(Local, const AccessorInfo &info) { - HandleScope scope; - Image *img = ObjectWrap::Unwrap(info.This()); - return scope.Close(Number::New(img->width)); +NAN_GETTER(Image::GetWidth) { + NanScope(); + Image *img = ObjectWrap::Unwrap(args.This()); + NanReturnValue(Number::New(img->width)); } /* * Get height. */ -Handle -Image::GetHeight(Local, const AccessorInfo &info) { - HandleScope scope; - Image *img = ObjectWrap::Unwrap(info.This()); - return scope.Close(Number::New(img->height)); +NAN_GETTER(Image::GetHeight) { + NanScope(); + Image *img = ObjectWrap::Unwrap(args.This()); + NanReturnValue(Number::New(img->height)); } /* * Get src path. */ -Handle -Image::GetSource(Local, const AccessorInfo &info) { - HandleScope scope; - Image *img = ObjectWrap::Unwrap(info.This()); - return scope.Close(String::New(img->filename ? img->filename : "")); +NAN_GETTER(Image::GetSource) { + NanScope(); + Image *img = ObjectWrap::Unwrap(args.This()); + NanReturnValue(String::New(img->filename ? img->filename : "")); } /* @@ -174,24 +166,23 @@ Image::clearData() { * Set src path. */ -void -Image::SetSource(Local, Local val, const AccessorInfo &info) { - HandleScope scope; - Image *img = ObjectWrap::Unwrap(info.This()); +NAN_SETTER(Image::SetSource) { + NanScope(); + Image *img = ObjectWrap::Unwrap(args.This()); cairo_status_t status = CAIRO_STATUS_READ_ERROR; img->clearData(); // url string - if (val->IsString()) { - String::AsciiValue src(val); + if (value->IsString()) { + String::AsciiValue src(value); if (img->filename) free(img->filename); img->filename = strdup(*src); status = img->load(); // Buffer - } else if (Buffer::HasInstance(val)) { - uint8_t *buf = (uint8_t *) Buffer::Data(val->ToObject()); - unsigned len = Buffer::Length(val->ToObject()); + } else if (Buffer::HasInstance(value)) { + uint8_t *buf = (uint8_t *) Buffer::Data(value->ToObject()); + unsigned len = Buffer::Length(value->ToObject()); status = img->loadFromBuffer(buf, len); } @@ -264,25 +255,20 @@ Image::readPNG(void *c, uint8_t *data, unsigned int len) { * Get onload callback. */ -Handle -Image::GetOnload(Local, const AccessorInfo &info) { - Image *img = ObjectWrap::Unwrap(info.This()); - return img->onload; +NAN_GETTER(Image::GetOnload) { + NanScope(); + Image *img = ObjectWrap::Unwrap(args.This()); + NanReturnValue(img->onload->GetFunction()); } /* * Set onload callback. */ -void -Image::SetOnload(Local, Local val, const AccessorInfo &info) { - if (val->IsFunction()) { - Image *img = ObjectWrap::Unwrap(info.This()); - #if NODE_VERSION_AT_LEAST(0, 11, 3) - img->onload = Persistent::New(Isolate::GetCurrent(), Handle::Cast(val)); - #else - img->onload = Persistent::New(Handle::Cast(val)); - #endif +NAN_SETTER(Image::SetOnload) { + if (value->IsFunction()) { + Image *img = ObjectWrap::Unwrap(args.This()); + img->onload = new NanCallback(value.As()); } } @@ -290,25 +276,20 @@ Image::SetOnload(Local, Local val, const AccessorInfo &info) { * Get onerror callback. */ -Handle -Image::GetOnerror(Local, const AccessorInfo &info) { - Image *img = ObjectWrap::Unwrap(info.This()); - return img->onerror; +NAN_GETTER(Image::GetOnerror) { + NanScope(); + Image *img = ObjectWrap::Unwrap(args.This()); + NanReturnValue(img->onerror->GetFunction()); } /* * Set onerror callback. */ -void -Image::SetOnerror(Local, Local val, const AccessorInfo &info) { - if (val->IsFunction()) { - Image *img = ObjectWrap::Unwrap(info.This()); - #if NODE_VERSION_AT_LEAST(0, 11, 3) - img->onerror = Persistent::New(Isolate::GetCurrent(), Handle::Cast(val)); - #else - img->onerror = Persistent::New(Handle::Cast(val)); - #endif +NAN_SETTER(Image::SetOnerror) { + if (value->IsFunction()) { + Image *img = ObjectWrap::Unwrap(args.This()); + img->onerror = new NanCallback(value.As()); } } @@ -323,6 +304,8 @@ Image::Image() { _surface = NULL; width = height = 0; state = DEFAULT; + onload = NULL; + onerror = NULL; } /* @@ -352,7 +335,7 @@ Image::load() { void Image::loaded() { - HandleScope scope; + NanScope(); state = COMPLETE; width = cairo_image_surface_get_width(_surface); @@ -360,13 +343,9 @@ Image::loaded() { _data_len = height * cairo_image_surface_get_stride(_surface); V8::AdjustAmountOfExternalAllocatedMemory(_data_len); - if (!onload.IsEmpty()) { - TryCatch try_catch; - onload->Call(Context::GetCurrent()->Global(), 0, NULL); - onload.Dispose(); - if (try_catch.HasCaught()) { - error(try_catch.Exception()); - } + if (onload != NULL) { + onload->Call(0, NULL); + delete onload; } } @@ -376,15 +355,11 @@ Image::loaded() { void Image::error(Local err) { - HandleScope scope; - if (!onerror.IsEmpty()) { + NanScope(); + if (onerror != NULL) { Local argv[1] = { err }; - TryCatch try_catch; - onerror->Call(Context::GetCurrent()->Global(), 1, argv); - onerror.Dispose(); - if (try_catch.HasCaught()) { - FatalException(try_catch); - } + onerror->Call(1, argv); + delete onerror; } } @@ -680,30 +655,30 @@ static void jpeg_mem_src (j_decompress_ptr cinfo, void* buffer, long nbytes) { */ cairo_status_t -Image::decodeJPEGIntoSurface(jpeg_decompress_struct *info) { +Image::decodeJPEGIntoSurface(jpeg_decompress_struct *args) { int stride = width * 4; cairo_status_t status; uint8_t *data = (uint8_t *) malloc(width * height * 4); if (!data) { - jpeg_abort_decompress(info); - jpeg_destroy_decompress(info); + jpeg_abort_decompress(args); + jpeg_destroy_decompress(args); return CAIRO_STATUS_NO_MEMORY; } - uint8_t *src = (uint8_t *) malloc(width * info->output_components); + uint8_t *src = (uint8_t *) malloc(width * args->output_components); if (!src) { free(data); - jpeg_abort_decompress(info); - jpeg_destroy_decompress(info); + jpeg_abort_decompress(args); + jpeg_destroy_decompress(args); return CAIRO_STATUS_NO_MEMORY; } for (int y = 0; y < height; ++y) { - jpeg_read_scanlines(info, &src, 1); + jpeg_read_scanlines(args, &src, 1); uint32_t *row = (uint32_t *)(data + stride * y); for (int x = 0; x < width; ++x) { - if (info->jpeg_color_space == 1) { + if (args->jpeg_color_space == 1) { uint32_t *pixel = row + x; *pixel = 255 << 24 | src[x] << 16 @@ -727,8 +702,8 @@ Image::decodeJPEGIntoSurface(jpeg_decompress_struct *info) { , height , cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width)); - jpeg_finish_decompress(info); - jpeg_destroy_decompress(info); + jpeg_finish_decompress(args); + jpeg_destroy_decompress(args); status = cairo_surface_status(_surface); if (status) { @@ -755,17 +730,17 @@ cairo_status_t Image::decodeJPEGBufferIntoMimeSurface(uint8_t *buf, unsigned len) { // TODO: remove this duplicate logic // JPEG setup - struct jpeg_decompress_struct info; + struct jpeg_decompress_struct args; struct jpeg_error_mgr err; - info.err = jpeg_std_error(&err); - jpeg_create_decompress(&info); + args.err = jpeg_std_error(&err); + jpeg_create_decompress(&args); - jpeg_mem_src(&info, buf, len); + jpeg_mem_src(&args, buf, len); - jpeg_read_header(&info, 1); - jpeg_start_decompress(&info); - width = info.output_width; - height = info.output_height; + jpeg_read_header(&args, 1); + jpeg_start_decompress(&args); + width = args.output_width; + height = args.output_height; // Data alloc // 8 pixels per byte using Alpha Channel format to reduce memory requirement. @@ -782,8 +757,8 @@ Image::decodeJPEGBufferIntoMimeSurface(uint8_t *buf, unsigned len) { , cairo_format_stride_for_width(CAIRO_FORMAT_A1, width)); // Cleanup - jpeg_abort_decompress(&info); - jpeg_destroy_decompress(&info); + jpeg_abort_decompress(&args); + jpeg_destroy_decompress(&args); cairo_status_t status = cairo_surface_status(_surface); if (status) { @@ -849,19 +824,19 @@ cairo_status_t Image::loadJPEGFromBuffer(uint8_t *buf, unsigned len) { // TODO: remove this duplicate logic // JPEG setup - struct jpeg_decompress_struct info; + struct jpeg_decompress_struct args; struct jpeg_error_mgr err; - info.err = jpeg_std_error(&err); - jpeg_create_decompress(&info); + args.err = jpeg_std_error(&err); + jpeg_create_decompress(&args); - jpeg_mem_src(&info, buf, len); + jpeg_mem_src(&args, buf, len); - jpeg_read_header(&info, 1); - jpeg_start_decompress(&info); - width = info.output_width; - height = info.output_height; + jpeg_read_header(&args, 1); + jpeg_start_decompress(&args); + width = args.output_width; + height = args.output_height; - return decodeJPEGIntoSurface(&info); + return decodeJPEGIntoSurface(&args); } /* @@ -874,19 +849,19 @@ Image::loadJPEG(FILE *stream) { if (data_mode == DATA_IMAGE) { // Can lazily read in the JPEG. // JPEG setup - struct jpeg_decompress_struct info; + struct jpeg_decompress_struct args; struct jpeg_error_mgr err; - info.err = jpeg_std_error(&err); - jpeg_create_decompress(&info); + args.err = jpeg_std_error(&err); + jpeg_create_decompress(&args); - jpeg_stdio_src(&info, stream); + jpeg_stdio_src(&args, stream); - jpeg_read_header(&info, 1); - jpeg_start_decompress(&info); - width = info.output_width; - height = info.output_height; + jpeg_read_header(&args, 1); + jpeg_start_decompress(&args); + width = args.output_width; + height = args.output_height; - status = decodeJPEGIntoSurface(&info); + status = decodeJPEGIntoSurface(&args); fclose(stream); } else { // We'll need the actual source jpeg data, so read fully. #if CAIRO_VERSION_MINOR >= 10 diff --git a/src/Image.h b/src/Image.h index adbb37f..9890f90 100644 --- a/src/Image.h +++ b/src/Image.h @@ -8,6 +8,7 @@ #ifndef __NODE_IMAGE_H__ #define __NODE_IMAGE_H__ +#include "nan.h" #include "Canvas.h" #ifdef HAVE_JPEG @@ -23,22 +24,22 @@ class Image: public node::ObjectWrap { public: char *filename; int width, height; - Persistent onload; - Persistent onerror; + NanCallback *onload; + NanCallback *onerror; static Persistent constructor; static void Initialize(Handle target); - static Handle New(const Arguments &args); - static Handle GetSource(Local prop, const AccessorInfo &info); - static Handle GetOnload(Local prop, const AccessorInfo &info); - static Handle GetOnerror(Local prop, const AccessorInfo &info); - static Handle GetComplete(Local prop, const AccessorInfo &info); - static Handle GetWidth(Local prop, const AccessorInfo &info); - static Handle GetHeight(Local prop, const AccessorInfo &info); - static Handle GetDataMode(Local prop, const AccessorInfo &info); - static void SetSource(Local prop, Local val, const AccessorInfo &info); - static void SetOnload(Local prop, Local val, const AccessorInfo &info); - static void SetOnerror(Local prop, Local val, const AccessorInfo &info); - static void SetDataMode(Local prop, Local val, const AccessorInfo &info); + static NAN_METHOD(New); + static NAN_GETTER(GetSource); + static NAN_GETTER(GetOnload); + static NAN_GETTER(GetOnerror); + static NAN_GETTER(GetComplete); + static NAN_GETTER(GetWidth); + static NAN_GETTER(GetHeight); + static NAN_GETTER(GetDataMode); + static NAN_SETTER(SetSource); + static NAN_SETTER(SetOnload); + static NAN_SETTER(SetOnerror); + static NAN_SETTER(SetDataMode); inline cairo_surface_t *surface(){ return _surface; } inline uint8_t *data(){ return cairo_image_surface_get_data(_surface); } inline int stride(){ return cairo_image_surface_get_stride(_surface); } diff --git a/src/ImageData.cc b/src/ImageData.cc index ae92dda..0694917 100644 --- a/src/ImageData.cc +++ b/src/ImageData.cc @@ -15,59 +15,55 @@ Persistent ImageData::constructor; void ImageData::Initialize(Handle target) { - HandleScope scope; + NanScope(); // Constructor - #if NODE_VERSION_AT_LEAST(0, 11, 3) - constructor = Persistent::New(Isolate::GetCurrent(), FunctionTemplate::New(ImageData::New)); - #else - constructor = Persistent::New(FunctionTemplate::New(ImageData::New)); - #endif - constructor->InstanceTemplate()->SetInternalFieldCount(1); - constructor->SetClassName(String::NewSymbol("ImageData")); + Local ctor = FunctionTemplate::New(ImageData::New); + NanAssignPersistent(FunctionTemplate, constructor, ctor); + ctor->InstanceTemplate()->SetInternalFieldCount(1); + ctor->SetClassName(NanSymbol("ImageData")); // Prototype - Local proto = constructor->PrototypeTemplate(); - proto->SetAccessor(String::NewSymbol("width"), GetWidth); - proto->SetAccessor(String::NewSymbol("height"), GetHeight); - target->Set(String::NewSymbol("ImageData"), constructor->GetFunction()); + Local proto = ctor->PrototypeTemplate(); + proto->SetAccessor(NanSymbol("width"), GetWidth); + proto->SetAccessor(NanSymbol("height"), GetHeight); + target->Set(NanSymbol("ImageData"), ctor->GetFunction()); } /* * Initialize a new ImageData object. */ -Handle -ImageData::New(const Arguments &args) { - HandleScope scope; +NAN_METHOD(ImageData::New) { + NanScope(); Local obj = args[0]->ToObject(); - if (!PixelArray::constructor->HasInstance(obj)) - return ThrowException(Exception::TypeError(String::New("CanvasPixelArray expected"))); + if (!NanHasInstance(PixelArray::constructor, obj)) + return NanThrowTypeError("CanvasPixelArray expected"); PixelArray *arr = ObjectWrap::Unwrap(obj); ImageData *imageData = new ImageData(arr); - args.This()->Set(String::NewSymbol("data"), args[0]); + args.This()->Set(NanSymbol("data"), args[0]); imageData->Wrap(args.This()); - return args.This(); + NanReturnValue(args.This()); } /* * Get width. */ -Handle -ImageData::GetWidth(Local prop, const AccessorInfo &info) { - ImageData *imageData = ObjectWrap::Unwrap(info.This()); - return Number::New(imageData->pixelArray()->width()); +NAN_GETTER(ImageData::GetWidth) { + NanScope(); + ImageData *imageData = ObjectWrap::Unwrap(args.This()); + NanReturnValue(Number::New(imageData->pixelArray()->width())); } /* * Get height. */ -Handle -ImageData::GetHeight(Local prop, const AccessorInfo &info) { - ImageData *imageData = ObjectWrap::Unwrap(info.This()); - return Number::New(imageData->pixelArray()->height()); +NAN_GETTER(ImageData::GetHeight) { + NanScope(); + ImageData *imageData = ObjectWrap::Unwrap(args.This()); + NanReturnValue(Number::New(imageData->pixelArray()->height())); } diff --git a/src/ImageData.h b/src/ImageData.h index 2ec51c9..150f662 100644 --- a/src/ImageData.h +++ b/src/ImageData.h @@ -16,9 +16,9 @@ class ImageData: public node::ObjectWrap { public: static Persistent constructor; static void Initialize(Handle target); - static Handle New(const Arguments &args); - static Handle GetWidth(Local prop, const AccessorInfo &info); - static Handle GetHeight(Local prop, const AccessorInfo &info); + static NAN_METHOD(New); + static NAN_GETTER(GetWidth); + static NAN_GETTER(GetHeight); inline PixelArray *pixelArray(){ return _arr; } ImageData(PixelArray *arr): _arr(arr) {} private: diff --git a/src/JPEGStream.h b/src/JPEGStream.h index a008c07..e32e1a1 100644 --- a/src/JPEGStream.h +++ b/src/JPEGStream.h @@ -6,6 +6,7 @@ #ifndef __NODE_JPEG_STREAM_H__ #define __NODE_JPEG_STREAM_H__ +#include "nan.h" #include "Canvas.h" #include #include @@ -30,20 +31,10 @@ init_closure_destination(j_compress_ptr cinfo){ boolean empty_closure_output_buffer(j_compress_ptr cinfo){ closure_destination_mgr *dest = (closure_destination_mgr *) cinfo->dest; - #if NODE_VERSION_AT_LEAST(0, 11, 3) - Local buf = Buffer::New(dest->bufsize); - memcpy(Buffer::Data(buf), dest->buffer, dest->bufsize); - #else - Local buf = Buffer::New(dest->bufsize); - memcpy(Buffer::Data(buf->handle_), dest->buffer, dest->bufsize); - #endif + Local buf = NanNewBufferHandle((char *)dest->buffer, dest->bufsize); Local argv[3] = { Local::New(Null()) - #if NODE_VERSION_AT_LEAST(0, 11, 3) - , Local::New(buf) - #else - , Local::New(buf->handle_) - #endif + , Local::New(buf) , Integer::New(dest->bufsize) }; dest->closure->fn->Call(Context::GetCurrent()->Global(), 3, argv); @@ -57,21 +48,11 @@ term_closure_destination(j_compress_ptr cinfo){ closure_destination_mgr *dest = (closure_destination_mgr *) cinfo->dest; /* emit remaining data */ size_t remaining = dest->bufsize - cinfo->dest->free_in_buffer; - #if NODE_VERSION_AT_LEAST(0, 11, 3) - Local buf = Buffer::New(remaining); - memcpy(Buffer::Data(buf), dest->buffer, remaining); - #else - Local buf = Buffer::New(remaining); - memcpy(Buffer::Data(buf->handle_), dest->buffer, remaining); - #endif + Local buf = NanNewBufferHandle((char *)dest->buffer, remaining); Local data_argv[3] = { Local::New(Null()) - #if NODE_VERSION_AT_LEAST(0, 11, 3) - , Local::New(buf) - #else - , Local::New(buf->handle_) - #endif + , Local::New(buf) , Integer::New(remaining) }; diff --git a/src/PixelArray.cc b/src/PixelArray.cc index fc0c348..4abc181 100644 --- a/src/PixelArray.cc +++ b/src/PixelArray.cc @@ -9,6 +9,8 @@ #include #include +#include "nan.h" + Persistent PixelArray::constructor; /* @@ -17,30 +19,26 @@ Persistent PixelArray::constructor; void PixelArray::Initialize(Handle target) { - HandleScope scope; + NanScope(); // Constructor - #if NODE_VERSION_AT_LEAST(0, 11, 3) - constructor = Persistent::New(Isolate::GetCurrent(), FunctionTemplate::New(PixelArray::New)); - #else - constructor = Persistent::New(FunctionTemplate::New(PixelArray::New)); - #endif - constructor->InstanceTemplate()->SetInternalFieldCount(1); - constructor->SetClassName(String::NewSymbol("CanvasPixelArray")); + Local ctor = FunctionTemplate::New(PixelArray::New); + NanAssignPersistent(FunctionTemplate, constructor, ctor); + ctor->InstanceTemplate()->SetInternalFieldCount(1); + ctor->SetClassName(NanSymbol("CanvasPixelArray")); // Prototype - Local proto = constructor->InstanceTemplate(); - proto->SetAccessor(String::NewSymbol("length"), GetLength); - target->Set(String::NewSymbol("CanvasPixelArray"), constructor->GetFunction()); + Local proto = ctor->InstanceTemplate(); + proto->SetAccessor(NanSymbol("length"), GetLength); + target->Set(NanSymbol("CanvasPixelArray"), ctor->GetFunction()); } /* * Initialize a new PixelArray. */ -Handle -PixelArray::New(const Arguments &args) { - HandleScope scope; +NAN_METHOD(PixelArray::New) { + NanScope(); PixelArray *arr; Local obj = args[0]->ToObject(); @@ -53,8 +51,8 @@ PixelArray::New(const Arguments &args) { break; // canvas, x, y, width, height case 5: { - if (!Canvas::constructor->HasInstance(obj)) - return ThrowException(Exception::TypeError(String::New("Canvas expected"))); + if (!NanHasInstance(Canvas::constructor, obj)) + return NanThrowTypeError("Canvas expected"); Canvas *canvas = ObjectWrap::Unwrap(obj); arr = new PixelArray( @@ -66,7 +64,7 @@ PixelArray::New(const Arguments &args) { } break; default: - return ThrowException(Exception::TypeError(String::New("invalid arguments"))); + return NanThrowTypeError("invalid arguments"); } // Let v8 handle accessors (and clamping) @@ -75,17 +73,16 @@ PixelArray::New(const Arguments &args) { , arr->length()); arr->Wrap(args.This()); - return args.This(); + NanReturnValue(args.This()); } /* * Get length. */ -Handle -PixelArray::GetLength(Local prop, const AccessorInfo &info) { - HandleScope scope; - return scope.Close(Number::New(info.This()->GetIndexedPropertiesPixelDataLength())); +NAN_GETTER(PixelArray::GetLength) { + NanScope(); + NanReturnValue(Number::New(args.This()->GetIndexedPropertiesPixelDataLength())); } /* diff --git a/src/PixelArray.h b/src/PixelArray.h index b03d2fd..21e68f1 100644 --- a/src/PixelArray.h +++ b/src/PixelArray.h @@ -14,8 +14,8 @@ class PixelArray: public node::ObjectWrap { public: static Persistent constructor; static void Initialize(Handle target); - static Handle New(const Arguments &args); - static Handle GetLength(Local prop, const AccessorInfo &info); + static NAN_METHOD(New); + static NAN_GETTER(GetLength); inline int length(){ return _width * _height * 4; } inline int width(){ return _width; } inline int height(){ return _height; } diff --git a/src/closure.h b/src/closure.h index b044dc6..49ec8e2 100644 --- a/src/closure.h +++ b/src/closure.h @@ -8,12 +8,14 @@ #ifndef __NODE_CLOSURE_H__ #define __NODE_CLOSURE_H__ +#include "nan.h" + /* * PNG stream closure. */ typedef struct { - Persistent pfn; + NanCallback *pfn; Handle fn; unsigned len; unsigned max_len; diff --git a/src/nan.h b/src/nan.h new file mode 100644 index 0000000..ead7d65 --- /dev/null +++ b/src/nan.h @@ -0,0 +1,344 @@ +/********************************************************************************** + * NAN - Native Abstractions for Node.js + * + * Copyright (c) 2013 Rod Vagg + * MIT +no-false-attribs License + * + * Version 0.1.0 (current Node unstable: 0.11.4) + * + * Changelog: + * * 0.1.0 Jul 21 2013 + * - Added `NAN_GETTER`, `NAN_SETTER` + * - Added `NanThrowError` with single Local argument + * - Added `NanNewBufferHandle` with single uint32_t argument + * - Added `NanHasInstance(Persistent&, Handle)` + * - Added `Local NanCallback#GetFunction()` + * - Added `NanCallback#Call(int, Local[])` + * - Deprecated `NanCallback#Run(int, Local[])` in favour of Call + * + * See https://github.com/rvagg/nan for the latest update to this file + **********************************************************************************/ + +#ifndef NAN_H +#define NAN_H + +#include +#include + +// some generic helpers + +#define NanSymbol(value) v8::String::NewSymbol(value) + +static inline char* NanFromV8String(v8::Local from) { + size_t sz_; + char* to; + v8::Local toStr = from->ToString(); + sz_ = toStr->Utf8Length(); + to = new char[sz_ + 1]; + toStr->WriteUtf8(to, -1, NULL, v8::String::NO_OPTIONS); + return to; +} + +static inline bool NanBooleanOptionValue( + v8::Local optionsObj + , v8::Handle opt, bool def) { + + if (def) { + return optionsObj.IsEmpty() + || !optionsObj->Has(opt) + || optionsObj->Get(opt)->BooleanValue(); + } else { + return !optionsObj.IsEmpty() + && optionsObj->Has(opt) + && optionsObj->Get(opt)->BooleanValue(); + } +} + +static inline bool NanBooleanOptionValue( + v8::Local optionsObj + , v8::Handle opt) { + return NanBooleanOptionValue(optionsObj, opt, false); +} + +static inline uint32_t NanUInt32OptionValue( + v8::Local optionsObj + , v8::Handle opt + , uint32_t def) { + + return !optionsObj.IsEmpty() + && optionsObj->Has(opt) + && optionsObj->Get(opt)->IsUint32() + ? optionsObj->Get(opt)->Uint32Value() + : def; +} + +#if (NODE_MODULE_VERSION > 0x000B) +// Node 0.11+ (0.11.3 and below won't compile with these) + +static v8::Isolate* nan_isolate = v8::Isolate::GetCurrent(); + +# define NAN_METHOD(name) \ + void name(const v8::FunctionCallbackInfo& args) +# define NAN_GETTER(name) \ + void name( \ + v8::Local property \ + , const v8::PropertyCallbackInfo& args) +# define NAN_SETTER(name) \ + void name( \ + v8::Local property \ + , v8::Local value \ + , const v8::PropertyCallbackInfo& args) + +# define NanScope() v8::HandleScope scope(nan_isolate) +# define NanReturnValue(value) return args.GetReturnValue().Set(value); +# define NanReturnUndefined() return; +# define NanAssignPersistent(type, handle, obj) handle.Reset(nan_isolate, obj); +# define NanObjectWrapHandle(obj) obj->handle() + +# define THROW_ERROR(fun, errmsg) \ + do { \ + NanScope(); \ + v8::ThrowException(fun(v8::String::New(errmsg))); \ + } while (0); + + inline static void NanThrowError(const char* errmsg) { + THROW_ERROR(v8::Exception::Error, errmsg); + } + + inline static void NanThrowError(v8::Local error) { + NanScope(); + v8::ThrowException(error); + } + + inline static void NanThrowTypeError(const char* errmsg) { + THROW_ERROR(v8::Exception::TypeError, errmsg); + } + + inline static void NanThrowRangeError(const char* errmsg) { + THROW_ERROR(v8::Exception::RangeError, errmsg); + } + + static inline void NanDispose(v8::Persistent &handle) { + handle.Dispose(nan_isolate); + } + + static inline v8::Local NanNewBufferHandle ( + char *data, uint32_t size) { + return node::Buffer::New(data, size); + } + + static inline v8::Local NanNewBufferHandle (uint32_t size) { + return node::Buffer::New(size); + } + + template + inline v8::Local NanPersistentToLocal( + const v8::Persistent& persistent) { + if (persistent.IsWeak()) { + return v8::Local::New(nan_isolate, persistent); + } else { + return *reinterpret_cast*>( + const_cast*>(&persistent)); + } + } + + inline bool NanHasInstance( + v8::Persistent& function_template + , v8::Handle value) { + return NanPersistentToLocal(function_template)->HasInstance(value); + } + +#else +// Node 0.8 and 0.10 + +# define NAN_METHOD(name) \ + v8::Handle name(const v8::Arguments& args) +# define NAN_GETTER(name) \ + v8::Handle name( \ + v8::Local property \ + , const v8::AccessorInfo &args) +# define NAN_SETTER(name) \ + void name( \ + v8::Local property \ + , v8::Local value \ + , const v8::AccessorInfo &args) + +# define NanScope() v8::HandleScope scope +# define NanReturnValue(value) return scope.Close(value); +# define NanReturnUndefined() return v8::Undefined(); +# define NanAssignPersistent(type, handle, obj) \ + handle = v8::Persistent::New(obj); +# define NanObjectWrapHandle(obj) obj->handle_ + +# define THROW_ERROR(fun, errmsg) \ + do { \ + NanScope(); \ + return v8::ThrowException(fun(v8::String::New(errmsg))); \ + } while (0); + + inline static v8::Handle NanThrowError(const char* errmsg) { + THROW_ERROR(v8::Exception::Error, errmsg); + } + + inline static v8::Handle NanThrowError( + v8::Local error) { + NanScope(); + return v8::ThrowException(error); + } + + inline static v8::Handle NanThrowTypeError(const char* errmsg) { + THROW_ERROR(v8::Exception::TypeError, errmsg); + } + + inline static v8::Handle NanThrowRangeError(const char* errmsg) { + THROW_ERROR(v8::Exception::RangeError, errmsg); + } + + static inline void NanDispose(v8::Persistent &handle) { + handle.Dispose(); + } + + static inline v8::Local NanNewBufferHandle ( + char *data, uint32_t size) { + return v8::Local::New(node::Buffer::New(data, size)->handle_); + } + + template + inline v8::Local NanPersistentToLocal( + const v8::Persistent& persistent) { + if (persistent.IsWeak()) { + return v8::Local::New(persistent); + } else { + return *reinterpret_cast*>( + const_cast*>(&persistent)); + } + } + + inline bool NanHasInstance( + v8::Persistent& function_template + , v8::Handle value) { + return function_template->HasInstance(value); + } + +#endif // node version + +class NanCallback { + public: + NanCallback(const v8::Local &fn) { + NanScope(); + v8::Local obj = v8::Object::New(); + obj->Set(NanSymbol("callback"), fn); + NanAssignPersistent(v8::Object, handle, obj); + } + + ~NanCallback() { + if (handle.IsEmpty()) return; + handle.Dispose(); + } + + v8::Local GetFunction () { + NanScope(); + return NanPersistentToLocal(handle).As(); + } + + // deprecated + void Run(int argc, v8::Local argv[]) { + Call(argc, argv); + } + + void Call(int argc, v8::Local argv[]) { + NanScope(); + v8::Local callback = NanPersistentToLocal(handle)-> + Get(NanSymbol("callback")).As(); + v8::TryCatch try_catch; + callback->Call(v8::Context::GetCurrent()->Global(), argc, argv); + if (try_catch.HasCaught()) { + node::FatalException(try_catch); + } + } + + private: + v8::Persistent handle; +}; + +/* abstract */ class NanAsyncWorker { +public: + NanAsyncWorker (NanCallback *callback) : callback(callback) { + request.data = this; + errmsg = NULL; + } + + virtual ~NanAsyncWorker () { + if (!persistentHandle.IsEmpty()) + NanDispose(persistentHandle); + if (callback) + delete callback; + } + + virtual void WorkComplete () { + NanScope(); + + if (errmsg == NULL) + HandleOKCallback(); + else + HandleErrorCallback(); + delete callback; + callback = NULL; + } + + virtual void Execute () =0; + + uv_work_t request; + +protected: + v8::Persistent persistentHandle; + NanCallback *callback; + const char *errmsg; + + void SavePersistent(const char *key, v8::Local &obj) { + v8::Local handle = NanPersistentToLocal(persistentHandle); + handle->Set(NanSymbol(key), obj); + } + + v8::Local GetFromPersistent(const char *key) { + v8::Local handle = NanPersistentToLocal(persistentHandle); + return handle->Get(NanSymbol(key)).As(); + } + + virtual void HandleOKCallback () { + NanScope(); + + callback->Call(0, NULL); + }; + + virtual void HandleErrorCallback () { + NanScope(); + + v8::Local argv[] = { + v8::Exception::Error(v8::String::New(errmsg)) + }; + callback->Call(1, argv); + } +}; + +inline void NanAsyncExecute (uv_work_t* req) { + NanAsyncWorker *worker = static_cast(req->data); + worker->Execute(); +} + +inline void NanAsyncExecuteComplete (uv_work_t* req) { + NanAsyncWorker* worker = static_cast(req->data); + worker->WorkComplete(); + delete worker; +} + +inline void NanAsyncQueueWorker (NanAsyncWorker* worker) { + uv_queue_work( + uv_default_loop() + , &worker->request + , NanAsyncExecute + , (uv_after_work_cb)NanAsyncExecuteComplete + ); +} + +#endif