comparison mupdf-source/source/tools/murun.c @ 2:b50eed0cc0ef upstream

ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4. The directory name has changed: no version number in the expanded directory now.
author Franz Glasner <fzglas.hg@dom66.de>
date Mon, 15 Sep 2025 11:43:07 +0200
parents
children
comparison
equal deleted inserted replaced
1:1d09e1dec1d9 2:b50eed0cc0ef
1 // Copyright (C) 2004-2025 Artifex Software, Inc.
2 //
3 // This file is part of MuPDF.
4 //
5 // MuPDF is free software: you can redistribute it and/or modify it under the
6 // terms of the GNU Affero General Public License as published by the Free
7 // Software Foundation, either version 3 of the License, or (at your option)
8 // any later version.
9 //
10 // MuPDF is distributed in the hope that it will be useful, but WITHOUT ANY
11 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12 // FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
13 // details.
14 //
15 // You should have received a copy of the GNU Affero General Public License
16 // along with MuPDF. If not, see <https://www.gnu.org/licenses/agpl-3.0.en.html>
17 //
18 // Alternative licensing terms are available from the licensor.
19 // For commercial licensing, see <https://www.artifex.com/> or contact
20 // Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco,
21 // CA 94129, USA, for further information.
22
23 #include "mupdf/fitz.h"
24
25 #if FZ_ENABLE_PDF
26 #include "mupdf/pdf.h"
27 #include "mupdf/helpers/pkcs7-openssl.h"
28 #endif
29
30 #if FZ_ENABLE_JS
31
32 #include "mujs.h"
33
34 #include <string.h>
35 #include <stdlib.h>
36 #include <stdio.h>
37 #include <math.h>
38
39 #define PS1 "> "
40
41 FZ_NORETURN static void rethrow(js_State *J)
42 {
43 js_newerror(J, fz_convert_error(js_getcontext(J), NULL));
44 js_throw(J);
45 }
46
47 FZ_NORETURN static void rethrow_as_fz(js_State *J)
48 {
49 fz_throw(js_getcontext(J), FZ_ERROR_GENERIC, "%s", js_tostring(J, -1));
50 }
51
52 static void *alloc(void *actx, void *ptr, int n)
53 {
54 return fz_realloc_no_throw(actx, ptr, n);
55 }
56
57 static int eval_print(js_State *J, const char *source)
58 {
59 if (js_ploadstring(J, "[string]", source)) {
60 fprintf(stderr, "%s\n", js_trystring(J, -1, "Error"));
61 js_pop(J, 1);
62 return 1;
63 }
64 js_pushundefined(J);
65 if (js_pcall(J, 0)) {
66 fprintf(stderr, "%s\n", js_trystring(J, -1, "Error"));
67 js_pop(J, 1);
68 return 1;
69 }
70 if (js_isdefined(J, -1)) {
71 printf("%s\n", js_tryrepr(J, -1, "can't convert to string"));
72 }
73 js_pop(J, 1);
74 return 0;
75 }
76
77 static void jsB_propfun(js_State *J, const char *name, js_CFunction cfun, int n)
78 {
79 const char *realname = strchr(name, '.');
80 realname = realname ? realname + 1 : name;
81 js_newcfunction(J, cfun, name, n);
82 js_defproperty(J, -2, realname, JS_DONTENUM);
83 }
84
85 static void jsB_propcon(js_State *J, const char *tag, const char *name, js_CFunction cfun, int n)
86 {
87 const char *realname = strchr(name, '.');
88 realname = realname ? realname + 1 : name;
89 js_getregistry(J, tag);
90 js_newcconstructor(J, cfun, cfun, name, n);
91 js_defproperty(J, -2, realname, JS_DONTENUM);
92 }
93
94 static void jsB_gc(js_State *J)
95 {
96 int report = js_toboolean(J, 1);
97 js_gc(J, report);
98 }
99
100 static void jsB_load(js_State *J)
101 {
102 const char *filename = js_tostring(J, 1);
103 int rv = js_dofile(J, filename);
104 js_pushboolean(J, !rv);
105 }
106
107 static void jsB_print(js_State *J)
108 {
109 unsigned int i, top = js_gettop(J);
110 for (i = 1; i < top; ++i) {
111 const char *s = js_tostring(J, i);
112 if (i > 1) putchar(' ');
113 fputs(s, stdout);
114 }
115 putchar('\n');
116 }
117
118 static void jsB_write(js_State *J)
119 {
120 unsigned int i, top = js_gettop(J);
121 for (i = 1; i < top; ++i) {
122 const char *s = js_tostring(J, i);
123 if (i > 1) putchar(' ');
124 fputs(s, stdout);
125 }
126 }
127
128 static void jsB_read(js_State *J)
129 {
130 fz_context *ctx = js_getcontext(J);
131 const char *filename = js_tostring(J, 1);
132 FILE *f;
133 char *s;
134 long n;
135 size_t t;
136
137 f = fopen(filename, "rb");
138 if (!f) {
139 js_error(J, "cannot open file: '%s'", filename);
140 }
141
142 if (fseek(f, 0, SEEK_END) < 0) {
143 fclose(f);
144 js_error(J, "cannot seek in file: '%s'", filename);
145 }
146
147 n = ftell(f);
148 if (n < 0) {
149 fclose(f);
150 js_error(J, "cannot tell in file: '%s'", filename);
151 }
152
153 if (fseek(f, 0, SEEK_SET) < 0) {
154 fclose(f);
155 js_error(J, "cannot seek in file: '%s'", filename);
156 }
157
158 s = fz_malloc(ctx, n + 1);
159 if (!s) {
160 fclose(f);
161 js_error(J, "cannot allocate storage for file contents: '%s'", filename);
162 }
163
164 t = fread(s, 1, n, f);
165 if (t != (size_t) n) {
166 fz_free(ctx, s);
167 fclose(f);
168 js_error(J, "cannot read data from file: '%s'", filename);
169 }
170 s[n] = 0;
171
172 js_pushstring(J, s);
173 fz_free(ctx, s);
174 fclose(f);
175 }
176
177 static void jsB_readline(js_State *J)
178 {
179 char line[256];
180 size_t n;
181 if (!fgets(line, sizeof line, stdin))
182 js_error(J, "cannot read line from stdin");
183 n = strlen(line);
184 if (n > 0 && line[n-1] == '\n')
185 line[n-1] = 0;
186 js_pushstring(J, line);
187 }
188
189 static void jsB_repr(js_State *J)
190 {
191 js_repr(J, 1);
192 }
193
194 static const char *import_stms[] = {
195 "import * as mupdf from \"mupdf\"",
196 "import * as mupdf from 'mupdf'",
197 "import mupdf from \"mupdf\"",
198 "import mupdf from 'mupdf'",
199 "import * as fs from \"fs\"",
200 "import * as fs from 'fs'",
201 "import fs from \"fs\"",
202 "import fs from 'fs'",
203 };
204
205 static int murun_dofile(js_State *J, const char *filename)
206 {
207 fz_context *ctx = js_getcontext(J);
208 FILE *f;
209 char *imp;
210 char *s;
211 long n;
212 size_t t;
213 int i;
214
215 f = fopen(filename, "rb");
216 if (!f) {
217 js_error(J, "cannot open file: '%s'", filename);
218 }
219
220 if (fseek(f, 0, SEEK_END) < 0) {
221 fclose(f);
222 js_error(J, "cannot seek in file: '%s'", filename);
223 }
224
225 n = ftell(f);
226 if (n < 0) {
227 fclose(f);
228 js_error(J, "cannot tell in file: '%s'", filename);
229 }
230
231 if (fseek(f, 0, SEEK_SET) < 0) {
232 fclose(f);
233 js_error(J, "cannot seek in file: '%s'", filename);
234 }
235
236 s = fz_malloc(ctx, n + 1);
237 if (!s) {
238 fclose(f);
239 js_error(J, "cannot allocate storage for file contents: '%s'", filename);
240 }
241
242 t = fread(s, 1, n, f);
243 if (t != (size_t) n) {
244 fz_free(ctx, s);
245 fclose(f);
246 js_error(J, "cannot read data from file: '%s'", filename);
247 }
248 s[n] = 0;
249
250 fclose(f);
251
252 // Scrub "import mupdf" statements so that the same scripts
253 // can run in both mupdf.js and mutool run if they otherwise
254 // stick to ES5 syntax.
255 for (i = 0; i < (int)nelem(import_stms); ++i)
256 {
257 imp = strstr(s, import_stms[i]);
258 if (imp)
259 memset(imp, ' ', strlen(import_stms[i]));
260 }
261
262 i = js_dostring(J, s);
263 fz_free(ctx, s);
264 return i;
265 }
266
267 JS_NORETURN
268 static void jsB_quit(js_State *J)
269 {
270 fz_context *ctx = js_getcontext(J);
271 int status = js_tonumber(J, 1);
272 js_freestate(J);
273 fz_drop_context(ctx);
274 exit(status);
275 }
276
277 static const char *prefix_js =
278 "var console = { log: print, info: print, error: print }\n"
279 "function require(name) {\n"
280 " var cache = require.cache\n"
281 " if (name in cache) return cache[name]\n"
282 " var exports = cache[name] = {}\n"
283 " Function('exports', read(name+'.js'))(exports)\n"
284 " return exports\n"
285 "}\n"
286 "require.cache = Object.create(null)\n"
287 "Error.prototype.toString = function() {\n"
288 " if (this.stackTrace) return this.name + ': ' + this.message + this.stackTrace\n"
289 " return this.name + ': ' + this.message\n"
290 "}\n"
291 ;
292
293 const char *postfix_js =
294 "var fs = {\n"
295 " readFileSync: readFile,\n"
296 " writeFileSync: function (fn, buf) { buf.save(fn) }\n"
297 "}\n"
298 "var process = { argv: [] }\n"
299 "require.cache.mupdf = mupdf\n"
300 "require.cache.fs = fs\n"
301 "\n"
302 "mupdf.Matrix = {\n"
303 " identity: [ 1, 0, 0, 1, 0, 0 ],\n"
304 " scale: function (sx, sy) {\n"
305 " return [ sx, 0, 0, sy, 0, 0 ]\n"
306 " },\n"
307 " translate: function (tx, ty) {\n"
308 " return [ 1, 0, 0, 1, tx, ty ]\n"
309 " },\n"
310 " rotate: function (d) {\n"
311 " while (d < 0)\n"
312 " d += 360\n"
313 " while (d >= 360)\n"
314 " d -= 360\n"
315 " var s = Math.sin((d * Math.PI) / 180)\n"
316 " var c = Math.cos((d * Math.PI) / 180)\n"
317 " return [ c, s, -s, c, 0, 0 ]\n"
318 " },\n"
319 " invert: function (m) {\n"
320 " var det = m[0] * m[3] - m[1] * m[2]\n"
321 " if (det > -1e-23 && det < 1e-23)\n"
322 " return m\n"
323 " var rdet = 1 / det\n"
324 " var inva = m[3] * rdet\n"
325 " var invb = -m[1] * rdet\n"
326 " var invc = -m[2] * rdet\n"
327 " var invd = m[0] * rdet\n"
328 " var inve = -m[4] * inva - m[5] * invc\n"
329 " var invf = -m[4] * invb - m[5] * invd\n"
330 " return [ inva, invb, invc, invd, inve, invf ]\n"
331 " },\n"
332 " concat: function (one, two) {\n"
333 " return [\n"
334 " one[0] * two[0] + one[1] * two[2],\n"
335 " one[0] * two[1] + one[1] * two[3],\n"
336 " one[2] * two[0] + one[3] * two[2],\n"
337 " one[2] * two[1] + one[3] * two[3],\n"
338 " one[4] * two[0] + one[5] * two[2] + two[4],\n"
339 " one[4] * two[1] + one[5] * two[3] + two[5],\n"
340 " ]\n"
341 " },\n"
342 "}\n"
343 "\n"
344 "mupdf.Point = {\n"
345 " transform: function (p, matrix) {\n"
346 " return [\n"
347 " p[0] * matrix[0] + p[1] * matrix[2] + matrix[4],\n"
348 " p[0] * matrix[1] + p[1] * matrix[3] + matrix[5]\n"
349 " ]\n"
350 " }\n"
351 "}\n"
352 "\n"
353 "mupdf.Rect = {\n"
354 " empty: [ 0x80000000, 0x80000000, 0x7fffff80, 0x7fffff80 ],\n"
355 " invalid: [ 0, 0, -1, -1 ],\n"
356 " infinite: [ 0x7fffff80, 0x7fffff80, 0x80000000, 0x80000000 ],\n"
357 " isEmpty: function (rect) {\n"
358 " return rect[0] >= rect[2] || rect[1] >= rect[3]\n"
359 " },\n"
360 " isValid: function (rect) {\n"
361 " return rect[0] <= rect[2] && rect[1] <= rect[3]\n"
362 " },\n"
363 " isInfinite: function (rect) {\n"
364 " return (\n"
365 " rect[0] === 0x7fffff80 &&\n"
366 " rect[1] === 0x7fffff80 &&\n"
367 " rect[2] === 0x80000000 &&\n"
368 " rect[3] === 0x80000000\n"
369 " )\n"
370 " },\n"
371 " transform: function (rect, matrix) {\n"
372 " var t\n"
373 " if (Rect.isInfinite(rect))\n"
374 " return rect\n"
375 " if (!Rect.isValid(rect))\n"
376 " return rect\n"
377 " var ax0 = rect[0] * matrix[0]\n"
378 " var ax1 = rect[2] * matrix[0]\n"
379 " if (ax0 > ax1)\n"
380 " t = ax0, ax0 = ax1, ax1 = t\n"
381 " var cy0 = rect[1] * matrix[2]\n"
382 " var cy1 = rect[3] * matrix[2]\n"
383 " if (cy0 > cy1)\n"
384 " t = cy0, cy0 = cy1, cy1 = t\n"
385 " ax0 += cy0 + matrix[4]\n"
386 " ax1 += cy1 + matrix[4]\n"
387 " var bx0 = rect[0] * matrix[1]\n"
388 " var bx1 = rect[2] * matrix[1]\n"
389 " if (bx0 > bx1)\n"
390 " t = bx0, bx0 = bx1, bx1 = t\n"
391 " var dy0 = rect[1] * matrix[3]\n"
392 " var dy1 = rect[3] * matrix[3]\n"
393 " if (dy0 > dy1)\n"
394 " t = dy0, dy0 = dy1, dy1 = t\n"
395 " bx0 += dy0 + matrix[5]\n"
396 " bx1 += dy1 + matrix[5]\n"
397 " return [ ax0, bx0, ax1, bx1 ]\n"
398 " },\n"
399 " isPointInside: function (r, p) {\n"
400 " return p[0] >= r[0] && p[0] < r[1] && p[1] >= r[2] && p[1] < r[3]\n"
401 " },\n"
402 " rectFromQuad: function (q) {\n"
403 " if (!Quad.isValid(r))\n"
404 " return Rect.invalid\n"
405 " if (Quad.isInfinite(r))\n"
406 " return Rect.infinite\n"
407 " return [\n"
408 " Math.min(q[0], q[2], q[4], q[6]),\n"
409 " Math.min(q[1], q[3], q[5], q[7]),\n"
410 " Math.max(q[0], q[2], q[4], q[6]),\n"
411 " Math.max(q[1], q[3], q[5], q[7])\n"
412 " ]\n"
413 " },\n"
414 "}\n"
415 "\n"
416 "mupdf.Quad = {\n"
417 " empty: [ 0, 0, 0, 0, 0, 0, 0, 0 ],\n"
418 " invalid: [ NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN ],\n"
419 " infinite: [ -Infinity, Infinity, Infinity, Infinity, -Infinity, -Infinity, Infinity, -Infinity ],\n"
420 " quadFromRect: function (r) {\n"
421 " if (!Rect.isValid(r))\n"
422 " return Quad.invalid\n"
423 " if (Rect.isInfinite(r))\n"
424 " return Quad.infinite\n"
425 " return [\n"
426 " r[0], r[1],\n"
427 " r[2], r[1],\n"
428 " r[0], r[3],\n"
429 " r[2], r[3],\n"
430 " ]\n"
431 " },\n"
432 " isValid: function (q) {\n"
433 " return (\n"
434 " !isNaN(q[0]) &&\n"
435 " !isNaN(q[1]) &&\n"
436 " !isNaN(q[2]) &&\n"
437 " !isNaN(q[3]) &&\n"
438 " !isNaN(q[4]) &&\n"
439 " !isNaN(q[5]) &&\n"
440 " !isNaN(q[6]) &&\n"
441 " !isNaN(q[7])\n"
442 " )\n"
443 " },\n"
444 " isInfiniteQuadTest: function (a, b, c, d) {\n"
445 " return (\n"
446 " a[0] < 0 && a[1] < 0 &&\n"
447 " b[0] < 0 && b[1] > 0 &&\n"
448 " c[0] > 0 && c[1] > 0 &&\n"
449 " d[0] > 0 && d[1] < 0\n"
450 " )\n"
451 " },\n"
452 " isInfinite: function (q) {\n"
453 " if (\n"
454 " isFinite(q[0]) ||\n"
455 " isFinite(q[1]) ||\n"
456 " isFinite(q[2]) ||\n"
457 " isFinite(q[3]) ||\n"
458 " isFinite(q[4]) ||\n"
459 " isFinite(q[5]) ||\n"
460 " isFinite(q[6]) ||\n"
461 " isFinite(q[7])\n"
462 " )\n"
463 " return false\n"
464 " return (\n"
465 " Quad.isInfiniteQuadTest(q.slice(4, 6), q.slice(0, 2), q.slice(2, 4), q.slice(6, 8)) || \n"
466 " Quad.isInfiniteQuadTest(q.slice(0, 2), q.slice(2, 4), q.slice(6, 8), q.slice(4, 6)) || \n"
467 " Quad.isInfiniteQuadTest(q.slice(2, 4), q.slice(6, 8), q.slice(4, 6), q.slice(0, 2)) || \n"
468 " Quad.isInfiniteQuadTest(q.slice(6, 8), q.slice(4, 6), q.slice(0, 2), q.slice(2, 4)) || \n"
469 " Quad.isInfiniteQuadTest(q.slice(4, 6), q.slice(6, 8), q.slice(2, 4), q.slice(0, 2)) || \n"
470 " Quad.isInfiniteQuadTest(q.slice(6, 8), q.slice(2, 4), q.slice(0, 2), q.slice(4, 6)) || \n"
471 " Quad.isInfiniteQuadTest(q.slice(2, 4), q.slice(0, 2), q.slice(4, 6), q.slice(6, 8)) || \n"
472 " Quad.isInfiniteQuadTest(q.slice(0, 2), q.slice(4, 6), q.slice(6, 8), q.slice(2, 4))\n"
473 " )\n"
474 " },\n"
475 " isEmpty: function (q) {\n"
476 " if (Quad.isInfinite(q))\n"
477 " return false\n"
478 " if (!Quad.isValid(q))\n"
479 " return true\n"
480 " var area =\n"
481 " q[6] * q[3] +\n"
482 " q[2] * q[1] +\n"
483 " q[0] * q[5] -\n"
484 " q[6] * q[5] -\n"
485 " q[2] * q[7] -\n"
486 " q[0] * q[3] -\n"
487 " q[4] * q[1]\n"
488 " return area == 0\n"
489 " },\n"
490 " transform: function (q, m) {\n"
491 " if (!Quad.isValid(q))\n"
492 " return q\n"
493 " if (Quad.isInfinite(q))\n"
494 " return q\n"
495 " var ul = Point.transform(q.slice(0, 2), m)\n"
496 " var ur = Point.transform(q.slice(2, 4), m)\n"
497 " var ll = Point.transform(q.slice(4, 6), m)\n"
498 " var lr = Point.transform(q.slice(6, 8), m)\n"
499 " return [\n"
500 " ul[0], ul[1],\n"
501 " ur[0], ur[1],\n"
502 " ll[0], ll[1],\n"
503 " lr[0], lr[1]\n"
504 " ]\n"
505 " },\n"
506 " crossProduct: function (a, b, p) {\n"
507 " return (b[0] - a[0]) * (p[1] - a[1]) - (b[1] - a[1]) * (p[0] - a[0])\n"
508 " },\n"
509 " isPointInsideTriangle: function (p, a, b) {\n"
510 " var crossa = Quad.crossProduct(a, b, p)\n"
511 " var crossb = Quad.crossProduct(b, c, p)\n"
512 " var crossc = Quad.crossProduct(c, a, p)\n"
513 " if (crossa == 0 && crossb == 0 && crossc == 0)\n"
514 " return a[0] == p[0] && a[1] == p[1]\n"
515 " if (crossa >= 0 && crossb >= 0 && crossc >= 0)\n"
516 " return true\n"
517 " if (crossa <= 0 && crossb <= 0 && crossc <= 0)\n"
518 " return true\n"
519 " return false\n"
520 " },\n"
521 " isPointInside: function (p, q) {\n"
522 " if (!Quad.isValid(q))\n"
523 " return false\n"
524 " if (Quad.isInfinite(q))\n"
525 " return true\n"
526 " return Quad.isPointInsideTriangle(p, q.slice(0, 2), q.slice(2, 4), q.slice(6, 8)) ||\n"
527 " Quad.isPointInsideTriangle(p, q.slice(0, 2), q.slice(6, 8), q.slice(4, 6))\n"
528 " },\n"
529 "}\n"
530 "\n"
531 "mupdf.PDFDocument.prototype.getEmbeddedFiles = function () {\n"
532 " function _getEmbeddedFilesRec(result, N) {\n"
533 " var i, n\n"
534 " if (N.isDictionary()) {\n"
535 " var NN = N.get('Names')\n"
536 " if (NN)\n"
537 " for (i = 0, n = NN.length; i < n; i += 2)\n"
538 " result[NN.get(i+0).asString()] = NN.get(i+1)\n"
539 " var NK = N.get('Kids')\n"
540 " if (NK)\n"
541 " for (i = 0, n = NK.length; i < n; i += 1)\n"
542 " _getEmbeddedFilesRec(result, NK.get(i))\n"
543 " }\n"
544 " return result\n"
545 " }\n"
546 " return _getEmbeddedFilesRec({}, this.getTrailer().get('Root', 'Names', 'EmbeddedFiles'))\n"
547 "}\n"
548 "mupdf.PDFDocument.prototype.insertEmbeddedFile = function (filename, filespec) {\n"
549 " var efs = this.getEmbeddedFiles()\n"
550 " efs[filename] = filespec\n"
551 " this._rewriteEmbeddedFiles(efs)\n"
552 "}\n"
553 "mupdf.PDFDocument.prototype.deleteEmbeddedFile = function (filename) {\n"
554 " var efs = this.getEmbeddedFiles()\n"
555 " delete efs[filename]\n"
556 " this._rewriteEmbeddedFiles(efs)\n"
557 "}\n"
558 "mupdf.PDFDocument.prototype._rewriteEmbeddedFiles = function (efs) {\n"
559 " var efs_keys = Object.keys(efs)\n"
560 " var root = this.getTrailer().get('Root')\n"
561 " var root_names = root.get('Names')\n"
562 " if (!root_names.isDictionary())\n"
563 " root_names = root.put('Names', this.newDictionary(1))\n"
564 " var root_names_efs = root_names.put('EmbeddedFiles', this.newDictionary(1))\n"
565 " var root_names_efs_names = root_names_efs.put('Names', this.newArray(efs_keys.length * 2))\n"
566 " for (var i = 0; i < efs_keys.length; ++i) {\n"
567 " root_names_efs_names.push(this.newString(efs_keys[i]))\n"
568 " root_names_efs_names.push(efs[efs_keys[i]])\n"
569 " }\n"
570 "}\n"
571 "mupdf.PDFDocument.prototype.loadNameTree = function loadNameTree(treeName) {\n"
572 " var root = this.getTrailer().get('Root').get('Names').get(treeName)\n"
573 " var dict = {}\n"
574 " if (root && root.isDictionary())\n"
575 " this._loadNameTreeRec(dict, root)\n"
576 " return dict\n"
577 "}\n"
578 "mupdf.PDFDocument.prototype._loadNameTreeRec = function (dict, node) {\n"
579 " var kids = node.get('Kids')\n"
580 " if (kids && kids.isArray())\n"
581 " for (var i = 0; i < kids.length; i += 1)\n"
582 " loadNameTreeRec(dict, kids[i])\n"
583 " var names = node.get('Names')\n"
584 " if (names && names.isArray())\n"
585 " for (var i = 0; i < names.length; i += 2)\n"
586 " dict[names[i].asString()] = names[i+1]\n"
587 "}\n"
588 "mupdf.Device = function Device(callbacks) { return callbacks }\n"
589 ;
590
591 struct event_cb_data
592 {
593 js_State *J;
594 const char *listener;
595 };
596
597 /* destructors */
598
599 static void ffi_gc_fz_archive(js_State *J, void *arch)
600 {
601 fz_context *ctx = js_getcontext(J);
602 fz_try(ctx)
603 fz_drop_archive(ctx, arch);
604 fz_catch(ctx)
605 rethrow(J);
606 }
607
608 static void ffi_gc_fz_buffer(js_State *J, void *buf)
609 {
610 fz_context *ctx = js_getcontext(J);
611 fz_try(ctx)
612 fz_drop_buffer(ctx, buf);
613 fz_catch(ctx)
614 rethrow(J);
615 }
616
617 static void ffi_gc_fz_document(js_State *J, void *doc)
618 {
619 fz_context *ctx = js_getcontext(J);
620 fz_drop_document(ctx, doc);
621 }
622
623 static void ffi_gc_fz_page(js_State *J, void *page)
624 {
625 fz_context *ctx = js_getcontext(J);
626 fz_drop_page(ctx, page);
627 }
628
629 static void ffi_gc_fz_colorspace(js_State *J, void *colorspace)
630 {
631 fz_context *ctx = js_getcontext(J);
632 fz_drop_colorspace(ctx, colorspace);
633 }
634
635 static void ffi_gc_fz_default_colorspaces(js_State *J, void *default_cs)
636 {
637 fz_context *ctx = js_getcontext(J);
638 fz_drop_default_colorspaces(ctx, default_cs);
639 }
640
641 static void ffi_gc_fz_pixmap(js_State *J, void *pixmap)
642 {
643 fz_context *ctx = js_getcontext(J);
644 fz_drop_pixmap(ctx, pixmap);
645 }
646
647 static void ffi_gc_fz_path(js_State *J, void *path)
648 {
649 fz_context *ctx = js_getcontext(J);
650 fz_drop_path(ctx, path);
651 }
652
653 static void ffi_gc_fz_text(js_State *J, void *text)
654 {
655 fz_context *ctx = js_getcontext(J);
656 fz_drop_text(ctx, text);
657 }
658
659 static void ffi_gc_fz_font(js_State *J, void *font)
660 {
661 fz_context *ctx = js_getcontext(J);
662 fz_drop_font(ctx, font);
663 }
664
665 static void ffi_gc_fz_shade(js_State *J, void *shade)
666 {
667 fz_context *ctx = js_getcontext(J);
668 fz_drop_shade(ctx, shade);
669 }
670
671 static void ffi_gc_fz_image(js_State *J, void *image)
672 {
673 fz_context *ctx = js_getcontext(J);
674 fz_drop_image(ctx, image);
675 }
676
677 static void ffi_gc_fz_display_list(js_State *J, void *list)
678 {
679 fz_context *ctx = js_getcontext(J);
680 fz_drop_display_list(ctx, list);
681 }
682
683 static void ffi_gc_fz_stext_page(js_State *J, void *text)
684 {
685 fz_context *ctx = js_getcontext(J);
686 fz_drop_stext_page(ctx, text);
687 }
688
689 static void ffi_gc_fz_device(js_State *J, void *device)
690 {
691 fz_context *ctx = js_getcontext(J);
692 fz_drop_device(ctx, device);
693 }
694
695 static void ffi_gc_fz_document_writer(js_State *J, void *wri)
696 {
697 fz_context *ctx = js_getcontext(J);
698 fz_drop_document_writer(ctx, wri);
699 }
700
701 static void ffi_gc_fz_outline_iterator(js_State *J, void *iter)
702 {
703 fz_context *ctx = js_getcontext(J);
704 fz_drop_outline_iterator(ctx, iter);
705 }
706
707 static void ffi_gc_fz_story(js_State *J, void *story)
708 {
709 fz_context *ctx = js_getcontext(J);
710 fz_drop_story(ctx, story);
711 }
712
713 static void ffi_gc_fz_xml(js_State *J, void *xml)
714 {
715 fz_context *ctx = js_getcontext(J);
716 fz_drop_xml(ctx, xml);
717 }
718
719 static void ffi_gc_fz_stroke_state(js_State *J, void *stroke)
720 {
721 fz_context *ctx = js_getcontext(J);
722 fz_drop_stroke_state(ctx, stroke);
723 }
724
725 static void ffi_pushoutlineiterator(js_State *J, fz_outline_iterator *iter)
726 {
727 js_getregistry(J, "fz_outline_iterator");
728 js_newuserdata(J, "fz_outline_iterator", iter, ffi_gc_fz_outline_iterator);
729 }
730
731 static void ffi_pushdom(js_State *J, fz_xml *dom)
732 {
733 fz_context *ctx = js_getcontext(J);
734 if (dom)
735 {
736 // all DOM are borrowed references.
737 // use keep here to take a reference to the owning XML document
738 fz_keep_xml(ctx, dom);
739
740 js_getregistry(J, "fz_xml");
741 js_newuserdata(J, "fz_xml", dom, ffi_gc_fz_xml);
742 }
743 else
744 js_pushnull(J);
745 }
746
747 static void ffi_pushpixmap(js_State *J, fz_pixmap *pixmap)
748 {
749 js_getregistry(J, "fz_pixmap");
750 js_newuserdata(J, "fz_pixmap", pixmap, ffi_gc_fz_pixmap);
751 }
752
753 static fz_pixmap *ffi_topixmap(js_State *J, int idx)
754 {
755 return (fz_pixmap *) js_touserdata(J, idx, "fz_pixmap");
756 }
757
758 static fz_image *ffi_toimage(js_State *J, int idx)
759 {
760 return (fz_image *) js_touserdata(J, idx, "fz_image");
761 }
762
763 #if FZ_ENABLE_PDF
764
765 static void ffi_pushobj(js_State *J, pdf_obj *obj);
766
767 static void ffi_gc_pdf_annot(js_State *J, void *annot)
768 {
769 fz_context *ctx = js_getcontext(J);
770 pdf_drop_annot(ctx, annot);
771 }
772
773 static void ffi_gc_pdf_document(js_State *J, void *doc)
774 {
775 fz_context *ctx = js_getcontext(J);
776 pdf_drop_document(ctx, doc);
777 }
778
779 static void ffi_gc_pdf_obj(js_State *J, void *obj)
780 {
781 fz_context *ctx = js_getcontext(J);
782 pdf_drop_obj(ctx, obj);
783 }
784
785 static void ffi_gc_pdf_graft_map(js_State *J, void *map)
786 {
787 fz_context *ctx = js_getcontext(J);
788 pdf_drop_graft_map(ctx, map);
789 }
790
791 static void ffi_gc_pdf_pkcs7_signer(js_State *J, void *signer_)
792 {
793 fz_context *ctx = js_getcontext(J);
794 pdf_pkcs7_signer *signer = (pdf_pkcs7_signer *)signer_;
795 if (signer)
796 signer->drop(ctx, signer);
797 }
798
799 static fz_document *ffi_todocument(js_State *J, int idx)
800 {
801 if (js_isuserdata(J, idx, "pdf_document"))
802 return js_touserdata(J, idx, "pdf_document");
803 return js_touserdata(J, idx, "fz_document");
804 }
805
806 static void ffi_pushdocument(js_State *J, fz_document *document)
807 {
808 fz_context *ctx = js_getcontext(J);
809 pdf_document *pdocument = pdf_document_from_fz_document(ctx, document);
810 if (pdocument) {
811 /* This relies on the fact that pdocument == document! */
812 js_getregistry(J, "pdf_document");
813 js_newuserdata(J, "pdf_document", document, ffi_gc_pdf_document);
814 } else {
815 js_getregistry(J, "fz_document");
816 js_newuserdata(J, "fz_document", document, ffi_gc_fz_document);
817 }
818 }
819
820 static void ffi_pushpdfdocument(js_State *J, pdf_document *document)
821 {
822 js_getregistry(J, "pdf_document");
823 js_newuserdata(J, "pdf_document", document, ffi_gc_pdf_document);
824 }
825
826 static void ffi_pushsigner(js_State *J, pdf_pkcs7_signer *signer)
827 {
828 js_getregistry(J, "pdf_pkcs7_signer");
829 js_newuserdata(J, "pdf_pkcs7_signer", signer, ffi_gc_pdf_pkcs7_signer);
830 }
831
832 static fz_page *ffi_topage(js_State *J, int idx)
833 {
834 if (js_isuserdata(J, idx, "pdf_page"))
835 return js_touserdata(J, idx, "pdf_page");
836 return js_touserdata(J, idx, "fz_page");
837 }
838
839 static pdf_annot *ffi_toannot(js_State *J, int idx)
840 {
841 if (js_isuserdata(J, idx, "pdf_widget"))
842 return js_touserdata(J, idx, "pdf_widget");
843 return js_touserdata(J, idx, "pdf_annot");
844 }
845
846 static void ffi_pushpage(js_State *J, fz_page *page)
847 {
848 fz_context *ctx = js_getcontext(J);
849 pdf_page *ppage = pdf_page_from_fz_page(ctx, page);
850 if (ppage) {
851 js_getregistry(J, "pdf_page");
852 js_newuserdata(J, "pdf_page", page, ffi_gc_fz_page);
853 } else {
854 js_getregistry(J, "fz_page");
855 js_newuserdata(J, "fz_page", page, ffi_gc_fz_page);
856 }
857 }
858
859 #else
860
861 static fz_document *ffi_todocument(js_State *J, int idx)
862 {
863 return js_touserdata(J, idx, "fz_document");
864 }
865
866 static void ffi_pushdocument(js_State *J, fz_document *document)
867 {
868 js_getregistry(J, "fz_document");
869 js_newuserdata(J, "fz_document", document, ffi_gc_fz_document);
870 }
871
872 static fz_page *ffi_topage(js_State *J, int idx)
873 {
874 return js_touserdata(J, idx, "fz_page");
875 }
876
877 static void ffi_pushpage(js_State *J, fz_page *page)
878 {
879 js_getregistry(J, "fz_page");
880 js_newuserdata(J, "fz_page", page, ffi_gc_fz_page);
881 }
882
883 #endif /* FZ_ENABLE_PDF */
884
885 /* type conversions */
886
887 struct color {
888 fz_colorspace *colorspace;
889 float color[FZ_MAX_COLORS];
890 float alpha;
891 };
892
893 static fz_matrix ffi_tomatrix(js_State *J, int idx)
894 {
895 if (js_iscoercible(J, idx))
896 {
897 fz_matrix matrix;
898 js_getindex(J, idx, 0); matrix.a = js_tonumber(J, -1); js_pop(J, 1);
899 js_getindex(J, idx, 1); matrix.b = js_tonumber(J, -1); js_pop(J, 1);
900 js_getindex(J, idx, 2); matrix.c = js_tonumber(J, -1); js_pop(J, 1);
901 js_getindex(J, idx, 3); matrix.d = js_tonumber(J, -1); js_pop(J, 1);
902 js_getindex(J, idx, 4); matrix.e = js_tonumber(J, -1); js_pop(J, 1);
903 js_getindex(J, idx, 5); matrix.f = js_tonumber(J, -1); js_pop(J, 1);
904 return matrix;
905 }
906 return fz_identity;
907 }
908
909 static void ffi_pushmatrix(js_State *J, fz_matrix matrix)
910 {
911 js_newarray(J);
912 js_pushnumber(J, matrix.a); js_setindex(J, -2, 0);
913 js_pushnumber(J, matrix.b); js_setindex(J, -2, 1);
914 js_pushnumber(J, matrix.c); js_setindex(J, -2, 2);
915 js_pushnumber(J, matrix.d); js_setindex(J, -2, 3);
916 js_pushnumber(J, matrix.e); js_setindex(J, -2, 4);
917 js_pushnumber(J, matrix.f); js_setindex(J, -2, 5);
918 }
919
920 static fz_point ffi_topoint(js_State *J, int idx)
921 {
922 fz_point point;
923 js_getindex(J, idx, 0); point.x = js_tonumber(J, -1); js_pop(J, 1);
924 js_getindex(J, idx, 1); point.y = js_tonumber(J, -1); js_pop(J, 1);
925 return point;
926 }
927
928 static void ffi_pushpoint(js_State *J, fz_point point)
929 {
930 js_newarray(J);
931 js_pushnumber(J, point.x); js_setindex(J, -2, 0);
932 js_pushnumber(J, point.y); js_setindex(J, -2, 1);
933 }
934
935 static fz_rect ffi_torect(js_State *J, int idx)
936 {
937 fz_rect rect;
938 js_getindex(J, idx, 0); rect.x0 = js_tonumber(J, -1); js_pop(J, 1);
939 js_getindex(J, idx, 1); rect.y0 = js_tonumber(J, -1); js_pop(J, 1);
940 js_getindex(J, idx, 2); rect.x1 = js_tonumber(J, -1); js_pop(J, 1);
941 js_getindex(J, idx, 3); rect.y1 = js_tonumber(J, -1); js_pop(J, 1);
942 return rect;
943 }
944
945 static void ffi_pushrect(js_State *J, fz_rect rect)
946 {
947 js_newarray(J);
948 js_pushnumber(J, rect.x0); js_setindex(J, -2, 0);
949 js_pushnumber(J, rect.y0); js_setindex(J, -2, 1);
950 js_pushnumber(J, rect.x1); js_setindex(J, -2, 2);
951 js_pushnumber(J, rect.y1); js_setindex(J, -2, 3);
952 }
953
954 #if FZ_ENABLE_PDF
955
956 static fz_quad ffi_toquad(js_State *J, int idx)
957 {
958 fz_quad quad;
959 js_getindex(J, idx, 0); quad.ul.x = js_tonumber(J, -1); js_pop(J, 1);
960 js_getindex(J, idx, 1); quad.ul.y = js_tonumber(J, -1); js_pop(J, 1);
961 js_getindex(J, idx, 2); quad.ur.x = js_tonumber(J, -1); js_pop(J, 1);
962 js_getindex(J, idx, 3); quad.ur.y = js_tonumber(J, -1); js_pop(J, 1);
963 js_getindex(J, idx, 4); quad.ll.x = js_tonumber(J, -1); js_pop(J, 1);
964 js_getindex(J, idx, 5); quad.ll.y = js_tonumber(J, -1); js_pop(J, 1);
965 js_getindex(J, idx, 6); quad.lr.x = js_tonumber(J, -1); js_pop(J, 1);
966 js_getindex(J, idx, 7); quad.lr.y = js_tonumber(J, -1); js_pop(J, 1);
967 return quad;
968 }
969
970 #endif /* FZ_ENABLE_PDF */
971
972 static void ffi_pushquad(js_State *J, fz_quad quad)
973 {
974 js_newarray(J);
975 js_pushnumber(J, quad.ul.x); js_setindex(J, -2, 0);
976 js_pushnumber(J, quad.ul.y); js_setindex(J, -2, 1);
977 js_pushnumber(J, quad.ur.x); js_setindex(J, -2, 2);
978 js_pushnumber(J, quad.ur.y); js_setindex(J, -2, 3);
979 js_pushnumber(J, quad.ll.x); js_setindex(J, -2, 4);
980 js_pushnumber(J, quad.ll.y); js_setindex(J, -2, 5);
981 js_pushnumber(J, quad.lr.x); js_setindex(J, -2, 6);
982 js_pushnumber(J, quad.lr.y); js_setindex(J, -2, 7);
983 }
984
985 static fz_irect ffi_toirect(js_State *J, int idx)
986 {
987 fz_irect irect;
988 js_getindex(J, idx, 0); irect.x0 = js_tointeger(J, -1); js_pop(J, 1);
989 js_getindex(J, idx, 1); irect.y0 = js_tointeger(J, -1); js_pop(J, 1);
990 js_getindex(J, idx, 2); irect.x1 = js_tointeger(J, -1); js_pop(J, 1);
991 js_getindex(J, idx, 3); irect.y1 = js_tointeger(J, -1); js_pop(J, 1);
992 return irect;
993 }
994
995 static void ffi_pusharray(js_State *J, const float *v, int n)
996 {
997 int i;
998 js_newarray(J);
999 for (i = 0; i < n; ++i) {
1000 js_pushnumber(J, v[i]);
1001 js_setindex(J, -2, i);
1002 }
1003 }
1004
1005 static void ffi_pushcolorspace(js_State *J, fz_colorspace *colorspace)
1006 {
1007 fz_context *ctx = js_getcontext(J);
1008 if (colorspace == NULL)
1009 js_pushnull(J);
1010 else if (colorspace == fz_device_rgb(ctx))
1011 js_getregistry(J, "DeviceRGB");
1012 else if (colorspace == fz_device_bgr(ctx))
1013 js_getregistry(J, "DeviceBGR");
1014 else if (colorspace == fz_device_gray(ctx))
1015 js_getregistry(J, "DeviceGray");
1016 else if (colorspace == fz_device_cmyk(ctx))
1017 js_getregistry(J, "DeviceCMYK");
1018 else if (colorspace == fz_device_lab(ctx))
1019 js_getregistry(J, "DeviceLab");
1020 else {
1021 js_getregistry(J, "fz_colorspace");
1022 js_newuserdata(J, "fz_colorspace", fz_keep_colorspace(ctx, colorspace), ffi_gc_fz_colorspace);
1023 }
1024 }
1025
1026 static void ffi_pushcolor(js_State *J, fz_colorspace *colorspace, const float *color, float alpha)
1027 {
1028 fz_context *ctx = js_getcontext(J);
1029 if (colorspace) {
1030 ffi_pushcolorspace(J, colorspace);
1031 ffi_pusharray(J, color, fz_colorspace_n(ctx, colorspace));
1032 } else {
1033 js_pushnull(J);
1034 js_pushnull(J);
1035 }
1036 js_pushnumber(J, alpha);
1037 }
1038
1039 void ffi_pushrgb(js_State *J, uint32_t argb)
1040 {
1041 float rgb[3];
1042 rgb[0] = ((argb >> 16) & 0xff) / 255.0f;
1043 rgb[1] = ((argb >> 8) & 0xff) / 255.0f;
1044 rgb[2] = ((argb) & 0xff) / 255.0f;
1045 ffi_pusharray(J, rgb, 3);
1046 }
1047
1048 static struct color ffi_tocolor(js_State *J, int idx)
1049 {
1050 struct color c;
1051 int n, i;
1052 fz_context *ctx = js_getcontext(J);
1053 c.colorspace = js_touserdata(J, idx, "fz_colorspace");
1054 if (c.colorspace) {
1055 n = fz_colorspace_n(ctx, c.colorspace);
1056 for (i=0; i < n; ++i) {
1057 js_getindex(J, idx + 1, i);
1058 c.color[i] = js_tonumber(J, -1);
1059 js_pop(J, 1);
1060 }
1061 }
1062 c.alpha = js_tonumber(J, idx + 2);
1063 return c;
1064 }
1065
1066 static const char *string_from_ri(uint8_t ri)
1067 {
1068 switch (ri) {
1069 default:
1070 case 0: return "Perceptual";
1071 case 1: return "RelativeColorimetric";
1072 case 2: return "Saturation";
1073 case 3: return "AbsoluteColorimetric";
1074 }
1075 }
1076
1077 static void ffi_pushcolorparams(js_State *J, fz_color_params color_params)
1078 {
1079 js_newobject(J);
1080 js_pushstring(J, string_from_ri(color_params.ri));
1081 js_setproperty(J, -2, "renderingIntent");
1082 js_pushboolean(J, color_params.bp);
1083 js_setproperty(J, -2, "blackPointCompensation");
1084 js_pushboolean(J, color_params.op);
1085 js_setproperty(J, -2, "overPrinting");
1086 js_pushboolean(J, color_params.opm);
1087 js_setproperty(J, -2, "overPrintMode");
1088 }
1089
1090 static fz_color_params ffi_tocolorparams(js_State *J, int idx)
1091 {
1092 fz_color_params color_params = { 0 };
1093
1094 if (!js_iscoercible(J, idx))
1095 return fz_default_color_params;
1096
1097 if (js_hasproperty(J, idx, "renderingIntent"))
1098 {
1099 js_getproperty(J, idx, "renderingIntent");
1100 color_params.ri = js_tointeger(J, -1);
1101 js_pop(J, 1);
1102 }
1103 if (js_hasproperty(J, idx, "blackPointCompensation"))
1104 {
1105 js_getproperty(J, idx, "blackPointCompensation");
1106 color_params.ri = js_toboolean(J, -1);
1107 js_pop(J, 1);
1108 }
1109 if (js_hasproperty(J, idx, "overPrinting"))
1110 {
1111 js_getproperty(J, idx, "overPrinting");
1112 color_params.ri = js_toboolean(J, -1);
1113 js_pop(J, 1);
1114 }
1115 if (js_hasproperty(J, idx, "overPrintMode"))
1116 {
1117 js_getproperty(J, idx, "overPrintMode");
1118 color_params.ri = js_toboolean(J, -1);
1119 js_pop(J, 1);
1120 }
1121
1122 return color_params;
1123 }
1124
1125 static void ffi_pushdefaultcolorspaces(js_State *J, fz_default_colorspaces *default_cs)
1126 {
1127 js_getregistry(J, "fz_default_colorspaces");
1128 js_newuserdata(J, "fz_default_colorspaces", default_cs, ffi_gc_fz_default_colorspaces);
1129 }
1130
1131 static fz_default_colorspaces *ffi_todefaultcolorspaces(js_State *J, int idx)
1132 {
1133 return (fz_default_colorspaces *) js_touserdata(J, idx, "fz_default_colorspaces");
1134 }
1135
1136 static struct {
1137 int flag;
1138 const char *name;
1139 } render_flags[] = {
1140 { FZ_DEVFLAG_MASK, "mask" },
1141 { FZ_DEVFLAG_COLOR, "color" },
1142 { FZ_DEVFLAG_UNCACHEABLE, "uncacheable" },
1143 { FZ_DEVFLAG_FILLCOLOR_UNDEFINED, "fillcolor-undefined" },
1144 { FZ_DEVFLAG_STROKECOLOR_UNDEFINED, "strokecolor-undefined" },
1145 { FZ_DEVFLAG_STARTCAP_UNDEFINED, "startcap-undefined" },
1146 { FZ_DEVFLAG_DASHCAP_UNDEFINED, "dashcap-undefined" },
1147 { FZ_DEVFLAG_ENDCAP_UNDEFINED, "endcap-undefined" },
1148 { FZ_DEVFLAG_LINEJOIN_UNDEFINED, "linejoin-undefined" },
1149 { FZ_DEVFLAG_MITERLIMIT_UNDEFINED, "miterlimit-undefined" },
1150 { FZ_DEVFLAG_LINEWIDTH_UNDEFINED, "linewidth-undefined" },
1151 { FZ_DEVFLAG_BBOX_DEFINED, "bbox-defined" },
1152 { FZ_DEVFLAG_GRIDFIT_AS_TILED, "gridfit-as-tiled" },
1153 };
1154
1155 static void ffi_pushrenderflags(js_State *J, int flags)
1156 {
1157 js_newarray(J);
1158 int idx = 0;
1159 size_t i;
1160 for (i = 0; i < nelem(render_flags); ++i)
1161 {
1162 if (flags & render_flags[i].flag)
1163 {
1164 js_pushliteral(J, render_flags[i].name);
1165 js_setindex(J, -2, idx++);
1166 }
1167 }
1168 }
1169
1170 static int ffi_torenderflags(js_State *J, int idx)
1171 {
1172 int flags = 0;
1173 const char *name;
1174 int i, n = fz_maxi(0, js_getlength(J, idx));
1175 size_t k;
1176 for (i = 0; i < n; ++i) {
1177 js_getindex(J, idx, i);
1178 name = js_tostring(J, -1);
1179 for (k = 0; k < nelem(render_flags); ++k)
1180 if (!strcmp(name, render_flags[k].name))
1181 flags |= render_flags[k].flag;
1182 js_pop(J, 1);
1183 }
1184 return flags;
1185 }
1186
1187 static const char *string_from_metatext(fz_metatext meta_text)
1188 {
1189 switch (meta_text) {
1190 default:
1191 case FZ_METATEXT_ACTUALTEXT: return "ActualText";
1192 case FZ_METATEXT_ALT: return "Alt";
1193 case FZ_METATEXT_ABBREVIATION: return "Abbreviation";
1194 case FZ_METATEXT_TITLE: return "Title";
1195 }
1196 }
1197
1198 static fz_metatext metatext_from_string(const char *str)
1199 {
1200 if (!strcmp(str, "ActualText")) return FZ_METATEXT_ACTUALTEXT;
1201 if (!strcmp(str, "Alt")) return FZ_METATEXT_ALT;
1202 if (!strcmp(str, "Abbreviation")) return FZ_METATEXT_ABBREVIATION;
1203 if (!strcmp(str, "Title")) return FZ_METATEXT_TITLE;
1204 return FZ_METATEXT_ACTUALTEXT;
1205 }
1206
1207 static fz_link_dest_type link_dest_type_from_string(const char *str);
1208
1209 static fz_link_dest ffi_tolinkdest(js_State *J, int idx)
1210 {
1211 fz_link_dest dest = fz_make_link_dest_none();
1212
1213 if (js_hasproperty(J, idx, "chapter")) {
1214 dest.loc.chapter = js_tointeger(J, -1);
1215 js_pop(J, 1);
1216 }
1217 if (js_hasproperty(J, idx, "page")) {
1218 dest.loc.page = js_tointeger(J, -1);
1219 js_pop(J, 1);
1220 }
1221 if (js_hasproperty(J, idx, "type")) {
1222 dest.type = link_dest_type_from_string(js_tostring(J, -1));
1223 js_pop(J, 1);
1224 }
1225 if (js_hasproperty(J, idx, "x")) {
1226 dest.x = js_tonumber(J, -1);
1227 js_pop(J, 1);
1228 }
1229 if (js_hasproperty(J, idx, "y")) {
1230 dest.y = js_tonumber(J, -1);
1231 js_pop(J, 1);
1232 }
1233 if (js_hasproperty(J, idx, "width")) {
1234 dest.w = js_tonumber(J, -1);
1235 js_pop(J, 1);
1236 }
1237 if (js_hasproperty(J, idx, "height")) {
1238 dest.h = js_tonumber(J, -1);
1239 js_pop(J, 1);
1240 }
1241 if (js_hasproperty(J, idx, "zoom")) {
1242 dest.zoom = js_tonumber(J, -1);
1243 js_pop(J, 1);
1244 }
1245
1246 return dest;
1247 }
1248
1249 static fz_outline_item ffi_tooutlineitem(js_State *J, int idx)
1250 {
1251 fz_context *ctx = js_getcontext(J);
1252 fz_outline_item item = { NULL, NULL, 0 };
1253
1254 if (js_hasproperty(J, idx, "title")) {
1255 if (js_iscoercible(J, -1)) {
1256 const char *title = js_tostring(J, -1);
1257 fz_try(ctx)
1258 item.title = fz_strdup(ctx, title);
1259 fz_always(ctx)
1260 js_pop(J, 1);
1261 fz_catch(ctx)
1262 fz_rethrow(ctx);
1263 }
1264 else
1265 item.title = NULL;
1266
1267 }
1268 if (js_hasproperty(J, idx, "open")) {
1269 item.is_open = js_toboolean(J, -1);
1270 js_pop(J, 1);
1271 }
1272 if (js_hasproperty(J, idx, "uri")) {
1273 if (js_iscoercible(J, -1)) {
1274 const char *uri = js_tostring(J, -1);
1275 fz_try(ctx)
1276 item.uri = fz_strdup(ctx, uri);
1277 fz_always(ctx)
1278 js_pop(J, 1);
1279 fz_catch(ctx)
1280 fz_rethrow(ctx);
1281 }
1282 else
1283 item.uri = NULL;
1284 }
1285 if (js_hasproperty(J, idx, "r")) {
1286 item.r = js_tonumber(J, -1);
1287 }
1288 if (js_hasproperty(J, idx, "g")) {
1289 item.g = js_tonumber(J, -1);
1290 }
1291 if (js_hasproperty(J, idx, "b")) {
1292 item.b = js_tonumber(J, -1);
1293 }
1294 if (js_hasproperty(J, idx, "flags")) {
1295 item.flags = js_tointeger(J, -1);
1296 }
1297
1298 return item;
1299 }
1300
1301 #if FZ_ENABLE_PDF
1302
1303 static const char *string_from_border_style(enum pdf_border_style style)
1304 {
1305 switch (style) {
1306 default:
1307 case PDF_BORDER_STYLE_SOLID: return "Solid";
1308 case PDF_BORDER_STYLE_DASHED: return "Dashed";
1309 case PDF_BORDER_STYLE_BEVELED: return "Beveled";
1310 case PDF_BORDER_STYLE_INSET: return "Inset";
1311 case PDF_BORDER_STYLE_UNDERLINE: return "Underline";
1312 }
1313 }
1314
1315 static const char *string_from_border_effect(enum pdf_border_effect effect)
1316 {
1317 switch (effect) {
1318 default:
1319 case PDF_BORDER_EFFECT_NONE: return "None";
1320 case PDF_BORDER_EFFECT_CLOUDY: return "Cloudy";
1321 }
1322 }
1323
1324 static const char *string_from_line_ending(enum pdf_line_ending style)
1325 {
1326 switch (style) {
1327 default:
1328 case PDF_ANNOT_LE_NONE: return "None";
1329 case PDF_ANNOT_LE_SQUARE: return "Square";
1330 case PDF_ANNOT_LE_CIRCLE: return "Circle";
1331 case PDF_ANNOT_LE_DIAMOND: return "Diamond";
1332 case PDF_ANNOT_LE_OPEN_ARROW: return "OpenArrow";
1333 case PDF_ANNOT_LE_CLOSED_ARROW: return "ClosedArrow";
1334 case PDF_ANNOT_LE_BUTT: return "Butt";
1335 case PDF_ANNOT_LE_R_OPEN_ARROW: return "ROpenArrow";
1336 case PDF_ANNOT_LE_R_CLOSED_ARROW: return "RClosedArrow";
1337 case PDF_ANNOT_LE_SLASH: return "Slash";
1338 }
1339 }
1340
1341 #endif
1342
1343 static const char *string_from_destination_type(fz_link_dest_type type)
1344 {
1345 switch (type) {
1346 default:
1347 case FZ_LINK_DEST_FIT: return "Fit";
1348 case FZ_LINK_DEST_XYZ: return "XYZ";
1349 case FZ_LINK_DEST_FIT_H: return "FitH";
1350 case FZ_LINK_DEST_FIT_V: return "FitV";
1351 case FZ_LINK_DEST_FIT_R: return "FitR";
1352 case FZ_LINK_DEST_FIT_B: return "FitB";
1353 case FZ_LINK_DEST_FIT_BH: return "FitBH";
1354 case FZ_LINK_DEST_FIT_BV: return "FitBV";
1355 }
1356 }
1357
1358 #if FZ_ENABLE_PDF
1359
1360 static enum pdf_border_style border_style_from_string(const char *str)
1361 {
1362 if (!strcmp(str, "Solid")) return PDF_BORDER_STYLE_SOLID;
1363 if (!strcmp(str, "Dashed")) return PDF_BORDER_STYLE_DASHED;
1364 if (!strcmp(str, "Beveled")) return PDF_BORDER_STYLE_INSET;
1365 if (!strcmp(str, "Inset")) return PDF_BORDER_STYLE_INSET;
1366 if (!strcmp(str, "Underline")) return PDF_BORDER_STYLE_UNDERLINE;
1367 return PDF_BORDER_STYLE_SOLID;
1368 }
1369
1370 static enum pdf_border_effect border_effect_from_string(const char *str)
1371 {
1372 if (!strcmp(str, "None")) return PDF_BORDER_EFFECT_NONE;
1373 if (!strcmp(str, "Cloudy")) return PDF_BORDER_EFFECT_CLOUDY;
1374 return PDF_BORDER_EFFECT_NONE;
1375 }
1376
1377 static enum pdf_line_ending line_ending_from_string(const char *str)
1378 {
1379 if (!strcmp(str, "None")) return PDF_ANNOT_LE_NONE;
1380 if (!strcmp(str, "Square")) return PDF_ANNOT_LE_SQUARE;
1381 if (!strcmp(str, "Circle")) return PDF_ANNOT_LE_CIRCLE;
1382 if (!strcmp(str, "Diamond")) return PDF_ANNOT_LE_DIAMOND;
1383 if (!strcmp(str, "OpenArrow")) return PDF_ANNOT_LE_OPEN_ARROW;
1384 if (!strcmp(str, "ClosedArrow")) return PDF_ANNOT_LE_CLOSED_ARROW;
1385 if (!strcmp(str, "Butt")) return PDF_ANNOT_LE_BUTT;
1386 if (!strcmp(str, "ROpenArrow")) return PDF_ANNOT_LE_R_OPEN_ARROW;
1387 if (!strcmp(str, "RClosedArrow")) return PDF_ANNOT_LE_R_CLOSED_ARROW;
1388 if (!strcmp(str, "Slash")) return PDF_ANNOT_LE_SLASH;
1389 return PDF_ANNOT_LE_NONE;
1390 }
1391
1392 #endif
1393
1394 static fz_link_dest_type link_dest_type_from_string(const char *str)
1395 {
1396 if (!strcmp(str, "XYZ")) return FZ_LINK_DEST_XYZ;
1397 if (!strcmp(str, "Fit")) return FZ_LINK_DEST_FIT;
1398 if (!strcmp(str, "FitH")) return FZ_LINK_DEST_FIT_H;
1399 if (!strcmp(str, "FitV")) return FZ_LINK_DEST_FIT_V;
1400 if (!strcmp(str, "FitR")) return FZ_LINK_DEST_FIT_R;
1401 if (!strcmp(str, "FitB")) return FZ_LINK_DEST_FIT_B;
1402 if (!strcmp(str, "FitBH")) return FZ_LINK_DEST_FIT_BH;
1403 if (!strcmp(str, "FitBV")) return FZ_LINK_DEST_FIT_BV;
1404 return FZ_LINK_DEST_FIT;
1405 }
1406
1407 static void ffi_gc_fz_link(js_State *J, void *link)
1408 {
1409 fz_context *ctx = js_getcontext(J);
1410 fz_drop_link(ctx, link);
1411 }
1412
1413 static fz_link *ffi_tolink(js_State *J, int idx)
1414 {
1415 return js_touserdata(J, idx, "fz_link");
1416 }
1417
1418 static void ffi_pushlink(js_State *J, fz_link *link)
1419 {
1420 js_getregistry(J, "fz_link");
1421 js_newuserdata(J, "fz_link", link, ffi_gc_fz_link);
1422 }
1423
1424 static void ffi_pushlinkdest(js_State *J, const fz_link_dest dest)
1425 {
1426 js_newobject(J);
1427
1428 js_pushnumber(J, dest.loc.chapter);
1429 js_setproperty(J, -2, "chapter");
1430 js_pushnumber(J, dest.loc.page);
1431 js_setproperty(J, -2, "page");
1432
1433 js_pushliteral(J, string_from_destination_type(dest.type));
1434 js_setproperty(J, -2, "type");
1435
1436 switch (dest.type)
1437 {
1438 default:
1439 case FZ_LINK_DEST_FIT:
1440 case FZ_LINK_DEST_FIT_B:
1441 break;
1442 case FZ_LINK_DEST_FIT_H:
1443 case FZ_LINK_DEST_FIT_BH:
1444 js_pushnumber(J, dest.y);
1445 js_setproperty(J, -2, "y");
1446 break;
1447 case FZ_LINK_DEST_FIT_V:
1448 case FZ_LINK_DEST_FIT_BV:
1449 js_pushnumber(J, dest.x);
1450 js_setproperty(J, -2, "x");
1451 break;
1452 case FZ_LINK_DEST_XYZ:
1453 js_pushnumber(J, dest.x);
1454 js_setproperty(J, -2, "x");
1455 js_pushnumber(J, dest.y);
1456 js_setproperty(J, -2, "y");
1457 js_pushnumber(J, dest.zoom);
1458 js_setproperty(J, -2, "zoom");
1459 break;
1460 case FZ_LINK_DEST_FIT_R:
1461 js_pushnumber(J, dest.x);
1462 js_setproperty(J, -2, "x");
1463 js_pushnumber(J, dest.y);
1464 js_setproperty(J, -2, "y");
1465 js_pushnumber(J, dest.w);
1466 js_setproperty(J, -2, "width");
1467 js_pushnumber(J, dest.h);
1468 js_setproperty(J, -2, "height");
1469 break;
1470 }
1471 }
1472
1473 static void ffi_pushstroke(js_State *J, const fz_stroke_state *stroke)
1474 {
1475 fz_context *ctx = js_getcontext(J);
1476 js_getregistry(J, "fz_stroke_state");
1477 js_newuserdata(J, "fz_stroke_state", fz_keep_stroke_state(ctx, stroke), NULL);
1478 }
1479
1480 static fz_stroke_state *ffi_tostroke(js_State *J, int idx)
1481 {
1482 return (fz_stroke_state *) js_touserdata(J, idx, "fz_stroke_state");
1483 }
1484
1485 static void ffi_pushtext(js_State *J, const fz_text *text)
1486 {
1487 fz_context *ctx = js_getcontext(J);
1488 js_getregistry(J, "fz_text");
1489 js_newuserdata(J, "fz_text", fz_keep_text(ctx, text), ffi_gc_fz_text);
1490 }
1491
1492 static void ffi_pushpath(js_State *J, const fz_path *path)
1493 {
1494 fz_context *ctx = js_getcontext(J);
1495 js_getregistry(J, "fz_path");
1496 js_newuserdata(J, "fz_path", fz_keep_path(ctx, path), ffi_gc_fz_path);
1497 }
1498
1499 static void ffi_pushfont(js_State *J, fz_font *font)
1500 {
1501 fz_context *ctx = js_getcontext(J);
1502 js_getregistry(J, "fz_font");
1503 js_newuserdata(J, "fz_font", fz_keep_font(ctx, font), ffi_gc_fz_font);
1504 }
1505
1506 static void ffi_pushshade(js_State *J, fz_shade *shade)
1507 {
1508 fz_context *ctx = js_getcontext(J);
1509 js_getregistry(J, "fz_shade");
1510 js_newuserdata(J, "fz_shade", fz_keep_shade(ctx, shade), ffi_gc_fz_shade);
1511 }
1512
1513 static void ffi_pushimage(js_State *J, fz_image *image)
1514 {
1515 fz_context *ctx = js_getcontext(J);
1516 js_getregistry(J, "fz_image");
1517 js_newuserdata(J, "fz_image", fz_keep_image(ctx, image), ffi_gc_fz_image);
1518 }
1519
1520 static void ffi_pushimage_own(js_State *J, fz_image *image)
1521 {
1522 js_getregistry(J, "fz_image");
1523 js_newuserdata(J, "fz_image", image, ffi_gc_fz_image);
1524 }
1525
1526 static int is_number(const char *key, int *idx)
1527 {
1528 char *end;
1529 *idx = strtol(key, &end, 10);
1530 return *end == 0;
1531 }
1532
1533 static fz_archive *ffi_toarchive(js_State *J, int idx)
1534 {
1535 if (js_isuserdata(J, idx, "fz_tree_archive"))
1536 return js_touserdata(J, idx, "fz_tree_archive");
1537 if (js_isuserdata(J, idx, "fz_multi_archive"))
1538 return js_touserdata(J, idx, "fz_multi_archive");
1539 return js_touserdata(J, idx, "fz_archive");
1540 }
1541
1542 static void ffi_pusharchive(js_State *J, fz_archive *arch)
1543 {
1544 js_getregistry(J, "fz_archive");
1545 js_newuserdata(J, "fz_archive", arch, ffi_gc_fz_archive);
1546 }
1547
1548 static void ffi_pushmultiarchive(js_State *J, fz_archive *arch)
1549 {
1550 js_getregistry(J, "fz_multi_archive");
1551 js_newuserdata(J, "fz_multi_archive", arch, ffi_gc_fz_archive);
1552 }
1553
1554 static void ffi_pushtreearchive(js_State *J, fz_archive *arch)
1555 {
1556 js_getregistry(J, "fz_tree_archive");
1557 js_newuserdata(J, "fz_tree_archive", arch, ffi_gc_fz_archive);
1558 }
1559
1560 static int ffi_buffer_has(js_State *J, void *buf_, const char *key)
1561 {
1562 fz_buffer *buf = buf_;
1563 int idx;
1564 unsigned char *data;
1565 size_t len = fz_buffer_storage(js_getcontext(J), buf, &data);
1566 if (is_number(key, &idx)) {
1567 if (idx < 0 || (size_t)idx >= len)
1568 js_rangeerror(J, "index out of bounds");
1569 js_pushnumber(J, data[idx]);
1570 return 1;
1571 }
1572 if (!strcmp(key, "length")) {
1573 js_pushnumber(J, len);
1574 return 1;
1575 }
1576 return 0;
1577 }
1578
1579 static int ffi_buffer_put(js_State *J, void *buf_, const char *key)
1580 {
1581 fz_buffer *buf = buf_;
1582 int idx;
1583 unsigned char *data;
1584 size_t len = fz_buffer_storage(js_getcontext(J), buf, &data);
1585 if (is_number(key, &idx)) {
1586 if (idx < 0 || (size_t)idx >= len)
1587 js_rangeerror(J, "index out of bounds");
1588 data[idx] = js_tointeger(J, -1);
1589 return 1;
1590 }
1591 if (!strcmp(key, "length"))
1592 js_typeerror(J, "buffer length is read-only");
1593 return 0;
1594 }
1595
1596 static void ffi_pushbuffer_own(js_State *J, fz_buffer *buf)
1597 {
1598 js_getregistry(J, "fz_buffer");
1599 js_newuserdatax(J, "fz_buffer", buf,
1600 ffi_buffer_has, ffi_buffer_put, NULL,
1601 ffi_gc_fz_buffer);
1602 }
1603
1604 static fz_buffer *ffi_tonewbuffer(js_State *J, int idx)
1605 {
1606 fz_context *ctx = js_getcontext(J);
1607 fz_buffer *buf = NULL;
1608
1609 if (js_isuserdata(J, idx, "fz_buffer"))
1610 buf = fz_keep_buffer(ctx, js_touserdata(J, idx, "fz_buffer"));
1611 else if (!js_iscoercible(J, idx)) {
1612 fz_try(ctx)
1613 buf = fz_new_buffer(ctx, 1);
1614 fz_catch(ctx)
1615 rethrow(J);
1616 }
1617 else {
1618 const char *str = js_tostring(J, idx);
1619 fz_try(ctx)
1620 buf = fz_new_buffer_from_copied_data(ctx, (const unsigned char *)str, strlen(str));
1621 fz_catch(ctx)
1622 rethrow(J);
1623 }
1624
1625 return buf;
1626 }
1627
1628 /* font loading callbacks */
1629
1630 static fz_font *load_js_font_file(fz_context *ctx, const char *name, const char *script, int bold, int italic)
1631 {
1632 js_State *J = fz_user_context(ctx);
1633 fz_font *font = NULL;
1634 if (js_try(J))
1635 rethrow_as_fz(J);
1636 js_getregistry(J, "load_font_file");
1637 if (js_iscallable(J, -1)) {
1638 js_pushnull(J);
1639 if (name)
1640 js_pushstring(J, name);
1641 else
1642 js_pushundefined(J);
1643 if (script)
1644 js_pushstring(J, script);
1645 else
1646 js_pushundefined(J);
1647 js_pushboolean(J, bold);
1648 js_pushboolean(J, italic);
1649 js_call(J, 4);
1650 if (js_iscoercible(J, -1))
1651 font = fz_keep_font(ctx, js_touserdata(J, -1, "fz_font"));
1652 js_pop(J, 1);
1653 }
1654 js_endtry(J);
1655 return font;
1656 }
1657
1658 static fz_font *load_js_font(fz_context *ctx, const char *name, int bold, int italic, int needs_exact_metrics)
1659 {
1660 return load_js_font_file(ctx, name, "undefined", bold, italic);
1661 }
1662
1663 static fz_font *load_js_cjk_font(fz_context *ctx, const char *name, int ordering, int serif)
1664 {
1665 switch (ordering)
1666 {
1667 case FZ_ADOBE_CNS: return load_js_font_file(ctx, name, "TC", 0, 0);
1668 case FZ_ADOBE_GB: return load_js_font_file(ctx, name, "SC", 0, 0);
1669 case FZ_ADOBE_JAPAN: return load_js_font_file(ctx, name, "JP", 0, 0);
1670 case FZ_ADOBE_KOREA: return load_js_font_file(ctx, name, "KR", 0, 0);
1671 }
1672 return NULL;
1673 }
1674
1675 static fz_font *load_js_fallback_font(fz_context *ctx, int script, int language, int serif, int bold, int italic)
1676 {
1677 return load_js_font_file(ctx, "undefined", fz_lookup_script_name(ctx, script, language), bold, italic);
1678 }
1679
1680 static void ffi_installLoadFontFunction(js_State *J)
1681 {
1682 fz_context *ctx = js_getcontext(J);
1683 js_copy(J, 1);
1684 js_setregistry(J, "load_font_file");
1685 fz_try(ctx) {
1686 fz_install_load_system_font_funcs(ctx,
1687 load_js_font,
1688 load_js_cjk_font,
1689 load_js_fallback_font
1690 );
1691 } fz_catch(ctx) {
1692 rethrow(J);
1693 }
1694 }
1695
1696 /* device calling into js from c */
1697
1698 typedef struct
1699 {
1700 fz_device super;
1701 js_State *J;
1702 } js_device;
1703
1704 static void
1705 js_dev_fill_path(fz_context *ctx, fz_device *dev, const fz_path *path, int even_odd, fz_matrix ctm,
1706 fz_colorspace *colorspace, const float *color, float alpha, fz_color_params color_params)
1707 {
1708 js_State *J = ((js_device*)dev)->J;
1709 if (js_try(J))
1710 rethrow_as_fz(J);
1711 if (js_hasproperty(J, -1, "fillPath")) {
1712 js_copy(J, -2);
1713 ffi_pushpath(J, path);
1714 js_pushboolean(J, even_odd);
1715 ffi_pushmatrix(J, ctm);
1716 ffi_pushcolor(J, colorspace, color, alpha);
1717 ffi_pushcolorparams(J, color_params);
1718 js_call(J, 7);
1719 js_pop(J, 1);
1720 }
1721 js_endtry(J);
1722 }
1723
1724 static void
1725 js_dev_clip_path(fz_context *ctx, fz_device *dev, const fz_path *path, int even_odd, fz_matrix ctm,
1726 fz_rect scissor)
1727 {
1728 js_State *J = ((js_device*)dev)->J;
1729 if (js_try(J))
1730 rethrow_as_fz(J);
1731 if (js_hasproperty(J, -1, "clipPath")) {
1732 js_copy(J, -2);
1733 ffi_pushpath(J, path);
1734 js_pushboolean(J, even_odd);
1735 ffi_pushmatrix(J, ctm);
1736 js_call(J, 3);
1737 js_pop(J, 1);
1738 }
1739 js_endtry(J);
1740 }
1741
1742 static void
1743 js_dev_stroke_path(fz_context *ctx, fz_device *dev, const fz_path *path,
1744 const fz_stroke_state *stroke, fz_matrix ctm,
1745 fz_colorspace *colorspace, const float *color, float alpha, fz_color_params color_params)
1746 {
1747 js_State *J = ((js_device*)dev)->J;
1748 if (js_try(J))
1749 rethrow_as_fz(J);
1750 if (js_hasproperty(J, -1, "strokePath")) {
1751 js_copy(J, -2);
1752 ffi_pushpath(J, path);
1753 ffi_pushstroke(J, stroke);
1754 ffi_pushmatrix(J, ctm);
1755 ffi_pushcolor(J, colorspace, color, alpha);
1756 ffi_pushcolorparams(J, color_params);
1757 js_call(J, 7);
1758 js_pop(J, 1);
1759 }
1760 js_endtry(J);
1761 }
1762
1763 static void
1764 js_dev_clip_stroke_path(fz_context *ctx, fz_device *dev, const fz_path *path, const fz_stroke_state *stroke,
1765 fz_matrix ctm, fz_rect scissor)
1766 {
1767 js_State *J = ((js_device*)dev)->J;
1768 if (js_try(J))
1769 rethrow_as_fz(J);
1770 if (js_hasproperty(J, -1, "clipStrokePath")) {
1771 js_copy(J, -2);
1772 ffi_pushpath(J, path);
1773 ffi_pushstroke(J, stroke);
1774 ffi_pushmatrix(J, ctm);
1775 js_call(J, 3);
1776 js_pop(J, 1);
1777 }
1778 js_endtry(J);
1779 }
1780
1781 static void
1782 js_dev_fill_text(fz_context *ctx, fz_device *dev, const fz_text *text, fz_matrix ctm,
1783 fz_colorspace *colorspace, const float *color, float alpha, fz_color_params color_params)
1784 {
1785 js_State *J = ((js_device*)dev)->J;
1786 if (js_try(J))
1787 rethrow_as_fz(J);
1788 if (js_hasproperty(J, -1, "fillText")) {
1789 js_copy(J, -2);
1790 ffi_pushtext(J, text);
1791 ffi_pushmatrix(J, ctm);
1792 ffi_pushcolor(J, colorspace, color, alpha);
1793 ffi_pushcolorparams(J, color_params);
1794 js_call(J, 6);
1795 js_pop(J, 1);
1796 }
1797 js_endtry(J);
1798 }
1799
1800 static void
1801 js_dev_stroke_text(fz_context *ctx, fz_device *dev, const fz_text *text, const fz_stroke_state *stroke,
1802 fz_matrix ctm, fz_colorspace *colorspace, const float *color, float alpha, fz_color_params color_params)
1803 {
1804 js_State *J = ((js_device*)dev)->J;
1805 if (js_try(J))
1806 rethrow_as_fz(J);
1807 if (js_hasproperty(J, -1, "strokeText")) {
1808 js_copy(J, -2);
1809 ffi_pushtext(J, text);
1810 ffi_pushstroke(J, stroke);
1811 ffi_pushmatrix(J, ctm);
1812 ffi_pushcolor(J, colorspace, color, alpha);
1813 ffi_pushcolorparams(J, color_params);
1814 js_call(J, 7);
1815 js_pop(J, 1);
1816 }
1817 js_endtry(J);
1818 }
1819
1820 static void
1821 js_dev_clip_text(fz_context *ctx, fz_device *dev, const fz_text *text, fz_matrix ctm, fz_rect scissor)
1822 {
1823 js_State *J = ((js_device*)dev)->J;
1824 if (js_try(J))
1825 rethrow_as_fz(J);
1826 if (js_hasproperty(J, -1, "clipText")) {
1827 js_copy(J, -2);
1828 ffi_pushtext(J, text);
1829 ffi_pushmatrix(J, ctm);
1830 js_call(J, 2);
1831 js_pop(J, 1);
1832 }
1833 js_endtry(J);
1834 }
1835
1836 static void
1837 js_dev_clip_stroke_text(fz_context *ctx, fz_device *dev, const fz_text *text, const fz_stroke_state *stroke,
1838 fz_matrix ctm, fz_rect scissor)
1839 {
1840 js_State *J = ((js_device*)dev)->J;
1841 if (js_try(J))
1842 rethrow_as_fz(J);
1843 if (js_hasproperty(J, -1, "clipStrokeText")) {
1844 js_copy(J, -2);
1845 ffi_pushtext(J, text);
1846 ffi_pushstroke(J, stroke);
1847 ffi_pushmatrix(J, ctm);
1848 js_call(J, 3);
1849 js_pop(J, 1);
1850 }
1851 js_endtry(J);
1852 }
1853
1854 static void
1855 js_dev_ignore_text(fz_context *ctx, fz_device *dev, const fz_text *text, fz_matrix ctm)
1856 {
1857 js_State *J = ((js_device*)dev)->J;
1858 if (js_try(J))
1859 rethrow_as_fz(J);
1860 if (js_hasproperty(J, -1, "ignoreText")) {
1861 js_copy(J, -2);
1862 ffi_pushtext(J, text);
1863 ffi_pushmatrix(J, ctm);
1864 js_call(J, 2);
1865 js_pop(J, 1);
1866 }
1867 js_endtry(J);
1868 }
1869
1870 static void
1871 js_dev_fill_shade(fz_context *ctx, fz_device *dev, fz_shade *shade, fz_matrix ctm, float alpha, fz_color_params color_params)
1872 {
1873 js_State *J = ((js_device*)dev)->J;
1874 if (js_try(J))
1875 rethrow_as_fz(J);
1876 if (js_hasproperty(J, -1, "fillShade")) {
1877 js_copy(J, -2);
1878 ffi_pushshade(J, shade);
1879 ffi_pushmatrix(J, ctm);
1880 js_pushnumber(J, alpha);
1881 ffi_pushcolorparams(J, color_params);
1882 js_call(J, 4);
1883 js_pop(J, 1);
1884 }
1885 js_endtry(J);
1886 }
1887
1888 static void
1889 js_dev_fill_image(fz_context *ctx, fz_device *dev, fz_image *image, fz_matrix ctm, float alpha, fz_color_params color_params)
1890 {
1891 js_State *J = ((js_device*)dev)->J;
1892 if (js_try(J))
1893 rethrow_as_fz(J);
1894 if (js_hasproperty(J, -1, "fillImage")) {
1895 js_copy(J, -2);
1896 ffi_pushimage(J, image);
1897 ffi_pushmatrix(J, ctm);
1898 js_pushnumber(J, alpha);
1899 ffi_pushcolorparams(J, color_params);
1900 js_call(J, 4);
1901 js_pop(J, 1);
1902 }
1903 js_endtry(J);
1904 }
1905
1906 static void
1907 js_dev_fill_image_mask(fz_context *ctx, fz_device *dev, fz_image *image, fz_matrix ctm,
1908 fz_colorspace *colorspace, const float *color, float alpha, fz_color_params color_params)
1909 {
1910 js_State *J = ((js_device*)dev)->J;
1911 if (js_try(J))
1912 rethrow_as_fz(J);
1913 if (js_hasproperty(J, -1, "fillImageMask")) {
1914 js_copy(J, -2);
1915 ffi_pushimage(J, image);
1916 ffi_pushmatrix(J, ctm);
1917 ffi_pushcolor(J, colorspace, color, alpha);
1918 ffi_pushcolorparams(J, color_params);
1919 js_call(J, 6);
1920 js_pop(J, 1);
1921 }
1922 js_endtry(J);
1923 }
1924
1925 static void
1926 js_dev_clip_image_mask(fz_context *ctx, fz_device *dev, fz_image *image, fz_matrix ctm, fz_rect scissor)
1927 {
1928 js_State *J = ((js_device*)dev)->J;
1929 if (js_try(J))
1930 rethrow_as_fz(J);
1931 if (js_hasproperty(J, -1, "clipImageMask")) {
1932 js_copy(J, -2);
1933 ffi_pushimage(J, image);
1934 ffi_pushmatrix(J, ctm);
1935 js_call(J, 2);
1936 js_pop(J, 1);
1937 }
1938 js_endtry(J);
1939 }
1940
1941 static void
1942 js_dev_pop_clip(fz_context *ctx, fz_device *dev)
1943 {
1944 js_State *J = ((js_device*)dev)->J;
1945 if (js_try(J))
1946 rethrow_as_fz(J);
1947 if (js_hasproperty(J, -1, "popClip")) {
1948 js_copy(J, -2);
1949 js_call(J, 0);
1950 js_pop(J, 1);
1951 }
1952 js_endtry(J);
1953 }
1954
1955 static void
1956 js_dev_begin_mask(fz_context *ctx, fz_device *dev, fz_rect bbox, int luminosity,
1957 fz_colorspace *colorspace, const float *color, fz_color_params color_params)
1958 {
1959 js_State *J = ((js_device*)dev)->J;
1960 if (js_try(J))
1961 rethrow_as_fz(J);
1962 if (js_hasproperty(J, -1, "beginMask")) {
1963 js_copy(J, -2);
1964 ffi_pushrect(J, bbox);
1965 js_pushboolean(J, luminosity);
1966 if (colorspace) {
1967 ffi_pushcolorspace(J, colorspace);
1968 ffi_pusharray(J, color, fz_colorspace_n(ctx, colorspace));
1969 } else {
1970 js_pushnull(J);
1971 js_pushnull(J);
1972 }
1973 ffi_pushcolorparams(J, color_params);
1974 js_call(J, 5);
1975 js_pop(J, 1);
1976 }
1977 js_endtry(J);
1978 }
1979
1980 static void
1981 js_dev_end_mask(fz_context *ctx, fz_device *dev, fz_function *tr)
1982 {
1983 js_State *J = ((js_device*)dev)->J;
1984
1985 if (tr)
1986 fz_warn(ctx, "Ignoring Transfer function");
1987 if (js_try(J))
1988 rethrow_as_fz(J);
1989 if (js_hasproperty(J, -1, "endMask")) {
1990 js_copy(J, -2);
1991 js_call(J, 0);
1992 js_pop(J, 1);
1993 }
1994 js_endtry(J);
1995 }
1996
1997 static void
1998 js_dev_begin_group(fz_context *ctx, fz_device *dev, fz_rect bbox,
1999 fz_colorspace *cs, int isolated, int knockout, int blendmode, float alpha)
2000 {
2001 js_State *J = ((js_device*)dev)->J;
2002 if (js_try(J))
2003 rethrow_as_fz(J);
2004 if (js_hasproperty(J, -1, "beginGroup")) {
2005 js_copy(J, -2);
2006 ffi_pushrect(J, bbox);
2007 ffi_pushcolorspace(J, cs);
2008 js_pushboolean(J, isolated);
2009 js_pushboolean(J, knockout);
2010 js_pushliteral(J, fz_blendmode_name(blendmode));
2011 js_pushnumber(J, alpha);
2012 js_call(J, 6);
2013 js_pop(J, 1);
2014 }
2015 js_endtry(J);
2016 }
2017
2018 static void
2019 js_dev_end_group(fz_context *ctx, fz_device *dev)
2020 {
2021 js_State *J = ((js_device*)dev)->J;
2022 if (js_try(J))
2023 rethrow_as_fz(J);
2024 if (js_hasproperty(J, -1, "endGroup")) {
2025 js_copy(J, -2);
2026 js_call(J, 0);
2027 js_pop(J, 1);
2028 }
2029 js_endtry(J);
2030 }
2031
2032 static int
2033 js_dev_begin_tile(fz_context *ctx, fz_device *dev, fz_rect area, fz_rect view,
2034 float xstep, float ystep, fz_matrix ctm, int id, int doc_id)
2035 {
2036 js_State *J = ((js_device*)dev)->J;
2037 if (js_try(J))
2038 rethrow_as_fz(J);
2039 if (js_hasproperty(J, -1, "beginTile")) {
2040 int n;
2041 js_copy(J, -2);
2042 ffi_pushrect(J, area);
2043 ffi_pushrect(J, view);
2044 js_pushnumber(J, xstep);
2045 js_pushnumber(J, ystep);
2046 ffi_pushmatrix(J, ctm);
2047 js_pushnumber(J, id);
2048 js_pushnumber(J, doc_id);
2049 js_call(J, 7);
2050 n = js_tointeger(J, -1);
2051 js_pop(J, 1);
2052 return n;
2053 }
2054 js_endtry(J);
2055 return 0;
2056 }
2057
2058 static void
2059 js_dev_end_tile(fz_context *ctx, fz_device *dev)
2060 {
2061 js_State *J = ((js_device*)dev)->J;
2062 if (js_try(J))
2063 rethrow_as_fz(J);
2064 if (js_hasproperty(J, -1, "endTile")) {
2065 js_copy(J, -2);
2066 js_call(J, 0);
2067 js_pop(J, 1);
2068 }
2069 js_endtry(J);
2070 }
2071
2072 static void
2073 js_dev_render_flags(fz_context *ctx, fz_device *dev, int set, int clear)
2074 {
2075 js_State *J = ((js_device*)dev)->J;
2076 if (js_try(J))
2077 rethrow_as_fz(J);
2078 if (js_hasproperty(J, -1, "renderFlags")) {
2079 js_copy(J, -2);
2080 ffi_pushrenderflags(J, set);
2081 ffi_pushrenderflags(J, clear);
2082 js_call(J, 2);
2083 js_pop(J, 1);
2084 }
2085 js_endtry(J);
2086 }
2087
2088 static void
2089 js_dev_set_default_colorspaces(fz_context *ctx, fz_device *dev, fz_default_colorspaces *default_cs)
2090 {
2091 js_State *J = ((js_device*)dev)->J;
2092 if (js_try(J))
2093 rethrow_as_fz(J);
2094 if (js_hasproperty(J, -1, "setDefaultColorSpaces")) {
2095 js_copy(J, -2);
2096 ffi_pushdefaultcolorspaces(J, fz_keep_default_colorspaces(ctx, default_cs));
2097 js_call(J, 1);
2098 js_pop(J, 1);
2099 }
2100 js_endtry(J);
2101 }
2102
2103 static void
2104 js_dev_begin_layer(fz_context *ctx, fz_device *dev, const char *name)
2105 {
2106 js_State *J = ((js_device*)dev)->J;
2107 if (js_try(J))
2108 rethrow_as_fz(J);
2109 if (js_hasproperty(J, -1, "beginLayer")) {
2110 js_copy(J, -2);
2111 if (name)
2112 js_pushstring(J, name);
2113 else
2114 js_pushnull(J);
2115 js_call(J, 1);
2116 js_pop(J, 1);
2117 }
2118 js_endtry(J);
2119 }
2120
2121 static void
2122 js_dev_end_layer(fz_context *ctx, fz_device *dev)
2123 {
2124 js_State *J = ((js_device*)dev)->J;
2125 if (js_try(J))
2126 rethrow_as_fz(J);
2127 if (js_hasproperty(J, -1, "endLayer")) {
2128 js_copy(J, -2);
2129 js_call(J, 0);
2130 js_pop(J, 1);
2131 }
2132 js_endtry(J);
2133 }
2134
2135 static void
2136 js_dev_begin_structure(fz_context *ctx, fz_device *dev, fz_structure standard, const char *raw, int idx)
2137 {
2138 js_State *J = ((js_device*)dev)->J;
2139 if (raw == NULL)
2140 raw = "";
2141 if (js_try(J))
2142 rethrow_as_fz(J);
2143 if (js_hasproperty(J, -1, "beginStructure")) {
2144 js_copy(J, -2);
2145 js_pushliteral(J, fz_structure_to_string(standard));
2146 js_pushstring(J, raw);
2147 js_pushnumber(J, idx);
2148 js_call(J, 3);
2149 js_pop(J, 1);
2150 }
2151 js_endtry(J);
2152 }
2153
2154 static void
2155 js_dev_end_structure(fz_context *ctx, fz_device *dev)
2156 {
2157 js_State *J = ((js_device*)dev)->J;
2158 if (js_try(J))
2159 rethrow_as_fz(J);
2160 if (js_hasproperty(J, -1, "endStructure")) {
2161 js_copy(J, -2);
2162 js_call(J, 0);
2163 js_pop(J, 1);
2164 }
2165 js_endtry(J);
2166 }
2167
2168 static void
2169 js_dev_begin_metatext(fz_context *ctx, fz_device *dev, fz_metatext meta, const char *text)
2170 {
2171 js_State *J = ((js_device*)dev)->J;
2172 if (js_try(J))
2173 rethrow_as_fz(J);
2174 if (js_hasproperty(J, -1, "beginMetatext")) {
2175 js_copy(J, -2);
2176 js_pushliteral(J, string_from_metatext(meta));
2177 if (text)
2178 js_pushstring(J, text);
2179 else
2180 js_pushnull(J);
2181 js_call(J, 2);
2182 js_pop(J, 1);
2183 }
2184 js_endtry(J);
2185 }
2186
2187 static void
2188 js_dev_end_metatext(fz_context *ctx, fz_device *dev)
2189 {
2190 js_State *J = ((js_device*)dev)->J;
2191 if (js_try(J))
2192 rethrow_as_fz(J);
2193 if (js_hasproperty(J, -1, "endMetatext")) {
2194 js_copy(J, -2);
2195 js_call(J, 0);
2196 js_pop(J, 1);
2197 }
2198 js_endtry(J);
2199 }
2200
2201 static fz_device *new_js_device(fz_context *ctx, js_State *J)
2202 {
2203 js_device *dev = fz_new_derived_device(ctx, js_device);
2204
2205 dev->super.fill_path = js_dev_fill_path;
2206 dev->super.stroke_path = js_dev_stroke_path;
2207 dev->super.clip_path = js_dev_clip_path;
2208 dev->super.clip_stroke_path = js_dev_clip_stroke_path;
2209
2210 dev->super.fill_text = js_dev_fill_text;
2211 dev->super.stroke_text = js_dev_stroke_text;
2212 dev->super.clip_text = js_dev_clip_text;
2213 dev->super.clip_stroke_text = js_dev_clip_stroke_text;
2214 dev->super.ignore_text = js_dev_ignore_text;
2215
2216 dev->super.fill_shade = js_dev_fill_shade;
2217 dev->super.fill_image = js_dev_fill_image;
2218 dev->super.fill_image_mask = js_dev_fill_image_mask;
2219 dev->super.clip_image_mask = js_dev_clip_image_mask;
2220
2221 dev->super.pop_clip = js_dev_pop_clip;
2222
2223 dev->super.begin_mask = js_dev_begin_mask;
2224 dev->super.end_mask = js_dev_end_mask;
2225 dev->super.begin_group = js_dev_begin_group;
2226 dev->super.end_group = js_dev_end_group;
2227
2228 dev->super.begin_tile = js_dev_begin_tile;
2229 dev->super.end_tile = js_dev_end_tile;
2230
2231 dev->super.render_flags = js_dev_render_flags;
2232 dev->super.set_default_colorspaces = js_dev_set_default_colorspaces;
2233
2234 dev->super.begin_layer = js_dev_begin_layer;
2235 dev->super.end_layer = js_dev_end_layer;
2236
2237 dev->super.begin_structure = js_dev_begin_structure;
2238 dev->super.end_structure = js_dev_end_structure;
2239
2240 dev->super.begin_metatext = js_dev_begin_metatext;
2241 dev->super.end_metatext = js_dev_end_metatext;
2242
2243 dev->J = J;
2244 return (fz_device*)dev;
2245 }
2246
2247 /* PDF operator processor */
2248
2249 #if FZ_ENABLE_PDF
2250
2251 typedef struct resources_stack
2252 {
2253 struct resources_stack *next;
2254 pdf_obj *resources;
2255 } resources_stack;
2256
2257 typedef struct
2258 {
2259 pdf_processor super;
2260 js_State *J;
2261 resources_stack *rstack;
2262 int extgstate;
2263 } pdf_js_processor;
2264
2265 #define PROC_BEGIN(OP) \
2266 { js_State *J = ((pdf_js_processor*)proc)->J; \
2267 if (js_try(J)) \
2268 rethrow_as_fz(J); \
2269 if (js_hasproperty(J, 1, OP)) { \
2270 js_copy(J, 1);
2271
2272 #define PROC_END(N) \
2273 js_call(J, N); \
2274 js_pop(J, 1); \
2275 } \
2276 js_endtry(J); }
2277
2278 static void js_proc_w(fz_context *ctx, pdf_processor *proc, float linewidth)
2279 {
2280 if (!((pdf_js_processor*)proc)->extgstate)
2281 {
2282 PROC_BEGIN("op_w");
2283 js_pushnumber(J, linewidth);
2284 PROC_END(1);
2285 }
2286 }
2287
2288 static void js_proc_j(fz_context *ctx, pdf_processor *proc, int linejoin)
2289 {
2290 if (!((pdf_js_processor*)proc)->extgstate)
2291 {
2292 PROC_BEGIN("op_j");
2293 js_pushnumber(J, linejoin);
2294 PROC_END(1);
2295 }
2296 }
2297
2298 static void js_proc_J(fz_context *ctx, pdf_processor *proc, int linecap)
2299 {
2300 if (!((pdf_js_processor*)proc)->extgstate)
2301 {
2302 PROC_BEGIN("op_J");
2303 js_pushnumber(J, linecap);
2304 PROC_END(1);
2305 }
2306 }
2307
2308 static void js_proc_M(fz_context *ctx, pdf_processor *proc, float miterlimit)
2309 {
2310 if (!((pdf_js_processor*)proc)->extgstate)
2311 {
2312 PROC_BEGIN("op_M");
2313 js_pushnumber(J, miterlimit);
2314 PROC_END(1);
2315 }
2316 }
2317
2318 static void js_proc_d(fz_context *ctx, pdf_processor *proc, pdf_obj *array, float phase)
2319 {
2320 int i, n = pdf_array_len(ctx, array);
2321 PROC_BEGIN("op_d");
2322 {
2323 js_newarray(J);
2324 for (i = 0; i < n; ++i)
2325 {
2326 /* we know the array only holds numbers and strings, so we are safe from exceptions here */
2327 js_pushnumber(J, pdf_array_get_real(ctx, array, i));
2328 js_setindex(J, -2, i);
2329 }
2330 js_pushnumber(J, phase);
2331 }
2332 PROC_END(2);
2333 }
2334
2335 static void js_proc_ri(fz_context *ctx, pdf_processor *proc, const char *intent)
2336 {
2337 if (!((pdf_js_processor*)proc)->extgstate)
2338 {
2339 PROC_BEGIN("op_ri");
2340 js_pushstring(J, intent);
2341 PROC_END(1);
2342 }
2343 }
2344
2345 static void js_proc_i(fz_context *ctx, pdf_processor *proc, float flatness)
2346 {
2347 if (!((pdf_js_processor*)proc)->extgstate)
2348 {
2349 PROC_BEGIN("op_i");
2350 js_pushnumber(J, flatness);
2351 PROC_END(1);
2352 }
2353 }
2354
2355 static void js_proc_gs_begin(fz_context *ctx, pdf_processor *proc, const char *name, pdf_obj *extgstate)
2356 {
2357 ((pdf_js_processor*)proc)->extgstate = 1;
2358 PROC_BEGIN("op_gs");
2359 js_pushstring(J, name);
2360 ffi_pushobj(J, pdf_keep_obj(ctx, extgstate));
2361 PROC_END(2);
2362 }
2363
2364 static void js_proc_gs_end(fz_context *ctx, pdf_processor *proc)
2365 {
2366 ((pdf_js_processor*)proc)->extgstate = 0;
2367 }
2368
2369 static void js_proc_q(fz_context *ctx, pdf_processor *proc)
2370 {
2371 PROC_BEGIN("op_q");
2372 PROC_END(0);
2373 }
2374
2375 static void js_proc_Q(fz_context *ctx, pdf_processor *proc)
2376 {
2377 PROC_BEGIN("op_Q");
2378 PROC_END(0);
2379 }
2380
2381 static void js_proc_cm(fz_context *ctx, pdf_processor *proc, float a, float b, float c, float d, float e, float f)
2382 {
2383 PROC_BEGIN("op_cm");
2384 js_pushnumber(J, a);
2385 js_pushnumber(J, b);
2386 js_pushnumber(J, c);
2387 js_pushnumber(J, d);
2388 js_pushnumber(J, e);
2389 js_pushnumber(J, f);
2390 PROC_END(6);
2391 }
2392
2393 static void js_proc_m(fz_context *ctx, pdf_processor *proc, float x, float y)
2394 {
2395 PROC_BEGIN("op_m");
2396 js_pushnumber(J, x);
2397 js_pushnumber(J, y);
2398 PROC_END(2);
2399 }
2400
2401 static void js_proc_l(fz_context *ctx, pdf_processor *proc, float x, float y)
2402 {
2403 PROC_BEGIN("op_l");
2404 js_pushnumber(J, x);
2405 js_pushnumber(J, y);
2406 PROC_END(2);
2407 }
2408
2409 static void js_proc_c(fz_context *ctx, pdf_processor *proc, float x1, float y1, float x2, float y2, float x3, float y3)
2410 {
2411 PROC_BEGIN("op_c");
2412 js_pushnumber(J, x1);
2413 js_pushnumber(J, y1);
2414 js_pushnumber(J, x2);
2415 js_pushnumber(J, y2);
2416 js_pushnumber(J, x3);
2417 js_pushnumber(J, y3);
2418 PROC_END(6);
2419 }
2420
2421 static void js_proc_v(fz_context *ctx, pdf_processor *proc, float x2, float y2, float x3, float y3)
2422 {
2423 PROC_BEGIN("op_v");
2424 js_pushnumber(J, x2);
2425 js_pushnumber(J, y2);
2426 js_pushnumber(J, x3);
2427 js_pushnumber(J, y3);
2428 PROC_END(4);
2429 }
2430
2431 static void js_proc_y(fz_context *ctx, pdf_processor *proc, float x1, float y1, float x3, float y3)
2432 {
2433 PROC_BEGIN("op_y");
2434 js_pushnumber(J, x1);
2435 js_pushnumber(J, y1);
2436 js_pushnumber(J, x3);
2437 js_pushnumber(J, y3);
2438 PROC_END(4);
2439 }
2440
2441 static void js_proc_h(fz_context *ctx, pdf_processor *proc)
2442 {
2443 PROC_BEGIN("op_h");
2444 PROC_END(0);
2445 }
2446
2447 static void js_proc_re(fz_context *ctx, pdf_processor *proc, float x, float y, float w, float h)
2448 {
2449 PROC_BEGIN("op_re");
2450 js_pushnumber(J, x);
2451 js_pushnumber(J, y);
2452 js_pushnumber(J, w);
2453 js_pushnumber(J, h);
2454 PROC_END(4);
2455 }
2456
2457 static void js_proc_S(fz_context *ctx, pdf_processor *proc)
2458 {
2459 PROC_BEGIN("op_S");
2460 PROC_END(0);
2461 }
2462
2463 static void js_proc_s(fz_context *ctx, pdf_processor *proc)
2464 {
2465 PROC_BEGIN("op_s");
2466 PROC_END(0);
2467 }
2468
2469 static void js_proc_F(fz_context *ctx, pdf_processor *proc)
2470 {
2471 PROC_BEGIN("op_F");
2472 PROC_END(0);
2473 }
2474
2475 static void js_proc_f(fz_context *ctx, pdf_processor *proc)
2476 {
2477 PROC_BEGIN("op_f");
2478 PROC_END(0);
2479 }
2480
2481 static void js_proc_fstar(fz_context *ctx, pdf_processor *proc)
2482 {
2483 PROC_BEGIN("op_fstar");
2484 PROC_END(0);
2485 }
2486
2487 static void js_proc_B(fz_context *ctx, pdf_processor *proc)
2488 {
2489 PROC_BEGIN("op_B");
2490 PROC_END(0);
2491 }
2492
2493 static void js_proc_Bstar(fz_context *ctx, pdf_processor *proc)
2494 {
2495 PROC_BEGIN("op_Bstar");
2496 PROC_END(0);
2497 }
2498
2499 static void js_proc_b(fz_context *ctx, pdf_processor *proc)
2500 {
2501 PROC_BEGIN("op_b");
2502 PROC_END(0);
2503 }
2504
2505 static void js_proc_bstar(fz_context *ctx, pdf_processor *proc)
2506 {
2507 PROC_BEGIN("op_bstar");
2508 PROC_END(0);
2509 }
2510
2511 static void js_proc_n(fz_context *ctx, pdf_processor *proc)
2512 {
2513 PROC_BEGIN("op_n");
2514 PROC_END(0);
2515 }
2516
2517 static void js_proc_W(fz_context *ctx, pdf_processor *proc)
2518 {
2519 PROC_BEGIN("op_W");
2520 PROC_END(0);
2521 }
2522
2523 static void js_proc_Wstar(fz_context *ctx, pdf_processor *proc)
2524 {
2525 PROC_BEGIN("op_Wstar");
2526 PROC_END(0);
2527 }
2528
2529 static void js_proc_BT(fz_context *ctx, pdf_processor *proc)
2530 {
2531 PROC_BEGIN("op_BT");
2532 PROC_END(0);
2533 }
2534
2535 static void js_proc_ET(fz_context *ctx, pdf_processor *proc)
2536 {
2537 PROC_BEGIN("op_ET");
2538 PROC_END(0);
2539 }
2540
2541 static void js_proc_Tc(fz_context *ctx, pdf_processor *proc, float charspace)
2542 {
2543 PROC_BEGIN("op_Tc");
2544 js_pushnumber(J, charspace);
2545 PROC_END(1);
2546 }
2547
2548 static void js_proc_Tw(fz_context *ctx, pdf_processor *proc, float wordspace)
2549 {
2550 PROC_BEGIN("op_Tw");
2551 js_pushnumber(J, wordspace);
2552 PROC_END(1);
2553 }
2554
2555 static void js_proc_Tz(fz_context *ctx, pdf_processor *proc, float scale)
2556 {
2557 PROC_BEGIN("op_Tz");
2558 js_pushnumber(J, scale);
2559 PROC_END(1);
2560 }
2561
2562 static void js_proc_TL(fz_context *ctx, pdf_processor *proc, float leading)
2563 {
2564 PROC_BEGIN("op_TL");
2565 js_pushnumber(J, leading);
2566 PROC_END(1);
2567 }
2568
2569 static void js_proc_Tf(fz_context *ctx, pdf_processor *proc, const char *name, pdf_font_desc *font, float size)
2570 {
2571 if (!((pdf_js_processor*)proc)->extgstate)
2572 {
2573 PROC_BEGIN("op_Tf");
2574 js_pushstring(J, name);
2575 js_pushnumber(J, size);
2576 PROC_END(2);
2577 }
2578 }
2579
2580 static void js_proc_Tr(fz_context *ctx, pdf_processor *proc, int render)
2581 {
2582 PROC_BEGIN("op_Tr");
2583 js_pushnumber(J, render);
2584 PROC_END(1);
2585 }
2586
2587 static void js_proc_Ts(fz_context *ctx, pdf_processor *proc, float rise)
2588 {
2589 PROC_BEGIN("op_Ts");
2590 js_pushnumber(J, rise);
2591 PROC_END(1);
2592 }
2593
2594 static void js_proc_Td(fz_context *ctx, pdf_processor *proc, float tx, float ty)
2595 {
2596 PROC_BEGIN("op_Td");
2597 js_pushnumber(J, tx);
2598 js_pushnumber(J, ty);
2599 PROC_END(2);
2600 }
2601
2602 static void js_proc_TD(fz_context *ctx, pdf_processor *proc, float tx, float ty)
2603 {
2604 PROC_BEGIN("op_TD");
2605 js_pushnumber(J, tx);
2606 js_pushnumber(J, ty);
2607 PROC_END(2);
2608 }
2609
2610 static void js_proc_Tm(fz_context *ctx, pdf_processor *proc, float a, float b, float c, float d, float e, float f)
2611 {
2612 PROC_BEGIN("op_Tm");
2613 js_pushnumber(J, a);
2614 js_pushnumber(J, b);
2615 js_pushnumber(J, c);
2616 js_pushnumber(J, d);
2617 js_pushnumber(J, e);
2618 js_pushnumber(J, f);
2619 PROC_END(6);
2620 }
2621
2622 static void js_proc_Tstar(fz_context *ctx, pdf_processor *proc)
2623 {
2624 PROC_BEGIN("op_Tstar");
2625 PROC_END(0);
2626 }
2627
2628 static void push_byte_string(js_State *J, unsigned char *str, size_t len)
2629 {
2630 size_t i, is_ascii = 1;
2631 for (i = 0; i < len; ++i)
2632 if (str[i] == 0 || str[i] > 127)
2633 is_ascii = 0;
2634 if (is_ascii)
2635 js_pushstring(J, (char*)str);
2636 else
2637 {
2638 js_newarray(J);
2639 for (i = 0; i < len; ++i)
2640 {
2641 js_pushnumber(J, str[i]);
2642 js_setindex(J, -2, (int)i);
2643 }
2644 }
2645 }
2646
2647 static void js_proc_TJ(fz_context *ctx, pdf_processor *proc, pdf_obj *array)
2648 {
2649 int i, n = pdf_array_len(ctx, array);
2650 pdf_obj *obj;
2651 PROC_BEGIN("op_TJ");
2652 {
2653 /* we know the array only holds numbers and strings, so we are safe from exceptions here */
2654 js_newarray(J);
2655 for (i = 0; i < n; ++i)
2656 {
2657 obj = pdf_array_get(ctx, array, i);
2658 if (pdf_is_number(ctx, obj))
2659 js_pushnumber(J, pdf_to_real(ctx, obj));
2660 else
2661 {
2662 push_byte_string(J, (unsigned char *)pdf_to_str_buf(ctx, obj), pdf_to_str_len(ctx, obj));
2663 }
2664 js_setindex(J, -2, i);
2665 }
2666 }
2667 PROC_END(1);
2668 }
2669
2670 static void js_proc_Tj(fz_context *ctx, pdf_processor *proc, char *str, size_t len)
2671 {
2672 PROC_BEGIN("op_Tj");
2673 push_byte_string(J, (unsigned char *)str, len);
2674 PROC_END(1);
2675 }
2676
2677 static void js_proc_squote(fz_context *ctx, pdf_processor *proc, char *str, size_t len)
2678 {
2679 PROC_BEGIN("op_squote");
2680 push_byte_string(J, (unsigned char *)str, len);
2681 PROC_END(1);
2682 }
2683
2684 static void js_proc_dquote(fz_context *ctx, pdf_processor *proc, float aw, float ac, char *str, size_t len)
2685 {
2686 PROC_BEGIN("op_dquote");
2687 js_pushnumber(J, aw);
2688 js_pushnumber(J, ac);
2689 push_byte_string(J, (unsigned char *)str, len);
2690 PROC_END(1);
2691 }
2692
2693 static void js_proc_d0(fz_context *ctx, pdf_processor *proc, float wx, float wy)
2694 {
2695 PROC_BEGIN("op_d0");
2696 js_pushnumber(J, wx);
2697 js_pushnumber(J, wy);
2698 PROC_END(2);
2699 }
2700
2701 static void js_proc_d1(fz_context *ctx, pdf_processor *proc,
2702 float wx, float wy, float llx, float lly, float urx, float ury)
2703 {
2704 PROC_BEGIN("op_d1");
2705 js_pushnumber(J, wx);
2706 js_pushnumber(J, wy);
2707 js_pushnumber(J, llx);
2708 js_pushnumber(J, lly);
2709 js_pushnumber(J, urx);
2710 js_pushnumber(J, ury);
2711 PROC_END(6);
2712 }
2713
2714 static void js_proc_CS(fz_context *ctx, pdf_processor *proc, const char *name, fz_colorspace *cs)
2715 {
2716 PROC_BEGIN("op_CS");
2717 js_pushstring(J, name);
2718 ffi_pushcolorspace(J, cs);
2719 PROC_END(2);
2720 }
2721
2722 static void js_proc_cs(fz_context *ctx, pdf_processor *proc, const char *name, fz_colorspace *cs)
2723 {
2724 PROC_BEGIN("op_cs");
2725 js_pushstring(J, name);
2726 ffi_pushcolorspace(J, cs);
2727 PROC_END(2);
2728 }
2729
2730 static void js_proc_SC_pattern(fz_context *ctx, pdf_processor *proc, const char *name, pdf_pattern *pat, int n, float *color)
2731 {
2732 int i;
2733 PROC_BEGIN("op_SC_pattern");
2734 js_pushstring(J, name);
2735 js_pushnumber(J, pat->id); /* TODO: pdf_obj instead! */
2736 js_newarray(J);
2737 for (i = 0; i < n; ++i)
2738 {
2739 js_pushnumber(J, color[i]);
2740 js_setindex(J, -2, i);
2741 }
2742 PROC_END(3);
2743 }
2744
2745 static void js_proc_sc_pattern(fz_context *ctx, pdf_processor *proc, const char *name, pdf_pattern *pat, int n, float *color)
2746 {
2747 int i;
2748 PROC_BEGIN("op_sc_pattern");
2749 js_pushstring(J, name);
2750 js_pushnumber(J, pat->id); /* TODO: pdf_obj instead! */
2751 js_newarray(J);
2752 for (i = 0; i < n; ++i)
2753 {
2754 js_pushnumber(J, color[i]);
2755 js_setindex(J, -2, i);
2756 }
2757 PROC_END(3);
2758 }
2759
2760 static void js_proc_SC_shade(fz_context *ctx, pdf_processor *proc, const char *name, fz_shade *shade)
2761 {
2762 PROC_BEGIN("op_SC_shade");
2763 js_pushstring(J, name);
2764 ffi_pushshade(J, shade);
2765 PROC_END(2);
2766 }
2767
2768 static void js_proc_sc_shade(fz_context *ctx, pdf_processor *proc, const char *name, fz_shade *shade)
2769 {
2770 PROC_BEGIN("op_sc_shade");
2771 js_pushstring(J, name);
2772 ffi_pushshade(J, shade);
2773 PROC_END(2);
2774 }
2775
2776 static void js_proc_SC_color(fz_context *ctx, pdf_processor *proc, int n, float *color)
2777 {
2778 int i;
2779 PROC_BEGIN("op_SC_color");
2780 js_newarray(J);
2781 for (i = 0; i < n; ++i)
2782 {
2783 js_pushnumber(J, color[i]);
2784 js_setindex(J, -2, i);
2785 }
2786 PROC_END(1);
2787 }
2788
2789 static void js_proc_sc_color(fz_context *ctx, pdf_processor *proc, int n, float *color)
2790 {
2791 int i;
2792 PROC_BEGIN("op_sc_color");
2793 js_newarray(J);
2794 for (i = 0; i < n; ++i)
2795 {
2796 js_pushnumber(J, color[i]);
2797 js_setindex(J, -2, i);
2798 }
2799 PROC_END(1);
2800 }
2801
2802 static void js_proc_G(fz_context *ctx, pdf_processor *proc, float g)
2803 {
2804 PROC_BEGIN("op_G");
2805 js_pushnumber(J, g);
2806 PROC_END(1);
2807 }
2808
2809 static void js_proc_g(fz_context *ctx, pdf_processor *proc, float g)
2810 {
2811 PROC_BEGIN("op_g");
2812 js_pushnumber(J, g);
2813 PROC_END(1);
2814 }
2815
2816 static void js_proc_RG(fz_context *ctx, pdf_processor *proc, float r, float g, float b)
2817 {
2818 PROC_BEGIN("op_RG");
2819 js_pushnumber(J, r);
2820 js_pushnumber(J, g);
2821 js_pushnumber(J, b);
2822 PROC_END(3);
2823 }
2824
2825 static void js_proc_rg(fz_context *ctx, pdf_processor *proc, float r, float g, float b)
2826 {
2827 PROC_BEGIN("op_rg");
2828 js_pushnumber(J, r);
2829 js_pushnumber(J, g);
2830 js_pushnumber(J, b);
2831 PROC_END(3);
2832 }
2833
2834 static void js_proc_K(fz_context *ctx, pdf_processor *proc, float c, float m, float y, float k)
2835 {
2836 PROC_BEGIN("op_K");
2837 js_pushnumber(J, c);
2838 js_pushnumber(J, m);
2839 js_pushnumber(J, y);
2840 js_pushnumber(J, k);
2841 PROC_END(4);
2842 }
2843
2844 static void js_proc_k(fz_context *ctx, pdf_processor *proc, float c, float m, float y, float k)
2845 {
2846 PROC_BEGIN("op_k");
2847 js_pushnumber(J, c);
2848 js_pushnumber(J, m);
2849 js_pushnumber(J, y);
2850 js_pushnumber(J, k);
2851 PROC_END(4);
2852 }
2853
2854 static void js_proc_BI(fz_context *ctx, pdf_processor *proc, fz_image *img, const char *colorspace)
2855 {
2856 PROC_BEGIN("op_BI");
2857 ffi_pushimage(J, img);
2858 js_pushstring(J, colorspace);
2859 PROC_END(2);
2860 }
2861
2862 static void js_proc_sh(fz_context *ctx, pdf_processor *proc, const char *name, fz_shade *shade)
2863 {
2864 PROC_BEGIN("op_sh");
2865 js_pushstring(J, name);
2866 ffi_pushshade(J, shade);
2867 PROC_END(2);
2868 }
2869
2870 static void js_proc_Do_image(fz_context *ctx, pdf_processor *proc, const char *name, fz_image *image)
2871 {
2872 PROC_BEGIN("op_Do_image");
2873 js_pushstring(J, name);
2874 ffi_pushimage(J, image);
2875 PROC_END(2);
2876 }
2877
2878 static void js_proc_Do_form(fz_context *ctx, pdf_processor *proc, const char *name, pdf_obj *xobj)
2879 {
2880 PROC_BEGIN("op_Do_form");
2881 js_pushstring(J, name);
2882 ffi_pushobj(J, pdf_keep_obj(ctx, xobj));
2883 ffi_pushobj(J, pdf_keep_obj(ctx, ((pdf_js_processor*)proc)->rstack->resources));
2884 PROC_END(3);
2885 }
2886
2887 static void js_proc_MP(fz_context *ctx, pdf_processor *proc, const char *tag)
2888 {
2889 PROC_BEGIN("op_MP");
2890 js_pushstring(J, tag);
2891 PROC_END(1);
2892 }
2893
2894 static void js_proc_DP(fz_context *ctx, pdf_processor *proc, const char *tag, pdf_obj *raw, pdf_obj *cooked)
2895 {
2896 PROC_BEGIN("op_DP");
2897 js_pushstring(J, tag);
2898 ffi_pushobj(J, pdf_keep_obj(ctx, raw));
2899 PROC_END(2);
2900 }
2901
2902 static void js_proc_BMC(fz_context *ctx, pdf_processor *proc, const char *tag)
2903 {
2904 PROC_BEGIN("op_BMC");
2905 js_pushstring(J, tag);
2906 PROC_END(1);
2907 }
2908
2909 static void js_proc_BDC(fz_context *ctx, pdf_processor *proc, const char *tag, pdf_obj *raw, pdf_obj *cooked)
2910 {
2911 PROC_BEGIN("op_BDC");
2912 js_pushstring(J, tag);
2913 ffi_pushobj(J, pdf_keep_obj(ctx, raw));
2914 PROC_END(2);
2915 }
2916
2917 static void js_proc_EMC(fz_context *ctx, pdf_processor *proc)
2918 {
2919 PROC_BEGIN("op_EMC");
2920 PROC_END(0);
2921 }
2922
2923 static void js_proc_BX(fz_context *ctx, pdf_processor *proc)
2924 {
2925 PROC_BEGIN("op_BX");
2926 PROC_END(0);
2927 }
2928
2929 static void js_proc_EX(fz_context *ctx, pdf_processor *proc)
2930 {
2931 PROC_BEGIN("op_EX");
2932 PROC_END(0);
2933 }
2934
2935 static void js_proc_push_resources(fz_context *ctx, pdf_processor *proc, pdf_obj *res)
2936 {
2937 PROC_BEGIN("push_resources");
2938 ffi_pushobj(J, pdf_keep_obj(ctx, res));
2939 PROC_END(1);
2940 }
2941
2942 static pdf_obj *js_proc_pop_resources(fz_context *ctx, pdf_processor *proc)
2943 {
2944 PROC_BEGIN("pop_resources");
2945 PROC_END(0);
2946 return NULL;
2947 }
2948
2949 static void js_proc_drop(fz_context *ctx, pdf_processor *proc)
2950 {
2951 pdf_js_processor *pr = (pdf_js_processor *)proc;
2952
2953 while (pr->rstack)
2954 {
2955 resources_stack *stk = pr->rstack;
2956 pr->rstack = stk->next;
2957 pdf_drop_obj(ctx, stk->resources);
2958 fz_free(ctx, stk);
2959 }
2960 }
2961
2962 static pdf_processor *new_js_processor(fz_context *ctx, js_State *J)
2963 {
2964 pdf_js_processor *proc = pdf_new_processor(ctx, sizeof *proc);
2965
2966 proc->super.close_processor = NULL;
2967 proc->super.drop_processor = js_proc_drop;
2968
2969 proc->super.push_resources = js_proc_push_resources;
2970 proc->super.pop_resources = js_proc_pop_resources;
2971
2972 /* general graphics state */
2973 proc->super.op_w = js_proc_w;
2974 proc->super.op_j = js_proc_j;
2975 proc->super.op_J = js_proc_J;
2976 proc->super.op_M = js_proc_M;
2977 proc->super.op_d = js_proc_d;
2978 proc->super.op_ri = js_proc_ri;
2979 proc->super.op_i = js_proc_i;
2980 proc->super.op_gs_begin = js_proc_gs_begin;
2981 proc->super.op_gs_end = js_proc_gs_end;
2982
2983 /* transparency graphics state */
2984 proc->super.op_gs_BM = NULL;
2985 proc->super.op_gs_CA = NULL;
2986 proc->super.op_gs_ca = NULL;
2987 proc->super.op_gs_SMask = NULL;
2988
2989 /* special graphics state */
2990 proc->super.op_q = js_proc_q;
2991 proc->super.op_Q = js_proc_Q;
2992 proc->super.op_cm = js_proc_cm;
2993
2994 /* path construction */
2995 proc->super.op_m = js_proc_m;
2996 proc->super.op_l = js_proc_l;
2997 proc->super.op_c = js_proc_c;
2998 proc->super.op_v = js_proc_v;
2999 proc->super.op_y = js_proc_y;
3000 proc->super.op_h = js_proc_h;
3001 proc->super.op_re = js_proc_re;
3002
3003 /* path painting */
3004 proc->super.op_S = js_proc_S;
3005 proc->super.op_s = js_proc_s;
3006 proc->super.op_F = js_proc_F;
3007 proc->super.op_f = js_proc_f;
3008 proc->super.op_fstar = js_proc_fstar;
3009 proc->super.op_B = js_proc_B;
3010 proc->super.op_Bstar = js_proc_Bstar;
3011 proc->super.op_b = js_proc_b;
3012 proc->super.op_bstar = js_proc_bstar;
3013 proc->super.op_n = js_proc_n;
3014
3015 /* clipping paths */
3016 proc->super.op_W = js_proc_W;
3017 proc->super.op_Wstar = js_proc_Wstar;
3018
3019 /* text objects */
3020 proc->super.op_BT = js_proc_BT;
3021 proc->super.op_ET = js_proc_ET;
3022
3023 /* text state */
3024 proc->super.op_Tc = js_proc_Tc;
3025 proc->super.op_Tw = js_proc_Tw;
3026 proc->super.op_Tz = js_proc_Tz;
3027 proc->super.op_TL = js_proc_TL;
3028 proc->super.op_Tf = js_proc_Tf;
3029 proc->super.op_Tr = js_proc_Tr;
3030 proc->super.op_Ts = js_proc_Ts;
3031
3032 /* text positioning */
3033 proc->super.op_Td = js_proc_Td;
3034 proc->super.op_TD = js_proc_TD;
3035 proc->super.op_Tm = js_proc_Tm;
3036 proc->super.op_Tstar = js_proc_Tstar;
3037
3038 /* text showing */
3039 proc->super.op_TJ = js_proc_TJ;
3040 proc->super.op_Tj = js_proc_Tj;
3041 proc->super.op_squote = js_proc_squote;
3042 proc->super.op_dquote = js_proc_dquote;
3043
3044 /* type 3 fonts */
3045 proc->super.op_d0 = js_proc_d0;
3046 proc->super.op_d1 = js_proc_d1;
3047
3048 /* color */
3049 proc->super.op_CS = js_proc_CS;
3050 proc->super.op_cs = js_proc_cs;
3051 proc->super.op_SC_color = js_proc_SC_color;
3052 proc->super.op_sc_color = js_proc_sc_color;
3053 proc->super.op_SC_pattern = js_proc_SC_pattern;
3054 proc->super.op_sc_pattern = js_proc_sc_pattern;
3055 proc->super.op_SC_shade = js_proc_SC_shade;
3056 proc->super.op_sc_shade = js_proc_sc_shade;
3057
3058 proc->super.op_G = js_proc_G;
3059 proc->super.op_g = js_proc_g;
3060 proc->super.op_RG = js_proc_RG;
3061 proc->super.op_rg = js_proc_rg;
3062 proc->super.op_K = js_proc_K;
3063 proc->super.op_k = js_proc_k;
3064
3065 /* shadings, images, xobjects */
3066 proc->super.op_BI = js_proc_BI;
3067 proc->super.op_sh = js_proc_sh;
3068 proc->super.op_Do_image = js_proc_Do_image;
3069 proc->super.op_Do_form = js_proc_Do_form;
3070
3071 /* marked content */
3072 proc->super.op_MP = js_proc_MP;
3073 proc->super.op_DP = js_proc_DP;
3074 proc->super.op_BMC = js_proc_BMC;
3075 proc->super.op_BDC = js_proc_BDC;
3076 proc->super.op_EMC = js_proc_EMC;
3077
3078 /* compatibility */
3079 proc->super.op_BX = js_proc_BX;
3080 proc->super.op_EX = js_proc_EX;
3081
3082 /* extgstate */
3083 proc->super.op_gs_OP = NULL;
3084 proc->super.op_gs_op = NULL;
3085 proc->super.op_gs_OPM = NULL;
3086 proc->super.op_gs_UseBlackPtComp = NULL;
3087
3088 proc->J = J;
3089
3090 return (pdf_processor*)proc;
3091 }
3092
3093 #endif /* FZ_ENABLE_PDF */
3094
3095 static void ffi_new_StrokeState(js_State *J)
3096 {
3097 fz_context *ctx = js_getcontext(J);
3098 fz_stroke_state *stroke = NULL;
3099
3100 if (js_hasproperty(J, 1, "dashPattern"))
3101 {
3102 int i, n = fz_maxi(0, js_getlength(J, -1));
3103 fz_try(ctx)
3104 stroke = fz_new_stroke_state_with_dash_len(ctx, n);
3105 fz_catch(ctx)
3106 rethrow(J);
3107 js_pop(J, 1);
3108
3109 if (js_try(J)) {
3110 fz_drop_stroke_state(ctx, stroke);
3111 js_throw(J);
3112 }
3113 for (i = 0; i < n; ++i) {
3114 js_getindex(J, -1, i);
3115 stroke->dash_list[i] = js_tonumber(J, -1);
3116 js_pop(J, 1);
3117 }
3118
3119 js_pop(J, 1);
3120 js_endtry(J);
3121 }
3122 else
3123 {
3124 fz_try(ctx)
3125 stroke = fz_new_stroke_state(ctx);
3126 fz_catch(ctx)
3127 rethrow(J);
3128 }
3129
3130 if (js_try(J)) {
3131 fz_drop_stroke_state(ctx, stroke);
3132 js_throw(J);
3133 }
3134
3135 if (js_hasproperty(J, 1, "lineCap"))
3136 {
3137 int linecap = fz_linecap_from_string(js_tostring(J, -1));
3138 stroke->start_cap = stroke->dash_cap = stroke->end_cap = linecap;
3139 js_pop(J, 1);
3140 }
3141
3142 if (js_hasproperty(J, 1, "lineJoin"))
3143 {
3144 stroke->linejoin = fz_linejoin_from_string(js_tostring(J, -1));
3145 js_pop(J, 1);
3146 }
3147
3148 if (js_hasproperty(J, 1, "lineWidth"))
3149 {
3150 stroke->linewidth = js_tonumber(J, -1);
3151 js_pop(J, 1);
3152 }
3153
3154 if (js_hasproperty(J, 1, "miterLimit"))
3155 {
3156 stroke->miterlimit = js_tonumber(J, -1);
3157 js_pop(J, 1);
3158 }
3159
3160 if (js_hasproperty(J, 1, "dashPhase"))
3161 {
3162 stroke->dash_phase = js_tonumber(J, -1);
3163 js_pop(J, 1);
3164 }
3165
3166 js_getregistry(J, "fz_stroke_state");
3167 js_newuserdata(J, "fz_stroke_state", stroke, ffi_gc_fz_stroke_state);
3168
3169 js_endtry(J);
3170 }
3171
3172 static void ffi_StrokeState_getLineCap(js_State *J)
3173 {
3174 fz_stroke_state *stroke = js_touserdata(J, 0, "fz_stroke_state");
3175 js_pushliteral(J, fz_string_from_linecap(stroke->start_cap));
3176 }
3177
3178 static void ffi_StrokeState_getLineJoin(js_State *J)
3179 {
3180 fz_stroke_state *stroke = js_touserdata(J, 0, "fz_stroke_state");
3181 js_pushliteral(J, fz_string_from_linejoin(stroke->linejoin));
3182 }
3183
3184 static void ffi_StrokeState_getLineWidth(js_State *J)
3185 {
3186 fz_stroke_state *stroke = js_touserdata(J, 0, "fz_stroke_state");
3187 js_pushnumber(J, stroke->linewidth);
3188 }
3189
3190 static void ffi_StrokeState_getMiterLimit(js_State *J)
3191 {
3192 fz_stroke_state *stroke = js_touserdata(J, 0, "fz_stroke_state");
3193 js_pushnumber(J, stroke->miterlimit);
3194 }
3195
3196 static void ffi_StrokeState_getDashPhase(js_State *J)
3197 {
3198 fz_stroke_state *stroke = js_touserdata(J, 0, "fz_stroke_state");
3199 js_pushnumber(J, stroke->dash_phase);
3200 }
3201
3202 static void ffi_StrokeState_getDashPattern(js_State *J)
3203 {
3204 fz_stroke_state *stroke = js_touserdata(J, 0, "fz_stroke_state");
3205 if (stroke->dash_len > 0)
3206 ffi_pusharray(J, stroke->dash_list, stroke->dash_len);
3207 else
3208 js_pushnull(J);
3209 }
3210
3211 /* device calling into c from js */
3212
3213 static void ffi_Device_close(js_State *J)
3214 {
3215 fz_context *ctx = js_getcontext(J);
3216 fz_device *dev = js_touserdata(J, 0, "fz_device");
3217 fz_try(ctx)
3218 fz_close_device(ctx, dev);
3219 fz_catch(ctx)
3220 rethrow(J);
3221 }
3222
3223 static void ffi_Device_fillPath(js_State *J)
3224 {
3225 fz_context *ctx = js_getcontext(J);
3226 fz_device *dev = js_touserdata(J, 0, "fz_device");
3227 fz_path *path = js_touserdata(J, 1, "fz_path");
3228 int even_odd = js_toboolean(J, 2);
3229 fz_matrix ctm = ffi_tomatrix(J, 3);
3230 struct color c = ffi_tocolor(J, 4);
3231 fz_color_params color_params = ffi_tocolorparams(J, 7);
3232 fz_try(ctx)
3233 fz_fill_path(ctx, dev, path, even_odd, ctm, c.colorspace, c.color, c.alpha, color_params);
3234 fz_catch(ctx)
3235 rethrow(J);
3236 }
3237
3238 static void ffi_Device_strokePath(js_State *J)
3239 {
3240 fz_context *ctx = js_getcontext(J);
3241 fz_device *dev = js_touserdata(J, 0, "fz_device");
3242 fz_path *path = js_touserdata(J, 1, "fz_path");
3243 fz_stroke_state *stroke = ffi_tostroke(J, 2);
3244 fz_matrix ctm = ffi_tomatrix(J, 3);
3245 struct color c = ffi_tocolor(J, 4);
3246 fz_color_params color_params = ffi_tocolorparams(J, 7);
3247 fz_try(ctx)
3248 fz_stroke_path(ctx, dev, path, stroke, ctm, c.colorspace, c.color, c.alpha, color_params);
3249 fz_catch(ctx)
3250 rethrow(J);
3251 }
3252
3253 static void ffi_Device_clipPath(js_State *J)
3254 {
3255 fz_context *ctx = js_getcontext(J);
3256 fz_device *dev = js_touserdata(J, 0, "fz_device");
3257 fz_path *path = js_touserdata(J, 1, "fz_path");
3258 int even_odd = js_toboolean(J, 2);
3259 fz_matrix ctm = ffi_tomatrix(J, 3);
3260 fz_try(ctx)
3261 fz_clip_path(ctx, dev, path, even_odd, ctm, fz_infinite_rect);
3262 fz_catch(ctx)
3263 rethrow(J);
3264 }
3265
3266 static void ffi_Device_clipStrokePath(js_State *J)
3267 {
3268 fz_context *ctx = js_getcontext(J);
3269 fz_device *dev = js_touserdata(J, 0, "fz_device");
3270 fz_path *path = js_touserdata(J, 1, "fz_path");
3271 fz_stroke_state *stroke = ffi_tostroke(J, 2);
3272 fz_matrix ctm = ffi_tomatrix(J, 3);
3273 fz_try(ctx)
3274 fz_clip_stroke_path(ctx, dev, path, stroke, ctm, fz_infinite_rect);
3275 fz_catch(ctx)
3276 rethrow(J);
3277 }
3278
3279 static void ffi_Device_fillText(js_State *J)
3280 {
3281 fz_context *ctx = js_getcontext(J);
3282 fz_device *dev = js_touserdata(J, 0, "fz_device");
3283 fz_text *text = js_touserdata(J, 1, "fz_text");
3284 fz_matrix ctm = ffi_tomatrix(J, 2);
3285 struct color c = ffi_tocolor(J, 3);
3286 fz_color_params color_params = ffi_tocolorparams(J, 6);
3287 fz_try(ctx)
3288 fz_fill_text(ctx, dev, text, ctm, c.colorspace, c.color, c.alpha, color_params);
3289 fz_catch(ctx)
3290 rethrow(J);
3291 }
3292
3293 static void ffi_Device_strokeText(js_State *J)
3294 {
3295 fz_context *ctx = js_getcontext(J);
3296 fz_device *dev = js_touserdata(J, 0, "fz_device");
3297 fz_text *text = js_touserdata(J, 1, "fz_text");
3298 fz_stroke_state *stroke = ffi_tostroke(J, 2);
3299 fz_matrix ctm = ffi_tomatrix(J, 3);
3300 struct color c = ffi_tocolor(J, 4);
3301 fz_color_params color_params = ffi_tocolorparams(J, 7);
3302 fz_try(ctx)
3303 fz_stroke_text(ctx, dev, text, stroke, ctm, c.colorspace, c.color, c.alpha, color_params);
3304 fz_catch(ctx)
3305 rethrow(J);
3306 }
3307
3308 static void ffi_Device_clipText(js_State *J)
3309 {
3310 fz_context *ctx = js_getcontext(J);
3311 fz_device *dev = js_touserdata(J, 0, "fz_device");
3312 fz_text *text = js_touserdata(J, 1, "fz_text");
3313 fz_matrix ctm = ffi_tomatrix(J, 2);
3314 fz_try(ctx)
3315 fz_clip_text(ctx, dev, text, ctm, fz_infinite_rect);
3316 fz_catch(ctx)
3317 rethrow(J);
3318 }
3319
3320 static void ffi_Device_clipStrokeText(js_State *J)
3321 {
3322 fz_context *ctx = js_getcontext(J);
3323 fz_device *dev = js_touserdata(J, 0, "fz_device");
3324 fz_text *text = js_touserdata(J, 1, "fz_text");
3325 fz_stroke_state *stroke = ffi_tostroke(J, 2);
3326 fz_matrix ctm = ffi_tomatrix(J, 3);
3327 fz_try(ctx)
3328 fz_clip_stroke_text(ctx, dev, text, stroke, ctm, fz_infinite_rect);
3329 fz_catch(ctx)
3330 rethrow(J);
3331 }
3332
3333 static void ffi_Device_ignoreText(js_State *J)
3334 {
3335 fz_context *ctx = js_getcontext(J);
3336 fz_device *dev = js_touserdata(J, 0, "fz_device");
3337 fz_text *text = js_touserdata(J, 1, "fz_text");
3338 fz_matrix ctm = ffi_tomatrix(J, 2);
3339 fz_try(ctx)
3340 fz_ignore_text(ctx, dev, text, ctm);
3341 fz_catch(ctx)
3342 rethrow(J);
3343 }
3344
3345 static void ffi_Device_fillShade(js_State *J)
3346 {
3347 fz_context *ctx = js_getcontext(J);
3348 fz_device *dev = js_touserdata(J, 0, "fz_device");
3349 fz_shade *shade = js_touserdata(J, 1, "fz_shade");
3350 fz_matrix ctm = ffi_tomatrix(J, 2);
3351 float alpha = js_tonumber(J, 3);
3352 fz_color_params color_params = ffi_tocolorparams(J, 4);
3353 fz_try(ctx)
3354 fz_fill_shade(ctx, dev, shade, ctm, alpha, color_params);
3355 fz_catch(ctx)
3356 rethrow(J);
3357 }
3358
3359 static void ffi_Device_fillImage(js_State *J)
3360 {
3361 fz_context *ctx = js_getcontext(J);
3362 fz_device *dev = js_touserdata(J, 0, "fz_device");
3363 fz_image *image = js_touserdata(J, 1, "fz_image");
3364 fz_matrix ctm = ffi_tomatrix(J, 2);
3365 float alpha = js_tonumber(J, 3);
3366 fz_color_params color_params = ffi_tocolorparams(J, 4);
3367 fz_try(ctx)
3368 fz_fill_image(ctx, dev, image, ctm, alpha, color_params);
3369 fz_catch(ctx)
3370 rethrow(J);
3371 }
3372
3373 static void ffi_Device_fillImageMask(js_State *J)
3374 {
3375 fz_context *ctx = js_getcontext(J);
3376 fz_device *dev = js_touserdata(J, 0, "fz_device");
3377 fz_image *image = js_touserdata(J, 1, "fz_image");
3378 fz_matrix ctm = ffi_tomatrix(J, 2);
3379 struct color c = ffi_tocolor(J, 3);
3380 fz_color_params color_params = ffi_tocolorparams(J, 6);
3381 fz_try(ctx)
3382 fz_fill_image_mask(ctx, dev, image, ctm, c.colorspace, c.color, c.alpha, color_params);
3383 fz_catch(ctx)
3384 rethrow(J);
3385 }
3386
3387 static void ffi_Device_clipImageMask(js_State *J)
3388 {
3389 fz_context *ctx = js_getcontext(J);
3390 fz_device *dev = js_touserdata(J, 0, "fz_device");
3391 fz_image *image = js_touserdata(J, 1, "fz_image");
3392 fz_matrix ctm = ffi_tomatrix(J, 2);
3393 fz_try(ctx)
3394 fz_clip_image_mask(ctx, dev, image, ctm, fz_infinite_rect);
3395 fz_catch(ctx)
3396 rethrow(J);
3397 }
3398
3399 static void ffi_Device_popClip(js_State *J)
3400 {
3401 fz_context *ctx = js_getcontext(J);
3402 fz_device *dev = js_touserdata(J, 0, "fz_device");
3403 fz_try(ctx)
3404 fz_pop_clip(ctx, dev);
3405 fz_catch(ctx)
3406 rethrow(J);
3407 }
3408
3409 static void ffi_Device_beginMask(js_State *J)
3410 {
3411 fz_context *ctx = js_getcontext(J);
3412 fz_device *dev = js_touserdata(J, 0, "fz_device");
3413 fz_rect area = ffi_torect(J, 1);
3414 int luminosity = js_toboolean(J, 2);
3415 fz_color_params color_params = ffi_tocolorparams(J, 5);
3416 struct color c = { 0 };
3417 int n, i;
3418
3419 c.colorspace = js_touserdata(J, 3, "fz_colorspace");
3420 if (c.colorspace)
3421 {
3422 n = fz_colorspace_n(ctx, c.colorspace);
3423 for (i = 0; i < n; ++i)
3424 {
3425 js_getindex(J, 4, i);
3426 c.color[i] = js_tonumber(J, -1);
3427 js_pop(J, 1);
3428 }
3429 }
3430
3431 fz_try(ctx)
3432 fz_begin_mask(ctx, dev, area, luminosity, c.colorspace, c.color, color_params);
3433 fz_catch(ctx)
3434 rethrow(J);
3435 }
3436
3437 static void ffi_Device_endMask(js_State *J)
3438 {
3439 fz_context *ctx = js_getcontext(J);
3440 fz_device *dev = js_touserdata(J, 0, "fz_device");
3441 fz_try(ctx)
3442 fz_end_mask(ctx, dev);
3443 fz_catch(ctx)
3444 rethrow(J);
3445 }
3446
3447 static void ffi_Device_beginGroup(js_State *J)
3448 {
3449 fz_context *ctx = js_getcontext(J);
3450 fz_device *dev = js_touserdata(J, 0, "fz_device");
3451 fz_rect area = ffi_torect(J, 1);
3452 fz_colorspace *cs = js_touserdata(J, 2, "fz_colorspace");
3453 int isolated = js_toboolean(J, 3);
3454 int knockout = js_toboolean(J, 4);
3455 int blendmode = fz_lookup_blendmode(js_tostring(J, 5));
3456 float alpha = js_tonumber(J, 6);
3457 fz_try(ctx)
3458 fz_begin_group(ctx, dev, area, cs, isolated, knockout, blendmode, alpha);
3459 fz_catch(ctx)
3460 rethrow(J);
3461 }
3462
3463 static void ffi_Device_endGroup(js_State *J)
3464 {
3465 fz_context *ctx = js_getcontext(J);
3466 fz_device *dev = js_touserdata(J, 0, "fz_device");
3467 fz_try(ctx)
3468 fz_end_group(ctx, dev);
3469 fz_catch(ctx)
3470 rethrow(J);
3471 }
3472
3473 static void ffi_Device_beginTile(js_State *J)
3474 {
3475 fz_context *ctx = js_getcontext(J);
3476 fz_device *dev = js_touserdata(J, 0, "fz_device");
3477 fz_rect area = ffi_torect(J, 1);
3478 fz_rect view = ffi_torect(J, 2);
3479 float xstep = js_tonumber(J, 3);
3480 float ystep = js_tonumber(J, 4);
3481 fz_matrix ctm = ffi_tomatrix(J, 5);
3482 int id = js_tointeger(J, 6);
3483 int n = 0;
3484 fz_try(ctx)
3485 n = fz_begin_tile_id(ctx, dev, area, view, xstep, ystep, ctm, id);
3486 fz_catch(ctx)
3487 rethrow(J);
3488 js_pushnumber(J, n);
3489 }
3490
3491 static void ffi_Device_endTile(js_State *J)
3492 {
3493 fz_context *ctx = js_getcontext(J);
3494 fz_device *dev = js_touserdata(J, 0, "fz_device");
3495 fz_try(ctx)
3496 fz_end_tile(ctx, dev);
3497 fz_catch(ctx)
3498 rethrow(J);
3499 }
3500
3501 static void ffi_Device_beginLayer(js_State *J)
3502 {
3503 fz_context *ctx = js_getcontext(J);
3504 fz_device *dev = js_touserdata(J, 0, "fz_device");
3505 const char *name = js_tostring(J, 1);
3506 fz_try(ctx)
3507 fz_begin_layer(ctx, dev, name);
3508 fz_catch(ctx)
3509 rethrow(J);
3510 }
3511
3512 static void ffi_Device_endLayer(js_State *J)
3513 {
3514 fz_context *ctx = js_getcontext(J);
3515 fz_device *dev = js_touserdata(J, 0, "fz_device");
3516 fz_try(ctx)
3517 fz_end_layer(ctx, dev);
3518 fz_catch(ctx)
3519 rethrow(J);
3520 }
3521
3522 static void ffi_Device_renderFlags(js_State *J)
3523 {
3524 fz_context *ctx = js_getcontext(J);
3525 fz_device *dev = js_touserdata(J, 0, "fz_device");
3526 int set = ffi_torenderflags(J, 1);
3527 int clear = ffi_torenderflags(J, 2);
3528 fz_try(ctx)
3529 fz_render_flags(ctx, dev, set, clear);
3530 fz_catch(ctx)
3531 rethrow(J);
3532 }
3533
3534 static void ffi_Device_setDefaultColorSpaces(js_State *J)
3535 {
3536 fz_context *ctx = js_getcontext(J);
3537 fz_device *dev = js_touserdata(J, 0, "fz_device");
3538 fz_default_colorspaces *default_cs = ffi_todefaultcolorspaces(J, 1);
3539 fz_try(ctx)
3540 fz_set_default_colorspaces(ctx, dev, default_cs);
3541 fz_catch(ctx)
3542 rethrow(J);
3543 }
3544
3545 static void ffi_Device_beginStructure(js_State *J)
3546 {
3547 fz_context *ctx = js_getcontext(J);
3548 fz_device *dev = js_touserdata(J, 0, "fz_device");
3549 fz_structure str = fz_structure_from_string(js_tostring(J, 1));
3550 const char *raw = js_iscoercible(J, 2) ? js_tostring(J, 2) : NULL;
3551 int idx = js_tointeger(J, 3);
3552
3553 fz_try(ctx)
3554 fz_begin_structure(ctx, dev, str, raw, idx);
3555 fz_catch(ctx)
3556 rethrow(J);
3557 }
3558
3559 static void ffi_Device_endStructure(js_State *J)
3560 {
3561 fz_context *ctx = js_getcontext(J);
3562 fz_device *dev = js_touserdata(J, 0, "fz_device");
3563 fz_try(ctx)
3564 fz_end_structure(ctx, dev);
3565 fz_catch(ctx)
3566 rethrow(J);
3567 }
3568
3569 static void ffi_Device_beginMetatext(js_State *J)
3570 {
3571 fz_context *ctx = js_getcontext(J);
3572 fz_device *dev = js_touserdata(J, 0, "fz_device");
3573 fz_metatext meta = metatext_from_string(js_tostring(J, 1));
3574 const char *meta_text = js_iscoercible(J, 2) ? js_tostring(J, 2) : NULL;
3575
3576 fz_try(ctx)
3577 fz_begin_metatext(ctx, dev, meta, meta_text);
3578 fz_catch(ctx)
3579 rethrow(J);
3580 }
3581
3582 static void ffi_Device_endMetatext(js_State *J)
3583 {
3584 fz_context *ctx = js_getcontext(J);
3585 fz_device *dev = js_touserdata(J, 0, "fz_device");
3586 fz_try(ctx)
3587 fz_end_metatext(ctx, dev);
3588 fz_catch(ctx)
3589 rethrow(J);
3590 }
3591
3592 /* mupdf module */
3593
3594 static void ffi_enableICC(js_State *J)
3595 {
3596 fz_context *ctx = js_getcontext(J);
3597 fz_try(ctx)
3598 fz_enable_icc(ctx);
3599 fz_catch(ctx)
3600 rethrow(J);
3601 }
3602
3603 static void ffi_disableICC(js_State *J)
3604 {
3605 fz_context *ctx = js_getcontext(J);
3606 fz_try(ctx)
3607 fz_disable_icc(ctx);
3608 fz_catch(ctx)
3609 rethrow(J);
3610 }
3611
3612 static void ffi_readFile(js_State *J)
3613 {
3614 fz_context *ctx = js_getcontext(J);
3615 const char *filename = js_tostring(J, 1);
3616 fz_buffer *buf = NULL;
3617 fz_try(ctx)
3618 buf = fz_read_file(ctx, filename);
3619 fz_catch(ctx)
3620 rethrow(J);
3621 ffi_pushbuffer_own(J, buf);
3622 }
3623
3624 static void ffi_setUserCSS(js_State *J)
3625 {
3626 fz_context *ctx = js_getcontext(J);
3627 const char *user_css = js_tostring(J, 1);
3628 int use_doc_css = js_iscoercible(J, 2) ? js_toboolean(J, 2) : 1;
3629 fz_try(ctx) {
3630 fz_set_user_css(ctx, user_css);
3631 fz_set_use_document_css(ctx, use_doc_css);
3632 } fz_catch(ctx)
3633 rethrow(J);
3634 }
3635
3636 static void ffi_new_Archive(js_State *J)
3637 {
3638 fz_context *ctx = js_getcontext(J);
3639 const char *path = js_tostring(J, 1);
3640 fz_archive *arch = NULL;
3641 fz_try(ctx)
3642 if (fz_is_directory(ctx, path))
3643 arch = fz_open_directory(ctx, path);
3644 else
3645 arch = fz_open_archive(ctx, path);
3646 fz_catch(ctx)
3647 rethrow(J);
3648 ffi_pusharchive(J, arch);
3649 }
3650
3651 static void ffi_Archive_getFormat(js_State *J)
3652 {
3653 fz_context *ctx = js_getcontext(J);
3654 fz_archive *arch = ffi_toarchive(J, 0);
3655 const char *format = NULL;
3656 fz_try(ctx)
3657 format = fz_archive_format(ctx, arch);
3658 fz_catch(ctx)
3659 rethrow(J);
3660 js_pushstring(J, format);
3661 }
3662
3663 static void ffi_Archive_countEntries(js_State *J)
3664 {
3665 fz_context *ctx = js_getcontext(J);
3666 fz_archive *arch = ffi_toarchive(J, 0);
3667 int count = 0;
3668 fz_try(ctx)
3669 count = fz_count_archive_entries(ctx, arch);
3670 fz_catch(ctx)
3671 rethrow(J);
3672 js_pushnumber(J, count);
3673 }
3674
3675 static void ffi_Archive_listEntry(js_State *J)
3676 {
3677 fz_context *ctx = js_getcontext(J);
3678 fz_archive *arch = ffi_toarchive(J, 0);
3679 int idx = js_tointeger(J, 1);
3680 const char *name = NULL;
3681 fz_try(ctx)
3682 name = fz_list_archive_entry(ctx, arch, idx);
3683 fz_catch(ctx)
3684 rethrow(J);
3685 if (name)
3686 js_pushstring(J, name);
3687 else
3688 js_pushnull(J);
3689 }
3690
3691 static void ffi_Archive_hasEntry(js_State *J)
3692 {
3693 fz_context *ctx = js_getcontext(J);
3694 fz_archive *arch = ffi_toarchive(J, 0);
3695 const char *name = js_tostring(J, 1);
3696 int has = 0;
3697 fz_try(ctx)
3698 has = fz_has_archive_entry(ctx, arch, name);
3699 fz_catch(ctx)
3700 rethrow(J);
3701 js_pushboolean(J, has);
3702 }
3703
3704 static void ffi_Archive_readEntry(js_State *J)
3705 {
3706 fz_context *ctx = js_getcontext(J);
3707 fz_archive *arch = ffi_toarchive(J, 0);
3708 const char *name = js_tostring(J, 1);
3709 fz_buffer *buf = NULL;
3710 fz_try(ctx)
3711 buf = fz_read_archive_entry(ctx, arch, name);
3712 fz_catch(ctx)
3713 rethrow(J);
3714 ffi_pushbuffer_own(J, buf);
3715 }
3716
3717 static void ffi_new_MultiArchive(js_State *J)
3718 {
3719 fz_context *ctx = js_getcontext(J);
3720 fz_archive *arch = NULL;
3721 fz_try(ctx)
3722 arch = fz_new_multi_archive(ctx);
3723 fz_catch(ctx)
3724 rethrow(J);
3725 ffi_pushmultiarchive(J, arch);
3726 }
3727
3728 static void ffi_new_TreeArchive(js_State *J)
3729 {
3730 fz_context *ctx = js_getcontext(J);
3731 fz_archive *arch = NULL;
3732 fz_try(ctx)
3733 arch = fz_new_tree_archive(ctx, NULL);
3734 fz_catch(ctx)
3735 rethrow(J);
3736 ffi_pushtreearchive(J, arch);
3737 }
3738
3739 static void ffi_MultiArchive_mountArchive(js_State *J)
3740 {
3741 fz_context *ctx = js_getcontext(J);
3742 fz_archive *arch = js_touserdata(J, 0, "fz_multi_archive");
3743 fz_archive *sub = ffi_toarchive(J, 1);
3744 const char *path = js_iscoercible(J, 2) ? js_tostring(J, 2) : NULL;
3745 fz_try(ctx)
3746 fz_mount_multi_archive(ctx, arch, sub, path);
3747 fz_catch(ctx)
3748 rethrow(J);
3749 }
3750
3751 static void ffi_TreeArchive_add(js_State *J)
3752 {
3753 fz_context *ctx = js_getcontext(J);
3754 fz_archive *arch = js_touserdata(J, 0, "fz_tree_archive");
3755 const char *name = js_tostring(J, 1);
3756 fz_buffer *buf = ffi_tonewbuffer(J, 2);
3757 fz_try(ctx)
3758 fz_tree_archive_add_buffer(ctx, arch, name, buf);
3759 fz_always(ctx)
3760 fz_drop_buffer(ctx, buf);
3761 fz_catch(ctx)
3762 rethrow(J);
3763 }
3764
3765 static void ffi_new_Buffer(js_State *J)
3766 {
3767 fz_buffer *buf = ffi_tonewbuffer(J, 1);
3768 ffi_pushbuffer_own(J, buf);
3769 }
3770
3771 static void ffi_Buffer_readByte(js_State *J)
3772 {
3773 fz_context *ctx = js_getcontext(J);
3774 fz_buffer *buf = js_touserdata(J, 0, "fz_buffer");
3775 size_t index = js_tointeger(J, 1);
3776 unsigned char *p = NULL;
3777 size_t len;
3778 fz_try(ctx)
3779 len = fz_buffer_storage(ctx, buf, &p);
3780 fz_catch(ctx)
3781 rethrow(J);
3782
3783 if (index < len)
3784 js_pushnumber(J, p[index]);
3785 }
3786
3787 static void ffi_Buffer_getLength(js_State *J)
3788 {
3789 fz_context *ctx = js_getcontext(J);
3790 fz_buffer *buf = js_touserdata(J, 0, "fz_buffer");
3791 size_t len;
3792 fz_try(ctx)
3793 len = fz_buffer_storage(ctx, buf, NULL);
3794 fz_catch(ctx)
3795 rethrow(J);
3796
3797 js_pushnumber(J, len);
3798 }
3799
3800 static void ffi_Buffer_writeByte(js_State *J)
3801 {
3802 fz_context *ctx = js_getcontext(J);
3803 fz_buffer *buf = js_touserdata(J, 0, "fz_buffer");
3804 unsigned char val = js_tointeger(J, 1);
3805 fz_try(ctx)
3806 fz_append_byte(ctx, buf, val);
3807 fz_catch(ctx)
3808 rethrow(J);
3809 }
3810
3811 static void ffi_Buffer_writeRune(js_State *J)
3812 {
3813 fz_context *ctx = js_getcontext(J);
3814 fz_buffer *buf = js_touserdata(J, 0, "fz_buffer");
3815 int val = js_tointeger(J, 1);
3816 fz_try(ctx)
3817 fz_append_rune(ctx, buf, val);
3818 fz_catch(ctx)
3819 rethrow(J);
3820 }
3821
3822 static void ffi_Buffer_write(js_State *J)
3823 {
3824 fz_context *ctx = js_getcontext(J);
3825 fz_buffer *buf = js_touserdata(J, 0, "fz_buffer");
3826 const char *cat = js_tostring(J, 1);
3827 fz_try(ctx)
3828 fz_append_string(ctx, buf, cat);
3829 fz_catch(ctx)
3830 rethrow(J);
3831 }
3832
3833 static void ffi_Buffer_writeLine(js_State *J)
3834 {
3835 fz_context *ctx = js_getcontext(J);
3836 fz_buffer *buf = js_touserdata(J, 0, "fz_buffer");
3837 const char *cat = js_tostring(J, 1);
3838 fz_try(ctx)
3839 {
3840 fz_append_string(ctx, buf, cat);
3841 fz_append_byte(ctx, buf, '\n');
3842 }
3843 fz_catch(ctx)
3844 rethrow(J);
3845 }
3846
3847 static void ffi_Buffer_writeBuffer(js_State *J)
3848 {
3849 fz_context *ctx = js_getcontext(J);
3850 fz_buffer *buf = js_touserdata(J, 0, "fz_buffer");
3851 fz_buffer *cat = js_touserdata(J, 1, "fz_buffer");
3852 fz_try(ctx)
3853 fz_append_buffer(ctx, buf, cat);
3854 fz_catch(ctx)
3855 rethrow(J);
3856 }
3857
3858 static void ffi_Buffer_save(js_State *J)
3859 {
3860 fz_context *ctx = js_getcontext(J);
3861 fz_buffer *buf = js_touserdata(J, 0, "fz_buffer");
3862 const char *filename = js_tostring(J, 1);
3863 fz_try(ctx)
3864 fz_save_buffer(ctx, buf, filename);
3865 fz_catch(ctx)
3866 rethrow(J);
3867 }
3868
3869 static void ffi_Buffer_asString(js_State *J)
3870 {
3871 fz_context *ctx = js_getcontext(J);
3872 fz_buffer *buf = js_touserdata(J, 0, "fz_buffer");
3873 const char *str = NULL;
3874 fz_try(ctx)
3875 str = fz_string_from_buffer(ctx, buf);
3876 fz_catch(ctx)
3877 rethrow(J);
3878 js_pushstring(J, str);
3879 }
3880
3881 static void ffi_Buffer_slice(js_State *J)
3882 {
3883 fz_context *ctx = js_getcontext(J);
3884 fz_buffer *buf = js_touserdata(J, 0, "fz_buffer");
3885 size_t size = fz_buffer_storage(ctx, buf, NULL);
3886 int64_t start = js_tointeger(J, 1);
3887 int64_t end = js_iscoercible(J, 2) ? js_tointeger(J, 2) : (int64_t) size;
3888 fz_buffer *copy = NULL;
3889
3890 fz_try(ctx)
3891 copy = fz_slice_buffer(ctx, buf, start, end);
3892 fz_catch(ctx)
3893 rethrow(J);
3894
3895 ffi_pushbuffer_own(J, copy);
3896 }
3897
3898 static void ffi_Document_openDocument(js_State *J)
3899 {
3900 fz_context *ctx = js_getcontext(J);
3901 fz_document *doc = NULL;
3902
3903 if (js_isuserdata(J, 1, "fz_buffer"))
3904 {
3905 const char *magic = js_tostring(J, 2);
3906 fz_buffer *buf = ffi_tonewbuffer(J, 1);
3907 fz_stream *stm = NULL;
3908 fz_var(stm);
3909 fz_try(ctx)
3910 {
3911 stm = fz_open_buffer(ctx, buf);
3912 doc = fz_open_document_with_stream(ctx, magic, stm);
3913 }
3914 fz_always(ctx)
3915 {
3916 fz_drop_stream(ctx, stm);
3917 fz_drop_buffer(ctx, buf);
3918 }
3919 fz_catch(ctx)
3920 rethrow(J);
3921 }
3922 else
3923 {
3924 const char *filename = js_tostring(J, 1);
3925 fz_try(ctx)
3926 doc = fz_open_document(ctx, filename);
3927 fz_catch(ctx)
3928 rethrow(J);
3929 }
3930
3931 ffi_pushdocument(J, doc);
3932 }
3933
3934 static void ffi_Document_isPDF(js_State *J)
3935 {
3936 js_pushboolean(J, js_isuserdata(J, 0, "pdf_document"));
3937 }
3938
3939 static void ffi_Document_asPDF(js_State *J)
3940 {
3941 fz_context *ctx = js_getcontext(J);
3942 fz_document *doc = ffi_todocument(J, 0);
3943 pdf_document *pdf;
3944
3945 fz_try(ctx)
3946 pdf = fz_new_pdf_document_from_fz_document(ctx, doc);
3947 fz_catch(ctx)
3948 rethrow(J);
3949
3950 if (pdf != NULL)
3951 ffi_pushpdfdocument(J, pdf);
3952 else
3953 js_pushnull(J);
3954 }
3955
3956 static void ffi_Document_formatLinkURI(js_State *J)
3957 {
3958 fz_context *ctx = js_getcontext(J);
3959 fz_document *doc = ffi_todocument(J, 0);
3960 fz_link_dest dest = ffi_tolinkdest(J, 1);
3961 char *uri = NULL;
3962
3963 fz_try(ctx)
3964 uri = fz_format_link_uri(ctx, doc, dest);
3965 fz_catch(ctx)
3966 rethrow(J);
3967
3968 if (js_try(J)) {
3969 fz_free(ctx, uri);
3970 js_throw(J);
3971 }
3972 js_pushstring(J, uri);
3973 js_endtry(J);
3974 fz_free(ctx, uri);
3975 }
3976
3977 static void ffi_Document_countPages(js_State *J)
3978 {
3979 fz_context *ctx = js_getcontext(J);
3980 fz_document *doc = ffi_todocument(J, 0);
3981 int count = 0;
3982
3983 fz_try(ctx)
3984 count = fz_count_pages(ctx, doc);
3985 fz_catch(ctx)
3986 rethrow(J);
3987
3988 js_pushnumber(J, count);
3989 }
3990
3991 static void ffi_Document_loadPage(js_State *J)
3992 {
3993 fz_context *ctx = js_getcontext(J);
3994 fz_document *doc = ffi_todocument(J, 0);
3995 int number = js_tointeger(J, 1);
3996 fz_page *page = NULL;
3997
3998 fz_try(ctx)
3999 page = fz_load_page(ctx, doc, number);
4000 fz_catch(ctx)
4001 rethrow(J);
4002
4003 ffi_pushpage(J, page);
4004 }
4005
4006 static void ffi_Document_needsPassword(js_State *J)
4007 {
4008 fz_context *ctx = js_getcontext(J);
4009 fz_document *doc = ffi_todocument(J, 0);
4010 int b = 0;
4011
4012 fz_try(ctx)
4013 b = fz_needs_password(ctx, doc);
4014 fz_catch(ctx)
4015 rethrow(J);
4016
4017 js_pushboolean(J, b);
4018 }
4019
4020 static void ffi_Document_authenticatePassword(js_State *J)
4021 {
4022 fz_context *ctx = js_getcontext(J);
4023 fz_document *doc = ffi_todocument(J, 0);
4024 const char *password = js_tostring(J, 1);
4025 int b = 0;
4026
4027 fz_try(ctx)
4028 b = fz_authenticate_password(ctx, doc, password);
4029 fz_catch(ctx)
4030 rethrow(J);
4031
4032 js_pushnumber(J, b);
4033 }
4034
4035 static void ffi_Document_hasPermission(js_State *J)
4036 {
4037 fz_context *ctx = js_getcontext(J);
4038 fz_document *doc = ffi_todocument(J, 0);
4039 const char *perm = js_tostring(J, 1);
4040 int flag = 0;
4041 int result = 0;
4042
4043 if (!strcmp(perm, "print")) flag = FZ_PERMISSION_PRINT;
4044 else if (!strcmp(perm, "edit")) flag = FZ_PERMISSION_EDIT;
4045 else if (!strcmp(perm, "copy")) flag = FZ_PERMISSION_COPY;
4046 else if (!strcmp(perm, "annotate")) flag = FZ_PERMISSION_ANNOTATE;
4047 else if (!strcmp(perm, "form")) flag = FZ_PERMISSION_FORM;
4048 else if (!strcmp(perm, "accessibility")) flag = FZ_PERMISSION_ACCESSIBILITY;
4049 else if (!strcmp(perm, "assemble")) flag = FZ_PERMISSION_ASSEMBLE;
4050 else if (!strcmp(perm, "print-hq")) flag = FZ_PERMISSION_PRINT_HQ;
4051 else js_error(J, "invalid permission name");
4052
4053 fz_try(ctx)
4054 result = fz_has_permission(ctx, doc, flag);
4055 fz_catch(ctx)
4056 rethrow(J);
4057
4058 js_pushboolean(J, result);
4059 }
4060
4061 static void ffi_Document_getMetaData(js_State *J)
4062 {
4063 fz_context *ctx = js_getcontext(J);
4064 fz_document *doc = ffi_todocument(J, 0);
4065 const char *key = js_tostring(J, 1);
4066 char info[256];
4067 int found;
4068
4069 fz_try(ctx)
4070 found = fz_lookup_metadata(ctx, doc, key, info, sizeof info);
4071 fz_catch(ctx)
4072 rethrow(J);
4073
4074 if (found)
4075 js_pushstring(J, info);
4076 else
4077 js_pushnull(J);
4078 }
4079
4080 static void ffi_Document_setMetaData(js_State *J)
4081 {
4082 fz_context *ctx = js_getcontext(J);
4083 fz_document *doc = ffi_todocument(J, 0);
4084 const char *key = js_tostring(J, 1);
4085 const char *value = js_tostring(J, 2);
4086 fz_try(ctx)
4087 fz_set_metadata(ctx, doc, key, value);
4088 fz_catch(ctx)
4089 rethrow(J);
4090 }
4091
4092 static void ffi_Document_resolveLink(js_State *J)
4093 {
4094 fz_context *ctx = js_getcontext(J);
4095 fz_document *doc = ffi_todocument(J, 0);
4096 fz_location dest = fz_make_location(0, 0);
4097 const char *uri;
4098
4099 if (js_isuserdata(J, 1, "fz_link"))
4100 {
4101 fz_link *link = js_touserdata(J, 0, "fz_link");
4102 uri = link->uri;
4103 }
4104 else
4105 uri = js_tostring(J, 1);
4106
4107 fz_try(ctx)
4108 dest = fz_resolve_link(ctx, doc, uri, NULL, NULL);
4109 fz_catch(ctx)
4110 rethrow(J);
4111
4112 js_pushnumber(J, fz_page_number_from_location(ctx, doc, dest));
4113 }
4114
4115 static void ffi_Document_resolveLinkDestination(js_State *J)
4116 {
4117 fz_context *ctx = js_getcontext(J);
4118 fz_document *doc = ffi_todocument(J, 0);
4119 fz_link_dest dest = fz_make_link_dest_none();
4120 const char *uri;
4121
4122 if (js_isuserdata(J, 1, "fz_link"))
4123 {
4124 fz_link *link = js_touserdata(J, 0, "fz_link");
4125 uri = link->uri;
4126 }
4127 else
4128 uri = js_tostring(J, 1);
4129
4130 fz_try(ctx)
4131 dest = fz_resolve_link_dest(ctx, doc, uri);
4132 fz_catch(ctx)
4133 rethrow(J);
4134
4135 ffi_pushlinkdest(J, dest);
4136 }
4137
4138 static void ffi_Document_isReflowable(js_State *J)
4139 {
4140 fz_context *ctx = js_getcontext(J);
4141 fz_document *doc = ffi_todocument(J, 0);
4142 int is_reflowable = 0;
4143
4144 fz_try(ctx)
4145 is_reflowable = fz_is_document_reflowable(ctx, doc);
4146 fz_catch(ctx)
4147 rethrow(J);
4148
4149 js_pushboolean(J, is_reflowable);
4150 }
4151
4152 static void ffi_Document_layout(js_State *J)
4153 {
4154 fz_context *ctx = js_getcontext(J);
4155 fz_document *doc = ffi_todocument(J, 0);
4156 float w = js_tonumber(J, 1);
4157 float h = js_tonumber(J, 2);
4158 float em = js_tonumber(J, 3);
4159
4160 fz_try(ctx)
4161 fz_layout_document(ctx, doc, w, h, em);
4162 fz_catch(ctx)
4163 rethrow(J);
4164 }
4165
4166 static void to_outline(js_State *J, fz_outline *outline)
4167 {
4168 int i = 0;
4169 js_newarray(J);
4170 while (outline) {
4171 js_newobject(J);
4172
4173 if (outline->title) {
4174 js_pushstring(J, outline->title);
4175 js_setproperty(J, -2, "title");
4176 }
4177
4178 if (outline->uri) {
4179 js_pushstring(J, outline->uri);
4180 js_setproperty(J, -2, "uri");
4181 }
4182
4183 if (outline->down) {
4184 to_outline(J, outline->down);
4185 js_setproperty(J, -2, "down");
4186 }
4187
4188 js_setindex(J, -2, i++);
4189 outline = outline->next;
4190 }
4191 }
4192
4193 static void ffi_Document_loadOutline(js_State *J)
4194 {
4195 fz_context *ctx = js_getcontext(J);
4196 fz_document *doc = ffi_todocument(J, 0);
4197 fz_outline *outline = NULL;
4198
4199 fz_try(ctx)
4200 outline = fz_load_outline(ctx, doc);
4201 fz_catch(ctx)
4202 rethrow(J);
4203
4204 if (js_try(J)) {
4205 fz_drop_outline(ctx, outline);
4206 js_throw(J);
4207 }
4208
4209 to_outline(J, outline);
4210
4211 js_endtry(J);
4212 fz_drop_outline(ctx, outline);
4213 }
4214
4215 static void ffi_Document_outlineIterator(js_State *J)
4216 {
4217 fz_context *ctx = js_getcontext(J);
4218 fz_document *doc = ffi_todocument(J, 0);
4219 fz_outline_iterator *iter = NULL;
4220
4221 fz_try(ctx)
4222 iter = fz_new_outline_iterator(ctx, doc);
4223 fz_catch(ctx)
4224 rethrow(J);
4225
4226 ffi_pushoutlineiterator(J, iter);
4227 }
4228
4229 static void ffi_OutlineIterator_item(js_State *J)
4230 {
4231 fz_context *ctx = js_getcontext(J);
4232 fz_outline_iterator *iter = js_touserdata(J, 0, "fz_outline_iterator");
4233 fz_outline_item *item;
4234
4235 fz_try(ctx)
4236 item = fz_outline_iterator_item(ctx, iter);
4237 fz_catch(ctx)
4238 rethrow(J);
4239
4240 if (!item)
4241 {
4242 js_pushnull(J);
4243 return;
4244 }
4245
4246 js_newobject(J);
4247
4248 if (item->title)
4249 js_pushstring(J, item->title);
4250 else
4251 js_pushundefined(J);
4252 js_setproperty(J, -2, "title");
4253
4254 if (item->uri)
4255 js_pushstring(J, item->uri);
4256 else
4257 js_pushundefined(J);
4258 js_setproperty(J, -2, "uri");
4259
4260 js_pushboolean(J, item->is_open);
4261 js_setproperty(J, -2, "open");
4262
4263 js_pushnumber(J, item->r);
4264 js_setproperty(J, -2, "r");
4265
4266 js_pushnumber(J, item->g);
4267 js_setproperty(J, -2, "g");
4268
4269 js_pushnumber(J, item->b);
4270 js_setproperty(J, -2, "b");
4271
4272 js_pushnumber(J, item->flags);
4273 js_setproperty(J, -2, "flags");
4274 }
4275
4276 static void ffi_OutlineIterator_next(js_State *J)
4277 {
4278 fz_context *ctx = js_getcontext(J);
4279 fz_outline_iterator *iter = js_touserdata(J, 0, "fz_outline_iterator");
4280 int result;
4281
4282 fz_try(ctx)
4283 result = fz_outline_iterator_next(ctx, iter);
4284 fz_catch(ctx)
4285 rethrow(J);
4286
4287 js_pushnumber(J, result);
4288 }
4289
4290 static void ffi_OutlineIterator_prev(js_State *J)
4291 {
4292 fz_context *ctx = js_getcontext(J);
4293 fz_outline_iterator *iter = js_touserdata(J, 0, "fz_outline_iterator");
4294 int result;
4295
4296 fz_try(ctx)
4297 result = fz_outline_iterator_prev(ctx, iter);
4298 fz_catch(ctx)
4299 rethrow(J);
4300
4301 js_pushnumber(J, result);
4302 }
4303
4304 static void ffi_OutlineIterator_up(js_State *J)
4305 {
4306 fz_context *ctx = js_getcontext(J);
4307 fz_outline_iterator *iter = js_touserdata(J, 0, "fz_outline_iterator");
4308 int result;
4309
4310 fz_try(ctx)
4311 result = fz_outline_iterator_up(ctx, iter);
4312 fz_catch(ctx)
4313 rethrow(J);
4314
4315 js_pushnumber(J, result);
4316 }
4317
4318 static void ffi_OutlineIterator_down(js_State *J)
4319 {
4320 fz_context *ctx = js_getcontext(J);
4321 fz_outline_iterator *iter = js_touserdata(J, 0, "fz_outline_iterator");
4322 int result;
4323
4324 fz_try(ctx)
4325 result = fz_outline_iterator_down(ctx, iter);
4326 fz_catch(ctx)
4327 rethrow(J);
4328
4329 js_pushnumber(J, result);
4330 }
4331
4332 static void ffi_OutlineIterator_insert(js_State *J)
4333 {
4334 fz_context *ctx = js_getcontext(J);
4335 fz_outline_iterator *iter = js_touserdata(J, 0, "fz_outline_iterator");
4336 fz_outline_item item = ffi_tooutlineitem(J, 1);
4337 int result;
4338
4339 fz_try(ctx)
4340 result = fz_outline_iterator_insert(ctx, iter, &item);
4341 fz_always(ctx)
4342 {
4343 fz_free(ctx, item.title);
4344 fz_free(ctx, item.uri);
4345 }
4346 fz_catch(ctx)
4347 rethrow(J);
4348
4349 js_pushnumber(J, result);
4350 }
4351
4352 static void ffi_OutlineIterator_delete(js_State *J)
4353 {
4354 fz_context *ctx = js_getcontext(J);
4355 fz_outline_iterator *iter = js_touserdata(J, 0, "fz_outline_iterator");
4356 int result;
4357
4358 fz_try(ctx)
4359 result = fz_outline_iterator_delete(ctx, iter);
4360 fz_catch(ctx)
4361 rethrow(J);
4362
4363 js_pushnumber(J, result);
4364 }
4365
4366 static void ffi_OutlineIterator_update(js_State *J)
4367 {
4368 fz_context *ctx = js_getcontext(J);
4369 fz_outline_iterator *iter = js_touserdata(J, 0, "fz_outline_iterator");
4370 fz_outline_item item = ffi_tooutlineitem(J, 1);
4371
4372 fz_try(ctx)
4373 fz_outline_iterator_update(ctx, iter, &item);
4374 fz_always(ctx)
4375 {
4376 fz_free(ctx, item.title);
4377 fz_free(ctx, item.uri);
4378 }
4379 fz_catch(ctx)
4380 rethrow(J);
4381 }
4382
4383 static void ffi_Page_isPDF(js_State *J)
4384 {
4385 js_pushboolean(J, js_isuserdata(J, 0, "pdf_page"));
4386 }
4387
4388 static void ffi_Page_getBounds(js_State *J)
4389 {
4390 fz_context *ctx = js_getcontext(J);
4391 fz_page *page = ffi_topage(J, 0);
4392 fz_box_type box_type = FZ_CROP_BOX;
4393 fz_rect bounds;
4394
4395 if (js_iscoercible(J, 1))
4396 box_type = fz_box_type_from_string(js_tostring(J, 1));
4397
4398 fz_try(ctx)
4399 bounds = fz_bound_page_box(ctx, page, box_type);
4400 fz_catch(ctx)
4401 rethrow(J);
4402
4403 ffi_pushrect(J, bounds);
4404 }
4405
4406 static void ffi_Page_run_imp(js_State *J, void(*run)(fz_context *, fz_page *, fz_device *, fz_matrix, fz_cookie *))
4407 {
4408 fz_context *ctx = js_getcontext(J);
4409 fz_page *page = ffi_topage(J, 0);
4410 fz_device *device = NULL;
4411 fz_matrix ctm = ffi_tomatrix(J, 2);
4412
4413 if (js_isuserdata(J, 1, "fz_device")) {
4414 device = js_touserdata(J, 1, "fz_device");
4415 fz_try(ctx)
4416 run(ctx, page, device, ctm, NULL);
4417 fz_catch(ctx)
4418 rethrow(J);
4419 } else {
4420 device = new_js_device(ctx, J);
4421 js_copy(J, 1); /* put the js device on the top so the callbacks know where to get it */
4422 fz_try(ctx)
4423 run(ctx, page, device, ctm, NULL);
4424 fz_always(ctx)
4425 fz_drop_device(ctx, device);
4426 fz_catch(ctx)
4427 rethrow(J);
4428 }
4429 }
4430
4431 static void ffi_Page_run(js_State *J) {
4432 ffi_Page_run_imp(J, fz_run_page);
4433 }
4434
4435 static void ffi_Page_runPageContents(js_State *J) {
4436 ffi_Page_run_imp(J, fz_run_page_contents);
4437 }
4438
4439 static void ffi_Page_runPageAnnots(js_State *J) {
4440 ffi_Page_run_imp(J, fz_run_page_annots);
4441 }
4442
4443 static void ffi_Page_runPageWidgets(js_State *J) {
4444 ffi_Page_run_imp(J, fz_run_page_widgets);
4445 }
4446
4447 static void ffi_Page_toDisplayList(js_State *J)
4448 {
4449 fz_context *ctx = js_getcontext(J);
4450 fz_page *page = ffi_topage(J, 0);
4451 int extra = js_isdefined(J, 1) ? js_toboolean(J, 1) : 1;
4452 fz_display_list *list = NULL;
4453
4454 fz_try(ctx)
4455 if (extra)
4456 list = fz_new_display_list_from_page(ctx, page);
4457 else
4458 list = fz_new_display_list_from_page_contents(ctx, page);
4459 fz_catch(ctx)
4460 rethrow(J);
4461
4462 js_getregistry(J, "fz_display_list");
4463 js_newuserdata(J, "fz_display_list", list, ffi_gc_fz_display_list);
4464 }
4465
4466 static void ffi_Page_toPixmap(js_State *J)
4467 {
4468 fz_context *ctx = js_getcontext(J);
4469 fz_page *page = ffi_topage(J, 0);
4470 fz_matrix ctm = ffi_tomatrix(J, 1);
4471 fz_colorspace *colorspace = js_touserdata(J, 2, "fz_colorspace");
4472 int alpha = js_toboolean(J, 3);
4473 int extra = js_isdefined(J, 4) ? js_toboolean(J, 4) : 1;
4474 fz_pixmap *pixmap = NULL;
4475
4476 fz_try(ctx)
4477 if (extra)
4478 pixmap = fz_new_pixmap_from_page(ctx, page, ctm, colorspace, alpha);
4479 else
4480 pixmap = fz_new_pixmap_from_page_contents(ctx, page, ctm, colorspace, alpha);
4481 fz_catch(ctx)
4482 rethrow(J);
4483
4484 ffi_pushpixmap(J, pixmap);
4485 }
4486
4487 static void ffi_Page_toStructuredText(js_State *J)
4488 {
4489 fz_context *ctx = js_getcontext(J);
4490 fz_page *page = ffi_topage(J, 0);
4491 const char *options = js_iscoercible(J, 1) ? js_tostring(J, 1) : NULL;
4492 fz_stext_options so;
4493 fz_stext_page *text = NULL;
4494
4495 fz_try(ctx) {
4496 fz_parse_stext_options(ctx, &so, options);
4497 text = fz_new_stext_page_from_page(ctx, page, &so);
4498 }
4499 fz_catch(ctx)
4500 rethrow(J);
4501
4502 js_getregistry(J, "fz_stext_page");
4503 js_newuserdata(J, "fz_stext_page", text, ffi_gc_fz_stext_page);
4504 }
4505
4506 typedef struct {
4507 js_State *J;
4508 int max_hits;
4509 int hits;
4510 int error;
4511 } search_state;
4512
4513 static int hit_callback(fz_context *ctx, void *opaque, int quads, fz_quad *quad)
4514 {
4515 search_state *state = (search_state *) opaque;
4516 int i;
4517
4518 if (state->hits >= state->max_hits)
4519 return 1;
4520
4521 if (js_try(state->J))
4522 {
4523 state->error = 1;
4524 return 1;
4525 }
4526
4527 js_newarray(state->J);
4528 for (i = 0; i < quads; ++i)
4529 {
4530 ffi_pushquad(state->J, quad[i]);
4531 js_setindex(state->J, -2, i);
4532 }
4533 js_setindex(state->J, -2, state->hits++);
4534
4535 js_endtry(state->J);
4536 return 0;
4537 }
4538
4539 static void ffi_Page_search(js_State *J)
4540 {
4541 fz_context *ctx = js_getcontext(J);
4542 fz_page *page = ffi_topage(J, 0);
4543 const char *needle = js_tostring(J, 1);
4544 search_state state = { J, 0, 0, 0 };
4545
4546 state.max_hits = js_iscoercible(J, 2) ? js_tointeger(J, 2) : 500;
4547
4548 js_newarray(J);
4549
4550 fz_try(ctx)
4551 fz_search_page_cb(ctx, page, needle, hit_callback, &state);
4552 fz_catch(ctx)
4553 rethrow(J);
4554
4555 if (state.error)
4556 js_throw(J);
4557 }
4558
4559 static void ffi_Page_getLinks(js_State *J)
4560 {
4561 fz_context *ctx = js_getcontext(J);
4562 fz_page *page = ffi_topage(J, 0);
4563 fz_link *link, *links = NULL;
4564 int i = 0;
4565
4566 fz_try(ctx)
4567 links = fz_load_links(ctx, page);
4568 fz_catch(ctx)
4569 rethrow(J);
4570
4571 if (js_try(J)) {
4572 fz_drop_link(ctx, links);
4573 js_throw(J);
4574 }
4575
4576 js_newarray(J);
4577 for (link = links; link; link = link->next) {
4578 ffi_pushlink(J, fz_keep_link(ctx, link));
4579 js_setindex(J, -2, i++);
4580 }
4581
4582 js_endtry(J);
4583 fz_drop_link(ctx, links);
4584 }
4585
4586 static void ffi_Page_createLink(js_State *J)
4587 {
4588 fz_context *ctx = js_getcontext(J);
4589 fz_page *page = ffi_topage(J, 0);
4590 fz_link *link = NULL;
4591 fz_rect rect = ffi_torect(J, 1);
4592 const char *uri = js_iscoercible(J, 2) ? js_tostring(J, 2) : "";
4593
4594 fz_try(ctx)
4595 link = fz_create_link(ctx, page, rect, uri);
4596 fz_catch(ctx)
4597 rethrow(J);
4598
4599 ffi_pushlink(J, link);
4600 }
4601
4602 static void ffi_Page_deleteLink(js_State *J)
4603 {
4604 fz_context *ctx = js_getcontext(J);
4605 fz_page *page = ffi_topage(J, 0);
4606 fz_link *link = ffi_tolink(J, 1);
4607
4608 fz_try(ctx)
4609 fz_delete_link(ctx, page, link);
4610 fz_catch(ctx)
4611 rethrow(J);
4612 }
4613
4614 static void ffi_Page_getLabel(js_State *J)
4615 {
4616 fz_context *ctx = js_getcontext(J);
4617 fz_page *page = ffi_topage(J, 0);
4618 char buf[100];
4619
4620 fz_try(ctx)
4621 fz_page_label(ctx, page, buf, sizeof buf);
4622 fz_catch(ctx)
4623 rethrow(J);
4624
4625 js_pushstring(J, buf);
4626 }
4627
4628 static void ffi_Page_decodeBarcode(js_State *J)
4629 {
4630 fz_context *ctx = js_getcontext(J);
4631 fz_page *page = ffi_topage(J, 0);
4632 fz_rect subarea = js_iscoercible(J, 1) ? ffi_torect(J, 1) : fz_infinite_rect;
4633 float rotate = js_iscoercible(J, 2) ? js_tonumber(J, 2) : 0;
4634 char *text;
4635 fz_barcode_type type;
4636
4637 fz_try(ctx)
4638 text = fz_decode_barcode_from_page(ctx, &type, page, subarea, rotate);
4639 fz_catch(ctx)
4640 rethrow(J);
4641
4642 if (js_try(J))
4643 {
4644 fz_free(ctx, text);
4645 js_throw(J);
4646 }
4647
4648 js_newobject(J);
4649 js_pushliteral(J, fz_string_from_barcode_type(type));
4650 js_setproperty(J, -2, "type");
4651 js_pushstring(J, text);
4652 js_setproperty(J, -2, "contents");
4653 js_endtry(J);
4654 fz_free(ctx, text);
4655 }
4656
4657 static void ffi_Link_getBounds(js_State *J)
4658 {
4659 fz_link *link = js_touserdata(J, 0, "fz_link");
4660 ffi_pushrect(J, link->rect);
4661 }
4662
4663 static void ffi_Link_setBounds(js_State *J)
4664 {
4665 fz_context *ctx = js_getcontext(J);
4666 fz_link *link = js_touserdata(J, 0, "fz_link");
4667 fz_rect rect = ffi_torect(J, 1);
4668
4669 fz_try(ctx)
4670 fz_set_link_rect(ctx, link, rect);
4671 fz_catch(ctx)
4672 rethrow(J);
4673 }
4674
4675 static void ffi_Link_getURI(js_State *J)
4676 {
4677 fz_link *link = js_touserdata(J, 0, "fz_link");
4678 js_pushstring(J, link->uri);
4679 }
4680
4681 static void ffi_Link_setURI(js_State *J)
4682 {
4683 fz_context *ctx = js_getcontext(J);
4684 fz_link *link = js_touserdata(J, 0, "fz_link");
4685 const char *uri = js_tostring(J, 1);
4686
4687 fz_try(ctx)
4688 fz_set_link_uri(ctx, link, uri);
4689 fz_catch(ctx)
4690 rethrow(J);
4691 }
4692
4693 static void ffi_Link_isExternal(js_State *J)
4694 {
4695 fz_link *link = js_touserdata(J, 0, "fz_link");
4696 fz_context *ctx = js_getcontext(J);
4697 int external = 0;
4698
4699 fz_try(ctx)
4700 external = fz_is_external_link(ctx, link->uri);
4701 fz_catch(ctx)
4702 fz_rethrow(ctx);
4703
4704 js_pushboolean(J, external);
4705 }
4706
4707 static void ffi_new_ColorSpace(js_State *J)
4708 {
4709 fz_context *ctx = js_getcontext(J);
4710 const char *name = js_tostring(J, 2);
4711 fz_colorspace *cs = NULL;
4712 fz_buffer *buf = NULL;
4713
4714 fz_var(buf);
4715
4716 if (js_isuserdata(J, 1, "fz_buffer"))
4717 {
4718 buf = js_touserdata(J, 1, "fz_buffer");
4719 fz_try(ctx)
4720 cs = fz_new_icc_colorspace(ctx, FZ_COLORSPACE_NONE, 0, name, buf);
4721 fz_catch(ctx)
4722 rethrow(J);
4723 }
4724 else
4725 {
4726 fz_try(ctx)
4727 {
4728 buf = fz_read_file(ctx, js_tostring(J, 1));
4729 cs = fz_new_icc_colorspace(ctx, FZ_COLORSPACE_NONE, 0, name, buf);
4730 }
4731 fz_always(ctx)
4732 fz_drop_buffer(ctx, buf);
4733 fz_catch(ctx)
4734 rethrow(J);
4735 }
4736 ffi_pushcolorspace(J, cs);
4737 }
4738
4739 static void ffi_ColorSpace_getNumberOfComponents(js_State *J)
4740 {
4741 fz_colorspace *colorspace = js_touserdata(J, 0, "fz_colorspace");
4742 fz_context *ctx = js_getcontext(J);
4743 js_pushnumber(J, fz_colorspace_n(ctx, colorspace));
4744 }
4745
4746 static void ffi_ColorSpace_getName(js_State *J)
4747 {
4748 fz_colorspace *colorspace = js_touserdata(J, 0, "fz_colorspace");
4749 fz_context *ctx = js_getcontext(J);
4750 js_pushstring(J, fz_colorspace_name(ctx, colorspace));
4751 }
4752
4753 static void ffi_ColorSpace_getType(js_State *J)
4754 {
4755 fz_colorspace *colorspace = js_touserdata(J, 0, "fz_colorspace");
4756 fz_context *ctx = js_getcontext(J);
4757 int t = fz_colorspace_type(ctx, colorspace);
4758 switch (t)
4759 {
4760 default:
4761 case FZ_COLORSPACE_NONE: js_pushliteral(J, "None"); break;
4762 case FZ_COLORSPACE_GRAY: js_pushliteral(J, "Gray"); break;
4763 case FZ_COLORSPACE_RGB: js_pushliteral(J, "RGB"); break;
4764 case FZ_COLORSPACE_BGR: js_pushliteral(J, "BGR"); break;
4765 case FZ_COLORSPACE_CMYK: js_pushliteral(J, "CMYK"); break;
4766 case FZ_COLORSPACE_LAB: js_pushliteral(J, "Lab"); break;
4767 case FZ_COLORSPACE_INDEXED: js_pushliteral(J, "Indexed"); break;
4768 case FZ_COLORSPACE_SEPARATION: js_pushliteral(J, "Separation"); break;
4769 }
4770 }
4771
4772 static void ffi_ColorSpace_toString(js_State *J)
4773 {
4774 fz_colorspace *colorspace = js_touserdata(J, 0, "fz_colorspace");
4775 fz_context *ctx = js_getcontext(J);
4776 const char *name = fz_colorspace_name(ctx, colorspace);
4777 char *s = NULL;
4778
4779 fz_try(ctx)
4780 s = fz_asprintf(ctx, "[ColorSpace %s]", name);
4781 fz_catch(ctx)
4782 rethrow(J);
4783
4784 if (js_try(J))
4785 {
4786 fz_free(ctx, s);
4787 js_throw(J);
4788 }
4789
4790 js_pushstring(J, s);
4791 js_endtry(J);
4792 fz_free(ctx, s);
4793 }
4794
4795 static void ffi_ColorSpace_isGray(js_State *J)
4796 {
4797 fz_colorspace *colorspace = js_touserdata(J, 0, "fz_colorspace");
4798 fz_context *ctx = js_getcontext(J);
4799 js_pushboolean(J, fz_colorspace_is_gray(ctx, colorspace));
4800 }
4801
4802 static void ffi_ColorSpace_isRGB(js_State *J)
4803 {
4804 fz_colorspace *colorspace = js_touserdata(J, 0, "fz_colorspace");
4805 fz_context *ctx = js_getcontext(J);
4806 js_pushboolean(J, fz_colorspace_is_rgb(ctx, colorspace));
4807 }
4808
4809 static void ffi_ColorSpace_isCMYK(js_State *J)
4810 {
4811 fz_colorspace *colorspace = js_touserdata(J, 0, "fz_colorspace");
4812 fz_context *ctx = js_getcontext(J);
4813 js_pushboolean(J, fz_colorspace_is_cmyk(ctx, colorspace));
4814 }
4815
4816 static void ffi_ColorSpace_isIndexed(js_State *J)
4817 {
4818 fz_colorspace *colorspace = js_touserdata(J, 0, "fz_colorspace");
4819 fz_context *ctx = js_getcontext(J);
4820 js_pushboolean(J, fz_colorspace_is_indexed(ctx, colorspace));
4821 }
4822
4823 static void ffi_ColorSpace_isLab(js_State *J)
4824 {
4825 fz_colorspace *colorspace = js_touserdata(J, 0, "fz_colorspace");
4826 fz_context *ctx = js_getcontext(J);
4827 js_pushboolean(J, fz_colorspace_is_lab(ctx, colorspace));
4828 }
4829
4830 static void ffi_ColorSpace_isDeviceN(js_State *J)
4831 {
4832 fz_colorspace *colorspace = js_touserdata(J, 0, "fz_colorspace");
4833 fz_context *ctx = js_getcontext(J);
4834 js_pushboolean(J, fz_colorspace_is_device_n(ctx, colorspace));
4835 }
4836
4837 static void ffi_ColorSpace_isSubtractive(js_State *J)
4838 {
4839 fz_colorspace *colorspace = js_touserdata(J, 0, "fz_colorspace");
4840 fz_context *ctx = js_getcontext(J);
4841 js_pushboolean(J, fz_colorspace_is_subtractive(ctx, colorspace));
4842 }
4843
4844 static void ffi_DefaultColorSpaces_getDefaultGray(js_State *J)
4845 {
4846 fz_default_colorspaces *default_cs = ffi_todefaultcolorspaces(J, 0);
4847 ffi_pushcolorspace(J, default_cs->gray);
4848 }
4849
4850 static void ffi_DefaultColorSpaces_getDefaultRGB(js_State *J)
4851 {
4852 fz_default_colorspaces *default_cs = ffi_todefaultcolorspaces(J, 0);
4853 ffi_pushcolorspace(J, default_cs->rgb);
4854 }
4855
4856 static void ffi_DefaultColorSpaces_getDefaultCMYK(js_State *J)
4857 {
4858 fz_default_colorspaces *default_cs = ffi_todefaultcolorspaces(J, 0);
4859 ffi_pushcolorspace(J, default_cs->cmyk);
4860 }
4861
4862 static void ffi_DefaultColorSpaces_getOutputIntent(js_State *J)
4863 {
4864 fz_default_colorspaces *default_cs = ffi_todefaultcolorspaces(J, 0);
4865 ffi_pushcolorspace(J, default_cs->oi);
4866 }
4867
4868 static void ffi_DefaultColorSpaces_setDefaultGray(js_State *J)
4869 {
4870 fz_context *ctx = js_getcontext(J);
4871 fz_default_colorspaces *default_cs = ffi_todefaultcolorspaces(J, 0);
4872 fz_colorspace *cs = js_touserdata(J, 1, "fz_colorspace");
4873 fz_drop_colorspace(ctx, default_cs->gray);
4874 default_cs->gray = fz_keep_colorspace(ctx, cs);
4875 }
4876
4877 static void ffi_DefaultColorSpaces_setDefaultRGB(js_State *J)
4878 {
4879 fz_context *ctx = js_getcontext(J);
4880 fz_default_colorspaces *default_cs = ffi_todefaultcolorspaces(J, 0);
4881 fz_colorspace *cs = js_touserdata(J, 1, "fz_colorspace");
4882 fz_drop_colorspace(ctx, default_cs->rgb);
4883 default_cs->rgb = fz_keep_colorspace(ctx, cs);
4884 }
4885
4886 static void ffi_DefaultColorSpaces_setDefaultCMYK(js_State *J)
4887 {
4888 fz_context *ctx = js_getcontext(J);
4889 fz_default_colorspaces *default_cs = ffi_todefaultcolorspaces(J, 0);
4890 fz_colorspace *cs = js_touserdata(J, 1, "fz_colorspace");
4891 fz_drop_colorspace(ctx, default_cs->cmyk);
4892 default_cs->cmyk = fz_keep_colorspace(ctx, cs);
4893 }
4894
4895 static void ffi_DefaultColorSpaces_setOutputIntent(js_State *J)
4896 {
4897 fz_context *ctx = js_getcontext(J);
4898 fz_default_colorspaces *default_cs = ffi_todefaultcolorspaces(J, 0);
4899 fz_colorspace *cs = js_touserdata(J, 1, "fz_colorspace");
4900 fz_drop_colorspace(ctx, default_cs->oi);
4901 default_cs->oi = fz_keep_colorspace(ctx, cs);
4902 }
4903
4904 static void ffi_new_Pixmap(js_State *J)
4905 {
4906 fz_context *ctx = js_getcontext(J);
4907 fz_pixmap *pixmap = NULL;
4908
4909 if (js_isuserdata(J, 1, "fz_pixmap")) {
4910 fz_pixmap *pix = ffi_topixmap(J, 1);
4911 fz_pixmap *mask = ffi_topixmap(J, 2);
4912
4913 fz_try(ctx)
4914 pixmap = fz_new_pixmap_from_color_and_mask(ctx, pix, mask);
4915 fz_catch(ctx)
4916 rethrow(J);
4917 } else {
4918 fz_colorspace *colorspace = js_iscoercible(J, 1) ? js_touserdata(J, 1, "fz_colorspace") : NULL;
4919 fz_irect bounds = ffi_toirect(J, 2);
4920 int alpha = js_toboolean(J, 3);
4921
4922 fz_try(ctx)
4923 pixmap = fz_new_pixmap_with_bbox(ctx, colorspace, bounds, 0, alpha);
4924 fz_catch(ctx)
4925 rethrow(J);
4926 }
4927
4928 ffi_pushpixmap(J, pixmap);
4929 }
4930
4931 static void ffi_Pixmap_invert(js_State *J)
4932 {
4933 fz_context *ctx = js_getcontext(J);
4934 fz_pixmap *pixmap = ffi_topixmap(J, 0);
4935
4936 fz_try(ctx)
4937 fz_invert_pixmap(ctx, pixmap);
4938 fz_catch(ctx)
4939 rethrow(J);
4940 }
4941
4942 static void ffi_Pixmap_invertLuminance(js_State *J)
4943 {
4944 fz_context *ctx = js_getcontext(J);
4945 fz_pixmap *pixmap = ffi_topixmap(J, 0);
4946
4947 fz_try(ctx)
4948 fz_invert_pixmap_luminance(ctx, pixmap);
4949 fz_catch(ctx)
4950 rethrow(J);
4951 }
4952
4953 static void ffi_Pixmap_gamma(js_State *J)
4954 {
4955 fz_context *ctx = js_getcontext(J);
4956 fz_pixmap *pixmap = ffi_topixmap(J, 0);
4957 float gamma = js_tonumber(J, 1);
4958
4959 fz_try(ctx)
4960 fz_gamma_pixmap(ctx, pixmap, gamma);
4961 fz_catch(ctx)
4962 rethrow(J);
4963 }
4964
4965 static void ffi_Pixmap_tint(js_State *J)
4966 {
4967 fz_context *ctx = js_getcontext(J);
4968 fz_pixmap *pixmap = ffi_topixmap(J, 0);
4969 int black = js_tointeger(J, 1);
4970 int white = js_tointeger(J, 2);
4971
4972 fz_try(ctx)
4973 fz_tint_pixmap(ctx, pixmap, black, white);
4974 fz_catch(ctx)
4975 rethrow(J);
4976 }
4977
4978 static void ffi_Pixmap_warp(js_State *J)
4979 {
4980 fz_context *ctx = js_getcontext(J);
4981 fz_pixmap *pixmap = ffi_topixmap(J, 0);
4982 fz_quad points = ffi_toquad(J, 1);
4983 int w = js_tointeger(J, 2);
4984 int h = js_tointeger(J, 3);
4985 fz_pixmap *dest = NULL;
4986
4987 fz_try(ctx)
4988 dest = fz_warp_pixmap(ctx, pixmap, points, w, h);
4989 fz_catch(ctx)
4990 rethrow(J);
4991
4992 ffi_pushpixmap(J, dest);
4993 }
4994
4995 static void ffi_Pixmap_detectSkew(js_State *J)
4996 {
4997 fz_context *ctx = js_getcontext(J);
4998 fz_pixmap *pixmap = ffi_topixmap(J, 0);
4999 double angle;
5000
5001 fz_try(ctx)
5002 angle = fz_detect_skew(ctx, pixmap);
5003 fz_catch(ctx)
5004 rethrow(J);
5005
5006 js_pushnumber(J, angle);
5007 }
5008
5009 static int deskew_border_from_string(const char *str)
5010 {
5011 if (!strcmp(str, "increase")) return FZ_DESKEW_BORDER_INCREASE;
5012 if (!strcmp(str, "decrease")) return FZ_DESKEW_BORDER_DECREASE;
5013 if (!strcmp(str, "maintain")) return FZ_DESKEW_BORDER_MAINTAIN;
5014 return FZ_DESKEW_BORDER_INCREASE;
5015 }
5016
5017 static void ffi_Pixmap_deskew(js_State *J)
5018 {
5019 fz_context *ctx = js_getcontext(J);
5020 fz_pixmap *pixmap = ffi_topixmap(J, 0);
5021 float degrees = js_tonumber(J, 1);
5022 int border = deskew_border_from_string(js_tostring(J, 2));
5023 fz_pixmap *dest = NULL;
5024
5025 fz_try(ctx)
5026 dest = fz_deskew_pixmap(ctx, pixmap, degrees, border);
5027 fz_catch(ctx)
5028 rethrow(J);
5029
5030 ffi_pushpixmap(J, dest);
5031 }
5032
5033 static void ffi_Pixmap_asPNG(js_State *J)
5034 {
5035 fz_context *ctx = js_getcontext(J);
5036 fz_pixmap *pixmap = ffi_topixmap(J, 0);
5037 fz_buffer *buf = NULL;
5038
5039 fz_try(ctx)
5040 buf = fz_new_buffer_from_pixmap_as_png(ctx, pixmap, fz_default_color_params);
5041 fz_catch(ctx)
5042 rethrow(J);
5043
5044 ffi_pushbuffer_own(J, buf);
5045 }
5046
5047 static void ffi_Pixmap_asPSD(js_State *J)
5048 {
5049 fz_context *ctx = js_getcontext(J);
5050 fz_pixmap *pixmap = ffi_topixmap(J, 0);
5051 fz_buffer *buf = NULL;
5052
5053 fz_try(ctx)
5054 buf = fz_new_buffer_from_pixmap_as_psd(ctx, pixmap, fz_default_color_params);
5055 fz_catch(ctx)
5056 rethrow(J);
5057
5058 ffi_pushbuffer_own(J, buf);
5059 }
5060
5061 static void ffi_Pixmap_asPAM(js_State *J)
5062 {
5063 fz_context *ctx = js_getcontext(J);
5064 fz_pixmap *pixmap = ffi_topixmap(J, 0);
5065 fz_buffer *buf = NULL;
5066
5067 fz_try(ctx)
5068 buf = fz_new_buffer_from_pixmap_as_pam(ctx, pixmap, fz_default_color_params);
5069 fz_catch(ctx)
5070 rethrow(J);
5071
5072 ffi_pushbuffer_own(J, buf);
5073 }
5074
5075 static void ffi_Pixmap_asJPEG(js_State *J)
5076 {
5077 fz_context *ctx = js_getcontext(J);
5078 fz_pixmap *pixmap = ffi_topixmap(J, 0);
5079 int quality = js_isdefined(J, 1) ? js_tointeger(J, 1) : 90;
5080 int invert_cmyk = js_isdefined(J, 1) ? js_toboolean(J, 1) : 0;
5081 fz_buffer *buf = NULL;
5082
5083 fz_try(ctx)
5084 buf = fz_new_buffer_from_pixmap_as_jpeg(ctx, pixmap, fz_default_color_params, quality, invert_cmyk);
5085 fz_catch(ctx)
5086 rethrow(J);
5087
5088 ffi_pushbuffer_own(J, buf);
5089 }
5090
5091 static void ffi_Pixmap_autowarp(js_State *J)
5092 {
5093 fz_context *ctx = js_getcontext(J);
5094 fz_pixmap *pixmap = js_touserdata(J, 0, "fz_pixmap");
5095 fz_quad points = ffi_toquad(J, 1);
5096 fz_pixmap *dest = NULL;
5097
5098 fz_try(ctx)
5099 dest = fz_autowarp_pixmap(ctx, pixmap, points);
5100 fz_catch(ctx)
5101 rethrow(J);
5102
5103 ffi_pushpixmap(J, dest);
5104 }
5105
5106 static void ffi_Pixmap_detectDocument(js_State *J)
5107 {
5108 fz_context *ctx = js_getcontext(J);
5109 fz_pixmap *pixmap = js_touserdata(J, 0, "fz_pixmap");
5110 fz_quad points = { 0 };
5111 int found;
5112
5113 fz_try(ctx)
5114 found = fz_detect_document(ctx, &points, pixmap);
5115 fz_catch(ctx)
5116 rethrow(J);
5117
5118 if (found)
5119 ffi_pushquad(J, points);
5120 else
5121 js_pushnull(J);
5122 }
5123
5124 static void ffi_Pixmap_decodeBarcode(js_State *J)
5125 {
5126 fz_context *ctx = js_getcontext(J);
5127 fz_pixmap *pixmap = js_touserdata(J, 0, "fz_pixmap");
5128 float rotate = js_iscoercible(J, 1) ? js_tonumber(J, 1) : 0;
5129 char *text;
5130 fz_barcode_type type;
5131
5132 fz_try(ctx)
5133 text = fz_decode_barcode_from_pixmap(ctx, &type, pixmap, rotate);
5134 fz_catch(ctx)
5135 rethrow(J);
5136
5137 if (js_try(J))
5138 {
5139 fz_free(ctx, text);
5140 js_throw(J);
5141 }
5142
5143 js_newobject(J);
5144 js_pushliteral(J, fz_string_from_barcode_type(type));
5145 js_setproperty(J, -2, "type");
5146 js_pushstring(J, text);
5147 js_setproperty(J, -2, "contents");
5148 js_endtry(J);
5149 fz_free(ctx, text);
5150 }
5151
5152 static void ffi_Pixmap_saveAsPNG(js_State *J)
5153 {
5154 fz_context *ctx = js_getcontext(J);
5155 fz_pixmap *pixmap = ffi_topixmap(J, 0);
5156 const char *filename = js_tostring(J, 1);
5157
5158 fz_try(ctx)
5159 fz_save_pixmap_as_png(ctx, pixmap, filename);
5160 fz_catch(ctx)
5161 rethrow(J);
5162 }
5163
5164 static void ffi_Pixmap_saveAsJPEG(js_State *J)
5165 {
5166 fz_context *ctx = js_getcontext(J);
5167 fz_pixmap *pixmap = ffi_topixmap(J, 0);
5168 const char *filename = js_tostring(J, 1);
5169 int quality = js_isdefined(J, 2) ? js_tointeger(J, 2) : 90;
5170
5171 fz_try(ctx)
5172 fz_save_pixmap_as_jpeg(ctx, pixmap, filename, quality);
5173 fz_catch(ctx)
5174 rethrow(J);
5175 }
5176
5177 static void ffi_Pixmap_saveAsPAM(js_State *J)
5178 {
5179 fz_context *ctx = js_getcontext(J);
5180 fz_pixmap *pixmap = ffi_topixmap(J, 0);
5181 const char *filename = js_tostring(J, 1);
5182
5183 fz_try(ctx)
5184 fz_save_pixmap_as_pam(ctx, pixmap, filename);
5185 fz_catch(ctx)
5186 rethrow(J);
5187 }
5188
5189 static void ffi_Pixmap_saveAsPNM(js_State *J)
5190 {
5191 fz_context *ctx = js_getcontext(J);
5192 fz_pixmap *pixmap = ffi_topixmap(J, 0);
5193 const char *filename = js_tostring(J, 1);
5194
5195 fz_try(ctx)
5196 fz_save_pixmap_as_pnm(ctx, pixmap, filename);
5197 fz_catch(ctx)
5198 rethrow(J);
5199 }
5200
5201 static void ffi_Pixmap_saveAsPBM(js_State *J)
5202 {
5203 fz_context *ctx = js_getcontext(J);
5204 fz_pixmap *pixmap = ffi_topixmap(J, 0);
5205 const char *filename = js_tostring(J, 1);
5206
5207 fz_try(ctx)
5208 fz_save_pixmap_as_pbm(ctx, pixmap, filename);
5209 fz_catch(ctx)
5210 rethrow(J);
5211 }
5212
5213 static void ffi_Pixmap_saveAsPKM(js_State *J)
5214 {
5215 fz_context *ctx = js_getcontext(J);
5216 fz_pixmap *pixmap = ffi_topixmap(J, 0);
5217 const char *filename = js_tostring(J, 1);
5218
5219 fz_try(ctx)
5220 fz_save_pixmap_as_pkm(ctx, pixmap, filename);
5221 fz_catch(ctx)
5222 rethrow(J);
5223 }
5224
5225 static void ffi_Pixmap_saveAsJPX(js_State *J)
5226 {
5227 fz_context *ctx = js_getcontext(J);
5228 fz_pixmap *pixmap = ffi_topixmap(J, 0);
5229 const char *filename = js_tostring(J, 1);
5230 int quality = js_isdefined(J, 2) ? js_tointeger(J, 2) : 90;
5231
5232 fz_try(ctx)
5233 fz_save_pixmap_as_jpx(ctx, pixmap, filename, quality);
5234 fz_catch(ctx)
5235 rethrow(J);
5236 }
5237
5238 static void ffi_Pixmap_convertToColorSpace(js_State *J)
5239 {
5240 fz_context *ctx = js_getcontext(J);
5241 fz_pixmap *pixmap = ffi_topixmap(J, 0);
5242 fz_colorspace *cs = js_touserdata(J, 1, "fz_colorspace");
5243 fz_colorspace *proof = js_iscoercible(J, 2) ? js_touserdata(J, 2, "fz_colorspace") : NULL;
5244 fz_default_colorspaces *default_cs = js_iscoercible(J, 3) ? ffi_todefaultcolorspaces(J, 3) : NULL;
5245 fz_color_params color_params = ffi_tocolorparams(J, 4);
5246 int keep_alpha = js_isdefined(J, 5) ? js_toboolean(J, 5) : 0;
5247 fz_pixmap *dst = NULL;
5248
5249 fz_try(ctx)
5250 dst = fz_convert_pixmap(ctx, pixmap, cs, proof, default_cs, color_params, keep_alpha);
5251 fz_catch(ctx)
5252 rethrow(J);
5253
5254 ffi_pushpixmap(J, dst);
5255 }
5256
5257 static void ffi_Pixmap_getBounds(js_State *J)
5258 {
5259 fz_pixmap *pixmap = ffi_topixmap(J, 0);
5260 fz_rect bounds;
5261
5262 // fz_irect and fz_pixmap_bbox instead
5263 bounds.x0 = pixmap->x;
5264 bounds.y0 = pixmap->y;
5265 bounds.x1 = pixmap->x + pixmap->w;
5266 bounds.y1 = pixmap->y + pixmap->h;
5267
5268 ffi_pushrect(J, bounds);
5269 }
5270
5271 static void ffi_Pixmap_clear(js_State *J)
5272 {
5273 fz_context *ctx = js_getcontext(J);
5274 fz_pixmap *pixmap = ffi_topixmap(J, 0);
5275 if (js_isdefined(J, 1)) {
5276 int value = js_tointeger(J, 1);
5277 fz_try(ctx)
5278 fz_clear_pixmap_with_value(ctx, pixmap, value);
5279 fz_catch(ctx)
5280 rethrow(J);
5281 } else {
5282 fz_try(ctx)
5283 fz_clear_pixmap(ctx, pixmap);
5284 fz_catch(ctx)
5285 rethrow(J);
5286 }
5287 }
5288
5289 static void ffi_Pixmap_computeMD5(js_State *J)
5290 {
5291 fz_context *ctx = js_getcontext(J);
5292 fz_pixmap *pixmap = ffi_topixmap(J, 0);
5293 const char *hexdigit = "0123456789abcdef";
5294 unsigned char digest[16] = { 0 };
5295 char str[33];
5296 size_t i;
5297
5298 fz_try(ctx)
5299 fz_md5_pixmap(ctx, pixmap, digest);
5300 fz_catch(ctx)
5301 rethrow(J);
5302
5303 for (i = 0; i < nelem(digest); i++)
5304 {
5305 str[2*i] = hexdigit[(digest[i] >> 4) & 0xf];
5306 str[2*i+1] = hexdigit[digest[i] & 0xf];
5307 }
5308 str[32] = '\0';
5309 js_pushstring(J, str);
5310 }
5311
5312 static void ffi_Pixmap_getX(js_State *J)
5313 {
5314 fz_pixmap *pixmap = ffi_topixmap(J, 0);
5315 js_pushnumber(J, pixmap->x);
5316 }
5317
5318 static void ffi_Pixmap_getY(js_State *J)
5319 {
5320 fz_pixmap *pixmap = ffi_topixmap(J, 0);
5321 js_pushnumber(J, pixmap->y);
5322 }
5323
5324 static void ffi_Pixmap_getWidth(js_State *J)
5325 {
5326 fz_pixmap *pixmap = ffi_topixmap(J, 0);
5327 js_pushnumber(J, pixmap->w);
5328 }
5329
5330 static void ffi_Pixmap_getHeight(js_State *J)
5331 {
5332 fz_pixmap *pixmap = ffi_topixmap(J, 0);
5333 js_pushnumber(J, pixmap->h);
5334 }
5335
5336 static void ffi_Pixmap_getNumberOfComponents(js_State *J)
5337 {
5338 fz_pixmap *pixmap = ffi_topixmap(J, 0);
5339 js_pushnumber(J, pixmap->n);
5340 }
5341
5342 static void ffi_Pixmap_getAlpha(js_State *J)
5343 {
5344 fz_pixmap *pixmap = ffi_topixmap(J, 0);
5345 js_pushboolean(J, pixmap->alpha);
5346 }
5347
5348 static void ffi_Pixmap_getStride(js_State *J)
5349 {
5350 fz_pixmap *pixmap = ffi_topixmap(J, 0);
5351 js_pushnumber(J, pixmap->stride);
5352 }
5353
5354 static void ffi_Pixmap_getSample(js_State *J)
5355 {
5356 fz_pixmap *pixmap = ffi_topixmap(J, 0);
5357 int x = js_tointeger(J, 1);
5358 int y = js_tointeger(J, 2);
5359 int k = js_tointeger(J, 3);
5360 if (x < 0 || x >= pixmap->w) js_rangeerror(J, "X out of range");
5361 if (y < 0 || y >= pixmap->h) js_rangeerror(J, "Y out of range");
5362 if (k < 0 || k >= pixmap->n) js_rangeerror(J, "N out of range");
5363 js_pushnumber(J, pixmap->samples[(x + y * pixmap->w) * pixmap->n + k]);
5364 }
5365
5366 static void ffi_Pixmap_getPixels(js_State *J)
5367 {
5368 fz_context *ctx = js_getcontext(J);
5369 fz_pixmap *pixmap = ffi_topixmap(J, 0);
5370 int w, h, n, stride, x, y, k, m;
5371 unsigned char *p;
5372
5373 fz_try(ctx)
5374 {
5375 w = fz_pixmap_width(ctx, pixmap);
5376 h = fz_pixmap_height(ctx, pixmap);
5377 n = fz_pixmap_components(ctx, pixmap);
5378 stride = fz_pixmap_stride(ctx, pixmap);
5379 }
5380 fz_catch(ctx)
5381 rethrow(J);
5382
5383 js_newarray(J);
5384 p = fz_pixmap_samples(ctx, pixmap);
5385 m = 0;
5386 for (y = 0; y < h; y++)
5387 {
5388 int remain = stride;
5389 for (x = 0; x < w; x++)
5390 {
5391 for (k = 0; k < n; k++)
5392 {
5393 js_pushnumber(J, *p++);
5394 remain--;
5395 js_setindex(J, -2, m++);
5396 }
5397 }
5398 p += remain;
5399 }
5400 }
5401
5402 static void ffi_Pixmap_getXResolution(js_State *J)
5403 {
5404 fz_pixmap *pixmap = ffi_topixmap(J, 0);
5405 js_pushnumber(J, pixmap->xres);
5406 }
5407
5408 static void ffi_Pixmap_getYResolution(js_State *J)
5409 {
5410 fz_pixmap *pixmap = ffi_topixmap(J, 0);
5411 js_pushnumber(J, pixmap->yres);
5412 }
5413
5414 static void ffi_Pixmap_getColorSpace(js_State *J)
5415 {
5416 fz_pixmap *pixmap = ffi_topixmap(J, 0);
5417 ffi_pushcolorspace(J, pixmap->colorspace);
5418 }
5419
5420 static void ffi_Pixmap_setResolution(js_State *J)
5421 {
5422 fz_context *ctx = js_getcontext(J);
5423 fz_pixmap *pixmap = ffi_topixmap(J, 0);
5424 int xres = js_tointeger(J, 1);
5425 int yres = js_tointeger(J, 2);
5426
5427 fz_set_pixmap_resolution(ctx, pixmap, xres, yres);
5428 }
5429
5430 static void ffi_encodeBarcode_Pixmap(js_State *J)
5431 {
5432 fz_context *ctx = js_getcontext(J);
5433 fz_barcode_type barcode_type = fz_barcode_type_from_string(js_tostring(J, 1));
5434 const char *contents = js_tostring(J, 2);
5435 int size = js_iscoercible(J, 3) ? js_tointeger(J, 3) : 0;
5436 int ec = js_iscoercible(J, 4) ? js_tointeger(J, 4) : 2;
5437 int quiet = js_iscoercible(J, 5) ? js_toboolean(J, 5) : 0;
5438 int hrt = js_iscoercible(J, 6) ? js_toboolean(J, 6) : 0;
5439 fz_pixmap *pix;
5440
5441 fz_try(ctx)
5442 pix = fz_new_barcode_pixmap(ctx, barcode_type, contents, size, ec, quiet, hrt);
5443 fz_catch(ctx)
5444 rethrow(J);
5445
5446 ffi_pushpixmap(J, pix);
5447 }
5448
5449 static void ffi_new_Image(js_State *J)
5450 {
5451 fz_context *ctx = js_getcontext(J);
5452 fz_image *image = NULL;
5453
5454 fz_image *mask = NULL;
5455 if (js_isuserdata(J, 2, "fz_image"))
5456 mask = js_touserdata(J, 2, "fz_image");
5457
5458 if (js_isuserdata(J, 1, "fz_pixmap")) {
5459 fz_pixmap *pixmap = ffi_topixmap(J, 1);
5460 fz_try(ctx)
5461 image = fz_new_image_from_pixmap(ctx, pixmap, mask);
5462 fz_catch(ctx)
5463 rethrow(J);
5464 } else if (js_isuserdata(J, 1, "fz_buffer")) {
5465 fz_buffer *buffer = ffi_tonewbuffer(J, 1);
5466 fz_try(ctx)
5467 {
5468 image = fz_new_image_from_buffer(ctx, buffer);
5469 if (mask)
5470 image->mask = fz_keep_image(ctx, mask);
5471 }
5472 fz_always(ctx)
5473 fz_drop_buffer(ctx, buffer);
5474 fz_catch(ctx)
5475 rethrow(J);
5476 } else {
5477 const char *name = js_tostring(J, 1);
5478 fz_try(ctx)
5479 {
5480 image = fz_new_image_from_file(ctx, name);
5481 if (mask)
5482 image->mask = fz_keep_image(ctx, mask);
5483 }
5484 fz_catch(ctx)
5485 rethrow(J);
5486 }
5487
5488 ffi_pushimage_own(J, image);
5489 }
5490
5491 static void ffi_Image_getWidth(js_State *J)
5492 {
5493 fz_image *image = js_touserdata(J, 0, "fz_image");
5494 js_pushnumber(J, image->w);
5495 }
5496
5497 static void ffi_Image_getHeight(js_State *J)
5498 {
5499 fz_image *image = js_touserdata(J, 0, "fz_image");
5500 js_pushnumber(J, image->h);
5501 }
5502
5503 static void ffi_Image_getXResolution(js_State *J)
5504 {
5505 fz_image *image = js_touserdata(J, 0, "fz_image");
5506 js_pushnumber(J, image->xres);
5507 }
5508
5509 static void ffi_Image_getYResolution(js_State *J)
5510 {
5511 fz_image *image = js_touserdata(J, 0, "fz_image");
5512 js_pushnumber(J, image->yres);
5513 }
5514
5515 static void ffi_Image_getNumberOfComponents(js_State *J)
5516 {
5517 fz_image *image = js_touserdata(J, 0, "fz_image");
5518 js_pushnumber(J, image->n);
5519 }
5520
5521 static void ffi_Image_getBitsPerComponent(js_State *J)
5522 {
5523 fz_image *image = js_touserdata(J, 0, "fz_image");
5524 js_pushnumber(J, image->bpc);
5525 }
5526
5527 static void ffi_Image_getInterpolate(js_State *J)
5528 {
5529 fz_image *image = js_touserdata(J, 0, "fz_image");
5530 js_pushboolean(J, image->interpolate);
5531 }
5532
5533 static void ffi_Image_getOrientation(js_State *J)
5534 {
5535 fz_context *ctx = js_getcontext(J);
5536 fz_image *image = js_touserdata(J, 0, "fz_image");
5537 js_pushnumber(J, fz_image_orientation(ctx, image));
5538 }
5539
5540 static void ffi_Image_getImageMask(js_State *J)
5541 {
5542 fz_image *image = js_touserdata(J, 0, "fz_image");
5543 js_pushboolean(J, image->imagemask);
5544 }
5545
5546 static void ffi_Image_getMask(js_State *J)
5547 {
5548 fz_image *image = js_touserdata(J, 0, "fz_image");
5549 if (image->mask)
5550 ffi_pushimage(J, image->mask);
5551 else
5552 js_pushnull(J);
5553 }
5554
5555 static void ffi_Image_getColorSpace(js_State *J)
5556 {
5557 fz_image *image = js_touserdata(J, 0, "fz_image");
5558 ffi_pushcolorspace(J, image->colorspace);
5559 }
5560
5561 static void ffi_Image_toPixmap(js_State *J)
5562 {
5563 fz_context *ctx = js_getcontext(J);
5564 fz_image *image = js_touserdata(J, 0, "fz_image");
5565 fz_matrix matrix_, *matrix = NULL;
5566 fz_pixmap *pixmap = NULL;
5567
5568 if (js_isnumber(J, 1) && js_isnumber(J, 2)) {
5569 matrix_ = fz_scale(js_tonumber(J, 1), js_tonumber(J, 2));
5570 matrix = &matrix_;
5571 }
5572
5573 fz_try(ctx)
5574 pixmap = fz_get_pixmap_from_image(ctx, image, NULL, matrix, NULL, NULL);
5575 fz_catch(ctx)
5576 rethrow(J);
5577
5578 ffi_pushpixmap(J, pixmap);
5579 }
5580
5581 static void ffi_Image_getColorKey(js_State *J)
5582 {
5583 fz_image *image = js_touserdata(J, 0, "fz_image");
5584 int i;
5585 if (image->use_colorkey)
5586 {
5587 js_newarray(J);
5588 for (i = 0; i < 2 * image->n; ++i)
5589 {
5590 js_pushnumber(J, image->colorkey[i]);
5591 js_setindex(J, -2, i);
5592 }
5593 }
5594 else
5595 js_pushnull(J);
5596 }
5597
5598 static void ffi_Image_getDecode(js_State *J)
5599 {
5600 fz_image *image = js_touserdata(J, 0, "fz_image");
5601 int i;
5602 if (image->use_decode)
5603 {
5604 js_newarray(J);
5605 for (i = 0; i < 2 * image->n; ++i)
5606 {
5607 js_pushnumber(J, image->decode[i]);
5608 js_setindex(J, -2, i);
5609 }
5610 }
5611 else
5612 js_pushnull(J);
5613 }
5614
5615 static void ffi_Image_setOrientation(js_State *J)
5616 {
5617 fz_image *image = js_touserdata(J, 0, "fz_image");
5618 int orientation = js_tointeger(J, 1);
5619 if (orientation < 0 || orientation > 8)
5620 js_rangeerror(J, "orientation out of range");
5621 image->orientation = js_tointeger(J, 1);
5622 }
5623
5624 static void ffi_Shade_getBounds(js_State *J)
5625 {
5626 fz_context *ctx = js_getcontext(J);
5627 fz_shade *shade = js_touserdata(J, 0, "fz_shade");
5628 fz_matrix ctm = ffi_tomatrix(J, 1);
5629 fz_rect bounds;
5630
5631 fz_try(ctx)
5632 bounds = fz_bound_shade(ctx, shade, ctm);
5633 fz_catch(ctx)
5634 rethrow(J);
5635
5636 ffi_pushrect(J, bounds);
5637 }
5638
5639 static void ffi_new_Font(js_State *J)
5640 {
5641 fz_context *ctx = js_getcontext(J);
5642 const char *name = js_tostring(J, 1);
5643 const char *path = js_isstring(J, 2) ? js_tostring(J, 2) : NULL;
5644 fz_buffer *buffer = js_isuserdata(J, 2, "fz_buffer") ? js_touserdata(J, 2, "fz_buffer") : NULL;
5645 int index = js_isnumber(J, 3) ? js_tointeger(J, 3) : 0;
5646 fz_font *font = NULL;
5647
5648 fz_try(ctx) {
5649 if (path)
5650 font = fz_new_font_from_file(ctx, name, path, index, 0);
5651 else if (buffer)
5652 font = fz_new_font_from_buffer(ctx, name, buffer, index, 0);
5653 else if (!strcmp(name, "zh-Hant"))
5654 font = fz_new_cjk_font(ctx, FZ_ADOBE_CNS);
5655 else if (!strcmp(name, "zh-Hans"))
5656 font = fz_new_cjk_font(ctx, FZ_ADOBE_GB);
5657 else if (!strcmp(name, "ja"))
5658 font = fz_new_cjk_font(ctx, FZ_ADOBE_JAPAN);
5659 else if (!strcmp(name, "ko"))
5660 font = fz_new_cjk_font(ctx, FZ_ADOBE_KOREA);
5661 else
5662 font = fz_new_base14_font(ctx, name);
5663 }
5664 fz_catch(ctx)
5665 rethrow(J);
5666
5667 js_getregistry(J, "fz_font");
5668 js_newuserdata(J, "fz_font", font, ffi_gc_fz_font);
5669 }
5670
5671 static void ffi_Font_getName(js_State *J)
5672 {
5673 fz_context *ctx = js_getcontext(J);
5674 fz_font *font = js_touserdata(J, 0, "fz_font");
5675 js_pushstring(J, fz_font_name(ctx, font));
5676 }
5677
5678 static void ffi_Font_isMono(js_State *J)
5679 {
5680 fz_context *ctx = js_getcontext(J);
5681 fz_font *font = js_touserdata(J, 0, "fz_font");
5682 js_pushboolean(J, fz_font_is_monospaced(ctx, font));
5683 }
5684
5685 static void ffi_Font_isSerif(js_State *J)
5686 {
5687 fz_context *ctx = js_getcontext(J);
5688 fz_font *font = js_touserdata(J, 0, "fz_font");
5689 js_pushboolean(J, fz_font_is_serif(ctx, font));
5690 }
5691
5692 static void ffi_Font_isBold(js_State *J)
5693 {
5694 fz_context *ctx = js_getcontext(J);
5695 fz_font *font = js_touserdata(J, 0, "fz_font");
5696 js_pushboolean(J, fz_font_is_bold(ctx, font));
5697 }
5698
5699 static void ffi_Font_isItalic(js_State *J)
5700 {
5701 fz_context *ctx = js_getcontext(J);
5702 fz_font *font = js_touserdata(J, 0, "fz_font");
5703 js_pushboolean(J, fz_font_is_italic(ctx, font));
5704 }
5705
5706 static void ffi_Font_encodeCharacter(js_State *J)
5707 {
5708 fz_context *ctx = js_getcontext(J);
5709 fz_font *font = js_touserdata(J, 0, "fz_font");
5710 int unicode = js_tointeger(J, 1);
5711 int glyph = 0;
5712 fz_try(ctx)
5713 glyph = fz_encode_character(ctx, font, unicode);
5714 fz_catch(ctx)
5715 rethrow(J);
5716 js_pushnumber(J, glyph);
5717 }
5718
5719 static void ffi_Font_advanceGlyph(js_State *J)
5720 {
5721 fz_context *ctx = js_getcontext(J);
5722 fz_font *font = js_touserdata(J, 0, "fz_font");
5723 int glyph = js_tointeger(J, 1);
5724 int wmode = js_tointeger(J, 2);
5725
5726 float advance = 0;
5727 fz_try(ctx)
5728 advance = fz_advance_glyph(ctx, font, glyph, wmode);
5729 fz_catch(ctx)
5730 rethrow(J);
5731 js_pushnumber(J, advance);
5732 }
5733
5734 static void ffi_new_Text(js_State *J)
5735 {
5736 fz_context *ctx = js_getcontext(J);
5737 fz_text *text = NULL;
5738
5739 fz_try(ctx)
5740 text = fz_new_text(ctx);
5741 fz_catch(ctx)
5742 rethrow(J);
5743
5744 js_getregistry(J, "fz_text");
5745 js_newuserdata(J, "fz_text", text, ffi_gc_fz_text);
5746 }
5747
5748 static void ffi_Text_getBounds(js_State *J)
5749 {
5750 fz_context *ctx = js_getcontext(J);
5751 fz_text *text = js_touserdata(J, 0, "fz_text");
5752 fz_stroke_state *stroke = js_iscoercible(J, 1) ? ffi_tostroke(J, 1) : NULL;
5753 fz_matrix ctm = ffi_tomatrix(J, 2);
5754 fz_rect bounds;
5755
5756 fz_try(ctx)
5757 bounds = fz_bound_text(ctx, text, stroke, ctm);
5758 fz_catch(ctx)
5759 rethrow(J);
5760
5761 ffi_pushrect(J, bounds);
5762 }
5763
5764 static void ffi_Text_walk(js_State *J)
5765 {
5766 fz_text *text = js_touserdata(J, 0, "fz_text");
5767 char buf[8];
5768 fz_text_span *span;
5769 fz_matrix trm;
5770 int i;
5771
5772 for (span = text->head; span; span = span->next) {
5773 ffi_pushfont(J, span->font);
5774 trm = span->trm;
5775 if (js_hasproperty(J, 1, "beginSpan")) {
5776 js_copy(J, 1); // this
5777 js_copy(J, -3); // font
5778 ffi_pushmatrix(J, trm);
5779 js_pushnumber(J, span->wmode);
5780 js_pushnumber(J, span->bidi_level);
5781 js_pushnumber(J, span->markup_dir);
5782 js_pushstring(J, fz_string_from_text_language(buf, span->language));
5783 js_call(J, 6);
5784 js_pop(J, 1);
5785 }
5786 for (i = 0; i < span->len; ++i) {
5787 trm.e = span->items[i].x;
5788 trm.f = span->items[i].y;
5789 if (js_hasproperty(J, 1, "showGlyph")) {
5790 js_copy(J, 1); /* object for this binding */
5791 js_copy(J, -3); /* font */
5792 ffi_pushmatrix(J, trm);
5793 js_pushnumber(J, span->items[i].gid);
5794 js_pushnumber(J, span->items[i].ucs);
5795 js_pushnumber(J, span->wmode);
5796 js_pushnumber(J, span->bidi_level);
5797 js_call(J, 6);
5798 js_pop(J, 1);
5799 }
5800 }
5801 js_pop(J, 1); /* pop font object */
5802 if (js_hasproperty(J, 1, "endSpan")) {
5803 js_copy(J, 1); // this
5804 js_call(J, 0);
5805 js_pop(J, 1);
5806 }
5807 }
5808 js_pop(J, 1); /* pop showGlyph function */
5809 }
5810
5811 static void ffi_Text_showGlyph(js_State *J)
5812 {
5813 fz_context *ctx = js_getcontext(J);
5814 fz_text *text = js_touserdata(J, 0, "fz_text");
5815 fz_font *font = js_touserdata(J, 1, "fz_font");
5816 fz_matrix trm = ffi_tomatrix(J, 2);
5817 int glyph = js_tointeger(J, 3);
5818 int unicode = js_tointeger(J, 4);
5819 int wmode = js_isdefined(J, 5) ? js_toboolean(J, 5) : 0;
5820
5821 fz_try(ctx)
5822 fz_show_glyph(ctx, text, font, trm, glyph, unicode, wmode, 0, FZ_BIDI_NEUTRAL, FZ_LANG_UNSET);
5823 fz_catch(ctx)
5824 rethrow(J);
5825 }
5826
5827 static void ffi_Text_showString(js_State *J)
5828 {
5829 fz_context *ctx = js_getcontext(J);
5830 fz_text *text = js_touserdata(J, 0, "fz_text");
5831 fz_font *font = js_touserdata(J, 1, "fz_font");
5832 fz_matrix trm = ffi_tomatrix(J, 2);
5833 const char *s = js_tostring(J, 3);
5834 int wmode = js_isdefined(J, 4) ? js_toboolean(J, 4) : 0;
5835
5836 fz_try(ctx)
5837 trm = fz_show_string(ctx, text, font, trm, s, wmode, 0, FZ_BIDI_NEUTRAL, FZ_LANG_UNSET);
5838 fz_catch(ctx)
5839 rethrow(J);
5840
5841 /* update matrix with new pen position */
5842 js_pushnumber(J, trm.e);
5843 js_setindex(J, 2, 4);
5844 js_pushnumber(J, trm.f);
5845 js_setindex(J, 2, 5);
5846 }
5847
5848 static void ffi_new_Path(js_State *J)
5849 {
5850 fz_context *ctx = js_getcontext(J);
5851 fz_path *path = NULL;
5852
5853 fz_try(ctx)
5854 path = fz_new_path(ctx);
5855 fz_catch(ctx)
5856 rethrow(J);
5857
5858 js_getregistry(J, "fz_path");
5859 js_newuserdata(J, "fz_path", path, ffi_gc_fz_path);
5860 }
5861
5862 static void ffi_Path_walk_moveTo(fz_context *ctx, void *arg, float x, float y)
5863 {
5864 js_State *J = arg;
5865 if (js_try(J))
5866 rethrow_as_fz(J);
5867 if (js_hasproperty(J, 1, "moveTo")) {
5868 js_copy(J, 1);
5869 js_pushnumber(J, x);
5870 js_pushnumber(J, y);
5871 js_call(J, 2);
5872 js_pop(J, 1);
5873 }
5874 js_endtry(J);
5875 }
5876
5877 static void ffi_Path_walk_lineTo(fz_context *ctx, void *arg, float x, float y)
5878 {
5879 js_State *J = arg;
5880 if (js_try(J))
5881 rethrow_as_fz(J);
5882 if (js_hasproperty(J, 1, "lineTo")) {
5883 js_copy(J, 1);
5884 js_pushnumber(J, x);
5885 js_pushnumber(J, y);
5886 js_call(J, 2);
5887 js_pop(J, 1);
5888 }
5889 js_endtry(J);
5890 }
5891
5892 static void ffi_Path_walk_curveTo(fz_context *ctx, void *arg,
5893 float x1, float y1, float x2, float y2, float x3, float y3)
5894 {
5895 js_State *J = arg;
5896 if (js_try(J))
5897 rethrow_as_fz(J);
5898 if (js_hasproperty(J, 1, "curveTo")) {
5899 js_copy(J, 1);
5900 js_pushnumber(J, x1);
5901 js_pushnumber(J, y1);
5902 js_pushnumber(J, x2);
5903 js_pushnumber(J, y2);
5904 js_pushnumber(J, x3);
5905 js_pushnumber(J, y3);
5906 js_call(J, 6);
5907 js_pop(J, 1);
5908 }
5909 js_endtry(J);
5910 }
5911
5912 static void ffi_Path_walk_closePath(fz_context *ctx, void *arg)
5913 {
5914 js_State *J = arg;
5915 if (js_try(J))
5916 rethrow_as_fz(J);
5917 if (js_hasproperty(J, 1, "closePath")) {
5918 js_copy(J, 1);
5919 js_call(J, 0);
5920 js_pop(J, 1);
5921 }
5922 js_endtry(J);
5923 }
5924
5925 static void ffi_Path_walk(js_State *J)
5926 {
5927 fz_context *ctx = js_getcontext(J);
5928 fz_path *path = js_touserdata(J, 0, "fz_path");
5929 fz_path_walker walker = {
5930 ffi_Path_walk_moveTo,
5931 ffi_Path_walk_lineTo,
5932 ffi_Path_walk_curveTo,
5933 ffi_Path_walk_closePath,
5934 };
5935
5936 fz_try(ctx)
5937 fz_walk_path(ctx, path, &walker, J);
5938 fz_catch(ctx)
5939 rethrow(J);
5940 }
5941
5942 static void ffi_Path_moveTo(js_State *J)
5943 {
5944 fz_context *ctx = js_getcontext(J);
5945 fz_path *path = js_touserdata(J, 0, "fz_path");
5946 float x = js_tonumber(J, 1);
5947 float y = js_tonumber(J, 2);
5948
5949 fz_try(ctx)
5950 fz_moveto(ctx, path, x, y);
5951 fz_catch(ctx)
5952 rethrow(J);
5953 }
5954
5955 static void ffi_Path_lineTo(js_State *J)
5956 {
5957 fz_context *ctx = js_getcontext(J);
5958 fz_path *path = js_touserdata(J, 0, "fz_path");
5959 float x = js_tonumber(J, 1);
5960 float y = js_tonumber(J, 2);
5961
5962 fz_try(ctx)
5963 fz_lineto(ctx, path, x, y);
5964 fz_catch(ctx)
5965 rethrow(J);
5966 }
5967
5968 static void ffi_Path_curveTo(js_State *J)
5969 {
5970 fz_context *ctx = js_getcontext(J);
5971 fz_path *path = js_touserdata(J, 0, "fz_path");
5972 float x1 = js_tonumber(J, 1);
5973 float y1 = js_tonumber(J, 2);
5974 float x2 = js_tonumber(J, 3);
5975 float y2 = js_tonumber(J, 4);
5976 float x3 = js_tonumber(J, 5);
5977 float y3 = js_tonumber(J, 6);
5978
5979 fz_try(ctx)
5980 fz_curveto(ctx, path, x1, y1, x2, y2, x3, y3);
5981 fz_catch(ctx)
5982 rethrow(J);
5983 }
5984
5985 static void ffi_Path_curveToV(js_State *J)
5986 {
5987 fz_context *ctx = js_getcontext(J);
5988 fz_path *path = js_touserdata(J, 0, "fz_path");
5989 float cx = js_tonumber(J, 1);
5990 float cy = js_tonumber(J, 2);
5991 float ex = js_tonumber(J, 3);
5992 float ey = js_tonumber(J, 4);
5993
5994 fz_try(ctx)
5995 fz_curvetov(ctx, path, cx, cy, ex, ey);
5996 fz_catch(ctx)
5997 rethrow(J);
5998 }
5999
6000 static void ffi_Path_curveToY(js_State *J)
6001 {
6002 fz_context *ctx = js_getcontext(J);
6003 fz_path *path = js_touserdata(J, 0, "fz_path");
6004 float cx = js_tonumber(J, 1);
6005 float cy = js_tonumber(J, 2);
6006 float ex = js_tonumber(J, 3);
6007 float ey = js_tonumber(J, 4);
6008
6009 fz_try(ctx)
6010 fz_curvetoy(ctx, path, cx, cy, ex, ey);
6011 fz_catch(ctx)
6012 rethrow(J);
6013 }
6014
6015 static void ffi_Path_closePath(js_State *J)
6016 {
6017 fz_context *ctx = js_getcontext(J);
6018 fz_path *path = js_touserdata(J, 0, "fz_path");
6019
6020 fz_try(ctx)
6021 fz_closepath(ctx, path);
6022 fz_catch(ctx)
6023 rethrow(J);
6024 }
6025
6026 static void ffi_Path_rect(js_State *J)
6027 {
6028 fz_context *ctx = js_getcontext(J);
6029 fz_path *path = js_touserdata(J, 0, "fz_path");
6030 float x1 = js_tonumber(J, 1);
6031 float y1 = js_tonumber(J, 2);
6032 float x2 = js_tonumber(J, 3);
6033 float y2 = js_tonumber(J, 4);
6034
6035 fz_try(ctx)
6036 fz_rectto(ctx, path, x1, y1, x2, y2);
6037 fz_catch(ctx)
6038 rethrow(J);
6039 }
6040
6041 static void ffi_Path_getBounds(js_State *J)
6042 {
6043 fz_context *ctx = js_getcontext(J);
6044 fz_path *path = js_touserdata(J, 0, "fz_path");
6045 fz_stroke_state *stroke = js_iscoercible(J, 1) ? ffi_tostroke(J, 1) : NULL;
6046 fz_matrix ctm = ffi_tomatrix(J, 2);
6047 fz_rect bounds;
6048
6049 fz_try(ctx)
6050 bounds = fz_bound_path(ctx, path, stroke, ctm);
6051 fz_catch(ctx)
6052 rethrow(J);
6053
6054 ffi_pushrect(J, bounds);
6055 }
6056
6057 static void ffi_Path_transform(js_State *J)
6058 {
6059 fz_context *ctx = js_getcontext(J);
6060 fz_path *path = js_touserdata(J, 0, "fz_path");
6061 fz_matrix ctm = ffi_tomatrix(J, 1);
6062
6063 fz_try(ctx)
6064 fz_transform_path(ctx, path, ctm);
6065 fz_catch(ctx)
6066 rethrow(J);
6067 }
6068
6069 static void ffi_new_DisplayList(js_State *J)
6070 {
6071 fz_context *ctx = js_getcontext(J);
6072 fz_rect mediabox = ffi_torect(J, 1);
6073 fz_display_list *list = NULL;
6074
6075 fz_try(ctx)
6076 list = fz_new_display_list(ctx, mediabox);
6077 fz_catch(ctx)
6078 rethrow(J);
6079
6080 js_getregistry(J, "fz_display_list");
6081 js_newuserdata(J, "fz_display_list", list, ffi_gc_fz_display_list);
6082 }
6083
6084 static void ffi_DisplayList_getBounds(js_State *J)
6085 {
6086 fz_context *ctx = js_getcontext(J);
6087 fz_display_list *list = js_touserdata(J, 0, "fz_display_list");
6088 fz_rect bounds;
6089
6090 fz_try(ctx)
6091 bounds = fz_bound_display_list(ctx, list);
6092 fz_catch(ctx)
6093 rethrow(J);
6094 ffi_pushrect(J, bounds);
6095 }
6096
6097 static void ffi_DisplayList_run(js_State *J)
6098 {
6099 fz_context *ctx = js_getcontext(J);
6100 fz_display_list *list = js_touserdata(J, 0, "fz_display_list");
6101 fz_device *device = NULL;
6102 fz_matrix ctm = ffi_tomatrix(J, 2);
6103
6104 if (js_isuserdata(J, 1, "fz_device")) {
6105 device = js_touserdata(J, 1, "fz_device");
6106 fz_try(ctx)
6107 fz_run_display_list(ctx, list, device, ctm, fz_infinite_rect, NULL);
6108 fz_catch(ctx)
6109 rethrow(J);
6110 } else {
6111 device = new_js_device(ctx, J);
6112 js_copy(J, 1);
6113 fz_try(ctx)
6114 fz_run_display_list(ctx, list, device, ctm, fz_infinite_rect, NULL);
6115 fz_always(ctx)
6116 fz_drop_device(ctx, device);
6117 fz_catch(ctx)
6118 rethrow(J);
6119 }
6120 }
6121
6122 static void ffi_DisplayList_toPixmap(js_State *J)
6123 {
6124 fz_context *ctx = js_getcontext(J);
6125 fz_display_list *list = js_touserdata(J, 0, "fz_display_list");
6126 fz_matrix ctm = ffi_tomatrix(J, 1);
6127 fz_colorspace *colorspace = js_touserdata(J, 2, "fz_colorspace");
6128 int alpha = js_isdefined(J, 3) ? js_toboolean(J, 3) : 0;
6129 fz_pixmap *pixmap = NULL;
6130
6131 fz_try(ctx)
6132 pixmap = fz_new_pixmap_from_display_list(ctx, list, ctm, colorspace, alpha);
6133 fz_catch(ctx)
6134 rethrow(J);
6135
6136 ffi_pushpixmap(J, pixmap);
6137 }
6138
6139 static void ffi_DisplayList_toStructuredText(js_State *J)
6140 {
6141 fz_context *ctx = js_getcontext(J);
6142 fz_display_list *list = js_touserdata(J, 0, "fz_display_list");
6143 const char *options = js_iscoercible(J, 1) ? js_tostring(J, 1) : NULL;
6144 fz_stext_options so;
6145 fz_stext_page *text = NULL;
6146
6147 fz_try(ctx) {
6148 fz_parse_stext_options(ctx, &so, options);
6149 text = fz_new_stext_page_from_display_list(ctx, list, &so);
6150 }
6151 fz_catch(ctx)
6152 rethrow(J);
6153
6154 js_getregistry(J, "fz_stext_page");
6155 js_newuserdata(J, "fz_stext_page", text, ffi_gc_fz_stext_page);
6156 }
6157
6158 static void ffi_DisplayList_search(js_State *J)
6159 {
6160 fz_context *ctx = js_getcontext(J);
6161 fz_display_list *list = js_touserdata(J, 0, "fz_display_list");
6162 const char *needle = js_tostring(J, 1);
6163 search_state state = { J, 0, 0, 0 };
6164
6165 state.max_hits = js_iscoercible(J, 2) ? js_tointeger(J, 2) : 500;
6166
6167 js_newarray(J);
6168
6169 fz_try(ctx)
6170 fz_search_display_list_cb(ctx, list, needle, hit_callback, &state);
6171 fz_catch(ctx)
6172 rethrow(J);
6173
6174 if (state.error)
6175 js_throw(J);
6176 }
6177
6178 static void ffi_DisplayList_decodeBarcode(js_State *J)
6179 {
6180 fz_context *ctx = js_getcontext(J);
6181 fz_display_list *list = js_touserdata(J, 0, "fz_display_list");
6182 fz_rect subarea = js_iscoercible(J, 1) ? ffi_torect(J, 1) : fz_infinite_rect;
6183 float rotate = js_iscoercible(J, 2) ? js_tonumber(J, 2) : 0;
6184 char *text;
6185 fz_barcode_type type;
6186
6187 fz_try(ctx)
6188 text = fz_decode_barcode_from_display_list(ctx, &type, list, subarea, rotate);
6189 fz_catch(ctx)
6190 rethrow(J);
6191
6192 if (js_try(J))
6193 {
6194 fz_free(ctx, text);
6195 js_throw(J);
6196 }
6197
6198 js_newobject(J);
6199 js_pushliteral(J, fz_string_from_barcode_type(type));
6200 js_setproperty(J, -2, "type");
6201 js_pushstring(J, text);
6202 js_setproperty(J, -2, "contents");
6203 js_endtry(J);
6204 fz_free(ctx, text);
6205 }
6206
6207 static void
6208 stext_walk(js_State *J, fz_stext_block *block)
6209 {
6210 fz_stext_line *line;
6211 fz_stext_char *ch;
6212
6213 while (block)
6214 {
6215 switch (block->type)
6216 {
6217 case FZ_STEXT_BLOCK_IMAGE:
6218 if (js_hasproperty(J, 1, "onImageBlock"))
6219 {
6220 js_pushnull(J);
6221 ffi_pushrect(J, block->bbox);
6222 ffi_pushmatrix(J, block->u.i.transform);
6223 ffi_pushimage(J, block->u.i.image);
6224 js_call(J, 3);
6225 js_pop(J, 1);
6226 }
6227 break;
6228 case FZ_STEXT_BLOCK_TEXT:
6229 if (js_hasproperty(J, 1, "beginTextBlock"))
6230 {
6231 js_pushnull(J);
6232 ffi_pushrect(J, block->bbox);
6233 js_call(J, 1);
6234 js_pop(J, 1);
6235 }
6236
6237 for (line = block->u.t.first_line; line; line = line->next)
6238 {
6239 if (js_hasproperty(J, 1, "beginLine"))
6240 {
6241 js_pushnull(J);
6242 ffi_pushrect(J, line->bbox);
6243 js_pushboolean(J, line->wmode);
6244 ffi_pushpoint(J, line->dir);
6245 js_call(J, 3);
6246 js_pop(J, 1);
6247 }
6248
6249 for (ch = line->first_char; ch; ch = ch->next)
6250 {
6251 if (js_hasproperty(J, 1, "onChar"))
6252 {
6253 char utf[10];
6254 js_pushnull(J);
6255 utf[fz_runetochar(utf, ch->c)] = 0;
6256 js_pushstring(J, utf);
6257 ffi_pushpoint(J, ch->origin);
6258 ffi_pushfont(J, ch->font);
6259 js_pushnumber(J, ch->size);
6260 ffi_pushquad(J, ch->quad);
6261 ffi_pushrgb(J, ch->argb);
6262 js_call(J, 6);
6263 js_pop(J, 1);
6264 }
6265 }
6266
6267 if (js_hasproperty(J, 1, "endLine"))
6268 {
6269 js_pushnull(J);
6270 js_call(J, 0);
6271 js_pop(J, 1);
6272 }
6273 }
6274
6275 if (js_hasproperty(J, 1, "endTextBlock"))
6276 {
6277 js_pushnull(J);
6278 js_call(J, 0);
6279 js_pop(J, 1);
6280 }
6281 break;
6282 case FZ_STEXT_BLOCK_STRUCT:
6283 if (block->u.s.down)
6284 {
6285 if (js_hasproperty(J, 1, "beginStruct"))
6286 {
6287 js_pushnull(J);
6288 js_pushliteral(J, fz_structure_to_string(block->u.s.down->standard));
6289 js_pushstring(J, block->u.s.down->raw);
6290 js_pushnumber(J, block->u.s.index);
6291 js_call(J, 3);
6292 js_pop(J, 1);
6293 }
6294 if (block->u.s.down)
6295 stext_walk(J, block->u.s.down->first_block);
6296 if (js_hasproperty(J, 1, "endStruct"))
6297 {
6298 js_pushnull(J);
6299 js_call(J, 0);
6300 js_pop(J, 1);
6301 }
6302 }
6303 break;
6304 case FZ_STEXT_BLOCK_VECTOR:
6305 if (js_hasproperty(J, 1, "onVector"))
6306 {
6307 js_pushnull(J);
6308 ffi_pushrect(J, block->bbox);
6309 js_newobject(J);
6310 js_pushboolean(J, block->u.v.flags & FZ_STEXT_VECTOR_IS_STROKED);
6311 js_setproperty(J, -2, "isStroked");
6312 js_pushboolean(J, block->u.v.flags & FZ_STEXT_VECTOR_IS_RECTANGLE);
6313 js_setproperty(J, -2, "isRectangle");
6314 ffi_pushrgb(J, block->u.v.argb);
6315 js_call(J, 4);
6316 js_pop(J, 1);
6317 }
6318 break;
6319 }
6320 block = block->next;
6321 }
6322 }
6323
6324 static void ffi_StructuredText_walk(js_State *J)
6325 {
6326 fz_stext_page *page = js_touserdata(J, 0, "fz_stext_page");
6327
6328 stext_walk(J, page->first_block);
6329 }
6330
6331 static void ffi_StructuredText_search(js_State *J)
6332 {
6333 fz_context *ctx = js_getcontext(J);
6334 fz_stext_page *text = js_touserdata(J, 0, "fz_stext_page");
6335 const char *needle = js_tostring(J, 1);
6336 search_state state = { J, 0, 0, 0 };
6337
6338 state.max_hits = js_iscoercible(J, 2) ? js_tointeger(J, 2) : 500;
6339 js_newarray(J);
6340
6341 fz_try(ctx)
6342 fz_search_stext_page_cb(ctx, text, needle, hit_callback, &state);
6343 fz_catch(ctx)
6344 rethrow(J);
6345
6346 if (state.error)
6347 js_throw(J);
6348 }
6349
6350 static void ffi_StructuredText_highlight(js_State *J)
6351 {
6352 fz_context *ctx = js_getcontext(J);
6353 fz_stext_page *text = js_touserdata(J, 0, "fz_stext_page");
6354 fz_point a = ffi_topoint(J, 1);
6355 fz_point b = ffi_topoint(J, 2);
6356 fz_quad hits[256];
6357 int i, n = 0;
6358
6359 fz_try(ctx)
6360 n = fz_highlight_selection(ctx, text, a, b, hits, nelem(hits));
6361 fz_catch(ctx)
6362 rethrow(J);
6363
6364 js_newarray(J);
6365 for (i = 0; i < n; ++i) {
6366 ffi_pushquad(J, hits[i]);
6367 js_setindex(J, -2, i);
6368 }
6369 }
6370
6371 static void ffi_StructuredText_copy(js_State *J)
6372 {
6373 fz_context *ctx = js_getcontext(J);
6374 fz_stext_page *text = js_touserdata(J, 0, "fz_stext_page");
6375 fz_point a = ffi_topoint(J, 1);
6376 fz_point b = ffi_topoint(J, 2);
6377 char *s = NULL;
6378
6379 fz_try(ctx)
6380 s = fz_copy_selection(ctx, text, a, b, 0);
6381 fz_catch(ctx)
6382 rethrow(J);
6383
6384 if (js_try(J))
6385 {
6386 fz_free(ctx, s);
6387 js_throw(J);
6388 }
6389 js_pushstring(J, s);
6390 js_endtry(J);
6391 fz_free(ctx, s);
6392 }
6393
6394 static void ffi_StructuredText_asJSON(js_State *J)
6395 {
6396 fz_context *ctx = js_getcontext(J);
6397 fz_stext_page *page = js_touserdata(J, 0, "fz_stext_page");
6398 double scale = js_tonumber(J, 1);
6399 const char *data = NULL;
6400 fz_buffer *buf = NULL;
6401 fz_output *out = NULL;
6402
6403 fz_var(out);
6404 fz_var(buf);
6405
6406 fz_try(ctx)
6407 {
6408 buf = fz_new_buffer(ctx, 1024);
6409 out = fz_new_output_with_buffer(ctx, buf);
6410 fz_print_stext_page_as_json(ctx, out, page, scale);
6411 fz_close_output(ctx, out);
6412 data = fz_string_from_buffer(ctx, buf);
6413 }
6414 fz_always(ctx)
6415 fz_drop_output(ctx, out);
6416 fz_catch(ctx)
6417 {
6418 fz_drop_buffer(ctx, buf);
6419 rethrow(J);
6420 }
6421
6422 if (js_try(J))
6423 {
6424 fz_drop_buffer(ctx, buf);
6425 js_throw(J);
6426 }
6427 js_pushstring(J, data);
6428 js_endtry(J);
6429 fz_drop_buffer(ctx, buf);
6430 }
6431
6432 static void ffi_StructuredText_asHTML(js_State *J)
6433 {
6434 fz_context *ctx = js_getcontext(J);
6435 fz_stext_page *page = js_touserdata(J, 0, "fz_stext_page");
6436 int id = js_tointeger(J, 1);
6437 const char *data = NULL;
6438 fz_buffer *buf = NULL;
6439 fz_output *out = NULL;
6440
6441 fz_var(out);
6442 fz_var(buf);
6443
6444 fz_try(ctx)
6445 {
6446 buf = fz_new_buffer(ctx, 1024);
6447 out = fz_new_output_with_buffer(ctx, buf);
6448 fz_print_stext_page_as_html(ctx, out, page, id);
6449 fz_close_output(ctx, out);
6450 data = fz_string_from_buffer(ctx, buf);
6451 }
6452 fz_always(ctx)
6453 fz_drop_output(ctx, out);
6454 fz_catch(ctx)
6455 {
6456 fz_drop_buffer(ctx, buf);
6457 rethrow(J);
6458 }
6459
6460 if (js_try(J))
6461 {
6462 fz_drop_buffer(ctx, buf);
6463 js_throw(J);
6464 }
6465 js_pushstring(J, data);
6466 js_endtry(J);
6467 fz_drop_buffer(ctx, buf);
6468 }
6469
6470 static void ffi_StructuredText_asText(js_State *J)
6471 {
6472 fz_context *ctx = js_getcontext(J);
6473 fz_stext_page *page = js_touserdata(J, 0, "fz_stext_page");
6474 const char *data = NULL;
6475 fz_buffer *buf = NULL;
6476 fz_output *out = NULL;
6477
6478 fz_var(out);
6479 fz_var(buf);
6480
6481 fz_try(ctx)
6482 {
6483 buf = fz_new_buffer(ctx, 1024);
6484 out = fz_new_output_with_buffer(ctx, buf);
6485 fz_print_stext_page_as_text(ctx, out, page);
6486 fz_close_output(ctx, out);
6487 data = fz_string_from_buffer(ctx, buf);
6488 }
6489 fz_always(ctx)
6490 fz_drop_output(ctx, out);
6491 fz_catch(ctx)
6492 {
6493 fz_drop_buffer(ctx, buf);
6494 rethrow(J);
6495 }
6496
6497 if (js_try(J))
6498 {
6499 fz_drop_buffer(ctx, buf);
6500 js_throw(J);
6501 }
6502 js_pushstring(J, data);
6503 js_endtry(J);
6504 fz_drop_buffer(ctx, buf);
6505 }
6506
6507 static void ffi_new_DisplayListDevice(js_State *J)
6508 {
6509 fz_context *ctx = js_getcontext(J);
6510 fz_display_list *list = js_touserdata(J, 1, "fz_display_list");
6511 fz_device *device = NULL;
6512
6513 fz_try(ctx)
6514 device = fz_new_list_device(ctx, list);
6515 fz_catch(ctx)
6516 rethrow(J);
6517
6518 js_getregistry(J, "fz_device");
6519 js_newuserdata(J, "fz_device", device, ffi_gc_fz_device);
6520 }
6521
6522 static void ffi_new_DrawDevice(js_State *J)
6523 {
6524 fz_context *ctx = js_getcontext(J);
6525 fz_matrix transform = ffi_tomatrix(J, 1);
6526 fz_pixmap *pixmap = ffi_topixmap(J, 2);
6527 fz_device *device = NULL;
6528
6529 fz_try(ctx)
6530 device = fz_new_draw_device(ctx, transform, pixmap);
6531 fz_catch(ctx)
6532 rethrow(J);
6533
6534 js_getregistry(J, "fz_device");
6535 js_newuserdata(J, "fz_device", device, ffi_gc_fz_device);
6536 }
6537
6538 static void ffi_new_DocumentWriter(js_State *J)
6539 {
6540 fz_context *ctx = js_getcontext(J);
6541 const char *filename = NULL;
6542 const char *format = js_iscoercible(J, 2) ? js_tostring(J, 2) : NULL;
6543 const char *options = js_iscoercible(J, 3) ? js_tostring(J, 3) : NULL;
6544 fz_document_writer *wri = NULL;
6545 fz_buffer *buf = NULL;
6546
6547 if (js_isuserdata(J, 1, "fz_buffer"))
6548 buf = js_touserdata(J, 1, "fz_buffer");
6549 else
6550 filename = js_tostring(J, 1);
6551
6552 fz_try(ctx) {
6553 if (buf)
6554 wri = fz_new_document_writer_with_buffer(ctx, buf, format, options);
6555 else
6556 wri = fz_new_document_writer(ctx, filename, format, options);
6557 } fz_catch(ctx) {
6558 rethrow(J);
6559 }
6560
6561 js_getregistry(J, "fz_document_writer");
6562 js_newuserdata(J, "fz_document_writer", wri, ffi_gc_fz_document_writer);
6563 }
6564
6565 static void ffi_DocumentWriter_beginPage(js_State *J)
6566 {
6567 fz_context *ctx = js_getcontext(J);
6568 fz_document_writer *wri = js_touserdata(J, 0, "fz_document_writer");
6569 fz_rect mediabox = ffi_torect(J, 1);
6570 fz_device *device = NULL;
6571
6572 fz_try(ctx)
6573 device = fz_begin_page(ctx, wri, mediabox);
6574 fz_catch(ctx)
6575 rethrow(J);
6576
6577 js_getregistry(J, "fz_device");
6578 js_newuserdata(J, "fz_device", fz_keep_device(ctx, device), ffi_gc_fz_device);
6579 }
6580
6581 static void ffi_DocumentWriter_endPage(js_State *J)
6582 {
6583 fz_context *ctx = js_getcontext(J);
6584 fz_document_writer *wri = js_touserdata(J, 0, "fz_document_writer");
6585 fz_try(ctx)
6586 fz_end_page(ctx, wri);
6587 fz_catch(ctx)
6588 rethrow(J);
6589 }
6590
6591 static void ffi_DocumentWriter_close(js_State *J)
6592 {
6593 fz_context *ctx = js_getcontext(J);
6594 fz_document_writer *wri = js_touserdata(J, 0, "fz_document_writer");
6595 fz_try(ctx)
6596 fz_close_document_writer(ctx, wri);
6597 fz_catch(ctx)
6598 rethrow(J);
6599 }
6600
6601 static void ffi_new_Story(js_State *J)
6602 {
6603 fz_context *ctx = js_getcontext(J);
6604 const char *user_css = js_iscoercible(J, 2) ? js_tostring(J, 2) : NULL;
6605 double em = js_isdefined(J, 3) ? js_tonumber(J, 3) : 12;
6606 fz_archive *arch = js_iscoercible(J, 4) ? ffi_toarchive(J, 4) : NULL;
6607 fz_buffer *contents = ffi_tonewbuffer(J, 1);
6608 fz_story *story = NULL;
6609
6610 fz_try(ctx)
6611 story = fz_new_story(ctx, contents, user_css, em, arch);
6612 fz_always(ctx)
6613 fz_drop_buffer(ctx, contents);
6614 fz_catch(ctx)
6615 rethrow(J);
6616
6617 js_getregistry(J, "fz_story");
6618 js_newuserdata(J, "fz_story", story, ffi_gc_fz_story);
6619 }
6620
6621 static void ffi_Story_place(js_State *J)
6622 {
6623 fz_context *ctx = js_getcontext(J);
6624 fz_story *story = js_touserdata(J, 0, "fz_story");
6625 fz_rect rect = ffi_torect(J, 1);
6626 int flags = js_iscoercible(J, 2) ? js_tointeger(J, 2) : 0;
6627 fz_rect filled = fz_empty_rect;
6628 int more;
6629
6630 fz_try(ctx)
6631 more = fz_place_story_flags(ctx, story, rect, &filled, flags);
6632 fz_catch(ctx)
6633 rethrow(J);
6634
6635 js_newobject(J);
6636
6637 ffi_pushrect(J, filled);
6638 js_setproperty(J, -2, "filled");
6639
6640 js_pushnumber(J, more);
6641 js_setproperty(J, -2, "more");
6642 }
6643
6644 static void ffi_Story_draw(js_State *J)
6645 {
6646 fz_context *ctx = js_getcontext(J);
6647 fz_story *story = js_touserdata(J, 0, "fz_story");
6648 fz_device *device;
6649 int drop = 1;
6650 fz_matrix ctm = ffi_tomatrix(J, 2);
6651
6652 if (js_isuserdata(J, 1, "fz_device")) {
6653 device = js_touserdata(J, 1, "fz_device");
6654 drop = 0;
6655 } else {
6656 device = new_js_device(ctx, J);
6657 js_copy(J, 1);
6658 }
6659
6660 fz_try(ctx) {
6661 fz_draw_story(ctx, story, device, ctm);
6662 }
6663 fz_always(ctx)
6664 {
6665 if (drop)
6666 fz_drop_device(ctx, device);
6667 }
6668 fz_catch(ctx)
6669 rethrow(J);
6670 }
6671
6672 static void ffi_Story_document(js_State *J)
6673 {
6674 fz_context *ctx = js_getcontext(J);
6675 fz_story *story = js_touserdata(J, 0, "fz_story");
6676 fz_xml *dom;
6677
6678 fz_try(ctx)
6679 dom = fz_story_document(ctx, story);
6680 fz_catch(ctx)
6681 rethrow(J);
6682
6683 ffi_pushdom(J, dom);
6684 }
6685
6686 static void ffi_DOM_body(js_State *J)
6687 {
6688 fz_context *ctx = js_getcontext(J);
6689 fz_xml *dom = js_touserdata(J, 0, "fz_xml");
6690
6691 fz_try(ctx)
6692 dom = fz_dom_body(ctx, dom);
6693 fz_catch(ctx)
6694 rethrow(J);
6695
6696 ffi_pushdom(J, dom);
6697 }
6698
6699 static void ffi_DOM_documentElement(js_State *J)
6700 {
6701 fz_context *ctx = js_getcontext(J);
6702 fz_xml *dom = js_touserdata(J, 0, "fz_xml");
6703
6704 fz_try(ctx)
6705 dom = fz_dom_document_element(ctx, dom);
6706 fz_catch(ctx)
6707 rethrow(J);
6708
6709 ffi_pushdom(J, dom);
6710 }
6711
6712 static void ffi_DOM_createElement(js_State *J)
6713 {
6714 fz_context *ctx = js_getcontext(J);
6715 fz_xml *dom = js_touserdata(J, 0, "fz_xml");
6716 const char *tag = js_iscoercible(J, 1) ? js_tostring(J, 1) : NULL;
6717
6718 fz_try(ctx)
6719 dom = fz_dom_create_element(ctx, dom, tag);
6720 fz_catch(ctx)
6721 rethrow(J);
6722
6723 ffi_pushdom(J, dom);
6724 }
6725
6726 static void ffi_DOM_createTextNode(js_State *J)
6727 {
6728 fz_context *ctx = js_getcontext(J);
6729 fz_xml *dom = js_touserdata(J, 0, "fz_xml");
6730 const char *text = js_iscoercible(J, 1) ? js_tostring(J, 1) : NULL;
6731
6732 fz_try(ctx)
6733 dom = fz_dom_create_text_node(ctx, dom, text);
6734 fz_catch(ctx)
6735 rethrow(J);
6736
6737 ffi_pushdom(J, dom);
6738 }
6739
6740 static void ffi_DOM_find(js_State *J)
6741 {
6742 fz_context *ctx = js_getcontext(J);
6743 fz_xml *dom = js_touserdata(J, 0, "fz_xml");
6744 const char *tag = js_iscoercible(J, 1) ? js_tostring(J, 1) : NULL;
6745 const char *att = js_iscoercible(J, 2) ? js_tostring(J, 2) : NULL;
6746 const char *val = js_iscoercible(J, 3) ? js_tostring(J, 3) : NULL;
6747
6748 fz_try(ctx)
6749 dom = fz_dom_find(ctx, dom, tag, att, val);
6750 fz_catch(ctx)
6751 rethrow(J);
6752
6753 ffi_pushdom(J, dom);
6754 }
6755
6756 static void ffi_DOM_findNext(js_State *J)
6757 {
6758 fz_context *ctx = js_getcontext(J);
6759 fz_xml *dom = js_touserdata(J, 0, "fz_xml");
6760 const char *tag = js_iscoercible(J, 1) ? js_tostring(J, 1) : NULL;
6761 const char *att = js_iscoercible(J, 2) ? js_tostring(J, 2) : NULL;
6762 const char *val = js_iscoercible(J, 3) ? js_tostring(J, 3) : NULL;
6763
6764 fz_try(ctx)
6765 dom = fz_dom_find_next(ctx, dom, tag, att, val);
6766 fz_catch(ctx)
6767 rethrow(J);
6768
6769 ffi_pushdom(J, dom);
6770 }
6771
6772 static void ffi_DOM_appendChild(js_State *J)
6773 {
6774 fz_context *ctx = js_getcontext(J);
6775 fz_xml *dom = js_touserdata(J, 0, "fz_xml");
6776 fz_xml *child = js_touserdata(J, 1, "fz_xml");
6777
6778 fz_try(ctx)
6779 fz_dom_append_child(ctx, dom, child);
6780 fz_catch(ctx)
6781 rethrow(J);
6782 }
6783
6784 static void ffi_DOM_insertBefore(js_State *J)
6785 {
6786 fz_context *ctx = js_getcontext(J);
6787 fz_xml *dom = js_touserdata(J, 0, "fz_xml");
6788 fz_xml *elt = js_touserdata(J, 1, "fz_xml");
6789
6790 fz_try(ctx)
6791 fz_dom_insert_before(ctx, dom, elt);
6792 fz_catch(ctx)
6793 rethrow(J);
6794 }
6795
6796 static void ffi_DOM_insertAfter(js_State *J)
6797 {
6798 fz_context *ctx = js_getcontext(J);
6799 fz_xml *dom = js_touserdata(J, 0, "fz_xml");
6800 fz_xml *elt = js_touserdata(J, 1, "fz_xml");
6801
6802 fz_try(ctx)
6803 fz_dom_insert_after(ctx, dom, elt);
6804 fz_catch(ctx)
6805 rethrow(J);
6806 }
6807
6808 static void ffi_DOM_remove(js_State *J)
6809 {
6810 fz_context *ctx = js_getcontext(J);
6811 fz_xml *dom = js_touserdata(J, 0, "fz_xml");
6812
6813 fz_try(ctx)
6814 fz_dom_remove(ctx, dom);
6815 fz_catch(ctx)
6816 rethrow(J);
6817 }
6818
6819 static void ffi_DOM_clone(js_State *J)
6820 {
6821 fz_context *ctx = js_getcontext(J);
6822 fz_xml *dom = js_touserdata(J, 0, "fz_xml");
6823
6824 fz_try(ctx)
6825 dom = fz_dom_clone(ctx, dom);
6826 fz_catch(ctx)
6827 rethrow(J);
6828
6829 ffi_pushdom(J, dom);
6830 }
6831
6832 static void ffi_DOM_firstChild(js_State *J)
6833 {
6834 fz_context *ctx = js_getcontext(J);
6835 fz_xml *dom = js_touserdata(J, 0, "fz_xml");
6836
6837 fz_try(ctx)
6838 dom = fz_dom_first_child(ctx, dom);
6839 fz_catch(ctx)
6840 rethrow(J);
6841
6842 ffi_pushdom(J, dom);
6843 }
6844
6845 static void ffi_DOM_parent(js_State *J)
6846 {
6847 fz_context *ctx = js_getcontext(J);
6848 fz_xml *dom = js_touserdata(J, 0, "fz_xml");
6849
6850 fz_try(ctx)
6851 dom = fz_dom_parent(ctx, dom);
6852 fz_catch(ctx)
6853 rethrow(J);
6854
6855 ffi_pushdom(J, dom);
6856 }
6857
6858 static void ffi_DOM_next(js_State *J)
6859 {
6860 fz_context *ctx = js_getcontext(J);
6861 fz_xml *dom = js_touserdata(J, 0, "fz_xml");
6862
6863 fz_try(ctx)
6864 dom = fz_dom_next(ctx, dom);
6865 fz_catch(ctx)
6866 rethrow(J);
6867
6868 ffi_pushdom(J, dom);
6869 }
6870
6871 static void ffi_DOM_previous(js_State *J)
6872 {
6873 fz_context *ctx = js_getcontext(J);
6874 fz_xml *dom = js_touserdata(J, 0, "fz_xml");
6875
6876 fz_try(ctx)
6877 dom = fz_dom_previous(ctx, dom);
6878 fz_catch(ctx)
6879 rethrow(J);
6880
6881 ffi_pushdom(J, dom);
6882 }
6883
6884 static void ffi_DOM_addAttribute(js_State *J)
6885 {
6886 fz_context *ctx = js_getcontext(J);
6887 fz_xml *dom = js_touserdata(J, 0, "fz_xml");
6888 const char *att = js_tostring(J, 1);
6889 const char *val = js_tostring(J, 2);
6890
6891 fz_try(ctx)
6892 fz_dom_add_attribute(ctx, dom, att, val);
6893 fz_catch(ctx)
6894 rethrow(J);
6895
6896 ffi_pushdom(J, dom);
6897 }
6898
6899 static void ffi_DOM_removeAttribute(js_State *J)
6900 {
6901 fz_context *ctx = js_getcontext(J);
6902 fz_xml *dom = js_touserdata(J, 0, "fz_xml");
6903 const char *att = js_tostring(J, 1);
6904
6905 fz_try(ctx)
6906 fz_dom_remove_attribute(ctx, dom, att);
6907 fz_catch(ctx)
6908 rethrow(J);
6909
6910 ffi_pushdom(J, dom);
6911 }
6912
6913 static void ffi_DOM_getAttribute(js_State *J)
6914 {
6915 fz_context *ctx = js_getcontext(J);
6916 fz_xml *dom = js_touserdata(J, 0, "fz_xml");
6917 const char *att = js_tostring(J, 1);
6918 const char *val;
6919
6920 fz_try(ctx)
6921 val = fz_dom_attribute(ctx, dom, att);
6922 fz_catch(ctx)
6923 rethrow(J);
6924
6925 if (val)
6926 js_pushstring(J, val);
6927 else
6928 js_pushnull(J);
6929 }
6930
6931 static void ffi_DOM_getAttributes(js_State *J)
6932 {
6933 fz_context *ctx = js_getcontext(J);
6934 fz_xml *dom = js_touserdata(J, 0, "fz_xml");
6935 const char *att;
6936 const char *val;
6937 int i;
6938
6939 js_newobject(J);
6940
6941 i = 0;
6942 while (1)
6943 {
6944 fz_try(ctx)
6945 val = fz_dom_get_attribute(ctx, dom, i, &att);
6946 fz_catch(ctx)
6947 rethrow(J);
6948 if (att == NULL)
6949 break;
6950 js_pushstring(J, val);
6951 js_setproperty(J, -2, att);
6952 i++;
6953 }
6954 }
6955
6956 /* PDF specifics */
6957
6958 #if FZ_ENABLE_PDF
6959
6960 static pdf_obj *ffi_tonewobj(js_State *J, pdf_document *pdf, int idx)
6961 {
6962 fz_context *ctx = js_getcontext(J);
6963 pdf_obj *obj = NULL;
6964
6965 /* make sure index is absolute */
6966 if (idx < 0)
6967 idx += js_gettop(J);
6968
6969 if (js_isuserdata(J, idx, "pdf_obj"))
6970 return pdf_keep_obj(ctx, js_touserdata(J, idx, "pdf_obj"));
6971
6972 if (js_isnumber(J, idx)) {
6973 float f = js_tonumber(J, idx);
6974 fz_try(ctx)
6975 if (f == (int)f)
6976 obj = pdf_new_int(ctx, f);
6977 else
6978 obj = pdf_new_real(ctx, f);
6979 fz_catch(ctx)
6980 rethrow(J);
6981 return obj;
6982 }
6983
6984 if (js_isstring(J, idx)) {
6985 const char *s = js_tostring(J, idx);
6986 fz_try(ctx)
6987 if (s[0] == '(' && s[1] != 0)
6988 obj = pdf_new_string(ctx, s+1, strlen(s)-2);
6989 else
6990 obj = pdf_new_name(ctx, s);
6991 fz_catch(ctx)
6992 rethrow(J);
6993 return obj;
6994 }
6995
6996 if (js_isboolean(J, idx)) {
6997 return js_toboolean(J, idx) ? PDF_TRUE : PDF_FALSE;
6998 }
6999
7000 if (js_isnull(J, idx)) {
7001 return PDF_NULL;
7002 }
7003
7004 if (js_isarray(J, idx)) {
7005 int i, n = fz_maxi(0, js_getlength(J, idx));
7006 pdf_obj *val;
7007 fz_try(ctx)
7008 obj = pdf_new_array(ctx, pdf, n);
7009 fz_catch(ctx)
7010 rethrow(J);
7011 if (js_try(J)) {
7012 pdf_drop_obj(ctx, obj);
7013 js_throw(J);
7014 }
7015 for (i = 0; i < n; ++i) {
7016 js_getindex(J, idx, i);
7017 val = ffi_tonewobj(J, pdf, -1);
7018 // FIXME val leaks if fz_try() runs out of space
7019 fz_try(ctx)
7020 pdf_array_push_drop(ctx, obj, val);
7021 fz_catch(ctx)
7022 rethrow(J);
7023 js_pop(J, 1);
7024 }
7025 js_endtry(J);
7026 return obj;
7027 }
7028
7029 if (js_isobject(J, idx)) {
7030 const char *key;
7031 pdf_obj *val;
7032 fz_try(ctx)
7033 obj = pdf_new_dict(ctx, pdf, 0);
7034 fz_catch(ctx)
7035 rethrow(J);
7036 if (js_try(J)) {
7037 pdf_drop_obj(ctx, obj);
7038 js_throw(J);
7039 }
7040 js_pushiterator(J, idx, 1);
7041 while ((key = js_nextiterator(J, -1))) {
7042 js_getproperty(J, idx, key);
7043 val = ffi_tonewobj(J, pdf, -1);
7044 // FIXME val leaks if fz_try() runs out of space
7045 fz_try(ctx)
7046 pdf_dict_puts_drop(ctx, obj, key, val);
7047 fz_catch(ctx)
7048 rethrow(J);
7049 js_pop(J, 1);
7050 }
7051 js_pop(J, 1);
7052 js_endtry(J);
7053 return obj;
7054 }
7055
7056 js_error(J, "cannot convert JS type to PDF");
7057 }
7058
7059 static int ffi_pdf_obj_has(js_State *J, void *obj, const char *key)
7060 {
7061 fz_context *ctx = js_getcontext(J);
7062 pdf_obj *val = NULL;
7063 int idx, len = 0;
7064
7065 if (!strcmp(key, "length")) {
7066 fz_try(ctx)
7067 len = pdf_array_len(ctx, obj);
7068 fz_catch(ctx)
7069 rethrow(J);
7070 js_pushnumber(J, len);
7071 return 1;
7072 }
7073
7074 if (is_number(key, &idx)) {
7075 fz_try(ctx)
7076 val = pdf_array_get(ctx, obj, idx);
7077 fz_catch(ctx)
7078 rethrow(J);
7079 } else {
7080 fz_try(ctx)
7081 val = pdf_dict_gets(ctx, obj, key);
7082 fz_catch(ctx)
7083 rethrow(J);
7084 }
7085 if (val) {
7086 ffi_pushobj(J, pdf_keep_obj(ctx, val));
7087 return 1;
7088 }
7089 return 0;
7090 }
7091
7092 static int ffi_pdf_obj_put(js_State *J, void *obj, const char *key)
7093 {
7094 fz_context *ctx = js_getcontext(J);
7095 pdf_document *pdf = NULL;
7096 pdf_obj *val;
7097 int idx;
7098
7099 fz_try(ctx)
7100 pdf = pdf_get_bound_document(ctx, obj);
7101 fz_catch(ctx)
7102 rethrow(J);
7103
7104 val = ffi_tonewobj(J, pdf, -1);
7105
7106 if (is_number(key, &idx)) {
7107 fz_try(ctx)
7108 pdf_array_put(ctx, obj, idx, val);
7109 fz_always(ctx)
7110 pdf_drop_obj(ctx, val);
7111 fz_catch(ctx)
7112 rethrow(J);
7113 } else {
7114 fz_try(ctx)
7115 pdf_dict_puts(ctx, obj, key, val);
7116 fz_always(ctx)
7117 pdf_drop_obj(ctx, val);
7118 fz_catch(ctx)
7119 rethrow(J);
7120 }
7121 return 1;
7122 }
7123
7124 static int ffi_pdf_obj_delete(js_State *J, void *obj, const char *key)
7125 {
7126 fz_context *ctx = js_getcontext(J);
7127 int idx;
7128
7129 if (is_number(key, &idx)) {
7130 fz_try(ctx)
7131 pdf_array_delete(ctx, obj, idx);
7132 fz_catch(ctx)
7133 rethrow(J);
7134 } else {
7135 fz_try(ctx)
7136 pdf_dict_dels(ctx, obj, key);
7137 fz_catch(ctx)
7138 rethrow(J);
7139 }
7140 return 1;
7141 }
7142
7143 static void ffi_pushobj(js_State *J, pdf_obj *obj)
7144 {
7145 if (obj) {
7146 js_getregistry(J, "pdf_obj");
7147 js_newuserdatax(J, "pdf_obj", obj,
7148 ffi_pdf_obj_has, ffi_pdf_obj_put, ffi_pdf_obj_delete,
7149 ffi_gc_pdf_obj);
7150 } else {
7151 js_pushnull(J);
7152 }
7153 }
7154
7155 static void ffi_new_PDFDocument(js_State *J)
7156 {
7157 fz_context *ctx = js_getcontext(J);
7158 const char *filename = js_iscoercible(J, 1) ? js_tostring(J, 1) : NULL;
7159 pdf_document *pdf = NULL;
7160
7161 fz_try(ctx)
7162 if (filename)
7163 pdf = pdf_open_document(ctx, filename);
7164 else
7165 pdf = pdf_create_document(ctx);
7166 fz_catch(ctx)
7167 rethrow(J);
7168
7169 js_getregistry(J, "pdf_document");
7170 js_newuserdata(J, "pdf_document", pdf, ffi_gc_pdf_document);
7171 }
7172
7173 static void ffi_PDFDocument_getVersion(js_State *J)
7174 {
7175 fz_context *ctx = js_getcontext(J);
7176 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
7177 int version;
7178
7179 fz_try(ctx)
7180 version = pdf_version(ctx, pdf);
7181 fz_catch(ctx)
7182 rethrow(J);
7183
7184 js_pushnumber(J, version);
7185 }
7186
7187 static void ffi_PDFDocument_getTrailer(js_State *J)
7188 {
7189 fz_context *ctx = js_getcontext(J);
7190 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
7191 pdf_obj *trailer = NULL;
7192
7193 fz_try(ctx)
7194 trailer = pdf_trailer(ctx, pdf);
7195 fz_catch(ctx)
7196 rethrow(J);
7197
7198 ffi_pushobj(J, pdf_keep_obj(ctx, trailer));
7199 }
7200
7201 static void ffi_PDFDocument_countObjects(js_State *J)
7202 {
7203 fz_context *ctx = js_getcontext(J);
7204 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
7205 int count = 0;
7206
7207 fz_try(ctx)
7208 count = pdf_xref_len(ctx, pdf);
7209 fz_catch(ctx)
7210 rethrow(J);
7211
7212 js_pushnumber(J, count);
7213 }
7214
7215 static void ffi_PDFDocument_createObject(js_State *J)
7216 {
7217 fz_context *ctx = js_getcontext(J);
7218 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
7219 pdf_obj *ind = NULL;
7220
7221 fz_try(ctx)
7222 ind = pdf_new_indirect(ctx, pdf, pdf_create_object(ctx, pdf), 0);
7223 fz_catch(ctx)
7224 rethrow(J);
7225
7226 ffi_pushobj(J, ind);
7227 }
7228
7229 static void ffi_PDFDocument_deleteObject(js_State *J)
7230 {
7231 fz_context *ctx = js_getcontext(J);
7232 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
7233 pdf_obj *ind = js_isuserdata(J, 1, "pdf_obj") ? js_touserdata(J, 1, "pdf_obj") : NULL;
7234 int num = ind ? pdf_to_num(ctx, ind) : js_tointeger(J, 1);
7235
7236 fz_try(ctx)
7237 pdf_delete_object(ctx, pdf, num);
7238 fz_catch(ctx)
7239 rethrow(J);
7240 }
7241
7242 static void ffi_PDFDocument_addObject(js_State *J)
7243 {
7244 fz_context *ctx = js_getcontext(J);
7245 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
7246 pdf_obj *obj = ffi_tonewobj(J, pdf, 1);
7247 pdf_obj *ind = NULL;
7248
7249 // FIXME if fz_try() runs out of space, obj leaks
7250 fz_try(ctx)
7251 ind = pdf_add_object_drop(ctx, pdf, obj);
7252 fz_catch(ctx)
7253 rethrow(J);
7254
7255 ffi_pushobj(J, ind);
7256 }
7257
7258 static void ffi_PDFDocument_addStream_imp(js_State *J, int compressed)
7259 {
7260 fz_context *ctx = js_getcontext(J);
7261 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
7262 pdf_obj *obj;
7263 fz_buffer *buf;
7264 pdf_obj *ind = NULL;
7265
7266 obj = js_iscoercible(J, 2) ? ffi_tonewobj(J, pdf, 2) : NULL;
7267 if (js_try(J)) {
7268 pdf_drop_obj(ctx, obj);
7269 js_throw(J);
7270 }
7271 buf = ffi_tonewbuffer(J, 1);
7272 js_endtry(J);
7273
7274 fz_try(ctx)
7275 ind = pdf_add_stream(ctx, pdf, buf, obj, compressed);
7276 fz_always(ctx) {
7277 fz_drop_buffer(ctx, buf);
7278 pdf_drop_obj(ctx, obj);
7279 } fz_catch(ctx)
7280 rethrow(J);
7281
7282 ffi_pushobj(J, ind);
7283 }
7284
7285 static void ffi_PDFDocument_addStream(js_State *J)
7286 {
7287 ffi_PDFDocument_addStream_imp(J, 0);
7288 }
7289
7290 static void ffi_PDFDocument_addRawStream(js_State *J)
7291 {
7292 ffi_PDFDocument_addStream_imp(J, 1);
7293 }
7294
7295 static void ffi_PDFDocument_addEmbeddedFile(js_State *J)
7296 {
7297 fz_context *ctx = js_getcontext(J);
7298 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
7299 const char *filename = js_iscoercible(J, 1) ? js_tostring(J, 1) : NULL;
7300 const char *mimetype = js_iscoercible(J, 2) ? js_tostring(J, 2) : NULL;
7301 fz_buffer *contents = ffi_tonewbuffer(J, 3);
7302 double created = js_trynumber(J, 4, -1);
7303 double modified = js_trynumber(J, 5, -1);
7304 int add_checksum = js_tryboolean(J, 6, 0);
7305 pdf_obj *ind = NULL;
7306
7307 if (created >= 0) created /= 1000;
7308 if (modified >= 0) modified /= 1000;
7309
7310 fz_try(ctx)
7311 ind = pdf_add_embedded_file(ctx, pdf, filename, mimetype, contents,
7312 created, modified, add_checksum);
7313 fz_always(ctx)
7314 fz_drop_buffer(ctx, contents);
7315 fz_catch(ctx)
7316 {
7317 pdf_drop_obj(ctx, ind);
7318 rethrow(J);
7319 }
7320
7321 ffi_pushobj(J, ind);
7322 }
7323
7324 static void ffi_pushfilespecparams(js_State *J, pdf_filespec_params *params)
7325 {
7326 js_newobject(J);
7327 if (params->filename)
7328 js_pushstring(J, params->filename);
7329 else
7330 js_pushundefined(J);
7331 js_setproperty(J, -2, "filename");
7332 if (params->mimetype)
7333 js_pushstring(J, params->mimetype);
7334 else
7335 js_pushundefined(J);
7336 js_setproperty(J, -2, "mimetype");
7337 if (params->size >= 0)
7338 js_pushnumber(J, params->size);
7339 else
7340 js_pushundefined(J);
7341 js_setproperty(J, -2, "size");
7342 if (params->created >= 0)
7343 {
7344 js_getglobal(J, "Date");
7345 js_pushnumber(J, params->created * 1000);
7346 js_construct(J, 1);
7347 }
7348 else
7349 js_pushundefined(J);
7350 js_setproperty(J, -2, "creationDate");
7351 if (params->modified >= 0)
7352 {
7353 js_getglobal(J, "Date");
7354 js_pushnumber(J, params->modified * 1000);
7355 js_construct(J, 1);
7356 }
7357 else
7358 js_pushundefined(J);
7359 js_setproperty(J, -2, "modificationDate");
7360 }
7361
7362 static void ffi_PDFDocument_getFilespecParams(js_State *J)
7363 {
7364 fz_context *ctx = js_getcontext(J);
7365 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
7366 pdf_obj *fs = ffi_tonewobj(J, pdf, 1);
7367 pdf_filespec_params params;
7368
7369 fz_try(ctx)
7370 pdf_get_filespec_params(ctx, fs, &params);
7371 fz_always(ctx)
7372 pdf_drop_obj(ctx, fs);
7373 fz_catch(ctx)
7374 rethrow(J);
7375
7376 ffi_pushfilespecparams(J, &params);
7377 }
7378
7379 static void ffi_PDFDocument_getEmbeddedFileContents(js_State *J)
7380 {
7381 fz_context *ctx = js_getcontext(J);
7382 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
7383 pdf_obj *fs = ffi_tonewobj(J, pdf, 1);
7384 fz_buffer *contents = NULL;
7385
7386 fz_try(ctx)
7387 contents = pdf_load_embedded_file_contents(ctx, fs);
7388 fz_always(ctx)
7389 pdf_drop_obj(ctx, fs);
7390 fz_catch(ctx)
7391 rethrow(J);
7392
7393 if (contents)
7394 ffi_pushbuffer_own(J, contents);
7395 else
7396 js_pushnull(J);
7397 }
7398
7399 static void ffi_PDFDocument_verifyEmbeddedFileChecksum(js_State *J)
7400 {
7401 fz_context *ctx = js_getcontext(J);
7402 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
7403 pdf_obj *fs = ffi_tonewobj(J, pdf, 1);
7404 int valid = 0;
7405
7406 fz_try(ctx)
7407 valid = pdf_verify_embedded_file_checksum(ctx, fs);
7408 fz_always(ctx)
7409 pdf_drop_obj(ctx, fs);
7410 fz_catch(ctx)
7411 rethrow(J);
7412
7413 js_pushboolean(J, valid);
7414 }
7415
7416 static void ffi_PDFDocument_isFilespec(js_State *J)
7417 {
7418 fz_context *ctx = js_getcontext(J);
7419 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
7420 pdf_obj *fs = ffi_tonewobj(J, pdf, 1);
7421 int result = 0;
7422 fz_try(ctx)
7423 result = pdf_is_filespec(ctx, fs);
7424 fz_catch(ctx)
7425 rethrow(J);
7426 js_pushboolean(J, result);
7427 }
7428
7429 static void ffi_PDFDocument_isEmbeddedFile(js_State *J)
7430 {
7431 fz_context *ctx = js_getcontext(J);
7432 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
7433 pdf_obj *fs = ffi_tonewobj(J, pdf, 1);
7434 int result = 0;
7435
7436 fz_try(ctx)
7437 result = pdf_is_embedded_file(ctx, fs);
7438 fz_always(ctx)
7439 pdf_drop_obj(ctx, fs);
7440 fz_catch(ctx)
7441 rethrow(J);
7442
7443 js_pushboolean(J, result);
7444 }
7445
7446 static void ffi_PDFDocument_addImage(js_State *J)
7447 {
7448 fz_context *ctx = js_getcontext(J);
7449 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
7450 fz_image *image = js_touserdata(J, 1, "fz_image");
7451 pdf_obj *ind = NULL;
7452
7453 fz_try(ctx)
7454 ind = pdf_add_image(ctx, pdf, image);
7455 fz_catch(ctx)
7456 rethrow(J);
7457
7458 ffi_pushobj(J, ind);
7459 }
7460
7461 static void ffi_PDFDocument_loadImage(js_State *J)
7462 {
7463 fz_context *ctx = js_getcontext(J);
7464 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
7465 pdf_obj *obj = ffi_tonewobj(J, pdf, 1);
7466 fz_image *img = NULL;
7467
7468 fz_try(ctx)
7469 img = pdf_load_image(ctx, pdf, obj);
7470 fz_always(ctx)
7471 pdf_drop_obj(ctx, obj);
7472 fz_catch(ctx)
7473 rethrow(J);
7474
7475 ffi_pushimage_own(J, img);
7476 }
7477
7478 static void ffi_PDFDocument_addSimpleFont(js_State *J)
7479 {
7480 fz_context *ctx = js_getcontext(J);
7481 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
7482 fz_font *font = js_touserdata(J, 1, "fz_font");
7483 const char *encname = js_tostring(J, 2);
7484 pdf_obj *ind = NULL;
7485 int enc = PDF_SIMPLE_ENCODING_LATIN;
7486
7487 if (!strcmp(encname, "Latin") || !strcmp(encname, "Latn"))
7488 enc = PDF_SIMPLE_ENCODING_LATIN;
7489 else if (!strcmp(encname, "Greek") || !strcmp(encname, "Grek"))
7490 enc = PDF_SIMPLE_ENCODING_GREEK;
7491 else if (!strcmp(encname, "Cyrillic") || !strcmp(encname, "Cyrl"))
7492 enc = PDF_SIMPLE_ENCODING_CYRILLIC;
7493
7494 fz_try(ctx)
7495 ind = pdf_add_simple_font(ctx, pdf, font, enc);
7496 fz_catch(ctx)
7497 rethrow(J);
7498
7499 ffi_pushobj(J, ind);
7500 }
7501
7502 static void ffi_PDFDocument_addCJKFont(js_State *J)
7503 {
7504 fz_context *ctx = js_getcontext(J);
7505 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
7506 fz_font *font = js_touserdata(J, 1, "fz_font");
7507 const char *lang = js_tostring(J, 2);
7508 int wmode = js_iscoercible(J, 3) ? js_tointeger(J, 3) : 0;
7509 int serif = js_iscoercible(J, 4) ? js_toboolean(J, 4) : 1;
7510 int ordering = fz_lookup_cjk_ordering_by_language(lang);
7511 pdf_obj *ind = NULL;
7512
7513 fz_try(ctx)
7514 ind = pdf_add_cjk_font(ctx, pdf, font, ordering, wmode, serif);
7515 fz_catch(ctx)
7516 rethrow(J);
7517
7518 ffi_pushobj(J, ind);
7519 }
7520
7521 static void ffi_PDFDocument_addFont(js_State *J)
7522 {
7523 fz_context *ctx = js_getcontext(J);
7524 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
7525 fz_font *font = js_touserdata(J, 1, "fz_font");
7526 pdf_obj *ind = NULL;
7527
7528 fz_try(ctx)
7529 ind = pdf_add_cid_font(ctx, pdf, font);
7530 fz_catch(ctx)
7531 rethrow(J);
7532
7533 ffi_pushobj(J, ind);
7534 }
7535
7536 static void ffi_PDFDocument_addPage(js_State *J)
7537 {
7538 fz_context *ctx = js_getcontext(J);
7539 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
7540 fz_rect mediabox = ffi_torect(J, 1);
7541 int rotate = js_tointeger(J, 2);
7542 pdf_obj *resources;
7543 fz_buffer *contents = NULL;
7544 pdf_obj *ind = NULL;
7545
7546 resources = ffi_tonewobj(J, pdf, 3);
7547 if (js_try(J)) {
7548 pdf_drop_obj(ctx, resources);
7549 js_throw(J);
7550 }
7551 contents = ffi_tonewbuffer(J, 4);
7552 js_endtry(J);
7553
7554 fz_try(ctx)
7555 ind = pdf_add_page(ctx, pdf, mediabox, rotate, resources, contents);
7556 fz_always(ctx) {
7557 fz_drop_buffer(ctx, contents);
7558 pdf_drop_obj(ctx, resources);
7559 } fz_catch(ctx)
7560 rethrow(J);
7561
7562 ffi_pushobj(J, ind);
7563 }
7564
7565 static void ffi_PDFDocument_insertPage(js_State *J)
7566 {
7567 fz_context *ctx = js_getcontext(J);
7568 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
7569 int at = js_tointeger(J, 1);
7570 pdf_obj *obj = ffi_tonewobj(J, pdf, 2);
7571
7572 fz_try(ctx)
7573 pdf_insert_page(ctx, pdf, at, obj);
7574 fz_always(ctx)
7575 pdf_drop_obj(ctx, obj);
7576 fz_catch(ctx)
7577 rethrow(J);
7578 }
7579
7580 static void ffi_PDFDocument_deletePage(js_State *J)
7581 {
7582 fz_context *ctx = js_getcontext(J);
7583 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
7584 int at = js_tointeger(J, 1);
7585
7586 fz_try(ctx)
7587 pdf_delete_page(ctx, pdf, at);
7588 fz_catch(ctx)
7589 rethrow(J);
7590 }
7591
7592 static void ffi_PDFDocument_countPages(js_State *J)
7593 {
7594 fz_context *ctx = js_getcontext(J);
7595 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
7596 int count = 0;
7597
7598 fz_try(ctx)
7599 count = pdf_count_pages(ctx, pdf);
7600 fz_catch(ctx)
7601 rethrow(J);
7602
7603 js_pushnumber(J, count);
7604 }
7605
7606 static void ffi_PDFDocument_findPage(js_State *J)
7607 {
7608 fz_context *ctx = js_getcontext(J);
7609 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
7610 int at = js_tointeger(J, 1);
7611 pdf_obj *obj = NULL;
7612
7613 fz_try(ctx)
7614 obj = pdf_lookup_page_obj(ctx, pdf, at);
7615 fz_catch(ctx)
7616 rethrow(J);
7617
7618 ffi_pushobj(J, pdf_keep_obj(ctx, obj));
7619 }
7620
7621 static void ffi_PDFDocument_findPageNumber(js_State *J)
7622 {
7623 fz_context *ctx = js_getcontext(J);
7624 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
7625 pdf_obj *ref = js_touserdata(J, 1, "pdf_obj");
7626 int num = 0;
7627
7628 fz_try(ctx)
7629 num = pdf_lookup_page_number(ctx, pdf, ref);
7630 fz_catch(ctx)
7631 rethrow(J);
7632
7633 js_pushnumber(J, num);
7634 }
7635
7636 static void ffi_PDFDocument_lookupDest(js_State *J)
7637 {
7638 fz_context *ctx = js_getcontext(J);
7639 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
7640 pdf_obj *needle = ffi_tonewobj(J, pdf, 1);
7641 pdf_obj *obj = NULL;
7642
7643 fz_try(ctx)
7644 obj = pdf_lookup_dest(ctx, pdf, needle);
7645 fz_always(ctx)
7646 pdf_drop_obj(ctx, needle);
7647 fz_catch(ctx)
7648 rethrow(J);
7649
7650 ffi_pushobj(J, pdf_keep_obj(ctx, obj));
7651 }
7652
7653 static void ffi_PDFDocument_save(js_State *J)
7654 {
7655 fz_context *ctx = js_getcontext(J);
7656 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
7657 const char *filename = js_tostring(J, 1);
7658 const char *options = js_iscoercible(J, 2) ? js_tostring(J, 2) : NULL;
7659 pdf_write_options pwo;
7660
7661 fz_try(ctx) {
7662 pdf_parse_write_options(ctx, &pwo, options);
7663 pdf_save_document(ctx, pdf, filename, &pwo);
7664 } fz_catch(ctx)
7665 rethrow(J);
7666 }
7667
7668 static void ffi_PDFDocument_saveToBuffer(js_State *J)
7669 {
7670 fz_context *ctx = js_getcontext(J);
7671 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
7672 const char *options = js_iscoercible(J, 1) ? js_tostring(J, 1) : NULL;
7673 pdf_write_options pwo;
7674 fz_buffer *buf;
7675 fz_output *out;
7676
7677 fz_try(ctx)
7678 {
7679 buf = fz_new_buffer(ctx, 32 << 10);
7680 out = fz_new_output_with_buffer(ctx, buf);
7681 pdf_parse_write_options(ctx, &pwo, options);
7682 pdf_write_document(ctx, pdf, out, &pwo);
7683 fz_close_output(ctx, out);
7684 }
7685 fz_always(ctx)
7686 fz_drop_output(ctx, out);
7687 fz_catch(ctx)
7688 {
7689 fz_drop_buffer(ctx, buf);
7690 rethrow(J);
7691 }
7692 ffi_pushbuffer_own(J, buf);
7693 }
7694
7695 static void ffi_PDFDocument_rearrangePages(js_State *J)
7696 {
7697 fz_context *ctx = js_getcontext(J);
7698 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
7699 int n = fz_maxi(0, js_getlength(J, 1));
7700 int *pages = NULL;
7701 int i;
7702
7703 fz_try(ctx)
7704 pages = fz_malloc_array(ctx, n, int);
7705 fz_catch(ctx)
7706 rethrow(J);
7707
7708 if (js_try(J)) {
7709 fz_free(ctx, pages);
7710 js_throw(J);
7711 }
7712
7713 for (i = 0; i < n; ++i)
7714 {
7715 js_getindex(J, 1, i);
7716 pages[i] = js_tointeger(J, -1);
7717 js_pop(J, 1);
7718 }
7719
7720 js_endtry(J);
7721
7722 fz_try(ctx)
7723 pdf_rearrange_pages(ctx, pdf, n, pages, PDF_CLEAN_STRUCTURE_DROP);
7724 fz_always(ctx)
7725 fz_free(ctx, pages);
7726 fz_catch(ctx)
7727 rethrow(J);
7728 }
7729
7730 static void ffi_PDFDocument_newNull(js_State *J)
7731 {
7732 ffi_pushobj(J, PDF_NULL);
7733 }
7734
7735 static void ffi_PDFDocument_newBoolean(js_State *J)
7736 {
7737 int val = js_toboolean(J, 1);
7738 ffi_pushobj(J, val ? PDF_TRUE : PDF_FALSE);
7739 }
7740
7741 static void ffi_PDFDocument_newInteger(js_State *J)
7742 {
7743 fz_context *ctx = js_getcontext(J);
7744 int val = js_tointeger(J, 1);
7745 pdf_obj *obj = NULL;
7746 fz_try(ctx)
7747 obj = pdf_new_int(ctx, val);
7748 fz_catch(ctx)
7749 rethrow(J);
7750 ffi_pushobj(J, obj);
7751 }
7752
7753 static void ffi_PDFDocument_newReal(js_State *J)
7754 {
7755 fz_context *ctx = js_getcontext(J);
7756 float val = js_tonumber(J, 1);
7757 pdf_obj *obj = NULL;
7758 fz_try(ctx)
7759 obj = pdf_new_real(ctx, val);
7760 fz_catch(ctx)
7761 rethrow(J);
7762 ffi_pushobj(J, obj);
7763 }
7764
7765 static void ffi_PDFDocument_newString(js_State *J)
7766 {
7767 fz_context *ctx = js_getcontext(J);
7768 const char *val = js_tostring(J, 1);
7769 pdf_obj *obj = NULL;
7770
7771 fz_try(ctx)
7772 obj = pdf_new_text_string(ctx, val);
7773 fz_catch(ctx)
7774 rethrow(J);
7775 ffi_pushobj(J, obj);
7776 }
7777
7778 static void ffi_PDFDocument_newByteString(js_State *J)
7779 {
7780 fz_context *ctx = js_getcontext(J);
7781 int n, i;
7782 char *buf;
7783 pdf_obj *obj = NULL;
7784
7785 n = fz_maxi(0, js_getlength(J, 1));
7786
7787 fz_try(ctx)
7788 buf = fz_malloc(ctx, n);
7789 fz_catch(ctx)
7790 rethrow(J);
7791
7792 if (js_try(J)) {
7793 fz_free(ctx, buf);
7794 js_throw(J);
7795 }
7796
7797 for (i = 0; i < n; ++i) {
7798 js_getindex(J, 1, i);
7799 buf[i] = js_tointeger(J, -1);
7800 js_pop(J, 1);
7801 }
7802
7803 js_endtry(J);
7804
7805 fz_try(ctx)
7806 obj = pdf_new_string(ctx, buf, n);
7807 fz_always(ctx)
7808 fz_free(ctx, buf);
7809 fz_catch(ctx)
7810 rethrow(J);
7811 ffi_pushobj(J, obj);
7812 }
7813
7814 static void ffi_PDFDocument_newName(js_State *J)
7815 {
7816 fz_context *ctx = js_getcontext(J);
7817 const char *val = js_tostring(J, 1);
7818 pdf_obj *obj = NULL;
7819 fz_try(ctx)
7820 obj = pdf_new_name(ctx, val);
7821 fz_catch(ctx)
7822 rethrow(J);
7823 ffi_pushobj(J, obj);
7824 }
7825
7826 static void ffi_PDFDocument_newIndirect(js_State *J)
7827 {
7828 fz_context *ctx = js_getcontext(J);
7829 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
7830 int num = js_tointeger(J, 1);
7831 int gen = js_tointeger(J, 2);
7832 pdf_obj *obj = NULL;
7833 fz_try(ctx)
7834 obj = pdf_new_indirect(ctx, pdf, num, gen);
7835 fz_catch(ctx)
7836 rethrow(J);
7837 ffi_pushobj(J, obj);
7838 }
7839
7840 static void ffi_PDFDocument_newArray(js_State *J)
7841 {
7842 fz_context *ctx = js_getcontext(J);
7843 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
7844 int cap = js_iscoercible(J, 1) ? js_tointeger(J, 1) : 8;
7845 pdf_obj *obj = NULL;
7846 fz_try(ctx)
7847 obj = pdf_new_array(ctx, pdf, cap);
7848 fz_catch(ctx)
7849 rethrow(J);
7850 ffi_pushobj(J, obj);
7851 }
7852
7853 static void ffi_PDFDocument_newDictionary(js_State *J)
7854 {
7855 fz_context *ctx = js_getcontext(J);
7856 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
7857 int cap = js_iscoercible(J, 1) ? js_tointeger(J, 1) : 8;
7858 pdf_obj *obj = NULL;
7859 fz_try(ctx)
7860 obj = pdf_new_dict(ctx, pdf, cap);
7861 fz_catch(ctx)
7862 rethrow(J);
7863 ffi_pushobj(J, obj);
7864 }
7865
7866 static void ffi_PDFDocument_enableJS(js_State *J)
7867 {
7868 fz_context *ctx = js_getcontext(J);
7869 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
7870 fz_try(ctx)
7871 pdf_enable_js(ctx, pdf);
7872 fz_catch(ctx)
7873 rethrow(J);
7874 }
7875
7876 static void ffi_PDFDocument_disableJS(js_State *J)
7877 {
7878 fz_context *ctx = js_getcontext(J);
7879 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
7880 fz_try(ctx)
7881 pdf_disable_js(ctx, pdf);
7882 fz_catch(ctx)
7883 rethrow(J);
7884 }
7885
7886 static void ffi_PDFDocument_isJSSupported(js_State *J)
7887 {
7888 fz_context *ctx = js_getcontext(J);
7889 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
7890 int supported = 0;
7891 fz_try(ctx)
7892 supported = pdf_js_supported(ctx, pdf);
7893 fz_catch(ctx)
7894 rethrow(J);
7895 js_pushboolean(J, supported);
7896 }
7897
7898 static void ffi_PDFDocument_countVersions(js_State *J)
7899 {
7900 fz_context *ctx = js_getcontext(J);
7901 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
7902 int val = 0;
7903 fz_try(ctx)
7904 val = pdf_count_versions(ctx, pdf);
7905 fz_catch(ctx)
7906 rethrow(J);
7907 js_pushnumber(J, val);
7908 }
7909
7910 static void ffi_PDFDocument_countUnsavedVersions(js_State *J)
7911 {
7912 fz_context *ctx = js_getcontext(J);
7913 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
7914 int val = 0;
7915 fz_try(ctx)
7916 val = pdf_count_unsaved_versions(ctx, pdf);
7917 fz_catch(ctx)
7918 rethrow(J);
7919 js_pushnumber(J, val);
7920 }
7921
7922 static void ffi_PDFDocument_validateChangeHistory(js_State *J)
7923 {
7924 fz_context *ctx = js_getcontext(J);
7925 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
7926 int val = 0;
7927 fz_try(ctx)
7928 val = pdf_validate_change_history(ctx, pdf);
7929 fz_catch(ctx)
7930 rethrow(J);
7931 js_pushnumber(J, val);
7932 }
7933
7934 static void ffi_PDFDocument_wasPureXFA(js_State *J)
7935 {
7936 fz_context *ctx = js_getcontext(J);
7937 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
7938 int val = 0;
7939 fz_try(ctx)
7940 val = pdf_was_pure_xfa(ctx, pdf);
7941 fz_catch(ctx)
7942 rethrow(J);
7943 js_pushboolean(J, val);
7944 }
7945
7946 static void free_event_cb_data(fz_context *ctx, void *data)
7947 {
7948 js_State *J = ((struct event_cb_data *) data)->J;
7949 const char *listener = ((struct event_cb_data *) data)->listener;
7950
7951 if (listener)
7952 js_unref(J, listener);
7953 fz_free(ctx, data);
7954 }
7955
7956 static void event_cb(fz_context *ctx, pdf_document *doc, pdf_doc_event *evt, void *data)
7957 {
7958 js_State *J = ((struct event_cb_data *) data)->J;
7959 const char *listener = ((struct event_cb_data *) data)->listener;
7960
7961 switch (evt->type)
7962 {
7963 case PDF_DOCUMENT_EVENT_ALERT:
7964 {
7965 pdf_alert_event *alert = pdf_access_alert_event(ctx, evt);
7966
7967 if (js_try(J))
7968 rethrow_as_fz(J);
7969
7970 js_getregistry(J, listener);
7971 if (js_hasproperty(J, -1, "onAlert"))
7972 {
7973 js_pushnull(J);
7974 js_pushstring(J, alert->message);
7975 js_pcall(J, 1);
7976 js_pop(J, 1);
7977 }
7978 js_endtry(J);
7979 }
7980 break;
7981
7982 default:
7983 fz_throw(ctx, FZ_ERROR_UNSUPPORTED, "event not yet implemented");
7984 break;
7985 }
7986 }
7987
7988 static void ffi_PDFDocument_setJSEventListener(js_State *J)
7989 {
7990 fz_context *ctx = js_getcontext(J);
7991 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
7992 struct event_cb_data *data = NULL;
7993
7994 fz_try(ctx)
7995 data = fz_calloc(ctx, 1, sizeof (struct event_cb_data));
7996 fz_catch(ctx)
7997 rethrow(J);
7998
7999 if (js_try(J)) {
8000 if (data->listener)
8001 js_unref(J, data->listener);
8002 fz_free(ctx, data);
8003 js_throw(J);
8004 }
8005 js_copy(J, 1);
8006 data->listener = js_ref(J);
8007 data->J = J;
8008 js_endtry(J);
8009
8010 fz_try(ctx)
8011 pdf_set_doc_event_callback(ctx, pdf, event_cb, free_event_cb_data, data);
8012 fz_catch(ctx)
8013 rethrow(J);
8014 }
8015
8016 static void ffi_PDFDocument_hasUnsavedChanges(js_State *J)
8017 {
8018 fz_context *ctx = js_getcontext(J);
8019 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
8020 int val = 0;
8021 fz_try(ctx)
8022 val = pdf_has_unsaved_changes(ctx, pdf);
8023 fz_catch(ctx)
8024 rethrow(J);
8025 js_pushboolean(J, val);
8026 }
8027
8028 static void ffi_PDFDocument_wasRepaired(js_State *J)
8029 {
8030 fz_context *ctx = js_getcontext(J);
8031 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
8032 int val = 0;
8033 fz_try(ctx)
8034 val = pdf_was_repaired(ctx, pdf);
8035 fz_catch(ctx)
8036 rethrow(J);
8037 js_pushboolean(J, val);
8038 }
8039
8040 static void ffi_PDFDocument_canBeSavedIncrementally(js_State *J)
8041 {
8042 fz_context *ctx = js_getcontext(J);
8043 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
8044 int val = 0;
8045 fz_try(ctx)
8046 val = pdf_can_be_saved_incrementally(ctx, pdf);
8047 fz_catch(ctx)
8048 rethrow(J);
8049 js_pushboolean(J, val);
8050 }
8051
8052 static void ffi_PDFDocument_newGraftMap(js_State *J)
8053 {
8054 fz_context *ctx = js_getcontext(J);
8055 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
8056 pdf_graft_map *map = NULL;
8057 fz_try(ctx)
8058 map = pdf_new_graft_map(ctx, pdf);
8059 fz_catch(ctx)
8060 rethrow(J);
8061 js_getregistry(J, "pdf_graft_map");
8062 js_newuserdata(J, "pdf_graft_map", map, ffi_gc_pdf_graft_map);
8063 }
8064
8065 static void ffi_PDFDocument_graftObject(js_State *J)
8066 {
8067 fz_context *ctx = js_getcontext(J);
8068 pdf_document *dst = js_touserdata(J, 0, "pdf_document");
8069 pdf_obj *obj = js_touserdata(J, 1, "pdf_obj");
8070 fz_try(ctx)
8071 obj = pdf_graft_object(ctx, dst, obj);
8072 fz_catch(ctx)
8073 rethrow(J);
8074 ffi_pushobj(J, obj);
8075 }
8076
8077 static void ffi_PDFDocument_graftPage(js_State *J)
8078 {
8079 fz_context *ctx = js_getcontext(J);
8080 pdf_document *dst = js_touserdata(J, 0, "pdf_document");
8081 int to = js_tointeger(J, 1);
8082 pdf_document *src = js_touserdata(J, 2, "pdf_document");
8083 int from = js_tointeger(J, 3);
8084 fz_try(ctx)
8085 pdf_graft_page(ctx, dst, to, src, from);
8086 fz_catch(ctx)
8087 rethrow(J);
8088 }
8089
8090 static void ffi_PDFDocument_enableJournal(js_State *J)
8091 {
8092 fz_context *ctx = js_getcontext(J);
8093 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
8094 fz_try(ctx)
8095 pdf_enable_journal(ctx, pdf);
8096 fz_catch(ctx)
8097 rethrow(J);
8098 }
8099
8100 static void ffi_PDFDocument_beginOperation(js_State *J)
8101 {
8102 fz_context *ctx = js_getcontext(J);
8103 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
8104 const char *operation = js_tostring(J, 1);
8105 fz_try(ctx)
8106 pdf_begin_operation(ctx, pdf, operation);
8107 fz_catch(ctx)
8108 rethrow(J);
8109 }
8110
8111 static void ffi_PDFDocument_beginImplicitOperation(js_State *J)
8112 {
8113 fz_context *ctx = js_getcontext(J);
8114 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
8115 fz_try(ctx)
8116 pdf_begin_implicit_operation(ctx, pdf);
8117 fz_catch(ctx)
8118 rethrow(J);
8119 }
8120
8121 static void ffi_PDFDocument_endOperation(js_State *J)
8122 {
8123 fz_context *ctx = js_getcontext(J);
8124 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
8125 fz_try(ctx)
8126 pdf_end_operation(ctx, pdf);
8127 fz_catch(ctx)
8128 rethrow(J);
8129 }
8130
8131 static void ffi_PDFDocument_abandonOperation(js_State *J)
8132 {
8133 fz_context *ctx = js_getcontext(J);
8134 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
8135 fz_try(ctx)
8136 pdf_abandon_operation(ctx, pdf);
8137 fz_catch(ctx)
8138 rethrow(J);
8139 }
8140
8141 static void ffi_PDFDocument_canUndo(js_State *J)
8142 {
8143 fz_context *ctx = js_getcontext(J);
8144 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
8145 int can;
8146 fz_try(ctx)
8147 can = pdf_can_undo(ctx, pdf);
8148 fz_catch(ctx)
8149 rethrow(J);
8150 js_pushboolean(J, can);
8151 }
8152
8153 static void ffi_PDFDocument_canRedo(js_State *J)
8154 {
8155 fz_context *ctx = js_getcontext(J);
8156 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
8157 int can;
8158 fz_try(ctx)
8159 can = pdf_can_redo(ctx, pdf);
8160 fz_catch(ctx)
8161 rethrow(J);
8162 js_pushboolean(J, can);
8163 }
8164
8165 static void ffi_PDFDocument_getJournal(js_State *J)
8166 {
8167 fz_context *ctx = js_getcontext(J);
8168 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
8169 const char *name;
8170 int i, position, count;
8171
8172 js_newobject(J);
8173
8174 fz_try(ctx)
8175 position = pdf_undoredo_state(ctx, pdf, &count);
8176 fz_catch(ctx)
8177 rethrow(J);
8178
8179 js_pushnumber(J, position);
8180 js_setproperty(J, -2, "position");
8181
8182 js_newarray(J);
8183 for (i = 0; i < count; ++i)
8184 {
8185 fz_try(ctx)
8186 name = pdf_undoredo_step(ctx, pdf, i);
8187 fz_catch(ctx)
8188 rethrow(J);
8189 js_pushstring(J, name);
8190 js_setindex(J, -2, i);
8191 }
8192 js_setproperty(J, -2, "steps");
8193 }
8194
8195 static void ffi_PDFDocument_undo(js_State *J)
8196 {
8197 fz_context *ctx = js_getcontext(J);
8198 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
8199 fz_try(ctx)
8200 pdf_undo(ctx, pdf);
8201 fz_catch(ctx)
8202 rethrow(J);
8203 }
8204
8205 static void ffi_PDFDocument_redo(js_State *J)
8206 {
8207 fz_context *ctx = js_getcontext(J);
8208 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
8209 fz_try(ctx)
8210 pdf_redo(ctx, pdf);
8211 fz_catch(ctx)
8212 rethrow(J);
8213 }
8214
8215 static void ffi_PDFDocument_saveJournal(js_State *J)
8216 {
8217 fz_context *ctx = js_getcontext(J);
8218 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
8219 const char *filename = js_tostring(J, 1);
8220 fz_output *out = NULL;
8221
8222 fz_var(out);
8223
8224 fz_try(ctx)
8225 {
8226 out = fz_new_output_with_path(ctx, filename, 0);
8227 pdf_write_journal(ctx, pdf, out);
8228 fz_close_output(ctx, out);
8229 }
8230 fz_always(ctx)
8231 fz_drop_output(ctx, out);
8232 fz_catch(ctx)
8233 rethrow(J);
8234 }
8235
8236 static void ffi_PDFDocument_subsetFonts(js_State *J)
8237 {
8238 fz_context *ctx = js_getcontext(J);
8239 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
8240 fz_try(ctx)
8241 pdf_subset_fonts(ctx, pdf, 0, NULL);
8242 fz_catch(ctx)
8243 rethrow(J);
8244 }
8245
8246 static void ffi_PDFDocument_setPageLabels(js_State *J)
8247 {
8248 fz_context *ctx = js_getcontext(J);
8249 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
8250 int index = js_tointeger(J, 1);
8251 const char *s = js_iscoercible(J, 2) ? js_tostring(J, 2) : "D";
8252 const char *p = js_iscoercible(J, 3) ? js_tostring(J, 3) : "";
8253 int st = js_iscoercible(J, 4) ? js_tointeger(J, 4) : 1;
8254 fz_try(ctx)
8255 pdf_set_page_labels(ctx, pdf, index, s[0], p, st);
8256 fz_catch(ctx)
8257 rethrow(J);
8258 }
8259
8260 static void ffi_PDFDocument_deletePageLabels(js_State *J)
8261 {
8262 fz_context *ctx = js_getcontext(J);
8263 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
8264 int index = js_tointeger(J, 1);
8265 fz_try(ctx)
8266 pdf_delete_page_labels(ctx, pdf, index);
8267 fz_catch(ctx)
8268 rethrow(J);
8269 }
8270
8271 static void ffi_PDFDocument_countLayers(js_State *J)
8272 {
8273 fz_context *ctx = js_getcontext(J);
8274 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
8275 int n = 0;
8276 fz_try(ctx)
8277 n = pdf_count_layers(ctx, pdf);
8278 fz_catch(ctx)
8279 rethrow(J);
8280 js_pushnumber(J, n);
8281 }
8282
8283 static void ffi_PDFDocument_isLayerVisible(js_State *J)
8284 {
8285 fz_context *ctx = js_getcontext(J);
8286 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
8287 int layer = js_tointeger(J, 1);
8288 int x = 0;
8289 fz_try(ctx)
8290 x = pdf_layer_is_enabled(ctx, pdf, layer);
8291 fz_catch(ctx)
8292 rethrow(J);
8293 js_pushboolean(J, x);
8294 }
8295
8296 static void ffi_PDFDocument_setLayerVisible(js_State *J)
8297 {
8298 fz_context *ctx = js_getcontext(J);
8299 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
8300 int layer = js_tointeger(J, 1);
8301 int x = js_toboolean(J, 2);
8302 fz_try(ctx)
8303 pdf_enable_layer(ctx, pdf, layer, x);
8304 fz_catch(ctx)
8305 rethrow(J);
8306 }
8307
8308 static void ffi_PDFDocument_getLayerName(js_State *J)
8309 {
8310 fz_context *ctx = js_getcontext(J);
8311 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
8312 int layer = js_tointeger(J, 1);
8313 const char *name;
8314 fz_try(ctx)
8315 name = pdf_layer_name(ctx, pdf, layer);
8316 fz_catch(ctx)
8317 rethrow(J);
8318 js_pushstring(J, name);
8319 }
8320
8321 static void ffi_PDFDocument_countAssociatedFiles(js_State *J)
8322 {
8323 fz_context *ctx = js_getcontext(J);
8324 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
8325 int n;
8326 fz_try(ctx)
8327 n = pdf_count_document_associated_files(ctx, pdf);
8328 fz_catch(ctx)
8329 rethrow(J);
8330 js_pushnumber(J, n);
8331 }
8332
8333 static void ffi_PDFDocument_associatedFile(js_State *J)
8334 {
8335 fz_context *ctx = js_getcontext(J);
8336 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
8337 int idx = js_tointeger(J, 1);
8338 pdf_obj *obj;
8339 fz_try(ctx)
8340 obj = pdf_document_associated_file(ctx, pdf, idx);
8341 fz_catch(ctx)
8342 rethrow(J);
8343 ffi_pushobj(J, obj);
8344 }
8345
8346 static void ffi_PDFDocument_zugferdProfile(js_State *J)
8347 {
8348 fz_context *ctx = js_getcontext(J);
8349 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
8350 enum pdf_zugferd_profile profile;
8351 float version;
8352 fz_try(ctx)
8353 profile = pdf_zugferd_profile(ctx, pdf, &version);
8354 fz_catch(ctx)
8355 rethrow(J);
8356 js_pushliteral(J, pdf_zugferd_profile_to_string(ctx, profile));
8357 }
8358
8359 static void ffi_PDFDocument_zugferdVersion(js_State *J)
8360 {
8361 fz_context *ctx = js_getcontext(J);
8362 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
8363 float version;
8364 fz_try(ctx)
8365 (void)pdf_zugferd_profile(ctx, pdf, &version);
8366 fz_catch(ctx)
8367 rethrow(J);
8368 js_pushnumber(J, version);
8369 }
8370
8371 static void ffi_PDFDocument_zugferdXML(js_State *J)
8372 {
8373 fz_context *ctx = js_getcontext(J);
8374 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
8375 fz_buffer *buf;
8376 fz_try(ctx)
8377 buf = pdf_zugferd_xml(ctx, pdf);
8378 fz_catch(ctx)
8379 rethrow(J);
8380 if (buf)
8381 ffi_pushbuffer_own(J, buf);
8382 else
8383 js_pushnull(J);
8384 }
8385
8386 static void ffi_PDFDocument_getLanguage(js_State *J)
8387 {
8388 fz_context *ctx = js_getcontext(J);
8389 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
8390 fz_text_language lang;
8391 const char *ret;
8392 char text[8];
8393 fz_try(ctx)
8394 {
8395 lang = pdf_document_language(ctx, pdf);
8396 ret = fz_string_from_text_language(text, lang);
8397 }
8398 fz_catch(ctx)
8399 rethrow(J);
8400
8401 if (ret)
8402 js_pushstring(J, text);
8403 else
8404 js_pushnull(J);
8405 }
8406
8407 static void ffi_PDFDocument_setLanguage(js_State *J)
8408 {
8409 fz_context *ctx = js_getcontext(J);
8410 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
8411 const char *lang = js_iscoercible(J, 1) ? js_tostring(J, 1) : NULL;
8412 fz_try(ctx)
8413 pdf_set_document_language(ctx, pdf, fz_text_language_from_string(lang));
8414 fz_catch(ctx)
8415 rethrow(J);
8416 }
8417
8418 static void ffi_PDFDocument_bake(js_State *J)
8419 {
8420 fz_context *ctx = js_getcontext(J);
8421 pdf_document *pdf = js_touserdata(J, 0, "pdf_document");
8422 int bake_annots = js_iscoercible(J, 1) ? js_toboolean(J, 1) : 1;
8423 int bake_widgets = js_iscoercible(J, 2) ? js_toboolean(J, 2) : 1;
8424 fz_try(ctx)
8425 pdf_bake_document(ctx, pdf, bake_annots, bake_widgets);
8426 fz_catch(ctx)
8427 rethrow(J);
8428 }
8429
8430 static void ffi_appendDestToURI(js_State *J)
8431 {
8432 fz_context *ctx = js_getcontext(J);
8433 const char *url = js_iscoercible(J, 1) ? js_tostring(J, 1) : NULL;
8434 const char *name = NULL;
8435 fz_link_dest dest = { 0 };
8436 char *uri = NULL;
8437
8438 if (js_isobject(J, 2))
8439 {
8440 dest = ffi_tolinkdest(J, 2);
8441 fz_try(ctx)
8442 uri = pdf_append_explicit_dest_to_uri(ctx, url, dest);
8443 fz_catch(ctx)
8444 rethrow(J);
8445 }
8446 else if (js_isnumber(J, 2))
8447 {
8448 dest = fz_make_link_dest_xyz(0, js_tointeger(J, 2) - 1, NAN, NAN, NAN);
8449 fz_try(ctx)
8450 uri = pdf_append_explicit_dest_to_uri(ctx, url, dest);
8451 fz_catch(ctx)
8452 rethrow(J);
8453 }
8454 else
8455 {
8456 name = js_tostring(J, 2);
8457 fz_try(ctx)
8458 uri = pdf_append_named_dest_to_uri(ctx, url, name);
8459 fz_catch(ctx)
8460 rethrow(J);
8461 }
8462
8463 if (js_try(J)) {
8464 fz_free(ctx, uri);
8465 js_throw(J);
8466 }
8467 if (uri)
8468 js_pushstring(J, uri);
8469 else
8470 js_pushnull(J);
8471 js_endtry(J);
8472 fz_free(ctx, uri);
8473 }
8474
8475 static void ffi_formatURIFromPathAndDest(js_State *J)
8476 {
8477 fz_context *ctx = js_getcontext(J);
8478 const char *path = js_iscoercible(J, 1) ? js_tostring(J, 1) : NULL;
8479 const char *name = NULL;
8480 fz_link_dest dest = { 0 };
8481 char *uri = NULL;
8482
8483 if (js_isobject(J, 2))
8484 {
8485 dest = ffi_tolinkdest(J, 2);
8486 fz_try(ctx)
8487 uri = pdf_new_uri_from_path_and_explicit_dest(ctx, path, dest);
8488 fz_catch(ctx)
8489 rethrow(J);
8490 }
8491 else if (js_isnumber(J, 2))
8492 {
8493 dest = fz_make_link_dest_xyz(0, js_tointeger(J, 2) - 1, NAN, NAN, NAN);
8494 fz_try(ctx)
8495 uri = pdf_new_uri_from_path_and_explicit_dest(ctx, path, dest);
8496 fz_catch(ctx)
8497 rethrow(J);
8498 }
8499 else
8500 {
8501 name = js_tostring(J, 2);
8502 fz_try(ctx)
8503 uri = pdf_new_uri_from_path_and_named_dest(ctx, path, name);
8504 fz_catch(ctx)
8505 rethrow(J);
8506 }
8507
8508 if (js_try(J)) {
8509 fz_free(ctx, uri);
8510 js_throw(J);
8511 }
8512 if (uri)
8513 js_pushstring(J, uri);
8514 else
8515 js_pushnull(J);
8516 js_endtry(J);
8517 fz_free(ctx, uri);
8518 }
8519
8520 static void ffi_PDFGraftMap_graftObject(js_State *J)
8521 {
8522 fz_context *ctx = js_getcontext(J);
8523 pdf_graft_map *map = js_touserdata(J, 0, "pdf_graft_map");
8524 pdf_obj *obj = js_touserdata(J, 1, "pdf_obj");
8525 fz_try(ctx)
8526 obj = pdf_graft_mapped_object(ctx, map, obj);
8527 fz_catch(ctx)
8528 rethrow(J);
8529 ffi_pushobj(J, obj);
8530 }
8531
8532 static void ffi_PDFGraftMap_graftPage(js_State *J)
8533 {
8534 fz_context *ctx = js_getcontext(J);
8535 pdf_graft_map *map = js_touserdata(J, 0, "pdf_graft_map");
8536 int to = js_tointeger(J, 1);
8537 pdf_document *src = js_touserdata(J, 2, "pdf_document");
8538 int from = js_tointeger(J, 3);
8539 fz_try(ctx)
8540 pdf_graft_mapped_page(ctx, map, to, src, from);
8541 fz_catch(ctx)
8542 rethrow(J);
8543 }
8544
8545 static pdf_obj *ffi_PDFObject_get_imp(js_State *J, int inheritable)
8546 {
8547 fz_context *ctx = js_getcontext(J);
8548 pdf_obj *obj = js_touserdata(J, 0, "pdf_obj");
8549 pdf_obj *val = NULL;
8550 int i, n = js_gettop(J);
8551
8552
8553 for (i = 1; i < n && obj; ++i) {
8554 if (pdf_is_array(ctx, obj)) {
8555 int key = js_tointeger(J, 1);
8556 fz_try(ctx)
8557 obj = val = pdf_array_get(ctx, obj, key);
8558 fz_catch(ctx)
8559 rethrow(J);
8560 } else if (js_isuserdata(J, i, "pdf_obj")) {
8561 pdf_obj *key = js_touserdata(J, i, "pdf_obj");
8562 fz_try(ctx)
8563 if (inheritable)
8564 obj = val = pdf_dict_get_inheritable(ctx, obj, key);
8565 else
8566 obj = val = pdf_dict_get(ctx, obj, key);
8567 fz_catch(ctx)
8568 rethrow(J);
8569 } else if (inheritable) {
8570 const char *key = js_tostring(J, i);
8571 fz_try(ctx)
8572 obj = val = pdf_dict_gets_inheritable(ctx, obj, key);
8573 fz_catch(ctx)
8574 rethrow(J);
8575 } else {
8576 const char *key = js_tostring(J, i);
8577 fz_try(ctx)
8578 obj = val = pdf_dict_gets(ctx, obj, key);
8579 fz_catch(ctx)
8580 rethrow(J);
8581 }
8582 }
8583
8584 return val;
8585 }
8586
8587 static void ffi_PDFObject_get(js_State *J)
8588 {
8589 fz_context *ctx = js_getcontext(J);
8590 pdf_obj *val = ffi_PDFObject_get_imp(J, 0);
8591 if (val)
8592 ffi_pushobj(J, pdf_keep_obj(ctx, val));
8593 else
8594 js_pushnull(J);
8595 }
8596
8597 static void ffi_PDFObject_getInheritable(js_State *J)
8598 {
8599 fz_context *ctx = js_getcontext(J);
8600 pdf_obj *val = ffi_PDFObject_get_imp(J, 1);
8601 if (val)
8602 ffi_pushobj(J, pdf_keep_obj(ctx, val));
8603 else
8604 js_pushnull(J);
8605 }
8606
8607 static void ffi_PDFObject_put(js_State *J)
8608 {
8609 pdf_obj *obj = js_touserdata(J, 0, "pdf_obj");
8610 const char *key = js_tostring(J, 1);
8611 js_copy(J, 2);
8612 ffi_pdf_obj_put(J, obj, key);
8613 }
8614
8615 static void ffi_PDFObject_delete(js_State *J)
8616 {
8617 pdf_obj *obj = js_touserdata(J, 0, "pdf_obj");
8618 const char *key = js_tostring(J, 1);
8619 ffi_pdf_obj_delete(J, obj, key);
8620 }
8621
8622 static void ffi_PDFObject_push(js_State *J)
8623 {
8624 fz_context *ctx = js_getcontext(J);
8625 pdf_obj *obj = js_touserdata(J, 0, "pdf_obj");
8626 pdf_document *pdf = pdf_get_bound_document(ctx, obj);
8627 pdf_obj *item = ffi_tonewobj(J, pdf, 1);
8628 fz_try(ctx)
8629 pdf_array_push(ctx, obj, item);
8630 fz_always(ctx)
8631 pdf_drop_obj(ctx, item);
8632 fz_catch(ctx)
8633 rethrow(J);
8634 }
8635
8636 static void ffi_PDFObject_resolve(js_State *J)
8637 {
8638 fz_context *ctx = js_getcontext(J);
8639 pdf_obj *obj = js_touserdata(J, 0, "pdf_obj");
8640 pdf_obj *ind = NULL;
8641 fz_try(ctx)
8642 ind = pdf_resolve_indirect(ctx, obj);
8643 fz_catch(ctx)
8644 rethrow(J);
8645 ffi_pushobj(J, pdf_keep_obj(ctx, ind));
8646 }
8647
8648 static void ffi_PDFObject_toString(js_State *J)
8649 {
8650 fz_context *ctx = js_getcontext(J);
8651 pdf_obj *obj = js_touserdata(J, 0, "pdf_obj");
8652 int tight = js_isdefined(J, 1) ? js_toboolean(J, 1) : 1;
8653 int ascii = js_isdefined(J, 2) ? js_toboolean(J, 2) : 0;
8654 char *s = NULL;
8655 size_t n;
8656
8657 fz_try(ctx)
8658 s = pdf_sprint_obj(ctx, NULL, 0, &n, obj, tight, ascii);
8659 fz_catch(ctx)
8660 rethrow(J);
8661
8662 if (js_try(J)) {
8663 fz_free(ctx, s);
8664 js_throw(J);
8665 }
8666 js_pushstring(J, s);
8667 js_endtry(J);
8668 fz_free(ctx, s);
8669 }
8670
8671 static void ffi_PDFObject_valueOf(js_State *J)
8672 {
8673 fz_context *ctx = js_getcontext(J);
8674 pdf_obj *obj = js_touserdata(J, 0, "pdf_obj");
8675 if (pdf_is_indirect(ctx, obj))
8676 {
8677 char buf[20];
8678 fz_snprintf(buf, sizeof buf, "%d 0 R", pdf_to_num(ctx, obj));
8679 js_pushstring(J, buf);
8680 }
8681 else if (pdf_is_null(ctx, obj))
8682 js_pushnull(J);
8683 else if (pdf_is_bool(ctx, obj))
8684 js_pushboolean(J, pdf_to_bool(ctx, obj));
8685 else if (pdf_is_int(ctx, obj))
8686 js_pushnumber(J, pdf_to_int(ctx, obj));
8687 else if (pdf_is_real(ctx, obj))
8688 js_pushnumber(J, pdf_to_real(ctx, obj));
8689 else if (pdf_is_string(ctx, obj))
8690 js_pushlstring(J, pdf_to_str_buf(ctx, obj), (int)pdf_to_str_len(ctx, obj));
8691 else if (pdf_is_name(ctx, obj))
8692 js_pushstring(J, pdf_to_name(ctx, obj));
8693 else
8694 js_copy(J, 0);
8695 }
8696
8697 static void ffi_PDFObject_isArray(js_State *J)
8698 {
8699 fz_context *ctx = js_getcontext(J);
8700 pdf_obj *obj = js_touserdata(J, 0, "pdf_obj");
8701 int b = 0;
8702 fz_try(ctx)
8703 b = pdf_is_array(ctx, obj);
8704 fz_catch(ctx)
8705 rethrow(J);
8706 js_pushboolean(J, b);
8707 }
8708
8709 static void ffi_PDFObject_isDictionary(js_State *J)
8710 {
8711 fz_context *ctx = js_getcontext(J);
8712 pdf_obj *obj = js_touserdata(J, 0, "pdf_obj");
8713 int b = 0;
8714 fz_try(ctx)
8715 b = pdf_is_dict(ctx, obj);
8716 fz_catch(ctx)
8717 rethrow(J);
8718 js_pushboolean(J, b);
8719 }
8720
8721 static void ffi_PDFObject_isIndirect(js_State *J)
8722 {
8723 fz_context *ctx = js_getcontext(J);
8724 pdf_obj *obj = js_touserdata(J, 0, "pdf_obj");
8725 int b = 0;
8726 fz_try(ctx)
8727 b = pdf_is_indirect(ctx, obj);
8728 fz_catch(ctx)
8729 rethrow(J);
8730 js_pushboolean(J, b);
8731 }
8732
8733 static void ffi_PDFObject_isInteger(js_State *J)
8734 {
8735 fz_context *ctx = js_getcontext(J);
8736 pdf_obj *obj = js_touserdata(J, 0, "pdf_obj");
8737 int b = 0;
8738 fz_try(ctx)
8739 b = pdf_is_int(ctx, obj);
8740 fz_catch(ctx)
8741 rethrow(J);
8742 js_pushboolean(J, b);
8743 }
8744
8745 static void ffi_PDFObject_asIndirect(js_State *J)
8746 {
8747 fz_context *ctx = js_getcontext(J);
8748 pdf_obj *obj = js_touserdata(J, 0, "pdf_obj");
8749 int num = 0;
8750 fz_try(ctx)
8751 num = pdf_to_num(ctx, obj);
8752 fz_catch(ctx)
8753 rethrow(J);
8754 js_pushnumber(J, num);
8755 }
8756
8757 static void ffi_PDFObject_isNull(js_State *J)
8758 {
8759 fz_context *ctx = js_getcontext(J);
8760 pdf_obj *obj = js_touserdata(J, 0, "pdf_obj");
8761 int b = 0;
8762 fz_try(ctx)
8763 b = pdf_is_null(ctx, obj);
8764 fz_catch(ctx)
8765 rethrow(J);
8766 js_pushboolean(J, b);
8767 }
8768
8769 static void ffi_PDFObject_isBoolean(js_State *J)
8770 {
8771 fz_context *ctx = js_getcontext(J);
8772 pdf_obj *obj = js_touserdata(J, 0, "pdf_obj");
8773 int b = 0;
8774 fz_try(ctx)
8775 b = pdf_is_bool(ctx, obj);
8776 fz_catch(ctx)
8777 rethrow(J);
8778 js_pushboolean(J, b);
8779 }
8780
8781 static void ffi_PDFObject_asBoolean(js_State *J)
8782 {
8783 fz_context *ctx = js_getcontext(J);
8784 pdf_obj *obj = js_touserdata(J, 0, "pdf_obj");
8785 int b = 0;
8786 fz_try(ctx)
8787 b = pdf_to_bool(ctx, obj);
8788 fz_catch(ctx)
8789 rethrow(J);
8790 js_pushboolean(J, b);
8791 }
8792
8793 static void ffi_PDFObject_isNumber(js_State *J)
8794 {
8795 fz_context *ctx = js_getcontext(J);
8796 pdf_obj *obj = js_touserdata(J, 0, "pdf_obj");
8797 int b = 0;
8798 fz_try(ctx)
8799 b = pdf_is_number(ctx, obj);
8800 fz_catch(ctx)
8801 rethrow(J);
8802 js_pushboolean(J, b);
8803 }
8804
8805 static void ffi_PDFObject_asNumber(js_State *J)
8806 {
8807 fz_context *ctx = js_getcontext(J);
8808 pdf_obj *obj = js_touserdata(J, 0, "pdf_obj");
8809 float num = 0;
8810 fz_try(ctx)
8811 if (pdf_is_int(ctx, obj))
8812 num = pdf_to_int(ctx, obj);
8813 else
8814 num = pdf_to_real(ctx, obj);
8815 fz_catch(ctx)
8816 rethrow(J);
8817 js_pushnumber(J, num);
8818 }
8819
8820 static void ffi_PDFObject_isName(js_State *J)
8821 {
8822 fz_context *ctx = js_getcontext(J);
8823 pdf_obj *obj = js_touserdata(J, 0, "pdf_obj");
8824 int b = 0;
8825 fz_try(ctx)
8826 b = pdf_is_name(ctx, obj);
8827 fz_catch(ctx)
8828 rethrow(J);
8829 js_pushboolean(J, b);
8830 }
8831
8832 static void ffi_PDFObject_asName(js_State *J)
8833 {
8834 fz_context *ctx = js_getcontext(J);
8835 pdf_obj *obj = js_touserdata(J, 0, "pdf_obj");
8836 const char *name = NULL;
8837 fz_try(ctx)
8838 name = pdf_to_name(ctx, obj);
8839 fz_catch(ctx)
8840 rethrow(J);
8841 js_pushstring(J, name);
8842 }
8843
8844 static void ffi_PDFObject_isReal(js_State *J)
8845 {
8846 fz_context *ctx = js_getcontext(J);
8847 pdf_obj *obj = js_touserdata(J, 0, "pdf_obj");
8848 int b = 0;
8849 fz_try(ctx)
8850 b = pdf_is_real(ctx, obj);
8851 fz_catch(ctx)
8852 rethrow(J);
8853 js_pushboolean(J, b);
8854 }
8855
8856 static void ffi_PDFObject_isString(js_State *J)
8857 {
8858 fz_context *ctx = js_getcontext(J);
8859 pdf_obj *obj = js_touserdata(J, 0, "pdf_obj");
8860 int b = 0;
8861 fz_try(ctx)
8862 b = pdf_is_string(ctx, obj);
8863 fz_catch(ctx)
8864 rethrow(J);
8865 js_pushboolean(J, b);
8866 }
8867
8868 static void ffi_PDFObject_asString(js_State *J)
8869 {
8870 fz_context *ctx = js_getcontext(J);
8871 pdf_obj *obj = js_touserdata(J, 0, "pdf_obj");
8872 const char *string = NULL;
8873
8874 fz_try(ctx)
8875 string = pdf_to_text_string(ctx, obj);
8876 fz_catch(ctx)
8877 rethrow(J);
8878
8879 js_pushstring(J, string);
8880 }
8881
8882 static void ffi_PDFObject_asByteString(js_State *J)
8883 {
8884 fz_context *ctx = js_getcontext(J);
8885 pdf_obj *obj = js_touserdata(J, 0, "pdf_obj");
8886 const char *buf;
8887 size_t i, len = 0;
8888
8889 fz_try(ctx)
8890 buf = pdf_to_string(ctx, obj, &len);
8891 fz_catch(ctx)
8892 rethrow(J);
8893
8894 js_newarray(J);
8895 for (i = 0; i < len; ++i) {
8896 js_pushnumber(J, (unsigned char)buf[i]);
8897 js_setindex(J, -2, (int)i);
8898 }
8899 }
8900
8901 static void ffi_PDFObject_isStream(js_State *J)
8902 {
8903 fz_context *ctx = js_getcontext(J);
8904 pdf_obj *obj = js_touserdata(J, 0, "pdf_obj");
8905 int b = 0;
8906 fz_try(ctx)
8907 b = pdf_is_stream(ctx, obj);
8908 fz_catch(ctx)
8909 rethrow(J);
8910 js_pushboolean(J, b);
8911 }
8912
8913 static void ffi_PDFObject_readStream(js_State *J)
8914 {
8915 fz_context *ctx = js_getcontext(J);
8916 pdf_obj *obj = js_touserdata(J, 0, "pdf_obj");
8917 fz_buffer *buf = NULL;
8918 fz_try(ctx)
8919 buf = pdf_load_stream(ctx, obj);
8920 fz_catch(ctx)
8921 rethrow(J);
8922 ffi_pushbuffer_own(J, buf);
8923 }
8924
8925 static void ffi_PDFObject_readRawStream(js_State *J)
8926 {
8927 fz_context *ctx = js_getcontext(J);
8928 pdf_obj *obj = js_touserdata(J, 0, "pdf_obj");
8929 fz_buffer *buf = NULL;
8930 fz_try(ctx)
8931 buf = pdf_load_raw_stream(ctx, obj);
8932 fz_catch(ctx)
8933 rethrow(J);
8934 ffi_pushbuffer_own(J, buf);
8935 }
8936
8937 static void ffi_PDFObject_writeObject(js_State *J)
8938 {
8939 fz_context *ctx = js_getcontext(J);
8940 pdf_obj *ref = js_touserdata(J, 0, "pdf_obj");
8941 pdf_document *pdf = pdf_get_bound_document(ctx, ref);
8942 pdf_obj *obj = ffi_tonewobj(J, pdf, 1);
8943 fz_try(ctx)
8944 pdf_update_object(ctx, pdf, pdf_to_num(ctx, ref), obj);
8945 fz_always(ctx)
8946 pdf_drop_obj(ctx, obj);
8947 fz_catch(ctx)
8948 rethrow(J);
8949 }
8950
8951 static void ffi_PDFObject_writeStream(js_State *J)
8952 {
8953 fz_context *ctx = js_getcontext(J);
8954 pdf_obj *obj = js_touserdata(J, 0, "pdf_obj");
8955 fz_buffer *buf = ffi_tonewbuffer(J, 1);
8956 fz_try(ctx)
8957 pdf_update_stream(ctx, pdf_get_bound_document(ctx, obj), obj, buf, 0);
8958 fz_always(ctx)
8959 fz_drop_buffer(ctx, buf);
8960 fz_catch(ctx)
8961 rethrow(J);
8962 }
8963
8964 static void ffi_PDFObject_writeRawStream(js_State *J)
8965 {
8966 fz_context *ctx = js_getcontext(J);
8967 pdf_obj *obj = js_touserdata(J, 0, "pdf_obj");
8968 fz_buffer *buf = ffi_tonewbuffer(J, 1);
8969 fz_try(ctx)
8970 pdf_update_stream(ctx, pdf_get_bound_document(ctx, obj), obj, buf, 1);
8971 fz_always(ctx)
8972 fz_drop_buffer(ctx, buf);
8973 fz_catch(ctx)
8974 rethrow(J);
8975 }
8976
8977 static void ffi_PDFObject_forEach(js_State *J)
8978 {
8979 fz_context *ctx = js_getcontext(J);
8980 pdf_obj *obj = js_touserdata(J, 0, "pdf_obj");
8981 pdf_obj *val = NULL;
8982 const char *key = NULL;
8983 int i, n = 0;
8984
8985 fz_try(ctx)
8986 obj = pdf_resolve_indirect_chain(ctx, obj);
8987 fz_catch(ctx)
8988 rethrow(J);
8989
8990 if (pdf_is_array(ctx, obj)) {
8991 fz_try(ctx)
8992 n = pdf_array_len(ctx, obj);
8993 fz_catch(ctx)
8994 rethrow(J);
8995 for (i = 0; i < n; ++i) {
8996 fz_try(ctx)
8997 val = pdf_array_get(ctx, obj, i);
8998 fz_catch(ctx)
8999 rethrow(J);
9000 js_copy(J, 1);
9001 js_pushnull(J);
9002 ffi_pushobj(J, pdf_keep_obj(ctx, val));
9003 js_pushnumber(J, i);
9004 js_copy(J, 0);
9005 js_call(J, 3);
9006 js_pop(J, 1);
9007 }
9008 return;
9009 }
9010
9011 if (pdf_is_dict(ctx, obj)) {
9012 fz_try(ctx)
9013 n = pdf_dict_len(ctx, obj);
9014 fz_catch(ctx)
9015 rethrow(J);
9016 for (i = 0; i < n; ++i) {
9017 fz_try(ctx) {
9018 key = pdf_to_name(ctx, pdf_dict_get_key(ctx, obj, i));
9019 val = pdf_dict_get_val(ctx, obj, i);
9020 } fz_catch(ctx)
9021 rethrow(J);
9022 js_copy(J, 1);
9023 js_pushnull(J);
9024 ffi_pushobj(J, pdf_keep_obj(ctx, val));
9025 js_pushstring(J, key);
9026 js_copy(J, 0);
9027 js_call(J, 3);
9028 js_pop(J, 1);
9029 }
9030 return;
9031 }
9032 }
9033
9034 static void ffi_PDFObject_compare(js_State *J)
9035 {
9036 fz_context *ctx = js_getcontext(J);
9037 pdf_obj *obj = js_touserdata(J, 0, "pdf_obj");
9038 pdf_obj *other = js_touserdata(J, 1, "pdf_obj");
9039 int result = 0;
9040
9041 fz_try(ctx)
9042 result = pdf_objcmp(ctx, obj, other);
9043 fz_catch(ctx)
9044 rethrow(J);
9045
9046 js_pushnumber(J, result);
9047 }
9048
9049 static void ffi_PDFPage_getObject(js_State *J)
9050 {
9051 fz_context *ctx = js_getcontext(J);
9052 pdf_page *page = js_touserdata(J, 0, "pdf_page");
9053 ffi_pushobj(J, pdf_keep_obj(ctx, page->obj));
9054 }
9055
9056 static void ffi_PDFPage_getWidgets(js_State *J)
9057 {
9058 fz_context *ctx = js_getcontext(J);
9059 pdf_page *page = js_touserdata(J, 0, "pdf_page");
9060 pdf_annot *widget = NULL;
9061 int i = 0;
9062
9063 fz_try(ctx)
9064 widget = pdf_first_widget(ctx, page);
9065 fz_catch(ctx)
9066 rethrow(J);
9067
9068 js_newarray(J);
9069
9070 while (widget) {
9071 js_getregistry(J, "pdf_widget");
9072 js_newuserdata(J, "pdf_widget", pdf_keep_widget(ctx, widget), ffi_gc_pdf_annot);
9073 js_setindex(J, -2, i++);
9074
9075 fz_try(ctx)
9076 widget = pdf_next_widget(ctx, widget);
9077 fz_catch(ctx)
9078 rethrow(J);
9079 }
9080 }
9081
9082 static void ffi_PDFPage_getAnnotations(js_State *J)
9083 {
9084 fz_context *ctx = js_getcontext(J);
9085 pdf_page *page = js_touserdata(J, 0, "pdf_page");
9086 pdf_annot *annot = NULL;
9087 int i = 0;
9088
9089 fz_try(ctx)
9090 annot = pdf_first_annot(ctx, page);
9091 fz_catch(ctx)
9092 rethrow(J);
9093
9094 js_newarray(J);
9095
9096 while (annot) {
9097 js_getregistry(J, "pdf_annot");
9098 js_newuserdata(J, "pdf_annot", pdf_keep_annot(ctx, annot), ffi_gc_pdf_annot);
9099 js_setindex(J, -2, i++);
9100
9101 fz_try(ctx)
9102 annot = pdf_next_annot(ctx, annot);
9103 fz_catch(ctx)
9104 rethrow(J);
9105 }
9106 }
9107
9108 static void ffi_PDFPage_createAnnotation(js_State *J)
9109 {
9110 fz_context *ctx = js_getcontext(J);
9111 pdf_page *page = js_touserdata(J, 0, "pdf_page");
9112 const char *name = js_tostring(J, 1);
9113 pdf_annot *annot = NULL;
9114 int type;
9115
9116 fz_try(ctx)
9117 {
9118 type = pdf_annot_type_from_string(ctx, name);
9119 annot = pdf_create_annot(ctx, page, type);
9120 }
9121 fz_catch(ctx)
9122 rethrow(J);
9123 js_getregistry(J, "pdf_annot");
9124 js_newuserdata(J, "pdf_annot", annot, ffi_gc_pdf_annot);
9125 }
9126
9127 static void ffi_PDFPage_deleteAnnotation(js_State *J)
9128 {
9129 fz_context *ctx = js_getcontext(J);
9130 pdf_page *page = js_touserdata(J, 0, "pdf_page");
9131 pdf_annot *annot = ffi_toannot(J, 1);
9132 fz_try(ctx)
9133 pdf_delete_annot(ctx, page, annot);
9134 fz_catch(ctx)
9135 rethrow(J);
9136 }
9137
9138 static void ffi_PDFPage_createSignature(js_State *J)
9139 {
9140 fz_context *ctx = js_getcontext(J);
9141 pdf_page *page = js_touserdata(J, 0, "pdf_page");
9142 const char *name = js_tostring(J, 1);
9143 pdf_annot *widget;
9144
9145 fz_try(ctx)
9146 widget = pdf_create_signature_widget(ctx, page, (char *) name);
9147 fz_catch(ctx)
9148 rethrow(J);
9149 js_getregistry(J, "pdf_widget");
9150 js_newuserdata(J, "pdf_widget", widget, ffi_gc_pdf_annot);
9151 }
9152
9153 static void ffi_PDFPage_update(js_State *J)
9154 {
9155 fz_context *ctx = js_getcontext(J);
9156 pdf_page *page = js_touserdata(J, 0, "pdf_page");
9157 int changed = 0;
9158 fz_try(ctx)
9159 changed = pdf_update_page(ctx, page);
9160 fz_catch(ctx)
9161 rethrow(J);
9162 js_pushboolean(J, changed);
9163 }
9164
9165 static void ffi_PDFPage_applyRedactions(js_State *J)
9166 {
9167 fz_context *ctx = js_getcontext(J);
9168 pdf_page *page = js_touserdata(J, 0, "pdf_page");
9169 pdf_redact_options opts = { 1, PDF_REDACT_IMAGE_PIXELS, 0 };
9170 if (js_isdefined(J, 1)) opts.black_boxes = js_toboolean(J, 1);
9171 if (js_isdefined(J, 2)) opts.image_method = js_tointeger(J, 2);
9172 if (js_isdefined(J, 3)) opts.line_art = js_tointeger(J, 3);
9173 if (js_isdefined(J, 4)) opts.text = js_tointeger(J, 4);
9174 fz_try(ctx)
9175 pdf_redact_page(ctx, page->doc, page, &opts);
9176 fz_catch(ctx)
9177 rethrow(J);
9178 }
9179
9180 static void ffi_PDFPage_process(js_State *J)
9181 {
9182 fz_context *ctx = js_getcontext(J);
9183 pdf_page *page = js_touserdata(J, 0, "pdf_page");
9184 pdf_processor *proc = new_js_processor(ctx, J);
9185 fz_try(ctx)
9186 {
9187 pdf_obj *resources = pdf_page_resources(ctx, page);
9188 pdf_obj *contents = pdf_page_contents(ctx, page);
9189 pdf_process_contents(ctx, proc, page->doc, resources, contents, NULL, NULL);
9190 pdf_close_processor(ctx, proc);
9191 }
9192 fz_always(ctx)
9193 pdf_drop_processor(ctx, proc);
9194 fz_catch(ctx)
9195 rethrow(J);
9196 }
9197
9198 static void ffi_PDFPage_toPixmap(js_State *J)
9199 {
9200 fz_context *ctx = js_getcontext(J);
9201 pdf_page *page = pdf_page_from_fz_page(ctx, ffi_topage(J, 0));
9202 fz_matrix ctm = ffi_tomatrix(J, 1);
9203 fz_colorspace *colorspace = js_touserdata(J, 2, "fz_colorspace");
9204 int alpha = js_toboolean(J, 3);
9205 int extra = js_isdefined(J, 4) ? js_toboolean(J, 4) : 1;
9206 const char *usage = js_isdefined(J, 5) ? js_tostring(J, 5) : "View";
9207 const char *box_name = js_isdefined(J, 6) ? js_tostring(J, 6) : NULL;
9208 fz_box_type box = FZ_CROP_BOX;
9209 fz_pixmap *pixmap = NULL;
9210
9211 if (box_name) {
9212 box = fz_box_type_from_string(box_name);
9213 if (box == FZ_UNKNOWN_BOX)
9214 js_error(J, "invalid page box name");
9215 }
9216
9217 fz_try(ctx)
9218 if (extra)
9219 pixmap = pdf_new_pixmap_from_page_with_usage(ctx, page, ctm, colorspace, alpha, usage, box);
9220 else
9221 pixmap = pdf_new_pixmap_from_page_contents_with_usage(ctx, page, ctm, colorspace, alpha, usage, box);
9222
9223 fz_catch(ctx)
9224 rethrow(J);
9225
9226 ffi_pushpixmap(J, pixmap);
9227 }
9228
9229 static void ffi_PDFPage_getTransform(js_State *J)
9230 {
9231 fz_context *ctx = js_getcontext(J);
9232 pdf_page *page = pdf_page_from_fz_page(ctx, ffi_topage(J, 0));
9233 fz_matrix ctm;
9234
9235 fz_try(ctx)
9236 pdf_page_transform(ctx, page, NULL, &ctm);
9237 fz_catch(ctx)
9238 rethrow(J);
9239
9240 ffi_pushmatrix(J, ctm);
9241 }
9242
9243 static void ffi_PDFPage_setPageBox(js_State *J)
9244 {
9245 fz_context *ctx = js_getcontext(J);
9246 pdf_page *page = js_touserdata(J, 0, "pdf_page");
9247 const char *box_name = js_tostring(J, 1);
9248 fz_rect rect = ffi_torect(J, 2);
9249 int box;
9250
9251 box = fz_box_type_from_string(box_name);
9252 if (box == FZ_UNKNOWN_BOX)
9253 js_error(J, "invalid page box name");
9254
9255 fz_try(ctx)
9256 pdf_set_page_box(ctx, page, box, rect);
9257 fz_catch(ctx)
9258 rethrow(J);
9259 }
9260
9261 static void ffi_PDFPage_countAssociatedFiles(js_State *J)
9262 {
9263 fz_context *ctx = js_getcontext(J);
9264 pdf_page *pdf = js_touserdata(J, 0, "pdf_page");
9265 int n;
9266 fz_try(ctx)
9267 n = pdf_count_page_associated_files(ctx, pdf);
9268 fz_catch(ctx)
9269 rethrow(J);
9270 js_pushnumber(J, n);
9271 }
9272
9273 static void ffi_PDFPage_associatedFile(js_State *J)
9274 {
9275 fz_context *ctx = js_getcontext(J);
9276 pdf_page *pdf = js_touserdata(J, 0, "pdf_page");
9277 int idx = js_tointeger(J, 1);
9278 pdf_obj *obj;
9279 fz_try(ctx)
9280 obj = pdf_page_associated_file(ctx, pdf, idx);
9281 fz_catch(ctx)
9282 rethrow(J);
9283 ffi_pushobj(J, obj);
9284 }
9285
9286 static void ffi_PDFAnnotation_getBounds(js_State *J)
9287 {
9288 fz_context *ctx = js_getcontext(J);
9289 pdf_annot *annot = ffi_toannot(J, 0);
9290 fz_rect bounds;
9291
9292 fz_try(ctx)
9293 bounds = pdf_bound_annot(ctx, annot);
9294 fz_catch(ctx)
9295 rethrow(J);
9296
9297 ffi_pushrect(J, bounds);
9298 }
9299
9300 static void ffi_PDFAnnotation_run(js_State *J)
9301 {
9302 fz_context *ctx = js_getcontext(J);
9303 pdf_annot *annot = ffi_toannot(J, 0);
9304 fz_device *device = NULL;
9305 fz_matrix ctm = ffi_tomatrix(J, 2);
9306
9307 if (js_isuserdata(J, 1, "fz_device")) {
9308 device = js_touserdata(J, 1, "fz_device");
9309 fz_try(ctx)
9310 pdf_run_annot(ctx, annot, device, ctm, NULL);
9311 fz_catch(ctx)
9312 rethrow(J);
9313 } else {
9314 device = new_js_device(ctx, J);
9315 js_copy(J, 1); /* put the js device on the top so the callbacks know where to get it */
9316 fz_try(ctx)
9317 pdf_run_annot(ctx, annot, device, ctm, NULL);
9318 fz_always(ctx)
9319 fz_drop_device(ctx, device);
9320 fz_catch(ctx)
9321 rethrow(J);
9322 }
9323 }
9324
9325 static void ffi_PDFAnnotation_toDisplayList(js_State *J)
9326 {
9327 fz_context *ctx = js_getcontext(J);
9328 pdf_annot *annot = ffi_toannot(J, 0);
9329 fz_display_list *list = NULL;
9330
9331 fz_try(ctx)
9332 list = pdf_new_display_list_from_annot(ctx, annot);
9333 fz_catch(ctx)
9334 rethrow(J);
9335
9336 js_getregistry(J, "fz_display_list");
9337 js_newuserdata(J, "fz_display_list", list, ffi_gc_fz_display_list);
9338 }
9339
9340 static void ffi_PDFAnnotation_toPixmap(js_State *J)
9341 {
9342 fz_context *ctx = js_getcontext(J);
9343 pdf_annot *annot = ffi_toannot(J, 0);
9344 fz_matrix ctm = ffi_tomatrix(J, 1);
9345 fz_colorspace *colorspace = js_touserdata(J, 2, "fz_colorspace");
9346 int alpha = js_toboolean(J, 3);
9347 fz_pixmap *pixmap = NULL;
9348
9349 fz_try(ctx)
9350 pixmap = pdf_new_pixmap_from_annot(ctx, annot, ctm, colorspace, NULL, alpha);
9351 fz_catch(ctx)
9352 rethrow(J);
9353
9354 ffi_pushpixmap(J, pixmap);
9355 }
9356
9357 static void ffi_PDFAnnotation_getObject(js_State *J)
9358 {
9359 fz_context *ctx = js_getcontext(J);
9360 pdf_annot *annot = ffi_toannot(J, 0);
9361 pdf_obj *obj;
9362
9363 obj = pdf_annot_obj(ctx, annot);
9364 ffi_pushobj(J, pdf_keep_obj(ctx, obj));
9365 }
9366
9367 static void ffi_PDFAnnotation_getType(js_State *J)
9368 {
9369 fz_context *ctx = js_getcontext(J);
9370 pdf_annot *annot = ffi_toannot(J, 0);
9371 int type;
9372 const char *typestr = NULL;
9373 fz_try(ctx)
9374 {
9375 type = pdf_annot_type(ctx, annot);
9376 typestr = pdf_string_from_annot_type(ctx, type);
9377 }
9378 fz_catch(ctx)
9379 rethrow(J);
9380 js_pushstring(J, typestr);
9381 }
9382
9383 static void ffi_PDFAnnotation_getFlags(js_State *J)
9384 {
9385 fz_context *ctx = js_getcontext(J);
9386 pdf_annot *annot = ffi_toannot(J, 0);
9387 int flags = 0;
9388 fz_try(ctx)
9389 flags = pdf_annot_flags(ctx, annot);
9390 fz_catch(ctx)
9391 rethrow(J);
9392 js_pushnumber(J, flags);
9393 }
9394
9395 static void ffi_PDFAnnotation_setFlags(js_State *J)
9396 {
9397 fz_context *ctx = js_getcontext(J);
9398 pdf_annot *annot = ffi_toannot(J, 0);
9399 int flags = js_tointeger(J, 1);
9400 fz_try(ctx)
9401 pdf_set_annot_flags(ctx, annot, flags);
9402 fz_catch(ctx)
9403 rethrow(J);
9404 }
9405
9406 static void ffi_PDFAnnotation_getContents(js_State *J)
9407 {
9408 fz_context *ctx = js_getcontext(J);
9409 pdf_annot *annot = ffi_toannot(J, 0);
9410 const char *contents = NULL;
9411
9412 fz_try(ctx)
9413 contents = pdf_annot_contents(ctx, annot);
9414 fz_catch(ctx)
9415 rethrow(J);
9416
9417 js_pushstring(J, contents);
9418 }
9419
9420 static void ffi_PDFAnnotation_setContents(js_State *J)
9421 {
9422 fz_context *ctx = js_getcontext(J);
9423 pdf_annot *annot = ffi_toannot(J, 0);
9424 const char *contents = js_tostring(J, 1);
9425 fz_try(ctx)
9426 pdf_set_annot_contents(ctx, annot, contents);
9427 fz_catch(ctx)
9428 rethrow(J);
9429 }
9430
9431 static void ffi_PDFAnnotation_hasRichContents(js_State *J)
9432 {
9433 fz_context *ctx = js_getcontext(J);
9434 pdf_annot *annot = ffi_toannot(J, 0);
9435 int has;
9436 fz_try(ctx)
9437 has = pdf_annot_has_rich_contents(ctx, annot);
9438 fz_catch(ctx)
9439 rethrow(J);
9440 js_pushboolean(J, has);
9441 }
9442
9443 static void ffi_PDFAnnotation_getRichContents(js_State *J)
9444 {
9445 fz_context *ctx = js_getcontext(J);
9446 pdf_annot *annot = ffi_toannot(J, 0);
9447 const char *contents = NULL;
9448
9449 fz_try(ctx)
9450 contents = pdf_annot_rich_contents(ctx, annot);
9451 fz_catch(ctx)
9452 rethrow(J);
9453
9454 js_pushstring(J, contents);
9455 }
9456
9457 static void ffi_PDFAnnotation_setRichContents(js_State *J)
9458 {
9459 fz_context *ctx = js_getcontext(J);
9460 pdf_annot *annot = ffi_toannot(J, 0);
9461 const char *plain_text = js_tostring(J, 1);
9462 const char *rich_text = js_tostring(J, 2);
9463 fz_try(ctx)
9464 pdf_set_annot_rich_contents(ctx, annot, plain_text, rich_text);
9465 fz_catch(ctx)
9466 rethrow(J);
9467 }
9468
9469 static void ffi_PDFAnnotation_getRichDefaults(js_State *J)
9470 {
9471 fz_context *ctx = js_getcontext(J);
9472 pdf_annot *annot = ffi_toannot(J, 0);
9473 const char *contents = NULL;
9474
9475 fz_try(ctx)
9476 contents = pdf_annot_rich_defaults(ctx, annot);
9477 fz_catch(ctx)
9478 rethrow(J);
9479
9480 js_pushstring(J, contents);
9481 }
9482
9483 static void ffi_PDFAnnotation_setRichDefaults(js_State *J)
9484 {
9485 fz_context *ctx = js_getcontext(J);
9486 pdf_annot *annot = ffi_toannot(J, 0);
9487 const char *style = js_tostring(J, 1);
9488 fz_try(ctx)
9489 pdf_set_annot_rich_defaults(ctx, annot, style);
9490 fz_catch(ctx)
9491 rethrow(J);
9492 }
9493
9494 static void ffi_PDFAnnotation_hasRect(js_State *J)
9495 {
9496 fz_context *ctx = js_getcontext(J);
9497 pdf_annot *annot = ffi_toannot(J, 0);
9498 int has;
9499 fz_try(ctx)
9500 has = pdf_annot_has_rect(ctx, annot);
9501 fz_catch(ctx)
9502 rethrow(J);
9503 js_pushboolean(J, has);
9504 }
9505
9506 static void ffi_PDFAnnotation_getRect(js_State *J)
9507 {
9508 fz_context *ctx = js_getcontext(J);
9509 pdf_annot *annot = ffi_toannot(J, 0);
9510 fz_rect rect;
9511 fz_try(ctx)
9512 rect = pdf_annot_rect(ctx, annot);
9513 fz_catch(ctx)
9514 rethrow(J);
9515 ffi_pushrect(J, rect);
9516 }
9517
9518 static void ffi_PDFAnnotation_setRect(js_State *J)
9519 {
9520 fz_context *ctx = js_getcontext(J);
9521 pdf_annot *annot = ffi_toannot(J, 0);
9522 fz_rect rect = ffi_torect(J, 1);
9523 fz_try(ctx)
9524 pdf_set_annot_rect(ctx, annot, rect);
9525 fz_catch(ctx)
9526 rethrow(J);
9527 }
9528
9529 static void ffi_PDFAnnotation_getColor(js_State *J)
9530 {
9531 fz_context *ctx = js_getcontext(J);
9532 pdf_annot *annot = ffi_toannot(J, 0);
9533 int i, n = 0;
9534 float color[4];
9535 fz_try(ctx)
9536 pdf_annot_color(ctx, annot, &n, color);
9537 fz_catch(ctx)
9538 rethrow(J);
9539
9540 if (n == 0 || n == 1 || n == 3 || n == 4)
9541 {
9542 js_newarray(J);
9543 for (i = 0; i < n; ++i) {
9544 js_pushnumber(J, color[i]);
9545 js_setindex(J, -2, i);
9546 }
9547 }
9548 else
9549 js_typeerror(J, "invalid number of components for Color");
9550 }
9551
9552 static void ffi_PDFAnnotation_setColor(js_State *J)
9553 {
9554 fz_context *ctx = js_getcontext(J);
9555 pdf_annot *annot = ffi_toannot(J, 0);
9556 int i, n = fz_maxi(0, js_getlength(J, 1));
9557 float color[4];
9558
9559 if (n == 0 || n == 1 || n == 3 || n == 4)
9560 {
9561 for (i = 0; i < n && i < (int) nelem(color); ++i) {
9562 js_getindex(J, 1, i);
9563 color[i] = js_tonumber(J, -1);
9564 js_pop(J, 1);
9565 }
9566 fz_try(ctx)
9567 pdf_set_annot_color(ctx, annot, n, color);
9568 fz_catch(ctx)
9569 rethrow(J);
9570 }
9571 else
9572 js_typeerror(J, "invalid number of components for Color");
9573 }
9574
9575 static void ffi_PDFAnnotation_hasInteriorColor(js_State *J)
9576 {
9577 fz_context *ctx = js_getcontext(J);
9578 pdf_annot *annot = ffi_toannot(J, 0);
9579 int has;
9580 fz_try(ctx)
9581 has = pdf_annot_has_interior_color(ctx, annot);
9582 fz_catch(ctx)
9583 rethrow(J);
9584 js_pushboolean(J, has);
9585 }
9586
9587 static void ffi_PDFAnnotation_getInteriorColor(js_State *J)
9588 {
9589 fz_context *ctx = js_getcontext(J);
9590 pdf_annot *annot = ffi_toannot(J, 0);
9591 int i, n = 0;
9592 float color[4];
9593 fz_try(ctx)
9594 pdf_annot_interior_color(ctx, annot, &n, color);
9595 fz_catch(ctx)
9596 rethrow(J);
9597 js_newarray(J);
9598 for (i = 0; i < n; ++i) {
9599 js_pushnumber(J, color[i]);
9600 js_setindex(J, -2, i);
9601 }
9602 }
9603
9604 static void ffi_PDFAnnotation_setInteriorColor(js_State *J)
9605 {
9606 fz_context *ctx = js_getcontext(J);
9607 pdf_annot *annot = ffi_toannot(J, 0);
9608 int i, n = fz_maxi(0, js_getlength(J, 1));
9609 float color[4];
9610
9611 if (n == 0 || n == 1 || n == 3 || n == 4)
9612 {
9613 for (i = 0; i < n && i < (int) nelem(color); ++i) {
9614 js_getindex(J, 1, i);
9615 color[i] = js_tonumber(J, -1);
9616 js_pop(J, 1);
9617 }
9618 fz_try(ctx)
9619 pdf_set_annot_interior_color(ctx, annot, n, color);
9620 fz_catch(ctx)
9621 rethrow(J);
9622 }
9623 else
9624 js_typeerror(J, "invalid number of components for Color");
9625 }
9626
9627 static void ffi_PDFAnnotation_getOpacity(js_State *J)
9628 {
9629 fz_context *ctx = js_getcontext(J);
9630 pdf_annot *annot = ffi_toannot(J, 0);
9631 float opacity;
9632 fz_try(ctx)
9633 opacity = pdf_annot_opacity(ctx, annot);
9634 fz_catch(ctx)
9635 rethrow(J);
9636 js_pushnumber(J, opacity);
9637 }
9638
9639 static void ffi_PDFAnnotation_setOpacity(js_State *J)
9640 {
9641 fz_context *ctx = js_getcontext(J);
9642 pdf_annot *annot = ffi_toannot(J, 0);
9643 float opacity = js_tonumber(J, 1);
9644 fz_try(ctx)
9645 pdf_set_annot_opacity(ctx, annot, opacity);
9646 fz_catch(ctx)
9647 rethrow(J);
9648 }
9649
9650 static void ffi_PDFAnnotation_hasQuadPoints(js_State *J)
9651 {
9652 fz_context *ctx = js_getcontext(J);
9653 pdf_annot *annot = ffi_toannot(J, 0);
9654 int has;
9655 fz_try(ctx)
9656 has = pdf_annot_has_quad_points(ctx, annot);
9657 fz_catch(ctx)
9658 rethrow(J);
9659 js_pushboolean(J, has);
9660 }
9661
9662 static void ffi_PDFAnnotation_getQuadPoints(js_State *J)
9663 {
9664 fz_context *ctx = js_getcontext(J);
9665 pdf_annot *annot = ffi_toannot(J, 0);
9666 fz_quad q;
9667 int i, n = 0;
9668
9669 fz_try(ctx)
9670 n = pdf_annot_quad_point_count(ctx, annot);
9671 fz_catch(ctx)
9672 rethrow(J);
9673
9674 js_newarray(J);
9675 for (i = 0; i < n; ++i) {
9676 fz_try(ctx)
9677 q = pdf_annot_quad_point(ctx, annot, i);
9678 fz_catch(ctx)
9679 rethrow(J);
9680 ffi_pushquad(J, q);
9681 js_setindex(J, -2, i);
9682 }
9683 }
9684
9685 static void ffi_PDFAnnotation_setQuadPoints(js_State *J)
9686 {
9687 fz_context *ctx = js_getcontext(J);
9688 pdf_annot *annot = ffi_toannot(J, 0);
9689 fz_quad *qp = NULL;
9690 int i, n;
9691
9692 n = fz_maxi(0, js_getlength(J, 1));
9693
9694 fz_try(ctx)
9695 qp = fz_malloc_array(ctx, n, fz_quad);
9696 fz_catch(ctx)
9697 rethrow(J);
9698
9699 for (i = 0; i < n; ++i) {
9700 js_getindex(J, 1, i);
9701 qp[i] = ffi_toquad(J, -1);
9702 js_pop(J, 1);
9703 }
9704
9705 fz_try(ctx)
9706 pdf_set_annot_quad_points(ctx, annot, n, qp);
9707 fz_always(ctx)
9708 fz_free(ctx, qp);
9709 fz_catch(ctx)
9710 rethrow(J);
9711 }
9712
9713 static void ffi_PDFAnnotation_clearQuadPoints(js_State *J)
9714 {
9715 fz_context *ctx = js_getcontext(J);
9716 pdf_annot *annot = ffi_toannot(J, 0);
9717
9718 fz_try(ctx)
9719 pdf_clear_annot_quad_points(ctx, annot);
9720 fz_catch(ctx)
9721 rethrow(J);
9722 }
9723
9724 static void ffi_PDFAnnotation_addQuadPoint(js_State *J)
9725 {
9726 fz_context *ctx = js_getcontext(J);
9727 pdf_annot *annot = ffi_toannot(J, 0);
9728 fz_quad q = ffi_toquad(J, 1);
9729
9730 fz_try(ctx)
9731 pdf_add_annot_quad_point(ctx, annot, q);
9732 fz_catch(ctx)
9733 rethrow(J);
9734 }
9735
9736 static void ffi_PDFAnnotation_hasVertices(js_State *J)
9737 {
9738 fz_context *ctx = js_getcontext(J);
9739 pdf_annot *annot = ffi_toannot(J, 0);
9740 int has;
9741 fz_try(ctx)
9742 has = pdf_annot_has_vertices(ctx, annot);
9743 fz_catch(ctx)
9744 rethrow(J);
9745 js_pushboolean(J, has);
9746 }
9747
9748 static void ffi_PDFAnnotation_getVertices(js_State *J)
9749 {
9750 fz_context *ctx = js_getcontext(J);
9751 pdf_annot *annot = ffi_toannot(J, 0);
9752 fz_point p;
9753 int i, n = 0;
9754
9755 fz_try(ctx)
9756 n = pdf_annot_vertex_count(ctx, annot);
9757 fz_catch(ctx)
9758 rethrow(J);
9759
9760 js_newarray(J);
9761 for (i = 0; i < n; ++i) {
9762 fz_try(ctx)
9763 p = pdf_annot_vertex(ctx, annot, i);
9764 fz_catch(ctx)
9765 rethrow(J);
9766 ffi_pushpoint(J, p);
9767 js_setindex(J, -2, i);
9768 }
9769 }
9770
9771 static void ffi_PDFAnnotation_setVertices(js_State *J)
9772 {
9773 fz_context *ctx = js_getcontext(J);
9774 pdf_annot *annot = ffi_toannot(J, 0);
9775 fz_point p;
9776 int i, n;
9777
9778 n = fz_maxi(0, js_getlength(J, 1));
9779
9780 fz_try(ctx)
9781 pdf_clear_annot_vertices(ctx, annot);
9782 fz_catch(ctx)
9783 rethrow(J);
9784
9785 for (i = 0; i < n; ++i) {
9786 js_getindex(J, 1, i);
9787 p = ffi_topoint(J, -1);
9788 js_pop(J, 1);
9789
9790 fz_try(ctx)
9791 pdf_add_annot_vertex(ctx, annot, p);
9792 fz_catch(ctx)
9793 rethrow(J);
9794 }
9795 }
9796
9797 static void ffi_PDFAnnotation_clearVertices(js_State *J)
9798 {
9799 fz_context *ctx = js_getcontext(J);
9800 pdf_annot *annot = ffi_toannot(J, 0);
9801
9802 fz_try(ctx)
9803 pdf_clear_annot_vertices(ctx, annot);
9804 fz_catch(ctx)
9805 rethrow(J);
9806 }
9807
9808 static void ffi_PDFAnnotation_addVertex(js_State *J)
9809 {
9810 fz_context *ctx = js_getcontext(J);
9811 pdf_annot *annot = ffi_toannot(J, 0);
9812 fz_point p = ffi_topoint(J, 1);
9813
9814 fz_try(ctx)
9815 pdf_add_annot_vertex(ctx, annot, p);
9816 fz_catch(ctx)
9817 rethrow(J);
9818 }
9819
9820 static void ffi_PDFAnnotation_hasInkList(js_State *J)
9821 {
9822 fz_context *ctx = js_getcontext(J);
9823 pdf_annot *annot = ffi_toannot(J, 0);
9824 int has;
9825 fz_try(ctx)
9826 has = pdf_annot_has_ink_list(ctx, annot);
9827 fz_catch(ctx)
9828 rethrow(J);
9829 js_pushboolean(J, has);
9830 }
9831
9832 /* Returns an array of strokes, where each stroke is an array of points, where
9833 each point is a two element array consisting of the point's x and y coordinates. */
9834 static void ffi_PDFAnnotation_getInkList(js_State *J)
9835 {
9836 fz_context *ctx = js_getcontext(J);
9837 pdf_annot *annot = ffi_toannot(J, 0);
9838 int i, k, m = 0, n = 0;
9839 fz_point pt;
9840
9841 js_newarray(J);
9842
9843 fz_try(ctx)
9844 n = pdf_annot_ink_list_count(ctx, annot);
9845 fz_catch(ctx)
9846 rethrow(J);
9847
9848 for (i = 0; i < n; ++i) {
9849 fz_try(ctx)
9850 m = pdf_annot_ink_list_stroke_count(ctx, annot, i);
9851 fz_catch(ctx)
9852 rethrow(J);
9853
9854 js_newarray(J);
9855 for (k = 0; k < m; ++k) {
9856 fz_try(ctx)
9857 pt = pdf_annot_ink_list_stroke_vertex(ctx, annot, i, k);
9858 fz_catch(ctx)
9859 rethrow(J);
9860 ffi_pushpoint(J, pt);
9861 js_setindex(J, -2, k);
9862 }
9863 js_setindex(J, -2, i);
9864 }
9865 }
9866
9867 #define MAX_INK_STROKE 256
9868 #define MAX_INK_POINT 16384
9869
9870 /* Takes an argument on the same format as getInkList returns. */
9871 static void ffi_PDFAnnotation_setInkList(js_State *J)
9872 {
9873 fz_context *ctx = js_getcontext(J);
9874 pdf_annot *annot = ffi_toannot(J, 0);
9875 fz_point *points = NULL;
9876 int *counts = NULL;
9877 int n, m, nv, k, i, v;
9878
9879 fz_var(counts);
9880 fz_var(points);
9881
9882 n = fz_maxi(0, js_getlength(J, 1));
9883 if (n > MAX_INK_STROKE)
9884 js_rangeerror(J, "too many strokes in ink annotation");
9885 nv = 0;
9886 for (i = 0; i < n; ++i) {
9887 js_getindex(J, 1, i);
9888 m = fz_maxi(0, js_getlength(J, -1));
9889 if (m > MAX_INK_POINT)
9890 js_rangeerror(J, "too many points in ink annotation stroke");
9891 nv += m;
9892 if (nv > MAX_INK_POINT)
9893 js_rangeerror(J, "too many points in ink annotation");
9894 js_pop(J, 1);
9895 }
9896
9897 fz_try(ctx) {
9898 counts = fz_malloc(ctx, n * sizeof(int));
9899 points = fz_malloc(ctx, nv * sizeof(fz_point));
9900 } fz_catch(ctx) {
9901 fz_free(ctx, counts);
9902 fz_free(ctx, points);
9903 rethrow(J);
9904 }
9905
9906 if (js_try(J)) {
9907 fz_free(ctx, counts);
9908 fz_free(ctx, points);
9909 js_throw(J);
9910 }
9911 for (i = v = 0; i < n; ++i) {
9912 js_getindex(J, 1, i);
9913 counts[i] = js_getlength(J, -1);
9914 for (k = 0; k < counts[i]; ++k) {
9915 js_getindex(J, -1, k);
9916 points[v] = ffi_topoint(J, -1);
9917 js_pop(J, 1);
9918 ++v;
9919 }
9920 js_pop(J, 1);
9921 }
9922 js_endtry(J);
9923
9924 fz_try(ctx)
9925 pdf_set_annot_ink_list(ctx, annot, n, counts, points);
9926 fz_always(ctx) {
9927 fz_free(ctx, counts);
9928 fz_free(ctx, points);
9929 }
9930 fz_catch(ctx)
9931 rethrow(J);
9932 }
9933
9934 static void ffi_PDFAnnotation_clearInkList(js_State *J)
9935 {
9936 fz_context *ctx = js_getcontext(J);
9937 pdf_annot *annot = ffi_toannot(J, 0);
9938 fz_try(ctx)
9939 pdf_clear_annot_ink_list(ctx, annot);
9940 fz_catch(ctx)
9941 rethrow(J);
9942 }
9943
9944 static void ffi_PDFAnnotation_addInkListStroke(js_State *J)
9945 {
9946 fz_context *ctx = js_getcontext(J);
9947 pdf_annot *annot = ffi_toannot(J, 0);
9948 fz_try(ctx)
9949 pdf_add_annot_ink_list_stroke(ctx, annot);
9950 fz_catch(ctx)
9951 rethrow(J);
9952 }
9953
9954 /* Takes a point argument which is a two element array
9955 consisting of the point's x and y coordinates. */
9956 static void ffi_PDFAnnotation_addInkListStrokeVertex(js_State *J)
9957 {
9958 fz_context *ctx = js_getcontext(J);
9959 pdf_annot *annot = ffi_toannot(J, 0);
9960 fz_point pt = ffi_topoint(J, 1);
9961 fz_try(ctx)
9962 pdf_add_annot_ink_list_stroke_vertex(ctx, annot, pt);
9963 fz_catch(ctx)
9964 rethrow(J);
9965 }
9966
9967 static void ffi_PDFAnnotation_hasAuthor(js_State *J)
9968 {
9969 fz_context *ctx = js_getcontext(J);
9970 pdf_annot *annot = ffi_toannot(J, 0);
9971 int has;
9972 fz_try(ctx)
9973 has = pdf_annot_has_author(ctx, annot);
9974 fz_catch(ctx)
9975 rethrow(J);
9976 js_pushboolean(J, has);
9977 }
9978
9979 static void ffi_PDFAnnotation_getAuthor(js_State *J)
9980 {
9981 fz_context *ctx = js_getcontext(J);
9982 pdf_annot *annot = ffi_toannot(J, 0);
9983 const char *author = NULL;
9984
9985 fz_try(ctx)
9986 author = pdf_annot_author(ctx, annot);
9987 fz_catch(ctx)
9988 rethrow(J);
9989
9990 js_pushstring(J, author);
9991 }
9992
9993 static void ffi_PDFAnnotation_setAuthor(js_State *J)
9994 {
9995 fz_context *ctx = js_getcontext(J);
9996 pdf_annot *annot = ffi_toannot(J, 0);
9997 const char *author = js_tostring(J, 1);
9998
9999 fz_try(ctx)
10000 pdf_set_annot_author(ctx, annot, author);
10001 fz_catch(ctx)
10002 rethrow(J);
10003 }
10004
10005 static void ffi_PDFAnnotation_getCreationDate(js_State *J)
10006 {
10007 fz_context *ctx = js_getcontext(J);
10008 pdf_annot *annot = ffi_toannot(J, 0);
10009 double time;
10010
10011 fz_try(ctx)
10012 time = pdf_annot_creation_date(ctx, annot);
10013 fz_catch(ctx)
10014 rethrow(J);
10015
10016 js_getglobal(J, "Date");
10017 js_pushnumber(J, time * 1000);
10018 js_construct(J, 1);
10019 }
10020
10021 static void ffi_PDFAnnotation_setCreationDate(js_State *J)
10022 {
10023 fz_context *ctx = js_getcontext(J);
10024 pdf_annot *annot = ffi_toannot(J, 0);
10025 double time = js_tonumber(J, 1);
10026
10027 fz_try(ctx)
10028 pdf_set_annot_creation_date(ctx, annot, time / 1000);
10029 fz_catch(ctx)
10030 rethrow(J);
10031 }
10032
10033 static void ffi_PDFAnnotation_getModificationDate(js_State *J)
10034 {
10035 fz_context *ctx = js_getcontext(J);
10036 pdf_annot *annot = ffi_toannot(J, 0);
10037 double time;
10038
10039 fz_try(ctx)
10040 time = pdf_annot_modification_date(ctx, annot);
10041 fz_catch(ctx)
10042 rethrow(J);
10043
10044 js_getglobal(J, "Date");
10045 js_pushnumber(J, time * 1000);
10046 js_construct(J, 1);
10047 }
10048
10049 static void ffi_PDFAnnotation_setModificationDate(js_State *J)
10050 {
10051 fz_context *ctx = js_getcontext(J);
10052 pdf_annot *annot = ffi_toannot(J, 0);
10053 double time = js_tonumber(J, 1);
10054
10055 fz_try(ctx)
10056 pdf_set_annot_modification_date(ctx, annot, time / 1000);
10057 fz_catch(ctx)
10058 rethrow(J);
10059 }
10060
10061 static void ffi_PDFAnnotation_hasLineEndingStyles(js_State *J)
10062 {
10063 fz_context *ctx = js_getcontext(J);
10064 pdf_annot *annot = ffi_toannot(J, 0);
10065 int has;
10066 fz_try(ctx)
10067 has = pdf_annot_has_line_ending_styles(ctx, annot);
10068 fz_catch(ctx)
10069 rethrow(J);
10070 js_pushboolean(J, has);
10071 }
10072
10073 static void ffi_PDFAnnotation_getLineEndingStyles(js_State *J)
10074 {
10075 fz_context *ctx = js_getcontext(J);
10076 pdf_annot *annot = ffi_toannot(J, 0);
10077 enum pdf_line_ending start, end;
10078
10079 js_newarray(J);
10080
10081 fz_try(ctx)
10082 pdf_annot_line_ending_styles(ctx, annot, &start, &end);
10083 fz_catch(ctx)
10084 rethrow(J);
10085
10086 js_newobject(J);
10087 js_pushliteral(J, string_from_line_ending(start));
10088 js_setproperty(J, -2, "start");
10089 js_pushliteral(J, string_from_line_ending(end));
10090 js_setproperty(J, -2, "end");
10091 }
10092
10093 static void ffi_PDFAnnotation_setLineEndingStyles(js_State *J)
10094 {
10095 fz_context *ctx = js_getcontext(J);
10096 pdf_annot *annot = ffi_toannot(J, 0);
10097 enum pdf_line_ending start = line_ending_from_string(js_tostring(J, 1));
10098 enum pdf_line_ending end = line_ending_from_string(js_tostring(J, 2));
10099
10100 fz_try(ctx)
10101 pdf_set_annot_line_ending_styles(ctx, annot, start, end);
10102 fz_catch(ctx)
10103 rethrow(J);
10104 }
10105
10106 static void ffi_PDFAnnotation_hasBorder(js_State *J)
10107 {
10108 fz_context *ctx = js_getcontext(J);
10109 pdf_annot *annot = ffi_toannot(J, 0);
10110 int has;
10111 fz_try(ctx)
10112 has = pdf_annot_has_border(ctx, annot);
10113 fz_catch(ctx)
10114 rethrow(J);
10115 js_pushboolean(J, has);
10116 }
10117
10118 static void ffi_PDFAnnotation_getBorderWidth(js_State *J)
10119 {
10120 fz_context *ctx = js_getcontext(J);
10121 pdf_annot *annot = ffi_toannot(J, 0);
10122 float width;
10123 fz_try(ctx)
10124 width = pdf_annot_border_width(ctx, annot);
10125 fz_catch(ctx)
10126 rethrow(J);
10127 js_pushnumber(J, width);
10128 }
10129
10130 static void ffi_PDFAnnotation_setBorderWidth(js_State *J)
10131 {
10132 fz_context *ctx = js_getcontext(J);
10133 pdf_annot *annot = ffi_toannot(J, 0);
10134 float width = js_tonumber(J, 1);
10135 fz_try(ctx)
10136 pdf_set_annot_border_width(ctx, annot, width);
10137 fz_catch(ctx)
10138 rethrow(J);
10139 }
10140
10141 static void ffi_PDFAnnotation_getBorderStyle(js_State *J)
10142 {
10143 fz_context *ctx = js_getcontext(J);
10144 pdf_annot *annot = ffi_toannot(J, 0);
10145 enum pdf_border_style style;
10146 fz_try(ctx)
10147 style = pdf_annot_border_style(ctx, annot);
10148 fz_catch(ctx)
10149 rethrow(J);
10150 js_pushliteral(J, string_from_border_style(style));
10151 }
10152
10153 static void ffi_PDFAnnotation_setBorderStyle(js_State *J)
10154 {
10155 fz_context *ctx = js_getcontext(J);
10156 pdf_annot *annot = ffi_toannot(J, 0);
10157 const char *str = js_iscoercible(J, 1) ? js_tostring(J, 1) : "Solid";
10158 enum pdf_border_style style = border_style_from_string(str);
10159 fz_try(ctx)
10160 pdf_set_annot_border_style(ctx, annot, style);
10161 fz_catch(ctx)
10162 rethrow(J);
10163 }
10164
10165 static void ffi_PDFAnnotation_getBorderDashCount(js_State *J)
10166 {
10167 fz_context *ctx = js_getcontext(J);
10168 pdf_annot *annot = ffi_toannot(J, 0);
10169 int count;
10170 fz_try(ctx)
10171 count = pdf_annot_border_dash_count(ctx, annot);
10172 fz_catch(ctx)
10173 rethrow(J);
10174 js_pushnumber(J, count);
10175 }
10176
10177 static void ffi_PDFAnnotation_getBorderDashItem(js_State *J)
10178 {
10179 fz_context *ctx = js_getcontext(J);
10180 pdf_annot *annot = ffi_toannot(J, 0);
10181 int i = js_tointeger(J, 1);
10182 float length;
10183 fz_try(ctx)
10184 length = pdf_annot_border_dash_item(ctx, annot, i);
10185 fz_catch(ctx)
10186 rethrow(J);
10187 js_pushnumber(J, length);
10188 }
10189
10190 static void ffi_PDFAnnotation_clearBorderDash(js_State *J)
10191 {
10192 fz_context *ctx = js_getcontext(J);
10193 pdf_annot *annot = ffi_toannot(J, 0);
10194 fz_try(ctx)
10195 pdf_clear_annot_border_dash(ctx, annot);
10196 fz_catch(ctx)
10197 rethrow(J);
10198 }
10199
10200 static void ffi_PDFAnnotation_addBorderDashItem(js_State *J)
10201 {
10202 fz_context *ctx = js_getcontext(J);
10203 pdf_annot *annot = ffi_toannot(J, 0);
10204 float length = js_tonumber(J, 1);
10205 fz_try(ctx)
10206 pdf_add_annot_border_dash_item(ctx, annot, length);
10207 fz_catch(ctx)
10208 rethrow(J);
10209 }
10210
10211 static void ffi_PDFAnnotation_setBorderDashPattern(js_State *J)
10212 {
10213 fz_context *ctx = js_getcontext(J);
10214 pdf_annot *annot = ffi_toannot(J, 0);
10215 int i, n = fz_maxi(0, js_getlength(J, 1));
10216 float length;
10217
10218 fz_try(ctx)
10219 pdf_clear_annot_border_dash(ctx, annot);
10220 fz_catch(ctx)
10221 rethrow(J);
10222
10223 for (i = 0; i < n; ++i)
10224 {
10225 js_getindex(J, 1, i);
10226 length = js_tonumber(J, -1);
10227 js_pop(J, 1);
10228 fz_try(ctx)
10229 pdf_add_annot_border_dash_item(ctx, annot, length);
10230 fz_catch(ctx)
10231 rethrow(J);
10232 }
10233 }
10234
10235 static void ffi_PDFAnnotation_hasBorderEffect(js_State *J)
10236 {
10237 fz_context *ctx = js_getcontext(J);
10238 pdf_annot *annot = ffi_toannot(J, 0);
10239 int has;
10240 fz_try(ctx)
10241 has = pdf_annot_has_border_effect(ctx, annot);
10242 fz_catch(ctx)
10243 rethrow(J);
10244 js_pushboolean(J, has);
10245 }
10246
10247 static void ffi_PDFAnnotation_getBorderEffect(js_State *J)
10248 {
10249 fz_context *ctx = js_getcontext(J);
10250 pdf_annot *annot = ffi_toannot(J, 0);
10251 enum pdf_border_effect effect;
10252 fz_try(ctx)
10253 effect = pdf_annot_border_effect(ctx, annot);
10254 fz_catch(ctx)
10255 rethrow(J);
10256 js_pushliteral(J, string_from_border_effect(effect));
10257 }
10258
10259 static void ffi_PDFAnnotation_setBorderEffect(js_State *J)
10260 {
10261 fz_context *ctx = js_getcontext(J);
10262 pdf_annot *annot = ffi_toannot(J, 0);
10263 const char *str = js_iscoercible(J, 1) ? js_tostring(J, 1) : "None";
10264 enum pdf_border_effect effect = border_effect_from_string(str);
10265 fz_try(ctx)
10266 pdf_set_annot_border_effect(ctx, annot, effect);
10267 fz_catch(ctx)
10268 rethrow(J);
10269 }
10270
10271 static void ffi_PDFAnnotation_getBorderEffectIntensity(js_State *J)
10272 {
10273 fz_context *ctx = js_getcontext(J);
10274 pdf_annot *annot = ffi_toannot(J, 0);
10275 float intensity;
10276 fz_try(ctx)
10277 intensity = pdf_annot_border_effect_intensity(ctx, annot);
10278 fz_catch(ctx)
10279 rethrow(J);
10280 js_pushnumber(J, intensity);
10281 }
10282
10283 static void ffi_PDFAnnotation_setBorderEffectIntensity(js_State *J)
10284 {
10285 fz_context *ctx = js_getcontext(J);
10286 pdf_annot *annot = ffi_toannot(J, 0);
10287 float intensity = js_tonumber(J, 1);
10288 fz_try(ctx)
10289 pdf_set_annot_border_effect_intensity(ctx, annot, intensity);
10290 fz_catch(ctx)
10291 rethrow(J);
10292 }
10293
10294 static void ffi_PDFAnnotation_hasIcon(js_State *J)
10295 {
10296 fz_context *ctx = js_getcontext(J);
10297 pdf_annot *annot = ffi_toannot(J, 0);
10298 int has;
10299 fz_try(ctx)
10300 has = pdf_annot_has_icon_name(ctx, annot);
10301 fz_catch(ctx)
10302 rethrow(J);
10303 js_pushboolean(J, has);
10304 }
10305
10306 static void ffi_PDFAnnotation_getIcon(js_State *J)
10307 {
10308 fz_context *ctx = js_getcontext(J);
10309 pdf_annot *annot = ffi_toannot(J, 0);
10310 const char *name;
10311 fz_try(ctx)
10312 name = pdf_annot_icon_name(ctx, annot);
10313 fz_catch(ctx)
10314 rethrow(J);
10315 js_pushstring(J, name);
10316 }
10317
10318 static void ffi_PDFAnnotation_setIcon(js_State *J)
10319 {
10320 fz_context *ctx = js_getcontext(J);
10321 pdf_annot *annot = ffi_toannot(J, 0);
10322 const char *name = js_tostring(J, 1);
10323 fz_try(ctx)
10324 pdf_set_annot_icon_name(ctx, annot, name);
10325 fz_catch(ctx)
10326 rethrow(J);
10327 }
10328
10329 static void ffi_PDFAnnotation_hasQuadding(js_State *J)
10330 {
10331 fz_context *ctx = js_getcontext(J);
10332 pdf_annot *annot = ffi_toannot(J, 0);
10333 int has;
10334 fz_try(ctx)
10335 has = pdf_annot_has_quadding(ctx, annot);
10336 fz_catch(ctx)
10337 rethrow(J);
10338 js_pushboolean(J, has);
10339 }
10340
10341 static void ffi_PDFAnnotation_getQuadding(js_State *J)
10342 {
10343 fz_context *ctx = js_getcontext(J);
10344 pdf_annot *annot = ffi_toannot(J, 0);
10345 int quadding;
10346 fz_try(ctx)
10347 quadding = pdf_annot_quadding(ctx, annot);
10348 fz_catch(ctx)
10349 rethrow(J);
10350 js_pushnumber(J, quadding);
10351 }
10352
10353 static void ffi_PDFAnnotation_setQuadding(js_State *J)
10354 {
10355 fz_context *ctx = js_getcontext(J);
10356 pdf_annot *annot = ffi_toannot(J, 0);
10357 int quadding = js_tointeger(J, 1);
10358 fz_try(ctx)
10359 pdf_set_annot_quadding(ctx, annot, quadding);
10360 fz_catch(ctx)
10361 rethrow(J);
10362 }
10363
10364 static void ffi_PDFAnnotation_getLanguage(js_State *J)
10365 {
10366 fz_context *ctx = js_getcontext(J);
10367 pdf_annot *annot = ffi_toannot(J, 0);
10368 const char *ret;
10369 char lang[8];
10370 fz_try(ctx)
10371 ret = fz_string_from_text_language(lang, pdf_annot_language(ctx, annot));
10372 fz_catch(ctx)
10373 rethrow(J);
10374
10375 if (ret)
10376 js_pushstring(J, lang);
10377 else
10378 js_pushnull(J);
10379 }
10380
10381 static void ffi_PDFAnnotation_setLanguage(js_State *J)
10382 {
10383 fz_context *ctx = js_getcontext(J);
10384 pdf_annot *annot = ffi_toannot(J, 0);
10385 const char *lang = js_tostring(J, 1);
10386 fz_try(ctx)
10387 pdf_set_annot_language(ctx, annot, fz_text_language_from_string(lang));
10388 fz_catch(ctx)
10389 rethrow(J);
10390 }
10391
10392 static void ffi_PDFAnnotation_hasIntent(js_State *J)
10393 {
10394 fz_context *ctx = js_getcontext(J);
10395 pdf_annot *annot = ffi_toannot(J, 0);
10396 int has;
10397 fz_try(ctx)
10398 has = pdf_annot_has_intent(ctx, annot);
10399 fz_catch(ctx)
10400 rethrow(J);
10401 js_pushboolean(J, has);
10402 }
10403
10404 static void ffi_PDFAnnotation_getIntent(js_State *J)
10405 {
10406 fz_context *ctx = js_getcontext(J);
10407 pdf_annot *annot = ffi_toannot(J, 0);
10408 const char *intent;
10409 fz_try(ctx)
10410 intent = pdf_string_from_intent(ctx, pdf_annot_intent(ctx, annot));
10411 fz_catch(ctx)
10412 rethrow(J);
10413 js_pushstring(J, intent);
10414 }
10415
10416 static void ffi_PDFAnnotation_setIntent(js_State *J)
10417 {
10418 fz_context *ctx = js_getcontext(J);
10419 pdf_annot *annot = ffi_toannot(J, 0);
10420 const char *intent = js_tostring(J, 1);
10421 fz_try(ctx)
10422 pdf_set_annot_intent(ctx, annot, pdf_intent_from_string(ctx, intent));
10423 fz_catch(ctx)
10424 rethrow(J);
10425 }
10426
10427 static void ffi_PDFAnnotation_hasLine(js_State *J)
10428 {
10429 fz_context *ctx = js_getcontext(J);
10430 pdf_annot *annot = ffi_toannot(J, 0);
10431 int has;
10432 fz_try(ctx)
10433 has = pdf_annot_has_line(ctx, annot);
10434 fz_catch(ctx)
10435 rethrow(J);
10436 js_pushboolean(J, has);
10437 }
10438
10439 /* Returns an array of two point denoting the end points of the
10440 line annotation. Each point is a two element array consisting
10441 of the point's x and y coordinates. */
10442 static void ffi_PDFAnnotation_getLine(js_State *J)
10443 {
10444 fz_context *ctx = js_getcontext(J);
10445 pdf_annot *annot = ffi_toannot(J, 0);
10446 fz_point a, b;
10447 fz_try(ctx)
10448 pdf_annot_line(ctx, annot, &a, &b);
10449 fz_catch(ctx)
10450 rethrow(J);
10451 js_newarray(J);
10452 ffi_pushpoint(J, a);
10453 js_setindex(J, -2, 0);
10454 ffi_pushpoint(J, b);
10455 js_setindex(J, -2, 1);
10456 }
10457
10458 /* Takes two point arguments denoting the end points of the
10459 line annotation. Each point is a two element array consisting
10460 of the point's x and y coordinates. */
10461 static void ffi_PDFAnnotation_setLine(js_State *J)
10462 {
10463 fz_context *ctx = js_getcontext(J);
10464 pdf_annot *annot = ffi_toannot(J, 0);
10465 fz_point a = ffi_topoint(J, 1);
10466 fz_point b = ffi_topoint(J, 2);
10467 fz_try(ctx)
10468 pdf_set_annot_line(ctx, annot, a, b);
10469 fz_catch(ctx)
10470 rethrow(J);
10471 }
10472
10473 static void ffi_PDFAnnotation_getLineLeader(js_State *J)
10474 {
10475 fz_context *ctx = js_getcontext(J);
10476 pdf_annot *annot = ffi_toannot(J, 0);
10477 float v;
10478 fz_try(ctx)
10479 v = pdf_annot_line_leader(ctx, annot);
10480 fz_catch(ctx)
10481 rethrow(J);
10482 js_pushnumber(J, v);
10483 }
10484
10485 static void ffi_PDFAnnotation_getLineLeaderExtension(js_State *J)
10486 {
10487 fz_context *ctx = js_getcontext(J);
10488 pdf_annot *annot = ffi_toannot(J, 0);
10489 float v;
10490 fz_try(ctx)
10491 v = pdf_annot_line_leader_extension(ctx, annot);
10492 fz_catch(ctx)
10493 rethrow(J);
10494 js_pushnumber(J, v);
10495 }
10496
10497 static void ffi_PDFAnnotation_getLineLeaderOffset(js_State *J)
10498 {
10499 fz_context *ctx = js_getcontext(J);
10500 pdf_annot *annot = ffi_toannot(J, 0);
10501 float v;
10502 fz_try(ctx)
10503 v = pdf_annot_line_leader_offset(ctx, annot);
10504 fz_catch(ctx)
10505 rethrow(J);
10506 js_pushnumber(J, v);
10507 }
10508
10509 static void ffi_PDFAnnotation_setLineLeader(js_State *J)
10510 {
10511 fz_context *ctx = js_getcontext(J);
10512 pdf_annot *annot = ffi_toannot(J, 0);
10513 float v = js_tonumber(J, 1);
10514 fz_try(ctx)
10515 pdf_set_annot_line_leader(ctx, annot, v);
10516 fz_catch(ctx)
10517 rethrow(J);
10518 }
10519
10520 static void ffi_PDFAnnotation_setLineLeaderExtension(js_State *J)
10521 {
10522 fz_context *ctx = js_getcontext(J);
10523 pdf_annot *annot = ffi_toannot(J, 0);
10524 float v = js_tonumber(J, 1);
10525 fz_try(ctx)
10526 pdf_set_annot_line_leader_extension(ctx, annot, v);
10527 fz_catch(ctx)
10528 rethrow(J);
10529 }
10530
10531 static void ffi_PDFAnnotation_setLineLeaderOffset(js_State *J)
10532 {
10533 fz_context *ctx = js_getcontext(J);
10534 pdf_annot *annot = ffi_toannot(J, 0);
10535 float v = js_tonumber(J, 1);
10536 fz_try(ctx)
10537 pdf_set_annot_line_leader_offset(ctx, annot, v);
10538 fz_catch(ctx)
10539 rethrow(J);
10540 }
10541
10542 static void ffi_PDFAnnotation_getLineCaption(js_State *J)
10543 {
10544 fz_context *ctx = js_getcontext(J);
10545 pdf_annot *annot = ffi_toannot(J, 0);
10546 int cap;
10547 fz_try(ctx)
10548 cap = pdf_annot_line_caption(ctx, annot);
10549 fz_catch(ctx)
10550 rethrow(J);
10551 js_pushboolean(J, cap);
10552 }
10553
10554 static void ffi_PDFAnnotation_setLineCaption(js_State *J)
10555 {
10556 fz_context *ctx = js_getcontext(J);
10557 pdf_annot *annot = ffi_toannot(J, 0);
10558 int cap = js_toboolean(J, 1);
10559 fz_try(ctx)
10560 pdf_set_annot_line_caption(ctx, annot, cap);
10561 fz_catch(ctx)
10562 rethrow(J);
10563 }
10564
10565 static void ffi_PDFAnnotation_getLineCaptionOffset(js_State *J)
10566 {
10567 fz_context *ctx = js_getcontext(J);
10568 pdf_annot *annot = ffi_toannot(J, 0);
10569 fz_point offset;
10570 fz_try(ctx)
10571 offset = pdf_annot_line_caption_offset(ctx, annot);
10572 fz_catch(ctx)
10573 rethrow(J);
10574 ffi_pushpoint(J, offset);
10575 }
10576
10577 static void ffi_PDFAnnotation_setLineCaptionOffset(js_State *J)
10578 {
10579 fz_context *ctx = js_getcontext(J);
10580 pdf_annot *annot = ffi_toannot(J, 0);
10581 fz_point offset = ffi_topoint(J, 1);
10582 fz_try(ctx)
10583 pdf_set_annot_line_caption_offset(ctx, annot, offset);
10584 fz_catch(ctx)
10585 rethrow(J);
10586 }
10587
10588 static void ffi_PDFAnnotation_hasDefaultAppearance(js_State *J)
10589 {
10590 fz_context *ctx = js_getcontext(J);
10591 pdf_annot *annot = ffi_toannot(J, 0);
10592 int has;
10593 fz_try(ctx)
10594 has = pdf_annot_has_default_appearance(ctx, annot);
10595 fz_catch(ctx)
10596 rethrow(J);
10597 js_pushboolean(J, has);
10598 }
10599
10600 static void ffi_PDFAnnotation_getDefaultAppearance(js_State *J)
10601 {
10602 fz_context *ctx = js_getcontext(J);
10603 pdf_annot *annot = ffi_toannot(J, 0);
10604 const char *font = NULL;
10605 float size = 0.0f;
10606 float color[4] = { 0.0f };
10607 int n = 0;
10608 fz_try(ctx)
10609 pdf_annot_default_appearance(ctx, annot, &font, &size, &n, color);
10610 fz_catch(ctx)
10611 rethrow(J);
10612
10613 if (n != 0 && n != 1 && n != 3 && n != 4)
10614 js_typeerror(J, "invalid number of components for Color");
10615
10616 js_newobject(J);
10617 js_pushstring(J, font);
10618 js_setproperty(J, -2, "font");
10619 js_pushnumber(J, size);
10620 js_setproperty(J, -2, "size");
10621 ffi_pusharray(J, color, n);
10622 js_setproperty(J, -2, "color");
10623 }
10624
10625 static void ffi_PDFAnnotation_setDefaultAppearance(js_State *J)
10626 {
10627 fz_context *ctx = js_getcontext(J);
10628 pdf_annot *annot = ffi_toannot(J, 0);
10629 const char *font = js_tostring(J, 1);
10630 float size = js_tonumber(J, 2);
10631 int i, n = fz_maxi(0, js_getlength(J, 3));
10632 float color[4] = { 0.0f };
10633
10634 if (n != 0 && n != 1 && n != 3 && n != 4)
10635 js_typeerror(J, "invalid number of components for Color");
10636
10637 for (i = 0; i < n && i < (int) nelem(color); ++i) {
10638 js_getindex(J, 3, i);
10639 color[i] = js_tonumber(J, -1);
10640 js_pop(J, 1);
10641 }
10642 fz_try(ctx)
10643 pdf_set_annot_default_appearance(ctx, annot, font, size, n, color);
10644 fz_catch(ctx)
10645 rethrow(J);
10646 }
10647
10648 static void ffi_PDFAnnotation_setStampImage(js_State *J)
10649 {
10650 fz_context *ctx = js_getcontext(J);
10651 pdf_annot *annot = ffi_toannot(J, 0);
10652 fz_image *img = ffi_toimage(J, 1);
10653 fz_try(ctx)
10654 pdf_set_annot_stamp_image(ctx, annot, img);
10655 fz_catch(ctx)
10656 rethrow(J);
10657 }
10658
10659 static void ffi_PDFAnnotation_setStampImageObject(js_State *J)
10660 {
10661 fz_context *ctx = js_getcontext(J);
10662 pdf_annot *annot = ffi_toannot(J, 0);
10663 pdf_document *pdf;
10664 pdf_obj *obj;
10665
10666 fz_try(ctx)
10667 pdf = pdf_get_bound_document(ctx, pdf_annot_obj(ctx, annot));
10668 fz_catch(ctx)
10669 rethrow(J);
10670
10671 obj = ffi_tonewobj(J, pdf, 1);
10672
10673 fz_try(ctx)
10674 pdf_set_annot_stamp_image_obj(ctx, annot, obj);
10675 fz_always(ctx)
10676 pdf_drop_obj(ctx, obj);
10677 fz_catch(ctx)
10678 rethrow(J);
10679 }
10680
10681 static void ffi_PDFAnnotation_getStampImageObject(js_State *J)
10682 {
10683 fz_context *ctx = js_getcontext(J);
10684 pdf_annot *annot = ffi_toannot(J, 0);
10685 pdf_obj *obj = NULL;
10686 fz_try(ctx)
10687 obj = pdf_annot_stamp_image_obj(ctx, annot);
10688 fz_catch(ctx)
10689 rethrow(J);
10690 ffi_pushobj(J, pdf_keep_obj(ctx, obj));
10691 }
10692
10693 static void ffi_PDFAnnotation_setAppearance(js_State *J)
10694 {
10695 fz_context *ctx = js_getcontext(J);
10696 pdf_annot *annot = ffi_toannot(J, 0);
10697 const char *appearance = js_iscoercible(J, 1) ? js_tostring(J, 1) : NULL;
10698 const char *state = js_iscoercible(J, 2) ? js_tostring(J, 2) : NULL;
10699 fz_matrix ctm = ffi_tomatrix(J, 3);
10700 fz_rect bbox = ffi_torect(J, 4);
10701 fz_buffer *contents;
10702 pdf_document *pdf;
10703 pdf_obj *res;
10704
10705 fz_try(ctx)
10706 pdf = pdf_get_bound_document(ctx, pdf_annot_obj(ctx, annot));
10707 fz_catch(ctx)
10708 rethrow(J);
10709
10710 res = ffi_tonewobj(J, pdf, 5);
10711 if (js_try(J)) {
10712 pdf_drop_obj(ctx, res);
10713 js_throw(J);
10714 }
10715 contents = ffi_tonewbuffer(J, 6);
10716 js_endtry(J);
10717
10718 fz_try(ctx)
10719 pdf_set_annot_appearance(ctx, annot, appearance, state, ctm, bbox, res, contents);
10720 fz_always(ctx)
10721 {
10722 fz_drop_buffer(ctx, contents);
10723 pdf_drop_obj(ctx, res);
10724 }
10725 fz_catch(ctx)
10726 rethrow(J);
10727 }
10728
10729 static void ffi_PDFAnnotation_setAppearanceFromDisplayList(js_State *J)
10730 {
10731 fz_context *ctx = js_getcontext(J);
10732 pdf_annot *annot = ffi_toannot(J, 0);
10733 const char *appearance = js_iscoercible(J, 1) ? js_tostring(J, 1) : NULL;
10734 const char *state = js_iscoercible(J, 2) ? js_tostring(J, 2) : NULL;
10735 fz_matrix ctm = ffi_tomatrix(J, 3);
10736 fz_display_list *list = js_touserdata(J, 4, "fz_display_list");
10737 fz_try(ctx)
10738 pdf_set_annot_appearance_from_display_list(ctx, annot, appearance, state, ctm, list);
10739 fz_catch(ctx)
10740 rethrow(J);
10741 }
10742
10743 static void ffi_PDFAnnotation_hasFilespec(js_State *J)
10744 {
10745 fz_context *ctx = js_getcontext(J);
10746 pdf_annot *annot = ffi_toannot(J, 0);
10747 int has;
10748 fz_try(ctx)
10749 has = pdf_annot_has_filespec(ctx, annot);
10750 fz_catch(ctx)
10751 rethrow(J);
10752 js_pushboolean(J, has);
10753 }
10754
10755 static void ffi_PDFAnnotation_getFilespec(js_State *J)
10756 {
10757 fz_context *ctx = js_getcontext(J);
10758 pdf_annot *annot = ffi_toannot(J, 0);
10759 pdf_obj *fs = NULL;
10760
10761 fz_try(ctx)
10762 fs = pdf_annot_filespec(ctx, annot);
10763 fz_catch(ctx)
10764 rethrow(J);
10765
10766 ffi_pushobj(J, pdf_keep_obj(ctx, fs));
10767 }
10768
10769 static void ffi_PDFAnnotation_setFilespec(js_State *J)
10770 {
10771 fz_context *ctx = js_getcontext(J);
10772 pdf_annot *annot = ffi_toannot(J, 0);
10773 pdf_obj *fs = js_iscoercible(J, 1) ? js_touserdata(J, 1, "pdf_obj") : NULL;
10774
10775 fz_try(ctx)
10776 pdf_set_annot_filespec(ctx, annot, fs);
10777 fz_catch(ctx)
10778 rethrow(J);
10779 }
10780
10781 static void ffi_PDFAnnotation_requestResynthesis(js_State *J)
10782 {
10783 fz_context *ctx = js_getcontext(J);
10784 pdf_annot *annot = ffi_toannot(J, 0);
10785 fz_try(ctx)
10786 pdf_annot_request_resynthesis(ctx, annot);
10787 fz_catch(ctx)
10788 rethrow(J);
10789 }
10790
10791 static void ffi_PDFAnnotation_requestSynthesis(js_State *J)
10792 {
10793 fz_context *ctx = js_getcontext(J);
10794 pdf_annot *annot = ffi_toannot(J, 0);
10795 fz_try(ctx)
10796 pdf_annot_request_synthesis(ctx, annot);
10797 fz_catch(ctx)
10798 rethrow(J);
10799 }
10800
10801 static void ffi_PDFAnnotation_update(js_State *J)
10802 {
10803 fz_context *ctx = js_getcontext(J);
10804 pdf_annot *annot = ffi_toannot(J, 0);
10805 int changed = 0;
10806 fz_try(ctx)
10807 changed = pdf_update_annot(ctx, annot);
10808 fz_catch(ctx)
10809 rethrow(J);
10810 js_pushboolean(J, changed);
10811 }
10812
10813 static void ffi_PDFAnnotation_applyRedaction(js_State *J)
10814 {
10815 fz_context *ctx = js_getcontext(J);
10816 pdf_annot *annot = ffi_toannot(J, 0);
10817 pdf_redact_options opts = { 1, PDF_REDACT_IMAGE_PIXELS, 0 };
10818 if (js_isdefined(J, 1)) opts.black_boxes = js_toboolean(J, 1);
10819 if (js_isdefined(J, 2)) opts.image_method = js_tointeger(J, 2);
10820 if (js_isdefined(J, 3)) opts.line_art = js_tointeger(J, 3);
10821 if (js_isdefined(J, 4)) opts.text = js_tointeger(J, 4);
10822 fz_try(ctx)
10823 pdf_apply_redaction(ctx, annot, &opts);
10824 fz_catch(ctx)
10825 rethrow(J);
10826 }
10827
10828 static void ffi_PDFAnnotation_process(js_State *J)
10829 {
10830 fz_context *ctx = js_getcontext(J);
10831 pdf_annot *annot = ffi_toannot(J, 0);
10832 pdf_processor *proc = new_js_processor(ctx, J);
10833 fz_try(ctx)
10834 {
10835 pdf_processor_push_resources(ctx, proc, pdf_page_resources(ctx, pdf_annot_page(ctx, annot)));
10836 pdf_process_annot(ctx, proc, annot, NULL);
10837 pdf_close_processor(ctx, proc);
10838 }
10839 fz_always(ctx)
10840 {
10841 pdf_processor_pop_resources(ctx, proc);
10842 pdf_drop_processor(ctx, proc);
10843 }
10844 fz_catch(ctx)
10845 rethrow(J);
10846 }
10847
10848 static void ffi_PDFAnnotation_getHot(js_State *J)
10849 {
10850 fz_context *ctx = js_getcontext(J);
10851 pdf_annot *annot = ffi_toannot(J, 0);
10852 int hot;
10853 fz_try(ctx)
10854 hot = pdf_annot_hot(ctx, annot);
10855 fz_catch(ctx)
10856 rethrow(J);
10857 js_pushboolean(J, hot);
10858 }
10859
10860 static void ffi_PDFAnnotation_setHot(js_State *J)
10861 {
10862 fz_context *ctx = js_getcontext(J);
10863 pdf_annot *annot = ffi_toannot(J, 0);
10864 int hot = js_toboolean(J, 1);
10865 fz_try(ctx)
10866 pdf_set_annot_hot(ctx, annot, hot);
10867 fz_catch(ctx)
10868 rethrow(J);
10869 }
10870
10871 static void ffi_PDFAnnotation_hasOpen(js_State *J)
10872 {
10873 fz_context *ctx = js_getcontext(J);
10874 pdf_annot *annot = ffi_toannot(J, 0);
10875 int has;
10876 fz_try(ctx)
10877 has = pdf_annot_has_open(ctx, annot);
10878 fz_catch(ctx)
10879 rethrow(J);
10880 js_pushboolean(J, has);
10881 }
10882
10883 static void ffi_PDFAnnotation_getIsOpen(js_State *J)
10884 {
10885 fz_context *ctx = js_getcontext(J);
10886 pdf_annot *annot = ffi_toannot(J, 0);
10887 int isopen;
10888 fz_try(ctx)
10889 isopen = pdf_annot_is_open(ctx, annot);
10890 fz_catch(ctx)
10891 rethrow(J);
10892 js_pushnumber(J, isopen);
10893 }
10894
10895 static void ffi_PDFAnnotation_setIsOpen(js_State *J)
10896 {
10897 fz_context *ctx = js_getcontext(J);
10898 pdf_annot *annot = ffi_toannot(J, 0);
10899 int isopen = js_tointeger(J, 1);
10900 fz_try(ctx)
10901 pdf_set_annot_is_open(ctx, annot, isopen);
10902 fz_catch(ctx)
10903 rethrow(J);
10904 }
10905
10906 static void ffi_PDFAnnotation_hasPopup(js_State *J)
10907 {
10908 fz_context *ctx = js_getcontext(J);
10909 pdf_annot *annot = ffi_toannot(J, 0);
10910 int has;
10911 fz_try(ctx)
10912 has = pdf_annot_has_popup(ctx, annot);
10913 fz_catch(ctx)
10914 rethrow(J);
10915 js_pushboolean(J, has);
10916 }
10917
10918 static void ffi_PDFAnnotation_getPopup(js_State *J)
10919 {
10920 fz_context *ctx = js_getcontext(J);
10921 pdf_annot *annot = ffi_toannot(J, 0);
10922 fz_rect rect;
10923 fz_try(ctx)
10924 rect = pdf_annot_popup(ctx, annot);
10925 fz_catch(ctx)
10926 rethrow(J);
10927 ffi_pushrect(J, rect);
10928 }
10929
10930 static void ffi_PDFAnnotation_setPopup(js_State *J)
10931 {
10932 fz_context *ctx = js_getcontext(J);
10933 pdf_annot *annot = ffi_toannot(J, 0);
10934 fz_rect rect = ffi_torect(J, 1);
10935 fz_try(ctx)
10936 pdf_set_annot_popup(ctx, annot, rect);
10937 fz_catch(ctx)
10938 rethrow(J);
10939 }
10940
10941 static void ffi_PDFAnnotation_hasCallout(js_State *J)
10942 {
10943 fz_context *ctx = js_getcontext(J);
10944 pdf_annot *annot = ffi_toannot(J, 0);
10945 int has;
10946 fz_try(ctx)
10947 has = pdf_annot_has_callout(ctx, annot);
10948 fz_catch(ctx)
10949 rethrow(J);
10950 js_pushboolean(J, has);
10951 }
10952
10953 static void ffi_PDFAnnotation_getCalloutStyle(js_State *J)
10954 {
10955 fz_context *ctx = js_getcontext(J);
10956 pdf_annot *annot = ffi_toannot(J, 0);
10957 enum pdf_line_ending style = PDF_ANNOT_LE_NONE;
10958 fz_try(ctx)
10959 style = pdf_annot_callout_style(ctx, annot);
10960 fz_catch(ctx)
10961 rethrow(J);
10962 js_pushliteral(J, string_from_line_ending(style));
10963 }
10964
10965 static void ffi_PDFAnnotation_setCalloutStyle(js_State *J)
10966 {
10967 fz_context *ctx = js_getcontext(J);
10968 pdf_annot *annot = ffi_toannot(J, 0);
10969 enum pdf_line_ending style = line_ending_from_string(js_tostring(J, 1));
10970 fz_try(ctx)
10971 pdf_set_annot_callout_style(ctx, annot, style);
10972 fz_catch(ctx)
10973 rethrow(J);
10974 }
10975
10976 static void ffi_PDFAnnotation_getCalloutLine(js_State *J)
10977 {
10978 fz_context *ctx = js_getcontext(J);
10979 pdf_annot *annot = ffi_toannot(J, 0);
10980 fz_point line[3];
10981 int i, n;
10982 fz_try(ctx)
10983 pdf_annot_callout_line(ctx, annot, line, &n);
10984 fz_catch(ctx)
10985 rethrow(J);
10986 if (n == 2 || n == 3)
10987 {
10988 js_newarray(J);
10989 for (i = 0; i < n; ++i)
10990 {
10991 ffi_pushpoint(J, line[i]);
10992 js_setindex(J, -2, i);
10993 }
10994 }
10995 else
10996 js_pushnull(J);
10997 }
10998
10999 static void ffi_PDFAnnotation_setCalloutLine(js_State *J)
11000 {
11001 fz_context *ctx = js_getcontext(J);
11002 pdf_annot *annot = ffi_toannot(J, 0);
11003 fz_point line[3] = { 0 };
11004 int i, n;
11005
11006 n = fz_maxi(0, js_getlength(J, 1));
11007 if (n == 2 || n == 3)
11008 {
11009 for (i = 0; i < n; ++i)
11010 {
11011 js_getindex(J, 1, i);
11012 line[i] = ffi_topoint(J, -1);
11013 js_pop(J, 1);
11014 }
11015 }
11016
11017 fz_try(ctx)
11018 pdf_set_annot_callout_line(ctx, annot, line, n);
11019 fz_catch(ctx)
11020 rethrow(J);
11021 }
11022
11023 static void ffi_PDFAnnotation_getCalloutPoint(js_State *J)
11024 {
11025 fz_context *ctx = js_getcontext(J);
11026 pdf_annot *annot = ffi_toannot(J, 0);
11027 fz_point p;
11028 fz_try(ctx)
11029 p = pdf_annot_callout_point(ctx, annot);
11030 fz_catch(ctx)
11031 rethrow(J);
11032 ffi_pushpoint(J, p);
11033 }
11034
11035 static void ffi_PDFAnnotation_setCalloutPoint(js_State *J)
11036 {
11037 fz_context *ctx = js_getcontext(J);
11038 pdf_annot *annot = ffi_toannot(J, 0);
11039 fz_point p = ffi_topoint(J, 1);
11040 fz_try(ctx)
11041 pdf_set_annot_callout_point(ctx, annot, p);
11042 fz_catch(ctx)
11043 rethrow(J);
11044 }
11045
11046 static void ffi_PDFAnnotation_getHiddenForEditing(js_State *J)
11047 {
11048 fz_context *ctx = js_getcontext(J);
11049 pdf_annot *annot = js_touserdata(J, 0, "pdf_annot");
11050 int hidden = 0;
11051
11052 fz_try(ctx)
11053 hidden = pdf_annot_hidden_for_editing(ctx, annot);
11054 fz_catch(ctx)
11055 rethrow(J);
11056
11057 js_pushboolean(J, hidden);
11058 }
11059
11060 static void ffi_PDFAnnotation_setHiddenForEditing(js_State *J)
11061 {
11062 fz_context *ctx = js_getcontext(J);
11063 pdf_annot *annot = js_touserdata(J, 0, "pdf_annot");
11064 int hidden = js_toboolean(J, 1);
11065
11066 fz_try(ctx)
11067 pdf_set_annot_hidden_for_editing(ctx, annot, hidden);
11068 fz_catch(ctx)
11069 rethrow(J);
11070 }
11071
11072 static void ffi_PDFAnnotation_eventEnter(js_State *J)
11073 {
11074 fz_context *ctx = js_getcontext(J);
11075 pdf_annot *annot = js_touserdata(J, 0, "pdf_annot");
11076 fz_try(ctx)
11077 pdf_annot_event_enter(ctx, annot);
11078 fz_catch(ctx)
11079 rethrow(J);
11080 }
11081
11082 static void ffi_PDFAnnotation_eventExit(js_State *J)
11083 {
11084 fz_context *ctx = js_getcontext(J);
11085 pdf_annot *annot = js_touserdata(J, 0, "pdf_annot");
11086 fz_try(ctx)
11087 pdf_annot_event_exit(ctx, annot);
11088 fz_catch(ctx)
11089 rethrow(J);
11090 }
11091
11092 static void ffi_PDFAnnotation_eventDown(js_State *J)
11093 {
11094 fz_context *ctx = js_getcontext(J);
11095 pdf_annot *annot = js_touserdata(J, 0, "pdf_annot");
11096 fz_try(ctx)
11097 pdf_annot_event_down(ctx, annot);
11098 fz_catch(ctx)
11099 rethrow(J);
11100 }
11101
11102 static void ffi_PDFAnnotation_eventUp(js_State *J)
11103 {
11104 fz_context *ctx = js_getcontext(J);
11105 pdf_annot *annot = js_touserdata(J, 0, "pdf_annot");
11106 fz_try(ctx)
11107 pdf_annot_event_up(ctx, annot);
11108 fz_catch(ctx)
11109 rethrow(J);
11110 }
11111
11112 static void ffi_PDFAnnotation_eventFocus(js_State *J)
11113 {
11114 fz_context *ctx = js_getcontext(J);
11115 pdf_annot *annot = js_touserdata(J, 0, "pdf_annot");
11116 fz_try(ctx)
11117 pdf_annot_event_focus(ctx, annot);
11118 fz_catch(ctx)
11119 rethrow(J);
11120 }
11121
11122 static void ffi_PDFAnnotation_eventBlur(js_State *J)
11123 {
11124 fz_context *ctx = js_getcontext(J);
11125 pdf_annot *annot = js_touserdata(J, 0, "pdf_annot");
11126 fz_try(ctx)
11127 pdf_annot_event_blur(ctx, annot);
11128 fz_catch(ctx)
11129 rethrow(J);
11130 }
11131
11132 static void ffi_PDFWidget_getFieldType(js_State *J)
11133 {
11134 fz_context *ctx = js_getcontext(J);
11135 pdf_annot *widget = js_touserdata(J, 0, "pdf_widget");
11136 const char *type;
11137 fz_try(ctx)
11138 type = pdf_field_type_string(ctx, pdf_annot_obj(ctx, widget));
11139 fz_catch(ctx)
11140 rethrow(J);
11141
11142 js_pushstring(J, type);
11143 }
11144
11145 static void ffi_PDFWidget_getFieldFlags(js_State *J)
11146 {
11147 fz_context *ctx = js_getcontext(J);
11148 pdf_annot *widget = js_touserdata(J, 0, "pdf_widget");
11149 int flags;
11150 fz_try(ctx)
11151 flags = pdf_field_flags(ctx, pdf_annot_obj(ctx, widget));
11152 fz_catch(ctx)
11153 rethrow(J);
11154 js_pushnumber(J, flags);
11155 }
11156
11157 static void ffi_PDFWidget_getValue(js_State *J)
11158 {
11159 fz_context *ctx = js_getcontext(J);
11160 pdf_annot *widget = js_touserdata(J, 0, "pdf_widget");
11161 const char *value;
11162 fz_try(ctx)
11163 value = pdf_annot_field_value(ctx, widget);
11164 fz_catch(ctx)
11165 rethrow(J);
11166 js_pushstring(J, value);
11167 }
11168
11169 static void ffi_PDFWidget_setTextValue(js_State *J)
11170 {
11171 fz_context *ctx = js_getcontext(J);
11172 pdf_annot *widget = js_touserdata(J, 0, "pdf_widget");
11173 const char *value = js_tostring(J, 1);
11174 int rc = 0;
11175 fz_try(ctx)
11176 rc = pdf_set_text_field_value(ctx, widget, value);
11177 fz_catch(ctx)
11178 rethrow(J);
11179 js_pushnumber(J, rc);
11180 }
11181
11182 static void ffi_PDFWidget_setChoiceValue(js_State *J)
11183 {
11184 fz_context *ctx = js_getcontext(J);
11185 pdf_annot *widget = js_touserdata(J, 0, "pdf_widget");
11186 const char *value = js_tostring(J, 1);
11187 int rc = 0;
11188 fz_try(ctx)
11189 rc = pdf_set_choice_field_value(ctx, widget, value);
11190 fz_catch(ctx)
11191 rethrow(J);
11192 js_pushnumber(J, rc);
11193 }
11194
11195 static void ffi_PDFWidget_toggle(js_State *J)
11196 {
11197 fz_context *ctx = js_getcontext(J);
11198 pdf_annot *widget = js_touserdata(J, 0, "pdf_widget");
11199 int changed = 0;
11200 fz_try(ctx)
11201 changed = pdf_toggle_widget(ctx, widget);
11202 fz_catch(ctx)
11203 rethrow(J);
11204 js_pushboolean(J, changed);
11205 }
11206
11207 static void ffi_PDFWidget_getMaxLen(js_State *J)
11208 {
11209 fz_context *ctx = js_getcontext(J);
11210 pdf_annot *widget = js_touserdata(J, 0, "pdf_widget");
11211 int maxLen = 0;
11212 fz_try(ctx)
11213 maxLen = pdf_text_widget_max_len(ctx, widget);
11214 fz_catch(ctx)
11215 rethrow(J);
11216 js_pushnumber(J, maxLen);
11217 }
11218
11219 static void ffi_PDFWidget_getOptions(js_State *J)
11220 {
11221 fz_context *ctx = js_getcontext(J);
11222 pdf_annot *widget = js_touserdata(J, 0, "pdf_widget");
11223 int export = js_toboolean(J, 1);
11224 const char *opt;
11225 int i, n;
11226 fz_try(ctx)
11227 n = pdf_choice_field_option_count(ctx, pdf_annot_obj(ctx, widget));
11228 fz_catch(ctx)
11229 rethrow(J);
11230 js_newarray(J);
11231 for (i = 0; i < n; ++i) {
11232 fz_try(ctx)
11233 opt = pdf_choice_field_option(ctx, pdf_annot_obj(ctx, widget), export, i);
11234 fz_catch(ctx)
11235 rethrow(J);
11236 js_pushstring(J, opt);
11237 js_setindex(J, -2, i);
11238 }
11239 }
11240
11241 static void ffi_PDFWidget_eventEnter(js_State *J)
11242 {
11243 fz_context *ctx = js_getcontext(J);
11244 pdf_annot *widget = js_touserdata(J, 0, "pdf_widget");
11245 fz_try(ctx)
11246 pdf_annot_event_enter(ctx, widget);
11247 fz_catch(ctx)
11248 rethrow(J);
11249 }
11250
11251 static void ffi_PDFWidget_eventExit(js_State *J)
11252 {
11253 fz_context *ctx = js_getcontext(J);
11254 pdf_annot *widget = js_touserdata(J, 0, "pdf_widget");
11255 fz_try(ctx)
11256 pdf_annot_event_exit(ctx, widget);
11257 fz_catch(ctx)
11258 rethrow(J);
11259 }
11260
11261 static void ffi_PDFWidget_eventDown(js_State *J)
11262 {
11263 fz_context *ctx = js_getcontext(J);
11264 pdf_annot *widget = js_touserdata(J, 0, "pdf_widget");
11265 fz_try(ctx)
11266 pdf_annot_event_down(ctx, widget);
11267 fz_catch(ctx)
11268 rethrow(J);
11269 }
11270
11271 static void ffi_PDFWidget_eventUp(js_State *J)
11272 {
11273 fz_context *ctx = js_getcontext(J);
11274 pdf_annot *widget = js_touserdata(J, 0, "pdf_widget");
11275 fz_try(ctx)
11276 pdf_annot_event_up(ctx, widget);
11277 fz_catch(ctx)
11278 rethrow(J);
11279 }
11280
11281 static void ffi_PDFWidget_eventFocus(js_State *J)
11282 {
11283 fz_context *ctx = js_getcontext(J);
11284 pdf_annot *widget = js_touserdata(J, 0, "pdf_widget");
11285 fz_try(ctx)
11286 pdf_annot_event_focus(ctx, widget);
11287 fz_catch(ctx)
11288 rethrow(J);
11289 }
11290
11291 static void ffi_PDFWidget_eventBlur(js_State *J)
11292 {
11293 fz_context *ctx = js_getcontext(J);
11294 pdf_annot *widget = js_touserdata(J, 0, "pdf_widget");
11295 fz_try(ctx)
11296 pdf_annot_event_blur(ctx, widget);
11297 fz_catch(ctx)
11298 rethrow(J);
11299 }
11300
11301 static void ffi_PDFWidget_validateSignature(js_State *J)
11302 {
11303 fz_context *ctx = js_getcontext(J);
11304 pdf_annot *widget = js_touserdata(J, 0, "pdf_widget");
11305 int val = 0;
11306 fz_try(ctx)
11307 val = pdf_validate_signature(ctx, widget);
11308 fz_catch(ctx)
11309 rethrow(J);
11310 js_pushnumber(J, val);
11311 }
11312
11313 static void ffi_PDFWidget_checkCertificate(js_State *J)
11314 {
11315 fz_context *ctx = js_getcontext(J);
11316 pdf_annot *widget = js_touserdata(J, 0, "pdf_widget");
11317 pdf_pkcs7_verifier *verifier = NULL;
11318 int val = 0;
11319 fz_var(verifier);
11320 fz_try(ctx)
11321 {
11322 verifier = pkcs7_openssl_new_verifier(ctx);
11323 val = pdf_check_widget_certificate(ctx, verifier, widget);
11324 }
11325 fz_always(ctx)
11326 pdf_drop_verifier(ctx, verifier);
11327 fz_catch(ctx)
11328 rethrow(J);
11329 js_pushliteral(J, pdf_signature_error_description(val));
11330 }
11331
11332 static void ffi_PDFWidget_checkDigest(js_State *J)
11333 {
11334 fz_context *ctx = js_getcontext(J);
11335 pdf_annot *widget = js_touserdata(J, 0, "pdf_widget");
11336 pdf_pkcs7_verifier *verifier = NULL;
11337 pdf_signature_error val = 0;
11338 fz_var(verifier);
11339 fz_try(ctx)
11340 {
11341 verifier = pkcs7_openssl_new_verifier(ctx);
11342 val = pdf_check_widget_digest(ctx, verifier, widget);
11343 }
11344 fz_always(ctx)
11345 pdf_drop_verifier(ctx, verifier);
11346 fz_catch(ctx)
11347 rethrow(J);
11348 js_pushliteral(J, pdf_signature_error_description(val));
11349 }
11350
11351 static void ffi_PDFWidget_incrementalChangesSinceSigning(js_State *J)
11352 {
11353 fz_context *ctx = js_getcontext(J);
11354 pdf_annot *widget = js_touserdata(J, 0, "pdf_widget");
11355 int changed = 0;
11356 fz_try(ctx)
11357 changed = pdf_incremental_change_since_signing_widget(ctx, widget);
11358 fz_catch(ctx)
11359 rethrow(J);
11360 js_pushboolean(J, changed);
11361 }
11362
11363 static void ffi_PDFWidget_getSignatory(js_State *J)
11364 {
11365 fz_context *ctx = js_getcontext(J);
11366 pdf_annot *widget = js_touserdata(J, 0, "pdf_widget");
11367 pdf_pkcs7_verifier *verifier = NULL;
11368 pdf_pkcs7_distinguished_name *dn = NULL;
11369 char buf[500];
11370 fz_var(verifier);
11371 fz_var(dn);
11372 fz_try(ctx)
11373 {
11374 verifier = pkcs7_openssl_new_verifier(ctx);
11375 dn = pdf_signature_get_widget_signatory(ctx, verifier, widget);
11376 if (dn)
11377 {
11378 char *s = pdf_signature_format_distinguished_name(ctx, dn);
11379 fz_strlcpy(buf, s, sizeof buf);
11380 fz_free(ctx, s);
11381 }
11382 else
11383 {
11384 fz_strlcpy(buf, "Signature information missing.", sizeof buf);
11385 }
11386 }
11387 fz_always(ctx)
11388 {
11389 pdf_signature_drop_distinguished_name(ctx, dn);
11390 pdf_drop_verifier(ctx, verifier);
11391 }
11392 fz_catch(ctx)
11393 rethrow(J);
11394 js_pushstring(J, buf);
11395 }
11396
11397 static void ffi_PDFWidget_isSigned(js_State *J)
11398 {
11399 fz_context *ctx = js_getcontext(J);
11400 pdf_annot *widget = js_touserdata(J, 0, "pdf_widget");
11401 int val = 0;
11402 fz_try(ctx)
11403 val = pdf_widget_is_signed(ctx, widget);
11404 fz_catch(ctx)
11405 rethrow(J);
11406 js_pushboolean(J, val);
11407 }
11408
11409 static void ffi_PDFWidget_isReadOnly(js_State *J)
11410 {
11411 fz_context *ctx = js_getcontext(J);
11412 pdf_annot *widget = js_touserdata(J, 0, "pdf_widget");
11413 int val = 0;
11414 fz_try(ctx)
11415 val = pdf_widget_is_readonly(ctx, widget);
11416 fz_catch(ctx)
11417 rethrow(J);
11418 js_pushboolean(J, val);
11419 }
11420
11421 static int check_option(js_State *J, int idx, const char *name) {
11422 int result = 0;
11423 if (js_hasproperty(J, idx, name)) {
11424 if (js_toboolean(J, -1))
11425 result = 1;
11426 js_pop(J, 1);
11427 }
11428 return result;
11429 }
11430
11431 static void ffi_PDFWidget_sign(js_State *J)
11432 {
11433 fz_context *ctx = js_getcontext(J);
11434 pdf_annot *widget = js_touserdata(J, 0, "pdf_widget");
11435 pdf_pkcs7_signer *signer = js_touserdata(J, 1, "pdf_pkcs7_signer");
11436 int flags = 0;
11437 fz_image *graphic = js_iscoercible(J, 3) ? js_touserdata(J, 3, "fz_image") : NULL;
11438 const char *reason = js_iscoercible(J, 4) ? js_tostring(J, 4) : NULL;
11439 const char *location = js_iscoercible(J, 5) ? js_tostring(J, 5) : NULL;
11440
11441 if (js_isobject(J, 2)) {
11442 if (check_option(J, 2, "showLabels"))
11443 flags |= PDF_SIGNATURE_SHOW_LABELS;
11444 if (check_option(J, 2, "showDN"))
11445 flags |= PDF_SIGNATURE_SHOW_DN;
11446 if (check_option(J, 2, "showDate"))
11447 flags |= PDF_SIGNATURE_SHOW_DATE;
11448 if (check_option(J, 2, "showTextName"))
11449 flags |= PDF_SIGNATURE_SHOW_TEXT_NAME;
11450 if (check_option(J, 2, "showGraphicName"))
11451 flags |= PDF_SIGNATURE_SHOW_GRAPHIC_NAME;
11452 if (check_option(J, 2, "showLogo"))
11453 flags |= PDF_SIGNATURE_SHOW_LOGO;
11454 } else {
11455 flags = PDF_SIGNATURE_DEFAULT_APPEARANCE;
11456 }
11457
11458 fz_try(ctx)
11459 pdf_sign_signature(ctx, widget, signer,
11460 flags,
11461 graphic,
11462 reason,
11463 location);
11464 fz_catch(ctx)
11465 rethrow(J);
11466 }
11467
11468 static void ffi_PDFWidget_previewSignature(js_State *J)
11469 {
11470 fz_context *ctx = js_getcontext(J);
11471 pdf_annot *widget = js_touserdata(J, 0, "pdf_widget");
11472 pdf_pkcs7_signer *signer = NULL;
11473 int flags = 0;
11474 fz_image *graphic = js_iscoercible(J, 3) ? js_touserdata(J, 3, "fz_image") : NULL;
11475 const char *reason = js_iscoercible(J, 4) ? js_tostring(J, 4) : NULL;
11476 const char *location = js_iscoercible(J, 5) ? js_tostring(J, 5) : NULL;
11477 fz_pixmap *pixmap;
11478
11479 if (js_isuserdata(J, 1, "pdf_pkcs7_signer"))
11480 signer = js_touserdata(J, 1, "pdf_pkcs7_signer");
11481
11482 if (js_isobject(J, 2)) {
11483 if (check_option(J, 2, "showLabels"))
11484 flags |= PDF_SIGNATURE_SHOW_LABELS;
11485 if (check_option(J, 2, "showDN"))
11486 flags |= PDF_SIGNATURE_SHOW_DN;
11487 if (check_option(J, 2, "showDate"))
11488 flags |= PDF_SIGNATURE_SHOW_DATE;
11489 if (check_option(J, 2, "showTextName"))
11490 flags |= PDF_SIGNATURE_SHOW_TEXT_NAME;
11491 if (check_option(J, 2, "showGraphicName"))
11492 flags |= PDF_SIGNATURE_SHOW_GRAPHIC_NAME;
11493 if (check_option(J, 2, "showLogo"))
11494 flags |= PDF_SIGNATURE_SHOW_LOGO;
11495 } else {
11496 flags = PDF_SIGNATURE_DEFAULT_APPEARANCE;
11497 }
11498
11499 fz_try(ctx) {
11500 fz_rect rect = pdf_annot_rect(ctx, widget);
11501 fz_text_language lang = pdf_annot_language(ctx, widget);
11502
11503 if (pdf_dict_get_inheritable(ctx, pdf_annot_obj(ctx, widget), PDF_NAME(FT)) != PDF_NAME(Sig))
11504 fz_throw(ctx, FZ_ERROR_GENERIC, "annotation is not a signature widget");
11505
11506 pixmap = pdf_preview_signature_as_pixmap(ctx,
11507 rect.x1-rect.x0, rect.y1-rect.y0, lang,
11508 signer,
11509 flags,
11510 graphic,
11511 reason,
11512 location);
11513 }
11514 fz_catch(ctx)
11515 rethrow(J);
11516
11517 ffi_pushpixmap(J, pixmap);
11518 }
11519
11520 static void ffi_PDFWidget_getEditingState(js_State *J)
11521 {
11522 fz_context *ctx = js_getcontext(J);
11523 pdf_annot *widget = js_touserdata(J, 0, "pdf_widget");
11524 int state = 0;
11525
11526 fz_try(ctx)
11527 state = pdf_get_widget_editing_state(ctx, widget);
11528 fz_catch(ctx)
11529 rethrow(J);
11530
11531 js_pushboolean(J, state);
11532 }
11533
11534 static void ffi_PDFWidget_setEditingState(js_State *J)
11535 {
11536 fz_context *ctx = js_getcontext(J);
11537 pdf_annot *widget = js_touserdata(J, 0, "pdf_widget");
11538 int state = js_toboolean(J, 1);
11539
11540 fz_try(ctx)
11541 pdf_set_widget_editing_state(ctx, widget, state);
11542 fz_catch(ctx)
11543 rethrow(J);
11544 }
11545
11546 static void ffi_PDFWidget_clearSignature(js_State *J)
11547 {
11548 fz_context *ctx = js_getcontext(J);
11549 pdf_annot *widget = js_touserdata(J, 0, "pdf_widget");
11550
11551 fz_try(ctx)
11552 pdf_clear_signature(ctx, widget);
11553 fz_catch(ctx)
11554 rethrow(J);
11555 }
11556
11557 static void ffi_PDFWidget_getLabel(js_State *J)
11558 {
11559 fz_context *ctx = js_getcontext(J);
11560 pdf_annot *widget = js_touserdata(J, 0, "pdf_widget");
11561 const char *label = NULL;
11562
11563 fz_try(ctx)
11564 label = pdf_annot_field_label(ctx, widget);
11565 fz_catch(ctx)
11566 rethrow(J);
11567
11568 js_pushstring(J, label);
11569 }
11570
11571 static void ffi_PDFWidget_getName(js_State *J)
11572 {
11573 fz_context *ctx = js_getcontext(J);
11574 pdf_annot *widget = js_touserdata(J, 0, "pdf_widget");
11575 char *name = NULL;
11576
11577 fz_try(ctx)
11578 name = pdf_load_field_name(ctx, pdf_annot_obj(ctx, widget));
11579 fz_catch(ctx)
11580 rethrow(J);
11581
11582 if (js_try(J))
11583 {
11584 fz_free(ctx, name);
11585 js_throw(J);
11586 }
11587
11588 js_pushstring(J, name);
11589
11590 js_endtry(J);
11591 fz_free(ctx, name);
11592 }
11593
11594 static void ffi_PDFWidget_layoutTextWidget(js_State *J)
11595 {
11596 fz_context *ctx = js_getcontext(J);
11597 pdf_annot *widget = js_touserdata(J, 0, "pdf_widget");
11598 fz_layout_block *layout = NULL;
11599 fz_layout_line *line = NULL;
11600 fz_layout_char *chr = NULL;
11601 fz_rect bounds;
11602 fz_matrix mat;
11603 const char *s;
11604 int i, k;
11605
11606 fz_try(ctx)
11607 {
11608 bounds = pdf_bound_widget(ctx, widget);
11609 layout = pdf_layout_text_widget(ctx, widget);
11610 mat = fz_concat(layout->inv_matrix, fz_translate(-bounds.x0, -bounds.y0));
11611 }
11612 fz_catch(ctx)
11613 rethrow(J);
11614
11615 if (js_try(J)) {
11616 fz_drop_layout(ctx, layout);
11617 js_throw(J);
11618 }
11619
11620 js_newobject(J);
11621 ffi_pushmatrix(J, layout->matrix);
11622 js_setproperty(J, -2, "matrix");
11623 ffi_pushmatrix(J, layout->inv_matrix);
11624 js_setproperty(J, -2, "invMatrix");
11625
11626 s = layout->head->p;
11627
11628 js_newarray(J);
11629 for (line = layout->head, i = 0; line; line = line->next, i++)
11630 {
11631 float y = line->y - line->font_size * 0.2f;
11632 float b = line->y + line->font_size;
11633 fz_rect lrect = fz_make_rect(line->x, y, line->x, b);
11634 lrect = fz_transform_rect(lrect, mat);
11635
11636 js_newobject(J);
11637 js_pushnumber(J, line->x);
11638 js_setproperty(J, -2, "x");
11639 js_pushnumber(J, line->y);
11640 js_setproperty(J, -2, "y");
11641 js_pushnumber(J, line->font_size);
11642 js_setproperty(J, -2, "fontSize");
11643 js_pushnumber(J, fz_runeidx(s, line->p));
11644 js_setproperty(J, -2, "index");
11645
11646 js_newarray(J);
11647 for (chr = line->text, k = 0; chr; chr = chr->next, k++)
11648 {
11649 fz_rect crect = fz_make_rect(chr->x, y, chr->x + chr->advance, b);
11650 crect = fz_transform_rect(crect, mat);
11651 lrect = fz_union_rect(lrect, crect);
11652
11653 js_newobject(J);
11654 js_pushnumber(J, chr->x);
11655 js_setproperty(J, -2, "x");
11656 js_pushnumber(J, chr->advance);
11657 js_setproperty(J, -2, "advance");
11658 js_pushnumber(J, fz_runeidx(s, chr->p));
11659 js_setproperty(J, -2, "index");
11660 ffi_pushrect(J, crect);
11661 js_setproperty(J, -2, "rect");
11662 js_setindex(J, -2, k);
11663 }
11664 js_setproperty(J, -2, "chars");
11665
11666 ffi_pushrect(J, lrect);
11667 js_setproperty(J, -2, "rect");
11668
11669 js_setindex(J, -2, i);
11670 }
11671 js_setproperty(J, -2, "lines");
11672
11673 js_endtry(J);
11674 fz_drop_layout(ctx, layout);
11675 }
11676
11677 static void ffi_new_PDFPKCS7Signer(js_State *J)
11678 {
11679 fz_context *ctx = js_getcontext(J);
11680 pdf_pkcs7_signer *signer = NULL;
11681 const char *filename = js_tostring(J, 1);
11682 const char *password = js_tostring(J, 2);
11683 fz_try(ctx)
11684 signer = pkcs7_openssl_read_pfx(ctx, filename, password);
11685 fz_catch(ctx)
11686 rethrow(J);
11687 ffi_pushsigner(J, signer);
11688 }
11689
11690 #endif /* FZ_ENABLE_PDF */
11691
11692 int murun_main(int argc, char **argv)
11693 {
11694 fz_context *ctx;
11695 js_State *J;
11696 int i;
11697
11698 ctx = fz_new_context(NULL, NULL, FZ_STORE_UNLIMITED);
11699 if (!ctx)
11700 {
11701 fprintf(stderr, "cannot initialise context\n");
11702 exit(1);
11703 }
11704
11705 fz_register_document_handlers(ctx);
11706
11707 J = js_newstate(alloc, ctx, JS_STRICT);
11708 if (!J)
11709 {
11710 fprintf(stderr, "cannot initialize mujs state\n");
11711 fz_drop_context(ctx);
11712 exit(1);
11713 }
11714
11715 js_setcontext(J, ctx);
11716 fz_set_user_context(ctx, J);
11717
11718 if (js_try(J))
11719 {
11720 fprintf(stderr, "cannot initialize mujs functions\n");
11721 js_freestate(J);
11722 fz_drop_context(ctx);
11723 exit(1);
11724 }
11725
11726 /* standard command line javascript functions */
11727
11728 js_newcfunction(J, jsB_gc, "gc", 0);
11729 js_setglobal(J, "gc");
11730
11731 js_newcfunction(J, jsB_load, "load", 1);
11732 js_setglobal(J, "load");
11733
11734 js_newcfunction(J, jsB_print, "print", 1);
11735 js_setglobal(J, "print");
11736
11737 js_newcfunction(J, jsB_write, "write", 0);
11738 js_setglobal(J, "write");
11739
11740 js_newcfunction(J, jsB_read, "read", 1);
11741 js_setglobal(J, "read");
11742
11743 js_newcfunction(J, jsB_readline, "readline", 0);
11744 js_setglobal(J, "readline");
11745
11746 js_newcfunction(J, jsB_repr, "repr", 1);
11747 js_setglobal(J, "repr");
11748
11749 js_newcfunction(J, jsB_quit, "quit", 1);
11750 js_setglobal(J, "quit");
11751
11752 js_dostring(J, prefix_js);
11753
11754 /* mupdf module */
11755
11756 /* Create superclass for all userdata objects */
11757 js_dostring(J, "function Userdata() { throw new Error('Userdata is not callable'); }");
11758 js_getglobal(J, "Userdata");
11759 js_getproperty(J, -1, "prototype");
11760 js_setregistry(J, "Userdata");
11761 js_pop(J, 1);
11762
11763 js_getregistry(J, "Userdata");
11764 js_newobjectx(J);
11765 {
11766 jsB_propfun(J, "Archive.getFormat", ffi_Archive_getFormat, 0);
11767 jsB_propfun(J, "Archive.countEntries", ffi_Archive_countEntries, 0);
11768 jsB_propfun(J, "Archive.listEntry", ffi_Archive_listEntry, 1);
11769 jsB_propfun(J, "Archive.hasEntry", ffi_Archive_hasEntry, 1);
11770 jsB_propfun(J, "Archive.readEntry", ffi_Archive_readEntry, 1);
11771 }
11772 js_setregistry(J, "fz_archive");
11773
11774 js_getregistry(J, "fz_archive");
11775 js_newobjectx(J);
11776 {
11777 jsB_propfun(J, "MultiArchive.mountArchive", ffi_MultiArchive_mountArchive, 2);
11778 }
11779 js_setregistry(J, "fz_multi_archive");
11780
11781 js_getregistry(J, "fz_archive");
11782 js_newobjectx(J);
11783 {
11784 jsB_propfun(J, "TreeArchive.add", ffi_TreeArchive_add, 2);
11785 }
11786 js_setregistry(J, "fz_tree_archive");
11787
11788 js_getregistry(J, "Userdata");
11789 js_newobjectx(J);
11790 {
11791 jsB_propfun(J, "Buffer.getLength", ffi_Buffer_getLength, 0);
11792 jsB_propfun(J, "Buffer.readByte", ffi_Buffer_readByte, 1);
11793 jsB_propfun(J, "Buffer.writeByte", ffi_Buffer_writeByte, 1);
11794 jsB_propfun(J, "Buffer.writeRune", ffi_Buffer_writeRune, 1);
11795 jsB_propfun(J, "Buffer.writeLine", ffi_Buffer_writeLine, 1);
11796 jsB_propfun(J, "Buffer.writeBuffer", ffi_Buffer_writeBuffer, 1);
11797 jsB_propfun(J, "Buffer.write", ffi_Buffer_write, 1);
11798 jsB_propfun(J, "Buffer.save", ffi_Buffer_save, 1);
11799 jsB_propfun(J, "Buffer.slice", ffi_Buffer_slice, 2);
11800 jsB_propfun(J, "Buffer.asString", ffi_Buffer_asString, 0);
11801 }
11802 js_setregistry(J, "fz_buffer");
11803
11804 js_getregistry(J, "Userdata");
11805 js_newobjectx(J);
11806 {
11807 jsB_propfun(J, "Document.isPDF", ffi_Document_isPDF, 0);
11808 jsB_propfun(J, "Document.needsPassword", ffi_Document_needsPassword, 0);
11809 jsB_propfun(J, "Document.authenticatePassword", ffi_Document_authenticatePassword, 1);
11810 jsB_propfun(J, "Document.hasPermission", ffi_Document_hasPermission, 1);
11811 jsB_propfun(J, "Document.getMetaData", ffi_Document_getMetaData, 1);
11812 jsB_propfun(J, "Document.setMetaData", ffi_Document_setMetaData, 2);
11813 jsB_propfun(J, "Document.resolveLink", ffi_Document_resolveLink, 1);
11814 jsB_propfun(J, "Document.resolveLinkDestination", ffi_Document_resolveLinkDestination, 1);
11815 jsB_propfun(J, "Document.formatLinkURI", ffi_Document_formatLinkURI, 1);
11816 jsB_propfun(J, "Document.isReflowable", ffi_Document_isReflowable, 0);
11817 jsB_propfun(J, "Document.layout", ffi_Document_layout, 3);
11818 jsB_propfun(J, "Document.countPages", ffi_Document_countPages, 0);
11819 jsB_propfun(J, "Document.loadPage", ffi_Document_loadPage, 1);
11820 jsB_propfun(J, "Document.loadOutline", ffi_Document_loadOutline, 0);
11821 jsB_propfun(J, "Document.outlineIterator", ffi_Document_outlineIterator, 0);
11822 jsB_propfun(J, "Document.asPDF", ffi_Document_asPDF, 0);
11823 }
11824 js_setregistry(J, "fz_document");
11825
11826 js_newobject(J);
11827 {
11828 jsB_propfun(J, "Document.openDocument", ffi_Document_openDocument, 2);
11829 }
11830 js_setglobal(J, "Document");
11831
11832 js_getregistry(J, "Userdata");
11833 js_newobjectx(J);
11834 {
11835 jsB_propfun(J, "Story.place", ffi_Story_place, 2);
11836 jsB_propfun(J, "Story.draw", ffi_Story_draw, 2);
11837 jsB_propfun(J, "Story.document", ffi_Story_document, 0);
11838 }
11839 js_setregistry(J, "fz_story");
11840
11841 js_getregistry(J, "Userdata");
11842 js_newobjectx(J);
11843 {
11844 jsB_propfun(J, "DOM.body", ffi_DOM_body, 0);
11845 jsB_propfun(J, "DOM.documentElement", ffi_DOM_documentElement, 0);
11846 jsB_propfun(J, "DOM.createElement", ffi_DOM_createElement, 1);
11847 jsB_propfun(J, "DOM.createTextNode", ffi_DOM_createTextNode, 1);
11848 jsB_propfun(J, "DOM.find", ffi_DOM_find, 3);
11849 jsB_propfun(J, "DOM.findNext", ffi_DOM_findNext, 3);
11850 jsB_propfun(J, "DOM.appendChild", ffi_DOM_appendChild, 1);
11851 jsB_propfun(J, "DOM.insertBefore", ffi_DOM_insertBefore, 1);
11852 jsB_propfun(J, "DOM.insertAfter", ffi_DOM_insertAfter, 1);
11853 jsB_propfun(J, "DOM.remove", ffi_DOM_remove, 0);
11854 jsB_propfun(J, "DOM.clone", ffi_DOM_clone, 0);
11855 jsB_propfun(J, "DOM.firstChild", ffi_DOM_firstChild, 0);
11856 jsB_propfun(J, "DOM.parent", ffi_DOM_parent, 0);
11857 jsB_propfun(J, "DOM.next", ffi_DOM_next, 0);
11858 jsB_propfun(J, "DOM.previous", ffi_DOM_previous, 0);
11859 jsB_propfun(J, "DOM.addAttribute", ffi_DOM_addAttribute, 2);
11860 jsB_propfun(J, "DOM.removeAttribute", ffi_DOM_removeAttribute, 1);
11861 jsB_propfun(J, "DOM.attribute", ffi_DOM_getAttribute, 1);
11862 jsB_propfun(J, "DOM.getAttributes", ffi_DOM_getAttributes, 0);
11863 }
11864 js_setregistry(J, "fz_xml");
11865
11866 js_getregistry(J, "Userdata");
11867 js_newobjectx(J);
11868 {
11869 jsB_propfun(J, "OutlineIterator.item", ffi_OutlineIterator_item, 0);
11870 jsB_propfun(J, "OutlineIterator.next", ffi_OutlineIterator_next, 0);
11871 jsB_propfun(J, "OutlineIterator.prev", ffi_OutlineIterator_prev, 0);
11872 jsB_propfun(J, "OutlineIterator.up", ffi_OutlineIterator_up, 0);
11873 jsB_propfun(J, "OutlineIterator.down", ffi_OutlineIterator_down, 0);
11874 jsB_propfun(J, "OutlineIterator.insert", ffi_OutlineIterator_insert, 1);
11875 jsB_propfun(J, "OutlineIterator.delete", ffi_OutlineIterator_delete, 0);
11876 jsB_propfun(J, "OutlineIterator.update", ffi_OutlineIterator_update, 1);
11877 }
11878 js_setregistry(J, "fz_outline_iterator");
11879
11880 js_getregistry(J, "Userdata");
11881 js_newobjectx(J);
11882 {
11883 jsB_propfun(J, "Page.isPDF", ffi_Page_isPDF, 0);
11884 jsB_propfun(J, "Page.getBounds", ffi_Page_getBounds, 1);
11885 jsB_propfun(J, "Page.run", ffi_Page_run, 2);
11886 jsB_propfun(J, "Page.runPageContents", ffi_Page_runPageContents, 2);
11887 jsB_propfun(J, "Page.runPageAnnots", ffi_Page_runPageAnnots, 2);
11888 jsB_propfun(J, "Page.runPageWidgets", ffi_Page_runPageWidgets, 2);
11889
11890 jsB_propfun(J, "Page.toPixmap", ffi_Page_toPixmap, 4);
11891 jsB_propfun(J, "Page.toDisplayList", ffi_Page_toDisplayList, 1);
11892 jsB_propfun(J, "Page.toStructuredText", ffi_Page_toStructuredText, 1);
11893 jsB_propfun(J, "Page.search", ffi_Page_search, 0);
11894 jsB_propfun(J, "Page.getLinks", ffi_Page_getLinks, 0);
11895 jsB_propfun(J, "Page.createLink", ffi_Page_createLink, 2);
11896 jsB_propfun(J, "Page.deleteLink", ffi_Page_deleteLink, 1);
11897 jsB_propfun(J, "Page.getLabel", ffi_Page_getLabel, 0);
11898 jsB_propfun(J, "Page.decodeBarcode", ffi_Page_decodeBarcode, 2);
11899 }
11900 js_setregistry(J, "fz_page");
11901
11902 js_getregistry(J, "Userdata");
11903 js_newobjectx(J);
11904 {
11905 jsB_propfun(J, "Link.getBounds", ffi_Link_getBounds, 0);
11906 jsB_propfun(J, "Link.setBounds", ffi_Link_setBounds, 1);
11907 jsB_propfun(J, "Link.getURI", ffi_Link_getURI, 0);
11908 jsB_propfun(J, "Link.setURI", ffi_Link_setURI, 1);
11909 jsB_propfun(J, "Link.isExternal", ffi_Link_isExternal, 0);
11910 }
11911 js_setregistry(J, "fz_link");
11912
11913 js_getregistry(J, "Userdata");
11914 js_newobjectx(J);
11915 {
11916 jsB_propfun(J, "StrokeState.getLineCap", ffi_StrokeState_getLineCap, 0);
11917 jsB_propfun(J, "StrokeState.getLineJoin", ffi_StrokeState_getLineJoin, 0);
11918 jsB_propfun(J, "StrokeState.getLineWidth", ffi_StrokeState_getLineWidth, 0);
11919 jsB_propfun(J, "StrokeState.getMiterLimit", ffi_StrokeState_getMiterLimit, 0);
11920 jsB_propfun(J, "StrokeState.getDashPhase", ffi_StrokeState_getDashPhase, 0);
11921 jsB_propfun(J, "StrokeState.getDashPattern", ffi_StrokeState_getDashPattern, 0);
11922 }
11923 js_setregistry(J, "fz_stroke_state");
11924
11925 js_getregistry(J, "Userdata");
11926 js_newobjectx(J);
11927 {
11928 jsB_propfun(J, "Device.close", ffi_Device_close, 0);
11929
11930 jsB_propfun(J, "Device.fillPath", ffi_Device_fillPath, 7);
11931 jsB_propfun(J, "Device.strokePath", ffi_Device_strokePath, 7);
11932 jsB_propfun(J, "Device.clipPath", ffi_Device_clipPath, 3);
11933 jsB_propfun(J, "Device.clipStrokePath", ffi_Device_clipStrokePath, 3);
11934
11935 jsB_propfun(J, "Device.fillText", ffi_Device_fillText, 6);
11936 jsB_propfun(J, "Device.strokeText", ffi_Device_strokeText, 7);
11937 jsB_propfun(J, "Device.clipText", ffi_Device_clipText, 2);
11938 jsB_propfun(J, "Device.clipStrokeText", ffi_Device_clipStrokeText, 3);
11939 jsB_propfun(J, "Device.ignoreText", ffi_Device_ignoreText, 2);
11940
11941 jsB_propfun(J, "Device.fillShade", ffi_Device_fillShade, 4);
11942 jsB_propfun(J, "Device.fillImage", ffi_Device_fillImage, 4);
11943 jsB_propfun(J, "Device.fillImageMask", ffi_Device_fillImageMask, 6);
11944 jsB_propfun(J, "Device.clipImageMask", ffi_Device_clipImageMask, 2);
11945
11946 jsB_propfun(J, "Device.popClip", ffi_Device_popClip, 0);
11947
11948 jsB_propfun(J, "Device.beginMask", ffi_Device_beginMask, 5);
11949 jsB_propfun(J, "Device.endMask", ffi_Device_endMask, 0);
11950 jsB_propfun(J, "Device.beginGroup", ffi_Device_beginGroup, 6);
11951 jsB_propfun(J, "Device.endGroup", ffi_Device_endGroup, 0);
11952 jsB_propfun(J, "Device.beginTile", ffi_Device_beginTile, 6);
11953 jsB_propfun(J, "Device.endTile", ffi_Device_endTile, 0);
11954
11955 jsB_propfun(J, "Device.beginLayer", ffi_Device_beginLayer, 1);
11956 jsB_propfun(J, "Device.endLayer", ffi_Device_endLayer, 0);
11957
11958 jsB_propfun(J, "Device.renderFlags", ffi_Device_renderFlags, 2);
11959 jsB_propfun(J, "Device.setDefaultColorSpaces", ffi_Device_setDefaultColorSpaces, 1);
11960
11961 jsB_propfun(J, "Device.beginStructure", ffi_Device_beginStructure, 3);
11962 jsB_propfun(J, "Device.endStructure", ffi_Device_endStructure, 0);
11963
11964 jsB_propfun(J, "Device.beginMetatext", ffi_Device_beginMetatext, 2);
11965 jsB_propfun(J, "Device.endMetatext", ffi_Device_endMetatext, 0);
11966
11967 }
11968 js_setregistry(J, "fz_device");
11969
11970 js_getregistry(J, "Userdata");
11971 js_newobjectx(J);
11972 {
11973 jsB_propfun(J, "ColorSpace.getNumberOfComponents", ffi_ColorSpace_getNumberOfComponents, 0);
11974 jsB_propfun(J, "ColorSpace.getName", ffi_ColorSpace_getName, 0);
11975 jsB_propfun(J, "ColorSpace.getType", ffi_ColorSpace_getType, 0);
11976 jsB_propfun(J, "ColorSpace.toString", ffi_ColorSpace_toString, 0);
11977 jsB_propfun(J, "ColorSpace.isGray", ffi_ColorSpace_isGray, 0);
11978 jsB_propfun(J, "ColorSpace.isRGB", ffi_ColorSpace_isRGB, 0);
11979 jsB_propfun(J, "ColorSpace.isCMYK", ffi_ColorSpace_isCMYK, 0);
11980 jsB_propfun(J, "ColorSpace.isIndexed", ffi_ColorSpace_isIndexed, 0);
11981 jsB_propfun(J, "ColorSpace.isLab", ffi_ColorSpace_isLab, 0);
11982 jsB_propfun(J, "ColorSpace.isDeviceN", ffi_ColorSpace_isDeviceN, 0);
11983 jsB_propfun(J, "ColorSpace.isSubtractive", ffi_ColorSpace_isSubtractive, 0);
11984 }
11985 js_dup(J);
11986 js_setregistry(J, "fz_colorspace");
11987
11988 js_getregistry(J, "Userdata");
11989 js_newobjectx(J);
11990 {
11991 jsB_propfun(J, "DefaultColorSpaces.getDefaultGray", ffi_DefaultColorSpaces_getDefaultGray, 0);
11992 jsB_propfun(J, "DefaultColorSpaces.getDefaultRGB", ffi_DefaultColorSpaces_getDefaultRGB, 0);
11993 jsB_propfun(J, "DefaultColorSpaces.getDefaultCMYK", ffi_DefaultColorSpaces_getDefaultCMYK, 0);
11994 jsB_propfun(J, "DefaultColorSpaces.getOutputIntent", ffi_DefaultColorSpaces_getOutputIntent, 0);
11995 jsB_propfun(J, "DefaultColorSpaces.setDefaultGray", ffi_DefaultColorSpaces_setDefaultGray, 1);
11996 jsB_propfun(J, "DefaultColorSpaces.setDefaultRGB", ffi_DefaultColorSpaces_setDefaultRGB, 1);
11997 jsB_propfun(J, "DefaultColorSpaces.setDefaultCMYK", ffi_DefaultColorSpaces_setDefaultCMYK, 1);
11998 jsB_propfun(J, "DefaultColorSpaces.setOutputIntent", ffi_DefaultColorSpaces_setOutputIntent, 1);
11999 }
12000 js_dup(J);
12001 js_setglobal(J, "DefaultColorSpaces");
12002 js_setregistry(J, "fz_default_colorspaces");
12003
12004 js_getregistry(J, "Userdata");
12005 js_newobjectx(J);
12006 {
12007 jsB_propfun(J, "Shade.getBounds", ffi_Shade_getBounds, 1);
12008 }
12009 js_setregistry(J, "fz_shade");
12010
12011 js_getregistry(J, "Userdata");
12012 js_newobjectx(J);
12013 {
12014 jsB_propfun(J, "Image.getWidth", ffi_Image_getWidth, 0);
12015 jsB_propfun(J, "Image.getHeight", ffi_Image_getHeight, 0);
12016 jsB_propfun(J, "Image.getColorSpace", ffi_Image_getColorSpace, 0);
12017 jsB_propfun(J, "Image.getXResolution", ffi_Image_getXResolution, 0);
12018 jsB_propfun(J, "Image.getYResolution", ffi_Image_getYResolution, 0);
12019 jsB_propfun(J, "Image.getNumberOfComponents", ffi_Image_getNumberOfComponents, 0);
12020 jsB_propfun(J, "Image.getBitsPerComponent", ffi_Image_getBitsPerComponent, 0);
12021 jsB_propfun(J, "Image.getImageMask", ffi_Image_getImageMask, 0);
12022 jsB_propfun(J, "Image.getInterpolate", ffi_Image_getInterpolate, 0);
12023 jsB_propfun(J, "Image.getColorKey", ffi_Image_getColorKey, 0);
12024 jsB_propfun(J, "Image.getDecode", ffi_Image_getDecode, 0);
12025 jsB_propfun(J, "Image.getOrientation", ffi_Image_getOrientation, 0);
12026 jsB_propfun(J, "Image.getMask", ffi_Image_getMask, 0);
12027 jsB_propfun(J, "Image.toPixmap", ffi_Image_toPixmap, 2);
12028 jsB_propfun(J, "Image.setOrientation", ffi_Image_setOrientation, 1);
12029 }
12030 js_setregistry(J, "fz_image");
12031
12032 js_getregistry(J, "Userdata");
12033 js_newobjectx(J);
12034 {
12035 jsB_propfun(J, "Font.getName", ffi_Font_getName, 0);
12036 jsB_propfun(J, "Font.encodeCharacter", ffi_Font_encodeCharacter, 1);
12037 jsB_propfun(J, "Font.advanceGlyph", ffi_Font_advanceGlyph, 2);
12038 jsB_propfun(J, "Font.isMono", ffi_Font_isMono, 0);
12039 jsB_propfun(J, "Font.isSerif", ffi_Font_isSerif, 0);
12040 jsB_propfun(J, "Font.isBold", ffi_Font_isBold, 0);
12041 jsB_propfun(J, "Font.isItalic", ffi_Font_isItalic, 0);
12042 }
12043 js_setregistry(J, "fz_font");
12044
12045 js_getregistry(J, "Userdata");
12046 js_newobjectx(J);
12047 {
12048 jsB_propfun(J, "Text.walk", ffi_Text_walk, 1);
12049 jsB_propfun(J, "Text.showGlyph", ffi_Text_showGlyph, 5);
12050 jsB_propfun(J, "Text.showString", ffi_Text_showString, 4);
12051 jsB_propfun(J, "Text.getBounds", ffi_Text_getBounds, 2);
12052 }
12053 js_setregistry(J, "fz_text");
12054
12055 js_getregistry(J, "Userdata");
12056 js_newobjectx(J);
12057 {
12058 jsB_propfun(J, "Path.walk", ffi_Path_walk, 1);
12059 jsB_propfun(J, "Path.moveTo", ffi_Path_moveTo, 2);
12060 jsB_propfun(J, "Path.lineTo", ffi_Path_lineTo, 2);
12061 jsB_propfun(J, "Path.curveTo", ffi_Path_curveTo, 6);
12062 jsB_propfun(J, "Path.curveToV", ffi_Path_curveToV, 4);
12063 jsB_propfun(J, "Path.curveToY", ffi_Path_curveToY, 4);
12064 jsB_propfun(J, "Path.closePath", ffi_Path_closePath, 0);
12065 jsB_propfun(J, "Path.rect", ffi_Path_rect, 4);
12066 jsB_propfun(J, "Path.getBounds", ffi_Path_getBounds, 2);
12067 jsB_propfun(J, "Path.transform", ffi_Path_transform, 1);
12068 }
12069 js_setregistry(J, "fz_path");
12070
12071 js_getregistry(J, "Userdata");
12072 js_newobjectx(J);
12073 {
12074 jsB_propfun(J, "DisplayList.run", ffi_DisplayList_run, 2);
12075 jsB_propfun(J, "DisplayList.getBounds", ffi_DisplayList_getBounds, 0);
12076 jsB_propfun(J, "DisplayList.toPixmap", ffi_DisplayList_toPixmap, 3);
12077 jsB_propfun(J, "DisplayList.toStructuredText", ffi_DisplayList_toStructuredText, 1);
12078 jsB_propfun(J, "DisplayList.search", ffi_DisplayList_search, 1);
12079 jsB_propfun(J, "DisplayList.decodeBarcode", ffi_DisplayList_decodeBarcode, 2);
12080 }
12081 js_setregistry(J, "fz_display_list");
12082
12083 js_getregistry(J, "Userdata");
12084 js_newobjectx(J);
12085 {
12086 jsB_propfun(J, "StructuredText.walk", ffi_StructuredText_walk, 1);
12087 jsB_propfun(J, "StructuredText.search", ffi_StructuredText_search, 1);
12088 jsB_propfun(J, "StructuredText.highlight", ffi_StructuredText_highlight, 2);
12089 jsB_propfun(J, "StructuredText.copy", ffi_StructuredText_copy, 2);
12090 jsB_propfun(J, "StructuredText.asJSON", ffi_StructuredText_asJSON, 1);
12091 jsB_propfun(J, "StructuredText.asHTML", ffi_StructuredText_asHTML, 1);
12092 jsB_propfun(J, "StructuredText.asText", ffi_StructuredText_asText, 0);
12093 }
12094 js_setregistry(J, "fz_stext_page");
12095
12096 js_getregistry(J, "Userdata");
12097 js_newobjectx(J);
12098 {
12099 jsB_propfun(J, "Pixmap.getBounds", ffi_Pixmap_getBounds, 0);
12100 jsB_propfun(J, "Pixmap.clear", ffi_Pixmap_clear, 1);
12101
12102 jsB_propfun(J, "Pixmap.computeMD5", ffi_Pixmap_computeMD5, 0);
12103 jsB_propfun(J, "Pixmap.getX", ffi_Pixmap_getX, 0);
12104 jsB_propfun(J, "Pixmap.getY", ffi_Pixmap_getY, 0);
12105 jsB_propfun(J, "Pixmap.getWidth", ffi_Pixmap_getWidth, 0);
12106 jsB_propfun(J, "Pixmap.getHeight", ffi_Pixmap_getHeight, 0);
12107 jsB_propfun(J, "Pixmap.getNumberOfComponents", ffi_Pixmap_getNumberOfComponents, 0);
12108 jsB_propfun(J, "Pixmap.getAlpha", ffi_Pixmap_getAlpha, 0);
12109 jsB_propfun(J, "Pixmap.getStride", ffi_Pixmap_getStride, 0);
12110 jsB_propfun(J, "Pixmap.getColorSpace", ffi_Pixmap_getColorSpace, 0);
12111 jsB_propfun(J, "Pixmap.getXResolution", ffi_Pixmap_getXResolution, 0);
12112 jsB_propfun(J, "Pixmap.getYResolution", ffi_Pixmap_getYResolution, 0);
12113 jsB_propfun(J, "Pixmap.getSample", ffi_Pixmap_getSample, 3);
12114 jsB_propfun(J, "Pixmap.getPixels", ffi_Pixmap_getPixels, 0);
12115 jsB_propfun(J, "Pixmap.setResolution", ffi_Pixmap_setResolution, 2);
12116 jsB_propfun(J, "Pixmap.invert", ffi_Pixmap_invert, 0);
12117 jsB_propfun(J, "Pixmap.invertLuminance", ffi_Pixmap_invertLuminance, 0);
12118 jsB_propfun(J, "Pixmap.gamma", ffi_Pixmap_gamma, 1);
12119 jsB_propfun(J, "Pixmap.tint", ffi_Pixmap_tint, 2);
12120 jsB_propfun(J, "Pixmap.warp", ffi_Pixmap_warp, 3);
12121 jsB_propfun(J, "Pixmap.detectSkew", ffi_Pixmap_detectSkew, 0);
12122 jsB_propfun(J, "Pixmap.deskew", ffi_Pixmap_deskew, 2);
12123 jsB_propfun(J, "Pixmap.convertToColorSpace", ffi_Pixmap_convertToColorSpace, 5);
12124 jsB_propfun(J, "Pixmap.autowarp", ffi_Pixmap_autowarp, 1);
12125 jsB_propfun(J, "Pixmap.detectDocument", ffi_Pixmap_detectDocument, 0);
12126 jsB_propfun(J, "Pixmap.decodeBarcode", ffi_Pixmap_decodeBarcode, 1);
12127
12128 // Pixmap.getPixels() - Buffer
12129 // Pixmap.scale()
12130
12131 jsB_propfun(J, "Pixmap.asPNG", ffi_Pixmap_asPNG, 0);
12132 jsB_propfun(J, "Pixmap.asPSD", ffi_Pixmap_asPSD, 0);
12133 jsB_propfun(J, "Pixmap.asPAM", ffi_Pixmap_asPAM, 0);
12134 jsB_propfun(J, "Pixmap.asJPEG", ffi_Pixmap_asJPEG, 2);
12135
12136 jsB_propfun(J, "Pixmap.saveAsPNG", ffi_Pixmap_saveAsPNG, 1);
12137 jsB_propfun(J, "Pixmap.saveAsJPEG", ffi_Pixmap_saveAsJPEG, 2);
12138 jsB_propfun(J, "Pixmap.saveAsPAM", ffi_Pixmap_saveAsPAM, 1);
12139 jsB_propfun(J, "Pixmap.saveAsPNM", ffi_Pixmap_saveAsPNM, 1);
12140 jsB_propfun(J, "Pixmap.saveAsPBM", ffi_Pixmap_saveAsPBM, 1);
12141 jsB_propfun(J, "Pixmap.saveAsPKM", ffi_Pixmap_saveAsPKM, 1);
12142 jsB_propfun(J, "Pixmap.saveAsJPX", ffi_Pixmap_saveAsJPX, 2);
12143 }
12144 js_setregistry(J, "fz_pixmap");
12145
12146 js_getregistry(J, "Userdata");
12147 js_newobjectx(J);
12148 {
12149 jsB_propfun(J, "DocumentWriter.beginPage", ffi_DocumentWriter_beginPage, 1);
12150 jsB_propfun(J, "DocumentWriter.endPage", ffi_DocumentWriter_endPage, 0);
12151 jsB_propfun(J, "DocumentWriter.close", ffi_DocumentWriter_close, 0);
12152 }
12153 js_setregistry(J, "fz_document_writer");
12154
12155 #if FZ_ENABLE_PDF
12156 js_getregistry(J, "fz_document");
12157 js_newobjectx(J);
12158 {
12159 jsB_propfun(J, "PDFDocument.getVersion", ffi_PDFDocument_getVersion, 0);
12160 jsB_propfun(J, "PDFDocument.getTrailer", ffi_PDFDocument_getTrailer, 0);
12161 jsB_propfun(J, "PDFDocument.countObjects", ffi_PDFDocument_countObjects, 0);
12162 jsB_propfun(J, "PDFDocument.createObject", ffi_PDFDocument_createObject, 0);
12163 jsB_propfun(J, "PDFDocument.deleteObject", ffi_PDFDocument_deleteObject, 1);
12164 jsB_propfun(J, "PDFDocument.addObject", ffi_PDFDocument_addObject, 1);
12165 jsB_propfun(J, "PDFDocument.addStream", ffi_PDFDocument_addStream, 2);
12166 jsB_propfun(J, "PDFDocument.addRawStream", ffi_PDFDocument_addRawStream, 2);
12167 jsB_propfun(J, "PDFDocument.addSimpleFont", ffi_PDFDocument_addSimpleFont, 2);
12168 jsB_propfun(J, "PDFDocument.addCJKFont", ffi_PDFDocument_addCJKFont, 4);
12169 jsB_propfun(J, "PDFDocument.addFont", ffi_PDFDocument_addFont, 1);
12170 jsB_propfun(J, "PDFDocument.addImage", ffi_PDFDocument_addImage, 1);
12171 jsB_propfun(J, "PDFDocument.loadImage", ffi_PDFDocument_loadImage, 1);
12172
12173 jsB_propfun(J, "PDFDocument.addEmbeddedFile", ffi_PDFDocument_addEmbeddedFile, 6);
12174 jsB_propfun(J, "PDFDocument.getFilespecParams", ffi_PDFDocument_getFilespecParams, 1);
12175 jsB_propfun(J, "PDFDocument.getEmbeddedFileContents", ffi_PDFDocument_getEmbeddedFileContents, 1);
12176 jsB_propfun(J, "PDFDocument.verifyEmbeddedFileChecksum", ffi_PDFDocument_verifyEmbeddedFileChecksum, 1);
12177 jsB_propfun(J, "PDFDocument.isFilespec", ffi_PDFDocument_isFilespec, 1);
12178 jsB_propfun(J, "PDFDocument.isEmbeddedFile", ffi_PDFDocument_isEmbeddedFile, 1);
12179
12180 jsB_propfun(J, "PDFDocument.addPage", ffi_PDFDocument_addPage, 4);
12181 jsB_propfun(J, "PDFDocument.insertPage", ffi_PDFDocument_insertPage, 2);
12182 jsB_propfun(J, "PDFDocument.deletePage", ffi_PDFDocument_deletePage, 1);
12183 jsB_propfun(J, "PDFDocument.countPages", ffi_PDFDocument_countPages, 0);
12184 jsB_propfun(J, "PDFDocument.findPage", ffi_PDFDocument_findPage, 1);
12185 jsB_propfun(J, "PDFDocument.findPageNumber", ffi_PDFDocument_findPageNumber, 1);
12186 jsB_propfun(J, "PDFDocument.lookupDest", ffi_PDFDocument_lookupDest, 1);
12187 jsB_propfun(J, "PDFDocument.rearrangePages", ffi_PDFDocument_rearrangePages, 1);
12188 jsB_propfun(J, "PDFDocument.save", ffi_PDFDocument_save, 2);
12189 jsB_propfun(J, "PDFDocument.saveToBuffer", ffi_PDFDocument_saveToBuffer, 1);
12190
12191 jsB_propfun(J, "PDFDocument.newNull", ffi_PDFDocument_newNull, 0);
12192 jsB_propfun(J, "PDFDocument.newBoolean", ffi_PDFDocument_newBoolean, 1);
12193 jsB_propfun(J, "PDFDocument.newInteger", ffi_PDFDocument_newInteger, 1);
12194 jsB_propfun(J, "PDFDocument.newReal", ffi_PDFDocument_newReal, 1);
12195 jsB_propfun(J, "PDFDocument.newString", ffi_PDFDocument_newString, 1);
12196 jsB_propfun(J, "PDFDocument.newByteString", ffi_PDFDocument_newByteString, 1);
12197 jsB_propfun(J, "PDFDocument.newName", ffi_PDFDocument_newName, 1);
12198 jsB_propfun(J, "PDFDocument.newIndirect", ffi_PDFDocument_newIndirect, 2);
12199 jsB_propfun(J, "PDFDocument.newArray", ffi_PDFDocument_newArray, 1);
12200 jsB_propfun(J, "PDFDocument.newDictionary", ffi_PDFDocument_newDictionary, 1);
12201
12202 jsB_propfun(J, "PDFDocument.newGraftMap", ffi_PDFDocument_newGraftMap, 0);
12203 jsB_propfun(J, "PDFDocument.graftObject", ffi_PDFDocument_graftObject, 1);
12204 jsB_propfun(J, "PDFDocument.graftPage", ffi_PDFDocument_graftPage, 3);
12205
12206 jsB_propfun(J, "PDFDocument.enableJS", ffi_PDFDocument_enableJS, 0);
12207 jsB_propfun(J, "PDFDocument.disableJS", ffi_PDFDocument_disableJS, 0);
12208 jsB_propfun(J, "PDFDocument.isJSSupported", ffi_PDFDocument_isJSSupported, 0);
12209 jsB_propfun(J, "PDFDocument.setJSEventListener", ffi_PDFDocument_setJSEventListener, 1);
12210
12211 jsB_propfun(J, "PDFDocument.countVersions", ffi_PDFDocument_countVersions, 0);
12212 jsB_propfun(J, "PDFDocument.countUnsavedVersions", ffi_PDFDocument_countUnsavedVersions, 0);
12213 jsB_propfun(J, "PDFDocument.validateChangeHistory", ffi_PDFDocument_validateChangeHistory, 0);
12214 jsB_propfun(J, "PDFDocument.wasPureXFA", ffi_PDFDocument_wasPureXFA, 0);
12215
12216 jsB_propfun(J, "PDFDocument.hasUnsavedChanges", ffi_PDFDocument_hasUnsavedChanges, 0);
12217 jsB_propfun(J, "PDFDocument.wasRepaired", ffi_PDFDocument_wasRepaired, 0);
12218 jsB_propfun(J, "PDFDocument.canBeSavedIncrementally", ffi_PDFDocument_canBeSavedIncrementally, 0);
12219
12220 jsB_propfun(J, "PDFDocument.enableJournal", ffi_PDFDocument_enableJournal, 0);
12221 jsB_propfun(J, "PDFDocument.getJournal", ffi_PDFDocument_getJournal, 0);
12222 jsB_propfun(J, "PDFDocument.beginOperation", ffi_PDFDocument_beginOperation, 1);
12223 jsB_propfun(J, "PDFDocument.beginImplicitOperation", ffi_PDFDocument_beginImplicitOperation, 0);
12224 jsB_propfun(J, "PDFDocument.endOperation", ffi_PDFDocument_endOperation, 0);
12225 jsB_propfun(J, "PDFDocument.abandonOperation", ffi_PDFDocument_abandonOperation, 0);
12226 jsB_propfun(J, "PDFDocument.canUndo", ffi_PDFDocument_canUndo, 0);
12227 jsB_propfun(J, "PDFDocument.canRedo", ffi_PDFDocument_canRedo, 0);
12228 jsB_propfun(J, "PDFDocument.undo", ffi_PDFDocument_undo, 0);
12229 jsB_propfun(J, "PDFDocument.redo", ffi_PDFDocument_redo, 0);
12230 jsB_propfun(J, "PDFDocument.saveJournal", ffi_PDFDocument_saveJournal, 1);
12231
12232 jsB_propfun(J, "PDFDocument.subsetFonts", ffi_PDFDocument_subsetFonts, 0);
12233
12234 jsB_propfun(J, "PDFDocument.setPageLabels", ffi_PDFDocument_setPageLabels, 4);
12235 jsB_propfun(J, "PDFDocument.deletePageLabels", ffi_PDFDocument_deletePageLabels, 1);
12236
12237 jsB_propfun(J, "PDFDocument.countLayers", ffi_PDFDocument_countLayers, 0);
12238 jsB_propfun(J, "PDFDocument.isLayerVisible", ffi_PDFDocument_isLayerVisible, 1);
12239 jsB_propfun(J, "PDFDocument.setLayerVisible", ffi_PDFDocument_setLayerVisible, 2);
12240 jsB_propfun(J, "PDFDocument.getLayerName", ffi_PDFDocument_getLayerName, 1);
12241
12242 jsB_propfun(J, "PDFDocument.countAssociatedFiles", ffi_PDFDocument_countAssociatedFiles, 0);
12243 jsB_propfun(J, "PDFDocument.associatedFile", ffi_PDFDocument_associatedFile, 1);
12244 jsB_propfun(J, "PDFDocument.zugferdProfile", ffi_PDFDocument_zugferdProfile, 0);
12245 jsB_propfun(J, "PDFDocument.zugferdVersion", ffi_PDFDocument_zugferdVersion, 0);
12246 jsB_propfun(J, "PDFDocument.zugferdXML", ffi_PDFDocument_zugferdXML, 0);
12247
12248 jsB_propfun(J, "PDFDocument.getLangauge", ffi_PDFDocument_getLanguage, 0);
12249 jsB_propfun(J, "PDFDocument.setLangauge", ffi_PDFDocument_setLanguage, 1);
12250 jsB_propfun(J, "PDFDocument.bake", ffi_PDFDocument_bake, 2);
12251 }
12252 js_setregistry(J, "pdf_document");
12253
12254 js_getregistry(J, "fz_page");
12255 js_newobjectx(J);
12256 {
12257 jsB_propfun(J, "PDFPage.getObject", ffi_PDFPage_getObject, 0);
12258 jsB_propfun(J, "PDFPage.getWidgets", ffi_PDFPage_getWidgets, 0);
12259 jsB_propfun(J, "PDFPage.getAnnotations", ffi_PDFPage_getAnnotations, 0);
12260 jsB_propfun(J, "PDFPage.createAnnotation", ffi_PDFPage_createAnnotation, 1);
12261 jsB_propfun(J, "PDFPage.deleteAnnotation", ffi_PDFPage_deleteAnnotation, 1);
12262 jsB_propfun(J, "PDFPage.createSignature", ffi_PDFPage_createSignature, 0);
12263 jsB_propfun(J, "PDFPage.update", ffi_PDFPage_update, 0);
12264 jsB_propfun(J, "PDFPage.applyRedactions", ffi_PDFPage_applyRedactions, 4);
12265 jsB_propfun(J, "PDFPage.process", ffi_PDFPage_process, 1);
12266 jsB_propfun(J, "PDFPage.toPixmap", ffi_PDFPage_toPixmap, 6);
12267 jsB_propfun(J, "PDFPage.getTransform", ffi_PDFPage_getTransform, 0);
12268 jsB_propfun(J, "PDFPage.setPageBox", ffi_PDFPage_setPageBox, 2);
12269 jsB_propfun(J, "PDFPage.countAssociatedFiles", ffi_PDFPage_countAssociatedFiles, 0);
12270 jsB_propfun(J, "PDFPage.associatedFile", ffi_PDFPage_associatedFile, 1);
12271 }
12272 js_setregistry(J, "pdf_page");
12273
12274 js_getregistry(J, "Userdata");
12275 js_newobjectx(J);
12276 {
12277 jsB_propfun(J, "PDFAnnotation.getBounds", ffi_PDFAnnotation_getBounds, 0);
12278 jsB_propfun(J, "PDFAnnotation.run", ffi_PDFAnnotation_run, 2);
12279 jsB_propfun(J, "PDFAnnotation.toPixmap", ffi_PDFAnnotation_toPixmap, 3);
12280 jsB_propfun(J, "PDFAnnotation.toDisplayList", ffi_PDFAnnotation_toDisplayList, 0);
12281 jsB_propfun(J, "PDFAnnotation.getObject", ffi_PDFAnnotation_getObject, 0);
12282
12283 jsB_propfun(J, "PDFAnnotation.getType", ffi_PDFAnnotation_getType, 0);
12284 jsB_propfun(J, "PDFAnnotation.getFlags", ffi_PDFAnnotation_getFlags, 0);
12285 jsB_propfun(J, "PDFAnnotation.setFlags", ffi_PDFAnnotation_setFlags, 1);
12286 jsB_propfun(J, "PDFAnnotation.getContents", ffi_PDFAnnotation_getContents, 0);
12287 jsB_propfun(J, "PDFAnnotation.setContents", ffi_PDFAnnotation_setContents, 1);
12288 jsB_propfun(J, "PDFAnnotation.hasRect", ffi_PDFAnnotation_hasRect, 0);
12289 jsB_propfun(J, "PDFAnnotation.getRect", ffi_PDFAnnotation_getRect, 0);
12290 jsB_propfun(J, "PDFAnnotation.setRect", ffi_PDFAnnotation_setRect, 1);
12291 jsB_propfun(J, "PDFAnnotation.getBorder", ffi_PDFAnnotation_getBorderWidth, 0); /* DEPRECATED */
12292 jsB_propfun(J, "PDFAnnotation.setBorder", ffi_PDFAnnotation_setBorderWidth, 1); /* DEPRECATED */
12293 jsB_propfun(J, "PDFAnnotation.getColor", ffi_PDFAnnotation_getColor, 0);
12294 jsB_propfun(J, "PDFAnnotation.setColor", ffi_PDFAnnotation_setColor, 1);
12295 jsB_propfun(J, "PDFAnnotation.hasInteriorColor", ffi_PDFAnnotation_hasInteriorColor, 0);
12296 jsB_propfun(J, "PDFAnnotation.getInteriorColor", ffi_PDFAnnotation_getInteriorColor, 0);
12297 jsB_propfun(J, "PDFAnnotation.setInteriorColor", ffi_PDFAnnotation_setInteriorColor, 1);
12298 jsB_propfun(J, "PDFAnnotation.getOpacity", ffi_PDFAnnotation_getOpacity, 0);
12299 jsB_propfun(J, "PDFAnnotation.setOpacity", ffi_PDFAnnotation_setOpacity, 1);
12300 jsB_propfun(J, "PDFAnnotation.hasAuthor", ffi_PDFAnnotation_hasAuthor, 0);
12301 jsB_propfun(J, "PDFAnnotation.getAuthor", ffi_PDFAnnotation_getAuthor, 0);
12302 jsB_propfun(J, "PDFAnnotation.setAuthor", ffi_PDFAnnotation_setAuthor, 1);
12303 jsB_propfun(J, "PDFAnnotation.getCreationDate", ffi_PDFAnnotation_getCreationDate, 0);
12304 jsB_propfun(J, "PDFAnnotation.setCreationDate", ffi_PDFAnnotation_setCreationDate, 1);
12305 jsB_propfun(J, "PDFAnnotation.getModificationDate", ffi_PDFAnnotation_getModificationDate, 0);
12306 jsB_propfun(J, "PDFAnnotation.setModificationDate", ffi_PDFAnnotation_setModificationDate, 1);
12307 jsB_propfun(J, "PDFAnnotation.hasLineEndingStyles", ffi_PDFAnnotation_hasLineEndingStyles, 0);
12308 jsB_propfun(J, "PDFAnnotation.getLineEndingStyles", ffi_PDFAnnotation_getLineEndingStyles, 0);
12309 jsB_propfun(J, "PDFAnnotation.setLineEndingStyles", ffi_PDFAnnotation_setLineEndingStyles, 2);
12310 jsB_propfun(J, "PDFAnnotation.hasBorder", ffi_PDFAnnotation_hasBorder, 0);
12311 jsB_propfun(J, "PDFAnnotation.getBorderStyle", ffi_PDFAnnotation_getBorderStyle, 0);
12312 jsB_propfun(J, "PDFAnnotation.setBorderStyle", ffi_PDFAnnotation_setBorderStyle, 1);
12313 jsB_propfun(J, "PDFAnnotation.getBorderWidth", ffi_PDFAnnotation_getBorderWidth, 0);
12314 jsB_propfun(J, "PDFAnnotation.setBorderWidth", ffi_PDFAnnotation_setBorderWidth, 1);
12315 jsB_propfun(J, "PDFAnnotation.getBorderDashCount", ffi_PDFAnnotation_getBorderDashCount, 0);
12316 jsB_propfun(J, "PDFAnnotation.getBorderDashItem", ffi_PDFAnnotation_getBorderDashItem, 1);
12317 jsB_propfun(J, "PDFAnnotation.setBorderDashPattern", ffi_PDFAnnotation_setBorderDashPattern, 1);
12318 jsB_propfun(J, "PDFAnnotation.clearBorderDash", ffi_PDFAnnotation_clearBorderDash, 0);
12319 jsB_propfun(J, "PDFAnnotation.addBorderDashItem", ffi_PDFAnnotation_addBorderDashItem, 1);
12320 jsB_propfun(J, "PDFAnnotation.hasBorderEffect", ffi_PDFAnnotation_hasBorderEffect, 0);
12321 jsB_propfun(J, "PDFAnnotation.getBorderEffect", ffi_PDFAnnotation_getBorderEffect, 0);
12322 jsB_propfun(J, "PDFAnnotation.setBorderEffect", ffi_PDFAnnotation_setBorderEffect, 1);
12323 jsB_propfun(J, "PDFAnnotation.getBorderEffectIntensity", ffi_PDFAnnotation_getBorderEffectIntensity, 0);
12324 jsB_propfun(J, "PDFAnnotation.setBorderEffectIntensity", ffi_PDFAnnotation_setBorderEffectIntensity, 1);
12325 jsB_propfun(J, "PDFAnnotation.hasIcon", ffi_PDFAnnotation_hasIcon, 0);
12326 jsB_propfun(J, "PDFAnnotation.getIcon", ffi_PDFAnnotation_getIcon, 0);
12327 jsB_propfun(J, "PDFAnnotation.setIcon", ffi_PDFAnnotation_setIcon, 1);
12328 jsB_propfun(J, "PDFAnnotation.hasQuadding", ffi_PDFAnnotation_hasQuadding, 0);
12329 jsB_propfun(J, "PDFAnnotation.getQuadding", ffi_PDFAnnotation_getQuadding, 0);
12330 jsB_propfun(J, "PDFAnnotation.setQuadding", ffi_PDFAnnotation_setQuadding, 1);
12331 jsB_propfun(J, "PDFAnnotation.getLanguage", ffi_PDFAnnotation_getLanguage, 0);
12332 jsB_propfun(J, "PDFAnnotation.setLanguage", ffi_PDFAnnotation_setLanguage, 1);
12333
12334 jsB_propfun(J, "PDFAnnotation.getStampImageObject", ffi_PDFAnnotation_getStampImageObject, 0);
12335 jsB_propfun(J, "PDFAnnotation.setStampImageObject", ffi_PDFAnnotation_setStampImageObject, 1);
12336 jsB_propfun(J, "PDFAnnotation.setStampImage", ffi_PDFAnnotation_setStampImage, 1);
12337
12338 jsB_propfun(J, "PDFAnnotation.hasIntent", ffi_PDFAnnotation_hasIntent, 0);
12339 jsB_propfun(J, "PDFAnnotation.getIntent", ffi_PDFAnnotation_getIntent, 0);
12340 jsB_propfun(J, "PDFAnnotation.setIntent", ffi_PDFAnnotation_setIntent, 1);
12341
12342 jsB_propfun(J, "PDFAnnotation.hasDefaultAppearance", ffi_PDFAnnotation_hasDefaultAppearance, 0);
12343 jsB_propfun(J, "PDFAnnotation.getDefaultAppearance", ffi_PDFAnnotation_getDefaultAppearance, 0);
12344 jsB_propfun(J, "PDFAnnotation.setDefaultAppearance", ffi_PDFAnnotation_setDefaultAppearance, 3);
12345 jsB_propfun(J, "PDFAnnotation.setAppearance", ffi_PDFAnnotation_setAppearance, 6);
12346 jsB_propfun(J, "PDFAnnotation.setAppearanceFromDisplayList", ffi_PDFAnnotation_setAppearanceFromDisplayList, 4);
12347
12348 jsB_propfun(J, "PDFAnnotation.hasFilespec", ffi_PDFAnnotation_hasFilespec, 0);
12349 jsB_propfun(J, "PDFAnnotation.getFilespec", ffi_PDFAnnotation_getFilespec, 0);
12350 jsB_propfun(J, "PDFAnnotation.setFilespec", ffi_PDFAnnotation_setFilespec, 1);
12351
12352 jsB_propfun(J, "PDFAnnotation.hasLine", ffi_PDFAnnotation_hasLine, 0);
12353 jsB_propfun(J, "PDFAnnotation.getLine", ffi_PDFAnnotation_getLine, 0);
12354 jsB_propfun(J, "PDFAnnotation.setLine", ffi_PDFAnnotation_setLine, 2);
12355 jsB_propfun(J, "PDFAnnotation.getLineLeader", ffi_PDFAnnotation_getLineLeader, 0);
12356 jsB_propfun(J, "PDFAnnotation.setLineLeader", ffi_PDFAnnotation_setLineLeader, 1);
12357 jsB_propfun(J, "PDFAnnotation.getLineLeaderExtension", ffi_PDFAnnotation_getLineLeaderExtension, 0);
12358 jsB_propfun(J, "PDFAnnotation.setLineLeaderExtension", ffi_PDFAnnotation_setLineLeaderExtension, 1);
12359 jsB_propfun(J, "PDFAnnotation.getLineLeaderOffset", ffi_PDFAnnotation_getLineLeaderOffset, 0);
12360 jsB_propfun(J, "PDFAnnotation.setLineLeaderOffset", ffi_PDFAnnotation_setLineLeaderOffset, 1);
12361 jsB_propfun(J, "PDFAnnotation.getLineCaption", ffi_PDFAnnotation_getLineCaption, 0);
12362 jsB_propfun(J, "PDFAnnotation.setLineCaption", ffi_PDFAnnotation_setLineCaption, 1);
12363 jsB_propfun(J, "PDFAnnotation.getLineCaptionOffset", ffi_PDFAnnotation_getLineCaptionOffset, 0);
12364 jsB_propfun(J, "PDFAnnotation.setLineCaptionOffset", ffi_PDFAnnotation_setLineCaptionOffset, 1);
12365
12366 jsB_propfun(J, "PDFAnnotation.hasInkList", ffi_PDFAnnotation_hasInkList, 0);
12367 jsB_propfun(J, "PDFAnnotation.getInkList", ffi_PDFAnnotation_getInkList, 0);
12368 jsB_propfun(J, "PDFAnnotation.setInkList", ffi_PDFAnnotation_setInkList, 1);
12369 jsB_propfun(J, "PDFAnnotation.clearInkList", ffi_PDFAnnotation_clearInkList, 0);
12370 jsB_propfun(J, "PDFAnnotation.addInkListStroke", ffi_PDFAnnotation_addInkListStroke, 0);
12371 jsB_propfun(J, "PDFAnnotation.addInkListStrokeVertex", ffi_PDFAnnotation_addInkListStrokeVertex, 1);
12372
12373 jsB_propfun(J, "PDFAnnotation.hasQuadPoints", ffi_PDFAnnotation_hasQuadPoints, 0);
12374 jsB_propfun(J, "PDFAnnotation.getQuadPoints", ffi_PDFAnnotation_getQuadPoints, 0);
12375 jsB_propfun(J, "PDFAnnotation.setQuadPoints", ffi_PDFAnnotation_setQuadPoints, 1);
12376 jsB_propfun(J, "PDFAnnotation.clearQuadPoints", ffi_PDFAnnotation_clearQuadPoints, 0);
12377 jsB_propfun(J, "PDFAnnotation.addQuadPoint", ffi_PDFAnnotation_addQuadPoint, 1);
12378
12379 jsB_propfun(J, "PDFAnnotation.hasVertices", ffi_PDFAnnotation_hasVertices, 0);
12380 jsB_propfun(J, "PDFAnnotation.getVertices", ffi_PDFAnnotation_getVertices, 0);
12381 jsB_propfun(J, "PDFAnnotation.setVertices", ffi_PDFAnnotation_setVertices, 1);
12382 jsB_propfun(J, "PDFAnnotation.clearVertices", ffi_PDFAnnotation_clearVertices, 0);
12383 jsB_propfun(J, "PDFAnnotation.addVertex", ffi_PDFAnnotation_addVertex, 2);
12384
12385 jsB_propfun(J, "PDFAnnotation.requestSynthesis", ffi_PDFAnnotation_requestSynthesis, 0);
12386 jsB_propfun(J, "PDFAnnotation.requestResynthesis", ffi_PDFAnnotation_requestResynthesis, 0);
12387 jsB_propfun(J, "PDFAnnotation.update", ffi_PDFAnnotation_update, 0);
12388
12389 jsB_propfun(J, "PDFAnnotation.getHot", ffi_PDFAnnotation_getHot, 0);
12390 jsB_propfun(J, "PDFAnnotation.setHot", ffi_PDFAnnotation_setHot, 1);
12391
12392 jsB_propfun(J, "PDFAnnotation.hasOpen", ffi_PDFAnnotation_hasOpen, 0);
12393 jsB_propfun(J, "PDFAnnotation.getIsOpen", ffi_PDFAnnotation_getIsOpen, 0);
12394 jsB_propfun(J, "PDFAnnotation.setIsOpen", ffi_PDFAnnotation_setIsOpen, 1);
12395
12396 jsB_propfun(J, "PDFAnnotation.hasPopup", ffi_PDFAnnotation_hasPopup, 0);
12397 jsB_propfun(J, "PDFAnnotation.getPopup", ffi_PDFAnnotation_getPopup, 0);
12398 jsB_propfun(J, "PDFAnnotation.setPopup", ffi_PDFAnnotation_setPopup, 1);
12399
12400 jsB_propfun(J, "PDFAnnotation.hasRichContents", ffi_PDFAnnotation_hasRichContents, 0);
12401 jsB_propfun(J, "PDFAnnotation.getRichContents", ffi_PDFAnnotation_getRichContents, 0);
12402 jsB_propfun(J, "PDFAnnotation.setRichContents", ffi_PDFAnnotation_setRichContents, 2);
12403 jsB_propfun(J, "PDFAnnotation.getRichDefaults", ffi_PDFAnnotation_getRichDefaults, 0);
12404 jsB_propfun(J, "PDFAnnotation.setRichDefaults", ffi_PDFAnnotation_setRichDefaults, 1);
12405
12406 jsB_propfun(J, "PDFAnnotation.hasCallout", ffi_PDFAnnotation_hasCallout, 0);
12407 jsB_propfun(J, "PDFAnnotation.getCalloutStyle", ffi_PDFAnnotation_getCalloutStyle, 0);
12408 jsB_propfun(J, "PDFAnnotation.setCalloutStyle", ffi_PDFAnnotation_setCalloutStyle, 1);
12409 jsB_propfun(J, "PDFAnnotation.getCalloutPoint", ffi_PDFAnnotation_getCalloutPoint, 0);
12410 jsB_propfun(J, "PDFAnnotation.setCalloutPoint", ffi_PDFAnnotation_setCalloutPoint, 1);
12411 jsB_propfun(J, "PDFAnnotation.getCalloutLine", ffi_PDFAnnotation_getCalloutLine, 0);
12412 jsB_propfun(J, "PDFAnnotation.setCalloutLine", ffi_PDFAnnotation_setCalloutLine, 1);
12413
12414 jsB_propfun(J, "PDFAnnotation.applyRedaction", ffi_PDFAnnotation_applyRedaction, 4);
12415 jsB_propfun(J, "PDFAnnotation.process", ffi_PDFAnnotation_process, 1);
12416
12417 jsB_propfun(J, "PDFAnnotation.getHiddenForEditing", ffi_PDFAnnotation_getHiddenForEditing, 0);
12418 jsB_propfun(J, "PDFAnnotation.setHiddenForEditing", ffi_PDFAnnotation_setHiddenForEditing, 1);
12419
12420 jsB_propfun(J, "PDFAnnotation.eventEnter", ffi_PDFAnnotation_eventEnter, 0);
12421 jsB_propfun(J, "PDFAnnotation.eventExit", ffi_PDFAnnotation_eventExit, 0);
12422 jsB_propfun(J, "PDFAnnotation.eventDown", ffi_PDFAnnotation_eventDown, 0);
12423 jsB_propfun(J, "PDFAnnotation.eventUp", ffi_PDFAnnotation_eventUp, 0);
12424 jsB_propfun(J, "PDFAnnotation.eventFocus", ffi_PDFAnnotation_eventFocus, 0);
12425 jsB_propfun(J, "PDFAnnotation.eventBlur", ffi_PDFAnnotation_eventBlur, 0);
12426 }
12427 js_setregistry(J, "pdf_annot");
12428
12429 js_getregistry(J, "pdf_annot");
12430 js_newobjectx(J);
12431 {
12432 jsB_propfun(J, "PDFWidget.getFieldType", ffi_PDFWidget_getFieldType, 0);
12433 jsB_propfun(J, "PDFWidget.getFieldFlags", ffi_PDFWidget_getFieldFlags, 0);
12434 jsB_propfun(J, "PDFWidget.getValue", ffi_PDFWidget_getValue, 0);
12435 jsB_propfun(J, "PDFWidget.setTextValue", ffi_PDFWidget_setTextValue, 1);
12436 jsB_propfun(J, "PDFWidget.setChoiceValue", ffi_PDFWidget_setChoiceValue, 1);
12437 jsB_propfun(J, "PDFWidget.toggle", ffi_PDFWidget_toggle, 0);
12438 jsB_propfun(J, "PDFWidget.getMaxLen", ffi_PDFWidget_getMaxLen, 0);
12439 jsB_propfun(J, "PDFWidget.getOptions", ffi_PDFWidget_getOptions, 1);
12440 jsB_propfun(J, "PDFWidget.layoutTextWidget", ffi_PDFWidget_layoutTextWidget, 0);
12441
12442 jsB_propfun(J, "PDFWidget.eventEnter", ffi_PDFWidget_eventEnter, 0);
12443 jsB_propfun(J, "PDFWidget.eventExit", ffi_PDFWidget_eventExit, 0);
12444 jsB_propfun(J, "PDFWidget.eventDown", ffi_PDFWidget_eventDown, 0);
12445 jsB_propfun(J, "PDFWidget.eventUp", ffi_PDFWidget_eventUp, 0);
12446 jsB_propfun(J, "PDFWidget.eventFocus", ffi_PDFWidget_eventFocus, 0);
12447 jsB_propfun(J, "PDFWidget.eventBlur", ffi_PDFWidget_eventBlur, 0);
12448
12449 jsB_propfun(J, "PDFWidget.isSigned", ffi_PDFWidget_isSigned, 0);
12450 jsB_propfun(J, "PDFWidget.isReadOnly", ffi_PDFWidget_isReadOnly, 0);
12451 jsB_propfun(J, "PDFWidget.validateSignature", ffi_PDFWidget_validateSignature, 0);
12452 jsB_propfun(J, "PDFWidget.checkCertificate", ffi_PDFWidget_checkCertificate, 0);
12453 jsB_propfun(J, "PDFWidget.checkDigest", ffi_PDFWidget_checkDigest, 0);
12454 jsB_propfun(J, "PDFWidget.incrementalChangesSinceSigning", ffi_PDFWidget_incrementalChangesSinceSigning, 0);
12455 jsB_propfun(J, "PDFWidget.getSignatory", ffi_PDFWidget_getSignatory, 0);
12456 jsB_propfun(J, "PDFWidget.clearSignature", ffi_PDFWidget_clearSignature, 0);
12457 jsB_propfun(J, "PDFWidget.sign", ffi_PDFWidget_sign, 5);
12458 jsB_propfun(J, "PDFWidget.previewSignature", ffi_PDFWidget_previewSignature, 5);
12459 jsB_propfun(J, "PDFWidget.getEditingState", ffi_PDFWidget_getEditingState, 0);
12460 jsB_propfun(J, "PDFWidget.setEditingState", ffi_PDFWidget_setEditingState, 1);
12461 jsB_propfun(J, "PDFWidget.getLabel", ffi_PDFWidget_getLabel, 0);
12462 jsB_propfun(J, "PDFWidget.getName", ffi_PDFWidget_getName, 0);
12463 }
12464 js_setregistry(J, "pdf_widget");
12465
12466 js_getregistry(J, "Userdata");
12467 js_newobjectx(J);
12468 js_setregistry(J, "pdf_pkcs7_signer");
12469
12470 js_getregistry(J, "Userdata");
12471 js_newobjectx(J);
12472 {
12473 jsB_propfun(J, "PDFObject.getInheritable", ffi_PDFObject_getInheritable, 1);
12474 jsB_propfun(J, "PDFObject.get", ffi_PDFObject_get, 1);
12475 jsB_propfun(J, "PDFObject.put", ffi_PDFObject_put, 2);
12476 jsB_propfun(J, "PDFObject.push", ffi_PDFObject_push, 1);
12477 jsB_propfun(J, "PDFObject.delete", ffi_PDFObject_delete, 1);
12478 jsB_propfun(J, "PDFObject.resolve", ffi_PDFObject_resolve, 0);
12479 jsB_propfun(J, "PDFObject.toString", ffi_PDFObject_toString, 2);
12480 jsB_propfun(J, "PDFObject.valueOf", ffi_PDFObject_valueOf, 0);
12481 jsB_propfun(J, "PDFObject.isArray", ffi_PDFObject_isArray, 0);
12482 jsB_propfun(J, "PDFObject.isDictionary", ffi_PDFObject_isDictionary, 0);
12483 jsB_propfun(J, "PDFObject.isIndirect", ffi_PDFObject_isIndirect, 0);
12484 jsB_propfun(J, "PDFObject.isInteger", ffi_PDFObject_isInteger, 0);
12485 jsB_propfun(J, "PDFObject.asIndirect", ffi_PDFObject_asIndirect, 0);
12486 jsB_propfun(J, "PDFObject.isNull", ffi_PDFObject_isNull, 0);
12487 jsB_propfun(J, "PDFObject.isBoolean", ffi_PDFObject_isBoolean, 0);
12488 jsB_propfun(J, "PDFObject.asBoolean", ffi_PDFObject_asBoolean, 0);
12489 jsB_propfun(J, "PDFObject.isNumber", ffi_PDFObject_isNumber, 0);
12490 jsB_propfun(J, "PDFObject.asNumber", ffi_PDFObject_asNumber, 0);
12491 jsB_propfun(J, "PDFObject.isName", ffi_PDFObject_isName, 0);
12492 jsB_propfun(J, "PDFObject.asName", ffi_PDFObject_asName, 0);
12493 jsB_propfun(J, "PDFObject.isReal", ffi_PDFObject_isReal, 0);
12494 jsB_propfun(J, "PDFObject.isString", ffi_PDFObject_isString, 0);
12495 jsB_propfun(J, "PDFObject.asString", ffi_PDFObject_asString, 0);
12496 jsB_propfun(J, "PDFObject.asByteString", ffi_PDFObject_asByteString, 0);
12497 jsB_propfun(J, "PDFObject.isStream", ffi_PDFObject_isStream, 0);
12498 jsB_propfun(J, "PDFObject.readStream", ffi_PDFObject_readStream, 0);
12499 jsB_propfun(J, "PDFObject.readRawStream", ffi_PDFObject_readRawStream, 0);
12500 jsB_propfun(J, "PDFObject.writeObject", ffi_PDFObject_writeObject, 1);
12501 jsB_propfun(J, "PDFObject.writeStream", ffi_PDFObject_writeStream, 1);
12502 jsB_propfun(J, "PDFObject.writeRawStream", ffi_PDFObject_writeRawStream, 1);
12503 jsB_propfun(J, "PDFObject.forEach", ffi_PDFObject_forEach, 1);
12504 jsB_propfun(J, "PDFObject.compare", ffi_PDFObject_compare, 1);
12505 }
12506 js_setregistry(J, "pdf_obj");
12507
12508 js_getregistry(J, "Userdata");
12509 js_newobjectx(J);
12510 {
12511 jsB_propfun(J, "PDFGraftMap.graftObject", ffi_PDFGraftMap_graftObject, 1);
12512 jsB_propfun(J, "PDFGraftMap.graftPage", ffi_PDFGraftMap_graftPage, 3);
12513 }
12514 js_setregistry(J, "pdf_graft_map");
12515 #endif
12516
12517 js_pushglobal(J);
12518 {
12519 #if FZ_ENABLE_PDF
12520 jsB_propcon(J, "pdf_document", "PDFDocument", ffi_new_PDFDocument, 1);
12521 js_getglobal(J, "PDFDocument");
12522 {
12523 jsB_propfun(J, "formatURIFromPathAndDest", ffi_formatURIFromPathAndDest, 2);
12524 jsB_propfun(J, "appendDestToURI", ffi_appendDestToURI, 2);
12525 }
12526 js_pop(J, 1);
12527 #endif
12528
12529 jsB_propcon(J, "fz_archive", "Archive", ffi_new_Archive, 1);
12530 jsB_propcon(J, "fz_multi_archive", "MultiArchive", ffi_new_MultiArchive, 1);
12531 jsB_propcon(J, "fz_tree_archive", "TreeArchive", ffi_new_TreeArchive, 1);
12532 jsB_propcon(J, "fz_buffer", "Buffer", ffi_new_Buffer, 1);
12533 jsB_propcon(J, "fz_pixmap", "Pixmap", ffi_new_Pixmap, 3);
12534 js_getglobal(J, "Pixmap");
12535 {
12536 jsB_propfun(J, "encodeBarcode", ffi_encodeBarcode_Pixmap, 6);
12537 }
12538 js_pop(J, 1);
12539 jsB_propcon(J, "fz_colorspace", "ColorSpace", ffi_new_ColorSpace, 2);
12540 jsB_propcon(J, "fz_image", "Image", ffi_new_Image, 2);
12541 jsB_propcon(J, "fz_font", "Font", ffi_new_Font, 3);
12542 jsB_propcon(J, "fz_text", "Text", ffi_new_Text, 0);
12543 jsB_propcon(J, "fz_path", "Path", ffi_new_Path, 0);
12544 jsB_propcon(J, "fz_display_list", "DisplayList", ffi_new_DisplayList, 1);
12545 jsB_propcon(J, "fz_device", "DrawDevice", ffi_new_DrawDevice, 2);
12546 jsB_propcon(J, "fz_device", "DisplayListDevice", ffi_new_DisplayListDevice, 1);
12547 jsB_propcon(J, "fz_document_writer", "DocumentWriter", ffi_new_DocumentWriter, 3);
12548 jsB_propcon(J, "fz_story", "Story", ffi_new_Story, 4);
12549 jsB_propcon(J, "fz_stroke_state", "StrokeState", ffi_new_StrokeState, 1);
12550 #if FZ_ENABLE_PDF
12551 jsB_propcon(J, "pdf_pkcs7_signer", "PDFPKCS7Signer", ffi_new_PDFPKCS7Signer, 2);
12552 #endif
12553
12554 jsB_propfun(J, "readFile", ffi_readFile, 1);
12555 jsB_propfun(J, "enableICC", ffi_enableICC, 0);
12556 jsB_propfun(J, "disableICC", ffi_disableICC, 0);
12557
12558 jsB_propfun(J, "setUserCSS", ffi_setUserCSS, 2);
12559
12560 jsB_propfun(J, "installLoadFontFunction", ffi_installLoadFontFunction, 1);
12561 }
12562
12563 // declare ColorSpace static objects
12564 js_getglobal(J, "ColorSpace");
12565 {
12566 js_getregistry(J, "fz_colorspace");
12567 js_newuserdata(J, "fz_colorspace", fz_keep_colorspace(ctx, fz_device_gray(ctx)), ffi_gc_fz_colorspace);
12568 js_dup(J);
12569 js_setregistry(J, "DeviceGray");
12570 js_setproperty(J, -2, "DeviceGray");
12571
12572 js_getregistry(J, "fz_colorspace");
12573 js_newuserdata(J, "fz_colorspace", fz_keep_colorspace(ctx, fz_device_rgb(ctx)), ffi_gc_fz_colorspace);
12574 js_dup(J);
12575 js_setregistry(J, "DeviceRGB");
12576 js_setproperty(J, -2, "DeviceRGB");
12577
12578 js_getregistry(J, "fz_colorspace");
12579 js_newuserdata(J, "fz_colorspace", fz_keep_colorspace(ctx, fz_device_bgr(ctx)), ffi_gc_fz_colorspace);
12580 js_dup(J);
12581 js_setregistry(J, "DeviceBGR");
12582 js_setproperty(J, -2, "DeviceBGR");
12583
12584 js_getregistry(J, "fz_colorspace");
12585 js_newuserdata(J, "fz_colorspace", fz_keep_colorspace(ctx, fz_device_cmyk(ctx)), ffi_gc_fz_colorspace);
12586 js_dup(J);
12587 js_setregistry(J, "DeviceCMYK");
12588 js_setproperty(J, -2, "DeviceCMYK");
12589
12590 js_getregistry(J, "fz_colorspace");
12591 js_newuserdata(J, "fz_colorspace", fz_keep_colorspace(ctx, fz_device_lab(ctx)), ffi_gc_fz_colorspace);
12592 js_dup(J);
12593 js_setregistry(J, "Lab");
12594 js_setproperty(J, -2, "Lab");
12595 }
12596 js_pop(J, 1);
12597
12598 // Declare "mupdf" as alias to global object.
12599 js_pushglobal(J);
12600 js_setglobal(J, "mupdf");
12601
12602 js_dostring(J, postfix_js);
12603
12604 js_endtry(J);
12605
12606 if (argc > 1) {
12607 if (js_try(J))
12608 {
12609 fprintf(stderr, "cannot initialize script arguments\n");
12610 js_freestate(J);
12611 fz_drop_context(ctx);
12612 exit(1);
12613 }
12614
12615 // scriptPath and scriptArgs
12616 js_pushstring(J, argv[1]);
12617 js_setglobal(J, "scriptPath");
12618 js_newarray(J);
12619 for (i = 2; i < argc; ++i) {
12620 js_pushstring(J, argv[i]);
12621 js_setindex(J, -2, i - 2);
12622 }
12623 js_setglobal(J, "scriptArgs");
12624
12625 // node compatible process.argv
12626 js_getglobal(J, "process");
12627 js_getproperty(J, -1, "argv");
12628 for (i = 0; i < argc; ++i) {
12629 js_pushstring(J, argv[i]);
12630 js_setindex(J, -2, i);
12631 }
12632 js_pop(J, 2);
12633
12634 js_endtry(J);
12635 if (murun_dofile(J, argv[1]))
12636 {
12637 js_freestate(J);
12638 fz_drop_context(ctx);
12639 return 1;
12640 }
12641 } else {
12642 char line[256];
12643 fputs(PS1, stdout);
12644 while (fgets(line, sizeof line, stdin)) {
12645 eval_print(J, line);
12646 fputs(PS1, stdout);
12647 }
12648 putchar('\n');
12649 }
12650
12651 js_freestate(J);
12652 fz_drop_context(ctx);
12653 return 0;
12654 }
12655
12656 #endif