#include "mupdf/fitz.h" #if FZ_ENABLE_PDF #include "mupdf/pdf.h" #endif #if FZ_ENABLE_JS #include "mujs.h" #include #include #include #define PS1 "> " FZ_NORETURN static void rethrow(js_State *J) { js_newerror(J, fz_caught_message(js_getcontext(J))); js_throw(J); } FZ_NORETURN static void rethrow_as_fz(js_State *J) { fz_throw(js_getcontext(J), FZ_ERROR_GENERIC, "%s", js_tostring(J, -1)); } static void *alloc(void *actx, void *ptr, int n) { fz_context *ctx = actx; if (n == 0) { fz_free(ctx, ptr); return NULL; } return fz_resize_array_no_throw(ctx, ptr, n, 1); } static int eval_print(js_State *J, const char *source) { if (js_ploadstring(J, "[string]", source)) { fprintf(stderr, "%s\n", js_trystring(J, -1, "Error")); js_pop(J, 1); return 1; } js_pushglobal(J); if (js_pcall(J, 0)) { fprintf(stderr, "%s\n", js_trystring(J, -1, "Error")); js_pop(J, 1); return 1; } if (js_isdefined(J, -1)) printf("%s\n", js_trystring(J, -1, "can't convert to string")); js_pop(J, 1); return 0; } static void jsB_propfun(js_State *J, const char *name, js_CFunction cfun, int n) { const char *realname = strchr(name, '.'); realname = realname ? realname + 1 : name; js_newcfunction(J, cfun, name, n); js_defproperty(J, -2, realname, JS_DONTENUM); } static void jsB_propcon(js_State *J, const char *tag, const char *name, js_CFunction cfun, int n) { const char *realname = strchr(name, '.'); realname = realname ? realname + 1 : name; js_getregistry(J, tag); js_newcconstructor(J, cfun, cfun, name, n); js_defproperty(J, -2, realname, JS_DONTENUM); } static void jsB_gc(js_State *J) { int report = js_toboolean(J, 1); js_gc(J, report); js_pushundefined(J); } static void jsB_load(js_State *J) { const char *filename = js_tostring(J, 1); int rv = js_dofile(J, filename); js_pushboolean(J, !rv); } static void jsB_print(js_State *J) { unsigned int i, top = js_gettop(J); for (i = 1; i < top; ++i) { const char *s = js_tostring(J, i); if (i > 1) putchar(' '); fputs(s, stdout); } putchar('\n'); js_pushundefined(J); } static void jsB_write(js_State *J) { unsigned int i, top = js_gettop(J); for (i = 1; i < top; ++i) { const char *s = js_tostring(J, i); if (i > 1) putchar(' '); fputs(s, stdout); } js_pushundefined(J); } static void jsB_read(js_State *J) { fz_context *ctx = js_getcontext(J); const char *filename = js_tostring(J, 1); FILE *f; char *s; long n; size_t t; f = fopen(filename, "rb"); if (!f) { js_error(J, "cannot open file: '%s'", filename); } if (fseek(f, 0, SEEK_END) < 0) { fclose(f); js_error(J, "cannot seek in file: '%s'", filename); } n = ftell(f); if (n < 0) { fclose(f); js_error(J, "cannot tell in file: '%s'", filename); } if (fseek(f, 0, SEEK_SET) < 0) { fclose(f); js_error(J, "cannot seek in file: '%s'", filename); } s = fz_malloc(ctx, n + 1); if (!s) { fclose(f); js_error(J, "cannot allocate storage for file contents: '%s'", filename); } t = fread(s, 1, n, f); if (t != n) { fz_free(ctx, s); fclose(f); js_error(J, "cannot read data from file: '%s'", filename); } s[n] = 0; js_pushstring(J, s); fz_free(ctx, s); fclose(f); } static void jsB_readline(js_State *J) { char line[256]; size_t n; if (!fgets(line, sizeof line, stdin)) js_error(J, "cannot read line from stdin"); n = strlen(line); if (n > 0 && line[n-1] == '\n') line[n-1] = 0; js_pushstring(J, line); } static void jsB_quit(js_State *J) { exit(js_tonumber(J, 1)); } static const char *require_js = "function require(name) {\n" "var cache = require.cache;\n" "if (name in cache) return cache[name];\n" "var exports = {};\n" "cache[name] = exports;\n" "Function('exports', read(name+'.js'))(exports);\n" "return exports;\n" "}\n" "require.cache = Object.create(null);\n" ; static const char *stacktrace_js = "Error.prototype.toString = function() {\n" "if (this.stackTrace) return this.name + ': ' + this.message + this.stackTrace;\n" "return this.name + ': ' + this.message;\n" "};\n" ; /* destructors */ static void ffi_gc_fz_buffer(js_State *J, void *buf) { fz_context *ctx = js_getcontext(J); fz_try(ctx) fz_drop_buffer(ctx, buf); fz_catch(ctx) rethrow(J); } static void ffi_gc_fz_document(js_State *J, void *doc) { fz_context *ctx = js_getcontext(J); fz_drop_document(ctx, doc); } static void ffi_gc_fz_page(js_State *J, void *page) { fz_context *ctx = js_getcontext(J); fz_drop_page(ctx, page); } static void ffi_gc_fz_annot(js_State *J, void *annot) { fz_context *ctx = js_getcontext(J); fz_drop_annot(ctx, annot); } static void ffi_gc_fz_colorspace(js_State *J, void *colorspace) { fz_context *ctx = js_getcontext(J); fz_drop_colorspace(ctx, colorspace); } static void ffi_gc_fz_pixmap(js_State *J, void *pixmap) { fz_context *ctx = js_getcontext(J); fz_drop_pixmap(ctx, pixmap); } static void ffi_gc_fz_path(js_State *J, void *path) { fz_context *ctx = js_getcontext(J); fz_drop_path(ctx, path); } static void ffi_gc_fz_text(js_State *J, void *text) { fz_context *ctx = js_getcontext(J); fz_drop_text(ctx, text); } static void ffi_gc_fz_font(js_State *J, void *font) { fz_context *ctx = js_getcontext(J); fz_drop_font(ctx, font); } static void ffi_gc_fz_shade(js_State *J, void *shade) { fz_context *ctx = js_getcontext(J); fz_drop_shade(ctx, shade); } static void ffi_gc_fz_image(js_State *J, void *image) { fz_context *ctx = js_getcontext(J); fz_drop_image(ctx, image); } static void ffi_gc_fz_display_list(js_State *J, void *list) { fz_context *ctx = js_getcontext(J); fz_drop_display_list(ctx, list); } static void ffi_gc_fz_stext_page(js_State *J, void *text) { fz_context *ctx = js_getcontext(J); fz_drop_stext_page(ctx, text); } static void ffi_gc_fz_device(js_State *J, void *device) { fz_context *ctx = js_getcontext(J); fz_drop_device(ctx, device); } static void ffi_gc_fz_document_writer(js_State *J, void *wri) { fz_context *ctx = js_getcontext(J); fz_drop_document_writer(ctx, wri); } #if FZ_ENABLE_PDF static void ffi_gc_pdf_document(js_State *J, void *doc) { fz_context *ctx = js_getcontext(J); pdf_drop_document(ctx, doc); } static void ffi_gc_pdf_obj(js_State *J, void *obj) { fz_context *ctx = js_getcontext(J); pdf_drop_obj(ctx, obj); } static void ffi_gc_pdf_graft_map(js_State *J, void *map) { fz_context *ctx = js_getcontext(J); pdf_drop_graft_map(ctx, map); } static fz_document *ffi_todocument(js_State *J, int idx) { if (js_isuserdata(J, idx, "pdf_document")) return js_touserdata(J, idx, "pdf_document"); return js_touserdata(J, idx, "fz_document"); } static void ffi_pushdocument(js_State *J, fz_document *document) { fz_context *ctx = js_getcontext(J); pdf_document *pdocument = pdf_document_from_fz_document(ctx, document); if (pdocument) { js_getregistry(J, "pdf_document"); js_newuserdata(J, "pdf_document", document, ffi_gc_fz_document); } else { js_getregistry(J, "fz_document"); js_newuserdata(J, "fz_document", document, ffi_gc_fz_document); } } static fz_page *ffi_topage(js_State *J, int idx) { if (js_isuserdata(J, idx, "pdf_page")) return js_touserdata(J, idx, "pdf_page"); return js_touserdata(J, idx, "fz_page"); } static void ffi_pushpage(js_State *J, fz_page *page) { fz_context *ctx = js_getcontext(J); pdf_page *ppage = pdf_page_from_fz_page(ctx, page); if (ppage) { js_getregistry(J, "pdf_page"); js_newuserdata(J, "pdf_page", page, ffi_gc_fz_page); } else { js_getregistry(J, "fz_page"); js_newuserdata(J, "fz_page", page, ffi_gc_fz_page); } } static fz_annot *ffi_toannot(js_State *J, int idx) { if (js_isuserdata(J, idx, "pdf_annot")) return js_touserdata(J, idx, "pdf_annot"); return js_touserdata(J, idx, "fz_annot"); } static void ffi_pushannot(js_State *J, fz_annot *annot) { fz_context *ctx = js_getcontext(J); pdf_annot *pannot = pdf_annot_from_fz_annot(ctx, annot); if (pannot) { int subtype; fz_try(ctx) subtype = pdf_annot_type(ctx, pannot); fz_catch(ctx) rethrow(J); switch (subtype) { default: js_getregistry(J, "pdf_annot"); break; case PDF_ANNOT_TEXT: js_getregistry(J, "pdf_annot"); break; case PDF_ANNOT_LINK: js_getregistry(J, "pdf_annot"); break; case PDF_ANNOT_FREE_TEXT: js_getregistry(J, "pdf_annot"); break; case PDF_ANNOT_LINE: js_getregistry(J, "pdf_annot"); break; case PDF_ANNOT_SQUARE: js_getregistry(J, "pdf_annot"); break; case PDF_ANNOT_CIRCLE: js_getregistry(J, "pdf_annot"); break; case PDF_ANNOT_POLYGON: js_getregistry(J, "pdf_annot"); break; case PDF_ANNOT_POLY_LINE: js_getregistry(J, "pdf_annot"); break; case PDF_ANNOT_HIGHLIGHT: js_getregistry(J, "pdf_annot"); break; case PDF_ANNOT_UNDERLINE: js_getregistry(J, "pdf_annot"); break; case PDF_ANNOT_SQUIGGLY: js_getregistry(J, "pdf_annot"); break; case PDF_ANNOT_STRIKE_OUT: js_getregistry(J, "pdf_annot"); break; case PDF_ANNOT_STAMP: js_getregistry(J, "pdf_annot"); break; case PDF_ANNOT_INK: js_getregistry(J, "pdf_annot"); break; } js_newuserdata(J, "pdf_annot", fz_keep_annot(ctx, annot), ffi_gc_fz_annot); } else { js_getregistry(J, "fz_annot"); js_newuserdata(J, "fz_annot", fz_keep_annot(ctx, annot), ffi_gc_fz_annot); } } #else static fz_document *ffi_todocument(js_State *J, int idx) { return js_touserdata(J, idx, "fz_document"); } static void ffi_pushdocument(js_State *J, fz_document *document) { js_getregistry(J, "fz_document"); js_newuserdata(J, "fz_document", doc, ffi_gc_fz_document); } static fz_page *ffi_topage(js_State *J, int idx) { return js_touserdata(J, idx, "fz_page"); } static void ffi_pushpage(js_State *J, fz_page *page) { js_getregistry(J, "fz_page"); js_newuserdata(J, "fz_page", page, ffi_gc_fz_page); } static fz_annot *ffi_toannot(js_State *J, int idx) { return js_touserdata(J, idx, "fz_annot"); } static void ffi_pushannot(js_State *J, fz_annot *annot) { fz_context *ctx = js_getcontext(J); js_getregistry(J, "fz_annot"); js_newuserdata(J, "fz_annot", fz_keep_annot(ctx, annot), ffi_gc_fz_annot); } #endif /* FZ_ENABLE_PDF */ /* type conversions */ struct color { fz_colorspace *colorspace; float color[FZ_MAX_COLORS]; float alpha; }; static fz_matrix ffi_tomatrix(js_State *J, int idx) { if (js_iscoercible(J, idx)) { fz_matrix matrix; js_getindex(J, idx, 0); matrix.a = js_tonumber(J, -1); js_pop(J, 1); js_getindex(J, idx, 1); matrix.b = js_tonumber(J, -1); js_pop(J, 1); js_getindex(J, idx, 2); matrix.c = js_tonumber(J, -1); js_pop(J, 1); js_getindex(J, idx, 3); matrix.d = js_tonumber(J, -1); js_pop(J, 1); js_getindex(J, idx, 4); matrix.e = js_tonumber(J, -1); js_pop(J, 1); js_getindex(J, idx, 5); matrix.f = js_tonumber(J, -1); js_pop(J, 1); return matrix; } return fz_identity; } static void ffi_pushmatrix(js_State *J, fz_matrix matrix) { js_newarray(J); js_pushnumber(J, matrix.a); js_setindex(J, -2, 0); js_pushnumber(J, matrix.b); js_setindex(J, -2, 1); js_pushnumber(J, matrix.c); js_setindex(J, -2, 2); js_pushnumber(J, matrix.d); js_setindex(J, -2, 3); js_pushnumber(J, matrix.e); js_setindex(J, -2, 4); js_pushnumber(J, matrix.f); js_setindex(J, -2, 5); } static fz_point ffi_topoint(js_State *J, int idx) { fz_point point; js_getindex(J, idx, 0); point.x = js_tonumber(J, -1); js_pop(J, 1); js_getindex(J, idx, 1); point.y = js_tonumber(J, -1); js_pop(J, 1); return point; } static fz_rect ffi_torect(js_State *J, int idx) { fz_rect rect; js_getindex(J, idx, 0); rect.x0 = js_tonumber(J, -1); js_pop(J, 1); js_getindex(J, idx, 1); rect.y0 = js_tonumber(J, -1); js_pop(J, 1); js_getindex(J, idx, 2); rect.x1 = js_tonumber(J, -1); js_pop(J, 1); js_getindex(J, idx, 3); rect.y1 = js_tonumber(J, -1); js_pop(J, 1); return rect; } static void ffi_pushrect(js_State *J, fz_rect rect) { js_newarray(J); js_pushnumber(J, rect.x0); js_setindex(J, -2, 0); js_pushnumber(J, rect.y0); js_setindex(J, -2, 1); js_pushnumber(J, rect.x1); js_setindex(J, -2, 2); js_pushnumber(J, rect.y1); js_setindex(J, -2, 3); } static void ffi_pushquad(js_State *J, fz_quad quad) { js_newarray(J); js_pushnumber(J, quad.ul.x); js_setindex(J, -2, 0); js_pushnumber(J, quad.ul.y); js_setindex(J, -2, 1); js_pushnumber(J, quad.ur.x); js_setindex(J, -2, 0); js_pushnumber(J, quad.ur.y); js_setindex(J, -2, 1); js_pushnumber(J, quad.ll.x); js_setindex(J, -2, 0); js_pushnumber(J, quad.ll.y); js_setindex(J, -2, 1); js_pushnumber(J, quad.lr.x); js_setindex(J, -2, 0); js_pushnumber(J, quad.lr.y); js_setindex(J, -2, 1); } static fz_irect ffi_toirect(js_State *J, int idx) { fz_irect irect; js_getindex(J, idx, 0); irect.x0 = js_tonumber(J, -1); js_pop(J, 1); js_getindex(J, idx, 1); irect.y0 = js_tonumber(J, -1); js_pop(J, 1); js_getindex(J, idx, 2); irect.x1 = js_tonumber(J, -1); js_pop(J, 1); js_getindex(J, idx, 3); irect.y1 = js_tonumber(J, -1); js_pop(J, 1); return irect; } static void ffi_pusharray(js_State *J, const float *v, int n) { int i; js_newarray(J); for (i = 0; i < n; ++i) { js_pushnumber(J, v[i]); js_setindex(J, -2, i); } } static void ffi_pushcolorspace(js_State *J, fz_colorspace *colorspace) { fz_context *ctx = js_getcontext(J); if (colorspace == fz_device_rgb(ctx)) js_getregistry(J, "DeviceRGB"); else if (colorspace == fz_device_bgr(ctx)) js_getregistry(J, "DeviceBGR"); else if (colorspace == fz_device_gray(ctx)) js_getregistry(J, "DeviceGray"); else if (colorspace == fz_device_cmyk(ctx)) js_getregistry(J, "DeviceCMYK"); else { js_getregistry(J, "fz_colorspace"); js_newuserdata(J, "fz_colorspace", fz_keep_colorspace(ctx, colorspace), ffi_gc_fz_colorspace); } } static void ffi_pushcolor(js_State *J, fz_colorspace *colorspace, const float *color, float alpha) { fz_context *ctx = js_getcontext(J); if (colorspace) { ffi_pushcolorspace(J, colorspace); ffi_pusharray(J, color, fz_colorspace_n(ctx, colorspace)); } else { js_pushnull(J); js_pushnull(J); } js_pushnumber(J, alpha); } static struct color ffi_tocolor(js_State *J, int idx) { struct color c; int n, i; fz_context *ctx = js_getcontext(J); c.colorspace = js_touserdata(J, idx, "fz_colorspace"); if (c.colorspace) { n = fz_colorspace_n(ctx, c.colorspace); for (i=0; i < n; ++i) { js_getindex(J, idx + 1, i); c.color[i] = js_tonumber(J, -1); js_pop(J, 1); } } c.alpha = js_tonumber(J, idx + 2); return c; } static fz_color_params *ffi_tocolorparams(js_State *J, int idx) { /* TODO */ return NULL; } static void ffi_pushcolorparams(js_State *J, const fz_color_params *color_params) { /* TODO */ js_pushnull(J); } static const char *string_from_cap(fz_linecap cap) { switch (cap) { default: case FZ_LINECAP_BUTT: return "Butt"; case FZ_LINECAP_ROUND: return "Round"; case FZ_LINECAP_SQUARE: return "Square"; case FZ_LINECAP_TRIANGLE: return "Triangle"; } } static const char *string_from_join(fz_linejoin join) { switch (join) { default: case FZ_LINEJOIN_MITER: return "Miter"; case FZ_LINEJOIN_ROUND: return "Round"; case FZ_LINEJOIN_BEVEL: return "Bevel"; case FZ_LINEJOIN_MITER_XPS: return "MiterXPS"; } } static fz_linecap cap_from_string(const char *str) { if (!strcmp(str, "Round")) return FZ_LINECAP_ROUND; if (!strcmp(str, "Square")) return FZ_LINECAP_SQUARE; if (!strcmp(str, "Triangle")) return FZ_LINECAP_TRIANGLE; return FZ_LINECAP_BUTT; } static fz_linejoin join_from_string(const char *str) { if (!strcmp(str, "Round")) return FZ_LINEJOIN_ROUND; if (!strcmp(str, "Bevel")) return FZ_LINEJOIN_BEVEL; if (!strcmp(str, "MiterXPS")) return FZ_LINEJOIN_MITER_XPS; return FZ_LINEJOIN_MITER; } static void ffi_pushstroke(js_State *J, const fz_stroke_state *stroke) { js_newobject(J); js_pushliteral(J, string_from_cap(stroke->start_cap)); js_setproperty(J, -2, "startCap"); js_pushliteral(J, string_from_cap(stroke->dash_cap)); js_setproperty(J, -2, "dashCap"); js_pushliteral(J, string_from_cap(stroke->end_cap)); js_setproperty(J, -2, "endCap"); js_pushliteral(J, string_from_join(stroke->linejoin)); js_setproperty(J, -2, "lineJoin"); js_pushnumber(J, stroke->linewidth); js_setproperty(J, -2, "lineWidth"); js_pushnumber(J, stroke->miterlimit); js_setproperty(J, -2, "miterLimit"); js_pushnumber(J, stroke->dash_phase); js_setproperty(J, -2, "dashPhase"); ffi_pusharray(J, stroke->dash_list, stroke->dash_len); js_setproperty(J, -2, "dashes"); } static fz_stroke_state ffi_tostroke(js_State *J, int idx) { fz_stroke_state stroke = fz_default_stroke_state; if (js_hasproperty(J, idx, "lineCap")) { stroke.start_cap = cap_from_string(js_tostring(J, -1)); stroke.dash_cap = stroke.start_cap; stroke.end_cap = stroke.start_cap; } if (js_hasproperty(J, idx, "startCap")) { stroke.start_cap = cap_from_string(js_tostring(J, -1)); js_pop(J, 1); } if (js_hasproperty(J, idx, "dashCap")) { stroke.dash_cap = cap_from_string(js_tostring(J, -1)); js_pop(J, 1); } if (js_hasproperty(J, idx, "endCap")) { stroke.end_cap = cap_from_string(js_tostring(J, -1)); js_pop(J, 1); } if (js_hasproperty(J, idx, "lineJoin")) { stroke.linejoin = join_from_string(js_tostring(J, -1)); js_pop(J, 1); } if (js_hasproperty(J, idx, "lineWidth")) { stroke.linewidth = js_tonumber(J, -1); js_pop(J, 1); } if (js_hasproperty(J, idx, "miterLimit")) { stroke.miterlimit = js_tonumber(J, -1); js_pop(J, 1); } if (js_hasproperty(J, idx, "dashPhase")) { stroke.dash_phase = js_tonumber(J, -1); js_pop(J, 1); } if (js_hasproperty(J, idx, "dashes")) { int i, n = js_getlength(J, -1); if (n > nelem(stroke.dash_list)) n = nelem(stroke.dash_list); stroke.dash_len = n; for (i = 0; i < n; ++i) { js_getindex(J, -1, i); stroke.dash_list[i] = js_tonumber(J, -1); js_pop(J, 1); } } return stroke; } static void ffi_pushtext(js_State *J, const fz_text *text) { fz_context *ctx = js_getcontext(J); js_getregistry(J, "fz_text"); js_newuserdata(J, "fz_text", fz_keep_text(ctx, text), ffi_gc_fz_text); } static void ffi_pushpath(js_State *J, const fz_path *path) { fz_context *ctx = js_getcontext(J); js_getregistry(J, "fz_path"); js_newuserdata(J, "fz_path", fz_keep_path(ctx, path), ffi_gc_fz_path); } static void ffi_pushfont(js_State *J, fz_font *font) { fz_context *ctx = js_getcontext(J); js_getregistry(J, "fz_font"); js_newuserdata(J, "fz_font", fz_keep_font(ctx, font), ffi_gc_fz_font); } static void ffi_pushshade(js_State *J, fz_shade *shade) { fz_context *ctx = js_getcontext(J); js_getregistry(J, "fz_shade"); js_newuserdata(J, "fz_shade", fz_keep_shade(ctx, shade), ffi_gc_fz_shade); } static void ffi_pushimage(js_State *J, fz_image *image) { fz_context *ctx = js_getcontext(J); js_getregistry(J, "fz_image"); js_newuserdata(J, "fz_image", fz_keep_image(ctx, image), ffi_gc_fz_image); } static void ffi_pushimage_own(js_State *J, fz_image *image) { js_getregistry(J, "fz_image"); js_newuserdata(J, "fz_image", image, ffi_gc_fz_image); } static int is_number(const char *key, int *idx) { char *end; *idx = strtol(key, &end, 10); return *end == 0; } static int ffi_buffer_has(js_State *J, void *buf_, const char *key) { fz_buffer *buf = buf_; int idx; unsigned char *data; size_t len = fz_buffer_storage(js_getcontext(J), buf, &data); if (is_number(key, &idx)) { if (idx < 0 || (size_t)idx >= len) js_rangeerror(J, "index out of bounds"); js_pushnumber(J, data[idx]); return 1; } if (!strcmp(key, "length")) { js_pushnumber(J, len); return 1; } return 0; } static int ffi_buffer_put(js_State *J, void *buf_, const char *key) { fz_buffer *buf = buf_; int idx; unsigned char *data; size_t len = fz_buffer_storage(js_getcontext(J), buf, &data); if (is_number(key, &idx)) { if (idx < 0 || (size_t)idx >= len) js_rangeerror(J, "index out of bounds"); data[idx] = js_tonumber(J, -1); return 1; } if (!strcmp(key, "length")) js_typeerror(J, "buffer length is read-only"); return 0; } static void ffi_pushbuffer(js_State *J, fz_buffer *buf) { js_getregistry(J, "fz_buffer"); js_newuserdatax(J, "fz_buffer", buf, ffi_buffer_has, ffi_buffer_put, NULL, ffi_gc_fz_buffer); } #if FZ_ENABLE_PDF static fz_buffer *ffi_tobuffer(js_State *J, int idx) { fz_context *ctx = js_getcontext(J); fz_buffer *buf = NULL; if (js_isuserdata(J, idx, "fz_buffer")) buf = fz_keep_buffer(ctx, js_touserdata(J, idx, "fz_buffer")); else { const char *str = js_tostring(J, idx); fz_try(ctx) buf = fz_new_buffer_from_copied_data(ctx, (const unsigned char *)str, strlen(str)); fz_catch(ctx) rethrow(J); } return buf; } #endif /* FZ_ENABLE_PDF */ /* device calling into js from c */ typedef struct js_device_s { fz_device super; js_State *J; } js_device; static void js_dev_fill_path(fz_context *ctx, fz_device *dev, const fz_path *path, int even_odd, fz_matrix ctm, fz_colorspace *colorspace, const float *color, float alpha, const fz_color_params *color_params) { js_State *J = ((js_device*)dev)->J; if (js_try(J)) rethrow_as_fz(J); if (js_hasproperty(J, -1, "fillPath")) { js_copy(J, -2); ffi_pushpath(J, path); js_pushboolean(J, even_odd); ffi_pushmatrix(J, ctm); ffi_pushcolor(J, colorspace, color, alpha); ffi_pushcolorparams(J, color_params); js_call(J, 7); js_pop(J, 1); } js_endtry(J); } static void js_dev_clip_path(fz_context *ctx, fz_device *dev, const fz_path *path, int even_odd, fz_matrix ctm, fz_rect scissor) { js_State *J = ((js_device*)dev)->J; if (js_try(J)) rethrow_as_fz(J); if (js_hasproperty(J, -1, "clipPath")) { js_copy(J, -2); ffi_pushpath(J, path); js_pushboolean(J, even_odd); ffi_pushmatrix(J, ctm); js_call(J, 3); js_pop(J, 1); } js_endtry(J); } static void js_dev_stroke_path(fz_context *ctx, fz_device *dev, const fz_path *path, const fz_stroke_state *stroke, fz_matrix ctm, fz_colorspace *colorspace, const float *color, float alpha, const fz_color_params *color_params) { js_State *J = ((js_device*)dev)->J; if (js_try(J)) rethrow_as_fz(J); if (js_hasproperty(J, -1, "strokePath")) { js_copy(J, -2); ffi_pushpath(J, path); ffi_pushstroke(J, stroke); ffi_pushmatrix(J, ctm); ffi_pushcolor(J, colorspace, color, alpha); ffi_pushcolorparams(J, color_params); js_call(J, 7); js_pop(J, 1); } js_endtry(J); } static void js_dev_clip_stroke_path(fz_context *ctx, fz_device *dev, const fz_path *path, const fz_stroke_state *stroke, fz_matrix ctm, fz_rect scissor) { js_State *J = ((js_device*)dev)->J; if (js_try(J)) rethrow_as_fz(J); if (js_hasproperty(J, -1, "clipStrokePath")) { js_copy(J, -2); ffi_pushpath(J, path); ffi_pushstroke(J, stroke); ffi_pushmatrix(J, ctm); js_call(J, 3); js_pop(J, 1); } js_endtry(J); } static void js_dev_fill_text(fz_context *ctx, fz_device *dev, const fz_text *text, fz_matrix ctm, fz_colorspace *colorspace, const float *color, float alpha, const fz_color_params *color_params) { js_State *J = ((js_device*)dev)->J; if (js_try(J)) rethrow_as_fz(J); if (js_hasproperty(J, -1, "fillText")) { js_copy(J, -2); ffi_pushtext(J, text); ffi_pushmatrix(J, ctm); ffi_pushcolor(J, colorspace, color, alpha); ffi_pushcolorparams(J, color_params); js_call(J, 6); js_pop(J, 1); } js_endtry(J); } static void js_dev_stroke_text(fz_context *ctx, fz_device *dev, const fz_text *text, const fz_stroke_state *stroke, fz_matrix ctm, fz_colorspace *colorspace, const float *color, float alpha, const fz_color_params *color_params) { js_State *J = ((js_device*)dev)->J; if (js_try(J)) rethrow_as_fz(J); if (js_hasproperty(J, -1, "strokeText")) { js_copy(J, -2); ffi_pushtext(J, text); ffi_pushstroke(J, stroke); ffi_pushmatrix(J, ctm); ffi_pushcolor(J, colorspace, color, alpha); ffi_pushcolorparams(J, color_params); js_call(J, 7); js_pop(J, 1); } js_endtry(J); } static void js_dev_clip_text(fz_context *ctx, fz_device *dev, const fz_text *text, fz_matrix ctm, fz_rect scissor) { js_State *J = ((js_device*)dev)->J; if (js_try(J)) rethrow_as_fz(J); if (js_hasproperty(J, -1, "clipText")) { js_copy(J, -2); ffi_pushtext(J, text); ffi_pushmatrix(J, ctm); js_call(J, 2); js_pop(J, 1); } js_endtry(J); } static void js_dev_clip_stroke_text(fz_context *ctx, fz_device *dev, const fz_text *text, const fz_stroke_state *stroke, fz_matrix ctm, fz_rect scissor) { js_State *J = ((js_device*)dev)->J; if (js_try(J)) rethrow_as_fz(J); if (js_hasproperty(J, -1, "clipStrokeText")) { js_copy(J, -2); ffi_pushtext(J, text); ffi_pushstroke(J, stroke); ffi_pushmatrix(J, ctm); js_call(J, 3); js_pop(J, 1); } js_endtry(J); } static void js_dev_ignore_text(fz_context *ctx, fz_device *dev, const fz_text *text, fz_matrix ctm) { js_State *J = ((js_device*)dev)->J; if (js_try(J)) rethrow_as_fz(J); if (js_hasproperty(J, -1, "ignoreText")) { js_copy(J, -2); ffi_pushtext(J, text); ffi_pushmatrix(J, ctm); js_call(J, 2); js_pop(J, 1); } js_endtry(J); } static void js_dev_fill_shade(fz_context *ctx, fz_device *dev, fz_shade *shade, fz_matrix ctm, float alpha, const fz_color_params *color_params) { js_State *J = ((js_device*)dev)->J; if (js_try(J)) rethrow_as_fz(J); if (js_hasproperty(J, -1, "fillShade")) { js_copy(J, -2); ffi_pushshade(J, shade); ffi_pushmatrix(J, ctm); js_pushnumber(J, alpha); ffi_pushcolorparams(J, color_params); js_call(J, 4); js_pop(J, 1); } js_endtry(J); } static void js_dev_fill_image(fz_context *ctx, fz_device *dev, fz_image *image, fz_matrix ctm, float alpha, const fz_color_params *color_params) { js_State *J = ((js_device*)dev)->J; if (js_try(J)) rethrow_as_fz(J); if (js_hasproperty(J, -1, "fillImage")) { js_copy(J, -2); ffi_pushimage(J, image); ffi_pushmatrix(J, ctm); js_pushnumber(J, alpha); ffi_pushcolorparams(J, color_params); js_call(J, 4); js_pop(J, 1); } js_endtry(J); } static void js_dev_fill_image_mask(fz_context *ctx, fz_device *dev, fz_image *image, fz_matrix ctm, fz_colorspace *colorspace, const float *color, float alpha, const fz_color_params *color_params) { js_State *J = ((js_device*)dev)->J; if (js_try(J)) rethrow_as_fz(J); if (js_hasproperty(J, -1, "fillImageMask")) { js_copy(J, -2); ffi_pushimage(J, image); ffi_pushmatrix(J, ctm); ffi_pushcolor(J, colorspace, color, alpha); ffi_pushcolorparams(J, color_params); js_call(J, 6); js_pop(J, 1); } js_endtry(J); } static void js_dev_clip_image_mask(fz_context *ctx, fz_device *dev, fz_image *image, fz_matrix ctm, fz_rect scissor) { js_State *J = ((js_device*)dev)->J; if (js_try(J)) rethrow_as_fz(J); if (js_hasproperty(J, -1, "clipImageMask")) { js_copy(J, -2); ffi_pushimage(J, image); ffi_pushmatrix(J, ctm); js_call(J, 2); js_pop(J, 1); } js_endtry(J); } static void js_dev_pop_clip(fz_context *ctx, fz_device *dev) { js_State *J = ((js_device*)dev)->J; if (js_try(J)) rethrow_as_fz(J); if (js_hasproperty(J, -1, "popClip")) { js_copy(J, -2); js_call(J, 0); js_pop(J, 1); } js_endtry(J); } static void js_dev_begin_mask(fz_context *ctx, fz_device *dev, fz_rect bbox, int luminosity, fz_colorspace *colorspace, const float *color, const fz_color_params *color_params) { js_State *J = ((js_device*)dev)->J; if (js_try(J)) rethrow_as_fz(J); if (js_hasproperty(J, -1, "beginMask")) { js_copy(J, -2); ffi_pushrect(J, bbox); js_pushboolean(J, luminosity); ffi_pushcolor(J, colorspace, color, 1); ffi_pushcolorparams(J, color_params); js_call(J, 6); js_pop(J, 1); } js_endtry(J); } static void js_dev_end_mask(fz_context *ctx, fz_device *dev) { js_State *J = ((js_device*)dev)->J; if (js_try(J)) rethrow_as_fz(J); if (js_hasproperty(J, -1, "endMask")) { js_copy(J, -2); js_call(J, 0); js_pop(J, 1); } js_endtry(J); } static void js_dev_begin_group(fz_context *ctx, fz_device *dev, fz_rect bbox, fz_colorspace *cs, int isolated, int knockout, int blendmode, float alpha) { js_State *J = ((js_device*)dev)->J; if (js_try(J)) rethrow_as_fz(J); if (js_hasproperty(J, -1, "beginGroup")) { js_copy(J, -2); ffi_pushrect(J, bbox); js_pushboolean(J, isolated); js_pushboolean(J, knockout); js_pushliteral(J, fz_blendmode_name(blendmode)); js_pushnumber(J, alpha); js_call(J, 5); js_pop(J, 1); } js_endtry(J); } static void js_dev_end_group(fz_context *ctx, fz_device *dev) { js_State *J = ((js_device*)dev)->J; if (js_try(J)) rethrow_as_fz(J); if (js_hasproperty(J, -1, "endGroup")) { js_copy(J, -2); js_call(J, 0); js_pop(J, 1); } js_endtry(J); } static int js_dev_begin_tile(fz_context *ctx, fz_device *dev, fz_rect area, fz_rect view, float xstep, float ystep, fz_matrix ctm, int id) { js_State *J = ((js_device*)dev)->J; if (js_try(J)) rethrow_as_fz(J); if (js_hasproperty(J, -1, "beginTile")) { int n; js_copy(J, -2); ffi_pushrect(J, area); ffi_pushrect(J, view); js_pushnumber(J, xstep); js_pushnumber(J, ystep); ffi_pushmatrix(J, ctm); js_pushnumber(J, id); js_call(J, 6); n = js_tointeger(J, -1); js_pop(J, 1); return n; } js_endtry(J); return 0; } static void js_dev_end_tile(fz_context *ctx, fz_device *dev) { js_State *J = ((js_device*)dev)->J; if (js_try(J)) rethrow_as_fz(J); if (js_hasproperty(J, -1, "endTile")) { js_copy(J, -2); js_call(J, 0); js_pop(J, 1); } js_endtry(J); } static void js_dev_begin_layer(fz_context *ctx, fz_device *dev, const char *name) { js_State *J = ((js_device*)dev)->J; if (js_try(J)) rethrow_as_fz(J); if (js_hasproperty(J, -1, "beginLayer")) { js_copy(J, -2); js_pushstring(J, name); js_call(J, 1); js_pop(J, 1); } js_endtry(J); } static void js_dev_end_layer(fz_context *ctx, fz_device *dev) { js_State *J = ((js_device*)dev)->J; if (js_try(J)) rethrow_as_fz(J); if (js_hasproperty(J, -1, "endLayer")) { js_copy(J, -2); js_call(J, 0); js_pop(J, 1); } js_endtry(J); } static fz_device *new_js_device(fz_context *ctx, js_State *J) { js_device *dev = fz_new_derived_device(ctx, js_device); dev->super.fill_path = js_dev_fill_path; dev->super.stroke_path = js_dev_stroke_path; dev->super.clip_path = js_dev_clip_path; dev->super.clip_stroke_path = js_dev_clip_stroke_path; dev->super.fill_text = js_dev_fill_text; dev->super.stroke_text = js_dev_stroke_text; dev->super.clip_text = js_dev_clip_text; dev->super.clip_stroke_text = js_dev_clip_stroke_text; dev->super.ignore_text = js_dev_ignore_text; dev->super.fill_shade = js_dev_fill_shade; dev->super.fill_image = js_dev_fill_image; dev->super.fill_image_mask = js_dev_fill_image_mask; dev->super.clip_image_mask = js_dev_clip_image_mask; dev->super.pop_clip = js_dev_pop_clip; dev->super.begin_mask = js_dev_begin_mask; dev->super.end_mask = js_dev_end_mask; dev->super.begin_group = js_dev_begin_group; dev->super.end_group = js_dev_end_group; dev->super.begin_tile = js_dev_begin_tile; dev->super.end_tile = js_dev_end_tile; dev->super.begin_layer = js_dev_begin_layer; dev->super.end_layer = js_dev_end_layer; dev->J = J; return (fz_device*)dev; } /* device calling into c from js */ static void ffi_Device_close(js_State *J) { fz_context *ctx = js_getcontext(J); fz_device *dev = js_touserdata(J, 0, "fz_device"); fz_try(ctx) fz_close_device(ctx, dev); fz_catch(ctx) rethrow(J); } static void ffi_Device_fillPath(js_State *J) { fz_context *ctx = js_getcontext(J); fz_device *dev = js_touserdata(J, 0, "fz_device"); fz_path *path = js_touserdata(J, 1, "fz_path"); int even_odd = js_toboolean(J, 2); fz_matrix ctm = ffi_tomatrix(J, 3); struct color c = ffi_tocolor(J, 4); fz_color_params *color_params = ffi_tocolorparams(J, 7); fz_try(ctx) fz_fill_path(ctx, dev, path, even_odd, ctm, c.colorspace, c.color, c.alpha, color_params); fz_catch(ctx) rethrow(J); } static void ffi_Device_strokePath(js_State *J) { fz_context *ctx = js_getcontext(J); fz_device *dev = js_touserdata(J, 0, "fz_device"); fz_path *path = js_touserdata(J, 1, "fz_path"); fz_stroke_state stroke = ffi_tostroke(J, 2); fz_matrix ctm = ffi_tomatrix(J, 3); struct color c = ffi_tocolor(J, 4); fz_color_params *color_params = ffi_tocolorparams(J, 7); fz_try(ctx) fz_stroke_path(ctx, dev, path, &stroke, ctm, c.colorspace, c.color, c.alpha, color_params); fz_catch(ctx) rethrow(J); } static void ffi_Device_clipPath(js_State *J) { fz_context *ctx = js_getcontext(J); fz_device *dev = js_touserdata(J, 0, "fz_device"); fz_path *path = js_touserdata(J, 1, "fz_path"); int even_odd = js_toboolean(J, 2); fz_matrix ctm = ffi_tomatrix(J, 3); fz_try(ctx) fz_clip_path(ctx, dev, path, even_odd, ctm, fz_infinite_rect); fz_catch(ctx) rethrow(J); } static void ffi_Device_clipStrokePath(js_State *J) { fz_context *ctx = js_getcontext(J); fz_device *dev = js_touserdata(J, 0, "fz_device"); fz_path *path = js_touserdata(J, 1, "fz_path"); fz_stroke_state stroke = ffi_tostroke(J, 2); fz_matrix ctm = ffi_tomatrix(J, 3); fz_try(ctx) fz_clip_stroke_path(ctx, dev, path, &stroke, ctm, fz_infinite_rect); fz_catch(ctx) rethrow(J); } static void ffi_Device_fillText(js_State *J) { fz_context *ctx = js_getcontext(J); fz_device *dev = js_touserdata(J, 0, "fz_device"); fz_text *text = js_touserdata(J, 1, "fz_text"); fz_matrix ctm = ffi_tomatrix(J, 2); struct color c = ffi_tocolor(J, 3); fz_color_params *color_params = ffi_tocolorparams(J, 6); fz_try(ctx) fz_fill_text(ctx, dev, text, ctm, c.colorspace, c.color, c.alpha, color_params); fz_catch(ctx) rethrow(J); } static void ffi_Device_strokeText(js_State *J) { fz_context *ctx = js_getcontext(J); fz_device *dev = js_touserdata(J, 0, "fz_device"); fz_text *text = js_touserdata(J, 1, "fz_text"); fz_stroke_state stroke = ffi_tostroke(J, 2); fz_matrix ctm = ffi_tomatrix(J, 3); struct color c = ffi_tocolor(J, 4); fz_color_params *color_params = ffi_tocolorparams(J, 7); fz_try(ctx) fz_stroke_text(ctx, dev, text, &stroke, ctm, c.colorspace, c.color, c.alpha, color_params); fz_catch(ctx) rethrow(J); } static void ffi_Device_clipText(js_State *J) { fz_context *ctx = js_getcontext(J); fz_device *dev = js_touserdata(J, 0, "fz_device"); fz_text *text = js_touserdata(J, 1, "fz_text"); fz_matrix ctm = ffi_tomatrix(J, 2); fz_try(ctx) fz_clip_text(ctx, dev, text, ctm, fz_infinite_rect); fz_catch(ctx) rethrow(J); } static void ffi_Device_clipStrokeText(js_State *J) { fz_context *ctx = js_getcontext(J); fz_device *dev = js_touserdata(J, 0, "fz_device"); fz_text *text = js_touserdata(J, 1, "fz_text"); fz_stroke_state stroke = ffi_tostroke(J, 2); fz_matrix ctm = ffi_tomatrix(J, 3); fz_try(ctx) fz_clip_stroke_text(ctx, dev, text, &stroke, ctm, fz_infinite_rect); fz_catch(ctx) rethrow(J); } static void ffi_Device_ignoreText(js_State *J) { fz_context *ctx = js_getcontext(J); fz_device *dev = js_touserdata(J, 0, "fz_device"); fz_text *text = js_touserdata(J, 1, "fz_text"); fz_matrix ctm = ffi_tomatrix(J, 2); fz_try(ctx) fz_ignore_text(ctx, dev, text, ctm); fz_catch(ctx) rethrow(J); } static void ffi_Device_fillShade(js_State *J) { fz_context *ctx = js_getcontext(J); fz_device *dev = js_touserdata(J, 0, "fz_device"); fz_shade *shade = js_touserdata(J, 1, "fz_shade"); fz_matrix ctm = ffi_tomatrix(J, 2); float alpha = js_tonumber(J, 3); fz_color_params *color_params = ffi_tocolorparams(J, 4); fz_try(ctx) fz_fill_shade(ctx, dev, shade, ctm, alpha, color_params); fz_catch(ctx) rethrow(J); } static void ffi_Device_fillImage(js_State *J) { fz_context *ctx = js_getcontext(J); fz_device *dev = js_touserdata(J, 0, "fz_device"); fz_image *image = js_touserdata(J, 1, "fz_image"); fz_matrix ctm = ffi_tomatrix(J, 2); float alpha = js_tonumber(J, 3); fz_color_params *color_params = ffi_tocolorparams(J, 4); fz_try(ctx) fz_fill_image(ctx, dev, image, ctm, alpha, color_params); fz_catch(ctx) rethrow(J); } static void ffi_Device_fillImageMask(js_State *J) { fz_context *ctx = js_getcontext(J); fz_device *dev = js_touserdata(J, 0, "fz_device"); fz_image *image = js_touserdata(J, 1, "fz_image"); fz_matrix ctm = ffi_tomatrix(J, 2); struct color c = ffi_tocolor(J, 3); fz_color_params *color_params = ffi_tocolorparams(J, 6); fz_try(ctx) fz_fill_image_mask(ctx, dev, image, ctm, c.colorspace, c.color, c.alpha, color_params); fz_catch(ctx) rethrow(J); } static void ffi_Device_clipImageMask(js_State *J) { fz_context *ctx = js_getcontext(J); fz_device *dev = js_touserdata(J, 0, "fz_device"); fz_image *image = js_touserdata(J, 1, "fz_image"); fz_matrix ctm = ffi_tomatrix(J, 2); fz_try(ctx) fz_clip_image_mask(ctx, dev, image, ctm, fz_infinite_rect); fz_catch(ctx) rethrow(J); } static void ffi_Device_popClip(js_State *J) { fz_context *ctx = js_getcontext(J); fz_device *dev = js_touserdata(J, 0, "fz_device"); fz_try(ctx) fz_pop_clip(ctx, dev); fz_catch(ctx) rethrow(J); } static void ffi_Device_beginMask(js_State *J) { fz_context *ctx = js_getcontext(J); fz_device *dev = js_touserdata(J, 0, "fz_device"); fz_rect area = ffi_torect(J, 1); int luminosity = js_toboolean(J, 2); struct color c = ffi_tocolor(J, 3); fz_color_params *color_params = ffi_tocolorparams(J, 6); fz_try(ctx) fz_begin_mask(ctx, dev, area, luminosity, c.colorspace, c.color, color_params); fz_catch(ctx) rethrow(J); } static void ffi_Device_endMask(js_State *J) { fz_context *ctx = js_getcontext(J); fz_device *dev = js_touserdata(J, 0, "fz_device"); fz_try(ctx) fz_end_mask(ctx, dev); fz_catch(ctx) rethrow(J); } static void ffi_Device_beginGroup(js_State *J) { fz_context *ctx = js_getcontext(J); fz_device *dev = js_touserdata(J, 0, "fz_device"); fz_rect area = ffi_torect(J, 1); int isolated = js_toboolean(J, 2); int knockout = js_toboolean(J, 3); int blendmode = fz_lookup_blendmode(js_tostring(J, 4)); float alpha = js_tonumber(J, 5); fz_try(ctx) fz_begin_group(ctx, dev, area, NULL, isolated, knockout, blendmode, alpha); fz_catch(ctx) rethrow(J); } static void ffi_Device_endGroup(js_State *J) { fz_context *ctx = js_getcontext(J); fz_device *dev = js_touserdata(J, 0, "fz_device"); fz_try(ctx) fz_end_group(ctx, dev); fz_catch(ctx) rethrow(J); } static void ffi_Device_beginTile(js_State *J) { fz_context *ctx = js_getcontext(J); fz_device *dev = js_touserdata(J, 0, "fz_device"); fz_rect area = ffi_torect(J, 1); fz_rect view = ffi_torect(J, 2); float xstep = js_tonumber(J, 3); float ystep = js_tonumber(J, 4); fz_matrix ctm = ffi_tomatrix(J, 5); int id = js_tonumber(J, 6); int n = 0; fz_try(ctx) n = fz_begin_tile_id(ctx, dev, area, view, xstep, ystep, ctm, id); fz_catch(ctx) rethrow(J); js_pushnumber(J, n); } static void ffi_Device_endTile(js_State *J) { fz_context *ctx = js_getcontext(J); fz_device *dev = js_touserdata(J, 0, "fz_device"); fz_try(ctx) fz_end_tile(ctx, dev); fz_catch(ctx) rethrow(J); } static void ffi_Device_beginLayer(js_State *J) { fz_context *ctx = js_getcontext(J); fz_device *dev = js_touserdata(J, 0, "fz_device"); const char *name = js_tostring(J, 1); fz_try(ctx) fz_begin_layer(ctx, dev, name); fz_catch(ctx) rethrow(J); } static void ffi_Device_endLayer(js_State *J) { fz_context *ctx = js_getcontext(J); fz_device *dev = js_touserdata(J, 0, "fz_device"); fz_try(ctx) fz_end_layer(ctx, dev); fz_catch(ctx) rethrow(J); } /* mupdf module */ static void ffi_readFile(js_State *J) { fz_context *ctx = js_getcontext(J); const char *filename = js_tostring(J, 1); fz_buffer *buf = NULL; fz_try(ctx) buf = fz_read_file(ctx, filename); fz_catch(ctx) rethrow(J); ffi_pushbuffer(J, buf); } static void ffi_setUserCSS(js_State *J) { fz_context *ctx = js_getcontext(J); const char *user_css = js_tostring(J, 1); int use_doc_css = js_iscoercible(J, 2) ? js_toboolean(J, 2) : 1; fz_try(ctx) { fz_set_user_css(ctx, user_css); fz_set_use_document_css(ctx, use_doc_css); } fz_catch(ctx) rethrow(J); } static void ffi_new_Buffer(js_State *J) { fz_context *ctx = js_getcontext(J); int n = js_isdefined(J, 1) ? js_tonumber(J, 1) : 0; fz_buffer *buf = NULL; fz_try(ctx) buf = fz_new_buffer(ctx, n); fz_catch(ctx) rethrow(J); ffi_pushbuffer(J, buf); } static void ffi_Buffer_writeByte(js_State *J) { fz_context *ctx = js_getcontext(J); fz_buffer *buf = js_touserdata(J, 0, "fz_buffer"); unsigned char val = js_tonumber(J, 1); fz_try(ctx) fz_append_byte(ctx, buf, val); fz_catch(ctx) rethrow(J); } static void ffi_Buffer_writeRune(js_State *J) { fz_context *ctx = js_getcontext(J); fz_buffer *buf = js_touserdata(J, 0, "fz_buffer"); int val = js_tonumber(J, 1); fz_try(ctx) fz_append_rune(ctx, buf, val); fz_catch(ctx) rethrow(J); } static void ffi_Buffer_write(js_State *J) { fz_context *ctx = js_getcontext(J); fz_buffer *buf = js_touserdata(J, 0, "fz_buffer"); int i, n = js_gettop(J); for (i = 1; i < n; ++i) { const char *s = js_tostring(J, i); fz_try(ctx) { if (i > 1) fz_append_byte(ctx, buf, ' '); fz_append_string(ctx, buf, s); } fz_catch(ctx) rethrow(J); } } static void ffi_Buffer_writeLine(js_State *J) { fz_context *ctx = js_getcontext(J); fz_buffer *buf = js_touserdata(J, 0, "fz_buffer"); ffi_Buffer_write(J); fz_try(ctx) fz_append_byte(ctx, buf, '\n'); fz_catch(ctx) rethrow(J); } static void ffi_Buffer_writeBuffer(js_State *J) { fz_context *ctx = js_getcontext(J); fz_buffer *buf = js_touserdata(J, 0, "fz_buffer"); fz_buffer *cat = js_touserdata(J, 1, "fz_buffer"); fz_try(ctx) fz_append_buffer(ctx, buf, cat); fz_catch(ctx) rethrow(J); } static void ffi_Buffer_save(js_State *J) { fz_context *ctx = js_getcontext(J); fz_buffer *buf = js_touserdata(J, 0, "fz_buffer"); const char *filename = js_tostring(J, 1); fz_try(ctx) fz_save_buffer(ctx, buf, filename); fz_catch(ctx) rethrow(J); } static void ffi_new_Document(js_State *J) { fz_context *ctx = js_getcontext(J); const char *filename = js_tostring(J, 1); fz_document *doc = NULL; fz_try(ctx) doc = fz_open_document(ctx, filename); fz_catch(ctx) rethrow(J); ffi_pushdocument(J, doc); } static void ffi_Document_isPDF(js_State *J) { js_pushboolean(J, js_isuserdata(J, 0, "pdf_document")); } static void ffi_Document_countPages(js_State *J) { fz_context *ctx = js_getcontext(J); fz_document *doc = ffi_todocument(J, 0); int count = 0; fz_try(ctx) count = fz_count_pages(ctx, doc); fz_catch(ctx) rethrow(J); js_pushnumber(J, count); } static void ffi_Document_loadPage(js_State *J) { fz_context *ctx = js_getcontext(J); fz_document *doc = ffi_todocument(J, 0); int number = js_tointeger(J, 1); fz_page *page = NULL; fz_try(ctx) page = fz_load_page(ctx, doc, number); fz_catch(ctx) rethrow(J); ffi_pushpage(J, page); } static void ffi_Document_needsPassword(js_State *J) { fz_context *ctx = js_getcontext(J); fz_document *doc = ffi_todocument(J, 0); int b = 0; fz_try(ctx) b = fz_needs_password(ctx, doc); fz_catch(ctx) rethrow(J); js_pushboolean(J, b); } static void ffi_Document_authenticatePassword(js_State *J) { fz_context *ctx = js_getcontext(J); fz_document *doc = ffi_todocument(J, 0); const char *password = js_tostring(J, 1); int b = 0; fz_try(ctx) b = fz_authenticate_password(ctx, doc, password); fz_catch(ctx) rethrow(J); js_pushboolean(J, b); } static void ffi_Document_getMetaData(js_State *J) { fz_context *ctx = js_getcontext(J); fz_document *doc = ffi_todocument(J, 0); const char *key = js_tostring(J, 1); char info[256]; int found; fz_try(ctx) found = fz_lookup_metadata(ctx, doc, key, info, sizeof info); fz_catch(ctx) rethrow(J); if (found) js_pushstring(J, info); else js_pushundefined(J); } static void ffi_Document_isReflowable(js_State *J) { fz_context *ctx = js_getcontext(J); fz_document *doc = ffi_todocument(J, 0); int is_reflowable = 0; fz_try(ctx) is_reflowable = fz_is_document_reflowable(ctx, doc); fz_catch(ctx) rethrow(J); js_pushboolean(J, is_reflowable); } static void ffi_Document_layout(js_State *J) { fz_context *ctx = js_getcontext(J); fz_document *doc = ffi_todocument(J, 0); float w = js_tonumber(J, 1); float h = js_tonumber(J, 2); float em = js_tonumber(J, 3); fz_try(ctx) fz_layout_document(ctx, doc, w, h, em); fz_catch(ctx) rethrow(J); } static void to_outline(js_State *J, fz_outline *outline) { int i = 0; js_newarray(J); while (outline) { js_newobject(J); if (outline->title) js_pushstring(J, outline->title); else js_pushundefined(J); js_setproperty(J, -2, "title"); if (outline->uri) js_pushstring(J, outline->uri); else js_pushundefined(J); js_setproperty(J, -2, "uri"); if (outline->page >= 0) js_pushnumber(J, outline->page); else js_pushundefined(J); js_setproperty(J, -2, "page"); if (outline->down) { to_outline(J, outline->down); js_setproperty(J, -2, "down"); } js_setindex(J, -2, i++); outline = outline->next; } } static void ffi_Document_loadOutline(js_State *J) { fz_context *ctx = js_getcontext(J); fz_document *doc = ffi_todocument(J, 0); fz_outline *outline = NULL; fz_try(ctx) outline = fz_load_outline(ctx, doc); fz_catch(ctx) rethrow(J); to_outline(J, outline); fz_drop_outline(ctx, outline); } static void ffi_Page_isPDF(js_State *J) { js_pushboolean(J, js_isuserdata(J, 0, "pdf_page")); } static void ffi_Page_bound(js_State *J) { fz_context *ctx = js_getcontext(J); fz_page *page = ffi_topage(J, 0); fz_rect bounds; fz_try(ctx) bounds = fz_bound_page(ctx, page); fz_catch(ctx) rethrow(J); ffi_pushrect(J, bounds); } static void ffi_Page_run(js_State *J) { fz_context *ctx = js_getcontext(J); fz_page *page = ffi_topage(J, 0); fz_device *device = NULL; fz_matrix ctm = ffi_tomatrix(J, 2); int no_annots = js_isdefined(J, 3) ? js_toboolean(J, 3) : 0; if (js_isuserdata(J, 1, "fz_device")) { device = js_touserdata(J, 1, "fz_device"); fz_try(ctx) if (no_annots) fz_run_page_contents(ctx, page, device, ctm, NULL); else fz_run_page(ctx, page, device, ctm, NULL); fz_catch(ctx) rethrow(J); } else { device = new_js_device(ctx, J); js_copy(J, 1); /* put the js device on the top so the callbacks know where to get it */ fz_try(ctx) { if (no_annots) fz_run_page_contents(ctx, page, device, ctm, NULL); else fz_run_page(ctx, page, device, ctm, NULL); fz_close_device(ctx, device); } fz_always(ctx) fz_drop_device(ctx, device); fz_catch(ctx) rethrow(J); } } static void ffi_Page_toDisplayList(js_State *J) { fz_context *ctx = js_getcontext(J); fz_page *page = ffi_topage(J, 0); int no_annots = js_isdefined(J, 1) ? js_toboolean(J, 1) : 0; fz_display_list *list = NULL; fz_try(ctx) if (no_annots) list = fz_new_display_list_from_page_contents(ctx, page); else list = fz_new_display_list_from_page(ctx, page); fz_catch(ctx) rethrow(J); js_getregistry(J, "fz_display_list"); js_newuserdata(J, "fz_display_list", list, ffi_gc_fz_display_list); } static void ffi_Page_toPixmap(js_State *J) { fz_context *ctx = js_getcontext(J); fz_page *page = ffi_topage(J, 0); fz_matrix ctm = ffi_tomatrix(J, 1); fz_colorspace *colorspace = js_touserdata(J, 2, "fz_colorspace"); int alpha = js_toboolean(J, 3); int no_annots = js_isdefined(J, 4) ? js_toboolean(J, 4) : 0; fz_pixmap *pixmap = NULL; fz_try(ctx) if (no_annots) pixmap = fz_new_pixmap_from_page_contents(ctx, page, ctm, colorspace, alpha); else pixmap = fz_new_pixmap_from_page(ctx, page, ctm, colorspace, alpha); fz_catch(ctx) rethrow(J); js_getregistry(J, "fz_pixmap"); js_newuserdata(J, "fz_pixmap", pixmap, ffi_gc_fz_pixmap); } static void ffi_Page_toStructuredText(js_State *J) { fz_context *ctx = js_getcontext(J); fz_page *page = ffi_topage(J, 0); const char *options = js_iscoercible(J, 1) ? js_tostring(J, 1) : NULL; fz_stext_options so; fz_stext_page *text = NULL; fz_try(ctx) { fz_parse_stext_options(ctx, &so, options); text = fz_new_stext_page_from_page(ctx, page, &so); } fz_catch(ctx) rethrow(J); js_getregistry(J, "fz_stext_page"); js_newuserdata(J, "fz_stext_page", text, ffi_gc_fz_stext_page); } static void ffi_Page_search(js_State *J) { fz_context *ctx = js_getcontext(J); fz_page *page = ffi_topage(J, 0); const char *needle = js_tostring(J, 1); fz_quad hits[256]; int i, n = 0; fz_try(ctx) n = fz_search_page(ctx, page, needle, hits, nelem(hits)); fz_catch(ctx) rethrow(J); js_newarray(J); for (i = 0; i < n; ++i) { ffi_pushquad(J, hits[i]); js_setindex(J, -2, i); } } static void ffi_Page_getAnnotations(js_State *J) { fz_context *ctx = js_getcontext(J); fz_page *page = ffi_topage(J, 0); fz_annot *annot = NULL; int i = 0; js_newarray(J); fz_try(ctx) annot = fz_first_annot(ctx, page); fz_catch(ctx) rethrow(J); while (annot) { ffi_pushannot(J, annot); js_setindex(J, -2, i++); fz_try(ctx) annot = fz_next_annot(ctx, annot); fz_catch(ctx) rethrow(J); } } static void ffi_Page_getLinks(js_State *J) { fz_context *ctx = js_getcontext(J); fz_page *page = ffi_topage(J, 0); fz_link *link, *links = NULL; int i = 0; js_newarray(J); fz_try(ctx) links = fz_load_links(ctx, page); fz_catch(ctx) rethrow(J); js_newarray(J); for (link = links; link; link = link->next) { js_newobject(J); ffi_pushrect(J, link->rect); js_setproperty(J, -2, "bounds"); js_pushstring(J, link->uri); js_setproperty(J, -2, "uri"); js_setindex(J, -2, i++); } fz_drop_link(ctx, links); } static void ffi_Annotation_isPDF(js_State *J) { js_pushboolean(J, js_isuserdata(J, 0, "pdf_annot")); } static void ffi_Annotation_bound(js_State *J) { fz_context *ctx = js_getcontext(J); fz_annot *annot = ffi_toannot(J, 0); fz_rect bounds; fz_try(ctx) bounds = fz_bound_annot(ctx, annot); fz_catch(ctx) rethrow(J); ffi_pushrect(J, bounds); } static void ffi_Annotation_run(js_State *J) { fz_context *ctx = js_getcontext(J); fz_annot *annot = ffi_toannot(J, 0); fz_device *device = NULL; fz_matrix ctm = ffi_tomatrix(J, 2); if (js_isuserdata(J, 1, "fz_device")) { device = js_touserdata(J, 1, "fz_device"); fz_try(ctx) fz_run_annot(ctx, annot, device, ctm, NULL); fz_catch(ctx) rethrow(J); } else { device = new_js_device(ctx, J); js_copy(J, 1); /* put the js device on the top so the callbacks know where to get it */ fz_try(ctx) { fz_run_annot(ctx, annot, device, ctm, NULL); fz_close_device(ctx, device); } fz_always(ctx) fz_drop_device(ctx, device); fz_catch(ctx) rethrow(J); } } static void ffi_Annotation_toDisplayList(js_State *J) { fz_context *ctx = js_getcontext(J); fz_annot *annot = ffi_toannot(J, 0); fz_display_list *list = NULL; fz_try(ctx) list = fz_new_display_list_from_annot(ctx, annot); fz_catch(ctx) rethrow(J); js_getregistry(J, "fz_display_list"); js_newuserdata(J, "fz_display_list", list, ffi_gc_fz_display_list); } static void ffi_Annotation_toPixmap(js_State *J) { fz_context *ctx = js_getcontext(J); fz_annot *annot = ffi_toannot(J, 0); fz_matrix ctm = ffi_tomatrix(J, 1); fz_colorspace *colorspace = js_touserdata(J, 2, "fz_colorspace"); int alpha = js_toboolean(J, 3); fz_pixmap *pixmap = NULL; fz_try(ctx) pixmap = fz_new_pixmap_from_annot(ctx, annot, ctm, colorspace, alpha); fz_catch(ctx) rethrow(J); js_getregistry(J, "fz_pixmap"); js_newuserdata(J, "fz_pixmap", pixmap, ffi_gc_fz_pixmap); } static void ffi_ColorSpace_getNumberOfComponents(js_State *J) { fz_colorspace *colorspace = js_touserdata(J, 0, "fz_colorspace"); fz_context *ctx = js_getcontext(J); js_pushnumber(J, fz_colorspace_n(ctx, colorspace)); } static void ffi_ColorSpace_toString(js_State *J) { fz_colorspace *colorspace = js_touserdata(J, 0, "fz_colorspace"); fz_context *ctx = js_getcontext(J); js_pushstring(J, fz_colorspace_name(ctx, colorspace)); } static void ffi_new_Pixmap(js_State *J) { fz_context *ctx = js_getcontext(J); fz_colorspace *colorspace = js_touserdata(J, 1, "fz_colorspace"); fz_irect bounds = ffi_toirect(J, 2); int alpha = js_toboolean(J, 3); fz_pixmap *pixmap = NULL; fz_try(ctx) pixmap = fz_new_pixmap_with_bbox(ctx, colorspace, bounds, 0, alpha); fz_catch(ctx) rethrow(J); js_getregistry(J, "fz_pixmap"); js_newuserdata(J, "fz_pixmap", pixmap, ffi_gc_fz_pixmap); } static void ffi_Pixmap_saveAsPNG(js_State *J) { fz_context *ctx = js_getcontext(J); fz_pixmap *pixmap = js_touserdata(J, 0, "fz_pixmap"); const char *filename = js_tostring(J, 1); fz_try(ctx) fz_save_pixmap_as_png(ctx, pixmap, filename); fz_catch(ctx) rethrow(J); } static void ffi_Pixmap_bound(js_State *J) { fz_pixmap *pixmap = js_touserdata(J, 0, "fz_pixmap"); fz_rect bounds; // fz_irect and fz_pixmap_bbox instead bounds.x0 = pixmap->x; bounds.y0 = pixmap->y; bounds.x1 = pixmap->x + pixmap->w; bounds.y1 = pixmap->y + pixmap->h; ffi_pushrect(J, bounds); } static void ffi_Pixmap_clear(js_State *J) { fz_context *ctx = js_getcontext(J); fz_pixmap *pixmap = js_touserdata(J, 0, "fz_pixmap"); if (js_isdefined(J, 1)) { int value = js_tonumber(J, 1); fz_try(ctx) fz_clear_pixmap_with_value(ctx, pixmap, value); fz_catch(ctx) rethrow(J); } else { fz_try(ctx) fz_clear_pixmap(ctx, pixmap); fz_catch(ctx) rethrow(J); } } static void ffi_Pixmap_getX(js_State *J) { fz_pixmap *pixmap = js_touserdata(J, 0, "fz_pixmap"); js_pushnumber(J, pixmap->x); } static void ffi_Pixmap_getY(js_State *J) { fz_pixmap *pixmap = js_touserdata(J, 0, "fz_pixmap"); js_pushnumber(J, pixmap->y); } static void ffi_Pixmap_getWidth(js_State *J) { fz_pixmap *pixmap = js_touserdata(J, 0, "fz_pixmap"); js_pushnumber(J, pixmap->w); } static void ffi_Pixmap_getHeight(js_State *J) { fz_pixmap *pixmap = js_touserdata(J, 0, "fz_pixmap"); js_pushnumber(J, pixmap->h); } static void ffi_Pixmap_getNumberOfComponents(js_State *J) { fz_pixmap *pixmap = js_touserdata(J, 0, "fz_pixmap"); js_pushnumber(J, pixmap->n); } static void ffi_Pixmap_getAlpha(js_State *J) { fz_pixmap *pixmap = js_touserdata(J, 0, "fz_pixmap"); js_pushnumber(J, pixmap->alpha); } static void ffi_Pixmap_getStride(js_State *J) { fz_pixmap *pixmap = js_touserdata(J, 0, "fz_pixmap"); js_pushnumber(J, pixmap->stride); } static void ffi_Pixmap_getSample(js_State *J) { fz_pixmap *pixmap = js_touserdata(J, 0, "fz_pixmap"); int x = js_tointeger(J, 1); int y = js_tointeger(J, 2); int k = js_tointeger(J, 3); if (x < 0 || x >= pixmap->w) js_rangeerror(J, "X out of range"); if (y < 0 || y >= pixmap->h) js_rangeerror(J, "Y out of range"); if (k < 0 || k >= pixmap->n) js_rangeerror(J, "N out of range"); js_pushnumber(J, pixmap->samples[(x + y * pixmap->w) * pixmap->n + k]); } static void ffi_Pixmap_getXResolution(js_State *J) { fz_pixmap *pixmap = js_touserdata(J, 0, "fz_pixmap"); js_pushnumber(J, pixmap->xres); } static void ffi_Pixmap_getYResolution(js_State *J) { fz_pixmap *pixmap = js_touserdata(J, 0, "fz_pixmap"); js_pushnumber(J, pixmap->yres); } static void ffi_Pixmap_getColorSpace(js_State *J) { fz_pixmap *pixmap = js_touserdata(J, 0, "fz_pixmap"); ffi_pushcolorspace(J, pixmap->colorspace); } static void ffi_new_Image(js_State *J) { fz_context *ctx = js_getcontext(J); fz_image *image = NULL; if (js_isuserdata(J, 1, "fz_pixmap")) { fz_pixmap *pixmap = js_touserdata(J, 1, "fz_pixmap"); fz_try(ctx) image = fz_new_image_from_pixmap(ctx, pixmap, NULL); fz_catch(ctx) rethrow(J); } else { const char *name = js_tostring(J, 1); fz_try(ctx) image = fz_new_image_from_file(ctx, name); fz_catch(ctx) rethrow(J); } ffi_pushimage_own(J, image); } static void ffi_Image_getWidth(js_State *J) { fz_image *image = js_touserdata(J, 0, "fz_image"); js_pushnumber(J, image->w); } static void ffi_Image_getHeight(js_State *J) { fz_image *image = js_touserdata(J, 0, "fz_image"); js_pushnumber(J, image->h); } static void ffi_Image_getXResolution(js_State *J) { fz_image *image = js_touserdata(J, 0, "fz_image"); js_pushnumber(J, image->xres); } static void ffi_Image_getYResolution(js_State *J) { fz_image *image = js_touserdata(J, 0, "fz_image"); js_pushnumber(J, image->yres); } static void ffi_Image_getNumberOfComponents(js_State *J) { fz_image *image = js_touserdata(J, 0, "fz_image"); js_pushnumber(J, image->n); } static void ffi_Image_getBitsPerComponent(js_State *J) { fz_image *image = js_touserdata(J, 0, "fz_image"); js_pushnumber(J, image->bpc); } static void ffi_Image_getInterpolate(js_State *J) { fz_image *image = js_touserdata(J, 0, "fz_image"); js_pushboolean(J, image->interpolate); } static void ffi_Image_getImageMask(js_State *J) { fz_image *image = js_touserdata(J, 0, "fz_image"); js_pushboolean(J, image->imagemask); } static void ffi_Image_getMask(js_State *J) { fz_image *image = js_touserdata(J, 0, "fz_image"); if (image->mask) ffi_pushimage(J, image->mask); else js_pushnull(J); } static void ffi_Image_getColorSpace(js_State *J) { fz_image *image = js_touserdata(J, 0, "fz_image"); ffi_pushcolorspace(J, image->colorspace); } static void ffi_Image_toPixmap(js_State *J) { fz_context *ctx = js_getcontext(J); fz_image *image = js_touserdata(J, 0, "fz_image"); fz_pixmap *pixmap = NULL; fz_try(ctx) pixmap = fz_get_pixmap_from_image(ctx, image, NULL, NULL, NULL, NULL); fz_catch(ctx) rethrow(J); js_getregistry(J, "fz_pixmap"); js_newuserdata(J, "fz_pixmap", pixmap, ffi_gc_fz_pixmap); } static void ffi_Shade_bound(js_State *J) { fz_context *ctx = js_getcontext(J); fz_shade *shade = js_touserdata(J, 0, "fz_shade"); fz_matrix ctm = ffi_tomatrix(J, 1); fz_rect bounds; fz_try(ctx) bounds = fz_bound_shade(ctx, shade, ctm); fz_catch(ctx) rethrow(J); ffi_pushrect(J, bounds); } static void ffi_new_Font(js_State *J) { fz_context *ctx = js_getcontext(J); const char *name = js_tostring(J, 1); int index = js_isnumber(J, 2) ? js_tonumber(J, 2) : 0; const unsigned char *data; int size; fz_font *font = NULL; fz_try(ctx) { data = fz_lookup_base14_font(ctx, name, &size); if (data) font = fz_new_font_from_memory(ctx, name, data, size, index, 0); else font = fz_new_font_from_file(ctx, name, name, index, 0); } fz_catch(ctx) rethrow(J); js_getregistry(J, "fz_font"); js_newuserdata(J, "fz_font", font, ffi_gc_fz_font); } static void ffi_Font_getName(js_State *J) { fz_context *ctx = js_getcontext(J); fz_font *font = js_touserdata(J, 0, "fz_font"); js_pushstring(J, fz_font_name(ctx, font)); } static void ffi_Font_encodeCharacter(js_State *J) { fz_context *ctx = js_getcontext(J); fz_font *font = js_touserdata(J, 0, "fz_font"); int unicode = js_tonumber(J, 1); int glyph = 0; fz_try(ctx) glyph = fz_encode_character(ctx, font, unicode); fz_catch(ctx) rethrow(J); js_pushnumber(J, glyph); } static void ffi_Font_advanceGlyph(js_State *J) { fz_context *ctx = js_getcontext(J); fz_font *font = js_touserdata(J, 0, "fz_font"); int glyph = js_tonumber(J, 1); int wmode = js_isdefined(J, 2) ? js_toboolean(J, 2) : 0; float advance = 0; fz_try(ctx) advance = fz_advance_glyph(ctx, font, glyph, wmode); fz_catch(ctx) rethrow(J); js_pushnumber(J, advance); } static void ffi_new_Text(js_State *J) { fz_context *ctx = js_getcontext(J); fz_text *text = NULL; fz_try(ctx) text = fz_new_text(ctx); fz_catch(ctx) rethrow(J); js_getregistry(J, "fz_text"); js_newuserdata(J, "fz_text", text, ffi_gc_fz_text); } static void ffi_Text_walk(js_State *J) { fz_text *text = js_touserdata(J, 0, "fz_text"); fz_text_span *span; fz_matrix trm; int i; js_getproperty(J, 1, "showGlyph"); for (span = text->head; span; span = span->next) { ffi_pushfont(J, span->font); trm = span->trm; for (i = 0; i < span->len; ++i) { trm.e = span->items[i].x; trm.f = span->items[i].y; js_copy(J, -2); /* showGlyph function */ js_copy(J, 1); /* object for this binding */ js_copy(J, -3); /* font */ ffi_pushmatrix(J, trm); js_pushnumber(J, span->items[i].gid); js_pushnumber(J, span->items[i].ucs); js_pushnumber(J, span->wmode); js_pushnumber(J, span->bidi_level); js_call(J, 6); js_pop(J, 1); } js_pop(J, 1); /* pop font object */ } js_pop(J, 1); /* pop showGlyph function */ } static void ffi_Text_showGlyph(js_State *J) { fz_context *ctx = js_getcontext(J); fz_text *text = js_touserdata(J, 0, "fz_text"); fz_font *font = js_touserdata(J, 1, "fz_font"); fz_matrix trm = ffi_tomatrix(J, 2); int glyph = js_tointeger(J, 3); int unicode = js_tointeger(J, 4); int wmode = js_isdefined(J, 5) ? js_toboolean(J, 5) : 0; fz_try(ctx) fz_show_glyph(ctx, text, font, trm, glyph, unicode, wmode, 0, FZ_BIDI_NEUTRAL, FZ_LANG_UNSET); fz_catch(ctx) rethrow(J); } static void ffi_Text_showString(js_State *J) { fz_context *ctx = js_getcontext(J); fz_text *text = js_touserdata(J, 0, "fz_text"); fz_font *font = js_touserdata(J, 1, "fz_font"); fz_matrix trm = ffi_tomatrix(J, 2); const char *s = js_tostring(J, 3); int wmode = js_isdefined(J, 4) ? js_toboolean(J, 4) : 0; fz_try(ctx) trm = fz_show_string(ctx, text, font, trm, s, wmode, 0, FZ_BIDI_NEUTRAL, FZ_LANG_UNSET); fz_catch(ctx) rethrow(J); /* update matrix with new pen position */ js_pushnumber(J, trm.e); js_setindex(J, 2, 4); js_pushnumber(J, trm.f); js_setindex(J, 2, 5); } static void ffi_new_Path(js_State *J) { fz_context *ctx = js_getcontext(J); fz_path *path = NULL; fz_try(ctx) path = fz_new_path(ctx); fz_catch(ctx) rethrow(J); js_getregistry(J, "fz_path"); js_newuserdata(J, "fz_path", path, ffi_gc_fz_path); } static void ffi_Path_walk_moveTo(fz_context *ctx, void *arg, float x, float y) { js_State *J = arg; if (js_try(J)) rethrow_as_fz(J); if (js_hasproperty(J, 1, "moveTo")) { js_copy(J, 1); js_pushnumber(J, x); js_pushnumber(J, y); js_call(J, 2); js_pop(J, 1); } js_endtry(J); } static void ffi_Path_walk_lineTo(fz_context *ctx, void *arg, float x, float y) { js_State *J = arg; if (js_try(J)) rethrow_as_fz(J); if (js_hasproperty(J, 1, "lineTo")) { js_copy(J, 1); js_pushnumber(J, x); js_pushnumber(J, y); js_call(J, 2); js_pop(J, 1); } js_endtry(J); } static void ffi_Path_walk_curveTo(fz_context *ctx, void *arg, float x1, float y1, float x2, float y2, float x3, float y3) { js_State *J = arg; if (js_try(J)) rethrow_as_fz(J); if (js_hasproperty(J, 1, "curveTo")) { js_copy(J, 1); js_pushnumber(J, x1); js_pushnumber(J, y1); js_pushnumber(J, x2); js_pushnumber(J, y2); js_pushnumber(J, x3); js_pushnumber(J, y3); js_call(J, 6); js_pop(J, 1); } js_endtry(J); } static void ffi_Path_walk_closePath(fz_context *ctx, void *arg) { js_State *J = arg; if (js_try(J)) rethrow_as_fz(J); if (js_hasproperty(J, 1, "closePath")) { js_copy(J, 1); js_call(J, 0); js_pop(J, 1); } js_endtry(J); } static void ffi_Path_walk(js_State *J) { fz_context *ctx = js_getcontext(J); fz_path *path = js_touserdata(J, 0, "fz_path"); fz_path_walker walker = { ffi_Path_walk_moveTo, ffi_Path_walk_lineTo, ffi_Path_walk_curveTo, ffi_Path_walk_closePath, }; fz_try(ctx) fz_walk_path(ctx, path, &walker, J); fz_catch(ctx) rethrow(J); } static void ffi_Path_moveTo(js_State *J) { fz_context *ctx = js_getcontext(J); fz_path *path = js_touserdata(J, 0, "fz_path"); float x = js_tonumber(J, 1); float y = js_tonumber(J, 2); fz_try(ctx) fz_moveto(ctx, path, x, y); fz_catch(ctx) rethrow(J); } static void ffi_Path_lineTo(js_State *J) { fz_context *ctx = js_getcontext(J); fz_path *path = js_touserdata(J, 0, "fz_path"); float x = js_tonumber(J, 1); float y = js_tonumber(J, 2); fz_try(ctx) fz_lineto(ctx, path, x, y); fz_catch(ctx) rethrow(J); } static void ffi_Path_curveTo(js_State *J) { fz_context *ctx = js_getcontext(J); fz_path *path = js_touserdata(J, 0, "fz_path"); float x1 = js_tonumber(J, 1); float y1 = js_tonumber(J, 2); float x2 = js_tonumber(J, 3); float y2 = js_tonumber(J, 4); float x3 = js_tonumber(J, 5); float y3 = js_tonumber(J, 6); fz_try(ctx) fz_curveto(ctx, path, x1, y1, x2, y2, x3, y3); fz_catch(ctx) rethrow(J); } static void ffi_Path_curveToV(js_State *J) { fz_context *ctx = js_getcontext(J); fz_path *path = js_touserdata(J, 0, "fz_path"); float cx = js_tonumber(J, 1); float cy = js_tonumber(J, 2); float ex = js_tonumber(J, 3); float ey = js_tonumber(J, 4); fz_try(ctx) fz_curvetov(ctx, path, cx, cy, ex, ey); fz_catch(ctx) rethrow(J); } static void ffi_Path_curveToY(js_State *J) { fz_context *ctx = js_getcontext(J); fz_path *path = js_touserdata(J, 0, "fz_path"); float cx = js_tonumber(J, 1); float cy = js_tonumber(J, 2); float ex = js_tonumber(J, 3); float ey = js_tonumber(J, 4); fz_try(ctx) fz_curvetoy(ctx, path, cx, cy, ex, ey); fz_catch(ctx) rethrow(J); } static void ffi_Path_closePath(js_State *J) { fz_context *ctx = js_getcontext(J); fz_path *path = js_touserdata(J, 0, "fz_path"); fz_try(ctx) fz_closepath(ctx, path); fz_catch(ctx) rethrow(J); } static void ffi_Path_rect(js_State *J) { fz_context *ctx = js_getcontext(J); fz_path *path = js_touserdata(J, 0, "fz_path"); float x1 = js_tonumber(J, 1); float y1 = js_tonumber(J, 2); float x2 = js_tonumber(J, 3); float y2 = js_tonumber(J, 4); fz_try(ctx) fz_rectto(ctx, path, x1, y1, x2, y2); fz_catch(ctx) rethrow(J); } static void ffi_Path_bound(js_State *J) { fz_context *ctx = js_getcontext(J); fz_path *path = js_touserdata(J, 0, "fz_path"); fz_stroke_state stroke = ffi_tostroke(J, 1); fz_matrix ctm = ffi_tomatrix(J, 2); fz_rect bounds; fz_try(ctx) bounds = fz_bound_path(ctx, path, &stroke, ctm); fz_catch(ctx) rethrow(J); ffi_pushrect(J, bounds); } static void ffi_Path_transform(js_State *J) { fz_context *ctx = js_getcontext(J); fz_path *path = js_touserdata(J, 0, "fz_path"); fz_matrix ctm = ffi_tomatrix(J, 1); fz_try(ctx) fz_transform_path(ctx, path, ctm); fz_catch(ctx) rethrow(J); } static void ffi_new_DisplayList(js_State *J) { fz_context *ctx = js_getcontext(J); fz_rect mediabox = js_iscoercible(J, 1) ? ffi_torect(J, 1) : fz_empty_rect; fz_display_list *list = NULL; fz_try(ctx) list = fz_new_display_list(ctx, mediabox); fz_catch(ctx) rethrow(J); js_getregistry(J, "fz_display_list"); js_newuserdata(J, "fz_display_list", list, ffi_gc_fz_display_list); } static void ffi_DisplayList_run(js_State *J) { fz_context *ctx = js_getcontext(J); fz_display_list *list = js_touserdata(J, 0, "fz_display_list"); fz_device *device = NULL; fz_matrix ctm = ffi_tomatrix(J, 2); if (js_isuserdata(J, 1, "fz_device")) { device = js_touserdata(J, 1, "fz_device"); fz_try(ctx) fz_run_display_list(ctx, list, device, ctm, fz_infinite_rect, NULL); fz_catch(ctx) rethrow(J); } else { device = new_js_device(ctx, J); js_copy(J, 1); fz_try(ctx) { fz_run_display_list(ctx, list, device, ctm, fz_infinite_rect, NULL); fz_close_device(ctx, device); } fz_always(ctx) fz_drop_device(ctx, device); fz_catch(ctx) rethrow(J); } } static void ffi_DisplayList_toPixmap(js_State *J) { fz_context *ctx = js_getcontext(J); fz_display_list *list = js_touserdata(J, 0, "fz_display_list"); fz_matrix ctm = ffi_tomatrix(J, 1); fz_colorspace *colorspace = js_touserdata(J, 2, "fz_colorspace"); int alpha = js_isdefined(J, 3) ? js_toboolean(J, 3) : 0; fz_pixmap *pixmap = NULL; fz_try(ctx) pixmap = fz_new_pixmap_from_display_list(ctx, list, ctm, colorspace, alpha); fz_catch(ctx) rethrow(J); js_getregistry(J, "fz_pixmap"); js_newuserdata(J, "fz_pixmap", pixmap, ffi_gc_fz_pixmap); } static void ffi_DisplayList_toStructuredText(js_State *J) { fz_context *ctx = js_getcontext(J); fz_display_list *list = js_touserdata(J, 0, "fz_display_list"); const char *options = js_iscoercible(J, 1) ? js_tostring(J, 1) : NULL; fz_stext_options so; fz_stext_page *text = NULL; fz_try(ctx) { fz_parse_stext_options(ctx, &so, options); text = fz_new_stext_page_from_display_list(ctx, list, &so); } fz_catch(ctx) rethrow(J); js_getregistry(J, "fz_stext_page"); js_newuserdata(J, "fz_stext_page", text, ffi_gc_fz_stext_page); } static void ffi_DisplayList_search(js_State *J) { fz_context *ctx = js_getcontext(J); fz_display_list *list = js_touserdata(J, 0, "fz_display_list"); const char *needle = js_tostring(J, 1); fz_quad hits[256]; int i, n = 0; fz_try(ctx) n = fz_search_display_list(ctx, list, needle, hits, nelem(hits)); fz_catch(ctx) rethrow(J); js_newarray(J); for (i = 0; i < n; ++i) { ffi_pushquad(J, hits[i]); js_setindex(J, -2, i); } } static void ffi_StructuredText_search(js_State *J) { fz_context *ctx = js_getcontext(J); fz_stext_page *text = js_touserdata(J, 0, "fz_stext_page"); const char *needle = js_tostring(J, 1); fz_quad hits[256]; int i, n = 0; fz_try(ctx) n = fz_search_stext_page(ctx, text, needle, hits, nelem(hits)); fz_catch(ctx) rethrow(J); js_newarray(J); for (i = 0; i < n; ++i) { ffi_pushquad(J, hits[i]); js_setindex(J, -2, i); } } static void ffi_StructuredText_highlight(js_State *J) { fz_context *ctx = js_getcontext(J); fz_stext_page *text = js_touserdata(J, 0, "fz_stext_page"); fz_point a = ffi_topoint(J, 1); fz_point b = ffi_topoint(J, 2); fz_quad hits[256]; int i, n = 0; fz_try(ctx) n = fz_highlight_selection(ctx, text, a, b, hits, nelem(hits)); fz_catch(ctx) rethrow(J); js_newarray(J); for (i = 0; i < n; ++i) { ffi_pushquad(J, hits[i]); js_setindex(J, -2, i); } } static void ffi_StructuredText_copy(js_State *J) { fz_context *ctx = js_getcontext(J); fz_stext_page *text = js_touserdata(J, 0, "fz_stext_page"); fz_point a = ffi_topoint(J, 1); fz_point b = ffi_topoint(J, 2); char *s = NULL; fz_try(ctx) s = fz_copy_selection(ctx, text, a, b, 0); fz_catch(ctx) rethrow(J); js_pushstring(J, s); fz_try(ctx) fz_free(ctx, s); fz_catch(ctx) rethrow(J); } static void ffi_new_DisplayListDevice(js_State *J) { fz_context *ctx = js_getcontext(J); fz_display_list *list = js_touserdata(J, 0, "fz_display_list"); fz_device *device = NULL; fz_try(ctx) device = fz_new_list_device(ctx, list); fz_catch(ctx) rethrow(J); js_getregistry(J, "fz_device"); js_newuserdata(J, "fz_device", device, ffi_gc_fz_device); } static void ffi_new_DrawDevice(js_State *J) { fz_context *ctx = js_getcontext(J); fz_matrix transform = ffi_tomatrix(J, 1); fz_pixmap *pixmap = js_touserdata(J, 2, "fz_pixmap"); fz_device *device = NULL; fz_try(ctx) device = fz_new_draw_device(ctx, transform, pixmap); fz_catch(ctx) rethrow(J); js_getregistry(J, "fz_device"); js_newuserdata(J, "fz_device", device, ffi_gc_fz_device); } static void ffi_new_DocumentWriter(js_State *J) { fz_context *ctx = js_getcontext(J); const char *filename = js_tostring(J, 1); const char *format = js_iscoercible(J, 2) ? js_tostring(J, 2) : NULL; const char *options = js_iscoercible(J, 3) ? js_tostring(J, 3) : NULL; fz_document_writer *wri = NULL; fz_try(ctx) wri = fz_new_document_writer(ctx, filename, format, options); fz_catch(ctx) rethrow(J); js_getregistry(J, "fz_document_writer"); js_newuserdata(J, "fz_document_writer", wri, ffi_gc_fz_document_writer); } static void ffi_DocumentWriter_beginPage(js_State *J) { fz_context *ctx = js_getcontext(J); fz_document_writer *wri = js_touserdata(J, 0, "fz_document_writer"); fz_rect mediabox = ffi_torect(J, 1); fz_device *device = NULL; fz_try(ctx) device = fz_begin_page(ctx, wri, mediabox); fz_catch(ctx) rethrow(J); js_getregistry(J, "fz_device"); js_newuserdata(J, "fz_device", fz_keep_device(ctx, device), ffi_gc_fz_device); } static void ffi_DocumentWriter_endPage(js_State *J) { fz_context *ctx = js_getcontext(J); fz_document_writer *wri = js_touserdata(J, 0, "fz_document_writer"); fz_try(ctx) fz_end_page(ctx, wri); fz_catch(ctx) rethrow(J); } static void ffi_DocumentWriter_close(js_State *J) { fz_context *ctx = js_getcontext(J); fz_document_writer *wri = js_touserdata(J, 0, "fz_document_writer"); fz_try(ctx) fz_close_document_writer(ctx, wri); fz_catch(ctx) rethrow(J); } /* PDF specifics */ #if FZ_ENABLE_PDF static pdf_obj *ffi_toobj(js_State *J, pdf_document *pdf, int idx) { fz_context *ctx = js_getcontext(J); pdf_obj *obj = NULL; /* make sure index is absolute */ if (idx < 0) idx += js_gettop(J); if (js_isuserdata(J, idx, "pdf_obj")) return pdf_keep_obj(ctx, js_touserdata(J, idx, "pdf_obj")); if (js_isnumber(J, idx)) { float f = js_tonumber(J, idx); fz_try(ctx) if (f == (int)f) obj = pdf_new_int(ctx, f); else obj = pdf_new_real(ctx, f); fz_catch(ctx) rethrow(J); return obj; } if (js_isstring(J, idx)) { const char *s = js_tostring(J, idx); fz_try(ctx) if (s[0] == '(' && s[1] != 0) obj = pdf_new_string(ctx, s+1, strlen(s)-2); else obj = pdf_new_name(ctx, s); fz_catch(ctx) rethrow(J); return obj; } if (js_isboolean(J, idx)) { return js_toboolean(J, idx) ? PDF_TRUE : PDF_FALSE; } if (js_isnull(J, idx)) { return PDF_NULL; } if (js_isarray(J, idx)) { pdf_obj *val; int i, n = js_getlength(J, idx); fz_try(ctx) obj = pdf_new_array(ctx, pdf, n); fz_catch(ctx) rethrow(J); for (i = 0; i < n; ++i) { js_getindex(J, idx, i); val = ffi_toobj(J, pdf, -1); fz_try(ctx) pdf_array_push(ctx, obj, val); fz_always(ctx) pdf_drop_obj(ctx, val); fz_catch(ctx) rethrow(J); js_pop(J, 1); } return obj; } if (js_isobject(J, idx)) { const char *key; pdf_obj *val; fz_try(ctx) obj = pdf_new_dict(ctx, pdf, 0); fz_catch(ctx) rethrow(J); js_pushiterator(J, idx, 1); while ((key = js_nextiterator(J, -1))) { js_getproperty(J, idx, key); val = ffi_toobj(J, pdf, -1); fz_try(ctx) pdf_dict_puts(ctx, obj, key, val); fz_always(ctx) pdf_drop_obj(ctx, val); fz_catch(ctx) rethrow(J); js_pop(J, 1); } js_pop(J, 1); return obj; } js_error(J, "cannot convert JS type to PDF"); } static void ffi_pushobj(js_State *J, pdf_obj *obj); static int ffi_pdf_obj_has(js_State *J, void *obj, const char *key) { fz_context *ctx = js_getcontext(J); pdf_obj *val = NULL; int idx, len = 0; if (!strcmp(key, "length")) { fz_try(ctx) len = pdf_array_len(ctx, obj); fz_catch(ctx) rethrow(J); js_pushnumber(J, len); return 1; } if (is_number(key, &idx)) { fz_try(ctx) val = pdf_array_get(ctx, obj, idx); fz_catch(ctx) rethrow(J); } else { fz_try(ctx) val = pdf_dict_gets(ctx, obj, key); fz_catch(ctx) rethrow(J); } if (val) { ffi_pushobj(J, pdf_keep_obj(ctx, val)); return 1; } return 0; } static int ffi_pdf_obj_put(js_State *J, void *obj, const char *key) { fz_context *ctx = js_getcontext(J); pdf_document *pdf = NULL; pdf_obj *val; int idx; fz_try(ctx) pdf = pdf_get_bound_document(ctx, obj); fz_catch(ctx) rethrow(J); val = ffi_toobj(J, pdf, -1); if (is_number(key, &idx)) { fz_try(ctx) pdf_array_put(ctx, obj, idx, val); fz_always(ctx) pdf_drop_obj(ctx, val); fz_catch(ctx) rethrow(J); } else { fz_try(ctx) pdf_dict_puts(ctx, obj, key, val); fz_always(ctx) pdf_drop_obj(ctx, val); fz_catch(ctx) rethrow(J); } return 1; } static int ffi_pdf_obj_delete(js_State *J, void *obj, const char *key) { fz_context *ctx = js_getcontext(J); int idx; if (is_number(key, &idx)) { fz_try(ctx) pdf_array_delete(ctx, obj, idx); fz_catch(ctx) rethrow(J); } else { fz_try(ctx) pdf_dict_dels(ctx, obj, key); fz_catch(ctx) rethrow(J); } return 1; } static void ffi_pushobj(js_State *J, pdf_obj *obj) { if (obj) { js_getregistry(J, "pdf_obj"); js_newuserdatax(J, "pdf_obj", obj, ffi_pdf_obj_has, ffi_pdf_obj_put, ffi_pdf_obj_delete, ffi_gc_pdf_obj); } else { js_pushnull(J); } } static void ffi_new_PDFDocument(js_State *J) { fz_context *ctx = js_getcontext(J); const char *filename = js_iscoercible(J, 1) ? js_tostring(J, 1) : NULL; pdf_document *pdf = NULL; fz_try(ctx) if (filename) pdf = pdf_open_document(ctx, filename); else pdf = pdf_create_document(ctx); fz_catch(ctx) rethrow(J); js_getregistry(J, "pdf_document"); js_newuserdata(J, "pdf_document", pdf, ffi_gc_pdf_document); } static void ffi_PDFDocument_getTrailer(js_State *J) { fz_context *ctx = js_getcontext(J); pdf_document *pdf = js_touserdata(J, 0, "pdf_document"); pdf_obj *trailer = NULL; fz_try(ctx) trailer = pdf_trailer(ctx, pdf); fz_catch(ctx) rethrow(J); ffi_pushobj(J, pdf_keep_obj(ctx, trailer)); } static void ffi_PDFDocument_countObjects(js_State *J) { fz_context *ctx = js_getcontext(J); pdf_document *pdf = js_touserdata(J, 0, "pdf_document"); int count = 0; fz_try(ctx) count = pdf_xref_len(ctx, pdf); fz_catch(ctx) rethrow(J); js_pushnumber(J, count); } static void ffi_PDFDocument_createObject(js_State *J) { fz_context *ctx = js_getcontext(J); pdf_document *pdf = js_touserdata(J, 0, "pdf_document"); pdf_obj *ind = NULL; fz_try(ctx) ind = pdf_new_indirect(ctx, pdf, pdf_create_object(ctx, pdf), 0); fz_catch(ctx) rethrow(J); ffi_pushobj(J, ind); } static void ffi_PDFDocument_deleteObject(js_State *J) { fz_context *ctx = js_getcontext(J); pdf_document *pdf = js_touserdata(J, 0, "pdf_document"); pdf_obj *ind = js_isuserdata(J, 1, "pdf_obj") ? js_touserdata(J, 1, "pdf_obj") : NULL; int num = ind ? pdf_to_num(ctx, ind) : js_tonumber(J, 1); fz_try(ctx) pdf_delete_object(ctx, pdf, num); fz_catch(ctx) rethrow(J); } static void ffi_PDFDocument_addObject(js_State *J) { fz_context *ctx = js_getcontext(J); pdf_document *pdf = js_touserdata(J, 0, "pdf_document"); pdf_obj *obj = ffi_toobj(J, pdf, 1); pdf_obj *ind = NULL; fz_try(ctx) ind = pdf_add_object_drop(ctx, pdf, obj); fz_catch(ctx) rethrow(J); ffi_pushobj(J, ind); } static void ffi_PDFDocument_addStream_imp(js_State *J, int compressed) { fz_context *ctx = js_getcontext(J); pdf_document *pdf = js_touserdata(J, 0, "pdf_document"); fz_buffer *buf = ffi_tobuffer(J, 1); /* FIXME: leak if ffi_toobj throws */ pdf_obj *obj = js_iscoercible(J, 2) ? ffi_toobj(J, pdf, 2) : NULL; pdf_obj *ind = NULL; fz_try(ctx) ind = pdf_add_stream(ctx, pdf, buf, obj, compressed); fz_always(ctx) { fz_drop_buffer(ctx, buf); pdf_drop_obj(ctx, obj); } fz_catch(ctx) rethrow(J); ffi_pushobj(J, ind); } static void ffi_PDFDocument_addStream(js_State *J) { ffi_PDFDocument_addStream_imp(J, 0); } static void ffi_PDFDocument_addRawStream(js_State *J) { ffi_PDFDocument_addStream_imp(J, 1); } static void ffi_PDFDocument_addImage(js_State *J) { fz_context *ctx = js_getcontext(J); pdf_document *pdf = js_touserdata(J, 0, "pdf_document"); fz_image *image = js_touserdata(J, 1, "fz_image"); pdf_obj *ind = NULL; fz_try(ctx) ind = pdf_add_image(ctx, pdf, image, 0); fz_catch(ctx) rethrow(J); ffi_pushobj(J, ind); } static void ffi_PDFDocument_addSimpleFont(js_State *J) { fz_context *ctx = js_getcontext(J); pdf_document *pdf = js_touserdata(J, 0, "pdf_document"); fz_font *font = js_touserdata(J, 1, "fz_font"); const char *encname = js_tostring(J, 2); pdf_obj *ind = NULL; int enc = PDF_SIMPLE_ENCODING_LATIN; if (!strcmp(encname, "Latin") || !strcmp(encname, "Latn")) enc = PDF_SIMPLE_ENCODING_LATIN; else if (!strcmp(encname, "Greek") || !strcmp(encname, "Grek")) enc = PDF_SIMPLE_ENCODING_GREEK; else if (!strcmp(encname, "Cyrillic") || !strcmp(encname, "Cyrl")) enc = PDF_SIMPLE_ENCODING_CYRILLIC; fz_try(ctx) ind = pdf_add_simple_font(ctx, pdf, font, enc); fz_catch(ctx) rethrow(J); ffi_pushobj(J, ind); } static void ffi_PDFDocument_addCJKFont(js_State *J) { fz_context *ctx = js_getcontext(J); pdf_document *pdf = js_touserdata(J, 0, "pdf_document"); fz_font *font = js_touserdata(J, 1, "fz_font"); const char *lang = js_tostring(J, 2); const char *wm = js_tostring(J, 3); const char *ss = js_tostring(J, 4); int ordering; int wmode = 0; int serif = 1; pdf_obj *ind = NULL; ordering = fz_lookup_cjk_ordering_by_language(lang); if (!strcmp(wm, "V")) wmode = 1; if (!strcmp(ss, "sans") || !strcmp(ss, "sans-serif")) serif = 0; fz_try(ctx) ind = pdf_add_cjk_font(ctx, pdf, font, ordering, wmode, serif); fz_catch(ctx) rethrow(J); ffi_pushobj(J, ind); } static void ffi_PDFDocument_addFont(js_State *J) { fz_context *ctx = js_getcontext(J); pdf_document *pdf = js_touserdata(J, 0, "pdf_document"); fz_font *font = js_touserdata(J, 1, "fz_font"); pdf_obj *ind = NULL; fz_try(ctx) ind = pdf_add_cid_font(ctx, pdf, font); fz_catch(ctx) rethrow(J); ffi_pushobj(J, ind); } static void ffi_PDFDocument_addPage(js_State *J) { fz_context *ctx = js_getcontext(J); pdf_document *pdf = js_touserdata(J, 0, "pdf_document"); fz_rect mediabox = ffi_torect(J, 1); int rotate = js_tonumber(J, 2); pdf_obj *resources = ffi_toobj(J, pdf, 3); /* FIXME: leak if ffi_tobuffer throws */ fz_buffer *contents = ffi_tobuffer(J, 4); pdf_obj *ind = NULL; fz_try(ctx) ind = pdf_add_page(ctx, pdf, mediabox, rotate, resources, contents); fz_always(ctx) { fz_drop_buffer(ctx, contents); pdf_drop_obj(ctx, resources); } fz_catch(ctx) rethrow(J); ffi_pushobj(J, ind); } static void ffi_PDFDocument_insertPage(js_State *J) { fz_context *ctx = js_getcontext(J); pdf_document *pdf = js_touserdata(J, 0, "pdf_document"); int at = js_tonumber(J, 1); pdf_obj *obj = ffi_toobj(J, pdf, 2); fz_try(ctx) pdf_insert_page(ctx, pdf, at, obj); fz_always(ctx) pdf_drop_obj(ctx, obj); fz_catch(ctx) rethrow(J); } static void ffi_PDFDocument_deletePage(js_State *J) { fz_context *ctx = js_getcontext(J); pdf_document *pdf = js_touserdata(J, 0, "pdf_document"); int at = js_tonumber(J, 1); fz_try(ctx) pdf_delete_page(ctx, pdf, at); fz_catch(ctx) rethrow(J); } static void ffi_PDFDocument_countPages(js_State *J) { fz_context *ctx = js_getcontext(J); pdf_document *pdf = js_touserdata(J, 0, "pdf_document"); int count = 0; fz_try(ctx) count = pdf_count_pages(ctx, pdf); fz_catch(ctx) rethrow(J); js_pushnumber(J, count); } static void ffi_PDFDocument_findPage(js_State *J) { fz_context *ctx = js_getcontext(J); pdf_document *pdf = js_touserdata(J, 0, "pdf_document"); int at = js_tonumber(J, 1); pdf_obj *obj = NULL; fz_try(ctx) obj = pdf_lookup_page_obj(ctx, pdf, at); fz_catch(ctx) rethrow(J); ffi_pushobj(J, pdf_keep_obj(ctx, obj)); } static void ffi_PDFDocument_save(js_State *J) { fz_context *ctx = js_getcontext(J); pdf_document *pdf = js_touserdata(J, 0, "pdf_document"); const char *filename = js_tostring(J, 1); const char *options = js_iscoercible(J, 2) ? js_tostring(J, 2) : NULL; pdf_write_options pwo; fz_try(ctx) { pdf_parse_write_options(ctx, &pwo, options); pdf_save_document(ctx, pdf, filename, &pwo); } fz_catch(ctx) rethrow(J); } static void ffi_PDFDocument_newNull(js_State *J) { ffi_pushobj(J, PDF_NULL); } static void ffi_PDFDocument_newBoolean(js_State *J) { int val = js_toboolean(J, 1); ffi_pushobj(J, val ? PDF_TRUE : PDF_FALSE); } static void ffi_PDFDocument_newInteger(js_State *J) { fz_context *ctx = js_getcontext(J); int val = js_tointeger(J, 1); pdf_obj *obj = NULL; fz_try(ctx) obj = pdf_new_int(ctx, val); fz_catch(ctx) rethrow(J); ffi_pushobj(J, obj); } static void ffi_PDFDocument_newReal(js_State *J) { fz_context *ctx = js_getcontext(J); float val = js_tonumber(J, 1); pdf_obj *obj = NULL; fz_try(ctx) obj = pdf_new_real(ctx, val); fz_catch(ctx) rethrow(J); ffi_pushobj(J, obj); } static void ffi_PDFDocument_newString(js_State *J) { fz_context *ctx = js_getcontext(J); const char *val = js_tostring(J, 1); pdf_obj *obj = NULL; fz_try(ctx) obj = pdf_new_text_string(ctx, val); fz_catch(ctx) rethrow(J); ffi_pushobj(J, obj); } static void ffi_PDFDocument_newByteString(js_State *J) { fz_context *ctx = js_getcontext(J); int n, i; char *buf; pdf_obj *obj = NULL; n = js_getlength(J, 1); fz_try(ctx) buf = fz_malloc(ctx, n); fz_catch(ctx) rethrow(J); if (js_try(J)) { fz_free(ctx, buf); js_throw(J); } for (i = 0; i < n; ++i) { js_getindex(J, 1, i); buf[i] = js_tonumber(J, -1); js_pop(J, 1); } js_endtry(J); fz_try(ctx) obj = pdf_new_string(ctx, buf, n); fz_always(ctx) fz_free(ctx, buf); fz_catch(ctx) rethrow(J); ffi_pushobj(J, obj); } static void ffi_PDFDocument_newName(js_State *J) { fz_context *ctx = js_getcontext(J); const char *val = js_tostring(J, 1); pdf_obj *obj = NULL; fz_try(ctx) obj = pdf_new_name(ctx, val); fz_catch(ctx) rethrow(J); ffi_pushobj(J, obj); } static void ffi_PDFDocument_newIndirect(js_State *J) { fz_context *ctx = js_getcontext(J); pdf_document *pdf = js_touserdata(J, 0, "pdf_document"); int num = js_tointeger(J, 1); int gen = js_tointeger(J, 2); pdf_obj *obj = NULL; fz_try(ctx) obj = pdf_new_indirect(ctx, pdf, num, gen); fz_catch(ctx) rethrow(J); ffi_pushobj(J, obj); } static void ffi_PDFDocument_newArray(js_State *J) { fz_context *ctx = js_getcontext(J); pdf_document *pdf = js_touserdata(J, 0, "pdf_document"); pdf_obj *obj = NULL; fz_try(ctx) obj = pdf_new_array(ctx, pdf, 0); fz_catch(ctx) rethrow(J); ffi_pushobj(J, obj); } static void ffi_PDFDocument_newDictionary(js_State *J) { fz_context *ctx = js_getcontext(J); pdf_document *pdf = js_touserdata(J, 0, "pdf_document"); pdf_obj *obj = NULL; fz_try(ctx) obj = pdf_new_dict(ctx, pdf, 0); fz_catch(ctx) rethrow(J); ffi_pushobj(J, obj); } static void ffi_PDFDocument_newGraftMap(js_State *J) { fz_context *ctx = js_getcontext(J); pdf_document *pdf = js_touserdata(J, 0, "pdf_document"); pdf_graft_map *map = NULL; fz_try(ctx) map = pdf_new_graft_map(ctx, pdf); fz_catch(ctx) rethrow(J); js_getregistry(J, "pdf_graft_map"); js_newuserdata(J, "pdf_graft_map", map, ffi_gc_pdf_graft_map); } static void ffi_PDFDocument_graftObject(js_State *J) { fz_context *ctx = js_getcontext(J); pdf_document *dst = js_touserdata(J, 0, "pdf_document"); pdf_obj *obj = js_touserdata(J, 1, "pdf_obj"); fz_try(ctx) obj = pdf_graft_object(ctx, dst, obj); fz_catch(ctx) rethrow(J); ffi_pushobj(J, obj); } static void ffi_PDFGraftMap_graftObject(js_State *J) { fz_context *ctx = js_getcontext(J); pdf_graft_map *map = js_touserdata(J, 0, "pdf_graft_map"); pdf_obj *obj = js_touserdata(J, 1, "pdf_obj"); fz_try(ctx) obj = pdf_graft_mapped_object(ctx, map, obj); fz_catch(ctx) rethrow(J); ffi_pushobj(J, obj); } static void ffi_PDFObject_get(js_State *J) { pdf_obj *obj = js_touserdata(J, 0, "pdf_obj"); const char *key = js_tostring(J, 1); if (!ffi_pdf_obj_has(J, obj, key)) js_pushundefined(J); } static void ffi_PDFObject_put(js_State *J) { pdf_obj *obj = js_touserdata(J, 0, "pdf_obj"); const char *key = js_tostring(J, 1); js_copy(J, 2); ffi_pdf_obj_put(J, obj, key); } static void ffi_PDFObject_delete(js_State *J) { pdf_obj *obj = js_touserdata(J, 0, "pdf_obj"); const char *key = js_tostring(J, 1); ffi_pdf_obj_delete(J, obj, key); } static void ffi_PDFObject_push(js_State *J) { fz_context *ctx = js_getcontext(J); pdf_obj *obj = js_touserdata(J, 0, "pdf_obj"); pdf_document *pdf = pdf_get_bound_document(ctx, obj); pdf_obj *item = ffi_toobj(J, pdf, 1); fz_try(ctx) pdf_array_push(ctx, obj, item); fz_always(ctx) pdf_drop_obj(ctx, item); fz_catch(ctx) rethrow(J); } static void ffi_PDFObject_resolve(js_State *J) { fz_context *ctx = js_getcontext(J); pdf_obj *obj = js_touserdata(J, 0, "pdf_obj"); pdf_obj *ind = NULL; fz_try(ctx) ind = pdf_resolve_indirect(ctx, obj); fz_catch(ctx) rethrow(J); ffi_pushobj(J, pdf_keep_obj(ctx, ind)); } static void ffi_PDFObject_toString(js_State *J) { fz_context *ctx = js_getcontext(J); pdf_obj *obj = js_touserdata(J, 0, "pdf_obj"); int tight = js_isdefined(J, 1) ? js_toboolean(J, 1) : 1; char *s = NULL; int n; fz_var(s); fz_try(ctx) { n = pdf_sprint_obj(ctx, NULL, 0, obj, tight); s = fz_malloc(ctx, n+1); pdf_sprint_obj(ctx, s, n+1, obj, tight); js_pushstring(J, s); } fz_always(ctx) { fz_free(ctx, s); } fz_catch(ctx) { rethrow(J); } } static void ffi_PDFObject_valueOf(js_State *J) { fz_context *ctx = js_getcontext(J); pdf_obj *obj = js_touserdata(J, 0, "pdf_obj"); if (pdf_is_indirect(ctx, obj)) js_pushstring(J, "R"); else if (pdf_is_null(ctx, obj)) js_pushnull(J); else if (pdf_is_bool(ctx, obj)) js_pushboolean(J, pdf_to_bool(ctx, obj)); else if (pdf_is_int(ctx, obj)) js_pushnumber(J, pdf_to_int(ctx, obj)); else if (pdf_is_real(ctx, obj)) js_pushnumber(J, pdf_to_real(ctx, obj)); else if (pdf_is_string(ctx, obj)) js_pushlstring(J, pdf_to_str_buf(ctx, obj), pdf_to_str_len(ctx, obj)); else if (pdf_is_name(ctx, obj)) js_pushstring(J, pdf_to_name(ctx, obj)); else js_copy(J, 0); } static void ffi_PDFObject_isArray(js_State *J) { fz_context *ctx = js_getcontext(J); pdf_obj *obj = js_touserdata(J, 0, "pdf_obj"); int b = 0; fz_try(ctx) b = pdf_is_array(ctx, obj); fz_catch(ctx) rethrow(J); js_pushboolean(J, b); } static void ffi_PDFObject_isDictionary(js_State *J) { fz_context *ctx = js_getcontext(J); pdf_obj *obj = js_touserdata(J, 0, "pdf_obj"); int b = 0; fz_try(ctx) b = pdf_is_dict(ctx, obj); fz_catch(ctx) rethrow(J); js_pushboolean(J, b); } static void ffi_PDFObject_isIndirect(js_State *J) { fz_context *ctx = js_getcontext(J); pdf_obj *obj = js_touserdata(J, 0, "pdf_obj"); int b = 0; fz_try(ctx) b = pdf_is_indirect(ctx, obj); fz_catch(ctx) rethrow(J); js_pushboolean(J, b); } static void ffi_PDFObject_asIndirect(js_State *J) { fz_context *ctx = js_getcontext(J); pdf_obj *obj = js_touserdata(J, 0, "pdf_obj"); int num = 0; fz_try(ctx) num = pdf_to_num(ctx, obj); fz_catch(ctx) rethrow(J); js_pushnumber(J, num); } static void ffi_PDFObject_isNull(js_State *J) { fz_context *ctx = js_getcontext(J); pdf_obj *obj = js_touserdata(J, 0, "pdf_obj"); int b = 0; fz_try(ctx) b = pdf_is_null(ctx, obj); fz_catch(ctx) rethrow(J); js_pushboolean(J, b); } static void ffi_PDFObject_isBoolean(js_State *J) { fz_context *ctx = js_getcontext(J); pdf_obj *obj = js_touserdata(J, 0, "pdf_obj"); int b = 0; fz_try(ctx) b = pdf_is_bool(ctx, obj); fz_catch(ctx) rethrow(J); js_pushboolean(J, b); } static void ffi_PDFObject_asBoolean(js_State *J) { fz_context *ctx = js_getcontext(J); pdf_obj *obj = js_touserdata(J, 0, "pdf_obj"); int b = 0; fz_try(ctx) b = pdf_to_bool(ctx, obj); fz_catch(ctx) rethrow(J); js_pushboolean(J, b); } static void ffi_PDFObject_isNumber(js_State *J) { fz_context *ctx = js_getcontext(J); pdf_obj *obj = js_touserdata(J, 0, "pdf_obj"); int b = 0; fz_try(ctx) b = pdf_is_number(ctx, obj); fz_catch(ctx) rethrow(J); js_pushboolean(J, b); } static void ffi_PDFObject_asNumber(js_State *J) { fz_context *ctx = js_getcontext(J); pdf_obj *obj = js_touserdata(J, 0, "pdf_obj"); float num = 0; fz_try(ctx) if (pdf_is_int(ctx, obj)) num = pdf_to_int(ctx, obj); else num = pdf_to_real(ctx, obj); fz_catch(ctx) rethrow(J); js_pushnumber(J, num); } static void ffi_PDFObject_isName(js_State *J) { fz_context *ctx = js_getcontext(J); pdf_obj *obj = js_touserdata(J, 0, "pdf_obj"); int b = 0; fz_try(ctx) b = pdf_is_name(ctx, obj); fz_catch(ctx) rethrow(J); js_pushboolean(J, b); } static void ffi_PDFObject_asName(js_State *J) { fz_context *ctx = js_getcontext(J); pdf_obj *obj = js_touserdata(J, 0, "pdf_obj"); const char *name = NULL; fz_try(ctx) name = pdf_to_name(ctx, obj); fz_catch(ctx) rethrow(J); js_pushstring(J, name); } static void ffi_PDFObject_isString(js_State *J) { fz_context *ctx = js_getcontext(J); pdf_obj *obj = js_touserdata(J, 0, "pdf_obj"); int b = 0; fz_try(ctx) b = pdf_is_string(ctx, obj); fz_catch(ctx) rethrow(J); js_pushboolean(J, b); } static void ffi_PDFObject_asString(js_State *J) { fz_context *ctx = js_getcontext(J); pdf_obj *obj = js_touserdata(J, 0, "pdf_obj"); const char *string = NULL; fz_try(ctx) string = pdf_to_text_string(ctx, obj); fz_catch(ctx) rethrow(J); js_pushstring(J, string); js_endtry(J); } static void ffi_PDFObject_asByteString(js_State *J) { fz_context *ctx = js_getcontext(J); pdf_obj *obj = js_touserdata(J, 0, "pdf_obj"); const char *buf; size_t i, len = 0; fz_try(ctx) buf = pdf_to_string(ctx, obj, &len); fz_catch(ctx) rethrow(J); js_newarray(J); for (i = 0; i < len; ++i) { js_pushnumber(J, (unsigned char)buf[i]); js_setindex(J, -2, i); } } static void ffi_PDFObject_isStream(js_State *J) { fz_context *ctx = js_getcontext(J); pdf_obj *obj = js_touserdata(J, 0, "pdf_obj"); int b = 0; fz_try(ctx) b = pdf_is_stream(ctx, obj); fz_catch(ctx) rethrow(J); js_pushboolean(J, b); } static void ffi_PDFObject_readStream(js_State *J) { fz_context *ctx = js_getcontext(J); pdf_obj *obj = js_touserdata(J, 0, "pdf_obj"); fz_buffer *buf = NULL; fz_try(ctx) buf = pdf_load_stream(ctx, obj); fz_catch(ctx) rethrow(J); ffi_pushbuffer(J, buf); } static void ffi_PDFObject_readRawStream(js_State *J) { fz_context *ctx = js_getcontext(J); pdf_obj *obj = js_touserdata(J, 0, "pdf_obj"); fz_buffer *buf = NULL; fz_try(ctx) buf = pdf_load_raw_stream(ctx, obj); fz_catch(ctx) rethrow(J); ffi_pushbuffer(J, buf); } static void ffi_PDFObject_writeObject(js_State *J) { fz_context *ctx = js_getcontext(J); pdf_obj *ref = js_touserdata(J, 0, "pdf_obj"); pdf_document *pdf = pdf_get_bound_document(ctx, ref); pdf_obj *obj = ffi_toobj(J, pdf, 1); fz_try(ctx) pdf_update_object(ctx, pdf, pdf_to_num(ctx, ref), obj); fz_always(ctx) pdf_drop_obj(ctx, obj); fz_catch(ctx) rethrow(J); } static void ffi_PDFObject_writeStream(js_State *J) { fz_context *ctx = js_getcontext(J); pdf_obj *obj = js_touserdata(J, 0, "pdf_obj"); fz_buffer *buf = ffi_tobuffer(J, 1); fz_try(ctx) pdf_update_stream(ctx, pdf_get_bound_document(ctx, obj), obj, buf, 0); fz_always(ctx) fz_drop_buffer(ctx, buf); fz_catch(ctx) rethrow(J); } static void ffi_PDFObject_writeRawStream(js_State *J) { fz_context *ctx = js_getcontext(J); pdf_obj *obj = js_touserdata(J, 0, "pdf_obj"); fz_buffer *buf = ffi_tobuffer(J, 1); fz_try(ctx) pdf_update_stream(ctx, pdf_get_bound_document(ctx, obj), obj, buf, 1); fz_always(ctx) fz_drop_buffer(ctx, buf); fz_catch(ctx) rethrow(J); } static void ffi_PDFObject_forEach(js_State *J) { fz_context *ctx = js_getcontext(J); pdf_obj *obj = js_touserdata(J, 0, "pdf_obj"); pdf_obj *val = NULL; const char *key = NULL; int i, n = 0; fz_try(ctx) obj = pdf_resolve_indirect_chain(ctx, obj); fz_catch(ctx) rethrow(J); if (pdf_is_array(ctx, obj)) { fz_try(ctx) n = pdf_array_len(ctx, obj); fz_catch(ctx) rethrow(J); for (i = 0; i < n; ++i) { fz_try(ctx) val = pdf_array_get(ctx, obj, i); fz_catch(ctx) rethrow(J); js_copy(J, 1); js_pushnull(J); js_pushnumber(J, i); ffi_pushobj(J, pdf_keep_obj(ctx, val)); js_call(J, 2); js_pop(J, 1); } return; } if (pdf_is_dict(ctx, obj)) { fz_try(ctx) n = pdf_dict_len(ctx, obj); fz_catch(ctx) rethrow(J); for (i = 0; i < n; ++i) { fz_try(ctx) { key = pdf_to_name(ctx, pdf_dict_get_key(ctx, obj, i)); val = pdf_dict_get_val(ctx, obj, i); } fz_catch(ctx) rethrow(J); js_copy(J, 1); js_pushnull(J); js_pushstring(J, key); ffi_pushobj(J, pdf_keep_obj(ctx, val)); js_call(J, 2); js_pop(J, 1); } return; } } static void ffi_PDFPage_createAnnotation(js_State *J) { fz_context *ctx = js_getcontext(J); pdf_page *page = js_touserdata(J, 0, "pdf_page"); const char *name = js_tostring(J, 1); pdf_annot *annot = NULL; int subtype; fz_try(ctx) { subtype = pdf_annot_type_from_string(ctx, name); annot = pdf_create_annot(ctx, page, subtype); } fz_catch(ctx) rethrow(J); ffi_pushannot(J, (fz_annot*)annot); } static void ffi_PDFPage_deleteAnnotation(js_State *J) { fz_context *ctx = js_getcontext(J); pdf_page *page = js_touserdata(J, 0, "pdf_page"); pdf_annot *annot = js_touserdata(J, 1, "pdf_annot"); fz_try(ctx) pdf_delete_annot(ctx, page, annot); fz_catch(ctx) rethrow(J); } static void ffi_PDFPage_update(js_State *J) { fz_context *ctx = js_getcontext(J); pdf_page *page = js_touserdata(J, 0, "pdf_page"); int changed = 0; fz_try(ctx) changed = pdf_update_page(ctx, page); fz_catch(ctx) rethrow(J); js_pushboolean(J, changed); } static void ffi_PDFAnnotation_getType(js_State *J) { fz_context *ctx = js_getcontext(J); pdf_annot *annot = js_touserdata(J, 0, "pdf_annot"); int type; const char *subtype = NULL; fz_try(ctx) { type = pdf_annot_type(ctx, annot); subtype = pdf_string_from_annot_type(ctx, type); } fz_catch(ctx) rethrow(J); js_pushstring(J, subtype); } static void ffi_PDFAnnotation_getFlags(js_State *J) { fz_context *ctx = js_getcontext(J); pdf_annot *annot = js_touserdata(J, 0, "pdf_annot"); int flags = 0; fz_try(ctx) flags = pdf_annot_flags(ctx, annot); fz_catch(ctx) rethrow(J); js_pushnumber(J, flags); } static void ffi_PDFAnnotation_setFlags(js_State *J) { fz_context *ctx = js_getcontext(J); pdf_annot *annot = js_touserdata(J, 0, "pdf_annot"); int flags = js_tonumber(J, 1); fz_try(ctx) pdf_set_annot_flags(ctx, annot, flags); fz_catch(ctx) rethrow(J); } static void ffi_PDFAnnotation_getContents(js_State *J) { fz_context *ctx = js_getcontext(J); pdf_annot *annot = js_touserdata(J, 0, "pdf_annot"); const char *contents = NULL; fz_try(ctx) contents = pdf_annot_contents(ctx, annot); fz_catch(ctx) rethrow(J); js_pushstring(J, contents); } static void ffi_PDFAnnotation_setContents(js_State *J) { fz_context *ctx = js_getcontext(J); pdf_annot *annot = js_touserdata(J, 0, "pdf_annot"); const char *contents = js_tostring(J, 1); fz_try(ctx) pdf_set_annot_contents(ctx, annot, contents); fz_catch(ctx) rethrow(J); } static void ffi_PDFAnnotation_getRect(js_State *J) { fz_context *ctx = js_getcontext(J); pdf_annot *annot = js_touserdata(J, 0, "pdf_annot"); fz_rect rect; fz_try(ctx) rect = pdf_annot_rect(ctx, annot); fz_catch(ctx) rethrow(J); ffi_pushrect(J, rect); } static void ffi_PDFAnnotation_setRect(js_State *J) { fz_context *ctx = js_getcontext(J); pdf_annot *annot = js_touserdata(J, 0, "pdf_annot"); fz_rect rect = ffi_torect(J, 1); fz_try(ctx) pdf_set_annot_rect(ctx, annot, rect); fz_catch(ctx) rethrow(J); } static void ffi_PDFAnnotation_getBorder(js_State *J) { fz_context *ctx = js_getcontext(J); pdf_annot *annot = js_touserdata(J, 0, "pdf_annot"); float border = 0; fz_try(ctx) border = pdf_annot_border(ctx, annot); fz_catch(ctx) rethrow(J); js_pushnumber(J, border); } static void ffi_PDFAnnotation_setBorder(js_State *J) { fz_context *ctx = js_getcontext(J); pdf_annot *annot = js_touserdata(J, 0, "pdf_annot"); float border = js_tonumber(J, 1); fz_try(ctx) pdf_set_annot_border(ctx, annot, border); fz_catch(ctx) rethrow(J); } static void ffi_PDFAnnotation_getColor(js_State *J) { fz_context *ctx = js_getcontext(J); pdf_annot *annot = js_touserdata(J, 0, "pdf_annot"); int i, n = 0; float color[4]; fz_try(ctx) pdf_annot_color(ctx, annot, &n, color); fz_catch(ctx) rethrow(J); js_newarray(J); for (i = 0; i < n; ++i) { js_pushnumber(J, color[i]); js_setindex(J, -2, i); } } static void ffi_PDFAnnotation_setColor(js_State *J) { fz_context *ctx = js_getcontext(J); pdf_annot *annot = js_touserdata(J, 0, "pdf_annot"); int i, n = js_getlength(J, 1); float color[4]; for (i = 0; i < n && i < 4; ++i) { js_getindex(J, 1, i); color[i] = js_tonumber(J, -1); js_pop(J, 1); } fz_try(ctx) pdf_set_annot_color(ctx, annot, n, color); fz_catch(ctx) rethrow(J); } static void ffi_PDFAnnotation_getInteriorColor(js_State *J) { fz_context *ctx = js_getcontext(J); pdf_annot *annot = js_touserdata(J, 0, "pdf_annot"); int i, n = 0; float color[4]; fz_try(ctx) pdf_annot_interior_color(ctx, annot, &n, color); fz_catch(ctx) rethrow(J); js_newarray(J); for (i = 0; i < n; ++i) { js_pushnumber(J, color[i]); js_setindex(J, -2, i); } } static void ffi_PDFAnnotation_setInteriorColor(js_State *J) { fz_context *ctx = js_getcontext(J); pdf_annot *annot = js_touserdata(J, 0, "pdf_annot"); int i, n = js_getlength(J, 1); float color[4]; for (i = 0; i < n && i < 4; ++i) { js_getindex(J, 1, i); color[i] = js_tonumber(J, -1); js_pop(J, 1); } fz_try(ctx) pdf_set_annot_interior_color(ctx, annot, n, color); fz_catch(ctx) rethrow(J); } static void ffi_PDFAnnotation_getQuadPoints(js_State *J) { fz_context *ctx = js_getcontext(J); pdf_annot *annot = js_touserdata(J, 0, "pdf_annot"); float qp[8] = { 0 }; int i, k, n = 0; fz_try(ctx) n = pdf_annot_quad_point_count(ctx, annot); fz_catch(ctx) rethrow(J); js_newarray(J); for (i = 0; i < n; ++i) { fz_try(ctx) pdf_annot_quad_point(ctx, annot, i, qp); fz_catch(ctx) rethrow(J); js_newarray(J); for (k = 0; k < 8; ++k) { js_pushnumber(J, qp[k]); js_setindex(J, -2, k); } js_setindex(J, -2, i); } } static void ffi_PDFAnnotation_setQuadPoints(js_State *J) { fz_context *ctx = js_getcontext(J); pdf_annot *annot = js_touserdata(J, 0, "pdf_annot"); float *qp = NULL; int k, i, n; n = js_getlength(J, 1); fz_try(ctx) qp = fz_malloc(ctx, n * 8 * sizeof *qp); fz_catch(ctx) rethrow(J); for (i = 0; i < n; ++i) { js_getindex(J, 1, i); for (k = 0; k < 8; ++k) { js_getindex(J, -1, k); qp[i * 8 + k] = js_tonumber(J, -1); js_pop(J, 1); } js_pop(J, 1); } fz_try(ctx) pdf_set_annot_quad_points(ctx, annot, n, qp); fz_always(ctx) fz_free(ctx, qp); fz_catch(ctx) rethrow(J); } static void ffi_PDFAnnotation_getInkList(js_State *J) { fz_context *ctx = js_getcontext(J); pdf_annot *annot = js_touserdata(J, 0, "pdf_annot"); int i, k, m = 0, n = 0; fz_point pt; js_newarray(J); fz_try(ctx) n = pdf_annot_ink_list_count(ctx, annot); fz_catch(ctx) rethrow(J); for (i = 0; i < n; ++i) { fz_try(ctx) m = pdf_annot_ink_list_stroke_count(ctx, annot, i); fz_catch(ctx) rethrow(J); js_newarray(J); for (k = 0; k < m; ++k) { fz_try(ctx) pt = pdf_annot_ink_list_stroke_vertex(ctx, annot, i, k); fz_catch(ctx) rethrow(J); js_pushnumber(J, pt.x); js_setindex(J, -2, k * 2 + 0); js_pushnumber(J, pt.y); js_setindex(J, -2, k * 2 + 1); } js_setindex(J, -2, i); } } static void ffi_PDFAnnotation_setInkList(js_State *J) { fz_context *ctx = js_getcontext(J); pdf_annot *annot = js_touserdata(J, 0, "pdf_annot"); fz_point *points = NULL; int *counts = NULL; int n, nv, k, i, v; fz_var(counts); fz_var(points); n = js_getlength(J, 1); nv = 0; for (i = 0; i < n; ++i) { js_getindex(J, 1, i); nv += js_getlength(J, -1) / 2; js_pop(J, 1); } fz_try(ctx) { counts = fz_malloc(ctx, n * sizeof(int)); points = fz_malloc(ctx, nv * sizeof(fz_point)); } fz_catch(ctx) { fz_free(ctx, counts); fz_free(ctx, points); rethrow(J); } if (js_try(J)) { fz_free(ctx, counts); fz_free(ctx, points); js_throw(J); } for (i = v = 0; i < n; ++i) { js_getindex(J, 1, i); counts[i] = js_getlength(J, -1) / 2; for (k = 0; k < counts[i]; ++k) { js_getindex(J, -1, k*2); points[v].x = js_tonumber(J, -1); js_pop(J, 1); js_getindex(J, -1, k*2+1); points[v].y = js_tonumber(J, -1); js_pop(J, 1); ++v; } js_pop(J, 1); } js_endtry(J); fz_try(ctx) pdf_set_annot_ink_list(ctx, annot, n, counts, points); fz_always(ctx) { fz_free(ctx, counts); fz_free(ctx, points); } fz_catch(ctx) rethrow(J); } static void ffi_PDFAnnotation_getAuthor(js_State *J) { fz_context *ctx = js_getcontext(J); pdf_annot *annot = js_touserdata(J, 0, "pdf_annot"); const char *author = NULL; fz_try(ctx) author = pdf_annot_author(ctx, annot); fz_catch(ctx) rethrow(J); js_pushstring(J, author); } static void ffi_PDFAnnotation_setAuthor(js_State *J) { fz_context *ctx = js_getcontext(J); pdf_annot *annot = js_touserdata(J, 0, "pdf_annot"); const char *author = js_tostring(J, 1); fz_try(ctx) pdf_set_annot_author(ctx, annot, author); fz_catch(ctx) rethrow(J); } static void ffi_PDFAnnotation_getModificationDate(js_State *J) { fz_context *ctx = js_getcontext(J); pdf_annot *annot = js_touserdata(J, 0, "pdf_annot"); double time; fz_try(ctx) time = pdf_annot_modification_date(ctx, annot); fz_catch(ctx) rethrow(J); js_getglobal(J, "Date"); js_pushnumber(J, time * 1000); js_construct(J, 1); } static void ffi_PDFAnnotation_setModificationDate(js_State *J) { fz_context *ctx = js_getcontext(J); pdf_annot *annot = js_touserdata(J, 0, "pdf_annot"); double time = js_tonumber(J, 1); fz_try(ctx) pdf_set_annot_modification_date(ctx, annot, time / 1000); fz_catch(ctx) rethrow(J); } static void ffi_PDFAnnotation_updateAppearance(js_State *J) { fz_context *ctx = js_getcontext(J); pdf_annot *annot = js_touserdata(J, 0, "pdf_annot"); fz_try(ctx) pdf_update_appearance(ctx, annot); fz_catch(ctx) rethrow(J); } static void ffi_PDFAnnotation_update(js_State *J) { fz_context *ctx = js_getcontext(J); pdf_annot *annot = js_touserdata(J, 0, "pdf_annot"); int changed = 0; fz_try(ctx) changed = pdf_update_annot(ctx, annot); fz_catch(ctx) rethrow(J); js_pushboolean(J, changed); } #endif /* FZ_ENABLE_PDF */ int murun_main(int argc, char **argv) { fz_context *ctx; js_State *J; int i; ctx = fz_new_context(NULL, NULL, FZ_STORE_UNLIMITED); fz_register_document_handlers(ctx); J = js_newstate(alloc, ctx, JS_STRICT); js_setcontext(J, ctx); /* standard command line javascript functions */ js_newcfunction(J, jsB_gc, "gc", 0); js_setglobal(J, "gc"); js_newcfunction(J, jsB_load, "load", 1); js_setglobal(J, "load"); js_newcfunction(J, jsB_print, "print", 1); js_setglobal(J, "print"); js_newcfunction(J, jsB_write, "write", 0); js_setglobal(J, "write"); js_newcfunction(J, jsB_read, "read", 1); js_setglobal(J, "read"); js_newcfunction(J, jsB_readline, "readline", 0); js_setglobal(J, "readline"); js_newcfunction(J, jsB_quit, "quit", 1); js_setglobal(J, "quit"); js_dostring(J, require_js); js_dostring(J, stacktrace_js); /* mupdf module */ js_newobject(J); { jsB_propfun(J, "Buffer.writeByte", ffi_Buffer_writeByte, 1); jsB_propfun(J, "Buffer.writeRune", ffi_Buffer_writeRune, 1); jsB_propfun(J, "Buffer.writeLine", ffi_Buffer_writeLine, 1); jsB_propfun(J, "Buffer.writeBuffer", ffi_Buffer_writeBuffer, 1); jsB_propfun(J, "Buffer.write", ffi_Buffer_write, 1); jsB_propfun(J, "Buffer.save", ffi_Buffer_save, 1); } js_setregistry(J, "fz_buffer"); js_newobject(J); { jsB_propfun(J, "Document.isPDF", ffi_Document_isPDF, 0); jsB_propfun(J, "Document.needsPassword", ffi_Document_needsPassword, 0); jsB_propfun(J, "Document.authenticatePassword", ffi_Document_authenticatePassword, 1); //jsB_propfun(J, "Document.hasPermission", ffi_Document_hasPermission, 1); jsB_propfun(J, "Document.getMetaData", ffi_Document_getMetaData, 1); jsB_propfun(J, "Document.isReflowable", ffi_Document_isReflowable, 0); jsB_propfun(J, "Document.layout", ffi_Document_layout, 3); jsB_propfun(J, "Document.countPages", ffi_Document_countPages, 0); jsB_propfun(J, "Document.loadPage", ffi_Document_loadPage, 1); jsB_propfun(J, "Document.loadOutline", ffi_Document_loadOutline, 0); } js_setregistry(J, "fz_document"); js_newobject(J); { jsB_propfun(J, "Page.isPDF", ffi_Page_isPDF, 0); jsB_propfun(J, "Page.bound", ffi_Page_bound, 0); jsB_propfun(J, "Page.run", ffi_Page_run, 3); jsB_propfun(J, "Page.toPixmap", ffi_Page_toPixmap, 4); jsB_propfun(J, "Page.toDisplayList", ffi_Page_toDisplayList, 1); jsB_propfun(J, "Page.toStructuredText", ffi_Page_toStructuredText, 1); jsB_propfun(J, "Page.search", ffi_Page_search, 0); jsB_propfun(J, "Page.getAnnotations", ffi_Page_getAnnotations, 0); jsB_propfun(J, "Page.getLinks", ffi_Page_getLinks, 0); } js_setregistry(J, "fz_page"); js_newobject(J); { jsB_propfun(J, "Annotation.isPDF", ffi_Annotation_isPDF, 0); jsB_propfun(J, "Annotation.bound", ffi_Annotation_bound, 0); jsB_propfun(J, "Annotation.run", ffi_Annotation_run, 2); jsB_propfun(J, "Annotation.toPixmap", ffi_Annotation_toPixmap, 3); jsB_propfun(J, "Annotation.toDisplayList", ffi_Annotation_toDisplayList, 0); } js_setregistry(J, "fz_annot"); js_newobject(J); { jsB_propfun(J, "Device.close", ffi_Device_close, 0); jsB_propfun(J, "Device.fillPath", ffi_Device_fillPath, 7); jsB_propfun(J, "Device.strokePath", ffi_Device_strokePath, 7); jsB_propfun(J, "Device.clipPath", ffi_Device_clipPath, 3); jsB_propfun(J, "Device.clipStrokePath", ffi_Device_clipStrokePath, 3); jsB_propfun(J, "Device.fillText", ffi_Device_fillText, 6); jsB_propfun(J, "Device.strokeText", ffi_Device_strokeText, 7); jsB_propfun(J, "Device.clipText", ffi_Device_clipText, 2); jsB_propfun(J, "Device.clipStrokeText", ffi_Device_clipStrokeText, 3); jsB_propfun(J, "Device.ignoreText", ffi_Device_ignoreText, 2); jsB_propfun(J, "Device.fillShade", ffi_Device_fillShade, 4); jsB_propfun(J, "Device.fillImage", ffi_Device_fillImage, 4); jsB_propfun(J, "Device.fillImageMask", ffi_Device_fillImageMask, 6); jsB_propfun(J, "Device.clipImageMask", ffi_Device_clipImageMask, 2); jsB_propfun(J, "Device.popClip", ffi_Device_popClip, 0); jsB_propfun(J, "Device.beginMask", ffi_Device_beginMask, 6); jsB_propfun(J, "Device.endMask", ffi_Device_endMask, 0); jsB_propfun(J, "Device.beginGroup", ffi_Device_beginGroup, 5); jsB_propfun(J, "Device.endGroup", ffi_Device_endGroup, 0); jsB_propfun(J, "Device.beginTile", ffi_Device_beginTile, 6); jsB_propfun(J, "Device.endTile", ffi_Device_endTile, 0); jsB_propfun(J, "Device.beginLayer", ffi_Device_beginLayer, 1); jsB_propfun(J, "Device.endLayer", ffi_Device_endLayer, 0); } js_setregistry(J, "fz_device"); js_newobject(J); { jsB_propfun(J, "ColorSpace.getNumberOfComponents", ffi_ColorSpace_getNumberOfComponents, 0); jsB_propfun(J, "ColorSpace.toString", ffi_ColorSpace_toString, 0); } js_setregistry(J, "fz_colorspace"); { js_getregistry(J, "fz_colorspace"); js_newuserdata(J, "fz_colorspace", fz_keep_colorspace(ctx, fz_device_gray(ctx)), ffi_gc_fz_colorspace); js_setregistry(J, "DeviceGray"); js_getregistry(J, "fz_colorspace"); js_newuserdata(J, "fz_colorspace", fz_keep_colorspace(ctx, fz_device_rgb(ctx)), ffi_gc_fz_colorspace); js_setregistry(J, "DeviceRGB"); js_getregistry(J, "fz_colorspace"); js_newuserdata(J, "fz_colorspace", fz_keep_colorspace(ctx, fz_device_bgr(ctx)), ffi_gc_fz_colorspace); js_setregistry(J, "DeviceBGR"); js_getregistry(J, "fz_colorspace"); js_newuserdata(J, "fz_colorspace", fz_keep_colorspace(ctx, fz_device_cmyk(ctx)), ffi_gc_fz_colorspace); js_setregistry(J, "DeviceCMYK"); } js_newobject(J); { jsB_propfun(J, "Shade.bound", ffi_Shade_bound, 1); } js_setregistry(J, "fz_shade"); js_newobject(J); { jsB_propfun(J, "Image.getWidth", ffi_Image_getWidth, 0); jsB_propfun(J, "Image.getHeight", ffi_Image_getHeight, 0); jsB_propfun(J, "Image.getColorSpace", ffi_Image_getColorSpace, 0); jsB_propfun(J, "Image.getXResolution", ffi_Image_getXResolution, 0); jsB_propfun(J, "Image.getYResolution", ffi_Image_getYResolution, 0); jsB_propfun(J, "Image.getNumberOfComponents", ffi_Image_getNumberOfComponents, 0); jsB_propfun(J, "Image.getBitsPerComponent", ffi_Image_getBitsPerComponent, 0); jsB_propfun(J, "Image.getInterpolate", ffi_Image_getInterpolate, 0); jsB_propfun(J, "Image.getImageMask", ffi_Image_getImageMask, 0); jsB_propfun(J, "Image.getMask", ffi_Image_getMask, 0); jsB_propfun(J, "Image.toPixmap", ffi_Image_toPixmap, 2); } js_setregistry(J, "fz_image"); js_newobject(J); { jsB_propfun(J, "Font.getName", ffi_Font_getName, 0); jsB_propfun(J, "Font.encodeCharacter", ffi_Font_encodeCharacter, 1); jsB_propfun(J, "Font.advanceGlyph", ffi_Font_advanceGlyph, 2); } js_setregistry(J, "fz_font"); js_newobject(J); { jsB_propfun(J, "Text.walk", ffi_Text_walk, 1); jsB_propfun(J, "Text.showGlyph", ffi_Text_showGlyph, 5); jsB_propfun(J, "Text.showString", ffi_Text_showString, 4); } js_setregistry(J, "fz_text"); js_newobject(J); { jsB_propfun(J, "Path.walk", ffi_Path_walk, 1); jsB_propfun(J, "Path.moveTo", ffi_Path_moveTo, 2); jsB_propfun(J, "Path.lineTo", ffi_Path_lineTo, 2); jsB_propfun(J, "Path.curveTo", ffi_Path_curveTo, 6); jsB_propfun(J, "Path.curveToV", ffi_Path_curveToV, 4); jsB_propfun(J, "Path.curveToY", ffi_Path_curveToY, 4); jsB_propfun(J, "Path.closePath", ffi_Path_closePath, 0); jsB_propfun(J, "Path.rect", ffi_Path_rect, 4); jsB_propfun(J, "Path.bound", ffi_Path_bound, 2); jsB_propfun(J, "Path.transform", ffi_Path_transform, 1); } js_setregistry(J, "fz_path"); js_newobject(J); { jsB_propfun(J, "DisplayList.run", ffi_DisplayList_run, 2); jsB_propfun(J, "DisplayList.toPixmap", ffi_DisplayList_toPixmap, 3); jsB_propfun(J, "DisplayList.toStructuredText", ffi_DisplayList_toStructuredText, 1); jsB_propfun(J, "DisplayList.search", ffi_DisplayList_search, 1); } js_setregistry(J, "fz_display_list"); js_newobject(J); { jsB_propfun(J, "StructuredText.search", ffi_StructuredText_search, 1); jsB_propfun(J, "StructuredText.highlight", ffi_StructuredText_highlight, 2); jsB_propfun(J, "StructuredText.copy", ffi_StructuredText_copy, 2); } js_setregistry(J, "fz_stext_page"); js_newobject(J); { jsB_propfun(J, "Pixmap.bound", ffi_Pixmap_bound, 0); jsB_propfun(J, "Pixmap.clear", ffi_Pixmap_clear, 1); jsB_propfun(J, "Pixmap.getX", ffi_Pixmap_getX, 0); jsB_propfun(J, "Pixmap.getY", ffi_Pixmap_getY, 0); jsB_propfun(J, "Pixmap.getWidth", ffi_Pixmap_getWidth, 0); jsB_propfun(J, "Pixmap.getHeight", ffi_Pixmap_getHeight, 0); jsB_propfun(J, "Pixmap.getNumberOfComponents", ffi_Pixmap_getNumberOfComponents, 0); jsB_propfun(J, "Pixmap.getAlpha", ffi_Pixmap_getAlpha, 0); jsB_propfun(J, "Pixmap.getStride", ffi_Pixmap_getStride, 0); jsB_propfun(J, "Pixmap.getColorSpace", ffi_Pixmap_getColorSpace, 0); jsB_propfun(J, "Pixmap.getXResolution", ffi_Pixmap_getXResolution, 0); jsB_propfun(J, "Pixmap.getYResolution", ffi_Pixmap_getYResolution, 0); jsB_propfun(J, "Pixmap.getSample", ffi_Pixmap_getSample, 3); // Pixmap.samples() // Pixmap.invert // Pixmap.tint // Pixmap.gamma // Pixmap.scale() jsB_propfun(J, "Pixmap.saveAsPNG", ffi_Pixmap_saveAsPNG, 1); // Pixmap.saveAsPNM, PAM, TGA, PWG, PCL // Pixmap.halftone() -> Bitmap // Pixmap.md5() } js_setregistry(J, "fz_pixmap"); js_newobject(J); { jsB_propfun(J, "DocumentWriter.beginPage", ffi_DocumentWriter_beginPage, 1); jsB_propfun(J, "DocumentWriter.endPage", ffi_DocumentWriter_endPage, 0); jsB_propfun(J, "DocumentWriter.close", ffi_DocumentWriter_close, 0); } js_setregistry(J, "fz_document_writer"); #if FZ_ENABLE_PDF js_getregistry(J, "fz_document"); js_newobjectx(J); { jsB_propfun(J, "PDFDocument.getTrailer", ffi_PDFDocument_getTrailer, 0); jsB_propfun(J, "PDFDocument.countObjects", ffi_PDFDocument_countObjects, 0); jsB_propfun(J, "PDFDocument.createObject", ffi_PDFDocument_createObject, 0); jsB_propfun(J, "PDFDocument.deleteObject", ffi_PDFDocument_deleteObject, 1); jsB_propfun(J, "PDFDocument.addObject", ffi_PDFDocument_addObject, 1); jsB_propfun(J, "PDFDocument.addStream", ffi_PDFDocument_addStream, 2); jsB_propfun(J, "PDFDocument.addRawStream", ffi_PDFDocument_addRawStream, 2); jsB_propfun(J, "PDFDocument.addSimpleFont", ffi_PDFDocument_addSimpleFont, 2); jsB_propfun(J, "PDFDocument.addCJKFont", ffi_PDFDocument_addCJKFont, 4); jsB_propfun(J, "PDFDocument.addFont", ffi_PDFDocument_addFont, 1); jsB_propfun(J, "PDFDocument.addImage", ffi_PDFDocument_addImage, 1); jsB_propfun(J, "PDFDocument.addPage", ffi_PDFDocument_addPage, 4); jsB_propfun(J, "PDFDocument.insertPage", ffi_PDFDocument_insertPage, 2); jsB_propfun(J, "PDFDocument.deletePage", ffi_PDFDocument_deletePage, 1); jsB_propfun(J, "PDFDocument.countPages", ffi_PDFDocument_countPages, 0); jsB_propfun(J, "PDFDocument.findPage", ffi_PDFDocument_findPage, 1); jsB_propfun(J, "PDFDocument.save", ffi_PDFDocument_save, 2); jsB_propfun(J, "PDFDocument.newNull", ffi_PDFDocument_newNull, 0); jsB_propfun(J, "PDFDocument.newBoolean", ffi_PDFDocument_newBoolean, 1); jsB_propfun(J, "PDFDocument.newInteger", ffi_PDFDocument_newInteger, 1); jsB_propfun(J, "PDFDocument.newReal", ffi_PDFDocument_newReal, 1); jsB_propfun(J, "PDFDocument.newString", ffi_PDFDocument_newString, 1); jsB_propfun(J, "PDFDocument.newByteString", ffi_PDFDocument_newByteString, 1); jsB_propfun(J, "PDFDocument.newName", ffi_PDFDocument_newName, 1); jsB_propfun(J, "PDFDocument.newIndirect", ffi_PDFDocument_newIndirect, 2); jsB_propfun(J, "PDFDocument.newArray", ffi_PDFDocument_newArray, 1); jsB_propfun(J, "PDFDocument.newDictionary", ffi_PDFDocument_newDictionary, 1); jsB_propfun(J, "PDFDocument.newGraftMap", ffi_PDFDocument_newGraftMap, 0); jsB_propfun(J, "PDFDocument.graftObject", ffi_PDFDocument_graftObject, 1); } js_setregistry(J, "pdf_document"); js_getregistry(J, "fz_page"); js_newobjectx(J); { jsB_propfun(J, "PDFPage.createAnnotation", ffi_PDFPage_createAnnotation, 1); jsB_propfun(J, "PDFPage.deleteAnnotation", ffi_PDFPage_deleteAnnotation, 1); jsB_propfun(J, "PDFPage.update", ffi_PDFPage_update, 0); } js_setregistry(J, "pdf_page"); js_getregistry(J, "fz_annot"); js_newobjectx(J); { jsB_propfun(J, "PDFAnnotation.getType", ffi_PDFAnnotation_getType, 0); jsB_propfun(J, "PDFAnnotation.getFlags", ffi_PDFAnnotation_getFlags, 0); jsB_propfun(J, "PDFAnnotation.setFlags", ffi_PDFAnnotation_setFlags, 1); jsB_propfun(J, "PDFAnnotation.getContents", ffi_PDFAnnotation_getContents, 0); jsB_propfun(J, "PDFAnnotation.setContents", ffi_PDFAnnotation_setContents, 1); jsB_propfun(J, "PDFAnnotation.getRect", ffi_PDFAnnotation_getRect, 0); jsB_propfun(J, "PDFAnnotation.setRect", ffi_PDFAnnotation_setRect, 1); jsB_propfun(J, "PDFAnnotation.getBorder", ffi_PDFAnnotation_getBorder, 0); jsB_propfun(J, "PDFAnnotation.setBorder", ffi_PDFAnnotation_setBorder, 1); jsB_propfun(J, "PDFAnnotation.getColor", ffi_PDFAnnotation_getColor, 0); jsB_propfun(J, "PDFAnnotation.setColor", ffi_PDFAnnotation_setColor, 1); jsB_propfun(J, "PDFAnnotation.getInteriorColor", ffi_PDFAnnotation_getInteriorColor, 0); jsB_propfun(J, "PDFAnnotation.setInteriorColor", ffi_PDFAnnotation_setInteriorColor, 1); jsB_propfun(J, "PDFAnnotation.getQuadPoints", ffi_PDFAnnotation_getQuadPoints, 0); jsB_propfun(J, "PDFAnnotation.setQuadPoints", ffi_PDFAnnotation_setQuadPoints, 1); jsB_propfun(J, "PDFAnnotation.getInkList", ffi_PDFAnnotation_getInkList, 0); jsB_propfun(J, "PDFAnnotation.setInkList", ffi_PDFAnnotation_setInkList, 1); jsB_propfun(J, "PDFAnnotation.getAuthor", ffi_PDFAnnotation_getAuthor, 0); jsB_propfun(J, "PDFAnnotation.setAuthor", ffi_PDFAnnotation_setAuthor, 1); jsB_propfun(J, "PDFAnnotation.getModificationDate", ffi_PDFAnnotation_getModificationDate, 0); jsB_propfun(J, "PDFAnnotation.setModificationDate", ffi_PDFAnnotation_setModificationDate, 0); jsB_propfun(J, "PDFAnnotation.updateAppearance", ffi_PDFAnnotation_updateAppearance, 0); jsB_propfun(J, "PDFAnnotation.update", ffi_PDFAnnotation_update, 0); } js_setregistry(J, "pdf_annot"); js_newobject(J); { jsB_propfun(J, "PDFObject.get", ffi_PDFObject_get, 1); jsB_propfun(J, "PDFObject.put", ffi_PDFObject_put, 2); jsB_propfun(J, "PDFObject.push", ffi_PDFObject_push, 1); jsB_propfun(J, "PDFObject.delete", ffi_PDFObject_delete, 1); jsB_propfun(J, "PDFObject.resolve", ffi_PDFObject_resolve, 0); jsB_propfun(J, "PDFObject.toString", ffi_PDFObject_toString, 1); jsB_propfun(J, "PDFObject.valueOf", ffi_PDFObject_valueOf, 0); jsB_propfun(J, "PDFObject.isArray", ffi_PDFObject_isArray, 0); jsB_propfun(J, "PDFObject.isDictionary", ffi_PDFObject_isDictionary, 0); jsB_propfun(J, "PDFObject.isIndirect", ffi_PDFObject_isIndirect, 0); jsB_propfun(J, "PDFObject.asIndirect", ffi_PDFObject_asIndirect, 0); jsB_propfun(J, "PDFObject.isNull", ffi_PDFObject_isNull, 0); jsB_propfun(J, "PDFObject.isBoolean", ffi_PDFObject_isBoolean, 0); jsB_propfun(J, "PDFObject.asBoolean", ffi_PDFObject_asBoolean, 0); jsB_propfun(J, "PDFObject.isNumber", ffi_PDFObject_isNumber, 0); jsB_propfun(J, "PDFObject.asNumber", ffi_PDFObject_asNumber, 0); jsB_propfun(J, "PDFObject.isName", ffi_PDFObject_isName, 0); jsB_propfun(J, "PDFObject.asName", ffi_PDFObject_asName, 0); jsB_propfun(J, "PDFObject.isString", ffi_PDFObject_isString, 0); jsB_propfun(J, "PDFObject.asString", ffi_PDFObject_asString, 0); jsB_propfun(J, "PDFObject.asByteString", ffi_PDFObject_asByteString, 0); jsB_propfun(J, "PDFObject.isStream", ffi_PDFObject_isStream, 0); jsB_propfun(J, "PDFObject.readStream", ffi_PDFObject_readStream, 0); jsB_propfun(J, "PDFObject.readRawStream", ffi_PDFObject_readRawStream, 0); jsB_propfun(J, "PDFObject.writeObject", ffi_PDFObject_writeObject, 1); jsB_propfun(J, "PDFObject.writeStream", ffi_PDFObject_writeStream, 1); jsB_propfun(J, "PDFObject.writeRawStream", ffi_PDFObject_writeRawStream, 1); jsB_propfun(J, "PDFObject.forEach", ffi_PDFObject_forEach, 1); } js_setregistry(J, "pdf_obj"); js_newobject(J); { jsB_propfun(J, "PDFGraftMap.graftObject", ffi_PDFGraftMap_graftObject, 1); } js_setregistry(J, "pdf_graft_map"); #endif js_pushglobal(J); { #if FZ_ENABLE_PDF jsB_propcon(J, "pdf_document", "PDFDocument", ffi_new_PDFDocument, 1); #endif jsB_propcon(J, "fz_buffer", "Buffer", ffi_new_Buffer, 1); jsB_propcon(J, "fz_document", "Document", ffi_new_Document, 1); jsB_propcon(J, "fz_pixmap", "Pixmap", ffi_new_Pixmap, 3); jsB_propcon(J, "fz_image", "Image", ffi_new_Image, 1); jsB_propcon(J, "fz_font", "Font", ffi_new_Font, 2); jsB_propcon(J, "fz_text", "Text", ffi_new_Text, 0); jsB_propcon(J, "fz_path", "Path", ffi_new_Path, 0); jsB_propcon(J, "fz_display_list", "DisplayList", ffi_new_DisplayList, 1); jsB_propcon(J, "fz_device", "DrawDevice", ffi_new_DrawDevice, 2); jsB_propcon(J, "fz_device", "DisplayListDevice", ffi_new_DisplayListDevice, 1); jsB_propcon(J, "fz_document_writer", "DocumentWriter", ffi_new_DocumentWriter, 3); jsB_propfun(J, "readFile", ffi_readFile, 1); js_getregistry(J, "DeviceGray"); js_defproperty(J, -2, "DeviceGray", JS_DONTENUM | JS_READONLY | JS_DONTCONF); js_getregistry(J, "DeviceRGB"); js_defproperty(J, -2, "DeviceRGB", JS_DONTENUM | JS_READONLY | JS_DONTCONF); js_getregistry(J, "DeviceBGR"); js_defproperty(J, -2, "DeviceBGR", JS_DONTENUM | JS_READONLY | JS_DONTCONF); js_getregistry(J, "DeviceCMYK"); js_defproperty(J, -2, "DeviceCMYK", JS_DONTENUM | JS_READONLY | JS_DONTCONF); jsB_propfun(J, "setUserCSS", ffi_setUserCSS, 2); } /* re-implement matrix math in javascript */ js_dostring(J, "var Identity = Object.freeze([1,0,0,1,0,0]);"); js_dostring(J, "function Scale(sx,sy) { return [sx,0,0,sy,0,0]; }"); js_dostring(J, "function Translate(tx,ty) { return [1,0,0,1,tx,ty]; }"); js_dostring(J, "function Concat(a,b) { return [" "a[0] * b[0] + a[1] * b[2]," "a[0] * b[1] + a[1] * b[3]," "a[2] * b[0] + a[3] * b[2]," "a[2] * b[1] + a[3] * b[3]," "a[4] * b[0] + a[5] * b[2] + b[4]," "a[4] * b[1] + a[5] * b[3] + b[5]];}"); if (argc > 1) { js_pushstring(J, argv[1]); js_setglobal(J, "scriptPath"); js_newarray(J); for (i = 2; i < argc; ++i) { js_pushstring(J, argv[i]); js_setindex(J, -2, i - 2); } js_setglobal(J, "scriptArgs"); if (js_dofile(J, argv[1])) return 1; } else { char line[256]; fputs(PS1, stdout); while (fgets(line, sizeof line, stdin)) { eval_print(J, line); fputs(PS1, stdout); } putchar('\n'); } js_freestate(J); fz_drop_context(ctx); return 0; } #endif