comparison mupdf-source/platform/wasm/lib/mupdf.ts @ 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 WASM Library.
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 "use strict"
24
25 import { Pointer } from "./mupdf-wasm.js"
26 import libmupdf_wasm from "./mupdf-wasm.js"
27
28 declare global {
29 var $libmupdf_wasm_Module: any
30 }
31
32 var node_fs: any = null
33 if (typeof process !== "undefined" && process.versions && process.versions.node)
34 node_fs = await import("node:fs")
35
36 const libmupdf = await libmupdf_wasm(globalThis["$libmupdf_wasm_Module"])
37
38 libmupdf._wasm_init_context()
39
40 function Malloc<T>(size: number) {
41 return libmupdf._wasm_malloc(size) as unknown as Pointer<T>
42 }
43
44 function Free(ptr: any) {
45 libmupdf._wasm_free(ptr as Pointer<"void">)
46 }
47
48 export const memento = {
49 listBlocks() {
50 libmupdf._wasm_Memento_listBlocks()
51 },
52 checkAllMemory() {
53 libmupdf._wasm_Memento_checkAllMemory()
54 },
55 }
56
57 /*
58 --------------------------------------------------------------------------------
59
60 How to call into WASM and convert values between JS and WASM (libmupdf) worlds:
61
62 Passing values into WASM needs to either copy primitive values into WASM memory
63 or passing around pointer values.
64
65 Wrap and/or copy non-Userdata values into WASM:
66
67 STRING(stringValue)
68 STRING2(stringValue) -- if you need to pass more than one string
69 MATRIX(matrixArray)
70 RECT(rectArray)
71 BUFFER(bufferValue)
72 etc.
73
74 Look up an enum value by string:
75
76 ENUM<EnumType>(string, listOfValidValues)
77
78 Pass the pointer when the value is a Userdata object:
79
80 userdataObject.pointer
81
82 Convert WASM pointer into a JS value (for simple types like strings and matrices).
83
84 fromType(pointer)
85
86 Wrap a WASM pointer in a new Userdata object (for complex types):
87
88 new Wrapper(pointer)
89
90 PDFObjects are always bound to a PDFDocument, so must be accessed via a document:
91
92 doc._fromPDFObjectNew(new_ptr)
93 doc._fromPDFObjectKeep(borrowed_ptr)
94 doc._PDFOBJ(value)
95
96 Type checking of input arguments at runtime.
97
98 checkType(value, "string")
99 checkType(value, Class)
100 checkRect(value)
101 checkMatrix(value)
102
103 This code needs to work type safely from plain Javascript too,
104 so do NOT rely on Typescript to do all the type checking.
105
106 --------------------------------------------------------------------------------
107 */
108
109 export type Matrix = [number, number, number, number, number, number]
110 export type Rect = [number, number, number, number]
111 export type Quad = [number, number, number, number, number, number, number, number]
112 export type Point = [number, number]
113 export type Color = [number] | [number, number, number] | [number, number, number, number]
114 export type AnnotColor = [] | Color
115
116 export type Rotate = 0 | 90 | 180 | 270
117
118 export const Matrix = {
119 identity: [ 1, 0, 0, 1, 0, 0 ] as Matrix,
120 scale(sx: number, sy: number): Matrix {
121 return [ sx, 0, 0, sy, 0, 0 ]
122 },
123 translate(tx: number, ty: number): Matrix {
124 return [ 1, 0, 0, 1, tx, ty ]
125 },
126 rotate(d: number): Matrix {
127 while (d < 0)
128 d += 360
129 while (d >= 360)
130 d -= 360
131 let s = Math.sin((d * Math.PI) / 180)
132 let c = Math.cos((d * Math.PI) / 180)
133 return [ c, s, -s, c, 0, 0 ]
134 },
135 invert(m: Matrix): Matrix {
136 checkMatrix(m)
137 let det = m[0] * m[3] - m[1] * m[2]
138 if (det > -1e-23 && det < 1e-23)
139 return m
140 let rdet = 1 / det
141 let inva = m[3] * rdet
142 let invb = -m[1] * rdet
143 let invc = -m[2] * rdet
144 let invd = m[0] * rdet
145 let inve = -m[4] * inva - m[5] * invc
146 let invf = -m[4] * invb - m[5] * invd
147 return [ inva, invb, invc, invd, inve, invf ]
148 },
149 concat(one: Matrix, two: Matrix): Matrix {
150 checkMatrix(one)
151 checkMatrix(two)
152 return [
153 one[0] * two[0] + one[1] * two[2],
154 one[0] * two[1] + one[1] * two[3],
155 one[2] * two[0] + one[3] * two[2],
156 one[2] * two[1] + one[3] * two[3],
157 one[4] * two[0] + one[5] * two[2] + two[4],
158 one[4] * two[1] + one[5] * two[3] + two[5],
159 ]
160 },
161 }
162
163 export const Rect = {
164 MIN_INF_RECT: 0x80000000,
165 MAX_INF_RECT: 0x7fffff80,
166 empty: [ 0x80000000, 0x80000000, 0x7fffff80, 0x7fffff80 ],
167 invalid: [ 0, 0, -1, -1 ],
168 infinite: [ 0x7fffff80, 0x7fffff80, 0x80000000, 0x80000000 ],
169 isEmpty: function (rect: Rect) {
170 checkRect(rect)
171 return rect[0] >= rect[2] || rect[1] >= rect[3]
172 },
173 isValid: function (rect: Rect) {
174 checkRect(rect)
175 return rect[0] <= rect[2] && rect[1] <= rect[3]
176 },
177 isInfinite: function (rect: Rect) {
178 checkRect(rect)
179 return (
180 rect[0] === Rect.MAX_INF_RECT &&
181 rect[1] === Rect.MAX_INF_RECT &&
182 rect[2] === Rect.MIN_INF_RECT &&
183 rect[3] === Rect.MIN_INF_RECT
184 )
185 },
186 transform: function (rect: Rect, matrix: Matrix): Rect {
187 checkRect(rect)
188 checkMatrix(matrix)
189 var t
190
191 if (Rect.isInfinite(rect))
192 return rect
193 if (!Rect.isValid(rect))
194 return rect
195
196 var ax0 = rect[0] * matrix[0]
197 var ax1 = rect[2] * matrix[0]
198 if (ax0 > ax1)
199 t = ax0, ax0 = ax1, ax1 = t
200
201 var cy0 = rect[1] * matrix[2]
202 var cy1 = rect[3] * matrix[2]
203 if (cy0 > cy1)
204 t = cy0, cy0 = cy1, cy1 = t
205
206 ax0 += cy0 + matrix[4]
207 ax1 += cy1 + matrix[4]
208
209 var bx0 = rect[0] * matrix[1]
210 var bx1 = rect[2] * matrix[1]
211 if (bx0 > bx1)
212 t = bx0, bx0 = bx1, bx1 = t
213
214 var dy0 = rect[1] * matrix[3]
215 var dy1 = rect[3] * matrix[3]
216 if (dy0 > dy1)
217 t = dy0, dy0 = dy1, dy1 = t
218
219 bx0 += dy0 + matrix[5]
220 bx1 += dy1 + matrix[5]
221
222 return [ ax0, bx0, ax1, bx1 ]
223 },
224 }
225
226 export function enableICC() {
227 libmupdf._wasm_enable_icc()
228 }
229
230 export function disableICC() {
231 libmupdf._wasm_disable_icc()
232 }
233
234 export function setUserCSS(text: string) {
235 libmupdf._wasm_set_user_css(STRING(text))
236 }
237
238 export function installLoadFontFunction(f: (name: string, script: string, bold: boolean, italic: boolean) => Font | null) {
239 $libmupdf_load_font_file_js = f
240 }
241
242 /* -------------------------------------------------------------------------- */
243
244 // To pass Rect and Matrix as pointer arguments
245 const _wasm_int = Malloc<"int">(4)
246 const _wasm_point = Malloc<"fz_point">(4 * 6) >> 2
247 const _wasm_rect = Malloc<"fz_rect">(4 * 8) >> 2
248 const _wasm_matrix = Malloc<"fz_matrix">(4 * 6) >> 2
249 const _wasm_color = Malloc<"number">(4 * 4) >> 2
250 const _wasm_quad = Malloc<"fz_quad">(4 * 8) >> 2
251 const _wasm_string: [ Pointer<"char">, Pointer<"char"> ] = [ 0 as Pointer<"char">, 0 as Pointer<"char"> ]
252
253 function checkType(value: any, type: any) {
254 if (typeof type === "string" && typeof value !== type)
255 throw new TypeError("expected " + type)
256 if (typeof type === "function" && !(value instanceof type))
257 throw new TypeError("expected " + type.name)
258 }
259
260 function checkPoint(value: any): asserts value is Point {
261 if (!Array.isArray(value) || value.length !== 2)
262 throw new TypeError("expected point")
263 }
264
265 function checkRect(value: any): asserts value is Rect {
266 if (!Array.isArray(value) || value.length !== 4)
267 throw new TypeError("expected rectangle")
268 }
269
270 function checkMatrix(value: any): asserts value is Matrix {
271 if (!Array.isArray(value) || value.length !== 6)
272 throw new TypeError("expected matrix")
273 }
274
275 function checkQuad(value: any): asserts value is Quad {
276 if (!Array.isArray(value) || value.length !== 8)
277 throw new TypeError("expected quad")
278 }
279
280 function checkColor(value: any): asserts value is Color {
281 if (!Array.isArray(value) || (value.length !== 1 && value.length !== 3 && value.length !== 4))
282 throw new TypeError("expected color array")
283 }
284
285 function checkAnnotColor(value: any): asserts value is AnnotColor {
286 if (!Array.isArray(value) || (value.length !== 0 && value.length !== 1 && value.length !== 3 && value.length !== 4))
287 throw new TypeError("expected color array")
288 }
289
290 /** The types that can be automatically converted into a Buffer object */
291 type AnyBuffer = Buffer | ArrayBuffer | Uint8Array | string
292
293 function BUFFER(input: AnyBuffer) {
294 if (input instanceof Buffer)
295 return input.pointer
296 if (input instanceof ArrayBuffer || input instanceof Uint8Array)
297 return new Buffer(input).pointer
298 if (typeof input === "string")
299 return new Buffer(input).pointer
300 throw new TypeError("expected buffer")
301 }
302
303 function ENUM<T>(value: T, list: readonly T[]): number {
304 if (typeof value === "number") {
305 if (value >= 0 && value < list.length)
306 return value
307 }
308 if (typeof value === "string") {
309 let idx = list.indexOf(value)
310 if (idx >= 0)
311 return idx
312 }
313 throw new TypeError(`invalid enum value ("${value}"; expected ${list.join(", ")})`)
314 }
315
316 function allocateUTF8(str: string) {
317 var size = libmupdf.lengthBytesUTF8(str) + 1
318 var pointer = Malloc<"XXX">(size) as unknown as Pointer<"char">
319 libmupdf.stringToUTF8(str, pointer, size)
320 return pointer
321 }
322
323 function STRING_N(s: string, i: number) {
324 if (_wasm_string[i]) {
325 Free(_wasm_string[i])
326 _wasm_string[i] = 0 as Pointer<"char">
327 }
328 return _wasm_string[i] = allocateUTF8(s)
329 }
330
331 function STRING(s: string) {
332 return STRING_N(s, 0)
333 }
334
335 function STRING2(s: string) {
336 return STRING_N(s, 1)
337 }
338
339 function STRING_OPT(s: string | null | undefined) {
340 return typeof s === "string" ? STRING_N(s, 0) : 0 as Pointer<"char">
341 }
342
343 function STRING2_OPT(s: string | null | undefined) {
344 return typeof s === "string" ? STRING_N(s, 1) : 0 as Pointer<"char">
345 }
346
347 function POINT(p: Point) {
348 libmupdf.HEAPF32[_wasm_point + 0] = p[0]
349 libmupdf.HEAPF32[_wasm_point + 1] = p[1]
350 return _wasm_point << 2 as Pointer<"fz_point">
351 }
352
353 function POINT2(p: Point) {
354 libmupdf.HEAPF32[_wasm_point + 2] = p[0]
355 libmupdf.HEAPF32[_wasm_point + 3] = p[1]
356 return (_wasm_point + 2) << 2 as Pointer<"fz_point">
357 }
358
359 function POINT3(p: Point) {
360 libmupdf.HEAPF32[_wasm_point + 4] = p[0]
361 libmupdf.HEAPF32[_wasm_point + 5] = p[1]
362 return (_wasm_point + 4) << 2 as Pointer<"fz_point">
363 }
364
365 function RECT(r: Rect) {
366 libmupdf.HEAPF32[_wasm_rect + 0] = r[0]
367 libmupdf.HEAPF32[_wasm_rect + 1] = r[1]
368 libmupdf.HEAPF32[_wasm_rect + 2] = r[2]
369 libmupdf.HEAPF32[_wasm_rect + 3] = r[3]
370 return _wasm_rect << 2 as Pointer<"fz_rect">
371 }
372
373 function RECT2(r: Rect) {
374 libmupdf.HEAPF32[_wasm_rect + 4] = r[0]
375 libmupdf.HEAPF32[_wasm_rect + 5] = r[1]
376 libmupdf.HEAPF32[_wasm_rect + 6] = r[2]
377 libmupdf.HEAPF32[_wasm_rect + 7] = r[3]
378 return (_wasm_rect + 4) << 2 as Pointer<"fz_rect">
379 }
380
381 function MATRIX(m: Matrix) {
382 libmupdf.HEAPF32[_wasm_matrix + 0] = m[0]
383 libmupdf.HEAPF32[_wasm_matrix + 1] = m[1]
384 libmupdf.HEAPF32[_wasm_matrix + 2] = m[2]
385 libmupdf.HEAPF32[_wasm_matrix + 3] = m[3]
386 libmupdf.HEAPF32[_wasm_matrix + 4] = m[4]
387 libmupdf.HEAPF32[_wasm_matrix + 5] = m[5]
388 return _wasm_matrix << 2 as Pointer<"fz_matrix">
389 }
390
391 function QUAD(q: Quad) {
392 libmupdf.HEAPF32[_wasm_quad + 0] = q[0]
393 libmupdf.HEAPF32[_wasm_quad + 1] = q[1]
394 libmupdf.HEAPF32[_wasm_quad + 2] = q[2]
395 libmupdf.HEAPF32[_wasm_quad + 3] = q[3]
396 libmupdf.HEAPF32[_wasm_quad + 4] = q[4]
397 libmupdf.HEAPF32[_wasm_quad + 5] = q[5]
398 libmupdf.HEAPF32[_wasm_quad + 6] = q[6]
399 libmupdf.HEAPF32[_wasm_quad + 7] = q[7]
400 return _wasm_quad << 2 as Pointer<"fz_quad">
401 }
402
403 function COLOR(c?: AnnotColor) {
404 if (typeof c !== "undefined") {
405 switch (c.length) {
406 case 0:
407 break
408 case 1:
409 libmupdf.HEAPF32[_wasm_color + 0] = c[0]
410 break
411 case 3:
412 libmupdf.HEAPF32[_wasm_color + 0] = c[0]
413 libmupdf.HEAPF32[_wasm_color + 1] = c[1]
414 libmupdf.HEAPF32[_wasm_color + 2] = c[2]
415 break
416 case 4:
417 libmupdf.HEAPF32[_wasm_color + 0] = c[0]
418 libmupdf.HEAPF32[_wasm_color + 1] = c[1]
419 libmupdf.HEAPF32[_wasm_color + 2] = c[2]
420 libmupdf.HEAPF32[_wasm_color + 3] = c[3]
421 break
422 }
423 }
424 return _wasm_color << 2 as Pointer<"float">
425 }
426
427 /* -------------------------------------------------------------------------- */
428
429 function fromColor(n: number): Color {
430 if (n === 1)
431 return [
432 libmupdf.HEAPF32[_wasm_color] as number
433 ]
434 if (n === 3)
435 return [
436 libmupdf.HEAPF32[_wasm_color + 0] as number,
437 libmupdf.HEAPF32[_wasm_color + 1] as number,
438 libmupdf.HEAPF32[_wasm_color + 2] as number,
439 ]
440 if (n === 4)
441 return [
442 libmupdf.HEAPF32[_wasm_color + 0] as number,
443 libmupdf.HEAPF32[_wasm_color + 1] as number,
444 libmupdf.HEAPF32[_wasm_color + 2] as number,
445 libmupdf.HEAPF32[_wasm_color + 3] as number,
446 ]
447 throw new TypeError("invalid number of components for Color: " + n)
448 }
449
450 function fromAnnotColor(n: number): AnnotColor {
451 if (n === 0)
452 return []
453 return fromColor(n)
454 }
455
456 function fromColorArray(n: number, ptr: Pointer<"float">): number[] {
457 let addr = ptr >> 2
458 let color: number[] = []
459 for (let i = 0; i < n; ++i)
460 color.push(libmupdf.HEAPF32[addr + i] as number)
461 return color
462 }
463
464 function fromStringOrNull(ptr: Pointer<"char">): string | null {
465 if (ptr === 0)
466 return null
467 return libmupdf.UTF8ToString(ptr)
468 }
469
470 function fromString(ptr: Pointer<"char">): string {
471 return libmupdf.UTF8ToString(ptr)
472 }
473
474 function fromStringFree(ptr: Pointer<"char">): string {
475 let str = libmupdf.UTF8ToString(ptr)
476 Free(ptr)
477 return str
478 }
479
480 function fromPoint(ptr: Pointer<"fz_point">): Point {
481 let addr = ptr >> 2
482 return [
483 libmupdf.HEAPF32[addr + 0] as number,
484 libmupdf.HEAPF32[addr + 1] as number,
485 ]
486 }
487
488 function fromRect(ptr: Pointer<"fz_rect">): Rect {
489 let addr = ptr >> 2
490 return [
491 libmupdf.HEAPF32[addr + 0] as number,
492 libmupdf.HEAPF32[addr + 1] as number,
493 libmupdf.HEAPF32[addr + 2] as number,
494 libmupdf.HEAPF32[addr + 3] as number,
495 ]
496 }
497
498 function fromMatrix(ptr: Pointer<"fz_matrix">): Matrix {
499 let addr = ptr >> 2
500 return [
501 libmupdf.HEAPF32[addr + 0] as number,
502 libmupdf.HEAPF32[addr + 1] as number,
503 libmupdf.HEAPF32[addr + 2] as number,
504 libmupdf.HEAPF32[addr + 3] as number,
505 libmupdf.HEAPF32[addr + 4] as number,
506 libmupdf.HEAPF32[addr + 5] as number,
507 ]
508 }
509
510 function fromQuad(ptr: Pointer<"fz_quad">): Quad {
511 let addr = ptr >> 2
512 return [
513 libmupdf.HEAPF32[addr + 0] as number,
514 libmupdf.HEAPF32[addr + 1] as number,
515 libmupdf.HEAPF32[addr + 2] as number,
516 libmupdf.HEAPF32[addr + 3] as number,
517 libmupdf.HEAPF32[addr + 4] as number,
518 libmupdf.HEAPF32[addr + 5] as number,
519 libmupdf.HEAPF32[addr + 6] as number,
520 libmupdf.HEAPF32[addr + 7] as number,
521 ]
522 }
523
524 function fromBuffer(ptr: Pointer<"fz_buffer">): Uint8Array {
525 let data = libmupdf._wasm_buffer_get_data(ptr)
526 let size = libmupdf._wasm_buffer_get_len(ptr)
527 return libmupdf.HEAPU8.slice(data, data + size)
528 }
529
530 /* unused for now
531 function rgbFromColor(c?: Color): [number, number, number] {
532 var r = 0, g = 0, b = 0
533 if (typeof c !== "undefined") {
534 switch (c.length) {
535 case 1:
536 r = g = b = c[0]
537 break
538 case 3:
539 r = c[0]
540 g = c[1]
541 b = c[2]
542 break
543 case 4:
544 r = 1 - Math.min(1, c[0] + c[3])
545 g = 1 - Math.min(1, c[1] + c[3])
546 b = 1 - Math.min(1, c[2] + c[3])
547 break
548 }
549 }
550 return [ r, g, b ]
551 }
552
553 function numberFromColor(c?: Color): number {
554 var [ r, g, b ] = rgbFromColor(c)
555 return (255 << 24) | (r << 16) | (g << 8) | b
556 }
557 */
558
559 function colorFromNumber(argb: number): Color {
560 var r = (argb >> 16) & 255
561 var g = (argb >> 8) & 255
562 var b = (argb) & 255
563 return [ r / 255, g / 255, b / 255 ]
564 }
565
566 /* -------------------------------------------------------------------------- */
567
568 type SearchFunction = (
569 display_list: any,
570 needle: Pointer<"char">,
571 marks: Pointer<"int">,
572 hits: Pointer<"fz_quad">,
573 hit_max: number
574 ) => number
575
576 function runSearch(searchFun: SearchFunction, searchThis: number, needle: string, max_hits = 500) {
577 checkType(needle, "string")
578 let hits = 0 as Pointer<"fz_quad">
579 let marks = 0 as Pointer<"int">
580 try {
581 hits = Malloc<"fz_quad">(32 * max_hits)
582 marks = Malloc<"int">(4 * max_hits)
583 let n = searchFun(searchThis as any, STRING(needle), marks, hits, max_hits)
584 let outer: Quad[][] = []
585 if (n > 0) {
586 let inner: Quad[] = []
587 for (let i = 0; i < n; ++i) {
588 let mark = libmupdf.HEAP32[(marks>>2) + i]
589 let quad = fromQuad(hits + i * 32 as Pointer<"fz_quad">)
590 if (i > 0 && mark) {
591 outer.push(inner)
592 inner = []
593 }
594 inner.push(quad)
595 }
596 outer.push(inner)
597 }
598 return outer
599 } finally {
600 Free(marks)
601 Free(hits)
602 }
603 }
604
605 /* -------------------------------------------------------------------------- */
606
607 abstract class Userdata<B> {
608 private static _finalizer: FinalizationRegistry<number>
609
610 static readonly _drop: (pointer: any) => void
611
612 pointer: Pointer<B>
613
614 constructor(pointer: Pointer<B>) {
615 if (typeof pointer !== "number")
616 throw new Error("invalid pointer: " + typeof pointer)
617 if (pointer !== 0) {
618 let ctor = this.constructor as typeof Userdata
619 if (!ctor._finalizer)
620 ctor._finalizer = new FinalizationRegistry(ctor._drop)
621 ctor._finalizer.register(this, pointer, this)
622 }
623 this.pointer = pointer
624 }
625
626 destroy() {
627 if (this.pointer !== 0) {
628 let ctor = this.constructor as typeof Userdata
629 ctor._finalizer.unregister(this)
630 ctor._drop(this.pointer)
631 }
632 this.pointer = 0 as Pointer<B>
633 }
634
635 // Custom "console.log" formatting for Node
636 [Symbol.for("nodejs.util.inspect.custom")]() {
637 return this.toString()
638 }
639
640 toString() {
641 return `[${this.constructor.name} ${this.pointer}]`
642 }
643
644 valueOf() {
645 throw new Error("cannot convert Userdata to Javascript value")
646 }
647 }
648
649 export class Buffer extends Userdata<"fz_buffer"> {
650 static override readonly _drop = libmupdf._wasm_drop_buffer
651
652 /** New empty Buffer. */
653 constructor()
654
655 /** New Buffer initialized with string contents as UTF-8. */
656 constructor(data: string)
657
658 /** New Buffer initialized with typed array contents. */
659 constructor(data: ArrayBuffer | Uint8Array)
660
661 /** PRIVATE */
662 constructor(pointer: Pointer<"fz_buffer">)
663
664 constructor(arg?: Pointer<"fz_buffer"> | string | ArrayBuffer | Uint8Array) {
665 if (typeof arg === "undefined")
666 super(libmupdf._wasm_new_buffer(1024))
667
668 else if (typeof arg === "number")
669 super(arg)
670
671 else if (typeof arg === "string") {
672 let data_len = libmupdf.lengthBytesUTF8(arg)
673 let data_ptr = Malloc<"char">(data_len + 1)
674 libmupdf.stringToUTF8(arg, data_ptr, data_len + 1)
675 super(libmupdf._wasm_new_buffer_from_data(data_ptr, data_len))
676 }
677
678 else if (arg instanceof ArrayBuffer || arg instanceof Uint8Array) {
679 let data_len = arg.byteLength
680 let data_ptr = Malloc<"char">(data_len)
681 libmupdf.HEAPU8.set(new Uint8Array(arg), data_ptr)
682 super(libmupdf._wasm_new_buffer_from_data(data_ptr, data_len))
683 }
684 }
685
686 get length() {
687 return this.getLength()
688 }
689
690 set length(_: number) {
691 throw new TypeError("buffer length is read-only")
692 }
693
694 getLength() {
695 return libmupdf._wasm_buffer_get_len(this.pointer)
696 }
697
698 readByte(at: number) {
699 let data = libmupdf._wasm_buffer_get_data(this.pointer)
700 return libmupdf.HEAPU8[data + at] as number
701 }
702
703 write(s: string) {
704 libmupdf._wasm_append_string(this.pointer, STRING(s))
705 }
706
707 writeByte(b: number) {
708 libmupdf._wasm_append_byte(this.pointer, b)
709 }
710
711 writeLine(s: string) {
712 this.write(s)
713 this.writeByte(10)
714 }
715
716 writeBuffer(other: AnyBuffer) {
717 libmupdf._wasm_append_buffer(this.pointer, BUFFER(other))
718 }
719
720 asUint8Array() {
721 let data = libmupdf._wasm_buffer_get_data(this.pointer)
722 let size = libmupdf._wasm_buffer_get_len(this.pointer)
723 return libmupdf.HEAPU8.subarray(data, data + size)
724 }
725
726 slice(start: number, end?: number) {
727 if (typeof end === "undefined")
728 end = this.getLength()
729 return new Buffer(libmupdf._wasm_slice_buffer(this.pointer, start, end))
730 }
731
732 asString() {
733 return fromString(libmupdf._wasm_string_from_buffer(this.pointer))
734 }
735
736 save(filename: string) {
737 if (node_fs)
738 node_fs.writeFileSync(filename, this.asUint8Array())
739 else
740 throw new Error("missing 'fs' module")
741 }
742 }
743
744 export type ColorSpaceType =
745 "None" |
746 "Gray" |
747 "RGB" |
748 "BGR" |
749 "CMYK" |
750 "Lab" |
751 "Indexed" |
752 "Separation"
753
754 export class ColorSpace extends Userdata<"fz_colorspace"> {
755 static override readonly _drop = libmupdf._wasm_drop_colorspace
756
757 static readonly COLORSPACE_TYPES: ColorSpaceType[] = [
758 "None",
759 "Gray",
760 "RGB",
761 "BGR",
762 "CMYK",
763 "Lab",
764 "Indexed",
765 "Separation"
766 ]
767
768 // Create ColorSpace from ICC profile.
769 constructor(profile: AnyBuffer, name: string)
770
771 // PRIVATE
772 constructor(pointer: Pointer<"fz_colorspace">)
773
774 constructor(from: Pointer<"fz_colorspace"> | AnyBuffer, name?: string) {
775 if (typeof from === "number") {
776 super(from)
777 } else {
778 if (typeof from === "string") {
779 if (node_fs)
780 from = node_fs.readFileSync(from)
781 else
782 throw new Error("missing 'fs' module")
783 }
784 super(libmupdf._wasm_new_icc_colorspace(STRING_OPT(name), BUFFER(from as AnyBuffer)))
785 }
786 }
787
788 getName() {
789 return fromString(libmupdf._wasm_colorspace_get_name(this.pointer))
790 }
791
792 getType() {
793 return ColorSpace.COLORSPACE_TYPES[libmupdf._wasm_colorspace_get_type(this.pointer)] || "None"
794 }
795
796 getNumberOfComponents() {
797 return libmupdf._wasm_colorspace_get_n(this.pointer)
798 }
799
800 isGray(): boolean { return this.getType() === "Gray" }
801 isRGB(): boolean { return this.getType() === "RGB" }
802 isCMYK(): boolean { return this.getType() === "CMYK" }
803 isIndexed(): boolean { return this.getType() === "Indexed" }
804 isLab(): boolean { return this.getType() === "Lab" }
805 isDeviceN(): boolean { return this.getType() === "Separation" }
806 isSubtractive(): boolean { return this.getType() === "CMYK" || this.getType() === "Separation" }
807
808 override toString() {
809 return "[ColorSpace " + this.getName() + "]"
810 }
811
812 static readonly DeviceGray = new ColorSpace(libmupdf._wasm_device_gray())
813 static readonly DeviceRGB = new ColorSpace(libmupdf._wasm_device_rgb())
814 static readonly DeviceBGR = new ColorSpace(libmupdf._wasm_device_bgr())
815 static readonly DeviceCMYK = new ColorSpace(libmupdf._wasm_device_cmyk())
816 static readonly Lab = new ColorSpace(libmupdf._wasm_device_lab())
817 }
818
819 export type FontSimpleEncoding = "Latin" | "Greek" | "Cyrillic"
820
821 export type FontCJKOrdering = 0 | 1 | 2 | 3
822
823 export type FontCJKLanguage =
824 "Adobe-CNS1" |
825 "Adobe-GB1" |
826 "Adobe-Japan1" |
827 "Adobe-Korea1" |
828 "zh-Hant" |
829 "zh-TW" |
830 "zh-HK" |
831 "zh-Hans" |
832 "zh-CN" |
833 "ja" |
834 "ko"
835
836 export class Font extends Userdata<"fz_font"> {
837 static override readonly _drop = libmupdf._wasm_drop_font
838
839 static readonly SIMPLE_ENCODING: FontSimpleEncoding[] = [
840 "Latin",
841 "Greek",
842 "Cyrillic"
843 ]
844
845 static readonly ADOBE_CNS = 0
846 static readonly ADOBE_GB = 1
847 static readonly ADOBE_JAPAN = 2
848 static readonly ADOBE_KOREA = 3
849
850 static readonly CJK_ORDERING_BY_LANG: Record<FontCJKLanguage,FontCJKOrdering> = {
851 "Adobe-CNS1": 0,
852 "Adobe-GB1": 1,
853 "Adobe-Japan1": 2,
854 "Adobe-Korea1": 3,
855 "zh-Hant": 0,
856 "zh-TW": 0,
857 "zh-HK": 0,
858 "zh-Hans": 1,
859 "zh-CN": 1,
860 "ja": 2,
861 "ko": 3,
862 }
863
864 constructor(name: string)
865 constructor(name: string, filename: string, subfont?: number)
866 constructor(name: string, data: AnyBuffer, subfont?: number)
867 constructor(pointer: Pointer<"fz_font">)
868
869 constructor(name_or_pointer: Pointer<"fz_font"> | string, data?: AnyBuffer, subfont=0) {
870 let pointer = 0 as Pointer<"fz_font">
871 if (typeof name_or_pointer === "number") {
872 pointer = libmupdf._wasm_keep_font(name_or_pointer)
873 } else {
874 if (typeof data === "string") {
875 if (node_fs)
876 data = node_fs.readFileSync(data)
877 else
878 throw new Error("missing 'fs' module")
879 }
880 if (data)
881 pointer = libmupdf._wasm_new_font_from_buffer(STRING(name_or_pointer), BUFFER(data), subfont)
882 else if (name_or_pointer === "zh-Hant")
883 pointer = libmupdf._wasm_new_cjk_font(Font.ADOBE_CNS)
884 else if (name_or_pointer === "zh-Hans")
885 pointer = libmupdf._wasm_new_cjk_font(Font.ADOBE_GB)
886 else if (name_or_pointer === "ja")
887 pointer = libmupdf._wasm_new_cjk_font(Font.ADOBE_JAPAN)
888 else if (name_or_pointer === "ko")
889 pointer = libmupdf._wasm_new_cjk_font(Font.ADOBE_KOREA)
890 else
891 pointer = libmupdf._wasm_new_base14_font(STRING(name_or_pointer))
892 }
893 super(pointer)
894 }
895
896 getName() {
897 return fromString(libmupdf._wasm_font_get_name(this.pointer))
898 }
899
900 encodeCharacter(uni: number | string) {
901 if (typeof uni === "string")
902 uni = uni.charCodeAt(0)
903 return libmupdf._wasm_encode_character(this.pointer, uni)
904 }
905
906 advanceGlyph(gid: number, wmode = 0) {
907 return libmupdf._wasm_advance_glyph(this.pointer, gid, wmode)
908 }
909
910 isMono() {
911 return !!libmupdf._wasm_font_is_monospaced(this.pointer)
912 }
913
914 isSerif() {
915 return !!libmupdf._wasm_font_is_serif(this.pointer)
916 }
917
918 isBold() {
919 return !!libmupdf._wasm_font_is_bold(this.pointer)
920 }
921
922 isItalic() {
923 return !!libmupdf._wasm_font_is_italic(this.pointer)
924 }
925 }
926
927 export class Image extends Userdata<"fz_image"> {
928 static override readonly _drop = libmupdf._wasm_drop_image
929
930 constructor(pointer: Pointer<"fz_image">)
931 constructor(filename: string)
932 constructor(data: AnyBuffer)
933 constructor(pixmap: Pixmap, mask?: Image)
934
935 constructor(data: Pointer<"fz_image"> | Pixmap | AnyBuffer, mask?: Image) {
936 let pointer = 0 as Pointer<"fz_image">
937 if (typeof data === "number") {
938 pointer = libmupdf._wasm_keep_image(data)
939 } else if (data instanceof Pixmap) {
940 pointer = libmupdf._wasm_new_image_from_pixmap(
941 data.pointer,
942 mask ? mask.pointer : 0 as Pointer<"fz_image">
943 )
944 } else {
945 if (typeof data === "string") {
946 if (node_fs)
947 data = node_fs.readFileSync(data)
948 else
949 throw new Error("missing 'fs' module")
950 }
951 pointer = libmupdf._wasm_new_image_from_buffer(BUFFER(data as Uint8Array))
952 }
953 super(pointer)
954 }
955
956 getWidth() {
957 return libmupdf._wasm_image_get_w(this.pointer)
958 }
959
960 getHeight() {
961 return libmupdf._wasm_image_get_h(this.pointer)
962 }
963
964 getNumberOfComponents() {
965 return libmupdf._wasm_image_get_n(this.pointer)
966 }
967
968 getBitsPerComponent() {
969 return libmupdf._wasm_image_get_bpc(this.pointer)
970 }
971
972 getXResolution() {
973 return libmupdf._wasm_image_get_xres(this.pointer)
974 }
975
976 getYResolution() {
977 return libmupdf._wasm_image_get_yres(this.pointer)
978 }
979
980 getImageMask() {
981 return !!libmupdf._wasm_image_get_imagemask(this.pointer)
982 }
983
984 getColorSpace() {
985 let cs = libmupdf._wasm_image_get_colorspace(this.pointer)
986 if (cs)
987 return new ColorSpace(libmupdf._wasm_keep_colorspace(cs))
988 return null
989 }
990
991 getMask() {
992 let mask = libmupdf._wasm_image_get_mask(this.pointer)
993 if (mask)
994 return new Image(libmupdf._wasm_keep_image(mask))
995 return null
996 }
997
998 toPixmap() {
999 return new Pixmap(libmupdf._wasm_get_pixmap_from_image(this.pointer))
1000 }
1001 }
1002
1003 export type LineCap = "Butt" | "Round" | "Square" | "Triangle"
1004 export type LineJoin = "Miter" | "Round" | "Bevel" | "MiterXPS"
1005
1006 // TODO: convert StrokeState from plain JS object to match mutool run ffi_pushstroke/ffi_tostroke
1007
1008 export type StrokeStateData = {
1009 lineCap: LineCap,
1010 lineJoin: LineJoin,
1011 lineWidth: number,
1012 miterLimit: number,
1013 dashPhase?: number,
1014 dashes?: number[],
1015 }
1016
1017 export class StrokeState extends Userdata<"fz_stroke_state"> {
1018 static override readonly _drop = libmupdf._wasm_drop_stroke_state
1019
1020 static readonly LINE_CAP: LineCap[] = [
1021 "Butt",
1022 "Round",
1023 "Square",
1024 "Triangle"
1025 ]
1026
1027 static readonly LINE_JOIN: LineJoin[] = [
1028 "Miter",
1029 "Round",
1030 "Bevel",
1031 "MiterXPS"
1032 ]
1033
1034 constructor(data: Pointer<"fz_stroke_state"> | StrokeStateData) {
1035 if (typeof data === "number") {
1036 super(data)
1037 return this
1038 }
1039 super(libmupdf._wasm_new_stroke_state(data?.dashes?.length ?? 0))
1040 let lineCap = ENUM<LineCap>(data.lineCap, StrokeState.LINE_CAP)
1041 let lineJoin = ENUM<LineJoin>(data.lineJoin, StrokeState.LINE_JOIN)
1042 libmupdf._wasm_stroke_state_set_start_cap(this.pointer, lineCap)
1043 libmupdf._wasm_stroke_state_set_dash_cap(this.pointer, lineCap)
1044 libmupdf._wasm_stroke_state_set_end_cap(this.pointer, lineCap)
1045 libmupdf._wasm_stroke_state_set_linejoin(this.pointer, lineJoin)
1046 libmupdf._wasm_stroke_state_set_linewidth(this.pointer, data.lineWidth)
1047 libmupdf._wasm_stroke_state_set_miterlimit(this.pointer, data.miterLimit)
1048 libmupdf._wasm_stroke_state_set_dash_phase(this.pointer, data.dashPhase ?? 0)
1049 if (data.dashes) {
1050 for (let i = 0; i < data.dashes.length; ++i)
1051 libmupdf._wasm_stroke_state_set_dash_item(this.pointer, i, data.dashes[i] ?? 0)
1052 }
1053 }
1054
1055 getLineCap() {
1056 return libmupdf._wasm_stroke_state_get_start_cap(this.pointer)
1057 }
1058
1059 getLineJoin() {
1060 return libmupdf._wasm_stroke_state_get_linejoin(this.pointer)
1061 }
1062
1063 getLineWidth() {
1064 return libmupdf._wasm_stroke_state_get_linewidth(this.pointer)
1065 }
1066
1067 getMiterLimit() {
1068 return libmupdf._wasm_stroke_state_get_miterlimit(this.pointer)
1069 }
1070
1071 getDashPhase() {
1072 return libmupdf._wasm_stroke_state_get_dash_phase(this.pointer)
1073 }
1074
1075 getDashes(): number[] | null {
1076 var n = libmupdf._wasm_stroke_state_get_dash_len(this.pointer)
1077 if (n > 0) {
1078 var out: number[] = []
1079 for (let i = 0; i < n; ++i)
1080 out[i] = libmupdf._wasm_stroke_state_get_dash_item(this.pointer, i)
1081 return out
1082 }
1083 return null
1084 }
1085 }
1086
1087 interface PathWalker {
1088 moveTo?(x: number, y: number): void
1089 lineTo?(x: number, y: number): void
1090 curveTo?(x1: number, y1: number, x2: number, y2: number, x3: number, y3: number): void
1091 closePath?(): void
1092 }
1093
1094 export class Path extends Userdata<"fz_path"> {
1095 static override readonly _drop = libmupdf._wasm_drop_path
1096
1097 constructor(pointer?: Pointer<"fz_path">) {
1098 if (typeof pointer === "number")
1099 super(pointer)
1100 else
1101 super(libmupdf._wasm_new_path())
1102 }
1103
1104 getBounds(strokeState: StrokeState, transform: Matrix) {
1105 if (strokeState !== null)
1106 checkType(strokeState, StrokeState)
1107 checkMatrix(transform)
1108 return fromRect(libmupdf._wasm_bound_path(this.pointer, strokeState?.pointer, MATRIX(transform)))
1109 }
1110
1111 moveTo(x: number, y: number) {
1112 checkType(x, "number")
1113 checkType(y, "number")
1114 libmupdf._wasm_moveto(this.pointer, x, y)
1115 }
1116
1117 lineTo(x: number, y: number) {
1118 checkType(x, "number")
1119 checkType(y, "number")
1120 libmupdf._wasm_lineto(this.pointer, x, y)
1121 }
1122
1123 curveTo(x1: number, y1: number, x2: number, y2: number, x3: number, y3: number) {
1124 checkType(x1, "number")
1125 checkType(y1, "number")
1126 checkType(x2, "number")
1127 checkType(y2, "number")
1128 checkType(x3, "number")
1129 checkType(y3, "number")
1130 libmupdf._wasm_curveto(this.pointer, x1, y1, x2, y2, x3, y3)
1131 }
1132
1133 curveToV(cx: number, cy: number, ex: number, ey: number) {
1134 checkType(cx, "number")
1135 checkType(cy, "number")
1136 checkType(ex, "number")
1137 checkType(ey, "number")
1138 libmupdf._wasm_curvetov(this.pointer, cx, cy, ex, ey)
1139 }
1140
1141 curveToY(cx: number, cy: number, ex: number, ey: number) {
1142 checkType(cx, "number")
1143 checkType(cy, "number")
1144 checkType(ex, "number")
1145 checkType(ey, "number")
1146 libmupdf._wasm_curvetoy(this.pointer, cx, cy, ex, ey)
1147 }
1148
1149 closePath() {
1150 libmupdf._wasm_closepath(this.pointer)
1151 }
1152
1153 rect(x1: number, y1: number, x2: number, y2: number) {
1154 checkType(x1, "number")
1155 checkType(y1, "number")
1156 checkType(x2, "number")
1157 checkType(y2, "number")
1158 libmupdf._wasm_rectto(this.pointer, x1, y1, x2, y2)
1159 }
1160
1161 transform(matrix: Matrix) {
1162 checkMatrix(matrix)
1163 libmupdf._wasm_transform_path(this.pointer, MATRIX(matrix))
1164 }
1165
1166 walk(walker: PathWalker) {
1167 let id = $libmupdf_path_id++
1168 $libmupdf_path_table.set(id, walker)
1169 libmupdf._wasm_walk_path(this.pointer, id)
1170 $libmupdf_path_table.delete(id)
1171 }
1172 }
1173
1174 interface TextWalker {
1175 beginSpan?(font: Font, trm: Matrix, wmode: number, bidi: number, markupDirection: number, language: string): void
1176 showGlyph?(font: Font, trm: Matrix, glyph: number, unicode: number, wmode: number, bidi: number): void
1177 endSpan?(): void
1178 }
1179
1180 export class Text extends Userdata<"fz_text"> {
1181 static override readonly _drop = libmupdf._wasm_drop_text
1182
1183 constructor(pointer?: Pointer<"fz_text">) {
1184 if (typeof pointer === "number")
1185 super(pointer)
1186 else
1187 super(libmupdf._wasm_new_text())
1188 }
1189
1190 getBounds(strokeState: StrokeState, transform: Matrix) {
1191 if (strokeState !== null)
1192 checkType(strokeState, StrokeState)
1193 checkMatrix(transform)
1194 return fromRect(libmupdf._wasm_bound_text(this.pointer, strokeState?.pointer, MATRIX(transform)))
1195 }
1196
1197 showGlyph(font: Font, trm: Matrix, gid: number, uni: number, wmode = 0) {
1198 checkType(font, Font)
1199 checkMatrix(trm)
1200 checkType(gid, "number")
1201 checkType(uni, "number")
1202 libmupdf._wasm_show_glyph(
1203 this.pointer,
1204 font.pointer,
1205 MATRIX(trm),
1206 gid,
1207 uni,
1208 wmode
1209 )
1210 }
1211
1212 showString(font: Font, trm: Matrix, str: string, wmode = 0) {
1213 checkType(font, Font)
1214 checkMatrix(trm)
1215 checkType(str, "string")
1216 return fromMatrix(
1217 libmupdf._wasm_show_string(
1218 this.pointer,
1219 font.pointer,
1220 MATRIX(trm),
1221 STRING(str),
1222 wmode
1223 )
1224 )
1225 }
1226
1227 walk(walker: TextWalker) {
1228 let id = $libmupdf_text_id++
1229 $libmupdf_text_table.set(id, walker)
1230 libmupdf._wasm_walk_text(this.pointer, id)
1231 $libmupdf_text_table.delete(id)
1232 }
1233 }
1234
1235 export class DisplayList extends Userdata<"fz_display_list"> {
1236 static override readonly _drop = libmupdf._wasm_drop_display_list
1237
1238 constructor(pointer: Pointer<"fz_display_list">)
1239 constructor(mediabox: Rect)
1240
1241 constructor(arg1: Pointer<"fz_display_list"> | Rect) {
1242 let pointer = 0 as Pointer<"fz_display_list">
1243 if (typeof arg1 === "number") {
1244 pointer = arg1
1245 } else {
1246 checkRect(arg1)
1247 pointer = libmupdf._wasm_new_display_list(RECT(arg1))
1248 }
1249 super(pointer)
1250 }
1251
1252 getBounds() {
1253 return fromRect(libmupdf._wasm_bound_display_list(this.pointer))
1254 }
1255
1256 toPixmap(matrix: Matrix, colorspace: ColorSpace, alpha = false) {
1257 checkMatrix(matrix)
1258 checkType(colorspace, ColorSpace)
1259 return new Pixmap(
1260 libmupdf._wasm_new_pixmap_from_display_list(
1261 this.pointer,
1262 MATRIX(matrix),
1263 colorspace.pointer,
1264 alpha
1265 )
1266 )
1267 }
1268
1269 toStructuredText(options = "") {
1270 checkType(options, "string")
1271 return new StructuredText(libmupdf._wasm_new_stext_page_from_display_list(this.pointer, STRING(options)))
1272 }
1273
1274 run(device: Device, matrix: Matrix) {
1275 checkType(device, Device)
1276 checkMatrix(matrix)
1277 libmupdf._wasm_run_display_list(this.pointer, device.pointer, MATRIX(matrix))
1278 }
1279
1280 search(needle: string, max_hits = 500) {
1281 return runSearch(libmupdf._wasm_search_display_list, this.pointer, needle, max_hits)
1282 }
1283 }
1284
1285 export class Pixmap extends Userdata<"fz_pixmap"> {
1286 static override readonly _drop = libmupdf._wasm_drop_pixmap
1287
1288 constructor(pointer: Pointer<"fz_pixmap">)
1289 constructor(colorspace: ColorSpace, bbox: Rect, alpha: boolean)
1290
1291 constructor(arg1: Pointer<"fz_pixmap"> | ColorSpace, bbox?: Rect, alpha = false) {
1292 if (typeof arg1 === "number") {
1293 super(arg1)
1294 }
1295 if (arg1 instanceof ColorSpace) {
1296 checkRect(bbox)
1297 super(libmupdf._wasm_new_pixmap_with_bbox(arg1.pointer, RECT(bbox), alpha))
1298 }
1299 if (arg1 === null) {
1300 checkRect(bbox)
1301 super(libmupdf._wasm_new_pixmap_with_bbox(0 as Pointer<"fz_colorspace">, RECT(bbox), alpha))
1302 }
1303 }
1304
1305 getBounds() {
1306 let x = libmupdf._wasm_pixmap_get_x(this.pointer)
1307 let y = libmupdf._wasm_pixmap_get_y(this.pointer)
1308 let w = libmupdf._wasm_pixmap_get_w(this.pointer)
1309 let h = libmupdf._wasm_pixmap_get_h(this.pointer)
1310 return [ x, y, x + w, y + h ]
1311 }
1312
1313 clear(value?: number) {
1314 if (typeof value === "undefined")
1315 libmupdf._wasm_clear_pixmap(this.pointer)
1316 else
1317 libmupdf._wasm_clear_pixmap_with_value(this.pointer, value)
1318 }
1319
1320 getWidth() {
1321 return libmupdf._wasm_pixmap_get_w(this.pointer)
1322 }
1323 getHeight() {
1324 return libmupdf._wasm_pixmap_get_h(this.pointer)
1325 }
1326 getX() {
1327 return libmupdf._wasm_pixmap_get_x(this.pointer)
1328 }
1329 getY() {
1330 return libmupdf._wasm_pixmap_get_y(this.pointer)
1331 }
1332 getStride() {
1333 return libmupdf._wasm_pixmap_get_stride(this.pointer)
1334 }
1335 getNumberOfComponents() {
1336 return libmupdf._wasm_pixmap_get_n(this.pointer)
1337 }
1338 getAlpha() {
1339 return libmupdf._wasm_pixmap_get_alpha(this.pointer)
1340 }
1341 getXResolution() {
1342 return libmupdf._wasm_pixmap_get_xres(this.pointer)
1343 }
1344 getYResolution() {
1345 return libmupdf._wasm_pixmap_get_yres(this.pointer)
1346 }
1347
1348 setResolution(x: number, y: number) {
1349 libmupdf._wasm_pixmap_set_xres(this.pointer, x)
1350 libmupdf._wasm_pixmap_set_yres(this.pointer, y)
1351 }
1352
1353 getColorSpace() {
1354 let cs = libmupdf._wasm_pixmap_get_colorspace(this.pointer)
1355 if (cs)
1356 return new ColorSpace(libmupdf._wasm_keep_colorspace(cs))
1357 return null
1358 }
1359
1360 getPixels() {
1361 let s = libmupdf._wasm_pixmap_get_stride(this.pointer)
1362 let h = libmupdf._wasm_pixmap_get_h(this.pointer)
1363 let p = libmupdf._wasm_pixmap_get_samples(this.pointer)
1364 return new Uint8ClampedArray(libmupdf.HEAPU8.buffer, p, s * h)
1365 }
1366
1367 asPNG() {
1368 let buf = libmupdf._wasm_new_buffer_from_pixmap_as_png(this.pointer)
1369 try {
1370 return fromBuffer(buf)
1371 } finally {
1372 libmupdf._wasm_drop_buffer(buf)
1373 }
1374 }
1375
1376 asPSD() {
1377 let buf = libmupdf._wasm_new_buffer_from_pixmap_as_psd(this.pointer)
1378 try {
1379 return fromBuffer(buf)
1380 } finally {
1381 libmupdf._wasm_drop_buffer(buf)
1382 }
1383 }
1384
1385 asPAM() {
1386 let buf = libmupdf._wasm_new_buffer_from_pixmap_as_pam(this.pointer)
1387 try {
1388 return fromBuffer(buf)
1389 } finally {
1390 libmupdf._wasm_drop_buffer(buf)
1391 }
1392 }
1393
1394 asJPEG(quality: number, invert_cmyk=false) {
1395 let buf = libmupdf._wasm_new_buffer_from_pixmap_as_jpeg(this.pointer, quality, invert_cmyk)
1396 try {
1397 return fromBuffer(buf)
1398 } finally {
1399 libmupdf._wasm_drop_buffer(buf)
1400 }
1401 }
1402
1403 invert() {
1404 libmupdf._wasm_invert_pixmap(this.pointer)
1405 }
1406
1407 invertLuminance() {
1408 libmupdf._wasm_invert_pixmap_luminance(this.pointer)
1409 }
1410
1411 gamma(p: number) {
1412 libmupdf._wasm_gamma_pixmap(this.pointer, p)
1413 }
1414
1415 tint(black: number | Color, white: number | Color) {
1416 let black_hex = 0x000000
1417 let white_hex = 0xffffff
1418 if (typeof black === "number")
1419 black_hex = black
1420 else if (black instanceof Array && black.length === 3)
1421 black_hex = ( ( (black[0] * 255) << 16 ) | ( (black[1] * 255) << 8 ) | ( (black[2] * 255) ) )
1422 if (typeof white === "number")
1423 white_hex = white
1424 else if (white instanceof Array && white.length === 3)
1425 white = ( ( (white[0] * 255) << 16 ) | ( (white[1] * 255) << 8 ) | ( (white[2] * 255) ) )
1426 libmupdf._wasm_tint_pixmap(this.pointer, black_hex, white_hex)
1427 }
1428
1429 convertToColorSpace(colorspace: ColorSpace, keepAlpha=false) {
1430 checkType(colorspace, ColorSpace)
1431 checkType(keepAlpha, "boolean")
1432 return new Pixmap(libmupdf._wasm_convert_pixmap(this.pointer, colorspace.pointer, keepAlpha))
1433 }
1434
1435 warp(points: Point[], width: number, height: number) {
1436 let quad = points.flat()
1437 checkQuad(quad)
1438 checkType(width, "number")
1439 checkType(height, "number")
1440 return new Pixmap(libmupdf._wasm_warp_pixmap(this.pointer, QUAD(quad), width, height))
1441 }
1442 }
1443
1444 export class Shade extends Userdata<"fz_shade"> {
1445 static override readonly _drop = libmupdf._wasm_drop_shade
1446 getBounds() {
1447 return fromRect(libmupdf._wasm_bound_shade(this.pointer))
1448 }
1449 }
1450
1451 interface StructuredTextWalker {
1452 onImageBlock?(bbox: Rect, transform: Matrix, image: Image): void
1453 beginTextBlock?(bbox: Rect): void
1454 beginLine?(bbox: Rect, wmode: number, direction: Point): void
1455 onChar?(c: string, origin: Point, font: Font, size: number, quad: Quad, color: Color): void
1456 endLine?(): void
1457 endTextBlock?(): void
1458 }
1459
1460 type SelectMode = "chars" | "words" | "lines"
1461
1462 export class StructuredText extends Userdata<"fz_stext_page"> {
1463 static override readonly _drop = libmupdf._wasm_drop_stext_page
1464
1465 static readonly SELECT_MODE: SelectMode[] = [
1466 "chars",
1467 "words",
1468 "lines"
1469 ]
1470
1471 static readonly SELECT_CHARS = "chars"
1472 static readonly SELECT_WORDS = "words"
1473 static readonly SELECT_LINES = "lines"
1474
1475 walk(walker: StructuredTextWalker) {
1476 let block = libmupdf._wasm_stext_page_get_first_block(this.pointer)
1477 while (block) {
1478 let block_type = libmupdf._wasm_stext_block_get_type(block)
1479 let block_bbox = fromRect(libmupdf._wasm_stext_block_get_bbox(block))
1480
1481 if (block_type === 1) {
1482 if (walker.onImageBlock) {
1483 let matrix = fromMatrix(libmupdf._wasm_stext_block_get_transform(block))
1484 let image = new Image(libmupdf._wasm_stext_block_get_image(block))
1485 walker.onImageBlock(block_bbox, matrix, image)
1486 }
1487 } else {
1488 if (walker.beginTextBlock)
1489 walker.beginTextBlock(block_bbox)
1490
1491 let line = libmupdf._wasm_stext_block_get_first_line(block)
1492 while (line) {
1493 let line_bbox = fromRect(libmupdf._wasm_stext_line_get_bbox(line))
1494 let line_wmode = libmupdf._wasm_stext_line_get_wmode(line)
1495 let line_dir = fromPoint(libmupdf._wasm_stext_line_get_dir(line))
1496
1497 if (walker.beginLine)
1498 walker.beginLine(line_bbox, line_wmode, line_dir)
1499
1500 if (walker.onChar) {
1501 let ch = libmupdf._wasm_stext_line_get_first_char(line)
1502 while (ch) {
1503 let ch_rune = String.fromCharCode(libmupdf._wasm_stext_char_get_c(ch))
1504 let ch_origin = fromPoint(libmupdf._wasm_stext_char_get_origin(ch))
1505 let ch_font = new Font(libmupdf._wasm_stext_char_get_font(ch))
1506 let ch_size = libmupdf._wasm_stext_char_get_size(ch)
1507 let ch_quad = fromQuad(libmupdf._wasm_stext_char_get_quad(ch))
1508 let ch_color = colorFromNumber(libmupdf._wasm_stext_char_get_argb(ch))
1509
1510 walker.onChar(ch_rune, ch_origin, ch_font, ch_size, ch_quad, ch_color)
1511
1512 ch = libmupdf._wasm_stext_char_get_next(ch)
1513 }
1514 }
1515
1516 if (walker.endLine)
1517 walker.endLine()
1518
1519 line = libmupdf._wasm_stext_line_get_next(line)
1520 }
1521
1522 if (walker.endTextBlock)
1523 walker.endTextBlock()
1524 }
1525
1526 block = libmupdf._wasm_stext_block_get_next(block)
1527 }
1528 }
1529
1530 asJSON(scale = 1) {
1531 return fromStringFree(libmupdf._wasm_print_stext_page_as_json(this.pointer, scale))
1532 }
1533
1534 asHTML(id: number) {
1535 return fromStringFree(libmupdf._wasm_print_stext_page_as_html(this.pointer, id))
1536 }
1537
1538 asText() {
1539 return fromStringFree(libmupdf._wasm_print_stext_page_as_text(this.pointer))
1540 }
1541
1542 snap(p: Point, q: Point, mode: SelectMode): Quad {
1543 let mm = ENUM<SelectMode>(mode, StructuredText.SELECT_MODE)
1544 return fromQuad(libmupdf._wasm_snap_selection(this.pointer, POINT(p), POINT2(q), mm))
1545 }
1546
1547 copy(p: Point, q: Point): string {
1548 return fromStringFree(libmupdf._wasm_copy_selection(this.pointer, POINT(p), POINT2(q)))
1549 }
1550
1551 highlight(p: Point, q: Point, max_hits = 100): Quad[] {
1552 let hits = 0 as Pointer<"fz_quad">
1553 let result: Quad[] = []
1554 try {
1555 hits = Malloc<"fz_quad">(32 * max_hits)
1556 let n = libmupdf._wasm_highlight_selection(this.pointer, POINT(p), POINT2(q), hits, max_hits)
1557 for (let i = 0; i < n; ++i)
1558 result.push(fromQuad(hits + i * 32 as Pointer<"fz_quad">))
1559 } finally {
1560 Free(hits)
1561 }
1562 return result
1563 }
1564
1565 search(needle: string, max_hits = 500) {
1566 return runSearch(libmupdf._wasm_search_stext_page, this.pointer, needle, max_hits)
1567 }
1568 }
1569
1570 export type BlendMode =
1571 "Normal" |
1572 "Multiply" |
1573 "Screen" |
1574 "Overlay" |
1575 "Darken" |
1576 "Lighten" |
1577 "ColorDodge" |
1578 "ColorBurn" |
1579 "HardLight" |
1580 "SoftLight" |
1581 "Difference" |
1582 "Exclusion" |
1583 "Hue" |
1584 "Saturation" |
1585 "Color" |
1586 "Luminosity"
1587
1588 export class Device extends Userdata<"fz_device"> {
1589 static override readonly _drop = libmupdf._wasm_drop_device
1590
1591 static readonly BLEND_MODES: BlendMode[] = [
1592 "Normal",
1593 "Multiply",
1594 "Screen",
1595 "Overlay",
1596 "Darken",
1597 "Lighten",
1598 "ColorDodge",
1599 "ColorBurn",
1600 "HardLight",
1601 "SoftLight",
1602 "Difference",
1603 "Exclusion",
1604 "Hue",
1605 "Saturation",
1606 "Color",
1607 "Luminosity",
1608 ]
1609
1610 constructor(pointer: Pointer<"fz_device">)
1611 constructor(callbacks: DeviceFunctions)
1612
1613 constructor(pointer_or_callbacks: Pointer<"fz_device"> | DeviceFunctions) {
1614 if (typeof pointer_or_callbacks === "number")
1615 super(pointer_or_callbacks)
1616 else {
1617 let id = $libmupdf_device_id++
1618 $libmupdf_device_table.set(id, pointer_or_callbacks)
1619 super(libmupdf._wasm_new_js_device(id))
1620 }
1621 }
1622
1623 fillPath(path: Path, evenOdd: boolean, ctm: Matrix, colorspace: ColorSpace, color: Color, alpha: number) {
1624 checkType(path, Path)
1625 checkMatrix(ctm)
1626 checkType(colorspace, ColorSpace)
1627 checkColor(color)
1628 libmupdf._wasm_fill_path(this.pointer, path.pointer, evenOdd, MATRIX(ctm), colorspace.pointer, COLOR(color), alpha)
1629 }
1630
1631 strokePath(path: Path, stroke: StrokeState, ctm: Matrix, colorspace: ColorSpace, color: Color, alpha: number) {
1632 checkType(path, Path)
1633 checkType(stroke, StrokeState)
1634 checkMatrix(ctm)
1635 checkType(colorspace, ColorSpace)
1636 checkColor(color)
1637 libmupdf._wasm_stroke_path(
1638 this.pointer,
1639 path.pointer,
1640 stroke.pointer,
1641 MATRIX(ctm),
1642 colorspace.pointer,
1643 COLOR(color),
1644 alpha
1645 )
1646 }
1647
1648 clipPath(path: Path, evenOdd: boolean, ctm: Matrix) {
1649 checkType(path, Path)
1650 checkMatrix(ctm)
1651 libmupdf._wasm_clip_path(this.pointer, path.pointer, evenOdd, MATRIX(ctm))
1652 }
1653
1654 clipStrokePath(path: Path, stroke: StrokeState, ctm: Matrix) {
1655 checkType(path, Path)
1656 checkType(stroke, StrokeState)
1657 checkMatrix(ctm)
1658 libmupdf._wasm_clip_stroke_path(this.pointer, path.pointer, stroke.pointer, MATRIX(ctm))
1659 }
1660
1661 fillText(text: Text, ctm: Matrix, colorspace: ColorSpace, color: Color, alpha: number) {
1662 checkType(text, Text)
1663 checkMatrix(ctm)
1664 checkType(colorspace, ColorSpace)
1665 checkColor(color)
1666 libmupdf._wasm_fill_text(this.pointer, text.pointer, MATRIX(ctm), colorspace.pointer, COLOR(color), alpha)
1667 }
1668
1669 strokeText(text: Text, stroke: StrokeState, ctm: Matrix, colorspace: ColorSpace, color: Color, alpha: number) {
1670 checkType(text, Text)
1671 checkType(stroke, StrokeState)
1672 checkMatrix(ctm)
1673 checkType(colorspace, ColorSpace)
1674 checkColor(color)
1675 libmupdf._wasm_stroke_text(
1676 this.pointer,
1677 text.pointer,
1678 stroke.pointer,
1679 MATRIX(ctm),
1680 colorspace.pointer,
1681 COLOR(color),
1682 alpha
1683 )
1684 }
1685
1686 clipText(text: Text, ctm: Matrix) {
1687 checkType(text, Text)
1688 checkMatrix(ctm)
1689 libmupdf._wasm_clip_text(this.pointer, text.pointer, MATRIX(ctm))
1690 }
1691
1692 clipStrokeText(text: Text, stroke: StrokeState, ctm: Matrix) {
1693 checkType(text, Text)
1694 checkType(stroke, StrokeState)
1695 checkMatrix(ctm)
1696 libmupdf._wasm_clip_stroke_text(this.pointer, text.pointer, stroke.pointer, MATRIX(ctm))
1697 }
1698
1699 ignoreText(text: Text, ctm: Matrix) {
1700 checkType(text, Text)
1701 checkMatrix(ctm)
1702 libmupdf._wasm_ignore_text(this.pointer, text.pointer, MATRIX(ctm))
1703 }
1704
1705 fillShade(shade: Shade, ctm: Matrix, alpha: number) {
1706 checkType(shade, Shade)
1707 checkMatrix(ctm)
1708 libmupdf._wasm_fill_shade(this.pointer, shade.pointer, MATRIX(ctm), alpha)
1709 }
1710
1711 fillImage(image: Image, ctm: Matrix, alpha: number) {
1712 checkType(image, Image)
1713 checkMatrix(ctm)
1714 libmupdf._wasm_fill_image(this.pointer, image.pointer, MATRIX(ctm), alpha)
1715 }
1716
1717 fillImageMask(image: Image, ctm: Matrix, colorspace: ColorSpace, color: Color, alpha: number) {
1718 checkType(image, Image)
1719 checkMatrix(ctm)
1720 checkType(colorspace, ColorSpace)
1721 checkColor(color)
1722 libmupdf._wasm_fill_image_mask(this.pointer, image.pointer, MATRIX(ctm), colorspace.pointer, COLOR(color), alpha)
1723 }
1724
1725 clipImageMask(image: Image, ctm: Matrix) {
1726 checkType(image, Image)
1727 checkMatrix(ctm)
1728 libmupdf._wasm_clip_image_mask(this.pointer, image.pointer, MATRIX(ctm))
1729 }
1730
1731 popClip() {
1732 libmupdf._wasm_pop_clip(this.pointer)
1733 }
1734
1735 beginMask(area: Rect, luminosity: boolean, colorspace: ColorSpace, color: Color) {
1736 checkRect(area)
1737 checkType(colorspace, ColorSpace)
1738 checkColor(color)
1739 libmupdf._wasm_begin_mask(this.pointer, RECT(area), luminosity, colorspace.pointer, COLOR(color))
1740 }
1741
1742 endMask() {
1743 libmupdf._wasm_end_mask(this.pointer)
1744 }
1745
1746 beginGroup(area: Rect, colorspace: ColorSpace, isolated: boolean, knockout: boolean, blendmode: BlendMode, alpha: number) {
1747 checkRect(area)
1748 checkType(colorspace, ColorSpace)
1749 let blendmode_ix = ENUM<BlendMode>(blendmode, Device.BLEND_MODES)
1750 libmupdf._wasm_begin_group(this.pointer, RECT(area), colorspace.pointer, isolated, knockout, blendmode_ix, alpha)
1751 }
1752
1753 endGroup() {
1754 libmupdf._wasm_end_group(this.pointer)
1755 }
1756
1757 beginTile(area: Rect, view: Rect, xstep: number, ystep: number, ctm: Matrix, id: number, doc_id: number) {
1758 checkRect(area)
1759 checkRect(view)
1760 checkMatrix(ctm)
1761 return libmupdf._wasm_begin_tile(this.pointer, RECT(area), RECT2(view), xstep, ystep, MATRIX(ctm), id, doc_id)
1762 }
1763
1764 endTile() {
1765 libmupdf._wasm_end_tile(this.pointer)
1766 }
1767
1768 beginLayer(name: string) {
1769 libmupdf._wasm_begin_layer(this.pointer, STRING(name))
1770 }
1771
1772 endLayer() {
1773 libmupdf._wasm_end_layer(this.pointer)
1774 }
1775
1776 close() {
1777 libmupdf._wasm_close_device(this.pointer)
1778 }
1779 }
1780
1781 export class DrawDevice extends Device {
1782 constructor(matrix: Matrix, pixmap: Pixmap) {
1783 checkMatrix(matrix)
1784 checkType(pixmap, Pixmap)
1785 super(libmupdf._wasm_new_draw_device(MATRIX(matrix), pixmap.pointer))
1786 }
1787 }
1788
1789 export class DisplayListDevice extends Device {
1790 constructor(displayList: DisplayList) {
1791 checkType(displayList, DisplayList)
1792 super(libmupdf._wasm_new_display_list_device(displayList.pointer))
1793 }
1794 }
1795
1796 export class DocumentWriter extends Userdata<"fz_document_writer"> {
1797 static override readonly _drop = libmupdf._wasm_drop_document_writer
1798
1799 constructor(buffer: Buffer, format: string, options: string) {
1800 super(
1801 libmupdf._wasm_new_document_writer_with_buffer(
1802 BUFFER(buffer),
1803 STRING(format),
1804 STRING2(options)
1805 )
1806 )
1807 }
1808
1809 beginPage(mediabox: Rect) {
1810 checkRect(mediabox)
1811 return new Device(
1812 libmupdf._wasm_keep_device(
1813 libmupdf._wasm_begin_page(this.pointer, RECT(mediabox))
1814 )
1815 )
1816 }
1817
1818 endPage() {
1819 libmupdf._wasm_end_page(this.pointer)
1820 }
1821
1822 close() {
1823 libmupdf._wasm_close_document_writer(this.pointer)
1824 }
1825 }
1826
1827 export type DocumentPermission =
1828 "print" |
1829 "copy" |
1830 "edit" |
1831 "annotate" |
1832 "form" |
1833 "accessibility" |
1834 "assemble" |
1835 "print-hq"
1836
1837 export class Document extends Userdata<"any_document"> {
1838 static override readonly _drop = libmupdf._wasm_drop_document
1839
1840 static readonly META_FORMAT = "format"
1841 static readonly META_ENCRYPTION = "encryption"
1842 static readonly META_INFO_AUTHOR = "info:Author"
1843 static readonly META_INFO_TITLE = "info:Title"
1844 static readonly META_INFO_SUBJECT = "info:Subject"
1845 static readonly META_INFO_KEYWORDS = "info:Keywords"
1846 static readonly META_INFO_CREATOR = "info:Creator"
1847 static readonly META_INFO_PRODUCER = "info:Producer"
1848 static readonly META_INFO_CREATIONDATE = "info:CreationDate"
1849 static readonly META_INFO_MODIFICATIONDATE = "info:ModDate"
1850
1851 static readonly PERMISSION: Record<DocumentPermission,number> = {
1852 "print": "p".charCodeAt(0),
1853 "copy": "c".charCodeAt(0),
1854 "edit": "e".charCodeAt(0),
1855 "annotate": "n".charCodeAt(0),
1856 "form": "f".charCodeAt(0),
1857 "accessibility": "y".charCodeAt(0),
1858 "assemble": "a".charCodeAt(0),
1859 "print-hq": "h".charCodeAt(0),
1860 }
1861
1862 static readonly LINK_DEST: LinkDestType[] = [
1863 "Fit",
1864 "FitB",
1865 "FitH",
1866 "FitBH",
1867 "FitV",
1868 "FitBV",
1869 "FitR",
1870 "XYZ",
1871 ]
1872
1873 static openDocument(from: Buffer | ArrayBuffer | Uint8Array | Stream | string, magic?: string): Document {
1874 let pointer = 0 as Pointer<"any_document">
1875 let free_from = false
1876
1877 if (typeof from === "string") {
1878 magic = from
1879 if (node_fs)
1880 from = node_fs.readFileSync(from)
1881 else
1882 throw new Error("missing 'fs' module")
1883 } else {
1884 if (typeof magic === "undefined")
1885 magic = "application/pdf"
1886 }
1887
1888 checkType(magic, "string")
1889
1890 if (from instanceof ArrayBuffer || from instanceof Uint8Array) {
1891 from = new Buffer(from)
1892 free_from = true
1893 }
1894 if (from instanceof Buffer)
1895 pointer = libmupdf._wasm_open_document_with_buffer(STRING(magic), from.pointer)
1896 else if (from instanceof Stream)
1897 pointer = libmupdf._wasm_open_document_with_stream(STRING(magic), from.pointer)
1898 else
1899 throw new Error("not a Buffer or Stream")
1900
1901 if (free_from) {
1902 // Destroy any implicit Buffer instances immediately!
1903 // This may help the GC and FinalizationRegistry out when
1904 // processing many documents without a pause.
1905 from.destroy()
1906 }
1907
1908 let pdf = libmupdf._wasm_pdf_document_from_fz_document(pointer)
1909 if (pdf)
1910 return new PDFDocument(pdf)
1911
1912 return new Document(pointer)
1913 }
1914
1915 formatLinkURI(dest: LinkDest) {
1916 return fromStringFree(
1917 libmupdf._wasm_format_link_uri(this.pointer,
1918 dest.chapter | 0,
1919 dest.page | 0,
1920 ENUM<LinkDestType>(dest.type, Document.LINK_DEST),
1921 +dest.x,
1922 +dest.y,
1923 +dest.width,
1924 +dest.height,
1925 +dest.zoom
1926 )
1927 )
1928 }
1929
1930 asPDF() {
1931 if (this instanceof PDFDocument)
1932 return this
1933 return null
1934 }
1935
1936 isPDF() {
1937 return this instanceof PDFDocument
1938 }
1939
1940 needsPassword() {
1941 return !!libmupdf._wasm_needs_password(this.pointer)
1942 }
1943
1944 authenticatePassword(password: string) {
1945 return libmupdf._wasm_authenticate_password(this.pointer, STRING(password))
1946 }
1947
1948 hasPermission(perm: DocumentPermission) {
1949 let perm_ix = Document.PERMISSION[perm]
1950 return !!libmupdf._wasm_has_permission(this.pointer, perm_ix)
1951 }
1952
1953 getMetaData(key: string) {
1954 let value = libmupdf._wasm_lookup_metadata(this.pointer, STRING(key))
1955 if (value)
1956 return fromString(value)
1957 return undefined
1958 }
1959
1960 setMetaData(key: string, value: string) {
1961 libmupdf._wasm_set_metadata(this.pointer, STRING(key), STRING2(value))
1962 }
1963
1964 countPages() {
1965 return libmupdf._wasm_count_pages(this.pointer)
1966 }
1967
1968 isReflowable() {
1969 libmupdf._wasm_is_document_reflowable(this.pointer)
1970 }
1971
1972 layout(w: number, h: number, em: number) {
1973 libmupdf._wasm_layout_document(this.pointer, w, h, em)
1974 }
1975
1976 loadPage(index: number) {
1977 let fz_ptr = libmupdf._wasm_load_page(this.pointer, index)
1978 if (this instanceof PDFDocument) {
1979 let pdf_ptr = libmupdf._wasm_pdf_page_from_fz_page(fz_ptr)
1980 if (pdf_ptr)
1981 return new PDFPage(this, pdf_ptr)
1982 }
1983 return new Page(fz_ptr)
1984 }
1985
1986 loadOutline() {
1987 let doc = this.pointer
1988 function to_outline(outline: Pointer<"fz_outline">) {
1989 let result: OutlineItem[] = []
1990 while (outline) {
1991 let title = libmupdf._wasm_outline_get_title(outline)
1992 let uri = libmupdf._wasm_outline_get_uri(outline)
1993 let open = libmupdf._wasm_outline_get_is_open(outline)
1994
1995 let item: OutlineItem = {
1996 title: title ? fromString(title) : undefined,
1997 uri: uri ? fromString(uri) : undefined,
1998 open: !!open,
1999 }
2000
2001 let page = libmupdf._wasm_outline_get_page(doc, outline)
2002 if (page >= 0)
2003 item.page = page
2004
2005 let down = libmupdf._wasm_outline_get_down(outline)
2006 if (down)
2007 item.down = to_outline(down)
2008
2009 result.push(item)
2010
2011 outline = libmupdf._wasm_outline_get_next(outline)
2012 }
2013 return result
2014 }
2015 let root = libmupdf._wasm_load_outline(doc)
2016 if (root)
2017 return to_outline(root)
2018 return null
2019 }
2020
2021 resolveLink(link: string | Link) {
2022 if (link instanceof Link)
2023 return libmupdf._wasm_resolve_link(this.pointer, libmupdf._wasm_link_get_uri(link.pointer))
2024 return libmupdf._wasm_resolve_link(this.pointer, STRING(link))
2025 }
2026
2027 resolveLinkDestination(link: string | Link): LinkDest {
2028 let dest: Pointer<"fz_link_dest">
2029 if (link instanceof Link)
2030 dest = libmupdf._wasm_resolve_link_dest(this.pointer, libmupdf._wasm_link_get_uri(link.pointer))
2031 else
2032 dest = libmupdf._wasm_resolve_link_dest(this.pointer, STRING(link))
2033 return {
2034 type: Document.LINK_DEST[libmupdf._wasm_link_dest_get_type(dest)] as LinkDestType,
2035 chapter: libmupdf._wasm_link_dest_get_chapter(dest),
2036 page: libmupdf._wasm_link_dest_get_page(dest),
2037 x: libmupdf._wasm_link_dest_get_x(dest),
2038 y: libmupdf._wasm_link_dest_get_y(dest),
2039 width: libmupdf._wasm_link_dest_get_w(dest),
2040 height: libmupdf._wasm_link_dest_get_h(dest),
2041 zoom: libmupdf._wasm_link_dest_get_zoom(dest),
2042 }
2043 }
2044
2045 outlineIterator() {
2046 return new OutlineIterator(libmupdf._wasm_new_outline_iterator(this.pointer))
2047 }
2048 }
2049
2050 interface OutlineItem {
2051 title: string | undefined,
2052 uri: string | undefined,
2053 open: boolean,
2054 down?: OutlineItem[],
2055 page?: number,
2056 }
2057
2058 export class OutlineIterator extends Userdata<"fz_outline_iterator"> {
2059 static override readonly _drop = libmupdf._wasm_drop_outline_iterator
2060
2061 static readonly RESULT_DID_NOT_MOVE = -1
2062 static readonly RESULT_AT_ITEM = 0
2063 static readonly RESULT_AT_EMPTY = 1
2064
2065 item() {
2066 let item = libmupdf._wasm_outline_iterator_item(this.pointer)
2067 if (item) {
2068 let title_ptr = libmupdf._wasm_outline_item_get_title(item)
2069 let uri_ptr = libmupdf._wasm_outline_item_get_uri(item)
2070 let is_open = libmupdf._wasm_outline_item_get_is_open(item)
2071 return {
2072 title: title_ptr ? fromString(title_ptr) : undefined,
2073 uri: uri_ptr ? fromString(uri_ptr) : undefined,
2074 open: !!is_open,
2075 } as OutlineItem
2076 }
2077 return null
2078 }
2079
2080 next() {
2081 return libmupdf._wasm_outline_iterator_next(this.pointer)
2082 }
2083
2084 prev() {
2085 return libmupdf._wasm_outline_iterator_prev(this.pointer)
2086 }
2087
2088 up() {
2089 return libmupdf._wasm_outline_iterator_up(this.pointer)
2090 }
2091
2092 down() {
2093 return libmupdf._wasm_outline_iterator_down(this.pointer)
2094 }
2095
2096 delete() {
2097 return libmupdf._wasm_outline_iterator_delete(this.pointer)
2098 }
2099
2100 insert(item: OutlineItem) {
2101 return libmupdf._wasm_outline_iterator_insert(this.pointer, STRING_OPT(item.title), STRING2_OPT(item.uri), item.open)
2102 }
2103
2104 update(item: OutlineItem) {
2105 libmupdf._wasm_outline_iterator_update(this.pointer, STRING_OPT(item.title), STRING2_OPT(item.uri), item.open)
2106 }
2107 }
2108
2109 export type LinkDestType =
2110 "Fit" |
2111 "FitB" |
2112 "FitH" |
2113 "FitBH" |
2114 "FitV" |
2115 "FitBV" |
2116 "FitR" |
2117 "XYZ"
2118
2119 interface LinkDest {
2120 type: LinkDestType,
2121 chapter: number,
2122 page: number,
2123 x: number,
2124 y: number,
2125 width: number,
2126 height: number,
2127 zoom: number,
2128 }
2129
2130 export class Link extends Userdata<"fz_link"> {
2131 static override readonly _drop = libmupdf._wasm_drop_link
2132
2133 getBounds() {
2134 return fromRect(libmupdf._wasm_link_get_rect(this.pointer))
2135 }
2136
2137 setBounds(rect: Rect) {
2138 checkRect(rect)
2139 libmupdf._wasm_link_set_rect(this.pointer, RECT(rect))
2140 }
2141
2142 getURI() {
2143 return fromString(libmupdf._wasm_link_get_uri(this.pointer))
2144 }
2145
2146 setURI(uri: string) {
2147 checkType(uri, "string")
2148 libmupdf._wasm_link_set_uri(this.pointer, STRING(uri))
2149 }
2150
2151 isExternal() {
2152 return /^\w[\w+-.]*:/.test(this.getURI())
2153 }
2154 }
2155
2156 export type PageBox = "MediaBox" | "CropBox" | "BleedBox" | "TrimBox" | "ArtBox"
2157
2158 export class Page extends Userdata<"any_page"> {
2159 static override readonly _drop = libmupdf._wasm_drop_page
2160
2161 static readonly BOXES: PageBox[] = [
2162 "MediaBox",
2163 "CropBox",
2164 "BleedBox",
2165 "TrimBox",
2166 "ArtBox"
2167 ]
2168
2169 isPDF() {
2170 return this instanceof PDFPage
2171 }
2172
2173 getBounds(box: PageBox = "CropBox") {
2174 let box_ix = ENUM<PageBox>(box, Page.BOXES)
2175 return fromRect(libmupdf._wasm_bound_page(this.pointer, box_ix))
2176 }
2177
2178 getLabel() {
2179 return fromString(libmupdf._wasm_page_label(this.pointer))
2180 }
2181
2182 run(device: Device, matrix: Matrix) {
2183 checkType(device, Device)
2184 checkMatrix(matrix)
2185 libmupdf._wasm_run_page(this.pointer, device.pointer, MATRIX(matrix))
2186 }
2187
2188 runPageContents(device: Device, matrix: Matrix) {
2189 checkType(device, Device)
2190 checkMatrix(matrix)
2191 libmupdf._wasm_run_page_contents(this.pointer, device.pointer, MATRIX(matrix))
2192 }
2193
2194 runPageAnnots(device: Device, matrix: Matrix) {
2195 checkType(device, Device)
2196 checkMatrix(matrix)
2197 libmupdf._wasm_run_page_annots(this.pointer, device.pointer, MATRIX(matrix))
2198 }
2199
2200 runPageWidgets(device: Device, matrix: Matrix) {
2201 checkType(device, Device)
2202 checkMatrix(matrix)
2203 libmupdf._wasm_run_page_widgets(this.pointer, device.pointer, MATRIX(matrix))
2204 }
2205
2206 toPixmap(matrix: Matrix, colorspace: ColorSpace, alpha = false, showExtras = true) {
2207 checkType(colorspace, ColorSpace)
2208 checkMatrix(matrix)
2209 let result
2210 if (showExtras)
2211 result = libmupdf._wasm_new_pixmap_from_page(this.pointer,
2212 MATRIX(matrix),
2213 colorspace.pointer,
2214 alpha)
2215 else
2216 result = libmupdf._wasm_new_pixmap_from_page_contents(this.pointer,
2217 MATRIX(matrix),
2218 colorspace.pointer,
2219 alpha)
2220 return new Pixmap(result)
2221 }
2222
2223 toDisplayList(showExtras = true) {
2224 let result
2225 if (showExtras)
2226 result = libmupdf._wasm_new_display_list_from_page(this.pointer)
2227 else
2228 result = libmupdf._wasm_new_display_list_from_page_contents(this.pointer)
2229 return new DisplayList(result)
2230 }
2231
2232 toStructuredText(options = "") {
2233 checkType(options, "string")
2234 return new StructuredText(libmupdf._wasm_new_stext_page_from_page(this.pointer, STRING(options)))
2235 }
2236
2237 getLinks() {
2238 let links: Link[] = []
2239 let link = libmupdf._wasm_load_links(this.pointer)
2240 while (link) {
2241 links.push(new Link(libmupdf._wasm_keep_link(link)))
2242 link = libmupdf._wasm_link_get_next(link)
2243 }
2244 return links
2245 }
2246
2247 createLink(bbox: Rect, uri: string) {
2248 checkRect(bbox)
2249 return new Link(libmupdf._wasm_create_link(this.pointer, RECT(bbox), STRING(uri)))
2250 }
2251
2252 deleteLink(link: Link) {
2253 checkType(link, Link)
2254 libmupdf._wasm_delete_link(this.pointer, link.pointer)
2255 }
2256
2257 search(needle: string, max_hits = 500) {
2258 return runSearch(libmupdf._wasm_search_page, this.pointer, needle, max_hits)
2259 }
2260
2261 }
2262
2263 /* -------------------------------------------------------------------------- */
2264
2265 export class PDFDocument extends Document {
2266 // Create a new empty document
2267 constructor()
2268
2269 // Open an existing document
2270 constructor(filename: string)
2271 constructor(data: Buffer | ArrayBuffer | Uint8Array | Stream)
2272
2273 // PRIVATE
2274 constructor(clone: PDFDocument)
2275 constructor(pointer: Pointer<"any_document">)
2276 constructor(data: Buffer | ArrayBuffer | Uint8Array | Stream)
2277
2278 constructor(arg1?: Pointer<"any_document"> | Buffer | ArrayBuffer | Uint8Array | Stream | PDFDocument | string) {
2279 if (typeof arg1 === "undefined")
2280 super(libmupdf._wasm_pdf_create_document())
2281 else if (typeof arg1 === "number")
2282 super(arg1)
2283 else if (arg1 instanceof PDFDocument) {
2284 super(arg1.pointer)
2285 libmupdf._wasm_keep_document(this.pointer)
2286 } else {
2287 let doc = Document.openDocument(arg1, "application/pdf")
2288 if (doc instanceof PDFDocument)
2289 return doc
2290 throw new Error("not a PDF document")
2291 }
2292 }
2293
2294 override loadPage(index: number) {
2295 return super.loadPage(index) as PDFPage
2296 }
2297
2298 // PDFObject instances are always bound to a document, so the WASM/JS value interface lives here.
2299
2300 // Wrap a pdf_obj in a Userdata object. The pointer must be newly created or we already own it.
2301 _fromPDFObjectNew(ptr: Pointer<"pdf_obj">) {
2302 if (ptr === 0)
2303 return PDFObject.Null
2304 return new PDFObject(this, ptr)
2305 }
2306
2307 // Wrap a pdf_obj in a Userdata object. The pointer must be a borrowed pointer, so we have to take ownership.
2308 _fromPDFObjectKeep(ptr: Pointer<"pdf_obj">) {
2309 if (ptr === 0)
2310 return PDFObject.Null
2311 return new PDFObject(this, libmupdf._wasm_pdf_keep_obj(ptr))
2312 }
2313
2314 _toPDFObject(obj: any) {
2315 if (obj instanceof PDFObject)
2316 return obj
2317 if (obj === null || obj === undefined)
2318 return this.newNull()
2319 if (typeof obj === "string") {
2320 // if a JS string is surrounded by parens, convert it to a PDF string
2321 if (obj.startsWith("(") && obj.endsWith(")"))
2322 return this.newString(obj.slice(1, -1))
2323 // otherwise treat it as a name
2324 return this.newName(obj)
2325 }
2326 if (typeof obj === "number") {
2327 if (obj === (obj | 0))
2328 return this.newInteger(obj)
2329 return this.newReal(obj)
2330 }
2331 if (typeof obj === "boolean")
2332 return this.newBoolean(obj)
2333 if (obj instanceof Array) {
2334 let result = this.newArray()
2335 for (let item of obj)
2336 result.push(item)
2337 return result
2338 }
2339 if (obj instanceof Object) {
2340 let result = this.newDictionary()
2341 for (let key in obj)
2342 result.put(key, obj[key])
2343 return result
2344 }
2345 throw new TypeError("cannot convert value to PDFObject")
2346 }
2347
2348 _PDFOBJ(obj: any) {
2349 // Note: We have to create a PDFObject instance for garbage collection.
2350 return this._toPDFObject(obj).pointer
2351 }
2352
2353 getVersion() {
2354 return libmupdf._wasm_pdf_version(this.pointer)
2355 }
2356
2357 getLanguage() {
2358 return fromStringOrNull(libmupdf._wasm_pdf_document_language(this.pointer))
2359 }
2360
2361 setLanguage(lang: string) {
2362 libmupdf._wasm_pdf_set_document_language(this.pointer, STRING(lang))
2363 }
2364
2365 countObjects() {
2366 return libmupdf._wasm_pdf_xref_len(this.pointer)
2367 }
2368
2369 getTrailer() {
2370 return new PDFObject(this, libmupdf._wasm_pdf_trailer(this.pointer))
2371 }
2372
2373 createObject() {
2374 let num = libmupdf._wasm_pdf_create_object(this.pointer)
2375 return this._fromPDFObjectNew(libmupdf._wasm_pdf_new_indirect(this.pointer, num))
2376 }
2377
2378 newNull() { return PDFObject.Null }
2379 newBoolean(v: boolean) { return this._fromPDFObjectNew(libmupdf._wasm_pdf_new_bool(v)) }
2380 newInteger(v: number) { return this._fromPDFObjectNew(libmupdf._wasm_pdf_new_int(v)) }
2381 newReal(v: number) { return this._fromPDFObjectNew(libmupdf._wasm_pdf_new_real(v)) }
2382 newName(v: string) { return this._fromPDFObjectNew(libmupdf._wasm_pdf_new_name(STRING(v))) }
2383 newString(v: string) { return this._fromPDFObjectNew(libmupdf._wasm_pdf_new_text_string(STRING(v))) }
2384
2385 newByteString(v: Uint8Array | number[]) {
2386 if (v instanceof Array)
2387 v = Uint8Array.from(v)
2388 checkType(v, Uint8Array)
2389 let len = v.byteLength
2390 let ptr = Malloc<"char">(len)
2391 libmupdf.HEAPU8.set(v, ptr)
2392 try {
2393 return this._fromPDFObjectNew(libmupdf._wasm_pdf_new_string(ptr, len))
2394 } finally {
2395 Free(ptr)
2396 }
2397 }
2398
2399 newIndirect(v: number) { return this._fromPDFObjectNew(libmupdf._wasm_pdf_new_indirect(this.pointer, v)) }
2400 newArray() { return this._fromPDFObjectNew(libmupdf._wasm_pdf_new_array(this.pointer)) }
2401 newDictionary() { return this._fromPDFObjectNew(libmupdf._wasm_pdf_new_dict(this.pointer)) }
2402
2403 deleteObject(num: number | PDFObject) {
2404 if (num instanceof PDFObject)
2405 num = num.asIndirect()
2406 else
2407 checkType(num, "number")
2408 libmupdf._wasm_pdf_delete_object(this.pointer, num)
2409 }
2410
2411 addObject(obj: any) {
2412 return this._fromPDFObjectNew(libmupdf._wasm_pdf_add_object(this.pointer, this._PDFOBJ(obj)))
2413 }
2414
2415 addStream(buf: AnyBuffer, obj: any) {
2416 return this._fromPDFObjectNew(libmupdf._wasm_pdf_add_stream(this.pointer, BUFFER(buf), this._PDFOBJ(obj), 0))
2417 }
2418
2419 addRawStream(buf: AnyBuffer, obj: any) {
2420 return this._fromPDFObjectNew(libmupdf._wasm_pdf_add_stream(this.pointer, BUFFER(buf), this._PDFOBJ(obj), 1))
2421 }
2422
2423 newGraftMap() {
2424 return new PDFGraftMap(this, libmupdf._wasm_pdf_new_graft_map(this.pointer))
2425 }
2426
2427 graftObject(obj: PDFObject) {
2428 checkType(obj, PDFObject)
2429 return this._fromPDFObjectNew(libmupdf._wasm_pdf_graft_object(this.pointer, obj.pointer))
2430 }
2431
2432 graftPage(to: number, srcDoc: PDFDocument, srcPage: number) {
2433 checkType(to, "number")
2434 checkType(srcDoc, PDFDocument)
2435 checkType(srcPage, "number")
2436 libmupdf._wasm_pdf_graft_page(this.pointer, to, srcDoc.pointer, srcPage)
2437 }
2438
2439 addSimpleFont(font: Font, encoding: FontSimpleEncoding = "Latin") {
2440 checkType(font, Font)
2441 var encoding_ix = ENUM<FontSimpleEncoding>(encoding, Font.SIMPLE_ENCODING)
2442 return this._fromPDFObjectNew(libmupdf._wasm_pdf_add_simple_font(this.pointer, font.pointer, encoding_ix))
2443 }
2444
2445 addCJKFont(font: Font, lang: FontCJKOrdering | FontCJKLanguage, wmode = 0, serif = true) {
2446 checkType(font, Font)
2447 if (typeof lang === "string")
2448 lang = Font.CJK_ORDERING_BY_LANG[lang]
2449 return this._fromPDFObjectNew(libmupdf._wasm_pdf_add_cjk_font(this.pointer, font.pointer, lang, wmode, serif))
2450 }
2451
2452 addFont(font: Font) {
2453 checkType(font, Font)
2454 return this._fromPDFObjectNew(libmupdf._wasm_pdf_add_cid_font(this.pointer, font.pointer))
2455 }
2456
2457 addImage(image: Image) {
2458 checkType(image, Image)
2459 return this._fromPDFObjectNew(libmupdf._wasm_pdf_add_image(this.pointer, image.pointer))
2460 }
2461
2462 loadImage(ref: PDFObject) {
2463 checkType(ref, PDFObject)
2464 return new Image(libmupdf._wasm_pdf_load_image(this.pointer, ref.pointer))
2465 }
2466
2467 findPage(index: number) {
2468 checkType(index, "number")
2469 return this._fromPDFObjectKeep(libmupdf._wasm_pdf_lookup_page_obj(this.pointer, index))
2470 }
2471
2472 addPage(mediabox: Rect, rotate: Rotate, resources: any, contents: AnyBuffer) {
2473 checkRect(mediabox)
2474 checkType(rotate, "number")
2475 return this._fromPDFObjectNew(
2476 libmupdf._wasm_pdf_add_page(
2477 this.pointer,
2478 RECT(mediabox),
2479 rotate,
2480 this._PDFOBJ(resources),
2481 BUFFER(contents)
2482 )
2483 )
2484 }
2485
2486 insertPage(at: number, obj: PDFObject) {
2487 checkType(at, "number")
2488 libmupdf._wasm_pdf_insert_page(this.pointer, at, this._PDFOBJ(obj))
2489 }
2490
2491 deletePage(at: number) {
2492 checkType(at, "number")
2493 libmupdf._wasm_pdf_delete_page(this.pointer, at)
2494 }
2495
2496 isEmbeddedFile(ref: PDFObject) {
2497 checkType(ref, PDFObject)
2498 return !!libmupdf._wasm_pdf_is_embedded_file(ref.pointer)
2499 }
2500
2501 addEmbeddedFile(filename: string, mimetype: string, contents: AnyBuffer, created: Date, modified: Date, checksum = false) {
2502 checkType(filename, "string")
2503 checkType(mimetype, "string")
2504 checkType(created, Date)
2505 checkType(modified, Date)
2506 checkType(checksum, "boolean")
2507 return this._fromPDFObjectNew(
2508 libmupdf._wasm_pdf_add_embedded_file(
2509 this.pointer,
2510 STRING(filename),
2511 STRING2(mimetype),
2512 BUFFER(contents),
2513 created.getTime() / 1000 | 0,
2514 modified.getTime() / 1000 | 0,
2515 checksum
2516 )
2517 )
2518 }
2519
2520 getFilespecParams(ref: PDFObject) {
2521 checkType(ref, PDFObject)
2522 let ptr = libmupdf._wasm_pdf_get_filespec_params(ref.pointer)
2523 return {
2524 filename:
2525 fromString(libmupdf._wasm_pdf_filespec_params_get_filename(ptr)),
2526 mimetype:
2527 fromString(libmupdf._wasm_pdf_filespec_params_get_mimetype(ptr)),
2528 size:
2529 libmupdf._wasm_pdf_filespec_params_get_filename(ptr),
2530 creationDate:
2531 new Date(libmupdf._wasm_pdf_filespec_params_get_created(ptr) * 1000),
2532 modificationDate:
2533 new Date(libmupdf._wasm_pdf_filespec_params_get_modified(ptr) * 1000),
2534 }
2535 }
2536
2537 getEmbeddedFileContents(ref: PDFObject) {
2538 checkType(ref, PDFObject)
2539 let contents = libmupdf._wasm_pdf_load_embedded_file_contents(ref.pointer)
2540 if (contents)
2541 return new Buffer(contents)
2542 return null
2543 }
2544
2545 getEmbeddedFiles(): Record<string,PDFObject> {
2546 function _getEmbeddedFilesRec(result: Record<string,PDFObject>, N: PDFObject) {
2547 var i, n
2548 if (N.isDictionary()) {
2549 var NN = N.get("Names")
2550 if (NN)
2551 for (i = 0, n = NN.length; i < n; i += 2)
2552 result[NN.get(i+0).asString()] = NN.get(i+1)
2553 var NK = N.get("Kids")
2554 if (NK)
2555 for (i = 0, n = NK.length; i < n; i += 1)
2556 _getEmbeddedFilesRec(result, NK.get(i))
2557 }
2558 return result
2559 }
2560 return _getEmbeddedFilesRec({}, this.getTrailer().get("Root", "Names", "EmbeddedFiles"))
2561 }
2562
2563 loadNameTree(treeName: string): Record<string,PDFObject> {
2564 function _loadNameTreeRec(dict: Record<string,PDFObject>, node: PDFObject) {
2565 var kids = node.get("Kids")
2566 if (kids && kids.isArray())
2567 for (var i = 0; i < kids.length; i += 1)
2568 _loadNameTreeRec(dict, kids.get(i))
2569 var names = node.get("Names")
2570 if (names && names.isArray())
2571 for (var i = 0; i < names.length; i += 2)
2572 dict[names.get(i).asString()] = names.get(i+1)
2573 }
2574 var node = this.getTrailer().get("Root").get("Names").get(treeName)
2575 var dict = {}
2576 if (node.isDictionary())
2577 _loadNameTreeRec(dict, node)
2578 return dict
2579 }
2580
2581 insertEmbeddedFile(filename: string, filespec: PDFObject) {
2582 var efs = this.getEmbeddedFiles()
2583 efs[filename] = filespec
2584 this._rewriteEmbeddedFiles(efs)
2585 }
2586
2587 deleteEmbeddedFile(filename: string) {
2588 var efs = this.getEmbeddedFiles()
2589 delete efs[filename]
2590 this._rewriteEmbeddedFiles(efs)
2591 }
2592
2593 _rewriteEmbeddedFiles(efs: Record<string,PDFObject>) {
2594 var efs_keys = Object.keys(efs)
2595 efs_keys.sort()
2596 var root = this.getTrailer().get("Root")
2597 var root_names = root.get("Names")
2598 if (!root_names.isDictionary())
2599 root_names = root.put("Names", this.newDictionary())
2600 var root_names_efs = root_names.put("EmbeddedFiles", this.newDictionary())
2601 var root_names_efs_names = root_names_efs.put("Names", this.newArray())
2602 for (var key of efs_keys) {
2603 root_names_efs_names.push(this.newString(key))
2604 root_names_efs_names.push(efs[key])
2605 }
2606 }
2607
2608 saveToBuffer(options: string | Record<string,any> = "") {
2609 var options_string
2610 if (typeof options === "object") {
2611 options_string = Object.entries(options).map(kv => {
2612 var k: string = kv[0]
2613 var v: any = kv[1]
2614 if (v === true)
2615 return k + "=" + "yes"
2616 else if (v === false)
2617 return k + "=" + "no"
2618 else
2619 return k + "=" + String(v).replaceAll(",", ":")
2620 }).join(",")
2621 } else {
2622 options_string = options
2623 }
2624 return new Buffer(libmupdf._wasm_pdf_write_document_buffer(this.pointer, STRING(options_string)))
2625 }
2626
2627 save(filename: string, options: string | Record<string,any> = "") {
2628 if (node_fs)
2629 node_fs.writeFileSync(filename, this.saveToBuffer(options).asUint8Array())
2630 else
2631 throw new Error("missing 'fs' module")
2632 }
2633
2634 static readonly PAGE_LABEL_NONE = "\0"
2635 static readonly PAGE_LABEL_DECIMAL = "D"
2636 static readonly PAGE_LABEL_ROMAN_UC = "R"
2637 static readonly PAGE_LABEL_ROMAN_LC = "r"
2638 static readonly PAGE_LABEL_ALPHA_UC = "A"
2639 static readonly PAGE_LABEL_ALPHA_LC = "a"
2640
2641 setPageLabels(index: number, style = "D", prefix = "", start = 1) {
2642 libmupdf._wasm_pdf_set_page_labels(this.pointer, index, style.charCodeAt(0), STRING(prefix), start)
2643 }
2644
2645 deletePageLabels(index: number) {
2646 libmupdf._wasm_pdf_delete_page_labels(this.pointer, index)
2647 }
2648
2649 wasRepaired() {
2650 return !!libmupdf._wasm_pdf_was_repaired(this.pointer)
2651 }
2652
2653 hasUnsavedChanges() {
2654 return !!libmupdf._wasm_pdf_has_unsaved_changes(this.pointer)
2655 }
2656
2657 countVersions() {
2658 return libmupdf._wasm_pdf_count_versions(this.pointer)
2659 }
2660
2661 countUnsavedVersions() {
2662 return libmupdf._wasm_pdf_count_unsaved_versions(this.pointer)
2663 }
2664
2665 validateChangeHistory() {
2666 return libmupdf._wasm_pdf_validate_change_history(this.pointer)
2667 }
2668
2669 canBeSavedIncrementally() {
2670 return !!libmupdf._wasm_pdf_can_be_saved_incrementally(this.pointer)
2671 }
2672
2673 enableJournal() {
2674 libmupdf._wasm_pdf_enable_journal(this.pointer)
2675 }
2676
2677 getJournal() {
2678 let position = libmupdf._wasm_pdf_undoredo_state_position(this.pointer)
2679 let n = libmupdf._wasm_pdf_undoredo_state_count(this.pointer)
2680 let steps: string[] = []
2681 for (let i = 0; i < n; ++i)
2682 steps.push(
2683 fromString(
2684 libmupdf._wasm_pdf_undoredo_step(this.pointer, i),
2685 )
2686 )
2687 return { position, steps }
2688 }
2689
2690 beginOperation(op: string) {
2691 libmupdf._wasm_pdf_begin_operation(this.pointer, STRING(op))
2692 }
2693
2694 beginImplicitOperation() {
2695 libmupdf._wasm_pdf_begin_implicit_operation(this.pointer)
2696 }
2697
2698 endOperation() {
2699 libmupdf._wasm_pdf_end_operation(this.pointer)
2700 }
2701
2702 abandonOperation() {
2703 libmupdf._wasm_pdf_abandon_operation(this.pointer)
2704 }
2705
2706 canUndo() {
2707 return !!libmupdf._wasm_pdf_can_undo(this.pointer)
2708 }
2709
2710 canRedo() {
2711 return !!libmupdf._wasm_pdf_can_redo(this.pointer)
2712 }
2713
2714 undo() {
2715 libmupdf._wasm_pdf_undo(this.pointer)
2716 }
2717
2718 redo() {
2719 libmupdf._wasm_pdf_redo(this.pointer)
2720 }
2721
2722 isJSSupported() {
2723 return !!libmupdf._wasm_pdf_js_supported(this.pointer)
2724 }
2725
2726 enableJS() {
2727 libmupdf._wasm_pdf_enable_js(this.pointer)
2728 }
2729
2730 disableJS() {
2731 libmupdf._wasm_pdf_disable_js(this.pointer)
2732 }
2733
2734 setJSEventListener(_listener: any) {
2735 throw "TODO"
2736 }
2737
2738 rearrangePages(pages: number[]) {
2739 let n = pages.length
2740 let ptr = Malloc<"int">(n << 2)
2741 for (let i = 0; i < n; ++i)
2742 libmupdf.HEAPU32[(ptr >> 2) + i] = pages[i] || 0
2743 try {
2744 libmupdf._wasm_pdf_rearrange_pages(this.pointer, n, ptr)
2745 } finally {
2746 Free(ptr)
2747 }
2748 }
2749
2750 subsetFonts() {
2751 libmupdf._wasm_pdf_subset_fonts(this.pointer)
2752 }
2753
2754 bake(bakeAnnots = true, bakeWidgets = true) {
2755 libmupdf._wasm_pdf_bake_document(this.pointer, bakeAnnots, bakeWidgets)
2756 }
2757
2758 countLayers(): number {
2759 return libmupdf._wasm_pdf_count_layers(this.pointer)
2760 }
2761
2762 isLayerVisible(layer: number): boolean {
2763 return !!libmupdf._wasm_pdf_layer_is_enabled(this.pointer, layer)
2764 }
2765
2766 setLayerVisible(layer: number, visible: boolean): void {
2767 libmupdf._wasm_pdf_enable_layer(this.pointer, layer, Number(visible))
2768 }
2769
2770 getLayerName(layer: number): string {
2771 return fromString(libmupdf._wasm_pdf_layer_name(this.pointer, layer))
2772 }
2773
2774 resetForm(fields: PDFObject, exclude: boolean) {
2775 libmupdf._wasm_pdf_reset_form(this.pointer, this._PDFOBJ(fields), Number(exclude))
2776 }
2777 }
2778
2779 export class PDFPage extends Page {
2780 _doc: PDFDocument
2781 _annots: PDFAnnotation[] | null
2782 _widgets: PDFWidget[] | null
2783
2784 // PRIVATE
2785 constructor(doc: PDFDocument, pointer: Pointer<"any_page">) {
2786 super(pointer)
2787 this._doc = doc
2788 this._annots = null
2789 this._widgets = null
2790 }
2791
2792 getObject() {
2793 return this._doc._fromPDFObjectKeep(libmupdf._wasm_pdf_page_get_obj(this.pointer))
2794 }
2795
2796 getTransform() {
2797 return fromMatrix(libmupdf._wasm_pdf_page_transform(this.pointer))
2798 }
2799
2800 setPageBox(box: PageBox, rect: Rect) {
2801 let box_ix = ENUM<PageBox>(box, Page.BOXES)
2802 checkRect(rect)
2803 libmupdf._wasm_pdf_set_page_box(this.pointer, box_ix, RECT(rect))
2804 }
2805
2806 override toPixmap(matrix: Matrix, colorspace: ColorSpace, alpha = false, showExtras = true, usage = "View", box: PageBox = "CropBox") {
2807 checkMatrix(matrix)
2808 checkType(colorspace, ColorSpace)
2809 let box_ix = ENUM<PageBox>(box, Page.BOXES)
2810 let result
2811 if (showExtras)
2812 result = libmupdf._wasm_pdf_new_pixmap_from_page_with_usage(this.pointer,
2813 MATRIX(matrix),
2814 colorspace.pointer,
2815 alpha,
2816 STRING(usage),
2817 box_ix)
2818 else
2819 result = libmupdf._wasm_pdf_new_pixmap_from_page_contents_with_usage(this.pointer,
2820 MATRIX(matrix),
2821 colorspace.pointer,
2822 alpha,
2823 STRING(usage),
2824 box_ix)
2825 return new Pixmap(result)
2826 }
2827
2828 getWidgets() {
2829 if (!this._widgets) {
2830 this._widgets = []
2831 let widget = libmupdf._wasm_pdf_first_widget(this.pointer)
2832 while (widget) {
2833 this._widgets.push(new PDFWidget(this._doc, libmupdf._wasm_pdf_keep_annot(widget)))
2834 widget = libmupdf._wasm_pdf_next_widget(widget)
2835 }
2836 }
2837 return this._widgets
2838 }
2839
2840 getAnnotations() {
2841 if (!this._annots) {
2842 this._annots = []
2843 let annot = libmupdf._wasm_pdf_first_annot(this.pointer)
2844 while (annot) {
2845 this._annots.push(new PDFAnnotation(this._doc, libmupdf._wasm_pdf_keep_annot(annot)))
2846 annot = libmupdf._wasm_pdf_next_annot(annot)
2847 }
2848 }
2849 return this._annots
2850 }
2851
2852 createAnnotation(type: PDFAnnotationType) {
2853 let type_ix = ENUM<PDFAnnotationType>(type, PDFAnnotation.ANNOT_TYPES)
2854 let annot = new PDFAnnotation(this._doc, libmupdf._wasm_pdf_create_annot(this.pointer, type_ix))
2855 if (this._annots)
2856 this._annots.push(annot)
2857 return annot
2858 }
2859
2860 deleteAnnotation(annot: PDFAnnotation) {
2861 checkType(annot, PDFAnnotation)
2862 libmupdf._wasm_pdf_delete_annot(this.pointer, annot.pointer)
2863 if (this._annots) {
2864 let ix = this._annots.indexOf(annot)
2865 if (ix >= 0)
2866 this._annots.splice(ix, 1)
2867 }
2868 }
2869
2870 static readonly REDACT_IMAGE_NONE = 0
2871 static readonly REDACT_IMAGE_REMOVE = 1
2872 static readonly REDACT_IMAGE_PIXELS = 2
2873 static readonly REDACT_IMAGE_UNLESS_INVISIBLE = 3
2874
2875 static readonly REDACT_LINE_ART_NONE = 0
2876 static readonly REDACT_LINE_ART_REMOVE_IF_COVERED = 1
2877 static readonly REDACT_LINE_ART_REMOVE_IF_TOUCHED = 2
2878
2879 static readonly REDACT_TEXT_REMOVE = 0
2880 static readonly REDACT_TEXT_NONE = 1
2881
2882 applyRedactions(black_boxes = true, image_method = 2, line_art_method = 1, text_method = 0) {
2883 libmupdf._wasm_pdf_redact_page(this.pointer, Number(black_boxes), image_method, line_art_method, text_method)
2884 }
2885
2886 update() {
2887 return !!libmupdf._wasm_pdf_update_page(this.pointer)
2888 }
2889 }
2890
2891 type PDFObjectPath = Array<number | string | PDFObject>
2892
2893 export class PDFObject extends Userdata<"pdf_obj"> {
2894 static override readonly _drop = libmupdf._wasm_pdf_drop_obj
2895
2896 static readonly Null = new PDFObject(null as unknown as PDFDocument, 0 as Pointer<"pdf_obj">)
2897
2898 _doc: PDFDocument
2899
2900 // PRIVATE
2901 constructor(doc: PDFDocument, pointer: Pointer<"pdf_obj">) {
2902 super(libmupdf._wasm_pdf_keep_obj(pointer))
2903 this._doc = doc
2904 }
2905
2906 isNull() { return this === PDFObject.Null }
2907 isIndirect() { return !!libmupdf._wasm_pdf_is_indirect(this.pointer) }
2908 isBoolean() { return !!libmupdf._wasm_pdf_is_bool(this.pointer) }
2909 isInteger() { return !!libmupdf._wasm_pdf_is_int(this.pointer) }
2910 isReal() { return !!libmupdf._wasm_pdf_is_real(this.pointer) }
2911 isNumber() { return !!libmupdf._wasm_pdf_is_number(this.pointer) }
2912 isName() { return !!libmupdf._wasm_pdf_is_name(this.pointer) }
2913 isString() { return !!libmupdf._wasm_pdf_is_string(this.pointer) }
2914 isArray() { return !!libmupdf._wasm_pdf_is_array(this.pointer) }
2915 isDictionary() { return !!libmupdf._wasm_pdf_is_dict(this.pointer) }
2916 isStream() { return !!libmupdf._wasm_pdf_is_stream(this.pointer) }
2917
2918 asIndirect(): number { return libmupdf._wasm_pdf_to_num(this.pointer) }
2919 asBoolean() { return !!libmupdf._wasm_pdf_to_bool(this.pointer) }
2920 asNumber(): number { return libmupdf._wasm_pdf_to_real(this.pointer) }
2921 asName() { return fromString(libmupdf._wasm_pdf_to_name(this.pointer)) }
2922 asString() { return fromString(libmupdf._wasm_pdf_to_text_string(this.pointer)) }
2923
2924 asByteString() {
2925 let ptr = libmupdf._wasm_pdf_to_string(this.pointer, _wasm_int)
2926 let len = libmupdf.HEAPU32[_wasm_int >> 2] as number
2927 return libmupdf.HEAPU8.slice(ptr, ptr + len)
2928 }
2929
2930 readStream() { return new Buffer(libmupdf._wasm_pdf_load_stream(this.pointer)) }
2931 readRawStream() { return new Buffer(libmupdf._wasm_pdf_load_raw_stream(this.pointer)) }
2932
2933 writeObject(obj: any) {
2934 if (!this.isIndirect())
2935 throw new TypeError("can only call PDFObject.writeObject on an indirect reference")
2936 libmupdf._wasm_pdf_update_object(this._doc.pointer, this.asIndirect(), this._doc._PDFOBJ(obj))
2937 }
2938
2939 writeStream(buf: AnyBuffer) {
2940 if (!this.isIndirect())
2941 throw new TypeError("can only call PDFObject.writeStream on an indirect reference")
2942 libmupdf._wasm_pdf_update_stream(this._doc.pointer, this.pointer, BUFFER(buf), 0)
2943 }
2944
2945 writeRawStream(buf: AnyBuffer) {
2946 if (!this.isIndirect())
2947 throw new TypeError("can only call PDFObject.writeRawStream on an indirect reference")
2948 libmupdf._wasm_pdf_update_stream(this._doc.pointer, this.pointer, BUFFER(buf), 1)
2949 }
2950
2951 resolve() {
2952 return this._doc._fromPDFObjectKeep(libmupdf._wasm_pdf_resolve_indirect(this.pointer))
2953 }
2954
2955 get length() {
2956 return libmupdf._wasm_pdf_array_len(this.pointer)
2957 }
2958
2959 set length(_: number) {
2960 throw new TypeError("object length is read-only")
2961 }
2962
2963 _get(path: PDFObjectPath) {
2964 let obj = this.pointer
2965 for (let key of path) {
2966 if (typeof key === "number")
2967 obj = libmupdf._wasm_pdf_array_get(obj, key)
2968 else if (key instanceof PDFObject)
2969 obj = libmupdf._wasm_pdf_dict_get(obj, key.pointer)
2970 else
2971 obj = libmupdf._wasm_pdf_dict_gets(obj, STRING(key))
2972 if (obj === 0)
2973 break
2974 }
2975 return obj
2976 }
2977
2978 get(...path: PDFObjectPath): PDFObject {
2979 return this._doc._fromPDFObjectKeep(this._get(path))
2980 }
2981
2982 getInheritable(key: string | PDFObject) {
2983 if (key instanceof PDFObject)
2984 return this._doc._fromPDFObjectKeep(libmupdf._wasm_pdf_dict_get_inheritable(this.pointer, key.pointer))
2985 return this._doc._fromPDFObjectKeep(libmupdf._wasm_pdf_dict_gets_inheritable(this.pointer, STRING(key)))
2986 }
2987
2988 put(key: number | string | PDFObject, value: any) {
2989 value = this._doc._toPDFObject(value)
2990 if (typeof key === "number")
2991 libmupdf._wasm_pdf_array_put(this.pointer, key, value.pointer)
2992 else if (key instanceof PDFObject)
2993 libmupdf._wasm_pdf_dict_put(this.pointer, key.pointer, value.pointer)
2994 else
2995 libmupdf._wasm_pdf_dict_puts(this.pointer, STRING(key), value.pointer)
2996 return value
2997 }
2998
2999 push(value: any) {
3000 value = this._doc._toPDFObject(value)
3001 libmupdf._wasm_pdf_array_push(this.pointer, value.pointer)
3002 return value
3003 }
3004
3005 delete(key: number | string | PDFObject) {
3006 if (typeof key === "number")
3007 libmupdf._wasm_pdf_array_delete(this.pointer, key)
3008 else if (key instanceof PDFObject)
3009 libmupdf._wasm_pdf_dict_del(this.pointer, key.pointer)
3010 else
3011 libmupdf._wasm_pdf_dict_dels(this.pointer, STRING(key))
3012 }
3013
3014 override valueOf() {
3015 if (this.isNull()) return null
3016 if (this.isBoolean()) return this.asBoolean()
3017 if (this.isNumber()) return this.asNumber()
3018 if (this.isName()) return this.asName()
3019 if (this.isString()) return this.asString()
3020 if (this.isIndirect()) return `${this.asIndirect()} 0 R`
3021 return this
3022 }
3023
3024 override toString(tight = true, ascii = true) {
3025 return fromStringFree(libmupdf._wasm_pdf_sprint_obj(this.pointer, tight, ascii))
3026 }
3027
3028 forEach(fn: (val: PDFObject, key: number | string, self: PDFObject) => void) {
3029 if (this.isArray()) {
3030 let n = this.length
3031 for (let i = 0; i < n; ++i)
3032 fn(this.get(i), i, this)
3033 } else if (this.isDictionary()) {
3034 let n = libmupdf._wasm_pdf_dict_len(this.pointer)
3035 for (let i = 0; i < n; ++i) {
3036 let key = this._doc._fromPDFObjectKeep(libmupdf._wasm_pdf_dict_get_key(this.pointer, i))
3037 let val = this._doc._fromPDFObjectKeep(libmupdf._wasm_pdf_dict_get_val(this.pointer, i))
3038 fn(val, key.asName(), this)
3039 }
3040 }
3041 }
3042
3043 // Convert to plain Javascript values, objects, and arrays.
3044 // If you want to resolve indirect references, pass an empty object or array as the first argument.
3045 // On exit, this object will contain all indirect objects encountered indexed by object number.
3046 // Note: This function will omit cyclic references.
3047 asJS(seen?: Record<number,PDFObject>): any {
3048 if (this.isIndirect()) {
3049 let ref = this.asIndirect()
3050 if (!seen)
3051 return `${ref} 0 R`
3052 if (ref in seen)
3053 return seen[ref]
3054 seen[ref] = PDFObject.Null // stop recursion!
3055 return seen[ref] = this.resolve().asJS(seen)
3056 }
3057
3058 if (this.isArray()) {
3059 let result: any[] = []
3060 this.forEach(val => {
3061 result.push(val.asJS(seen))
3062 })
3063 return result
3064 }
3065
3066 if (this.isDictionary()) {
3067 let result: Record<string,any> = {}
3068 this.forEach((val, key) => {
3069 result[key] = val.asJS(seen)
3070 })
3071 return result
3072 }
3073
3074 return this.valueOf()
3075 }
3076 }
3077
3078 export class PDFGraftMap extends Userdata<"pdf_graft_map"> {
3079 static override readonly _drop = libmupdf._wasm_pdf_drop_graft_map
3080
3081 _doc: PDFDocument
3082
3083 // PRIVATE
3084 constructor(doc: PDFDocument, pointer: Pointer<"pdf_graft_map">) {
3085 super(pointer)
3086 this._doc = doc
3087 }
3088
3089 graftObject(obj: PDFObject) {
3090 checkType(obj, PDFObject)
3091 return this._doc._fromPDFObjectNew(libmupdf._wasm_pdf_graft_mapped_object(this.pointer, obj.pointer))
3092 }
3093
3094 graftPage(to: number, srcDoc: PDFDocument, srcPage: number) {
3095 checkType(to, "number")
3096 checkType(srcDoc, PDFDocument)
3097 checkType(srcPage, "number")
3098 libmupdf._wasm_pdf_graft_mapped_page(this.pointer, to, srcDoc.pointer, srcPage)
3099 }
3100 }
3101
3102 export type PDFAnnotationType =
3103 "Text" |
3104 "Link" |
3105 "FreeText" |
3106 "Line" |
3107 "Square" |
3108 "Circle" |
3109 "Polygon" |
3110 "PolyLine" |
3111 "Highlight" |
3112 "Underline" |
3113 "Squiggly" |
3114 "StrikeOut" |
3115 "Redact" |
3116 "Stamp" |
3117 "Caret" |
3118 "Ink" |
3119 "Popup" |
3120 "FileAttachment" |
3121 "Sound" |
3122 "Movie" |
3123 "RichMedia" |
3124 "Widget" |
3125 "Screen" |
3126 "PrinterMark" |
3127 "TrapNet" |
3128 "Watermark" |
3129 "3D" |
3130 "Projection"
3131
3132 export type PDFAnnotationLineEndingStyle =
3133 "None" |
3134 "Square" |
3135 "Circle" |
3136 "Diamond" |
3137 "OpenArrow" |
3138 "ClosedArrow" |
3139 "Butt" |
3140 "ROpenArrow" |
3141 "RClosedArrow" |
3142 "Slash"
3143
3144 export type PDFAnnotationBorderStyle = "Solid" | "Dashed" | "Beveled" | "Inset" | "Underline"
3145
3146 export type PDFAnnotationBorderEffect = "None" | "Cloudy"
3147
3148 export type PDFAnnotationIntent =
3149 null |
3150 "FreeTextCallout" |
3151 "FreeTextTypeWriter" |
3152 "LineArrow" |
3153 "LineDimension" |
3154 "PloyLine" |
3155 "PolygonCloud" |
3156 "PolygonDimension" |
3157 "StampImage" |
3158 "StampSnapshot"
3159
3160 export class PDFAnnotation extends Userdata<"pdf_annot"> {
3161 static override readonly _drop = libmupdf._wasm_pdf_drop_annot
3162
3163 _doc: PDFDocument
3164
3165 /* IMPORTANT: Keep in sync with mupdf/pdf/annot.h and PDFAnnotation.java */
3166 static readonly ANNOT_TYPES: PDFAnnotationType[] = [
3167 "Text",
3168 "Link",
3169 "FreeText",
3170 "Line",
3171 "Square",
3172 "Circle",
3173 "Polygon",
3174 "PolyLine",
3175 "Highlight",
3176 "Underline",
3177 "Squiggly",
3178 "StrikeOut",
3179 "Redact",
3180 "Stamp",
3181 "Caret",
3182 "Ink",
3183 "Popup",
3184 "FileAttachment",
3185 "Sound",
3186 "Movie",
3187 "RichMedia",
3188 "Widget",
3189 "Screen",
3190 "PrinterMark",
3191 "TrapNet",
3192 "Watermark",
3193 "3D",
3194 "Projection",
3195 ]
3196
3197 static readonly LINE_ENDING: PDFAnnotationLineEndingStyle[] = [
3198 "None",
3199 "Square",
3200 "Circle",
3201 "Diamond",
3202 "OpenArrow",
3203 "ClosedArrow",
3204 "Butt",
3205 "ROpenArrow",
3206 "RClosedArrow",
3207 "Slash",
3208 ]
3209
3210 static readonly BORDER_STYLE: PDFAnnotationBorderStyle[] = [ "Solid", "Dashed", "Beveled", "Inset", "Underline" ]
3211
3212 static readonly BORDER_EFFECT: PDFAnnotationBorderEffect[] = [ "None", "Cloudy" ]
3213
3214 static readonly INTENT: PDFAnnotationIntent[] = [
3215 null,
3216 "FreeTextCallout",
3217 "FreeTextTypeWriter",
3218 "LineArrow",
3219 "LineDimension",
3220 "PloyLine",
3221 "PolygonCloud",
3222 "PolygonDimension",
3223 "StampImage",
3224 "StampSnapshot"
3225 ]
3226
3227 // Bit masks for getFlags and setFlags
3228 static readonly IS_INVISIBLE = 1 << (1 - 1)
3229 static readonly IS_HIDDEN = 1 << (2 - 1)
3230 static readonly IS_PRINT = 1 << (3 - 1)
3231 static readonly IS_NO_ZOOM = 1 << (4 - 1)
3232 static readonly IS_NO_ROTATE = 1 << (5 - 1)
3233 static readonly IS_NO_VIEW = 1 << (6 - 1)
3234 static readonly IS_READ_ONLY = 1 << (7 - 1)
3235 static readonly IS_LOCKED = 1 << (8 - 1)
3236 static readonly IS_TOGGLE_NO_VIEW = 1 << (9 - 1)
3237 static readonly IS_LOCKED_CONTENTS = 1 << (10 - 1)
3238
3239 // PRIVATE
3240 constructor(doc: PDFDocument, pointer: Pointer<"pdf_annot">) {
3241 super(pointer)
3242 this._doc = doc
3243 }
3244
3245 getObject() {
3246 return this._doc._fromPDFObjectKeep(libmupdf._wasm_pdf_annot_obj(this.pointer))
3247 }
3248
3249 getBounds() {
3250 return fromRect(libmupdf._wasm_pdf_bound_annot(this.pointer))
3251 }
3252
3253 run(device: Device, matrix: Matrix) {
3254 checkType(device, Device)
3255 checkMatrix(matrix)
3256 libmupdf._wasm_pdf_run_annot(this.pointer, device.pointer, MATRIX(matrix))
3257 }
3258
3259 toPixmap(matrix: Matrix, colorspace: ColorSpace, alpha = false) {
3260 checkMatrix(matrix)
3261 checkType(colorspace, ColorSpace)
3262 return new Pixmap(
3263 libmupdf._wasm_pdf_new_pixmap_from_annot(
3264 this.pointer,
3265 MATRIX(matrix),
3266 colorspace.pointer,
3267 alpha)
3268 )
3269 }
3270
3271 toDisplayList() {
3272 return new DisplayList(libmupdf._wasm_pdf_new_display_list_from_annot(this.pointer))
3273 }
3274
3275 update() {
3276 return !!libmupdf._wasm_pdf_update_annot(this.pointer)
3277 }
3278
3279 getType() {
3280 let type = libmupdf._wasm_pdf_annot_type(this.pointer)
3281 return PDFAnnotation.ANNOT_TYPES[type] || "Text"
3282 }
3283
3284 getLanguage() {
3285 return fromStringOrNull(libmupdf._wasm_pdf_annot_language(this.pointer))
3286 }
3287
3288 setLanguage(lang: string) {
3289 libmupdf._wasm_pdf_set_annot_language(this.pointer, STRING(lang))
3290 }
3291
3292 getFlags() {
3293 return libmupdf._wasm_pdf_annot_flags(this.pointer)
3294 }
3295
3296 setFlags(flags: number) {
3297 return libmupdf._wasm_pdf_set_annot_flags(this.pointer, flags)
3298 }
3299
3300 getContents() {
3301 return fromString(libmupdf._wasm_pdf_annot_contents(this.pointer))
3302 }
3303
3304 setContents(text: string) {
3305 libmupdf._wasm_pdf_set_annot_contents(this.pointer, STRING(text))
3306 }
3307
3308 getAuthor() {
3309 return fromString(libmupdf._wasm_pdf_annot_author(this.pointer))
3310 }
3311
3312 setAuthor(text: string) {
3313 libmupdf._wasm_pdf_set_annot_author(this.pointer, STRING(text))
3314 }
3315
3316 getCreationDate() {
3317 return new Date(libmupdf._wasm_pdf_annot_creation_date(this.pointer) * 1000)
3318 }
3319
3320 setCreationDate(date: Date) {
3321 checkType(date, Date)
3322 libmupdf._wasm_pdf_set_annot_creation_date(this.pointer, date.getTime() / 1000)
3323 }
3324
3325 getModificationDate() {
3326 return new Date(libmupdf._wasm_pdf_annot_modification_date(this.pointer) * 1000)
3327 }
3328
3329 setModificationDate(date: Date) {
3330 checkType(date, Date)
3331 libmupdf._wasm_pdf_set_annot_modification_date(this.pointer, date.getTime() / 1000)
3332 }
3333
3334 hasRect() {
3335 return !!libmupdf._wasm_pdf_annot_has_rect(this.pointer)
3336 }
3337 hasInkList() {
3338 return !!libmupdf._wasm_pdf_annot_has_ink_list(this.pointer)
3339 }
3340 hasQuadPoints() {
3341 return !!libmupdf._wasm_pdf_annot_has_quad_points(this.pointer)
3342 }
3343 hasVertices() {
3344 return !!libmupdf._wasm_pdf_annot_has_vertices(this.pointer)
3345 }
3346 hasLine() {
3347 return !!libmupdf._wasm_pdf_annot_has_line(this.pointer)
3348 }
3349 hasInteriorColor() {
3350 return !!libmupdf._wasm_pdf_annot_has_interior_color(this.pointer)
3351 }
3352 hasLineEndingStyles() {
3353 return !!libmupdf._wasm_pdf_annot_has_line_ending_styles(this.pointer)
3354 }
3355 hasBorder() {
3356 return !!libmupdf._wasm_pdf_annot_has_border(this.pointer)
3357 }
3358 hasBorderEffect() {
3359 return !!libmupdf._wasm_pdf_annot_has_border_effect(this.pointer)
3360 }
3361 hasIcon() {
3362 return !!libmupdf._wasm_pdf_annot_has_icon_name(this.pointer)
3363 }
3364 hasOpen() {
3365 return !!libmupdf._wasm_pdf_annot_has_open(this.pointer)
3366 }
3367 hasAuthor() {
3368 return !!libmupdf._wasm_pdf_annot_has_author(this.pointer)
3369 }
3370 hasFilespec() {
3371 return !!libmupdf._wasm_pdf_annot_has_filespec(this.pointer)
3372 }
3373 hasCallout() {
3374 return !!libmupdf._wasm_pdf_annot_has_callout(this.pointer)
3375 }
3376 hasRichContents() {
3377 return !!libmupdf._wasm_pdf_annot_has_rich_contents(this.pointer)
3378 }
3379
3380 getRect() {
3381 return fromRect(libmupdf._wasm_pdf_annot_rect(this.pointer))
3382 }
3383
3384 setRect(rect: Rect) {
3385 checkRect(rect)
3386 libmupdf._wasm_pdf_set_annot_rect(this.pointer, RECT(rect))
3387 }
3388
3389 getPopup() {
3390 return fromRect(libmupdf._wasm_pdf_annot_popup(this.pointer))
3391 }
3392
3393 setPopup(rect: Rect) {
3394 checkRect(rect)
3395 libmupdf._wasm_pdf_set_annot_popup(this.pointer, RECT(rect))
3396 }
3397
3398 getIsOpen() {
3399 return !!libmupdf._wasm_pdf_annot_is_open(this.pointer)
3400 }
3401
3402 setIsOpen(isOpen: boolean) {
3403 checkType(isOpen, "boolean")
3404 libmupdf._wasm_pdf_set_annot_is_open(this.pointer, isOpen)
3405 }
3406
3407 getHiddenForEditing() {
3408 return !!libmupdf._wasm_pdf_annot_hidden_for_editing(this.pointer)
3409 }
3410
3411 setHiddenForEditing(isHidden: boolean) {
3412 checkType(isHidden, "boolean")
3413 libmupdf._wasm_pdf_set_annot_hidden_for_editing(this.pointer, isHidden)
3414 }
3415
3416 getIcon() {
3417 return fromString(libmupdf._wasm_pdf_annot_icon_name(this.pointer))
3418 }
3419
3420 setIcon(text: string) {
3421 checkType(text, "string")
3422 libmupdf._wasm_pdf_set_annot_icon_name(this.pointer, STRING(text))
3423 }
3424
3425 getOpacity() {
3426 return libmupdf._wasm_pdf_annot_opacity(this.pointer)
3427 }
3428
3429 setOpacity(opacity: number) {
3430 checkType(opacity, "number")
3431 libmupdf._wasm_pdf_set_annot_opacity(this.pointer, opacity)
3432 }
3433
3434 getQuadding() {
3435 return libmupdf._wasm_pdf_annot_quadding(this.pointer)
3436 }
3437
3438 setQuadding(quadding: number) {
3439 checkType(quadding, "number")
3440 libmupdf._wasm_pdf_set_annot_quadding(this.pointer, quadding)
3441 }
3442
3443 getLine() {
3444 let a = fromPoint(libmupdf._wasm_pdf_annot_line_1(this.pointer))
3445 let b = fromPoint(libmupdf._wasm_pdf_annot_line_2(this.pointer))
3446 return [ a, b ]
3447 }
3448
3449 setLine(a: Point, b: Point) {
3450 checkPoint(a)
3451 checkPoint(b)
3452 libmupdf._wasm_pdf_set_annot_line(this.pointer, POINT(a), POINT2(b))
3453 }
3454
3455 getLineEndingStyles() {
3456 let a = libmupdf._wasm_pdf_annot_line_ending_styles_start(this.pointer)
3457 let b = libmupdf._wasm_pdf_annot_line_ending_styles_end(this.pointer)
3458 return {
3459 start: PDFAnnotation.LINE_ENDING[a] || "None",
3460 end: PDFAnnotation.LINE_ENDING[b] || "None",
3461 }
3462 }
3463
3464 setLineEndingStyles(start: PDFAnnotationLineEndingStyle, end: PDFAnnotationLineEndingStyle) {
3465 let start_ix = ENUM<PDFAnnotationLineEndingStyle>(start, PDFAnnotation.LINE_ENDING)
3466 let end_ix = ENUM<PDFAnnotationLineEndingStyle>(end, PDFAnnotation.LINE_ENDING)
3467 libmupdf._wasm_pdf_set_annot_line_ending_styles(this.pointer, start_ix, end_ix)
3468 }
3469
3470 getLineCaption() {
3471 return libmupdf._wasm_pdf_annot_line_caption(this.pointer)
3472 }
3473
3474 setLineCaption(on: boolean) {
3475 return libmupdf._wasm_pdf_set_annot_line_caption(this.pointer, on)
3476 }
3477
3478 getLineCaptionOffset() {
3479 return fromPoint(libmupdf._wasm_pdf_annot_line_caption_offset(this.pointer))
3480 }
3481
3482 setLineCaptionOffset(p: Point) {
3483 return libmupdf._wasm_pdf_set_annot_line_caption_offset(this.pointer, POINT(p))
3484 }
3485
3486 getLineLeader() {
3487 return libmupdf._wasm_pdf_annot_line_leader(this.pointer)
3488 }
3489
3490 getLineLeaderExtension() {
3491 return libmupdf._wasm_pdf_annot_line_leader_extension(this.pointer)
3492 }
3493
3494 getLineLeaderOffset() {
3495 return libmupdf._wasm_pdf_annot_line_leader_offset(this.pointer)
3496 }
3497
3498 setLineLeader(v: number) {
3499 return libmupdf._wasm_pdf_set_annot_line_leader(this.pointer, v)
3500 }
3501
3502 setLineLeaderExtension(v: number) {
3503 return libmupdf._wasm_pdf_set_annot_line_leader_extension(this.pointer, v)
3504 }
3505
3506 setLineLeaderOffset(v: number) {
3507 return libmupdf._wasm_pdf_set_annot_line_leader_offset(this.pointer, v)
3508 }
3509
3510 getCalloutStyle() {
3511 let style = libmupdf._wasm_pdf_annot_callout_style(this.pointer)
3512 return PDFAnnotation.LINE_ENDING[style] || "None"
3513 }
3514
3515 setCalloutStyle(style: PDFAnnotationLineEndingStyle) {
3516 let style_ix = ENUM<PDFAnnotationLineEndingStyle>(style, PDFAnnotation.LINE_ENDING)
3517 libmupdf._wasm_pdf_set_annot_callout_style(this.pointer, style_ix)
3518 }
3519
3520 getCalloutLine() {
3521 let n = libmupdf._wasm_pdf_annot_callout_line(this.pointer,
3522 (_wasm_point << 2) as Pointer<"fz_point">)
3523 if (n == 3)
3524 return [
3525 fromPoint((_wasm_point+0) << 2 as Pointer<"fz_point">),
3526 fromPoint((_wasm_point+1) << 2 as Pointer<"fz_point">),
3527 fromPoint((_wasm_point+2) << 2 as Pointer<"fz_point">)
3528 ]
3529 if (n == 2)
3530 return [
3531 fromPoint((_wasm_point+0) << 2 as Pointer<"fz_point">),
3532 fromPoint((_wasm_point+1) << 2 as Pointer<"fz_point">)
3533 ]
3534 return null
3535 }
3536
3537 setCalloutLine(line: Point[]) {
3538 let a = line[0] || [0, 0]
3539 let b = line[1] || [0, 0]
3540 let c = line[2] || [0, 0]
3541 libmupdf._wasm_pdf_set_annot_callout_line(this.pointer, line.length, POINT(a), POINT2(b), POINT3(c))
3542 }
3543
3544 getCalloutPoint() {
3545 let line = this.getCalloutLine()
3546 if (line)
3547 return line[0]
3548 return undefined
3549 }
3550
3551 setCalloutPoint(p: Point) {
3552 libmupdf._wasm_pdf_set_annot_callout_point(this.pointer, POINT(p))
3553 }
3554
3555 getColor() {
3556 return fromAnnotColor(libmupdf._wasm_pdf_annot_color(this.pointer, COLOR()))
3557 }
3558
3559 getInteriorColor() {
3560 return fromAnnotColor(libmupdf._wasm_pdf_annot_interior_color(this.pointer, COLOR()))
3561 }
3562
3563 setColor(color: AnnotColor) {
3564 checkAnnotColor(color)
3565 libmupdf._wasm_pdf_set_annot_color(this.pointer, color.length, COLOR(color))
3566 }
3567
3568 setInteriorColor(color: AnnotColor) {
3569 checkAnnotColor(color)
3570 libmupdf._wasm_pdf_set_annot_interior_color(this.pointer, color.length, COLOR(color))
3571 }
3572
3573 getBorderWidth() {
3574 return libmupdf._wasm_pdf_annot_border_width(this.pointer)
3575 }
3576
3577 setBorderWidth(value: number) {
3578 checkType(value, "number")
3579 return libmupdf._wasm_pdf_set_annot_border_width(this.pointer, value)
3580 }
3581
3582 getBorderStyle() {
3583 return PDFAnnotation.BORDER_STYLE[libmupdf._wasm_pdf_annot_border_style(this.pointer)] || "Solid"
3584 }
3585
3586 setBorderStyle(value: PDFAnnotationBorderStyle) {
3587 let value_ix = ENUM<PDFAnnotationBorderStyle>(value, PDFAnnotation.BORDER_STYLE)
3588 return libmupdf._wasm_pdf_set_annot_border_style(this.pointer, value_ix)
3589 }
3590
3591 getBorderEffect() {
3592 return PDFAnnotation.BORDER_EFFECT[libmupdf._wasm_pdf_annot_border_effect(this.pointer)] || "None"
3593 }
3594
3595 setBorderEffect(value: PDFAnnotationBorderEffect) {
3596 let value_ix = ENUM<PDFAnnotationBorderEffect>(value, PDFAnnotation.BORDER_EFFECT)
3597 return libmupdf._wasm_pdf_set_annot_border_effect(this.pointer, value_ix)
3598 }
3599
3600 getBorderEffectIntensity() {
3601 return libmupdf._wasm_pdf_annot_border_effect_intensity(this.pointer)
3602 }
3603
3604 setBorderEffectIntensity(value: number) {
3605 checkType(value, "number")
3606 return libmupdf._wasm_pdf_set_annot_border_effect_intensity(this.pointer, value)
3607 }
3608
3609 getBorderDashCount() {
3610 return libmupdf._wasm_pdf_annot_border_dash_count(this.pointer)
3611 }
3612
3613 getBorderDashItem(idx: number) {
3614 return libmupdf._wasm_pdf_annot_border_dash_item(this.pointer, idx)
3615 }
3616
3617 clearBorderDash() {
3618 libmupdf._wasm_pdf_clear_annot_border_dash(this.pointer)
3619 }
3620
3621 addBorderDashItem(v: number) {
3622 checkType(v, "number")
3623 return libmupdf._wasm_pdf_add_annot_border_dash_item(this.pointer, v)
3624 }
3625
3626 getBorderDashPattern() {
3627 let n = this.getBorderDashCount()
3628 let result = new Array(n)
3629 for (let i = 0; i < n; ++i)
3630 result[i] = this.getBorderDashItem(i)
3631 return result
3632 }
3633
3634 setBorderDashPattern(list: number[]) {
3635 this.clearBorderDash()
3636 for (let v of list)
3637 this.addBorderDashItem(v)
3638 }
3639
3640 getIntent(): PDFAnnotationIntent {
3641 return PDFAnnotation.INTENT[libmupdf._wasm_pdf_annot_intent(this.pointer)] || null
3642 }
3643
3644 setIntent(value: PDFAnnotationIntent) {
3645 let value_ix = ENUM<PDFAnnotationIntent>(value, PDFAnnotation.INTENT)
3646 return libmupdf._wasm_pdf_set_annot_intent(this.pointer, value_ix)
3647 }
3648
3649 setDefaultAppearance(fontName: string, size: number, color: AnnotColor) {
3650 checkType(fontName, "string")
3651 checkType(size, "number")
3652 checkAnnotColor(color)
3653 libmupdf._wasm_pdf_set_annot_default_appearance(this.pointer, STRING(fontName), size, color.length, COLOR(color))
3654 }
3655
3656 getDefaultAppearance() {
3657 let font = fromString(libmupdf._wasm_pdf_annot_default_appearance_font(this.pointer))
3658 let size = libmupdf._wasm_pdf_annot_default_appearance_size(this.pointer)
3659 let color = fromAnnotColor(libmupdf._wasm_pdf_annot_default_appearance_color(this.pointer, COLOR()))
3660 return { font, size, color }
3661 }
3662
3663 getFileSpec() {
3664 return this._doc._fromPDFObjectKeep(libmupdf._wasm_pdf_annot_filespec(this.pointer))
3665 }
3666
3667 setFileSpec(fs: PDFObject) {
3668 return libmupdf._wasm_pdf_set_annot_filespec(this.pointer, this._doc._PDFOBJ(fs))
3669 }
3670
3671 getQuadPoints() {
3672 let n = libmupdf._wasm_pdf_annot_quad_point_count(this.pointer)
3673 let result: Quad[] = []
3674 for (let i = 0; i < n; ++i)
3675 result.push(fromQuad(libmupdf._wasm_pdf_annot_quad_point(this.pointer, i)))
3676 return result
3677 }
3678
3679 clearQuadPoints() {
3680 libmupdf._wasm_pdf_clear_annot_quad_points(this.pointer)
3681 }
3682
3683 addQuadPoint(quad: Quad) {
3684 checkQuad(quad)
3685 libmupdf._wasm_pdf_add_annot_quad_point(this.pointer, QUAD(quad))
3686 }
3687
3688 setQuadPoints(quadlist: Quad[]) {
3689 this.clearQuadPoints()
3690 for (let quad of quadlist)
3691 this.addQuadPoint(quad)
3692 }
3693
3694 getVertices() {
3695 let n = libmupdf._wasm_pdf_annot_vertex_count(this.pointer)
3696 let result: Point[] = new Array(n)
3697 for (let i = 0; i < n; ++i)
3698 result[i] = fromPoint(libmupdf._wasm_pdf_annot_vertex(this.pointer, i))
3699 return result
3700 }
3701
3702 clearVertices() {
3703 libmupdf._wasm_pdf_clear_annot_vertices(this.pointer)
3704 }
3705
3706 addVertex(vertex: Point) {
3707 checkPoint(vertex)
3708 libmupdf._wasm_pdf_add_annot_vertex(this.pointer, POINT(vertex))
3709 }
3710
3711 setVertices(vertexlist: Point[]) {
3712 this.clearVertices()
3713 for (let vertex of vertexlist)
3714 this.addVertex(vertex)
3715 }
3716
3717 getInkList() {
3718 let n = libmupdf._wasm_pdf_annot_ink_list_count(this.pointer)
3719 let outer: Point[][] = []
3720 for (let i = 0; i < n; ++i) {
3721 let m = libmupdf._wasm_pdf_annot_ink_list_stroke_count(this.pointer, i)
3722 let inner: Point[] = new Array(m)
3723 for (let k = 0; k < m; ++k)
3724 inner[k] = fromPoint(libmupdf._wasm_pdf_annot_ink_list_stroke_vertex(this.pointer, i, k))
3725 outer.push(inner)
3726 }
3727 return outer
3728 }
3729
3730 clearInkList() {
3731 libmupdf._wasm_pdf_clear_annot_ink_list(this.pointer)
3732 }
3733
3734 addInkListStroke() {
3735 libmupdf._wasm_pdf_add_annot_ink_list_stroke(this.pointer)
3736 }
3737
3738 addInkListStrokeVertex(v: Point) {
3739 checkPoint(v)
3740 libmupdf._wasm_pdf_add_annot_ink_list_stroke_vertex(this.pointer, POINT(v))
3741 }
3742
3743 setInkList(inklist: Point[][]) {
3744 this.clearInkList()
3745 for (let stroke of inklist) {
3746 this.addInkListStroke()
3747 for (let vertex of stroke)
3748 this.addInkListStrokeVertex(vertex)
3749 }
3750 }
3751
3752 getRichContents() {
3753 return fromString(libmupdf._wasm_pdf_annot_rich_contents(this.pointer))
3754 }
3755
3756 setRichContents(plain: string, html: string) {
3757 checkType(plain, "string")
3758 checkType(html, "string")
3759 libmupdf._wasm_pdf_set_annot_rich_contents(this.pointer, STRING(plain), STRING2(html))
3760 }
3761
3762 getRichDefaults() {
3763 return fromString(libmupdf._wasm_pdf_annot_rich_defaults(this.pointer))
3764 }
3765
3766 setRichDefaults(style: string) {
3767 checkType(style, "string")
3768 libmupdf._wasm_pdf_set_annot_rich_defaults(this.pointer, STRING(style))
3769 }
3770
3771 setStampImage(image: Image) {
3772 libmupdf._wasm_pdf_set_annot_stamp_image(this.pointer, image.pointer)
3773 }
3774
3775 setAppearanceFromDisplayList(appearance: string | null, state: string | null, transform: Matrix, list: DisplayList) {
3776 checkMatrix(transform)
3777 checkType(list, DisplayList)
3778 libmupdf._wasm_pdf_set_annot_appearance_from_display_list(
3779 this.pointer,
3780 STRING_OPT(appearance),
3781 STRING2_OPT(state),
3782 MATRIX(transform),
3783 list.pointer
3784 )
3785 }
3786
3787 setAppearance(appearance: string | null, state: string | null, transform: Matrix, bbox: Rect, resources: any, contents: AnyBuffer) {
3788 checkMatrix(transform)
3789 checkRect(bbox)
3790 libmupdf._wasm_pdf_set_annot_appearance(
3791 this.pointer,
3792 STRING_OPT(appearance),
3793 STRING2_OPT(state),
3794 MATRIX(transform),
3795 RECT(bbox),
3796 this._doc._PDFOBJ(resources),
3797 BUFFER(contents)
3798 )
3799 }
3800
3801 applyRedaction(black_boxes = 1, image_method = 2, line_art_method = 1, text_method = 0) {
3802 libmupdf._wasm_pdf_apply_redaction(this.pointer, black_boxes, image_method, line_art_method, text_method)
3803 }
3804 }
3805
3806 export class PDFWidget extends PDFAnnotation {
3807 /* IMPORTANT: Keep in sync with mupdf/pdf/widget.h and PDFWidget.java */
3808 static readonly WIDGET_TYPES = [
3809 "widget", // unknown
3810 "button",
3811 "checkbox",
3812 "combobox",
3813 "listbox",
3814 "radiobutton",
3815 "signature",
3816 "text",
3817 ]
3818
3819 /* Field flags */
3820 static readonly FIELD_IS_READ_ONLY = 1
3821 static readonly FIELD_IS_REQUIRED = 1 << 1
3822 static readonly FIELD_IS_NO_EXPORT = 1 << 2
3823
3824 /* Text fields */
3825 static readonly TX_FIELD_IS_MULTILINE = 1 << 12
3826 static readonly TX_FIELD_IS_PASSWORD = 1 << 13
3827 static readonly TX_FIELD_IS_COMB = 1 << 24
3828
3829 /* Button fields */
3830 static readonly BTN_FIELD_IS_NO_TOGGLE_TO_OFF = 1 << 14
3831 static readonly BTN_FIELD_IS_RADIO = 1 << 15
3832 static readonly BTN_FIELD_IS_PUSHBUTTON = 1 << 16
3833
3834 /* Choice fields */
3835 static readonly CH_FIELD_IS_COMBO = 1 << 17
3836 static readonly CH_FIELD_IS_EDIT = 1 << 18
3837 static readonly CH_FIELD_IS_SORT = 1 << 19
3838 static readonly CH_FIELD_IS_MULTI_SELECT = 1 << 21
3839
3840 getFieldType() {
3841 return PDFWidget.WIDGET_TYPES[libmupdf._wasm_pdf_annot_field_type(this.pointer)] || "button"
3842 }
3843
3844 isButton() {
3845 let type = this.getFieldType()
3846 return type === "button" || type === "checkbox" || type === "radiobutton"
3847 }
3848
3849 isPushButton() {
3850 return this.getFieldType() === "button"
3851 }
3852
3853 isCheckbox() {
3854 return this.getFieldType() === "checkbox"
3855 }
3856
3857 isRadioButton() {
3858 return this.getFieldType() === "radiobutton"
3859 }
3860
3861 isText() {
3862 return this.getFieldType() === "text"
3863 }
3864
3865 isChoice() {
3866 let type = this.getFieldType()
3867 return type === "combobox" || type === "listbox"
3868 }
3869
3870 isListBox() {
3871 return this.getFieldType() === "listbox"
3872 }
3873
3874 isComboBox() {
3875 return this.getFieldType() === "combobox"
3876 }
3877
3878 getFieldFlags() {
3879 return libmupdf._wasm_pdf_annot_field_flags(this.pointer)
3880 }
3881
3882 isMultiline() {
3883 return (this.getFieldFlags() & PDFWidget.TX_FIELD_IS_MULTILINE) !== 0
3884 }
3885
3886 isPassword() {
3887 return (this.getFieldFlags() & PDFWidget.TX_FIELD_IS_PASSWORD) !== 0
3888 }
3889
3890 isComb() {
3891 return (this.getFieldFlags() & PDFWidget.TX_FIELD_IS_COMB) !== 0
3892 }
3893
3894 isReadOnly() {
3895 return (this.getFieldFlags() & PDFWidget.FIELD_IS_READ_ONLY) !== 0
3896 }
3897
3898 getLabel() {
3899 return fromString(libmupdf._wasm_pdf_annot_field_label(this.pointer))
3900 }
3901
3902 getName() {
3903 return fromStringFree(libmupdf._wasm_pdf_load_field_name(this.pointer))
3904 }
3905
3906 getValue() {
3907 return fromString(libmupdf._wasm_pdf_annot_field_value(this.pointer))
3908 }
3909
3910 setTextValue(value: string) {
3911 return libmupdf._wasm_pdf_set_annot_text_field_value(this.pointer, STRING(value))
3912 }
3913
3914 getMaxLen() {
3915 return libmupdf._wasm_pdf_annot_text_widget_max_len(this.pointer)
3916 }
3917
3918 setChoiceValue(value: string) {
3919 return libmupdf._wasm_pdf_set_annot_choice_field_value(this.pointer, STRING(value))
3920 }
3921
3922 getOptions(isExport=false) {
3923 let result: string[] = []
3924 let n = libmupdf._wasm_pdf_annot_choice_field_option_count(this.pointer)
3925 for (let i = 0; i < n; ++i) {
3926 result.push(
3927 fromString(
3928 libmupdf._wasm_pdf_annot_choice_field_option(this.pointer, isExport, i)
3929 )
3930 )
3931 }
3932 return result
3933 }
3934
3935 toggle() {
3936 return libmupdf._wasm_pdf_toggle_widget(this.pointer)
3937 }
3938
3939 // Interactive Text Widget editing in a GUI.
3940 // TODO: getEditingState()
3941 // TODO: setEditingState()
3942 // TODO: clearEditingState()
3943 // TODO: layoutTextWidget()
3944
3945 // Interactive form validation Javascript triggers.
3946 // NOTE: No embedded PDF Javascript engine in WASM build.
3947 // TODO: eventEnter()
3948 // TODO: eventExit()
3949 // TODO: eventDown()
3950 // TODO: eventUp()
3951 // TODO: eventFocus()
3952 // TODO: eventBlur()
3953
3954 // NOTE: No OpenSSL support in WASM build.
3955 // TODO: isSigned()
3956 // TODO: validateSignature()
3957 // TODO: checkCertificate()
3958 // TODO: checkDigest()
3959 // TODO: getSignature()
3960 // TODO: previewSignature()
3961 // TODO: clearSignature()
3962 // TODO: sign()
3963 }
3964
3965 /* -------------------------------------------------------------------------- */
3966
3967 /* We need a certain level of ugliness to allow callbacks from C to JS */
3968
3969 declare global {
3970 function $libmupdf_stm_close(ptr: number): void
3971 function $libmupdf_stm_seek(ptr: number, pos: number, offset: number, whence: number): number
3972 function $libmupdf_stm_read(ptr: number, pos: number, addr: number, size: number): number
3973 }
3974
3975 interface StreamHandle {
3976 fileSize(): number,
3977 read(memory: Uint8Array, offset: number, length: number, position: number): number,
3978 close(): void,
3979 }
3980
3981 var $libmupdf_stm_id = 0
3982 var $libmupdf_stm_table: Map<number,StreamHandle> = new Map()
3983
3984 globalThis.$libmupdf_stm_close = function (id: number) {
3985 let handle = $libmupdf_stm_table.get(id)
3986 if (handle) {
3987 handle.close()
3988 $libmupdf_stm_table.delete(id)
3989 return
3990 }
3991 throw new Error("invalid file handle")
3992 }
3993
3994 globalThis.$libmupdf_stm_seek = function (id: number, pos: number, offset: number, whence: number) {
3995 let handle = $libmupdf_stm_table.get(id)
3996 if (handle) {
3997 if (whence === 0)
3998 return offset
3999 if (whence === 1)
4000 return pos + offset
4001 if (whence === 2) {
4002 let size = handle.fileSize()
4003 if (size < 0)
4004 return -1
4005 return size + offset
4006 }
4007 throw new Error("invalid whence argument")
4008 }
4009 throw new Error("invalid file handle")
4010 }
4011
4012 globalThis.$libmupdf_stm_read = function (id: number, pos: number, addr: number, size: number) {
4013 let handle = $libmupdf_stm_table.get(id)
4014 if (handle) {
4015 return handle.read(libmupdf.HEAPU8, addr, size, pos)
4016 }
4017 throw new Error("invalid file handle")
4018 }
4019
4020 export class Stream extends Userdata<"fz_stream"> {
4021 static override readonly _drop = libmupdf._wasm_drop_stream
4022 constructor(handle: StreamHandle) {
4023 let id = $libmupdf_stm_id++
4024 $libmupdf_stm_table.set(id, handle)
4025 super(libmupdf._wasm_new_stream(id))
4026 }
4027 }
4028
4029 /* -------------------------------------------------------------------------- */
4030
4031 var $libmupdf_load_font_file_js: (name: string, script: string, bold: boolean, italic: boolean) => Font | null
4032
4033 declare global {
4034 function $libmupdf_load_font_file(name: Pointer<"char">, script: Pointer<"char">, bold: boolean, italic: boolean): Pointer<"fz_font">
4035 }
4036
4037 globalThis.$libmupdf_load_font_file = function (name, script, bold, italic) {
4038 if ($libmupdf_load_font_file_js) {
4039 var font = $libmupdf_load_font_file_js(fromString(name), fromString(script), bold, italic)
4040 if (font) {
4041 checkType(font, Font)
4042 return font.pointer
4043 }
4044 }
4045 return 0 as Pointer<"fz_font">
4046 }
4047
4048 interface DeviceFunctions {
4049 drop?(): void,
4050 close?(): void,
4051
4052 fillPath?(path: Path, evenOdd: boolean, ctm: Matrix, colorspace: ColorSpace, color: number[], alpha: number): void,
4053 strokePath?(path: Path, stroke: StrokeState, ctm: Matrix, colorspace: ColorSpace, color: number[], alpha: number): void,
4054 clipPath?(path: Path, evenOdd: boolean, ctm: Matrix): void,
4055 clipStrokePath?(path: Path, stroke: StrokeState, ctm: Matrix): void,
4056
4057 fillText?(text: Text, ctm: Matrix, colorspace: ColorSpace, color: number[], alpha: number): void,
4058 strokeText?(text: Text, stroke: StrokeState, ctm: Matrix, colorspace: ColorSpace, color: number[], alpha: number): void,
4059 clipText?(text: Text, ctm: Matrix): void,
4060 clipStrokeText?(text: Text, stroke: StrokeState, ctm: Matrix): void,
4061 ignoreText?(text: Text, ctm: Matrix): void,
4062
4063 fillShade?(shade: Shade, ctm: Matrix, alpha: number): void,
4064
4065 fillImage?(image: Image, ctm: Matrix, alpha: number): void,
4066 fillImageMask?(image: Image, ctm: Matrix, colorspace: ColorSpace, color: number[], alpha: number): void,
4067 clipImageMask?(image: Image, ctm: Matrix): void,
4068
4069 popClip?(): void,
4070
4071 beginMask?(bbox: Rect, luminosity: boolean, colorspace: ColorSpace, color: number[]): void,
4072 endMask?(): void,
4073
4074 beginGroup?(bbox: Rect, colorspace: ColorSpace, isolated: boolean, knockout: boolean, blendmode: BlendMode, alpha: number): void,
4075 endGroup?(): void,
4076
4077 beginTile?(area: Rect, view: Rect, xstep: number, ystep: number, ctm: Matrix, id: number, doc_id: number): number,
4078 endTile?(): void,
4079
4080 beginLayer?(name: string): void,
4081 endLayer?(): void,
4082 }
4083
4084 var $libmupdf_device_id = 0
4085 var $libmupdf_device_table: Map<number,DeviceFunctions> = new Map()
4086
4087 var $libmupdf_path_id = 0
4088 var $libmupdf_path_table: Map<number,PathWalker> = new Map()
4089
4090 var $libmupdf_text_id = 0
4091 var $libmupdf_text_table: Map<number,TextWalker> = new Map()
4092
4093 declare global {
4094 var $libmupdf_path_walk: any
4095 var $libmupdf_text_walk: any
4096 var $libmupdf_device: any
4097 }
4098
4099 globalThis.$libmupdf_path_walk = {
4100 moveto(id: number, x: number, y: number): void {
4101 $libmupdf_path_table.get(id)?.moveTo?.(x, y)
4102 },
4103 lineto(id: number, x: number, y: number): void {
4104 $libmupdf_path_table.get(id)?.lineTo?.(x, y)
4105 },
4106 curveto(id: number, x1: number, y1: number, x2: number, y2: number, x3: number, y3: number): void {
4107 $libmupdf_path_table.get(id)?.curveTo?.(x1, y1, x2, y2, x3, y3)
4108 },
4109 closepath(id: number): void {
4110 $libmupdf_path_table.get(id)?.closePath?.()
4111 },
4112 }
4113
4114 var $libmupdf_text_font: Font | null = null
4115
4116 globalThis.$libmupdf_text_walk = {
4117 begin_span(
4118 id: number,
4119 font: Pointer<"fz_font">,
4120 trm: Pointer<"fz_matrix">,
4121 wmode: number,
4122 bidi: number,
4123 dir: number,
4124 lang: Pointer<"char">
4125 ): void {
4126 if (font !== $libmupdf_text_font?.pointer)
4127 $libmupdf_text_font = new Font(font)
4128 $libmupdf_text_table.get(id)?.beginSpan?.(
4129 $libmupdf_text_font,
4130 fromMatrix(trm),
4131 wmode,
4132 bidi,
4133 dir,
4134 fromString(lang)
4135 )
4136 },
4137 end_span(id: number): void {
4138 $libmupdf_text_table.get(id)?.endSpan?.()
4139 },
4140 show_glyph(
4141 id: number,
4142 font: Pointer<"fz_font">,
4143 trm: Pointer<"fz_matrix">,
4144 glyph: number,
4145 unicode: number,
4146 wmode: number,
4147 bidi: number
4148 ): void {
4149 if (font !== $libmupdf_text_font?.pointer)
4150 $libmupdf_text_font = new Font(font)
4151 $libmupdf_text_table.get(id)?.showGlyph?.(
4152 $libmupdf_text_font,
4153 fromMatrix(trm),
4154 glyph,
4155 unicode,
4156 wmode,
4157 bidi
4158 )
4159 },
4160 }
4161
4162 globalThis.$libmupdf_device = {
4163 drop_device(id: number): void {
4164 $libmupdf_device_table.get(id)?.drop?.()
4165 $libmupdf_device_table.delete(id)
4166 },
4167
4168 close_device(id: number): void {
4169 $libmupdf_device_table.get(id)?.close?.()
4170 },
4171
4172 fill_path(
4173 id: number,
4174 path: Pointer<"fz_path">,
4175 even_odd: number,
4176 ctm: Pointer<"fz_matrix">,
4177 colorspace: Pointer<"fz_colorspace">,
4178 color_n: number,
4179 color_arr: Pointer<"float">,
4180 alpha: number
4181 ): void {
4182 $libmupdf_device_table.get(id)?.fillPath?.(
4183 new Path(libmupdf._wasm_keep_path(path)),
4184 !!even_odd,
4185 fromMatrix(ctm),
4186 new ColorSpace(libmupdf._wasm_keep_colorspace(colorspace)),
4187 fromColorArray(color_n, color_arr),
4188 alpha
4189 )
4190 },
4191
4192 clip_path(
4193 id: number,
4194 path: Pointer<"fz_path">,
4195 even_odd: number,
4196 ctm: Pointer<"fz_matrix">
4197 ): void {
4198 $libmupdf_device_table.get(id)?.clipPath?.(
4199 new Path(libmupdf._wasm_keep_path(path)),
4200 !!even_odd,
4201 fromMatrix(ctm)
4202 )
4203 },
4204
4205 stroke_path(
4206 id: number,
4207 path: Pointer<"fz_path">,
4208 stroke: Pointer<"fz_stroke_state">,
4209 ctm: Pointer<"fz_matrix">,
4210 colorspace: Pointer<"fz_colorspace">,
4211 color_n: number,
4212 color_arr: Pointer<"float">,
4213 alpha: number
4214 ): void {
4215 $libmupdf_device_table.get(id)?.strokePath?.(
4216 new Path(libmupdf._wasm_keep_path(path)),
4217 new StrokeState(libmupdf._wasm_keep_stroke_state(stroke)),
4218 fromMatrix(ctm),
4219 new ColorSpace(libmupdf._wasm_keep_colorspace(colorspace)),
4220 fromColorArray(color_n, color_arr),
4221 alpha
4222 )
4223 },
4224
4225 clip_stroke_path(
4226 id: number,
4227 path: Pointer<"fz_path">,
4228 stroke: Pointer<"fz_stroke_state">,
4229 ctm: Pointer<"fz_matrix">
4230 ): void {
4231 $libmupdf_device_table.get(id)?.clipStrokePath?.(
4232 new Path(libmupdf._wasm_keep_path(path)),
4233 new StrokeState(libmupdf._wasm_keep_stroke_state(stroke)),
4234 fromMatrix(ctm)
4235 )
4236 },
4237
4238 fill_text(
4239 id: number,
4240 text: Pointer<"fz_text">,
4241 ctm: Pointer<"fz_matrix">,
4242 colorspace: Pointer<"fz_colorspace">,
4243 color_n: number,
4244 color_arr: Pointer<"float">,
4245 alpha: number
4246 ): void {
4247 $libmupdf_device_table.get(id)?.fillText?.(
4248 new Text(libmupdf._wasm_keep_text(text)),
4249 fromMatrix(ctm),
4250 new ColorSpace(libmupdf._wasm_keep_colorspace(colorspace)),
4251 fromColorArray(color_n, color_arr),
4252 alpha
4253 )
4254 },
4255
4256 stroke_text(
4257 id: number,
4258 text: Pointer<"fz_text">,
4259 stroke: Pointer<"fz_stroke_state">,
4260 ctm: Pointer<"fz_matrix">,
4261 colorspace: Pointer<"fz_colorspace">,
4262 color_n: number,
4263 color_arr: Pointer<"float">,
4264 alpha: number
4265 ): void {
4266 $libmupdf_device_table.get(id)?.strokeText?.(
4267 new Text(libmupdf._wasm_keep_text(text)),
4268 new StrokeState(libmupdf._wasm_keep_stroke_state(stroke)),
4269 fromMatrix(ctm),
4270 new ColorSpace(libmupdf._wasm_keep_colorspace(colorspace)),
4271 fromColorArray(color_n, color_arr),
4272 alpha
4273 )
4274 },
4275
4276 clip_text(
4277 id: number,
4278 text: Pointer<"fz_text">,
4279 ctm: Pointer<"fz_matrix">
4280 ): void {
4281 $libmupdf_device_table.get(id)?.clipText?.(
4282 new Text(libmupdf._wasm_keep_text(text)),
4283 fromMatrix(ctm)
4284 )
4285 },
4286
4287 clip_stroke_text(
4288 id: number,
4289 text: Pointer<"fz_text">,
4290 stroke: Pointer<"fz_stroke_state">,
4291 ctm: Pointer<"fz_matrix">,
4292 ): void {
4293 $libmupdf_device_table.get(id)?.clipStrokeText?.(
4294 new Text(libmupdf._wasm_keep_text(text)),
4295 new StrokeState(libmupdf._wasm_keep_stroke_state(stroke)),
4296 fromMatrix(ctm)
4297 )
4298 },
4299
4300 ignore_text(
4301 id: number,
4302 text: Pointer<"fz_text">,
4303 ctm: Pointer<"fz_matrix">
4304 ): void {
4305 $libmupdf_device_table.get(id)?.ignoreText?.(
4306 new Text(libmupdf._wasm_keep_text(text)),
4307 fromMatrix(ctm)
4308 )
4309 },
4310
4311 fill_shade(
4312 id: number,
4313 shade: Pointer<"fz_shade">,
4314 ctm: Pointer<"fz_matrix">,
4315 alpha: number
4316 ): void {
4317 $libmupdf_device_table.get(id)?.fillShade?.(
4318 new Shade(shade),
4319 fromMatrix(ctm),
4320 alpha
4321 )
4322 },
4323
4324 fill_image(
4325 id: number,
4326 image: Pointer<"fz_image">,
4327 ctm: Pointer<"fz_matrix">,
4328 alpha: number
4329 ): void {
4330 $libmupdf_device_table.get(id)?.fillImage?.(
4331 new Image(image),
4332 fromMatrix(ctm),
4333 alpha
4334 )
4335 },
4336
4337 fill_image_mask(
4338 id: number,
4339 image: Pointer<"fz_image">,
4340 ctm: Pointer<"fz_matrix">,
4341 colorspace: Pointer<"fz_colorspace">,
4342 color_n: number,
4343 color_arr: Pointer<"float">,
4344 alpha: number
4345 ): void {
4346 $libmupdf_device_table.get(id)?.fillImageMask?.(
4347 new Image(image),
4348 fromMatrix(ctm),
4349 new ColorSpace(libmupdf._wasm_keep_colorspace(colorspace)),
4350 fromColorArray(color_n, color_arr),
4351 alpha
4352 )
4353 },
4354
4355 clip_image_mask(
4356 id: number,
4357 image: Pointer<"fz_image">,
4358 ctm: Pointer<"fz_matrix">
4359 ): void {
4360 $libmupdf_device_table.get(id)?.clipImageMask?.(
4361 new Image(image),
4362 fromMatrix(ctm)
4363 )
4364 },
4365
4366 pop_clip(id: number): void {
4367 $libmupdf_device_table.get(id)?.popClip?.()
4368 },
4369
4370 begin_mask(
4371 id: number,
4372 bbox: Pointer<"fz_rect">,
4373 luminosity: number,
4374 colorspace: Pointer<"fz_colorspace">,
4375 color_n: number,
4376 color_arr: Pointer<"float">
4377 ): void {
4378 $libmupdf_device_table.get(id)?.beginMask?.(
4379 fromRect(bbox),
4380 !!luminosity,
4381 new ColorSpace(libmupdf._wasm_keep_colorspace(colorspace)),
4382 fromColorArray(color_n, color_arr)
4383 )
4384 },
4385
4386 begin_group(
4387 id: number,
4388 bbox: Pointer<"fz_rect">,
4389 colorspace: Pointer<"fz_colorspace">,
4390 isolated: number,
4391 knockout: number,
4392 blendmode: number,
4393 alpha: number
4394 ): void {
4395 $libmupdf_device_table.get(id)?.beginGroup?.(
4396 fromRect(bbox),
4397 new ColorSpace(libmupdf._wasm_keep_colorspace(colorspace)),
4398 !!isolated,
4399 !!knockout,
4400 Device.BLEND_MODES[blendmode] as BlendMode,
4401 alpha
4402 )
4403 },
4404
4405 begin_tile(
4406 id: number,
4407 area: Pointer<"fz_rect">,
4408 view: Pointer<"fz_rect">,
4409 xstep: number,
4410 ystep: number,
4411 ctm: Pointer<"fz_matrix">,
4412 tile_id: number,
4413 doc_id: number
4414 ): number {
4415 return $libmupdf_device_table.get(id)?.beginTile?.(
4416 fromRect(area),
4417 fromRect(view),
4418 xstep,
4419 ystep,
4420 fromMatrix(ctm),
4421 tile_id,
4422 doc_id
4423 ) || 0
4424 },
4425
4426 begin_layer(id: number, name: Pointer<"char">): void {
4427 $libmupdf_device_table.get(id)?.beginLayer?.(
4428 fromString(name)
4429 )
4430 },
4431
4432 end_mask(id: number): void {
4433 $libmupdf_device_table.get(id)?.endMask?.()
4434 },
4435
4436 end_group(id: number): void {
4437 $libmupdf_device_table.get(id)?.endGroup?.()
4438 },
4439
4440 end_tile(id: number): void {
4441 $libmupdf_device_table.get(id)?.endTile?.()
4442 },
4443
4444 end_layer(id: number): void {
4445 $libmupdf_device_table.get(id)?.endLayer?.()
4446 },
4447
4448 }
4449
4450 /* default exports */
4451 export default {
4452 // const
4453 Matrix,
4454 Rect,
4455
4456 // function
4457 enableICC,
4458 disableICC,
4459 setUserCSS,
4460 installLoadFontFunction,
4461
4462 // class
4463 Buffer,
4464 ColorSpace,
4465 Font,
4466 Image,
4467 StrokeState,
4468 Path,
4469 Text,
4470 DisplayList,
4471 Pixmap,
4472 Shade,
4473 StructuredText,
4474 Device,
4475 DrawDevice,
4476 DisplayListDevice,
4477 DocumentWriter,
4478 Document,
4479 OutlineIterator,
4480 Link,
4481 Page,
4482 PDFDocument,
4483 PDFPage,
4484 PDFObject,
4485 PDFGraftMap,
4486 PDFAnnotation,
4487 PDFWidget,
4488 Stream,
4489
4490 // debugging
4491 memento
4492 }