Browse Source

Update to NAN 2 and node 3+ APIs

v1.x
Zach Bjornson 9 years ago
parent
commit
d4d3b9c724
  1. 15
      .travis.yml
  2. 105
      benchmarks/run.js
  3. 4
      package.json
  4. 258
      src/Canvas.cc
  5. 8
      src/Canvas.h
  6. 73
      src/CanvasGradient.cc
  7. 6
      src/CanvasGradient.h
  8. 36
      src/CanvasPattern.cc
  9. 6
      src/CanvasPattern.h
  10. 939
      src/CanvasRenderingContext2d.cc
  11. 6
      src/CanvasRenderingContext2d.h
  12. 38
      src/FontFace.cc
  13. 6
      src/FontFace.h
  14. 105
      src/Image.cc
  15. 16
      src/Image.h
  16. 70
      src/ImageData.cc
  17. 6
      src/ImageData.h
  18. 32
      src/JPEGStream.h
  19. 6
      src/closure.h
  20. 12
      src/init.cc
  21. 18
      test/canvas.test.js

15
.travis.yml

@ -5,7 +5,20 @@ node_js:
- "0.12" - "0.12"
- "iojs-v1.8.4" - "iojs-v1.8.4"
- "iojs-v2.5.0" - "iojs-v2.5.0"
- "iojs-v3.3.0"
- "4"
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-4.8
before_install: before_install:
- '[ "${TRAVIS_NODE_VERSION}" != "0.8" ] || npm install -g npm@1.4.28' - if [[ $TRAVIS_NODE_VERSION == 0.8 ]]; then npm install -g npm@1.4.28; fi
- if [[ $TRAVIS_OS_NAME == "linux" ]]; then export CXX=g++-4.8; fi
- $CXX --version
- sudo chown -R $USER /usr/local - sudo chown -R $USER /usr/local
- sh install - sh install
- npm explore npm -g -- npm install node-gyp@latest
after_script:
- make benchmark

105
benchmarks/run.js

@ -1,6 +1,7 @@
/** /**
* Module dependencies. * Adaptive benchmarking. Starts with `initialTimes` iterations, increasing by
* a power of two each time until the benchmark takes at least `minDuration_ms`
* milliseconds to complete.
*/ */
var Canvas = require('../lib/canvas') var Canvas = require('../lib/canvas')
@ -8,34 +9,50 @@ var Canvas = require('../lib/canvas')
, largeCanvas = new Canvas(1000, 1000) , largeCanvas = new Canvas(1000, 1000)
, ctx = canvas.getContext('2d'); , ctx = canvas.getContext('2d');
var times = 10000; var initialTimes = 10;
console.log('\n \x1b[33m%s\x1b[0m times\n', times); var minDuration_ms = 2000;
function bm(label, overrideTimes, fn) { var queue = [], running = false;
var start = new Date
, n = times;
if ('function' == typeof overrideTimes) { function bm(label, fn) {
fn = overrideTimes; queue.push({label: label, fn: fn});
} else { next();
n = overrideTimes; }
label += ' (' + n + ' times)';
}
var pending = n;
function done(){ function next() {
var duration = (new Date - start) / 1000; if (queue.length && !running) {
console.log(' - \x1b[33m%s\x1b[0m %ss', label, duration); run(queue.pop(), initialTimes, Date.now());
} }
}
if (fn.length) { function run(benchmark, n, start) {
while (n--) fn(function(){ running = true;
--pending || done(); var originalN = n;
var fn = benchmark.fn;
if (fn.length) { // async
var pending = n;
while (n--) fn(function () {
--pending || done(benchmark, originalN, start, true);
}); });
} else { } else {
while (n--) fn(); while (n--) fn();
done(); done(benchmark, originalN, start);
}
}
function done(benchmark, times, start, async) {
var duration = Date.now() - start;
if (duration < minDuration_ms) {
run(benchmark, times * 2, Date.now());
} else {
var opsSec = times / duration * 1000
if (async) {
console.log(' - \x1b[33m%s\x1b[0m %s ops/sec (%s times, async)', benchmark.label, opsSec.toLocaleString(), times);
} else {
console.log(' - \x1b[33m%s\x1b[0m %s ops/sec (%s times)', benchmark.label, opsSec.toLocaleString(), times);
}
running = false;
next();
} }
} }
@ -46,7 +63,7 @@ bm('lineTo()', function(){
}); });
bm('arc()', function(){ bm('arc()', function(){
ctx.arc(75,75,50,0,Math.PI*2,true); ctx.arc(75,75,50,0,Math.PI*2,true);
}); });
bm('fillStyle= hex', function(){ bm('fillStyle= hex', function(){
@ -57,6 +74,8 @@ bm('fillStyle= rgba()', function(){
ctx.fillStyle = 'rgba(0,255,80,1)'; ctx.fillStyle = 'rgba(0,255,80,1)';
}); });
// Apparently there's a bug in cairo by which the fillRect and strokeRect are
// slow only after a ton of arcs have been drawn.
bm('fillRect()', function(){ bm('fillRect()', function(){
ctx.fillRect(50, 50, 100, 100); ctx.fillRect(50, 50, 100, 100);
}); });
@ -73,19 +92,31 @@ bm('linear gradients', function(){
ctx.fillRect(10,10,130,130); ctx.fillRect(10,10,130,130);
}); });
bm('toBuffer() 200x200', 50, function(){ bm('toBuffer() 200x200', function(){
canvas.toBuffer(); canvas.toBuffer();
}); });
bm('toBuffer() 1000x1000', 50, function(){ bm('toBuffer() 1000x1000', function(){
largeCanvas.toBuffer(); largeCanvas.toBuffer();
}); });
bm('toBuffer().toString("base64") 200x200', 50, function(){ bm('toBuffer() async 200x200', function(done){
canvas.toBuffer(function (err, buf) {
done();
});
});
bm('toBuffer() async 1000x1000', function(done){
largeCanvas.toBuffer(function (err, buf) {
done();
});
});
bm('toBuffer().toString("base64") 200x200', function(){
canvas.toBuffer().toString('base64'); canvas.toBuffer().toString('base64');
}); });
bm('toDataURL() 200x200', 50, function(){ bm('toDataURL() 200x200', function(){
canvas.toDataURL(); canvas.toDataURL();
}); });
@ -109,14 +140,12 @@ bm('getImageData(0,0,100,100)', function(){
ctx.getImageData(0,0,100,100); ctx.getImageData(0,0,100,100);
}); });
// bm('PNGStream 200x200', 50, function(done){ bm('PNGStream 200x200', function(done){
// var stream = canvas.createSyncPNGStream(); var stream = canvas.createSyncPNGStream();
// stream.on('data', function(chunk){ stream.on('data', function(chunk){
// // whatever // whatever
// }); });
// stream.on('end', function(){ stream.on('end', function(){
// done(); done();
// }); });
// }); });
console.log();

4
package.json

@ -24,7 +24,7 @@
"test": "make test" "test": "make test"
}, },
"dependencies": { "dependencies": {
"nan": "^1.8.4" "nan": "^2.0.9"
}, },
"devDependencies": { "devDependencies": {
"body-parser": "^1.13.3", "body-parser": "^1.13.3",
@ -33,7 +33,7 @@
"mocha": "*" "mocha": "*"
}, },
"engines": { "engines": {
"node": ">=0.8.0 <3" "node": ">=0.8.0"
}, },
"main": "./lib/canvas.js", "main": "./lib/canvas.js",
"license": "MIT" "license": "MIT"

258
src/Canvas.cc

@ -20,42 +20,42 @@
#include "JPEGStream.h" #include "JPEGStream.h"
#endif #endif
Persistent<FunctionTemplate> Canvas::constructor; Nan::Persistent<FunctionTemplate> Canvas::constructor;
/* /*
* Initialize Canvas. * Initialize Canvas.
*/ */
void void
Canvas::Initialize(Handle<Object> target) { Canvas::Initialize(Nan::ADDON_REGISTER_FUNCTION_ARGS_TYPE target) {
NanScope(); Nan::HandleScope scope;
// Constructor // Constructor
Local<FunctionTemplate> ctor = NanNew<FunctionTemplate>(Canvas::New); Local<FunctionTemplate> ctor = Nan::New<FunctionTemplate>(Canvas::New);
NanAssignPersistent(constructor, ctor); constructor.Reset(ctor);
ctor->InstanceTemplate()->SetInternalFieldCount(1); ctor->InstanceTemplate()->SetInternalFieldCount(1);
ctor->SetClassName(NanNew("Canvas")); ctor->SetClassName(Nan::New("Canvas").ToLocalChecked());
// Prototype // Prototype
Local<ObjectTemplate> proto = ctor->PrototypeTemplate(); Local<ObjectTemplate> proto = ctor->PrototypeTemplate();
NODE_SET_PROTOTYPE_METHOD(ctor, "toBuffer", ToBuffer); Nan::SetPrototypeMethod(ctor, "toBuffer", ToBuffer);
NODE_SET_PROTOTYPE_METHOD(ctor, "streamPNGSync", StreamPNGSync); Nan::SetPrototypeMethod(ctor, "streamPNGSync", StreamPNGSync);
#ifdef HAVE_JPEG #ifdef HAVE_JPEG
NODE_SET_PROTOTYPE_METHOD(ctor, "streamJPEGSync", StreamJPEGSync); Nan::SetPrototypeMethod(ctor, "streamJPEGSync", StreamJPEGSync);
#endif #endif
proto->SetAccessor(NanNew("type"), GetType); Nan::SetAccessor(proto, Nan::New("type").ToLocalChecked(), GetType);
proto->SetAccessor(NanNew("width"), GetWidth, SetWidth); Nan::SetAccessor(proto, Nan::New("width").ToLocalChecked(), GetWidth, SetWidth);
proto->SetAccessor(NanNew("height"), GetHeight, SetHeight); Nan::SetAccessor(proto, Nan::New("height").ToLocalChecked(), GetHeight, SetHeight);
NanSetTemplate(proto, "PNG_NO_FILTERS", NanNew<Uint32>(PNG_NO_FILTERS)); Nan::SetTemplate(proto, "PNG_NO_FILTERS", Nan::New<Uint32>(PNG_NO_FILTERS));
NanSetTemplate(proto, "PNG_FILTER_NONE", NanNew<Uint32>(PNG_FILTER_NONE)); Nan::SetTemplate(proto, "PNG_FILTER_NONE", Nan::New<Uint32>(PNG_FILTER_NONE));
NanSetTemplate(proto, "PNG_FILTER_SUB", NanNew<Uint32>(PNG_FILTER_SUB)); Nan::SetTemplate(proto, "PNG_FILTER_SUB", Nan::New<Uint32>(PNG_FILTER_SUB));
NanSetTemplate(proto, "PNG_FILTER_UP", NanNew<Uint32>(PNG_FILTER_UP)); Nan::SetTemplate(proto, "PNG_FILTER_UP", Nan::New<Uint32>(PNG_FILTER_UP));
NanSetTemplate(proto, "PNG_FILTER_AVG", NanNew<Uint32>(PNG_FILTER_AVG)); Nan::SetTemplate(proto, "PNG_FILTER_AVG", Nan::New<Uint32>(PNG_FILTER_AVG));
NanSetTemplate(proto, "PNG_FILTER_PAETH", NanNew<Uint32>(PNG_FILTER_PAETH)); Nan::SetTemplate(proto, "PNG_FILTER_PAETH", Nan::New<Uint32>(PNG_FILTER_PAETH));
NanSetTemplate(proto, "PNG_ALL_FILTERS", NanNew<Uint32>(PNG_ALL_FILTERS)); Nan::SetTemplate(proto, "PNG_ALL_FILTERS", Nan::New<Uint32>(PNG_ALL_FILTERS));
target->Set(NanNew("Canvas"), ctor->GetFunction()); Nan::Set(target, Nan::New("Canvas").ToLocalChecked(), ctor->GetFunction());
} }
/* /*
@ -63,19 +63,18 @@ Canvas::Initialize(Handle<Object> target) {
*/ */
NAN_METHOD(Canvas::New) { NAN_METHOD(Canvas::New) {
NanScope();
int width = 0, height = 0; int width = 0, height = 0;
canvas_type_t type = CANVAS_TYPE_IMAGE; canvas_type_t type = CANVAS_TYPE_IMAGE;
if (args[0]->IsNumber()) width = args[0]->Uint32Value(); if (info[0]->IsNumber()) width = info[0]->Uint32Value();
if (args[1]->IsNumber()) height = args[1]->Uint32Value(); if (info[1]->IsNumber()) height = info[1]->Uint32Value();
if (args[2]->IsString()) type = !strcmp("pdf", *String::Utf8Value(args[2])) if (info[2]->IsString()) type = !strcmp("pdf", *String::Utf8Value(info[2]))
? CANVAS_TYPE_PDF ? CANVAS_TYPE_PDF
: !strcmp("svg", *String::Utf8Value(args[2])) : !strcmp("svg", *String::Utf8Value(info[2]))
? CANVAS_TYPE_SVG ? CANVAS_TYPE_SVG
: CANVAS_TYPE_IMAGE; : CANVAS_TYPE_IMAGE;
Canvas *canvas = new Canvas(width, height, type); Canvas *canvas = new Canvas(width, height, type);
canvas->Wrap(args.This()); canvas->Wrap(info.This());
NanReturnValue(args.This()); info.GetReturnValue().Set(info.This());
} }
/* /*
@ -83,9 +82,8 @@ NAN_METHOD(Canvas::New) {
*/ */
NAN_GETTER(Canvas::GetType) { NAN_GETTER(Canvas::GetType) {
NanScope(); Canvas *canvas = Nan::ObjectWrap::Unwrap<Canvas>(info.This());
Canvas *canvas = ObjectWrap::Unwrap<Canvas>(args.This()); info.GetReturnValue().Set(Nan::New<String>(canvas->isPDF() ? "pdf" : canvas->isSVG() ? "svg" : "image").ToLocalChecked());
NanReturnValue(NanNew<String>(canvas->isPDF() ? "pdf" : canvas->isSVG() ? "svg" : "image"));
} }
/* /*
@ -93,9 +91,8 @@ NAN_GETTER(Canvas::GetType) {
*/ */
NAN_GETTER(Canvas::GetWidth) { NAN_GETTER(Canvas::GetWidth) {
NanScope(); Canvas *canvas = Nan::ObjectWrap::Unwrap<Canvas>(info.This());
Canvas *canvas = ObjectWrap::Unwrap<Canvas>(args.This()); info.GetReturnValue().Set(Nan::New<Number>(canvas->width));
NanReturnValue(NanNew<Number>(canvas->width));
} }
/* /*
@ -103,11 +100,10 @@ NAN_GETTER(Canvas::GetWidth) {
*/ */
NAN_SETTER(Canvas::SetWidth) { NAN_SETTER(Canvas::SetWidth) {
NanScope();
if (value->IsNumber()) { if (value->IsNumber()) {
Canvas *canvas = ObjectWrap::Unwrap<Canvas>(args.This()); Canvas *canvas = Nan::ObjectWrap::Unwrap<Canvas>(info.This());
canvas->width = value->Uint32Value(); canvas->width = value->Uint32Value();
canvas->resurface(args.This()); canvas->resurface(info.This());
} }
} }
@ -116,9 +112,8 @@ NAN_SETTER(Canvas::SetWidth) {
*/ */
NAN_GETTER(Canvas::GetHeight) { NAN_GETTER(Canvas::GetHeight) {
NanScope(); Canvas *canvas = Nan::ObjectWrap::Unwrap<Canvas>(info.This());
Canvas *canvas = ObjectWrap::Unwrap<Canvas>(args.This()); info.GetReturnValue().Set(Nan::New<Number>(canvas->height));
NanReturnValue(NanNew<Number>(canvas->height));
} }
/* /*
@ -126,11 +121,10 @@ NAN_GETTER(Canvas::GetHeight) {
*/ */
NAN_SETTER(Canvas::SetHeight) { NAN_SETTER(Canvas::SetHeight) {
NanScope();
if (value->IsNumber()) { if (value->IsNumber()) {
Canvas *canvas = ObjectWrap::Unwrap<Canvas>(args.This()); Canvas *canvas = Nan::ObjectWrap::Unwrap<Canvas>(info.This());
canvas->height = value->Uint32Value(); canvas->height = value->Uint32Value();
canvas->resurface(args.This()); canvas->resurface(info.This());
} }
} }
@ -200,7 +194,7 @@ int
Canvas::EIO_AfterToBuffer(eio_req *req) { Canvas::EIO_AfterToBuffer(eio_req *req) {
#endif #endif
NanScope(); Nan::HandleScope scope;
closure_t *closure = (closure_t *) req->data; closure_t *closure = (closure_t *) req->data;
#if NODE_VERSION_AT_LEAST(0, 6, 0) #if NODE_VERSION_AT_LEAST(0, 6, 0)
delete req; delete req;
@ -212,9 +206,9 @@ Canvas::EIO_AfterToBuffer(eio_req *req) {
Local<Value> argv[1] = { Canvas::Error(closure->status) }; Local<Value> argv[1] = { Canvas::Error(closure->status) };
closure->pfn->Call(1, argv); closure->pfn->Call(1, argv);
} else { } else {
Local<Object> buf = NanNewBufferHandle((char*)closure->data, closure->len); Local<Object> buf = Nan::CopyBuffer((char*)closure->data, closure->len).ToLocalChecked();
memcpy(Buffer::Data(buf), closure->data, closure->len); memcpy(Buffer::Data(buf), closure->data, closure->len);
Local<Value> argv[2] = { NanNew(NanNull()), buf }; Local<Value> argv[2] = { Nan::Null(), buf };
closure->pfn->Call(2, argv); closure->pfn->Call(2, argv);
} }
@ -234,31 +228,31 @@ Canvas::EIO_AfterToBuffer(eio_req *req) {
*/ */
NAN_METHOD(Canvas::ToBuffer) { NAN_METHOD(Canvas::ToBuffer) {
NanScope();
cairo_status_t status; cairo_status_t status;
uint32_t compression_level = 6; uint32_t compression_level = 6;
uint32_t filter = PNG_ALL_FILTERS; uint32_t filter = PNG_ALL_FILTERS;
Canvas *canvas = ObjectWrap::Unwrap<Canvas>(args.This()); Canvas *canvas = Nan::ObjectWrap::Unwrap<Canvas>(info.This());
// TODO: async / move this out // TODO: async / move this out
if (canvas->isPDF() || canvas->isSVG()) { if (canvas->isPDF() || canvas->isSVG()) {
cairo_surface_finish(canvas->surface()); cairo_surface_finish(canvas->surface());
closure_t *closure = (closure_t *) canvas->closure(); closure_t *closure = (closure_t *) canvas->closure();
Local<Object> buf = NanNewBufferHandle((char*) closure->data, closure->len); Local<Object> buf = Nan::CopyBuffer((char*) closure->data, closure->len).ToLocalChecked();
NanReturnValue(buf); info.GetReturnValue().Set(buf);
return;
} }
if (args.Length() > 1 && !(args[1]->StrictEquals(NanUndefined()) && args[2]->StrictEquals(NanUndefined()))) { if (info.Length() > 1 && !(info[1]->IsUndefined() && info[2]->IsUndefined())) {
if (!args[1]->StrictEquals(NanUndefined())) { if (!info[1]->IsUndefined()) {
bool good = true; bool good = true;
if (args[1]->IsNumber()) { if (info[1]->IsNumber()) {
compression_level = args[1]->Uint32Value(); compression_level = info[1]->Uint32Value();
} else if (args[1]->IsString()) { } else if (info[1]->IsString()) {
if (args[1]->StrictEquals(NanNew<String>("0"))) { if (info[1]->StrictEquals(Nan::New<String>("0").ToLocalChecked())) {
compression_level = 0; compression_level = 0;
} else { } else {
uint32_t tmp = args[1]->Uint32Value(); uint32_t tmp = info[1]->Uint32Value();
if (tmp == 0) { if (tmp == 0) {
good = false; good = false;
} else { } else {
@ -271,24 +265,24 @@ NAN_METHOD(Canvas::ToBuffer) {
if (good) { if (good) {
if (compression_level > 9) { if (compression_level > 9) {
return NanThrowRangeError("Allowed compression levels lie in the range [0, 9]."); return Nan::ThrowRangeError("Allowed compression levels lie in the range [0, 9].");
} }
} else { } else {
return NanThrowTypeError("Compression level must be a number."); return Nan::ThrowTypeError("Compression level must be a number.");
} }
} }
if (!args[2]->StrictEquals(NanUndefined())) { if (!info[2]->IsUndefined()) {
if (args[2]->IsUint32()) { if (info[2]->IsUint32()) {
filter = args[2]->Uint32Value(); filter = info[2]->Uint32Value();
} else { } else {
return NanThrowTypeError("Invalid filter value."); return Nan::ThrowTypeError("Invalid filter value.");
} }
} }
} }
// Async // Async
if (args[0]->IsFunction()) { if (info[0]->IsFunction()) {
closure_t *closure = (closure_t *) malloc(sizeof(closure_t)); closure_t *closure = (closure_t *) malloc(sizeof(closure_t));
status = closure_init(closure, canvas, compression_level, filter); status = closure_init(closure, canvas, compression_level, filter);
@ -296,12 +290,12 @@ NAN_METHOD(Canvas::ToBuffer) {
if (status) { if (status) {
closure_destroy(closure); closure_destroy(closure);
free(closure); free(closure);
return NanThrowError(Canvas::Error(status)); return Nan::ThrowError(Canvas::Error(status));
} }
// TODO: only one callback fn in closure // TODO: only one callback fn in closure
canvas->Ref(); canvas->Ref();
closure->pfn = new NanCallback(args[0].As<Function>()); closure->pfn = new Nan::Callback(info[0].As<Function>());
#if NODE_VERSION_AT_LEAST(0, 6, 0) #if NODE_VERSION_AT_LEAST(0, 6, 0)
uv_work_t* req = new uv_work_t; uv_work_t* req = new uv_work_t;
@ -312,7 +306,7 @@ NAN_METHOD(Canvas::ToBuffer) {
ev_ref(EV_DEFAULT_UC); ev_ref(EV_DEFAULT_UC);
#endif #endif
NanReturnUndefined(); return;
// Sync // Sync
} else { } else {
closure_t closure; closure_t closure;
@ -321,7 +315,7 @@ NAN_METHOD(Canvas::ToBuffer) {
// ensure closure is ok // ensure closure is ok
if (status) { if (status) {
closure_destroy(&closure); closure_destroy(&closure);
return NanThrowError(Canvas::Error(status)); return Nan::ThrowError(Canvas::Error(status));
} }
TryCatch try_catch; TryCatch try_catch;
@ -329,14 +323,16 @@ NAN_METHOD(Canvas::ToBuffer) {
if (try_catch.HasCaught()) { if (try_catch.HasCaught()) {
closure_destroy(&closure); closure_destroy(&closure);
NanReturnValue(try_catch.ReThrow()); try_catch.ReThrow();
return;
} else if (status) { } else if (status) {
closure_destroy(&closure); closure_destroy(&closure);
return NanThrowError(Canvas::Error(status)); return Nan::ThrowError(Canvas::Error(status));
} else { } else {
Local<Object> buf = NanNewBufferHandle((char *)closure.data, closure.len); Local<Object> buf = Nan::CopyBuffer((char *)closure.data, closure.len).ToLocalChecked();
closure_destroy(&closure); closure_destroy(&closure);
NanReturnValue(buf); info.GetReturnValue().Set(buf);
return;
} }
} }
} }
@ -347,14 +343,14 @@ NAN_METHOD(Canvas::ToBuffer) {
static cairo_status_t static cairo_status_t
streamPNG(void *c, const uint8_t *data, unsigned len) { streamPNG(void *c, const uint8_t *data, unsigned len) {
NanScope(); Nan::HandleScope scope;
closure_t *closure = (closure_t *) c; closure_t *closure = (closure_t *) c;
Local<Object> buf = NanNewBufferHandle((char *)data, len); Local<Object> buf = Nan::CopyBuffer((char *)data, len).ToLocalChecked();
Local<Value> argv[3] = { Local<Value> argv[3] = {
NanNew(NanNull()) Nan::Null()
, buf , buf
, NanNew<Number>(len) }; , Nan::New<Number>(len) };
NanMakeCallback(NanGetCurrentContext()->Global(), closure->fn, 3, argv); Nan::MakeCallback(Nan::GetCurrentContext()->Global(), (v8::Local<v8::Function>)closure->fn, 3, argv);
return CAIRO_STATUS_SUCCESS; return CAIRO_STATUS_SUCCESS;
} }
@ -363,23 +359,22 @@ streamPNG(void *c, const uint8_t *data, unsigned len) {
*/ */
NAN_METHOD(Canvas::StreamPNGSync) { NAN_METHOD(Canvas::StreamPNGSync) {
NanScope();
uint32_t compression_level = 6; uint32_t compression_level = 6;
uint32_t filter = PNG_ALL_FILTERS; uint32_t filter = PNG_ALL_FILTERS;
// TODO: async as well // TODO: async as well
if (!args[0]->IsFunction()) if (!info[0]->IsFunction())
return NanThrowTypeError("callback function required"); return Nan::ThrowTypeError("callback function required");
if (args.Length() > 1 && !(args[1]->StrictEquals(NanUndefined()) && args[2]->StrictEquals(NanUndefined()))) { if (info.Length() > 1 && !(info[1]->IsUndefined() && info[2]->IsUndefined())) {
if (!args[1]->StrictEquals(NanUndefined())) { if (!info[1]->IsUndefined()) {
bool good = true; bool good = true;
if (args[1]->IsNumber()) { if (info[1]->IsNumber()) {
compression_level = args[1]->Uint32Value(); compression_level = info[1]->Uint32Value();
} else if (args[1]->IsString()) { } else if (info[1]->IsString()) {
if (args[1]->StrictEquals(NanNew<String>("0"))) { if (info[1]->StrictEquals(Nan::New<String>("0").ToLocalChecked())) {
compression_level = 0; compression_level = 0;
} else { } else {
uint32_t tmp = args[1]->Uint32Value(); uint32_t tmp = info[1]->Uint32Value();
if (tmp == 0) { if (tmp == 0) {
good = false; good = false;
} else { } else {
@ -392,26 +387,26 @@ NAN_METHOD(Canvas::StreamPNGSync) {
if (good) { if (good) {
if (compression_level > 9) { if (compression_level > 9) {
return NanThrowRangeError("Allowed compression levels lie in the range [0, 9]."); return Nan::ThrowRangeError("Allowed compression levels lie in the range [0, 9].");
} }
} else { } else {
return NanThrowTypeError("Compression level must be a number."); return Nan::ThrowTypeError("Compression level must be a number.");
} }
} }
if (!args[2]->StrictEquals(NanUndefined())) { if (!info[2]->IsUndefined()) {
if (args[2]->IsUint32()) { if (info[2]->IsUint32()) {
filter = args[2]->Uint32Value(); filter = info[2]->Uint32Value();
} else { } else {
return NanThrowTypeError("Invalid filter value."); return Nan::ThrowTypeError("Invalid filter value.");
} }
} }
} }
Canvas *canvas = ObjectWrap::Unwrap<Canvas>(args.This()); Canvas *canvas = Nan::ObjectWrap::Unwrap<Canvas>(info.This());
closure_t closure; closure_t closure;
closure.fn = Handle<Function>::Cast(args[0]); closure.fn = Local<Function>::Cast(info[0]);
closure.compression_level = compression_level; closure.compression_level = compression_level;
closure.filter = filter; closure.filter = filter;
@ -420,18 +415,19 @@ NAN_METHOD(Canvas::StreamPNGSync) {
cairo_status_t status = canvas_write_to_png_stream(canvas->surface(), streamPNG, &closure); cairo_status_t status = canvas_write_to_png_stream(canvas->surface(), streamPNG, &closure);
if (try_catch.HasCaught()) { if (try_catch.HasCaught()) {
NanReturnValue(try_catch.ReThrow()); try_catch.ReThrow();
return;
} else if (status) { } else if (status) {
Local<Value> argv[1] = { Canvas::Error(status) }; Local<Value> argv[1] = { Canvas::Error(status) };
NanMakeCallback(NanGetCurrentContext()->Global(), closure.fn, 1, argv); Nan::MakeCallback(Nan::GetCurrentContext()->Global(), (v8::Local<v8::Function>)closure.fn, 1, argv);
} else { } else {
Local<Value> argv[3] = { Local<Value> argv[3] = {
NanNew(NanNull()) Nan::Null()
, NanNew(NanNull()) , Nan::Null()
, NanNew<Uint32>(0) }; , Nan::New<Uint32>(0) };
NanMakeCallback(NanGetCurrentContext()->Global(), closure.fn, 1, argv); Nan::MakeCallback(Nan::GetCurrentContext()->Global(), (v8::Local<v8::Function>)closure.fn, 1, argv);
} }
NanReturnUndefined(); return;
} }
/* /*
@ -441,27 +437,27 @@ NAN_METHOD(Canvas::StreamPNGSync) {
#ifdef HAVE_JPEG #ifdef HAVE_JPEG
NAN_METHOD(Canvas::StreamJPEGSync) { NAN_METHOD(Canvas::StreamJPEGSync) {
NanScope();
// TODO: async as well // TODO: async as well
if (!args[0]->IsNumber()) if (!info[0]->IsNumber())
return NanThrowTypeError("buffer size required"); return Nan::ThrowTypeError("buffer size required");
if (!args[1]->IsNumber()) if (!info[1]->IsNumber())
return NanThrowTypeError("quality setting required"); return Nan::ThrowTypeError("quality setting required");
if (!args[2]->IsBoolean()) if (!info[2]->IsBoolean())
return NanThrowTypeError("progressive setting required"); return Nan::ThrowTypeError("progressive setting required");
if (!args[3]->IsFunction()) if (!info[3]->IsFunction())
return NanThrowTypeError("callback function required"); return Nan::ThrowTypeError("callback function required");
Canvas *canvas = ObjectWrap::Unwrap<Canvas>(args.This()); Canvas *canvas = Nan::ObjectWrap::Unwrap<Canvas>(info.This());
closure_t closure; closure_t closure;
closure.fn = Handle<Function>::Cast(args[3]); closure.fn = Local<Function>::Cast(info[3]);
TryCatch try_catch; TryCatch try_catch;
write_to_jpeg_stream(canvas->surface(), args[0]->NumberValue(), args[1]->NumberValue(), args[2]->BooleanValue(), &closure); write_to_jpeg_stream(canvas->surface(), info[0]->NumberValue(), info[1]->NumberValue(), info[2]->BooleanValue(), &closure);
if (try_catch.HasCaught()) if (try_catch.HasCaught()) {
NanReturnValue(try_catch.ReThrow()); try_catch.ReThrow();
NanReturnUndefined(); }
return;
} }
#endif #endif
@ -470,7 +466,7 @@ NAN_METHOD(Canvas::StreamJPEGSync) {
* Initialize cairo surface. * Initialize cairo surface.
*/ */
Canvas::Canvas(int w, int h, canvas_type_t t): ObjectWrap() { Canvas::Canvas(int w, int h, canvas_type_t t): Nan::ObjectWrap() {
type = t; type = t;
width = w; width = w;
height = h; height = h;
@ -492,7 +488,7 @@ Canvas::Canvas(int w, int h, canvas_type_t t): ObjectWrap() {
} else { } else {
_surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, w, h); _surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, w, h);
assert(_surface); assert(_surface);
NanAdjustExternalMemory(4 * w * h); Nan::AdjustExternalMemory(4 * w * h);
} }
} }
@ -511,7 +507,7 @@ Canvas::~Canvas() {
break; break;
case CANVAS_TYPE_IMAGE: case CANVAS_TYPE_IMAGE:
cairo_surface_destroy(_surface); cairo_surface_destroy(_surface);
NanAdjustExternalMemory(-4 * width * height); Nan::AdjustExternalMemory(-4 * width * height);
break; break;
} }
} }
@ -521,9 +517,9 @@ Canvas::~Canvas() {
*/ */
void void
Canvas::resurface(Handle<Object> canvas) { Canvas::resurface(Local<Object> canvas) {
NanScope(); Nan::HandleScope scope;
Handle<Value> context; Local<Value> context;
switch (type) { switch (type) {
case CANVAS_TYPE_PDF: case CANVAS_TYPE_PDF:
cairo_pdf_surface_set_size(_surface, width, height); cairo_pdf_surface_set_size(_surface, width, height);
@ -537,9 +533,9 @@ Canvas::resurface(Handle<Object> canvas) {
_surface = cairo_svg_surface_create_for_stream(toBuffer, _closure, width, height); _surface = cairo_svg_surface_create_for_stream(toBuffer, _closure, width, height);
// Reset context // Reset context
context = canvas->Get(NanNew<String>("context")); context = canvas->Get(Nan::New<String>("context").ToLocalChecked());
if (!context->IsUndefined()) { if (!context->IsUndefined()) {
Context2d *context2d = ObjectWrap::Unwrap<Context2d>(context->ToObject()); Context2d *context2d = Nan::ObjectWrap::Unwrap<Context2d>(context->ToObject());
cairo_t *prev = context2d->context(); cairo_t *prev = context2d->context();
context2d->setContext(cairo_create(surface())); context2d->setContext(cairo_create(surface()));
cairo_destroy(prev); cairo_destroy(prev);
@ -551,12 +547,12 @@ Canvas::resurface(Handle<Object> canvas) {
int old_height = cairo_image_surface_get_height(_surface); int old_height = cairo_image_surface_get_height(_surface);
cairo_surface_destroy(_surface); cairo_surface_destroy(_surface);
_surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height); _surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
NanAdjustExternalMemory(4 * (width * height - old_width * old_height)); Nan::AdjustExternalMemory(4 * (width * height - old_width * old_height));
// Reset context // Reset context
context = canvas->Get(NanNew<String>("context")); context = canvas->Get(Nan::New<String>("context").ToLocalChecked());
if (!context->IsUndefined()) { if (!context->IsUndefined()) {
Context2d *context2d = ObjectWrap::Unwrap<Context2d>(context->ToObject()); Context2d *context2d = Nan::ObjectWrap::Unwrap<Context2d>(context->ToObject());
cairo_t *prev = context2d->context(); cairo_t *prev = context2d->context();
context2d->setContext(cairo_create(surface())); context2d->setContext(cairo_create(surface()));
cairo_destroy(prev); cairo_destroy(prev);
@ -571,5 +567,5 @@ Canvas::resurface(Handle<Object> canvas) {
Local<Value> Local<Value>
Canvas::Error(cairo_status_t status) { Canvas::Error(cairo_status_t status) {
return Exception::Error(NanNew<String>(cairo_status_to_string(status))); return Exception::Error(Nan::New<String>(cairo_status_to_string(status)).ToLocalChecked());
} }

8
src/Canvas.h

@ -47,13 +47,13 @@ typedef enum {
* Canvas. * Canvas.
*/ */
class Canvas: public node::ObjectWrap { class Canvas: public Nan::ObjectWrap {
public: public:
int width; int width;
int height; int height;
canvas_type_t type; canvas_type_t type;
static Persistent<FunctionTemplate> constructor; static Nan::Persistent<FunctionTemplate> constructor;
static void Initialize(Handle<Object> target); static void Initialize(Nan::ADDON_REGISTER_FUNCTION_ARGS_TYPE target);
static NAN_METHOD(New); static NAN_METHOD(New);
static NAN_METHOD(ToBuffer); static NAN_METHOD(ToBuffer);
static NAN_GETTER(GetType); static NAN_GETTER(GetType);
@ -85,7 +85,7 @@ class Canvas: public node::ObjectWrap {
inline uint8_t *data(){ return cairo_image_surface_get_data(_surface); } inline uint8_t *data(){ return cairo_image_surface_get_data(_surface); }
inline int stride(){ return cairo_image_surface_get_stride(_surface); } inline int stride(){ return cairo_image_surface_get_stride(_surface); }
Canvas(int width, int height, canvas_type_t type); Canvas(int width, int height, canvas_type_t type);
void resurface(Handle<Object> canvas); void resurface(Local<Object> canvas);
private: private:
~Canvas(); ~Canvas();

73
src/CanvasGradient.cc

@ -9,25 +9,25 @@
#include "Canvas.h" #include "Canvas.h"
#include "CanvasGradient.h" #include "CanvasGradient.h"
Persistent<FunctionTemplate> Gradient::constructor; Nan::Persistent<FunctionTemplate> Gradient::constructor;
/* /*
* Initialize CanvasGradient. * Initialize CanvasGradient.
*/ */
void void
Gradient::Initialize(Handle<Object> target) { Gradient::Initialize(Nan::ADDON_REGISTER_FUNCTION_ARGS_TYPE target) {
NanScope(); Nan::HandleScope scope;
// Constructor // Constructor
Local<FunctionTemplate> ctor = NanNew<FunctionTemplate>(Gradient::New); Local<FunctionTemplate> ctor = Nan::New<FunctionTemplate>(Gradient::New);
NanAssignPersistent(constructor, ctor); constructor.Reset(ctor);
ctor->InstanceTemplate()->SetInternalFieldCount(1); ctor->InstanceTemplate()->SetInternalFieldCount(1);
ctor->SetClassName(NanNew("CanvasGradient")); ctor->SetClassName(Nan::New("CanvasGradient").ToLocalChecked());
// Prototype // Prototype
NODE_SET_PROTOTYPE_METHOD(ctor, "addColorStop", AddColorStop); Nan::SetPrototypeMethod(ctor, "addColorStop", AddColorStop);
target->Set(NanNew("CanvasGradient"), ctor->GetFunction()); Nan::Set(target, Nan::New("CanvasGradient").ToLocalChecked(), ctor->GetFunction());
} }
/* /*
@ -35,33 +35,33 @@ Gradient::Initialize(Handle<Object> target) {
*/ */
NAN_METHOD(Gradient::New) { NAN_METHOD(Gradient::New) {
NanScope();
// Linear // Linear
if (4 == args.Length()) { if (4 == info.Length()) {
Gradient *grad = new Gradient( Gradient *grad = new Gradient(
args[0]->NumberValue() info[0]->NumberValue()
, args[1]->NumberValue() , info[1]->NumberValue()
, args[2]->NumberValue() , info[2]->NumberValue()
, args[3]->NumberValue()); , info[3]->NumberValue());
grad->Wrap(args.This()); grad->Wrap(info.This());
NanReturnValue(args.This()); info.GetReturnValue().Set(info.This());
return;
} }
// Radial // Radial
if (6 == args.Length()) { if (6 == info.Length()) {
Gradient *grad = new Gradient( Gradient *grad = new Gradient(
args[0]->NumberValue() info[0]->NumberValue()
, args[1]->NumberValue() , info[1]->NumberValue()
, args[2]->NumberValue() , info[2]->NumberValue()
, args[3]->NumberValue() , info[3]->NumberValue()
, args[4]->NumberValue() , info[4]->NumberValue()
, args[5]->NumberValue()); , info[5]->NumberValue());
grad->Wrap(args.This()); grad->Wrap(info.This());
NanReturnValue(args.This()); info.GetReturnValue().Set(info.This());
return;
} }
return NanThrowTypeError("invalid arguments"); return Nan::ThrowTypeError("invalid arguments");
} }
/* /*
@ -69,31 +69,28 @@ NAN_METHOD(Gradient::New) {
*/ */
NAN_METHOD(Gradient::AddColorStop) { NAN_METHOD(Gradient::AddColorStop) {
NanScope(); if (!info[0]->IsNumber())
if (!args[0]->IsNumber()) return Nan::ThrowTypeError("offset required");
return NanThrowTypeError("offset required"); if (!info[1]->IsString())
if (!args[1]->IsString()) return Nan::ThrowTypeError("color string required");
return NanThrowTypeError("color string required");
Gradient *grad = ObjectWrap::Unwrap<Gradient>(args.This()); Gradient *grad = Nan::ObjectWrap::Unwrap<Gradient>(info.This());
short ok; short ok;
String::Utf8Value str(args[1]); String::Utf8Value str(info[1]);
uint32_t rgba = rgba_from_string(*str, &ok); uint32_t rgba = rgba_from_string(*str, &ok);
if (ok) { if (ok) {
rgba_t color = rgba_create(rgba); rgba_t color = rgba_create(rgba);
cairo_pattern_add_color_stop_rgba( cairo_pattern_add_color_stop_rgba(
grad->pattern() grad->pattern()
, args[0]->NumberValue() , info[0]->NumberValue()
, color.r , color.r
, color.g , color.g
, color.b , color.b
, color.a); , color.a);
} else { } else {
return NanThrowTypeError("parse color failed"); return Nan::ThrowTypeError("parse color failed");
} }
NanReturnUndefined();
} }
/* /*

6
src/CanvasGradient.h

@ -10,10 +10,10 @@
#include "Canvas.h" #include "Canvas.h"
class Gradient: public node::ObjectWrap { class Gradient: public Nan::ObjectWrap {
public: public:
static Persistent<FunctionTemplate> constructor; static Nan::Persistent<FunctionTemplate> constructor;
static void Initialize(Handle<Object> target); static void Initialize(Nan::ADDON_REGISTER_FUNCTION_ARGS_TYPE target);
static NAN_METHOD(New); static NAN_METHOD(New);
static NAN_METHOD(AddColorStop); static NAN_METHOD(AddColorStop);
Gradient(double x0, double y0, double x1, double y1); Gradient(double x0, double y0, double x1, double y1);

36
src/CanvasPattern.cc

@ -9,27 +9,27 @@
#include "Image.h" #include "Image.h"
#include "CanvasPattern.h" #include "CanvasPattern.h"
Persistent<FunctionTemplate> Pattern::constructor; Nan::Persistent<FunctionTemplate> Pattern::constructor;
/* /*
* Initialize CanvasPattern. * Initialize CanvasPattern.
*/ */
void void
Pattern::Initialize(Handle<Object> target) { Pattern::Initialize(Nan::ADDON_REGISTER_FUNCTION_ARGS_TYPE target) {
NanScope(); Nan::HandleScope scope;
// Constructor // Constructor
Local<FunctionTemplate> ctor = NanNew<FunctionTemplate>(Pattern::New); Local<FunctionTemplate> ctor = Nan::New<FunctionTemplate>(Pattern::New);
NanAssignPersistent(constructor, ctor); constructor.Reset(ctor);
ctor->InstanceTemplate()->SetInternalFieldCount(1); ctor->InstanceTemplate()->SetInternalFieldCount(1);
ctor->SetClassName(NanNew("CanvasPattern")); ctor->SetClassName(Nan::New("CanvasPattern").ToLocalChecked());
ctor->InstanceTemplate()->SetInternalFieldCount(1); ctor->InstanceTemplate()->SetInternalFieldCount(1);
ctor->SetClassName(NanNew("CanvasPattern")); ctor->SetClassName(Nan::New("CanvasPattern").ToLocalChecked());
// Prototype // Prototype
target->Set(NanNew("CanvasPattern"), ctor->GetFunction()); Nan::Set(target, Nan::New("CanvasPattern").ToLocalChecked(), ctor->GetFunction());
} }
/* /*
@ -37,39 +37,37 @@ Pattern::Initialize(Handle<Object> target) {
*/ */
NAN_METHOD(Pattern::New) { NAN_METHOD(Pattern::New) {
NanScope();
int w = 0 int w = 0
, h = 0; , h = 0;
cairo_surface_t *surface; cairo_surface_t *surface;
Local<Object> obj = args[0]->ToObject(); Local<Object> obj = info[0]->ToObject();
// Image // Image
if (NanHasInstance(Image::constructor, obj)) { if (Nan::New(Image::constructor)->HasInstance(obj)) {
Image *img = ObjectWrap::Unwrap<Image>(obj); Image *img = Nan::ObjectWrap::Unwrap<Image>(obj);
if (!img->isComplete()) { if (!img->isComplete()) {
return NanThrowError("Image given has not completed loading"); return Nan::ThrowError("Image given has not completed loading");
} }
w = img->width; w = img->width;
h = img->height; h = img->height;
surface = img->surface(); surface = img->surface();
// Canvas // Canvas
} else if (NanHasInstance(Canvas::constructor, obj)) { } else if (Nan::New(Canvas::constructor)->HasInstance(obj)) {
Canvas *canvas = ObjectWrap::Unwrap<Canvas>(obj); Canvas *canvas = Nan::ObjectWrap::Unwrap<Canvas>(obj);
w = canvas->width; w = canvas->width;
h = canvas->height; h = canvas->height;
surface = canvas->surface(); surface = canvas->surface();
// Invalid // Invalid
} else { } else {
return NanThrowTypeError("Image or Canvas expected"); return Nan::ThrowTypeError("Image or Canvas expected");
} }
Pattern *pattern = new Pattern(surface,w,h); Pattern *pattern = new Pattern(surface,w,h);
pattern->Wrap(args.This()); pattern->Wrap(info.This());
NanReturnValue(args.This()); info.GetReturnValue().Set(info.This());
} }

6
src/CanvasPattern.h

@ -10,10 +10,10 @@
#include "Canvas.h" #include "Canvas.h"
class Pattern: public node::ObjectWrap { class Pattern: public Nan::ObjectWrap {
public: public:
static Persistent<FunctionTemplate> constructor; static Nan::Persistent<FunctionTemplate> constructor;
static void Initialize(Handle<Object> target); static void Initialize(Nan::ADDON_REGISTER_FUNCTION_ARGS_TYPE target);
static NAN_METHOD(New); static NAN_METHOD(New);
Pattern(cairo_surface_t *surface, int w, int h); Pattern(cairo_surface_t *surface, int w, int h);
inline cairo_pattern_t *pattern(){ return _pattern; } inline cairo_pattern_t *pattern(){ return _pattern; }

939
src/CanvasRenderingContext2d.cc

File diff suppressed because it is too large

6
src/CanvasRenderingContext2d.h

@ -63,14 +63,14 @@ typedef struct {
void state_assign_fontFamily(canvas_state_t *state, const char *str); void state_assign_fontFamily(canvas_state_t *state, const char *str);
#endif #endif
class Context2d: public node::ObjectWrap { class Context2d: public Nan::ObjectWrap {
public: public:
short stateno; short stateno;
canvas_state_t *states[CANVAS_MAX_STATES]; canvas_state_t *states[CANVAS_MAX_STATES];
canvas_state_t *state; canvas_state_t *state;
Context2d(Canvas *canvas); Context2d(Canvas *canvas);
static Persistent<FunctionTemplate> constructor; static Nan::Persistent<FunctionTemplate> constructor;
static void Initialize(Handle<Object> target); static void Initialize(Nan::ADDON_REGISTER_FUNCTION_ARGS_TYPE target);
static NAN_METHOD(New); static NAN_METHOD(New);
static NAN_METHOD(DrawImage); static NAN_METHOD(DrawImage);
static NAN_METHOD(PutImageData); static NAN_METHOD(PutImageData);

38
src/FontFace.cc

@ -8,7 +8,7 @@
#include <fontconfig/fontconfig.h> #include <fontconfig/fontconfig.h>
Persistent<FunctionTemplate> FontFace::constructor; Nan::Persistent<FunctionTemplate> FontFace::constructor;
/* /*
* Destroy ft_face. * Destroy ft_face.
@ -26,17 +26,17 @@ FontFace::~FontFace() {
*/ */
void void
FontFace::Initialize(Handle<Object> target) { FontFace::Initialize(Nan::ADDON_REGISTER_FUNCTION_ARGS_TYPE target) {
NanScope(); Nan::HandleScope scope;
// Constructor // Constructor
Local<FunctionTemplate> ctor = NanNew<FunctionTemplate>(FontFace::New); Local<FunctionTemplate> ctor = Nan::New<FunctionTemplate>(FontFace::New);
NanAssignPersistent(constructor, ctor); constructor.Reset(ctor);
ctor->InstanceTemplate()->SetInternalFieldCount(1); ctor->InstanceTemplate()->SetInternalFieldCount(1);
ctor->SetClassName(NanNew("FontFace")); ctor->SetClassName(Nan::New("FontFace").ToLocalChecked());
// Prototype // Prototype
target->Set(NanNew("FontFace"), ctor->GetFunction()); Nan::Set(target, Nan::New("FontFace").ToLocalChecked(), ctor->GetFunction());
} }
/* /*
@ -53,15 +53,13 @@ static cairo_user_data_key_t key;
*/ */
NAN_METHOD(FontFace::New) { NAN_METHOD(FontFace::New) {
NanScope(); if (!info[0]->IsString()
|| !info[1]->IsNumber()) {
if (!args[0]->IsString() return Nan::ThrowError("Wrong argument types passed to FontFace constructor");
|| !args[1]->IsNumber()) {
return NanThrowError("Wrong argument types passed to FontFace constructor");
} }
String::Utf8Value filePath(args[0]); String::Utf8Value filePath(info[0]);
int faceIdx = int(args[1]->NumberValue()); int faceIdx = int(info[1]->NumberValue());
FT_Face ftFace; FT_Face ftFace;
FT_Error ftError; FT_Error ftError;
@ -71,21 +69,21 @@ NAN_METHOD(FontFace::New) {
_initLibrary = false; _initLibrary = false;
ftError = FT_Init_FreeType(&library); ftError = FT_Init_FreeType(&library);
if (ftError) { if (ftError) {
return NanThrowError("Could not load library"); return Nan::ThrowError("Could not load library");
} }
} }
// Create new freetype font face. // Create new freetype font face.
ftError = FT_New_Face(library, *filePath, faceIdx, &ftFace); ftError = FT_New_Face(library, *filePath, faceIdx, &ftFace);
if (ftError) { if (ftError) {
return NanThrowError("Could not load font file"); return Nan::ThrowError("Could not load font file");
} }
#if HAVE_PANGO #if HAVE_PANGO
// Load the font file in fontconfig // Load the font file in fontconfig
FcBool ok = FcConfigAppFontAddFile(FcConfigGetCurrent(), (FcChar8 *)(*filePath)); FcBool ok = FcConfigAppFontAddFile(FcConfigGetCurrent(), (FcChar8 *)(*filePath));
if (!ok) { if (!ok) {
return NanThrowError("Could not load font in FontConfig"); return Nan::ThrowError("Could not load font in FontConfig");
} }
#endif #endif
@ -98,7 +96,7 @@ NAN_METHOD(FontFace::New) {
if (status) { if (status) {
cairo_font_face_destroy (crFace); cairo_font_face_destroy (crFace);
FT_Done_Face (ftFace); FT_Done_Face (ftFace);
return NanThrowError("Failed to setup cairo font face user data"); return Nan::ThrowError("Failed to setup cairo font face user data");
} }
// Explicit reference count the cairo font face. Otherwise the font face might // Explicit reference count the cairo font face. Otherwise the font face might
@ -106,7 +104,7 @@ NAN_METHOD(FontFace::New) {
cairo_font_face_reference(crFace); cairo_font_face_reference(crFace);
FontFace *face = new FontFace(ftFace, crFace); FontFace *face = new FontFace(ftFace, crFace);
face->Wrap(args.This()); face->Wrap(info.This());
NanReturnValue(args.This()); info.GetReturnValue().Set(info.This());
} }

6
src/FontFace.h

@ -13,10 +13,10 @@
#include <cairo-ft.h> #include <cairo-ft.h>
#include FT_FREETYPE_H #include FT_FREETYPE_H
class FontFace: public node::ObjectWrap { class FontFace: public Nan::ObjectWrap {
public: public:
static Persistent<FunctionTemplate> constructor; static Nan::Persistent<FunctionTemplate> constructor;
static void Initialize(Handle<Object> target); static void Initialize(Nan::ADDON_REGISTER_FUNCTION_ARGS_TYPE target);
static NAN_METHOD(New); static NAN_METHOD(New);
FontFace(FT_Face ftFace, cairo_font_face_t *crFace) FontFace(FT_Face ftFace, cairo_font_face_t *crFace)
:_ftFace(ftFace), _crFace(crFace) {} :_ftFace(ftFace), _crFace(crFace) {}

105
src/Image.cc

@ -28,38 +28,38 @@ typedef struct {
uint8_t *buf; uint8_t *buf;
} read_closure_t; } read_closure_t;
Persistent<FunctionTemplate> Image::constructor; Nan::Persistent<FunctionTemplate> Image::constructor;
/* /*
* Initialize Image. * Initialize Image.
*/ */
void void
Image::Initialize(Handle<Object> target) { Image::Initialize(Nan::ADDON_REGISTER_FUNCTION_ARGS_TYPE target) {
NanScope(); Nan::HandleScope scope;
Local<FunctionTemplate> ctor = NanNew<FunctionTemplate>(Image::New); Local<FunctionTemplate> ctor = Nan::New<FunctionTemplate>(Image::New);
NanAssignPersistent(constructor, ctor); constructor.Reset(ctor);
ctor->InstanceTemplate()->SetInternalFieldCount(1); ctor->InstanceTemplate()->SetInternalFieldCount(1);
ctor->SetClassName(NanNew("Image")); ctor->SetClassName(Nan::New("Image").ToLocalChecked());
ctor->InstanceTemplate()->SetInternalFieldCount(1); ctor->InstanceTemplate()->SetInternalFieldCount(1);
ctor->SetClassName(NanNew("Image")); ctor->SetClassName(Nan::New("Image").ToLocalChecked());
// Prototype // Prototype
Local<ObjectTemplate> proto = ctor->PrototypeTemplate(); Local<ObjectTemplate> proto = ctor->PrototypeTemplate();
proto->SetAccessor(NanNew("source"), GetSource, SetSource); Nan::SetAccessor(proto, Nan::New("source").ToLocalChecked(), GetSource, SetSource);
proto->SetAccessor(NanNew("complete"), GetComplete); Nan::SetAccessor(proto, Nan::New("complete").ToLocalChecked(), GetComplete);
proto->SetAccessor(NanNew("width"), GetWidth); Nan::SetAccessor(proto, Nan::New("width").ToLocalChecked(), GetWidth);
proto->SetAccessor(NanNew("height"), GetHeight); Nan::SetAccessor(proto, Nan::New("height").ToLocalChecked(), GetHeight);
proto->SetAccessor(NanNew("onload"), GetOnload, SetOnload); Nan::SetAccessor(proto, Nan::New("onload").ToLocalChecked(), GetOnload, SetOnload);
proto->SetAccessor(NanNew("onerror"), GetOnerror, SetOnerror); Nan::SetAccessor(proto, Nan::New("onerror").ToLocalChecked(), GetOnerror, SetOnerror);
#if CAIRO_VERSION_MINOR >= 10 #if CAIRO_VERSION_MINOR >= 10
proto->SetAccessor(NanNew("dataMode"), GetDataMode, SetDataMode); Nan::SetAccessor(proto, Nan::New("dataMode").ToLocalChecked(), GetDataMode, SetDataMode);
ctor->Set(NanNew("MODE_IMAGE"), NanNew<Number>(DATA_IMAGE)); ctor->Set(Nan::New("MODE_IMAGE").ToLocalChecked(), Nan::New<Number>(DATA_IMAGE));
ctor->Set(NanNew("MODE_MIME"), NanNew<Number>(DATA_MIME)); ctor->Set(Nan::New("MODE_MIME").ToLocalChecked(), Nan::New<Number>(DATA_MIME));
#endif #endif
target->Set(NanNew("Image"), ctor->GetFunction()); Nan::Set(target, Nan::New("Image").ToLocalChecked(), ctor->GetFunction());
} }
/* /*
@ -67,11 +67,10 @@ Image::Initialize(Handle<Object> target) {
*/ */
NAN_METHOD(Image::New) { NAN_METHOD(Image::New) {
NanScope();
Image *img = new Image; Image *img = new Image;
img->data_mode = DATA_IMAGE; img->data_mode = DATA_IMAGE;
img->Wrap(args.This()); img->Wrap(info.This());
NanReturnValue(args.This()); info.GetReturnValue().Set(info.This());
} }
/* /*
@ -79,9 +78,8 @@ NAN_METHOD(Image::New) {
*/ */
NAN_GETTER(Image::GetComplete) { NAN_GETTER(Image::GetComplete) {
NanScope(); Image *img = Nan::ObjectWrap::Unwrap<Image>(info.This());
Image *img = ObjectWrap::Unwrap<Image>(args.This()); info.GetReturnValue().Set(Nan::New<Boolean>(Image::COMPLETE == img->state));
NanReturnValue(NanNew<Boolean>(Image::COMPLETE == img->state));
} }
#if CAIRO_VERSION_MINOR >= 10 #if CAIRO_VERSION_MINOR >= 10
@ -91,9 +89,8 @@ NAN_GETTER(Image::GetComplete) {
*/ */
NAN_GETTER(Image::GetDataMode) { NAN_GETTER(Image::GetDataMode) {
NanScope(); Image *img = Nan::ObjectWrap::Unwrap<Image>(info.This());
Image *img = ObjectWrap::Unwrap<Image>(args.This()); info.GetReturnValue().Set(Nan::New<Number>(img->data_mode));
NanReturnValue(NanNew<Number>(img->data_mode));
} }
/* /*
@ -102,7 +99,7 @@ NAN_GETTER(Image::GetDataMode) {
NAN_SETTER(Image::SetDataMode) { NAN_SETTER(Image::SetDataMode) {
if (value->IsNumber()) { if (value->IsNumber()) {
Image *img = ObjectWrap::Unwrap<Image>(args.This()); Image *img = Nan::ObjectWrap::Unwrap<Image>(info.This());
int mode = value->Uint32Value(); int mode = value->Uint32Value();
img->data_mode = (data_mode_t) mode; img->data_mode = (data_mode_t) mode;
} }
@ -115,18 +112,16 @@ NAN_SETTER(Image::SetDataMode) {
*/ */
NAN_GETTER(Image::GetWidth) { NAN_GETTER(Image::GetWidth) {
NanScope(); Image *img = Nan::ObjectWrap::Unwrap<Image>(info.This());
Image *img = ObjectWrap::Unwrap<Image>(args.This()); info.GetReturnValue().Set(Nan::New<Number>(img->width));
NanReturnValue(NanNew<Number>(img->width));
} }
/* /*
* Get height. * Get height.
*/ */
NAN_GETTER(Image::GetHeight) { NAN_GETTER(Image::GetHeight) {
NanScope(); Image *img = Nan::ObjectWrap::Unwrap<Image>(info.This());
Image *img = ObjectWrap::Unwrap<Image>(args.This()); info.GetReturnValue().Set(Nan::New<Number>(img->height));
NanReturnValue(NanNew<Number>(img->height));
} }
/* /*
@ -134,9 +129,8 @@ NAN_GETTER(Image::GetHeight) {
*/ */
NAN_GETTER(Image::GetSource) { NAN_GETTER(Image::GetSource) {
NanScope(); Image *img = Nan::ObjectWrap::Unwrap<Image>(info.This());
Image *img = ObjectWrap::Unwrap<Image>(args.This()); info.GetReturnValue().Set(Nan::New<String>(img->filename ? img->filename : "").ToLocalChecked());
NanReturnValue(NanNew<String>(img->filename ? img->filename : ""));
} }
/* /*
@ -147,7 +141,7 @@ void
Image::clearData() { Image::clearData() {
if (_surface) { if (_surface) {
cairo_surface_destroy(_surface); cairo_surface_destroy(_surface);
NanAdjustExternalMemory(-_data_len); Nan::AdjustExternalMemory(-_data_len);
_data_len = 0; _data_len = 0;
_surface = NULL; _surface = NULL;
} }
@ -167,8 +161,7 @@ Image::clearData() {
*/ */
NAN_SETTER(Image::SetSource) { NAN_SETTER(Image::SetSource) {
NanScope(); Image *img = Nan::ObjectWrap::Unwrap<Image>(info.This());
Image *img = ObjectWrap::Unwrap<Image>(args.This());
cairo_status_t status = CAIRO_STATUS_READ_ERROR; cairo_status_t status = CAIRO_STATUS_READ_ERROR;
img->clearData(); img->clearData();
@ -259,12 +252,11 @@ Image::readPNG(void *c, uint8_t *data, unsigned int len) {
*/ */
NAN_GETTER(Image::GetOnload) { NAN_GETTER(Image::GetOnload) {
NanScope(); Image *img = Nan::ObjectWrap::Unwrap<Image>(info.This());
Image *img = ObjectWrap::Unwrap<Image>(args.This());
if (img->onload) { if (img->onload) {
NanReturnValue(img->onload->GetFunction()); info.GetReturnValue().Set(img->onload->GetFunction());
} else { } else {
NanReturnNull(); info.GetReturnValue().SetNull();
} }
} }
@ -274,8 +266,8 @@ NAN_GETTER(Image::GetOnload) {
NAN_SETTER(Image::SetOnload) { NAN_SETTER(Image::SetOnload) {
if (value->IsFunction()) { if (value->IsFunction()) {
Image *img = ObjectWrap::Unwrap<Image>(args.This()); Image *img = Nan::ObjectWrap::Unwrap<Image>(info.This());
img->onload = new NanCallback(value.As<Function>()); img->onload = new Nan::Callback(value.As<Function>());
} }
} }
@ -284,12 +276,11 @@ NAN_SETTER(Image::SetOnload) {
*/ */
NAN_GETTER(Image::GetOnerror) { NAN_GETTER(Image::GetOnerror) {
NanScope(); Image *img = Nan::ObjectWrap::Unwrap<Image>(info.This());
Image *img = ObjectWrap::Unwrap<Image>(args.This());
if (img->onerror) { if (img->onerror) {
NanReturnValue(img->onerror->GetFunction()); info.GetReturnValue().Set(img->onerror->GetFunction());
} else { } else {
NanReturnNull(); info.GetReturnValue().SetNull();
} }
} }
@ -299,8 +290,8 @@ NAN_GETTER(Image::GetOnerror) {
NAN_SETTER(Image::SetOnerror) { NAN_SETTER(Image::SetOnerror) {
if (value->IsFunction()) { if (value->IsFunction()) {
Image *img = ObjectWrap::Unwrap<Image>(args.This()); Image *img = Nan::ObjectWrap::Unwrap<Image>(info.This());
img->onerror = new NanCallback(value.As<Function>()); img->onerror = new Nan::Callback(value.As<Function>());
} }
} }
@ -356,13 +347,13 @@ Image::load() {
void void
Image::loaded() { Image::loaded() {
NanScope(); Nan::HandleScope scope;
state = COMPLETE; state = COMPLETE;
width = cairo_image_surface_get_width(_surface); width = cairo_image_surface_get_width(_surface);
height = cairo_image_surface_get_height(_surface); height = cairo_image_surface_get_height(_surface);
_data_len = height * cairo_image_surface_get_stride(_surface); _data_len = height * cairo_image_surface_get_stride(_surface);
NanAdjustExternalMemory(_data_len); Nan::AdjustExternalMemory(_data_len);
if (onload != NULL) { if (onload != NULL) {
onload->Call(0, NULL); onload->Call(0, NULL);
@ -377,7 +368,7 @@ Image::loaded() {
void void
Image::error(Local<Value> err) { Image::error(Local<Value> err) {
NanScope(); Nan::HandleScope scope;
if (onerror != NULL) { if (onerror != NULL) {
Local<Value> argv[1] = { err }; Local<Value> argv[1] = { err };
onerror->Call(1, argv); onerror->Call(1, argv);
@ -448,7 +439,7 @@ get_gif_transparent_color(GifFileType *gif, int frame) {
int len = gif->SavedImages[frame].ExtensionBlockCount; int len = gif->SavedImages[frame].ExtensionBlockCount;
for (int x = 0; x < len; ++x, ++ext) { for (int x = 0; x < len; ++x, ++ext) {
if ((ext->Function == GRAPHICS_EXT_FUNC_CODE) && (ext->Bytes[0] & 1)) { if ((ext->Function == GRAPHICS_EXT_FUNC_CODE) && (ext->Bytes[0] & 1)) {
return ext->Bytes[3] == 0 ? 0 : (uint8_t) ext->Bytes[3]; return ext->Bytes[3] == 0 ? 0 : (uint8_t) ext->Bytes[3];
} }
} }
return -1; return -1;
@ -810,7 +801,7 @@ Image::decodeJPEGBufferIntoMimeSurface(uint8_t *buf, unsigned len) {
void void
clearMimeData(void *closure) { clearMimeData(void *closure) {
NanAdjustExternalMemory(-((read_closure_t *)closure)->len); Nan::AdjustExternalMemory(-((read_closure_t *)closure)->len);
free(((read_closure_t *) closure)->buf); free(((read_closure_t *) closure)->buf);
free(closure); free(closure);
} }
@ -837,7 +828,7 @@ Image::assignDataAsMime(uint8_t *data, int len, const char *mime_type) {
mime_closure->buf = mime_data; mime_closure->buf = mime_data;
mime_closure->len = len; mime_closure->len = len;
NanAdjustExternalMemory(len); Nan::AdjustExternalMemory(len);
return cairo_surface_set_mime_data(_surface return cairo_surface_set_mime_data(_surface
, mime_type , mime_type

16
src/Image.h

@ -27,14 +27,14 @@
class Image: public node::ObjectWrap { class Image: public Nan::ObjectWrap {
public: public:
char *filename; char *filename;
int width, height; int width, height;
NanCallback *onload; Nan::Callback *onload;
NanCallback *onerror; Nan::Callback *onerror;
static Persistent<FunctionTemplate> constructor; static Nan::Persistent<FunctionTemplate> constructor;
static void Initialize(Handle<Object> target); static void Initialize(Nan::ADDON_REGISTER_FUNCTION_ARGS_TYPE target);
static NAN_METHOD(New); static NAN_METHOD(New);
static NAN_GETTER(GetSource); static NAN_GETTER(GetSource);
static NAN_GETTER(GetOnload); static NAN_GETTER(GetOnload);
@ -47,9 +47,9 @@ class Image: public node::ObjectWrap {
static NAN_SETTER(SetOnload); static NAN_SETTER(SetOnload);
static NAN_SETTER(SetOnerror); static NAN_SETTER(SetOnerror);
static NAN_SETTER(SetDataMode); static NAN_SETTER(SetDataMode);
inline cairo_surface_t *surface(){ return _surface; } inline cairo_surface_t *surface(){ return _surface; }
inline uint8_t *data(){ return cairo_image_surface_get_data(_surface); } inline uint8_t *data(){ return cairo_image_surface_get_data(_surface); }
inline int stride(){ return cairo_image_surface_get_stride(_surface); } inline int stride(){ return cairo_image_surface_get_stride(_surface); }
static int isPNG(uint8_t *data); static int isPNG(uint8_t *data);
static int isJPEG(uint8_t *data); static int isJPEG(uint8_t *data);
static int isGIF(uint8_t *data); static int isGIF(uint8_t *data);

70
src/ImageData.cc

@ -7,27 +7,27 @@
#include "ImageData.h" #include "ImageData.h"
Persistent<FunctionTemplate> ImageData::constructor; Nan::Persistent<FunctionTemplate> ImageData::constructor;
/* /*
* Initialize ImageData. * Initialize ImageData.
*/ */
void void
ImageData::Initialize(Handle<Object> target) { ImageData::Initialize(Nan::ADDON_REGISTER_FUNCTION_ARGS_TYPE target) {
NanScope(); Nan::HandleScope scope;
// Constructor // Constructor
Local<FunctionTemplate> ctor = NanNew<FunctionTemplate>(ImageData::New); Local<FunctionTemplate> ctor = Nan::New<FunctionTemplate>(ImageData::New);
NanAssignPersistent(constructor, ctor); constructor.Reset(ctor);
ctor->InstanceTemplate()->SetInternalFieldCount(1); ctor->InstanceTemplate()->SetInternalFieldCount(1);
ctor->SetClassName(NanNew("ImageData")); ctor->SetClassName(Nan::New("ImageData").ToLocalChecked());
// Prototype // Prototype
Local<ObjectTemplate> proto = ctor->PrototypeTemplate(); Local<ObjectTemplate> proto = ctor->PrototypeTemplate();
proto->SetAccessor(NanNew("width"), GetWidth); Nan::SetAccessor(proto, Nan::New("width").ToLocalChecked(), GetWidth);
proto->SetAccessor(NanNew("height"), GetHeight); Nan::SetAccessor(proto, Nan::New("height").ToLocalChecked(), GetHeight);
target->Set(NanNew("ImageData"), ctor->GetFunction()); Nan::Set(target, Nan::New("ImageData").ToLocalChecked(), ctor->GetFunction());
} }
/* /*
@ -35,8 +35,6 @@ ImageData::Initialize(Handle<Object> target) {
*/ */
NAN_METHOD(ImageData::New) { NAN_METHOD(ImageData::New) {
NanScope();
#if NODE_MAJOR_VERSION == 0 && NODE_MINOR_VERSION <= 10 #if NODE_MAJOR_VERSION == 0 && NODE_MINOR_VERSION <= 10
Local<v8::Object> clampedArray; Local<v8::Object> clampedArray;
Local<Object> global = Context::GetCurrent()->Global(); Local<Object> global = Context::GetCurrent()->Global();
@ -47,29 +45,29 @@ NAN_METHOD(ImageData::New) {
int width; int width;
int height; int height;
if (info[0]->IsUint32() && info[1]->IsUint32()) {
if (args[0]->IsUint32() && args[1]->IsUint32()) { width = info[0]->Uint32Value();
width = args[0]->Uint32Value(); height = info[1]->Uint32Value();
height = args[1]->Uint32Value();
int size = width * height; int size = width * height;
#if NODE_MAJOR_VERSION == 0 && NODE_MINOR_VERSION <= 10 #if NODE_MAJOR_VERSION == 0 && NODE_MINOR_VERSION <= 10
Handle<Value> caargv[] = { NanNew(size) }; Local<Int32> sizeHandle = Nan::New(size);
Local<Object> clampedArray = global->Get(NanNew("Uint8ClampedArray")).As<Function>()->NewInstance(1, caargv); Local<Value> caargv[] = { sizeHandle };
clampedArray = global->Get(Nan::New("Uint8ClampedArray").ToLocalChecked()).As<Function>()->NewInstance(1, caargv);
#else #else
clampedArray = Uint8ClampedArray::New(ArrayBuffer::New(Isolate::GetCurrent(), size), 0, size); clampedArray = Uint8ClampedArray::New(ArrayBuffer::New(Isolate::GetCurrent(), size), 0, size);
#endif #endif
#if NODE_MAJOR_VERSION == 0 && NODE_MINOR_VERSION <= 10 #if NODE_MAJOR_VERSION == 0 && NODE_MINOR_VERSION <= 10
} else if (args[0]->ToObject()->GetIndexedPropertiesExternalArrayDataType() == kExternalPixelArray && args[1]->IsUint32()) { } else if (info[0]->ToObject()->GetIndexedPropertiesExternalArrayDataType() == kExternalPixelArray && info[1]->IsUint32()) {
clampedArray = args[0]->ToObject(); clampedArray = info[0]->ToObject();
#else #else
} else if (args[0]->IsUint8ClampedArray() && args[1]->IsUint32()) { } else if (info[0]->IsUint8ClampedArray() && info[1]->IsUint32()) {
clampedArray = args[0].As<Uint8ClampedArray>(); clampedArray = info[0].As<Uint8ClampedArray>();
#endif #endif
width = args[1]->Uint32Value(); width = info[1]->Uint32Value();
if (args[2]->IsUint32()) { if (info[2]->IsUint32()) {
height = args[2]->Uint32Value(); height = info[2]->Uint32Value();
} else { } else {
#if NODE_MAJOR_VERSION == 0 && NODE_MINOR_VERSION <= 10 #if NODE_MAJOR_VERSION == 0 && NODE_MINOR_VERSION <= 10
height = clampedArray->GetIndexedPropertiesExternalArrayDataLength() / width; height = clampedArray->GetIndexedPropertiesExternalArrayDataLength() / width;
@ -78,20 +76,24 @@ NAN_METHOD(ImageData::New) {
#endif #endif
} }
} else { } else {
NanThrowTypeError("Expected (Uint8ClampedArray, width[, height]) or (width, height)"); Nan::ThrowTypeError("Expected (Uint8ClampedArray, width[, height]) or (width, height)");
NanReturnUndefined(); return;
} }
// No behavior defined in spec. This is what WebKit does: // No behavior defined in spec. This is what WebKit does:
if (width < 1) width = 1; if (width < 1) width = 1;
if (height < 1) height = 1; if (height < 1) height = 1;
#if NODE_MAJOR_VERSION < 3
void *dataPtr = clampedArray->GetIndexedPropertiesExternalArrayData(); void *dataPtr = clampedArray->GetIndexedPropertiesExternalArrayData();
#else
void *dataPtr = clampedArray->Buffer()->GetContents().Data();
#endif
ImageData *imageData = new ImageData(reinterpret_cast<uint8_t*>(dataPtr), width, height); ImageData *imageData = new ImageData(reinterpret_cast<uint8_t*>(dataPtr), width, height);
imageData->Wrap(args.This()); imageData->Wrap(info.This());
args.This()->Set(NanNew("data"), clampedArray); info.This()->Set(Nan::New("data").ToLocalChecked(), clampedArray);
NanReturnValue(args.This()); info.GetReturnValue().Set(info.This());
} }
/* /*
@ -99,9 +101,8 @@ NAN_METHOD(ImageData::New) {
*/ */
NAN_GETTER(ImageData::GetWidth) { NAN_GETTER(ImageData::GetWidth) {
NanScope(); ImageData *imageData = Nan::ObjectWrap::Unwrap<ImageData>(info.This());
ImageData *imageData = ObjectWrap::Unwrap<ImageData>(args.This()); info.GetReturnValue().Set(Nan::New<Number>(imageData->width()));
NanReturnValue(NanNew<Number>(imageData->width()));
} }
/* /*
@ -109,7 +110,6 @@ NAN_GETTER(ImageData::GetWidth) {
*/ */
NAN_GETTER(ImageData::GetHeight) { NAN_GETTER(ImageData::GetHeight) {
NanScope(); ImageData *imageData = Nan::ObjectWrap::Unwrap<ImageData>(info.This());
ImageData *imageData = ObjectWrap::Unwrap<ImageData>(args.This()); info.GetReturnValue().Set(Nan::New<Number>(imageData->height()));
NanReturnValue(NanNew<Number>(imageData->height()));
} }

6
src/ImageData.h

@ -12,10 +12,10 @@
#include <stdlib.h> #include <stdlib.h>
#include "v8.h" #include "v8.h"
class ImageData: public node::ObjectWrap { class ImageData: public Nan::ObjectWrap {
public: public:
static Persistent<FunctionTemplate> constructor; static Nan::Persistent<FunctionTemplate> constructor;
static void Initialize(Handle<Object> target); static void Initialize(Nan::ADDON_REGISTER_FUNCTION_ARGS_TYPE target);
static NAN_METHOD(New); static NAN_METHOD(New);
static NAN_GETTER(GetWidth); static NAN_GETTER(GetWidth);
static NAN_GETTER(GetHeight); static NAN_GETTER(GetHeight);

32
src/JPEGStream.h

@ -29,15 +29,15 @@ init_closure_destination(j_compress_ptr cinfo){
boolean boolean
empty_closure_output_buffer(j_compress_ptr cinfo){ empty_closure_output_buffer(j_compress_ptr cinfo){
NanScope(); Nan::HandleScope scope;
closure_destination_mgr *dest = (closure_destination_mgr *) cinfo->dest; closure_destination_mgr *dest = (closure_destination_mgr *) cinfo->dest;
Local<Object> buf = NanNewBufferHandle((char *)dest->buffer, dest->bufsize); Local<Object> buf = Nan::NewBuffer((char *)dest->buffer, dest->bufsize).ToLocalChecked();
Local<Value> argv[3] = { Local<Value> argv[3] = {
NanNew(NanNull()) Nan::Null()
, NanNew(buf) , buf
, NanNew<Integer>(dest->bufsize) , Nan::New<Integer>(dest->bufsize)
}; };
NanMakeCallback(NanGetCurrentContext()->Global(), dest->closure->fn, 3, argv); Nan::MakeCallback(Nan::GetCurrentContext()->Global(), (v8::Local<v8::Function>)dest->closure->fn, 3, argv);
cinfo->dest->next_output_byte = dest->buffer; cinfo->dest->next_output_byte = dest->buffer;
cinfo->dest->free_in_buffer = dest->bufsize; cinfo->dest->free_in_buffer = dest->bufsize;
return true; return true;
@ -45,28 +45,28 @@ empty_closure_output_buffer(j_compress_ptr cinfo){
void void
term_closure_destination(j_compress_ptr cinfo){ term_closure_destination(j_compress_ptr cinfo){
NanScope(); Nan::HandleScope scope;
closure_destination_mgr *dest = (closure_destination_mgr *) cinfo->dest; closure_destination_mgr *dest = (closure_destination_mgr *) cinfo->dest;
/* emit remaining data */ /* emit remaining data */
size_t remaining = dest->bufsize - cinfo->dest->free_in_buffer; size_t remaining = dest->bufsize - cinfo->dest->free_in_buffer;
Local<Object> buf = NanNewBufferHandle((char *)dest->buffer, remaining); Local<Object> buf = Nan::NewBuffer((char *)dest->buffer, remaining).ToLocalChecked();
Local<Value> data_argv[3] = { Local<Value> data_argv[3] = {
NanNew(NanNull()) Nan::Null()
, NanNew(buf) , buf
, NanNew<Number>(remaining) , Nan::New<Number>(remaining)
}; };
NanMakeCallback(NanGetCurrentContext()->Global(), dest->closure->fn, 3, data_argv); Nan::MakeCallback(Nan::GetCurrentContext()->Global(), (v8::Local<v8::Function>)dest->closure->fn, 3, data_argv);
// emit "end" // emit "end"
Local<Value> end_argv[3] = { Local<Value> end_argv[3] = {
NanNew(NanNull()) Nan::Null()
, NanNew(NanNull()) , Nan::Null()
, NanNew<Integer>(0) , Nan::New<Integer>(0)
}; };
NanMakeCallback(NanGetCurrentContext()->Global(), dest->closure->fn, 3, end_argv); Nan::MakeCallback(Nan::GetCurrentContext()->Global(), (v8::Local<v8::Function>)dest->closure->fn, 3, end_argv);
} }
void void

6
src/closure.h

@ -23,8 +23,8 @@
*/ */
typedef struct { typedef struct {
NanCallback *pfn; Nan::Callback *pfn;
Handle<Function> fn; Local<Function> fn;
unsigned len; unsigned len;
unsigned max_len; unsigned max_len;
uint8_t *data; uint8_t *data;
@ -58,7 +58,7 @@ void
closure_destroy(closure_t *closure) { closure_destroy(closure_t *closure) {
if (closure->len) { if (closure->len) {
free(closure->data); free(closure->data);
NanAdjustExternalMemory(-((intptr_t) closure->max_len)); Nan::AdjustExternalMemory(-((intptr_t) closure->max_len));
} }
} }

12
src/init.cc

@ -17,9 +17,7 @@
#include "FontFace.h" #include "FontFace.h"
#endif #endif
extern "C" void NAN_MODULE_INIT(init) {
init (Handle<Object> target) {
NanScope();
Canvas::Initialize(target); Canvas::Initialize(target);
Image::Initialize(target); Image::Initialize(target);
ImageData::Initialize(target); ImageData::Initialize(target);
@ -30,7 +28,7 @@ init (Handle<Object> target) {
FontFace::Initialize(target); FontFace::Initialize(target);
#endif #endif
target->Set(NanNew<String>("cairoVersion"), NanNew<String>(cairo_version_string())); target->Set(Nan::New<String>("cairoVersion").ToLocalChecked(), Nan::New<String>(cairo_version_string()).ToLocalChecked());
#ifdef HAVE_JPEG #ifdef HAVE_JPEG
#ifndef JPEG_LIB_VERSION_MAJOR #ifndef JPEG_LIB_VERSION_MAJOR
@ -55,16 +53,16 @@ init (Handle<Object> target) {
} else { } else {
snprintf(jpeg_version, 10, "%d", JPEG_LIB_VERSION_MAJOR); snprintf(jpeg_version, 10, "%d", JPEG_LIB_VERSION_MAJOR);
} }
target->Set(NanNew<String>("jpegVersion"), NanNew<String>(jpeg_version)); target->Set(Nan::New<String>("jpegVersion").ToLocalChecked(), Nan::New<String>(jpeg_version).ToLocalChecked());
#endif #endif
#ifdef HAVE_GIF #ifdef HAVE_GIF
#ifndef GIF_LIB_VERSION #ifndef GIF_LIB_VERSION
char gif_version[10]; char gif_version[10];
snprintf(gif_version, 10, "%d.%d.%d", GIFLIB_MAJOR, GIFLIB_MINOR, GIFLIB_RELEASE); snprintf(gif_version, 10, "%d.%d.%d", GIFLIB_MAJOR, GIFLIB_MINOR, GIFLIB_RELEASE);
target->Set(NanNew<String>("gifVersion"), NanNew<String>(gif_version)); target->Set(Nan::New<String>("gifVersion").ToLocalChecked(), Nan::New<String>(gif_version).ToLocalChecked());
#else #else
target->Set(NanNew<String>("gifVersion"), NanNew<String>(GIF_LIB_VERSION)); target->Set(Nan::New<String>("gifVersion").ToLocalChecked(), Nan::New<String>(GIF_LIB_VERSION).ToLocalChecked());
#endif #endif
#endif #endif
} }

18
test/canvas.test.js

@ -639,5 +639,23 @@ module.exports = {
assert.equal(0, imageData.data[i+2]); assert.equal(0, imageData.data[i+2]);
assert.equal(255, imageData.data[i+3]); assert.equal(255, imageData.data[i+3]);
},
'test Canvas#createSyncPNGStream()': function(done) {
var canvas = new Canvas(20, 20);
var stream = canvas.createSyncPNGStream();
var firstChunk = true;
stream.on('data', function(chunk){
if (firstChunk) {
firstChunk = false;
assert.equal('PNG', chunk.slice(1,4).toString());
}
});
stream.on('end', function(){
done();
});
stream.on('error', function(err) {
done(err);
});
} }
} }

Loading…
Cancel
Save