Browse Source

0.11.4+ compatibility using NAN

See https://github.com/rvagg/nan
v1.x
Rod Vagg 11 years ago
committed by TJ Holowaychuk
parent
commit
2354d9bb8c
  1. 199
      src/Canvas.cc
  2. 20
      src/Canvas.h
  3. 41
      src/CanvasGradient.cc
  4. 5
      src/CanvasGradient.h
  5. 31
      src/CanvasPattern.cc
  6. 3
      src/CanvasPattern.h
  7. 727
      src/CanvasRenderingContext2d.cc
  8. 136
      src/CanvasRenderingContext2d.h
  9. 32
      src/FontFace.cc
  10. 2
      src/FontFace.h
  11. 265
      src/Image.cc
  12. 29
      src/Image.h
  13. 50
      src/ImageData.cc
  14. 6
      src/ImageData.h
  15. 29
      src/JPEGStream.h
  16. 41
      src/PixelArray.cc
  17. 4
      src/PixelArray.h
  18. 4
      src/closure.h
  19. 344
      src/nan.h

199
src/Canvas.cc

@ -26,37 +26,33 @@ Persistent<FunctionTemplate> Canvas::constructor;
void
Canvas::Initialize(Handle<Object> target) {
HandleScope scope;
NanScope();
// Constructor
#if NODE_VERSION_AT_LEAST(0, 11, 3)
constructor = Persistent<FunctionTemplate>::New(Isolate::GetCurrent(), FunctionTemplate::New(Canvas::New));
#else
constructor = Persistent<FunctionTemplate>::New(FunctionTemplate::New(Canvas::New));
#endif
constructor->InstanceTemplate()->SetInternalFieldCount(1);
constructor->SetClassName(String::NewSymbol("Canvas"));
Local<FunctionTemplate> ctor = FunctionTemplate::New(Canvas::New);
NanAssignPersistent(FunctionTemplate, constructor, ctor);
ctor->InstanceTemplate()->SetInternalFieldCount(1);
ctor->SetClassName(NanSymbol("Canvas"));
// Prototype
Local<ObjectTemplate> proto = constructor->PrototypeTemplate();
NODE_SET_PROTOTYPE_METHOD(constructor, "toBuffer", ToBuffer);
NODE_SET_PROTOTYPE_METHOD(constructor, "streamPNGSync", StreamPNGSync);
Local<ObjectTemplate> 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<Value>
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<Value>
Canvas::GetType(Local<String> prop, const AccessorInfo &info) {
HandleScope scope;
Canvas *canvas = ObjectWrap::Unwrap<Canvas>(info.This());
return scope.Close(String::New(canvas->isPDF() ? "pdf" : "image"));
NAN_GETTER(Canvas::GetType) {
NanScope();
Canvas *canvas = ObjectWrap::Unwrap<Canvas>(args.This());
NanReturnValue(String::New(canvas->isPDF() ? "pdf" : "image"));
}
/*
* Get width.
*/
Handle<Value>
Canvas::GetWidth(Local<String> prop, const AccessorInfo &info) {
HandleScope scope;
Canvas *canvas = ObjectWrap::Unwrap<Canvas>(info.This());
return scope.Close(Number::New(canvas->width));
NAN_GETTER(Canvas::GetWidth) {
NanScope();
Canvas *canvas = ObjectWrap::Unwrap<Canvas>(args.This());
NanReturnValue(Number::New(canvas->width));
}
/*
* Set width.
*/
void
Canvas::SetWidth(Local<String> prop, Local<Value> val, const AccessorInfo &info) {
if (val->IsNumber()) {
Canvas *canvas = ObjectWrap::Unwrap<Canvas>(info.This());
canvas->width = val->Uint32Value();
canvas->resurface(info.This());
NAN_SETTER(Canvas::SetWidth) {
NanScope();
if (value->IsNumber()) {
Canvas *canvas = ObjectWrap::Unwrap<Canvas>(args.This());
canvas->width = value->Uint32Value();
canvas->resurface(args.This());
}
}
@ -108,23 +102,22 @@ Canvas::SetWidth(Local<String> prop, Local<Value> val, const AccessorInfo &info)
* Get height.
*/
Handle<Value>
Canvas::GetHeight(Local<String> prop, const AccessorInfo &info) {
HandleScope scope;
Canvas *canvas = ObjectWrap::Unwrap<Canvas>(info.This());
return scope.Close(Number::New(canvas->height));
NAN_GETTER(Canvas::GetHeight) {
NanScope();
Canvas *canvas = ObjectWrap::Unwrap<Canvas>(args.This());
NanReturnValue(Number::New(canvas->height));
}
/*
* Set height.
*/
void
Canvas::SetHeight(Local<String> prop, Local<Value> val, const AccessorInfo &info) {
if (val->IsNumber()) {
Canvas *canvas = ObjectWrap::Unwrap<Canvas>(info.This());
canvas->height = val->Uint32Value();
canvas->resurface(info.This());
NAN_SETTER(Canvas::SetHeight) {
NanScope();
if (value->IsNumber()) {
Canvas *canvas = ObjectWrap::Unwrap<Canvas>(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<Value> 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<Object> buf = Buffer::New(closure->len);
#else
Buffer *buf = Buffer::New(closure->len);
#endif
Local<Object> buf = NanNewBufferHandle((char*)closure->data, closure->len);
memcpy(Buffer::Data(buf), closure->data, closure->len);
#if NODE_VERSION_AT_LEAST(0, 11, 3)
Local<Value> argv[2] = { Local<Value>::New(Null()), Local<Value>::New(buf) };
#else
Local<Value> argv[2] = { Local<Value>::New(Null()), Local<Value>::New(buf->handle_) };
#endif
closure->pfn->Call(Context::GetCurrent()->Global(), 2, argv);
Local<Value> argv[2] = { Local<Value>::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<Value>
Canvas::ToBuffer(const Arguments &args) {
HandleScope scope;
NAN_METHOD(Canvas::ToBuffer) {
NanScope();
cairo_status_t status;
Canvas *canvas = ObjectWrap::Unwrap<Canvas>(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<Object> 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<Object> 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<Function>::New(Isolate::GetCurrent(), Handle<Function>::Cast(args[0]));
#else
closure->pfn = Persistent<Function>::New(Handle<Function>::Cast(args[0]));
#endif
closure->pfn = new NanCallback(args[0].As<Function>());
#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<Object> buf = Buffer::New(closure.len);
#else
Buffer *buf = Buffer::New(closure.len);
#endif
memcpy(Buffer::Data(buf), closure.data, closure.len);
Local<Object> 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<Object> buf = Buffer::New(len);
memcpy(Buffer::Data(buf), data, len);
#else
Local<Buffer> buf = Buffer::New(len);
memcpy(Buffer::Data(buf->handle_), data, len);
#endif
Local<Object> buf = NanNewBufferHandle((char *)data, len);
Local<Value> argv[3] = {
Local<Value>::New(Null())
#if NODE_VERSION_AT_LEAST(0, 11, 3)
, Local<Value>::New(buf)
#else
, Local<Value>::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<Value>
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<Canvas>(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<Value> 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<Value>
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<Canvas>(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

20
src/Canvas.h

@ -19,6 +19,8 @@
#include <cairo/cairo.h>
#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<FunctionTemplate> constructor;
static void Initialize(Handle<Object> target);
static Handle<Value> New(const Arguments &args);
static Handle<Value> ToBuffer(const Arguments &args);
static Handle<Value> GetType(Local<String> prop, const AccessorInfo &info);
static Handle<Value> GetWidth(Local<String> prop, const AccessorInfo &info);
static Handle<Value> GetHeight(Local<String> prop, const AccessorInfo &info);
static void SetWidth(Local<String> prop, Local<Value> val, const AccessorInfo &info);
static void SetHeight(Local<String> prop, Local<Value> val, const AccessorInfo &info);
static Handle<Value> StreamPNGSync(const Arguments &args);
static Handle<Value> 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<Value> Error(cairo_status_t status);
#if NODE_VERSION_AT_LEAST(0, 6, 0)
static void ToBufferAsync(uv_work_t *req);

41
src/CanvasGradient.cc

@ -17,29 +17,25 @@ Persistent<FunctionTemplate> Gradient::constructor;
void
Gradient::Initialize(Handle<Object> target) {
HandleScope scope;
NanScope();
// Constructor
#if NODE_VERSION_AT_LEAST(0, 11, 3)
constructor = Persistent<FunctionTemplate>::New(Isolate::GetCurrent(), FunctionTemplate::New(Gradient::New));
#else
constructor = Persistent<FunctionTemplate>::New(FunctionTemplate::New(Gradient::New));
#endif
constructor->InstanceTemplate()->SetInternalFieldCount(1);
constructor->SetClassName(String::NewSymbol("CanvasGradient"));
Local<FunctionTemplate> 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<Value>
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<Value>
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<Gradient>(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();
}
/*

5
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<FunctionTemplate> constructor;
static void Initialize(Handle<Object> target);
static Handle<Value> New(const Arguments &args);
static Handle<Value> 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; }

31
src/CanvasPattern.cc

@ -20,25 +20,24 @@ Pattern::Initialize(Handle<Object> target) {
HandleScope scope;
// Constructor
#if NODE_VERSION_AT_LEAST(0, 11, 3)
constructor = Persistent<FunctionTemplate>::New(Isolate::GetCurrent(), FunctionTemplate::New(Pattern::New));
#else
constructor = Persistent<FunctionTemplate>::New(FunctionTemplate::New(Pattern::New));
#endif
constructor->InstanceTemplate()->SetInternalFieldCount(1);
constructor->SetClassName(String::NewSymbol("CanvasPattern"));
Local<FunctionTemplate> 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<Value>
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<Object> obj = args[0]->ToObject();
// Image
if (Image::constructor->HasInstance(obj)) {
if (NanHasInstance(Image::constructor, obj)) {
Image *img = ObjectWrap::Unwrap<Image>(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<Canvas>(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());
}

3
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<FunctionTemplate> constructor;
static void Initialize(Handle<Object> target);
static Handle<Value> New(const Arguments &args);
static NAN_METHOD(New);
Pattern(cairo_surface_t *surface, int w, int h);
inline cairo_pattern_t *pattern(){ return _pattern; }

727
src/CanvasRenderingContext2d.cc

File diff suppressed because it is too large

136
src/CanvasRenderingContext2d.h

@ -71,76 +71,76 @@ class Context2d: public node::ObjectWrap {
Context2d(Canvas *canvas);
static Persistent<FunctionTemplate> constructor;
static void Initialize(Handle<Object> target);
static Handle<Value> New(const Arguments &args);
static Handle<Value> DrawImage(const Arguments &args);
static Handle<Value> PutImageData(const Arguments &args);
static Handle<Value> Save(const Arguments &args);
static Handle<Value> Restore(const Arguments &args);
static Handle<Value> Rotate(const Arguments &args);
static Handle<Value> Translate(const Arguments &args);
static Handle<Value> Scale(const Arguments &args);
static Handle<Value> Transform(const Arguments &args);
static Handle<Value> ResetTransform(const Arguments &args);
static Handle<Value> IsPointInPath(const Arguments &args);
static Handle<Value> BeginPath(const Arguments &args);
static Handle<Value> ClosePath(const Arguments &args);
static Handle<Value> AddPage(const Arguments &args);
static Handle<Value> Clip(const Arguments &args);
static Handle<Value> Fill(const Arguments &args);
static Handle<Value> Stroke(const Arguments &args);
static Handle<Value> FillText(const Arguments &args);
static Handle<Value> StrokeText(const Arguments &args);
static Handle<Value> 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<Value> SetFontFace(const Arguments &args);
static NAN_METHOD(SetFontFace);
#endif
static Handle<Value> SetFillColor(const Arguments &args);
static Handle<Value> SetStrokeColor(const Arguments &args);
static Handle<Value> SetFillPattern(const Arguments &args);
static Handle<Value> SetStrokePattern(const Arguments &args);
static Handle<Value> SetTextBaseline(const Arguments &args);
static Handle<Value> SetTextAlignment(const Arguments &args);
static Handle<Value> MeasureText(const Arguments &args);
static Handle<Value> BezierCurveTo(const Arguments &args);
static Handle<Value> QuadraticCurveTo(const Arguments &args);
static Handle<Value> LineTo(const Arguments &args);
static Handle<Value> MoveTo(const Arguments &args);
static Handle<Value> FillRect(const Arguments &args);
static Handle<Value> StrokeRect(const Arguments &args);
static Handle<Value> ClearRect(const Arguments &args);
static Handle<Value> Rect(const Arguments &args);
static Handle<Value> Arc(const Arguments &args);
static Handle<Value> ArcTo(const Arguments &args);
static Handle<Value> GetPatternQuality(Local<String> prop, const AccessorInfo &info);
static Handle<Value> GetGlobalCompositeOperation(Local<String> prop, const AccessorInfo &info);
static Handle<Value> GetGlobalAlpha(Local<String> prop, const AccessorInfo &info);
static Handle<Value> GetShadowColor(Local<String> prop, const AccessorInfo &info);
static Handle<Value> GetFillColor(Local<String> prop, const AccessorInfo &info);
static Handle<Value> GetStrokeColor(Local<String> prop, const AccessorInfo &info);
static Handle<Value> GetMiterLimit(Local<String> prop, const AccessorInfo &info);
static Handle<Value> GetLineCap(Local<String> prop, const AccessorInfo &info);
static Handle<Value> GetLineJoin(Local<String> prop, const AccessorInfo &info);
static Handle<Value> GetLineWidth(Local<String> prop, const AccessorInfo &info);
static Handle<Value> GetShadowOffsetX(Local<String> prop, const AccessorInfo &info);
static Handle<Value> GetShadowOffsetY(Local<String> prop, const AccessorInfo &info);
static Handle<Value> GetShadowBlur(Local<String> prop, const AccessorInfo &info);
static Handle<Value> GetAntiAlias(Local<String> prop, const AccessorInfo &info);
static Handle<Value> GetTextDrawingMode(Local<String> prop, const AccessorInfo &info);
static Handle<Value> GetFilter(Local<String> prop, const AccessorInfo &info);
static void SetPatternQuality(Local<String> prop, Local<Value> val, const AccessorInfo &info);
static void SetGlobalCompositeOperation(Local<String> prop, Local<Value> val, const AccessorInfo &info);
static void SetGlobalAlpha(Local<String> prop, Local<Value> val, const AccessorInfo &info);
static void SetShadowColor(Local<String> prop, Local<Value> val, const AccessorInfo &info);
static void SetMiterLimit(Local<String> prop, Local<Value> val, const AccessorInfo &info);
static void SetLineCap(Local<String> prop, Local<Value> val, const AccessorInfo &info);
static void SetLineJoin(Local<String> prop, Local<Value> val, const AccessorInfo &info);
static void SetLineWidth(Local<String> prop, Local<Value> val, const AccessorInfo &info);
static void SetShadowOffsetX(Local<String> prop, Local<Value> val, const AccessorInfo &info);
static void SetShadowOffsetY(Local<String> prop, Local<Value> val, const AccessorInfo &info);
static void SetShadowBlur(Local<String> prop, Local<Value> val, const AccessorInfo &info);
static void SetAntiAlias(Local<String> prop, Local<Value> val, const AccessorInfo &info);
static void SetTextDrawingMode(Local<String> prop, Local<Value> val, const AccessorInfo &info);
static void SetFilter(Local<String> prop, Local<Value> 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; }

32
src/FontFace.cc

@ -6,6 +6,8 @@
#include "FontFace.h"
#include "nan.h"
Persistent<FunctionTemplate> FontFace::constructor;
/*
@ -25,19 +27,16 @@ FontFace::~FontFace() {
void
FontFace::Initialize(Handle<Object> target) {
HandleScope scope;
NanScope();
// Constructor
#if NODE_VERSION_AT_LEAST(0, 11, 3)
constructor = Persistent<FunctionTemplate>::New(Isolate::GetCurrent(), FunctionTemplate::New(FontFace::New));
#else
constructor = Persistent<FunctionTemplate>::New(FunctionTemplate::New(FontFace::New));
#endif
constructor->InstanceTemplate()->SetInternalFieldCount(1);
constructor->SetClassName(String::NewSymbol("FontFace"));
Local<FunctionTemplate> 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<Value>
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());
}

2
src/FontFace.h

@ -17,7 +17,7 @@ class FontFace: public node::ObjectWrap {
public:
static Persistent<FunctionTemplate> constructor;
static void Initialize(Handle<Object> target);
static Handle<Value> New(const Arguments &args);
static NAN_METHOD(New);
FontFace(FT_Face ftFace, cairo_font_face_t *crFace)
:_ftFace(ftFace), _crFace(crFace) {}

265
src/Image.cc

@ -19,8 +19,6 @@ typedef struct {
} gif_data_t;
#endif
Persistent<FunctionTemplate> Image::constructor;
/*
* Read closure used by loadFromBuffer.
*/
@ -30,61 +28,60 @@ typedef struct {
uint8_t *buf;
} read_closure_t;
Persistent<FunctionTemplate> Image::constructor;
/*
* Initialize Image.
*/
void
Image::Initialize(Handle<Object> target) {
HandleScope scope;
NanScope();
Local<FunctionTemplate> 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<FunctionTemplate>::New(Isolate::GetCurrent(), FunctionTemplate::New(Image::New));
#else
constructor = Persistent<FunctionTemplate>::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<ObjectTemplate> 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<ObjectTemplate> 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<Value>
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<Value>
Image::GetComplete(Local<String>, const AccessorInfo &info) {
HandleScope scope;
Image *img = ObjectWrap::Unwrap<Image>(info.This());
return scope.Close(Boolean::New(Image::COMPLETE == img->state));
NAN_GETTER(Image::GetComplete) {
NanScope();
Image *img = ObjectWrap::Unwrap<Image>(args.This());
NanReturnValue(Boolean::New(Image::COMPLETE == img->state));
}
#if CAIRO_VERSION_MINOR >= 10
@ -93,22 +90,20 @@ Image::GetComplete(Local<String>, const AccessorInfo &info) {
* Get dataMode.
*/
Handle<Value>
Image::GetDataMode(Local<String>, const AccessorInfo &info) {
HandleScope scope;
Image *img = ObjectWrap::Unwrap<Image>(info.This());
return scope.Close(Number::New(img->data_mode));
NAN_GETTER(Image::GetDataMode) {
NanScope();
Image *img = ObjectWrap::Unwrap<Image>(args.This());
NanReturnValue(Number::New(img->data_mode));
}
/*
* Set dataMode.
*/
void
Image::SetDataMode(Local<String>, Local<Value> val, const AccessorInfo &info) {
if (val->IsNumber()) {
Image *img = ObjectWrap::Unwrap<Image>(info.This());
int mode = val->Uint32Value();
NAN_SETTER(Image::SetDataMode) {
if (value->IsNumber()) {
Image *img = ObjectWrap::Unwrap<Image>(args.This());
int mode = value->Uint32Value();
img->data_mode = (data_mode_t) mode;
}
}
@ -119,32 +114,29 @@ Image::SetDataMode(Local<String>, Local<Value> val, const AccessorInfo &info) {
* Get width.
*/
Handle<Value>
Image::GetWidth(Local<String>, const AccessorInfo &info) {
HandleScope scope;
Image *img = ObjectWrap::Unwrap<Image>(info.This());
return scope.Close(Number::New(img->width));
NAN_GETTER(Image::GetWidth) {
NanScope();
Image *img = ObjectWrap::Unwrap<Image>(args.This());
NanReturnValue(Number::New(img->width));
}
/*
* Get height.
*/
Handle<Value>
Image::GetHeight(Local<String>, const AccessorInfo &info) {
HandleScope scope;
Image *img = ObjectWrap::Unwrap<Image>(info.This());
return scope.Close(Number::New(img->height));
NAN_GETTER(Image::GetHeight) {
NanScope();
Image *img = ObjectWrap::Unwrap<Image>(args.This());
NanReturnValue(Number::New(img->height));
}
/*
* Get src path.
*/
Handle<Value>
Image::GetSource(Local<String>, const AccessorInfo &info) {
HandleScope scope;
Image *img = ObjectWrap::Unwrap<Image>(info.This());
return scope.Close(String::New(img->filename ? img->filename : ""));
NAN_GETTER(Image::GetSource) {
NanScope();
Image *img = ObjectWrap::Unwrap<Image>(args.This());
NanReturnValue(String::New(img->filename ? img->filename : ""));
}
/*
@ -174,24 +166,23 @@ Image::clearData() {
* Set src path.
*/
void
Image::SetSource(Local<String>, Local<Value> val, const AccessorInfo &info) {
HandleScope scope;
Image *img = ObjectWrap::Unwrap<Image>(info.This());
NAN_SETTER(Image::SetSource) {
NanScope();
Image *img = ObjectWrap::Unwrap<Image>(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<Value>
Image::GetOnload(Local<String>, const AccessorInfo &info) {
Image *img = ObjectWrap::Unwrap<Image>(info.This());
return img->onload;
NAN_GETTER(Image::GetOnload) {
NanScope();
Image *img = ObjectWrap::Unwrap<Image>(args.This());
NanReturnValue(img->onload->GetFunction());
}
/*
* Set onload callback.
*/
void
Image::SetOnload(Local<String>, Local<Value> val, const AccessorInfo &info) {
if (val->IsFunction()) {
Image *img = ObjectWrap::Unwrap<Image>(info.This());
#if NODE_VERSION_AT_LEAST(0, 11, 3)
img->onload = Persistent<Function>::New(Isolate::GetCurrent(), Handle<Function>::Cast(val));
#else
img->onload = Persistent<Function>::New(Handle<Function>::Cast(val));
#endif
NAN_SETTER(Image::SetOnload) {
if (value->IsFunction()) {
Image *img = ObjectWrap::Unwrap<Image>(args.This());
img->onload = new NanCallback(value.As<Function>());
}
}
@ -290,25 +276,20 @@ Image::SetOnload(Local<String>, Local<Value> val, const AccessorInfo &info) {
* Get onerror callback.
*/
Handle<Value>
Image::GetOnerror(Local<String>, const AccessorInfo &info) {
Image *img = ObjectWrap::Unwrap<Image>(info.This());
return img->onerror;
NAN_GETTER(Image::GetOnerror) {
NanScope();
Image *img = ObjectWrap::Unwrap<Image>(args.This());
NanReturnValue(img->onerror->GetFunction());
}
/*
* Set onerror callback.
*/
void
Image::SetOnerror(Local<String>, Local<Value> val, const AccessorInfo &info) {
if (val->IsFunction()) {
Image *img = ObjectWrap::Unwrap<Image>(info.This());
#if NODE_VERSION_AT_LEAST(0, 11, 3)
img->onerror = Persistent<Function>::New(Isolate::GetCurrent(), Handle<Function>::Cast(val));
#else
img->onerror = Persistent<Function>::New(Handle<Function>::Cast(val));
#endif
NAN_SETTER(Image::SetOnerror) {
if (value->IsFunction()) {
Image *img = ObjectWrap::Unwrap<Image>(args.This());
img->onerror = new NanCallback(value.As<Function>());
}
}
@ -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<Value> err) {
HandleScope scope;
if (!onerror.IsEmpty()) {
NanScope();
if (onerror != NULL) {
Local<Value> 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

29
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<Function> onload;
Persistent<Function> onerror;
NanCallback *onload;
NanCallback *onerror;
static Persistent<FunctionTemplate> constructor;
static void Initialize(Handle<Object> target);
static Handle<Value> New(const Arguments &args);
static Handle<Value> GetSource(Local<String> prop, const AccessorInfo &info);
static Handle<Value> GetOnload(Local<String> prop, const AccessorInfo &info);
static Handle<Value> GetOnerror(Local<String> prop, const AccessorInfo &info);
static Handle<Value> GetComplete(Local<String> prop, const AccessorInfo &info);
static Handle<Value> GetWidth(Local<String> prop, const AccessorInfo &info);
static Handle<Value> GetHeight(Local<String> prop, const AccessorInfo &info);
static Handle<Value> GetDataMode(Local<String> prop, const AccessorInfo &info);
static void SetSource(Local<String> prop, Local<Value> val, const AccessorInfo &info);
static void SetOnload(Local<String> prop, Local<Value> val, const AccessorInfo &info);
static void SetOnerror(Local<String> prop, Local<Value> val, const AccessorInfo &info);
static void SetDataMode(Local<String> prop, Local<Value> 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); }

50
src/ImageData.cc

@ -15,59 +15,55 @@ Persistent<FunctionTemplate> ImageData::constructor;
void
ImageData::Initialize(Handle<Object> target) {
HandleScope scope;
NanScope();
// Constructor
#if NODE_VERSION_AT_LEAST(0, 11, 3)
constructor = Persistent<FunctionTemplate>::New(Isolate::GetCurrent(), FunctionTemplate::New(ImageData::New));
#else
constructor = Persistent<FunctionTemplate>::New(FunctionTemplate::New(ImageData::New));
#endif
constructor->InstanceTemplate()->SetInternalFieldCount(1);
constructor->SetClassName(String::NewSymbol("ImageData"));
Local<FunctionTemplate> ctor = FunctionTemplate::New(ImageData::New);
NanAssignPersistent(FunctionTemplate, constructor, ctor);
ctor->InstanceTemplate()->SetInternalFieldCount(1);
ctor->SetClassName(NanSymbol("ImageData"));
// Prototype
Local<ObjectTemplate> proto = constructor->PrototypeTemplate();
proto->SetAccessor(String::NewSymbol("width"), GetWidth);
proto->SetAccessor(String::NewSymbol("height"), GetHeight);
target->Set(String::NewSymbol("ImageData"), constructor->GetFunction());
Local<ObjectTemplate> 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<Value>
ImageData::New(const Arguments &args) {
HandleScope scope;
NAN_METHOD(ImageData::New) {
NanScope();
Local<Object> 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<PixelArray>(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<Value>
ImageData::GetWidth(Local<String> prop, const AccessorInfo &info) {
ImageData *imageData = ObjectWrap::Unwrap<ImageData>(info.This());
return Number::New(imageData->pixelArray()->width());
NAN_GETTER(ImageData::GetWidth) {
NanScope();
ImageData *imageData = ObjectWrap::Unwrap<ImageData>(args.This());
NanReturnValue(Number::New(imageData->pixelArray()->width()));
}
/*
* Get height.
*/
Handle<Value>
ImageData::GetHeight(Local<String> prop, const AccessorInfo &info) {
ImageData *imageData = ObjectWrap::Unwrap<ImageData>(info.This());
return Number::New(imageData->pixelArray()->height());
NAN_GETTER(ImageData::GetHeight) {
NanScope();
ImageData *imageData = ObjectWrap::Unwrap<ImageData>(args.This());
NanReturnValue(Number::New(imageData->pixelArray()->height()));
}

6
src/ImageData.h

@ -16,9 +16,9 @@ class ImageData: public node::ObjectWrap {
public:
static Persistent<FunctionTemplate> constructor;
static void Initialize(Handle<Object> target);
static Handle<Value> New(const Arguments &args);
static Handle<Value> GetWidth(Local<String> prop, const AccessorInfo &info);
static Handle<Value> GetHeight(Local<String> 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:

29
src/JPEGStream.h

@ -6,6 +6,7 @@
#ifndef __NODE_JPEG_STREAM_H__
#define __NODE_JPEG_STREAM_H__
#include "nan.h"
#include "Canvas.h"
#include <jpeglib.h>
#include <jerror.h>
@ -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<Object> buf = Buffer::New(dest->bufsize);
memcpy(Buffer::Data(buf), dest->buffer, dest->bufsize);
#else
Local<Buffer> buf = Buffer::New(dest->bufsize);
memcpy(Buffer::Data(buf->handle_), dest->buffer, dest->bufsize);
#endif
Local<Object> buf = NanNewBufferHandle((char *)dest->buffer, dest->bufsize);
Local<Value> argv[3] = {
Local<Value>::New(Null())
#if NODE_VERSION_AT_LEAST(0, 11, 3)
, Local<Value>::New(buf)
#else
, Local<Value>::New(buf->handle_)
#endif
, Local<Value>::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<Object> buf = Buffer::New(remaining);
memcpy(Buffer::Data(buf), dest->buffer, remaining);
#else
Local<Buffer> buf = Buffer::New(remaining);
memcpy(Buffer::Data(buf->handle_), dest->buffer, remaining);
#endif
Local<Object> buf = NanNewBufferHandle((char *)dest->buffer, remaining);
Local<Value> data_argv[3] = {
Local<Value>::New(Null())
#if NODE_VERSION_AT_LEAST(0, 11, 3)
, Local<Value>::New(buf)
#else
, Local<Value>::New(buf->handle_)
#endif
, Local<Value>::New(buf)
, Integer::New(remaining)
};

41
src/PixelArray.cc

@ -9,6 +9,8 @@
#include <stdlib.h>
#include <string.h>
#include "nan.h"
Persistent<FunctionTemplate> PixelArray::constructor;
/*
@ -17,30 +19,26 @@ Persistent<FunctionTemplate> PixelArray::constructor;
void
PixelArray::Initialize(Handle<Object> target) {
HandleScope scope;
NanScope();
// Constructor
#if NODE_VERSION_AT_LEAST(0, 11, 3)
constructor = Persistent<FunctionTemplate>::New(Isolate::GetCurrent(), FunctionTemplate::New(PixelArray::New));
#else
constructor = Persistent<FunctionTemplate>::New(FunctionTemplate::New(PixelArray::New));
#endif
constructor->InstanceTemplate()->SetInternalFieldCount(1);
constructor->SetClassName(String::NewSymbol("CanvasPixelArray"));
Local<FunctionTemplate> ctor = FunctionTemplate::New(PixelArray::New);
NanAssignPersistent(FunctionTemplate, constructor, ctor);
ctor->InstanceTemplate()->SetInternalFieldCount(1);
ctor->SetClassName(NanSymbol("CanvasPixelArray"));
// Prototype
Local<ObjectTemplate> proto = constructor->InstanceTemplate();
proto->SetAccessor(String::NewSymbol("length"), GetLength);
target->Set(String::NewSymbol("CanvasPixelArray"), constructor->GetFunction());
Local<ObjectTemplate> proto = ctor->InstanceTemplate();
proto->SetAccessor(NanSymbol("length"), GetLength);
target->Set(NanSymbol("CanvasPixelArray"), ctor->GetFunction());
}
/*
* Initialize a new PixelArray.
*/
Handle<Value>
PixelArray::New(const Arguments &args) {
HandleScope scope;
NAN_METHOD(PixelArray::New) {
NanScope();
PixelArray *arr;
Local<Object> 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<Canvas>(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<Value>
PixelArray::GetLength(Local<String> 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()));
}
/*

4
src/PixelArray.h

@ -14,8 +14,8 @@ class PixelArray: public node::ObjectWrap {
public:
static Persistent<FunctionTemplate> constructor;
static void Initialize(Handle<Object> target);
static Handle<Value> New(const Arguments &args);
static Handle<Value> GetLength(Local<String> 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; }

4
src/closure.h

@ -8,12 +8,14 @@
#ifndef __NODE_CLOSURE_H__
#define __NODE_CLOSURE_H__
#include "nan.h"
/*
* PNG stream closure.
*/
typedef struct {
Persistent<Function> pfn;
NanCallback *pfn;
Handle<Function> fn;
unsigned len;
unsigned max_len;

344
src/nan.h

@ -0,0 +1,344 @@
/**********************************************************************************
* NAN - Native Abstractions for Node.js
*
* Copyright (c) 2013 Rod Vagg
* MIT +no-false-attribs License <https://github.com/rvagg/nan/blob/master/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<Value> argument
* - Added `NanNewBufferHandle` with single uint32_t argument
* - Added `NanHasInstance(Persistent<FunctionTemplate>&, Handle<Value>)`
* - Added `Local<Function> NanCallback#GetFunction()`
* - Added `NanCallback#Call(int, Local<Value>[])`
* - Deprecated `NanCallback#Run(int, Local<Value>[])` in favour of Call
*
* See https://github.com/rvagg/nan for the latest update to this file
**********************************************************************************/
#ifndef NAN_H
#define NAN_H
#include <node.h>
#include <node_buffer.h>
// some generic helpers
#define NanSymbol(value) v8::String::NewSymbol(value)
static inline char* NanFromV8String(v8::Local<v8::Value> from) {
size_t sz_;
char* to;
v8::Local<v8::String> 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<v8::Object> optionsObj
, v8::Handle<v8::String> 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<v8::Object> optionsObj
, v8::Handle<v8::String> opt) {
return NanBooleanOptionValue(optionsObj, opt, false);
}
static inline uint32_t NanUInt32OptionValue(
v8::Local<v8::Object> optionsObj
, v8::Handle<v8::String> 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<v8::Value>& args)
# define NAN_GETTER(name) \
void name( \
v8::Local<v8::String> property \
, const v8::PropertyCallbackInfo<v8::Value>& args)
# define NAN_SETTER(name) \
void name( \
v8::Local<v8::String> property \
, v8::Local<v8::Value> value \
, const v8::PropertyCallbackInfo<void>& 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<v8::Value> 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<v8::Object> &handle) {
handle.Dispose(nan_isolate);
}
static inline v8::Local<v8::Object> NanNewBufferHandle (
char *data, uint32_t size) {
return node::Buffer::New(data, size);
}
static inline v8::Local<v8::Object> NanNewBufferHandle (uint32_t size) {
return node::Buffer::New(size);
}
template <class TypeName>
inline v8::Local<TypeName> NanPersistentToLocal(
const v8::Persistent<TypeName>& persistent) {
if (persistent.IsWeak()) {
return v8::Local<TypeName>::New(nan_isolate, persistent);
} else {
return *reinterpret_cast<v8::Local<TypeName>*>(
const_cast<v8::Persistent<TypeName>*>(&persistent));
}
}
inline bool NanHasInstance(
v8::Persistent<v8::FunctionTemplate>& function_template
, v8::Handle<v8::Value> value) {
return NanPersistentToLocal(function_template)->HasInstance(value);
}
#else
// Node 0.8 and 0.10
# define NAN_METHOD(name) \
v8::Handle<v8::Value> name(const v8::Arguments& args)
# define NAN_GETTER(name) \
v8::Handle<v8::Value> name( \
v8::Local<v8::String> property \
, const v8::AccessorInfo &args)
# define NAN_SETTER(name) \
void name( \
v8::Local<v8::String> property \
, v8::Local<v8::Value> 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<type>::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<v8::Value> NanThrowError(const char* errmsg) {
THROW_ERROR(v8::Exception::Error, errmsg);
}
inline static v8::Handle<v8::Value> NanThrowError(
v8::Local<v8::Value> error) {
NanScope();
return v8::ThrowException(error);
}
inline static v8::Handle<v8::Value> NanThrowTypeError(const char* errmsg) {
THROW_ERROR(v8::Exception::TypeError, errmsg);
}
inline static v8::Handle<v8::Value> NanThrowRangeError(const char* errmsg) {
THROW_ERROR(v8::Exception::RangeError, errmsg);
}
static inline void NanDispose(v8::Persistent<v8::Object> &handle) {
handle.Dispose();
}
static inline v8::Local<v8::Object> NanNewBufferHandle (
char *data, uint32_t size) {
return v8::Local<v8::Object>::New(node::Buffer::New(data, size)->handle_);
}
template <class TypeName>
inline v8::Local<TypeName> NanPersistentToLocal(
const v8::Persistent<TypeName>& persistent) {
if (persistent.IsWeak()) {
return v8::Local<TypeName>::New(persistent);
} else {
return *reinterpret_cast<v8::Local<TypeName>*>(
const_cast<v8::Persistent<TypeName>*>(&persistent));
}
}
inline bool NanHasInstance(
v8::Persistent<v8::FunctionTemplate>& function_template
, v8::Handle<v8::Value> value) {
return function_template->HasInstance(value);
}
#endif // node version
class NanCallback {
public:
NanCallback(const v8::Local<v8::Function> &fn) {
NanScope();
v8::Local<v8::Object> obj = v8::Object::New();
obj->Set(NanSymbol("callback"), fn);
NanAssignPersistent(v8::Object, handle, obj);
}
~NanCallback() {
if (handle.IsEmpty()) return;
handle.Dispose();
}
v8::Local<v8::Function> GetFunction () {
NanScope();
return NanPersistentToLocal(handle).As<v8::Function>();
}
// deprecated
void Run(int argc, v8::Local<v8::Value> argv[]) {
Call(argc, argv);
}
void Call(int argc, v8::Local<v8::Value> argv[]) {
NanScope();
v8::Local<v8::Function> callback = NanPersistentToLocal(handle)->
Get(NanSymbol("callback")).As<v8::Function>();
v8::TryCatch try_catch;
callback->Call(v8::Context::GetCurrent()->Global(), argc, argv);
if (try_catch.HasCaught()) {
node::FatalException(try_catch);
}
}
private:
v8::Persistent<v8::Object> 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<v8::Object> persistentHandle;
NanCallback *callback;
const char *errmsg;
void SavePersistent(const char *key, v8::Local<v8::Object> &obj) {
v8::Local<v8::Object> handle = NanPersistentToLocal(persistentHandle);
handle->Set(NanSymbol(key), obj);
}
v8::Local<v8::Object> GetFromPersistent(const char *key) {
v8::Local<v8::Object> handle = NanPersistentToLocal(persistentHandle);
return handle->Get(NanSymbol(key)).As<v8::Object>();
}
virtual void HandleOKCallback () {
NanScope();
callback->Call(0, NULL);
};
virtual void HandleErrorCallback () {
NanScope();
v8::Local<v8::Value> argv[] = {
v8::Exception::Error(v8::String::New(errmsg))
};
callback->Call(1, argv);
}
};
inline void NanAsyncExecute (uv_work_t* req) {
NanAsyncWorker *worker = static_cast<NanAsyncWorker*>(req->data);
worker->Execute();
}
inline void NanAsyncExecuteComplete (uv_work_t* req) {
NanAsyncWorker* worker = static_cast<NanAsyncWorker*>(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
Loading…
Cancel
Save