@@ -100,6 +100,7 @@ Context2d::Initialize(Nan::ADDON_REGISTER_FUNCTION_ARGS_TYPE target) {
100100 Nan::SetPrototypeMethod (ctor, " getImageData" , GetImageData);
101101 Nan::SetPrototypeMethod (ctor, " createImageData" , CreateImageData);
102102 Nan::SetPrototypeMethod (ctor, " addPage" , AddPage);
103+ Nan::SetPrototypeMethod (ctor, " addPageAsync" , AddPageAsync);
103104 Nan::SetPrototypeMethod (ctor, " save" , Save);
104105 Nan::SetPrototypeMethod (ctor, " restore" , Restore);
105106 Nan::SetPrototypeMethod (ctor, " rotate" , Rotate);
@@ -746,7 +747,6 @@ NAN_GETTER(Context2d::GetFormat) {
746747/*
747748 * Create a new page.
748749 */
749-
750750NAN_METHOD (Context2d::AddPage) {
751751 Context2d *context = Nan::ObjectWrap::Unwrap<Context2d>(info.This ());
752752 if (context->canvas ()->backend ()->getName () != " pdf" ) {
@@ -761,6 +761,59 @@ NAN_METHOD(Context2d::AddPage) {
761761 return ;
762762}
763763
764+ struct AddPageInfo {
765+ Nan::Callback cb;
766+ Context2d* context;
767+ Nan::AsyncResource* async;
768+ int width;
769+ int height;
770+ };
771+
772+ void AddPageAsyncTask (uv_work_t * req) {
773+ AddPageInfo* pi = static_cast <AddPageInfo*>(req->data );
774+ cairo_show_page (pi->context ->context ());
775+ cairo_pdf_surface_set_size (pi->context ->canvas ()->surface (), pi->width , pi->height );
776+ }
777+
778+ void
779+ Context2d::AddPageAsyncTaskAfter (uv_work_t * req) {
780+ Nan::HandleScope scope;
781+ AddPageInfo* pi = static_cast <AddPageInfo*>(req->data );
782+ delete req;
783+ pi->cb .Call (0 , {}, pi->async );
784+ pi->context ->Unref ();
785+ delete pi->async ;
786+ delete pi;
787+ }
788+
789+ /*
790+ * Create a new page asynchronously. When using a PDF surface, Cairo actually
791+ * creates a recording surface, then when cairo_show_page() is called, it plays
792+ * back the operations *three times*. As such, this can be a very slow function
793+ * that benefits from running in a separate thread.
794+ */
795+ NAN_METHOD (Context2d::AddPageAsync) {
796+ Context2d *context = Nan::ObjectWrap::Unwrap<Context2d>(info.This ());
797+ if (context->canvas ()->backend ()->getName () != " pdf" ) {
798+ return Nan::ThrowError (" only PDF canvases support .addPage()" );
799+ }
800+ int width = Nan::To<int32_t >(info[1 ]).FromMaybe (0 );
801+ int height = Nan::To<int32_t >(info[2 ]).FromMaybe (0 );
802+ if (width < 1 ) width = context->canvas ()->getWidth ();
803+ if (height < 1 ) height = context->canvas ()->getHeight ();
804+ AddPageInfo* pi = new AddPageInfo;
805+ pi->cb .Reset (info[0 ].As <Function>());
806+ pi->context = context;
807+ pi->async = new Nan::AsyncResource (" canvas:AddPageAsyncAfter" );
808+ context->Ref ();
809+ pi->width = width;
810+ pi->height = height;
811+ uv_loop_t * loop = uv_default_loop ();
812+ uv_work_t * req = new uv_work_t ;
813+ req->data = pi;
814+ uv_queue_work (loop, req, AddPageAsyncTask, (uv_after_work_cb)AddPageAsyncTaskAfter);
815+ }
816+
764817/*
765818 * Put image data.
766819 *
0 commit comments