comparison mupdf-source/platform/wasm/examples/simple-viewer/worker.js @ 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) 2022, 2024 Artifex Software, Inc.
2 //
3 // This file is part of MuPDF.
4 //
5 // MuPDF is free software: you can redistribute it and/or modify it under the
6 // terms of the GNU Affero General Public License as published by the Free
7 // Software Foundation, either version 3 of the License, or (at your option)
8 // any later version.
9 //
10 // MuPDF is distributed in the hope that it will be useful, but WITHOUT ANY
11 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12 // FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
13 // details.
14 //
15 // You should have received a copy of the GNU Affero General Public License
16 // along with MuPDF. If not, see <https://www.gnu.org/licenses/agpl-3.0.en.html>
17 //
18 // Alternative licensing terms are available from the licensor.
19 // For commercial licensing, see <https://www.artifex.com/> or contact
20 // Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco,
21 // CA 94129, USA, for further information.
22
23 "use strict"
24
25 import * as mupdf from "../../dist/mupdf.js"
26
27 const methods = {}
28
29 onmessage = async function (event) {
30 let [ func, id, args ] = event.data
31 try {
32 let result = methods[func](...args)
33 postMessage([ "RESULT", id, result ])
34 } catch (error) {
35 postMessage([ "ERROR", id, { name: error.name, message: error.message, stack: error.stack } ])
36 }
37 }
38
39 var document_next_id = 1
40 var document_map = {} // open mupdf.Document handles
41
42 class WorkerBlobStream {
43 constructor(blob) {
44 this.reader = new FileReaderSync()
45 this.blob = blob
46 }
47 fileSize() {
48 return this.blob.size
49 }
50 read(memory, offset, size, position) {
51 let data = this.reader.readAsArrayBuffer(this.blob.slice(position, position + size))
52 memory.set(new Uint8Array(data), offset)
53 return data.byteLength
54 }
55 close() {
56 this.reader = null
57 this.blob = null
58 }
59 }
60
61 methods.openDocumentFromBlob = function (blob, magic) {
62 let stm = new mupdf.Stream(new WorkerBlobStream(blob))
63 let doc_id = document_next_id++
64 document_map[doc_id] = mupdf.Document.openDocument(stm, magic)
65 return doc_id
66 }
67
68 methods.openDocumentFromBuffer = function (buffer, magic) {
69 let doc_id = document_next_id++
70 document_map[doc_id] = mupdf.Document.openDocument(buffer, magic)
71 return doc_id
72 }
73
74 methods.closeDocument = function (doc_id) {
75 let doc = document_map[doc_id]
76 doc.destroy()
77 delete document_map[doc_id]
78 }
79
80 methods.documentTitle = function (doc_id) {
81 let doc = document_map[doc_id]
82 return doc.getMetaData(mupdf.Document.META_INFO_TITLE)
83 }
84
85 methods.documentOutline = function (doc_id) {
86 let doc = document_map[doc_id]
87 return doc.loadOutline()
88 }
89
90 methods.countPages = function (doc_id) {
91 let doc = document_map[doc_id]
92 return doc.countPages()
93 }
94
95 methods.getPageSize = function (doc_id, page_number) {
96 let doc = document_map[doc_id]
97 let page = doc.loadPage(page_number)
98 let bounds = page.getBounds()
99 return { width: bounds[2] - bounds[0], height: bounds[3] - bounds[1] }
100 }
101
102 methods.getPageLinks = function (doc_id, page_number) {
103 let doc = document_map[doc_id]
104 let page = doc.loadPage(page_number)
105 let links = page.getLinks()
106
107 return links.map((link) => {
108 const [ x0, y0, x1, y1 ] = link.getBounds()
109
110 let href
111 if (link.isExternal())
112 href = link.getURI()
113 else
114 href = `#page${doc.resolveLink(link) + 1}`
115
116 return {
117 x: x0,
118 y: y0,
119 w: x1 - x0,
120 h: y1 - y0,
121 href,
122 }
123 })
124 }
125
126 methods.getPageText = function (doc_id, page_number) {
127 let doc = document_map[doc_id]
128 let page = doc.loadPage(page_number)
129 let text = page.toStructuredText().asJSON()
130 return JSON.parse(text)
131 }
132
133 methods.search = function (doc_id, page_number, needle) {
134 let doc = document_map[doc_id]
135 let page = doc.loadPage(page_number)
136 const hits = page.search(needle)
137 let result = []
138 for (let hit of hits) {
139 for (let quad of hit) {
140 const [ ulx, uly, urx, ury, llx, lly, lrx, lry ] = quad
141 result.push({
142 x: ulx,
143 y: uly,
144 w: urx - ulx,
145 h: lly - uly,
146 })
147 }
148 }
149 return result
150 }
151
152 methods.getPageAnnotations = function (doc_id, page_number, dpi) {
153 let doc = document_map[doc_id]
154 let page = doc.loadPage(page_number)
155
156 if (page == null) {
157 return []
158 }
159
160 const annotations = page.getAnnotations()
161 const doc_to_screen = [ dpi = 72, 0, 0, dpi / 72, 0, 0 ]
162
163 return annotations.map((annotation) => {
164 const [ x0, y0, x1, y1 ] = mupdf.Matrix.transformRect(annotation.getBounds())
165 return {
166 x: x0,
167 y: y0,
168 w: x1 - x0,
169 h: y1 - y0,
170 type: annotation.getType(),
171 ref: annotation.pointer,
172 }
173 })
174 }
175
176 methods.drawPageAsPixmap = function (doc_id, page_number, dpi) {
177 const doc_to_screen = mupdf.Matrix.scale(dpi / 72, dpi / 72)
178
179 let doc = document_map[doc_id]
180 let page = doc.loadPage(page_number)
181 let bbox = mupdf.Rect.transform(page.getBounds(), doc_to_screen)
182
183 let pixmap = new mupdf.Pixmap(mupdf.ColorSpace.DeviceRGB, bbox, true)
184 pixmap.clear(255)
185
186 let device = new mupdf.DrawDevice(doc_to_screen, pixmap)
187 page.run(device, mupdf.Matrix.identity)
188 device.close()
189
190 // TODO: do we need to make a copy with slice() ?
191 let imageData = new ImageData(pixmap.getPixels().slice(), pixmap.getWidth(), pixmap.getHeight())
192
193 pixmap.destroy()
194
195 // TODO: do we need to pass image data as transferable to avoid copying?
196 return imageData
197 }
198
199 postMessage([ "INIT", 0, Object.keys(methods) ])