@@ -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);
0 commit comments