@vaadin-component-factory/vcf-pdf-viewer 0.9.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (172) hide show
  1. package/README.md +1 -1
  2. package/package.json +42 -26
  3. package/{src/display → pdfjs/dist}/display_utils.js +344 -139
  4. package/{src/display → pdfjs/dist}/fetch_stream.js +115 -97
  5. package/pdfjs/dist/l10n_utils.js +140 -0
  6. package/{src/shared → pdfjs/dist}/message_handler.js +243 -259
  7. package/{src/display → pdfjs/dist}/network.js +149 -87
  8. package/{src/display/content_disposition.js → pdfjs/dist/network_utils.js} +167 -55
  9. package/{src/display → pdfjs/dist}/node_stream.js +133 -98
  10. package/pdfjs/dist/pdf.js +12778 -0
  11. package/pdfjs/dist/pdf_link_service.js +638 -0
  12. package/pdfjs/dist/pdf_rendering_queue.js +199 -0
  13. package/pdfjs/dist/pdf_thumbnail_viewer.js +819 -0
  14. package/pdfjs/dist/pdf_viewer.js +3598 -0
  15. package/pdfjs/dist/ui_utils.js +1033 -0
  16. package/{src/shared → pdfjs/dist}/util.js +301 -287
  17. package/pdfjs/dist/worker.js +62813 -0
  18. package/src/vcf-pdf-viewer.js +98 -46
  19. package/theme/lumo/vcf-pdf-viewer-styles.js +4 -4
  20. package/theme/material/vcf-pdf-viewer-styles.js +4 -4
  21. package/theme/material/vcf-pdf-viewer.js +2 -2
  22. package/src/core/.eslintrc +0 -13
  23. package/src/core/annotation.js +0 -2948
  24. package/src/core/arithmetic_decoder.js +0 -182
  25. package/src/core/ascii_85_stream.js +0 -98
  26. package/src/core/ascii_hex_stream.js +0 -79
  27. package/src/core/base_stream.js +0 -110
  28. package/src/core/bidi.js +0 -438
  29. package/src/core/calibri_factors.js +0 -308
  30. package/src/core/catalog.js +0 -1459
  31. package/src/core/ccitt.js +0 -1062
  32. package/src/core/ccitt_stream.js +0 -60
  33. package/src/core/cff_font.js +0 -116
  34. package/src/core/cff_parser.js +0 -1949
  35. package/src/core/charsets.js +0 -119
  36. package/src/core/chunked_stream.js +0 -557
  37. package/src/core/cmap.js +0 -1039
  38. package/src/core/colorspace.js +0 -1533
  39. package/src/core/core_utils.js +0 -464
  40. package/src/core/crypto.js +0 -1900
  41. package/src/core/decode_stream.js +0 -170
  42. package/src/core/decrypt_stream.js +0 -59
  43. package/src/core/default_appearance.js +0 -99
  44. package/src/core/document.js +0 -1456
  45. package/src/core/encodings.js +0 -301
  46. package/src/core/evaluator.js +0 -4601
  47. package/src/core/file_spec.js +0 -108
  48. package/src/core/flate_stream.js +0 -402
  49. package/src/core/font_renderer.js +0 -882
  50. package/src/core/fonts.js +0 -3260
  51. package/src/core/fonts_utils.js +0 -221
  52. package/src/core/function.js +0 -1257
  53. package/src/core/glyf.js +0 -706
  54. package/src/core/glyphlist.js +0 -4558
  55. package/src/core/helvetica_factors.js +0 -353
  56. package/src/core/image.js +0 -802
  57. package/src/core/image_utils.js +0 -291
  58. package/src/core/jbig2.js +0 -2572
  59. package/src/core/jbig2_stream.js +0 -73
  60. package/src/core/jpeg_stream.js +0 -105
  61. package/src/core/jpg.js +0 -1416
  62. package/src/core/jpx.js +0 -2343
  63. package/src/core/jpx_stream.js +0 -87
  64. package/src/core/liberationsans_widths.js +0 -221
  65. package/src/core/lzw_stream.js +0 -150
  66. package/src/core/metadata_parser.js +0 -146
  67. package/src/core/metrics.js +0 -2970
  68. package/src/core/murmurhash3.js +0 -139
  69. package/src/core/myriadpro_factors.js +0 -290
  70. package/src/core/name_number_tree.js +0 -153
  71. package/src/core/object_loader.js +0 -149
  72. package/src/core/opentype_file_builder.js +0 -154
  73. package/src/core/operator_list.js +0 -734
  74. package/src/core/parser.js +0 -1416
  75. package/src/core/pattern.js +0 -985
  76. package/src/core/pdf_manager.js +0 -217
  77. package/src/core/predictor_stream.js +0 -238
  78. package/src/core/primitives.js +0 -402
  79. package/src/core/ps_parser.js +0 -272
  80. package/src/core/run_length_stream.js +0 -61
  81. package/src/core/segoeui_factors.js +0 -308
  82. package/src/core/standard_fonts.js +0 -817
  83. package/src/core/stream.js +0 -103
  84. package/src/core/struct_tree.js +0 -335
  85. package/src/core/to_unicode_map.js +0 -103
  86. package/src/core/type1_font.js +0 -421
  87. package/src/core/type1_parser.js +0 -776
  88. package/src/core/unicode.js +0 -1649
  89. package/src/core/worker.js +0 -848
  90. package/src/core/worker_stream.js +0 -135
  91. package/src/core/writer.js +0 -278
  92. package/src/core/xfa/bind.js +0 -652
  93. package/src/core/xfa/builder.js +0 -207
  94. package/src/core/xfa/config.js +0 -1926
  95. package/src/core/xfa/connection_set.js +0 -202
  96. package/src/core/xfa/data.js +0 -82
  97. package/src/core/xfa/datasets.js +0 -76
  98. package/src/core/xfa/factory.js +0 -111
  99. package/src/core/xfa/fonts.js +0 -181
  100. package/src/core/xfa/formcalc_lexer.js +0 -385
  101. package/src/core/xfa/formcalc_parser.js +0 -1340
  102. package/src/core/xfa/html_utils.js +0 -639
  103. package/src/core/xfa/layout.js +0 -383
  104. package/src/core/xfa/locale_set.js +0 -345
  105. package/src/core/xfa/namespaces.js +0 -81
  106. package/src/core/xfa/parser.js +0 -184
  107. package/src/core/xfa/setup.js +0 -38
  108. package/src/core/xfa/signature.js +0 -40
  109. package/src/core/xfa/som.js +0 -338
  110. package/src/core/xfa/stylesheet.js +0 -40
  111. package/src/core/xfa/template.js +0 -6260
  112. package/src/core/xfa/text.js +0 -290
  113. package/src/core/xfa/unknown.js +0 -29
  114. package/src/core/xfa/utils.js +0 -217
  115. package/src/core/xfa/xdp.js +0 -59
  116. package/src/core/xfa/xfa_object.js +0 -1130
  117. package/src/core/xfa/xhtml.js +0 -543
  118. package/src/core/xfa_fonts.js +0 -208
  119. package/src/core/xml_parser.js +0 -507
  120. package/src/core/xref.js +0 -899
  121. package/src/display/annotation_layer.js +0 -2107
  122. package/src/display/annotation_storage.js +0 -113
  123. package/src/display/api.js +0 -3292
  124. package/src/display/base_factory.js +0 -180
  125. package/src/display/canvas.js +0 -2828
  126. package/src/display/font_loader.js +0 -484
  127. package/src/display/metadata.js +0 -41
  128. package/src/display/network_utils.js +0 -100
  129. package/src/display/node_utils.js +0 -83
  130. package/src/display/optional_content_config.js +0 -189
  131. package/src/display/pattern_helper.js +0 -659
  132. package/src/display/svg.js +0 -1709
  133. package/src/display/text_layer.js +0 -847
  134. package/src/display/transport_stream.js +0 -303
  135. package/src/display/worker_options.js +0 -40
  136. package/src/display/xfa_layer.js +0 -204
  137. package/src/doc_helper.js +0 -25
  138. package/src/images/logo.svg +0 -41
  139. package/src/interfaces.js +0 -169
  140. package/src/license_header.js +0 -14
  141. package/src/license_header_libre.js +0 -21
  142. package/src/pdf.image_decoders.js +0 -46
  143. package/src/pdf.js +0 -146
  144. package/src/pdf.sandbox.external.js +0 -181
  145. package/src/pdf.sandbox.js +0 -151
  146. package/src/pdf.scripting.js +0 -25
  147. package/src/pdf.worker.entry.js +0 -19
  148. package/src/pdf.worker.js +0 -23
  149. package/src/scripting_api/aform.js +0 -608
  150. package/src/scripting_api/app.js +0 -621
  151. package/src/scripting_api/color.js +0 -129
  152. package/src/scripting_api/common.js +0 -58
  153. package/src/scripting_api/console.js +0 -38
  154. package/src/scripting_api/constants.js +0 -208
  155. package/src/scripting_api/doc.js +0 -1195
  156. package/src/scripting_api/error.js +0 -23
  157. package/src/scripting_api/event.js +0 -232
  158. package/src/scripting_api/field.js +0 -620
  159. package/src/scripting_api/fullscreen.js +0 -145
  160. package/src/scripting_api/initialization.js +0 -223
  161. package/src/scripting_api/pdf_object.js +0 -24
  162. package/src/scripting_api/print_params.js +0 -146
  163. package/src/scripting_api/proxy.js +0 -139
  164. package/src/scripting_api/thermometer.js +0 -69
  165. package/src/scripting_api/util.js +0 -581
  166. package/src/shared/.eslintrc +0 -13
  167. package/src/shared/cffStandardStrings.js +0 -311
  168. package/src/shared/compatibility.js +0 -114
  169. package/src/shared/fonts_utils.js +0 -429
  170. package/src/shared/is_node.js +0 -27
  171. package/src/shared/scripting_utils.js +0 -85
  172. package/src/worker_loader.js +0 -32
@@ -1,1709 +0,0 @@
1
- /* Copyright 2012 Mozilla Foundation
2
- *
3
- * Licensed under the Apache License, Version 2.0 (the "License");
4
- * you may not use this file except in compliance with the License.
5
- * You may obtain a copy of the License at
6
- *
7
- * http://www.apache.org/licenses/LICENSE-2.0
8
- *
9
- * Unless required by applicable law or agreed to in writing, software
10
- * distributed under the License is distributed on an "AS IS" BASIS,
11
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
- * See the License for the specific language governing permissions and
13
- * limitations under the License.
14
- */
15
- /* globals __non_webpack_require__ */
16
-
17
- import {
18
- createObjectURL,
19
- FONT_IDENTITY_MATRIX,
20
- IDENTITY_MATRIX,
21
- ImageKind,
22
- isNum,
23
- OPS,
24
- TextRenderingMode,
25
- unreachable,
26
- Util,
27
- warn,
28
- } from "../shared/util.js";
29
- import { DOMSVGFactory } from "./display_utils.js";
30
- import { isNodeJS } from "../shared/is_node.js";
31
-
32
- /** @type {any} */
33
- let SVGGraphics = class {
34
- constructor() {
35
- unreachable("Not implemented: SVGGraphics");
36
- }
37
- };
38
-
39
- if (
40
- typeof PDFJSDev === "undefined" ||
41
- PDFJSDev.test("!PRODUCTION || GENERIC")
42
- ) {
43
- const SVG_DEFAULTS = {
44
- fontStyle: "normal",
45
- fontWeight: "normal",
46
- fillColor: "#000000",
47
- };
48
- const XML_NS = "http://www.w3.org/XML/1998/namespace";
49
- const XLINK_NS = "http://www.w3.org/1999/xlink";
50
- const LINE_CAP_STYLES = ["butt", "round", "square"];
51
- const LINE_JOIN_STYLES = ["miter", "round", "bevel"];
52
-
53
- const convertImgDataToPng = (function () {
54
- const PNG_HEADER = new Uint8Array([
55
- 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a,
56
- ]);
57
- const CHUNK_WRAPPER_SIZE = 12;
58
-
59
- const crcTable = new Int32Array(256);
60
- for (let i = 0; i < 256; i++) {
61
- let c = i;
62
- for (let h = 0; h < 8; h++) {
63
- if (c & 1) {
64
- c = 0xedb88320 ^ ((c >> 1) & 0x7fffffff);
65
- } else {
66
- c = (c >> 1) & 0x7fffffff;
67
- }
68
- }
69
- crcTable[i] = c;
70
- }
71
-
72
- function crc32(data, start, end) {
73
- let crc = -1;
74
- for (let i = start; i < end; i++) {
75
- const a = (crc ^ data[i]) & 0xff;
76
- const b = crcTable[a];
77
- crc = (crc >>> 8) ^ b;
78
- }
79
- return crc ^ -1;
80
- }
81
-
82
- function writePngChunk(type, body, data, offset) {
83
- let p = offset;
84
- const len = body.length;
85
-
86
- data[p] = (len >> 24) & 0xff;
87
- data[p + 1] = (len >> 16) & 0xff;
88
- data[p + 2] = (len >> 8) & 0xff;
89
- data[p + 3] = len & 0xff;
90
- p += 4;
91
-
92
- data[p] = type.charCodeAt(0) & 0xff;
93
- data[p + 1] = type.charCodeAt(1) & 0xff;
94
- data[p + 2] = type.charCodeAt(2) & 0xff;
95
- data[p + 3] = type.charCodeAt(3) & 0xff;
96
- p += 4;
97
-
98
- data.set(body, p);
99
- p += body.length;
100
-
101
- const crc = crc32(data, offset + 4, p);
102
- data[p] = (crc >> 24) & 0xff;
103
- data[p + 1] = (crc >> 16) & 0xff;
104
- data[p + 2] = (crc >> 8) & 0xff;
105
- data[p + 3] = crc & 0xff;
106
- }
107
-
108
- function adler32(data, start, end) {
109
- let a = 1;
110
- let b = 0;
111
- for (let i = start; i < end; ++i) {
112
- a = (a + (data[i] & 0xff)) % 65521;
113
- b = (b + a) % 65521;
114
- }
115
- return (b << 16) | a;
116
- }
117
-
118
- /**
119
- * @param {Uint8Array} literals The input data.
120
- * @returns {Uint8Array} The DEFLATE-compressed data stream in zlib format.
121
- * This is the required format for compressed streams in the PNG format:
122
- * http://www.libpng.org/pub/png/spec/1.2/PNG-Compression.html
123
- */
124
- function deflateSync(literals) {
125
- if (!isNodeJS) {
126
- // zlib is certainly not available outside of Node.js. We can either use
127
- // the pako library for client-side DEFLATE compression, or use the
128
- // canvas API of the browser to obtain a more optimal PNG file.
129
- return deflateSyncUncompressed(literals);
130
- }
131
- try {
132
- // NOTE: This implementation is far from perfect, but already way better
133
- // than not applying any compression.
134
- //
135
- // A better algorithm will try to choose a good predictor/filter and
136
- // then choose a suitable zlib compression strategy (e.g. 3,Z_RLE).
137
- //
138
- // Node v0.11.12 zlib.deflateSync is introduced (and returns a Buffer).
139
- // Node v3.0.0 Buffer inherits from Uint8Array.
140
- // Node v8.0.0 zlib.deflateSync accepts Uint8Array as input.
141
- let input;
142
- // eslint-disable-next-line no-undef
143
- if (parseInt(process.versions.node) >= 8) {
144
- input = literals;
145
- } else {
146
- // eslint-disable-next-line no-undef
147
- input = Buffer.from(literals);
148
- }
149
- const output = __non_webpack_require__("zlib").deflateSync(input, {
150
- level: 9,
151
- });
152
- return output instanceof Uint8Array ? output : new Uint8Array(output);
153
- } catch (e) {
154
- warn(
155
- "Not compressing PNG because zlib.deflateSync is unavailable: " + e
156
- );
157
- }
158
-
159
- return deflateSyncUncompressed(literals);
160
- }
161
-
162
- // An implementation of DEFLATE with compression level 0 (Z_NO_COMPRESSION).
163
- function deflateSyncUncompressed(literals) {
164
- let len = literals.length;
165
- const maxBlockLength = 0xffff;
166
-
167
- const deflateBlocks = Math.ceil(len / maxBlockLength);
168
- const idat = new Uint8Array(2 + len + deflateBlocks * 5 + 4);
169
- let pi = 0;
170
- idat[pi++] = 0x78; // compression method and flags
171
- idat[pi++] = 0x9c; // flags
172
-
173
- let pos = 0;
174
- while (len > maxBlockLength) {
175
- // writing non-final DEFLATE blocks type 0 and length of 65535
176
- idat[pi++] = 0x00;
177
- idat[pi++] = 0xff;
178
- idat[pi++] = 0xff;
179
- idat[pi++] = 0x00;
180
- idat[pi++] = 0x00;
181
- idat.set(literals.subarray(pos, pos + maxBlockLength), pi);
182
- pi += maxBlockLength;
183
- pos += maxBlockLength;
184
- len -= maxBlockLength;
185
- }
186
-
187
- // writing non-final DEFLATE blocks type 0
188
- idat[pi++] = 0x01;
189
- idat[pi++] = len & 0xff;
190
- idat[pi++] = (len >> 8) & 0xff;
191
- idat[pi++] = ~len & 0xffff & 0xff;
192
- idat[pi++] = ((~len & 0xffff) >> 8) & 0xff;
193
- idat.set(literals.subarray(pos), pi);
194
- pi += literals.length - pos;
195
-
196
- const adler = adler32(literals, 0, literals.length); // checksum
197
- idat[pi++] = (adler >> 24) & 0xff;
198
- idat[pi++] = (adler >> 16) & 0xff;
199
- idat[pi++] = (adler >> 8) & 0xff;
200
- idat[pi++] = adler & 0xff;
201
- return idat;
202
- }
203
-
204
- function encode(imgData, kind, forceDataSchema, isMask) {
205
- const width = imgData.width;
206
- const height = imgData.height;
207
- let bitDepth, colorType, lineSize;
208
- const bytes = imgData.data;
209
-
210
- switch (kind) {
211
- case ImageKind.GRAYSCALE_1BPP:
212
- colorType = 0;
213
- bitDepth = 1;
214
- lineSize = (width + 7) >> 3;
215
- break;
216
- case ImageKind.RGB_24BPP:
217
- colorType = 2;
218
- bitDepth = 8;
219
- lineSize = width * 3;
220
- break;
221
- case ImageKind.RGBA_32BPP:
222
- colorType = 6;
223
- bitDepth = 8;
224
- lineSize = width * 4;
225
- break;
226
- default:
227
- throw new Error("invalid format");
228
- }
229
-
230
- // prefix every row with predictor 0
231
- const literals = new Uint8Array((1 + lineSize) * height);
232
- let offsetLiterals = 0,
233
- offsetBytes = 0;
234
- for (let y = 0; y < height; ++y) {
235
- literals[offsetLiterals++] = 0; // no prediction
236
- literals.set(
237
- bytes.subarray(offsetBytes, offsetBytes + lineSize),
238
- offsetLiterals
239
- );
240
- offsetBytes += lineSize;
241
- offsetLiterals += lineSize;
242
- }
243
-
244
- if (kind === ImageKind.GRAYSCALE_1BPP && isMask) {
245
- // inverting for image masks
246
- offsetLiterals = 0;
247
- for (let y = 0; y < height; y++) {
248
- offsetLiterals++; // skipping predictor
249
- for (let i = 0; i < lineSize; i++) {
250
- literals[offsetLiterals++] ^= 0xff;
251
- }
252
- }
253
- }
254
-
255
- const ihdr = new Uint8Array([
256
- (width >> 24) & 0xff,
257
- (width >> 16) & 0xff,
258
- (width >> 8) & 0xff,
259
- width & 0xff,
260
- (height >> 24) & 0xff,
261
- (height >> 16) & 0xff,
262
- (height >> 8) & 0xff,
263
- height & 0xff,
264
- bitDepth, // bit depth
265
- colorType, // color type
266
- 0x00, // compression method
267
- 0x00, // filter method
268
- 0x00, // interlace method
269
- ]);
270
- const idat = deflateSync(literals);
271
-
272
- // PNG consists of: header, IHDR+data, IDAT+data, and IEND.
273
- const pngLength =
274
- PNG_HEADER.length + CHUNK_WRAPPER_SIZE * 3 + ihdr.length + idat.length;
275
- const data = new Uint8Array(pngLength);
276
- let offset = 0;
277
- data.set(PNG_HEADER, offset);
278
- offset += PNG_HEADER.length;
279
- writePngChunk("IHDR", ihdr, data, offset);
280
- offset += CHUNK_WRAPPER_SIZE + ihdr.length;
281
- writePngChunk("IDATA", idat, data, offset);
282
- offset += CHUNK_WRAPPER_SIZE + idat.length;
283
- writePngChunk("IEND", new Uint8Array(0), data, offset);
284
-
285
- return createObjectURL(data, "image/png", forceDataSchema);
286
- }
287
-
288
- // eslint-disable-next-line no-shadow
289
- return function convertImgDataToPng(imgData, forceDataSchema, isMask) {
290
- const kind =
291
- imgData.kind === undefined ? ImageKind.GRAYSCALE_1BPP : imgData.kind;
292
- return encode(imgData, kind, forceDataSchema, isMask);
293
- };
294
- })();
295
-
296
- class SVGExtraState {
297
- constructor() {
298
- this.fontSizeScale = 1;
299
- this.fontWeight = SVG_DEFAULTS.fontWeight;
300
- this.fontSize = 0;
301
-
302
- this.textMatrix = IDENTITY_MATRIX;
303
- this.fontMatrix = FONT_IDENTITY_MATRIX;
304
- this.leading = 0;
305
- this.textRenderingMode = TextRenderingMode.FILL;
306
- this.textMatrixScale = 1;
307
-
308
- // Current point (in user coordinates)
309
- this.x = 0;
310
- this.y = 0;
311
-
312
- // Start of text line (in text coordinates)
313
- this.lineX = 0;
314
- this.lineY = 0;
315
-
316
- // Character and word spacing
317
- this.charSpacing = 0;
318
- this.wordSpacing = 0;
319
- this.textHScale = 1;
320
- this.textRise = 0;
321
-
322
- // Default foreground and background colors
323
- this.fillColor = SVG_DEFAULTS.fillColor;
324
- this.strokeColor = "#000000";
325
-
326
- this.fillAlpha = 1;
327
- this.strokeAlpha = 1;
328
- this.lineWidth = 1;
329
- this.lineJoin = "";
330
- this.lineCap = "";
331
- this.miterLimit = 0;
332
-
333
- this.dashArray = [];
334
- this.dashPhase = 0;
335
-
336
- this.dependencies = [];
337
-
338
- // Clipping
339
- this.activeClipUrl = null;
340
- this.clipGroup = null;
341
-
342
- this.maskId = "";
343
- }
344
-
345
- clone() {
346
- return Object.create(this);
347
- }
348
-
349
- setCurrentPoint(x, y) {
350
- this.x = x;
351
- this.y = y;
352
- }
353
- }
354
-
355
- // eslint-disable-next-line no-inner-declarations
356
- function opListToTree(opList) {
357
- let opTree = [];
358
- const tmp = [];
359
-
360
- for (const opListElement of opList) {
361
- if (opListElement.fn === "save") {
362
- opTree.push({ fnId: 92, fn: "group", items: [] });
363
- tmp.push(opTree);
364
- opTree = opTree[opTree.length - 1].items;
365
- continue;
366
- }
367
-
368
- if (opListElement.fn === "restore") {
369
- opTree = tmp.pop();
370
- } else {
371
- opTree.push(opListElement);
372
- }
373
- }
374
- return opTree;
375
- }
376
-
377
- /**
378
- * Format a float number as a string.
379
- *
380
- * @param value {number} - The float number to format.
381
- * @returns {string}
382
- */
383
- // eslint-disable-next-line no-inner-declarations
384
- function pf(value) {
385
- if (Number.isInteger(value)) {
386
- return value.toString();
387
- }
388
- const s = value.toFixed(10);
389
- let i = s.length - 1;
390
- if (s[i] !== "0") {
391
- return s;
392
- }
393
-
394
- // Remove trailing zeros.
395
- do {
396
- i--;
397
- } while (s[i] === "0");
398
- return s.substring(0, s[i] === "." ? i : i + 1);
399
- }
400
-
401
- /**
402
- * Format a transform matrix as a string. The standard rotation, scale and
403
- * translation matrices are replaced by their shorter forms, and for
404
- * identity matrices an empty string is returned to save memory.
405
- *
406
- * @param m {Array} - The transform matrix to format.
407
- * @returns {string}
408
- */
409
- // eslint-disable-next-line no-inner-declarations
410
- function pm(m) {
411
- if (m[4] === 0 && m[5] === 0) {
412
- if (m[1] === 0 && m[2] === 0) {
413
- if (m[0] === 1 && m[3] === 1) {
414
- return "";
415
- }
416
- return `scale(${pf(m[0])} ${pf(m[3])})`;
417
- }
418
- if (m[0] === m[3] && m[1] === -m[2]) {
419
- const a = (Math.acos(m[0]) * 180) / Math.PI;
420
- return `rotate(${pf(a)})`;
421
- }
422
- } else {
423
- if (m[0] === 1 && m[1] === 0 && m[2] === 0 && m[3] === 1) {
424
- return `translate(${pf(m[4])} ${pf(m[5])})`;
425
- }
426
- }
427
- return (
428
- `matrix(${pf(m[0])} ${pf(m[1])} ${pf(m[2])} ${pf(m[3])} ${pf(m[4])} ` +
429
- `${pf(m[5])})`
430
- );
431
- }
432
-
433
- // The counts below are relevant for all pages, so they have to be global
434
- // instead of being members of `SVGGraphics` (which is recreated for
435
- // each page).
436
- let clipCount = 0;
437
- let maskCount = 0;
438
- let shadingCount = 0;
439
-
440
- SVGGraphics = class {
441
- constructor(commonObjs, objs, forceDataSchema = false) {
442
- this.svgFactory = new DOMSVGFactory();
443
-
444
- this.current = new SVGExtraState();
445
- this.transformMatrix = IDENTITY_MATRIX; // Graphics state matrix
446
- this.transformStack = [];
447
- this.extraStack = [];
448
- this.commonObjs = commonObjs;
449
- this.objs = objs;
450
- this.pendingClip = null;
451
- this.pendingEOFill = false;
452
-
453
- this.embedFonts = false;
454
- this.embeddedFonts = Object.create(null);
455
- this.cssStyle = null;
456
- this.forceDataSchema = !!forceDataSchema;
457
-
458
- // In `src/shared/util.js` the operator names are mapped to IDs.
459
- // The list below represents the reverse of that, i.e., it maps IDs
460
- // to operator names.
461
- this._operatorIdMapping = [];
462
- for (const op in OPS) {
463
- this._operatorIdMapping[OPS[op]] = op;
464
- }
465
- }
466
-
467
- save() {
468
- this.transformStack.push(this.transformMatrix);
469
- const old = this.current;
470
- this.extraStack.push(old);
471
- this.current = old.clone();
472
- }
473
-
474
- restore() {
475
- this.transformMatrix = this.transformStack.pop();
476
- this.current = this.extraStack.pop();
477
- this.pendingClip = null;
478
- this.tgrp = null;
479
- }
480
-
481
- group(items) {
482
- this.save();
483
- this.executeOpTree(items);
484
- this.restore();
485
- }
486
-
487
- loadDependencies(operatorList) {
488
- const fnArray = operatorList.fnArray;
489
- const argsArray = operatorList.argsArray;
490
-
491
- for (let i = 0, ii = fnArray.length; i < ii; i++) {
492
- if (fnArray[i] !== OPS.dependency) {
493
- continue;
494
- }
495
-
496
- for (const obj of argsArray[i]) {
497
- const objsPool = obj.startsWith("g_") ? this.commonObjs : this.objs;
498
- const promise = new Promise(resolve => {
499
- objsPool.get(obj, resolve);
500
- });
501
- this.current.dependencies.push(promise);
502
- }
503
- }
504
- return Promise.all(this.current.dependencies);
505
- }
506
-
507
- transform(a, b, c, d, e, f) {
508
- const transformMatrix = [a, b, c, d, e, f];
509
- this.transformMatrix = Util.transform(
510
- this.transformMatrix,
511
- transformMatrix
512
- );
513
- this.tgrp = null;
514
- }
515
-
516
- getSVG(operatorList, viewport) {
517
- this.viewport = viewport;
518
-
519
- const svgElement = this._initialize(viewport);
520
- return this.loadDependencies(operatorList).then(() => {
521
- this.transformMatrix = IDENTITY_MATRIX;
522
- this.executeOpTree(this.convertOpList(operatorList));
523
- return svgElement;
524
- });
525
- }
526
-
527
- convertOpList(operatorList) {
528
- const operatorIdMapping = this._operatorIdMapping;
529
- const argsArray = operatorList.argsArray;
530
- const fnArray = operatorList.fnArray;
531
- const opList = [];
532
- for (let i = 0, ii = fnArray.length; i < ii; i++) {
533
- const fnId = fnArray[i];
534
- opList.push({
535
- fnId,
536
- fn: operatorIdMapping[fnId],
537
- args: argsArray[i],
538
- });
539
- }
540
- return opListToTree(opList);
541
- }
542
-
543
- executeOpTree(opTree) {
544
- for (const opTreeElement of opTree) {
545
- const fn = opTreeElement.fn;
546
- const fnId = opTreeElement.fnId;
547
- const args = opTreeElement.args;
548
-
549
- switch (fnId | 0) {
550
- case OPS.beginText:
551
- this.beginText();
552
- break;
553
- case OPS.dependency:
554
- // Handled in `loadDependencies`, so no warning should be shown.
555
- break;
556
- case OPS.setLeading:
557
- this.setLeading(args);
558
- break;
559
- case OPS.setLeadingMoveText:
560
- this.setLeadingMoveText(args[0], args[1]);
561
- break;
562
- case OPS.setFont:
563
- this.setFont(args);
564
- break;
565
- case OPS.showText:
566
- this.showText(args[0]);
567
- break;
568
- case OPS.showSpacedText:
569
- this.showText(args[0]);
570
- break;
571
- case OPS.endText:
572
- this.endText();
573
- break;
574
- case OPS.moveText:
575
- this.moveText(args[0], args[1]);
576
- break;
577
- case OPS.setCharSpacing:
578
- this.setCharSpacing(args[0]);
579
- break;
580
- case OPS.setWordSpacing:
581
- this.setWordSpacing(args[0]);
582
- break;
583
- case OPS.setHScale:
584
- this.setHScale(args[0]);
585
- break;
586
- case OPS.setTextMatrix:
587
- this.setTextMatrix(
588
- args[0],
589
- args[1],
590
- args[2],
591
- args[3],
592
- args[4],
593
- args[5]
594
- );
595
- break;
596
- case OPS.setTextRise:
597
- this.setTextRise(args[0]);
598
- break;
599
- case OPS.setTextRenderingMode:
600
- this.setTextRenderingMode(args[0]);
601
- break;
602
- case OPS.setLineWidth:
603
- this.setLineWidth(args[0]);
604
- break;
605
- case OPS.setLineJoin:
606
- this.setLineJoin(args[0]);
607
- break;
608
- case OPS.setLineCap:
609
- this.setLineCap(args[0]);
610
- break;
611
- case OPS.setMiterLimit:
612
- this.setMiterLimit(args[0]);
613
- break;
614
- case OPS.setFillRGBColor:
615
- this.setFillRGBColor(args[0], args[1], args[2]);
616
- break;
617
- case OPS.setStrokeRGBColor:
618
- this.setStrokeRGBColor(args[0], args[1], args[2]);
619
- break;
620
- case OPS.setStrokeColorN:
621
- this.setStrokeColorN(args);
622
- break;
623
- case OPS.setFillColorN:
624
- this.setFillColorN(args);
625
- break;
626
- case OPS.shadingFill:
627
- this.shadingFill(args[0]);
628
- break;
629
- case OPS.setDash:
630
- this.setDash(args[0], args[1]);
631
- break;
632
- case OPS.setRenderingIntent:
633
- this.setRenderingIntent(args[0]);
634
- break;
635
- case OPS.setFlatness:
636
- this.setFlatness(args[0]);
637
- break;
638
- case OPS.setGState:
639
- this.setGState(args[0]);
640
- break;
641
- case OPS.fill:
642
- this.fill();
643
- break;
644
- case OPS.eoFill:
645
- this.eoFill();
646
- break;
647
- case OPS.stroke:
648
- this.stroke();
649
- break;
650
- case OPS.fillStroke:
651
- this.fillStroke();
652
- break;
653
- case OPS.eoFillStroke:
654
- this.eoFillStroke();
655
- break;
656
- case OPS.clip:
657
- this.clip("nonzero");
658
- break;
659
- case OPS.eoClip:
660
- this.clip("evenodd");
661
- break;
662
- case OPS.paintSolidColorImageMask:
663
- this.paintSolidColorImageMask();
664
- break;
665
- case OPS.paintImageXObject:
666
- this.paintImageXObject(args[0]);
667
- break;
668
- case OPS.paintInlineImageXObject:
669
- this.paintInlineImageXObject(args[0]);
670
- break;
671
- case OPS.paintImageMaskXObject:
672
- this.paintImageMaskXObject(args[0]);
673
- break;
674
- case OPS.paintFormXObjectBegin:
675
- this.paintFormXObjectBegin(args[0], args[1]);
676
- break;
677
- case OPS.paintFormXObjectEnd:
678
- this.paintFormXObjectEnd();
679
- break;
680
- case OPS.closePath:
681
- this.closePath();
682
- break;
683
- case OPS.closeStroke:
684
- this.closeStroke();
685
- break;
686
- case OPS.closeFillStroke:
687
- this.closeFillStroke();
688
- break;
689
- case OPS.closeEOFillStroke:
690
- this.closeEOFillStroke();
691
- break;
692
- case OPS.nextLine:
693
- this.nextLine();
694
- break;
695
- case OPS.transform:
696
- this.transform(
697
- args[0],
698
- args[1],
699
- args[2],
700
- args[3],
701
- args[4],
702
- args[5]
703
- );
704
- break;
705
- case OPS.constructPath:
706
- this.constructPath(args[0], args[1]);
707
- break;
708
- case OPS.endPath:
709
- this.endPath();
710
- break;
711
- case 92:
712
- this.group(opTreeElement.items);
713
- break;
714
- default:
715
- warn(`Unimplemented operator ${fn}`);
716
- break;
717
- }
718
- }
719
- }
720
-
721
- setWordSpacing(wordSpacing) {
722
- this.current.wordSpacing = wordSpacing;
723
- }
724
-
725
- setCharSpacing(charSpacing) {
726
- this.current.charSpacing = charSpacing;
727
- }
728
-
729
- nextLine() {
730
- this.moveText(0, this.current.leading);
731
- }
732
-
733
- setTextMatrix(a, b, c, d, e, f) {
734
- const current = this.current;
735
- current.textMatrix = current.lineMatrix = [a, b, c, d, e, f];
736
- current.textMatrixScale = Math.hypot(a, b);
737
-
738
- current.x = current.lineX = 0;
739
- current.y = current.lineY = 0;
740
-
741
- current.xcoords = [];
742
- current.ycoords = [];
743
- current.tspan = this.svgFactory.createElement("svg:tspan");
744
- current.tspan.setAttributeNS(null, "font-family", current.fontFamily);
745
- current.tspan.setAttributeNS(
746
- null,
747
- "font-size",
748
- `${pf(current.fontSize)}px`
749
- );
750
- current.tspan.setAttributeNS(null, "y", pf(-current.y));
751
-
752
- current.txtElement = this.svgFactory.createElement("svg:text");
753
- current.txtElement.appendChild(current.tspan);
754
- }
755
-
756
- beginText() {
757
- const current = this.current;
758
- current.x = current.lineX = 0;
759
- current.y = current.lineY = 0;
760
- current.textMatrix = IDENTITY_MATRIX;
761
- current.lineMatrix = IDENTITY_MATRIX;
762
- current.textMatrixScale = 1;
763
- current.tspan = this.svgFactory.createElement("svg:tspan");
764
- current.txtElement = this.svgFactory.createElement("svg:text");
765
- current.txtgrp = this.svgFactory.createElement("svg:g");
766
- current.xcoords = [];
767
- current.ycoords = [];
768
- }
769
-
770
- moveText(x, y) {
771
- const current = this.current;
772
- current.x = current.lineX += x;
773
- current.y = current.lineY += y;
774
-
775
- current.xcoords = [];
776
- current.ycoords = [];
777
- current.tspan = this.svgFactory.createElement("svg:tspan");
778
- current.tspan.setAttributeNS(null, "font-family", current.fontFamily);
779
- current.tspan.setAttributeNS(
780
- null,
781
- "font-size",
782
- `${pf(current.fontSize)}px`
783
- );
784
- current.tspan.setAttributeNS(null, "y", pf(-current.y));
785
- }
786
-
787
- showText(glyphs) {
788
- const current = this.current;
789
- const font = current.font;
790
- const fontSize = current.fontSize;
791
- if (fontSize === 0) {
792
- return;
793
- }
794
-
795
- const fontSizeScale = current.fontSizeScale;
796
- const charSpacing = current.charSpacing;
797
- const wordSpacing = current.wordSpacing;
798
- const fontDirection = current.fontDirection;
799
- const textHScale = current.textHScale * fontDirection;
800
- const vertical = font.vertical;
801
- const spacingDir = vertical ? 1 : -1;
802
- const defaultVMetrics = font.defaultVMetrics;
803
- const widthAdvanceScale = fontSize * current.fontMatrix[0];
804
-
805
- let x = 0;
806
- for (const glyph of glyphs) {
807
- if (glyph === null) {
808
- // Word break
809
- x += fontDirection * wordSpacing;
810
- continue;
811
- } else if (isNum(glyph)) {
812
- x += (spacingDir * glyph * fontSize) / 1000;
813
- continue;
814
- }
815
-
816
- const spacing = (glyph.isSpace ? wordSpacing : 0) + charSpacing;
817
- const character = glyph.fontChar;
818
- let scaledX, scaledY;
819
- let width = glyph.width;
820
- if (vertical) {
821
- let vx;
822
- const vmetric = glyph.vmetric || defaultVMetrics;
823
- vx = glyph.vmetric ? vmetric[1] : width * 0.5;
824
- vx = -vx * widthAdvanceScale;
825
- const vy = vmetric[2] * widthAdvanceScale;
826
-
827
- width = vmetric ? -vmetric[0] : width;
828
- scaledX = vx / fontSizeScale;
829
- scaledY = (x + vy) / fontSizeScale;
830
- } else {
831
- scaledX = x / fontSizeScale;
832
- scaledY = 0;
833
- }
834
-
835
- if (glyph.isInFont || font.missingFile) {
836
- current.xcoords.push(current.x + scaledX);
837
- if (vertical) {
838
- current.ycoords.push(-current.y + scaledY);
839
- }
840
- current.tspan.textContent += character;
841
- } else {
842
- // TODO: To assist with text selection, we should replace the missing
843
- // character with a space character if charWidth is not zero.
844
- // But we cannot just do "character = ' '", because the ' ' character
845
- // might actually map to a different glyph.
846
- }
847
-
848
- let charWidth;
849
- if (vertical) {
850
- charWidth = width * widthAdvanceScale - spacing * fontDirection;
851
- } else {
852
- charWidth = width * widthAdvanceScale + spacing * fontDirection;
853
- }
854
-
855
- x += charWidth;
856
- }
857
- current.tspan.setAttributeNS(
858
- null,
859
- "x",
860
- current.xcoords.map(pf).join(" ")
861
- );
862
- if (vertical) {
863
- current.tspan.setAttributeNS(
864
- null,
865
- "y",
866
- current.ycoords.map(pf).join(" ")
867
- );
868
- } else {
869
- current.tspan.setAttributeNS(null, "y", pf(-current.y));
870
- }
871
-
872
- if (vertical) {
873
- current.y -= x;
874
- } else {
875
- current.x += x * textHScale;
876
- }
877
-
878
- current.tspan.setAttributeNS(null, "font-family", current.fontFamily);
879
- current.tspan.setAttributeNS(
880
- null,
881
- "font-size",
882
- `${pf(current.fontSize)}px`
883
- );
884
- if (current.fontStyle !== SVG_DEFAULTS.fontStyle) {
885
- current.tspan.setAttributeNS(null, "font-style", current.fontStyle);
886
- }
887
- if (current.fontWeight !== SVG_DEFAULTS.fontWeight) {
888
- current.tspan.setAttributeNS(null, "font-weight", current.fontWeight);
889
- }
890
-
891
- const fillStrokeMode =
892
- current.textRenderingMode & TextRenderingMode.FILL_STROKE_MASK;
893
- if (
894
- fillStrokeMode === TextRenderingMode.FILL ||
895
- fillStrokeMode === TextRenderingMode.FILL_STROKE
896
- ) {
897
- if (current.fillColor !== SVG_DEFAULTS.fillColor) {
898
- current.tspan.setAttributeNS(null, "fill", current.fillColor);
899
- }
900
- if (current.fillAlpha < 1) {
901
- current.tspan.setAttributeNS(null, "fill-opacity", current.fillAlpha);
902
- }
903
- } else if (current.textRenderingMode === TextRenderingMode.ADD_TO_PATH) {
904
- // Workaround for Firefox: We must set fill="transparent" because
905
- // fill="none" would generate an empty clipping path.
906
- current.tspan.setAttributeNS(null, "fill", "transparent");
907
- } else {
908
- current.tspan.setAttributeNS(null, "fill", "none");
909
- }
910
-
911
- if (
912
- fillStrokeMode === TextRenderingMode.STROKE ||
913
- fillStrokeMode === TextRenderingMode.FILL_STROKE
914
- ) {
915
- const lineWidthScale = 1 / (current.textMatrixScale || 1);
916
- this._setStrokeAttributes(current.tspan, lineWidthScale);
917
- }
918
-
919
- // Include the text rise in the text matrix since the `pm` function
920
- // creates the SVG element's `translate` entry (work on a copy to avoid
921
- // altering the original text matrix).
922
- let textMatrix = current.textMatrix;
923
- if (current.textRise !== 0) {
924
- textMatrix = textMatrix.slice();
925
- textMatrix[5] += current.textRise;
926
- }
927
-
928
- current.txtElement.setAttributeNS(
929
- null,
930
- "transform",
931
- `${pm(textMatrix)} scale(${pf(textHScale)}, -1)`
932
- );
933
- current.txtElement.setAttributeNS(XML_NS, "xml:space", "preserve");
934
- current.txtElement.appendChild(current.tspan);
935
- current.txtgrp.appendChild(current.txtElement);
936
-
937
- this._ensureTransformGroup().appendChild(current.txtElement);
938
- }
939
-
940
- setLeadingMoveText(x, y) {
941
- this.setLeading(-y);
942
- this.moveText(x, y);
943
- }
944
-
945
- addFontStyle(fontObj) {
946
- if (!fontObj.data) {
947
- throw new Error(
948
- "addFontStyle: No font data available, " +
949
- 'ensure that the "fontExtraProperties" API parameter is set.'
950
- );
951
- }
952
- if (!this.cssStyle) {
953
- this.cssStyle = this.svgFactory.createElement("svg:style");
954
- this.cssStyle.setAttributeNS(null, "type", "text/css");
955
- this.defs.appendChild(this.cssStyle);
956
- }
957
-
958
- const url = createObjectURL(
959
- fontObj.data,
960
- fontObj.mimetype,
961
- this.forceDataSchema
962
- );
963
- this.cssStyle.textContent +=
964
- `@font-face { font-family: "${fontObj.loadedName}";` +
965
- ` src: url(${url}); }\n`;
966
- }
967
-
968
- setFont(details) {
969
- const current = this.current;
970
- const fontObj = this.commonObjs.get(details[0]);
971
- let size = details[1];
972
- current.font = fontObj;
973
-
974
- if (
975
- this.embedFonts &&
976
- !fontObj.missingFile &&
977
- !this.embeddedFonts[fontObj.loadedName]
978
- ) {
979
- this.addFontStyle(fontObj);
980
- this.embeddedFonts[fontObj.loadedName] = fontObj;
981
- }
982
- current.fontMatrix = fontObj.fontMatrix || FONT_IDENTITY_MATRIX;
983
-
984
- let bold = "normal";
985
- if (fontObj.black) {
986
- bold = "900";
987
- } else if (fontObj.bold) {
988
- bold = "bold";
989
- }
990
- const italic = fontObj.italic ? "italic" : "normal";
991
-
992
- if (size < 0) {
993
- size = -size;
994
- current.fontDirection = -1;
995
- } else {
996
- current.fontDirection = 1;
997
- }
998
- current.fontSize = size;
999
- current.fontFamily = fontObj.loadedName;
1000
- current.fontWeight = bold;
1001
- current.fontStyle = italic;
1002
-
1003
- current.tspan = this.svgFactory.createElement("svg:tspan");
1004
- current.tspan.setAttributeNS(null, "y", pf(-current.y));
1005
- current.xcoords = [];
1006
- current.ycoords = [];
1007
- }
1008
-
1009
- endText() {
1010
- const current = this.current;
1011
- if (
1012
- current.textRenderingMode & TextRenderingMode.ADD_TO_PATH_FLAG &&
1013
- current.txtElement?.hasChildNodes()
1014
- ) {
1015
- // If no glyphs are shown (i.e. no child nodes), no clipping occurs.
1016
- current.element = current.txtElement;
1017
- this.clip("nonzero");
1018
- this.endPath();
1019
- }
1020
- }
1021
-
1022
- // Path properties
1023
- setLineWidth(width) {
1024
- if (width > 0) {
1025
- this.current.lineWidth = width;
1026
- }
1027
- }
1028
-
1029
- setLineCap(style) {
1030
- this.current.lineCap = LINE_CAP_STYLES[style];
1031
- }
1032
-
1033
- setLineJoin(style) {
1034
- this.current.lineJoin = LINE_JOIN_STYLES[style];
1035
- }
1036
-
1037
- setMiterLimit(limit) {
1038
- this.current.miterLimit = limit;
1039
- }
1040
-
1041
- setStrokeAlpha(strokeAlpha) {
1042
- this.current.strokeAlpha = strokeAlpha;
1043
- }
1044
-
1045
- setStrokeRGBColor(r, g, b) {
1046
- this.current.strokeColor = Util.makeHexColor(r, g, b);
1047
- }
1048
-
1049
- setFillAlpha(fillAlpha) {
1050
- this.current.fillAlpha = fillAlpha;
1051
- }
1052
-
1053
- setFillRGBColor(r, g, b) {
1054
- this.current.fillColor = Util.makeHexColor(r, g, b);
1055
- this.current.tspan = this.svgFactory.createElement("svg:tspan");
1056
- this.current.xcoords = [];
1057
- this.current.ycoords = [];
1058
- }
1059
-
1060
- setStrokeColorN(args) {
1061
- this.current.strokeColor = this._makeColorN_Pattern(args);
1062
- }
1063
-
1064
- setFillColorN(args) {
1065
- this.current.fillColor = this._makeColorN_Pattern(args);
1066
- }
1067
-
1068
- shadingFill(args) {
1069
- const width = this.viewport.width;
1070
- const height = this.viewport.height;
1071
- const inv = Util.inverseTransform(this.transformMatrix);
1072
- const bl = Util.applyTransform([0, 0], inv);
1073
- const br = Util.applyTransform([0, height], inv);
1074
- const ul = Util.applyTransform([width, 0], inv);
1075
- const ur = Util.applyTransform([width, height], inv);
1076
- const x0 = Math.min(bl[0], br[0], ul[0], ur[0]);
1077
- const y0 = Math.min(bl[1], br[1], ul[1], ur[1]);
1078
- const x1 = Math.max(bl[0], br[0], ul[0], ur[0]);
1079
- const y1 = Math.max(bl[1], br[1], ul[1], ur[1]);
1080
-
1081
- const rect = this.svgFactory.createElement("svg:rect");
1082
- rect.setAttributeNS(null, "x", x0);
1083
- rect.setAttributeNS(null, "y", y0);
1084
- rect.setAttributeNS(null, "width", x1 - x0);
1085
- rect.setAttributeNS(null, "height", y1 - y0);
1086
- rect.setAttributeNS(null, "fill", this._makeShadingPattern(args));
1087
- if (this.current.fillAlpha < 1) {
1088
- rect.setAttributeNS(null, "fill-opacity", this.current.fillAlpha);
1089
- }
1090
- this._ensureTransformGroup().appendChild(rect);
1091
- }
1092
-
1093
- /**
1094
- * @private
1095
- */
1096
- _makeColorN_Pattern(args) {
1097
- if (args[0] === "TilingPattern") {
1098
- return this._makeTilingPattern(args);
1099
- }
1100
- return this._makeShadingPattern(args);
1101
- }
1102
-
1103
- /**
1104
- * @private
1105
- */
1106
- _makeTilingPattern(args) {
1107
- const color = args[1];
1108
- const operatorList = args[2];
1109
- const matrix = args[3] || IDENTITY_MATRIX;
1110
- const [x0, y0, x1, y1] = args[4];
1111
- const xstep = args[5];
1112
- const ystep = args[6];
1113
- const paintType = args[7];
1114
-
1115
- const tilingId = `shading${shadingCount++}`;
1116
- const [tx0, ty0, tx1, ty1] = Util.normalizeRect([
1117
- ...Util.applyTransform([x0, y0], matrix),
1118
- ...Util.applyTransform([x1, y1], matrix),
1119
- ]);
1120
- const [xscale, yscale] = Util.singularValueDecompose2dScale(matrix);
1121
- const txstep = xstep * xscale;
1122
- const tystep = ystep * yscale;
1123
-
1124
- const tiling = this.svgFactory.createElement("svg:pattern");
1125
- tiling.setAttributeNS(null, "id", tilingId);
1126
- tiling.setAttributeNS(null, "patternUnits", "userSpaceOnUse");
1127
- tiling.setAttributeNS(null, "width", txstep);
1128
- tiling.setAttributeNS(null, "height", tystep);
1129
- tiling.setAttributeNS(null, "x", `${tx0}`);
1130
- tiling.setAttributeNS(null, "y", `${ty0}`);
1131
-
1132
- // Save current state.
1133
- const svg = this.svg;
1134
- const transformMatrix = this.transformMatrix;
1135
- const fillColor = this.current.fillColor;
1136
- const strokeColor = this.current.strokeColor;
1137
-
1138
- const bbox = this.svgFactory.create(tx1 - tx0, ty1 - ty0);
1139
- this.svg = bbox;
1140
- this.transformMatrix = matrix;
1141
- if (paintType === 2) {
1142
- const cssColor = Util.makeHexColor(...color);
1143
- this.current.fillColor = cssColor;
1144
- this.current.strokeColor = cssColor;
1145
- }
1146
- this.executeOpTree(this.convertOpList(operatorList));
1147
-
1148
- // Restore saved state.
1149
- this.svg = svg;
1150
- this.transformMatrix = transformMatrix;
1151
- this.current.fillColor = fillColor;
1152
- this.current.strokeColor = strokeColor;
1153
-
1154
- tiling.appendChild(bbox.childNodes[0]);
1155
- this.defs.appendChild(tiling);
1156
- return `url(#${tilingId})`;
1157
- }
1158
-
1159
- /**
1160
- * @private
1161
- */
1162
- _makeShadingPattern(args) {
1163
- switch (args[0]) {
1164
- case "RadialAxial":
1165
- const shadingId = `shading${shadingCount++}`;
1166
- const colorStops = args[3];
1167
- let gradient;
1168
-
1169
- switch (args[1]) {
1170
- case "axial":
1171
- const point0 = args[4];
1172
- const point1 = args[5];
1173
- gradient = this.svgFactory.createElement("svg:linearGradient");
1174
- gradient.setAttributeNS(null, "id", shadingId);
1175
- gradient.setAttributeNS(null, "gradientUnits", "userSpaceOnUse");
1176
- gradient.setAttributeNS(null, "x1", point0[0]);
1177
- gradient.setAttributeNS(null, "y1", point0[1]);
1178
- gradient.setAttributeNS(null, "x2", point1[0]);
1179
- gradient.setAttributeNS(null, "y2", point1[1]);
1180
- break;
1181
- case "radial":
1182
- const focalPoint = args[4];
1183
- const circlePoint = args[5];
1184
- const focalRadius = args[6];
1185
- const circleRadius = args[7];
1186
- gradient = this.svgFactory.createElement("svg:radialGradient");
1187
- gradient.setAttributeNS(null, "id", shadingId);
1188
- gradient.setAttributeNS(null, "gradientUnits", "userSpaceOnUse");
1189
- gradient.setAttributeNS(null, "cx", circlePoint[0]);
1190
- gradient.setAttributeNS(null, "cy", circlePoint[1]);
1191
- gradient.setAttributeNS(null, "r", circleRadius);
1192
- gradient.setAttributeNS(null, "fx", focalPoint[0]);
1193
- gradient.setAttributeNS(null, "fy", focalPoint[1]);
1194
- gradient.setAttributeNS(null, "fr", focalRadius);
1195
- break;
1196
- default:
1197
- throw new Error(`Unknown RadialAxial type: ${args[1]}`);
1198
- }
1199
- for (const colorStop of colorStops) {
1200
- const stop = this.svgFactory.createElement("svg:stop");
1201
- stop.setAttributeNS(null, "offset", colorStop[0]);
1202
- stop.setAttributeNS(null, "stop-color", colorStop[1]);
1203
- gradient.appendChild(stop);
1204
- }
1205
- this.defs.appendChild(gradient);
1206
- return `url(#${shadingId})`;
1207
- case "Mesh":
1208
- warn("Unimplemented pattern Mesh");
1209
- return null;
1210
- case "Dummy":
1211
- return "hotpink";
1212
- default:
1213
- throw new Error(`Unknown IR type: ${args[0]}`);
1214
- }
1215
- }
1216
-
1217
- setDash(dashArray, dashPhase) {
1218
- this.current.dashArray = dashArray;
1219
- this.current.dashPhase = dashPhase;
1220
- }
1221
-
1222
- constructPath(ops, args) {
1223
- const current = this.current;
1224
- let x = current.x,
1225
- y = current.y;
1226
- let d = [];
1227
- let j = 0;
1228
-
1229
- for (const op of ops) {
1230
- switch (op | 0) {
1231
- case OPS.rectangle:
1232
- x = args[j++];
1233
- y = args[j++];
1234
- const width = args[j++];
1235
- const height = args[j++];
1236
- const xw = x + width;
1237
- const yh = y + height;
1238
- d.push(
1239
- "M",
1240
- pf(x),
1241
- pf(y),
1242
- "L",
1243
- pf(xw),
1244
- pf(y),
1245
- "L",
1246
- pf(xw),
1247
- pf(yh),
1248
- "L",
1249
- pf(x),
1250
- pf(yh),
1251
- "Z"
1252
- );
1253
- break;
1254
- case OPS.moveTo:
1255
- x = args[j++];
1256
- y = args[j++];
1257
- d.push("M", pf(x), pf(y));
1258
- break;
1259
- case OPS.lineTo:
1260
- x = args[j++];
1261
- y = args[j++];
1262
- d.push("L", pf(x), pf(y));
1263
- break;
1264
- case OPS.curveTo:
1265
- x = args[j + 4];
1266
- y = args[j + 5];
1267
- d.push(
1268
- "C",
1269
- pf(args[j]),
1270
- pf(args[j + 1]),
1271
- pf(args[j + 2]),
1272
- pf(args[j + 3]),
1273
- pf(x),
1274
- pf(y)
1275
- );
1276
- j += 6;
1277
- break;
1278
- case OPS.curveTo2:
1279
- d.push(
1280
- "C",
1281
- pf(x),
1282
- pf(y),
1283
- pf(args[j]),
1284
- pf(args[j + 1]),
1285
- pf(args[j + 2]),
1286
- pf(args[j + 3])
1287
- );
1288
- x = args[j + 2];
1289
- y = args[j + 3];
1290
- j += 4;
1291
- break;
1292
- case OPS.curveTo3:
1293
- x = args[j + 2];
1294
- y = args[j + 3];
1295
- d.push(
1296
- "C",
1297
- pf(args[j]),
1298
- pf(args[j + 1]),
1299
- pf(x),
1300
- pf(y),
1301
- pf(x),
1302
- pf(y)
1303
- );
1304
- j += 4;
1305
- break;
1306
- case OPS.closePath:
1307
- d.push("Z");
1308
- break;
1309
- }
1310
- }
1311
-
1312
- d = d.join(" ");
1313
-
1314
- if (
1315
- current.path &&
1316
- ops.length > 0 &&
1317
- ops[0] !== OPS.rectangle &&
1318
- ops[0] !== OPS.moveTo
1319
- ) {
1320
- // If a path does not start with an OPS.rectangle or OPS.moveTo, it has
1321
- // probably been divided into two OPS.constructPath operators by
1322
- // OperatorList. Append the commands to the previous path element.
1323
- d = current.path.getAttributeNS(null, "d") + d;
1324
- } else {
1325
- current.path = this.svgFactory.createElement("svg:path");
1326
- this._ensureTransformGroup().appendChild(current.path);
1327
- }
1328
-
1329
- current.path.setAttributeNS(null, "d", d);
1330
- current.path.setAttributeNS(null, "fill", "none");
1331
-
1332
- // Saving a reference in current.element so that it can be addressed
1333
- // in 'fill' and 'stroke'
1334
- current.element = current.path;
1335
- current.setCurrentPoint(x, y);
1336
- }
1337
-
1338
- endPath() {
1339
- const current = this.current;
1340
-
1341
- // Painting operators end a path.
1342
- current.path = null;
1343
-
1344
- if (!this.pendingClip) {
1345
- return;
1346
- }
1347
- if (!current.element) {
1348
- this.pendingClip = null;
1349
- return;
1350
- }
1351
-
1352
- // Add the current path to a clipping path.
1353
- const clipId = `clippath${clipCount++}`;
1354
- const clipPath = this.svgFactory.createElement("svg:clipPath");
1355
- clipPath.setAttributeNS(null, "id", clipId);
1356
- clipPath.setAttributeNS(null, "transform", pm(this.transformMatrix));
1357
-
1358
- // A deep clone is needed when text is used as a clipping path.
1359
- const clipElement = current.element.cloneNode(true);
1360
- if (this.pendingClip === "evenodd") {
1361
- clipElement.setAttributeNS(null, "clip-rule", "evenodd");
1362
- } else {
1363
- clipElement.setAttributeNS(null, "clip-rule", "nonzero");
1364
- }
1365
- this.pendingClip = null;
1366
- clipPath.appendChild(clipElement);
1367
- this.defs.appendChild(clipPath);
1368
-
1369
- if (current.activeClipUrl) {
1370
- // The previous clipping group content can go out of order -- resetting
1371
- // cached clipGroups.
1372
- current.clipGroup = null;
1373
- for (const prev of this.extraStack) {
1374
- prev.clipGroup = null;
1375
- }
1376
- // Intersect with the previous clipping path.
1377
- clipPath.setAttributeNS(null, "clip-path", current.activeClipUrl);
1378
- }
1379
- current.activeClipUrl = `url(#${clipId})`;
1380
-
1381
- this.tgrp = null;
1382
- }
1383
-
1384
- clip(type) {
1385
- this.pendingClip = type;
1386
- }
1387
-
1388
- closePath() {
1389
- const current = this.current;
1390
- if (current.path) {
1391
- const d = `${current.path.getAttributeNS(null, "d")}Z`;
1392
- current.path.setAttributeNS(null, "d", d);
1393
- }
1394
- }
1395
-
1396
- setLeading(leading) {
1397
- this.current.leading = -leading;
1398
- }
1399
-
1400
- setTextRise(textRise) {
1401
- this.current.textRise = textRise;
1402
- }
1403
-
1404
- setTextRenderingMode(textRenderingMode) {
1405
- this.current.textRenderingMode = textRenderingMode;
1406
- }
1407
-
1408
- setHScale(scale) {
1409
- this.current.textHScale = scale / 100;
1410
- }
1411
-
1412
- setRenderingIntent(intent) {
1413
- // This operation is ignored since we haven't found a use case for it yet.
1414
- }
1415
-
1416
- setFlatness(flatness) {
1417
- // This operation is ignored since we haven't found a use case for it yet.
1418
- }
1419
-
1420
- setGState(states) {
1421
- for (const [key, value] of states) {
1422
- switch (key) {
1423
- case "LW":
1424
- this.setLineWidth(value);
1425
- break;
1426
- case "LC":
1427
- this.setLineCap(value);
1428
- break;
1429
- case "LJ":
1430
- this.setLineJoin(value);
1431
- break;
1432
- case "ML":
1433
- this.setMiterLimit(value);
1434
- break;
1435
- case "D":
1436
- this.setDash(value[0], value[1]);
1437
- break;
1438
- case "RI":
1439
- this.setRenderingIntent(value);
1440
- break;
1441
- case "FL":
1442
- this.setFlatness(value);
1443
- break;
1444
- case "Font":
1445
- this.setFont(value);
1446
- break;
1447
- case "CA":
1448
- this.setStrokeAlpha(value);
1449
- break;
1450
- case "ca":
1451
- this.setFillAlpha(value);
1452
- break;
1453
- default:
1454
- warn(`Unimplemented graphic state operator ${key}`);
1455
- break;
1456
- }
1457
- }
1458
- }
1459
-
1460
- fill() {
1461
- const current = this.current;
1462
- if (current.element) {
1463
- current.element.setAttributeNS(null, "fill", current.fillColor);
1464
- current.element.setAttributeNS(null, "fill-opacity", current.fillAlpha);
1465
- this.endPath();
1466
- }
1467
- }
1468
-
1469
- stroke() {
1470
- const current = this.current;
1471
- if (current.element) {
1472
- this._setStrokeAttributes(current.element);
1473
- current.element.setAttributeNS(null, "fill", "none");
1474
- this.endPath();
1475
- }
1476
- }
1477
-
1478
- /**
1479
- * @private
1480
- */
1481
- _setStrokeAttributes(element, lineWidthScale = 1) {
1482
- const current = this.current;
1483
- let dashArray = current.dashArray;
1484
- if (lineWidthScale !== 1 && dashArray.length > 0) {
1485
- dashArray = dashArray.map(function (value) {
1486
- return lineWidthScale * value;
1487
- });
1488
- }
1489
- element.setAttributeNS(null, "stroke", current.strokeColor);
1490
- element.setAttributeNS(null, "stroke-opacity", current.strokeAlpha);
1491
- element.setAttributeNS(null, "stroke-miterlimit", pf(current.miterLimit));
1492
- element.setAttributeNS(null, "stroke-linecap", current.lineCap);
1493
- element.setAttributeNS(null, "stroke-linejoin", current.lineJoin);
1494
- element.setAttributeNS(
1495
- null,
1496
- "stroke-width",
1497
- pf(lineWidthScale * current.lineWidth) + "px"
1498
- );
1499
- element.setAttributeNS(
1500
- null,
1501
- "stroke-dasharray",
1502
- dashArray.map(pf).join(" ")
1503
- );
1504
- element.setAttributeNS(
1505
- null,
1506
- "stroke-dashoffset",
1507
- pf(lineWidthScale * current.dashPhase) + "px"
1508
- );
1509
- }
1510
-
1511
- eoFill() {
1512
- if (this.current.element) {
1513
- this.current.element.setAttributeNS(null, "fill-rule", "evenodd");
1514
- }
1515
- this.fill();
1516
- }
1517
-
1518
- fillStroke() {
1519
- // Order is important since stroke wants fill to be none.
1520
- // First stroke, then if fill needed, it will be overwritten.
1521
- this.stroke();
1522
- this.fill();
1523
- }
1524
-
1525
- eoFillStroke() {
1526
- if (this.current.element) {
1527
- this.current.element.setAttributeNS(null, "fill-rule", "evenodd");
1528
- }
1529
- this.fillStroke();
1530
- }
1531
-
1532
- closeStroke() {
1533
- this.closePath();
1534
- this.stroke();
1535
- }
1536
-
1537
- closeFillStroke() {
1538
- this.closePath();
1539
- this.fillStroke();
1540
- }
1541
-
1542
- closeEOFillStroke() {
1543
- this.closePath();
1544
- this.eoFillStroke();
1545
- }
1546
-
1547
- paintSolidColorImageMask() {
1548
- const rect = this.svgFactory.createElement("svg:rect");
1549
- rect.setAttributeNS(null, "x", "0");
1550
- rect.setAttributeNS(null, "y", "0");
1551
- rect.setAttributeNS(null, "width", "1px");
1552
- rect.setAttributeNS(null, "height", "1px");
1553
- rect.setAttributeNS(null, "fill", this.current.fillColor);
1554
-
1555
- this._ensureTransformGroup().appendChild(rect);
1556
- }
1557
-
1558
- paintImageXObject(objId) {
1559
- const imgData = objId.startsWith("g_")
1560
- ? this.commonObjs.get(objId)
1561
- : this.objs.get(objId);
1562
- if (!imgData) {
1563
- warn(`Dependent image with object ID ${objId} is not ready yet`);
1564
- return;
1565
- }
1566
- this.paintInlineImageXObject(imgData);
1567
- }
1568
-
1569
- paintInlineImageXObject(imgData, mask) {
1570
- const width = imgData.width;
1571
- const height = imgData.height;
1572
-
1573
- const imgSrc = convertImgDataToPng(imgData, this.forceDataSchema, !!mask);
1574
- const cliprect = this.svgFactory.createElement("svg:rect");
1575
- cliprect.setAttributeNS(null, "x", "0");
1576
- cliprect.setAttributeNS(null, "y", "0");
1577
- cliprect.setAttributeNS(null, "width", pf(width));
1578
- cliprect.setAttributeNS(null, "height", pf(height));
1579
- this.current.element = cliprect;
1580
- this.clip("nonzero");
1581
-
1582
- const imgEl = this.svgFactory.createElement("svg:image");
1583
- imgEl.setAttributeNS(XLINK_NS, "xlink:href", imgSrc);
1584
- imgEl.setAttributeNS(null, "x", "0");
1585
- imgEl.setAttributeNS(null, "y", pf(-height));
1586
- imgEl.setAttributeNS(null, "width", pf(width) + "px");
1587
- imgEl.setAttributeNS(null, "height", pf(height) + "px");
1588
- imgEl.setAttributeNS(
1589
- null,
1590
- "transform",
1591
- `scale(${pf(1 / width)} ${pf(-1 / height)})`
1592
- );
1593
- if (mask) {
1594
- mask.appendChild(imgEl);
1595
- } else {
1596
- this._ensureTransformGroup().appendChild(imgEl);
1597
- }
1598
- }
1599
-
1600
- paintImageMaskXObject(imgData) {
1601
- const current = this.current;
1602
- const width = imgData.width;
1603
- const height = imgData.height;
1604
- const fillColor = current.fillColor;
1605
-
1606
- current.maskId = `mask${maskCount++}`;
1607
- const mask = this.svgFactory.createElement("svg:mask");
1608
- mask.setAttributeNS(null, "id", current.maskId);
1609
-
1610
- const rect = this.svgFactory.createElement("svg:rect");
1611
- rect.setAttributeNS(null, "x", "0");
1612
- rect.setAttributeNS(null, "y", "0");
1613
- rect.setAttributeNS(null, "width", pf(width));
1614
- rect.setAttributeNS(null, "height", pf(height));
1615
- rect.setAttributeNS(null, "fill", fillColor);
1616
- rect.setAttributeNS(null, "mask", `url(#${current.maskId})`);
1617
-
1618
- this.defs.appendChild(mask);
1619
- this._ensureTransformGroup().appendChild(rect);
1620
-
1621
- this.paintInlineImageXObject(imgData, mask);
1622
- }
1623
-
1624
- paintFormXObjectBegin(matrix, bbox) {
1625
- if (Array.isArray(matrix) && matrix.length === 6) {
1626
- this.transform(
1627
- matrix[0],
1628
- matrix[1],
1629
- matrix[2],
1630
- matrix[3],
1631
- matrix[4],
1632
- matrix[5]
1633
- );
1634
- }
1635
-
1636
- if (bbox) {
1637
- const width = bbox[2] - bbox[0];
1638
- const height = bbox[3] - bbox[1];
1639
-
1640
- const cliprect = this.svgFactory.createElement("svg:rect");
1641
- cliprect.setAttributeNS(null, "x", bbox[0]);
1642
- cliprect.setAttributeNS(null, "y", bbox[1]);
1643
- cliprect.setAttributeNS(null, "width", pf(width));
1644
- cliprect.setAttributeNS(null, "height", pf(height));
1645
- this.current.element = cliprect;
1646
- this.clip("nonzero");
1647
- this.endPath();
1648
- }
1649
- }
1650
-
1651
- paintFormXObjectEnd() {}
1652
-
1653
- /**
1654
- * @private
1655
- */
1656
- _initialize(viewport) {
1657
- const svg = this.svgFactory.create(viewport.width, viewport.height);
1658
-
1659
- // Create the definitions element.
1660
- const definitions = this.svgFactory.createElement("svg:defs");
1661
- svg.appendChild(definitions);
1662
- this.defs = definitions;
1663
-
1664
- // Create the root group element, which acts a container for all other
1665
- // groups and applies the viewport transform.
1666
- const rootGroup = this.svgFactory.createElement("svg:g");
1667
- rootGroup.setAttributeNS(null, "transform", pm(viewport.transform));
1668
- svg.appendChild(rootGroup);
1669
-
1670
- // For the construction of the SVG image we are only interested in the
1671
- // root group, so we expose it as the entry point of the SVG image for
1672
- // the other code in this class.
1673
- this.svg = rootGroup;
1674
-
1675
- return svg;
1676
- }
1677
-
1678
- /**
1679
- * @private
1680
- */
1681
- _ensureClipGroup() {
1682
- if (!this.current.clipGroup) {
1683
- const clipGroup = this.svgFactory.createElement("svg:g");
1684
- clipGroup.setAttributeNS(null, "clip-path", this.current.activeClipUrl);
1685
- this.svg.appendChild(clipGroup);
1686
- this.current.clipGroup = clipGroup;
1687
- }
1688
- return this.current.clipGroup;
1689
- }
1690
-
1691
- /**
1692
- * @private
1693
- */
1694
- _ensureTransformGroup() {
1695
- if (!this.tgrp) {
1696
- this.tgrp = this.svgFactory.createElement("svg:g");
1697
- this.tgrp.setAttributeNS(null, "transform", pm(this.transformMatrix));
1698
- if (this.current.activeClipUrl) {
1699
- this._ensureClipGroup().appendChild(this.tgrp);
1700
- } else {
1701
- this.svg.appendChild(this.tgrp);
1702
- }
1703
- }
1704
- return this.tgrp;
1705
- }
1706
- };
1707
- }
1708
-
1709
- export { SVGGraphics };