muwasm: Add Device class to JS API.
authorOlivier FAURE <[email protected]>
Fri, 9 Sep 2022 14:03:01 +0000 (16:03 +0200)
committerOlivier FAURE <[email protected]>
Wed, 14 Sep 2022 11:58:10 +0000 (13:58 +0200)
Add `run`, `runContents`, `runAnnots` and `runWidgets` methods to the Page class.
Add `Page.toPixmapTest` method which uses the above methods.

Co-authored-by: Tor Andersson <[email protected]>
platform/wasm/lib/mupdf.js
platform/wasm/lib/wrap.c

index 232e39851414b50f9aab4d3926b2ac357d23434f..4cd569e0d7d31d8f4266bdaa4b098ff8c57dd264 100644 (file)
@@ -110,6 +110,10 @@ class Rect {
        translated(xoff, yoff) {
                return new Rect(this.x0 + xoff, this.y0 + yoff, this.x1 + xoff, this.y1 + yoff);
        }
+
+       transformed(matrix) {
+               return matrix.transformRect(this);
+       }
 }
 
 class Matrix {
@@ -122,6 +126,8 @@ class Matrix {
                this.f = f;
        }
 
+       static identity = new Matrix(1, 0, 0, 1, 0, 0);
+
        static fromPtr(ptr) {
                ptr = ptr >> 2;
                return new Matrix(
@@ -266,6 +272,55 @@ class Page extends Wrapper {
                return this.bounds().height();
        }
 
+       run(device, transformMatrix, cookie = null) {
+               // TODO - transformMatrix = Matrix.identity
+               assert(device instanceof Device, "invalid device argument");
+               assert(transformMatrix instanceof Matrix, "invalid transformMatrix argument");
+               let m = transformMatrix;
+               libmupdf._wasm_run_page(
+                       this.pointer,
+                       device.pointer,
+                       m.a, m.b, m.c, m.d, m.e, m.f,
+                       cookie?.pointer,
+               );
+       }
+
+       runContents(device, transformMatrix, cookie = null) {
+               assert(device instanceof Device, "invalid device argument");
+               assert(transformMatrix instanceof Matrix, "invalid transformMatrix argument");
+               let m = transformMatrix;
+               libmupdf._wasm_run_page_contents(
+                       this.pointer,
+                       device.pointer,
+                       m.a, m.b, m.c, m.d, m.e, m.f,
+                       cookie?.pointer,
+               );
+       }
+
+       runAnnots(device, transformMatrix = new Matrix(), cookie = null) {
+               assert(device instanceof Device, "invalid device argument");
+               assert(transformMatrix instanceof Matrix, "invalid transformMatrix argument");
+               let m = transformMatrix;
+               libmupdf._wasm_run_page_annots(
+                       this.pointer,
+                       device.pointer,
+                       m.a, m.b, m.c, m.d, m.e, m.f,
+                       cookie?.pointer,
+               );
+       }
+
+       runWidgets(device, transformMatrix, cookie = null) {
+               assert(device instanceof Device, "invalid device argument");
+               assert(transformMatrix instanceof Matrix, "invalid transformMatrix argument");
+               let m = transformMatrix;
+               libmupdf._wasm_run_page_widgets(
+                       this.pointer,
+                       device.pointer,
+                       m.a, m.b, m.c, m.d, m.e, m.f,
+                       cookie?.pointer,
+               );
+       }
+
        toPixmap(transformMatrix, colorspace, alpha = false) {
                assert(transformMatrix instanceof Matrix, "invalid transformMatrix argument");
                assert(colorspace instanceof ColorSpace, "invalid colorspace argument");
@@ -280,6 +335,24 @@ class Page extends Wrapper {
                );
        }
 
+       toPixmapTest(transform, colorspace, alpha = false, cookie = null, drawContents = true, drawAnnots = true, drawWidgets = true) {
+               let bbox = this.bounds().transformed(transform);
+               let pixmap = Pixmap.withBbox(colorspace, bbox, alpha);
+               if (alpha)
+                       pixmap.clear();
+               else
+                       pixmap.clearWithWhite();
+               let device = Device.drawDevice(transform, pixmap);
+               if (drawContents)
+                       this.runContents(device, Matrix.identity, cookie);
+               if (drawAnnots)
+                       this.runAnnots(device, Matrix.identity, cookie);
+               if (drawWidgets)
+                       this.runWidgets(device, Matrix.identity, cookie);
+               device.close();
+               return pixmap;
+       }
+
        toSTextPage() {
                return new STextPage(
                        libmupdf._wasm_new_stext_page_from_page(this.pointer)
@@ -849,6 +922,23 @@ class Pixmap extends Wrapper {
                this.bbox = Rect.fromIntRectPtr(libmupdf._wasm_pixmap_bbox(this.pointer));
        }
 
+       static withBbox(colorspace, bbox, alpha) {
+               return new Pixmap(libmupdf._wasm_new_pixmap_with_bbox(
+                       colorspace.pointer,
+                       bbox.x0, bbox.y0, bbox.x1, bbox.y1,
+                       0,
+                       alpha,
+               ));
+       }
+
+       clear() {
+               libmupdf._wasm_clear_pixmap(this.pointer);
+       }
+
+       clearWithWhite() {
+               libmupdf._wasm_clear_pixmap_with_value(this.pointer, 0xff);
+       }
+
        width() {
                return this.bbox.width();
        }
@@ -870,6 +960,7 @@ class Pixmap extends Wrapper {
                let p = libmupdf._wasm_pixmap_samples(this.pointer);
                return libmupdf.HEAPU8.subarray(p, p + n);
        }
+
        toPNG() {
                let buf = libmupdf._wasm_new_buffer_from_pixmap_as_png(this.pointer);
                try {
@@ -882,6 +973,26 @@ class Pixmap extends Wrapper {
        }
 }
 
+class Device extends Wrapper {
+       constructor(pointer) {
+               super(pointer, libmupdf._wasm_drop_device);
+       }
+
+       static drawDevice(transformMatrix, pixmap) {
+               assert(transformMatrix instanceof Matrix, "invalid transformMatrix argument");
+               assert(pixmap instanceof Pixmap, "invalid pixmap argument");
+               let m = transformMatrix;
+               return new Device(libmupdf._wasm_new_draw_device(
+                       m.a, m.b, m.c, m.d, m.e, m.f,
+                       pixmap.pointer
+               ));
+       }
+
+       close() {
+               libmupdf._wasm_close_device(this.pointer);
+       }
+}
+
 class Buffer extends Wrapper {
        constructor(pointer) {
                super(pointer, libmupdf._wasm_drop_buffer);
index fdb8c5cda694b271a1a45190ea6f97be22d8b946..65c7a23f78a7b8a999866a741aabc0b0c0a2f51e 100644 (file)
@@ -175,6 +175,94 @@ fz_rect *wasm_bound_page(fz_page *page)
        return &out_rect;
 }
 
+EMSCRIPTEN_KEEPALIVE
+void wasm_run_page(
+       fz_page *page,
+       fz_device *dev,
+       float ctm_0, float ctm_1, float ctm_2, float ctm_3, float ctm_4, float ctm_5,
+       fz_cookie *cookie
+) {
+       fz_matrix ctm = fz_make_matrix(ctm_0, ctm_1, ctm_2, ctm_3, ctm_4, ctm_5);
+       fz_try(ctx)
+               fz_run_page(ctx, page, dev, ctm, cookie);
+       fz_catch(ctx)
+               wasm_rethrow(ctx);
+}
+
+EMSCRIPTEN_KEEPALIVE
+void wasm_run_page_contents(
+       fz_page *page,
+       fz_device *dev,
+       float ctm_0, float ctm_1, float ctm_2, float ctm_3, float ctm_4, float ctm_5,
+       fz_cookie *cookie
+) {
+       fz_matrix ctm = fz_make_matrix(ctm_0, ctm_1, ctm_2, ctm_3, ctm_4, ctm_5);
+       fz_try(ctx)
+               fz_run_page_contents(ctx, page, dev, ctm, cookie);
+       fz_catch(ctx)
+               wasm_rethrow(ctx);
+}
+
+EMSCRIPTEN_KEEPALIVE
+void wasm_run_page_annots(
+       fz_page *page,
+       fz_device *dev,
+       float ctm_0, float ctm_1, float ctm_2, float ctm_3, float ctm_4, float ctm_5,
+       fz_cookie *cookie
+) {
+       fz_matrix ctm = fz_make_matrix(ctm_0, ctm_1, ctm_2, ctm_3, ctm_4, ctm_5);
+       fz_try(ctx)
+               fz_run_page_annots(ctx, page, dev, ctm, cookie);
+       fz_catch(ctx)
+               wasm_rethrow(ctx);
+}
+
+EMSCRIPTEN_KEEPALIVE
+void wasm_run_page_widgets(
+       fz_page *page,
+       fz_device *dev,
+       float ctm_0, float ctm_1, float ctm_2, float ctm_3, float ctm_4, float ctm_5,
+       fz_cookie *cookie
+) {
+       fz_matrix ctm = fz_make_matrix(ctm_0, ctm_1, ctm_2, ctm_3, ctm_4, ctm_5);
+       fz_try(ctx)
+               fz_run_page_widgets(ctx, page, dev, ctm, cookie);
+       fz_catch(ctx)
+               wasm_rethrow(ctx);
+}
+
+EMSCRIPTEN_KEEPALIVE
+fz_device *wasm_new_draw_device(
+       float ctm_0, float ctm_1, float ctm_2, float ctm_3, float ctm_4, float ctm_5,
+       fz_pixmap *dest
+) {
+       fz_matrix ctm = fz_make_matrix(ctm_0, ctm_1, ctm_2, ctm_3, ctm_4, ctm_5);
+       fz_device *device;
+       fz_try(ctx)
+               device = fz_new_draw_device(ctx, ctm, dest);
+       fz_catch(ctx)
+               wasm_rethrow(ctx);
+       return device;
+}
+
+EMSCRIPTEN_KEEPALIVE
+void wasm_close_device(fz_device *dev)
+{
+       fz_try(ctx)
+               fz_close_device(ctx, dev);
+       fz_catch(ctx)
+               wasm_rethrow(ctx);
+}
+
+EMSCRIPTEN_KEEPALIVE
+void wasm_drop_device(fz_device *dev)
+{
+       fz_try(ctx)
+               fz_drop_device(ctx, dev);
+       fz_catch(ctx)
+               wasm_rethrow(ctx);
+}
+
 EMSCRIPTEN_KEEPALIVE
 fz_stext_page *wasm_new_stext_page_from_page(fz_page *page) {
        fz_stext_page *stext_page;
@@ -355,13 +443,31 @@ void wasm_drop_colorspace(fz_colorspace *cs)
 
 EMSCRIPTEN_KEEPALIVE
 fz_pixmap *wasm_new_pixmap_from_page(fz_page *page,
-       float a, float b, float c, float d, float e, float f,
+       float ctm_0, float ctm_1, float ctm_2, float ctm_3, float ctm_4, float ctm_5,
        fz_colorspace *colorspace,
        int alpha)
 {
+       fz_matrix ctm = fz_make_matrix(ctm_0, ctm_1, ctm_2, ctm_3, ctm_4, ctm_5);
+       fz_pixmap *pix;
+       fz_try(ctx)
+               pix = fz_new_pixmap_from_page(ctx, page, ctm, colorspace, alpha);
+       fz_catch(ctx)
+               wasm_rethrow(ctx);
+       return pix;
+}
+
+EMSCRIPTEN_KEEPALIVE
+fz_pixmap *wasm_new_pixmap_with_bbox(
+       fz_colorspace *colorspace,
+       int bbox_x0, int bbox_y0, int bbox_x1, int bbox_y1,
+       fz_separations *seps,
+       int alpha
+)
+{
+       fz_irect bbox = fz_make_irect(bbox_x0, bbox_y0, bbox_x1, bbox_y1);
        fz_pixmap *pix;
        fz_try(ctx)
-               pix = fz_new_pixmap_from_page(ctx, page, fz_make_matrix(a,b,c,d,e,f), colorspace, alpha);
+               pix = fz_new_pixmap_with_bbox(ctx, colorspace, bbox, seps, alpha);
        fz_catch(ctx)
                wasm_rethrow(ctx);
        return pix;
@@ -391,6 +497,20 @@ void wasm_clear_pixmap_rect_with_value(fz_pixmap *pix, int value, int rect_x0, i
        fz_clear_pixmap_rect_with_value(ctx, pix, value, rect);
 }
 
+EMSCRIPTEN_KEEPALIVE
+void wasm_clear_pixmap(fz_pixmap *pix)
+{
+       // never throws
+       fz_clear_pixmap(ctx, pix);
+}
+
+EMSCRIPTEN_KEEPALIVE
+void wasm_clear_pixmap_with_value(fz_pixmap *pix, int value)
+{
+       // never throws
+       fz_clear_pixmap_with_value(ctx, pix, value);
+}
+
 EMSCRIPTEN_KEEPALIVE
 int wasm_pixmap_stride(fz_pixmap *pix)
 {