summaryrefslogtreecommitdiff
path: root/platform/wasm/wrap.c
diff options
context:
space:
mode:
Diffstat (limited to 'platform/wasm/wrap.c')
-rw-r--r--platform/wasm/wrap.c247
1 files changed, 247 insertions, 0 deletions
diff --git a/platform/wasm/wrap.c b/platform/wasm/wrap.c
new file mode 100644
index 00000000..d2a3379e
--- /dev/null
+++ b/platform/wasm/wrap.c
@@ -0,0 +1,247 @@
+#include "emscripten.h"
+#include "mupdf/fitz.h"
+
+static fz_context *ctx;
+
+EMSCRIPTEN_KEEPALIVE
+void initContext(void)
+{
+ ctx = fz_new_context(NULL, NULL, 100<<20);
+ fz_register_document_handlers(ctx);
+}
+
+EMSCRIPTEN_KEEPALIVE
+fz_document *openDocument(const char *filename)
+{
+ return fz_open_document(ctx, filename);
+}
+
+EMSCRIPTEN_KEEPALIVE
+void freeDocument(fz_document *doc)
+{
+ fz_drop_document(ctx, doc);
+}
+
+EMSCRIPTEN_KEEPALIVE
+int countPages(fz_document *doc)
+{
+ return fz_count_pages(ctx, doc);
+}
+
+static fz_page *lastPage = NULL;
+
+static void loadPage(fz_document *doc, int number)
+{
+ static fz_document *lastPageDoc = NULL;
+ static int lastPageNumber = -1;
+ if (lastPageNumber != number || lastPageDoc != doc)
+ {
+ if (lastPage)
+ fz_drop_page(ctx, lastPage);
+ lastPage = fz_load_page(ctx, doc, number-1);
+ lastPageDoc = doc;
+ lastPageNumber = number;
+ }
+}
+
+EMSCRIPTEN_KEEPALIVE
+char *drawPageAsHTML(fz_document *doc, int number)
+{
+ static unsigned char *data = NULL;
+ fz_stext_page *text;
+ fz_buffer *buf;
+ fz_output *out;
+
+ fz_free(ctx, data);
+ data = NULL;
+
+ loadPage(doc, number);
+
+ buf = fz_new_buffer(ctx, 0);
+ {
+ out = fz_new_output_with_buffer(ctx, buf);
+ {
+ text = fz_new_stext_page_from_page(ctx, lastPage, NULL);
+ fz_print_stext_page_as_html(ctx, out, text);
+ fz_drop_stext_page(ctx, text);
+ }
+ fz_write_byte(ctx, out, 0);
+ fz_close_output(ctx, out);
+ fz_drop_output(ctx, out);
+ }
+ fz_buffer_extract(ctx, buf, &data);
+ fz_drop_buffer(ctx, buf);
+
+ return (char*)data;
+}
+
+EMSCRIPTEN_KEEPALIVE
+char *drawPageAsSVG(fz_document *doc, int number)
+{
+ static int id = 0;
+ static unsigned char *data = NULL;
+ fz_buffer *buf;
+ fz_output *out;
+ fz_device *dev;
+ fz_rect bbox;
+
+ fz_free(ctx, data);
+ data = NULL;
+
+ loadPage(doc, number);
+
+ buf = fz_new_buffer(ctx, 0);
+ {
+ out = fz_new_output_with_buffer(ctx, buf);
+ {
+ bbox = fz_bound_page(ctx, lastPage);
+ dev = fz_new_svg_device(ctx, out, bbox.x1-bbox.x0, bbox.y1-bbox.y0, FZ_SVG_TEXT_AS_PATH, 0, &id);
+ fz_run_page(ctx, lastPage, dev, fz_identity, NULL);
+ fz_close_device(ctx, dev);
+ fz_drop_device(ctx, dev);
+ }
+ fz_write_byte(ctx, out, 0);
+ fz_close_output(ctx, out);
+ fz_drop_output(ctx, out);
+ }
+ fz_buffer_extract(ctx, buf, &data);
+ fz_drop_buffer(ctx, buf);
+
+ return (char*)data;
+}
+
+EMSCRIPTEN_KEEPALIVE
+char *drawPageAsPNG(fz_document *doc, int number, float dpi)
+{
+ static unsigned char *data = NULL;
+ float zoom = dpi / 72;
+ fz_pixmap *pix;
+ fz_buffer *buf;
+ fz_output *out;
+
+ fz_free(ctx, data);
+ data = NULL;
+
+ loadPage(doc, number);
+
+ buf = fz_new_buffer(ctx, 0);
+ {
+ out = fz_new_output_with_buffer(ctx, buf);
+ {
+ pix = fz_new_pixmap_from_page(ctx, lastPage, fz_scale(zoom, zoom), fz_device_rgb(ctx), 0);
+ fz_write_pixmap_as_data_uri(ctx, out, pix);
+ fz_drop_pixmap(ctx, pix);
+ }
+ fz_write_byte(ctx, out, 0);
+ fz_close_output(ctx, out);
+ fz_drop_output(ctx, out);
+ }
+ fz_buffer_extract(ctx, buf, &data);
+ fz_drop_buffer(ctx, buf);
+
+ return (char*)data;
+}
+
+static fz_irect pageBounds(fz_document *doc, int number, float dpi)
+{
+ loadPage(doc, number);
+ return fz_round_rect(fz_transform_rect(fz_bound_page(ctx, lastPage), fz_scale(dpi/72, dpi/72)));
+}
+
+EMSCRIPTEN_KEEPALIVE
+int pageWidth(fz_document *doc, int number, float dpi)
+{
+ fz_irect bbox = pageBounds(doc, number, dpi);
+ return bbox.x1 - bbox.x0;
+}
+
+EMSCRIPTEN_KEEPALIVE
+int pageHeight(fz_document *doc, int number, float dpi)
+{
+ fz_irect bbox = pageBounds(doc, number, dpi);
+ return bbox.y1 - bbox.y0;
+}
+
+EMSCRIPTEN_KEEPALIVE
+char *pageLinks(fz_document *doc, int number, float dpi)
+{
+ static unsigned char *data = NULL;
+ fz_buffer *buf;
+ fz_link *links, *link;
+
+ fz_free(ctx, data);
+ data = NULL;
+
+ loadPage(doc, number);
+
+ buf = fz_new_buffer(ctx, 0);
+ {
+ links = fz_load_links(ctx, lastPage);
+ {
+ for (link = links; link; link = link->next)
+ {
+ fz_irect bbox = fz_round_rect(fz_transform_rect(link->rect, fz_scale(dpi/72, dpi/72)));
+ fz_append_printf(ctx, buf, "<area shape=\"rect\" coords=\"%d,%d,%d,%d\"",
+ bbox.x0, bbox.y0, bbox.x1, bbox.y1);
+ if (fz_is_external_link(ctx, link->uri))
+ fz_append_printf(ctx, buf, " href=\"%s\">\n", link->uri);
+ else
+ {
+ int linkNumber = fz_resolve_link(ctx, doc, link->uri, NULL, NULL);
+ fz_append_printf(ctx, buf, " href=\"#page%d\">\n", linkNumber+1);
+ }
+ }
+ }
+ fz_append_byte(ctx, buf, 0);
+ fz_drop_link(ctx, links);
+ }
+ fz_buffer_extract(ctx, buf, &data);
+ fz_drop_buffer(ctx, buf);
+
+ return (char*)data;
+}
+
+EMSCRIPTEN_KEEPALIVE
+char *documentTitle(fz_document *doc)
+{
+ static char buf[100];
+ if (fz_lookup_metadata(ctx, doc, FZ_META_INFO_TITLE, buf, sizeof buf) > 0)
+ return buf;
+ return "Untitled";
+}
+
+EMSCRIPTEN_KEEPALIVE
+fz_outline *loadOutline(fz_document *doc)
+{
+ return fz_load_outline(ctx, doc);
+}
+
+EMSCRIPTEN_KEEPALIVE
+void freeOutline(fz_outline *outline)
+{
+ fz_drop_outline(ctx, outline);
+}
+
+EMSCRIPTEN_KEEPALIVE
+char *outlineTitle(fz_outline *node)
+{
+ return node->title;
+}
+
+EMSCRIPTEN_KEEPALIVE
+int outlinePage(fz_outline *node)
+{
+ return node->page + 1;
+}
+
+EMSCRIPTEN_KEEPALIVE
+fz_outline *outlineDown(fz_outline *node)
+{
+ return node->down;
+}
+
+EMSCRIPTEN_KEEPALIVE
+fz_outline *outlineNext(fz_outline *node)
+{
+ return node->next;
+}