1 #include "mupdf/fitz.h"
2
3 #if FZ_ENABLE_PDF
4 #include "mupdf/pdf.h"
5 #include "mupdf/helpers/pkcs7-openssl.h"
6 #endif
7
8 #if FZ_ENABLE_JS
9
10 #include "mujs.h"
11
12 #include <string.h>
13 #include <stdlib.h>
14 #include <stdio.h>
15
16 #define PS1 "> "
17
rethrow(js_State * J)18 FZ_NORETURN static void rethrow(js_State *J)
19 {
20 js_newerror(J, fz_caught_message(js_getcontext(J)));
21 js_throw(J);
22 }
23
rethrow_as_fz(js_State * J)24 FZ_NORETURN static void rethrow_as_fz(js_State *J)
25 {
26 fz_throw(js_getcontext(J), FZ_ERROR_GENERIC, "%s", js_tostring(J, -1));
27 }
28
alloc(void * actx,void * ptr,int n)29 static void *alloc(void *actx, void *ptr, int n)
30 {
31 return fz_realloc_no_throw(actx, ptr, n);
32 }
33
eval_print(js_State * J,const char * source)34 static int eval_print(js_State *J, const char *source)
35 {
36 if (js_ploadstring(J, "[string]", source)) {
37 fprintf(stderr, "%s\n", js_trystring(J, -1, "Error"));
38 js_pop(J, 1);
39 return 1;
40 }
41 js_pushundefined(J);
42 if (js_pcall(J, 0)) {
43 fprintf(stderr, "%s\n", js_trystring(J, -1, "Error"));
44 js_pop(J, 1);
45 return 1;
46 }
47 if (js_isdefined(J, -1)) {
48 printf("%s\n", js_tryrepr(J, -1, "can't convert to string"));
49 }
50 js_pop(J, 1);
51 return 0;
52 }
53
jsB_propfun(js_State * J,const char * name,js_CFunction cfun,int n)54 static void jsB_propfun(js_State *J, const char *name, js_CFunction cfun, int n)
55 {
56 const char *realname = strchr(name, '.');
57 realname = realname ? realname + 1 : name;
58 js_newcfunction(J, cfun, name, n);
59 js_defproperty(J, -2, realname, JS_DONTENUM);
60 }
61
jsB_propcon(js_State * J,const char * tag,const char * name,js_CFunction cfun,int n)62 static void jsB_propcon(js_State *J, const char *tag, const char *name, js_CFunction cfun, int n)
63 {
64 const char *realname = strchr(name, '.');
65 realname = realname ? realname + 1 : name;
66 js_getregistry(J, tag);
67 js_newcconstructor(J, cfun, cfun, name, n);
68 js_defproperty(J, -2, realname, JS_DONTENUM);
69 }
70
jsB_gc(js_State * J)71 static void jsB_gc(js_State *J)
72 {
73 int report = js_toboolean(J, 1);
74 js_gc(J, report);
75 js_pushundefined(J);
76 }
77
jsB_load(js_State * J)78 static void jsB_load(js_State *J)
79 {
80 const char *filename = js_tostring(J, 1);
81 int rv = js_dofile(J, filename);
82 js_pushboolean(J, !rv);
83 }
84
jsB_print(js_State * J)85 static void jsB_print(js_State *J)
86 {
87 unsigned int i, top = js_gettop(J);
88 for (i = 1; i < top; ++i) {
89 const char *s = js_tostring(J, i);
90 if (i > 1) putchar(' ');
91 fputs(s, stdout);
92 }
93 putchar('\n');
94 js_pushundefined(J);
95 }
96
jsB_write(js_State * J)97 static void jsB_write(js_State *J)
98 {
99 unsigned int i, top = js_gettop(J);
100 for (i = 1; i < top; ++i) {
101 const char *s = js_tostring(J, i);
102 if (i > 1) putchar(' ');
103 fputs(s, stdout);
104 }
105 js_pushundefined(J);
106 }
107
jsB_read(js_State * J)108 static void jsB_read(js_State *J)
109 {
110 fz_context *ctx = js_getcontext(J);
111 const char *filename = js_tostring(J, 1);
112 FILE *f;
113 char *s;
114 long n;
115 size_t t;
116
117 f = fopen(filename, "rb");
118 if (!f) {
119 js_error(J, "cannot open file: '%s'", filename);
120 }
121
122 if (fseek(f, 0, SEEK_END) < 0) {
123 fclose(f);
124 js_error(J, "cannot seek in file: '%s'", filename);
125 }
126
127 n = ftell(f);
128 if (n < 0) {
129 fclose(f);
130 js_error(J, "cannot tell in file: '%s'", filename);
131 }
132
133 if (fseek(f, 0, SEEK_SET) < 0) {
134 fclose(f);
135 js_error(J, "cannot seek in file: '%s'", filename);
136 }
137
138 s = fz_malloc(ctx, n + 1);
139 if (!s) {
140 fclose(f);
141 js_error(J, "cannot allocate storage for file contents: '%s'", filename);
142 }
143
144 t = fread(s, 1, n, f);
145 if (t != (size_t) n) {
146 fz_free(ctx, s);
147 fclose(f);
148 js_error(J, "cannot read data from file: '%s'", filename);
149 }
150 s[n] = 0;
151
152 js_pushstring(J, s);
153 fz_free(ctx, s);
154 fclose(f);
155 }
156
jsB_readline(js_State * J)157 static void jsB_readline(js_State *J)
158 {
159 char line[256];
160 size_t n;
161 if (!fgets(line, sizeof line, stdin))
162 js_error(J, "cannot read line from stdin");
163 n = strlen(line);
164 if (n > 0 && line[n-1] == '\n')
165 line[n-1] = 0;
166 js_pushstring(J, line);
167 }
168
jsB_repr(js_State * J)169 static void jsB_repr(js_State *J)
170 {
171 js_repr(J, 1);
172 }
173
jsB_quit(js_State * J)174 static void jsB_quit(js_State *J)
175 {
176 exit(js_tonumber(J, 1));
177 }
178
179 static const char *require_js =
180 "function require(name) {\n"
181 "var cache = require.cache;\n"
182 "if (name in cache) return cache[name];\n"
183 "var exports = {};\n"
184 "cache[name] = exports;\n"
185 "Function('exports', read(name+'.js'))(exports);\n"
186 "return exports;\n"
187 "}\n"
188 "require.cache = Object.create(null);\n"
189 ;
190
191 static const char *stacktrace_js =
192 "Error.prototype.toString = function() {\n"
193 "if (this.stackTrace) return this.name + ': ' + this.message + this.stackTrace;\n"
194 "return this.name + ': ' + this.message;\n"
195 "};\n"
196 ;
197
198 /* destructors */
199
ffi_gc_fz_buffer(js_State * J,void * buf)200 static void ffi_gc_fz_buffer(js_State *J, void *buf)
201 {
202 fz_context *ctx = js_getcontext(J);
203 fz_try(ctx)
204 fz_drop_buffer(ctx, buf);
205 fz_catch(ctx)
206 rethrow(J);
207 }
208
ffi_gc_fz_document(js_State * J,void * doc)209 static void ffi_gc_fz_document(js_State *J, void *doc)
210 {
211 fz_context *ctx = js_getcontext(J);
212 fz_drop_document(ctx, doc);
213 }
214
ffi_gc_pdf_pkcs7_signer(js_State * J,void * signer_)215 static void ffi_gc_pdf_pkcs7_signer(js_State *J, void *signer_)
216 {
217 fz_context *ctx = js_getcontext(J);
218 pdf_pkcs7_signer *signer = (pdf_pkcs7_signer *)signer_;
219 if (signer)
220 signer->drop(ctx, signer);
221 }
222
ffi_gc_fz_page(js_State * J,void * page)223 static void ffi_gc_fz_page(js_State *J, void *page)
224 {
225 fz_context *ctx = js_getcontext(J);
226 fz_drop_page(ctx, page);
227 }
228
ffi_gc_fz_colorspace(js_State * J,void * colorspace)229 static void ffi_gc_fz_colorspace(js_State *J, void *colorspace)
230 {
231 fz_context *ctx = js_getcontext(J);
232 fz_drop_colorspace(ctx, colorspace);
233 }
234
ffi_gc_fz_pixmap(js_State * J,void * pixmap)235 static void ffi_gc_fz_pixmap(js_State *J, void *pixmap)
236 {
237 fz_context *ctx = js_getcontext(J);
238 fz_drop_pixmap(ctx, pixmap);
239 }
240
ffi_gc_fz_path(js_State * J,void * path)241 static void ffi_gc_fz_path(js_State *J, void *path)
242 {
243 fz_context *ctx = js_getcontext(J);
244 fz_drop_path(ctx, path);
245 }
246
ffi_gc_fz_text(js_State * J,void * text)247 static void ffi_gc_fz_text(js_State *J, void *text)
248 {
249 fz_context *ctx = js_getcontext(J);
250 fz_drop_text(ctx, text);
251 }
252
ffi_gc_fz_font(js_State * J,void * font)253 static void ffi_gc_fz_font(js_State *J, void *font)
254 {
255 fz_context *ctx = js_getcontext(J);
256 fz_drop_font(ctx, font);
257 }
258
ffi_gc_fz_shade(js_State * J,void * shade)259 static void ffi_gc_fz_shade(js_State *J, void *shade)
260 {
261 fz_context *ctx = js_getcontext(J);
262 fz_drop_shade(ctx, shade);
263 }
264
ffi_gc_fz_image(js_State * J,void * image)265 static void ffi_gc_fz_image(js_State *J, void *image)
266 {
267 fz_context *ctx = js_getcontext(J);
268 fz_drop_image(ctx, image);
269 }
270
ffi_gc_fz_display_list(js_State * J,void * list)271 static void ffi_gc_fz_display_list(js_State *J, void *list)
272 {
273 fz_context *ctx = js_getcontext(J);
274 fz_drop_display_list(ctx, list);
275 }
276
ffi_gc_fz_stext_page(js_State * J,void * text)277 static void ffi_gc_fz_stext_page(js_State *J, void *text)
278 {
279 fz_context *ctx = js_getcontext(J);
280 fz_drop_stext_page(ctx, text);
281 }
282
ffi_gc_fz_device(js_State * J,void * device)283 static void ffi_gc_fz_device(js_State *J, void *device)
284 {
285 fz_context *ctx = js_getcontext(J);
286 fz_drop_device(ctx, device);
287 }
288
ffi_gc_fz_document_writer(js_State * J,void * wri)289 static void ffi_gc_fz_document_writer(js_State *J, void *wri)
290 {
291 fz_context *ctx = js_getcontext(J);
292 fz_drop_document_writer(ctx, wri);
293 }
294
295 #if FZ_ENABLE_PDF
296
297 static void ffi_pushobj(js_State *J, pdf_obj *obj);
298
ffi_gc_pdf_widget(js_State * J,void * widget)299 static void ffi_gc_pdf_widget(js_State *J, void *widget)
300 {
301 fz_context *ctx = js_getcontext(J);
302 pdf_drop_widget(ctx, widget);
303 }
304
ffi_gc_pdf_annot(js_State * J,void * annot)305 static void ffi_gc_pdf_annot(js_State *J, void *annot)
306 {
307 fz_context *ctx = js_getcontext(J);
308 pdf_drop_annot(ctx, annot);
309 }
310
ffi_gc_pdf_document(js_State * J,void * doc)311 static void ffi_gc_pdf_document(js_State *J, void *doc)
312 {
313 fz_context *ctx = js_getcontext(J);
314 pdf_drop_document(ctx, doc);
315 }
316
ffi_gc_pdf_obj(js_State * J,void * obj)317 static void ffi_gc_pdf_obj(js_State *J, void *obj)
318 {
319 fz_context *ctx = js_getcontext(J);
320 pdf_drop_obj(ctx, obj);
321 }
322
ffi_gc_pdf_graft_map(js_State * J,void * map)323 static void ffi_gc_pdf_graft_map(js_State *J, void *map)
324 {
325 fz_context *ctx = js_getcontext(J);
326 pdf_drop_graft_map(ctx, map);
327 }
328
ffi_todocument(js_State * J,int idx)329 static fz_document *ffi_todocument(js_State *J, int idx)
330 {
331 if (js_isuserdata(J, idx, "pdf_document"))
332 return js_touserdata(J, idx, "pdf_document");
333 return js_touserdata(J, idx, "fz_document");
334 }
335
ffi_pushdocument(js_State * J,fz_document * document)336 static void ffi_pushdocument(js_State *J, fz_document *document)
337 {
338 fz_context *ctx = js_getcontext(J);
339 pdf_document *pdocument = pdf_document_from_fz_document(ctx, document);
340 if (pdocument) {
341 js_getregistry(J, "pdf_document");
342 js_newuserdata(J, "pdf_document", document, ffi_gc_fz_document);
343 } else {
344 js_getregistry(J, "fz_document");
345 js_newuserdata(J, "fz_document", document, ffi_gc_fz_document);
346 }
347 }
348
ffi_pushsigner(js_State * J,pdf_pkcs7_signer * signer)349 static void ffi_pushsigner(js_State *J, pdf_pkcs7_signer *signer)
350 {
351 js_getregistry(J, "pdf_pkcs7_signer");
352 js_newuserdata(J, "pdf_pkcs7_signer", signer, ffi_gc_pdf_pkcs7_signer);
353 }
354
ffi_topage(js_State * J,int idx)355 static fz_page *ffi_topage(js_State *J, int idx)
356 {
357 if (js_isuserdata(J, idx, "pdf_page"))
358 return js_touserdata(J, idx, "pdf_page");
359 return js_touserdata(J, idx, "fz_page");
360 }
361
ffi_pushpage(js_State * J,fz_page * page)362 static void ffi_pushpage(js_State *J, fz_page *page)
363 {
364 fz_context *ctx = js_getcontext(J);
365 pdf_page *ppage = pdf_page_from_fz_page(ctx, page);
366 if (ppage) {
367 js_getregistry(J, "pdf_page");
368 js_newuserdata(J, "pdf_page", page, ffi_gc_fz_page);
369 } else {
370 js_getregistry(J, "fz_page");
371 js_newuserdata(J, "fz_page", page, ffi_gc_fz_page);
372 }
373 }
374
375 #else
376
ffi_todocument(js_State * J,int idx)377 static fz_document *ffi_todocument(js_State *J, int idx)
378 {
379 return js_touserdata(J, idx, "fz_document");
380 }
381
ffi_pushdocument(js_State * J,fz_document * document)382 static void ffi_pushdocument(js_State *J, fz_document *document)
383 {
384 js_getregistry(J, "fz_document");
385 js_newuserdata(J, "fz_document", doc, ffi_gc_fz_document);
386 }
387
ffi_topage(js_State * J,int idx)388 static fz_page *ffi_topage(js_State *J, int idx)
389 {
390 return js_touserdata(J, idx, "fz_page");
391 }
392
ffi_pushpage(js_State * J,fz_page * page)393 static void ffi_pushpage(js_State *J, fz_page *page)
394 {
395 js_getregistry(J, "fz_page");
396 js_newuserdata(J, "fz_page", page, ffi_gc_fz_page);
397 }
398
399 #endif /* FZ_ENABLE_PDF */
400
401 /* type conversions */
402
403 struct color {
404 fz_colorspace *colorspace;
405 float color[FZ_MAX_COLORS];
406 float alpha;
407 };
408
ffi_tomatrix(js_State * J,int idx)409 static fz_matrix ffi_tomatrix(js_State *J, int idx)
410 {
411 if (js_iscoercible(J, idx))
412 {
413 fz_matrix matrix;
414 js_getindex(J, idx, 0); matrix.a = js_tonumber(J, -1); js_pop(J, 1);
415 js_getindex(J, idx, 1); matrix.b = js_tonumber(J, -1); js_pop(J, 1);
416 js_getindex(J, idx, 2); matrix.c = js_tonumber(J, -1); js_pop(J, 1);
417 js_getindex(J, idx, 3); matrix.d = js_tonumber(J, -1); js_pop(J, 1);
418 js_getindex(J, idx, 4); matrix.e = js_tonumber(J, -1); js_pop(J, 1);
419 js_getindex(J, idx, 5); matrix.f = js_tonumber(J, -1); js_pop(J, 1);
420 return matrix;
421 }
422 return fz_identity;
423 }
424
ffi_pushmatrix(js_State * J,fz_matrix matrix)425 static void ffi_pushmatrix(js_State *J, fz_matrix matrix)
426 {
427 js_newarray(J);
428 js_pushnumber(J, matrix.a); js_setindex(J, -2, 0);
429 js_pushnumber(J, matrix.b); js_setindex(J, -2, 1);
430 js_pushnumber(J, matrix.c); js_setindex(J, -2, 2);
431 js_pushnumber(J, matrix.d); js_setindex(J, -2, 3);
432 js_pushnumber(J, matrix.e); js_setindex(J, -2, 4);
433 js_pushnumber(J, matrix.f); js_setindex(J, -2, 5);
434 }
435
ffi_topoint(js_State * J,int idx)436 static fz_point ffi_topoint(js_State *J, int idx)
437 {
438 fz_point point;
439 js_getindex(J, idx, 0); point.x = js_tonumber(J, -1); js_pop(J, 1);
440 js_getindex(J, idx, 1); point.y = js_tonumber(J, -1); js_pop(J, 1);
441 return point;
442 }
443
ffi_pushpoint(js_State * J,fz_point point)444 static void ffi_pushpoint(js_State *J, fz_point point)
445 {
446 js_newarray(J);
447 js_pushnumber(J, point.x); js_setindex(J, -2, 0);
448 js_pushnumber(J, point.y); js_setindex(J, -2, 1);
449 }
450
ffi_torect(js_State * J,int idx)451 static fz_rect ffi_torect(js_State *J, int idx)
452 {
453 fz_rect rect;
454 js_getindex(J, idx, 0); rect.x0 = js_tonumber(J, -1); js_pop(J, 1);
455 js_getindex(J, idx, 1); rect.y0 = js_tonumber(J, -1); js_pop(J, 1);
456 js_getindex(J, idx, 2); rect.x1 = js_tonumber(J, -1); js_pop(J, 1);
457 js_getindex(J, idx, 3); rect.y1 = js_tonumber(J, -1); js_pop(J, 1);
458 return rect;
459 }
460
ffi_pushrect(js_State * J,fz_rect rect)461 static void ffi_pushrect(js_State *J, fz_rect rect)
462 {
463 js_newarray(J);
464 js_pushnumber(J, rect.x0); js_setindex(J, -2, 0);
465 js_pushnumber(J, rect.y0); js_setindex(J, -2, 1);
466 js_pushnumber(J, rect.x1); js_setindex(J, -2, 2);
467 js_pushnumber(J, rect.y1); js_setindex(J, -2, 3);
468 }
469
ffi_toquad(js_State * J,int idx)470 static fz_quad ffi_toquad(js_State *J, int idx)
471 {
472 fz_quad quad;
473 js_getindex(J, idx, 0); quad.ul.x = js_tonumber(J, -1); js_pop(J, 1);
474 js_getindex(J, idx, 1); quad.ul.y = js_tonumber(J, -1); js_pop(J, 1);
475 js_getindex(J, idx, 2); quad.ur.x = js_tonumber(J, -1); js_pop(J, 1);
476 js_getindex(J, idx, 3); quad.ur.y = js_tonumber(J, -1); js_pop(J, 1);
477 js_getindex(J, idx, 4); quad.ll.x = js_tonumber(J, -1); js_pop(J, 1);
478 js_getindex(J, idx, 5); quad.ll.y = js_tonumber(J, -1); js_pop(J, 1);
479 js_getindex(J, idx, 6); quad.lr.x = js_tonumber(J, -1); js_pop(J, 1);
480 js_getindex(J, idx, 7); quad.lr.y = js_tonumber(J, -1); js_pop(J, 1);
481 return quad;
482 }
483
ffi_pushquad(js_State * J,fz_quad quad)484 static void ffi_pushquad(js_State *J, fz_quad quad)
485 {
486 js_newarray(J);
487 js_pushnumber(J, quad.ul.x); js_setindex(J, -2, 0);
488 js_pushnumber(J, quad.ul.y); js_setindex(J, -2, 1);
489 js_pushnumber(J, quad.ur.x); js_setindex(J, -2, 2);
490 js_pushnumber(J, quad.ur.y); js_setindex(J, -2, 3);
491 js_pushnumber(J, quad.ll.x); js_setindex(J, -2, 4);
492 js_pushnumber(J, quad.ll.y); js_setindex(J, -2, 5);
493 js_pushnumber(J, quad.lr.x); js_setindex(J, -2, 6);
494 js_pushnumber(J, quad.lr.y); js_setindex(J, -2, 7);
495 }
496
ffi_toirect(js_State * J,int idx)497 static fz_irect ffi_toirect(js_State *J, int idx)
498 {
499 fz_irect irect;
500 js_getindex(J, idx, 0); irect.x0 = js_tonumber(J, -1); js_pop(J, 1);
501 js_getindex(J, idx, 1); irect.y0 = js_tonumber(J, -1); js_pop(J, 1);
502 js_getindex(J, idx, 2); irect.x1 = js_tonumber(J, -1); js_pop(J, 1);
503 js_getindex(J, idx, 3); irect.y1 = js_tonumber(J, -1); js_pop(J, 1);
504 return irect;
505 }
506
ffi_pusharray(js_State * J,const float * v,int n)507 static void ffi_pusharray(js_State *J, const float *v, int n)
508 {
509 int i;
510 js_newarray(J);
511 for (i = 0; i < n; ++i) {
512 js_pushnumber(J, v[i]);
513 js_setindex(J, -2, i);
514 }
515 }
516
ffi_pushcolorspace(js_State * J,fz_colorspace * colorspace)517 static void ffi_pushcolorspace(js_State *J, fz_colorspace *colorspace)
518 {
519 fz_context *ctx = js_getcontext(J);
520 if (colorspace == fz_device_rgb(ctx))
521 js_getregistry(J, "DeviceRGB");
522 else if (colorspace == fz_device_bgr(ctx))
523 js_getregistry(J, "DeviceBGR");
524 else if (colorspace == fz_device_gray(ctx))
525 js_getregistry(J, "DeviceGray");
526 else if (colorspace == fz_device_cmyk(ctx))
527 js_getregistry(J, "DeviceCMYK");
528 else {
529 js_getregistry(J, "fz_colorspace");
530 js_newuserdata(J, "fz_colorspace", fz_keep_colorspace(ctx, colorspace), ffi_gc_fz_colorspace);
531 }
532 }
533
ffi_pushcolor(js_State * J,fz_colorspace * colorspace,const float * color,float alpha)534 static void ffi_pushcolor(js_State *J, fz_colorspace *colorspace, const float *color, float alpha)
535 {
536 fz_context *ctx = js_getcontext(J);
537 if (colorspace) {
538 ffi_pushcolorspace(J, colorspace);
539 ffi_pusharray(J, color, fz_colorspace_n(ctx, colorspace));
540 } else {
541 js_pushnull(J);
542 js_pushnull(J);
543 }
544 js_pushnumber(J, alpha);
545 }
546
ffi_tocolor(js_State * J,int idx)547 static struct color ffi_tocolor(js_State *J, int idx)
548 {
549 struct color c;
550 int n, i;
551 fz_context *ctx = js_getcontext(J);
552 c.colorspace = js_touserdata(J, idx, "fz_colorspace");
553 if (c.colorspace) {
554 n = fz_colorspace_n(ctx, c.colorspace);
555 for (i=0; i < n; ++i) {
556 js_getindex(J, idx + 1, i);
557 c.color[i] = js_tonumber(J, -1);
558 js_pop(J, 1);
559 }
560 }
561 c.alpha = js_tonumber(J, idx + 2);
562 return c;
563 }
564
ffi_tocolorparams(js_State * J,int idx)565 static fz_color_params ffi_tocolorparams(js_State *J, int idx)
566 {
567 /* TODO */
568 return fz_default_color_params;
569 }
570
ffi_pushcolorparams(js_State * J,fz_color_params color_params)571 static void ffi_pushcolorparams(js_State *J, fz_color_params color_params)
572 {
573 /* TODO */
574 js_pushnull(J);
575 }
576
string_from_cap(fz_linecap cap)577 static const char *string_from_cap(fz_linecap cap)
578 {
579 switch (cap) {
580 default:
581 case FZ_LINECAP_BUTT: return "Butt";
582 case FZ_LINECAP_ROUND: return "Round";
583 case FZ_LINECAP_SQUARE: return "Square";
584 case FZ_LINECAP_TRIANGLE: return "Triangle";
585 }
586 }
587
string_from_join(fz_linejoin join)588 static const char *string_from_join(fz_linejoin join)
589 {
590 switch (join) {
591 default:
592 case FZ_LINEJOIN_MITER: return "Miter";
593 case FZ_LINEJOIN_ROUND: return "Round";
594 case FZ_LINEJOIN_BEVEL: return "Bevel";
595 case FZ_LINEJOIN_MITER_XPS: return "MiterXPS";
596 }
597 }
598
string_from_line_ending(enum pdf_line_ending style)599 static const char *string_from_line_ending(enum pdf_line_ending style)
600 {
601 switch (style) {
602 default:
603 case PDF_ANNOT_LE_NONE: return "None";
604 case PDF_ANNOT_LE_SQUARE: return "Square";
605 case PDF_ANNOT_LE_CIRCLE: return "Circle";
606 case PDF_ANNOT_LE_DIAMOND: return "Diamond";
607 case PDF_ANNOT_LE_OPEN_ARROW: return "OpenArrow";
608 case PDF_ANNOT_LE_CLOSED_ARROW: return "ClosedArrow";
609 case PDF_ANNOT_LE_BUTT: return "Butt";
610 case PDF_ANNOT_LE_R_OPEN_ARROW: return "ROpenArrow";
611 case PDF_ANNOT_LE_R_CLOSED_ARROW: return "RCloseArrow";
612 case PDF_ANNOT_LE_SLASH: return "Slash";
613 }
614 }
615
cap_from_string(const char * str)616 static fz_linecap cap_from_string(const char *str)
617 {
618 if (!strcmp(str, "Round")) return FZ_LINECAP_ROUND;
619 if (!strcmp(str, "Square")) return FZ_LINECAP_SQUARE;
620 if (!strcmp(str, "Triangle")) return FZ_LINECAP_TRIANGLE;
621 return FZ_LINECAP_BUTT;
622 }
623
join_from_string(const char * str)624 static fz_linejoin join_from_string(const char *str)
625 {
626 if (!strcmp(str, "Round")) return FZ_LINEJOIN_ROUND;
627 if (!strcmp(str, "Bevel")) return FZ_LINEJOIN_BEVEL;
628 if (!strcmp(str, "MiterXPS")) return FZ_LINEJOIN_MITER_XPS;
629 return FZ_LINEJOIN_MITER;
630 }
631
line_ending_from_string(const char * str)632 static enum pdf_line_ending line_ending_from_string(const char *str)
633 {
634 if (!strcmp(str, "None")) return PDF_ANNOT_LE_NONE;
635 if (!strcmp(str, "Square")) return PDF_ANNOT_LE_SQUARE;
636 if (!strcmp(str, "Circle")) return PDF_ANNOT_LE_CIRCLE;
637 if (!strcmp(str, "Diamond")) return PDF_ANNOT_LE_DIAMOND;
638 if (!strcmp(str, "OpenArrow")) return PDF_ANNOT_LE_OPEN_ARROW;
639 if (!strcmp(str, "ClosedArrow")) return PDF_ANNOT_LE_CLOSED_ARROW;
640 if (!strcmp(str, "Butt")) return PDF_ANNOT_LE_BUTT;
641 if (!strcmp(str, "ROpenArrow")) return PDF_ANNOT_LE_R_OPEN_ARROW;
642 if (!strcmp(str, "RClosedArrow")) return PDF_ANNOT_LE_R_CLOSED_ARROW;
643 if (!strcmp(str, "Slash")) return PDF_ANNOT_LE_SLASH;
644 return PDF_ANNOT_LE_NONE;
645 }
646
ffi_pushstroke(js_State * J,const fz_stroke_state * stroke)647 static void ffi_pushstroke(js_State *J, const fz_stroke_state *stroke)
648 {
649 js_newobject(J);
650 js_pushliteral(J, string_from_cap(stroke->start_cap));
651 js_setproperty(J, -2, "startCap");
652 js_pushliteral(J, string_from_cap(stroke->dash_cap));
653 js_setproperty(J, -2, "dashCap");
654 js_pushliteral(J, string_from_cap(stroke->end_cap));
655 js_setproperty(J, -2, "endCap");
656 js_pushliteral(J, string_from_join(stroke->linejoin));
657 js_setproperty(J, -2, "lineJoin");
658 js_pushnumber(J, stroke->linewidth);
659 js_setproperty(J, -2, "lineWidth");
660 js_pushnumber(J, stroke->miterlimit);
661 js_setproperty(J, -2, "miterLimit");
662 js_pushnumber(J, stroke->dash_phase);
663 js_setproperty(J, -2, "dashPhase");
664 ffi_pusharray(J, stroke->dash_list, stroke->dash_len);
665 js_setproperty(J, -2, "dashes");
666 }
667
ffi_tostroke(js_State * J,int idx)668 static fz_stroke_state ffi_tostroke(js_State *J, int idx)
669 {
670 fz_stroke_state stroke = fz_default_stroke_state;
671 if (js_hasproperty(J, idx, "lineCap")) {
672 stroke.start_cap = cap_from_string(js_tostring(J, -1));
673 stroke.dash_cap = stroke.start_cap;
674 stroke.end_cap = stroke.start_cap;
675 }
676 if (js_hasproperty(J, idx, "startCap")) {
677 stroke.start_cap = cap_from_string(js_tostring(J, -1));
678 js_pop(J, 1);
679 }
680 if (js_hasproperty(J, idx, "dashCap")) {
681 stroke.dash_cap = cap_from_string(js_tostring(J, -1));
682 js_pop(J, 1);
683 }
684 if (js_hasproperty(J, idx, "endCap")) {
685 stroke.end_cap = cap_from_string(js_tostring(J, -1));
686 js_pop(J, 1);
687 }
688 if (js_hasproperty(J, idx, "lineJoin")) {
689 stroke.linejoin = join_from_string(js_tostring(J, -1));
690 js_pop(J, 1);
691 }
692 if (js_hasproperty(J, idx, "lineWidth")) {
693 stroke.linewidth = js_tonumber(J, -1);
694 js_pop(J, 1);
695 }
696 if (js_hasproperty(J, idx, "miterLimit")) {
697 stroke.miterlimit = js_tonumber(J, -1);
698 js_pop(J, 1);
699 }
700 if (js_hasproperty(J, idx, "dashPhase")) {
701 stroke.dash_phase = js_tonumber(J, -1);
702 js_pop(J, 1);
703 }
704 if (js_hasproperty(J, idx, "dashes")) {
705 int i, n = js_getlength(J, -1);
706 if (n > (int)nelem(stroke.dash_list))
707 n = nelem(stroke.dash_list);
708 stroke.dash_len = n;
709 for (i = 0; i < n; ++i) {
710 js_getindex(J, -1, i);
711 stroke.dash_list[i] = js_tonumber(J, -1);
712 js_pop(J, 1);
713 }
714 }
715 return stroke;
716 }
717
ffi_pushtext(js_State * J,const fz_text * text)718 static void ffi_pushtext(js_State *J, const fz_text *text)
719 {
720 fz_context *ctx = js_getcontext(J);
721 js_getregistry(J, "fz_text");
722 js_newuserdata(J, "fz_text", fz_keep_text(ctx, text), ffi_gc_fz_text);
723 }
724
ffi_pushpath(js_State * J,const fz_path * path)725 static void ffi_pushpath(js_State *J, const fz_path *path)
726 {
727 fz_context *ctx = js_getcontext(J);
728 js_getregistry(J, "fz_path");
729 js_newuserdata(J, "fz_path", fz_keep_path(ctx, path), ffi_gc_fz_path);
730 }
731
ffi_pushfont(js_State * J,fz_font * font)732 static void ffi_pushfont(js_State *J, fz_font *font)
733 {
734 fz_context *ctx = js_getcontext(J);
735 js_getregistry(J, "fz_font");
736 js_newuserdata(J, "fz_font", fz_keep_font(ctx, font), ffi_gc_fz_font);
737 }
738
ffi_pushshade(js_State * J,fz_shade * shade)739 static void ffi_pushshade(js_State *J, fz_shade *shade)
740 {
741 fz_context *ctx = js_getcontext(J);
742 js_getregistry(J, "fz_shade");
743 js_newuserdata(J, "fz_shade", fz_keep_shade(ctx, shade), ffi_gc_fz_shade);
744 }
745
ffi_pushimage(js_State * J,fz_image * image)746 static void ffi_pushimage(js_State *J, fz_image *image)
747 {
748 fz_context *ctx = js_getcontext(J);
749 js_getregistry(J, "fz_image");
750 js_newuserdata(J, "fz_image", fz_keep_image(ctx, image), ffi_gc_fz_image);
751 }
752
ffi_pushimage_own(js_State * J,fz_image * image)753 static void ffi_pushimage_own(js_State *J, fz_image *image)
754 {
755 js_getregistry(J, "fz_image");
756 js_newuserdata(J, "fz_image", image, ffi_gc_fz_image);
757 }
758
is_number(const char * key,int * idx)759 static int is_number(const char *key, int *idx)
760 {
761 char *end;
762 *idx = strtol(key, &end, 10);
763 return *end == 0;
764 }
765
ffi_buffer_has(js_State * J,void * buf_,const char * key)766 static int ffi_buffer_has(js_State *J, void *buf_, const char *key)
767 {
768 fz_buffer *buf = buf_;
769 int idx;
770 unsigned char *data;
771 size_t len = fz_buffer_storage(js_getcontext(J), buf, &data);
772 if (is_number(key, &idx)) {
773 if (idx < 0 || (size_t)idx >= len)
774 js_rangeerror(J, "index out of bounds");
775 js_pushnumber(J, data[idx]);
776 return 1;
777 }
778 if (!strcmp(key, "length")) {
779 js_pushnumber(J, len);
780 return 1;
781 }
782 return 0;
783 }
784
ffi_buffer_put(js_State * J,void * buf_,const char * key)785 static int ffi_buffer_put(js_State *J, void *buf_, const char *key)
786 {
787 fz_buffer *buf = buf_;
788 int idx;
789 unsigned char *data;
790 size_t len = fz_buffer_storage(js_getcontext(J), buf, &data);
791 if (is_number(key, &idx)) {
792 if (idx < 0 || (size_t)idx >= len)
793 js_rangeerror(J, "index out of bounds");
794 data[idx] = js_tonumber(J, -1);
795 return 1;
796 }
797 if (!strcmp(key, "length"))
798 js_typeerror(J, "buffer length is read-only");
799 return 0;
800 }
801
ffi_pushbuffer(js_State * J,fz_buffer * buf)802 static void ffi_pushbuffer(js_State *J, fz_buffer *buf)
803 {
804 js_getregistry(J, "fz_buffer");
805 js_newuserdatax(J, "fz_buffer", buf,
806 ffi_buffer_has, ffi_buffer_put, NULL,
807 ffi_gc_fz_buffer);
808 }
809
810 #if FZ_ENABLE_PDF
811
ffi_tobuffer(js_State * J,int idx)812 static fz_buffer *ffi_tobuffer(js_State *J, int idx)
813 {
814 fz_context *ctx = js_getcontext(J);
815 fz_buffer *buf = NULL;
816
817 if (js_isuserdata(J, idx, "fz_buffer"))
818 buf = fz_keep_buffer(ctx, js_touserdata(J, idx, "fz_buffer"));
819 else {
820 const char *str = js_tostring(J, idx);
821 fz_try(ctx)
822 buf = fz_new_buffer_from_copied_data(ctx, (const unsigned char *)str, strlen(str));
823 fz_catch(ctx)
824 rethrow(J);
825 }
826
827 return buf;
828 }
829
830 #endif /* FZ_ENABLE_PDF */
831
832 /* device calling into js from c */
833
834 typedef struct
835 {
836 fz_device super;
837 js_State *J;
838 } js_device;
839
840 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,fz_color_params color_params)841 js_dev_fill_path(fz_context *ctx, fz_device *dev, const fz_path *path, int even_odd, fz_matrix ctm,
842 fz_colorspace *colorspace, const float *color, float alpha, fz_color_params color_params)
843 {
844 js_State *J = ((js_device*)dev)->J;
845 if (js_try(J))
846 rethrow_as_fz(J);
847 if (js_hasproperty(J, -1, "fillPath")) {
848 js_copy(J, -2);
849 ffi_pushpath(J, path);
850 js_pushboolean(J, even_odd);
851 ffi_pushmatrix(J, ctm);
852 ffi_pushcolor(J, colorspace, color, alpha);
853 ffi_pushcolorparams(J, color_params);
854 js_call(J, 7);
855 js_pop(J, 1);
856 }
857 js_endtry(J);
858 }
859
860 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)861 js_dev_clip_path(fz_context *ctx, fz_device *dev, const fz_path *path, int even_odd, fz_matrix ctm,
862 fz_rect scissor)
863 {
864 js_State *J = ((js_device*)dev)->J;
865 if (js_try(J))
866 rethrow_as_fz(J);
867 if (js_hasproperty(J, -1, "clipPath")) {
868 js_copy(J, -2);
869 ffi_pushpath(J, path);
870 js_pushboolean(J, even_odd);
871 ffi_pushmatrix(J, ctm);
872 js_call(J, 3);
873 js_pop(J, 1);
874 }
875 js_endtry(J);
876 }
877
878 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,fz_color_params color_params)879 js_dev_stroke_path(fz_context *ctx, fz_device *dev, const fz_path *path,
880 const fz_stroke_state *stroke, fz_matrix ctm,
881 fz_colorspace *colorspace, const float *color, float alpha, fz_color_params color_params)
882 {
883 js_State *J = ((js_device*)dev)->J;
884 if (js_try(J))
885 rethrow_as_fz(J);
886 if (js_hasproperty(J, -1, "strokePath")) {
887 js_copy(J, -2);
888 ffi_pushpath(J, path);
889 ffi_pushstroke(J, stroke);
890 ffi_pushmatrix(J, ctm);
891 ffi_pushcolor(J, colorspace, color, alpha);
892 ffi_pushcolorparams(J, color_params);
893 js_call(J, 7);
894 js_pop(J, 1);
895 }
896 js_endtry(J);
897 }
898
899 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)900 js_dev_clip_stroke_path(fz_context *ctx, fz_device *dev, const fz_path *path, const fz_stroke_state *stroke,
901 fz_matrix ctm, fz_rect scissor)
902 {
903 js_State *J = ((js_device*)dev)->J;
904 if (js_try(J))
905 rethrow_as_fz(J);
906 if (js_hasproperty(J, -1, "clipStrokePath")) {
907 js_copy(J, -2);
908 ffi_pushpath(J, path);
909 ffi_pushstroke(J, stroke);
910 ffi_pushmatrix(J, ctm);
911 js_call(J, 3);
912 js_pop(J, 1);
913 }
914 js_endtry(J);
915 }
916
917 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,fz_color_params color_params)918 js_dev_fill_text(fz_context *ctx, fz_device *dev, const fz_text *text, fz_matrix ctm,
919 fz_colorspace *colorspace, const float *color, float alpha, fz_color_params color_params)
920 {
921 js_State *J = ((js_device*)dev)->J;
922 if (js_try(J))
923 rethrow_as_fz(J);
924 if (js_hasproperty(J, -1, "fillText")) {
925 js_copy(J, -2);
926 ffi_pushtext(J, text);
927 ffi_pushmatrix(J, ctm);
928 ffi_pushcolor(J, colorspace, color, alpha);
929 ffi_pushcolorparams(J, color_params);
930 js_call(J, 6);
931 js_pop(J, 1);
932 }
933 js_endtry(J);
934 }
935
936 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,fz_color_params color_params)937 js_dev_stroke_text(fz_context *ctx, fz_device *dev, const fz_text *text, const fz_stroke_state *stroke,
938 fz_matrix ctm, fz_colorspace *colorspace, const float *color, float alpha, fz_color_params color_params)
939 {
940 js_State *J = ((js_device*)dev)->J;
941 if (js_try(J))
942 rethrow_as_fz(J);
943 if (js_hasproperty(J, -1, "strokeText")) {
944 js_copy(J, -2);
945 ffi_pushtext(J, text);
946 ffi_pushstroke(J, stroke);
947 ffi_pushmatrix(J, ctm);
948 ffi_pushcolor(J, colorspace, color, alpha);
949 ffi_pushcolorparams(J, color_params);
950 js_call(J, 7);
951 js_pop(J, 1);
952 }
953 js_endtry(J);
954 }
955
956 static void
js_dev_clip_text(fz_context * ctx,fz_device * dev,const fz_text * text,fz_matrix ctm,fz_rect scissor)957 js_dev_clip_text(fz_context *ctx, fz_device *dev, const fz_text *text, fz_matrix ctm, fz_rect scissor)
958 {
959 js_State *J = ((js_device*)dev)->J;
960 if (js_try(J))
961 rethrow_as_fz(J);
962 if (js_hasproperty(J, -1, "clipText")) {
963 js_copy(J, -2);
964 ffi_pushtext(J, text);
965 ffi_pushmatrix(J, ctm);
966 js_call(J, 2);
967 js_pop(J, 1);
968 }
969 js_endtry(J);
970 }
971
972 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)973 js_dev_clip_stroke_text(fz_context *ctx, fz_device *dev, const fz_text *text, const fz_stroke_state *stroke,
974 fz_matrix ctm, fz_rect scissor)
975 {
976 js_State *J = ((js_device*)dev)->J;
977 if (js_try(J))
978 rethrow_as_fz(J);
979 if (js_hasproperty(J, -1, "clipStrokeText")) {
980 js_copy(J, -2);
981 ffi_pushtext(J, text);
982 ffi_pushstroke(J, stroke);
983 ffi_pushmatrix(J, ctm);
984 js_call(J, 3);
985 js_pop(J, 1);
986 }
987 js_endtry(J);
988 }
989
990 static void
js_dev_ignore_text(fz_context * ctx,fz_device * dev,const fz_text * text,fz_matrix ctm)991 js_dev_ignore_text(fz_context *ctx, fz_device *dev, const fz_text *text, fz_matrix ctm)
992 {
993 js_State *J = ((js_device*)dev)->J;
994 if (js_try(J))
995 rethrow_as_fz(J);
996 if (js_hasproperty(J, -1, "ignoreText")) {
997 js_copy(J, -2);
998 ffi_pushtext(J, text);
999 ffi_pushmatrix(J, ctm);
1000 js_call(J, 2);
1001 js_pop(J, 1);
1002 }
1003 js_endtry(J);
1004 }
1005
1006 static void
js_dev_fill_shade(fz_context * ctx,fz_device * dev,fz_shade * shade,fz_matrix ctm,float alpha,fz_color_params color_params)1007 js_dev_fill_shade(fz_context *ctx, fz_device *dev, fz_shade *shade, fz_matrix ctm, float alpha, fz_color_params color_params)
1008 {
1009 js_State *J = ((js_device*)dev)->J;
1010 if (js_try(J))
1011 rethrow_as_fz(J);
1012 if (js_hasproperty(J, -1, "fillShade")) {
1013 js_copy(J, -2);
1014 ffi_pushshade(J, shade);
1015 ffi_pushmatrix(J, ctm);
1016 js_pushnumber(J, alpha);
1017 ffi_pushcolorparams(J, color_params);
1018 js_call(J, 4);
1019 js_pop(J, 1);
1020 }
1021 js_endtry(J);
1022 }
1023
1024 static void
js_dev_fill_image(fz_context * ctx,fz_device * dev,fz_image * image,fz_matrix ctm,float alpha,fz_color_params color_params)1025 js_dev_fill_image(fz_context *ctx, fz_device *dev, fz_image *image, fz_matrix ctm, float alpha, fz_color_params color_params)
1026 {
1027 js_State *J = ((js_device*)dev)->J;
1028 if (js_try(J))
1029 rethrow_as_fz(J);
1030 if (js_hasproperty(J, -1, "fillImage")) {
1031 js_copy(J, -2);
1032 ffi_pushimage(J, image);
1033 ffi_pushmatrix(J, ctm);
1034 js_pushnumber(J, alpha);
1035 ffi_pushcolorparams(J, color_params);
1036 js_call(J, 4);
1037 js_pop(J, 1);
1038 }
1039 js_endtry(J);
1040 }
1041
1042 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,fz_color_params color_params)1043 js_dev_fill_image_mask(fz_context *ctx, fz_device *dev, fz_image *image, fz_matrix ctm,
1044 fz_colorspace *colorspace, const float *color, float alpha, fz_color_params color_params)
1045 {
1046 js_State *J = ((js_device*)dev)->J;
1047 if (js_try(J))
1048 rethrow_as_fz(J);
1049 if (js_hasproperty(J, -1, "fillImageMask")) {
1050 js_copy(J, -2);
1051 ffi_pushimage(J, image);
1052 ffi_pushmatrix(J, ctm);
1053 ffi_pushcolor(J, colorspace, color, alpha);
1054 ffi_pushcolorparams(J, color_params);
1055 js_call(J, 6);
1056 js_pop(J, 1);
1057 }
1058 js_endtry(J);
1059 }
1060
1061 static void
js_dev_clip_image_mask(fz_context * ctx,fz_device * dev,fz_image * image,fz_matrix ctm,fz_rect scissor)1062 js_dev_clip_image_mask(fz_context *ctx, fz_device *dev, fz_image *image, fz_matrix ctm, fz_rect scissor)
1063 {
1064 js_State *J = ((js_device*)dev)->J;
1065 if (js_try(J))
1066 rethrow_as_fz(J);
1067 if (js_hasproperty(J, -1, "clipImageMask")) {
1068 js_copy(J, -2);
1069 ffi_pushimage(J, image);
1070 ffi_pushmatrix(J, ctm);
1071 js_call(J, 2);
1072 js_pop(J, 1);
1073 }
1074 js_endtry(J);
1075 }
1076
1077 static void
js_dev_pop_clip(fz_context * ctx,fz_device * dev)1078 js_dev_pop_clip(fz_context *ctx, fz_device *dev)
1079 {
1080 js_State *J = ((js_device*)dev)->J;
1081 if (js_try(J))
1082 rethrow_as_fz(J);
1083 if (js_hasproperty(J, -1, "popClip")) {
1084 js_copy(J, -2);
1085 js_call(J, 0);
1086 js_pop(J, 1);
1087 }
1088 js_endtry(J);
1089 }
1090
1091 static void
js_dev_begin_mask(fz_context * ctx,fz_device * dev,fz_rect bbox,int luminosity,fz_colorspace * colorspace,const float * color,fz_color_params color_params)1092 js_dev_begin_mask(fz_context *ctx, fz_device *dev, fz_rect bbox, int luminosity,
1093 fz_colorspace *colorspace, const float *color, fz_color_params color_params)
1094 {
1095 js_State *J = ((js_device*)dev)->J;
1096 if (js_try(J))
1097 rethrow_as_fz(J);
1098 if (js_hasproperty(J, -1, "beginMask")) {
1099 js_copy(J, -2);
1100 ffi_pushrect(J, bbox);
1101 js_pushboolean(J, luminosity);
1102 ffi_pushcolor(J, colorspace, color, 1);
1103 ffi_pushcolorparams(J, color_params);
1104 js_call(J, 6);
1105 js_pop(J, 1);
1106 }
1107 js_endtry(J);
1108 }
1109
1110 static void
js_dev_end_mask(fz_context * ctx,fz_device * dev)1111 js_dev_end_mask(fz_context *ctx, fz_device *dev)
1112 {
1113 js_State *J = ((js_device*)dev)->J;
1114 if (js_try(J))
1115 rethrow_as_fz(J);
1116 if (js_hasproperty(J, -1, "endMask")) {
1117 js_copy(J, -2);
1118 js_call(J, 0);
1119 js_pop(J, 1);
1120 }
1121 js_endtry(J);
1122 }
1123
1124 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)1125 js_dev_begin_group(fz_context *ctx, fz_device *dev, fz_rect bbox,
1126 fz_colorspace *cs, int isolated, int knockout, int blendmode, float alpha)
1127 {
1128 js_State *J = ((js_device*)dev)->J;
1129 if (js_try(J))
1130 rethrow_as_fz(J);
1131 if (js_hasproperty(J, -1, "beginGroup")) {
1132 js_copy(J, -2);
1133 ffi_pushrect(J, bbox);
1134 js_pushboolean(J, isolated);
1135 js_pushboolean(J, knockout);
1136 js_pushliteral(J, fz_blendmode_name(blendmode));
1137 js_pushnumber(J, alpha);
1138 js_call(J, 5);
1139 js_pop(J, 1);
1140 }
1141 js_endtry(J);
1142 }
1143
1144 static void
js_dev_end_group(fz_context * ctx,fz_device * dev)1145 js_dev_end_group(fz_context *ctx, fz_device *dev)
1146 {
1147 js_State *J = ((js_device*)dev)->J;
1148 if (js_try(J))
1149 rethrow_as_fz(J);
1150 if (js_hasproperty(J, -1, "endGroup")) {
1151 js_copy(J, -2);
1152 js_call(J, 0);
1153 js_pop(J, 1);
1154 }
1155 js_endtry(J);
1156 }
1157
1158 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)1159 js_dev_begin_tile(fz_context *ctx, fz_device *dev, fz_rect area, fz_rect view,
1160 float xstep, float ystep, fz_matrix ctm, int id)
1161 {
1162 js_State *J = ((js_device*)dev)->J;
1163 if (js_try(J))
1164 rethrow_as_fz(J);
1165 if (js_hasproperty(J, -1, "beginTile")) {
1166 int n;
1167 js_copy(J, -2);
1168 ffi_pushrect(J, area);
1169 ffi_pushrect(J, view);
1170 js_pushnumber(J, xstep);
1171 js_pushnumber(J, ystep);
1172 ffi_pushmatrix(J, ctm);
1173 js_pushnumber(J, id);
1174 js_call(J, 6);
1175 n = js_tointeger(J, -1);
1176 js_pop(J, 1);
1177 return n;
1178 }
1179 js_endtry(J);
1180 return 0;
1181 }
1182
1183 static void
js_dev_end_tile(fz_context * ctx,fz_device * dev)1184 js_dev_end_tile(fz_context *ctx, fz_device *dev)
1185 {
1186 js_State *J = ((js_device*)dev)->J;
1187 if (js_try(J))
1188 rethrow_as_fz(J);
1189 if (js_hasproperty(J, -1, "endTile")) {
1190 js_copy(J, -2);
1191 js_call(J, 0);
1192 js_pop(J, 1);
1193 }
1194 js_endtry(J);
1195 }
1196
1197 static void
js_dev_begin_layer(fz_context * ctx,fz_device * dev,const char * name)1198 js_dev_begin_layer(fz_context *ctx, fz_device *dev, const char *name)
1199 {
1200 js_State *J = ((js_device*)dev)->J;
1201 if (js_try(J))
1202 rethrow_as_fz(J);
1203 if (js_hasproperty(J, -1, "beginLayer")) {
1204 js_copy(J, -2);
1205 js_pushstring(J, name);
1206 js_call(J, 1);
1207 js_pop(J, 1);
1208 }
1209 js_endtry(J);
1210 }
1211
1212 static void
js_dev_end_layer(fz_context * ctx,fz_device * dev)1213 js_dev_end_layer(fz_context *ctx, fz_device *dev)
1214 {
1215 js_State *J = ((js_device*)dev)->J;
1216 if (js_try(J))
1217 rethrow_as_fz(J);
1218 if (js_hasproperty(J, -1, "endLayer")) {
1219 js_copy(J, -2);
1220 js_call(J, 0);
1221 js_pop(J, 1);
1222 }
1223 js_endtry(J);
1224 }
1225
new_js_device(fz_context * ctx,js_State * J)1226 static fz_device *new_js_device(fz_context *ctx, js_State *J)
1227 {
1228 js_device *dev = fz_new_derived_device(ctx, js_device);
1229
1230 dev->super.fill_path = js_dev_fill_path;
1231 dev->super.stroke_path = js_dev_stroke_path;
1232 dev->super.clip_path = js_dev_clip_path;
1233 dev->super.clip_stroke_path = js_dev_clip_stroke_path;
1234
1235 dev->super.fill_text = js_dev_fill_text;
1236 dev->super.stroke_text = js_dev_stroke_text;
1237 dev->super.clip_text = js_dev_clip_text;
1238 dev->super.clip_stroke_text = js_dev_clip_stroke_text;
1239 dev->super.ignore_text = js_dev_ignore_text;
1240
1241 dev->super.fill_shade = js_dev_fill_shade;
1242 dev->super.fill_image = js_dev_fill_image;
1243 dev->super.fill_image_mask = js_dev_fill_image_mask;
1244 dev->super.clip_image_mask = js_dev_clip_image_mask;
1245
1246 dev->super.pop_clip = js_dev_pop_clip;
1247
1248 dev->super.begin_mask = js_dev_begin_mask;
1249 dev->super.end_mask = js_dev_end_mask;
1250 dev->super.begin_group = js_dev_begin_group;
1251 dev->super.end_group = js_dev_end_group;
1252
1253 dev->super.begin_tile = js_dev_begin_tile;
1254 dev->super.end_tile = js_dev_end_tile;
1255
1256 dev->super.begin_layer = js_dev_begin_layer;
1257 dev->super.end_layer = js_dev_end_layer;
1258
1259 dev->J = J;
1260 return (fz_device*)dev;
1261 }
1262
1263 /* PDF operator processor */
1264
1265 #if FZ_ENABLE_PDF
1266
1267 typedef struct
1268 {
1269 pdf_processor super;
1270 js_State *J;
1271 int extgstate;
1272 } pdf_js_processor;
1273
1274 #define PROC_BEGIN(OP) \
1275 { js_State *J = ((pdf_js_processor*)proc)->J; \
1276 if (js_try(J)) \
1277 rethrow_as_fz(J); \
1278 if (js_hasproperty(J, 1, OP)) { \
1279 js_copy(J, 1);
1280
1281 #define PROC_END(N) \
1282 js_call(J, N); \
1283 js_pop(J, 1); \
1284 } \
1285 js_endtry(J); }
1286
js_proc_w(fz_context * ctx,pdf_processor * proc,float linewidth)1287 static void js_proc_w(fz_context *ctx, pdf_processor *proc, float linewidth)
1288 {
1289 if (!((pdf_js_processor*)proc)->extgstate)
1290 {
1291 PROC_BEGIN("op_w");
1292 js_pushnumber(J, linewidth);
1293 PROC_END(1);
1294 }
1295 }
1296
js_proc_j(fz_context * ctx,pdf_processor * proc,int linejoin)1297 static void js_proc_j(fz_context *ctx, pdf_processor *proc, int linejoin)
1298 {
1299 if (!((pdf_js_processor*)proc)->extgstate)
1300 {
1301 PROC_BEGIN("op_w");
1302 js_pushnumber(J, linejoin);
1303 PROC_END(1);
1304 }
1305 }
1306
js_proc_J(fz_context * ctx,pdf_processor * proc,int linecap)1307 static void js_proc_J(fz_context *ctx, pdf_processor *proc, int linecap)
1308 {
1309 if (!((pdf_js_processor*)proc)->extgstate)
1310 {
1311 PROC_BEGIN("op_J");
1312 js_pushnumber(J, linecap);
1313 PROC_END(1);
1314 }
1315 }
1316
js_proc_M(fz_context * ctx,pdf_processor * proc,float miterlimit)1317 static void js_proc_M(fz_context *ctx, pdf_processor *proc, float miterlimit)
1318 {
1319 if (!((pdf_js_processor*)proc)->extgstate)
1320 {
1321 PROC_BEGIN("op_M");
1322 js_pushnumber(J, miterlimit);
1323 PROC_END(1);
1324 }
1325 }
1326
js_proc_d(fz_context * ctx,pdf_processor * proc,pdf_obj * array,float phase)1327 static void js_proc_d(fz_context *ctx, pdf_processor *proc, pdf_obj *array, float phase)
1328 {
1329 int i, n = pdf_array_len(ctx, array);
1330 PROC_BEGIN("op_d");
1331 {
1332 js_newarray(J);
1333 for (i = 0; i < n; ++i)
1334 {
1335 /* we know the array only holds numbers and strings, so we are safe from exceptions here */
1336 js_pushnumber(J, pdf_array_get_real(ctx, array, i));
1337 js_setindex(J, -2, i);
1338 }
1339 js_pushnumber(J, phase);
1340 }
1341 PROC_END(2);
1342 }
1343
js_proc_ri(fz_context * ctx,pdf_processor * proc,const char * intent)1344 static void js_proc_ri(fz_context *ctx, pdf_processor *proc, const char *intent)
1345 {
1346 if (!((pdf_js_processor*)proc)->extgstate)
1347 {
1348 PROC_BEGIN("op_ri");
1349 js_pushstring(J, intent);
1350 PROC_END(1);
1351 }
1352 }
1353
js_proc_i(fz_context * ctx,pdf_processor * proc,float flatness)1354 static void js_proc_i(fz_context *ctx, pdf_processor *proc, float flatness)
1355 {
1356 if (!((pdf_js_processor*)proc)->extgstate)
1357 {
1358 PROC_BEGIN("op_i");
1359 js_pushnumber(J, flatness);
1360 PROC_END(1);
1361 }
1362 }
1363
js_proc_gs_begin(fz_context * ctx,pdf_processor * proc,const char * name,pdf_obj * extgstate)1364 static void js_proc_gs_begin(fz_context *ctx, pdf_processor *proc, const char *name, pdf_obj *extgstate)
1365 {
1366 ((pdf_js_processor*)proc)->extgstate = 1;
1367 PROC_BEGIN("op_gs");
1368 js_pushstring(J, name);
1369 ffi_pushobj(J, pdf_keep_obj(ctx, extgstate));
1370 PROC_END(2);
1371 }
1372
js_proc_gs_end(fz_context * ctx,pdf_processor * proc)1373 static void js_proc_gs_end(fz_context *ctx, pdf_processor *proc)
1374 {
1375 ((pdf_js_processor*)proc)->extgstate = 0;
1376 }
1377
js_proc_q(fz_context * ctx,pdf_processor * proc)1378 static void js_proc_q(fz_context *ctx, pdf_processor *proc)
1379 {
1380 PROC_BEGIN("op_q");
1381 PROC_END(0);
1382 }
1383
js_proc_Q(fz_context * ctx,pdf_processor * proc)1384 static void js_proc_Q(fz_context *ctx, pdf_processor *proc)
1385 {
1386 PROC_BEGIN("op_Q");
1387 PROC_END(0);
1388 }
1389
js_proc_cm(fz_context * ctx,pdf_processor * proc,float a,float b,float c,float d,float e,float f)1390 static void js_proc_cm(fz_context *ctx, pdf_processor *proc, float a, float b, float c, float d, float e, float f)
1391 {
1392 PROC_BEGIN("op_cm");
1393 js_pushnumber(J, a);
1394 js_pushnumber(J, b);
1395 js_pushnumber(J, c);
1396 js_pushnumber(J, d);
1397 js_pushnumber(J, e);
1398 js_pushnumber(J, f);
1399 PROC_END(6);
1400 }
1401
js_proc_m(fz_context * ctx,pdf_processor * proc,float x,float y)1402 static void js_proc_m(fz_context *ctx, pdf_processor *proc, float x, float y)
1403 {
1404 PROC_BEGIN("op_m");
1405 js_pushnumber(J, x);
1406 js_pushnumber(J, y);
1407 PROC_END(2);
1408 }
1409
js_proc_l(fz_context * ctx,pdf_processor * proc,float x,float y)1410 static void js_proc_l(fz_context *ctx, pdf_processor *proc, float x, float y)
1411 {
1412 PROC_BEGIN("op_l");
1413 js_pushnumber(J, x);
1414 js_pushnumber(J, y);
1415 PROC_END(2);
1416 }
1417
js_proc_c(fz_context * ctx,pdf_processor * proc,float x1,float y1,float x2,float y2,float x3,float y3)1418 static void js_proc_c(fz_context *ctx, pdf_processor *proc, float x1, float y1, float x2, float y2, float x3, float y3)
1419 {
1420 PROC_BEGIN("op_c");
1421 js_pushnumber(J, x1);
1422 js_pushnumber(J, y1);
1423 js_pushnumber(J, x2);
1424 js_pushnumber(J, y2);
1425 js_pushnumber(J, x3);
1426 js_pushnumber(J, y3);
1427 PROC_END(6);
1428 }
1429
js_proc_v(fz_context * ctx,pdf_processor * proc,float x2,float y2,float x3,float y3)1430 static void js_proc_v(fz_context *ctx, pdf_processor *proc, float x2, float y2, float x3, float y3)
1431 {
1432 PROC_BEGIN("op_v");
1433 js_pushnumber(J, x2);
1434 js_pushnumber(J, y2);
1435 js_pushnumber(J, x3);
1436 js_pushnumber(J, y3);
1437 PROC_END(4);
1438 }
1439
js_proc_y(fz_context * ctx,pdf_processor * proc,float x1,float y1,float x3,float y3)1440 static void js_proc_y(fz_context *ctx, pdf_processor *proc, float x1, float y1, float x3, float y3)
1441 {
1442 PROC_BEGIN("op_y");
1443 js_pushnumber(J, x1);
1444 js_pushnumber(J, y1);
1445 js_pushnumber(J, x3);
1446 js_pushnumber(J, y3);
1447 PROC_END(4);
1448 }
1449
js_proc_h(fz_context * ctx,pdf_processor * proc)1450 static void js_proc_h(fz_context *ctx, pdf_processor *proc)
1451 {
1452 PROC_BEGIN("op_h");
1453 PROC_END(0);
1454 }
1455
js_proc_re(fz_context * ctx,pdf_processor * proc,float x,float y,float w,float h)1456 static void js_proc_re(fz_context *ctx, pdf_processor *proc, float x, float y, float w, float h)
1457 {
1458 PROC_BEGIN("op_re");
1459 js_pushnumber(J, x);
1460 js_pushnumber(J, y);
1461 js_pushnumber(J, w);
1462 js_pushnumber(J, h);
1463 PROC_END(4);
1464 }
1465
js_proc_S(fz_context * ctx,pdf_processor * proc)1466 static void js_proc_S(fz_context *ctx, pdf_processor *proc)
1467 {
1468 PROC_BEGIN("op_S");
1469 PROC_END(0);
1470 }
1471
js_proc_s(fz_context * ctx,pdf_processor * proc)1472 static void js_proc_s(fz_context *ctx, pdf_processor *proc)
1473 {
1474 PROC_BEGIN("op_s");
1475 PROC_END(0);
1476 }
1477
js_proc_F(fz_context * ctx,pdf_processor * proc)1478 static void js_proc_F(fz_context *ctx, pdf_processor *proc)
1479 {
1480 PROC_BEGIN("op_F");
1481 PROC_END(0);
1482 }
1483
js_proc_f(fz_context * ctx,pdf_processor * proc)1484 static void js_proc_f(fz_context *ctx, pdf_processor *proc)
1485 {
1486 PROC_BEGIN("op_f");
1487 PROC_END(0);
1488 }
1489
js_proc_fstar(fz_context * ctx,pdf_processor * proc)1490 static void js_proc_fstar(fz_context *ctx, pdf_processor *proc)
1491 {
1492 PROC_BEGIN("op_fstar");
1493 PROC_END(0);
1494 }
1495
js_proc_B(fz_context * ctx,pdf_processor * proc)1496 static void js_proc_B(fz_context *ctx, pdf_processor *proc)
1497 {
1498 PROC_BEGIN("op_B");
1499 PROC_END(0);
1500 }
1501
js_proc_Bstar(fz_context * ctx,pdf_processor * proc)1502 static void js_proc_Bstar(fz_context *ctx, pdf_processor *proc)
1503 {
1504 PROC_BEGIN("op_Bstar");
1505 PROC_END(0);
1506 }
1507
js_proc_b(fz_context * ctx,pdf_processor * proc)1508 static void js_proc_b(fz_context *ctx, pdf_processor *proc)
1509 {
1510 PROC_BEGIN("op_b");
1511 PROC_END(0);
1512 }
1513
js_proc_bstar(fz_context * ctx,pdf_processor * proc)1514 static void js_proc_bstar(fz_context *ctx, pdf_processor *proc)
1515 {
1516 PROC_BEGIN("op_bstar");
1517 PROC_END(0);
1518 }
1519
js_proc_n(fz_context * ctx,pdf_processor * proc)1520 static void js_proc_n(fz_context *ctx, pdf_processor *proc)
1521 {
1522 PROC_BEGIN("op_n");
1523 PROC_END(0);
1524 }
1525
js_proc_W(fz_context * ctx,pdf_processor * proc)1526 static void js_proc_W(fz_context *ctx, pdf_processor *proc)
1527 {
1528 PROC_BEGIN("op_W");
1529 PROC_END(0);
1530 }
1531
js_proc_Wstar(fz_context * ctx,pdf_processor * proc)1532 static void js_proc_Wstar(fz_context *ctx, pdf_processor *proc)
1533 {
1534 PROC_BEGIN("op_Wstar");
1535 PROC_END(0);
1536 }
1537
js_proc_BT(fz_context * ctx,pdf_processor * proc)1538 static void js_proc_BT(fz_context *ctx, pdf_processor *proc)
1539 {
1540 PROC_BEGIN("op_BT");
1541 PROC_END(0);
1542 }
1543
js_proc_ET(fz_context * ctx,pdf_processor * proc)1544 static void js_proc_ET(fz_context *ctx, pdf_processor *proc)
1545 {
1546 PROC_BEGIN("op_ET");
1547 PROC_END(0);
1548 }
1549
js_proc_Tc(fz_context * ctx,pdf_processor * proc,float charspace)1550 static void js_proc_Tc(fz_context *ctx, pdf_processor *proc, float charspace)
1551 {
1552 PROC_BEGIN("op_Tc");
1553 js_pushnumber(J, charspace);
1554 PROC_END(1);
1555 }
1556
js_proc_Tw(fz_context * ctx,pdf_processor * proc,float wordspace)1557 static void js_proc_Tw(fz_context *ctx, pdf_processor *proc, float wordspace)
1558 {
1559 PROC_BEGIN("op_Tw");
1560 js_pushnumber(J, wordspace);
1561 PROC_END(1);
1562 }
1563
js_proc_Tz(fz_context * ctx,pdf_processor * proc,float scale)1564 static void js_proc_Tz(fz_context *ctx, pdf_processor *proc, float scale)
1565 {
1566 PROC_BEGIN("op_Tz");
1567 js_pushnumber(J, scale);
1568 PROC_END(1);
1569 }
1570
js_proc_TL(fz_context * ctx,pdf_processor * proc,float leading)1571 static void js_proc_TL(fz_context *ctx, pdf_processor *proc, float leading)
1572 {
1573 PROC_BEGIN("op_TL");
1574 js_pushnumber(J, leading);
1575 PROC_END(1);
1576 }
1577
js_proc_Tf(fz_context * ctx,pdf_processor * proc,const char * name,pdf_font_desc * font,float size)1578 static void js_proc_Tf(fz_context *ctx, pdf_processor *proc, const char *name, pdf_font_desc *font, float size)
1579 {
1580 if (!((pdf_js_processor*)proc)->extgstate)
1581 {
1582 PROC_BEGIN("op_Tf");
1583 js_pushstring(J, name);
1584 js_pushnumber(J, size);
1585 PROC_END(2);
1586 }
1587 }
1588
js_proc_Tr(fz_context * ctx,pdf_processor * proc,int render)1589 static void js_proc_Tr(fz_context *ctx, pdf_processor *proc, int render)
1590 {
1591 PROC_BEGIN("op_Tr");
1592 js_pushnumber(J, render);
1593 PROC_END(1);
1594 }
1595
js_proc_Ts(fz_context * ctx,pdf_processor * proc,float rise)1596 static void js_proc_Ts(fz_context *ctx, pdf_processor *proc, float rise)
1597 {
1598 PROC_BEGIN("op_Ts");
1599 js_pushnumber(J, rise);
1600 PROC_END(1);
1601 }
1602
js_proc_Td(fz_context * ctx,pdf_processor * proc,float tx,float ty)1603 static void js_proc_Td(fz_context *ctx, pdf_processor *proc, float tx, float ty)
1604 {
1605 PROC_BEGIN("op_Td");
1606 js_pushnumber(J, tx);
1607 js_pushnumber(J, ty);
1608 PROC_END(2);
1609 }
1610
js_proc_TD(fz_context * ctx,pdf_processor * proc,float tx,float ty)1611 static void js_proc_TD(fz_context *ctx, pdf_processor *proc, float tx, float ty)
1612 {
1613 PROC_BEGIN("op_TD");
1614 js_pushnumber(J, tx);
1615 js_pushnumber(J, ty);
1616 PROC_END(2);
1617 }
1618
js_proc_Tm(fz_context * ctx,pdf_processor * proc,float a,float b,float c,float d,float e,float f)1619 static void js_proc_Tm(fz_context *ctx, pdf_processor *proc, float a, float b, float c, float d, float e, float f)
1620 {
1621 PROC_BEGIN("op_Tm");
1622 js_pushnumber(J, a);
1623 js_pushnumber(J, b);
1624 js_pushnumber(J, c);
1625 js_pushnumber(J, d);
1626 js_pushnumber(J, e);
1627 js_pushnumber(J, f);
1628 PROC_END(6);
1629 }
1630
js_proc_Tstar(fz_context * ctx,pdf_processor * proc)1631 static void js_proc_Tstar(fz_context *ctx, pdf_processor *proc)
1632 {
1633 PROC_BEGIN("op_Tstar");
1634 PROC_END(0);
1635 }
1636
push_byte_string(js_State * J,unsigned char * str,size_t len)1637 static void push_byte_string(js_State *J, unsigned char *str, size_t len)
1638 {
1639 size_t i, is_ascii = 1;
1640 for (i = 0; i < len; ++i)
1641 if (str[i] == 0 || str[i] > 127)
1642 is_ascii = 0;
1643 if (is_ascii)
1644 js_pushstring(J, (char*)str);
1645 else
1646 {
1647 js_newarray(J);
1648 for (i = 0; i < len; ++i)
1649 {
1650 js_pushnumber(J, str[i]);
1651 js_setindex(J, -2, (int)i);
1652 }
1653 }
1654 }
1655
js_proc_TJ(fz_context * ctx,pdf_processor * proc,pdf_obj * array)1656 static void js_proc_TJ(fz_context *ctx, pdf_processor *proc, pdf_obj *array)
1657 {
1658 int i, n = pdf_array_len(ctx, array);
1659 pdf_obj *obj;
1660 PROC_BEGIN("op_TJ");
1661 {
1662 /* we know the array only holds numbers and strings, so we are safe from exceptions here */
1663 js_newarray(J);
1664 for (i = 0; i < n; ++i)
1665 {
1666 obj = pdf_array_get(ctx, array, i);
1667 if (pdf_is_number(ctx, obj))
1668 js_pushnumber(J, pdf_to_real(ctx, obj));
1669 else
1670 {
1671 push_byte_string(J, (unsigned char *)pdf_to_str_buf(ctx, obj), pdf_to_str_len(ctx, obj));
1672 }
1673 js_setindex(J, -2, i);
1674 }
1675 }
1676 PROC_END(1);
1677 }
1678
js_proc_Tj(fz_context * ctx,pdf_processor * proc,char * str,size_t len)1679 static void js_proc_Tj(fz_context *ctx, pdf_processor *proc, char *str, size_t len)
1680 {
1681 PROC_BEGIN("op_Tj");
1682 push_byte_string(J, (unsigned char *)str, len);
1683 PROC_END(1);
1684 }
1685
js_proc_squote(fz_context * ctx,pdf_processor * proc,char * str,size_t len)1686 static void js_proc_squote(fz_context *ctx, pdf_processor *proc, char *str, size_t len)
1687 {
1688 PROC_BEGIN("op_squote");
1689 push_byte_string(J, (unsigned char *)str, len);
1690 PROC_END(1);
1691 }
1692
js_proc_dquote(fz_context * ctx,pdf_processor * proc,float aw,float ac,char * str,size_t len)1693 static void js_proc_dquote(fz_context *ctx, pdf_processor *proc, float aw, float ac, char *str, size_t len)
1694 {
1695 PROC_BEGIN("op_dquote");
1696 js_pushnumber(J, aw);
1697 js_pushnumber(J, ac);
1698 push_byte_string(J, (unsigned char *)str, len);
1699 PROC_END(1);
1700 }
1701
js_proc_d0(fz_context * ctx,pdf_processor * proc,float wx,float wy)1702 static void js_proc_d0(fz_context *ctx, pdf_processor *proc, float wx, float wy)
1703 {
1704 PROC_BEGIN("op_d0");
1705 js_pushnumber(J, wx);
1706 js_pushnumber(J, wy);
1707 PROC_END(2);
1708 }
1709
js_proc_d1(fz_context * ctx,pdf_processor * proc,float wx,float wy,float llx,float lly,float urx,float ury)1710 static void js_proc_d1(fz_context *ctx, pdf_processor *proc,
1711 float wx, float wy, float llx, float lly, float urx, float ury)
1712 {
1713 PROC_BEGIN("op_d1");
1714 js_pushnumber(J, wx);
1715 js_pushnumber(J, wy);
1716 js_pushnumber(J, llx);
1717 js_pushnumber(J, lly);
1718 js_pushnumber(J, urx);
1719 js_pushnumber(J, ury);
1720 PROC_END(6);
1721 }
1722
js_proc_CS(fz_context * ctx,pdf_processor * proc,const char * name,fz_colorspace * cs)1723 static void js_proc_CS(fz_context *ctx, pdf_processor *proc, const char *name, fz_colorspace *cs)
1724 {
1725 PROC_BEGIN("op_CS");
1726 js_pushstring(J, name);
1727 ffi_pushcolorspace(J, cs);
1728 PROC_END(2);
1729 }
1730
js_proc_cs(fz_context * ctx,pdf_processor * proc,const char * name,fz_colorspace * cs)1731 static void js_proc_cs(fz_context *ctx, pdf_processor *proc, const char *name, fz_colorspace *cs)
1732 {
1733 PROC_BEGIN("op_cs");
1734 js_pushstring(J, name);
1735 ffi_pushcolorspace(J, cs);
1736 PROC_END(2);
1737 }
1738
js_proc_SC_pattern(fz_context * ctx,pdf_processor * proc,const char * name,pdf_pattern * pat,int n,float * color)1739 static void js_proc_SC_pattern(fz_context *ctx, pdf_processor *proc, const char *name, pdf_pattern *pat, int n, float *color)
1740 {
1741 int i;
1742 PROC_BEGIN("op_SC_pattern");
1743 js_pushstring(J, name);
1744 js_pushnumber(J, pat->id); /* TODO: pdf_obj instead! */
1745 js_newarray(J);
1746 for (i = 0; i < n; ++i)
1747 {
1748 js_pushnumber(J, color[i]);
1749 js_setindex(J, -2, i);
1750 }
1751 PROC_END(3);
1752 }
1753
js_proc_sc_pattern(fz_context * ctx,pdf_processor * proc,const char * name,pdf_pattern * pat,int n,float * color)1754 static void js_proc_sc_pattern(fz_context *ctx, pdf_processor *proc, const char *name, pdf_pattern *pat, int n, float *color)
1755 {
1756 int i;
1757 PROC_BEGIN("op_sc_pattern");
1758 js_pushstring(J, name);
1759 js_pushnumber(J, pat->id); /* TODO: pdf_obj instead! */
1760 js_newarray(J);
1761 for (i = 0; i < n; ++i)
1762 {
1763 js_pushnumber(J, color[i]);
1764 js_setindex(J, -2, i);
1765 }
1766 PROC_END(3);
1767 }
1768
js_proc_SC_shade(fz_context * ctx,pdf_processor * proc,const char * name,fz_shade * shade)1769 static void js_proc_SC_shade(fz_context *ctx, pdf_processor *proc, const char *name, fz_shade *shade)
1770 {
1771 PROC_BEGIN("op_SC_shade");
1772 js_pushstring(J, name);
1773 ffi_pushshade(J, shade);
1774 PROC_END(2);
1775 }
1776
js_proc_sc_shade(fz_context * ctx,pdf_processor * proc,const char * name,fz_shade * shade)1777 static void js_proc_sc_shade(fz_context *ctx, pdf_processor *proc, const char *name, fz_shade *shade)
1778 {
1779 PROC_BEGIN("op_sc_shade");
1780 js_pushstring(J, name);
1781 ffi_pushshade(J, shade);
1782 PROC_END(2);
1783 }
1784
js_proc_SC_color(fz_context * ctx,pdf_processor * proc,int n,float * color)1785 static void js_proc_SC_color(fz_context *ctx, pdf_processor *proc, int n, float *color)
1786 {
1787 int i;
1788 PROC_BEGIN("op_SC_color");
1789 js_newarray(J);
1790 for (i = 0; i < n; ++i)
1791 {
1792 js_pushnumber(J, color[i]);
1793 js_setindex(J, -2, i);
1794 }
1795 PROC_END(1);
1796 }
1797
js_proc_sc_color(fz_context * ctx,pdf_processor * proc,int n,float * color)1798 static void js_proc_sc_color(fz_context *ctx, pdf_processor *proc, int n, float *color)
1799 {
1800 int i;
1801 PROC_BEGIN("op_sc_color");
1802 js_newarray(J);
1803 for (i = 0; i < n; ++i)
1804 {
1805 js_pushnumber(J, color[i]);
1806 js_setindex(J, -2, i);
1807 }
1808 PROC_END(1);
1809 }
1810
js_proc_G(fz_context * ctx,pdf_processor * proc,float g)1811 static void js_proc_G(fz_context *ctx, pdf_processor *proc, float g)
1812 {
1813 PROC_BEGIN("op_G");
1814 js_pushnumber(J, g);
1815 PROC_END(1);
1816 }
1817
js_proc_g(fz_context * ctx,pdf_processor * proc,float g)1818 static void js_proc_g(fz_context *ctx, pdf_processor *proc, float g)
1819 {
1820 PROC_BEGIN("op_g");
1821 js_pushnumber(J, g);
1822 PROC_END(1);
1823 }
1824
js_proc_RG(fz_context * ctx,pdf_processor * proc,float r,float g,float b)1825 static void js_proc_RG(fz_context *ctx, pdf_processor *proc, float r, float g, float b)
1826 {
1827 PROC_BEGIN("op_RG");
1828 js_pushnumber(J, r);
1829 js_pushnumber(J, g);
1830 js_pushnumber(J, b);
1831 PROC_END(3);
1832 }
1833
js_proc_rg(fz_context * ctx,pdf_processor * proc,float r,float g,float b)1834 static void js_proc_rg(fz_context *ctx, pdf_processor *proc, float r, float g, float b)
1835 {
1836 PROC_BEGIN("op_rg");
1837 js_pushnumber(J, r);
1838 js_pushnumber(J, g);
1839 js_pushnumber(J, b);
1840 PROC_END(3);
1841 }
1842
js_proc_K(fz_context * ctx,pdf_processor * proc,float c,float m,float y,float k)1843 static void js_proc_K(fz_context *ctx, pdf_processor *proc, float c, float m, float y, float k)
1844 {
1845 PROC_BEGIN("op_K");
1846 js_pushnumber(J, c);
1847 js_pushnumber(J, m);
1848 js_pushnumber(J, y);
1849 js_pushnumber(J, k);
1850 PROC_END(4);
1851 }
1852
js_proc_k(fz_context * ctx,pdf_processor * proc,float c,float m,float y,float k)1853 static void js_proc_k(fz_context *ctx, pdf_processor *proc, float c, float m, float y, float k)
1854 {
1855 PROC_BEGIN("op_k");
1856 js_pushnumber(J, c);
1857 js_pushnumber(J, m);
1858 js_pushnumber(J, y);
1859 js_pushnumber(J, k);
1860 PROC_END(4);
1861 }
1862
js_proc_BI(fz_context * ctx,pdf_processor * proc,fz_image * img,const char * colorspace)1863 static void js_proc_BI(fz_context *ctx, pdf_processor *proc, fz_image *img, const char *colorspace)
1864 {
1865 PROC_BEGIN("op_BI");
1866 ffi_pushimage(J, img);
1867 js_pushstring(J, colorspace);
1868 PROC_END(2);
1869 }
1870
js_proc_sh(fz_context * ctx,pdf_processor * proc,const char * name,fz_shade * shade)1871 static void js_proc_sh(fz_context *ctx, pdf_processor *proc, const char *name, fz_shade *shade)
1872 {
1873 PROC_BEGIN("op_sh");
1874 js_pushstring(J, name);
1875 ffi_pushshade(J, shade);
1876 PROC_END(2);
1877 }
1878
js_proc_Do_image(fz_context * ctx,pdf_processor * proc,const char * name,fz_image * image)1879 static void js_proc_Do_image(fz_context *ctx, pdf_processor *proc, const char *name, fz_image *image)
1880 {
1881 PROC_BEGIN("op_Do_image");
1882 js_pushstring(J, name);
1883 ffi_pushimage(J, image);
1884 PROC_END(2);
1885 }
1886
js_proc_Do_form(fz_context * ctx,pdf_processor * proc,const char * name,pdf_obj * xobj,pdf_obj * page_resources)1887 static void js_proc_Do_form(fz_context *ctx, pdf_processor *proc, const char *name, pdf_obj *xobj, pdf_obj *page_resources)
1888 {
1889 PROC_BEGIN("op_Do_form");
1890 js_pushstring(J, name);
1891 ffi_pushobj(J, pdf_keep_obj(ctx, xobj));
1892 ffi_pushobj(J, pdf_keep_obj(ctx, page_resources));
1893 PROC_END(3);
1894 }
1895
js_proc_MP(fz_context * ctx,pdf_processor * proc,const char * tag)1896 static void js_proc_MP(fz_context *ctx, pdf_processor *proc, const char *tag)
1897 {
1898 PROC_BEGIN("op_MP");
1899 js_pushstring(J, tag);
1900 PROC_END(1);
1901 }
1902
js_proc_DP(fz_context * ctx,pdf_processor * proc,const char * tag,pdf_obj * raw,pdf_obj * cooked)1903 static void js_proc_DP(fz_context *ctx, pdf_processor *proc, const char *tag, pdf_obj *raw, pdf_obj *cooked)
1904 {
1905 PROC_BEGIN("op_DP");
1906 js_pushstring(J, tag);
1907 ffi_pushobj(J, pdf_keep_obj(ctx, raw));
1908 PROC_END(2);
1909 }
1910
js_proc_BMC(fz_context * ctx,pdf_processor * proc,const char * tag)1911 static void js_proc_BMC(fz_context *ctx, pdf_processor *proc, const char *tag)
1912 {
1913 PROC_BEGIN("op_BMC");
1914 js_pushstring(J, tag);
1915 PROC_END(1);
1916 }
1917
js_proc_BDC(fz_context * ctx,pdf_processor * proc,const char * tag,pdf_obj * raw,pdf_obj * cooked)1918 static void js_proc_BDC(fz_context *ctx, pdf_processor *proc, const char *tag, pdf_obj *raw, pdf_obj *cooked)
1919 {
1920 PROC_BEGIN("op_BDC");
1921 js_pushstring(J, tag);
1922 ffi_pushobj(J, pdf_keep_obj(ctx, raw));
1923 PROC_END(2);
1924 }
1925
js_proc_EMC(fz_context * ctx,pdf_processor * proc)1926 static void js_proc_EMC(fz_context *ctx, pdf_processor *proc)
1927 {
1928 PROC_BEGIN("op_EMC");
1929 PROC_END(0);
1930 }
1931
js_proc_BX(fz_context * ctx,pdf_processor * proc)1932 static void js_proc_BX(fz_context *ctx, pdf_processor *proc)
1933 {
1934 PROC_BEGIN("op_BX");
1935 PROC_END(0);
1936 }
1937
js_proc_EX(fz_context * ctx,pdf_processor * proc)1938 static void js_proc_EX(fz_context *ctx, pdf_processor *proc)
1939 {
1940 PROC_BEGIN("op_EX");
1941 PROC_END(0);
1942 }
1943
new_js_processor(fz_context * ctx,js_State * J)1944 static pdf_processor *new_js_processor(fz_context *ctx, js_State *J)
1945 {
1946 pdf_js_processor *proc = pdf_new_processor(ctx, sizeof *proc);
1947
1948 proc->super.close_processor = NULL;
1949 proc->super.drop_processor = NULL;
1950
1951 /* general graphics state */
1952 proc->super.op_w = js_proc_w;
1953 proc->super.op_j = js_proc_j;
1954 proc->super.op_J = js_proc_J;
1955 proc->super.op_M = js_proc_M;
1956 proc->super.op_d = js_proc_d;
1957 proc->super.op_ri = js_proc_ri;
1958 proc->super.op_i = js_proc_i;
1959 proc->super.op_gs_begin = js_proc_gs_begin;
1960 proc->super.op_gs_end = js_proc_gs_end;
1961
1962 /* transparency graphics state */
1963 proc->super.op_gs_BM = NULL;
1964 proc->super.op_gs_CA = NULL;
1965 proc->super.op_gs_ca = NULL;
1966 proc->super.op_gs_SMask = NULL;
1967
1968 /* special graphics state */
1969 proc->super.op_q = js_proc_q;
1970 proc->super.op_Q = js_proc_Q;
1971 proc->super.op_cm = js_proc_cm;
1972
1973 /* path construction */
1974 proc->super.op_m = js_proc_m;
1975 proc->super.op_l = js_proc_l;
1976 proc->super.op_c = js_proc_c;
1977 proc->super.op_v = js_proc_v;
1978 proc->super.op_y = js_proc_y;
1979 proc->super.op_h = js_proc_h;
1980 proc->super.op_re = js_proc_re;
1981
1982 /* path painting */
1983 proc->super.op_S = js_proc_S;
1984 proc->super.op_s = js_proc_s;
1985 proc->super.op_F = js_proc_F;
1986 proc->super.op_f = js_proc_f;
1987 proc->super.op_fstar = js_proc_fstar;
1988 proc->super.op_B = js_proc_B;
1989 proc->super.op_Bstar = js_proc_Bstar;
1990 proc->super.op_b = js_proc_b;
1991 proc->super.op_bstar = js_proc_bstar;
1992 proc->super.op_n = js_proc_n;
1993
1994 /* clipping paths */
1995 proc->super.op_W = js_proc_W;
1996 proc->super.op_Wstar = js_proc_Wstar;
1997
1998 /* text objects */
1999 proc->super.op_BT = js_proc_BT;
2000 proc->super.op_ET = js_proc_ET;
2001
2002 /* text state */
2003 proc->super.op_Tc = js_proc_Tc;
2004 proc->super.op_Tw = js_proc_Tw;
2005 proc->super.op_Tz = js_proc_Tz;
2006 proc->super.op_TL = js_proc_TL;
2007 proc->super.op_Tf = js_proc_Tf;
2008 proc->super.op_Tr = js_proc_Tr;
2009 proc->super.op_Ts = js_proc_Ts;
2010
2011 /* text positioning */
2012 proc->super.op_Td = js_proc_Td;
2013 proc->super.op_TD = js_proc_TD;
2014 proc->super.op_Tm = js_proc_Tm;
2015 proc->super.op_Tstar = js_proc_Tstar;
2016
2017 /* text showing */
2018 proc->super.op_TJ = js_proc_TJ;
2019 proc->super.op_Tj = js_proc_Tj;
2020 proc->super.op_squote = js_proc_squote;
2021 proc->super.op_dquote = js_proc_dquote;
2022
2023 /* type 3 fonts */
2024 proc->super.op_d0 = js_proc_d0;
2025 proc->super.op_d1 = js_proc_d1;
2026
2027 /* color */
2028 proc->super.op_CS = js_proc_CS;
2029 proc->super.op_cs = js_proc_cs;
2030 proc->super.op_SC_color = js_proc_SC_color;
2031 proc->super.op_sc_color = js_proc_sc_color;
2032 proc->super.op_SC_pattern = js_proc_SC_pattern;
2033 proc->super.op_sc_pattern = js_proc_sc_pattern;
2034 proc->super.op_SC_shade = js_proc_SC_shade;
2035 proc->super.op_sc_shade = js_proc_sc_shade;
2036
2037 proc->super.op_G = js_proc_G;
2038 proc->super.op_g = js_proc_g;
2039 proc->super.op_RG = js_proc_RG;
2040 proc->super.op_rg = js_proc_rg;
2041 proc->super.op_K = js_proc_K;
2042 proc->super.op_k = js_proc_k;
2043
2044 /* shadings, images, xobjects */
2045 proc->super.op_BI = js_proc_BI;
2046 proc->super.op_sh = js_proc_sh;
2047 proc->super.op_Do_image = js_proc_Do_image;
2048 proc->super.op_Do_form = js_proc_Do_form;
2049
2050 /* marked content */
2051 proc->super.op_MP = js_proc_MP;
2052 proc->super.op_DP = js_proc_DP;
2053 proc->super.op_BMC = js_proc_BMC;
2054 proc->super.op_BDC = js_proc_BDC;
2055 proc->super.op_EMC = js_proc_EMC;
2056
2057 /* compatibility */
2058 proc->super.op_BX = js_proc_BX;
2059 proc->super.op_EX = js_proc_EX;
2060
2061 /* extgstate */
2062 proc->super.op_gs_OP = NULL;
2063 proc->super.op_gs_op = NULL;
2064 proc->super.op_gs_OPM = NULL;
2065 proc->super.op_gs_UseBlackPtComp = NULL;
2066
2067 proc->J = J;
2068
2069 return (pdf_processor*)proc;
2070 }
2071
2072 #endif /* FZ_ENABLE_PDF */
2073
2074 /* device calling into c from js */
2075
ffi_Device_close(js_State * J)2076 static void ffi_Device_close(js_State *J)
2077 {
2078 fz_context *ctx = js_getcontext(J);
2079 fz_device *dev = js_touserdata(J, 0, "fz_device");
2080 fz_try(ctx)
2081 fz_close_device(ctx, dev);
2082 fz_catch(ctx)
2083 rethrow(J);
2084 }
2085
ffi_Device_fillPath(js_State * J)2086 static void ffi_Device_fillPath(js_State *J)
2087 {
2088 fz_context *ctx = js_getcontext(J);
2089 fz_device *dev = js_touserdata(J, 0, "fz_device");
2090 fz_path *path = js_touserdata(J, 1, "fz_path");
2091 int even_odd = js_toboolean(J, 2);
2092 fz_matrix ctm = ffi_tomatrix(J, 3);
2093 struct color c = ffi_tocolor(J, 4);
2094 fz_color_params color_params = ffi_tocolorparams(J, 7);
2095 fz_try(ctx)
2096 fz_fill_path(ctx, dev, path, even_odd, ctm, c.colorspace, c.color, c.alpha, color_params);
2097 fz_catch(ctx)
2098 rethrow(J);
2099 }
2100
ffi_Device_strokePath(js_State * J)2101 static void ffi_Device_strokePath(js_State *J)
2102 {
2103 fz_context *ctx = js_getcontext(J);
2104 fz_device *dev = js_touserdata(J, 0, "fz_device");
2105 fz_path *path = js_touserdata(J, 1, "fz_path");
2106 fz_stroke_state stroke = ffi_tostroke(J, 2);
2107 fz_matrix ctm = ffi_tomatrix(J, 3);
2108 struct color c = ffi_tocolor(J, 4);
2109 fz_color_params color_params = ffi_tocolorparams(J, 7);
2110 fz_try(ctx)
2111 fz_stroke_path(ctx, dev, path, &stroke, ctm, c.colorspace, c.color, c.alpha, color_params);
2112 fz_catch(ctx)
2113 rethrow(J);
2114 }
2115
ffi_Device_clipPath(js_State * J)2116 static void ffi_Device_clipPath(js_State *J)
2117 {
2118 fz_context *ctx = js_getcontext(J);
2119 fz_device *dev = js_touserdata(J, 0, "fz_device");
2120 fz_path *path = js_touserdata(J, 1, "fz_path");
2121 int even_odd = js_toboolean(J, 2);
2122 fz_matrix ctm = ffi_tomatrix(J, 3);
2123 fz_try(ctx)
2124 fz_clip_path(ctx, dev, path, even_odd, ctm, fz_infinite_rect);
2125 fz_catch(ctx)
2126 rethrow(J);
2127 }
2128
ffi_Device_clipStrokePath(js_State * J)2129 static void ffi_Device_clipStrokePath(js_State *J)
2130 {
2131 fz_context *ctx = js_getcontext(J);
2132 fz_device *dev = js_touserdata(J, 0, "fz_device");
2133 fz_path *path = js_touserdata(J, 1, "fz_path");
2134 fz_stroke_state stroke = ffi_tostroke(J, 2);
2135 fz_matrix ctm = ffi_tomatrix(J, 3);
2136 fz_try(ctx)
2137 fz_clip_stroke_path(ctx, dev, path, &stroke, ctm, fz_infinite_rect);
2138 fz_catch(ctx)
2139 rethrow(J);
2140 }
2141
ffi_Device_fillText(js_State * J)2142 static void ffi_Device_fillText(js_State *J)
2143 {
2144 fz_context *ctx = js_getcontext(J);
2145 fz_device *dev = js_touserdata(J, 0, "fz_device");
2146 fz_text *text = js_touserdata(J, 1, "fz_text");
2147 fz_matrix ctm = ffi_tomatrix(J, 2);
2148 struct color c = ffi_tocolor(J, 3);
2149 fz_color_params color_params = ffi_tocolorparams(J, 6);
2150 fz_try(ctx)
2151 fz_fill_text(ctx, dev, text, ctm, c.colorspace, c.color, c.alpha, color_params);
2152 fz_catch(ctx)
2153 rethrow(J);
2154 }
2155
ffi_Device_strokeText(js_State * J)2156 static void ffi_Device_strokeText(js_State *J)
2157 {
2158 fz_context *ctx = js_getcontext(J);
2159 fz_device *dev = js_touserdata(J, 0, "fz_device");
2160 fz_text *text = js_touserdata(J, 1, "fz_text");
2161 fz_stroke_state stroke = ffi_tostroke(J, 2);
2162 fz_matrix ctm = ffi_tomatrix(J, 3);
2163 struct color c = ffi_tocolor(J, 4);
2164 fz_color_params color_params = ffi_tocolorparams(J, 7);
2165 fz_try(ctx)
2166 fz_stroke_text(ctx, dev, text, &stroke, ctm, c.colorspace, c.color, c.alpha, color_params);
2167 fz_catch(ctx)
2168 rethrow(J);
2169 }
2170
ffi_Device_clipText(js_State * J)2171 static void ffi_Device_clipText(js_State *J)
2172 {
2173 fz_context *ctx = js_getcontext(J);
2174 fz_device *dev = js_touserdata(J, 0, "fz_device");
2175 fz_text *text = js_touserdata(J, 1, "fz_text");
2176 fz_matrix ctm = ffi_tomatrix(J, 2);
2177 fz_try(ctx)
2178 fz_clip_text(ctx, dev, text, ctm, fz_infinite_rect);
2179 fz_catch(ctx)
2180 rethrow(J);
2181 }
2182
ffi_Device_clipStrokeText(js_State * J)2183 static void ffi_Device_clipStrokeText(js_State *J)
2184 {
2185 fz_context *ctx = js_getcontext(J);
2186 fz_device *dev = js_touserdata(J, 0, "fz_device");
2187 fz_text *text = js_touserdata(J, 1, "fz_text");
2188 fz_stroke_state stroke = ffi_tostroke(J, 2);
2189 fz_matrix ctm = ffi_tomatrix(J, 3);
2190 fz_try(ctx)
2191 fz_clip_stroke_text(ctx, dev, text, &stroke, ctm, fz_infinite_rect);
2192 fz_catch(ctx)
2193 rethrow(J);
2194 }
2195
ffi_Device_ignoreText(js_State * J)2196 static void ffi_Device_ignoreText(js_State *J)
2197 {
2198 fz_context *ctx = js_getcontext(J);
2199 fz_device *dev = js_touserdata(J, 0, "fz_device");
2200 fz_text *text = js_touserdata(J, 1, "fz_text");
2201 fz_matrix ctm = ffi_tomatrix(J, 2);
2202 fz_try(ctx)
2203 fz_ignore_text(ctx, dev, text, ctm);
2204 fz_catch(ctx)
2205 rethrow(J);
2206 }
2207
ffi_Device_fillShade(js_State * J)2208 static void ffi_Device_fillShade(js_State *J)
2209 {
2210 fz_context *ctx = js_getcontext(J);
2211 fz_device *dev = js_touserdata(J, 0, "fz_device");
2212 fz_shade *shade = js_touserdata(J, 1, "fz_shade");
2213 fz_matrix ctm = ffi_tomatrix(J, 2);
2214 float alpha = js_tonumber(J, 3);
2215 fz_color_params color_params = ffi_tocolorparams(J, 4);
2216 fz_try(ctx)
2217 fz_fill_shade(ctx, dev, shade, ctm, alpha, color_params);
2218 fz_catch(ctx)
2219 rethrow(J);
2220 }
2221
ffi_Device_fillImage(js_State * J)2222 static void ffi_Device_fillImage(js_State *J)
2223 {
2224 fz_context *ctx = js_getcontext(J);
2225 fz_device *dev = js_touserdata(J, 0, "fz_device");
2226 fz_image *image = js_touserdata(J, 1, "fz_image");
2227 fz_matrix ctm = ffi_tomatrix(J, 2);
2228 float alpha = js_tonumber(J, 3);
2229 fz_color_params color_params = ffi_tocolorparams(J, 4);
2230 fz_try(ctx)
2231 fz_fill_image(ctx, dev, image, ctm, alpha, color_params);
2232 fz_catch(ctx)
2233 rethrow(J);
2234 }
2235
ffi_Device_fillImageMask(js_State * J)2236 static void ffi_Device_fillImageMask(js_State *J)
2237 {
2238 fz_context *ctx = js_getcontext(J);
2239 fz_device *dev = js_touserdata(J, 0, "fz_device");
2240 fz_image *image = js_touserdata(J, 1, "fz_image");
2241 fz_matrix ctm = ffi_tomatrix(J, 2);
2242 struct color c = ffi_tocolor(J, 3);
2243 fz_color_params color_params = ffi_tocolorparams(J, 6);
2244 fz_try(ctx)
2245 fz_fill_image_mask(ctx, dev, image, ctm, c.colorspace, c.color, c.alpha, color_params);
2246 fz_catch(ctx)
2247 rethrow(J);
2248 }
2249
ffi_Device_clipImageMask(js_State * J)2250 static void ffi_Device_clipImageMask(js_State *J)
2251 {
2252 fz_context *ctx = js_getcontext(J);
2253 fz_device *dev = js_touserdata(J, 0, "fz_device");
2254 fz_image *image = js_touserdata(J, 1, "fz_image");
2255 fz_matrix ctm = ffi_tomatrix(J, 2);
2256 fz_try(ctx)
2257 fz_clip_image_mask(ctx, dev, image, ctm, fz_infinite_rect);
2258 fz_catch(ctx)
2259 rethrow(J);
2260 }
2261
ffi_Device_popClip(js_State * J)2262 static void ffi_Device_popClip(js_State *J)
2263 {
2264 fz_context *ctx = js_getcontext(J);
2265 fz_device *dev = js_touserdata(J, 0, "fz_device");
2266 fz_try(ctx)
2267 fz_pop_clip(ctx, dev);
2268 fz_catch(ctx)
2269 rethrow(J);
2270 }
2271
ffi_Device_beginMask(js_State * J)2272 static void ffi_Device_beginMask(js_State *J)
2273 {
2274 fz_context *ctx = js_getcontext(J);
2275 fz_device *dev = js_touserdata(J, 0, "fz_device");
2276 fz_rect area = ffi_torect(J, 1);
2277 int luminosity = js_toboolean(J, 2);
2278 struct color c = ffi_tocolor(J, 3);
2279 fz_color_params color_params = ffi_tocolorparams(J, 6);
2280 fz_try(ctx)
2281 fz_begin_mask(ctx, dev, area, luminosity, c.colorspace, c.color, color_params);
2282 fz_catch(ctx)
2283 rethrow(J);
2284 }
2285
ffi_Device_endMask(js_State * J)2286 static void ffi_Device_endMask(js_State *J)
2287 {
2288 fz_context *ctx = js_getcontext(J);
2289 fz_device *dev = js_touserdata(J, 0, "fz_device");
2290 fz_try(ctx)
2291 fz_end_mask(ctx, dev);
2292 fz_catch(ctx)
2293 rethrow(J);
2294 }
2295
ffi_Device_beginGroup(js_State * J)2296 static void ffi_Device_beginGroup(js_State *J)
2297 {
2298 fz_context *ctx = js_getcontext(J);
2299 fz_device *dev = js_touserdata(J, 0, "fz_device");
2300 fz_rect area = ffi_torect(J, 1);
2301 int isolated = js_toboolean(J, 2);
2302 int knockout = js_toboolean(J, 3);
2303 int blendmode = fz_lookup_blendmode(js_tostring(J, 4));
2304 float alpha = js_tonumber(J, 5);
2305 fz_try(ctx)
2306 fz_begin_group(ctx, dev, area, NULL, isolated, knockout, blendmode, alpha);
2307 fz_catch(ctx)
2308 rethrow(J);
2309 }
2310
ffi_Device_endGroup(js_State * J)2311 static void ffi_Device_endGroup(js_State *J)
2312 {
2313 fz_context *ctx = js_getcontext(J);
2314 fz_device *dev = js_touserdata(J, 0, "fz_device");
2315 fz_try(ctx)
2316 fz_end_group(ctx, dev);
2317 fz_catch(ctx)
2318 rethrow(J);
2319 }
2320
ffi_Device_beginTile(js_State * J)2321 static void ffi_Device_beginTile(js_State *J)
2322 {
2323 fz_context *ctx = js_getcontext(J);
2324 fz_device *dev = js_touserdata(J, 0, "fz_device");
2325 fz_rect area = ffi_torect(J, 1);
2326 fz_rect view = ffi_torect(J, 2);
2327 float xstep = js_tonumber(J, 3);
2328 float ystep = js_tonumber(J, 4);
2329 fz_matrix ctm = ffi_tomatrix(J, 5);
2330 int id = js_tonumber(J, 6);
2331 int n = 0;
2332 fz_try(ctx)
2333 n = fz_begin_tile_id(ctx, dev, area, view, xstep, ystep, ctm, id);
2334 fz_catch(ctx)
2335 rethrow(J);
2336 js_pushnumber(J, n);
2337 }
2338
ffi_Device_endTile(js_State * J)2339 static void ffi_Device_endTile(js_State *J)
2340 {
2341 fz_context *ctx = js_getcontext(J);
2342 fz_device *dev = js_touserdata(J, 0, "fz_device");
2343 fz_try(ctx)
2344 fz_end_tile(ctx, dev);
2345 fz_catch(ctx)
2346 rethrow(J);
2347 }
2348
ffi_Device_beginLayer(js_State * J)2349 static void ffi_Device_beginLayer(js_State *J)
2350 {
2351 fz_context *ctx = js_getcontext(J);
2352 fz_device *dev = js_touserdata(J, 0, "fz_device");
2353 const char *name = js_tostring(J, 1);
2354 fz_try(ctx)
2355 fz_begin_layer(ctx, dev, name);
2356 fz_catch(ctx)
2357 rethrow(J);
2358 }
2359
ffi_Device_endLayer(js_State * J)2360 static void ffi_Device_endLayer(js_State *J)
2361 {
2362 fz_context *ctx = js_getcontext(J);
2363 fz_device *dev = js_touserdata(J, 0, "fz_device");
2364 fz_try(ctx)
2365 fz_end_layer(ctx, dev);
2366 fz_catch(ctx)
2367 rethrow(J);
2368 }
2369
2370 /* mupdf module */
2371
ffi_readFile(js_State * J)2372 static void ffi_readFile(js_State *J)
2373 {
2374 fz_context *ctx = js_getcontext(J);
2375 const char *filename = js_tostring(J, 1);
2376 fz_buffer *buf = NULL;
2377 fz_try(ctx)
2378 buf = fz_read_file(ctx, filename);
2379 fz_catch(ctx)
2380 rethrow(J);
2381 ffi_pushbuffer(J, buf);
2382 }
2383
ffi_setUserCSS(js_State * J)2384 static void ffi_setUserCSS(js_State *J)
2385 {
2386 fz_context *ctx = js_getcontext(J);
2387 const char *user_css = js_tostring(J, 1);
2388 int use_doc_css = js_iscoercible(J, 2) ? js_toboolean(J, 2) : 1;
2389 fz_try(ctx) {
2390 fz_set_user_css(ctx, user_css);
2391 fz_set_use_document_css(ctx, use_doc_css);
2392 } fz_catch(ctx)
2393 rethrow(J);
2394 }
2395
ffi_new_Buffer(js_State * J)2396 static void ffi_new_Buffer(js_State *J)
2397 {
2398 fz_context *ctx = js_getcontext(J);
2399 int n = js_isdefined(J, 1) ? js_tonumber(J, 1) : 0;
2400 fz_buffer *buf = NULL;
2401 fz_try(ctx)
2402 buf = fz_new_buffer(ctx, n);
2403 fz_catch(ctx)
2404 rethrow(J);
2405 ffi_pushbuffer(J, buf);
2406 }
2407
ffi_Buffer_writeByte(js_State * J)2408 static void ffi_Buffer_writeByte(js_State *J)
2409 {
2410 fz_context *ctx = js_getcontext(J);
2411 fz_buffer *buf = js_touserdata(J, 0, "fz_buffer");
2412 unsigned char val = js_tonumber(J, 1);
2413 fz_try(ctx)
2414 fz_append_byte(ctx, buf, val);
2415 fz_catch(ctx)
2416 rethrow(J);
2417 }
2418
ffi_Buffer_writeRune(js_State * J)2419 static void ffi_Buffer_writeRune(js_State *J)
2420 {
2421 fz_context *ctx = js_getcontext(J);
2422 fz_buffer *buf = js_touserdata(J, 0, "fz_buffer");
2423 int val = js_tonumber(J, 1);
2424 fz_try(ctx)
2425 fz_append_rune(ctx, buf, val);
2426 fz_catch(ctx)
2427 rethrow(J);
2428 }
2429
ffi_Buffer_write(js_State * J)2430 static void ffi_Buffer_write(js_State *J)
2431 {
2432 fz_context *ctx = js_getcontext(J);
2433 fz_buffer *buf = js_touserdata(J, 0, "fz_buffer");
2434 int i, n = js_gettop(J);
2435
2436 for (i = 1; i < n; ++i) {
2437 const char *s = js_tostring(J, i);
2438 fz_try(ctx) {
2439 if (i > 1)
2440 fz_append_byte(ctx, buf, ' ');
2441 fz_append_string(ctx, buf, s);
2442 } fz_catch(ctx)
2443 rethrow(J);
2444 }
2445 }
2446
ffi_Buffer_writeLine(js_State * J)2447 static void ffi_Buffer_writeLine(js_State *J)
2448 {
2449 fz_context *ctx = js_getcontext(J);
2450 fz_buffer *buf = js_touserdata(J, 0, "fz_buffer");
2451 ffi_Buffer_write(J);
2452 fz_try(ctx)
2453 fz_append_byte(ctx, buf, '\n');
2454 fz_catch(ctx)
2455 rethrow(J);
2456 }
2457
ffi_Buffer_writeBuffer(js_State * J)2458 static void ffi_Buffer_writeBuffer(js_State *J)
2459 {
2460 fz_context *ctx = js_getcontext(J);
2461 fz_buffer *buf = js_touserdata(J, 0, "fz_buffer");
2462 fz_buffer *cat = js_touserdata(J, 1, "fz_buffer");
2463 fz_try(ctx)
2464 fz_append_buffer(ctx, buf, cat);
2465 fz_catch(ctx)
2466 rethrow(J);
2467 }
2468
ffi_Buffer_save(js_State * J)2469 static void ffi_Buffer_save(js_State *J)
2470 {
2471 fz_context *ctx = js_getcontext(J);
2472 fz_buffer *buf = js_touserdata(J, 0, "fz_buffer");
2473 const char *filename = js_tostring(J, 1);
2474 fz_try(ctx)
2475 fz_save_buffer(ctx, buf, filename);
2476 fz_catch(ctx)
2477 rethrow(J);
2478 }
2479
ffi_new_Document(js_State * J)2480 static void ffi_new_Document(js_State *J)
2481 {
2482 fz_context *ctx = js_getcontext(J);
2483 const char *filename = js_tostring(J, 1);
2484 fz_document *doc = NULL;
2485
2486 fz_try(ctx)
2487 doc = fz_open_document(ctx, filename);
2488 fz_catch(ctx)
2489 rethrow(J);
2490
2491 ffi_pushdocument(J, doc);
2492 }
2493
ffi_Document_isPDF(js_State * J)2494 static void ffi_Document_isPDF(js_State *J)
2495 {
2496 js_pushboolean(J, js_isuserdata(J, 0, "pdf_document"));
2497 }
2498
ffi_Document_countPages(js_State * J)2499 static void ffi_Document_countPages(js_State *J)
2500 {
2501 fz_context *ctx = js_getcontext(J);
2502 fz_document *doc = ffi_todocument(J, 0);
2503 int count = 0;
2504
2505 fz_try(ctx)
2506 count = fz_count_pages(ctx, doc);
2507 fz_catch(ctx)
2508 rethrow(J);
2509
2510 js_pushnumber(J, count);
2511 }
2512
ffi_Document_loadPage(js_State * J)2513 static void ffi_Document_loadPage(js_State *J)
2514 {
2515 fz_context *ctx = js_getcontext(J);
2516 fz_document *doc = ffi_todocument(J, 0);
2517 int number = js_tointeger(J, 1);
2518 fz_page *page = NULL;
2519
2520 fz_try(ctx)
2521 page = fz_load_page(ctx, doc, number);
2522 fz_catch(ctx)
2523 rethrow(J);
2524
2525 ffi_pushpage(J, page);
2526 }
2527
ffi_Document_needsPassword(js_State * J)2528 static void ffi_Document_needsPassword(js_State *J)
2529 {
2530 fz_context *ctx = js_getcontext(J);
2531 fz_document *doc = ffi_todocument(J, 0);
2532 int b = 0;
2533
2534 fz_try(ctx)
2535 b = fz_needs_password(ctx, doc);
2536 fz_catch(ctx)
2537 rethrow(J);
2538
2539 js_pushboolean(J, b);
2540 }
2541
ffi_Document_authenticatePassword(js_State * J)2542 static void ffi_Document_authenticatePassword(js_State *J)
2543 {
2544 fz_context *ctx = js_getcontext(J);
2545 fz_document *doc = ffi_todocument(J, 0);
2546 const char *password = js_tostring(J, 1);
2547 int b = 0;
2548
2549 fz_try(ctx)
2550 b = fz_authenticate_password(ctx, doc, password);
2551 fz_catch(ctx)
2552 rethrow(J);
2553
2554 js_pushboolean(J, b);
2555 }
2556
ffi_Document_hasPermission(js_State * J)2557 static void ffi_Document_hasPermission(js_State *J)
2558 {
2559 fz_context *ctx = js_getcontext(J);
2560 fz_document *doc = ffi_todocument(J, 0);
2561 const char *perm = js_tostring(J, 1);
2562 int flag = 0;
2563 int result = 0;
2564
2565 if (!strcmp(perm, "print")) flag = FZ_PERMISSION_PRINT;
2566 else if (!strcmp(perm, "annotate")) flag = FZ_PERMISSION_ANNOTATE;
2567 else if (!strcmp(perm, "edit")) flag = FZ_PERMISSION_EDIT;
2568 else if (!strcmp(perm, "copy")) flag = FZ_PERMISSION_COPY;
2569 else js_error(J, "invalid permission name");
2570
2571 fz_try(ctx)
2572 result = fz_has_permission(ctx, doc, flag);
2573 fz_catch(ctx)
2574 rethrow(J);
2575
2576 js_pushboolean(J, result);
2577 }
2578
ffi_Document_getMetaData(js_State * J)2579 static void ffi_Document_getMetaData(js_State *J)
2580 {
2581 fz_context *ctx = js_getcontext(J);
2582 fz_document *doc = ffi_todocument(J, 0);
2583 const char *key = js_tostring(J, 1);
2584 char info[256];
2585 int found;
2586
2587 fz_try(ctx)
2588 found = fz_lookup_metadata(ctx, doc, key, info, sizeof info);
2589 fz_catch(ctx)
2590 rethrow(J);
2591
2592 if (found)
2593 js_pushstring(J, info);
2594 else
2595 js_pushundefined(J);
2596 }
2597
ffi_Document_isReflowable(js_State * J)2598 static void ffi_Document_isReflowable(js_State *J)
2599 {
2600 fz_context *ctx = js_getcontext(J);
2601 fz_document *doc = ffi_todocument(J, 0);
2602 int is_reflowable = 0;
2603
2604 fz_try(ctx)
2605 is_reflowable = fz_is_document_reflowable(ctx, doc);
2606 fz_catch(ctx)
2607 rethrow(J);
2608
2609 js_pushboolean(J, is_reflowable);
2610 }
2611
ffi_Document_layout(js_State * J)2612 static void ffi_Document_layout(js_State *J)
2613 {
2614 fz_context *ctx = js_getcontext(J);
2615 fz_document *doc = ffi_todocument(J, 0);
2616 float w = js_tonumber(J, 1);
2617 float h = js_tonumber(J, 2);
2618 float em = js_tonumber(J, 3);
2619
2620 fz_try(ctx)
2621 fz_layout_document(ctx, doc, w, h, em);
2622 fz_catch(ctx)
2623 rethrow(J);
2624 }
2625
to_outline(js_State * J,fz_outline * outline)2626 static void to_outline(js_State *J, fz_outline *outline)
2627 {
2628 int i = 0;
2629 js_newarray(J);
2630 while (outline) {
2631 js_newobject(J);
2632
2633 if (outline->title)
2634 js_pushstring(J, outline->title);
2635 else
2636 js_pushundefined(J);
2637 js_setproperty(J, -2, "title");
2638
2639 if (outline->uri)
2640 js_pushstring(J, outline->uri);
2641 else
2642 js_pushundefined(J);
2643 js_setproperty(J, -2, "uri");
2644
2645 if (outline->page >= 0)
2646 js_pushnumber(J, outline->page);
2647 else
2648 js_pushundefined(J);
2649 js_setproperty(J, -2, "page");
2650
2651 if (outline->down) {
2652 to_outline(J, outline->down);
2653 js_setproperty(J, -2, "down");
2654 }
2655
2656 js_setindex(J, -2, i++);
2657 outline = outline->next;
2658 }
2659 }
2660
ffi_Document_loadOutline(js_State * J)2661 static void ffi_Document_loadOutline(js_State *J)
2662 {
2663 fz_context *ctx = js_getcontext(J);
2664 fz_document *doc = ffi_todocument(J, 0);
2665 fz_outline *outline = NULL;
2666
2667 fz_try(ctx)
2668 outline = fz_load_outline(ctx, doc);
2669 fz_catch(ctx)
2670 rethrow(J);
2671
2672 to_outline(J, outline);
2673
2674 fz_drop_outline(ctx, outline);
2675 }
2676
ffi_Page_isPDF(js_State * J)2677 static void ffi_Page_isPDF(js_State *J)
2678 {
2679 js_pushboolean(J, js_isuserdata(J, 0, "pdf_page"));
2680 }
2681
ffi_Page_bound(js_State * J)2682 static void ffi_Page_bound(js_State *J)
2683 {
2684 fz_context *ctx = js_getcontext(J);
2685 fz_page *page = ffi_topage(J, 0);
2686 fz_rect bounds;
2687
2688 fz_try(ctx)
2689 bounds = fz_bound_page(ctx, page);
2690 fz_catch(ctx)
2691 rethrow(J);
2692
2693 ffi_pushrect(J, bounds);
2694 }
2695
ffi_Page_run(js_State * J)2696 static void ffi_Page_run(js_State *J)
2697 {
2698 fz_context *ctx = js_getcontext(J);
2699 fz_page *page = ffi_topage(J, 0);
2700 fz_device *device = NULL;
2701 fz_matrix ctm = ffi_tomatrix(J, 2);
2702 int no_annots = js_isdefined(J, 3) ? js_toboolean(J, 3) : 0;
2703
2704 if (js_isuserdata(J, 1, "fz_device")) {
2705 device = js_touserdata(J, 1, "fz_device");
2706 fz_try(ctx)
2707 if (no_annots)
2708 fz_run_page_contents(ctx, page, device, ctm, NULL);
2709 else
2710 fz_run_page(ctx, page, device, ctm, NULL);
2711 fz_catch(ctx)
2712 rethrow(J);
2713 } else {
2714 device = new_js_device(ctx, J);
2715 js_copy(J, 1); /* put the js device on the top so the callbacks know where to get it */
2716 fz_try(ctx) {
2717 if (no_annots)
2718 fz_run_page_contents(ctx, page, device, ctm, NULL);
2719 else
2720 fz_run_page(ctx, page, device, ctm, NULL);
2721 fz_close_device(ctx, device);
2722 }
2723 fz_always(ctx)
2724 fz_drop_device(ctx, device);
2725 fz_catch(ctx)
2726 rethrow(J);
2727 }
2728 }
2729
ffi_Page_toDisplayList(js_State * J)2730 static void ffi_Page_toDisplayList(js_State *J)
2731 {
2732 fz_context *ctx = js_getcontext(J);
2733 fz_page *page = ffi_topage(J, 0);
2734 int no_annots = js_isdefined(J, 1) ? js_toboolean(J, 1) : 0;
2735 fz_display_list *list = NULL;
2736
2737 fz_try(ctx)
2738 if (no_annots)
2739 list = fz_new_display_list_from_page_contents(ctx, page);
2740 else
2741 list = fz_new_display_list_from_page(ctx, page);
2742 fz_catch(ctx)
2743 rethrow(J);
2744
2745 js_getregistry(J, "fz_display_list");
2746 js_newuserdata(J, "fz_display_list", list, ffi_gc_fz_display_list);
2747 }
2748
ffi_Page_toPixmap(js_State * J)2749 static void ffi_Page_toPixmap(js_State *J)
2750 {
2751 fz_context *ctx = js_getcontext(J);
2752 fz_page *page = ffi_topage(J, 0);
2753 fz_matrix ctm = ffi_tomatrix(J, 1);
2754 fz_colorspace *colorspace = js_touserdata(J, 2, "fz_colorspace");
2755 int alpha = js_toboolean(J, 3);
2756 int no_annots = js_isdefined(J, 4) ? js_toboolean(J, 4) : 0;
2757 fz_pixmap *pixmap = NULL;
2758
2759 fz_try(ctx)
2760 if (no_annots)
2761 pixmap = fz_new_pixmap_from_page_contents(ctx, page, ctm, colorspace, alpha);
2762 else
2763 pixmap = fz_new_pixmap_from_page(ctx, page, ctm, colorspace, alpha);
2764 fz_catch(ctx)
2765 rethrow(J);
2766
2767 js_getregistry(J, "fz_pixmap");
2768 js_newuserdata(J, "fz_pixmap", pixmap, ffi_gc_fz_pixmap);
2769 }
2770
ffi_Page_toStructuredText(js_State * J)2771 static void ffi_Page_toStructuredText(js_State *J)
2772 {
2773 fz_context *ctx = js_getcontext(J);
2774 fz_page *page = ffi_topage(J, 0);
2775 const char *options = js_iscoercible(J, 1) ? js_tostring(J, 1) : NULL;
2776 fz_stext_options so;
2777 fz_stext_page *text = NULL;
2778
2779 fz_try(ctx) {
2780 fz_parse_stext_options(ctx, &so, options);
2781 text = fz_new_stext_page_from_page(ctx, page, &so);
2782 }
2783 fz_catch(ctx)
2784 rethrow(J);
2785
2786 js_getregistry(J, "fz_stext_page");
2787 js_newuserdata(J, "fz_stext_page", text, ffi_gc_fz_stext_page);
2788 }
2789
ffi_Page_search(js_State * J)2790 static void ffi_Page_search(js_State *J)
2791 {
2792 fz_context *ctx = js_getcontext(J);
2793 fz_page *page = ffi_topage(J, 0);
2794 const char *needle = js_tostring(J, 1);
2795 fz_quad hits[256];
2796 int i, n = 0;
2797
2798 fz_try(ctx)
2799 n = fz_search_page(ctx, page, needle, hits, nelem(hits));
2800 fz_catch(ctx)
2801 rethrow(J);
2802
2803 js_newarray(J);
2804 for (i = 0; i < n; ++i) {
2805 ffi_pushquad(J, hits[i]);
2806 js_setindex(J, -2, i);
2807 }
2808 }
2809
ffi_Page_getLinks(js_State * J)2810 static void ffi_Page_getLinks(js_State *J)
2811 {
2812 fz_context *ctx = js_getcontext(J);
2813 fz_page *page = ffi_topage(J, 0);
2814 fz_link *link, *links = NULL;
2815 int i = 0;
2816
2817 js_newarray(J);
2818
2819 fz_try(ctx)
2820 links = fz_load_links(ctx, page);
2821 fz_catch(ctx)
2822 rethrow(J);
2823
2824 js_newarray(J);
2825 for (link = links; link; link = link->next) {
2826 js_newobject(J);
2827
2828 ffi_pushrect(J, link->rect);
2829 js_setproperty(J, -2, "bounds");
2830
2831 js_pushstring(J, link->uri);
2832 js_setproperty(J, -2, "uri");
2833
2834 js_setindex(J, -2, i++);
2835 }
2836
2837 fz_drop_link(ctx, links);
2838 }
2839
ffi_ColorSpace_getNumberOfComponents(js_State * J)2840 static void ffi_ColorSpace_getNumberOfComponents(js_State *J)
2841 {
2842 fz_colorspace *colorspace = js_touserdata(J, 0, "fz_colorspace");
2843 fz_context *ctx = js_getcontext(J);
2844 js_pushnumber(J, fz_colorspace_n(ctx, colorspace));
2845 }
2846
ffi_ColorSpace_toString(js_State * J)2847 static void ffi_ColorSpace_toString(js_State *J)
2848 {
2849 fz_colorspace *colorspace = js_touserdata(J, 0, "fz_colorspace");
2850 fz_context *ctx = js_getcontext(J);
2851 js_pushstring(J, fz_colorspace_name(ctx, colorspace));
2852 }
2853
ffi_new_Pixmap(js_State * J)2854 static void ffi_new_Pixmap(js_State *J)
2855 {
2856 fz_context *ctx = js_getcontext(J);
2857 fz_colorspace *colorspace = js_touserdata(J, 1, "fz_colorspace");
2858 fz_irect bounds = ffi_toirect(J, 2);
2859 int alpha = js_toboolean(J, 3);
2860 fz_pixmap *pixmap = NULL;
2861
2862 fz_try(ctx)
2863 pixmap = fz_new_pixmap_with_bbox(ctx, colorspace, bounds, 0, alpha);
2864 fz_catch(ctx)
2865 rethrow(J);
2866
2867 js_getregistry(J, "fz_pixmap");
2868 js_newuserdata(J, "fz_pixmap", pixmap, ffi_gc_fz_pixmap);
2869 }
2870
ffi_Pixmap_warp(js_State * J)2871 static void ffi_Pixmap_warp(js_State *J)
2872 {
2873 fz_context *ctx = js_getcontext(J);
2874 fz_pixmap *pixmap = js_touserdata(J, 0, "fz_pixmap");
2875 /* 1 = array of 8 floats for points */
2876 int w = js_tonumber(J, 2);
2877 int h = js_tonumber(J, 3);
2878 fz_pixmap *dest = NULL;
2879 fz_point points[4];
2880 int i;
2881
2882 if (w < 0 || h < 0 || !js_isarray(J, 1) || js_getlength(J, 1) != 8)
2883 js_throw(J);
2884
2885 for (i = 0; i < 8; i++)
2886 {
2887 float *f = i&1 ? &points[i>>1].y : &points[i>>1].x;
2888 js_getindex(J, 1, i);
2889 *f = js_tonumber(J, -1);
2890 js_pop(J, 1);
2891 }
2892
2893 fz_try(ctx)
2894 dest = fz_warp_pixmap(ctx, pixmap, points, w, h);
2895 fz_catch(ctx)
2896 rethrow(J);
2897
2898 js_getregistry(J, "fz_pixmap");
2899 js_newuserdata(J, "fz_pixmap", dest, ffi_gc_fz_pixmap);
2900 }
2901
ffi_Pixmap_saveAsPNG(js_State * J)2902 static void ffi_Pixmap_saveAsPNG(js_State *J)
2903 {
2904 fz_context *ctx = js_getcontext(J);
2905 fz_pixmap *pixmap = js_touserdata(J, 0, "fz_pixmap");
2906 const char *filename = js_tostring(J, 1);
2907
2908 fz_try(ctx)
2909 fz_save_pixmap_as_png(ctx, pixmap, filename);
2910 fz_catch(ctx)
2911 rethrow(J);
2912 }
2913
ffi_Pixmap_bound(js_State * J)2914 static void ffi_Pixmap_bound(js_State *J)
2915 {
2916 fz_pixmap *pixmap = js_touserdata(J, 0, "fz_pixmap");
2917 fz_rect bounds;
2918
2919 // fz_irect and fz_pixmap_bbox instead
2920 bounds.x0 = pixmap->x;
2921 bounds.y0 = pixmap->y;
2922 bounds.x1 = pixmap->x + pixmap->w;
2923 bounds.y1 = pixmap->y + pixmap->h;
2924
2925 ffi_pushrect(J, bounds);
2926 }
2927
ffi_Pixmap_clear(js_State * J)2928 static void ffi_Pixmap_clear(js_State *J)
2929 {
2930 fz_context *ctx = js_getcontext(J);
2931 fz_pixmap *pixmap = js_touserdata(J, 0, "fz_pixmap");
2932 if (js_isdefined(J, 1)) {
2933 int value = js_tonumber(J, 1);
2934 fz_try(ctx)
2935 fz_clear_pixmap_with_value(ctx, pixmap, value);
2936 fz_catch(ctx)
2937 rethrow(J);
2938 } else {
2939 fz_try(ctx)
2940 fz_clear_pixmap(ctx, pixmap);
2941 fz_catch(ctx)
2942 rethrow(J);
2943 }
2944 }
2945
ffi_Pixmap_getX(js_State * J)2946 static void ffi_Pixmap_getX(js_State *J)
2947 {
2948 fz_pixmap *pixmap = js_touserdata(J, 0, "fz_pixmap");
2949 js_pushnumber(J, pixmap->x);
2950 }
2951
ffi_Pixmap_getY(js_State * J)2952 static void ffi_Pixmap_getY(js_State *J)
2953 {
2954 fz_pixmap *pixmap = js_touserdata(J, 0, "fz_pixmap");
2955 js_pushnumber(J, pixmap->y);
2956 }
2957
ffi_Pixmap_getWidth(js_State * J)2958 static void ffi_Pixmap_getWidth(js_State *J)
2959 {
2960 fz_pixmap *pixmap = js_touserdata(J, 0, "fz_pixmap");
2961 js_pushnumber(J, pixmap->w);
2962 }
2963
ffi_Pixmap_getHeight(js_State * J)2964 static void ffi_Pixmap_getHeight(js_State *J)
2965 {
2966 fz_pixmap *pixmap = js_touserdata(J, 0, "fz_pixmap");
2967 js_pushnumber(J, pixmap->h);
2968 }
2969
ffi_Pixmap_getNumberOfComponents(js_State * J)2970 static void ffi_Pixmap_getNumberOfComponents(js_State *J)
2971 {
2972 fz_pixmap *pixmap = js_touserdata(J, 0, "fz_pixmap");
2973 js_pushnumber(J, pixmap->n);
2974 }
2975
ffi_Pixmap_getAlpha(js_State * J)2976 static void ffi_Pixmap_getAlpha(js_State *J)
2977 {
2978 fz_pixmap *pixmap = js_touserdata(J, 0, "fz_pixmap");
2979 js_pushnumber(J, pixmap->alpha);
2980 }
2981
ffi_Pixmap_getStride(js_State * J)2982 static void ffi_Pixmap_getStride(js_State *J)
2983 {
2984 fz_pixmap *pixmap = js_touserdata(J, 0, "fz_pixmap");
2985 js_pushnumber(J, pixmap->stride);
2986 }
2987
ffi_Pixmap_getSample(js_State * J)2988 static void ffi_Pixmap_getSample(js_State *J)
2989 {
2990 fz_pixmap *pixmap = js_touserdata(J, 0, "fz_pixmap");
2991 int x = js_tointeger(J, 1);
2992 int y = js_tointeger(J, 2);
2993 int k = js_tointeger(J, 3);
2994 if (x < 0 || x >= pixmap->w) js_rangeerror(J, "X out of range");
2995 if (y < 0 || y >= pixmap->h) js_rangeerror(J, "Y out of range");
2996 if (k < 0 || k >= pixmap->n) js_rangeerror(J, "N out of range");
2997 js_pushnumber(J, pixmap->samples[(x + y * pixmap->w) * pixmap->n + k]);
2998 }
2999
ffi_Pixmap_getXResolution(js_State * J)3000 static void ffi_Pixmap_getXResolution(js_State *J)
3001 {
3002 fz_pixmap *pixmap = js_touserdata(J, 0, "fz_pixmap");
3003 js_pushnumber(J, pixmap->xres);
3004 }
3005
ffi_Pixmap_getYResolution(js_State * J)3006 static void ffi_Pixmap_getYResolution(js_State *J)
3007 {
3008 fz_pixmap *pixmap = js_touserdata(J, 0, "fz_pixmap");
3009 js_pushnumber(J, pixmap->yres);
3010 }
3011
ffi_Pixmap_getColorSpace(js_State * J)3012 static void ffi_Pixmap_getColorSpace(js_State *J)
3013 {
3014 fz_pixmap *pixmap = js_touserdata(J, 0, "fz_pixmap");
3015 ffi_pushcolorspace(J, pixmap->colorspace);
3016 }
3017
ffi_new_Image(js_State * J)3018 static void ffi_new_Image(js_State *J)
3019 {
3020 fz_context *ctx = js_getcontext(J);
3021 fz_image *image = NULL;
3022
3023 if (js_isuserdata(J, 1, "fz_pixmap")) {
3024 fz_pixmap *pixmap = js_touserdata(J, 1, "fz_pixmap");
3025 fz_image *mask = NULL;
3026 if (js_isuserdata(J, 2, "fz_image"))
3027 mask = js_touserdata(J, 2, "fz_image");
3028 fz_try(ctx)
3029 image = fz_new_image_from_pixmap(ctx, pixmap, mask);
3030 fz_catch(ctx)
3031 rethrow(J);
3032 } else {
3033 const char *name = js_tostring(J, 1);
3034 fz_try(ctx)
3035 image = fz_new_image_from_file(ctx, name);
3036 fz_catch(ctx)
3037 rethrow(J);
3038 }
3039
3040 ffi_pushimage_own(J, image);
3041 }
3042
ffi_Image_getWidth(js_State * J)3043 static void ffi_Image_getWidth(js_State *J)
3044 {
3045 fz_image *image = js_touserdata(J, 0, "fz_image");
3046 js_pushnumber(J, image->w);
3047 }
3048
ffi_Image_getHeight(js_State * J)3049 static void ffi_Image_getHeight(js_State *J)
3050 {
3051 fz_image *image = js_touserdata(J, 0, "fz_image");
3052 js_pushnumber(J, image->h);
3053 }
3054
ffi_Image_getXResolution(js_State * J)3055 static void ffi_Image_getXResolution(js_State *J)
3056 {
3057 fz_image *image = js_touserdata(J, 0, "fz_image");
3058 js_pushnumber(J, image->xres);
3059 }
3060
ffi_Image_getYResolution(js_State * J)3061 static void ffi_Image_getYResolution(js_State *J)
3062 {
3063 fz_image *image = js_touserdata(J, 0, "fz_image");
3064 js_pushnumber(J, image->yres);
3065 }
3066
ffi_Image_getNumberOfComponents(js_State * J)3067 static void ffi_Image_getNumberOfComponents(js_State *J)
3068 {
3069 fz_image *image = js_touserdata(J, 0, "fz_image");
3070 js_pushnumber(J, image->n);
3071 }
3072
ffi_Image_getBitsPerComponent(js_State * J)3073 static void ffi_Image_getBitsPerComponent(js_State *J)
3074 {
3075 fz_image *image = js_touserdata(J, 0, "fz_image");
3076 js_pushnumber(J, image->bpc);
3077 }
3078
ffi_Image_getInterpolate(js_State * J)3079 static void ffi_Image_getInterpolate(js_State *J)
3080 {
3081 fz_image *image = js_touserdata(J, 0, "fz_image");
3082 js_pushboolean(J, image->interpolate);
3083 }
3084
ffi_Image_getImageMask(js_State * J)3085 static void ffi_Image_getImageMask(js_State *J)
3086 {
3087 fz_image *image = js_touserdata(J, 0, "fz_image");
3088 js_pushboolean(J, image->imagemask);
3089 }
3090
ffi_Image_getMask(js_State * J)3091 static void ffi_Image_getMask(js_State *J)
3092 {
3093 fz_image *image = js_touserdata(J, 0, "fz_image");
3094 if (image->mask)
3095 ffi_pushimage(J, image->mask);
3096 else
3097 js_pushnull(J);
3098 }
3099
ffi_Image_getColorSpace(js_State * J)3100 static void ffi_Image_getColorSpace(js_State *J)
3101 {
3102 fz_image *image = js_touserdata(J, 0, "fz_image");
3103 ffi_pushcolorspace(J, image->colorspace);
3104 }
3105
ffi_Image_toPixmap(js_State * J)3106 static void ffi_Image_toPixmap(js_State *J)
3107 {
3108 fz_context *ctx = js_getcontext(J);
3109 fz_image *image = js_touserdata(J, 0, "fz_image");
3110 fz_matrix matrix_, *matrix = NULL;
3111 fz_pixmap *pixmap = NULL;
3112
3113 if (js_isnumber(J, 1) && js_isnumber(J, 2)) {
3114 matrix_ = fz_scale(js_tonumber(J, 1), js_tonumber(J, 2));
3115 matrix = &matrix_;
3116 }
3117
3118 fz_try(ctx)
3119 pixmap = fz_get_pixmap_from_image(ctx, image, NULL, matrix, NULL, NULL);
3120 fz_catch(ctx)
3121 rethrow(J);
3122
3123 js_getregistry(J, "fz_pixmap");
3124 js_newuserdata(J, "fz_pixmap", pixmap, ffi_gc_fz_pixmap);
3125 }
3126
ffi_Shade_bound(js_State * J)3127 static void ffi_Shade_bound(js_State *J)
3128 {
3129 fz_context *ctx = js_getcontext(J);
3130 fz_shade *shade = js_touserdata(J, 0, "fz_shade");
3131 fz_matrix ctm = ffi_tomatrix(J, 1);
3132 fz_rect bounds;
3133
3134 fz_try(ctx)
3135 bounds = fz_bound_shade(ctx, shade, ctm);
3136 fz_catch(ctx)
3137 rethrow(J);
3138
3139 ffi_pushrect(J, bounds);
3140 }
3141
ffi_new_Font(js_State * J)3142 static void ffi_new_Font(js_State *J)
3143 {
3144 fz_context *ctx = js_getcontext(J);
3145 const char *name = js_tostring(J, 1);
3146 int index = js_isnumber(J, 2) ? js_tonumber(J, 2) : 0;
3147 const unsigned char *data;
3148 int size;
3149 fz_font *font = NULL;
3150
3151 fz_try(ctx) {
3152 data = fz_lookup_base14_font(ctx, name, &size);
3153 if (!data)
3154 data = fz_lookup_cjk_font_by_language(ctx, name, &size, &index);
3155 if (data)
3156 font = fz_new_font_from_memory(ctx, name, data, size, index, 0);
3157 else
3158 font = fz_new_font_from_file(ctx, name, name, index, 0);
3159 }
3160 fz_catch(ctx)
3161 rethrow(J);
3162
3163 js_getregistry(J, "fz_font");
3164 js_newuserdata(J, "fz_font", font, ffi_gc_fz_font);
3165 }
3166
ffi_Font_getName(js_State * J)3167 static void ffi_Font_getName(js_State *J)
3168 {
3169 fz_context *ctx = js_getcontext(J);
3170 fz_font *font = js_touserdata(J, 0, "fz_font");
3171 js_pushstring(J, fz_font_name(ctx, font));
3172 }
3173
ffi_Font_encodeCharacter(js_State * J)3174 static void ffi_Font_encodeCharacter(js_State *J)
3175 {
3176 fz_context *ctx = js_getcontext(J);
3177 fz_font *font = js_touserdata(J, 0, "fz_font");
3178 int unicode = js_tonumber(J, 1);
3179 int glyph = 0;
3180 fz_try(ctx)
3181 glyph = fz_encode_character(ctx, font, unicode);
3182 fz_catch(ctx)
3183 rethrow(J);
3184 js_pushnumber(J, glyph);
3185 }
3186
ffi_Font_advanceGlyph(js_State * J)3187 static void ffi_Font_advanceGlyph(js_State *J)
3188 {
3189 fz_context *ctx = js_getcontext(J);
3190 fz_font *font = js_touserdata(J, 0, "fz_font");
3191 int glyph = js_tonumber(J, 1);
3192 int wmode = js_isdefined(J, 2) ? js_toboolean(J, 2) : 0;
3193
3194 float advance = 0;
3195 fz_try(ctx)
3196 advance = fz_advance_glyph(ctx, font, glyph, wmode);
3197 fz_catch(ctx)
3198 rethrow(J);
3199 js_pushnumber(J, advance);
3200 }
3201
ffi_new_Text(js_State * J)3202 static void ffi_new_Text(js_State *J)
3203 {
3204 fz_context *ctx = js_getcontext(J);
3205 fz_text *text = NULL;
3206
3207 fz_try(ctx)
3208 text = fz_new_text(ctx);
3209 fz_catch(ctx)
3210 rethrow(J);
3211
3212 js_getregistry(J, "fz_text");
3213 js_newuserdata(J, "fz_text", text, ffi_gc_fz_text);
3214 }
3215
ffi_Text_walk(js_State * J)3216 static void ffi_Text_walk(js_State *J)
3217 {
3218 fz_text *text = js_touserdata(J, 0, "fz_text");
3219 char buf[8];
3220 fz_text_span *span;
3221 fz_matrix trm;
3222 int i;
3223
3224 for (span = text->head; span; span = span->next) {
3225 ffi_pushfont(J, span->font);
3226 trm = span->trm;
3227 if (js_hasproperty(J, 1, "beginSpan")) {
3228 js_copy(J, 1); // this
3229 js_copy(J, -3); // font
3230 ffi_pushmatrix(J, trm);
3231 js_pushboolean(J, span->wmode);
3232 js_pushnumber(J, span->bidi_level);
3233 js_pushnumber(J, span->markup_dir);
3234 js_pushstring(J, fz_string_from_text_language(buf, span->language));
3235 js_call(J, 6);
3236 js_pop(J, 1);
3237 }
3238 for (i = 0; i < span->len; ++i) {
3239 trm.e = span->items[i].x;
3240 trm.f = span->items[i].y;
3241 if (js_hasproperty(J, 1, "showGlyph")) {
3242 js_copy(J, 1); /* object for this binding */
3243 js_copy(J, -3); /* font */
3244 ffi_pushmatrix(J, trm);
3245 js_pushnumber(J, span->items[i].gid);
3246 js_pushnumber(J, span->items[i].ucs);
3247 js_pushnumber(J, span->wmode);
3248 js_pushnumber(J, span->bidi_level);
3249 js_call(J, 6);
3250 js_pop(J, 1);
3251 }
3252 }
3253 js_pop(J, 1); /* pop font object */
3254 if (js_hasproperty(J, 1, "endSpan")) {
3255 js_copy(J, 1); // this
3256 js_call(J, 0);
3257 js_pop(J, 1);
3258 }
3259 }
3260 js_pop(J, 1); /* pop showGlyph function */
3261 }
3262
ffi_Text_showGlyph(js_State * J)3263 static void ffi_Text_showGlyph(js_State *J)
3264 {
3265 fz_context *ctx = js_getcontext(J);
3266 fz_text *text = js_touserdata(J, 0, "fz_text");
3267 fz_font *font = js_touserdata(J, 1, "fz_font");
3268 fz_matrix trm = ffi_tomatrix(J, 2);
3269 int glyph = js_tointeger(J, 3);
3270 int unicode = js_tointeger(J, 4);
3271 int wmode = js_isdefined(J, 5) ? js_toboolean(J, 5) : 0;
3272
3273 fz_try(ctx)
3274 fz_show_glyph(ctx, text, font, trm, glyph, unicode, wmode, 0, FZ_BIDI_NEUTRAL, FZ_LANG_UNSET);
3275 fz_catch(ctx)
3276 rethrow(J);
3277 }
3278
ffi_Text_showString(js_State * J)3279 static void ffi_Text_showString(js_State *J)
3280 {
3281 fz_context *ctx = js_getcontext(J);
3282 fz_text *text = js_touserdata(J, 0, "fz_text");
3283 fz_font *font = js_touserdata(J, 1, "fz_font");
3284 fz_matrix trm = ffi_tomatrix(J, 2);
3285 const char *s = js_tostring(J, 3);
3286 int wmode = js_isdefined(J, 4) ? js_toboolean(J, 4) : 0;
3287
3288 fz_try(ctx)
3289 trm = fz_show_string(ctx, text, font, trm, s, wmode, 0, FZ_BIDI_NEUTRAL, FZ_LANG_UNSET);
3290 fz_catch(ctx)
3291 rethrow(J);
3292
3293 /* update matrix with new pen position */
3294 js_pushnumber(J, trm.e);
3295 js_setindex(J, 2, 4);
3296 js_pushnumber(J, trm.f);
3297 js_setindex(J, 2, 5);
3298 }
3299
ffi_new_Path(js_State * J)3300 static void ffi_new_Path(js_State *J)
3301 {
3302 fz_context *ctx = js_getcontext(J);
3303 fz_path *path = NULL;
3304
3305 fz_try(ctx)
3306 path = fz_new_path(ctx);
3307 fz_catch(ctx)
3308 rethrow(J);
3309
3310 js_getregistry(J, "fz_path");
3311 js_newuserdata(J, "fz_path", path, ffi_gc_fz_path);
3312 }
3313
ffi_Path_walk_moveTo(fz_context * ctx,void * arg,float x,float y)3314 static void ffi_Path_walk_moveTo(fz_context *ctx, void *arg, float x, float y)
3315 {
3316 js_State *J = arg;
3317 if (js_try(J))
3318 rethrow_as_fz(J);
3319 if (js_hasproperty(J, 1, "moveTo")) {
3320 js_copy(J, 1);
3321 js_pushnumber(J, x);
3322 js_pushnumber(J, y);
3323 js_call(J, 2);
3324 js_pop(J, 1);
3325 }
3326 js_endtry(J);
3327 }
3328
ffi_Path_walk_lineTo(fz_context * ctx,void * arg,float x,float y)3329 static void ffi_Path_walk_lineTo(fz_context *ctx, void *arg, float x, float y)
3330 {
3331 js_State *J = arg;
3332 if (js_try(J))
3333 rethrow_as_fz(J);
3334 if (js_hasproperty(J, 1, "lineTo")) {
3335 js_copy(J, 1);
3336 js_pushnumber(J, x);
3337 js_pushnumber(J, y);
3338 js_call(J, 2);
3339 js_pop(J, 1);
3340 }
3341 js_endtry(J);
3342 }
3343
ffi_Path_walk_curveTo(fz_context * ctx,void * arg,float x1,float y1,float x2,float y2,float x3,float y3)3344 static void ffi_Path_walk_curveTo(fz_context *ctx, void *arg,
3345 float x1, float y1, float x2, float y2, float x3, float y3)
3346 {
3347 js_State *J = arg;
3348 if (js_try(J))
3349 rethrow_as_fz(J);
3350 if (js_hasproperty(J, 1, "curveTo")) {
3351 js_copy(J, 1);
3352 js_pushnumber(J, x1);
3353 js_pushnumber(J, y1);
3354 js_pushnumber(J, x2);
3355 js_pushnumber(J, y2);
3356 js_pushnumber(J, x3);
3357 js_pushnumber(J, y3);
3358 js_call(J, 6);
3359 js_pop(J, 1);
3360 }
3361 js_endtry(J);
3362 }
3363
ffi_Path_walk_closePath(fz_context * ctx,void * arg)3364 static void ffi_Path_walk_closePath(fz_context *ctx, void *arg)
3365 {
3366 js_State *J = arg;
3367 if (js_try(J))
3368 rethrow_as_fz(J);
3369 if (js_hasproperty(J, 1, "closePath")) {
3370 js_copy(J, 1);
3371 js_call(J, 0);
3372 js_pop(J, 1);
3373 }
3374 js_endtry(J);
3375 }
3376
ffi_Path_walk(js_State * J)3377 static void ffi_Path_walk(js_State *J)
3378 {
3379 fz_context *ctx = js_getcontext(J);
3380 fz_path *path = js_touserdata(J, 0, "fz_path");
3381 fz_path_walker walker = {
3382 ffi_Path_walk_moveTo,
3383 ffi_Path_walk_lineTo,
3384 ffi_Path_walk_curveTo,
3385 ffi_Path_walk_closePath,
3386 };
3387
3388 fz_try(ctx)
3389 fz_walk_path(ctx, path, &walker, J);
3390 fz_catch(ctx)
3391 rethrow(J);
3392 }
3393
ffi_Path_moveTo(js_State * J)3394 static void ffi_Path_moveTo(js_State *J)
3395 {
3396 fz_context *ctx = js_getcontext(J);
3397 fz_path *path = js_touserdata(J, 0, "fz_path");
3398 float x = js_tonumber(J, 1);
3399 float y = js_tonumber(J, 2);
3400
3401 fz_try(ctx)
3402 fz_moveto(ctx, path, x, y);
3403 fz_catch(ctx)
3404 rethrow(J);
3405 }
3406
ffi_Path_lineTo(js_State * J)3407 static void ffi_Path_lineTo(js_State *J)
3408 {
3409 fz_context *ctx = js_getcontext(J);
3410 fz_path *path = js_touserdata(J, 0, "fz_path");
3411 float x = js_tonumber(J, 1);
3412 float y = js_tonumber(J, 2);
3413
3414 fz_try(ctx)
3415 fz_lineto(ctx, path, x, y);
3416 fz_catch(ctx)
3417 rethrow(J);
3418 }
3419
ffi_Path_curveTo(js_State * J)3420 static void ffi_Path_curveTo(js_State *J)
3421 {
3422 fz_context *ctx = js_getcontext(J);
3423 fz_path *path = js_touserdata(J, 0, "fz_path");
3424 float x1 = js_tonumber(J, 1);
3425 float y1 = js_tonumber(J, 2);
3426 float x2 = js_tonumber(J, 3);
3427 float y2 = js_tonumber(J, 4);
3428 float x3 = js_tonumber(J, 5);
3429 float y3 = js_tonumber(J, 6);
3430
3431 fz_try(ctx)
3432 fz_curveto(ctx, path, x1, y1, x2, y2, x3, y3);
3433 fz_catch(ctx)
3434 rethrow(J);
3435 }
3436
ffi_Path_curveToV(js_State * J)3437 static void ffi_Path_curveToV(js_State *J)
3438 {
3439 fz_context *ctx = js_getcontext(J);
3440 fz_path *path = js_touserdata(J, 0, "fz_path");
3441 float cx = js_tonumber(J, 1);
3442 float cy = js_tonumber(J, 2);
3443 float ex = js_tonumber(J, 3);
3444 float ey = js_tonumber(J, 4);
3445
3446 fz_try(ctx)
3447 fz_curvetov(ctx, path, cx, cy, ex, ey);
3448 fz_catch(ctx)
3449 rethrow(J);
3450 }
3451
ffi_Path_curveToY(js_State * J)3452 static void ffi_Path_curveToY(js_State *J)
3453 {
3454 fz_context *ctx = js_getcontext(J);
3455 fz_path *path = js_touserdata(J, 0, "fz_path");
3456 float cx = js_tonumber(J, 1);
3457 float cy = js_tonumber(J, 2);
3458 float ex = js_tonumber(J, 3);
3459 float ey = js_tonumber(J, 4);
3460
3461 fz_try(ctx)
3462 fz_curvetoy(ctx, path, cx, cy, ex, ey);
3463 fz_catch(ctx)
3464 rethrow(J);
3465 }
3466
ffi_Path_closePath(js_State * J)3467 static void ffi_Path_closePath(js_State *J)
3468 {
3469 fz_context *ctx = js_getcontext(J);
3470 fz_path *path = js_touserdata(J, 0, "fz_path");
3471
3472 fz_try(ctx)
3473 fz_closepath(ctx, path);
3474 fz_catch(ctx)
3475 rethrow(J);
3476 }
3477
ffi_Path_rect(js_State * J)3478 static void ffi_Path_rect(js_State *J)
3479 {
3480 fz_context *ctx = js_getcontext(J);
3481 fz_path *path = js_touserdata(J, 0, "fz_path");
3482 float x1 = js_tonumber(J, 1);
3483 float y1 = js_tonumber(J, 2);
3484 float x2 = js_tonumber(J, 3);
3485 float y2 = js_tonumber(J, 4);
3486
3487 fz_try(ctx)
3488 fz_rectto(ctx, path, x1, y1, x2, y2);
3489 fz_catch(ctx)
3490 rethrow(J);
3491 }
3492
ffi_Path_bound(js_State * J)3493 static void ffi_Path_bound(js_State *J)
3494 {
3495 fz_context *ctx = js_getcontext(J);
3496 fz_path *path = js_touserdata(J, 0, "fz_path");
3497 fz_stroke_state stroke = ffi_tostroke(J, 1);
3498 fz_matrix ctm = ffi_tomatrix(J, 2);
3499 fz_rect bounds;
3500
3501 fz_try(ctx)
3502 bounds = fz_bound_path(ctx, path, &stroke, ctm);
3503 fz_catch(ctx)
3504 rethrow(J);
3505
3506 ffi_pushrect(J, bounds);
3507 }
3508
ffi_Path_transform(js_State * J)3509 static void ffi_Path_transform(js_State *J)
3510 {
3511 fz_context *ctx = js_getcontext(J);
3512 fz_path *path = js_touserdata(J, 0, "fz_path");
3513 fz_matrix ctm = ffi_tomatrix(J, 1);
3514
3515 fz_try(ctx)
3516 fz_transform_path(ctx, path, ctm);
3517 fz_catch(ctx)
3518 rethrow(J);
3519 }
3520
ffi_new_DisplayList(js_State * J)3521 static void ffi_new_DisplayList(js_State *J)
3522 {
3523 fz_context *ctx = js_getcontext(J);
3524 fz_rect mediabox = js_iscoercible(J, 1) ? ffi_torect(J, 1) : fz_empty_rect;
3525 fz_display_list *list = NULL;
3526
3527 fz_try(ctx)
3528 list = fz_new_display_list(ctx, mediabox);
3529 fz_catch(ctx)
3530 rethrow(J);
3531
3532 js_getregistry(J, "fz_display_list");
3533 js_newuserdata(J, "fz_display_list", list, ffi_gc_fz_display_list);
3534 }
3535
ffi_DisplayList_run(js_State * J)3536 static void ffi_DisplayList_run(js_State *J)
3537 {
3538 fz_context *ctx = js_getcontext(J);
3539 fz_display_list *list = js_touserdata(J, 0, "fz_display_list");
3540 fz_device *device = NULL;
3541 fz_matrix ctm = ffi_tomatrix(J, 2);
3542
3543 if (js_isuserdata(J, 1, "fz_device")) {
3544 device = js_touserdata(J, 1, "fz_device");
3545 fz_try(ctx)
3546 fz_run_display_list(ctx, list, device, ctm, fz_infinite_rect, NULL);
3547 fz_catch(ctx)
3548 rethrow(J);
3549 } else {
3550 device = new_js_device(ctx, J);
3551 js_copy(J, 1);
3552 fz_try(ctx) {
3553 fz_run_display_list(ctx, list, device, ctm, fz_infinite_rect, NULL);
3554 fz_close_device(ctx, device);
3555 }
3556 fz_always(ctx)
3557 fz_drop_device(ctx, device);
3558 fz_catch(ctx)
3559 rethrow(J);
3560 }
3561 }
3562
ffi_DisplayList_toPixmap(js_State * J)3563 static void ffi_DisplayList_toPixmap(js_State *J)
3564 {
3565 fz_context *ctx = js_getcontext(J);
3566 fz_display_list *list = js_touserdata(J, 0, "fz_display_list");
3567 fz_matrix ctm = ffi_tomatrix(J, 1);
3568 fz_colorspace *colorspace = js_touserdata(J, 2, "fz_colorspace");
3569 int alpha = js_isdefined(J, 3) ? js_toboolean(J, 3) : 0;
3570 fz_pixmap *pixmap = NULL;
3571
3572 fz_try(ctx)
3573 pixmap = fz_new_pixmap_from_display_list(ctx, list, ctm, colorspace, alpha);
3574 fz_catch(ctx)
3575 rethrow(J);
3576
3577 js_getregistry(J, "fz_pixmap");
3578 js_newuserdata(J, "fz_pixmap", pixmap, ffi_gc_fz_pixmap);
3579 }
3580
ffi_DisplayList_toStructuredText(js_State * J)3581 static void ffi_DisplayList_toStructuredText(js_State *J)
3582 {
3583 fz_context *ctx = js_getcontext(J);
3584 fz_display_list *list = js_touserdata(J, 0, "fz_display_list");
3585 const char *options = js_iscoercible(J, 1) ? js_tostring(J, 1) : NULL;
3586 fz_stext_options so;
3587 fz_stext_page *text = NULL;
3588
3589 fz_try(ctx) {
3590 fz_parse_stext_options(ctx, &so, options);
3591 text = fz_new_stext_page_from_display_list(ctx, list, &so);
3592 }
3593 fz_catch(ctx)
3594 rethrow(J);
3595
3596 js_getregistry(J, "fz_stext_page");
3597 js_newuserdata(J, "fz_stext_page", text, ffi_gc_fz_stext_page);
3598 }
3599
ffi_DisplayList_search(js_State * J)3600 static void ffi_DisplayList_search(js_State *J)
3601 {
3602 fz_context *ctx = js_getcontext(J);
3603 fz_display_list *list = js_touserdata(J, 0, "fz_display_list");
3604 const char *needle = js_tostring(J, 1);
3605 fz_quad hits[256];
3606 int i, n = 0;
3607
3608 fz_try(ctx)
3609 n = fz_search_display_list(ctx, list, needle, hits, nelem(hits));
3610 fz_catch(ctx)
3611 rethrow(J);
3612
3613 js_newarray(J);
3614 for (i = 0; i < n; ++i) {
3615 ffi_pushquad(J, hits[i]);
3616 js_setindex(J, -2, i);
3617 }
3618 }
3619
ffi_StructuredText_walk(js_State * J)3620 static void ffi_StructuredText_walk(js_State *J)
3621 {
3622 fz_stext_page *page = js_touserdata(J, 0, "fz_stext_page");
3623 fz_stext_block *block;
3624 fz_stext_line *line;
3625 fz_stext_char *ch;
3626
3627 for (block = page->first_block; block; block = block->next)
3628 {
3629 if (block->type == FZ_STEXT_BLOCK_IMAGE)
3630 {
3631 if (js_hasproperty(J, 1, "onImageBlock"))
3632 {
3633 js_pushnull(J);
3634 ffi_pushrect(J, block->bbox);
3635 ffi_pushmatrix(J, block->u.i.transform);
3636 ffi_pushimage(J, block->u.i.image);
3637 js_call(J, 3);
3638 js_pop(J, 1);
3639 }
3640 }
3641 else if (block->type == FZ_STEXT_BLOCK_TEXT)
3642 {
3643 if (js_hasproperty(J, 1, "beginTextBlock"))
3644 {
3645 js_pushnull(J);
3646 ffi_pushrect(J, block->bbox);
3647 js_call(J, 1);
3648 js_pop(J, 1);
3649 }
3650
3651 for (line = block->u.t.first_line; line; line = line->next)
3652 {
3653 if (js_hasproperty(J, 1, "beginLine"))
3654 {
3655 js_pushnull(J);
3656 ffi_pushrect(J, line->bbox);
3657 js_pushboolean(J, line->wmode);
3658 js_call(J, 2);
3659 js_pop(J, 1);
3660 }
3661
3662 for (ch = line->first_char; ch; ch = ch->next)
3663 {
3664 if (js_hasproperty(J, 1, "onChar"))
3665 {
3666 char utf[10];
3667 js_pushnull(J);
3668 utf[fz_runetochar(utf, ch->c)] = 0;
3669 js_pushstring(J, utf);
3670 ffi_pushpoint(J, ch->origin);
3671 ffi_pushfont(J, ch->font);
3672 js_pushnumber(J, ch->size);
3673 ffi_pushquad(J, ch->quad);
3674 js_call(J, 5);
3675 js_pop(J, 1);
3676 }
3677 }
3678
3679 if (js_hasproperty(J, 1, "endLine"))
3680 {
3681 js_pushnull(J);
3682 js_call(J, 0);
3683 js_pop(J, 1);
3684 }
3685 }
3686
3687 if (js_hasproperty(J, 1, "endTextBlock"))
3688 {
3689 js_pushnull(J);
3690 js_call(J, 0);
3691 js_pop(J, 1);
3692 }
3693 }
3694 }
3695 }
3696
ffi_StructuredText_search(js_State * J)3697 static void ffi_StructuredText_search(js_State *J)
3698 {
3699 fz_context *ctx = js_getcontext(J);
3700 fz_stext_page *text = js_touserdata(J, 0, "fz_stext_page");
3701 const char *needle = js_tostring(J, 1);
3702 fz_quad hits[256];
3703 int i, n = 0;
3704
3705 fz_try(ctx)
3706 n = fz_search_stext_page(ctx, text, needle, hits, nelem(hits));
3707 fz_catch(ctx)
3708 rethrow(J);
3709
3710 js_newarray(J);
3711 for (i = 0; i < n; ++i) {
3712 ffi_pushquad(J, hits[i]);
3713 js_setindex(J, -2, i);
3714 }
3715 }
3716
ffi_StructuredText_highlight(js_State * J)3717 static void ffi_StructuredText_highlight(js_State *J)
3718 {
3719 fz_context *ctx = js_getcontext(J);
3720 fz_stext_page *text = js_touserdata(J, 0, "fz_stext_page");
3721 fz_point a = ffi_topoint(J, 1);
3722 fz_point b = ffi_topoint(J, 2);
3723 fz_quad hits[256];
3724 int i, n = 0;
3725
3726 fz_try(ctx)
3727 n = fz_highlight_selection(ctx, text, a, b, hits, nelem(hits));
3728 fz_catch(ctx)
3729 rethrow(J);
3730
3731 js_newarray(J);
3732 for (i = 0; i < n; ++i) {
3733 ffi_pushquad(J, hits[i]);
3734 js_setindex(J, -2, i);
3735 }
3736 }
3737
ffi_StructuredText_copy(js_State * J)3738 static void ffi_StructuredText_copy(js_State *J)
3739 {
3740 fz_context *ctx = js_getcontext(J);
3741 fz_stext_page *text = js_touserdata(J, 0, "fz_stext_page");
3742 fz_point a = ffi_topoint(J, 1);
3743 fz_point b = ffi_topoint(J, 2);
3744 char *s = NULL;
3745
3746 fz_try(ctx)
3747 s = fz_copy_selection(ctx, text, a, b, 0);
3748 fz_catch(ctx)
3749 rethrow(J);
3750
3751 js_pushstring(J, s);
3752
3753 fz_try(ctx)
3754 fz_free(ctx, s);
3755 fz_catch(ctx)
3756 rethrow(J);
3757 }
3758
ffi_new_DisplayListDevice(js_State * J)3759 static void ffi_new_DisplayListDevice(js_State *J)
3760 {
3761 fz_context *ctx = js_getcontext(J);
3762 fz_display_list *list = js_touserdata(J, 0, "fz_display_list");
3763 fz_device *device = NULL;
3764
3765 fz_try(ctx)
3766 device = fz_new_list_device(ctx, list);
3767 fz_catch(ctx)
3768 rethrow(J);
3769
3770 js_getregistry(J, "fz_device");
3771 js_newuserdata(J, "fz_device", device, ffi_gc_fz_device);
3772 }
3773
ffi_new_DrawDevice(js_State * J)3774 static void ffi_new_DrawDevice(js_State *J)
3775 {
3776 fz_context *ctx = js_getcontext(J);
3777 fz_matrix transform = ffi_tomatrix(J, 1);
3778 fz_pixmap *pixmap = js_touserdata(J, 2, "fz_pixmap");
3779 fz_device *device = NULL;
3780
3781 fz_try(ctx)
3782 device = fz_new_draw_device(ctx, transform, pixmap);
3783 fz_catch(ctx)
3784 rethrow(J);
3785
3786 js_getregistry(J, "fz_device");
3787 js_newuserdata(J, "fz_device", device, ffi_gc_fz_device);
3788 }
3789
ffi_new_DocumentWriter(js_State * J)3790 static void ffi_new_DocumentWriter(js_State *J)
3791 {
3792 fz_context *ctx = js_getcontext(J);
3793 const char *filename = js_tostring(J, 1);
3794 const char *format = js_iscoercible(J, 2) ? js_tostring(J, 2) : NULL;
3795 const char *options = js_iscoercible(J, 3) ? js_tostring(J, 3) : NULL;
3796 fz_document_writer *wri = NULL;
3797
3798 fz_try(ctx)
3799 wri = fz_new_document_writer(ctx, filename, format, options);
3800 fz_catch(ctx)
3801 rethrow(J);
3802
3803 js_getregistry(J, "fz_document_writer");
3804 js_newuserdata(J, "fz_document_writer", wri, ffi_gc_fz_document_writer);
3805 }
3806
ffi_DocumentWriter_beginPage(js_State * J)3807 static void ffi_DocumentWriter_beginPage(js_State *J)
3808 {
3809 fz_context *ctx = js_getcontext(J);
3810 fz_document_writer *wri = js_touserdata(J, 0, "fz_document_writer");
3811 fz_rect mediabox = ffi_torect(J, 1);
3812 fz_device *device = NULL;
3813
3814 fz_try(ctx)
3815 device = fz_begin_page(ctx, wri, mediabox);
3816 fz_catch(ctx)
3817 rethrow(J);
3818
3819 js_getregistry(J, "fz_device");
3820 js_newuserdata(J, "fz_device", fz_keep_device(ctx, device), ffi_gc_fz_device);
3821 }
3822
ffi_DocumentWriter_endPage(js_State * J)3823 static void ffi_DocumentWriter_endPage(js_State *J)
3824 {
3825 fz_context *ctx = js_getcontext(J);
3826 fz_document_writer *wri = js_touserdata(J, 0, "fz_document_writer");
3827 fz_try(ctx)
3828 fz_end_page(ctx, wri);
3829 fz_catch(ctx)
3830 rethrow(J);
3831 }
3832
ffi_DocumentWriter_close(js_State * J)3833 static void ffi_DocumentWriter_close(js_State *J)
3834 {
3835 fz_context *ctx = js_getcontext(J);
3836 fz_document_writer *wri = js_touserdata(J, 0, "fz_document_writer");
3837 fz_try(ctx)
3838 fz_close_document_writer(ctx, wri);
3839 fz_catch(ctx)
3840 rethrow(J);
3841 }
3842
3843 /* PDF specifics */
3844
3845 #if FZ_ENABLE_PDF
3846
ffi_toobj(js_State * J,pdf_document * pdf,int idx)3847 static pdf_obj *ffi_toobj(js_State *J, pdf_document *pdf, int idx)
3848 {
3849 fz_context *ctx = js_getcontext(J);
3850 pdf_obj *obj = NULL;
3851
3852 /* make sure index is absolute */
3853 if (idx < 0)
3854 idx += js_gettop(J);
3855
3856 if (js_isuserdata(J, idx, "pdf_obj"))
3857 return pdf_keep_obj(ctx, js_touserdata(J, idx, "pdf_obj"));
3858
3859 if (js_isnumber(J, idx)) {
3860 float f = js_tonumber(J, idx);
3861 fz_try(ctx)
3862 if (f == (int)f)
3863 obj = pdf_new_int(ctx, f);
3864 else
3865 obj = pdf_new_real(ctx, f);
3866 fz_catch(ctx)
3867 rethrow(J);
3868 return obj;
3869 }
3870
3871 if (js_isstring(J, idx)) {
3872 const char *s = js_tostring(J, idx);
3873 fz_try(ctx)
3874 if (s[0] == '(' && s[1] != 0)
3875 obj = pdf_new_string(ctx, s+1, strlen(s)-2);
3876 else
3877 obj = pdf_new_name(ctx, s);
3878 fz_catch(ctx)
3879 rethrow(J);
3880 return obj;
3881 }
3882
3883 if (js_isboolean(J, idx)) {
3884 return js_toboolean(J, idx) ? PDF_TRUE : PDF_FALSE;
3885 }
3886
3887 if (js_isnull(J, idx)) {
3888 return PDF_NULL;
3889 }
3890
3891 if (js_isarray(J, idx)) {
3892 int i, n = js_getlength(J, idx);
3893 pdf_obj *val;
3894 fz_try(ctx)
3895 obj = pdf_new_array(ctx, pdf, n);
3896 fz_catch(ctx)
3897 rethrow(J);
3898 if (js_try(J)) {
3899 pdf_drop_obj(ctx, obj);
3900 js_throw(J);
3901 }
3902 for (i = 0; i < n; ++i) {
3903 js_getindex(J, idx, i);
3904 val = ffi_toobj(J, pdf, -1);
3905 fz_try(ctx)
3906 pdf_array_push_drop(ctx, obj, val);
3907 fz_catch(ctx)
3908 rethrow(J);
3909 js_pop(J, 1);
3910 }
3911 js_endtry(J);
3912 return obj;
3913 }
3914
3915 if (js_isobject(J, idx)) {
3916 const char *key;
3917 pdf_obj *val;
3918 fz_try(ctx)
3919 obj = pdf_new_dict(ctx, pdf, 0);
3920 fz_catch(ctx)
3921 rethrow(J);
3922 if (js_try(J)) {
3923 pdf_drop_obj(ctx, obj);
3924 js_throw(J);
3925 }
3926 js_pushiterator(J, idx, 1);
3927 while ((key = js_nextiterator(J, -1))) {
3928 js_getproperty(J, idx, key);
3929 val = ffi_toobj(J, pdf, -1);
3930 fz_try(ctx)
3931 pdf_dict_puts_drop(ctx, obj, key, val);
3932 fz_catch(ctx)
3933 rethrow(J);
3934 js_pop(J, 1);
3935 }
3936 js_pop(J, 1);
3937 js_endtry(J);
3938 return obj;
3939 }
3940
3941 js_error(J, "cannot convert JS type to PDF");
3942 }
3943
ffi_pdf_obj_has(js_State * J,void * obj,const char * key)3944 static int ffi_pdf_obj_has(js_State *J, void *obj, const char *key)
3945 {
3946 fz_context *ctx = js_getcontext(J);
3947 pdf_obj *val = NULL;
3948 int idx, len = 0;
3949
3950 if (!strcmp(key, "length")) {
3951 fz_try(ctx)
3952 len = pdf_array_len(ctx, obj);
3953 fz_catch(ctx)
3954 rethrow(J);
3955 js_pushnumber(J, len);
3956 return 1;
3957 }
3958
3959 if (is_number(key, &idx)) {
3960 fz_try(ctx)
3961 val = pdf_array_get(ctx, obj, idx);
3962 fz_catch(ctx)
3963 rethrow(J);
3964 } else {
3965 fz_try(ctx)
3966 val = pdf_dict_gets(ctx, obj, key);
3967 fz_catch(ctx)
3968 rethrow(J);
3969 }
3970 if (val) {
3971 ffi_pushobj(J, pdf_keep_obj(ctx, val));
3972 return 1;
3973 }
3974 return 0;
3975 }
3976
ffi_pdf_obj_put(js_State * J,void * obj,const char * key)3977 static int ffi_pdf_obj_put(js_State *J, void *obj, const char *key)
3978 {
3979 fz_context *ctx = js_getcontext(J);
3980 pdf_document *pdf = NULL;
3981 pdf_obj *val;
3982 int idx;
3983
3984 fz_try(ctx)
3985 pdf = pdf_get_bound_document(ctx, obj);
3986 fz_catch(ctx)
3987 rethrow(J);
3988
3989 val = ffi_toobj(J, pdf, -1);
3990
3991 if (is_number(key, &idx)) {
3992 fz_try(ctx)
3993 pdf_array_put(ctx, obj, idx, val);
3994 fz_always(ctx)
3995 pdf_drop_obj(ctx, val);
3996 fz_catch(ctx)
3997 rethrow(J);
3998 } else {
3999 fz_try(ctx)
4000 pdf_dict_puts(ctx, obj, key, val);
4001 fz_always(ctx)
4002 pdf_drop_obj(ctx, val);
4003 fz_catch(ctx)
4004 rethrow(J);
4005 }
4006 return 1;
4007 }
4008
ffi_pdf_obj_delete(js_State * J,void * obj,const char * key)4009 static int ffi_pdf_obj_delete(js_State *J, void *obj, const char *key)
4010 {
4011 fz_context *ctx = js_getcontext(J);
4012 int idx;
4013
4014 if (is_number(key, &idx)) {
4015 fz_try(ctx)
4016 pdf_array_delete(ctx, obj, idx);
4017 fz_catch(ctx)
4018 rethrow(J);
4019 } else {
4020 fz_try(ctx)
4021 pdf_dict_dels(ctx, obj, key);
4022 fz_catch(ctx)
4023 rethrow(J);
4024 }
4025 return 1;
4026 }
4027
ffi_pushobj(js_State * J,pdf_obj * obj)4028 static void ffi_pushobj(js_State *J, pdf_obj *obj)
4029 {
4030 if (obj) {
4031 js_getregistry(J, "pdf_obj");
4032 js_newuserdatax(J, "pdf_obj", obj,
4033 ffi_pdf_obj_has, ffi_pdf_obj_put, ffi_pdf_obj_delete,
4034 ffi_gc_pdf_obj);
4035 } else {
4036 js_pushnull(J);
4037 }
4038 }
4039
ffi_new_PDFDocument(js_State * J)4040 static void ffi_new_PDFDocument(js_State *J)
4041 {
4042 fz_context *ctx = js_getcontext(J);
4043 const char *filename = js_iscoercible(J, 1) ? js_tostring(J, 1) : NULL;
4044 pdf_document *pdf = NULL;
4045
4046 fz_try(ctx)
4047 if (filename)
4048 pdf = pdf_open_document(ctx, filename);
4049 else
4050 pdf = pdf_create_document(ctx);
4051 fz_catch(ctx)
4052 rethrow(J);
4053
4054 js_getregistry(J, "pdf_document");
4055 js_newuserdata(J, "pdf_document", pdf, ffi_gc_pdf_document);
4056 }
4057
ffi_PDFDocument_getTrailer(js_State * J)4058 static void ffi_PDFDocument_getTrailer(js_State *J)
4059 {
4060 fz_context *ctx = js_getcontext(J);
4061 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
4062 pdf_obj *trailer = NULL;
4063
4064 fz_try(ctx)
4065 trailer = pdf_trailer(ctx, pdf);
4066 fz_catch(ctx)
4067 rethrow(J);
4068
4069 ffi_pushobj(J, pdf_keep_obj(ctx, trailer));
4070 }
4071
ffi_PDFDocument_countObjects(js_State * J)4072 static void ffi_PDFDocument_countObjects(js_State *J)
4073 {
4074 fz_context *ctx = js_getcontext(J);
4075 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
4076 int count = 0;
4077
4078 fz_try(ctx)
4079 count = pdf_xref_len(ctx, pdf);
4080 fz_catch(ctx)
4081 rethrow(J);
4082
4083 js_pushnumber(J, count);
4084 }
4085
ffi_PDFDocument_createObject(js_State * J)4086 static void ffi_PDFDocument_createObject(js_State *J)
4087 {
4088 fz_context *ctx = js_getcontext(J);
4089 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
4090 pdf_obj *ind = NULL;
4091
4092 fz_try(ctx)
4093 ind = pdf_new_indirect(ctx, pdf, pdf_create_object(ctx, pdf), 0);
4094 fz_catch(ctx)
4095 rethrow(J);
4096
4097 ffi_pushobj(J, ind);
4098 }
4099
ffi_PDFDocument_deleteObject(js_State * J)4100 static void ffi_PDFDocument_deleteObject(js_State *J)
4101 {
4102 fz_context *ctx = js_getcontext(J);
4103 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
4104 pdf_obj *ind = js_isuserdata(J, 1, "pdf_obj") ? js_touserdata(J, 1, "pdf_obj") : NULL;
4105 int num = ind ? pdf_to_num(ctx, ind) : js_tonumber(J, 1);
4106
4107 fz_try(ctx)
4108 pdf_delete_object(ctx, pdf, num);
4109 fz_catch(ctx)
4110 rethrow(J);
4111 }
4112
ffi_PDFDocument_addObject(js_State * J)4113 static void ffi_PDFDocument_addObject(js_State *J)
4114 {
4115 fz_context *ctx = js_getcontext(J);
4116 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
4117 pdf_obj *obj = ffi_toobj(J, pdf, 1);
4118 pdf_obj *ind = NULL;
4119
4120 fz_try(ctx)
4121 ind = pdf_add_object_drop(ctx, pdf, obj);
4122 fz_catch(ctx)
4123 rethrow(J);
4124
4125 ffi_pushobj(J, ind);
4126 }
4127
ffi_PDFDocument_addStream_imp(js_State * J,int compressed)4128 static void ffi_PDFDocument_addStream_imp(js_State *J, int compressed)
4129 {
4130 fz_context *ctx = js_getcontext(J);
4131 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
4132 fz_buffer *buf = ffi_tobuffer(J, 1); /* FIXME: leak if ffi_toobj throws */
4133 pdf_obj *obj = js_iscoercible(J, 2) ? ffi_toobj(J, pdf, 2) : NULL;
4134 pdf_obj *ind = NULL;
4135
4136 fz_try(ctx)
4137 ind = pdf_add_stream(ctx, pdf, buf, obj, compressed);
4138 fz_always(ctx) {
4139 fz_drop_buffer(ctx, buf);
4140 pdf_drop_obj(ctx, obj);
4141 } fz_catch(ctx)
4142 rethrow(J);
4143
4144 ffi_pushobj(J, ind);
4145 }
4146
ffi_PDFDocument_addStream(js_State * J)4147 static void ffi_PDFDocument_addStream(js_State *J)
4148 {
4149 ffi_PDFDocument_addStream_imp(J, 0);
4150 }
4151
ffi_PDFDocument_addRawStream(js_State * J)4152 static void ffi_PDFDocument_addRawStream(js_State *J)
4153 {
4154 ffi_PDFDocument_addStream_imp(J, 1);
4155 }
4156
ffi_PDFDocument_addImage(js_State * J)4157 static void ffi_PDFDocument_addImage(js_State *J)
4158 {
4159 fz_context *ctx = js_getcontext(J);
4160 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
4161 fz_image *image = js_touserdata(J, 1, "fz_image");
4162 pdf_obj *ind = NULL;
4163
4164 fz_try(ctx)
4165 ind = pdf_add_image(ctx, pdf, image);
4166 fz_catch(ctx)
4167 rethrow(J);
4168
4169 ffi_pushobj(J, ind);
4170 }
4171
ffi_PDFDocument_loadImage(js_State * J)4172 static void ffi_PDFDocument_loadImage(js_State *J)
4173 {
4174 fz_context *ctx = js_getcontext(J);
4175 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
4176 pdf_obj *obj = ffi_toobj(J, pdf, 1);
4177 fz_image *img = NULL;
4178
4179 fz_try(ctx)
4180 img = pdf_load_image(ctx, pdf, obj);
4181 fz_catch(ctx)
4182 rethrow(J);
4183
4184 ffi_pushimage_own(J, img);
4185 }
4186
ffi_PDFDocument_addSimpleFont(js_State * J)4187 static void ffi_PDFDocument_addSimpleFont(js_State *J)
4188 {
4189 fz_context *ctx = js_getcontext(J);
4190 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
4191 fz_font *font = js_touserdata(J, 1, "fz_font");
4192 const char *encname = js_tostring(J, 2);
4193 pdf_obj *ind = NULL;
4194 int enc = PDF_SIMPLE_ENCODING_LATIN;
4195
4196 if (!strcmp(encname, "Latin") || !strcmp(encname, "Latn"))
4197 enc = PDF_SIMPLE_ENCODING_LATIN;
4198 else if (!strcmp(encname, "Greek") || !strcmp(encname, "Grek"))
4199 enc = PDF_SIMPLE_ENCODING_GREEK;
4200 else if (!strcmp(encname, "Cyrillic") || !strcmp(encname, "Cyrl"))
4201 enc = PDF_SIMPLE_ENCODING_CYRILLIC;
4202
4203 fz_try(ctx)
4204 ind = pdf_add_simple_font(ctx, pdf, font, enc);
4205 fz_catch(ctx)
4206 rethrow(J);
4207
4208 ffi_pushobj(J, ind);
4209 }
4210
ffi_PDFDocument_addCJKFont(js_State * J)4211 static void ffi_PDFDocument_addCJKFont(js_State *J)
4212 {
4213 fz_context *ctx = js_getcontext(J);
4214 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
4215 fz_font *font = js_touserdata(J, 1, "fz_font");
4216 const char *lang = js_tostring(J, 2);
4217 const char *wm = js_tostring(J, 3);
4218 const char *ss = js_tostring(J, 4);
4219 int ordering;
4220 int wmode = 0;
4221 int serif = 1;
4222 pdf_obj *ind = NULL;
4223
4224 ordering = fz_lookup_cjk_ordering_by_language(lang);
4225
4226 if (!strcmp(wm, "V"))
4227 wmode = 1;
4228 if (!strcmp(ss, "sans") || !strcmp(ss, "sans-serif"))
4229 serif = 0;
4230
4231 fz_try(ctx)
4232 ind = pdf_add_cjk_font(ctx, pdf, font, ordering, wmode, serif);
4233 fz_catch(ctx)
4234 rethrow(J);
4235
4236 ffi_pushobj(J, ind);
4237 }
4238
ffi_PDFDocument_addFont(js_State * J)4239 static void ffi_PDFDocument_addFont(js_State *J)
4240 {
4241 fz_context *ctx = js_getcontext(J);
4242 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
4243 fz_font *font = js_touserdata(J, 1, "fz_font");
4244 pdf_obj *ind = NULL;
4245
4246 fz_try(ctx)
4247 ind = pdf_add_cid_font(ctx, pdf, font);
4248 fz_catch(ctx)
4249 rethrow(J);
4250
4251 ffi_pushobj(J, ind);
4252 }
4253
ffi_PDFDocument_addPage(js_State * J)4254 static void ffi_PDFDocument_addPage(js_State *J)
4255 {
4256 fz_context *ctx = js_getcontext(J);
4257 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
4258 fz_rect mediabox = ffi_torect(J, 1);
4259 int rotate = js_tonumber(J, 2);
4260 pdf_obj *resources = ffi_toobj(J, pdf, 3); /* FIXME: leak if ffi_tobuffer throws */
4261 fz_buffer *contents = ffi_tobuffer(J, 4);
4262 pdf_obj *ind = NULL;
4263
4264 fz_try(ctx)
4265 ind = pdf_add_page(ctx, pdf, mediabox, rotate, resources, contents);
4266 fz_always(ctx) {
4267 fz_drop_buffer(ctx, contents);
4268 pdf_drop_obj(ctx, resources);
4269 } fz_catch(ctx)
4270 rethrow(J);
4271
4272 ffi_pushobj(J, ind);
4273 }
4274
ffi_PDFDocument_insertPage(js_State * J)4275 static void ffi_PDFDocument_insertPage(js_State *J)
4276 {
4277 fz_context *ctx = js_getcontext(J);
4278 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
4279 int at = js_tonumber(J, 1);
4280 pdf_obj *obj = ffi_toobj(J, pdf, 2);
4281
4282 fz_try(ctx)
4283 pdf_insert_page(ctx, pdf, at, obj);
4284 fz_always(ctx)
4285 pdf_drop_obj(ctx, obj);
4286 fz_catch(ctx)
4287 rethrow(J);
4288 }
4289
ffi_PDFDocument_deletePage(js_State * J)4290 static void ffi_PDFDocument_deletePage(js_State *J)
4291 {
4292 fz_context *ctx = js_getcontext(J);
4293 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
4294 int at = js_tonumber(J, 1);
4295
4296 fz_try(ctx)
4297 pdf_delete_page(ctx, pdf, at);
4298 fz_catch(ctx)
4299 rethrow(J);
4300 }
4301
ffi_PDFDocument_countPages(js_State * J)4302 static void ffi_PDFDocument_countPages(js_State *J)
4303 {
4304 fz_context *ctx = js_getcontext(J);
4305 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
4306 int count = 0;
4307
4308 fz_try(ctx)
4309 count = pdf_count_pages(ctx, pdf);
4310 fz_catch(ctx)
4311 rethrow(J);
4312
4313 js_pushnumber(J, count);
4314 }
4315
ffi_PDFDocument_findPage(js_State * J)4316 static void ffi_PDFDocument_findPage(js_State *J)
4317 {
4318 fz_context *ctx = js_getcontext(J);
4319 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
4320 int at = js_tonumber(J, 1);
4321 pdf_obj *obj = NULL;
4322
4323 fz_try(ctx)
4324 obj = pdf_lookup_page_obj(ctx, pdf, at);
4325 fz_catch(ctx)
4326 rethrow(J);
4327
4328 ffi_pushobj(J, pdf_keep_obj(ctx, obj));
4329 }
4330
ffi_PDFDocument_save(js_State * J)4331 static void ffi_PDFDocument_save(js_State *J)
4332 {
4333 fz_context *ctx = js_getcontext(J);
4334 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
4335 const char *filename = js_tostring(J, 1);
4336 const char *options = js_iscoercible(J, 2) ? js_tostring(J, 2) : NULL;
4337 pdf_write_options pwo;
4338
4339 fz_try(ctx) {
4340 pdf_parse_write_options(ctx, &pwo, options);
4341 pdf_save_document(ctx, pdf, filename, &pwo);
4342 } fz_catch(ctx)
4343 rethrow(J);
4344 }
4345
ffi_PDFDocument_newNull(js_State * J)4346 static void ffi_PDFDocument_newNull(js_State *J)
4347 {
4348 ffi_pushobj(J, PDF_NULL);
4349 }
4350
ffi_PDFDocument_newBoolean(js_State * J)4351 static void ffi_PDFDocument_newBoolean(js_State *J)
4352 {
4353 int val = js_toboolean(J, 1);
4354 ffi_pushobj(J, val ? PDF_TRUE : PDF_FALSE);
4355 }
4356
ffi_PDFDocument_newInteger(js_State * J)4357 static void ffi_PDFDocument_newInteger(js_State *J)
4358 {
4359 fz_context *ctx = js_getcontext(J);
4360 int val = js_tointeger(J, 1);
4361 pdf_obj *obj = NULL;
4362 fz_try(ctx)
4363 obj = pdf_new_int(ctx, val);
4364 fz_catch(ctx)
4365 rethrow(J);
4366 ffi_pushobj(J, obj);
4367 }
4368
ffi_PDFDocument_newReal(js_State * J)4369 static void ffi_PDFDocument_newReal(js_State *J)
4370 {
4371 fz_context *ctx = js_getcontext(J);
4372 float val = js_tonumber(J, 1);
4373 pdf_obj *obj = NULL;
4374 fz_try(ctx)
4375 obj = pdf_new_real(ctx, val);
4376 fz_catch(ctx)
4377 rethrow(J);
4378 ffi_pushobj(J, obj);
4379 }
4380
ffi_PDFDocument_newString(js_State * J)4381 static void ffi_PDFDocument_newString(js_State *J)
4382 {
4383 fz_context *ctx = js_getcontext(J);
4384 const char *val = js_tostring(J, 1);
4385 pdf_obj *obj = NULL;
4386
4387 fz_try(ctx)
4388 obj = pdf_new_text_string(ctx, val);
4389 fz_catch(ctx)
4390 rethrow(J);
4391 ffi_pushobj(J, obj);
4392 }
4393
ffi_PDFDocument_newByteString(js_State * J)4394 static void ffi_PDFDocument_newByteString(js_State *J)
4395 {
4396 fz_context *ctx = js_getcontext(J);
4397 int n, i;
4398 char *buf;
4399 pdf_obj *obj = NULL;
4400
4401 n = js_getlength(J, 1);
4402
4403 fz_try(ctx)
4404 buf = fz_malloc(ctx, n);
4405 fz_catch(ctx)
4406 rethrow(J);
4407
4408 if (js_try(J)) {
4409 fz_free(ctx, buf);
4410 js_throw(J);
4411 }
4412
4413 for (i = 0; i < n; ++i) {
4414 js_getindex(J, 1, i);
4415 buf[i] = js_tonumber(J, -1);
4416 js_pop(J, 1);
4417 }
4418
4419 js_endtry(J);
4420
4421 fz_try(ctx)
4422 obj = pdf_new_string(ctx, buf, n);
4423 fz_always(ctx)
4424 fz_free(ctx, buf);
4425 fz_catch(ctx)
4426 rethrow(J);
4427 ffi_pushobj(J, obj);
4428 }
4429
ffi_PDFDocument_newName(js_State * J)4430 static void ffi_PDFDocument_newName(js_State *J)
4431 {
4432 fz_context *ctx = js_getcontext(J);
4433 const char *val = js_tostring(J, 1);
4434 pdf_obj *obj = NULL;
4435 fz_try(ctx)
4436 obj = pdf_new_name(ctx, val);
4437 fz_catch(ctx)
4438 rethrow(J);
4439 ffi_pushobj(J, obj);
4440 }
4441
ffi_PDFDocument_newIndirect(js_State * J)4442 static void ffi_PDFDocument_newIndirect(js_State *J)
4443 {
4444 fz_context *ctx = js_getcontext(J);
4445 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
4446 int num = js_tointeger(J, 1);
4447 int gen = js_tointeger(J, 2);
4448 pdf_obj *obj = NULL;
4449 fz_try(ctx)
4450 obj = pdf_new_indirect(ctx, pdf, num, gen);
4451 fz_catch(ctx)
4452 rethrow(J);
4453 ffi_pushobj(J, obj);
4454 }
4455
ffi_PDFDocument_newArray(js_State * J)4456 static void ffi_PDFDocument_newArray(js_State *J)
4457 {
4458 fz_context *ctx = js_getcontext(J);
4459 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
4460 pdf_obj *obj = NULL;
4461 fz_try(ctx)
4462 obj = pdf_new_array(ctx, pdf, 0);
4463 fz_catch(ctx)
4464 rethrow(J);
4465 ffi_pushobj(J, obj);
4466 }
4467
ffi_PDFDocument_newDictionary(js_State * J)4468 static void ffi_PDFDocument_newDictionary(js_State *J)
4469 {
4470 fz_context *ctx = js_getcontext(J);
4471 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
4472 pdf_obj *obj = NULL;
4473 fz_try(ctx)
4474 obj = pdf_new_dict(ctx, pdf, 0);
4475 fz_catch(ctx)
4476 rethrow(J);
4477 ffi_pushobj(J, obj);
4478 }
4479
ffi_PDFDocument_enableJS(js_State * J)4480 static void ffi_PDFDocument_enableJS(js_State *J)
4481 {
4482 fz_context *ctx = js_getcontext(J);
4483 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
4484 fz_try(ctx)
4485 pdf_enable_js(ctx, pdf);
4486 fz_catch(ctx)
4487 rethrow(J);
4488 }
4489
ffi_PDFDocument_countVersions(js_State * J)4490 static void ffi_PDFDocument_countVersions(js_State *J)
4491 {
4492 fz_context *ctx = js_getcontext(J);
4493 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
4494 int val = 0;
4495 fz_try(ctx)
4496 val = pdf_count_versions(ctx, pdf);
4497 fz_catch(ctx)
4498 rethrow(J);
4499 js_pushnumber(J, val);
4500 }
4501
ffi_PDFDocument_countUnsavedVersions(js_State * J)4502 static void ffi_PDFDocument_countUnsavedVersions(js_State *J)
4503 {
4504 fz_context *ctx = js_getcontext(J);
4505 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
4506 int val = 0;
4507 fz_try(ctx)
4508 val = pdf_count_unsaved_versions(ctx, pdf);
4509 fz_catch(ctx)
4510 rethrow(J);
4511 js_pushnumber(J, val);
4512 }
4513
ffi_PDFDocument_validateChangeHistory(js_State * J)4514 static void ffi_PDFDocument_validateChangeHistory(js_State *J)
4515 {
4516 fz_context *ctx = js_getcontext(J);
4517 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
4518 int val = 0;
4519 fz_try(ctx)
4520 val = pdf_validate_change_history(ctx, pdf);
4521 fz_catch(ctx)
4522 rethrow(J);
4523 js_pushboolean(J, val);
4524 }
4525
ffi_PDFDocument_wasPureXFA(js_State * J)4526 static void ffi_PDFDocument_wasPureXFA(js_State *J)
4527 {
4528 fz_context *ctx = js_getcontext(J);
4529 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
4530 int val = 0;
4531 fz_try(ctx)
4532 val = pdf_validate_change_history(ctx, pdf);
4533 fz_catch(ctx)
4534 rethrow(J);
4535 js_pushboolean(J, val);
4536 }
4537
ffi_PDFDocument_hasUnsavedChanges(js_State * J)4538 static void ffi_PDFDocument_hasUnsavedChanges(js_State *J)
4539 {
4540 fz_context *ctx = js_getcontext(J);
4541 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
4542 int val = 0;
4543 fz_try(ctx)
4544 val = pdf_has_unsaved_changes(ctx, pdf);
4545 fz_catch(ctx)
4546 rethrow(J);
4547 js_pushboolean(J, val);
4548 }
4549
ffi_PDFDocument_wasRepaired(js_State * J)4550 static void ffi_PDFDocument_wasRepaired(js_State *J)
4551 {
4552 fz_context *ctx = js_getcontext(J);
4553 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
4554 int val = 0;
4555 fz_try(ctx)
4556 val = pdf_was_repaired(ctx, pdf);
4557 fz_catch(ctx)
4558 rethrow(J);
4559 js_pushboolean(J, val);
4560 }
4561
ffi_PDFDocument_canBeSavedIncrementally(js_State * J)4562 static void ffi_PDFDocument_canBeSavedIncrementally(js_State *J)
4563 {
4564 fz_context *ctx = js_getcontext(J);
4565 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
4566 int val = 0;
4567 fz_try(ctx)
4568 val = pdf_can_be_saved_incrementally(ctx, pdf);
4569 fz_catch(ctx)
4570 rethrow(J);
4571 js_pushboolean(J, val);
4572 }
4573
ffi_PDFDocument_newGraftMap(js_State * J)4574 static void ffi_PDFDocument_newGraftMap(js_State *J)
4575 {
4576 fz_context *ctx = js_getcontext(J);
4577 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
4578 pdf_graft_map *map = NULL;
4579 fz_try(ctx)
4580 map = pdf_new_graft_map(ctx, pdf);
4581 fz_catch(ctx)
4582 rethrow(J);
4583 js_getregistry(J, "pdf_graft_map");
4584 js_newuserdata(J, "pdf_graft_map", map, ffi_gc_pdf_graft_map);
4585 }
4586
ffi_PDFDocument_graftObject(js_State * J)4587 static void ffi_PDFDocument_graftObject(js_State *J)
4588 {
4589 fz_context *ctx = js_getcontext(J);
4590 pdf_document *dst = js_touserdata(J, 0, "pdf_document");
4591 pdf_obj *obj = js_touserdata(J, 1, "pdf_obj");
4592 fz_try(ctx)
4593 obj = pdf_graft_object(ctx, dst, obj);
4594 fz_catch(ctx)
4595 rethrow(J);
4596 ffi_pushobj(J, obj);
4597 }
4598
ffi_PDFDocument_graftPage(js_State * J)4599 static void ffi_PDFDocument_graftPage(js_State *J)
4600 {
4601 fz_context *ctx = js_getcontext(J);
4602 pdf_document *dst = js_touserdata(J, 0, "pdf_document");
4603 int to = js_tonumber(J, 1);
4604 pdf_document *src = js_touserdata(J, 2, "pdf_document");
4605 int from = js_tonumber(J, 3);
4606 fz_try(ctx)
4607 pdf_graft_page(ctx, dst, to, src, from);
4608 fz_catch(ctx)
4609 rethrow(J);
4610 }
4611
ffi_PDFGraftMap_graftObject(js_State * J)4612 static void ffi_PDFGraftMap_graftObject(js_State *J)
4613 {
4614 fz_context *ctx = js_getcontext(J);
4615 pdf_graft_map *map = js_touserdata(J, 0, "pdf_graft_map");
4616 pdf_obj *obj = js_touserdata(J, 1, "pdf_obj");
4617 fz_try(ctx)
4618 obj = pdf_graft_mapped_object(ctx, map, obj);
4619 fz_catch(ctx)
4620 rethrow(J);
4621 ffi_pushobj(J, obj);
4622 }
4623
ffi_PDFGraftMap_graftPage(js_State * J)4624 static void ffi_PDFGraftMap_graftPage(js_State *J)
4625 {
4626 fz_context *ctx = js_getcontext(J);
4627 pdf_graft_map *map = js_touserdata(J, 0, "pdf_graft_map");
4628 int to = js_tointeger(J, 1);
4629 pdf_document *src = js_touserdata(J, 2, "pdf_document");
4630 int from = js_tointeger(J, 3);
4631 fz_try(ctx)
4632 pdf_graft_mapped_page(ctx, map, to, src, from);
4633 fz_catch(ctx)
4634 rethrow(J);
4635 }
4636
ffi_PDFObject_get(js_State * J)4637 static void ffi_PDFObject_get(js_State *J)
4638 {
4639 pdf_obj *obj = js_touserdata(J, 0, "pdf_obj");
4640 const char *key = js_tostring(J, 1);
4641 if (!ffi_pdf_obj_has(J, obj, key))
4642 js_pushundefined(J);
4643 }
4644
ffi_PDFObject_put(js_State * J)4645 static void ffi_PDFObject_put(js_State *J)
4646 {
4647 pdf_obj *obj = js_touserdata(J, 0, "pdf_obj");
4648 const char *key = js_tostring(J, 1);
4649 js_copy(J, 2);
4650 ffi_pdf_obj_put(J, obj, key);
4651 }
4652
ffi_PDFObject_delete(js_State * J)4653 static void ffi_PDFObject_delete(js_State *J)
4654 {
4655 pdf_obj *obj = js_touserdata(J, 0, "pdf_obj");
4656 const char *key = js_tostring(J, 1);
4657 ffi_pdf_obj_delete(J, obj, key);
4658 }
4659
ffi_PDFObject_push(js_State * J)4660 static void ffi_PDFObject_push(js_State *J)
4661 {
4662 fz_context *ctx = js_getcontext(J);
4663 pdf_obj *obj = js_touserdata(J, 0, "pdf_obj");
4664 pdf_document *pdf = pdf_get_bound_document(ctx, obj);
4665 pdf_obj *item = ffi_toobj(J, pdf, 1);
4666 fz_try(ctx)
4667 pdf_array_push(ctx, obj, item);
4668 fz_always(ctx)
4669 pdf_drop_obj(ctx, item);
4670 fz_catch(ctx)
4671 rethrow(J);
4672 }
4673
ffi_PDFObject_resolve(js_State * J)4674 static void ffi_PDFObject_resolve(js_State *J)
4675 {
4676 fz_context *ctx = js_getcontext(J);
4677 pdf_obj *obj = js_touserdata(J, 0, "pdf_obj");
4678 pdf_obj *ind = NULL;
4679 fz_try(ctx)
4680 ind = pdf_resolve_indirect(ctx, obj);
4681 fz_catch(ctx)
4682 rethrow(J);
4683 ffi_pushobj(J, pdf_keep_obj(ctx, ind));
4684 }
4685
ffi_PDFObject_toString(js_State * J)4686 static void ffi_PDFObject_toString(js_State *J)
4687 {
4688 fz_context *ctx = js_getcontext(J);
4689 pdf_obj *obj = js_touserdata(J, 0, "pdf_obj");
4690 int tight = js_isdefined(J, 1) ? js_toboolean(J, 1) : 1;
4691 int ascii = js_isdefined(J, 2) ? js_toboolean(J, 2) : 0;
4692 char *s = NULL;
4693 size_t n;
4694
4695 fz_try(ctx)
4696 s = pdf_sprint_obj(ctx, NULL, 0, &n, obj, tight, ascii);
4697 fz_catch(ctx)
4698 rethrow(J);
4699
4700 if (js_try(J)) {
4701 fz_free(ctx, s);
4702 js_throw(J);
4703 }
4704 js_pushstring(J, s);
4705 js_endtry(J);
4706 fz_free(ctx, s);
4707 }
4708
ffi_PDFObject_valueOf(js_State * J)4709 static void ffi_PDFObject_valueOf(js_State *J)
4710 {
4711 fz_context *ctx = js_getcontext(J);
4712 pdf_obj *obj = js_touserdata(J, 0, "pdf_obj");
4713 if (pdf_is_indirect(ctx, obj))
4714 js_pushstring(J, "R");
4715 else if (pdf_is_null(ctx, obj))
4716 js_pushnull(J);
4717 else if (pdf_is_bool(ctx, obj))
4718 js_pushboolean(J, pdf_to_bool(ctx, obj));
4719 else if (pdf_is_int(ctx, obj))
4720 js_pushnumber(J, pdf_to_int(ctx, obj));
4721 else if (pdf_is_real(ctx, obj))
4722 js_pushnumber(J, pdf_to_real(ctx, obj));
4723 else if (pdf_is_string(ctx, obj))
4724 js_pushlstring(J, pdf_to_str_buf(ctx, obj), (int)pdf_to_str_len(ctx, obj));
4725 else if (pdf_is_name(ctx, obj))
4726 js_pushstring(J, pdf_to_name(ctx, obj));
4727 else
4728 js_copy(J, 0);
4729 }
4730
ffi_PDFObject_isArray(js_State * J)4731 static void ffi_PDFObject_isArray(js_State *J)
4732 {
4733 fz_context *ctx = js_getcontext(J);
4734 pdf_obj *obj = js_touserdata(J, 0, "pdf_obj");
4735 int b = 0;
4736 fz_try(ctx)
4737 b = pdf_is_array(ctx, obj);
4738 fz_catch(ctx)
4739 rethrow(J);
4740 js_pushboolean(J, b);
4741 }
4742
ffi_PDFObject_isDictionary(js_State * J)4743 static void ffi_PDFObject_isDictionary(js_State *J)
4744 {
4745 fz_context *ctx = js_getcontext(J);
4746 pdf_obj *obj = js_touserdata(J, 0, "pdf_obj");
4747 int b = 0;
4748 fz_try(ctx)
4749 b = pdf_is_dict(ctx, obj);
4750 fz_catch(ctx)
4751 rethrow(J);
4752 js_pushboolean(J, b);
4753 }
4754
ffi_PDFObject_isIndirect(js_State * J)4755 static void ffi_PDFObject_isIndirect(js_State *J)
4756 {
4757 fz_context *ctx = js_getcontext(J);
4758 pdf_obj *obj = js_touserdata(J, 0, "pdf_obj");
4759 int b = 0;
4760 fz_try(ctx)
4761 b = pdf_is_indirect(ctx, obj);
4762 fz_catch(ctx)
4763 rethrow(J);
4764 js_pushboolean(J, b);
4765 }
4766
ffi_PDFObject_asIndirect(js_State * J)4767 static void ffi_PDFObject_asIndirect(js_State *J)
4768 {
4769 fz_context *ctx = js_getcontext(J);
4770 pdf_obj *obj = js_touserdata(J, 0, "pdf_obj");
4771 int num = 0;
4772 fz_try(ctx)
4773 num = pdf_to_num(ctx, obj);
4774 fz_catch(ctx)
4775 rethrow(J);
4776 js_pushnumber(J, num);
4777 }
4778
ffi_PDFObject_isNull(js_State * J)4779 static void ffi_PDFObject_isNull(js_State *J)
4780 {
4781 fz_context *ctx = js_getcontext(J);
4782 pdf_obj *obj = js_touserdata(J, 0, "pdf_obj");
4783 int b = 0;
4784 fz_try(ctx)
4785 b = pdf_is_null(ctx, obj);
4786 fz_catch(ctx)
4787 rethrow(J);
4788 js_pushboolean(J, b);
4789 }
4790
ffi_PDFObject_isBoolean(js_State * J)4791 static void ffi_PDFObject_isBoolean(js_State *J)
4792 {
4793 fz_context *ctx = js_getcontext(J);
4794 pdf_obj *obj = js_touserdata(J, 0, "pdf_obj");
4795 int b = 0;
4796 fz_try(ctx)
4797 b = pdf_is_bool(ctx, obj);
4798 fz_catch(ctx)
4799 rethrow(J);
4800 js_pushboolean(J, b);
4801 }
4802
ffi_PDFObject_asBoolean(js_State * J)4803 static void ffi_PDFObject_asBoolean(js_State *J)
4804 {
4805 fz_context *ctx = js_getcontext(J);
4806 pdf_obj *obj = js_touserdata(J, 0, "pdf_obj");
4807 int b = 0;
4808 fz_try(ctx)
4809 b = pdf_to_bool(ctx, obj);
4810 fz_catch(ctx)
4811 rethrow(J);
4812 js_pushboolean(J, b);
4813 }
4814
ffi_PDFObject_isNumber(js_State * J)4815 static void ffi_PDFObject_isNumber(js_State *J)
4816 {
4817 fz_context *ctx = js_getcontext(J);
4818 pdf_obj *obj = js_touserdata(J, 0, "pdf_obj");
4819 int b = 0;
4820 fz_try(ctx)
4821 b = pdf_is_number(ctx, obj);
4822 fz_catch(ctx)
4823 rethrow(J);
4824 js_pushboolean(J, b);
4825 }
4826
ffi_PDFObject_asNumber(js_State * J)4827 static void ffi_PDFObject_asNumber(js_State *J)
4828 {
4829 fz_context *ctx = js_getcontext(J);
4830 pdf_obj *obj = js_touserdata(J, 0, "pdf_obj");
4831 float num = 0;
4832 fz_try(ctx)
4833 if (pdf_is_int(ctx, obj))
4834 num = pdf_to_int(ctx, obj);
4835 else
4836 num = pdf_to_real(ctx, obj);
4837 fz_catch(ctx)
4838 rethrow(J);
4839 js_pushnumber(J, num);
4840 }
4841
ffi_PDFObject_isName(js_State * J)4842 static void ffi_PDFObject_isName(js_State *J)
4843 {
4844 fz_context *ctx = js_getcontext(J);
4845 pdf_obj *obj = js_touserdata(J, 0, "pdf_obj");
4846 int b = 0;
4847 fz_try(ctx)
4848 b = pdf_is_name(ctx, obj);
4849 fz_catch(ctx)
4850 rethrow(J);
4851 js_pushboolean(J, b);
4852 }
4853
ffi_PDFObject_asName(js_State * J)4854 static void ffi_PDFObject_asName(js_State *J)
4855 {
4856 fz_context *ctx = js_getcontext(J);
4857 pdf_obj *obj = js_touserdata(J, 0, "pdf_obj");
4858 const char *name = NULL;
4859 fz_try(ctx)
4860 name = pdf_to_name(ctx, obj);
4861 fz_catch(ctx)
4862 rethrow(J);
4863 js_pushstring(J, name);
4864 }
4865
ffi_PDFObject_isString(js_State * J)4866 static void ffi_PDFObject_isString(js_State *J)
4867 {
4868 fz_context *ctx = js_getcontext(J);
4869 pdf_obj *obj = js_touserdata(J, 0, "pdf_obj");
4870 int b = 0;
4871 fz_try(ctx)
4872 b = pdf_is_string(ctx, obj);
4873 fz_catch(ctx)
4874 rethrow(J);
4875 js_pushboolean(J, b);
4876 }
4877
ffi_PDFObject_asString(js_State * J)4878 static void ffi_PDFObject_asString(js_State *J)
4879 {
4880 fz_context *ctx = js_getcontext(J);
4881 pdf_obj *obj = js_touserdata(J, 0, "pdf_obj");
4882 const char *string = NULL;
4883
4884 fz_try(ctx)
4885 string = pdf_to_text_string(ctx, obj);
4886 fz_catch(ctx)
4887 rethrow(J);
4888
4889 js_pushstring(J, string);
4890 }
4891
ffi_PDFObject_asByteString(js_State * J)4892 static void ffi_PDFObject_asByteString(js_State *J)
4893 {
4894 fz_context *ctx = js_getcontext(J);
4895 pdf_obj *obj = js_touserdata(J, 0, "pdf_obj");
4896 const char *buf;
4897 size_t i, len = 0;
4898
4899 fz_try(ctx)
4900 buf = pdf_to_string(ctx, obj, &len);
4901 fz_catch(ctx)
4902 rethrow(J);
4903
4904 js_newarray(J);
4905 for (i = 0; i < len; ++i) {
4906 js_pushnumber(J, (unsigned char)buf[i]);
4907 js_setindex(J, -2, (int)i);
4908 }
4909 }
4910
ffi_PDFObject_isStream(js_State * J)4911 static void ffi_PDFObject_isStream(js_State *J)
4912 {
4913 fz_context *ctx = js_getcontext(J);
4914 pdf_obj *obj = js_touserdata(J, 0, "pdf_obj");
4915 int b = 0;
4916 fz_try(ctx)
4917 b = pdf_is_stream(ctx, obj);
4918 fz_catch(ctx)
4919 rethrow(J);
4920 js_pushboolean(J, b);
4921 }
4922
ffi_PDFObject_readStream(js_State * J)4923 static void ffi_PDFObject_readStream(js_State *J)
4924 {
4925 fz_context *ctx = js_getcontext(J);
4926 pdf_obj *obj = js_touserdata(J, 0, "pdf_obj");
4927 fz_buffer *buf = NULL;
4928 fz_try(ctx)
4929 buf = pdf_load_stream(ctx, obj);
4930 fz_catch(ctx)
4931 rethrow(J);
4932 ffi_pushbuffer(J, buf);
4933 }
4934
ffi_PDFObject_readRawStream(js_State * J)4935 static void ffi_PDFObject_readRawStream(js_State *J)
4936 {
4937 fz_context *ctx = js_getcontext(J);
4938 pdf_obj *obj = js_touserdata(J, 0, "pdf_obj");
4939 fz_buffer *buf = NULL;
4940 fz_try(ctx)
4941 buf = pdf_load_raw_stream(ctx, obj);
4942 fz_catch(ctx)
4943 rethrow(J);
4944 ffi_pushbuffer(J, buf);
4945 }
4946
ffi_PDFObject_writeObject(js_State * J)4947 static void ffi_PDFObject_writeObject(js_State *J)
4948 {
4949 fz_context *ctx = js_getcontext(J);
4950 pdf_obj *ref = js_touserdata(J, 0, "pdf_obj");
4951 pdf_document *pdf = pdf_get_bound_document(ctx, ref);
4952 pdf_obj *obj = ffi_toobj(J, pdf, 1);
4953 fz_try(ctx)
4954 pdf_update_object(ctx, pdf, pdf_to_num(ctx, ref), obj);
4955 fz_always(ctx)
4956 pdf_drop_obj(ctx, obj);
4957 fz_catch(ctx)
4958 rethrow(J);
4959 }
4960
ffi_PDFObject_writeStream(js_State * J)4961 static void ffi_PDFObject_writeStream(js_State *J)
4962 {
4963 fz_context *ctx = js_getcontext(J);
4964 pdf_obj *obj = js_touserdata(J, 0, "pdf_obj");
4965 fz_buffer *buf = ffi_tobuffer(J, 1);
4966 fz_try(ctx)
4967 pdf_update_stream(ctx, pdf_get_bound_document(ctx, obj), obj, buf, 0);
4968 fz_always(ctx)
4969 fz_drop_buffer(ctx, buf);
4970 fz_catch(ctx)
4971 rethrow(J);
4972 }
4973
ffi_PDFObject_writeRawStream(js_State * J)4974 static void ffi_PDFObject_writeRawStream(js_State *J)
4975 {
4976 fz_context *ctx = js_getcontext(J);
4977 pdf_obj *obj = js_touserdata(J, 0, "pdf_obj");
4978 fz_buffer *buf = ffi_tobuffer(J, 1);
4979 fz_try(ctx)
4980 pdf_update_stream(ctx, pdf_get_bound_document(ctx, obj), obj, buf, 1);
4981 fz_always(ctx)
4982 fz_drop_buffer(ctx, buf);
4983 fz_catch(ctx)
4984 rethrow(J);
4985 }
4986
ffi_PDFObject_forEach(js_State * J)4987 static void ffi_PDFObject_forEach(js_State *J)
4988 {
4989 fz_context *ctx = js_getcontext(J);
4990 pdf_obj *obj = js_touserdata(J, 0, "pdf_obj");
4991 pdf_obj *val = NULL;
4992 const char *key = NULL;
4993 int i, n = 0;
4994
4995 fz_try(ctx)
4996 obj = pdf_resolve_indirect_chain(ctx, obj);
4997 fz_catch(ctx)
4998 rethrow(J);
4999
5000 if (pdf_is_array(ctx, obj)) {
5001 fz_try(ctx)
5002 n = pdf_array_len(ctx, obj);
5003 fz_catch(ctx)
5004 rethrow(J);
5005 for (i = 0; i < n; ++i) {
5006 fz_try(ctx)
5007 val = pdf_array_get(ctx, obj, i);
5008 fz_catch(ctx)
5009 rethrow(J);
5010 js_copy(J, 1);
5011 js_pushnull(J);
5012 js_pushnumber(J, i);
5013 ffi_pushobj(J, pdf_keep_obj(ctx, val));
5014 js_call(J, 2);
5015 js_pop(J, 1);
5016 }
5017 return;
5018 }
5019
5020 if (pdf_is_dict(ctx, obj)) {
5021 fz_try(ctx)
5022 n = pdf_dict_len(ctx, obj);
5023 fz_catch(ctx)
5024 rethrow(J);
5025 for (i = 0; i < n; ++i) {
5026 fz_try(ctx) {
5027 key = pdf_to_name(ctx, pdf_dict_get_key(ctx, obj, i));
5028 val = pdf_dict_get_val(ctx, obj, i);
5029 } fz_catch(ctx)
5030 rethrow(J);
5031 js_copy(J, 1);
5032 js_pushnull(J);
5033 js_pushstring(J, key);
5034 ffi_pushobj(J, pdf_keep_obj(ctx, val));
5035 js_call(J, 2);
5036 js_pop(J, 1);
5037 }
5038 return;
5039 }
5040 }
5041
ffi_PDFPage_getWidgets(js_State * J)5042 static void ffi_PDFPage_getWidgets(js_State *J)
5043 {
5044 fz_context *ctx = js_getcontext(J);
5045 pdf_page *page = js_touserdata(J, 0, "pdf_page");
5046 pdf_widget *widget = NULL;
5047 int i = 0;
5048
5049 fz_try(ctx)
5050 widget = pdf_first_widget(ctx, page);
5051 fz_catch(ctx)
5052 rethrow(J);
5053
5054 js_newarray(J);
5055
5056 while (widget) {
5057 js_getregistry(J, "pdf_widget");
5058 js_newuserdata(J, "pdf_widget", pdf_keep_widget(ctx, widget), ffi_gc_pdf_widget);
5059 js_setindex(J, -2, i++);
5060
5061 fz_try(ctx)
5062 widget = pdf_next_widget(ctx, widget);
5063 fz_catch(ctx)
5064 rethrow(J);
5065 }
5066 }
5067
ffi_PDFPage_getAnnotations(js_State * J)5068 static void ffi_PDFPage_getAnnotations(js_State *J)
5069 {
5070 fz_context *ctx = js_getcontext(J);
5071 pdf_page *page = js_touserdata(J, 0, "pdf_page");
5072 pdf_annot *annot = NULL;
5073 int i = 0;
5074
5075 fz_try(ctx)
5076 annot = pdf_first_annot(ctx, page);
5077 fz_catch(ctx)
5078 rethrow(J);
5079
5080 js_newarray(J);
5081
5082 while (annot) {
5083 js_getregistry(J, "pdf_annot");
5084 js_newuserdata(J, "pdf_annot", pdf_keep_annot(ctx, annot), ffi_gc_pdf_annot);
5085 js_setindex(J, -2, i++);
5086
5087 fz_try(ctx)
5088 annot = pdf_next_annot(ctx, annot);
5089 fz_catch(ctx)
5090 rethrow(J);
5091 }
5092 }
5093
ffi_PDFPage_createAnnotation(js_State * J)5094 static void ffi_PDFPage_createAnnotation(js_State *J)
5095 {
5096 fz_context *ctx = js_getcontext(J);
5097 pdf_page *page = js_touserdata(J, 0, "pdf_page");
5098 const char *name = js_tostring(J, 1);
5099 pdf_annot *annot = NULL;
5100 int subtype;
5101
5102 fz_try(ctx)
5103 {
5104 subtype = pdf_annot_type_from_string(ctx, name);
5105 annot = pdf_create_annot(ctx, page, subtype);
5106 }
5107 fz_catch(ctx)
5108 rethrow(J);
5109 js_getregistry(J, "pdf_annot");
5110 js_newuserdata(J, "pdf_annot", annot, ffi_gc_pdf_annot);
5111 }
5112
ffi_PDFPage_deleteAnnotation(js_State * J)5113 static void ffi_PDFPage_deleteAnnotation(js_State *J)
5114 {
5115 fz_context *ctx = js_getcontext(J);
5116 pdf_page *page = js_touserdata(J, 0, "pdf_page");
5117 pdf_annot *annot = js_touserdata(J, 1, "pdf_annot");
5118 fz_try(ctx)
5119 pdf_delete_annot(ctx, page, annot);
5120 fz_catch(ctx)
5121 rethrow(J);
5122 }
5123
ffi_PDFPage_update(js_State * J)5124 static void ffi_PDFPage_update(js_State *J)
5125 {
5126 fz_context *ctx = js_getcontext(J);
5127 pdf_page *page = js_touserdata(J, 0, "pdf_page");
5128 int changed = 0;
5129 fz_try(ctx)
5130 changed = pdf_update_page(ctx, page);
5131 fz_catch(ctx)
5132 rethrow(J);
5133 js_pushboolean(J, changed);
5134 }
5135
ffi_PDFPage_applyRedactions(js_State * J)5136 static void ffi_PDFPage_applyRedactions(js_State *J)
5137 {
5138 fz_context *ctx = js_getcontext(J);
5139 pdf_page *page = js_touserdata(J, 0, "pdf_page");
5140 pdf_redact_options opts = { 1, PDF_REDACT_IMAGE_PIXELS };
5141 if (js_isdefined(J, 1)) opts.black_boxes = js_toboolean(J, 1);
5142 if (js_isdefined(J, 2)) opts.image_method = js_tointeger(J, 2);
5143 fz_try(ctx)
5144 pdf_redact_page(ctx, page->doc, page, &opts);
5145 fz_catch(ctx)
5146 rethrow(J);
5147 }
5148
ffi_PDFPage_process(js_State * J)5149 static void ffi_PDFPage_process(js_State *J)
5150 {
5151 fz_context *ctx = js_getcontext(J);
5152 pdf_page *page = js_touserdata(J, 0, "pdf_page");
5153 pdf_processor *proc = new_js_processor(ctx, J);
5154 fz_try(ctx)
5155 {
5156 pdf_obj *resources = pdf_page_resources(ctx, page);
5157 pdf_obj *contents = pdf_page_contents(ctx, page);
5158 pdf_process_contents(ctx, proc, page->doc, resources, contents, NULL);
5159 pdf_close_processor(ctx, proc);
5160 }
5161 fz_always(ctx)
5162 pdf_drop_processor(ctx, proc);
5163 fz_catch(ctx)
5164 rethrow(J);
5165 }
5166
ffi_PDFAnnotation_bound(js_State * J)5167 static void ffi_PDFAnnotation_bound(js_State *J)
5168 {
5169 fz_context *ctx = js_getcontext(J);
5170 pdf_annot *annot = js_touserdata(J, 0, "pdf_annot");
5171 fz_rect bounds;
5172
5173 fz_try(ctx)
5174 bounds = pdf_bound_annot(ctx, annot);
5175 fz_catch(ctx)
5176 rethrow(J);
5177
5178 ffi_pushrect(J, bounds);
5179 }
5180
ffi_PDFAnnotation_run(js_State * J)5181 static void ffi_PDFAnnotation_run(js_State *J)
5182 {
5183 fz_context *ctx = js_getcontext(J);
5184 pdf_annot *annot = js_touserdata(J, 0, "pdf_annot");
5185 fz_device *device = NULL;
5186 fz_matrix ctm = ffi_tomatrix(J, 2);
5187
5188 if (js_isuserdata(J, 1, "fz_device")) {
5189 device = js_touserdata(J, 1, "fz_device");
5190 fz_try(ctx)
5191 pdf_run_annot(ctx, annot, device, ctm, NULL);
5192 fz_catch(ctx)
5193 rethrow(J);
5194 } else {
5195 device = new_js_device(ctx, J);
5196 js_copy(J, 1); /* put the js device on the top so the callbacks know where to get it */
5197 fz_try(ctx) {
5198 pdf_run_annot(ctx, annot, device, ctm, NULL);
5199 fz_close_device(ctx, device);
5200 }
5201 fz_always(ctx)
5202 fz_drop_device(ctx, device);
5203 fz_catch(ctx)
5204 rethrow(J);
5205 }
5206 }
5207
ffi_PDFAnnotation_toDisplayList(js_State * J)5208 static void ffi_PDFAnnotation_toDisplayList(js_State *J)
5209 {
5210 fz_context *ctx = js_getcontext(J);
5211 pdf_annot *annot = js_touserdata(J, 0, "pdf_annot");
5212 fz_display_list *list = NULL;
5213
5214 fz_try(ctx)
5215 list = pdf_new_display_list_from_annot(ctx, annot);
5216 fz_catch(ctx)
5217 rethrow(J);
5218
5219 js_getregistry(J, "fz_display_list");
5220 js_newuserdata(J, "fz_display_list", list, ffi_gc_fz_display_list);
5221 }
5222
ffi_PDFAnnotation_toPixmap(js_State * J)5223 static void ffi_PDFAnnotation_toPixmap(js_State *J)
5224 {
5225 fz_context *ctx = js_getcontext(J);
5226 pdf_annot *annot = js_touserdata(J, 0, "pdf_annot");
5227 fz_matrix ctm = ffi_tomatrix(J, 1);
5228 fz_colorspace *colorspace = js_touserdata(J, 2, "fz_colorspace");
5229 int alpha = js_toboolean(J, 3);
5230 fz_pixmap *pixmap = NULL;
5231
5232 fz_try(ctx)
5233 pixmap = pdf_new_pixmap_from_annot(ctx, annot, ctm, colorspace, NULL, alpha);
5234 fz_catch(ctx)
5235 rethrow(J);
5236
5237 js_getregistry(J, "fz_pixmap");
5238 js_newuserdata(J, "fz_pixmap", pixmap, ffi_gc_fz_pixmap);
5239 }
5240
ffi_PDFAnnotation_getType(js_State * J)5241 static void ffi_PDFAnnotation_getType(js_State *J)
5242 {
5243 fz_context *ctx = js_getcontext(J);
5244 pdf_annot *annot = js_touserdata(J, 0, "pdf_annot");
5245 int type;
5246 const char *subtype = NULL;
5247 fz_try(ctx)
5248 {
5249 type = pdf_annot_type(ctx, annot);
5250 subtype = pdf_string_from_annot_type(ctx, type);
5251 }
5252 fz_catch(ctx)
5253 rethrow(J);
5254 js_pushstring(J, subtype);
5255 }
5256
ffi_PDFAnnotation_getFlags(js_State * J)5257 static void ffi_PDFAnnotation_getFlags(js_State *J)
5258 {
5259 fz_context *ctx = js_getcontext(J);
5260 pdf_annot *annot = js_touserdata(J, 0, "pdf_annot");
5261 int flags = 0;
5262 fz_try(ctx)
5263 flags = pdf_annot_flags(ctx, annot);
5264 fz_catch(ctx)
5265 rethrow(J);
5266 js_pushnumber(J, flags);
5267 }
5268
ffi_PDFAnnotation_setFlags(js_State * J)5269 static void ffi_PDFAnnotation_setFlags(js_State *J)
5270 {
5271 fz_context *ctx = js_getcontext(J);
5272 pdf_annot *annot = js_touserdata(J, 0, "pdf_annot");
5273 int flags = js_tonumber(J, 1);
5274 fz_try(ctx)
5275 pdf_set_annot_flags(ctx, annot, flags);
5276 fz_catch(ctx)
5277 rethrow(J);
5278 }
5279
ffi_PDFAnnotation_getContents(js_State * J)5280 static void ffi_PDFAnnotation_getContents(js_State *J)
5281 {
5282 fz_context *ctx = js_getcontext(J);
5283 pdf_annot *annot = js_touserdata(J, 0, "pdf_annot");
5284 const char *contents = NULL;
5285
5286 fz_try(ctx)
5287 contents = pdf_annot_contents(ctx, annot);
5288 fz_catch(ctx)
5289 rethrow(J);
5290
5291 js_pushstring(J, contents);
5292 }
5293
ffi_PDFAnnotation_setContents(js_State * J)5294 static void ffi_PDFAnnotation_setContents(js_State *J)
5295 {
5296 fz_context *ctx = js_getcontext(J);
5297 pdf_annot *annot = js_touserdata(J, 0, "pdf_annot");
5298 const char *contents = js_tostring(J, 1);
5299 fz_try(ctx)
5300 pdf_set_annot_contents(ctx, annot, contents);
5301 fz_catch(ctx)
5302 rethrow(J);
5303 }
5304
ffi_PDFAnnotation_getRect(js_State * J)5305 static void ffi_PDFAnnotation_getRect(js_State *J)
5306 {
5307 fz_context *ctx = js_getcontext(J);
5308 pdf_annot *annot = js_touserdata(J, 0, "pdf_annot");
5309 fz_rect rect;
5310 fz_try(ctx)
5311 rect = pdf_annot_rect(ctx, annot);
5312 fz_catch(ctx)
5313 rethrow(J);
5314 ffi_pushrect(J, rect);
5315 }
5316
ffi_PDFAnnotation_setRect(js_State * J)5317 static void ffi_PDFAnnotation_setRect(js_State *J)
5318 {
5319 fz_context *ctx = js_getcontext(J);
5320 pdf_annot *annot = js_touserdata(J, 0, "pdf_annot");
5321 fz_rect rect = ffi_torect(J, 1);
5322 fz_try(ctx)
5323 pdf_set_annot_rect(ctx, annot, rect);
5324 fz_catch(ctx)
5325 rethrow(J);
5326 }
5327
ffi_PDFAnnotation_getBorder(js_State * J)5328 static void ffi_PDFAnnotation_getBorder(js_State *J)
5329 {
5330 fz_context *ctx = js_getcontext(J);
5331 pdf_annot *annot = js_touserdata(J, 0, "pdf_annot");
5332 float border = 0;
5333 fz_try(ctx)
5334 border = pdf_annot_border(ctx, annot);
5335 fz_catch(ctx)
5336 rethrow(J);
5337 js_pushnumber(J, border);
5338 }
5339
ffi_PDFAnnotation_setBorder(js_State * J)5340 static void ffi_PDFAnnotation_setBorder(js_State *J)
5341 {
5342 fz_context *ctx = js_getcontext(J);
5343 pdf_annot *annot = js_touserdata(J, 0, "pdf_annot");
5344 float border = js_tonumber(J, 1);
5345 fz_try(ctx)
5346 pdf_set_annot_border(ctx, annot, border);
5347 fz_catch(ctx)
5348 rethrow(J);
5349 }
5350
ffi_PDFAnnotation_getColor(js_State * J)5351 static void ffi_PDFAnnotation_getColor(js_State *J)
5352 {
5353 fz_context *ctx = js_getcontext(J);
5354 pdf_annot *annot = js_touserdata(J, 0, "pdf_annot");
5355 int i, n = 0;
5356 float color[4];
5357 fz_try(ctx)
5358 pdf_annot_color(ctx, annot, &n, color);
5359 fz_catch(ctx)
5360 rethrow(J);
5361 js_newarray(J);
5362 for (i = 0; i < n; ++i) {
5363 js_pushnumber(J, color[i]);
5364 js_setindex(J, -2, i);
5365 }
5366 }
5367
ffi_PDFAnnotation_setColor(js_State * J)5368 static void ffi_PDFAnnotation_setColor(js_State *J)
5369 {
5370 fz_context *ctx = js_getcontext(J);
5371 pdf_annot *annot = js_touserdata(J, 0, "pdf_annot");
5372 int i, n = js_getlength(J, 1);
5373 float color[4];
5374 for (i = 0; i < n && i < 4; ++i) {
5375 js_getindex(J, 1, i);
5376 color[i] = js_tonumber(J, -1);
5377 js_pop(J, 1);
5378 }
5379 fz_try(ctx)
5380 pdf_set_annot_color(ctx, annot, n, color);
5381 fz_catch(ctx)
5382 rethrow(J);
5383 }
5384
ffi_PDFAnnotation_getInteriorColor(js_State * J)5385 static void ffi_PDFAnnotation_getInteriorColor(js_State *J)
5386 {
5387 fz_context *ctx = js_getcontext(J);
5388 pdf_annot *annot = js_touserdata(J, 0, "pdf_annot");
5389 int i, n = 0;
5390 float color[4];
5391 fz_try(ctx)
5392 pdf_annot_interior_color(ctx, annot, &n, color);
5393 fz_catch(ctx)
5394 rethrow(J);
5395 js_newarray(J);
5396 for (i = 0; i < n; ++i) {
5397 js_pushnumber(J, color[i]);
5398 js_setindex(J, -2, i);
5399 }
5400 }
5401
ffi_PDFAnnotation_setInteriorColor(js_State * J)5402 static void ffi_PDFAnnotation_setInteriorColor(js_State *J)
5403 {
5404 fz_context *ctx = js_getcontext(J);
5405 pdf_annot *annot = js_touserdata(J, 0, "pdf_annot");
5406 int i, n = js_getlength(J, 1);
5407 float color[4];
5408 for (i = 0; i < n && i < 4; ++i) {
5409 js_getindex(J, 1, i);
5410 color[i] = js_tonumber(J, -1);
5411 js_pop(J, 1);
5412 }
5413 fz_try(ctx)
5414 pdf_set_annot_interior_color(ctx, annot, n, color);
5415 fz_catch(ctx)
5416 rethrow(J);
5417 }
5418
ffi_PDFAnnotation_getQuadPoints(js_State * J)5419 static void ffi_PDFAnnotation_getQuadPoints(js_State *J)
5420 {
5421 fz_context *ctx = js_getcontext(J);
5422 pdf_annot *annot = js_touserdata(J, 0, "pdf_annot");
5423 fz_quad q;
5424 int i, n = 0;
5425
5426 fz_try(ctx)
5427 n = pdf_annot_quad_point_count(ctx, annot);
5428 fz_catch(ctx)
5429 rethrow(J);
5430
5431 js_newarray(J);
5432 for (i = 0; i < n; ++i) {
5433 fz_try(ctx)
5434 q = pdf_annot_quad_point(ctx, annot, i);
5435 fz_catch(ctx)
5436 rethrow(J);
5437 ffi_pushquad(J, q);
5438 js_setindex(J, -2, i);
5439 }
5440 }
5441
ffi_PDFAnnotation_setQuadPoints(js_State * J)5442 static void ffi_PDFAnnotation_setQuadPoints(js_State *J)
5443 {
5444 fz_context *ctx = js_getcontext(J);
5445 pdf_annot *annot = js_touserdata(J, 0, "pdf_annot");
5446 fz_quad *qp = NULL;
5447 int i, n;
5448
5449 n = js_getlength(J, 1);
5450
5451 fz_try(ctx)
5452 qp = fz_malloc_array(ctx, n, fz_quad);
5453 fz_catch(ctx)
5454 rethrow(J);
5455
5456 for (i = 0; i < n; ++i) {
5457 js_getindex(J, 1, i);
5458 qp[i] = ffi_toquad(J, -1);
5459 js_pop(J, 1);
5460 }
5461
5462 fz_try(ctx)
5463 pdf_set_annot_quad_points(ctx, annot, n, qp);
5464 fz_always(ctx)
5465 fz_free(ctx, qp);
5466 fz_catch(ctx)
5467 rethrow(J);
5468 }
5469
ffi_PDFAnnotation_clearQuadPoints(js_State * J)5470 static void ffi_PDFAnnotation_clearQuadPoints(js_State *J)
5471 {
5472 fz_context *ctx = js_getcontext(J);
5473 pdf_annot *annot = js_touserdata(J, 0, "pdf_annot");
5474
5475 fz_try(ctx)
5476 pdf_clear_annot_quad_points(ctx, annot);
5477 fz_catch(ctx)
5478 rethrow(J);
5479 }
5480
ffi_PDFAnnotation_addQuadPoint(js_State * J)5481 static void ffi_PDFAnnotation_addQuadPoint(js_State *J)
5482 {
5483 fz_context *ctx = js_getcontext(J);
5484 pdf_annot *annot = js_touserdata(J, 0, "pdf_annot");
5485 fz_quad q = ffi_toquad(J, 1);
5486
5487 fz_try(ctx)
5488 pdf_add_annot_quad_point(ctx, annot, q);
5489 fz_catch(ctx)
5490 rethrow(J);
5491 }
5492
ffi_PDFAnnotation_getVertices(js_State * J)5493 static void ffi_PDFAnnotation_getVertices(js_State *J)
5494 {
5495 fz_context *ctx = js_getcontext(J);
5496 pdf_annot *annot = js_touserdata(J, 0, "pdf_annot");
5497 fz_point p;
5498 int i, n = 0;
5499
5500 fz_try(ctx)
5501 n = pdf_annot_vertex_count(ctx, annot);
5502 fz_catch(ctx)
5503 rethrow(J);
5504
5505 js_newarray(J);
5506 for (i = 0; i < n; ++i) {
5507 fz_try(ctx)
5508 p = pdf_annot_vertex(ctx, annot, i);
5509 fz_catch(ctx)
5510 rethrow(J);
5511 ffi_pushpoint(J, p);
5512 js_setindex(J, -2, i);
5513 }
5514 }
5515
ffi_PDFAnnotation_setVertices(js_State * J)5516 static void ffi_PDFAnnotation_setVertices(js_State *J)
5517 {
5518 fz_context *ctx = js_getcontext(J);
5519 pdf_annot *annot = js_touserdata(J, 0, "pdf_annot");
5520 fz_point p;
5521 int i, n;
5522
5523 n = js_getlength(J, 1);
5524
5525 fz_try(ctx)
5526 pdf_clear_annot_vertices(ctx, annot);
5527 fz_catch(ctx)
5528 rethrow(J);
5529
5530 for (i = 0; i < n; ++i) {
5531 js_getindex(J, 1, i);
5532 p = ffi_topoint(J, -1);
5533 js_pop(J, 1);
5534
5535 fz_try(ctx)
5536 pdf_add_annot_vertex(ctx, annot, p);
5537 fz_catch(ctx)
5538 rethrow(J);
5539 }
5540 }
5541
ffi_PDFAnnotation_clearVertices(js_State * J)5542 static void ffi_PDFAnnotation_clearVertices(js_State *J)
5543 {
5544 fz_context *ctx = js_getcontext(J);
5545 pdf_annot *annot = js_touserdata(J, 0, "pdf_annot");
5546
5547 fz_try(ctx)
5548 pdf_clear_annot_vertices(ctx, annot);
5549 fz_catch(ctx)
5550 rethrow(J);
5551 }
5552
ffi_PDFAnnotation_addVertex(js_State * J)5553 static void ffi_PDFAnnotation_addVertex(js_State *J)
5554 {
5555 fz_context *ctx = js_getcontext(J);
5556 pdf_annot *annot = js_touserdata(J, 0, "pdf_annot");
5557 fz_point p = ffi_topoint(J, 1);
5558
5559 fz_try(ctx)
5560 pdf_add_annot_vertex(ctx, annot, p);
5561 fz_catch(ctx)
5562 rethrow(J);
5563 }
5564
ffi_PDFAnnotation_getInkList(js_State * J)5565 static void ffi_PDFAnnotation_getInkList(js_State *J)
5566 {
5567 fz_context *ctx = js_getcontext(J);
5568 pdf_annot *annot = js_touserdata(J, 0, "pdf_annot");
5569 int i, k, m = 0, n = 0;
5570 fz_point pt;
5571
5572 js_newarray(J);
5573
5574 fz_try(ctx)
5575 n = pdf_annot_ink_list_count(ctx, annot);
5576 fz_catch(ctx)
5577 rethrow(J);
5578
5579 for (i = 0; i < n; ++i) {
5580 fz_try(ctx)
5581 m = pdf_annot_ink_list_stroke_count(ctx, annot, i);
5582 fz_catch(ctx)
5583 rethrow(J);
5584
5585 js_newarray(J);
5586 for (k = 0; k < m; ++k) {
5587 fz_try(ctx)
5588 pt = pdf_annot_ink_list_stroke_vertex(ctx, annot, i, k);
5589 fz_catch(ctx)
5590 rethrow(J);
5591 js_pushnumber(J, pt.x);
5592 js_setindex(J, -2, k * 2 + 0);
5593 js_pushnumber(J, pt.y);
5594 js_setindex(J, -2, k * 2 + 1);
5595 }
5596 js_setindex(J, -2, i);
5597 }
5598 }
5599
ffi_PDFAnnotation_setInkList(js_State * J)5600 static void ffi_PDFAnnotation_setInkList(js_State *J)
5601 {
5602 fz_context *ctx = js_getcontext(J);
5603 pdf_annot *annot = js_touserdata(J, 0, "pdf_annot");
5604 fz_point *points = NULL;
5605 int *counts = NULL;
5606 int n, nv, k, i, v;
5607
5608 fz_var(counts);
5609 fz_var(points);
5610
5611 n = js_getlength(J, 1);
5612 nv = 0;
5613 for (i = 0; i < n; ++i) {
5614 js_getindex(J, 1, i);
5615 nv += js_getlength(J, -1) / 2;
5616 js_pop(J, 1);
5617 }
5618
5619 fz_try(ctx) {
5620 counts = fz_malloc(ctx, n * sizeof(int));
5621 points = fz_malloc(ctx, nv * sizeof(fz_point));
5622 } fz_catch(ctx) {
5623 fz_free(ctx, counts);
5624 fz_free(ctx, points);
5625 rethrow(J);
5626 }
5627
5628 if (js_try(J)) {
5629 fz_free(ctx, counts);
5630 fz_free(ctx, points);
5631 js_throw(J);
5632 }
5633 for (i = v = 0; i < n; ++i) {
5634 js_getindex(J, 1, i);
5635 counts[i] = js_getlength(J, -1) / 2;
5636 for (k = 0; k < counts[i]; ++k) {
5637 js_getindex(J, -1, k*2);
5638 points[v].x = js_tonumber(J, -1);
5639 js_pop(J, 1);
5640 js_getindex(J, -1, k*2+1);
5641 points[v].y = js_tonumber(J, -1);
5642 js_pop(J, 1);
5643 ++v;
5644 }
5645 js_pop(J, 1);
5646 }
5647 js_endtry(J);
5648
5649 fz_try(ctx)
5650 pdf_set_annot_ink_list(ctx, annot, n, counts, points);
5651 fz_always(ctx) {
5652 fz_free(ctx, counts);
5653 fz_free(ctx, points);
5654 }
5655 fz_catch(ctx)
5656 rethrow(J);
5657 }
5658
ffi_PDFAnnotation_clearInkList(js_State * J)5659 static void ffi_PDFAnnotation_clearInkList(js_State *J)
5660 {
5661 fz_context *ctx = js_getcontext(J);
5662 pdf_annot *annot = js_touserdata(J, 0, "pdf_annot");
5663 fz_try(ctx)
5664 pdf_clear_annot_ink_list(ctx, annot);
5665 fz_catch(ctx)
5666 rethrow(J);
5667 }
5668
ffi_PDFAnnotation_addInkList(js_State * J)5669 static void ffi_PDFAnnotation_addInkList(js_State *J)
5670 {
5671 fz_context *ctx = js_getcontext(J);
5672 pdf_annot *annot = js_touserdata(J, 0, "pdf_annot");
5673 int i, n;
5674 float x, y;
5675
5676 n = js_getlength(J, 1);
5677
5678 fz_try(ctx)
5679 pdf_add_annot_ink_list_stroke(ctx, annot);
5680 fz_catch(ctx)
5681 rethrow(J);
5682
5683 for (i = 0; i < n; i += 2) {
5684 js_getindex(J, 1, i);
5685 x = js_tonumber(J, -1);
5686 js_pop(J, 1);
5687
5688 js_getindex(J, 1, i+1);
5689 y = js_tonumber(J, -1);
5690 js_pop(J, 1);
5691
5692 fz_try(ctx)
5693 pdf_add_annot_ink_list_stroke_vertex(ctx, annot, fz_make_point(x, y));
5694 fz_catch(ctx)
5695 rethrow(J);
5696 }
5697 }
5698
ffi_PDFAnnotation_addInkListStroke(js_State * J)5699 static void ffi_PDFAnnotation_addInkListStroke(js_State *J)
5700 {
5701 fz_context *ctx = js_getcontext(J);
5702 pdf_annot *annot = js_touserdata(J, 0, "pdf_annot");
5703 fz_try(ctx)
5704 pdf_add_annot_ink_list_stroke(ctx, annot);
5705 fz_catch(ctx)
5706 rethrow(J);
5707 }
5708
ffi_PDFAnnotation_addInkListStrokeVertex(js_State * J)5709 static void ffi_PDFAnnotation_addInkListStrokeVertex(js_State *J)
5710 {
5711 fz_context *ctx = js_getcontext(J);
5712 pdf_annot *annot = js_touserdata(J, 0, "pdf_annot");
5713 float x = js_tonumber(J, 1);
5714 float y = js_tonumber(J, 2);
5715 fz_try(ctx)
5716 pdf_add_annot_ink_list_stroke_vertex(ctx, annot, fz_make_point(x, y));
5717 fz_catch(ctx)
5718 rethrow(J);
5719 }
5720
ffi_PDFAnnotation_getAuthor(js_State * J)5721 static void ffi_PDFAnnotation_getAuthor(js_State *J)
5722 {
5723 fz_context *ctx = js_getcontext(J);
5724 pdf_annot *annot = js_touserdata(J, 0, "pdf_annot");
5725 const char *author = NULL;
5726
5727 fz_try(ctx)
5728 author = pdf_annot_author(ctx, annot);
5729 fz_catch(ctx)
5730 rethrow(J);
5731
5732 js_pushstring(J, author);
5733 }
5734
ffi_PDFAnnotation_setAuthor(js_State * J)5735 static void ffi_PDFAnnotation_setAuthor(js_State *J)
5736 {
5737 fz_context *ctx = js_getcontext(J);
5738 pdf_annot *annot = js_touserdata(J, 0, "pdf_annot");
5739 const char *author = js_tostring(J, 1);
5740
5741 fz_try(ctx)
5742 pdf_set_annot_author(ctx, annot, author);
5743 fz_catch(ctx)
5744 rethrow(J);
5745 }
5746
ffi_PDFAnnotation_getModificationDate(js_State * J)5747 static void ffi_PDFAnnotation_getModificationDate(js_State *J)
5748 {
5749 fz_context *ctx = js_getcontext(J);
5750 pdf_annot *annot = js_touserdata(J, 0, "pdf_annot");
5751 double time;
5752
5753 fz_try(ctx)
5754 time = pdf_annot_modification_date(ctx, annot);
5755 fz_catch(ctx)
5756 rethrow(J);
5757
5758 js_getglobal(J, "Date");
5759 js_pushnumber(J, time * 1000);
5760 js_construct(J, 1);
5761 }
5762
ffi_PDFAnnotation_setModificationDate(js_State * J)5763 static void ffi_PDFAnnotation_setModificationDate(js_State *J)
5764 {
5765 fz_context *ctx = js_getcontext(J);
5766 pdf_annot *annot = js_touserdata(J, 0, "pdf_annot");
5767 double time = js_tonumber(J, 1);
5768
5769 fz_try(ctx)
5770 pdf_set_annot_modification_date(ctx, annot, time / 1000);
5771 fz_catch(ctx)
5772 rethrow(J);
5773 }
5774
ffi_PDFAnnotation_getLineEndingStyles(js_State * J)5775 static void ffi_PDFAnnotation_getLineEndingStyles(js_State *J)
5776 {
5777 fz_context *ctx = js_getcontext(J);
5778 pdf_annot *annot = js_touserdata(J, 0, "pdf_annot");
5779 enum pdf_line_ending start, end;
5780
5781 js_newarray(J);
5782
5783 fz_try(ctx)
5784 pdf_annot_line_ending_styles(ctx, annot, &start, &end);
5785 fz_catch(ctx)
5786 rethrow(J);
5787
5788 js_newobject(J);
5789 js_pushliteral(J, string_from_line_ending(start));
5790 js_setproperty(J, -2, "start");
5791 js_pushliteral(J, string_from_line_ending(end));
5792 js_setproperty(J, -2, "end");
5793 }
5794
ffi_PDFAnnotation_setLineEndingStyles(js_State * J)5795 static void ffi_PDFAnnotation_setLineEndingStyles(js_State *J)
5796 {
5797 fz_context *ctx = js_getcontext(J);
5798 pdf_annot *annot = js_touserdata(J, 0, "pdf_annot");
5799 enum pdf_line_ending start = line_ending_from_string(js_tostring(J, 1));
5800 enum pdf_line_ending end = line_ending_from_string(js_tostring(J, 2));
5801
5802 fz_try(ctx)
5803 pdf_set_annot_line_ending_styles(ctx, annot, start, end);
5804 fz_catch(ctx)
5805 rethrow(J);
5806 }
5807
ffi_PDFAnnotation_updateAppearance(js_State * J)5808 static void ffi_PDFAnnotation_updateAppearance(js_State *J)
5809 {
5810 fz_context *ctx = js_getcontext(J);
5811 pdf_annot *annot = js_touserdata(J, 0, "pdf_annot");
5812 fz_try(ctx)
5813 pdf_update_appearance(ctx, annot);
5814 fz_catch(ctx)
5815 rethrow(J);
5816 }
5817
ffi_PDFAnnotation_update(js_State * J)5818 static void ffi_PDFAnnotation_update(js_State *J)
5819 {
5820 fz_context *ctx = js_getcontext(J);
5821 pdf_annot *annot = js_touserdata(J, 0, "pdf_annot");
5822 int changed = 0;
5823 fz_try(ctx)
5824 changed = pdf_update_annot(ctx, annot);
5825 fz_catch(ctx)
5826 rethrow(J);
5827 js_pushboolean(J, changed);
5828 }
5829
ffi_PDFAnnotation_process(js_State * J)5830 static void ffi_PDFAnnotation_process(js_State *J)
5831 {
5832 fz_context *ctx = js_getcontext(J);
5833 pdf_annot *annot = js_touserdata(J, 0, "pdf_annot");
5834 pdf_processor *proc = new_js_processor(ctx, J);
5835 fz_try(ctx)
5836 {
5837 pdf_process_annot(ctx, proc, annot->page->doc, annot->page, annot, NULL);
5838 pdf_close_processor(ctx, proc);
5839 }
5840 fz_always(ctx)
5841 pdf_drop_processor(ctx, proc);
5842 fz_catch(ctx)
5843 rethrow(J);
5844 }
5845
ffi_PDFWidget_getFieldType(js_State * J)5846 static void ffi_PDFWidget_getFieldType(js_State *J)
5847 {
5848 fz_context *ctx = js_getcontext(J);
5849 pdf_widget *widget = js_touserdata(J, 0, "pdf_widget");
5850 int type;
5851 fz_try(ctx)
5852 type = pdf_field_type(ctx, widget->obj);
5853 fz_catch(ctx)
5854 rethrow(J);
5855 switch (type)
5856 {
5857 default:
5858 case PDF_WIDGET_TYPE_BUTTON: js_pushstring(J, "button"); break;
5859 case PDF_WIDGET_TYPE_CHECKBOX: js_pushstring(J, "checkbox"); break;
5860 case PDF_WIDGET_TYPE_COMBOBOX: js_pushstring(J, "combobox"); break;
5861 case PDF_WIDGET_TYPE_LISTBOX: js_pushstring(J, "listbox"); break;
5862 case PDF_WIDGET_TYPE_RADIOBUTTON: js_pushstring(J, "radiobutton"); break;
5863 case PDF_WIDGET_TYPE_SIGNATURE: js_pushstring(J, "signature"); break;
5864 case PDF_WIDGET_TYPE_TEXT: js_pushstring(J, "text"); break;
5865 }
5866 }
5867
ffi_PDFWidget_getFieldFlags(js_State * J)5868 static void ffi_PDFWidget_getFieldFlags(js_State *J)
5869 {
5870 fz_context *ctx = js_getcontext(J);
5871 pdf_widget *widget = js_touserdata(J, 0, "pdf_widget");
5872 int flags;
5873 fz_try(ctx)
5874 flags = pdf_field_flags(ctx, widget->obj);
5875 fz_catch(ctx)
5876 rethrow(J);
5877 js_pushnumber(J, flags);
5878 }
5879
ffi_PDFWidget_getRect(js_State * J)5880 static void ffi_PDFWidget_getRect(js_State *J)
5881 {
5882 fz_context *ctx = js_getcontext(J);
5883 pdf_widget *widget = js_touserdata(J, 0, "pdf_widget");
5884 fz_rect rect;
5885 fz_try(ctx)
5886 rect = pdf_annot_rect(ctx, widget);
5887 fz_catch(ctx)
5888 rethrow(J);
5889 ffi_pushrect(J, rect);
5890 }
5891
ffi_PDFWidget_setRect(js_State * J)5892 static void ffi_PDFWidget_setRect(js_State *J)
5893 {
5894 fz_context *ctx = js_getcontext(J);
5895 pdf_widget *widget = js_touserdata(J, 0, "pdf_widget");
5896 fz_rect rect = ffi_torect(J, 1);
5897 fz_try(ctx)
5898 pdf_set_annot_rect(ctx, widget, rect);
5899 fz_catch(ctx)
5900 rethrow(J);
5901 }
5902
ffi_PDFWidget_getValue(js_State * J)5903 static void ffi_PDFWidget_getValue(js_State *J)
5904 {
5905 fz_context *ctx = js_getcontext(J);
5906 pdf_widget *widget = js_touserdata(J, 0, "pdf_widget");
5907 const char *value;
5908 fz_try(ctx)
5909 value = pdf_field_value(ctx, widget->obj);
5910 fz_catch(ctx)
5911 rethrow(J);
5912 js_pushstring(J, value);
5913 }
5914
ffi_PDFWidget_setTextValue(js_State * J)5915 static void ffi_PDFWidget_setTextValue(js_State *J)
5916 {
5917 fz_context *ctx = js_getcontext(J);
5918 pdf_widget *widget = js_touserdata(J, 0, "pdf_widget");
5919 const char *value = js_tostring(J, 1);
5920 fz_try(ctx)
5921 pdf_set_text_field_value(ctx, widget, value);
5922 fz_catch(ctx)
5923 rethrow(J);
5924 }
5925
ffi_PDFWidget_setChoiceValue(js_State * J)5926 static void ffi_PDFWidget_setChoiceValue(js_State *J)
5927 {
5928 fz_context *ctx = js_getcontext(J);
5929 pdf_widget *widget = js_touserdata(J, 0, "pdf_widget");
5930 const char *value = js_tostring(J, 1);
5931 fz_try(ctx)
5932 pdf_set_choice_field_value(ctx, widget, value);
5933 fz_catch(ctx)
5934 rethrow(J);
5935 }
5936
ffi_PDFWidget_toggle(js_State * J)5937 static void ffi_PDFWidget_toggle(js_State *J)
5938 {
5939 fz_context *ctx = js_getcontext(J);
5940 pdf_widget *widget = js_touserdata(J, 0, "pdf_widget");
5941 int changed = 0;
5942 fz_try(ctx)
5943 changed = pdf_toggle_widget(ctx, widget);
5944 fz_catch(ctx)
5945 rethrow(J);
5946 js_pushboolean(J, changed);
5947 }
5948
ffi_PDFWidget_getMaxLen(js_State * J)5949 static void ffi_PDFWidget_getMaxLen(js_State *J)
5950 {
5951 fz_context *ctx = js_getcontext(J);
5952 pdf_widget *widget = js_touserdata(J, 0, "pdf_widget");
5953 int maxLen = 0;
5954 fz_try(ctx)
5955 maxLen = pdf_text_widget_max_len(ctx, widget);
5956 fz_catch(ctx)
5957 rethrow(J);
5958 js_pushnumber(J, maxLen);
5959 }
5960
ffi_PDFWidget_getOptions(js_State * J)5961 static void ffi_PDFWidget_getOptions(js_State *J)
5962 {
5963 fz_context *ctx = js_getcontext(J);
5964 pdf_widget *widget = js_touserdata(J, 0, "pdf_widget");
5965 int export = js_toboolean(J, 1);
5966 const char *opt;
5967 int i, n;
5968 fz_try(ctx)
5969 n = pdf_choice_field_option_count(ctx, widget->obj);
5970 fz_catch(ctx)
5971 rethrow(J);
5972 js_newarray(J);
5973 for (i = 0; i < n; ++i) {
5974 fz_try(ctx)
5975 opt = pdf_choice_field_option(ctx, widget->obj, export, i);
5976 fz_catch(ctx)
5977 rethrow(J);
5978 js_pushstring(J, opt);
5979 }
5980 js_endtry(J);
5981 }
5982
ffi_PDFWidget_update(js_State * J)5983 static void ffi_PDFWidget_update(js_State *J)
5984 {
5985 fz_context *ctx = js_getcontext(J);
5986 pdf_widget *widget = js_touserdata(J, 0, "pdf_widget");
5987 int changed = 0;
5988 fz_try(ctx)
5989 changed = pdf_update_widget(ctx, widget);
5990 fz_catch(ctx)
5991 rethrow(J);
5992 js_pushboolean(J, changed);
5993 }
5994
ffi_PDFWidget_eventEnter(js_State * J)5995 static void ffi_PDFWidget_eventEnter(js_State *J)
5996 {
5997 fz_context *ctx = js_getcontext(J);
5998 pdf_widget *widget = js_touserdata(J, 0, "pdf_widget");
5999 fz_try(ctx)
6000 pdf_annot_event_enter(ctx, widget);
6001 fz_catch(ctx)
6002 rethrow(J);
6003 }
6004
ffi_PDFWidget_eventExit(js_State * J)6005 static void ffi_PDFWidget_eventExit(js_State *J)
6006 {
6007 fz_context *ctx = js_getcontext(J);
6008 pdf_widget *widget = js_touserdata(J, 0, "pdf_widget");
6009 fz_try(ctx)
6010 pdf_annot_event_exit(ctx, widget);
6011 fz_catch(ctx)
6012 rethrow(J);
6013 }
6014
ffi_PDFWidget_eventDown(js_State * J)6015 static void ffi_PDFWidget_eventDown(js_State *J)
6016 {
6017 fz_context *ctx = js_getcontext(J);
6018 pdf_widget *widget = js_touserdata(J, 0, "pdf_widget");
6019 fz_try(ctx)
6020 pdf_annot_event_down(ctx, widget);
6021 fz_catch(ctx)
6022 rethrow(J);
6023 }
6024
ffi_PDFWidget_eventUp(js_State * J)6025 static void ffi_PDFWidget_eventUp(js_State *J)
6026 {
6027 fz_context *ctx = js_getcontext(J);
6028 pdf_widget *widget = js_touserdata(J, 0, "pdf_widget");
6029 fz_try(ctx)
6030 pdf_annot_event_up(ctx, widget);
6031 fz_catch(ctx)
6032 rethrow(J);
6033 }
6034
ffi_PDFWidget_eventFocus(js_State * J)6035 static void ffi_PDFWidget_eventFocus(js_State *J)
6036 {
6037 fz_context *ctx = js_getcontext(J);
6038 pdf_widget *widget = js_touserdata(J, 0, "pdf_widget");
6039 fz_try(ctx)
6040 pdf_annot_event_focus(ctx, widget);
6041 fz_catch(ctx)
6042 rethrow(J);
6043 }
6044
ffi_PDFWidget_eventBlur(js_State * J)6045 static void ffi_PDFWidget_eventBlur(js_State *J)
6046 {
6047 fz_context *ctx = js_getcontext(J);
6048 pdf_widget *widget = js_touserdata(J, 0, "pdf_widget");
6049 fz_try(ctx)
6050 pdf_annot_event_blur(ctx, widget);
6051 fz_catch(ctx)
6052 rethrow(J);
6053 }
6054
ffi_PDFWidget_validateSignature(js_State * J)6055 static void ffi_PDFWidget_validateSignature(js_State *J)
6056 {
6057 fz_context *ctx = js_getcontext(J);
6058 pdf_widget *widget = js_touserdata(J, 0, "pdf_widget");
6059 int val = 0;
6060 fz_try(ctx)
6061 val = pdf_validate_signature(ctx, widget);
6062 fz_catch(ctx)
6063 rethrow(J);
6064 js_pushnumber(J, val);
6065 }
6066
ffi_PDFWidget_isSigned(js_State * J)6067 static void ffi_PDFWidget_isSigned(js_State *J)
6068 {
6069 fz_context *ctx = js_getcontext(J);
6070 pdf_widget *widget = js_touserdata(J, 0, "pdf_widget");
6071 int val = 0;
6072 fz_try(ctx)
6073 val = pdf_widget_is_signed(ctx, widget);
6074 fz_catch(ctx)
6075 rethrow(J);
6076 js_pushboolean(J, val);
6077 }
6078
ffi_PDFWidget_sign(js_State * J)6079 static void ffi_PDFWidget_sign(js_State *J)
6080 {
6081 fz_context *ctx = js_getcontext(J);
6082 pdf_widget *widget = js_touserdata(J, 0, "pdf_widget");
6083 pdf_pkcs7_signer *signer = js_touserdata(J, 1, "pdf_pkcs7_signer");
6084
6085 fz_try(ctx)
6086 pdf_sign_signature(ctx, widget, signer);
6087 fz_catch(ctx)
6088 rethrow(J);
6089 }
6090
ffi_PDFWidget_clearSignature(js_State * J)6091 static void ffi_PDFWidget_clearSignature(js_State *J)
6092 {
6093 fz_context *ctx = js_getcontext(J);
6094 pdf_widget *widget = js_touserdata(J, 0, "pdf_widget");
6095
6096 fz_try(ctx)
6097 pdf_clear_signature(ctx, widget);
6098 fz_catch(ctx)
6099 rethrow(J);
6100 }
6101
ffi_new_PDFPKCS7Signer(js_State * J)6102 static void ffi_new_PDFPKCS7Signer(js_State *J)
6103 {
6104 fz_context *ctx = js_getcontext(J);
6105 pdf_pkcs7_signer *signer = NULL;
6106 const char *filename = js_tostring(J, 1);
6107 const char *password = js_tostring(J, 2);
6108 fz_try(ctx)
6109 signer = pkcs7_openssl_read_pfx(ctx, filename, password);
6110 fz_catch(ctx)
6111 rethrow(J);
6112 ffi_pushsigner(J, signer);
6113 }
6114
6115 #endif /* FZ_ENABLE_PDF */
6116
murun_main(int argc,char ** argv)6117 int murun_main(int argc, char **argv)
6118 {
6119 fz_context *ctx;
6120 js_State *J;
6121 int i;
6122
6123 ctx = fz_new_context(NULL, NULL, FZ_STORE_UNLIMITED);
6124 fz_register_document_handlers(ctx);
6125
6126 J = js_newstate(alloc, ctx, JS_STRICT);
6127 js_setcontext(J, ctx);
6128
6129 /* standard command line javascript functions */
6130
6131 js_newcfunction(J, jsB_gc, "gc", 0);
6132 js_setglobal(J, "gc");
6133
6134 js_newcfunction(J, jsB_load, "load", 1);
6135 js_setglobal(J, "load");
6136
6137 js_newcfunction(J, jsB_print, "print", 1);
6138 js_setglobal(J, "print");
6139
6140 js_newcfunction(J, jsB_write, "write", 0);
6141 js_setglobal(J, "write");
6142
6143 js_newcfunction(J, jsB_read, "read", 1);
6144 js_setglobal(J, "read");
6145
6146 js_newcfunction(J, jsB_readline, "readline", 0);
6147 js_setglobal(J, "readline");
6148
6149 js_newcfunction(J, jsB_repr, "repr", 1);
6150 js_setglobal(J, "repr");
6151
6152 js_newcfunction(J, jsB_quit, "quit", 1);
6153 js_setglobal(J, "quit");
6154
6155 js_dostring(J, require_js);
6156 js_dostring(J, stacktrace_js);
6157
6158 /* mupdf module */
6159
6160 /* Create superclass for all userdata objects */
6161 js_dostring(J, "function Userdata() { throw new Error('Userdata is not callable'); }");
6162 js_getglobal(J, "Userdata");
6163 js_getproperty(J, -1, "prototype");
6164 js_setregistry(J, "Userdata");
6165 js_pop(J, 1);
6166
6167 js_getregistry(J, "Userdata");
6168 js_newobjectx(J);
6169 {
6170 jsB_propfun(J, "Buffer.writeByte", ffi_Buffer_writeByte, 1);
6171 jsB_propfun(J, "Buffer.writeRune", ffi_Buffer_writeRune, 1);
6172 jsB_propfun(J, "Buffer.writeLine", ffi_Buffer_writeLine, 1);
6173 jsB_propfun(J, "Buffer.writeBuffer", ffi_Buffer_writeBuffer, 1);
6174 jsB_propfun(J, "Buffer.write", ffi_Buffer_write, 1);
6175 jsB_propfun(J, "Buffer.save", ffi_Buffer_save, 1);
6176 }
6177 js_setregistry(J, "fz_buffer");
6178
6179 js_getregistry(J, "Userdata");
6180 js_newobjectx(J);
6181 {
6182 jsB_propfun(J, "Document.isPDF", ffi_Document_isPDF, 0);
6183 jsB_propfun(J, "Document.needsPassword", ffi_Document_needsPassword, 0);
6184 jsB_propfun(J, "Document.authenticatePassword", ffi_Document_authenticatePassword, 1);
6185 jsB_propfun(J, "Document.hasPermission", ffi_Document_hasPermission, 1);
6186 jsB_propfun(J, "Document.getMetaData", ffi_Document_getMetaData, 1);
6187 jsB_propfun(J, "Document.isReflowable", ffi_Document_isReflowable, 0);
6188 jsB_propfun(J, "Document.layout", ffi_Document_layout, 3);
6189 jsB_propfun(J, "Document.countPages", ffi_Document_countPages, 0);
6190 jsB_propfun(J, "Document.loadPage", ffi_Document_loadPage, 1);
6191 jsB_propfun(J, "Document.loadOutline", ffi_Document_loadOutline, 0);
6192 }
6193 js_setregistry(J, "fz_document");
6194
6195 js_getregistry(J, "Userdata");
6196 js_newobjectx(J);
6197 {
6198 jsB_propfun(J, "Page.isPDF", ffi_Page_isPDF, 0);
6199 jsB_propfun(J, "Page.bound", ffi_Page_bound, 0);
6200 jsB_propfun(J, "Page.run", ffi_Page_run, 3);
6201 jsB_propfun(J, "Page.toPixmap", ffi_Page_toPixmap, 4);
6202 jsB_propfun(J, "Page.toDisplayList", ffi_Page_toDisplayList, 1);
6203 jsB_propfun(J, "Page.toStructuredText", ffi_Page_toStructuredText, 1);
6204 jsB_propfun(J, "Page.search", ffi_Page_search, 0);
6205 jsB_propfun(J, "Page.getLinks", ffi_Page_getLinks, 0);
6206 }
6207 js_setregistry(J, "fz_page");
6208
6209 js_getregistry(J, "Userdata");
6210 js_newobjectx(J);
6211 {
6212 jsB_propfun(J, "Device.close", ffi_Device_close, 0);
6213
6214 jsB_propfun(J, "Device.fillPath", ffi_Device_fillPath, 7);
6215 jsB_propfun(J, "Device.strokePath", ffi_Device_strokePath, 7);
6216 jsB_propfun(J, "Device.clipPath", ffi_Device_clipPath, 3);
6217 jsB_propfun(J, "Device.clipStrokePath", ffi_Device_clipStrokePath, 3);
6218
6219 jsB_propfun(J, "Device.fillText", ffi_Device_fillText, 6);
6220 jsB_propfun(J, "Device.strokeText", ffi_Device_strokeText, 7);
6221 jsB_propfun(J, "Device.clipText", ffi_Device_clipText, 2);
6222 jsB_propfun(J, "Device.clipStrokeText", ffi_Device_clipStrokeText, 3);
6223 jsB_propfun(J, "Device.ignoreText", ffi_Device_ignoreText, 2);
6224
6225 jsB_propfun(J, "Device.fillShade", ffi_Device_fillShade, 4);
6226 jsB_propfun(J, "Device.fillImage", ffi_Device_fillImage, 4);
6227 jsB_propfun(J, "Device.fillImageMask", ffi_Device_fillImageMask, 6);
6228 jsB_propfun(J, "Device.clipImageMask", ffi_Device_clipImageMask, 2);
6229
6230 jsB_propfun(J, "Device.popClip", ffi_Device_popClip, 0);
6231
6232 jsB_propfun(J, "Device.beginMask", ffi_Device_beginMask, 6);
6233 jsB_propfun(J, "Device.endMask", ffi_Device_endMask, 0);
6234 jsB_propfun(J, "Device.beginGroup", ffi_Device_beginGroup, 5);
6235 jsB_propfun(J, "Device.endGroup", ffi_Device_endGroup, 0);
6236 jsB_propfun(J, "Device.beginTile", ffi_Device_beginTile, 6);
6237 jsB_propfun(J, "Device.endTile", ffi_Device_endTile, 0);
6238
6239 jsB_propfun(J, "Device.beginLayer", ffi_Device_beginLayer, 1);
6240 jsB_propfun(J, "Device.endLayer", ffi_Device_endLayer, 0);
6241 }
6242 js_setregistry(J, "fz_device");
6243
6244 js_getregistry(J, "Userdata");
6245 js_newobjectx(J);
6246 {
6247 jsB_propfun(J, "ColorSpace.getNumberOfComponents", ffi_ColorSpace_getNumberOfComponents, 0);
6248 jsB_propfun(J, "ColorSpace.toString", ffi_ColorSpace_toString, 0);
6249 }
6250 js_setregistry(J, "fz_colorspace");
6251 {
6252 js_getregistry(J, "fz_colorspace");
6253 js_newuserdata(J, "fz_colorspace", fz_keep_colorspace(ctx, fz_device_gray(ctx)), ffi_gc_fz_colorspace);
6254 js_setregistry(J, "DeviceGray");
6255
6256 js_getregistry(J, "fz_colorspace");
6257 js_newuserdata(J, "fz_colorspace", fz_keep_colorspace(ctx, fz_device_rgb(ctx)), ffi_gc_fz_colorspace);
6258 js_setregistry(J, "DeviceRGB");
6259
6260 js_getregistry(J, "fz_colorspace");
6261 js_newuserdata(J, "fz_colorspace", fz_keep_colorspace(ctx, fz_device_bgr(ctx)), ffi_gc_fz_colorspace);
6262 js_setregistry(J, "DeviceBGR");
6263
6264 js_getregistry(J, "fz_colorspace");
6265 js_newuserdata(J, "fz_colorspace", fz_keep_colorspace(ctx, fz_device_cmyk(ctx)), ffi_gc_fz_colorspace);
6266 js_setregistry(J, "DeviceCMYK");
6267 }
6268
6269 js_getregistry(J, "Userdata");
6270 js_newobjectx(J);
6271 {
6272 jsB_propfun(J, "Shade.bound", ffi_Shade_bound, 1);
6273 }
6274 js_setregistry(J, "fz_shade");
6275
6276 js_getregistry(J, "Userdata");
6277 js_newobjectx(J);
6278 {
6279 jsB_propfun(J, "Image.getWidth", ffi_Image_getWidth, 0);
6280 jsB_propfun(J, "Image.getHeight", ffi_Image_getHeight, 0);
6281 jsB_propfun(J, "Image.getColorSpace", ffi_Image_getColorSpace, 0);
6282 jsB_propfun(J, "Image.getXResolution", ffi_Image_getXResolution, 0);
6283 jsB_propfun(J, "Image.getYResolution", ffi_Image_getYResolution, 0);
6284 jsB_propfun(J, "Image.getNumberOfComponents", ffi_Image_getNumberOfComponents, 0);
6285 jsB_propfun(J, "Image.getBitsPerComponent", ffi_Image_getBitsPerComponent, 0);
6286 jsB_propfun(J, "Image.getInterpolate", ffi_Image_getInterpolate, 0);
6287 jsB_propfun(J, "Image.getImageMask", ffi_Image_getImageMask, 0);
6288 jsB_propfun(J, "Image.getMask", ffi_Image_getMask, 0);
6289 jsB_propfun(J, "Image.toPixmap", ffi_Image_toPixmap, 2);
6290 }
6291 js_setregistry(J, "fz_image");
6292
6293 js_getregistry(J, "Userdata");
6294 js_newobjectx(J);
6295 {
6296 jsB_propfun(J, "Font.getName", ffi_Font_getName, 0);
6297 jsB_propfun(J, "Font.encodeCharacter", ffi_Font_encodeCharacter, 1);
6298 jsB_propfun(J, "Font.advanceGlyph", ffi_Font_advanceGlyph, 2);
6299 }
6300 js_setregistry(J, "fz_font");
6301
6302 js_getregistry(J, "Userdata");
6303 js_newobjectx(J);
6304 {
6305 jsB_propfun(J, "Text.walk", ffi_Text_walk, 1);
6306 jsB_propfun(J, "Text.showGlyph", ffi_Text_showGlyph, 5);
6307 jsB_propfun(J, "Text.showString", ffi_Text_showString, 4);
6308 }
6309 js_setregistry(J, "fz_text");
6310
6311 js_getregistry(J, "Userdata");
6312 js_newobjectx(J);
6313 {
6314 jsB_propfun(J, "Path.walk", ffi_Path_walk, 1);
6315 jsB_propfun(J, "Path.moveTo", ffi_Path_moveTo, 2);
6316 jsB_propfun(J, "Path.lineTo", ffi_Path_lineTo, 2);
6317 jsB_propfun(J, "Path.curveTo", ffi_Path_curveTo, 6);
6318 jsB_propfun(J, "Path.curveToV", ffi_Path_curveToV, 4);
6319 jsB_propfun(J, "Path.curveToY", ffi_Path_curveToY, 4);
6320 jsB_propfun(J, "Path.closePath", ffi_Path_closePath, 0);
6321 jsB_propfun(J, "Path.rect", ffi_Path_rect, 4);
6322 jsB_propfun(J, "Path.bound", ffi_Path_bound, 2);
6323 jsB_propfun(J, "Path.transform", ffi_Path_transform, 1);
6324 }
6325 js_setregistry(J, "fz_path");
6326
6327 js_getregistry(J, "Userdata");
6328 js_newobjectx(J);
6329 {
6330 jsB_propfun(J, "DisplayList.run", ffi_DisplayList_run, 2);
6331 jsB_propfun(J, "DisplayList.toPixmap", ffi_DisplayList_toPixmap, 3);
6332 jsB_propfun(J, "DisplayList.toStructuredText", ffi_DisplayList_toStructuredText, 1);
6333 jsB_propfun(J, "DisplayList.search", ffi_DisplayList_search, 1);
6334 }
6335 js_setregistry(J, "fz_display_list");
6336
6337 js_getregistry(J, "Userdata");
6338 js_newobjectx(J);
6339 {
6340 jsB_propfun(J, "StructuredText.walk", ffi_StructuredText_walk, 1);
6341 jsB_propfun(J, "StructuredText.search", ffi_StructuredText_search, 1);
6342 jsB_propfun(J, "StructuredText.highlight", ffi_StructuredText_highlight, 2);
6343 jsB_propfun(J, "StructuredText.copy", ffi_StructuredText_copy, 2);
6344 }
6345 js_setregistry(J, "fz_stext_page");
6346
6347 js_getregistry(J, "Userdata");
6348 js_newobjectx(J);
6349 {
6350 jsB_propfun(J, "Pixmap.bound", ffi_Pixmap_bound, 0);
6351 jsB_propfun(J, "Pixmap.clear", ffi_Pixmap_clear, 1);
6352
6353 jsB_propfun(J, "Pixmap.getX", ffi_Pixmap_getX, 0);
6354 jsB_propfun(J, "Pixmap.getY", ffi_Pixmap_getY, 0);
6355 jsB_propfun(J, "Pixmap.getWidth", ffi_Pixmap_getWidth, 0);
6356 jsB_propfun(J, "Pixmap.getHeight", ffi_Pixmap_getHeight, 0);
6357 jsB_propfun(J, "Pixmap.getNumberOfComponents", ffi_Pixmap_getNumberOfComponents, 0);
6358 jsB_propfun(J, "Pixmap.getAlpha", ffi_Pixmap_getAlpha, 0);
6359 jsB_propfun(J, "Pixmap.getStride", ffi_Pixmap_getStride, 0);
6360 jsB_propfun(J, "Pixmap.getColorSpace", ffi_Pixmap_getColorSpace, 0);
6361 jsB_propfun(J, "Pixmap.getXResolution", ffi_Pixmap_getXResolution, 0);
6362 jsB_propfun(J, "Pixmap.getYResolution", ffi_Pixmap_getYResolution, 0);
6363 jsB_propfun(J, "Pixmap.getSample", ffi_Pixmap_getSample, 3);
6364 jsB_propfun(J, "Pixmap.warp", ffi_Pixmap_warp, 3);
6365
6366 // Pixmap.samples()
6367 // Pixmap.invert
6368 // Pixmap.tint
6369 // Pixmap.gamma
6370 // Pixmap.scale()
6371
6372 jsB_propfun(J, "Pixmap.saveAsPNG", ffi_Pixmap_saveAsPNG, 1);
6373 // Pixmap.saveAsPNM, PAM, PWG, PCL
6374
6375 // Pixmap.halftone() -> Bitmap
6376 // Pixmap.md5()
6377 }
6378 js_setregistry(J, "fz_pixmap");
6379
6380 js_getregistry(J, "Userdata");
6381 js_newobjectx(J);
6382 {
6383 jsB_propfun(J, "DocumentWriter.beginPage", ffi_DocumentWriter_beginPage, 1);
6384 jsB_propfun(J, "DocumentWriter.endPage", ffi_DocumentWriter_endPage, 0);
6385 jsB_propfun(J, "DocumentWriter.close", ffi_DocumentWriter_close, 0);
6386 }
6387 js_setregistry(J, "fz_document_writer");
6388
6389 #if FZ_ENABLE_PDF
6390 js_getregistry(J, "fz_document");
6391 js_newobjectx(J);
6392 {
6393 jsB_propfun(J, "PDFDocument.getTrailer", ffi_PDFDocument_getTrailer, 0);
6394 jsB_propfun(J, "PDFDocument.countObjects", ffi_PDFDocument_countObjects, 0);
6395 jsB_propfun(J, "PDFDocument.createObject", ffi_PDFDocument_createObject, 0);
6396 jsB_propfun(J, "PDFDocument.deleteObject", ffi_PDFDocument_deleteObject, 1);
6397 jsB_propfun(J, "PDFDocument.addObject", ffi_PDFDocument_addObject, 1);
6398 jsB_propfun(J, "PDFDocument.addStream", ffi_PDFDocument_addStream, 2);
6399 jsB_propfun(J, "PDFDocument.addRawStream", ffi_PDFDocument_addRawStream, 2);
6400 jsB_propfun(J, "PDFDocument.addSimpleFont", ffi_PDFDocument_addSimpleFont, 2);
6401 jsB_propfun(J, "PDFDocument.addCJKFont", ffi_PDFDocument_addCJKFont, 4);
6402 jsB_propfun(J, "PDFDocument.addFont", ffi_PDFDocument_addFont, 1);
6403 jsB_propfun(J, "PDFDocument.addImage", ffi_PDFDocument_addImage, 1);
6404 jsB_propfun(J, "PDFDocument.loadImage", ffi_PDFDocument_loadImage, 1);
6405 jsB_propfun(J, "PDFDocument.addPage", ffi_PDFDocument_addPage, 4);
6406 jsB_propfun(J, "PDFDocument.insertPage", ffi_PDFDocument_insertPage, 2);
6407 jsB_propfun(J, "PDFDocument.deletePage", ffi_PDFDocument_deletePage, 1);
6408 jsB_propfun(J, "PDFDocument.countPages", ffi_PDFDocument_countPages, 0);
6409 jsB_propfun(J, "PDFDocument.findPage", ffi_PDFDocument_findPage, 1);
6410 jsB_propfun(J, "PDFDocument.save", ffi_PDFDocument_save, 2);
6411
6412 jsB_propfun(J, "PDFDocument.newNull", ffi_PDFDocument_newNull, 0);
6413 jsB_propfun(J, "PDFDocument.newBoolean", ffi_PDFDocument_newBoolean, 1);
6414 jsB_propfun(J, "PDFDocument.newInteger", ffi_PDFDocument_newInteger, 1);
6415 jsB_propfun(J, "PDFDocument.newReal", ffi_PDFDocument_newReal, 1);
6416 jsB_propfun(J, "PDFDocument.newString", ffi_PDFDocument_newString, 1);
6417 jsB_propfun(J, "PDFDocument.newByteString", ffi_PDFDocument_newByteString, 1);
6418 jsB_propfun(J, "PDFDocument.newName", ffi_PDFDocument_newName, 1);
6419 jsB_propfun(J, "PDFDocument.newIndirect", ffi_PDFDocument_newIndirect, 2);
6420 jsB_propfun(J, "PDFDocument.newArray", ffi_PDFDocument_newArray, 1);
6421 jsB_propfun(J, "PDFDocument.newDictionary", ffi_PDFDocument_newDictionary, 1);
6422
6423 jsB_propfun(J, "PDFDocument.newGraftMap", ffi_PDFDocument_newGraftMap, 0);
6424 jsB_propfun(J, "PDFDocument.graftObject", ffi_PDFDocument_graftObject, 1);
6425 jsB_propfun(J, "PDFDocument.graftPage", ffi_PDFDocument_graftPage, 3);
6426
6427 jsB_propfun(J, "PDFDocument.enableJS", ffi_PDFDocument_enableJS, 0);
6428 jsB_propfun(J, "PDFDocument.countVersions", ffi_PDFDocument_countVersions, 0);
6429 jsB_propfun(J, "PDFDocument.countUnsavedVersions", ffi_PDFDocument_countUnsavedVersions, 0);
6430 jsB_propfun(J, "PDFDocument.validateChangeHistory", ffi_PDFDocument_validateChangeHistory, 0);
6431 jsB_propfun(J, "PDFDocument.wasPureXFA", ffi_PDFDocument_wasPureXFA, 0);
6432
6433 jsB_propfun(J, "PDFDocument.hasUnsavedChanges", ffi_PDFDocument_hasUnsavedChanges, 0);
6434 jsB_propfun(J, "PDFDocument.wasRepaired", ffi_PDFDocument_wasRepaired, 0);
6435 jsB_propfun(J, "PDFDocument.canBeSavedIncrementally", ffi_PDFDocument_canBeSavedIncrementally, 0);
6436 }
6437 js_setregistry(J, "pdf_document");
6438
6439 js_getregistry(J, "fz_page");
6440 js_newobjectx(J);
6441 {
6442 jsB_propfun(J, "PDFPage.getWidgets", ffi_PDFPage_getWidgets, 0);
6443 jsB_propfun(J, "PDFPage.getAnnotations", ffi_PDFPage_getAnnotations, 0);
6444 jsB_propfun(J, "PDFPage.createAnnotation", ffi_PDFPage_createAnnotation, 1);
6445 jsB_propfun(J, "PDFPage.deleteAnnotation", ffi_PDFPage_deleteAnnotation, 1);
6446 jsB_propfun(J, "PDFPage.update", ffi_PDFPage_update, 0);
6447 jsB_propfun(J, "PDFPage.applyRedactions", ffi_PDFPage_applyRedactions, 2);
6448 jsB_propfun(J, "PDFPage.process", ffi_PDFPage_process, 1);
6449 }
6450 js_setregistry(J, "pdf_page");
6451
6452 js_getregistry(J, "Userdata");
6453 js_newobjectx(J);
6454 {
6455 jsB_propfun(J, "PDFAnnotation.bound", ffi_PDFAnnotation_bound, 0);
6456 jsB_propfun(J, "PDFAnnotation.run", ffi_PDFAnnotation_run, 2);
6457 jsB_propfun(J, "PDFAnnotation.toPixmap", ffi_PDFAnnotation_toPixmap, 3);
6458 jsB_propfun(J, "PDFAnnotation.toDisplayList", ffi_PDFAnnotation_toDisplayList, 0);
6459
6460 jsB_propfun(J, "PDFAnnotation.getType", ffi_PDFAnnotation_getType, 0);
6461 jsB_propfun(J, "PDFAnnotation.getFlags", ffi_PDFAnnotation_getFlags, 0);
6462 jsB_propfun(J, "PDFAnnotation.setFlags", ffi_PDFAnnotation_setFlags, 1);
6463 jsB_propfun(J, "PDFAnnotation.getContents", ffi_PDFAnnotation_getContents, 0);
6464 jsB_propfun(J, "PDFAnnotation.setContents", ffi_PDFAnnotation_setContents, 1);
6465 jsB_propfun(J, "PDFAnnotation.getRect", ffi_PDFAnnotation_getRect, 0);
6466 jsB_propfun(J, "PDFAnnotation.setRect", ffi_PDFAnnotation_setRect, 1);
6467 jsB_propfun(J, "PDFAnnotation.getBorder", ffi_PDFAnnotation_getBorder, 0);
6468 jsB_propfun(J, "PDFAnnotation.setBorder", ffi_PDFAnnotation_setBorder, 1);
6469 jsB_propfun(J, "PDFAnnotation.getColor", ffi_PDFAnnotation_getColor, 0);
6470 jsB_propfun(J, "PDFAnnotation.setColor", ffi_PDFAnnotation_setColor, 1);
6471 jsB_propfun(J, "PDFAnnotation.getInteriorColor", ffi_PDFAnnotation_getInteriorColor, 0);
6472 jsB_propfun(J, "PDFAnnotation.setInteriorColor", ffi_PDFAnnotation_setInteriorColor, 1);
6473 jsB_propfun(J, "PDFAnnotation.getAuthor", ffi_PDFAnnotation_getAuthor, 0);
6474 jsB_propfun(J, "PDFAnnotation.setAuthor", ffi_PDFAnnotation_setAuthor, 1);
6475 jsB_propfun(J, "PDFAnnotation.getModificationDate", ffi_PDFAnnotation_getModificationDate, 0);
6476 jsB_propfun(J, "PDFAnnotation.setModificationDate", ffi_PDFAnnotation_setModificationDate, 0);
6477 jsB_propfun(J, "PDFAnnotation.getLineEndingStyles", ffi_PDFAnnotation_getLineEndingStyles, 0);
6478 jsB_propfun(J, "PDFAnnotation.setLineEndingStyles", ffi_PDFAnnotation_setLineEndingStyles, 0);
6479
6480 jsB_propfun(J, "PDFAnnotation.getInkList", ffi_PDFAnnotation_getInkList, 0);
6481 jsB_propfun(J, "PDFAnnotation.setInkList", ffi_PDFAnnotation_setInkList, 1);
6482 jsB_propfun(J, "PDFAnnotation.clearInkList", ffi_PDFAnnotation_clearInkList, 0);
6483 jsB_propfun(J, "PDFAnnotation.addInkList", ffi_PDFAnnotation_addInkList, 1);
6484 jsB_propfun(J, "PDFAnnotation.addInkListStroke", ffi_PDFAnnotation_addInkListStroke, 0);
6485 jsB_propfun(J, "PDFAnnotation.addInkListStrokeVertex", ffi_PDFAnnotation_addInkListStrokeVertex, 2);
6486
6487 jsB_propfun(J, "PDFAnnotation.getQuadPoints", ffi_PDFAnnotation_getQuadPoints, 0);
6488 jsB_propfun(J, "PDFAnnotation.setQuadPoints", ffi_PDFAnnotation_setQuadPoints, 1);
6489 jsB_propfun(J, "PDFAnnotation.clearQuadPoints", ffi_PDFAnnotation_clearQuadPoints, 0);
6490 jsB_propfun(J, "PDFAnnotation.addQuadPoint", ffi_PDFAnnotation_addQuadPoint, 1);
6491
6492 jsB_propfun(J, "PDFAnnotation.getVertices", ffi_PDFAnnotation_getVertices, 0);
6493 jsB_propfun(J, "PDFAnnotation.setVertices", ffi_PDFAnnotation_setVertices, 1);
6494 jsB_propfun(J, "PDFAnnotation.clearVertices", ffi_PDFAnnotation_clearVertices, 0);
6495 jsB_propfun(J, "PDFAnnotation.addVertex", ffi_PDFAnnotation_addVertex, 2);
6496
6497 jsB_propfun(J, "PDFAnnotation.updateAppearance", ffi_PDFAnnotation_updateAppearance, 0);
6498 jsB_propfun(J, "PDFAnnotation.update", ffi_PDFAnnotation_update, 0);
6499
6500 jsB_propfun(J, "PDFAnnotation.process", ffi_PDFAnnotation_process, 1);
6501 }
6502 js_dup(J);
6503 js_setglobal(J, "PDFAnnot");
6504 js_setregistry(J, "pdf_annot");
6505
6506 js_getregistry(J, "Userdata");
6507 js_newobjectx(J);
6508 {
6509 // jsB_propfun(J, "PDFWidget.bound", ffi_PDFWidget_bound, 0);
6510 // jsB_propfun(J, "PDFWidget.run", ffi_PDFWidget_run, 2);
6511 // jsB_propfun(J, "PDFWidget.toPixmap", ffi_PDFWidget_toPixmap, 3);
6512 // jsB_propfun(J, "PDFWidget.toDisplayList", ffi_PDFWidget_toDisplayList, 0);
6513
6514 jsB_propfun(J, "PDFWidget.getFieldType", ffi_PDFWidget_getFieldType, 0);
6515 jsB_propfun(J, "PDFWidget.getFieldFlags", ffi_PDFWidget_getFieldFlags, 0);
6516 jsB_propfun(J, "PDFWidget.getRect", ffi_PDFWidget_getRect, 0);
6517 jsB_propfun(J, "PDFWidget.setRect", ffi_PDFWidget_setRect, 1);
6518 jsB_propfun(J, "PDFWidget.getValue", ffi_PDFWidget_getValue, 0);
6519 jsB_propfun(J, "PDFWidget.setTextValue", ffi_PDFWidget_setTextValue, 1);
6520 jsB_propfun(J, "PDFWidget.setChoiceValue", ffi_PDFWidget_setChoiceValue, 1);
6521 jsB_propfun(J, "PDFWidget.toggle", ffi_PDFWidget_toggle, 0);
6522 jsB_propfun(J, "PDFWidget.getMaxLen", ffi_PDFWidget_getMaxLen, 0);
6523 jsB_propfun(J, "PDFWidget.getOptions", ffi_PDFWidget_getOptions, 1);
6524
6525 jsB_propfun(J, "PDFWidget.update", ffi_PDFWidget_update, 0);
6526
6527 jsB_propfun(J, "PDFWidget.eventEnter", ffi_PDFWidget_eventEnter, 0);
6528 jsB_propfun(J, "PDFWidget.eventExit", ffi_PDFWidget_eventExit, 0);
6529 jsB_propfun(J, "PDFWidget.eventDown", ffi_PDFWidget_eventDown, 0);
6530 jsB_propfun(J, "PDFWidget.eventUp", ffi_PDFWidget_eventUp, 0);
6531 jsB_propfun(J, "PDFWidget.eventFocus", ffi_PDFWidget_eventFocus, 0);
6532 jsB_propfun(J, "PDFWidget.eventBlur", ffi_PDFWidget_eventBlur, 0);
6533 jsB_propfun(J, "PDFWidget.validateSignature", ffi_PDFWidget_validateSignature, 0);
6534 jsB_propfun(J, "PDFWidget.isSigned", ffi_PDFWidget_isSigned, 0);
6535 jsB_propfun(J, "PDFWidget.sign", ffi_PDFWidget_sign, 1);
6536 jsB_propfun(J, "PDFWidget.clearSignature", ffi_PDFWidget_clearSignature, 0);
6537 }
6538 js_dup(J);
6539 js_setglobal(J, "PDFWidget");
6540 js_setregistry(J, "pdf_widget");
6541
6542 js_getregistry(J, "Userdata");
6543 js_newobjectx(J);
6544 {
6545 }
6546 js_dup(J);
6547 js_setglobal(J, "PDFPKCS7Signer");
6548 js_setregistry(J, "pdf_pkcs7_signer");
6549
6550 js_getregistry(J, "Userdata");
6551 js_newobjectx(J);
6552 {
6553 jsB_propfun(J, "PDFObject.get", ffi_PDFObject_get, 1);
6554 jsB_propfun(J, "PDFObject.put", ffi_PDFObject_put, 2);
6555 jsB_propfun(J, "PDFObject.push", ffi_PDFObject_push, 1);
6556 jsB_propfun(J, "PDFObject.delete", ffi_PDFObject_delete, 1);
6557 jsB_propfun(J, "PDFObject.resolve", ffi_PDFObject_resolve, 0);
6558 jsB_propfun(J, "PDFObject.toString", ffi_PDFObject_toString, 2);
6559 jsB_propfun(J, "PDFObject.valueOf", ffi_PDFObject_valueOf, 0);
6560 jsB_propfun(J, "PDFObject.isArray", ffi_PDFObject_isArray, 0);
6561 jsB_propfun(J, "PDFObject.isDictionary", ffi_PDFObject_isDictionary, 0);
6562 jsB_propfun(J, "PDFObject.isIndirect", ffi_PDFObject_isIndirect, 0);
6563 jsB_propfun(J, "PDFObject.asIndirect", ffi_PDFObject_asIndirect, 0);
6564 jsB_propfun(J, "PDFObject.isNull", ffi_PDFObject_isNull, 0);
6565 jsB_propfun(J, "PDFObject.isBoolean", ffi_PDFObject_isBoolean, 0);
6566 jsB_propfun(J, "PDFObject.asBoolean", ffi_PDFObject_asBoolean, 0);
6567 jsB_propfun(J, "PDFObject.isNumber", ffi_PDFObject_isNumber, 0);
6568 jsB_propfun(J, "PDFObject.asNumber", ffi_PDFObject_asNumber, 0);
6569 jsB_propfun(J, "PDFObject.isName", ffi_PDFObject_isName, 0);
6570 jsB_propfun(J, "PDFObject.asName", ffi_PDFObject_asName, 0);
6571 jsB_propfun(J, "PDFObject.isString", ffi_PDFObject_isString, 0);
6572 jsB_propfun(J, "PDFObject.asString", ffi_PDFObject_asString, 0);
6573 jsB_propfun(J, "PDFObject.asByteString", ffi_PDFObject_asByteString, 0);
6574 jsB_propfun(J, "PDFObject.isStream", ffi_PDFObject_isStream, 0);
6575 jsB_propfun(J, "PDFObject.readStream", ffi_PDFObject_readStream, 0);
6576 jsB_propfun(J, "PDFObject.readRawStream", ffi_PDFObject_readRawStream, 0);
6577 jsB_propfun(J, "PDFObject.writeObject", ffi_PDFObject_writeObject, 1);
6578 jsB_propfun(J, "PDFObject.writeStream", ffi_PDFObject_writeStream, 1);
6579 jsB_propfun(J, "PDFObject.writeRawStream", ffi_PDFObject_writeRawStream, 1);
6580 jsB_propfun(J, "PDFObject.forEach", ffi_PDFObject_forEach, 1);
6581 }
6582 js_setregistry(J, "pdf_obj");
6583
6584 js_getregistry(J, "Userdata");
6585 js_newobjectx(J);
6586 {
6587 jsB_propfun(J, "PDFGraftMap.graftObject", ffi_PDFGraftMap_graftObject, 1);
6588 jsB_propfun(J, "PDFGraftMap.graftPage", ffi_PDFGraftMap_graftPage, 3);
6589 }
6590 js_setregistry(J, "pdf_graft_map");
6591 #endif
6592
6593 js_pushglobal(J);
6594 {
6595 #if FZ_ENABLE_PDF
6596 jsB_propcon(J, "pdf_document", "PDFDocument", ffi_new_PDFDocument, 1);
6597 #endif
6598
6599 jsB_propcon(J, "fz_buffer", "Buffer", ffi_new_Buffer, 1);
6600 jsB_propcon(J, "fz_document", "Document", ffi_new_Document, 1);
6601 jsB_propcon(J, "fz_pixmap", "Pixmap", ffi_new_Pixmap, 3);
6602 jsB_propcon(J, "fz_image", "Image", ffi_new_Image, 2);
6603 jsB_propcon(J, "fz_font", "Font", ffi_new_Font, 2);
6604 jsB_propcon(J, "fz_text", "Text", ffi_new_Text, 0);
6605 jsB_propcon(J, "fz_path", "Path", ffi_new_Path, 0);
6606 jsB_propcon(J, "fz_display_list", "DisplayList", ffi_new_DisplayList, 1);
6607 jsB_propcon(J, "fz_device", "DrawDevice", ffi_new_DrawDevice, 2);
6608 jsB_propcon(J, "fz_device", "DisplayListDevice", ffi_new_DisplayListDevice, 1);
6609 jsB_propcon(J, "fz_document_writer", "DocumentWriter", ffi_new_DocumentWriter, 3);
6610 jsB_propcon(J, "pdf_pkcs7_signer", "PDFPKCS7Signer", ffi_new_PDFPKCS7Signer, 2);
6611
6612 jsB_propfun(J, "readFile", ffi_readFile, 1);
6613
6614 js_getregistry(J, "DeviceGray");
6615 js_defproperty(J, -2, "DeviceGray", JS_DONTENUM | JS_READONLY | JS_DONTCONF);
6616
6617 js_getregistry(J, "DeviceRGB");
6618 js_defproperty(J, -2, "DeviceRGB", JS_DONTENUM | JS_READONLY | JS_DONTCONF);
6619
6620 js_getregistry(J, "DeviceBGR");
6621 js_defproperty(J, -2, "DeviceBGR", JS_DONTENUM | JS_READONLY | JS_DONTCONF);
6622
6623 js_getregistry(J, "DeviceCMYK");
6624 js_defproperty(J, -2, "DeviceCMYK", JS_DONTENUM | JS_READONLY | JS_DONTCONF);
6625
6626 jsB_propfun(J, "setUserCSS", ffi_setUserCSS, 2);
6627 }
6628
6629 /* re-implement matrix math in javascript */
6630 js_dostring(J, "var Identity = Object.freeze([1,0,0,1,0,0]);");
6631 js_dostring(J, "function Scale(sx,sy) { return [sx,0,0,sy,0,0]; }");
6632 js_dostring(J, "function Translate(tx,ty) { return [1,0,0,1,tx,ty]; }");
6633 js_dostring(J, "function Concat(a,b) { return ["
6634 "a[0] * b[0] + a[1] * b[2],"
6635 "a[0] * b[1] + a[1] * b[3],"
6636 "a[2] * b[0] + a[3] * b[2],"
6637 "a[2] * b[1] + a[3] * b[3],"
6638 "a[4] * b[0] + a[5] * b[2] + b[4],"
6639 "a[4] * b[1] + a[5] * b[3] + b[5]];}");
6640
6641 if (argc > 1) {
6642 js_pushstring(J, argv[1]);
6643 js_setglobal(J, "scriptPath");
6644 js_newarray(J);
6645 for (i = 2; i < argc; ++i) {
6646 js_pushstring(J, argv[i]);
6647 js_setindex(J, -2, i - 2);
6648 }
6649 js_setglobal(J, "scriptArgs");
6650 if (js_dofile(J, argv[1]))
6651 {
6652 js_freestate(J);
6653 fz_drop_context(ctx);
6654 return 1;
6655 }
6656 } else {
6657 char line[256];
6658 fputs(PS1, stdout);
6659 while (fgets(line, sizeof line, stdin)) {
6660 eval_print(J, line);
6661 fputs(PS1, stdout);
6662 }
6663 putchar('\n');
6664 }
6665
6666 js_freestate(J);
6667 fz_drop_context(ctx);
6668 return 0;
6669 }
6670
6671 #endif
6672