@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
@@ -0,0 +1,3598 @@
1
+ import { DEFAULT_SCALE, TextLayerMode, RendererType, CSS_UNITS, getOutputScale, approximateFraction, roundToDivide, watchScroll, PresentationModeState, UNKNOWN_SCALE, isValidRotation, SpreadMode, ScrollMode, scrollIntoView, isPortraitOrientation, MAX_AUTO_SCALE, SCROLLBAR_PADDING, VERTICAL_PADDING, DEFAULT_SCALE_VALUE, getVisibleElements, isValidScrollMode, isValidSpreadMode, moveToEndOfArray } from './ui_utils.js';
2
+ import { AnnotationLayer, SVGGraphics, renderTextLayer, XfaLayer, version } from './pdf.js';
3
+ import { RenderingStates, PDFRenderingQueue } from './pdf_rendering_queue.js';
4
+ import { NullL10n } from './l10n_utils.js';
5
+ import { l as createPromiseCapability, s as shadow } from './util.js';
6
+ import { R as RenderingCancelledException } from './display_utils.js';
7
+ import { SimpleLinkService } from './pdf_link_service.js';
8
+ import './message_handler.js';
9
+
10
+ /* Copyright 2014 Mozilla Foundation
11
+ *
12
+ * Licensed under the Apache License, Version 2.0 (the "License");
13
+ * you may not use this file except in compliance with the License.
14
+ * You may obtain a copy of the License at
15
+ *
16
+ * http://www.apache.org/licenses/LICENSE-2.0
17
+ *
18
+ * Unless required by applicable law or agreed to in writing, software
19
+ * distributed under the License is distributed on an "AS IS" BASIS,
20
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21
+ * See the License for the specific language governing permissions and
22
+ * limitations under the License.
23
+ */
24
+ /**
25
+ * @typedef {Object} AnnotationLayerBuilderOptions
26
+ * @property {HTMLDivElement} pageDiv
27
+ * @property {PDFPage} pdfPage
28
+ * @property {AnnotationStorage} [annotationStorage]
29
+ * @property {string} [imageResourcesPath] - Path for image resources, mainly
30
+ * for annotation icons. Include trailing slash.
31
+ * @property {boolean} renderInteractiveForms
32
+ * @property {IPDFLinkService} linkService
33
+ * @property {DownloadManager} downloadManager
34
+ * @property {IL10n} l10n - Localization service.
35
+ * @property {boolean} [enableScripting]
36
+ * @property {Promise<boolean>} [hasJSActionsPromise]
37
+ * @property {Object} [mouseState]
38
+ */
39
+
40
+ class AnnotationLayerBuilder {
41
+ /**
42
+ * @param {AnnotationLayerBuilderOptions} options
43
+ */
44
+ constructor({
45
+ pageDiv,
46
+ pdfPage,
47
+ linkService,
48
+ downloadManager,
49
+ annotationStorage = null,
50
+ imageResourcesPath = "",
51
+ renderInteractiveForms = true,
52
+ l10n = NullL10n,
53
+ enableScripting = false,
54
+ hasJSActionsPromise = null,
55
+ mouseState = null
56
+ }) {
57
+ this.pageDiv = pageDiv;
58
+ this.pdfPage = pdfPage;
59
+ this.linkService = linkService;
60
+ this.downloadManager = downloadManager;
61
+ this.imageResourcesPath = imageResourcesPath;
62
+ this.renderInteractiveForms = renderInteractiveForms;
63
+ this.l10n = l10n;
64
+ this.annotationStorage = annotationStorage;
65
+ this.enableScripting = enableScripting;
66
+ this._hasJSActionsPromise = hasJSActionsPromise;
67
+ this._mouseState = mouseState;
68
+ this.div = null;
69
+ this._cancelled = false;
70
+ }
71
+ /**
72
+ * @param {PageViewport} viewport
73
+ * @param {string} intent (default value is 'display')
74
+ * @returns {Promise<void>} A promise that is resolved when rendering of the
75
+ * annotations is complete.
76
+ */
77
+
78
+
79
+ render(viewport, intent = "display") {
80
+ return Promise.all([this.pdfPage.getAnnotations({
81
+ intent
82
+ }), this._hasJSActionsPromise]).then(([annotations, hasJSActions = false]) => {
83
+ if (this._cancelled) {
84
+ return;
85
+ }
86
+
87
+ if (annotations.length === 0) {
88
+ return;
89
+ }
90
+
91
+ const parameters = {
92
+ viewport: viewport.clone({
93
+ dontFlip: true
94
+ }),
95
+ div: this.div,
96
+ annotations,
97
+ page: this.pdfPage,
98
+ imageResourcesPath: this.imageResourcesPath,
99
+ renderInteractiveForms: this.renderInteractiveForms,
100
+ linkService: this.linkService,
101
+ downloadManager: this.downloadManager,
102
+ annotationStorage: this.annotationStorage,
103
+ enableScripting: this.enableScripting,
104
+ hasJSActions,
105
+ mouseState: this._mouseState
106
+ };
107
+
108
+ if (this.div) {
109
+ // If an annotationLayer already exists, refresh its children's
110
+ // transformation matrices.
111
+ AnnotationLayer.update(parameters);
112
+ } else {
113
+ // Create an annotation layer div and render the annotations
114
+ // if there is at least one annotation.
115
+ this.div = document.createElement("div");
116
+ this.div.className = "annotationLayer";
117
+ this.pageDiv.appendChild(this.div);
118
+ parameters.div = this.div;
119
+ AnnotationLayer.render(parameters);
120
+ this.l10n.translate(this.div);
121
+ }
122
+ });
123
+ }
124
+
125
+ cancel() {
126
+ this._cancelled = true;
127
+ }
128
+
129
+ hide() {
130
+ if (!this.div) {
131
+ return;
132
+ }
133
+
134
+ this.div.hidden = true;
135
+ }
136
+
137
+ }
138
+
139
+ /* Copyright 2018 Mozilla Foundation
140
+ *
141
+ * Licensed under the Apache License, Version 2.0 (the "License");
142
+ * you may not use this file except in compliance with the License.
143
+ * You may obtain a copy of the License at
144
+ *
145
+ * http://www.apache.org/licenses/LICENSE-2.0
146
+ *
147
+ * Unless required by applicable law or agreed to in writing, software
148
+ * distributed under the License is distributed on an "AS IS" BASIS,
149
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
150
+ * See the License for the specific language governing permissions and
151
+ * limitations under the License.
152
+ */
153
+ const compatibilityParams = Object.create(null);
154
+
155
+ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("GENERIC")) {
156
+ const userAgent = typeof navigator !== "undefined" && navigator.userAgent || "";
157
+ const platform = typeof navigator !== "undefined" && navigator.platform || "";
158
+ const maxTouchPoints = typeof navigator !== "undefined" && navigator.maxTouchPoints || 1;
159
+ const isAndroid = /Android/.test(userAgent);
160
+ const isIOS = /\b(iPad|iPhone|iPod)(?=;)/.test(userAgent) || platform === "MacIntel" && maxTouchPoints > 1;
161
+ const isIOSChrome = /CriOS/.test(userAgent); // Checks if possible to use URL.createObjectURL()
162
+ // Support: IE, Chrome on iOS
163
+
164
+ (function checkOnBlobSupport() {
165
+ // Sometimes Chrome on iOS loses data created with createObjectURL(),
166
+ // see issue #8081.
167
+ if (isIOSChrome) {
168
+ compatibilityParams.disableCreateObjectURL = true;
169
+ }
170
+ })(); // Limit canvas size to 5 mega-pixels on mobile.
171
+ // Support: Android, iOS
172
+
173
+
174
+ (function checkCanvasSizeLimitation() {
175
+ if (isIOS || isAndroid) {
176
+ compatibilityParams.maxCanvasPixels = 5242880;
177
+ }
178
+ })();
179
+ }
180
+
181
+ const viewerCompatibilityParams = Object.freeze(compatibilityParams);
182
+
183
+ /* Copyright 2012 Mozilla Foundation
184
+ *
185
+ * Licensed under the Apache License, Version 2.0 (the "License");
186
+ * you may not use this file except in compliance with the License.
187
+ * You may obtain a copy of the License at
188
+ *
189
+ * http://www.apache.org/licenses/LICENSE-2.0
190
+ *
191
+ * Unless required by applicable law or agreed to in writing, software
192
+ * distributed under the License is distributed on an "AS IS" BASIS,
193
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
194
+ * See the License for the specific language governing permissions and
195
+ * limitations under the License.
196
+ */
197
+ /**
198
+ * @typedef {Object} PDFPageViewOptions
199
+ * @property {HTMLDivElement} container - The viewer element.
200
+ * @property {EventBus} eventBus - The application event bus.
201
+ * @property {number} id - The page unique ID (normally its number).
202
+ * @property {number} scale - The page scale display.
203
+ * @property {PageViewport} defaultViewport - The page viewport.
204
+ * @property {Promise<OptionalContentConfig>} [optionalContentConfigPromise] -
205
+ * A promise that is resolved with an {@link OptionalContentConfig} instance.
206
+ * The default value is `null`.
207
+ * @property {PDFRenderingQueue} renderingQueue - The rendering queue object.
208
+ * @property {IPDFTextLayerFactory} textLayerFactory
209
+ * @property {number} [textLayerMode] - Controls if the text layer used for
210
+ * selection and searching is created, and if the improved text selection
211
+ * behaviour is enabled. The constants from {TextLayerMode} should be used.
212
+ * The default value is `TextLayerMode.ENABLE`.
213
+ * @property {IPDFAnnotationLayerFactory} annotationLayerFactory
214
+ * @property {IPDFXfaLayerFactory} xfaLayerFactory
215
+ * @property {IPDFStructTreeLayerFactory} structTreeLayerFactory
216
+ * @property {string} [imageResourcesPath] - Path for image resources, mainly
217
+ * for annotation icons. Include trailing slash.
218
+ * @property {boolean} renderInteractiveForms - Turns on rendering of
219
+ * interactive form elements. The default value is `true`.
220
+ * @property {string} renderer - 'canvas' or 'svg'. The default is 'canvas'.
221
+ * @property {boolean} [useOnlyCssZoom] - Enables CSS only zooming. The default
222
+ * value is `false`.
223
+ * @property {number} [maxCanvasPixels] - The maximum supported canvas size in
224
+ * total pixels, i.e. width * height. Use -1 for no limit. The default value
225
+ * is 4096 * 4096 (16 mega-pixels).
226
+ * @property {IL10n} l10n - Localization service.
227
+ */
228
+
229
+ const MAX_CANVAS_PIXELS = viewerCompatibilityParams.maxCanvasPixels || 16777216;
230
+ /**
231
+ * @implements {IRenderableView}
232
+ */
233
+
234
+ class PDFPageView {
235
+ /**
236
+ * @param {PDFPageViewOptions} options
237
+ */
238
+ constructor(options) {
239
+ const container = options.container;
240
+ const defaultViewport = options.defaultViewport;
241
+ this.id = options.id;
242
+ this.renderingId = "page" + this.id;
243
+ this.pdfPage = null;
244
+ this.pageLabel = null;
245
+ this.rotation = 0;
246
+ this.scale = options.scale || DEFAULT_SCALE;
247
+ this.viewport = defaultViewport;
248
+ this.pdfPageRotate = defaultViewport.rotation;
249
+ this._optionalContentConfigPromise = options.optionalContentConfigPromise || null;
250
+ this.hasRestrictedScaling = false;
251
+ this.textLayerMode = Number.isInteger(options.textLayerMode) ? options.textLayerMode : TextLayerMode.ENABLE;
252
+ this.imageResourcesPath = options.imageResourcesPath || "";
253
+ this.renderInteractiveForms = options.renderInteractiveForms !== false;
254
+ this.useOnlyCssZoom = options.useOnlyCssZoom || false;
255
+ this.maxCanvasPixels = options.maxCanvasPixels || MAX_CANVAS_PIXELS;
256
+ this.eventBus = options.eventBus;
257
+ this.renderingQueue = options.renderingQueue;
258
+ this.textLayerFactory = options.textLayerFactory;
259
+ this.annotationLayerFactory = options.annotationLayerFactory;
260
+ this.xfaLayerFactory = options.xfaLayerFactory;
261
+ this.structTreeLayerFactory = options.structTreeLayerFactory;
262
+ this.renderer = options.renderer || RendererType.CANVAS;
263
+ this.l10n = options.l10n || NullL10n;
264
+ this.paintTask = null;
265
+ this.paintedViewportMap = new WeakMap();
266
+ this.renderingState = RenderingStates.INITIAL;
267
+ this.resume = null;
268
+ this._renderError = null;
269
+ this.annotationLayer = null;
270
+ this.textLayer = null;
271
+ this.zoomLayer = null;
272
+ this.xfaLayer = null;
273
+ this.structTreeLayer = null;
274
+ const div = document.createElement("div");
275
+ div.className = "page";
276
+ div.style.width = Math.floor(this.viewport.width) + "px";
277
+ div.style.height = Math.floor(this.viewport.height) + "px";
278
+ div.setAttribute("data-page-number", this.id);
279
+ div.setAttribute("role", "region");
280
+ this.l10n.get("page_landmark", {
281
+ page: this.id
282
+ }).then(msg => {
283
+ div.setAttribute("aria-label", msg);
284
+ });
285
+ this.div = div;
286
+ container.appendChild(div);
287
+ }
288
+
289
+ setPdfPage(pdfPage) {
290
+ this.pdfPage = pdfPage;
291
+ this.pdfPageRotate = pdfPage.rotate;
292
+ const totalRotation = (this.rotation + this.pdfPageRotate) % 360;
293
+ this.viewport = pdfPage.getViewport({
294
+ scale: this.scale * CSS_UNITS,
295
+ rotation: totalRotation
296
+ });
297
+ this.reset();
298
+ }
299
+
300
+ destroy() {
301
+ this.reset();
302
+
303
+ if (this.pdfPage) {
304
+ this.pdfPage.cleanup();
305
+ }
306
+ }
307
+ /**
308
+ * @private
309
+ */
310
+
311
+
312
+ async _renderAnnotationLayer() {
313
+ let error = null;
314
+
315
+ try {
316
+ await this.annotationLayer.render(this.viewport, "display");
317
+ } catch (ex) {
318
+ error = ex;
319
+ } finally {
320
+ this.eventBus.dispatch("annotationlayerrendered", {
321
+ source: this,
322
+ pageNumber: this.id,
323
+ error
324
+ });
325
+ }
326
+ }
327
+ /**
328
+ * @private
329
+ */
330
+
331
+
332
+ async _renderXfaLayer() {
333
+ let error = null;
334
+
335
+ try {
336
+ await this.xfaLayer.render(this.viewport, "display");
337
+ } catch (ex) {
338
+ error = ex;
339
+ } finally {
340
+ this.eventBus.dispatch("xfalayerrendered", {
341
+ source: this,
342
+ pageNumber: this.id,
343
+ error
344
+ });
345
+ }
346
+ }
347
+ /**
348
+ * @private
349
+ */
350
+
351
+
352
+ _resetZoomLayer(removeFromDOM = false) {
353
+ if (!this.zoomLayer) {
354
+ return;
355
+ }
356
+
357
+ const zoomLayerCanvas = this.zoomLayer.firstChild;
358
+ this.paintedViewportMap.delete(zoomLayerCanvas); // Zeroing the width and height causes Firefox to release graphics
359
+ // resources immediately, which can greatly reduce memory consumption.
360
+
361
+ zoomLayerCanvas.width = 0;
362
+ zoomLayerCanvas.height = 0;
363
+
364
+ if (removeFromDOM) {
365
+ // Note: `ChildNode.remove` doesn't throw if the parent node is undefined.
366
+ this.zoomLayer.remove();
367
+ }
368
+
369
+ this.zoomLayer = null;
370
+ }
371
+
372
+ reset({
373
+ keepZoomLayer = false,
374
+ keepAnnotationLayer = false,
375
+ keepXfaLayer = false
376
+ } = {}) {
377
+ var _this$annotationLayer, _this$xfaLayer;
378
+
379
+ this.cancelRendering({
380
+ keepAnnotationLayer,
381
+ keepXfaLayer
382
+ });
383
+ this.renderingState = RenderingStates.INITIAL;
384
+ const div = this.div;
385
+ div.style.width = Math.floor(this.viewport.width) + "px";
386
+ div.style.height = Math.floor(this.viewport.height) + "px";
387
+ const childNodes = div.childNodes,
388
+ zoomLayerNode = keepZoomLayer && this.zoomLayer || null,
389
+ annotationLayerNode = keepAnnotationLayer && ((_this$annotationLayer = this.annotationLayer) === null || _this$annotationLayer === void 0 ? void 0 : _this$annotationLayer.div) || null,
390
+ xfaLayerNode = keepXfaLayer && ((_this$xfaLayer = this.xfaLayer) === null || _this$xfaLayer === void 0 ? void 0 : _this$xfaLayer.div) || null;
391
+
392
+ for (let i = childNodes.length - 1; i >= 0; i--) {
393
+ const node = childNodes[i];
394
+
395
+ switch (node) {
396
+ case zoomLayerNode:
397
+ case annotationLayerNode:
398
+ case xfaLayerNode:
399
+ continue;
400
+ }
401
+
402
+ div.removeChild(node);
403
+ }
404
+
405
+ div.removeAttribute("data-loaded");
406
+
407
+ if (annotationLayerNode) {
408
+ // Hide the annotation layer until all elements are resized
409
+ // so they are not displayed on the already resized page.
410
+ this.annotationLayer.hide();
411
+ }
412
+
413
+ if (xfaLayerNode) {
414
+ // Hide the XFA layer until all elements are resized
415
+ // so they are not displayed on the already resized page.
416
+ this.xfaLayer.hide();
417
+ }
418
+
419
+ if (!zoomLayerNode) {
420
+ if (this.canvas) {
421
+ this.paintedViewportMap.delete(this.canvas); // Zeroing the width and height causes Firefox to release graphics
422
+ // resources immediately, which can greatly reduce memory consumption.
423
+
424
+ this.canvas.width = 0;
425
+ this.canvas.height = 0;
426
+ delete this.canvas;
427
+ }
428
+
429
+ this._resetZoomLayer();
430
+ }
431
+
432
+ if (this.svg) {
433
+ this.paintedViewportMap.delete(this.svg);
434
+ delete this.svg;
435
+ }
436
+
437
+ this.loadingIconDiv = document.createElement("div");
438
+ this.loadingIconDiv.className = "loadingIcon";
439
+ this.loadingIconDiv.setAttribute("role", "img");
440
+ this.l10n.get("loading").then(msg => {
441
+ var _this$loadingIconDiv;
442
+
443
+ (_this$loadingIconDiv = this.loadingIconDiv) === null || _this$loadingIconDiv === void 0 ? void 0 : _this$loadingIconDiv.setAttribute("aria-label", msg);
444
+ });
445
+ div.appendChild(this.loadingIconDiv);
446
+ }
447
+
448
+ update(scale, rotation, optionalContentConfigPromise = null) {
449
+ this.scale = scale || this.scale; // The rotation may be zero.
450
+
451
+ if (typeof rotation !== "undefined") {
452
+ this.rotation = rotation;
453
+ }
454
+
455
+ if (optionalContentConfigPromise instanceof Promise) {
456
+ this._optionalContentConfigPromise = optionalContentConfigPromise;
457
+ }
458
+
459
+ const totalRotation = (this.rotation + this.pdfPageRotate) % 360;
460
+ this.viewport = this.viewport.clone({
461
+ scale: this.scale * CSS_UNITS,
462
+ rotation: totalRotation
463
+ });
464
+
465
+ if (this.svg) {
466
+ this.cssTransform({
467
+ target: this.svg,
468
+ redrawAnnotationLayer: true,
469
+ redrawXfaLayer: true
470
+ });
471
+ this.eventBus.dispatch("pagerendered", {
472
+ source: this,
473
+ pageNumber: this.id,
474
+ cssTransform: true,
475
+ timestamp: performance.now(),
476
+ error: this._renderError
477
+ });
478
+ return;
479
+ }
480
+
481
+ let isScalingRestricted = false;
482
+
483
+ if (this.canvas && this.maxCanvasPixels > 0) {
484
+ const outputScale = this.outputScale;
485
+
486
+ if ((Math.floor(this.viewport.width) * outputScale.sx | 0) * (Math.floor(this.viewport.height) * outputScale.sy | 0) > this.maxCanvasPixels) {
487
+ isScalingRestricted = true;
488
+ }
489
+ }
490
+
491
+ if (this.canvas) {
492
+ if (this.useOnlyCssZoom || this.hasRestrictedScaling && isScalingRestricted) {
493
+ this.cssTransform({
494
+ target: this.canvas,
495
+ redrawAnnotationLayer: true,
496
+ redrawXfaLayer: true
497
+ });
498
+ this.eventBus.dispatch("pagerendered", {
499
+ source: this,
500
+ pageNumber: this.id,
501
+ cssTransform: true,
502
+ timestamp: performance.now(),
503
+ error: this._renderError
504
+ });
505
+ return;
506
+ }
507
+
508
+ if (!this.zoomLayer && !this.canvas.hidden) {
509
+ this.zoomLayer = this.canvas.parentNode;
510
+ this.zoomLayer.style.position = "absolute";
511
+ }
512
+ }
513
+
514
+ if (this.zoomLayer) {
515
+ this.cssTransform({
516
+ target: this.zoomLayer.firstChild
517
+ });
518
+ }
519
+
520
+ this.reset({
521
+ keepZoomLayer: true,
522
+ keepAnnotationLayer: true,
523
+ keepXfaLayer: true
524
+ });
525
+ }
526
+ /**
527
+ * PLEASE NOTE: Most likely you want to use the `this.reset()` method,
528
+ * rather than calling this one directly.
529
+ */
530
+
531
+
532
+ cancelRendering({
533
+ keepAnnotationLayer = false,
534
+ keepXfaLayer = false
535
+ } = {}) {
536
+ if (this.paintTask) {
537
+ this.paintTask.cancel();
538
+ this.paintTask = null;
539
+ }
540
+
541
+ this.resume = null;
542
+
543
+ if (this.textLayer) {
544
+ this.textLayer.cancel();
545
+ this.textLayer = null;
546
+ }
547
+
548
+ if (this.annotationLayer && (!keepAnnotationLayer || !this.annotationLayer.div)) {
549
+ this.annotationLayer.cancel();
550
+ this.annotationLayer = null;
551
+ }
552
+
553
+ if (this.xfaLayer && (!keepXfaLayer || !this.xfaLayer.div)) {
554
+ this.xfaLayer.cancel();
555
+ this.xfaLayer = null;
556
+ }
557
+
558
+ if (this._onTextLayerRendered) {
559
+ this.eventBus._off("textlayerrendered", this._onTextLayerRendered);
560
+
561
+ this._onTextLayerRendered = null;
562
+ }
563
+ }
564
+
565
+ cssTransform({
566
+ target,
567
+ redrawAnnotationLayer = false,
568
+ redrawXfaLayer = false
569
+ }) {
570
+ // Scale target (canvas or svg), its wrapper and page container.
571
+ const width = this.viewport.width;
572
+ const height = this.viewport.height;
573
+ const div = this.div;
574
+ target.style.width = target.parentNode.style.width = div.style.width = Math.floor(width) + "px";
575
+ target.style.height = target.parentNode.style.height = div.style.height = Math.floor(height) + "px"; // The canvas may have been originally rotated; rotate relative to that.
576
+
577
+ const relativeRotation = this.viewport.rotation - this.paintedViewportMap.get(target).rotation;
578
+ const absRotation = Math.abs(relativeRotation);
579
+ let scaleX = 1,
580
+ scaleY = 1;
581
+
582
+ if (absRotation === 90 || absRotation === 270) {
583
+ // Scale x and y because of the rotation.
584
+ scaleX = height / width;
585
+ scaleY = width / height;
586
+ }
587
+
588
+ target.style.transform = `rotate(${relativeRotation}deg) scale(${scaleX}, ${scaleY})`;
589
+
590
+ if (this.textLayer) {
591
+ // Rotating the text layer is more complicated since the divs inside the
592
+ // the text layer are rotated.
593
+ // TODO: This could probably be simplified by drawing the text layer in
594
+ // one orientation and then rotating overall.
595
+ const textLayerViewport = this.textLayer.viewport;
596
+ const textRelativeRotation = this.viewport.rotation - textLayerViewport.rotation;
597
+ const textAbsRotation = Math.abs(textRelativeRotation);
598
+ let scale = width / textLayerViewport.width;
599
+
600
+ if (textAbsRotation === 90 || textAbsRotation === 270) {
601
+ scale = width / textLayerViewport.height;
602
+ }
603
+
604
+ const textLayerDiv = this.textLayer.textLayerDiv;
605
+ let transX, transY;
606
+
607
+ switch (textAbsRotation) {
608
+ case 0:
609
+ transX = transY = 0;
610
+ break;
611
+
612
+ case 90:
613
+ transX = 0;
614
+ transY = "-" + textLayerDiv.style.height;
615
+ break;
616
+
617
+ case 180:
618
+ transX = "-" + textLayerDiv.style.width;
619
+ transY = "-" + textLayerDiv.style.height;
620
+ break;
621
+
622
+ case 270:
623
+ transX = "-" + textLayerDiv.style.width;
624
+ transY = 0;
625
+ break;
626
+
627
+ default:
628
+ console.error("Bad rotation value.");
629
+ break;
630
+ }
631
+
632
+ textLayerDiv.style.transform = `rotate(${textAbsRotation}deg) ` + `scale(${scale}) ` + `translate(${transX}, ${transY})`;
633
+ textLayerDiv.style.transformOrigin = "0% 0%";
634
+ }
635
+
636
+ if (redrawAnnotationLayer && this.annotationLayer) {
637
+ this._renderAnnotationLayer();
638
+ }
639
+
640
+ if (redrawXfaLayer && this.xfaLayer) {
641
+ this._renderXfaLayer();
642
+ }
643
+ }
644
+
645
+ get width() {
646
+ return this.viewport.width;
647
+ }
648
+
649
+ get height() {
650
+ return this.viewport.height;
651
+ }
652
+
653
+ getPagePoint(x, y) {
654
+ return this.viewport.convertToPdfPoint(x, y);
655
+ }
656
+
657
+ draw() {
658
+ var _this$annotationLayer2, _this$xfaLayer2;
659
+
660
+ if (this.renderingState !== RenderingStates.INITIAL) {
661
+ console.error("Must be in new state before drawing");
662
+ this.reset(); // Ensure that we reset all state to prevent issues.
663
+ }
664
+
665
+ const {
666
+ div,
667
+ pdfPage
668
+ } = this;
669
+
670
+ if (!pdfPage) {
671
+ this.renderingState = RenderingStates.FINISHED;
672
+
673
+ if (this.loadingIconDiv) {
674
+ div.removeChild(this.loadingIconDiv);
675
+ delete this.loadingIconDiv;
676
+ }
677
+
678
+ return Promise.reject(new Error("pdfPage is not loaded"));
679
+ }
680
+
681
+ this.renderingState = RenderingStates.RUNNING; // Wrap the canvas so that if it has a CSS transform for high DPI the
682
+ // overflow will be hidden in Firefox.
683
+
684
+ const canvasWrapper = document.createElement("div");
685
+ canvasWrapper.style.width = div.style.width;
686
+ canvasWrapper.style.height = div.style.height;
687
+ canvasWrapper.classList.add("canvasWrapper");
688
+
689
+ if ((_this$annotationLayer2 = this.annotationLayer) !== null && _this$annotationLayer2 !== void 0 && _this$annotationLayer2.div) {
690
+ // The annotation layer needs to stay on top.
691
+ div.insertBefore(canvasWrapper, this.annotationLayer.div);
692
+ } else {
693
+ div.appendChild(canvasWrapper);
694
+ }
695
+
696
+ let textLayer = null;
697
+
698
+ if (this.textLayerMode !== TextLayerMode.DISABLE && this.textLayerFactory) {
699
+ var _this$annotationLayer3;
700
+
701
+ const textLayerDiv = document.createElement("div");
702
+ textLayerDiv.className = "textLayer";
703
+ textLayerDiv.style.width = canvasWrapper.style.width;
704
+ textLayerDiv.style.height = canvasWrapper.style.height;
705
+
706
+ if ((_this$annotationLayer3 = this.annotationLayer) !== null && _this$annotationLayer3 !== void 0 && _this$annotationLayer3.div) {
707
+ // The annotation layer needs to stay on top.
708
+ div.insertBefore(textLayerDiv, this.annotationLayer.div);
709
+ } else {
710
+ div.appendChild(textLayerDiv);
711
+ }
712
+
713
+ textLayer = this.textLayerFactory.createTextLayerBuilder(textLayerDiv, this.id - 1, this.viewport, this.textLayerMode === TextLayerMode.ENABLE_ENHANCE, this.eventBus);
714
+ }
715
+
716
+ this.textLayer = textLayer;
717
+
718
+ if ((_this$xfaLayer2 = this.xfaLayer) !== null && _this$xfaLayer2 !== void 0 && _this$xfaLayer2.div) {
719
+ // The xfa layer needs to stay on top.
720
+ div.appendChild(this.xfaLayer.div);
721
+ }
722
+
723
+ let renderContinueCallback = null;
724
+
725
+ if (this.renderingQueue) {
726
+ renderContinueCallback = cont => {
727
+ if (!this.renderingQueue.isHighestPriority(this)) {
728
+ this.renderingState = RenderingStates.PAUSED;
729
+
730
+ this.resume = () => {
731
+ this.renderingState = RenderingStates.RUNNING;
732
+ cont();
733
+ };
734
+
735
+ return;
736
+ }
737
+
738
+ cont();
739
+ };
740
+ }
741
+
742
+ const finishPaintTask = async (error = null) => {
743
+ // The paintTask may have been replaced by a new one, so only remove
744
+ // the reference to the paintTask if it matches the one that is
745
+ // triggering this callback.
746
+ if (paintTask === this.paintTask) {
747
+ this.paintTask = null;
748
+ }
749
+
750
+ if (error instanceof RenderingCancelledException) {
751
+ this._renderError = null;
752
+ return;
753
+ }
754
+
755
+ this._renderError = error;
756
+ this.renderingState = RenderingStates.FINISHED;
757
+
758
+ if (this.loadingIconDiv) {
759
+ div.removeChild(this.loadingIconDiv);
760
+ delete this.loadingIconDiv;
761
+ }
762
+
763
+ this._resetZoomLayer(
764
+ /* removeFromDOM = */
765
+ true);
766
+
767
+ this.eventBus.dispatch("pagerendered", {
768
+ source: this,
769
+ pageNumber: this.id,
770
+ cssTransform: false,
771
+ timestamp: performance.now(),
772
+ error: this._renderError
773
+ });
774
+
775
+ if (error) {
776
+ throw error;
777
+ }
778
+ };
779
+
780
+ const paintTask = this.renderer === RendererType.SVG ? this.paintOnSvg(canvasWrapper) : this.paintOnCanvas(canvasWrapper);
781
+ paintTask.onRenderContinue = renderContinueCallback;
782
+ this.paintTask = paintTask;
783
+ const resultPromise = paintTask.promise.then(() => {
784
+ return finishPaintTask(null).then(() => {
785
+ if (textLayer) {
786
+ const readableStream = pdfPage.streamTextContent({
787
+ normalizeWhitespace: true,
788
+ includeMarkedContent: true
789
+ });
790
+ textLayer.setTextContentStream(readableStream);
791
+ textLayer.render();
792
+ }
793
+ });
794
+ }, function (reason) {
795
+ return finishPaintTask(reason);
796
+ });
797
+
798
+ if (this.annotationLayerFactory) {
799
+ if (!this.annotationLayer) {
800
+ this.annotationLayer = this.annotationLayerFactory.createAnnotationLayerBuilder(div, pdfPage,
801
+ /* annotationStorage = */
802
+ null, this.imageResourcesPath, this.renderInteractiveForms, this.l10n,
803
+ /* enableScripting */
804
+ null,
805
+ /* hasJSActionsPromise = */
806
+ null,
807
+ /* mouseState = */
808
+ null);
809
+ }
810
+
811
+ this._renderAnnotationLayer();
812
+ }
813
+
814
+ if (this.xfaLayerFactory) {
815
+ if (!this.xfaLayer) {
816
+ this.xfaLayer = this.xfaLayerFactory.createXfaLayerBuilder(div, pdfPage,
817
+ /* annotationStorage = */
818
+ null);
819
+ }
820
+
821
+ this._renderXfaLayer();
822
+ } // The structure tree is currently only supported when the text layer is
823
+ // enabled and a canvas is used for rendering.
824
+
825
+
826
+ if (this.structTreeLayerFactory && this.textLayer && this.canvas) {
827
+ // The structure tree must be generated after the text layer for the
828
+ // aria-owns to work.
829
+ this._onTextLayerRendered = event => {
830
+ if (event.pageNumber !== this.id) {
831
+ return;
832
+ }
833
+
834
+ this.eventBus._off("textlayerrendered", this._onTextLayerRendered);
835
+
836
+ this._onTextLayerRendered = null;
837
+
838
+ if (!this.canvas) {
839
+ return; // The canvas was removed, prevent errors below.
840
+ }
841
+
842
+ this.pdfPage.getStructTree().then(tree => {
843
+ if (!tree) {
844
+ return;
845
+ }
846
+
847
+ if (!this.canvas) {
848
+ return; // The canvas was removed, prevent errors below.
849
+ }
850
+
851
+ const treeDom = this.structTreeLayer.render(tree);
852
+ treeDom.classList.add("structTree");
853
+ this.canvas.appendChild(treeDom);
854
+ });
855
+ };
856
+
857
+ this.eventBus._on("textlayerrendered", this._onTextLayerRendered);
858
+
859
+ this.structTreeLayer = this.structTreeLayerFactory.createStructTreeLayerBuilder(pdfPage);
860
+ }
861
+
862
+ div.setAttribute("data-loaded", true);
863
+ this.eventBus.dispatch("pagerender", {
864
+ source: this,
865
+ pageNumber: this.id
866
+ });
867
+ return resultPromise;
868
+ }
869
+
870
+ paintOnCanvas(canvasWrapper) {
871
+ const renderCapability = createPromiseCapability();
872
+ const result = {
873
+ promise: renderCapability.promise,
874
+
875
+ onRenderContinue(cont) {
876
+ cont();
877
+ },
878
+
879
+ cancel() {
880
+ renderTask.cancel();
881
+ }
882
+
883
+ };
884
+ const viewport = this.viewport;
885
+ const canvas = document.createElement("canvas"); // Keep the canvas hidden until the first draw callback, or until drawing
886
+ // is complete when `!this.renderingQueue`, to prevent black flickering.
887
+
888
+ canvas.hidden = true;
889
+ let isCanvasHidden = true;
890
+
891
+ const showCanvas = function () {
892
+ if (isCanvasHidden) {
893
+ canvas.hidden = false;
894
+ isCanvasHidden = false;
895
+ }
896
+ };
897
+
898
+ canvasWrapper.appendChild(canvas);
899
+ this.canvas = canvas;
900
+
901
+ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("MOZCENTRAL || GENERIC")) {
902
+ canvas.mozOpaque = true;
903
+ }
904
+
905
+ const ctx = canvas.getContext("2d", {
906
+ alpha: false
907
+ });
908
+ const outputScale = getOutputScale(ctx);
909
+ this.outputScale = outputScale;
910
+
911
+ if (this.useOnlyCssZoom) {
912
+ const actualSizeViewport = viewport.clone({
913
+ scale: CSS_UNITS
914
+ }); // Use a scale that makes the canvas have the originally intended size
915
+ // of the page.
916
+
917
+ outputScale.sx *= actualSizeViewport.width / viewport.width;
918
+ outputScale.sy *= actualSizeViewport.height / viewport.height;
919
+ outputScale.scaled = true;
920
+ }
921
+
922
+ if (this.maxCanvasPixels > 0) {
923
+ const pixelsInViewport = viewport.width * viewport.height;
924
+ const maxScale = Math.sqrt(this.maxCanvasPixels / pixelsInViewport);
925
+
926
+ if (outputScale.sx > maxScale || outputScale.sy > maxScale) {
927
+ outputScale.sx = maxScale;
928
+ outputScale.sy = maxScale;
929
+ outputScale.scaled = true;
930
+ this.hasRestrictedScaling = true;
931
+ } else {
932
+ this.hasRestrictedScaling = false;
933
+ }
934
+ }
935
+
936
+ const sfx = approximateFraction(outputScale.sx);
937
+ const sfy = approximateFraction(outputScale.sy);
938
+ canvas.width = roundToDivide(viewport.width * outputScale.sx, sfx[0]);
939
+ canvas.height = roundToDivide(viewport.height * outputScale.sy, sfy[0]);
940
+ canvas.style.width = roundToDivide(viewport.width, sfx[1]) + "px";
941
+ canvas.style.height = roundToDivide(viewport.height, sfy[1]) + "px"; // Add the viewport so it's known what it was originally drawn with.
942
+
943
+ this.paintedViewportMap.set(canvas, viewport); // Rendering area
944
+
945
+ const transform = !outputScale.scaled ? null : [outputScale.sx, 0, 0, outputScale.sy, 0, 0];
946
+ const renderContext = {
947
+ canvasContext: ctx,
948
+ transform,
949
+ viewport: this.viewport,
950
+ renderInteractiveForms: this.renderInteractiveForms,
951
+ optionalContentConfigPromise: this._optionalContentConfigPromise
952
+ };
953
+ const renderTask = this.pdfPage.render(renderContext);
954
+
955
+ renderTask.onContinue = function (cont) {
956
+ showCanvas();
957
+
958
+ if (result.onRenderContinue) {
959
+ result.onRenderContinue(cont);
960
+ } else {
961
+ cont();
962
+ }
963
+ };
964
+
965
+ renderTask.promise.then(function () {
966
+ showCanvas();
967
+ renderCapability.resolve(undefined);
968
+ }, function (error) {
969
+ showCanvas();
970
+ renderCapability.reject(error);
971
+ });
972
+ return result;
973
+ }
974
+
975
+ paintOnSvg(wrapper) {
976
+ if (typeof PDFJSDev !== "undefined" && PDFJSDev.test("MOZCENTRAL || CHROME")) {
977
+ // Return a mock object, to prevent errors such as e.g.
978
+ // "TypeError: paintTask.promise is undefined".
979
+ return {
980
+ promise: Promise.reject(new Error("SVG rendering is not supported.")),
981
+
982
+ onRenderContinue(cont) {},
983
+
984
+ cancel() {}
985
+
986
+ };
987
+ }
988
+
989
+ let cancelled = false;
990
+
991
+ const ensureNotCancelled = () => {
992
+ if (cancelled) {
993
+ throw new RenderingCancelledException(`Rendering cancelled, page ${this.id}`, "svg");
994
+ }
995
+ };
996
+
997
+ const pdfPage = this.pdfPage;
998
+ const actualSizeViewport = this.viewport.clone({
999
+ scale: CSS_UNITS
1000
+ });
1001
+ const promise = pdfPage.getOperatorList().then(opList => {
1002
+ ensureNotCancelled();
1003
+ const svgGfx = new SVGGraphics(pdfPage.commonObjs, pdfPage.objs,
1004
+ /* forceDataSchema = */
1005
+ viewerCompatibilityParams.disableCreateObjectURL);
1006
+ return svgGfx.getSVG(opList, actualSizeViewport).then(svg => {
1007
+ ensureNotCancelled();
1008
+ this.svg = svg;
1009
+ this.paintedViewportMap.set(svg, actualSizeViewport);
1010
+ svg.style.width = wrapper.style.width;
1011
+ svg.style.height = wrapper.style.height;
1012
+ this.renderingState = RenderingStates.FINISHED;
1013
+ wrapper.appendChild(svg);
1014
+ });
1015
+ });
1016
+ return {
1017
+ promise,
1018
+
1019
+ onRenderContinue(cont) {
1020
+ cont();
1021
+ },
1022
+
1023
+ cancel() {
1024
+ cancelled = true;
1025
+ }
1026
+
1027
+ };
1028
+ }
1029
+ /**
1030
+ * @param {string|null} label
1031
+ */
1032
+
1033
+
1034
+ setPageLabel(label) {
1035
+ this.pageLabel = typeof label === "string" ? label : null;
1036
+
1037
+ if (this.pageLabel !== null) {
1038
+ this.div.setAttribute("data-page-label", this.pageLabel);
1039
+ } else {
1040
+ this.div.removeAttribute("data-page-label");
1041
+ }
1042
+ }
1043
+
1044
+ }
1045
+
1046
+ /* Copyright 2021 Mozilla Foundation
1047
+ *
1048
+ * Licensed under the Apache License, Version 2.0 (the "License");
1049
+ * you may not use this file except in compliance with the License.
1050
+ * You may obtain a copy of the License at
1051
+ *
1052
+ * http://www.apache.org/licenses/LICENSE-2.0
1053
+ *
1054
+ * Unless required by applicable law or agreed to in writing, software
1055
+ * distributed under the License is distributed on an "AS IS" BASIS,
1056
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1057
+ * See the License for the specific language governing permissions and
1058
+ * limitations under the License.
1059
+ */
1060
+ const PDF_ROLE_TO_HTML_ROLE = {
1061
+ // Document level structure types
1062
+ Document: null,
1063
+ // There's a "document" role, but it doesn't make sense here.
1064
+ DocumentFragment: null,
1065
+ // Grouping level structure types
1066
+ Part: "group",
1067
+ Sect: "group",
1068
+ // XXX: There's a "section" role, but it's abstract.
1069
+ Div: "group",
1070
+ Aside: "note",
1071
+ NonStruct: "none",
1072
+ // Block level structure types
1073
+ P: null,
1074
+ // H<n>,
1075
+ H: "heading",
1076
+ Title: null,
1077
+ FENote: "note",
1078
+ // Sub-block level structure type
1079
+ Sub: "group",
1080
+ // General inline level structure types
1081
+ Lbl: null,
1082
+ Span: null,
1083
+ Em: null,
1084
+ Strong: null,
1085
+ Link: "link",
1086
+ Annot: "note",
1087
+ Form: "form",
1088
+ // Ruby and Warichu structure types
1089
+ Ruby: null,
1090
+ RB: null,
1091
+ RT: null,
1092
+ RP: null,
1093
+ Warichu: null,
1094
+ WT: null,
1095
+ WP: null,
1096
+ // List standard structure types
1097
+ L: "list",
1098
+ LI: "listitem",
1099
+ LBody: null,
1100
+ // Table standard structure types
1101
+ Table: "table",
1102
+ TR: "row",
1103
+ TH: "columnheader",
1104
+ TD: "cell",
1105
+ THead: "columnheader",
1106
+ TBody: null,
1107
+ TFoot: null,
1108
+ // Standard structure type Caption
1109
+ Caption: null,
1110
+ // Standard structure type Figure
1111
+ Figure: "figure",
1112
+ // Standard structure type Formula
1113
+ Formula: null,
1114
+ // standard structure type Artifact
1115
+ Artifact: null
1116
+ };
1117
+ const HEADING_PATTERN = /^H(\d+)$/;
1118
+ /**
1119
+ * @typedef {Object} StructTreeLayerBuilderOptions
1120
+ * @property {PDFPage} pdfPage
1121
+ */
1122
+
1123
+ class StructTreeLayerBuilder {
1124
+ /**
1125
+ * @param {StructTreeLayerBuilderOptions} options
1126
+ */
1127
+ constructor({
1128
+ pdfPage
1129
+ }) {
1130
+ this.pdfPage = pdfPage;
1131
+ }
1132
+
1133
+ render(structTree) {
1134
+ return this._walk(structTree);
1135
+ }
1136
+
1137
+ _setAttributes(structElement, htmlElement) {
1138
+ if (structElement.alt !== undefined) {
1139
+ htmlElement.setAttribute("aria-label", structElement.alt);
1140
+ }
1141
+
1142
+ if (structElement.id !== undefined) {
1143
+ htmlElement.setAttribute("aria-owns", structElement.id);
1144
+ }
1145
+ }
1146
+
1147
+ _walk(node) {
1148
+ if (!node) {
1149
+ return null;
1150
+ }
1151
+
1152
+ const element = document.createElement("span");
1153
+
1154
+ if ("role" in node) {
1155
+ const {
1156
+ role
1157
+ } = node;
1158
+ const match = role.match(HEADING_PATTERN);
1159
+
1160
+ if (match) {
1161
+ element.setAttribute("role", "heading");
1162
+ element.setAttribute("aria-level", match[1]);
1163
+ } else if (PDF_ROLE_TO_HTML_ROLE[role]) {
1164
+ element.setAttribute("role", PDF_ROLE_TO_HTML_ROLE[role]);
1165
+ }
1166
+ }
1167
+
1168
+ this._setAttributes(node, element);
1169
+
1170
+ if (node.children) {
1171
+ if (node.children.length === 1 && "id" in node.children[0]) {
1172
+ // Often there is only one content node so just set the values on the
1173
+ // parent node to avoid creating an extra span.
1174
+ this._setAttributes(node.children[0], element);
1175
+ } else {
1176
+ for (const kid of node.children) {
1177
+ element.appendChild(this._walk(kid));
1178
+ }
1179
+ }
1180
+ }
1181
+
1182
+ return element;
1183
+ }
1184
+
1185
+ }
1186
+
1187
+ /* Copyright 2012 Mozilla Foundation
1188
+ *
1189
+ * Licensed under the Apache License, Version 2.0 (the "License");
1190
+ * you may not use this file except in compliance with the License.
1191
+ * You may obtain a copy of the License at
1192
+ *
1193
+ * http://www.apache.org/licenses/LICENSE-2.0
1194
+ *
1195
+ * Unless required by applicable law or agreed to in writing, software
1196
+ * distributed under the License is distributed on an "AS IS" BASIS,
1197
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1198
+ * See the License for the specific language governing permissions and
1199
+ * limitations under the License.
1200
+ */
1201
+ const EXPAND_DIVS_TIMEOUT = 300; // ms
1202
+
1203
+ /**
1204
+ * @typedef {Object} TextLayerBuilderOptions
1205
+ * @property {HTMLDivElement} textLayerDiv - The text layer container.
1206
+ * @property {EventBus} eventBus - The application event bus.
1207
+ * @property {number} pageIndex - The page index.
1208
+ * @property {PageViewport} viewport - The viewport of the text layer.
1209
+ * @property {PDFFindController} findController
1210
+ * @property {boolean} enhanceTextSelection - Option to turn on improved
1211
+ * text selection.
1212
+ */
1213
+
1214
+ /**
1215
+ * The text layer builder provides text selection functionality for the PDF.
1216
+ * It does this by creating overlay divs over the PDF's text. These divs
1217
+ * contain text that matches the PDF text they are overlaying. This object
1218
+ * also provides a way to highlight text that is being searched for.
1219
+ */
1220
+
1221
+ class TextLayerBuilder {
1222
+ constructor({
1223
+ textLayerDiv,
1224
+ eventBus,
1225
+ pageIndex,
1226
+ viewport,
1227
+ findController = null,
1228
+ enhanceTextSelection = false
1229
+ }) {
1230
+ this.textLayerDiv = textLayerDiv;
1231
+ this.eventBus = eventBus;
1232
+ this.textContent = null;
1233
+ this.textContentItemsStr = [];
1234
+ this.textContentStream = null;
1235
+ this.renderingDone = false;
1236
+ this.pageIdx = pageIndex;
1237
+ this.pageNumber = this.pageIdx + 1;
1238
+ this.matches = [];
1239
+ this.viewport = viewport;
1240
+ this.textDivs = [];
1241
+ this.findController = findController;
1242
+ this.textLayerRenderTask = null;
1243
+ this.enhanceTextSelection = enhanceTextSelection;
1244
+ this._onUpdateTextLayerMatches = null;
1245
+
1246
+ this._bindMouse();
1247
+ }
1248
+ /**
1249
+ * @private
1250
+ */
1251
+
1252
+
1253
+ _finishRendering() {
1254
+ this.renderingDone = true;
1255
+
1256
+ if (!this.enhanceTextSelection) {
1257
+ const endOfContent = document.createElement("div");
1258
+ endOfContent.className = "endOfContent";
1259
+ this.textLayerDiv.appendChild(endOfContent);
1260
+ }
1261
+
1262
+ this.eventBus.dispatch("textlayerrendered", {
1263
+ source: this,
1264
+ pageNumber: this.pageNumber,
1265
+ numTextDivs: this.textDivs.length
1266
+ });
1267
+ }
1268
+ /**
1269
+ * Renders the text layer.
1270
+ *
1271
+ * @param {number} [timeout] - Wait for a specified amount of milliseconds
1272
+ * before rendering.
1273
+ */
1274
+
1275
+
1276
+ render(timeout = 0) {
1277
+ if (!(this.textContent || this.textContentStream) || this.renderingDone) {
1278
+ return;
1279
+ }
1280
+
1281
+ this.cancel();
1282
+ this.textDivs = [];
1283
+ const textLayerFrag = document.createDocumentFragment();
1284
+ this.textLayerRenderTask = renderTextLayer({
1285
+ textContent: this.textContent,
1286
+ textContentStream: this.textContentStream,
1287
+ container: textLayerFrag,
1288
+ viewport: this.viewport,
1289
+ textDivs: this.textDivs,
1290
+ textContentItemsStr: this.textContentItemsStr,
1291
+ timeout,
1292
+ enhanceTextSelection: this.enhanceTextSelection
1293
+ });
1294
+ this.textLayerRenderTask.promise.then(() => {
1295
+ this.textLayerDiv.appendChild(textLayerFrag);
1296
+
1297
+ this._finishRendering();
1298
+
1299
+ this._updateMatches();
1300
+ }, function (reason) {// Cancelled or failed to render text layer; skipping errors.
1301
+ });
1302
+
1303
+ if (!this._onUpdateTextLayerMatches) {
1304
+ this._onUpdateTextLayerMatches = evt => {
1305
+ if (evt.pageIndex === this.pageIdx || evt.pageIndex === -1) {
1306
+ this._updateMatches();
1307
+ }
1308
+ };
1309
+
1310
+ this.eventBus._on("updatetextlayermatches", this._onUpdateTextLayerMatches);
1311
+ }
1312
+ }
1313
+ /**
1314
+ * Cancel rendering of the text layer.
1315
+ */
1316
+
1317
+
1318
+ cancel() {
1319
+ if (this.textLayerRenderTask) {
1320
+ this.textLayerRenderTask.cancel();
1321
+ this.textLayerRenderTask = null;
1322
+ }
1323
+
1324
+ if (this._onUpdateTextLayerMatches) {
1325
+ this.eventBus._off("updatetextlayermatches", this._onUpdateTextLayerMatches);
1326
+
1327
+ this._onUpdateTextLayerMatches = null;
1328
+ }
1329
+ }
1330
+
1331
+ setTextContentStream(readableStream) {
1332
+ this.cancel();
1333
+ this.textContentStream = readableStream;
1334
+ }
1335
+
1336
+ setTextContent(textContent) {
1337
+ this.cancel();
1338
+ this.textContent = textContent;
1339
+ }
1340
+
1341
+ _convertMatches(matches, matchesLength) {
1342
+ // Early exit if there is nothing to convert.
1343
+ if (!matches) {
1344
+ return [];
1345
+ }
1346
+
1347
+ const {
1348
+ textContentItemsStr
1349
+ } = this;
1350
+ let i = 0,
1351
+ iIndex = 0;
1352
+ const end = textContentItemsStr.length - 1;
1353
+ const result = [];
1354
+
1355
+ for (let m = 0, mm = matches.length; m < mm; m++) {
1356
+ // Calculate the start position.
1357
+ let matchIdx = matches[m]; // Loop over the divIdxs.
1358
+
1359
+ while (i !== end && matchIdx >= iIndex + textContentItemsStr[i].length) {
1360
+ iIndex += textContentItemsStr[i].length;
1361
+ i++;
1362
+ }
1363
+
1364
+ if (i === textContentItemsStr.length) {
1365
+ console.error("Could not find a matching mapping");
1366
+ }
1367
+
1368
+ const match = {
1369
+ begin: {
1370
+ divIdx: i,
1371
+ offset: matchIdx - iIndex
1372
+ }
1373
+ }; // Calculate the end position.
1374
+
1375
+ matchIdx += matchesLength[m]; // Somewhat the same array as above, but use > instead of >= to get
1376
+ // the end position right.
1377
+
1378
+ while (i !== end && matchIdx > iIndex + textContentItemsStr[i].length) {
1379
+ iIndex += textContentItemsStr[i].length;
1380
+ i++;
1381
+ }
1382
+
1383
+ match.end = {
1384
+ divIdx: i,
1385
+ offset: matchIdx - iIndex
1386
+ };
1387
+ result.push(match);
1388
+ }
1389
+
1390
+ return result;
1391
+ }
1392
+
1393
+ _renderMatches(matches) {
1394
+ // Early exit if there is nothing to render.
1395
+ if (matches.length === 0) {
1396
+ return;
1397
+ }
1398
+
1399
+ const {
1400
+ findController,
1401
+ pageIdx,
1402
+ textContentItemsStr,
1403
+ textDivs
1404
+ } = this;
1405
+ const isSelectedPage = pageIdx === findController.selected.pageIdx;
1406
+ const selectedMatchIdx = findController.selected.matchIdx;
1407
+ const highlightAll = findController.state.highlightAll;
1408
+ let prevEnd = null;
1409
+ const infinity = {
1410
+ divIdx: -1,
1411
+ offset: undefined
1412
+ };
1413
+
1414
+ function beginText(begin, className) {
1415
+ const divIdx = begin.divIdx;
1416
+ textDivs[divIdx].textContent = "";
1417
+ return appendTextToDiv(divIdx, 0, begin.offset, className);
1418
+ }
1419
+
1420
+ function appendTextToDiv(divIdx, fromOffset, toOffset, className) {
1421
+ const div = textDivs[divIdx];
1422
+ const content = textContentItemsStr[divIdx].substring(fromOffset, toOffset);
1423
+ const node = document.createTextNode(content);
1424
+
1425
+ if (className) {
1426
+ const span = document.createElement("span");
1427
+ span.className = `${className} appended`;
1428
+ span.appendChild(node);
1429
+ div.appendChild(span);
1430
+ return className.includes("selected") ? span.offsetLeft : 0;
1431
+ }
1432
+
1433
+ div.appendChild(node);
1434
+ return 0;
1435
+ }
1436
+
1437
+ let i0 = selectedMatchIdx,
1438
+ i1 = i0 + 1;
1439
+
1440
+ if (highlightAll) {
1441
+ i0 = 0;
1442
+ i1 = matches.length;
1443
+ } else if (!isSelectedPage) {
1444
+ // Not highlighting all and this isn't the selected page, so do nothing.
1445
+ return;
1446
+ }
1447
+
1448
+ for (let i = i0; i < i1; i++) {
1449
+ const match = matches[i];
1450
+ const begin = match.begin;
1451
+ const end = match.end;
1452
+ const isSelected = isSelectedPage && i === selectedMatchIdx;
1453
+ const highlightSuffix = isSelected ? " selected" : "";
1454
+ let selectedLeft = 0; // Match inside new div.
1455
+
1456
+ if (!prevEnd || begin.divIdx !== prevEnd.divIdx) {
1457
+ // If there was a previous div, then add the text at the end.
1458
+ if (prevEnd !== null) {
1459
+ appendTextToDiv(prevEnd.divIdx, prevEnd.offset, infinity.offset);
1460
+ } // Clear the divs and set the content until the starting point.
1461
+
1462
+
1463
+ beginText(begin);
1464
+ } else {
1465
+ appendTextToDiv(prevEnd.divIdx, prevEnd.offset, begin.offset);
1466
+ }
1467
+
1468
+ if (begin.divIdx === end.divIdx) {
1469
+ selectedLeft = appendTextToDiv(begin.divIdx, begin.offset, end.offset, "highlight" + highlightSuffix);
1470
+ } else {
1471
+ selectedLeft = appendTextToDiv(begin.divIdx, begin.offset, infinity.offset, "highlight begin" + highlightSuffix);
1472
+
1473
+ for (let n0 = begin.divIdx + 1, n1 = end.divIdx; n0 < n1; n0++) {
1474
+ textDivs[n0].className = "highlight middle" + highlightSuffix;
1475
+ }
1476
+
1477
+ beginText(end, "highlight end" + highlightSuffix);
1478
+ }
1479
+
1480
+ prevEnd = end;
1481
+
1482
+ if (isSelected) {
1483
+ // Attempt to scroll the selected match into view.
1484
+ findController.scrollMatchIntoView({
1485
+ element: textDivs[begin.divIdx],
1486
+ selectedLeft,
1487
+ pageIndex: pageIdx,
1488
+ matchIndex: selectedMatchIdx
1489
+ });
1490
+ }
1491
+ }
1492
+
1493
+ if (prevEnd) {
1494
+ appendTextToDiv(prevEnd.divIdx, prevEnd.offset, infinity.offset);
1495
+ }
1496
+ }
1497
+
1498
+ _updateMatches() {
1499
+ // Only show matches when all rendering is done.
1500
+ if (!this.renderingDone) {
1501
+ return;
1502
+ }
1503
+
1504
+ const {
1505
+ findController,
1506
+ matches,
1507
+ pageIdx,
1508
+ textContentItemsStr,
1509
+ textDivs
1510
+ } = this;
1511
+ let clearedUntilDivIdx = -1; // Clear all current matches.
1512
+
1513
+ for (let i = 0, ii = matches.length; i < ii; i++) {
1514
+ const match = matches[i];
1515
+ const begin = Math.max(clearedUntilDivIdx, match.begin.divIdx);
1516
+
1517
+ for (let n = begin, end = match.end.divIdx; n <= end; n++) {
1518
+ const div = textDivs[n];
1519
+ div.textContent = textContentItemsStr[n];
1520
+ div.className = "";
1521
+ }
1522
+
1523
+ clearedUntilDivIdx = match.end.divIdx + 1;
1524
+ }
1525
+
1526
+ if (!(findController !== null && findController !== void 0 && findController.highlightMatches)) {
1527
+ return;
1528
+ } // Convert the matches on the `findController` into the match format
1529
+ // used for the textLayer.
1530
+
1531
+
1532
+ const pageMatches = findController.pageMatches[pageIdx] || null;
1533
+ const pageMatchesLength = findController.pageMatchesLength[pageIdx] || null;
1534
+ this.matches = this._convertMatches(pageMatches, pageMatchesLength);
1535
+
1536
+ this._renderMatches(this.matches);
1537
+ }
1538
+ /**
1539
+ * Improves text selection by adding an additional div where the mouse was
1540
+ * clicked. This reduces flickering of the content if the mouse is slowly
1541
+ * dragged up or down.
1542
+ *
1543
+ * @private
1544
+ */
1545
+
1546
+
1547
+ _bindMouse() {
1548
+ const div = this.textLayerDiv;
1549
+ let expandDivsTimer = null;
1550
+ div.addEventListener("mousedown", evt => {
1551
+ if (this.enhanceTextSelection && this.textLayerRenderTask) {
1552
+ this.textLayerRenderTask.expandTextDivs(true);
1553
+
1554
+ if ((typeof PDFJSDev === "undefined" || !PDFJSDev.test("MOZCENTRAL")) && expandDivsTimer) {
1555
+ clearTimeout(expandDivsTimer);
1556
+ expandDivsTimer = null;
1557
+ }
1558
+
1559
+ return;
1560
+ }
1561
+
1562
+ const end = div.querySelector(".endOfContent");
1563
+
1564
+ if (!end) {
1565
+ return;
1566
+ }
1567
+
1568
+ if (typeof PDFJSDev === "undefined" || !PDFJSDev.test("MOZCENTRAL")) {
1569
+ // On non-Firefox browsers, the selection will feel better if the height
1570
+ // of the `endOfContent` div is adjusted to start at mouse click
1571
+ // location. This avoids flickering when the selection moves up.
1572
+ // However it does not work when selection is started on empty space.
1573
+ let adjustTop = evt.target !== div;
1574
+
1575
+ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("GENERIC")) {
1576
+ adjustTop = adjustTop && window.getComputedStyle(end).getPropertyValue("-moz-user-select") !== "none";
1577
+ }
1578
+
1579
+ if (adjustTop) {
1580
+ const divBounds = div.getBoundingClientRect();
1581
+ const r = Math.max(0, (evt.pageY - divBounds.top) / divBounds.height);
1582
+ end.style.top = (r * 100).toFixed(2) + "%";
1583
+ }
1584
+ }
1585
+
1586
+ end.classList.add("active");
1587
+ });
1588
+ div.addEventListener("mouseup", () => {
1589
+ if (this.enhanceTextSelection && this.textLayerRenderTask) {
1590
+ if (typeof PDFJSDev === "undefined" || !PDFJSDev.test("MOZCENTRAL")) {
1591
+ expandDivsTimer = setTimeout(() => {
1592
+ if (this.textLayerRenderTask) {
1593
+ this.textLayerRenderTask.expandTextDivs(false);
1594
+ }
1595
+
1596
+ expandDivsTimer = null;
1597
+ }, EXPAND_DIVS_TIMEOUT);
1598
+ } else {
1599
+ this.textLayerRenderTask.expandTextDivs(false);
1600
+ }
1601
+
1602
+ return;
1603
+ }
1604
+
1605
+ const end = div.querySelector(".endOfContent");
1606
+
1607
+ if (!end) {
1608
+ return;
1609
+ }
1610
+
1611
+ if (typeof PDFJSDev === "undefined" || !PDFJSDev.test("MOZCENTRAL")) {
1612
+ end.style.top = "";
1613
+ }
1614
+
1615
+ end.classList.remove("active");
1616
+ });
1617
+ }
1618
+
1619
+ }
1620
+
1621
+ /* Copyright 2021 Mozilla Foundation
1622
+ *
1623
+ * Licensed under the Apache License, Version 2.0 (the "License");
1624
+ * you may not use this file except in compliance with the License.
1625
+ * You may obtain a copy of the License at
1626
+ *
1627
+ * http://www.apache.org/licenses/LICENSE-2.0
1628
+ *
1629
+ * Unless required by applicable law or agreed to in writing, software
1630
+ * distributed under the License is distributed on an "AS IS" BASIS,
1631
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1632
+ * See the License for the specific language governing permissions and
1633
+ * limitations under the License.
1634
+ */
1635
+ /**
1636
+ * @typedef {Object} XfaLayerBuilderOptions
1637
+ * @property {HTMLDivElement} pageDiv
1638
+ * @property {PDFPage} pdfPage
1639
+ * @property {AnnotationStorage} [annotationStorage]
1640
+ */
1641
+
1642
+ class XfaLayerBuilder {
1643
+ /**
1644
+ * @param {XfaLayerBuilderOptions} options
1645
+ */
1646
+ constructor({
1647
+ pageDiv,
1648
+ pdfPage,
1649
+ xfaHtml,
1650
+ annotationStorage
1651
+ }) {
1652
+ this.pageDiv = pageDiv;
1653
+ this.pdfPage = pdfPage;
1654
+ this.xfaHtml = xfaHtml;
1655
+ this.annotationStorage = annotationStorage;
1656
+ this.div = null;
1657
+ this._cancelled = false;
1658
+ }
1659
+ /**
1660
+ * @param {PageViewport} viewport
1661
+ * @param {string} intent (default value is 'display')
1662
+ * @returns {Promise<void>} A promise that is resolved when rendering of the
1663
+ * annotations is complete.
1664
+ */
1665
+
1666
+
1667
+ render(viewport, intent = "display") {
1668
+ if (intent === "print") {
1669
+ const parameters = {
1670
+ viewport: viewport.clone({
1671
+ dontFlip: true
1672
+ }),
1673
+ div: this.div,
1674
+ xfa: this.xfaHtml,
1675
+ page: null,
1676
+ annotationStorage: this.annotationStorage,
1677
+ intent
1678
+ }; // Create an xfa layer div and render the form
1679
+
1680
+ const div = document.createElement("div");
1681
+ this.pageDiv.appendChild(div);
1682
+ parameters.div = div;
1683
+ XfaLayer.render(parameters);
1684
+ return Promise.resolve();
1685
+ } // intent === "display"
1686
+
1687
+
1688
+ return this.pdfPage.getXfa().then(xfa => {
1689
+ if (this._cancelled) {
1690
+ return;
1691
+ }
1692
+
1693
+ const parameters = {
1694
+ viewport: viewport.clone({
1695
+ dontFlip: true
1696
+ }),
1697
+ div: this.div,
1698
+ xfa,
1699
+ page: this.pdfPage,
1700
+ annotationStorage: this.annotationStorage,
1701
+ intent
1702
+ };
1703
+
1704
+ if (this.div) {
1705
+ XfaLayer.update(parameters);
1706
+ } else {
1707
+ // Create an xfa layer div and render the form
1708
+ this.div = document.createElement("div");
1709
+ this.pageDiv.appendChild(this.div);
1710
+ parameters.div = this.div;
1711
+ XfaLayer.render(parameters);
1712
+ }
1713
+ }).catch(error => {
1714
+ console.error(error);
1715
+ });
1716
+ }
1717
+
1718
+ cancel() {
1719
+ this._cancelled = true;
1720
+ }
1721
+
1722
+ hide() {
1723
+ if (!this.div) {
1724
+ return;
1725
+ }
1726
+
1727
+ this.div.hidden = true;
1728
+ }
1729
+
1730
+ }
1731
+
1732
+ /* Copyright 2014 Mozilla Foundation
1733
+ *
1734
+ * Licensed under the Apache License, Version 2.0 (the "License");
1735
+ * you may not use this file except in compliance with the License.
1736
+ * You may obtain a copy of the License at
1737
+ *
1738
+ * http://www.apache.org/licenses/LICENSE-2.0
1739
+ *
1740
+ * Unless required by applicable law or agreed to in writing, software
1741
+ * distributed under the License is distributed on an "AS IS" BASIS,
1742
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1743
+ * See the License for the specific language governing permissions and
1744
+ * limitations under the License.
1745
+ */
1746
+ const DEFAULT_CACHE_SIZE = 10;
1747
+ /**
1748
+ * @typedef {Object} PDFViewerOptions
1749
+ * @property {HTMLDivElement} container - The container for the viewer element.
1750
+ * @property {HTMLDivElement} [viewer] - The viewer element.
1751
+ * @property {EventBus} eventBus - The application event bus.
1752
+ * @property {IPDFLinkService} linkService - The navigation/linking service.
1753
+ * @property {DownloadManager} [downloadManager] - The download manager
1754
+ * component.
1755
+ * @property {PDFFindController} [findController] - The find controller
1756
+ * component.
1757
+ * @property {PDFScriptingManager} [scriptingManager] - The scripting manager
1758
+ * component.
1759
+ * @property {PDFRenderingQueue} [renderingQueue] - The rendering queue object.
1760
+ * @property {boolean} [removePageBorders] - Removes the border shadow around
1761
+ * the pages. The default value is `false`.
1762
+ * @property {number} [textLayerMode] - Controls if the text layer used for
1763
+ * selection and searching is created, and if the improved text selection
1764
+ * behaviour is enabled. The constants from {TextLayerMode} should be used.
1765
+ * The default value is `TextLayerMode.ENABLE`.
1766
+ * @property {string} [imageResourcesPath] - Path for image resources, mainly
1767
+ * mainly for annotation icons. Include trailing slash.
1768
+ * @property {boolean} [renderInteractiveForms] - Enables rendering of
1769
+ * interactive form elements. The default value is `true`.
1770
+ * @property {boolean} [enablePrintAutoRotate] - Enables automatic rotation of
1771
+ * landscape pages upon printing. The default is `false`.
1772
+ * @property {string} renderer - 'canvas' or 'svg'. The default is 'canvas'.
1773
+ * @property {boolean} [useOnlyCssZoom] - Enables CSS only zooming. The default
1774
+ * value is `false`.
1775
+ * @property {number} [maxCanvasPixels] - The maximum supported canvas size in
1776
+ * total pixels, i.e. width * height. Use -1 for no limit. The default value
1777
+ * is 4096 * 4096 (16 mega-pixels).
1778
+ * @property {IL10n} l10n - Localization service.
1779
+ * @property {boolean} [enableScripting] - Enable embedded script execution
1780
+ * (also requires {scriptingManager} being set). The default value is `false`.
1781
+ */
1782
+
1783
+ function PDFPageViewBuffer(size) {
1784
+ const data = [];
1785
+
1786
+ this.push = function (view) {
1787
+ const i = data.indexOf(view);
1788
+
1789
+ if (i >= 0) {
1790
+ data.splice(i, 1);
1791
+ }
1792
+
1793
+ data.push(view);
1794
+
1795
+ if (data.length > size) {
1796
+ data.shift().destroy();
1797
+ }
1798
+ };
1799
+ /**
1800
+ * After calling resize, the size of the buffer will be newSize. The optional
1801
+ * parameter pagesToKeep is, if present, an array of pages to push to the back
1802
+ * of the buffer, delaying their destruction. The size of pagesToKeep has no
1803
+ * impact on the final size of the buffer; if pagesToKeep has length larger
1804
+ * than newSize, some of those pages will be destroyed anyway.
1805
+ */
1806
+
1807
+
1808
+ this.resize = function (newSize, pagesToKeep) {
1809
+ size = newSize;
1810
+
1811
+ if (pagesToKeep) {
1812
+ const pageIdsToKeep = new Set();
1813
+
1814
+ for (let i = 0, iMax = pagesToKeep.length; i < iMax; ++i) {
1815
+ pageIdsToKeep.add(pagesToKeep[i].id);
1816
+ }
1817
+
1818
+ moveToEndOfArray(data, function (page) {
1819
+ return pageIdsToKeep.has(page.id);
1820
+ });
1821
+ }
1822
+
1823
+ while (data.length > size) {
1824
+ data.shift().destroy();
1825
+ }
1826
+ };
1827
+
1828
+ this.has = function (view) {
1829
+ return data.includes(view);
1830
+ };
1831
+ }
1832
+
1833
+ function isSameScale(oldScale, newScale) {
1834
+ if (newScale === oldScale) {
1835
+ return true;
1836
+ }
1837
+
1838
+ if (Math.abs(newScale - oldScale) < 1e-15) {
1839
+ // Prevent unnecessary re-rendering of all pages when the scale
1840
+ // changes only because of limited numerical precision.
1841
+ return true;
1842
+ }
1843
+
1844
+ return false;
1845
+ }
1846
+ /**
1847
+ * Simple viewer control to display PDF content/pages.
1848
+ * @implements {IRenderableView}
1849
+ */
1850
+
1851
+
1852
+ class BaseViewer {
1853
+ /**
1854
+ * @param {PDFViewerOptions} options
1855
+ */
1856
+ constructor(options) {
1857
+ if (this.constructor === BaseViewer) {
1858
+ throw new Error("Cannot initialize BaseViewer.");
1859
+ }
1860
+
1861
+ const viewerVersion = typeof PDFJSDev !== "undefined" ? PDFJSDev.eval("BUNDLE_VERSION") : null;
1862
+
1863
+ if (version !== viewerVersion) {
1864
+ throw new Error(`The API version "${version}" does not match the Viewer version "${viewerVersion}".`);
1865
+ }
1866
+
1867
+ this._name = this.constructor.name;
1868
+ this.container = options.container;
1869
+ this.viewer = options.viewer || options.container.firstElementChild;
1870
+
1871
+ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("!PRODUCTION || GENERIC")) {
1872
+ var _this$container, _this$viewer;
1873
+
1874
+ if (!(((_this$container = this.container) === null || _this$container === void 0 ? void 0 : _this$container.tagName.toUpperCase()) === "DIV" && ((_this$viewer = this.viewer) === null || _this$viewer === void 0 ? void 0 : _this$viewer.tagName.toUpperCase()) === "DIV")) {
1875
+ throw new Error("Invalid `container` and/or `viewer` option.");
1876
+ }
1877
+
1878
+ if (this.container.offsetParent && getComputedStyle(this.container).position !== "absolute") {
1879
+ throw new Error("The `container` must be absolutely positioned.");
1880
+ }
1881
+ }
1882
+
1883
+ this.eventBus = options.eventBus;
1884
+ this.linkService = options.linkService || new SimpleLinkService();
1885
+ this.downloadManager = options.downloadManager || null;
1886
+ this.findController = options.findController || null;
1887
+ this._scriptingManager = options.scriptingManager || null;
1888
+ this.removePageBorders = options.removePageBorders || false;
1889
+ this.textLayerMode = Number.isInteger(options.textLayerMode) ? options.textLayerMode : TextLayerMode.ENABLE;
1890
+ this.imageResourcesPath = options.imageResourcesPath || "";
1891
+ this.renderInteractiveForms = options.renderInteractiveForms !== false;
1892
+ this.enablePrintAutoRotate = options.enablePrintAutoRotate || false;
1893
+ this.renderer = options.renderer || RendererType.CANVAS;
1894
+ this.useOnlyCssZoom = options.useOnlyCssZoom || false;
1895
+ this.maxCanvasPixels = options.maxCanvasPixels;
1896
+ this.l10n = options.l10n || NullL10n;
1897
+ this.enableScripting = options.enableScripting === true && !!this._scriptingManager;
1898
+ this.defaultRenderingQueue = !options.renderingQueue;
1899
+
1900
+ if (this.defaultRenderingQueue) {
1901
+ // Custom rendering queue is not specified, using default one
1902
+ this.renderingQueue = new PDFRenderingQueue();
1903
+ this.renderingQueue.setViewer(this);
1904
+ } else {
1905
+ this.renderingQueue = options.renderingQueue;
1906
+ }
1907
+
1908
+ this.scroll = watchScroll(this.container, this._scrollUpdate.bind(this));
1909
+ this.presentationModeState = PresentationModeState.UNKNOWN;
1910
+ this._onBeforeDraw = this._onAfterDraw = null;
1911
+
1912
+ this._resetView();
1913
+
1914
+ if (this.removePageBorders) {
1915
+ this.viewer.classList.add("removePageBorders");
1916
+ } // Defer the dispatching of this event, to give other viewer components
1917
+ // time to initialize *and* register 'baseviewerinit' event listeners.
1918
+
1919
+
1920
+ Promise.resolve().then(() => {
1921
+ this.eventBus.dispatch("baseviewerinit", {
1922
+ source: this
1923
+ });
1924
+ });
1925
+ }
1926
+
1927
+ get pagesCount() {
1928
+ return this._pages.length;
1929
+ }
1930
+
1931
+ getPageView(index) {
1932
+ return this._pages[index];
1933
+ }
1934
+ /**
1935
+ * @type {boolean} - True if all {PDFPageView} objects are initialized.
1936
+ */
1937
+
1938
+
1939
+ get pageViewsReady() {
1940
+ if (!this._pagesCapability.settled) {
1941
+ return false;
1942
+ } // Prevent printing errors when 'disableAutoFetch' is set, by ensuring
1943
+ // that *all* pages have in fact been completely loaded.
1944
+
1945
+
1946
+ return this._pages.every(function (pageView) {
1947
+ return pageView === null || pageView === void 0 ? void 0 : pageView.pdfPage;
1948
+ });
1949
+ }
1950
+ /**
1951
+ * @type {number}
1952
+ */
1953
+
1954
+
1955
+ get currentPageNumber() {
1956
+ return this._currentPageNumber;
1957
+ }
1958
+ /**
1959
+ * @param {number} val - The page number.
1960
+ */
1961
+
1962
+
1963
+ set currentPageNumber(val) {
1964
+ if (!Number.isInteger(val)) {
1965
+ throw new Error("Invalid page number.");
1966
+ }
1967
+
1968
+ if (!this.pdfDocument) {
1969
+ return;
1970
+ } // The intent can be to just reset a scroll position and/or scale.
1971
+
1972
+
1973
+ if (!this._setCurrentPageNumber(val,
1974
+ /* resetCurrentPageView = */
1975
+ true)) {
1976
+ console.error(`${this._name}.currentPageNumber: "${val}" is not a valid page.`);
1977
+ }
1978
+ }
1979
+ /**
1980
+ * @returns {boolean} Whether the pageNumber is valid (within bounds).
1981
+ * @private
1982
+ */
1983
+
1984
+
1985
+ _setCurrentPageNumber(val, resetCurrentPageView = false) {
1986
+ var _this$_pageLabels, _this$_pageLabels2;
1987
+
1988
+ if (this._currentPageNumber === val) {
1989
+ if (resetCurrentPageView) {
1990
+ this._resetCurrentPageView();
1991
+ }
1992
+
1993
+ return true;
1994
+ }
1995
+
1996
+ if (!(0 < val && val <= this.pagesCount)) {
1997
+ return false;
1998
+ }
1999
+
2000
+ const previous = this._currentPageNumber;
2001
+ this._currentPageNumber = val;
2002
+ this.eventBus.dispatch("pagechanging", {
2003
+ source: this,
2004
+ pageNumber: val,
2005
+ pageLabel: (_this$_pageLabels = (_this$_pageLabels2 = this._pageLabels) === null || _this$_pageLabels2 === void 0 ? void 0 : _this$_pageLabels2[val - 1]) !== null && _this$_pageLabels !== void 0 ? _this$_pageLabels : null,
2006
+ previous
2007
+ });
2008
+
2009
+ if (resetCurrentPageView) {
2010
+ this._resetCurrentPageView();
2011
+ }
2012
+
2013
+ return true;
2014
+ }
2015
+ /**
2016
+ * @type {string|null} Returns the current page label, or `null` if no page
2017
+ * labels exist.
2018
+ */
2019
+
2020
+
2021
+ get currentPageLabel() {
2022
+ var _this$_pageLabels3, _this$_pageLabels4;
2023
+
2024
+ return (_this$_pageLabels3 = (_this$_pageLabels4 = this._pageLabels) === null || _this$_pageLabels4 === void 0 ? void 0 : _this$_pageLabels4[this._currentPageNumber - 1]) !== null && _this$_pageLabels3 !== void 0 ? _this$_pageLabels3 : null;
2025
+ }
2026
+ /**
2027
+ * @param {string} val - The page label.
2028
+ */
2029
+
2030
+
2031
+ set currentPageLabel(val) {
2032
+ if (!this.pdfDocument) {
2033
+ return;
2034
+ }
2035
+
2036
+ let page = val | 0; // Fallback page number.
2037
+
2038
+ if (this._pageLabels) {
2039
+ const i = this._pageLabels.indexOf(val);
2040
+
2041
+ if (i >= 0) {
2042
+ page = i + 1;
2043
+ }
2044
+ } // The intent can be to just reset a scroll position and/or scale.
2045
+
2046
+
2047
+ if (!this._setCurrentPageNumber(page,
2048
+ /* resetCurrentPageView = */
2049
+ true)) {
2050
+ console.error(`${this._name}.currentPageLabel: "${val}" is not a valid page.`);
2051
+ }
2052
+ }
2053
+ /**
2054
+ * @type {number}
2055
+ */
2056
+
2057
+
2058
+ get currentScale() {
2059
+ return this._currentScale !== UNKNOWN_SCALE ? this._currentScale : DEFAULT_SCALE;
2060
+ }
2061
+ /**
2062
+ * @param {number} val - Scale of the pages in percents.
2063
+ */
2064
+
2065
+
2066
+ set currentScale(val) {
2067
+ if (isNaN(val)) {
2068
+ throw new Error("Invalid numeric scale.");
2069
+ }
2070
+
2071
+ if (!this.pdfDocument) {
2072
+ return;
2073
+ }
2074
+
2075
+ this._setScale(val, false);
2076
+ }
2077
+ /**
2078
+ * @type {string}
2079
+ */
2080
+
2081
+
2082
+ get currentScaleValue() {
2083
+ return this._currentScaleValue;
2084
+ }
2085
+ /**
2086
+ * @param val - The scale of the pages (in percent or predefined value).
2087
+ */
2088
+
2089
+
2090
+ set currentScaleValue(val) {
2091
+ if (!this.pdfDocument) {
2092
+ return;
2093
+ }
2094
+
2095
+ this._setScale(val, false);
2096
+ }
2097
+ /**
2098
+ * @type {number}
2099
+ */
2100
+
2101
+
2102
+ get pagesRotation() {
2103
+ return this._pagesRotation;
2104
+ }
2105
+ /**
2106
+ * @param {number} rotation - The rotation of the pages (0, 90, 180, 270).
2107
+ */
2108
+
2109
+
2110
+ set pagesRotation(rotation) {
2111
+ if (!isValidRotation(rotation)) {
2112
+ throw new Error("Invalid pages rotation angle.");
2113
+ }
2114
+
2115
+ if (!this.pdfDocument) {
2116
+ return;
2117
+ } // Normalize the rotation, by clamping it to the [0, 360) range.
2118
+
2119
+
2120
+ rotation %= 360;
2121
+
2122
+ if (rotation < 0) {
2123
+ rotation += 360;
2124
+ }
2125
+
2126
+ if (this._pagesRotation === rotation) {
2127
+ return; // The rotation didn't change.
2128
+ }
2129
+
2130
+ this._pagesRotation = rotation;
2131
+ const pageNumber = this._currentPageNumber;
2132
+
2133
+ for (let i = 0, ii = this._pages.length; i < ii; i++) {
2134
+ const pageView = this._pages[i];
2135
+ pageView.update(pageView.scale, rotation);
2136
+ } // Prevent errors in case the rotation changes *before* the scale has been
2137
+ // set to a non-default value.
2138
+
2139
+
2140
+ if (this._currentScaleValue) {
2141
+ this._setScale(this._currentScaleValue, true);
2142
+ }
2143
+
2144
+ this.eventBus.dispatch("rotationchanging", {
2145
+ source: this,
2146
+ pagesRotation: rotation,
2147
+ pageNumber
2148
+ });
2149
+
2150
+ if (this.defaultRenderingQueue) {
2151
+ this.update();
2152
+ }
2153
+ }
2154
+
2155
+ get firstPagePromise() {
2156
+ return this.pdfDocument ? this._firstPageCapability.promise : null;
2157
+ }
2158
+
2159
+ get onePageRendered() {
2160
+ return this.pdfDocument ? this._onePageRenderedCapability.promise : null;
2161
+ }
2162
+
2163
+ get pagesPromise() {
2164
+ return this.pdfDocument ? this._pagesCapability.promise : null;
2165
+ }
2166
+ /**
2167
+ * @private
2168
+ */
2169
+
2170
+
2171
+ get _viewerElement() {
2172
+ // In most viewers, e.g. `PDFViewer`, this should return `this.viewer`.
2173
+ throw new Error("Not implemented: _viewerElement");
2174
+ }
2175
+ /**
2176
+ * @private
2177
+ */
2178
+
2179
+
2180
+ _onePageRenderedOrForceFetch() {
2181
+ // Unless the viewer *and* its pages are visible, rendering won't start and
2182
+ // `this._onePageRenderedCapability` thus won't be resolved.
2183
+ // To ensure that automatic printing, on document load, still works even in
2184
+ // those cases we force-allow fetching of all pages when:
2185
+ // - The viewer is hidden in the DOM, e.g. in a `display: none` <iframe>
2186
+ // element; fixes bug 1618621.
2187
+ // - The viewer is visible, but none of the pages are (e.g. if the
2188
+ // viewer is very small); fixes bug 1618955.
2189
+ if (!this.container.offsetParent || this._getVisiblePages().views.length === 0) {
2190
+ return Promise.resolve();
2191
+ }
2192
+
2193
+ return this._onePageRenderedCapability.promise;
2194
+ }
2195
+ /**
2196
+ * @param pdfDocument {PDFDocument}
2197
+ */
2198
+
2199
+
2200
+ setDocument(pdfDocument) {
2201
+ if (this.pdfDocument) {
2202
+ this.eventBus.dispatch("pagesdestroy", {
2203
+ source: this
2204
+ });
2205
+
2206
+ this._cancelRendering();
2207
+
2208
+ this._resetView();
2209
+
2210
+ if (this.findController) {
2211
+ this.findController.setDocument(null);
2212
+ }
2213
+
2214
+ if (this._scriptingManager) {
2215
+ this._scriptingManager.setDocument(null);
2216
+ }
2217
+ }
2218
+
2219
+ this.pdfDocument = pdfDocument;
2220
+
2221
+ if (!pdfDocument) {
2222
+ return;
2223
+ }
2224
+
2225
+ const isPureXfa = pdfDocument.isPureXfa;
2226
+ const pagesCount = pdfDocument.numPages;
2227
+ const firstPagePromise = pdfDocument.getPage(1); // Rendering (potentially) depends on this, hence fetching it immediately.
2228
+
2229
+ const optionalContentConfigPromise = pdfDocument.getOptionalContentConfig();
2230
+
2231
+ this._pagesCapability.promise.then(() => {
2232
+ this.eventBus.dispatch("pagesloaded", {
2233
+ source: this,
2234
+ pagesCount
2235
+ });
2236
+ });
2237
+
2238
+ this._onBeforeDraw = evt => {
2239
+ const pageView = this._pages[evt.pageNumber - 1];
2240
+
2241
+ if (!pageView) {
2242
+ return;
2243
+ } // Add the page to the buffer at the start of drawing. That way it can be
2244
+ // evicted from the buffer and destroyed even if we pause its rendering.
2245
+
2246
+
2247
+ this._buffer.push(pageView);
2248
+ };
2249
+
2250
+ this.eventBus._on("pagerender", this._onBeforeDraw);
2251
+
2252
+ this._onAfterDraw = evt => {
2253
+ if (evt.cssTransform || this._onePageRenderedCapability.settled) {
2254
+ return;
2255
+ }
2256
+
2257
+ this._onePageRenderedCapability.resolve();
2258
+
2259
+ this.eventBus._off("pagerendered", this._onAfterDraw);
2260
+
2261
+ this._onAfterDraw = null;
2262
+ };
2263
+
2264
+ this.eventBus._on("pagerendered", this._onAfterDraw); // Fetch a single page so we can get a viewport that will be the default
2265
+ // viewport for all pages
2266
+
2267
+
2268
+ firstPagePromise.then(firstPdfPage => {
2269
+ this._firstPageCapability.resolve(firstPdfPage);
2270
+
2271
+ this._optionalContentConfigPromise = optionalContentConfigPromise;
2272
+ const scale = this.currentScale;
2273
+ const viewport = firstPdfPage.getViewport({
2274
+ scale: scale * CSS_UNITS
2275
+ });
2276
+ const textLayerFactory = this.textLayerMode !== TextLayerMode.DISABLE ? this : null;
2277
+ const xfaLayerFactory = isPureXfa ? this : null;
2278
+
2279
+ for (let pageNum = 1; pageNum <= pagesCount; ++pageNum) {
2280
+ const pageView = new PDFPageView({
2281
+ container: this._viewerElement,
2282
+ eventBus: this.eventBus,
2283
+ id: pageNum,
2284
+ scale,
2285
+ defaultViewport: viewport.clone(),
2286
+ optionalContentConfigPromise,
2287
+ renderingQueue: this.renderingQueue,
2288
+ textLayerFactory,
2289
+ textLayerMode: this.textLayerMode,
2290
+ annotationLayerFactory: this,
2291
+ xfaLayerFactory,
2292
+ structTreeLayerFactory: this,
2293
+ imageResourcesPath: this.imageResourcesPath,
2294
+ renderInteractiveForms: this.renderInteractiveForms,
2295
+ renderer: this.renderer,
2296
+ useOnlyCssZoom: this.useOnlyCssZoom,
2297
+ maxCanvasPixels: this.maxCanvasPixels,
2298
+ l10n: this.l10n
2299
+ });
2300
+
2301
+ this._pages.push(pageView);
2302
+ } // Set the first `pdfPage` immediately, since it's already loaded,
2303
+ // rather than having to repeat the `PDFDocumentProxy.getPage` call in
2304
+ // the `this._ensurePdfPageLoaded` method before rendering can start.
2305
+
2306
+
2307
+ const firstPageView = this._pages[0];
2308
+
2309
+ if (firstPageView) {
2310
+ firstPageView.setPdfPage(firstPdfPage);
2311
+ this.linkService.cachePageRef(1, firstPdfPage.ref);
2312
+ }
2313
+
2314
+ if (this._spreadMode !== SpreadMode.NONE) {
2315
+ this._updateSpreadMode();
2316
+ } // Fetch all the pages since the viewport is needed before printing
2317
+ // starts to create the correct size canvas. Wait until one page is
2318
+ // rendered so we don't tie up too many resources early on.
2319
+
2320
+
2321
+ this._onePageRenderedOrForceFetch().then(() => {
2322
+ if (this.findController) {
2323
+ this.findController.setDocument(pdfDocument); // Enable searching.
2324
+ }
2325
+
2326
+ if (this.enableScripting) {
2327
+ this._scriptingManager.setDocument(pdfDocument);
2328
+ } // In addition to 'disableAutoFetch' being set, also attempt to reduce
2329
+ // resource usage when loading *very* long/large documents.
2330
+
2331
+
2332
+ if (pdfDocument.loadingParams.disableAutoFetch || pagesCount > 7500) {
2333
+ // XXX: Printing is semi-broken with auto fetch disabled.
2334
+ this._pagesCapability.resolve();
2335
+
2336
+ return;
2337
+ }
2338
+
2339
+ let getPagesLeft = pagesCount - 1; // The first page was already loaded.
2340
+
2341
+ if (getPagesLeft <= 0) {
2342
+ this._pagesCapability.resolve();
2343
+
2344
+ return;
2345
+ }
2346
+
2347
+ for (let pageNum = 2; pageNum <= pagesCount; ++pageNum) {
2348
+ pdfDocument.getPage(pageNum).then(pdfPage => {
2349
+ const pageView = this._pages[pageNum - 1];
2350
+
2351
+ if (!pageView.pdfPage) {
2352
+ pageView.setPdfPage(pdfPage);
2353
+ }
2354
+
2355
+ this.linkService.cachePageRef(pageNum, pdfPage.ref);
2356
+
2357
+ if (--getPagesLeft === 0) {
2358
+ this._pagesCapability.resolve();
2359
+ }
2360
+ }, reason => {
2361
+ console.error(`Unable to get page ${pageNum} to initialize viewer`, reason);
2362
+
2363
+ if (--getPagesLeft === 0) {
2364
+ this._pagesCapability.resolve();
2365
+ }
2366
+ });
2367
+ }
2368
+ });
2369
+
2370
+ this.eventBus.dispatch("pagesinit", {
2371
+ source: this
2372
+ });
2373
+
2374
+ if (this.defaultRenderingQueue) {
2375
+ this.update();
2376
+ }
2377
+ }).catch(reason => {
2378
+ console.error("Unable to initialize viewer", reason);
2379
+ });
2380
+ }
2381
+ /**
2382
+ * @param {Array|null} labels
2383
+ */
2384
+
2385
+
2386
+ setPageLabels(labels) {
2387
+ if (!this.pdfDocument) {
2388
+ return;
2389
+ }
2390
+
2391
+ if (!labels) {
2392
+ this._pageLabels = null;
2393
+ } else if (!(Array.isArray(labels) && this.pdfDocument.numPages === labels.length)) {
2394
+ this._pageLabels = null;
2395
+ console.error(`${this._name}.setPageLabels: Invalid page labels.`);
2396
+ } else {
2397
+ this._pageLabels = labels;
2398
+ } // Update all the `PDFPageView` instances.
2399
+
2400
+
2401
+ for (let i = 0, ii = this._pages.length; i < ii; i++) {
2402
+ var _this$_pageLabels$i, _this$_pageLabels5;
2403
+
2404
+ this._pages[i].setPageLabel((_this$_pageLabels$i = (_this$_pageLabels5 = this._pageLabels) === null || _this$_pageLabels5 === void 0 ? void 0 : _this$_pageLabels5[i]) !== null && _this$_pageLabels$i !== void 0 ? _this$_pageLabels$i : null);
2405
+ }
2406
+ }
2407
+
2408
+ _resetView() {
2409
+ this._pages = [];
2410
+ this._currentPageNumber = 1;
2411
+ this._currentScale = UNKNOWN_SCALE;
2412
+ this._currentScaleValue = null;
2413
+ this._pageLabels = null;
2414
+ this._buffer = new PDFPageViewBuffer(DEFAULT_CACHE_SIZE);
2415
+ this._location = null;
2416
+ this._pagesRotation = 0;
2417
+ this._optionalContentConfigPromise = null;
2418
+ this._pagesRequests = new WeakMap();
2419
+ this._firstPageCapability = createPromiseCapability();
2420
+ this._onePageRenderedCapability = createPromiseCapability();
2421
+ this._pagesCapability = createPromiseCapability();
2422
+ this._scrollMode = ScrollMode.VERTICAL;
2423
+ this._spreadMode = SpreadMode.NONE;
2424
+
2425
+ if (this._onBeforeDraw) {
2426
+ this.eventBus._off("pagerender", this._onBeforeDraw);
2427
+
2428
+ this._onBeforeDraw = null;
2429
+ }
2430
+
2431
+ if (this._onAfterDraw) {
2432
+ this.eventBus._off("pagerendered", this._onAfterDraw);
2433
+
2434
+ this._onAfterDraw = null;
2435
+ } // Remove the pages from the DOM...
2436
+
2437
+
2438
+ this.viewer.textContent = ""; // ... and reset the Scroll mode CSS class(es) afterwards.
2439
+
2440
+ this._updateScrollMode();
2441
+ }
2442
+
2443
+ _scrollUpdate() {
2444
+ if (this.pagesCount === 0) {
2445
+ return;
2446
+ }
2447
+
2448
+ this.update();
2449
+ }
2450
+
2451
+ _scrollIntoView({
2452
+ pageDiv,
2453
+ pageSpot = null,
2454
+ pageNumber = null
2455
+ }) {
2456
+ scrollIntoView(pageDiv, pageSpot);
2457
+ }
2458
+
2459
+ _setScaleUpdatePages(newScale, newValue, noScroll = false, preset = false) {
2460
+ this._currentScaleValue = newValue.toString();
2461
+
2462
+ if (isSameScale(this._currentScale, newScale)) {
2463
+ if (preset) {
2464
+ this.eventBus.dispatch("scalechanging", {
2465
+ source: this,
2466
+ scale: newScale,
2467
+ presetValue: newValue
2468
+ });
2469
+ }
2470
+
2471
+ return;
2472
+ }
2473
+
2474
+ for (let i = 0, ii = this._pages.length; i < ii; i++) {
2475
+ this._pages[i].update(newScale);
2476
+ }
2477
+
2478
+ this._currentScale = newScale;
2479
+
2480
+ if (!noScroll) {
2481
+ let page = this._currentPageNumber,
2482
+ dest;
2483
+
2484
+ if (this._location && !(this.isInPresentationMode || this.isChangingPresentationMode)) {
2485
+ page = this._location.pageNumber;
2486
+ dest = [null, {
2487
+ name: "XYZ"
2488
+ }, this._location.left, this._location.top, null];
2489
+ }
2490
+
2491
+ this.scrollPageIntoView({
2492
+ pageNumber: page,
2493
+ destArray: dest,
2494
+ allowNegativeOffset: true
2495
+ });
2496
+ }
2497
+
2498
+ this.eventBus.dispatch("scalechanging", {
2499
+ source: this,
2500
+ scale: newScale,
2501
+ presetValue: preset ? newValue : undefined
2502
+ });
2503
+
2504
+ if (this.defaultRenderingQueue) {
2505
+ this.update();
2506
+ }
2507
+ }
2508
+ /**
2509
+ * @private
2510
+ */
2511
+
2512
+
2513
+ get _pageWidthScaleFactor() {
2514
+ if (this._spreadMode !== SpreadMode.NONE && this._scrollMode !== ScrollMode.HORIZONTAL && !this.isInPresentationMode) {
2515
+ return 2;
2516
+ }
2517
+
2518
+ return 1;
2519
+ }
2520
+
2521
+ _setScale(value, noScroll = false) {
2522
+ let scale = parseFloat(value);
2523
+
2524
+ if (scale > 0) {
2525
+ this._setScaleUpdatePages(scale, value, noScroll,
2526
+ /* preset = */
2527
+ false);
2528
+ } else {
2529
+ const currentPage = this._pages[this._currentPageNumber - 1];
2530
+
2531
+ if (!currentPage) {
2532
+ return;
2533
+ }
2534
+
2535
+ const noPadding = this.isInPresentationMode || this.removePageBorders;
2536
+ let hPadding = noPadding ? 0 : SCROLLBAR_PADDING;
2537
+ let vPadding = noPadding ? 0 : VERTICAL_PADDING;
2538
+
2539
+ if (!noPadding && this._isScrollModeHorizontal) {
2540
+ [hPadding, vPadding] = [vPadding, hPadding]; // Swap the padding values.
2541
+ }
2542
+
2543
+ const pageWidthScale = (this.container.clientWidth - hPadding) / currentPage.width * currentPage.scale / this._pageWidthScaleFactor;
2544
+ const pageHeightScale = (this.container.clientHeight - vPadding) / currentPage.height * currentPage.scale;
2545
+
2546
+ switch (value) {
2547
+ case "page-actual":
2548
+ scale = 1;
2549
+ break;
2550
+
2551
+ case "page-width":
2552
+ scale = pageWidthScale;
2553
+ break;
2554
+
2555
+ case "page-height":
2556
+ scale = pageHeightScale;
2557
+ break;
2558
+
2559
+ case "page-fit":
2560
+ scale = Math.min(pageWidthScale, pageHeightScale);
2561
+ break;
2562
+
2563
+ case "auto":
2564
+ // For pages in landscape mode, fit the page height to the viewer
2565
+ // *unless* the page would thus become too wide to fit horizontally.
2566
+ const horizontalScale = isPortraitOrientation(currentPage) ? pageWidthScale : Math.min(pageHeightScale, pageWidthScale);
2567
+ scale = Math.min(MAX_AUTO_SCALE, horizontalScale);
2568
+ break;
2569
+
2570
+ default:
2571
+ console.error(`${this._name}._setScale: "${value}" is an unknown zoom value.`);
2572
+ return;
2573
+ }
2574
+
2575
+ this._setScaleUpdatePages(scale, value, noScroll,
2576
+ /* preset = */
2577
+ true);
2578
+ }
2579
+ }
2580
+ /**
2581
+ * Refreshes page view: scrolls to the current page and updates the scale.
2582
+ * @private
2583
+ */
2584
+
2585
+
2586
+ _resetCurrentPageView() {
2587
+ if (this.isInPresentationMode) {
2588
+ // Fixes the case when PDF has different page sizes.
2589
+ this._setScale(this._currentScaleValue, true);
2590
+ }
2591
+
2592
+ const pageView = this._pages[this._currentPageNumber - 1];
2593
+
2594
+ this._scrollIntoView({
2595
+ pageDiv: pageView.div
2596
+ });
2597
+ }
2598
+ /**
2599
+ * @param {string} label - The page label.
2600
+ * @returns {number|null} The page number corresponding to the page label,
2601
+ * or `null` when no page labels exist and/or the input is invalid.
2602
+ */
2603
+
2604
+
2605
+ pageLabelToPageNumber(label) {
2606
+ if (!this._pageLabels) {
2607
+ return null;
2608
+ }
2609
+
2610
+ const i = this._pageLabels.indexOf(label);
2611
+
2612
+ if (i < 0) {
2613
+ return null;
2614
+ }
2615
+
2616
+ return i + 1;
2617
+ }
2618
+ /**
2619
+ * @typedef ScrollPageIntoViewParameters
2620
+ * @property {number} pageNumber - The page number.
2621
+ * @property {Array} [destArray] - The original PDF destination array, in the
2622
+ * format: <page-ref> </XYZ|/FitXXX> <args..>
2623
+ * @property {boolean} [allowNegativeOffset] - Allow negative page offsets.
2624
+ * The default value is `false`.
2625
+ * @property {boolean} [ignoreDestinationZoom] - Ignore the zoom argument in
2626
+ * the destination array. The default value is `false`.
2627
+ */
2628
+
2629
+ /**
2630
+ * Scrolls page into view.
2631
+ * @param {ScrollPageIntoViewParameters} params
2632
+ */
2633
+
2634
+
2635
+ scrollPageIntoView({
2636
+ pageNumber,
2637
+ destArray = null,
2638
+ allowNegativeOffset = false,
2639
+ ignoreDestinationZoom = false
2640
+ }) {
2641
+ if (!this.pdfDocument) {
2642
+ return;
2643
+ }
2644
+
2645
+ const pageView = Number.isInteger(pageNumber) && this._pages[pageNumber - 1];
2646
+
2647
+ if (!pageView) {
2648
+ console.error(`${this._name}.scrollPageIntoView: ` + `"${pageNumber}" is not a valid pageNumber parameter.`);
2649
+ return;
2650
+ }
2651
+
2652
+ if (this.isInPresentationMode || !destArray) {
2653
+ this._setCurrentPageNumber(pageNumber,
2654
+ /* resetCurrentPageView = */
2655
+ true);
2656
+
2657
+ return;
2658
+ }
2659
+
2660
+ let x = 0,
2661
+ y = 0;
2662
+ let width = 0,
2663
+ height = 0,
2664
+ widthScale,
2665
+ heightScale;
2666
+ const changeOrientation = pageView.rotation % 180 !== 0;
2667
+ const pageWidth = (changeOrientation ? pageView.height : pageView.width) / pageView.scale / CSS_UNITS;
2668
+ const pageHeight = (changeOrientation ? pageView.width : pageView.height) / pageView.scale / CSS_UNITS;
2669
+ let scale = 0;
2670
+
2671
+ switch (destArray[1].name) {
2672
+ case "XYZ":
2673
+ x = destArray[2];
2674
+ y = destArray[3];
2675
+ scale = destArray[4]; // If x and/or y coordinates are not supplied, default to
2676
+ // _top_ left of the page (not the obvious bottom left,
2677
+ // since aligning the bottom of the intended page with the
2678
+ // top of the window is rarely helpful).
2679
+
2680
+ x = x !== null ? x : 0;
2681
+ y = y !== null ? y : pageHeight;
2682
+ break;
2683
+
2684
+ case "Fit":
2685
+ case "FitB":
2686
+ scale = "page-fit";
2687
+ break;
2688
+
2689
+ case "FitH":
2690
+ case "FitBH":
2691
+ y = destArray[2];
2692
+ scale = "page-width"; // According to the PDF spec, section 12.3.2.2, a `null` value in the
2693
+ // parameter should maintain the position relative to the new page.
2694
+
2695
+ if (y === null && this._location) {
2696
+ x = this._location.left;
2697
+ y = this._location.top;
2698
+ } else if (typeof y !== "number") {
2699
+ // The "top" value isn't optional, according to the spec, however some
2700
+ // bad PDF generators will pretend that it is (fixes bug 1663390).
2701
+ y = pageHeight;
2702
+ }
2703
+
2704
+ break;
2705
+
2706
+ case "FitV":
2707
+ case "FitBV":
2708
+ x = destArray[2];
2709
+ width = pageWidth;
2710
+ height = pageHeight;
2711
+ scale = "page-height";
2712
+ break;
2713
+
2714
+ case "FitR":
2715
+ x = destArray[2];
2716
+ y = destArray[3];
2717
+ width = destArray[4] - x;
2718
+ height = destArray[5] - y;
2719
+ const hPadding = this.removePageBorders ? 0 : SCROLLBAR_PADDING;
2720
+ const vPadding = this.removePageBorders ? 0 : VERTICAL_PADDING;
2721
+ widthScale = (this.container.clientWidth - hPadding) / width / CSS_UNITS;
2722
+ heightScale = (this.container.clientHeight - vPadding) / height / CSS_UNITS;
2723
+ scale = Math.min(Math.abs(widthScale), Math.abs(heightScale));
2724
+ break;
2725
+
2726
+ default:
2727
+ console.error(`${this._name}.scrollPageIntoView: ` + `"${destArray[1].name}" is not a valid destination type.`);
2728
+ return;
2729
+ }
2730
+
2731
+ if (!ignoreDestinationZoom) {
2732
+ if (scale && scale !== this._currentScale) {
2733
+ this.currentScaleValue = scale;
2734
+ } else if (this._currentScale === UNKNOWN_SCALE) {
2735
+ this.currentScaleValue = DEFAULT_SCALE_VALUE;
2736
+ }
2737
+ }
2738
+
2739
+ if (scale === "page-fit" && !destArray[4]) {
2740
+ this._scrollIntoView({
2741
+ pageDiv: pageView.div,
2742
+ pageNumber
2743
+ });
2744
+
2745
+ return;
2746
+ }
2747
+
2748
+ const boundingRect = [pageView.viewport.convertToViewportPoint(x, y), pageView.viewport.convertToViewportPoint(x + width, y + height)];
2749
+ let left = Math.min(boundingRect[0][0], boundingRect[1][0]);
2750
+ let top = Math.min(boundingRect[0][1], boundingRect[1][1]);
2751
+
2752
+ if (!allowNegativeOffset) {
2753
+ // Some bad PDF generators will create destinations with e.g. top values
2754
+ // that exceeds the page height. Ensure that offsets are not negative,
2755
+ // to prevent a previous page from becoming visible (fixes bug 874482).
2756
+ left = Math.max(left, 0);
2757
+ top = Math.max(top, 0);
2758
+ }
2759
+
2760
+ this._scrollIntoView({
2761
+ pageDiv: pageView.div,
2762
+ pageSpot: {
2763
+ left,
2764
+ top
2765
+ },
2766
+ pageNumber
2767
+ });
2768
+ }
2769
+
2770
+ _updateLocation(firstPage) {
2771
+ const currentScale = this._currentScale;
2772
+ const currentScaleValue = this._currentScaleValue;
2773
+ const normalizedScaleValue = parseFloat(currentScaleValue) === currentScale ? Math.round(currentScale * 10000) / 100 : currentScaleValue;
2774
+ const pageNumber = firstPage.id;
2775
+ let pdfOpenParams = "#page=" + pageNumber;
2776
+ pdfOpenParams += "&zoom=" + normalizedScaleValue;
2777
+ const currentPageView = this._pages[pageNumber - 1];
2778
+ const container = this.container;
2779
+ const topLeft = currentPageView.getPagePoint(container.scrollLeft - firstPage.x, container.scrollTop - firstPage.y);
2780
+ const intLeft = Math.round(topLeft[0]);
2781
+ const intTop = Math.round(topLeft[1]);
2782
+ pdfOpenParams += "," + intLeft + "," + intTop;
2783
+ this._location = {
2784
+ pageNumber,
2785
+ scale: normalizedScaleValue,
2786
+ top: intTop,
2787
+ left: intLeft,
2788
+ rotation: this._pagesRotation,
2789
+ pdfOpenParams
2790
+ };
2791
+ }
2792
+
2793
+ _updateHelper(visiblePages) {
2794
+ throw new Error("Not implemented: _updateHelper");
2795
+ }
2796
+
2797
+ update() {
2798
+ const visible = this._getVisiblePages();
2799
+
2800
+ const visiblePages = visible.views,
2801
+ numVisiblePages = visiblePages.length;
2802
+
2803
+ if (numVisiblePages === 0) {
2804
+ return;
2805
+ }
2806
+
2807
+ const newCacheSize = Math.max(DEFAULT_CACHE_SIZE, 2 * numVisiblePages + 1);
2808
+
2809
+ this._buffer.resize(newCacheSize, visiblePages);
2810
+
2811
+ this.renderingQueue.renderHighestPriority(visible);
2812
+
2813
+ this._updateHelper(visiblePages); // Run any class-specific update code.
2814
+
2815
+
2816
+ this._updateLocation(visible.first);
2817
+
2818
+ this.eventBus.dispatch("updateviewarea", {
2819
+ source: this,
2820
+ location: this._location
2821
+ });
2822
+ }
2823
+
2824
+ containsElement(element) {
2825
+ return this.container.contains(element);
2826
+ }
2827
+
2828
+ focus() {
2829
+ this.container.focus();
2830
+ }
2831
+
2832
+ get _isScrollModeHorizontal() {
2833
+ // Used to ensure that pre-rendering of the next/previous page works
2834
+ // correctly, since Scroll/Spread modes are ignored in Presentation Mode.
2835
+ return this.isInPresentationMode ? false : this._scrollMode === ScrollMode.HORIZONTAL;
2836
+ }
2837
+
2838
+ get _isContainerRtl() {
2839
+ return getComputedStyle(this.container).direction === "rtl";
2840
+ }
2841
+
2842
+ get isInPresentationMode() {
2843
+ return this.presentationModeState === PresentationModeState.FULLSCREEN;
2844
+ }
2845
+
2846
+ get isChangingPresentationMode() {
2847
+ return this.presentationModeState === PresentationModeState.CHANGING;
2848
+ }
2849
+
2850
+ get isHorizontalScrollbarEnabled() {
2851
+ return this.isInPresentationMode ? false : this.container.scrollWidth > this.container.clientWidth;
2852
+ }
2853
+
2854
+ get isVerticalScrollbarEnabled() {
2855
+ return this.isInPresentationMode ? false : this.container.scrollHeight > this.container.clientHeight;
2856
+ }
2857
+ /**
2858
+ * Helper method for `this._getVisiblePages`. Should only ever be used when
2859
+ * the viewer can only display a single page at a time, for example in:
2860
+ * - `PDFSinglePageViewer`.
2861
+ * - `PDFViewer` with Presentation Mode active.
2862
+ */
2863
+
2864
+
2865
+ _getCurrentVisiblePage() {
2866
+ if (!this.pagesCount) {
2867
+ return {
2868
+ views: []
2869
+ };
2870
+ }
2871
+
2872
+ const pageView = this._pages[this._currentPageNumber - 1]; // NOTE: Compute the `x` and `y` properties of the current view,
2873
+ // since `this._updateLocation` depends of them being available.
2874
+
2875
+ const element = pageView.div;
2876
+ const view = {
2877
+ id: pageView.id,
2878
+ x: element.offsetLeft + element.clientLeft,
2879
+ y: element.offsetTop + element.clientTop,
2880
+ view: pageView
2881
+ };
2882
+ return {
2883
+ first: view,
2884
+ last: view,
2885
+ views: [view]
2886
+ };
2887
+ }
2888
+
2889
+ _getVisiblePages() {
2890
+ return getVisibleElements({
2891
+ scrollEl: this.container,
2892
+ views: this._pages,
2893
+ sortByVisibility: true,
2894
+ horizontal: this._isScrollModeHorizontal,
2895
+ rtl: this._isScrollModeHorizontal && this._isContainerRtl
2896
+ });
2897
+ }
2898
+ /**
2899
+ * @param {number} pageNumber
2900
+ */
2901
+
2902
+
2903
+ isPageVisible(pageNumber) {
2904
+ if (!this.pdfDocument) {
2905
+ return false;
2906
+ }
2907
+
2908
+ if (!(Number.isInteger(pageNumber) && pageNumber > 0 && pageNumber <= this.pagesCount)) {
2909
+ console.error(`${this._name}.isPageVisible: "${pageNumber}" is not a valid page.`);
2910
+ return false;
2911
+ }
2912
+
2913
+ return this._getVisiblePages().views.some(function (view) {
2914
+ return view.id === pageNumber;
2915
+ });
2916
+ }
2917
+ /**
2918
+ * @param {number} pageNumber
2919
+ */
2920
+
2921
+
2922
+ isPageCached(pageNumber) {
2923
+ if (!this.pdfDocument || !this._buffer) {
2924
+ return false;
2925
+ }
2926
+
2927
+ if (!(Number.isInteger(pageNumber) && pageNumber > 0 && pageNumber <= this.pagesCount)) {
2928
+ console.error(`${this._name}.isPageCached: "${pageNumber}" is not a valid page.`);
2929
+ return false;
2930
+ }
2931
+
2932
+ const pageView = this._pages[pageNumber - 1];
2933
+
2934
+ if (!pageView) {
2935
+ return false;
2936
+ }
2937
+
2938
+ return this._buffer.has(pageView);
2939
+ }
2940
+
2941
+ cleanup() {
2942
+ for (let i = 0, ii = this._pages.length; i < ii; i++) {
2943
+ if (this._pages[i] && this._pages[i].renderingState !== RenderingStates.FINISHED) {
2944
+ this._pages[i].reset();
2945
+ }
2946
+ }
2947
+ }
2948
+ /**
2949
+ * @private
2950
+ */
2951
+
2952
+
2953
+ _cancelRendering() {
2954
+ for (let i = 0, ii = this._pages.length; i < ii; i++) {
2955
+ if (this._pages[i]) {
2956
+ this._pages[i].cancelRendering();
2957
+ }
2958
+ }
2959
+ }
2960
+ /**
2961
+ * @param {PDFPageView} pageView
2962
+ * @returns {Promise} Returns a promise containing a {PDFPageProxy} object.
2963
+ * @private
2964
+ */
2965
+
2966
+
2967
+ _ensurePdfPageLoaded(pageView) {
2968
+ if (pageView.pdfPage) {
2969
+ return Promise.resolve(pageView.pdfPage);
2970
+ }
2971
+
2972
+ if (this._pagesRequests.has(pageView)) {
2973
+ return this._pagesRequests.get(pageView);
2974
+ }
2975
+
2976
+ const promise = this.pdfDocument.getPage(pageView.id).then(pdfPage => {
2977
+ if (!pageView.pdfPage) {
2978
+ pageView.setPdfPage(pdfPage);
2979
+ }
2980
+
2981
+ this._pagesRequests.delete(pageView);
2982
+
2983
+ return pdfPage;
2984
+ }).catch(reason => {
2985
+ console.error("Unable to get page for page view", reason); // Page error -- there is nothing that can be done.
2986
+
2987
+ this._pagesRequests.delete(pageView);
2988
+ });
2989
+
2990
+ this._pagesRequests.set(pageView, promise);
2991
+
2992
+ return promise;
2993
+ }
2994
+
2995
+ forceRendering(currentlyVisiblePages) {
2996
+ const visiblePages = currentlyVisiblePages || this._getVisiblePages();
2997
+
2998
+ const scrollAhead = this._isScrollModeHorizontal ? this.scroll.right : this.scroll.down;
2999
+ const pageView = this.renderingQueue.getHighestPriority(visiblePages, this._pages, scrollAhead);
3000
+
3001
+ if (pageView) {
3002
+ this._ensurePdfPageLoaded(pageView).then(() => {
3003
+ this.renderingQueue.renderView(pageView);
3004
+ });
3005
+
3006
+ return true;
3007
+ }
3008
+
3009
+ return false;
3010
+ }
3011
+ /**
3012
+ * @param {HTMLDivElement} textLayerDiv
3013
+ * @param {number} pageIndex
3014
+ * @param {PageViewport} viewport
3015
+ * @param {boolean} enhanceTextSelection
3016
+ * @param {EventBus} eventBus
3017
+ * @returns {TextLayerBuilder}
3018
+ */
3019
+
3020
+
3021
+ createTextLayerBuilder(textLayerDiv, pageIndex, viewport, enhanceTextSelection = false, eventBus) {
3022
+ return new TextLayerBuilder({
3023
+ textLayerDiv,
3024
+ eventBus,
3025
+ pageIndex,
3026
+ viewport,
3027
+ findController: this.isInPresentationMode ? null : this.findController,
3028
+ enhanceTextSelection: this.isInPresentationMode ? false : enhanceTextSelection
3029
+ });
3030
+ }
3031
+ /**
3032
+ * @param {HTMLDivElement} pageDiv
3033
+ * @param {PDFPage} pdfPage
3034
+ * @param {AnnotationStorage} [annotationStorage] - Storage for annotation
3035
+ * data in forms.
3036
+ * @param {string} [imageResourcesPath] - Path for image resources, mainly
3037
+ * for annotation icons. Include trailing slash.
3038
+ * @param {boolean} renderInteractiveForms
3039
+ * @param {IL10n} l10n
3040
+ * @param {boolean} [enableScripting]
3041
+ * @param {Promise<boolean>} [hasJSActionsPromise]
3042
+ * @param {Object} [mouseState]
3043
+ * @returns {AnnotationLayerBuilder}
3044
+ */
3045
+
3046
+
3047
+ createAnnotationLayerBuilder(pageDiv, pdfPage, annotationStorage = null, imageResourcesPath = "", renderInteractiveForms = false, l10n = NullL10n, enableScripting = null, hasJSActionsPromise = null, mouseState = null) {
3048
+ var _this$pdfDocument, _this$pdfDocument2, _this$_scriptingManag;
3049
+
3050
+ return new AnnotationLayerBuilder({
3051
+ pageDiv,
3052
+ pdfPage,
3053
+ annotationStorage: annotationStorage || ((_this$pdfDocument = this.pdfDocument) === null || _this$pdfDocument === void 0 ? void 0 : _this$pdfDocument.annotationStorage),
3054
+ imageResourcesPath,
3055
+ renderInteractiveForms,
3056
+ linkService: this.linkService,
3057
+ downloadManager: this.downloadManager,
3058
+ l10n,
3059
+ enableScripting: enableScripting !== null && enableScripting !== void 0 ? enableScripting : this.enableScripting,
3060
+ hasJSActionsPromise: hasJSActionsPromise || ((_this$pdfDocument2 = this.pdfDocument) === null || _this$pdfDocument2 === void 0 ? void 0 : _this$pdfDocument2.hasJSActions()),
3061
+ mouseState: mouseState || ((_this$_scriptingManag = this._scriptingManager) === null || _this$_scriptingManag === void 0 ? void 0 : _this$_scriptingManag.mouseState)
3062
+ });
3063
+ }
3064
+ /**
3065
+ * @param {HTMLDivElement} pageDiv
3066
+ * @param {PDFPage} pdfPage
3067
+ * @param {AnnotationStorage} [annotationStorage] - Storage for annotation
3068
+ * data in forms.
3069
+ * @returns {XfaLayerBuilder}
3070
+ */
3071
+
3072
+
3073
+ createXfaLayerBuilder(pageDiv, pdfPage, annotationStorage = null) {
3074
+ var _this$pdfDocument3;
3075
+
3076
+ return new XfaLayerBuilder({
3077
+ pageDiv,
3078
+ pdfPage,
3079
+ annotationStorage: annotationStorage || ((_this$pdfDocument3 = this.pdfDocument) === null || _this$pdfDocument3 === void 0 ? void 0 : _this$pdfDocument3.annotationStorage)
3080
+ });
3081
+ }
3082
+ /**
3083
+ * @param {PDFPage} pdfPage
3084
+ * @returns {StructTreeLayerBuilder}
3085
+ */
3086
+
3087
+
3088
+ createStructTreeLayerBuilder(pdfPage) {
3089
+ return new StructTreeLayerBuilder({
3090
+ pdfPage
3091
+ });
3092
+ }
3093
+ /**
3094
+ * @type {boolean} Whether all pages of the PDF document have identical
3095
+ * widths and heights.
3096
+ */
3097
+
3098
+
3099
+ get hasEqualPageSizes() {
3100
+ const firstPageView = this._pages[0];
3101
+
3102
+ for (let i = 1, ii = this._pages.length; i < ii; ++i) {
3103
+ const pageView = this._pages[i];
3104
+
3105
+ if (pageView.width !== firstPageView.width || pageView.height !== firstPageView.height) {
3106
+ return false;
3107
+ }
3108
+ }
3109
+
3110
+ return true;
3111
+ }
3112
+ /**
3113
+ * Returns sizes of the pages.
3114
+ * @returns {Array} Array of objects with width/height/rotation fields.
3115
+ */
3116
+
3117
+
3118
+ getPagesOverview() {
3119
+ return this._pages.map(pageView => {
3120
+ const viewport = pageView.pdfPage.getViewport({
3121
+ scale: 1
3122
+ });
3123
+
3124
+ if (!this.enablePrintAutoRotate || isPortraitOrientation(viewport)) {
3125
+ return {
3126
+ width: viewport.width,
3127
+ height: viewport.height,
3128
+ rotation: viewport.rotation
3129
+ };
3130
+ } // Landscape orientation.
3131
+
3132
+
3133
+ return {
3134
+ width: viewport.height,
3135
+ height: viewport.width,
3136
+ rotation: (viewport.rotation - 90) % 360
3137
+ };
3138
+ });
3139
+ }
3140
+ /**
3141
+ * @type {Promise<OptionalContentConfig | null>}
3142
+ */
3143
+
3144
+
3145
+ get optionalContentConfigPromise() {
3146
+ if (!this.pdfDocument) {
3147
+ return Promise.resolve(null);
3148
+ }
3149
+
3150
+ if (!this._optionalContentConfigPromise) {
3151
+ // Prevent issues if the getter is accessed *before* the `onePageRendered`
3152
+ // promise has resolved; won't (normally) happen in the default viewer.
3153
+ return this.pdfDocument.getOptionalContentConfig();
3154
+ }
3155
+
3156
+ return this._optionalContentConfigPromise;
3157
+ }
3158
+ /**
3159
+ * @param {Promise<OptionalContentConfig>} promise - A promise that is
3160
+ * resolved with an {@link OptionalContentConfig} instance.
3161
+ */
3162
+
3163
+
3164
+ set optionalContentConfigPromise(promise) {
3165
+ if (!(promise instanceof Promise)) {
3166
+ throw new Error(`Invalid optionalContentConfigPromise: ${promise}`);
3167
+ }
3168
+
3169
+ if (!this.pdfDocument) {
3170
+ return;
3171
+ }
3172
+
3173
+ if (!this._optionalContentConfigPromise) {
3174
+ // Ignore the setter *before* the `onePageRendered` promise has resolved,
3175
+ // since it'll be overwritten anyway; won't happen in the default viewer.
3176
+ return;
3177
+ }
3178
+
3179
+ this._optionalContentConfigPromise = promise;
3180
+
3181
+ for (const pageView of this._pages) {
3182
+ pageView.update(pageView.scale, pageView.rotation, promise);
3183
+ }
3184
+
3185
+ this.update();
3186
+ this.eventBus.dispatch("optionalcontentconfigchanged", {
3187
+ source: this,
3188
+ promise
3189
+ });
3190
+ }
3191
+ /**
3192
+ * @type {number} One of the values in {ScrollMode}.
3193
+ */
3194
+
3195
+
3196
+ get scrollMode() {
3197
+ return this._scrollMode;
3198
+ }
3199
+ /**
3200
+ * @param {number} mode - The direction in which the document pages should be
3201
+ * laid out within the scrolling container.
3202
+ * The constants from {ScrollMode} should be used.
3203
+ */
3204
+
3205
+
3206
+ set scrollMode(mode) {
3207
+ if (this._scrollMode === mode) {
3208
+ return; // The Scroll mode didn't change.
3209
+ }
3210
+
3211
+ if (!isValidScrollMode(mode)) {
3212
+ throw new Error(`Invalid scroll mode: ${mode}`);
3213
+ }
3214
+
3215
+ this._scrollMode = mode;
3216
+ this.eventBus.dispatch("scrollmodechanged", {
3217
+ source: this,
3218
+ mode
3219
+ });
3220
+
3221
+ this._updateScrollMode(
3222
+ /* pageNumber = */
3223
+ this._currentPageNumber);
3224
+ }
3225
+
3226
+ _updateScrollMode(pageNumber = null) {
3227
+ const scrollMode = this._scrollMode,
3228
+ viewer = this.viewer;
3229
+ viewer.classList.toggle("scrollHorizontal", scrollMode === ScrollMode.HORIZONTAL);
3230
+ viewer.classList.toggle("scrollWrapped", scrollMode === ScrollMode.WRAPPED);
3231
+
3232
+ if (!this.pdfDocument || !pageNumber) {
3233
+ return;
3234
+ } // Non-numeric scale values can be sensitive to the scroll orientation.
3235
+ // Call this before re-scrolling to the current page, to ensure that any
3236
+ // changes in scale don't move the current page.
3237
+
3238
+
3239
+ if (this._currentScaleValue && isNaN(this._currentScaleValue)) {
3240
+ this._setScale(this._currentScaleValue, true);
3241
+ }
3242
+
3243
+ this._setCurrentPageNumber(pageNumber,
3244
+ /* resetCurrentPageView = */
3245
+ true);
3246
+
3247
+ this.update();
3248
+ }
3249
+ /**
3250
+ * @type {number} One of the values in {SpreadMode}.
3251
+ */
3252
+
3253
+
3254
+ get spreadMode() {
3255
+ return this._spreadMode;
3256
+ }
3257
+ /**
3258
+ * @param {number} mode - Group the pages in spreads, starting with odd- or
3259
+ * even-number pages (unless `SpreadMode.NONE` is used).
3260
+ * The constants from {SpreadMode} should be used.
3261
+ */
3262
+
3263
+
3264
+ set spreadMode(mode) {
3265
+ if (this._spreadMode === mode) {
3266
+ return; // The Spread mode didn't change.
3267
+ }
3268
+
3269
+ if (!isValidSpreadMode(mode)) {
3270
+ throw new Error(`Invalid spread mode: ${mode}`);
3271
+ }
3272
+
3273
+ this._spreadMode = mode;
3274
+ this.eventBus.dispatch("spreadmodechanged", {
3275
+ source: this,
3276
+ mode
3277
+ });
3278
+
3279
+ this._updateSpreadMode(
3280
+ /* pageNumber = */
3281
+ this._currentPageNumber);
3282
+ }
3283
+
3284
+ _updateSpreadMode(pageNumber = null) {
3285
+ if (!this.pdfDocument) {
3286
+ return;
3287
+ }
3288
+
3289
+ const viewer = this.viewer,
3290
+ pages = this._pages; // Temporarily remove all the pages from the DOM.
3291
+
3292
+ viewer.textContent = "";
3293
+
3294
+ if (this._spreadMode === SpreadMode.NONE) {
3295
+ for (let i = 0, iMax = pages.length; i < iMax; ++i) {
3296
+ viewer.appendChild(pages[i].div);
3297
+ }
3298
+ } else {
3299
+ const parity = this._spreadMode - 1;
3300
+ let spread = null;
3301
+
3302
+ for (let i = 0, iMax = pages.length; i < iMax; ++i) {
3303
+ if (spread === null) {
3304
+ spread = document.createElement("div");
3305
+ spread.className = "spread";
3306
+ viewer.appendChild(spread);
3307
+ } else if (i % 2 === parity) {
3308
+ spread = spread.cloneNode(false);
3309
+ viewer.appendChild(spread);
3310
+ }
3311
+
3312
+ spread.appendChild(pages[i].div);
3313
+ }
3314
+ }
3315
+
3316
+ if (!pageNumber) {
3317
+ return;
3318
+ }
3319
+
3320
+ if (this._currentScaleValue && isNaN(this._currentScaleValue)) {
3321
+ this._setScale(this._currentScaleValue, true);
3322
+ }
3323
+
3324
+ this._setCurrentPageNumber(pageNumber,
3325
+ /* resetCurrentPageView = */
3326
+ true);
3327
+
3328
+ this.update();
3329
+ }
3330
+ /**
3331
+ * @private
3332
+ */
3333
+
3334
+
3335
+ _getPageAdvance(currentPageNumber, previous = false) {
3336
+ if (this.isInPresentationMode) {
3337
+ return 1;
3338
+ }
3339
+
3340
+ switch (this._scrollMode) {
3341
+ case ScrollMode.WRAPPED:
3342
+ {
3343
+ const {
3344
+ views
3345
+ } = this._getVisiblePages(),
3346
+ pageLayout = new Map(); // Determine the current (visible) page layout.
3347
+
3348
+
3349
+ for (const {
3350
+ id,
3351
+ y,
3352
+ percent,
3353
+ widthPercent
3354
+ } of views) {
3355
+ if (percent === 0 || widthPercent < 100) {
3356
+ continue;
3357
+ }
3358
+
3359
+ let yArray = pageLayout.get(y);
3360
+
3361
+ if (!yArray) {
3362
+ pageLayout.set(y, yArray || (yArray = []));
3363
+ }
3364
+
3365
+ yArray.push(id);
3366
+ } // Find the row of the current page.
3367
+
3368
+
3369
+ for (const yArray of pageLayout.values()) {
3370
+ const currentIndex = yArray.indexOf(currentPageNumber);
3371
+
3372
+ if (currentIndex === -1) {
3373
+ continue;
3374
+ }
3375
+
3376
+ const numPages = yArray.length;
3377
+
3378
+ if (numPages === 1) {
3379
+ break;
3380
+ } // Handle documents with varying page sizes.
3381
+
3382
+
3383
+ if (previous) {
3384
+ for (let i = currentIndex - 1, ii = 0; i >= ii; i--) {
3385
+ const currentId = yArray[i],
3386
+ expectedId = yArray[i + 1] - 1;
3387
+
3388
+ if (currentId < expectedId) {
3389
+ return currentPageNumber - expectedId;
3390
+ }
3391
+ }
3392
+ } else {
3393
+ for (let i = currentIndex + 1, ii = numPages; i < ii; i++) {
3394
+ const currentId = yArray[i],
3395
+ expectedId = yArray[i - 1] + 1;
3396
+
3397
+ if (currentId > expectedId) {
3398
+ return expectedId - currentPageNumber;
3399
+ }
3400
+ }
3401
+ } // The current row is "complete", advance to the previous/next one.
3402
+
3403
+
3404
+ if (previous) {
3405
+ const firstId = yArray[0];
3406
+
3407
+ if (firstId < currentPageNumber) {
3408
+ return currentPageNumber - firstId + 1;
3409
+ }
3410
+ } else {
3411
+ const lastId = yArray[numPages - 1];
3412
+
3413
+ if (lastId > currentPageNumber) {
3414
+ return lastId - currentPageNumber + 1;
3415
+ }
3416
+ }
3417
+
3418
+ break;
3419
+ }
3420
+
3421
+ break;
3422
+ }
3423
+
3424
+ case ScrollMode.HORIZONTAL:
3425
+ {
3426
+ break;
3427
+ }
3428
+
3429
+ case ScrollMode.VERTICAL:
3430
+ {
3431
+ if (this._spreadMode === SpreadMode.NONE) {
3432
+ break; // Normal vertical scrolling.
3433
+ }
3434
+
3435
+ const parity = this._spreadMode - 1;
3436
+
3437
+ if (previous && currentPageNumber % 2 !== parity) {
3438
+ break; // Left-hand side page.
3439
+ } else if (!previous && currentPageNumber % 2 === parity) {
3440
+ break; // Right-hand side page.
3441
+ }
3442
+
3443
+ const {
3444
+ views
3445
+ } = this._getVisiblePages(),
3446
+ expectedId = previous ? currentPageNumber - 1 : currentPageNumber + 1;
3447
+
3448
+ for (const {
3449
+ id,
3450
+ percent,
3451
+ widthPercent
3452
+ } of views) {
3453
+ if (id !== expectedId) {
3454
+ continue;
3455
+ }
3456
+
3457
+ if (percent > 0 && widthPercent === 100) {
3458
+ return 2;
3459
+ }
3460
+
3461
+ break;
3462
+ }
3463
+
3464
+ break;
3465
+ }
3466
+ }
3467
+
3468
+ return 1;
3469
+ }
3470
+ /**
3471
+ * Go to the next page, taking scroll/spread-modes into account.
3472
+ * @returns {boolean} Whether navigation occured.
3473
+ */
3474
+
3475
+
3476
+ nextPage() {
3477
+ const currentPageNumber = this._currentPageNumber,
3478
+ pagesCount = this.pagesCount;
3479
+
3480
+ if (currentPageNumber >= pagesCount) {
3481
+ return false;
3482
+ }
3483
+
3484
+ const advance = this._getPageAdvance(currentPageNumber,
3485
+ /* previous = */
3486
+ false) || 1;
3487
+ this.currentPageNumber = Math.min(currentPageNumber + advance, pagesCount);
3488
+ return true;
3489
+ }
3490
+ /**
3491
+ * Go to the previous page, taking scroll/spread-modes into account.
3492
+ * @returns {boolean} Whether navigation occured.
3493
+ */
3494
+
3495
+
3496
+ previousPage() {
3497
+ const currentPageNumber = this._currentPageNumber;
3498
+
3499
+ if (currentPageNumber <= 1) {
3500
+ return false;
3501
+ }
3502
+
3503
+ const advance = this._getPageAdvance(currentPageNumber,
3504
+ /* previous = */
3505
+ true) || 1;
3506
+ this.currentPageNumber = Math.max(currentPageNumber - advance, 1);
3507
+ return true;
3508
+ }
3509
+
3510
+ }
3511
+
3512
+ /* Copyright 2014 Mozilla Foundation
3513
+ *
3514
+ * Licensed under the Apache License, Version 2.0 (the "License");
3515
+ * you may not use this file except in compliance with the License.
3516
+ * You may obtain a copy of the License at
3517
+ *
3518
+ * http://www.apache.org/licenses/LICENSE-2.0
3519
+ *
3520
+ * Unless required by applicable law or agreed to in writing, software
3521
+ * distributed under the License is distributed on an "AS IS" BASIS,
3522
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
3523
+ * See the License for the specific language governing permissions and
3524
+ * limitations under the License.
3525
+ */
3526
+
3527
+ class PDFViewer extends BaseViewer {
3528
+ get _viewerElement() {
3529
+ return shadow(this, "_viewerElement", this.viewer);
3530
+ }
3531
+
3532
+ _scrollIntoView({
3533
+ pageDiv,
3534
+ pageSpot = null,
3535
+ pageNumber = null
3536
+ }) {
3537
+ if (!pageSpot && !this.isInPresentationMode) {
3538
+ const left = pageDiv.offsetLeft + pageDiv.clientLeft;
3539
+ const right = left + pageDiv.clientWidth;
3540
+ const {
3541
+ scrollLeft,
3542
+ clientWidth
3543
+ } = this.container;
3544
+
3545
+ if (this._isScrollModeHorizontal || left < scrollLeft || right > scrollLeft + clientWidth) {
3546
+ pageSpot = {
3547
+ left: 0,
3548
+ top: 0
3549
+ };
3550
+ }
3551
+ }
3552
+
3553
+ super._scrollIntoView({
3554
+ pageDiv,
3555
+ pageSpot,
3556
+ pageNumber
3557
+ });
3558
+ }
3559
+
3560
+ _getVisiblePages() {
3561
+ if (this.isInPresentationMode) {
3562
+ // The algorithm in `getVisibleElements` doesn't work in all browsers and
3563
+ // configurations (e.g. Chrome) when Presentation Mode is active.
3564
+ return this._getCurrentVisiblePage();
3565
+ }
3566
+
3567
+ return super._getVisiblePages();
3568
+ }
3569
+
3570
+ _updateHelper(visiblePages) {
3571
+ if (this.isInPresentationMode) {
3572
+ return;
3573
+ }
3574
+
3575
+ let currentId = this._currentPageNumber;
3576
+ let stillFullyVisible = false;
3577
+
3578
+ for (const page of visiblePages) {
3579
+ if (page.percent < 100) {
3580
+ break;
3581
+ }
3582
+
3583
+ if (page.id === currentId && this._scrollMode === ScrollMode.VERTICAL && this._spreadMode === SpreadMode.NONE) {
3584
+ stillFullyVisible = true;
3585
+ break;
3586
+ }
3587
+ }
3588
+
3589
+ if (!stillFullyVisible) {
3590
+ currentId = visiblePages[0].id;
3591
+ }
3592
+
3593
+ this._setCurrentPageNumber(currentId);
3594
+ }
3595
+
3596
+ }
3597
+
3598
+ export { PDFViewer };