Browse Source

Added another optional argument for setting row filters.

v1.x
King Koopa 12 years ago
committed by TJ Holowaychuk
parent
commit
14d9f587b6
  1. 130
      src/Canvas.cc
  2. 1
      src/PNG.h
  3. 6
      src/closure.h

130
src/Canvas.cc

@ -45,6 +45,15 @@ Canvas::Initialize(Handle<Object> target) {
proto->SetAccessor(NanSymbol("type"), GetType); proto->SetAccessor(NanSymbol("type"), GetType);
proto->SetAccessor(NanSymbol("width"), GetWidth, SetWidth); proto->SetAccessor(NanSymbol("width"), GetWidth, SetWidth);
proto->SetAccessor(NanSymbol("height"), GetHeight, SetHeight); proto->SetAccessor(NanSymbol("height"), GetHeight, SetHeight);
proto->Set("PNG_NO_FILTERS", Uint32::New(PNG_NO_FILTERS));
proto->Set("PNG_FILTER_NONE", Uint32::New(PNG_FILTER_NONE));
proto->Set("PNG_FILTER_SUB", Uint32::New(PNG_FILTER_SUB));
proto->Set("PNG_FILTER_UP", Uint32::New(PNG_FILTER_UP));
proto->Set("PNG_FILTER_AVG", Uint32::New(PNG_FILTER_AVG));
proto->Set("PNG_FILTER_PAETH", Uint32::New(PNG_FILTER_PAETH));
proto->Set("PNG_ALL_FILTERS", Uint32::New(PNG_ALL_FILTERS));
target->Set(NanSymbol("Canvas"), ctor->GetFunction()); target->Set(NanSymbol("Canvas"), ctor->GetFunction());
} }
@ -225,6 +234,7 @@ NAN_METHOD(Canvas::ToBuffer) {
NanScope(); 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;
Canvas *canvas = ObjectWrap::Unwrap<Canvas>(args.This()); Canvas *canvas = ObjectWrap::Unwrap<Canvas>(args.This());
// TODO: async / move this out // TODO: async / move this out
@ -236,38 +246,48 @@ NAN_METHOD(Canvas::ToBuffer) {
NanReturnValue(buf); NanReturnValue(buf);
} }
if (args.Length() == 2 && !args[1]->StrictEquals(Undefined())) { if (args.Length() > 1 && !(args[1]->StrictEquals(Undefined()) && args[2]->StrictEquals(Undefined()))) {
bool good = true; if (!args[1]->StrictEquals(Undefined())) {
if (args[1]->IsNumber()) { bool good = true;
compression_level = args[1]->Uint32Value(); if (args[1]->IsNumber()) {
} else if (args[1]->IsString()) { compression_level = args[1]->Uint32Value();
if (args[1]->StrictEquals(String::New("0"))) { } else if (args[1]->IsString()) {
compression_level = 0; if (args[1]->StrictEquals(String::New("0"))) {
} else { compression_level = 0;
uint32_t tmp = args[1]->Uint32Value();
if (tmp == 0) {
good = false;
} else { } else {
compression_level = tmp; uint32_t tmp = args[1]->Uint32Value();
if (tmp == 0) {
good = false;
} else {
compression_level = tmp;
}
} }
} } else {
} else { good = false;
good = false; }
}
if (good) {
if (good) { if (compression_level > 9) {
if (compression_level > 9) { return NanThrowRangeError("Allowed compression levels lie in the range [0, 9].");
return NanThrowRangeError("Allowed compression levels lie in the range [0, 9]."); }
} else {
return NanThrowTypeError("Compression level must be a number.");
} }
} else { }
return NanThrowTypeError("Compression level must be a number.");
} if (!args[2]->StrictEquals(Undefined())) {
if (args[2]->IsUint32()) {
filter = args[1]->Uint32Value();
} else {
return NanThrowTypeError("Invalid filter value.");
}
}
} }
// Async // Async
if (args[0]->IsFunction()) { if (args[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); status = closure_init(closure, canvas, compression_level, filter);
// ensure closure is ok // ensure closure is ok
if (status) { if (status) {
@ -293,7 +313,7 @@ NAN_METHOD(Canvas::ToBuffer) {
// Sync // Sync
} else { } else {
closure_t closure; closure_t closure;
status = closure_init(&closure, canvas, compression_level); status = closure_init(&closure, canvas, compression_level, filter);
// ensure closure is ok // ensure closure is ok
if (status) { if (status) {
@ -342,36 +362,47 @@ streamPNG(void *c, const uint8_t *data, unsigned len) {
NAN_METHOD(Canvas::StreamPNGSync) { NAN_METHOD(Canvas::StreamPNGSync) {
NanScope(); NanScope();
uint32_t compression_level = 6; uint32_t compression_level = 6;
uint32_t filter = PNG_ALL_FILTERS;
// TODO: async as well // TODO: async as well
if (!args[0]->IsFunction()) if (!args[0]->IsFunction())
return NanThrowTypeError("callback function required"); return NanThrowTypeError("callback function required");
if (args.Length() == 2 && !args[1]->StrictEquals(Undefined())) { if (args.Length() > 1 && !(args[1]->StrictEquals(Undefined()) && args[2]->StrictEquals(Undefined()))) {
bool good = true; if (!args[1]->StrictEquals(Undefined())) {
if (args[1]->IsNumber()) { bool good = true;
compression_level = args[1]->Uint32Value(); if (args[1]->IsNumber()) {
} else if (args[1]->IsString()) { compression_level = args[1]->Uint32Value();
if (args[1]->StrictEquals(String::New("0"))) { } else if (args[1]->IsString()) {
compression_level = 0; if (args[1]->StrictEquals(String::New("0"))) {
} else { compression_level = 0;
uint32_t tmp = args[1]->Uint32Value();
if (tmp == 0) {
good = false;
} else { } else {
compression_level = tmp; uint32_t tmp = args[1]->Uint32Value();
if (tmp == 0) {
good = false;
} else {
compression_level = tmp;
}
} }
} } else {
} else { good = false;
good = false; }
}
if (good) {
if (good) { if (compression_level > 9) {
if (compression_level > 9) { return NanThrowRangeError("Allowed compression levels lie in the range [0, 9].");
return NanThrowRangeError("Allowed compression levels lie in the range [0, 9]."); }
} else {
return NanThrowTypeError("Compression level must be a number.");
} }
} else { }
return NanThrowTypeError("Compression level must be a number.");
} if (!args[2]->StrictEquals(Undefined())) {
if (args[2]->IsUint32()) {
filter = args[1]->Uint32Value();
} else {
return NanThrowTypeError("Invalid filter value.");
}
}
} }
@ -379,6 +410,7 @@ NAN_METHOD(Canvas::StreamPNGSync) {
closure_t closure; closure_t closure;
closure.fn = Handle<Function>::Cast(args[0]); closure.fn = Handle<Function>::Cast(args[0]);
closure.compression_level = compression_level; closure.compression_level = compression_level;
closure.filter = filter;
TryCatch try_catch; TryCatch try_catch;
@ -443,7 +475,7 @@ Canvas::Canvas(int w, int h, canvas_type_t t): ObjectWrap() {
if (CANVAS_TYPE_PDF == t) { if (CANVAS_TYPE_PDF == t) {
_closure = malloc(sizeof(closure_t)); _closure = malloc(sizeof(closure_t));
assert(_closure); assert(_closure);
cairo_status_t status = closure_init((closure_t *) _closure, this, 0); cairo_status_t status = closure_init((closure_t *) _closure, this, 0, PNG_NO_FILTERS);
assert(status == CAIRO_STATUS_SUCCESS); assert(status == CAIRO_STATUS_SUCCESS);
_surface = cairo_pdf_surface_create_for_stream(toBuffer, _closure, w, h); _surface = cairo_pdf_surface_create_for_stream(toBuffer, _closure, w, h);
} else { } else {

1
src/PNG.h

@ -129,6 +129,7 @@ static cairo_status_t canvas_write_png(cairo_surface_t *surface, png_rw_ptr writ
png_set_write_fn(png, closure, write_func, canvas_png_flush); png_set_write_fn(png, closure, write_func, canvas_png_flush);
png_set_compression_level(png, ((closure_t *) ((canvas_png_write_closure_t *) closure)->closure)->compression_level); png_set_compression_level(png, ((closure_t *) ((canvas_png_write_closure_t *) closure)->closure)->compression_level);
png_set_filter(png, 0, ((closure_t *) ((canvas_png_write_closure_t *) closure)->closure)->filter);
switch (cairo_image_surface_get_format(surface)) { switch (cairo_image_surface_get_format(surface)) {
case CAIRO_FORMAT_ARGB32: case CAIRO_FORMAT_ARGB32:

6
src/closure.h

@ -30,7 +30,8 @@ typedef struct {
uint8_t *data; uint8_t *data;
Canvas *canvas; Canvas *canvas;
cairo_status_t status; cairo_status_t status;
unsigned int compression_level; uint32_t compression_level;
uint32_t filter;
} closure_t; } closure_t;
/* /*
@ -38,12 +39,13 @@ typedef struct {
*/ */
cairo_status_t cairo_status_t
closure_init(closure_t *closure, Canvas *canvas, unsigned int compression_level) { closure_init(closure_t *closure, Canvas *canvas, unsigned int compression_level, unsigned int filter) {
closure->len = 0; closure->len = 0;
closure->canvas = canvas; closure->canvas = canvas;
closure->data = (uint8_t *) malloc(closure->max_len = PAGE_SIZE); closure->data = (uint8_t *) malloc(closure->max_len = PAGE_SIZE);
if (!closure->data) return CAIRO_STATUS_NO_MEMORY; if (!closure->data) return CAIRO_STATUS_NO_MEMORY;
closure->compression_level = compression_level; closure->compression_level = compression_level;
closure->filter = filter;
return CAIRO_STATUS_SUCCESS; return CAIRO_STATUS_SUCCESS;
} }

Loading…
Cancel
Save