Skip to content

Commit 0e4fdba

Browse files
committed
allow a format and explicit Buffer as backing store
slightly modified version of Automattic#678 for canvas 1.6
1 parent 3db3a21 commit 0e4fdba

2 files changed

Lines changed: 60 additions & 8 deletions

File tree

src/Canvas.cc

Lines changed: 56 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,14 @@ Canvas::Initialize(Nan::ADDON_REGISTER_FUNCTION_ARGS_TYPE target) {
3939
// Prototype
4040
Local<ObjectTemplate> proto = ctor->PrototypeTemplate();
4141
Nan::SetPrototypeMethod(ctor, "toBuffer", ToBuffer);
42+
Nan::SetPrototypeMethod(ctor, "flush", Flush);
4243
Nan::SetPrototypeMethod(ctor, "streamPNGSync", StreamPNGSync);
4344
Nan::SetPrototypeMethod(ctor, "streamPDFSync", StreamPDFSync);
4445
#ifdef HAVE_JPEG
4546
Nan::SetPrototypeMethod(ctor, "streamJPEGSync", StreamJPEGSync);
4647
#endif
4748
Nan::SetAccessor(proto, Nan::New("type").ToLocalChecked(), GetType);
49+
Nan::SetAccessor(proto, Nan::New("format").ToLocalChecked(), GetFormat);
4850
Nan::SetAccessor(proto, Nan::New("stride").ToLocalChecked(), GetStride);
4951
Nan::SetAccessor(proto, Nan::New("width").ToLocalChecked(), GetWidth, SetWidth);
5052
Nan::SetAccessor(proto, Nan::New("height").ToLocalChecked(), GetHeight, SetHeight);
@@ -57,6 +59,16 @@ Canvas::Initialize(Nan::ADDON_REGISTER_FUNCTION_ARGS_TYPE target) {
5759
Nan::SetTemplate(proto, "PNG_FILTER_PAETH", Nan::New<Uint32>(PNG_FILTER_PAETH));
5860
Nan::SetTemplate(proto, "PNG_ALL_FILTERS", Nan::New<Uint32>(PNG_ALL_FILTERS));
5961

62+
ctor->Set(Nan::New("CAIRO_FORMAT_INVALID").ToLocalChecked(), Nan::New<Uint32>(CAIRO_FORMAT_INVALID));
63+
ctor->Set(Nan::New("CAIRO_FORMAT_ARGB32").ToLocalChecked(), Nan::New<Uint32>(CAIRO_FORMAT_ARGB32));
64+
ctor->Set(Nan::New("CAIRO_FORMAT_RGB24").ToLocalChecked(), Nan::New<Uint32>(CAIRO_FORMAT_RGB24));
65+
ctor->Set(Nan::New("CAIRO_FORMAT_A8").ToLocalChecked(), Nan::New<Uint32>(CAIRO_FORMAT_A8));
66+
ctor->Set(Nan::New("CAIRO_FORMAT_A1").ToLocalChecked(), Nan::New<Uint32>(CAIRO_FORMAT_A1));
67+
ctor->Set(Nan::New("CAIRO_FORMAT_RGB16_565").ToLocalChecked(), Nan::New<Uint32>(CAIRO_FORMAT_RGB16_565));
68+
#ifdef CAIRO_FORMAT_RGB30
69+
ctor->Set(Nan::New("CAIRO_FORMAT_RGB30").ToLocalChecked(), Nan::New<Uint32>(CAIRO_FORMAT_RGB30));
70+
#endif
71+
6072
Nan::Set(target, Nan::New("Canvas").ToLocalChecked(), ctor->GetFunction());
6173
}
6274

@@ -70,15 +82,25 @@ NAN_METHOD(Canvas::New) {
7082
}
7183

7284
int width = 0, height = 0;
85+
unsigned char* data = nullptr;
86+
cairo_format_t format = CAIRO_FORMAT_ARGB32;
7387
canvas_type_t type = CANVAS_TYPE_IMAGE;
7488
if (info[0]->IsNumber()) width = info[0]->Uint32Value();
7589
if (info[1]->IsNumber()) height = info[1]->Uint32Value();
76-
if (info[2]->IsString()) type = !strcmp("pdf", *String::Utf8Value(info[2]))
77-
? CANVAS_TYPE_PDF
78-
: !strcmp("svg", *String::Utf8Value(info[2]))
79-
? CANVAS_TYPE_SVG
80-
: CANVAS_TYPE_IMAGE;
81-
Canvas *canvas = new Canvas(width, height, type);
90+
if (info[2]->IsString()) {
91+
type = !strcmp("pdf", *String::Utf8Value(info[2]))
92+
? CANVAS_TYPE_PDF
93+
: !strcmp("svg", *String::Utf8Value(info[2]))
94+
? CANVAS_TYPE_SVG
95+
: CANVAS_TYPE_IMAGE;
96+
} else if (node::Buffer::HasInstance(info[2])) {
97+
type = CANVAS_TYPE_IMAGE;
98+
data = reinterpret_cast<unsigned char*>(node::Buffer::Data(info[2]));
99+
}
100+
if (info[3]->IsNumber()) {
101+
format = static_cast<cairo_format_t>(info[3]->Uint32Value());
102+
}
103+
Canvas *canvas = new Canvas(width, height, type, data, format);
82104
canvas->Wrap(info.This());
83105
info.GetReturnValue().Set(info.This());
84106
}
@@ -92,6 +114,15 @@ NAN_GETTER(Canvas::GetType) {
92114
info.GetReturnValue().Set(Nan::New<String>(canvas->isPDF() ? "pdf" : canvas->isSVG() ? "svg" : "image").ToLocalChecked());
93115
}
94116

117+
/*
118+
* Get format string.
119+
*/
120+
121+
NAN_GETTER(Canvas::GetFormat) {
122+
Canvas *canvas = Nan::ObjectWrap::Unwrap<Canvas>(info.This());
123+
info.GetReturnValue().Set(Nan::New<Number>(canvas->format));
124+
}
125+
95126
/*
96127
* Get stride.
97128
*/
@@ -236,6 +267,19 @@ Canvas::EIO_AfterToBuffer(eio_req *req) {
236267
#endif
237268
}
238269

270+
/*
271+
* Non-standard.
272+
* Flushes the context contents to the backing store.
273+
* Useful when an explicit Buffer backing store was passed
274+
* in, and you want the Buffer contents to be up-to-date
275+
*/
276+
277+
NAN_METHOD(Canvas::Flush) {
278+
Nan::HandleScope scope;
279+
Canvas *canvas = ObjectWrap::Unwrap<Canvas>(info.This());
280+
cairo_surface_flush(canvas->surface());
281+
}
282+
239283
/*
240284
* Convert PNG data to a node::Buffer, async when a
241285
* callback function is passed.
@@ -568,10 +612,11 @@ NAN_METHOD(Canvas::StreamJPEGSync) {
568612
* Initialize cairo surface.
569613
*/
570614

571-
Canvas::Canvas(int w, int h, canvas_type_t t): Nan::ObjectWrap() {
615+
Canvas::Canvas(int w, int h, canvas_type_t t, unsigned char* data, cairo_format_t f): Nan::ObjectWrap() {
572616
type = t;
573617
width = w;
574618
height = h;
619+
format = f;
575620
_surface = NULL;
576621
_closure = NULL;
577622

@@ -587,6 +632,10 @@ Canvas::Canvas(int w, int h, canvas_type_t t): Nan::ObjectWrap() {
587632
cairo_status_t status = closure_init((closure_t *) _closure, this, 0, PNG_NO_FILTERS);
588633
assert(status == CAIRO_STATUS_SUCCESS);
589634
_surface = cairo_svg_surface_create_for_stream(toBuffer, _closure, w, h);
635+
} else if (data) {
636+
_surface = cairo_image_surface_create_for_data(data, format, w, h,
637+
cairo_format_stride_for_width(format, w));
638+
assert(_surface);
590639
} else {
591640
_surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, w, h);
592641
assert(_surface);

src/Canvas.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,11 +52,14 @@ class Canvas: public Nan::ObjectWrap {
5252
int width;
5353
int height;
5454
canvas_type_t type;
55+
cairo_format_t format;
5556
static Nan::Persistent<FunctionTemplate> constructor;
5657
static void Initialize(Nan::ADDON_REGISTER_FUNCTION_ARGS_TYPE target);
5758
static NAN_METHOD(New);
59+
static NAN_METHOD(Flush);
5860
static NAN_METHOD(ToBuffer);
5961
static NAN_GETTER(GetType);
62+
static NAN_GETTER(GetFormat);
6063
static NAN_GETTER(GetStride);
6164
static NAN_GETTER(GetWidth);
6265
static NAN_GETTER(GetHeight);
@@ -87,7 +90,7 @@ class Canvas: public Nan::ObjectWrap {
8790
inline uint8_t *data(){ return cairo_image_surface_get_data(_surface); }
8891
inline int stride(){ return cairo_image_surface_get_stride(_surface); }
8992
inline int nBytes(){ return height * stride(); }
90-
Canvas(int width, int height, canvas_type_t type);
93+
Canvas(int width, int height, canvas_type_t type, unsigned char* data, cairo_format_t f);
9194
void resurface(Local<Object> canvas);
9295

9396
private:

0 commit comments

Comments
 (0)