summaryrefslogtreecommitdiffstats
path: root/toolkit/components/pdfjs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
commit26a029d407be480d791972afb5975cf62c9360a6 (patch)
treef435a8308119effd964b339f76abb83a57c29483 /toolkit/components/pdfjs
parentInitial commit. (diff)
downloadfirefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz
firefox-26a029d407be480d791972afb5975cf62c9360a6.zip
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'toolkit/components/pdfjs')
-rw-r--r--toolkit/components/pdfjs/LICENSE177
-rw-r--r--toolkit/components/pdfjs/README.mozilla11
-rw-r--r--toolkit/components/pdfjs/chrome.manifest1
-rw-r--r--toolkit/components/pdfjs/components.conf19
-rw-r--r--toolkit/components/pdfjs/content/GeckoViewPdfjsChild.sys.mjs47
-rw-r--r--toolkit/components/pdfjs/content/GeckoViewPdfjsParent.sys.mjs364
-rw-r--r--toolkit/components/pdfjs/content/PdfJs.sys.mjs256
-rw-r--r--toolkit/components/pdfjs/content/PdfJsDefaultPreferences.sys.mjs51
-rw-r--r--toolkit/components/pdfjs/content/PdfJsNetwork.sys.mjs193
-rw-r--r--toolkit/components/pdfjs/content/PdfJsTelemetry.sys.mjs138
-rw-r--r--toolkit/components/pdfjs/content/PdfSandbox.sys.mjs87
-rw-r--r--toolkit/components/pdfjs/content/PdfStreamConverter.sys.mjs1110
-rw-r--r--toolkit/components/pdfjs/content/PdfjsChild.sys.mjs52
-rw-r--r--toolkit/components/pdfjs/content/PdfjsParent.sys.mjs290
-rw-r--r--toolkit/components/pdfjs/content/build/pdf.mjs17198
-rw-r--r--toolkit/components/pdfjs/content/build/pdf.sandbox.external.sys.mjs127
-rw-r--r--toolkit/components/pdfjs/content/build/pdf.scripting.mjs3964
-rw-r--r--toolkit/components/pdfjs/content/build/pdf.worker.mjs57228
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/78-EUC-H.bcmapbin0 -> 2404 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/78-EUC-V.bcmapbin0 -> 173 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/78-H.bcmapbin0 -> 2379 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/78-RKSJ-H.bcmapbin0 -> 2398 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/78-RKSJ-V.bcmapbin0 -> 173 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/78-V.bcmapbin0 -> 169 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/78ms-RKSJ-H.bcmapbin0 -> 2651 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/78ms-RKSJ-V.bcmapbin0 -> 290 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/83pv-RKSJ-H.bcmapbin0 -> 905 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/90ms-RKSJ-H.bcmapbin0 -> 721 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/90ms-RKSJ-V.bcmapbin0 -> 290 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/90msp-RKSJ-H.bcmapbin0 -> 715 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/90msp-RKSJ-V.bcmapbin0 -> 291 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/90pv-RKSJ-H.bcmapbin0 -> 982 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/90pv-RKSJ-V.bcmapbin0 -> 260 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/Add-H.bcmapbin0 -> 2419 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/Add-RKSJ-H.bcmapbin0 -> 2413 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/Add-RKSJ-V.bcmapbin0 -> 287 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/Add-V.bcmapbin0 -> 282 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/Adobe-CNS1-0.bcmapbin0 -> 317 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/Adobe-CNS1-1.bcmapbin0 -> 371 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/Adobe-CNS1-2.bcmapbin0 -> 376 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/Adobe-CNS1-3.bcmapbin0 -> 401 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/Adobe-CNS1-4.bcmapbin0 -> 405 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/Adobe-CNS1-5.bcmapbin0 -> 406 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/Adobe-CNS1-6.bcmapbin0 -> 406 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/Adobe-CNS1-UCS2.bcmapbin0 -> 41193 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/Adobe-GB1-0.bcmapbin0 -> 217 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/Adobe-GB1-1.bcmapbin0 -> 250 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/Adobe-GB1-2.bcmapbin0 -> 465 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/Adobe-GB1-3.bcmapbin0 -> 470 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/Adobe-GB1-4.bcmapbin0 -> 601 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/Adobe-GB1-5.bcmapbin0 -> 625 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/Adobe-GB1-UCS2.bcmapbin0 -> 33974 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/Adobe-Japan1-0.bcmapbin0 -> 225 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/Adobe-Japan1-1.bcmapbin0 -> 226 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/Adobe-Japan1-2.bcmapbin0 -> 233 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/Adobe-Japan1-3.bcmapbin0 -> 242 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/Adobe-Japan1-4.bcmapbin0 -> 337 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/Adobe-Japan1-5.bcmapbin0 -> 430 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/Adobe-Japan1-6.bcmapbin0 -> 485 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/Adobe-Japan1-UCS2.bcmapbin0 -> 40951 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/Adobe-Korea1-0.bcmapbin0 -> 241 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/Adobe-Korea1-1.bcmapbin0 -> 386 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/Adobe-Korea1-2.bcmapbin0 -> 391 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/Adobe-Korea1-UCS2.bcmapbin0 -> 23293 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/B5-H.bcmapbin0 -> 1086 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/B5-V.bcmapbin0 -> 142 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/B5pc-H.bcmapbin0 -> 1099 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/B5pc-V.bcmapbin0 -> 144 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/CNS-EUC-H.bcmapbin0 -> 1780 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/CNS-EUC-V.bcmapbin0 -> 1920 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/CNS1-H.bcmapbin0 -> 706 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/CNS1-V.bcmapbin0 -> 143 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/CNS2-H.bcmapbin0 -> 504 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/CNS2-V.bcmap3
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/ETHK-B5-H.bcmapbin0 -> 4426 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/ETHK-B5-V.bcmapbin0 -> 158 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/ETen-B5-H.bcmapbin0 -> 1125 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/ETen-B5-V.bcmapbin0 -> 158 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/ETenms-B5-H.bcmap3
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/ETenms-B5-V.bcmapbin0 -> 172 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/EUC-H.bcmapbin0 -> 578 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/EUC-V.bcmapbin0 -> 170 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/Ext-H.bcmapbin0 -> 2536 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/Ext-RKSJ-H.bcmapbin0 -> 2542 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/Ext-RKSJ-V.bcmapbin0 -> 218 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/Ext-V.bcmapbin0 -> 215 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/GB-EUC-H.bcmapbin0 -> 549 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/GB-EUC-V.bcmapbin0 -> 179 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/GB-H.bcmap4
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/GB-V.bcmapbin0 -> 175 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/GBK-EUC-H.bcmapbin0 -> 14692 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/GBK-EUC-V.bcmapbin0 -> 180 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/GBK2K-H.bcmapbin0 -> 19662 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/GBK2K-V.bcmapbin0 -> 219 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/GBKp-EUC-H.bcmapbin0 -> 14686 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/GBKp-EUC-V.bcmapbin0 -> 181 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/GBT-EUC-H.bcmapbin0 -> 7290 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/GBT-EUC-V.bcmapbin0 -> 180 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/GBT-H.bcmapbin0 -> 7269 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/GBT-V.bcmapbin0 -> 176 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/GBTpc-EUC-H.bcmapbin0 -> 7298 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/GBTpc-EUC-V.bcmapbin0 -> 182 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/GBpc-EUC-H.bcmapbin0 -> 557 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/GBpc-EUC-V.bcmapbin0 -> 181 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/H.bcmapbin0 -> 553 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/HKdla-B5-H.bcmapbin0 -> 2654 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/HKdla-B5-V.bcmapbin0 -> 148 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/HKdlb-B5-H.bcmapbin0 -> 2414 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/HKdlb-B5-V.bcmapbin0 -> 148 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/HKgccs-B5-H.bcmapbin0 -> 2292 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/HKgccs-B5-V.bcmapbin0 -> 149 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/HKm314-B5-H.bcmapbin0 -> 1772 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/HKm314-B5-V.bcmapbin0 -> 149 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/HKm471-B5-H.bcmapbin0 -> 2171 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/HKm471-B5-V.bcmapbin0 -> 149 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/HKscs-B5-H.bcmapbin0 -> 4437 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/HKscs-B5-V.bcmapbin0 -> 159 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/Hankaku.bcmapbin0 -> 132 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/Hiragana.bcmapbin0 -> 124 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/KSC-EUC-H.bcmapbin0 -> 1848 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/KSC-EUC-V.bcmapbin0 -> 164 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/KSC-H.bcmapbin0 -> 1831 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/KSC-Johab-H.bcmapbin0 -> 16791 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/KSC-Johab-V.bcmapbin0 -> 166 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/KSC-V.bcmapbin0 -> 160 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/KSCms-UHC-H.bcmapbin0 -> 2787 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/KSCms-UHC-HW-H.bcmapbin0 -> 2789 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/KSCms-UHC-HW-V.bcmapbin0 -> 169 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/KSCms-UHC-V.bcmapbin0 -> 166 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/KSCpc-EUC-H.bcmapbin0 -> 2024 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/KSCpc-EUC-V.bcmapbin0 -> 166 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/Katakana.bcmapbin0 -> 100 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/LICENSE36
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/NWP-H.bcmapbin0 -> 2765 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/NWP-V.bcmapbin0 -> 252 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/RKSJ-H.bcmapbin0 -> 534 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/RKSJ-V.bcmapbin0 -> 170 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/Roman.bcmapbin0 -> 96 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/UniCNS-UCS2-H.bcmapbin0 -> 48280 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/UniCNS-UCS2-V.bcmapbin0 -> 156 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/UniCNS-UTF16-H.bcmapbin0 -> 50419 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/UniCNS-UTF16-V.bcmapbin0 -> 156 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/UniCNS-UTF32-H.bcmapbin0 -> 52679 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/UniCNS-UTF32-V.bcmapbin0 -> 160 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/UniCNS-UTF8-H.bcmapbin0 -> 53629 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/UniCNS-UTF8-V.bcmapbin0 -> 157 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/UniGB-UCS2-H.bcmapbin0 -> 43366 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/UniGB-UCS2-V.bcmapbin0 -> 193 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/UniGB-UTF16-H.bcmapbin0 -> 44086 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/UniGB-UTF16-V.bcmapbin0 -> 178 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/UniGB-UTF32-H.bcmapbin0 -> 45738 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/UniGB-UTF32-V.bcmapbin0 -> 182 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/UniGB-UTF8-H.bcmapbin0 -> 46837 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/UniGB-UTF8-V.bcmapbin0 -> 181 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/UniJIS-UCS2-H.bcmapbin0 -> 25439 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/UniJIS-UCS2-HW-H.bcmapbin0 -> 119 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/UniJIS-UCS2-HW-V.bcmapbin0 -> 680 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/UniJIS-UCS2-V.bcmapbin0 -> 664 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/UniJIS-UTF16-H.bcmapbin0 -> 39443 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/UniJIS-UTF16-V.bcmapbin0 -> 643 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/UniJIS-UTF32-H.bcmapbin0 -> 40539 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/UniJIS-UTF32-V.bcmapbin0 -> 677 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/UniJIS-UTF8-H.bcmapbin0 -> 41695 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/UniJIS-UTF8-V.bcmapbin0 -> 678 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/UniJIS2004-UTF16-H.bcmapbin0 -> 39534 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/UniJIS2004-UTF16-V.bcmapbin0 -> 647 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/UniJIS2004-UTF32-H.bcmapbin0 -> 40630 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/UniJIS2004-UTF32-V.bcmapbin0 -> 681 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/UniJIS2004-UTF8-H.bcmapbin0 -> 41779 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/UniJIS2004-UTF8-V.bcmapbin0 -> 682 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/UniJISPro-UCS2-HW-V.bcmapbin0 -> 705 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/UniJISPro-UCS2-V.bcmapbin0 -> 689 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/UniJISPro-UTF8-V.bcmapbin0 -> 726 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/UniJISX0213-UTF32-H.bcmapbin0 -> 40517 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/UniJISX0213-UTF32-V.bcmapbin0 -> 684 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/UniJISX02132004-UTF32-H.bcmapbin0 -> 40608 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/UniJISX02132004-UTF32-V.bcmapbin0 -> 688 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/UniKS-UCS2-H.bcmapbin0 -> 25783 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/UniKS-UCS2-V.bcmapbin0 -> 178 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/UniKS-UTF16-H.bcmapbin0 -> 26327 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/UniKS-UTF16-V.bcmapbin0 -> 164 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/UniKS-UTF32-H.bcmapbin0 -> 26451 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/UniKS-UTF32-V.bcmapbin0 -> 168 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/UniKS-UTF8-H.bcmapbin0 -> 27790 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/UniKS-UTF8-V.bcmapbin0 -> 169 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/V.bcmapbin0 -> 166 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/cmaps/WP-Symbol.bcmapbin0 -> 179 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/debugger.css111
-rw-r--r--toolkit/components/pdfjs/content/web/debugger.mjs623
-rw-r--r--toolkit/components/pdfjs/content/web/images/altText_add.svg3
-rw-r--r--toolkit/components/pdfjs/content/web/images/altText_done.svg3
-rw-r--r--toolkit/components/pdfjs/content/web/images/annotation-check.svg11
-rw-r--r--toolkit/components/pdfjs/content/web/images/annotation-comment.svg16
-rw-r--r--toolkit/components/pdfjs/content/web/images/annotation-help.svg26
-rw-r--r--toolkit/components/pdfjs/content/web/images/annotation-insert.svg10
-rw-r--r--toolkit/components/pdfjs/content/web/images/annotation-key.svg11
-rw-r--r--toolkit/components/pdfjs/content/web/images/annotation-newparagraph.svg11
-rw-r--r--toolkit/components/pdfjs/content/web/images/annotation-noicon.svg7
-rw-r--r--toolkit/components/pdfjs/content/web/images/annotation-note.svg42
-rw-r--r--toolkit/components/pdfjs/content/web/images/annotation-paperclip.svg6
-rw-r--r--toolkit/components/pdfjs/content/web/images/annotation-paragraph.svg16
-rw-r--r--toolkit/components/pdfjs/content/web/images/annotation-pushpin.svg7
-rw-r--r--toolkit/components/pdfjs/content/web/images/cursor-editorFreeHighlight.svg6
-rw-r--r--toolkit/components/pdfjs/content/web/images/cursor-editorFreeText.svg3
-rw-r--r--toolkit/components/pdfjs/content/web/images/cursor-editorInk.svg4
-rw-r--r--toolkit/components/pdfjs/content/web/images/cursor-editorTextHighlight.svg8
-rw-r--r--toolkit/components/pdfjs/content/web/images/editor-toolbar-delete.svg5
-rw-r--r--toolkit/components/pdfjs/content/web/images/findbarButton-next.svg3
-rw-r--r--toolkit/components/pdfjs/content/web/images/findbarButton-previous.svg3
-rw-r--r--toolkit/components/pdfjs/content/web/images/gv-toolbarButton-download.svg3
-rw-r--r--toolkit/components/pdfjs/content/web/images/gv-toolbarButton-openinapp.svg11
-rw-r--r--toolkit/components/pdfjs/content/web/images/loading-icon.gifbin0 -> 2545 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/images/loading.svg1
-rw-r--r--toolkit/components/pdfjs/content/web/images/secondaryToolbarButton-documentProperties.svg3
-rw-r--r--toolkit/components/pdfjs/content/web/images/secondaryToolbarButton-firstPage.svg3
-rw-r--r--toolkit/components/pdfjs/content/web/images/secondaryToolbarButton-handTool.svg3
-rw-r--r--toolkit/components/pdfjs/content/web/images/secondaryToolbarButton-lastPage.svg3
-rw-r--r--toolkit/components/pdfjs/content/web/images/secondaryToolbarButton-rotateCcw.svg3
-rw-r--r--toolkit/components/pdfjs/content/web/images/secondaryToolbarButton-rotateCw.svg3
-rw-r--r--toolkit/components/pdfjs/content/web/images/secondaryToolbarButton-scrollHorizontal.svg3
-rw-r--r--toolkit/components/pdfjs/content/web/images/secondaryToolbarButton-scrollPage.svg3
-rw-r--r--toolkit/components/pdfjs/content/web/images/secondaryToolbarButton-scrollVertical.svg3
-rw-r--r--toolkit/components/pdfjs/content/web/images/secondaryToolbarButton-scrollWrapped.svg3
-rw-r--r--toolkit/components/pdfjs/content/web/images/secondaryToolbarButton-selectTool.svg3
-rw-r--r--toolkit/components/pdfjs/content/web/images/secondaryToolbarButton-spreadEven.svg3
-rw-r--r--toolkit/components/pdfjs/content/web/images/secondaryToolbarButton-spreadNone.svg3
-rw-r--r--toolkit/components/pdfjs/content/web/images/secondaryToolbarButton-spreadOdd.svg3
-rw-r--r--toolkit/components/pdfjs/content/web/images/toolbarButton-bookmark.svg3
-rw-r--r--toolkit/components/pdfjs/content/web/images/toolbarButton-currentOutlineItem.svg3
-rw-r--r--toolkit/components/pdfjs/content/web/images/toolbarButton-download.svg4
-rw-r--r--toolkit/components/pdfjs/content/web/images/toolbarButton-editorFreeText.svg5
-rw-r--r--toolkit/components/pdfjs/content/web/images/toolbarButton-editorHighlight.svg6
-rw-r--r--toolkit/components/pdfjs/content/web/images/toolbarButton-editorInk.svg4
-rw-r--r--toolkit/components/pdfjs/content/web/images/toolbarButton-editorStamp.svg8
-rw-r--r--toolkit/components/pdfjs/content/web/images/toolbarButton-menuArrow.svg3
-rw-r--r--toolkit/components/pdfjs/content/web/images/toolbarButton-pageDown.svg3
-rw-r--r--toolkit/components/pdfjs/content/web/images/toolbarButton-pageUp.svg3
-rw-r--r--toolkit/components/pdfjs/content/web/images/toolbarButton-presentationMode.svg3
-rw-r--r--toolkit/components/pdfjs/content/web/images/toolbarButton-print.svg3
-rw-r--r--toolkit/components/pdfjs/content/web/images/toolbarButton-search.svg3
-rw-r--r--toolkit/components/pdfjs/content/web/images/toolbarButton-secondaryToolbarToggle.svg3
-rw-r--r--toolkit/components/pdfjs/content/web/images/toolbarButton-sidebarToggle.svg3
-rw-r--r--toolkit/components/pdfjs/content/web/images/toolbarButton-viewAttachments.svg3
-rw-r--r--toolkit/components/pdfjs/content/web/images/toolbarButton-viewLayers.svg3
-rw-r--r--toolkit/components/pdfjs/content/web/images/toolbarButton-viewOutline.svg3
-rw-r--r--toolkit/components/pdfjs/content/web/images/toolbarButton-viewThumbnail.svg3
-rw-r--r--toolkit/components/pdfjs/content/web/images/toolbarButton-zoomIn.svg3
-rw-r--r--toolkit/components/pdfjs/content/web/images/toolbarButton-zoomOut.svg3
-rw-r--r--toolkit/components/pdfjs/content/web/images/treeitem-collapsed.svg1
-rw-r--r--toolkit/components/pdfjs/content/web/images/treeitem-expanded.svg1
-rw-r--r--toolkit/components/pdfjs/content/web/standard_fonts/FoxitDingbats.pfbbin0 -> 29513 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/standard_fonts/FoxitFixed.pfbbin0 -> 17597 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/standard_fonts/FoxitFixedBold.pfbbin0 -> 18055 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/standard_fonts/FoxitFixedBoldItalic.pfbbin0 -> 19151 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/standard_fonts/FoxitFixedItalic.pfbbin0 -> 18746 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/standard_fonts/FoxitSerif.pfbbin0 -> 19469 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/standard_fonts/FoxitSerifBold.pfbbin0 -> 19395 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/standard_fonts/FoxitSerifBoldItalic.pfbbin0 -> 20733 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/standard_fonts/FoxitSerifItalic.pfbbin0 -> 21227 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/standard_fonts/FoxitSymbol.pfbbin0 -> 16729 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/standard_fonts/LICENSE_FOXIT27
-rw-r--r--toolkit/components/pdfjs/content/web/standard_fonts/LICENSE_LIBERATION102
-rw-r--r--toolkit/components/pdfjs/content/web/standard_fonts/LiberationSans-Bold.ttfbin0 -> 137052 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/standard_fonts/LiberationSans-BoldItalic.ttfbin0 -> 135124 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/standard_fonts/LiberationSans-Italic.ttfbin0 -> 162036 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/standard_fonts/LiberationSans-Regular.ttfbin0 -> 139512 bytes
-rw-r--r--toolkit/components/pdfjs/content/web/viewer-geckoview.css1261
-rw-r--r--toolkit/components/pdfjs/content/web/viewer-geckoview.html76
-rw-r--r--toolkit/components/pdfjs/content/web/viewer-geckoview.mjs9554
-rw-r--r--toolkit/components/pdfjs/content/web/viewer.css3648
-rw-r--r--toolkit/components/pdfjs/content/web/viewer.html485
-rw-r--r--toolkit/components/pdfjs/content/web/viewer.mjs12740
-rw-r--r--toolkit/components/pdfjs/jar.mn38
-rw-r--r--toolkit/components/pdfjs/metrics.yaml334
-rw-r--r--toolkit/components/pdfjs/moz.build21
-rw-r--r--toolkit/components/pdfjs/moz.yaml61
-rw-r--r--toolkit/components/pdfjs/pdfjs.sys.mjs28
-rw-r--r--toolkit/components/pdfjs/test/browser.toml83
-rw-r--r--toolkit/components/pdfjs/test/browser_pdfjs_download_button.js125
-rw-r--r--toolkit/components/pdfjs/test/browser_pdfjs_editing_contextmenu.js381
-rw-r--r--toolkit/components/pdfjs/test/browser_pdfjs_editing_telemetry.js96
-rw-r--r--toolkit/components/pdfjs/test/browser_pdfjs_fill_login.js108
-rw-r--r--toolkit/components/pdfjs/test/browser_pdfjs_filters.js81
-rw-r--r--toolkit/components/pdfjs/test/browser_pdfjs_find.js137
-rw-r--r--toolkit/components/pdfjs/test/browser_pdfjs_force_opening_files.js89
-rw-r--r--toolkit/components/pdfjs/test/browser_pdfjs_form.js85
-rw-r--r--toolkit/components/pdfjs/test/browser_pdfjs_fullscreen.js84
-rw-r--r--toolkit/components/pdfjs/test/browser_pdfjs_hcm.js104
-rw-r--r--toolkit/components/pdfjs/test/browser_pdfjs_highlight_telemetry.js234
-rw-r--r--toolkit/components/pdfjs/test/browser_pdfjs_js.js49
-rw-r--r--toolkit/components/pdfjs/test/browser_pdfjs_load_telemetry.js51
-rw-r--r--toolkit/components/pdfjs/test/browser_pdfjs_main.js72
-rw-r--r--toolkit/components/pdfjs/test/browser_pdfjs_minimum_font_size.js70
-rw-r--r--toolkit/components/pdfjs/test/browser_pdfjs_navigation.js314
-rw-r--r--toolkit/components/pdfjs/test/browser_pdfjs_nonpdf_filename.js73
-rw-r--r--toolkit/components/pdfjs/test/browser_pdfjs_not_default.js26
-rw-r--r--toolkit/components/pdfjs/test/browser_pdfjs_octet_stream.js146
-rw-r--r--toolkit/components/pdfjs/test/browser_pdfjs_saveas.js216
-rw-r--r--toolkit/components/pdfjs/test/browser_pdfjs_savedialog.js53
-rw-r--r--toolkit/components/pdfjs/test/browser_pdfjs_secondary_toolbar_telemetry.js67
-rw-r--r--toolkit/components/pdfjs/test/browser_pdfjs_stamp_telemetry.js219
-rw-r--r--toolkit/components/pdfjs/test/browser_pdfjs_views.js106
-rw-r--r--toolkit/components/pdfjs/test/browser_pdfjs_zoom.js279
-rw-r--r--toolkit/components/pdfjs/test/file_pdf_download_link.html4
-rw-r--r--toolkit/components/pdfjs/test/file_pdfjs_form.pdfbin0 -> 8586 bytes
-rw-r--r--toolkit/components/pdfjs/test/file_pdfjs_hcm.pdf24
-rw-r--r--toolkit/components/pdfjs/test/file_pdfjs_js.pdfbin0 -> 24153 bytes
-rw-r--r--toolkit/components/pdfjs/test/file_pdfjs_object_stream.pdfbin0 -> 1568 bytes
-rw-r--r--toolkit/components/pdfjs/test/file_pdfjs_object_stream.pdf^headers^2
-rw-r--r--toolkit/components/pdfjs/test/file_pdfjs_test.pdfbin0 -> 150611 bytes
-rw-r--r--toolkit/components/pdfjs/test/file_pdfjs_transfer_map.pdfbin0 -> 62324 bytes
-rw-r--r--toolkit/components/pdfjs/test/head.js428
-rw-r--r--toolkit/components/pdfjs/test/mochitest.toml7
-rw-r--r--toolkit/components/pdfjs/test/moz.pngbin0 -> 580 bytes
-rw-r--r--toolkit/components/pdfjs/test/test_pdf_file_in_iframe.html50
-rwxr-xr-xtoolkit/components/pdfjs/update.sh49
316 files changed, 114715 insertions, 0 deletions
diff --git a/toolkit/components/pdfjs/LICENSE b/toolkit/components/pdfjs/LICENSE
new file mode 100644
index 0000000000..f433b1a53f
--- /dev/null
+++ b/toolkit/components/pdfjs/LICENSE
@@ -0,0 +1,177 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
diff --git a/toolkit/components/pdfjs/README.mozilla b/toolkit/components/pdfjs/README.mozilla
new file mode 100644
index 0000000000..e34cf727d8
--- /dev/null
+++ b/toolkit/components/pdfjs/README.mozilla
@@ -0,0 +1,11 @@
+This is the PDF.js project output, https://github.com/mozilla/pdf.js
+
+The current upstream commit is documented in the revision field in moz.yaml
+
+To update PDF.js locally, run
+ ./mach vendor toolkit/components/pdfjs/moz.yaml
+
+To avoid cloning PDF.js locally for every invocation of that command, you can
+point ./mach vendor at a local repo by setting the PDFJS_CHECKOUT env var.
+The update process will perform a git fetch and checkout the latest version to
+update to, so any uncommited local changes will cause the update script to break. \ No newline at end of file
diff --git a/toolkit/components/pdfjs/chrome.manifest b/toolkit/components/pdfjs/chrome.manifest
new file mode 100644
index 0000000000..1aef83abc4
--- /dev/null
+++ b/toolkit/components/pdfjs/chrome.manifest
@@ -0,0 +1 @@
+resource pdf.js content/
diff --git a/toolkit/components/pdfjs/components.conf b/toolkit/components/pdfjs/components.conf
new file mode 100644
index 0000000000..170a1c4dac
--- /dev/null
+++ b/toolkit/components/pdfjs/components.conf
@@ -0,0 +1,19 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+Classes = [
+ {
+ 'cid': '{d0c5195d-e798-49d4-b1d3-9324328b2291}',
+ 'contract_ids': [
+ '@mozilla.org/streamconv;1?from=application/pdf&to=*/*',
+ '@mozilla.org/streamconv;1?from=application/pdf&to=text/html',
+ '@mozilla.org/streamconv;1?from=application/octet-stream&to=*/*',
+ '@mozilla.org/streamconv;1?from=application/octet-stream&to=text/html',
+ ],
+ 'esModule': 'resource://gre/modules/pdfjs.sys.mjs',
+ 'constructor': 'StreamConverterFactory',
+ },
+]
diff --git a/toolkit/components/pdfjs/content/GeckoViewPdfjsChild.sys.mjs b/toolkit/components/pdfjs/content/GeckoViewPdfjsChild.sys.mjs
new file mode 100644
index 0000000000..e838c67874
--- /dev/null
+++ b/toolkit/components/pdfjs/content/GeckoViewPdfjsChild.sys.mjs
@@ -0,0 +1,47 @@
+/* Copyright 2022 Mozilla Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { GeckoViewActorChild } from "resource://gre/modules/GeckoViewActorChild.sys.mjs";
+
+export class GeckoViewPdfjsChild extends GeckoViewActorChild {
+ init(aSupportsFind) {
+ if (aSupportsFind) {
+ this.sendAsyncMessage("PDFJS:Parent:addEventListener");
+ }
+ }
+
+ dispatchEvent(aType, aDetail) {
+ const forward = this.contentWindow.document.createEvent("CustomEvent");
+ forward.initCustomEvent(aType, true, true, aDetail);
+ this.contentWindow.dispatchEvent(forward);
+ }
+
+ receiveMessage(aMsg) {
+ debug`receiveMessage: name=${aMsg.name}, data=${aMsg.data}`;
+
+ switch (aMsg.name) {
+ case "PDFJS:Child:handleEvent": {
+ const detail = Cu.cloneInto(aMsg.data.detail, this.contentWindow);
+ this.dispatchEvent(aMsg.data.type, detail);
+ break;
+ }
+ case "PDFJS:Child:getNimbus":
+ Services.obs.notifyObservers(aMsg.data, "pdfjs-getNimbus");
+ break;
+ }
+ }
+}
+
+const { debug } = GeckoViewPdfjsChild.initLogging("GeckoViewPdfjsChild");
diff --git a/toolkit/components/pdfjs/content/GeckoViewPdfjsParent.sys.mjs b/toolkit/components/pdfjs/content/GeckoViewPdfjsParent.sys.mjs
new file mode 100644
index 0000000000..b07ed8c7b1
--- /dev/null
+++ b/toolkit/components/pdfjs/content/GeckoViewPdfjsParent.sys.mjs
@@ -0,0 +1,364 @@
+/* Copyright 2022 Mozilla Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { GeckoViewActorParent } from "resource://gre/modules/GeckoViewActorParent.sys.mjs";
+
+const lazy = {};
+ChromeUtils.defineESModuleGetters(lazy, {
+ PdfJsTelemetry: "resource://pdf.js/PdfJsTelemetry.sys.mjs",
+ PrivateBrowsingUtils: "resource://gre/modules/PrivateBrowsingUtils.sys.mjs",
+});
+
+class FindHandler {
+ #browser;
+
+ #callbacks = null;
+
+ #state = null;
+
+ constructor(aBrowser) {
+ this.#browser = aBrowser;
+ }
+
+ cleanup() {
+ this.#state = null;
+ this.#callbacks = null;
+ }
+
+ onEvent(aEvent, aData, aCallback) {
+ if (
+ this.#browser.contentPrincipal.spec !==
+ "resource://pdf.js/web/viewer.html"
+ ) {
+ return;
+ }
+
+ debug`onEvent: name=${aEvent}, data=${aData}`;
+
+ switch (aEvent) {
+ case "GeckoView:ClearMatches":
+ this.cleanup();
+ this.#browser.sendMessageToActor(
+ "PDFJS:Child:handleEvent",
+ {
+ type: "findbarclose",
+ detail: null,
+ },
+ "GeckoViewPdfjs"
+ );
+ break;
+ case "GeckoView:DisplayMatches":
+ if (!this.#state) {
+ return;
+ }
+ this.#browser.sendMessageToActor(
+ "PDFJS:Child:handleEvent",
+ {
+ type: "findhighlightallchange",
+ detail: this.#state,
+ },
+ "GeckoViewPdfjs"
+ );
+ break;
+ case "GeckoView:FindInPage":
+ const type = this.#getFindType(aData);
+ this.#browser.sendMessageToActor(
+ "PDFJS:Child:handleEvent",
+ {
+ type,
+ detail: this.#state,
+ },
+ "GeckoViewPdfjs"
+ );
+ this.#callbacks.push([aCallback, this.#state]);
+ break;
+ }
+ }
+
+ #getFindType(aData) {
+ const newState = {
+ query: this.#state?.query,
+ caseSensitive: !!aData.matchCase,
+ entireWord: !!aData.wholeWord,
+ highlightAll: !!aData.highlightAll,
+ findPrevious: !!aData.backwards,
+ matchDiacritics: !!aData.matchDiacritics,
+ };
+ if (!this.#state) {
+ // It's a new search.
+ newState.query = aData.searchString;
+ this.#state = newState;
+ this.#callbacks = [];
+ return "find";
+ }
+
+ if (aData.searchString && this.#state.query !== aData.searchString) {
+ // The searched string has changed.
+ newState.query = aData.searchString;
+ this.#state = newState;
+ return "find";
+ }
+
+ for (const [key, type] of [
+ ["caseSensitive", "findcasesensitivitychange"],
+ ["entireWord", "findentirewordchange"],
+ ["matchDiacritics", "finddiacriticmatchingchange"],
+ ]) {
+ if (this.#state[key] !== newState[key]) {
+ this.#state = newState;
+ return type;
+ }
+ }
+
+ this.#state = newState;
+ return "findagain";
+ }
+
+ updateMatchesCount(aData, aResult) {
+ if (
+ (aResult !== Ci.nsITypeAheadFind.FIND_FOUND &&
+ aResult !== Ci.nsITypeAheadFind.FIND_WRAPPED) ||
+ !this.#state
+ ) {
+ return;
+ }
+
+ if (this.#callbacks.length === 0) {
+ warn`There are no callbacks to use to set the matches count.`;
+ return;
+ }
+
+ const [callback, state] = this.#callbacks.shift();
+
+ aData ||= { current: 0, total: -1 };
+
+ const response = {
+ found: aData.total !== 0,
+ wrapped:
+ aData.total === 0 || aResult === Ci.nsITypeAheadFind.FIND_WRAPPED,
+ current: aData.current,
+ total: aData.total,
+ searchString: state.query,
+ linkURL: null,
+ clientRect: null,
+ flags: {
+ backwards: state.findPrevious,
+ matchCase: state.caseSensitive,
+ wholeWord: state.entireWord,
+ },
+ };
+ callback.onSuccess(response);
+ }
+}
+
+class FileSaver {
+ #browser;
+
+ #callback = null;
+
+ #eventDispatcher;
+
+ constructor(aBrowser, eventDispatcher) {
+ this.#browser = aBrowser;
+ this.#eventDispatcher = eventDispatcher;
+ }
+
+ cleanup() {
+ this.#callback = null;
+ }
+
+ onEvent(aEvent, aData, aCallback) {
+ if (
+ this.#browser.contentPrincipal.spec !==
+ "resource://pdf.js/web/viewer.html"
+ ) {
+ return;
+ }
+
+ lazy.PdfJsTelemetry.onGeckoview("save_as_pdf_tapped");
+
+ this.#callback = aCallback;
+ this.#browser.sendMessageToActor(
+ "PDFJS:Child:handleEvent",
+ {
+ type: "save",
+ },
+ "GeckoViewPdfjs"
+ );
+ }
+
+ async save({
+ blobUrl,
+ filename,
+ originalUrl,
+ options: { openInExternalApp },
+ }) {
+ try {
+ const isPrivate = lazy.PrivateBrowsingUtils.isBrowserPrivate(
+ this.#browser
+ );
+
+ if (this.#callback) {
+ // "Save as PDF" from the share menu.
+ this.#callback.onSuccess({
+ url: blobUrl,
+ filename,
+ originalUrl,
+ isPrivate,
+ });
+ } else {
+ // "Download" or "Open in app" from the pdf.js toolbar.
+ this.#eventDispatcher.sendRequest({
+ type: "GeckoView:SavePdf",
+ url: blobUrl,
+ filename,
+ originalUrl,
+ isPrivate,
+ skipConfirmation: true,
+ requestExternalApp: !!openInExternalApp,
+ });
+ }
+ lazy.PdfJsTelemetry.onGeckoview("download_succeeded");
+ } catch (e) {
+ lazy.PdfJsTelemetry.onGeckoview("download_failed");
+ if (this.#callback) {
+ this.#callback?.onError(`Cannot save the pdf: ${e}.`);
+ } else {
+ warn`Cannot save the pdf because of: ${e}`;
+ }
+ } finally {
+ this.cleanup();
+ }
+ }
+}
+
+export class GeckoViewPdfjsParent extends GeckoViewActorParent {
+ #findHandler;
+
+ #fileSaver;
+
+ receiveMessage(aMsg) {
+ debug`receiveMessage: name=${aMsg.name}, data=${aMsg.data}`;
+
+ switch (aMsg.name) {
+ case "PDFJS:Parent:updateControlState":
+ return this.#updateControlState(aMsg);
+ case "PDFJS:Parent:updateMatchesCount":
+ return this.#updateMatchesCount(aMsg);
+ case "PDFJS:Parent:addEventListener":
+ return this.#addEventListener();
+ case "PDFJS:Parent:saveURL":
+ return this.#save(aMsg);
+ case "PDFJS:Parent:getNimbus":
+ return this.#getExperimentFeature();
+ case "PDFJS:Parent:recordExposure":
+ return this.#recordExposure();
+ case "PDFJS:Parent:reportTelemetry":
+ return this.#reportTelemetry(aMsg);
+ default:
+ break;
+ }
+
+ return undefined;
+ }
+
+ didDestroy() {
+ debug`didDestroy`;
+
+ if (!this.#findHandler) {
+ return;
+ }
+
+ // The eventDispatcher is null when the tab is destroyed.
+ if (this.eventDispatcher) {
+ this.eventDispatcher.unregisterListener(this.#findHandler, [
+ "GeckoView:ClearMatches",
+ "GeckoView:DisplayMatches",
+ "GeckoView:FindInPage",
+ ]);
+ this.eventDispatcher.unregisterListener(this.#fileSaver, [
+ "GeckoView:PDFSave",
+ ]);
+ }
+
+ this.#findHandler.cleanup();
+ this.#findHandler = null;
+ this.#fileSaver.cleanup();
+ this.#fileSaver = null;
+ }
+
+ #addEventListener() {
+ if (this.#findHandler) {
+ this.#findHandler.cleanup();
+ return;
+ }
+
+ this.#findHandler = new FindHandler(this.browser);
+ this.eventDispatcher.registerListener(this.#findHandler, [
+ "GeckoView:ClearMatches",
+ "GeckoView:DisplayMatches",
+ "GeckoView:FindInPage",
+ ]);
+
+ this.#fileSaver = new FileSaver(this.browser, this.eventDispatcher);
+ this.eventDispatcher.registerListener(this.#fileSaver, [
+ "GeckoView:PDFSave",
+ ]);
+ }
+
+ #updateMatchesCount({ data }) {
+ this.#findHandler.updateMatchesCount(data, Ci.nsITypeAheadFind.FIND_FOUND);
+ }
+
+ #updateControlState({ data: { matchesCount, result } }) {
+ this.#findHandler.updateMatchesCount(matchesCount, result);
+ }
+
+ #save({ data }) {
+ this.#fileSaver.save(data);
+ }
+
+ async #getExperimentFeature() {
+ let result = null;
+ try {
+ const experimentActor = this.window.moduleManager.getActor(
+ "GeckoViewExperimentDelegate"
+ );
+ result = await experimentActor.getExperimentFeature("pdfjs");
+ } catch (e) {
+ warn`Cannot get experiment feature: ${e}`;
+ }
+ this.sendAsyncMessage("PDFJS:Child:getNimbus", result);
+ }
+
+ async #recordExposure() {
+ try {
+ const experimentActor = this.window.moduleManager.getActor(
+ "GeckoViewExperimentDelegate"
+ );
+ await experimentActor.recordExposure("pdfjs");
+ } catch (e) {
+ warn`Cannot record experiment exposure: ${e}`;
+ }
+ }
+
+ #reportTelemetry(aMsg) {
+ lazy.PdfJsTelemetry.report(aMsg.data);
+ }
+}
+
+const { debug, warn } = GeckoViewPdfjsParent.initLogging(
+ "GeckoViewPdfjsParent"
+);
diff --git a/toolkit/components/pdfjs/content/PdfJs.sys.mjs b/toolkit/components/pdfjs/content/PdfJs.sys.mjs
new file mode 100644
index 0000000000..fd6757737e
--- /dev/null
+++ b/toolkit/components/pdfjs/content/PdfJs.sys.mjs
@@ -0,0 +1,256 @@
+/* Copyright 2012 Mozilla Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+const PREF_DISABLED = "pdfjs.disabled";
+const PREF_MIGRATION_VERSION = "pdfjs.migrationVersion";
+const PREF_PREVIOUS_ACTION = "pdfjs.previousHandler.preferredAction";
+const PREF_PREVIOUS_ASK = "pdfjs.previousHandler.alwaysAskBeforeHandling";
+const PREF_ISDEFAULT_CACHE_STATE = "pdfjs.enabledCache.state";
+const TOPIC_PDFJS_HANDLER_CHANGED = "pdfjs:handlerChanged";
+const PDF_CONTENT_TYPE = "application/pdf";
+
+import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs";
+
+var Svc = {};
+XPCOMUtils.defineLazyServiceGetter(
+ Svc,
+ "mime",
+ "@mozilla.org/mime;1",
+ "nsIMIMEService"
+);
+XPCOMUtils.defineLazyServiceGetter(
+ Svc,
+ "handlerService",
+ "@mozilla.org/uriloader/handler-service;1",
+ "nsIHandlerService"
+);
+const lazy = {};
+ChromeUtils.defineESModuleGetters(lazy, {
+ PdfJsDefaultPreferences: "resource://pdf.js/PdfJsDefaultPreferences.sys.mjs",
+});
+
+function initializeDefaultPreferences() {
+ var defaultBranch = Services.prefs.getDefaultBranch("pdfjs.");
+ var defaultValue;
+ for (var key in lazy.PdfJsDefaultPreferences) {
+ // Skip prefs that are already defined, so we can enable/disable things
+ // in all.js.
+ let prefType = defaultBranch.getPrefType(key);
+ if (prefType !== Ci.nsIPrefBranch.PREF_INVALID) {
+ continue;
+ }
+ defaultValue = lazy.PdfJsDefaultPreferences[key];
+ switch (typeof defaultValue) {
+ case "boolean":
+ defaultBranch.setBoolPref(key, defaultValue);
+ break;
+ case "number":
+ defaultBranch.setIntPref(key, defaultValue);
+ break;
+ case "string":
+ defaultBranch.setCharPref(key, defaultValue);
+ break;
+ }
+ }
+}
+
+// We're supposed to get this type of thing from the OS, and generally we do.
+// But doing so is expensive, so on startup paths we can use this to make the
+// handler service get and store the Right Thing (it just goes into a JSON
+// file) and avoid the performance issues.
+const gPdfFakeHandlerInfo = {
+ QueryInterface: ChromeUtils.generateQI(["nsIMIMEInfo"]),
+ getFileExtensions() {
+ return ["pdf"];
+ },
+ possibleApplicationHandlers: Cc["@mozilla.org/array;1"].createInstance(
+ Ci.nsIMutableArray
+ ),
+ extensionExists(ext) {
+ return ext == "pdf";
+ },
+ alwaysAskBeforeHandling: false,
+ preferredAction: Ci.nsIHandlerInfo.handleInternally,
+ type: PDF_CONTENT_TYPE,
+};
+
+export var PdfJs = {
+ QueryInterface: ChromeUtils.generateQI(["nsIObserver"]),
+ _initialized: false,
+ _cachedIsDefault: true,
+
+ init: function init(isNewProfile) {
+ if (
+ Services.appinfo.processType !== Services.appinfo.PROCESS_TYPE_DEFAULT
+ ) {
+ throw new Error(
+ "PdfJs.init should only get called in the parent process."
+ );
+ }
+ this.initPrefs();
+ this.checkIsDefault(isNewProfile);
+ },
+
+ initPrefs: function initPrefs() {
+ if (this._initialized) {
+ return;
+ }
+ this._initialized = true;
+
+ if (this._prefDisabled) {
+ this._unbecomeHandler();
+ } else {
+ this._migrate();
+ }
+
+ // Listen for when a different pdf handler is chosen.
+ Services.obs.addObserver(this, TOPIC_PDFJS_HANDLER_CHANGED);
+
+ initializeDefaultPreferences();
+ },
+
+ uninit: function uninit() {
+ if (this._initialized) {
+ Services.obs.removeObserver(this, TOPIC_PDFJS_HANDLER_CHANGED);
+ this._initialized = false;
+ }
+ },
+
+ _migrate: function migrate() {
+ const VERSION = 2;
+ var currentVersion = Services.prefs.getIntPref(PREF_MIGRATION_VERSION, 0);
+ if (currentVersion >= VERSION) {
+ return;
+ }
+ // Make pdf.js the default pdf viewer on the first migration.
+ if (currentVersion < 1) {
+ this._becomeHandler();
+ }
+ if (currentVersion < 2) {
+ // cleaning up of unused database preference (see #3994)
+ Services.prefs.clearUserPref("pdfjs.database");
+ }
+ Services.prefs.setIntPref(PREF_MIGRATION_VERSION, VERSION);
+ },
+
+ _becomeHandler: function _becomeHandler() {
+ // Normally, this happens in the first run at some point, where the
+ // handler service doesn't have any info on user preferences yet.
+ // Don't bother storing old defaults in this case, as they're
+ // meaningless anyway.
+ if (!Svc.handlerService.exists(gPdfFakeHandlerInfo)) {
+ // Store the requisite info into the DB, and nothing else:
+ Svc.handlerService.store(gPdfFakeHandlerInfo);
+ } else {
+ let handlerInfo = Svc.mime.getFromTypeAndExtension(
+ PDF_CONTENT_TYPE,
+ "pdf"
+ );
+ let prefs = Services.prefs;
+ if (
+ handlerInfo.preferredAction !== Ci.nsIHandlerInfo.handleInternally &&
+ handlerInfo.alwaysAskBeforeHandling !== false
+ ) {
+ // Store the previous settings of preferredAction and
+ // alwaysAskBeforeHandling in case we need to revert them in a hotfix that
+ // would turn pdf.js off.
+ prefs.setIntPref(PREF_PREVIOUS_ACTION, handlerInfo.preferredAction);
+ prefs.setBoolPref(
+ PREF_PREVIOUS_ASK,
+ handlerInfo.alwaysAskBeforeHandling
+ );
+ }
+
+ // Change and save mime handler settings.
+ handlerInfo.alwaysAskBeforeHandling = false;
+ handlerInfo.preferredAction = Ci.nsIHandlerInfo.handleInternally;
+ Svc.handlerService.store(handlerInfo);
+ }
+ },
+
+ _unbecomeHandler: function _unbecomeHandler() {
+ let handlerInfo = Svc.mime.getFromTypeAndExtension(PDF_CONTENT_TYPE, "pdf");
+ if (handlerInfo.preferredAction === Ci.nsIHandlerInfo.handleInternally) {
+ // If PDFJS is disabled, but we're still marked to handleInternally,
+ // either put it back to what it was, or remove it.
+ if (Services.prefs.prefHasUserValue(PREF_PREVIOUS_ACTION)) {
+ handlerInfo.preferredAction =
+ Services.prefs.getIntPref(PREF_PREVIOUS_ACTION);
+ handlerInfo.alwaysAskBeforeHandling =
+ Services.prefs.getBoolPref(PREF_PREVIOUS_ASK);
+ Svc.handlerService.store(handlerInfo);
+ } else {
+ Svc.handlerService.remove(handlerInfo);
+ // Clear migration pref so the handler comes back if reenabled
+ Services.prefs.clearUserPref(PREF_MIGRATION_VERSION);
+ }
+ }
+ },
+
+ /**
+ * @param isNewProfile used to decide whether we need to check the
+ * handler service to see if the user configured
+ * pdfs differently. If we're on a new profile,
+ * there's no need to check.
+ */
+ _isDefault(isNewProfile) {
+ let { processType, PROCESS_TYPE_DEFAULT } = Services.appinfo;
+ if (processType !== PROCESS_TYPE_DEFAULT) {
+ throw new Error(
+ "isDefault should only get called in the parent process."
+ );
+ }
+
+ if (this._prefDisabled) {
+ return false;
+ }
+
+ // Don't bother with the handler service on a new profile:
+ if (isNewProfile) {
+ return true;
+ }
+ // Check if the 'application/pdf' preview handler is configured properly.
+ let handlerInfo = Svc.mime.getFromTypeAndExtension(PDF_CONTENT_TYPE, "pdf");
+ return (
+ !handlerInfo.alwaysAskBeforeHandling &&
+ handlerInfo.preferredAction == Ci.nsIHandlerInfo.handleInternally
+ );
+ },
+
+ checkIsDefault(isNewProfile) {
+ this._cachedIsDefault = this._isDefault(isNewProfile);
+ Services.prefs.setBoolPref(
+ PREF_ISDEFAULT_CACHE_STATE,
+ this._cachedIsDefault
+ );
+ },
+
+ cachedIsDefault() {
+ return this._cachedIsDefault;
+ },
+
+ // nsIObserver
+ observe(aSubject, aTopic, aData) {
+ this.checkIsDefault();
+ },
+};
+
+XPCOMUtils.defineLazyPreferenceGetter(
+ PdfJs,
+ "_prefDisabled",
+ PREF_DISABLED,
+ false,
+ () => PdfJs.checkIsDefault()
+);
diff --git a/toolkit/components/pdfjs/content/PdfJsDefaultPreferences.sys.mjs b/toolkit/components/pdfjs/content/PdfJsDefaultPreferences.sys.mjs
new file mode 100644
index 0000000000..02d1095919
--- /dev/null
+++ b/toolkit/components/pdfjs/content/PdfJsDefaultPreferences.sys.mjs
@@ -0,0 +1,51 @@
+/* Copyright 2023 Mozilla Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//
+// THIS FILE IS GENERATED AUTOMATICALLY, DO NOT EDIT MANUALLY!
+//
+
+export const PdfJsDefaultPreferences = Object.freeze({
+ annotationEditorMode: 0,
+ annotationMode: 2,
+ cursorToolOnLoad: 0,
+ defaultZoomDelay: 400,
+ defaultZoomValue: "",
+ disablePageLabels: false,
+ enableHighlightEditor: false,
+ enableML: false,
+ enablePermissions: false,
+ enablePrintAutoRotate: true,
+ enableScripting: true,
+ enableStampEditor: true,
+ externalLinkTarget: 0,
+ highlightEditorColors: "yellow=#FFFF98,green=#53FFBC,blue=#80EBFF,pink=#FFCBE6,red=#FF4F5F",
+ historyUpdateUrl: false,
+ ignoreDestinationZoom: false,
+ forcePageColors: false,
+ pageColorsBackground: "Canvas",
+ pageColorsForeground: "CanvasText",
+ pdfBugEnabled: false,
+ sidebarViewOnLoad: -1,
+ scrollModeOnLoad: -1,
+ spreadModeOnLoad: -1,
+ textLayerMode: 1,
+ viewOnLoad: 0,
+ disableAutoFetch: false,
+ disableFontFace: false,
+ disableRange: false,
+ disableStream: false,
+ enableXfa: true
+});
diff --git a/toolkit/components/pdfjs/content/PdfJsNetwork.sys.mjs b/toolkit/components/pdfjs/content/PdfJsNetwork.sys.mjs
new file mode 100644
index 0000000000..dd3ebc6bf5
--- /dev/null
+++ b/toolkit/components/pdfjs/content/PdfJsNetwork.sys.mjs
@@ -0,0 +1,193 @@
+/* Copyright 2012 Mozilla Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+function getTypedArray(xhr) {
+ const data = xhr.response;
+ if (typeof data !== "string") {
+ return new Uint8Array(data);
+ }
+ return Uint8Array.from(data, ch => ch.charCodeAt(0) & 0xff);
+}
+
+const OK_RESPONSE = 200;
+const PARTIAL_CONTENT_RESPONSE = 206;
+
+export class NetworkManager {
+ constructor(url, args = {}) {
+ this.url = url;
+ this.isHttp = /^https?:/i.test(url);
+ this.httpHeaders = (this.isHttp && args.httpHeaders) || {};
+ this.withCredentials = args.withCredentials || false;
+ this.getXhr =
+ args.getXhr ||
+ function NetworkManager_getXhr() {
+ return new XMLHttpRequest();
+ };
+
+ this.currXhrId = 0;
+ this.pendingRequests = Object.create(null);
+ }
+
+ requestRange(begin, end, listeners) {
+ var args = {
+ begin,
+ end,
+ };
+ for (var prop in listeners) {
+ args[prop] = listeners[prop];
+ }
+ return this.request(args);
+ }
+
+ request(args) {
+ var xhr = this.getXhr();
+ var xhrId = this.currXhrId++;
+ var pendingRequest = (this.pendingRequests[xhrId] = {
+ xhr,
+ });
+
+ xhr.open("GET", this.url);
+ xhr.withCredentials = this.withCredentials;
+ for (var property in this.httpHeaders) {
+ var value = this.httpHeaders[property];
+ if (typeof value === "undefined") {
+ continue;
+ }
+ xhr.setRequestHeader(property, value);
+ }
+ if (this.isHttp && "begin" in args && "end" in args) {
+ var rangeStr = args.begin + "-" + (args.end - 1);
+ xhr.setRequestHeader("Range", "bytes=" + rangeStr);
+ pendingRequest.expectedStatus = 206;
+ xhr.channel.QueryInterface(Ci.nsIHttpChannel).redirectionLimit = 0;
+ } else {
+ pendingRequest.expectedStatus = 200;
+ }
+
+ xhr.responseType = "arraybuffer";
+
+ if (args.onError) {
+ xhr.onerror = function (evt) {
+ args.onError(xhr.status);
+ };
+ }
+ xhr.onreadystatechange = this.onStateChange.bind(this, xhrId);
+ xhr.onprogress = this.onProgress.bind(this, xhrId);
+
+ pendingRequest.onHeadersReceived = args.onHeadersReceived;
+ pendingRequest.onDone = args.onDone;
+ pendingRequest.onError = args.onError;
+ pendingRequest.onProgress = args.onProgress;
+
+ xhr.send(null);
+
+ return xhrId;
+ }
+
+ onProgress(xhrId, evt) {
+ var pendingRequest = this.pendingRequests[xhrId];
+ if (!pendingRequest) {
+ // Maybe abortRequest was called...
+ return;
+ }
+
+ var onProgress = pendingRequest.onProgress;
+ if (onProgress) {
+ onProgress(evt);
+ }
+ }
+
+ onStateChange(xhrId, evt) {
+ var pendingRequest = this.pendingRequests[xhrId];
+ if (!pendingRequest) {
+ // Maybe abortRequest was called...
+ return;
+ }
+
+ var xhr = pendingRequest.xhr;
+ if (xhr.readyState >= 2 && pendingRequest.onHeadersReceived) {
+ pendingRequest.onHeadersReceived();
+ delete pendingRequest.onHeadersReceived;
+ }
+
+ if (xhr.readyState !== 4) {
+ return;
+ }
+
+ if (!(xhrId in this.pendingRequests)) {
+ // The XHR request might have been aborted in onHeadersReceived()
+ // callback, in which case we should abort request
+ return;
+ }
+
+ delete this.pendingRequests[xhrId];
+
+ // success status == 0 can be on ftp, file and other protocols
+ if (xhr.status === 0 && this.isHttp) {
+ if (pendingRequest.onError) {
+ pendingRequest.onError(xhr.status);
+ }
+ return;
+ }
+ var xhrStatus = xhr.status || OK_RESPONSE;
+
+ // From http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.35.2:
+ // "A server MAY ignore the Range header". This means it's possible to
+ // get a 200 rather than a 206 response from a range request.
+ var ok_response_on_range_request =
+ xhrStatus === OK_RESPONSE &&
+ pendingRequest.expectedStatus === PARTIAL_CONTENT_RESPONSE;
+
+ if (
+ !ok_response_on_range_request &&
+ xhrStatus !== pendingRequest.expectedStatus
+ ) {
+ if (pendingRequest.onError) {
+ pendingRequest.onError(xhr.status);
+ }
+ return;
+ }
+
+ const chunk = getTypedArray(xhr);
+ if (xhrStatus === PARTIAL_CONTENT_RESPONSE) {
+ var rangeHeader = xhr.getResponseHeader("Content-Range");
+ var matches = /bytes (\d+)-(\d+)\/(\d+)/.exec(rangeHeader);
+ var begin = parseInt(matches[1], 10);
+ pendingRequest.onDone({
+ begin,
+ chunk,
+ });
+ } else if (chunk) {
+ pendingRequest.onDone({
+ begin: 0,
+ chunk,
+ });
+ } else if (pendingRequest.onError) {
+ pendingRequest.onError(xhr.status);
+ }
+ }
+
+ abortAllRequests() {
+ for (var xhrId in this.pendingRequests) {
+ this.abortRequest(xhrId | 0);
+ }
+ }
+
+ abortRequest(xhrId) {
+ var xhr = this.pendingRequests[xhrId].xhr;
+ delete this.pendingRequests[xhrId];
+ xhr.abort();
+ }
+}
diff --git a/toolkit/components/pdfjs/content/PdfJsTelemetry.sys.mjs b/toolkit/components/pdfjs/content/PdfJsTelemetry.sys.mjs
new file mode 100644
index 0000000000..16e4e85d58
--- /dev/null
+++ b/toolkit/components/pdfjs/content/PdfJsTelemetry.sys.mjs
@@ -0,0 +1,138 @@
+/* Copyright 2013 Mozilla Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+export class PdfJsTelemetryContent {
+ static onViewerIsUsed() {
+ Glean.pdfjs.used.add(1);
+ }
+}
+
+export class PdfJsTelemetry {
+ static report(aData) {
+ const { type } = aData;
+ switch (type) {
+ case "pageInfo":
+ this.onTimeToView(aData.timestamp);
+ break;
+ case "editing":
+ this.onEditing(aData);
+ break;
+ case "buttons":
+ case "gv-buttons":
+ {
+ const id = aData.data.id.replace(
+ /([A-Z])/g,
+ c => `_${c.toLowerCase()}`
+ );
+ if (type === "buttons") {
+ this.onButtons(id);
+ } else {
+ this.onGeckoview(id);
+ }
+ }
+ break;
+ }
+ }
+
+ static onTimeToView(ms) {
+ Glean.pdfjs.timeToView.accumulateSamples([ms]);
+ }
+
+ static onEditing({ type, data }) {
+ if (type !== "editing" || !data) {
+ return;
+ }
+
+ switch (data.type) {
+ case "freetext":
+ case "ink":
+ Glean.pdfjs.editing[data.type].add(1);
+ return;
+ case "print":
+ case "save":
+ {
+ Glean.pdfjs.editing[data.type].add(1);
+ if (!data.stats) {
+ return;
+ }
+ const numbers = ["one", "two", "three", "four", "five"];
+ Glean.pdfjsEditingHighlight[data.type].add(1);
+ Glean.pdfjsEditingHighlight.numberOfColors[
+ numbers[data.stats.highlight.numberOfColors - 1]
+ ].add(1);
+ }
+ return;
+ case "stamp":
+ if (data.action === "added") {
+ Glean.pdfjs.editing.stamp.add(1);
+ return;
+ }
+ Glean.pdfjs.stamp[data.action].add(1);
+ for (const key of [
+ "alt_text_keyboard",
+ "alt_text_decorative",
+ "alt_text_description",
+ "alt_text_edit",
+ ]) {
+ if (data[key]) {
+ Glean.pdfjs.stamp[key].add(1);
+ }
+ }
+ return;
+ case "highlight":
+ case "free_highlight":
+ switch (data.action) {
+ case "added":
+ Glean.pdfjsEditingHighlight.kind[data.type].add(1);
+ Glean.pdfjsEditingHighlight.method[data.methodOfCreation].add(1);
+ Glean.pdfjsEditingHighlight.color[data.color].add(1);
+ if (data.type === "free_highlight") {
+ Glean.pdfjsEditingHighlight.thickness.accumulateSamples([
+ data.thickness,
+ ]);
+ }
+ break;
+ case "color_changed":
+ Glean.pdfjsEditingHighlight.color[data.color].add(1);
+ Glean.pdfjsEditingHighlight.colorChanged.add(1);
+ break;
+ case "thickness_changed":
+ Glean.pdfjsEditingHighlight.thickness.accumulateSamples([
+ data.thickness,
+ ]);
+ Glean.pdfjsEditingHighlight.thicknessChanged.add(1);
+ break;
+ case "deleted":
+ Glean.pdfjsEditingHighlight.deleted.add(1);
+ break;
+ case "edited":
+ Glean.pdfjsEditingHighlight.edited.add(1);
+ break;
+ case "toggle_visibility":
+ Glean.pdfjsEditingHighlight.toggleVisibility.add(1);
+ break;
+ }
+ break;
+ }
+ }
+
+ static onButtons(id) {
+ Glean.pdfjs.buttons[id].add(1);
+ }
+
+ static onGeckoview(id) {
+ Glean.pdfjs.geckoview[id].add(1);
+ }
+}
diff --git a/toolkit/components/pdfjs/content/PdfSandbox.sys.mjs b/toolkit/components/pdfjs/content/PdfSandbox.sys.mjs
new file mode 100644
index 0000000000..d75a57a7ac
--- /dev/null
+++ b/toolkit/components/pdfjs/content/PdfSandbox.sys.mjs
@@ -0,0 +1,87 @@
+/* Copyright 2020 Mozilla Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { SandboxSupportBase } from "resource://pdf.js/build/pdf.sandbox.external.sys.mjs";
+
+class SandboxSupport extends SandboxSupportBase {
+ constructor(win, sandbox) {
+ super(win);
+ this.sandbox = sandbox;
+ }
+ exportValueToSandbox(val) {
+ return Cu.cloneInto(val, this.sandbox);
+ }
+
+ importValueFromSandbox(val) {
+ return Cu.cloneInto(val, this.win);
+ }
+
+ createErrorForSandbox(errorMessage) {
+ return new this.sandbox.Error(errorMessage);
+ }
+}
+
+export class PdfSandbox {
+ constructor(window, data) {
+ this.window = window;
+ const sandbox = Cu.Sandbox(null, {
+ sandboxName: "PDF.js scripting sandbox",
+ sameZoneAs: window,
+ wantXrays: true,
+ wantGlobalProperties: [],
+ wantComponents: false,
+ wantExportHelpers: false,
+ });
+ this.sandbox = sandbox;
+ this.support = new SandboxSupport(window, sandbox);
+
+ const sandboxInit = Cu.createObjectIn(sandbox);
+ sandboxInit.data = Cu.cloneInto(data, sandbox);
+
+ sandbox.callExternalFunction = Cu.exportFunction(
+ this.support.createSandboxExternals(),
+ sandbox
+ );
+
+ try {
+ // Run the code in the bundle
+ Services.scriptloader.loadSubScript(
+ "resource://pdf.js/build/pdf.scripting.mjs",
+ sandbox
+ );
+
+ this.support.commFun =
+ sandbox.pdfjsScripting.wrappedJSObject.initSandbox(sandboxInit);
+ } catch (error) {
+ // error belongs to the sandbox so create a new one
+ const msg = error.message;
+ this.destroy();
+ throw new Error(msg);
+ }
+ }
+
+ dispatchEvent(event) {
+ this.support.callSandboxFunction("dispatchEvent", event);
+ }
+
+ destroy() {
+ if (this.sandbox) {
+ this.support.destroy();
+ this.support = null;
+ Cu.nukeSandbox(this.sandbox);
+ this.sandbox = null;
+ }
+ }
+}
diff --git a/toolkit/components/pdfjs/content/PdfStreamConverter.sys.mjs b/toolkit/components/pdfjs/content/PdfStreamConverter.sys.mjs
new file mode 100644
index 0000000000..050d730872
--- /dev/null
+++ b/toolkit/components/pdfjs/content/PdfStreamConverter.sys.mjs
@@ -0,0 +1,1110 @@
+/* Copyright 2012 Mozilla Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+const PDFJS_EVENT_ID = "pdf.js.message";
+const PDF_VIEWER_ORIGIN = "resource://pdf.js";
+const PDF_VIEWER_WEB_PAGE = "resource://pdf.js/web/viewer.html";
+const MAX_NUMBER_OF_PREFS = 50;
+const PDF_CONTENT_TYPE = "application/pdf";
+
+import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs";
+import { AppConstants } from "resource://gre/modules/AppConstants.sys.mjs";
+
+const lazy = {};
+ChromeUtils.defineESModuleGetters(lazy, {
+ NetUtil: "resource://gre/modules/NetUtil.sys.mjs",
+ NetworkManager: "resource://pdf.js/PdfJsNetwork.sys.mjs",
+ PdfJs: "resource://pdf.js/PdfJs.sys.mjs",
+ PdfJsTelemetryContent: "resource://pdf.js/PdfJsTelemetry.sys.mjs",
+ PdfSandbox: "resource://pdf.js/PdfSandbox.sys.mjs",
+ PrivateBrowsingUtils: "resource://gre/modules/PrivateBrowsingUtils.sys.mjs",
+});
+
+var Svc = {};
+XPCOMUtils.defineLazyServiceGetter(
+ Svc,
+ "mime",
+ "@mozilla.org/mime;1",
+ "nsIMIMEService"
+);
+XPCOMUtils.defineLazyServiceGetter(
+ Svc,
+ "handlers",
+ "@mozilla.org/uriloader/handler-service;1",
+ "nsIHandlerService"
+);
+
+ChromeUtils.defineLazyGetter(lazy, "gOurBinary", () => {
+ let file = Services.dirsvc.get("XREExeF", Ci.nsIFile);
+ // Make sure to get the .app on macOS
+ if (AppConstants.platform == "macosx") {
+ while (file) {
+ if (/\.app\/?$/i.test(file.leafName)) {
+ break;
+ }
+ file = file.parent;
+ }
+ }
+ return file;
+});
+
+function log(aMsg) {
+ if (!Services.prefs.getBoolPref("pdfjs.pdfBugEnabled", false)) {
+ return;
+ }
+ var msg = "PdfStreamConverter.js: " + (aMsg.join ? aMsg.join("") : aMsg);
+ Services.console.logStringMessage(msg);
+ dump(msg + "\n");
+}
+
+function getDOMWindow(aChannel, aPrincipal) {
+ var requestor = aChannel.notificationCallbacks
+ ? aChannel.notificationCallbacks
+ : aChannel.loadGroup.notificationCallbacks;
+ var win = requestor.getInterface(Ci.nsIDOMWindow);
+ // Ensure the window wasn't navigated to something that is not PDF.js.
+ if (!win.document.nodePrincipal.equals(aPrincipal)) {
+ return null;
+ }
+ return win;
+}
+
+function getActor(window) {
+ try {
+ const actorName =
+ AppConstants.platform === "android" ? "GeckoViewPdfjs" : "Pdfjs";
+ return window.windowGlobalChild.getActor(actorName);
+ } catch (ex) {
+ return null;
+ }
+}
+
+function isValidMatchesCount(data) {
+ if (typeof data !== "object" || data === null) {
+ return false;
+ }
+ const { current, total } = data;
+ if (
+ typeof total !== "number" ||
+ total < 0 ||
+ typeof current !== "number" ||
+ current < 0 ||
+ current > total
+ ) {
+ return false;
+ }
+ return true;
+}
+
+// PDF data storage
+function PdfDataListener(length) {
+ this.length = length; // less than 0, if length is unknown
+ this.buffers = [];
+ this.loaded = 0;
+}
+
+PdfDataListener.prototype = {
+ append: function PdfDataListener_append(chunk) {
+ // In most of the cases we will pass data as we receive it, but at the
+ // beginning of the loading we may accumulate some data.
+ this.buffers.push(chunk);
+ this.loaded += chunk.length;
+ if (this.length >= 0 && this.length < this.loaded) {
+ this.length = -1; // reset the length, server is giving incorrect one
+ }
+ this.onprogress(this.loaded, this.length >= 0 ? this.length : void 0);
+ },
+ readData: function PdfDataListener_readData() {
+ if (this.buffers.length === 0) {
+ return null;
+ }
+ if (this.buffers.length === 1) {
+ return this.buffers.pop();
+ }
+ // There are multiple buffers that need to be combined into a single
+ // buffer.
+ let combinedLength = 0;
+ for (let buffer of this.buffers) {
+ combinedLength += buffer.length;
+ }
+ let combinedArray = new Uint8Array(combinedLength);
+ let writeOffset = 0;
+ while (this.buffers.length) {
+ let buffer = this.buffers.shift();
+ combinedArray.set(buffer, writeOffset);
+ writeOffset += buffer.length;
+ }
+ return combinedArray;
+ },
+ get isDone() {
+ return !!this.isDataReady;
+ },
+ finish: function PdfDataListener_finish() {
+ this.isDataReady = true;
+ if (this.oncompleteCallback) {
+ this.oncompleteCallback(this.readData());
+ }
+ },
+ error: function PdfDataListener_error(errorCode) {
+ this.errorCode = errorCode;
+ if (this.oncompleteCallback) {
+ this.oncompleteCallback(null, errorCode);
+ }
+ },
+ onprogress() {},
+ get oncomplete() {
+ return this.oncompleteCallback;
+ },
+ set oncomplete(value) {
+ this.oncompleteCallback = value;
+ if (this.isDataReady) {
+ value(this.readData());
+ }
+ if (this.errorCode) {
+ value(null, this.errorCode);
+ }
+ },
+};
+
+/**
+ * All the privileged actions.
+ */
+class ChromeActions {
+ constructor(domWindow, contentDispositionFilename) {
+ this.domWindow = domWindow;
+ this.contentDispositionFilename = contentDispositionFilename;
+ this.sandbox = null;
+ this.unloadListener = null;
+ }
+
+ createSandbox(data, sendResponse) {
+ function sendResp(res) {
+ if (sendResponse) {
+ sendResponse(res);
+ }
+ return res;
+ }
+
+ if (!Services.prefs.getBoolPref("pdfjs.enableScripting", false)) {
+ return sendResp(false);
+ }
+
+ if (this.sandbox !== null) {
+ return sendResp(true);
+ }
+
+ try {
+ this.sandbox = new lazy.PdfSandbox(this.domWindow, data);
+ } catch (err) {
+ // If there's an error here, it means that something is really wrong
+ // on pdf.js side during sandbox initialization phase.
+ console.error(err);
+ return sendResp(false);
+ }
+
+ this.unloadListener = () => {
+ this.destroySandbox();
+ };
+ this.domWindow.addEventListener("unload", this.unloadListener);
+
+ return sendResp(true);
+ }
+
+ dispatchEventInSandbox(event) {
+ if (this.sandbox) {
+ this.sandbox.dispatchEvent(event);
+ }
+ }
+
+ dispatchAsyncEventInSandbox(event, sendResponse) {
+ this.dispatchEventInSandbox(event);
+ sendResponse();
+ }
+
+ destroySandbox() {
+ if (this.sandbox) {
+ this.domWindow.removeEventListener("unload", this.unloadListener);
+ this.sandbox.destroy();
+ this.sandbox = null;
+ }
+ }
+
+ isInPrivateBrowsing() {
+ return lazy.PrivateBrowsingUtils.isContentWindowPrivate(this.domWindow);
+ }
+
+ getWindowOriginAttributes() {
+ try {
+ return this.domWindow.document.nodePrincipal.originAttributes;
+ } catch (err) {
+ return {};
+ }
+ }
+
+ download(data, sendResponse) {
+ const { originalUrl, options } = data;
+ const blobUrl = data.blobUrl || originalUrl;
+ let { filename } = data;
+ if (
+ typeof filename !== "string" ||
+ (!/\.pdf$/i.test(filename) && !data.isAttachment)
+ ) {
+ filename = "document.pdf";
+ }
+
+ const actor = getActor(this.domWindow);
+ actor.sendAsyncMessage("PDFJS:Parent:saveURL", {
+ blobUrl,
+ originalUrl,
+ filename,
+ options: options || {},
+ });
+ }
+
+ getLocaleProperties(_data, sendResponse) {
+ const { requestedLocale, defaultLocale, isAppLocaleRTL } = Services.locale;
+ sendResponse({
+ lang: requestedLocale || defaultLocale,
+ isRTL: isAppLocaleRTL,
+ });
+ }
+
+ supportsIntegratedFind() {
+ // Integrated find is only supported when we're not in a frame
+ return this.domWindow.windowGlobalChild.browsingContext.parent === null;
+ }
+
+ getBrowserPrefs() {
+ return {
+ canvasMaxAreaInBytes: Services.prefs.getIntPref("gfx.max-alloc-size"),
+ isInAutomation: Cu.isInAutomation,
+ supportsDocumentFonts:
+ !!Services.prefs.getIntPref("browser.display.use_document_fonts") &&
+ Services.prefs.getBoolPref("gfx.downloadable_fonts.enabled"),
+ supportsIntegratedFind: this.supportsIntegratedFind(),
+ supportsMouseWheelZoomCtrlKey:
+ Services.prefs.getIntPref("mousewheel.with_control.action") === 3,
+ supportsMouseWheelZoomMetaKey:
+ Services.prefs.getIntPref("mousewheel.with_meta.action") === 3,
+ supportsPinchToZoom: Services.prefs.getBoolPref("apz.allow_zooming"),
+ supportsCaretBrowsingMode: Services.prefs.getBoolPref(
+ "accessibility.browsewithcaret"
+ ),
+ };
+ }
+
+ isMobile() {
+ return AppConstants.platform === "android";
+ }
+
+ getNimbusExperimentData(_data, sendResponse) {
+ if (!this.isMobile()) {
+ sendResponse(null);
+ return;
+ }
+ const actor = getActor(this.domWindow);
+ actor.sendAsyncMessage("PDFJS:Parent:getNimbus");
+ Services.obs.addObserver(
+ {
+ observe(aSubject, aTopic, aData) {
+ if (aTopic === "pdfjs-getNimbus") {
+ Services.obs.removeObserver(this, aTopic);
+ sendResponse(aSubject && JSON.stringify(aSubject.wrappedJSObject));
+ }
+ },
+ },
+ "pdfjs-getNimbus"
+ );
+ }
+
+ reportTelemetry(data) {
+ const probeInfo = JSON.parse(data);
+ const actor = getActor(this.domWindow);
+ actor?.sendAsyncMessage("PDFJS:Parent:reportTelemetry", probeInfo);
+ }
+
+ updateFindControlState(data) {
+ if (!this.supportsIntegratedFind()) {
+ return;
+ }
+ // Verify what we're sending to the findbar.
+ var result = data.result;
+ var findPrevious = data.findPrevious;
+ var findPreviousType = typeof findPrevious;
+ if (
+ typeof result !== "number" ||
+ result < 0 ||
+ result > 3 ||
+ (findPreviousType !== "undefined" && findPreviousType !== "boolean")
+ ) {
+ return;
+ }
+ // Allow the `matchesCount` property to be optional, and ensure that
+ // it's valid before including it in the data sent to the findbar.
+ let matchesCount = null;
+ if (isValidMatchesCount(data.matchesCount)) {
+ matchesCount = data.matchesCount;
+ }
+ // Same for the `rawQuery` property.
+ let rawQuery = null;
+ if (typeof data.rawQuery === "string") {
+ rawQuery = data.rawQuery;
+ }
+
+ let actor = getActor(this.domWindow);
+ actor?.sendAsyncMessage("PDFJS:Parent:updateControlState", {
+ result,
+ findPrevious,
+ matchesCount,
+ rawQuery,
+ });
+ }
+
+ updateFindMatchesCount(data) {
+ if (!this.supportsIntegratedFind()) {
+ return;
+ }
+ // Verify what we're sending to the findbar.
+ if (!isValidMatchesCount(data)) {
+ return;
+ }
+
+ let actor = getActor(this.domWindow);
+ actor?.sendAsyncMessage("PDFJS:Parent:updateMatchesCount", data);
+ }
+
+ getPreferences(prefs, sendResponse) {
+ var defaultBranch = Services.prefs.getDefaultBranch("pdfjs.");
+ var currentPrefs = {},
+ numberOfPrefs = 0;
+ for (var key in prefs) {
+ if (++numberOfPrefs > MAX_NUMBER_OF_PREFS) {
+ log(
+ "getPreferences - Exceeded the maximum number of preferences " +
+ "that is allowed to be fetched at once."
+ );
+ break;
+ } else if (!defaultBranch.getPrefType(key)) {
+ continue;
+ }
+ const prefName = `pdfjs.${key}`,
+ prefValue = prefs[key];
+ switch (typeof prefValue) {
+ case "boolean":
+ currentPrefs[key] = Services.prefs.getBoolPref(prefName, prefValue);
+ break;
+ case "number":
+ currentPrefs[key] = Services.prefs.getIntPref(prefName, prefValue);
+ break;
+ case "string":
+ currentPrefs[key] = Services.prefs.getStringPref(prefName, prefValue);
+ break;
+ }
+ }
+
+ sendResponse({
+ browserPrefs: this.getBrowserPrefs(),
+ prefs: currentPrefs,
+ });
+ }
+
+ /**
+ * Set the different editor states in order to be able to update the context
+ * menu.
+ * @param {Object} details
+ */
+ updateEditorStates({ details }) {
+ const doc = this.domWindow.document;
+ if (!doc.editorStates) {
+ doc.editorStates = {
+ isEditing: false,
+ isEmpty: true,
+ hasSomethingToUndo: false,
+ hasSomethingToRedo: false,
+ hasSelectedEditor: false,
+ };
+ }
+ const { editorStates } = doc;
+ for (const [key, value] of Object.entries(details)) {
+ if (typeof value === "boolean" && key in editorStates) {
+ editorStates[key] = value;
+ }
+ }
+ }
+}
+
+/**
+ * This is for range requests.
+ */
+class RangedChromeActions extends ChromeActions {
+ constructor(
+ domWindow,
+ contentDispositionFilename,
+ originalRequest,
+ rangeEnabled,
+ streamingEnabled,
+ dataListener
+ ) {
+ super(domWindow, contentDispositionFilename);
+ this.dataListener = dataListener;
+ this.originalRequest = originalRequest;
+ this.rangeEnabled = rangeEnabled;
+ this.streamingEnabled = streamingEnabled;
+
+ this.pdfUrl = originalRequest.URI.spec;
+ this.contentLength = originalRequest.contentLength;
+
+ // Pass all the headers from the original request through
+ var httpHeaderVisitor = {
+ headers: {},
+ visitHeader(aHeader, aValue) {
+ if (aHeader === "Range") {
+ // When loading the PDF from cache, firefox seems to set the Range
+ // request header to fetch only the unfetched portions of the file
+ // (e.g. 'Range: bytes=1024-'). However, we want to set this header
+ // manually to fetch the PDF in chunks.
+ return;
+ }
+ this.headers[aHeader] = aValue;
+ },
+ };
+ if (originalRequest.visitRequestHeaders) {
+ originalRequest.visitRequestHeaders(httpHeaderVisitor);
+ }
+
+ var self = this;
+ var xhr_onreadystatechange = function xhr_onreadystatechange() {
+ if (this.readyState === 1) {
+ // LOADING
+ var netChannel = this.channel;
+ // override this XMLHttpRequest's OriginAttributes with our cached parent window's
+ // OriginAttributes, as we are currently running under the SystemPrincipal
+ this.setOriginAttributes(self.getWindowOriginAttributes());
+ if (
+ "nsIPrivateBrowsingChannel" in Ci &&
+ netChannel instanceof Ci.nsIPrivateBrowsingChannel
+ ) {
+ var docIsPrivate = self.isInPrivateBrowsing();
+ netChannel.setPrivate(docIsPrivate);
+ }
+ }
+ };
+ var getXhr = function getXhr() {
+ var xhr = new XMLHttpRequest();
+ xhr.addEventListener("readystatechange", xhr_onreadystatechange);
+ return xhr;
+ };
+
+ this.networkManager = new lazy.NetworkManager(this.pdfUrl, {
+ httpHeaders: httpHeaderVisitor.headers,
+ getXhr,
+ });
+
+ // If we are in range request mode, this means we manually issued xhr
+ // requests, which we need to abort when we leave the page
+ domWindow.addEventListener("unload", function unload(e) {
+ domWindow.removeEventListener(e.type, unload);
+ self.abortLoading();
+ });
+ }
+
+ initPassiveLoading() {
+ let data, done;
+ if (!this.streamingEnabled) {
+ this.originalRequest.cancel(Cr.NS_BINDING_ABORTED);
+ this.originalRequest = null;
+ data = this.dataListener.readData();
+ done = this.dataListener.isDone;
+ this.dataListener = null;
+ } else {
+ data = this.dataListener.readData();
+ done = this.dataListener.isDone;
+
+ this.dataListener.onprogress = (loaded, total) => {
+ const chunk = this.dataListener.readData();
+
+ this.domWindow.postMessage(
+ {
+ pdfjsLoadAction: "progressiveRead",
+ loaded,
+ total,
+ chunk,
+ },
+ PDF_VIEWER_ORIGIN,
+ chunk ? [chunk.buffer] : undefined
+ );
+ };
+ this.dataListener.oncomplete = () => {
+ if (!done && this.dataListener.isDone) {
+ this.domWindow.postMessage(
+ {
+ pdfjsLoadAction: "progressiveDone",
+ },
+ PDF_VIEWER_ORIGIN
+ );
+ }
+ this.dataListener = null;
+ };
+ }
+
+ this.domWindow.postMessage(
+ {
+ pdfjsLoadAction: "supportsRangedLoading",
+ rangeEnabled: this.rangeEnabled,
+ streamingEnabled: this.streamingEnabled,
+ pdfUrl: this.pdfUrl,
+ length: this.contentLength,
+ data,
+ done,
+ filename: this.contentDispositionFilename,
+ },
+ PDF_VIEWER_ORIGIN,
+ data ? [data.buffer] : undefined
+ );
+
+ return true;
+ }
+
+ requestDataRange(args) {
+ if (!this.rangeEnabled) {
+ return;
+ }
+
+ var begin = args.begin;
+ var end = args.end;
+ var domWindow = this.domWindow;
+ // TODO(mack): Support error handler. We're not currently not handling
+ // errors from chrome code for non-range requests, so this doesn't
+ // seem high-pri
+ this.networkManager.requestRange(begin, end, {
+ onDone: function RangedChromeActions_onDone({ begin, chunk }) {
+ domWindow.postMessage(
+ {
+ pdfjsLoadAction: "range",
+ begin,
+ chunk,
+ },
+ PDF_VIEWER_ORIGIN,
+ chunk ? [chunk.buffer] : undefined
+ );
+ },
+ onProgress: function RangedChromeActions_onProgress(evt) {
+ domWindow.postMessage(
+ {
+ pdfjsLoadAction: "rangeProgress",
+ loaded: evt.loaded,
+ },
+ PDF_VIEWER_ORIGIN
+ );
+ },
+ });
+ }
+
+ abortLoading() {
+ this.networkManager.abortAllRequests();
+ if (this.originalRequest) {
+ this.originalRequest.cancel(Cr.NS_BINDING_ABORTED);
+ this.originalRequest = null;
+ }
+ this.dataListener = null;
+ }
+}
+
+/**
+ * This is for a single network stream.
+ */
+class StandardChromeActions extends ChromeActions {
+ constructor(
+ domWindow,
+ contentDispositionFilename,
+ originalRequest,
+ dataListener
+ ) {
+ super(domWindow, contentDispositionFilename);
+ this.originalRequest = originalRequest;
+ this.dataListener = dataListener;
+ }
+
+ initPassiveLoading() {
+ if (!this.dataListener) {
+ return false;
+ }
+
+ this.dataListener.onprogress = (loaded, total) => {
+ this.domWindow.postMessage(
+ {
+ pdfjsLoadAction: "progress",
+ loaded,
+ total,
+ },
+ PDF_VIEWER_ORIGIN
+ );
+ };
+
+ this.dataListener.oncomplete = (data, errorCode) => {
+ this.domWindow.postMessage(
+ {
+ pdfjsLoadAction: "complete",
+ data,
+ errorCode,
+ filename: this.contentDispositionFilename,
+ },
+ PDF_VIEWER_ORIGIN,
+ data ? [data.buffer] : undefined
+ );
+
+ this.dataListener = null;
+ this.originalRequest = null;
+ };
+
+ return true;
+ }
+
+ abortLoading() {
+ if (this.originalRequest) {
+ this.originalRequest.cancel(Cr.NS_BINDING_ABORTED);
+ this.originalRequest = null;
+ }
+ this.dataListener = null;
+ }
+}
+
+/**
+ * Event listener to trigger chrome privileged code.
+ */
+class RequestListener {
+ constructor(actions) {
+ this.actions = actions;
+ }
+
+ // Receive an event and (optionally) asynchronously responds.
+ receive({ target, detail }) {
+ const doc = target.ownerDocument;
+ const { action, data, responseExpected } = detail;
+
+ const actionFn = this.actions[action];
+ if (!actionFn) {
+ log("Unknown action: " + action);
+ return;
+ }
+ let response = null;
+
+ if (!responseExpected) {
+ doc.documentElement.removeChild(target);
+ } else {
+ response = function (aResponse) {
+ try {
+ const listener = doc.createEvent("CustomEvent");
+ const detail = Cu.cloneInto({ response: aResponse }, doc.defaultView);
+ listener.initCustomEvent("pdf.js.response", true, false, detail);
+ return target.dispatchEvent(listener);
+ } catch (e) {
+ // doc is no longer accessible because the requestor is already
+ // gone. unloaded content cannot receive the response anyway.
+ return false;
+ }
+ };
+ }
+ actionFn.call(this.actions, data, response);
+ }
+}
+
+export function PdfStreamConverter() {}
+
+PdfStreamConverter.prototype = {
+ QueryInterface: ChromeUtils.generateQI([
+ "nsIStreamConverter",
+ "nsIStreamListener",
+ "nsIRequestObserver",
+ ]),
+
+ /*
+ * This component works as such:
+ * 1. asyncConvertData stores the listener
+ * 2. onStartRequest creates a new channel, streams the viewer
+ * 3. If range requests are supported:
+ * 3.1. Leave the request open until the viewer is ready to switch to
+ * range requests.
+ *
+ * If range rquests are not supported:
+ * 3.1. Read the stream as it's loaded in onDataAvailable to send
+ * to the viewer
+ *
+ * The convert function just returns the stream, it's just the synchronous
+ * version of asyncConvertData.
+ */
+
+ // nsIStreamConverter::convert
+ convert(aFromStream, aFromType, aToType, aCtxt) {
+ throw Components.Exception("", Cr.NS_ERROR_NOT_IMPLEMENTED);
+ },
+
+ // nsIStreamConverter::asyncConvertData
+ asyncConvertData(aFromType, aToType, aListener, aCtxt) {
+ if (aCtxt && aCtxt instanceof Ci.nsIChannel) {
+ aCtxt.QueryInterface(Ci.nsIChannel);
+ }
+ // We need to check if we're supposed to convert here, because not all
+ // asyncConvertData consumers will call getConvertedType first:
+ this.getConvertedType(aFromType, aCtxt);
+
+ // Store the listener passed to us
+ this.listener = aListener;
+ },
+
+ _usableHandler(handlerInfo) {
+ let { preferredApplicationHandler } = handlerInfo;
+ if (
+ !preferredApplicationHandler ||
+ !(preferredApplicationHandler instanceof Ci.nsILocalHandlerApp)
+ ) {
+ return false;
+ }
+ preferredApplicationHandler.QueryInterface(Ci.nsILocalHandlerApp);
+ // We have an app, grab the executable
+ let { executable } = preferredApplicationHandler;
+ if (!executable) {
+ return false;
+ }
+ return !executable.equals(lazy.gOurBinary);
+ },
+
+ /*
+ * Check if the user wants to use PDF.js. Returns true if PDF.js should
+ * handle PDFs, and false if not. Will always return true on non-parent
+ * processes.
+ *
+ * If the user has selected to open PDFs with a helper app, and we are that
+ * helper app, or if the user has selected the OS default, and we are that
+ * OS default, reset the preference back to pdf.js .
+ *
+ */
+ _validateAndMaybeUpdatePDFPrefs() {
+ let { processType, PROCESS_TYPE_DEFAULT } = Services.appinfo;
+ // If we're not in the parent, or are the default, then just say yes.
+ if (processType != PROCESS_TYPE_DEFAULT || lazy.PdfJs.cachedIsDefault()) {
+ return { shouldOpen: true };
+ }
+
+ // OK, PDF.js might not be the default. Find out if we've misled the user
+ // into making Firefox an external handler or if we're the OS default and
+ // Firefox is set to use the OS default:
+ let mime = Svc.mime.getFromTypeAndExtension(PDF_CONTENT_TYPE, "pdf");
+ // The above might throw errors. We're deliberately letting those bubble
+ // back up, where they'll tell the stream converter not to use us.
+
+ if (!mime) {
+ // This shouldn't happen, but we can't fix what isn't there. Assume
+ // we're OK to handle with PDF.js
+ return { shouldOpen: true };
+ }
+
+ const { saveToDisk, useHelperApp, useSystemDefault } = Ci.nsIHandlerInfo;
+ let { preferredAction, alwaysAskBeforeHandling } = mime;
+ // return this info so getConvertedType can use it.
+ let rv = { alwaysAskBeforeHandling, shouldOpen: false };
+ // If the user has indicated they want to be asked or want to save to
+ // disk, we shouldn't render inline immediately:
+ if (alwaysAskBeforeHandling || preferredAction == saveToDisk) {
+ return rv;
+ }
+ // If we have usable helper app info, don't use PDF.js
+ if (preferredAction == useHelperApp && this._usableHandler(mime)) {
+ return rv;
+ }
+ // If we want the OS default and that's not Firefox, don't use PDF.js
+ if (preferredAction == useSystemDefault && !mime.isCurrentAppOSDefault()) {
+ return rv;
+ }
+ rv.shouldOpen = true;
+ // Log that we're doing this to help debug issues if people end up being
+ // surprised by this behaviour.
+ console.error("Found unusable PDF preferences. Fixing back to PDF.js");
+
+ mime.preferredAction = Ci.nsIHandlerInfo.handleInternally;
+ mime.alwaysAskBeforeHandling = false;
+ Svc.handlers.store(mime);
+ return true;
+ },
+
+ getConvertedType(aFromType, aChannel) {
+ const HTML = "text/html";
+ let channelURI = aChannel?.URI;
+ // We can be invoked for application/octet-stream; check if we want the
+ // channel first:
+ if (aFromType != "application/pdf") {
+ // Check if the filename has a PDF extension.
+ let isPDF = false;
+ try {
+ isPDF = aChannel.contentDispositionFilename.endsWith(".pdf");
+ } catch (ex) {}
+ if (!isPDF) {
+ isPDF =
+ channelURI?.QueryInterface(Ci.nsIURL).fileExtension.toLowerCase() ==
+ "pdf";
+ }
+
+ let browsingContext = aChannel?.loadInfo.targetBrowsingContext;
+ let toplevelOctetStream =
+ aFromType == "application/octet-stream" &&
+ browsingContext &&
+ !browsingContext.parent;
+ if (
+ !isPDF ||
+ !toplevelOctetStream ||
+ !Services.prefs.getBoolPref("pdfjs.handleOctetStream", false)
+ ) {
+ throw new Components.Exception(
+ "Ignore PDF.js for this download.",
+ Cr.NS_ERROR_FAILURE
+ );
+ }
+ // fall through, this appears to be a pdf.
+ }
+
+ let { alwaysAskBeforeHandling, shouldOpen } =
+ this._validateAndMaybeUpdatePDFPrefs();
+
+ if (shouldOpen) {
+ return HTML;
+ }
+ // Hm, so normally, no pdfjs. However... if this is a file: channel there
+ // are some edge-cases.
+ if (channelURI?.schemeIs("file")) {
+ // If we're loaded with system principal, we were likely handed the PDF
+ // by the OS or directly from the URL bar. Assume we should load it:
+ let triggeringPrincipal = aChannel.loadInfo?.triggeringPrincipal;
+ if (triggeringPrincipal?.isSystemPrincipal) {
+ return HTML;
+ }
+
+ // If we're loading from a file: link, load it in PDF.js unless the user
+ // has told us they always want to open/save PDFs.
+ // This is because handing off the choice to open in Firefox itself
+ // through the dialog doesn't work properly and making it work is
+ // non-trivial (see https://bugzilla.mozilla.org/show_bug.cgi?id=1680147#c3 )
+ // - and anyway, opening the file is what we do for *all*
+ // other file types we handle internally (and users can then use other UI
+ // to save or open it with other apps from there).
+ if (triggeringPrincipal?.schemeIs("file") && alwaysAskBeforeHandling) {
+ return HTML;
+ }
+ }
+
+ throw new Components.Exception("Can't use PDF.js", Cr.NS_ERROR_FAILURE);
+ },
+
+ // nsIStreamListener::onDataAvailable
+ onDataAvailable(aRequest, aInputStream, aOffset, aCount) {
+ if (!this.dataListener) {
+ return;
+ }
+
+ var binaryStream = this.binaryStream;
+ binaryStream.setInputStream(aInputStream);
+ let chunk = new ArrayBuffer(aCount);
+ binaryStream.readArrayBuffer(aCount, chunk);
+ this.dataListener.append(new Uint8Array(chunk));
+ },
+
+ // nsIRequestObserver::onStartRequest
+ onStartRequest(aRequest) {
+ // Setup the request so we can use it below.
+ var isHttpRequest = false;
+ try {
+ aRequest.QueryInterface(Ci.nsIHttpChannel);
+ isHttpRequest = true;
+ } catch (e) {}
+
+ var rangeRequest = false;
+ var streamRequest = false;
+ if (isHttpRequest) {
+ var contentEncoding = "identity";
+ try {
+ contentEncoding = aRequest.getResponseHeader("Content-Encoding");
+ } catch (e) {}
+
+ var acceptRanges;
+ try {
+ acceptRanges = aRequest.getResponseHeader("Accept-Ranges");
+ } catch (e) {}
+
+ var hash = aRequest.URI.ref;
+ const isPDFBugEnabled = Services.prefs.getBoolPref(
+ "pdfjs.pdfBugEnabled",
+ false
+ );
+ rangeRequest =
+ contentEncoding === "identity" &&
+ acceptRanges === "bytes" &&
+ aRequest.contentLength >= 0 &&
+ !Services.prefs.getBoolPref("pdfjs.disableRange", false) &&
+ (!isPDFBugEnabled || !hash.toLowerCase().includes("disablerange=true"));
+ streamRequest =
+ contentEncoding === "identity" &&
+ aRequest.contentLength >= 0 &&
+ !Services.prefs.getBoolPref("pdfjs.disableStream", false) &&
+ (!isPDFBugEnabled ||
+ !hash.toLowerCase().includes("disablestream=true"));
+ }
+
+ aRequest.QueryInterface(Ci.nsIChannel);
+
+ aRequest.QueryInterface(Ci.nsIWritablePropertyBag);
+
+ var contentDispositionFilename;
+ try {
+ contentDispositionFilename = aRequest.contentDispositionFilename;
+ } catch (e) {}
+
+ if (
+ contentDispositionFilename &&
+ !/\.pdf$/i.test(contentDispositionFilename)
+ ) {
+ contentDispositionFilename += ".pdf";
+ }
+
+ // Change the content type so we don't get stuck in a loop.
+ aRequest.setProperty("contentType", aRequest.contentType);
+ aRequest.contentType = "text/html";
+ if (isHttpRequest) {
+ // We trust PDF viewer, using no CSP
+ aRequest.setResponseHeader("Content-Security-Policy", "", false);
+ aRequest.setResponseHeader(
+ "Content-Security-Policy-Report-Only",
+ "",
+ false
+ );
+ // The viewer does not need to handle HTTP Refresh header.
+ aRequest.setResponseHeader("Refresh", "", false);
+ }
+
+ lazy.PdfJsTelemetryContent.onViewerIsUsed();
+
+ // The document will be loaded via the stream converter as html,
+ // but since we may have come here via a download or attachment
+ // that was opened directly, force the content disposition to be
+ // inline so that the html document will be loaded normally instead
+ // of going to the helper service.
+ aRequest.contentDisposition = Ci.nsIChannel.DISPOSITION_FORCE_INLINE;
+
+ // Creating storage for PDF data
+ var contentLength = aRequest.contentLength;
+ this.dataListener = new PdfDataListener(contentLength);
+ this.binaryStream = Cc["@mozilla.org/binaryinputstream;1"].createInstance(
+ Ci.nsIBinaryInputStream
+ );
+
+ // Create a new channel that is viewer loaded as a resource.
+ var channel = lazy.NetUtil.newChannel({
+ uri: PDF_VIEWER_WEB_PAGE,
+ loadUsingSystemPrincipal: true,
+ });
+
+ var listener = this.listener;
+ var dataListener = this.dataListener;
+ // Proxy all the request observer calls, when it gets to onStopRequest
+ // we can get the dom window. We also intentionally pass on the original
+ // request(aRequest) below so we don't overwrite the original channel and
+ // trigger an assertion.
+ var proxy = {
+ onStartRequest(request) {
+ listener.onStartRequest(aRequest);
+ },
+ onDataAvailable(request, inputStream, offset, count) {
+ listener.onDataAvailable(aRequest, inputStream, offset, count);
+ },
+ onStopRequest(request, statusCode) {
+ var domWindow = getDOMWindow(channel, resourcePrincipal);
+ if (!Components.isSuccessCode(statusCode) || !domWindow) {
+ // The request may have been aborted and the document may have been
+ // replaced with something that is not PDF.js, abort attaching.
+ listener.onStopRequest(aRequest, statusCode);
+ return;
+ }
+ var actions;
+ if (rangeRequest || streamRequest) {
+ actions = new RangedChromeActions(
+ domWindow,
+ contentDispositionFilename,
+ aRequest,
+ rangeRequest,
+ streamRequest,
+ dataListener
+ );
+ } else {
+ actions = new StandardChromeActions(
+ domWindow,
+ contentDispositionFilename,
+ aRequest,
+ dataListener
+ );
+ }
+ var requestListener = new RequestListener(actions);
+ domWindow.document.addEventListener(
+ PDFJS_EVENT_ID,
+ function (event) {
+ requestListener.receive(event);
+ },
+ false,
+ true
+ );
+
+ let actor = getActor(domWindow);
+ actor?.init(actions.supportsIntegratedFind());
+ actor?.sendAsyncMessage("PDFJS:Parent:recordExposure");
+ listener.onStopRequest(aRequest, statusCode);
+ },
+ };
+
+ // Keep the URL the same so the browser sees it as the same.
+ channel.originalURI = aRequest.URI;
+ channel.loadGroup = aRequest.loadGroup;
+ channel.loadInfo.originAttributes = aRequest.loadInfo.originAttributes;
+
+ // We can use the resource principal when data is fetched by the chrome,
+ // e.g. useful for NoScript. Make make sure we reuse the origin attributes
+ // from the request channel to keep isolation consistent.
+ var uri = lazy.NetUtil.newURI(PDF_VIEWER_WEB_PAGE);
+ var resourcePrincipal =
+ Services.scriptSecurityManager.createContentPrincipal(
+ uri,
+ aRequest.loadInfo.originAttributes
+ );
+ // Remember the principal we would have had before we mess with it.
+ let originalPrincipal =
+ Services.scriptSecurityManager.getChannelResultPrincipal(aRequest);
+ aRequest.owner = resourcePrincipal;
+ aRequest.setProperty("noPDFJSPrincipal", originalPrincipal);
+
+ channel.asyncOpen(proxy);
+ },
+
+ // nsIRequestObserver::onStopRequest
+ onStopRequest(aRequest, aStatusCode) {
+ if (!this.dataListener) {
+ // Do nothing
+ return;
+ }
+
+ if (Components.isSuccessCode(aStatusCode)) {
+ this.dataListener.finish();
+ } else {
+ this.dataListener.error(aStatusCode);
+ }
+ delete this.dataListener;
+ delete this.binaryStream;
+ },
+};
diff --git a/toolkit/components/pdfjs/content/PdfjsChild.sys.mjs b/toolkit/components/pdfjs/content/PdfjsChild.sys.mjs
new file mode 100644
index 0000000000..0b5276ec12
--- /dev/null
+++ b/toolkit/components/pdfjs/content/PdfjsChild.sys.mjs
@@ -0,0 +1,52 @@
+/* Copyright 2012 Mozilla Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+export class PdfjsChild extends JSWindowActorChild {
+ init(supportsFind) {
+ if (supportsFind) {
+ this.sendAsyncMessage("PDFJS:Parent:addEventListener");
+ }
+ }
+
+ dispatchEvent(type, detail) {
+ const contentWindow = this.contentWindow;
+ const forward = contentWindow.document.createEvent("CustomEvent");
+ forward.initCustomEvent(type, true, true, detail);
+ contentWindow.dispatchEvent(forward);
+ }
+
+ receiveMessage(msg) {
+ switch (msg.name) {
+ case "PDFJS:Child:handleEvent": {
+ let detail = Cu.cloneInto(msg.data.detail, this.contentWindow);
+ this.dispatchEvent(msg.data.type, detail);
+ break;
+ }
+
+ case "PDFJS:Editing":
+ let data = Cu.cloneInto(msg.data, this.contentWindow);
+ this.dispatchEvent("editingaction", data);
+ break;
+ case "PDFJS:ZoomIn":
+ case "PDFJS:ZoomOut":
+ case "PDFJS:ZoomReset":
+ case "PDFJS:Save": {
+ const type = msg.name.split("PDFJS:")[1].toLowerCase();
+ this.dispatchEvent(type, null);
+ break;
+ }
+ }
+ }
+}
diff --git a/toolkit/components/pdfjs/content/PdfjsParent.sys.mjs b/toolkit/components/pdfjs/content/PdfjsParent.sys.mjs
new file mode 100644
index 0000000000..a11d68ef02
--- /dev/null
+++ b/toolkit/components/pdfjs/content/PdfjsParent.sys.mjs
@@ -0,0 +1,290 @@
+/* Copyright 2012 Mozilla Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs";
+
+const lazy = {};
+
+ChromeUtils.defineESModuleGetters(lazy, {
+ NimbusFeatures: "resource://nimbus/ExperimentAPI.sys.mjs",
+ PdfJsTelemetry: "resource://pdf.js/PdfJsTelemetry.sys.mjs",
+ PrivateBrowsingUtils: "resource://gre/modules/PrivateBrowsingUtils.sys.mjs",
+ SetClipboardSearchString: "resource://gre/modules/Finder.sys.mjs",
+});
+
+var Svc = {};
+XPCOMUtils.defineLazyServiceGetter(
+ Svc,
+ "mime",
+ "@mozilla.org/mime;1",
+ "nsIMIMEService"
+);
+
+XPCOMUtils.defineLazyPreferenceGetter(
+ lazy,
+ "matchesCountLimit",
+ "accessibility.typeaheadfind.matchesCountLimit"
+);
+
+let gFindTypes = [
+ "find",
+ "findagain",
+ "findhighlightallchange",
+ "findcasesensitivitychange",
+ "findbarclose",
+ "finddiacriticmatchingchange",
+];
+
+export class PdfjsParent extends JSWindowActorParent {
+ constructor() {
+ super();
+ this._boundToFindbar = null;
+ this._findFailedString = null;
+ }
+
+ didDestroy() {
+ this._removeEventListener();
+ }
+
+ receiveMessage(aMsg) {
+ switch (aMsg.name) {
+ case "PDFJS:Parent:updateControlState":
+ return this._updateControlState(aMsg);
+ case "PDFJS:Parent:updateMatchesCount":
+ return this._updateMatchesCount(aMsg);
+ case "PDFJS:Parent:addEventListener":
+ return this._addEventListener();
+ case "PDFJS:Parent:saveURL":
+ return this._saveURL(aMsg);
+ case "PDFJS:Parent:recordExposure":
+ return this._recordExposure();
+ case "PDFJS:Parent:reportTelemetry":
+ return this._reportTelemetry(aMsg);
+ }
+ return undefined;
+ }
+
+ /*
+ * Internal
+ */
+
+ get browser() {
+ return this.browsingContext.top.embedderElement;
+ }
+
+ _recordExposure() {
+ lazy.NimbusFeatures.pdfjs.recordExposureEvent({ once: true });
+ }
+
+ _reportTelemetry(aMsg) {
+ lazy.PdfJsTelemetry.report(aMsg.data);
+ }
+
+ _saveURL(aMsg) {
+ const data = aMsg.data;
+ this.browser.ownerGlobal.saveURL(
+ data.blobUrl /* aURL */,
+ data.originalUrl /* aOriginalURL */,
+ data.filename /* aFileName */,
+ null /* aFilePickerTitleKey */,
+ true /* aShouldBypassCache */,
+ false /* aSkipPrompt */,
+ null /* aReferrerInfo */,
+ null /* aCookieJarSettings*/,
+ null /* aSourceDocument */,
+ lazy.PrivateBrowsingUtils.isBrowserPrivate(
+ this.browser
+ ) /* aIsContentWindowPrivate */,
+ Services.scriptSecurityManager.getSystemPrincipal() /* aPrincipal */
+ );
+ }
+
+ _updateControlState(aMsg) {
+ let data = aMsg.data;
+ let browser = this.browser;
+ let tabbrowser = browser.getTabBrowser();
+ let tab = tabbrowser.getTabForBrowser(browser);
+ tabbrowser.getFindBar(tab).then(fb => {
+ if (!fb) {
+ // The tab or window closed.
+ return;
+ }
+ fb.updateControlState(data.result, data.findPrevious);
+
+ if (
+ data.result === Ci.nsITypeAheadFind.FIND_FOUND ||
+ data.result === Ci.nsITypeAheadFind.FIND_WRAPPED ||
+ (data.result === Ci.nsITypeAheadFind.FIND_PENDING &&
+ !this._findFailedString)
+ ) {
+ this._findFailedString = null;
+ lazy.SetClipboardSearchString(data.rawQuery);
+ } else if (!this._findFailedString) {
+ this._findFailedString = data.rawQuery;
+ lazy.SetClipboardSearchString(data.rawQuery);
+ }
+
+ const matchesCount = this._requestMatchesCount(data.matchesCount);
+ fb.onMatchesCountResult(matchesCount);
+ });
+ }
+
+ _updateMatchesCount(aMsg) {
+ let data = aMsg.data;
+ let browser = this.browser;
+ let tabbrowser = browser.getTabBrowser();
+ let tab = tabbrowser.getTabForBrowser(browser);
+ tabbrowser.getFindBar(tab).then(fb => {
+ if (!fb) {
+ // The tab or window closed.
+ return;
+ }
+ const matchesCount = this._requestMatchesCount(data);
+ fb.onMatchesCountResult(matchesCount);
+ });
+ }
+
+ _requestMatchesCount(data) {
+ if (!data) {
+ return { current: 0, total: 0 };
+ }
+ let result = {
+ current: data.current,
+ total: data.total,
+ limit:
+ typeof lazy.matchesCountLimit === "number" ? lazy.matchesCountLimit : 0,
+ };
+ if (result.total > result.limit) {
+ result.total = -1;
+ }
+ return result;
+ }
+
+ handleEvent(aEvent) {
+ const type = aEvent.type;
+ // Handle the tab find initialized event specially:
+ if (type == "TabFindInitialized") {
+ let browser = aEvent.target.linkedBrowser;
+ this._hookupEventListeners(browser);
+ aEvent.target.removeEventListener(type, this);
+ return;
+ }
+
+ if (type == "SwapDocShells") {
+ this._removeEventListener();
+ let newBrowser = aEvent.detail;
+ newBrowser.addEventListener(
+ "EndSwapDocShells",
+ evt => {
+ this._hookupEventListeners(newBrowser);
+ },
+ { once: true }
+ );
+ return;
+ }
+
+ // Ignore events findbar events which arrive while the Pdfjs document is in
+ // the BFCache.
+ if (this.windowContext.isInBFCache) {
+ return;
+ }
+
+ // To avoid forwarding the message as a CPOW, create a structured cloneable
+ // version of the event for both performance, and ease of usage, reasons.
+ let detail = null;
+ if (type !== "findbarclose") {
+ detail = {
+ query: aEvent.detail.query,
+ caseSensitive: aEvent.detail.caseSensitive,
+ entireWord: aEvent.detail.entireWord,
+ highlightAll: aEvent.detail.highlightAll,
+ findPrevious: aEvent.detail.findPrevious,
+ matchDiacritics: aEvent.detail.matchDiacritics,
+ };
+ }
+
+ let browser = aEvent.currentTarget.browser;
+ if (!this._boundToFindbar) {
+ throw new Error(
+ "FindEventManager was not bound for the current browser."
+ );
+ }
+ browser.sendMessageToActor(
+ "PDFJS:Child:handleEvent",
+ { type, detail },
+ "Pdfjs"
+ );
+ aEvent.preventDefault();
+ }
+
+ _addEventListener() {
+ let browser = this.browser;
+ if (this._boundToFindbar) {
+ throw new Error(
+ "FindEventManager was bound 2nd time without unbinding it first."
+ );
+ }
+
+ this._hookupEventListeners(browser);
+ }
+
+ /**
+ * Either hook up all the find event listeners if a findbar exists,
+ * or listen for a find bar being created and hook up event listeners
+ * when it does get created.
+ */
+ _hookupEventListeners(aBrowser) {
+ let tabbrowser = aBrowser.getTabBrowser();
+ let tab = tabbrowser.getTabForBrowser(aBrowser);
+ let findbar = tabbrowser.getCachedFindBar(tab);
+ if (findbar) {
+ // And we need to start listening to find events.
+ for (var i = 0; i < gFindTypes.length; i++) {
+ var type = gFindTypes[i];
+ findbar.addEventListener(type, this, true);
+ }
+ this._boundToFindbar = findbar;
+ } else {
+ tab.addEventListener("TabFindInitialized", this);
+ }
+ aBrowser.addEventListener("SwapDocShells", this);
+ return !!findbar;
+ }
+
+ _removeEventListener() {
+ let browser = this.browser;
+
+ // make sure the listener has been removed.
+ let findbar = this._boundToFindbar;
+ if (findbar) {
+ // No reason to listen to find events any longer.
+ for (var i = 0; i < gFindTypes.length; i++) {
+ var type = gFindTypes[i];
+ findbar.removeEventListener(type, this, true);
+ }
+ } else if (browser) {
+ // If we registered a `TabFindInitialized` listener which never fired,
+ // make sure we remove it.
+ let tabbrowser = browser.getTabBrowser();
+ let tab = tabbrowser.getTabForBrowser(browser);
+ tab?.removeEventListener("TabFindInitialized", this);
+ }
+
+ this._boundToFindbar = null;
+
+ // Clean up any SwapDocShells event listeners.
+ browser?.removeEventListener("SwapDocShells", this);
+ }
+}
diff --git a/toolkit/components/pdfjs/content/build/pdf.mjs b/toolkit/components/pdfjs/content/build/pdf.mjs
new file mode 100644
index 0000000000..72dcbae165
--- /dev/null
+++ b/toolkit/components/pdfjs/content/build/pdf.mjs
@@ -0,0 +1,17198 @@
+/**
+ * @licstart The following is the entire license notice for the
+ * JavaScript code in this page
+ *
+ * Copyright 2023 Mozilla Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * @licend The above is the entire license notice for the
+ * JavaScript code in this page
+ */
+
+/******/ // The require scope
+/******/ var __webpack_require__ = {};
+/******/
+/************************************************************************/
+/******/ /* webpack/runtime/define property getters */
+/******/ (() => {
+/******/ // define getter functions for harmony exports
+/******/ __webpack_require__.d = (exports, definition) => {
+/******/ for(var key in definition) {
+/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
+/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
+/******/ }
+/******/ }
+/******/ };
+/******/ })();
+/******/
+/******/ /* webpack/runtime/hasOwnProperty shorthand */
+/******/ (() => {
+/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
+/******/ })();
+/******/
+/************************************************************************/
+var __webpack_exports__ = globalThis.pdfjsLib = {};
+
+// EXPORTS
+__webpack_require__.d(__webpack_exports__, {
+ AbortException: () => (/* reexport */ AbortException),
+ AnnotationEditorLayer: () => (/* reexport */ AnnotationEditorLayer),
+ AnnotationEditorParamsType: () => (/* reexport */ AnnotationEditorParamsType),
+ AnnotationEditorType: () => (/* reexport */ AnnotationEditorType),
+ AnnotationEditorUIManager: () => (/* reexport */ AnnotationEditorUIManager),
+ AnnotationLayer: () => (/* reexport */ AnnotationLayer),
+ AnnotationMode: () => (/* reexport */ AnnotationMode),
+ CMapCompressionType: () => (/* reexport */ CMapCompressionType),
+ ColorPicker: () => (/* reexport */ ColorPicker),
+ DOMSVGFactory: () => (/* reexport */ DOMSVGFactory),
+ DrawLayer: () => (/* reexport */ DrawLayer),
+ FeatureTest: () => (/* reexport */ util_FeatureTest),
+ GlobalWorkerOptions: () => (/* reexport */ GlobalWorkerOptions),
+ ImageKind: () => (/* reexport */ util_ImageKind),
+ InvalidPDFException: () => (/* reexport */ InvalidPDFException),
+ MissingPDFException: () => (/* reexport */ MissingPDFException),
+ OPS: () => (/* reexport */ OPS),
+ Outliner: () => (/* reexport */ Outliner),
+ PDFDataRangeTransport: () => (/* reexport */ PDFDataRangeTransport),
+ PDFDateString: () => (/* reexport */ PDFDateString),
+ PDFWorker: () => (/* reexport */ PDFWorker),
+ PasswordResponses: () => (/* reexport */ PasswordResponses),
+ PermissionFlag: () => (/* reexport */ PermissionFlag),
+ PixelsPerInch: () => (/* reexport */ PixelsPerInch),
+ PromiseCapability: () => (/* reexport */ PromiseCapability),
+ RenderingCancelledException: () => (/* reexport */ RenderingCancelledException),
+ UnexpectedResponseException: () => (/* reexport */ UnexpectedResponseException),
+ Util: () => (/* reexport */ Util),
+ VerbosityLevel: () => (/* reexport */ VerbosityLevel),
+ XfaLayer: () => (/* reexport */ XfaLayer),
+ build: () => (/* reexport */ build),
+ createValidAbsoluteUrl: () => (/* reexport */ createValidAbsoluteUrl),
+ fetchData: () => (/* reexport */ fetchData),
+ getDocument: () => (/* reexport */ getDocument),
+ getFilenameFromUrl: () => (/* reexport */ getFilenameFromUrl),
+ getPdfFilenameFromUrl: () => (/* reexport */ getPdfFilenameFromUrl),
+ getXfaPageViewport: () => (/* reexport */ getXfaPageViewport),
+ isDataScheme: () => (/* reexport */ isDataScheme),
+ isPdfFile: () => (/* reexport */ isPdfFile),
+ noContextMenu: () => (/* reexport */ noContextMenu),
+ normalizeUnicode: () => (/* reexport */ normalizeUnicode),
+ renderTextLayer: () => (/* reexport */ renderTextLayer),
+ setLayerDimensions: () => (/* reexport */ setLayerDimensions),
+ shadow: () => (/* reexport */ shadow),
+ updateTextLayer: () => (/* reexport */ updateTextLayer),
+ version: () => (/* reexport */ version)
+});
+
+;// CONCATENATED MODULE: ./src/shared/util.js
+const isNodeJS = false;
+const IDENTITY_MATRIX = [1, 0, 0, 1, 0, 0];
+const FONT_IDENTITY_MATRIX = [0.001, 0, 0, 0.001, 0, 0];
+const MAX_IMAGE_SIZE_TO_CACHE = 10e6;
+const LINE_FACTOR = 1.35;
+const LINE_DESCENT_FACTOR = 0.35;
+const BASELINE_FACTOR = LINE_DESCENT_FACTOR / LINE_FACTOR;
+const RenderingIntentFlag = {
+ ANY: 0x01,
+ DISPLAY: 0x02,
+ PRINT: 0x04,
+ SAVE: 0x08,
+ ANNOTATIONS_FORMS: 0x10,
+ ANNOTATIONS_STORAGE: 0x20,
+ ANNOTATIONS_DISABLE: 0x40,
+ OPLIST: 0x100
+};
+const AnnotationMode = {
+ DISABLE: 0,
+ ENABLE: 1,
+ ENABLE_FORMS: 2,
+ ENABLE_STORAGE: 3
+};
+const AnnotationEditorPrefix = "pdfjs_internal_editor_";
+const AnnotationEditorType = {
+ DISABLE: -1,
+ NONE: 0,
+ FREETEXT: 3,
+ HIGHLIGHT: 9,
+ STAMP: 13,
+ INK: 15
+};
+const AnnotationEditorParamsType = {
+ RESIZE: 1,
+ CREATE: 2,
+ FREETEXT_SIZE: 11,
+ FREETEXT_COLOR: 12,
+ FREETEXT_OPACITY: 13,
+ INK_COLOR: 21,
+ INK_THICKNESS: 22,
+ INK_OPACITY: 23,
+ HIGHLIGHT_COLOR: 31,
+ HIGHLIGHT_DEFAULT_COLOR: 32,
+ HIGHLIGHT_THICKNESS: 33,
+ HIGHLIGHT_FREE: 34
+};
+const PermissionFlag = {
+ PRINT: 0x04,
+ MODIFY_CONTENTS: 0x08,
+ COPY: 0x10,
+ MODIFY_ANNOTATIONS: 0x20,
+ FILL_INTERACTIVE_FORMS: 0x100,
+ COPY_FOR_ACCESSIBILITY: 0x200,
+ ASSEMBLE: 0x400,
+ PRINT_HIGH_QUALITY: 0x800
+};
+const TextRenderingMode = {
+ FILL: 0,
+ STROKE: 1,
+ FILL_STROKE: 2,
+ INVISIBLE: 3,
+ FILL_ADD_TO_PATH: 4,
+ STROKE_ADD_TO_PATH: 5,
+ FILL_STROKE_ADD_TO_PATH: 6,
+ ADD_TO_PATH: 7,
+ FILL_STROKE_MASK: 3,
+ ADD_TO_PATH_FLAG: 4
+};
+const util_ImageKind = {
+ GRAYSCALE_1BPP: 1,
+ RGB_24BPP: 2,
+ RGBA_32BPP: 3
+};
+const AnnotationType = {
+ TEXT: 1,
+ LINK: 2,
+ FREETEXT: 3,
+ LINE: 4,
+ SQUARE: 5,
+ CIRCLE: 6,
+ POLYGON: 7,
+ POLYLINE: 8,
+ HIGHLIGHT: 9,
+ UNDERLINE: 10,
+ SQUIGGLY: 11,
+ STRIKEOUT: 12,
+ STAMP: 13,
+ CARET: 14,
+ INK: 15,
+ POPUP: 16,
+ FILEATTACHMENT: 17,
+ SOUND: 18,
+ MOVIE: 19,
+ WIDGET: 20,
+ SCREEN: 21,
+ PRINTERMARK: 22,
+ TRAPNET: 23,
+ WATERMARK: 24,
+ THREED: 25,
+ REDACT: 26
+};
+const AnnotationReplyType = {
+ GROUP: "Group",
+ REPLY: "R"
+};
+const AnnotationFlag = {
+ INVISIBLE: 0x01,
+ HIDDEN: 0x02,
+ PRINT: 0x04,
+ NOZOOM: 0x08,
+ NOROTATE: 0x10,
+ NOVIEW: 0x20,
+ READONLY: 0x40,
+ LOCKED: 0x80,
+ TOGGLENOVIEW: 0x100,
+ LOCKEDCONTENTS: 0x200
+};
+const AnnotationFieldFlag = {
+ READONLY: 0x0000001,
+ REQUIRED: 0x0000002,
+ NOEXPORT: 0x0000004,
+ MULTILINE: 0x0001000,
+ PASSWORD: 0x0002000,
+ NOTOGGLETOOFF: 0x0004000,
+ RADIO: 0x0008000,
+ PUSHBUTTON: 0x0010000,
+ COMBO: 0x0020000,
+ EDIT: 0x0040000,
+ SORT: 0x0080000,
+ FILESELECT: 0x0100000,
+ MULTISELECT: 0x0200000,
+ DONOTSPELLCHECK: 0x0400000,
+ DONOTSCROLL: 0x0800000,
+ COMB: 0x1000000,
+ RICHTEXT: 0x2000000,
+ RADIOSINUNISON: 0x2000000,
+ COMMITONSELCHANGE: 0x4000000
+};
+const AnnotationBorderStyleType = {
+ SOLID: 1,
+ DASHED: 2,
+ BEVELED: 3,
+ INSET: 4,
+ UNDERLINE: 5
+};
+const AnnotationActionEventType = {
+ E: "Mouse Enter",
+ X: "Mouse Exit",
+ D: "Mouse Down",
+ U: "Mouse Up",
+ Fo: "Focus",
+ Bl: "Blur",
+ PO: "PageOpen",
+ PC: "PageClose",
+ PV: "PageVisible",
+ PI: "PageInvisible",
+ K: "Keystroke",
+ F: "Format",
+ V: "Validate",
+ C: "Calculate"
+};
+const DocumentActionEventType = {
+ WC: "WillClose",
+ WS: "WillSave",
+ DS: "DidSave",
+ WP: "WillPrint",
+ DP: "DidPrint"
+};
+const PageActionEventType = {
+ O: "PageOpen",
+ C: "PageClose"
+};
+const VerbosityLevel = {
+ ERRORS: 0,
+ WARNINGS: 1,
+ INFOS: 5
+};
+const CMapCompressionType = {
+ NONE: 0,
+ BINARY: 1
+};
+const OPS = {
+ dependency: 1,
+ setLineWidth: 2,
+ setLineCap: 3,
+ setLineJoin: 4,
+ setMiterLimit: 5,
+ setDash: 6,
+ setRenderingIntent: 7,
+ setFlatness: 8,
+ setGState: 9,
+ save: 10,
+ restore: 11,
+ transform: 12,
+ moveTo: 13,
+ lineTo: 14,
+ curveTo: 15,
+ curveTo2: 16,
+ curveTo3: 17,
+ closePath: 18,
+ rectangle: 19,
+ stroke: 20,
+ closeStroke: 21,
+ fill: 22,
+ eoFill: 23,
+ fillStroke: 24,
+ eoFillStroke: 25,
+ closeFillStroke: 26,
+ closeEOFillStroke: 27,
+ endPath: 28,
+ clip: 29,
+ eoClip: 30,
+ beginText: 31,
+ endText: 32,
+ setCharSpacing: 33,
+ setWordSpacing: 34,
+ setHScale: 35,
+ setLeading: 36,
+ setFont: 37,
+ setTextRenderingMode: 38,
+ setTextRise: 39,
+ moveText: 40,
+ setLeadingMoveText: 41,
+ setTextMatrix: 42,
+ nextLine: 43,
+ showText: 44,
+ showSpacedText: 45,
+ nextLineShowText: 46,
+ nextLineSetSpacingShowText: 47,
+ setCharWidth: 48,
+ setCharWidthAndBounds: 49,
+ setStrokeColorSpace: 50,
+ setFillColorSpace: 51,
+ setStrokeColor: 52,
+ setStrokeColorN: 53,
+ setFillColor: 54,
+ setFillColorN: 55,
+ setStrokeGray: 56,
+ setFillGray: 57,
+ setStrokeRGBColor: 58,
+ setFillRGBColor: 59,
+ setStrokeCMYKColor: 60,
+ setFillCMYKColor: 61,
+ shadingFill: 62,
+ beginInlineImage: 63,
+ beginImageData: 64,
+ endInlineImage: 65,
+ paintXObject: 66,
+ markPoint: 67,
+ markPointProps: 68,
+ beginMarkedContent: 69,
+ beginMarkedContentProps: 70,
+ endMarkedContent: 71,
+ beginCompat: 72,
+ endCompat: 73,
+ paintFormXObjectBegin: 74,
+ paintFormXObjectEnd: 75,
+ beginGroup: 76,
+ endGroup: 77,
+ beginAnnotation: 80,
+ endAnnotation: 81,
+ paintImageMaskXObject: 83,
+ paintImageMaskXObjectGroup: 84,
+ paintImageXObject: 85,
+ paintInlineImageXObject: 86,
+ paintInlineImageXObjectGroup: 87,
+ paintImageXObjectRepeat: 88,
+ paintImageMaskXObjectRepeat: 89,
+ paintSolidColorImageMask: 90,
+ constructPath: 91
+};
+const PasswordResponses = {
+ NEED_PASSWORD: 1,
+ INCORRECT_PASSWORD: 2
+};
+let verbosity = VerbosityLevel.WARNINGS;
+function setVerbosityLevel(level) {
+ if (Number.isInteger(level)) {
+ verbosity = level;
+ }
+}
+function getVerbosityLevel() {
+ return verbosity;
+}
+function info(msg) {
+ if (verbosity >= VerbosityLevel.INFOS) {
+ console.log(`Info: ${msg}`);
+ }
+}
+function warn(msg) {
+ if (verbosity >= VerbosityLevel.WARNINGS) {
+ console.log(`Warning: ${msg}`);
+ }
+}
+function unreachable(msg) {
+ throw new Error(msg);
+}
+function assert(cond, msg) {
+ if (!cond) {
+ unreachable(msg);
+ }
+}
+function _isValidProtocol(url) {
+ switch (url?.protocol) {
+ case "http:":
+ case "https:":
+ case "ftp:":
+ case "mailto:":
+ case "tel:":
+ return true;
+ default:
+ return false;
+ }
+}
+function createValidAbsoluteUrl(url, baseUrl = null, options = null) {
+ if (!url) {
+ return null;
+ }
+ try {
+ if (options && typeof url === "string") {
+ if (options.addDefaultProtocol && url.startsWith("www.")) {
+ const dots = url.match(/\./g);
+ if (dots?.length >= 2) {
+ url = `http://${url}`;
+ }
+ }
+ if (options.tryConvertEncoding) {
+ try {
+ url = stringToUTF8String(url);
+ } catch {}
+ }
+ }
+ const absoluteUrl = baseUrl ? new URL(url, baseUrl) : new URL(url);
+ if (_isValidProtocol(absoluteUrl)) {
+ return absoluteUrl;
+ }
+ } catch {}
+ return null;
+}
+function shadow(obj, prop, value, nonSerializable = false) {
+ Object.defineProperty(obj, prop, {
+ value,
+ enumerable: !nonSerializable,
+ configurable: true,
+ writable: false
+ });
+ return value;
+}
+const BaseException = function BaseExceptionClosure() {
+ function BaseException(message, name) {
+ if (this.constructor === BaseException) {
+ unreachable("Cannot initialize BaseException.");
+ }
+ this.message = message;
+ this.name = name;
+ }
+ BaseException.prototype = new Error();
+ BaseException.constructor = BaseException;
+ return BaseException;
+}();
+class PasswordException extends BaseException {
+ constructor(msg, code) {
+ super(msg, "PasswordException");
+ this.code = code;
+ }
+}
+class UnknownErrorException extends BaseException {
+ constructor(msg, details) {
+ super(msg, "UnknownErrorException");
+ this.details = details;
+ }
+}
+class InvalidPDFException extends BaseException {
+ constructor(msg) {
+ super(msg, "InvalidPDFException");
+ }
+}
+class MissingPDFException extends BaseException {
+ constructor(msg) {
+ super(msg, "MissingPDFException");
+ }
+}
+class UnexpectedResponseException extends BaseException {
+ constructor(msg, status) {
+ super(msg, "UnexpectedResponseException");
+ this.status = status;
+ }
+}
+class FormatError extends BaseException {
+ constructor(msg) {
+ super(msg, "FormatError");
+ }
+}
+class AbortException extends BaseException {
+ constructor(msg) {
+ super(msg, "AbortException");
+ }
+}
+function bytesToString(bytes) {
+ if (typeof bytes !== "object" || bytes?.length === undefined) {
+ unreachable("Invalid argument for bytesToString");
+ }
+ const length = bytes.length;
+ const MAX_ARGUMENT_COUNT = 8192;
+ if (length < MAX_ARGUMENT_COUNT) {
+ return String.fromCharCode.apply(null, bytes);
+ }
+ const strBuf = [];
+ for (let i = 0; i < length; i += MAX_ARGUMENT_COUNT) {
+ const chunkEnd = Math.min(i + MAX_ARGUMENT_COUNT, length);
+ const chunk = bytes.subarray(i, chunkEnd);
+ strBuf.push(String.fromCharCode.apply(null, chunk));
+ }
+ return strBuf.join("");
+}
+function stringToBytes(str) {
+ if (typeof str !== "string") {
+ unreachable("Invalid argument for stringToBytes");
+ }
+ const length = str.length;
+ const bytes = new Uint8Array(length);
+ for (let i = 0; i < length; ++i) {
+ bytes[i] = str.charCodeAt(i) & 0xff;
+ }
+ return bytes;
+}
+function string32(value) {
+ return String.fromCharCode(value >> 24 & 0xff, value >> 16 & 0xff, value >> 8 & 0xff, value & 0xff);
+}
+function objectSize(obj) {
+ return Object.keys(obj).length;
+}
+function objectFromMap(map) {
+ const obj = Object.create(null);
+ for (const [key, value] of map) {
+ obj[key] = value;
+ }
+ return obj;
+}
+function isLittleEndian() {
+ const buffer8 = new Uint8Array(4);
+ buffer8[0] = 1;
+ const view32 = new Uint32Array(buffer8.buffer, 0, 1);
+ return view32[0] === 1;
+}
+function isEvalSupported() {
+ try {
+ new Function("");
+ return true;
+ } catch {
+ return false;
+ }
+}
+class util_FeatureTest {
+ static get isLittleEndian() {
+ return shadow(this, "isLittleEndian", isLittleEndian());
+ }
+ static get isEvalSupported() {
+ return shadow(this, "isEvalSupported", isEvalSupported());
+ }
+ static get isOffscreenCanvasSupported() {
+ return shadow(this, "isOffscreenCanvasSupported", typeof OffscreenCanvas !== "undefined");
+ }
+ static get platform() {
+ return shadow(this, "platform", {
+ isMac: navigator.platform.includes("Mac")
+ });
+ }
+ static get isCSSRoundSupported() {
+ return shadow(this, "isCSSRoundSupported", globalThis.CSS?.supports?.("width: round(1.5px, 1px)"));
+ }
+}
+const hexNumbers = Array.from(Array(256).keys(), n => n.toString(16).padStart(2, "0"));
+class Util {
+ static makeHexColor(r, g, b) {
+ return `#${hexNumbers[r]}${hexNumbers[g]}${hexNumbers[b]}`;
+ }
+ static scaleMinMax(transform, minMax) {
+ let temp;
+ if (transform[0]) {
+ if (transform[0] < 0) {
+ temp = minMax[0];
+ minMax[0] = minMax[2];
+ minMax[2] = temp;
+ }
+ minMax[0] *= transform[0];
+ minMax[2] *= transform[0];
+ if (transform[3] < 0) {
+ temp = minMax[1];
+ minMax[1] = minMax[3];
+ minMax[3] = temp;
+ }
+ minMax[1] *= transform[3];
+ minMax[3] *= transform[3];
+ } else {
+ temp = minMax[0];
+ minMax[0] = minMax[1];
+ minMax[1] = temp;
+ temp = minMax[2];
+ minMax[2] = minMax[3];
+ minMax[3] = temp;
+ if (transform[1] < 0) {
+ temp = minMax[1];
+ minMax[1] = minMax[3];
+ minMax[3] = temp;
+ }
+ minMax[1] *= transform[1];
+ minMax[3] *= transform[1];
+ if (transform[2] < 0) {
+ temp = minMax[0];
+ minMax[0] = minMax[2];
+ minMax[2] = temp;
+ }
+ minMax[0] *= transform[2];
+ minMax[2] *= transform[2];
+ }
+ minMax[0] += transform[4];
+ minMax[1] += transform[5];
+ minMax[2] += transform[4];
+ minMax[3] += transform[5];
+ }
+ static transform(m1, m2) {
+ return [m1[0] * m2[0] + m1[2] * m2[1], m1[1] * m2[0] + m1[3] * m2[1], m1[0] * m2[2] + m1[2] * m2[3], m1[1] * m2[2] + m1[3] * m2[3], m1[0] * m2[4] + m1[2] * m2[5] + m1[4], m1[1] * m2[4] + m1[3] * m2[5] + m1[5]];
+ }
+ static applyTransform(p, m) {
+ const xt = p[0] * m[0] + p[1] * m[2] + m[4];
+ const yt = p[0] * m[1] + p[1] * m[3] + m[5];
+ return [xt, yt];
+ }
+ static applyInverseTransform(p, m) {
+ const d = m[0] * m[3] - m[1] * m[2];
+ const xt = (p[0] * m[3] - p[1] * m[2] + m[2] * m[5] - m[4] * m[3]) / d;
+ const yt = (-p[0] * m[1] + p[1] * m[0] + m[4] * m[1] - m[5] * m[0]) / d;
+ return [xt, yt];
+ }
+ static getAxialAlignedBoundingBox(r, m) {
+ const p1 = this.applyTransform(r, m);
+ const p2 = this.applyTransform(r.slice(2, 4), m);
+ const p3 = this.applyTransform([r[0], r[3]], m);
+ const p4 = this.applyTransform([r[2], r[1]], m);
+ return [Math.min(p1[0], p2[0], p3[0], p4[0]), Math.min(p1[1], p2[1], p3[1], p4[1]), Math.max(p1[0], p2[0], p3[0], p4[0]), Math.max(p1[1], p2[1], p3[1], p4[1])];
+ }
+ static inverseTransform(m) {
+ const d = m[0] * m[3] - m[1] * m[2];
+ return [m[3] / d, -m[1] / d, -m[2] / d, m[0] / d, (m[2] * m[5] - m[4] * m[3]) / d, (m[4] * m[1] - m[5] * m[0]) / d];
+ }
+ static singularValueDecompose2dScale(m) {
+ const transpose = [m[0], m[2], m[1], m[3]];
+ const a = m[0] * transpose[0] + m[1] * transpose[2];
+ const b = m[0] * transpose[1] + m[1] * transpose[3];
+ const c = m[2] * transpose[0] + m[3] * transpose[2];
+ const d = m[2] * transpose[1] + m[3] * transpose[3];
+ const first = (a + d) / 2;
+ const second = Math.sqrt((a + d) ** 2 - 4 * (a * d - c * b)) / 2;
+ const sx = first + second || 1;
+ const sy = first - second || 1;
+ return [Math.sqrt(sx), Math.sqrt(sy)];
+ }
+ static normalizeRect(rect) {
+ const r = rect.slice(0);
+ if (rect[0] > rect[2]) {
+ r[0] = rect[2];
+ r[2] = rect[0];
+ }
+ if (rect[1] > rect[3]) {
+ r[1] = rect[3];
+ r[3] = rect[1];
+ }
+ return r;
+ }
+ static intersect(rect1, rect2) {
+ const xLow = Math.max(Math.min(rect1[0], rect1[2]), Math.min(rect2[0], rect2[2]));
+ const xHigh = Math.min(Math.max(rect1[0], rect1[2]), Math.max(rect2[0], rect2[2]));
+ if (xLow > xHigh) {
+ return null;
+ }
+ const yLow = Math.max(Math.min(rect1[1], rect1[3]), Math.min(rect2[1], rect2[3]));
+ const yHigh = Math.min(Math.max(rect1[1], rect1[3]), Math.max(rect2[1], rect2[3]));
+ if (yLow > yHigh) {
+ return null;
+ }
+ return [xLow, yLow, xHigh, yHigh];
+ }
+ static #getExtremumOnCurve(x0, x1, x2, x3, y0, y1, y2, y3, t, minMax) {
+ if (t <= 0 || t >= 1) {
+ return;
+ }
+ const mt = 1 - t;
+ const tt = t * t;
+ const ttt = tt * t;
+ const x = mt * (mt * (mt * x0 + 3 * t * x1) + 3 * tt * x2) + ttt * x3;
+ const y = mt * (mt * (mt * y0 + 3 * t * y1) + 3 * tt * y2) + ttt * y3;
+ minMax[0] = Math.min(minMax[0], x);
+ minMax[1] = Math.min(minMax[1], y);
+ minMax[2] = Math.max(minMax[2], x);
+ minMax[3] = Math.max(minMax[3], y);
+ }
+ static #getExtremum(x0, x1, x2, x3, y0, y1, y2, y3, a, b, c, minMax) {
+ if (Math.abs(a) < 1e-12) {
+ if (Math.abs(b) >= 1e-12) {
+ this.#getExtremumOnCurve(x0, x1, x2, x3, y0, y1, y2, y3, -c / b, minMax);
+ }
+ return;
+ }
+ const delta = b ** 2 - 4 * c * a;
+ if (delta < 0) {
+ return;
+ }
+ const sqrtDelta = Math.sqrt(delta);
+ const a2 = 2 * a;
+ this.#getExtremumOnCurve(x0, x1, x2, x3, y0, y1, y2, y3, (-b + sqrtDelta) / a2, minMax);
+ this.#getExtremumOnCurve(x0, x1, x2, x3, y0, y1, y2, y3, (-b - sqrtDelta) / a2, minMax);
+ }
+ static bezierBoundingBox(x0, y0, x1, y1, x2, y2, x3, y3, minMax) {
+ if (minMax) {
+ minMax[0] = Math.min(minMax[0], x0, x3);
+ minMax[1] = Math.min(minMax[1], y0, y3);
+ minMax[2] = Math.max(minMax[2], x0, x3);
+ minMax[3] = Math.max(minMax[3], y0, y3);
+ } else {
+ minMax = [Math.min(x0, x3), Math.min(y0, y3), Math.max(x0, x3), Math.max(y0, y3)];
+ }
+ this.#getExtremum(x0, x1, x2, x3, y0, y1, y2, y3, 3 * (-x0 + 3 * (x1 - x2) + x3), 6 * (x0 - 2 * x1 + x2), 3 * (x1 - x0), minMax);
+ this.#getExtremum(x0, x1, x2, x3, y0, y1, y2, y3, 3 * (-y0 + 3 * (y1 - y2) + y3), 6 * (y0 - 2 * y1 + y2), 3 * (y1 - y0), minMax);
+ return minMax;
+ }
+}
+const PDFStringTranslateTable = (/* unused pure expression or super */ null && ([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x2d8, 0x2c7, 0x2c6, 0x2d9, 0x2dd, 0x2db, 0x2da, 0x2dc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x2022, 0x2020, 0x2021, 0x2026, 0x2014, 0x2013, 0x192, 0x2044, 0x2039, 0x203a, 0x2212, 0x2030, 0x201e, 0x201c, 0x201d, 0x2018, 0x2019, 0x201a, 0x2122, 0xfb01, 0xfb02, 0x141, 0x152, 0x160, 0x178, 0x17d, 0x131, 0x142, 0x153, 0x161, 0x17e, 0, 0x20ac]));
+function stringToPDFString(str) {
+ if (str[0] >= "\xEF") {
+ let encoding;
+ if (str[0] === "\xFE" && str[1] === "\xFF") {
+ encoding = "utf-16be";
+ if (str.length % 2 === 1) {
+ str = str.slice(0, -1);
+ }
+ } else if (str[0] === "\xFF" && str[1] === "\xFE") {
+ encoding = "utf-16le";
+ if (str.length % 2 === 1) {
+ str = str.slice(0, -1);
+ }
+ } else if (str[0] === "\xEF" && str[1] === "\xBB" && str[2] === "\xBF") {
+ encoding = "utf-8";
+ }
+ if (encoding) {
+ try {
+ const decoder = new TextDecoder(encoding, {
+ fatal: true
+ });
+ const buffer = stringToBytes(str);
+ const decoded = decoder.decode(buffer);
+ if (!decoded.includes("\x1b")) {
+ return decoded;
+ }
+ return decoded.replaceAll(/\x1b[^\x1b]*(?:\x1b|$)/g, "");
+ } catch (ex) {
+ warn(`stringToPDFString: "${ex}".`);
+ }
+ }
+ }
+ const strBuf = [];
+ for (let i = 0, ii = str.length; i < ii; i++) {
+ const charCode = str.charCodeAt(i);
+ if (charCode === 0x1b) {
+ while (++i < ii && str.charCodeAt(i) !== 0x1b) {}
+ continue;
+ }
+ const code = PDFStringTranslateTable[charCode];
+ strBuf.push(code ? String.fromCharCode(code) : str.charAt(i));
+ }
+ return strBuf.join("");
+}
+function stringToUTF8String(str) {
+ return decodeURIComponent(escape(str));
+}
+function utf8StringToString(str) {
+ return unescape(encodeURIComponent(str));
+}
+function isArrayEqual(arr1, arr2) {
+ if (arr1.length !== arr2.length) {
+ return false;
+ }
+ for (let i = 0, ii = arr1.length; i < ii; i++) {
+ if (arr1[i] !== arr2[i]) {
+ return false;
+ }
+ }
+ return true;
+}
+function getModificationDate(date = new Date()) {
+ const buffer = [date.getUTCFullYear().toString(), (date.getUTCMonth() + 1).toString().padStart(2, "0"), date.getUTCDate().toString().padStart(2, "0"), date.getUTCHours().toString().padStart(2, "0"), date.getUTCMinutes().toString().padStart(2, "0"), date.getUTCSeconds().toString().padStart(2, "0")];
+ return buffer.join("");
+}
+class PromiseCapability {
+ #settled = false;
+ constructor() {
+ this.promise = new Promise((resolve, reject) => {
+ this.resolve = data => {
+ this.#settled = true;
+ resolve(data);
+ };
+ this.reject = reason => {
+ this.#settled = true;
+ reject(reason);
+ };
+ });
+ }
+ get settled() {
+ return this.#settled;
+ }
+}
+let NormalizeRegex = null;
+let NormalizationMap = null;
+function normalizeUnicode(str) {
+ if (!NormalizeRegex) {
+ NormalizeRegex = /([\u00a0\u00b5\u037e\u0eb3\u2000-\u200a\u202f\u2126\ufb00-\ufb04\ufb06\ufb20-\ufb36\ufb38-\ufb3c\ufb3e\ufb40-\ufb41\ufb43-\ufb44\ufb46-\ufba1\ufba4-\ufba9\ufbae-\ufbb1\ufbd3-\ufbdc\ufbde-\ufbe7\ufbea-\ufbf8\ufbfc-\ufbfd\ufc00-\ufc5d\ufc64-\ufcf1\ufcf5-\ufd3d\ufd88\ufdf4\ufdfa-\ufdfb\ufe71\ufe77\ufe79\ufe7b\ufe7d]+)|(\ufb05+)/gu;
+ NormalizationMap = new Map([["ſt", "ſt"]]);
+ }
+ return str.replaceAll(NormalizeRegex, (_, p1, p2) => p1 ? p1.normalize("NFKC") : NormalizationMap.get(p2));
+}
+function getUuid() {
+ return crypto.randomUUID();
+}
+const AnnotationPrefix = "pdfjs_internal_id_";
+
+;// CONCATENATED MODULE: ./src/display/base_factory.js
+
+class BaseFilterFactory {
+ constructor() {
+ if (this.constructor === BaseFilterFactory) {
+ unreachable("Cannot initialize BaseFilterFactory.");
+ }
+ }
+ addFilter(maps) {
+ return "none";
+ }
+ addHCMFilter(fgColor, bgColor) {
+ return "none";
+ }
+ addHighlightHCMFilter(filterName, fgColor, bgColor, newFgColor, newBgColor) {
+ return "none";
+ }
+ destroy(keepHCM = false) {}
+}
+class BaseCanvasFactory {
+ constructor() {
+ if (this.constructor === BaseCanvasFactory) {
+ unreachable("Cannot initialize BaseCanvasFactory.");
+ }
+ }
+ create(width, height) {
+ if (width <= 0 || height <= 0) {
+ throw new Error("Invalid canvas size");
+ }
+ const canvas = this._createCanvas(width, height);
+ return {
+ canvas,
+ context: canvas.getContext("2d")
+ };
+ }
+ reset(canvasAndContext, width, height) {
+ if (!canvasAndContext.canvas) {
+ throw new Error("Canvas is not specified");
+ }
+ if (width <= 0 || height <= 0) {
+ throw new Error("Invalid canvas size");
+ }
+ canvasAndContext.canvas.width = width;
+ canvasAndContext.canvas.height = height;
+ }
+ destroy(canvasAndContext) {
+ if (!canvasAndContext.canvas) {
+ throw new Error("Canvas is not specified");
+ }
+ canvasAndContext.canvas.width = 0;
+ canvasAndContext.canvas.height = 0;
+ canvasAndContext.canvas = null;
+ canvasAndContext.context = null;
+ }
+ _createCanvas(width, height) {
+ unreachable("Abstract method `_createCanvas` called.");
+ }
+}
+class BaseCMapReaderFactory {
+ constructor({
+ baseUrl = null,
+ isCompressed = true
+ }) {
+ if (this.constructor === BaseCMapReaderFactory) {
+ unreachable("Cannot initialize BaseCMapReaderFactory.");
+ }
+ this.baseUrl = baseUrl;
+ this.isCompressed = isCompressed;
+ }
+ async fetch({
+ name
+ }) {
+ if (!this.baseUrl) {
+ throw new Error('The CMap "baseUrl" parameter must be specified, ensure that ' + 'the "cMapUrl" and "cMapPacked" API parameters are provided.');
+ }
+ if (!name) {
+ throw new Error("CMap name must be specified.");
+ }
+ const url = this.baseUrl + name + (this.isCompressed ? ".bcmap" : "");
+ const compressionType = this.isCompressed ? CMapCompressionType.BINARY : CMapCompressionType.NONE;
+ return this._fetchData(url, compressionType).catch(reason => {
+ throw new Error(`Unable to load ${this.isCompressed ? "binary " : ""}CMap at: ${url}`);
+ });
+ }
+ _fetchData(url, compressionType) {
+ unreachable("Abstract method `_fetchData` called.");
+ }
+}
+class BaseStandardFontDataFactory {
+ constructor({
+ baseUrl = null
+ }) {
+ if (this.constructor === BaseStandardFontDataFactory) {
+ unreachable("Cannot initialize BaseStandardFontDataFactory.");
+ }
+ this.baseUrl = baseUrl;
+ }
+ async fetch({
+ filename
+ }) {
+ if (!this.baseUrl) {
+ throw new Error('The standard font "baseUrl" parameter must be specified, ensure that ' + 'the "standardFontDataUrl" API parameter is provided.');
+ }
+ if (!filename) {
+ throw new Error("Font filename must be specified.");
+ }
+ const url = `${this.baseUrl}${filename}`;
+ return this._fetchData(url).catch(reason => {
+ throw new Error(`Unable to load font data at: ${url}`);
+ });
+ }
+ _fetchData(url) {
+ unreachable("Abstract method `_fetchData` called.");
+ }
+}
+class BaseSVGFactory {
+ constructor() {
+ if (this.constructor === BaseSVGFactory) {
+ unreachable("Cannot initialize BaseSVGFactory.");
+ }
+ }
+ create(width, height, skipDimensions = false) {
+ if (width <= 0 || height <= 0) {
+ throw new Error("Invalid SVG dimensions");
+ }
+ const svg = this._createSVG("svg:svg");
+ svg.setAttribute("version", "1.1");
+ if (!skipDimensions) {
+ svg.setAttribute("width", `${width}px`);
+ svg.setAttribute("height", `${height}px`);
+ }
+ svg.setAttribute("preserveAspectRatio", "none");
+ svg.setAttribute("viewBox", `0 0 ${width} ${height}`);
+ return svg;
+ }
+ createElement(type) {
+ if (typeof type !== "string") {
+ throw new Error("Invalid SVG element type");
+ }
+ return this._createSVG(type);
+ }
+ _createSVG(type) {
+ unreachable("Abstract method `_createSVG` called.");
+ }
+}
+
+;// CONCATENATED MODULE: ./src/display/display_utils.js
+
+
+const SVG_NS = "http://www.w3.org/2000/svg";
+class PixelsPerInch {
+ static CSS = 96.0;
+ static PDF = 72.0;
+ static PDF_TO_CSS_UNITS = this.CSS / this.PDF;
+}
+class DOMFilterFactory extends BaseFilterFactory {
+ #_cache;
+ #_defs;
+ #docId;
+ #document;
+ #_hcmCache;
+ #id = 0;
+ constructor({
+ docId,
+ ownerDocument = globalThis.document
+ } = {}) {
+ super();
+ this.#docId = docId;
+ this.#document = ownerDocument;
+ }
+ get #cache() {
+ return this.#_cache ||= new Map();
+ }
+ get #hcmCache() {
+ return this.#_hcmCache ||= new Map();
+ }
+ get #defs() {
+ if (!this.#_defs) {
+ const div = this.#document.createElement("div");
+ const {
+ style
+ } = div;
+ style.visibility = "hidden";
+ style.contain = "strict";
+ style.width = style.height = 0;
+ style.position = "absolute";
+ style.top = style.left = 0;
+ style.zIndex = -1;
+ const svg = this.#document.createElementNS(SVG_NS, "svg");
+ svg.setAttribute("width", 0);
+ svg.setAttribute("height", 0);
+ this.#_defs = this.#document.createElementNS(SVG_NS, "defs");
+ div.append(svg);
+ svg.append(this.#_defs);
+ this.#document.body.append(div);
+ }
+ return this.#_defs;
+ }
+ addFilter(maps) {
+ if (!maps) {
+ return "none";
+ }
+ let value = this.#cache.get(maps);
+ if (value) {
+ return value;
+ }
+ let tableR, tableG, tableB, key;
+ if (maps.length === 1) {
+ const mapR = maps[0];
+ const buffer = new Array(256);
+ for (let i = 0; i < 256; i++) {
+ buffer[i] = mapR[i] / 255;
+ }
+ key = tableR = tableG = tableB = buffer.join(",");
+ } else {
+ const [mapR, mapG, mapB] = maps;
+ const bufferR = new Array(256);
+ const bufferG = new Array(256);
+ const bufferB = new Array(256);
+ for (let i = 0; i < 256; i++) {
+ bufferR[i] = mapR[i] / 255;
+ bufferG[i] = mapG[i] / 255;
+ bufferB[i] = mapB[i] / 255;
+ }
+ tableR = bufferR.join(",");
+ tableG = bufferG.join(",");
+ tableB = bufferB.join(",");
+ key = `${tableR}${tableG}${tableB}`;
+ }
+ value = this.#cache.get(key);
+ if (value) {
+ this.#cache.set(maps, value);
+ return value;
+ }
+ const id = `g_${this.#docId}_transfer_map_${this.#id++}`;
+ const url = `url(#${id})`;
+ this.#cache.set(maps, url);
+ this.#cache.set(key, url);
+ const filter = this.#createFilter(id);
+ this.#addTransferMapConversion(tableR, tableG, tableB, filter);
+ return url;
+ }
+ addHCMFilter(fgColor, bgColor) {
+ const key = `${fgColor}-${bgColor}`;
+ const filterName = "base";
+ let info = this.#hcmCache.get(filterName);
+ if (info?.key === key) {
+ return info.url;
+ }
+ if (info) {
+ info.filter?.remove();
+ info.key = key;
+ info.url = "none";
+ info.filter = null;
+ } else {
+ info = {
+ key,
+ url: "none",
+ filter: null
+ };
+ this.#hcmCache.set(filterName, info);
+ }
+ if (!fgColor || !bgColor) {
+ return info.url;
+ }
+ const fgRGB = this.#getRGB(fgColor);
+ fgColor = Util.makeHexColor(...fgRGB);
+ const bgRGB = this.#getRGB(bgColor);
+ bgColor = Util.makeHexColor(...bgRGB);
+ this.#defs.style.color = "";
+ if (fgColor === "#000000" && bgColor === "#ffffff" || fgColor === bgColor) {
+ return info.url;
+ }
+ const map = new Array(256);
+ for (let i = 0; i <= 255; i++) {
+ const x = i / 255;
+ map[i] = x <= 0.03928 ? x / 12.92 : ((x + 0.055) / 1.055) ** 2.4;
+ }
+ const table = map.join(",");
+ const id = `g_${this.#docId}_hcm_filter`;
+ const filter = info.filter = this.#createFilter(id);
+ this.#addTransferMapConversion(table, table, table, filter);
+ this.#addGrayConversion(filter);
+ const getSteps = (c, n) => {
+ const start = fgRGB[c] / 255;
+ const end = bgRGB[c] / 255;
+ const arr = new Array(n + 1);
+ for (let i = 0; i <= n; i++) {
+ arr[i] = start + i / n * (end - start);
+ }
+ return arr.join(",");
+ };
+ this.#addTransferMapConversion(getSteps(0, 5), getSteps(1, 5), getSteps(2, 5), filter);
+ info.url = `url(#${id})`;
+ return info.url;
+ }
+ addHighlightHCMFilter(filterName, fgColor, bgColor, newFgColor, newBgColor) {
+ const key = `${fgColor}-${bgColor}-${newFgColor}-${newBgColor}`;
+ let info = this.#hcmCache.get(filterName);
+ if (info?.key === key) {
+ return info.url;
+ }
+ if (info) {
+ info.filter?.remove();
+ info.key = key;
+ info.url = "none";
+ info.filter = null;
+ } else {
+ info = {
+ key,
+ url: "none",
+ filter: null
+ };
+ this.#hcmCache.set(filterName, info);
+ }
+ if (!fgColor || !bgColor) {
+ return info.url;
+ }
+ const [fgRGB, bgRGB] = [fgColor, bgColor].map(this.#getRGB.bind(this));
+ let fgGray = Math.round(0.2126 * fgRGB[0] + 0.7152 * fgRGB[1] + 0.0722 * fgRGB[2]);
+ let bgGray = Math.round(0.2126 * bgRGB[0] + 0.7152 * bgRGB[1] + 0.0722 * bgRGB[2]);
+ let [newFgRGB, newBgRGB] = [newFgColor, newBgColor].map(this.#getRGB.bind(this));
+ if (bgGray < fgGray) {
+ [fgGray, bgGray, newFgRGB, newBgRGB] = [bgGray, fgGray, newBgRGB, newFgRGB];
+ }
+ this.#defs.style.color = "";
+ const getSteps = (fg, bg, n) => {
+ const arr = new Array(256);
+ const step = (bgGray - fgGray) / n;
+ const newStart = fg / 255;
+ const newStep = (bg - fg) / (255 * n);
+ let prev = 0;
+ for (let i = 0; i <= n; i++) {
+ const k = Math.round(fgGray + i * step);
+ const value = newStart + i * newStep;
+ for (let j = prev; j <= k; j++) {
+ arr[j] = value;
+ }
+ prev = k + 1;
+ }
+ for (let i = prev; i < 256; i++) {
+ arr[i] = arr[prev - 1];
+ }
+ return arr.join(",");
+ };
+ const id = `g_${this.#docId}_hcm_${filterName}_filter`;
+ const filter = info.filter = this.#createFilter(id);
+ this.#addGrayConversion(filter);
+ this.#addTransferMapConversion(getSteps(newFgRGB[0], newBgRGB[0], 5), getSteps(newFgRGB[1], newBgRGB[1], 5), getSteps(newFgRGB[2], newBgRGB[2], 5), filter);
+ info.url = `url(#${id})`;
+ return info.url;
+ }
+ destroy(keepHCM = false) {
+ if (keepHCM && this.#hcmCache.size !== 0) {
+ return;
+ }
+ if (this.#_defs) {
+ this.#_defs.parentNode.parentNode.remove();
+ this.#_defs = null;
+ }
+ if (this.#_cache) {
+ this.#_cache.clear();
+ this.#_cache = null;
+ }
+ this.#id = 0;
+ }
+ #addGrayConversion(filter) {
+ const feColorMatrix = this.#document.createElementNS(SVG_NS, "feColorMatrix");
+ feColorMatrix.setAttribute("type", "matrix");
+ feColorMatrix.setAttribute("values", "0.2126 0.7152 0.0722 0 0 0.2126 0.7152 0.0722 0 0 0.2126 0.7152 0.0722 0 0 0 0 0 1 0");
+ filter.append(feColorMatrix);
+ }
+ #createFilter(id) {
+ const filter = this.#document.createElementNS(SVG_NS, "filter");
+ filter.setAttribute("color-interpolation-filters", "sRGB");
+ filter.setAttribute("id", id);
+ this.#defs.append(filter);
+ return filter;
+ }
+ #appendFeFunc(feComponentTransfer, func, table) {
+ const feFunc = this.#document.createElementNS(SVG_NS, func);
+ feFunc.setAttribute("type", "discrete");
+ feFunc.setAttribute("tableValues", table);
+ feComponentTransfer.append(feFunc);
+ }
+ #addTransferMapConversion(rTable, gTable, bTable, filter) {
+ const feComponentTransfer = this.#document.createElementNS(SVG_NS, "feComponentTransfer");
+ filter.append(feComponentTransfer);
+ this.#appendFeFunc(feComponentTransfer, "feFuncR", rTable);
+ this.#appendFeFunc(feComponentTransfer, "feFuncG", gTable);
+ this.#appendFeFunc(feComponentTransfer, "feFuncB", bTable);
+ }
+ #getRGB(color) {
+ this.#defs.style.color = color;
+ return getRGB(getComputedStyle(this.#defs).getPropertyValue("color"));
+ }
+}
+class DOMCanvasFactory extends BaseCanvasFactory {
+ constructor({
+ ownerDocument = globalThis.document
+ } = {}) {
+ super();
+ this._document = ownerDocument;
+ }
+ _createCanvas(width, height) {
+ const canvas = this._document.createElement("canvas");
+ canvas.width = width;
+ canvas.height = height;
+ return canvas;
+ }
+}
+async function fetchData(url, type = "text") {
+ const response = await fetch(url);
+ if (!response.ok) {
+ throw new Error(response.statusText);
+ }
+ switch (type) {
+ case "arraybuffer":
+ return response.arrayBuffer();
+ case "blob":
+ return response.blob();
+ case "json":
+ return response.json();
+ }
+ return response.text();
+}
+class DOMCMapReaderFactory extends BaseCMapReaderFactory {
+ _fetchData(url, compressionType) {
+ return fetchData(url, this.isCompressed ? "arraybuffer" : "text").then(data => ({
+ cMapData: data instanceof ArrayBuffer ? new Uint8Array(data) : stringToBytes(data),
+ compressionType
+ }));
+ }
+}
+class DOMStandardFontDataFactory extends BaseStandardFontDataFactory {
+ _fetchData(url) {
+ return fetchData(url, "arraybuffer").then(data => new Uint8Array(data));
+ }
+}
+class DOMSVGFactory extends BaseSVGFactory {
+ _createSVG(type) {
+ return document.createElementNS(SVG_NS, type);
+ }
+}
+class PageViewport {
+ constructor({
+ viewBox,
+ scale,
+ rotation,
+ offsetX = 0,
+ offsetY = 0,
+ dontFlip = false
+ }) {
+ this.viewBox = viewBox;
+ this.scale = scale;
+ this.rotation = rotation;
+ this.offsetX = offsetX;
+ this.offsetY = offsetY;
+ const centerX = (viewBox[2] + viewBox[0]) / 2;
+ const centerY = (viewBox[3] + viewBox[1]) / 2;
+ let rotateA, rotateB, rotateC, rotateD;
+ rotation %= 360;
+ if (rotation < 0) {
+ rotation += 360;
+ }
+ switch (rotation) {
+ case 180:
+ rotateA = -1;
+ rotateB = 0;
+ rotateC = 0;
+ rotateD = 1;
+ break;
+ case 90:
+ rotateA = 0;
+ rotateB = 1;
+ rotateC = 1;
+ rotateD = 0;
+ break;
+ case 270:
+ rotateA = 0;
+ rotateB = -1;
+ rotateC = -1;
+ rotateD = 0;
+ break;
+ case 0:
+ rotateA = 1;
+ rotateB = 0;
+ rotateC = 0;
+ rotateD = -1;
+ break;
+ default:
+ throw new Error("PageViewport: Invalid rotation, must be a multiple of 90 degrees.");
+ }
+ if (dontFlip) {
+ rotateC = -rotateC;
+ rotateD = -rotateD;
+ }
+ let offsetCanvasX, offsetCanvasY;
+ let width, height;
+ if (rotateA === 0) {
+ offsetCanvasX = Math.abs(centerY - viewBox[1]) * scale + offsetX;
+ offsetCanvasY = Math.abs(centerX - viewBox[0]) * scale + offsetY;
+ width = (viewBox[3] - viewBox[1]) * scale;
+ height = (viewBox[2] - viewBox[0]) * scale;
+ } else {
+ offsetCanvasX = Math.abs(centerX - viewBox[0]) * scale + offsetX;
+ offsetCanvasY = Math.abs(centerY - viewBox[1]) * scale + offsetY;
+ width = (viewBox[2] - viewBox[0]) * scale;
+ height = (viewBox[3] - viewBox[1]) * scale;
+ }
+ this.transform = [rotateA * scale, rotateB * scale, rotateC * scale, rotateD * scale, offsetCanvasX - rotateA * scale * centerX - rotateC * scale * centerY, offsetCanvasY - rotateB * scale * centerX - rotateD * scale * centerY];
+ this.width = width;
+ this.height = height;
+ }
+ get rawDims() {
+ const {
+ viewBox
+ } = this;
+ return shadow(this, "rawDims", {
+ pageWidth: viewBox[2] - viewBox[0],
+ pageHeight: viewBox[3] - viewBox[1],
+ pageX: viewBox[0],
+ pageY: viewBox[1]
+ });
+ }
+ clone({
+ scale = this.scale,
+ rotation = this.rotation,
+ offsetX = this.offsetX,
+ offsetY = this.offsetY,
+ dontFlip = false
+ } = {}) {
+ return new PageViewport({
+ viewBox: this.viewBox.slice(),
+ scale,
+ rotation,
+ offsetX,
+ offsetY,
+ dontFlip
+ });
+ }
+ convertToViewportPoint(x, y) {
+ return Util.applyTransform([x, y], this.transform);
+ }
+ convertToViewportRectangle(rect) {
+ const topLeft = Util.applyTransform([rect[0], rect[1]], this.transform);
+ const bottomRight = Util.applyTransform([rect[2], rect[3]], this.transform);
+ return [topLeft[0], topLeft[1], bottomRight[0], bottomRight[1]];
+ }
+ convertToPdfPoint(x, y) {
+ return Util.applyInverseTransform([x, y], this.transform);
+ }
+}
+class RenderingCancelledException extends BaseException {
+ constructor(msg, extraDelay = 0) {
+ super(msg, "RenderingCancelledException");
+ this.extraDelay = extraDelay;
+ }
+}
+function isDataScheme(url) {
+ const ii = url.length;
+ let i = 0;
+ while (i < ii && url[i].trim() === "") {
+ i++;
+ }
+ return url.substring(i, i + 5).toLowerCase() === "data:";
+}
+function isPdfFile(filename) {
+ return typeof filename === "string" && /\.pdf$/i.test(filename);
+}
+function getFilenameFromUrl(url, onlyStripPath = false) {
+ if (!onlyStripPath) {
+ [url] = url.split(/[#?]/, 1);
+ }
+ return url.substring(url.lastIndexOf("/") + 1);
+}
+function getPdfFilenameFromUrl(url, defaultFilename = "document.pdf") {
+ if (typeof url !== "string") {
+ return defaultFilename;
+ }
+ if (isDataScheme(url)) {
+ warn('getPdfFilenameFromUrl: ignore "data:"-URL for performance reasons.');
+ return defaultFilename;
+ }
+ const reURI = /^(?:(?:[^:]+:)?\/\/[^/]+)?([^?#]*)(\?[^#]*)?(#.*)?$/;
+ const reFilename = /[^/?#=]+\.pdf\b(?!.*\.pdf\b)/i;
+ const splitURI = reURI.exec(url);
+ let suggestedFilename = reFilename.exec(splitURI[1]) || reFilename.exec(splitURI[2]) || reFilename.exec(splitURI[3]);
+ if (suggestedFilename) {
+ suggestedFilename = suggestedFilename[0];
+ if (suggestedFilename.includes("%")) {
+ try {
+ suggestedFilename = reFilename.exec(decodeURIComponent(suggestedFilename))[0];
+ } catch {}
+ }
+ }
+ return suggestedFilename || defaultFilename;
+}
+class StatTimer {
+ started = Object.create(null);
+ times = [];
+ time(name) {
+ if (name in this.started) {
+ warn(`Timer is already running for ${name}`);
+ }
+ this.started[name] = Date.now();
+ }
+ timeEnd(name) {
+ if (!(name in this.started)) {
+ warn(`Timer has not been started for ${name}`);
+ }
+ this.times.push({
+ name,
+ start: this.started[name],
+ end: Date.now()
+ });
+ delete this.started[name];
+ }
+ toString() {
+ const outBuf = [];
+ let longest = 0;
+ for (const {
+ name
+ } of this.times) {
+ longest = Math.max(name.length, longest);
+ }
+ for (const {
+ name,
+ start,
+ end
+ } of this.times) {
+ outBuf.push(`${name.padEnd(longest)} ${end - start}ms\n`);
+ }
+ return outBuf.join("");
+ }
+}
+function isValidFetchUrl(url, baseUrl) {
+ throw new Error("Not implemented: isValidFetchUrl");
+}
+function noContextMenu(e) {
+ e.preventDefault();
+}
+function deprecated(details) {
+ console.log("Deprecated API usage: " + details);
+}
+let pdfDateStringRegex;
+class PDFDateString {
+ static toDateObject(input) {
+ if (!input || typeof input !== "string") {
+ return null;
+ }
+ pdfDateStringRegex ||= new RegExp("^D:" + "(\\d{4})" + "(\\d{2})?" + "(\\d{2})?" + "(\\d{2})?" + "(\\d{2})?" + "(\\d{2})?" + "([Z|+|-])?" + "(\\d{2})?" + "'?" + "(\\d{2})?" + "'?");
+ const matches = pdfDateStringRegex.exec(input);
+ if (!matches) {
+ return null;
+ }
+ const year = parseInt(matches[1], 10);
+ let month = parseInt(matches[2], 10);
+ month = month >= 1 && month <= 12 ? month - 1 : 0;
+ let day = parseInt(matches[3], 10);
+ day = day >= 1 && day <= 31 ? day : 1;
+ let hour = parseInt(matches[4], 10);
+ hour = hour >= 0 && hour <= 23 ? hour : 0;
+ let minute = parseInt(matches[5], 10);
+ minute = minute >= 0 && minute <= 59 ? minute : 0;
+ let second = parseInt(matches[6], 10);
+ second = second >= 0 && second <= 59 ? second : 0;
+ const universalTimeRelation = matches[7] || "Z";
+ let offsetHour = parseInt(matches[8], 10);
+ offsetHour = offsetHour >= 0 && offsetHour <= 23 ? offsetHour : 0;
+ let offsetMinute = parseInt(matches[9], 10) || 0;
+ offsetMinute = offsetMinute >= 0 && offsetMinute <= 59 ? offsetMinute : 0;
+ if (universalTimeRelation === "-") {
+ hour += offsetHour;
+ minute += offsetMinute;
+ } else if (universalTimeRelation === "+") {
+ hour -= offsetHour;
+ minute -= offsetMinute;
+ }
+ return new Date(Date.UTC(year, month, day, hour, minute, second));
+ }
+}
+function getXfaPageViewport(xfaPage, {
+ scale = 1,
+ rotation = 0
+}) {
+ const {
+ width,
+ height
+ } = xfaPage.attributes.style;
+ const viewBox = [0, 0, parseInt(width), parseInt(height)];
+ return new PageViewport({
+ viewBox,
+ scale,
+ rotation
+ });
+}
+function getRGB(color) {
+ if (color.startsWith("#")) {
+ const colorRGB = parseInt(color.slice(1), 16);
+ return [(colorRGB & 0xff0000) >> 16, (colorRGB & 0x00ff00) >> 8, colorRGB & 0x0000ff];
+ }
+ if (color.startsWith("rgb(")) {
+ return color.slice(4, -1).split(",").map(x => parseInt(x));
+ }
+ if (color.startsWith("rgba(")) {
+ return color.slice(5, -1).split(",").map(x => parseInt(x)).slice(0, 3);
+ }
+ warn(`Not a valid color format: "${color}"`);
+ return [0, 0, 0];
+}
+function getColorValues(colors) {
+ const span = document.createElement("span");
+ span.style.visibility = "hidden";
+ document.body.append(span);
+ for (const name of colors.keys()) {
+ span.style.color = name;
+ const computedColor = window.getComputedStyle(span).color;
+ colors.set(name, getRGB(computedColor));
+ }
+ span.remove();
+}
+function getCurrentTransform(ctx) {
+ const {
+ a,
+ b,
+ c,
+ d,
+ e,
+ f
+ } = ctx.getTransform();
+ return [a, b, c, d, e, f];
+}
+function getCurrentTransformInverse(ctx) {
+ const {
+ a,
+ b,
+ c,
+ d,
+ e,
+ f
+ } = ctx.getTransform().invertSelf();
+ return [a, b, c, d, e, f];
+}
+function setLayerDimensions(div, viewport, mustFlip = false, mustRotate = true) {
+ if (viewport instanceof PageViewport) {
+ const {
+ pageWidth,
+ pageHeight
+ } = viewport.rawDims;
+ const {
+ style
+ } = div;
+ const useRound = util_FeatureTest.isCSSRoundSupported;
+ const w = `var(--scale-factor) * ${pageWidth}px`,
+ h = `var(--scale-factor) * ${pageHeight}px`;
+ const widthStr = useRound ? `round(${w}, 1px)` : `calc(${w})`,
+ heightStr = useRound ? `round(${h}, 1px)` : `calc(${h})`;
+ if (!mustFlip || viewport.rotation % 180 === 0) {
+ style.width = widthStr;
+ style.height = heightStr;
+ } else {
+ style.width = heightStr;
+ style.height = widthStr;
+ }
+ }
+ if (mustRotate) {
+ div.setAttribute("data-main-rotation", viewport.rotation);
+ }
+}
+
+;// CONCATENATED MODULE: ./src/display/editor/tools.js
+
+
+function bindEvents(obj, element, names) {
+ for (const name of names) {
+ element.addEventListener(name, obj[name].bind(obj));
+ }
+}
+function opacityToHex(opacity) {
+ return Math.round(Math.min(255, Math.max(1, 255 * opacity))).toString(16).padStart(2, "0");
+}
+class IdManager {
+ #id = 0;
+ constructor() {}
+ get id() {
+ return `${AnnotationEditorPrefix}${this.#id++}`;
+ }
+}
+class ImageManager {
+ #baseId = getUuid();
+ #id = 0;
+ #cache = null;
+ static get _isSVGFittingCanvas() {
+ const svg = `data:image/svg+xml;charset=UTF-8,<svg viewBox="0 0 1 1" width="1" height="1" xmlns="http://www.w3.org/2000/svg"><rect width="1" height="1" style="fill:red;"/></svg>`;
+ const canvas = new OffscreenCanvas(1, 3);
+ const ctx = canvas.getContext("2d");
+ const image = new Image();
+ image.src = svg;
+ const promise = image.decode().then(() => {
+ ctx.drawImage(image, 0, 0, 1, 1, 0, 0, 1, 3);
+ return new Uint32Array(ctx.getImageData(0, 0, 1, 1).data.buffer)[0] === 0;
+ });
+ return shadow(this, "_isSVGFittingCanvas", promise);
+ }
+ async #get(key, rawData) {
+ this.#cache ||= new Map();
+ let data = this.#cache.get(key);
+ if (data === null) {
+ return null;
+ }
+ if (data?.bitmap) {
+ data.refCounter += 1;
+ return data;
+ }
+ try {
+ data ||= {
+ bitmap: null,
+ id: `image_${this.#baseId}_${this.#id++}`,
+ refCounter: 0,
+ isSvg: false
+ };
+ let image;
+ if (typeof rawData === "string") {
+ data.url = rawData;
+ image = await fetchData(rawData, "blob");
+ } else {
+ image = data.file = rawData;
+ }
+ if (image.type === "image/svg+xml") {
+ const mustRemoveAspectRatioPromise = ImageManager._isSVGFittingCanvas;
+ const fileReader = new FileReader();
+ const imageElement = new Image();
+ const imagePromise = new Promise((resolve, reject) => {
+ imageElement.onload = () => {
+ data.bitmap = imageElement;
+ data.isSvg = true;
+ resolve();
+ };
+ fileReader.onload = async () => {
+ const url = data.svgUrl = fileReader.result;
+ imageElement.src = (await mustRemoveAspectRatioPromise) ? `${url}#svgView(preserveAspectRatio(none))` : url;
+ };
+ imageElement.onerror = fileReader.onerror = reject;
+ });
+ fileReader.readAsDataURL(image);
+ await imagePromise;
+ } else {
+ data.bitmap = await createImageBitmap(image);
+ }
+ data.refCounter = 1;
+ } catch (e) {
+ console.error(e);
+ data = null;
+ }
+ this.#cache.set(key, data);
+ if (data) {
+ this.#cache.set(data.id, data);
+ }
+ return data;
+ }
+ async getFromFile(file) {
+ const {
+ lastModified,
+ name,
+ size,
+ type
+ } = file;
+ return this.#get(`${lastModified}_${name}_${size}_${type}`, file);
+ }
+ async getFromUrl(url) {
+ return this.#get(url, url);
+ }
+ async getFromId(id) {
+ this.#cache ||= new Map();
+ const data = this.#cache.get(id);
+ if (!data) {
+ return null;
+ }
+ if (data.bitmap) {
+ data.refCounter += 1;
+ return data;
+ }
+ if (data.file) {
+ return this.getFromFile(data.file);
+ }
+ return this.getFromUrl(data.url);
+ }
+ getSvgUrl(id) {
+ const data = this.#cache.get(id);
+ if (!data?.isSvg) {
+ return null;
+ }
+ return data.svgUrl;
+ }
+ deleteId(id) {
+ this.#cache ||= new Map();
+ const data = this.#cache.get(id);
+ if (!data) {
+ return;
+ }
+ data.refCounter -= 1;
+ if (data.refCounter !== 0) {
+ return;
+ }
+ data.bitmap = null;
+ }
+ isValidId(id) {
+ return id.startsWith(`image_${this.#baseId}_`);
+ }
+}
+class CommandManager {
+ #commands = [];
+ #locked = false;
+ #maxSize;
+ #position = -1;
+ constructor(maxSize = 128) {
+ this.#maxSize = maxSize;
+ }
+ add({
+ cmd,
+ undo,
+ post,
+ mustExec,
+ type = NaN,
+ overwriteIfSameType = false,
+ keepUndo = false
+ }) {
+ if (mustExec) {
+ cmd();
+ }
+ if (this.#locked) {
+ return;
+ }
+ const save = {
+ cmd,
+ undo,
+ post,
+ type
+ };
+ if (this.#position === -1) {
+ if (this.#commands.length > 0) {
+ this.#commands.length = 0;
+ }
+ this.#position = 0;
+ this.#commands.push(save);
+ return;
+ }
+ if (overwriteIfSameType && this.#commands[this.#position].type === type) {
+ if (keepUndo) {
+ save.undo = this.#commands[this.#position].undo;
+ }
+ this.#commands[this.#position] = save;
+ return;
+ }
+ const next = this.#position + 1;
+ if (next === this.#maxSize) {
+ this.#commands.splice(0, 1);
+ } else {
+ this.#position = next;
+ if (next < this.#commands.length) {
+ this.#commands.splice(next);
+ }
+ }
+ this.#commands.push(save);
+ }
+ undo() {
+ if (this.#position === -1) {
+ return;
+ }
+ this.#locked = true;
+ const {
+ undo,
+ post
+ } = this.#commands[this.#position];
+ undo();
+ post?.();
+ this.#locked = false;
+ this.#position -= 1;
+ }
+ redo() {
+ if (this.#position < this.#commands.length - 1) {
+ this.#position += 1;
+ this.#locked = true;
+ const {
+ cmd,
+ post
+ } = this.#commands[this.#position];
+ cmd();
+ post?.();
+ this.#locked = false;
+ }
+ }
+ hasSomethingToUndo() {
+ return this.#position !== -1;
+ }
+ hasSomethingToRedo() {
+ return this.#position < this.#commands.length - 1;
+ }
+ destroy() {
+ this.#commands = null;
+ }
+}
+class KeyboardManager {
+ constructor(callbacks) {
+ this.buffer = [];
+ this.callbacks = new Map();
+ this.allKeys = new Set();
+ const {
+ isMac
+ } = util_FeatureTest.platform;
+ for (const [keys, callback, options = {}] of callbacks) {
+ for (const key of keys) {
+ const isMacKey = key.startsWith("mac+");
+ if (isMac && isMacKey) {
+ this.callbacks.set(key.slice(4), {
+ callback,
+ options
+ });
+ this.allKeys.add(key.split("+").at(-1));
+ } else if (!isMac && !isMacKey) {
+ this.callbacks.set(key, {
+ callback,
+ options
+ });
+ this.allKeys.add(key.split("+").at(-1));
+ }
+ }
+ }
+ }
+ #serialize(event) {
+ if (event.altKey) {
+ this.buffer.push("alt");
+ }
+ if (event.ctrlKey) {
+ this.buffer.push("ctrl");
+ }
+ if (event.metaKey) {
+ this.buffer.push("meta");
+ }
+ if (event.shiftKey) {
+ this.buffer.push("shift");
+ }
+ this.buffer.push(event.key);
+ const str = this.buffer.join("+");
+ this.buffer.length = 0;
+ return str;
+ }
+ exec(self, event) {
+ if (!this.allKeys.has(event.key)) {
+ return;
+ }
+ const info = this.callbacks.get(this.#serialize(event));
+ if (!info) {
+ return;
+ }
+ const {
+ callback,
+ options: {
+ bubbles = false,
+ args = [],
+ checker = null
+ }
+ } = info;
+ if (checker && !checker(self, event)) {
+ return;
+ }
+ callback.bind(self, ...args, event)();
+ if (!bubbles) {
+ event.stopPropagation();
+ event.preventDefault();
+ }
+ }
+}
+class ColorManager {
+ static _colorsMapping = new Map([["CanvasText", [0, 0, 0]], ["Canvas", [255, 255, 255]]]);
+ get _colors() {
+ const colors = new Map([["CanvasText", null], ["Canvas", null]]);
+ getColorValues(colors);
+ return shadow(this, "_colors", colors);
+ }
+ convert(color) {
+ const rgb = getRGB(color);
+ if (!window.matchMedia("(forced-colors: active)").matches) {
+ return rgb;
+ }
+ for (const [name, RGB] of this._colors) {
+ if (RGB.every((x, i) => x === rgb[i])) {
+ return ColorManager._colorsMapping.get(name);
+ }
+ }
+ return rgb;
+ }
+ getHexCode(name) {
+ const rgb = this._colors.get(name);
+ if (!rgb) {
+ return name;
+ }
+ return Util.makeHexColor(...rgb);
+ }
+}
+class AnnotationEditorUIManager {
+ #activeEditor = null;
+ #allEditors = new Map();
+ #allLayers = new Map();
+ #altTextManager = null;
+ #annotationStorage = null;
+ #commandManager = new CommandManager();
+ #currentPageIndex = 0;
+ #deletedAnnotationsElementIds = new Set();
+ #draggingEditors = null;
+ #editorTypes = null;
+ #editorsToRescale = new Set();
+ #filterFactory = null;
+ #focusMainContainerTimeoutId = null;
+ #highlightColors = null;
+ #highlightWhenShiftUp = false;
+ #idManager = new IdManager();
+ #isEnabled = false;
+ #isWaiting = false;
+ #lastActiveElement = null;
+ #mainHighlightColorPicker = null;
+ #mlManager = null;
+ #mode = AnnotationEditorType.NONE;
+ #selectedEditors = new Set();
+ #selectedTextNode = null;
+ #pageColors = null;
+ #boundBlur = this.blur.bind(this);
+ #boundFocus = this.focus.bind(this);
+ #boundCopy = this.copy.bind(this);
+ #boundCut = this.cut.bind(this);
+ #boundPaste = this.paste.bind(this);
+ #boundKeydown = this.keydown.bind(this);
+ #boundKeyup = this.keyup.bind(this);
+ #boundOnEditingAction = this.onEditingAction.bind(this);
+ #boundOnPageChanging = this.onPageChanging.bind(this);
+ #boundOnScaleChanging = this.onScaleChanging.bind(this);
+ #boundSelectionChange = this.#selectionChange.bind(this);
+ #boundOnRotationChanging = this.onRotationChanging.bind(this);
+ #previousStates = {
+ isEditing: false,
+ isEmpty: true,
+ hasSomethingToUndo: false,
+ hasSomethingToRedo: false,
+ hasSelectedEditor: false,
+ hasSelectedText: false
+ };
+ #translation = [0, 0];
+ #translationTimeoutId = null;
+ #container = null;
+ #viewer = null;
+ static TRANSLATE_SMALL = 1;
+ static TRANSLATE_BIG = 10;
+ static get _keyboardManager() {
+ const proto = AnnotationEditorUIManager.prototype;
+ const arrowChecker = self => self.#container.contains(document.activeElement) && document.activeElement.tagName !== "BUTTON" && self.hasSomethingToControl();
+ const textInputChecker = (_self, {
+ target: el
+ }) => {
+ if (el instanceof HTMLInputElement) {
+ const {
+ type
+ } = el;
+ return type !== "text" && type !== "number";
+ }
+ return true;
+ };
+ const small = this.TRANSLATE_SMALL;
+ const big = this.TRANSLATE_BIG;
+ return shadow(this, "_keyboardManager", new KeyboardManager([[["ctrl+a", "mac+meta+a"], proto.selectAll, {
+ checker: textInputChecker
+ }], [["ctrl+z", "mac+meta+z"], proto.undo, {
+ checker: textInputChecker
+ }], [["ctrl+y", "ctrl+shift+z", "mac+meta+shift+z", "ctrl+shift+Z", "mac+meta+shift+Z"], proto.redo, {
+ checker: textInputChecker
+ }], [["Backspace", "alt+Backspace", "ctrl+Backspace", "shift+Backspace", "mac+Backspace", "mac+alt+Backspace", "mac+ctrl+Backspace", "Delete", "ctrl+Delete", "shift+Delete", "mac+Delete"], proto.delete, {
+ checker: textInputChecker
+ }], [["Enter", "mac+Enter"], proto.addNewEditorFromKeyboard, {
+ checker: (self, {
+ target: el
+ }) => !(el instanceof HTMLButtonElement) && self.#container.contains(el) && !self.isEnterHandled
+ }], [[" ", "mac+ "], proto.addNewEditorFromKeyboard, {
+ checker: (self, {
+ target: el
+ }) => !(el instanceof HTMLButtonElement) && self.#container.contains(document.activeElement)
+ }], [["Escape", "mac+Escape"], proto.unselectAll], [["ArrowLeft", "mac+ArrowLeft"], proto.translateSelectedEditors, {
+ args: [-small, 0],
+ checker: arrowChecker
+ }], [["ctrl+ArrowLeft", "mac+shift+ArrowLeft"], proto.translateSelectedEditors, {
+ args: [-big, 0],
+ checker: arrowChecker
+ }], [["ArrowRight", "mac+ArrowRight"], proto.translateSelectedEditors, {
+ args: [small, 0],
+ checker: arrowChecker
+ }], [["ctrl+ArrowRight", "mac+shift+ArrowRight"], proto.translateSelectedEditors, {
+ args: [big, 0],
+ checker: arrowChecker
+ }], [["ArrowUp", "mac+ArrowUp"], proto.translateSelectedEditors, {
+ args: [0, -small],
+ checker: arrowChecker
+ }], [["ctrl+ArrowUp", "mac+shift+ArrowUp"], proto.translateSelectedEditors, {
+ args: [0, -big],
+ checker: arrowChecker
+ }], [["ArrowDown", "mac+ArrowDown"], proto.translateSelectedEditors, {
+ args: [0, small],
+ checker: arrowChecker
+ }], [["ctrl+ArrowDown", "mac+shift+ArrowDown"], proto.translateSelectedEditors, {
+ args: [0, big],
+ checker: arrowChecker
+ }]]));
+ }
+ constructor(container, viewer, altTextManager, eventBus, pdfDocument, pageColors, highlightColors, mlManager) {
+ this.#container = container;
+ this.#viewer = viewer;
+ this.#altTextManager = altTextManager;
+ this._eventBus = eventBus;
+ this._eventBus._on("editingaction", this.#boundOnEditingAction);
+ this._eventBus._on("pagechanging", this.#boundOnPageChanging);
+ this._eventBus._on("scalechanging", this.#boundOnScaleChanging);
+ this._eventBus._on("rotationchanging", this.#boundOnRotationChanging);
+ this.#addSelectionListener();
+ this.#annotationStorage = pdfDocument.annotationStorage;
+ this.#filterFactory = pdfDocument.filterFactory;
+ this.#pageColors = pageColors;
+ this.#highlightColors = highlightColors || null;
+ this.#mlManager = mlManager || null;
+ this.viewParameters = {
+ realScale: PixelsPerInch.PDF_TO_CSS_UNITS,
+ rotation: 0
+ };
+ this.isShiftKeyDown = false;
+ }
+ destroy() {
+ this.#removeKeyboardManager();
+ this.#removeFocusManager();
+ this._eventBus._off("editingaction", this.#boundOnEditingAction);
+ this._eventBus._off("pagechanging", this.#boundOnPageChanging);
+ this._eventBus._off("scalechanging", this.#boundOnScaleChanging);
+ this._eventBus._off("rotationchanging", this.#boundOnRotationChanging);
+ for (const layer of this.#allLayers.values()) {
+ layer.destroy();
+ }
+ this.#allLayers.clear();
+ this.#allEditors.clear();
+ this.#editorsToRescale.clear();
+ this.#activeEditor = null;
+ this.#selectedEditors.clear();
+ this.#commandManager.destroy();
+ this.#altTextManager?.destroy();
+ if (this.#focusMainContainerTimeoutId) {
+ clearTimeout(this.#focusMainContainerTimeoutId);
+ this.#focusMainContainerTimeoutId = null;
+ }
+ if (this.#translationTimeoutId) {
+ clearTimeout(this.#translationTimeoutId);
+ this.#translationTimeoutId = null;
+ }
+ this.#removeSelectionListener();
+ }
+ async mlGuess(data) {
+ return this.#mlManager?.guess(data) || null;
+ }
+ get hasMLManager() {
+ return !!this.#mlManager;
+ }
+ get hcmFilter() {
+ return shadow(this, "hcmFilter", this.#pageColors ? this.#filterFactory.addHCMFilter(this.#pageColors.foreground, this.#pageColors.background) : "none");
+ }
+ get direction() {
+ return shadow(this, "direction", getComputedStyle(this.#container).direction);
+ }
+ get highlightColors() {
+ return shadow(this, "highlightColors", this.#highlightColors ? new Map(this.#highlightColors.split(",").map(pair => pair.split("=").map(x => x.trim()))) : null);
+ }
+ get highlightColorNames() {
+ return shadow(this, "highlightColorNames", this.highlightColors ? new Map(Array.from(this.highlightColors, e => e.reverse())) : null);
+ }
+ setMainHighlightColorPicker(colorPicker) {
+ this.#mainHighlightColorPicker = colorPicker;
+ }
+ editAltText(editor) {
+ this.#altTextManager?.editAltText(this, editor);
+ }
+ onPageChanging({
+ pageNumber
+ }) {
+ this.#currentPageIndex = pageNumber - 1;
+ }
+ focusMainContainer() {
+ this.#container.focus();
+ }
+ findParent(x, y) {
+ for (const layer of this.#allLayers.values()) {
+ const {
+ x: layerX,
+ y: layerY,
+ width,
+ height
+ } = layer.div.getBoundingClientRect();
+ if (x >= layerX && x <= layerX + width && y >= layerY && y <= layerY + height) {
+ return layer;
+ }
+ }
+ return null;
+ }
+ disableUserSelect(value = false) {
+ this.#viewer.classList.toggle("noUserSelect", value);
+ }
+ addShouldRescale(editor) {
+ this.#editorsToRescale.add(editor);
+ }
+ removeShouldRescale(editor) {
+ this.#editorsToRescale.delete(editor);
+ }
+ onScaleChanging({
+ scale
+ }) {
+ this.commitOrRemove();
+ this.viewParameters.realScale = scale * PixelsPerInch.PDF_TO_CSS_UNITS;
+ for (const editor of this.#editorsToRescale) {
+ editor.onScaleChanging();
+ }
+ }
+ onRotationChanging({
+ pagesRotation
+ }) {
+ this.commitOrRemove();
+ this.viewParameters.rotation = pagesRotation;
+ }
+ highlightSelection(methodOfCreation = "") {
+ const selection = document.getSelection();
+ if (!selection || selection.isCollapsed) {
+ return;
+ }
+ const {
+ anchorNode,
+ anchorOffset,
+ focusNode,
+ focusOffset
+ } = selection;
+ const anchorElement = anchorNode.nodeType === Node.TEXT_NODE ? anchorNode.parentElement : anchorNode;
+ const textLayer = anchorElement.closest(".textLayer");
+ const boxes = this.getSelectionBoxes(textLayer);
+ selection.empty();
+ if (this.#mode === AnnotationEditorType.NONE) {
+ this._eventBus.dispatch("showannotationeditorui", {
+ source: this,
+ mode: AnnotationEditorType.HIGHLIGHT
+ });
+ }
+ for (const layer of this.#allLayers.values()) {
+ if (layer.hasTextLayer(textLayer)) {
+ layer.createAndAddNewEditor({
+ x: 0,
+ y: 0
+ }, false, {
+ methodOfCreation,
+ boxes,
+ anchorNode,
+ anchorOffset,
+ focusNode,
+ focusOffset
+ });
+ break;
+ }
+ }
+ }
+ addToAnnotationStorage(editor) {
+ if (!editor.isEmpty() && this.#annotationStorage && !this.#annotationStorage.has(editor.id)) {
+ this.#annotationStorage.setValue(editor.id, editor);
+ }
+ }
+ #selectionChange() {
+ const selection = document.getSelection();
+ if (!selection || selection.isCollapsed) {
+ if (this.#selectedTextNode) {
+ this.#selectedTextNode = null;
+ this.#dispatchUpdateStates({
+ hasSelectedText: false
+ });
+ }
+ return;
+ }
+ const {
+ anchorNode
+ } = selection;
+ if (anchorNode === this.#selectedTextNode) {
+ return;
+ }
+ const anchorElement = anchorNode.nodeType === Node.TEXT_NODE ? anchorNode.parentElement : anchorNode;
+ if (!anchorElement.closest(".textLayer")) {
+ if (this.#selectedTextNode) {
+ this.#selectedTextNode = null;
+ this.#dispatchUpdateStates({
+ hasSelectedText: false
+ });
+ }
+ return;
+ }
+ this.#selectedTextNode = anchorNode;
+ this.#dispatchUpdateStates({
+ hasSelectedText: true
+ });
+ if (this.#mode !== AnnotationEditorType.HIGHLIGHT) {
+ return;
+ }
+ this.#highlightWhenShiftUp = this.isShiftKeyDown;
+ if (!this.isShiftKeyDown) {
+ const pointerup = e => {
+ if (e.type === "pointerup" && e.button !== 0) {
+ return;
+ }
+ window.removeEventListener("pointerup", pointerup);
+ window.removeEventListener("blur", pointerup);
+ if (e.type === "pointerup") {
+ this.highlightSelection("main_toolbar");
+ }
+ };
+ window.addEventListener("pointerup", pointerup);
+ window.addEventListener("blur", pointerup);
+ }
+ }
+ #addSelectionListener() {
+ document.addEventListener("selectionchange", this.#boundSelectionChange);
+ }
+ #removeSelectionListener() {
+ document.removeEventListener("selectionchange", this.#boundSelectionChange);
+ }
+ #addFocusManager() {
+ window.addEventListener("focus", this.#boundFocus);
+ window.addEventListener("blur", this.#boundBlur);
+ }
+ #removeFocusManager() {
+ window.removeEventListener("focus", this.#boundFocus);
+ window.removeEventListener("blur", this.#boundBlur);
+ }
+ blur() {
+ this.isShiftKeyDown = false;
+ if (this.#highlightWhenShiftUp) {
+ this.#highlightWhenShiftUp = false;
+ this.highlightSelection("main_toolbar");
+ }
+ if (!this.hasSelection) {
+ return;
+ }
+ const {
+ activeElement
+ } = document;
+ for (const editor of this.#selectedEditors) {
+ if (editor.div.contains(activeElement)) {
+ this.#lastActiveElement = [editor, activeElement];
+ editor._focusEventsAllowed = false;
+ break;
+ }
+ }
+ }
+ focus() {
+ if (!this.#lastActiveElement) {
+ return;
+ }
+ const [lastEditor, lastActiveElement] = this.#lastActiveElement;
+ this.#lastActiveElement = null;
+ lastActiveElement.addEventListener("focusin", () => {
+ lastEditor._focusEventsAllowed = true;
+ }, {
+ once: true
+ });
+ lastActiveElement.focus();
+ }
+ #addKeyboardManager() {
+ window.addEventListener("keydown", this.#boundKeydown);
+ window.addEventListener("keyup", this.#boundKeyup);
+ }
+ #removeKeyboardManager() {
+ window.removeEventListener("keydown", this.#boundKeydown);
+ window.removeEventListener("keyup", this.#boundKeyup);
+ }
+ #addCopyPasteListeners() {
+ document.addEventListener("copy", this.#boundCopy);
+ document.addEventListener("cut", this.#boundCut);
+ document.addEventListener("paste", this.#boundPaste);
+ }
+ #removeCopyPasteListeners() {
+ document.removeEventListener("copy", this.#boundCopy);
+ document.removeEventListener("cut", this.#boundCut);
+ document.removeEventListener("paste", this.#boundPaste);
+ }
+ addEditListeners() {
+ this.#addKeyboardManager();
+ this.#addCopyPasteListeners();
+ }
+ removeEditListeners() {
+ this.#removeKeyboardManager();
+ this.#removeCopyPasteListeners();
+ }
+ copy(event) {
+ event.preventDefault();
+ this.#activeEditor?.commitOrRemove();
+ if (!this.hasSelection) {
+ return;
+ }
+ const editors = [];
+ for (const editor of this.#selectedEditors) {
+ const serialized = editor.serialize(true);
+ if (serialized) {
+ editors.push(serialized);
+ }
+ }
+ if (editors.length === 0) {
+ return;
+ }
+ event.clipboardData.setData("application/pdfjs", JSON.stringify(editors));
+ }
+ cut(event) {
+ this.copy(event);
+ this.delete();
+ }
+ paste(event) {
+ event.preventDefault();
+ const {
+ clipboardData
+ } = event;
+ for (const item of clipboardData.items) {
+ for (const editorType of this.#editorTypes) {
+ if (editorType.isHandlingMimeForPasting(item.type)) {
+ editorType.paste(item, this.currentLayer);
+ return;
+ }
+ }
+ }
+ let data = clipboardData.getData("application/pdfjs");
+ if (!data) {
+ return;
+ }
+ try {
+ data = JSON.parse(data);
+ } catch (ex) {
+ warn(`paste: "${ex.message}".`);
+ return;
+ }
+ if (!Array.isArray(data)) {
+ return;
+ }
+ this.unselectAll();
+ const layer = this.currentLayer;
+ try {
+ const newEditors = [];
+ for (const editor of data) {
+ const deserializedEditor = layer.deserialize(editor);
+ if (!deserializedEditor) {
+ return;
+ }
+ newEditors.push(deserializedEditor);
+ }
+ const cmd = () => {
+ for (const editor of newEditors) {
+ this.#addEditorToLayer(editor);
+ }
+ this.#selectEditors(newEditors);
+ };
+ const undo = () => {
+ for (const editor of newEditors) {
+ editor.remove();
+ }
+ };
+ this.addCommands({
+ cmd,
+ undo,
+ mustExec: true
+ });
+ } catch (ex) {
+ warn(`paste: "${ex.message}".`);
+ }
+ }
+ keydown(event) {
+ if (!this.isShiftKeyDown && event.key === "Shift") {
+ this.isShiftKeyDown = true;
+ }
+ if (!this.isEditorHandlingKeyboard) {
+ AnnotationEditorUIManager._keyboardManager.exec(this, event);
+ }
+ }
+ keyup(event) {
+ if (this.isShiftKeyDown && event.key === "Shift") {
+ this.isShiftKeyDown = false;
+ if (this.#highlightWhenShiftUp) {
+ this.#highlightWhenShiftUp = false;
+ this.highlightSelection("main_toolbar");
+ }
+ }
+ }
+ onEditingAction({
+ name
+ }) {
+ switch (name) {
+ case "undo":
+ case "redo":
+ case "delete":
+ case "selectAll":
+ this[name]();
+ break;
+ case "highlightSelection":
+ this.highlightSelection("context_menu");
+ break;
+ }
+ }
+ #dispatchUpdateStates(details) {
+ const hasChanged = Object.entries(details).some(([key, value]) => this.#previousStates[key] !== value);
+ if (hasChanged) {
+ this._eventBus.dispatch("annotationeditorstateschanged", {
+ source: this,
+ details: Object.assign(this.#previousStates, details)
+ });
+ if (this.#mode === AnnotationEditorType.HIGHLIGHT && details.hasSelectedEditor === false) {
+ this.#dispatchUpdateUI([[AnnotationEditorParamsType.HIGHLIGHT_FREE, true]]);
+ }
+ }
+ }
+ #dispatchUpdateUI(details) {
+ this._eventBus.dispatch("annotationeditorparamschanged", {
+ source: this,
+ details
+ });
+ }
+ setEditingState(isEditing) {
+ if (isEditing) {
+ this.#addFocusManager();
+ this.#addKeyboardManager();
+ this.#addCopyPasteListeners();
+ this.#dispatchUpdateStates({
+ isEditing: this.#mode !== AnnotationEditorType.NONE,
+ isEmpty: this.#isEmpty(),
+ hasSomethingToUndo: this.#commandManager.hasSomethingToUndo(),
+ hasSomethingToRedo: this.#commandManager.hasSomethingToRedo(),
+ hasSelectedEditor: false
+ });
+ } else {
+ this.#removeFocusManager();
+ this.#removeKeyboardManager();
+ this.#removeCopyPasteListeners();
+ this.#dispatchUpdateStates({
+ isEditing: false
+ });
+ this.disableUserSelect(false);
+ }
+ }
+ registerEditorTypes(types) {
+ if (this.#editorTypes) {
+ return;
+ }
+ this.#editorTypes = types;
+ for (const editorType of this.#editorTypes) {
+ this.#dispatchUpdateUI(editorType.defaultPropertiesToUpdate);
+ }
+ }
+ getId() {
+ return this.#idManager.id;
+ }
+ get currentLayer() {
+ return this.#allLayers.get(this.#currentPageIndex);
+ }
+ getLayer(pageIndex) {
+ return this.#allLayers.get(pageIndex);
+ }
+ get currentPageIndex() {
+ return this.#currentPageIndex;
+ }
+ addLayer(layer) {
+ this.#allLayers.set(layer.pageIndex, layer);
+ if (this.#isEnabled) {
+ layer.enable();
+ } else {
+ layer.disable();
+ }
+ }
+ removeLayer(layer) {
+ this.#allLayers.delete(layer.pageIndex);
+ }
+ updateMode(mode, editId = null, isFromKeyboard = false) {
+ if (this.#mode === mode) {
+ return;
+ }
+ this.#mode = mode;
+ if (mode === AnnotationEditorType.NONE) {
+ this.setEditingState(false);
+ this.#disableAll();
+ return;
+ }
+ this.setEditingState(true);
+ this.#enableAll();
+ this.unselectAll();
+ for (const layer of this.#allLayers.values()) {
+ layer.updateMode(mode);
+ }
+ if (!editId && isFromKeyboard) {
+ this.addNewEditorFromKeyboard();
+ return;
+ }
+ if (!editId) {
+ return;
+ }
+ for (const editor of this.#allEditors.values()) {
+ if (editor.annotationElementId === editId) {
+ this.setSelected(editor);
+ editor.enterInEditMode();
+ break;
+ }
+ }
+ }
+ addNewEditorFromKeyboard() {
+ if (this.currentLayer.canCreateNewEmptyEditor()) {
+ this.currentLayer.addNewEditor();
+ }
+ }
+ updateToolbar(mode) {
+ if (mode === this.#mode) {
+ return;
+ }
+ this._eventBus.dispatch("switchannotationeditormode", {
+ source: this,
+ mode
+ });
+ }
+ updateParams(type, value) {
+ if (!this.#editorTypes) {
+ return;
+ }
+ switch (type) {
+ case AnnotationEditorParamsType.CREATE:
+ this.currentLayer.addNewEditor();
+ return;
+ case AnnotationEditorParamsType.HIGHLIGHT_DEFAULT_COLOR:
+ this.#mainHighlightColorPicker?.updateColor(value);
+ break;
+ }
+ for (const editor of this.#selectedEditors) {
+ editor.updateParams(type, value);
+ }
+ for (const editorType of this.#editorTypes) {
+ editorType.updateDefaultParams(type, value);
+ }
+ }
+ enableWaiting(mustWait = false) {
+ if (this.#isWaiting === mustWait) {
+ return;
+ }
+ this.#isWaiting = mustWait;
+ for (const layer of this.#allLayers.values()) {
+ if (mustWait) {
+ layer.disableClick();
+ } else {
+ layer.enableClick();
+ }
+ layer.div.classList.toggle("waiting", mustWait);
+ }
+ }
+ #enableAll() {
+ if (!this.#isEnabled) {
+ this.#isEnabled = true;
+ for (const layer of this.#allLayers.values()) {
+ layer.enable();
+ }
+ }
+ }
+ #disableAll() {
+ this.unselectAll();
+ if (this.#isEnabled) {
+ this.#isEnabled = false;
+ for (const layer of this.#allLayers.values()) {
+ layer.disable();
+ }
+ }
+ }
+ getEditors(pageIndex) {
+ const editors = [];
+ for (const editor of this.#allEditors.values()) {
+ if (editor.pageIndex === pageIndex) {
+ editors.push(editor);
+ }
+ }
+ return editors;
+ }
+ getEditor(id) {
+ return this.#allEditors.get(id);
+ }
+ addEditor(editor) {
+ this.#allEditors.set(editor.id, editor);
+ }
+ removeEditor(editor) {
+ if (editor.div.contains(document.activeElement)) {
+ if (this.#focusMainContainerTimeoutId) {
+ clearTimeout(this.#focusMainContainerTimeoutId);
+ }
+ this.#focusMainContainerTimeoutId = setTimeout(() => {
+ this.focusMainContainer();
+ this.#focusMainContainerTimeoutId = null;
+ }, 0);
+ }
+ this.#allEditors.delete(editor.id);
+ this.unselect(editor);
+ if (!editor.annotationElementId || !this.#deletedAnnotationsElementIds.has(editor.annotationElementId)) {
+ this.#annotationStorage?.remove(editor.id);
+ }
+ }
+ addDeletedAnnotationElement(editor) {
+ this.#deletedAnnotationsElementIds.add(editor.annotationElementId);
+ editor.deleted = true;
+ }
+ isDeletedAnnotationElement(annotationElementId) {
+ return this.#deletedAnnotationsElementIds.has(annotationElementId);
+ }
+ removeDeletedAnnotationElement(editor) {
+ this.#deletedAnnotationsElementIds.delete(editor.annotationElementId);
+ editor.deleted = false;
+ }
+ #addEditorToLayer(editor) {
+ const layer = this.#allLayers.get(editor.pageIndex);
+ if (layer) {
+ layer.addOrRebuild(editor);
+ } else {
+ this.addEditor(editor);
+ }
+ }
+ setActiveEditor(editor) {
+ if (this.#activeEditor === editor) {
+ return;
+ }
+ this.#activeEditor = editor;
+ if (editor) {
+ this.#dispatchUpdateUI(editor.propertiesToUpdate);
+ }
+ }
+ get #lastSelectedEditor() {
+ let ed = null;
+ for (ed of this.#selectedEditors) {}
+ return ed;
+ }
+ updateUI(editor) {
+ if (this.#lastSelectedEditor === editor) {
+ this.#dispatchUpdateUI(editor.propertiesToUpdate);
+ }
+ }
+ toggleSelected(editor) {
+ if (this.#selectedEditors.has(editor)) {
+ this.#selectedEditors.delete(editor);
+ editor.unselect();
+ this.#dispatchUpdateStates({
+ hasSelectedEditor: this.hasSelection
+ });
+ return;
+ }
+ this.#selectedEditors.add(editor);
+ editor.select();
+ this.#dispatchUpdateUI(editor.propertiesToUpdate);
+ this.#dispatchUpdateStates({
+ hasSelectedEditor: true
+ });
+ }
+ setSelected(editor) {
+ for (const ed of this.#selectedEditors) {
+ if (ed !== editor) {
+ ed.unselect();
+ }
+ }
+ this.#selectedEditors.clear();
+ this.#selectedEditors.add(editor);
+ editor.select();
+ this.#dispatchUpdateUI(editor.propertiesToUpdate);
+ this.#dispatchUpdateStates({
+ hasSelectedEditor: true
+ });
+ }
+ isSelected(editor) {
+ return this.#selectedEditors.has(editor);
+ }
+ get firstSelectedEditor() {
+ return this.#selectedEditors.values().next().value;
+ }
+ unselect(editor) {
+ editor.unselect();
+ this.#selectedEditors.delete(editor);
+ this.#dispatchUpdateStates({
+ hasSelectedEditor: this.hasSelection
+ });
+ }
+ get hasSelection() {
+ return this.#selectedEditors.size !== 0;
+ }
+ get isEnterHandled() {
+ return this.#selectedEditors.size === 1 && this.firstSelectedEditor.isEnterHandled;
+ }
+ undo() {
+ this.#commandManager.undo();
+ this.#dispatchUpdateStates({
+ hasSomethingToUndo: this.#commandManager.hasSomethingToUndo(),
+ hasSomethingToRedo: true,
+ isEmpty: this.#isEmpty()
+ });
+ }
+ redo() {
+ this.#commandManager.redo();
+ this.#dispatchUpdateStates({
+ hasSomethingToUndo: true,
+ hasSomethingToRedo: this.#commandManager.hasSomethingToRedo(),
+ isEmpty: this.#isEmpty()
+ });
+ }
+ addCommands(params) {
+ this.#commandManager.add(params);
+ this.#dispatchUpdateStates({
+ hasSomethingToUndo: true,
+ hasSomethingToRedo: false,
+ isEmpty: this.#isEmpty()
+ });
+ }
+ #isEmpty() {
+ if (this.#allEditors.size === 0) {
+ return true;
+ }
+ if (this.#allEditors.size === 1) {
+ for (const editor of this.#allEditors.values()) {
+ return editor.isEmpty();
+ }
+ }
+ return false;
+ }
+ delete() {
+ this.commitOrRemove();
+ if (!this.hasSelection) {
+ return;
+ }
+ const editors = [...this.#selectedEditors];
+ const cmd = () => {
+ for (const editor of editors) {
+ editor.remove();
+ }
+ };
+ const undo = () => {
+ for (const editor of editors) {
+ this.#addEditorToLayer(editor);
+ }
+ };
+ this.addCommands({
+ cmd,
+ undo,
+ mustExec: true
+ });
+ }
+ commitOrRemove() {
+ this.#activeEditor?.commitOrRemove();
+ }
+ hasSomethingToControl() {
+ return this.#activeEditor || this.hasSelection;
+ }
+ #selectEditors(editors) {
+ for (const editor of this.#selectedEditors) {
+ editor.unselect();
+ }
+ this.#selectedEditors.clear();
+ for (const editor of editors) {
+ if (editor.isEmpty()) {
+ continue;
+ }
+ this.#selectedEditors.add(editor);
+ editor.select();
+ }
+ this.#dispatchUpdateStates({
+ hasSelectedEditor: this.hasSelection
+ });
+ }
+ selectAll() {
+ for (const editor of this.#selectedEditors) {
+ editor.commit();
+ }
+ this.#selectEditors(this.#allEditors.values());
+ }
+ unselectAll() {
+ if (this.#activeEditor) {
+ this.#activeEditor.commitOrRemove();
+ if (this.#mode !== AnnotationEditorType.NONE) {
+ return;
+ }
+ }
+ if (!this.hasSelection) {
+ return;
+ }
+ for (const editor of this.#selectedEditors) {
+ editor.unselect();
+ }
+ this.#selectedEditors.clear();
+ this.#dispatchUpdateStates({
+ hasSelectedEditor: false
+ });
+ }
+ translateSelectedEditors(x, y, noCommit = false) {
+ if (!noCommit) {
+ this.commitOrRemove();
+ }
+ if (!this.hasSelection) {
+ return;
+ }
+ this.#translation[0] += x;
+ this.#translation[1] += y;
+ const [totalX, totalY] = this.#translation;
+ const editors = [...this.#selectedEditors];
+ const TIME_TO_WAIT = 1000;
+ if (this.#translationTimeoutId) {
+ clearTimeout(this.#translationTimeoutId);
+ }
+ this.#translationTimeoutId = setTimeout(() => {
+ this.#translationTimeoutId = null;
+ this.#translation[0] = this.#translation[1] = 0;
+ this.addCommands({
+ cmd: () => {
+ for (const editor of editors) {
+ if (this.#allEditors.has(editor.id)) {
+ editor.translateInPage(totalX, totalY);
+ }
+ }
+ },
+ undo: () => {
+ for (const editor of editors) {
+ if (this.#allEditors.has(editor.id)) {
+ editor.translateInPage(-totalX, -totalY);
+ }
+ }
+ },
+ mustExec: false
+ });
+ }, TIME_TO_WAIT);
+ for (const editor of editors) {
+ editor.translateInPage(x, y);
+ }
+ }
+ setUpDragSession() {
+ if (!this.hasSelection) {
+ return;
+ }
+ this.disableUserSelect(true);
+ this.#draggingEditors = new Map();
+ for (const editor of this.#selectedEditors) {
+ this.#draggingEditors.set(editor, {
+ savedX: editor.x,
+ savedY: editor.y,
+ savedPageIndex: editor.pageIndex,
+ newX: 0,
+ newY: 0,
+ newPageIndex: -1
+ });
+ }
+ }
+ endDragSession() {
+ if (!this.#draggingEditors) {
+ return false;
+ }
+ this.disableUserSelect(false);
+ const map = this.#draggingEditors;
+ this.#draggingEditors = null;
+ let mustBeAddedInUndoStack = false;
+ for (const [{
+ x,
+ y,
+ pageIndex
+ }, value] of map) {
+ value.newX = x;
+ value.newY = y;
+ value.newPageIndex = pageIndex;
+ mustBeAddedInUndoStack ||= x !== value.savedX || y !== value.savedY || pageIndex !== value.savedPageIndex;
+ }
+ if (!mustBeAddedInUndoStack) {
+ return false;
+ }
+ const move = (editor, x, y, pageIndex) => {
+ if (this.#allEditors.has(editor.id)) {
+ const parent = this.#allLayers.get(pageIndex);
+ if (parent) {
+ editor._setParentAndPosition(parent, x, y);
+ } else {
+ editor.pageIndex = pageIndex;
+ editor.x = x;
+ editor.y = y;
+ }
+ }
+ };
+ this.addCommands({
+ cmd: () => {
+ for (const [editor, {
+ newX,
+ newY,
+ newPageIndex
+ }] of map) {
+ move(editor, newX, newY, newPageIndex);
+ }
+ },
+ undo: () => {
+ for (const [editor, {
+ savedX,
+ savedY,
+ savedPageIndex
+ }] of map) {
+ move(editor, savedX, savedY, savedPageIndex);
+ }
+ },
+ mustExec: true
+ });
+ return true;
+ }
+ dragSelectedEditors(tx, ty) {
+ if (!this.#draggingEditors) {
+ return;
+ }
+ for (const editor of this.#draggingEditors.keys()) {
+ editor.drag(tx, ty);
+ }
+ }
+ rebuild(editor) {
+ if (editor.parent === null) {
+ const parent = this.getLayer(editor.pageIndex);
+ if (parent) {
+ parent.changeParent(editor);
+ parent.addOrRebuild(editor);
+ } else {
+ this.addEditor(editor);
+ this.addToAnnotationStorage(editor);
+ editor.rebuild();
+ }
+ } else {
+ editor.parent.addOrRebuild(editor);
+ }
+ }
+ get isEditorHandlingKeyboard() {
+ return this.getActive()?.shouldGetKeyboardEvents() || this.#selectedEditors.size === 1 && this.firstSelectedEditor.shouldGetKeyboardEvents();
+ }
+ isActive(editor) {
+ return this.#activeEditor === editor;
+ }
+ getActive() {
+ return this.#activeEditor;
+ }
+ getMode() {
+ return this.#mode;
+ }
+ get imageManager() {
+ return shadow(this, "imageManager", new ImageManager());
+ }
+ getSelectionBoxes(textLayer) {
+ if (!textLayer) {
+ return null;
+ }
+ const selection = document.getSelection();
+ for (let i = 0, ii = selection.rangeCount; i < ii; i++) {
+ if (!textLayer.contains(selection.getRangeAt(i).commonAncestorContainer)) {
+ return null;
+ }
+ }
+ const {
+ x: layerX,
+ y: layerY,
+ width: parentWidth,
+ height: parentHeight
+ } = textLayer.getBoundingClientRect();
+ let rotator;
+ switch (textLayer.getAttribute("data-main-rotation")) {
+ case "90":
+ rotator = (x, y, w, h) => ({
+ x: (y - layerY) / parentHeight,
+ y: 1 - (x + w - layerX) / parentWidth,
+ width: h / parentHeight,
+ height: w / parentWidth
+ });
+ break;
+ case "180":
+ rotator = (x, y, w, h) => ({
+ x: 1 - (x + w - layerX) / parentWidth,
+ y: 1 - (y + h - layerY) / parentHeight,
+ width: w / parentWidth,
+ height: h / parentHeight
+ });
+ break;
+ case "270":
+ rotator = (x, y, w, h) => ({
+ x: 1 - (y + h - layerY) / parentHeight,
+ y: (x - layerX) / parentWidth,
+ width: h / parentHeight,
+ height: w / parentWidth
+ });
+ break;
+ default:
+ rotator = (x, y, w, h) => ({
+ x: (x - layerX) / parentWidth,
+ y: (y - layerY) / parentHeight,
+ width: w / parentWidth,
+ height: h / parentHeight
+ });
+ break;
+ }
+ const boxes = [];
+ for (let i = 0, ii = selection.rangeCount; i < ii; i++) {
+ const range = selection.getRangeAt(i);
+ if (range.collapsed) {
+ continue;
+ }
+ for (const {
+ x,
+ y,
+ width,
+ height
+ } of range.getClientRects()) {
+ if (width === 0 || height === 0) {
+ continue;
+ }
+ boxes.push(rotator(x, y, width, height));
+ }
+ }
+ return boxes.length === 0 ? null : boxes;
+ }
+}
+
+;// CONCATENATED MODULE: ./src/display/editor/alt_text.js
+
+class AltText {
+ #altText = "";
+ #altTextDecorative = false;
+ #altTextButton = null;
+ #altTextTooltip = null;
+ #altTextTooltipTimeout = null;
+ #altTextWasFromKeyBoard = false;
+ #editor = null;
+ static _l10nPromise = null;
+ constructor(editor) {
+ this.#editor = editor;
+ }
+ static initialize(l10nPromise) {
+ AltText._l10nPromise ||= l10nPromise;
+ }
+ async render() {
+ const altText = this.#altTextButton = document.createElement("button");
+ altText.className = "altText";
+ const msg = await AltText._l10nPromise.get("pdfjs-editor-alt-text-button-label");
+ altText.textContent = msg;
+ altText.setAttribute("aria-label", msg);
+ altText.tabIndex = "0";
+ altText.addEventListener("contextmenu", noContextMenu);
+ altText.addEventListener("pointerdown", event => event.stopPropagation());
+ const onClick = event => {
+ event.preventDefault();
+ this.#editor._uiManager.editAltText(this.#editor);
+ };
+ altText.addEventListener("click", onClick, {
+ capture: true
+ });
+ altText.addEventListener("keydown", event => {
+ if (event.target === altText && event.key === "Enter") {
+ this.#altTextWasFromKeyBoard = true;
+ onClick(event);
+ }
+ });
+ await this.#setState();
+ return altText;
+ }
+ finish() {
+ if (!this.#altTextButton) {
+ return;
+ }
+ this.#altTextButton.focus({
+ focusVisible: this.#altTextWasFromKeyBoard
+ });
+ this.#altTextWasFromKeyBoard = false;
+ }
+ isEmpty() {
+ return !this.#altText && !this.#altTextDecorative;
+ }
+ get data() {
+ return {
+ altText: this.#altText,
+ decorative: this.#altTextDecorative
+ };
+ }
+ set data({
+ altText,
+ decorative
+ }) {
+ if (this.#altText === altText && this.#altTextDecorative === decorative) {
+ return;
+ }
+ this.#altText = altText;
+ this.#altTextDecorative = decorative;
+ this.#setState();
+ }
+ toggle(enabled = false) {
+ if (!this.#altTextButton) {
+ return;
+ }
+ if (!enabled && this.#altTextTooltipTimeout) {
+ clearTimeout(this.#altTextTooltipTimeout);
+ this.#altTextTooltipTimeout = null;
+ }
+ this.#altTextButton.disabled = !enabled;
+ }
+ destroy() {
+ this.#altTextButton?.remove();
+ this.#altTextButton = null;
+ this.#altTextTooltip = null;
+ }
+ async #setState() {
+ const button = this.#altTextButton;
+ if (!button) {
+ return;
+ }
+ if (!this.#altText && !this.#altTextDecorative) {
+ button.classList.remove("done");
+ this.#altTextTooltip?.remove();
+ return;
+ }
+ button.classList.add("done");
+ AltText._l10nPromise.get("pdfjs-editor-alt-text-edit-button-label").then(msg => {
+ button.setAttribute("aria-label", msg);
+ });
+ let tooltip = this.#altTextTooltip;
+ if (!tooltip) {
+ this.#altTextTooltip = tooltip = document.createElement("span");
+ tooltip.className = "tooltip";
+ tooltip.setAttribute("role", "tooltip");
+ const id = tooltip.id = `alt-text-tooltip-${this.#editor.id}`;
+ button.setAttribute("aria-describedby", id);
+ const DELAY_TO_SHOW_TOOLTIP = 100;
+ button.addEventListener("mouseenter", () => {
+ this.#altTextTooltipTimeout = setTimeout(() => {
+ this.#altTextTooltipTimeout = null;
+ this.#altTextTooltip.classList.add("show");
+ this.#editor._reportTelemetry({
+ action: "alt_text_tooltip"
+ });
+ }, DELAY_TO_SHOW_TOOLTIP);
+ });
+ button.addEventListener("mouseleave", () => {
+ if (this.#altTextTooltipTimeout) {
+ clearTimeout(this.#altTextTooltipTimeout);
+ this.#altTextTooltipTimeout = null;
+ }
+ this.#altTextTooltip?.classList.remove("show");
+ });
+ }
+ tooltip.innerText = this.#altTextDecorative ? await AltText._l10nPromise.get("pdfjs-editor-alt-text-decorative-tooltip") : this.#altText;
+ if (!tooltip.parentNode) {
+ button.append(tooltip);
+ }
+ const element = this.#editor.getImageForAltText();
+ element?.setAttribute("aria-describedby", tooltip.id);
+ }
+}
+
+;// CONCATENATED MODULE: ./src/display/editor/toolbar.js
+
+class EditorToolbar {
+ #toolbar = null;
+ #colorPicker = null;
+ #editor;
+ #buttons = null;
+ constructor(editor) {
+ this.#editor = editor;
+ }
+ render() {
+ const editToolbar = this.#toolbar = document.createElement("div");
+ editToolbar.className = "editToolbar";
+ editToolbar.addEventListener("contextmenu", noContextMenu);
+ editToolbar.addEventListener("pointerdown", EditorToolbar.#pointerDown);
+ const buttons = this.#buttons = document.createElement("div");
+ buttons.className = "buttons";
+ editToolbar.append(buttons);
+ const position = this.#editor.toolbarPosition;
+ if (position) {
+ const {
+ style
+ } = editToolbar;
+ const x = this.#editor._uiManager.direction === "ltr" ? 1 - position[0] : position[0];
+ style.insetInlineEnd = `${100 * x}%`;
+ style.top = `calc(${100 * position[1]}% + var(--editor-toolbar-vert-offset))`;
+ }
+ this.#addDeleteButton();
+ return editToolbar;
+ }
+ static #pointerDown(e) {
+ e.stopPropagation();
+ }
+ #focusIn(e) {
+ this.#editor._focusEventsAllowed = false;
+ e.preventDefault();
+ e.stopPropagation();
+ }
+ #focusOut(e) {
+ this.#editor._focusEventsAllowed = true;
+ e.preventDefault();
+ e.stopPropagation();
+ }
+ #addListenersToElement(element) {
+ element.addEventListener("focusin", this.#focusIn.bind(this), {
+ capture: true
+ });
+ element.addEventListener("focusout", this.#focusOut.bind(this), {
+ capture: true
+ });
+ element.addEventListener("contextmenu", noContextMenu);
+ }
+ hide() {
+ this.#toolbar.classList.add("hidden");
+ this.#colorPicker?.hideDropdown();
+ }
+ show() {
+ this.#toolbar.classList.remove("hidden");
+ }
+ #addDeleteButton() {
+ const button = document.createElement("button");
+ button.className = "delete";
+ button.tabIndex = 0;
+ button.setAttribute("data-l10n-id", `pdfjs-editor-remove-${this.#editor.editorType}-button`);
+ this.#addListenersToElement(button);
+ button.addEventListener("click", e => {
+ this.#editor._uiManager.delete();
+ });
+ this.#buttons.append(button);
+ }
+ get #divider() {
+ const divider = document.createElement("div");
+ divider.className = "divider";
+ return divider;
+ }
+ addAltTextButton(button) {
+ this.#addListenersToElement(button);
+ this.#buttons.prepend(button, this.#divider);
+ }
+ addColorPicker(colorPicker) {
+ this.#colorPicker = colorPicker;
+ const button = colorPicker.renderButton();
+ this.#addListenersToElement(button);
+ this.#buttons.prepend(button, this.#divider);
+ }
+ remove() {
+ this.#toolbar.remove();
+ this.#colorPicker?.destroy();
+ this.#colorPicker = null;
+ }
+}
+
+;// CONCATENATED MODULE: ./src/display/editor/editor.js
+
+
+
+
+
+class AnnotationEditor {
+ #allResizerDivs = null;
+ #altText = null;
+ #keepAspectRatio = false;
+ #resizersDiv = null;
+ #savedDimensions = null;
+ #boundFocusin = this.focusin.bind(this);
+ #boundFocusout = this.focusout.bind(this);
+ #editToolbar = null;
+ #focusedResizerName = "";
+ #hasBeenClicked = false;
+ #isEditing = false;
+ #isInEditMode = false;
+ #isResizerEnabledForKeyboard = false;
+ #moveInDOMTimeout = null;
+ #prevDragX = 0;
+ #prevDragY = 0;
+ #telemetryTimeouts = null;
+ _initialOptions = Object.create(null);
+ _uiManager = null;
+ _focusEventsAllowed = true;
+ _l10nPromise = null;
+ #isDraggable = false;
+ #zIndex = AnnotationEditor._zIndex++;
+ static _borderLineWidth = -1;
+ static _colorManager = new ColorManager();
+ static _zIndex = 1;
+ static _telemetryTimeout = 1000;
+ static get _resizerKeyboardManager() {
+ const resize = AnnotationEditor.prototype._resizeWithKeyboard;
+ const small = AnnotationEditorUIManager.TRANSLATE_SMALL;
+ const big = AnnotationEditorUIManager.TRANSLATE_BIG;
+ return shadow(this, "_resizerKeyboardManager", new KeyboardManager([[["ArrowLeft", "mac+ArrowLeft"], resize, {
+ args: [-small, 0]
+ }], [["ctrl+ArrowLeft", "mac+shift+ArrowLeft"], resize, {
+ args: [-big, 0]
+ }], [["ArrowRight", "mac+ArrowRight"], resize, {
+ args: [small, 0]
+ }], [["ctrl+ArrowRight", "mac+shift+ArrowRight"], resize, {
+ args: [big, 0]
+ }], [["ArrowUp", "mac+ArrowUp"], resize, {
+ args: [0, -small]
+ }], [["ctrl+ArrowUp", "mac+shift+ArrowUp"], resize, {
+ args: [0, -big]
+ }], [["ArrowDown", "mac+ArrowDown"], resize, {
+ args: [0, small]
+ }], [["ctrl+ArrowDown", "mac+shift+ArrowDown"], resize, {
+ args: [0, big]
+ }], [["Escape", "mac+Escape"], AnnotationEditor.prototype._stopResizingWithKeyboard]]));
+ }
+ constructor(parameters) {
+ if (this.constructor === AnnotationEditor) {
+ unreachable("Cannot initialize AnnotationEditor.");
+ }
+ this.parent = parameters.parent;
+ this.id = parameters.id;
+ this.width = this.height = null;
+ this.pageIndex = parameters.parent.pageIndex;
+ this.name = parameters.name;
+ this.div = null;
+ this._uiManager = parameters.uiManager;
+ this.annotationElementId = null;
+ this._willKeepAspectRatio = false;
+ this._initialOptions.isCentered = parameters.isCentered;
+ this._structTreeParentId = null;
+ const {
+ rotation,
+ rawDims: {
+ pageWidth,
+ pageHeight,
+ pageX,
+ pageY
+ }
+ } = this.parent.viewport;
+ this.rotation = rotation;
+ this.pageRotation = (360 + rotation - this._uiManager.viewParameters.rotation) % 360;
+ this.pageDimensions = [pageWidth, pageHeight];
+ this.pageTranslation = [pageX, pageY];
+ const [width, height] = this.parentDimensions;
+ this.x = parameters.x / width;
+ this.y = parameters.y / height;
+ this.isAttachedToDOM = false;
+ this.deleted = false;
+ }
+ get editorType() {
+ return Object.getPrototypeOf(this).constructor._type;
+ }
+ static get _defaultLineColor() {
+ return shadow(this, "_defaultLineColor", this._colorManager.getHexCode("CanvasText"));
+ }
+ static deleteAnnotationElement(editor) {
+ const fakeEditor = new FakeEditor({
+ id: editor.parent.getNextId(),
+ parent: editor.parent,
+ uiManager: editor._uiManager
+ });
+ fakeEditor.annotationElementId = editor.annotationElementId;
+ fakeEditor.deleted = true;
+ fakeEditor._uiManager.addToAnnotationStorage(fakeEditor);
+ }
+ static initialize(l10n, _uiManager, options) {
+ AnnotationEditor._l10nPromise ||= new Map(["pdfjs-editor-alt-text-button-label", "pdfjs-editor-alt-text-edit-button-label", "pdfjs-editor-alt-text-decorative-tooltip", "pdfjs-editor-resizer-label-topLeft", "pdfjs-editor-resizer-label-topMiddle", "pdfjs-editor-resizer-label-topRight", "pdfjs-editor-resizer-label-middleRight", "pdfjs-editor-resizer-label-bottomRight", "pdfjs-editor-resizer-label-bottomMiddle", "pdfjs-editor-resizer-label-bottomLeft", "pdfjs-editor-resizer-label-middleLeft"].map(str => [str, l10n.get(str.replaceAll(/([A-Z])/g, c => `-${c.toLowerCase()}`))]));
+ if (options?.strings) {
+ for (const str of options.strings) {
+ AnnotationEditor._l10nPromise.set(str, l10n.get(str));
+ }
+ }
+ if (AnnotationEditor._borderLineWidth !== -1) {
+ return;
+ }
+ const style = getComputedStyle(document.documentElement);
+ AnnotationEditor._borderLineWidth = parseFloat(style.getPropertyValue("--outline-width")) || 0;
+ }
+ static updateDefaultParams(_type, _value) {}
+ static get defaultPropertiesToUpdate() {
+ return [];
+ }
+ static isHandlingMimeForPasting(mime) {
+ return false;
+ }
+ static paste(item, parent) {
+ unreachable("Not implemented");
+ }
+ get propertiesToUpdate() {
+ return [];
+ }
+ get _isDraggable() {
+ return this.#isDraggable;
+ }
+ set _isDraggable(value) {
+ this.#isDraggable = value;
+ this.div?.classList.toggle("draggable", value);
+ }
+ get isEnterHandled() {
+ return true;
+ }
+ center() {
+ const [pageWidth, pageHeight] = this.pageDimensions;
+ switch (this.parentRotation) {
+ case 90:
+ this.x -= this.height * pageHeight / (pageWidth * 2);
+ this.y += this.width * pageWidth / (pageHeight * 2);
+ break;
+ case 180:
+ this.x += this.width / 2;
+ this.y += this.height / 2;
+ break;
+ case 270:
+ this.x += this.height * pageHeight / (pageWidth * 2);
+ this.y -= this.width * pageWidth / (pageHeight * 2);
+ break;
+ default:
+ this.x -= this.width / 2;
+ this.y -= this.height / 2;
+ break;
+ }
+ this.fixAndSetPosition();
+ }
+ addCommands(params) {
+ this._uiManager.addCommands(params);
+ }
+ get currentLayer() {
+ return this._uiManager.currentLayer;
+ }
+ setInBackground() {
+ this.div.style.zIndex = 0;
+ }
+ setInForeground() {
+ this.div.style.zIndex = this.#zIndex;
+ }
+ setParent(parent) {
+ if (parent !== null) {
+ this.pageIndex = parent.pageIndex;
+ this.pageDimensions = parent.pageDimensions;
+ } else {
+ this.#stopResizing();
+ }
+ this.parent = parent;
+ }
+ focusin(event) {
+ if (!this._focusEventsAllowed) {
+ return;
+ }
+ if (!this.#hasBeenClicked) {
+ this.parent.setSelected(this);
+ } else {
+ this.#hasBeenClicked = false;
+ }
+ }
+ focusout(event) {
+ if (!this._focusEventsAllowed) {
+ return;
+ }
+ if (!this.isAttachedToDOM) {
+ return;
+ }
+ const target = event.relatedTarget;
+ if (target?.closest(`#${this.id}`)) {
+ return;
+ }
+ event.preventDefault();
+ if (!this.parent?.isMultipleSelection) {
+ this.commitOrRemove();
+ }
+ }
+ commitOrRemove() {
+ if (this.isEmpty()) {
+ this.remove();
+ } else {
+ this.commit();
+ }
+ }
+ commit() {
+ this.addToAnnotationStorage();
+ }
+ addToAnnotationStorage() {
+ this._uiManager.addToAnnotationStorage(this);
+ }
+ setAt(x, y, tx, ty) {
+ const [width, height] = this.parentDimensions;
+ [tx, ty] = this.screenToPageTranslation(tx, ty);
+ this.x = (x + tx) / width;
+ this.y = (y + ty) / height;
+ this.fixAndSetPosition();
+ }
+ #translate([width, height], x, y) {
+ [x, y] = this.screenToPageTranslation(x, y);
+ this.x += x / width;
+ this.y += y / height;
+ this.fixAndSetPosition();
+ }
+ translate(x, y) {
+ this.#translate(this.parentDimensions, x, y);
+ }
+ translateInPage(x, y) {
+ this.#translate(this.pageDimensions, x, y);
+ this.div.scrollIntoView({
+ block: "nearest"
+ });
+ }
+ drag(tx, ty) {
+ const [parentWidth, parentHeight] = this.parentDimensions;
+ this.x += tx / parentWidth;
+ this.y += ty / parentHeight;
+ if (this.parent && (this.x < 0 || this.x > 1 || this.y < 0 || this.y > 1)) {
+ const {
+ x,
+ y
+ } = this.div.getBoundingClientRect();
+ if (this.parent.findNewParent(this, x, y)) {
+ this.x -= Math.floor(this.x);
+ this.y -= Math.floor(this.y);
+ }
+ }
+ let {
+ x,
+ y
+ } = this;
+ const [bx, by] = this.getBaseTranslation();
+ x += bx;
+ y += by;
+ this.div.style.left = `${(100 * x).toFixed(2)}%`;
+ this.div.style.top = `${(100 * y).toFixed(2)}%`;
+ this.div.scrollIntoView({
+ block: "nearest"
+ });
+ }
+ getBaseTranslation() {
+ const [parentWidth, parentHeight] = this.parentDimensions;
+ const {
+ _borderLineWidth
+ } = AnnotationEditor;
+ const x = _borderLineWidth / parentWidth;
+ const y = _borderLineWidth / parentHeight;
+ switch (this.rotation) {
+ case 90:
+ return [-x, y];
+ case 180:
+ return [x, y];
+ case 270:
+ return [x, -y];
+ default:
+ return [-x, -y];
+ }
+ }
+ fixAndSetPosition(rotation = this.rotation) {
+ const [pageWidth, pageHeight] = this.pageDimensions;
+ let {
+ x,
+ y,
+ width,
+ height
+ } = this;
+ width *= pageWidth;
+ height *= pageHeight;
+ x *= pageWidth;
+ y *= pageHeight;
+ switch (rotation) {
+ case 0:
+ x = Math.max(0, Math.min(pageWidth - width, x));
+ y = Math.max(0, Math.min(pageHeight - height, y));
+ break;
+ case 90:
+ x = Math.max(0, Math.min(pageWidth - height, x));
+ y = Math.min(pageHeight, Math.max(width, y));
+ break;
+ case 180:
+ x = Math.min(pageWidth, Math.max(width, x));
+ y = Math.min(pageHeight, Math.max(height, y));
+ break;
+ case 270:
+ x = Math.min(pageWidth, Math.max(height, x));
+ y = Math.max(0, Math.min(pageHeight - width, y));
+ break;
+ }
+ this.x = x /= pageWidth;
+ this.y = y /= pageHeight;
+ const [bx, by] = this.getBaseTranslation();
+ x += bx;
+ y += by;
+ const {
+ style
+ } = this.div;
+ style.left = `${(100 * x).toFixed(2)}%`;
+ style.top = `${(100 * y).toFixed(2)}%`;
+ this.moveInDOM();
+ }
+ static #rotatePoint(x, y, angle) {
+ switch (angle) {
+ case 90:
+ return [y, -x];
+ case 180:
+ return [-x, -y];
+ case 270:
+ return [-y, x];
+ default:
+ return [x, y];
+ }
+ }
+ screenToPageTranslation(x, y) {
+ return AnnotationEditor.#rotatePoint(x, y, this.parentRotation);
+ }
+ pageTranslationToScreen(x, y) {
+ return AnnotationEditor.#rotatePoint(x, y, 360 - this.parentRotation);
+ }
+ #getRotationMatrix(rotation) {
+ switch (rotation) {
+ case 90:
+ {
+ const [pageWidth, pageHeight] = this.pageDimensions;
+ return [0, -pageWidth / pageHeight, pageHeight / pageWidth, 0];
+ }
+ case 180:
+ return [-1, 0, 0, -1];
+ case 270:
+ {
+ const [pageWidth, pageHeight] = this.pageDimensions;
+ return [0, pageWidth / pageHeight, -pageHeight / pageWidth, 0];
+ }
+ default:
+ return [1, 0, 0, 1];
+ }
+ }
+ get parentScale() {
+ return this._uiManager.viewParameters.realScale;
+ }
+ get parentRotation() {
+ return (this._uiManager.viewParameters.rotation + this.pageRotation) % 360;
+ }
+ get parentDimensions() {
+ const {
+ parentScale,
+ pageDimensions: [pageWidth, pageHeight]
+ } = this;
+ const scaledWidth = pageWidth * parentScale;
+ const scaledHeight = pageHeight * parentScale;
+ return util_FeatureTest.isCSSRoundSupported ? [Math.round(scaledWidth), Math.round(scaledHeight)] : [scaledWidth, scaledHeight];
+ }
+ setDims(width, height) {
+ const [parentWidth, parentHeight] = this.parentDimensions;
+ this.div.style.width = `${(100 * width / parentWidth).toFixed(2)}%`;
+ if (!this.#keepAspectRatio) {
+ this.div.style.height = `${(100 * height / parentHeight).toFixed(2)}%`;
+ }
+ }
+ fixDims() {
+ const {
+ style
+ } = this.div;
+ const {
+ height,
+ width
+ } = style;
+ const widthPercent = width.endsWith("%");
+ const heightPercent = !this.#keepAspectRatio && height.endsWith("%");
+ if (widthPercent && heightPercent) {
+ return;
+ }
+ const [parentWidth, parentHeight] = this.parentDimensions;
+ if (!widthPercent) {
+ style.width = `${(100 * parseFloat(width) / parentWidth).toFixed(2)}%`;
+ }
+ if (!this.#keepAspectRatio && !heightPercent) {
+ style.height = `${(100 * parseFloat(height) / parentHeight).toFixed(2)}%`;
+ }
+ }
+ getInitialTranslation() {
+ return [0, 0];
+ }
+ #createResizers() {
+ if (this.#resizersDiv) {
+ return;
+ }
+ this.#resizersDiv = document.createElement("div");
+ this.#resizersDiv.classList.add("resizers");
+ const classes = this._willKeepAspectRatio ? ["topLeft", "topRight", "bottomRight", "bottomLeft"] : ["topLeft", "topMiddle", "topRight", "middleRight", "bottomRight", "bottomMiddle", "bottomLeft", "middleLeft"];
+ for (const name of classes) {
+ const div = document.createElement("div");
+ this.#resizersDiv.append(div);
+ div.classList.add("resizer", name);
+ div.setAttribute("data-resizer-name", name);
+ div.addEventListener("pointerdown", this.#resizerPointerdown.bind(this, name));
+ div.addEventListener("contextmenu", noContextMenu);
+ div.tabIndex = -1;
+ }
+ this.div.prepend(this.#resizersDiv);
+ }
+ #resizerPointerdown(name, event) {
+ event.preventDefault();
+ const {
+ isMac
+ } = util_FeatureTest.platform;
+ if (event.button !== 0 || event.ctrlKey && isMac) {
+ return;
+ }
+ this.#altText?.toggle(false);
+ const boundResizerPointermove = this.#resizerPointermove.bind(this, name);
+ const savedDraggable = this._isDraggable;
+ this._isDraggable = false;
+ const pointerMoveOptions = {
+ passive: true,
+ capture: true
+ };
+ this.parent.togglePointerEvents(false);
+ window.addEventListener("pointermove", boundResizerPointermove, pointerMoveOptions);
+ const savedX = this.x;
+ const savedY = this.y;
+ const savedWidth = this.width;
+ const savedHeight = this.height;
+ const savedParentCursor = this.parent.div.style.cursor;
+ const savedCursor = this.div.style.cursor;
+ this.div.style.cursor = this.parent.div.style.cursor = window.getComputedStyle(event.target).cursor;
+ const pointerUpCallback = () => {
+ this.parent.togglePointerEvents(true);
+ this.#altText?.toggle(true);
+ this._isDraggable = savedDraggable;
+ window.removeEventListener("pointerup", pointerUpCallback);
+ window.removeEventListener("blur", pointerUpCallback);
+ window.removeEventListener("pointermove", boundResizerPointermove, pointerMoveOptions);
+ this.parent.div.style.cursor = savedParentCursor;
+ this.div.style.cursor = savedCursor;
+ this.#addResizeToUndoStack(savedX, savedY, savedWidth, savedHeight);
+ };
+ window.addEventListener("pointerup", pointerUpCallback);
+ window.addEventListener("blur", pointerUpCallback);
+ }
+ #addResizeToUndoStack(savedX, savedY, savedWidth, savedHeight) {
+ const newX = this.x;
+ const newY = this.y;
+ const newWidth = this.width;
+ const newHeight = this.height;
+ if (newX === savedX && newY === savedY && newWidth === savedWidth && newHeight === savedHeight) {
+ return;
+ }
+ this.addCommands({
+ cmd: () => {
+ this.width = newWidth;
+ this.height = newHeight;
+ this.x = newX;
+ this.y = newY;
+ const [parentWidth, parentHeight] = this.parentDimensions;
+ this.setDims(parentWidth * newWidth, parentHeight * newHeight);
+ this.fixAndSetPosition();
+ },
+ undo: () => {
+ this.width = savedWidth;
+ this.height = savedHeight;
+ this.x = savedX;
+ this.y = savedY;
+ const [parentWidth, parentHeight] = this.parentDimensions;
+ this.setDims(parentWidth * savedWidth, parentHeight * savedHeight);
+ this.fixAndSetPosition();
+ },
+ mustExec: true
+ });
+ }
+ #resizerPointermove(name, event) {
+ const [parentWidth, parentHeight] = this.parentDimensions;
+ const savedX = this.x;
+ const savedY = this.y;
+ const savedWidth = this.width;
+ const savedHeight = this.height;
+ const minWidth = AnnotationEditor.MIN_SIZE / parentWidth;
+ const minHeight = AnnotationEditor.MIN_SIZE / parentHeight;
+ const round = x => Math.round(x * 10000) / 10000;
+ const rotationMatrix = this.#getRotationMatrix(this.rotation);
+ const transf = (x, y) => [rotationMatrix[0] * x + rotationMatrix[2] * y, rotationMatrix[1] * x + rotationMatrix[3] * y];
+ const invRotationMatrix = this.#getRotationMatrix(360 - this.rotation);
+ const invTransf = (x, y) => [invRotationMatrix[0] * x + invRotationMatrix[2] * y, invRotationMatrix[1] * x + invRotationMatrix[3] * y];
+ let getPoint;
+ let getOpposite;
+ let isDiagonal = false;
+ let isHorizontal = false;
+ switch (name) {
+ case "topLeft":
+ isDiagonal = true;
+ getPoint = (w, h) => [0, 0];
+ getOpposite = (w, h) => [w, h];
+ break;
+ case "topMiddle":
+ getPoint = (w, h) => [w / 2, 0];
+ getOpposite = (w, h) => [w / 2, h];
+ break;
+ case "topRight":
+ isDiagonal = true;
+ getPoint = (w, h) => [w, 0];
+ getOpposite = (w, h) => [0, h];
+ break;
+ case "middleRight":
+ isHorizontal = true;
+ getPoint = (w, h) => [w, h / 2];
+ getOpposite = (w, h) => [0, h / 2];
+ break;
+ case "bottomRight":
+ isDiagonal = true;
+ getPoint = (w, h) => [w, h];
+ getOpposite = (w, h) => [0, 0];
+ break;
+ case "bottomMiddle":
+ getPoint = (w, h) => [w / 2, h];
+ getOpposite = (w, h) => [w / 2, 0];
+ break;
+ case "bottomLeft":
+ isDiagonal = true;
+ getPoint = (w, h) => [0, h];
+ getOpposite = (w, h) => [w, 0];
+ break;
+ case "middleLeft":
+ isHorizontal = true;
+ getPoint = (w, h) => [0, h / 2];
+ getOpposite = (w, h) => [w, h / 2];
+ break;
+ }
+ const point = getPoint(savedWidth, savedHeight);
+ const oppositePoint = getOpposite(savedWidth, savedHeight);
+ let transfOppositePoint = transf(...oppositePoint);
+ const oppositeX = round(savedX + transfOppositePoint[0]);
+ const oppositeY = round(savedY + transfOppositePoint[1]);
+ let ratioX = 1;
+ let ratioY = 1;
+ let [deltaX, deltaY] = this.screenToPageTranslation(event.movementX, event.movementY);
+ [deltaX, deltaY] = invTransf(deltaX / parentWidth, deltaY / parentHeight);
+ if (isDiagonal) {
+ const oldDiag = Math.hypot(savedWidth, savedHeight);
+ ratioX = ratioY = Math.max(Math.min(Math.hypot(oppositePoint[0] - point[0] - deltaX, oppositePoint[1] - point[1] - deltaY) / oldDiag, 1 / savedWidth, 1 / savedHeight), minWidth / savedWidth, minHeight / savedHeight);
+ } else if (isHorizontal) {
+ ratioX = Math.max(minWidth, Math.min(1, Math.abs(oppositePoint[0] - point[0] - deltaX))) / savedWidth;
+ } else {
+ ratioY = Math.max(minHeight, Math.min(1, Math.abs(oppositePoint[1] - point[1] - deltaY))) / savedHeight;
+ }
+ const newWidth = round(savedWidth * ratioX);
+ const newHeight = round(savedHeight * ratioY);
+ transfOppositePoint = transf(...getOpposite(newWidth, newHeight));
+ const newX = oppositeX - transfOppositePoint[0];
+ const newY = oppositeY - transfOppositePoint[1];
+ this.width = newWidth;
+ this.height = newHeight;
+ this.x = newX;
+ this.y = newY;
+ this.setDims(parentWidth * newWidth, parentHeight * newHeight);
+ this.fixAndSetPosition();
+ }
+ altTextFinish() {
+ this.#altText?.finish();
+ }
+ async addEditToolbar() {
+ if (this.#editToolbar || this.#isInEditMode) {
+ return this.#editToolbar;
+ }
+ this.#editToolbar = new EditorToolbar(this);
+ this.div.append(this.#editToolbar.render());
+ if (this.#altText) {
+ this.#editToolbar.addAltTextButton(await this.#altText.render());
+ }
+ return this.#editToolbar;
+ }
+ removeEditToolbar() {
+ if (!this.#editToolbar) {
+ return;
+ }
+ this.#editToolbar.remove();
+ this.#editToolbar = null;
+ this.#altText?.destroy();
+ }
+ getClientDimensions() {
+ return this.div.getBoundingClientRect();
+ }
+ async addAltTextButton() {
+ if (this.#altText) {
+ return;
+ }
+ AltText.initialize(AnnotationEditor._l10nPromise);
+ this.#altText = new AltText(this);
+ await this.addEditToolbar();
+ }
+ get altTextData() {
+ return this.#altText?.data;
+ }
+ set altTextData(data) {
+ if (!this.#altText) {
+ return;
+ }
+ this.#altText.data = data;
+ }
+ hasAltText() {
+ return !this.#altText?.isEmpty();
+ }
+ render() {
+ this.div = document.createElement("div");
+ this.div.setAttribute("data-editor-rotation", (360 - this.rotation) % 360);
+ this.div.className = this.name;
+ this.div.setAttribute("id", this.id);
+ this.div.setAttribute("tabIndex", 0);
+ this.setInForeground();
+ this.div.addEventListener("focusin", this.#boundFocusin);
+ this.div.addEventListener("focusout", this.#boundFocusout);
+ const [parentWidth, parentHeight] = this.parentDimensions;
+ if (this.parentRotation % 180 !== 0) {
+ this.div.style.maxWidth = `${(100 * parentHeight / parentWidth).toFixed(2)}%`;
+ this.div.style.maxHeight = `${(100 * parentWidth / parentHeight).toFixed(2)}%`;
+ }
+ const [tx, ty] = this.getInitialTranslation();
+ this.translate(tx, ty);
+ bindEvents(this, this.div, ["pointerdown"]);
+ return this.div;
+ }
+ pointerdown(event) {
+ const {
+ isMac
+ } = util_FeatureTest.platform;
+ if (event.button !== 0 || event.ctrlKey && isMac) {
+ event.preventDefault();
+ return;
+ }
+ this.#hasBeenClicked = true;
+ if (this._isDraggable) {
+ this.#setUpDragSession(event);
+ return;
+ }
+ this.#selectOnPointerEvent(event);
+ }
+ #selectOnPointerEvent(event) {
+ const {
+ isMac
+ } = util_FeatureTest.platform;
+ if (event.ctrlKey && !isMac || event.shiftKey || event.metaKey && isMac) {
+ this.parent.toggleSelected(this);
+ } else {
+ this.parent.setSelected(this);
+ }
+ }
+ #setUpDragSession(event) {
+ const isSelected = this._uiManager.isSelected(this);
+ this._uiManager.setUpDragSession();
+ let pointerMoveOptions, pointerMoveCallback;
+ if (isSelected) {
+ this.div.classList.add("moving");
+ pointerMoveOptions = {
+ passive: true,
+ capture: true
+ };
+ this.#prevDragX = event.clientX;
+ this.#prevDragY = event.clientY;
+ pointerMoveCallback = e => {
+ const {
+ clientX: x,
+ clientY: y
+ } = e;
+ const [tx, ty] = this.screenToPageTranslation(x - this.#prevDragX, y - this.#prevDragY);
+ this.#prevDragX = x;
+ this.#prevDragY = y;
+ this._uiManager.dragSelectedEditors(tx, ty);
+ };
+ window.addEventListener("pointermove", pointerMoveCallback, pointerMoveOptions);
+ }
+ const pointerUpCallback = () => {
+ window.removeEventListener("pointerup", pointerUpCallback);
+ window.removeEventListener("blur", pointerUpCallback);
+ if (isSelected) {
+ this.div.classList.remove("moving");
+ window.removeEventListener("pointermove", pointerMoveCallback, pointerMoveOptions);
+ }
+ this.#hasBeenClicked = false;
+ if (!this._uiManager.endDragSession()) {
+ this.#selectOnPointerEvent(event);
+ }
+ };
+ window.addEventListener("pointerup", pointerUpCallback);
+ window.addEventListener("blur", pointerUpCallback);
+ }
+ moveInDOM() {
+ if (this.#moveInDOMTimeout) {
+ clearTimeout(this.#moveInDOMTimeout);
+ }
+ this.#moveInDOMTimeout = setTimeout(() => {
+ this.#moveInDOMTimeout = null;
+ this.parent?.moveEditorInDOM(this);
+ }, 0);
+ }
+ _setParentAndPosition(parent, x, y) {
+ parent.changeParent(this);
+ this.x = x;
+ this.y = y;
+ this.fixAndSetPosition();
+ }
+ getRect(tx, ty, rotation = this.rotation) {
+ const scale = this.parentScale;
+ const [pageWidth, pageHeight] = this.pageDimensions;
+ const [pageX, pageY] = this.pageTranslation;
+ const shiftX = tx / scale;
+ const shiftY = ty / scale;
+ const x = this.x * pageWidth;
+ const y = this.y * pageHeight;
+ const width = this.width * pageWidth;
+ const height = this.height * pageHeight;
+ switch (rotation) {
+ case 0:
+ return [x + shiftX + pageX, pageHeight - y - shiftY - height + pageY, x + shiftX + width + pageX, pageHeight - y - shiftY + pageY];
+ case 90:
+ return [x + shiftY + pageX, pageHeight - y + shiftX + pageY, x + shiftY + height + pageX, pageHeight - y + shiftX + width + pageY];
+ case 180:
+ return [x - shiftX - width + pageX, pageHeight - y + shiftY + pageY, x - shiftX + pageX, pageHeight - y + shiftY + height + pageY];
+ case 270:
+ return [x - shiftY - height + pageX, pageHeight - y - shiftX - width + pageY, x - shiftY + pageX, pageHeight - y - shiftX + pageY];
+ default:
+ throw new Error("Invalid rotation");
+ }
+ }
+ getRectInCurrentCoords(rect, pageHeight) {
+ const [x1, y1, x2, y2] = rect;
+ const width = x2 - x1;
+ const height = y2 - y1;
+ switch (this.rotation) {
+ case 0:
+ return [x1, pageHeight - y2, width, height];
+ case 90:
+ return [x1, pageHeight - y1, height, width];
+ case 180:
+ return [x2, pageHeight - y1, width, height];
+ case 270:
+ return [x2, pageHeight - y2, height, width];
+ default:
+ throw new Error("Invalid rotation");
+ }
+ }
+ onceAdded() {}
+ isEmpty() {
+ return false;
+ }
+ enableEditMode() {
+ this.#isInEditMode = true;
+ }
+ disableEditMode() {
+ this.#isInEditMode = false;
+ }
+ isInEditMode() {
+ return this.#isInEditMode;
+ }
+ shouldGetKeyboardEvents() {
+ return this.#isResizerEnabledForKeyboard;
+ }
+ needsToBeRebuilt() {
+ return this.div && !this.isAttachedToDOM;
+ }
+ rebuild() {
+ this.div?.addEventListener("focusin", this.#boundFocusin);
+ this.div?.addEventListener("focusout", this.#boundFocusout);
+ }
+ rotate(_angle) {}
+ serialize(isForCopying = false, context = null) {
+ unreachable("An editor must be serializable");
+ }
+ static deserialize(data, parent, uiManager) {
+ const editor = new this.prototype.constructor({
+ parent,
+ id: parent.getNextId(),
+ uiManager
+ });
+ editor.rotation = data.rotation;
+ const [pageWidth, pageHeight] = editor.pageDimensions;
+ const [x, y, width, height] = editor.getRectInCurrentCoords(data.rect, pageHeight);
+ editor.x = x / pageWidth;
+ editor.y = y / pageHeight;
+ editor.width = width / pageWidth;
+ editor.height = height / pageHeight;
+ return editor;
+ }
+ remove() {
+ this.div.removeEventListener("focusin", this.#boundFocusin);
+ this.div.removeEventListener("focusout", this.#boundFocusout);
+ if (!this.isEmpty()) {
+ this.commit();
+ }
+ if (this.parent) {
+ this.parent.remove(this);
+ } else {
+ this._uiManager.removeEditor(this);
+ }
+ if (this.#moveInDOMTimeout) {
+ clearTimeout(this.#moveInDOMTimeout);
+ this.#moveInDOMTimeout = null;
+ }
+ this.#stopResizing();
+ this.removeEditToolbar();
+ if (this.#telemetryTimeouts) {
+ for (const timeout of this.#telemetryTimeouts.values()) {
+ clearTimeout(timeout);
+ }
+ this.#telemetryTimeouts = null;
+ }
+ }
+ get isResizable() {
+ return false;
+ }
+ makeResizable() {
+ if (this.isResizable) {
+ this.#createResizers();
+ this.#resizersDiv.classList.remove("hidden");
+ bindEvents(this, this.div, ["keydown"]);
+ }
+ }
+ get toolbarPosition() {
+ return null;
+ }
+ keydown(event) {
+ if (!this.isResizable || event.target !== this.div || event.key !== "Enter") {
+ return;
+ }
+ this._uiManager.setSelected(this);
+ this.#savedDimensions = {
+ savedX: this.x,
+ savedY: this.y,
+ savedWidth: this.width,
+ savedHeight: this.height
+ };
+ const children = this.#resizersDiv.children;
+ if (!this.#allResizerDivs) {
+ this.#allResizerDivs = Array.from(children);
+ const boundResizerKeydown = this.#resizerKeydown.bind(this);
+ const boundResizerBlur = this.#resizerBlur.bind(this);
+ for (const div of this.#allResizerDivs) {
+ const name = div.getAttribute("data-resizer-name");
+ div.setAttribute("role", "spinbutton");
+ div.addEventListener("keydown", boundResizerKeydown);
+ div.addEventListener("blur", boundResizerBlur);
+ div.addEventListener("focus", this.#resizerFocus.bind(this, name));
+ AnnotationEditor._l10nPromise.get(`pdfjs-editor-resizer-label-${name}`).then(msg => div.setAttribute("aria-label", msg));
+ }
+ }
+ const first = this.#allResizerDivs[0];
+ let firstPosition = 0;
+ for (const div of children) {
+ if (div === first) {
+ break;
+ }
+ firstPosition++;
+ }
+ const nextFirstPosition = (360 - this.rotation + this.parentRotation) % 360 / 90 * (this.#allResizerDivs.length / 4);
+ if (nextFirstPosition !== firstPosition) {
+ if (nextFirstPosition < firstPosition) {
+ for (let i = 0; i < firstPosition - nextFirstPosition; i++) {
+ this.#resizersDiv.append(this.#resizersDiv.firstChild);
+ }
+ } else if (nextFirstPosition > firstPosition) {
+ for (let i = 0; i < nextFirstPosition - firstPosition; i++) {
+ this.#resizersDiv.firstChild.before(this.#resizersDiv.lastChild);
+ }
+ }
+ let i = 0;
+ for (const child of children) {
+ const div = this.#allResizerDivs[i++];
+ const name = div.getAttribute("data-resizer-name");
+ AnnotationEditor._l10nPromise.get(`pdfjs-editor-resizer-label-${name}`).then(msg => child.setAttribute("aria-label", msg));
+ }
+ }
+ this.#setResizerTabIndex(0);
+ this.#isResizerEnabledForKeyboard = true;
+ this.#resizersDiv.firstChild.focus({
+ focusVisible: true
+ });
+ event.preventDefault();
+ event.stopImmediatePropagation();
+ }
+ #resizerKeydown(event) {
+ AnnotationEditor._resizerKeyboardManager.exec(this, event);
+ }
+ #resizerBlur(event) {
+ if (this.#isResizerEnabledForKeyboard && event.relatedTarget?.parentNode !== this.#resizersDiv) {
+ this.#stopResizing();
+ }
+ }
+ #resizerFocus(name) {
+ this.#focusedResizerName = this.#isResizerEnabledForKeyboard ? name : "";
+ }
+ #setResizerTabIndex(value) {
+ if (!this.#allResizerDivs) {
+ return;
+ }
+ for (const div of this.#allResizerDivs) {
+ div.tabIndex = value;
+ }
+ }
+ _resizeWithKeyboard(x, y) {
+ if (!this.#isResizerEnabledForKeyboard) {
+ return;
+ }
+ this.#resizerPointermove(this.#focusedResizerName, {
+ movementX: x,
+ movementY: y
+ });
+ }
+ #stopResizing() {
+ this.#isResizerEnabledForKeyboard = false;
+ this.#setResizerTabIndex(-1);
+ if (this.#savedDimensions) {
+ const {
+ savedX,
+ savedY,
+ savedWidth,
+ savedHeight
+ } = this.#savedDimensions;
+ this.#addResizeToUndoStack(savedX, savedY, savedWidth, savedHeight);
+ this.#savedDimensions = null;
+ }
+ }
+ _stopResizingWithKeyboard() {
+ this.#stopResizing();
+ this.div.focus();
+ }
+ select() {
+ this.makeResizable();
+ this.div?.classList.add("selectedEditor");
+ if (!this.#editToolbar) {
+ this.addEditToolbar().then(() => {
+ if (this.div?.classList.contains("selectedEditor")) {
+ this.#editToolbar?.show();
+ }
+ });
+ return;
+ }
+ this.#editToolbar?.show();
+ }
+ unselect() {
+ this.#resizersDiv?.classList.add("hidden");
+ this.div?.classList.remove("selectedEditor");
+ if (this.div?.contains(document.activeElement)) {
+ this._uiManager.currentLayer.div.focus({
+ preventScroll: true
+ });
+ }
+ this.#editToolbar?.hide();
+ }
+ updateParams(type, value) {}
+ disableEditing() {}
+ enableEditing() {}
+ enterInEditMode() {}
+ getImageForAltText() {
+ return null;
+ }
+ get contentDiv() {
+ return this.div;
+ }
+ get isEditing() {
+ return this.#isEditing;
+ }
+ set isEditing(value) {
+ this.#isEditing = value;
+ if (!this.parent) {
+ return;
+ }
+ if (value) {
+ this.parent.setSelected(this);
+ this.parent.setActiveEditor(this);
+ } else {
+ this.parent.setActiveEditor(null);
+ }
+ }
+ setAspectRatio(width, height) {
+ this.#keepAspectRatio = true;
+ const aspectRatio = width / height;
+ const {
+ style
+ } = this.div;
+ style.aspectRatio = aspectRatio;
+ style.height = "auto";
+ }
+ static get MIN_SIZE() {
+ return 16;
+ }
+ static canCreateNewEmptyEditor() {
+ return true;
+ }
+ get telemetryInitialData() {
+ return {
+ action: "added"
+ };
+ }
+ get telemetryFinalData() {
+ return null;
+ }
+ _reportTelemetry(data, mustWait = false) {
+ if (mustWait) {
+ this.#telemetryTimeouts ||= new Map();
+ const {
+ action
+ } = data;
+ let timeout = this.#telemetryTimeouts.get(action);
+ if (timeout) {
+ clearTimeout(timeout);
+ }
+ timeout = setTimeout(() => {
+ this._reportTelemetry(data);
+ this.#telemetryTimeouts.delete(action);
+ if (this.#telemetryTimeouts.size === 0) {
+ this.#telemetryTimeouts = null;
+ }
+ }, AnnotationEditor._telemetryTimeout);
+ this.#telemetryTimeouts.set(action, timeout);
+ return;
+ }
+ data.type ||= this.editorType;
+ this._uiManager._eventBus.dispatch("reporttelemetry", {
+ source: this,
+ details: {
+ type: "editing",
+ data
+ }
+ });
+ }
+}
+class FakeEditor extends AnnotationEditor {
+ constructor(params) {
+ super(params);
+ this.annotationElementId = params.annotationElementId;
+ this.deleted = true;
+ }
+ serialize() {
+ return {
+ id: this.annotationElementId,
+ deleted: true,
+ pageIndex: this.pageIndex
+ };
+ }
+}
+
+;// CONCATENATED MODULE: ./src/shared/murmurhash3.js
+const SEED = 0xc3d2e1f0;
+const MASK_HIGH = 0xffff0000;
+const MASK_LOW = 0xffff;
+class MurmurHash3_64 {
+ constructor(seed) {
+ this.h1 = seed ? seed & 0xffffffff : SEED;
+ this.h2 = seed ? seed & 0xffffffff : SEED;
+ }
+ update(input) {
+ let data, length;
+ if (typeof input === "string") {
+ data = new Uint8Array(input.length * 2);
+ length = 0;
+ for (let i = 0, ii = input.length; i < ii; i++) {
+ const code = input.charCodeAt(i);
+ if (code <= 0xff) {
+ data[length++] = code;
+ } else {
+ data[length++] = code >>> 8;
+ data[length++] = code & 0xff;
+ }
+ }
+ } else if (ArrayBuffer.isView(input)) {
+ data = input.slice();
+ length = data.byteLength;
+ } else {
+ throw new Error("Invalid data format, must be a string or TypedArray.");
+ }
+ const blockCounts = length >> 2;
+ const tailLength = length - blockCounts * 4;
+ const dataUint32 = new Uint32Array(data.buffer, 0, blockCounts);
+ let k1 = 0,
+ k2 = 0;
+ let h1 = this.h1,
+ h2 = this.h2;
+ const C1 = 0xcc9e2d51,
+ C2 = 0x1b873593;
+ const C1_LOW = C1 & MASK_LOW,
+ C2_LOW = C2 & MASK_LOW;
+ for (let i = 0; i < blockCounts; i++) {
+ if (i & 1) {
+ k1 = dataUint32[i];
+ k1 = k1 * C1 & MASK_HIGH | k1 * C1_LOW & MASK_LOW;
+ k1 = k1 << 15 | k1 >>> 17;
+ k1 = k1 * C2 & MASK_HIGH | k1 * C2_LOW & MASK_LOW;
+ h1 ^= k1;
+ h1 = h1 << 13 | h1 >>> 19;
+ h1 = h1 * 5 + 0xe6546b64;
+ } else {
+ k2 = dataUint32[i];
+ k2 = k2 * C1 & MASK_HIGH | k2 * C1_LOW & MASK_LOW;
+ k2 = k2 << 15 | k2 >>> 17;
+ k2 = k2 * C2 & MASK_HIGH | k2 * C2_LOW & MASK_LOW;
+ h2 ^= k2;
+ h2 = h2 << 13 | h2 >>> 19;
+ h2 = h2 * 5 + 0xe6546b64;
+ }
+ }
+ k1 = 0;
+ switch (tailLength) {
+ case 3:
+ k1 ^= data[blockCounts * 4 + 2] << 16;
+ case 2:
+ k1 ^= data[blockCounts * 4 + 1] << 8;
+ case 1:
+ k1 ^= data[blockCounts * 4];
+ k1 = k1 * C1 & MASK_HIGH | k1 * C1_LOW & MASK_LOW;
+ k1 = k1 << 15 | k1 >>> 17;
+ k1 = k1 * C2 & MASK_HIGH | k1 * C2_LOW & MASK_LOW;
+ if (blockCounts & 1) {
+ h1 ^= k1;
+ } else {
+ h2 ^= k1;
+ }
+ }
+ this.h1 = h1;
+ this.h2 = h2;
+ }
+ hexdigest() {
+ let h1 = this.h1,
+ h2 = this.h2;
+ h1 ^= h2 >>> 1;
+ h1 = h1 * 0xed558ccd & MASK_HIGH | h1 * 0x8ccd & MASK_LOW;
+ h2 = h2 * 0xff51afd7 & MASK_HIGH | ((h2 << 16 | h1 >>> 16) * 0xafd7ed55 & MASK_HIGH) >>> 16;
+ h1 ^= h2 >>> 1;
+ h1 = h1 * 0x1a85ec53 & MASK_HIGH | h1 * 0xec53 & MASK_LOW;
+ h2 = h2 * 0xc4ceb9fe & MASK_HIGH | ((h2 << 16 | h1 >>> 16) * 0xb9fe1a85 & MASK_HIGH) >>> 16;
+ h1 ^= h2 >>> 1;
+ return (h1 >>> 0).toString(16).padStart(8, "0") + (h2 >>> 0).toString(16).padStart(8, "0");
+ }
+}
+
+;// CONCATENATED MODULE: ./src/display/annotation_storage.js
+
+
+
+const SerializableEmpty = Object.freeze({
+ map: null,
+ hash: "",
+ transfer: undefined
+});
+class AnnotationStorage {
+ #modified = false;
+ #storage = new Map();
+ constructor() {
+ this.onSetModified = null;
+ this.onResetModified = null;
+ this.onAnnotationEditor = null;
+ }
+ getValue(key, defaultValue) {
+ const value = this.#storage.get(key);
+ if (value === undefined) {
+ return defaultValue;
+ }
+ return Object.assign(defaultValue, value);
+ }
+ getRawValue(key) {
+ return this.#storage.get(key);
+ }
+ remove(key) {
+ this.#storage.delete(key);
+ if (this.#storage.size === 0) {
+ this.resetModified();
+ }
+ if (typeof this.onAnnotationEditor === "function") {
+ for (const value of this.#storage.values()) {
+ if (value instanceof AnnotationEditor) {
+ return;
+ }
+ }
+ this.onAnnotationEditor(null);
+ }
+ }
+ setValue(key, value) {
+ const obj = this.#storage.get(key);
+ let modified = false;
+ if (obj !== undefined) {
+ for (const [entry, val] of Object.entries(value)) {
+ if (obj[entry] !== val) {
+ modified = true;
+ obj[entry] = val;
+ }
+ }
+ } else {
+ modified = true;
+ this.#storage.set(key, value);
+ }
+ if (modified) {
+ this.#setModified();
+ }
+ if (value instanceof AnnotationEditor && typeof this.onAnnotationEditor === "function") {
+ this.onAnnotationEditor(value.constructor._type);
+ }
+ }
+ has(key) {
+ return this.#storage.has(key);
+ }
+ getAll() {
+ return this.#storage.size > 0 ? objectFromMap(this.#storage) : null;
+ }
+ setAll(obj) {
+ for (const [key, val] of Object.entries(obj)) {
+ this.setValue(key, val);
+ }
+ }
+ get size() {
+ return this.#storage.size;
+ }
+ #setModified() {
+ if (!this.#modified) {
+ this.#modified = true;
+ if (typeof this.onSetModified === "function") {
+ this.onSetModified();
+ }
+ }
+ }
+ resetModified() {
+ if (this.#modified) {
+ this.#modified = false;
+ if (typeof this.onResetModified === "function") {
+ this.onResetModified();
+ }
+ }
+ }
+ get print() {
+ return new PrintAnnotationStorage(this);
+ }
+ get serializable() {
+ if (this.#storage.size === 0) {
+ return SerializableEmpty;
+ }
+ const map = new Map(),
+ hash = new MurmurHash3_64(),
+ transfer = [];
+ const context = Object.create(null);
+ let hasBitmap = false;
+ for (const [key, val] of this.#storage) {
+ const serialized = val instanceof AnnotationEditor ? val.serialize(false, context) : val;
+ if (serialized) {
+ map.set(key, serialized);
+ hash.update(`${key}:${JSON.stringify(serialized)}`);
+ hasBitmap ||= !!serialized.bitmap;
+ }
+ }
+ if (hasBitmap) {
+ for (const value of map.values()) {
+ if (value.bitmap) {
+ transfer.push(value.bitmap);
+ }
+ }
+ }
+ return map.size > 0 ? {
+ map,
+ hash: hash.hexdigest(),
+ transfer
+ } : SerializableEmpty;
+ }
+ get editorStats() {
+ let stats = null;
+ const typeToEditor = new Map();
+ for (const value of this.#storage.values()) {
+ if (!(value instanceof AnnotationEditor)) {
+ continue;
+ }
+ const editorStats = value.telemetryFinalData;
+ if (!editorStats) {
+ continue;
+ }
+ const {
+ type
+ } = editorStats;
+ if (!typeToEditor.has(type)) {
+ typeToEditor.set(type, Object.getPrototypeOf(value).constructor);
+ }
+ stats ||= Object.create(null);
+ const map = stats[type] ||= new Map();
+ for (const [key, val] of Object.entries(editorStats)) {
+ if (key === "type") {
+ continue;
+ }
+ let counters = map.get(key);
+ if (!counters) {
+ counters = new Map();
+ map.set(key, counters);
+ }
+ const count = counters.get(val) ?? 0;
+ counters.set(val, count + 1);
+ }
+ }
+ for (const [type, editor] of typeToEditor) {
+ stats[type] = editor.computeTelemetryFinalData(stats[type]);
+ }
+ return stats;
+ }
+}
+class PrintAnnotationStorage extends AnnotationStorage {
+ #serializable;
+ constructor(parent) {
+ super();
+ const {
+ map,
+ hash,
+ transfer
+ } = parent.serializable;
+ const clone = structuredClone(map, transfer ? {
+ transfer
+ } : null);
+ this.#serializable = {
+ map: clone,
+ hash,
+ transfer
+ };
+ }
+ get print() {
+ unreachable("Should not call PrintAnnotationStorage.print");
+ }
+ get serializable() {
+ return this.#serializable;
+ }
+}
+
+;// CONCATENATED MODULE: ./src/display/font_loader.js
+
+class FontLoader {
+ #systemFonts = new Set();
+ constructor({
+ ownerDocument = globalThis.document,
+ styleElement = null
+ }) {
+ this._document = ownerDocument;
+ this.nativeFontFaces = new Set();
+ this.styleElement = null;
+ }
+ addNativeFontFace(nativeFontFace) {
+ this.nativeFontFaces.add(nativeFontFace);
+ this._document.fonts.add(nativeFontFace);
+ }
+ removeNativeFontFace(nativeFontFace) {
+ this.nativeFontFaces.delete(nativeFontFace);
+ this._document.fonts.delete(nativeFontFace);
+ }
+ insertRule(rule) {
+ if (!this.styleElement) {
+ this.styleElement = this._document.createElement("style");
+ this._document.documentElement.getElementsByTagName("head")[0].append(this.styleElement);
+ }
+ const styleSheet = this.styleElement.sheet;
+ styleSheet.insertRule(rule, styleSheet.cssRules.length);
+ }
+ clear() {
+ for (const nativeFontFace of this.nativeFontFaces) {
+ this._document.fonts.delete(nativeFontFace);
+ }
+ this.nativeFontFaces.clear();
+ this.#systemFonts.clear();
+ if (this.styleElement) {
+ this.styleElement.remove();
+ this.styleElement = null;
+ }
+ }
+ async loadSystemFont({
+ systemFontInfo: info,
+ _inspectFont
+ }) {
+ if (!info || this.#systemFonts.has(info.loadedName)) {
+ return;
+ }
+ assert(!this.disableFontFace, "loadSystemFont shouldn't be called when `disableFontFace` is set.");
+ if (this.isFontLoadingAPISupported) {
+ const {
+ loadedName,
+ src,
+ style
+ } = info;
+ const fontFace = new FontFace(loadedName, src, style);
+ this.addNativeFontFace(fontFace);
+ try {
+ await fontFace.load();
+ this.#systemFonts.add(loadedName);
+ _inspectFont?.(info);
+ } catch {
+ warn(`Cannot load system font: ${info.baseFontName}, installing it could help to improve PDF rendering.`);
+ this.removeNativeFontFace(fontFace);
+ }
+ return;
+ }
+ unreachable("Not implemented: loadSystemFont without the Font Loading API.");
+ }
+ async bind(font) {
+ if (font.attached || font.missingFile && !font.systemFontInfo) {
+ return;
+ }
+ font.attached = true;
+ if (font.systemFontInfo) {
+ await this.loadSystemFont(font);
+ return;
+ }
+ if (this.isFontLoadingAPISupported) {
+ const nativeFontFace = font.createNativeFontFace();
+ if (nativeFontFace) {
+ this.addNativeFontFace(nativeFontFace);
+ try {
+ await nativeFontFace.loaded;
+ } catch (ex) {
+ warn(`Failed to load font '${nativeFontFace.family}': '${ex}'.`);
+ font.disableFontFace = true;
+ throw ex;
+ }
+ }
+ return;
+ }
+ const rule = font.createFontFaceRule();
+ if (rule) {
+ this.insertRule(rule);
+ if (this.isSyncFontLoadingSupported) {
+ return;
+ }
+ throw new Error("Not implemented: async font loading");
+ }
+ }
+ get isFontLoadingAPISupported() {
+ const hasFonts = !!this._document?.fonts;
+ return shadow(this, "isFontLoadingAPISupported", hasFonts);
+ }
+ get isSyncFontLoadingSupported() {
+ return shadow(this, "isSyncFontLoadingSupported", true);
+ }
+ _queueLoadingCallback(callback) {
+ throw new Error("Not implemented: _queueLoadingCallback");
+ }
+ get _loadTestFont() {
+ throw new Error("Not implemented: _loadTestFont");
+ }
+ _prepareFontLoadEvent(font, request) {
+ throw new Error("Not implemented: _prepareFontLoadEvent");
+ }
+}
+class FontFaceObject {
+ constructor(translatedData, {
+ isEvalSupported = true,
+ disableFontFace = false,
+ ignoreErrors = false,
+ inspectFont = null
+ }) {
+ this.compiledGlyphs = Object.create(null);
+ for (const i in translatedData) {
+ this[i] = translatedData[i];
+ }
+ this.isEvalSupported = isEvalSupported !== false;
+ this.disableFontFace = disableFontFace === true;
+ this.ignoreErrors = ignoreErrors === true;
+ this._inspectFont = inspectFont;
+ }
+ createNativeFontFace() {
+ if (!this.data || this.disableFontFace) {
+ return null;
+ }
+ let nativeFontFace;
+ if (!this.cssFontInfo) {
+ nativeFontFace = new FontFace(this.loadedName, this.data, {});
+ } else {
+ const css = {
+ weight: this.cssFontInfo.fontWeight
+ };
+ if (this.cssFontInfo.italicAngle) {
+ css.style = `oblique ${this.cssFontInfo.italicAngle}deg`;
+ }
+ nativeFontFace = new FontFace(this.cssFontInfo.fontFamily, this.data, css);
+ }
+ this._inspectFont?.(this);
+ return nativeFontFace;
+ }
+ createFontFaceRule() {
+ if (!this.data || this.disableFontFace) {
+ return null;
+ }
+ const data = bytesToString(this.data);
+ const url = `url(data:${this.mimetype};base64,${btoa(data)});`;
+ let rule;
+ if (!this.cssFontInfo) {
+ rule = `@font-face {font-family:"${this.loadedName}";src:${url}}`;
+ } else {
+ let css = `font-weight: ${this.cssFontInfo.fontWeight};`;
+ if (this.cssFontInfo.italicAngle) {
+ css += `font-style: oblique ${this.cssFontInfo.italicAngle}deg;`;
+ }
+ rule = `@font-face {font-family:"${this.cssFontInfo.fontFamily}";${css}src:${url}}`;
+ }
+ this._inspectFont?.(this, url);
+ return rule;
+ }
+ getPathGenerator(objs, character) {
+ if (this.compiledGlyphs[character] !== undefined) {
+ return this.compiledGlyphs[character];
+ }
+ let cmds;
+ try {
+ cmds = objs.get(this.loadedName + "_path_" + character);
+ } catch (ex) {
+ if (!this.ignoreErrors) {
+ throw ex;
+ }
+ warn(`getPathGenerator - ignoring character: "${ex}".`);
+ return this.compiledGlyphs[character] = function (c, size) {};
+ }
+ if (this.isEvalSupported && util_FeatureTest.isEvalSupported) {
+ const jsBuf = [];
+ for (const current of cmds) {
+ const args = current.args !== undefined ? current.args.join(",") : "";
+ jsBuf.push("c.", current.cmd, "(", args, ");\n");
+ }
+ return this.compiledGlyphs[character] = new Function("c", "size", jsBuf.join(""));
+ }
+ return this.compiledGlyphs[character] = function (c, size) {
+ for (const current of cmds) {
+ if (current.cmd === "scale") {
+ current.args = [size, -size];
+ }
+ c[current.cmd].apply(c, current.args);
+ }
+ };
+ }
+}
+
+;// CONCATENATED MODULE: ./src/display/pattern_helper.js
+
+
+const PathType = {
+ FILL: "Fill",
+ STROKE: "Stroke",
+ SHADING: "Shading"
+};
+function applyBoundingBox(ctx, bbox) {
+ if (!bbox) {
+ return;
+ }
+ const width = bbox[2] - bbox[0];
+ const height = bbox[3] - bbox[1];
+ const region = new Path2D();
+ region.rect(bbox[0], bbox[1], width, height);
+ ctx.clip(region);
+}
+class BaseShadingPattern {
+ constructor() {
+ if (this.constructor === BaseShadingPattern) {
+ unreachable("Cannot initialize BaseShadingPattern.");
+ }
+ }
+ getPattern() {
+ unreachable("Abstract method `getPattern` called.");
+ }
+}
+class RadialAxialShadingPattern extends BaseShadingPattern {
+ constructor(IR) {
+ super();
+ this._type = IR[1];
+ this._bbox = IR[2];
+ this._colorStops = IR[3];
+ this._p0 = IR[4];
+ this._p1 = IR[5];
+ this._r0 = IR[6];
+ this._r1 = IR[7];
+ this.matrix = null;
+ }
+ _createGradient(ctx) {
+ let grad;
+ if (this._type === "axial") {
+ grad = ctx.createLinearGradient(this._p0[0], this._p0[1], this._p1[0], this._p1[1]);
+ } else if (this._type === "radial") {
+ grad = ctx.createRadialGradient(this._p0[0], this._p0[1], this._r0, this._p1[0], this._p1[1], this._r1);
+ }
+ for (const colorStop of this._colorStops) {
+ grad.addColorStop(colorStop[0], colorStop[1]);
+ }
+ return grad;
+ }
+ getPattern(ctx, owner, inverse, pathType) {
+ let pattern;
+ if (pathType === PathType.STROKE || pathType === PathType.FILL) {
+ const ownerBBox = owner.current.getClippedPathBoundingBox(pathType, getCurrentTransform(ctx)) || [0, 0, 0, 0];
+ const width = Math.ceil(ownerBBox[2] - ownerBBox[0]) || 1;
+ const height = Math.ceil(ownerBBox[3] - ownerBBox[1]) || 1;
+ const tmpCanvas = owner.cachedCanvases.getCanvas("pattern", width, height, true);
+ const tmpCtx = tmpCanvas.context;
+ tmpCtx.clearRect(0, 0, tmpCtx.canvas.width, tmpCtx.canvas.height);
+ tmpCtx.beginPath();
+ tmpCtx.rect(0, 0, tmpCtx.canvas.width, tmpCtx.canvas.height);
+ tmpCtx.translate(-ownerBBox[0], -ownerBBox[1]);
+ inverse = Util.transform(inverse, [1, 0, 0, 1, ownerBBox[0], ownerBBox[1]]);
+ tmpCtx.transform(...owner.baseTransform);
+ if (this.matrix) {
+ tmpCtx.transform(...this.matrix);
+ }
+ applyBoundingBox(tmpCtx, this._bbox);
+ tmpCtx.fillStyle = this._createGradient(tmpCtx);
+ tmpCtx.fill();
+ pattern = ctx.createPattern(tmpCanvas.canvas, "no-repeat");
+ const domMatrix = new DOMMatrix(inverse);
+ pattern.setTransform(domMatrix);
+ } else {
+ applyBoundingBox(ctx, this._bbox);
+ pattern = this._createGradient(ctx);
+ }
+ return pattern;
+ }
+}
+function drawTriangle(data, context, p1, p2, p3, c1, c2, c3) {
+ const coords = context.coords,
+ colors = context.colors;
+ const bytes = data.data,
+ rowSize = data.width * 4;
+ let tmp;
+ if (coords[p1 + 1] > coords[p2 + 1]) {
+ tmp = p1;
+ p1 = p2;
+ p2 = tmp;
+ tmp = c1;
+ c1 = c2;
+ c2 = tmp;
+ }
+ if (coords[p2 + 1] > coords[p3 + 1]) {
+ tmp = p2;
+ p2 = p3;
+ p3 = tmp;
+ tmp = c2;
+ c2 = c3;
+ c3 = tmp;
+ }
+ if (coords[p1 + 1] > coords[p2 + 1]) {
+ tmp = p1;
+ p1 = p2;
+ p2 = tmp;
+ tmp = c1;
+ c1 = c2;
+ c2 = tmp;
+ }
+ const x1 = (coords[p1] + context.offsetX) * context.scaleX;
+ const y1 = (coords[p1 + 1] + context.offsetY) * context.scaleY;
+ const x2 = (coords[p2] + context.offsetX) * context.scaleX;
+ const y2 = (coords[p2 + 1] + context.offsetY) * context.scaleY;
+ const x3 = (coords[p3] + context.offsetX) * context.scaleX;
+ const y3 = (coords[p3 + 1] + context.offsetY) * context.scaleY;
+ if (y1 >= y3) {
+ return;
+ }
+ const c1r = colors[c1],
+ c1g = colors[c1 + 1],
+ c1b = colors[c1 + 2];
+ const c2r = colors[c2],
+ c2g = colors[c2 + 1],
+ c2b = colors[c2 + 2];
+ const c3r = colors[c3],
+ c3g = colors[c3 + 1],
+ c3b = colors[c3 + 2];
+ const minY = Math.round(y1),
+ maxY = Math.round(y3);
+ let xa, car, cag, cab;
+ let xb, cbr, cbg, cbb;
+ for (let y = minY; y <= maxY; y++) {
+ if (y < y2) {
+ const k = y < y1 ? 0 : (y1 - y) / (y1 - y2);
+ xa = x1 - (x1 - x2) * k;
+ car = c1r - (c1r - c2r) * k;
+ cag = c1g - (c1g - c2g) * k;
+ cab = c1b - (c1b - c2b) * k;
+ } else {
+ let k;
+ if (y > y3) {
+ k = 1;
+ } else if (y2 === y3) {
+ k = 0;
+ } else {
+ k = (y2 - y) / (y2 - y3);
+ }
+ xa = x2 - (x2 - x3) * k;
+ car = c2r - (c2r - c3r) * k;
+ cag = c2g - (c2g - c3g) * k;
+ cab = c2b - (c2b - c3b) * k;
+ }
+ let k;
+ if (y < y1) {
+ k = 0;
+ } else if (y > y3) {
+ k = 1;
+ } else {
+ k = (y1 - y) / (y1 - y3);
+ }
+ xb = x1 - (x1 - x3) * k;
+ cbr = c1r - (c1r - c3r) * k;
+ cbg = c1g - (c1g - c3g) * k;
+ cbb = c1b - (c1b - c3b) * k;
+ const x1_ = Math.round(Math.min(xa, xb));
+ const x2_ = Math.round(Math.max(xa, xb));
+ let j = rowSize * y + x1_ * 4;
+ for (let x = x1_; x <= x2_; x++) {
+ k = (xa - x) / (xa - xb);
+ if (k < 0) {
+ k = 0;
+ } else if (k > 1) {
+ k = 1;
+ }
+ bytes[j++] = car - (car - cbr) * k | 0;
+ bytes[j++] = cag - (cag - cbg) * k | 0;
+ bytes[j++] = cab - (cab - cbb) * k | 0;
+ bytes[j++] = 255;
+ }
+ }
+}
+function drawFigure(data, figure, context) {
+ const ps = figure.coords;
+ const cs = figure.colors;
+ let i, ii;
+ switch (figure.type) {
+ case "lattice":
+ const verticesPerRow = figure.verticesPerRow;
+ const rows = Math.floor(ps.length / verticesPerRow) - 1;
+ const cols = verticesPerRow - 1;
+ for (i = 0; i < rows; i++) {
+ let q = i * verticesPerRow;
+ for (let j = 0; j < cols; j++, q++) {
+ drawTriangle(data, context, ps[q], ps[q + 1], ps[q + verticesPerRow], cs[q], cs[q + 1], cs[q + verticesPerRow]);
+ drawTriangle(data, context, ps[q + verticesPerRow + 1], ps[q + 1], ps[q + verticesPerRow], cs[q + verticesPerRow + 1], cs[q + 1], cs[q + verticesPerRow]);
+ }
+ }
+ break;
+ case "triangles":
+ for (i = 0, ii = ps.length; i < ii; i += 3) {
+ drawTriangle(data, context, ps[i], ps[i + 1], ps[i + 2], cs[i], cs[i + 1], cs[i + 2]);
+ }
+ break;
+ default:
+ throw new Error("illegal figure");
+ }
+}
+class MeshShadingPattern extends BaseShadingPattern {
+ constructor(IR) {
+ super();
+ this._coords = IR[2];
+ this._colors = IR[3];
+ this._figures = IR[4];
+ this._bounds = IR[5];
+ this._bbox = IR[7];
+ this._background = IR[8];
+ this.matrix = null;
+ }
+ _createMeshCanvas(combinedScale, backgroundColor, cachedCanvases) {
+ const EXPECTED_SCALE = 1.1;
+ const MAX_PATTERN_SIZE = 3000;
+ const BORDER_SIZE = 2;
+ const offsetX = Math.floor(this._bounds[0]);
+ const offsetY = Math.floor(this._bounds[1]);
+ const boundsWidth = Math.ceil(this._bounds[2]) - offsetX;
+ const boundsHeight = Math.ceil(this._bounds[3]) - offsetY;
+ const width = Math.min(Math.ceil(Math.abs(boundsWidth * combinedScale[0] * EXPECTED_SCALE)), MAX_PATTERN_SIZE);
+ const height = Math.min(Math.ceil(Math.abs(boundsHeight * combinedScale[1] * EXPECTED_SCALE)), MAX_PATTERN_SIZE);
+ const scaleX = boundsWidth / width;
+ const scaleY = boundsHeight / height;
+ const context = {
+ coords: this._coords,
+ colors: this._colors,
+ offsetX: -offsetX,
+ offsetY: -offsetY,
+ scaleX: 1 / scaleX,
+ scaleY: 1 / scaleY
+ };
+ const paddedWidth = width + BORDER_SIZE * 2;
+ const paddedHeight = height + BORDER_SIZE * 2;
+ const tmpCanvas = cachedCanvases.getCanvas("mesh", paddedWidth, paddedHeight, false);
+ const tmpCtx = tmpCanvas.context;
+ const data = tmpCtx.createImageData(width, height);
+ if (backgroundColor) {
+ const bytes = data.data;
+ for (let i = 0, ii = bytes.length; i < ii; i += 4) {
+ bytes[i] = backgroundColor[0];
+ bytes[i + 1] = backgroundColor[1];
+ bytes[i + 2] = backgroundColor[2];
+ bytes[i + 3] = 255;
+ }
+ }
+ for (const figure of this._figures) {
+ drawFigure(data, figure, context);
+ }
+ tmpCtx.putImageData(data, BORDER_SIZE, BORDER_SIZE);
+ const canvas = tmpCanvas.canvas;
+ return {
+ canvas,
+ offsetX: offsetX - BORDER_SIZE * scaleX,
+ offsetY: offsetY - BORDER_SIZE * scaleY,
+ scaleX,
+ scaleY
+ };
+ }
+ getPattern(ctx, owner, inverse, pathType) {
+ applyBoundingBox(ctx, this._bbox);
+ let scale;
+ if (pathType === PathType.SHADING) {
+ scale = Util.singularValueDecompose2dScale(getCurrentTransform(ctx));
+ } else {
+ scale = Util.singularValueDecompose2dScale(owner.baseTransform);
+ if (this.matrix) {
+ const matrixScale = Util.singularValueDecompose2dScale(this.matrix);
+ scale = [scale[0] * matrixScale[0], scale[1] * matrixScale[1]];
+ }
+ }
+ const temporaryPatternCanvas = this._createMeshCanvas(scale, pathType === PathType.SHADING ? null : this._background, owner.cachedCanvases);
+ if (pathType !== PathType.SHADING) {
+ ctx.setTransform(...owner.baseTransform);
+ if (this.matrix) {
+ ctx.transform(...this.matrix);
+ }
+ }
+ ctx.translate(temporaryPatternCanvas.offsetX, temporaryPatternCanvas.offsetY);
+ ctx.scale(temporaryPatternCanvas.scaleX, temporaryPatternCanvas.scaleY);
+ return ctx.createPattern(temporaryPatternCanvas.canvas, "no-repeat");
+ }
+}
+class DummyShadingPattern extends BaseShadingPattern {
+ getPattern() {
+ return "hotpink";
+ }
+}
+function getShadingPattern(IR) {
+ switch (IR[0]) {
+ case "RadialAxial":
+ return new RadialAxialShadingPattern(IR);
+ case "Mesh":
+ return new MeshShadingPattern(IR);
+ case "Dummy":
+ return new DummyShadingPattern();
+ }
+ throw new Error(`Unknown IR type: ${IR[0]}`);
+}
+const PaintType = {
+ COLORED: 1,
+ UNCOLORED: 2
+};
+class TilingPattern {
+ static MAX_PATTERN_SIZE = 3000;
+ constructor(IR, color, ctx, canvasGraphicsFactory, baseTransform) {
+ this.operatorList = IR[2];
+ this.matrix = IR[3] || [1, 0, 0, 1, 0, 0];
+ this.bbox = IR[4];
+ this.xstep = IR[5];
+ this.ystep = IR[6];
+ this.paintType = IR[7];
+ this.tilingType = IR[8];
+ this.color = color;
+ this.ctx = ctx;
+ this.canvasGraphicsFactory = canvasGraphicsFactory;
+ this.baseTransform = baseTransform;
+ }
+ createPatternCanvas(owner) {
+ const operatorList = this.operatorList;
+ const bbox = this.bbox;
+ const xstep = this.xstep;
+ const ystep = this.ystep;
+ const paintType = this.paintType;
+ const tilingType = this.tilingType;
+ const color = this.color;
+ const canvasGraphicsFactory = this.canvasGraphicsFactory;
+ info("TilingType: " + tilingType);
+ const x0 = bbox[0],
+ y0 = bbox[1],
+ x1 = bbox[2],
+ y1 = bbox[3];
+ const matrixScale = Util.singularValueDecompose2dScale(this.matrix);
+ const curMatrixScale = Util.singularValueDecompose2dScale(this.baseTransform);
+ const combinedScale = [matrixScale[0] * curMatrixScale[0], matrixScale[1] * curMatrixScale[1]];
+ const dimx = this.getSizeAndScale(xstep, this.ctx.canvas.width, combinedScale[0]);
+ const dimy = this.getSizeAndScale(ystep, this.ctx.canvas.height, combinedScale[1]);
+ const tmpCanvas = owner.cachedCanvases.getCanvas("pattern", dimx.size, dimy.size, true);
+ const tmpCtx = tmpCanvas.context;
+ const graphics = canvasGraphicsFactory.createCanvasGraphics(tmpCtx);
+ graphics.groupLevel = owner.groupLevel;
+ this.setFillAndStrokeStyleToContext(graphics, paintType, color);
+ let adjustedX0 = x0;
+ let adjustedY0 = y0;
+ let adjustedX1 = x1;
+ let adjustedY1 = y1;
+ if (x0 < 0) {
+ adjustedX0 = 0;
+ adjustedX1 += Math.abs(x0);
+ }
+ if (y0 < 0) {
+ adjustedY0 = 0;
+ adjustedY1 += Math.abs(y0);
+ }
+ tmpCtx.translate(-(dimx.scale * adjustedX0), -(dimy.scale * adjustedY0));
+ graphics.transform(dimx.scale, 0, 0, dimy.scale, 0, 0);
+ tmpCtx.save();
+ this.clipBbox(graphics, adjustedX0, adjustedY0, adjustedX1, adjustedY1);
+ graphics.baseTransform = getCurrentTransform(graphics.ctx);
+ graphics.executeOperatorList(operatorList);
+ graphics.endDrawing();
+ return {
+ canvas: tmpCanvas.canvas,
+ scaleX: dimx.scale,
+ scaleY: dimy.scale,
+ offsetX: adjustedX0,
+ offsetY: adjustedY0
+ };
+ }
+ getSizeAndScale(step, realOutputSize, scale) {
+ step = Math.abs(step);
+ const maxSize = Math.max(TilingPattern.MAX_PATTERN_SIZE, realOutputSize);
+ let size = Math.ceil(step * scale);
+ if (size >= maxSize) {
+ size = maxSize;
+ } else {
+ scale = size / step;
+ }
+ return {
+ scale,
+ size
+ };
+ }
+ clipBbox(graphics, x0, y0, x1, y1) {
+ const bboxWidth = x1 - x0;
+ const bboxHeight = y1 - y0;
+ graphics.ctx.rect(x0, y0, bboxWidth, bboxHeight);
+ graphics.current.updateRectMinMax(getCurrentTransform(graphics.ctx), [x0, y0, x1, y1]);
+ graphics.clip();
+ graphics.endPath();
+ }
+ setFillAndStrokeStyleToContext(graphics, paintType, color) {
+ const context = graphics.ctx,
+ current = graphics.current;
+ switch (paintType) {
+ case PaintType.COLORED:
+ const ctx = this.ctx;
+ context.fillStyle = ctx.fillStyle;
+ context.strokeStyle = ctx.strokeStyle;
+ current.fillColor = ctx.fillStyle;
+ current.strokeColor = ctx.strokeStyle;
+ break;
+ case PaintType.UNCOLORED:
+ const cssColor = Util.makeHexColor(color[0], color[1], color[2]);
+ context.fillStyle = cssColor;
+ context.strokeStyle = cssColor;
+ current.fillColor = cssColor;
+ current.strokeColor = cssColor;
+ break;
+ default:
+ throw new FormatError(`Unsupported paint type: ${paintType}`);
+ }
+ }
+ getPattern(ctx, owner, inverse, pathType) {
+ let matrix = inverse;
+ if (pathType !== PathType.SHADING) {
+ matrix = Util.transform(matrix, owner.baseTransform);
+ if (this.matrix) {
+ matrix = Util.transform(matrix, this.matrix);
+ }
+ }
+ const temporaryPatternCanvas = this.createPatternCanvas(owner);
+ let domMatrix = new DOMMatrix(matrix);
+ domMatrix = domMatrix.translate(temporaryPatternCanvas.offsetX, temporaryPatternCanvas.offsetY);
+ domMatrix = domMatrix.scale(1 / temporaryPatternCanvas.scaleX, 1 / temporaryPatternCanvas.scaleY);
+ const pattern = ctx.createPattern(temporaryPatternCanvas.canvas, "repeat");
+ pattern.setTransform(domMatrix);
+ return pattern;
+ }
+}
+
+;// CONCATENATED MODULE: ./src/shared/image_utils.js
+
+function convertToRGBA(params) {
+ switch (params.kind) {
+ case ImageKind.GRAYSCALE_1BPP:
+ return convertBlackAndWhiteToRGBA(params);
+ case ImageKind.RGB_24BPP:
+ return convertRGBToRGBA(params);
+ }
+ return null;
+}
+function convertBlackAndWhiteToRGBA({
+ src,
+ srcPos = 0,
+ dest,
+ width,
+ height,
+ nonBlackColor = 0xffffffff,
+ inverseDecode = false
+}) {
+ const black = util_FeatureTest.isLittleEndian ? 0xff000000 : 0x000000ff;
+ const [zeroMapping, oneMapping] = inverseDecode ? [nonBlackColor, black] : [black, nonBlackColor];
+ const widthInSource = width >> 3;
+ const widthRemainder = width & 7;
+ const srcLength = src.length;
+ dest = new Uint32Array(dest.buffer);
+ let destPos = 0;
+ for (let i = 0; i < height; i++) {
+ for (const max = srcPos + widthInSource; srcPos < max; srcPos++) {
+ const elem = srcPos < srcLength ? src[srcPos] : 255;
+ dest[destPos++] = elem & 0b10000000 ? oneMapping : zeroMapping;
+ dest[destPos++] = elem & 0b1000000 ? oneMapping : zeroMapping;
+ dest[destPos++] = elem & 0b100000 ? oneMapping : zeroMapping;
+ dest[destPos++] = elem & 0b10000 ? oneMapping : zeroMapping;
+ dest[destPos++] = elem & 0b1000 ? oneMapping : zeroMapping;
+ dest[destPos++] = elem & 0b100 ? oneMapping : zeroMapping;
+ dest[destPos++] = elem & 0b10 ? oneMapping : zeroMapping;
+ dest[destPos++] = elem & 0b1 ? oneMapping : zeroMapping;
+ }
+ if (widthRemainder === 0) {
+ continue;
+ }
+ const elem = srcPos < srcLength ? src[srcPos++] : 255;
+ for (let j = 0; j < widthRemainder; j++) {
+ dest[destPos++] = elem & 1 << 7 - j ? oneMapping : zeroMapping;
+ }
+ }
+ return {
+ srcPos,
+ destPos
+ };
+}
+function convertRGBToRGBA({
+ src,
+ srcPos = 0,
+ dest,
+ destPos = 0,
+ width,
+ height
+}) {
+ let i = 0;
+ const len32 = src.length >> 2;
+ const src32 = new Uint32Array(src.buffer, srcPos, len32);
+ if (FeatureTest.isLittleEndian) {
+ for (; i < len32 - 2; i += 3, destPos += 4) {
+ const s1 = src32[i];
+ const s2 = src32[i + 1];
+ const s3 = src32[i + 2];
+ dest[destPos] = s1 | 0xff000000;
+ dest[destPos + 1] = s1 >>> 24 | s2 << 8 | 0xff000000;
+ dest[destPos + 2] = s2 >>> 16 | s3 << 16 | 0xff000000;
+ dest[destPos + 3] = s3 >>> 8 | 0xff000000;
+ }
+ for (let j = i * 4, jj = src.length; j < jj; j += 3) {
+ dest[destPos++] = src[j] | src[j + 1] << 8 | src[j + 2] << 16 | 0xff000000;
+ }
+ } else {
+ for (; i < len32 - 2; i += 3, destPos += 4) {
+ const s1 = src32[i];
+ const s2 = src32[i + 1];
+ const s3 = src32[i + 2];
+ dest[destPos] = s1 | 0xff;
+ dest[destPos + 1] = s1 << 24 | s2 >>> 8 | 0xff;
+ dest[destPos + 2] = s2 << 16 | s3 >>> 16 | 0xff;
+ dest[destPos + 3] = s3 << 8 | 0xff;
+ }
+ for (let j = i * 4, jj = src.length; j < jj; j += 3) {
+ dest[destPos++] = src[j] << 24 | src[j + 1] << 16 | src[j + 2] << 8 | 0xff;
+ }
+ }
+ return {
+ srcPos,
+ destPos
+ };
+}
+function grayToRGBA(src, dest) {
+ if (FeatureTest.isLittleEndian) {
+ for (let i = 0, ii = src.length; i < ii; i++) {
+ dest[i] = src[i] * 0x10101 | 0xff000000;
+ }
+ } else {
+ for (let i = 0, ii = src.length; i < ii; i++) {
+ dest[i] = src[i] * 0x1010100 | 0x000000ff;
+ }
+ }
+}
+
+;// CONCATENATED MODULE: ./src/display/canvas.js
+
+
+
+
+const MIN_FONT_SIZE = 16;
+const MAX_FONT_SIZE = 100;
+const MAX_GROUP_SIZE = 4096;
+const EXECUTION_TIME = 15;
+const EXECUTION_STEPS = 10;
+const MAX_SIZE_TO_COMPILE = 1000;
+const FULL_CHUNK_HEIGHT = 16;
+function mirrorContextOperations(ctx, destCtx) {
+ if (ctx._removeMirroring) {
+ throw new Error("Context is already forwarding operations.");
+ }
+ ctx.__originalSave = ctx.save;
+ ctx.__originalRestore = ctx.restore;
+ ctx.__originalRotate = ctx.rotate;
+ ctx.__originalScale = ctx.scale;
+ ctx.__originalTranslate = ctx.translate;
+ ctx.__originalTransform = ctx.transform;
+ ctx.__originalSetTransform = ctx.setTransform;
+ ctx.__originalResetTransform = ctx.resetTransform;
+ ctx.__originalClip = ctx.clip;
+ ctx.__originalMoveTo = ctx.moveTo;
+ ctx.__originalLineTo = ctx.lineTo;
+ ctx.__originalBezierCurveTo = ctx.bezierCurveTo;
+ ctx.__originalRect = ctx.rect;
+ ctx.__originalClosePath = ctx.closePath;
+ ctx.__originalBeginPath = ctx.beginPath;
+ ctx._removeMirroring = () => {
+ ctx.save = ctx.__originalSave;
+ ctx.restore = ctx.__originalRestore;
+ ctx.rotate = ctx.__originalRotate;
+ ctx.scale = ctx.__originalScale;
+ ctx.translate = ctx.__originalTranslate;
+ ctx.transform = ctx.__originalTransform;
+ ctx.setTransform = ctx.__originalSetTransform;
+ ctx.resetTransform = ctx.__originalResetTransform;
+ ctx.clip = ctx.__originalClip;
+ ctx.moveTo = ctx.__originalMoveTo;
+ ctx.lineTo = ctx.__originalLineTo;
+ ctx.bezierCurveTo = ctx.__originalBezierCurveTo;
+ ctx.rect = ctx.__originalRect;
+ ctx.closePath = ctx.__originalClosePath;
+ ctx.beginPath = ctx.__originalBeginPath;
+ delete ctx._removeMirroring;
+ };
+ ctx.save = function ctxSave() {
+ destCtx.save();
+ this.__originalSave();
+ };
+ ctx.restore = function ctxRestore() {
+ destCtx.restore();
+ this.__originalRestore();
+ };
+ ctx.translate = function ctxTranslate(x, y) {
+ destCtx.translate(x, y);
+ this.__originalTranslate(x, y);
+ };
+ ctx.scale = function ctxScale(x, y) {
+ destCtx.scale(x, y);
+ this.__originalScale(x, y);
+ };
+ ctx.transform = function ctxTransform(a, b, c, d, e, f) {
+ destCtx.transform(a, b, c, d, e, f);
+ this.__originalTransform(a, b, c, d, e, f);
+ };
+ ctx.setTransform = function ctxSetTransform(a, b, c, d, e, f) {
+ destCtx.setTransform(a, b, c, d, e, f);
+ this.__originalSetTransform(a, b, c, d, e, f);
+ };
+ ctx.resetTransform = function ctxResetTransform() {
+ destCtx.resetTransform();
+ this.__originalResetTransform();
+ };
+ ctx.rotate = function ctxRotate(angle) {
+ destCtx.rotate(angle);
+ this.__originalRotate(angle);
+ };
+ ctx.clip = function ctxRotate(rule) {
+ destCtx.clip(rule);
+ this.__originalClip(rule);
+ };
+ ctx.moveTo = function (x, y) {
+ destCtx.moveTo(x, y);
+ this.__originalMoveTo(x, y);
+ };
+ ctx.lineTo = function (x, y) {
+ destCtx.lineTo(x, y);
+ this.__originalLineTo(x, y);
+ };
+ ctx.bezierCurveTo = function (cp1x, cp1y, cp2x, cp2y, x, y) {
+ destCtx.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y);
+ this.__originalBezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y);
+ };
+ ctx.rect = function (x, y, width, height) {
+ destCtx.rect(x, y, width, height);
+ this.__originalRect(x, y, width, height);
+ };
+ ctx.closePath = function () {
+ destCtx.closePath();
+ this.__originalClosePath();
+ };
+ ctx.beginPath = function () {
+ destCtx.beginPath();
+ this.__originalBeginPath();
+ };
+}
+class CachedCanvases {
+ constructor(canvasFactory) {
+ this.canvasFactory = canvasFactory;
+ this.cache = Object.create(null);
+ }
+ getCanvas(id, width, height) {
+ let canvasEntry;
+ if (this.cache[id] !== undefined) {
+ canvasEntry = this.cache[id];
+ this.canvasFactory.reset(canvasEntry, width, height);
+ } else {
+ canvasEntry = this.canvasFactory.create(width, height);
+ this.cache[id] = canvasEntry;
+ }
+ return canvasEntry;
+ }
+ delete(id) {
+ delete this.cache[id];
+ }
+ clear() {
+ for (const id in this.cache) {
+ const canvasEntry = this.cache[id];
+ this.canvasFactory.destroy(canvasEntry);
+ delete this.cache[id];
+ }
+ }
+}
+function drawImageAtIntegerCoords(ctx, srcImg, srcX, srcY, srcW, srcH, destX, destY, destW, destH) {
+ const [a, b, c, d, tx, ty] = getCurrentTransform(ctx);
+ if (b === 0 && c === 0) {
+ const tlX = destX * a + tx;
+ const rTlX = Math.round(tlX);
+ const tlY = destY * d + ty;
+ const rTlY = Math.round(tlY);
+ const brX = (destX + destW) * a + tx;
+ const rWidth = Math.abs(Math.round(brX) - rTlX) || 1;
+ const brY = (destY + destH) * d + ty;
+ const rHeight = Math.abs(Math.round(brY) - rTlY) || 1;
+ ctx.setTransform(Math.sign(a), 0, 0, Math.sign(d), rTlX, rTlY);
+ ctx.drawImage(srcImg, srcX, srcY, srcW, srcH, 0, 0, rWidth, rHeight);
+ ctx.setTransform(a, b, c, d, tx, ty);
+ return [rWidth, rHeight];
+ }
+ if (a === 0 && d === 0) {
+ const tlX = destY * c + tx;
+ const rTlX = Math.round(tlX);
+ const tlY = destX * b + ty;
+ const rTlY = Math.round(tlY);
+ const brX = (destY + destH) * c + tx;
+ const rWidth = Math.abs(Math.round(brX) - rTlX) || 1;
+ const brY = (destX + destW) * b + ty;
+ const rHeight = Math.abs(Math.round(brY) - rTlY) || 1;
+ ctx.setTransform(0, Math.sign(b), Math.sign(c), 0, rTlX, rTlY);
+ ctx.drawImage(srcImg, srcX, srcY, srcW, srcH, 0, 0, rHeight, rWidth);
+ ctx.setTransform(a, b, c, d, tx, ty);
+ return [rHeight, rWidth];
+ }
+ ctx.drawImage(srcImg, srcX, srcY, srcW, srcH, destX, destY, destW, destH);
+ const scaleX = Math.hypot(a, b);
+ const scaleY = Math.hypot(c, d);
+ return [scaleX * destW, scaleY * destH];
+}
+function compileType3Glyph(imgData) {
+ const {
+ width,
+ height
+ } = imgData;
+ if (width > MAX_SIZE_TO_COMPILE || height > MAX_SIZE_TO_COMPILE) {
+ return null;
+ }
+ const POINT_TO_PROCESS_LIMIT = 1000;
+ const POINT_TYPES = new Uint8Array([0, 2, 4, 0, 1, 0, 5, 4, 8, 10, 0, 8, 0, 2, 1, 0]);
+ const width1 = width + 1;
+ let points = new Uint8Array(width1 * (height + 1));
+ let i, j, j0;
+ const lineSize = width + 7 & ~7;
+ let data = new Uint8Array(lineSize * height),
+ pos = 0;
+ for (const elem of imgData.data) {
+ let mask = 128;
+ while (mask > 0) {
+ data[pos++] = elem & mask ? 0 : 255;
+ mask >>= 1;
+ }
+ }
+ let count = 0;
+ pos = 0;
+ if (data[pos] !== 0) {
+ points[0] = 1;
+ ++count;
+ }
+ for (j = 1; j < width; j++) {
+ if (data[pos] !== data[pos + 1]) {
+ points[j] = data[pos] ? 2 : 1;
+ ++count;
+ }
+ pos++;
+ }
+ if (data[pos] !== 0) {
+ points[j] = 2;
+ ++count;
+ }
+ for (i = 1; i < height; i++) {
+ pos = i * lineSize;
+ j0 = i * width1;
+ if (data[pos - lineSize] !== data[pos]) {
+ points[j0] = data[pos] ? 1 : 8;
+ ++count;
+ }
+ let sum = (data[pos] ? 4 : 0) + (data[pos - lineSize] ? 8 : 0);
+ for (j = 1; j < width; j++) {
+ sum = (sum >> 2) + (data[pos + 1] ? 4 : 0) + (data[pos - lineSize + 1] ? 8 : 0);
+ if (POINT_TYPES[sum]) {
+ points[j0 + j] = POINT_TYPES[sum];
+ ++count;
+ }
+ pos++;
+ }
+ if (data[pos - lineSize] !== data[pos]) {
+ points[j0 + j] = data[pos] ? 2 : 4;
+ ++count;
+ }
+ if (count > POINT_TO_PROCESS_LIMIT) {
+ return null;
+ }
+ }
+ pos = lineSize * (height - 1);
+ j0 = i * width1;
+ if (data[pos] !== 0) {
+ points[j0] = 8;
+ ++count;
+ }
+ for (j = 1; j < width; j++) {
+ if (data[pos] !== data[pos + 1]) {
+ points[j0 + j] = data[pos] ? 4 : 8;
+ ++count;
+ }
+ pos++;
+ }
+ if (data[pos] !== 0) {
+ points[j0 + j] = 4;
+ ++count;
+ }
+ if (count > POINT_TO_PROCESS_LIMIT) {
+ return null;
+ }
+ const steps = new Int32Array([0, width1, -1, 0, -width1, 0, 0, 0, 1]);
+ const path = new Path2D();
+ for (i = 0; count && i <= height; i++) {
+ let p = i * width1;
+ const end = p + width;
+ while (p < end && !points[p]) {
+ p++;
+ }
+ if (p === end) {
+ continue;
+ }
+ path.moveTo(p % width1, i);
+ const p0 = p;
+ let type = points[p];
+ do {
+ const step = steps[type];
+ do {
+ p += step;
+ } while (!points[p]);
+ const pp = points[p];
+ if (pp !== 5 && pp !== 10) {
+ type = pp;
+ points[p] = 0;
+ } else {
+ type = pp & 0x33 * type >> 4;
+ points[p] &= type >> 2 | type << 2;
+ }
+ path.lineTo(p % width1, p / width1 | 0);
+ if (!points[p]) {
+ --count;
+ }
+ } while (p0 !== p);
+ --i;
+ }
+ data = null;
+ points = null;
+ const drawOutline = function (c) {
+ c.save();
+ c.scale(1 / width, -1 / height);
+ c.translate(0, -height);
+ c.fill(path);
+ c.beginPath();
+ c.restore();
+ };
+ return drawOutline;
+}
+class CanvasExtraState {
+ constructor(width, height) {
+ this.alphaIsShape = false;
+ this.fontSize = 0;
+ this.fontSizeScale = 1;
+ this.textMatrix = IDENTITY_MATRIX;
+ this.textMatrixScale = 1;
+ this.fontMatrix = FONT_IDENTITY_MATRIX;
+ this.leading = 0;
+ this.x = 0;
+ this.y = 0;
+ this.lineX = 0;
+ this.lineY = 0;
+ this.charSpacing = 0;
+ this.wordSpacing = 0;
+ this.textHScale = 1;
+ this.textRenderingMode = TextRenderingMode.FILL;
+ this.textRise = 0;
+ this.fillColor = "#000000";
+ this.strokeColor = "#000000";
+ this.patternFill = false;
+ this.fillAlpha = 1;
+ this.strokeAlpha = 1;
+ this.lineWidth = 1;
+ this.activeSMask = null;
+ this.transferMaps = "none";
+ this.startNewPathAndClipBox([0, 0, width, height]);
+ }
+ clone() {
+ const clone = Object.create(this);
+ clone.clipBox = this.clipBox.slice();
+ return clone;
+ }
+ setCurrentPoint(x, y) {
+ this.x = x;
+ this.y = y;
+ }
+ updatePathMinMax(transform, x, y) {
+ [x, y] = Util.applyTransform([x, y], transform);
+ this.minX = Math.min(this.minX, x);
+ this.minY = Math.min(this.minY, y);
+ this.maxX = Math.max(this.maxX, x);
+ this.maxY = Math.max(this.maxY, y);
+ }
+ updateRectMinMax(transform, rect) {
+ const p1 = Util.applyTransform(rect, transform);
+ const p2 = Util.applyTransform(rect.slice(2), transform);
+ const p3 = Util.applyTransform([rect[0], rect[3]], transform);
+ const p4 = Util.applyTransform([rect[2], rect[1]], transform);
+ this.minX = Math.min(this.minX, p1[0], p2[0], p3[0], p4[0]);
+ this.minY = Math.min(this.minY, p1[1], p2[1], p3[1], p4[1]);
+ this.maxX = Math.max(this.maxX, p1[0], p2[0], p3[0], p4[0]);
+ this.maxY = Math.max(this.maxY, p1[1], p2[1], p3[1], p4[1]);
+ }
+ updateScalingPathMinMax(transform, minMax) {
+ Util.scaleMinMax(transform, minMax);
+ this.minX = Math.min(this.minX, minMax[0]);
+ this.minY = Math.min(this.minY, minMax[1]);
+ this.maxX = Math.max(this.maxX, minMax[2]);
+ this.maxY = Math.max(this.maxY, minMax[3]);
+ }
+ updateCurvePathMinMax(transform, x0, y0, x1, y1, x2, y2, x3, y3, minMax) {
+ const box = Util.bezierBoundingBox(x0, y0, x1, y1, x2, y2, x3, y3, minMax);
+ if (minMax) {
+ return;
+ }
+ this.updateRectMinMax(transform, box);
+ }
+ getPathBoundingBox(pathType = PathType.FILL, transform = null) {
+ const box = [this.minX, this.minY, this.maxX, this.maxY];
+ if (pathType === PathType.STROKE) {
+ if (!transform) {
+ unreachable("Stroke bounding box must include transform.");
+ }
+ const scale = Util.singularValueDecompose2dScale(transform);
+ const xStrokePad = scale[0] * this.lineWidth / 2;
+ const yStrokePad = scale[1] * this.lineWidth / 2;
+ box[0] -= xStrokePad;
+ box[1] -= yStrokePad;
+ box[2] += xStrokePad;
+ box[3] += yStrokePad;
+ }
+ return box;
+ }
+ updateClipFromPath() {
+ const intersect = Util.intersect(this.clipBox, this.getPathBoundingBox());
+ this.startNewPathAndClipBox(intersect || [0, 0, 0, 0]);
+ }
+ isEmptyClip() {
+ return this.minX === Infinity;
+ }
+ startNewPathAndClipBox(box) {
+ this.clipBox = box;
+ this.minX = Infinity;
+ this.minY = Infinity;
+ this.maxX = 0;
+ this.maxY = 0;
+ }
+ getClippedPathBoundingBox(pathType = PathType.FILL, transform = null) {
+ return Util.intersect(this.clipBox, this.getPathBoundingBox(pathType, transform));
+ }
+}
+function putBinaryImageData(ctx, imgData) {
+ if (typeof ImageData !== "undefined" && imgData instanceof ImageData) {
+ ctx.putImageData(imgData, 0, 0);
+ return;
+ }
+ const height = imgData.height,
+ width = imgData.width;
+ const partialChunkHeight = height % FULL_CHUNK_HEIGHT;
+ const fullChunks = (height - partialChunkHeight) / FULL_CHUNK_HEIGHT;
+ const totalChunks = partialChunkHeight === 0 ? fullChunks : fullChunks + 1;
+ const chunkImgData = ctx.createImageData(width, FULL_CHUNK_HEIGHT);
+ let srcPos = 0,
+ destPos;
+ const src = imgData.data;
+ const dest = chunkImgData.data;
+ let i, j, thisChunkHeight, elemsInThisChunk;
+ if (imgData.kind === util_ImageKind.GRAYSCALE_1BPP) {
+ const srcLength = src.byteLength;
+ const dest32 = new Uint32Array(dest.buffer, 0, dest.byteLength >> 2);
+ const dest32DataLength = dest32.length;
+ const fullSrcDiff = width + 7 >> 3;
+ const white = 0xffffffff;
+ const black = util_FeatureTest.isLittleEndian ? 0xff000000 : 0x000000ff;
+ for (i = 0; i < totalChunks; i++) {
+ thisChunkHeight = i < fullChunks ? FULL_CHUNK_HEIGHT : partialChunkHeight;
+ destPos = 0;
+ for (j = 0; j < thisChunkHeight; j++) {
+ const srcDiff = srcLength - srcPos;
+ let k = 0;
+ const kEnd = srcDiff > fullSrcDiff ? width : srcDiff * 8 - 7;
+ const kEndUnrolled = kEnd & ~7;
+ let mask = 0;
+ let srcByte = 0;
+ for (; k < kEndUnrolled; k += 8) {
+ srcByte = src[srcPos++];
+ dest32[destPos++] = srcByte & 128 ? white : black;
+ dest32[destPos++] = srcByte & 64 ? white : black;
+ dest32[destPos++] = srcByte & 32 ? white : black;
+ dest32[destPos++] = srcByte & 16 ? white : black;
+ dest32[destPos++] = srcByte & 8 ? white : black;
+ dest32[destPos++] = srcByte & 4 ? white : black;
+ dest32[destPos++] = srcByte & 2 ? white : black;
+ dest32[destPos++] = srcByte & 1 ? white : black;
+ }
+ for (; k < kEnd; k++) {
+ if (mask === 0) {
+ srcByte = src[srcPos++];
+ mask = 128;
+ }
+ dest32[destPos++] = srcByte & mask ? white : black;
+ mask >>= 1;
+ }
+ }
+ while (destPos < dest32DataLength) {
+ dest32[destPos++] = 0;
+ }
+ ctx.putImageData(chunkImgData, 0, i * FULL_CHUNK_HEIGHT);
+ }
+ } else if (imgData.kind === util_ImageKind.RGBA_32BPP) {
+ j = 0;
+ elemsInThisChunk = width * FULL_CHUNK_HEIGHT * 4;
+ for (i = 0; i < fullChunks; i++) {
+ dest.set(src.subarray(srcPos, srcPos + elemsInThisChunk));
+ srcPos += elemsInThisChunk;
+ ctx.putImageData(chunkImgData, 0, j);
+ j += FULL_CHUNK_HEIGHT;
+ }
+ if (i < totalChunks) {
+ elemsInThisChunk = width * partialChunkHeight * 4;
+ dest.set(src.subarray(srcPos, srcPos + elemsInThisChunk));
+ ctx.putImageData(chunkImgData, 0, j);
+ }
+ } else if (imgData.kind === util_ImageKind.RGB_24BPP) {
+ thisChunkHeight = FULL_CHUNK_HEIGHT;
+ elemsInThisChunk = width * thisChunkHeight;
+ for (i = 0; i < totalChunks; i++) {
+ if (i >= fullChunks) {
+ thisChunkHeight = partialChunkHeight;
+ elemsInThisChunk = width * thisChunkHeight;
+ }
+ destPos = 0;
+ for (j = elemsInThisChunk; j--;) {
+ dest[destPos++] = src[srcPos++];
+ dest[destPos++] = src[srcPos++];
+ dest[destPos++] = src[srcPos++];
+ dest[destPos++] = 255;
+ }
+ ctx.putImageData(chunkImgData, 0, i * FULL_CHUNK_HEIGHT);
+ }
+ } else {
+ throw new Error(`bad image kind: ${imgData.kind}`);
+ }
+}
+function putBinaryImageMask(ctx, imgData) {
+ if (imgData.bitmap) {
+ ctx.drawImage(imgData.bitmap, 0, 0);
+ return;
+ }
+ const height = imgData.height,
+ width = imgData.width;
+ const partialChunkHeight = height % FULL_CHUNK_HEIGHT;
+ const fullChunks = (height - partialChunkHeight) / FULL_CHUNK_HEIGHT;
+ const totalChunks = partialChunkHeight === 0 ? fullChunks : fullChunks + 1;
+ const chunkImgData = ctx.createImageData(width, FULL_CHUNK_HEIGHT);
+ let srcPos = 0;
+ const src = imgData.data;
+ const dest = chunkImgData.data;
+ for (let i = 0; i < totalChunks; i++) {
+ const thisChunkHeight = i < fullChunks ? FULL_CHUNK_HEIGHT : partialChunkHeight;
+ ({
+ srcPos
+ } = convertBlackAndWhiteToRGBA({
+ src,
+ srcPos,
+ dest,
+ width,
+ height: thisChunkHeight,
+ nonBlackColor: 0
+ }));
+ ctx.putImageData(chunkImgData, 0, i * FULL_CHUNK_HEIGHT);
+ }
+}
+function copyCtxState(sourceCtx, destCtx) {
+ const properties = ["strokeStyle", "fillStyle", "fillRule", "globalAlpha", "lineWidth", "lineCap", "lineJoin", "miterLimit", "globalCompositeOperation", "font", "filter"];
+ for (const property of properties) {
+ if (sourceCtx[property] !== undefined) {
+ destCtx[property] = sourceCtx[property];
+ }
+ }
+ if (sourceCtx.setLineDash !== undefined) {
+ destCtx.setLineDash(sourceCtx.getLineDash());
+ destCtx.lineDashOffset = sourceCtx.lineDashOffset;
+ }
+}
+function resetCtxToDefault(ctx) {
+ ctx.strokeStyle = ctx.fillStyle = "#000000";
+ ctx.fillRule = "nonzero";
+ ctx.globalAlpha = 1;
+ ctx.lineWidth = 1;
+ ctx.lineCap = "butt";
+ ctx.lineJoin = "miter";
+ ctx.miterLimit = 10;
+ ctx.globalCompositeOperation = "source-over";
+ ctx.font = "10px sans-serif";
+ if (ctx.setLineDash !== undefined) {
+ ctx.setLineDash([]);
+ ctx.lineDashOffset = 0;
+ }
+ const {
+ filter
+ } = ctx;
+ if (filter !== "none" && filter !== "") {
+ ctx.filter = "none";
+ }
+}
+function composeSMaskBackdrop(bytes, r0, g0, b0) {
+ const length = bytes.length;
+ for (let i = 3; i < length; i += 4) {
+ const alpha = bytes[i];
+ if (alpha === 0) {
+ bytes[i - 3] = r0;
+ bytes[i - 2] = g0;
+ bytes[i - 1] = b0;
+ } else if (alpha < 255) {
+ const alpha_ = 255 - alpha;
+ bytes[i - 3] = bytes[i - 3] * alpha + r0 * alpha_ >> 8;
+ bytes[i - 2] = bytes[i - 2] * alpha + g0 * alpha_ >> 8;
+ bytes[i - 1] = bytes[i - 1] * alpha + b0 * alpha_ >> 8;
+ }
+ }
+}
+function composeSMaskAlpha(maskData, layerData, transferMap) {
+ const length = maskData.length;
+ const scale = 1 / 255;
+ for (let i = 3; i < length; i += 4) {
+ const alpha = transferMap ? transferMap[maskData[i]] : maskData[i];
+ layerData[i] = layerData[i] * alpha * scale | 0;
+ }
+}
+function composeSMaskLuminosity(maskData, layerData, transferMap) {
+ const length = maskData.length;
+ for (let i = 3; i < length; i += 4) {
+ const y = maskData[i - 3] * 77 + maskData[i - 2] * 152 + maskData[i - 1] * 28;
+ layerData[i] = transferMap ? layerData[i] * transferMap[y >> 8] >> 8 : layerData[i] * y >> 16;
+ }
+}
+function genericComposeSMask(maskCtx, layerCtx, width, height, subtype, backdrop, transferMap, layerOffsetX, layerOffsetY, maskOffsetX, maskOffsetY) {
+ const hasBackdrop = !!backdrop;
+ const r0 = hasBackdrop ? backdrop[0] : 0;
+ const g0 = hasBackdrop ? backdrop[1] : 0;
+ const b0 = hasBackdrop ? backdrop[2] : 0;
+ const composeFn = subtype === "Luminosity" ? composeSMaskLuminosity : composeSMaskAlpha;
+ const PIXELS_TO_PROCESS = 1048576;
+ const chunkSize = Math.min(height, Math.ceil(PIXELS_TO_PROCESS / width));
+ for (let row = 0; row < height; row += chunkSize) {
+ const chunkHeight = Math.min(chunkSize, height - row);
+ const maskData = maskCtx.getImageData(layerOffsetX - maskOffsetX, row + (layerOffsetY - maskOffsetY), width, chunkHeight);
+ const layerData = layerCtx.getImageData(layerOffsetX, row + layerOffsetY, width, chunkHeight);
+ if (hasBackdrop) {
+ composeSMaskBackdrop(maskData.data, r0, g0, b0);
+ }
+ composeFn(maskData.data, layerData.data, transferMap);
+ layerCtx.putImageData(layerData, layerOffsetX, row + layerOffsetY);
+ }
+}
+function composeSMask(ctx, smask, layerCtx, layerBox) {
+ const layerOffsetX = layerBox[0];
+ const layerOffsetY = layerBox[1];
+ const layerWidth = layerBox[2] - layerOffsetX;
+ const layerHeight = layerBox[3] - layerOffsetY;
+ if (layerWidth === 0 || layerHeight === 0) {
+ return;
+ }
+ genericComposeSMask(smask.context, layerCtx, layerWidth, layerHeight, smask.subtype, smask.backdrop, smask.transferMap, layerOffsetX, layerOffsetY, smask.offsetX, smask.offsetY);
+ ctx.save();
+ ctx.globalAlpha = 1;
+ ctx.globalCompositeOperation = "source-over";
+ ctx.setTransform(1, 0, 0, 1, 0, 0);
+ ctx.drawImage(layerCtx.canvas, 0, 0);
+ ctx.restore();
+}
+function getImageSmoothingEnabled(transform, interpolate) {
+ const scale = Util.singularValueDecompose2dScale(transform);
+ scale[0] = Math.fround(scale[0]);
+ scale[1] = Math.fround(scale[1]);
+ const actualScale = Math.fround((globalThis.devicePixelRatio || 1) * PixelsPerInch.PDF_TO_CSS_UNITS);
+ if (interpolate !== undefined) {
+ return interpolate;
+ } else if (scale[0] <= actualScale || scale[1] <= actualScale) {
+ return true;
+ }
+ return false;
+}
+const LINE_CAP_STYLES = ["butt", "round", "square"];
+const LINE_JOIN_STYLES = ["miter", "round", "bevel"];
+const NORMAL_CLIP = {};
+const EO_CLIP = {};
+class CanvasGraphics {
+ constructor(canvasCtx, commonObjs, objs, canvasFactory, filterFactory, {
+ optionalContentConfig,
+ markedContentStack = null
+ }, annotationCanvasMap, pageColors) {
+ this.ctx = canvasCtx;
+ this.current = new CanvasExtraState(this.ctx.canvas.width, this.ctx.canvas.height);
+ this.stateStack = [];
+ this.pendingClip = null;
+ this.pendingEOFill = false;
+ this.res = null;
+ this.xobjs = null;
+ this.commonObjs = commonObjs;
+ this.objs = objs;
+ this.canvasFactory = canvasFactory;
+ this.filterFactory = filterFactory;
+ this.groupStack = [];
+ this.processingType3 = null;
+ this.baseTransform = null;
+ this.baseTransformStack = [];
+ this.groupLevel = 0;
+ this.smaskStack = [];
+ this.smaskCounter = 0;
+ this.tempSMask = null;
+ this.suspendedCtx = null;
+ this.contentVisible = true;
+ this.markedContentStack = markedContentStack || [];
+ this.optionalContentConfig = optionalContentConfig;
+ this.cachedCanvases = new CachedCanvases(this.canvasFactory);
+ this.cachedPatterns = new Map();
+ this.annotationCanvasMap = annotationCanvasMap;
+ this.viewportScale = 1;
+ this.outputScaleX = 1;
+ this.outputScaleY = 1;
+ this.pageColors = pageColors;
+ this._cachedScaleForStroking = [-1, 0];
+ this._cachedGetSinglePixelWidth = null;
+ this._cachedBitmapsMap = new Map();
+ }
+ getObject(data, fallback = null) {
+ if (typeof data === "string") {
+ return data.startsWith("g_") ? this.commonObjs.get(data) : this.objs.get(data);
+ }
+ return fallback;
+ }
+ beginDrawing({
+ transform,
+ viewport,
+ transparency = false,
+ background = null
+ }) {
+ const width = this.ctx.canvas.width;
+ const height = this.ctx.canvas.height;
+ const savedFillStyle = this.ctx.fillStyle;
+ this.ctx.fillStyle = background || "#ffffff";
+ this.ctx.fillRect(0, 0, width, height);
+ this.ctx.fillStyle = savedFillStyle;
+ if (transparency) {
+ const transparentCanvas = this.cachedCanvases.getCanvas("transparent", width, height);
+ this.compositeCtx = this.ctx;
+ this.transparentCanvas = transparentCanvas.canvas;
+ this.ctx = transparentCanvas.context;
+ this.ctx.save();
+ this.ctx.transform(...getCurrentTransform(this.compositeCtx));
+ }
+ this.ctx.save();
+ resetCtxToDefault(this.ctx);
+ if (transform) {
+ this.ctx.transform(...transform);
+ this.outputScaleX = transform[0];
+ this.outputScaleY = transform[0];
+ }
+ this.ctx.transform(...viewport.transform);
+ this.viewportScale = viewport.scale;
+ this.baseTransform = getCurrentTransform(this.ctx);
+ }
+ executeOperatorList(operatorList, executionStartIdx, continueCallback, stepper) {
+ const argsArray = operatorList.argsArray;
+ const fnArray = operatorList.fnArray;
+ let i = executionStartIdx || 0;
+ const argsArrayLen = argsArray.length;
+ if (argsArrayLen === i) {
+ return i;
+ }
+ const chunkOperations = argsArrayLen - i > EXECUTION_STEPS && typeof continueCallback === "function";
+ const endTime = chunkOperations ? Date.now() + EXECUTION_TIME : 0;
+ let steps = 0;
+ const commonObjs = this.commonObjs;
+ const objs = this.objs;
+ let fnId;
+ while (true) {
+ if (stepper !== undefined && i === stepper.nextBreakPoint) {
+ stepper.breakIt(i, continueCallback);
+ return i;
+ }
+ fnId = fnArray[i];
+ if (fnId !== OPS.dependency) {
+ this[fnId].apply(this, argsArray[i]);
+ } else {
+ for (const depObjId of argsArray[i]) {
+ const objsPool = depObjId.startsWith("g_") ? commonObjs : objs;
+ if (!objsPool.has(depObjId)) {
+ objsPool.get(depObjId, continueCallback);
+ return i;
+ }
+ }
+ }
+ i++;
+ if (i === argsArrayLen) {
+ return i;
+ }
+ if (chunkOperations && ++steps > EXECUTION_STEPS) {
+ if (Date.now() > endTime) {
+ continueCallback();
+ return i;
+ }
+ steps = 0;
+ }
+ }
+ }
+ #restoreInitialState() {
+ while (this.stateStack.length || this.inSMaskMode) {
+ this.restore();
+ }
+ this.ctx.restore();
+ if (this.transparentCanvas) {
+ this.ctx = this.compositeCtx;
+ this.ctx.save();
+ this.ctx.setTransform(1, 0, 0, 1, 0, 0);
+ this.ctx.drawImage(this.transparentCanvas, 0, 0);
+ this.ctx.restore();
+ this.transparentCanvas = null;
+ }
+ }
+ endDrawing() {
+ this.#restoreInitialState();
+ this.cachedCanvases.clear();
+ this.cachedPatterns.clear();
+ for (const cache of this._cachedBitmapsMap.values()) {
+ for (const canvas of cache.values()) {
+ if (typeof HTMLCanvasElement !== "undefined" && canvas instanceof HTMLCanvasElement) {
+ canvas.width = canvas.height = 0;
+ }
+ }
+ cache.clear();
+ }
+ this._cachedBitmapsMap.clear();
+ this.#drawFilter();
+ }
+ #drawFilter() {
+ if (this.pageColors) {
+ const hcmFilterId = this.filterFactory.addHCMFilter(this.pageColors.foreground, this.pageColors.background);
+ if (hcmFilterId !== "none") {
+ const savedFilter = this.ctx.filter;
+ this.ctx.filter = hcmFilterId;
+ this.ctx.drawImage(this.ctx.canvas, 0, 0);
+ this.ctx.filter = savedFilter;
+ }
+ }
+ }
+ _scaleImage(img, inverseTransform) {
+ const width = img.width;
+ const height = img.height;
+ let widthScale = Math.max(Math.hypot(inverseTransform[0], inverseTransform[1]), 1);
+ let heightScale = Math.max(Math.hypot(inverseTransform[2], inverseTransform[3]), 1);
+ let paintWidth = width,
+ paintHeight = height;
+ let tmpCanvasId = "prescale1";
+ let tmpCanvas, tmpCtx;
+ while (widthScale > 2 && paintWidth > 1 || heightScale > 2 && paintHeight > 1) {
+ let newWidth = paintWidth,
+ newHeight = paintHeight;
+ if (widthScale > 2 && paintWidth > 1) {
+ newWidth = paintWidth >= 16384 ? Math.floor(paintWidth / 2) - 1 || 1 : Math.ceil(paintWidth / 2);
+ widthScale /= paintWidth / newWidth;
+ }
+ if (heightScale > 2 && paintHeight > 1) {
+ newHeight = paintHeight >= 16384 ? Math.floor(paintHeight / 2) - 1 || 1 : Math.ceil(paintHeight) / 2;
+ heightScale /= paintHeight / newHeight;
+ }
+ tmpCanvas = this.cachedCanvases.getCanvas(tmpCanvasId, newWidth, newHeight);
+ tmpCtx = tmpCanvas.context;
+ tmpCtx.clearRect(0, 0, newWidth, newHeight);
+ tmpCtx.drawImage(img, 0, 0, paintWidth, paintHeight, 0, 0, newWidth, newHeight);
+ img = tmpCanvas.canvas;
+ paintWidth = newWidth;
+ paintHeight = newHeight;
+ tmpCanvasId = tmpCanvasId === "prescale1" ? "prescale2" : "prescale1";
+ }
+ return {
+ img,
+ paintWidth,
+ paintHeight
+ };
+ }
+ _createMaskCanvas(img) {
+ const ctx = this.ctx;
+ const {
+ width,
+ height
+ } = img;
+ const fillColor = this.current.fillColor;
+ const isPatternFill = this.current.patternFill;
+ const currentTransform = getCurrentTransform(ctx);
+ let cache, cacheKey, scaled, maskCanvas;
+ if ((img.bitmap || img.data) && img.count > 1) {
+ const mainKey = img.bitmap || img.data.buffer;
+ cacheKey = JSON.stringify(isPatternFill ? currentTransform : [currentTransform.slice(0, 4), fillColor]);
+ cache = this._cachedBitmapsMap.get(mainKey);
+ if (!cache) {
+ cache = new Map();
+ this._cachedBitmapsMap.set(mainKey, cache);
+ }
+ const cachedImage = cache.get(cacheKey);
+ if (cachedImage && !isPatternFill) {
+ const offsetX = Math.round(Math.min(currentTransform[0], currentTransform[2]) + currentTransform[4]);
+ const offsetY = Math.round(Math.min(currentTransform[1], currentTransform[3]) + currentTransform[5]);
+ return {
+ canvas: cachedImage,
+ offsetX,
+ offsetY
+ };
+ }
+ scaled = cachedImage;
+ }
+ if (!scaled) {
+ maskCanvas = this.cachedCanvases.getCanvas("maskCanvas", width, height);
+ putBinaryImageMask(maskCanvas.context, img);
+ }
+ let maskToCanvas = Util.transform(currentTransform, [1 / width, 0, 0, -1 / height, 0, 0]);
+ maskToCanvas = Util.transform(maskToCanvas, [1, 0, 0, 1, 0, -height]);
+ const [minX, minY, maxX, maxY] = Util.getAxialAlignedBoundingBox([0, 0, width, height], maskToCanvas);
+ const drawnWidth = Math.round(maxX - minX) || 1;
+ const drawnHeight = Math.round(maxY - minY) || 1;
+ const fillCanvas = this.cachedCanvases.getCanvas("fillCanvas", drawnWidth, drawnHeight);
+ const fillCtx = fillCanvas.context;
+ const offsetX = minX;
+ const offsetY = minY;
+ fillCtx.translate(-offsetX, -offsetY);
+ fillCtx.transform(...maskToCanvas);
+ if (!scaled) {
+ scaled = this._scaleImage(maskCanvas.canvas, getCurrentTransformInverse(fillCtx));
+ scaled = scaled.img;
+ if (cache && isPatternFill) {
+ cache.set(cacheKey, scaled);
+ }
+ }
+ fillCtx.imageSmoothingEnabled = getImageSmoothingEnabled(getCurrentTransform(fillCtx), img.interpolate);
+ drawImageAtIntegerCoords(fillCtx, scaled, 0, 0, scaled.width, scaled.height, 0, 0, width, height);
+ fillCtx.globalCompositeOperation = "source-in";
+ const inverse = Util.transform(getCurrentTransformInverse(fillCtx), [1, 0, 0, 1, -offsetX, -offsetY]);
+ fillCtx.fillStyle = isPatternFill ? fillColor.getPattern(ctx, this, inverse, PathType.FILL) : fillColor;
+ fillCtx.fillRect(0, 0, width, height);
+ if (cache && !isPatternFill) {
+ this.cachedCanvases.delete("fillCanvas");
+ cache.set(cacheKey, fillCanvas.canvas);
+ }
+ return {
+ canvas: fillCanvas.canvas,
+ offsetX: Math.round(offsetX),
+ offsetY: Math.round(offsetY)
+ };
+ }
+ setLineWidth(width) {
+ if (width !== this.current.lineWidth) {
+ this._cachedScaleForStroking[0] = -1;
+ }
+ this.current.lineWidth = width;
+ this.ctx.lineWidth = width;
+ }
+ setLineCap(style) {
+ this.ctx.lineCap = LINE_CAP_STYLES[style];
+ }
+ setLineJoin(style) {
+ this.ctx.lineJoin = LINE_JOIN_STYLES[style];
+ }
+ setMiterLimit(limit) {
+ this.ctx.miterLimit = limit;
+ }
+ setDash(dashArray, dashPhase) {
+ const ctx = this.ctx;
+ if (ctx.setLineDash !== undefined) {
+ ctx.setLineDash(dashArray);
+ ctx.lineDashOffset = dashPhase;
+ }
+ }
+ setRenderingIntent(intent) {}
+ setFlatness(flatness) {}
+ setGState(states) {
+ for (const [key, value] of states) {
+ switch (key) {
+ case "LW":
+ this.setLineWidth(value);
+ break;
+ case "LC":
+ this.setLineCap(value);
+ break;
+ case "LJ":
+ this.setLineJoin(value);
+ break;
+ case "ML":
+ this.setMiterLimit(value);
+ break;
+ case "D":
+ this.setDash(value[0], value[1]);
+ break;
+ case "RI":
+ this.setRenderingIntent(value);
+ break;
+ case "FL":
+ this.setFlatness(value);
+ break;
+ case "Font":
+ this.setFont(value[0], value[1]);
+ break;
+ case "CA":
+ this.current.strokeAlpha = value;
+ break;
+ case "ca":
+ this.current.fillAlpha = value;
+ this.ctx.globalAlpha = value;
+ break;
+ case "BM":
+ this.ctx.globalCompositeOperation = value;
+ break;
+ case "SMask":
+ this.current.activeSMask = value ? this.tempSMask : null;
+ this.tempSMask = null;
+ this.checkSMaskState();
+ break;
+ case "TR":
+ this.ctx.filter = this.current.transferMaps = this.filterFactory.addFilter(value);
+ break;
+ }
+ }
+ }
+ get inSMaskMode() {
+ return !!this.suspendedCtx;
+ }
+ checkSMaskState() {
+ const inSMaskMode = this.inSMaskMode;
+ if (this.current.activeSMask && !inSMaskMode) {
+ this.beginSMaskMode();
+ } else if (!this.current.activeSMask && inSMaskMode) {
+ this.endSMaskMode();
+ }
+ }
+ beginSMaskMode() {
+ if (this.inSMaskMode) {
+ throw new Error("beginSMaskMode called while already in smask mode");
+ }
+ const drawnWidth = this.ctx.canvas.width;
+ const drawnHeight = this.ctx.canvas.height;
+ const cacheId = "smaskGroupAt" + this.groupLevel;
+ const scratchCanvas = this.cachedCanvases.getCanvas(cacheId, drawnWidth, drawnHeight);
+ this.suspendedCtx = this.ctx;
+ this.ctx = scratchCanvas.context;
+ const ctx = this.ctx;
+ ctx.setTransform(...getCurrentTransform(this.suspendedCtx));
+ copyCtxState(this.suspendedCtx, ctx);
+ mirrorContextOperations(ctx, this.suspendedCtx);
+ this.setGState([["BM", "source-over"], ["ca", 1], ["CA", 1]]);
+ }
+ endSMaskMode() {
+ if (!this.inSMaskMode) {
+ throw new Error("endSMaskMode called while not in smask mode");
+ }
+ this.ctx._removeMirroring();
+ copyCtxState(this.ctx, this.suspendedCtx);
+ this.ctx = this.suspendedCtx;
+ this.suspendedCtx = null;
+ }
+ compose(dirtyBox) {
+ if (!this.current.activeSMask) {
+ return;
+ }
+ if (!dirtyBox) {
+ dirtyBox = [0, 0, this.ctx.canvas.width, this.ctx.canvas.height];
+ } else {
+ dirtyBox[0] = Math.floor(dirtyBox[0]);
+ dirtyBox[1] = Math.floor(dirtyBox[1]);
+ dirtyBox[2] = Math.ceil(dirtyBox[2]);
+ dirtyBox[3] = Math.ceil(dirtyBox[3]);
+ }
+ const smask = this.current.activeSMask;
+ const suspendedCtx = this.suspendedCtx;
+ composeSMask(suspendedCtx, smask, this.ctx, dirtyBox);
+ this.ctx.save();
+ this.ctx.setTransform(1, 0, 0, 1, 0, 0);
+ this.ctx.clearRect(0, 0, this.ctx.canvas.width, this.ctx.canvas.height);
+ this.ctx.restore();
+ }
+ save() {
+ if (this.inSMaskMode) {
+ copyCtxState(this.ctx, this.suspendedCtx);
+ this.suspendedCtx.save();
+ } else {
+ this.ctx.save();
+ }
+ const old = this.current;
+ this.stateStack.push(old);
+ this.current = old.clone();
+ }
+ restore() {
+ if (this.stateStack.length === 0 && this.inSMaskMode) {
+ this.endSMaskMode();
+ }
+ if (this.stateStack.length !== 0) {
+ this.current = this.stateStack.pop();
+ if (this.inSMaskMode) {
+ this.suspendedCtx.restore();
+ copyCtxState(this.suspendedCtx, this.ctx);
+ } else {
+ this.ctx.restore();
+ }
+ this.checkSMaskState();
+ this.pendingClip = null;
+ this._cachedScaleForStroking[0] = -1;
+ this._cachedGetSinglePixelWidth = null;
+ }
+ }
+ transform(a, b, c, d, e, f) {
+ this.ctx.transform(a, b, c, d, e, f);
+ this._cachedScaleForStroking[0] = -1;
+ this._cachedGetSinglePixelWidth = null;
+ }
+ constructPath(ops, args, minMax) {
+ const ctx = this.ctx;
+ const current = this.current;
+ let x = current.x,
+ y = current.y;
+ let startX, startY;
+ const currentTransform = getCurrentTransform(ctx);
+ const isScalingMatrix = currentTransform[0] === 0 && currentTransform[3] === 0 || currentTransform[1] === 0 && currentTransform[2] === 0;
+ const minMaxForBezier = isScalingMatrix ? minMax.slice(0) : null;
+ for (let i = 0, j = 0, ii = ops.length; i < ii; i++) {
+ switch (ops[i] | 0) {
+ case OPS.rectangle:
+ x = args[j++];
+ y = args[j++];
+ const width = args[j++];
+ const height = args[j++];
+ const xw = x + width;
+ const yh = y + height;
+ ctx.moveTo(x, y);
+ if (width === 0 || height === 0) {
+ ctx.lineTo(xw, yh);
+ } else {
+ ctx.lineTo(xw, y);
+ ctx.lineTo(xw, yh);
+ ctx.lineTo(x, yh);
+ }
+ if (!isScalingMatrix) {
+ current.updateRectMinMax(currentTransform, [x, y, xw, yh]);
+ }
+ ctx.closePath();
+ break;
+ case OPS.moveTo:
+ x = args[j++];
+ y = args[j++];
+ ctx.moveTo(x, y);
+ if (!isScalingMatrix) {
+ current.updatePathMinMax(currentTransform, x, y);
+ }
+ break;
+ case OPS.lineTo:
+ x = args[j++];
+ y = args[j++];
+ ctx.lineTo(x, y);
+ if (!isScalingMatrix) {
+ current.updatePathMinMax(currentTransform, x, y);
+ }
+ break;
+ case OPS.curveTo:
+ startX = x;
+ startY = y;
+ x = args[j + 4];
+ y = args[j + 5];
+ ctx.bezierCurveTo(args[j], args[j + 1], args[j + 2], args[j + 3], x, y);
+ current.updateCurvePathMinMax(currentTransform, startX, startY, args[j], args[j + 1], args[j + 2], args[j + 3], x, y, minMaxForBezier);
+ j += 6;
+ break;
+ case OPS.curveTo2:
+ startX = x;
+ startY = y;
+ ctx.bezierCurveTo(x, y, args[j], args[j + 1], args[j + 2], args[j + 3]);
+ current.updateCurvePathMinMax(currentTransform, startX, startY, x, y, args[j], args[j + 1], args[j + 2], args[j + 3], minMaxForBezier);
+ x = args[j + 2];
+ y = args[j + 3];
+ j += 4;
+ break;
+ case OPS.curveTo3:
+ startX = x;
+ startY = y;
+ x = args[j + 2];
+ y = args[j + 3];
+ ctx.bezierCurveTo(args[j], args[j + 1], x, y, x, y);
+ current.updateCurvePathMinMax(currentTransform, startX, startY, args[j], args[j + 1], x, y, x, y, minMaxForBezier);
+ j += 4;
+ break;
+ case OPS.closePath:
+ ctx.closePath();
+ break;
+ }
+ }
+ if (isScalingMatrix) {
+ current.updateScalingPathMinMax(currentTransform, minMaxForBezier);
+ }
+ current.setCurrentPoint(x, y);
+ }
+ closePath() {
+ this.ctx.closePath();
+ }
+ stroke(consumePath = true) {
+ const ctx = this.ctx;
+ const strokeColor = this.current.strokeColor;
+ ctx.globalAlpha = this.current.strokeAlpha;
+ if (this.contentVisible) {
+ if (typeof strokeColor === "object" && strokeColor?.getPattern) {
+ ctx.save();
+ ctx.strokeStyle = strokeColor.getPattern(ctx, this, getCurrentTransformInverse(ctx), PathType.STROKE);
+ this.rescaleAndStroke(false);
+ ctx.restore();
+ } else {
+ this.rescaleAndStroke(true);
+ }
+ }
+ if (consumePath) {
+ this.consumePath(this.current.getClippedPathBoundingBox());
+ }
+ ctx.globalAlpha = this.current.fillAlpha;
+ }
+ closeStroke() {
+ this.closePath();
+ this.stroke();
+ }
+ fill(consumePath = true) {
+ const ctx = this.ctx;
+ const fillColor = this.current.fillColor;
+ const isPatternFill = this.current.patternFill;
+ let needRestore = false;
+ if (isPatternFill) {
+ ctx.save();
+ ctx.fillStyle = fillColor.getPattern(ctx, this, getCurrentTransformInverse(ctx), PathType.FILL);
+ needRestore = true;
+ }
+ const intersect = this.current.getClippedPathBoundingBox();
+ if (this.contentVisible && intersect !== null) {
+ if (this.pendingEOFill) {
+ ctx.fill("evenodd");
+ this.pendingEOFill = false;
+ } else {
+ ctx.fill();
+ }
+ }
+ if (needRestore) {
+ ctx.restore();
+ }
+ if (consumePath) {
+ this.consumePath(intersect);
+ }
+ }
+ eoFill() {
+ this.pendingEOFill = true;
+ this.fill();
+ }
+ fillStroke() {
+ this.fill(false);
+ this.stroke(false);
+ this.consumePath();
+ }
+ eoFillStroke() {
+ this.pendingEOFill = true;
+ this.fillStroke();
+ }
+ closeFillStroke() {
+ this.closePath();
+ this.fillStroke();
+ }
+ closeEOFillStroke() {
+ this.pendingEOFill = true;
+ this.closePath();
+ this.fillStroke();
+ }
+ endPath() {
+ this.consumePath();
+ }
+ clip() {
+ this.pendingClip = NORMAL_CLIP;
+ }
+ eoClip() {
+ this.pendingClip = EO_CLIP;
+ }
+ beginText() {
+ this.current.textMatrix = IDENTITY_MATRIX;
+ this.current.textMatrixScale = 1;
+ this.current.x = this.current.lineX = 0;
+ this.current.y = this.current.lineY = 0;
+ }
+ endText() {
+ const paths = this.pendingTextPaths;
+ const ctx = this.ctx;
+ if (paths === undefined) {
+ ctx.beginPath();
+ return;
+ }
+ ctx.save();
+ ctx.beginPath();
+ for (const path of paths) {
+ ctx.setTransform(...path.transform);
+ ctx.translate(path.x, path.y);
+ path.addToPath(ctx, path.fontSize);
+ }
+ ctx.restore();
+ ctx.clip();
+ ctx.beginPath();
+ delete this.pendingTextPaths;
+ }
+ setCharSpacing(spacing) {
+ this.current.charSpacing = spacing;
+ }
+ setWordSpacing(spacing) {
+ this.current.wordSpacing = spacing;
+ }
+ setHScale(scale) {
+ this.current.textHScale = scale / 100;
+ }
+ setLeading(leading) {
+ this.current.leading = -leading;
+ }
+ setFont(fontRefName, size) {
+ const fontObj = this.commonObjs.get(fontRefName);
+ const current = this.current;
+ if (!fontObj) {
+ throw new Error(`Can't find font for ${fontRefName}`);
+ }
+ current.fontMatrix = fontObj.fontMatrix || FONT_IDENTITY_MATRIX;
+ if (current.fontMatrix[0] === 0 || current.fontMatrix[3] === 0) {
+ warn("Invalid font matrix for font " + fontRefName);
+ }
+ if (size < 0) {
+ size = -size;
+ current.fontDirection = -1;
+ } else {
+ current.fontDirection = 1;
+ }
+ this.current.font = fontObj;
+ this.current.fontSize = size;
+ if (fontObj.isType3Font) {
+ return;
+ }
+ const name = fontObj.loadedName || "sans-serif";
+ const typeface = fontObj.systemFontInfo?.css || `"${name}", ${fontObj.fallbackName}`;
+ let bold = "normal";
+ if (fontObj.black) {
+ bold = "900";
+ } else if (fontObj.bold) {
+ bold = "bold";
+ }
+ const italic = fontObj.italic ? "italic" : "normal";
+ let browserFontSize = size;
+ if (size < MIN_FONT_SIZE) {
+ browserFontSize = MIN_FONT_SIZE;
+ } else if (size > MAX_FONT_SIZE) {
+ browserFontSize = MAX_FONT_SIZE;
+ }
+ this.current.fontSizeScale = size / browserFontSize;
+ this.ctx.font = `${italic} ${bold} ${browserFontSize}px ${typeface}`;
+ }
+ setTextRenderingMode(mode) {
+ this.current.textRenderingMode = mode;
+ }
+ setTextRise(rise) {
+ this.current.textRise = rise;
+ }
+ moveText(x, y) {
+ this.current.x = this.current.lineX += x;
+ this.current.y = this.current.lineY += y;
+ }
+ setLeadingMoveText(x, y) {
+ this.setLeading(-y);
+ this.moveText(x, y);
+ }
+ setTextMatrix(a, b, c, d, e, f) {
+ this.current.textMatrix = [a, b, c, d, e, f];
+ this.current.textMatrixScale = Math.hypot(a, b);
+ this.current.x = this.current.lineX = 0;
+ this.current.y = this.current.lineY = 0;
+ }
+ nextLine() {
+ this.moveText(0, this.current.leading);
+ }
+ paintChar(character, x, y, patternTransform) {
+ const ctx = this.ctx;
+ const current = this.current;
+ const font = current.font;
+ const textRenderingMode = current.textRenderingMode;
+ const fontSize = current.fontSize / current.fontSizeScale;
+ const fillStrokeMode = textRenderingMode & TextRenderingMode.FILL_STROKE_MASK;
+ const isAddToPathSet = !!(textRenderingMode & TextRenderingMode.ADD_TO_PATH_FLAG);
+ const patternFill = current.patternFill && !font.missingFile;
+ let addToPath;
+ if (font.disableFontFace || isAddToPathSet || patternFill) {
+ addToPath = font.getPathGenerator(this.commonObjs, character);
+ }
+ if (font.disableFontFace || patternFill) {
+ ctx.save();
+ ctx.translate(x, y);
+ ctx.beginPath();
+ addToPath(ctx, fontSize);
+ if (patternTransform) {
+ ctx.setTransform(...patternTransform);
+ }
+ if (fillStrokeMode === TextRenderingMode.FILL || fillStrokeMode === TextRenderingMode.FILL_STROKE) {
+ ctx.fill();
+ }
+ if (fillStrokeMode === TextRenderingMode.STROKE || fillStrokeMode === TextRenderingMode.FILL_STROKE) {
+ ctx.stroke();
+ }
+ ctx.restore();
+ } else {
+ if (fillStrokeMode === TextRenderingMode.FILL || fillStrokeMode === TextRenderingMode.FILL_STROKE) {
+ ctx.fillText(character, x, y);
+ }
+ if (fillStrokeMode === TextRenderingMode.STROKE || fillStrokeMode === TextRenderingMode.FILL_STROKE) {
+ ctx.strokeText(character, x, y);
+ }
+ }
+ if (isAddToPathSet) {
+ const paths = this.pendingTextPaths ||= [];
+ paths.push({
+ transform: getCurrentTransform(ctx),
+ x,
+ y,
+ fontSize,
+ addToPath
+ });
+ }
+ }
+ get isFontSubpixelAAEnabled() {
+ const {
+ context: ctx
+ } = this.cachedCanvases.getCanvas("isFontSubpixelAAEnabled", 10, 10);
+ ctx.scale(1.5, 1);
+ ctx.fillText("I", 0, 10);
+ const data = ctx.getImageData(0, 0, 10, 10).data;
+ let enabled = false;
+ for (let i = 3; i < data.length; i += 4) {
+ if (data[i] > 0 && data[i] < 255) {
+ enabled = true;
+ break;
+ }
+ }
+ return shadow(this, "isFontSubpixelAAEnabled", enabled);
+ }
+ showText(glyphs) {
+ const current = this.current;
+ const font = current.font;
+ if (font.isType3Font) {
+ return this.showType3Text(glyphs);
+ }
+ const fontSize = current.fontSize;
+ if (fontSize === 0) {
+ return undefined;
+ }
+ const ctx = this.ctx;
+ const fontSizeScale = current.fontSizeScale;
+ const charSpacing = current.charSpacing;
+ const wordSpacing = current.wordSpacing;
+ const fontDirection = current.fontDirection;
+ const textHScale = current.textHScale * fontDirection;
+ const glyphsLength = glyphs.length;
+ const vertical = font.vertical;
+ const spacingDir = vertical ? 1 : -1;
+ const defaultVMetrics = font.defaultVMetrics;
+ const widthAdvanceScale = fontSize * current.fontMatrix[0];
+ const simpleFillText = current.textRenderingMode === TextRenderingMode.FILL && !font.disableFontFace && !current.patternFill;
+ ctx.save();
+ ctx.transform(...current.textMatrix);
+ ctx.translate(current.x, current.y + current.textRise);
+ if (fontDirection > 0) {
+ ctx.scale(textHScale, -1);
+ } else {
+ ctx.scale(textHScale, 1);
+ }
+ let patternTransform;
+ if (current.patternFill) {
+ ctx.save();
+ const pattern = current.fillColor.getPattern(ctx, this, getCurrentTransformInverse(ctx), PathType.FILL);
+ patternTransform = getCurrentTransform(ctx);
+ ctx.restore();
+ ctx.fillStyle = pattern;
+ }
+ let lineWidth = current.lineWidth;
+ const scale = current.textMatrixScale;
+ if (scale === 0 || lineWidth === 0) {
+ const fillStrokeMode = current.textRenderingMode & TextRenderingMode.FILL_STROKE_MASK;
+ if (fillStrokeMode === TextRenderingMode.STROKE || fillStrokeMode === TextRenderingMode.FILL_STROKE) {
+ lineWidth = this.getSinglePixelWidth();
+ }
+ } else {
+ lineWidth /= scale;
+ }
+ if (fontSizeScale !== 1.0) {
+ ctx.scale(fontSizeScale, fontSizeScale);
+ lineWidth /= fontSizeScale;
+ }
+ ctx.lineWidth = lineWidth;
+ if (font.isInvalidPDFjsFont) {
+ const chars = [];
+ let width = 0;
+ for (const glyph of glyphs) {
+ chars.push(glyph.unicode);
+ width += glyph.width;
+ }
+ ctx.fillText(chars.join(""), 0, 0);
+ current.x += width * widthAdvanceScale * textHScale;
+ ctx.restore();
+ this.compose();
+ return undefined;
+ }
+ let x = 0,
+ i;
+ for (i = 0; i < glyphsLength; ++i) {
+ const glyph = glyphs[i];
+ if (typeof glyph === "number") {
+ x += spacingDir * glyph * fontSize / 1000;
+ continue;
+ }
+ let restoreNeeded = false;
+ const spacing = (glyph.isSpace ? wordSpacing : 0) + charSpacing;
+ const character = glyph.fontChar;
+ const accent = glyph.accent;
+ let scaledX, scaledY;
+ let width = glyph.width;
+ if (vertical) {
+ const vmetric = glyph.vmetric || defaultVMetrics;
+ const vx = -(glyph.vmetric ? vmetric[1] : width * 0.5) * widthAdvanceScale;
+ const vy = vmetric[2] * widthAdvanceScale;
+ width = vmetric ? -vmetric[0] : width;
+ scaledX = vx / fontSizeScale;
+ scaledY = (x + vy) / fontSizeScale;
+ } else {
+ scaledX = x / fontSizeScale;
+ scaledY = 0;
+ }
+ if (font.remeasure && width > 0) {
+ const measuredWidth = ctx.measureText(character).width * 1000 / fontSize * fontSizeScale;
+ if (width < measuredWidth && this.isFontSubpixelAAEnabled) {
+ const characterScaleX = width / measuredWidth;
+ restoreNeeded = true;
+ ctx.save();
+ ctx.scale(characterScaleX, 1);
+ scaledX /= characterScaleX;
+ } else if (width !== measuredWidth) {
+ scaledX += (width - measuredWidth) / 2000 * fontSize / fontSizeScale;
+ }
+ }
+ if (this.contentVisible && (glyph.isInFont || font.missingFile)) {
+ if (simpleFillText && !accent) {
+ ctx.fillText(character, scaledX, scaledY);
+ } else {
+ this.paintChar(character, scaledX, scaledY, patternTransform);
+ if (accent) {
+ const scaledAccentX = scaledX + fontSize * accent.offset.x / fontSizeScale;
+ const scaledAccentY = scaledY - fontSize * accent.offset.y / fontSizeScale;
+ this.paintChar(accent.fontChar, scaledAccentX, scaledAccentY, patternTransform);
+ }
+ }
+ }
+ const charWidth = vertical ? width * widthAdvanceScale - spacing * fontDirection : width * widthAdvanceScale + spacing * fontDirection;
+ x += charWidth;
+ if (restoreNeeded) {
+ ctx.restore();
+ }
+ }
+ if (vertical) {
+ current.y -= x;
+ } else {
+ current.x += x * textHScale;
+ }
+ ctx.restore();
+ this.compose();
+ return undefined;
+ }
+ showType3Text(glyphs) {
+ const ctx = this.ctx;
+ const current = this.current;
+ const font = current.font;
+ const fontSize = current.fontSize;
+ const fontDirection = current.fontDirection;
+ const spacingDir = font.vertical ? 1 : -1;
+ const charSpacing = current.charSpacing;
+ const wordSpacing = current.wordSpacing;
+ const textHScale = current.textHScale * fontDirection;
+ const fontMatrix = current.fontMatrix || FONT_IDENTITY_MATRIX;
+ const glyphsLength = glyphs.length;
+ const isTextInvisible = current.textRenderingMode === TextRenderingMode.INVISIBLE;
+ let i, glyph, width, spacingLength;
+ if (isTextInvisible || fontSize === 0) {
+ return;
+ }
+ this._cachedScaleForStroking[0] = -1;
+ this._cachedGetSinglePixelWidth = null;
+ ctx.save();
+ ctx.transform(...current.textMatrix);
+ ctx.translate(current.x, current.y);
+ ctx.scale(textHScale, fontDirection);
+ for (i = 0; i < glyphsLength; ++i) {
+ glyph = glyphs[i];
+ if (typeof glyph === "number") {
+ spacingLength = spacingDir * glyph * fontSize / 1000;
+ this.ctx.translate(spacingLength, 0);
+ current.x += spacingLength * textHScale;
+ continue;
+ }
+ const spacing = (glyph.isSpace ? wordSpacing : 0) + charSpacing;
+ const operatorList = font.charProcOperatorList[glyph.operatorListId];
+ if (!operatorList) {
+ warn(`Type3 character "${glyph.operatorListId}" is not available.`);
+ continue;
+ }
+ if (this.contentVisible) {
+ this.processingType3 = glyph;
+ this.save();
+ ctx.scale(fontSize, fontSize);
+ ctx.transform(...fontMatrix);
+ this.executeOperatorList(operatorList);
+ this.restore();
+ }
+ const transformed = Util.applyTransform([glyph.width, 0], fontMatrix);
+ width = transformed[0] * fontSize + spacing;
+ ctx.translate(width, 0);
+ current.x += width * textHScale;
+ }
+ ctx.restore();
+ this.processingType3 = null;
+ }
+ setCharWidth(xWidth, yWidth) {}
+ setCharWidthAndBounds(xWidth, yWidth, llx, lly, urx, ury) {
+ this.ctx.rect(llx, lly, urx - llx, ury - lly);
+ this.ctx.clip();
+ this.endPath();
+ }
+ getColorN_Pattern(IR) {
+ let pattern;
+ if (IR[0] === "TilingPattern") {
+ const color = IR[1];
+ const baseTransform = this.baseTransform || getCurrentTransform(this.ctx);
+ const canvasGraphicsFactory = {
+ createCanvasGraphics: ctx => new CanvasGraphics(ctx, this.commonObjs, this.objs, this.canvasFactory, this.filterFactory, {
+ optionalContentConfig: this.optionalContentConfig,
+ markedContentStack: this.markedContentStack
+ })
+ };
+ pattern = new TilingPattern(IR, color, this.ctx, canvasGraphicsFactory, baseTransform);
+ } else {
+ pattern = this._getPattern(IR[1], IR[2]);
+ }
+ return pattern;
+ }
+ setStrokeColorN() {
+ this.current.strokeColor = this.getColorN_Pattern(arguments);
+ }
+ setFillColorN() {
+ this.current.fillColor = this.getColorN_Pattern(arguments);
+ this.current.patternFill = true;
+ }
+ setStrokeRGBColor(r, g, b) {
+ const color = Util.makeHexColor(r, g, b);
+ this.ctx.strokeStyle = color;
+ this.current.strokeColor = color;
+ }
+ setFillRGBColor(r, g, b) {
+ const color = Util.makeHexColor(r, g, b);
+ this.ctx.fillStyle = color;
+ this.current.fillColor = color;
+ this.current.patternFill = false;
+ }
+ _getPattern(objId, matrix = null) {
+ let pattern;
+ if (this.cachedPatterns.has(objId)) {
+ pattern = this.cachedPatterns.get(objId);
+ } else {
+ pattern = getShadingPattern(this.getObject(objId));
+ this.cachedPatterns.set(objId, pattern);
+ }
+ if (matrix) {
+ pattern.matrix = matrix;
+ }
+ return pattern;
+ }
+ shadingFill(objId) {
+ if (!this.contentVisible) {
+ return;
+ }
+ const ctx = this.ctx;
+ this.save();
+ const pattern = this._getPattern(objId);
+ ctx.fillStyle = pattern.getPattern(ctx, this, getCurrentTransformInverse(ctx), PathType.SHADING);
+ const inv = getCurrentTransformInverse(ctx);
+ if (inv) {
+ const {
+ width,
+ height
+ } = ctx.canvas;
+ const [x0, y0, x1, y1] = Util.getAxialAlignedBoundingBox([0, 0, width, height], inv);
+ this.ctx.fillRect(x0, y0, x1 - x0, y1 - y0);
+ } else {
+ this.ctx.fillRect(-1e10, -1e10, 2e10, 2e10);
+ }
+ this.compose(this.current.getClippedPathBoundingBox());
+ this.restore();
+ }
+ beginInlineImage() {
+ unreachable("Should not call beginInlineImage");
+ }
+ beginImageData() {
+ unreachable("Should not call beginImageData");
+ }
+ paintFormXObjectBegin(matrix, bbox) {
+ if (!this.contentVisible) {
+ return;
+ }
+ this.save();
+ this.baseTransformStack.push(this.baseTransform);
+ if (Array.isArray(matrix) && matrix.length === 6) {
+ this.transform(...matrix);
+ }
+ this.baseTransform = getCurrentTransform(this.ctx);
+ if (bbox) {
+ const width = bbox[2] - bbox[0];
+ const height = bbox[3] - bbox[1];
+ this.ctx.rect(bbox[0], bbox[1], width, height);
+ this.current.updateRectMinMax(getCurrentTransform(this.ctx), bbox);
+ this.clip();
+ this.endPath();
+ }
+ }
+ paintFormXObjectEnd() {
+ if (!this.contentVisible) {
+ return;
+ }
+ this.restore();
+ this.baseTransform = this.baseTransformStack.pop();
+ }
+ beginGroup(group) {
+ if (!this.contentVisible) {
+ return;
+ }
+ this.save();
+ if (this.inSMaskMode) {
+ this.endSMaskMode();
+ this.current.activeSMask = null;
+ }
+ const currentCtx = this.ctx;
+ if (!group.isolated) {
+ info("TODO: Support non-isolated groups.");
+ }
+ if (group.knockout) {
+ warn("Knockout groups not supported.");
+ }
+ const currentTransform = getCurrentTransform(currentCtx);
+ if (group.matrix) {
+ currentCtx.transform(...group.matrix);
+ }
+ if (!group.bbox) {
+ throw new Error("Bounding box is required.");
+ }
+ let bounds = Util.getAxialAlignedBoundingBox(group.bbox, getCurrentTransform(currentCtx));
+ const canvasBounds = [0, 0, currentCtx.canvas.width, currentCtx.canvas.height];
+ bounds = Util.intersect(bounds, canvasBounds) || [0, 0, 0, 0];
+ const offsetX = Math.floor(bounds[0]);
+ const offsetY = Math.floor(bounds[1]);
+ let drawnWidth = Math.max(Math.ceil(bounds[2]) - offsetX, 1);
+ let drawnHeight = Math.max(Math.ceil(bounds[3]) - offsetY, 1);
+ let scaleX = 1,
+ scaleY = 1;
+ if (drawnWidth > MAX_GROUP_SIZE) {
+ scaleX = drawnWidth / MAX_GROUP_SIZE;
+ drawnWidth = MAX_GROUP_SIZE;
+ }
+ if (drawnHeight > MAX_GROUP_SIZE) {
+ scaleY = drawnHeight / MAX_GROUP_SIZE;
+ drawnHeight = MAX_GROUP_SIZE;
+ }
+ this.current.startNewPathAndClipBox([0, 0, drawnWidth, drawnHeight]);
+ let cacheId = "groupAt" + this.groupLevel;
+ if (group.smask) {
+ cacheId += "_smask_" + this.smaskCounter++ % 2;
+ }
+ const scratchCanvas = this.cachedCanvases.getCanvas(cacheId, drawnWidth, drawnHeight);
+ const groupCtx = scratchCanvas.context;
+ groupCtx.scale(1 / scaleX, 1 / scaleY);
+ groupCtx.translate(-offsetX, -offsetY);
+ groupCtx.transform(...currentTransform);
+ if (group.smask) {
+ this.smaskStack.push({
+ canvas: scratchCanvas.canvas,
+ context: groupCtx,
+ offsetX,
+ offsetY,
+ scaleX,
+ scaleY,
+ subtype: group.smask.subtype,
+ backdrop: group.smask.backdrop,
+ transferMap: group.smask.transferMap || null,
+ startTransformInverse: null
+ });
+ } else {
+ currentCtx.setTransform(1, 0, 0, 1, 0, 0);
+ currentCtx.translate(offsetX, offsetY);
+ currentCtx.scale(scaleX, scaleY);
+ currentCtx.save();
+ }
+ copyCtxState(currentCtx, groupCtx);
+ this.ctx = groupCtx;
+ this.setGState([["BM", "source-over"], ["ca", 1], ["CA", 1]]);
+ this.groupStack.push(currentCtx);
+ this.groupLevel++;
+ }
+ endGroup(group) {
+ if (!this.contentVisible) {
+ return;
+ }
+ this.groupLevel--;
+ const groupCtx = this.ctx;
+ const ctx = this.groupStack.pop();
+ this.ctx = ctx;
+ this.ctx.imageSmoothingEnabled = false;
+ if (group.smask) {
+ this.tempSMask = this.smaskStack.pop();
+ this.restore();
+ } else {
+ this.ctx.restore();
+ const currentMtx = getCurrentTransform(this.ctx);
+ this.restore();
+ this.ctx.save();
+ this.ctx.setTransform(...currentMtx);
+ const dirtyBox = Util.getAxialAlignedBoundingBox([0, 0, groupCtx.canvas.width, groupCtx.canvas.height], currentMtx);
+ this.ctx.drawImage(groupCtx.canvas, 0, 0);
+ this.ctx.restore();
+ this.compose(dirtyBox);
+ }
+ }
+ beginAnnotation(id, rect, transform, matrix, hasOwnCanvas) {
+ this.#restoreInitialState();
+ resetCtxToDefault(this.ctx);
+ this.ctx.save();
+ this.save();
+ if (this.baseTransform) {
+ this.ctx.setTransform(...this.baseTransform);
+ }
+ if (Array.isArray(rect) && rect.length === 4) {
+ const width = rect[2] - rect[0];
+ const height = rect[3] - rect[1];
+ if (hasOwnCanvas && this.annotationCanvasMap) {
+ transform = transform.slice();
+ transform[4] -= rect[0];
+ transform[5] -= rect[1];
+ rect = rect.slice();
+ rect[0] = rect[1] = 0;
+ rect[2] = width;
+ rect[3] = height;
+ const [scaleX, scaleY] = Util.singularValueDecompose2dScale(getCurrentTransform(this.ctx));
+ const {
+ viewportScale
+ } = this;
+ const canvasWidth = Math.ceil(width * this.outputScaleX * viewportScale);
+ const canvasHeight = Math.ceil(height * this.outputScaleY * viewportScale);
+ this.annotationCanvas = this.canvasFactory.create(canvasWidth, canvasHeight);
+ const {
+ canvas,
+ context
+ } = this.annotationCanvas;
+ this.annotationCanvasMap.set(id, canvas);
+ this.annotationCanvas.savedCtx = this.ctx;
+ this.ctx = context;
+ this.ctx.save();
+ this.ctx.setTransform(scaleX, 0, 0, -scaleY, 0, height * scaleY);
+ resetCtxToDefault(this.ctx);
+ } else {
+ resetCtxToDefault(this.ctx);
+ this.ctx.rect(rect[0], rect[1], width, height);
+ this.ctx.clip();
+ this.endPath();
+ }
+ }
+ this.current = new CanvasExtraState(this.ctx.canvas.width, this.ctx.canvas.height);
+ this.transform(...transform);
+ this.transform(...matrix);
+ }
+ endAnnotation() {
+ if (this.annotationCanvas) {
+ this.ctx.restore();
+ this.#drawFilter();
+ this.ctx = this.annotationCanvas.savedCtx;
+ delete this.annotationCanvas.savedCtx;
+ delete this.annotationCanvas;
+ }
+ }
+ paintImageMaskXObject(img) {
+ if (!this.contentVisible) {
+ return;
+ }
+ const count = img.count;
+ img = this.getObject(img.data, img);
+ img.count = count;
+ const ctx = this.ctx;
+ const glyph = this.processingType3;
+ if (glyph) {
+ if (glyph.compiled === undefined) {
+ glyph.compiled = compileType3Glyph(img);
+ }
+ if (glyph.compiled) {
+ glyph.compiled(ctx);
+ return;
+ }
+ }
+ const mask = this._createMaskCanvas(img);
+ const maskCanvas = mask.canvas;
+ ctx.save();
+ ctx.setTransform(1, 0, 0, 1, 0, 0);
+ ctx.drawImage(maskCanvas, mask.offsetX, mask.offsetY);
+ ctx.restore();
+ this.compose();
+ }
+ paintImageMaskXObjectRepeat(img, scaleX, skewX = 0, skewY = 0, scaleY, positions) {
+ if (!this.contentVisible) {
+ return;
+ }
+ img = this.getObject(img.data, img);
+ const ctx = this.ctx;
+ ctx.save();
+ const currentTransform = getCurrentTransform(ctx);
+ ctx.transform(scaleX, skewX, skewY, scaleY, 0, 0);
+ const mask = this._createMaskCanvas(img);
+ ctx.setTransform(1, 0, 0, 1, mask.offsetX - currentTransform[4], mask.offsetY - currentTransform[5]);
+ for (let i = 0, ii = positions.length; i < ii; i += 2) {
+ const trans = Util.transform(currentTransform, [scaleX, skewX, skewY, scaleY, positions[i], positions[i + 1]]);
+ const [x, y] = Util.applyTransform([0, 0], trans);
+ ctx.drawImage(mask.canvas, x, y);
+ }
+ ctx.restore();
+ this.compose();
+ }
+ paintImageMaskXObjectGroup(images) {
+ if (!this.contentVisible) {
+ return;
+ }
+ const ctx = this.ctx;
+ const fillColor = this.current.fillColor;
+ const isPatternFill = this.current.patternFill;
+ for (const image of images) {
+ const {
+ data,
+ width,
+ height,
+ transform
+ } = image;
+ const maskCanvas = this.cachedCanvases.getCanvas("maskCanvas", width, height);
+ const maskCtx = maskCanvas.context;
+ maskCtx.save();
+ const img = this.getObject(data, image);
+ putBinaryImageMask(maskCtx, img);
+ maskCtx.globalCompositeOperation = "source-in";
+ maskCtx.fillStyle = isPatternFill ? fillColor.getPattern(maskCtx, this, getCurrentTransformInverse(ctx), PathType.FILL) : fillColor;
+ maskCtx.fillRect(0, 0, width, height);
+ maskCtx.restore();
+ ctx.save();
+ ctx.transform(...transform);
+ ctx.scale(1, -1);
+ drawImageAtIntegerCoords(ctx, maskCanvas.canvas, 0, 0, width, height, 0, -1, 1, 1);
+ ctx.restore();
+ }
+ this.compose();
+ }
+ paintImageXObject(objId) {
+ if (!this.contentVisible) {
+ return;
+ }
+ const imgData = this.getObject(objId);
+ if (!imgData) {
+ warn("Dependent image isn't ready yet");
+ return;
+ }
+ this.paintInlineImageXObject(imgData);
+ }
+ paintImageXObjectRepeat(objId, scaleX, scaleY, positions) {
+ if (!this.contentVisible) {
+ return;
+ }
+ const imgData = this.getObject(objId);
+ if (!imgData) {
+ warn("Dependent image isn't ready yet");
+ return;
+ }
+ const width = imgData.width;
+ const height = imgData.height;
+ const map = [];
+ for (let i = 0, ii = positions.length; i < ii; i += 2) {
+ map.push({
+ transform: [scaleX, 0, 0, scaleY, positions[i], positions[i + 1]],
+ x: 0,
+ y: 0,
+ w: width,
+ h: height
+ });
+ }
+ this.paintInlineImageXObjectGroup(imgData, map);
+ }
+ applyTransferMapsToCanvas(ctx) {
+ if (this.current.transferMaps !== "none") {
+ ctx.filter = this.current.transferMaps;
+ ctx.drawImage(ctx.canvas, 0, 0);
+ ctx.filter = "none";
+ }
+ return ctx.canvas;
+ }
+ applyTransferMapsToBitmap(imgData) {
+ if (this.current.transferMaps === "none") {
+ return imgData.bitmap;
+ }
+ const {
+ bitmap,
+ width,
+ height
+ } = imgData;
+ const tmpCanvas = this.cachedCanvases.getCanvas("inlineImage", width, height);
+ const tmpCtx = tmpCanvas.context;
+ tmpCtx.filter = this.current.transferMaps;
+ tmpCtx.drawImage(bitmap, 0, 0);
+ tmpCtx.filter = "none";
+ return tmpCanvas.canvas;
+ }
+ paintInlineImageXObject(imgData) {
+ if (!this.contentVisible) {
+ return;
+ }
+ const width = imgData.width;
+ const height = imgData.height;
+ const ctx = this.ctx;
+ this.save();
+ const {
+ filter
+ } = ctx;
+ if (filter !== "none" && filter !== "") {
+ ctx.filter = "none";
+ }
+ ctx.scale(1 / width, -1 / height);
+ let imgToPaint;
+ if (imgData.bitmap) {
+ imgToPaint = this.applyTransferMapsToBitmap(imgData);
+ } else if (typeof HTMLElement === "function" && imgData instanceof HTMLElement || !imgData.data) {
+ imgToPaint = imgData;
+ } else {
+ const tmpCanvas = this.cachedCanvases.getCanvas("inlineImage", width, height);
+ const tmpCtx = tmpCanvas.context;
+ putBinaryImageData(tmpCtx, imgData);
+ imgToPaint = this.applyTransferMapsToCanvas(tmpCtx);
+ }
+ const scaled = this._scaleImage(imgToPaint, getCurrentTransformInverse(ctx));
+ ctx.imageSmoothingEnabled = getImageSmoothingEnabled(getCurrentTransform(ctx), imgData.interpolate);
+ drawImageAtIntegerCoords(ctx, scaled.img, 0, 0, scaled.paintWidth, scaled.paintHeight, 0, -height, width, height);
+ this.compose();
+ this.restore();
+ }
+ paintInlineImageXObjectGroup(imgData, map) {
+ if (!this.contentVisible) {
+ return;
+ }
+ const ctx = this.ctx;
+ let imgToPaint;
+ if (imgData.bitmap) {
+ imgToPaint = imgData.bitmap;
+ } else {
+ const w = imgData.width;
+ const h = imgData.height;
+ const tmpCanvas = this.cachedCanvases.getCanvas("inlineImage", w, h);
+ const tmpCtx = tmpCanvas.context;
+ putBinaryImageData(tmpCtx, imgData);
+ imgToPaint = this.applyTransferMapsToCanvas(tmpCtx);
+ }
+ for (const entry of map) {
+ ctx.save();
+ ctx.transform(...entry.transform);
+ ctx.scale(1, -1);
+ drawImageAtIntegerCoords(ctx, imgToPaint, entry.x, entry.y, entry.w, entry.h, 0, -1, 1, 1);
+ ctx.restore();
+ }
+ this.compose();
+ }
+ paintSolidColorImageMask() {
+ if (!this.contentVisible) {
+ return;
+ }
+ this.ctx.fillRect(0, 0, 1, 1);
+ this.compose();
+ }
+ markPoint(tag) {}
+ markPointProps(tag, properties) {}
+ beginMarkedContent(tag) {
+ this.markedContentStack.push({
+ visible: true
+ });
+ }
+ beginMarkedContentProps(tag, properties) {
+ if (tag === "OC") {
+ this.markedContentStack.push({
+ visible: this.optionalContentConfig.isVisible(properties)
+ });
+ } else {
+ this.markedContentStack.push({
+ visible: true
+ });
+ }
+ this.contentVisible = this.isContentVisible();
+ }
+ endMarkedContent() {
+ this.markedContentStack.pop();
+ this.contentVisible = this.isContentVisible();
+ }
+ beginCompat() {}
+ endCompat() {}
+ consumePath(clipBox) {
+ const isEmpty = this.current.isEmptyClip();
+ if (this.pendingClip) {
+ this.current.updateClipFromPath();
+ }
+ if (!this.pendingClip) {
+ this.compose(clipBox);
+ }
+ const ctx = this.ctx;
+ if (this.pendingClip) {
+ if (!isEmpty) {
+ if (this.pendingClip === EO_CLIP) {
+ ctx.clip("evenodd");
+ } else {
+ ctx.clip();
+ }
+ }
+ this.pendingClip = null;
+ }
+ this.current.startNewPathAndClipBox(this.current.clipBox);
+ ctx.beginPath();
+ }
+ getSinglePixelWidth() {
+ if (!this._cachedGetSinglePixelWidth) {
+ const m = getCurrentTransform(this.ctx);
+ if (m[1] === 0 && m[2] === 0) {
+ this._cachedGetSinglePixelWidth = 1 / Math.min(Math.abs(m[0]), Math.abs(m[3]));
+ } else {
+ const absDet = Math.abs(m[0] * m[3] - m[2] * m[1]);
+ const normX = Math.hypot(m[0], m[2]);
+ const normY = Math.hypot(m[1], m[3]);
+ this._cachedGetSinglePixelWidth = Math.max(normX, normY) / absDet;
+ }
+ }
+ return this._cachedGetSinglePixelWidth;
+ }
+ getScaleForStroking() {
+ if (this._cachedScaleForStroking[0] === -1) {
+ const {
+ lineWidth
+ } = this.current;
+ const {
+ a,
+ b,
+ c,
+ d
+ } = this.ctx.getTransform();
+ let scaleX, scaleY;
+ if (b === 0 && c === 0) {
+ const normX = Math.abs(a);
+ const normY = Math.abs(d);
+ if (normX === normY) {
+ if (lineWidth === 0) {
+ scaleX = scaleY = 1 / normX;
+ } else {
+ const scaledLineWidth = normX * lineWidth;
+ scaleX = scaleY = scaledLineWidth < 1 ? 1 / scaledLineWidth : 1;
+ }
+ } else if (lineWidth === 0) {
+ scaleX = 1 / normX;
+ scaleY = 1 / normY;
+ } else {
+ const scaledXLineWidth = normX * lineWidth;
+ const scaledYLineWidth = normY * lineWidth;
+ scaleX = scaledXLineWidth < 1 ? 1 / scaledXLineWidth : 1;
+ scaleY = scaledYLineWidth < 1 ? 1 / scaledYLineWidth : 1;
+ }
+ } else {
+ const absDet = Math.abs(a * d - b * c);
+ const normX = Math.hypot(a, b);
+ const normY = Math.hypot(c, d);
+ if (lineWidth === 0) {
+ scaleX = normY / absDet;
+ scaleY = normX / absDet;
+ } else {
+ const baseArea = lineWidth * absDet;
+ scaleX = normY > baseArea ? normY / baseArea : 1;
+ scaleY = normX > baseArea ? normX / baseArea : 1;
+ }
+ }
+ this._cachedScaleForStroking[0] = scaleX;
+ this._cachedScaleForStroking[1] = scaleY;
+ }
+ return this._cachedScaleForStroking;
+ }
+ rescaleAndStroke(saveRestore) {
+ const {
+ ctx
+ } = this;
+ const {
+ lineWidth
+ } = this.current;
+ const [scaleX, scaleY] = this.getScaleForStroking();
+ ctx.lineWidth = lineWidth || 1;
+ if (scaleX === 1 && scaleY === 1) {
+ ctx.stroke();
+ return;
+ }
+ const dashes = ctx.getLineDash();
+ if (saveRestore) {
+ ctx.save();
+ }
+ ctx.scale(scaleX, scaleY);
+ if (dashes.length > 0) {
+ const scale = Math.max(scaleX, scaleY);
+ ctx.setLineDash(dashes.map(x => x / scale));
+ ctx.lineDashOffset /= scale;
+ }
+ ctx.stroke();
+ if (saveRestore) {
+ ctx.restore();
+ }
+ }
+ isContentVisible() {
+ for (let i = this.markedContentStack.length - 1; i >= 0; i--) {
+ if (!this.markedContentStack[i].visible) {
+ return false;
+ }
+ }
+ return true;
+ }
+}
+for (const op in OPS) {
+ if (CanvasGraphics.prototype[op] !== undefined) {
+ CanvasGraphics.prototype[OPS[op]] = CanvasGraphics.prototype[op];
+ }
+}
+
+;// CONCATENATED MODULE: ./src/display/text_layer.js
+
+
+const MAX_TEXT_DIVS_TO_RENDER = 100000;
+const DEFAULT_FONT_SIZE = 30;
+const DEFAULT_FONT_ASCENT = 0.8;
+const ascentCache = new Map();
+let _canvasContext = null;
+function getCtx() {
+ if (!_canvasContext) {
+ const canvas = document.createElement("canvas");
+ canvas.className = "hiddenCanvasElement";
+ document.body.append(canvas);
+ _canvasContext = canvas.getContext("2d", {
+ alpha: false
+ });
+ }
+ return _canvasContext;
+}
+function cleanupTextLayer() {
+ _canvasContext?.canvas.remove();
+ _canvasContext = null;
+}
+function getAscent(fontFamily) {
+ const cachedAscent = ascentCache.get(fontFamily);
+ if (cachedAscent) {
+ return cachedAscent;
+ }
+ const ctx = getCtx();
+ const savedFont = ctx.font;
+ ctx.canvas.width = ctx.canvas.height = DEFAULT_FONT_SIZE;
+ ctx.font = `${DEFAULT_FONT_SIZE}px ${fontFamily}`;
+ const metrics = ctx.measureText("");
+ let ascent = metrics.fontBoundingBoxAscent;
+ let descent = Math.abs(metrics.fontBoundingBoxDescent);
+ if (ascent) {
+ const ratio = ascent / (ascent + descent);
+ ascentCache.set(fontFamily, ratio);
+ ctx.canvas.width = ctx.canvas.height = 0;
+ ctx.font = savedFont;
+ return ratio;
+ }
+ ctx.strokeStyle = "red";
+ ctx.clearRect(0, 0, DEFAULT_FONT_SIZE, DEFAULT_FONT_SIZE);
+ ctx.strokeText("g", 0, 0);
+ let pixels = ctx.getImageData(0, 0, DEFAULT_FONT_SIZE, DEFAULT_FONT_SIZE).data;
+ descent = 0;
+ for (let i = pixels.length - 1 - 3; i >= 0; i -= 4) {
+ if (pixels[i] > 0) {
+ descent = Math.ceil(i / 4 / DEFAULT_FONT_SIZE);
+ break;
+ }
+ }
+ ctx.clearRect(0, 0, DEFAULT_FONT_SIZE, DEFAULT_FONT_SIZE);
+ ctx.strokeText("A", 0, DEFAULT_FONT_SIZE);
+ pixels = ctx.getImageData(0, 0, DEFAULT_FONT_SIZE, DEFAULT_FONT_SIZE).data;
+ ascent = 0;
+ for (let i = 0, ii = pixels.length; i < ii; i += 4) {
+ if (pixels[i] > 0) {
+ ascent = DEFAULT_FONT_SIZE - Math.floor(i / 4 / DEFAULT_FONT_SIZE);
+ break;
+ }
+ }
+ ctx.canvas.width = ctx.canvas.height = 0;
+ ctx.font = savedFont;
+ if (ascent) {
+ const ratio = ascent / (ascent + descent);
+ ascentCache.set(fontFamily, ratio);
+ return ratio;
+ }
+ ascentCache.set(fontFamily, DEFAULT_FONT_ASCENT);
+ return DEFAULT_FONT_ASCENT;
+}
+function appendText(task, geom, styles) {
+ const textDiv = document.createElement("span");
+ const textDivProperties = {
+ angle: 0,
+ canvasWidth: 0,
+ hasText: geom.str !== "",
+ hasEOL: geom.hasEOL,
+ fontSize: 0
+ };
+ task._textDivs.push(textDiv);
+ const tx = Util.transform(task._transform, geom.transform);
+ let angle = Math.atan2(tx[1], tx[0]);
+ const style = styles[geom.fontName];
+ if (style.vertical) {
+ angle += Math.PI / 2;
+ }
+ const fontFamily = task._fontInspectorEnabled && style.fontSubstitution || style.fontFamily;
+ const fontHeight = Math.hypot(tx[2], tx[3]);
+ const fontAscent = fontHeight * getAscent(fontFamily);
+ let left, top;
+ if (angle === 0) {
+ left = tx[4];
+ top = tx[5] - fontAscent;
+ } else {
+ left = tx[4] + fontAscent * Math.sin(angle);
+ top = tx[5] - fontAscent * Math.cos(angle);
+ }
+ const scaleFactorStr = "calc(var(--scale-factor)*";
+ const divStyle = textDiv.style;
+ if (task._container === task._rootContainer) {
+ divStyle.left = `${(100 * left / task._pageWidth).toFixed(2)}%`;
+ divStyle.top = `${(100 * top / task._pageHeight).toFixed(2)}%`;
+ } else {
+ divStyle.left = `${scaleFactorStr}${left.toFixed(2)}px)`;
+ divStyle.top = `${scaleFactorStr}${top.toFixed(2)}px)`;
+ }
+ divStyle.fontSize = `${scaleFactorStr}${fontHeight.toFixed(2)}px)`;
+ divStyle.fontFamily = fontFamily;
+ textDivProperties.fontSize = fontHeight;
+ textDiv.setAttribute("role", "presentation");
+ textDiv.textContent = geom.str;
+ textDiv.dir = geom.dir;
+ if (task._fontInspectorEnabled) {
+ textDiv.dataset.fontName = style.fontSubstitutionLoadedName || geom.fontName;
+ }
+ if (angle !== 0) {
+ textDivProperties.angle = angle * (180 / Math.PI);
+ }
+ let shouldScaleText = false;
+ if (geom.str.length > 1) {
+ shouldScaleText = true;
+ } else if (geom.str !== " " && geom.transform[0] !== geom.transform[3]) {
+ const absScaleX = Math.abs(geom.transform[0]),
+ absScaleY = Math.abs(geom.transform[3]);
+ if (absScaleX !== absScaleY && Math.max(absScaleX, absScaleY) / Math.min(absScaleX, absScaleY) > 1.5) {
+ shouldScaleText = true;
+ }
+ }
+ if (shouldScaleText) {
+ textDivProperties.canvasWidth = style.vertical ? geom.height : geom.width;
+ }
+ task._textDivProperties.set(textDiv, textDivProperties);
+ if (task._isReadableStream) {
+ task._layoutText(textDiv);
+ }
+}
+function layout(params) {
+ const {
+ div,
+ scale,
+ properties,
+ ctx,
+ prevFontSize,
+ prevFontFamily
+ } = params;
+ const {
+ style
+ } = div;
+ let transform = "";
+ if (properties.canvasWidth !== 0 && properties.hasText) {
+ const {
+ fontFamily
+ } = style;
+ const {
+ canvasWidth,
+ fontSize
+ } = properties;
+ if (prevFontSize !== fontSize || prevFontFamily !== fontFamily) {
+ ctx.font = `${fontSize * scale}px ${fontFamily}`;
+ params.prevFontSize = fontSize;
+ params.prevFontFamily = fontFamily;
+ }
+ const {
+ width
+ } = ctx.measureText(div.textContent);
+ if (width > 0) {
+ transform = `scaleX(${canvasWidth * scale / width})`;
+ }
+ }
+ if (properties.angle !== 0) {
+ transform = `rotate(${properties.angle}deg) ${transform}`;
+ }
+ if (transform.length > 0) {
+ style.transform = transform;
+ }
+}
+function render(task) {
+ if (task._canceled) {
+ return;
+ }
+ const textDivs = task._textDivs;
+ const capability = task._capability;
+ const textDivsLength = textDivs.length;
+ if (textDivsLength > MAX_TEXT_DIVS_TO_RENDER) {
+ capability.resolve();
+ return;
+ }
+ if (!task._isReadableStream) {
+ for (const textDiv of textDivs) {
+ task._layoutText(textDiv);
+ }
+ }
+ capability.resolve();
+}
+class TextLayerRenderTask {
+ constructor({
+ textContentSource,
+ container,
+ viewport,
+ textDivs,
+ textDivProperties,
+ textContentItemsStr
+ }) {
+ this._textContentSource = textContentSource;
+ this._isReadableStream = textContentSource instanceof ReadableStream;
+ this._container = this._rootContainer = container;
+ this._textDivs = textDivs || [];
+ this._textContentItemsStr = textContentItemsStr || [];
+ this._fontInspectorEnabled = !!globalThis.FontInspector?.enabled;
+ this._reader = null;
+ this._textDivProperties = textDivProperties || new WeakMap();
+ this._canceled = false;
+ this._capability = new PromiseCapability();
+ this._layoutTextParams = {
+ prevFontSize: null,
+ prevFontFamily: null,
+ div: null,
+ scale: viewport.scale * (globalThis.devicePixelRatio || 1),
+ properties: null,
+ ctx: getCtx()
+ };
+ const {
+ pageWidth,
+ pageHeight,
+ pageX,
+ pageY
+ } = viewport.rawDims;
+ this._transform = [1, 0, 0, -1, -pageX, pageY + pageHeight];
+ this._pageWidth = pageWidth;
+ this._pageHeight = pageHeight;
+ setLayerDimensions(container, viewport);
+ this._capability.promise.finally(() => {
+ this._layoutTextParams = null;
+ }).catch(() => {});
+ }
+ get promise() {
+ return this._capability.promise;
+ }
+ cancel() {
+ this._canceled = true;
+ if (this._reader) {
+ this._reader.cancel(new AbortException("TextLayer task cancelled.")).catch(() => {});
+ this._reader = null;
+ }
+ this._capability.reject(new AbortException("TextLayer task cancelled."));
+ }
+ _processItems(items, styleCache) {
+ for (const item of items) {
+ if (item.str === undefined) {
+ if (item.type === "beginMarkedContentProps" || item.type === "beginMarkedContent") {
+ const parent = this._container;
+ this._container = document.createElement("span");
+ this._container.classList.add("markedContent");
+ if (item.id !== null) {
+ this._container.setAttribute("id", `${item.id}`);
+ }
+ parent.append(this._container);
+ } else if (item.type === "endMarkedContent") {
+ this._container = this._container.parentNode;
+ }
+ continue;
+ }
+ this._textContentItemsStr.push(item.str);
+ appendText(this, item, styleCache);
+ }
+ }
+ _layoutText(textDiv) {
+ const textDivProperties = this._layoutTextParams.properties = this._textDivProperties.get(textDiv);
+ this._layoutTextParams.div = textDiv;
+ layout(this._layoutTextParams);
+ if (textDivProperties.hasText) {
+ this._container.append(textDiv);
+ }
+ if (textDivProperties.hasEOL) {
+ const br = document.createElement("br");
+ br.setAttribute("role", "presentation");
+ this._container.append(br);
+ }
+ }
+ _render() {
+ const capability = new PromiseCapability();
+ let styleCache = Object.create(null);
+ if (this._isReadableStream) {
+ const pump = () => {
+ this._reader.read().then(({
+ value,
+ done
+ }) => {
+ if (done) {
+ capability.resolve();
+ return;
+ }
+ Object.assign(styleCache, value.styles);
+ this._processItems(value.items, styleCache);
+ pump();
+ }, capability.reject);
+ };
+ this._reader = this._textContentSource.getReader();
+ pump();
+ } else if (this._textContentSource) {
+ const {
+ items,
+ styles
+ } = this._textContentSource;
+ this._processItems(items, styles);
+ capability.resolve();
+ } else {
+ throw new Error('No "textContentSource" parameter specified.');
+ }
+ capability.promise.then(() => {
+ styleCache = null;
+ render(this);
+ }, this._capability.reject);
+ }
+}
+function renderTextLayer(params) {
+ const task = new TextLayerRenderTask(params);
+ task._render();
+ return task;
+}
+function updateTextLayer({
+ container,
+ viewport,
+ textDivs,
+ textDivProperties,
+ mustRotate = true,
+ mustRescale = true
+}) {
+ if (mustRotate) {
+ setLayerDimensions(container, {
+ rotation: viewport.rotation
+ });
+ }
+ if (mustRescale) {
+ const ctx = getCtx();
+ const scale = viewport.scale * (globalThis.devicePixelRatio || 1);
+ const params = {
+ prevFontSize: null,
+ prevFontFamily: null,
+ div: null,
+ scale,
+ properties: null,
+ ctx
+ };
+ for (const div of textDivs) {
+ params.properties = textDivProperties.get(div);
+ params.div = div;
+ layout(params);
+ }
+ }
+}
+
+;// CONCATENATED MODULE: ./src/display/worker_options.js
+class GlobalWorkerOptions {
+ static #port = null;
+ static #src = "";
+ static get workerPort() {
+ return this.#port;
+ }
+ static set workerPort(val) {
+ if (!(typeof Worker !== "undefined" && val instanceof Worker) && val !== null) {
+ throw new Error("Invalid `workerPort` type.");
+ }
+ this.#port = val;
+ }
+ static get workerSrc() {
+ return this.#src;
+ }
+ static set workerSrc(val) {
+ if (typeof val !== "string") {
+ throw new Error("Invalid `workerSrc` type.");
+ }
+ this.#src = val;
+ }
+}
+
+;// CONCATENATED MODULE: ./src/shared/message_handler.js
+
+const CallbackKind = {
+ UNKNOWN: 0,
+ DATA: 1,
+ ERROR: 2
+};
+const StreamKind = {
+ UNKNOWN: 0,
+ CANCEL: 1,
+ CANCEL_COMPLETE: 2,
+ CLOSE: 3,
+ ENQUEUE: 4,
+ ERROR: 5,
+ PULL: 6,
+ PULL_COMPLETE: 7,
+ START_COMPLETE: 8
+};
+function wrapReason(reason) {
+ if (!(reason instanceof Error || typeof reason === "object" && reason !== null)) {
+ unreachable('wrapReason: Expected "reason" to be a (possibly cloned) Error.');
+ }
+ switch (reason.name) {
+ case "AbortException":
+ return new AbortException(reason.message);
+ case "MissingPDFException":
+ return new MissingPDFException(reason.message);
+ case "PasswordException":
+ return new PasswordException(reason.message, reason.code);
+ case "UnexpectedResponseException":
+ return new UnexpectedResponseException(reason.message, reason.status);
+ case "UnknownErrorException":
+ return new UnknownErrorException(reason.message, reason.details);
+ default:
+ return new UnknownErrorException(reason.message, reason.toString());
+ }
+}
+class MessageHandler {
+ constructor(sourceName, targetName, comObj) {
+ this.sourceName = sourceName;
+ this.targetName = targetName;
+ this.comObj = comObj;
+ this.callbackId = 1;
+ this.streamId = 1;
+ this.streamSinks = Object.create(null);
+ this.streamControllers = Object.create(null);
+ this.callbackCapabilities = Object.create(null);
+ this.actionHandler = Object.create(null);
+ this._onComObjOnMessage = event => {
+ const data = event.data;
+ if (data.targetName !== this.sourceName) {
+ return;
+ }
+ if (data.stream) {
+ this.#processStreamMessage(data);
+ return;
+ }
+ if (data.callback) {
+ const callbackId = data.callbackId;
+ const capability = this.callbackCapabilities[callbackId];
+ if (!capability) {
+ throw new Error(`Cannot resolve callback ${callbackId}`);
+ }
+ delete this.callbackCapabilities[callbackId];
+ if (data.callback === CallbackKind.DATA) {
+ capability.resolve(data.data);
+ } else if (data.callback === CallbackKind.ERROR) {
+ capability.reject(wrapReason(data.reason));
+ } else {
+ throw new Error("Unexpected callback case");
+ }
+ return;
+ }
+ const action = this.actionHandler[data.action];
+ if (!action) {
+ throw new Error(`Unknown action from worker: ${data.action}`);
+ }
+ if (data.callbackId) {
+ const cbSourceName = this.sourceName;
+ const cbTargetName = data.sourceName;
+ new Promise(function (resolve) {
+ resolve(action(data.data));
+ }).then(function (result) {
+ comObj.postMessage({
+ sourceName: cbSourceName,
+ targetName: cbTargetName,
+ callback: CallbackKind.DATA,
+ callbackId: data.callbackId,
+ data: result
+ });
+ }, function (reason) {
+ comObj.postMessage({
+ sourceName: cbSourceName,
+ targetName: cbTargetName,
+ callback: CallbackKind.ERROR,
+ callbackId: data.callbackId,
+ reason: wrapReason(reason)
+ });
+ });
+ return;
+ }
+ if (data.streamId) {
+ this.#createStreamSink(data);
+ return;
+ }
+ action(data.data);
+ };
+ comObj.addEventListener("message", this._onComObjOnMessage);
+ }
+ on(actionName, handler) {
+ const ah = this.actionHandler;
+ if (ah[actionName]) {
+ throw new Error(`There is already an actionName called "${actionName}"`);
+ }
+ ah[actionName] = handler;
+ }
+ send(actionName, data, transfers) {
+ this.comObj.postMessage({
+ sourceName: this.sourceName,
+ targetName: this.targetName,
+ action: actionName,
+ data
+ }, transfers);
+ }
+ sendWithPromise(actionName, data, transfers) {
+ const callbackId = this.callbackId++;
+ const capability = new PromiseCapability();
+ this.callbackCapabilities[callbackId] = capability;
+ try {
+ this.comObj.postMessage({
+ sourceName: this.sourceName,
+ targetName: this.targetName,
+ action: actionName,
+ callbackId,
+ data
+ }, transfers);
+ } catch (ex) {
+ capability.reject(ex);
+ }
+ return capability.promise;
+ }
+ sendWithStream(actionName, data, queueingStrategy, transfers) {
+ const streamId = this.streamId++,
+ sourceName = this.sourceName,
+ targetName = this.targetName,
+ comObj = this.comObj;
+ return new ReadableStream({
+ start: controller => {
+ const startCapability = new PromiseCapability();
+ this.streamControllers[streamId] = {
+ controller,
+ startCall: startCapability,
+ pullCall: null,
+ cancelCall: null,
+ isClosed: false
+ };
+ comObj.postMessage({
+ sourceName,
+ targetName,
+ action: actionName,
+ streamId,
+ data,
+ desiredSize: controller.desiredSize
+ }, transfers);
+ return startCapability.promise;
+ },
+ pull: controller => {
+ const pullCapability = new PromiseCapability();
+ this.streamControllers[streamId].pullCall = pullCapability;
+ comObj.postMessage({
+ sourceName,
+ targetName,
+ stream: StreamKind.PULL,
+ streamId,
+ desiredSize: controller.desiredSize
+ });
+ return pullCapability.promise;
+ },
+ cancel: reason => {
+ assert(reason instanceof Error, "cancel must have a valid reason");
+ const cancelCapability = new PromiseCapability();
+ this.streamControllers[streamId].cancelCall = cancelCapability;
+ this.streamControllers[streamId].isClosed = true;
+ comObj.postMessage({
+ sourceName,
+ targetName,
+ stream: StreamKind.CANCEL,
+ streamId,
+ reason: wrapReason(reason)
+ });
+ return cancelCapability.promise;
+ }
+ }, queueingStrategy);
+ }
+ #createStreamSink(data) {
+ const streamId = data.streamId,
+ sourceName = this.sourceName,
+ targetName = data.sourceName,
+ comObj = this.comObj;
+ const self = this,
+ action = this.actionHandler[data.action];
+ const streamSink = {
+ enqueue(chunk, size = 1, transfers) {
+ if (this.isCancelled) {
+ return;
+ }
+ const lastDesiredSize = this.desiredSize;
+ this.desiredSize -= size;
+ if (lastDesiredSize > 0 && this.desiredSize <= 0) {
+ this.sinkCapability = new PromiseCapability();
+ this.ready = this.sinkCapability.promise;
+ }
+ comObj.postMessage({
+ sourceName,
+ targetName,
+ stream: StreamKind.ENQUEUE,
+ streamId,
+ chunk
+ }, transfers);
+ },
+ close() {
+ if (this.isCancelled) {
+ return;
+ }
+ this.isCancelled = true;
+ comObj.postMessage({
+ sourceName,
+ targetName,
+ stream: StreamKind.CLOSE,
+ streamId
+ });
+ delete self.streamSinks[streamId];
+ },
+ error(reason) {
+ assert(reason instanceof Error, "error must have a valid reason");
+ if (this.isCancelled) {
+ return;
+ }
+ this.isCancelled = true;
+ comObj.postMessage({
+ sourceName,
+ targetName,
+ stream: StreamKind.ERROR,
+ streamId,
+ reason: wrapReason(reason)
+ });
+ },
+ sinkCapability: new PromiseCapability(),
+ onPull: null,
+ onCancel: null,
+ isCancelled: false,
+ desiredSize: data.desiredSize,
+ ready: null
+ };
+ streamSink.sinkCapability.resolve();
+ streamSink.ready = streamSink.sinkCapability.promise;
+ this.streamSinks[streamId] = streamSink;
+ new Promise(function (resolve) {
+ resolve(action(data.data, streamSink));
+ }).then(function () {
+ comObj.postMessage({
+ sourceName,
+ targetName,
+ stream: StreamKind.START_COMPLETE,
+ streamId,
+ success: true
+ });
+ }, function (reason) {
+ comObj.postMessage({
+ sourceName,
+ targetName,
+ stream: StreamKind.START_COMPLETE,
+ streamId,
+ reason: wrapReason(reason)
+ });
+ });
+ }
+ #processStreamMessage(data) {
+ const streamId = data.streamId,
+ sourceName = this.sourceName,
+ targetName = data.sourceName,
+ comObj = this.comObj;
+ const streamController = this.streamControllers[streamId],
+ streamSink = this.streamSinks[streamId];
+ switch (data.stream) {
+ case StreamKind.START_COMPLETE:
+ if (data.success) {
+ streamController.startCall.resolve();
+ } else {
+ streamController.startCall.reject(wrapReason(data.reason));
+ }
+ break;
+ case StreamKind.PULL_COMPLETE:
+ if (data.success) {
+ streamController.pullCall.resolve();
+ } else {
+ streamController.pullCall.reject(wrapReason(data.reason));
+ }
+ break;
+ case StreamKind.PULL:
+ if (!streamSink) {
+ comObj.postMessage({
+ sourceName,
+ targetName,
+ stream: StreamKind.PULL_COMPLETE,
+ streamId,
+ success: true
+ });
+ break;
+ }
+ if (streamSink.desiredSize <= 0 && data.desiredSize > 0) {
+ streamSink.sinkCapability.resolve();
+ }
+ streamSink.desiredSize = data.desiredSize;
+ new Promise(function (resolve) {
+ resolve(streamSink.onPull?.());
+ }).then(function () {
+ comObj.postMessage({
+ sourceName,
+ targetName,
+ stream: StreamKind.PULL_COMPLETE,
+ streamId,
+ success: true
+ });
+ }, function (reason) {
+ comObj.postMessage({
+ sourceName,
+ targetName,
+ stream: StreamKind.PULL_COMPLETE,
+ streamId,
+ reason: wrapReason(reason)
+ });
+ });
+ break;
+ case StreamKind.ENQUEUE:
+ assert(streamController, "enqueue should have stream controller");
+ if (streamController.isClosed) {
+ break;
+ }
+ streamController.controller.enqueue(data.chunk);
+ break;
+ case StreamKind.CLOSE:
+ assert(streamController, "close should have stream controller");
+ if (streamController.isClosed) {
+ break;
+ }
+ streamController.isClosed = true;
+ streamController.controller.close();
+ this.#deleteStreamController(streamController, streamId);
+ break;
+ case StreamKind.ERROR:
+ assert(streamController, "error should have stream controller");
+ streamController.controller.error(wrapReason(data.reason));
+ this.#deleteStreamController(streamController, streamId);
+ break;
+ case StreamKind.CANCEL_COMPLETE:
+ if (data.success) {
+ streamController.cancelCall.resolve();
+ } else {
+ streamController.cancelCall.reject(wrapReason(data.reason));
+ }
+ this.#deleteStreamController(streamController, streamId);
+ break;
+ case StreamKind.CANCEL:
+ if (!streamSink) {
+ break;
+ }
+ new Promise(function (resolve) {
+ resolve(streamSink.onCancel?.(wrapReason(data.reason)));
+ }).then(function () {
+ comObj.postMessage({
+ sourceName,
+ targetName,
+ stream: StreamKind.CANCEL_COMPLETE,
+ streamId,
+ success: true
+ });
+ }, function (reason) {
+ comObj.postMessage({
+ sourceName,
+ targetName,
+ stream: StreamKind.CANCEL_COMPLETE,
+ streamId,
+ reason: wrapReason(reason)
+ });
+ });
+ streamSink.sinkCapability.reject(wrapReason(data.reason));
+ streamSink.isCancelled = true;
+ delete this.streamSinks[streamId];
+ break;
+ default:
+ throw new Error("Unexpected stream case");
+ }
+ }
+ async #deleteStreamController(streamController, streamId) {
+ await Promise.allSettled([streamController.startCall?.promise, streamController.pullCall?.promise, streamController.cancelCall?.promise]);
+ delete this.streamControllers[streamId];
+ }
+ destroy() {
+ this.comObj.removeEventListener("message", this._onComObjOnMessage);
+ }
+}
+
+;// CONCATENATED MODULE: ./src/display/metadata.js
+
+class Metadata {
+ #metadataMap;
+ #data;
+ constructor({
+ parsedData,
+ rawData
+ }) {
+ this.#metadataMap = parsedData;
+ this.#data = rawData;
+ }
+ getRaw() {
+ return this.#data;
+ }
+ get(name) {
+ return this.#metadataMap.get(name) ?? null;
+ }
+ getAll() {
+ return objectFromMap(this.#metadataMap);
+ }
+ has(name) {
+ return this.#metadataMap.has(name);
+ }
+}
+
+;// CONCATENATED MODULE: ./src/display/optional_content_config.js
+
+
+const INTERNAL = Symbol("INTERNAL");
+class OptionalContentGroup {
+ #visible = true;
+ constructor(name, intent) {
+ this.name = name;
+ this.intent = intent;
+ }
+ get visible() {
+ return this.#visible;
+ }
+ _setVisible(internal, visible) {
+ if (internal !== INTERNAL) {
+ unreachable("Internal method `_setVisible` called.");
+ }
+ this.#visible = visible;
+ }
+}
+class OptionalContentConfig {
+ #cachedGetHash = null;
+ #groups = new Map();
+ #initialHash = null;
+ #order = null;
+ constructor(data) {
+ this.name = null;
+ this.creator = null;
+ if (data === null) {
+ return;
+ }
+ this.name = data.name;
+ this.creator = data.creator;
+ this.#order = data.order;
+ for (const group of data.groups) {
+ this.#groups.set(group.id, new OptionalContentGroup(group.name, group.intent));
+ }
+ if (data.baseState === "OFF") {
+ for (const group of this.#groups.values()) {
+ group._setVisible(INTERNAL, false);
+ }
+ }
+ for (const on of data.on) {
+ this.#groups.get(on)._setVisible(INTERNAL, true);
+ }
+ for (const off of data.off) {
+ this.#groups.get(off)._setVisible(INTERNAL, false);
+ }
+ this.#initialHash = this.getHash();
+ }
+ #evaluateVisibilityExpression(array) {
+ const length = array.length;
+ if (length < 2) {
+ return true;
+ }
+ const operator = array[0];
+ for (let i = 1; i < length; i++) {
+ const element = array[i];
+ let state;
+ if (Array.isArray(element)) {
+ state = this.#evaluateVisibilityExpression(element);
+ } else if (this.#groups.has(element)) {
+ state = this.#groups.get(element).visible;
+ } else {
+ warn(`Optional content group not found: ${element}`);
+ return true;
+ }
+ switch (operator) {
+ case "And":
+ if (!state) {
+ return false;
+ }
+ break;
+ case "Or":
+ if (state) {
+ return true;
+ }
+ break;
+ case "Not":
+ return !state;
+ default:
+ return true;
+ }
+ }
+ return operator === "And";
+ }
+ isVisible(group) {
+ if (this.#groups.size === 0) {
+ return true;
+ }
+ if (!group) {
+ info("Optional content group not defined.");
+ return true;
+ }
+ if (group.type === "OCG") {
+ if (!this.#groups.has(group.id)) {
+ warn(`Optional content group not found: ${group.id}`);
+ return true;
+ }
+ return this.#groups.get(group.id).visible;
+ } else if (group.type === "OCMD") {
+ if (group.expression) {
+ return this.#evaluateVisibilityExpression(group.expression);
+ }
+ if (!group.policy || group.policy === "AnyOn") {
+ for (const id of group.ids) {
+ if (!this.#groups.has(id)) {
+ warn(`Optional content group not found: ${id}`);
+ return true;
+ }
+ if (this.#groups.get(id).visible) {
+ return true;
+ }
+ }
+ return false;
+ } else if (group.policy === "AllOn") {
+ for (const id of group.ids) {
+ if (!this.#groups.has(id)) {
+ warn(`Optional content group not found: ${id}`);
+ return true;
+ }
+ if (!this.#groups.get(id).visible) {
+ return false;
+ }
+ }
+ return true;
+ } else if (group.policy === "AnyOff") {
+ for (const id of group.ids) {
+ if (!this.#groups.has(id)) {
+ warn(`Optional content group not found: ${id}`);
+ return true;
+ }
+ if (!this.#groups.get(id).visible) {
+ return true;
+ }
+ }
+ return false;
+ } else if (group.policy === "AllOff") {
+ for (const id of group.ids) {
+ if (!this.#groups.has(id)) {
+ warn(`Optional content group not found: ${id}`);
+ return true;
+ }
+ if (this.#groups.get(id).visible) {
+ return false;
+ }
+ }
+ return true;
+ }
+ warn(`Unknown optional content policy ${group.policy}.`);
+ return true;
+ }
+ warn(`Unknown group type ${group.type}.`);
+ return true;
+ }
+ setVisibility(id, visible = true) {
+ if (!this.#groups.has(id)) {
+ warn(`Optional content group not found: ${id}`);
+ return;
+ }
+ this.#groups.get(id)._setVisible(INTERNAL, !!visible);
+ this.#cachedGetHash = null;
+ }
+ get hasInitialVisibility() {
+ return this.#initialHash === null || this.getHash() === this.#initialHash;
+ }
+ getOrder() {
+ if (!this.#groups.size) {
+ return null;
+ }
+ if (this.#order) {
+ return this.#order.slice();
+ }
+ return [...this.#groups.keys()];
+ }
+ getGroups() {
+ return this.#groups.size > 0 ? objectFromMap(this.#groups) : null;
+ }
+ getGroup(id) {
+ return this.#groups.get(id) || null;
+ }
+ getHash() {
+ if (this.#cachedGetHash !== null) {
+ return this.#cachedGetHash;
+ }
+ const hash = new MurmurHash3_64();
+ for (const [id, group] of this.#groups) {
+ hash.update(`${id}:${group.visible}`);
+ }
+ return this.#cachedGetHash = hash.hexdigest();
+ }
+}
+
+;// CONCATENATED MODULE: ./src/display/transport_stream.js
+
+
+class PDFDataTransportStream {
+ constructor(pdfDataRangeTransport, {
+ disableRange = false,
+ disableStream = false
+ }) {
+ assert(pdfDataRangeTransport, 'PDFDataTransportStream - missing required "pdfDataRangeTransport" argument.');
+ const {
+ length,
+ initialData,
+ progressiveDone,
+ contentDispositionFilename
+ } = pdfDataRangeTransport;
+ this._queuedChunks = [];
+ this._progressiveDone = progressiveDone;
+ this._contentDispositionFilename = contentDispositionFilename;
+ if (initialData?.length > 0) {
+ const buffer = initialData instanceof Uint8Array && initialData.byteLength === initialData.buffer.byteLength ? initialData.buffer : new Uint8Array(initialData).buffer;
+ this._queuedChunks.push(buffer);
+ }
+ this._pdfDataRangeTransport = pdfDataRangeTransport;
+ this._isStreamingSupported = !disableStream;
+ this._isRangeSupported = !disableRange;
+ this._contentLength = length;
+ this._fullRequestReader = null;
+ this._rangeReaders = [];
+ pdfDataRangeTransport.addRangeListener((begin, chunk) => {
+ this._onReceiveData({
+ begin,
+ chunk
+ });
+ });
+ pdfDataRangeTransport.addProgressListener((loaded, total) => {
+ this._onProgress({
+ loaded,
+ total
+ });
+ });
+ pdfDataRangeTransport.addProgressiveReadListener(chunk => {
+ this._onReceiveData({
+ chunk
+ });
+ });
+ pdfDataRangeTransport.addProgressiveDoneListener(() => {
+ this._onProgressiveDone();
+ });
+ pdfDataRangeTransport.transportReady();
+ }
+ _onReceiveData({
+ begin,
+ chunk
+ }) {
+ const buffer = chunk instanceof Uint8Array && chunk.byteLength === chunk.buffer.byteLength ? chunk.buffer : new Uint8Array(chunk).buffer;
+ if (begin === undefined) {
+ if (this._fullRequestReader) {
+ this._fullRequestReader._enqueue(buffer);
+ } else {
+ this._queuedChunks.push(buffer);
+ }
+ } else {
+ const found = this._rangeReaders.some(function (rangeReader) {
+ if (rangeReader._begin !== begin) {
+ return false;
+ }
+ rangeReader._enqueue(buffer);
+ return true;
+ });
+ assert(found, "_onReceiveData - no `PDFDataTransportStreamRangeReader` instance found.");
+ }
+ }
+ get _progressiveDataLength() {
+ return this._fullRequestReader?._loaded ?? 0;
+ }
+ _onProgress(evt) {
+ if (evt.total === undefined) {
+ this._rangeReaders[0]?.onProgress?.({
+ loaded: evt.loaded
+ });
+ } else {
+ this._fullRequestReader?.onProgress?.({
+ loaded: evt.loaded,
+ total: evt.total
+ });
+ }
+ }
+ _onProgressiveDone() {
+ this._fullRequestReader?.progressiveDone();
+ this._progressiveDone = true;
+ }
+ _removeRangeReader(reader) {
+ const i = this._rangeReaders.indexOf(reader);
+ if (i >= 0) {
+ this._rangeReaders.splice(i, 1);
+ }
+ }
+ getFullReader() {
+ assert(!this._fullRequestReader, "PDFDataTransportStream.getFullReader can only be called once.");
+ const queuedChunks = this._queuedChunks;
+ this._queuedChunks = null;
+ return new PDFDataTransportStreamReader(this, queuedChunks, this._progressiveDone, this._contentDispositionFilename);
+ }
+ getRangeReader(begin, end) {
+ if (end <= this._progressiveDataLength) {
+ return null;
+ }
+ const reader = new PDFDataTransportStreamRangeReader(this, begin, end);
+ this._pdfDataRangeTransport.requestDataRange(begin, end);
+ this._rangeReaders.push(reader);
+ return reader;
+ }
+ cancelAllRequests(reason) {
+ this._fullRequestReader?.cancel(reason);
+ for (const reader of this._rangeReaders.slice(0)) {
+ reader.cancel(reason);
+ }
+ this._pdfDataRangeTransport.abort();
+ }
+}
+class PDFDataTransportStreamReader {
+ constructor(stream, queuedChunks, progressiveDone = false, contentDispositionFilename = null) {
+ this._stream = stream;
+ this._done = progressiveDone || false;
+ this._filename = isPdfFile(contentDispositionFilename) ? contentDispositionFilename : null;
+ this._queuedChunks = queuedChunks || [];
+ this._loaded = 0;
+ for (const chunk of this._queuedChunks) {
+ this._loaded += chunk.byteLength;
+ }
+ this._requests = [];
+ this._headersReady = Promise.resolve();
+ stream._fullRequestReader = this;
+ this.onProgress = null;
+ }
+ _enqueue(chunk) {
+ if (this._done) {
+ return;
+ }
+ if (this._requests.length > 0) {
+ const requestCapability = this._requests.shift();
+ requestCapability.resolve({
+ value: chunk,
+ done: false
+ });
+ } else {
+ this._queuedChunks.push(chunk);
+ }
+ this._loaded += chunk.byteLength;
+ }
+ get headersReady() {
+ return this._headersReady;
+ }
+ get filename() {
+ return this._filename;
+ }
+ get isRangeSupported() {
+ return this._stream._isRangeSupported;
+ }
+ get isStreamingSupported() {
+ return this._stream._isStreamingSupported;
+ }
+ get contentLength() {
+ return this._stream._contentLength;
+ }
+ async read() {
+ if (this._queuedChunks.length > 0) {
+ const chunk = this._queuedChunks.shift();
+ return {
+ value: chunk,
+ done: false
+ };
+ }
+ if (this._done) {
+ return {
+ value: undefined,
+ done: true
+ };
+ }
+ const requestCapability = new PromiseCapability();
+ this._requests.push(requestCapability);
+ return requestCapability.promise;
+ }
+ cancel(reason) {
+ this._done = true;
+ for (const requestCapability of this._requests) {
+ requestCapability.resolve({
+ value: undefined,
+ done: true
+ });
+ }
+ this._requests.length = 0;
+ }
+ progressiveDone() {
+ if (this._done) {
+ return;
+ }
+ this._done = true;
+ }
+}
+class PDFDataTransportStreamRangeReader {
+ constructor(stream, begin, end) {
+ this._stream = stream;
+ this._begin = begin;
+ this._end = end;
+ this._queuedChunk = null;
+ this._requests = [];
+ this._done = false;
+ this.onProgress = null;
+ }
+ _enqueue(chunk) {
+ if (this._done) {
+ return;
+ }
+ if (this._requests.length === 0) {
+ this._queuedChunk = chunk;
+ } else {
+ const requestsCapability = this._requests.shift();
+ requestsCapability.resolve({
+ value: chunk,
+ done: false
+ });
+ for (const requestCapability of this._requests) {
+ requestCapability.resolve({
+ value: undefined,
+ done: true
+ });
+ }
+ this._requests.length = 0;
+ }
+ this._done = true;
+ this._stream._removeRangeReader(this);
+ }
+ get isStreamingSupported() {
+ return false;
+ }
+ async read() {
+ if (this._queuedChunk) {
+ const chunk = this._queuedChunk;
+ this._queuedChunk = null;
+ return {
+ value: chunk,
+ done: false
+ };
+ }
+ if (this._done) {
+ return {
+ value: undefined,
+ done: true
+ };
+ }
+ const requestCapability = new PromiseCapability();
+ this._requests.push(requestCapability);
+ return requestCapability.promise;
+ }
+ cancel(reason) {
+ this._done = true;
+ for (const requestCapability of this._requests) {
+ requestCapability.resolve({
+ value: undefined,
+ done: true
+ });
+ }
+ this._requests.length = 0;
+ this._stream._removeRangeReader(this);
+ }
+}
+
+;// CONCATENATED MODULE: ./src/display/xfa_text.js
+class XfaText {
+ static textContent(xfa) {
+ const items = [];
+ const output = {
+ items,
+ styles: Object.create(null)
+ };
+ function walk(node) {
+ if (!node) {
+ return;
+ }
+ let str = null;
+ const name = node.name;
+ if (name === "#text") {
+ str = node.value;
+ } else if (!XfaText.shouldBuildText(name)) {
+ return;
+ } else if (node?.attributes?.textContent) {
+ str = node.attributes.textContent;
+ } else if (node.value) {
+ str = node.value;
+ }
+ if (str !== null) {
+ items.push({
+ str
+ });
+ }
+ if (!node.children) {
+ return;
+ }
+ for (const child of node.children) {
+ walk(child);
+ }
+ }
+ walk(xfa);
+ return output;
+ }
+ static shouldBuildText(name) {
+ return !(name === "textarea" || name === "input" || name === "option" || name === "select");
+ }
+}
+
+;// CONCATENATED MODULE: ./src/display/api.js
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+const DEFAULT_RANGE_CHUNK_SIZE = 65536;
+const RENDERING_CANCELLED_TIMEOUT = 100;
+const DELAYED_CLEANUP_TIMEOUT = 5000;
+const DefaultCanvasFactory = DOMCanvasFactory;
+const DefaultCMapReaderFactory = DOMCMapReaderFactory;
+const DefaultFilterFactory = DOMFilterFactory;
+const DefaultStandardFontDataFactory = DOMStandardFontDataFactory;
+function getDocument(src) {
+ if (typeof src !== "object") {
+ throw new Error("Invalid parameter in getDocument, need parameter object.");
+ }
+ if (!src.url && !src.data && !src.range) {
+ throw new Error("Invalid parameter object: need either .data, .range or .url");
+ }
+ const task = new PDFDocumentLoadingTask();
+ const {
+ docId
+ } = task;
+ const url = src.url ? getUrlProp(src.url) : null;
+ const data = src.data ? getDataProp(src.data) : null;
+ const httpHeaders = src.httpHeaders || null;
+ const withCredentials = src.withCredentials === true;
+ const password = src.password ?? null;
+ const rangeTransport = src.range instanceof PDFDataRangeTransport ? src.range : null;
+ const rangeChunkSize = Number.isInteger(src.rangeChunkSize) && src.rangeChunkSize > 0 ? src.rangeChunkSize : DEFAULT_RANGE_CHUNK_SIZE;
+ let worker = src.worker instanceof PDFWorker ? src.worker : null;
+ const verbosity = src.verbosity;
+ const docBaseUrl = typeof src.docBaseUrl === "string" && !isDataScheme(src.docBaseUrl) ? src.docBaseUrl : null;
+ const cMapUrl = typeof src.cMapUrl === "string" ? src.cMapUrl : null;
+ const cMapPacked = src.cMapPacked !== false;
+ const CMapReaderFactory = src.CMapReaderFactory || DefaultCMapReaderFactory;
+ const standardFontDataUrl = typeof src.standardFontDataUrl === "string" ? src.standardFontDataUrl : null;
+ const StandardFontDataFactory = src.StandardFontDataFactory || DefaultStandardFontDataFactory;
+ const ignoreErrors = src.stopAtErrors !== true;
+ const maxImageSize = Number.isInteger(src.maxImageSize) && src.maxImageSize > -1 ? src.maxImageSize : -1;
+ const isEvalSupported = src.isEvalSupported !== false;
+ const isOffscreenCanvasSupported = typeof src.isOffscreenCanvasSupported === "boolean" ? src.isOffscreenCanvasSupported : !isNodeJS;
+ const canvasMaxAreaInBytes = Number.isInteger(src.canvasMaxAreaInBytes) ? src.canvasMaxAreaInBytes : -1;
+ const disableFontFace = typeof src.disableFontFace === "boolean" ? src.disableFontFace : isNodeJS;
+ const fontExtraProperties = src.fontExtraProperties === true;
+ const enableXfa = src.enableXfa === true;
+ const ownerDocument = src.ownerDocument || globalThis.document;
+ const disableRange = src.disableRange === true;
+ const disableStream = src.disableStream === true;
+ const disableAutoFetch = src.disableAutoFetch === true;
+ const pdfBug = src.pdfBug === true;
+ const length = rangeTransport ? rangeTransport.length : src.length ?? NaN;
+ const useSystemFonts = typeof src.useSystemFonts === "boolean" ? src.useSystemFonts : !isNodeJS && !disableFontFace;
+ const useWorkerFetch = typeof src.useWorkerFetch === "boolean" ? src.useWorkerFetch : true;
+ const canvasFactory = src.canvasFactory || new DefaultCanvasFactory({
+ ownerDocument
+ });
+ const filterFactory = src.filterFactory || new DefaultFilterFactory({
+ docId,
+ ownerDocument
+ });
+ const styleElement = null;
+ setVerbosityLevel(verbosity);
+ const transportFactory = {
+ canvasFactory,
+ filterFactory
+ };
+ if (!useWorkerFetch) {
+ transportFactory.cMapReaderFactory = new CMapReaderFactory({
+ baseUrl: cMapUrl,
+ isCompressed: cMapPacked
+ });
+ transportFactory.standardFontDataFactory = new StandardFontDataFactory({
+ baseUrl: standardFontDataUrl
+ });
+ }
+ if (!worker) {
+ const workerParams = {
+ verbosity,
+ port: GlobalWorkerOptions.workerPort
+ };
+ worker = workerParams.port ? PDFWorker.fromPort(workerParams) : new PDFWorker(workerParams);
+ task._worker = worker;
+ }
+ const fetchDocParams = {
+ docId,
+ apiVersion: "4.1.249",
+ data,
+ password,
+ disableAutoFetch,
+ rangeChunkSize,
+ length,
+ docBaseUrl,
+ enableXfa,
+ evaluatorOptions: {
+ maxImageSize,
+ disableFontFace,
+ ignoreErrors,
+ isEvalSupported,
+ isOffscreenCanvasSupported,
+ canvasMaxAreaInBytes,
+ fontExtraProperties,
+ useSystemFonts,
+ cMapUrl: useWorkerFetch ? cMapUrl : null,
+ standardFontDataUrl: useWorkerFetch ? standardFontDataUrl : null
+ }
+ };
+ const transportParams = {
+ ignoreErrors,
+ isEvalSupported,
+ disableFontFace,
+ fontExtraProperties,
+ enableXfa,
+ ownerDocument,
+ disableAutoFetch,
+ pdfBug,
+ styleElement
+ };
+ worker.promise.then(function () {
+ if (task.destroyed) {
+ throw new Error("Loading aborted");
+ }
+ const workerIdPromise = _fetchDocument(worker, fetchDocParams);
+ const networkStreamPromise = new Promise(function (resolve) {
+ let networkStream;
+ if (rangeTransport) {
+ networkStream = new PDFDataTransportStream(rangeTransport, {
+ disableRange,
+ disableStream
+ });
+ } else if (!data) {
+ throw new Error("Not implemented: createPDFNetworkStream");
+ }
+ resolve(networkStream);
+ });
+ return Promise.all([workerIdPromise, networkStreamPromise]).then(function ([workerId, networkStream]) {
+ if (task.destroyed) {
+ throw new Error("Loading aborted");
+ }
+ const messageHandler = new MessageHandler(docId, workerId, worker.port);
+ const transport = new WorkerTransport(messageHandler, task, networkStream, transportParams, transportFactory);
+ task._transport = transport;
+ messageHandler.send("Ready", null);
+ });
+ }).catch(task._capability.reject);
+ return task;
+}
+async function _fetchDocument(worker, source) {
+ if (worker.destroyed) {
+ throw new Error("Worker was destroyed");
+ }
+ const workerId = await worker.messageHandler.sendWithPromise("GetDocRequest", source, source.data ? [source.data.buffer] : null);
+ if (worker.destroyed) {
+ throw new Error("Worker was destroyed");
+ }
+ return workerId;
+}
+function getUrlProp(val) {
+ return null;
+}
+function getDataProp(val) {
+ if (val instanceof Uint8Array && val.byteLength === val.buffer.byteLength) {
+ return val;
+ }
+ if (typeof val === "string") {
+ return stringToBytes(val);
+ }
+ if (val instanceof ArrayBuffer || ArrayBuffer.isView(val) || typeof val === "object" && !isNaN(val?.length)) {
+ return new Uint8Array(val);
+ }
+ throw new Error("Invalid PDF binary data: either TypedArray, " + "string, or array-like object is expected in the data property.");
+}
+class PDFDocumentLoadingTask {
+ static #docId = 0;
+ constructor() {
+ this._capability = new PromiseCapability();
+ this._transport = null;
+ this._worker = null;
+ this.docId = `d${PDFDocumentLoadingTask.#docId++}`;
+ this.destroyed = false;
+ this.onPassword = null;
+ this.onProgress = null;
+ }
+ get promise() {
+ return this._capability.promise;
+ }
+ async destroy() {
+ this.destroyed = true;
+ try {
+ if (this._worker?.port) {
+ this._worker._pendingDestroy = true;
+ }
+ await this._transport?.destroy();
+ } catch (ex) {
+ if (this._worker?.port) {
+ delete this._worker._pendingDestroy;
+ }
+ throw ex;
+ }
+ this._transport = null;
+ if (this._worker) {
+ this._worker.destroy();
+ this._worker = null;
+ }
+ }
+}
+class PDFDataRangeTransport {
+ constructor(length, initialData, progressiveDone = false, contentDispositionFilename = null) {
+ this.length = length;
+ this.initialData = initialData;
+ this.progressiveDone = progressiveDone;
+ this.contentDispositionFilename = contentDispositionFilename;
+ this._rangeListeners = [];
+ this._progressListeners = [];
+ this._progressiveReadListeners = [];
+ this._progressiveDoneListeners = [];
+ this._readyCapability = new PromiseCapability();
+ }
+ addRangeListener(listener) {
+ this._rangeListeners.push(listener);
+ }
+ addProgressListener(listener) {
+ this._progressListeners.push(listener);
+ }
+ addProgressiveReadListener(listener) {
+ this._progressiveReadListeners.push(listener);
+ }
+ addProgressiveDoneListener(listener) {
+ this._progressiveDoneListeners.push(listener);
+ }
+ onDataRange(begin, chunk) {
+ for (const listener of this._rangeListeners) {
+ listener(begin, chunk);
+ }
+ }
+ onDataProgress(loaded, total) {
+ this._readyCapability.promise.then(() => {
+ for (const listener of this._progressListeners) {
+ listener(loaded, total);
+ }
+ });
+ }
+ onDataProgressiveRead(chunk) {
+ this._readyCapability.promise.then(() => {
+ for (const listener of this._progressiveReadListeners) {
+ listener(chunk);
+ }
+ });
+ }
+ onDataProgressiveDone() {
+ this._readyCapability.promise.then(() => {
+ for (const listener of this._progressiveDoneListeners) {
+ listener();
+ }
+ });
+ }
+ transportReady() {
+ this._readyCapability.resolve();
+ }
+ requestDataRange(begin, end) {
+ unreachable("Abstract method PDFDataRangeTransport.requestDataRange");
+ }
+ abort() {}
+}
+class PDFDocumentProxy {
+ constructor(pdfInfo, transport) {
+ this._pdfInfo = pdfInfo;
+ this._transport = transport;
+ }
+ get annotationStorage() {
+ return this._transport.annotationStorage;
+ }
+ get filterFactory() {
+ return this._transport.filterFactory;
+ }
+ get numPages() {
+ return this._pdfInfo.numPages;
+ }
+ get fingerprints() {
+ return this._pdfInfo.fingerprints;
+ }
+ get isPureXfa() {
+ return shadow(this, "isPureXfa", !!this._transport._htmlForXfa);
+ }
+ get allXfaHtml() {
+ return this._transport._htmlForXfa;
+ }
+ getPage(pageNumber) {
+ return this._transport.getPage(pageNumber);
+ }
+ getPageIndex(ref) {
+ return this._transport.getPageIndex(ref);
+ }
+ getDestinations() {
+ return this._transport.getDestinations();
+ }
+ getDestination(id) {
+ return this._transport.getDestination(id);
+ }
+ getPageLabels() {
+ return this._transport.getPageLabels();
+ }
+ getPageLayout() {
+ return this._transport.getPageLayout();
+ }
+ getPageMode() {
+ return this._transport.getPageMode();
+ }
+ getViewerPreferences() {
+ return this._transport.getViewerPreferences();
+ }
+ getOpenAction() {
+ return this._transport.getOpenAction();
+ }
+ getAttachments() {
+ return this._transport.getAttachments();
+ }
+ getJSActions() {
+ return this._transport.getDocJSActions();
+ }
+ getOutline() {
+ return this._transport.getOutline();
+ }
+ getOptionalContentConfig() {
+ return this._transport.getOptionalContentConfig();
+ }
+ getPermissions() {
+ return this._transport.getPermissions();
+ }
+ getMetadata() {
+ return this._transport.getMetadata();
+ }
+ getMarkInfo() {
+ return this._transport.getMarkInfo();
+ }
+ getData() {
+ return this._transport.getData();
+ }
+ saveDocument() {
+ return this._transport.saveDocument();
+ }
+ getDownloadInfo() {
+ return this._transport.downloadInfoCapability.promise;
+ }
+ cleanup(keepLoadedFonts = false) {
+ return this._transport.startCleanup(keepLoadedFonts || this.isPureXfa);
+ }
+ destroy() {
+ return this.loadingTask.destroy();
+ }
+ get loadingParams() {
+ return this._transport.loadingParams;
+ }
+ get loadingTask() {
+ return this._transport.loadingTask;
+ }
+ getFieldObjects() {
+ return this._transport.getFieldObjects();
+ }
+ hasJSActions() {
+ return this._transport.hasJSActions();
+ }
+ getCalculationOrderIds() {
+ return this._transport.getCalculationOrderIds();
+ }
+}
+class PDFPageProxy {
+ #delayedCleanupTimeout = null;
+ #pendingCleanup = false;
+ constructor(pageIndex, pageInfo, transport, pdfBug = false) {
+ this._pageIndex = pageIndex;
+ this._pageInfo = pageInfo;
+ this._transport = transport;
+ this._stats = pdfBug ? new StatTimer() : null;
+ this._pdfBug = pdfBug;
+ this.commonObjs = transport.commonObjs;
+ this.objs = new PDFObjects();
+ this._maybeCleanupAfterRender = false;
+ this._intentStates = new Map();
+ this.destroyed = false;
+ }
+ get pageNumber() {
+ return this._pageIndex + 1;
+ }
+ get rotate() {
+ return this._pageInfo.rotate;
+ }
+ get ref() {
+ return this._pageInfo.ref;
+ }
+ get userUnit() {
+ return this._pageInfo.userUnit;
+ }
+ get view() {
+ return this._pageInfo.view;
+ }
+ getViewport({
+ scale,
+ rotation = this.rotate,
+ offsetX = 0,
+ offsetY = 0,
+ dontFlip = false
+ } = {}) {
+ return new PageViewport({
+ viewBox: this.view,
+ scale,
+ rotation,
+ offsetX,
+ offsetY,
+ dontFlip
+ });
+ }
+ getAnnotations({
+ intent = "display"
+ } = {}) {
+ const intentArgs = this._transport.getRenderingIntent(intent);
+ return this._transport.getAnnotations(this._pageIndex, intentArgs.renderingIntent);
+ }
+ getJSActions() {
+ return this._transport.getPageJSActions(this._pageIndex);
+ }
+ get filterFactory() {
+ return this._transport.filterFactory;
+ }
+ get isPureXfa() {
+ return shadow(this, "isPureXfa", !!this._transport._htmlForXfa);
+ }
+ async getXfa() {
+ return this._transport._htmlForXfa?.children[this._pageIndex] || null;
+ }
+ render({
+ canvasContext,
+ viewport,
+ intent = "display",
+ annotationMode = AnnotationMode.ENABLE,
+ transform = null,
+ background = null,
+ optionalContentConfigPromise = null,
+ annotationCanvasMap = null,
+ pageColors = null,
+ printAnnotationStorage = null
+ }) {
+ this._stats?.time("Overall");
+ const intentArgs = this._transport.getRenderingIntent(intent, annotationMode, printAnnotationStorage);
+ this.#pendingCleanup = false;
+ this.#abortDelayedCleanup();
+ if (!optionalContentConfigPromise) {
+ optionalContentConfigPromise = this._transport.getOptionalContentConfig();
+ }
+ let intentState = this._intentStates.get(intentArgs.cacheKey);
+ if (!intentState) {
+ intentState = Object.create(null);
+ this._intentStates.set(intentArgs.cacheKey, intentState);
+ }
+ if (intentState.streamReaderCancelTimeout) {
+ clearTimeout(intentState.streamReaderCancelTimeout);
+ intentState.streamReaderCancelTimeout = null;
+ }
+ const intentPrint = !!(intentArgs.renderingIntent & RenderingIntentFlag.PRINT);
+ if (!intentState.displayReadyCapability) {
+ intentState.displayReadyCapability = new PromiseCapability();
+ intentState.operatorList = {
+ fnArray: [],
+ argsArray: [],
+ lastChunk: false,
+ separateAnnots: null
+ };
+ this._stats?.time("Page Request");
+ this._pumpOperatorList(intentArgs);
+ }
+ const complete = error => {
+ intentState.renderTasks.delete(internalRenderTask);
+ if (this._maybeCleanupAfterRender || intentPrint) {
+ this.#pendingCleanup = true;
+ }
+ this.#tryCleanup(!intentPrint);
+ if (error) {
+ internalRenderTask.capability.reject(error);
+ this._abortOperatorList({
+ intentState,
+ reason: error instanceof Error ? error : new Error(error)
+ });
+ } else {
+ internalRenderTask.capability.resolve();
+ }
+ this._stats?.timeEnd("Rendering");
+ this._stats?.timeEnd("Overall");
+ };
+ const internalRenderTask = new InternalRenderTask({
+ callback: complete,
+ params: {
+ canvasContext,
+ viewport,
+ transform,
+ background
+ },
+ objs: this.objs,
+ commonObjs: this.commonObjs,
+ annotationCanvasMap,
+ operatorList: intentState.operatorList,
+ pageIndex: this._pageIndex,
+ canvasFactory: this._transport.canvasFactory,
+ filterFactory: this._transport.filterFactory,
+ useRequestAnimationFrame: !intentPrint,
+ pdfBug: this._pdfBug,
+ pageColors
+ });
+ (intentState.renderTasks ||= new Set()).add(internalRenderTask);
+ const renderTask = internalRenderTask.task;
+ Promise.all([intentState.displayReadyCapability.promise, optionalContentConfigPromise]).then(([transparency, optionalContentConfig]) => {
+ if (this.destroyed) {
+ complete();
+ return;
+ }
+ this._stats?.time("Rendering");
+ internalRenderTask.initializeGraphics({
+ transparency,
+ optionalContentConfig
+ });
+ internalRenderTask.operatorListChanged();
+ }).catch(complete);
+ return renderTask;
+ }
+ getOperatorList({
+ intent = "display",
+ annotationMode = AnnotationMode.ENABLE,
+ printAnnotationStorage = null
+ } = {}) {
+ throw new Error("Not implemented: getOperatorList");
+ }
+ streamTextContent({
+ includeMarkedContent = false,
+ disableNormalization = false
+ } = {}) {
+ const TEXT_CONTENT_CHUNK_SIZE = 100;
+ return this._transport.messageHandler.sendWithStream("GetTextContent", {
+ pageIndex: this._pageIndex,
+ includeMarkedContent: includeMarkedContent === true,
+ disableNormalization: disableNormalization === true
+ }, {
+ highWaterMark: TEXT_CONTENT_CHUNK_SIZE,
+ size(textContent) {
+ return textContent.items.length;
+ }
+ });
+ }
+ getTextContent(params = {}) {
+ if (this._transport._htmlForXfa) {
+ return this.getXfa().then(xfa => XfaText.textContent(xfa));
+ }
+ const readableStream = this.streamTextContent(params);
+ return new Promise(function (resolve, reject) {
+ function pump() {
+ reader.read().then(function ({
+ value,
+ done
+ }) {
+ if (done) {
+ resolve(textContent);
+ return;
+ }
+ Object.assign(textContent.styles, value.styles);
+ textContent.items.push(...value.items);
+ pump();
+ }, reject);
+ }
+ const reader = readableStream.getReader();
+ const textContent = {
+ items: [],
+ styles: Object.create(null)
+ };
+ pump();
+ });
+ }
+ getStructTree() {
+ return this._transport.getStructTree(this._pageIndex);
+ }
+ _destroy() {
+ this.destroyed = true;
+ const waitOn = [];
+ for (const intentState of this._intentStates.values()) {
+ this._abortOperatorList({
+ intentState,
+ reason: new Error("Page was destroyed."),
+ force: true
+ });
+ if (intentState.opListReadCapability) {
+ continue;
+ }
+ for (const internalRenderTask of intentState.renderTasks) {
+ waitOn.push(internalRenderTask.completed);
+ internalRenderTask.cancel();
+ }
+ }
+ this.objs.clear();
+ this.#pendingCleanup = false;
+ this.#abortDelayedCleanup();
+ return Promise.all(waitOn);
+ }
+ cleanup(resetStats = false) {
+ this.#pendingCleanup = true;
+ const success = this.#tryCleanup(false);
+ if (resetStats && success) {
+ this._stats &&= new StatTimer();
+ }
+ return success;
+ }
+ #tryCleanup(delayed = false) {
+ this.#abortDelayedCleanup();
+ if (!this.#pendingCleanup || this.destroyed) {
+ return false;
+ }
+ if (delayed) {
+ this.#delayedCleanupTimeout = setTimeout(() => {
+ this.#delayedCleanupTimeout = null;
+ this.#tryCleanup(false);
+ }, DELAYED_CLEANUP_TIMEOUT);
+ return false;
+ }
+ for (const {
+ renderTasks,
+ operatorList
+ } of this._intentStates.values()) {
+ if (renderTasks.size > 0 || !operatorList.lastChunk) {
+ return false;
+ }
+ }
+ this._intentStates.clear();
+ this.objs.clear();
+ this.#pendingCleanup = false;
+ return true;
+ }
+ #abortDelayedCleanup() {
+ if (this.#delayedCleanupTimeout) {
+ clearTimeout(this.#delayedCleanupTimeout);
+ this.#delayedCleanupTimeout = null;
+ }
+ }
+ _startRenderPage(transparency, cacheKey) {
+ const intentState = this._intentStates.get(cacheKey);
+ if (!intentState) {
+ return;
+ }
+ this._stats?.timeEnd("Page Request");
+ intentState.displayReadyCapability?.resolve(transparency);
+ }
+ _renderPageChunk(operatorListChunk, intentState) {
+ for (let i = 0, ii = operatorListChunk.length; i < ii; i++) {
+ intentState.operatorList.fnArray.push(operatorListChunk.fnArray[i]);
+ intentState.operatorList.argsArray.push(operatorListChunk.argsArray[i]);
+ }
+ intentState.operatorList.lastChunk = operatorListChunk.lastChunk;
+ intentState.operatorList.separateAnnots = operatorListChunk.separateAnnots;
+ for (const internalRenderTask of intentState.renderTasks) {
+ internalRenderTask.operatorListChanged();
+ }
+ if (operatorListChunk.lastChunk) {
+ this.#tryCleanup(true);
+ }
+ }
+ _pumpOperatorList({
+ renderingIntent,
+ cacheKey,
+ annotationStorageSerializable
+ }) {
+ const {
+ map,
+ transfer
+ } = annotationStorageSerializable;
+ const readableStream = this._transport.messageHandler.sendWithStream("GetOperatorList", {
+ pageIndex: this._pageIndex,
+ intent: renderingIntent,
+ cacheKey,
+ annotationStorage: map
+ }, transfer);
+ const reader = readableStream.getReader();
+ const intentState = this._intentStates.get(cacheKey);
+ intentState.streamReader = reader;
+ const pump = () => {
+ reader.read().then(({
+ value,
+ done
+ }) => {
+ if (done) {
+ intentState.streamReader = null;
+ return;
+ }
+ if (this._transport.destroyed) {
+ return;
+ }
+ this._renderPageChunk(value, intentState);
+ pump();
+ }, reason => {
+ intentState.streamReader = null;
+ if (this._transport.destroyed) {
+ return;
+ }
+ if (intentState.operatorList) {
+ intentState.operatorList.lastChunk = true;
+ for (const internalRenderTask of intentState.renderTasks) {
+ internalRenderTask.operatorListChanged();
+ }
+ this.#tryCleanup(true);
+ }
+ if (intentState.displayReadyCapability) {
+ intentState.displayReadyCapability.reject(reason);
+ } else if (intentState.opListReadCapability) {
+ intentState.opListReadCapability.reject(reason);
+ } else {
+ throw reason;
+ }
+ });
+ };
+ pump();
+ }
+ _abortOperatorList({
+ intentState,
+ reason,
+ force = false
+ }) {
+ if (!intentState.streamReader) {
+ return;
+ }
+ if (intentState.streamReaderCancelTimeout) {
+ clearTimeout(intentState.streamReaderCancelTimeout);
+ intentState.streamReaderCancelTimeout = null;
+ }
+ if (!force) {
+ if (intentState.renderTasks.size > 0) {
+ return;
+ }
+ if (reason instanceof RenderingCancelledException) {
+ let delay = RENDERING_CANCELLED_TIMEOUT;
+ if (reason.extraDelay > 0 && reason.extraDelay < 1000) {
+ delay += reason.extraDelay;
+ }
+ intentState.streamReaderCancelTimeout = setTimeout(() => {
+ intentState.streamReaderCancelTimeout = null;
+ this._abortOperatorList({
+ intentState,
+ reason,
+ force: true
+ });
+ }, delay);
+ return;
+ }
+ }
+ intentState.streamReader.cancel(new AbortException(reason.message)).catch(() => {});
+ intentState.streamReader = null;
+ if (this._transport.destroyed) {
+ return;
+ }
+ for (const [curCacheKey, curIntentState] of this._intentStates) {
+ if (curIntentState === intentState) {
+ this._intentStates.delete(curCacheKey);
+ break;
+ }
+ }
+ this.cleanup();
+ }
+ get stats() {
+ return this._stats;
+ }
+}
+class LoopbackPort {
+ #listeners = new Set();
+ #deferred = Promise.resolve();
+ postMessage(obj, transfer) {
+ const event = {
+ data: structuredClone(obj, transfer ? {
+ transfer
+ } : null)
+ };
+ this.#deferred.then(() => {
+ for (const listener of this.#listeners) {
+ listener.call(this, event);
+ }
+ });
+ }
+ addEventListener(name, listener) {
+ this.#listeners.add(listener);
+ }
+ removeEventListener(name, listener) {
+ this.#listeners.delete(listener);
+ }
+ terminate() {
+ this.#listeners.clear();
+ }
+}
+const PDFWorkerUtil = {
+ isWorkerDisabled: false,
+ fakeWorkerId: 0
+};
+class PDFWorker {
+ static #workerPorts;
+ constructor({
+ name = null,
+ port = null,
+ verbosity = getVerbosityLevel()
+ } = {}) {
+ this.name = name;
+ this.destroyed = false;
+ this.verbosity = verbosity;
+ this._readyCapability = new PromiseCapability();
+ this._port = null;
+ this._webWorker = null;
+ this._messageHandler = null;
+ this._initialize();
+ }
+ get promise() {
+ return this._readyCapability.promise;
+ }
+ get port() {
+ return this._port;
+ }
+ get messageHandler() {
+ return this._messageHandler;
+ }
+ _initializeFromPort(port) {
+ throw new Error("Not implemented: _initializeFromPort");
+ }
+ _initialize() {
+ if (!PDFWorkerUtil.isWorkerDisabled && !PDFWorker.#mainThreadWorkerMessageHandler) {
+ let {
+ workerSrc
+ } = PDFWorker;
+ try {
+ const worker = new Worker(workerSrc, {
+ type: "module"
+ });
+ const messageHandler = new MessageHandler("main", "worker", worker);
+ const terminateEarly = () => {
+ worker.removeEventListener("error", onWorkerError);
+ messageHandler.destroy();
+ worker.terminate();
+ if (this.destroyed) {
+ this._readyCapability.reject(new Error("Worker was destroyed"));
+ } else {
+ this._setupFakeWorker();
+ }
+ };
+ const onWorkerError = () => {
+ if (!this._webWorker) {
+ terminateEarly();
+ }
+ };
+ worker.addEventListener("error", onWorkerError);
+ messageHandler.on("test", data => {
+ worker.removeEventListener("error", onWorkerError);
+ if (this.destroyed) {
+ terminateEarly();
+ return;
+ }
+ if (data) {
+ this._messageHandler = messageHandler;
+ this._port = worker;
+ this._webWorker = worker;
+ this._readyCapability.resolve();
+ messageHandler.send("configure", {
+ verbosity: this.verbosity
+ });
+ } else {
+ this._setupFakeWorker();
+ messageHandler.destroy();
+ worker.terminate();
+ }
+ });
+ messageHandler.on("ready", data => {
+ worker.removeEventListener("error", onWorkerError);
+ if (this.destroyed) {
+ terminateEarly();
+ return;
+ }
+ try {
+ sendTest();
+ } catch {
+ this._setupFakeWorker();
+ }
+ });
+ const sendTest = () => {
+ const testObj = new Uint8Array();
+ messageHandler.send("test", testObj, [testObj.buffer]);
+ };
+ sendTest();
+ return;
+ } catch {
+ info("The worker has been disabled.");
+ }
+ }
+ this._setupFakeWorker();
+ }
+ _setupFakeWorker() {
+ if (!PDFWorkerUtil.isWorkerDisabled) {
+ warn("Setting up fake worker.");
+ PDFWorkerUtil.isWorkerDisabled = true;
+ }
+ PDFWorker._setupFakeWorkerGlobal.then(WorkerMessageHandler => {
+ if (this.destroyed) {
+ this._readyCapability.reject(new Error("Worker was destroyed"));
+ return;
+ }
+ const port = new LoopbackPort();
+ this._port = port;
+ const id = `fake${PDFWorkerUtil.fakeWorkerId++}`;
+ const workerHandler = new MessageHandler(id + "_worker", id, port);
+ WorkerMessageHandler.setup(workerHandler, port);
+ const messageHandler = new MessageHandler(id, id + "_worker", port);
+ this._messageHandler = messageHandler;
+ this._readyCapability.resolve();
+ messageHandler.send("configure", {
+ verbosity: this.verbosity
+ });
+ }).catch(reason => {
+ this._readyCapability.reject(new Error(`Setting up fake worker failed: "${reason.message}".`));
+ });
+ }
+ destroy() {
+ this.destroyed = true;
+ if (this._webWorker) {
+ this._webWorker.terminate();
+ this._webWorker = null;
+ }
+ PDFWorker.#workerPorts?.delete(this._port);
+ this._port = null;
+ if (this._messageHandler) {
+ this._messageHandler.destroy();
+ this._messageHandler = null;
+ }
+ }
+ static fromPort(params) {
+ throw new Error("Not implemented: fromPort");
+ }
+ static get workerSrc() {
+ if (GlobalWorkerOptions.workerSrc) {
+ return GlobalWorkerOptions.workerSrc;
+ }
+ throw new Error('No "GlobalWorkerOptions.workerSrc" specified.');
+ }
+ static get #mainThreadWorkerMessageHandler() {
+ try {
+ return globalThis.pdfjsWorker?.WorkerMessageHandler || null;
+ } catch {
+ return null;
+ }
+ }
+ static get _setupFakeWorkerGlobal() {
+ const loader = async () => {
+ if (this.#mainThreadWorkerMessageHandler) {
+ return this.#mainThreadWorkerMessageHandler;
+ }
+ const worker = await import( /*webpackIgnore: true*/this.workerSrc);
+ return worker.WorkerMessageHandler;
+ };
+ return shadow(this, "_setupFakeWorkerGlobal", loader());
+ }
+}
+class WorkerTransport {
+ #methodPromises = new Map();
+ #pageCache = new Map();
+ #pagePromises = new Map();
+ #passwordCapability = null;
+ constructor(messageHandler, loadingTask, networkStream, params, factory) {
+ this.messageHandler = messageHandler;
+ this.loadingTask = loadingTask;
+ this.commonObjs = new PDFObjects();
+ this.fontLoader = new FontLoader({
+ ownerDocument: params.ownerDocument,
+ styleElement: params.styleElement
+ });
+ this._params = params;
+ this.canvasFactory = factory.canvasFactory;
+ this.filterFactory = factory.filterFactory;
+ this.cMapReaderFactory = factory.cMapReaderFactory;
+ this.standardFontDataFactory = factory.standardFontDataFactory;
+ this.destroyed = false;
+ this.destroyCapability = null;
+ this._networkStream = networkStream;
+ this._fullReader = null;
+ this._lastProgress = null;
+ this.downloadInfoCapability = new PromiseCapability();
+ this.setupMessageHandler();
+ }
+ #cacheSimpleMethod(name, data = null) {
+ const cachedPromise = this.#methodPromises.get(name);
+ if (cachedPromise) {
+ return cachedPromise;
+ }
+ const promise = this.messageHandler.sendWithPromise(name, data);
+ this.#methodPromises.set(name, promise);
+ return promise;
+ }
+ get annotationStorage() {
+ return shadow(this, "annotationStorage", new AnnotationStorage());
+ }
+ getRenderingIntent(intent, annotationMode = AnnotationMode.ENABLE, printAnnotationStorage = null, isOpList = false) {
+ let renderingIntent = RenderingIntentFlag.DISPLAY;
+ let annotationStorageSerializable = SerializableEmpty;
+ switch (intent) {
+ case "any":
+ renderingIntent = RenderingIntentFlag.ANY;
+ break;
+ case "display":
+ break;
+ case "print":
+ renderingIntent = RenderingIntentFlag.PRINT;
+ break;
+ default:
+ warn(`getRenderingIntent - invalid intent: ${intent}`);
+ }
+ switch (annotationMode) {
+ case AnnotationMode.DISABLE:
+ renderingIntent += RenderingIntentFlag.ANNOTATIONS_DISABLE;
+ break;
+ case AnnotationMode.ENABLE:
+ break;
+ case AnnotationMode.ENABLE_FORMS:
+ renderingIntent += RenderingIntentFlag.ANNOTATIONS_FORMS;
+ break;
+ case AnnotationMode.ENABLE_STORAGE:
+ renderingIntent += RenderingIntentFlag.ANNOTATIONS_STORAGE;
+ const annotationStorage = renderingIntent & RenderingIntentFlag.PRINT && printAnnotationStorage instanceof PrintAnnotationStorage ? printAnnotationStorage : this.annotationStorage;
+ annotationStorageSerializable = annotationStorage.serializable;
+ break;
+ default:
+ warn(`getRenderingIntent - invalid annotationMode: ${annotationMode}`);
+ }
+ if (isOpList) {
+ renderingIntent += RenderingIntentFlag.OPLIST;
+ }
+ return {
+ renderingIntent,
+ cacheKey: `${renderingIntent}_${annotationStorageSerializable.hash}`,
+ annotationStorageSerializable
+ };
+ }
+ destroy() {
+ if (this.destroyCapability) {
+ return this.destroyCapability.promise;
+ }
+ this.destroyed = true;
+ this.destroyCapability = new PromiseCapability();
+ this.#passwordCapability?.reject(new Error("Worker was destroyed during onPassword callback"));
+ const waitOn = [];
+ for (const page of this.#pageCache.values()) {
+ waitOn.push(page._destroy());
+ }
+ this.#pageCache.clear();
+ this.#pagePromises.clear();
+ if (this.hasOwnProperty("annotationStorage")) {
+ this.annotationStorage.resetModified();
+ }
+ const terminated = this.messageHandler.sendWithPromise("Terminate", null);
+ waitOn.push(terminated);
+ Promise.all(waitOn).then(() => {
+ this.commonObjs.clear();
+ this.fontLoader.clear();
+ this.#methodPromises.clear();
+ this.filterFactory.destroy();
+ cleanupTextLayer();
+ this._networkStream?.cancelAllRequests(new AbortException("Worker was terminated."));
+ if (this.messageHandler) {
+ this.messageHandler.destroy();
+ this.messageHandler = null;
+ }
+ this.destroyCapability.resolve();
+ }, this.destroyCapability.reject);
+ return this.destroyCapability.promise;
+ }
+ setupMessageHandler() {
+ const {
+ messageHandler,
+ loadingTask
+ } = this;
+ messageHandler.on("GetReader", (data, sink) => {
+ assert(this._networkStream, "GetReader - no `IPDFStream` instance available.");
+ this._fullReader = this._networkStream.getFullReader();
+ this._fullReader.onProgress = evt => {
+ this._lastProgress = {
+ loaded: evt.loaded,
+ total: evt.total
+ };
+ };
+ sink.onPull = () => {
+ this._fullReader.read().then(function ({
+ value,
+ done
+ }) {
+ if (done) {
+ sink.close();
+ return;
+ }
+ assert(value instanceof ArrayBuffer, "GetReader - expected an ArrayBuffer.");
+ sink.enqueue(new Uint8Array(value), 1, [value]);
+ }).catch(reason => {
+ sink.error(reason);
+ });
+ };
+ sink.onCancel = reason => {
+ this._fullReader.cancel(reason);
+ sink.ready.catch(readyReason => {
+ if (this.destroyed) {
+ return;
+ }
+ throw readyReason;
+ });
+ };
+ });
+ messageHandler.on("ReaderHeadersReady", data => {
+ const headersCapability = new PromiseCapability();
+ const fullReader = this._fullReader;
+ fullReader.headersReady.then(() => {
+ if (!fullReader.isStreamingSupported || !fullReader.isRangeSupported) {
+ if (this._lastProgress) {
+ loadingTask.onProgress?.(this._lastProgress);
+ }
+ fullReader.onProgress = evt => {
+ loadingTask.onProgress?.({
+ loaded: evt.loaded,
+ total: evt.total
+ });
+ };
+ }
+ headersCapability.resolve({
+ isStreamingSupported: fullReader.isStreamingSupported,
+ isRangeSupported: fullReader.isRangeSupported,
+ contentLength: fullReader.contentLength
+ });
+ }, headersCapability.reject);
+ return headersCapability.promise;
+ });
+ messageHandler.on("GetRangeReader", (data, sink) => {
+ assert(this._networkStream, "GetRangeReader - no `IPDFStream` instance available.");
+ const rangeReader = this._networkStream.getRangeReader(data.begin, data.end);
+ if (!rangeReader) {
+ sink.close();
+ return;
+ }
+ sink.onPull = () => {
+ rangeReader.read().then(function ({
+ value,
+ done
+ }) {
+ if (done) {
+ sink.close();
+ return;
+ }
+ assert(value instanceof ArrayBuffer, "GetRangeReader - expected an ArrayBuffer.");
+ sink.enqueue(new Uint8Array(value), 1, [value]);
+ }).catch(reason => {
+ sink.error(reason);
+ });
+ };
+ sink.onCancel = reason => {
+ rangeReader.cancel(reason);
+ sink.ready.catch(readyReason => {
+ if (this.destroyed) {
+ return;
+ }
+ throw readyReason;
+ });
+ };
+ });
+ messageHandler.on("GetDoc", ({
+ pdfInfo
+ }) => {
+ this._numPages = pdfInfo.numPages;
+ this._htmlForXfa = pdfInfo.htmlForXfa;
+ delete pdfInfo.htmlForXfa;
+ loadingTask._capability.resolve(new PDFDocumentProxy(pdfInfo, this));
+ });
+ messageHandler.on("DocException", function (ex) {
+ let reason;
+ switch (ex.name) {
+ case "PasswordException":
+ reason = new PasswordException(ex.message, ex.code);
+ break;
+ case "InvalidPDFException":
+ reason = new InvalidPDFException(ex.message);
+ break;
+ case "MissingPDFException":
+ reason = new MissingPDFException(ex.message);
+ break;
+ case "UnexpectedResponseException":
+ reason = new UnexpectedResponseException(ex.message, ex.status);
+ break;
+ case "UnknownErrorException":
+ reason = new UnknownErrorException(ex.message, ex.details);
+ break;
+ default:
+ unreachable("DocException - expected a valid Error.");
+ }
+ loadingTask._capability.reject(reason);
+ });
+ messageHandler.on("PasswordRequest", exception => {
+ this.#passwordCapability = new PromiseCapability();
+ if (loadingTask.onPassword) {
+ const updatePassword = password => {
+ if (password instanceof Error) {
+ this.#passwordCapability.reject(password);
+ } else {
+ this.#passwordCapability.resolve({
+ password
+ });
+ }
+ };
+ try {
+ loadingTask.onPassword(updatePassword, exception.code);
+ } catch (ex) {
+ this.#passwordCapability.reject(ex);
+ }
+ } else {
+ this.#passwordCapability.reject(new PasswordException(exception.message, exception.code));
+ }
+ return this.#passwordCapability.promise;
+ });
+ messageHandler.on("DataLoaded", data => {
+ loadingTask.onProgress?.({
+ loaded: data.length,
+ total: data.length
+ });
+ this.downloadInfoCapability.resolve(data);
+ });
+ messageHandler.on("StartRenderPage", data => {
+ if (this.destroyed) {
+ return;
+ }
+ const page = this.#pageCache.get(data.pageIndex);
+ page._startRenderPage(data.transparency, data.cacheKey);
+ });
+ messageHandler.on("commonobj", ([id, type, exportedData]) => {
+ if (this.destroyed) {
+ return null;
+ }
+ if (this.commonObjs.has(id)) {
+ return null;
+ }
+ switch (type) {
+ case "Font":
+ const params = this._params;
+ if ("error" in exportedData) {
+ const exportedError = exportedData.error;
+ warn(`Error during font loading: ${exportedError}`);
+ this.commonObjs.resolve(id, exportedError);
+ break;
+ }
+ const inspectFont = params.pdfBug && globalThis.FontInspector?.enabled ? (font, url) => globalThis.FontInspector.fontAdded(font, url) : null;
+ const font = new FontFaceObject(exportedData, {
+ isEvalSupported: params.isEvalSupported,
+ disableFontFace: params.disableFontFace,
+ ignoreErrors: params.ignoreErrors,
+ inspectFont
+ });
+ this.fontLoader.bind(font).catch(() => messageHandler.sendWithPromise("FontFallback", {
+ id
+ })).finally(() => {
+ if (!params.fontExtraProperties && font.data) {
+ font.data = null;
+ }
+ this.commonObjs.resolve(id, font);
+ });
+ break;
+ case "CopyLocalImage":
+ const {
+ imageRef
+ } = exportedData;
+ assert(imageRef, "The imageRef must be defined.");
+ for (const pageProxy of this.#pageCache.values()) {
+ for (const [, data] of pageProxy.objs) {
+ if (data.ref !== imageRef) {
+ continue;
+ }
+ if (!data.dataLen) {
+ return null;
+ }
+ this.commonObjs.resolve(id, structuredClone(data));
+ return data.dataLen;
+ }
+ }
+ break;
+ case "FontPath":
+ case "Image":
+ case "Pattern":
+ this.commonObjs.resolve(id, exportedData);
+ break;
+ default:
+ throw new Error(`Got unknown common object type ${type}`);
+ }
+ return null;
+ });
+ messageHandler.on("obj", ([id, pageIndex, type, imageData]) => {
+ if (this.destroyed) {
+ return;
+ }
+ const pageProxy = this.#pageCache.get(pageIndex);
+ if (pageProxy.objs.has(id)) {
+ return;
+ }
+ if (pageProxy._intentStates.size === 0) {
+ imageData?.bitmap?.close();
+ return;
+ }
+ switch (type) {
+ case "Image":
+ pageProxy.objs.resolve(id, imageData);
+ if (imageData?.dataLen > MAX_IMAGE_SIZE_TO_CACHE) {
+ pageProxy._maybeCleanupAfterRender = true;
+ }
+ break;
+ case "Pattern":
+ pageProxy.objs.resolve(id, imageData);
+ break;
+ default:
+ throw new Error(`Got unknown object type ${type}`);
+ }
+ });
+ messageHandler.on("DocProgress", data => {
+ if (this.destroyed) {
+ return;
+ }
+ loadingTask.onProgress?.({
+ loaded: data.loaded,
+ total: data.total
+ });
+ });
+ messageHandler.on("FetchBuiltInCMap", data => {
+ if (this.destroyed) {
+ return Promise.reject(new Error("Worker was destroyed."));
+ }
+ if (!this.cMapReaderFactory) {
+ return Promise.reject(new Error("CMapReaderFactory not initialized, see the `useWorkerFetch` parameter."));
+ }
+ return this.cMapReaderFactory.fetch(data);
+ });
+ messageHandler.on("FetchStandardFontData", data => {
+ if (this.destroyed) {
+ return Promise.reject(new Error("Worker was destroyed."));
+ }
+ if (!this.standardFontDataFactory) {
+ return Promise.reject(new Error("StandardFontDataFactory not initialized, see the `useWorkerFetch` parameter."));
+ }
+ return this.standardFontDataFactory.fetch(data);
+ });
+ }
+ getData() {
+ return this.messageHandler.sendWithPromise("GetData", null);
+ }
+ saveDocument() {
+ if (this.annotationStorage.size <= 0) {
+ warn("saveDocument called while `annotationStorage` is empty, " + "please use the getData-method instead.");
+ }
+ const {
+ map,
+ transfer
+ } = this.annotationStorage.serializable;
+ return this.messageHandler.sendWithPromise("SaveDocument", {
+ isPureXfa: !!this._htmlForXfa,
+ numPages: this._numPages,
+ annotationStorage: map,
+ filename: this._fullReader?.filename ?? null
+ }, transfer).finally(() => {
+ this.annotationStorage.resetModified();
+ });
+ }
+ getPage(pageNumber) {
+ if (!Number.isInteger(pageNumber) || pageNumber <= 0 || pageNumber > this._numPages) {
+ return Promise.reject(new Error("Invalid page request."));
+ }
+ const pageIndex = pageNumber - 1,
+ cachedPromise = this.#pagePromises.get(pageIndex);
+ if (cachedPromise) {
+ return cachedPromise;
+ }
+ const promise = this.messageHandler.sendWithPromise("GetPage", {
+ pageIndex
+ }).then(pageInfo => {
+ if (this.destroyed) {
+ throw new Error("Transport destroyed");
+ }
+ const page = new PDFPageProxy(pageIndex, pageInfo, this, this._params.pdfBug);
+ this.#pageCache.set(pageIndex, page);
+ return page;
+ });
+ this.#pagePromises.set(pageIndex, promise);
+ return promise;
+ }
+ getPageIndex(ref) {
+ if (typeof ref !== "object" || ref === null || !Number.isInteger(ref.num) || ref.num < 0 || !Number.isInteger(ref.gen) || ref.gen < 0) {
+ return Promise.reject(new Error("Invalid pageIndex request."));
+ }
+ return this.messageHandler.sendWithPromise("GetPageIndex", {
+ num: ref.num,
+ gen: ref.gen
+ });
+ }
+ getAnnotations(pageIndex, intent) {
+ return this.messageHandler.sendWithPromise("GetAnnotations", {
+ pageIndex,
+ intent
+ });
+ }
+ getFieldObjects() {
+ return this.#cacheSimpleMethod("GetFieldObjects");
+ }
+ hasJSActions() {
+ return this.#cacheSimpleMethod("HasJSActions");
+ }
+ getCalculationOrderIds() {
+ return this.messageHandler.sendWithPromise("GetCalculationOrderIds", null);
+ }
+ getDestinations() {
+ return this.messageHandler.sendWithPromise("GetDestinations", null);
+ }
+ getDestination(id) {
+ if (typeof id !== "string") {
+ return Promise.reject(new Error("Invalid destination request."));
+ }
+ return this.messageHandler.sendWithPromise("GetDestination", {
+ id
+ });
+ }
+ getPageLabels() {
+ return this.messageHandler.sendWithPromise("GetPageLabels", null);
+ }
+ getPageLayout() {
+ return this.messageHandler.sendWithPromise("GetPageLayout", null);
+ }
+ getPageMode() {
+ return this.messageHandler.sendWithPromise("GetPageMode", null);
+ }
+ getViewerPreferences() {
+ return this.messageHandler.sendWithPromise("GetViewerPreferences", null);
+ }
+ getOpenAction() {
+ return this.messageHandler.sendWithPromise("GetOpenAction", null);
+ }
+ getAttachments() {
+ return this.messageHandler.sendWithPromise("GetAttachments", null);
+ }
+ getDocJSActions() {
+ return this.#cacheSimpleMethod("GetDocJSActions");
+ }
+ getPageJSActions(pageIndex) {
+ return this.messageHandler.sendWithPromise("GetPageJSActions", {
+ pageIndex
+ });
+ }
+ getStructTree(pageIndex) {
+ return this.messageHandler.sendWithPromise("GetStructTree", {
+ pageIndex
+ });
+ }
+ getOutline() {
+ return this.messageHandler.sendWithPromise("GetOutline", null);
+ }
+ getOptionalContentConfig() {
+ return this.messageHandler.sendWithPromise("GetOptionalContentConfig", null).then(results => new OptionalContentConfig(results));
+ }
+ getPermissions() {
+ return this.messageHandler.sendWithPromise("GetPermissions", null);
+ }
+ getMetadata() {
+ const name = "GetMetadata",
+ cachedPromise = this.#methodPromises.get(name);
+ if (cachedPromise) {
+ return cachedPromise;
+ }
+ const promise = this.messageHandler.sendWithPromise(name, null).then(results => ({
+ info: results[0],
+ metadata: results[1] ? new Metadata(results[1]) : null,
+ contentDispositionFilename: this._fullReader?.filename ?? null,
+ contentLength: this._fullReader?.contentLength ?? null
+ }));
+ this.#methodPromises.set(name, promise);
+ return promise;
+ }
+ getMarkInfo() {
+ return this.messageHandler.sendWithPromise("GetMarkInfo", null);
+ }
+ async startCleanup(keepLoadedFonts = false) {
+ if (this.destroyed) {
+ return;
+ }
+ await this.messageHandler.sendWithPromise("Cleanup", null);
+ for (const page of this.#pageCache.values()) {
+ const cleanupSuccessful = page.cleanup();
+ if (!cleanupSuccessful) {
+ throw new Error(`startCleanup: Page ${page.pageNumber} is currently rendering.`);
+ }
+ }
+ this.commonObjs.clear();
+ if (!keepLoadedFonts) {
+ this.fontLoader.clear();
+ }
+ this.#methodPromises.clear();
+ this.filterFactory.destroy(true);
+ cleanupTextLayer();
+ }
+ get loadingParams() {
+ const {
+ disableAutoFetch,
+ enableXfa
+ } = this._params;
+ return shadow(this, "loadingParams", {
+ disableAutoFetch,
+ enableXfa
+ });
+ }
+}
+class PDFObjects {
+ #objs = Object.create(null);
+ #ensureObj(objId) {
+ return this.#objs[objId] ||= {
+ capability: new PromiseCapability(),
+ data: null
+ };
+ }
+ get(objId, callback = null) {
+ if (callback) {
+ const obj = this.#ensureObj(objId);
+ obj.capability.promise.then(() => callback(obj.data));
+ return null;
+ }
+ const obj = this.#objs[objId];
+ if (!obj?.capability.settled) {
+ throw new Error(`Requesting object that isn't resolved yet ${objId}.`);
+ }
+ return obj.data;
+ }
+ has(objId) {
+ const obj = this.#objs[objId];
+ return obj?.capability.settled ?? false;
+ }
+ resolve(objId, data = null) {
+ const obj = this.#ensureObj(objId);
+ obj.data = data;
+ obj.capability.resolve();
+ }
+ clear() {
+ for (const objId in this.#objs) {
+ const {
+ data
+ } = this.#objs[objId];
+ data?.bitmap?.close();
+ }
+ this.#objs = Object.create(null);
+ }
+ *[Symbol.iterator]() {
+ for (const objId in this.#objs) {
+ const {
+ capability,
+ data
+ } = this.#objs[objId];
+ if (!capability.settled) {
+ continue;
+ }
+ yield [objId, data];
+ }
+ }
+}
+class RenderTask {
+ #internalRenderTask = null;
+ constructor(internalRenderTask) {
+ this.#internalRenderTask = internalRenderTask;
+ this.onContinue = null;
+ }
+ get promise() {
+ return this.#internalRenderTask.capability.promise;
+ }
+ cancel(extraDelay = 0) {
+ this.#internalRenderTask.cancel(null, extraDelay);
+ }
+ get separateAnnots() {
+ const {
+ separateAnnots
+ } = this.#internalRenderTask.operatorList;
+ if (!separateAnnots) {
+ return false;
+ }
+ const {
+ annotationCanvasMap
+ } = this.#internalRenderTask;
+ return separateAnnots.form || separateAnnots.canvas && annotationCanvasMap?.size > 0;
+ }
+}
+class InternalRenderTask {
+ static #canvasInUse = new WeakSet();
+ constructor({
+ callback,
+ params,
+ objs,
+ commonObjs,
+ annotationCanvasMap,
+ operatorList,
+ pageIndex,
+ canvasFactory,
+ filterFactory,
+ useRequestAnimationFrame = false,
+ pdfBug = false,
+ pageColors = null
+ }) {
+ this.callback = callback;
+ this.params = params;
+ this.objs = objs;
+ this.commonObjs = commonObjs;
+ this.annotationCanvasMap = annotationCanvasMap;
+ this.operatorListIdx = null;
+ this.operatorList = operatorList;
+ this._pageIndex = pageIndex;
+ this.canvasFactory = canvasFactory;
+ this.filterFactory = filterFactory;
+ this._pdfBug = pdfBug;
+ this.pageColors = pageColors;
+ this.running = false;
+ this.graphicsReadyCallback = null;
+ this.graphicsReady = false;
+ this._useRequestAnimationFrame = useRequestAnimationFrame === true && typeof window !== "undefined";
+ this.cancelled = false;
+ this.capability = new PromiseCapability();
+ this.task = new RenderTask(this);
+ this._cancelBound = this.cancel.bind(this);
+ this._continueBound = this._continue.bind(this);
+ this._scheduleNextBound = this._scheduleNext.bind(this);
+ this._nextBound = this._next.bind(this);
+ this._canvas = params.canvasContext.canvas;
+ }
+ get completed() {
+ return this.capability.promise.catch(function () {});
+ }
+ initializeGraphics({
+ transparency = false,
+ optionalContentConfig
+ }) {
+ if (this.cancelled) {
+ return;
+ }
+ if (this._canvas) {
+ if (InternalRenderTask.#canvasInUse.has(this._canvas)) {
+ throw new Error("Cannot use the same canvas during multiple render() operations. " + "Use different canvas or ensure previous operations were " + "cancelled or completed.");
+ }
+ InternalRenderTask.#canvasInUse.add(this._canvas);
+ }
+ if (this._pdfBug && globalThis.StepperManager?.enabled) {
+ this.stepper = globalThis.StepperManager.create(this._pageIndex);
+ this.stepper.init(this.operatorList);
+ this.stepper.nextBreakPoint = this.stepper.getNextBreakPoint();
+ }
+ const {
+ canvasContext,
+ viewport,
+ transform,
+ background
+ } = this.params;
+ this.gfx = new CanvasGraphics(canvasContext, this.commonObjs, this.objs, this.canvasFactory, this.filterFactory, {
+ optionalContentConfig
+ }, this.annotationCanvasMap, this.pageColors);
+ this.gfx.beginDrawing({
+ transform,
+ viewport,
+ transparency,
+ background
+ });
+ this.operatorListIdx = 0;
+ this.graphicsReady = true;
+ this.graphicsReadyCallback?.();
+ }
+ cancel(error = null, extraDelay = 0) {
+ this.running = false;
+ this.cancelled = true;
+ this.gfx?.endDrawing();
+ InternalRenderTask.#canvasInUse.delete(this._canvas);
+ this.callback(error || new RenderingCancelledException(`Rendering cancelled, page ${this._pageIndex + 1}`, extraDelay));
+ }
+ operatorListChanged() {
+ if (!this.graphicsReady) {
+ this.graphicsReadyCallback ||= this._continueBound;
+ return;
+ }
+ this.stepper?.updateOperatorList(this.operatorList);
+ if (this.running) {
+ return;
+ }
+ this._continue();
+ }
+ _continue() {
+ this.running = true;
+ if (this.cancelled) {
+ return;
+ }
+ if (this.task.onContinue) {
+ this.task.onContinue(this._scheduleNextBound);
+ } else {
+ this._scheduleNext();
+ }
+ }
+ _scheduleNext() {
+ if (this._useRequestAnimationFrame) {
+ window.requestAnimationFrame(() => {
+ this._nextBound().catch(this._cancelBound);
+ });
+ } else {
+ Promise.resolve().then(this._nextBound).catch(this._cancelBound);
+ }
+ }
+ async _next() {
+ if (this.cancelled) {
+ return;
+ }
+ this.operatorListIdx = this.gfx.executeOperatorList(this.operatorList, this.operatorListIdx, this._continueBound, this.stepper);
+ if (this.operatorListIdx === this.operatorList.argsArray.length) {
+ this.running = false;
+ if (this.operatorList.lastChunk) {
+ this.gfx.endDrawing();
+ InternalRenderTask.#canvasInUse.delete(this._canvas);
+ this.callback();
+ }
+ }
+ }
+}
+const version = "4.1.249";
+const build = "d07f37f44";
+
+;// CONCATENATED MODULE: ./src/shared/scripting_utils.js
+function makeColorComp(n) {
+ return Math.floor(Math.max(0, Math.min(1, n)) * 255).toString(16).padStart(2, "0");
+}
+function scaleAndClamp(x) {
+ return Math.max(0, Math.min(255, 255 * x));
+}
+class ColorConverters {
+ static CMYK_G([c, y, m, k]) {
+ return ["G", 1 - Math.min(1, 0.3 * c + 0.59 * m + 0.11 * y + k)];
+ }
+ static G_CMYK([g]) {
+ return ["CMYK", 0, 0, 0, 1 - g];
+ }
+ static G_RGB([g]) {
+ return ["RGB", g, g, g];
+ }
+ static G_rgb([g]) {
+ g = scaleAndClamp(g);
+ return [g, g, g];
+ }
+ static G_HTML([g]) {
+ const G = makeColorComp(g);
+ return `#${G}${G}${G}`;
+ }
+ static RGB_G([r, g, b]) {
+ return ["G", 0.3 * r + 0.59 * g + 0.11 * b];
+ }
+ static RGB_rgb(color) {
+ return color.map(scaleAndClamp);
+ }
+ static RGB_HTML(color) {
+ return `#${color.map(makeColorComp).join("")}`;
+ }
+ static T_HTML() {
+ return "#00000000";
+ }
+ static T_rgb() {
+ return [null];
+ }
+ static CMYK_RGB([c, y, m, k]) {
+ return ["RGB", 1 - Math.min(1, c + k), 1 - Math.min(1, m + k), 1 - Math.min(1, y + k)];
+ }
+ static CMYK_rgb([c, y, m, k]) {
+ return [scaleAndClamp(1 - Math.min(1, c + k)), scaleAndClamp(1 - Math.min(1, m + k)), scaleAndClamp(1 - Math.min(1, y + k))];
+ }
+ static CMYK_HTML(components) {
+ const rgb = this.CMYK_RGB(components).slice(1);
+ return this.RGB_HTML(rgb);
+ }
+ static RGB_CMYK([r, g, b]) {
+ const c = 1 - r;
+ const m = 1 - g;
+ const y = 1 - b;
+ const k = Math.min(c, m, y);
+ return ["CMYK", c, m, y, k];
+ }
+}
+
+;// CONCATENATED MODULE: ./src/display/xfa_layer.js
+
+class XfaLayer {
+ static setupStorage(html, id, element, storage, intent) {
+ const storedData = storage.getValue(id, {
+ value: null
+ });
+ switch (element.name) {
+ case "textarea":
+ if (storedData.value !== null) {
+ html.textContent = storedData.value;
+ }
+ if (intent === "print") {
+ break;
+ }
+ html.addEventListener("input", event => {
+ storage.setValue(id, {
+ value: event.target.value
+ });
+ });
+ break;
+ case "input":
+ if (element.attributes.type === "radio" || element.attributes.type === "checkbox") {
+ if (storedData.value === element.attributes.xfaOn) {
+ html.setAttribute("checked", true);
+ } else if (storedData.value === element.attributes.xfaOff) {
+ html.removeAttribute("checked");
+ }
+ if (intent === "print") {
+ break;
+ }
+ html.addEventListener("change", event => {
+ storage.setValue(id, {
+ value: event.target.checked ? event.target.getAttribute("xfaOn") : event.target.getAttribute("xfaOff")
+ });
+ });
+ } else {
+ if (storedData.value !== null) {
+ html.setAttribute("value", storedData.value);
+ }
+ if (intent === "print") {
+ break;
+ }
+ html.addEventListener("input", event => {
+ storage.setValue(id, {
+ value: event.target.value
+ });
+ });
+ }
+ break;
+ case "select":
+ if (storedData.value !== null) {
+ html.setAttribute("value", storedData.value);
+ for (const option of element.children) {
+ if (option.attributes.value === storedData.value) {
+ option.attributes.selected = true;
+ } else if (option.attributes.hasOwnProperty("selected")) {
+ delete option.attributes.selected;
+ }
+ }
+ }
+ html.addEventListener("input", event => {
+ const options = event.target.options;
+ const value = options.selectedIndex === -1 ? "" : options[options.selectedIndex].value;
+ storage.setValue(id, {
+ value
+ });
+ });
+ break;
+ }
+ }
+ static setAttributes({
+ html,
+ element,
+ storage = null,
+ intent,
+ linkService
+ }) {
+ const {
+ attributes
+ } = element;
+ const isHTMLAnchorElement = html instanceof HTMLAnchorElement;
+ if (attributes.type === "radio") {
+ attributes.name = `${attributes.name}-${intent}`;
+ }
+ for (const [key, value] of Object.entries(attributes)) {
+ if (value === null || value === undefined) {
+ continue;
+ }
+ switch (key) {
+ case "class":
+ if (value.length) {
+ html.setAttribute(key, value.join(" "));
+ }
+ break;
+ case "dataId":
+ break;
+ case "id":
+ html.setAttribute("data-element-id", value);
+ break;
+ case "style":
+ Object.assign(html.style, value);
+ break;
+ case "textContent":
+ html.textContent = value;
+ break;
+ default:
+ if (!isHTMLAnchorElement || key !== "href" && key !== "newWindow") {
+ html.setAttribute(key, value);
+ }
+ }
+ }
+ if (isHTMLAnchorElement) {
+ linkService.addLinkAttributes(html, attributes.href, attributes.newWindow);
+ }
+ if (storage && attributes.dataId) {
+ this.setupStorage(html, attributes.dataId, element, storage);
+ }
+ }
+ static render(parameters) {
+ const storage = parameters.annotationStorage;
+ const linkService = parameters.linkService;
+ const root = parameters.xfaHtml;
+ const intent = parameters.intent || "display";
+ const rootHtml = document.createElement(root.name);
+ if (root.attributes) {
+ this.setAttributes({
+ html: rootHtml,
+ element: root,
+ intent,
+ linkService
+ });
+ }
+ const isNotForRichText = intent !== "richText";
+ const rootDiv = parameters.div;
+ rootDiv.append(rootHtml);
+ if (parameters.viewport) {
+ const transform = `matrix(${parameters.viewport.transform.join(",")})`;
+ rootDiv.style.transform = transform;
+ }
+ if (isNotForRichText) {
+ rootDiv.setAttribute("class", "xfaLayer xfaFont");
+ }
+ const textDivs = [];
+ if (root.children.length === 0) {
+ if (root.value) {
+ const node = document.createTextNode(root.value);
+ rootHtml.append(node);
+ if (isNotForRichText && XfaText.shouldBuildText(root.name)) {
+ textDivs.push(node);
+ }
+ }
+ return {
+ textDivs
+ };
+ }
+ const stack = [[root, -1, rootHtml]];
+ while (stack.length > 0) {
+ const [parent, i, html] = stack.at(-1);
+ if (i + 1 === parent.children.length) {
+ stack.pop();
+ continue;
+ }
+ const child = parent.children[++stack.at(-1)[1]];
+ if (child === null) {
+ continue;
+ }
+ const {
+ name
+ } = child;
+ if (name === "#text") {
+ const node = document.createTextNode(child.value);
+ textDivs.push(node);
+ html.append(node);
+ continue;
+ }
+ const childHtml = child?.attributes?.xmlns ? document.createElementNS(child.attributes.xmlns, name) : document.createElement(name);
+ html.append(childHtml);
+ if (child.attributes) {
+ this.setAttributes({
+ html: childHtml,
+ element: child,
+ storage,
+ intent,
+ linkService
+ });
+ }
+ if (child.children?.length > 0) {
+ stack.push([child, -1, childHtml]);
+ } else if (child.value) {
+ const node = document.createTextNode(child.value);
+ if (isNotForRichText && XfaText.shouldBuildText(name)) {
+ textDivs.push(node);
+ }
+ childHtml.append(node);
+ }
+ }
+ for (const el of rootDiv.querySelectorAll(".xfaNonInteractive input, .xfaNonInteractive textarea")) {
+ el.setAttribute("readOnly", true);
+ }
+ return {
+ textDivs
+ };
+ }
+ static update(parameters) {
+ const transform = `matrix(${parameters.viewport.transform.join(",")})`;
+ parameters.div.style.transform = transform;
+ parameters.div.hidden = false;
+ }
+}
+
+;// CONCATENATED MODULE: ./src/display/annotation_layer.js
+
+
+
+
+
+const DEFAULT_TAB_INDEX = 1000;
+const annotation_layer_DEFAULT_FONT_SIZE = 9;
+const GetElementsByNameSet = new WeakSet();
+function getRectDims(rect) {
+ return {
+ width: rect[2] - rect[0],
+ height: rect[3] - rect[1]
+ };
+}
+class AnnotationElementFactory {
+ static create(parameters) {
+ const subtype = parameters.data.annotationType;
+ switch (subtype) {
+ case AnnotationType.LINK:
+ return new LinkAnnotationElement(parameters);
+ case AnnotationType.TEXT:
+ return new TextAnnotationElement(parameters);
+ case AnnotationType.WIDGET:
+ const fieldType = parameters.data.fieldType;
+ switch (fieldType) {
+ case "Tx":
+ return new TextWidgetAnnotationElement(parameters);
+ case "Btn":
+ if (parameters.data.radioButton) {
+ return new RadioButtonWidgetAnnotationElement(parameters);
+ } else if (parameters.data.checkBox) {
+ return new CheckboxWidgetAnnotationElement(parameters);
+ }
+ return new PushButtonWidgetAnnotationElement(parameters);
+ case "Ch":
+ return new ChoiceWidgetAnnotationElement(parameters);
+ case "Sig":
+ return new SignatureWidgetAnnotationElement(parameters);
+ }
+ return new WidgetAnnotationElement(parameters);
+ case AnnotationType.POPUP:
+ return new PopupAnnotationElement(parameters);
+ case AnnotationType.FREETEXT:
+ return new FreeTextAnnotationElement(parameters);
+ case AnnotationType.LINE:
+ return new LineAnnotationElement(parameters);
+ case AnnotationType.SQUARE:
+ return new SquareAnnotationElement(parameters);
+ case AnnotationType.CIRCLE:
+ return new CircleAnnotationElement(parameters);
+ case AnnotationType.POLYLINE:
+ return new PolylineAnnotationElement(parameters);
+ case AnnotationType.CARET:
+ return new CaretAnnotationElement(parameters);
+ case AnnotationType.INK:
+ return new InkAnnotationElement(parameters);
+ case AnnotationType.POLYGON:
+ return new PolygonAnnotationElement(parameters);
+ case AnnotationType.HIGHLIGHT:
+ return new HighlightAnnotationElement(parameters);
+ case AnnotationType.UNDERLINE:
+ return new UnderlineAnnotationElement(parameters);
+ case AnnotationType.SQUIGGLY:
+ return new SquigglyAnnotationElement(parameters);
+ case AnnotationType.STRIKEOUT:
+ return new StrikeOutAnnotationElement(parameters);
+ case AnnotationType.STAMP:
+ return new StampAnnotationElement(parameters);
+ case AnnotationType.FILEATTACHMENT:
+ return new FileAttachmentAnnotationElement(parameters);
+ default:
+ return new AnnotationElement(parameters);
+ }
+ }
+}
+class AnnotationElement {
+ #hasBorder = false;
+ constructor(parameters, {
+ isRenderable = false,
+ ignoreBorder = false,
+ createQuadrilaterals = false
+ } = {}) {
+ this.isRenderable = isRenderable;
+ this.data = parameters.data;
+ this.layer = parameters.layer;
+ this.linkService = parameters.linkService;
+ this.downloadManager = parameters.downloadManager;
+ this.imageResourcesPath = parameters.imageResourcesPath;
+ this.renderForms = parameters.renderForms;
+ this.svgFactory = parameters.svgFactory;
+ this.annotationStorage = parameters.annotationStorage;
+ this.enableScripting = parameters.enableScripting;
+ this.hasJSActions = parameters.hasJSActions;
+ this._fieldObjects = parameters.fieldObjects;
+ this.parent = parameters.parent;
+ if (isRenderable) {
+ this.container = this._createContainer(ignoreBorder);
+ }
+ if (createQuadrilaterals) {
+ this._createQuadrilaterals();
+ }
+ }
+ static _hasPopupData({
+ titleObj,
+ contentsObj,
+ richText
+ }) {
+ return !!(titleObj?.str || contentsObj?.str || richText?.str);
+ }
+ get hasPopupData() {
+ return AnnotationElement._hasPopupData(this.data);
+ }
+ _createContainer(ignoreBorder) {
+ const {
+ data,
+ parent: {
+ page,
+ viewport
+ }
+ } = this;
+ const container = document.createElement("section");
+ container.setAttribute("data-annotation-id", data.id);
+ if (!(this instanceof WidgetAnnotationElement)) {
+ container.tabIndex = DEFAULT_TAB_INDEX;
+ }
+ container.style.zIndex = this.parent.zIndex++;
+ if (this.data.popupRef) {
+ container.setAttribute("aria-haspopup", "dialog");
+ }
+ if (data.noRotate) {
+ container.classList.add("norotate");
+ }
+ const {
+ pageWidth,
+ pageHeight,
+ pageX,
+ pageY
+ } = viewport.rawDims;
+ if (!data.rect || this instanceof PopupAnnotationElement) {
+ const {
+ rotation
+ } = data;
+ if (!data.hasOwnCanvas && rotation !== 0) {
+ this.setRotation(rotation, container);
+ }
+ return container;
+ }
+ const {
+ width,
+ height
+ } = getRectDims(data.rect);
+ const rect = Util.normalizeRect([data.rect[0], page.view[3] - data.rect[1] + page.view[1], data.rect[2], page.view[3] - data.rect[3] + page.view[1]]);
+ if (!ignoreBorder && data.borderStyle.width > 0) {
+ container.style.borderWidth = `${data.borderStyle.width}px`;
+ const horizontalRadius = data.borderStyle.horizontalCornerRadius;
+ const verticalRadius = data.borderStyle.verticalCornerRadius;
+ if (horizontalRadius > 0 || verticalRadius > 0) {
+ const radius = `calc(${horizontalRadius}px * var(--scale-factor)) / calc(${verticalRadius}px * var(--scale-factor))`;
+ container.style.borderRadius = radius;
+ } else if (this instanceof RadioButtonWidgetAnnotationElement) {
+ const radius = `calc(${width}px * var(--scale-factor)) / calc(${height}px * var(--scale-factor))`;
+ container.style.borderRadius = radius;
+ }
+ switch (data.borderStyle.style) {
+ case AnnotationBorderStyleType.SOLID:
+ container.style.borderStyle = "solid";
+ break;
+ case AnnotationBorderStyleType.DASHED:
+ container.style.borderStyle = "dashed";
+ break;
+ case AnnotationBorderStyleType.BEVELED:
+ warn("Unimplemented border style: beveled");
+ break;
+ case AnnotationBorderStyleType.INSET:
+ warn("Unimplemented border style: inset");
+ break;
+ case AnnotationBorderStyleType.UNDERLINE:
+ container.style.borderBottomStyle = "solid";
+ break;
+ default:
+ break;
+ }
+ const borderColor = data.borderColor || null;
+ if (borderColor) {
+ this.#hasBorder = true;
+ container.style.borderColor = Util.makeHexColor(borderColor[0] | 0, borderColor[1] | 0, borderColor[2] | 0);
+ } else {
+ container.style.borderWidth = 0;
+ }
+ }
+ container.style.left = `${100 * (rect[0] - pageX) / pageWidth}%`;
+ container.style.top = `${100 * (rect[1] - pageY) / pageHeight}%`;
+ const {
+ rotation
+ } = data;
+ if (data.hasOwnCanvas || rotation === 0) {
+ container.style.width = `${100 * width / pageWidth}%`;
+ container.style.height = `${100 * height / pageHeight}%`;
+ } else {
+ this.setRotation(rotation, container);
+ }
+ return container;
+ }
+ setRotation(angle, container = this.container) {
+ if (!this.data.rect) {
+ return;
+ }
+ const {
+ pageWidth,
+ pageHeight
+ } = this.parent.viewport.rawDims;
+ const {
+ width,
+ height
+ } = getRectDims(this.data.rect);
+ let elementWidth, elementHeight;
+ if (angle % 180 === 0) {
+ elementWidth = 100 * width / pageWidth;
+ elementHeight = 100 * height / pageHeight;
+ } else {
+ elementWidth = 100 * height / pageWidth;
+ elementHeight = 100 * width / pageHeight;
+ }
+ container.style.width = `${elementWidth}%`;
+ container.style.height = `${elementHeight}%`;
+ container.setAttribute("data-main-rotation", (360 - angle) % 360);
+ }
+ get _commonActions() {
+ const setColor = (jsName, styleName, event) => {
+ const color = event.detail[jsName];
+ const colorType = color[0];
+ const colorArray = color.slice(1);
+ event.target.style[styleName] = ColorConverters[`${colorType}_HTML`](colorArray);
+ this.annotationStorage.setValue(this.data.id, {
+ [styleName]: ColorConverters[`${colorType}_rgb`](colorArray)
+ });
+ };
+ return shadow(this, "_commonActions", {
+ display: event => {
+ const {
+ display
+ } = event.detail;
+ const hidden = display % 2 === 1;
+ this.container.style.visibility = hidden ? "hidden" : "visible";
+ this.annotationStorage.setValue(this.data.id, {
+ noView: hidden,
+ noPrint: display === 1 || display === 2
+ });
+ },
+ print: event => {
+ this.annotationStorage.setValue(this.data.id, {
+ noPrint: !event.detail.print
+ });
+ },
+ hidden: event => {
+ const {
+ hidden
+ } = event.detail;
+ this.container.style.visibility = hidden ? "hidden" : "visible";
+ this.annotationStorage.setValue(this.data.id, {
+ noPrint: hidden,
+ noView: hidden
+ });
+ },
+ focus: event => {
+ setTimeout(() => event.target.focus({
+ preventScroll: false
+ }), 0);
+ },
+ userName: event => {
+ event.target.title = event.detail.userName;
+ },
+ readonly: event => {
+ event.target.disabled = event.detail.readonly;
+ },
+ required: event => {
+ this._setRequired(event.target, event.detail.required);
+ },
+ bgColor: event => {
+ setColor("bgColor", "backgroundColor", event);
+ },
+ fillColor: event => {
+ setColor("fillColor", "backgroundColor", event);
+ },
+ fgColor: event => {
+ setColor("fgColor", "color", event);
+ },
+ textColor: event => {
+ setColor("textColor", "color", event);
+ },
+ borderColor: event => {
+ setColor("borderColor", "borderColor", event);
+ },
+ strokeColor: event => {
+ setColor("strokeColor", "borderColor", event);
+ },
+ rotation: event => {
+ const angle = event.detail.rotation;
+ this.setRotation(angle);
+ this.annotationStorage.setValue(this.data.id, {
+ rotation: angle
+ });
+ }
+ });
+ }
+ _dispatchEventFromSandbox(actions, jsEvent) {
+ const commonActions = this._commonActions;
+ for (const name of Object.keys(jsEvent.detail)) {
+ const action = actions[name] || commonActions[name];
+ action?.(jsEvent);
+ }
+ }
+ _setDefaultPropertiesFromJS(element) {
+ if (!this.enableScripting) {
+ return;
+ }
+ const storedData = this.annotationStorage.getRawValue(this.data.id);
+ if (!storedData) {
+ return;
+ }
+ const commonActions = this._commonActions;
+ for (const [actionName, detail] of Object.entries(storedData)) {
+ const action = commonActions[actionName];
+ if (action) {
+ const eventProxy = {
+ detail: {
+ [actionName]: detail
+ },
+ target: element
+ };
+ action(eventProxy);
+ delete storedData[actionName];
+ }
+ }
+ }
+ _createQuadrilaterals() {
+ if (!this.container) {
+ return;
+ }
+ const {
+ quadPoints
+ } = this.data;
+ if (!quadPoints) {
+ return;
+ }
+ const [rectBlX, rectBlY, rectTrX, rectTrY] = this.data.rect;
+ if (quadPoints.length === 1) {
+ const [, {
+ x: trX,
+ y: trY
+ }, {
+ x: blX,
+ y: blY
+ }] = quadPoints[0];
+ if (rectTrX === trX && rectTrY === trY && rectBlX === blX && rectBlY === blY) {
+ return;
+ }
+ }
+ const {
+ style
+ } = this.container;
+ let svgBuffer;
+ if (this.#hasBorder) {
+ const {
+ borderColor,
+ borderWidth
+ } = style;
+ style.borderWidth = 0;
+ svgBuffer = ["url('data:image/svg+xml;utf8,", `<svg xmlns="http://www.w3.org/2000/svg"`, ` preserveAspectRatio="none" viewBox="0 0 1 1">`, `<g fill="transparent" stroke="${borderColor}" stroke-width="${borderWidth}">`];
+ this.container.classList.add("hasBorder");
+ }
+ const width = rectTrX - rectBlX;
+ const height = rectTrY - rectBlY;
+ const {
+ svgFactory
+ } = this;
+ const svg = svgFactory.createElement("svg");
+ svg.classList.add("quadrilateralsContainer");
+ svg.setAttribute("width", 0);
+ svg.setAttribute("height", 0);
+ const defs = svgFactory.createElement("defs");
+ svg.append(defs);
+ const clipPath = svgFactory.createElement("clipPath");
+ const id = `clippath_${this.data.id}`;
+ clipPath.setAttribute("id", id);
+ clipPath.setAttribute("clipPathUnits", "objectBoundingBox");
+ defs.append(clipPath);
+ for (const [, {
+ x: trX,
+ y: trY
+ }, {
+ x: blX,
+ y: blY
+ }] of quadPoints) {
+ const rect = svgFactory.createElement("rect");
+ const x = (blX - rectBlX) / width;
+ const y = (rectTrY - trY) / height;
+ const rectWidth = (trX - blX) / width;
+ const rectHeight = (trY - blY) / height;
+ rect.setAttribute("x", x);
+ rect.setAttribute("y", y);
+ rect.setAttribute("width", rectWidth);
+ rect.setAttribute("height", rectHeight);
+ clipPath.append(rect);
+ svgBuffer?.push(`<rect vector-effect="non-scaling-stroke" x="${x}" y="${y}" width="${rectWidth}" height="${rectHeight}"/>`);
+ }
+ if (this.#hasBorder) {
+ svgBuffer.push(`</g></svg>')`);
+ style.backgroundImage = svgBuffer.join("");
+ }
+ this.container.append(svg);
+ this.container.style.clipPath = `url(#${id})`;
+ }
+ _createPopup() {
+ const {
+ container,
+ data
+ } = this;
+ container.setAttribute("aria-haspopup", "dialog");
+ const popup = new PopupAnnotationElement({
+ data: {
+ color: data.color,
+ titleObj: data.titleObj,
+ modificationDate: data.modificationDate,
+ contentsObj: data.contentsObj,
+ richText: data.richText,
+ parentRect: data.rect,
+ borderStyle: 0,
+ id: `popup_${data.id}`,
+ rotation: data.rotation
+ },
+ parent: this.parent,
+ elements: [this]
+ });
+ this.parent.div.append(popup.render());
+ }
+ render() {
+ unreachable("Abstract method `AnnotationElement.render` called");
+ }
+ _getElementsByName(name, skipId = null) {
+ const fields = [];
+ if (this._fieldObjects) {
+ const fieldObj = this._fieldObjects[name];
+ if (fieldObj) {
+ for (const {
+ page,
+ id,
+ exportValues
+ } of fieldObj) {
+ if (page === -1) {
+ continue;
+ }
+ if (id === skipId) {
+ continue;
+ }
+ const exportValue = typeof exportValues === "string" ? exportValues : null;
+ const domElement = document.querySelector(`[data-element-id="${id}"]`);
+ if (domElement && !GetElementsByNameSet.has(domElement)) {
+ warn(`_getElementsByName - element not allowed: ${id}`);
+ continue;
+ }
+ fields.push({
+ id,
+ exportValue,
+ domElement
+ });
+ }
+ }
+ return fields;
+ }
+ for (const domElement of document.getElementsByName(name)) {
+ const {
+ exportValue
+ } = domElement;
+ const id = domElement.getAttribute("data-element-id");
+ if (id === skipId) {
+ continue;
+ }
+ if (!GetElementsByNameSet.has(domElement)) {
+ continue;
+ }
+ fields.push({
+ id,
+ exportValue,
+ domElement
+ });
+ }
+ return fields;
+ }
+ show() {
+ if (this.container) {
+ this.container.hidden = false;
+ }
+ this.popup?.maybeShow();
+ }
+ hide() {
+ if (this.container) {
+ this.container.hidden = true;
+ }
+ this.popup?.forceHide();
+ }
+ getElementsToTriggerPopup() {
+ return this.container;
+ }
+ addHighlightArea() {
+ const triggers = this.getElementsToTriggerPopup();
+ if (Array.isArray(triggers)) {
+ for (const element of triggers) {
+ element.classList.add("highlightArea");
+ }
+ } else {
+ triggers.classList.add("highlightArea");
+ }
+ }
+ get _isEditable() {
+ return false;
+ }
+ _editOnDoubleClick() {
+ if (!this._isEditable) {
+ return;
+ }
+ const {
+ annotationEditorType: mode,
+ data: {
+ id: editId
+ }
+ } = this;
+ this.container.addEventListener("dblclick", () => {
+ this.linkService.eventBus?.dispatch("switchannotationeditormode", {
+ source: this,
+ mode,
+ editId
+ });
+ });
+ }
+}
+class LinkAnnotationElement extends AnnotationElement {
+ constructor(parameters, options = null) {
+ super(parameters, {
+ isRenderable: true,
+ ignoreBorder: !!options?.ignoreBorder,
+ createQuadrilaterals: true
+ });
+ this.isTooltipOnly = parameters.data.isTooltipOnly;
+ }
+ render() {
+ const {
+ data,
+ linkService
+ } = this;
+ const link = document.createElement("a");
+ link.setAttribute("data-element-id", data.id);
+ let isBound = false;
+ if (data.url) {
+ linkService.addLinkAttributes(link, data.url, data.newWindow);
+ isBound = true;
+ } else if (data.action) {
+ this._bindNamedAction(link, data.action);
+ isBound = true;
+ } else if (data.attachment) {
+ this.#bindAttachment(link, data.attachment, data.attachmentDest);
+ isBound = true;
+ } else if (data.setOCGState) {
+ this.#bindSetOCGState(link, data.setOCGState);
+ isBound = true;
+ } else if (data.dest) {
+ this._bindLink(link, data.dest);
+ isBound = true;
+ } else {
+ if (data.actions && (data.actions.Action || data.actions["Mouse Up"] || data.actions["Mouse Down"]) && this.enableScripting && this.hasJSActions) {
+ this._bindJSAction(link, data);
+ isBound = true;
+ }
+ if (data.resetForm) {
+ this._bindResetFormAction(link, data.resetForm);
+ isBound = true;
+ } else if (this.isTooltipOnly && !isBound) {
+ this._bindLink(link, "");
+ isBound = true;
+ }
+ }
+ this.container.classList.add("linkAnnotation");
+ if (isBound) {
+ this.container.append(link);
+ }
+ return this.container;
+ }
+ #setInternalLink() {
+ this.container.setAttribute("data-internal-link", "");
+ }
+ _bindLink(link, destination) {
+ link.href = this.linkService.getDestinationHash(destination);
+ link.onclick = () => {
+ if (destination) {
+ this.linkService.goToDestination(destination);
+ }
+ return false;
+ };
+ if (destination || destination === "") {
+ this.#setInternalLink();
+ }
+ }
+ _bindNamedAction(link, action) {
+ link.href = this.linkService.getAnchorUrl("");
+ link.onclick = () => {
+ this.linkService.executeNamedAction(action);
+ return false;
+ };
+ this.#setInternalLink();
+ }
+ #bindAttachment(link, attachment, dest = null) {
+ link.href = this.linkService.getAnchorUrl("");
+ link.onclick = () => {
+ this.downloadManager?.openOrDownloadData(attachment.content, attachment.filename, dest);
+ return false;
+ };
+ this.#setInternalLink();
+ }
+ #bindSetOCGState(link, action) {
+ link.href = this.linkService.getAnchorUrl("");
+ link.onclick = () => {
+ this.linkService.executeSetOCGState(action);
+ return false;
+ };
+ this.#setInternalLink();
+ }
+ _bindJSAction(link, data) {
+ link.href = this.linkService.getAnchorUrl("");
+ const map = new Map([["Action", "onclick"], ["Mouse Up", "onmouseup"], ["Mouse Down", "onmousedown"]]);
+ for (const name of Object.keys(data.actions)) {
+ const jsName = map.get(name);
+ if (!jsName) {
+ continue;
+ }
+ link[jsName] = () => {
+ this.linkService.eventBus?.dispatch("dispatcheventinsandbox", {
+ source: this,
+ detail: {
+ id: data.id,
+ name
+ }
+ });
+ return false;
+ };
+ }
+ if (!link.onclick) {
+ link.onclick = () => false;
+ }
+ this.#setInternalLink();
+ }
+ _bindResetFormAction(link, resetForm) {
+ const otherClickAction = link.onclick;
+ if (!otherClickAction) {
+ link.href = this.linkService.getAnchorUrl("");
+ }
+ this.#setInternalLink();
+ if (!this._fieldObjects) {
+ warn(`_bindResetFormAction - "resetForm" action not supported, ` + "ensure that the `fieldObjects` parameter is provided.");
+ if (!otherClickAction) {
+ link.onclick = () => false;
+ }
+ return;
+ }
+ link.onclick = () => {
+ otherClickAction?.();
+ const {
+ fields: resetFormFields,
+ refs: resetFormRefs,
+ include
+ } = resetForm;
+ const allFields = [];
+ if (resetFormFields.length !== 0 || resetFormRefs.length !== 0) {
+ const fieldIds = new Set(resetFormRefs);
+ for (const fieldName of resetFormFields) {
+ const fields = this._fieldObjects[fieldName] || [];
+ for (const {
+ id
+ } of fields) {
+ fieldIds.add(id);
+ }
+ }
+ for (const fields of Object.values(this._fieldObjects)) {
+ for (const field of fields) {
+ if (fieldIds.has(field.id) === include) {
+ allFields.push(field);
+ }
+ }
+ }
+ } else {
+ for (const fields of Object.values(this._fieldObjects)) {
+ allFields.push(...fields);
+ }
+ }
+ const storage = this.annotationStorage;
+ const allIds = [];
+ for (const field of allFields) {
+ const {
+ id
+ } = field;
+ allIds.push(id);
+ switch (field.type) {
+ case "text":
+ {
+ const value = field.defaultValue || "";
+ storage.setValue(id, {
+ value
+ });
+ break;
+ }
+ case "checkbox":
+ case "radiobutton":
+ {
+ const value = field.defaultValue === field.exportValues;
+ storage.setValue(id, {
+ value
+ });
+ break;
+ }
+ case "combobox":
+ case "listbox":
+ {
+ const value = field.defaultValue || "";
+ storage.setValue(id, {
+ value
+ });
+ break;
+ }
+ default:
+ continue;
+ }
+ const domElement = document.querySelector(`[data-element-id="${id}"]`);
+ if (!domElement) {
+ continue;
+ } else if (!GetElementsByNameSet.has(domElement)) {
+ warn(`_bindResetFormAction - element not allowed: ${id}`);
+ continue;
+ }
+ domElement.dispatchEvent(new Event("resetform"));
+ }
+ if (this.enableScripting) {
+ this.linkService.eventBus?.dispatch("dispatcheventinsandbox", {
+ source: this,
+ detail: {
+ id: "app",
+ ids: allIds,
+ name: "ResetForm"
+ }
+ });
+ }
+ return false;
+ };
+ }
+}
+class TextAnnotationElement extends AnnotationElement {
+ constructor(parameters) {
+ super(parameters, {
+ isRenderable: true
+ });
+ }
+ render() {
+ this.container.classList.add("textAnnotation");
+ const image = document.createElement("img");
+ image.src = this.imageResourcesPath + "annotation-" + this.data.name.toLowerCase() + ".svg";
+ image.setAttribute("data-l10n-id", "pdfjs-text-annotation-type");
+ image.setAttribute("data-l10n-args", JSON.stringify({
+ type: this.data.name
+ }));
+ if (!this.data.popupRef && this.hasPopupData) {
+ this._createPopup();
+ }
+ this.container.append(image);
+ return this.container;
+ }
+}
+class WidgetAnnotationElement extends AnnotationElement {
+ render() {
+ if (this.data.alternativeText) {
+ this.container.title = this.data.alternativeText;
+ }
+ return this.container;
+ }
+ showElementAndHideCanvas(element) {
+ if (this.data.hasOwnCanvas) {
+ if (element.previousSibling?.nodeName === "CANVAS") {
+ element.previousSibling.hidden = true;
+ }
+ element.hidden = false;
+ }
+ }
+ _getKeyModifier(event) {
+ return util_FeatureTest.platform.isMac ? event.metaKey : event.ctrlKey;
+ }
+ _setEventListener(element, elementData, baseName, eventName, valueGetter) {
+ if (baseName.includes("mouse")) {
+ element.addEventListener(baseName, event => {
+ this.linkService.eventBus?.dispatch("dispatcheventinsandbox", {
+ source: this,
+ detail: {
+ id: this.data.id,
+ name: eventName,
+ value: valueGetter(event),
+ shift: event.shiftKey,
+ modifier: this._getKeyModifier(event)
+ }
+ });
+ });
+ } else {
+ element.addEventListener(baseName, event => {
+ if (baseName === "blur") {
+ if (!elementData.focused || !event.relatedTarget) {
+ return;
+ }
+ elementData.focused = false;
+ } else if (baseName === "focus") {
+ if (elementData.focused) {
+ return;
+ }
+ elementData.focused = true;
+ }
+ if (!valueGetter) {
+ return;
+ }
+ this.linkService.eventBus?.dispatch("dispatcheventinsandbox", {
+ source: this,
+ detail: {
+ id: this.data.id,
+ name: eventName,
+ value: valueGetter(event)
+ }
+ });
+ });
+ }
+ }
+ _setEventListeners(element, elementData, names, getter) {
+ for (const [baseName, eventName] of names) {
+ if (eventName === "Action" || this.data.actions?.[eventName]) {
+ if (eventName === "Focus" || eventName === "Blur") {
+ elementData ||= {
+ focused: false
+ };
+ }
+ this._setEventListener(element, elementData, baseName, eventName, getter);
+ if (eventName === "Focus" && !this.data.actions?.Blur) {
+ this._setEventListener(element, elementData, "blur", "Blur", null);
+ } else if (eventName === "Blur" && !this.data.actions?.Focus) {
+ this._setEventListener(element, elementData, "focus", "Focus", null);
+ }
+ }
+ }
+ }
+ _setBackgroundColor(element) {
+ const color = this.data.backgroundColor || null;
+ element.style.backgroundColor = color === null ? "transparent" : Util.makeHexColor(color[0], color[1], color[2]);
+ }
+ _setTextStyle(element) {
+ const TEXT_ALIGNMENT = ["left", "center", "right"];
+ const {
+ fontColor
+ } = this.data.defaultAppearanceData;
+ const fontSize = this.data.defaultAppearanceData.fontSize || annotation_layer_DEFAULT_FONT_SIZE;
+ const style = element.style;
+ let computedFontSize;
+ const BORDER_SIZE = 2;
+ const roundToOneDecimal = x => Math.round(10 * x) / 10;
+ if (this.data.multiLine) {
+ const height = Math.abs(this.data.rect[3] - this.data.rect[1] - BORDER_SIZE);
+ const numberOfLines = Math.round(height / (LINE_FACTOR * fontSize)) || 1;
+ const lineHeight = height / numberOfLines;
+ computedFontSize = Math.min(fontSize, roundToOneDecimal(lineHeight / LINE_FACTOR));
+ } else {
+ const height = Math.abs(this.data.rect[3] - this.data.rect[1] - BORDER_SIZE);
+ computedFontSize = Math.min(fontSize, roundToOneDecimal(height / LINE_FACTOR));
+ }
+ style.fontSize = `calc(${computedFontSize}px * var(--scale-factor))`;
+ style.color = Util.makeHexColor(fontColor[0], fontColor[1], fontColor[2]);
+ if (this.data.textAlignment !== null) {
+ style.textAlign = TEXT_ALIGNMENT[this.data.textAlignment];
+ }
+ }
+ _setRequired(element, isRequired) {
+ if (isRequired) {
+ element.setAttribute("required", true);
+ } else {
+ element.removeAttribute("required");
+ }
+ element.setAttribute("aria-required", isRequired);
+ }
+}
+class TextWidgetAnnotationElement extends WidgetAnnotationElement {
+ constructor(parameters) {
+ const isRenderable = parameters.renderForms || parameters.data.hasOwnCanvas || !parameters.data.hasAppearance && !!parameters.data.fieldValue;
+ super(parameters, {
+ isRenderable
+ });
+ }
+ setPropertyOnSiblings(base, key, value, keyInStorage) {
+ const storage = this.annotationStorage;
+ for (const element of this._getElementsByName(base.name, base.id)) {
+ if (element.domElement) {
+ element.domElement[key] = value;
+ }
+ storage.setValue(element.id, {
+ [keyInStorage]: value
+ });
+ }
+ }
+ render() {
+ const storage = this.annotationStorage;
+ const id = this.data.id;
+ this.container.classList.add("textWidgetAnnotation");
+ let element = null;
+ if (this.renderForms) {
+ const storedData = storage.getValue(id, {
+ value: this.data.fieldValue
+ });
+ let textContent = storedData.value || "";
+ const maxLen = storage.getValue(id, {
+ charLimit: this.data.maxLen
+ }).charLimit;
+ if (maxLen && textContent.length > maxLen) {
+ textContent = textContent.slice(0, maxLen);
+ }
+ let fieldFormattedValues = storedData.formattedValue || this.data.textContent?.join("\n") || null;
+ if (fieldFormattedValues && this.data.comb) {
+ fieldFormattedValues = fieldFormattedValues.replaceAll(/\s+/g, "");
+ }
+ const elementData = {
+ userValue: textContent,
+ formattedValue: fieldFormattedValues,
+ lastCommittedValue: null,
+ commitKey: 1,
+ focused: false
+ };
+ if (this.data.multiLine) {
+ element = document.createElement("textarea");
+ element.textContent = fieldFormattedValues ?? textContent;
+ if (this.data.doNotScroll) {
+ element.style.overflowY = "hidden";
+ }
+ } else {
+ element = document.createElement("input");
+ element.type = "text";
+ element.setAttribute("value", fieldFormattedValues ?? textContent);
+ if (this.data.doNotScroll) {
+ element.style.overflowX = "hidden";
+ }
+ }
+ if (this.data.hasOwnCanvas) {
+ element.hidden = true;
+ }
+ GetElementsByNameSet.add(element);
+ element.setAttribute("data-element-id", id);
+ element.disabled = this.data.readOnly;
+ element.name = this.data.fieldName;
+ element.tabIndex = DEFAULT_TAB_INDEX;
+ this._setRequired(element, this.data.required);
+ if (maxLen) {
+ element.maxLength = maxLen;
+ }
+ element.addEventListener("input", event => {
+ storage.setValue(id, {
+ value: event.target.value
+ });
+ this.setPropertyOnSiblings(element, "value", event.target.value, "value");
+ elementData.formattedValue = null;
+ });
+ element.addEventListener("resetform", event => {
+ const defaultValue = this.data.defaultFieldValue ?? "";
+ element.value = elementData.userValue = defaultValue;
+ elementData.formattedValue = null;
+ });
+ let blurListener = event => {
+ const {
+ formattedValue
+ } = elementData;
+ if (formattedValue !== null && formattedValue !== undefined) {
+ event.target.value = formattedValue;
+ }
+ event.target.scrollLeft = 0;
+ };
+ if (this.enableScripting && this.hasJSActions) {
+ element.addEventListener("focus", event => {
+ if (elementData.focused) {
+ return;
+ }
+ const {
+ target
+ } = event;
+ if (elementData.userValue) {
+ target.value = elementData.userValue;
+ }
+ elementData.lastCommittedValue = target.value;
+ elementData.commitKey = 1;
+ if (!this.data.actions?.Focus) {
+ elementData.focused = true;
+ }
+ });
+ element.addEventListener("updatefromsandbox", jsEvent => {
+ this.showElementAndHideCanvas(jsEvent.target);
+ const actions = {
+ value(event) {
+ elementData.userValue = event.detail.value ?? "";
+ storage.setValue(id, {
+ value: elementData.userValue.toString()
+ });
+ event.target.value = elementData.userValue;
+ },
+ formattedValue(event) {
+ const {
+ formattedValue
+ } = event.detail;
+ elementData.formattedValue = formattedValue;
+ if (formattedValue !== null && formattedValue !== undefined && event.target !== document.activeElement) {
+ event.target.value = formattedValue;
+ }
+ storage.setValue(id, {
+ formattedValue
+ });
+ },
+ selRange(event) {
+ event.target.setSelectionRange(...event.detail.selRange);
+ },
+ charLimit: event => {
+ const {
+ charLimit
+ } = event.detail;
+ const {
+ target
+ } = event;
+ if (charLimit === 0) {
+ target.removeAttribute("maxLength");
+ return;
+ }
+ target.setAttribute("maxLength", charLimit);
+ let value = elementData.userValue;
+ if (!value || value.length <= charLimit) {
+ return;
+ }
+ value = value.slice(0, charLimit);
+ target.value = elementData.userValue = value;
+ storage.setValue(id, {
+ value
+ });
+ this.linkService.eventBus?.dispatch("dispatcheventinsandbox", {
+ source: this,
+ detail: {
+ id,
+ name: "Keystroke",
+ value,
+ willCommit: true,
+ commitKey: 1,
+ selStart: target.selectionStart,
+ selEnd: target.selectionEnd
+ }
+ });
+ }
+ };
+ this._dispatchEventFromSandbox(actions, jsEvent);
+ });
+ element.addEventListener("keydown", event => {
+ elementData.commitKey = 1;
+ let commitKey = -1;
+ if (event.key === "Escape") {
+ commitKey = 0;
+ } else if (event.key === "Enter" && !this.data.multiLine) {
+ commitKey = 2;
+ } else if (event.key === "Tab") {
+ elementData.commitKey = 3;
+ }
+ if (commitKey === -1) {
+ return;
+ }
+ const {
+ value
+ } = event.target;
+ if (elementData.lastCommittedValue === value) {
+ return;
+ }
+ elementData.lastCommittedValue = value;
+ elementData.userValue = value;
+ this.linkService.eventBus?.dispatch("dispatcheventinsandbox", {
+ source: this,
+ detail: {
+ id,
+ name: "Keystroke",
+ value,
+ willCommit: true,
+ commitKey,
+ selStart: event.target.selectionStart,
+ selEnd: event.target.selectionEnd
+ }
+ });
+ });
+ const _blurListener = blurListener;
+ blurListener = null;
+ element.addEventListener("blur", event => {
+ if (!elementData.focused || !event.relatedTarget) {
+ return;
+ }
+ if (!this.data.actions?.Blur) {
+ elementData.focused = false;
+ }
+ const {
+ value
+ } = event.target;
+ elementData.userValue = value;
+ if (elementData.lastCommittedValue !== value) {
+ this.linkService.eventBus?.dispatch("dispatcheventinsandbox", {
+ source: this,
+ detail: {
+ id,
+ name: "Keystroke",
+ value,
+ willCommit: true,
+ commitKey: elementData.commitKey,
+ selStart: event.target.selectionStart,
+ selEnd: event.target.selectionEnd
+ }
+ });
+ }
+ _blurListener(event);
+ });
+ if (this.data.actions?.Keystroke) {
+ element.addEventListener("beforeinput", event => {
+ elementData.lastCommittedValue = null;
+ const {
+ data,
+ target
+ } = event;
+ const {
+ value,
+ selectionStart,
+ selectionEnd
+ } = target;
+ let selStart = selectionStart,
+ selEnd = selectionEnd;
+ switch (event.inputType) {
+ case "deleteWordBackward":
+ {
+ const match = value.substring(0, selectionStart).match(/\w*[^\w]*$/);
+ if (match) {
+ selStart -= match[0].length;
+ }
+ break;
+ }
+ case "deleteWordForward":
+ {
+ const match = value.substring(selectionStart).match(/^[^\w]*\w*/);
+ if (match) {
+ selEnd += match[0].length;
+ }
+ break;
+ }
+ case "deleteContentBackward":
+ if (selectionStart === selectionEnd) {
+ selStart -= 1;
+ }
+ break;
+ case "deleteContentForward":
+ if (selectionStart === selectionEnd) {
+ selEnd += 1;
+ }
+ break;
+ }
+ event.preventDefault();
+ this.linkService.eventBus?.dispatch("dispatcheventinsandbox", {
+ source: this,
+ detail: {
+ id,
+ name: "Keystroke",
+ value,
+ change: data || "",
+ willCommit: false,
+ selStart,
+ selEnd
+ }
+ });
+ });
+ }
+ this._setEventListeners(element, elementData, [["focus", "Focus"], ["blur", "Blur"], ["mousedown", "Mouse Down"], ["mouseenter", "Mouse Enter"], ["mouseleave", "Mouse Exit"], ["mouseup", "Mouse Up"]], event => event.target.value);
+ }
+ if (blurListener) {
+ element.addEventListener("blur", blurListener);
+ }
+ if (this.data.comb) {
+ const fieldWidth = this.data.rect[2] - this.data.rect[0];
+ const combWidth = fieldWidth / maxLen;
+ element.classList.add("comb");
+ element.style.letterSpacing = `calc(${combWidth}px * var(--scale-factor) - 1ch)`;
+ }
+ } else {
+ element = document.createElement("div");
+ element.textContent = this.data.fieldValue;
+ element.style.verticalAlign = "middle";
+ element.style.display = "table-cell";
+ if (this.data.hasOwnCanvas) {
+ element.hidden = true;
+ }
+ }
+ this._setTextStyle(element);
+ this._setBackgroundColor(element);
+ this._setDefaultPropertiesFromJS(element);
+ this.container.append(element);
+ return this.container;
+ }
+}
+class SignatureWidgetAnnotationElement extends WidgetAnnotationElement {
+ constructor(parameters) {
+ super(parameters, {
+ isRenderable: !!parameters.data.hasOwnCanvas
+ });
+ }
+}
+class CheckboxWidgetAnnotationElement extends WidgetAnnotationElement {
+ constructor(parameters) {
+ super(parameters, {
+ isRenderable: parameters.renderForms
+ });
+ }
+ render() {
+ const storage = this.annotationStorage;
+ const data = this.data;
+ const id = data.id;
+ let value = storage.getValue(id, {
+ value: data.exportValue === data.fieldValue
+ }).value;
+ if (typeof value === "string") {
+ value = value !== "Off";
+ storage.setValue(id, {
+ value
+ });
+ }
+ this.container.classList.add("buttonWidgetAnnotation", "checkBox");
+ const element = document.createElement("input");
+ GetElementsByNameSet.add(element);
+ element.setAttribute("data-element-id", id);
+ element.disabled = data.readOnly;
+ this._setRequired(element, this.data.required);
+ element.type = "checkbox";
+ element.name = data.fieldName;
+ if (value) {
+ element.setAttribute("checked", true);
+ }
+ element.setAttribute("exportValue", data.exportValue);
+ element.tabIndex = DEFAULT_TAB_INDEX;
+ element.addEventListener("change", event => {
+ const {
+ name,
+ checked
+ } = event.target;
+ for (const checkbox of this._getElementsByName(name, id)) {
+ const curChecked = checked && checkbox.exportValue === data.exportValue;
+ if (checkbox.domElement) {
+ checkbox.domElement.checked = curChecked;
+ }
+ storage.setValue(checkbox.id, {
+ value: curChecked
+ });
+ }
+ storage.setValue(id, {
+ value: checked
+ });
+ });
+ element.addEventListener("resetform", event => {
+ const defaultValue = data.defaultFieldValue || "Off";
+ event.target.checked = defaultValue === data.exportValue;
+ });
+ if (this.enableScripting && this.hasJSActions) {
+ element.addEventListener("updatefromsandbox", jsEvent => {
+ const actions = {
+ value(event) {
+ event.target.checked = event.detail.value !== "Off";
+ storage.setValue(id, {
+ value: event.target.checked
+ });
+ }
+ };
+ this._dispatchEventFromSandbox(actions, jsEvent);
+ });
+ this._setEventListeners(element, null, [["change", "Validate"], ["change", "Action"], ["focus", "Focus"], ["blur", "Blur"], ["mousedown", "Mouse Down"], ["mouseenter", "Mouse Enter"], ["mouseleave", "Mouse Exit"], ["mouseup", "Mouse Up"]], event => event.target.checked);
+ }
+ this._setBackgroundColor(element);
+ this._setDefaultPropertiesFromJS(element);
+ this.container.append(element);
+ return this.container;
+ }
+}
+class RadioButtonWidgetAnnotationElement extends WidgetAnnotationElement {
+ constructor(parameters) {
+ super(parameters, {
+ isRenderable: parameters.renderForms
+ });
+ }
+ render() {
+ this.container.classList.add("buttonWidgetAnnotation", "radioButton");
+ const storage = this.annotationStorage;
+ const data = this.data;
+ const id = data.id;
+ let value = storage.getValue(id, {
+ value: data.fieldValue === data.buttonValue
+ }).value;
+ if (typeof value === "string") {
+ value = value !== data.buttonValue;
+ storage.setValue(id, {
+ value
+ });
+ }
+ if (value) {
+ for (const radio of this._getElementsByName(data.fieldName, id)) {
+ storage.setValue(radio.id, {
+ value: false
+ });
+ }
+ }
+ const element = document.createElement("input");
+ GetElementsByNameSet.add(element);
+ element.setAttribute("data-element-id", id);
+ element.disabled = data.readOnly;
+ this._setRequired(element, this.data.required);
+ element.type = "radio";
+ element.name = data.fieldName;
+ if (value) {
+ element.setAttribute("checked", true);
+ }
+ element.tabIndex = DEFAULT_TAB_INDEX;
+ element.addEventListener("change", event => {
+ const {
+ name,
+ checked
+ } = event.target;
+ for (const radio of this._getElementsByName(name, id)) {
+ storage.setValue(radio.id, {
+ value: false
+ });
+ }
+ storage.setValue(id, {
+ value: checked
+ });
+ });
+ element.addEventListener("resetform", event => {
+ const defaultValue = data.defaultFieldValue;
+ event.target.checked = defaultValue !== null && defaultValue !== undefined && defaultValue === data.buttonValue;
+ });
+ if (this.enableScripting && this.hasJSActions) {
+ const pdfButtonValue = data.buttonValue;
+ element.addEventListener("updatefromsandbox", jsEvent => {
+ const actions = {
+ value: event => {
+ const checked = pdfButtonValue === event.detail.value;
+ for (const radio of this._getElementsByName(event.target.name)) {
+ const curChecked = checked && radio.id === id;
+ if (radio.domElement) {
+ radio.domElement.checked = curChecked;
+ }
+ storage.setValue(radio.id, {
+ value: curChecked
+ });
+ }
+ }
+ };
+ this._dispatchEventFromSandbox(actions, jsEvent);
+ });
+ this._setEventListeners(element, null, [["change", "Validate"], ["change", "Action"], ["focus", "Focus"], ["blur", "Blur"], ["mousedown", "Mouse Down"], ["mouseenter", "Mouse Enter"], ["mouseleave", "Mouse Exit"], ["mouseup", "Mouse Up"]], event => event.target.checked);
+ }
+ this._setBackgroundColor(element);
+ this._setDefaultPropertiesFromJS(element);
+ this.container.append(element);
+ return this.container;
+ }
+}
+class PushButtonWidgetAnnotationElement extends LinkAnnotationElement {
+ constructor(parameters) {
+ super(parameters, {
+ ignoreBorder: parameters.data.hasAppearance
+ });
+ }
+ render() {
+ const container = super.render();
+ container.classList.add("buttonWidgetAnnotation", "pushButton");
+ if (this.data.alternativeText) {
+ container.title = this.data.alternativeText;
+ }
+ const linkElement = container.lastChild;
+ if (this.enableScripting && this.hasJSActions && linkElement) {
+ this._setDefaultPropertiesFromJS(linkElement);
+ linkElement.addEventListener("updatefromsandbox", jsEvent => {
+ this._dispatchEventFromSandbox({}, jsEvent);
+ });
+ }
+ return container;
+ }
+}
+class ChoiceWidgetAnnotationElement extends WidgetAnnotationElement {
+ constructor(parameters) {
+ super(parameters, {
+ isRenderable: parameters.renderForms
+ });
+ }
+ render() {
+ this.container.classList.add("choiceWidgetAnnotation");
+ const storage = this.annotationStorage;
+ const id = this.data.id;
+ const storedData = storage.getValue(id, {
+ value: this.data.fieldValue
+ });
+ const selectElement = document.createElement("select");
+ GetElementsByNameSet.add(selectElement);
+ selectElement.setAttribute("data-element-id", id);
+ selectElement.disabled = this.data.readOnly;
+ this._setRequired(selectElement, this.data.required);
+ selectElement.name = this.data.fieldName;
+ selectElement.tabIndex = DEFAULT_TAB_INDEX;
+ let addAnEmptyEntry = this.data.combo && this.data.options.length > 0;
+ if (!this.data.combo) {
+ selectElement.size = this.data.options.length;
+ if (this.data.multiSelect) {
+ selectElement.multiple = true;
+ }
+ }
+ selectElement.addEventListener("resetform", event => {
+ const defaultValue = this.data.defaultFieldValue;
+ for (const option of selectElement.options) {
+ option.selected = option.value === defaultValue;
+ }
+ });
+ for (const option of this.data.options) {
+ const optionElement = document.createElement("option");
+ optionElement.textContent = option.displayValue;
+ optionElement.value = option.exportValue;
+ if (storedData.value.includes(option.exportValue)) {
+ optionElement.setAttribute("selected", true);
+ addAnEmptyEntry = false;
+ }
+ selectElement.append(optionElement);
+ }
+ let removeEmptyEntry = null;
+ if (addAnEmptyEntry) {
+ const noneOptionElement = document.createElement("option");
+ noneOptionElement.value = " ";
+ noneOptionElement.setAttribute("hidden", true);
+ noneOptionElement.setAttribute("selected", true);
+ selectElement.prepend(noneOptionElement);
+ removeEmptyEntry = () => {
+ noneOptionElement.remove();
+ selectElement.removeEventListener("input", removeEmptyEntry);
+ removeEmptyEntry = null;
+ };
+ selectElement.addEventListener("input", removeEmptyEntry);
+ }
+ const getValue = isExport => {
+ const name = isExport ? "value" : "textContent";
+ const {
+ options,
+ multiple
+ } = selectElement;
+ if (!multiple) {
+ return options.selectedIndex === -1 ? null : options[options.selectedIndex][name];
+ }
+ return Array.prototype.filter.call(options, option => option.selected).map(option => option[name]);
+ };
+ let selectedValues = getValue(false);
+ const getItems = event => {
+ const options = event.target.options;
+ return Array.prototype.map.call(options, option => ({
+ displayValue: option.textContent,
+ exportValue: option.value
+ }));
+ };
+ if (this.enableScripting && this.hasJSActions) {
+ selectElement.addEventListener("updatefromsandbox", jsEvent => {
+ const actions = {
+ value(event) {
+ removeEmptyEntry?.();
+ const value = event.detail.value;
+ const values = new Set(Array.isArray(value) ? value : [value]);
+ for (const option of selectElement.options) {
+ option.selected = values.has(option.value);
+ }
+ storage.setValue(id, {
+ value: getValue(true)
+ });
+ selectedValues = getValue(false);
+ },
+ multipleSelection(event) {
+ selectElement.multiple = true;
+ },
+ remove(event) {
+ const options = selectElement.options;
+ const index = event.detail.remove;
+ options[index].selected = false;
+ selectElement.remove(index);
+ if (options.length > 0) {
+ const i = Array.prototype.findIndex.call(options, option => option.selected);
+ if (i === -1) {
+ options[0].selected = true;
+ }
+ }
+ storage.setValue(id, {
+ value: getValue(true),
+ items: getItems(event)
+ });
+ selectedValues = getValue(false);
+ },
+ clear(event) {
+ while (selectElement.length !== 0) {
+ selectElement.remove(0);
+ }
+ storage.setValue(id, {
+ value: null,
+ items: []
+ });
+ selectedValues = getValue(false);
+ },
+ insert(event) {
+ const {
+ index,
+ displayValue,
+ exportValue
+ } = event.detail.insert;
+ const selectChild = selectElement.children[index];
+ const optionElement = document.createElement("option");
+ optionElement.textContent = displayValue;
+ optionElement.value = exportValue;
+ if (selectChild) {
+ selectChild.before(optionElement);
+ } else {
+ selectElement.append(optionElement);
+ }
+ storage.setValue(id, {
+ value: getValue(true),
+ items: getItems(event)
+ });
+ selectedValues = getValue(false);
+ },
+ items(event) {
+ const {
+ items
+ } = event.detail;
+ while (selectElement.length !== 0) {
+ selectElement.remove(0);
+ }
+ for (const item of items) {
+ const {
+ displayValue,
+ exportValue
+ } = item;
+ const optionElement = document.createElement("option");
+ optionElement.textContent = displayValue;
+ optionElement.value = exportValue;
+ selectElement.append(optionElement);
+ }
+ if (selectElement.options.length > 0) {
+ selectElement.options[0].selected = true;
+ }
+ storage.setValue(id, {
+ value: getValue(true),
+ items: getItems(event)
+ });
+ selectedValues = getValue(false);
+ },
+ indices(event) {
+ const indices = new Set(event.detail.indices);
+ for (const option of event.target.options) {
+ option.selected = indices.has(option.index);
+ }
+ storage.setValue(id, {
+ value: getValue(true)
+ });
+ selectedValues = getValue(false);
+ },
+ editable(event) {
+ event.target.disabled = !event.detail.editable;
+ }
+ };
+ this._dispatchEventFromSandbox(actions, jsEvent);
+ });
+ selectElement.addEventListener("input", event => {
+ const exportValue = getValue(true);
+ storage.setValue(id, {
+ value: exportValue
+ });
+ event.preventDefault();
+ this.linkService.eventBus?.dispatch("dispatcheventinsandbox", {
+ source: this,
+ detail: {
+ id,
+ name: "Keystroke",
+ value: selectedValues,
+ changeEx: exportValue,
+ willCommit: false,
+ commitKey: 1,
+ keyDown: false
+ }
+ });
+ });
+ this._setEventListeners(selectElement, null, [["focus", "Focus"], ["blur", "Blur"], ["mousedown", "Mouse Down"], ["mouseenter", "Mouse Enter"], ["mouseleave", "Mouse Exit"], ["mouseup", "Mouse Up"], ["input", "Action"], ["input", "Validate"]], event => event.target.value);
+ } else {
+ selectElement.addEventListener("input", function (event) {
+ storage.setValue(id, {
+ value: getValue(true)
+ });
+ });
+ }
+ if (this.data.combo) {
+ this._setTextStyle(selectElement);
+ } else {}
+ this._setBackgroundColor(selectElement);
+ this._setDefaultPropertiesFromJS(selectElement);
+ this.container.append(selectElement);
+ return this.container;
+ }
+}
+class PopupAnnotationElement extends AnnotationElement {
+ constructor(parameters) {
+ const {
+ data,
+ elements
+ } = parameters;
+ super(parameters, {
+ isRenderable: AnnotationElement._hasPopupData(data)
+ });
+ this.elements = elements;
+ }
+ render() {
+ this.container.classList.add("popupAnnotation");
+ const popup = new PopupElement({
+ container: this.container,
+ color: this.data.color,
+ titleObj: this.data.titleObj,
+ modificationDate: this.data.modificationDate,
+ contentsObj: this.data.contentsObj,
+ richText: this.data.richText,
+ rect: this.data.rect,
+ parentRect: this.data.parentRect || null,
+ parent: this.parent,
+ elements: this.elements,
+ open: this.data.open
+ });
+ const elementIds = [];
+ for (const element of this.elements) {
+ element.popup = popup;
+ elementIds.push(element.data.id);
+ element.addHighlightArea();
+ }
+ this.container.setAttribute("aria-controls", elementIds.map(id => `${AnnotationPrefix}${id}`).join(","));
+ return this.container;
+ }
+}
+class PopupElement {
+ #boundKeyDown = this.#keyDown.bind(this);
+ #boundHide = this.#hide.bind(this);
+ #boundShow = this.#show.bind(this);
+ #boundToggle = this.#toggle.bind(this);
+ #color = null;
+ #container = null;
+ #contentsObj = null;
+ #dateObj = null;
+ #elements = null;
+ #parent = null;
+ #parentRect = null;
+ #pinned = false;
+ #popup = null;
+ #rect = null;
+ #richText = null;
+ #titleObj = null;
+ #wasVisible = false;
+ constructor({
+ container,
+ color,
+ elements,
+ titleObj,
+ modificationDate,
+ contentsObj,
+ richText,
+ parent,
+ rect,
+ parentRect,
+ open
+ }) {
+ this.#container = container;
+ this.#titleObj = titleObj;
+ this.#contentsObj = contentsObj;
+ this.#richText = richText;
+ this.#parent = parent;
+ this.#color = color;
+ this.#rect = rect;
+ this.#parentRect = parentRect;
+ this.#elements = elements;
+ this.#dateObj = PDFDateString.toDateObject(modificationDate);
+ this.trigger = elements.flatMap(e => e.getElementsToTriggerPopup());
+ for (const element of this.trigger) {
+ element.addEventListener("click", this.#boundToggle);
+ element.addEventListener("mouseenter", this.#boundShow);
+ element.addEventListener("mouseleave", this.#boundHide);
+ element.classList.add("popupTriggerArea");
+ }
+ for (const element of elements) {
+ element.container?.addEventListener("keydown", this.#boundKeyDown);
+ }
+ this.#container.hidden = true;
+ if (open) {
+ this.#toggle();
+ }
+ }
+ render() {
+ if (this.#popup) {
+ return;
+ }
+ const {
+ page: {
+ view
+ },
+ viewport: {
+ rawDims: {
+ pageWidth,
+ pageHeight,
+ pageX,
+ pageY
+ }
+ }
+ } = this.#parent;
+ const popup = this.#popup = document.createElement("div");
+ popup.className = "popup";
+ if (this.#color) {
+ const baseColor = popup.style.outlineColor = Util.makeHexColor(...this.#color);
+ popup.style.backgroundColor = `color-mix(in srgb, ${baseColor} 30%, white)`;
+ }
+ const header = document.createElement("span");
+ header.className = "header";
+ const title = document.createElement("h1");
+ header.append(title);
+ ({
+ dir: title.dir,
+ str: title.textContent
+ } = this.#titleObj);
+ popup.append(header);
+ if (this.#dateObj) {
+ const modificationDate = document.createElement("span");
+ modificationDate.classList.add("popupDate");
+ modificationDate.setAttribute("data-l10n-id", "pdfjs-annotation-date-string");
+ modificationDate.setAttribute("data-l10n-args", JSON.stringify({
+ date: this.#dateObj.toLocaleDateString(),
+ time: this.#dateObj.toLocaleTimeString()
+ }));
+ header.append(modificationDate);
+ }
+ const contentsObj = this.#contentsObj;
+ const richText = this.#richText;
+ if (richText?.str && (!contentsObj?.str || contentsObj.str === richText.str)) {
+ XfaLayer.render({
+ xfaHtml: richText.html,
+ intent: "richText",
+ div: popup
+ });
+ popup.lastChild.classList.add("richText", "popupContent");
+ } else {
+ const contents = this._formatContents(contentsObj);
+ popup.append(contents);
+ }
+ let useParentRect = !!this.#parentRect;
+ let rect = useParentRect ? this.#parentRect : this.#rect;
+ for (const element of this.#elements) {
+ if (!rect || Util.intersect(element.data.rect, rect) !== null) {
+ rect = element.data.rect;
+ useParentRect = true;
+ break;
+ }
+ }
+ const normalizedRect = Util.normalizeRect([rect[0], view[3] - rect[1] + view[1], rect[2], view[3] - rect[3] + view[1]]);
+ const HORIZONTAL_SPACE_AFTER_ANNOTATION = 5;
+ const parentWidth = useParentRect ? rect[2] - rect[0] + HORIZONTAL_SPACE_AFTER_ANNOTATION : 0;
+ const popupLeft = normalizedRect[0] + parentWidth;
+ const popupTop = normalizedRect[1];
+ const {
+ style
+ } = this.#container;
+ style.left = `${100 * (popupLeft - pageX) / pageWidth}%`;
+ style.top = `${100 * (popupTop - pageY) / pageHeight}%`;
+ this.#container.append(popup);
+ }
+ _formatContents({
+ str,
+ dir
+ }) {
+ const p = document.createElement("p");
+ p.classList.add("popupContent");
+ p.dir = dir;
+ const lines = str.split(/(?:\r\n?|\n)/);
+ for (let i = 0, ii = lines.length; i < ii; ++i) {
+ const line = lines[i];
+ p.append(document.createTextNode(line));
+ if (i < ii - 1) {
+ p.append(document.createElement("br"));
+ }
+ }
+ return p;
+ }
+ #keyDown(event) {
+ if (event.altKey || event.shiftKey || event.ctrlKey || event.metaKey) {
+ return;
+ }
+ if (event.key === "Enter" || event.key === "Escape" && this.#pinned) {
+ this.#toggle();
+ }
+ }
+ #toggle() {
+ this.#pinned = !this.#pinned;
+ if (this.#pinned) {
+ this.#show();
+ this.#container.addEventListener("click", this.#boundToggle);
+ this.#container.addEventListener("keydown", this.#boundKeyDown);
+ } else {
+ this.#hide();
+ this.#container.removeEventListener("click", this.#boundToggle);
+ this.#container.removeEventListener("keydown", this.#boundKeyDown);
+ }
+ }
+ #show() {
+ if (!this.#popup) {
+ this.render();
+ }
+ if (!this.isVisible) {
+ this.#container.hidden = false;
+ this.#container.style.zIndex = parseInt(this.#container.style.zIndex) + 1000;
+ } else if (this.#pinned) {
+ this.#container.classList.add("focused");
+ }
+ }
+ #hide() {
+ this.#container.classList.remove("focused");
+ if (this.#pinned || !this.isVisible) {
+ return;
+ }
+ this.#container.hidden = true;
+ this.#container.style.zIndex = parseInt(this.#container.style.zIndex) - 1000;
+ }
+ forceHide() {
+ this.#wasVisible = this.isVisible;
+ if (!this.#wasVisible) {
+ return;
+ }
+ this.#container.hidden = true;
+ }
+ maybeShow() {
+ if (!this.#wasVisible) {
+ return;
+ }
+ this.#wasVisible = false;
+ this.#container.hidden = false;
+ }
+ get isVisible() {
+ return this.#container.hidden === false;
+ }
+}
+class FreeTextAnnotationElement extends AnnotationElement {
+ constructor(parameters) {
+ super(parameters, {
+ isRenderable: true,
+ ignoreBorder: true
+ });
+ this.textContent = parameters.data.textContent;
+ this.textPosition = parameters.data.textPosition;
+ this.annotationEditorType = AnnotationEditorType.FREETEXT;
+ }
+ render() {
+ this.container.classList.add("freeTextAnnotation");
+ if (this.textContent) {
+ const content = document.createElement("div");
+ content.classList.add("annotationTextContent");
+ content.setAttribute("role", "comment");
+ for (const line of this.textContent) {
+ const lineSpan = document.createElement("span");
+ lineSpan.textContent = line;
+ content.append(lineSpan);
+ }
+ this.container.append(content);
+ }
+ if (!this.data.popupRef && this.hasPopupData) {
+ this._createPopup();
+ }
+ this._editOnDoubleClick();
+ return this.container;
+ }
+ get _isEditable() {
+ return this.data.hasOwnCanvas;
+ }
+}
+class LineAnnotationElement extends AnnotationElement {
+ #line = null;
+ constructor(parameters) {
+ super(parameters, {
+ isRenderable: true,
+ ignoreBorder: true
+ });
+ }
+ render() {
+ this.container.classList.add("lineAnnotation");
+ const data = this.data;
+ const {
+ width,
+ height
+ } = getRectDims(data.rect);
+ const svg = this.svgFactory.create(width, height, true);
+ const line = this.#line = this.svgFactory.createElement("svg:line");
+ line.setAttribute("x1", data.rect[2] - data.lineCoordinates[0]);
+ line.setAttribute("y1", data.rect[3] - data.lineCoordinates[1]);
+ line.setAttribute("x2", data.rect[2] - data.lineCoordinates[2]);
+ line.setAttribute("y2", data.rect[3] - data.lineCoordinates[3]);
+ line.setAttribute("stroke-width", data.borderStyle.width || 1);
+ line.setAttribute("stroke", "transparent");
+ line.setAttribute("fill", "transparent");
+ svg.append(line);
+ this.container.append(svg);
+ if (!data.popupRef && this.hasPopupData) {
+ this._createPopup();
+ }
+ return this.container;
+ }
+ getElementsToTriggerPopup() {
+ return this.#line;
+ }
+ addHighlightArea() {
+ this.container.classList.add("highlightArea");
+ }
+}
+class SquareAnnotationElement extends AnnotationElement {
+ #square = null;
+ constructor(parameters) {
+ super(parameters, {
+ isRenderable: true,
+ ignoreBorder: true
+ });
+ }
+ render() {
+ this.container.classList.add("squareAnnotation");
+ const data = this.data;
+ const {
+ width,
+ height
+ } = getRectDims(data.rect);
+ const svg = this.svgFactory.create(width, height, true);
+ const borderWidth = data.borderStyle.width;
+ const square = this.#square = this.svgFactory.createElement("svg:rect");
+ square.setAttribute("x", borderWidth / 2);
+ square.setAttribute("y", borderWidth / 2);
+ square.setAttribute("width", width - borderWidth);
+ square.setAttribute("height", height - borderWidth);
+ square.setAttribute("stroke-width", borderWidth || 1);
+ square.setAttribute("stroke", "transparent");
+ square.setAttribute("fill", "transparent");
+ svg.append(square);
+ this.container.append(svg);
+ if (!data.popupRef && this.hasPopupData) {
+ this._createPopup();
+ }
+ return this.container;
+ }
+ getElementsToTriggerPopup() {
+ return this.#square;
+ }
+ addHighlightArea() {
+ this.container.classList.add("highlightArea");
+ }
+}
+class CircleAnnotationElement extends AnnotationElement {
+ #circle = null;
+ constructor(parameters) {
+ super(parameters, {
+ isRenderable: true,
+ ignoreBorder: true
+ });
+ }
+ render() {
+ this.container.classList.add("circleAnnotation");
+ const data = this.data;
+ const {
+ width,
+ height
+ } = getRectDims(data.rect);
+ const svg = this.svgFactory.create(width, height, true);
+ const borderWidth = data.borderStyle.width;
+ const circle = this.#circle = this.svgFactory.createElement("svg:ellipse");
+ circle.setAttribute("cx", width / 2);
+ circle.setAttribute("cy", height / 2);
+ circle.setAttribute("rx", width / 2 - borderWidth / 2);
+ circle.setAttribute("ry", height / 2 - borderWidth / 2);
+ circle.setAttribute("stroke-width", borderWidth || 1);
+ circle.setAttribute("stroke", "transparent");
+ circle.setAttribute("fill", "transparent");
+ svg.append(circle);
+ this.container.append(svg);
+ if (!data.popupRef && this.hasPopupData) {
+ this._createPopup();
+ }
+ return this.container;
+ }
+ getElementsToTriggerPopup() {
+ return this.#circle;
+ }
+ addHighlightArea() {
+ this.container.classList.add("highlightArea");
+ }
+}
+class PolylineAnnotationElement extends AnnotationElement {
+ #polyline = null;
+ constructor(parameters) {
+ super(parameters, {
+ isRenderable: true,
+ ignoreBorder: true
+ });
+ this.containerClassName = "polylineAnnotation";
+ this.svgElementName = "svg:polyline";
+ }
+ render() {
+ this.container.classList.add(this.containerClassName);
+ const data = this.data;
+ const {
+ width,
+ height
+ } = getRectDims(data.rect);
+ const svg = this.svgFactory.create(width, height, true);
+ let points = [];
+ for (const coordinate of data.vertices) {
+ const x = coordinate.x - data.rect[0];
+ const y = data.rect[3] - coordinate.y;
+ points.push(x + "," + y);
+ }
+ points = points.join(" ");
+ const polyline = this.#polyline = this.svgFactory.createElement(this.svgElementName);
+ polyline.setAttribute("points", points);
+ polyline.setAttribute("stroke-width", data.borderStyle.width || 1);
+ polyline.setAttribute("stroke", "transparent");
+ polyline.setAttribute("fill", "transparent");
+ svg.append(polyline);
+ this.container.append(svg);
+ if (!data.popupRef && this.hasPopupData) {
+ this._createPopup();
+ }
+ return this.container;
+ }
+ getElementsToTriggerPopup() {
+ return this.#polyline;
+ }
+ addHighlightArea() {
+ this.container.classList.add("highlightArea");
+ }
+}
+class PolygonAnnotationElement extends PolylineAnnotationElement {
+ constructor(parameters) {
+ super(parameters);
+ this.containerClassName = "polygonAnnotation";
+ this.svgElementName = "svg:polygon";
+ }
+}
+class CaretAnnotationElement extends AnnotationElement {
+ constructor(parameters) {
+ super(parameters, {
+ isRenderable: true,
+ ignoreBorder: true
+ });
+ }
+ render() {
+ this.container.classList.add("caretAnnotation");
+ if (!this.data.popupRef && this.hasPopupData) {
+ this._createPopup();
+ }
+ return this.container;
+ }
+}
+class InkAnnotationElement extends AnnotationElement {
+ #polylines = [];
+ constructor(parameters) {
+ super(parameters, {
+ isRenderable: true,
+ ignoreBorder: true
+ });
+ this.containerClassName = "inkAnnotation";
+ this.svgElementName = "svg:polyline";
+ this.annotationEditorType = AnnotationEditorType.INK;
+ }
+ render() {
+ this.container.classList.add(this.containerClassName);
+ const data = this.data;
+ const {
+ width,
+ height
+ } = getRectDims(data.rect);
+ const svg = this.svgFactory.create(width, height, true);
+ for (const inkList of data.inkLists) {
+ let points = [];
+ for (const coordinate of inkList) {
+ const x = coordinate.x - data.rect[0];
+ const y = data.rect[3] - coordinate.y;
+ points.push(`${x},${y}`);
+ }
+ points = points.join(" ");
+ const polyline = this.svgFactory.createElement(this.svgElementName);
+ this.#polylines.push(polyline);
+ polyline.setAttribute("points", points);
+ polyline.setAttribute("stroke-width", data.borderStyle.width || 1);
+ polyline.setAttribute("stroke", "transparent");
+ polyline.setAttribute("fill", "transparent");
+ if (!data.popupRef && this.hasPopupData) {
+ this._createPopup();
+ }
+ svg.append(polyline);
+ }
+ this.container.append(svg);
+ return this.container;
+ }
+ getElementsToTriggerPopup() {
+ return this.#polylines;
+ }
+ addHighlightArea() {
+ this.container.classList.add("highlightArea");
+ }
+}
+class HighlightAnnotationElement extends AnnotationElement {
+ constructor(parameters) {
+ super(parameters, {
+ isRenderable: true,
+ ignoreBorder: true,
+ createQuadrilaterals: true
+ });
+ }
+ render() {
+ if (!this.data.popupRef && this.hasPopupData) {
+ this._createPopup();
+ }
+ this.container.classList.add("highlightAnnotation");
+ return this.container;
+ }
+}
+class UnderlineAnnotationElement extends AnnotationElement {
+ constructor(parameters) {
+ super(parameters, {
+ isRenderable: true,
+ ignoreBorder: true,
+ createQuadrilaterals: true
+ });
+ }
+ render() {
+ if (!this.data.popupRef && this.hasPopupData) {
+ this._createPopup();
+ }
+ this.container.classList.add("underlineAnnotation");
+ return this.container;
+ }
+}
+class SquigglyAnnotationElement extends AnnotationElement {
+ constructor(parameters) {
+ super(parameters, {
+ isRenderable: true,
+ ignoreBorder: true,
+ createQuadrilaterals: true
+ });
+ }
+ render() {
+ if (!this.data.popupRef && this.hasPopupData) {
+ this._createPopup();
+ }
+ this.container.classList.add("squigglyAnnotation");
+ return this.container;
+ }
+}
+class StrikeOutAnnotationElement extends AnnotationElement {
+ constructor(parameters) {
+ super(parameters, {
+ isRenderable: true,
+ ignoreBorder: true,
+ createQuadrilaterals: true
+ });
+ }
+ render() {
+ if (!this.data.popupRef && this.hasPopupData) {
+ this._createPopup();
+ }
+ this.container.classList.add("strikeoutAnnotation");
+ return this.container;
+ }
+}
+class StampAnnotationElement extends AnnotationElement {
+ constructor(parameters) {
+ super(parameters, {
+ isRenderable: true,
+ ignoreBorder: true
+ });
+ }
+ render() {
+ this.container.classList.add("stampAnnotation");
+ if (!this.data.popupRef && this.hasPopupData) {
+ this._createPopup();
+ }
+ return this.container;
+ }
+}
+class FileAttachmentAnnotationElement extends AnnotationElement {
+ #trigger = null;
+ constructor(parameters) {
+ super(parameters, {
+ isRenderable: true
+ });
+ const {
+ filename,
+ content
+ } = this.data.file;
+ this.filename = getFilenameFromUrl(filename, true);
+ this.content = content;
+ this.linkService.eventBus?.dispatch("fileattachmentannotation", {
+ source: this,
+ filename,
+ content
+ });
+ }
+ render() {
+ this.container.classList.add("fileAttachmentAnnotation");
+ const {
+ container,
+ data
+ } = this;
+ let trigger;
+ if (data.hasAppearance || data.fillAlpha === 0) {
+ trigger = document.createElement("div");
+ } else {
+ trigger = document.createElement("img");
+ trigger.src = `${this.imageResourcesPath}annotation-${/paperclip/i.test(data.name) ? "paperclip" : "pushpin"}.svg`;
+ if (data.fillAlpha && data.fillAlpha < 1) {
+ trigger.style = `filter: opacity(${Math.round(data.fillAlpha * 100)}%);`;
+ }
+ }
+ trigger.addEventListener("dblclick", this.#download.bind(this));
+ this.#trigger = trigger;
+ const {
+ isMac
+ } = util_FeatureTest.platform;
+ container.addEventListener("keydown", evt => {
+ if (evt.key === "Enter" && (isMac ? evt.metaKey : evt.ctrlKey)) {
+ this.#download();
+ }
+ });
+ if (!data.popupRef && this.hasPopupData) {
+ this._createPopup();
+ } else {
+ trigger.classList.add("popupTriggerArea");
+ }
+ container.append(trigger);
+ return container;
+ }
+ getElementsToTriggerPopup() {
+ return this.#trigger;
+ }
+ addHighlightArea() {
+ this.container.classList.add("highlightArea");
+ }
+ #download() {
+ this.downloadManager?.openOrDownloadData(this.content, this.filename);
+ }
+}
+class AnnotationLayer {
+ #accessibilityManager = null;
+ #annotationCanvasMap = null;
+ #editableAnnotations = new Map();
+ constructor({
+ div,
+ accessibilityManager,
+ annotationCanvasMap,
+ page,
+ viewport
+ }) {
+ this.div = div;
+ this.#accessibilityManager = accessibilityManager;
+ this.#annotationCanvasMap = annotationCanvasMap;
+ this.page = page;
+ this.viewport = viewport;
+ this.zIndex = 0;
+ }
+ #appendElement(element, id) {
+ const contentElement = element.firstChild || element;
+ contentElement.id = `${AnnotationPrefix}${id}`;
+ this.div.append(element);
+ this.#accessibilityManager?.moveElementInDOM(this.div, element, contentElement, false);
+ }
+ async render(params) {
+ const {
+ annotations
+ } = params;
+ const layer = this.div;
+ setLayerDimensions(layer, this.viewport);
+ const popupToElements = new Map();
+ const elementParams = {
+ data: null,
+ layer,
+ linkService: params.linkService,
+ downloadManager: params.downloadManager,
+ imageResourcesPath: params.imageResourcesPath || "",
+ renderForms: params.renderForms !== false,
+ svgFactory: new DOMSVGFactory(),
+ annotationStorage: params.annotationStorage || new AnnotationStorage(),
+ enableScripting: params.enableScripting === true,
+ hasJSActions: params.hasJSActions,
+ fieldObjects: params.fieldObjects,
+ parent: this,
+ elements: null
+ };
+ for (const data of annotations) {
+ if (data.noHTML) {
+ continue;
+ }
+ const isPopupAnnotation = data.annotationType === AnnotationType.POPUP;
+ if (!isPopupAnnotation) {
+ const {
+ width,
+ height
+ } = getRectDims(data.rect);
+ if (width <= 0 || height <= 0) {
+ continue;
+ }
+ } else {
+ const elements = popupToElements.get(data.id);
+ if (!elements) {
+ continue;
+ }
+ elementParams.elements = elements;
+ }
+ elementParams.data = data;
+ const element = AnnotationElementFactory.create(elementParams);
+ if (!element.isRenderable) {
+ continue;
+ }
+ if (!isPopupAnnotation && data.popupRef) {
+ const elements = popupToElements.get(data.popupRef);
+ if (!elements) {
+ popupToElements.set(data.popupRef, [element]);
+ } else {
+ elements.push(element);
+ }
+ }
+ if (element.annotationEditorType > 0) {
+ this.#editableAnnotations.set(element.data.id, element);
+ }
+ const rendered = element.render();
+ if (data.hidden) {
+ rendered.style.visibility = "hidden";
+ }
+ this.#appendElement(rendered, data.id);
+ }
+ this.#setAnnotationCanvasMap();
+ }
+ update({
+ viewport
+ }) {
+ const layer = this.div;
+ this.viewport = viewport;
+ setLayerDimensions(layer, {
+ rotation: viewport.rotation
+ });
+ this.#setAnnotationCanvasMap();
+ layer.hidden = false;
+ }
+ #setAnnotationCanvasMap() {
+ if (!this.#annotationCanvasMap) {
+ return;
+ }
+ const layer = this.div;
+ for (const [id, canvas] of this.#annotationCanvasMap) {
+ const element = layer.querySelector(`[data-annotation-id="${id}"]`);
+ if (!element) {
+ continue;
+ }
+ const {
+ firstChild
+ } = element;
+ if (!firstChild) {
+ element.append(canvas);
+ } else if (firstChild.nodeName === "CANVAS") {
+ firstChild.replaceWith(canvas);
+ } else {
+ firstChild.before(canvas);
+ }
+ }
+ this.#annotationCanvasMap.clear();
+ }
+ getEditableAnnotations() {
+ return Array.from(this.#editableAnnotations.values());
+ }
+ getEditableAnnotation(id) {
+ return this.#editableAnnotations.get(id);
+ }
+}
+
+;// CONCATENATED MODULE: ./src/display/editor/freetext.js
+
+
+
+
+class FreeTextEditor extends AnnotationEditor {
+ #boundEditorDivBlur = this.editorDivBlur.bind(this);
+ #boundEditorDivFocus = this.editorDivFocus.bind(this);
+ #boundEditorDivInput = this.editorDivInput.bind(this);
+ #boundEditorDivKeydown = this.editorDivKeydown.bind(this);
+ #color;
+ #content = "";
+ #editorDivId = `${this.id}-editor`;
+ #fontSize;
+ #initialData = null;
+ static _freeTextDefaultContent = "";
+ static _internalPadding = 0;
+ static _defaultColor = null;
+ static _defaultFontSize = 10;
+ static get _keyboardManager() {
+ const proto = FreeTextEditor.prototype;
+ const arrowChecker = self => self.isEmpty();
+ const small = AnnotationEditorUIManager.TRANSLATE_SMALL;
+ const big = AnnotationEditorUIManager.TRANSLATE_BIG;
+ return shadow(this, "_keyboardManager", new KeyboardManager([[["ctrl+s", "mac+meta+s", "ctrl+p", "mac+meta+p"], proto.commitOrRemove, {
+ bubbles: true
+ }], [["ctrl+Enter", "mac+meta+Enter", "Escape", "mac+Escape"], proto.commitOrRemove], [["ArrowLeft", "mac+ArrowLeft"], proto._translateEmpty, {
+ args: [-small, 0],
+ checker: arrowChecker
+ }], [["ctrl+ArrowLeft", "mac+shift+ArrowLeft"], proto._translateEmpty, {
+ args: [-big, 0],
+ checker: arrowChecker
+ }], [["ArrowRight", "mac+ArrowRight"], proto._translateEmpty, {
+ args: [small, 0],
+ checker: arrowChecker
+ }], [["ctrl+ArrowRight", "mac+shift+ArrowRight"], proto._translateEmpty, {
+ args: [big, 0],
+ checker: arrowChecker
+ }], [["ArrowUp", "mac+ArrowUp"], proto._translateEmpty, {
+ args: [0, -small],
+ checker: arrowChecker
+ }], [["ctrl+ArrowUp", "mac+shift+ArrowUp"], proto._translateEmpty, {
+ args: [0, -big],
+ checker: arrowChecker
+ }], [["ArrowDown", "mac+ArrowDown"], proto._translateEmpty, {
+ args: [0, small],
+ checker: arrowChecker
+ }], [["ctrl+ArrowDown", "mac+shift+ArrowDown"], proto._translateEmpty, {
+ args: [0, big],
+ checker: arrowChecker
+ }]]));
+ }
+ static _type = "freetext";
+ static _editorType = AnnotationEditorType.FREETEXT;
+ constructor(params) {
+ super({
+ ...params,
+ name: "freeTextEditor"
+ });
+ this.#color = params.color || FreeTextEditor._defaultColor || AnnotationEditor._defaultLineColor;
+ this.#fontSize = params.fontSize || FreeTextEditor._defaultFontSize;
+ }
+ static initialize(l10n, uiManager) {
+ AnnotationEditor.initialize(l10n, uiManager, {
+ strings: ["pdfjs-free-text-default-content"]
+ });
+ const style = getComputedStyle(document.documentElement);
+ this._internalPadding = parseFloat(style.getPropertyValue("--freetext-padding"));
+ }
+ static updateDefaultParams(type, value) {
+ switch (type) {
+ case AnnotationEditorParamsType.FREETEXT_SIZE:
+ FreeTextEditor._defaultFontSize = value;
+ break;
+ case AnnotationEditorParamsType.FREETEXT_COLOR:
+ FreeTextEditor._defaultColor = value;
+ break;
+ }
+ }
+ updateParams(type, value) {
+ switch (type) {
+ case AnnotationEditorParamsType.FREETEXT_SIZE:
+ this.#updateFontSize(value);
+ break;
+ case AnnotationEditorParamsType.FREETEXT_COLOR:
+ this.#updateColor(value);
+ break;
+ }
+ }
+ static get defaultPropertiesToUpdate() {
+ return [[AnnotationEditorParamsType.FREETEXT_SIZE, FreeTextEditor._defaultFontSize], [AnnotationEditorParamsType.FREETEXT_COLOR, FreeTextEditor._defaultColor || AnnotationEditor._defaultLineColor]];
+ }
+ get propertiesToUpdate() {
+ return [[AnnotationEditorParamsType.FREETEXT_SIZE, this.#fontSize], [AnnotationEditorParamsType.FREETEXT_COLOR, this.#color]];
+ }
+ #updateFontSize(fontSize) {
+ const setFontsize = size => {
+ this.editorDiv.style.fontSize = `calc(${size}px * var(--scale-factor))`;
+ this.translate(0, -(size - this.#fontSize) * this.parentScale);
+ this.#fontSize = size;
+ this.#setEditorDimensions();
+ };
+ const savedFontsize = this.#fontSize;
+ this.addCommands({
+ cmd: setFontsize.bind(this, fontSize),
+ undo: setFontsize.bind(this, savedFontsize),
+ post: this._uiManager.updateUI.bind(this._uiManager, this),
+ mustExec: true,
+ type: AnnotationEditorParamsType.FREETEXT_SIZE,
+ overwriteIfSameType: true,
+ keepUndo: true
+ });
+ }
+ #updateColor(color) {
+ const setColor = col => {
+ this.#color = this.editorDiv.style.color = col;
+ };
+ const savedColor = this.#color;
+ this.addCommands({
+ cmd: setColor.bind(this, color),
+ undo: setColor.bind(this, savedColor),
+ post: this._uiManager.updateUI.bind(this._uiManager, this),
+ mustExec: true,
+ type: AnnotationEditorParamsType.FREETEXT_COLOR,
+ overwriteIfSameType: true,
+ keepUndo: true
+ });
+ }
+ _translateEmpty(x, y) {
+ this._uiManager.translateSelectedEditors(x, y, true);
+ }
+ getInitialTranslation() {
+ const scale = this.parentScale;
+ return [-FreeTextEditor._internalPadding * scale, -(FreeTextEditor._internalPadding + this.#fontSize) * scale];
+ }
+ rebuild() {
+ if (!this.parent) {
+ return;
+ }
+ super.rebuild();
+ if (this.div === null) {
+ return;
+ }
+ if (!this.isAttachedToDOM) {
+ this.parent.add(this);
+ }
+ }
+ enableEditMode() {
+ if (this.isInEditMode()) {
+ return;
+ }
+ this.parent.setEditingState(false);
+ this.parent.updateToolbar(AnnotationEditorType.FREETEXT);
+ super.enableEditMode();
+ this.overlayDiv.classList.remove("enabled");
+ this.editorDiv.contentEditable = true;
+ this._isDraggable = false;
+ this.div.removeAttribute("aria-activedescendant");
+ this.editorDiv.addEventListener("keydown", this.#boundEditorDivKeydown);
+ this.editorDiv.addEventListener("focus", this.#boundEditorDivFocus);
+ this.editorDiv.addEventListener("blur", this.#boundEditorDivBlur);
+ this.editorDiv.addEventListener("input", this.#boundEditorDivInput);
+ }
+ disableEditMode() {
+ if (!this.isInEditMode()) {
+ return;
+ }
+ this.parent.setEditingState(true);
+ super.disableEditMode();
+ this.overlayDiv.classList.add("enabled");
+ this.editorDiv.contentEditable = false;
+ this.div.setAttribute("aria-activedescendant", this.#editorDivId);
+ this._isDraggable = true;
+ this.editorDiv.removeEventListener("keydown", this.#boundEditorDivKeydown);
+ this.editorDiv.removeEventListener("focus", this.#boundEditorDivFocus);
+ this.editorDiv.removeEventListener("blur", this.#boundEditorDivBlur);
+ this.editorDiv.removeEventListener("input", this.#boundEditorDivInput);
+ this.div.focus({
+ preventScroll: true
+ });
+ this.isEditing = false;
+ this.parent.div.classList.add("freetextEditing");
+ }
+ focusin(event) {
+ if (!this._focusEventsAllowed) {
+ return;
+ }
+ super.focusin(event);
+ if (event.target !== this.editorDiv) {
+ this.editorDiv.focus();
+ }
+ }
+ onceAdded() {
+ if (this.width) {
+ this.#cheatInitialRect();
+ return;
+ }
+ this.enableEditMode();
+ this.editorDiv.focus();
+ if (this._initialOptions?.isCentered) {
+ this.center();
+ }
+ this._initialOptions = null;
+ }
+ isEmpty() {
+ return !this.editorDiv || this.editorDiv.innerText.trim() === "";
+ }
+ remove() {
+ this.isEditing = false;
+ if (this.parent) {
+ this.parent.setEditingState(true);
+ this.parent.div.classList.add("freetextEditing");
+ }
+ super.remove();
+ }
+ #extractText() {
+ const buffer = [];
+ this.editorDiv.normalize();
+ const EOL_PATTERN = /\r\n?|\n/g;
+ for (const child of this.editorDiv.childNodes) {
+ const content = child.nodeType === Node.TEXT_NODE ? child.nodeValue : child.innerText;
+ buffer.push(content.replaceAll(EOL_PATTERN, ""));
+ }
+ return buffer.join("\n");
+ }
+ #setEditorDimensions() {
+ const [parentWidth, parentHeight] = this.parentDimensions;
+ let rect;
+ if (this.isAttachedToDOM) {
+ rect = this.div.getBoundingClientRect();
+ } else {
+ const {
+ currentLayer,
+ div
+ } = this;
+ const savedDisplay = div.style.display;
+ div.style.display = "hidden";
+ currentLayer.div.append(this.div);
+ rect = div.getBoundingClientRect();
+ div.remove();
+ div.style.display = savedDisplay;
+ }
+ if (this.rotation % 180 === this.parentRotation % 180) {
+ this.width = rect.width / parentWidth;
+ this.height = rect.height / parentHeight;
+ } else {
+ this.width = rect.height / parentWidth;
+ this.height = rect.width / parentHeight;
+ }
+ this.fixAndSetPosition();
+ }
+ commit() {
+ if (!this.isInEditMode()) {
+ return;
+ }
+ super.commit();
+ this.disableEditMode();
+ const savedText = this.#content;
+ const newText = this.#content = this.#extractText().trimEnd();
+ if (savedText === newText) {
+ return;
+ }
+ const setText = text => {
+ this.#content = text;
+ if (!text) {
+ this.remove();
+ return;
+ }
+ this.#setContent();
+ this._uiManager.rebuild(this);
+ this.#setEditorDimensions();
+ };
+ this.addCommands({
+ cmd: () => {
+ setText(newText);
+ },
+ undo: () => {
+ setText(savedText);
+ },
+ mustExec: false
+ });
+ this.#setEditorDimensions();
+ }
+ shouldGetKeyboardEvents() {
+ return this.isInEditMode();
+ }
+ enterInEditMode() {
+ this.enableEditMode();
+ this.editorDiv.focus();
+ }
+ dblclick(event) {
+ this.enterInEditMode();
+ }
+ keydown(event) {
+ if (event.target === this.div && event.key === "Enter") {
+ this.enterInEditMode();
+ event.preventDefault();
+ }
+ }
+ editorDivKeydown(event) {
+ FreeTextEditor._keyboardManager.exec(this, event);
+ }
+ editorDivFocus(event) {
+ this.isEditing = true;
+ }
+ editorDivBlur(event) {
+ this.isEditing = false;
+ }
+ editorDivInput(event) {
+ this.parent.div.classList.toggle("freetextEditing", this.isEmpty());
+ }
+ disableEditing() {
+ this.editorDiv.setAttribute("role", "comment");
+ this.editorDiv.removeAttribute("aria-multiline");
+ }
+ enableEditing() {
+ this.editorDiv.setAttribute("role", "textbox");
+ this.editorDiv.setAttribute("aria-multiline", true);
+ }
+ render() {
+ if (this.div) {
+ return this.div;
+ }
+ let baseX, baseY;
+ if (this.width) {
+ baseX = this.x;
+ baseY = this.y;
+ }
+ super.render();
+ this.editorDiv = document.createElement("div");
+ this.editorDiv.className = "internal";
+ this.editorDiv.setAttribute("id", this.#editorDivId);
+ this.editorDiv.setAttribute("data-l10n-id", "pdfjs-free-text");
+ this.enableEditing();
+ AnnotationEditor._l10nPromise.get("pdfjs-free-text-default-content").then(msg => this.editorDiv?.setAttribute("default-content", msg));
+ this.editorDiv.contentEditable = true;
+ const {
+ style
+ } = this.editorDiv;
+ style.fontSize = `calc(${this.#fontSize}px * var(--scale-factor))`;
+ style.color = this.#color;
+ this.div.append(this.editorDiv);
+ this.overlayDiv = document.createElement("div");
+ this.overlayDiv.classList.add("overlay", "enabled");
+ this.div.append(this.overlayDiv);
+ bindEvents(this, this.div, ["dblclick", "keydown"]);
+ if (this.width) {
+ const [parentWidth, parentHeight] = this.parentDimensions;
+ if (this.annotationElementId) {
+ const {
+ position
+ } = this.#initialData;
+ let [tx, ty] = this.getInitialTranslation();
+ [tx, ty] = this.pageTranslationToScreen(tx, ty);
+ const [pageWidth, pageHeight] = this.pageDimensions;
+ const [pageX, pageY] = this.pageTranslation;
+ let posX, posY;
+ switch (this.rotation) {
+ case 0:
+ posX = baseX + (position[0] - pageX) / pageWidth;
+ posY = baseY + this.height - (position[1] - pageY) / pageHeight;
+ break;
+ case 90:
+ posX = baseX + (position[0] - pageX) / pageWidth;
+ posY = baseY - (position[1] - pageY) / pageHeight;
+ [tx, ty] = [ty, -tx];
+ break;
+ case 180:
+ posX = baseX - this.width + (position[0] - pageX) / pageWidth;
+ posY = baseY - (position[1] - pageY) / pageHeight;
+ [tx, ty] = [-tx, -ty];
+ break;
+ case 270:
+ posX = baseX + (position[0] - pageX - this.height * pageHeight) / pageWidth;
+ posY = baseY + (position[1] - pageY - this.width * pageWidth) / pageHeight;
+ [tx, ty] = [-ty, tx];
+ break;
+ }
+ this.setAt(posX * parentWidth, posY * parentHeight, tx, ty);
+ } else {
+ this.setAt(baseX * parentWidth, baseY * parentHeight, this.width * parentWidth, this.height * parentHeight);
+ }
+ this.#setContent();
+ this._isDraggable = true;
+ this.editorDiv.contentEditable = false;
+ } else {
+ this._isDraggable = false;
+ this.editorDiv.contentEditable = true;
+ }
+ return this.div;
+ }
+ #setContent() {
+ this.editorDiv.replaceChildren();
+ if (!this.#content) {
+ return;
+ }
+ for (const line of this.#content.split("\n")) {
+ const div = document.createElement("div");
+ div.append(line ? document.createTextNode(line) : document.createElement("br"));
+ this.editorDiv.append(div);
+ }
+ }
+ #serializeContent() {
+ return this.#content.replaceAll("\xa0", " ");
+ }
+ static #deserializeContent(content) {
+ return content.replaceAll(" ", "\xa0");
+ }
+ get contentDiv() {
+ return this.editorDiv;
+ }
+ static deserialize(data, parent, uiManager) {
+ let initialData = null;
+ if (data instanceof FreeTextAnnotationElement) {
+ const {
+ data: {
+ defaultAppearanceData: {
+ fontSize,
+ fontColor
+ },
+ rect,
+ rotation,
+ id
+ },
+ textContent,
+ textPosition,
+ parent: {
+ page: {
+ pageNumber
+ }
+ }
+ } = data;
+ if (!textContent || textContent.length === 0) {
+ return null;
+ }
+ initialData = data = {
+ annotationType: AnnotationEditorType.FREETEXT,
+ color: Array.from(fontColor),
+ fontSize,
+ value: textContent.join("\n"),
+ position: textPosition,
+ pageIndex: pageNumber - 1,
+ rect,
+ rotation,
+ id,
+ deleted: false
+ };
+ }
+ const editor = super.deserialize(data, parent, uiManager);
+ editor.#fontSize = data.fontSize;
+ editor.#color = Util.makeHexColor(...data.color);
+ editor.#content = FreeTextEditor.#deserializeContent(data.value);
+ editor.annotationElementId = data.id || null;
+ editor.#initialData = initialData;
+ return editor;
+ }
+ serialize(isForCopying = false) {
+ if (this.isEmpty()) {
+ return null;
+ }
+ if (this.deleted) {
+ return {
+ pageIndex: this.pageIndex,
+ id: this.annotationElementId,
+ deleted: true
+ };
+ }
+ const padding = FreeTextEditor._internalPadding * this.parentScale;
+ const rect = this.getRect(padding, padding);
+ const color = AnnotationEditor._colorManager.convert(this.isAttachedToDOM ? getComputedStyle(this.editorDiv).color : this.#color);
+ const serialized = {
+ annotationType: AnnotationEditorType.FREETEXT,
+ color,
+ fontSize: this.#fontSize,
+ value: this.#serializeContent(),
+ pageIndex: this.pageIndex,
+ rect,
+ rotation: this.rotation,
+ structTreeParentId: this._structTreeParentId
+ };
+ if (isForCopying) {
+ return serialized;
+ }
+ if (this.annotationElementId && !this.#hasElementChanged(serialized)) {
+ return null;
+ }
+ serialized.id = this.annotationElementId;
+ return serialized;
+ }
+ #hasElementChanged(serialized) {
+ const {
+ value,
+ fontSize,
+ color,
+ rect,
+ pageIndex
+ } = this.#initialData;
+ return serialized.value !== value || serialized.fontSize !== fontSize || serialized.rect.some((x, i) => Math.abs(x - rect[i]) >= 1) || serialized.color.some((c, i) => c !== color[i]) || serialized.pageIndex !== pageIndex;
+ }
+ #cheatInitialRect(delayed = false) {
+ if (!this.annotationElementId) {
+ return;
+ }
+ this.#setEditorDimensions();
+ if (!delayed && (this.width === 0 || this.height === 0)) {
+ setTimeout(() => this.#cheatInitialRect(true), 0);
+ return;
+ }
+ const padding = FreeTextEditor._internalPadding * this.parentScale;
+ this.#initialData.rect = this.getRect(padding, padding);
+ }
+}
+
+;// CONCATENATED MODULE: ./src/display/editor/outliner.js
+
+class Outliner {
+ #box;
+ #verticalEdges = [];
+ #intervals = [];
+ constructor(boxes, borderWidth = 0, innerMargin = 0, isLTR = true) {
+ let minX = Infinity;
+ let maxX = -Infinity;
+ let minY = Infinity;
+ let maxY = -Infinity;
+ const NUMBER_OF_DIGITS = 4;
+ const EPSILON = 10 ** -NUMBER_OF_DIGITS;
+ for (const {
+ x,
+ y,
+ width,
+ height
+ } of boxes) {
+ const x1 = Math.floor((x - borderWidth) / EPSILON) * EPSILON;
+ const x2 = Math.ceil((x + width + borderWidth) / EPSILON) * EPSILON;
+ const y1 = Math.floor((y - borderWidth) / EPSILON) * EPSILON;
+ const y2 = Math.ceil((y + height + borderWidth) / EPSILON) * EPSILON;
+ const left = [x1, y1, y2, true];
+ const right = [x2, y1, y2, false];
+ this.#verticalEdges.push(left, right);
+ minX = Math.min(minX, x1);
+ maxX = Math.max(maxX, x2);
+ minY = Math.min(minY, y1);
+ maxY = Math.max(maxY, y2);
+ }
+ const bboxWidth = maxX - minX + 2 * innerMargin;
+ const bboxHeight = maxY - minY + 2 * innerMargin;
+ const shiftedMinX = minX - innerMargin;
+ const shiftedMinY = minY - innerMargin;
+ const lastEdge = this.#verticalEdges.at(isLTR ? -1 : -2);
+ const lastPoint = [lastEdge[0], lastEdge[2]];
+ for (const edge of this.#verticalEdges) {
+ const [x, y1, y2] = edge;
+ edge[0] = (x - shiftedMinX) / bboxWidth;
+ edge[1] = (y1 - shiftedMinY) / bboxHeight;
+ edge[2] = (y2 - shiftedMinY) / bboxHeight;
+ }
+ this.#box = {
+ x: shiftedMinX,
+ y: shiftedMinY,
+ width: bboxWidth,
+ height: bboxHeight,
+ lastPoint
+ };
+ }
+ getOutlines() {
+ this.#verticalEdges.sort((a, b) => a[0] - b[0] || a[1] - b[1] || a[2] - b[2]);
+ const outlineVerticalEdges = [];
+ for (const edge of this.#verticalEdges) {
+ if (edge[3]) {
+ outlineVerticalEdges.push(...this.#breakEdge(edge));
+ this.#insert(edge);
+ } else {
+ this.#remove(edge);
+ outlineVerticalEdges.push(...this.#breakEdge(edge));
+ }
+ }
+ return this.#getOutlines(outlineVerticalEdges);
+ }
+ #getOutlines(outlineVerticalEdges) {
+ const edges = [];
+ const allEdges = new Set();
+ for (const edge of outlineVerticalEdges) {
+ const [x, y1, y2] = edge;
+ edges.push([x, y1, edge], [x, y2, edge]);
+ }
+ edges.sort((a, b) => a[1] - b[1] || a[0] - b[0]);
+ for (let i = 0, ii = edges.length; i < ii; i += 2) {
+ const edge1 = edges[i][2];
+ const edge2 = edges[i + 1][2];
+ edge1.push(edge2);
+ edge2.push(edge1);
+ allEdges.add(edge1);
+ allEdges.add(edge2);
+ }
+ const outlines = [];
+ let outline;
+ while (allEdges.size > 0) {
+ const edge = allEdges.values().next().value;
+ let [x, y1, y2, edge1, edge2] = edge;
+ allEdges.delete(edge);
+ let lastPointX = x;
+ let lastPointY = y1;
+ outline = [x, y2];
+ outlines.push(outline);
+ while (true) {
+ let e;
+ if (allEdges.has(edge1)) {
+ e = edge1;
+ } else if (allEdges.has(edge2)) {
+ e = edge2;
+ } else {
+ break;
+ }
+ allEdges.delete(e);
+ [x, y1, y2, edge1, edge2] = e;
+ if (lastPointX !== x) {
+ outline.push(lastPointX, lastPointY, x, lastPointY === y1 ? y1 : y2);
+ lastPointX = x;
+ }
+ lastPointY = lastPointY === y1 ? y2 : y1;
+ }
+ outline.push(lastPointX, lastPointY);
+ }
+ return new HighlightOutline(outlines, this.#box);
+ }
+ #binarySearch(y) {
+ const array = this.#intervals;
+ let start = 0;
+ let end = array.length - 1;
+ while (start <= end) {
+ const middle = start + end >> 1;
+ const y1 = array[middle][0];
+ if (y1 === y) {
+ return middle;
+ }
+ if (y1 < y) {
+ start = middle + 1;
+ } else {
+ end = middle - 1;
+ }
+ }
+ return end + 1;
+ }
+ #insert([, y1, y2]) {
+ const index = this.#binarySearch(y1);
+ this.#intervals.splice(index, 0, [y1, y2]);
+ }
+ #remove([, y1, y2]) {
+ const index = this.#binarySearch(y1);
+ for (let i = index; i < this.#intervals.length; i++) {
+ const [start, end] = this.#intervals[i];
+ if (start !== y1) {
+ break;
+ }
+ if (start === y1 && end === y2) {
+ this.#intervals.splice(i, 1);
+ return;
+ }
+ }
+ for (let i = index - 1; i >= 0; i--) {
+ const [start, end] = this.#intervals[i];
+ if (start !== y1) {
+ break;
+ }
+ if (start === y1 && end === y2) {
+ this.#intervals.splice(i, 1);
+ return;
+ }
+ }
+ }
+ #breakEdge(edge) {
+ const [x, y1, y2] = edge;
+ const results = [[x, y1, y2]];
+ const index = this.#binarySearch(y2);
+ for (let i = 0; i < index; i++) {
+ const [start, end] = this.#intervals[i];
+ for (let j = 0, jj = results.length; j < jj; j++) {
+ const [, y3, y4] = results[j];
+ if (end <= y3 || y4 <= start) {
+ continue;
+ }
+ if (y3 >= start) {
+ if (y4 > end) {
+ results[j][1] = end;
+ } else {
+ if (jj === 1) {
+ return [];
+ }
+ results.splice(j, 1);
+ j--;
+ jj--;
+ }
+ continue;
+ }
+ results[j][2] = start;
+ if (y4 > end) {
+ results.push([x, end, y4]);
+ }
+ }
+ }
+ return results;
+ }
+}
+class Outline {
+ toSVGPath() {
+ throw new Error("Abstract method `toSVGPath` must be implemented.");
+ }
+ get box() {
+ throw new Error("Abstract getter `box` must be implemented.");
+ }
+ serialize(_bbox, _rotation) {
+ throw new Error("Abstract method `serialize` must be implemented.");
+ }
+ get free() {
+ return this instanceof FreeHighlightOutline;
+ }
+}
+class HighlightOutline extends Outline {
+ #box;
+ #outlines;
+ constructor(outlines, box) {
+ super();
+ this.#outlines = outlines;
+ this.#box = box;
+ }
+ toSVGPath() {
+ const buffer = [];
+ for (const polygon of this.#outlines) {
+ let [prevX, prevY] = polygon;
+ buffer.push(`M${prevX} ${prevY}`);
+ for (let i = 2; i < polygon.length; i += 2) {
+ const x = polygon[i];
+ const y = polygon[i + 1];
+ if (x === prevX) {
+ buffer.push(`V${y}`);
+ prevY = y;
+ } else if (y === prevY) {
+ buffer.push(`H${x}`);
+ prevX = x;
+ }
+ }
+ buffer.push("Z");
+ }
+ return buffer.join(" ");
+ }
+ serialize([blX, blY, trX, trY], _rotation) {
+ const outlines = [];
+ const width = trX - blX;
+ const height = trY - blY;
+ for (const outline of this.#outlines) {
+ const points = new Array(outline.length);
+ for (let i = 0; i < outline.length; i += 2) {
+ points[i] = blX + outline[i] * width;
+ points[i + 1] = trY - outline[i + 1] * height;
+ }
+ outlines.push(points);
+ }
+ return outlines;
+ }
+ get box() {
+ return this.#box;
+ }
+}
+class FreeOutliner {
+ #box;
+ #bottom = [];
+ #innerMargin;
+ #isLTR;
+ #top = [];
+ #last = new Float64Array(18);
+ #lastX;
+ #lastY;
+ #min;
+ #min_dist;
+ #scaleFactor;
+ #thickness;
+ #points = [];
+ static #MIN_DIST = 8;
+ static #MIN_DIFF = 2;
+ static #MIN = FreeOutliner.#MIN_DIST + FreeOutliner.#MIN_DIFF;
+ constructor({
+ x,
+ y
+ }, box, scaleFactor, thickness, isLTR, innerMargin = 0) {
+ this.#box = box;
+ this.#thickness = thickness * scaleFactor;
+ this.#isLTR = isLTR;
+ this.#last.set([NaN, NaN, NaN, NaN, x, y], 6);
+ this.#innerMargin = innerMargin;
+ this.#min_dist = FreeOutliner.#MIN_DIST * scaleFactor;
+ this.#min = FreeOutliner.#MIN * scaleFactor;
+ this.#scaleFactor = scaleFactor;
+ this.#points.push(x, y);
+ }
+ get free() {
+ return true;
+ }
+ isEmpty() {
+ return isNaN(this.#last[8]);
+ }
+ #getLastCoords() {
+ const lastTop = this.#last.subarray(4, 6);
+ const lastBottom = this.#last.subarray(16, 18);
+ const [x, y, width, height] = this.#box;
+ return [(this.#lastX + (lastTop[0] - lastBottom[0]) / 2 - x) / width, (this.#lastY + (lastTop[1] - lastBottom[1]) / 2 - y) / height, (this.#lastX + (lastBottom[0] - lastTop[0]) / 2 - x) / width, (this.#lastY + (lastBottom[1] - lastTop[1]) / 2 - y) / height];
+ }
+ add({
+ x,
+ y
+ }) {
+ this.#lastX = x;
+ this.#lastY = y;
+ const [layerX, layerY, layerWidth, layerHeight] = this.#box;
+ let [x1, y1, x2, y2] = this.#last.subarray(8, 12);
+ const diffX = x - x2;
+ const diffY = y - y2;
+ const d = Math.hypot(diffX, diffY);
+ if (d < this.#min) {
+ return false;
+ }
+ const diffD = d - this.#min_dist;
+ const K = diffD / d;
+ const shiftX = K * diffX;
+ const shiftY = K * diffY;
+ let x0 = x1;
+ let y0 = y1;
+ x1 = x2;
+ y1 = y2;
+ x2 += shiftX;
+ y2 += shiftY;
+ this.#points?.push(x, y);
+ const nX = -shiftY / diffD;
+ const nY = shiftX / diffD;
+ const thX = nX * this.#thickness;
+ const thY = nY * this.#thickness;
+ this.#last.set(this.#last.subarray(2, 8), 0);
+ this.#last.set([x2 + thX, y2 + thY], 4);
+ this.#last.set(this.#last.subarray(14, 18), 12);
+ this.#last.set([x2 - thX, y2 - thY], 16);
+ if (isNaN(this.#last[6])) {
+ if (this.#top.length === 0) {
+ this.#last.set([x1 + thX, y1 + thY], 2);
+ this.#top.push(NaN, NaN, NaN, NaN, (x1 + thX - layerX) / layerWidth, (y1 + thY - layerY) / layerHeight);
+ this.#last.set([x1 - thX, y1 - thY], 14);
+ this.#bottom.push(NaN, NaN, NaN, NaN, (x1 - thX - layerX) / layerWidth, (y1 - thY - layerY) / layerHeight);
+ }
+ this.#last.set([x0, y0, x1, y1, x2, y2], 6);
+ return !this.isEmpty();
+ }
+ this.#last.set([x0, y0, x1, y1, x2, y2], 6);
+ const angle = Math.abs(Math.atan2(y0 - y1, x0 - x1) - Math.atan2(shiftY, shiftX));
+ if (angle < Math.PI / 2) {
+ [x1, y1, x2, y2] = this.#last.subarray(2, 6);
+ this.#top.push(NaN, NaN, NaN, NaN, ((x1 + x2) / 2 - layerX) / layerWidth, ((y1 + y2) / 2 - layerY) / layerHeight);
+ [x1, y1, x0, y0] = this.#last.subarray(14, 18);
+ this.#bottom.push(NaN, NaN, NaN, NaN, ((x0 + x1) / 2 - layerX) / layerWidth, ((y0 + y1) / 2 - layerY) / layerHeight);
+ return true;
+ }
+ [x0, y0, x1, y1, x2, y2] = this.#last.subarray(0, 6);
+ this.#top.push(((x0 + 5 * x1) / 6 - layerX) / layerWidth, ((y0 + 5 * y1) / 6 - layerY) / layerHeight, ((5 * x1 + x2) / 6 - layerX) / layerWidth, ((5 * y1 + y2) / 6 - layerY) / layerHeight, ((x1 + x2) / 2 - layerX) / layerWidth, ((y1 + y2) / 2 - layerY) / layerHeight);
+ [x2, y2, x1, y1, x0, y0] = this.#last.subarray(12, 18);
+ this.#bottom.push(((x0 + 5 * x1) / 6 - layerX) / layerWidth, ((y0 + 5 * y1) / 6 - layerY) / layerHeight, ((5 * x1 + x2) / 6 - layerX) / layerWidth, ((5 * y1 + y2) / 6 - layerY) / layerHeight, ((x1 + x2) / 2 - layerX) / layerWidth, ((y1 + y2) / 2 - layerY) / layerHeight);
+ return true;
+ }
+ toSVGPath() {
+ if (this.isEmpty()) {
+ return "";
+ }
+ const top = this.#top;
+ const bottom = this.#bottom;
+ const lastTop = this.#last.subarray(4, 6);
+ const lastBottom = this.#last.subarray(16, 18);
+ const [x, y, width, height] = this.#box;
+ const [lastTopX, lastTopY, lastBottomX, lastBottomY] = this.#getLastCoords();
+ if (isNaN(this.#last[6]) && !this.isEmpty()) {
+ return `M${(this.#last[2] - x) / width} ${(this.#last[3] - y) / height} L${(this.#last[4] - x) / width} ${(this.#last[5] - y) / height} L${lastTopX} ${lastTopY} L${lastBottomX} ${lastBottomY} L${(this.#last[16] - x) / width} ${(this.#last[17] - y) / height} L${(this.#last[14] - x) / width} ${(this.#last[15] - y) / height} Z`;
+ }
+ const buffer = [];
+ buffer.push(`M${top[4]} ${top[5]}`);
+ for (let i = 6; i < top.length; i += 6) {
+ if (isNaN(top[i])) {
+ buffer.push(`L${top[i + 4]} ${top[i + 5]}`);
+ } else {
+ buffer.push(`C${top[i]} ${top[i + 1]} ${top[i + 2]} ${top[i + 3]} ${top[i + 4]} ${top[i + 5]}`);
+ }
+ }
+ buffer.push(`L${(lastTop[0] - x) / width} ${(lastTop[1] - y) / height} L${lastTopX} ${lastTopY} L${lastBottomX} ${lastBottomY} L${(lastBottom[0] - x) / width} ${(lastBottom[1] - y) / height}`);
+ for (let i = bottom.length - 6; i >= 6; i -= 6) {
+ if (isNaN(bottom[i])) {
+ buffer.push(`L${bottom[i + 4]} ${bottom[i + 5]}`);
+ } else {
+ buffer.push(`C${bottom[i]} ${bottom[i + 1]} ${bottom[i + 2]} ${bottom[i + 3]} ${bottom[i + 4]} ${bottom[i + 5]}`);
+ }
+ }
+ buffer.push(`L${bottom[4]} ${bottom[5]} Z`);
+ return buffer.join(" ");
+ }
+ getOutlines() {
+ const top = this.#top;
+ const bottom = this.#bottom;
+ const last = this.#last;
+ const lastTop = last.subarray(4, 6);
+ const lastBottom = last.subarray(16, 18);
+ const [layerX, layerY, layerWidth, layerHeight] = this.#box;
+ const points = new Float64Array((this.#points?.length ?? 0) + 2);
+ for (let i = 0, ii = points.length - 2; i < ii; i += 2) {
+ points[i] = (this.#points[i] - layerX) / layerWidth;
+ points[i + 1] = (this.#points[i + 1] - layerY) / layerHeight;
+ }
+ points[points.length - 2] = (this.#lastX - layerX) / layerWidth;
+ points[points.length - 1] = (this.#lastY - layerY) / layerHeight;
+ const [lastTopX, lastTopY, lastBottomX, lastBottomY] = this.#getLastCoords();
+ if (isNaN(last[6]) && !this.isEmpty()) {
+ const outline = new Float64Array(36);
+ outline.set([NaN, NaN, NaN, NaN, (last[2] - layerX) / layerWidth, (last[3] - layerY) / layerHeight, NaN, NaN, NaN, NaN, (last[4] - layerX) / layerWidth, (last[5] - layerY) / layerHeight, NaN, NaN, NaN, NaN, lastTopX, lastTopY, NaN, NaN, NaN, NaN, lastBottomX, lastBottomY, NaN, NaN, NaN, NaN, (last[16] - layerX) / layerWidth, (last[17] - layerY) / layerHeight, NaN, NaN, NaN, NaN, (last[14] - layerX) / layerWidth, (last[15] - layerY) / layerHeight], 0);
+ return new FreeHighlightOutline(outline, points, this.#box, this.#scaleFactor, this.#innerMargin, this.#isLTR);
+ }
+ const outline = new Float64Array(this.#top.length + 24 + this.#bottom.length);
+ let N = top.length;
+ for (let i = 0; i < N; i += 2) {
+ if (isNaN(top[i])) {
+ outline[i] = outline[i + 1] = NaN;
+ continue;
+ }
+ outline[i] = top[i];
+ outline[i + 1] = top[i + 1];
+ }
+ outline.set([NaN, NaN, NaN, NaN, (lastTop[0] - layerX) / layerWidth, (lastTop[1] - layerY) / layerHeight, NaN, NaN, NaN, NaN, lastTopX, lastTopY, NaN, NaN, NaN, NaN, lastBottomX, lastBottomY, NaN, NaN, NaN, NaN, (lastBottom[0] - layerX) / layerWidth, (lastBottom[1] - layerY) / layerHeight], N);
+ N += 24;
+ for (let i = bottom.length - 6; i >= 6; i -= 6) {
+ for (let j = 0; j < 6; j += 2) {
+ if (isNaN(bottom[i + j])) {
+ outline[N] = outline[N + 1] = NaN;
+ N += 2;
+ continue;
+ }
+ outline[N] = bottom[i + j];
+ outline[N + 1] = bottom[i + j + 1];
+ N += 2;
+ }
+ }
+ outline.set([NaN, NaN, NaN, NaN, bottom[4], bottom[5]], N);
+ return new FreeHighlightOutline(outline, points, this.#box, this.#scaleFactor, this.#innerMargin, this.#isLTR);
+ }
+}
+class FreeHighlightOutline extends Outline {
+ #box;
+ #bbox = null;
+ #innerMargin;
+ #isLTR;
+ #points;
+ #scaleFactor;
+ #outline;
+ constructor(outline, points, box, scaleFactor, innerMargin, isLTR) {
+ super();
+ this.#outline = outline;
+ this.#points = points;
+ this.#box = box;
+ this.#scaleFactor = scaleFactor;
+ this.#innerMargin = innerMargin;
+ this.#isLTR = isLTR;
+ this.#computeMinMax(isLTR);
+ const {
+ x,
+ y,
+ width,
+ height
+ } = this.#bbox;
+ for (let i = 0, ii = outline.length; i < ii; i += 2) {
+ outline[i] = (outline[i] - x) / width;
+ outline[i + 1] = (outline[i + 1] - y) / height;
+ }
+ for (let i = 0, ii = points.length; i < ii; i += 2) {
+ points[i] = (points[i] - x) / width;
+ points[i + 1] = (points[i + 1] - y) / height;
+ }
+ }
+ toSVGPath() {
+ const buffer = [`M${this.#outline[4]} ${this.#outline[5]}`];
+ for (let i = 6, ii = this.#outline.length; i < ii; i += 6) {
+ if (isNaN(this.#outline[i])) {
+ buffer.push(`L${this.#outline[i + 4]} ${this.#outline[i + 5]}`);
+ continue;
+ }
+ buffer.push(`C${this.#outline[i]} ${this.#outline[i + 1]} ${this.#outline[i + 2]} ${this.#outline[i + 3]} ${this.#outline[i + 4]} ${this.#outline[i + 5]}`);
+ }
+ buffer.push("Z");
+ return buffer.join(" ");
+ }
+ serialize([blX, blY, trX, trY], rotation) {
+ const width = trX - blX;
+ const height = trY - blY;
+ let outline;
+ let points;
+ switch (rotation) {
+ case 0:
+ outline = this.#rescale(this.#outline, blX, trY, width, -height);
+ points = this.#rescale(this.#points, blX, trY, width, -height);
+ break;
+ case 90:
+ outline = this.#rescaleAndSwap(this.#outline, blX, blY, width, height);
+ points = this.#rescaleAndSwap(this.#points, blX, blY, width, height);
+ break;
+ case 180:
+ outline = this.#rescale(this.#outline, trX, blY, -width, height);
+ points = this.#rescale(this.#points, trX, blY, -width, height);
+ break;
+ case 270:
+ outline = this.#rescaleAndSwap(this.#outline, trX, trY, -width, -height);
+ points = this.#rescaleAndSwap(this.#points, trX, trY, -width, -height);
+ break;
+ }
+ return {
+ outline: Array.from(outline),
+ points: [Array.from(points)]
+ };
+ }
+ #rescale(src, tx, ty, sx, sy) {
+ const dest = new Float64Array(src.length);
+ for (let i = 0, ii = src.length; i < ii; i += 2) {
+ dest[i] = tx + src[i] * sx;
+ dest[i + 1] = ty + src[i + 1] * sy;
+ }
+ return dest;
+ }
+ #rescaleAndSwap(src, tx, ty, sx, sy) {
+ const dest = new Float64Array(src.length);
+ for (let i = 0, ii = src.length; i < ii; i += 2) {
+ dest[i] = tx + src[i + 1] * sx;
+ dest[i + 1] = ty + src[i] * sy;
+ }
+ return dest;
+ }
+ #computeMinMax(isLTR) {
+ const outline = this.#outline;
+ let lastX = outline[4];
+ let lastY = outline[5];
+ let minX = lastX;
+ let minY = lastY;
+ let maxX = lastX;
+ let maxY = lastY;
+ let lastPointX = lastX;
+ let lastPointY = lastY;
+ const ltrCallback = isLTR ? Math.max : Math.min;
+ for (let i = 6, ii = outline.length; i < ii; i += 6) {
+ if (isNaN(outline[i])) {
+ minX = Math.min(minX, outline[i + 4]);
+ minY = Math.min(minY, outline[i + 5]);
+ maxX = Math.max(maxX, outline[i + 4]);
+ maxY = Math.max(maxY, outline[i + 5]);
+ if (lastPointY < outline[i + 5]) {
+ lastPointX = outline[i + 4];
+ lastPointY = outline[i + 5];
+ } else if (lastPointY === outline[i + 5]) {
+ lastPointX = ltrCallback(lastPointX, outline[i + 4]);
+ }
+ } else {
+ const bbox = Util.bezierBoundingBox(lastX, lastY, ...outline.slice(i, i + 6));
+ minX = Math.min(minX, bbox[0]);
+ minY = Math.min(minY, bbox[1]);
+ maxX = Math.max(maxX, bbox[2]);
+ maxY = Math.max(maxY, bbox[3]);
+ if (lastPointY < bbox[3]) {
+ lastPointX = bbox[2];
+ lastPointY = bbox[3];
+ } else if (lastPointY === bbox[3]) {
+ lastPointX = ltrCallback(lastPointX, bbox[2]);
+ }
+ }
+ lastX = outline[i + 4];
+ lastY = outline[i + 5];
+ }
+ const x = minX - this.#innerMargin,
+ y = minY - this.#innerMargin,
+ width = maxX - minX + 2 * this.#innerMargin,
+ height = maxY - minY + 2 * this.#innerMargin;
+ this.#bbox = {
+ x,
+ y,
+ width,
+ height,
+ lastPoint: [lastPointX, lastPointY]
+ };
+ }
+ get box() {
+ return this.#bbox;
+ }
+ getNewOutline(thickness, innerMargin) {
+ const {
+ x,
+ y,
+ width,
+ height
+ } = this.#bbox;
+ const [layerX, layerY, layerWidth, layerHeight] = this.#box;
+ const sx = width * layerWidth;
+ const sy = height * layerHeight;
+ const tx = x * layerWidth + layerX;
+ const ty = y * layerHeight + layerY;
+ const outliner = new FreeOutliner({
+ x: this.#points[0] * sx + tx,
+ y: this.#points[1] * sy + ty
+ }, this.#box, this.#scaleFactor, thickness, this.#isLTR, innerMargin ?? this.#innerMargin);
+ for (let i = 2; i < this.#points.length; i += 2) {
+ outliner.add({
+ x: this.#points[i] * sx + tx,
+ y: this.#points[i + 1] * sy + ty
+ });
+ }
+ return outliner.getOutlines();
+ }
+}
+
+;// CONCATENATED MODULE: ./src/display/editor/color_picker.js
+
+
+
+class ColorPicker {
+ #boundKeyDown = this.#keyDown.bind(this);
+ #boundPointerDown = this.#pointerDown.bind(this);
+ #button = null;
+ #buttonSwatch = null;
+ #defaultColor;
+ #dropdown = null;
+ #dropdownWasFromKeyboard = false;
+ #isMainColorPicker = false;
+ #eventBus;
+ #uiManager = null;
+ #type;
+ static get _keyboardManager() {
+ return shadow(this, "_keyboardManager", new KeyboardManager([[["Escape", "mac+Escape"], ColorPicker.prototype._hideDropdownFromKeyboard], [[" ", "mac+ "], ColorPicker.prototype._colorSelectFromKeyboard], [["ArrowDown", "ArrowRight", "mac+ArrowDown", "mac+ArrowRight"], ColorPicker.prototype._moveToNext], [["ArrowUp", "ArrowLeft", "mac+ArrowUp", "mac+ArrowLeft"], ColorPicker.prototype._moveToPrevious], [["Home", "mac+Home"], ColorPicker.prototype._moveToBeginning], [["End", "mac+End"], ColorPicker.prototype._moveToEnd]]));
+ }
+ constructor({
+ editor = null,
+ uiManager = null
+ }) {
+ if (editor) {
+ this.#isMainColorPicker = false;
+ this.#type = AnnotationEditorParamsType.HIGHLIGHT_COLOR;
+ } else {
+ this.#isMainColorPicker = true;
+ this.#type = AnnotationEditorParamsType.HIGHLIGHT_DEFAULT_COLOR;
+ }
+ this.#uiManager = editor?._uiManager || uiManager;
+ this.#eventBus = this.#uiManager._eventBus;
+ this.#defaultColor = editor?.color || this.#uiManager?.highlightColors.values().next().value || "#FFFF98";
+ }
+ renderButton() {
+ const button = this.#button = document.createElement("button");
+ button.className = "colorPicker";
+ button.tabIndex = "0";
+ button.setAttribute("data-l10n-id", "pdfjs-editor-colorpicker-button");
+ button.setAttribute("aria-haspopup", true);
+ button.addEventListener("click", this.#openDropdown.bind(this));
+ button.addEventListener("keydown", this.#boundKeyDown);
+ const swatch = this.#buttonSwatch = document.createElement("span");
+ swatch.className = "swatch";
+ swatch.style.backgroundColor = this.#defaultColor;
+ button.append(swatch);
+ return button;
+ }
+ renderMainDropdown() {
+ const dropdown = this.#dropdown = this.#getDropdownRoot();
+ dropdown.setAttribute("aria-orientation", "horizontal");
+ dropdown.setAttribute("aria-labelledby", "highlightColorPickerLabel");
+ return dropdown;
+ }
+ #getDropdownRoot() {
+ const div = document.createElement("div");
+ div.addEventListener("contextmenu", noContextMenu);
+ div.className = "dropdown";
+ div.role = "listbox";
+ div.setAttribute("aria-multiselectable", false);
+ div.setAttribute("aria-orientation", "vertical");
+ div.setAttribute("data-l10n-id", "pdfjs-editor-colorpicker-dropdown");
+ for (const [name, color] of this.#uiManager.highlightColors) {
+ const button = document.createElement("button");
+ button.tabIndex = "0";
+ button.role = "option";
+ button.setAttribute("data-color", color);
+ button.title = name;
+ button.setAttribute("data-l10n-id", `pdfjs-editor-colorpicker-${name}`);
+ const swatch = document.createElement("span");
+ button.append(swatch);
+ swatch.className = "swatch";
+ swatch.style.backgroundColor = color;
+ button.setAttribute("aria-selected", color === this.#defaultColor);
+ button.addEventListener("click", this.#colorSelect.bind(this, color));
+ div.append(button);
+ }
+ div.addEventListener("keydown", this.#boundKeyDown);
+ return div;
+ }
+ #colorSelect(color, event) {
+ event.stopPropagation();
+ this.#eventBus.dispatch("switchannotationeditorparams", {
+ source: this,
+ type: this.#type,
+ value: color
+ });
+ }
+ _colorSelectFromKeyboard(event) {
+ if (event.target === this.#button) {
+ this.#openDropdown(event);
+ return;
+ }
+ const color = event.target.getAttribute("data-color");
+ if (!color) {
+ return;
+ }
+ this.#colorSelect(color, event);
+ }
+ _moveToNext(event) {
+ if (!this.#isDropdownVisible) {
+ this.#openDropdown(event);
+ return;
+ }
+ if (event.target === this.#button) {
+ this.#dropdown.firstChild?.focus();
+ return;
+ }
+ event.target.nextSibling?.focus();
+ }
+ _moveToPrevious(event) {
+ if (event.target === this.#dropdown?.firstChild || event.target === this.#button) {
+ if (this.#isDropdownVisible) {
+ this._hideDropdownFromKeyboard();
+ }
+ return;
+ }
+ if (!this.#isDropdownVisible) {
+ this.#openDropdown(event);
+ }
+ event.target.previousSibling?.focus();
+ }
+ _moveToBeginning(event) {
+ if (!this.#isDropdownVisible) {
+ this.#openDropdown(event);
+ return;
+ }
+ this.#dropdown.firstChild?.focus();
+ }
+ _moveToEnd(event) {
+ if (!this.#isDropdownVisible) {
+ this.#openDropdown(event);
+ return;
+ }
+ this.#dropdown.lastChild?.focus();
+ }
+ #keyDown(event) {
+ ColorPicker._keyboardManager.exec(this, event);
+ }
+ #openDropdown(event) {
+ if (this.#isDropdownVisible) {
+ this.hideDropdown();
+ return;
+ }
+ this.#dropdownWasFromKeyboard = event.detail === 0;
+ window.addEventListener("pointerdown", this.#boundPointerDown);
+ if (this.#dropdown) {
+ this.#dropdown.classList.remove("hidden");
+ return;
+ }
+ const root = this.#dropdown = this.#getDropdownRoot();
+ this.#button.append(root);
+ }
+ #pointerDown(event) {
+ if (this.#dropdown?.contains(event.target)) {
+ return;
+ }
+ this.hideDropdown();
+ }
+ hideDropdown() {
+ this.#dropdown?.classList.add("hidden");
+ window.removeEventListener("pointerdown", this.#boundPointerDown);
+ }
+ get #isDropdownVisible() {
+ return this.#dropdown && !this.#dropdown.classList.contains("hidden");
+ }
+ _hideDropdownFromKeyboard() {
+ if (this.#isMainColorPicker || !this.#isDropdownVisible) {
+ return;
+ }
+ this.hideDropdown();
+ this.#button.focus({
+ preventScroll: true,
+ focusVisible: this.#dropdownWasFromKeyboard
+ });
+ }
+ updateColor(color) {
+ if (this.#buttonSwatch) {
+ this.#buttonSwatch.style.backgroundColor = color;
+ }
+ if (!this.#dropdown) {
+ return;
+ }
+ const i = this.#uiManager.highlightColors.values();
+ for (const child of this.#dropdown.children) {
+ child.setAttribute("aria-selected", i.next().value === color);
+ }
+ }
+ destroy() {
+ this.#button?.remove();
+ this.#button = null;
+ this.#buttonSwatch = null;
+ this.#dropdown?.remove();
+ this.#dropdown = null;
+ }
+}
+
+;// CONCATENATED MODULE: ./src/display/editor/highlight.js
+
+
+
+
+
+
+class HighlightEditor extends AnnotationEditor {
+ #anchorNode = null;
+ #anchorOffset = 0;
+ #boxes;
+ #clipPathId = null;
+ #colorPicker = null;
+ #focusOutlines = null;
+ #focusNode = null;
+ #focusOffset = 0;
+ #highlightDiv = null;
+ #highlightOutlines = null;
+ #id = null;
+ #isFreeHighlight = false;
+ #boundKeydown = this.#keydown.bind(this);
+ #lastPoint = null;
+ #opacity;
+ #outlineId = null;
+ #thickness;
+ #methodOfCreation = "";
+ static _defaultColor = null;
+ static _defaultOpacity = 1;
+ static _defaultThickness = 12;
+ static _l10nPromise;
+ static _type = "highlight";
+ static _editorType = AnnotationEditorType.HIGHLIGHT;
+ static _freeHighlightId = -1;
+ static _freeHighlight = null;
+ static _freeHighlightClipId = "";
+ static get _keyboardManager() {
+ const proto = HighlightEditor.prototype;
+ return shadow(this, "_keyboardManager", new KeyboardManager([[["ArrowLeft", "mac+ArrowLeft"], proto._moveCaret, {
+ args: [0]
+ }], [["ArrowRight", "mac+ArrowRight"], proto._moveCaret, {
+ args: [1]
+ }], [["ArrowUp", "mac+ArrowUp"], proto._moveCaret, {
+ args: [2]
+ }], [["ArrowDown", "mac+ArrowDown"], proto._moveCaret, {
+ args: [3]
+ }]]));
+ }
+ constructor(params) {
+ super({
+ ...params,
+ name: "highlightEditor"
+ });
+ this.color = params.color || HighlightEditor._defaultColor;
+ this.#thickness = params.thickness || HighlightEditor._defaultThickness;
+ this.#opacity = params.opacity || HighlightEditor._defaultOpacity;
+ this.#boxes = params.boxes || null;
+ this.#methodOfCreation = params.methodOfCreation || "";
+ this._isDraggable = false;
+ if (params.highlightId > -1) {
+ this.#isFreeHighlight = true;
+ this.#createFreeOutlines(params);
+ this.#addToDrawLayer();
+ } else {
+ this.#anchorNode = params.anchorNode;
+ this.#anchorOffset = params.anchorOffset;
+ this.#focusNode = params.focusNode;
+ this.#focusOffset = params.focusOffset;
+ this.#createOutlines();
+ this.#addToDrawLayer();
+ this.rotate(this.rotation);
+ }
+ }
+ get telemetryInitialData() {
+ return {
+ action: "added",
+ type: this.#isFreeHighlight ? "free_highlight" : "highlight",
+ color: this._uiManager.highlightColorNames.get(this.color),
+ thickness: this.#thickness,
+ methodOfCreation: this.#methodOfCreation
+ };
+ }
+ get telemetryFinalData() {
+ return {
+ type: "highlight",
+ color: this._uiManager.highlightColorNames.get(this.color)
+ };
+ }
+ static computeTelemetryFinalData(data) {
+ return {
+ numberOfColors: data.get("color").size
+ };
+ }
+ #createOutlines() {
+ const outliner = new Outliner(this.#boxes, 0.001);
+ this.#highlightOutlines = outliner.getOutlines();
+ ({
+ x: this.x,
+ y: this.y,
+ width: this.width,
+ height: this.height
+ } = this.#highlightOutlines.box);
+ const outlinerForOutline = new Outliner(this.#boxes, 0.0025, 0.001, this._uiManager.direction === "ltr");
+ this.#focusOutlines = outlinerForOutline.getOutlines();
+ const {
+ lastPoint
+ } = this.#focusOutlines.box;
+ this.#lastPoint = [(lastPoint[0] - this.x) / this.width, (lastPoint[1] - this.y) / this.height];
+ }
+ #createFreeOutlines({
+ highlightOutlines,
+ highlightId,
+ clipPathId
+ }) {
+ this.#highlightOutlines = highlightOutlines;
+ const extraThickness = 1.5;
+ this.#focusOutlines = highlightOutlines.getNewOutline(this.#thickness / 2 + extraThickness, 0.0025);
+ if (highlightId >= 0) {
+ this.#id = highlightId;
+ this.#clipPathId = clipPathId;
+ this.parent.drawLayer.finalizeLine(highlightId, highlightOutlines);
+ this.#outlineId = this.parent.drawLayer.highlightOutline(this.#focusOutlines);
+ } else if (this.parent) {
+ const angle = this.parent.viewport.rotation;
+ this.parent.drawLayer.updateLine(this.#id, highlightOutlines);
+ this.parent.drawLayer.updateBox(this.#id, HighlightEditor.#rotateBbox(this.#highlightOutlines.box, (angle - this.rotation + 360) % 360));
+ this.parent.drawLayer.updateLine(this.#outlineId, this.#focusOutlines);
+ this.parent.drawLayer.updateBox(this.#outlineId, HighlightEditor.#rotateBbox(this.#focusOutlines.box, angle));
+ }
+ const {
+ x,
+ y,
+ width,
+ height
+ } = highlightOutlines.box;
+ switch (this.rotation) {
+ case 0:
+ this.x = x;
+ this.y = y;
+ this.width = width;
+ this.height = height;
+ break;
+ case 90:
+ {
+ const [pageWidth, pageHeight] = this.parentDimensions;
+ this.x = y;
+ this.y = 1 - x;
+ this.width = width * pageHeight / pageWidth;
+ this.height = height * pageWidth / pageHeight;
+ break;
+ }
+ case 180:
+ this.x = 1 - x;
+ this.y = 1 - y;
+ this.width = width;
+ this.height = height;
+ break;
+ case 270:
+ {
+ const [pageWidth, pageHeight] = this.parentDimensions;
+ this.x = 1 - y;
+ this.y = x;
+ this.width = width * pageHeight / pageWidth;
+ this.height = height * pageWidth / pageHeight;
+ break;
+ }
+ }
+ const {
+ lastPoint
+ } = this.#focusOutlines.box;
+ this.#lastPoint = [(lastPoint[0] - x) / width, (lastPoint[1] - y) / height];
+ }
+ static initialize(l10n, uiManager) {
+ AnnotationEditor.initialize(l10n, uiManager);
+ HighlightEditor._defaultColor ||= uiManager.highlightColors?.values().next().value || "#fff066";
+ }
+ static updateDefaultParams(type, value) {
+ switch (type) {
+ case AnnotationEditorParamsType.HIGHLIGHT_DEFAULT_COLOR:
+ HighlightEditor._defaultColor = value;
+ break;
+ case AnnotationEditorParamsType.HIGHLIGHT_THICKNESS:
+ HighlightEditor._defaultThickness = value;
+ break;
+ }
+ }
+ translateInPage(x, y) {}
+ get toolbarPosition() {
+ return this.#lastPoint;
+ }
+ updateParams(type, value) {
+ switch (type) {
+ case AnnotationEditorParamsType.HIGHLIGHT_COLOR:
+ this.#updateColor(value);
+ break;
+ case AnnotationEditorParamsType.HIGHLIGHT_THICKNESS:
+ this.#updateThickness(value);
+ break;
+ }
+ }
+ static get defaultPropertiesToUpdate() {
+ return [[AnnotationEditorParamsType.HIGHLIGHT_DEFAULT_COLOR, HighlightEditor._defaultColor], [AnnotationEditorParamsType.HIGHLIGHT_THICKNESS, HighlightEditor._defaultThickness]];
+ }
+ get propertiesToUpdate() {
+ return [[AnnotationEditorParamsType.HIGHLIGHT_COLOR, this.color || HighlightEditor._defaultColor], [AnnotationEditorParamsType.HIGHLIGHT_THICKNESS, this.#thickness || HighlightEditor._defaultThickness], [AnnotationEditorParamsType.HIGHLIGHT_FREE, this.#isFreeHighlight]];
+ }
+ #updateColor(color) {
+ const setColor = col => {
+ this.color = col;
+ this.parent?.drawLayer.changeColor(this.#id, col);
+ this.#colorPicker?.updateColor(col);
+ };
+ const savedColor = this.color;
+ this.addCommands({
+ cmd: setColor.bind(this, color),
+ undo: setColor.bind(this, savedColor),
+ post: this._uiManager.updateUI.bind(this._uiManager, this),
+ mustExec: true,
+ type: AnnotationEditorParamsType.HIGHLIGHT_COLOR,
+ overwriteIfSameType: true,
+ keepUndo: true
+ });
+ this._reportTelemetry({
+ action: "color_changed",
+ color: this._uiManager.highlightColorNames.get(color)
+ }, true);
+ }
+ #updateThickness(thickness) {
+ const savedThickness = this.#thickness;
+ const setThickness = th => {
+ this.#thickness = th;
+ this.#changeThickness(th);
+ };
+ this.addCommands({
+ cmd: setThickness.bind(this, thickness),
+ undo: setThickness.bind(this, savedThickness),
+ post: this._uiManager.updateUI.bind(this._uiManager, this),
+ mustExec: true,
+ type: AnnotationEditorParamsType.INK_THICKNESS,
+ overwriteIfSameType: true,
+ keepUndo: true
+ });
+ this._reportTelemetry({
+ action: "thickness_changed",
+ thickness
+ }, true);
+ }
+ async addEditToolbar() {
+ const toolbar = await super.addEditToolbar();
+ if (!toolbar) {
+ return null;
+ }
+ if (this._uiManager.highlightColors) {
+ this.#colorPicker = new ColorPicker({
+ editor: this
+ });
+ toolbar.addColorPicker(this.#colorPicker);
+ }
+ return toolbar;
+ }
+ disableEditing() {
+ super.disableEditing();
+ this.div.classList.toggle("disabled", true);
+ }
+ enableEditing() {
+ super.enableEditing();
+ this.div.classList.toggle("disabled", false);
+ }
+ fixAndSetPosition() {
+ return super.fixAndSetPosition(this.#getRotation());
+ }
+ getBaseTranslation() {
+ return [0, 0];
+ }
+ getRect(tx, ty) {
+ return super.getRect(tx, ty, this.#getRotation());
+ }
+ onceAdded() {
+ this.parent.addUndoableEditor(this);
+ this.div.focus();
+ }
+ remove() {
+ super.remove();
+ this.#cleanDrawLayer();
+ this._reportTelemetry({
+ action: "deleted"
+ });
+ }
+ rebuild() {
+ if (!this.parent) {
+ return;
+ }
+ super.rebuild();
+ if (this.div === null) {
+ return;
+ }
+ this.#addToDrawLayer();
+ if (!this.isAttachedToDOM) {
+ this.parent.add(this);
+ }
+ }
+ setParent(parent) {
+ let mustBeSelected = false;
+ if (this.parent && !parent) {
+ this.#cleanDrawLayer();
+ } else if (parent) {
+ this.#addToDrawLayer(parent);
+ mustBeSelected = !this.parent && this.div?.classList.contains("selectedEditor");
+ }
+ super.setParent(parent);
+ if (mustBeSelected) {
+ this.select();
+ }
+ }
+ #changeThickness(thickness) {
+ if (!this.#isFreeHighlight) {
+ return;
+ }
+ this.#createFreeOutlines({
+ highlightOutlines: this.#highlightOutlines.getNewOutline(thickness / 2)
+ });
+ this.fixAndSetPosition();
+ const [parentWidth, parentHeight] = this.parentDimensions;
+ this.setDims(this.width * parentWidth, this.height * parentHeight);
+ }
+ #cleanDrawLayer() {
+ if (this.#id === null || !this.parent) {
+ return;
+ }
+ this.parent.drawLayer.remove(this.#id);
+ this.#id = null;
+ this.parent.drawLayer.remove(this.#outlineId);
+ this.#outlineId = null;
+ }
+ #addToDrawLayer(parent = this.parent) {
+ if (this.#id !== null) {
+ return;
+ }
+ ({
+ id: this.#id,
+ clipPathId: this.#clipPathId
+ } = parent.drawLayer.highlight(this.#highlightOutlines, this.color, this.#opacity));
+ this.#outlineId = parent.drawLayer.highlightOutline(this.#focusOutlines);
+ if (this.#highlightDiv) {
+ this.#highlightDiv.style.clipPath = this.#clipPathId;
+ }
+ }
+ static #rotateBbox({
+ x,
+ y,
+ width,
+ height
+ }, angle) {
+ switch (angle) {
+ case 90:
+ return {
+ x: 1 - y - height,
+ y: x,
+ width: height,
+ height: width
+ };
+ case 180:
+ return {
+ x: 1 - x - width,
+ y: 1 - y - height,
+ width,
+ height
+ };
+ case 270:
+ return {
+ x: y,
+ y: 1 - x - width,
+ width: height,
+ height: width
+ };
+ }
+ return {
+ x,
+ y,
+ width,
+ height
+ };
+ }
+ rotate(angle) {
+ const {
+ drawLayer
+ } = this.parent;
+ let box;
+ if (this.#isFreeHighlight) {
+ angle = (angle - this.rotation + 360) % 360;
+ box = HighlightEditor.#rotateBbox(this.#highlightOutlines.box, angle);
+ } else {
+ box = HighlightEditor.#rotateBbox(this, angle);
+ }
+ drawLayer.rotate(this.#id, angle);
+ drawLayer.rotate(this.#outlineId, angle);
+ drawLayer.updateBox(this.#id, box);
+ drawLayer.updateBox(this.#outlineId, HighlightEditor.#rotateBbox(this.#focusOutlines.box, angle));
+ }
+ render() {
+ if (this.div) {
+ return this.div;
+ }
+ const div = super.render();
+ if (this.#isFreeHighlight) {
+ div.classList.add("free");
+ } else {
+ this.div.addEventListener("keydown", this.#boundKeydown);
+ }
+ const highlightDiv = this.#highlightDiv = document.createElement("div");
+ div.append(highlightDiv);
+ highlightDiv.className = "internal";
+ highlightDiv.style.clipPath = this.#clipPathId;
+ const [parentWidth, parentHeight] = this.parentDimensions;
+ this.setDims(this.width * parentWidth, this.height * parentHeight);
+ bindEvents(this, this.#highlightDiv, ["pointerover", "pointerleave"]);
+ this.enableEditing();
+ return div;
+ }
+ pointerover() {
+ this.parent.drawLayer.addClass(this.#outlineId, "hovered");
+ }
+ pointerleave() {
+ this.parent.drawLayer.removeClass(this.#outlineId, "hovered");
+ }
+ #keydown(event) {
+ HighlightEditor._keyboardManager.exec(this, event);
+ }
+ _moveCaret(direction) {
+ this.parent.unselect(this);
+ switch (direction) {
+ case 0:
+ case 2:
+ this.#setCaret(true);
+ break;
+ case 1:
+ case 3:
+ this.#setCaret(false);
+ break;
+ }
+ }
+ #setCaret(start) {
+ if (!this.#anchorNode) {
+ return;
+ }
+ const selection = window.getSelection();
+ if (start) {
+ selection.setPosition(this.#anchorNode, this.#anchorOffset);
+ } else {
+ selection.setPosition(this.#focusNode, this.#focusOffset);
+ }
+ }
+ select() {
+ super.select();
+ this.parent?.drawLayer.removeClass(this.#outlineId, "hovered");
+ this.parent?.drawLayer.addClass(this.#outlineId, "selected");
+ }
+ unselect() {
+ super.unselect();
+ this.parent?.drawLayer.removeClass(this.#outlineId, "selected");
+ if (!this.#isFreeHighlight) {
+ this.#setCaret(false);
+ }
+ }
+ #getRotation() {
+ return this.#isFreeHighlight ? this.rotation : 0;
+ }
+ #serializeBoxes() {
+ if (this.#isFreeHighlight) {
+ return null;
+ }
+ const [pageWidth, pageHeight] = this.pageDimensions;
+ const boxes = this.#boxes;
+ const quadPoints = new Array(boxes.length * 8);
+ let i = 0;
+ for (const {
+ x,
+ y,
+ width,
+ height
+ } of boxes) {
+ const sx = x * pageWidth;
+ const sy = (1 - y - height) * pageHeight;
+ quadPoints[i] = quadPoints[i + 4] = sx;
+ quadPoints[i + 1] = quadPoints[i + 3] = sy;
+ quadPoints[i + 2] = quadPoints[i + 6] = sx + width * pageWidth;
+ quadPoints[i + 5] = quadPoints[i + 7] = sy + height * pageHeight;
+ i += 8;
+ }
+ return quadPoints;
+ }
+ #serializeOutlines(rect) {
+ return this.#highlightOutlines.serialize(rect, this.#getRotation());
+ }
+ static startHighlighting(parent, isLTR, {
+ target: textLayer,
+ x,
+ y
+ }) {
+ const {
+ x: layerX,
+ y: layerY,
+ width: parentWidth,
+ height: parentHeight
+ } = textLayer.getBoundingClientRect();
+ const pointerMove = e => {
+ this.#highlightMove(parent, e);
+ };
+ const pointerDownOptions = {
+ capture: true,
+ passive: false
+ };
+ const pointerDown = e => {
+ e.preventDefault();
+ e.stopPropagation();
+ };
+ const pointerUpCallback = e => {
+ textLayer.removeEventListener("pointermove", pointerMove);
+ window.removeEventListener("blur", pointerUpCallback);
+ window.removeEventListener("pointerup", pointerUpCallback);
+ window.removeEventListener("pointerdown", pointerDown, pointerDownOptions);
+ window.removeEventListener("contextmenu", noContextMenu);
+ this.#endHighlight(parent, e);
+ };
+ window.addEventListener("blur", pointerUpCallback);
+ window.addEventListener("pointerup", pointerUpCallback);
+ window.addEventListener("pointerdown", pointerDown, pointerDownOptions);
+ window.addEventListener("contextmenu", noContextMenu);
+ textLayer.addEventListener("pointermove", pointerMove);
+ this._freeHighlight = new FreeOutliner({
+ x,
+ y
+ }, [layerX, layerY, parentWidth, parentHeight], parent.scale, this._defaultThickness / 2, isLTR, 0.001);
+ ({
+ id: this._freeHighlightId,
+ clipPathId: this._freeHighlightClipId
+ } = parent.drawLayer.highlight(this._freeHighlight, this._defaultColor, this._defaultOpacity, true));
+ }
+ static #highlightMove(parent, event) {
+ if (this._freeHighlight.add(event)) {
+ parent.drawLayer.updatePath(this._freeHighlightId, this._freeHighlight);
+ }
+ }
+ static #endHighlight(parent, event) {
+ if (!this._freeHighlight.isEmpty()) {
+ parent.createAndAddNewEditor(event, false, {
+ highlightId: this._freeHighlightId,
+ highlightOutlines: this._freeHighlight.getOutlines(),
+ clipPathId: this._freeHighlightClipId,
+ methodOfCreation: "main_toolbar"
+ });
+ } else {
+ parent.drawLayer.removeFreeHighlight(this._freeHighlightId);
+ }
+ this._freeHighlightId = -1;
+ this._freeHighlight = null;
+ this._freeHighlightClipId = "";
+ }
+ static deserialize(data, parent, uiManager) {
+ const editor = super.deserialize(data, parent, uiManager);
+ const {
+ rect: [blX, blY, trX, trY],
+ color,
+ quadPoints
+ } = data;
+ editor.color = Util.makeHexColor(...color);
+ editor.#opacity = data.opacity;
+ const [pageWidth, pageHeight] = editor.pageDimensions;
+ editor.width = (trX - blX) / pageWidth;
+ editor.height = (trY - blY) / pageHeight;
+ const boxes = editor.#boxes = [];
+ for (let i = 0; i < quadPoints.length; i += 8) {
+ boxes.push({
+ x: (quadPoints[4] - trX) / pageWidth,
+ y: (trY - (1 - quadPoints[i + 5])) / pageHeight,
+ width: (quadPoints[i + 2] - quadPoints[i]) / pageWidth,
+ height: (quadPoints[i + 5] - quadPoints[i + 1]) / pageHeight
+ });
+ }
+ editor.#createOutlines();
+ return editor;
+ }
+ serialize(isForCopying = false) {
+ if (this.isEmpty() || isForCopying) {
+ return null;
+ }
+ const rect = this.getRect(0, 0);
+ const color = AnnotationEditor._colorManager.convert(this.color);
+ return {
+ annotationType: AnnotationEditorType.HIGHLIGHT,
+ color,
+ opacity: this.#opacity,
+ thickness: this.#thickness,
+ quadPoints: this.#serializeBoxes(),
+ outlines: this.#serializeOutlines(rect),
+ pageIndex: this.pageIndex,
+ rect,
+ rotation: this.#getRotation(),
+ structTreeParentId: this._structTreeParentId
+ };
+ }
+ static canCreateNewEmptyEditor() {
+ return false;
+ }
+}
+
+;// CONCATENATED MODULE: ./src/display/editor/ink.js
+
+
+
+
+
+class InkEditor extends AnnotationEditor {
+ #baseHeight = 0;
+ #baseWidth = 0;
+ #boundCanvasPointermove = this.canvasPointermove.bind(this);
+ #boundCanvasPointerleave = this.canvasPointerleave.bind(this);
+ #boundCanvasPointerup = this.canvasPointerup.bind(this);
+ #boundCanvasPointerdown = this.canvasPointerdown.bind(this);
+ #canvasContextMenuTimeoutId = null;
+ #currentPath2D = new Path2D();
+ #disableEditing = false;
+ #hasSomethingToDraw = false;
+ #isCanvasInitialized = false;
+ #observer = null;
+ #realWidth = 0;
+ #realHeight = 0;
+ #requestFrameCallback = null;
+ static _defaultColor = null;
+ static _defaultOpacity = 1;
+ static _defaultThickness = 1;
+ static _type = "ink";
+ static _editorType = AnnotationEditorType.INK;
+ constructor(params) {
+ super({
+ ...params,
+ name: "inkEditor"
+ });
+ this.color = params.color || null;
+ this.thickness = params.thickness || null;
+ this.opacity = params.opacity || null;
+ this.paths = [];
+ this.bezierPath2D = [];
+ this.allRawPaths = [];
+ this.currentPath = [];
+ this.scaleFactor = 1;
+ this.translationX = this.translationY = 0;
+ this.x = 0;
+ this.y = 0;
+ this._willKeepAspectRatio = true;
+ }
+ static initialize(l10n, uiManager) {
+ AnnotationEditor.initialize(l10n, uiManager);
+ }
+ static updateDefaultParams(type, value) {
+ switch (type) {
+ case AnnotationEditorParamsType.INK_THICKNESS:
+ InkEditor._defaultThickness = value;
+ break;
+ case AnnotationEditorParamsType.INK_COLOR:
+ InkEditor._defaultColor = value;
+ break;
+ case AnnotationEditorParamsType.INK_OPACITY:
+ InkEditor._defaultOpacity = value / 100;
+ break;
+ }
+ }
+ updateParams(type, value) {
+ switch (type) {
+ case AnnotationEditorParamsType.INK_THICKNESS:
+ this.#updateThickness(value);
+ break;
+ case AnnotationEditorParamsType.INK_COLOR:
+ this.#updateColor(value);
+ break;
+ case AnnotationEditorParamsType.INK_OPACITY:
+ this.#updateOpacity(value);
+ break;
+ }
+ }
+ static get defaultPropertiesToUpdate() {
+ return [[AnnotationEditorParamsType.INK_THICKNESS, InkEditor._defaultThickness], [AnnotationEditorParamsType.INK_COLOR, InkEditor._defaultColor || AnnotationEditor._defaultLineColor], [AnnotationEditorParamsType.INK_OPACITY, Math.round(InkEditor._defaultOpacity * 100)]];
+ }
+ get propertiesToUpdate() {
+ return [[AnnotationEditorParamsType.INK_THICKNESS, this.thickness || InkEditor._defaultThickness], [AnnotationEditorParamsType.INK_COLOR, this.color || InkEditor._defaultColor || AnnotationEditor._defaultLineColor], [AnnotationEditorParamsType.INK_OPACITY, Math.round(100 * (this.opacity ?? InkEditor._defaultOpacity))]];
+ }
+ #updateThickness(thickness) {
+ const setThickness = th => {
+ this.thickness = th;
+ this.#fitToContent();
+ };
+ const savedThickness = this.thickness;
+ this.addCommands({
+ cmd: setThickness.bind(this, thickness),
+ undo: setThickness.bind(this, savedThickness),
+ post: this._uiManager.updateUI.bind(this._uiManager, this),
+ mustExec: true,
+ type: AnnotationEditorParamsType.INK_THICKNESS,
+ overwriteIfSameType: true,
+ keepUndo: true
+ });
+ }
+ #updateColor(color) {
+ const setColor = col => {
+ this.color = col;
+ this.#redraw();
+ };
+ const savedColor = this.color;
+ this.addCommands({
+ cmd: setColor.bind(this, color),
+ undo: setColor.bind(this, savedColor),
+ post: this._uiManager.updateUI.bind(this._uiManager, this),
+ mustExec: true,
+ type: AnnotationEditorParamsType.INK_COLOR,
+ overwriteIfSameType: true,
+ keepUndo: true
+ });
+ }
+ #updateOpacity(opacity) {
+ const setOpacity = op => {
+ this.opacity = op;
+ this.#redraw();
+ };
+ opacity /= 100;
+ const savedOpacity = this.opacity;
+ this.addCommands({
+ cmd: setOpacity.bind(this, opacity),
+ undo: setOpacity.bind(this, savedOpacity),
+ post: this._uiManager.updateUI.bind(this._uiManager, this),
+ mustExec: true,
+ type: AnnotationEditorParamsType.INK_OPACITY,
+ overwriteIfSameType: true,
+ keepUndo: true
+ });
+ }
+ rebuild() {
+ if (!this.parent) {
+ return;
+ }
+ super.rebuild();
+ if (this.div === null) {
+ return;
+ }
+ if (!this.canvas) {
+ this.#createCanvas();
+ this.#createObserver();
+ }
+ if (!this.isAttachedToDOM) {
+ this.parent.add(this);
+ this.#setCanvasDims();
+ }
+ this.#fitToContent();
+ }
+ remove() {
+ if (this.canvas === null) {
+ return;
+ }
+ if (!this.isEmpty()) {
+ this.commit();
+ }
+ this.canvas.width = this.canvas.height = 0;
+ this.canvas.remove();
+ this.canvas = null;
+ if (this.#canvasContextMenuTimeoutId) {
+ clearTimeout(this.#canvasContextMenuTimeoutId);
+ this.#canvasContextMenuTimeoutId = null;
+ }
+ this.#observer.disconnect();
+ this.#observer = null;
+ super.remove();
+ }
+ setParent(parent) {
+ if (!this.parent && parent) {
+ this._uiManager.removeShouldRescale(this);
+ } else if (this.parent && parent === null) {
+ this._uiManager.addShouldRescale(this);
+ }
+ super.setParent(parent);
+ }
+ onScaleChanging() {
+ const [parentWidth, parentHeight] = this.parentDimensions;
+ const width = this.width * parentWidth;
+ const height = this.height * parentHeight;
+ this.setDimensions(width, height);
+ }
+ enableEditMode() {
+ if (this.#disableEditing || this.canvas === null) {
+ return;
+ }
+ super.enableEditMode();
+ this._isDraggable = false;
+ this.canvas.addEventListener("pointerdown", this.#boundCanvasPointerdown);
+ }
+ disableEditMode() {
+ if (!this.isInEditMode() || this.canvas === null) {
+ return;
+ }
+ super.disableEditMode();
+ this._isDraggable = !this.isEmpty();
+ this.div.classList.remove("editing");
+ this.canvas.removeEventListener("pointerdown", this.#boundCanvasPointerdown);
+ }
+ onceAdded() {
+ this._isDraggable = !this.isEmpty();
+ }
+ isEmpty() {
+ return this.paths.length === 0 || this.paths.length === 1 && this.paths[0].length === 0;
+ }
+ #getInitialBBox() {
+ const {
+ parentRotation,
+ parentDimensions: [width, height]
+ } = this;
+ switch (parentRotation) {
+ case 90:
+ return [0, height, height, width];
+ case 180:
+ return [width, height, width, height];
+ case 270:
+ return [width, 0, height, width];
+ default:
+ return [0, 0, width, height];
+ }
+ }
+ #setStroke() {
+ const {
+ ctx,
+ color,
+ opacity,
+ thickness,
+ parentScale,
+ scaleFactor
+ } = this;
+ ctx.lineWidth = thickness * parentScale / scaleFactor;
+ ctx.lineCap = "round";
+ ctx.lineJoin = "round";
+ ctx.miterLimit = 10;
+ ctx.strokeStyle = `${color}${opacityToHex(opacity)}`;
+ }
+ #startDrawing(x, y) {
+ this.canvas.addEventListener("contextmenu", noContextMenu);
+ this.canvas.addEventListener("pointerleave", this.#boundCanvasPointerleave);
+ this.canvas.addEventListener("pointermove", this.#boundCanvasPointermove);
+ this.canvas.addEventListener("pointerup", this.#boundCanvasPointerup);
+ this.canvas.removeEventListener("pointerdown", this.#boundCanvasPointerdown);
+ this.isEditing = true;
+ if (!this.#isCanvasInitialized) {
+ this.#isCanvasInitialized = true;
+ this.#setCanvasDims();
+ this.thickness ||= InkEditor._defaultThickness;
+ this.color ||= InkEditor._defaultColor || AnnotationEditor._defaultLineColor;
+ this.opacity ??= InkEditor._defaultOpacity;
+ }
+ this.currentPath.push([x, y]);
+ this.#hasSomethingToDraw = false;
+ this.#setStroke();
+ this.#requestFrameCallback = () => {
+ this.#drawPoints();
+ if (this.#requestFrameCallback) {
+ window.requestAnimationFrame(this.#requestFrameCallback);
+ }
+ };
+ window.requestAnimationFrame(this.#requestFrameCallback);
+ }
+ #draw(x, y) {
+ const [lastX, lastY] = this.currentPath.at(-1);
+ if (this.currentPath.length > 1 && x === lastX && y === lastY) {
+ return;
+ }
+ const currentPath = this.currentPath;
+ let path2D = this.#currentPath2D;
+ currentPath.push([x, y]);
+ this.#hasSomethingToDraw = true;
+ if (currentPath.length <= 2) {
+ path2D.moveTo(...currentPath[0]);
+ path2D.lineTo(x, y);
+ return;
+ }
+ if (currentPath.length === 3) {
+ this.#currentPath2D = path2D = new Path2D();
+ path2D.moveTo(...currentPath[0]);
+ }
+ this.#makeBezierCurve(path2D, ...currentPath.at(-3), ...currentPath.at(-2), x, y);
+ }
+ #endPath() {
+ if (this.currentPath.length === 0) {
+ return;
+ }
+ const lastPoint = this.currentPath.at(-1);
+ this.#currentPath2D.lineTo(...lastPoint);
+ }
+ #stopDrawing(x, y) {
+ this.#requestFrameCallback = null;
+ x = Math.min(Math.max(x, 0), this.canvas.width);
+ y = Math.min(Math.max(y, 0), this.canvas.height);
+ this.#draw(x, y);
+ this.#endPath();
+ let bezier;
+ if (this.currentPath.length !== 1) {
+ bezier = this.#generateBezierPoints();
+ } else {
+ const xy = [x, y];
+ bezier = [[xy, xy.slice(), xy.slice(), xy]];
+ }
+ const path2D = this.#currentPath2D;
+ const currentPath = this.currentPath;
+ this.currentPath = [];
+ this.#currentPath2D = new Path2D();
+ const cmd = () => {
+ this.allRawPaths.push(currentPath);
+ this.paths.push(bezier);
+ this.bezierPath2D.push(path2D);
+ this.rebuild();
+ };
+ const undo = () => {
+ this.allRawPaths.pop();
+ this.paths.pop();
+ this.bezierPath2D.pop();
+ if (this.paths.length === 0) {
+ this.remove();
+ } else {
+ if (!this.canvas) {
+ this.#createCanvas();
+ this.#createObserver();
+ }
+ this.#fitToContent();
+ }
+ };
+ this.addCommands({
+ cmd,
+ undo,
+ mustExec: true
+ });
+ }
+ #drawPoints() {
+ if (!this.#hasSomethingToDraw) {
+ return;
+ }
+ this.#hasSomethingToDraw = false;
+ const thickness = Math.ceil(this.thickness * this.parentScale);
+ const lastPoints = this.currentPath.slice(-3);
+ const x = lastPoints.map(xy => xy[0]);
+ const y = lastPoints.map(xy => xy[1]);
+ const xMin = Math.min(...x) - thickness;
+ const xMax = Math.max(...x) + thickness;
+ const yMin = Math.min(...y) - thickness;
+ const yMax = Math.max(...y) + thickness;
+ const {
+ ctx
+ } = this;
+ ctx.save();
+ ctx.clearRect(xMin, yMin, xMax - xMin, yMax - yMin);
+ ctx.beginPath();
+ ctx.rect(xMin, yMin, xMax - xMin, yMax - yMin);
+ ctx.clip();
+ for (const path of this.bezierPath2D) {
+ ctx.stroke(path);
+ }
+ ctx.stroke(this.#currentPath2D);
+ ctx.restore();
+ }
+ #makeBezierCurve(path2D, x0, y0, x1, y1, x2, y2) {
+ const prevX = (x0 + x1) / 2;
+ const prevY = (y0 + y1) / 2;
+ const x3 = (x1 + x2) / 2;
+ const y3 = (y1 + y2) / 2;
+ path2D.bezierCurveTo(prevX + 2 * (x1 - prevX) / 3, prevY + 2 * (y1 - prevY) / 3, x3 + 2 * (x1 - x3) / 3, y3 + 2 * (y1 - y3) / 3, x3, y3);
+ }
+ #generateBezierPoints() {
+ const path = this.currentPath;
+ if (path.length <= 2) {
+ return [[path[0], path[0], path.at(-1), path.at(-1)]];
+ }
+ const bezierPoints = [];
+ let i;
+ let [x0, y0] = path[0];
+ for (i = 1; i < path.length - 2; i++) {
+ const [x1, y1] = path[i];
+ const [x2, y2] = path[i + 1];
+ const x3 = (x1 + x2) / 2;
+ const y3 = (y1 + y2) / 2;
+ const control1 = [x0 + 2 * (x1 - x0) / 3, y0 + 2 * (y1 - y0) / 3];
+ const control2 = [x3 + 2 * (x1 - x3) / 3, y3 + 2 * (y1 - y3) / 3];
+ bezierPoints.push([[x0, y0], control1, control2, [x3, y3]]);
+ [x0, y0] = [x3, y3];
+ }
+ const [x1, y1] = path[i];
+ const [x2, y2] = path[i + 1];
+ const control1 = [x0 + 2 * (x1 - x0) / 3, y0 + 2 * (y1 - y0) / 3];
+ const control2 = [x2 + 2 * (x1 - x2) / 3, y2 + 2 * (y1 - y2) / 3];
+ bezierPoints.push([[x0, y0], control1, control2, [x2, y2]]);
+ return bezierPoints;
+ }
+ #redraw() {
+ if (this.isEmpty()) {
+ this.#updateTransform();
+ return;
+ }
+ this.#setStroke();
+ const {
+ canvas,
+ ctx
+ } = this;
+ ctx.setTransform(1, 0, 0, 1, 0, 0);
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
+ this.#updateTransform();
+ for (const path of this.bezierPath2D) {
+ ctx.stroke(path);
+ }
+ }
+ commit() {
+ if (this.#disableEditing) {
+ return;
+ }
+ super.commit();
+ this.isEditing = false;
+ this.disableEditMode();
+ this.setInForeground();
+ this.#disableEditing = true;
+ this.div.classList.add("disabled");
+ this.#fitToContent(true);
+ this.select();
+ this.parent.addInkEditorIfNeeded(true);
+ this.moveInDOM();
+ this.div.focus({
+ preventScroll: true
+ });
+ }
+ focusin(event) {
+ if (!this._focusEventsAllowed) {
+ return;
+ }
+ super.focusin(event);
+ this.enableEditMode();
+ }
+ canvasPointerdown(event) {
+ if (event.button !== 0 || !this.isInEditMode() || this.#disableEditing) {
+ return;
+ }
+ this.setInForeground();
+ event.preventDefault();
+ if (!this.div.contains(document.activeElement)) {
+ this.div.focus({
+ preventScroll: true
+ });
+ }
+ this.#startDrawing(event.offsetX, event.offsetY);
+ }
+ canvasPointermove(event) {
+ event.preventDefault();
+ this.#draw(event.offsetX, event.offsetY);
+ }
+ canvasPointerup(event) {
+ event.preventDefault();
+ this.#endDrawing(event);
+ }
+ canvasPointerleave(event) {
+ this.#endDrawing(event);
+ }
+ #endDrawing(event) {
+ this.canvas.removeEventListener("pointerleave", this.#boundCanvasPointerleave);
+ this.canvas.removeEventListener("pointermove", this.#boundCanvasPointermove);
+ this.canvas.removeEventListener("pointerup", this.#boundCanvasPointerup);
+ this.canvas.addEventListener("pointerdown", this.#boundCanvasPointerdown);
+ if (this.#canvasContextMenuTimeoutId) {
+ clearTimeout(this.#canvasContextMenuTimeoutId);
+ }
+ this.#canvasContextMenuTimeoutId = setTimeout(() => {
+ this.#canvasContextMenuTimeoutId = null;
+ this.canvas.removeEventListener("contextmenu", noContextMenu);
+ }, 10);
+ this.#stopDrawing(event.offsetX, event.offsetY);
+ this.addToAnnotationStorage();
+ this.setInBackground();
+ }
+ #createCanvas() {
+ this.canvas = document.createElement("canvas");
+ this.canvas.width = this.canvas.height = 0;
+ this.canvas.className = "inkEditorCanvas";
+ this.canvas.setAttribute("data-l10n-id", "pdfjs-ink-canvas");
+ this.div.append(this.canvas);
+ this.ctx = this.canvas.getContext("2d");
+ }
+ #createObserver() {
+ this.#observer = new ResizeObserver(entries => {
+ const rect = entries[0].contentRect;
+ if (rect.width && rect.height) {
+ this.setDimensions(rect.width, rect.height);
+ }
+ });
+ this.#observer.observe(this.div);
+ }
+ get isResizable() {
+ return !this.isEmpty() && this.#disableEditing;
+ }
+ render() {
+ if (this.div) {
+ return this.div;
+ }
+ let baseX, baseY;
+ if (this.width) {
+ baseX = this.x;
+ baseY = this.y;
+ }
+ super.render();
+ this.div.setAttribute("data-l10n-id", "pdfjs-ink");
+ const [x, y, w, h] = this.#getInitialBBox();
+ this.setAt(x, y, 0, 0);
+ this.setDims(w, h);
+ this.#createCanvas();
+ if (this.width) {
+ const [parentWidth, parentHeight] = this.parentDimensions;
+ this.setAspectRatio(this.width * parentWidth, this.height * parentHeight);
+ this.setAt(baseX * parentWidth, baseY * parentHeight, this.width * parentWidth, this.height * parentHeight);
+ this.#isCanvasInitialized = true;
+ this.#setCanvasDims();
+ this.setDims(this.width * parentWidth, this.height * parentHeight);
+ this.#redraw();
+ this.div.classList.add("disabled");
+ } else {
+ this.div.classList.add("editing");
+ this.enableEditMode();
+ }
+ this.#createObserver();
+ return this.div;
+ }
+ #setCanvasDims() {
+ if (!this.#isCanvasInitialized) {
+ return;
+ }
+ const [parentWidth, parentHeight] = this.parentDimensions;
+ this.canvas.width = Math.ceil(this.width * parentWidth);
+ this.canvas.height = Math.ceil(this.height * parentHeight);
+ this.#updateTransform();
+ }
+ setDimensions(width, height) {
+ const roundedWidth = Math.round(width);
+ const roundedHeight = Math.round(height);
+ if (this.#realWidth === roundedWidth && this.#realHeight === roundedHeight) {
+ return;
+ }
+ this.#realWidth = roundedWidth;
+ this.#realHeight = roundedHeight;
+ this.canvas.style.visibility = "hidden";
+ const [parentWidth, parentHeight] = this.parentDimensions;
+ this.width = width / parentWidth;
+ this.height = height / parentHeight;
+ this.fixAndSetPosition();
+ if (this.#disableEditing) {
+ this.#setScaleFactor(width, height);
+ }
+ this.#setCanvasDims();
+ this.#redraw();
+ this.canvas.style.visibility = "visible";
+ this.fixDims();
+ }
+ #setScaleFactor(width, height) {
+ const padding = this.#getPadding();
+ const scaleFactorW = (width - padding) / this.#baseWidth;
+ const scaleFactorH = (height - padding) / this.#baseHeight;
+ this.scaleFactor = Math.min(scaleFactorW, scaleFactorH);
+ }
+ #updateTransform() {
+ const padding = this.#getPadding() / 2;
+ this.ctx.setTransform(this.scaleFactor, 0, 0, this.scaleFactor, this.translationX * this.scaleFactor + padding, this.translationY * this.scaleFactor + padding);
+ }
+ static #buildPath2D(bezier) {
+ const path2D = new Path2D();
+ for (let i = 0, ii = bezier.length; i < ii; i++) {
+ const [first, control1, control2, second] = bezier[i];
+ if (i === 0) {
+ path2D.moveTo(...first);
+ }
+ path2D.bezierCurveTo(control1[0], control1[1], control2[0], control2[1], second[0], second[1]);
+ }
+ return path2D;
+ }
+ static #toPDFCoordinates(points, rect, rotation) {
+ const [blX, blY, trX, trY] = rect;
+ switch (rotation) {
+ case 0:
+ for (let i = 0, ii = points.length; i < ii; i += 2) {
+ points[i] += blX;
+ points[i + 1] = trY - points[i + 1];
+ }
+ break;
+ case 90:
+ for (let i = 0, ii = points.length; i < ii; i += 2) {
+ const x = points[i];
+ points[i] = points[i + 1] + blX;
+ points[i + 1] = x + blY;
+ }
+ break;
+ case 180:
+ for (let i = 0, ii = points.length; i < ii; i += 2) {
+ points[i] = trX - points[i];
+ points[i + 1] += blY;
+ }
+ break;
+ case 270:
+ for (let i = 0, ii = points.length; i < ii; i += 2) {
+ const x = points[i];
+ points[i] = trX - points[i + 1];
+ points[i + 1] = trY - x;
+ }
+ break;
+ default:
+ throw new Error("Invalid rotation");
+ }
+ return points;
+ }
+ static #fromPDFCoordinates(points, rect, rotation) {
+ const [blX, blY, trX, trY] = rect;
+ switch (rotation) {
+ case 0:
+ for (let i = 0, ii = points.length; i < ii; i += 2) {
+ points[i] -= blX;
+ points[i + 1] = trY - points[i + 1];
+ }
+ break;
+ case 90:
+ for (let i = 0, ii = points.length; i < ii; i += 2) {
+ const x = points[i];
+ points[i] = points[i + 1] - blY;
+ points[i + 1] = x - blX;
+ }
+ break;
+ case 180:
+ for (let i = 0, ii = points.length; i < ii; i += 2) {
+ points[i] = trX - points[i];
+ points[i + 1] -= blY;
+ }
+ break;
+ case 270:
+ for (let i = 0, ii = points.length; i < ii; i += 2) {
+ const x = points[i];
+ points[i] = trY - points[i + 1];
+ points[i + 1] = trX - x;
+ }
+ break;
+ default:
+ throw new Error("Invalid rotation");
+ }
+ return points;
+ }
+ #serializePaths(s, tx, ty, rect) {
+ const paths = [];
+ const padding = this.thickness / 2;
+ const shiftX = s * tx + padding;
+ const shiftY = s * ty + padding;
+ for (const bezier of this.paths) {
+ const buffer = [];
+ const points = [];
+ for (let j = 0, jj = bezier.length; j < jj; j++) {
+ const [first, control1, control2, second] = bezier[j];
+ if (first[0] === second[0] && first[1] === second[1] && jj === 1) {
+ const p0 = s * first[0] + shiftX;
+ const p1 = s * first[1] + shiftY;
+ buffer.push(p0, p1);
+ points.push(p0, p1);
+ break;
+ }
+ const p10 = s * first[0] + shiftX;
+ const p11 = s * first[1] + shiftY;
+ const p20 = s * control1[0] + shiftX;
+ const p21 = s * control1[1] + shiftY;
+ const p30 = s * control2[0] + shiftX;
+ const p31 = s * control2[1] + shiftY;
+ const p40 = s * second[0] + shiftX;
+ const p41 = s * second[1] + shiftY;
+ if (j === 0) {
+ buffer.push(p10, p11);
+ points.push(p10, p11);
+ }
+ buffer.push(p20, p21, p30, p31, p40, p41);
+ points.push(p20, p21);
+ if (j === jj - 1) {
+ points.push(p40, p41);
+ }
+ }
+ paths.push({
+ bezier: InkEditor.#toPDFCoordinates(buffer, rect, this.rotation),
+ points: InkEditor.#toPDFCoordinates(points, rect, this.rotation)
+ });
+ }
+ return paths;
+ }
+ #getBbox() {
+ let xMin = Infinity;
+ let xMax = -Infinity;
+ let yMin = Infinity;
+ let yMax = -Infinity;
+ for (const path of this.paths) {
+ for (const [first, control1, control2, second] of path) {
+ const bbox = Util.bezierBoundingBox(...first, ...control1, ...control2, ...second);
+ xMin = Math.min(xMin, bbox[0]);
+ yMin = Math.min(yMin, bbox[1]);
+ xMax = Math.max(xMax, bbox[2]);
+ yMax = Math.max(yMax, bbox[3]);
+ }
+ }
+ return [xMin, yMin, xMax, yMax];
+ }
+ #getPadding() {
+ return this.#disableEditing ? Math.ceil(this.thickness * this.parentScale) : 0;
+ }
+ #fitToContent(firstTime = false) {
+ if (this.isEmpty()) {
+ return;
+ }
+ if (!this.#disableEditing) {
+ this.#redraw();
+ return;
+ }
+ const bbox = this.#getBbox();
+ const padding = this.#getPadding();
+ this.#baseWidth = Math.max(AnnotationEditor.MIN_SIZE, bbox[2] - bbox[0]);
+ this.#baseHeight = Math.max(AnnotationEditor.MIN_SIZE, bbox[3] - bbox[1]);
+ const width = Math.ceil(padding + this.#baseWidth * this.scaleFactor);
+ const height = Math.ceil(padding + this.#baseHeight * this.scaleFactor);
+ const [parentWidth, parentHeight] = this.parentDimensions;
+ this.width = width / parentWidth;
+ this.height = height / parentHeight;
+ this.setAspectRatio(width, height);
+ const prevTranslationX = this.translationX;
+ const prevTranslationY = this.translationY;
+ this.translationX = -bbox[0];
+ this.translationY = -bbox[1];
+ this.#setCanvasDims();
+ this.#redraw();
+ this.#realWidth = width;
+ this.#realHeight = height;
+ this.setDims(width, height);
+ const unscaledPadding = firstTime ? padding / this.scaleFactor / 2 : 0;
+ this.translate(prevTranslationX - this.translationX - unscaledPadding, prevTranslationY - this.translationY - unscaledPadding);
+ }
+ static deserialize(data, parent, uiManager) {
+ if (data instanceof InkAnnotationElement) {
+ return null;
+ }
+ const editor = super.deserialize(data, parent, uiManager);
+ editor.thickness = data.thickness;
+ editor.color = Util.makeHexColor(...data.color);
+ editor.opacity = data.opacity;
+ const [pageWidth, pageHeight] = editor.pageDimensions;
+ const width = editor.width * pageWidth;
+ const height = editor.height * pageHeight;
+ const scaleFactor = editor.parentScale;
+ const padding = data.thickness / 2;
+ editor.#disableEditing = true;
+ editor.#realWidth = Math.round(width);
+ editor.#realHeight = Math.round(height);
+ const {
+ paths,
+ rect,
+ rotation
+ } = data;
+ for (let {
+ bezier
+ } of paths) {
+ bezier = InkEditor.#fromPDFCoordinates(bezier, rect, rotation);
+ const path = [];
+ editor.paths.push(path);
+ let p0 = scaleFactor * (bezier[0] - padding);
+ let p1 = scaleFactor * (bezier[1] - padding);
+ for (let i = 2, ii = bezier.length; i < ii; i += 6) {
+ const p10 = scaleFactor * (bezier[i] - padding);
+ const p11 = scaleFactor * (bezier[i + 1] - padding);
+ const p20 = scaleFactor * (bezier[i + 2] - padding);
+ const p21 = scaleFactor * (bezier[i + 3] - padding);
+ const p30 = scaleFactor * (bezier[i + 4] - padding);
+ const p31 = scaleFactor * (bezier[i + 5] - padding);
+ path.push([[p0, p1], [p10, p11], [p20, p21], [p30, p31]]);
+ p0 = p30;
+ p1 = p31;
+ }
+ const path2D = this.#buildPath2D(path);
+ editor.bezierPath2D.push(path2D);
+ }
+ const bbox = editor.#getBbox();
+ editor.#baseWidth = Math.max(AnnotationEditor.MIN_SIZE, bbox[2] - bbox[0]);
+ editor.#baseHeight = Math.max(AnnotationEditor.MIN_SIZE, bbox[3] - bbox[1]);
+ editor.#setScaleFactor(width, height);
+ return editor;
+ }
+ serialize() {
+ if (this.isEmpty()) {
+ return null;
+ }
+ const rect = this.getRect(0, 0);
+ const color = AnnotationEditor._colorManager.convert(this.ctx.strokeStyle);
+ return {
+ annotationType: AnnotationEditorType.INK,
+ color,
+ thickness: this.thickness,
+ opacity: this.opacity,
+ paths: this.#serializePaths(this.scaleFactor / this.parentScale, this.translationX, this.translationY, rect),
+ pageIndex: this.pageIndex,
+ rect,
+ rotation: this.rotation,
+ structTreeParentId: this._structTreeParentId
+ };
+ }
+}
+
+;// CONCATENATED MODULE: ./src/display/editor/stamp.js
+
+
+
+
+class StampEditor extends AnnotationEditor {
+ #bitmap = null;
+ #bitmapId = null;
+ #bitmapPromise = null;
+ #bitmapUrl = null;
+ #bitmapFile = null;
+ #bitmapFileName = "";
+ #canvas = null;
+ #observer = null;
+ #resizeTimeoutId = null;
+ #isSvg = false;
+ #hasBeenAddedInUndoStack = false;
+ static _type = "stamp";
+ static _editorType = AnnotationEditorType.STAMP;
+ constructor(params) {
+ super({
+ ...params,
+ name: "stampEditor"
+ });
+ this.#bitmapUrl = params.bitmapUrl;
+ this.#bitmapFile = params.bitmapFile;
+ }
+ static initialize(l10n, uiManager) {
+ AnnotationEditor.initialize(l10n, uiManager);
+ }
+ static get supportedTypes() {
+ const types = ["apng", "avif", "bmp", "gif", "jpeg", "png", "svg+xml", "webp", "x-icon"];
+ return shadow(this, "supportedTypes", types.map(type => `image/${type}`));
+ }
+ static get supportedTypesStr() {
+ return shadow(this, "supportedTypesStr", this.supportedTypes.join(","));
+ }
+ static isHandlingMimeForPasting(mime) {
+ return this.supportedTypes.includes(mime);
+ }
+ static paste(item, parent) {
+ parent.pasteEditor(AnnotationEditorType.STAMP, {
+ bitmapFile: item.getAsFile()
+ });
+ }
+ #getBitmapFetched(data, fromId = false) {
+ if (!data) {
+ this.remove();
+ return;
+ }
+ this.#bitmap = data.bitmap;
+ if (!fromId) {
+ this.#bitmapId = data.id;
+ this.#isSvg = data.isSvg;
+ }
+ if (data.file) {
+ this.#bitmapFileName = data.file.name;
+ }
+ this.#createCanvas();
+ }
+ #getBitmapDone() {
+ this.#bitmapPromise = null;
+ this._uiManager.enableWaiting(false);
+ if (this.#canvas) {
+ this.div.focus();
+ }
+ }
+ #getBitmap() {
+ if (this.#bitmapId) {
+ this._uiManager.enableWaiting(true);
+ this._uiManager.imageManager.getFromId(this.#bitmapId).then(data => this.#getBitmapFetched(data, true)).finally(() => this.#getBitmapDone());
+ return;
+ }
+ if (this.#bitmapUrl) {
+ const url = this.#bitmapUrl;
+ this.#bitmapUrl = null;
+ this._uiManager.enableWaiting(true);
+ this.#bitmapPromise = this._uiManager.imageManager.getFromUrl(url).then(data => this.#getBitmapFetched(data)).finally(() => this.#getBitmapDone());
+ return;
+ }
+ if (this.#bitmapFile) {
+ const file = this.#bitmapFile;
+ this.#bitmapFile = null;
+ this._uiManager.enableWaiting(true);
+ this.#bitmapPromise = this._uiManager.imageManager.getFromFile(file).then(data => this.#getBitmapFetched(data)).finally(() => this.#getBitmapDone());
+ return;
+ }
+ const input = document.createElement("input");
+ input.type = "file";
+ input.accept = StampEditor.supportedTypesStr;
+ this.#bitmapPromise = new Promise(resolve => {
+ input.addEventListener("change", async () => {
+ if (!input.files || input.files.length === 0) {
+ this.remove();
+ } else {
+ this._uiManager.enableWaiting(true);
+ const data = await this._uiManager.imageManager.getFromFile(input.files[0]);
+ this.#getBitmapFetched(data);
+ }
+ resolve();
+ });
+ input.addEventListener("cancel", () => {
+ this.remove();
+ resolve();
+ });
+ }).finally(() => this.#getBitmapDone());
+ input.click();
+ }
+ remove() {
+ if (this.#bitmapId) {
+ this.#bitmap = null;
+ this._uiManager.imageManager.deleteId(this.#bitmapId);
+ this.#canvas?.remove();
+ this.#canvas = null;
+ this.#observer?.disconnect();
+ this.#observer = null;
+ if (this.#resizeTimeoutId) {
+ clearTimeout(this.#resizeTimeoutId);
+ this.#resizeTimeoutId = null;
+ }
+ }
+ super.remove();
+ }
+ rebuild() {
+ if (!this.parent) {
+ if (this.#bitmapId) {
+ this.#getBitmap();
+ }
+ return;
+ }
+ super.rebuild();
+ if (this.div === null) {
+ return;
+ }
+ if (this.#bitmapId) {
+ this.#getBitmap();
+ }
+ if (!this.isAttachedToDOM) {
+ this.parent.add(this);
+ }
+ }
+ onceAdded() {
+ this._isDraggable = true;
+ this.div.focus();
+ }
+ isEmpty() {
+ return !(this.#bitmapPromise || this.#bitmap || this.#bitmapUrl || this.#bitmapFile);
+ }
+ get isResizable() {
+ return true;
+ }
+ render() {
+ if (this.div) {
+ return this.div;
+ }
+ let baseX, baseY;
+ if (this.width) {
+ baseX = this.x;
+ baseY = this.y;
+ }
+ super.render();
+ this.div.hidden = true;
+ if (this.#bitmap) {
+ this.#createCanvas();
+ } else {
+ this.#getBitmap();
+ }
+ if (this.width) {
+ const [parentWidth, parentHeight] = this.parentDimensions;
+ this.setAt(baseX * parentWidth, baseY * parentHeight, this.width * parentWidth, this.height * parentHeight);
+ }
+ return this.div;
+ }
+ #createCanvas() {
+ const {
+ div
+ } = this;
+ let {
+ width,
+ height
+ } = this.#bitmap;
+ const [pageWidth, pageHeight] = this.pageDimensions;
+ const MAX_RATIO = 0.75;
+ if (this.width) {
+ width = this.width * pageWidth;
+ height = this.height * pageHeight;
+ } else if (width > MAX_RATIO * pageWidth || height > MAX_RATIO * pageHeight) {
+ const factor = Math.min(MAX_RATIO * pageWidth / width, MAX_RATIO * pageHeight / height);
+ width *= factor;
+ height *= factor;
+ }
+ const [parentWidth, parentHeight] = this.parentDimensions;
+ this.setDims(width * parentWidth / pageWidth, height * parentHeight / pageHeight);
+ this._uiManager.enableWaiting(false);
+ const canvas = this.#canvas = document.createElement("canvas");
+ div.append(canvas);
+ div.hidden = false;
+ this.#drawBitmap(width, height);
+ this.#createObserver();
+ if (!this.#hasBeenAddedInUndoStack) {
+ this.parent.addUndoableEditor(this);
+ this.#hasBeenAddedInUndoStack = true;
+ }
+ this._reportTelemetry({
+ action: "inserted_image"
+ });
+ this.addAltTextButton();
+ if (this.#bitmapFileName) {
+ canvas.setAttribute("aria-label", this.#bitmapFileName);
+ }
+ }
+ #setDimensions(width, height) {
+ const [parentWidth, parentHeight] = this.parentDimensions;
+ this.width = width / parentWidth;
+ this.height = height / parentHeight;
+ this.setDims(width, height);
+ if (this._initialOptions?.isCentered) {
+ this.center();
+ } else {
+ this.fixAndSetPosition();
+ }
+ this._initialOptions = null;
+ if (this.#resizeTimeoutId !== null) {
+ clearTimeout(this.#resizeTimeoutId);
+ }
+ const TIME_TO_WAIT = 200;
+ this.#resizeTimeoutId = setTimeout(() => {
+ this.#resizeTimeoutId = null;
+ this.#drawBitmap(width, height);
+ }, TIME_TO_WAIT);
+ }
+ #scaleBitmap(width, height) {
+ const {
+ width: bitmapWidth,
+ height: bitmapHeight
+ } = this.#bitmap;
+ let newWidth = bitmapWidth;
+ let newHeight = bitmapHeight;
+ let bitmap = this.#bitmap;
+ while (newWidth > 2 * width || newHeight > 2 * height) {
+ const prevWidth = newWidth;
+ const prevHeight = newHeight;
+ if (newWidth > 2 * width) {
+ newWidth = newWidth >= 16384 ? Math.floor(newWidth / 2) - 1 : Math.ceil(newWidth / 2);
+ }
+ if (newHeight > 2 * height) {
+ newHeight = newHeight >= 16384 ? Math.floor(newHeight / 2) - 1 : Math.ceil(newHeight / 2);
+ }
+ const offscreen = new OffscreenCanvas(newWidth, newHeight);
+ const ctx = offscreen.getContext("2d");
+ ctx.drawImage(bitmap, 0, 0, prevWidth, prevHeight, 0, 0, newWidth, newHeight);
+ bitmap = offscreen.transferToImageBitmap();
+ }
+ return bitmap;
+ }
+ #drawBitmap(width, height) {
+ width = Math.ceil(width);
+ height = Math.ceil(height);
+ const canvas = this.#canvas;
+ if (!canvas || canvas.width === width && canvas.height === height) {
+ return;
+ }
+ canvas.width = width;
+ canvas.height = height;
+ const bitmap = this.#isSvg ? this.#bitmap : this.#scaleBitmap(width, height);
+ if (this._uiManager.hasMLManager && !this.hasAltText()) {
+ const offscreen = new OffscreenCanvas(width, height);
+ const ctx = offscreen.getContext("2d");
+ ctx.drawImage(bitmap, 0, 0, bitmap.width, bitmap.height, 0, 0, width, height);
+ offscreen.convertToBlob().then(blob => {
+ const fileReader = new FileReader();
+ fileReader.onload = () => {
+ const url = fileReader.result;
+ this._uiManager.mlGuess({
+ service: "image-to-text",
+ request: {
+ imageData: url
+ }
+ }).then(response => {
+ const altText = response?.output || "";
+ if (this.parent && altText && !this.hasAltText()) {
+ this.altTextData = {
+ altText,
+ decorative: false
+ };
+ }
+ });
+ };
+ fileReader.readAsDataURL(blob);
+ });
+ }
+ const ctx = canvas.getContext("2d");
+ ctx.filter = this._uiManager.hcmFilter;
+ ctx.drawImage(bitmap, 0, 0, bitmap.width, bitmap.height, 0, 0, width, height);
+ }
+ getImageForAltText() {
+ return this.#canvas;
+ }
+ #serializeBitmap(toUrl) {
+ if (toUrl) {
+ if (this.#isSvg) {
+ const url = this._uiManager.imageManager.getSvgUrl(this.#bitmapId);
+ if (url) {
+ return url;
+ }
+ }
+ const canvas = document.createElement("canvas");
+ ({
+ width: canvas.width,
+ height: canvas.height
+ } = this.#bitmap);
+ const ctx = canvas.getContext("2d");
+ ctx.drawImage(this.#bitmap, 0, 0);
+ return canvas.toDataURL();
+ }
+ if (this.#isSvg) {
+ const [pageWidth, pageHeight] = this.pageDimensions;
+ const width = Math.round(this.width * pageWidth * PixelsPerInch.PDF_TO_CSS_UNITS);
+ const height = Math.round(this.height * pageHeight * PixelsPerInch.PDF_TO_CSS_UNITS);
+ const offscreen = new OffscreenCanvas(width, height);
+ const ctx = offscreen.getContext("2d");
+ ctx.drawImage(this.#bitmap, 0, 0, this.#bitmap.width, this.#bitmap.height, 0, 0, width, height);
+ return offscreen.transferToImageBitmap();
+ }
+ return structuredClone(this.#bitmap);
+ }
+ #createObserver() {
+ this.#observer = new ResizeObserver(entries => {
+ const rect = entries[0].contentRect;
+ if (rect.width && rect.height) {
+ this.#setDimensions(rect.width, rect.height);
+ }
+ });
+ this.#observer.observe(this.div);
+ }
+ static deserialize(data, parent, uiManager) {
+ if (data instanceof StampAnnotationElement) {
+ return null;
+ }
+ const editor = super.deserialize(data, parent, uiManager);
+ const {
+ rect,
+ bitmapUrl,
+ bitmapId,
+ isSvg,
+ accessibilityData
+ } = data;
+ if (bitmapId && uiManager.imageManager.isValidId(bitmapId)) {
+ editor.#bitmapId = bitmapId;
+ } else {
+ editor.#bitmapUrl = bitmapUrl;
+ }
+ editor.#isSvg = isSvg;
+ const [parentWidth, parentHeight] = editor.pageDimensions;
+ editor.width = (rect[2] - rect[0]) / parentWidth;
+ editor.height = (rect[3] - rect[1]) / parentHeight;
+ if (accessibilityData) {
+ editor.altTextData = accessibilityData;
+ }
+ return editor;
+ }
+ serialize(isForCopying = false, context = null) {
+ if (this.isEmpty()) {
+ return null;
+ }
+ const serialized = {
+ annotationType: AnnotationEditorType.STAMP,
+ bitmapId: this.#bitmapId,
+ pageIndex: this.pageIndex,
+ rect: this.getRect(0, 0),
+ rotation: this.rotation,
+ isSvg: this.#isSvg,
+ structTreeParentId: this._structTreeParentId
+ };
+ if (isForCopying) {
+ serialized.bitmapUrl = this.#serializeBitmap(true);
+ serialized.accessibilityData = this.altTextData;
+ return serialized;
+ }
+ const {
+ decorative,
+ altText
+ } = this.altTextData;
+ if (!decorative && altText) {
+ serialized.accessibilityData = {
+ type: "Figure",
+ alt: altText
+ };
+ }
+ if (context === null) {
+ return serialized;
+ }
+ context.stamps ||= new Map();
+ const area = this.#isSvg ? (serialized.rect[2] - serialized.rect[0]) * (serialized.rect[3] - serialized.rect[1]) : null;
+ if (!context.stamps.has(this.#bitmapId)) {
+ context.stamps.set(this.#bitmapId, {
+ area,
+ serialized
+ });
+ serialized.bitmap = this.#serializeBitmap(false);
+ } else if (this.#isSvg) {
+ const prevData = context.stamps.get(this.#bitmapId);
+ if (area > prevData.area) {
+ prevData.area = area;
+ prevData.serialized.bitmap.close();
+ prevData.serialized.bitmap = this.#serializeBitmap(false);
+ }
+ }
+ return serialized;
+ }
+}
+
+;// CONCATENATED MODULE: ./src/display/editor/annotation_editor_layer.js
+
+
+
+
+
+
+
+class AnnotationEditorLayer {
+ #accessibilityManager;
+ #allowClick = false;
+ #annotationLayer = null;
+ #boundPointerup = this.pointerup.bind(this);
+ #boundPointerdown = this.pointerdown.bind(this);
+ #boundTextLayerPointerDown = this.#textLayerPointerDown.bind(this);
+ #editorFocusTimeoutId = null;
+ #editors = new Map();
+ #hadPointerDown = false;
+ #isCleaningUp = false;
+ #isDisabling = false;
+ #textLayer = null;
+ #uiManager;
+ static _initialized = false;
+ static #editorTypes = new Map([FreeTextEditor, InkEditor, StampEditor, HighlightEditor].map(type => [type._editorType, type]));
+ constructor({
+ uiManager,
+ pageIndex,
+ div,
+ accessibilityManager,
+ annotationLayer,
+ drawLayer,
+ textLayer,
+ viewport,
+ l10n
+ }) {
+ const editorTypes = [...AnnotationEditorLayer.#editorTypes.values()];
+ if (!AnnotationEditorLayer._initialized) {
+ AnnotationEditorLayer._initialized = true;
+ for (const editorType of editorTypes) {
+ editorType.initialize(l10n, uiManager);
+ }
+ }
+ uiManager.registerEditorTypes(editorTypes);
+ this.#uiManager = uiManager;
+ this.pageIndex = pageIndex;
+ this.div = div;
+ this.#accessibilityManager = accessibilityManager;
+ this.#annotationLayer = annotationLayer;
+ this.viewport = viewport;
+ this.#textLayer = textLayer;
+ this.drawLayer = drawLayer;
+ this.#uiManager.addLayer(this);
+ }
+ get isEmpty() {
+ return this.#editors.size === 0;
+ }
+ updateToolbar(mode) {
+ this.#uiManager.updateToolbar(mode);
+ }
+ updateMode(mode = this.#uiManager.getMode()) {
+ this.#cleanup();
+ switch (mode) {
+ case AnnotationEditorType.NONE:
+ this.disableTextSelection();
+ this.togglePointerEvents(false);
+ this.toggleAnnotationLayerPointerEvents(true);
+ this.disableClick();
+ return;
+ case AnnotationEditorType.INK:
+ this.addInkEditorIfNeeded(false);
+ this.disableTextSelection();
+ this.togglePointerEvents(true);
+ this.disableClick();
+ break;
+ case AnnotationEditorType.HIGHLIGHT:
+ this.enableTextSelection();
+ this.togglePointerEvents(false);
+ this.disableClick();
+ break;
+ default:
+ this.disableTextSelection();
+ this.togglePointerEvents(true);
+ this.enableClick();
+ }
+ this.toggleAnnotationLayerPointerEvents(false);
+ const {
+ classList
+ } = this.div;
+ for (const editorType of AnnotationEditorLayer.#editorTypes.values()) {
+ classList.toggle(`${editorType._type}Editing`, mode === editorType._editorType);
+ }
+ this.div.hidden = false;
+ }
+ hasTextLayer(textLayer) {
+ return textLayer === this.#textLayer?.div;
+ }
+ addInkEditorIfNeeded(isCommitting) {
+ if (this.#uiManager.getMode() !== AnnotationEditorType.INK) {
+ return;
+ }
+ if (!isCommitting) {
+ for (const editor of this.#editors.values()) {
+ if (editor.isEmpty()) {
+ editor.setInBackground();
+ return;
+ }
+ }
+ }
+ const editor = this.createAndAddNewEditor({
+ offsetX: 0,
+ offsetY: 0
+ }, false);
+ editor.setInBackground();
+ }
+ setEditingState(isEditing) {
+ this.#uiManager.setEditingState(isEditing);
+ }
+ addCommands(params) {
+ this.#uiManager.addCommands(params);
+ }
+ togglePointerEvents(enabled = false) {
+ this.div.classList.toggle("disabled", !enabled);
+ }
+ toggleAnnotationLayerPointerEvents(enabled = false) {
+ this.#annotationLayer?.div.classList.toggle("disabled", !enabled);
+ }
+ enable() {
+ this.togglePointerEvents(true);
+ const annotationElementIds = new Set();
+ for (const editor of this.#editors.values()) {
+ editor.enableEditing();
+ if (editor.annotationElementId) {
+ annotationElementIds.add(editor.annotationElementId);
+ }
+ }
+ if (!this.#annotationLayer) {
+ return;
+ }
+ const editables = this.#annotationLayer.getEditableAnnotations();
+ for (const editable of editables) {
+ editable.hide();
+ if (this.#uiManager.isDeletedAnnotationElement(editable.data.id)) {
+ continue;
+ }
+ if (annotationElementIds.has(editable.data.id)) {
+ continue;
+ }
+ const editor = this.deserialize(editable);
+ if (!editor) {
+ continue;
+ }
+ this.addOrRebuild(editor);
+ editor.enableEditing();
+ }
+ }
+ disable() {
+ this.#isDisabling = true;
+ this.togglePointerEvents(false);
+ const hiddenAnnotationIds = new Set();
+ for (const editor of this.#editors.values()) {
+ editor.disableEditing();
+ if (!editor.annotationElementId || editor.serialize() !== null) {
+ hiddenAnnotationIds.add(editor.annotationElementId);
+ continue;
+ }
+ this.getEditableAnnotation(editor.annotationElementId)?.show();
+ editor.remove();
+ }
+ if (this.#annotationLayer) {
+ const editables = this.#annotationLayer.getEditableAnnotations();
+ for (const editable of editables) {
+ const {
+ id
+ } = editable.data;
+ if (hiddenAnnotationIds.has(id) || this.#uiManager.isDeletedAnnotationElement(id)) {
+ continue;
+ }
+ editable.show();
+ }
+ }
+ this.#cleanup();
+ if (this.isEmpty) {
+ this.div.hidden = true;
+ }
+ const {
+ classList
+ } = this.div;
+ for (const editorType of AnnotationEditorLayer.#editorTypes.values()) {
+ classList.remove(`${editorType._type}Editing`);
+ }
+ this.disableTextSelection();
+ this.toggleAnnotationLayerPointerEvents(true);
+ this.#isDisabling = false;
+ }
+ getEditableAnnotation(id) {
+ return this.#annotationLayer?.getEditableAnnotation(id) || null;
+ }
+ setActiveEditor(editor) {
+ const currentActive = this.#uiManager.getActive();
+ if (currentActive === editor) {
+ return;
+ }
+ this.#uiManager.setActiveEditor(editor);
+ }
+ enableTextSelection() {
+ if (this.#textLayer?.div) {
+ this.#textLayer.div.addEventListener("pointerdown", this.#boundTextLayerPointerDown);
+ this.#textLayer.div.classList.add("highlighting");
+ }
+ }
+ disableTextSelection() {
+ if (this.#textLayer?.div) {
+ this.#textLayer.div.removeEventListener("pointerdown", this.#boundTextLayerPointerDown);
+ this.#textLayer.div.classList.remove("highlighting");
+ }
+ }
+ #textLayerPointerDown(event) {
+ this.#uiManager.unselectAll();
+ if (event.target === this.#textLayer.div) {
+ const {
+ isMac
+ } = util_FeatureTest.platform;
+ if (event.button !== 0 || event.ctrlKey && isMac) {
+ return;
+ }
+ this.#textLayer.div.classList.add("free");
+ HighlightEditor.startHighlighting(this, this.#uiManager.direction === "ltr", event);
+ this.#textLayer.div.addEventListener("pointerup", () => {
+ this.#textLayer.div.classList.remove("free");
+ }, {
+ once: true
+ });
+ event.preventDefault();
+ }
+ }
+ enableClick() {
+ this.div.addEventListener("pointerdown", this.#boundPointerdown);
+ this.div.addEventListener("pointerup", this.#boundPointerup);
+ }
+ disableClick() {
+ this.div.removeEventListener("pointerdown", this.#boundPointerdown);
+ this.div.removeEventListener("pointerup", this.#boundPointerup);
+ }
+ attach(editor) {
+ this.#editors.set(editor.id, editor);
+ const {
+ annotationElementId
+ } = editor;
+ if (annotationElementId && this.#uiManager.isDeletedAnnotationElement(annotationElementId)) {
+ this.#uiManager.removeDeletedAnnotationElement(editor);
+ }
+ }
+ detach(editor) {
+ this.#editors.delete(editor.id);
+ this.#accessibilityManager?.removePointerInTextLayer(editor.contentDiv);
+ if (!this.#isDisabling && editor.annotationElementId) {
+ this.#uiManager.addDeletedAnnotationElement(editor);
+ }
+ }
+ remove(editor) {
+ this.detach(editor);
+ this.#uiManager.removeEditor(editor);
+ editor.div.remove();
+ editor.isAttachedToDOM = false;
+ if (!this.#isCleaningUp) {
+ this.addInkEditorIfNeeded(false);
+ }
+ }
+ changeParent(editor) {
+ if (editor.parent === this) {
+ return;
+ }
+ if (editor.annotationElementId) {
+ this.#uiManager.addDeletedAnnotationElement(editor.annotationElementId);
+ AnnotationEditor.deleteAnnotationElement(editor);
+ editor.annotationElementId = null;
+ }
+ this.attach(editor);
+ editor.parent?.detach(editor);
+ editor.setParent(this);
+ if (editor.div && editor.isAttachedToDOM) {
+ editor.div.remove();
+ this.div.append(editor.div);
+ }
+ }
+ add(editor) {
+ this.changeParent(editor);
+ this.#uiManager.addEditor(editor);
+ this.attach(editor);
+ if (!editor.isAttachedToDOM) {
+ const div = editor.render();
+ this.div.append(div);
+ editor.isAttachedToDOM = true;
+ }
+ editor.fixAndSetPosition();
+ editor.onceAdded();
+ this.#uiManager.addToAnnotationStorage(editor);
+ editor._reportTelemetry(editor.telemetryInitialData);
+ }
+ moveEditorInDOM(editor) {
+ if (!editor.isAttachedToDOM) {
+ return;
+ }
+ const {
+ activeElement
+ } = document;
+ if (editor.div.contains(activeElement) && !this.#editorFocusTimeoutId) {
+ editor._focusEventsAllowed = false;
+ this.#editorFocusTimeoutId = setTimeout(() => {
+ this.#editorFocusTimeoutId = null;
+ if (!editor.div.contains(document.activeElement)) {
+ editor.div.addEventListener("focusin", () => {
+ editor._focusEventsAllowed = true;
+ }, {
+ once: true
+ });
+ activeElement.focus();
+ } else {
+ editor._focusEventsAllowed = true;
+ }
+ }, 0);
+ }
+ editor._structTreeParentId = this.#accessibilityManager?.moveElementInDOM(this.div, editor.div, editor.contentDiv, true);
+ }
+ addOrRebuild(editor) {
+ if (editor.needsToBeRebuilt()) {
+ editor.parent ||= this;
+ editor.rebuild();
+ } else {
+ this.add(editor);
+ }
+ }
+ addUndoableEditor(editor) {
+ const cmd = () => editor._uiManager.rebuild(editor);
+ const undo = () => {
+ editor.remove();
+ };
+ this.addCommands({
+ cmd,
+ undo,
+ mustExec: false
+ });
+ }
+ getNextId() {
+ return this.#uiManager.getId();
+ }
+ get #currentEditorType() {
+ return AnnotationEditorLayer.#editorTypes.get(this.#uiManager.getMode());
+ }
+ #createNewEditor(params) {
+ const editorType = this.#currentEditorType;
+ return editorType ? new editorType.prototype.constructor(params) : null;
+ }
+ canCreateNewEmptyEditor() {
+ return this.#currentEditorType?.canCreateNewEmptyEditor();
+ }
+ pasteEditor(mode, params) {
+ this.#uiManager.updateToolbar(mode);
+ this.#uiManager.updateMode(mode);
+ const {
+ offsetX,
+ offsetY
+ } = this.#getCenterPoint();
+ const id = this.getNextId();
+ const editor = this.#createNewEditor({
+ parent: this,
+ id,
+ x: offsetX,
+ y: offsetY,
+ uiManager: this.#uiManager,
+ isCentered: true,
+ ...params
+ });
+ if (editor) {
+ this.add(editor);
+ }
+ }
+ deserialize(data) {
+ return AnnotationEditorLayer.#editorTypes.get(data.annotationType ?? data.annotationEditorType)?.deserialize(data, this, this.#uiManager) || null;
+ }
+ createAndAddNewEditor(event, isCentered, data = {}) {
+ const id = this.getNextId();
+ const editor = this.#createNewEditor({
+ parent: this,
+ id,
+ x: event.offsetX,
+ y: event.offsetY,
+ uiManager: this.#uiManager,
+ isCentered,
+ ...data
+ });
+ if (editor) {
+ this.add(editor);
+ }
+ return editor;
+ }
+ #getCenterPoint() {
+ const {
+ x,
+ y,
+ width,
+ height
+ } = this.div.getBoundingClientRect();
+ const tlX = Math.max(0, x);
+ const tlY = Math.max(0, y);
+ const brX = Math.min(window.innerWidth, x + width);
+ const brY = Math.min(window.innerHeight, y + height);
+ const centerX = (tlX + brX) / 2 - x;
+ const centerY = (tlY + brY) / 2 - y;
+ const [offsetX, offsetY] = this.viewport.rotation % 180 === 0 ? [centerX, centerY] : [centerY, centerX];
+ return {
+ offsetX,
+ offsetY
+ };
+ }
+ addNewEditor() {
+ this.createAndAddNewEditor(this.#getCenterPoint(), true);
+ }
+ setSelected(editor) {
+ this.#uiManager.setSelected(editor);
+ }
+ toggleSelected(editor) {
+ this.#uiManager.toggleSelected(editor);
+ }
+ isSelected(editor) {
+ return this.#uiManager.isSelected(editor);
+ }
+ unselect(editor) {
+ this.#uiManager.unselect(editor);
+ }
+ pointerup(event) {
+ const {
+ isMac
+ } = util_FeatureTest.platform;
+ if (event.button !== 0 || event.ctrlKey && isMac) {
+ return;
+ }
+ if (event.target !== this.div) {
+ return;
+ }
+ if (!this.#hadPointerDown) {
+ return;
+ }
+ this.#hadPointerDown = false;
+ if (!this.#allowClick) {
+ this.#allowClick = true;
+ return;
+ }
+ if (this.#uiManager.getMode() === AnnotationEditorType.STAMP) {
+ this.#uiManager.unselectAll();
+ return;
+ }
+ this.createAndAddNewEditor(event, false);
+ }
+ pointerdown(event) {
+ if (this.#uiManager.getMode() === AnnotationEditorType.HIGHLIGHT) {
+ this.enableTextSelection();
+ }
+ if (this.#hadPointerDown) {
+ this.#hadPointerDown = false;
+ return;
+ }
+ const {
+ isMac
+ } = util_FeatureTest.platform;
+ if (event.button !== 0 || event.ctrlKey && isMac) {
+ return;
+ }
+ if (event.target !== this.div) {
+ return;
+ }
+ this.#hadPointerDown = true;
+ const editor = this.#uiManager.getActive();
+ this.#allowClick = !editor || editor.isEmpty();
+ }
+ findNewParent(editor, x, y) {
+ const layer = this.#uiManager.findParent(x, y);
+ if (layer === null || layer === this) {
+ return false;
+ }
+ layer.changeParent(editor);
+ return true;
+ }
+ destroy() {
+ if (this.#uiManager.getActive()?.parent === this) {
+ this.#uiManager.commitOrRemove();
+ this.#uiManager.setActiveEditor(null);
+ }
+ if (this.#editorFocusTimeoutId) {
+ clearTimeout(this.#editorFocusTimeoutId);
+ this.#editorFocusTimeoutId = null;
+ }
+ for (const editor of this.#editors.values()) {
+ this.#accessibilityManager?.removePointerInTextLayer(editor.contentDiv);
+ editor.setParent(null);
+ editor.isAttachedToDOM = false;
+ editor.div.remove();
+ }
+ this.div = null;
+ this.#editors.clear();
+ this.#uiManager.removeLayer(this);
+ }
+ #cleanup() {
+ this.#isCleaningUp = true;
+ for (const editor of this.#editors.values()) {
+ if (editor.isEmpty()) {
+ editor.remove();
+ }
+ }
+ this.#isCleaningUp = false;
+ }
+ render({
+ viewport
+ }) {
+ this.viewport = viewport;
+ setLayerDimensions(this.div, viewport);
+ for (const editor of this.#uiManager.getEditors(this.pageIndex)) {
+ this.add(editor);
+ }
+ this.updateMode();
+ }
+ update({
+ viewport
+ }) {
+ this.#uiManager.commitOrRemove();
+ const oldRotation = this.viewport.rotation;
+ const rotation = viewport.rotation;
+ this.viewport = viewport;
+ setLayerDimensions(this.div, {
+ rotation
+ });
+ if (oldRotation !== rotation) {
+ for (const editor of this.#editors.values()) {
+ editor.rotate(rotation);
+ }
+ }
+ this.updateMode();
+ }
+ get pageDimensions() {
+ const {
+ pageWidth,
+ pageHeight
+ } = this.viewport.rawDims;
+ return [pageWidth, pageHeight];
+ }
+ get scale() {
+ return this.#uiManager.viewParameters.realScale;
+ }
+}
+
+;// CONCATENATED MODULE: ./src/display/draw_layer.js
+
+
+class DrawLayer {
+ #parent = null;
+ #id = 0;
+ #mapping = new Map();
+ #toUpdate = new Map();
+ constructor({
+ pageIndex
+ }) {
+ this.pageIndex = pageIndex;
+ }
+ setParent(parent) {
+ if (!this.#parent) {
+ this.#parent = parent;
+ return;
+ }
+ if (this.#parent !== parent) {
+ if (this.#mapping.size > 0) {
+ for (const root of this.#mapping.values()) {
+ root.remove();
+ parent.append(root);
+ }
+ }
+ this.#parent = parent;
+ }
+ }
+ static get _svgFactory() {
+ return shadow(this, "_svgFactory", new DOMSVGFactory());
+ }
+ static #setBox(element, {
+ x = 0,
+ y = 0,
+ width = 1,
+ height = 1
+ } = {}) {
+ const {
+ style
+ } = element;
+ style.top = `${100 * y}%`;
+ style.left = `${100 * x}%`;
+ style.width = `${100 * width}%`;
+ style.height = `${100 * height}%`;
+ }
+ #createSVG(box) {
+ const svg = DrawLayer._svgFactory.create(1, 1, true);
+ this.#parent.append(svg);
+ DrawLayer.#setBox(svg, box);
+ return svg;
+ }
+ #createClipPath(defs, pathId) {
+ const clipPath = DrawLayer._svgFactory.createElement("clipPath");
+ defs.append(clipPath);
+ const clipPathId = `clip_${pathId}`;
+ clipPath.setAttribute("id", clipPathId);
+ clipPath.setAttribute("clipPathUnits", "objectBoundingBox");
+ const clipPathUse = DrawLayer._svgFactory.createElement("use");
+ clipPath.append(clipPathUse);
+ clipPathUse.setAttribute("href", `#${pathId}`);
+ clipPathUse.classList.add("clip");
+ return clipPathId;
+ }
+ highlight(outlines, color, opacity, isPathUpdatable = false) {
+ const id = this.#id++;
+ const root = this.#createSVG(outlines.box);
+ root.classList.add("highlight");
+ if (outlines.free) {
+ root.classList.add("free");
+ }
+ const defs = DrawLayer._svgFactory.createElement("defs");
+ root.append(defs);
+ const path = DrawLayer._svgFactory.createElement("path");
+ defs.append(path);
+ const pathId = `path_p${this.pageIndex}_${id}`;
+ path.setAttribute("id", pathId);
+ path.setAttribute("d", outlines.toSVGPath());
+ if (isPathUpdatable) {
+ this.#toUpdate.set(id, path);
+ }
+ const clipPathId = this.#createClipPath(defs, pathId);
+ const use = DrawLayer._svgFactory.createElement("use");
+ root.append(use);
+ root.setAttribute("fill", color);
+ root.setAttribute("fill-opacity", opacity);
+ use.setAttribute("href", `#${pathId}`);
+ this.#mapping.set(id, root);
+ return {
+ id,
+ clipPathId: `url(#${clipPathId})`
+ };
+ }
+ highlightOutline(outlines) {
+ const id = this.#id++;
+ const root = this.#createSVG(outlines.box);
+ root.classList.add("highlightOutline");
+ const defs = DrawLayer._svgFactory.createElement("defs");
+ root.append(defs);
+ const path = DrawLayer._svgFactory.createElement("path");
+ defs.append(path);
+ const pathId = `path_p${this.pageIndex}_${id}`;
+ path.setAttribute("id", pathId);
+ path.setAttribute("d", outlines.toSVGPath());
+ path.setAttribute("vector-effect", "non-scaling-stroke");
+ let maskId;
+ if (outlines.free) {
+ root.classList.add("free");
+ const mask = DrawLayer._svgFactory.createElement("mask");
+ defs.append(mask);
+ maskId = `mask_p${this.pageIndex}_${id}`;
+ mask.setAttribute("id", maskId);
+ mask.setAttribute("maskUnits", "objectBoundingBox");
+ const rect = DrawLayer._svgFactory.createElement("rect");
+ mask.append(rect);
+ rect.setAttribute("width", "1");
+ rect.setAttribute("height", "1");
+ rect.setAttribute("fill", "white");
+ const use = DrawLayer._svgFactory.createElement("use");
+ mask.append(use);
+ use.setAttribute("href", `#${pathId}`);
+ use.setAttribute("stroke", "none");
+ use.setAttribute("fill", "black");
+ use.setAttribute("fill-rule", "nonzero");
+ use.classList.add("mask");
+ }
+ const use1 = DrawLayer._svgFactory.createElement("use");
+ root.append(use1);
+ use1.setAttribute("href", `#${pathId}`);
+ if (maskId) {
+ use1.setAttribute("mask", `url(#${maskId})`);
+ }
+ const use2 = use1.cloneNode();
+ root.append(use2);
+ use1.classList.add("mainOutline");
+ use2.classList.add("secondaryOutline");
+ this.#mapping.set(id, root);
+ return id;
+ }
+ finalizeLine(id, line) {
+ const path = this.#toUpdate.get(id);
+ this.#toUpdate.delete(id);
+ this.updateBox(id, line.box);
+ path.setAttribute("d", line.toSVGPath());
+ }
+ updateLine(id, line) {
+ const root = this.#mapping.get(id);
+ const defs = root.firstChild;
+ const path = defs.firstChild;
+ path.setAttribute("d", line.toSVGPath());
+ }
+ removeFreeHighlight(id) {
+ this.remove(id);
+ this.#toUpdate.delete(id);
+ }
+ updatePath(id, line) {
+ this.#toUpdate.get(id).setAttribute("d", line.toSVGPath());
+ }
+ updateBox(id, box) {
+ DrawLayer.#setBox(this.#mapping.get(id), box);
+ }
+ rotate(id, angle) {
+ this.#mapping.get(id).setAttribute("data-main-rotation", angle);
+ }
+ changeColor(id, color) {
+ this.#mapping.get(id).setAttribute("fill", color);
+ }
+ changeOpacity(id, opacity) {
+ this.#mapping.get(id).setAttribute("fill-opacity", opacity);
+ }
+ addClass(id, className) {
+ this.#mapping.get(id).classList.add(className);
+ }
+ removeClass(id, className) {
+ this.#mapping.get(id).classList.remove(className);
+ }
+ remove(id) {
+ if (this.#parent === null) {
+ return;
+ }
+ this.#mapping.get(id).remove();
+ this.#mapping.delete(id);
+ }
+ destroy() {
+ this.#parent = null;
+ for (const root of this.#mapping.values()) {
+ root.remove();
+ }
+ this.#mapping.clear();
+ }
+}
+
+;// CONCATENATED MODULE: ./src/pdf.js
+
+
+
+
+
+
+
+
+
+
+
+
+const pdfjsVersion = "4.1.249";
+const pdfjsBuild = "d07f37f44";
+
+var __webpack_exports__AbortException = __webpack_exports__.AbortException;
+var __webpack_exports__AnnotationEditorLayer = __webpack_exports__.AnnotationEditorLayer;
+var __webpack_exports__AnnotationEditorParamsType = __webpack_exports__.AnnotationEditorParamsType;
+var __webpack_exports__AnnotationEditorType = __webpack_exports__.AnnotationEditorType;
+var __webpack_exports__AnnotationEditorUIManager = __webpack_exports__.AnnotationEditorUIManager;
+var __webpack_exports__AnnotationLayer = __webpack_exports__.AnnotationLayer;
+var __webpack_exports__AnnotationMode = __webpack_exports__.AnnotationMode;
+var __webpack_exports__CMapCompressionType = __webpack_exports__.CMapCompressionType;
+var __webpack_exports__ColorPicker = __webpack_exports__.ColorPicker;
+var __webpack_exports__DOMSVGFactory = __webpack_exports__.DOMSVGFactory;
+var __webpack_exports__DrawLayer = __webpack_exports__.DrawLayer;
+var __webpack_exports__FeatureTest = __webpack_exports__.FeatureTest;
+var __webpack_exports__GlobalWorkerOptions = __webpack_exports__.GlobalWorkerOptions;
+var __webpack_exports__ImageKind = __webpack_exports__.ImageKind;
+var __webpack_exports__InvalidPDFException = __webpack_exports__.InvalidPDFException;
+var __webpack_exports__MissingPDFException = __webpack_exports__.MissingPDFException;
+var __webpack_exports__OPS = __webpack_exports__.OPS;
+var __webpack_exports__Outliner = __webpack_exports__.Outliner;
+var __webpack_exports__PDFDataRangeTransport = __webpack_exports__.PDFDataRangeTransport;
+var __webpack_exports__PDFDateString = __webpack_exports__.PDFDateString;
+var __webpack_exports__PDFWorker = __webpack_exports__.PDFWorker;
+var __webpack_exports__PasswordResponses = __webpack_exports__.PasswordResponses;
+var __webpack_exports__PermissionFlag = __webpack_exports__.PermissionFlag;
+var __webpack_exports__PixelsPerInch = __webpack_exports__.PixelsPerInch;
+var __webpack_exports__PromiseCapability = __webpack_exports__.PromiseCapability;
+var __webpack_exports__RenderingCancelledException = __webpack_exports__.RenderingCancelledException;
+var __webpack_exports__UnexpectedResponseException = __webpack_exports__.UnexpectedResponseException;
+var __webpack_exports__Util = __webpack_exports__.Util;
+var __webpack_exports__VerbosityLevel = __webpack_exports__.VerbosityLevel;
+var __webpack_exports__XfaLayer = __webpack_exports__.XfaLayer;
+var __webpack_exports__build = __webpack_exports__.build;
+var __webpack_exports__createValidAbsoluteUrl = __webpack_exports__.createValidAbsoluteUrl;
+var __webpack_exports__fetchData = __webpack_exports__.fetchData;
+var __webpack_exports__getDocument = __webpack_exports__.getDocument;
+var __webpack_exports__getFilenameFromUrl = __webpack_exports__.getFilenameFromUrl;
+var __webpack_exports__getPdfFilenameFromUrl = __webpack_exports__.getPdfFilenameFromUrl;
+var __webpack_exports__getXfaPageViewport = __webpack_exports__.getXfaPageViewport;
+var __webpack_exports__isDataScheme = __webpack_exports__.isDataScheme;
+var __webpack_exports__isPdfFile = __webpack_exports__.isPdfFile;
+var __webpack_exports__noContextMenu = __webpack_exports__.noContextMenu;
+var __webpack_exports__normalizeUnicode = __webpack_exports__.normalizeUnicode;
+var __webpack_exports__renderTextLayer = __webpack_exports__.renderTextLayer;
+var __webpack_exports__setLayerDimensions = __webpack_exports__.setLayerDimensions;
+var __webpack_exports__shadow = __webpack_exports__.shadow;
+var __webpack_exports__updateTextLayer = __webpack_exports__.updateTextLayer;
+var __webpack_exports__version = __webpack_exports__.version;
+export { __webpack_exports__AbortException as AbortException, __webpack_exports__AnnotationEditorLayer as AnnotationEditorLayer, __webpack_exports__AnnotationEditorParamsType as AnnotationEditorParamsType, __webpack_exports__AnnotationEditorType as AnnotationEditorType, __webpack_exports__AnnotationEditorUIManager as AnnotationEditorUIManager, __webpack_exports__AnnotationLayer as AnnotationLayer, __webpack_exports__AnnotationMode as AnnotationMode, __webpack_exports__CMapCompressionType as CMapCompressionType, __webpack_exports__ColorPicker as ColorPicker, __webpack_exports__DOMSVGFactory as DOMSVGFactory, __webpack_exports__DrawLayer as DrawLayer, __webpack_exports__FeatureTest as FeatureTest, __webpack_exports__GlobalWorkerOptions as GlobalWorkerOptions, __webpack_exports__ImageKind as ImageKind, __webpack_exports__InvalidPDFException as InvalidPDFException, __webpack_exports__MissingPDFException as MissingPDFException, __webpack_exports__OPS as OPS, __webpack_exports__Outliner as Outliner, __webpack_exports__PDFDataRangeTransport as PDFDataRangeTransport, __webpack_exports__PDFDateString as PDFDateString, __webpack_exports__PDFWorker as PDFWorker, __webpack_exports__PasswordResponses as PasswordResponses, __webpack_exports__PermissionFlag as PermissionFlag, __webpack_exports__PixelsPerInch as PixelsPerInch, __webpack_exports__PromiseCapability as PromiseCapability, __webpack_exports__RenderingCancelledException as RenderingCancelledException, __webpack_exports__UnexpectedResponseException as UnexpectedResponseException, __webpack_exports__Util as Util, __webpack_exports__VerbosityLevel as VerbosityLevel, __webpack_exports__XfaLayer as XfaLayer, __webpack_exports__build as build, __webpack_exports__createValidAbsoluteUrl as createValidAbsoluteUrl, __webpack_exports__fetchData as fetchData, __webpack_exports__getDocument as getDocument, __webpack_exports__getFilenameFromUrl as getFilenameFromUrl, __webpack_exports__getPdfFilenameFromUrl as getPdfFilenameFromUrl, __webpack_exports__getXfaPageViewport as getXfaPageViewport, __webpack_exports__isDataScheme as isDataScheme, __webpack_exports__isPdfFile as isPdfFile, __webpack_exports__noContextMenu as noContextMenu, __webpack_exports__normalizeUnicode as normalizeUnicode, __webpack_exports__renderTextLayer as renderTextLayer, __webpack_exports__setLayerDimensions as setLayerDimensions, __webpack_exports__shadow as shadow, __webpack_exports__updateTextLayer as updateTextLayer, __webpack_exports__version as version };
diff --git a/toolkit/components/pdfjs/content/build/pdf.sandbox.external.sys.mjs b/toolkit/components/pdfjs/content/build/pdf.sandbox.external.sys.mjs
new file mode 100644
index 0000000000..3dfe4eb2e1
--- /dev/null
+++ b/toolkit/components/pdfjs/content/build/pdf.sandbox.external.sys.mjs
@@ -0,0 +1,127 @@
+/* Copyright 2023 Mozilla Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+export class SandboxSupportBase {
+ constructor(win) {
+ this.win = win;
+ this.timeoutIds = new Map();
+ this.commFun = null;
+ }
+ destroy() {
+ this.commFun = null;
+ for (const id of this.timeoutIds.values()) {
+ this.win.clearTimeout(id);
+ }
+ this.timeoutIds = null;
+ }
+ exportValueToSandbox(val) {
+ throw new Error("Not implemented");
+ }
+ importValueFromSandbox(val) {
+ throw new Error("Not implemented");
+ }
+ createErrorForSandbox(errorMessage) {
+ throw new Error("Not implemented");
+ }
+ callSandboxFunction(name, args) {
+ try {
+ args = this.exportValueToSandbox(args);
+ this.commFun(name, args);
+ } catch (e) {
+ this.win.console.error(e);
+ }
+ }
+ createSandboxExternals() {
+ const externals = {
+ setTimeout: (callbackId, nMilliseconds) => {
+ if (typeof callbackId !== "number" || typeof nMilliseconds !== "number") {
+ return;
+ }
+ if (callbackId === 0) {
+ this.win.clearTimeout(this.timeoutIds.get(callbackId));
+ }
+ const id = this.win.setTimeout(() => {
+ this.timeoutIds.delete(callbackId);
+ this.callSandboxFunction("timeoutCb", {
+ callbackId,
+ interval: false
+ });
+ }, nMilliseconds);
+ this.timeoutIds.set(callbackId, id);
+ },
+ clearTimeout: callbackId => {
+ this.win.clearTimeout(this.timeoutIds.get(callbackId));
+ this.timeoutIds.delete(callbackId);
+ },
+ setInterval: (callbackId, nMilliseconds) => {
+ if (typeof callbackId !== "number" || typeof nMilliseconds !== "number") {
+ return;
+ }
+ const id = this.win.setInterval(() => {
+ this.callSandboxFunction("timeoutCb", {
+ callbackId,
+ interval: true
+ });
+ }, nMilliseconds);
+ this.timeoutIds.set(callbackId, id);
+ },
+ clearInterval: callbackId => {
+ this.win.clearInterval(this.timeoutIds.get(callbackId));
+ this.timeoutIds.delete(callbackId);
+ },
+ alert: cMsg => {
+ if (typeof cMsg !== "string") {
+ return;
+ }
+ this.win.alert(cMsg);
+ },
+ confirm: cMsg => {
+ if (typeof cMsg !== "string") {
+ return false;
+ }
+ return this.win.confirm(cMsg);
+ },
+ prompt: (cQuestion, cDefault) => {
+ if (typeof cQuestion !== "string" || typeof cDefault !== "string") {
+ return null;
+ }
+ return this.win.prompt(cQuestion, cDefault);
+ },
+ parseURL: cUrl => {
+ const url = new this.win.URL(cUrl);
+ const props = ["hash", "host", "hostname", "href", "origin", "password", "pathname", "port", "protocol", "search", "searchParams", "username"];
+ return Object.fromEntries(props.map(name => [name, url[name].toString()]));
+ },
+ send: data => {
+ if (!data) {
+ return;
+ }
+ const event = new this.win.CustomEvent("updatefromsandbox", {
+ detail: this.importValueFromSandbox(data)
+ });
+ this.win.dispatchEvent(event);
+ }
+ };
+ Object.setPrototypeOf(externals, null);
+ return (name, args) => {
+ try {
+ const result = externals[name](...args);
+ return this.exportValueToSandbox(result);
+ } catch (error) {
+ throw this.createErrorForSandbox(error?.toString() ?? "");
+ }
+ };
+ }
+} \ No newline at end of file
diff --git a/toolkit/components/pdfjs/content/build/pdf.scripting.mjs b/toolkit/components/pdfjs/content/build/pdf.scripting.mjs
new file mode 100644
index 0000000000..d667676f1a
--- /dev/null
+++ b/toolkit/components/pdfjs/content/build/pdf.scripting.mjs
@@ -0,0 +1,3964 @@
+/**
+ * @licstart The following is the entire license notice for the
+ * JavaScript code in this page
+ *
+ * Copyright 2023 Mozilla Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * @licend The above is the entire license notice for the
+ * JavaScript code in this page
+ */
+
+var __webpack_exports__ = {};
+
+;// CONCATENATED MODULE: ./src/scripting_api/constants.js
+const Border = Object.freeze({
+ s: "solid",
+ d: "dashed",
+ b: "beveled",
+ i: "inset",
+ u: "underline"
+});
+const Cursor = Object.freeze({
+ visible: 0,
+ hidden: 1,
+ delay: 2
+});
+const Display = Object.freeze({
+ visible: 0,
+ hidden: 1,
+ noPrint: 2,
+ noView: 3
+});
+const Font = Object.freeze({
+ Times: "Times-Roman",
+ TimesB: "Times-Bold",
+ TimesI: "Times-Italic",
+ TimesBI: "Times-BoldItalic",
+ Helv: "Helvetica",
+ HelvB: "Helvetica-Bold",
+ HelvI: "Helvetica-Oblique",
+ HelvBI: "Helvetica-BoldOblique",
+ Cour: "Courier",
+ CourB: "Courier-Bold",
+ CourI: "Courier-Oblique",
+ CourBI: "Courier-BoldOblique",
+ Symbol: "Symbol",
+ ZapfD: "ZapfDingbats",
+ KaGo: "HeiseiKakuGo-W5-UniJIS-UCS2-H",
+ KaMi: "HeiseiMin-W3-UniJIS-UCS2-H"
+});
+const Highlight = Object.freeze({
+ n: "none",
+ i: "invert",
+ p: "push",
+ o: "outline"
+});
+const Position = Object.freeze({
+ textOnly: 0,
+ iconOnly: 1,
+ iconTextV: 2,
+ textIconV: 3,
+ iconTextH: 4,
+ textIconH: 5,
+ overlay: 6
+});
+const ScaleHow = Object.freeze({
+ proportional: 0,
+ anamorphic: 1
+});
+const ScaleWhen = Object.freeze({
+ always: 0,
+ never: 1,
+ tooBig: 2,
+ tooSmall: 3
+});
+const Style = Object.freeze({
+ ch: "check",
+ cr: "cross",
+ di: "diamond",
+ ci: "circle",
+ st: "star",
+ sq: "square"
+});
+const Trans = Object.freeze({
+ blindsH: "BlindsHorizontal",
+ blindsV: "BlindsVertical",
+ boxI: "BoxIn",
+ boxO: "BoxOut",
+ dissolve: "Dissolve",
+ glitterD: "GlitterDown",
+ glitterR: "GlitterRight",
+ glitterRD: "GlitterRightDown",
+ random: "Random",
+ replace: "Replace",
+ splitHI: "SplitHorizontalIn",
+ splitHO: "SplitHorizontalOut",
+ splitVI: "SplitVerticalIn",
+ splitVO: "SplitVerticalOut",
+ wipeD: "WipeDown",
+ wipeL: "WipeLeft",
+ wipeR: "WipeRight",
+ wipeU: "WipeUp"
+});
+const ZoomType = Object.freeze({
+ none: "NoVary",
+ fitP: "FitPage",
+ fitW: "FitWidth",
+ fitH: "FitHeight",
+ fitV: "FitVisibleWidth",
+ pref: "Preferred",
+ refW: "ReflowWidth"
+});
+const GlobalConstants = Object.freeze({
+ IDS_GREATER_THAN: "Invalid value: must be greater than or equal to % s.",
+ IDS_GT_AND_LT: "Invalid value: must be greater than or equal to % s " + "and less than or equal to % s.",
+ IDS_LESS_THAN: "Invalid value: must be less than or equal to % s.",
+ IDS_INVALID_MONTH: "** Invalid **",
+ IDS_INVALID_DATE: "Invalid date / time: please ensure that the date / time exists. Field",
+ IDS_INVALID_DATE2: " should match format ",
+ IDS_INVALID_VALUE: "The value entered does not match the format of the field",
+ IDS_AM: "am",
+ IDS_PM: "pm",
+ IDS_MONTH_INFO: "January[1] February[2] March[3] April[4] May[5] " + "June[6] July[7] August[8] September[9] October[10] " + "November[11] December[12] Sept[9] Jan[1] Feb[2] Mar[3] " + "Apr[4] Jun[6] Jul[7] Aug[8] Sep[9] Oct[10] Nov[11] Dec[12]",
+ IDS_STARTUP_CONSOLE_MSG: "** ^ _ ^ **",
+ RE_NUMBER_ENTRY_DOT_SEP: ["[+-]?\\d*\\.?\\d*"],
+ RE_NUMBER_COMMIT_DOT_SEP: ["[+-]?\\d+(\\.\\d+)?", "[+-]?\\.\\d+", "[+-]?\\d+\\."],
+ RE_NUMBER_ENTRY_COMMA_SEP: ["[+-]?\\d*,?\\d*"],
+ RE_NUMBER_COMMIT_COMMA_SEP: ["[+-]?\\d+([.,]\\d+)?", "[+-]?[.,]\\d+", "[+-]?\\d+[.,]"],
+ RE_ZIP_ENTRY: ["\\d{0,5}"],
+ RE_ZIP_COMMIT: ["\\d{5}"],
+ RE_ZIP4_ENTRY: ["\\d{0,5}(\\.|[- ])?\\d{0,4}"],
+ RE_ZIP4_COMMIT: ["\\d{5}(\\.|[- ])?\\d{4}"],
+ RE_PHONE_ENTRY: ["\\d{0,3}(\\.|[- ])?\\d{0,3}(\\.|[- ])?\\d{0,4}", "\\(\\d{0,3}", "\\(\\d{0,3}\\)(\\.|[- ])?\\d{0,3}(\\.|[- ])?\\d{0,4}", "\\(\\d{0,3}(\\.|[- ])?\\d{0,3}(\\.|[- ])?\\d{0,4}", "\\d{0,3}\\)(\\.|[- ])?\\d{0,3}(\\.|[- ])?\\d{0,4}", "011(\\.|[- \\d])*"],
+ RE_PHONE_COMMIT: ["\\d{3}(\\.|[- ])?\\d{4}", "\\d{3}(\\.|[- ])?\\d{3}(\\.|[- ])?\\d{4}", "\\(\\d{3}\\)(\\.|[- ])?\\d{3}(\\.|[- ])?\\d{4}", "011(\\.|[- \\d])*"],
+ RE_SSN_ENTRY: ["\\d{0,3}(\\.|[- ])?\\d{0,2}(\\.|[- ])?\\d{0,4}"],
+ RE_SSN_COMMIT: ["\\d{3}(\\.|[- ])?\\d{2}(\\.|[- ])?\\d{4}"]
+});
+
+;// CONCATENATED MODULE: ./src/scripting_api/common.js
+const FieldType = {
+ none: 0,
+ number: 1,
+ percent: 2,
+ date: 3,
+ time: 4
+};
+function createActionsMap(actions) {
+ const actionsMap = new Map();
+ if (actions) {
+ for (const [eventType, actionsForEvent] of Object.entries(actions)) {
+ actionsMap.set(eventType, actionsForEvent);
+ }
+ }
+ return actionsMap;
+}
+function getFieldType(actions) {
+ let format = actions.get("Format");
+ if (!format) {
+ return FieldType.none;
+ }
+ format = format[0];
+ format = format.trim();
+ if (format.startsWith("AFNumber_")) {
+ return FieldType.number;
+ }
+ if (format.startsWith("AFPercent_")) {
+ return FieldType.percent;
+ }
+ if (format.startsWith("AFDate_")) {
+ return FieldType.date;
+ }
+ if (format.startsWith("AFTime_")) {
+ return FieldType.time;
+ }
+ return FieldType.none;
+}
+
+;// CONCATENATED MODULE: ./src/shared/scripting_utils.js
+function makeColorComp(n) {
+ return Math.floor(Math.max(0, Math.min(1, n)) * 255).toString(16).padStart(2, "0");
+}
+function scaleAndClamp(x) {
+ return Math.max(0, Math.min(255, 255 * x));
+}
+class ColorConverters {
+ static CMYK_G([c, y, m, k]) {
+ return ["G", 1 - Math.min(1, 0.3 * c + 0.59 * m + 0.11 * y + k)];
+ }
+ static G_CMYK([g]) {
+ return ["CMYK", 0, 0, 0, 1 - g];
+ }
+ static G_RGB([g]) {
+ return ["RGB", g, g, g];
+ }
+ static G_rgb([g]) {
+ g = scaleAndClamp(g);
+ return [g, g, g];
+ }
+ static G_HTML([g]) {
+ const G = makeColorComp(g);
+ return `#${G}${G}${G}`;
+ }
+ static RGB_G([r, g, b]) {
+ return ["G", 0.3 * r + 0.59 * g + 0.11 * b];
+ }
+ static RGB_rgb(color) {
+ return color.map(scaleAndClamp);
+ }
+ static RGB_HTML(color) {
+ return `#${color.map(makeColorComp).join("")}`;
+ }
+ static T_HTML() {
+ return "#00000000";
+ }
+ static T_rgb() {
+ return [null];
+ }
+ static CMYK_RGB([c, y, m, k]) {
+ return ["RGB", 1 - Math.min(1, c + k), 1 - Math.min(1, m + k), 1 - Math.min(1, y + k)];
+ }
+ static CMYK_rgb([c, y, m, k]) {
+ return [scaleAndClamp(1 - Math.min(1, c + k)), scaleAndClamp(1 - Math.min(1, m + k)), scaleAndClamp(1 - Math.min(1, y + k))];
+ }
+ static CMYK_HTML(components) {
+ const rgb = this.CMYK_RGB(components).slice(1);
+ return this.RGB_HTML(rgb);
+ }
+ static RGB_CMYK([r, g, b]) {
+ const c = 1 - r;
+ const m = 1 - g;
+ const y = 1 - b;
+ const k = Math.min(c, m, y);
+ return ["CMYK", c, m, y, k];
+ }
+}
+
+;// CONCATENATED MODULE: ./src/scripting_api/pdf_object.js
+class PDFObject {
+ constructor(data) {
+ this._expandos = Object.create(null);
+ this._send = data.send || null;
+ this._id = data.id || null;
+ }
+}
+
+;// CONCATENATED MODULE: ./src/scripting_api/color.js
+
+
+class Color extends PDFObject {
+ constructor() {
+ super({});
+ this.transparent = ["T"];
+ this.black = ["G", 0];
+ this.white = ["G", 1];
+ this.red = ["RGB", 1, 0, 0];
+ this.green = ["RGB", 0, 1, 0];
+ this.blue = ["RGB", 0, 0, 1];
+ this.cyan = ["CMYK", 1, 0, 0, 0];
+ this.magenta = ["CMYK", 0, 1, 0, 0];
+ this.yellow = ["CMYK", 0, 0, 1, 0];
+ this.dkGray = ["G", 0.25];
+ this.gray = ["G", 0.5];
+ this.ltGray = ["G", 0.75];
+ }
+ static _isValidSpace(cColorSpace) {
+ return typeof cColorSpace === "string" && (cColorSpace === "T" || cColorSpace === "G" || cColorSpace === "RGB" || cColorSpace === "CMYK");
+ }
+ static _isValidColor(colorArray) {
+ if (!Array.isArray(colorArray) || colorArray.length === 0) {
+ return false;
+ }
+ const space = colorArray[0];
+ if (!Color._isValidSpace(space)) {
+ return false;
+ }
+ switch (space) {
+ case "T":
+ if (colorArray.length !== 1) {
+ return false;
+ }
+ break;
+ case "G":
+ if (colorArray.length !== 2) {
+ return false;
+ }
+ break;
+ case "RGB":
+ if (colorArray.length !== 4) {
+ return false;
+ }
+ break;
+ case "CMYK":
+ if (colorArray.length !== 5) {
+ return false;
+ }
+ break;
+ default:
+ return false;
+ }
+ return colorArray.slice(1).every(c => typeof c === "number" && c >= 0 && c <= 1);
+ }
+ static _getCorrectColor(colorArray) {
+ return Color._isValidColor(colorArray) ? colorArray : ["G", 0];
+ }
+ convert(colorArray, cColorSpace) {
+ if (!Color._isValidSpace(cColorSpace)) {
+ return this.black;
+ }
+ if (cColorSpace === "T") {
+ return ["T"];
+ }
+ colorArray = Color._getCorrectColor(colorArray);
+ if (colorArray[0] === cColorSpace) {
+ return colorArray;
+ }
+ if (colorArray[0] === "T") {
+ return this.convert(this.black, cColorSpace);
+ }
+ return ColorConverters[`${colorArray[0]}_${cColorSpace}`](colorArray.slice(1));
+ }
+ equal(colorArray1, colorArray2) {
+ colorArray1 = Color._getCorrectColor(colorArray1);
+ colorArray2 = Color._getCorrectColor(colorArray2);
+ if (colorArray1[0] === "T" || colorArray2[0] === "T") {
+ return colorArray1[0] === "T" && colorArray2[0] === "T";
+ }
+ if (colorArray1[0] !== colorArray2[0]) {
+ colorArray2 = this.convert(colorArray2, colorArray1[0]);
+ }
+ return colorArray1.slice(1).every((c, i) => c === colorArray2[i + 1]);
+ }
+}
+
+;// CONCATENATED MODULE: ./src/scripting_api/field.js
+
+
+
+class Field extends PDFObject {
+ constructor(data) {
+ super(data);
+ this.alignment = data.alignment || "left";
+ this.borderStyle = data.borderStyle || "";
+ this.buttonAlignX = data.buttonAlignX || 50;
+ this.buttonAlignY = data.buttonAlignY || 50;
+ this.buttonFitBounds = data.buttonFitBounds;
+ this.buttonPosition = data.buttonPosition;
+ this.buttonScaleHow = data.buttonScaleHow;
+ this.ButtonScaleWhen = data.buttonScaleWhen;
+ this.calcOrderIndex = data.calcOrderIndex;
+ this.comb = data.comb;
+ this.commitOnSelChange = data.commitOnSelChange;
+ this.currentValueIndices = data.currentValueIndices;
+ this.defaultStyle = data.defaultStyle;
+ this.defaultValue = data.defaultValue;
+ this.doNotScroll = data.doNotScroll;
+ this.doNotSpellCheck = data.doNotSpellCheck;
+ this.delay = data.delay;
+ this.display = data.display;
+ this.doc = data.doc.wrapped;
+ this.editable = data.editable;
+ this.exportValues = data.exportValues;
+ this.fileSelect = data.fileSelect;
+ this.hidden = data.hidden;
+ this.highlight = data.highlight;
+ this.lineWidth = data.lineWidth;
+ this.multiline = data.multiline;
+ this.multipleSelection = !!data.multipleSelection;
+ this.name = data.name;
+ this.password = data.password;
+ this.print = data.print;
+ this.radiosInUnison = data.radiosInUnison;
+ this.readonly = data.readonly;
+ this.rect = data.rect;
+ this.required = data.required;
+ this.richText = data.richText;
+ this.richValue = data.richValue;
+ this.style = data.style;
+ this.submitName = data.submitName;
+ this.textFont = data.textFont;
+ this.textSize = data.textSize;
+ this.type = data.type;
+ this.userName = data.userName;
+ this._actions = createActionsMap(data.actions);
+ this._browseForFileToSubmit = data.browseForFileToSubmit || null;
+ this._buttonCaption = null;
+ this._buttonIcon = null;
+ this._charLimit = data.charLimit;
+ this._children = null;
+ this._currentValueIndices = data.currentValueIndices || 0;
+ this._document = data.doc;
+ this._fieldPath = data.fieldPath;
+ this._fillColor = data.fillColor || ["T"];
+ this._isChoice = Array.isArray(data.items);
+ this._items = data.items || [];
+ this._hasValue = data.hasOwnProperty("value");
+ this._page = data.page || 0;
+ this._strokeColor = data.strokeColor || ["G", 0];
+ this._textColor = data.textColor || ["G", 0];
+ this._value = null;
+ this._kidIds = data.kidIds || null;
+ this._fieldType = getFieldType(this._actions);
+ this._siblings = data.siblings || null;
+ this._rotation = data.rotation || 0;
+ this._globalEval = data.globalEval;
+ this._appObjects = data.appObjects;
+ this.value = data.value || "";
+ }
+ get currentValueIndices() {
+ if (!this._isChoice) {
+ return 0;
+ }
+ return this._currentValueIndices;
+ }
+ set currentValueIndices(indices) {
+ if (!this._isChoice) {
+ return;
+ }
+ if (!Array.isArray(indices)) {
+ indices = [indices];
+ }
+ if (!indices.every(i => typeof i === "number" && Number.isInteger(i) && i >= 0 && i < this.numItems)) {
+ return;
+ }
+ indices.sort();
+ if (this.multipleSelection) {
+ this._currentValueIndices = indices;
+ this._value = [];
+ indices.forEach(i => {
+ this._value.push(this._items[i].displayValue);
+ });
+ } else if (indices.length > 0) {
+ indices = indices.splice(1, indices.length - 1);
+ this._currentValueIndices = indices[0];
+ this._value = this._items[this._currentValueIndices];
+ }
+ this._send({
+ id: this._id,
+ indices
+ });
+ }
+ get fillColor() {
+ return this._fillColor;
+ }
+ set fillColor(color) {
+ if (Color._isValidColor(color)) {
+ this._fillColor = color;
+ }
+ }
+ get bgColor() {
+ return this.fillColor;
+ }
+ set bgColor(color) {
+ this.fillColor = color;
+ }
+ get charLimit() {
+ return this._charLimit;
+ }
+ set charLimit(limit) {
+ if (typeof limit !== "number") {
+ throw new Error("Invalid argument value");
+ }
+ this._charLimit = Math.max(0, Math.floor(limit));
+ }
+ get numItems() {
+ if (!this._isChoice) {
+ throw new Error("Not a choice widget");
+ }
+ return this._items.length;
+ }
+ set numItems(_) {
+ throw new Error("field.numItems is read-only");
+ }
+ get strokeColor() {
+ return this._strokeColor;
+ }
+ set strokeColor(color) {
+ if (Color._isValidColor(color)) {
+ this._strokeColor = color;
+ }
+ }
+ get borderColor() {
+ return this.strokeColor;
+ }
+ set borderColor(color) {
+ this.strokeColor = color;
+ }
+ get page() {
+ return this._page;
+ }
+ set page(_) {
+ throw new Error("field.page is read-only");
+ }
+ get rotation() {
+ return this._rotation;
+ }
+ set rotation(angle) {
+ angle = Math.floor(angle);
+ if (angle % 90 !== 0) {
+ throw new Error("Invalid rotation: must be a multiple of 90");
+ }
+ angle %= 360;
+ if (angle < 0) {
+ angle += 360;
+ }
+ this._rotation = angle;
+ }
+ get textColor() {
+ return this._textColor;
+ }
+ set textColor(color) {
+ if (Color._isValidColor(color)) {
+ this._textColor = color;
+ }
+ }
+ get fgColor() {
+ return this.textColor;
+ }
+ set fgColor(color) {
+ this.textColor = color;
+ }
+ get value() {
+ return this._value;
+ }
+ set value(value) {
+ if (this._isChoice) {
+ this._setChoiceValue(value);
+ return;
+ }
+ if (value === "" || typeof value !== "string" || this._fieldType >= FieldType.date) {
+ this._originalValue = undefined;
+ this._value = value;
+ return;
+ }
+ this._originalValue = value;
+ const _value = value.trim().replace(",", ".");
+ this._value = !isNaN(_value) ? parseFloat(_value) : value;
+ }
+ _getValue() {
+ return this._originalValue ?? this.value;
+ }
+ _setChoiceValue(value) {
+ if (this.multipleSelection) {
+ if (!Array.isArray(value)) {
+ value = [value];
+ }
+ const values = new Set(value);
+ if (Array.isArray(this._currentValueIndices)) {
+ this._currentValueIndices.length = 0;
+ this._value.length = 0;
+ } else {
+ this._currentValueIndices = [];
+ this._value = [];
+ }
+ this._items.forEach((item, i) => {
+ if (values.has(item.exportValue)) {
+ this._currentValueIndices.push(i);
+ this._value.push(item.exportValue);
+ }
+ });
+ } else {
+ if (Array.isArray(value)) {
+ value = value[0];
+ }
+ const index = this._items.findIndex(({
+ exportValue
+ }) => value === exportValue);
+ if (index !== -1) {
+ this._currentValueIndices = index;
+ this._value = this._items[index].exportValue;
+ }
+ }
+ }
+ get valueAsString() {
+ return (this._value ?? "").toString();
+ }
+ set valueAsString(_) {}
+ browseForFileToSubmit() {
+ if (this._browseForFileToSubmit) {
+ this._browseForFileToSubmit();
+ }
+ }
+ buttonGetCaption(nFace = 0) {
+ if (this._buttonCaption) {
+ return this._buttonCaption[nFace];
+ }
+ return "";
+ }
+ buttonGetIcon(nFace = 0) {
+ if (this._buttonIcon) {
+ return this._buttonIcon[nFace];
+ }
+ return null;
+ }
+ buttonImportIcon(cPath = null, nPave = 0) {}
+ buttonSetCaption(cCaption, nFace = 0) {
+ if (!this._buttonCaption) {
+ this._buttonCaption = ["", "", ""];
+ }
+ this._buttonCaption[nFace] = cCaption;
+ }
+ buttonSetIcon(oIcon, nFace = 0) {
+ if (!this._buttonIcon) {
+ this._buttonIcon = [null, null, null];
+ }
+ this._buttonIcon[nFace] = oIcon;
+ }
+ checkThisBox(nWidget, bCheckIt = true) {}
+ clearItems() {
+ if (!this._isChoice) {
+ throw new Error("Not a choice widget");
+ }
+ this._items = [];
+ this._send({
+ id: this._id,
+ clear: null
+ });
+ }
+ deleteItemAt(nIdx = null) {
+ if (!this._isChoice) {
+ throw new Error("Not a choice widget");
+ }
+ if (!this.numItems) {
+ return;
+ }
+ if (nIdx === null) {
+ nIdx = Array.isArray(this._currentValueIndices) ? this._currentValueIndices[0] : this._currentValueIndices;
+ nIdx ||= 0;
+ }
+ if (nIdx < 0 || nIdx >= this.numItems) {
+ nIdx = this.numItems - 1;
+ }
+ this._items.splice(nIdx, 1);
+ if (Array.isArray(this._currentValueIndices)) {
+ let index = this._currentValueIndices.findIndex(i => i >= nIdx);
+ if (index !== -1) {
+ if (this._currentValueIndices[index] === nIdx) {
+ this._currentValueIndices.splice(index, 1);
+ }
+ for (const ii = this._currentValueIndices.length; index < ii; index++) {
+ --this._currentValueIndices[index];
+ }
+ }
+ } else if (this._currentValueIndices === nIdx) {
+ this._currentValueIndices = this.numItems > 0 ? 0 : -1;
+ } else if (this._currentValueIndices > nIdx) {
+ --this._currentValueIndices;
+ }
+ this._send({
+ id: this._id,
+ remove: nIdx
+ });
+ }
+ getItemAt(nIdx = -1, bExportValue = false) {
+ if (!this._isChoice) {
+ throw new Error("Not a choice widget");
+ }
+ if (nIdx < 0 || nIdx >= this.numItems) {
+ nIdx = this.numItems - 1;
+ }
+ const item = this._items[nIdx];
+ return bExportValue ? item.exportValue : item.displayValue;
+ }
+ getArray() {
+ if (this._kidIds) {
+ const array = [];
+ const fillArrayWithKids = kidIds => {
+ for (const id of kidIds) {
+ const obj = this._appObjects[id];
+ if (!obj) {
+ continue;
+ }
+ if (obj.obj._hasValue) {
+ array.push(obj.wrapped);
+ }
+ if (obj.obj._kidIds) {
+ fillArrayWithKids(obj.obj._kidIds);
+ }
+ }
+ };
+ fillArrayWithKids(this._kidIds);
+ return array;
+ }
+ if (this._children === null) {
+ this._children = this._document.obj._getTerminalChildren(this._fieldPath);
+ }
+ return this._children;
+ }
+ getLock() {
+ return undefined;
+ }
+ isBoxChecked(nWidget) {
+ return false;
+ }
+ isDefaultChecked(nWidget) {
+ return false;
+ }
+ insertItemAt(cName, cExport = undefined, nIdx = 0) {
+ if (!this._isChoice) {
+ throw new Error("Not a choice widget");
+ }
+ if (!cName) {
+ return;
+ }
+ if (nIdx < 0 || nIdx > this.numItems) {
+ nIdx = this.numItems;
+ }
+ if (this._items.some(({
+ displayValue
+ }) => displayValue === cName)) {
+ return;
+ }
+ if (cExport === undefined) {
+ cExport = cName;
+ }
+ const data = {
+ displayValue: cName,
+ exportValue: cExport
+ };
+ this._items.splice(nIdx, 0, data);
+ if (Array.isArray(this._currentValueIndices)) {
+ let index = this._currentValueIndices.findIndex(i => i >= nIdx);
+ if (index !== -1) {
+ for (const ii = this._currentValueIndices.length; index < ii; index++) {
+ ++this._currentValueIndices[index];
+ }
+ }
+ } else if (this._currentValueIndices >= nIdx) {
+ ++this._currentValueIndices;
+ }
+ this._send({
+ id: this._id,
+ insert: {
+ index: nIdx,
+ ...data
+ }
+ });
+ }
+ setAction(cTrigger, cScript) {
+ if (typeof cTrigger !== "string" || typeof cScript !== "string") {
+ return;
+ }
+ if (!(cTrigger in this._actions)) {
+ this._actions[cTrigger] = [];
+ }
+ this._actions[cTrigger].push(cScript);
+ }
+ setFocus() {
+ this._send({
+ id: this._id,
+ focus: true
+ });
+ }
+ setItems(oArray) {
+ if (!this._isChoice) {
+ throw new Error("Not a choice widget");
+ }
+ this._items.length = 0;
+ for (const element of oArray) {
+ let displayValue, exportValue;
+ if (Array.isArray(element)) {
+ displayValue = element[0]?.toString() || "";
+ exportValue = element[1]?.toString() || "";
+ } else {
+ displayValue = exportValue = element?.toString() || "";
+ }
+ this._items.push({
+ displayValue,
+ exportValue
+ });
+ }
+ this._currentValueIndices = 0;
+ this._send({
+ id: this._id,
+ items: this._items
+ });
+ }
+ setLock() {}
+ signatureGetModifications() {}
+ signatureGetSeedValue() {}
+ signatureInfo() {}
+ signatureSetSeedValue() {}
+ signatureSign() {}
+ signatureValidate() {}
+ _isButton() {
+ return false;
+ }
+ _reset() {
+ this.value = this.defaultValue;
+ }
+ _runActions(event) {
+ const eventName = event.name;
+ if (!this._actions.has(eventName)) {
+ return false;
+ }
+ const actions = this._actions.get(eventName);
+ try {
+ for (const action of actions) {
+ this._globalEval(action);
+ }
+ } catch (error) {
+ event.rc = false;
+ throw error;
+ }
+ return true;
+ }
+}
+class RadioButtonField extends Field {
+ constructor(otherButtons, data) {
+ super(data);
+ this.exportValues = [this.exportValues];
+ this._radioIds = [this._id];
+ this._radioActions = [this._actions];
+ for (const radioData of otherButtons) {
+ this.exportValues.push(radioData.exportValues);
+ this._radioIds.push(radioData.id);
+ this._radioActions.push(createActionsMap(radioData.actions));
+ if (this._value === radioData.exportValues) {
+ this._id = radioData.id;
+ }
+ }
+ this._hasBeenInitialized = true;
+ this._value = data.value || "";
+ }
+ get value() {
+ return this._value;
+ }
+ set value(value) {
+ if (!this._hasBeenInitialized) {
+ return;
+ }
+ if (value === null || value === undefined) {
+ this._value = "";
+ }
+ const i = this.exportValues.indexOf(value);
+ if (0 <= i && i < this._radioIds.length) {
+ this._id = this._radioIds[i];
+ this._value = value;
+ } else if (value === "Off" && this._radioIds.length === 2) {
+ const nextI = (1 + this._radioIds.indexOf(this._id)) % 2;
+ this._id = this._radioIds[nextI];
+ this._value = this.exportValues[nextI];
+ }
+ }
+ checkThisBox(nWidget, bCheckIt = true) {
+ if (nWidget < 0 || nWidget >= this._radioIds.length || !bCheckIt) {
+ return;
+ }
+ this._id = this._radioIds[nWidget];
+ this._value = this.exportValues[nWidget];
+ this._send({
+ id: this._id,
+ value: this._value
+ });
+ }
+ isBoxChecked(nWidget) {
+ return nWidget >= 0 && nWidget < this._radioIds.length && this._id === this._radioIds[nWidget];
+ }
+ isDefaultChecked(nWidget) {
+ return nWidget >= 0 && nWidget < this.exportValues.length && this.defaultValue === this.exportValues[nWidget];
+ }
+ _getExportValue(state) {
+ const i = this._radioIds.indexOf(this._id);
+ return this.exportValues[i];
+ }
+ _runActions(event) {
+ const i = this._radioIds.indexOf(this._id);
+ this._actions = this._radioActions[i];
+ return super._runActions(event);
+ }
+ _isButton() {
+ return true;
+ }
+}
+class CheckboxField extends RadioButtonField {
+ get value() {
+ return this._value;
+ }
+ set value(value) {
+ if (!value || value === "Off") {
+ this._value = "Off";
+ } else {
+ super.value = value;
+ }
+ }
+ _getExportValue(state) {
+ return state ? super._getExportValue(state) : "Off";
+ }
+ isBoxChecked(nWidget) {
+ if (this._value === "Off") {
+ return false;
+ }
+ return super.isBoxChecked(nWidget);
+ }
+ isDefaultChecked(nWidget) {
+ if (this.defaultValue === "Off") {
+ return this._value === "Off";
+ }
+ return super.isDefaultChecked(nWidget);
+ }
+ checkThisBox(nWidget, bCheckIt = true) {
+ if (nWidget < 0 || nWidget >= this._radioIds.length) {
+ return;
+ }
+ this._id = this._radioIds[nWidget];
+ this._value = bCheckIt ? this.exportValues[nWidget] : "Off";
+ this._send({
+ id: this._id,
+ value: this._value
+ });
+ }
+}
+
+;// CONCATENATED MODULE: ./src/scripting_api/aform.js
+
+class AForm {
+ constructor(document, app, util, color) {
+ this._document = document;
+ this._app = app;
+ this._util = util;
+ this._color = color;
+ this._dateFormats = ["m/d", "m/d/yy", "mm/dd/yy", "mm/yy", "d-mmm", "d-mmm-yy", "dd-mmm-yy", "yy-mm-dd", "mmm-yy", "mmmm-yy", "mmm d, yyyy", "mmmm d, yyyy", "m/d/yy h:MM tt", "m/d/yy HH:MM"];
+ this._timeFormats = ["HH:MM", "h:MM tt", "HH:MM:ss", "h:MM:ss tt"];
+ this._dateActionsCache = new Map();
+ this._emailRegex = new RegExp("^[a-zA-Z0-9.!#$%&'*+\\/=?^_`{|}~-]+" + "@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?" + "(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$");
+ }
+ _mkTargetName(event) {
+ return event.target ? `[ ${event.target.name} ]` : "";
+ }
+ _tryToGuessDate(cFormat, cDate) {
+ let actions = this._dateActionsCache.get(cFormat);
+ if (!actions) {
+ actions = [];
+ this._dateActionsCache.set(cFormat, actions);
+ cFormat.replaceAll(/(d+)|(m+)|(y+)|(H+)|(M+)|(s+)/g, function (match, d, m, y, H, M, s) {
+ if (d) {
+ actions.push((n, date) => {
+ if (n >= 1 && n <= 31) {
+ date.setDate(n);
+ return true;
+ }
+ return false;
+ });
+ } else if (m) {
+ actions.push((n, date) => {
+ if (n >= 1 && n <= 12) {
+ date.setMonth(n - 1);
+ return true;
+ }
+ return false;
+ });
+ } else if (y) {
+ actions.push((n, date) => {
+ if (n < 50) {
+ n += 2000;
+ } else if (n < 100) {
+ n += 1900;
+ }
+ date.setYear(n);
+ return true;
+ });
+ } else if (H) {
+ actions.push((n, date) => {
+ if (n >= 0 && n <= 23) {
+ date.setHours(n);
+ return true;
+ }
+ return false;
+ });
+ } else if (M) {
+ actions.push((n, date) => {
+ if (n >= 0 && n <= 59) {
+ date.setMinutes(n);
+ return true;
+ }
+ return false;
+ });
+ } else if (s) {
+ actions.push((n, date) => {
+ if (n >= 0 && n <= 59) {
+ date.setSeconds(n);
+ return true;
+ }
+ return false;
+ });
+ }
+ return "";
+ });
+ }
+ const number = /\d+/g;
+ let i = 0;
+ let array;
+ const date = new Date();
+ while ((array = number.exec(cDate)) !== null) {
+ if (i < actions.length) {
+ if (!actions[i++](parseInt(array[0]), date)) {
+ return null;
+ }
+ } else {
+ break;
+ }
+ }
+ if (i === 0) {
+ return null;
+ }
+ return date;
+ }
+ _parseDate(cFormat, cDate) {
+ let date = null;
+ try {
+ date = this._util.scand(cFormat, cDate);
+ } catch {}
+ if (!date) {
+ date = Date.parse(cDate);
+ date = isNaN(date) ? this._tryToGuessDate(cFormat, cDate) : new Date(date);
+ }
+ return date;
+ }
+ AFMergeChange(event = globalThis.event) {
+ if (event.willCommit) {
+ return event.value.toString();
+ }
+ return this._app._eventDispatcher.mergeChange(event);
+ }
+ AFParseDateEx(cString, cOrder) {
+ return this._parseDate(cOrder, cString);
+ }
+ AFExtractNums(str) {
+ if (typeof str === "number") {
+ return [str];
+ }
+ if (!str || typeof str !== "string") {
+ return null;
+ }
+ const first = str.charAt(0);
+ if (first === "." || first === ",") {
+ str = `0${str}`;
+ }
+ const numbers = str.match(/(\d+)/g);
+ if (numbers.length === 0) {
+ return null;
+ }
+ return numbers;
+ }
+ AFMakeNumber(str) {
+ if (typeof str === "number") {
+ return str;
+ }
+ if (typeof str !== "string") {
+ return null;
+ }
+ str = str.trim().replace(",", ".");
+ const number = parseFloat(str);
+ if (isNaN(number) || !isFinite(number)) {
+ return null;
+ }
+ return number;
+ }
+ AFMakeArrayFromList(string) {
+ if (typeof string === "string") {
+ return string.split(/, ?/g);
+ }
+ return string;
+ }
+ AFNumber_Format(nDec, sepStyle, negStyle, currStyle, strCurrency, bCurrencyPrepend) {
+ const event = globalThis.event;
+ let value = this.AFMakeNumber(event.value);
+ if (value === null) {
+ event.value = "";
+ return;
+ }
+ const sign = Math.sign(value);
+ const buf = [];
+ let hasParen = false;
+ if (sign === -1 && bCurrencyPrepend && negStyle === 0) {
+ buf.push("-");
+ }
+ if ((negStyle === 2 || negStyle === 3) && sign === -1) {
+ buf.push("(");
+ hasParen = true;
+ }
+ if (bCurrencyPrepend) {
+ buf.push(strCurrency);
+ }
+ sepStyle = Math.min(Math.max(0, Math.floor(sepStyle)), 4);
+ buf.push("%,", sepStyle, ".", nDec.toString(), "f");
+ if (!bCurrencyPrepend) {
+ buf.push(strCurrency);
+ }
+ if (hasParen) {
+ buf.push(")");
+ }
+ if (negStyle === 1 || negStyle === 3) {
+ event.target.textColor = sign === 1 ? this._color.black : this._color.red;
+ }
+ if ((negStyle !== 0 || bCurrencyPrepend) && sign === -1) {
+ value = -value;
+ }
+ const formatStr = buf.join("");
+ event.value = this._util.printf(formatStr, value);
+ }
+ AFNumber_Keystroke(nDec, sepStyle, negStyle, currStyle, strCurrency, bCurrencyPrepend) {
+ const event = globalThis.event;
+ let value = this.AFMergeChange(event);
+ if (!value) {
+ return;
+ }
+ value = value.trim();
+ let pattern;
+ if (sepStyle > 1) {
+ pattern = event.willCommit ? /^[+-]?(\d+(,\d*)?|,\d+)$/ : /^[+-]?\d*,?\d*$/;
+ } else {
+ pattern = event.willCommit ? /^[+-]?(\d+(\.\d*)?|\.\d+)$/ : /^[+-]?\d*\.?\d*$/;
+ }
+ if (!pattern.test(value)) {
+ if (event.willCommit) {
+ const err = `${GlobalConstants.IDS_INVALID_VALUE} ${this._mkTargetName(event)}`;
+ this._app.alert(err);
+ }
+ event.rc = false;
+ }
+ if (event.willCommit && sepStyle > 1) {
+ event.value = parseFloat(value.replace(",", "."));
+ }
+ }
+ AFPercent_Format(nDec, sepStyle, percentPrepend = false) {
+ if (typeof nDec !== "number") {
+ return;
+ }
+ if (typeof sepStyle !== "number") {
+ return;
+ }
+ if (nDec < 0) {
+ throw new Error("Invalid nDec value in AFPercent_Format");
+ }
+ const event = globalThis.event;
+ if (nDec > 512) {
+ event.value = "%";
+ return;
+ }
+ nDec = Math.floor(nDec);
+ sepStyle = Math.min(Math.max(0, Math.floor(sepStyle)), 4);
+ let value = this.AFMakeNumber(event.value);
+ if (value === null) {
+ event.value = "%";
+ return;
+ }
+ const formatStr = `%,${sepStyle}.${nDec}f`;
+ value = this._util.printf(formatStr, value * 100);
+ event.value = percentPrepend ? `%${value}` : `${value}%`;
+ }
+ AFPercent_Keystroke(nDec, sepStyle) {
+ this.AFNumber_Keystroke(nDec, sepStyle, 0, 0, "", true);
+ }
+ AFDate_FormatEx(cFormat) {
+ const event = globalThis.event;
+ const value = event.value;
+ if (!value) {
+ return;
+ }
+ const date = this._parseDate(cFormat, value);
+ if (date !== null) {
+ event.value = this._util.printd(cFormat, date);
+ }
+ }
+ AFDate_Format(pdf) {
+ if (pdf >= 0 && pdf < this._dateFormats.length) {
+ this.AFDate_FormatEx(this._dateFormats[pdf]);
+ }
+ }
+ AFDate_KeystrokeEx(cFormat) {
+ const event = globalThis.event;
+ if (!event.willCommit) {
+ return;
+ }
+ const value = this.AFMergeChange(event);
+ if (!value) {
+ return;
+ }
+ if (this._parseDate(cFormat, value) === null) {
+ const invalid = GlobalConstants.IDS_INVALID_DATE;
+ const invalid2 = GlobalConstants.IDS_INVALID_DATE2;
+ const err = `${invalid} ${this._mkTargetName(event)}${invalid2}${cFormat}`;
+ this._app.alert(err);
+ event.rc = false;
+ }
+ }
+ AFDate_Keystroke(pdf) {
+ if (pdf >= 0 && pdf < this._dateFormats.length) {
+ this.AFDate_KeystrokeEx(this._dateFormats[pdf]);
+ }
+ }
+ AFRange_Validate(bGreaterThan, nGreaterThan, bLessThan, nLessThan) {
+ const event = globalThis.event;
+ if (!event.value) {
+ return;
+ }
+ const value = this.AFMakeNumber(event.value);
+ if (value === null) {
+ return;
+ }
+ bGreaterThan = !!bGreaterThan;
+ bLessThan = !!bLessThan;
+ if (bGreaterThan) {
+ nGreaterThan = this.AFMakeNumber(nGreaterThan);
+ if (nGreaterThan === null) {
+ return;
+ }
+ }
+ if (bLessThan) {
+ nLessThan = this.AFMakeNumber(nLessThan);
+ if (nLessThan === null) {
+ return;
+ }
+ }
+ let err = "";
+ if (bGreaterThan && bLessThan) {
+ if (value < nGreaterThan || value > nLessThan) {
+ err = this._util.printf(GlobalConstants.IDS_GT_AND_LT, nGreaterThan, nLessThan);
+ }
+ } else if (bGreaterThan) {
+ if (value < nGreaterThan) {
+ err = this._util.printf(GlobalConstants.IDS_GREATER_THAN, nGreaterThan);
+ }
+ } else if (value > nLessThan) {
+ err = this._util.printf(GlobalConstants.IDS_LESS_THAN, nLessThan);
+ }
+ if (err) {
+ this._app.alert(err);
+ event.rc = false;
+ }
+ }
+ AFSimple(cFunction, nValue1, nValue2) {
+ const value1 = this.AFMakeNumber(nValue1);
+ if (value1 === null) {
+ throw new Error("Invalid nValue1 in AFSimple");
+ }
+ const value2 = this.AFMakeNumber(nValue2);
+ if (value2 === null) {
+ throw new Error("Invalid nValue2 in AFSimple");
+ }
+ switch (cFunction) {
+ case "AVG":
+ return (value1 + value2) / 2;
+ case "SUM":
+ return value1 + value2;
+ case "PRD":
+ return value1 * value2;
+ case "MIN":
+ return Math.min(value1, value2);
+ case "MAX":
+ return Math.max(value1, value2);
+ }
+ throw new Error("Invalid cFunction in AFSimple");
+ }
+ AFSimple_Calculate(cFunction, cFields) {
+ const actions = {
+ AVG: args => args.reduce((acc, value) => acc + value, 0) / args.length,
+ SUM: args => args.reduce((acc, value) => acc + value, 0),
+ PRD: args => args.reduce((acc, value) => acc * value, 1),
+ MIN: args => args.reduce((acc, value) => Math.min(acc, value), Number.MAX_VALUE),
+ MAX: args => args.reduce((acc, value) => Math.max(acc, value), Number.MIN_VALUE)
+ };
+ if (!(cFunction in actions)) {
+ throw new TypeError("Invalid function in AFSimple_Calculate");
+ }
+ const event = globalThis.event;
+ const values = [];
+ cFields = this.AFMakeArrayFromList(cFields);
+ for (const cField of cFields) {
+ const field = this._document.getField(cField);
+ if (!field) {
+ continue;
+ }
+ for (const child of field.getArray()) {
+ const number = this.AFMakeNumber(child.value);
+ if (number !== null) {
+ values.push(number);
+ }
+ }
+ }
+ if (values.length === 0) {
+ event.value = cFunction === "PRD" ? 1 : 0;
+ return;
+ }
+ const res = actions[cFunction](values);
+ event.value = Math.round(1e6 * res) / 1e6;
+ }
+ AFSpecial_Format(psf) {
+ const event = globalThis.event;
+ if (!event.value) {
+ return;
+ }
+ psf = this.AFMakeNumber(psf);
+ let formatStr;
+ switch (psf) {
+ case 0:
+ formatStr = "99999";
+ break;
+ case 1:
+ formatStr = "99999-9999";
+ break;
+ case 2:
+ formatStr = this._util.printx("9999999999", event.value).length >= 10 ? "(999) 999-9999" : "999-9999";
+ break;
+ case 3:
+ formatStr = "999-99-9999";
+ break;
+ default:
+ throw new Error("Invalid psf in AFSpecial_Format");
+ }
+ event.value = this._util.printx(formatStr, event.value);
+ }
+ AFSpecial_KeystrokeEx(cMask) {
+ if (!cMask) {
+ return;
+ }
+ const event = globalThis.event;
+ const value = this.AFMergeChange(event);
+ if (!value) {
+ return;
+ }
+ const checkers = new Map([["9", char => char >= "0" && char <= "9"], ["A", char => "a" <= char && char <= "z" || "A" <= char && char <= "Z"], ["O", char => "a" <= char && char <= "z" || "A" <= char && char <= "Z" || "0" <= char && char <= "9"], ["X", char => true]]);
+ function _checkValidity(_value, _cMask) {
+ for (let i = 0, ii = _value.length; i < ii; i++) {
+ const mask = _cMask.charAt(i);
+ const char = _value.charAt(i);
+ const checker = checkers.get(mask);
+ if (checker) {
+ if (!checker(char)) {
+ return false;
+ }
+ } else if (mask !== char) {
+ return false;
+ }
+ }
+ return true;
+ }
+ const err = `${GlobalConstants.IDS_INVALID_VALUE} = "${cMask}"`;
+ if (value.length > cMask.length) {
+ this._app.alert(err);
+ event.rc = false;
+ return;
+ }
+ if (event.willCommit) {
+ if (value.length < cMask.length) {
+ this._app.alert(err);
+ event.rc = false;
+ return;
+ }
+ if (!_checkValidity(value, cMask)) {
+ this._app.alert(err);
+ event.rc = false;
+ return;
+ }
+ event.value += cMask.substring(value.length);
+ return;
+ }
+ if (value.length < cMask.length) {
+ cMask = cMask.substring(0, value.length);
+ }
+ if (!_checkValidity(value, cMask)) {
+ this._app.alert(err);
+ event.rc = false;
+ }
+ }
+ AFSpecial_Keystroke(psf) {
+ const event = globalThis.event;
+ psf = this.AFMakeNumber(psf);
+ let formatStr;
+ switch (psf) {
+ case 0:
+ formatStr = "99999";
+ break;
+ case 1:
+ formatStr = "99999-9999";
+ break;
+ case 2:
+ const value = this.AFMergeChange(event);
+ formatStr = value.length > 8 || value.startsWith("(") ? "(999) 999-9999" : "999-9999";
+ break;
+ case 3:
+ formatStr = "999-99-9999";
+ break;
+ default:
+ throw new Error("Invalid psf in AFSpecial_Keystroke");
+ }
+ this.AFSpecial_KeystrokeEx(formatStr);
+ }
+ AFTime_FormatEx(cFormat) {
+ this.AFDate_FormatEx(cFormat);
+ }
+ AFTime_Format(pdf) {
+ if (pdf >= 0 && pdf < this._timeFormats.length) {
+ this.AFDate_FormatEx(this._timeFormats[pdf]);
+ }
+ }
+ AFTime_KeystrokeEx(cFormat) {
+ this.AFDate_KeystrokeEx(cFormat);
+ }
+ AFTime_Keystroke(pdf) {
+ if (pdf >= 0 && pdf < this._timeFormats.length) {
+ this.AFDate_KeystrokeEx(this._timeFormats[pdf]);
+ }
+ }
+ eMailValidate(str) {
+ return this._emailRegex.test(str);
+ }
+ AFExactMatch(rePatterns, str) {
+ if (rePatterns instanceof RegExp) {
+ return str.match(rePatterns)?.[0] === str || 0;
+ }
+ return rePatterns.findIndex(re => str.match(re)?.[0] === str) + 1;
+ }
+}
+
+;// CONCATENATED MODULE: ./src/scripting_api/app_utils.js
+const VIEWER_TYPE = "PDF.js";
+const VIEWER_VARIATION = "Full";
+const VIEWER_VERSION = 21.00720099;
+const FORMS_VERSION = 21.00720099;
+const USERACTIVATION_CALLBACKID = 0;
+const USERACTIVATION_MAXTIME_VALIDITY = 5000;
+function serializeError(error) {
+ const value = `${error.toString()}\n${error.stack}`;
+ return {
+ command: "error",
+ value
+ };
+}
+
+;// CONCATENATED MODULE: ./src/scripting_api/event.js
+
+class Event {
+ constructor(data) {
+ this.change = data.change || "";
+ this.changeEx = data.changeEx || null;
+ this.commitKey = data.commitKey || 0;
+ this.fieldFull = data.fieldFull || false;
+ this.keyDown = data.keyDown || false;
+ this.modifier = data.modifier || false;
+ this.name = data.name;
+ this.rc = true;
+ this.richChange = data.richChange || [];
+ this.richChangeEx = data.richChangeEx || [];
+ this.richValue = data.richValue || [];
+ this.selEnd = data.selEnd ?? -1;
+ this.selStart = data.selStart ?? -1;
+ this.shift = data.shift || false;
+ this.source = data.source || null;
+ this.target = data.target || null;
+ this.targetName = "";
+ this.type = "Field";
+ this.value = data.value || "";
+ this.willCommit = data.willCommit || false;
+ }
+}
+class EventDispatcher {
+ constructor(document, calculationOrder, objects, externalCall) {
+ this._document = document;
+ this._calculationOrder = calculationOrder;
+ this._objects = objects;
+ this._externalCall = externalCall;
+ this._document.obj._eventDispatcher = this;
+ this._isCalculating = false;
+ }
+ mergeChange(event) {
+ let value = event.value;
+ if (Array.isArray(value)) {
+ return value;
+ }
+ if (typeof value !== "string") {
+ value = value.toString();
+ }
+ const prefix = event.selStart >= 0 ? value.substring(0, event.selStart) : "";
+ const postfix = event.selEnd >= 0 && event.selEnd <= value.length ? value.substring(event.selEnd) : "";
+ return `${prefix}${event.change}${postfix}`;
+ }
+ userActivation() {
+ this._document.obj._userActivation = true;
+ this._externalCall("setTimeout", [USERACTIVATION_CALLBACKID, USERACTIVATION_MAXTIME_VALIDITY]);
+ }
+ dispatch(baseEvent) {
+ const id = baseEvent.id;
+ if (!(id in this._objects)) {
+ let event;
+ if (id === "doc" || id === "page") {
+ event = globalThis.event = new Event(baseEvent);
+ event.source = event.target = this._document.wrapped;
+ event.name = baseEvent.name;
+ }
+ if (id === "doc") {
+ const eventName = event.name;
+ if (eventName === "Open") {
+ this.userActivation();
+ this._document.obj._initActions();
+ this.formatAll();
+ }
+ if (!["DidPrint", "DidSave", "WillPrint", "WillSave"].includes(eventName)) {
+ this.userActivation();
+ }
+ this._document.obj._dispatchDocEvent(event.name);
+ } else if (id === "page") {
+ this.userActivation();
+ this._document.obj._dispatchPageEvent(event.name, baseEvent.actions, baseEvent.pageNumber);
+ } else if (id === "app" && baseEvent.name === "ResetForm") {
+ this.userActivation();
+ for (const fieldId of baseEvent.ids) {
+ const obj = this._objects[fieldId];
+ obj?.obj._reset();
+ }
+ }
+ return;
+ }
+ const name = baseEvent.name;
+ const source = this._objects[id];
+ const event = globalThis.event = new Event(baseEvent);
+ let savedChange;
+ this.userActivation();
+ if (source.obj._isButton()) {
+ source.obj._id = id;
+ event.value = source.obj._getExportValue(event.value);
+ if (name === "Action") {
+ source.obj._value = event.value;
+ }
+ }
+ switch (name) {
+ case "Keystroke":
+ savedChange = {
+ value: event.value,
+ changeEx: event.changeEx,
+ change: event.change,
+ selStart: event.selStart,
+ selEnd: event.selEnd
+ };
+ break;
+ case "Blur":
+ case "Focus":
+ Object.defineProperty(event, "value", {
+ configurable: false,
+ writable: false,
+ enumerable: true,
+ value: event.value
+ });
+ break;
+ case "Validate":
+ this.runValidation(source, event);
+ return;
+ case "Action":
+ this.runActions(source, source, event, name);
+ this.runCalculate(source, event);
+ return;
+ }
+ this.runActions(source, source, event, name);
+ if (name !== "Keystroke") {
+ return;
+ }
+ if (event.rc) {
+ if (event.willCommit) {
+ this.runValidation(source, event);
+ } else {
+ if (source.obj._isChoice) {
+ source.obj.value = savedChange.changeEx;
+ source.obj._send({
+ id: source.obj._id,
+ siblings: source.obj._siblings,
+ value: source.obj.value
+ });
+ return;
+ }
+ const value = source.obj.value = this.mergeChange(event);
+ let selStart, selEnd;
+ if (event.selStart !== savedChange.selStart || event.selEnd !== savedChange.selEnd) {
+ selStart = event.selStart;
+ selEnd = event.selEnd;
+ } else {
+ selEnd = selStart = savedChange.selStart + event.change.length;
+ }
+ source.obj._send({
+ id: source.obj._id,
+ siblings: source.obj._siblings,
+ value,
+ selRange: [selStart, selEnd]
+ });
+ }
+ } else if (!event.willCommit) {
+ source.obj._send({
+ id: source.obj._id,
+ siblings: source.obj._siblings,
+ value: savedChange.value,
+ selRange: [savedChange.selStart, savedChange.selEnd]
+ });
+ } else {
+ source.obj._send({
+ id: source.obj._id,
+ siblings: source.obj._siblings,
+ value: "",
+ formattedValue: null,
+ selRange: [0, 0]
+ });
+ }
+ }
+ formatAll() {
+ const event = globalThis.event = new Event({});
+ for (const source of Object.values(this._objects)) {
+ event.value = source.obj.value;
+ this.runActions(source, source, event, "Format");
+ }
+ }
+ runValidation(source, event) {
+ const didValidateRun = this.runActions(source, source, event, "Validate");
+ if (event.rc) {
+ source.obj.value = event.value;
+ this.runCalculate(source, event);
+ const savedValue = source.obj._getValue();
+ event.value = source.obj.value;
+ let formattedValue = null;
+ if (this.runActions(source, source, event, "Format")) {
+ formattedValue = event.value?.toString?.();
+ }
+ source.obj._send({
+ id: source.obj._id,
+ siblings: source.obj._siblings,
+ value: savedValue,
+ formattedValue
+ });
+ event.value = savedValue;
+ } else if (didValidateRun) {
+ source.obj._send({
+ id: source.obj._id,
+ siblings: source.obj._siblings,
+ value: "",
+ formattedValue: null,
+ selRange: [0, 0],
+ focus: true
+ });
+ }
+ }
+ runActions(source, target, event, eventName) {
+ event.source = source.wrapped;
+ event.target = target.wrapped;
+ event.name = eventName;
+ event.targetName = target.obj.name;
+ event.rc = true;
+ return target.obj._runActions(event);
+ }
+ calculateNow() {
+ if (!this._calculationOrder || this._isCalculating || !this._document.obj.calculate) {
+ return;
+ }
+ this._isCalculating = true;
+ const first = this._calculationOrder[0];
+ const source = this._objects[first];
+ globalThis.event = new Event({});
+ try {
+ this.runCalculate(source, globalThis.event);
+ } catch (error) {
+ this._isCalculating = false;
+ throw error;
+ }
+ this._isCalculating = false;
+ }
+ runCalculate(source, event) {
+ if (!this._calculationOrder || !this._document.obj.calculate) {
+ return;
+ }
+ for (const targetId of this._calculationOrder) {
+ if (!(targetId in this._objects)) {
+ continue;
+ }
+ if (!this._document.obj.calculate) {
+ break;
+ }
+ event.value = null;
+ const target = this._objects[targetId];
+ let savedValue = target.obj._getValue();
+ this.runActions(source, target, event, "Calculate");
+ if (!event.rc) {
+ continue;
+ }
+ if (event.value !== null) {
+ target.obj.value = event.value;
+ } else {
+ event.value = target.obj._getValue();
+ }
+ this.runActions(target, target, event, "Validate");
+ if (!event.rc) {
+ if (target.obj._getValue() !== savedValue) {
+ target.wrapped.value = savedValue;
+ }
+ continue;
+ }
+ if (event.value === null) {
+ event.value = target.obj._getValue();
+ }
+ savedValue = target.obj._getValue();
+ let formattedValue = null;
+ if (this.runActions(target, target, event, "Format")) {
+ formattedValue = event.value?.toString?.();
+ }
+ target.obj._send({
+ id: target.obj._id,
+ siblings: target.obj._siblings,
+ value: savedValue,
+ formattedValue
+ });
+ }
+ }
+}
+
+;// CONCATENATED MODULE: ./src/scripting_api/fullscreen.js
+
+
+class FullScreen extends PDFObject {
+ constructor(data) {
+ super(data);
+ this._backgroundColor = [];
+ this._clickAdvances = true;
+ this._cursor = Cursor.hidden;
+ this._defaultTransition = "";
+ this._escapeExits = true;
+ this._isFullScreen = true;
+ this._loop = false;
+ this._timeDelay = 3600;
+ this._usePageTiming = false;
+ this._useTimer = false;
+ }
+ get backgroundColor() {
+ return this._backgroundColor;
+ }
+ set backgroundColor(_) {}
+ get clickAdvances() {
+ return this._clickAdvances;
+ }
+ set clickAdvances(_) {}
+ get cursor() {
+ return this._cursor;
+ }
+ set cursor(_) {}
+ get defaultTransition() {
+ return this._defaultTransition;
+ }
+ set defaultTransition(_) {}
+ get escapeExits() {
+ return this._escapeExits;
+ }
+ set escapeExits(_) {}
+ get isFullScreen() {
+ return this._isFullScreen;
+ }
+ set isFullScreen(_) {}
+ get loop() {
+ return this._loop;
+ }
+ set loop(_) {}
+ get timeDelay() {
+ return this._timeDelay;
+ }
+ set timeDelay(_) {}
+ get transitions() {
+ return ["Replace", "WipeRight", "WipeLeft", "WipeDown", "WipeUp", "SplitHorizontalIn", "SplitHorizontalOut", "SplitVerticalIn", "SplitVerticalOut", "BlindsHorizontal", "BlindsVertical", "BoxIn", "BoxOut", "GlitterRight", "GlitterDown", "GlitterRightDown", "Dissolve", "Random"];
+ }
+ set transitions(_) {
+ throw new Error("fullscreen.transitions is read-only");
+ }
+ get usePageTiming() {
+ return this._usePageTiming;
+ }
+ set usePageTiming(_) {}
+ get useTimer() {
+ return this._useTimer;
+ }
+ set useTimer(_) {}
+}
+
+;// CONCATENATED MODULE: ./src/scripting_api/thermometer.js
+
+class Thermometer extends PDFObject {
+ constructor(data) {
+ super(data);
+ this._cancelled = false;
+ this._duration = 100;
+ this._text = "";
+ this._value = 0;
+ }
+ get cancelled() {
+ return this._cancelled;
+ }
+ set cancelled(_) {
+ throw new Error("thermometer.cancelled is read-only");
+ }
+ get duration() {
+ return this._duration;
+ }
+ set duration(val) {
+ this._duration = val;
+ }
+ get text() {
+ return this._text;
+ }
+ set text(val) {
+ this._text = val;
+ }
+ get value() {
+ return this._value;
+ }
+ set value(val) {
+ this._value = val;
+ }
+ begin() {}
+ end() {}
+}
+
+;// CONCATENATED MODULE: ./src/scripting_api/app.js
+
+
+
+
+
+
+class App extends PDFObject {
+ constructor(data) {
+ super(data);
+ this._constants = null;
+ this._focusRect = true;
+ this._fs = null;
+ this._language = App._getLanguage(data.language);
+ this._openInPlace = false;
+ this._platform = App._getPlatform(data.platform);
+ this._runtimeHighlight = false;
+ this._runtimeHighlightColor = ["T"];
+ this._thermometer = null;
+ this._toolbar = false;
+ this._document = data._document;
+ this._proxyHandler = data.proxyHandler;
+ this._objects = Object.create(null);
+ this._eventDispatcher = new EventDispatcher(this._document, data.calculationOrder, this._objects, data.externalCall);
+ this._timeoutIds = new WeakMap();
+ if (typeof FinalizationRegistry !== "undefined") {
+ this._timeoutIdsRegistry = new FinalizationRegistry(this._cleanTimeout.bind(this));
+ } else {
+ this._timeoutIdsRegistry = null;
+ }
+ this._timeoutCallbackIds = new Map();
+ this._timeoutCallbackId = USERACTIVATION_CALLBACKID + 1;
+ this._globalEval = data.globalEval;
+ this._externalCall = data.externalCall;
+ }
+ _dispatchEvent(pdfEvent) {
+ this._eventDispatcher.dispatch(pdfEvent);
+ }
+ _registerTimeoutCallback(cExpr) {
+ const id = this._timeoutCallbackId++;
+ this._timeoutCallbackIds.set(id, cExpr);
+ return id;
+ }
+ _unregisterTimeoutCallback(id) {
+ this._timeoutCallbackIds.delete(id);
+ }
+ _evalCallback({
+ callbackId,
+ interval
+ }) {
+ if (callbackId === USERACTIVATION_CALLBACKID) {
+ this._document.obj._userActivation = false;
+ return;
+ }
+ const expr = this._timeoutCallbackIds.get(callbackId);
+ if (!interval) {
+ this._unregisterTimeoutCallback(callbackId);
+ }
+ if (expr) {
+ this._globalEval(expr);
+ }
+ }
+ _registerTimeout(callbackId, interval) {
+ const timeout = Object.create(null);
+ const id = {
+ callbackId,
+ interval
+ };
+ this._timeoutIds.set(timeout, id);
+ this._timeoutIdsRegistry?.register(timeout, id);
+ return timeout;
+ }
+ _unregisterTimeout(timeout) {
+ this._timeoutIdsRegistry?.unregister(timeout);
+ const data = this._timeoutIds.get(timeout);
+ if (!data) {
+ return;
+ }
+ this._timeoutIds.delete(timeout);
+ this._cleanTimeout(data);
+ }
+ _cleanTimeout({
+ callbackId,
+ interval
+ }) {
+ this._unregisterTimeoutCallback(callbackId);
+ if (interval) {
+ this._externalCall("clearInterval", [callbackId]);
+ } else {
+ this._externalCall("clearTimeout", [callbackId]);
+ }
+ }
+ static _getPlatform(platform) {
+ if (typeof platform === "string") {
+ platform = platform.toLowerCase();
+ if (platform.includes("win")) {
+ return "WIN";
+ } else if (platform.includes("mac")) {
+ return "MAC";
+ }
+ }
+ return "UNIX";
+ }
+ static _getLanguage(language) {
+ const [main, sub] = language.toLowerCase().split(/[-_]/);
+ switch (main) {
+ case "zh":
+ if (sub === "cn" || sub === "sg") {
+ return "CHS";
+ }
+ return "CHT";
+ case "da":
+ return "DAN";
+ case "de":
+ return "DEU";
+ case "es":
+ return "ESP";
+ case "fr":
+ return "FRA";
+ case "it":
+ return "ITA";
+ case "ko":
+ return "KOR";
+ case "ja":
+ return "JPN";
+ case "nl":
+ return "NLD";
+ case "no":
+ return "NOR";
+ case "pt":
+ if (sub === "br") {
+ return "PTB";
+ }
+ return "ENU";
+ case "fi":
+ return "SUO";
+ case "SV":
+ return "SVE";
+ default:
+ return "ENU";
+ }
+ }
+ get activeDocs() {
+ return [this._document.wrapped];
+ }
+ set activeDocs(_) {
+ throw new Error("app.activeDocs is read-only");
+ }
+ get calculate() {
+ return this._document.obj.calculate;
+ }
+ set calculate(calculate) {
+ this._document.obj.calculate = calculate;
+ }
+ get constants() {
+ if (!this._constants) {
+ this._constants = Object.freeze({
+ align: Object.freeze({
+ left: 0,
+ center: 1,
+ right: 2,
+ top: 3,
+ bottom: 4
+ })
+ });
+ }
+ return this._constants;
+ }
+ set constants(_) {
+ throw new Error("app.constants is read-only");
+ }
+ get focusRect() {
+ return this._focusRect;
+ }
+ set focusRect(val) {
+ this._focusRect = val;
+ }
+ get formsVersion() {
+ return FORMS_VERSION;
+ }
+ set formsVersion(_) {
+ throw new Error("app.formsVersion is read-only");
+ }
+ get fromPDFConverters() {
+ return [];
+ }
+ set fromPDFConverters(_) {
+ throw new Error("app.fromPDFConverters is read-only");
+ }
+ get fs() {
+ if (this._fs === null) {
+ this._fs = new Proxy(new FullScreen({
+ send: this._send
+ }), this._proxyHandler);
+ }
+ return this._fs;
+ }
+ set fs(_) {
+ throw new Error("app.fs is read-only");
+ }
+ get language() {
+ return this._language;
+ }
+ set language(_) {
+ throw new Error("app.language is read-only");
+ }
+ get media() {
+ return undefined;
+ }
+ set media(_) {
+ throw new Error("app.media is read-only");
+ }
+ get monitors() {
+ return [];
+ }
+ set monitors(_) {
+ throw new Error("app.monitors is read-only");
+ }
+ get numPlugins() {
+ return 0;
+ }
+ set numPlugins(_) {
+ throw new Error("app.numPlugins is read-only");
+ }
+ get openInPlace() {
+ return this._openInPlace;
+ }
+ set openInPlace(val) {
+ this._openInPlace = val;
+ }
+ get platform() {
+ return this._platform;
+ }
+ set platform(_) {
+ throw new Error("app.platform is read-only");
+ }
+ get plugins() {
+ return [];
+ }
+ set plugins(_) {
+ throw new Error("app.plugins is read-only");
+ }
+ get printColorProfiles() {
+ return [];
+ }
+ set printColorProfiles(_) {
+ throw new Error("app.printColorProfiles is read-only");
+ }
+ get printerNames() {
+ return [];
+ }
+ set printerNames(_) {
+ throw new Error("app.printerNames is read-only");
+ }
+ get runtimeHighlight() {
+ return this._runtimeHighlight;
+ }
+ set runtimeHighlight(val) {
+ this._runtimeHighlight = val;
+ }
+ get runtimeHighlightColor() {
+ return this._runtimeHighlightColor;
+ }
+ set runtimeHighlightColor(val) {
+ if (Color._isValidColor(val)) {
+ this._runtimeHighlightColor = val;
+ }
+ }
+ get thermometer() {
+ if (this._thermometer === null) {
+ this._thermometer = new Proxy(new Thermometer({
+ send: this._send
+ }), this._proxyHandler);
+ }
+ return this._thermometer;
+ }
+ set thermometer(_) {
+ throw new Error("app.thermometer is read-only");
+ }
+ get toolbar() {
+ return this._toolbar;
+ }
+ set toolbar(val) {
+ this._toolbar = val;
+ }
+ get toolbarHorizontal() {
+ return this.toolbar;
+ }
+ set toolbarHorizontal(value) {
+ this.toolbar = value;
+ }
+ get toolbarVertical() {
+ return this.toolbar;
+ }
+ set toolbarVertical(value) {
+ this.toolbar = value;
+ }
+ get viewerType() {
+ return VIEWER_TYPE;
+ }
+ set viewerType(_) {
+ throw new Error("app.viewerType is read-only");
+ }
+ get viewerVariation() {
+ return VIEWER_VARIATION;
+ }
+ set viewerVariation(_) {
+ throw new Error("app.viewerVariation is read-only");
+ }
+ get viewerVersion() {
+ return VIEWER_VERSION;
+ }
+ set viewerVersion(_) {
+ throw new Error("app.viewerVersion is read-only");
+ }
+ addMenuItem() {}
+ addSubMenu() {}
+ addToolButton() {}
+ alert(cMsg, nIcon = 0, nType = 0, cTitle = "PDF.js", oDoc = null, oCheckbox = null) {
+ if (!this._document.obj._userActivation) {
+ return 0;
+ }
+ this._document.obj._userActivation = false;
+ if (cMsg && typeof cMsg === "object") {
+ nType = cMsg.nType;
+ cMsg = cMsg.cMsg;
+ }
+ cMsg = (cMsg || "").toString();
+ nType = typeof nType !== "number" || isNaN(nType) || nType < 0 || nType > 3 ? 0 : nType;
+ if (nType >= 2) {
+ return this._externalCall("confirm", [cMsg]) ? 4 : 3;
+ }
+ this._externalCall("alert", [cMsg]);
+ return 1;
+ }
+ beep() {}
+ beginPriv() {}
+ browseForDoc() {}
+ clearInterval(oInterval) {
+ this._unregisterTimeout(oInterval);
+ }
+ clearTimeOut(oTime) {
+ this._unregisterTimeout(oTime);
+ }
+ endPriv() {}
+ execDialog() {}
+ execMenuItem(item) {
+ if (!this._document.obj._userActivation) {
+ return;
+ }
+ this._document.obj._userActivation = false;
+ switch (item) {
+ case "SaveAs":
+ if (this._document.obj._disableSaving) {
+ return;
+ }
+ this._send({
+ command: item
+ });
+ break;
+ case "FirstPage":
+ case "LastPage":
+ case "NextPage":
+ case "PrevPage":
+ case "ZoomViewIn":
+ case "ZoomViewOut":
+ this._send({
+ command: item
+ });
+ break;
+ case "FitPage":
+ this._send({
+ command: "zoom",
+ value: "page-fit"
+ });
+ break;
+ case "Print":
+ if (this._document.obj._disablePrinting) {
+ return;
+ }
+ this._send({
+ command: "print"
+ });
+ break;
+ }
+ }
+ getNthPlugInName() {}
+ getPath() {}
+ goBack() {}
+ goForward() {}
+ hideMenuItem() {}
+ hideToolbarButton() {}
+ launchURL() {}
+ listMenuItems() {}
+ listToolbarButtons() {}
+ loadPolicyFile() {}
+ mailGetAddrs() {}
+ mailMsg() {}
+ newDoc() {}
+ newCollection() {}
+ newFDF() {}
+ openDoc() {}
+ openFDF() {}
+ popUpMenu() {}
+ popUpMenuEx() {}
+ removeToolButton() {}
+ response(cQuestion, cTitle = "", cDefault = "", bPassword = "", cLabel = "") {
+ if (cQuestion && typeof cQuestion === "object") {
+ cDefault = cQuestion.cDefault;
+ cQuestion = cQuestion.cQuestion;
+ }
+ cQuestion = (cQuestion || "").toString();
+ cDefault = (cDefault || "").toString();
+ return this._externalCall("prompt", [cQuestion, cDefault || ""]);
+ }
+ setInterval(cExpr, nMilliseconds = 0) {
+ if (cExpr && typeof cExpr === "object") {
+ nMilliseconds = cExpr.nMilliseconds || 0;
+ cExpr = cExpr.cExpr;
+ }
+ if (typeof cExpr !== "string") {
+ throw new TypeError("First argument of app.setInterval must be a string");
+ }
+ if (typeof nMilliseconds !== "number") {
+ throw new TypeError("Second argument of app.setInterval must be a number");
+ }
+ const callbackId = this._registerTimeoutCallback(cExpr);
+ this._externalCall("setInterval", [callbackId, nMilliseconds]);
+ return this._registerTimeout(callbackId, true);
+ }
+ setTimeOut(cExpr, nMilliseconds = 0) {
+ if (cExpr && typeof cExpr === "object") {
+ nMilliseconds = cExpr.nMilliseconds || 0;
+ cExpr = cExpr.cExpr;
+ }
+ if (typeof cExpr !== "string") {
+ throw new TypeError("First argument of app.setTimeOut must be a string");
+ }
+ if (typeof nMilliseconds !== "number") {
+ throw new TypeError("Second argument of app.setTimeOut must be a number");
+ }
+ const callbackId = this._registerTimeoutCallback(cExpr);
+ this._externalCall("setTimeout", [callbackId, nMilliseconds]);
+ return this._registerTimeout(callbackId, false);
+ }
+ trustedFunction() {}
+ trustPropagatorFunction() {}
+}
+
+;// CONCATENATED MODULE: ./src/scripting_api/console.js
+
+class Console extends PDFObject {
+ clear() {
+ this._send({
+ id: "clear"
+ });
+ }
+ hide() {}
+ println(msg) {
+ if (typeof msg === "string") {
+ this._send({
+ command: "println",
+ value: "PDF.js Console:: " + msg
+ });
+ }
+ }
+ show() {}
+}
+
+;// CONCATENATED MODULE: ./src/scripting_api/print_params.js
+class PrintParams {
+ constructor(data) {
+ this.binaryOk = true;
+ this.bitmapDPI = 150;
+ this.booklet = {
+ binding: 0,
+ duplexMode: 0,
+ subsetFrom: 0,
+ subsetTo: -1
+ };
+ this.colorOverride = 0;
+ this.colorProfile = "";
+ this.constants = Object.freeze({
+ bookletBindings: Object.freeze({
+ Left: 0,
+ Right: 1,
+ LeftTall: 2,
+ RightTall: 3
+ }),
+ bookletDuplexMode: Object.freeze({
+ BothSides: 0,
+ FrontSideOnly: 1,
+ BasicSideOnly: 2
+ }),
+ colorOverrides: Object.freeze({
+ auto: 0,
+ gray: 1,
+ mono: 2
+ }),
+ fontPolicies: Object.freeze({
+ everyPage: 0,
+ jobStart: 1,
+ pageRange: 2
+ }),
+ handling: Object.freeze({
+ none: 0,
+ fit: 1,
+ shrink: 2,
+ tileAll: 3,
+ tileLarge: 4,
+ nUp: 5,
+ booklet: 6
+ }),
+ interactionLevel: Object.freeze({
+ automatic: 0,
+ full: 1,
+ silent: 2
+ }),
+ nUpPageOrders: Object.freeze({
+ Horizontal: 0,
+ HorizontalReversed: 1,
+ Vertical: 2
+ }),
+ printContents: Object.freeze({
+ doc: 0,
+ docAndComments: 1,
+ formFieldsOnly: 2
+ }),
+ flagValues: Object.freeze({
+ applyOverPrint: 1,
+ applySoftProofSettings: 1 << 1,
+ applyWorkingColorSpaces: 1 << 2,
+ emitHalftones: 1 << 3,
+ emitPostScriptXObjects: 1 << 4,
+ emitFormsAsPSForms: 1 << 5,
+ maxJP2KRes: 1 << 6,
+ setPageSize: 1 << 7,
+ suppressBG: 1 << 8,
+ suppressCenter: 1 << 9,
+ suppressCJKFontSubst: 1 << 10,
+ suppressCropClip: 1 << 1,
+ suppressRotate: 1 << 12,
+ suppressTransfer: 1 << 13,
+ suppressUCR: 1 << 14,
+ useTrapAnnots: 1 << 15,
+ usePrintersMarks: 1 << 16
+ }),
+ rasterFlagValues: Object.freeze({
+ textToOutline: 1,
+ strokesToOutline: 1 << 1,
+ allowComplexClip: 1 << 2,
+ preserveOverprint: 1 << 3
+ }),
+ subsets: Object.freeze({
+ all: 0,
+ even: 1,
+ odd: 2
+ }),
+ tileMarks: Object.freeze({
+ none: 0,
+ west: 1,
+ east: 2
+ }),
+ usages: Object.freeze({
+ auto: 0,
+ use: 1,
+ noUse: 2
+ })
+ });
+ this.downloadFarEastFonts = false;
+ this.fileName = "";
+ this.firstPage = 0;
+ this.flags = 0;
+ this.fontPolicy = 0;
+ this.gradientDPI = 150;
+ this.interactive = 1;
+ this.lastPage = data.lastPage;
+ this.npUpAutoRotate = false;
+ this.npUpNumPagesH = 2;
+ this.npUpNumPagesV = 2;
+ this.npUpPageBorder = false;
+ this.npUpPageOrder = 0;
+ this.pageHandling = 0;
+ this.pageSubset = 0;
+ this.printAsImage = false;
+ this.printContent = 0;
+ this.printerName = "";
+ this.psLevel = 0;
+ this.rasterFlags = 0;
+ this.reversePages = false;
+ this.tileLabel = false;
+ this.tileMark = 0;
+ this.tileOverlap = 0;
+ this.tileScale = 1.0;
+ this.transparencyLevel = 75;
+ this.usePrinterCRD = 0;
+ this.useT1Conversion = 0;
+ }
+}
+
+;// CONCATENATED MODULE: ./src/scripting_api/doc.js
+
+
+
+
+
+const DOC_EXTERNAL = false;
+class InfoProxyHandler {
+ static get(obj, prop) {
+ return obj[prop.toLowerCase()];
+ }
+ static set(obj, prop, value) {
+ throw new Error(`doc.info.${prop} is read-only`);
+ }
+}
+class Doc extends PDFObject {
+ constructor(data) {
+ super(data);
+ this._expandos = globalThis;
+ this._baseURL = data.baseURL || "";
+ this._calculate = true;
+ this._delay = false;
+ this._dirty = false;
+ this._disclosed = false;
+ this._media = undefined;
+ this._metadata = data.metadata || "";
+ this._noautocomplete = undefined;
+ this._nocache = undefined;
+ this._spellDictionaryOrder = [];
+ this._spellLanguageOrder = [];
+ this._printParams = null;
+ this._fields = new Map();
+ this._fieldNames = [];
+ this._event = null;
+ this._author = data.Author || "";
+ this._creator = data.Creator || "";
+ this._creationDate = this._getDate(data.CreationDate) || null;
+ this._docID = data.docID || ["", ""];
+ this._documentFileName = data.filename || "";
+ this._filesize = data.filesize || 0;
+ this._keywords = data.Keywords || "";
+ this._layout = data.layout || "";
+ this._modDate = this._getDate(data.ModDate) || null;
+ this._numFields = 0;
+ this._numPages = data.numPages || 1;
+ this._pageNum = data.pageNum || 0;
+ this._producer = data.Producer || "";
+ this._securityHandler = data.EncryptFilterName || null;
+ this._subject = data.Subject || "";
+ this._title = data.Title || "";
+ this._URL = data.URL || "";
+ this._info = new Proxy({
+ title: this._title,
+ author: this._author,
+ authors: data.authors || [this._author],
+ subject: this._subject,
+ keywords: this._keywords,
+ creator: this._creator,
+ producer: this._producer,
+ creationdate: this._creationDate,
+ moddate: this._modDate,
+ trapped: data.Trapped || "Unknown"
+ }, InfoProxyHandler);
+ this._zoomType = ZoomType.none;
+ this._zoom = data.zoom || 100;
+ this._actions = createActionsMap(data.actions);
+ this._globalEval = data.globalEval;
+ this._pageActions = new Map();
+ this._userActivation = false;
+ this._disablePrinting = false;
+ this._disableSaving = false;
+ }
+ _initActions() {
+ const dontRun = new Set(["WillClose", "WillSave", "DidSave", "WillPrint", "DidPrint", "OpenAction"]);
+ this._disableSaving = true;
+ for (const actionName of this._actions.keys()) {
+ if (!dontRun.has(actionName)) {
+ this._runActions(actionName);
+ }
+ }
+ this._runActions("OpenAction");
+ this._disableSaving = false;
+ }
+ _dispatchDocEvent(name) {
+ switch (name) {
+ case "Open":
+ this._disableSaving = true;
+ this._runActions("OpenAction");
+ this._disableSaving = false;
+ break;
+ case "WillPrint":
+ this._disablePrinting = true;
+ try {
+ this._runActions(name);
+ } catch (error) {
+ this._send(serializeError(error));
+ }
+ this._send({
+ command: "WillPrintFinished"
+ });
+ this._disablePrinting = false;
+ break;
+ case "WillSave":
+ this._disableSaving = true;
+ this._runActions(name);
+ this._disableSaving = false;
+ break;
+ default:
+ this._runActions(name);
+ }
+ }
+ _dispatchPageEvent(name, actions, pageNumber) {
+ if (name === "PageOpen") {
+ if (!this._pageActions.has(pageNumber)) {
+ this._pageActions.set(pageNumber, createActionsMap(actions));
+ }
+ this._pageNum = pageNumber - 1;
+ }
+ actions = this._pageActions.get(pageNumber)?.get(name);
+ if (actions) {
+ for (const action of actions) {
+ this._globalEval(action);
+ }
+ }
+ }
+ _runActions(name) {
+ const actions = this._actions.get(name);
+ if (actions) {
+ for (const action of actions) {
+ this._globalEval(action);
+ }
+ }
+ }
+ _addField(name, field) {
+ this._fields.set(name, field);
+ this._fieldNames.push(name);
+ this._numFields++;
+ }
+ _getDate(date) {
+ if (!date || date.length < 15 || !date.startsWith("D:")) {
+ return date;
+ }
+ date = date.substring(2);
+ const year = date.substring(0, 4);
+ const month = date.substring(4, 6);
+ const day = date.substring(6, 8);
+ const hour = date.substring(8, 10);
+ const minute = date.substring(10, 12);
+ const o = date.charAt(12);
+ let second, offsetPos;
+ if (o === "Z" || o === "+" || o === "-") {
+ second = "00";
+ offsetPos = 12;
+ } else {
+ second = date.substring(12, 14);
+ offsetPos = 14;
+ }
+ const offset = date.substring(offsetPos).replaceAll("'", "");
+ return new Date(`${year}-${month}-${day}T${hour}:${minute}:${second}${offset}`);
+ }
+ get author() {
+ return this._author;
+ }
+ set author(_) {
+ throw new Error("doc.author is read-only");
+ }
+ get baseURL() {
+ return this._baseURL;
+ }
+ set baseURL(baseURL) {
+ this._baseURL = baseURL;
+ }
+ get bookmarkRoot() {
+ return undefined;
+ }
+ set bookmarkRoot(_) {
+ throw new Error("doc.bookmarkRoot is read-only");
+ }
+ get calculate() {
+ return this._calculate;
+ }
+ set calculate(calculate) {
+ this._calculate = calculate;
+ }
+ get creator() {
+ return this._creator;
+ }
+ set creator(_) {
+ throw new Error("doc.creator is read-only");
+ }
+ get dataObjects() {
+ return [];
+ }
+ set dataObjects(_) {
+ throw new Error("doc.dataObjects is read-only");
+ }
+ get delay() {
+ return this._delay;
+ }
+ set delay(delay) {
+ this._delay = delay;
+ }
+ get dirty() {
+ return this._dirty;
+ }
+ set dirty(dirty) {
+ this._dirty = dirty;
+ }
+ get disclosed() {
+ return this._disclosed;
+ }
+ set disclosed(disclosed) {
+ this._disclosed = disclosed;
+ }
+ get docID() {
+ return this._docID;
+ }
+ set docID(_) {
+ throw new Error("doc.docID is read-only");
+ }
+ get documentFileName() {
+ return this._documentFileName;
+ }
+ set documentFileName(_) {
+ throw new Error("doc.documentFileName is read-only");
+ }
+ get dynamicXFAForm() {
+ return false;
+ }
+ set dynamicXFAForm(_) {
+ throw new Error("doc.dynamicXFAForm is read-only");
+ }
+ get external() {
+ return DOC_EXTERNAL;
+ }
+ set external(_) {
+ throw new Error("doc.external is read-only");
+ }
+ get filesize() {
+ return this._filesize;
+ }
+ set filesize(_) {
+ throw new Error("doc.filesize is read-only");
+ }
+ get hidden() {
+ return false;
+ }
+ set hidden(_) {
+ throw new Error("doc.hidden is read-only");
+ }
+ get hostContainer() {
+ return undefined;
+ }
+ set hostContainer(_) {
+ throw new Error("doc.hostContainer is read-only");
+ }
+ get icons() {
+ return undefined;
+ }
+ set icons(_) {
+ throw new Error("doc.icons is read-only");
+ }
+ get info() {
+ return this._info;
+ }
+ set info(_) {
+ throw new Error("doc.info is read-only");
+ }
+ get innerAppWindowRect() {
+ return [0, 0, 0, 0];
+ }
+ set innerAppWindowRect(_) {
+ throw new Error("doc.innerAppWindowRect is read-only");
+ }
+ get innerDocWindowRect() {
+ return [0, 0, 0, 0];
+ }
+ set innerDocWindowRect(_) {
+ throw new Error("doc.innerDocWindowRect is read-only");
+ }
+ get isModal() {
+ return false;
+ }
+ set isModal(_) {
+ throw new Error("doc.isModal is read-only");
+ }
+ get keywords() {
+ return this._keywords;
+ }
+ set keywords(_) {
+ throw new Error("doc.keywords is read-only");
+ }
+ get layout() {
+ return this._layout;
+ }
+ set layout(value) {
+ if (!this._userActivation) {
+ return;
+ }
+ this._userActivation = false;
+ if (typeof value !== "string") {
+ return;
+ }
+ if (value !== "SinglePage" && value !== "OneColumn" && value !== "TwoColumnLeft" && value !== "TwoPageLeft" && value !== "TwoColumnRight" && value !== "TwoPageRight") {
+ value = "SinglePage";
+ }
+ this._send({
+ command: "layout",
+ value
+ });
+ this._layout = value;
+ }
+ get media() {
+ return this._media;
+ }
+ set media(media) {
+ this._media = media;
+ }
+ get metadata() {
+ return this._metadata;
+ }
+ set metadata(metadata) {
+ this._metadata = metadata;
+ }
+ get modDate() {
+ return this._modDate;
+ }
+ set modDate(_) {
+ throw new Error("doc.modDate is read-only");
+ }
+ get mouseX() {
+ return 0;
+ }
+ set mouseX(_) {
+ throw new Error("doc.mouseX is read-only");
+ }
+ get mouseY() {
+ return 0;
+ }
+ set mouseY(_) {
+ throw new Error("doc.mouseY is read-only");
+ }
+ get noautocomplete() {
+ return this._noautocomplete;
+ }
+ set noautocomplete(noautocomplete) {
+ this._noautocomplete = noautocomplete;
+ }
+ get nocache() {
+ return this._nocache;
+ }
+ set nocache(nocache) {
+ this._nocache = nocache;
+ }
+ get numFields() {
+ return this._numFields;
+ }
+ set numFields(_) {
+ throw new Error("doc.numFields is read-only");
+ }
+ get numPages() {
+ return this._numPages;
+ }
+ set numPages(_) {
+ throw new Error("doc.numPages is read-only");
+ }
+ get numTemplates() {
+ return 0;
+ }
+ set numTemplates(_) {
+ throw new Error("doc.numTemplates is read-only");
+ }
+ get outerAppWindowRect() {
+ return [0, 0, 0, 0];
+ }
+ set outerAppWindowRect(_) {
+ throw new Error("doc.outerAppWindowRect is read-only");
+ }
+ get outerDocWindowRect() {
+ return [0, 0, 0, 0];
+ }
+ set outerDocWindowRect(_) {
+ throw new Error("doc.outerDocWindowRect is read-only");
+ }
+ get pageNum() {
+ return this._pageNum;
+ }
+ set pageNum(value) {
+ if (!this._userActivation) {
+ return;
+ }
+ this._userActivation = false;
+ if (typeof value !== "number" || value < 0 || value >= this._numPages) {
+ return;
+ }
+ this._send({
+ command: "page-num",
+ value
+ });
+ this._pageNum = value;
+ }
+ get pageWindowRect() {
+ return [0, 0, 0, 0];
+ }
+ set pageWindowRect(_) {
+ throw new Error("doc.pageWindowRect is read-only");
+ }
+ get path() {
+ return "";
+ }
+ set path(_) {
+ throw new Error("doc.path is read-only");
+ }
+ get permStatusReady() {
+ return true;
+ }
+ set permStatusReady(_) {
+ throw new Error("doc.permStatusReady is read-only");
+ }
+ get producer() {
+ return this._producer;
+ }
+ set producer(_) {
+ throw new Error("doc.producer is read-only");
+ }
+ get requiresFullSave() {
+ return false;
+ }
+ set requiresFullSave(_) {
+ throw new Error("doc.requiresFullSave is read-only");
+ }
+ get securityHandler() {
+ return this._securityHandler;
+ }
+ set securityHandler(_) {
+ throw new Error("doc.securityHandler is read-only");
+ }
+ get selectedAnnots() {
+ return [];
+ }
+ set selectedAnnots(_) {
+ throw new Error("doc.selectedAnnots is read-only");
+ }
+ get sounds() {
+ return [];
+ }
+ set sounds(_) {
+ throw new Error("doc.sounds is read-only");
+ }
+ get spellDictionaryOrder() {
+ return this._spellDictionaryOrder;
+ }
+ set spellDictionaryOrder(spellDictionaryOrder) {
+ this._spellDictionaryOrder = spellDictionaryOrder;
+ }
+ get spellLanguageOrder() {
+ return this._spellLanguageOrder;
+ }
+ set spellLanguageOrder(spellLanguageOrder) {
+ this._spellLanguageOrder = spellLanguageOrder;
+ }
+ get subject() {
+ return this._subject;
+ }
+ set subject(_) {
+ throw new Error("doc.subject is read-only");
+ }
+ get templates() {
+ return [];
+ }
+ set templates(_) {
+ throw new Error("doc.templates is read-only");
+ }
+ get title() {
+ return this._title;
+ }
+ set title(_) {
+ throw new Error("doc.title is read-only");
+ }
+ get URL() {
+ return this._URL;
+ }
+ set URL(_) {
+ throw new Error("doc.URL is read-only");
+ }
+ get viewState() {
+ return undefined;
+ }
+ set viewState(_) {
+ throw new Error("doc.viewState is read-only");
+ }
+ get xfa() {
+ return this._xfa;
+ }
+ set xfa(_) {
+ throw new Error("doc.xfa is read-only");
+ }
+ get XFAForeground() {
+ return false;
+ }
+ set XFAForeground(_) {
+ throw new Error("doc.XFAForeground is read-only");
+ }
+ get zoomType() {
+ return this._zoomType;
+ }
+ set zoomType(type) {
+ if (!this._userActivation) {
+ return;
+ }
+ this._userActivation = false;
+ if (typeof type !== "string") {
+ return;
+ }
+ switch (type) {
+ case ZoomType.none:
+ this._send({
+ command: "zoom",
+ value: 1
+ });
+ break;
+ case ZoomType.fitP:
+ this._send({
+ command: "zoom",
+ value: "page-fit"
+ });
+ break;
+ case ZoomType.fitW:
+ this._send({
+ command: "zoom",
+ value: "page-width"
+ });
+ break;
+ case ZoomType.fitH:
+ this._send({
+ command: "zoom",
+ value: "page-height"
+ });
+ break;
+ case ZoomType.fitV:
+ this._send({
+ command: "zoom",
+ value: "auto"
+ });
+ break;
+ case ZoomType.pref:
+ case ZoomType.refW:
+ break;
+ default:
+ return;
+ }
+ this._zoomType = type;
+ }
+ get zoom() {
+ return this._zoom;
+ }
+ set zoom(value) {
+ if (!this._userActivation) {
+ return;
+ }
+ this._userActivation = false;
+ if (typeof value !== "number" || value < 8.33 || value > 6400) {
+ return;
+ }
+ this._send({
+ command: "zoom",
+ value: value / 100
+ });
+ }
+ addAnnot() {}
+ addField() {}
+ addIcon() {}
+ addLink() {}
+ addRecipientListCryptFilter() {}
+ addRequirement() {}
+ addScript() {}
+ addThumbnails() {}
+ addWatermarkFromFile() {}
+ addWatermarkFromText() {}
+ addWeblinks() {}
+ bringToFront() {}
+ calculateNow() {
+ this._eventDispatcher.calculateNow();
+ }
+ closeDoc() {}
+ colorConvertPage() {}
+ createDataObject() {}
+ createTemplate() {}
+ deletePages() {}
+ deleteSound() {}
+ embedDocAsDataObject() {}
+ embedOutputIntent() {}
+ encryptForRecipients() {}
+ encryptUsingPolicy() {}
+ exportAsFDF() {}
+ exportAsFDFStr() {}
+ exportAsText() {}
+ exportAsXFDF() {}
+ exportAsXFDFStr() {}
+ exportDataObject() {}
+ exportXFAData() {}
+ extractPages() {}
+ flattenPages() {}
+ getAnnot() {}
+ getAnnots() {}
+ getAnnot3D() {}
+ getAnnots3D() {}
+ getColorConvertAction() {}
+ getDataObject() {}
+ getDataObjectContents() {}
+ _getField(cName) {
+ if (cName && typeof cName === "object") {
+ cName = cName.cName;
+ }
+ if (typeof cName !== "string") {
+ throw new TypeError("Invalid field name: must be a string");
+ }
+ const searchedField = this._fields.get(cName);
+ if (searchedField) {
+ return searchedField;
+ }
+ const parts = cName.split("#");
+ let childIndex = NaN;
+ if (parts.length === 2) {
+ childIndex = Math.floor(parseFloat(parts[1]));
+ cName = parts[0];
+ }
+ for (const [name, field] of this._fields.entries()) {
+ if (name.endsWith(cName)) {
+ if (!isNaN(childIndex)) {
+ const children = this._getChildren(name);
+ if (childIndex < 0 || childIndex >= children.length) {
+ childIndex = 0;
+ }
+ if (childIndex < children.length) {
+ this._fields.set(cName, children[childIndex]);
+ return children[childIndex];
+ }
+ }
+ this._fields.set(cName, field);
+ return field;
+ }
+ }
+ return null;
+ }
+ getField(cName) {
+ const field = this._getField(cName);
+ if (!field) {
+ return null;
+ }
+ return field.wrapped;
+ }
+ _getChildren(fieldName) {
+ const len = fieldName.length;
+ const children = [];
+ const pattern = /^\.[^.]+$/;
+ for (const [name, field] of this._fields.entries()) {
+ if (name.startsWith(fieldName)) {
+ const finalPart = name.slice(len);
+ if (pattern.test(finalPart)) {
+ children.push(field);
+ }
+ }
+ }
+ return children;
+ }
+ _getTerminalChildren(fieldName) {
+ const children = [];
+ const len = fieldName.length;
+ for (const [name, field] of this._fields.entries()) {
+ if (name.startsWith(fieldName)) {
+ const finalPart = name.slice(len);
+ if (field.obj._hasValue && (finalPart === "" || finalPart.startsWith("."))) {
+ children.push(field.wrapped);
+ }
+ }
+ }
+ return children;
+ }
+ getIcon() {}
+ getLegalWarnings() {}
+ getLinks() {}
+ getNthFieldName(nIndex) {
+ if (nIndex && typeof nIndex === "object") {
+ nIndex = nIndex.nIndex;
+ }
+ if (typeof nIndex !== "number") {
+ throw new TypeError("Invalid field index: must be a number");
+ }
+ if (0 <= nIndex && nIndex < this.numFields) {
+ return this._fieldNames[Math.trunc(nIndex)];
+ }
+ return null;
+ }
+ getNthTemplate() {
+ return null;
+ }
+ getOCGs() {}
+ getOCGOrder() {}
+ getPageBox() {}
+ getPageLabel() {}
+ getPageNthWord() {}
+ getPageNthWordQuads() {}
+ getPageNumWords() {}
+ getPageRotation() {}
+ getPageTransition() {}
+ getPrintParams() {
+ return this._printParams ||= new PrintParams({
+ lastPage: this._numPages - 1
+ });
+ }
+ getSound() {}
+ getTemplate() {}
+ getURL() {}
+ gotoNamedDest() {}
+ importAnFDF() {}
+ importAnXFDF() {}
+ importDataObject() {}
+ importIcon() {}
+ importSound() {}
+ importTextData() {}
+ importXFAData() {}
+ insertPages() {}
+ mailDoc() {}
+ mailForm() {}
+ movePage() {}
+ newPage() {}
+ openDataObject() {}
+ print(bUI = true, nStart = 0, nEnd = -1, bSilent = false, bShrinkToFit = false, bPrintAsImage = false, bReverse = false, bAnnotations = true, printParams = null) {
+ if (this._disablePrinting || !this._userActivation) {
+ return;
+ }
+ this._userActivation = false;
+ if (bUI && typeof bUI === "object") {
+ nStart = bUI.nStart;
+ nEnd = bUI.nEnd;
+ bSilent = bUI.bSilent;
+ bShrinkToFit = bUI.bShrinkToFit;
+ bPrintAsImage = bUI.bPrintAsImage;
+ bReverse = bUI.bReverse;
+ bAnnotations = bUI.bAnnotations;
+ printParams = bUI.printParams;
+ bUI = bUI.bUI;
+ }
+ if (printParams) {
+ nStart = printParams.firstPage;
+ nEnd = printParams.lastPage;
+ }
+ nStart = typeof nStart === "number" ? Math.max(0, Math.trunc(nStart)) : 0;
+ nEnd = typeof nEnd === "number" ? Math.max(0, Math.trunc(nEnd)) : -1;
+ this._send({
+ command: "print",
+ start: nStart,
+ end: nEnd
+ });
+ }
+ removeDataObject() {}
+ removeField() {}
+ removeIcon() {}
+ removeLinks() {}
+ removeRequirement() {}
+ removeScript() {}
+ removeTemplate() {}
+ removeThumbnails() {}
+ removeWeblinks() {}
+ replacePages() {}
+ resetForm(aFields = null) {
+ if (aFields && typeof aFields === "object" && !Array.isArray(aFields)) {
+ aFields = aFields.aFields;
+ }
+ if (aFields && !Array.isArray(aFields)) {
+ aFields = [aFields];
+ }
+ let mustCalculate = false;
+ let fieldsToReset;
+ if (aFields) {
+ fieldsToReset = [];
+ for (const fieldName of aFields) {
+ if (!fieldName) {
+ continue;
+ }
+ if (typeof fieldName !== "string") {
+ fieldsToReset = null;
+ break;
+ }
+ const field = this._getField(fieldName);
+ if (!field) {
+ continue;
+ }
+ fieldsToReset.push(field);
+ mustCalculate = true;
+ }
+ }
+ if (!fieldsToReset) {
+ fieldsToReset = this._fields.values();
+ mustCalculate = this._fields.size !== 0;
+ }
+ for (const field of fieldsToReset) {
+ field.obj.value = field.obj.defaultValue;
+ this._send({
+ id: field.obj._id,
+ siblings: field.obj._siblings,
+ value: field.obj.defaultValue,
+ formattedValue: null,
+ selRange: [0, 0]
+ });
+ }
+ if (mustCalculate) {
+ this.calculateNow();
+ }
+ }
+ saveAs() {}
+ scroll() {}
+ selectPageNthWord() {}
+ setAction() {}
+ setDataObjectContents() {}
+ setOCGOrder() {}
+ setPageAction() {}
+ setPageBoxes() {}
+ setPageLabels() {}
+ setPageRotations() {}
+ setPageTabOrder() {}
+ setPageTransitions() {}
+ spawnPageFromTemplate() {}
+ submitForm() {}
+ syncAnnotScan() {}
+}
+
+;// CONCATENATED MODULE: ./src/scripting_api/proxy.js
+class ProxyHandler {
+ constructor() {
+ this.nosend = new Set(["delay"]);
+ }
+ get(obj, prop) {
+ if (prop in obj._expandos) {
+ const val = obj._expandos[prop];
+ if (typeof val === "function") {
+ return val.bind(obj);
+ }
+ return val;
+ }
+ if (typeof prop === "string" && !prop.startsWith("_") && prop in obj) {
+ const val = obj[prop];
+ if (typeof val === "function") {
+ return val.bind(obj);
+ }
+ return val;
+ }
+ return undefined;
+ }
+ set(obj, prop, value) {
+ if (obj._kidIds) {
+ obj._kidIds.forEach(id => {
+ obj._appObjects[id].wrapped[prop] = value;
+ });
+ }
+ if (typeof prop === "string" && !prop.startsWith("_") && prop in obj) {
+ const old = obj[prop];
+ obj[prop] = value;
+ if (!this.nosend.has(prop) && obj._send && obj._id !== null && typeof old !== "function") {
+ const data = {
+ id: obj._id
+ };
+ data[prop] = prop === "value" ? obj._getValue() : obj[prop];
+ if (!obj._siblings) {
+ obj._send(data);
+ } else {
+ data.siblings = obj._siblings;
+ obj._send(data);
+ }
+ }
+ } else {
+ obj._expandos[prop] = value;
+ }
+ return true;
+ }
+ has(obj, prop) {
+ return prop in obj._expandos || typeof prop === "string" && !prop.startsWith("_") && prop in obj;
+ }
+ getPrototypeOf(obj) {
+ return null;
+ }
+ setPrototypeOf(obj, proto) {
+ return false;
+ }
+ isExtensible(obj) {
+ return true;
+ }
+ preventExtensions(obj) {
+ return false;
+ }
+ getOwnPropertyDescriptor(obj, prop) {
+ if (prop in obj._expandos) {
+ return {
+ configurable: true,
+ enumerable: true,
+ value: obj._expandos[prop]
+ };
+ }
+ if (typeof prop === "string" && !prop.startsWith("_") && prop in obj) {
+ return {
+ configurable: true,
+ enumerable: true,
+ value: obj[prop]
+ };
+ }
+ return undefined;
+ }
+ defineProperty(obj, key, descriptor) {
+ Object.defineProperty(obj._expandos, key, descriptor);
+ return true;
+ }
+ deleteProperty(obj, prop) {
+ if (prop in obj._expandos) {
+ delete obj._expandos[prop];
+ }
+ }
+ ownKeys(obj) {
+ const fromExpandos = Reflect.ownKeys(obj._expandos);
+ const fromObj = Reflect.ownKeys(obj).filter(k => !k.startsWith("_"));
+ return fromExpandos.concat(fromObj);
+ }
+}
+
+;// CONCATENATED MODULE: ./src/scripting_api/util.js
+
+class Util extends PDFObject {
+ constructor(data) {
+ super(data);
+ this._scandCache = new Map();
+ this._months = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
+ this._days = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
+ this.MILLISECONDS_IN_DAY = 86400000;
+ this.MILLISECONDS_IN_WEEK = 604800000;
+ this._externalCall = data.externalCall;
+ }
+ printf(...args) {
+ if (args.length === 0) {
+ throw new Error("Invalid number of params in printf");
+ }
+ if (typeof args[0] !== "string") {
+ throw new TypeError("First argument of printf must be a string");
+ }
+ const pattern = /%(,[0-4])?([+ 0#]+)?(\d+)?(\.\d+)?(.)/g;
+ const PLUS = 1;
+ const SPACE = 2;
+ const ZERO = 4;
+ const HASH = 8;
+ let i = 0;
+ return args[0].replaceAll(pattern, function (match, nDecSep, cFlags, nWidth, nPrecision, cConvChar) {
+ if (cConvChar !== "d" && cConvChar !== "f" && cConvChar !== "s" && cConvChar !== "x") {
+ const buf = ["%"];
+ for (const str of [nDecSep, cFlags, nWidth, nPrecision, cConvChar]) {
+ if (str) {
+ buf.push(str);
+ }
+ }
+ return buf.join("");
+ }
+ i++;
+ if (i === args.length) {
+ throw new Error("Not enough arguments in printf");
+ }
+ const arg = args[i];
+ if (cConvChar === "s") {
+ return arg.toString();
+ }
+ let flags = 0;
+ if (cFlags) {
+ for (const flag of cFlags) {
+ switch (flag) {
+ case "+":
+ flags |= PLUS;
+ break;
+ case " ":
+ flags |= SPACE;
+ break;
+ case "0":
+ flags |= ZERO;
+ break;
+ case "#":
+ flags |= HASH;
+ break;
+ }
+ }
+ }
+ cFlags = flags;
+ if (nWidth) {
+ nWidth = parseInt(nWidth);
+ }
+ let intPart = Math.trunc(arg);
+ if (cConvChar === "x") {
+ let hex = Math.abs(intPart).toString(16).toUpperCase();
+ if (nWidth !== undefined) {
+ hex = hex.padStart(nWidth, cFlags & ZERO ? "0" : " ");
+ }
+ if (cFlags & HASH) {
+ hex = `0x${hex}`;
+ }
+ return hex;
+ }
+ if (nPrecision) {
+ nPrecision = parseInt(nPrecision.substring(1));
+ }
+ nDecSep = nDecSep ? nDecSep.substring(1) : "0";
+ const separators = {
+ 0: [",", "."],
+ 1: ["", "."],
+ 2: [".", ","],
+ 3: ["", ","],
+ 4: ["'", "."]
+ };
+ const [thousandSep, decimalSep] = separators[nDecSep];
+ let decPart = "";
+ if (cConvChar === "f") {
+ decPart = nPrecision !== undefined ? Math.abs(arg - intPart).toFixed(nPrecision) : Math.abs(arg - intPart).toString();
+ if (decPart.length > 2) {
+ decPart = `${decimalSep}${decPart.substring(2)}`;
+ } else {
+ if (decPart === "1") {
+ intPart += Math.sign(arg);
+ }
+ decPart = cFlags & HASH ? "." : "";
+ }
+ }
+ let sign = "";
+ if (intPart < 0) {
+ sign = "-";
+ intPart = -intPart;
+ } else if (cFlags & PLUS) {
+ sign = "+";
+ } else if (cFlags & SPACE) {
+ sign = " ";
+ }
+ if (thousandSep && intPart >= 1000) {
+ const buf = [];
+ while (true) {
+ buf.push((intPart % 1000).toString().padStart(3, "0"));
+ intPart = Math.trunc(intPart / 1000);
+ if (intPart < 1000) {
+ buf.push(intPart.toString());
+ break;
+ }
+ }
+ intPart = buf.reverse().join(thousandSep);
+ } else {
+ intPart = intPart.toString();
+ }
+ let n = `${intPart}${decPart}`;
+ if (nWidth !== undefined) {
+ n = n.padStart(nWidth - sign.length, cFlags & ZERO ? "0" : " ");
+ }
+ return `${sign}${n}`;
+ });
+ }
+ iconStreamFromIcon() {}
+ printd(cFormat, oDate) {
+ switch (cFormat) {
+ case 0:
+ return this.printd("D:yyyymmddHHMMss", oDate);
+ case 1:
+ return this.printd("yyyy.mm.dd HH:MM:ss", oDate);
+ case 2:
+ return this.printd("m/d/yy h:MM:ss tt", oDate);
+ }
+ const handlers = {
+ mmmm: data => this._months[data.month],
+ mmm: data => this._months[data.month].substring(0, 3),
+ mm: data => (data.month + 1).toString().padStart(2, "0"),
+ m: data => (data.month + 1).toString(),
+ dddd: data => this._days[data.dayOfWeek],
+ ddd: data => this._days[data.dayOfWeek].substring(0, 3),
+ dd: data => data.day.toString().padStart(2, "0"),
+ d: data => data.day.toString(),
+ yyyy: data => data.year.toString(),
+ yy: data => (data.year % 100).toString().padStart(2, "0"),
+ HH: data => data.hours.toString().padStart(2, "0"),
+ H: data => data.hours.toString(),
+ hh: data => (1 + (data.hours + 11) % 12).toString().padStart(2, "0"),
+ h: data => (1 + (data.hours + 11) % 12).toString(),
+ MM: data => data.minutes.toString().padStart(2, "0"),
+ M: data => data.minutes.toString(),
+ ss: data => data.seconds.toString().padStart(2, "0"),
+ s: data => data.seconds.toString(),
+ tt: data => data.hours < 12 ? "am" : "pm",
+ t: data => data.hours < 12 ? "a" : "p"
+ };
+ const data = {
+ year: oDate.getFullYear(),
+ month: oDate.getMonth(),
+ day: oDate.getDate(),
+ dayOfWeek: oDate.getDay(),
+ hours: oDate.getHours(),
+ minutes: oDate.getMinutes(),
+ seconds: oDate.getSeconds()
+ };
+ const patterns = /(mmmm|mmm|mm|m|dddd|ddd|dd|d|yyyy|yy|HH|H|hh|h|MM|M|ss|s|tt|t|\\.)/g;
+ return cFormat.replaceAll(patterns, function (match, pattern) {
+ if (pattern in handlers) {
+ return handlers[pattern](data);
+ }
+ return pattern.charCodeAt(1);
+ });
+ }
+ printx(cFormat, cSource) {
+ cSource = (cSource ?? "").toString();
+ const handlers = [x => x, x => x.toUpperCase(), x => x.toLowerCase()];
+ const buf = [];
+ let i = 0;
+ const ii = cSource.length;
+ let currCase = handlers[0];
+ let escaped = false;
+ for (const command of cFormat) {
+ if (escaped) {
+ buf.push(command);
+ escaped = false;
+ continue;
+ }
+ if (i >= ii) {
+ break;
+ }
+ switch (command) {
+ case "?":
+ buf.push(currCase(cSource.charAt(i++)));
+ break;
+ case "X":
+ while (i < ii) {
+ const char = cSource.charAt(i++);
+ if ("a" <= char && char <= "z" || "A" <= char && char <= "Z" || "0" <= char && char <= "9") {
+ buf.push(currCase(char));
+ break;
+ }
+ }
+ break;
+ case "A":
+ while (i < ii) {
+ const char = cSource.charAt(i++);
+ if ("a" <= char && char <= "z" || "A" <= char && char <= "Z") {
+ buf.push(currCase(char));
+ break;
+ }
+ }
+ break;
+ case "9":
+ while (i < ii) {
+ const char = cSource.charAt(i++);
+ if ("0" <= char && char <= "9") {
+ buf.push(char);
+ break;
+ }
+ }
+ break;
+ case "*":
+ while (i < ii) {
+ buf.push(currCase(cSource.charAt(i++)));
+ }
+ break;
+ case "\\":
+ escaped = true;
+ break;
+ case ">":
+ currCase = handlers[1];
+ break;
+ case "<":
+ currCase = handlers[2];
+ break;
+ case "=":
+ currCase = handlers[0];
+ break;
+ default:
+ buf.push(command);
+ }
+ }
+ return buf.join("");
+ }
+ scand(cFormat, cDate) {
+ if (typeof cDate !== "string") {
+ return new Date(cDate);
+ }
+ if (cDate === "") {
+ return new Date();
+ }
+ switch (cFormat) {
+ case 0:
+ return this.scand("D:yyyymmddHHMMss", cDate);
+ case 1:
+ return this.scand("yyyy.mm.dd HH:MM:ss", cDate);
+ case 2:
+ return this.scand("m/d/yy h:MM:ss tt", cDate);
+ }
+ if (!this._scandCache.has(cFormat)) {
+ const months = this._months;
+ const days = this._days;
+ const handlers = {
+ mmmm: {
+ pattern: `(${months.join("|")})`,
+ action: (value, data) => {
+ data.month = months.indexOf(value);
+ }
+ },
+ mmm: {
+ pattern: `(${months.map(month => month.substring(0, 3)).join("|")})`,
+ action: (value, data) => {
+ data.month = months.findIndex(month => month.substring(0, 3) === value);
+ }
+ },
+ mm: {
+ pattern: `(\\d{2})`,
+ action: (value, data) => {
+ data.month = parseInt(value) - 1;
+ }
+ },
+ m: {
+ pattern: `(\\d{1,2})`,
+ action: (value, data) => {
+ data.month = parseInt(value) - 1;
+ }
+ },
+ dddd: {
+ pattern: `(${days.join("|")})`,
+ action: (value, data) => {
+ data.day = days.indexOf(value);
+ }
+ },
+ ddd: {
+ pattern: `(${days.map(day => day.substring(0, 3)).join("|")})`,
+ action: (value, data) => {
+ data.day = days.findIndex(day => day.substring(0, 3) === value);
+ }
+ },
+ dd: {
+ pattern: "(\\d{2})",
+ action: (value, data) => {
+ data.day = parseInt(value);
+ }
+ },
+ d: {
+ pattern: "(\\d{1,2})",
+ action: (value, data) => {
+ data.day = parseInt(value);
+ }
+ },
+ yyyy: {
+ pattern: "(\\d{4})",
+ action: (value, data) => {
+ data.year = parseInt(value);
+ }
+ },
+ yy: {
+ pattern: "(\\d{2})",
+ action: (value, data) => {
+ data.year = 2000 + parseInt(value);
+ }
+ },
+ HH: {
+ pattern: "(\\d{2})",
+ action: (value, data) => {
+ data.hours = parseInt(value);
+ }
+ },
+ H: {
+ pattern: "(\\d{1,2})",
+ action: (value, data) => {
+ data.hours = parseInt(value);
+ }
+ },
+ hh: {
+ pattern: "(\\d{2})",
+ action: (value, data) => {
+ data.hours = parseInt(value);
+ }
+ },
+ h: {
+ pattern: "(\\d{1,2})",
+ action: (value, data) => {
+ data.hours = parseInt(value);
+ }
+ },
+ MM: {
+ pattern: "(\\d{2})",
+ action: (value, data) => {
+ data.minutes = parseInt(value);
+ }
+ },
+ M: {
+ pattern: "(\\d{1,2})",
+ action: (value, data) => {
+ data.minutes = parseInt(value);
+ }
+ },
+ ss: {
+ pattern: "(\\d{2})",
+ action: (value, data) => {
+ data.seconds = parseInt(value);
+ }
+ },
+ s: {
+ pattern: "(\\d{1,2})",
+ action: (value, data) => {
+ data.seconds = parseInt(value);
+ }
+ },
+ tt: {
+ pattern: "([aApP][mM])",
+ action: (value, data) => {
+ const char = value.charAt(0);
+ data.am = char === "a" || char === "A";
+ }
+ },
+ t: {
+ pattern: "([aApP])",
+ action: (value, data) => {
+ data.am = value === "a" || value === "A";
+ }
+ }
+ };
+ const escapedFormat = cFormat.replaceAll(/[.*+\-?^${}()|[\]\\]/g, "\\$&");
+ const patterns = /(mmmm|mmm|mm|m|dddd|ddd|dd|d|yyyy|yy|HH|H|hh|h|MM|M|ss|s|tt|t)/g;
+ const actions = [];
+ const re = escapedFormat.replaceAll(patterns, function (match, patternElement) {
+ const {
+ pattern,
+ action
+ } = handlers[patternElement];
+ actions.push(action);
+ return pattern;
+ });
+ this._scandCache.set(cFormat, [re, actions]);
+ }
+ const [re, actions] = this._scandCache.get(cFormat);
+ const matches = new RegExp(`^${re}$`, "g").exec(cDate);
+ if (!matches || matches.length !== actions.length + 1) {
+ return null;
+ }
+ const data = {
+ year: 2000,
+ month: 0,
+ day: 1,
+ hours: 0,
+ minutes: 0,
+ seconds: 0,
+ am: null
+ };
+ actions.forEach((action, i) => action(matches[i + 1], data));
+ if (data.am !== null) {
+ data.hours = data.hours % 12 + (data.am ? 0 : 12);
+ }
+ return new Date(data.year, data.month, data.day, data.hours, data.minutes, data.seconds);
+ }
+ spansToXML() {}
+ stringFromStream() {}
+ xmlToSpans() {}
+}
+
+;// CONCATENATED MODULE: ./src/scripting_api/initialization.js
+
+
+
+
+
+
+
+
+
+
+function initSandbox(params) {
+ delete globalThis.pdfjsScripting;
+ const externalCall = globalThis.callExternalFunction;
+ delete globalThis.callExternalFunction;
+ const globalEval = code => globalThis.eval(code);
+ const send = data => externalCall("send", [data]);
+ const proxyHandler = new ProxyHandler();
+ const {
+ data
+ } = params;
+ const doc = new Doc({
+ send,
+ globalEval,
+ ...data.docInfo
+ });
+ const _document = {
+ obj: doc,
+ wrapped: new Proxy(doc, proxyHandler)
+ };
+ const app = new App({
+ send,
+ globalEval,
+ externalCall,
+ _document,
+ calculationOrder: data.calculationOrder,
+ proxyHandler,
+ ...data.appInfo
+ });
+ const util = new Util({
+ externalCall
+ });
+ const appObjects = app._objects;
+ if (data.objects) {
+ const annotations = [];
+ for (const [name, objs] of Object.entries(data.objects)) {
+ annotations.length = 0;
+ let container = null;
+ for (const obj of objs) {
+ if (obj.type !== "") {
+ annotations.push(obj);
+ } else {
+ container = obj;
+ }
+ }
+ let obj = container;
+ if (annotations.length > 0) {
+ obj = annotations[0];
+ obj.send = send;
+ }
+ obj.globalEval = globalEval;
+ obj.doc = _document;
+ obj.fieldPath = name;
+ obj.appObjects = appObjects;
+ let field;
+ switch (obj.type) {
+ case "radiobutton":
+ {
+ const otherButtons = annotations.slice(1);
+ field = new RadioButtonField(otherButtons, obj);
+ break;
+ }
+ case "checkbox":
+ {
+ const otherButtons = annotations.slice(1);
+ field = new CheckboxField(otherButtons, obj);
+ break;
+ }
+ case "text":
+ if (annotations.length <= 1) {
+ field = new Field(obj);
+ break;
+ }
+ obj.siblings = annotations.map(x => x.id).slice(1);
+ field = new Field(obj);
+ break;
+ default:
+ field = new Field(obj);
+ }
+ const wrapped = new Proxy(field, proxyHandler);
+ const _object = {
+ obj: field,
+ wrapped
+ };
+ doc._addField(name, _object);
+ for (const object of objs) {
+ appObjects[object.id] = _object;
+ }
+ if (container) {
+ appObjects[container.id] = _object;
+ }
+ }
+ }
+ const color = new Color();
+ globalThis.event = null;
+ globalThis.global = Object.create(null);
+ globalThis.app = new Proxy(app, proxyHandler);
+ globalThis.color = new Proxy(color, proxyHandler);
+ globalThis.console = new Proxy(new Console({
+ send
+ }), proxyHandler);
+ globalThis.util = new Proxy(util, proxyHandler);
+ globalThis.border = Border;
+ globalThis.cursor = Cursor;
+ globalThis.display = Display;
+ globalThis.font = Font;
+ globalThis.highlight = Highlight;
+ globalThis.position = Position;
+ globalThis.scaleHow = ScaleHow;
+ globalThis.scaleWhen = ScaleWhen;
+ globalThis.style = Style;
+ globalThis.trans = Trans;
+ globalThis.zoomtype = ZoomType;
+ globalThis.ADBE = {
+ Reader_Value_Asked: true,
+ Viewer_Value_Asked: true
+ };
+ const aform = new AForm(doc, app, util, color);
+ for (const name of Object.getOwnPropertyNames(AForm.prototype)) {
+ if (name !== "constructor" && !name.startsWith("_")) {
+ globalThis[name] = aform[name].bind(aform);
+ }
+ }
+ for (const [name, value] of Object.entries(GlobalConstants)) {
+ Object.defineProperty(globalThis, name, {
+ value,
+ writable: false
+ });
+ }
+ Object.defineProperties(globalThis, {
+ ColorConvert: {
+ value: color.convert.bind(color),
+ writable: true
+ },
+ ColorEqual: {
+ value: color.equal.bind(color),
+ writable: true
+ }
+ });
+ const properties = Object.create(null);
+ for (const name of Object.getOwnPropertyNames(Doc.prototype)) {
+ if (name === "constructor" || name.startsWith("_")) {
+ continue;
+ }
+ const descriptor = Object.getOwnPropertyDescriptor(Doc.prototype, name);
+ if (descriptor.get) {
+ properties[name] = {
+ get: descriptor.get.bind(doc),
+ set: descriptor.set.bind(doc)
+ };
+ } else {
+ properties[name] = {
+ value: Doc.prototype[name].bind(doc)
+ };
+ }
+ }
+ Object.defineProperties(globalThis, properties);
+ const functions = {
+ dispatchEvent: app._dispatchEvent.bind(app),
+ timeoutCb: app._evalCallback.bind(app)
+ };
+ return (name, args) => {
+ try {
+ functions[name](args);
+ } catch (error) {
+ send(serializeError(error));
+ }
+ };
+}
+
+;// CONCATENATED MODULE: ./src/pdf.scripting.js
+
+const pdfjsVersion = "4.1.249";
+const pdfjsBuild = "d07f37f44";
+globalThis.pdfjsScripting = {
+ initSandbox: initSandbox
+};
diff --git a/toolkit/components/pdfjs/content/build/pdf.worker.mjs b/toolkit/components/pdfjs/content/build/pdf.worker.mjs
new file mode 100644
index 0000000000..8929572511
--- /dev/null
+++ b/toolkit/components/pdfjs/content/build/pdf.worker.mjs
@@ -0,0 +1,57228 @@
+/**
+ * @licstart The following is the entire license notice for the
+ * JavaScript code in this page
+ *
+ * Copyright 2023 Mozilla Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * @licend The above is the entire license notice for the
+ * JavaScript code in this page
+ */
+
+/******/ // The require scope
+/******/ var __webpack_require__ = {};
+/******/
+/************************************************************************/
+/******/ /* webpack/runtime/define property getters */
+/******/ (() => {
+/******/ // define getter functions for harmony exports
+/******/ __webpack_require__.d = (exports, definition) => {
+/******/ for(var key in definition) {
+/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
+/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
+/******/ }
+/******/ }
+/******/ };
+/******/ })();
+/******/
+/******/ /* webpack/runtime/hasOwnProperty shorthand */
+/******/ (() => {
+/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
+/******/ })();
+/******/
+/************************************************************************/
+var __webpack_exports__ = globalThis.pdfjsWorker = {};
+
+// EXPORTS
+__webpack_require__.d(__webpack_exports__, {
+ WorkerMessageHandler: () => (/* reexport */ WorkerMessageHandler)
+});
+
+;// CONCATENATED MODULE: ./src/shared/util.js
+const isNodeJS = false;
+const IDENTITY_MATRIX = [1, 0, 0, 1, 0, 0];
+const FONT_IDENTITY_MATRIX = [0.001, 0, 0, 0.001, 0, 0];
+const MAX_IMAGE_SIZE_TO_CACHE = 10e6;
+const LINE_FACTOR = 1.35;
+const LINE_DESCENT_FACTOR = 0.35;
+const BASELINE_FACTOR = LINE_DESCENT_FACTOR / LINE_FACTOR;
+const RenderingIntentFlag = {
+ ANY: 0x01,
+ DISPLAY: 0x02,
+ PRINT: 0x04,
+ SAVE: 0x08,
+ ANNOTATIONS_FORMS: 0x10,
+ ANNOTATIONS_STORAGE: 0x20,
+ ANNOTATIONS_DISABLE: 0x40,
+ OPLIST: 0x100
+};
+const AnnotationMode = {
+ DISABLE: 0,
+ ENABLE: 1,
+ ENABLE_FORMS: 2,
+ ENABLE_STORAGE: 3
+};
+const AnnotationEditorPrefix = "pdfjs_internal_editor_";
+const AnnotationEditorType = {
+ DISABLE: -1,
+ NONE: 0,
+ FREETEXT: 3,
+ HIGHLIGHT: 9,
+ STAMP: 13,
+ INK: 15
+};
+const AnnotationEditorParamsType = {
+ RESIZE: 1,
+ CREATE: 2,
+ FREETEXT_SIZE: 11,
+ FREETEXT_COLOR: 12,
+ FREETEXT_OPACITY: 13,
+ INK_COLOR: 21,
+ INK_THICKNESS: 22,
+ INK_OPACITY: 23,
+ HIGHLIGHT_COLOR: 31,
+ HIGHLIGHT_DEFAULT_COLOR: 32,
+ HIGHLIGHT_THICKNESS: 33,
+ HIGHLIGHT_FREE: 34
+};
+const PermissionFlag = {
+ PRINT: 0x04,
+ MODIFY_CONTENTS: 0x08,
+ COPY: 0x10,
+ MODIFY_ANNOTATIONS: 0x20,
+ FILL_INTERACTIVE_FORMS: 0x100,
+ COPY_FOR_ACCESSIBILITY: 0x200,
+ ASSEMBLE: 0x400,
+ PRINT_HIGH_QUALITY: 0x800
+};
+const TextRenderingMode = {
+ FILL: 0,
+ STROKE: 1,
+ FILL_STROKE: 2,
+ INVISIBLE: 3,
+ FILL_ADD_TO_PATH: 4,
+ STROKE_ADD_TO_PATH: 5,
+ FILL_STROKE_ADD_TO_PATH: 6,
+ ADD_TO_PATH: 7,
+ FILL_STROKE_MASK: 3,
+ ADD_TO_PATH_FLAG: 4
+};
+const ImageKind = {
+ GRAYSCALE_1BPP: 1,
+ RGB_24BPP: 2,
+ RGBA_32BPP: 3
+};
+const AnnotationType = {
+ TEXT: 1,
+ LINK: 2,
+ FREETEXT: 3,
+ LINE: 4,
+ SQUARE: 5,
+ CIRCLE: 6,
+ POLYGON: 7,
+ POLYLINE: 8,
+ HIGHLIGHT: 9,
+ UNDERLINE: 10,
+ SQUIGGLY: 11,
+ STRIKEOUT: 12,
+ STAMP: 13,
+ CARET: 14,
+ INK: 15,
+ POPUP: 16,
+ FILEATTACHMENT: 17,
+ SOUND: 18,
+ MOVIE: 19,
+ WIDGET: 20,
+ SCREEN: 21,
+ PRINTERMARK: 22,
+ TRAPNET: 23,
+ WATERMARK: 24,
+ THREED: 25,
+ REDACT: 26
+};
+const AnnotationReplyType = {
+ GROUP: "Group",
+ REPLY: "R"
+};
+const AnnotationFlag = {
+ INVISIBLE: 0x01,
+ HIDDEN: 0x02,
+ PRINT: 0x04,
+ NOZOOM: 0x08,
+ NOROTATE: 0x10,
+ NOVIEW: 0x20,
+ READONLY: 0x40,
+ LOCKED: 0x80,
+ TOGGLENOVIEW: 0x100,
+ LOCKEDCONTENTS: 0x200
+};
+const AnnotationFieldFlag = {
+ READONLY: 0x0000001,
+ REQUIRED: 0x0000002,
+ NOEXPORT: 0x0000004,
+ MULTILINE: 0x0001000,
+ PASSWORD: 0x0002000,
+ NOTOGGLETOOFF: 0x0004000,
+ RADIO: 0x0008000,
+ PUSHBUTTON: 0x0010000,
+ COMBO: 0x0020000,
+ EDIT: 0x0040000,
+ SORT: 0x0080000,
+ FILESELECT: 0x0100000,
+ MULTISELECT: 0x0200000,
+ DONOTSPELLCHECK: 0x0400000,
+ DONOTSCROLL: 0x0800000,
+ COMB: 0x1000000,
+ RICHTEXT: 0x2000000,
+ RADIOSINUNISON: 0x2000000,
+ COMMITONSELCHANGE: 0x4000000
+};
+const AnnotationBorderStyleType = {
+ SOLID: 1,
+ DASHED: 2,
+ BEVELED: 3,
+ INSET: 4,
+ UNDERLINE: 5
+};
+const AnnotationActionEventType = {
+ E: "Mouse Enter",
+ X: "Mouse Exit",
+ D: "Mouse Down",
+ U: "Mouse Up",
+ Fo: "Focus",
+ Bl: "Blur",
+ PO: "PageOpen",
+ PC: "PageClose",
+ PV: "PageVisible",
+ PI: "PageInvisible",
+ K: "Keystroke",
+ F: "Format",
+ V: "Validate",
+ C: "Calculate"
+};
+const DocumentActionEventType = {
+ WC: "WillClose",
+ WS: "WillSave",
+ DS: "DidSave",
+ WP: "WillPrint",
+ DP: "DidPrint"
+};
+const PageActionEventType = {
+ O: "PageOpen",
+ C: "PageClose"
+};
+const VerbosityLevel = {
+ ERRORS: 0,
+ WARNINGS: 1,
+ INFOS: 5
+};
+const CMapCompressionType = {
+ NONE: 0,
+ BINARY: 1
+};
+const OPS = {
+ dependency: 1,
+ setLineWidth: 2,
+ setLineCap: 3,
+ setLineJoin: 4,
+ setMiterLimit: 5,
+ setDash: 6,
+ setRenderingIntent: 7,
+ setFlatness: 8,
+ setGState: 9,
+ save: 10,
+ restore: 11,
+ transform: 12,
+ moveTo: 13,
+ lineTo: 14,
+ curveTo: 15,
+ curveTo2: 16,
+ curveTo3: 17,
+ closePath: 18,
+ rectangle: 19,
+ stroke: 20,
+ closeStroke: 21,
+ fill: 22,
+ eoFill: 23,
+ fillStroke: 24,
+ eoFillStroke: 25,
+ closeFillStroke: 26,
+ closeEOFillStroke: 27,
+ endPath: 28,
+ clip: 29,
+ eoClip: 30,
+ beginText: 31,
+ endText: 32,
+ setCharSpacing: 33,
+ setWordSpacing: 34,
+ setHScale: 35,
+ setLeading: 36,
+ setFont: 37,
+ setTextRenderingMode: 38,
+ setTextRise: 39,
+ moveText: 40,
+ setLeadingMoveText: 41,
+ setTextMatrix: 42,
+ nextLine: 43,
+ showText: 44,
+ showSpacedText: 45,
+ nextLineShowText: 46,
+ nextLineSetSpacingShowText: 47,
+ setCharWidth: 48,
+ setCharWidthAndBounds: 49,
+ setStrokeColorSpace: 50,
+ setFillColorSpace: 51,
+ setStrokeColor: 52,
+ setStrokeColorN: 53,
+ setFillColor: 54,
+ setFillColorN: 55,
+ setStrokeGray: 56,
+ setFillGray: 57,
+ setStrokeRGBColor: 58,
+ setFillRGBColor: 59,
+ setStrokeCMYKColor: 60,
+ setFillCMYKColor: 61,
+ shadingFill: 62,
+ beginInlineImage: 63,
+ beginImageData: 64,
+ endInlineImage: 65,
+ paintXObject: 66,
+ markPoint: 67,
+ markPointProps: 68,
+ beginMarkedContent: 69,
+ beginMarkedContentProps: 70,
+ endMarkedContent: 71,
+ beginCompat: 72,
+ endCompat: 73,
+ paintFormXObjectBegin: 74,
+ paintFormXObjectEnd: 75,
+ beginGroup: 76,
+ endGroup: 77,
+ beginAnnotation: 80,
+ endAnnotation: 81,
+ paintImageMaskXObject: 83,
+ paintImageMaskXObjectGroup: 84,
+ paintImageXObject: 85,
+ paintInlineImageXObject: 86,
+ paintInlineImageXObjectGroup: 87,
+ paintImageXObjectRepeat: 88,
+ paintImageMaskXObjectRepeat: 89,
+ paintSolidColorImageMask: 90,
+ constructPath: 91
+};
+const PasswordResponses = {
+ NEED_PASSWORD: 1,
+ INCORRECT_PASSWORD: 2
+};
+let verbosity = VerbosityLevel.WARNINGS;
+function setVerbosityLevel(level) {
+ if (Number.isInteger(level)) {
+ verbosity = level;
+ }
+}
+function getVerbosityLevel() {
+ return verbosity;
+}
+function info(msg) {
+ if (verbosity >= VerbosityLevel.INFOS) {
+ console.log(`Info: ${msg}`);
+ }
+}
+function warn(msg) {
+ if (verbosity >= VerbosityLevel.WARNINGS) {
+ console.log(`Warning: ${msg}`);
+ }
+}
+function unreachable(msg) {
+ throw new Error(msg);
+}
+function assert(cond, msg) {
+ if (!cond) {
+ unreachable(msg);
+ }
+}
+function _isValidProtocol(url) {
+ switch (url?.protocol) {
+ case "http:":
+ case "https:":
+ case "ftp:":
+ case "mailto:":
+ case "tel:":
+ return true;
+ default:
+ return false;
+ }
+}
+function createValidAbsoluteUrl(url, baseUrl = null, options = null) {
+ if (!url) {
+ return null;
+ }
+ try {
+ if (options && typeof url === "string") {
+ if (options.addDefaultProtocol && url.startsWith("www.")) {
+ const dots = url.match(/\./g);
+ if (dots?.length >= 2) {
+ url = `http://${url}`;
+ }
+ }
+ if (options.tryConvertEncoding) {
+ try {
+ url = stringToUTF8String(url);
+ } catch {}
+ }
+ }
+ const absoluteUrl = baseUrl ? new URL(url, baseUrl) : new URL(url);
+ if (_isValidProtocol(absoluteUrl)) {
+ return absoluteUrl;
+ }
+ } catch {}
+ return null;
+}
+function shadow(obj, prop, value, nonSerializable = false) {
+ Object.defineProperty(obj, prop, {
+ value,
+ enumerable: !nonSerializable,
+ configurable: true,
+ writable: false
+ });
+ return value;
+}
+const BaseException = function BaseExceptionClosure() {
+ function BaseException(message, name) {
+ if (this.constructor === BaseException) {
+ unreachable("Cannot initialize BaseException.");
+ }
+ this.message = message;
+ this.name = name;
+ }
+ BaseException.prototype = new Error();
+ BaseException.constructor = BaseException;
+ return BaseException;
+}();
+class PasswordException extends BaseException {
+ constructor(msg, code) {
+ super(msg, "PasswordException");
+ this.code = code;
+ }
+}
+class UnknownErrorException extends BaseException {
+ constructor(msg, details) {
+ super(msg, "UnknownErrorException");
+ this.details = details;
+ }
+}
+class InvalidPDFException extends BaseException {
+ constructor(msg) {
+ super(msg, "InvalidPDFException");
+ }
+}
+class MissingPDFException extends BaseException {
+ constructor(msg) {
+ super(msg, "MissingPDFException");
+ }
+}
+class UnexpectedResponseException extends BaseException {
+ constructor(msg, status) {
+ super(msg, "UnexpectedResponseException");
+ this.status = status;
+ }
+}
+class FormatError extends BaseException {
+ constructor(msg) {
+ super(msg, "FormatError");
+ }
+}
+class AbortException extends BaseException {
+ constructor(msg) {
+ super(msg, "AbortException");
+ }
+}
+function bytesToString(bytes) {
+ if (typeof bytes !== "object" || bytes?.length === undefined) {
+ unreachable("Invalid argument for bytesToString");
+ }
+ const length = bytes.length;
+ const MAX_ARGUMENT_COUNT = 8192;
+ if (length < MAX_ARGUMENT_COUNT) {
+ return String.fromCharCode.apply(null, bytes);
+ }
+ const strBuf = [];
+ for (let i = 0; i < length; i += MAX_ARGUMENT_COUNT) {
+ const chunkEnd = Math.min(i + MAX_ARGUMENT_COUNT, length);
+ const chunk = bytes.subarray(i, chunkEnd);
+ strBuf.push(String.fromCharCode.apply(null, chunk));
+ }
+ return strBuf.join("");
+}
+function stringToBytes(str) {
+ if (typeof str !== "string") {
+ unreachable("Invalid argument for stringToBytes");
+ }
+ const length = str.length;
+ const bytes = new Uint8Array(length);
+ for (let i = 0; i < length; ++i) {
+ bytes[i] = str.charCodeAt(i) & 0xff;
+ }
+ return bytes;
+}
+function string32(value) {
+ return String.fromCharCode(value >> 24 & 0xff, value >> 16 & 0xff, value >> 8 & 0xff, value & 0xff);
+}
+function objectSize(obj) {
+ return Object.keys(obj).length;
+}
+function objectFromMap(map) {
+ const obj = Object.create(null);
+ for (const [key, value] of map) {
+ obj[key] = value;
+ }
+ return obj;
+}
+function isLittleEndian() {
+ const buffer8 = new Uint8Array(4);
+ buffer8[0] = 1;
+ const view32 = new Uint32Array(buffer8.buffer, 0, 1);
+ return view32[0] === 1;
+}
+function isEvalSupported() {
+ try {
+ new Function("");
+ return true;
+ } catch {
+ return false;
+ }
+}
+class FeatureTest {
+ static get isLittleEndian() {
+ return shadow(this, "isLittleEndian", isLittleEndian());
+ }
+ static get isEvalSupported() {
+ return shadow(this, "isEvalSupported", isEvalSupported());
+ }
+ static get isOffscreenCanvasSupported() {
+ return shadow(this, "isOffscreenCanvasSupported", typeof OffscreenCanvas !== "undefined");
+ }
+ static get platform() {
+ return shadow(this, "platform", {
+ isMac: navigator.platform.includes("Mac")
+ });
+ }
+ static get isCSSRoundSupported() {
+ return shadow(this, "isCSSRoundSupported", globalThis.CSS?.supports?.("width: round(1.5px, 1px)"));
+ }
+}
+const hexNumbers = Array.from(Array(256).keys(), n => n.toString(16).padStart(2, "0"));
+class Util {
+ static makeHexColor(r, g, b) {
+ return `#${hexNumbers[r]}${hexNumbers[g]}${hexNumbers[b]}`;
+ }
+ static scaleMinMax(transform, minMax) {
+ let temp;
+ if (transform[0]) {
+ if (transform[0] < 0) {
+ temp = minMax[0];
+ minMax[0] = minMax[2];
+ minMax[2] = temp;
+ }
+ minMax[0] *= transform[0];
+ minMax[2] *= transform[0];
+ if (transform[3] < 0) {
+ temp = minMax[1];
+ minMax[1] = minMax[3];
+ minMax[3] = temp;
+ }
+ minMax[1] *= transform[3];
+ minMax[3] *= transform[3];
+ } else {
+ temp = minMax[0];
+ minMax[0] = minMax[1];
+ minMax[1] = temp;
+ temp = minMax[2];
+ minMax[2] = minMax[3];
+ minMax[3] = temp;
+ if (transform[1] < 0) {
+ temp = minMax[1];
+ minMax[1] = minMax[3];
+ minMax[3] = temp;
+ }
+ minMax[1] *= transform[1];
+ minMax[3] *= transform[1];
+ if (transform[2] < 0) {
+ temp = minMax[0];
+ minMax[0] = minMax[2];
+ minMax[2] = temp;
+ }
+ minMax[0] *= transform[2];
+ minMax[2] *= transform[2];
+ }
+ minMax[0] += transform[4];
+ minMax[1] += transform[5];
+ minMax[2] += transform[4];
+ minMax[3] += transform[5];
+ }
+ static transform(m1, m2) {
+ return [m1[0] * m2[0] + m1[2] * m2[1], m1[1] * m2[0] + m1[3] * m2[1], m1[0] * m2[2] + m1[2] * m2[3], m1[1] * m2[2] + m1[3] * m2[3], m1[0] * m2[4] + m1[2] * m2[5] + m1[4], m1[1] * m2[4] + m1[3] * m2[5] + m1[5]];
+ }
+ static applyTransform(p, m) {
+ const xt = p[0] * m[0] + p[1] * m[2] + m[4];
+ const yt = p[0] * m[1] + p[1] * m[3] + m[5];
+ return [xt, yt];
+ }
+ static applyInverseTransform(p, m) {
+ const d = m[0] * m[3] - m[1] * m[2];
+ const xt = (p[0] * m[3] - p[1] * m[2] + m[2] * m[5] - m[4] * m[3]) / d;
+ const yt = (-p[0] * m[1] + p[1] * m[0] + m[4] * m[1] - m[5] * m[0]) / d;
+ return [xt, yt];
+ }
+ static getAxialAlignedBoundingBox(r, m) {
+ const p1 = this.applyTransform(r, m);
+ const p2 = this.applyTransform(r.slice(2, 4), m);
+ const p3 = this.applyTransform([r[0], r[3]], m);
+ const p4 = this.applyTransform([r[2], r[1]], m);
+ return [Math.min(p1[0], p2[0], p3[0], p4[0]), Math.min(p1[1], p2[1], p3[1], p4[1]), Math.max(p1[0], p2[0], p3[0], p4[0]), Math.max(p1[1], p2[1], p3[1], p4[1])];
+ }
+ static inverseTransform(m) {
+ const d = m[0] * m[3] - m[1] * m[2];
+ return [m[3] / d, -m[1] / d, -m[2] / d, m[0] / d, (m[2] * m[5] - m[4] * m[3]) / d, (m[4] * m[1] - m[5] * m[0]) / d];
+ }
+ static singularValueDecompose2dScale(m) {
+ const transpose = [m[0], m[2], m[1], m[3]];
+ const a = m[0] * transpose[0] + m[1] * transpose[2];
+ const b = m[0] * transpose[1] + m[1] * transpose[3];
+ const c = m[2] * transpose[0] + m[3] * transpose[2];
+ const d = m[2] * transpose[1] + m[3] * transpose[3];
+ const first = (a + d) / 2;
+ const second = Math.sqrt((a + d) ** 2 - 4 * (a * d - c * b)) / 2;
+ const sx = first + second || 1;
+ const sy = first - second || 1;
+ return [Math.sqrt(sx), Math.sqrt(sy)];
+ }
+ static normalizeRect(rect) {
+ const r = rect.slice(0);
+ if (rect[0] > rect[2]) {
+ r[0] = rect[2];
+ r[2] = rect[0];
+ }
+ if (rect[1] > rect[3]) {
+ r[1] = rect[3];
+ r[3] = rect[1];
+ }
+ return r;
+ }
+ static intersect(rect1, rect2) {
+ const xLow = Math.max(Math.min(rect1[0], rect1[2]), Math.min(rect2[0], rect2[2]));
+ const xHigh = Math.min(Math.max(rect1[0], rect1[2]), Math.max(rect2[0], rect2[2]));
+ if (xLow > xHigh) {
+ return null;
+ }
+ const yLow = Math.max(Math.min(rect1[1], rect1[3]), Math.min(rect2[1], rect2[3]));
+ const yHigh = Math.min(Math.max(rect1[1], rect1[3]), Math.max(rect2[1], rect2[3]));
+ if (yLow > yHigh) {
+ return null;
+ }
+ return [xLow, yLow, xHigh, yHigh];
+ }
+ static #getExtremumOnCurve(x0, x1, x2, x3, y0, y1, y2, y3, t, minMax) {
+ if (t <= 0 || t >= 1) {
+ return;
+ }
+ const mt = 1 - t;
+ const tt = t * t;
+ const ttt = tt * t;
+ const x = mt * (mt * (mt * x0 + 3 * t * x1) + 3 * tt * x2) + ttt * x3;
+ const y = mt * (mt * (mt * y0 + 3 * t * y1) + 3 * tt * y2) + ttt * y3;
+ minMax[0] = Math.min(minMax[0], x);
+ minMax[1] = Math.min(minMax[1], y);
+ minMax[2] = Math.max(minMax[2], x);
+ minMax[3] = Math.max(minMax[3], y);
+ }
+ static #getExtremum(x0, x1, x2, x3, y0, y1, y2, y3, a, b, c, minMax) {
+ if (Math.abs(a) < 1e-12) {
+ if (Math.abs(b) >= 1e-12) {
+ this.#getExtremumOnCurve(x0, x1, x2, x3, y0, y1, y2, y3, -c / b, minMax);
+ }
+ return;
+ }
+ const delta = b ** 2 - 4 * c * a;
+ if (delta < 0) {
+ return;
+ }
+ const sqrtDelta = Math.sqrt(delta);
+ const a2 = 2 * a;
+ this.#getExtremumOnCurve(x0, x1, x2, x3, y0, y1, y2, y3, (-b + sqrtDelta) / a2, minMax);
+ this.#getExtremumOnCurve(x0, x1, x2, x3, y0, y1, y2, y3, (-b - sqrtDelta) / a2, minMax);
+ }
+ static bezierBoundingBox(x0, y0, x1, y1, x2, y2, x3, y3, minMax) {
+ if (minMax) {
+ minMax[0] = Math.min(minMax[0], x0, x3);
+ minMax[1] = Math.min(minMax[1], y0, y3);
+ minMax[2] = Math.max(minMax[2], x0, x3);
+ minMax[3] = Math.max(minMax[3], y0, y3);
+ } else {
+ minMax = [Math.min(x0, x3), Math.min(y0, y3), Math.max(x0, x3), Math.max(y0, y3)];
+ }
+ this.#getExtremum(x0, x1, x2, x3, y0, y1, y2, y3, 3 * (-x0 + 3 * (x1 - x2) + x3), 6 * (x0 - 2 * x1 + x2), 3 * (x1 - x0), minMax);
+ this.#getExtremum(x0, x1, x2, x3, y0, y1, y2, y3, 3 * (-y0 + 3 * (y1 - y2) + y3), 6 * (y0 - 2 * y1 + y2), 3 * (y1 - y0), minMax);
+ return minMax;
+ }
+}
+const PDFStringTranslateTable = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x2d8, 0x2c7, 0x2c6, 0x2d9, 0x2dd, 0x2db, 0x2da, 0x2dc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x2022, 0x2020, 0x2021, 0x2026, 0x2014, 0x2013, 0x192, 0x2044, 0x2039, 0x203a, 0x2212, 0x2030, 0x201e, 0x201c, 0x201d, 0x2018, 0x2019, 0x201a, 0x2122, 0xfb01, 0xfb02, 0x141, 0x152, 0x160, 0x178, 0x17d, 0x131, 0x142, 0x153, 0x161, 0x17e, 0, 0x20ac];
+function stringToPDFString(str) {
+ if (str[0] >= "\xEF") {
+ let encoding;
+ if (str[0] === "\xFE" && str[1] === "\xFF") {
+ encoding = "utf-16be";
+ if (str.length % 2 === 1) {
+ str = str.slice(0, -1);
+ }
+ } else if (str[0] === "\xFF" && str[1] === "\xFE") {
+ encoding = "utf-16le";
+ if (str.length % 2 === 1) {
+ str = str.slice(0, -1);
+ }
+ } else if (str[0] === "\xEF" && str[1] === "\xBB" && str[2] === "\xBF") {
+ encoding = "utf-8";
+ }
+ if (encoding) {
+ try {
+ const decoder = new TextDecoder(encoding, {
+ fatal: true
+ });
+ const buffer = stringToBytes(str);
+ const decoded = decoder.decode(buffer);
+ if (!decoded.includes("\x1b")) {
+ return decoded;
+ }
+ return decoded.replaceAll(/\x1b[^\x1b]*(?:\x1b|$)/g, "");
+ } catch (ex) {
+ warn(`stringToPDFString: "${ex}".`);
+ }
+ }
+ }
+ const strBuf = [];
+ for (let i = 0, ii = str.length; i < ii; i++) {
+ const charCode = str.charCodeAt(i);
+ if (charCode === 0x1b) {
+ while (++i < ii && str.charCodeAt(i) !== 0x1b) {}
+ continue;
+ }
+ const code = PDFStringTranslateTable[charCode];
+ strBuf.push(code ? String.fromCharCode(code) : str.charAt(i));
+ }
+ return strBuf.join("");
+}
+function stringToUTF8String(str) {
+ return decodeURIComponent(escape(str));
+}
+function utf8StringToString(str) {
+ return unescape(encodeURIComponent(str));
+}
+function isArrayEqual(arr1, arr2) {
+ if (arr1.length !== arr2.length) {
+ return false;
+ }
+ for (let i = 0, ii = arr1.length; i < ii; i++) {
+ if (arr1[i] !== arr2[i]) {
+ return false;
+ }
+ }
+ return true;
+}
+function getModificationDate(date = new Date()) {
+ const buffer = [date.getUTCFullYear().toString(), (date.getUTCMonth() + 1).toString().padStart(2, "0"), date.getUTCDate().toString().padStart(2, "0"), date.getUTCHours().toString().padStart(2, "0"), date.getUTCMinutes().toString().padStart(2, "0"), date.getUTCSeconds().toString().padStart(2, "0")];
+ return buffer.join("");
+}
+class PromiseCapability {
+ #settled = false;
+ constructor() {
+ this.promise = new Promise((resolve, reject) => {
+ this.resolve = data => {
+ this.#settled = true;
+ resolve(data);
+ };
+ this.reject = reason => {
+ this.#settled = true;
+ reject(reason);
+ };
+ });
+ }
+ get settled() {
+ return this.#settled;
+ }
+}
+let NormalizeRegex = null;
+let NormalizationMap = null;
+function normalizeUnicode(str) {
+ if (!NormalizeRegex) {
+ NormalizeRegex = /([\u00a0\u00b5\u037e\u0eb3\u2000-\u200a\u202f\u2126\ufb00-\ufb04\ufb06\ufb20-\ufb36\ufb38-\ufb3c\ufb3e\ufb40-\ufb41\ufb43-\ufb44\ufb46-\ufba1\ufba4-\ufba9\ufbae-\ufbb1\ufbd3-\ufbdc\ufbde-\ufbe7\ufbea-\ufbf8\ufbfc-\ufbfd\ufc00-\ufc5d\ufc64-\ufcf1\ufcf5-\ufd3d\ufd88\ufdf4\ufdfa-\ufdfb\ufe71\ufe77\ufe79\ufe7b\ufe7d]+)|(\ufb05+)/gu;
+ NormalizationMap = new Map([["ſt", "ſt"]]);
+ }
+ return str.replaceAll(NormalizeRegex, (_, p1, p2) => p1 ? p1.normalize("NFKC") : NormalizationMap.get(p2));
+}
+function getUuid() {
+ return crypto.randomUUID();
+}
+const AnnotationPrefix = "pdfjs_internal_id_";
+
+;// CONCATENATED MODULE: ./src/core/primitives.js
+
+const CIRCULAR_REF = Symbol("CIRCULAR_REF");
+const EOF = Symbol("EOF");
+let CmdCache = Object.create(null);
+let NameCache = Object.create(null);
+let RefCache = Object.create(null);
+function clearPrimitiveCaches() {
+ CmdCache = Object.create(null);
+ NameCache = Object.create(null);
+ RefCache = Object.create(null);
+}
+class Name {
+ constructor(name) {
+ this.name = name;
+ }
+ static get(name) {
+ return NameCache[name] ||= new Name(name);
+ }
+}
+class Cmd {
+ constructor(cmd) {
+ this.cmd = cmd;
+ }
+ static get(cmd) {
+ return CmdCache[cmd] ||= new Cmd(cmd);
+ }
+}
+const nonSerializable = function nonSerializableClosure() {
+ return nonSerializable;
+};
+class Dict {
+ constructor(xref = null) {
+ this._map = Object.create(null);
+ this.xref = xref;
+ this.objId = null;
+ this.suppressEncryption = false;
+ this.__nonSerializable__ = nonSerializable;
+ }
+ assignXref(newXref) {
+ this.xref = newXref;
+ }
+ get size() {
+ return Object.keys(this._map).length;
+ }
+ get(key1, key2, key3) {
+ let value = this._map[key1];
+ if (value === undefined && key2 !== undefined) {
+ value = this._map[key2];
+ if (value === undefined && key3 !== undefined) {
+ value = this._map[key3];
+ }
+ }
+ if (value instanceof Ref && this.xref) {
+ return this.xref.fetch(value, this.suppressEncryption);
+ }
+ return value;
+ }
+ async getAsync(key1, key2, key3) {
+ let value = this._map[key1];
+ if (value === undefined && key2 !== undefined) {
+ value = this._map[key2];
+ if (value === undefined && key3 !== undefined) {
+ value = this._map[key3];
+ }
+ }
+ if (value instanceof Ref && this.xref) {
+ return this.xref.fetchAsync(value, this.suppressEncryption);
+ }
+ return value;
+ }
+ getArray(key1, key2, key3) {
+ let value = this._map[key1];
+ if (value === undefined && key2 !== undefined) {
+ value = this._map[key2];
+ if (value === undefined && key3 !== undefined) {
+ value = this._map[key3];
+ }
+ }
+ if (value instanceof Ref && this.xref) {
+ value = this.xref.fetch(value, this.suppressEncryption);
+ }
+ if (Array.isArray(value)) {
+ value = value.slice();
+ for (let i = 0, ii = value.length; i < ii; i++) {
+ if (value[i] instanceof Ref && this.xref) {
+ value[i] = this.xref.fetch(value[i], this.suppressEncryption);
+ }
+ }
+ }
+ return value;
+ }
+ getRaw(key) {
+ return this._map[key];
+ }
+ getKeys() {
+ return Object.keys(this._map);
+ }
+ getRawValues() {
+ return Object.values(this._map);
+ }
+ set(key, value) {
+ this._map[key] = value;
+ }
+ has(key) {
+ return this._map[key] !== undefined;
+ }
+ forEach(callback) {
+ for (const key in this._map) {
+ callback(key, this.get(key));
+ }
+ }
+ static get empty() {
+ const emptyDict = new Dict(null);
+ emptyDict.set = (key, value) => {
+ unreachable("Should not call `set` on the empty dictionary.");
+ };
+ return shadow(this, "empty", emptyDict);
+ }
+ static merge({
+ xref,
+ dictArray,
+ mergeSubDicts = false
+ }) {
+ const mergedDict = new Dict(xref),
+ properties = new Map();
+ for (const dict of dictArray) {
+ if (!(dict instanceof Dict)) {
+ continue;
+ }
+ for (const [key, value] of Object.entries(dict._map)) {
+ let property = properties.get(key);
+ if (property === undefined) {
+ property = [];
+ properties.set(key, property);
+ } else if (!mergeSubDicts || !(value instanceof Dict)) {
+ continue;
+ }
+ property.push(value);
+ }
+ }
+ for (const [name, values] of properties) {
+ if (values.length === 1 || !(values[0] instanceof Dict)) {
+ mergedDict._map[name] = values[0];
+ continue;
+ }
+ const subDict = new Dict(xref);
+ for (const dict of values) {
+ for (const [key, value] of Object.entries(dict._map)) {
+ if (subDict._map[key] === undefined) {
+ subDict._map[key] = value;
+ }
+ }
+ }
+ if (subDict.size > 0) {
+ mergedDict._map[name] = subDict;
+ }
+ }
+ properties.clear();
+ return mergedDict.size > 0 ? mergedDict : Dict.empty;
+ }
+ clone() {
+ const dict = new Dict(this.xref);
+ for (const key of this.getKeys()) {
+ dict.set(key, this.getRaw(key));
+ }
+ return dict;
+ }
+}
+class Ref {
+ constructor(num, gen) {
+ this.num = num;
+ this.gen = gen;
+ }
+ toString() {
+ if (this.gen === 0) {
+ return `${this.num}R`;
+ }
+ return `${this.num}R${this.gen}`;
+ }
+ static fromString(str) {
+ const ref = RefCache[str];
+ if (ref) {
+ return ref;
+ }
+ const m = /^(\d+)R(\d*)$/.exec(str);
+ if (!m || m[1] === "0") {
+ return null;
+ }
+ return RefCache[str] = new Ref(parseInt(m[1]), !m[2] ? 0 : parseInt(m[2]));
+ }
+ static get(num, gen) {
+ const key = gen === 0 ? `${num}R` : `${num}R${gen}`;
+ return RefCache[key] ||= new Ref(num, gen);
+ }
+}
+class RefSet {
+ constructor(parent = null) {
+ this._set = new Set(parent?._set);
+ }
+ has(ref) {
+ return this._set.has(ref.toString());
+ }
+ put(ref) {
+ this._set.add(ref.toString());
+ }
+ remove(ref) {
+ this._set.delete(ref.toString());
+ }
+ [Symbol.iterator]() {
+ return this._set.values();
+ }
+ clear() {
+ this._set.clear();
+ }
+}
+class RefSetCache {
+ constructor() {
+ this._map = new Map();
+ }
+ get size() {
+ return this._map.size;
+ }
+ get(ref) {
+ return this._map.get(ref.toString());
+ }
+ has(ref) {
+ return this._map.has(ref.toString());
+ }
+ put(ref, obj) {
+ this._map.set(ref.toString(), obj);
+ }
+ putAlias(ref, aliasRef) {
+ this._map.set(ref.toString(), this.get(aliasRef));
+ }
+ [Symbol.iterator]() {
+ return this._map.values();
+ }
+ clear() {
+ this._map.clear();
+ }
+}
+function isName(v, name) {
+ return v instanceof Name && (name === undefined || v.name === name);
+}
+function isCmd(v, cmd) {
+ return v instanceof Cmd && (cmd === undefined || v.cmd === cmd);
+}
+function isDict(v, type) {
+ return v instanceof Dict && (type === undefined || isName(v.get("Type"), type));
+}
+function isRefsEqual(v1, v2) {
+ return v1.num === v2.num && v1.gen === v2.gen;
+}
+
+;// CONCATENATED MODULE: ./src/core/base_stream.js
+
+class BaseStream {
+ constructor() {
+ if (this.constructor === BaseStream) {
+ unreachable("Cannot initialize BaseStream.");
+ }
+ }
+ get length() {
+ unreachable("Abstract getter `length` accessed");
+ }
+ get isEmpty() {
+ unreachable("Abstract getter `isEmpty` accessed");
+ }
+ get isDataLoaded() {
+ return shadow(this, "isDataLoaded", true);
+ }
+ getByte() {
+ unreachable("Abstract method `getByte` called");
+ }
+ getBytes(length) {
+ unreachable("Abstract method `getBytes` called");
+ }
+ peekByte() {
+ const peekedByte = this.getByte();
+ if (peekedByte !== -1) {
+ this.pos--;
+ }
+ return peekedByte;
+ }
+ peekBytes(length) {
+ const bytes = this.getBytes(length);
+ this.pos -= bytes.length;
+ return bytes;
+ }
+ getUint16() {
+ const b0 = this.getByte();
+ const b1 = this.getByte();
+ if (b0 === -1 || b1 === -1) {
+ return -1;
+ }
+ return (b0 << 8) + b1;
+ }
+ getInt32() {
+ const b0 = this.getByte();
+ const b1 = this.getByte();
+ const b2 = this.getByte();
+ const b3 = this.getByte();
+ return (b0 << 24) + (b1 << 16) + (b2 << 8) + b3;
+ }
+ getByteRange(begin, end) {
+ unreachable("Abstract method `getByteRange` called");
+ }
+ getString(length) {
+ return bytesToString(this.getBytes(length));
+ }
+ skip(n) {
+ this.pos += n || 1;
+ }
+ reset() {
+ unreachable("Abstract method `reset` called");
+ }
+ moveStart() {
+ unreachable("Abstract method `moveStart` called");
+ }
+ makeSubStream(start, length, dict = null) {
+ unreachable("Abstract method `makeSubStream` called");
+ }
+ getBaseStreams() {
+ return null;
+ }
+}
+
+;// CONCATENATED MODULE: ./src/core/core_utils.js
+
+
+
+const PDF_VERSION_REGEXP = /^[1-9]\.\d$/;
+function getLookupTableFactory(initializer) {
+ let lookup;
+ return function () {
+ if (initializer) {
+ lookup = Object.create(null);
+ initializer(lookup);
+ initializer = null;
+ }
+ return lookup;
+ };
+}
+class MissingDataException extends BaseException {
+ constructor(begin, end) {
+ super(`Missing data [${begin}, ${end})`, "MissingDataException");
+ this.begin = begin;
+ this.end = end;
+ }
+}
+class ParserEOFException extends BaseException {
+ constructor(msg) {
+ super(msg, "ParserEOFException");
+ }
+}
+class XRefEntryException extends BaseException {
+ constructor(msg) {
+ super(msg, "XRefEntryException");
+ }
+}
+class XRefParseException extends BaseException {
+ constructor(msg) {
+ super(msg, "XRefParseException");
+ }
+}
+function arrayBuffersToBytes(arr) {
+ const length = arr.length;
+ if (length === 0) {
+ return new Uint8Array(0);
+ }
+ if (length === 1) {
+ return new Uint8Array(arr[0]);
+ }
+ let dataLength = 0;
+ for (let i = 0; i < length; i++) {
+ dataLength += arr[i].byteLength;
+ }
+ const data = new Uint8Array(dataLength);
+ let pos = 0;
+ for (let i = 0; i < length; i++) {
+ const item = new Uint8Array(arr[i]);
+ data.set(item, pos);
+ pos += item.byteLength;
+ }
+ return data;
+}
+function getInheritableProperty({
+ dict,
+ key,
+ getArray = false,
+ stopWhenFound = true
+}) {
+ let values;
+ const visited = new RefSet();
+ while (dict instanceof Dict && !(dict.objId && visited.has(dict.objId))) {
+ if (dict.objId) {
+ visited.put(dict.objId);
+ }
+ const value = getArray ? dict.getArray(key) : dict.get(key);
+ if (value !== undefined) {
+ if (stopWhenFound) {
+ return value;
+ }
+ (values ||= []).push(value);
+ }
+ dict = dict.get("Parent");
+ }
+ return values;
+}
+const ROMAN_NUMBER_MAP = ["", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM", "", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC", "", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"];
+function toRomanNumerals(number, lowerCase = false) {
+ assert(Number.isInteger(number) && number > 0, "The number should be a positive integer.");
+ const romanBuf = [];
+ let pos;
+ while (number >= 1000) {
+ number -= 1000;
+ romanBuf.push("M");
+ }
+ pos = number / 100 | 0;
+ number %= 100;
+ romanBuf.push(ROMAN_NUMBER_MAP[pos]);
+ pos = number / 10 | 0;
+ number %= 10;
+ romanBuf.push(ROMAN_NUMBER_MAP[10 + pos]);
+ romanBuf.push(ROMAN_NUMBER_MAP[20 + number]);
+ const romanStr = romanBuf.join("");
+ return lowerCase ? romanStr.toLowerCase() : romanStr;
+}
+function log2(x) {
+ if (x <= 0) {
+ return 0;
+ }
+ return Math.ceil(Math.log2(x));
+}
+function readInt8(data, offset) {
+ return data[offset] << 24 >> 24;
+}
+function readUint16(data, offset) {
+ return data[offset] << 8 | data[offset + 1];
+}
+function readUint32(data, offset) {
+ return (data[offset] << 24 | data[offset + 1] << 16 | data[offset + 2] << 8 | data[offset + 3]) >>> 0;
+}
+function isWhiteSpace(ch) {
+ return ch === 0x20 || ch === 0x09 || ch === 0x0d || ch === 0x0a;
+}
+function parseXFAPath(path) {
+ const positionPattern = /(.+)\[(\d+)\]$/;
+ return path.split(".").map(component => {
+ const m = component.match(positionPattern);
+ if (m) {
+ return {
+ name: m[1],
+ pos: parseInt(m[2], 10)
+ };
+ }
+ return {
+ name: component,
+ pos: 0
+ };
+ });
+}
+function escapePDFName(str) {
+ const buffer = [];
+ let start = 0;
+ for (let i = 0, ii = str.length; i < ii; i++) {
+ const char = str.charCodeAt(i);
+ if (char < 0x21 || char > 0x7e || char === 0x23 || char === 0x28 || char === 0x29 || char === 0x3c || char === 0x3e || char === 0x5b || char === 0x5d || char === 0x7b || char === 0x7d || char === 0x2f || char === 0x25) {
+ if (start < i) {
+ buffer.push(str.substring(start, i));
+ }
+ buffer.push(`#${char.toString(16)}`);
+ start = i + 1;
+ }
+ }
+ if (buffer.length === 0) {
+ return str;
+ }
+ if (start < str.length) {
+ buffer.push(str.substring(start, str.length));
+ }
+ return buffer.join("");
+}
+function escapeString(str) {
+ return str.replaceAll(/([()\\\n\r])/g, match => {
+ if (match === "\n") {
+ return "\\n";
+ } else if (match === "\r") {
+ return "\\r";
+ }
+ return `\\${match}`;
+ });
+}
+function _collectJS(entry, xref, list, parents) {
+ if (!entry) {
+ return;
+ }
+ let parent = null;
+ if (entry instanceof Ref) {
+ if (parents.has(entry)) {
+ return;
+ }
+ parent = entry;
+ parents.put(parent);
+ entry = xref.fetch(entry);
+ }
+ if (Array.isArray(entry)) {
+ for (const element of entry) {
+ _collectJS(element, xref, list, parents);
+ }
+ } else if (entry instanceof Dict) {
+ if (isName(entry.get("S"), "JavaScript")) {
+ const js = entry.get("JS");
+ let code;
+ if (js instanceof BaseStream) {
+ code = js.getString();
+ } else if (typeof js === "string") {
+ code = js;
+ }
+ code &&= stringToPDFString(code).replaceAll("\x00", "");
+ if (code) {
+ list.push(code);
+ }
+ }
+ _collectJS(entry.getRaw("Next"), xref, list, parents);
+ }
+ if (parent) {
+ parents.remove(parent);
+ }
+}
+function collectActions(xref, dict, eventType) {
+ const actions = Object.create(null);
+ const additionalActionsDicts = getInheritableProperty({
+ dict,
+ key: "AA",
+ stopWhenFound: false
+ });
+ if (additionalActionsDicts) {
+ for (let i = additionalActionsDicts.length - 1; i >= 0; i--) {
+ const additionalActions = additionalActionsDicts[i];
+ if (!(additionalActions instanceof Dict)) {
+ continue;
+ }
+ for (const key of additionalActions.getKeys()) {
+ const action = eventType[key];
+ if (!action) {
+ continue;
+ }
+ const actionDict = additionalActions.getRaw(key);
+ const parents = new RefSet();
+ const list = [];
+ _collectJS(actionDict, xref, list, parents);
+ if (list.length > 0) {
+ actions[action] = list;
+ }
+ }
+ }
+ }
+ if (dict.has("A")) {
+ const actionDict = dict.get("A");
+ const parents = new RefSet();
+ const list = [];
+ _collectJS(actionDict, xref, list, parents);
+ if (list.length > 0) {
+ actions.Action = list;
+ }
+ }
+ return objectSize(actions) > 0 ? actions : null;
+}
+const XMLEntities = {
+ 0x3c: "&lt;",
+ 0x3e: "&gt;",
+ 0x26: "&amp;",
+ 0x22: "&quot;",
+ 0x27: "&apos;"
+};
+function* codePointIter(str) {
+ for (let i = 0, ii = str.length; i < ii; i++) {
+ const char = str.codePointAt(i);
+ if (char > 0xd7ff && (char < 0xe000 || char > 0xfffd)) {
+ i++;
+ }
+ yield char;
+ }
+}
+function encodeToXmlString(str) {
+ const buffer = [];
+ let start = 0;
+ for (let i = 0, ii = str.length; i < ii; i++) {
+ const char = str.codePointAt(i);
+ if (0x20 <= char && char <= 0x7e) {
+ const entity = XMLEntities[char];
+ if (entity) {
+ if (start < i) {
+ buffer.push(str.substring(start, i));
+ }
+ buffer.push(entity);
+ start = i + 1;
+ }
+ } else {
+ if (start < i) {
+ buffer.push(str.substring(start, i));
+ }
+ buffer.push(`&#x${char.toString(16).toUpperCase()};`);
+ if (char > 0xd7ff && (char < 0xe000 || char > 0xfffd)) {
+ i++;
+ }
+ start = i + 1;
+ }
+ }
+ if (buffer.length === 0) {
+ return str;
+ }
+ if (start < str.length) {
+ buffer.push(str.substring(start, str.length));
+ }
+ return buffer.join("");
+}
+function validateFontName(fontFamily, mustWarn = false) {
+ const m = /^("|').*("|')$/.exec(fontFamily);
+ if (m && m[1] === m[2]) {
+ const re = new RegExp(`[^\\\\]${m[1]}`);
+ if (re.test(fontFamily.slice(1, -1))) {
+ if (mustWarn) {
+ warn(`FontFamily contains unescaped ${m[1]}: ${fontFamily}.`);
+ }
+ return false;
+ }
+ } else {
+ for (const ident of fontFamily.split(/[ \t]+/)) {
+ if (/^(\d|(-(\d|-)))/.test(ident) || !/^[\w-\\]+$/.test(ident)) {
+ if (mustWarn) {
+ warn(`FontFamily contains invalid <custom-ident>: ${fontFamily}.`);
+ }
+ return false;
+ }
+ }
+ }
+ return true;
+}
+function validateCSSFont(cssFontInfo) {
+ const DEFAULT_CSS_FONT_OBLIQUE = "14";
+ const DEFAULT_CSS_FONT_WEIGHT = "400";
+ const CSS_FONT_WEIGHT_VALUES = new Set(["100", "200", "300", "400", "500", "600", "700", "800", "900", "1000", "normal", "bold", "bolder", "lighter"]);
+ const {
+ fontFamily,
+ fontWeight,
+ italicAngle
+ } = cssFontInfo;
+ if (!validateFontName(fontFamily, true)) {
+ return false;
+ }
+ const weight = fontWeight ? fontWeight.toString() : "";
+ cssFontInfo.fontWeight = CSS_FONT_WEIGHT_VALUES.has(weight) ? weight : DEFAULT_CSS_FONT_WEIGHT;
+ const angle = parseFloat(italicAngle);
+ cssFontInfo.italicAngle = isNaN(angle) || angle < -90 || angle > 90 ? DEFAULT_CSS_FONT_OBLIQUE : italicAngle.toString();
+ return true;
+}
+function recoverJsURL(str) {
+ const URL_OPEN_METHODS = ["app.launchURL", "window.open", "xfa.host.gotoURL"];
+ const regex = new RegExp("^\\s*(" + URL_OPEN_METHODS.join("|").replaceAll(".", "\\.") + ")\\((?:'|\")([^'\"]*)(?:'|\")(?:,\\s*(\\w+)\\)|\\))", "i");
+ const jsUrl = regex.exec(str);
+ if (jsUrl?.[2]) {
+ const url = jsUrl[2];
+ let newWindow = false;
+ if (jsUrl[3] === "true" && jsUrl[1] === "app.launchURL") {
+ newWindow = true;
+ }
+ return {
+ url,
+ newWindow
+ };
+ }
+ return null;
+}
+function numberToString(value) {
+ if (Number.isInteger(value)) {
+ return value.toString();
+ }
+ const roundedValue = Math.round(value * 100);
+ if (roundedValue % 100 === 0) {
+ return (roundedValue / 100).toString();
+ }
+ if (roundedValue % 10 === 0) {
+ return value.toFixed(1);
+ }
+ return value.toFixed(2);
+}
+function getNewAnnotationsMap(annotationStorage) {
+ if (!annotationStorage) {
+ return null;
+ }
+ const newAnnotationsByPage = new Map();
+ for (const [key, value] of annotationStorage) {
+ if (!key.startsWith(AnnotationEditorPrefix)) {
+ continue;
+ }
+ let annotations = newAnnotationsByPage.get(value.pageIndex);
+ if (!annotations) {
+ annotations = [];
+ newAnnotationsByPage.set(value.pageIndex, annotations);
+ }
+ annotations.push(value);
+ }
+ return newAnnotationsByPage.size > 0 ? newAnnotationsByPage : null;
+}
+function isAscii(str) {
+ return /^[\x00-\x7F]*$/.test(str);
+}
+function stringToUTF16HexString(str) {
+ const buf = [];
+ for (let i = 0, ii = str.length; i < ii; i++) {
+ const char = str.charCodeAt(i);
+ buf.push((char >> 8 & 0xff).toString(16).padStart(2, "0"), (char & 0xff).toString(16).padStart(2, "0"));
+ }
+ return buf.join("");
+}
+function stringToUTF16String(str, bigEndian = false) {
+ const buf = [];
+ if (bigEndian) {
+ buf.push("\xFE\xFF");
+ }
+ for (let i = 0, ii = str.length; i < ii; i++) {
+ const char = str.charCodeAt(i);
+ buf.push(String.fromCharCode(char >> 8 & 0xff), String.fromCharCode(char & 0xff));
+ }
+ return buf.join("");
+}
+function getRotationMatrix(rotation, width, height) {
+ switch (rotation) {
+ case 90:
+ return [0, 1, -1, 0, width, 0];
+ case 180:
+ return [-1, 0, 0, -1, width, height];
+ case 270:
+ return [0, -1, 1, 0, 0, height];
+ default:
+ throw new Error("Invalid rotation");
+ }
+}
+function getSizeInBytes(x) {
+ return Math.ceil(Math.ceil(Math.log2(1 + x)) / 8);
+}
+
+;// CONCATENATED MODULE: ./src/core/stream.js
+
+
+class Stream extends BaseStream {
+ constructor(arrayBuffer, start, length, dict) {
+ super();
+ this.bytes = arrayBuffer instanceof Uint8Array ? arrayBuffer : new Uint8Array(arrayBuffer);
+ this.start = start || 0;
+ this.pos = this.start;
+ this.end = start + length || this.bytes.length;
+ this.dict = dict;
+ }
+ get length() {
+ return this.end - this.start;
+ }
+ get isEmpty() {
+ return this.length === 0;
+ }
+ getByte() {
+ if (this.pos >= this.end) {
+ return -1;
+ }
+ return this.bytes[this.pos++];
+ }
+ getBytes(length) {
+ const bytes = this.bytes;
+ const pos = this.pos;
+ const strEnd = this.end;
+ if (!length) {
+ return bytes.subarray(pos, strEnd);
+ }
+ let end = pos + length;
+ if (end > strEnd) {
+ end = strEnd;
+ }
+ this.pos = end;
+ return bytes.subarray(pos, end);
+ }
+ getByteRange(begin, end) {
+ if (begin < 0) {
+ begin = 0;
+ }
+ if (end > this.end) {
+ end = this.end;
+ }
+ return this.bytes.subarray(begin, end);
+ }
+ reset() {
+ this.pos = this.start;
+ }
+ moveStart() {
+ this.start = this.pos;
+ }
+ makeSubStream(start, length, dict = null) {
+ return new Stream(this.bytes.buffer, start, length, dict);
+ }
+}
+class StringStream extends Stream {
+ constructor(str) {
+ super(stringToBytes(str));
+ }
+}
+class NullStream extends Stream {
+ constructor() {
+ super(new Uint8Array(0));
+ }
+}
+
+;// CONCATENATED MODULE: ./src/core/chunked_stream.js
+
+
+
+class ChunkedStream extends Stream {
+ constructor(length, chunkSize, manager) {
+ super(new Uint8Array(length), 0, length, null);
+ this.chunkSize = chunkSize;
+ this._loadedChunks = new Set();
+ this.numChunks = Math.ceil(length / chunkSize);
+ this.manager = manager;
+ this.progressiveDataLength = 0;
+ this.lastSuccessfulEnsureByteChunk = -1;
+ }
+ getMissingChunks() {
+ const chunks = [];
+ for (let chunk = 0, n = this.numChunks; chunk < n; ++chunk) {
+ if (!this._loadedChunks.has(chunk)) {
+ chunks.push(chunk);
+ }
+ }
+ return chunks;
+ }
+ get numChunksLoaded() {
+ return this._loadedChunks.size;
+ }
+ get isDataLoaded() {
+ return this.numChunksLoaded === this.numChunks;
+ }
+ onReceiveData(begin, chunk) {
+ const chunkSize = this.chunkSize;
+ if (begin % chunkSize !== 0) {
+ throw new Error(`Bad begin offset: ${begin}`);
+ }
+ const end = begin + chunk.byteLength;
+ if (end % chunkSize !== 0 && end !== this.bytes.length) {
+ throw new Error(`Bad end offset: ${end}`);
+ }
+ this.bytes.set(new Uint8Array(chunk), begin);
+ const beginChunk = Math.floor(begin / chunkSize);
+ const endChunk = Math.floor((end - 1) / chunkSize) + 1;
+ for (let curChunk = beginChunk; curChunk < endChunk; ++curChunk) {
+ this._loadedChunks.add(curChunk);
+ }
+ }
+ onReceiveProgressiveData(data) {
+ let position = this.progressiveDataLength;
+ const beginChunk = Math.floor(position / this.chunkSize);
+ this.bytes.set(new Uint8Array(data), position);
+ position += data.byteLength;
+ this.progressiveDataLength = position;
+ const endChunk = position >= this.end ? this.numChunks : Math.floor(position / this.chunkSize);
+ for (let curChunk = beginChunk; curChunk < endChunk; ++curChunk) {
+ this._loadedChunks.add(curChunk);
+ }
+ }
+ ensureByte(pos) {
+ if (pos < this.progressiveDataLength) {
+ return;
+ }
+ const chunk = Math.floor(pos / this.chunkSize);
+ if (chunk > this.numChunks) {
+ return;
+ }
+ if (chunk === this.lastSuccessfulEnsureByteChunk) {
+ return;
+ }
+ if (!this._loadedChunks.has(chunk)) {
+ throw new MissingDataException(pos, pos + 1);
+ }
+ this.lastSuccessfulEnsureByteChunk = chunk;
+ }
+ ensureRange(begin, end) {
+ if (begin >= end) {
+ return;
+ }
+ if (end <= this.progressiveDataLength) {
+ return;
+ }
+ const beginChunk = Math.floor(begin / this.chunkSize);
+ if (beginChunk > this.numChunks) {
+ return;
+ }
+ const endChunk = Math.min(Math.floor((end - 1) / this.chunkSize) + 1, this.numChunks);
+ for (let chunk = beginChunk; chunk < endChunk; ++chunk) {
+ if (!this._loadedChunks.has(chunk)) {
+ throw new MissingDataException(begin, end);
+ }
+ }
+ }
+ nextEmptyChunk(beginChunk) {
+ const numChunks = this.numChunks;
+ for (let i = 0; i < numChunks; ++i) {
+ const chunk = (beginChunk + i) % numChunks;
+ if (!this._loadedChunks.has(chunk)) {
+ return chunk;
+ }
+ }
+ return null;
+ }
+ hasChunk(chunk) {
+ return this._loadedChunks.has(chunk);
+ }
+ getByte() {
+ const pos = this.pos;
+ if (pos >= this.end) {
+ return -1;
+ }
+ if (pos >= this.progressiveDataLength) {
+ this.ensureByte(pos);
+ }
+ return this.bytes[this.pos++];
+ }
+ getBytes(length) {
+ const bytes = this.bytes;
+ const pos = this.pos;
+ const strEnd = this.end;
+ if (!length) {
+ if (strEnd > this.progressiveDataLength) {
+ this.ensureRange(pos, strEnd);
+ }
+ return bytes.subarray(pos, strEnd);
+ }
+ let end = pos + length;
+ if (end > strEnd) {
+ end = strEnd;
+ }
+ if (end > this.progressiveDataLength) {
+ this.ensureRange(pos, end);
+ }
+ this.pos = end;
+ return bytes.subarray(pos, end);
+ }
+ getByteRange(begin, end) {
+ if (begin < 0) {
+ begin = 0;
+ }
+ if (end > this.end) {
+ end = this.end;
+ }
+ if (end > this.progressiveDataLength) {
+ this.ensureRange(begin, end);
+ }
+ return this.bytes.subarray(begin, end);
+ }
+ makeSubStream(start, length, dict = null) {
+ if (length) {
+ if (start + length > this.progressiveDataLength) {
+ this.ensureRange(start, start + length);
+ }
+ } else if (start >= this.progressiveDataLength) {
+ this.ensureByte(start);
+ }
+ function ChunkedStreamSubstream() {}
+ ChunkedStreamSubstream.prototype = Object.create(this);
+ ChunkedStreamSubstream.prototype.getMissingChunks = function () {
+ const chunkSize = this.chunkSize;
+ const beginChunk = Math.floor(this.start / chunkSize);
+ const endChunk = Math.floor((this.end - 1) / chunkSize) + 1;
+ const missingChunks = [];
+ for (let chunk = beginChunk; chunk < endChunk; ++chunk) {
+ if (!this._loadedChunks.has(chunk)) {
+ missingChunks.push(chunk);
+ }
+ }
+ return missingChunks;
+ };
+ Object.defineProperty(ChunkedStreamSubstream.prototype, "isDataLoaded", {
+ get() {
+ if (this.numChunksLoaded === this.numChunks) {
+ return true;
+ }
+ return this.getMissingChunks().length === 0;
+ },
+ configurable: true
+ });
+ const subStream = new ChunkedStreamSubstream();
+ subStream.pos = subStream.start = start;
+ subStream.end = start + length || this.end;
+ subStream.dict = dict;
+ return subStream;
+ }
+ getBaseStreams() {
+ return [this];
+ }
+}
+class ChunkedStreamManager {
+ constructor(pdfNetworkStream, args) {
+ this.length = args.length;
+ this.chunkSize = args.rangeChunkSize;
+ this.stream = new ChunkedStream(this.length, this.chunkSize, this);
+ this.pdfNetworkStream = pdfNetworkStream;
+ this.disableAutoFetch = args.disableAutoFetch;
+ this.msgHandler = args.msgHandler;
+ this.currRequestId = 0;
+ this._chunksNeededByRequest = new Map();
+ this._requestsByChunk = new Map();
+ this._promisesByRequest = new Map();
+ this.progressiveDataLength = 0;
+ this.aborted = false;
+ this._loadedStreamCapability = new PromiseCapability();
+ }
+ sendRequest(begin, end) {
+ const rangeReader = this.pdfNetworkStream.getRangeReader(begin, end);
+ if (!rangeReader.isStreamingSupported) {
+ rangeReader.onProgress = this.onProgress.bind(this);
+ }
+ let chunks = [],
+ loaded = 0;
+ return new Promise((resolve, reject) => {
+ const readChunk = ({
+ value,
+ done
+ }) => {
+ try {
+ if (done) {
+ const chunkData = arrayBuffersToBytes(chunks);
+ chunks = null;
+ resolve(chunkData);
+ return;
+ }
+ loaded += value.byteLength;
+ if (rangeReader.isStreamingSupported) {
+ this.onProgress({
+ loaded
+ });
+ }
+ chunks.push(value);
+ rangeReader.read().then(readChunk, reject);
+ } catch (e) {
+ reject(e);
+ }
+ };
+ rangeReader.read().then(readChunk, reject);
+ }).then(data => {
+ if (this.aborted) {
+ return;
+ }
+ this.onReceiveData({
+ chunk: data,
+ begin
+ });
+ });
+ }
+ requestAllChunks(noFetch = false) {
+ if (!noFetch) {
+ const missingChunks = this.stream.getMissingChunks();
+ this._requestChunks(missingChunks);
+ }
+ return this._loadedStreamCapability.promise;
+ }
+ _requestChunks(chunks) {
+ const requestId = this.currRequestId++;
+ const chunksNeeded = new Set();
+ this._chunksNeededByRequest.set(requestId, chunksNeeded);
+ for (const chunk of chunks) {
+ if (!this.stream.hasChunk(chunk)) {
+ chunksNeeded.add(chunk);
+ }
+ }
+ if (chunksNeeded.size === 0) {
+ return Promise.resolve();
+ }
+ const capability = new PromiseCapability();
+ this._promisesByRequest.set(requestId, capability);
+ const chunksToRequest = [];
+ for (const chunk of chunksNeeded) {
+ let requestIds = this._requestsByChunk.get(chunk);
+ if (!requestIds) {
+ requestIds = [];
+ this._requestsByChunk.set(chunk, requestIds);
+ chunksToRequest.push(chunk);
+ }
+ requestIds.push(requestId);
+ }
+ if (chunksToRequest.length > 0) {
+ const groupedChunksToRequest = this.groupChunks(chunksToRequest);
+ for (const groupedChunk of groupedChunksToRequest) {
+ const begin = groupedChunk.beginChunk * this.chunkSize;
+ const end = Math.min(groupedChunk.endChunk * this.chunkSize, this.length);
+ this.sendRequest(begin, end).catch(capability.reject);
+ }
+ }
+ return capability.promise.catch(reason => {
+ if (this.aborted) {
+ return;
+ }
+ throw reason;
+ });
+ }
+ getStream() {
+ return this.stream;
+ }
+ requestRange(begin, end) {
+ end = Math.min(end, this.length);
+ const beginChunk = this.getBeginChunk(begin);
+ const endChunk = this.getEndChunk(end);
+ const chunks = [];
+ for (let chunk = beginChunk; chunk < endChunk; ++chunk) {
+ chunks.push(chunk);
+ }
+ return this._requestChunks(chunks);
+ }
+ requestRanges(ranges = []) {
+ const chunksToRequest = [];
+ for (const range of ranges) {
+ const beginChunk = this.getBeginChunk(range.begin);
+ const endChunk = this.getEndChunk(range.end);
+ for (let chunk = beginChunk; chunk < endChunk; ++chunk) {
+ if (!chunksToRequest.includes(chunk)) {
+ chunksToRequest.push(chunk);
+ }
+ }
+ }
+ chunksToRequest.sort(function (a, b) {
+ return a - b;
+ });
+ return this._requestChunks(chunksToRequest);
+ }
+ groupChunks(chunks) {
+ const groupedChunks = [];
+ let beginChunk = -1;
+ let prevChunk = -1;
+ for (let i = 0, ii = chunks.length; i < ii; ++i) {
+ const chunk = chunks[i];
+ if (beginChunk < 0) {
+ beginChunk = chunk;
+ }
+ if (prevChunk >= 0 && prevChunk + 1 !== chunk) {
+ groupedChunks.push({
+ beginChunk,
+ endChunk: prevChunk + 1
+ });
+ beginChunk = chunk;
+ }
+ if (i + 1 === chunks.length) {
+ groupedChunks.push({
+ beginChunk,
+ endChunk: chunk + 1
+ });
+ }
+ prevChunk = chunk;
+ }
+ return groupedChunks;
+ }
+ onProgress(args) {
+ this.msgHandler.send("DocProgress", {
+ loaded: this.stream.numChunksLoaded * this.chunkSize + args.loaded,
+ total: this.length
+ });
+ }
+ onReceiveData(args) {
+ const chunk = args.chunk;
+ const isProgressive = args.begin === undefined;
+ const begin = isProgressive ? this.progressiveDataLength : args.begin;
+ const end = begin + chunk.byteLength;
+ const beginChunk = Math.floor(begin / this.chunkSize);
+ const endChunk = end < this.length ? Math.floor(end / this.chunkSize) : Math.ceil(end / this.chunkSize);
+ if (isProgressive) {
+ this.stream.onReceiveProgressiveData(chunk);
+ this.progressiveDataLength = end;
+ } else {
+ this.stream.onReceiveData(begin, chunk);
+ }
+ if (this.stream.isDataLoaded) {
+ this._loadedStreamCapability.resolve(this.stream);
+ }
+ const loadedRequests = [];
+ for (let curChunk = beginChunk; curChunk < endChunk; ++curChunk) {
+ const requestIds = this._requestsByChunk.get(curChunk);
+ if (!requestIds) {
+ continue;
+ }
+ this._requestsByChunk.delete(curChunk);
+ for (const requestId of requestIds) {
+ const chunksNeeded = this._chunksNeededByRequest.get(requestId);
+ if (chunksNeeded.has(curChunk)) {
+ chunksNeeded.delete(curChunk);
+ }
+ if (chunksNeeded.size > 0) {
+ continue;
+ }
+ loadedRequests.push(requestId);
+ }
+ }
+ if (!this.disableAutoFetch && this._requestsByChunk.size === 0) {
+ let nextEmptyChunk;
+ if (this.stream.numChunksLoaded === 1) {
+ const lastChunk = this.stream.numChunks - 1;
+ if (!this.stream.hasChunk(lastChunk)) {
+ nextEmptyChunk = lastChunk;
+ }
+ } else {
+ nextEmptyChunk = this.stream.nextEmptyChunk(endChunk);
+ }
+ if (Number.isInteger(nextEmptyChunk)) {
+ this._requestChunks([nextEmptyChunk]);
+ }
+ }
+ for (const requestId of loadedRequests) {
+ const capability = this._promisesByRequest.get(requestId);
+ this._promisesByRequest.delete(requestId);
+ capability.resolve();
+ }
+ this.msgHandler.send("DocProgress", {
+ loaded: this.stream.numChunksLoaded * this.chunkSize,
+ total: this.length
+ });
+ }
+ onError(err) {
+ this._loadedStreamCapability.reject(err);
+ }
+ getBeginChunk(begin) {
+ return Math.floor(begin / this.chunkSize);
+ }
+ getEndChunk(end) {
+ return Math.floor((end - 1) / this.chunkSize) + 1;
+ }
+ abort(reason) {
+ this.aborted = true;
+ this.pdfNetworkStream?.cancelAllRequests(reason);
+ for (const capability of this._promisesByRequest.values()) {
+ capability.reject(reason);
+ }
+ }
+}
+
+;// CONCATENATED MODULE: ./src/core/colorspace.js
+
+
+
+
+function resizeRgbImage(src, dest, w1, h1, w2, h2, alpha01) {
+ const COMPONENTS = 3;
+ alpha01 = alpha01 !== 1 ? 0 : alpha01;
+ const xRatio = w1 / w2;
+ const yRatio = h1 / h2;
+ let newIndex = 0,
+ oldIndex;
+ const xScaled = new Uint16Array(w2);
+ const w1Scanline = w1 * COMPONENTS;
+ for (let i = 0; i < w2; i++) {
+ xScaled[i] = Math.floor(i * xRatio) * COMPONENTS;
+ }
+ for (let i = 0; i < h2; i++) {
+ const py = Math.floor(i * yRatio) * w1Scanline;
+ for (let j = 0; j < w2; j++) {
+ oldIndex = py + xScaled[j];
+ dest[newIndex++] = src[oldIndex++];
+ dest[newIndex++] = src[oldIndex++];
+ dest[newIndex++] = src[oldIndex++];
+ newIndex += alpha01;
+ }
+ }
+}
+class ColorSpace {
+ constructor(name, numComps) {
+ if (this.constructor === ColorSpace) {
+ unreachable("Cannot initialize ColorSpace.");
+ }
+ this.name = name;
+ this.numComps = numComps;
+ }
+ getRgb(src, srcOffset) {
+ const rgb = new Uint8ClampedArray(3);
+ this.getRgbItem(src, srcOffset, rgb, 0);
+ return rgb;
+ }
+ getRgbItem(src, srcOffset, dest, destOffset) {
+ unreachable("Should not call ColorSpace.getRgbItem");
+ }
+ getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
+ unreachable("Should not call ColorSpace.getRgbBuffer");
+ }
+ getOutputLength(inputLength, alpha01) {
+ unreachable("Should not call ColorSpace.getOutputLength");
+ }
+ isPassthrough(bits) {
+ return false;
+ }
+ isDefaultDecode(decodeMap, bpc) {
+ return ColorSpace.isDefaultDecode(decodeMap, this.numComps);
+ }
+ fillRgb(dest, originalWidth, originalHeight, width, height, actualHeight, bpc, comps, alpha01) {
+ const count = originalWidth * originalHeight;
+ let rgbBuf = null;
+ const numComponentColors = 1 << bpc;
+ const needsResizing = originalHeight !== height || originalWidth !== width;
+ if (this.isPassthrough(bpc)) {
+ rgbBuf = comps;
+ } else if (this.numComps === 1 && count > numComponentColors && this.name !== "DeviceGray" && this.name !== "DeviceRGB") {
+ const allColors = bpc <= 8 ? new Uint8Array(numComponentColors) : new Uint16Array(numComponentColors);
+ for (let i = 0; i < numComponentColors; i++) {
+ allColors[i] = i;
+ }
+ const colorMap = new Uint8ClampedArray(numComponentColors * 3);
+ this.getRgbBuffer(allColors, 0, numComponentColors, colorMap, 0, bpc, 0);
+ if (!needsResizing) {
+ let destPos = 0;
+ for (let i = 0; i < count; ++i) {
+ const key = comps[i] * 3;
+ dest[destPos++] = colorMap[key];
+ dest[destPos++] = colorMap[key + 1];
+ dest[destPos++] = colorMap[key + 2];
+ destPos += alpha01;
+ }
+ } else {
+ rgbBuf = new Uint8Array(count * 3);
+ let rgbPos = 0;
+ for (let i = 0; i < count; ++i) {
+ const key = comps[i] * 3;
+ rgbBuf[rgbPos++] = colorMap[key];
+ rgbBuf[rgbPos++] = colorMap[key + 1];
+ rgbBuf[rgbPos++] = colorMap[key + 2];
+ }
+ }
+ } else if (!needsResizing) {
+ this.getRgbBuffer(comps, 0, width * actualHeight, dest, 0, bpc, alpha01);
+ } else {
+ rgbBuf = new Uint8ClampedArray(count * 3);
+ this.getRgbBuffer(comps, 0, count, rgbBuf, 0, bpc, 0);
+ }
+ if (rgbBuf) {
+ if (needsResizing) {
+ resizeRgbImage(rgbBuf, dest, originalWidth, originalHeight, width, height, alpha01);
+ } else {
+ let destPos = 0,
+ rgbPos = 0;
+ for (let i = 0, ii = width * actualHeight; i < ii; i++) {
+ dest[destPos++] = rgbBuf[rgbPos++];
+ dest[destPos++] = rgbBuf[rgbPos++];
+ dest[destPos++] = rgbBuf[rgbPos++];
+ destPos += alpha01;
+ }
+ }
+ }
+ }
+ get usesZeroToOneRange() {
+ return shadow(this, "usesZeroToOneRange", true);
+ }
+ static _cache(cacheKey, xref, localColorSpaceCache, parsedColorSpace) {
+ if (!localColorSpaceCache) {
+ throw new Error('ColorSpace._cache - expected "localColorSpaceCache" argument.');
+ }
+ if (!parsedColorSpace) {
+ throw new Error('ColorSpace._cache - expected "parsedColorSpace" argument.');
+ }
+ let csName, csRef;
+ if (cacheKey instanceof Ref) {
+ csRef = cacheKey;
+ cacheKey = xref.fetch(cacheKey);
+ }
+ if (cacheKey instanceof Name) {
+ csName = cacheKey.name;
+ }
+ if (csName || csRef) {
+ localColorSpaceCache.set(csName, csRef, parsedColorSpace);
+ }
+ }
+ static getCached(cacheKey, xref, localColorSpaceCache) {
+ if (!localColorSpaceCache) {
+ throw new Error('ColorSpace.getCached - expected "localColorSpaceCache" argument.');
+ }
+ if (cacheKey instanceof Ref) {
+ const localColorSpace = localColorSpaceCache.getByRef(cacheKey);
+ if (localColorSpace) {
+ return localColorSpace;
+ }
+ try {
+ cacheKey = xref.fetch(cacheKey);
+ } catch (ex) {
+ if (ex instanceof MissingDataException) {
+ throw ex;
+ }
+ }
+ }
+ if (cacheKey instanceof Name) {
+ const localColorSpace = localColorSpaceCache.getByName(cacheKey.name);
+ if (localColorSpace) {
+ return localColorSpace;
+ }
+ }
+ return null;
+ }
+ static async parseAsync({
+ cs,
+ xref,
+ resources = null,
+ pdfFunctionFactory,
+ localColorSpaceCache
+ }) {
+ const parsedColorSpace = this._parse(cs, xref, resources, pdfFunctionFactory);
+ this._cache(cs, xref, localColorSpaceCache, parsedColorSpace);
+ return parsedColorSpace;
+ }
+ static parse({
+ cs,
+ xref,
+ resources = null,
+ pdfFunctionFactory,
+ localColorSpaceCache
+ }) {
+ const cachedColorSpace = this.getCached(cs, xref, localColorSpaceCache);
+ if (cachedColorSpace) {
+ return cachedColorSpace;
+ }
+ const parsedColorSpace = this._parse(cs, xref, resources, pdfFunctionFactory);
+ this._cache(cs, xref, localColorSpaceCache, parsedColorSpace);
+ return parsedColorSpace;
+ }
+ static _parse(cs, xref, resources = null, pdfFunctionFactory) {
+ cs = xref.fetchIfRef(cs);
+ if (cs instanceof Name) {
+ switch (cs.name) {
+ case "G":
+ case "DeviceGray":
+ return this.singletons.gray;
+ case "RGB":
+ case "DeviceRGB":
+ return this.singletons.rgb;
+ case "CMYK":
+ case "DeviceCMYK":
+ return this.singletons.cmyk;
+ case "Pattern":
+ return new PatternCS(null);
+ default:
+ if (resources instanceof Dict) {
+ const colorSpaces = resources.get("ColorSpace");
+ if (colorSpaces instanceof Dict) {
+ const resourcesCS = colorSpaces.get(cs.name);
+ if (resourcesCS) {
+ if (resourcesCS instanceof Name) {
+ return this._parse(resourcesCS, xref, resources, pdfFunctionFactory);
+ }
+ cs = resourcesCS;
+ break;
+ }
+ }
+ }
+ throw new FormatError(`Unrecognized ColorSpace: ${cs.name}`);
+ }
+ }
+ if (Array.isArray(cs)) {
+ const mode = xref.fetchIfRef(cs[0]).name;
+ let params, numComps, baseCS, whitePoint, blackPoint, gamma;
+ switch (mode) {
+ case "G":
+ case "DeviceGray":
+ return this.singletons.gray;
+ case "RGB":
+ case "DeviceRGB":
+ return this.singletons.rgb;
+ case "CMYK":
+ case "DeviceCMYK":
+ return this.singletons.cmyk;
+ case "CalGray":
+ params = xref.fetchIfRef(cs[1]);
+ whitePoint = params.getArray("WhitePoint");
+ blackPoint = params.getArray("BlackPoint");
+ gamma = params.get("Gamma");
+ return new CalGrayCS(whitePoint, blackPoint, gamma);
+ case "CalRGB":
+ params = xref.fetchIfRef(cs[1]);
+ whitePoint = params.getArray("WhitePoint");
+ blackPoint = params.getArray("BlackPoint");
+ gamma = params.getArray("Gamma");
+ const matrix = params.getArray("Matrix");
+ return new CalRGBCS(whitePoint, blackPoint, gamma, matrix);
+ case "ICCBased":
+ const stream = xref.fetchIfRef(cs[1]);
+ const dict = stream.dict;
+ numComps = dict.get("N");
+ const alt = dict.get("Alternate");
+ if (alt) {
+ const altCS = this._parse(alt, xref, resources, pdfFunctionFactory);
+ if (altCS.numComps === numComps) {
+ return altCS;
+ }
+ warn("ICCBased color space: Ignoring incorrect /Alternate entry.");
+ }
+ if (numComps === 1) {
+ return this.singletons.gray;
+ } else if (numComps === 3) {
+ return this.singletons.rgb;
+ } else if (numComps === 4) {
+ return this.singletons.cmyk;
+ }
+ break;
+ case "Pattern":
+ baseCS = cs[1] || null;
+ if (baseCS) {
+ baseCS = this._parse(baseCS, xref, resources, pdfFunctionFactory);
+ }
+ return new PatternCS(baseCS);
+ case "I":
+ case "Indexed":
+ baseCS = this._parse(cs[1], xref, resources, pdfFunctionFactory);
+ const hiVal = xref.fetchIfRef(cs[2]) + 1;
+ const lookup = xref.fetchIfRef(cs[3]);
+ return new IndexedCS(baseCS, hiVal, lookup);
+ case "Separation":
+ case "DeviceN":
+ const name = xref.fetchIfRef(cs[1]);
+ numComps = Array.isArray(name) ? name.length : 1;
+ baseCS = this._parse(cs[2], xref, resources, pdfFunctionFactory);
+ const tintFn = pdfFunctionFactory.create(cs[3]);
+ return new AlternateCS(numComps, baseCS, tintFn);
+ case "Lab":
+ params = xref.fetchIfRef(cs[1]);
+ whitePoint = params.getArray("WhitePoint");
+ blackPoint = params.getArray("BlackPoint");
+ const range = params.getArray("Range");
+ return new LabCS(whitePoint, blackPoint, range);
+ default:
+ throw new FormatError(`Unimplemented ColorSpace object: ${mode}`);
+ }
+ }
+ throw new FormatError(`Unrecognized ColorSpace object: ${cs}`);
+ }
+ static isDefaultDecode(decode, numComps) {
+ if (!Array.isArray(decode)) {
+ return true;
+ }
+ if (numComps * 2 !== decode.length) {
+ warn("The decode map is not the correct length");
+ return true;
+ }
+ for (let i = 0, ii = decode.length; i < ii; i += 2) {
+ if (decode[i] !== 0 || decode[i + 1] !== 1) {
+ return false;
+ }
+ }
+ return true;
+ }
+ static get singletons() {
+ return shadow(this, "singletons", {
+ get gray() {
+ return shadow(this, "gray", new DeviceGrayCS());
+ },
+ get rgb() {
+ return shadow(this, "rgb", new DeviceRgbCS());
+ },
+ get cmyk() {
+ return shadow(this, "cmyk", new DeviceCmykCS());
+ }
+ });
+ }
+}
+class AlternateCS extends ColorSpace {
+ constructor(numComps, base, tintFn) {
+ super("Alternate", numComps);
+ this.base = base;
+ this.tintFn = tintFn;
+ this.tmpBuf = new Float32Array(base.numComps);
+ }
+ getRgbItem(src, srcOffset, dest, destOffset) {
+ const tmpBuf = this.tmpBuf;
+ this.tintFn(src, srcOffset, tmpBuf, 0);
+ this.base.getRgbItem(tmpBuf, 0, dest, destOffset);
+ }
+ getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
+ const tintFn = this.tintFn;
+ const base = this.base;
+ const scale = 1 / ((1 << bits) - 1);
+ const baseNumComps = base.numComps;
+ const usesZeroToOneRange = base.usesZeroToOneRange;
+ const isPassthrough = (base.isPassthrough(8) || !usesZeroToOneRange) && alpha01 === 0;
+ let pos = isPassthrough ? destOffset : 0;
+ const baseBuf = isPassthrough ? dest : new Uint8ClampedArray(baseNumComps * count);
+ const numComps = this.numComps;
+ const scaled = new Float32Array(numComps);
+ const tinted = new Float32Array(baseNumComps);
+ let i, j;
+ for (i = 0; i < count; i++) {
+ for (j = 0; j < numComps; j++) {
+ scaled[j] = src[srcOffset++] * scale;
+ }
+ tintFn(scaled, 0, tinted, 0);
+ if (usesZeroToOneRange) {
+ for (j = 0; j < baseNumComps; j++) {
+ baseBuf[pos++] = tinted[j] * 255;
+ }
+ } else {
+ base.getRgbItem(tinted, 0, baseBuf, pos);
+ pos += baseNumComps;
+ }
+ }
+ if (!isPassthrough) {
+ base.getRgbBuffer(baseBuf, 0, count, dest, destOffset, 8, alpha01);
+ }
+ }
+ getOutputLength(inputLength, alpha01) {
+ return this.base.getOutputLength(inputLength * this.base.numComps / this.numComps, alpha01);
+ }
+}
+class PatternCS extends ColorSpace {
+ constructor(baseCS) {
+ super("Pattern", null);
+ this.base = baseCS;
+ }
+ isDefaultDecode(decodeMap, bpc) {
+ unreachable("Should not call PatternCS.isDefaultDecode");
+ }
+}
+class IndexedCS extends ColorSpace {
+ constructor(base, highVal, lookup) {
+ super("Indexed", 1);
+ this.base = base;
+ this.highVal = highVal;
+ const length = base.numComps * highVal;
+ this.lookup = new Uint8Array(length);
+ if (lookup instanceof BaseStream) {
+ const bytes = lookup.getBytes(length);
+ this.lookup.set(bytes);
+ } else if (typeof lookup === "string") {
+ for (let i = 0; i < length; ++i) {
+ this.lookup[i] = lookup.charCodeAt(i) & 0xff;
+ }
+ } else {
+ throw new FormatError(`IndexedCS - unrecognized lookup table: ${lookup}`);
+ }
+ }
+ getRgbItem(src, srcOffset, dest, destOffset) {
+ const numComps = this.base.numComps;
+ const start = src[srcOffset] * numComps;
+ this.base.getRgbBuffer(this.lookup, start, 1, dest, destOffset, 8, 0);
+ }
+ getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
+ const base = this.base;
+ const numComps = base.numComps;
+ const outputDelta = base.getOutputLength(numComps, alpha01);
+ const lookup = this.lookup;
+ for (let i = 0; i < count; ++i) {
+ const lookupPos = src[srcOffset++] * numComps;
+ base.getRgbBuffer(lookup, lookupPos, 1, dest, destOffset, 8, alpha01);
+ destOffset += outputDelta;
+ }
+ }
+ getOutputLength(inputLength, alpha01) {
+ return this.base.getOutputLength(inputLength * this.base.numComps, alpha01);
+ }
+ isDefaultDecode(decodeMap, bpc) {
+ if (!Array.isArray(decodeMap)) {
+ return true;
+ }
+ if (decodeMap.length !== 2) {
+ warn("Decode map length is not correct");
+ return true;
+ }
+ if (!Number.isInteger(bpc) || bpc < 1) {
+ warn("Bits per component is not correct");
+ return true;
+ }
+ return decodeMap[0] === 0 && decodeMap[1] === (1 << bpc) - 1;
+ }
+}
+class DeviceGrayCS extends ColorSpace {
+ constructor() {
+ super("DeviceGray", 1);
+ }
+ getRgbItem(src, srcOffset, dest, destOffset) {
+ const c = src[srcOffset] * 255;
+ dest[destOffset] = dest[destOffset + 1] = dest[destOffset + 2] = c;
+ }
+ getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
+ const scale = 255 / ((1 << bits) - 1);
+ let j = srcOffset,
+ q = destOffset;
+ for (let i = 0; i < count; ++i) {
+ const c = scale * src[j++];
+ dest[q++] = c;
+ dest[q++] = c;
+ dest[q++] = c;
+ q += alpha01;
+ }
+ }
+ getOutputLength(inputLength, alpha01) {
+ return inputLength * (3 + alpha01);
+ }
+}
+class DeviceRgbCS extends ColorSpace {
+ constructor() {
+ super("DeviceRGB", 3);
+ }
+ getRgbItem(src, srcOffset, dest, destOffset) {
+ dest[destOffset] = src[srcOffset] * 255;
+ dest[destOffset + 1] = src[srcOffset + 1] * 255;
+ dest[destOffset + 2] = src[srcOffset + 2] * 255;
+ }
+ getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
+ if (bits === 8 && alpha01 === 0) {
+ dest.set(src.subarray(srcOffset, srcOffset + count * 3), destOffset);
+ return;
+ }
+ const scale = 255 / ((1 << bits) - 1);
+ let j = srcOffset,
+ q = destOffset;
+ for (let i = 0; i < count; ++i) {
+ dest[q++] = scale * src[j++];
+ dest[q++] = scale * src[j++];
+ dest[q++] = scale * src[j++];
+ q += alpha01;
+ }
+ }
+ getOutputLength(inputLength, alpha01) {
+ return inputLength * (3 + alpha01) / 3 | 0;
+ }
+ isPassthrough(bits) {
+ return bits === 8;
+ }
+}
+class DeviceCmykCS extends ColorSpace {
+ constructor() {
+ super("DeviceCMYK", 4);
+ }
+ #toRgb(src, srcOffset, srcScale, dest, destOffset) {
+ const c = src[srcOffset] * srcScale;
+ const m = src[srcOffset + 1] * srcScale;
+ const y = src[srcOffset + 2] * srcScale;
+ const k = src[srcOffset + 3] * srcScale;
+ dest[destOffset] = 255 + c * (-4.387332384609988 * c + 54.48615194189176 * m + 18.82290502165302 * y + 212.25662451639585 * k + -285.2331026137004) + m * (1.7149763477362134 * m - 5.6096736904047315 * y + -17.873870861415444 * k - 5.497006427196366) + y * (-2.5217340131683033 * y - 21.248923337353073 * k + 17.5119270841813) + k * (-21.86122147463605 * k - 189.48180835922747);
+ dest[destOffset + 1] = 255 + c * (8.841041422036149 * c + 60.118027045597366 * m + 6.871425592049007 * y + 31.159100130055922 * k + -79.2970844816548) + m * (-15.310361306967817 * m + 17.575251261109482 * y + 131.35250912493976 * k - 190.9453302588951) + y * (4.444339102852739 * y + 9.8632861493405 * k - 24.86741582555878) + k * (-20.737325471181034 * k - 187.80453709719578);
+ dest[destOffset + 2] = 255 + c * (0.8842522430003296 * c + 8.078677503112928 * m + 30.89978309703729 * y - 0.23883238689178934 * k + -14.183576799673286) + m * (10.49593273432072 * m + 63.02378494754052 * y + 50.606957656360734 * k - 112.23884253719248) + y * (0.03296041114873217 * y + 115.60384449646641 * k + -193.58209356861505) + k * (-22.33816807309886 * k - 180.12613974708367);
+ }
+ getRgbItem(src, srcOffset, dest, destOffset) {
+ this.#toRgb(src, srcOffset, 1, dest, destOffset);
+ }
+ getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
+ const scale = 1 / ((1 << bits) - 1);
+ for (let i = 0; i < count; i++) {
+ this.#toRgb(src, srcOffset, scale, dest, destOffset);
+ srcOffset += 4;
+ destOffset += 3 + alpha01;
+ }
+ }
+ getOutputLength(inputLength, alpha01) {
+ return inputLength / 4 * (3 + alpha01) | 0;
+ }
+}
+class CalGrayCS extends ColorSpace {
+ constructor(whitePoint, blackPoint, gamma) {
+ super("CalGray", 1);
+ if (!whitePoint) {
+ throw new FormatError("WhitePoint missing - required for color space CalGray");
+ }
+ [this.XW, this.YW, this.ZW] = whitePoint;
+ [this.XB, this.YB, this.ZB] = blackPoint || [0, 0, 0];
+ this.G = gamma || 1;
+ if (this.XW < 0 || this.ZW < 0 || this.YW !== 1) {
+ throw new FormatError(`Invalid WhitePoint components for ${this.name}, no fallback available`);
+ }
+ if (this.XB < 0 || this.YB < 0 || this.ZB < 0) {
+ info(`Invalid BlackPoint for ${this.name}, falling back to default.`);
+ this.XB = this.YB = this.ZB = 0;
+ }
+ if (this.XB !== 0 || this.YB !== 0 || this.ZB !== 0) {
+ warn(`${this.name}, BlackPoint: XB: ${this.XB}, YB: ${this.YB}, ` + `ZB: ${this.ZB}, only default values are supported.`);
+ }
+ if (this.G < 1) {
+ info(`Invalid Gamma: ${this.G} for ${this.name}, falling back to default.`);
+ this.G = 1;
+ }
+ }
+ #toRgb(src, srcOffset, dest, destOffset, scale) {
+ const A = src[srcOffset] * scale;
+ const AG = A ** this.G;
+ const L = this.YW * AG;
+ const val = Math.max(295.8 * L ** 0.3333333333333333 - 40.8, 0);
+ dest[destOffset] = val;
+ dest[destOffset + 1] = val;
+ dest[destOffset + 2] = val;
+ }
+ getRgbItem(src, srcOffset, dest, destOffset) {
+ this.#toRgb(src, srcOffset, dest, destOffset, 1);
+ }
+ getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
+ const scale = 1 / ((1 << bits) - 1);
+ for (let i = 0; i < count; ++i) {
+ this.#toRgb(src, srcOffset, dest, destOffset, scale);
+ srcOffset += 1;
+ destOffset += 3 + alpha01;
+ }
+ }
+ getOutputLength(inputLength, alpha01) {
+ return inputLength * (3 + alpha01);
+ }
+}
+class CalRGBCS extends ColorSpace {
+ static #BRADFORD_SCALE_MATRIX = new Float32Array([0.8951, 0.2664, -0.1614, -0.7502, 1.7135, 0.0367, 0.0389, -0.0685, 1.0296]);
+ static #BRADFORD_SCALE_INVERSE_MATRIX = new Float32Array([0.9869929, -0.1470543, 0.1599627, 0.4323053, 0.5183603, 0.0492912, -0.0085287, 0.0400428, 0.9684867]);
+ static #SRGB_D65_XYZ_TO_RGB_MATRIX = new Float32Array([3.2404542, -1.5371385, -0.4985314, -0.9692660, 1.8760108, 0.0415560, 0.0556434, -0.2040259, 1.0572252]);
+ static #FLAT_WHITEPOINT_MATRIX = new Float32Array([1, 1, 1]);
+ static #tempNormalizeMatrix = new Float32Array(3);
+ static #tempConvertMatrix1 = new Float32Array(3);
+ static #tempConvertMatrix2 = new Float32Array(3);
+ static #DECODE_L_CONSTANT = ((8 + 16) / 116) ** 3 / 8.0;
+ constructor(whitePoint, blackPoint, gamma, matrix) {
+ super("CalRGB", 3);
+ if (!whitePoint) {
+ throw new FormatError("WhitePoint missing - required for color space CalRGB");
+ }
+ const [XW, YW, ZW] = this.whitePoint = whitePoint;
+ const [XB, YB, ZB] = this.blackPoint = blackPoint || new Float32Array(3);
+ [this.GR, this.GG, this.GB] = gamma || new Float32Array([1, 1, 1]);
+ [this.MXA, this.MYA, this.MZA, this.MXB, this.MYB, this.MZB, this.MXC, this.MYC, this.MZC] = matrix || new Float32Array([1, 0, 0, 0, 1, 0, 0, 0, 1]);
+ if (XW < 0 || ZW < 0 || YW !== 1) {
+ throw new FormatError(`Invalid WhitePoint components for ${this.name}, no fallback available`);
+ }
+ if (XB < 0 || YB < 0 || ZB < 0) {
+ info(`Invalid BlackPoint for ${this.name} [${XB}, ${YB}, ${ZB}], ` + "falling back to default.");
+ this.blackPoint = new Float32Array(3);
+ }
+ if (this.GR < 0 || this.GG < 0 || this.GB < 0) {
+ info(`Invalid Gamma [${this.GR}, ${this.GG}, ${this.GB}] for ` + `${this.name}, falling back to default.`);
+ this.GR = this.GG = this.GB = 1;
+ }
+ }
+ #matrixProduct(a, b, result) {
+ result[0] = a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
+ result[1] = a[3] * b[0] + a[4] * b[1] + a[5] * b[2];
+ result[2] = a[6] * b[0] + a[7] * b[1] + a[8] * b[2];
+ }
+ #toFlat(sourceWhitePoint, LMS, result) {
+ result[0] = LMS[0] * 1 / sourceWhitePoint[0];
+ result[1] = LMS[1] * 1 / sourceWhitePoint[1];
+ result[2] = LMS[2] * 1 / sourceWhitePoint[2];
+ }
+ #toD65(sourceWhitePoint, LMS, result) {
+ const D65X = 0.95047;
+ const D65Y = 1;
+ const D65Z = 1.08883;
+ result[0] = LMS[0] * D65X / sourceWhitePoint[0];
+ result[1] = LMS[1] * D65Y / sourceWhitePoint[1];
+ result[2] = LMS[2] * D65Z / sourceWhitePoint[2];
+ }
+ #sRGBTransferFunction(color) {
+ if (color <= 0.0031308) {
+ return this.#adjustToRange(0, 1, 12.92 * color);
+ }
+ if (color >= 0.99554525) {
+ return 1;
+ }
+ return this.#adjustToRange(0, 1, (1 + 0.055) * color ** (1 / 2.4) - 0.055);
+ }
+ #adjustToRange(min, max, value) {
+ return Math.max(min, Math.min(max, value));
+ }
+ #decodeL(L) {
+ if (L < 0) {
+ return -this.#decodeL(-L);
+ }
+ if (L > 8.0) {
+ return ((L + 16) / 116) ** 3;
+ }
+ return L * CalRGBCS.#DECODE_L_CONSTANT;
+ }
+ #compensateBlackPoint(sourceBlackPoint, XYZ_Flat, result) {
+ if (sourceBlackPoint[0] === 0 && sourceBlackPoint[1] === 0 && sourceBlackPoint[2] === 0) {
+ result[0] = XYZ_Flat[0];
+ result[1] = XYZ_Flat[1];
+ result[2] = XYZ_Flat[2];
+ return;
+ }
+ const zeroDecodeL = this.#decodeL(0);
+ const X_DST = zeroDecodeL;
+ const X_SRC = this.#decodeL(sourceBlackPoint[0]);
+ const Y_DST = zeroDecodeL;
+ const Y_SRC = this.#decodeL(sourceBlackPoint[1]);
+ const Z_DST = zeroDecodeL;
+ const Z_SRC = this.#decodeL(sourceBlackPoint[2]);
+ const X_Scale = (1 - X_DST) / (1 - X_SRC);
+ const X_Offset = 1 - X_Scale;
+ const Y_Scale = (1 - Y_DST) / (1 - Y_SRC);
+ const Y_Offset = 1 - Y_Scale;
+ const Z_Scale = (1 - Z_DST) / (1 - Z_SRC);
+ const Z_Offset = 1 - Z_Scale;
+ result[0] = XYZ_Flat[0] * X_Scale + X_Offset;
+ result[1] = XYZ_Flat[1] * Y_Scale + Y_Offset;
+ result[2] = XYZ_Flat[2] * Z_Scale + Z_Offset;
+ }
+ #normalizeWhitePointToFlat(sourceWhitePoint, XYZ_In, result) {
+ if (sourceWhitePoint[0] === 1 && sourceWhitePoint[2] === 1) {
+ result[0] = XYZ_In[0];
+ result[1] = XYZ_In[1];
+ result[2] = XYZ_In[2];
+ return;
+ }
+ const LMS = result;
+ this.#matrixProduct(CalRGBCS.#BRADFORD_SCALE_MATRIX, XYZ_In, LMS);
+ const LMS_Flat = CalRGBCS.#tempNormalizeMatrix;
+ this.#toFlat(sourceWhitePoint, LMS, LMS_Flat);
+ this.#matrixProduct(CalRGBCS.#BRADFORD_SCALE_INVERSE_MATRIX, LMS_Flat, result);
+ }
+ #normalizeWhitePointToD65(sourceWhitePoint, XYZ_In, result) {
+ const LMS = result;
+ this.#matrixProduct(CalRGBCS.#BRADFORD_SCALE_MATRIX, XYZ_In, LMS);
+ const LMS_D65 = CalRGBCS.#tempNormalizeMatrix;
+ this.#toD65(sourceWhitePoint, LMS, LMS_D65);
+ this.#matrixProduct(CalRGBCS.#BRADFORD_SCALE_INVERSE_MATRIX, LMS_D65, result);
+ }
+ #toRgb(src, srcOffset, dest, destOffset, scale) {
+ const A = this.#adjustToRange(0, 1, src[srcOffset] * scale);
+ const B = this.#adjustToRange(0, 1, src[srcOffset + 1] * scale);
+ const C = this.#adjustToRange(0, 1, src[srcOffset + 2] * scale);
+ const AGR = A === 1 ? 1 : A ** this.GR;
+ const BGG = B === 1 ? 1 : B ** this.GG;
+ const CGB = C === 1 ? 1 : C ** this.GB;
+ const X = this.MXA * AGR + this.MXB * BGG + this.MXC * CGB;
+ const Y = this.MYA * AGR + this.MYB * BGG + this.MYC * CGB;
+ const Z = this.MZA * AGR + this.MZB * BGG + this.MZC * CGB;
+ const XYZ = CalRGBCS.#tempConvertMatrix1;
+ XYZ[0] = X;
+ XYZ[1] = Y;
+ XYZ[2] = Z;
+ const XYZ_Flat = CalRGBCS.#tempConvertMatrix2;
+ this.#normalizeWhitePointToFlat(this.whitePoint, XYZ, XYZ_Flat);
+ const XYZ_Black = CalRGBCS.#tempConvertMatrix1;
+ this.#compensateBlackPoint(this.blackPoint, XYZ_Flat, XYZ_Black);
+ const XYZ_D65 = CalRGBCS.#tempConvertMatrix2;
+ this.#normalizeWhitePointToD65(CalRGBCS.#FLAT_WHITEPOINT_MATRIX, XYZ_Black, XYZ_D65);
+ const SRGB = CalRGBCS.#tempConvertMatrix1;
+ this.#matrixProduct(CalRGBCS.#SRGB_D65_XYZ_TO_RGB_MATRIX, XYZ_D65, SRGB);
+ dest[destOffset] = this.#sRGBTransferFunction(SRGB[0]) * 255;
+ dest[destOffset + 1] = this.#sRGBTransferFunction(SRGB[1]) * 255;
+ dest[destOffset + 2] = this.#sRGBTransferFunction(SRGB[2]) * 255;
+ }
+ getRgbItem(src, srcOffset, dest, destOffset) {
+ this.#toRgb(src, srcOffset, dest, destOffset, 1);
+ }
+ getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
+ const scale = 1 / ((1 << bits) - 1);
+ for (let i = 0; i < count; ++i) {
+ this.#toRgb(src, srcOffset, dest, destOffset, scale);
+ srcOffset += 3;
+ destOffset += 3 + alpha01;
+ }
+ }
+ getOutputLength(inputLength, alpha01) {
+ return inputLength * (3 + alpha01) / 3 | 0;
+ }
+}
+class LabCS extends ColorSpace {
+ constructor(whitePoint, blackPoint, range) {
+ super("Lab", 3);
+ if (!whitePoint) {
+ throw new FormatError("WhitePoint missing - required for color space Lab");
+ }
+ [this.XW, this.YW, this.ZW] = whitePoint;
+ [this.amin, this.amax, this.bmin, this.bmax] = range || [-100, 100, -100, 100];
+ [this.XB, this.YB, this.ZB] = blackPoint || [0, 0, 0];
+ if (this.XW < 0 || this.ZW < 0 || this.YW !== 1) {
+ throw new FormatError("Invalid WhitePoint components, no fallback available");
+ }
+ if (this.XB < 0 || this.YB < 0 || this.ZB < 0) {
+ info("Invalid BlackPoint, falling back to default");
+ this.XB = this.YB = this.ZB = 0;
+ }
+ if (this.amin > this.amax || this.bmin > this.bmax) {
+ info("Invalid Range, falling back to defaults");
+ this.amin = -100;
+ this.amax = 100;
+ this.bmin = -100;
+ this.bmax = 100;
+ }
+ }
+ #fn_g(x) {
+ return x >= 6 / 29 ? x ** 3 : 108 / 841 * (x - 4 / 29);
+ }
+ #decode(value, high1, low2, high2) {
+ return low2 + value * (high2 - low2) / high1;
+ }
+ #toRgb(src, srcOffset, maxVal, dest, destOffset) {
+ let Ls = src[srcOffset];
+ let as = src[srcOffset + 1];
+ let bs = src[srcOffset + 2];
+ if (maxVal !== false) {
+ Ls = this.#decode(Ls, maxVal, 0, 100);
+ as = this.#decode(as, maxVal, this.amin, this.amax);
+ bs = this.#decode(bs, maxVal, this.bmin, this.bmax);
+ }
+ if (as > this.amax) {
+ as = this.amax;
+ } else if (as < this.amin) {
+ as = this.amin;
+ }
+ if (bs > this.bmax) {
+ bs = this.bmax;
+ } else if (bs < this.bmin) {
+ bs = this.bmin;
+ }
+ const M = (Ls + 16) / 116;
+ const L = M + as / 500;
+ const N = M - bs / 200;
+ const X = this.XW * this.#fn_g(L);
+ const Y = this.YW * this.#fn_g(M);
+ const Z = this.ZW * this.#fn_g(N);
+ let r, g, b;
+ if (this.ZW < 1) {
+ r = X * 3.1339 + Y * -1.617 + Z * -0.4906;
+ g = X * -0.9785 + Y * 1.916 + Z * 0.0333;
+ b = X * 0.072 + Y * -0.229 + Z * 1.4057;
+ } else {
+ r = X * 3.2406 + Y * -1.5372 + Z * -0.4986;
+ g = X * -0.9689 + Y * 1.8758 + Z * 0.0415;
+ b = X * 0.0557 + Y * -0.204 + Z * 1.057;
+ }
+ dest[destOffset] = Math.sqrt(r) * 255;
+ dest[destOffset + 1] = Math.sqrt(g) * 255;
+ dest[destOffset + 2] = Math.sqrt(b) * 255;
+ }
+ getRgbItem(src, srcOffset, dest, destOffset) {
+ this.#toRgb(src, srcOffset, false, dest, destOffset);
+ }
+ getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
+ const maxVal = (1 << bits) - 1;
+ for (let i = 0; i < count; i++) {
+ this.#toRgb(src, srcOffset, maxVal, dest, destOffset);
+ srcOffset += 3;
+ destOffset += 3 + alpha01;
+ }
+ }
+ getOutputLength(inputLength, alpha01) {
+ return inputLength * (3 + alpha01) / 3 | 0;
+ }
+ isDefaultDecode(decodeMap, bpc) {
+ return true;
+ }
+ get usesZeroToOneRange() {
+ return shadow(this, "usesZeroToOneRange", false);
+ }
+}
+
+;// CONCATENATED MODULE: ./src/core/binary_cmap.js
+
+function hexToInt(a, size) {
+ let n = 0;
+ for (let i = 0; i <= size; i++) {
+ n = n << 8 | a[i];
+ }
+ return n >>> 0;
+}
+function hexToStr(a, size) {
+ if (size === 1) {
+ return String.fromCharCode(a[0], a[1]);
+ }
+ if (size === 3) {
+ return String.fromCharCode(a[0], a[1], a[2], a[3]);
+ }
+ return String.fromCharCode(...a.subarray(0, size + 1));
+}
+function addHex(a, b, size) {
+ let c = 0;
+ for (let i = size; i >= 0; i--) {
+ c += a[i] + b[i];
+ a[i] = c & 255;
+ c >>= 8;
+ }
+}
+function incHex(a, size) {
+ let c = 1;
+ for (let i = size; i >= 0 && c > 0; i--) {
+ c += a[i];
+ a[i] = c & 255;
+ c >>= 8;
+ }
+}
+const MAX_NUM_SIZE = 16;
+const MAX_ENCODED_NUM_SIZE = 19;
+class BinaryCMapStream {
+ constructor(data) {
+ this.buffer = data;
+ this.pos = 0;
+ this.end = data.length;
+ this.tmpBuf = new Uint8Array(MAX_ENCODED_NUM_SIZE);
+ }
+ readByte() {
+ if (this.pos >= this.end) {
+ return -1;
+ }
+ return this.buffer[this.pos++];
+ }
+ readNumber() {
+ let n = 0;
+ let last;
+ do {
+ const b = this.readByte();
+ if (b < 0) {
+ throw new FormatError("unexpected EOF in bcmap");
+ }
+ last = !(b & 0x80);
+ n = n << 7 | b & 0x7f;
+ } while (!last);
+ return n;
+ }
+ readSigned() {
+ const n = this.readNumber();
+ return n & 1 ? ~(n >>> 1) : n >>> 1;
+ }
+ readHex(num, size) {
+ num.set(this.buffer.subarray(this.pos, this.pos + size + 1));
+ this.pos += size + 1;
+ }
+ readHexNumber(num, size) {
+ let last;
+ const stack = this.tmpBuf;
+ let sp = 0;
+ do {
+ const b = this.readByte();
+ if (b < 0) {
+ throw new FormatError("unexpected EOF in bcmap");
+ }
+ last = !(b & 0x80);
+ stack[sp++] = b & 0x7f;
+ } while (!last);
+ let i = size,
+ buffer = 0,
+ bufferSize = 0;
+ while (i >= 0) {
+ while (bufferSize < 8 && stack.length > 0) {
+ buffer |= stack[--sp] << bufferSize;
+ bufferSize += 7;
+ }
+ num[i] = buffer & 255;
+ i--;
+ buffer >>= 8;
+ bufferSize -= 8;
+ }
+ }
+ readHexSigned(num, size) {
+ this.readHexNumber(num, size);
+ const sign = num[size] & 1 ? 255 : 0;
+ let c = 0;
+ for (let i = 0; i <= size; i++) {
+ c = (c & 1) << 8 | num[i];
+ num[i] = c >> 1 ^ sign;
+ }
+ }
+ readString() {
+ const len = this.readNumber(),
+ buf = new Array(len);
+ for (let i = 0; i < len; i++) {
+ buf[i] = this.readNumber();
+ }
+ return String.fromCharCode(...buf);
+ }
+}
+class BinaryCMapReader {
+ async process(data, cMap, extend) {
+ const stream = new BinaryCMapStream(data);
+ const header = stream.readByte();
+ cMap.vertical = !!(header & 1);
+ let useCMap = null;
+ const start = new Uint8Array(MAX_NUM_SIZE);
+ const end = new Uint8Array(MAX_NUM_SIZE);
+ const char = new Uint8Array(MAX_NUM_SIZE);
+ const charCode = new Uint8Array(MAX_NUM_SIZE);
+ const tmp = new Uint8Array(MAX_NUM_SIZE);
+ let code;
+ let b;
+ while ((b = stream.readByte()) >= 0) {
+ const type = b >> 5;
+ if (type === 7) {
+ switch (b & 0x1f) {
+ case 0:
+ stream.readString();
+ break;
+ case 1:
+ useCMap = stream.readString();
+ break;
+ }
+ continue;
+ }
+ const sequence = !!(b & 0x10);
+ const dataSize = b & 15;
+ if (dataSize + 1 > MAX_NUM_SIZE) {
+ throw new Error("BinaryCMapReader.process: Invalid dataSize.");
+ }
+ const ucs2DataSize = 1;
+ const subitemsCount = stream.readNumber();
+ switch (type) {
+ case 0:
+ stream.readHex(start, dataSize);
+ stream.readHexNumber(end, dataSize);
+ addHex(end, start, dataSize);
+ cMap.addCodespaceRange(dataSize + 1, hexToInt(start, dataSize), hexToInt(end, dataSize));
+ for (let i = 1; i < subitemsCount; i++) {
+ incHex(end, dataSize);
+ stream.readHexNumber(start, dataSize);
+ addHex(start, end, dataSize);
+ stream.readHexNumber(end, dataSize);
+ addHex(end, start, dataSize);
+ cMap.addCodespaceRange(dataSize + 1, hexToInt(start, dataSize), hexToInt(end, dataSize));
+ }
+ break;
+ case 1:
+ stream.readHex(start, dataSize);
+ stream.readHexNumber(end, dataSize);
+ addHex(end, start, dataSize);
+ stream.readNumber();
+ for (let i = 1; i < subitemsCount; i++) {
+ incHex(end, dataSize);
+ stream.readHexNumber(start, dataSize);
+ addHex(start, end, dataSize);
+ stream.readHexNumber(end, dataSize);
+ addHex(end, start, dataSize);
+ stream.readNumber();
+ }
+ break;
+ case 2:
+ stream.readHex(char, dataSize);
+ code = stream.readNumber();
+ cMap.mapOne(hexToInt(char, dataSize), code);
+ for (let i = 1; i < subitemsCount; i++) {
+ incHex(char, dataSize);
+ if (!sequence) {
+ stream.readHexNumber(tmp, dataSize);
+ addHex(char, tmp, dataSize);
+ }
+ code = stream.readSigned() + (code + 1);
+ cMap.mapOne(hexToInt(char, dataSize), code);
+ }
+ break;
+ case 3:
+ stream.readHex(start, dataSize);
+ stream.readHexNumber(end, dataSize);
+ addHex(end, start, dataSize);
+ code = stream.readNumber();
+ cMap.mapCidRange(hexToInt(start, dataSize), hexToInt(end, dataSize), code);
+ for (let i = 1; i < subitemsCount; i++) {
+ incHex(end, dataSize);
+ if (!sequence) {
+ stream.readHexNumber(start, dataSize);
+ addHex(start, end, dataSize);
+ } else {
+ start.set(end);
+ }
+ stream.readHexNumber(end, dataSize);
+ addHex(end, start, dataSize);
+ code = stream.readNumber();
+ cMap.mapCidRange(hexToInt(start, dataSize), hexToInt(end, dataSize), code);
+ }
+ break;
+ case 4:
+ stream.readHex(char, ucs2DataSize);
+ stream.readHex(charCode, dataSize);
+ cMap.mapOne(hexToInt(char, ucs2DataSize), hexToStr(charCode, dataSize));
+ for (let i = 1; i < subitemsCount; i++) {
+ incHex(char, ucs2DataSize);
+ if (!sequence) {
+ stream.readHexNumber(tmp, ucs2DataSize);
+ addHex(char, tmp, ucs2DataSize);
+ }
+ incHex(charCode, dataSize);
+ stream.readHexSigned(tmp, dataSize);
+ addHex(charCode, tmp, dataSize);
+ cMap.mapOne(hexToInt(char, ucs2DataSize), hexToStr(charCode, dataSize));
+ }
+ break;
+ case 5:
+ stream.readHex(start, ucs2DataSize);
+ stream.readHexNumber(end, ucs2DataSize);
+ addHex(end, start, ucs2DataSize);
+ stream.readHex(charCode, dataSize);
+ cMap.mapBfRange(hexToInt(start, ucs2DataSize), hexToInt(end, ucs2DataSize), hexToStr(charCode, dataSize));
+ for (let i = 1; i < subitemsCount; i++) {
+ incHex(end, ucs2DataSize);
+ if (!sequence) {
+ stream.readHexNumber(start, ucs2DataSize);
+ addHex(start, end, ucs2DataSize);
+ } else {
+ start.set(end);
+ }
+ stream.readHexNumber(end, ucs2DataSize);
+ addHex(end, start, ucs2DataSize);
+ stream.readHex(charCode, dataSize);
+ cMap.mapBfRange(hexToInt(start, ucs2DataSize), hexToInt(end, ucs2DataSize), hexToStr(charCode, dataSize));
+ }
+ break;
+ default:
+ throw new Error(`BinaryCMapReader.process - unknown type: ${type}`);
+ }
+ }
+ if (useCMap) {
+ return extend(useCMap);
+ }
+ return cMap;
+ }
+}
+
+;// CONCATENATED MODULE: ./src/core/decode_stream.js
+
+
+const emptyBuffer = new Uint8Array(0);
+class DecodeStream extends BaseStream {
+ constructor(maybeMinBufferLength) {
+ super();
+ this._rawMinBufferLength = maybeMinBufferLength || 0;
+ this.pos = 0;
+ this.bufferLength = 0;
+ this.eof = false;
+ this.buffer = emptyBuffer;
+ this.minBufferLength = 512;
+ if (maybeMinBufferLength) {
+ while (this.minBufferLength < maybeMinBufferLength) {
+ this.minBufferLength *= 2;
+ }
+ }
+ }
+ get isEmpty() {
+ while (!this.eof && this.bufferLength === 0) {
+ this.readBlock();
+ }
+ return this.bufferLength === 0;
+ }
+ ensureBuffer(requested) {
+ const buffer = this.buffer;
+ if (requested <= buffer.byteLength) {
+ return buffer;
+ }
+ let size = this.minBufferLength;
+ while (size < requested) {
+ size *= 2;
+ }
+ const buffer2 = new Uint8Array(size);
+ buffer2.set(buffer);
+ return this.buffer = buffer2;
+ }
+ getByte() {
+ const pos = this.pos;
+ while (this.bufferLength <= pos) {
+ if (this.eof) {
+ return -1;
+ }
+ this.readBlock();
+ }
+ return this.buffer[this.pos++];
+ }
+ getBytes(length) {
+ const pos = this.pos;
+ let end;
+ if (length) {
+ this.ensureBuffer(pos + length);
+ end = pos + length;
+ while (!this.eof && this.bufferLength < end) {
+ this.readBlock();
+ }
+ const bufEnd = this.bufferLength;
+ if (end > bufEnd) {
+ end = bufEnd;
+ }
+ } else {
+ while (!this.eof) {
+ this.readBlock();
+ }
+ end = this.bufferLength;
+ }
+ this.pos = end;
+ return this.buffer.subarray(pos, end);
+ }
+ reset() {
+ this.pos = 0;
+ }
+ makeSubStream(start, length, dict = null) {
+ if (length === undefined) {
+ while (!this.eof) {
+ this.readBlock();
+ }
+ } else {
+ const end = start + length;
+ while (this.bufferLength <= end && !this.eof) {
+ this.readBlock();
+ }
+ }
+ return new Stream(this.buffer, start, length, dict);
+ }
+ getBaseStreams() {
+ return this.str ? this.str.getBaseStreams() : null;
+ }
+}
+class StreamsSequenceStream extends DecodeStream {
+ constructor(streams, onError = null) {
+ let maybeLength = 0;
+ for (const stream of streams) {
+ maybeLength += stream instanceof DecodeStream ? stream._rawMinBufferLength : stream.length;
+ }
+ super(maybeLength);
+ this.streams = streams;
+ this._onError = onError;
+ }
+ readBlock() {
+ const streams = this.streams;
+ if (streams.length === 0) {
+ this.eof = true;
+ return;
+ }
+ const stream = streams.shift();
+ let chunk;
+ try {
+ chunk = stream.getBytes();
+ } catch (reason) {
+ if (this._onError) {
+ this._onError(reason, stream.dict?.objId);
+ return;
+ }
+ throw reason;
+ }
+ const bufferLength = this.bufferLength;
+ const newLength = bufferLength + chunk.length;
+ const buffer = this.ensureBuffer(newLength);
+ buffer.set(chunk, bufferLength);
+ this.bufferLength = newLength;
+ }
+ getBaseStreams() {
+ const baseStreamsBuf = [];
+ for (const stream of this.streams) {
+ const baseStreams = stream.getBaseStreams();
+ if (baseStreams) {
+ baseStreamsBuf.push(...baseStreams);
+ }
+ }
+ return baseStreamsBuf.length > 0 ? baseStreamsBuf : null;
+ }
+}
+
+;// CONCATENATED MODULE: ./src/core/ascii_85_stream.js
+
+
+class Ascii85Stream extends DecodeStream {
+ constructor(str, maybeLength) {
+ if (maybeLength) {
+ maybeLength *= 0.8;
+ }
+ super(maybeLength);
+ this.str = str;
+ this.dict = str.dict;
+ this.input = new Uint8Array(5);
+ }
+ readBlock() {
+ const TILDA_CHAR = 0x7e;
+ const Z_LOWER_CHAR = 0x7a;
+ const EOF = -1;
+ const str = this.str;
+ let c = str.getByte();
+ while (isWhiteSpace(c)) {
+ c = str.getByte();
+ }
+ if (c === EOF || c === TILDA_CHAR) {
+ this.eof = true;
+ return;
+ }
+ const bufferLength = this.bufferLength;
+ let buffer, i;
+ if (c === Z_LOWER_CHAR) {
+ buffer = this.ensureBuffer(bufferLength + 4);
+ for (i = 0; i < 4; ++i) {
+ buffer[bufferLength + i] = 0;
+ }
+ this.bufferLength += 4;
+ } else {
+ const input = this.input;
+ input[0] = c;
+ for (i = 1; i < 5; ++i) {
+ c = str.getByte();
+ while (isWhiteSpace(c)) {
+ c = str.getByte();
+ }
+ input[i] = c;
+ if (c === EOF || c === TILDA_CHAR) {
+ break;
+ }
+ }
+ buffer = this.ensureBuffer(bufferLength + i - 1);
+ this.bufferLength += i - 1;
+ if (i < 5) {
+ for (; i < 5; ++i) {
+ input[i] = 0x21 + 84;
+ }
+ this.eof = true;
+ }
+ let t = 0;
+ for (i = 0; i < 5; ++i) {
+ t = t * 85 + (input[i] - 0x21);
+ }
+ for (i = 3; i >= 0; --i) {
+ buffer[bufferLength + i] = t & 0xff;
+ t >>= 8;
+ }
+ }
+ }
+}
+
+;// CONCATENATED MODULE: ./src/core/ascii_hex_stream.js
+
+class AsciiHexStream extends DecodeStream {
+ constructor(str, maybeLength) {
+ if (maybeLength) {
+ maybeLength *= 0.5;
+ }
+ super(maybeLength);
+ this.str = str;
+ this.dict = str.dict;
+ this.firstDigit = -1;
+ }
+ readBlock() {
+ const UPSTREAM_BLOCK_SIZE = 8000;
+ const bytes = this.str.getBytes(UPSTREAM_BLOCK_SIZE);
+ if (!bytes.length) {
+ this.eof = true;
+ return;
+ }
+ const maxDecodeLength = bytes.length + 1 >> 1;
+ const buffer = this.ensureBuffer(this.bufferLength + maxDecodeLength);
+ let bufferLength = this.bufferLength;
+ let firstDigit = this.firstDigit;
+ for (const ch of bytes) {
+ let digit;
+ if (ch >= 0x30 && ch <= 0x39) {
+ digit = ch & 0x0f;
+ } else if (ch >= 0x41 && ch <= 0x46 || ch >= 0x61 && ch <= 0x66) {
+ digit = (ch & 0x0f) + 9;
+ } else if (ch === 0x3e) {
+ this.eof = true;
+ break;
+ } else {
+ continue;
+ }
+ if (firstDigit < 0) {
+ firstDigit = digit;
+ } else {
+ buffer[bufferLength++] = firstDigit << 4 | digit;
+ firstDigit = -1;
+ }
+ }
+ if (firstDigit >= 0 && this.eof) {
+ buffer[bufferLength++] = firstDigit << 4;
+ firstDigit = -1;
+ }
+ this.firstDigit = firstDigit;
+ this.bufferLength = bufferLength;
+ }
+}
+
+;// CONCATENATED MODULE: ./src/core/ccitt.js
+
+const ccittEOL = -2;
+const ccittEOF = -1;
+const twoDimPass = 0;
+const twoDimHoriz = 1;
+const twoDimVert0 = 2;
+const twoDimVertR1 = 3;
+const twoDimVertL1 = 4;
+const twoDimVertR2 = 5;
+const twoDimVertL2 = 6;
+const twoDimVertR3 = 7;
+const twoDimVertL3 = 8;
+const twoDimTable = [[-1, -1], [-1, -1], [7, twoDimVertL3], [7, twoDimVertR3], [6, twoDimVertL2], [6, twoDimVertL2], [6, twoDimVertR2], [6, twoDimVertR2], [4, twoDimPass], [4, twoDimPass], [4, twoDimPass], [4, twoDimPass], [4, twoDimPass], [4, twoDimPass], [4, twoDimPass], [4, twoDimPass], [3, twoDimHoriz], [3, twoDimHoriz], [3, twoDimHoriz], [3, twoDimHoriz], [3, twoDimHoriz], [3, twoDimHoriz], [3, twoDimHoriz], [3, twoDimHoriz], [3, twoDimHoriz], [3, twoDimHoriz], [3, twoDimHoriz], [3, twoDimHoriz], [3, twoDimHoriz], [3, twoDimHoriz], [3, twoDimHoriz], [3, twoDimHoriz], [3, twoDimVertL1], [3, twoDimVertL1], [3, twoDimVertL1], [3, twoDimVertL1], [3, twoDimVertL1], [3, twoDimVertL1], [3, twoDimVertL1], [3, twoDimVertL1], [3, twoDimVertL1], [3, twoDimVertL1], [3, twoDimVertL1], [3, twoDimVertL1], [3, twoDimVertL1], [3, twoDimVertL1], [3, twoDimVertL1], [3, twoDimVertL1], [3, twoDimVertR1], [3, twoDimVertR1], [3, twoDimVertR1], [3, twoDimVertR1], [3, twoDimVertR1], [3, twoDimVertR1], [3, twoDimVertR1], [3, twoDimVertR1], [3, twoDimVertR1], [3, twoDimVertR1], [3, twoDimVertR1], [3, twoDimVertR1], [3, twoDimVertR1], [3, twoDimVertR1], [3, twoDimVertR1], [3, twoDimVertR1], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0]];
+const whiteTable1 = [[-1, -1], [12, ccittEOL], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [11, 1792], [11, 1792], [12, 1984], [12, 2048], [12, 2112], [12, 2176], [12, 2240], [12, 2304], [11, 1856], [11, 1856], [11, 1920], [11, 1920], [12, 2368], [12, 2432], [12, 2496], [12, 2560]];
+const whiteTable2 = [[-1, -1], [-1, -1], [-1, -1], [-1, -1], [8, 29], [8, 29], [8, 30], [8, 30], [8, 45], [8, 45], [8, 46], [8, 46], [7, 22], [7, 22], [7, 22], [7, 22], [7, 23], [7, 23], [7, 23], [7, 23], [8, 47], [8, 47], [8, 48], [8, 48], [6, 13], [6, 13], [6, 13], [6, 13], [6, 13], [6, 13], [6, 13], [6, 13], [7, 20], [7, 20], [7, 20], [7, 20], [8, 33], [8, 33], [8, 34], [8, 34], [8, 35], [8, 35], [8, 36], [8, 36], [8, 37], [8, 37], [8, 38], [8, 38], [7, 19], [7, 19], [7, 19], [7, 19], [8, 31], [8, 31], [8, 32], [8, 32], [6, 1], [6, 1], [6, 1], [6, 1], [6, 1], [6, 1], [6, 1], [6, 1], [6, 12], [6, 12], [6, 12], [6, 12], [6, 12], [6, 12], [6, 12], [6, 12], [8, 53], [8, 53], [8, 54], [8, 54], [7, 26], [7, 26], [7, 26], [7, 26], [8, 39], [8, 39], [8, 40], [8, 40], [8, 41], [8, 41], [8, 42], [8, 42], [8, 43], [8, 43], [8, 44], [8, 44], [7, 21], [7, 21], [7, 21], [7, 21], [7, 28], [7, 28], [7, 28], [7, 28], [8, 61], [8, 61], [8, 62], [8, 62], [8, 63], [8, 63], [8, 0], [8, 0], [8, 320], [8, 320], [8, 384], [8, 384], [5, 10], [5, 10], [5, 10], [5, 10], [5, 10], [5, 10], [5, 10], [5, 10], [5, 10], [5, 10], [5, 10], [5, 10], [5, 10], [5, 10], [5, 10], [5, 10], [5, 11], [5, 11], [5, 11], [5, 11], [5, 11], [5, 11], [5, 11], [5, 11], [5, 11], [5, 11], [5, 11], [5, 11], [5, 11], [5, 11], [5, 11], [5, 11], [7, 27], [7, 27], [7, 27], [7, 27], [8, 59], [8, 59], [8, 60], [8, 60], [9, 1472], [9, 1536], [9, 1600], [9, 1728], [7, 18], [7, 18], [7, 18], [7, 18], [7, 24], [7, 24], [7, 24], [7, 24], [8, 49], [8, 49], [8, 50], [8, 50], [8, 51], [8, 51], [8, 52], [8, 52], [7, 25], [7, 25], [7, 25], [7, 25], [8, 55], [8, 55], [8, 56], [8, 56], [8, 57], [8, 57], [8, 58], [8, 58], [6, 192], [6, 192], [6, 192], [6, 192], [6, 192], [6, 192], [6, 192], [6, 192], [6, 1664], [6, 1664], [6, 1664], [6, 1664], [6, 1664], [6, 1664], [6, 1664], [6, 1664], [8, 448], [8, 448], [8, 512], [8, 512], [9, 704], [9, 768], [8, 640], [8, 640], [8, 576], [8, 576], [9, 832], [9, 896], [9, 960], [9, 1024], [9, 1088], [9, 1152], [9, 1216], [9, 1280], [9, 1344], [9, 1408], [7, 256], [7, 256], [7, 256], [7, 256], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [5, 128], [5, 128], [5, 128], [5, 128], [5, 128], [5, 128], [5, 128], [5, 128], [5, 128], [5, 128], [5, 128], [5, 128], [5, 128], [5, 128], [5, 128], [5, 128], [5, 8], [5, 8], [5, 8], [5, 8], [5, 8], [5, 8], [5, 8], [5, 8], [5, 8], [5, 8], [5, 8], [5, 8], [5, 8], [5, 8], [5, 8], [5, 8], [5, 9], [5, 9], [5, 9], [5, 9], [5, 9], [5, 9], [5, 9], [5, 9], [5, 9], [5, 9], [5, 9], [5, 9], [5, 9], [5, 9], [5, 9], [5, 9], [6, 16], [6, 16], [6, 16], [6, 16], [6, 16], [6, 16], [6, 16], [6, 16], [6, 17], [6, 17], [6, 17], [6, 17], [6, 17], [6, 17], [6, 17], [6, 17], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [6, 14], [6, 14], [6, 14], [6, 14], [6, 14], [6, 14], [6, 14], [6, 14], [6, 15], [6, 15], [6, 15], [6, 15], [6, 15], [6, 15], [6, 15], [6, 15], [5, 64], [5, 64], [5, 64], [5, 64], [5, 64], [5, 64], [5, 64], [5, 64], [5, 64], [5, 64], [5, 64], [5, 64], [5, 64], [5, 64], [5, 64], [5, 64], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7]];
+const blackTable1 = [[-1, -1], [-1, -1], [12, ccittEOL], [12, ccittEOL], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [11, 1792], [11, 1792], [11, 1792], [11, 1792], [12, 1984], [12, 1984], [12, 2048], [12, 2048], [12, 2112], [12, 2112], [12, 2176], [12, 2176], [12, 2240], [12, 2240], [12, 2304], [12, 2304], [11, 1856], [11, 1856], [11, 1856], [11, 1856], [11, 1920], [11, 1920], [11, 1920], [11, 1920], [12, 2368], [12, 2368], [12, 2432], [12, 2432], [12, 2496], [12, 2496], [12, 2560], [12, 2560], [10, 18], [10, 18], [10, 18], [10, 18], [10, 18], [10, 18], [10, 18], [10, 18], [12, 52], [12, 52], [13, 640], [13, 704], [13, 768], [13, 832], [12, 55], [12, 55], [12, 56], [12, 56], [13, 1280], [13, 1344], [13, 1408], [13, 1472], [12, 59], [12, 59], [12, 60], [12, 60], [13, 1536], [13, 1600], [11, 24], [11, 24], [11, 24], [11, 24], [11, 25], [11, 25], [11, 25], [11, 25], [13, 1664], [13, 1728], [12, 320], [12, 320], [12, 384], [12, 384], [12, 448], [12, 448], [13, 512], [13, 576], [12, 53], [12, 53], [12, 54], [12, 54], [13, 896], [13, 960], [13, 1024], [13, 1088], [13, 1152], [13, 1216], [10, 64], [10, 64], [10, 64], [10, 64], [10, 64], [10, 64], [10, 64], [10, 64]];
+const blackTable2 = [[8, 13], [8, 13], [8, 13], [8, 13], [8, 13], [8, 13], [8, 13], [8, 13], [8, 13], [8, 13], [8, 13], [8, 13], [8, 13], [8, 13], [8, 13], [8, 13], [11, 23], [11, 23], [12, 50], [12, 51], [12, 44], [12, 45], [12, 46], [12, 47], [12, 57], [12, 58], [12, 61], [12, 256], [10, 16], [10, 16], [10, 16], [10, 16], [10, 17], [10, 17], [10, 17], [10, 17], [12, 48], [12, 49], [12, 62], [12, 63], [12, 30], [12, 31], [12, 32], [12, 33], [12, 40], [12, 41], [11, 22], [11, 22], [8, 14], [8, 14], [8, 14], [8, 14], [8, 14], [8, 14], [8, 14], [8, 14], [8, 14], [8, 14], [8, 14], [8, 14], [8, 14], [8, 14], [8, 14], [8, 14], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [9, 15], [9, 15], [9, 15], [9, 15], [9, 15], [9, 15], [9, 15], [9, 15], [12, 128], [12, 192], [12, 26], [12, 27], [12, 28], [12, 29], [11, 19], [11, 19], [11, 20], [11, 20], [12, 34], [12, 35], [12, 36], [12, 37], [12, 38], [12, 39], [11, 21], [11, 21], [12, 42], [12, 43], [10, 0], [10, 0], [10, 0], [10, 0], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12]];
+const blackTable3 = [[-1, -1], [-1, -1], [-1, -1], [-1, -1], [6, 9], [6, 8], [5, 7], [5, 7], [4, 6], [4, 6], [4, 6], [4, 6], [4, 5], [4, 5], [4, 5], [4, 5], [3, 1], [3, 1], [3, 1], [3, 1], [3, 1], [3, 1], [3, 1], [3, 1], [3, 4], [3, 4], [3, 4], [3, 4], [3, 4], [3, 4], [3, 4], [3, 4], [2, 3], [2, 3], [2, 3], [2, 3], [2, 3], [2, 3], [2, 3], [2, 3], [2, 3], [2, 3], [2, 3], [2, 3], [2, 3], [2, 3], [2, 3], [2, 3], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2]];
+class CCITTFaxDecoder {
+ constructor(source, options = {}) {
+ if (!source || typeof source.next !== "function") {
+ throw new Error('CCITTFaxDecoder - invalid "source" parameter.');
+ }
+ this.source = source;
+ this.eof = false;
+ this.encoding = options.K || 0;
+ this.eoline = options.EndOfLine || false;
+ this.byteAlign = options.EncodedByteAlign || false;
+ this.columns = options.Columns || 1728;
+ this.rows = options.Rows || 0;
+ this.eoblock = options.EndOfBlock ?? true;
+ this.black = options.BlackIs1 || false;
+ this.codingLine = new Uint32Array(this.columns + 1);
+ this.refLine = new Uint32Array(this.columns + 2);
+ this.codingLine[0] = this.columns;
+ this.codingPos = 0;
+ this.row = 0;
+ this.nextLine2D = this.encoding < 0;
+ this.inputBits = 0;
+ this.inputBuf = 0;
+ this.outputBits = 0;
+ this.rowsDone = false;
+ let code1;
+ while ((code1 = this._lookBits(12)) === 0) {
+ this._eatBits(1);
+ }
+ if (code1 === 1) {
+ this._eatBits(12);
+ }
+ if (this.encoding > 0) {
+ this.nextLine2D = !this._lookBits(1);
+ this._eatBits(1);
+ }
+ }
+ readNextChar() {
+ if (this.eof) {
+ return -1;
+ }
+ const refLine = this.refLine;
+ const codingLine = this.codingLine;
+ const columns = this.columns;
+ let refPos, blackPixels, bits, i;
+ if (this.outputBits === 0) {
+ if (this.rowsDone) {
+ this.eof = true;
+ }
+ if (this.eof) {
+ return -1;
+ }
+ this.err = false;
+ let code1, code2, code3;
+ if (this.nextLine2D) {
+ for (i = 0; codingLine[i] < columns; ++i) {
+ refLine[i] = codingLine[i];
+ }
+ refLine[i++] = columns;
+ refLine[i] = columns;
+ codingLine[0] = 0;
+ this.codingPos = 0;
+ refPos = 0;
+ blackPixels = 0;
+ while (codingLine[this.codingPos] < columns) {
+ code1 = this._getTwoDimCode();
+ switch (code1) {
+ case twoDimPass:
+ this._addPixels(refLine[refPos + 1], blackPixels);
+ if (refLine[refPos + 1] < columns) {
+ refPos += 2;
+ }
+ break;
+ case twoDimHoriz:
+ code1 = code2 = 0;
+ if (blackPixels) {
+ do {
+ code1 += code3 = this._getBlackCode();
+ } while (code3 >= 64);
+ do {
+ code2 += code3 = this._getWhiteCode();
+ } while (code3 >= 64);
+ } else {
+ do {
+ code1 += code3 = this._getWhiteCode();
+ } while (code3 >= 64);
+ do {
+ code2 += code3 = this._getBlackCode();
+ } while (code3 >= 64);
+ }
+ this._addPixels(codingLine[this.codingPos] + code1, blackPixels);
+ if (codingLine[this.codingPos] < columns) {
+ this._addPixels(codingLine[this.codingPos] + code2, blackPixels ^ 1);
+ }
+ while (refLine[refPos] <= codingLine[this.codingPos] && refLine[refPos] < columns) {
+ refPos += 2;
+ }
+ break;
+ case twoDimVertR3:
+ this._addPixels(refLine[refPos] + 3, blackPixels);
+ blackPixels ^= 1;
+ if (codingLine[this.codingPos] < columns) {
+ ++refPos;
+ while (refLine[refPos] <= codingLine[this.codingPos] && refLine[refPos] < columns) {
+ refPos += 2;
+ }
+ }
+ break;
+ case twoDimVertR2:
+ this._addPixels(refLine[refPos] + 2, blackPixels);
+ blackPixels ^= 1;
+ if (codingLine[this.codingPos] < columns) {
+ ++refPos;
+ while (refLine[refPos] <= codingLine[this.codingPos] && refLine[refPos] < columns) {
+ refPos += 2;
+ }
+ }
+ break;
+ case twoDimVertR1:
+ this._addPixels(refLine[refPos] + 1, blackPixels);
+ blackPixels ^= 1;
+ if (codingLine[this.codingPos] < columns) {
+ ++refPos;
+ while (refLine[refPos] <= codingLine[this.codingPos] && refLine[refPos] < columns) {
+ refPos += 2;
+ }
+ }
+ break;
+ case twoDimVert0:
+ this._addPixels(refLine[refPos], blackPixels);
+ blackPixels ^= 1;
+ if (codingLine[this.codingPos] < columns) {
+ ++refPos;
+ while (refLine[refPos] <= codingLine[this.codingPos] && refLine[refPos] < columns) {
+ refPos += 2;
+ }
+ }
+ break;
+ case twoDimVertL3:
+ this._addPixelsNeg(refLine[refPos] - 3, blackPixels);
+ blackPixels ^= 1;
+ if (codingLine[this.codingPos] < columns) {
+ if (refPos > 0) {
+ --refPos;
+ } else {
+ ++refPos;
+ }
+ while (refLine[refPos] <= codingLine[this.codingPos] && refLine[refPos] < columns) {
+ refPos += 2;
+ }
+ }
+ break;
+ case twoDimVertL2:
+ this._addPixelsNeg(refLine[refPos] - 2, blackPixels);
+ blackPixels ^= 1;
+ if (codingLine[this.codingPos] < columns) {
+ if (refPos > 0) {
+ --refPos;
+ } else {
+ ++refPos;
+ }
+ while (refLine[refPos] <= codingLine[this.codingPos] && refLine[refPos] < columns) {
+ refPos += 2;
+ }
+ }
+ break;
+ case twoDimVertL1:
+ this._addPixelsNeg(refLine[refPos] - 1, blackPixels);
+ blackPixels ^= 1;
+ if (codingLine[this.codingPos] < columns) {
+ if (refPos > 0) {
+ --refPos;
+ } else {
+ ++refPos;
+ }
+ while (refLine[refPos] <= codingLine[this.codingPos] && refLine[refPos] < columns) {
+ refPos += 2;
+ }
+ }
+ break;
+ case ccittEOF:
+ this._addPixels(columns, 0);
+ this.eof = true;
+ break;
+ default:
+ info("bad 2d code");
+ this._addPixels(columns, 0);
+ this.err = true;
+ }
+ }
+ } else {
+ codingLine[0] = 0;
+ this.codingPos = 0;
+ blackPixels = 0;
+ while (codingLine[this.codingPos] < columns) {
+ code1 = 0;
+ if (blackPixels) {
+ do {
+ code1 += code3 = this._getBlackCode();
+ } while (code3 >= 64);
+ } else {
+ do {
+ code1 += code3 = this._getWhiteCode();
+ } while (code3 >= 64);
+ }
+ this._addPixels(codingLine[this.codingPos] + code1, blackPixels);
+ blackPixels ^= 1;
+ }
+ }
+ let gotEOL = false;
+ if (this.byteAlign) {
+ this.inputBits &= ~7;
+ }
+ if (!this.eoblock && this.row === this.rows - 1) {
+ this.rowsDone = true;
+ } else {
+ code1 = this._lookBits(12);
+ if (this.eoline) {
+ while (code1 !== ccittEOF && code1 !== 1) {
+ this._eatBits(1);
+ code1 = this._lookBits(12);
+ }
+ } else {
+ while (code1 === 0) {
+ this._eatBits(1);
+ code1 = this._lookBits(12);
+ }
+ }
+ if (code1 === 1) {
+ this._eatBits(12);
+ gotEOL = true;
+ } else if (code1 === ccittEOF) {
+ this.eof = true;
+ }
+ }
+ if (!this.eof && this.encoding > 0 && !this.rowsDone) {
+ this.nextLine2D = !this._lookBits(1);
+ this._eatBits(1);
+ }
+ if (this.eoblock && gotEOL && this.byteAlign) {
+ code1 = this._lookBits(12);
+ if (code1 === 1) {
+ this._eatBits(12);
+ if (this.encoding > 0) {
+ this._lookBits(1);
+ this._eatBits(1);
+ }
+ if (this.encoding >= 0) {
+ for (i = 0; i < 4; ++i) {
+ code1 = this._lookBits(12);
+ if (code1 !== 1) {
+ info("bad rtc code: " + code1);
+ }
+ this._eatBits(12);
+ if (this.encoding > 0) {
+ this._lookBits(1);
+ this._eatBits(1);
+ }
+ }
+ }
+ this.eof = true;
+ }
+ } else if (this.err && this.eoline) {
+ while (true) {
+ code1 = this._lookBits(13);
+ if (code1 === ccittEOF) {
+ this.eof = true;
+ return -1;
+ }
+ if (code1 >> 1 === 1) {
+ break;
+ }
+ this._eatBits(1);
+ }
+ this._eatBits(12);
+ if (this.encoding > 0) {
+ this._eatBits(1);
+ this.nextLine2D = !(code1 & 1);
+ }
+ }
+ this.outputBits = codingLine[0] > 0 ? codingLine[this.codingPos = 0] : codingLine[this.codingPos = 1];
+ this.row++;
+ }
+ let c;
+ if (this.outputBits >= 8) {
+ c = this.codingPos & 1 ? 0 : 0xff;
+ this.outputBits -= 8;
+ if (this.outputBits === 0 && codingLine[this.codingPos] < columns) {
+ this.codingPos++;
+ this.outputBits = codingLine[this.codingPos] - codingLine[this.codingPos - 1];
+ }
+ } else {
+ bits = 8;
+ c = 0;
+ do {
+ if (typeof this.outputBits !== "number") {
+ throw new FormatError('Invalid /CCITTFaxDecode data, "outputBits" must be a number.');
+ }
+ if (this.outputBits > bits) {
+ c <<= bits;
+ if (!(this.codingPos & 1)) {
+ c |= 0xff >> 8 - bits;
+ }
+ this.outputBits -= bits;
+ bits = 0;
+ } else {
+ c <<= this.outputBits;
+ if (!(this.codingPos & 1)) {
+ c |= 0xff >> 8 - this.outputBits;
+ }
+ bits -= this.outputBits;
+ this.outputBits = 0;
+ if (codingLine[this.codingPos] < columns) {
+ this.codingPos++;
+ this.outputBits = codingLine[this.codingPos] - codingLine[this.codingPos - 1];
+ } else if (bits > 0) {
+ c <<= bits;
+ bits = 0;
+ }
+ }
+ } while (bits);
+ }
+ if (this.black) {
+ c ^= 0xff;
+ }
+ return c;
+ }
+ _addPixels(a1, blackPixels) {
+ const codingLine = this.codingLine;
+ let codingPos = this.codingPos;
+ if (a1 > codingLine[codingPos]) {
+ if (a1 > this.columns) {
+ info("row is wrong length");
+ this.err = true;
+ a1 = this.columns;
+ }
+ if (codingPos & 1 ^ blackPixels) {
+ ++codingPos;
+ }
+ codingLine[codingPos] = a1;
+ }
+ this.codingPos = codingPos;
+ }
+ _addPixelsNeg(a1, blackPixels) {
+ const codingLine = this.codingLine;
+ let codingPos = this.codingPos;
+ if (a1 > codingLine[codingPos]) {
+ if (a1 > this.columns) {
+ info("row is wrong length");
+ this.err = true;
+ a1 = this.columns;
+ }
+ if (codingPos & 1 ^ blackPixels) {
+ ++codingPos;
+ }
+ codingLine[codingPos] = a1;
+ } else if (a1 < codingLine[codingPos]) {
+ if (a1 < 0) {
+ info("invalid code");
+ this.err = true;
+ a1 = 0;
+ }
+ while (codingPos > 0 && a1 < codingLine[codingPos - 1]) {
+ --codingPos;
+ }
+ codingLine[codingPos] = a1;
+ }
+ this.codingPos = codingPos;
+ }
+ _findTableCode(start, end, table, limit) {
+ const limitValue = limit || 0;
+ for (let i = start; i <= end; ++i) {
+ let code = this._lookBits(i);
+ if (code === ccittEOF) {
+ return [true, 1, false];
+ }
+ if (i < end) {
+ code <<= end - i;
+ }
+ if (!limitValue || code >= limitValue) {
+ const p = table[code - limitValue];
+ if (p[0] === i) {
+ this._eatBits(i);
+ return [true, p[1], true];
+ }
+ }
+ }
+ return [false, 0, false];
+ }
+ _getTwoDimCode() {
+ let code = 0;
+ let p;
+ if (this.eoblock) {
+ code = this._lookBits(7);
+ p = twoDimTable[code];
+ if (p?.[0] > 0) {
+ this._eatBits(p[0]);
+ return p[1];
+ }
+ } else {
+ const result = this._findTableCode(1, 7, twoDimTable);
+ if (result[0] && result[2]) {
+ return result[1];
+ }
+ }
+ info("Bad two dim code");
+ return ccittEOF;
+ }
+ _getWhiteCode() {
+ let code = 0;
+ let p;
+ if (this.eoblock) {
+ code = this._lookBits(12);
+ if (code === ccittEOF) {
+ return 1;
+ }
+ p = code >> 5 === 0 ? whiteTable1[code] : whiteTable2[code >> 3];
+ if (p[0] > 0) {
+ this._eatBits(p[0]);
+ return p[1];
+ }
+ } else {
+ let result = this._findTableCode(1, 9, whiteTable2);
+ if (result[0]) {
+ return result[1];
+ }
+ result = this._findTableCode(11, 12, whiteTable1);
+ if (result[0]) {
+ return result[1];
+ }
+ }
+ info("bad white code");
+ this._eatBits(1);
+ return 1;
+ }
+ _getBlackCode() {
+ let code, p;
+ if (this.eoblock) {
+ code = this._lookBits(13);
+ if (code === ccittEOF) {
+ return 1;
+ }
+ if (code >> 7 === 0) {
+ p = blackTable1[code];
+ } else if (code >> 9 === 0 && code >> 7 !== 0) {
+ p = blackTable2[(code >> 1) - 64];
+ } else {
+ p = blackTable3[code >> 7];
+ }
+ if (p[0] > 0) {
+ this._eatBits(p[0]);
+ return p[1];
+ }
+ } else {
+ let result = this._findTableCode(2, 6, blackTable3);
+ if (result[0]) {
+ return result[1];
+ }
+ result = this._findTableCode(7, 12, blackTable2, 64);
+ if (result[0]) {
+ return result[1];
+ }
+ result = this._findTableCode(10, 13, blackTable1);
+ if (result[0]) {
+ return result[1];
+ }
+ }
+ info("bad black code");
+ this._eatBits(1);
+ return 1;
+ }
+ _lookBits(n) {
+ let c;
+ while (this.inputBits < n) {
+ if ((c = this.source.next()) === -1) {
+ if (this.inputBits === 0) {
+ return ccittEOF;
+ }
+ return this.inputBuf << n - this.inputBits & 0xffff >> 16 - n;
+ }
+ this.inputBuf = this.inputBuf << 8 | c;
+ this.inputBits += 8;
+ }
+ return this.inputBuf >> this.inputBits - n & 0xffff >> 16 - n;
+ }
+ _eatBits(n) {
+ if ((this.inputBits -= n) < 0) {
+ this.inputBits = 0;
+ }
+ }
+}
+
+;// CONCATENATED MODULE: ./src/core/ccitt_stream.js
+
+
+
+class CCITTFaxStream extends DecodeStream {
+ constructor(str, maybeLength, params) {
+ super(maybeLength);
+ this.str = str;
+ this.dict = str.dict;
+ if (!(params instanceof Dict)) {
+ params = Dict.empty;
+ }
+ const source = {
+ next() {
+ return str.getByte();
+ }
+ };
+ this.ccittFaxDecoder = new CCITTFaxDecoder(source, {
+ K: params.get("K"),
+ EndOfLine: params.get("EndOfLine"),
+ EncodedByteAlign: params.get("EncodedByteAlign"),
+ Columns: params.get("Columns"),
+ Rows: params.get("Rows"),
+ EndOfBlock: params.get("EndOfBlock"),
+ BlackIs1: params.get("BlackIs1")
+ });
+ }
+ readBlock() {
+ while (!this.eof) {
+ const c = this.ccittFaxDecoder.readNextChar();
+ if (c === -1) {
+ this.eof = true;
+ return;
+ }
+ this.ensureBuffer(this.bufferLength + 1);
+ this.buffer[this.bufferLength++] = c;
+ }
+ }
+}
+
+;// CONCATENATED MODULE: ./src/core/flate_stream.js
+
+
+const codeLenCodeMap = new Int32Array([16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15]);
+const lengthDecode = new Int32Array([0x00003, 0x00004, 0x00005, 0x00006, 0x00007, 0x00008, 0x00009, 0x0000a, 0x1000b, 0x1000d, 0x1000f, 0x10011, 0x20013, 0x20017, 0x2001b, 0x2001f, 0x30023, 0x3002b, 0x30033, 0x3003b, 0x40043, 0x40053, 0x40063, 0x40073, 0x50083, 0x500a3, 0x500c3, 0x500e3, 0x00102, 0x00102, 0x00102]);
+const distDecode = new Int32Array([0x00001, 0x00002, 0x00003, 0x00004, 0x10005, 0x10007, 0x20009, 0x2000d, 0x30011, 0x30019, 0x40021, 0x40031, 0x50041, 0x50061, 0x60081, 0x600c1, 0x70101, 0x70181, 0x80201, 0x80301, 0x90401, 0x90601, 0xa0801, 0xa0c01, 0xb1001, 0xb1801, 0xc2001, 0xc3001, 0xd4001, 0xd6001]);
+const fixedLitCodeTab = [new Int32Array([0x70100, 0x80050, 0x80010, 0x80118, 0x70110, 0x80070, 0x80030, 0x900c0, 0x70108, 0x80060, 0x80020, 0x900a0, 0x80000, 0x80080, 0x80040, 0x900e0, 0x70104, 0x80058, 0x80018, 0x90090, 0x70114, 0x80078, 0x80038, 0x900d0, 0x7010c, 0x80068, 0x80028, 0x900b0, 0x80008, 0x80088, 0x80048, 0x900f0, 0x70102, 0x80054, 0x80014, 0x8011c, 0x70112, 0x80074, 0x80034, 0x900c8, 0x7010a, 0x80064, 0x80024, 0x900a8, 0x80004, 0x80084, 0x80044, 0x900e8, 0x70106, 0x8005c, 0x8001c, 0x90098, 0x70116, 0x8007c, 0x8003c, 0x900d8, 0x7010e, 0x8006c, 0x8002c, 0x900b8, 0x8000c, 0x8008c, 0x8004c, 0x900f8, 0x70101, 0x80052, 0x80012, 0x8011a, 0x70111, 0x80072, 0x80032, 0x900c4, 0x70109, 0x80062, 0x80022, 0x900a4, 0x80002, 0x80082, 0x80042, 0x900e4, 0x70105, 0x8005a, 0x8001a, 0x90094, 0x70115, 0x8007a, 0x8003a, 0x900d4, 0x7010d, 0x8006a, 0x8002a, 0x900b4, 0x8000a, 0x8008a, 0x8004a, 0x900f4, 0x70103, 0x80056, 0x80016, 0x8011e, 0x70113, 0x80076, 0x80036, 0x900cc, 0x7010b, 0x80066, 0x80026, 0x900ac, 0x80006, 0x80086, 0x80046, 0x900ec, 0x70107, 0x8005e, 0x8001e, 0x9009c, 0x70117, 0x8007e, 0x8003e, 0x900dc, 0x7010f, 0x8006e, 0x8002e, 0x900bc, 0x8000e, 0x8008e, 0x8004e, 0x900fc, 0x70100, 0x80051, 0x80011, 0x80119, 0x70110, 0x80071, 0x80031, 0x900c2, 0x70108, 0x80061, 0x80021, 0x900a2, 0x80001, 0x80081, 0x80041, 0x900e2, 0x70104, 0x80059, 0x80019, 0x90092, 0x70114, 0x80079, 0x80039, 0x900d2, 0x7010c, 0x80069, 0x80029, 0x900b2, 0x80009, 0x80089, 0x80049, 0x900f2, 0x70102, 0x80055, 0x80015, 0x8011d, 0x70112, 0x80075, 0x80035, 0x900ca, 0x7010a, 0x80065, 0x80025, 0x900aa, 0x80005, 0x80085, 0x80045, 0x900ea, 0x70106, 0x8005d, 0x8001d, 0x9009a, 0x70116, 0x8007d, 0x8003d, 0x900da, 0x7010e, 0x8006d, 0x8002d, 0x900ba, 0x8000d, 0x8008d, 0x8004d, 0x900fa, 0x70101, 0x80053, 0x80013, 0x8011b, 0x70111, 0x80073, 0x80033, 0x900c6, 0x70109, 0x80063, 0x80023, 0x900a6, 0x80003, 0x80083, 0x80043, 0x900e6, 0x70105, 0x8005b, 0x8001b, 0x90096, 0x70115, 0x8007b, 0x8003b, 0x900d6, 0x7010d, 0x8006b, 0x8002b, 0x900b6, 0x8000b, 0x8008b, 0x8004b, 0x900f6, 0x70103, 0x80057, 0x80017, 0x8011f, 0x70113, 0x80077, 0x80037, 0x900ce, 0x7010b, 0x80067, 0x80027, 0x900ae, 0x80007, 0x80087, 0x80047, 0x900ee, 0x70107, 0x8005f, 0x8001f, 0x9009e, 0x70117, 0x8007f, 0x8003f, 0x900de, 0x7010f, 0x8006f, 0x8002f, 0x900be, 0x8000f, 0x8008f, 0x8004f, 0x900fe, 0x70100, 0x80050, 0x80010, 0x80118, 0x70110, 0x80070, 0x80030, 0x900c1, 0x70108, 0x80060, 0x80020, 0x900a1, 0x80000, 0x80080, 0x80040, 0x900e1, 0x70104, 0x80058, 0x80018, 0x90091, 0x70114, 0x80078, 0x80038, 0x900d1, 0x7010c, 0x80068, 0x80028, 0x900b1, 0x80008, 0x80088, 0x80048, 0x900f1, 0x70102, 0x80054, 0x80014, 0x8011c, 0x70112, 0x80074, 0x80034, 0x900c9, 0x7010a, 0x80064, 0x80024, 0x900a9, 0x80004, 0x80084, 0x80044, 0x900e9, 0x70106, 0x8005c, 0x8001c, 0x90099, 0x70116, 0x8007c, 0x8003c, 0x900d9, 0x7010e, 0x8006c, 0x8002c, 0x900b9, 0x8000c, 0x8008c, 0x8004c, 0x900f9, 0x70101, 0x80052, 0x80012, 0x8011a, 0x70111, 0x80072, 0x80032, 0x900c5, 0x70109, 0x80062, 0x80022, 0x900a5, 0x80002, 0x80082, 0x80042, 0x900e5, 0x70105, 0x8005a, 0x8001a, 0x90095, 0x70115, 0x8007a, 0x8003a, 0x900d5, 0x7010d, 0x8006a, 0x8002a, 0x900b5, 0x8000a, 0x8008a, 0x8004a, 0x900f5, 0x70103, 0x80056, 0x80016, 0x8011e, 0x70113, 0x80076, 0x80036, 0x900cd, 0x7010b, 0x80066, 0x80026, 0x900ad, 0x80006, 0x80086, 0x80046, 0x900ed, 0x70107, 0x8005e, 0x8001e, 0x9009d, 0x70117, 0x8007e, 0x8003e, 0x900dd, 0x7010f, 0x8006e, 0x8002e, 0x900bd, 0x8000e, 0x8008e, 0x8004e, 0x900fd, 0x70100, 0x80051, 0x80011, 0x80119, 0x70110, 0x80071, 0x80031, 0x900c3, 0x70108, 0x80061, 0x80021, 0x900a3, 0x80001, 0x80081, 0x80041, 0x900e3, 0x70104, 0x80059, 0x80019, 0x90093, 0x70114, 0x80079, 0x80039, 0x900d3, 0x7010c, 0x80069, 0x80029, 0x900b3, 0x80009, 0x80089, 0x80049, 0x900f3, 0x70102, 0x80055, 0x80015, 0x8011d, 0x70112, 0x80075, 0x80035, 0x900cb, 0x7010a, 0x80065, 0x80025, 0x900ab, 0x80005, 0x80085, 0x80045, 0x900eb, 0x70106, 0x8005d, 0x8001d, 0x9009b, 0x70116, 0x8007d, 0x8003d, 0x900db, 0x7010e, 0x8006d, 0x8002d, 0x900bb, 0x8000d, 0x8008d, 0x8004d, 0x900fb, 0x70101, 0x80053, 0x80013, 0x8011b, 0x70111, 0x80073, 0x80033, 0x900c7, 0x70109, 0x80063, 0x80023, 0x900a7, 0x80003, 0x80083, 0x80043, 0x900e7, 0x70105, 0x8005b, 0x8001b, 0x90097, 0x70115, 0x8007b, 0x8003b, 0x900d7, 0x7010d, 0x8006b, 0x8002b, 0x900b7, 0x8000b, 0x8008b, 0x8004b, 0x900f7, 0x70103, 0x80057, 0x80017, 0x8011f, 0x70113, 0x80077, 0x80037, 0x900cf, 0x7010b, 0x80067, 0x80027, 0x900af, 0x80007, 0x80087, 0x80047, 0x900ef, 0x70107, 0x8005f, 0x8001f, 0x9009f, 0x70117, 0x8007f, 0x8003f, 0x900df, 0x7010f, 0x8006f, 0x8002f, 0x900bf, 0x8000f, 0x8008f, 0x8004f, 0x900ff]), 9];
+const fixedDistCodeTab = [new Int32Array([0x50000, 0x50010, 0x50008, 0x50018, 0x50004, 0x50014, 0x5000c, 0x5001c, 0x50002, 0x50012, 0x5000a, 0x5001a, 0x50006, 0x50016, 0x5000e, 0x00000, 0x50001, 0x50011, 0x50009, 0x50019, 0x50005, 0x50015, 0x5000d, 0x5001d, 0x50003, 0x50013, 0x5000b, 0x5001b, 0x50007, 0x50017, 0x5000f, 0x00000]), 5];
+class FlateStream extends DecodeStream {
+ constructor(str, maybeLength) {
+ super(maybeLength);
+ this.str = str;
+ this.dict = str.dict;
+ const cmf = str.getByte();
+ const flg = str.getByte();
+ if (cmf === -1 || flg === -1) {
+ throw new FormatError(`Invalid header in flate stream: ${cmf}, ${flg}`);
+ }
+ if ((cmf & 0x0f) !== 0x08) {
+ throw new FormatError(`Unknown compression method in flate stream: ${cmf}, ${flg}`);
+ }
+ if (((cmf << 8) + flg) % 31 !== 0) {
+ throw new FormatError(`Bad FCHECK in flate stream: ${cmf}, ${flg}`);
+ }
+ if (flg & 0x20) {
+ throw new FormatError(`FDICT bit set in flate stream: ${cmf}, ${flg}`);
+ }
+ this.codeSize = 0;
+ this.codeBuf = 0;
+ }
+ getBits(bits) {
+ const str = this.str;
+ let codeSize = this.codeSize;
+ let codeBuf = this.codeBuf;
+ let b;
+ while (codeSize < bits) {
+ if ((b = str.getByte()) === -1) {
+ throw new FormatError("Bad encoding in flate stream");
+ }
+ codeBuf |= b << codeSize;
+ codeSize += 8;
+ }
+ b = codeBuf & (1 << bits) - 1;
+ this.codeBuf = codeBuf >> bits;
+ this.codeSize = codeSize -= bits;
+ return b;
+ }
+ getCode(table) {
+ const str = this.str;
+ const codes = table[0];
+ const maxLen = table[1];
+ let codeSize = this.codeSize;
+ let codeBuf = this.codeBuf;
+ let b;
+ while (codeSize < maxLen) {
+ if ((b = str.getByte()) === -1) {
+ break;
+ }
+ codeBuf |= b << codeSize;
+ codeSize += 8;
+ }
+ const code = codes[codeBuf & (1 << maxLen) - 1];
+ const codeLen = code >> 16;
+ const codeVal = code & 0xffff;
+ if (codeLen < 1 || codeSize < codeLen) {
+ throw new FormatError("Bad encoding in flate stream");
+ }
+ this.codeBuf = codeBuf >> codeLen;
+ this.codeSize = codeSize - codeLen;
+ return codeVal;
+ }
+ generateHuffmanTable(lengths) {
+ const n = lengths.length;
+ let maxLen = 0;
+ let i;
+ for (i = 0; i < n; ++i) {
+ if (lengths[i] > maxLen) {
+ maxLen = lengths[i];
+ }
+ }
+ const size = 1 << maxLen;
+ const codes = new Int32Array(size);
+ for (let len = 1, code = 0, skip = 2; len <= maxLen; ++len, code <<= 1, skip <<= 1) {
+ for (let val = 0; val < n; ++val) {
+ if (lengths[val] === len) {
+ let code2 = 0;
+ let t = code;
+ for (i = 0; i < len; ++i) {
+ code2 = code2 << 1 | t & 1;
+ t >>= 1;
+ }
+ for (i = code2; i < size; i += skip) {
+ codes[i] = len << 16 | val;
+ }
+ ++code;
+ }
+ }
+ }
+ return [codes, maxLen];
+ }
+ #endsStreamOnError(err) {
+ info(err);
+ this.eof = true;
+ }
+ readBlock() {
+ let buffer, len;
+ const str = this.str;
+ let hdr = this.getBits(3);
+ if (hdr & 1) {
+ this.eof = true;
+ }
+ hdr >>= 1;
+ if (hdr === 0) {
+ let b;
+ if ((b = str.getByte()) === -1) {
+ this.#endsStreamOnError("Bad block header in flate stream");
+ return;
+ }
+ let blockLen = b;
+ if ((b = str.getByte()) === -1) {
+ this.#endsStreamOnError("Bad block header in flate stream");
+ return;
+ }
+ blockLen |= b << 8;
+ if ((b = str.getByte()) === -1) {
+ this.#endsStreamOnError("Bad block header in flate stream");
+ return;
+ }
+ let check = b;
+ if ((b = str.getByte()) === -1) {
+ this.#endsStreamOnError("Bad block header in flate stream");
+ return;
+ }
+ check |= b << 8;
+ if (check !== (~blockLen & 0xffff) && (blockLen !== 0 || check !== 0)) {
+ throw new FormatError("Bad uncompressed block length in flate stream");
+ }
+ this.codeBuf = 0;
+ this.codeSize = 0;
+ const bufferLength = this.bufferLength,
+ end = bufferLength + blockLen;
+ buffer = this.ensureBuffer(end);
+ this.bufferLength = end;
+ if (blockLen === 0) {
+ if (str.peekByte() === -1) {
+ this.eof = true;
+ }
+ } else {
+ const block = str.getBytes(blockLen);
+ buffer.set(block, bufferLength);
+ if (block.length < blockLen) {
+ this.eof = true;
+ }
+ }
+ return;
+ }
+ let litCodeTable;
+ let distCodeTable;
+ if (hdr === 1) {
+ litCodeTable = fixedLitCodeTab;
+ distCodeTable = fixedDistCodeTab;
+ } else if (hdr === 2) {
+ const numLitCodes = this.getBits(5) + 257;
+ const numDistCodes = this.getBits(5) + 1;
+ const numCodeLenCodes = this.getBits(4) + 4;
+ const codeLenCodeLengths = new Uint8Array(codeLenCodeMap.length);
+ let i;
+ for (i = 0; i < numCodeLenCodes; ++i) {
+ codeLenCodeLengths[codeLenCodeMap[i]] = this.getBits(3);
+ }
+ const codeLenCodeTab = this.generateHuffmanTable(codeLenCodeLengths);
+ len = 0;
+ i = 0;
+ const codes = numLitCodes + numDistCodes;
+ const codeLengths = new Uint8Array(codes);
+ let bitsLength, bitsOffset, what;
+ while (i < codes) {
+ const code = this.getCode(codeLenCodeTab);
+ if (code === 16) {
+ bitsLength = 2;
+ bitsOffset = 3;
+ what = len;
+ } else if (code === 17) {
+ bitsLength = 3;
+ bitsOffset = 3;
+ what = len = 0;
+ } else if (code === 18) {
+ bitsLength = 7;
+ bitsOffset = 11;
+ what = len = 0;
+ } else {
+ codeLengths[i++] = len = code;
+ continue;
+ }
+ let repeatLength = this.getBits(bitsLength) + bitsOffset;
+ while (repeatLength-- > 0) {
+ codeLengths[i++] = what;
+ }
+ }
+ litCodeTable = this.generateHuffmanTable(codeLengths.subarray(0, numLitCodes));
+ distCodeTable = this.generateHuffmanTable(codeLengths.subarray(numLitCodes, codes));
+ } else {
+ throw new FormatError("Unknown block type in flate stream");
+ }
+ buffer = this.buffer;
+ let limit = buffer ? buffer.length : 0;
+ let pos = this.bufferLength;
+ while (true) {
+ let code1 = this.getCode(litCodeTable);
+ if (code1 < 256) {
+ if (pos + 1 >= limit) {
+ buffer = this.ensureBuffer(pos + 1);
+ limit = buffer.length;
+ }
+ buffer[pos++] = code1;
+ continue;
+ }
+ if (code1 === 256) {
+ this.bufferLength = pos;
+ return;
+ }
+ code1 -= 257;
+ code1 = lengthDecode[code1];
+ let code2 = code1 >> 16;
+ if (code2 > 0) {
+ code2 = this.getBits(code2);
+ }
+ len = (code1 & 0xffff) + code2;
+ code1 = this.getCode(distCodeTable);
+ code1 = distDecode[code1];
+ code2 = code1 >> 16;
+ if (code2 > 0) {
+ code2 = this.getBits(code2);
+ }
+ const dist = (code1 & 0xffff) + code2;
+ if (pos + len >= limit) {
+ buffer = this.ensureBuffer(pos + len);
+ limit = buffer.length;
+ }
+ for (let k = 0; k < len; ++k, ++pos) {
+ buffer[pos] = buffer[pos - dist];
+ }
+ }
+ }
+}
+
+;// CONCATENATED MODULE: ./src/core/arithmetic_decoder.js
+const QeTable = [{
+ qe: 0x5601,
+ nmps: 1,
+ nlps: 1,
+ switchFlag: 1
+}, {
+ qe: 0x3401,
+ nmps: 2,
+ nlps: 6,
+ switchFlag: 0
+}, {
+ qe: 0x1801,
+ nmps: 3,
+ nlps: 9,
+ switchFlag: 0
+}, {
+ qe: 0x0ac1,
+ nmps: 4,
+ nlps: 12,
+ switchFlag: 0
+}, {
+ qe: 0x0521,
+ nmps: 5,
+ nlps: 29,
+ switchFlag: 0
+}, {
+ qe: 0x0221,
+ nmps: 38,
+ nlps: 33,
+ switchFlag: 0
+}, {
+ qe: 0x5601,
+ nmps: 7,
+ nlps: 6,
+ switchFlag: 1
+}, {
+ qe: 0x5401,
+ nmps: 8,
+ nlps: 14,
+ switchFlag: 0
+}, {
+ qe: 0x4801,
+ nmps: 9,
+ nlps: 14,
+ switchFlag: 0
+}, {
+ qe: 0x3801,
+ nmps: 10,
+ nlps: 14,
+ switchFlag: 0
+}, {
+ qe: 0x3001,
+ nmps: 11,
+ nlps: 17,
+ switchFlag: 0
+}, {
+ qe: 0x2401,
+ nmps: 12,
+ nlps: 18,
+ switchFlag: 0
+}, {
+ qe: 0x1c01,
+ nmps: 13,
+ nlps: 20,
+ switchFlag: 0
+}, {
+ qe: 0x1601,
+ nmps: 29,
+ nlps: 21,
+ switchFlag: 0
+}, {
+ qe: 0x5601,
+ nmps: 15,
+ nlps: 14,
+ switchFlag: 1
+}, {
+ qe: 0x5401,
+ nmps: 16,
+ nlps: 14,
+ switchFlag: 0
+}, {
+ qe: 0x5101,
+ nmps: 17,
+ nlps: 15,
+ switchFlag: 0
+}, {
+ qe: 0x4801,
+ nmps: 18,
+ nlps: 16,
+ switchFlag: 0
+}, {
+ qe: 0x3801,
+ nmps: 19,
+ nlps: 17,
+ switchFlag: 0
+}, {
+ qe: 0x3401,
+ nmps: 20,
+ nlps: 18,
+ switchFlag: 0
+}, {
+ qe: 0x3001,
+ nmps: 21,
+ nlps: 19,
+ switchFlag: 0
+}, {
+ qe: 0x2801,
+ nmps: 22,
+ nlps: 19,
+ switchFlag: 0
+}, {
+ qe: 0x2401,
+ nmps: 23,
+ nlps: 20,
+ switchFlag: 0
+}, {
+ qe: 0x2201,
+ nmps: 24,
+ nlps: 21,
+ switchFlag: 0
+}, {
+ qe: 0x1c01,
+ nmps: 25,
+ nlps: 22,
+ switchFlag: 0
+}, {
+ qe: 0x1801,
+ nmps: 26,
+ nlps: 23,
+ switchFlag: 0
+}, {
+ qe: 0x1601,
+ nmps: 27,
+ nlps: 24,
+ switchFlag: 0
+}, {
+ qe: 0x1401,
+ nmps: 28,
+ nlps: 25,
+ switchFlag: 0
+}, {
+ qe: 0x1201,
+ nmps: 29,
+ nlps: 26,
+ switchFlag: 0
+}, {
+ qe: 0x1101,
+ nmps: 30,
+ nlps: 27,
+ switchFlag: 0
+}, {
+ qe: 0x0ac1,
+ nmps: 31,
+ nlps: 28,
+ switchFlag: 0
+}, {
+ qe: 0x09c1,
+ nmps: 32,
+ nlps: 29,
+ switchFlag: 0
+}, {
+ qe: 0x08a1,
+ nmps: 33,
+ nlps: 30,
+ switchFlag: 0
+}, {
+ qe: 0x0521,
+ nmps: 34,
+ nlps: 31,
+ switchFlag: 0
+}, {
+ qe: 0x0441,
+ nmps: 35,
+ nlps: 32,
+ switchFlag: 0
+}, {
+ qe: 0x02a1,
+ nmps: 36,
+ nlps: 33,
+ switchFlag: 0
+}, {
+ qe: 0x0221,
+ nmps: 37,
+ nlps: 34,
+ switchFlag: 0
+}, {
+ qe: 0x0141,
+ nmps: 38,
+ nlps: 35,
+ switchFlag: 0
+}, {
+ qe: 0x0111,
+ nmps: 39,
+ nlps: 36,
+ switchFlag: 0
+}, {
+ qe: 0x0085,
+ nmps: 40,
+ nlps: 37,
+ switchFlag: 0
+}, {
+ qe: 0x0049,
+ nmps: 41,
+ nlps: 38,
+ switchFlag: 0
+}, {
+ qe: 0x0025,
+ nmps: 42,
+ nlps: 39,
+ switchFlag: 0
+}, {
+ qe: 0x0015,
+ nmps: 43,
+ nlps: 40,
+ switchFlag: 0
+}, {
+ qe: 0x0009,
+ nmps: 44,
+ nlps: 41,
+ switchFlag: 0
+}, {
+ qe: 0x0005,
+ nmps: 45,
+ nlps: 42,
+ switchFlag: 0
+}, {
+ qe: 0x0001,
+ nmps: 45,
+ nlps: 43,
+ switchFlag: 0
+}, {
+ qe: 0x5601,
+ nmps: 46,
+ nlps: 46,
+ switchFlag: 0
+}];
+class ArithmeticDecoder {
+ constructor(data, start, end) {
+ this.data = data;
+ this.bp = start;
+ this.dataEnd = end;
+ this.chigh = data[start];
+ this.clow = 0;
+ this.byteIn();
+ this.chigh = this.chigh << 7 & 0xffff | this.clow >> 9 & 0x7f;
+ this.clow = this.clow << 7 & 0xffff;
+ this.ct -= 7;
+ this.a = 0x8000;
+ }
+ byteIn() {
+ const data = this.data;
+ let bp = this.bp;
+ if (data[bp] === 0xff) {
+ if (data[bp + 1] > 0x8f) {
+ this.clow += 0xff00;
+ this.ct = 8;
+ } else {
+ bp++;
+ this.clow += data[bp] << 9;
+ this.ct = 7;
+ this.bp = bp;
+ }
+ } else {
+ bp++;
+ this.clow += bp < this.dataEnd ? data[bp] << 8 : 0xff00;
+ this.ct = 8;
+ this.bp = bp;
+ }
+ if (this.clow > 0xffff) {
+ this.chigh += this.clow >> 16;
+ this.clow &= 0xffff;
+ }
+ }
+ readBit(contexts, pos) {
+ let cx_index = contexts[pos] >> 1,
+ cx_mps = contexts[pos] & 1;
+ const qeTableIcx = QeTable[cx_index];
+ const qeIcx = qeTableIcx.qe;
+ let d;
+ let a = this.a - qeIcx;
+ if (this.chigh < qeIcx) {
+ if (a < qeIcx) {
+ a = qeIcx;
+ d = cx_mps;
+ cx_index = qeTableIcx.nmps;
+ } else {
+ a = qeIcx;
+ d = 1 ^ cx_mps;
+ if (qeTableIcx.switchFlag === 1) {
+ cx_mps = d;
+ }
+ cx_index = qeTableIcx.nlps;
+ }
+ } else {
+ this.chigh -= qeIcx;
+ if ((a & 0x8000) !== 0) {
+ this.a = a;
+ return cx_mps;
+ }
+ if (a < qeIcx) {
+ d = 1 ^ cx_mps;
+ if (qeTableIcx.switchFlag === 1) {
+ cx_mps = d;
+ }
+ cx_index = qeTableIcx.nlps;
+ } else {
+ d = cx_mps;
+ cx_index = qeTableIcx.nmps;
+ }
+ }
+ do {
+ if (this.ct === 0) {
+ this.byteIn();
+ }
+ a <<= 1;
+ this.chigh = this.chigh << 1 & 0xffff | this.clow >> 15 & 1;
+ this.clow = this.clow << 1 & 0xffff;
+ this.ct--;
+ } while ((a & 0x8000) === 0);
+ this.a = a;
+ contexts[pos] = cx_index << 1 | cx_mps;
+ return d;
+ }
+}
+
+;// CONCATENATED MODULE: ./src/core/jbig2.js
+
+
+
+
+class Jbig2Error extends BaseException {
+ constructor(msg) {
+ super(`JBIG2 error: ${msg}`, "Jbig2Error");
+ }
+}
+class ContextCache {
+ getContexts(id) {
+ if (id in this) {
+ return this[id];
+ }
+ return this[id] = new Int8Array(1 << 16);
+ }
+}
+class DecodingContext {
+ constructor(data, start, end) {
+ this.data = data;
+ this.start = start;
+ this.end = end;
+ }
+ get decoder() {
+ const decoder = new ArithmeticDecoder(this.data, this.start, this.end);
+ return shadow(this, "decoder", decoder);
+ }
+ get contextCache() {
+ const cache = new ContextCache();
+ return shadow(this, "contextCache", cache);
+ }
+}
+const MAX_INT_32 = 2 ** 31 - 1;
+const MIN_INT_32 = -(2 ** 31);
+function decodeInteger(contextCache, procedure, decoder) {
+ const contexts = contextCache.getContexts(procedure);
+ let prev = 1;
+ function readBits(length) {
+ let v = 0;
+ for (let i = 0; i < length; i++) {
+ const bit = decoder.readBit(contexts, prev);
+ prev = prev < 256 ? prev << 1 | bit : (prev << 1 | bit) & 511 | 256;
+ v = v << 1 | bit;
+ }
+ return v >>> 0;
+ }
+ const sign = readBits(1);
+ const value = readBits(1) ? readBits(1) ? readBits(1) ? readBits(1) ? readBits(1) ? readBits(32) + 4436 : readBits(12) + 340 : readBits(8) + 84 : readBits(6) + 20 : readBits(4) + 4 : readBits(2);
+ let signedValue;
+ if (sign === 0) {
+ signedValue = value;
+ } else if (value > 0) {
+ signedValue = -value;
+ }
+ if (signedValue >= MIN_INT_32 && signedValue <= MAX_INT_32) {
+ return signedValue;
+ }
+ return null;
+}
+function decodeIAID(contextCache, decoder, codeLength) {
+ const contexts = contextCache.getContexts("IAID");
+ let prev = 1;
+ for (let i = 0; i < codeLength; i++) {
+ const bit = decoder.readBit(contexts, prev);
+ prev = prev << 1 | bit;
+ }
+ if (codeLength < 31) {
+ return prev & (1 << codeLength) - 1;
+ }
+ return prev & 0x7fffffff;
+}
+const SegmentTypes = ["SymbolDictionary", null, null, null, "IntermediateTextRegion", null, "ImmediateTextRegion", "ImmediateLosslessTextRegion", null, null, null, null, null, null, null, null, "PatternDictionary", null, null, null, "IntermediateHalftoneRegion", null, "ImmediateHalftoneRegion", "ImmediateLosslessHalftoneRegion", null, null, null, null, null, null, null, null, null, null, null, null, "IntermediateGenericRegion", null, "ImmediateGenericRegion", "ImmediateLosslessGenericRegion", "IntermediateGenericRefinementRegion", null, "ImmediateGenericRefinementRegion", "ImmediateLosslessGenericRefinementRegion", null, null, null, null, "PageInformation", "EndOfPage", "EndOfStripe", "EndOfFile", "Profiles", "Tables", null, null, null, null, null, null, null, null, "Extension"];
+const CodingTemplates = [[{
+ x: -1,
+ y: -2
+}, {
+ x: 0,
+ y: -2
+}, {
+ x: 1,
+ y: -2
+}, {
+ x: -2,
+ y: -1
+}, {
+ x: -1,
+ y: -1
+}, {
+ x: 0,
+ y: -1
+}, {
+ x: 1,
+ y: -1
+}, {
+ x: 2,
+ y: -1
+}, {
+ x: -4,
+ y: 0
+}, {
+ x: -3,
+ y: 0
+}, {
+ x: -2,
+ y: 0
+}, {
+ x: -1,
+ y: 0
+}], [{
+ x: -1,
+ y: -2
+}, {
+ x: 0,
+ y: -2
+}, {
+ x: 1,
+ y: -2
+}, {
+ x: 2,
+ y: -2
+}, {
+ x: -2,
+ y: -1
+}, {
+ x: -1,
+ y: -1
+}, {
+ x: 0,
+ y: -1
+}, {
+ x: 1,
+ y: -1
+}, {
+ x: 2,
+ y: -1
+}, {
+ x: -3,
+ y: 0
+}, {
+ x: -2,
+ y: 0
+}, {
+ x: -1,
+ y: 0
+}], [{
+ x: -1,
+ y: -2
+}, {
+ x: 0,
+ y: -2
+}, {
+ x: 1,
+ y: -2
+}, {
+ x: -2,
+ y: -1
+}, {
+ x: -1,
+ y: -1
+}, {
+ x: 0,
+ y: -1
+}, {
+ x: 1,
+ y: -1
+}, {
+ x: -2,
+ y: 0
+}, {
+ x: -1,
+ y: 0
+}], [{
+ x: -3,
+ y: -1
+}, {
+ x: -2,
+ y: -1
+}, {
+ x: -1,
+ y: -1
+}, {
+ x: 0,
+ y: -1
+}, {
+ x: 1,
+ y: -1
+}, {
+ x: -4,
+ y: 0
+}, {
+ x: -3,
+ y: 0
+}, {
+ x: -2,
+ y: 0
+}, {
+ x: -1,
+ y: 0
+}]];
+const RefinementTemplates = [{
+ coding: [{
+ x: 0,
+ y: -1
+ }, {
+ x: 1,
+ y: -1
+ }, {
+ x: -1,
+ y: 0
+ }],
+ reference: [{
+ x: 0,
+ y: -1
+ }, {
+ x: 1,
+ y: -1
+ }, {
+ x: -1,
+ y: 0
+ }, {
+ x: 0,
+ y: 0
+ }, {
+ x: 1,
+ y: 0
+ }, {
+ x: -1,
+ y: 1
+ }, {
+ x: 0,
+ y: 1
+ }, {
+ x: 1,
+ y: 1
+ }]
+}, {
+ coding: [{
+ x: -1,
+ y: -1
+ }, {
+ x: 0,
+ y: -1
+ }, {
+ x: 1,
+ y: -1
+ }, {
+ x: -1,
+ y: 0
+ }],
+ reference: [{
+ x: 0,
+ y: -1
+ }, {
+ x: -1,
+ y: 0
+ }, {
+ x: 0,
+ y: 0
+ }, {
+ x: 1,
+ y: 0
+ }, {
+ x: 0,
+ y: 1
+ }, {
+ x: 1,
+ y: 1
+ }]
+}];
+const ReusedContexts = [0x9b25, 0x0795, 0x00e5, 0x0195];
+const RefinementReusedContexts = [0x0020, 0x0008];
+function decodeBitmapTemplate0(width, height, decodingContext) {
+ const decoder = decodingContext.decoder;
+ const contexts = decodingContext.contextCache.getContexts("GB");
+ const bitmap = [];
+ let contextLabel, i, j, pixel, row, row1, row2;
+ const OLD_PIXEL_MASK = 0x7bf7;
+ for (i = 0; i < height; i++) {
+ row = bitmap[i] = new Uint8Array(width);
+ row1 = i < 1 ? row : bitmap[i - 1];
+ row2 = i < 2 ? row : bitmap[i - 2];
+ contextLabel = row2[0] << 13 | row2[1] << 12 | row2[2] << 11 | row1[0] << 7 | row1[1] << 6 | row1[2] << 5 | row1[3] << 4;
+ for (j = 0; j < width; j++) {
+ row[j] = pixel = decoder.readBit(contexts, contextLabel);
+ contextLabel = (contextLabel & OLD_PIXEL_MASK) << 1 | (j + 3 < width ? row2[j + 3] << 11 : 0) | (j + 4 < width ? row1[j + 4] << 4 : 0) | pixel;
+ }
+ }
+ return bitmap;
+}
+function decodeBitmap(mmr, width, height, templateIndex, prediction, skip, at, decodingContext) {
+ if (mmr) {
+ const input = new Reader(decodingContext.data, decodingContext.start, decodingContext.end);
+ return decodeMMRBitmap(input, width, height, false);
+ }
+ if (templateIndex === 0 && !skip && !prediction && at.length === 4 && at[0].x === 3 && at[0].y === -1 && at[1].x === -3 && at[1].y === -1 && at[2].x === 2 && at[2].y === -2 && at[3].x === -2 && at[3].y === -2) {
+ return decodeBitmapTemplate0(width, height, decodingContext);
+ }
+ const useskip = !!skip;
+ const template = CodingTemplates[templateIndex].concat(at);
+ template.sort(function (a, b) {
+ return a.y - b.y || a.x - b.x;
+ });
+ const templateLength = template.length;
+ const templateX = new Int8Array(templateLength);
+ const templateY = new Int8Array(templateLength);
+ const changingTemplateEntries = [];
+ let reuseMask = 0,
+ minX = 0,
+ maxX = 0,
+ minY = 0;
+ let c, k;
+ for (k = 0; k < templateLength; k++) {
+ templateX[k] = template[k].x;
+ templateY[k] = template[k].y;
+ minX = Math.min(minX, template[k].x);
+ maxX = Math.max(maxX, template[k].x);
+ minY = Math.min(minY, template[k].y);
+ if (k < templateLength - 1 && template[k].y === template[k + 1].y && template[k].x === template[k + 1].x - 1) {
+ reuseMask |= 1 << templateLength - 1 - k;
+ } else {
+ changingTemplateEntries.push(k);
+ }
+ }
+ const changingEntriesLength = changingTemplateEntries.length;
+ const changingTemplateX = new Int8Array(changingEntriesLength);
+ const changingTemplateY = new Int8Array(changingEntriesLength);
+ const changingTemplateBit = new Uint16Array(changingEntriesLength);
+ for (c = 0; c < changingEntriesLength; c++) {
+ k = changingTemplateEntries[c];
+ changingTemplateX[c] = template[k].x;
+ changingTemplateY[c] = template[k].y;
+ changingTemplateBit[c] = 1 << templateLength - 1 - k;
+ }
+ const sbb_left = -minX;
+ const sbb_top = -minY;
+ const sbb_right = width - maxX;
+ const pseudoPixelContext = ReusedContexts[templateIndex];
+ let row = new Uint8Array(width);
+ const bitmap = [];
+ const decoder = decodingContext.decoder;
+ const contexts = decodingContext.contextCache.getContexts("GB");
+ let ltp = 0,
+ j,
+ i0,
+ j0,
+ contextLabel = 0,
+ bit,
+ shift;
+ for (let i = 0; i < height; i++) {
+ if (prediction) {
+ const sltp = decoder.readBit(contexts, pseudoPixelContext);
+ ltp ^= sltp;
+ if (ltp) {
+ bitmap.push(row);
+ continue;
+ }
+ }
+ row = new Uint8Array(row);
+ bitmap.push(row);
+ for (j = 0; j < width; j++) {
+ if (useskip && skip[i][j]) {
+ row[j] = 0;
+ continue;
+ }
+ if (j >= sbb_left && j < sbb_right && i >= sbb_top) {
+ contextLabel = contextLabel << 1 & reuseMask;
+ for (k = 0; k < changingEntriesLength; k++) {
+ i0 = i + changingTemplateY[k];
+ j0 = j + changingTemplateX[k];
+ bit = bitmap[i0][j0];
+ if (bit) {
+ bit = changingTemplateBit[k];
+ contextLabel |= bit;
+ }
+ }
+ } else {
+ contextLabel = 0;
+ shift = templateLength - 1;
+ for (k = 0; k < templateLength; k++, shift--) {
+ j0 = j + templateX[k];
+ if (j0 >= 0 && j0 < width) {
+ i0 = i + templateY[k];
+ if (i0 >= 0) {
+ bit = bitmap[i0][j0];
+ if (bit) {
+ contextLabel |= bit << shift;
+ }
+ }
+ }
+ }
+ }
+ const pixel = decoder.readBit(contexts, contextLabel);
+ row[j] = pixel;
+ }
+ }
+ return bitmap;
+}
+function decodeRefinement(width, height, templateIndex, referenceBitmap, offsetX, offsetY, prediction, at, decodingContext) {
+ let codingTemplate = RefinementTemplates[templateIndex].coding;
+ if (templateIndex === 0) {
+ codingTemplate = codingTemplate.concat([at[0]]);
+ }
+ const codingTemplateLength = codingTemplate.length;
+ const codingTemplateX = new Int32Array(codingTemplateLength);
+ const codingTemplateY = new Int32Array(codingTemplateLength);
+ let k;
+ for (k = 0; k < codingTemplateLength; k++) {
+ codingTemplateX[k] = codingTemplate[k].x;
+ codingTemplateY[k] = codingTemplate[k].y;
+ }
+ let referenceTemplate = RefinementTemplates[templateIndex].reference;
+ if (templateIndex === 0) {
+ referenceTemplate = referenceTemplate.concat([at[1]]);
+ }
+ const referenceTemplateLength = referenceTemplate.length;
+ const referenceTemplateX = new Int32Array(referenceTemplateLength);
+ const referenceTemplateY = new Int32Array(referenceTemplateLength);
+ for (k = 0; k < referenceTemplateLength; k++) {
+ referenceTemplateX[k] = referenceTemplate[k].x;
+ referenceTemplateY[k] = referenceTemplate[k].y;
+ }
+ const referenceWidth = referenceBitmap[0].length;
+ const referenceHeight = referenceBitmap.length;
+ const pseudoPixelContext = RefinementReusedContexts[templateIndex];
+ const bitmap = [];
+ const decoder = decodingContext.decoder;
+ const contexts = decodingContext.contextCache.getContexts("GR");
+ let ltp = 0;
+ for (let i = 0; i < height; i++) {
+ if (prediction) {
+ const sltp = decoder.readBit(contexts, pseudoPixelContext);
+ ltp ^= sltp;
+ if (ltp) {
+ throw new Jbig2Error("prediction is not supported");
+ }
+ }
+ const row = new Uint8Array(width);
+ bitmap.push(row);
+ for (let j = 0; j < width; j++) {
+ let i0, j0;
+ let contextLabel = 0;
+ for (k = 0; k < codingTemplateLength; k++) {
+ i0 = i + codingTemplateY[k];
+ j0 = j + codingTemplateX[k];
+ if (i0 < 0 || j0 < 0 || j0 >= width) {
+ contextLabel <<= 1;
+ } else {
+ contextLabel = contextLabel << 1 | bitmap[i0][j0];
+ }
+ }
+ for (k = 0; k < referenceTemplateLength; k++) {
+ i0 = i + referenceTemplateY[k] - offsetY;
+ j0 = j + referenceTemplateX[k] - offsetX;
+ if (i0 < 0 || i0 >= referenceHeight || j0 < 0 || j0 >= referenceWidth) {
+ contextLabel <<= 1;
+ } else {
+ contextLabel = contextLabel << 1 | referenceBitmap[i0][j0];
+ }
+ }
+ const pixel = decoder.readBit(contexts, contextLabel);
+ row[j] = pixel;
+ }
+ }
+ return bitmap;
+}
+function decodeSymbolDictionary(huffman, refinement, symbols, numberOfNewSymbols, numberOfExportedSymbols, huffmanTables, templateIndex, at, refinementTemplateIndex, refinementAt, decodingContext, huffmanInput) {
+ if (huffman && refinement) {
+ throw new Jbig2Error("symbol refinement with Huffman is not supported");
+ }
+ const newSymbols = [];
+ let currentHeight = 0;
+ let symbolCodeLength = log2(symbols.length + numberOfNewSymbols);
+ const decoder = decodingContext.decoder;
+ const contextCache = decodingContext.contextCache;
+ let tableB1, symbolWidths;
+ if (huffman) {
+ tableB1 = getStandardTable(1);
+ symbolWidths = [];
+ symbolCodeLength = Math.max(symbolCodeLength, 1);
+ }
+ while (newSymbols.length < numberOfNewSymbols) {
+ const deltaHeight = huffman ? huffmanTables.tableDeltaHeight.decode(huffmanInput) : decodeInteger(contextCache, "IADH", decoder);
+ currentHeight += deltaHeight;
+ let currentWidth = 0,
+ totalWidth = 0;
+ const firstSymbol = huffman ? symbolWidths.length : 0;
+ while (true) {
+ const deltaWidth = huffman ? huffmanTables.tableDeltaWidth.decode(huffmanInput) : decodeInteger(contextCache, "IADW", decoder);
+ if (deltaWidth === null) {
+ break;
+ }
+ currentWidth += deltaWidth;
+ totalWidth += currentWidth;
+ let bitmap;
+ if (refinement) {
+ const numberOfInstances = decodeInteger(contextCache, "IAAI", decoder);
+ if (numberOfInstances > 1) {
+ bitmap = decodeTextRegion(huffman, refinement, currentWidth, currentHeight, 0, numberOfInstances, 1, symbols.concat(newSymbols), symbolCodeLength, 0, 0, 1, 0, huffmanTables, refinementTemplateIndex, refinementAt, decodingContext, 0, huffmanInput);
+ } else {
+ const symbolId = decodeIAID(contextCache, decoder, symbolCodeLength);
+ const rdx = decodeInteger(contextCache, "IARDX", decoder);
+ const rdy = decodeInteger(contextCache, "IARDY", decoder);
+ const symbol = symbolId < symbols.length ? symbols[symbolId] : newSymbols[symbolId - symbols.length];
+ bitmap = decodeRefinement(currentWidth, currentHeight, refinementTemplateIndex, symbol, rdx, rdy, false, refinementAt, decodingContext);
+ }
+ newSymbols.push(bitmap);
+ } else if (huffman) {
+ symbolWidths.push(currentWidth);
+ } else {
+ bitmap = decodeBitmap(false, currentWidth, currentHeight, templateIndex, false, null, at, decodingContext);
+ newSymbols.push(bitmap);
+ }
+ }
+ if (huffman && !refinement) {
+ const bitmapSize = huffmanTables.tableBitmapSize.decode(huffmanInput);
+ huffmanInput.byteAlign();
+ let collectiveBitmap;
+ if (bitmapSize === 0) {
+ collectiveBitmap = readUncompressedBitmap(huffmanInput, totalWidth, currentHeight);
+ } else {
+ const originalEnd = huffmanInput.end;
+ const bitmapEnd = huffmanInput.position + bitmapSize;
+ huffmanInput.end = bitmapEnd;
+ collectiveBitmap = decodeMMRBitmap(huffmanInput, totalWidth, currentHeight, false);
+ huffmanInput.end = originalEnd;
+ huffmanInput.position = bitmapEnd;
+ }
+ const numberOfSymbolsDecoded = symbolWidths.length;
+ if (firstSymbol === numberOfSymbolsDecoded - 1) {
+ newSymbols.push(collectiveBitmap);
+ } else {
+ let i,
+ y,
+ xMin = 0,
+ xMax,
+ bitmapWidth,
+ symbolBitmap;
+ for (i = firstSymbol; i < numberOfSymbolsDecoded; i++) {
+ bitmapWidth = symbolWidths[i];
+ xMax = xMin + bitmapWidth;
+ symbolBitmap = [];
+ for (y = 0; y < currentHeight; y++) {
+ symbolBitmap.push(collectiveBitmap[y].subarray(xMin, xMax));
+ }
+ newSymbols.push(symbolBitmap);
+ xMin = xMax;
+ }
+ }
+ }
+ }
+ const exportedSymbols = [],
+ flags = [];
+ let currentFlag = false,
+ i,
+ ii;
+ const totalSymbolsLength = symbols.length + numberOfNewSymbols;
+ while (flags.length < totalSymbolsLength) {
+ let runLength = huffman ? tableB1.decode(huffmanInput) : decodeInteger(contextCache, "IAEX", decoder);
+ while (runLength--) {
+ flags.push(currentFlag);
+ }
+ currentFlag = !currentFlag;
+ }
+ for (i = 0, ii = symbols.length; i < ii; i++) {
+ if (flags[i]) {
+ exportedSymbols.push(symbols[i]);
+ }
+ }
+ for (let j = 0; j < numberOfNewSymbols; i++, j++) {
+ if (flags[i]) {
+ exportedSymbols.push(newSymbols[j]);
+ }
+ }
+ return exportedSymbols;
+}
+function decodeTextRegion(huffman, refinement, width, height, defaultPixelValue, numberOfSymbolInstances, stripSize, inputSymbols, symbolCodeLength, transposed, dsOffset, referenceCorner, combinationOperator, huffmanTables, refinementTemplateIndex, refinementAt, decodingContext, logStripSize, huffmanInput) {
+ if (huffman && refinement) {
+ throw new Jbig2Error("refinement with Huffman is not supported");
+ }
+ const bitmap = [];
+ let i, row;
+ for (i = 0; i < height; i++) {
+ row = new Uint8Array(width);
+ if (defaultPixelValue) {
+ for (let j = 0; j < width; j++) {
+ row[j] = defaultPixelValue;
+ }
+ }
+ bitmap.push(row);
+ }
+ const decoder = decodingContext.decoder;
+ const contextCache = decodingContext.contextCache;
+ let stripT = huffman ? -huffmanTables.tableDeltaT.decode(huffmanInput) : -decodeInteger(contextCache, "IADT", decoder);
+ let firstS = 0;
+ i = 0;
+ while (i < numberOfSymbolInstances) {
+ const deltaT = huffman ? huffmanTables.tableDeltaT.decode(huffmanInput) : decodeInteger(contextCache, "IADT", decoder);
+ stripT += deltaT;
+ const deltaFirstS = huffman ? huffmanTables.tableFirstS.decode(huffmanInput) : decodeInteger(contextCache, "IAFS", decoder);
+ firstS += deltaFirstS;
+ let currentS = firstS;
+ do {
+ let currentT = 0;
+ if (stripSize > 1) {
+ currentT = huffman ? huffmanInput.readBits(logStripSize) : decodeInteger(contextCache, "IAIT", decoder);
+ }
+ const t = stripSize * stripT + currentT;
+ const symbolId = huffman ? huffmanTables.symbolIDTable.decode(huffmanInput) : decodeIAID(contextCache, decoder, symbolCodeLength);
+ const applyRefinement = refinement && (huffman ? huffmanInput.readBit() : decodeInteger(contextCache, "IARI", decoder));
+ let symbolBitmap = inputSymbols[symbolId];
+ let symbolWidth = symbolBitmap[0].length;
+ let symbolHeight = symbolBitmap.length;
+ if (applyRefinement) {
+ const rdw = decodeInteger(contextCache, "IARDW", decoder);
+ const rdh = decodeInteger(contextCache, "IARDH", decoder);
+ const rdx = decodeInteger(contextCache, "IARDX", decoder);
+ const rdy = decodeInteger(contextCache, "IARDY", decoder);
+ symbolWidth += rdw;
+ symbolHeight += rdh;
+ symbolBitmap = decodeRefinement(symbolWidth, symbolHeight, refinementTemplateIndex, symbolBitmap, (rdw >> 1) + rdx, (rdh >> 1) + rdy, false, refinementAt, decodingContext);
+ }
+ const offsetT = t - (referenceCorner & 1 ? 0 : symbolHeight - 1);
+ const offsetS = currentS - (referenceCorner & 2 ? symbolWidth - 1 : 0);
+ let s2, t2, symbolRow;
+ if (transposed) {
+ for (s2 = 0; s2 < symbolHeight; s2++) {
+ row = bitmap[offsetS + s2];
+ if (!row) {
+ continue;
+ }
+ symbolRow = symbolBitmap[s2];
+ const maxWidth = Math.min(width - offsetT, symbolWidth);
+ switch (combinationOperator) {
+ case 0:
+ for (t2 = 0; t2 < maxWidth; t2++) {
+ row[offsetT + t2] |= symbolRow[t2];
+ }
+ break;
+ case 2:
+ for (t2 = 0; t2 < maxWidth; t2++) {
+ row[offsetT + t2] ^= symbolRow[t2];
+ }
+ break;
+ default:
+ throw new Jbig2Error(`operator ${combinationOperator} is not supported`);
+ }
+ }
+ currentS += symbolHeight - 1;
+ } else {
+ for (t2 = 0; t2 < symbolHeight; t2++) {
+ row = bitmap[offsetT + t2];
+ if (!row) {
+ continue;
+ }
+ symbolRow = symbolBitmap[t2];
+ switch (combinationOperator) {
+ case 0:
+ for (s2 = 0; s2 < symbolWidth; s2++) {
+ row[offsetS + s2] |= symbolRow[s2];
+ }
+ break;
+ case 2:
+ for (s2 = 0; s2 < symbolWidth; s2++) {
+ row[offsetS + s2] ^= symbolRow[s2];
+ }
+ break;
+ default:
+ throw new Jbig2Error(`operator ${combinationOperator} is not supported`);
+ }
+ }
+ currentS += symbolWidth - 1;
+ }
+ i++;
+ const deltaS = huffman ? huffmanTables.tableDeltaS.decode(huffmanInput) : decodeInteger(contextCache, "IADS", decoder);
+ if (deltaS === null) {
+ break;
+ }
+ currentS += deltaS + dsOffset;
+ } while (true);
+ }
+ return bitmap;
+}
+function decodePatternDictionary(mmr, patternWidth, patternHeight, maxPatternIndex, template, decodingContext) {
+ const at = [];
+ if (!mmr) {
+ at.push({
+ x: -patternWidth,
+ y: 0
+ });
+ if (template === 0) {
+ at.push({
+ x: -3,
+ y: -1
+ }, {
+ x: 2,
+ y: -2
+ }, {
+ x: -2,
+ y: -2
+ });
+ }
+ }
+ const collectiveWidth = (maxPatternIndex + 1) * patternWidth;
+ const collectiveBitmap = decodeBitmap(mmr, collectiveWidth, patternHeight, template, false, null, at, decodingContext);
+ const patterns = [];
+ for (let i = 0; i <= maxPatternIndex; i++) {
+ const patternBitmap = [];
+ const xMin = patternWidth * i;
+ const xMax = xMin + patternWidth;
+ for (let y = 0; y < patternHeight; y++) {
+ patternBitmap.push(collectiveBitmap[y].subarray(xMin, xMax));
+ }
+ patterns.push(patternBitmap);
+ }
+ return patterns;
+}
+function decodeHalftoneRegion(mmr, patterns, template, regionWidth, regionHeight, defaultPixelValue, enableSkip, combinationOperator, gridWidth, gridHeight, gridOffsetX, gridOffsetY, gridVectorX, gridVectorY, decodingContext) {
+ const skip = null;
+ if (enableSkip) {
+ throw new Jbig2Error("skip is not supported");
+ }
+ if (combinationOperator !== 0) {
+ throw new Jbig2Error(`operator "${combinationOperator}" is not supported in halftone region`);
+ }
+ const regionBitmap = [];
+ let i, j, row;
+ for (i = 0; i < regionHeight; i++) {
+ row = new Uint8Array(regionWidth);
+ if (defaultPixelValue) {
+ for (j = 0; j < regionWidth; j++) {
+ row[j] = defaultPixelValue;
+ }
+ }
+ regionBitmap.push(row);
+ }
+ const numberOfPatterns = patterns.length;
+ const pattern0 = patterns[0];
+ const patternWidth = pattern0[0].length,
+ patternHeight = pattern0.length;
+ const bitsPerValue = log2(numberOfPatterns);
+ const at = [];
+ if (!mmr) {
+ at.push({
+ x: template <= 1 ? 3 : 2,
+ y: -1
+ });
+ if (template === 0) {
+ at.push({
+ x: -3,
+ y: -1
+ }, {
+ x: 2,
+ y: -2
+ }, {
+ x: -2,
+ y: -2
+ });
+ }
+ }
+ const grayScaleBitPlanes = [];
+ let mmrInput, bitmap;
+ if (mmr) {
+ mmrInput = new Reader(decodingContext.data, decodingContext.start, decodingContext.end);
+ }
+ for (i = bitsPerValue - 1; i >= 0; i--) {
+ if (mmr) {
+ bitmap = decodeMMRBitmap(mmrInput, gridWidth, gridHeight, true);
+ } else {
+ bitmap = decodeBitmap(false, gridWidth, gridHeight, template, false, skip, at, decodingContext);
+ }
+ grayScaleBitPlanes[i] = bitmap;
+ }
+ let mg, ng, bit, patternIndex, patternBitmap, x, y, patternRow, regionRow;
+ for (mg = 0; mg < gridHeight; mg++) {
+ for (ng = 0; ng < gridWidth; ng++) {
+ bit = 0;
+ patternIndex = 0;
+ for (j = bitsPerValue - 1; j >= 0; j--) {
+ bit ^= grayScaleBitPlanes[j][mg][ng];
+ patternIndex |= bit << j;
+ }
+ patternBitmap = patterns[patternIndex];
+ x = gridOffsetX + mg * gridVectorY + ng * gridVectorX >> 8;
+ y = gridOffsetY + mg * gridVectorX - ng * gridVectorY >> 8;
+ if (x >= 0 && x + patternWidth <= regionWidth && y >= 0 && y + patternHeight <= regionHeight) {
+ for (i = 0; i < patternHeight; i++) {
+ regionRow = regionBitmap[y + i];
+ patternRow = patternBitmap[i];
+ for (j = 0; j < patternWidth; j++) {
+ regionRow[x + j] |= patternRow[j];
+ }
+ }
+ } else {
+ let regionX, regionY;
+ for (i = 0; i < patternHeight; i++) {
+ regionY = y + i;
+ if (regionY < 0 || regionY >= regionHeight) {
+ continue;
+ }
+ regionRow = regionBitmap[regionY];
+ patternRow = patternBitmap[i];
+ for (j = 0; j < patternWidth; j++) {
+ regionX = x + j;
+ if (regionX >= 0 && regionX < regionWidth) {
+ regionRow[regionX] |= patternRow[j];
+ }
+ }
+ }
+ }
+ }
+ }
+ return regionBitmap;
+}
+function readSegmentHeader(data, start) {
+ const segmentHeader = {};
+ segmentHeader.number = readUint32(data, start);
+ const flags = data[start + 4];
+ const segmentType = flags & 0x3f;
+ if (!SegmentTypes[segmentType]) {
+ throw new Jbig2Error("invalid segment type: " + segmentType);
+ }
+ segmentHeader.type = segmentType;
+ segmentHeader.typeName = SegmentTypes[segmentType];
+ segmentHeader.deferredNonRetain = !!(flags & 0x80);
+ const pageAssociationFieldSize = !!(flags & 0x40);
+ const referredFlags = data[start + 5];
+ let referredToCount = referredFlags >> 5 & 7;
+ const retainBits = [referredFlags & 31];
+ let position = start + 6;
+ if (referredFlags === 7) {
+ referredToCount = readUint32(data, position - 1) & 0x1fffffff;
+ position += 3;
+ let bytes = referredToCount + 7 >> 3;
+ retainBits[0] = data[position++];
+ while (--bytes > 0) {
+ retainBits.push(data[position++]);
+ }
+ } else if (referredFlags === 5 || referredFlags === 6) {
+ throw new Jbig2Error("invalid referred-to flags");
+ }
+ segmentHeader.retainBits = retainBits;
+ let referredToSegmentNumberSize = 4;
+ if (segmentHeader.number <= 256) {
+ referredToSegmentNumberSize = 1;
+ } else if (segmentHeader.number <= 65536) {
+ referredToSegmentNumberSize = 2;
+ }
+ const referredTo = [];
+ let i, ii;
+ for (i = 0; i < referredToCount; i++) {
+ let number;
+ if (referredToSegmentNumberSize === 1) {
+ number = data[position];
+ } else if (referredToSegmentNumberSize === 2) {
+ number = readUint16(data, position);
+ } else {
+ number = readUint32(data, position);
+ }
+ referredTo.push(number);
+ position += referredToSegmentNumberSize;
+ }
+ segmentHeader.referredTo = referredTo;
+ if (!pageAssociationFieldSize) {
+ segmentHeader.pageAssociation = data[position++];
+ } else {
+ segmentHeader.pageAssociation = readUint32(data, position);
+ position += 4;
+ }
+ segmentHeader.length = readUint32(data, position);
+ position += 4;
+ if (segmentHeader.length === 0xffffffff) {
+ if (segmentType === 38) {
+ const genericRegionInfo = readRegionSegmentInformation(data, position);
+ const genericRegionSegmentFlags = data[position + RegionSegmentInformationFieldLength];
+ const genericRegionMmr = !!(genericRegionSegmentFlags & 1);
+ const searchPatternLength = 6;
+ const searchPattern = new Uint8Array(searchPatternLength);
+ if (!genericRegionMmr) {
+ searchPattern[0] = 0xff;
+ searchPattern[1] = 0xac;
+ }
+ searchPattern[2] = genericRegionInfo.height >>> 24 & 0xff;
+ searchPattern[3] = genericRegionInfo.height >> 16 & 0xff;
+ searchPattern[4] = genericRegionInfo.height >> 8 & 0xff;
+ searchPattern[5] = genericRegionInfo.height & 0xff;
+ for (i = position, ii = data.length; i < ii; i++) {
+ let j = 0;
+ while (j < searchPatternLength && searchPattern[j] === data[i + j]) {
+ j++;
+ }
+ if (j === searchPatternLength) {
+ segmentHeader.length = i + searchPatternLength;
+ break;
+ }
+ }
+ if (segmentHeader.length === 0xffffffff) {
+ throw new Jbig2Error("segment end was not found");
+ }
+ } else {
+ throw new Jbig2Error("invalid unknown segment length");
+ }
+ }
+ segmentHeader.headerEnd = position;
+ return segmentHeader;
+}
+function readSegments(header, data, start, end) {
+ const segments = [];
+ let position = start;
+ while (position < end) {
+ const segmentHeader = readSegmentHeader(data, position);
+ position = segmentHeader.headerEnd;
+ const segment = {
+ header: segmentHeader,
+ data
+ };
+ if (!header.randomAccess) {
+ segment.start = position;
+ position += segmentHeader.length;
+ segment.end = position;
+ }
+ segments.push(segment);
+ if (segmentHeader.type === 51) {
+ break;
+ }
+ }
+ if (header.randomAccess) {
+ for (let i = 0, ii = segments.length; i < ii; i++) {
+ segments[i].start = position;
+ position += segments[i].header.length;
+ segments[i].end = position;
+ }
+ }
+ return segments;
+}
+function readRegionSegmentInformation(data, start) {
+ return {
+ width: readUint32(data, start),
+ height: readUint32(data, start + 4),
+ x: readUint32(data, start + 8),
+ y: readUint32(data, start + 12),
+ combinationOperator: data[start + 16] & 7
+ };
+}
+const RegionSegmentInformationFieldLength = 17;
+function processSegment(segment, visitor) {
+ const header = segment.header;
+ const data = segment.data,
+ end = segment.end;
+ let position = segment.start;
+ let args, at, i, atLength;
+ switch (header.type) {
+ case 0:
+ const dictionary = {};
+ const dictionaryFlags = readUint16(data, position);
+ dictionary.huffman = !!(dictionaryFlags & 1);
+ dictionary.refinement = !!(dictionaryFlags & 2);
+ dictionary.huffmanDHSelector = dictionaryFlags >> 2 & 3;
+ dictionary.huffmanDWSelector = dictionaryFlags >> 4 & 3;
+ dictionary.bitmapSizeSelector = dictionaryFlags >> 6 & 1;
+ dictionary.aggregationInstancesSelector = dictionaryFlags >> 7 & 1;
+ dictionary.bitmapCodingContextUsed = !!(dictionaryFlags & 256);
+ dictionary.bitmapCodingContextRetained = !!(dictionaryFlags & 512);
+ dictionary.template = dictionaryFlags >> 10 & 3;
+ dictionary.refinementTemplate = dictionaryFlags >> 12 & 1;
+ position += 2;
+ if (!dictionary.huffman) {
+ atLength = dictionary.template === 0 ? 4 : 1;
+ at = [];
+ for (i = 0; i < atLength; i++) {
+ at.push({
+ x: readInt8(data, position),
+ y: readInt8(data, position + 1)
+ });
+ position += 2;
+ }
+ dictionary.at = at;
+ }
+ if (dictionary.refinement && !dictionary.refinementTemplate) {
+ at = [];
+ for (i = 0; i < 2; i++) {
+ at.push({
+ x: readInt8(data, position),
+ y: readInt8(data, position + 1)
+ });
+ position += 2;
+ }
+ dictionary.refinementAt = at;
+ }
+ dictionary.numberOfExportedSymbols = readUint32(data, position);
+ position += 4;
+ dictionary.numberOfNewSymbols = readUint32(data, position);
+ position += 4;
+ args = [dictionary, header.number, header.referredTo, data, position, end];
+ break;
+ case 6:
+ case 7:
+ const textRegion = {};
+ textRegion.info = readRegionSegmentInformation(data, position);
+ position += RegionSegmentInformationFieldLength;
+ const textRegionSegmentFlags = readUint16(data, position);
+ position += 2;
+ textRegion.huffman = !!(textRegionSegmentFlags & 1);
+ textRegion.refinement = !!(textRegionSegmentFlags & 2);
+ textRegion.logStripSize = textRegionSegmentFlags >> 2 & 3;
+ textRegion.stripSize = 1 << textRegion.logStripSize;
+ textRegion.referenceCorner = textRegionSegmentFlags >> 4 & 3;
+ textRegion.transposed = !!(textRegionSegmentFlags & 64);
+ textRegion.combinationOperator = textRegionSegmentFlags >> 7 & 3;
+ textRegion.defaultPixelValue = textRegionSegmentFlags >> 9 & 1;
+ textRegion.dsOffset = textRegionSegmentFlags << 17 >> 27;
+ textRegion.refinementTemplate = textRegionSegmentFlags >> 15 & 1;
+ if (textRegion.huffman) {
+ const textRegionHuffmanFlags = readUint16(data, position);
+ position += 2;
+ textRegion.huffmanFS = textRegionHuffmanFlags & 3;
+ textRegion.huffmanDS = textRegionHuffmanFlags >> 2 & 3;
+ textRegion.huffmanDT = textRegionHuffmanFlags >> 4 & 3;
+ textRegion.huffmanRefinementDW = textRegionHuffmanFlags >> 6 & 3;
+ textRegion.huffmanRefinementDH = textRegionHuffmanFlags >> 8 & 3;
+ textRegion.huffmanRefinementDX = textRegionHuffmanFlags >> 10 & 3;
+ textRegion.huffmanRefinementDY = textRegionHuffmanFlags >> 12 & 3;
+ textRegion.huffmanRefinementSizeSelector = !!(textRegionHuffmanFlags & 0x4000);
+ }
+ if (textRegion.refinement && !textRegion.refinementTemplate) {
+ at = [];
+ for (i = 0; i < 2; i++) {
+ at.push({
+ x: readInt8(data, position),
+ y: readInt8(data, position + 1)
+ });
+ position += 2;
+ }
+ textRegion.refinementAt = at;
+ }
+ textRegion.numberOfSymbolInstances = readUint32(data, position);
+ position += 4;
+ args = [textRegion, header.referredTo, data, position, end];
+ break;
+ case 16:
+ const patternDictionary = {};
+ const patternDictionaryFlags = data[position++];
+ patternDictionary.mmr = !!(patternDictionaryFlags & 1);
+ patternDictionary.template = patternDictionaryFlags >> 1 & 3;
+ patternDictionary.patternWidth = data[position++];
+ patternDictionary.patternHeight = data[position++];
+ patternDictionary.maxPatternIndex = readUint32(data, position);
+ position += 4;
+ args = [patternDictionary, header.number, data, position, end];
+ break;
+ case 22:
+ case 23:
+ const halftoneRegion = {};
+ halftoneRegion.info = readRegionSegmentInformation(data, position);
+ position += RegionSegmentInformationFieldLength;
+ const halftoneRegionFlags = data[position++];
+ halftoneRegion.mmr = !!(halftoneRegionFlags & 1);
+ halftoneRegion.template = halftoneRegionFlags >> 1 & 3;
+ halftoneRegion.enableSkip = !!(halftoneRegionFlags & 8);
+ halftoneRegion.combinationOperator = halftoneRegionFlags >> 4 & 7;
+ halftoneRegion.defaultPixelValue = halftoneRegionFlags >> 7 & 1;
+ halftoneRegion.gridWidth = readUint32(data, position);
+ position += 4;
+ halftoneRegion.gridHeight = readUint32(data, position);
+ position += 4;
+ halftoneRegion.gridOffsetX = readUint32(data, position) & 0xffffffff;
+ position += 4;
+ halftoneRegion.gridOffsetY = readUint32(data, position) & 0xffffffff;
+ position += 4;
+ halftoneRegion.gridVectorX = readUint16(data, position);
+ position += 2;
+ halftoneRegion.gridVectorY = readUint16(data, position);
+ position += 2;
+ args = [halftoneRegion, header.referredTo, data, position, end];
+ break;
+ case 38:
+ case 39:
+ const genericRegion = {};
+ genericRegion.info = readRegionSegmentInformation(data, position);
+ position += RegionSegmentInformationFieldLength;
+ const genericRegionSegmentFlags = data[position++];
+ genericRegion.mmr = !!(genericRegionSegmentFlags & 1);
+ genericRegion.template = genericRegionSegmentFlags >> 1 & 3;
+ genericRegion.prediction = !!(genericRegionSegmentFlags & 8);
+ if (!genericRegion.mmr) {
+ atLength = genericRegion.template === 0 ? 4 : 1;
+ at = [];
+ for (i = 0; i < atLength; i++) {
+ at.push({
+ x: readInt8(data, position),
+ y: readInt8(data, position + 1)
+ });
+ position += 2;
+ }
+ genericRegion.at = at;
+ }
+ args = [genericRegion, data, position, end];
+ break;
+ case 48:
+ const pageInfo = {
+ width: readUint32(data, position),
+ height: readUint32(data, position + 4),
+ resolutionX: readUint32(data, position + 8),
+ resolutionY: readUint32(data, position + 12)
+ };
+ if (pageInfo.height === 0xffffffff) {
+ delete pageInfo.height;
+ }
+ const pageSegmentFlags = data[position + 16];
+ readUint16(data, position + 17);
+ pageInfo.lossless = !!(pageSegmentFlags & 1);
+ pageInfo.refinement = !!(pageSegmentFlags & 2);
+ pageInfo.defaultPixelValue = pageSegmentFlags >> 2 & 1;
+ pageInfo.combinationOperator = pageSegmentFlags >> 3 & 3;
+ pageInfo.requiresBuffer = !!(pageSegmentFlags & 32);
+ pageInfo.combinationOperatorOverride = !!(pageSegmentFlags & 64);
+ args = [pageInfo];
+ break;
+ case 49:
+ break;
+ case 50:
+ break;
+ case 51:
+ break;
+ case 53:
+ args = [header.number, data, position, end];
+ break;
+ case 62:
+ break;
+ default:
+ throw new Jbig2Error(`segment type ${header.typeName}(${header.type}) is not implemented`);
+ }
+ const callbackName = "on" + header.typeName;
+ if (callbackName in visitor) {
+ visitor[callbackName].apply(visitor, args);
+ }
+}
+function processSegments(segments, visitor) {
+ for (let i = 0, ii = segments.length; i < ii; i++) {
+ processSegment(segments[i], visitor);
+ }
+}
+function parseJbig2Chunks(chunks) {
+ const visitor = new SimpleSegmentVisitor();
+ for (let i = 0, ii = chunks.length; i < ii; i++) {
+ const chunk = chunks[i];
+ const segments = readSegments({}, chunk.data, chunk.start, chunk.end);
+ processSegments(segments, visitor);
+ }
+ return visitor.buffer;
+}
+function parseJbig2(data) {
+ throw new Error("Not implemented: parseJbig2");
+}
+class SimpleSegmentVisitor {
+ onPageInformation(info) {
+ this.currentPageInfo = info;
+ const rowSize = info.width + 7 >> 3;
+ const buffer = new Uint8ClampedArray(rowSize * info.height);
+ if (info.defaultPixelValue) {
+ buffer.fill(0xff);
+ }
+ this.buffer = buffer;
+ }
+ drawBitmap(regionInfo, bitmap) {
+ const pageInfo = this.currentPageInfo;
+ const width = regionInfo.width,
+ height = regionInfo.height;
+ const rowSize = pageInfo.width + 7 >> 3;
+ const combinationOperator = pageInfo.combinationOperatorOverride ? regionInfo.combinationOperator : pageInfo.combinationOperator;
+ const buffer = this.buffer;
+ const mask0 = 128 >> (regionInfo.x & 7);
+ let offset0 = regionInfo.y * rowSize + (regionInfo.x >> 3);
+ let i, j, mask, offset;
+ switch (combinationOperator) {
+ case 0:
+ for (i = 0; i < height; i++) {
+ mask = mask0;
+ offset = offset0;
+ for (j = 0; j < width; j++) {
+ if (bitmap[i][j]) {
+ buffer[offset] |= mask;
+ }
+ mask >>= 1;
+ if (!mask) {
+ mask = 128;
+ offset++;
+ }
+ }
+ offset0 += rowSize;
+ }
+ break;
+ case 2:
+ for (i = 0; i < height; i++) {
+ mask = mask0;
+ offset = offset0;
+ for (j = 0; j < width; j++) {
+ if (bitmap[i][j]) {
+ buffer[offset] ^= mask;
+ }
+ mask >>= 1;
+ if (!mask) {
+ mask = 128;
+ offset++;
+ }
+ }
+ offset0 += rowSize;
+ }
+ break;
+ default:
+ throw new Jbig2Error(`operator ${combinationOperator} is not supported`);
+ }
+ }
+ onImmediateGenericRegion(region, data, start, end) {
+ const regionInfo = region.info;
+ const decodingContext = new DecodingContext(data, start, end);
+ const bitmap = decodeBitmap(region.mmr, regionInfo.width, regionInfo.height, region.template, region.prediction, null, region.at, decodingContext);
+ this.drawBitmap(regionInfo, bitmap);
+ }
+ onImmediateLosslessGenericRegion() {
+ this.onImmediateGenericRegion(...arguments);
+ }
+ onSymbolDictionary(dictionary, currentSegment, referredSegments, data, start, end) {
+ let huffmanTables, huffmanInput;
+ if (dictionary.huffman) {
+ huffmanTables = getSymbolDictionaryHuffmanTables(dictionary, referredSegments, this.customTables);
+ huffmanInput = new Reader(data, start, end);
+ }
+ let symbols = this.symbols;
+ if (!symbols) {
+ this.symbols = symbols = {};
+ }
+ const inputSymbols = [];
+ for (const referredSegment of referredSegments) {
+ const referredSymbols = symbols[referredSegment];
+ if (referredSymbols) {
+ inputSymbols.push(...referredSymbols);
+ }
+ }
+ const decodingContext = new DecodingContext(data, start, end);
+ symbols[currentSegment] = decodeSymbolDictionary(dictionary.huffman, dictionary.refinement, inputSymbols, dictionary.numberOfNewSymbols, dictionary.numberOfExportedSymbols, huffmanTables, dictionary.template, dictionary.at, dictionary.refinementTemplate, dictionary.refinementAt, decodingContext, huffmanInput);
+ }
+ onImmediateTextRegion(region, referredSegments, data, start, end) {
+ const regionInfo = region.info;
+ let huffmanTables, huffmanInput;
+ const symbols = this.symbols;
+ const inputSymbols = [];
+ for (const referredSegment of referredSegments) {
+ const referredSymbols = symbols[referredSegment];
+ if (referredSymbols) {
+ inputSymbols.push(...referredSymbols);
+ }
+ }
+ const symbolCodeLength = log2(inputSymbols.length);
+ if (region.huffman) {
+ huffmanInput = new Reader(data, start, end);
+ huffmanTables = getTextRegionHuffmanTables(region, referredSegments, this.customTables, inputSymbols.length, huffmanInput);
+ }
+ const decodingContext = new DecodingContext(data, start, end);
+ const bitmap = decodeTextRegion(region.huffman, region.refinement, regionInfo.width, regionInfo.height, region.defaultPixelValue, region.numberOfSymbolInstances, region.stripSize, inputSymbols, symbolCodeLength, region.transposed, region.dsOffset, region.referenceCorner, region.combinationOperator, huffmanTables, region.refinementTemplate, region.refinementAt, decodingContext, region.logStripSize, huffmanInput);
+ this.drawBitmap(regionInfo, bitmap);
+ }
+ onImmediateLosslessTextRegion() {
+ this.onImmediateTextRegion(...arguments);
+ }
+ onPatternDictionary(dictionary, currentSegment, data, start, end) {
+ let patterns = this.patterns;
+ if (!patterns) {
+ this.patterns = patterns = {};
+ }
+ const decodingContext = new DecodingContext(data, start, end);
+ patterns[currentSegment] = decodePatternDictionary(dictionary.mmr, dictionary.patternWidth, dictionary.patternHeight, dictionary.maxPatternIndex, dictionary.template, decodingContext);
+ }
+ onImmediateHalftoneRegion(region, referredSegments, data, start, end) {
+ const patterns = this.patterns[referredSegments[0]];
+ const regionInfo = region.info;
+ const decodingContext = new DecodingContext(data, start, end);
+ const bitmap = decodeHalftoneRegion(region.mmr, patterns, region.template, regionInfo.width, regionInfo.height, region.defaultPixelValue, region.enableSkip, region.combinationOperator, region.gridWidth, region.gridHeight, region.gridOffsetX, region.gridOffsetY, region.gridVectorX, region.gridVectorY, decodingContext);
+ this.drawBitmap(regionInfo, bitmap);
+ }
+ onImmediateLosslessHalftoneRegion() {
+ this.onImmediateHalftoneRegion(...arguments);
+ }
+ onTables(currentSegment, data, start, end) {
+ let customTables = this.customTables;
+ if (!customTables) {
+ this.customTables = customTables = {};
+ }
+ customTables[currentSegment] = decodeTablesSegment(data, start, end);
+ }
+}
+class HuffmanLine {
+ constructor(lineData) {
+ if (lineData.length === 2) {
+ this.isOOB = true;
+ this.rangeLow = 0;
+ this.prefixLength = lineData[0];
+ this.rangeLength = 0;
+ this.prefixCode = lineData[1];
+ this.isLowerRange = false;
+ } else {
+ this.isOOB = false;
+ this.rangeLow = lineData[0];
+ this.prefixLength = lineData[1];
+ this.rangeLength = lineData[2];
+ this.prefixCode = lineData[3];
+ this.isLowerRange = lineData[4] === "lower";
+ }
+ }
+}
+class HuffmanTreeNode {
+ constructor(line) {
+ this.children = [];
+ if (line) {
+ this.isLeaf = true;
+ this.rangeLength = line.rangeLength;
+ this.rangeLow = line.rangeLow;
+ this.isLowerRange = line.isLowerRange;
+ this.isOOB = line.isOOB;
+ } else {
+ this.isLeaf = false;
+ }
+ }
+ buildTree(line, shift) {
+ const bit = line.prefixCode >> shift & 1;
+ if (shift <= 0) {
+ this.children[bit] = new HuffmanTreeNode(line);
+ } else {
+ let node = this.children[bit];
+ if (!node) {
+ this.children[bit] = node = new HuffmanTreeNode(null);
+ }
+ node.buildTree(line, shift - 1);
+ }
+ }
+ decodeNode(reader) {
+ if (this.isLeaf) {
+ if (this.isOOB) {
+ return null;
+ }
+ const htOffset = reader.readBits(this.rangeLength);
+ return this.rangeLow + (this.isLowerRange ? -htOffset : htOffset);
+ }
+ const node = this.children[reader.readBit()];
+ if (!node) {
+ throw new Jbig2Error("invalid Huffman data");
+ }
+ return node.decodeNode(reader);
+ }
+}
+class HuffmanTable {
+ constructor(lines, prefixCodesDone) {
+ if (!prefixCodesDone) {
+ this.assignPrefixCodes(lines);
+ }
+ this.rootNode = new HuffmanTreeNode(null);
+ for (let i = 0, ii = lines.length; i < ii; i++) {
+ const line = lines[i];
+ if (line.prefixLength > 0) {
+ this.rootNode.buildTree(line, line.prefixLength - 1);
+ }
+ }
+ }
+ decode(reader) {
+ return this.rootNode.decodeNode(reader);
+ }
+ assignPrefixCodes(lines) {
+ const linesLength = lines.length;
+ let prefixLengthMax = 0;
+ for (let i = 0; i < linesLength; i++) {
+ prefixLengthMax = Math.max(prefixLengthMax, lines[i].prefixLength);
+ }
+ const histogram = new Uint32Array(prefixLengthMax + 1);
+ for (let i = 0; i < linesLength; i++) {
+ histogram[lines[i].prefixLength]++;
+ }
+ let currentLength = 1,
+ firstCode = 0,
+ currentCode,
+ currentTemp,
+ line;
+ histogram[0] = 0;
+ while (currentLength <= prefixLengthMax) {
+ firstCode = firstCode + histogram[currentLength - 1] << 1;
+ currentCode = firstCode;
+ currentTemp = 0;
+ while (currentTemp < linesLength) {
+ line = lines[currentTemp];
+ if (line.prefixLength === currentLength) {
+ line.prefixCode = currentCode;
+ currentCode++;
+ }
+ currentTemp++;
+ }
+ currentLength++;
+ }
+ }
+}
+function decodeTablesSegment(data, start, end) {
+ const flags = data[start];
+ const lowestValue = readUint32(data, start + 1) & 0xffffffff;
+ const highestValue = readUint32(data, start + 5) & 0xffffffff;
+ const reader = new Reader(data, start + 9, end);
+ const prefixSizeBits = (flags >> 1 & 7) + 1;
+ const rangeSizeBits = (flags >> 4 & 7) + 1;
+ const lines = [];
+ let prefixLength,
+ rangeLength,
+ currentRangeLow = lowestValue;
+ do {
+ prefixLength = reader.readBits(prefixSizeBits);
+ rangeLength = reader.readBits(rangeSizeBits);
+ lines.push(new HuffmanLine([currentRangeLow, prefixLength, rangeLength, 0]));
+ currentRangeLow += 1 << rangeLength;
+ } while (currentRangeLow < highestValue);
+ prefixLength = reader.readBits(prefixSizeBits);
+ lines.push(new HuffmanLine([lowestValue - 1, prefixLength, 32, 0, "lower"]));
+ prefixLength = reader.readBits(prefixSizeBits);
+ lines.push(new HuffmanLine([highestValue, prefixLength, 32, 0]));
+ if (flags & 1) {
+ prefixLength = reader.readBits(prefixSizeBits);
+ lines.push(new HuffmanLine([prefixLength, 0]));
+ }
+ return new HuffmanTable(lines, false);
+}
+const standardTablesCache = {};
+function getStandardTable(number) {
+ let table = standardTablesCache[number];
+ if (table) {
+ return table;
+ }
+ let lines;
+ switch (number) {
+ case 1:
+ lines = [[0, 1, 4, 0x0], [16, 2, 8, 0x2], [272, 3, 16, 0x6], [65808, 3, 32, 0x7]];
+ break;
+ case 2:
+ lines = [[0, 1, 0, 0x0], [1, 2, 0, 0x2], [2, 3, 0, 0x6], [3, 4, 3, 0xe], [11, 5, 6, 0x1e], [75, 6, 32, 0x3e], [6, 0x3f]];
+ break;
+ case 3:
+ lines = [[-256, 8, 8, 0xfe], [0, 1, 0, 0x0], [1, 2, 0, 0x2], [2, 3, 0, 0x6], [3, 4, 3, 0xe], [11, 5, 6, 0x1e], [-257, 8, 32, 0xff, "lower"], [75, 7, 32, 0x7e], [6, 0x3e]];
+ break;
+ case 4:
+ lines = [[1, 1, 0, 0x0], [2, 2, 0, 0x2], [3, 3, 0, 0x6], [4, 4, 3, 0xe], [12, 5, 6, 0x1e], [76, 5, 32, 0x1f]];
+ break;
+ case 5:
+ lines = [[-255, 7, 8, 0x7e], [1, 1, 0, 0x0], [2, 2, 0, 0x2], [3, 3, 0, 0x6], [4, 4, 3, 0xe], [12, 5, 6, 0x1e], [-256, 7, 32, 0x7f, "lower"], [76, 6, 32, 0x3e]];
+ break;
+ case 6:
+ lines = [[-2048, 5, 10, 0x1c], [-1024, 4, 9, 0x8], [-512, 4, 8, 0x9], [-256, 4, 7, 0xa], [-128, 5, 6, 0x1d], [-64, 5, 5, 0x1e], [-32, 4, 5, 0xb], [0, 2, 7, 0x0], [128, 3, 7, 0x2], [256, 3, 8, 0x3], [512, 4, 9, 0xc], [1024, 4, 10, 0xd], [-2049, 6, 32, 0x3e, "lower"], [2048, 6, 32, 0x3f]];
+ break;
+ case 7:
+ lines = [[-1024, 4, 9, 0x8], [-512, 3, 8, 0x0], [-256, 4, 7, 0x9], [-128, 5, 6, 0x1a], [-64, 5, 5, 0x1b], [-32, 4, 5, 0xa], [0, 4, 5, 0xb], [32, 5, 5, 0x1c], [64, 5, 6, 0x1d], [128, 4, 7, 0xc], [256, 3, 8, 0x1], [512, 3, 9, 0x2], [1024, 3, 10, 0x3], [-1025, 5, 32, 0x1e, "lower"], [2048, 5, 32, 0x1f]];
+ break;
+ case 8:
+ lines = [[-15, 8, 3, 0xfc], [-7, 9, 1, 0x1fc], [-5, 8, 1, 0xfd], [-3, 9, 0, 0x1fd], [-2, 7, 0, 0x7c], [-1, 4, 0, 0xa], [0, 2, 1, 0x0], [2, 5, 0, 0x1a], [3, 6, 0, 0x3a], [4, 3, 4, 0x4], [20, 6, 1, 0x3b], [22, 4, 4, 0xb], [38, 4, 5, 0xc], [70, 5, 6, 0x1b], [134, 5, 7, 0x1c], [262, 6, 7, 0x3c], [390, 7, 8, 0x7d], [646, 6, 10, 0x3d], [-16, 9, 32, 0x1fe, "lower"], [1670, 9, 32, 0x1ff], [2, 0x1]];
+ break;
+ case 9:
+ lines = [[-31, 8, 4, 0xfc], [-15, 9, 2, 0x1fc], [-11, 8, 2, 0xfd], [-7, 9, 1, 0x1fd], [-5, 7, 1, 0x7c], [-3, 4, 1, 0xa], [-1, 3, 1, 0x2], [1, 3, 1, 0x3], [3, 5, 1, 0x1a], [5, 6, 1, 0x3a], [7, 3, 5, 0x4], [39, 6, 2, 0x3b], [43, 4, 5, 0xb], [75, 4, 6, 0xc], [139, 5, 7, 0x1b], [267, 5, 8, 0x1c], [523, 6, 8, 0x3c], [779, 7, 9, 0x7d], [1291, 6, 11, 0x3d], [-32, 9, 32, 0x1fe, "lower"], [3339, 9, 32, 0x1ff], [2, 0x0]];
+ break;
+ case 10:
+ lines = [[-21, 7, 4, 0x7a], [-5, 8, 0, 0xfc], [-4, 7, 0, 0x7b], [-3, 5, 0, 0x18], [-2, 2, 2, 0x0], [2, 5, 0, 0x19], [3, 6, 0, 0x36], [4, 7, 0, 0x7c], [5, 8, 0, 0xfd], [6, 2, 6, 0x1], [70, 5, 5, 0x1a], [102, 6, 5, 0x37], [134, 6, 6, 0x38], [198, 6, 7, 0x39], [326, 6, 8, 0x3a], [582, 6, 9, 0x3b], [1094, 6, 10, 0x3c], [2118, 7, 11, 0x7d], [-22, 8, 32, 0xfe, "lower"], [4166, 8, 32, 0xff], [2, 0x2]];
+ break;
+ case 11:
+ lines = [[1, 1, 0, 0x0], [2, 2, 1, 0x2], [4, 4, 0, 0xc], [5, 4, 1, 0xd], [7, 5, 1, 0x1c], [9, 5, 2, 0x1d], [13, 6, 2, 0x3c], [17, 7, 2, 0x7a], [21, 7, 3, 0x7b], [29, 7, 4, 0x7c], [45, 7, 5, 0x7d], [77, 7, 6, 0x7e], [141, 7, 32, 0x7f]];
+ break;
+ case 12:
+ lines = [[1, 1, 0, 0x0], [2, 2, 0, 0x2], [3, 3, 1, 0x6], [5, 5, 0, 0x1c], [6, 5, 1, 0x1d], [8, 6, 1, 0x3c], [10, 7, 0, 0x7a], [11, 7, 1, 0x7b], [13, 7, 2, 0x7c], [17, 7, 3, 0x7d], [25, 7, 4, 0x7e], [41, 8, 5, 0xfe], [73, 8, 32, 0xff]];
+ break;
+ case 13:
+ lines = [[1, 1, 0, 0x0], [2, 3, 0, 0x4], [3, 4, 0, 0xc], [4, 5, 0, 0x1c], [5, 4, 1, 0xd], [7, 3, 3, 0x5], [15, 6, 1, 0x3a], [17, 6, 2, 0x3b], [21, 6, 3, 0x3c], [29, 6, 4, 0x3d], [45, 6, 5, 0x3e], [77, 7, 6, 0x7e], [141, 7, 32, 0x7f]];
+ break;
+ case 14:
+ lines = [[-2, 3, 0, 0x4], [-1, 3, 0, 0x5], [0, 1, 0, 0x0], [1, 3, 0, 0x6], [2, 3, 0, 0x7]];
+ break;
+ case 15:
+ lines = [[-24, 7, 4, 0x7c], [-8, 6, 2, 0x3c], [-4, 5, 1, 0x1c], [-2, 4, 0, 0xc], [-1, 3, 0, 0x4], [0, 1, 0, 0x0], [1, 3, 0, 0x5], [2, 4, 0, 0xd], [3, 5, 1, 0x1d], [5, 6, 2, 0x3d], [9, 7, 4, 0x7d], [-25, 7, 32, 0x7e, "lower"], [25, 7, 32, 0x7f]];
+ break;
+ default:
+ throw new Jbig2Error(`standard table B.${number} does not exist`);
+ }
+ for (let i = 0, ii = lines.length; i < ii; i++) {
+ lines[i] = new HuffmanLine(lines[i]);
+ }
+ table = new HuffmanTable(lines, true);
+ standardTablesCache[number] = table;
+ return table;
+}
+class Reader {
+ constructor(data, start, end) {
+ this.data = data;
+ this.start = start;
+ this.end = end;
+ this.position = start;
+ this.shift = -1;
+ this.currentByte = 0;
+ }
+ readBit() {
+ if (this.shift < 0) {
+ if (this.position >= this.end) {
+ throw new Jbig2Error("end of data while reading bit");
+ }
+ this.currentByte = this.data[this.position++];
+ this.shift = 7;
+ }
+ const bit = this.currentByte >> this.shift & 1;
+ this.shift--;
+ return bit;
+ }
+ readBits(numBits) {
+ let result = 0,
+ i;
+ for (i = numBits - 1; i >= 0; i--) {
+ result |= this.readBit() << i;
+ }
+ return result;
+ }
+ byteAlign() {
+ this.shift = -1;
+ }
+ next() {
+ if (this.position >= this.end) {
+ return -1;
+ }
+ return this.data[this.position++];
+ }
+}
+function getCustomHuffmanTable(index, referredTo, customTables) {
+ let currentIndex = 0;
+ for (let i = 0, ii = referredTo.length; i < ii; i++) {
+ const table = customTables[referredTo[i]];
+ if (table) {
+ if (index === currentIndex) {
+ return table;
+ }
+ currentIndex++;
+ }
+ }
+ throw new Jbig2Error("can't find custom Huffman table");
+}
+function getTextRegionHuffmanTables(textRegion, referredTo, customTables, numberOfSymbols, reader) {
+ const codes = [];
+ for (let i = 0; i <= 34; i++) {
+ const codeLength = reader.readBits(4);
+ codes.push(new HuffmanLine([i, codeLength, 0, 0]));
+ }
+ const runCodesTable = new HuffmanTable(codes, false);
+ codes.length = 0;
+ for (let i = 0; i < numberOfSymbols;) {
+ const codeLength = runCodesTable.decode(reader);
+ if (codeLength >= 32) {
+ let repeatedLength, numberOfRepeats, j;
+ switch (codeLength) {
+ case 32:
+ if (i === 0) {
+ throw new Jbig2Error("no previous value in symbol ID table");
+ }
+ numberOfRepeats = reader.readBits(2) + 3;
+ repeatedLength = codes[i - 1].prefixLength;
+ break;
+ case 33:
+ numberOfRepeats = reader.readBits(3) + 3;
+ repeatedLength = 0;
+ break;
+ case 34:
+ numberOfRepeats = reader.readBits(7) + 11;
+ repeatedLength = 0;
+ break;
+ default:
+ throw new Jbig2Error("invalid code length in symbol ID table");
+ }
+ for (j = 0; j < numberOfRepeats; j++) {
+ codes.push(new HuffmanLine([i, repeatedLength, 0, 0]));
+ i++;
+ }
+ } else {
+ codes.push(new HuffmanLine([i, codeLength, 0, 0]));
+ i++;
+ }
+ }
+ reader.byteAlign();
+ const symbolIDTable = new HuffmanTable(codes, false);
+ let customIndex = 0,
+ tableFirstS,
+ tableDeltaS,
+ tableDeltaT;
+ switch (textRegion.huffmanFS) {
+ case 0:
+ case 1:
+ tableFirstS = getStandardTable(textRegion.huffmanFS + 6);
+ break;
+ case 3:
+ tableFirstS = getCustomHuffmanTable(customIndex, referredTo, customTables);
+ customIndex++;
+ break;
+ default:
+ throw new Jbig2Error("invalid Huffman FS selector");
+ }
+ switch (textRegion.huffmanDS) {
+ case 0:
+ case 1:
+ case 2:
+ tableDeltaS = getStandardTable(textRegion.huffmanDS + 8);
+ break;
+ case 3:
+ tableDeltaS = getCustomHuffmanTable(customIndex, referredTo, customTables);
+ customIndex++;
+ break;
+ default:
+ throw new Jbig2Error("invalid Huffman DS selector");
+ }
+ switch (textRegion.huffmanDT) {
+ case 0:
+ case 1:
+ case 2:
+ tableDeltaT = getStandardTable(textRegion.huffmanDT + 11);
+ break;
+ case 3:
+ tableDeltaT = getCustomHuffmanTable(customIndex, referredTo, customTables);
+ customIndex++;
+ break;
+ default:
+ throw new Jbig2Error("invalid Huffman DT selector");
+ }
+ if (textRegion.refinement) {
+ throw new Jbig2Error("refinement with Huffman is not supported");
+ }
+ return {
+ symbolIDTable,
+ tableFirstS,
+ tableDeltaS,
+ tableDeltaT
+ };
+}
+function getSymbolDictionaryHuffmanTables(dictionary, referredTo, customTables) {
+ let customIndex = 0,
+ tableDeltaHeight,
+ tableDeltaWidth;
+ switch (dictionary.huffmanDHSelector) {
+ case 0:
+ case 1:
+ tableDeltaHeight = getStandardTable(dictionary.huffmanDHSelector + 4);
+ break;
+ case 3:
+ tableDeltaHeight = getCustomHuffmanTable(customIndex, referredTo, customTables);
+ customIndex++;
+ break;
+ default:
+ throw new Jbig2Error("invalid Huffman DH selector");
+ }
+ switch (dictionary.huffmanDWSelector) {
+ case 0:
+ case 1:
+ tableDeltaWidth = getStandardTable(dictionary.huffmanDWSelector + 2);
+ break;
+ case 3:
+ tableDeltaWidth = getCustomHuffmanTable(customIndex, referredTo, customTables);
+ customIndex++;
+ break;
+ default:
+ throw new Jbig2Error("invalid Huffman DW selector");
+ }
+ let tableBitmapSize, tableAggregateInstances;
+ if (dictionary.bitmapSizeSelector) {
+ tableBitmapSize = getCustomHuffmanTable(customIndex, referredTo, customTables);
+ customIndex++;
+ } else {
+ tableBitmapSize = getStandardTable(1);
+ }
+ if (dictionary.aggregationInstancesSelector) {
+ tableAggregateInstances = getCustomHuffmanTable(customIndex, referredTo, customTables);
+ } else {
+ tableAggregateInstances = getStandardTable(1);
+ }
+ return {
+ tableDeltaHeight,
+ tableDeltaWidth,
+ tableBitmapSize,
+ tableAggregateInstances
+ };
+}
+function readUncompressedBitmap(reader, width, height) {
+ const bitmap = [];
+ for (let y = 0; y < height; y++) {
+ const row = new Uint8Array(width);
+ bitmap.push(row);
+ for (let x = 0; x < width; x++) {
+ row[x] = reader.readBit();
+ }
+ reader.byteAlign();
+ }
+ return bitmap;
+}
+function decodeMMRBitmap(input, width, height, endOfBlock) {
+ const params = {
+ K: -1,
+ Columns: width,
+ Rows: height,
+ BlackIs1: true,
+ EndOfBlock: endOfBlock
+ };
+ const decoder = new CCITTFaxDecoder(input, params);
+ const bitmap = [];
+ let currentByte,
+ eof = false;
+ for (let y = 0; y < height; y++) {
+ const row = new Uint8Array(width);
+ bitmap.push(row);
+ let shift = -1;
+ for (let x = 0; x < width; x++) {
+ if (shift < 0) {
+ currentByte = decoder.readNextChar();
+ if (currentByte === -1) {
+ currentByte = 0;
+ eof = true;
+ }
+ shift = 7;
+ }
+ row[x] = currentByte >> shift & 1;
+ shift--;
+ }
+ }
+ if (endOfBlock && !eof) {
+ const lookForEOFLimit = 5;
+ for (let i = 0; i < lookForEOFLimit; i++) {
+ if (decoder.readNextChar() === -1) {
+ break;
+ }
+ }
+ }
+ return bitmap;
+}
+class Jbig2Image {
+ parseChunks(chunks) {
+ return parseJbig2Chunks(chunks);
+ }
+ parse(data) {
+ throw new Error("Not implemented: Jbig2Image.parse");
+ }
+}
+
+;// CONCATENATED MODULE: ./src/core/jbig2_stream.js
+
+
+
+
+
+class Jbig2Stream extends DecodeStream {
+ constructor(stream, maybeLength, params) {
+ super(maybeLength);
+ this.stream = stream;
+ this.dict = stream.dict;
+ this.maybeLength = maybeLength;
+ this.params = params;
+ }
+ get bytes() {
+ return shadow(this, "bytes", this.stream.getBytes(this.maybeLength));
+ }
+ ensureBuffer(requested) {}
+ readBlock() {
+ if (this.eof) {
+ return;
+ }
+ const jbig2Image = new Jbig2Image();
+ const chunks = [];
+ if (this.params instanceof Dict) {
+ const globalsStream = this.params.get("JBIG2Globals");
+ if (globalsStream instanceof BaseStream) {
+ const globals = globalsStream.getBytes();
+ chunks.push({
+ data: globals,
+ start: 0,
+ end: globals.length
+ });
+ }
+ }
+ chunks.push({
+ data: this.bytes,
+ start: 0,
+ end: this.bytes.length
+ });
+ const data = jbig2Image.parseChunks(chunks);
+ const dataLength = data.length;
+ for (let i = 0; i < dataLength; i++) {
+ data[i] ^= 0xff;
+ }
+ this.buffer = data;
+ this.bufferLength = dataLength;
+ this.eof = true;
+ }
+}
+
+;// CONCATENATED MODULE: ./src/shared/image_utils.js
+
+function convertToRGBA(params) {
+ switch (params.kind) {
+ case ImageKind.GRAYSCALE_1BPP:
+ return convertBlackAndWhiteToRGBA(params);
+ case ImageKind.RGB_24BPP:
+ return convertRGBToRGBA(params);
+ }
+ return null;
+}
+function convertBlackAndWhiteToRGBA({
+ src,
+ srcPos = 0,
+ dest,
+ width,
+ height,
+ nonBlackColor = 0xffffffff,
+ inverseDecode = false
+}) {
+ const black = FeatureTest.isLittleEndian ? 0xff000000 : 0x000000ff;
+ const [zeroMapping, oneMapping] = inverseDecode ? [nonBlackColor, black] : [black, nonBlackColor];
+ const widthInSource = width >> 3;
+ const widthRemainder = width & 7;
+ const srcLength = src.length;
+ dest = new Uint32Array(dest.buffer);
+ let destPos = 0;
+ for (let i = 0; i < height; i++) {
+ for (const max = srcPos + widthInSource; srcPos < max; srcPos++) {
+ const elem = srcPos < srcLength ? src[srcPos] : 255;
+ dest[destPos++] = elem & 0b10000000 ? oneMapping : zeroMapping;
+ dest[destPos++] = elem & 0b1000000 ? oneMapping : zeroMapping;
+ dest[destPos++] = elem & 0b100000 ? oneMapping : zeroMapping;
+ dest[destPos++] = elem & 0b10000 ? oneMapping : zeroMapping;
+ dest[destPos++] = elem & 0b1000 ? oneMapping : zeroMapping;
+ dest[destPos++] = elem & 0b100 ? oneMapping : zeroMapping;
+ dest[destPos++] = elem & 0b10 ? oneMapping : zeroMapping;
+ dest[destPos++] = elem & 0b1 ? oneMapping : zeroMapping;
+ }
+ if (widthRemainder === 0) {
+ continue;
+ }
+ const elem = srcPos < srcLength ? src[srcPos++] : 255;
+ for (let j = 0; j < widthRemainder; j++) {
+ dest[destPos++] = elem & 1 << 7 - j ? oneMapping : zeroMapping;
+ }
+ }
+ return {
+ srcPos,
+ destPos
+ };
+}
+function convertRGBToRGBA({
+ src,
+ srcPos = 0,
+ dest,
+ destPos = 0,
+ width,
+ height
+}) {
+ let i = 0;
+ const len32 = src.length >> 2;
+ const src32 = new Uint32Array(src.buffer, srcPos, len32);
+ if (FeatureTest.isLittleEndian) {
+ for (; i < len32 - 2; i += 3, destPos += 4) {
+ const s1 = src32[i];
+ const s2 = src32[i + 1];
+ const s3 = src32[i + 2];
+ dest[destPos] = s1 | 0xff000000;
+ dest[destPos + 1] = s1 >>> 24 | s2 << 8 | 0xff000000;
+ dest[destPos + 2] = s2 >>> 16 | s3 << 16 | 0xff000000;
+ dest[destPos + 3] = s3 >>> 8 | 0xff000000;
+ }
+ for (let j = i * 4, jj = src.length; j < jj; j += 3) {
+ dest[destPos++] = src[j] | src[j + 1] << 8 | src[j + 2] << 16 | 0xff000000;
+ }
+ } else {
+ for (; i < len32 - 2; i += 3, destPos += 4) {
+ const s1 = src32[i];
+ const s2 = src32[i + 1];
+ const s3 = src32[i + 2];
+ dest[destPos] = s1 | 0xff;
+ dest[destPos + 1] = s1 << 24 | s2 >>> 8 | 0xff;
+ dest[destPos + 2] = s2 << 16 | s3 >>> 16 | 0xff;
+ dest[destPos + 3] = s3 << 8 | 0xff;
+ }
+ for (let j = i * 4, jj = src.length; j < jj; j += 3) {
+ dest[destPos++] = src[j] << 24 | src[j + 1] << 16 | src[j + 2] << 8 | 0xff;
+ }
+ }
+ return {
+ srcPos,
+ destPos
+ };
+}
+function grayToRGBA(src, dest) {
+ if (FeatureTest.isLittleEndian) {
+ for (let i = 0, ii = src.length; i < ii; i++) {
+ dest[i] = src[i] * 0x10101 | 0xff000000;
+ }
+ } else {
+ for (let i = 0, ii = src.length; i < ii; i++) {
+ dest[i] = src[i] * 0x1010100 | 0x000000ff;
+ }
+ }
+}
+
+;// CONCATENATED MODULE: ./src/core/jpg.js
+
+
+
+class JpegError extends BaseException {
+ constructor(msg) {
+ super(`JPEG error: ${msg}`, "JpegError");
+ }
+}
+class DNLMarkerError extends BaseException {
+ constructor(message, scanLines) {
+ super(message, "DNLMarkerError");
+ this.scanLines = scanLines;
+ }
+}
+class EOIMarkerError extends BaseException {
+ constructor(msg) {
+ super(msg, "EOIMarkerError");
+ }
+}
+const dctZigZag = new Uint8Array([0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, 12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, 35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51, 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63]);
+const dctCos1 = 4017;
+const dctSin1 = 799;
+const dctCos3 = 3406;
+const dctSin3 = 2276;
+const dctCos6 = 1567;
+const dctSin6 = 3784;
+const dctSqrt2 = 5793;
+const dctSqrt1d2 = 2896;
+function buildHuffmanTable(codeLengths, values) {
+ let k = 0,
+ i,
+ j,
+ length = 16;
+ while (length > 0 && !codeLengths[length - 1]) {
+ length--;
+ }
+ const code = [{
+ children: [],
+ index: 0
+ }];
+ let p = code[0],
+ q;
+ for (i = 0; i < length; i++) {
+ for (j = 0; j < codeLengths[i]; j++) {
+ p = code.pop();
+ p.children[p.index] = values[k];
+ while (p.index > 0) {
+ p = code.pop();
+ }
+ p.index++;
+ code.push(p);
+ while (code.length <= i) {
+ code.push(q = {
+ children: [],
+ index: 0
+ });
+ p.children[p.index] = q.children;
+ p = q;
+ }
+ k++;
+ }
+ if (i + 1 < length) {
+ code.push(q = {
+ children: [],
+ index: 0
+ });
+ p.children[p.index] = q.children;
+ p = q;
+ }
+ }
+ return code[0].children;
+}
+function getBlockBufferOffset(component, row, col) {
+ return 64 * ((component.blocksPerLine + 1) * row + col);
+}
+function decodeScan(data, offset, frame, components, resetInterval, spectralStart, spectralEnd, successivePrev, successive, parseDNLMarker = false) {
+ const mcusPerLine = frame.mcusPerLine;
+ const progressive = frame.progressive;
+ const startOffset = offset;
+ let bitsData = 0,
+ bitsCount = 0;
+ function readBit() {
+ if (bitsCount > 0) {
+ bitsCount--;
+ return bitsData >> bitsCount & 1;
+ }
+ bitsData = data[offset++];
+ if (bitsData === 0xff) {
+ const nextByte = data[offset++];
+ if (nextByte) {
+ if (nextByte === 0xdc && parseDNLMarker) {
+ offset += 2;
+ const scanLines = readUint16(data, offset);
+ offset += 2;
+ if (scanLines > 0 && scanLines !== frame.scanLines) {
+ throw new DNLMarkerError("Found DNL marker (0xFFDC) while parsing scan data", scanLines);
+ }
+ } else if (nextByte === 0xd9) {
+ if (parseDNLMarker) {
+ const maybeScanLines = blockRow * (frame.precision === 8 ? 8 : 0);
+ if (maybeScanLines > 0 && Math.round(frame.scanLines / maybeScanLines) >= 5) {
+ throw new DNLMarkerError("Found EOI marker (0xFFD9) while parsing scan data, " + "possibly caused by incorrect `scanLines` parameter", maybeScanLines);
+ }
+ }
+ throw new EOIMarkerError("Found EOI marker (0xFFD9) while parsing scan data");
+ }
+ throw new JpegError(`unexpected marker ${(bitsData << 8 | nextByte).toString(16)}`);
+ }
+ }
+ bitsCount = 7;
+ return bitsData >>> 7;
+ }
+ function decodeHuffman(tree) {
+ let node = tree;
+ while (true) {
+ node = node[readBit()];
+ switch (typeof node) {
+ case "number":
+ return node;
+ case "object":
+ continue;
+ }
+ throw new JpegError("invalid huffman sequence");
+ }
+ }
+ function receive(length) {
+ let n = 0;
+ while (length > 0) {
+ n = n << 1 | readBit();
+ length--;
+ }
+ return n;
+ }
+ function receiveAndExtend(length) {
+ if (length === 1) {
+ return readBit() === 1 ? 1 : -1;
+ }
+ const n = receive(length);
+ if (n >= 1 << length - 1) {
+ return n;
+ }
+ return n + (-1 << length) + 1;
+ }
+ function decodeBaseline(component, blockOffset) {
+ const t = decodeHuffman(component.huffmanTableDC);
+ const diff = t === 0 ? 0 : receiveAndExtend(t);
+ component.blockData[blockOffset] = component.pred += diff;
+ let k = 1;
+ while (k < 64) {
+ const rs = decodeHuffman(component.huffmanTableAC);
+ const s = rs & 15,
+ r = rs >> 4;
+ if (s === 0) {
+ if (r < 15) {
+ break;
+ }
+ k += 16;
+ continue;
+ }
+ k += r;
+ const z = dctZigZag[k];
+ component.blockData[blockOffset + z] = receiveAndExtend(s);
+ k++;
+ }
+ }
+ function decodeDCFirst(component, blockOffset) {
+ const t = decodeHuffman(component.huffmanTableDC);
+ const diff = t === 0 ? 0 : receiveAndExtend(t) << successive;
+ component.blockData[blockOffset] = component.pred += diff;
+ }
+ function decodeDCSuccessive(component, blockOffset) {
+ component.blockData[blockOffset] |= readBit() << successive;
+ }
+ let eobrun = 0;
+ function decodeACFirst(component, blockOffset) {
+ if (eobrun > 0) {
+ eobrun--;
+ return;
+ }
+ let k = spectralStart;
+ const e = spectralEnd;
+ while (k <= e) {
+ const rs = decodeHuffman(component.huffmanTableAC);
+ const s = rs & 15,
+ r = rs >> 4;
+ if (s === 0) {
+ if (r < 15) {
+ eobrun = receive(r) + (1 << r) - 1;
+ break;
+ }
+ k += 16;
+ continue;
+ }
+ k += r;
+ const z = dctZigZag[k];
+ component.blockData[blockOffset + z] = receiveAndExtend(s) * (1 << successive);
+ k++;
+ }
+ }
+ let successiveACState = 0,
+ successiveACNextValue;
+ function decodeACSuccessive(component, blockOffset) {
+ let k = spectralStart;
+ const e = spectralEnd;
+ let r = 0;
+ let s;
+ let rs;
+ while (k <= e) {
+ const offsetZ = blockOffset + dctZigZag[k];
+ const sign = component.blockData[offsetZ] < 0 ? -1 : 1;
+ switch (successiveACState) {
+ case 0:
+ rs = decodeHuffman(component.huffmanTableAC);
+ s = rs & 15;
+ r = rs >> 4;
+ if (s === 0) {
+ if (r < 15) {
+ eobrun = receive(r) + (1 << r);
+ successiveACState = 4;
+ } else {
+ r = 16;
+ successiveACState = 1;
+ }
+ } else {
+ if (s !== 1) {
+ throw new JpegError("invalid ACn encoding");
+ }
+ successiveACNextValue = receiveAndExtend(s);
+ successiveACState = r ? 2 : 3;
+ }
+ continue;
+ case 1:
+ case 2:
+ if (component.blockData[offsetZ]) {
+ component.blockData[offsetZ] += sign * (readBit() << successive);
+ } else {
+ r--;
+ if (r === 0) {
+ successiveACState = successiveACState === 2 ? 3 : 0;
+ }
+ }
+ break;
+ case 3:
+ if (component.blockData[offsetZ]) {
+ component.blockData[offsetZ] += sign * (readBit() << successive);
+ } else {
+ component.blockData[offsetZ] = successiveACNextValue << successive;
+ successiveACState = 0;
+ }
+ break;
+ case 4:
+ if (component.blockData[offsetZ]) {
+ component.blockData[offsetZ] += sign * (readBit() << successive);
+ }
+ break;
+ }
+ k++;
+ }
+ if (successiveACState === 4) {
+ eobrun--;
+ if (eobrun === 0) {
+ successiveACState = 0;
+ }
+ }
+ }
+ let blockRow = 0;
+ function decodeMcu(component, decode, mcu, row, col) {
+ const mcuRow = mcu / mcusPerLine | 0;
+ const mcuCol = mcu % mcusPerLine;
+ blockRow = mcuRow * component.v + row;
+ const blockCol = mcuCol * component.h + col;
+ const blockOffset = getBlockBufferOffset(component, blockRow, blockCol);
+ decode(component, blockOffset);
+ }
+ function decodeBlock(component, decode, mcu) {
+ blockRow = mcu / component.blocksPerLine | 0;
+ const blockCol = mcu % component.blocksPerLine;
+ const blockOffset = getBlockBufferOffset(component, blockRow, blockCol);
+ decode(component, blockOffset);
+ }
+ const componentsLength = components.length;
+ let component, i, j, k, n;
+ let decodeFn;
+ if (progressive) {
+ if (spectralStart === 0) {
+ decodeFn = successivePrev === 0 ? decodeDCFirst : decodeDCSuccessive;
+ } else {
+ decodeFn = successivePrev === 0 ? decodeACFirst : decodeACSuccessive;
+ }
+ } else {
+ decodeFn = decodeBaseline;
+ }
+ let mcu = 0,
+ fileMarker;
+ const mcuExpected = componentsLength === 1 ? components[0].blocksPerLine * components[0].blocksPerColumn : mcusPerLine * frame.mcusPerColumn;
+ let h, v;
+ while (mcu <= mcuExpected) {
+ const mcuToRead = resetInterval ? Math.min(mcuExpected - mcu, resetInterval) : mcuExpected;
+ if (mcuToRead > 0) {
+ for (i = 0; i < componentsLength; i++) {
+ components[i].pred = 0;
+ }
+ eobrun = 0;
+ if (componentsLength === 1) {
+ component = components[0];
+ for (n = 0; n < mcuToRead; n++) {
+ decodeBlock(component, decodeFn, mcu);
+ mcu++;
+ }
+ } else {
+ for (n = 0; n < mcuToRead; n++) {
+ for (i = 0; i < componentsLength; i++) {
+ component = components[i];
+ h = component.h;
+ v = component.v;
+ for (j = 0; j < v; j++) {
+ for (k = 0; k < h; k++) {
+ decodeMcu(component, decodeFn, mcu, j, k);
+ }
+ }
+ }
+ mcu++;
+ }
+ }
+ }
+ bitsCount = 0;
+ fileMarker = findNextFileMarker(data, offset);
+ if (!fileMarker) {
+ break;
+ }
+ if (fileMarker.invalid) {
+ const partialMsg = mcuToRead > 0 ? "unexpected" : "excessive";
+ warn(`decodeScan - ${partialMsg} MCU data, current marker is: ${fileMarker.invalid}`);
+ offset = fileMarker.offset;
+ }
+ if (fileMarker.marker >= 0xffd0 && fileMarker.marker <= 0xffd7) {
+ offset += 2;
+ } else {
+ break;
+ }
+ }
+ return offset - startOffset;
+}
+function quantizeAndInverse(component, blockBufferOffset, p) {
+ const qt = component.quantizationTable,
+ blockData = component.blockData;
+ let v0, v1, v2, v3, v4, v5, v6, v7;
+ let p0, p1, p2, p3, p4, p5, p6, p7;
+ let t;
+ if (!qt) {
+ throw new JpegError("missing required Quantization Table.");
+ }
+ for (let row = 0; row < 64; row += 8) {
+ p0 = blockData[blockBufferOffset + row];
+ p1 = blockData[blockBufferOffset + row + 1];
+ p2 = blockData[blockBufferOffset + row + 2];
+ p3 = blockData[blockBufferOffset + row + 3];
+ p4 = blockData[blockBufferOffset + row + 4];
+ p5 = blockData[blockBufferOffset + row + 5];
+ p6 = blockData[blockBufferOffset + row + 6];
+ p7 = blockData[blockBufferOffset + row + 7];
+ p0 *= qt[row];
+ if ((p1 | p2 | p3 | p4 | p5 | p6 | p7) === 0) {
+ t = dctSqrt2 * p0 + 512 >> 10;
+ p[row] = t;
+ p[row + 1] = t;
+ p[row + 2] = t;
+ p[row + 3] = t;
+ p[row + 4] = t;
+ p[row + 5] = t;
+ p[row + 6] = t;
+ p[row + 7] = t;
+ continue;
+ }
+ p1 *= qt[row + 1];
+ p2 *= qt[row + 2];
+ p3 *= qt[row + 3];
+ p4 *= qt[row + 4];
+ p5 *= qt[row + 5];
+ p6 *= qt[row + 6];
+ p7 *= qt[row + 7];
+ v0 = dctSqrt2 * p0 + 128 >> 8;
+ v1 = dctSqrt2 * p4 + 128 >> 8;
+ v2 = p2;
+ v3 = p6;
+ v4 = dctSqrt1d2 * (p1 - p7) + 128 >> 8;
+ v7 = dctSqrt1d2 * (p1 + p7) + 128 >> 8;
+ v5 = p3 << 4;
+ v6 = p5 << 4;
+ v0 = v0 + v1 + 1 >> 1;
+ v1 = v0 - v1;
+ t = v2 * dctSin6 + v3 * dctCos6 + 128 >> 8;
+ v2 = v2 * dctCos6 - v3 * dctSin6 + 128 >> 8;
+ v3 = t;
+ v4 = v4 + v6 + 1 >> 1;
+ v6 = v4 - v6;
+ v7 = v7 + v5 + 1 >> 1;
+ v5 = v7 - v5;
+ v0 = v0 + v3 + 1 >> 1;
+ v3 = v0 - v3;
+ v1 = v1 + v2 + 1 >> 1;
+ v2 = v1 - v2;
+ t = v4 * dctSin3 + v7 * dctCos3 + 2048 >> 12;
+ v4 = v4 * dctCos3 - v7 * dctSin3 + 2048 >> 12;
+ v7 = t;
+ t = v5 * dctSin1 + v6 * dctCos1 + 2048 >> 12;
+ v5 = v5 * dctCos1 - v6 * dctSin1 + 2048 >> 12;
+ v6 = t;
+ p[row] = v0 + v7;
+ p[row + 7] = v0 - v7;
+ p[row + 1] = v1 + v6;
+ p[row + 6] = v1 - v6;
+ p[row + 2] = v2 + v5;
+ p[row + 5] = v2 - v5;
+ p[row + 3] = v3 + v4;
+ p[row + 4] = v3 - v4;
+ }
+ for (let col = 0; col < 8; ++col) {
+ p0 = p[col];
+ p1 = p[col + 8];
+ p2 = p[col + 16];
+ p3 = p[col + 24];
+ p4 = p[col + 32];
+ p5 = p[col + 40];
+ p6 = p[col + 48];
+ p7 = p[col + 56];
+ if ((p1 | p2 | p3 | p4 | p5 | p6 | p7) === 0) {
+ t = dctSqrt2 * p0 + 8192 >> 14;
+ if (t < -2040) {
+ t = 0;
+ } else if (t >= 2024) {
+ t = 255;
+ } else {
+ t = t + 2056 >> 4;
+ }
+ blockData[blockBufferOffset + col] = t;
+ blockData[blockBufferOffset + col + 8] = t;
+ blockData[blockBufferOffset + col + 16] = t;
+ blockData[blockBufferOffset + col + 24] = t;
+ blockData[blockBufferOffset + col + 32] = t;
+ blockData[blockBufferOffset + col + 40] = t;
+ blockData[blockBufferOffset + col + 48] = t;
+ blockData[blockBufferOffset + col + 56] = t;
+ continue;
+ }
+ v0 = dctSqrt2 * p0 + 2048 >> 12;
+ v1 = dctSqrt2 * p4 + 2048 >> 12;
+ v2 = p2;
+ v3 = p6;
+ v4 = dctSqrt1d2 * (p1 - p7) + 2048 >> 12;
+ v7 = dctSqrt1d2 * (p1 + p7) + 2048 >> 12;
+ v5 = p3;
+ v6 = p5;
+ v0 = (v0 + v1 + 1 >> 1) + 4112;
+ v1 = v0 - v1;
+ t = v2 * dctSin6 + v3 * dctCos6 + 2048 >> 12;
+ v2 = v2 * dctCos6 - v3 * dctSin6 + 2048 >> 12;
+ v3 = t;
+ v4 = v4 + v6 + 1 >> 1;
+ v6 = v4 - v6;
+ v7 = v7 + v5 + 1 >> 1;
+ v5 = v7 - v5;
+ v0 = v0 + v3 + 1 >> 1;
+ v3 = v0 - v3;
+ v1 = v1 + v2 + 1 >> 1;
+ v2 = v1 - v2;
+ t = v4 * dctSin3 + v7 * dctCos3 + 2048 >> 12;
+ v4 = v4 * dctCos3 - v7 * dctSin3 + 2048 >> 12;
+ v7 = t;
+ t = v5 * dctSin1 + v6 * dctCos1 + 2048 >> 12;
+ v5 = v5 * dctCos1 - v6 * dctSin1 + 2048 >> 12;
+ v6 = t;
+ p0 = v0 + v7;
+ p7 = v0 - v7;
+ p1 = v1 + v6;
+ p6 = v1 - v6;
+ p2 = v2 + v5;
+ p5 = v2 - v5;
+ p3 = v3 + v4;
+ p4 = v3 - v4;
+ if (p0 < 16) {
+ p0 = 0;
+ } else if (p0 >= 4080) {
+ p0 = 255;
+ } else {
+ p0 >>= 4;
+ }
+ if (p1 < 16) {
+ p1 = 0;
+ } else if (p1 >= 4080) {
+ p1 = 255;
+ } else {
+ p1 >>= 4;
+ }
+ if (p2 < 16) {
+ p2 = 0;
+ } else if (p2 >= 4080) {
+ p2 = 255;
+ } else {
+ p2 >>= 4;
+ }
+ if (p3 < 16) {
+ p3 = 0;
+ } else if (p3 >= 4080) {
+ p3 = 255;
+ } else {
+ p3 >>= 4;
+ }
+ if (p4 < 16) {
+ p4 = 0;
+ } else if (p4 >= 4080) {
+ p4 = 255;
+ } else {
+ p4 >>= 4;
+ }
+ if (p5 < 16) {
+ p5 = 0;
+ } else if (p5 >= 4080) {
+ p5 = 255;
+ } else {
+ p5 >>= 4;
+ }
+ if (p6 < 16) {
+ p6 = 0;
+ } else if (p6 >= 4080) {
+ p6 = 255;
+ } else {
+ p6 >>= 4;
+ }
+ if (p7 < 16) {
+ p7 = 0;
+ } else if (p7 >= 4080) {
+ p7 = 255;
+ } else {
+ p7 >>= 4;
+ }
+ blockData[blockBufferOffset + col] = p0;
+ blockData[blockBufferOffset + col + 8] = p1;
+ blockData[blockBufferOffset + col + 16] = p2;
+ blockData[blockBufferOffset + col + 24] = p3;
+ blockData[blockBufferOffset + col + 32] = p4;
+ blockData[blockBufferOffset + col + 40] = p5;
+ blockData[blockBufferOffset + col + 48] = p6;
+ blockData[blockBufferOffset + col + 56] = p7;
+ }
+}
+function buildComponentData(frame, component) {
+ const blocksPerLine = component.blocksPerLine;
+ const blocksPerColumn = component.blocksPerColumn;
+ const computationBuffer = new Int16Array(64);
+ for (let blockRow = 0; blockRow < blocksPerColumn; blockRow++) {
+ for (let blockCol = 0; blockCol < blocksPerLine; blockCol++) {
+ const offset = getBlockBufferOffset(component, blockRow, blockCol);
+ quantizeAndInverse(component, offset, computationBuffer);
+ }
+ }
+ return component.blockData;
+}
+function findNextFileMarker(data, currentPos, startPos = currentPos) {
+ const maxPos = data.length - 1;
+ let newPos = startPos < currentPos ? startPos : currentPos;
+ if (currentPos >= maxPos) {
+ return null;
+ }
+ const currentMarker = readUint16(data, currentPos);
+ if (currentMarker >= 0xffc0 && currentMarker <= 0xfffe) {
+ return {
+ invalid: null,
+ marker: currentMarker,
+ offset: currentPos
+ };
+ }
+ let newMarker = readUint16(data, newPos);
+ while (!(newMarker >= 0xffc0 && newMarker <= 0xfffe)) {
+ if (++newPos >= maxPos) {
+ return null;
+ }
+ newMarker = readUint16(data, newPos);
+ }
+ return {
+ invalid: currentMarker.toString(16),
+ marker: newMarker,
+ offset: newPos
+ };
+}
+class JpegImage {
+ constructor({
+ decodeTransform = null,
+ colorTransform = -1
+ } = {}) {
+ this._decodeTransform = decodeTransform;
+ this._colorTransform = colorTransform;
+ }
+ parse(data, {
+ dnlScanLines = null
+ } = {}) {
+ function readDataBlock() {
+ const length = readUint16(data, offset);
+ offset += 2;
+ let endOffset = offset + length - 2;
+ const fileMarker = findNextFileMarker(data, endOffset, offset);
+ if (fileMarker?.invalid) {
+ warn("readDataBlock - incorrect length, current marker is: " + fileMarker.invalid);
+ endOffset = fileMarker.offset;
+ }
+ const array = data.subarray(offset, endOffset);
+ offset += array.length;
+ return array;
+ }
+ function prepareComponents(frame) {
+ const mcusPerLine = Math.ceil(frame.samplesPerLine / 8 / frame.maxH);
+ const mcusPerColumn = Math.ceil(frame.scanLines / 8 / frame.maxV);
+ for (const component of frame.components) {
+ const blocksPerLine = Math.ceil(Math.ceil(frame.samplesPerLine / 8) * component.h / frame.maxH);
+ const blocksPerColumn = Math.ceil(Math.ceil(frame.scanLines / 8) * component.v / frame.maxV);
+ const blocksPerLineForMcu = mcusPerLine * component.h;
+ const blocksPerColumnForMcu = mcusPerColumn * component.v;
+ const blocksBufferSize = 64 * blocksPerColumnForMcu * (blocksPerLineForMcu + 1);
+ component.blockData = new Int16Array(blocksBufferSize);
+ component.blocksPerLine = blocksPerLine;
+ component.blocksPerColumn = blocksPerColumn;
+ }
+ frame.mcusPerLine = mcusPerLine;
+ frame.mcusPerColumn = mcusPerColumn;
+ }
+ let offset = 0;
+ let jfif = null;
+ let adobe = null;
+ let frame, resetInterval;
+ let numSOSMarkers = 0;
+ const quantizationTables = [];
+ const huffmanTablesAC = [],
+ huffmanTablesDC = [];
+ let fileMarker = readUint16(data, offset);
+ offset += 2;
+ if (fileMarker !== 0xffd8) {
+ throw new JpegError("SOI not found");
+ }
+ fileMarker = readUint16(data, offset);
+ offset += 2;
+ markerLoop: while (fileMarker !== 0xffd9) {
+ let i, j, l;
+ switch (fileMarker) {
+ case 0xffe0:
+ case 0xffe1:
+ case 0xffe2:
+ case 0xffe3:
+ case 0xffe4:
+ case 0xffe5:
+ case 0xffe6:
+ case 0xffe7:
+ case 0xffe8:
+ case 0xffe9:
+ case 0xffea:
+ case 0xffeb:
+ case 0xffec:
+ case 0xffed:
+ case 0xffee:
+ case 0xffef:
+ case 0xfffe:
+ const appData = readDataBlock();
+ if (fileMarker === 0xffe0) {
+ if (appData[0] === 0x4a && appData[1] === 0x46 && appData[2] === 0x49 && appData[3] === 0x46 && appData[4] === 0) {
+ jfif = {
+ version: {
+ major: appData[5],
+ minor: appData[6]
+ },
+ densityUnits: appData[7],
+ xDensity: appData[8] << 8 | appData[9],
+ yDensity: appData[10] << 8 | appData[11],
+ thumbWidth: appData[12],
+ thumbHeight: appData[13],
+ thumbData: appData.subarray(14, 14 + 3 * appData[12] * appData[13])
+ };
+ }
+ }
+ if (fileMarker === 0xffee) {
+ if (appData[0] === 0x41 && appData[1] === 0x64 && appData[2] === 0x6f && appData[3] === 0x62 && appData[4] === 0x65) {
+ adobe = {
+ version: appData[5] << 8 | appData[6],
+ flags0: appData[7] << 8 | appData[8],
+ flags1: appData[9] << 8 | appData[10],
+ transformCode: appData[11]
+ };
+ }
+ }
+ break;
+ case 0xffdb:
+ const quantizationTablesLength = readUint16(data, offset);
+ offset += 2;
+ const quantizationTablesEnd = quantizationTablesLength + offset - 2;
+ let z;
+ while (offset < quantizationTablesEnd) {
+ const quantizationTableSpec = data[offset++];
+ const tableData = new Uint16Array(64);
+ if (quantizationTableSpec >> 4 === 0) {
+ for (j = 0; j < 64; j++) {
+ z = dctZigZag[j];
+ tableData[z] = data[offset++];
+ }
+ } else if (quantizationTableSpec >> 4 === 1) {
+ for (j = 0; j < 64; j++) {
+ z = dctZigZag[j];
+ tableData[z] = readUint16(data, offset);
+ offset += 2;
+ }
+ } else {
+ throw new JpegError("DQT - invalid table spec");
+ }
+ quantizationTables[quantizationTableSpec & 15] = tableData;
+ }
+ break;
+ case 0xffc0:
+ case 0xffc1:
+ case 0xffc2:
+ if (frame) {
+ throw new JpegError("Only single frame JPEGs supported");
+ }
+ offset += 2;
+ frame = {};
+ frame.extended = fileMarker === 0xffc1;
+ frame.progressive = fileMarker === 0xffc2;
+ frame.precision = data[offset++];
+ const sofScanLines = readUint16(data, offset);
+ offset += 2;
+ frame.scanLines = dnlScanLines || sofScanLines;
+ frame.samplesPerLine = readUint16(data, offset);
+ offset += 2;
+ frame.components = [];
+ frame.componentIds = {};
+ const componentsCount = data[offset++];
+ let maxH = 0,
+ maxV = 0;
+ for (i = 0; i < componentsCount; i++) {
+ const componentId = data[offset];
+ const h = data[offset + 1] >> 4;
+ const v = data[offset + 1] & 15;
+ if (maxH < h) {
+ maxH = h;
+ }
+ if (maxV < v) {
+ maxV = v;
+ }
+ const qId = data[offset + 2];
+ l = frame.components.push({
+ h,
+ v,
+ quantizationId: qId,
+ quantizationTable: null
+ });
+ frame.componentIds[componentId] = l - 1;
+ offset += 3;
+ }
+ frame.maxH = maxH;
+ frame.maxV = maxV;
+ prepareComponents(frame);
+ break;
+ case 0xffc4:
+ const huffmanLength = readUint16(data, offset);
+ offset += 2;
+ for (i = 2; i < huffmanLength;) {
+ const huffmanTableSpec = data[offset++];
+ const codeLengths = new Uint8Array(16);
+ let codeLengthSum = 0;
+ for (j = 0; j < 16; j++, offset++) {
+ codeLengthSum += codeLengths[j] = data[offset];
+ }
+ const huffmanValues = new Uint8Array(codeLengthSum);
+ for (j = 0; j < codeLengthSum; j++, offset++) {
+ huffmanValues[j] = data[offset];
+ }
+ i += 17 + codeLengthSum;
+ (huffmanTableSpec >> 4 === 0 ? huffmanTablesDC : huffmanTablesAC)[huffmanTableSpec & 15] = buildHuffmanTable(codeLengths, huffmanValues);
+ }
+ break;
+ case 0xffdd:
+ offset += 2;
+ resetInterval = readUint16(data, offset);
+ offset += 2;
+ break;
+ case 0xffda:
+ const parseDNLMarker = ++numSOSMarkers === 1 && !dnlScanLines;
+ offset += 2;
+ const selectorsCount = data[offset++],
+ components = [];
+ for (i = 0; i < selectorsCount; i++) {
+ const index = data[offset++];
+ const componentIndex = frame.componentIds[index];
+ const component = frame.components[componentIndex];
+ component.index = index;
+ const tableSpec = data[offset++];
+ component.huffmanTableDC = huffmanTablesDC[tableSpec >> 4];
+ component.huffmanTableAC = huffmanTablesAC[tableSpec & 15];
+ components.push(component);
+ }
+ const spectralStart = data[offset++],
+ spectralEnd = data[offset++],
+ successiveApproximation = data[offset++];
+ try {
+ const processed = decodeScan(data, offset, frame, components, resetInterval, spectralStart, spectralEnd, successiveApproximation >> 4, successiveApproximation & 15, parseDNLMarker);
+ offset += processed;
+ } catch (ex) {
+ if (ex instanceof DNLMarkerError) {
+ warn(`${ex.message} -- attempting to re-parse the JPEG image.`);
+ return this.parse(data, {
+ dnlScanLines: ex.scanLines
+ });
+ } else if (ex instanceof EOIMarkerError) {
+ warn(`${ex.message} -- ignoring the rest of the image data.`);
+ break markerLoop;
+ }
+ throw ex;
+ }
+ break;
+ case 0xffdc:
+ offset += 4;
+ break;
+ case 0xffff:
+ if (data[offset] !== 0xff) {
+ offset--;
+ }
+ break;
+ default:
+ const nextFileMarker = findNextFileMarker(data, offset - 2, offset - 3);
+ if (nextFileMarker?.invalid) {
+ warn("JpegImage.parse - unexpected data, current marker is: " + nextFileMarker.invalid);
+ offset = nextFileMarker.offset;
+ break;
+ }
+ if (!nextFileMarker || offset >= data.length - 1) {
+ warn("JpegImage.parse - reached the end of the image data " + "without finding an EOI marker (0xFFD9).");
+ break markerLoop;
+ }
+ throw new JpegError("JpegImage.parse - unknown marker: " + fileMarker.toString(16));
+ }
+ fileMarker = readUint16(data, offset);
+ offset += 2;
+ }
+ if (!frame) {
+ throw new JpegError("JpegImage.parse - no frame data found.");
+ }
+ this.width = frame.samplesPerLine;
+ this.height = frame.scanLines;
+ this.jfif = jfif;
+ this.adobe = adobe;
+ this.components = [];
+ for (const component of frame.components) {
+ const quantizationTable = quantizationTables[component.quantizationId];
+ if (quantizationTable) {
+ component.quantizationTable = quantizationTable;
+ }
+ this.components.push({
+ index: component.index,
+ output: buildComponentData(frame, component),
+ scaleX: component.h / frame.maxH,
+ scaleY: component.v / frame.maxV,
+ blocksPerLine: component.blocksPerLine,
+ blocksPerColumn: component.blocksPerColumn
+ });
+ }
+ this.numComponents = this.components.length;
+ return undefined;
+ }
+ _getLinearizedBlockData(width, height, isSourcePDF = false) {
+ const scaleX = this.width / width,
+ scaleY = this.height / height;
+ let component, componentScaleX, componentScaleY, blocksPerScanline;
+ let x, y, i, j, k;
+ let index;
+ let offset = 0;
+ let output;
+ const numComponents = this.components.length;
+ const dataLength = width * height * numComponents;
+ const data = new Uint8ClampedArray(dataLength);
+ const xScaleBlockOffset = new Uint32Array(width);
+ const mask3LSB = 0xfffffff8;
+ let lastComponentScaleX;
+ for (i = 0; i < numComponents; i++) {
+ component = this.components[i];
+ componentScaleX = component.scaleX * scaleX;
+ componentScaleY = component.scaleY * scaleY;
+ offset = i;
+ output = component.output;
+ blocksPerScanline = component.blocksPerLine + 1 << 3;
+ if (componentScaleX !== lastComponentScaleX) {
+ for (x = 0; x < width; x++) {
+ j = 0 | x * componentScaleX;
+ xScaleBlockOffset[x] = (j & mask3LSB) << 3 | j & 7;
+ }
+ lastComponentScaleX = componentScaleX;
+ }
+ for (y = 0; y < height; y++) {
+ j = 0 | y * componentScaleY;
+ index = blocksPerScanline * (j & mask3LSB) | (j & 7) << 3;
+ for (x = 0; x < width; x++) {
+ data[offset] = output[index + xScaleBlockOffset[x]];
+ offset += numComponents;
+ }
+ }
+ }
+ let transform = this._decodeTransform;
+ if (!isSourcePDF && numComponents === 4 && !transform) {
+ transform = new Int32Array([-256, 255, -256, 255, -256, 255, -256, 255]);
+ }
+ if (transform) {
+ for (i = 0; i < dataLength;) {
+ for (j = 0, k = 0; j < numComponents; j++, i++, k += 2) {
+ data[i] = (data[i] * transform[k] >> 8) + transform[k + 1];
+ }
+ }
+ }
+ return data;
+ }
+ get _isColorConversionNeeded() {
+ if (this.adobe) {
+ return !!this.adobe.transformCode;
+ }
+ if (this.numComponents === 3) {
+ if (this._colorTransform === 0) {
+ return false;
+ } else if (this.components[0].index === 0x52 && this.components[1].index === 0x47 && this.components[2].index === 0x42) {
+ return false;
+ }
+ return true;
+ }
+ if (this._colorTransform === 1) {
+ return true;
+ }
+ return false;
+ }
+ _convertYccToRgb(data) {
+ let Y, Cb, Cr;
+ for (let i = 0, length = data.length; i < length; i += 3) {
+ Y = data[i];
+ Cb = data[i + 1];
+ Cr = data[i + 2];
+ data[i] = Y - 179.456 + 1.402 * Cr;
+ data[i + 1] = Y + 135.459 - 0.344 * Cb - 0.714 * Cr;
+ data[i + 2] = Y - 226.816 + 1.772 * Cb;
+ }
+ return data;
+ }
+ _convertYccToRgba(data, out) {
+ for (let i = 0, j = 0, length = data.length; i < length; i += 3, j += 4) {
+ const Y = data[i];
+ const Cb = data[i + 1];
+ const Cr = data[i + 2];
+ out[j] = Y - 179.456 + 1.402 * Cr;
+ out[j + 1] = Y + 135.459 - 0.344 * Cb - 0.714 * Cr;
+ out[j + 2] = Y - 226.816 + 1.772 * Cb;
+ out[j + 3] = 255;
+ }
+ return out;
+ }
+ _convertYcckToRgb(data) {
+ let Y, Cb, Cr, k;
+ let offset = 0;
+ for (let i = 0, length = data.length; i < length; i += 4) {
+ Y = data[i];
+ Cb = data[i + 1];
+ Cr = data[i + 2];
+ k = data[i + 3];
+ data[offset++] = -122.67195406894 + Cb * (-6.60635669420364e-5 * Cb + 0.000437130475926232 * Cr - 5.4080610064599e-5 * Y + 0.00048449797120281 * k - 0.154362151871126) + Cr * (-0.000957964378445773 * Cr + 0.000817076911346625 * Y - 0.00477271405408747 * k + 1.53380253221734) + Y * (0.000961250184130688 * Y - 0.00266257332283933 * k + 0.48357088451265) + k * (-0.000336197177618394 * k + 0.484791561490776);
+ data[offset++] = 107.268039397724 + Cb * (2.19927104525741e-5 * Cb - 0.000640992018297945 * Cr + 0.000659397001245577 * Y + 0.000426105652938837 * k - 0.176491792462875) + Cr * (-0.000778269941513683 * Cr + 0.00130872261408275 * Y + 0.000770482631801132 * k - 0.151051492775562) + Y * (0.00126935368114843 * Y - 0.00265090189010898 * k + 0.25802910206845) + k * (-0.000318913117588328 * k - 0.213742400323665);
+ data[offset++] = -20.810012546947 + Cb * (-0.000570115196973677 * Cb - 2.63409051004589e-5 * Cr + 0.0020741088115012 * Y - 0.00288260236853442 * k + 0.814272968359295) + Cr * (-1.53496057440975e-5 * Cr - 0.000132689043961446 * Y + 0.000560833691242812 * k - 0.195152027534049) + Y * (0.00174418132927582 * Y - 0.00255243321439347 * k + 0.116935020465145) + k * (-0.000343531996510555 * k + 0.24165260232407);
+ }
+ return data.subarray(0, offset);
+ }
+ _convertYcckToRgba(data) {
+ for (let i = 0, length = data.length; i < length; i += 4) {
+ const Y = data[i];
+ const Cb = data[i + 1];
+ const Cr = data[i + 2];
+ const k = data[i + 3];
+ data[i] = -122.67195406894 + Cb * (-6.60635669420364e-5 * Cb + 0.000437130475926232 * Cr - 5.4080610064599e-5 * Y + 0.00048449797120281 * k - 0.154362151871126) + Cr * (-0.000957964378445773 * Cr + 0.000817076911346625 * Y - 0.00477271405408747 * k + 1.53380253221734) + Y * (0.000961250184130688 * Y - 0.00266257332283933 * k + 0.48357088451265) + k * (-0.000336197177618394 * k + 0.484791561490776);
+ data[i + 1] = 107.268039397724 + Cb * (2.19927104525741e-5 * Cb - 0.000640992018297945 * Cr + 0.000659397001245577 * Y + 0.000426105652938837 * k - 0.176491792462875) + Cr * (-0.000778269941513683 * Cr + 0.00130872261408275 * Y + 0.000770482631801132 * k - 0.151051492775562) + Y * (0.00126935368114843 * Y - 0.00265090189010898 * k + 0.25802910206845) + k * (-0.000318913117588328 * k - 0.213742400323665);
+ data[i + 2] = -20.810012546947 + Cb * (-0.000570115196973677 * Cb - 2.63409051004589e-5 * Cr + 0.0020741088115012 * Y - 0.00288260236853442 * k + 0.814272968359295) + Cr * (-1.53496057440975e-5 * Cr - 0.000132689043961446 * Y + 0.000560833691242812 * k - 0.195152027534049) + Y * (0.00174418132927582 * Y - 0.00255243321439347 * k + 0.116935020465145) + k * (-0.000343531996510555 * k + 0.24165260232407);
+ data[i + 3] = 255;
+ }
+ return data;
+ }
+ _convertYcckToCmyk(data) {
+ let Y, Cb, Cr;
+ for (let i = 0, length = data.length; i < length; i += 4) {
+ Y = data[i];
+ Cb = data[i + 1];
+ Cr = data[i + 2];
+ data[i] = 434.456 - Y - 1.402 * Cr;
+ data[i + 1] = 119.541 - Y + 0.344 * Cb + 0.714 * Cr;
+ data[i + 2] = 481.816 - Y - 1.772 * Cb;
+ }
+ return data;
+ }
+ _convertCmykToRgb(data) {
+ let c, m, y, k;
+ let offset = 0;
+ for (let i = 0, length = data.length; i < length; i += 4) {
+ c = data[i];
+ m = data[i + 1];
+ y = data[i + 2];
+ k = data[i + 3];
+ data[offset++] = 255 + c * (-0.00006747147073602441 * c + 0.0008379262121013727 * m + 0.0002894718188643294 * y + 0.003264231057537806 * k - 1.1185611867203937) + m * (0.000026374107616089405 * m - 0.00008626949158638572 * y - 0.0002748769067499491 * k - 0.02155688794978967) + y * (-0.00003878099212869363 * y - 0.0003267808279485286 * k + 0.0686742238595345) - k * (0.0003361971776183937 * k + 0.7430659151342254);
+ data[offset++] = 255 + c * (0.00013596372813588848 * c + 0.000924537132573585 * m + 0.00010567359618683593 * y + 0.0004791864687436512 * k - 0.3109689587515875) + m * (-0.00023545346108370344 * m + 0.0002702845253534714 * y + 0.0020200308977307156 * k - 0.7488052167015494) + y * (0.00006834815998235662 * y + 0.00015168452363460973 * k - 0.09751927774728933) - k * (0.0003189131175883281 * k + 0.7364883807733168);
+ data[offset++] = 255 + c * (0.000013598650411385307 * c + 0.00012423956175490851 * m + 0.0004751985097583589 * y - 0.0000036729317476630422 * k - 0.05562186980264034) + m * (0.00016141380598724676 * m + 0.0009692239130725186 * y + 0.0007782692450036253 * k - 0.44015232367526463) + y * (5.068882914068769e-7 * y + 0.0017778369011375071 * k - 0.7591454649749609) - k * (0.0003435319965105553 * k + 0.7063770186160144);
+ }
+ return data.subarray(0, offset);
+ }
+ _convertCmykToRgba(data) {
+ for (let i = 0, length = data.length; i < length; i += 4) {
+ const c = data[i];
+ const m = data[i + 1];
+ const y = data[i + 2];
+ const k = data[i + 3];
+ data[i] = 255 + c * (-0.00006747147073602441 * c + 0.0008379262121013727 * m + 0.0002894718188643294 * y + 0.003264231057537806 * k - 1.1185611867203937) + m * (0.000026374107616089405 * m - 0.00008626949158638572 * y - 0.0002748769067499491 * k - 0.02155688794978967) + y * (-0.00003878099212869363 * y - 0.0003267808279485286 * k + 0.0686742238595345) - k * (0.0003361971776183937 * k + 0.7430659151342254);
+ data[i + 1] = 255 + c * (0.00013596372813588848 * c + 0.000924537132573585 * m + 0.00010567359618683593 * y + 0.0004791864687436512 * k - 0.3109689587515875) + m * (-0.00023545346108370344 * m + 0.0002702845253534714 * y + 0.0020200308977307156 * k - 0.7488052167015494) + y * (0.00006834815998235662 * y + 0.00015168452363460973 * k - 0.09751927774728933) - k * (0.0003189131175883281 * k + 0.7364883807733168);
+ data[i + 2] = 255 + c * (0.000013598650411385307 * c + 0.00012423956175490851 * m + 0.0004751985097583589 * y - 0.0000036729317476630422 * k - 0.05562186980264034) + m * (0.00016141380598724676 * m + 0.0009692239130725186 * y + 0.0007782692450036253 * k - 0.44015232367526463) + y * (5.068882914068769e-7 * y + 0.0017778369011375071 * k - 0.7591454649749609) - k * (0.0003435319965105553 * k + 0.7063770186160144);
+ data[i + 3] = 255;
+ }
+ return data;
+ }
+ getData({
+ width,
+ height,
+ forceRGBA = false,
+ forceRGB = false,
+ isSourcePDF = false
+ }) {
+ if (this.numComponents > 4) {
+ throw new JpegError("Unsupported color mode");
+ }
+ const data = this._getLinearizedBlockData(width, height, isSourcePDF);
+ if (this.numComponents === 1 && (forceRGBA || forceRGB)) {
+ const len = data.length * (forceRGBA ? 4 : 3);
+ const rgbaData = new Uint8ClampedArray(len);
+ let offset = 0;
+ if (forceRGBA) {
+ grayToRGBA(data, new Uint32Array(rgbaData.buffer));
+ } else {
+ for (const grayColor of data) {
+ rgbaData[offset++] = grayColor;
+ rgbaData[offset++] = grayColor;
+ rgbaData[offset++] = grayColor;
+ }
+ }
+ return rgbaData;
+ } else if (this.numComponents === 3 && this._isColorConversionNeeded) {
+ if (forceRGBA) {
+ const rgbaData = new Uint8ClampedArray(data.length / 3 * 4);
+ return this._convertYccToRgba(data, rgbaData);
+ }
+ return this._convertYccToRgb(data);
+ } else if (this.numComponents === 4) {
+ if (this._isColorConversionNeeded) {
+ if (forceRGBA) {
+ return this._convertYcckToRgba(data);
+ }
+ if (forceRGB) {
+ return this._convertYcckToRgb(data);
+ }
+ return this._convertYcckToCmyk(data);
+ } else if (forceRGBA) {
+ return this._convertCmykToRgba(data);
+ } else if (forceRGB) {
+ return this._convertCmykToRgb(data);
+ }
+ }
+ return data;
+ }
+}
+
+;// CONCATENATED MODULE: ./src/core/jpeg_stream.js
+
+
+
+
+class JpegStream extends DecodeStream {
+ constructor(stream, maybeLength, params) {
+ let ch;
+ while ((ch = stream.getByte()) !== -1) {
+ if (ch === 0xff) {
+ stream.skip(-1);
+ break;
+ }
+ }
+ super(maybeLength);
+ this.stream = stream;
+ this.dict = stream.dict;
+ this.maybeLength = maybeLength;
+ this.params = params;
+ }
+ get bytes() {
+ return shadow(this, "bytes", this.stream.getBytes(this.maybeLength));
+ }
+ ensureBuffer(requested) {}
+ readBlock() {
+ if (this.eof) {
+ return;
+ }
+ const jpegOptions = {
+ decodeTransform: undefined,
+ colorTransform: undefined
+ };
+ const decodeArr = this.dict.getArray("D", "Decode");
+ if ((this.forceRGBA || this.forceRGB) && Array.isArray(decodeArr)) {
+ const bitsPerComponent = this.dict.get("BPC", "BitsPerComponent") || 8;
+ const decodeArrLength = decodeArr.length;
+ const transform = new Int32Array(decodeArrLength);
+ let transformNeeded = false;
+ const maxValue = (1 << bitsPerComponent) - 1;
+ for (let i = 0; i < decodeArrLength; i += 2) {
+ transform[i] = (decodeArr[i + 1] - decodeArr[i]) * 256 | 0;
+ transform[i + 1] = decodeArr[i] * maxValue | 0;
+ if (transform[i] !== 256 || transform[i + 1] !== 0) {
+ transformNeeded = true;
+ }
+ }
+ if (transformNeeded) {
+ jpegOptions.decodeTransform = transform;
+ }
+ }
+ if (this.params instanceof Dict) {
+ const colorTransform = this.params.get("ColorTransform");
+ if (Number.isInteger(colorTransform)) {
+ jpegOptions.colorTransform = colorTransform;
+ }
+ }
+ const jpegImage = new JpegImage(jpegOptions);
+ jpegImage.parse(this.bytes);
+ const data = jpegImage.getData({
+ width: this.drawWidth,
+ height: this.drawHeight,
+ forceRGBA: this.forceRGBA,
+ forceRGB: this.forceRGB,
+ isSourcePDF: true
+ });
+ this.buffer = data;
+ this.bufferLength = data.length;
+ this.eof = true;
+ }
+}
+
+;// CONCATENATED MODULE: ./src/core/jpx.js
+
+
+
+class JpxError extends BaseException {
+ constructor(msg) {
+ super(`JPX error: ${msg}`, "JpxError");
+ }
+}
+const SubbandsGainLog2 = {
+ LL: 0,
+ LH: 1,
+ HL: 1,
+ HH: 2
+};
+class JpxImage {
+ constructor() {
+ this.failOnCorruptedImage = false;
+ }
+ parse(data) {
+ const head = readUint16(data, 0);
+ if (head === 0xff4f) {
+ this.parseCodestream(data, 0, data.length);
+ return;
+ }
+ const length = data.length;
+ let position = 0;
+ while (position < length) {
+ let headerSize = 8;
+ let lbox = readUint32(data, position);
+ const tbox = readUint32(data, position + 4);
+ position += headerSize;
+ if (lbox === 1) {
+ lbox = readUint32(data, position) * 4294967296 + readUint32(data, position + 4);
+ position += 8;
+ headerSize += 8;
+ }
+ if (lbox === 0) {
+ lbox = length - position + headerSize;
+ }
+ if (lbox < headerSize) {
+ throw new JpxError("Invalid box field size");
+ }
+ const dataLength = lbox - headerSize;
+ let jumpDataLength = true;
+ switch (tbox) {
+ case 0x6a703268:
+ jumpDataLength = false;
+ break;
+ case 0x636f6c72:
+ const method = data[position];
+ if (method === 1) {
+ const colorspace = readUint32(data, position + 3);
+ switch (colorspace) {
+ case 16:
+ case 17:
+ case 18:
+ break;
+ default:
+ warn("Unknown colorspace " + colorspace);
+ break;
+ }
+ } else if (method === 2) {
+ info("ICC profile not supported");
+ }
+ break;
+ case 0x6a703263:
+ this.parseCodestream(data, position, position + dataLength);
+ break;
+ case 0x6a502020:
+ if (readUint32(data, position) !== 0x0d0a870a) {
+ warn("Invalid JP2 signature");
+ }
+ break;
+ case 0x6a501a1a:
+ case 0x66747970:
+ case 0x72726571:
+ case 0x72657320:
+ case 0x69686472:
+ break;
+ default:
+ const headerType = String.fromCharCode(tbox >> 24 & 0xff, tbox >> 16 & 0xff, tbox >> 8 & 0xff, tbox & 0xff);
+ warn(`Unsupported header type ${tbox} (${headerType}).`);
+ break;
+ }
+ if (jumpDataLength) {
+ position += dataLength;
+ }
+ }
+ }
+ parseImageProperties(stream) {
+ let newByte = stream.getByte();
+ while (newByte >= 0) {
+ const oldByte = newByte;
+ newByte = stream.getByte();
+ const code = oldByte << 8 | newByte;
+ if (code === 0xff51) {
+ stream.skip(4);
+ const Xsiz = stream.getInt32() >>> 0;
+ const Ysiz = stream.getInt32() >>> 0;
+ const XOsiz = stream.getInt32() >>> 0;
+ const YOsiz = stream.getInt32() >>> 0;
+ stream.skip(16);
+ const Csiz = stream.getUint16();
+ this.width = Xsiz - XOsiz;
+ this.height = Ysiz - YOsiz;
+ this.componentsCount = Csiz;
+ this.bitsPerComponent = 8;
+ return;
+ }
+ }
+ throw new JpxError("No size marker found in JPX stream");
+ }
+ parseCodestream(data, start, end) {
+ const context = {};
+ let doNotRecover = false;
+ try {
+ let position = start;
+ while (position + 1 < end) {
+ const code = readUint16(data, position);
+ position += 2;
+ let length = 0,
+ j,
+ sqcd,
+ spqcds,
+ spqcdSize,
+ scalarExpounded,
+ tile;
+ switch (code) {
+ case 0xff4f:
+ context.mainHeader = true;
+ break;
+ case 0xffd9:
+ break;
+ case 0xff51:
+ length = readUint16(data, position);
+ const siz = {};
+ siz.Xsiz = readUint32(data, position + 4);
+ siz.Ysiz = readUint32(data, position + 8);
+ siz.XOsiz = readUint32(data, position + 12);
+ siz.YOsiz = readUint32(data, position + 16);
+ siz.XTsiz = readUint32(data, position + 20);
+ siz.YTsiz = readUint32(data, position + 24);
+ siz.XTOsiz = readUint32(data, position + 28);
+ siz.YTOsiz = readUint32(data, position + 32);
+ const componentsCount = readUint16(data, position + 36);
+ siz.Csiz = componentsCount;
+ const components = [];
+ j = position + 38;
+ for (let i = 0; i < componentsCount; i++) {
+ const component = {
+ precision: (data[j] & 0x7f) + 1,
+ isSigned: !!(data[j] & 0x80),
+ XRsiz: data[j + 1],
+ YRsiz: data[j + 2]
+ };
+ j += 3;
+ calculateComponentDimensions(component, siz);
+ components.push(component);
+ }
+ context.SIZ = siz;
+ context.components = components;
+ calculateTileGrids(context, components);
+ context.QCC = [];
+ context.COC = [];
+ break;
+ case 0xff5c:
+ length = readUint16(data, position);
+ const qcd = {};
+ j = position + 2;
+ sqcd = data[j++];
+ switch (sqcd & 0x1f) {
+ case 0:
+ spqcdSize = 8;
+ scalarExpounded = true;
+ break;
+ case 1:
+ spqcdSize = 16;
+ scalarExpounded = false;
+ break;
+ case 2:
+ spqcdSize = 16;
+ scalarExpounded = true;
+ break;
+ default:
+ throw new Error("Invalid SQcd value " + sqcd);
+ }
+ qcd.noQuantization = spqcdSize === 8;
+ qcd.scalarExpounded = scalarExpounded;
+ qcd.guardBits = sqcd >> 5;
+ spqcds = [];
+ while (j < length + position) {
+ const spqcd = {};
+ if (spqcdSize === 8) {
+ spqcd.epsilon = data[j++] >> 3;
+ spqcd.mu = 0;
+ } else {
+ spqcd.epsilon = data[j] >> 3;
+ spqcd.mu = (data[j] & 0x7) << 8 | data[j + 1];
+ j += 2;
+ }
+ spqcds.push(spqcd);
+ }
+ qcd.SPqcds = spqcds;
+ if (context.mainHeader) {
+ context.QCD = qcd;
+ } else {
+ context.currentTile.QCD = qcd;
+ context.currentTile.QCC = [];
+ }
+ break;
+ case 0xff5d:
+ length = readUint16(data, position);
+ const qcc = {};
+ j = position + 2;
+ let cqcc;
+ if (context.SIZ.Csiz < 257) {
+ cqcc = data[j++];
+ } else {
+ cqcc = readUint16(data, j);
+ j += 2;
+ }
+ sqcd = data[j++];
+ switch (sqcd & 0x1f) {
+ case 0:
+ spqcdSize = 8;
+ scalarExpounded = true;
+ break;
+ case 1:
+ spqcdSize = 16;
+ scalarExpounded = false;
+ break;
+ case 2:
+ spqcdSize = 16;
+ scalarExpounded = true;
+ break;
+ default:
+ throw new Error("Invalid SQcd value " + sqcd);
+ }
+ qcc.noQuantization = spqcdSize === 8;
+ qcc.scalarExpounded = scalarExpounded;
+ qcc.guardBits = sqcd >> 5;
+ spqcds = [];
+ while (j < length + position) {
+ const spqcd = {};
+ if (spqcdSize === 8) {
+ spqcd.epsilon = data[j++] >> 3;
+ spqcd.mu = 0;
+ } else {
+ spqcd.epsilon = data[j] >> 3;
+ spqcd.mu = (data[j] & 0x7) << 8 | data[j + 1];
+ j += 2;
+ }
+ spqcds.push(spqcd);
+ }
+ qcc.SPqcds = spqcds;
+ if (context.mainHeader) {
+ context.QCC[cqcc] = qcc;
+ } else {
+ context.currentTile.QCC[cqcc] = qcc;
+ }
+ break;
+ case 0xff52:
+ length = readUint16(data, position);
+ const cod = {};
+ j = position + 2;
+ const scod = data[j++];
+ cod.entropyCoderWithCustomPrecincts = !!(scod & 1);
+ cod.sopMarkerUsed = !!(scod & 2);
+ cod.ephMarkerUsed = !!(scod & 4);
+ cod.progressionOrder = data[j++];
+ cod.layersCount = readUint16(data, j);
+ j += 2;
+ cod.multipleComponentTransform = data[j++];
+ cod.decompositionLevelsCount = data[j++];
+ cod.xcb = (data[j++] & 0xf) + 2;
+ cod.ycb = (data[j++] & 0xf) + 2;
+ const blockStyle = data[j++];
+ cod.selectiveArithmeticCodingBypass = !!(blockStyle & 1);
+ cod.resetContextProbabilities = !!(blockStyle & 2);
+ cod.terminationOnEachCodingPass = !!(blockStyle & 4);
+ cod.verticallyStripe = !!(blockStyle & 8);
+ cod.predictableTermination = !!(blockStyle & 16);
+ cod.segmentationSymbolUsed = !!(blockStyle & 32);
+ cod.reversibleTransformation = data[j++];
+ if (cod.entropyCoderWithCustomPrecincts) {
+ const precinctsSizes = [];
+ while (j < length + position) {
+ const precinctsSize = data[j++];
+ precinctsSizes.push({
+ PPx: precinctsSize & 0xf,
+ PPy: precinctsSize >> 4
+ });
+ }
+ cod.precinctsSizes = precinctsSizes;
+ }
+ const unsupported = [];
+ if (cod.selectiveArithmeticCodingBypass) {
+ unsupported.push("selectiveArithmeticCodingBypass");
+ }
+ if (cod.terminationOnEachCodingPass) {
+ unsupported.push("terminationOnEachCodingPass");
+ }
+ if (cod.verticallyStripe) {
+ unsupported.push("verticallyStripe");
+ }
+ if (cod.predictableTermination) {
+ unsupported.push("predictableTermination");
+ }
+ if (unsupported.length > 0) {
+ doNotRecover = true;
+ warn(`JPX: Unsupported COD options (${unsupported.join(", ")}).`);
+ }
+ if (context.mainHeader) {
+ context.COD = cod;
+ } else {
+ context.currentTile.COD = cod;
+ context.currentTile.COC = [];
+ }
+ break;
+ case 0xff90:
+ length = readUint16(data, position);
+ tile = {};
+ tile.index = readUint16(data, position + 2);
+ tile.length = readUint32(data, position + 4);
+ tile.dataEnd = tile.length + position - 2;
+ tile.partIndex = data[position + 8];
+ tile.partsCount = data[position + 9];
+ context.mainHeader = false;
+ if (tile.partIndex === 0) {
+ tile.COD = context.COD;
+ tile.COC = context.COC.slice(0);
+ tile.QCD = context.QCD;
+ tile.QCC = context.QCC.slice(0);
+ }
+ context.currentTile = tile;
+ break;
+ case 0xff93:
+ tile = context.currentTile;
+ if (tile.partIndex === 0) {
+ initializeTile(context, tile.index);
+ buildPackets(context);
+ }
+ length = tile.dataEnd - position;
+ parseTilePackets(context, data, position, length);
+ break;
+ case 0xff53:
+ warn("JPX: Codestream code 0xFF53 (COC) is not implemented.");
+ case 0xff55:
+ case 0xff57:
+ case 0xff58:
+ case 0xff64:
+ length = readUint16(data, position);
+ break;
+ default:
+ throw new Error("Unknown codestream code: " + code.toString(16));
+ }
+ position += length;
+ }
+ } catch (e) {
+ if (doNotRecover || this.failOnCorruptedImage) {
+ throw new JpxError(e.message);
+ } else {
+ warn(`JPX: Trying to recover from: "${e.message}".`);
+ }
+ }
+ this.tiles = transformComponents(context);
+ this.width = context.SIZ.Xsiz - context.SIZ.XOsiz;
+ this.height = context.SIZ.Ysiz - context.SIZ.YOsiz;
+ this.componentsCount = context.SIZ.Csiz;
+ }
+}
+function calculateComponentDimensions(component, siz) {
+ component.x0 = Math.ceil(siz.XOsiz / component.XRsiz);
+ component.x1 = Math.ceil(siz.Xsiz / component.XRsiz);
+ component.y0 = Math.ceil(siz.YOsiz / component.YRsiz);
+ component.y1 = Math.ceil(siz.Ysiz / component.YRsiz);
+ component.width = component.x1 - component.x0;
+ component.height = component.y1 - component.y0;
+}
+function calculateTileGrids(context, components) {
+ const siz = context.SIZ;
+ const tiles = [];
+ let tile;
+ const numXtiles = Math.ceil((siz.Xsiz - siz.XTOsiz) / siz.XTsiz);
+ const numYtiles = Math.ceil((siz.Ysiz - siz.YTOsiz) / siz.YTsiz);
+ for (let q = 0; q < numYtiles; q++) {
+ for (let p = 0; p < numXtiles; p++) {
+ tile = {};
+ tile.tx0 = Math.max(siz.XTOsiz + p * siz.XTsiz, siz.XOsiz);
+ tile.ty0 = Math.max(siz.YTOsiz + q * siz.YTsiz, siz.YOsiz);
+ tile.tx1 = Math.min(siz.XTOsiz + (p + 1) * siz.XTsiz, siz.Xsiz);
+ tile.ty1 = Math.min(siz.YTOsiz + (q + 1) * siz.YTsiz, siz.Ysiz);
+ tile.width = tile.tx1 - tile.tx0;
+ tile.height = tile.ty1 - tile.ty0;
+ tile.components = [];
+ tiles.push(tile);
+ }
+ }
+ context.tiles = tiles;
+ const componentsCount = siz.Csiz;
+ for (let i = 0, ii = componentsCount; i < ii; i++) {
+ const component = components[i];
+ for (let j = 0, jj = tiles.length; j < jj; j++) {
+ const tileComponent = {};
+ tile = tiles[j];
+ tileComponent.tcx0 = Math.ceil(tile.tx0 / component.XRsiz);
+ tileComponent.tcy0 = Math.ceil(tile.ty0 / component.YRsiz);
+ tileComponent.tcx1 = Math.ceil(tile.tx1 / component.XRsiz);
+ tileComponent.tcy1 = Math.ceil(tile.ty1 / component.YRsiz);
+ tileComponent.width = tileComponent.tcx1 - tileComponent.tcx0;
+ tileComponent.height = tileComponent.tcy1 - tileComponent.tcy0;
+ tile.components[i] = tileComponent;
+ }
+ }
+}
+function getBlocksDimensions(context, component, r) {
+ const codOrCoc = component.codingStyleParameters;
+ const result = {};
+ if (!codOrCoc.entropyCoderWithCustomPrecincts) {
+ result.PPx = 15;
+ result.PPy = 15;
+ } else {
+ result.PPx = codOrCoc.precinctsSizes[r].PPx;
+ result.PPy = codOrCoc.precinctsSizes[r].PPy;
+ }
+ result.xcb_ = r > 0 ? Math.min(codOrCoc.xcb, result.PPx - 1) : Math.min(codOrCoc.xcb, result.PPx);
+ result.ycb_ = r > 0 ? Math.min(codOrCoc.ycb, result.PPy - 1) : Math.min(codOrCoc.ycb, result.PPy);
+ return result;
+}
+function buildPrecincts(context, resolution, dimensions) {
+ const precinctWidth = 1 << dimensions.PPx;
+ const precinctHeight = 1 << dimensions.PPy;
+ const isZeroRes = resolution.resLevel === 0;
+ const precinctWidthInSubband = 1 << dimensions.PPx + (isZeroRes ? 0 : -1);
+ const precinctHeightInSubband = 1 << dimensions.PPy + (isZeroRes ? 0 : -1);
+ const numprecinctswide = resolution.trx1 > resolution.trx0 ? Math.ceil(resolution.trx1 / precinctWidth) - Math.floor(resolution.trx0 / precinctWidth) : 0;
+ const numprecinctshigh = resolution.try1 > resolution.try0 ? Math.ceil(resolution.try1 / precinctHeight) - Math.floor(resolution.try0 / precinctHeight) : 0;
+ const numprecincts = numprecinctswide * numprecinctshigh;
+ resolution.precinctParameters = {
+ precinctWidth,
+ precinctHeight,
+ numprecinctswide,
+ numprecinctshigh,
+ numprecincts,
+ precinctWidthInSubband,
+ precinctHeightInSubband
+ };
+}
+function buildCodeblocks(context, subband, dimensions) {
+ const xcb_ = dimensions.xcb_;
+ const ycb_ = dimensions.ycb_;
+ const codeblockWidth = 1 << xcb_;
+ const codeblockHeight = 1 << ycb_;
+ const cbx0 = subband.tbx0 >> xcb_;
+ const cby0 = subband.tby0 >> ycb_;
+ const cbx1 = subband.tbx1 + codeblockWidth - 1 >> xcb_;
+ const cby1 = subband.tby1 + codeblockHeight - 1 >> ycb_;
+ const precinctParameters = subband.resolution.precinctParameters;
+ const codeblocks = [];
+ const precincts = [];
+ let i, j, codeblock, precinctNumber;
+ for (j = cby0; j < cby1; j++) {
+ for (i = cbx0; i < cbx1; i++) {
+ codeblock = {
+ cbx: i,
+ cby: j,
+ tbx0: codeblockWidth * i,
+ tby0: codeblockHeight * j,
+ tbx1: codeblockWidth * (i + 1),
+ tby1: codeblockHeight * (j + 1)
+ };
+ codeblock.tbx0_ = Math.max(subband.tbx0, codeblock.tbx0);
+ codeblock.tby0_ = Math.max(subband.tby0, codeblock.tby0);
+ codeblock.tbx1_ = Math.min(subband.tbx1, codeblock.tbx1);
+ codeblock.tby1_ = Math.min(subband.tby1, codeblock.tby1);
+ const pi = Math.floor((codeblock.tbx0_ - subband.tbx0) / precinctParameters.precinctWidthInSubband);
+ const pj = Math.floor((codeblock.tby0_ - subband.tby0) / precinctParameters.precinctHeightInSubband);
+ precinctNumber = pi + pj * precinctParameters.numprecinctswide;
+ codeblock.precinctNumber = precinctNumber;
+ codeblock.subbandType = subband.type;
+ codeblock.Lblock = 3;
+ if (codeblock.tbx1_ <= codeblock.tbx0_ || codeblock.tby1_ <= codeblock.tby0_) {
+ continue;
+ }
+ codeblocks.push(codeblock);
+ let precinct = precincts[precinctNumber];
+ if (precinct !== undefined) {
+ if (i < precinct.cbxMin) {
+ precinct.cbxMin = i;
+ } else if (i > precinct.cbxMax) {
+ precinct.cbxMax = i;
+ }
+ if (j < precinct.cbyMin) {
+ precinct.cbxMin = j;
+ } else if (j > precinct.cbyMax) {
+ precinct.cbyMax = j;
+ }
+ } else {
+ precincts[precinctNumber] = precinct = {
+ cbxMin: i,
+ cbyMin: j,
+ cbxMax: i,
+ cbyMax: j
+ };
+ }
+ codeblock.precinct = precinct;
+ }
+ }
+ subband.codeblockParameters = {
+ codeblockWidth: xcb_,
+ codeblockHeight: ycb_,
+ numcodeblockwide: cbx1 - cbx0 + 1,
+ numcodeblockhigh: cby1 - cby0 + 1
+ };
+ subband.codeblocks = codeblocks;
+ subband.precincts = precincts;
+}
+function createPacket(resolution, precinctNumber, layerNumber) {
+ const precinctCodeblocks = [];
+ const subbands = resolution.subbands;
+ for (let i = 0, ii = subbands.length; i < ii; i++) {
+ const subband = subbands[i];
+ const codeblocks = subband.codeblocks;
+ for (let j = 0, jj = codeblocks.length; j < jj; j++) {
+ const codeblock = codeblocks[j];
+ if (codeblock.precinctNumber !== precinctNumber) {
+ continue;
+ }
+ precinctCodeblocks.push(codeblock);
+ }
+ }
+ return {
+ layerNumber,
+ codeblocks: precinctCodeblocks
+ };
+}
+function LayerResolutionComponentPositionIterator(context) {
+ const siz = context.SIZ;
+ const tileIndex = context.currentTile.index;
+ const tile = context.tiles[tileIndex];
+ const layersCount = tile.codingStyleDefaultParameters.layersCount;
+ const componentsCount = siz.Csiz;
+ let maxDecompositionLevelsCount = 0;
+ for (let q = 0; q < componentsCount; q++) {
+ maxDecompositionLevelsCount = Math.max(maxDecompositionLevelsCount, tile.components[q].codingStyleParameters.decompositionLevelsCount);
+ }
+ let l = 0,
+ r = 0,
+ i = 0,
+ k = 0;
+ this.nextPacket = function JpxImage_nextPacket() {
+ for (; l < layersCount; l++) {
+ for (; r <= maxDecompositionLevelsCount; r++) {
+ for (; i < componentsCount; i++) {
+ const component = tile.components[i];
+ if (r > component.codingStyleParameters.decompositionLevelsCount) {
+ continue;
+ }
+ const resolution = component.resolutions[r];
+ const numprecincts = resolution.precinctParameters.numprecincts;
+ for (; k < numprecincts;) {
+ const packet = createPacket(resolution, k, l);
+ k++;
+ return packet;
+ }
+ k = 0;
+ }
+ i = 0;
+ }
+ r = 0;
+ }
+ throw new JpxError("Out of packets");
+ };
+}
+function ResolutionLayerComponentPositionIterator(context) {
+ const siz = context.SIZ;
+ const tileIndex = context.currentTile.index;
+ const tile = context.tiles[tileIndex];
+ const layersCount = tile.codingStyleDefaultParameters.layersCount;
+ const componentsCount = siz.Csiz;
+ let maxDecompositionLevelsCount = 0;
+ for (let q = 0; q < componentsCount; q++) {
+ maxDecompositionLevelsCount = Math.max(maxDecompositionLevelsCount, tile.components[q].codingStyleParameters.decompositionLevelsCount);
+ }
+ let r = 0,
+ l = 0,
+ i = 0,
+ k = 0;
+ this.nextPacket = function JpxImage_nextPacket() {
+ for (; r <= maxDecompositionLevelsCount; r++) {
+ for (; l < layersCount; l++) {
+ for (; i < componentsCount; i++) {
+ const component = tile.components[i];
+ if (r > component.codingStyleParameters.decompositionLevelsCount) {
+ continue;
+ }
+ const resolution = component.resolutions[r];
+ const numprecincts = resolution.precinctParameters.numprecincts;
+ for (; k < numprecincts;) {
+ const packet = createPacket(resolution, k, l);
+ k++;
+ return packet;
+ }
+ k = 0;
+ }
+ i = 0;
+ }
+ l = 0;
+ }
+ throw new JpxError("Out of packets");
+ };
+}
+function ResolutionPositionComponentLayerIterator(context) {
+ const siz = context.SIZ;
+ const tileIndex = context.currentTile.index;
+ const tile = context.tiles[tileIndex];
+ const layersCount = tile.codingStyleDefaultParameters.layersCount;
+ const componentsCount = siz.Csiz;
+ let l, r, c, p;
+ let maxDecompositionLevelsCount = 0;
+ for (c = 0; c < componentsCount; c++) {
+ const component = tile.components[c];
+ maxDecompositionLevelsCount = Math.max(maxDecompositionLevelsCount, component.codingStyleParameters.decompositionLevelsCount);
+ }
+ const maxNumPrecinctsInLevel = new Int32Array(maxDecompositionLevelsCount + 1);
+ for (r = 0; r <= maxDecompositionLevelsCount; ++r) {
+ let maxNumPrecincts = 0;
+ for (c = 0; c < componentsCount; ++c) {
+ const resolutions = tile.components[c].resolutions;
+ if (r < resolutions.length) {
+ maxNumPrecincts = Math.max(maxNumPrecincts, resolutions[r].precinctParameters.numprecincts);
+ }
+ }
+ maxNumPrecinctsInLevel[r] = maxNumPrecincts;
+ }
+ l = 0;
+ r = 0;
+ c = 0;
+ p = 0;
+ this.nextPacket = function JpxImage_nextPacket() {
+ for (; r <= maxDecompositionLevelsCount; r++) {
+ for (; p < maxNumPrecinctsInLevel[r]; p++) {
+ for (; c < componentsCount; c++) {
+ const component = tile.components[c];
+ if (r > component.codingStyleParameters.decompositionLevelsCount) {
+ continue;
+ }
+ const resolution = component.resolutions[r];
+ const numprecincts = resolution.precinctParameters.numprecincts;
+ if (p >= numprecincts) {
+ continue;
+ }
+ for (; l < layersCount;) {
+ const packet = createPacket(resolution, p, l);
+ l++;
+ return packet;
+ }
+ l = 0;
+ }
+ c = 0;
+ }
+ p = 0;
+ }
+ throw new JpxError("Out of packets");
+ };
+}
+function PositionComponentResolutionLayerIterator(context) {
+ const siz = context.SIZ;
+ const tileIndex = context.currentTile.index;
+ const tile = context.tiles[tileIndex];
+ const layersCount = tile.codingStyleDefaultParameters.layersCount;
+ const componentsCount = siz.Csiz;
+ const precinctsSizes = getPrecinctSizesInImageScale(tile);
+ const precinctsIterationSizes = precinctsSizes;
+ let l = 0,
+ r = 0,
+ c = 0,
+ px = 0,
+ py = 0;
+ this.nextPacket = function JpxImage_nextPacket() {
+ for (; py < precinctsIterationSizes.maxNumHigh; py++) {
+ for (; px < precinctsIterationSizes.maxNumWide; px++) {
+ for (; c < componentsCount; c++) {
+ const component = tile.components[c];
+ const decompositionLevelsCount = component.codingStyleParameters.decompositionLevelsCount;
+ for (; r <= decompositionLevelsCount; r++) {
+ const resolution = component.resolutions[r];
+ const sizeInImageScale = precinctsSizes.components[c].resolutions[r];
+ const k = getPrecinctIndexIfExist(px, py, sizeInImageScale, precinctsIterationSizes, resolution);
+ if (k === null) {
+ continue;
+ }
+ for (; l < layersCount;) {
+ const packet = createPacket(resolution, k, l);
+ l++;
+ return packet;
+ }
+ l = 0;
+ }
+ r = 0;
+ }
+ c = 0;
+ }
+ px = 0;
+ }
+ throw new JpxError("Out of packets");
+ };
+}
+function ComponentPositionResolutionLayerIterator(context) {
+ const siz = context.SIZ;
+ const tileIndex = context.currentTile.index;
+ const tile = context.tiles[tileIndex];
+ const layersCount = tile.codingStyleDefaultParameters.layersCount;
+ const componentsCount = siz.Csiz;
+ const precinctsSizes = getPrecinctSizesInImageScale(tile);
+ let l = 0,
+ r = 0,
+ c = 0,
+ px = 0,
+ py = 0;
+ this.nextPacket = function JpxImage_nextPacket() {
+ for (; c < componentsCount; ++c) {
+ const component = tile.components[c];
+ const precinctsIterationSizes = precinctsSizes.components[c];
+ const decompositionLevelsCount = component.codingStyleParameters.decompositionLevelsCount;
+ for (; py < precinctsIterationSizes.maxNumHigh; py++) {
+ for (; px < precinctsIterationSizes.maxNumWide; px++) {
+ for (; r <= decompositionLevelsCount; r++) {
+ const resolution = component.resolutions[r];
+ const sizeInImageScale = precinctsIterationSizes.resolutions[r];
+ const k = getPrecinctIndexIfExist(px, py, sizeInImageScale, precinctsIterationSizes, resolution);
+ if (k === null) {
+ continue;
+ }
+ for (; l < layersCount;) {
+ const packet = createPacket(resolution, k, l);
+ l++;
+ return packet;
+ }
+ l = 0;
+ }
+ r = 0;
+ }
+ px = 0;
+ }
+ py = 0;
+ }
+ throw new JpxError("Out of packets");
+ };
+}
+function getPrecinctIndexIfExist(pxIndex, pyIndex, sizeInImageScale, precinctIterationSizes, resolution) {
+ const posX = pxIndex * precinctIterationSizes.minWidth;
+ const posY = pyIndex * precinctIterationSizes.minHeight;
+ if (posX % sizeInImageScale.width !== 0 || posY % sizeInImageScale.height !== 0) {
+ return null;
+ }
+ const startPrecinctRowIndex = posY / sizeInImageScale.width * resolution.precinctParameters.numprecinctswide;
+ return posX / sizeInImageScale.height + startPrecinctRowIndex;
+}
+function getPrecinctSizesInImageScale(tile) {
+ const componentsCount = tile.components.length;
+ let minWidth = Number.MAX_VALUE;
+ let minHeight = Number.MAX_VALUE;
+ let maxNumWide = 0;
+ let maxNumHigh = 0;
+ const sizePerComponent = new Array(componentsCount);
+ for (let c = 0; c < componentsCount; c++) {
+ const component = tile.components[c];
+ const decompositionLevelsCount = component.codingStyleParameters.decompositionLevelsCount;
+ const sizePerResolution = new Array(decompositionLevelsCount + 1);
+ let minWidthCurrentComponent = Number.MAX_VALUE;
+ let minHeightCurrentComponent = Number.MAX_VALUE;
+ let maxNumWideCurrentComponent = 0;
+ let maxNumHighCurrentComponent = 0;
+ let scale = 1;
+ for (let r = decompositionLevelsCount; r >= 0; --r) {
+ const resolution = component.resolutions[r];
+ const widthCurrentResolution = scale * resolution.precinctParameters.precinctWidth;
+ const heightCurrentResolution = scale * resolution.precinctParameters.precinctHeight;
+ minWidthCurrentComponent = Math.min(minWidthCurrentComponent, widthCurrentResolution);
+ minHeightCurrentComponent = Math.min(minHeightCurrentComponent, heightCurrentResolution);
+ maxNumWideCurrentComponent = Math.max(maxNumWideCurrentComponent, resolution.precinctParameters.numprecinctswide);
+ maxNumHighCurrentComponent = Math.max(maxNumHighCurrentComponent, resolution.precinctParameters.numprecinctshigh);
+ sizePerResolution[r] = {
+ width: widthCurrentResolution,
+ height: heightCurrentResolution
+ };
+ scale <<= 1;
+ }
+ minWidth = Math.min(minWidth, minWidthCurrentComponent);
+ minHeight = Math.min(minHeight, minHeightCurrentComponent);
+ maxNumWide = Math.max(maxNumWide, maxNumWideCurrentComponent);
+ maxNumHigh = Math.max(maxNumHigh, maxNumHighCurrentComponent);
+ sizePerComponent[c] = {
+ resolutions: sizePerResolution,
+ minWidth: minWidthCurrentComponent,
+ minHeight: minHeightCurrentComponent,
+ maxNumWide: maxNumWideCurrentComponent,
+ maxNumHigh: maxNumHighCurrentComponent
+ };
+ }
+ return {
+ components: sizePerComponent,
+ minWidth,
+ minHeight,
+ maxNumWide,
+ maxNumHigh
+ };
+}
+function buildPackets(context) {
+ const siz = context.SIZ;
+ const tileIndex = context.currentTile.index;
+ const tile = context.tiles[tileIndex];
+ const componentsCount = siz.Csiz;
+ for (let c = 0; c < componentsCount; c++) {
+ const component = tile.components[c];
+ const decompositionLevelsCount = component.codingStyleParameters.decompositionLevelsCount;
+ const resolutions = [];
+ const subbands = [];
+ for (let r = 0; r <= decompositionLevelsCount; r++) {
+ const blocksDimensions = getBlocksDimensions(context, component, r);
+ const resolution = {};
+ const scale = 1 << decompositionLevelsCount - r;
+ resolution.trx0 = Math.ceil(component.tcx0 / scale);
+ resolution.try0 = Math.ceil(component.tcy0 / scale);
+ resolution.trx1 = Math.ceil(component.tcx1 / scale);
+ resolution.try1 = Math.ceil(component.tcy1 / scale);
+ resolution.resLevel = r;
+ buildPrecincts(context, resolution, blocksDimensions);
+ resolutions.push(resolution);
+ let subband;
+ if (r === 0) {
+ subband = {};
+ subband.type = "LL";
+ subband.tbx0 = Math.ceil(component.tcx0 / scale);
+ subband.tby0 = Math.ceil(component.tcy0 / scale);
+ subband.tbx1 = Math.ceil(component.tcx1 / scale);
+ subband.tby1 = Math.ceil(component.tcy1 / scale);
+ subband.resolution = resolution;
+ buildCodeblocks(context, subband, blocksDimensions);
+ subbands.push(subband);
+ resolution.subbands = [subband];
+ } else {
+ const bscale = 1 << decompositionLevelsCount - r + 1;
+ const resolutionSubbands = [];
+ subband = {};
+ subband.type = "HL";
+ subband.tbx0 = Math.ceil(component.tcx0 / bscale - 0.5);
+ subband.tby0 = Math.ceil(component.tcy0 / bscale);
+ subband.tbx1 = Math.ceil(component.tcx1 / bscale - 0.5);
+ subband.tby1 = Math.ceil(component.tcy1 / bscale);
+ subband.resolution = resolution;
+ buildCodeblocks(context, subband, blocksDimensions);
+ subbands.push(subband);
+ resolutionSubbands.push(subband);
+ subband = {};
+ subband.type = "LH";
+ subband.tbx0 = Math.ceil(component.tcx0 / bscale);
+ subband.tby0 = Math.ceil(component.tcy0 / bscale - 0.5);
+ subband.tbx1 = Math.ceil(component.tcx1 / bscale);
+ subband.tby1 = Math.ceil(component.tcy1 / bscale - 0.5);
+ subband.resolution = resolution;
+ buildCodeblocks(context, subband, blocksDimensions);
+ subbands.push(subband);
+ resolutionSubbands.push(subband);
+ subband = {};
+ subband.type = "HH";
+ subband.tbx0 = Math.ceil(component.tcx0 / bscale - 0.5);
+ subband.tby0 = Math.ceil(component.tcy0 / bscale - 0.5);
+ subband.tbx1 = Math.ceil(component.tcx1 / bscale - 0.5);
+ subband.tby1 = Math.ceil(component.tcy1 / bscale - 0.5);
+ subband.resolution = resolution;
+ buildCodeblocks(context, subband, blocksDimensions);
+ subbands.push(subband);
+ resolutionSubbands.push(subband);
+ resolution.subbands = resolutionSubbands;
+ }
+ }
+ component.resolutions = resolutions;
+ component.subbands = subbands;
+ }
+ const progressionOrder = tile.codingStyleDefaultParameters.progressionOrder;
+ switch (progressionOrder) {
+ case 0:
+ tile.packetsIterator = new LayerResolutionComponentPositionIterator(context);
+ break;
+ case 1:
+ tile.packetsIterator = new ResolutionLayerComponentPositionIterator(context);
+ break;
+ case 2:
+ tile.packetsIterator = new ResolutionPositionComponentLayerIterator(context);
+ break;
+ case 3:
+ tile.packetsIterator = new PositionComponentResolutionLayerIterator(context);
+ break;
+ case 4:
+ tile.packetsIterator = new ComponentPositionResolutionLayerIterator(context);
+ break;
+ default:
+ throw new JpxError(`Unsupported progression order ${progressionOrder}`);
+ }
+}
+function parseTilePackets(context, data, offset, dataLength) {
+ let position = 0;
+ let buffer,
+ bufferSize = 0,
+ skipNextBit = false;
+ function readBits(count) {
+ while (bufferSize < count) {
+ const b = data[offset + position];
+ position++;
+ if (skipNextBit) {
+ buffer = buffer << 7 | b;
+ bufferSize += 7;
+ skipNextBit = false;
+ } else {
+ buffer = buffer << 8 | b;
+ bufferSize += 8;
+ }
+ if (b === 0xff) {
+ skipNextBit = true;
+ }
+ }
+ bufferSize -= count;
+ return buffer >>> bufferSize & (1 << count) - 1;
+ }
+ function skipMarkerIfEqual(value) {
+ if (data[offset + position - 1] === 0xff && data[offset + position] === value) {
+ skipBytes(1);
+ return true;
+ } else if (data[offset + position] === 0xff && data[offset + position + 1] === value) {
+ skipBytes(2);
+ return true;
+ }
+ return false;
+ }
+ function skipBytes(count) {
+ position += count;
+ }
+ function alignToByte() {
+ bufferSize = 0;
+ if (skipNextBit) {
+ position++;
+ skipNextBit = false;
+ }
+ }
+ function readCodingpasses() {
+ if (readBits(1) === 0) {
+ return 1;
+ }
+ if (readBits(1) === 0) {
+ return 2;
+ }
+ let value = readBits(2);
+ if (value < 3) {
+ return value + 3;
+ }
+ value = readBits(5);
+ if (value < 31) {
+ return value + 6;
+ }
+ value = readBits(7);
+ return value + 37;
+ }
+ const tileIndex = context.currentTile.index;
+ const tile = context.tiles[tileIndex];
+ const sopMarkerUsed = context.COD.sopMarkerUsed;
+ const ephMarkerUsed = context.COD.ephMarkerUsed;
+ const packetsIterator = tile.packetsIterator;
+ while (position < dataLength) {
+ alignToByte();
+ if (sopMarkerUsed && skipMarkerIfEqual(0x91)) {
+ skipBytes(4);
+ }
+ const packet = packetsIterator.nextPacket();
+ if (!readBits(1)) {
+ continue;
+ }
+ const layerNumber = packet.layerNumber,
+ queue = [];
+ let codeblock;
+ for (let i = 0, ii = packet.codeblocks.length; i < ii; i++) {
+ codeblock = packet.codeblocks[i];
+ let precinct = codeblock.precinct;
+ const codeblockColumn = codeblock.cbx - precinct.cbxMin;
+ const codeblockRow = codeblock.cby - precinct.cbyMin;
+ let codeblockIncluded = false;
+ let firstTimeInclusion = false;
+ let valueReady, zeroBitPlanesTree;
+ if (codeblock.included !== undefined) {
+ codeblockIncluded = !!readBits(1);
+ } else {
+ precinct = codeblock.precinct;
+ let inclusionTree;
+ if (precinct.inclusionTree !== undefined) {
+ inclusionTree = precinct.inclusionTree;
+ } else {
+ const width = precinct.cbxMax - precinct.cbxMin + 1;
+ const height = precinct.cbyMax - precinct.cbyMin + 1;
+ inclusionTree = new InclusionTree(width, height, layerNumber);
+ zeroBitPlanesTree = new TagTree(width, height);
+ precinct.inclusionTree = inclusionTree;
+ precinct.zeroBitPlanesTree = zeroBitPlanesTree;
+ for (let l = 0; l < layerNumber; l++) {
+ if (readBits(1) !== 0) {
+ throw new JpxError("Invalid tag tree");
+ }
+ }
+ }
+ if (inclusionTree.reset(codeblockColumn, codeblockRow, layerNumber)) {
+ while (true) {
+ if (readBits(1)) {
+ valueReady = !inclusionTree.nextLevel();
+ if (valueReady) {
+ codeblock.included = true;
+ codeblockIncluded = firstTimeInclusion = true;
+ break;
+ }
+ } else {
+ inclusionTree.incrementValue(layerNumber);
+ break;
+ }
+ }
+ }
+ }
+ if (!codeblockIncluded) {
+ continue;
+ }
+ if (firstTimeInclusion) {
+ zeroBitPlanesTree = precinct.zeroBitPlanesTree;
+ zeroBitPlanesTree.reset(codeblockColumn, codeblockRow);
+ while (true) {
+ if (readBits(1)) {
+ valueReady = !zeroBitPlanesTree.nextLevel();
+ if (valueReady) {
+ break;
+ }
+ } else {
+ zeroBitPlanesTree.incrementValue();
+ }
+ }
+ codeblock.zeroBitPlanes = zeroBitPlanesTree.value;
+ }
+ const codingpasses = readCodingpasses();
+ while (readBits(1)) {
+ codeblock.Lblock++;
+ }
+ const codingpassesLog2 = log2(codingpasses);
+ const bits = (codingpasses < 1 << codingpassesLog2 ? codingpassesLog2 - 1 : codingpassesLog2) + codeblock.Lblock;
+ const codedDataLength = readBits(bits);
+ queue.push({
+ codeblock,
+ codingpasses,
+ dataLength: codedDataLength
+ });
+ }
+ alignToByte();
+ if (ephMarkerUsed) {
+ skipMarkerIfEqual(0x92);
+ }
+ while (queue.length > 0) {
+ const packetItem = queue.shift();
+ codeblock = packetItem.codeblock;
+ if (codeblock.data === undefined) {
+ codeblock.data = [];
+ }
+ codeblock.data.push({
+ data,
+ start: offset + position,
+ end: offset + position + packetItem.dataLength,
+ codingpasses: packetItem.codingpasses
+ });
+ position += packetItem.dataLength;
+ }
+ }
+ return position;
+}
+function copyCoefficients(coefficients, levelWidth, levelHeight, subband, delta, mb, reversible, segmentationSymbolUsed, resetContextProbabilities) {
+ const x0 = subband.tbx0;
+ const y0 = subband.tby0;
+ const width = subband.tbx1 - subband.tbx0;
+ const codeblocks = subband.codeblocks;
+ const right = subband.type.charAt(0) === "H" ? 1 : 0;
+ const bottom = subband.type.charAt(1) === "H" ? levelWidth : 0;
+ for (let i = 0, ii = codeblocks.length; i < ii; ++i) {
+ const codeblock = codeblocks[i];
+ const blockWidth = codeblock.tbx1_ - codeblock.tbx0_;
+ const blockHeight = codeblock.tby1_ - codeblock.tby0_;
+ if (blockWidth === 0 || blockHeight === 0) {
+ continue;
+ }
+ if (codeblock.data === undefined) {
+ continue;
+ }
+ const bitModel = new BitModel(blockWidth, blockHeight, codeblock.subbandType, codeblock.zeroBitPlanes, mb);
+ let currentCodingpassType = 2;
+ const data = codeblock.data;
+ let totalLength = 0,
+ codingpasses = 0;
+ let j, jj, dataItem;
+ for (j = 0, jj = data.length; j < jj; j++) {
+ dataItem = data[j];
+ totalLength += dataItem.end - dataItem.start;
+ codingpasses += dataItem.codingpasses;
+ }
+ const encodedData = new Uint8Array(totalLength);
+ let position = 0;
+ for (j = 0, jj = data.length; j < jj; j++) {
+ dataItem = data[j];
+ const chunk = dataItem.data.subarray(dataItem.start, dataItem.end);
+ encodedData.set(chunk, position);
+ position += chunk.length;
+ }
+ const decoder = new ArithmeticDecoder(encodedData, 0, totalLength);
+ bitModel.setDecoder(decoder);
+ for (j = 0; j < codingpasses; j++) {
+ switch (currentCodingpassType) {
+ case 0:
+ bitModel.runSignificancePropagationPass();
+ break;
+ case 1:
+ bitModel.runMagnitudeRefinementPass();
+ break;
+ case 2:
+ bitModel.runCleanupPass();
+ if (segmentationSymbolUsed) {
+ bitModel.checkSegmentationSymbol();
+ }
+ break;
+ }
+ if (resetContextProbabilities) {
+ bitModel.reset();
+ }
+ currentCodingpassType = (currentCodingpassType + 1) % 3;
+ }
+ let offset = codeblock.tbx0_ - x0 + (codeblock.tby0_ - y0) * width;
+ const sign = bitModel.coefficentsSign;
+ const magnitude = bitModel.coefficentsMagnitude;
+ const bitsDecoded = bitModel.bitsDecoded;
+ const magnitudeCorrection = reversible ? 0 : 0.5;
+ let k, n, nb;
+ position = 0;
+ const interleave = subband.type !== "LL";
+ for (j = 0; j < blockHeight; j++) {
+ const row = offset / width | 0;
+ const levelOffset = 2 * row * (levelWidth - width) + right + bottom;
+ for (k = 0; k < blockWidth; k++) {
+ n = magnitude[position];
+ if (n !== 0) {
+ n = (n + magnitudeCorrection) * delta;
+ if (sign[position] !== 0) {
+ n = -n;
+ }
+ nb = bitsDecoded[position];
+ const pos = interleave ? levelOffset + (offset << 1) : offset;
+ coefficients[pos] = reversible && nb >= mb ? n : n * (1 << mb - nb);
+ }
+ offset++;
+ position++;
+ }
+ offset += width - blockWidth;
+ }
+ }
+}
+function transformTile(context, tile, c) {
+ const component = tile.components[c];
+ const codingStyleParameters = component.codingStyleParameters;
+ const quantizationParameters = component.quantizationParameters;
+ const decompositionLevelsCount = codingStyleParameters.decompositionLevelsCount;
+ const spqcds = quantizationParameters.SPqcds;
+ const scalarExpounded = quantizationParameters.scalarExpounded;
+ const guardBits = quantizationParameters.guardBits;
+ const segmentationSymbolUsed = codingStyleParameters.segmentationSymbolUsed;
+ const resetContextProbabilities = codingStyleParameters.resetContextProbabilities;
+ const precision = context.components[c].precision;
+ const reversible = codingStyleParameters.reversibleTransformation;
+ const transform = reversible ? new ReversibleTransform() : new IrreversibleTransform();
+ const subbandCoefficients = [];
+ let b = 0;
+ for (let i = 0; i <= decompositionLevelsCount; i++) {
+ const resolution = component.resolutions[i];
+ const width = resolution.trx1 - resolution.trx0;
+ const height = resolution.try1 - resolution.try0;
+ const coefficients = new Float32Array(width * height);
+ for (let j = 0, jj = resolution.subbands.length; j < jj; j++) {
+ let mu, epsilon;
+ if (!scalarExpounded) {
+ mu = spqcds[0].mu;
+ epsilon = spqcds[0].epsilon + (i > 0 ? 1 - i : 0);
+ } else {
+ mu = spqcds[b].mu;
+ epsilon = spqcds[b].epsilon;
+ b++;
+ }
+ const subband = resolution.subbands[j];
+ const gainLog2 = SubbandsGainLog2[subband.type];
+ const delta = reversible ? 1 : 2 ** (precision + gainLog2 - epsilon) * (1 + mu / 2048);
+ const mb = guardBits + epsilon - 1;
+ copyCoefficients(coefficients, width, height, subband, delta, mb, reversible, segmentationSymbolUsed, resetContextProbabilities);
+ }
+ subbandCoefficients.push({
+ width,
+ height,
+ items: coefficients
+ });
+ }
+ const result = transform.calculate(subbandCoefficients, component.tcx0, component.tcy0);
+ return {
+ left: component.tcx0,
+ top: component.tcy0,
+ width: result.width,
+ height: result.height,
+ items: result.items
+ };
+}
+function transformComponents(context) {
+ const siz = context.SIZ;
+ const components = context.components;
+ const componentsCount = siz.Csiz;
+ const resultImages = [];
+ for (let i = 0, ii = context.tiles.length; i < ii; i++) {
+ const tile = context.tiles[i];
+ const transformedTiles = [];
+ for (let c = 0; c < componentsCount; c++) {
+ transformedTiles[c] = transformTile(context, tile, c);
+ }
+ const tile0 = transformedTiles[0];
+ const out = new Uint8ClampedArray(tile0.items.length * componentsCount);
+ const result = {
+ left: tile0.left,
+ top: tile0.top,
+ width: tile0.width,
+ height: tile0.height,
+ items: out
+ };
+ let shift, offset;
+ let pos = 0,
+ j,
+ jj,
+ y0,
+ y1,
+ y2;
+ if (tile.codingStyleDefaultParameters.multipleComponentTransform) {
+ const fourComponents = componentsCount === 4;
+ const y0items = transformedTiles[0].items;
+ const y1items = transformedTiles[1].items;
+ const y2items = transformedTiles[2].items;
+ const y3items = fourComponents ? transformedTiles[3].items : null;
+ shift = components[0].precision - 8;
+ offset = (128 << shift) + 0.5;
+ const component0 = tile.components[0];
+ const alpha01 = componentsCount - 3;
+ jj = y0items.length;
+ if (!component0.codingStyleParameters.reversibleTransformation) {
+ for (j = 0; j < jj; j++, pos += alpha01) {
+ y0 = y0items[j] + offset;
+ y1 = y1items[j];
+ y2 = y2items[j];
+ out[pos++] = y0 + 1.402 * y2 >> shift;
+ out[pos++] = y0 - 0.34413 * y1 - 0.71414 * y2 >> shift;
+ out[pos++] = y0 + 1.772 * y1 >> shift;
+ }
+ } else {
+ for (j = 0; j < jj; j++, pos += alpha01) {
+ y0 = y0items[j] + offset;
+ y1 = y1items[j];
+ y2 = y2items[j];
+ const g = y0 - (y2 + y1 >> 2);
+ out[pos++] = g + y2 >> shift;
+ out[pos++] = g >> shift;
+ out[pos++] = g + y1 >> shift;
+ }
+ }
+ if (fourComponents) {
+ for (j = 0, pos = 3; j < jj; j++, pos += 4) {
+ out[pos] = y3items[j] + offset >> shift;
+ }
+ }
+ } else {
+ for (let c = 0; c < componentsCount; c++) {
+ const items = transformedTiles[c].items;
+ shift = components[c].precision - 8;
+ offset = (128 << shift) + 0.5;
+ for (pos = c, j = 0, jj = items.length; j < jj; j++) {
+ out[pos] = items[j] + offset >> shift;
+ pos += componentsCount;
+ }
+ }
+ }
+ resultImages.push(result);
+ }
+ return resultImages;
+}
+function initializeTile(context, tileIndex) {
+ const siz = context.SIZ;
+ const componentsCount = siz.Csiz;
+ const tile = context.tiles[tileIndex];
+ for (let c = 0; c < componentsCount; c++) {
+ const component = tile.components[c];
+ const qcdOrQcc = context.currentTile.QCC[c] !== undefined ? context.currentTile.QCC[c] : context.currentTile.QCD;
+ component.quantizationParameters = qcdOrQcc;
+ const codOrCoc = context.currentTile.COC[c] !== undefined ? context.currentTile.COC[c] : context.currentTile.COD;
+ component.codingStyleParameters = codOrCoc;
+ }
+ tile.codingStyleDefaultParameters = context.currentTile.COD;
+}
+class TagTree {
+ constructor(width, height) {
+ const levelsLength = log2(Math.max(width, height)) + 1;
+ this.levels = [];
+ for (let i = 0; i < levelsLength; i++) {
+ const level = {
+ width,
+ height,
+ items: []
+ };
+ this.levels.push(level);
+ width = Math.ceil(width / 2);
+ height = Math.ceil(height / 2);
+ }
+ }
+ reset(i, j) {
+ let currentLevel = 0,
+ value = 0,
+ level;
+ while (currentLevel < this.levels.length) {
+ level = this.levels[currentLevel];
+ const index = i + j * level.width;
+ if (level.items[index] !== undefined) {
+ value = level.items[index];
+ break;
+ }
+ level.index = index;
+ i >>= 1;
+ j >>= 1;
+ currentLevel++;
+ }
+ currentLevel--;
+ level = this.levels[currentLevel];
+ level.items[level.index] = value;
+ this.currentLevel = currentLevel;
+ delete this.value;
+ }
+ incrementValue() {
+ const level = this.levels[this.currentLevel];
+ level.items[level.index]++;
+ }
+ nextLevel() {
+ let currentLevel = this.currentLevel;
+ let level = this.levels[currentLevel];
+ const value = level.items[level.index];
+ currentLevel--;
+ if (currentLevel < 0) {
+ this.value = value;
+ return false;
+ }
+ this.currentLevel = currentLevel;
+ level = this.levels[currentLevel];
+ level.items[level.index] = value;
+ return true;
+ }
+}
+class InclusionTree {
+ constructor(width, height, defaultValue) {
+ const levelsLength = log2(Math.max(width, height)) + 1;
+ this.levels = [];
+ for (let i = 0; i < levelsLength; i++) {
+ const items = new Uint8Array(width * height);
+ for (let j = 0, jj = items.length; j < jj; j++) {
+ items[j] = defaultValue;
+ }
+ const level = {
+ width,
+ height,
+ items
+ };
+ this.levels.push(level);
+ width = Math.ceil(width / 2);
+ height = Math.ceil(height / 2);
+ }
+ }
+ reset(i, j, stopValue) {
+ let currentLevel = 0;
+ while (currentLevel < this.levels.length) {
+ const level = this.levels[currentLevel];
+ const index = i + j * level.width;
+ level.index = index;
+ const value = level.items[index];
+ if (value === 0xff) {
+ break;
+ }
+ if (value > stopValue) {
+ this.currentLevel = currentLevel;
+ this.propagateValues();
+ return false;
+ }
+ i >>= 1;
+ j >>= 1;
+ currentLevel++;
+ }
+ this.currentLevel = currentLevel - 1;
+ return true;
+ }
+ incrementValue(stopValue) {
+ const level = this.levels[this.currentLevel];
+ level.items[level.index] = stopValue + 1;
+ this.propagateValues();
+ }
+ propagateValues() {
+ let levelIndex = this.currentLevel;
+ let level = this.levels[levelIndex];
+ const currentValue = level.items[level.index];
+ while (--levelIndex >= 0) {
+ level = this.levels[levelIndex];
+ level.items[level.index] = currentValue;
+ }
+ }
+ nextLevel() {
+ let currentLevel = this.currentLevel;
+ let level = this.levels[currentLevel];
+ const value = level.items[level.index];
+ level.items[level.index] = 0xff;
+ currentLevel--;
+ if (currentLevel < 0) {
+ return false;
+ }
+ this.currentLevel = currentLevel;
+ level = this.levels[currentLevel];
+ level.items[level.index] = value;
+ return true;
+ }
+}
+class BitModel {
+ static UNIFORM_CONTEXT = 17;
+ static RUNLENGTH_CONTEXT = 18;
+ static LLAndLHContextsLabel = new Uint8Array([0, 5, 8, 0, 3, 7, 8, 0, 4, 7, 8, 0, 0, 0, 0, 0, 1, 6, 8, 0, 3, 7, 8, 0, 4, 7, 8, 0, 0, 0, 0, 0, 2, 6, 8, 0, 3, 7, 8, 0, 4, 7, 8, 0, 0, 0, 0, 0, 2, 6, 8, 0, 3, 7, 8, 0, 4, 7, 8, 0, 0, 0, 0, 0, 2, 6, 8, 0, 3, 7, 8, 0, 4, 7, 8]);
+ static HLContextLabel = new Uint8Array([0, 3, 4, 0, 5, 7, 7, 0, 8, 8, 8, 0, 0, 0, 0, 0, 1, 3, 4, 0, 6, 7, 7, 0, 8, 8, 8, 0, 0, 0, 0, 0, 2, 3, 4, 0, 6, 7, 7, 0, 8, 8, 8, 0, 0, 0, 0, 0, 2, 3, 4, 0, 6, 7, 7, 0, 8, 8, 8, 0, 0, 0, 0, 0, 2, 3, 4, 0, 6, 7, 7, 0, 8, 8, 8]);
+ static HHContextLabel = new Uint8Array([0, 1, 2, 0, 1, 2, 2, 0, 2, 2, 2, 0, 0, 0, 0, 0, 3, 4, 5, 0, 4, 5, 5, 0, 5, 5, 5, 0, 0, 0, 0, 0, 6, 7, 7, 0, 7, 7, 7, 0, 7, 7, 7, 0, 0, 0, 0, 0, 8, 8, 8, 0, 8, 8, 8, 0, 8, 8, 8, 0, 0, 0, 0, 0, 8, 8, 8, 0, 8, 8, 8, 0, 8, 8, 8]);
+ constructor(width, height, subband, zeroBitPlanes, mb) {
+ this.width = width;
+ this.height = height;
+ let contextLabelTable;
+ if (subband === "HH") {
+ contextLabelTable = BitModel.HHContextLabel;
+ } else if (subband === "HL") {
+ contextLabelTable = BitModel.HLContextLabel;
+ } else {
+ contextLabelTable = BitModel.LLAndLHContextsLabel;
+ }
+ this.contextLabelTable = contextLabelTable;
+ const coefficientCount = width * height;
+ this.neighborsSignificance = new Uint8Array(coefficientCount);
+ this.coefficentsSign = new Uint8Array(coefficientCount);
+ let coefficentsMagnitude;
+ if (mb > 14) {
+ coefficentsMagnitude = new Uint32Array(coefficientCount);
+ } else if (mb > 6) {
+ coefficentsMagnitude = new Uint16Array(coefficientCount);
+ } else {
+ coefficentsMagnitude = new Uint8Array(coefficientCount);
+ }
+ this.coefficentsMagnitude = coefficentsMagnitude;
+ this.processingFlags = new Uint8Array(coefficientCount);
+ const bitsDecoded = new Uint8Array(coefficientCount);
+ if (zeroBitPlanes !== 0) {
+ for (let i = 0; i < coefficientCount; i++) {
+ bitsDecoded[i] = zeroBitPlanes;
+ }
+ }
+ this.bitsDecoded = bitsDecoded;
+ this.reset();
+ }
+ setDecoder(decoder) {
+ this.decoder = decoder;
+ }
+ reset() {
+ this.contexts = new Int8Array(19);
+ this.contexts[0] = 4 << 1 | 0;
+ this.contexts[BitModel.UNIFORM_CONTEXT] = 46 << 1 | 0;
+ this.contexts[BitModel.RUNLENGTH_CONTEXT] = 3 << 1 | 0;
+ }
+ setNeighborsSignificance(row, column, index) {
+ const neighborsSignificance = this.neighborsSignificance;
+ const width = this.width,
+ height = this.height;
+ const left = column > 0;
+ const right = column + 1 < width;
+ let i;
+ if (row > 0) {
+ i = index - width;
+ if (left) {
+ neighborsSignificance[i - 1] += 0x10;
+ }
+ if (right) {
+ neighborsSignificance[i + 1] += 0x10;
+ }
+ neighborsSignificance[i] += 0x04;
+ }
+ if (row + 1 < height) {
+ i = index + width;
+ if (left) {
+ neighborsSignificance[i - 1] += 0x10;
+ }
+ if (right) {
+ neighborsSignificance[i + 1] += 0x10;
+ }
+ neighborsSignificance[i] += 0x04;
+ }
+ if (left) {
+ neighborsSignificance[index - 1] += 0x01;
+ }
+ if (right) {
+ neighborsSignificance[index + 1] += 0x01;
+ }
+ neighborsSignificance[index] |= 0x80;
+ }
+ runSignificancePropagationPass() {
+ const decoder = this.decoder;
+ const width = this.width,
+ height = this.height;
+ const coefficentsMagnitude = this.coefficentsMagnitude;
+ const coefficentsSign = this.coefficentsSign;
+ const neighborsSignificance = this.neighborsSignificance;
+ const processingFlags = this.processingFlags;
+ const contexts = this.contexts;
+ const labels = this.contextLabelTable;
+ const bitsDecoded = this.bitsDecoded;
+ const processedInverseMask = ~1;
+ const processedMask = 1;
+ const firstMagnitudeBitMask = 2;
+ for (let i0 = 0; i0 < height; i0 += 4) {
+ for (let j = 0; j < width; j++) {
+ let index = i0 * width + j;
+ for (let i1 = 0; i1 < 4; i1++, index += width) {
+ const i = i0 + i1;
+ if (i >= height) {
+ break;
+ }
+ processingFlags[index] &= processedInverseMask;
+ if (coefficentsMagnitude[index] || !neighborsSignificance[index]) {
+ continue;
+ }
+ const contextLabel = labels[neighborsSignificance[index]];
+ const decision = decoder.readBit(contexts, contextLabel);
+ if (decision) {
+ const sign = this.decodeSignBit(i, j, index);
+ coefficentsSign[index] = sign;
+ coefficentsMagnitude[index] = 1;
+ this.setNeighborsSignificance(i, j, index);
+ processingFlags[index] |= firstMagnitudeBitMask;
+ }
+ bitsDecoded[index]++;
+ processingFlags[index] |= processedMask;
+ }
+ }
+ }
+ }
+ decodeSignBit(row, column, index) {
+ const width = this.width,
+ height = this.height;
+ const coefficentsMagnitude = this.coefficentsMagnitude;
+ const coefficentsSign = this.coefficentsSign;
+ let contribution, sign0, sign1, significance1;
+ let contextLabel, decoded;
+ significance1 = column > 0 && coefficentsMagnitude[index - 1] !== 0;
+ if (column + 1 < width && coefficentsMagnitude[index + 1] !== 0) {
+ sign1 = coefficentsSign[index + 1];
+ if (significance1) {
+ sign0 = coefficentsSign[index - 1];
+ contribution = 1 - sign1 - sign0;
+ } else {
+ contribution = 1 - sign1 - sign1;
+ }
+ } else if (significance1) {
+ sign0 = coefficentsSign[index - 1];
+ contribution = 1 - sign0 - sign0;
+ } else {
+ contribution = 0;
+ }
+ const horizontalContribution = 3 * contribution;
+ significance1 = row > 0 && coefficentsMagnitude[index - width] !== 0;
+ if (row + 1 < height && coefficentsMagnitude[index + width] !== 0) {
+ sign1 = coefficentsSign[index + width];
+ if (significance1) {
+ sign0 = coefficentsSign[index - width];
+ contribution = 1 - sign1 - sign0 + horizontalContribution;
+ } else {
+ contribution = 1 - sign1 - sign1 + horizontalContribution;
+ }
+ } else if (significance1) {
+ sign0 = coefficentsSign[index - width];
+ contribution = 1 - sign0 - sign0 + horizontalContribution;
+ } else {
+ contribution = horizontalContribution;
+ }
+ if (contribution >= 0) {
+ contextLabel = 9 + contribution;
+ decoded = this.decoder.readBit(this.contexts, contextLabel);
+ } else {
+ contextLabel = 9 - contribution;
+ decoded = this.decoder.readBit(this.contexts, contextLabel) ^ 1;
+ }
+ return decoded;
+ }
+ runMagnitudeRefinementPass() {
+ const decoder = this.decoder;
+ const width = this.width,
+ height = this.height;
+ const coefficentsMagnitude = this.coefficentsMagnitude;
+ const neighborsSignificance = this.neighborsSignificance;
+ const contexts = this.contexts;
+ const bitsDecoded = this.bitsDecoded;
+ const processingFlags = this.processingFlags;
+ const processedMask = 1;
+ const firstMagnitudeBitMask = 2;
+ const length = width * height;
+ const width4 = width * 4;
+ for (let index0 = 0, indexNext; index0 < length; index0 = indexNext) {
+ indexNext = Math.min(length, index0 + width4);
+ for (let j = 0; j < width; j++) {
+ for (let index = index0 + j; index < indexNext; index += width) {
+ if (!coefficentsMagnitude[index] || (processingFlags[index] & processedMask) !== 0) {
+ continue;
+ }
+ let contextLabel = 16;
+ if ((processingFlags[index] & firstMagnitudeBitMask) !== 0) {
+ processingFlags[index] ^= firstMagnitudeBitMask;
+ const significance = neighborsSignificance[index] & 127;
+ contextLabel = significance === 0 ? 15 : 14;
+ }
+ const bit = decoder.readBit(contexts, contextLabel);
+ coefficentsMagnitude[index] = coefficentsMagnitude[index] << 1 | bit;
+ bitsDecoded[index]++;
+ processingFlags[index] |= processedMask;
+ }
+ }
+ }
+ }
+ runCleanupPass() {
+ const decoder = this.decoder;
+ const width = this.width,
+ height = this.height;
+ const neighborsSignificance = this.neighborsSignificance;
+ const coefficentsMagnitude = this.coefficentsMagnitude;
+ const coefficentsSign = this.coefficentsSign;
+ const contexts = this.contexts;
+ const labels = this.contextLabelTable;
+ const bitsDecoded = this.bitsDecoded;
+ const processingFlags = this.processingFlags;
+ const processedMask = 1;
+ const firstMagnitudeBitMask = 2;
+ const oneRowDown = width;
+ const twoRowsDown = width * 2;
+ const threeRowsDown = width * 3;
+ let iNext;
+ for (let i0 = 0; i0 < height; i0 = iNext) {
+ iNext = Math.min(i0 + 4, height);
+ const indexBase = i0 * width;
+ const checkAllEmpty = i0 + 3 < height;
+ for (let j = 0; j < width; j++) {
+ const index0 = indexBase + j;
+ const allEmpty = checkAllEmpty && processingFlags[index0] === 0 && processingFlags[index0 + oneRowDown] === 0 && processingFlags[index0 + twoRowsDown] === 0 && processingFlags[index0 + threeRowsDown] === 0 && neighborsSignificance[index0] === 0 && neighborsSignificance[index0 + oneRowDown] === 0 && neighborsSignificance[index0 + twoRowsDown] === 0 && neighborsSignificance[index0 + threeRowsDown] === 0;
+ let i1 = 0,
+ index = index0;
+ let i = i0,
+ sign;
+ if (allEmpty) {
+ const hasSignificantCoefficent = decoder.readBit(contexts, BitModel.RUNLENGTH_CONTEXT);
+ if (!hasSignificantCoefficent) {
+ bitsDecoded[index0]++;
+ bitsDecoded[index0 + oneRowDown]++;
+ bitsDecoded[index0 + twoRowsDown]++;
+ bitsDecoded[index0 + threeRowsDown]++;
+ continue;
+ }
+ i1 = decoder.readBit(contexts, BitModel.UNIFORM_CONTEXT) << 1 | decoder.readBit(contexts, BitModel.UNIFORM_CONTEXT);
+ if (i1 !== 0) {
+ i = i0 + i1;
+ index += i1 * width;
+ }
+ sign = this.decodeSignBit(i, j, index);
+ coefficentsSign[index] = sign;
+ coefficentsMagnitude[index] = 1;
+ this.setNeighborsSignificance(i, j, index);
+ processingFlags[index] |= firstMagnitudeBitMask;
+ index = index0;
+ for (let i2 = i0; i2 <= i; i2++, index += width) {
+ bitsDecoded[index]++;
+ }
+ i1++;
+ }
+ for (i = i0 + i1; i < iNext; i++, index += width) {
+ if (coefficentsMagnitude[index] || (processingFlags[index] & processedMask) !== 0) {
+ continue;
+ }
+ const contextLabel = labels[neighborsSignificance[index]];
+ const decision = decoder.readBit(contexts, contextLabel);
+ if (decision === 1) {
+ sign = this.decodeSignBit(i, j, index);
+ coefficentsSign[index] = sign;
+ coefficentsMagnitude[index] = 1;
+ this.setNeighborsSignificance(i, j, index);
+ processingFlags[index] |= firstMagnitudeBitMask;
+ }
+ bitsDecoded[index]++;
+ }
+ }
+ }
+ }
+ checkSegmentationSymbol() {
+ const decoder = this.decoder;
+ const contexts = this.contexts;
+ const symbol = decoder.readBit(contexts, BitModel.UNIFORM_CONTEXT) << 3 | decoder.readBit(contexts, BitModel.UNIFORM_CONTEXT) << 2 | decoder.readBit(contexts, BitModel.UNIFORM_CONTEXT) << 1 | decoder.readBit(contexts, BitModel.UNIFORM_CONTEXT);
+ if (symbol !== 0xa) {
+ throw new JpxError("Invalid segmentation symbol");
+ }
+ }
+}
+class Transform {
+ constructor() {
+ if (this.constructor === Transform) {
+ unreachable("Cannot initialize Transform.");
+ }
+ }
+ calculate(subbands, u0, v0) {
+ let ll = subbands[0];
+ for (let i = 1, ii = subbands.length; i < ii; i++) {
+ ll = this.iterate(ll, subbands[i], u0, v0);
+ }
+ return ll;
+ }
+ extend(buffer, offset, size) {
+ let i1 = offset - 1,
+ j1 = offset + 1;
+ let i2 = offset + size - 2,
+ j2 = offset + size;
+ buffer[i1--] = buffer[j1++];
+ buffer[j2++] = buffer[i2--];
+ buffer[i1--] = buffer[j1++];
+ buffer[j2++] = buffer[i2--];
+ buffer[i1--] = buffer[j1++];
+ buffer[j2++] = buffer[i2--];
+ buffer[i1] = buffer[j1];
+ buffer[j2] = buffer[i2];
+ }
+ filter(x, offset, length) {
+ unreachable("Abstract method `filter` called");
+ }
+ iterate(ll, hl_lh_hh, u0, v0) {
+ const llWidth = ll.width,
+ llHeight = ll.height;
+ let llItems = ll.items;
+ const width = hl_lh_hh.width;
+ const height = hl_lh_hh.height;
+ const items = hl_lh_hh.items;
+ let i, j, k, l, u, v;
+ for (k = 0, i = 0; i < llHeight; i++) {
+ l = i * 2 * width;
+ for (j = 0; j < llWidth; j++, k++, l += 2) {
+ items[l] = llItems[k];
+ }
+ }
+ llItems = ll.items = null;
+ const bufferPadding = 4;
+ const rowBuffer = new Float32Array(width + 2 * bufferPadding);
+ if (width === 1) {
+ if ((u0 & 1) !== 0) {
+ for (v = 0, k = 0; v < height; v++, k += width) {
+ items[k] *= 0.5;
+ }
+ }
+ } else {
+ for (v = 0, k = 0; v < height; v++, k += width) {
+ rowBuffer.set(items.subarray(k, k + width), bufferPadding);
+ this.extend(rowBuffer, bufferPadding, width);
+ this.filter(rowBuffer, bufferPadding, width);
+ items.set(rowBuffer.subarray(bufferPadding, bufferPadding + width), k);
+ }
+ }
+ let numBuffers = 16;
+ const colBuffers = [];
+ for (i = 0; i < numBuffers; i++) {
+ colBuffers.push(new Float32Array(height + 2 * bufferPadding));
+ }
+ let b,
+ currentBuffer = 0;
+ ll = bufferPadding + height;
+ if (height === 1) {
+ if ((v0 & 1) !== 0) {
+ for (u = 0; u < width; u++) {
+ items[u] *= 0.5;
+ }
+ }
+ } else {
+ for (u = 0; u < width; u++) {
+ if (currentBuffer === 0) {
+ numBuffers = Math.min(width - u, numBuffers);
+ for (k = u, l = bufferPadding; l < ll; k += width, l++) {
+ for (b = 0; b < numBuffers; b++) {
+ colBuffers[b][l] = items[k + b];
+ }
+ }
+ currentBuffer = numBuffers;
+ }
+ currentBuffer--;
+ const buffer = colBuffers[currentBuffer];
+ this.extend(buffer, bufferPadding, height);
+ this.filter(buffer, bufferPadding, height);
+ if (currentBuffer === 0) {
+ k = u - numBuffers + 1;
+ for (l = bufferPadding; l < ll; k += width, l++) {
+ for (b = 0; b < numBuffers; b++) {
+ items[k + b] = colBuffers[b][l];
+ }
+ }
+ }
+ }
+ }
+ return {
+ width,
+ height,
+ items
+ };
+ }
+}
+class IrreversibleTransform extends Transform {
+ filter(x, offset, length) {
+ const len = length >> 1;
+ offset |= 0;
+ let j, n, current, next;
+ const alpha = -1.586134342059924;
+ const beta = -0.052980118572961;
+ const gamma = 0.882911075530934;
+ const delta = 0.443506852043971;
+ const K = 1.230174104914001;
+ const K_ = 1 / K;
+ j = offset - 3;
+ for (n = len + 4; n--; j += 2) {
+ x[j] *= K_;
+ }
+ j = offset - 2;
+ current = delta * x[j - 1];
+ for (n = len + 3; n--; j += 2) {
+ next = delta * x[j + 1];
+ x[j] = K * x[j] - current - next;
+ if (n--) {
+ j += 2;
+ current = delta * x[j + 1];
+ x[j] = K * x[j] - current - next;
+ } else {
+ break;
+ }
+ }
+ j = offset - 1;
+ current = gamma * x[j - 1];
+ for (n = len + 2; n--; j += 2) {
+ next = gamma * x[j + 1];
+ x[j] -= current + next;
+ if (n--) {
+ j += 2;
+ current = gamma * x[j + 1];
+ x[j] -= current + next;
+ } else {
+ break;
+ }
+ }
+ j = offset;
+ current = beta * x[j - 1];
+ for (n = len + 1; n--; j += 2) {
+ next = beta * x[j + 1];
+ x[j] -= current + next;
+ if (n--) {
+ j += 2;
+ current = beta * x[j + 1];
+ x[j] -= current + next;
+ } else {
+ break;
+ }
+ }
+ if (len !== 0) {
+ j = offset + 1;
+ current = alpha * x[j - 1];
+ for (n = len; n--; j += 2) {
+ next = alpha * x[j + 1];
+ x[j] -= current + next;
+ if (n--) {
+ j += 2;
+ current = alpha * x[j + 1];
+ x[j] -= current + next;
+ } else {
+ break;
+ }
+ }
+ }
+ }
+}
+class ReversibleTransform extends Transform {
+ filter(x, offset, length) {
+ const len = length >> 1;
+ offset |= 0;
+ let j, n;
+ for (j = offset, n = len + 1; n--; j += 2) {
+ x[j] -= x[j - 1] + x[j + 1] + 2 >> 2;
+ }
+ for (j = offset + 1, n = len; n--; j += 2) {
+ x[j] += x[j - 1] + x[j + 1] >> 1;
+ }
+ }
+}
+
+;// CONCATENATED MODULE: ./src/core/jpx_stream.js
+
+
+
+class JpxStream extends DecodeStream {
+ constructor(stream, maybeLength, params) {
+ super(maybeLength);
+ this.stream = stream;
+ this.dict = stream.dict;
+ this.maybeLength = maybeLength;
+ this.params = params;
+ }
+ get bytes() {
+ return shadow(this, "bytes", this.stream.getBytes(this.maybeLength));
+ }
+ ensureBuffer(requested) {}
+ readBlock() {
+ if (this.eof) {
+ return;
+ }
+ const jpxImage = new JpxImage();
+ jpxImage.parse(this.bytes);
+ const width = jpxImage.width;
+ const height = jpxImage.height;
+ const componentsCount = jpxImage.componentsCount;
+ const tileCount = jpxImage.tiles.length;
+ if (tileCount === 1) {
+ this.buffer = jpxImage.tiles[0].items;
+ } else {
+ const data = new Uint8ClampedArray(width * height * componentsCount);
+ for (let k = 0; k < tileCount; k++) {
+ const tileComponents = jpxImage.tiles[k];
+ const tileWidth = tileComponents.width;
+ const tileHeight = tileComponents.height;
+ const tileLeft = tileComponents.left;
+ const tileTop = tileComponents.top;
+ const src = tileComponents.items;
+ let srcPosition = 0;
+ let dataPosition = (width * tileTop + tileLeft) * componentsCount;
+ const imgRowSize = width * componentsCount;
+ const tileRowSize = tileWidth * componentsCount;
+ for (let j = 0; j < tileHeight; j++) {
+ const rowBytes = src.subarray(srcPosition, srcPosition + tileRowSize);
+ data.set(rowBytes, dataPosition);
+ srcPosition += tileRowSize;
+ dataPosition += imgRowSize;
+ }
+ }
+ this.buffer = data;
+ }
+ this.bufferLength = this.buffer.length;
+ this.eof = true;
+ }
+}
+
+;// CONCATENATED MODULE: ./src/core/lzw_stream.js
+
+class LZWStream extends DecodeStream {
+ constructor(str, maybeLength, earlyChange) {
+ super(maybeLength);
+ this.str = str;
+ this.dict = str.dict;
+ this.cachedData = 0;
+ this.bitsCached = 0;
+ const maxLzwDictionarySize = 4096;
+ const lzwState = {
+ earlyChange,
+ codeLength: 9,
+ nextCode: 258,
+ dictionaryValues: new Uint8Array(maxLzwDictionarySize),
+ dictionaryLengths: new Uint16Array(maxLzwDictionarySize),
+ dictionaryPrevCodes: new Uint16Array(maxLzwDictionarySize),
+ currentSequence: new Uint8Array(maxLzwDictionarySize),
+ currentSequenceLength: 0
+ };
+ for (let i = 0; i < 256; ++i) {
+ lzwState.dictionaryValues[i] = i;
+ lzwState.dictionaryLengths[i] = 1;
+ }
+ this.lzwState = lzwState;
+ }
+ readBits(n) {
+ let bitsCached = this.bitsCached;
+ let cachedData = this.cachedData;
+ while (bitsCached < n) {
+ const c = this.str.getByte();
+ if (c === -1) {
+ this.eof = true;
+ return null;
+ }
+ cachedData = cachedData << 8 | c;
+ bitsCached += 8;
+ }
+ this.bitsCached = bitsCached -= n;
+ this.cachedData = cachedData;
+ this.lastCode = null;
+ return cachedData >>> bitsCached & (1 << n) - 1;
+ }
+ readBlock() {
+ const blockSize = 512,
+ decodedSizeDelta = blockSize;
+ let estimatedDecodedSize = blockSize * 2;
+ let i, j, q;
+ const lzwState = this.lzwState;
+ if (!lzwState) {
+ return;
+ }
+ const earlyChange = lzwState.earlyChange;
+ let nextCode = lzwState.nextCode;
+ const dictionaryValues = lzwState.dictionaryValues;
+ const dictionaryLengths = lzwState.dictionaryLengths;
+ const dictionaryPrevCodes = lzwState.dictionaryPrevCodes;
+ let codeLength = lzwState.codeLength;
+ let prevCode = lzwState.prevCode;
+ const currentSequence = lzwState.currentSequence;
+ let currentSequenceLength = lzwState.currentSequenceLength;
+ let decodedLength = 0;
+ let currentBufferLength = this.bufferLength;
+ let buffer = this.ensureBuffer(this.bufferLength + estimatedDecodedSize);
+ for (i = 0; i < blockSize; i++) {
+ const code = this.readBits(codeLength);
+ const hasPrev = currentSequenceLength > 0;
+ if (code < 256) {
+ currentSequence[0] = code;
+ currentSequenceLength = 1;
+ } else if (code >= 258) {
+ if (code < nextCode) {
+ currentSequenceLength = dictionaryLengths[code];
+ for (j = currentSequenceLength - 1, q = code; j >= 0; j--) {
+ currentSequence[j] = dictionaryValues[q];
+ q = dictionaryPrevCodes[q];
+ }
+ } else {
+ currentSequence[currentSequenceLength++] = currentSequence[0];
+ }
+ } else if (code === 256) {
+ codeLength = 9;
+ nextCode = 258;
+ currentSequenceLength = 0;
+ continue;
+ } else {
+ this.eof = true;
+ delete this.lzwState;
+ break;
+ }
+ if (hasPrev) {
+ dictionaryPrevCodes[nextCode] = prevCode;
+ dictionaryLengths[nextCode] = dictionaryLengths[prevCode] + 1;
+ dictionaryValues[nextCode] = currentSequence[0];
+ nextCode++;
+ codeLength = nextCode + earlyChange & nextCode + earlyChange - 1 ? codeLength : Math.min(Math.log(nextCode + earlyChange) / 0.6931471805599453 + 1, 12) | 0;
+ }
+ prevCode = code;
+ decodedLength += currentSequenceLength;
+ if (estimatedDecodedSize < decodedLength) {
+ do {
+ estimatedDecodedSize += decodedSizeDelta;
+ } while (estimatedDecodedSize < decodedLength);
+ buffer = this.ensureBuffer(this.bufferLength + estimatedDecodedSize);
+ }
+ for (j = 0; j < currentSequenceLength; j++) {
+ buffer[currentBufferLength++] = currentSequence[j];
+ }
+ }
+ lzwState.nextCode = nextCode;
+ lzwState.codeLength = codeLength;
+ lzwState.prevCode = prevCode;
+ lzwState.currentSequenceLength = currentSequenceLength;
+ this.bufferLength = currentBufferLength;
+ }
+}
+
+;// CONCATENATED MODULE: ./src/core/predictor_stream.js
+
+
+
+class PredictorStream extends DecodeStream {
+ constructor(str, maybeLength, params) {
+ super(maybeLength);
+ if (!(params instanceof Dict)) {
+ return str;
+ }
+ const predictor = this.predictor = params.get("Predictor") || 1;
+ if (predictor <= 1) {
+ return str;
+ }
+ if (predictor !== 2 && (predictor < 10 || predictor > 15)) {
+ throw new FormatError(`Unsupported predictor: ${predictor}`);
+ }
+ this.readBlock = predictor === 2 ? this.readBlockTiff : this.readBlockPng;
+ this.str = str;
+ this.dict = str.dict;
+ const colors = this.colors = params.get("Colors") || 1;
+ const bits = this.bits = params.get("BPC", "BitsPerComponent") || 8;
+ const columns = this.columns = params.get("Columns") || 1;
+ this.pixBytes = colors * bits + 7 >> 3;
+ this.rowBytes = columns * colors * bits + 7 >> 3;
+ return this;
+ }
+ readBlockTiff() {
+ const rowBytes = this.rowBytes;
+ const bufferLength = this.bufferLength;
+ const buffer = this.ensureBuffer(bufferLength + rowBytes);
+ const bits = this.bits;
+ const colors = this.colors;
+ const rawBytes = this.str.getBytes(rowBytes);
+ this.eof = !rawBytes.length;
+ if (this.eof) {
+ return;
+ }
+ let inbuf = 0,
+ outbuf = 0;
+ let inbits = 0,
+ outbits = 0;
+ let pos = bufferLength;
+ let i;
+ if (bits === 1 && colors === 1) {
+ for (i = 0; i < rowBytes; ++i) {
+ let c = rawBytes[i] ^ inbuf;
+ c ^= c >> 1;
+ c ^= c >> 2;
+ c ^= c >> 4;
+ inbuf = (c & 1) << 7;
+ buffer[pos++] = c;
+ }
+ } else if (bits === 8) {
+ for (i = 0; i < colors; ++i) {
+ buffer[pos++] = rawBytes[i];
+ }
+ for (; i < rowBytes; ++i) {
+ buffer[pos] = buffer[pos - colors] + rawBytes[i];
+ pos++;
+ }
+ } else if (bits === 16) {
+ const bytesPerPixel = colors * 2;
+ for (i = 0; i < bytesPerPixel; ++i) {
+ buffer[pos++] = rawBytes[i];
+ }
+ for (; i < rowBytes; i += 2) {
+ const sum = ((rawBytes[i] & 0xff) << 8) + (rawBytes[i + 1] & 0xff) + ((buffer[pos - bytesPerPixel] & 0xff) << 8) + (buffer[pos - bytesPerPixel + 1] & 0xff);
+ buffer[pos++] = sum >> 8 & 0xff;
+ buffer[pos++] = sum & 0xff;
+ }
+ } else {
+ const compArray = new Uint8Array(colors + 1);
+ const bitMask = (1 << bits) - 1;
+ let j = 0,
+ k = bufferLength;
+ const columns = this.columns;
+ for (i = 0; i < columns; ++i) {
+ for (let kk = 0; kk < colors; ++kk) {
+ if (inbits < bits) {
+ inbuf = inbuf << 8 | rawBytes[j++] & 0xff;
+ inbits += 8;
+ }
+ compArray[kk] = compArray[kk] + (inbuf >> inbits - bits) & bitMask;
+ inbits -= bits;
+ outbuf = outbuf << bits | compArray[kk];
+ outbits += bits;
+ if (outbits >= 8) {
+ buffer[k++] = outbuf >> outbits - 8 & 0xff;
+ outbits -= 8;
+ }
+ }
+ }
+ if (outbits > 0) {
+ buffer[k++] = (outbuf << 8 - outbits) + (inbuf & (1 << 8 - outbits) - 1);
+ }
+ }
+ this.bufferLength += rowBytes;
+ }
+ readBlockPng() {
+ const rowBytes = this.rowBytes;
+ const pixBytes = this.pixBytes;
+ const predictor = this.str.getByte();
+ const rawBytes = this.str.getBytes(rowBytes);
+ this.eof = !rawBytes.length;
+ if (this.eof) {
+ return;
+ }
+ const bufferLength = this.bufferLength;
+ const buffer = this.ensureBuffer(bufferLength + rowBytes);
+ let prevRow = buffer.subarray(bufferLength - rowBytes, bufferLength);
+ if (prevRow.length === 0) {
+ prevRow = new Uint8Array(rowBytes);
+ }
+ let i,
+ j = bufferLength,
+ up,
+ c;
+ switch (predictor) {
+ case 0:
+ for (i = 0; i < rowBytes; ++i) {
+ buffer[j++] = rawBytes[i];
+ }
+ break;
+ case 1:
+ for (i = 0; i < pixBytes; ++i) {
+ buffer[j++] = rawBytes[i];
+ }
+ for (; i < rowBytes; ++i) {
+ buffer[j] = buffer[j - pixBytes] + rawBytes[i] & 0xff;
+ j++;
+ }
+ break;
+ case 2:
+ for (i = 0; i < rowBytes; ++i) {
+ buffer[j++] = prevRow[i] + rawBytes[i] & 0xff;
+ }
+ break;
+ case 3:
+ for (i = 0; i < pixBytes; ++i) {
+ buffer[j++] = (prevRow[i] >> 1) + rawBytes[i];
+ }
+ for (; i < rowBytes; ++i) {
+ buffer[j] = (prevRow[i] + buffer[j - pixBytes] >> 1) + rawBytes[i] & 0xff;
+ j++;
+ }
+ break;
+ case 4:
+ for (i = 0; i < pixBytes; ++i) {
+ up = prevRow[i];
+ c = rawBytes[i];
+ buffer[j++] = up + c;
+ }
+ for (; i < rowBytes; ++i) {
+ up = prevRow[i];
+ const upLeft = prevRow[i - pixBytes];
+ const left = buffer[j - pixBytes];
+ const p = left + up - upLeft;
+ let pa = p - left;
+ if (pa < 0) {
+ pa = -pa;
+ }
+ let pb = p - up;
+ if (pb < 0) {
+ pb = -pb;
+ }
+ let pc = p - upLeft;
+ if (pc < 0) {
+ pc = -pc;
+ }
+ c = rawBytes[i];
+ if (pa <= pb && pa <= pc) {
+ buffer[j++] = left + c;
+ } else if (pb <= pc) {
+ buffer[j++] = up + c;
+ } else {
+ buffer[j++] = upLeft + c;
+ }
+ }
+ break;
+ default:
+ throw new FormatError(`Unsupported predictor: ${predictor}`);
+ }
+ this.bufferLength += rowBytes;
+ }
+}
+
+;// CONCATENATED MODULE: ./src/core/run_length_stream.js
+
+class RunLengthStream extends DecodeStream {
+ constructor(str, maybeLength) {
+ super(maybeLength);
+ this.str = str;
+ this.dict = str.dict;
+ }
+ readBlock() {
+ const repeatHeader = this.str.getBytes(2);
+ if (!repeatHeader || repeatHeader.length < 2 || repeatHeader[0] === 128) {
+ this.eof = true;
+ return;
+ }
+ let buffer;
+ let bufferLength = this.bufferLength;
+ let n = repeatHeader[0];
+ if (n < 128) {
+ buffer = this.ensureBuffer(bufferLength + n + 1);
+ buffer[bufferLength++] = repeatHeader[1];
+ if (n > 0) {
+ const source = this.str.getBytes(n);
+ buffer.set(source, bufferLength);
+ bufferLength += n;
+ }
+ } else {
+ n = 257 - n;
+ const b = repeatHeader[1];
+ buffer = this.ensureBuffer(bufferLength + n + 1);
+ for (let i = 0; i < n; i++) {
+ buffer[bufferLength++] = b;
+ }
+ }
+ this.bufferLength = bufferLength;
+ }
+}
+
+;// CONCATENATED MODULE: ./src/core/parser.js
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+const MAX_LENGTH_TO_CACHE = 1000;
+function getInlineImageCacheKey(bytes) {
+ const strBuf = [],
+ ii = bytes.length;
+ let i = 0;
+ while (i < ii - 1) {
+ strBuf.push(bytes[i++] << 8 | bytes[i++]);
+ }
+ if (i < ii) {
+ strBuf.push(bytes[i]);
+ }
+ return ii + "_" + String.fromCharCode.apply(null, strBuf);
+}
+class Parser {
+ constructor({
+ lexer,
+ xref,
+ allowStreams = false,
+ recoveryMode = false
+ }) {
+ this.lexer = lexer;
+ this.xref = xref;
+ this.allowStreams = allowStreams;
+ this.recoveryMode = recoveryMode;
+ this.imageCache = Object.create(null);
+ this._imageId = 0;
+ this.refill();
+ }
+ refill() {
+ this.buf1 = this.lexer.getObj();
+ this.buf2 = this.lexer.getObj();
+ }
+ shift() {
+ if (this.buf2 instanceof Cmd && this.buf2.cmd === "ID") {
+ this.buf1 = this.buf2;
+ this.buf2 = null;
+ } else {
+ this.buf1 = this.buf2;
+ this.buf2 = this.lexer.getObj();
+ }
+ }
+ tryShift() {
+ try {
+ this.shift();
+ return true;
+ } catch (e) {
+ if (e instanceof MissingDataException) {
+ throw e;
+ }
+ return false;
+ }
+ }
+ getObj(cipherTransform = null) {
+ const buf1 = this.buf1;
+ this.shift();
+ if (buf1 instanceof Cmd) {
+ switch (buf1.cmd) {
+ case "BI":
+ return this.makeInlineImage(cipherTransform);
+ case "[":
+ const array = [];
+ while (!isCmd(this.buf1, "]") && this.buf1 !== EOF) {
+ array.push(this.getObj(cipherTransform));
+ }
+ if (this.buf1 === EOF) {
+ if (this.recoveryMode) {
+ return array;
+ }
+ throw new ParserEOFException("End of file inside array.");
+ }
+ this.shift();
+ return array;
+ case "<<":
+ const dict = new Dict(this.xref);
+ while (!isCmd(this.buf1, ">>") && this.buf1 !== EOF) {
+ if (!(this.buf1 instanceof Name)) {
+ info("Malformed dictionary: key must be a name object");
+ this.shift();
+ continue;
+ }
+ const key = this.buf1.name;
+ this.shift();
+ if (this.buf1 === EOF) {
+ break;
+ }
+ dict.set(key, this.getObj(cipherTransform));
+ }
+ if (this.buf1 === EOF) {
+ if (this.recoveryMode) {
+ return dict;
+ }
+ throw new ParserEOFException("End of file inside dictionary.");
+ }
+ if (isCmd(this.buf2, "stream")) {
+ return this.allowStreams ? this.makeStream(dict, cipherTransform) : dict;
+ }
+ this.shift();
+ return dict;
+ default:
+ return buf1;
+ }
+ }
+ if (Number.isInteger(buf1)) {
+ if (Number.isInteger(this.buf1) && isCmd(this.buf2, "R")) {
+ const ref = Ref.get(buf1, this.buf1);
+ this.shift();
+ this.shift();
+ return ref;
+ }
+ return buf1;
+ }
+ if (typeof buf1 === "string") {
+ if (cipherTransform) {
+ return cipherTransform.decryptString(buf1);
+ }
+ return buf1;
+ }
+ return buf1;
+ }
+ findDefaultInlineStreamEnd(stream) {
+ const E = 0x45,
+ I = 0x49,
+ SPACE = 0x20,
+ LF = 0xa,
+ CR = 0xd,
+ NUL = 0x0;
+ const {
+ knownCommands
+ } = this.lexer,
+ startPos = stream.pos,
+ n = 15;
+ let state = 0,
+ ch,
+ maybeEIPos;
+ while ((ch = stream.getByte()) !== -1) {
+ if (state === 0) {
+ state = ch === E ? 1 : 0;
+ } else if (state === 1) {
+ state = ch === I ? 2 : 0;
+ } else {
+ if (ch === SPACE || ch === LF || ch === CR) {
+ maybeEIPos = stream.pos;
+ const followingBytes = stream.peekBytes(n);
+ const ii = followingBytes.length;
+ if (ii === 0) {
+ break;
+ }
+ for (let i = 0; i < ii; i++) {
+ ch = followingBytes[i];
+ if (ch === NUL && followingBytes[i + 1] !== NUL) {
+ continue;
+ }
+ if (ch !== LF && ch !== CR && (ch < SPACE || ch > 0x7f)) {
+ state = 0;
+ break;
+ }
+ }
+ if (state !== 2) {
+ continue;
+ }
+ if (!knownCommands) {
+ warn("findDefaultInlineStreamEnd - `lexer.knownCommands` is undefined.");
+ continue;
+ }
+ const tmpLexer = new Lexer(new Stream(followingBytes.slice()), knownCommands);
+ tmpLexer._hexStringWarn = () => {};
+ let numArgs = 0;
+ while (true) {
+ const nextObj = tmpLexer.getObj();
+ if (nextObj === EOF) {
+ state = 0;
+ break;
+ }
+ if (nextObj instanceof Cmd) {
+ const knownCommand = knownCommands[nextObj.cmd];
+ if (!knownCommand) {
+ state = 0;
+ break;
+ } else if (knownCommand.variableArgs ? numArgs <= knownCommand.numArgs : numArgs === knownCommand.numArgs) {
+ break;
+ }
+ numArgs = 0;
+ continue;
+ }
+ numArgs++;
+ }
+ if (state === 2) {
+ break;
+ }
+ } else {
+ state = 0;
+ }
+ }
+ }
+ if (ch === -1) {
+ warn("findDefaultInlineStreamEnd: " + "Reached the end of the stream without finding a valid EI marker");
+ if (maybeEIPos) {
+ warn('... trying to recover by using the last "EI" occurrence.');
+ stream.skip(-(stream.pos - maybeEIPos));
+ }
+ }
+ let endOffset = 4;
+ stream.skip(-endOffset);
+ ch = stream.peekByte();
+ stream.skip(endOffset);
+ if (!isWhiteSpace(ch)) {
+ endOffset--;
+ }
+ return stream.pos - endOffset - startPos;
+ }
+ findDCTDecodeInlineStreamEnd(stream) {
+ const startPos = stream.pos;
+ let foundEOI = false,
+ b,
+ markerLength;
+ while ((b = stream.getByte()) !== -1) {
+ if (b !== 0xff) {
+ continue;
+ }
+ switch (stream.getByte()) {
+ case 0x00:
+ break;
+ case 0xff:
+ stream.skip(-1);
+ break;
+ case 0xd9:
+ foundEOI = true;
+ break;
+ case 0xc0:
+ case 0xc1:
+ case 0xc2:
+ case 0xc3:
+ case 0xc5:
+ case 0xc6:
+ case 0xc7:
+ case 0xc9:
+ case 0xca:
+ case 0xcb:
+ case 0xcd:
+ case 0xce:
+ case 0xcf:
+ case 0xc4:
+ case 0xcc:
+ case 0xda:
+ case 0xdb:
+ case 0xdc:
+ case 0xdd:
+ case 0xde:
+ case 0xdf:
+ case 0xe0:
+ case 0xe1:
+ case 0xe2:
+ case 0xe3:
+ case 0xe4:
+ case 0xe5:
+ case 0xe6:
+ case 0xe7:
+ case 0xe8:
+ case 0xe9:
+ case 0xea:
+ case 0xeb:
+ case 0xec:
+ case 0xed:
+ case 0xee:
+ case 0xef:
+ case 0xfe:
+ markerLength = stream.getUint16();
+ if (markerLength > 2) {
+ stream.skip(markerLength - 2);
+ } else {
+ stream.skip(-2);
+ }
+ break;
+ }
+ if (foundEOI) {
+ break;
+ }
+ }
+ const length = stream.pos - startPos;
+ if (b === -1) {
+ warn("Inline DCTDecode image stream: " + "EOI marker not found, searching for /EI/ instead.");
+ stream.skip(-length);
+ return this.findDefaultInlineStreamEnd(stream);
+ }
+ this.inlineStreamSkipEI(stream);
+ return length;
+ }
+ findASCII85DecodeInlineStreamEnd(stream) {
+ const TILDE = 0x7e,
+ GT = 0x3e;
+ const startPos = stream.pos;
+ let ch;
+ while ((ch = stream.getByte()) !== -1) {
+ if (ch === TILDE) {
+ const tildePos = stream.pos;
+ ch = stream.peekByte();
+ while (isWhiteSpace(ch)) {
+ stream.skip();
+ ch = stream.peekByte();
+ }
+ if (ch === GT) {
+ stream.skip();
+ break;
+ }
+ if (stream.pos > tildePos) {
+ const maybeEI = stream.peekBytes(2);
+ if (maybeEI[0] === 0x45 && maybeEI[1] === 0x49) {
+ break;
+ }
+ }
+ }
+ }
+ const length = stream.pos - startPos;
+ if (ch === -1) {
+ warn("Inline ASCII85Decode image stream: " + "EOD marker not found, searching for /EI/ instead.");
+ stream.skip(-length);
+ return this.findDefaultInlineStreamEnd(stream);
+ }
+ this.inlineStreamSkipEI(stream);
+ return length;
+ }
+ findASCIIHexDecodeInlineStreamEnd(stream) {
+ const GT = 0x3e;
+ const startPos = stream.pos;
+ let ch;
+ while ((ch = stream.getByte()) !== -1) {
+ if (ch === GT) {
+ break;
+ }
+ }
+ const length = stream.pos - startPos;
+ if (ch === -1) {
+ warn("Inline ASCIIHexDecode image stream: " + "EOD marker not found, searching for /EI/ instead.");
+ stream.skip(-length);
+ return this.findDefaultInlineStreamEnd(stream);
+ }
+ this.inlineStreamSkipEI(stream);
+ return length;
+ }
+ inlineStreamSkipEI(stream) {
+ const E = 0x45,
+ I = 0x49;
+ let state = 0,
+ ch;
+ while ((ch = stream.getByte()) !== -1) {
+ if (state === 0) {
+ state = ch === E ? 1 : 0;
+ } else if (state === 1) {
+ state = ch === I ? 2 : 0;
+ } else if (state === 2) {
+ break;
+ }
+ }
+ }
+ makeInlineImage(cipherTransform) {
+ const lexer = this.lexer;
+ const stream = lexer.stream;
+ const dictMap = Object.create(null);
+ let dictLength;
+ while (!isCmd(this.buf1, "ID") && this.buf1 !== EOF) {
+ if (!(this.buf1 instanceof Name)) {
+ throw new FormatError("Dictionary key must be a name object");
+ }
+ const key = this.buf1.name;
+ this.shift();
+ if (this.buf1 === EOF) {
+ break;
+ }
+ dictMap[key] = this.getObj(cipherTransform);
+ }
+ if (lexer.beginInlineImagePos !== -1) {
+ dictLength = stream.pos - lexer.beginInlineImagePos;
+ }
+ const filter = this.xref.fetchIfRef(dictMap.F || dictMap.Filter);
+ let filterName;
+ if (filter instanceof Name) {
+ filterName = filter.name;
+ } else if (Array.isArray(filter)) {
+ const filterZero = this.xref.fetchIfRef(filter[0]);
+ if (filterZero instanceof Name) {
+ filterName = filterZero.name;
+ }
+ }
+ const startPos = stream.pos;
+ let length;
+ switch (filterName) {
+ case "DCT":
+ case "DCTDecode":
+ length = this.findDCTDecodeInlineStreamEnd(stream);
+ break;
+ case "A85":
+ case "ASCII85Decode":
+ length = this.findASCII85DecodeInlineStreamEnd(stream);
+ break;
+ case "AHx":
+ case "ASCIIHexDecode":
+ length = this.findASCIIHexDecodeInlineStreamEnd(stream);
+ break;
+ default:
+ length = this.findDefaultInlineStreamEnd(stream);
+ }
+ let cacheKey;
+ if (length < MAX_LENGTH_TO_CACHE && dictLength > 0) {
+ const initialStreamPos = stream.pos;
+ stream.pos = lexer.beginInlineImagePos;
+ cacheKey = getInlineImageCacheKey(stream.getBytes(dictLength + length));
+ stream.pos = initialStreamPos;
+ const cacheEntry = this.imageCache[cacheKey];
+ if (cacheEntry !== undefined) {
+ this.buf2 = Cmd.get("EI");
+ this.shift();
+ cacheEntry.reset();
+ return cacheEntry;
+ }
+ }
+ const dict = new Dict(this.xref);
+ for (const key in dictMap) {
+ dict.set(key, dictMap[key]);
+ }
+ let imageStream = stream.makeSubStream(startPos, length, dict);
+ if (cipherTransform) {
+ imageStream = cipherTransform.createStream(imageStream, length);
+ }
+ imageStream = this.filter(imageStream, dict, length);
+ imageStream.dict = dict;
+ if (cacheKey !== undefined) {
+ imageStream.cacheKey = `inline_img_${++this._imageId}`;
+ this.imageCache[cacheKey] = imageStream;
+ }
+ this.buf2 = Cmd.get("EI");
+ this.shift();
+ return imageStream;
+ }
+ _findStreamLength(startPos, signature) {
+ const {
+ stream
+ } = this.lexer;
+ stream.pos = startPos;
+ const SCAN_BLOCK_LENGTH = 2048;
+ const signatureLength = signature.length;
+ while (stream.pos < stream.end) {
+ const scanBytes = stream.peekBytes(SCAN_BLOCK_LENGTH);
+ const scanLength = scanBytes.length - signatureLength;
+ if (scanLength <= 0) {
+ break;
+ }
+ let pos = 0;
+ while (pos < scanLength) {
+ let j = 0;
+ while (j < signatureLength && scanBytes[pos + j] === signature[j]) {
+ j++;
+ }
+ if (j >= signatureLength) {
+ stream.pos += pos;
+ return stream.pos - startPos;
+ }
+ pos++;
+ }
+ stream.pos += scanLength;
+ }
+ return -1;
+ }
+ makeStream(dict, cipherTransform) {
+ const lexer = this.lexer;
+ let stream = lexer.stream;
+ lexer.skipToNextLine();
+ const startPos = stream.pos - 1;
+ let length = dict.get("Length");
+ if (!Number.isInteger(length)) {
+ info(`Bad length "${length && length.toString()}" in stream.`);
+ length = 0;
+ }
+ stream.pos = startPos + length;
+ lexer.nextChar();
+ if (this.tryShift() && isCmd(this.buf2, "endstream")) {
+ this.shift();
+ } else {
+ const ENDSTREAM_SIGNATURE = new Uint8Array([0x65, 0x6e, 0x64, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d]);
+ let actualLength = this._findStreamLength(startPos, ENDSTREAM_SIGNATURE);
+ if (actualLength < 0) {
+ const MAX_TRUNCATION = 1;
+ for (let i = 1; i <= MAX_TRUNCATION; i++) {
+ const end = ENDSTREAM_SIGNATURE.length - i;
+ const TRUNCATED_SIGNATURE = ENDSTREAM_SIGNATURE.slice(0, end);
+ const maybeLength = this._findStreamLength(startPos, TRUNCATED_SIGNATURE);
+ if (maybeLength >= 0) {
+ const lastByte = stream.peekBytes(end + 1)[end];
+ if (!isWhiteSpace(lastByte)) {
+ break;
+ }
+ info(`Found "${bytesToString(TRUNCATED_SIGNATURE)}" when ` + "searching for endstream command.");
+ actualLength = maybeLength;
+ break;
+ }
+ }
+ if (actualLength < 0) {
+ throw new FormatError("Missing endstream command.");
+ }
+ }
+ length = actualLength;
+ lexer.nextChar();
+ this.shift();
+ this.shift();
+ }
+ this.shift();
+ stream = stream.makeSubStream(startPos, length, dict);
+ if (cipherTransform) {
+ stream = cipherTransform.createStream(stream, length);
+ }
+ stream = this.filter(stream, dict, length);
+ stream.dict = dict;
+ return stream;
+ }
+ filter(stream, dict, length) {
+ let filter = dict.get("F", "Filter");
+ let params = dict.get("DP", "DecodeParms");
+ if (filter instanceof Name) {
+ if (Array.isArray(params)) {
+ warn("/DecodeParms should not be an Array, when /Filter is a Name.");
+ }
+ return this.makeFilter(stream, filter.name, length, params);
+ }
+ let maybeLength = length;
+ if (Array.isArray(filter)) {
+ const filterArray = filter;
+ const paramsArray = params;
+ for (let i = 0, ii = filterArray.length; i < ii; ++i) {
+ filter = this.xref.fetchIfRef(filterArray[i]);
+ if (!(filter instanceof Name)) {
+ throw new FormatError(`Bad filter name "${filter}"`);
+ }
+ params = null;
+ if (Array.isArray(paramsArray) && i in paramsArray) {
+ params = this.xref.fetchIfRef(paramsArray[i]);
+ }
+ stream = this.makeFilter(stream, filter.name, maybeLength, params);
+ maybeLength = null;
+ }
+ }
+ return stream;
+ }
+ makeFilter(stream, name, maybeLength, params) {
+ if (maybeLength === 0) {
+ warn(`Empty "${name}" stream.`);
+ return new NullStream();
+ }
+ try {
+ switch (name) {
+ case "Fl":
+ case "FlateDecode":
+ if (params) {
+ return new PredictorStream(new FlateStream(stream, maybeLength), maybeLength, params);
+ }
+ return new FlateStream(stream, maybeLength);
+ case "LZW":
+ case "LZWDecode":
+ let earlyChange = 1;
+ if (params) {
+ if (params.has("EarlyChange")) {
+ earlyChange = params.get("EarlyChange");
+ }
+ return new PredictorStream(new LZWStream(stream, maybeLength, earlyChange), maybeLength, params);
+ }
+ return new LZWStream(stream, maybeLength, earlyChange);
+ case "DCT":
+ case "DCTDecode":
+ return new JpegStream(stream, maybeLength, params);
+ case "JPX":
+ case "JPXDecode":
+ return new JpxStream(stream, maybeLength, params);
+ case "A85":
+ case "ASCII85Decode":
+ return new Ascii85Stream(stream, maybeLength);
+ case "AHx":
+ case "ASCIIHexDecode":
+ return new AsciiHexStream(stream, maybeLength);
+ case "CCF":
+ case "CCITTFaxDecode":
+ return new CCITTFaxStream(stream, maybeLength, params);
+ case "RL":
+ case "RunLengthDecode":
+ return new RunLengthStream(stream, maybeLength);
+ case "JBIG2Decode":
+ return new Jbig2Stream(stream, maybeLength, params);
+ }
+ warn(`Filter "${name}" is not supported.`);
+ return stream;
+ } catch (ex) {
+ if (ex instanceof MissingDataException) {
+ throw ex;
+ }
+ warn(`Invalid stream: "${ex}"`);
+ return new NullStream();
+ }
+ }
+}
+const specialChars = [1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 2, 0, 0, 2, 2, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
+function toHexDigit(ch) {
+ if (ch >= 0x30 && ch <= 0x39) {
+ return ch & 0x0f;
+ }
+ if (ch >= 0x41 && ch <= 0x46 || ch >= 0x61 && ch <= 0x66) {
+ return (ch & 0x0f) + 9;
+ }
+ return -1;
+}
+class Lexer {
+ constructor(stream, knownCommands = null) {
+ this.stream = stream;
+ this.nextChar();
+ this.strBuf = [];
+ this.knownCommands = knownCommands;
+ this._hexStringNumWarn = 0;
+ this.beginInlineImagePos = -1;
+ }
+ nextChar() {
+ return this.currentChar = this.stream.getByte();
+ }
+ peekChar() {
+ return this.stream.peekByte();
+ }
+ getNumber() {
+ let ch = this.currentChar;
+ let eNotation = false;
+ let divideBy = 0;
+ let sign = 1;
+ if (ch === 0x2d) {
+ sign = -1;
+ ch = this.nextChar();
+ if (ch === 0x2d) {
+ ch = this.nextChar();
+ }
+ } else if (ch === 0x2b) {
+ ch = this.nextChar();
+ }
+ if (ch === 0x0a || ch === 0x0d) {
+ do {
+ ch = this.nextChar();
+ } while (ch === 0x0a || ch === 0x0d);
+ }
+ if (ch === 0x2e) {
+ divideBy = 10;
+ ch = this.nextChar();
+ }
+ if (ch < 0x30 || ch > 0x39) {
+ const msg = `Invalid number: ${String.fromCharCode(ch)} (charCode ${ch})`;
+ if (isWhiteSpace(ch) || ch === -1) {
+ info(`Lexer.getNumber - "${msg}".`);
+ return 0;
+ }
+ throw new FormatError(msg);
+ }
+ let baseValue = ch - 0x30;
+ let powerValue = 0;
+ let powerValueSign = 1;
+ while ((ch = this.nextChar()) >= 0) {
+ if (ch >= 0x30 && ch <= 0x39) {
+ const currentDigit = ch - 0x30;
+ if (eNotation) {
+ powerValue = powerValue * 10 + currentDigit;
+ } else {
+ if (divideBy !== 0) {
+ divideBy *= 10;
+ }
+ baseValue = baseValue * 10 + currentDigit;
+ }
+ } else if (ch === 0x2e) {
+ if (divideBy === 0) {
+ divideBy = 1;
+ } else {
+ break;
+ }
+ } else if (ch === 0x2d) {
+ warn("Badly formatted number: minus sign in the middle");
+ } else if (ch === 0x45 || ch === 0x65) {
+ ch = this.peekChar();
+ if (ch === 0x2b || ch === 0x2d) {
+ powerValueSign = ch === 0x2d ? -1 : 1;
+ this.nextChar();
+ } else if (ch < 0x30 || ch > 0x39) {
+ break;
+ }
+ eNotation = true;
+ } else {
+ break;
+ }
+ }
+ if (divideBy !== 0) {
+ baseValue /= divideBy;
+ }
+ if (eNotation) {
+ baseValue *= 10 ** (powerValueSign * powerValue);
+ }
+ return sign * baseValue;
+ }
+ getString() {
+ let numParen = 1;
+ let done = false;
+ const strBuf = this.strBuf;
+ strBuf.length = 0;
+ let ch = this.nextChar();
+ while (true) {
+ let charBuffered = false;
+ switch (ch | 0) {
+ case -1:
+ warn("Unterminated string");
+ done = true;
+ break;
+ case 0x28:
+ ++numParen;
+ strBuf.push("(");
+ break;
+ case 0x29:
+ if (--numParen === 0) {
+ this.nextChar();
+ done = true;
+ } else {
+ strBuf.push(")");
+ }
+ break;
+ case 0x5c:
+ ch = this.nextChar();
+ switch (ch) {
+ case -1:
+ warn("Unterminated string");
+ done = true;
+ break;
+ case 0x6e:
+ strBuf.push("\n");
+ break;
+ case 0x72:
+ strBuf.push("\r");
+ break;
+ case 0x74:
+ strBuf.push("\t");
+ break;
+ case 0x62:
+ strBuf.push("\b");
+ break;
+ case 0x66:
+ strBuf.push("\f");
+ break;
+ case 0x5c:
+ case 0x28:
+ case 0x29:
+ strBuf.push(String.fromCharCode(ch));
+ break;
+ case 0x30:
+ case 0x31:
+ case 0x32:
+ case 0x33:
+ case 0x34:
+ case 0x35:
+ case 0x36:
+ case 0x37:
+ let x = ch & 0x0f;
+ ch = this.nextChar();
+ charBuffered = true;
+ if (ch >= 0x30 && ch <= 0x37) {
+ x = (x << 3) + (ch & 0x0f);
+ ch = this.nextChar();
+ if (ch >= 0x30 && ch <= 0x37) {
+ charBuffered = false;
+ x = (x << 3) + (ch & 0x0f);
+ }
+ }
+ strBuf.push(String.fromCharCode(x));
+ break;
+ case 0x0d:
+ if (this.peekChar() === 0x0a) {
+ this.nextChar();
+ }
+ break;
+ case 0x0a:
+ break;
+ default:
+ strBuf.push(String.fromCharCode(ch));
+ break;
+ }
+ break;
+ default:
+ strBuf.push(String.fromCharCode(ch));
+ break;
+ }
+ if (done) {
+ break;
+ }
+ if (!charBuffered) {
+ ch = this.nextChar();
+ }
+ }
+ return strBuf.join("");
+ }
+ getName() {
+ let ch, previousCh;
+ const strBuf = this.strBuf;
+ strBuf.length = 0;
+ while ((ch = this.nextChar()) >= 0 && !specialChars[ch]) {
+ if (ch === 0x23) {
+ ch = this.nextChar();
+ if (specialChars[ch]) {
+ warn("Lexer_getName: " + "NUMBER SIGN (#) should be followed by a hexadecimal number.");
+ strBuf.push("#");
+ break;
+ }
+ const x = toHexDigit(ch);
+ if (x !== -1) {
+ previousCh = ch;
+ ch = this.nextChar();
+ const x2 = toHexDigit(ch);
+ if (x2 === -1) {
+ warn(`Lexer_getName: Illegal digit (${String.fromCharCode(ch)}) ` + "in hexadecimal number.");
+ strBuf.push("#", String.fromCharCode(previousCh));
+ if (specialChars[ch]) {
+ break;
+ }
+ strBuf.push(String.fromCharCode(ch));
+ continue;
+ }
+ strBuf.push(String.fromCharCode(x << 4 | x2));
+ } else {
+ strBuf.push("#", String.fromCharCode(ch));
+ }
+ } else {
+ strBuf.push(String.fromCharCode(ch));
+ }
+ }
+ if (strBuf.length > 127) {
+ warn(`Name token is longer than allowed by the spec: ${strBuf.length}`);
+ }
+ return Name.get(strBuf.join(""));
+ }
+ _hexStringWarn(ch) {
+ const MAX_HEX_STRING_NUM_WARN = 5;
+ if (this._hexStringNumWarn++ === MAX_HEX_STRING_NUM_WARN) {
+ warn("getHexString - ignoring additional invalid characters.");
+ return;
+ }
+ if (this._hexStringNumWarn > MAX_HEX_STRING_NUM_WARN) {
+ return;
+ }
+ warn(`getHexString - ignoring invalid character: ${ch}`);
+ }
+ getHexString() {
+ const strBuf = this.strBuf;
+ strBuf.length = 0;
+ let ch = this.currentChar;
+ let isFirstHex = true;
+ let firstDigit, secondDigit;
+ this._hexStringNumWarn = 0;
+ while (true) {
+ if (ch < 0) {
+ warn("Unterminated hex string");
+ break;
+ } else if (ch === 0x3e) {
+ this.nextChar();
+ break;
+ } else if (specialChars[ch] === 1) {
+ ch = this.nextChar();
+ continue;
+ } else {
+ if (isFirstHex) {
+ firstDigit = toHexDigit(ch);
+ if (firstDigit === -1) {
+ this._hexStringWarn(ch);
+ ch = this.nextChar();
+ continue;
+ }
+ } else {
+ secondDigit = toHexDigit(ch);
+ if (secondDigit === -1) {
+ this._hexStringWarn(ch);
+ ch = this.nextChar();
+ continue;
+ }
+ strBuf.push(String.fromCharCode(firstDigit << 4 | secondDigit));
+ }
+ isFirstHex = !isFirstHex;
+ ch = this.nextChar();
+ }
+ }
+ return strBuf.join("");
+ }
+ getObj() {
+ let comment = false;
+ let ch = this.currentChar;
+ while (true) {
+ if (ch < 0) {
+ return EOF;
+ }
+ if (comment) {
+ if (ch === 0x0a || ch === 0x0d) {
+ comment = false;
+ }
+ } else if (ch === 0x25) {
+ comment = true;
+ } else if (specialChars[ch] !== 1) {
+ break;
+ }
+ ch = this.nextChar();
+ }
+ switch (ch | 0) {
+ case 0x30:
+ case 0x31:
+ case 0x32:
+ case 0x33:
+ case 0x34:
+ case 0x35:
+ case 0x36:
+ case 0x37:
+ case 0x38:
+ case 0x39:
+ case 0x2b:
+ case 0x2d:
+ case 0x2e:
+ return this.getNumber();
+ case 0x28:
+ return this.getString();
+ case 0x2f:
+ return this.getName();
+ case 0x5b:
+ this.nextChar();
+ return Cmd.get("[");
+ case 0x5d:
+ this.nextChar();
+ return Cmd.get("]");
+ case 0x3c:
+ ch = this.nextChar();
+ if (ch === 0x3c) {
+ this.nextChar();
+ return Cmd.get("<<");
+ }
+ return this.getHexString();
+ case 0x3e:
+ ch = this.nextChar();
+ if (ch === 0x3e) {
+ this.nextChar();
+ return Cmd.get(">>");
+ }
+ return Cmd.get(">");
+ case 0x7b:
+ this.nextChar();
+ return Cmd.get("{");
+ case 0x7d:
+ this.nextChar();
+ return Cmd.get("}");
+ case 0x29:
+ this.nextChar();
+ throw new FormatError(`Illegal character: ${ch}`);
+ }
+ let str = String.fromCharCode(ch);
+ if (ch < 0x20 || ch > 0x7f) {
+ const nextCh = this.peekChar();
+ if (nextCh >= 0x20 && nextCh <= 0x7f) {
+ this.nextChar();
+ return Cmd.get(str);
+ }
+ }
+ const knownCommands = this.knownCommands;
+ let knownCommandFound = knownCommands?.[str] !== undefined;
+ while ((ch = this.nextChar()) >= 0 && !specialChars[ch]) {
+ const possibleCommand = str + String.fromCharCode(ch);
+ if (knownCommandFound && knownCommands[possibleCommand] === undefined) {
+ break;
+ }
+ if (str.length === 128) {
+ throw new FormatError(`Command token too long: ${str.length}`);
+ }
+ str = possibleCommand;
+ knownCommandFound = knownCommands?.[str] !== undefined;
+ }
+ if (str === "true") {
+ return true;
+ }
+ if (str === "false") {
+ return false;
+ }
+ if (str === "null") {
+ return null;
+ }
+ if (str === "BI") {
+ this.beginInlineImagePos = this.stream.pos;
+ }
+ return Cmd.get(str);
+ }
+ skipToNextLine() {
+ let ch = this.currentChar;
+ while (ch >= 0) {
+ if (ch === 0x0d) {
+ ch = this.nextChar();
+ if (ch === 0x0a) {
+ this.nextChar();
+ }
+ break;
+ } else if (ch === 0x0a) {
+ this.nextChar();
+ break;
+ }
+ ch = this.nextChar();
+ }
+ }
+}
+class Linearization {
+ static create(stream) {
+ function getInt(linDict, name, allowZeroValue = false) {
+ const obj = linDict.get(name);
+ if (Number.isInteger(obj) && (allowZeroValue ? obj >= 0 : obj > 0)) {
+ return obj;
+ }
+ throw new Error(`The "${name}" parameter in the linearization ` + "dictionary is invalid.");
+ }
+ function getHints(linDict) {
+ const hints = linDict.get("H");
+ let hintsLength;
+ if (Array.isArray(hints) && ((hintsLength = hints.length) === 2 || hintsLength === 4)) {
+ for (let index = 0; index < hintsLength; index++) {
+ const hint = hints[index];
+ if (!(Number.isInteger(hint) && hint > 0)) {
+ throw new Error(`Hint (${index}) in the linearization dictionary is invalid.`);
+ }
+ }
+ return hints;
+ }
+ throw new Error("Hint array in the linearization dictionary is invalid.");
+ }
+ const parser = new Parser({
+ lexer: new Lexer(stream),
+ xref: null
+ });
+ const obj1 = parser.getObj();
+ const obj2 = parser.getObj();
+ const obj3 = parser.getObj();
+ const linDict = parser.getObj();
+ let obj, length;
+ if (!(Number.isInteger(obj1) && Number.isInteger(obj2) && isCmd(obj3, "obj") && linDict instanceof Dict && typeof (obj = linDict.get("Linearized")) === "number" && obj > 0)) {
+ return null;
+ } else if ((length = getInt(linDict, "L")) !== stream.length) {
+ throw new Error('The "L" parameter in the linearization dictionary ' + "does not equal the stream length.");
+ }
+ return {
+ length,
+ hints: getHints(linDict),
+ objectNumberFirst: getInt(linDict, "O"),
+ endFirst: getInt(linDict, "E"),
+ numPages: getInt(linDict, "N"),
+ mainXRefEntriesOffset: getInt(linDict, "T"),
+ pageFirst: linDict.has("P") ? getInt(linDict, "P", true) : 0
+ };
+ }
+}
+
+;// CONCATENATED MODULE: ./src/core/cmap.js
+
+
+
+
+
+
+
+const BUILT_IN_CMAPS = ["Adobe-GB1-UCS2", "Adobe-CNS1-UCS2", "Adobe-Japan1-UCS2", "Adobe-Korea1-UCS2", "78-EUC-H", "78-EUC-V", "78-H", "78-RKSJ-H", "78-RKSJ-V", "78-V", "78ms-RKSJ-H", "78ms-RKSJ-V", "83pv-RKSJ-H", "90ms-RKSJ-H", "90ms-RKSJ-V", "90msp-RKSJ-H", "90msp-RKSJ-V", "90pv-RKSJ-H", "90pv-RKSJ-V", "Add-H", "Add-RKSJ-H", "Add-RKSJ-V", "Add-V", "Adobe-CNS1-0", "Adobe-CNS1-1", "Adobe-CNS1-2", "Adobe-CNS1-3", "Adobe-CNS1-4", "Adobe-CNS1-5", "Adobe-CNS1-6", "Adobe-GB1-0", "Adobe-GB1-1", "Adobe-GB1-2", "Adobe-GB1-3", "Adobe-GB1-4", "Adobe-GB1-5", "Adobe-Japan1-0", "Adobe-Japan1-1", "Adobe-Japan1-2", "Adobe-Japan1-3", "Adobe-Japan1-4", "Adobe-Japan1-5", "Adobe-Japan1-6", "Adobe-Korea1-0", "Adobe-Korea1-1", "Adobe-Korea1-2", "B5-H", "B5-V", "B5pc-H", "B5pc-V", "CNS-EUC-H", "CNS-EUC-V", "CNS1-H", "CNS1-V", "CNS2-H", "CNS2-V", "ETHK-B5-H", "ETHK-B5-V", "ETen-B5-H", "ETen-B5-V", "ETenms-B5-H", "ETenms-B5-V", "EUC-H", "EUC-V", "Ext-H", "Ext-RKSJ-H", "Ext-RKSJ-V", "Ext-V", "GB-EUC-H", "GB-EUC-V", "GB-H", "GB-V", "GBK-EUC-H", "GBK-EUC-V", "GBK2K-H", "GBK2K-V", "GBKp-EUC-H", "GBKp-EUC-V", "GBT-EUC-H", "GBT-EUC-V", "GBT-H", "GBT-V", "GBTpc-EUC-H", "GBTpc-EUC-V", "GBpc-EUC-H", "GBpc-EUC-V", "H", "HKdla-B5-H", "HKdla-B5-V", "HKdlb-B5-H", "HKdlb-B5-V", "HKgccs-B5-H", "HKgccs-B5-V", "HKm314-B5-H", "HKm314-B5-V", "HKm471-B5-H", "HKm471-B5-V", "HKscs-B5-H", "HKscs-B5-V", "Hankaku", "Hiragana", "KSC-EUC-H", "KSC-EUC-V", "KSC-H", "KSC-Johab-H", "KSC-Johab-V", "KSC-V", "KSCms-UHC-H", "KSCms-UHC-HW-H", "KSCms-UHC-HW-V", "KSCms-UHC-V", "KSCpc-EUC-H", "KSCpc-EUC-V", "Katakana", "NWP-H", "NWP-V", "RKSJ-H", "RKSJ-V", "Roman", "UniCNS-UCS2-H", "UniCNS-UCS2-V", "UniCNS-UTF16-H", "UniCNS-UTF16-V", "UniCNS-UTF32-H", "UniCNS-UTF32-V", "UniCNS-UTF8-H", "UniCNS-UTF8-V", "UniGB-UCS2-H", "UniGB-UCS2-V", "UniGB-UTF16-H", "UniGB-UTF16-V", "UniGB-UTF32-H", "UniGB-UTF32-V", "UniGB-UTF8-H", "UniGB-UTF8-V", "UniJIS-UCS2-H", "UniJIS-UCS2-HW-H", "UniJIS-UCS2-HW-V", "UniJIS-UCS2-V", "UniJIS-UTF16-H", "UniJIS-UTF16-V", "UniJIS-UTF32-H", "UniJIS-UTF32-V", "UniJIS-UTF8-H", "UniJIS-UTF8-V", "UniJIS2004-UTF16-H", "UniJIS2004-UTF16-V", "UniJIS2004-UTF32-H", "UniJIS2004-UTF32-V", "UniJIS2004-UTF8-H", "UniJIS2004-UTF8-V", "UniJISPro-UCS2-HW-V", "UniJISPro-UCS2-V", "UniJISPro-UTF8-V", "UniJISX0213-UTF32-H", "UniJISX0213-UTF32-V", "UniJISX02132004-UTF32-H", "UniJISX02132004-UTF32-V", "UniKS-UCS2-H", "UniKS-UCS2-V", "UniKS-UTF16-H", "UniKS-UTF16-V", "UniKS-UTF32-H", "UniKS-UTF32-V", "UniKS-UTF8-H", "UniKS-UTF8-V", "V", "WP-Symbol"];
+const MAX_MAP_RANGE = 2 ** 24 - 1;
+class CMap {
+ constructor(builtInCMap = false) {
+ this.codespaceRanges = [[], [], [], []];
+ this.numCodespaceRanges = 0;
+ this._map = [];
+ this.name = "";
+ this.vertical = false;
+ this.useCMap = null;
+ this.builtInCMap = builtInCMap;
+ }
+ addCodespaceRange(n, low, high) {
+ this.codespaceRanges[n - 1].push(low, high);
+ this.numCodespaceRanges++;
+ }
+ mapCidRange(low, high, dstLow) {
+ if (high - low > MAX_MAP_RANGE) {
+ throw new Error("mapCidRange - ignoring data above MAX_MAP_RANGE.");
+ }
+ while (low <= high) {
+ this._map[low++] = dstLow++;
+ }
+ }
+ mapBfRange(low, high, dstLow) {
+ if (high - low > MAX_MAP_RANGE) {
+ throw new Error("mapBfRange - ignoring data above MAX_MAP_RANGE.");
+ }
+ const lastByte = dstLow.length - 1;
+ while (low <= high) {
+ this._map[low++] = dstLow;
+ const nextCharCode = dstLow.charCodeAt(lastByte) + 1;
+ if (nextCharCode > 0xff) {
+ dstLow = dstLow.substring(0, lastByte - 1) + String.fromCharCode(dstLow.charCodeAt(lastByte - 1) + 1) + "\x00";
+ continue;
+ }
+ dstLow = dstLow.substring(0, lastByte) + String.fromCharCode(nextCharCode);
+ }
+ }
+ mapBfRangeToArray(low, high, array) {
+ if (high - low > MAX_MAP_RANGE) {
+ throw new Error("mapBfRangeToArray - ignoring data above MAX_MAP_RANGE.");
+ }
+ const ii = array.length;
+ let i = 0;
+ while (low <= high && i < ii) {
+ this._map[low] = array[i++];
+ ++low;
+ }
+ }
+ mapOne(src, dst) {
+ this._map[src] = dst;
+ }
+ lookup(code) {
+ return this._map[code];
+ }
+ contains(code) {
+ return this._map[code] !== undefined;
+ }
+ forEach(callback) {
+ const map = this._map;
+ const length = map.length;
+ if (length <= 0x10000) {
+ for (let i = 0; i < length; i++) {
+ if (map[i] !== undefined) {
+ callback(i, map[i]);
+ }
+ }
+ } else {
+ for (const i in map) {
+ callback(i, map[i]);
+ }
+ }
+ }
+ charCodeOf(value) {
+ const map = this._map;
+ if (map.length <= 0x10000) {
+ return map.indexOf(value);
+ }
+ for (const charCode in map) {
+ if (map[charCode] === value) {
+ return charCode | 0;
+ }
+ }
+ return -1;
+ }
+ getMap() {
+ return this._map;
+ }
+ readCharCode(str, offset, out) {
+ let c = 0;
+ const codespaceRanges = this.codespaceRanges;
+ for (let n = 0, nn = codespaceRanges.length; n < nn; n++) {
+ c = (c << 8 | str.charCodeAt(offset + n)) >>> 0;
+ const codespaceRange = codespaceRanges[n];
+ for (let k = 0, kk = codespaceRange.length; k < kk;) {
+ const low = codespaceRange[k++];
+ const high = codespaceRange[k++];
+ if (c >= low && c <= high) {
+ out.charcode = c;
+ out.length = n + 1;
+ return;
+ }
+ }
+ }
+ out.charcode = 0;
+ out.length = 1;
+ }
+ getCharCodeLength(charCode) {
+ const codespaceRanges = this.codespaceRanges;
+ for (let n = 0, nn = codespaceRanges.length; n < nn; n++) {
+ const codespaceRange = codespaceRanges[n];
+ for (let k = 0, kk = codespaceRange.length; k < kk;) {
+ const low = codespaceRange[k++];
+ const high = codespaceRange[k++];
+ if (charCode >= low && charCode <= high) {
+ return n + 1;
+ }
+ }
+ }
+ return 1;
+ }
+ get length() {
+ return this._map.length;
+ }
+ get isIdentityCMap() {
+ if (!(this.name === "Identity-H" || this.name === "Identity-V")) {
+ return false;
+ }
+ if (this._map.length !== 0x10000) {
+ return false;
+ }
+ for (let i = 0; i < 0x10000; i++) {
+ if (this._map[i] !== i) {
+ return false;
+ }
+ }
+ return true;
+ }
+}
+class IdentityCMap extends CMap {
+ constructor(vertical, n) {
+ super();
+ this.vertical = vertical;
+ this.addCodespaceRange(n, 0, 0xffff);
+ }
+ mapCidRange(low, high, dstLow) {
+ unreachable("should not call mapCidRange");
+ }
+ mapBfRange(low, high, dstLow) {
+ unreachable("should not call mapBfRange");
+ }
+ mapBfRangeToArray(low, high, array) {
+ unreachable("should not call mapBfRangeToArray");
+ }
+ mapOne(src, dst) {
+ unreachable("should not call mapCidOne");
+ }
+ lookup(code) {
+ return Number.isInteger(code) && code <= 0xffff ? code : undefined;
+ }
+ contains(code) {
+ return Number.isInteger(code) && code <= 0xffff;
+ }
+ forEach(callback) {
+ for (let i = 0; i <= 0xffff; i++) {
+ callback(i, i);
+ }
+ }
+ charCodeOf(value) {
+ return Number.isInteger(value) && value <= 0xffff ? value : -1;
+ }
+ getMap() {
+ const map = new Array(0x10000);
+ for (let i = 0; i <= 0xffff; i++) {
+ map[i] = i;
+ }
+ return map;
+ }
+ get length() {
+ return 0x10000;
+ }
+ get isIdentityCMap() {
+ unreachable("should not access .isIdentityCMap");
+ }
+}
+function strToInt(str) {
+ let a = 0;
+ for (let i = 0; i < str.length; i++) {
+ a = a << 8 | str.charCodeAt(i);
+ }
+ return a >>> 0;
+}
+function expectString(obj) {
+ if (typeof obj !== "string") {
+ throw new FormatError("Malformed CMap: expected string.");
+ }
+}
+function expectInt(obj) {
+ if (!Number.isInteger(obj)) {
+ throw new FormatError("Malformed CMap: expected int.");
+ }
+}
+function parseBfChar(cMap, lexer) {
+ while (true) {
+ let obj = lexer.getObj();
+ if (obj === EOF) {
+ break;
+ }
+ if (isCmd(obj, "endbfchar")) {
+ return;
+ }
+ expectString(obj);
+ const src = strToInt(obj);
+ obj = lexer.getObj();
+ expectString(obj);
+ const dst = obj;
+ cMap.mapOne(src, dst);
+ }
+}
+function parseBfRange(cMap, lexer) {
+ while (true) {
+ let obj = lexer.getObj();
+ if (obj === EOF) {
+ break;
+ }
+ if (isCmd(obj, "endbfrange")) {
+ return;
+ }
+ expectString(obj);
+ const low = strToInt(obj);
+ obj = lexer.getObj();
+ expectString(obj);
+ const high = strToInt(obj);
+ obj = lexer.getObj();
+ if (Number.isInteger(obj) || typeof obj === "string") {
+ const dstLow = Number.isInteger(obj) ? String.fromCharCode(obj) : obj;
+ cMap.mapBfRange(low, high, dstLow);
+ } else if (isCmd(obj, "[")) {
+ obj = lexer.getObj();
+ const array = [];
+ while (!isCmd(obj, "]") && obj !== EOF) {
+ array.push(obj);
+ obj = lexer.getObj();
+ }
+ cMap.mapBfRangeToArray(low, high, array);
+ } else {
+ break;
+ }
+ }
+ throw new FormatError("Invalid bf range.");
+}
+function parseCidChar(cMap, lexer) {
+ while (true) {
+ let obj = lexer.getObj();
+ if (obj === EOF) {
+ break;
+ }
+ if (isCmd(obj, "endcidchar")) {
+ return;
+ }
+ expectString(obj);
+ const src = strToInt(obj);
+ obj = lexer.getObj();
+ expectInt(obj);
+ const dst = obj;
+ cMap.mapOne(src, dst);
+ }
+}
+function parseCidRange(cMap, lexer) {
+ while (true) {
+ let obj = lexer.getObj();
+ if (obj === EOF) {
+ break;
+ }
+ if (isCmd(obj, "endcidrange")) {
+ return;
+ }
+ expectString(obj);
+ const low = strToInt(obj);
+ obj = lexer.getObj();
+ expectString(obj);
+ const high = strToInt(obj);
+ obj = lexer.getObj();
+ expectInt(obj);
+ const dstLow = obj;
+ cMap.mapCidRange(low, high, dstLow);
+ }
+}
+function parseCodespaceRange(cMap, lexer) {
+ while (true) {
+ let obj = lexer.getObj();
+ if (obj === EOF) {
+ break;
+ }
+ if (isCmd(obj, "endcodespacerange")) {
+ return;
+ }
+ if (typeof obj !== "string") {
+ break;
+ }
+ const low = strToInt(obj);
+ obj = lexer.getObj();
+ if (typeof obj !== "string") {
+ break;
+ }
+ const high = strToInt(obj);
+ cMap.addCodespaceRange(obj.length, low, high);
+ }
+ throw new FormatError("Invalid codespace range.");
+}
+function parseWMode(cMap, lexer) {
+ const obj = lexer.getObj();
+ if (Number.isInteger(obj)) {
+ cMap.vertical = !!obj;
+ }
+}
+function parseCMapName(cMap, lexer) {
+ const obj = lexer.getObj();
+ if (obj instanceof Name) {
+ cMap.name = obj.name;
+ }
+}
+async function parseCMap(cMap, lexer, fetchBuiltInCMap, useCMap) {
+ let previous, embeddedUseCMap;
+ objLoop: while (true) {
+ try {
+ const obj = lexer.getObj();
+ if (obj === EOF) {
+ break;
+ } else if (obj instanceof Name) {
+ if (obj.name === "WMode") {
+ parseWMode(cMap, lexer);
+ } else if (obj.name === "CMapName") {
+ parseCMapName(cMap, lexer);
+ }
+ previous = obj;
+ } else if (obj instanceof Cmd) {
+ switch (obj.cmd) {
+ case "endcmap":
+ break objLoop;
+ case "usecmap":
+ if (previous instanceof Name) {
+ embeddedUseCMap = previous.name;
+ }
+ break;
+ case "begincodespacerange":
+ parseCodespaceRange(cMap, lexer);
+ break;
+ case "beginbfchar":
+ parseBfChar(cMap, lexer);
+ break;
+ case "begincidchar":
+ parseCidChar(cMap, lexer);
+ break;
+ case "beginbfrange":
+ parseBfRange(cMap, lexer);
+ break;
+ case "begincidrange":
+ parseCidRange(cMap, lexer);
+ break;
+ }
+ }
+ } catch (ex) {
+ if (ex instanceof MissingDataException) {
+ throw ex;
+ }
+ warn("Invalid cMap data: " + ex);
+ continue;
+ }
+ }
+ if (!useCMap && embeddedUseCMap) {
+ useCMap = embeddedUseCMap;
+ }
+ if (useCMap) {
+ return extendCMap(cMap, fetchBuiltInCMap, useCMap);
+ }
+ return cMap;
+}
+async function extendCMap(cMap, fetchBuiltInCMap, useCMap) {
+ cMap.useCMap = await createBuiltInCMap(useCMap, fetchBuiltInCMap);
+ if (cMap.numCodespaceRanges === 0) {
+ const useCodespaceRanges = cMap.useCMap.codespaceRanges;
+ for (let i = 0; i < useCodespaceRanges.length; i++) {
+ cMap.codespaceRanges[i] = useCodespaceRanges[i].slice();
+ }
+ cMap.numCodespaceRanges = cMap.useCMap.numCodespaceRanges;
+ }
+ cMap.useCMap.forEach(function (key, value) {
+ if (!cMap.contains(key)) {
+ cMap.mapOne(key, cMap.useCMap.lookup(key));
+ }
+ });
+ return cMap;
+}
+async function createBuiltInCMap(name, fetchBuiltInCMap) {
+ if (name === "Identity-H") {
+ return new IdentityCMap(false, 2);
+ } else if (name === "Identity-V") {
+ return new IdentityCMap(true, 2);
+ }
+ if (!BUILT_IN_CMAPS.includes(name)) {
+ throw new Error("Unknown CMap name: " + name);
+ }
+ if (!fetchBuiltInCMap) {
+ throw new Error("Built-in CMap parameters are not provided.");
+ }
+ const {
+ cMapData,
+ compressionType
+ } = await fetchBuiltInCMap(name);
+ const cMap = new CMap(true);
+ if (compressionType === CMapCompressionType.BINARY) {
+ return new BinaryCMapReader().process(cMapData, cMap, useCMap => extendCMap(cMap, fetchBuiltInCMap, useCMap));
+ }
+ if (compressionType === CMapCompressionType.NONE) {
+ const lexer = new Lexer(new Stream(cMapData));
+ return parseCMap(cMap, lexer, fetchBuiltInCMap, null);
+ }
+ throw new Error(`Invalid CMap "compressionType" value: ${compressionType}`);
+}
+class CMapFactory {
+ static async create({
+ encoding,
+ fetchBuiltInCMap,
+ useCMap
+ }) {
+ if (encoding instanceof Name) {
+ return createBuiltInCMap(encoding.name, fetchBuiltInCMap);
+ } else if (encoding instanceof BaseStream) {
+ const parsedCMap = await parseCMap(new CMap(), new Lexer(encoding), fetchBuiltInCMap, useCMap);
+ if (parsedCMap.isIdentityCMap) {
+ return createBuiltInCMap(parsedCMap.name, fetchBuiltInCMap);
+ }
+ return parsedCMap;
+ }
+ throw new Error("Encoding required.");
+ }
+}
+
+;// CONCATENATED MODULE: ./src/core/charsets.js
+const ISOAdobeCharset = [".notdef", "space", "exclam", "quotedbl", "numbersign", "dollar", "percent", "ampersand", "quoteright", "parenleft", "parenright", "asterisk", "plus", "comma", "hyphen", "period", "slash", "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "colon", "semicolon", "less", "equal", "greater", "question", "at", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "bracketleft", "backslash", "bracketright", "asciicircum", "underscore", "quoteleft", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "braceleft", "bar", "braceright", "asciitilde", "exclamdown", "cent", "sterling", "fraction", "yen", "florin", "section", "currency", "quotesingle", "quotedblleft", "guillemotleft", "guilsinglleft", "guilsinglright", "fi", "fl", "endash", "dagger", "daggerdbl", "periodcentered", "paragraph", "bullet", "quotesinglbase", "quotedblbase", "quotedblright", "guillemotright", "ellipsis", "perthousand", "questiondown", "grave", "acute", "circumflex", "tilde", "macron", "breve", "dotaccent", "dieresis", "ring", "cedilla", "hungarumlaut", "ogonek", "caron", "emdash", "AE", "ordfeminine", "Lslash", "Oslash", "OE", "ordmasculine", "ae", "dotlessi", "lslash", "oslash", "oe", "germandbls", "onesuperior", "logicalnot", "mu", "trademark", "Eth", "onehalf", "plusminus", "Thorn", "onequarter", "divide", "brokenbar", "degree", "thorn", "threequarters", "twosuperior", "registered", "minus", "eth", "multiply", "threesuperior", "copyright", "Aacute", "Acircumflex", "Adieresis", "Agrave", "Aring", "Atilde", "Ccedilla", "Eacute", "Ecircumflex", "Edieresis", "Egrave", "Iacute", "Icircumflex", "Idieresis", "Igrave", "Ntilde", "Oacute", "Ocircumflex", "Odieresis", "Ograve", "Otilde", "Scaron", "Uacute", "Ucircumflex", "Udieresis", "Ugrave", "Yacute", "Ydieresis", "Zcaron", "aacute", "acircumflex", "adieresis", "agrave", "aring", "atilde", "ccedilla", "eacute", "ecircumflex", "edieresis", "egrave", "iacute", "icircumflex", "idieresis", "igrave", "ntilde", "oacute", "ocircumflex", "odieresis", "ograve", "otilde", "scaron", "uacute", "ucircumflex", "udieresis", "ugrave", "yacute", "ydieresis", "zcaron"];
+const ExpertCharset = [".notdef", "space", "exclamsmall", "Hungarumlautsmall", "dollaroldstyle", "dollarsuperior", "ampersandsmall", "Acutesmall", "parenleftsuperior", "parenrightsuperior", "twodotenleader", "onedotenleader", "comma", "hyphen", "period", "fraction", "zerooldstyle", "oneoldstyle", "twooldstyle", "threeoldstyle", "fouroldstyle", "fiveoldstyle", "sixoldstyle", "sevenoldstyle", "eightoldstyle", "nineoldstyle", "colon", "semicolon", "commasuperior", "threequartersemdash", "periodsuperior", "questionsmall", "asuperior", "bsuperior", "centsuperior", "dsuperior", "esuperior", "isuperior", "lsuperior", "msuperior", "nsuperior", "osuperior", "rsuperior", "ssuperior", "tsuperior", "ff", "fi", "fl", "ffi", "ffl", "parenleftinferior", "parenrightinferior", "Circumflexsmall", "hyphensuperior", "Gravesmall", "Asmall", "Bsmall", "Csmall", "Dsmall", "Esmall", "Fsmall", "Gsmall", "Hsmall", "Ismall", "Jsmall", "Ksmall", "Lsmall", "Msmall", "Nsmall", "Osmall", "Psmall", "Qsmall", "Rsmall", "Ssmall", "Tsmall", "Usmall", "Vsmall", "Wsmall", "Xsmall", "Ysmall", "Zsmall", "colonmonetary", "onefitted", "rupiah", "Tildesmall", "exclamdownsmall", "centoldstyle", "Lslashsmall", "Scaronsmall", "Zcaronsmall", "Dieresissmall", "Brevesmall", "Caronsmall", "Dotaccentsmall", "Macronsmall", "figuredash", "hypheninferior", "Ogoneksmall", "Ringsmall", "Cedillasmall", "onequarter", "onehalf", "threequarters", "questiondownsmall", "oneeighth", "threeeighths", "fiveeighths", "seveneighths", "onethird", "twothirds", "zerosuperior", "onesuperior", "twosuperior", "threesuperior", "foursuperior", "fivesuperior", "sixsuperior", "sevensuperior", "eightsuperior", "ninesuperior", "zeroinferior", "oneinferior", "twoinferior", "threeinferior", "fourinferior", "fiveinferior", "sixinferior", "seveninferior", "eightinferior", "nineinferior", "centinferior", "dollarinferior", "periodinferior", "commainferior", "Agravesmall", "Aacutesmall", "Acircumflexsmall", "Atildesmall", "Adieresissmall", "Aringsmall", "AEsmall", "Ccedillasmall", "Egravesmall", "Eacutesmall", "Ecircumflexsmall", "Edieresissmall", "Igravesmall", "Iacutesmall", "Icircumflexsmall", "Idieresissmall", "Ethsmall", "Ntildesmall", "Ogravesmall", "Oacutesmall", "Ocircumflexsmall", "Otildesmall", "Odieresissmall", "OEsmall", "Oslashsmall", "Ugravesmall", "Uacutesmall", "Ucircumflexsmall", "Udieresissmall", "Yacutesmall", "Thornsmall", "Ydieresissmall"];
+const ExpertSubsetCharset = [".notdef", "space", "dollaroldstyle", "dollarsuperior", "parenleftsuperior", "parenrightsuperior", "twodotenleader", "onedotenleader", "comma", "hyphen", "period", "fraction", "zerooldstyle", "oneoldstyle", "twooldstyle", "threeoldstyle", "fouroldstyle", "fiveoldstyle", "sixoldstyle", "sevenoldstyle", "eightoldstyle", "nineoldstyle", "colon", "semicolon", "commasuperior", "threequartersemdash", "periodsuperior", "asuperior", "bsuperior", "centsuperior", "dsuperior", "esuperior", "isuperior", "lsuperior", "msuperior", "nsuperior", "osuperior", "rsuperior", "ssuperior", "tsuperior", "ff", "fi", "fl", "ffi", "ffl", "parenleftinferior", "parenrightinferior", "hyphensuperior", "colonmonetary", "onefitted", "rupiah", "centoldstyle", "figuredash", "hypheninferior", "onequarter", "onehalf", "threequarters", "oneeighth", "threeeighths", "fiveeighths", "seveneighths", "onethird", "twothirds", "zerosuperior", "onesuperior", "twosuperior", "threesuperior", "foursuperior", "fivesuperior", "sixsuperior", "sevensuperior", "eightsuperior", "ninesuperior", "zeroinferior", "oneinferior", "twoinferior", "threeinferior", "fourinferior", "fiveinferior", "sixinferior", "seveninferior", "eightinferior", "nineinferior", "centinferior", "dollarinferior", "periodinferior", "commainferior"];
+
+;// CONCATENATED MODULE: ./src/core/encodings.js
+const ExpertEncoding = ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "space", "exclamsmall", "Hungarumlautsmall", "", "dollaroldstyle", "dollarsuperior", "ampersandsmall", "Acutesmall", "parenleftsuperior", "parenrightsuperior", "twodotenleader", "onedotenleader", "comma", "hyphen", "period", "fraction", "zerooldstyle", "oneoldstyle", "twooldstyle", "threeoldstyle", "fouroldstyle", "fiveoldstyle", "sixoldstyle", "sevenoldstyle", "eightoldstyle", "nineoldstyle", "colon", "semicolon", "commasuperior", "threequartersemdash", "periodsuperior", "questionsmall", "", "asuperior", "bsuperior", "centsuperior", "dsuperior", "esuperior", "", "", "", "isuperior", "", "", "lsuperior", "msuperior", "nsuperior", "osuperior", "", "", "rsuperior", "ssuperior", "tsuperior", "", "ff", "fi", "fl", "ffi", "ffl", "parenleftinferior", "", "parenrightinferior", "Circumflexsmall", "hyphensuperior", "Gravesmall", "Asmall", "Bsmall", "Csmall", "Dsmall", "Esmall", "Fsmall", "Gsmall", "Hsmall", "Ismall", "Jsmall", "Ksmall", "Lsmall", "Msmall", "Nsmall", "Osmall", "Psmall", "Qsmall", "Rsmall", "Ssmall", "Tsmall", "Usmall", "Vsmall", "Wsmall", "Xsmall", "Ysmall", "Zsmall", "colonmonetary", "onefitted", "rupiah", "Tildesmall", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "exclamdownsmall", "centoldstyle", "Lslashsmall", "", "", "Scaronsmall", "Zcaronsmall", "Dieresissmall", "Brevesmall", "Caronsmall", "", "Dotaccentsmall", "", "", "Macronsmall", "", "", "figuredash", "hypheninferior", "", "", "Ogoneksmall", "Ringsmall", "Cedillasmall", "", "", "", "onequarter", "onehalf", "threequarters", "questiondownsmall", "oneeighth", "threeeighths", "fiveeighths", "seveneighths", "onethird", "twothirds", "", "", "zerosuperior", "onesuperior", "twosuperior", "threesuperior", "foursuperior", "fivesuperior", "sixsuperior", "sevensuperior", "eightsuperior", "ninesuperior", "zeroinferior", "oneinferior", "twoinferior", "threeinferior", "fourinferior", "fiveinferior", "sixinferior", "seveninferior", "eightinferior", "nineinferior", "centinferior", "dollarinferior", "periodinferior", "commainferior", "Agravesmall", "Aacutesmall", "Acircumflexsmall", "Atildesmall", "Adieresissmall", "Aringsmall", "AEsmall", "Ccedillasmall", "Egravesmall", "Eacutesmall", "Ecircumflexsmall", "Edieresissmall", "Igravesmall", "Iacutesmall", "Icircumflexsmall", "Idieresissmall", "Ethsmall", "Ntildesmall", "Ogravesmall", "Oacutesmall", "Ocircumflexsmall", "Otildesmall", "Odieresissmall", "OEsmall", "Oslashsmall", "Ugravesmall", "Uacutesmall", "Ucircumflexsmall", "Udieresissmall", "Yacutesmall", "Thornsmall", "Ydieresissmall"];
+const MacExpertEncoding = ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "space", "exclamsmall", "Hungarumlautsmall", "centoldstyle", "dollaroldstyle", "dollarsuperior", "ampersandsmall", "Acutesmall", "parenleftsuperior", "parenrightsuperior", "twodotenleader", "onedotenleader", "comma", "hyphen", "period", "fraction", "zerooldstyle", "oneoldstyle", "twooldstyle", "threeoldstyle", "fouroldstyle", "fiveoldstyle", "sixoldstyle", "sevenoldstyle", "eightoldstyle", "nineoldstyle", "colon", "semicolon", "", "threequartersemdash", "", "questionsmall", "", "", "", "", "Ethsmall", "", "", "onequarter", "onehalf", "threequarters", "oneeighth", "threeeighths", "fiveeighths", "seveneighths", "onethird", "twothirds", "", "", "", "", "", "", "ff", "fi", "fl", "ffi", "ffl", "parenleftinferior", "", "parenrightinferior", "Circumflexsmall", "hypheninferior", "Gravesmall", "Asmall", "Bsmall", "Csmall", "Dsmall", "Esmall", "Fsmall", "Gsmall", "Hsmall", "Ismall", "Jsmall", "Ksmall", "Lsmall", "Msmall", "Nsmall", "Osmall", "Psmall", "Qsmall", "Rsmall", "Ssmall", "Tsmall", "Usmall", "Vsmall", "Wsmall", "Xsmall", "Ysmall", "Zsmall", "colonmonetary", "onefitted", "rupiah", "Tildesmall", "", "", "asuperior", "centsuperior", "", "", "", "", "Aacutesmall", "Agravesmall", "Acircumflexsmall", "Adieresissmall", "Atildesmall", "Aringsmall", "Ccedillasmall", "Eacutesmall", "Egravesmall", "Ecircumflexsmall", "Edieresissmall", "Iacutesmall", "Igravesmall", "Icircumflexsmall", "Idieresissmall", "Ntildesmall", "Oacutesmall", "Ogravesmall", "Ocircumflexsmall", "Odieresissmall", "Otildesmall", "Uacutesmall", "Ugravesmall", "Ucircumflexsmall", "Udieresissmall", "", "eightsuperior", "fourinferior", "threeinferior", "sixinferior", "eightinferior", "seveninferior", "Scaronsmall", "", "centinferior", "twoinferior", "", "Dieresissmall", "", "Caronsmall", "osuperior", "fiveinferior", "", "commainferior", "periodinferior", "Yacutesmall", "", "dollarinferior", "", "", "Thornsmall", "", "nineinferior", "zeroinferior", "Zcaronsmall", "AEsmall", "Oslashsmall", "questiondownsmall", "oneinferior", "Lslashsmall", "", "", "", "", "", "", "Cedillasmall", "", "", "", "", "", "OEsmall", "figuredash", "hyphensuperior", "", "", "", "", "exclamdownsmall", "", "Ydieresissmall", "", "onesuperior", "twosuperior", "threesuperior", "foursuperior", "fivesuperior", "sixsuperior", "sevensuperior", "ninesuperior", "zerosuperior", "", "esuperior", "rsuperior", "tsuperior", "", "", "isuperior", "ssuperior", "dsuperior", "", "", "", "", "", "lsuperior", "Ogoneksmall", "Brevesmall", "Macronsmall", "bsuperior", "nsuperior", "msuperior", "commasuperior", "periodsuperior", "Dotaccentsmall", "Ringsmall", "", "", "", ""];
+const MacRomanEncoding = ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "space", "exclam", "quotedbl", "numbersign", "dollar", "percent", "ampersand", "quotesingle", "parenleft", "parenright", "asterisk", "plus", "comma", "hyphen", "period", "slash", "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "colon", "semicolon", "less", "equal", "greater", "question", "at", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "bracketleft", "backslash", "bracketright", "asciicircum", "underscore", "grave", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "braceleft", "bar", "braceright", "asciitilde", "", "Adieresis", "Aring", "Ccedilla", "Eacute", "Ntilde", "Odieresis", "Udieresis", "aacute", "agrave", "acircumflex", "adieresis", "atilde", "aring", "ccedilla", "eacute", "egrave", "ecircumflex", "edieresis", "iacute", "igrave", "icircumflex", "idieresis", "ntilde", "oacute", "ograve", "ocircumflex", "odieresis", "otilde", "uacute", "ugrave", "ucircumflex", "udieresis", "dagger", "degree", "cent", "sterling", "section", "bullet", "paragraph", "germandbls", "registered", "copyright", "trademark", "acute", "dieresis", "notequal", "AE", "Oslash", "infinity", "plusminus", "lessequal", "greaterequal", "yen", "mu", "partialdiff", "summation", "product", "pi", "integral", "ordfeminine", "ordmasculine", "Omega", "ae", "oslash", "questiondown", "exclamdown", "logicalnot", "radical", "florin", "approxequal", "Delta", "guillemotleft", "guillemotright", "ellipsis", "space", "Agrave", "Atilde", "Otilde", "OE", "oe", "endash", "emdash", "quotedblleft", "quotedblright", "quoteleft", "quoteright", "divide", "lozenge", "ydieresis", "Ydieresis", "fraction", "currency", "guilsinglleft", "guilsinglright", "fi", "fl", "daggerdbl", "periodcentered", "quotesinglbase", "quotedblbase", "perthousand", "Acircumflex", "Ecircumflex", "Aacute", "Edieresis", "Egrave", "Iacute", "Icircumflex", "Idieresis", "Igrave", "Oacute", "Ocircumflex", "apple", "Ograve", "Uacute", "Ucircumflex", "Ugrave", "dotlessi", "circumflex", "tilde", "macron", "breve", "dotaccent", "ring", "cedilla", "hungarumlaut", "ogonek", "caron"];
+const StandardEncoding = ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "space", "exclam", "quotedbl", "numbersign", "dollar", "percent", "ampersand", "quoteright", "parenleft", "parenright", "asterisk", "plus", "comma", "hyphen", "period", "slash", "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "colon", "semicolon", "less", "equal", "greater", "question", "at", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "bracketleft", "backslash", "bracketright", "asciicircum", "underscore", "quoteleft", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "braceleft", "bar", "braceright", "asciitilde", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "exclamdown", "cent", "sterling", "fraction", "yen", "florin", "section", "currency", "quotesingle", "quotedblleft", "guillemotleft", "guilsinglleft", "guilsinglright", "fi", "fl", "", "endash", "dagger", "daggerdbl", "periodcentered", "", "paragraph", "bullet", "quotesinglbase", "quotedblbase", "quotedblright", "guillemotright", "ellipsis", "perthousand", "", "questiondown", "", "grave", "acute", "circumflex", "tilde", "macron", "breve", "dotaccent", "dieresis", "", "ring", "cedilla", "", "hungarumlaut", "ogonek", "caron", "emdash", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "AE", "", "ordfeminine", "", "", "", "", "Lslash", "Oslash", "OE", "ordmasculine", "", "", "", "", "", "ae", "", "", "", "dotlessi", "", "", "lslash", "oslash", "oe", "germandbls", "", "", "", ""];
+const WinAnsiEncoding = ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "space", "exclam", "quotedbl", "numbersign", "dollar", "percent", "ampersand", "quotesingle", "parenleft", "parenright", "asterisk", "plus", "comma", "hyphen", "period", "slash", "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "colon", "semicolon", "less", "equal", "greater", "question", "at", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "bracketleft", "backslash", "bracketright", "asciicircum", "underscore", "grave", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "braceleft", "bar", "braceright", "asciitilde", "bullet", "Euro", "bullet", "quotesinglbase", "florin", "quotedblbase", "ellipsis", "dagger", "daggerdbl", "circumflex", "perthousand", "Scaron", "guilsinglleft", "OE", "bullet", "Zcaron", "bullet", "bullet", "quoteleft", "quoteright", "quotedblleft", "quotedblright", "bullet", "endash", "emdash", "tilde", "trademark", "scaron", "guilsinglright", "oe", "bullet", "zcaron", "Ydieresis", "space", "exclamdown", "cent", "sterling", "currency", "yen", "brokenbar", "section", "dieresis", "copyright", "ordfeminine", "guillemotleft", "logicalnot", "hyphen", "registered", "macron", "degree", "plusminus", "twosuperior", "threesuperior", "acute", "mu", "paragraph", "periodcentered", "cedilla", "onesuperior", "ordmasculine", "guillemotright", "onequarter", "onehalf", "threequarters", "questiondown", "Agrave", "Aacute", "Acircumflex", "Atilde", "Adieresis", "Aring", "AE", "Ccedilla", "Egrave", "Eacute", "Ecircumflex", "Edieresis", "Igrave", "Iacute", "Icircumflex", "Idieresis", "Eth", "Ntilde", "Ograve", "Oacute", "Ocircumflex", "Otilde", "Odieresis", "multiply", "Oslash", "Ugrave", "Uacute", "Ucircumflex", "Udieresis", "Yacute", "Thorn", "germandbls", "agrave", "aacute", "acircumflex", "atilde", "adieresis", "aring", "ae", "ccedilla", "egrave", "eacute", "ecircumflex", "edieresis", "igrave", "iacute", "icircumflex", "idieresis", "eth", "ntilde", "ograve", "oacute", "ocircumflex", "otilde", "odieresis", "divide", "oslash", "ugrave", "uacute", "ucircumflex", "udieresis", "yacute", "thorn", "ydieresis"];
+const SymbolSetEncoding = ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "space", "exclam", "universal", "numbersign", "existential", "percent", "ampersand", "suchthat", "parenleft", "parenright", "asteriskmath", "plus", "comma", "minus", "period", "slash", "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "colon", "semicolon", "less", "equal", "greater", "question", "congruent", "Alpha", "Beta", "Chi", "Delta", "Epsilon", "Phi", "Gamma", "Eta", "Iota", "theta1", "Kappa", "Lambda", "Mu", "Nu", "Omicron", "Pi", "Theta", "Rho", "Sigma", "Tau", "Upsilon", "sigma1", "Omega", "Xi", "Psi", "Zeta", "bracketleft", "therefore", "bracketright", "perpendicular", "underscore", "radicalex", "alpha", "beta", "chi", "delta", "epsilon", "phi", "gamma", "eta", "iota", "phi1", "kappa", "lambda", "mu", "nu", "omicron", "pi", "theta", "rho", "sigma", "tau", "upsilon", "omega1", "omega", "xi", "psi", "zeta", "braceleft", "bar", "braceright", "similar", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "Euro", "Upsilon1", "minute", "lessequal", "fraction", "infinity", "florin", "club", "diamond", "heart", "spade", "arrowboth", "arrowleft", "arrowup", "arrowright", "arrowdown", "degree", "plusminus", "second", "greaterequal", "multiply", "proportional", "partialdiff", "bullet", "divide", "notequal", "equivalence", "approxequal", "ellipsis", "arrowvertex", "arrowhorizex", "carriagereturn", "aleph", "Ifraktur", "Rfraktur", "weierstrass", "circlemultiply", "circleplus", "emptyset", "intersection", "union", "propersuperset", "reflexsuperset", "notsubset", "propersubset", "reflexsubset", "element", "notelement", "angle", "gradient", "registerserif", "copyrightserif", "trademarkserif", "product", "radical", "dotmath", "logicalnot", "logicaland", "logicalor", "arrowdblboth", "arrowdblleft", "arrowdblup", "arrowdblright", "arrowdbldown", "lozenge", "angleleft", "registersans", "copyrightsans", "trademarksans", "summation", "parenlefttp", "parenleftex", "parenleftbt", "bracketlefttp", "bracketleftex", "bracketleftbt", "bracelefttp", "braceleftmid", "braceleftbt", "braceex", "", "angleright", "integral", "integraltp", "integralex", "integralbt", "parenrighttp", "parenrightex", "parenrightbt", "bracketrighttp", "bracketrightex", "bracketrightbt", "bracerighttp", "bracerightmid", "bracerightbt", ""];
+const ZapfDingbatsEncoding = ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "space", "a1", "a2", "a202", "a3", "a4", "a5", "a119", "a118", "a117", "a11", "a12", "a13", "a14", "a15", "a16", "a105", "a17", "a18", "a19", "a20", "a21", "a22", "a23", "a24", "a25", "a26", "a27", "a28", "a6", "a7", "a8", "a9", "a10", "a29", "a30", "a31", "a32", "a33", "a34", "a35", "a36", "a37", "a38", "a39", "a40", "a41", "a42", "a43", "a44", "a45", "a46", "a47", "a48", "a49", "a50", "a51", "a52", "a53", "a54", "a55", "a56", "a57", "a58", "a59", "a60", "a61", "a62", "a63", "a64", "a65", "a66", "a67", "a68", "a69", "a70", "a71", "a72", "a73", "a74", "a203", "a75", "a204", "a76", "a77", "a78", "a79", "a81", "a82", "a83", "a84", "a97", "a98", "a99", "a100", "", "a89", "a90", "a93", "a94", "a91", "a92", "a205", "a85", "a206", "a86", "a87", "a88", "a95", "a96", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "a101", "a102", "a103", "a104", "a106", "a107", "a108", "a112", "a111", "a110", "a109", "a120", "a121", "a122", "a123", "a124", "a125", "a126", "a127", "a128", "a129", "a130", "a131", "a132", "a133", "a134", "a135", "a136", "a137", "a138", "a139", "a140", "a141", "a142", "a143", "a144", "a145", "a146", "a147", "a148", "a149", "a150", "a151", "a152", "a153", "a154", "a155", "a156", "a157", "a158", "a159", "a160", "a161", "a163", "a164", "a196", "a165", "a192", "a166", "a167", "a168", "a169", "a170", "a171", "a172", "a173", "a162", "a174", "a175", "a176", "a177", "a178", "a179", "a193", "a180", "a199", "a181", "a200", "a182", "", "a201", "a183", "a184", "a197", "a185", "a194", "a198", "a186", "a195", "a187", "a188", "a189", "a190", "a191", ""];
+function getEncoding(encodingName) {
+ switch (encodingName) {
+ case "WinAnsiEncoding":
+ return WinAnsiEncoding;
+ case "StandardEncoding":
+ return StandardEncoding;
+ case "MacRomanEncoding":
+ return MacRomanEncoding;
+ case "SymbolSetEncoding":
+ return SymbolSetEncoding;
+ case "ZapfDingbatsEncoding":
+ return ZapfDingbatsEncoding;
+ case "ExpertEncoding":
+ return ExpertEncoding;
+ case "MacExpertEncoding":
+ return MacExpertEncoding;
+ default:
+ return null;
+ }
+}
+
+;// CONCATENATED MODULE: ./src/core/cff_parser.js
+
+
+
+const MAX_SUBR_NESTING = 10;
+const CFFStandardStrings = [".notdef", "space", "exclam", "quotedbl", "numbersign", "dollar", "percent", "ampersand", "quoteright", "parenleft", "parenright", "asterisk", "plus", "comma", "hyphen", "period", "slash", "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "colon", "semicolon", "less", "equal", "greater", "question", "at", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "bracketleft", "backslash", "bracketright", "asciicircum", "underscore", "quoteleft", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "braceleft", "bar", "braceright", "asciitilde", "exclamdown", "cent", "sterling", "fraction", "yen", "florin", "section", "currency", "quotesingle", "quotedblleft", "guillemotleft", "guilsinglleft", "guilsinglright", "fi", "fl", "endash", "dagger", "daggerdbl", "periodcentered", "paragraph", "bullet", "quotesinglbase", "quotedblbase", "quotedblright", "guillemotright", "ellipsis", "perthousand", "questiondown", "grave", "acute", "circumflex", "tilde", "macron", "breve", "dotaccent", "dieresis", "ring", "cedilla", "hungarumlaut", "ogonek", "caron", "emdash", "AE", "ordfeminine", "Lslash", "Oslash", "OE", "ordmasculine", "ae", "dotlessi", "lslash", "oslash", "oe", "germandbls", "onesuperior", "logicalnot", "mu", "trademark", "Eth", "onehalf", "plusminus", "Thorn", "onequarter", "divide", "brokenbar", "degree", "thorn", "threequarters", "twosuperior", "registered", "minus", "eth", "multiply", "threesuperior", "copyright", "Aacute", "Acircumflex", "Adieresis", "Agrave", "Aring", "Atilde", "Ccedilla", "Eacute", "Ecircumflex", "Edieresis", "Egrave", "Iacute", "Icircumflex", "Idieresis", "Igrave", "Ntilde", "Oacute", "Ocircumflex", "Odieresis", "Ograve", "Otilde", "Scaron", "Uacute", "Ucircumflex", "Udieresis", "Ugrave", "Yacute", "Ydieresis", "Zcaron", "aacute", "acircumflex", "adieresis", "agrave", "aring", "atilde", "ccedilla", "eacute", "ecircumflex", "edieresis", "egrave", "iacute", "icircumflex", "idieresis", "igrave", "ntilde", "oacute", "ocircumflex", "odieresis", "ograve", "otilde", "scaron", "uacute", "ucircumflex", "udieresis", "ugrave", "yacute", "ydieresis", "zcaron", "exclamsmall", "Hungarumlautsmall", "dollaroldstyle", "dollarsuperior", "ampersandsmall", "Acutesmall", "parenleftsuperior", "parenrightsuperior", "twodotenleader", "onedotenleader", "zerooldstyle", "oneoldstyle", "twooldstyle", "threeoldstyle", "fouroldstyle", "fiveoldstyle", "sixoldstyle", "sevenoldstyle", "eightoldstyle", "nineoldstyle", "commasuperior", "threequartersemdash", "periodsuperior", "questionsmall", "asuperior", "bsuperior", "centsuperior", "dsuperior", "esuperior", "isuperior", "lsuperior", "msuperior", "nsuperior", "osuperior", "rsuperior", "ssuperior", "tsuperior", "ff", "ffi", "ffl", "parenleftinferior", "parenrightinferior", "Circumflexsmall", "hyphensuperior", "Gravesmall", "Asmall", "Bsmall", "Csmall", "Dsmall", "Esmall", "Fsmall", "Gsmall", "Hsmall", "Ismall", "Jsmall", "Ksmall", "Lsmall", "Msmall", "Nsmall", "Osmall", "Psmall", "Qsmall", "Rsmall", "Ssmall", "Tsmall", "Usmall", "Vsmall", "Wsmall", "Xsmall", "Ysmall", "Zsmall", "colonmonetary", "onefitted", "rupiah", "Tildesmall", "exclamdownsmall", "centoldstyle", "Lslashsmall", "Scaronsmall", "Zcaronsmall", "Dieresissmall", "Brevesmall", "Caronsmall", "Dotaccentsmall", "Macronsmall", "figuredash", "hypheninferior", "Ogoneksmall", "Ringsmall", "Cedillasmall", "questiondownsmall", "oneeighth", "threeeighths", "fiveeighths", "seveneighths", "onethird", "twothirds", "zerosuperior", "foursuperior", "fivesuperior", "sixsuperior", "sevensuperior", "eightsuperior", "ninesuperior", "zeroinferior", "oneinferior", "twoinferior", "threeinferior", "fourinferior", "fiveinferior", "sixinferior", "seveninferior", "eightinferior", "nineinferior", "centinferior", "dollarinferior", "periodinferior", "commainferior", "Agravesmall", "Aacutesmall", "Acircumflexsmall", "Atildesmall", "Adieresissmall", "Aringsmall", "AEsmall", "Ccedillasmall", "Egravesmall", "Eacutesmall", "Ecircumflexsmall", "Edieresissmall", "Igravesmall", "Iacutesmall", "Icircumflexsmall", "Idieresissmall", "Ethsmall", "Ntildesmall", "Ogravesmall", "Oacutesmall", "Ocircumflexsmall", "Otildesmall", "Odieresissmall", "OEsmall", "Oslashsmall", "Ugravesmall", "Uacutesmall", "Ucircumflexsmall", "Udieresissmall", "Yacutesmall", "Thornsmall", "Ydieresissmall", "001.000", "001.001", "001.002", "001.003", "Black", "Bold", "Book", "Light", "Medium", "Regular", "Roman", "Semibold"];
+const NUM_STANDARD_CFF_STRINGS = 391;
+const CharstringValidationData = [null, {
+ id: "hstem",
+ min: 2,
+ stackClearing: true,
+ stem: true
+}, null, {
+ id: "vstem",
+ min: 2,
+ stackClearing: true,
+ stem: true
+}, {
+ id: "vmoveto",
+ min: 1,
+ stackClearing: true
+}, {
+ id: "rlineto",
+ min: 2,
+ resetStack: true
+}, {
+ id: "hlineto",
+ min: 1,
+ resetStack: true
+}, {
+ id: "vlineto",
+ min: 1,
+ resetStack: true
+}, {
+ id: "rrcurveto",
+ min: 6,
+ resetStack: true
+}, null, {
+ id: "callsubr",
+ min: 1,
+ undefStack: true
+}, {
+ id: "return",
+ min: 0,
+ undefStack: true
+}, null, null, {
+ id: "endchar",
+ min: 0,
+ stackClearing: true
+}, null, null, null, {
+ id: "hstemhm",
+ min: 2,
+ stackClearing: true,
+ stem: true
+}, {
+ id: "hintmask",
+ min: 0,
+ stackClearing: true
+}, {
+ id: "cntrmask",
+ min: 0,
+ stackClearing: true
+}, {
+ id: "rmoveto",
+ min: 2,
+ stackClearing: true
+}, {
+ id: "hmoveto",
+ min: 1,
+ stackClearing: true
+}, {
+ id: "vstemhm",
+ min: 2,
+ stackClearing: true,
+ stem: true
+}, {
+ id: "rcurveline",
+ min: 8,
+ resetStack: true
+}, {
+ id: "rlinecurve",
+ min: 8,
+ resetStack: true
+}, {
+ id: "vvcurveto",
+ min: 4,
+ resetStack: true
+}, {
+ id: "hhcurveto",
+ min: 4,
+ resetStack: true
+}, null, {
+ id: "callgsubr",
+ min: 1,
+ undefStack: true
+}, {
+ id: "vhcurveto",
+ min: 4,
+ resetStack: true
+}, {
+ id: "hvcurveto",
+ min: 4,
+ resetStack: true
+}];
+const CharstringValidationData12 = [null, null, null, {
+ id: "and",
+ min: 2,
+ stackDelta: -1
+}, {
+ id: "or",
+ min: 2,
+ stackDelta: -1
+}, {
+ id: "not",
+ min: 1,
+ stackDelta: 0
+}, null, null, null, {
+ id: "abs",
+ min: 1,
+ stackDelta: 0
+}, {
+ id: "add",
+ min: 2,
+ stackDelta: -1,
+ stackFn(stack, index) {
+ stack[index - 2] = stack[index - 2] + stack[index - 1];
+ }
+}, {
+ id: "sub",
+ min: 2,
+ stackDelta: -1,
+ stackFn(stack, index) {
+ stack[index - 2] = stack[index - 2] - stack[index - 1];
+ }
+}, {
+ id: "div",
+ min: 2,
+ stackDelta: -1,
+ stackFn(stack, index) {
+ stack[index - 2] = stack[index - 2] / stack[index - 1];
+ }
+}, null, {
+ id: "neg",
+ min: 1,
+ stackDelta: 0,
+ stackFn(stack, index) {
+ stack[index - 1] = -stack[index - 1];
+ }
+}, {
+ id: "eq",
+ min: 2,
+ stackDelta: -1
+}, null, null, {
+ id: "drop",
+ min: 1,
+ stackDelta: -1
+}, null, {
+ id: "put",
+ min: 2,
+ stackDelta: -2
+}, {
+ id: "get",
+ min: 1,
+ stackDelta: 0
+}, {
+ id: "ifelse",
+ min: 4,
+ stackDelta: -3
+}, {
+ id: "random",
+ min: 0,
+ stackDelta: 1
+}, {
+ id: "mul",
+ min: 2,
+ stackDelta: -1,
+ stackFn(stack, index) {
+ stack[index - 2] = stack[index - 2] * stack[index - 1];
+ }
+}, null, {
+ id: "sqrt",
+ min: 1,
+ stackDelta: 0
+}, {
+ id: "dup",
+ min: 1,
+ stackDelta: 1
+}, {
+ id: "exch",
+ min: 2,
+ stackDelta: 0
+}, {
+ id: "index",
+ min: 2,
+ stackDelta: 0
+}, {
+ id: "roll",
+ min: 3,
+ stackDelta: -2
+}, null, null, null, {
+ id: "hflex",
+ min: 7,
+ resetStack: true
+}, {
+ id: "flex",
+ min: 13,
+ resetStack: true
+}, {
+ id: "hflex1",
+ min: 9,
+ resetStack: true
+}, {
+ id: "flex1",
+ min: 11,
+ resetStack: true
+}];
+class CFFParser {
+ constructor(file, properties, seacAnalysisEnabled) {
+ this.bytes = file.getBytes();
+ this.properties = properties;
+ this.seacAnalysisEnabled = !!seacAnalysisEnabled;
+ }
+ parse() {
+ const properties = this.properties;
+ const cff = new CFF();
+ this.cff = cff;
+ const header = this.parseHeader();
+ const nameIndex = this.parseIndex(header.endPos);
+ const topDictIndex = this.parseIndex(nameIndex.endPos);
+ const stringIndex = this.parseIndex(topDictIndex.endPos);
+ const globalSubrIndex = this.parseIndex(stringIndex.endPos);
+ const topDictParsed = this.parseDict(topDictIndex.obj.get(0));
+ const topDict = this.createDict(CFFTopDict, topDictParsed, cff.strings);
+ cff.header = header.obj;
+ cff.names = this.parseNameIndex(nameIndex.obj);
+ cff.strings = this.parseStringIndex(stringIndex.obj);
+ cff.topDict = topDict;
+ cff.globalSubrIndex = globalSubrIndex.obj;
+ this.parsePrivateDict(cff.topDict);
+ cff.isCIDFont = topDict.hasName("ROS");
+ const charStringOffset = topDict.getByName("CharStrings");
+ const charStringIndex = this.parseIndex(charStringOffset).obj;
+ const fontMatrix = topDict.getByName("FontMatrix");
+ if (fontMatrix) {
+ properties.fontMatrix = fontMatrix;
+ }
+ const fontBBox = topDict.getByName("FontBBox");
+ if (fontBBox) {
+ properties.ascent = Math.max(fontBBox[3], fontBBox[1]);
+ properties.descent = Math.min(fontBBox[1], fontBBox[3]);
+ properties.ascentScaled = true;
+ }
+ let charset, encoding;
+ if (cff.isCIDFont) {
+ const fdArrayIndex = this.parseIndex(topDict.getByName("FDArray")).obj;
+ for (let i = 0, ii = fdArrayIndex.count; i < ii; ++i) {
+ const dictRaw = fdArrayIndex.get(i);
+ const fontDict = this.createDict(CFFTopDict, this.parseDict(dictRaw), cff.strings);
+ this.parsePrivateDict(fontDict);
+ cff.fdArray.push(fontDict);
+ }
+ encoding = null;
+ charset = this.parseCharsets(topDict.getByName("charset"), charStringIndex.count, cff.strings, true);
+ cff.fdSelect = this.parseFDSelect(topDict.getByName("FDSelect"), charStringIndex.count);
+ } else {
+ charset = this.parseCharsets(topDict.getByName("charset"), charStringIndex.count, cff.strings, false);
+ encoding = this.parseEncoding(topDict.getByName("Encoding"), properties, cff.strings, charset.charset);
+ }
+ cff.charset = charset;
+ cff.encoding = encoding;
+ const charStringsAndSeacs = this.parseCharStrings({
+ charStrings: charStringIndex,
+ localSubrIndex: topDict.privateDict.subrsIndex,
+ globalSubrIndex: globalSubrIndex.obj,
+ fdSelect: cff.fdSelect,
+ fdArray: cff.fdArray,
+ privateDict: topDict.privateDict
+ });
+ cff.charStrings = charStringsAndSeacs.charStrings;
+ cff.seacs = charStringsAndSeacs.seacs;
+ cff.widths = charStringsAndSeacs.widths;
+ return cff;
+ }
+ parseHeader() {
+ let bytes = this.bytes;
+ const bytesLength = bytes.length;
+ let offset = 0;
+ while (offset < bytesLength && bytes[offset] !== 1) {
+ ++offset;
+ }
+ if (offset >= bytesLength) {
+ throw new FormatError("Invalid CFF header");
+ }
+ if (offset !== 0) {
+ info("cff data is shifted");
+ bytes = bytes.subarray(offset);
+ this.bytes = bytes;
+ }
+ const major = bytes[0];
+ const minor = bytes[1];
+ const hdrSize = bytes[2];
+ const offSize = bytes[3];
+ const header = new CFFHeader(major, minor, hdrSize, offSize);
+ return {
+ obj: header,
+ endPos: hdrSize
+ };
+ }
+ parseDict(dict) {
+ let pos = 0;
+ function parseOperand() {
+ let value = dict[pos++];
+ if (value === 30) {
+ return parseFloatOperand();
+ } else if (value === 28) {
+ value = dict[pos++];
+ value = (value << 24 | dict[pos++] << 16) >> 16;
+ return value;
+ } else if (value === 29) {
+ value = dict[pos++];
+ value = value << 8 | dict[pos++];
+ value = value << 8 | dict[pos++];
+ value = value << 8 | dict[pos++];
+ return value;
+ } else if (value >= 32 && value <= 246) {
+ return value - 139;
+ } else if (value >= 247 && value <= 250) {
+ return (value - 247) * 256 + dict[pos++] + 108;
+ } else if (value >= 251 && value <= 254) {
+ return -((value - 251) * 256) - dict[pos++] - 108;
+ }
+ warn('CFFParser_parseDict: "' + value + '" is a reserved command.');
+ return NaN;
+ }
+ function parseFloatOperand() {
+ let str = "";
+ const eof = 15;
+ const lookup = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", ".", "E", "E-", null, "-"];
+ const length = dict.length;
+ while (pos < length) {
+ const b = dict[pos++];
+ const b1 = b >> 4;
+ const b2 = b & 15;
+ if (b1 === eof) {
+ break;
+ }
+ str += lookup[b1];
+ if (b2 === eof) {
+ break;
+ }
+ str += lookup[b2];
+ }
+ return parseFloat(str);
+ }
+ let operands = [];
+ const entries = [];
+ pos = 0;
+ const end = dict.length;
+ while (pos < end) {
+ let b = dict[pos];
+ if (b <= 21) {
+ if (b === 12) {
+ b = b << 8 | dict[++pos];
+ }
+ entries.push([b, operands]);
+ operands = [];
+ ++pos;
+ } else {
+ operands.push(parseOperand());
+ }
+ }
+ return entries;
+ }
+ parseIndex(pos) {
+ const cffIndex = new CFFIndex();
+ const bytes = this.bytes;
+ const count = bytes[pos++] << 8 | bytes[pos++];
+ const offsets = [];
+ let end = pos;
+ let i, ii;
+ if (count !== 0) {
+ const offsetSize = bytes[pos++];
+ const startPos = pos + (count + 1) * offsetSize - 1;
+ for (i = 0, ii = count + 1; i < ii; ++i) {
+ let offset = 0;
+ for (let j = 0; j < offsetSize; ++j) {
+ offset <<= 8;
+ offset += bytes[pos++];
+ }
+ offsets.push(startPos + offset);
+ }
+ end = offsets[count];
+ }
+ for (i = 0, ii = offsets.length - 1; i < ii; ++i) {
+ const offsetStart = offsets[i];
+ const offsetEnd = offsets[i + 1];
+ cffIndex.add(bytes.subarray(offsetStart, offsetEnd));
+ }
+ return {
+ obj: cffIndex,
+ endPos: end
+ };
+ }
+ parseNameIndex(index) {
+ const names = [];
+ for (let i = 0, ii = index.count; i < ii; ++i) {
+ const name = index.get(i);
+ names.push(bytesToString(name));
+ }
+ return names;
+ }
+ parseStringIndex(index) {
+ const strings = new CFFStrings();
+ for (let i = 0, ii = index.count; i < ii; ++i) {
+ const data = index.get(i);
+ strings.add(bytesToString(data));
+ }
+ return strings;
+ }
+ createDict(Type, dict, strings) {
+ const cffDict = new Type(strings);
+ for (const [key, value] of dict) {
+ cffDict.setByKey(key, value);
+ }
+ return cffDict;
+ }
+ parseCharString(state, data, localSubrIndex, globalSubrIndex) {
+ if (!data || state.callDepth > MAX_SUBR_NESTING) {
+ return false;
+ }
+ let stackSize = state.stackSize;
+ const stack = state.stack;
+ let length = data.length;
+ for (let j = 0; j < length;) {
+ const value = data[j++];
+ let validationCommand = null;
+ if (value === 12) {
+ const q = data[j++];
+ if (q === 0) {
+ data[j - 2] = 139;
+ data[j - 1] = 22;
+ stackSize = 0;
+ } else {
+ validationCommand = CharstringValidationData12[q];
+ }
+ } else if (value === 28) {
+ stack[stackSize] = (data[j] << 24 | data[j + 1] << 16) >> 16;
+ j += 2;
+ stackSize++;
+ } else if (value === 14) {
+ if (stackSize >= 4) {
+ stackSize -= 4;
+ if (this.seacAnalysisEnabled) {
+ state.seac = stack.slice(stackSize, stackSize + 4);
+ return false;
+ }
+ }
+ validationCommand = CharstringValidationData[value];
+ } else if (value >= 32 && value <= 246) {
+ stack[stackSize] = value - 139;
+ stackSize++;
+ } else if (value >= 247 && value <= 254) {
+ stack[stackSize] = value < 251 ? (value - 247 << 8) + data[j] + 108 : -(value - 251 << 8) - data[j] - 108;
+ j++;
+ stackSize++;
+ } else if (value === 255) {
+ stack[stackSize] = (data[j] << 24 | data[j + 1] << 16 | data[j + 2] << 8 | data[j + 3]) / 65536;
+ j += 4;
+ stackSize++;
+ } else if (value === 19 || value === 20) {
+ state.hints += stackSize >> 1;
+ if (state.hints === 0) {
+ data.copyWithin(j - 1, j, -1);
+ j -= 1;
+ length -= 1;
+ continue;
+ }
+ j += state.hints + 7 >> 3;
+ stackSize %= 2;
+ validationCommand = CharstringValidationData[value];
+ } else if (value === 10 || value === 29) {
+ const subrsIndex = value === 10 ? localSubrIndex : globalSubrIndex;
+ if (!subrsIndex) {
+ validationCommand = CharstringValidationData[value];
+ warn("Missing subrsIndex for " + validationCommand.id);
+ return false;
+ }
+ let bias = 32768;
+ if (subrsIndex.count < 1240) {
+ bias = 107;
+ } else if (subrsIndex.count < 33900) {
+ bias = 1131;
+ }
+ const subrNumber = stack[--stackSize] + bias;
+ if (subrNumber < 0 || subrNumber >= subrsIndex.count || isNaN(subrNumber)) {
+ validationCommand = CharstringValidationData[value];
+ warn("Out of bounds subrIndex for " + validationCommand.id);
+ return false;
+ }
+ state.stackSize = stackSize;
+ state.callDepth++;
+ const valid = this.parseCharString(state, subrsIndex.get(subrNumber), localSubrIndex, globalSubrIndex);
+ if (!valid) {
+ return false;
+ }
+ state.callDepth--;
+ stackSize = state.stackSize;
+ continue;
+ } else if (value === 11) {
+ state.stackSize = stackSize;
+ return true;
+ } else if (value === 0 && j === data.length) {
+ data[j - 1] = 14;
+ validationCommand = CharstringValidationData[14];
+ } else if (value === 9) {
+ data.copyWithin(j - 1, j, -1);
+ j -= 1;
+ length -= 1;
+ continue;
+ } else {
+ validationCommand = CharstringValidationData[value];
+ }
+ if (validationCommand) {
+ if (validationCommand.stem) {
+ state.hints += stackSize >> 1;
+ if (value === 3 || value === 23) {
+ state.hasVStems = true;
+ } else if (state.hasVStems && (value === 1 || value === 18)) {
+ warn("CFF stem hints are in wrong order");
+ data[j - 1] = value === 1 ? 3 : 23;
+ }
+ }
+ if ("min" in validationCommand) {
+ if (!state.undefStack && stackSize < validationCommand.min) {
+ warn("Not enough parameters for " + validationCommand.id + "; actual: " + stackSize + ", expected: " + validationCommand.min);
+ if (stackSize === 0) {
+ data[j - 1] = 14;
+ return true;
+ }
+ return false;
+ }
+ }
+ if (state.firstStackClearing && validationCommand.stackClearing) {
+ state.firstStackClearing = false;
+ stackSize -= validationCommand.min;
+ if (stackSize >= 2 && validationCommand.stem) {
+ stackSize %= 2;
+ } else if (stackSize > 1) {
+ warn("Found too many parameters for stack-clearing command");
+ }
+ if (stackSize > 0) {
+ state.width = stack[stackSize - 1];
+ }
+ }
+ if ("stackDelta" in validationCommand) {
+ if ("stackFn" in validationCommand) {
+ validationCommand.stackFn(stack, stackSize);
+ }
+ stackSize += validationCommand.stackDelta;
+ } else if (validationCommand.stackClearing) {
+ stackSize = 0;
+ } else if (validationCommand.resetStack) {
+ stackSize = 0;
+ state.undefStack = false;
+ } else if (validationCommand.undefStack) {
+ stackSize = 0;
+ state.undefStack = true;
+ state.firstStackClearing = false;
+ }
+ }
+ }
+ if (length < data.length) {
+ data.fill(14, length);
+ }
+ state.stackSize = stackSize;
+ return true;
+ }
+ parseCharStrings({
+ charStrings,
+ localSubrIndex,
+ globalSubrIndex,
+ fdSelect,
+ fdArray,
+ privateDict
+ }) {
+ const seacs = [];
+ const widths = [];
+ const count = charStrings.count;
+ for (let i = 0; i < count; i++) {
+ const charstring = charStrings.get(i);
+ const state = {
+ callDepth: 0,
+ stackSize: 0,
+ stack: [],
+ undefStack: true,
+ hints: 0,
+ firstStackClearing: true,
+ seac: null,
+ width: null,
+ hasVStems: false
+ };
+ let valid = true;
+ let localSubrToUse = null;
+ let privateDictToUse = privateDict;
+ if (fdSelect && fdArray.length) {
+ const fdIndex = fdSelect.getFDIndex(i);
+ if (fdIndex === -1) {
+ warn("Glyph index is not in fd select.");
+ valid = false;
+ }
+ if (fdIndex >= fdArray.length) {
+ warn("Invalid fd index for glyph index.");
+ valid = false;
+ }
+ if (valid) {
+ privateDictToUse = fdArray[fdIndex].privateDict;
+ localSubrToUse = privateDictToUse.subrsIndex;
+ }
+ } else if (localSubrIndex) {
+ localSubrToUse = localSubrIndex;
+ }
+ if (valid) {
+ valid = this.parseCharString(state, charstring, localSubrToUse, globalSubrIndex);
+ }
+ if (state.width !== null) {
+ const nominalWidth = privateDictToUse.getByName("nominalWidthX");
+ widths[i] = nominalWidth + state.width;
+ } else {
+ const defaultWidth = privateDictToUse.getByName("defaultWidthX");
+ widths[i] = defaultWidth;
+ }
+ if (state.seac !== null) {
+ seacs[i] = state.seac;
+ }
+ if (!valid) {
+ charStrings.set(i, new Uint8Array([14]));
+ }
+ }
+ return {
+ charStrings,
+ seacs,
+ widths
+ };
+ }
+ emptyPrivateDictionary(parentDict) {
+ const privateDict = this.createDict(CFFPrivateDict, [], parentDict.strings);
+ parentDict.setByKey(18, [0, 0]);
+ parentDict.privateDict = privateDict;
+ }
+ parsePrivateDict(parentDict) {
+ if (!parentDict.hasName("Private")) {
+ this.emptyPrivateDictionary(parentDict);
+ return;
+ }
+ const privateOffset = parentDict.getByName("Private");
+ if (!Array.isArray(privateOffset) || privateOffset.length !== 2) {
+ parentDict.removeByName("Private");
+ return;
+ }
+ const size = privateOffset[0];
+ const offset = privateOffset[1];
+ if (size === 0 || offset >= this.bytes.length) {
+ this.emptyPrivateDictionary(parentDict);
+ return;
+ }
+ const privateDictEnd = offset + size;
+ const dictData = this.bytes.subarray(offset, privateDictEnd);
+ const dict = this.parseDict(dictData);
+ const privateDict = this.createDict(CFFPrivateDict, dict, parentDict.strings);
+ parentDict.privateDict = privateDict;
+ if (privateDict.getByName("ExpansionFactor") === 0) {
+ privateDict.setByName("ExpansionFactor", 0.06);
+ }
+ if (!privateDict.getByName("Subrs")) {
+ return;
+ }
+ const subrsOffset = privateDict.getByName("Subrs");
+ const relativeOffset = offset + subrsOffset;
+ if (subrsOffset === 0 || relativeOffset >= this.bytes.length) {
+ this.emptyPrivateDictionary(parentDict);
+ return;
+ }
+ const subrsIndex = this.parseIndex(relativeOffset);
+ privateDict.subrsIndex = subrsIndex.obj;
+ }
+ parseCharsets(pos, length, strings, cid) {
+ if (pos === 0) {
+ return new CFFCharset(true, CFFCharsetPredefinedTypes.ISO_ADOBE, ISOAdobeCharset);
+ } else if (pos === 1) {
+ return new CFFCharset(true, CFFCharsetPredefinedTypes.EXPERT, ExpertCharset);
+ } else if (pos === 2) {
+ return new CFFCharset(true, CFFCharsetPredefinedTypes.EXPERT_SUBSET, ExpertSubsetCharset);
+ }
+ const bytes = this.bytes;
+ const start = pos;
+ const format = bytes[pos++];
+ const charset = [cid ? 0 : ".notdef"];
+ let id, count, i;
+ length -= 1;
+ switch (format) {
+ case 0:
+ for (i = 0; i < length; i++) {
+ id = bytes[pos++] << 8 | bytes[pos++];
+ charset.push(cid ? id : strings.get(id));
+ }
+ break;
+ case 1:
+ while (charset.length <= length) {
+ id = bytes[pos++] << 8 | bytes[pos++];
+ count = bytes[pos++];
+ for (i = 0; i <= count; i++) {
+ charset.push(cid ? id++ : strings.get(id++));
+ }
+ }
+ break;
+ case 2:
+ while (charset.length <= length) {
+ id = bytes[pos++] << 8 | bytes[pos++];
+ count = bytes[pos++] << 8 | bytes[pos++];
+ for (i = 0; i <= count; i++) {
+ charset.push(cid ? id++ : strings.get(id++));
+ }
+ }
+ break;
+ default:
+ throw new FormatError("Unknown charset format");
+ }
+ const end = pos;
+ const raw = bytes.subarray(start, end);
+ return new CFFCharset(false, format, charset, raw);
+ }
+ parseEncoding(pos, properties, strings, charset) {
+ const encoding = Object.create(null);
+ const bytes = this.bytes;
+ let predefined = false;
+ let format, i, ii;
+ let raw = null;
+ function readSupplement() {
+ const supplementsCount = bytes[pos++];
+ for (i = 0; i < supplementsCount; i++) {
+ const code = bytes[pos++];
+ const sid = (bytes[pos++] << 8) + (bytes[pos++] & 0xff);
+ encoding[code] = charset.indexOf(strings.get(sid));
+ }
+ }
+ if (pos === 0 || pos === 1) {
+ predefined = true;
+ format = pos;
+ const baseEncoding = pos ? ExpertEncoding : StandardEncoding;
+ for (i = 0, ii = charset.length; i < ii; i++) {
+ const index = baseEncoding.indexOf(charset[i]);
+ if (index !== -1) {
+ encoding[index] = i;
+ }
+ }
+ } else {
+ const dataStart = pos;
+ format = bytes[pos++];
+ switch (format & 0x7f) {
+ case 0:
+ const glyphsCount = bytes[pos++];
+ for (i = 1; i <= glyphsCount; i++) {
+ encoding[bytes[pos++]] = i;
+ }
+ break;
+ case 1:
+ const rangesCount = bytes[pos++];
+ let gid = 1;
+ for (i = 0; i < rangesCount; i++) {
+ const start = bytes[pos++];
+ const left = bytes[pos++];
+ for (let j = start; j <= start + left; j++) {
+ encoding[j] = gid++;
+ }
+ }
+ break;
+ default:
+ throw new FormatError(`Unknown encoding format: ${format} in CFF`);
+ }
+ const dataEnd = pos;
+ if (format & 0x80) {
+ bytes[dataStart] &= 0x7f;
+ readSupplement();
+ }
+ raw = bytes.subarray(dataStart, dataEnd);
+ }
+ format &= 0x7f;
+ return new CFFEncoding(predefined, format, encoding, raw);
+ }
+ parseFDSelect(pos, length) {
+ const bytes = this.bytes;
+ const format = bytes[pos++];
+ const fdSelect = [];
+ let i;
+ switch (format) {
+ case 0:
+ for (i = 0; i < length; ++i) {
+ const id = bytes[pos++];
+ fdSelect.push(id);
+ }
+ break;
+ case 3:
+ const rangesCount = bytes[pos++] << 8 | bytes[pos++];
+ for (i = 0; i < rangesCount; ++i) {
+ let first = bytes[pos++] << 8 | bytes[pos++];
+ if (i === 0 && first !== 0) {
+ warn("parseFDSelect: The first range must have a first GID of 0" + " -- trying to recover.");
+ first = 0;
+ }
+ const fdIndex = bytes[pos++];
+ const next = bytes[pos] << 8 | bytes[pos + 1];
+ for (let j = first; j < next; ++j) {
+ fdSelect.push(fdIndex);
+ }
+ }
+ pos += 2;
+ break;
+ default:
+ throw new FormatError(`parseFDSelect: Unknown format "${format}".`);
+ }
+ if (fdSelect.length !== length) {
+ throw new FormatError("parseFDSelect: Invalid font data.");
+ }
+ return new CFFFDSelect(format, fdSelect);
+ }
+}
+class CFF {
+ constructor() {
+ this.header = null;
+ this.names = [];
+ this.topDict = null;
+ this.strings = new CFFStrings();
+ this.globalSubrIndex = null;
+ this.encoding = null;
+ this.charset = null;
+ this.charStrings = null;
+ this.fdArray = [];
+ this.fdSelect = null;
+ this.isCIDFont = false;
+ }
+ duplicateFirstGlyph() {
+ if (this.charStrings.count >= 65535) {
+ warn("Not enough space in charstrings to duplicate first glyph.");
+ return;
+ }
+ const glyphZero = this.charStrings.get(0);
+ this.charStrings.add(glyphZero);
+ if (this.isCIDFont) {
+ this.fdSelect.fdSelect.push(this.fdSelect.fdSelect[0]);
+ }
+ }
+ hasGlyphId(id) {
+ if (id < 0 || id >= this.charStrings.count) {
+ return false;
+ }
+ const glyph = this.charStrings.get(id);
+ return glyph.length > 0;
+ }
+}
+class CFFHeader {
+ constructor(major, minor, hdrSize, offSize) {
+ this.major = major;
+ this.minor = minor;
+ this.hdrSize = hdrSize;
+ this.offSize = offSize;
+ }
+}
+class CFFStrings {
+ constructor() {
+ this.strings = [];
+ }
+ get(index) {
+ if (index >= 0 && index <= NUM_STANDARD_CFF_STRINGS - 1) {
+ return CFFStandardStrings[index];
+ }
+ if (index - NUM_STANDARD_CFF_STRINGS <= this.strings.length) {
+ return this.strings[index - NUM_STANDARD_CFF_STRINGS];
+ }
+ return CFFStandardStrings[0];
+ }
+ getSID(str) {
+ let index = CFFStandardStrings.indexOf(str);
+ if (index !== -1) {
+ return index;
+ }
+ index = this.strings.indexOf(str);
+ if (index !== -1) {
+ return index + NUM_STANDARD_CFF_STRINGS;
+ }
+ return -1;
+ }
+ add(value) {
+ this.strings.push(value);
+ }
+ get count() {
+ return this.strings.length;
+ }
+}
+class CFFIndex {
+ constructor() {
+ this.objects = [];
+ this.length = 0;
+ }
+ add(data) {
+ this.length += data.length;
+ this.objects.push(data);
+ }
+ set(index, data) {
+ this.length += data.length - this.objects[index].length;
+ this.objects[index] = data;
+ }
+ get(index) {
+ return this.objects[index];
+ }
+ get count() {
+ return this.objects.length;
+ }
+}
+class CFFDict {
+ constructor(tables, strings) {
+ this.keyToNameMap = tables.keyToNameMap;
+ this.nameToKeyMap = tables.nameToKeyMap;
+ this.defaults = tables.defaults;
+ this.types = tables.types;
+ this.opcodes = tables.opcodes;
+ this.order = tables.order;
+ this.strings = strings;
+ this.values = Object.create(null);
+ }
+ setByKey(key, value) {
+ if (!(key in this.keyToNameMap)) {
+ return false;
+ }
+ if (value.length === 0) {
+ return true;
+ }
+ for (const val of value) {
+ if (isNaN(val)) {
+ warn(`Invalid CFFDict value: "${value}" for key "${key}".`);
+ return true;
+ }
+ }
+ const type = this.types[key];
+ if (type === "num" || type === "sid" || type === "offset") {
+ value = value[0];
+ }
+ this.values[key] = value;
+ return true;
+ }
+ setByName(name, value) {
+ if (!(name in this.nameToKeyMap)) {
+ throw new FormatError(`Invalid dictionary name "${name}"`);
+ }
+ this.values[this.nameToKeyMap[name]] = value;
+ }
+ hasName(name) {
+ return this.nameToKeyMap[name] in this.values;
+ }
+ getByName(name) {
+ if (!(name in this.nameToKeyMap)) {
+ throw new FormatError(`Invalid dictionary name ${name}"`);
+ }
+ const key = this.nameToKeyMap[name];
+ if (!(key in this.values)) {
+ return this.defaults[key];
+ }
+ return this.values[key];
+ }
+ removeByName(name) {
+ delete this.values[this.nameToKeyMap[name]];
+ }
+ static createTables(layout) {
+ const tables = {
+ keyToNameMap: {},
+ nameToKeyMap: {},
+ defaults: {},
+ types: {},
+ opcodes: {},
+ order: []
+ };
+ for (const entry of layout) {
+ const key = Array.isArray(entry[0]) ? (entry[0][0] << 8) + entry[0][1] : entry[0];
+ tables.keyToNameMap[key] = entry[1];
+ tables.nameToKeyMap[entry[1]] = key;
+ tables.types[key] = entry[2];
+ tables.defaults[key] = entry[3];
+ tables.opcodes[key] = Array.isArray(entry[0]) ? entry[0] : [entry[0]];
+ tables.order.push(key);
+ }
+ return tables;
+ }
+}
+const CFFTopDictLayout = [[[12, 30], "ROS", ["sid", "sid", "num"], null], [[12, 20], "SyntheticBase", "num", null], [0, "version", "sid", null], [1, "Notice", "sid", null], [[12, 0], "Copyright", "sid", null], [2, "FullName", "sid", null], [3, "FamilyName", "sid", null], [4, "Weight", "sid", null], [[12, 1], "isFixedPitch", "num", 0], [[12, 2], "ItalicAngle", "num", 0], [[12, 3], "UnderlinePosition", "num", -100], [[12, 4], "UnderlineThickness", "num", 50], [[12, 5], "PaintType", "num", 0], [[12, 6], "CharstringType", "num", 2], [[12, 7], "FontMatrix", ["num", "num", "num", "num", "num", "num"], [0.001, 0, 0, 0.001, 0, 0]], [13, "UniqueID", "num", null], [5, "FontBBox", ["num", "num", "num", "num"], [0, 0, 0, 0]], [[12, 8], "StrokeWidth", "num", 0], [14, "XUID", "array", null], [15, "charset", "offset", 0], [16, "Encoding", "offset", 0], [17, "CharStrings", "offset", 0], [18, "Private", ["offset", "offset"], null], [[12, 21], "PostScript", "sid", null], [[12, 22], "BaseFontName", "sid", null], [[12, 23], "BaseFontBlend", "delta", null], [[12, 31], "CIDFontVersion", "num", 0], [[12, 32], "CIDFontRevision", "num", 0], [[12, 33], "CIDFontType", "num", 0], [[12, 34], "CIDCount", "num", 8720], [[12, 35], "UIDBase", "num", null], [[12, 37], "FDSelect", "offset", null], [[12, 36], "FDArray", "offset", null], [[12, 38], "FontName", "sid", null]];
+class CFFTopDict extends CFFDict {
+ static get tables() {
+ return shadow(this, "tables", this.createTables(CFFTopDictLayout));
+ }
+ constructor(strings) {
+ super(CFFTopDict.tables, strings);
+ this.privateDict = null;
+ }
+}
+const CFFPrivateDictLayout = [[6, "BlueValues", "delta", null], [7, "OtherBlues", "delta", null], [8, "FamilyBlues", "delta", null], [9, "FamilyOtherBlues", "delta", null], [[12, 9], "BlueScale", "num", 0.039625], [[12, 10], "BlueShift", "num", 7], [[12, 11], "BlueFuzz", "num", 1], [10, "StdHW", "num", null], [11, "StdVW", "num", null], [[12, 12], "StemSnapH", "delta", null], [[12, 13], "StemSnapV", "delta", null], [[12, 14], "ForceBold", "num", 0], [[12, 17], "LanguageGroup", "num", 0], [[12, 18], "ExpansionFactor", "num", 0.06], [[12, 19], "initialRandomSeed", "num", 0], [20, "defaultWidthX", "num", 0], [21, "nominalWidthX", "num", 0], [19, "Subrs", "offset", null]];
+class CFFPrivateDict extends CFFDict {
+ static get tables() {
+ return shadow(this, "tables", this.createTables(CFFPrivateDictLayout));
+ }
+ constructor(strings) {
+ super(CFFPrivateDict.tables, strings);
+ this.subrsIndex = null;
+ }
+}
+const CFFCharsetPredefinedTypes = {
+ ISO_ADOBE: 0,
+ EXPERT: 1,
+ EXPERT_SUBSET: 2
+};
+class CFFCharset {
+ constructor(predefined, format, charset, raw) {
+ this.predefined = predefined;
+ this.format = format;
+ this.charset = charset;
+ this.raw = raw;
+ }
+}
+class CFFEncoding {
+ constructor(predefined, format, encoding, raw) {
+ this.predefined = predefined;
+ this.format = format;
+ this.encoding = encoding;
+ this.raw = raw;
+ }
+}
+class CFFFDSelect {
+ constructor(format, fdSelect) {
+ this.format = format;
+ this.fdSelect = fdSelect;
+ }
+ getFDIndex(glyphIndex) {
+ if (glyphIndex < 0 || glyphIndex >= this.fdSelect.length) {
+ return -1;
+ }
+ return this.fdSelect[glyphIndex];
+ }
+}
+class CFFOffsetTracker {
+ constructor() {
+ this.offsets = Object.create(null);
+ }
+ isTracking(key) {
+ return key in this.offsets;
+ }
+ track(key, location) {
+ if (key in this.offsets) {
+ throw new FormatError(`Already tracking location of ${key}`);
+ }
+ this.offsets[key] = location;
+ }
+ offset(value) {
+ for (const key in this.offsets) {
+ this.offsets[key] += value;
+ }
+ }
+ setEntryLocation(key, values, output) {
+ if (!(key in this.offsets)) {
+ throw new FormatError(`Not tracking location of ${key}`);
+ }
+ const data = output.data;
+ const dataOffset = this.offsets[key];
+ const size = 5;
+ for (let i = 0, ii = values.length; i < ii; ++i) {
+ const offset0 = i * size + dataOffset;
+ const offset1 = offset0 + 1;
+ const offset2 = offset0 + 2;
+ const offset3 = offset0 + 3;
+ const offset4 = offset0 + 4;
+ if (data[offset0] !== 0x1d || data[offset1] !== 0 || data[offset2] !== 0 || data[offset3] !== 0 || data[offset4] !== 0) {
+ throw new FormatError("writing to an offset that is not empty");
+ }
+ const value = values[i];
+ data[offset0] = 0x1d;
+ data[offset1] = value >> 24 & 0xff;
+ data[offset2] = value >> 16 & 0xff;
+ data[offset3] = value >> 8 & 0xff;
+ data[offset4] = value & 0xff;
+ }
+ }
+}
+class CFFCompiler {
+ constructor(cff) {
+ this.cff = cff;
+ }
+ compile() {
+ const cff = this.cff;
+ const output = {
+ data: [],
+ length: 0,
+ add(data) {
+ try {
+ this.data.push(...data);
+ } catch {
+ this.data = this.data.concat(data);
+ }
+ this.length = this.data.length;
+ }
+ };
+ const header = this.compileHeader(cff.header);
+ output.add(header);
+ const nameIndex = this.compileNameIndex(cff.names);
+ output.add(nameIndex);
+ if (cff.isCIDFont) {
+ if (cff.topDict.hasName("FontMatrix")) {
+ const base = cff.topDict.getByName("FontMatrix");
+ cff.topDict.removeByName("FontMatrix");
+ for (const subDict of cff.fdArray) {
+ let matrix = base.slice(0);
+ if (subDict.hasName("FontMatrix")) {
+ matrix = Util.transform(matrix, subDict.getByName("FontMatrix"));
+ }
+ subDict.setByName("FontMatrix", matrix);
+ }
+ }
+ }
+ const xuid = cff.topDict.getByName("XUID");
+ if (xuid?.length > 16) {
+ cff.topDict.removeByName("XUID");
+ }
+ cff.topDict.setByName("charset", 0);
+ let compiled = this.compileTopDicts([cff.topDict], output.length, cff.isCIDFont);
+ output.add(compiled.output);
+ const topDictTracker = compiled.trackers[0];
+ const stringIndex = this.compileStringIndex(cff.strings.strings);
+ output.add(stringIndex);
+ const globalSubrIndex = this.compileIndex(cff.globalSubrIndex);
+ output.add(globalSubrIndex);
+ if (cff.encoding && cff.topDict.hasName("Encoding")) {
+ if (cff.encoding.predefined) {
+ topDictTracker.setEntryLocation("Encoding", [cff.encoding.format], output);
+ } else {
+ const encoding = this.compileEncoding(cff.encoding);
+ topDictTracker.setEntryLocation("Encoding", [output.length], output);
+ output.add(encoding);
+ }
+ }
+ const charset = this.compileCharset(cff.charset, cff.charStrings.count, cff.strings, cff.isCIDFont);
+ topDictTracker.setEntryLocation("charset", [output.length], output);
+ output.add(charset);
+ const charStrings = this.compileCharStrings(cff.charStrings);
+ topDictTracker.setEntryLocation("CharStrings", [output.length], output);
+ output.add(charStrings);
+ if (cff.isCIDFont) {
+ topDictTracker.setEntryLocation("FDSelect", [output.length], output);
+ const fdSelect = this.compileFDSelect(cff.fdSelect);
+ output.add(fdSelect);
+ compiled = this.compileTopDicts(cff.fdArray, output.length, true);
+ topDictTracker.setEntryLocation("FDArray", [output.length], output);
+ output.add(compiled.output);
+ const fontDictTrackers = compiled.trackers;
+ this.compilePrivateDicts(cff.fdArray, fontDictTrackers, output);
+ }
+ this.compilePrivateDicts([cff.topDict], [topDictTracker], output);
+ output.add([0]);
+ return output.data;
+ }
+ encodeNumber(value) {
+ if (Number.isInteger(value)) {
+ return this.encodeInteger(value);
+ }
+ return this.encodeFloat(value);
+ }
+ static get EncodeFloatRegExp() {
+ return shadow(this, "EncodeFloatRegExp", /\.(\d*?)(?:9{5,20}|0{5,20})\d{0,2}(?:e(.+)|$)/);
+ }
+ encodeFloat(num) {
+ let value = num.toString();
+ const m = CFFCompiler.EncodeFloatRegExp.exec(value);
+ if (m) {
+ const epsilon = parseFloat("1e" + ((m[2] ? +m[2] : 0) + m[1].length));
+ value = (Math.round(num * epsilon) / epsilon).toString();
+ }
+ let nibbles = "";
+ let i, ii;
+ for (i = 0, ii = value.length; i < ii; ++i) {
+ const a = value[i];
+ if (a === "e") {
+ nibbles += value[++i] === "-" ? "c" : "b";
+ } else if (a === ".") {
+ nibbles += "a";
+ } else if (a === "-") {
+ nibbles += "e";
+ } else {
+ nibbles += a;
+ }
+ }
+ nibbles += nibbles.length & 1 ? "f" : "ff";
+ const out = [30];
+ for (i = 0, ii = nibbles.length; i < ii; i += 2) {
+ out.push(parseInt(nibbles.substring(i, i + 2), 16));
+ }
+ return out;
+ }
+ encodeInteger(value) {
+ let code;
+ if (value >= -107 && value <= 107) {
+ code = [value + 139];
+ } else if (value >= 108 && value <= 1131) {
+ value -= 108;
+ code = [(value >> 8) + 247, value & 0xff];
+ } else if (value >= -1131 && value <= -108) {
+ value = -value - 108;
+ code = [(value >> 8) + 251, value & 0xff];
+ } else if (value >= -32768 && value <= 32767) {
+ code = [0x1c, value >> 8 & 0xff, value & 0xff];
+ } else {
+ code = [0x1d, value >> 24 & 0xff, value >> 16 & 0xff, value >> 8 & 0xff, value & 0xff];
+ }
+ return code;
+ }
+ compileHeader(header) {
+ return [header.major, header.minor, 4, header.offSize];
+ }
+ compileNameIndex(names) {
+ const nameIndex = new CFFIndex();
+ for (const name of names) {
+ const length = Math.min(name.length, 127);
+ let sanitizedName = new Array(length);
+ for (let j = 0; j < length; j++) {
+ let char = name[j];
+ if (char < "!" || char > "~" || char === "[" || char === "]" || char === "(" || char === ")" || char === "{" || char === "}" || char === "<" || char === ">" || char === "/" || char === "%") {
+ char = "_";
+ }
+ sanitizedName[j] = char;
+ }
+ sanitizedName = sanitizedName.join("");
+ if (sanitizedName === "") {
+ sanitizedName = "Bad_Font_Name";
+ }
+ nameIndex.add(stringToBytes(sanitizedName));
+ }
+ return this.compileIndex(nameIndex);
+ }
+ compileTopDicts(dicts, length, removeCidKeys) {
+ const fontDictTrackers = [];
+ let fdArrayIndex = new CFFIndex();
+ for (const fontDict of dicts) {
+ if (removeCidKeys) {
+ fontDict.removeByName("CIDFontVersion");
+ fontDict.removeByName("CIDFontRevision");
+ fontDict.removeByName("CIDFontType");
+ fontDict.removeByName("CIDCount");
+ fontDict.removeByName("UIDBase");
+ }
+ const fontDictTracker = new CFFOffsetTracker();
+ const fontDictData = this.compileDict(fontDict, fontDictTracker);
+ fontDictTrackers.push(fontDictTracker);
+ fdArrayIndex.add(fontDictData);
+ fontDictTracker.offset(length);
+ }
+ fdArrayIndex = this.compileIndex(fdArrayIndex, fontDictTrackers);
+ return {
+ trackers: fontDictTrackers,
+ output: fdArrayIndex
+ };
+ }
+ compilePrivateDicts(dicts, trackers, output) {
+ for (let i = 0, ii = dicts.length; i < ii; ++i) {
+ const fontDict = dicts[i];
+ const privateDict = fontDict.privateDict;
+ if (!privateDict || !fontDict.hasName("Private")) {
+ throw new FormatError("There must be a private dictionary.");
+ }
+ const privateDictTracker = new CFFOffsetTracker();
+ const privateDictData = this.compileDict(privateDict, privateDictTracker);
+ let outputLength = output.length;
+ privateDictTracker.offset(outputLength);
+ if (!privateDictData.length) {
+ outputLength = 0;
+ }
+ trackers[i].setEntryLocation("Private", [privateDictData.length, outputLength], output);
+ output.add(privateDictData);
+ if (privateDict.subrsIndex && privateDict.hasName("Subrs")) {
+ const subrs = this.compileIndex(privateDict.subrsIndex);
+ privateDictTracker.setEntryLocation("Subrs", [privateDictData.length], output);
+ output.add(subrs);
+ }
+ }
+ }
+ compileDict(dict, offsetTracker) {
+ const out = [];
+ for (const key of dict.order) {
+ if (!(key in dict.values)) {
+ continue;
+ }
+ let values = dict.values[key];
+ let types = dict.types[key];
+ if (!Array.isArray(types)) {
+ types = [types];
+ }
+ if (!Array.isArray(values)) {
+ values = [values];
+ }
+ if (values.length === 0) {
+ continue;
+ }
+ for (let j = 0, jj = types.length; j < jj; ++j) {
+ const type = types[j];
+ const value = values[j];
+ switch (type) {
+ case "num":
+ case "sid":
+ out.push(...this.encodeNumber(value));
+ break;
+ case "offset":
+ const name = dict.keyToNameMap[key];
+ if (!offsetTracker.isTracking(name)) {
+ offsetTracker.track(name, out.length);
+ }
+ out.push(0x1d, 0, 0, 0, 0);
+ break;
+ case "array":
+ case "delta":
+ out.push(...this.encodeNumber(value));
+ for (let k = 1, kk = values.length; k < kk; ++k) {
+ out.push(...this.encodeNumber(values[k]));
+ }
+ break;
+ default:
+ throw new FormatError(`Unknown data type of ${type}`);
+ }
+ }
+ out.push(...dict.opcodes[key]);
+ }
+ return out;
+ }
+ compileStringIndex(strings) {
+ const stringIndex = new CFFIndex();
+ for (const string of strings) {
+ stringIndex.add(stringToBytes(string));
+ }
+ return this.compileIndex(stringIndex);
+ }
+ compileCharStrings(charStrings) {
+ const charStringsIndex = new CFFIndex();
+ for (let i = 0; i < charStrings.count; i++) {
+ const glyph = charStrings.get(i);
+ if (glyph.length === 0) {
+ charStringsIndex.add(new Uint8Array([0x8b, 0x0e]));
+ continue;
+ }
+ charStringsIndex.add(glyph);
+ }
+ return this.compileIndex(charStringsIndex);
+ }
+ compileCharset(charset, numGlyphs, strings, isCIDFont) {
+ let out;
+ const numGlyphsLessNotDef = numGlyphs - 1;
+ if (isCIDFont) {
+ out = new Uint8Array([2, 0, 0, numGlyphsLessNotDef >> 8 & 0xff, numGlyphsLessNotDef & 0xff]);
+ } else {
+ const length = 1 + numGlyphsLessNotDef * 2;
+ out = new Uint8Array(length);
+ out[0] = 0;
+ let charsetIndex = 0;
+ const numCharsets = charset.charset.length;
+ let warned = false;
+ for (let i = 1; i < out.length; i += 2) {
+ let sid = 0;
+ if (charsetIndex < numCharsets) {
+ const name = charset.charset[charsetIndex++];
+ sid = strings.getSID(name);
+ if (sid === -1) {
+ sid = 0;
+ if (!warned) {
+ warned = true;
+ warn(`Couldn't find ${name} in CFF strings`);
+ }
+ }
+ }
+ out[i] = sid >> 8 & 0xff;
+ out[i + 1] = sid & 0xff;
+ }
+ }
+ return this.compileTypedArray(out);
+ }
+ compileEncoding(encoding) {
+ return this.compileTypedArray(encoding.raw);
+ }
+ compileFDSelect(fdSelect) {
+ const format = fdSelect.format;
+ let out, i;
+ switch (format) {
+ case 0:
+ out = new Uint8Array(1 + fdSelect.fdSelect.length);
+ out[0] = format;
+ for (i = 0; i < fdSelect.fdSelect.length; i++) {
+ out[i + 1] = fdSelect.fdSelect[i];
+ }
+ break;
+ case 3:
+ const start = 0;
+ let lastFD = fdSelect.fdSelect[0];
+ const ranges = [format, 0, 0, start >> 8 & 0xff, start & 0xff, lastFD];
+ for (i = 1; i < fdSelect.fdSelect.length; i++) {
+ const currentFD = fdSelect.fdSelect[i];
+ if (currentFD !== lastFD) {
+ ranges.push(i >> 8 & 0xff, i & 0xff, currentFD);
+ lastFD = currentFD;
+ }
+ }
+ const numRanges = (ranges.length - 3) / 3;
+ ranges[1] = numRanges >> 8 & 0xff;
+ ranges[2] = numRanges & 0xff;
+ ranges.push(i >> 8 & 0xff, i & 0xff);
+ out = new Uint8Array(ranges);
+ break;
+ }
+ return this.compileTypedArray(out);
+ }
+ compileTypedArray(data) {
+ return Array.from(data);
+ }
+ compileIndex(index, trackers = []) {
+ const objects = index.objects;
+ const count = objects.length;
+ if (count === 0) {
+ return [0, 0];
+ }
+ const data = [count >> 8 & 0xff, count & 0xff];
+ let lastOffset = 1,
+ i;
+ for (i = 0; i < count; ++i) {
+ lastOffset += objects[i].length;
+ }
+ let offsetSize;
+ if (lastOffset < 0x100) {
+ offsetSize = 1;
+ } else if (lastOffset < 0x10000) {
+ offsetSize = 2;
+ } else if (lastOffset < 0x1000000) {
+ offsetSize = 3;
+ } else {
+ offsetSize = 4;
+ }
+ data.push(offsetSize);
+ let relativeOffset = 1;
+ for (i = 0; i < count + 1; i++) {
+ if (offsetSize === 1) {
+ data.push(relativeOffset & 0xff);
+ } else if (offsetSize === 2) {
+ data.push(relativeOffset >> 8 & 0xff, relativeOffset & 0xff);
+ } else if (offsetSize === 3) {
+ data.push(relativeOffset >> 16 & 0xff, relativeOffset >> 8 & 0xff, relativeOffset & 0xff);
+ } else {
+ data.push(relativeOffset >>> 24 & 0xff, relativeOffset >> 16 & 0xff, relativeOffset >> 8 & 0xff, relativeOffset & 0xff);
+ }
+ if (objects[i]) {
+ relativeOffset += objects[i].length;
+ }
+ }
+ for (i = 0; i < count; i++) {
+ if (trackers[i]) {
+ trackers[i].offset(data.length);
+ }
+ data.push(...objects[i]);
+ }
+ return data;
+ }
+}
+
+;// CONCATENATED MODULE: ./src/core/glyphlist.js
+
+const getGlyphsUnicode = getLookupTableFactory(function (t) {
+ t.A = 0x0041;
+ t.AE = 0x00c6;
+ t.AEacute = 0x01fc;
+ t.AEmacron = 0x01e2;
+ t.AEsmall = 0xf7e6;
+ t.Aacute = 0x00c1;
+ t.Aacutesmall = 0xf7e1;
+ t.Abreve = 0x0102;
+ t.Abreveacute = 0x1eae;
+ t.Abrevecyrillic = 0x04d0;
+ t.Abrevedotbelow = 0x1eb6;
+ t.Abrevegrave = 0x1eb0;
+ t.Abrevehookabove = 0x1eb2;
+ t.Abrevetilde = 0x1eb4;
+ t.Acaron = 0x01cd;
+ t.Acircle = 0x24b6;
+ t.Acircumflex = 0x00c2;
+ t.Acircumflexacute = 0x1ea4;
+ t.Acircumflexdotbelow = 0x1eac;
+ t.Acircumflexgrave = 0x1ea6;
+ t.Acircumflexhookabove = 0x1ea8;
+ t.Acircumflexsmall = 0xf7e2;
+ t.Acircumflextilde = 0x1eaa;
+ t.Acute = 0xf6c9;
+ t.Acutesmall = 0xf7b4;
+ t.Acyrillic = 0x0410;
+ t.Adblgrave = 0x0200;
+ t.Adieresis = 0x00c4;
+ t.Adieresiscyrillic = 0x04d2;
+ t.Adieresismacron = 0x01de;
+ t.Adieresissmall = 0xf7e4;
+ t.Adotbelow = 0x1ea0;
+ t.Adotmacron = 0x01e0;
+ t.Agrave = 0x00c0;
+ t.Agravesmall = 0xf7e0;
+ t.Ahookabove = 0x1ea2;
+ t.Aiecyrillic = 0x04d4;
+ t.Ainvertedbreve = 0x0202;
+ t.Alpha = 0x0391;
+ t.Alphatonos = 0x0386;
+ t.Amacron = 0x0100;
+ t.Amonospace = 0xff21;
+ t.Aogonek = 0x0104;
+ t.Aring = 0x00c5;
+ t.Aringacute = 0x01fa;
+ t.Aringbelow = 0x1e00;
+ t.Aringsmall = 0xf7e5;
+ t.Asmall = 0xf761;
+ t.Atilde = 0x00c3;
+ t.Atildesmall = 0xf7e3;
+ t.Aybarmenian = 0x0531;
+ t.B = 0x0042;
+ t.Bcircle = 0x24b7;
+ t.Bdotaccent = 0x1e02;
+ t.Bdotbelow = 0x1e04;
+ t.Becyrillic = 0x0411;
+ t.Benarmenian = 0x0532;
+ t.Beta = 0x0392;
+ t.Bhook = 0x0181;
+ t.Blinebelow = 0x1e06;
+ t.Bmonospace = 0xff22;
+ t.Brevesmall = 0xf6f4;
+ t.Bsmall = 0xf762;
+ t.Btopbar = 0x0182;
+ t.C = 0x0043;
+ t.Caarmenian = 0x053e;
+ t.Cacute = 0x0106;
+ t.Caron = 0xf6ca;
+ t.Caronsmall = 0xf6f5;
+ t.Ccaron = 0x010c;
+ t.Ccedilla = 0x00c7;
+ t.Ccedillaacute = 0x1e08;
+ t.Ccedillasmall = 0xf7e7;
+ t.Ccircle = 0x24b8;
+ t.Ccircumflex = 0x0108;
+ t.Cdot = 0x010a;
+ t.Cdotaccent = 0x010a;
+ t.Cedillasmall = 0xf7b8;
+ t.Chaarmenian = 0x0549;
+ t.Cheabkhasiancyrillic = 0x04bc;
+ t.Checyrillic = 0x0427;
+ t.Chedescenderabkhasiancyrillic = 0x04be;
+ t.Chedescendercyrillic = 0x04b6;
+ t.Chedieresiscyrillic = 0x04f4;
+ t.Cheharmenian = 0x0543;
+ t.Chekhakassiancyrillic = 0x04cb;
+ t.Cheverticalstrokecyrillic = 0x04b8;
+ t.Chi = 0x03a7;
+ t.Chook = 0x0187;
+ t.Circumflexsmall = 0xf6f6;
+ t.Cmonospace = 0xff23;
+ t.Coarmenian = 0x0551;
+ t.Csmall = 0xf763;
+ t.D = 0x0044;
+ t.DZ = 0x01f1;
+ t.DZcaron = 0x01c4;
+ t.Daarmenian = 0x0534;
+ t.Dafrican = 0x0189;
+ t.Dcaron = 0x010e;
+ t.Dcedilla = 0x1e10;
+ t.Dcircle = 0x24b9;
+ t.Dcircumflexbelow = 0x1e12;
+ t.Dcroat = 0x0110;
+ t.Ddotaccent = 0x1e0a;
+ t.Ddotbelow = 0x1e0c;
+ t.Decyrillic = 0x0414;
+ t.Deicoptic = 0x03ee;
+ t.Delta = 0x2206;
+ t.Deltagreek = 0x0394;
+ t.Dhook = 0x018a;
+ t.Dieresis = 0xf6cb;
+ t.DieresisAcute = 0xf6cc;
+ t.DieresisGrave = 0xf6cd;
+ t.Dieresissmall = 0xf7a8;
+ t.Digammagreek = 0x03dc;
+ t.Djecyrillic = 0x0402;
+ t.Dlinebelow = 0x1e0e;
+ t.Dmonospace = 0xff24;
+ t.Dotaccentsmall = 0xf6f7;
+ t.Dslash = 0x0110;
+ t.Dsmall = 0xf764;
+ t.Dtopbar = 0x018b;
+ t.Dz = 0x01f2;
+ t.Dzcaron = 0x01c5;
+ t.Dzeabkhasiancyrillic = 0x04e0;
+ t.Dzecyrillic = 0x0405;
+ t.Dzhecyrillic = 0x040f;
+ t.E = 0x0045;
+ t.Eacute = 0x00c9;
+ t.Eacutesmall = 0xf7e9;
+ t.Ebreve = 0x0114;
+ t.Ecaron = 0x011a;
+ t.Ecedillabreve = 0x1e1c;
+ t.Echarmenian = 0x0535;
+ t.Ecircle = 0x24ba;
+ t.Ecircumflex = 0x00ca;
+ t.Ecircumflexacute = 0x1ebe;
+ t.Ecircumflexbelow = 0x1e18;
+ t.Ecircumflexdotbelow = 0x1ec6;
+ t.Ecircumflexgrave = 0x1ec0;
+ t.Ecircumflexhookabove = 0x1ec2;
+ t.Ecircumflexsmall = 0xf7ea;
+ t.Ecircumflextilde = 0x1ec4;
+ t.Ecyrillic = 0x0404;
+ t.Edblgrave = 0x0204;
+ t.Edieresis = 0x00cb;
+ t.Edieresissmall = 0xf7eb;
+ t.Edot = 0x0116;
+ t.Edotaccent = 0x0116;
+ t.Edotbelow = 0x1eb8;
+ t.Efcyrillic = 0x0424;
+ t.Egrave = 0x00c8;
+ t.Egravesmall = 0xf7e8;
+ t.Eharmenian = 0x0537;
+ t.Ehookabove = 0x1eba;
+ t.Eightroman = 0x2167;
+ t.Einvertedbreve = 0x0206;
+ t.Eiotifiedcyrillic = 0x0464;
+ t.Elcyrillic = 0x041b;
+ t.Elevenroman = 0x216a;
+ t.Emacron = 0x0112;
+ t.Emacronacute = 0x1e16;
+ t.Emacrongrave = 0x1e14;
+ t.Emcyrillic = 0x041c;
+ t.Emonospace = 0xff25;
+ t.Encyrillic = 0x041d;
+ t.Endescendercyrillic = 0x04a2;
+ t.Eng = 0x014a;
+ t.Enghecyrillic = 0x04a4;
+ t.Enhookcyrillic = 0x04c7;
+ t.Eogonek = 0x0118;
+ t.Eopen = 0x0190;
+ t.Epsilon = 0x0395;
+ t.Epsilontonos = 0x0388;
+ t.Ercyrillic = 0x0420;
+ t.Ereversed = 0x018e;
+ t.Ereversedcyrillic = 0x042d;
+ t.Escyrillic = 0x0421;
+ t.Esdescendercyrillic = 0x04aa;
+ t.Esh = 0x01a9;
+ t.Esmall = 0xf765;
+ t.Eta = 0x0397;
+ t.Etarmenian = 0x0538;
+ t.Etatonos = 0x0389;
+ t.Eth = 0x00d0;
+ t.Ethsmall = 0xf7f0;
+ t.Etilde = 0x1ebc;
+ t.Etildebelow = 0x1e1a;
+ t.Euro = 0x20ac;
+ t.Ezh = 0x01b7;
+ t.Ezhcaron = 0x01ee;
+ t.Ezhreversed = 0x01b8;
+ t.F = 0x0046;
+ t.Fcircle = 0x24bb;
+ t.Fdotaccent = 0x1e1e;
+ t.Feharmenian = 0x0556;
+ t.Feicoptic = 0x03e4;
+ t.Fhook = 0x0191;
+ t.Fitacyrillic = 0x0472;
+ t.Fiveroman = 0x2164;
+ t.Fmonospace = 0xff26;
+ t.Fourroman = 0x2163;
+ t.Fsmall = 0xf766;
+ t.G = 0x0047;
+ t.GBsquare = 0x3387;
+ t.Gacute = 0x01f4;
+ t.Gamma = 0x0393;
+ t.Gammaafrican = 0x0194;
+ t.Gangiacoptic = 0x03ea;
+ t.Gbreve = 0x011e;
+ t.Gcaron = 0x01e6;
+ t.Gcedilla = 0x0122;
+ t.Gcircle = 0x24bc;
+ t.Gcircumflex = 0x011c;
+ t.Gcommaaccent = 0x0122;
+ t.Gdot = 0x0120;
+ t.Gdotaccent = 0x0120;
+ t.Gecyrillic = 0x0413;
+ t.Ghadarmenian = 0x0542;
+ t.Ghemiddlehookcyrillic = 0x0494;
+ t.Ghestrokecyrillic = 0x0492;
+ t.Gheupturncyrillic = 0x0490;
+ t.Ghook = 0x0193;
+ t.Gimarmenian = 0x0533;
+ t.Gjecyrillic = 0x0403;
+ t.Gmacron = 0x1e20;
+ t.Gmonospace = 0xff27;
+ t.Grave = 0xf6ce;
+ t.Gravesmall = 0xf760;
+ t.Gsmall = 0xf767;
+ t.Gsmallhook = 0x029b;
+ t.Gstroke = 0x01e4;
+ t.H = 0x0048;
+ t.H18533 = 0x25cf;
+ t.H18543 = 0x25aa;
+ t.H18551 = 0x25ab;
+ t.H22073 = 0x25a1;
+ t.HPsquare = 0x33cb;
+ t.Haabkhasiancyrillic = 0x04a8;
+ t.Hadescendercyrillic = 0x04b2;
+ t.Hardsigncyrillic = 0x042a;
+ t.Hbar = 0x0126;
+ t.Hbrevebelow = 0x1e2a;
+ t.Hcedilla = 0x1e28;
+ t.Hcircle = 0x24bd;
+ t.Hcircumflex = 0x0124;
+ t.Hdieresis = 0x1e26;
+ t.Hdotaccent = 0x1e22;
+ t.Hdotbelow = 0x1e24;
+ t.Hmonospace = 0xff28;
+ t.Hoarmenian = 0x0540;
+ t.Horicoptic = 0x03e8;
+ t.Hsmall = 0xf768;
+ t.Hungarumlaut = 0xf6cf;
+ t.Hungarumlautsmall = 0xf6f8;
+ t.Hzsquare = 0x3390;
+ t.I = 0x0049;
+ t.IAcyrillic = 0x042f;
+ t.IJ = 0x0132;
+ t.IUcyrillic = 0x042e;
+ t.Iacute = 0x00cd;
+ t.Iacutesmall = 0xf7ed;
+ t.Ibreve = 0x012c;
+ t.Icaron = 0x01cf;
+ t.Icircle = 0x24be;
+ t.Icircumflex = 0x00ce;
+ t.Icircumflexsmall = 0xf7ee;
+ t.Icyrillic = 0x0406;
+ t.Idblgrave = 0x0208;
+ t.Idieresis = 0x00cf;
+ t.Idieresisacute = 0x1e2e;
+ t.Idieresiscyrillic = 0x04e4;
+ t.Idieresissmall = 0xf7ef;
+ t.Idot = 0x0130;
+ t.Idotaccent = 0x0130;
+ t.Idotbelow = 0x1eca;
+ t.Iebrevecyrillic = 0x04d6;
+ t.Iecyrillic = 0x0415;
+ t.Ifraktur = 0x2111;
+ t.Igrave = 0x00cc;
+ t.Igravesmall = 0xf7ec;
+ t.Ihookabove = 0x1ec8;
+ t.Iicyrillic = 0x0418;
+ t.Iinvertedbreve = 0x020a;
+ t.Iishortcyrillic = 0x0419;
+ t.Imacron = 0x012a;
+ t.Imacroncyrillic = 0x04e2;
+ t.Imonospace = 0xff29;
+ t.Iniarmenian = 0x053b;
+ t.Iocyrillic = 0x0401;
+ t.Iogonek = 0x012e;
+ t.Iota = 0x0399;
+ t.Iotaafrican = 0x0196;
+ t.Iotadieresis = 0x03aa;
+ t.Iotatonos = 0x038a;
+ t.Ismall = 0xf769;
+ t.Istroke = 0x0197;
+ t.Itilde = 0x0128;
+ t.Itildebelow = 0x1e2c;
+ t.Izhitsacyrillic = 0x0474;
+ t.Izhitsadblgravecyrillic = 0x0476;
+ t.J = 0x004a;
+ t.Jaarmenian = 0x0541;
+ t.Jcircle = 0x24bf;
+ t.Jcircumflex = 0x0134;
+ t.Jecyrillic = 0x0408;
+ t.Jheharmenian = 0x054b;
+ t.Jmonospace = 0xff2a;
+ t.Jsmall = 0xf76a;
+ t.K = 0x004b;
+ t.KBsquare = 0x3385;
+ t.KKsquare = 0x33cd;
+ t.Kabashkircyrillic = 0x04a0;
+ t.Kacute = 0x1e30;
+ t.Kacyrillic = 0x041a;
+ t.Kadescendercyrillic = 0x049a;
+ t.Kahookcyrillic = 0x04c3;
+ t.Kappa = 0x039a;
+ t.Kastrokecyrillic = 0x049e;
+ t.Kaverticalstrokecyrillic = 0x049c;
+ t.Kcaron = 0x01e8;
+ t.Kcedilla = 0x0136;
+ t.Kcircle = 0x24c0;
+ t.Kcommaaccent = 0x0136;
+ t.Kdotbelow = 0x1e32;
+ t.Keharmenian = 0x0554;
+ t.Kenarmenian = 0x053f;
+ t.Khacyrillic = 0x0425;
+ t.Kheicoptic = 0x03e6;
+ t.Khook = 0x0198;
+ t.Kjecyrillic = 0x040c;
+ t.Klinebelow = 0x1e34;
+ t.Kmonospace = 0xff2b;
+ t.Koppacyrillic = 0x0480;
+ t.Koppagreek = 0x03de;
+ t.Ksicyrillic = 0x046e;
+ t.Ksmall = 0xf76b;
+ t.L = 0x004c;
+ t.LJ = 0x01c7;
+ t.LL = 0xf6bf;
+ t.Lacute = 0x0139;
+ t.Lambda = 0x039b;
+ t.Lcaron = 0x013d;
+ t.Lcedilla = 0x013b;
+ t.Lcircle = 0x24c1;
+ t.Lcircumflexbelow = 0x1e3c;
+ t.Lcommaaccent = 0x013b;
+ t.Ldot = 0x013f;
+ t.Ldotaccent = 0x013f;
+ t.Ldotbelow = 0x1e36;
+ t.Ldotbelowmacron = 0x1e38;
+ t.Liwnarmenian = 0x053c;
+ t.Lj = 0x01c8;
+ t.Ljecyrillic = 0x0409;
+ t.Llinebelow = 0x1e3a;
+ t.Lmonospace = 0xff2c;
+ t.Lslash = 0x0141;
+ t.Lslashsmall = 0xf6f9;
+ t.Lsmall = 0xf76c;
+ t.M = 0x004d;
+ t.MBsquare = 0x3386;
+ t.Macron = 0xf6d0;
+ t.Macronsmall = 0xf7af;
+ t.Macute = 0x1e3e;
+ t.Mcircle = 0x24c2;
+ t.Mdotaccent = 0x1e40;
+ t.Mdotbelow = 0x1e42;
+ t.Menarmenian = 0x0544;
+ t.Mmonospace = 0xff2d;
+ t.Msmall = 0xf76d;
+ t.Mturned = 0x019c;
+ t.Mu = 0x039c;
+ t.N = 0x004e;
+ t.NJ = 0x01ca;
+ t.Nacute = 0x0143;
+ t.Ncaron = 0x0147;
+ t.Ncedilla = 0x0145;
+ t.Ncircle = 0x24c3;
+ t.Ncircumflexbelow = 0x1e4a;
+ t.Ncommaaccent = 0x0145;
+ t.Ndotaccent = 0x1e44;
+ t.Ndotbelow = 0x1e46;
+ t.Nhookleft = 0x019d;
+ t.Nineroman = 0x2168;
+ t.Nj = 0x01cb;
+ t.Njecyrillic = 0x040a;
+ t.Nlinebelow = 0x1e48;
+ t.Nmonospace = 0xff2e;
+ t.Nowarmenian = 0x0546;
+ t.Nsmall = 0xf76e;
+ t.Ntilde = 0x00d1;
+ t.Ntildesmall = 0xf7f1;
+ t.Nu = 0x039d;
+ t.O = 0x004f;
+ t.OE = 0x0152;
+ t.OEsmall = 0xf6fa;
+ t.Oacute = 0x00d3;
+ t.Oacutesmall = 0xf7f3;
+ t.Obarredcyrillic = 0x04e8;
+ t.Obarreddieresiscyrillic = 0x04ea;
+ t.Obreve = 0x014e;
+ t.Ocaron = 0x01d1;
+ t.Ocenteredtilde = 0x019f;
+ t.Ocircle = 0x24c4;
+ t.Ocircumflex = 0x00d4;
+ t.Ocircumflexacute = 0x1ed0;
+ t.Ocircumflexdotbelow = 0x1ed8;
+ t.Ocircumflexgrave = 0x1ed2;
+ t.Ocircumflexhookabove = 0x1ed4;
+ t.Ocircumflexsmall = 0xf7f4;
+ t.Ocircumflextilde = 0x1ed6;
+ t.Ocyrillic = 0x041e;
+ t.Odblacute = 0x0150;
+ t.Odblgrave = 0x020c;
+ t.Odieresis = 0x00d6;
+ t.Odieresiscyrillic = 0x04e6;
+ t.Odieresissmall = 0xf7f6;
+ t.Odotbelow = 0x1ecc;
+ t.Ogoneksmall = 0xf6fb;
+ t.Ograve = 0x00d2;
+ t.Ogravesmall = 0xf7f2;
+ t.Oharmenian = 0x0555;
+ t.Ohm = 0x2126;
+ t.Ohookabove = 0x1ece;
+ t.Ohorn = 0x01a0;
+ t.Ohornacute = 0x1eda;
+ t.Ohorndotbelow = 0x1ee2;
+ t.Ohorngrave = 0x1edc;
+ t.Ohornhookabove = 0x1ede;
+ t.Ohorntilde = 0x1ee0;
+ t.Ohungarumlaut = 0x0150;
+ t.Oi = 0x01a2;
+ t.Oinvertedbreve = 0x020e;
+ t.Omacron = 0x014c;
+ t.Omacronacute = 0x1e52;
+ t.Omacrongrave = 0x1e50;
+ t.Omega = 0x2126;
+ t.Omegacyrillic = 0x0460;
+ t.Omegagreek = 0x03a9;
+ t.Omegaroundcyrillic = 0x047a;
+ t.Omegatitlocyrillic = 0x047c;
+ t.Omegatonos = 0x038f;
+ t.Omicron = 0x039f;
+ t.Omicrontonos = 0x038c;
+ t.Omonospace = 0xff2f;
+ t.Oneroman = 0x2160;
+ t.Oogonek = 0x01ea;
+ t.Oogonekmacron = 0x01ec;
+ t.Oopen = 0x0186;
+ t.Oslash = 0x00d8;
+ t.Oslashacute = 0x01fe;
+ t.Oslashsmall = 0xf7f8;
+ t.Osmall = 0xf76f;
+ t.Ostrokeacute = 0x01fe;
+ t.Otcyrillic = 0x047e;
+ t.Otilde = 0x00d5;
+ t.Otildeacute = 0x1e4c;
+ t.Otildedieresis = 0x1e4e;
+ t.Otildesmall = 0xf7f5;
+ t.P = 0x0050;
+ t.Pacute = 0x1e54;
+ t.Pcircle = 0x24c5;
+ t.Pdotaccent = 0x1e56;
+ t.Pecyrillic = 0x041f;
+ t.Peharmenian = 0x054a;
+ t.Pemiddlehookcyrillic = 0x04a6;
+ t.Phi = 0x03a6;
+ t.Phook = 0x01a4;
+ t.Pi = 0x03a0;
+ t.Piwrarmenian = 0x0553;
+ t.Pmonospace = 0xff30;
+ t.Psi = 0x03a8;
+ t.Psicyrillic = 0x0470;
+ t.Psmall = 0xf770;
+ t.Q = 0x0051;
+ t.Qcircle = 0x24c6;
+ t.Qmonospace = 0xff31;
+ t.Qsmall = 0xf771;
+ t.R = 0x0052;
+ t.Raarmenian = 0x054c;
+ t.Racute = 0x0154;
+ t.Rcaron = 0x0158;
+ t.Rcedilla = 0x0156;
+ t.Rcircle = 0x24c7;
+ t.Rcommaaccent = 0x0156;
+ t.Rdblgrave = 0x0210;
+ t.Rdotaccent = 0x1e58;
+ t.Rdotbelow = 0x1e5a;
+ t.Rdotbelowmacron = 0x1e5c;
+ t.Reharmenian = 0x0550;
+ t.Rfraktur = 0x211c;
+ t.Rho = 0x03a1;
+ t.Ringsmall = 0xf6fc;
+ t.Rinvertedbreve = 0x0212;
+ t.Rlinebelow = 0x1e5e;
+ t.Rmonospace = 0xff32;
+ t.Rsmall = 0xf772;
+ t.Rsmallinverted = 0x0281;
+ t.Rsmallinvertedsuperior = 0x02b6;
+ t.S = 0x0053;
+ t.SF010000 = 0x250c;
+ t.SF020000 = 0x2514;
+ t.SF030000 = 0x2510;
+ t.SF040000 = 0x2518;
+ t.SF050000 = 0x253c;
+ t.SF060000 = 0x252c;
+ t.SF070000 = 0x2534;
+ t.SF080000 = 0x251c;
+ t.SF090000 = 0x2524;
+ t.SF100000 = 0x2500;
+ t.SF110000 = 0x2502;
+ t.SF190000 = 0x2561;
+ t.SF200000 = 0x2562;
+ t.SF210000 = 0x2556;
+ t.SF220000 = 0x2555;
+ t.SF230000 = 0x2563;
+ t.SF240000 = 0x2551;
+ t.SF250000 = 0x2557;
+ t.SF260000 = 0x255d;
+ t.SF270000 = 0x255c;
+ t.SF280000 = 0x255b;
+ t.SF360000 = 0x255e;
+ t.SF370000 = 0x255f;
+ t.SF380000 = 0x255a;
+ t.SF390000 = 0x2554;
+ t.SF400000 = 0x2569;
+ t.SF410000 = 0x2566;
+ t.SF420000 = 0x2560;
+ t.SF430000 = 0x2550;
+ t.SF440000 = 0x256c;
+ t.SF450000 = 0x2567;
+ t.SF460000 = 0x2568;
+ t.SF470000 = 0x2564;
+ t.SF480000 = 0x2565;
+ t.SF490000 = 0x2559;
+ t.SF500000 = 0x2558;
+ t.SF510000 = 0x2552;
+ t.SF520000 = 0x2553;
+ t.SF530000 = 0x256b;
+ t.SF540000 = 0x256a;
+ t.Sacute = 0x015a;
+ t.Sacutedotaccent = 0x1e64;
+ t.Sampigreek = 0x03e0;
+ t.Scaron = 0x0160;
+ t.Scarondotaccent = 0x1e66;
+ t.Scaronsmall = 0xf6fd;
+ t.Scedilla = 0x015e;
+ t.Schwa = 0x018f;
+ t.Schwacyrillic = 0x04d8;
+ t.Schwadieresiscyrillic = 0x04da;
+ t.Scircle = 0x24c8;
+ t.Scircumflex = 0x015c;
+ t.Scommaaccent = 0x0218;
+ t.Sdotaccent = 0x1e60;
+ t.Sdotbelow = 0x1e62;
+ t.Sdotbelowdotaccent = 0x1e68;
+ t.Seharmenian = 0x054d;
+ t.Sevenroman = 0x2166;
+ t.Shaarmenian = 0x0547;
+ t.Shacyrillic = 0x0428;
+ t.Shchacyrillic = 0x0429;
+ t.Sheicoptic = 0x03e2;
+ t.Shhacyrillic = 0x04ba;
+ t.Shimacoptic = 0x03ec;
+ t.Sigma = 0x03a3;
+ t.Sixroman = 0x2165;
+ t.Smonospace = 0xff33;
+ t.Softsigncyrillic = 0x042c;
+ t.Ssmall = 0xf773;
+ t.Stigmagreek = 0x03da;
+ t.T = 0x0054;
+ t.Tau = 0x03a4;
+ t.Tbar = 0x0166;
+ t.Tcaron = 0x0164;
+ t.Tcedilla = 0x0162;
+ t.Tcircle = 0x24c9;
+ t.Tcircumflexbelow = 0x1e70;
+ t.Tcommaaccent = 0x0162;
+ t.Tdotaccent = 0x1e6a;
+ t.Tdotbelow = 0x1e6c;
+ t.Tecyrillic = 0x0422;
+ t.Tedescendercyrillic = 0x04ac;
+ t.Tenroman = 0x2169;
+ t.Tetsecyrillic = 0x04b4;
+ t.Theta = 0x0398;
+ t.Thook = 0x01ac;
+ t.Thorn = 0x00de;
+ t.Thornsmall = 0xf7fe;
+ t.Threeroman = 0x2162;
+ t.Tildesmall = 0xf6fe;
+ t.Tiwnarmenian = 0x054f;
+ t.Tlinebelow = 0x1e6e;
+ t.Tmonospace = 0xff34;
+ t.Toarmenian = 0x0539;
+ t.Tonefive = 0x01bc;
+ t.Tonesix = 0x0184;
+ t.Tonetwo = 0x01a7;
+ t.Tretroflexhook = 0x01ae;
+ t.Tsecyrillic = 0x0426;
+ t.Tshecyrillic = 0x040b;
+ t.Tsmall = 0xf774;
+ t.Twelveroman = 0x216b;
+ t.Tworoman = 0x2161;
+ t.U = 0x0055;
+ t.Uacute = 0x00da;
+ t.Uacutesmall = 0xf7fa;
+ t.Ubreve = 0x016c;
+ t.Ucaron = 0x01d3;
+ t.Ucircle = 0x24ca;
+ t.Ucircumflex = 0x00db;
+ t.Ucircumflexbelow = 0x1e76;
+ t.Ucircumflexsmall = 0xf7fb;
+ t.Ucyrillic = 0x0423;
+ t.Udblacute = 0x0170;
+ t.Udblgrave = 0x0214;
+ t.Udieresis = 0x00dc;
+ t.Udieresisacute = 0x01d7;
+ t.Udieresisbelow = 0x1e72;
+ t.Udieresiscaron = 0x01d9;
+ t.Udieresiscyrillic = 0x04f0;
+ t.Udieresisgrave = 0x01db;
+ t.Udieresismacron = 0x01d5;
+ t.Udieresissmall = 0xf7fc;
+ t.Udotbelow = 0x1ee4;
+ t.Ugrave = 0x00d9;
+ t.Ugravesmall = 0xf7f9;
+ t.Uhookabove = 0x1ee6;
+ t.Uhorn = 0x01af;
+ t.Uhornacute = 0x1ee8;
+ t.Uhorndotbelow = 0x1ef0;
+ t.Uhorngrave = 0x1eea;
+ t.Uhornhookabove = 0x1eec;
+ t.Uhorntilde = 0x1eee;
+ t.Uhungarumlaut = 0x0170;
+ t.Uhungarumlautcyrillic = 0x04f2;
+ t.Uinvertedbreve = 0x0216;
+ t.Ukcyrillic = 0x0478;
+ t.Umacron = 0x016a;
+ t.Umacroncyrillic = 0x04ee;
+ t.Umacrondieresis = 0x1e7a;
+ t.Umonospace = 0xff35;
+ t.Uogonek = 0x0172;
+ t.Upsilon = 0x03a5;
+ t.Upsilon1 = 0x03d2;
+ t.Upsilonacutehooksymbolgreek = 0x03d3;
+ t.Upsilonafrican = 0x01b1;
+ t.Upsilondieresis = 0x03ab;
+ t.Upsilondieresishooksymbolgreek = 0x03d4;
+ t.Upsilonhooksymbol = 0x03d2;
+ t.Upsilontonos = 0x038e;
+ t.Uring = 0x016e;
+ t.Ushortcyrillic = 0x040e;
+ t.Usmall = 0xf775;
+ t.Ustraightcyrillic = 0x04ae;
+ t.Ustraightstrokecyrillic = 0x04b0;
+ t.Utilde = 0x0168;
+ t.Utildeacute = 0x1e78;
+ t.Utildebelow = 0x1e74;
+ t.V = 0x0056;
+ t.Vcircle = 0x24cb;
+ t.Vdotbelow = 0x1e7e;
+ t.Vecyrillic = 0x0412;
+ t.Vewarmenian = 0x054e;
+ t.Vhook = 0x01b2;
+ t.Vmonospace = 0xff36;
+ t.Voarmenian = 0x0548;
+ t.Vsmall = 0xf776;
+ t.Vtilde = 0x1e7c;
+ t.W = 0x0057;
+ t.Wacute = 0x1e82;
+ t.Wcircle = 0x24cc;
+ t.Wcircumflex = 0x0174;
+ t.Wdieresis = 0x1e84;
+ t.Wdotaccent = 0x1e86;
+ t.Wdotbelow = 0x1e88;
+ t.Wgrave = 0x1e80;
+ t.Wmonospace = 0xff37;
+ t.Wsmall = 0xf777;
+ t.X = 0x0058;
+ t.Xcircle = 0x24cd;
+ t.Xdieresis = 0x1e8c;
+ t.Xdotaccent = 0x1e8a;
+ t.Xeharmenian = 0x053d;
+ t.Xi = 0x039e;
+ t.Xmonospace = 0xff38;
+ t.Xsmall = 0xf778;
+ t.Y = 0x0059;
+ t.Yacute = 0x00dd;
+ t.Yacutesmall = 0xf7fd;
+ t.Yatcyrillic = 0x0462;
+ t.Ycircle = 0x24ce;
+ t.Ycircumflex = 0x0176;
+ t.Ydieresis = 0x0178;
+ t.Ydieresissmall = 0xf7ff;
+ t.Ydotaccent = 0x1e8e;
+ t.Ydotbelow = 0x1ef4;
+ t.Yericyrillic = 0x042b;
+ t.Yerudieresiscyrillic = 0x04f8;
+ t.Ygrave = 0x1ef2;
+ t.Yhook = 0x01b3;
+ t.Yhookabove = 0x1ef6;
+ t.Yiarmenian = 0x0545;
+ t.Yicyrillic = 0x0407;
+ t.Yiwnarmenian = 0x0552;
+ t.Ymonospace = 0xff39;
+ t.Ysmall = 0xf779;
+ t.Ytilde = 0x1ef8;
+ t.Yusbigcyrillic = 0x046a;
+ t.Yusbigiotifiedcyrillic = 0x046c;
+ t.Yuslittlecyrillic = 0x0466;
+ t.Yuslittleiotifiedcyrillic = 0x0468;
+ t.Z = 0x005a;
+ t.Zaarmenian = 0x0536;
+ t.Zacute = 0x0179;
+ t.Zcaron = 0x017d;
+ t.Zcaronsmall = 0xf6ff;
+ t.Zcircle = 0x24cf;
+ t.Zcircumflex = 0x1e90;
+ t.Zdot = 0x017b;
+ t.Zdotaccent = 0x017b;
+ t.Zdotbelow = 0x1e92;
+ t.Zecyrillic = 0x0417;
+ t.Zedescendercyrillic = 0x0498;
+ t.Zedieresiscyrillic = 0x04de;
+ t.Zeta = 0x0396;
+ t.Zhearmenian = 0x053a;
+ t.Zhebrevecyrillic = 0x04c1;
+ t.Zhecyrillic = 0x0416;
+ t.Zhedescendercyrillic = 0x0496;
+ t.Zhedieresiscyrillic = 0x04dc;
+ t.Zlinebelow = 0x1e94;
+ t.Zmonospace = 0xff3a;
+ t.Zsmall = 0xf77a;
+ t.Zstroke = 0x01b5;
+ t.a = 0x0061;
+ t.aabengali = 0x0986;
+ t.aacute = 0x00e1;
+ t.aadeva = 0x0906;
+ t.aagujarati = 0x0a86;
+ t.aagurmukhi = 0x0a06;
+ t.aamatragurmukhi = 0x0a3e;
+ t.aarusquare = 0x3303;
+ t.aavowelsignbengali = 0x09be;
+ t.aavowelsigndeva = 0x093e;
+ t.aavowelsigngujarati = 0x0abe;
+ t.abbreviationmarkarmenian = 0x055f;
+ t.abbreviationsigndeva = 0x0970;
+ t.abengali = 0x0985;
+ t.abopomofo = 0x311a;
+ t.abreve = 0x0103;
+ t.abreveacute = 0x1eaf;
+ t.abrevecyrillic = 0x04d1;
+ t.abrevedotbelow = 0x1eb7;
+ t.abrevegrave = 0x1eb1;
+ t.abrevehookabove = 0x1eb3;
+ t.abrevetilde = 0x1eb5;
+ t.acaron = 0x01ce;
+ t.acircle = 0x24d0;
+ t.acircumflex = 0x00e2;
+ t.acircumflexacute = 0x1ea5;
+ t.acircumflexdotbelow = 0x1ead;
+ t.acircumflexgrave = 0x1ea7;
+ t.acircumflexhookabove = 0x1ea9;
+ t.acircumflextilde = 0x1eab;
+ t.acute = 0x00b4;
+ t.acutebelowcmb = 0x0317;
+ t.acutecmb = 0x0301;
+ t.acutecomb = 0x0301;
+ t.acutedeva = 0x0954;
+ t.acutelowmod = 0x02cf;
+ t.acutetonecmb = 0x0341;
+ t.acyrillic = 0x0430;
+ t.adblgrave = 0x0201;
+ t.addakgurmukhi = 0x0a71;
+ t.adeva = 0x0905;
+ t.adieresis = 0x00e4;
+ t.adieresiscyrillic = 0x04d3;
+ t.adieresismacron = 0x01df;
+ t.adotbelow = 0x1ea1;
+ t.adotmacron = 0x01e1;
+ t.ae = 0x00e6;
+ t.aeacute = 0x01fd;
+ t.aekorean = 0x3150;
+ t.aemacron = 0x01e3;
+ t.afii00208 = 0x2015;
+ t.afii08941 = 0x20a4;
+ t.afii10017 = 0x0410;
+ t.afii10018 = 0x0411;
+ t.afii10019 = 0x0412;
+ t.afii10020 = 0x0413;
+ t.afii10021 = 0x0414;
+ t.afii10022 = 0x0415;
+ t.afii10023 = 0x0401;
+ t.afii10024 = 0x0416;
+ t.afii10025 = 0x0417;
+ t.afii10026 = 0x0418;
+ t.afii10027 = 0x0419;
+ t.afii10028 = 0x041a;
+ t.afii10029 = 0x041b;
+ t.afii10030 = 0x041c;
+ t.afii10031 = 0x041d;
+ t.afii10032 = 0x041e;
+ t.afii10033 = 0x041f;
+ t.afii10034 = 0x0420;
+ t.afii10035 = 0x0421;
+ t.afii10036 = 0x0422;
+ t.afii10037 = 0x0423;
+ t.afii10038 = 0x0424;
+ t.afii10039 = 0x0425;
+ t.afii10040 = 0x0426;
+ t.afii10041 = 0x0427;
+ t.afii10042 = 0x0428;
+ t.afii10043 = 0x0429;
+ t.afii10044 = 0x042a;
+ t.afii10045 = 0x042b;
+ t.afii10046 = 0x042c;
+ t.afii10047 = 0x042d;
+ t.afii10048 = 0x042e;
+ t.afii10049 = 0x042f;
+ t.afii10050 = 0x0490;
+ t.afii10051 = 0x0402;
+ t.afii10052 = 0x0403;
+ t.afii10053 = 0x0404;
+ t.afii10054 = 0x0405;
+ t.afii10055 = 0x0406;
+ t.afii10056 = 0x0407;
+ t.afii10057 = 0x0408;
+ t.afii10058 = 0x0409;
+ t.afii10059 = 0x040a;
+ t.afii10060 = 0x040b;
+ t.afii10061 = 0x040c;
+ t.afii10062 = 0x040e;
+ t.afii10063 = 0xf6c4;
+ t.afii10064 = 0xf6c5;
+ t.afii10065 = 0x0430;
+ t.afii10066 = 0x0431;
+ t.afii10067 = 0x0432;
+ t.afii10068 = 0x0433;
+ t.afii10069 = 0x0434;
+ t.afii10070 = 0x0435;
+ t.afii10071 = 0x0451;
+ t.afii10072 = 0x0436;
+ t.afii10073 = 0x0437;
+ t.afii10074 = 0x0438;
+ t.afii10075 = 0x0439;
+ t.afii10076 = 0x043a;
+ t.afii10077 = 0x043b;
+ t.afii10078 = 0x043c;
+ t.afii10079 = 0x043d;
+ t.afii10080 = 0x043e;
+ t.afii10081 = 0x043f;
+ t.afii10082 = 0x0440;
+ t.afii10083 = 0x0441;
+ t.afii10084 = 0x0442;
+ t.afii10085 = 0x0443;
+ t.afii10086 = 0x0444;
+ t.afii10087 = 0x0445;
+ t.afii10088 = 0x0446;
+ t.afii10089 = 0x0447;
+ t.afii10090 = 0x0448;
+ t.afii10091 = 0x0449;
+ t.afii10092 = 0x044a;
+ t.afii10093 = 0x044b;
+ t.afii10094 = 0x044c;
+ t.afii10095 = 0x044d;
+ t.afii10096 = 0x044e;
+ t.afii10097 = 0x044f;
+ t.afii10098 = 0x0491;
+ t.afii10099 = 0x0452;
+ t.afii10100 = 0x0453;
+ t.afii10101 = 0x0454;
+ t.afii10102 = 0x0455;
+ t.afii10103 = 0x0456;
+ t.afii10104 = 0x0457;
+ t.afii10105 = 0x0458;
+ t.afii10106 = 0x0459;
+ t.afii10107 = 0x045a;
+ t.afii10108 = 0x045b;
+ t.afii10109 = 0x045c;
+ t.afii10110 = 0x045e;
+ t.afii10145 = 0x040f;
+ t.afii10146 = 0x0462;
+ t.afii10147 = 0x0472;
+ t.afii10148 = 0x0474;
+ t.afii10192 = 0xf6c6;
+ t.afii10193 = 0x045f;
+ t.afii10194 = 0x0463;
+ t.afii10195 = 0x0473;
+ t.afii10196 = 0x0475;
+ t.afii10831 = 0xf6c7;
+ t.afii10832 = 0xf6c8;
+ t.afii10846 = 0x04d9;
+ t.afii299 = 0x200e;
+ t.afii300 = 0x200f;
+ t.afii301 = 0x200d;
+ t.afii57381 = 0x066a;
+ t.afii57388 = 0x060c;
+ t.afii57392 = 0x0660;
+ t.afii57393 = 0x0661;
+ t.afii57394 = 0x0662;
+ t.afii57395 = 0x0663;
+ t.afii57396 = 0x0664;
+ t.afii57397 = 0x0665;
+ t.afii57398 = 0x0666;
+ t.afii57399 = 0x0667;
+ t.afii57400 = 0x0668;
+ t.afii57401 = 0x0669;
+ t.afii57403 = 0x061b;
+ t.afii57407 = 0x061f;
+ t.afii57409 = 0x0621;
+ t.afii57410 = 0x0622;
+ t.afii57411 = 0x0623;
+ t.afii57412 = 0x0624;
+ t.afii57413 = 0x0625;
+ t.afii57414 = 0x0626;
+ t.afii57415 = 0x0627;
+ t.afii57416 = 0x0628;
+ t.afii57417 = 0x0629;
+ t.afii57418 = 0x062a;
+ t.afii57419 = 0x062b;
+ t.afii57420 = 0x062c;
+ t.afii57421 = 0x062d;
+ t.afii57422 = 0x062e;
+ t.afii57423 = 0x062f;
+ t.afii57424 = 0x0630;
+ t.afii57425 = 0x0631;
+ t.afii57426 = 0x0632;
+ t.afii57427 = 0x0633;
+ t.afii57428 = 0x0634;
+ t.afii57429 = 0x0635;
+ t.afii57430 = 0x0636;
+ t.afii57431 = 0x0637;
+ t.afii57432 = 0x0638;
+ t.afii57433 = 0x0639;
+ t.afii57434 = 0x063a;
+ t.afii57440 = 0x0640;
+ t.afii57441 = 0x0641;
+ t.afii57442 = 0x0642;
+ t.afii57443 = 0x0643;
+ t.afii57444 = 0x0644;
+ t.afii57445 = 0x0645;
+ t.afii57446 = 0x0646;
+ t.afii57448 = 0x0648;
+ t.afii57449 = 0x0649;
+ t.afii57450 = 0x064a;
+ t.afii57451 = 0x064b;
+ t.afii57452 = 0x064c;
+ t.afii57453 = 0x064d;
+ t.afii57454 = 0x064e;
+ t.afii57455 = 0x064f;
+ t.afii57456 = 0x0650;
+ t.afii57457 = 0x0651;
+ t.afii57458 = 0x0652;
+ t.afii57470 = 0x0647;
+ t.afii57505 = 0x06a4;
+ t.afii57506 = 0x067e;
+ t.afii57507 = 0x0686;
+ t.afii57508 = 0x0698;
+ t.afii57509 = 0x06af;
+ t.afii57511 = 0x0679;
+ t.afii57512 = 0x0688;
+ t.afii57513 = 0x0691;
+ t.afii57514 = 0x06ba;
+ t.afii57519 = 0x06d2;
+ t.afii57534 = 0x06d5;
+ t.afii57636 = 0x20aa;
+ t.afii57645 = 0x05be;
+ t.afii57658 = 0x05c3;
+ t.afii57664 = 0x05d0;
+ t.afii57665 = 0x05d1;
+ t.afii57666 = 0x05d2;
+ t.afii57667 = 0x05d3;
+ t.afii57668 = 0x05d4;
+ t.afii57669 = 0x05d5;
+ t.afii57670 = 0x05d6;
+ t.afii57671 = 0x05d7;
+ t.afii57672 = 0x05d8;
+ t.afii57673 = 0x05d9;
+ t.afii57674 = 0x05da;
+ t.afii57675 = 0x05db;
+ t.afii57676 = 0x05dc;
+ t.afii57677 = 0x05dd;
+ t.afii57678 = 0x05de;
+ t.afii57679 = 0x05df;
+ t.afii57680 = 0x05e0;
+ t.afii57681 = 0x05e1;
+ t.afii57682 = 0x05e2;
+ t.afii57683 = 0x05e3;
+ t.afii57684 = 0x05e4;
+ t.afii57685 = 0x05e5;
+ t.afii57686 = 0x05e6;
+ t.afii57687 = 0x05e7;
+ t.afii57688 = 0x05e8;
+ t.afii57689 = 0x05e9;
+ t.afii57690 = 0x05ea;
+ t.afii57694 = 0xfb2a;
+ t.afii57695 = 0xfb2b;
+ t.afii57700 = 0xfb4b;
+ t.afii57705 = 0xfb1f;
+ t.afii57716 = 0x05f0;
+ t.afii57717 = 0x05f1;
+ t.afii57718 = 0x05f2;
+ t.afii57723 = 0xfb35;
+ t.afii57793 = 0x05b4;
+ t.afii57794 = 0x05b5;
+ t.afii57795 = 0x05b6;
+ t.afii57796 = 0x05bb;
+ t.afii57797 = 0x05b8;
+ t.afii57798 = 0x05b7;
+ t.afii57799 = 0x05b0;
+ t.afii57800 = 0x05b2;
+ t.afii57801 = 0x05b1;
+ t.afii57802 = 0x05b3;
+ t.afii57803 = 0x05c2;
+ t.afii57804 = 0x05c1;
+ t.afii57806 = 0x05b9;
+ t.afii57807 = 0x05bc;
+ t.afii57839 = 0x05bd;
+ t.afii57841 = 0x05bf;
+ t.afii57842 = 0x05c0;
+ t.afii57929 = 0x02bc;
+ t.afii61248 = 0x2105;
+ t.afii61289 = 0x2113;
+ t.afii61352 = 0x2116;
+ t.afii61573 = 0x202c;
+ t.afii61574 = 0x202d;
+ t.afii61575 = 0x202e;
+ t.afii61664 = 0x200c;
+ t.afii63167 = 0x066d;
+ t.afii64937 = 0x02bd;
+ t.agrave = 0x00e0;
+ t.agujarati = 0x0a85;
+ t.agurmukhi = 0x0a05;
+ t.ahiragana = 0x3042;
+ t.ahookabove = 0x1ea3;
+ t.aibengali = 0x0990;
+ t.aibopomofo = 0x311e;
+ t.aideva = 0x0910;
+ t.aiecyrillic = 0x04d5;
+ t.aigujarati = 0x0a90;
+ t.aigurmukhi = 0x0a10;
+ t.aimatragurmukhi = 0x0a48;
+ t.ainarabic = 0x0639;
+ t.ainfinalarabic = 0xfeca;
+ t.aininitialarabic = 0xfecb;
+ t.ainmedialarabic = 0xfecc;
+ t.ainvertedbreve = 0x0203;
+ t.aivowelsignbengali = 0x09c8;
+ t.aivowelsigndeva = 0x0948;
+ t.aivowelsigngujarati = 0x0ac8;
+ t.akatakana = 0x30a2;
+ t.akatakanahalfwidth = 0xff71;
+ t.akorean = 0x314f;
+ t.alef = 0x05d0;
+ t.alefarabic = 0x0627;
+ t.alefdageshhebrew = 0xfb30;
+ t.aleffinalarabic = 0xfe8e;
+ t.alefhamzaabovearabic = 0x0623;
+ t.alefhamzaabovefinalarabic = 0xfe84;
+ t.alefhamzabelowarabic = 0x0625;
+ t.alefhamzabelowfinalarabic = 0xfe88;
+ t.alefhebrew = 0x05d0;
+ t.aleflamedhebrew = 0xfb4f;
+ t.alefmaddaabovearabic = 0x0622;
+ t.alefmaddaabovefinalarabic = 0xfe82;
+ t.alefmaksuraarabic = 0x0649;
+ t.alefmaksurafinalarabic = 0xfef0;
+ t.alefmaksurainitialarabic = 0xfef3;
+ t.alefmaksuramedialarabic = 0xfef4;
+ t.alefpatahhebrew = 0xfb2e;
+ t.alefqamatshebrew = 0xfb2f;
+ t.aleph = 0x2135;
+ t.allequal = 0x224c;
+ t.alpha = 0x03b1;
+ t.alphatonos = 0x03ac;
+ t.amacron = 0x0101;
+ t.amonospace = 0xff41;
+ t.ampersand = 0x0026;
+ t.ampersandmonospace = 0xff06;
+ t.ampersandsmall = 0xf726;
+ t.amsquare = 0x33c2;
+ t.anbopomofo = 0x3122;
+ t.angbopomofo = 0x3124;
+ t.angbracketleft = 0x3008;
+ t.angbracketright = 0x3009;
+ t.angkhankhuthai = 0x0e5a;
+ t.angle = 0x2220;
+ t.anglebracketleft = 0x3008;
+ t.anglebracketleftvertical = 0xfe3f;
+ t.anglebracketright = 0x3009;
+ t.anglebracketrightvertical = 0xfe40;
+ t.angleleft = 0x2329;
+ t.angleright = 0x232a;
+ t.angstrom = 0x212b;
+ t.anoteleia = 0x0387;
+ t.anudattadeva = 0x0952;
+ t.anusvarabengali = 0x0982;
+ t.anusvaradeva = 0x0902;
+ t.anusvaragujarati = 0x0a82;
+ t.aogonek = 0x0105;
+ t.apaatosquare = 0x3300;
+ t.aparen = 0x249c;
+ t.apostrophearmenian = 0x055a;
+ t.apostrophemod = 0x02bc;
+ t.apple = 0xf8ff;
+ t.approaches = 0x2250;
+ t.approxequal = 0x2248;
+ t.approxequalorimage = 0x2252;
+ t.approximatelyequal = 0x2245;
+ t.araeaekorean = 0x318e;
+ t.araeakorean = 0x318d;
+ t.arc = 0x2312;
+ t.arighthalfring = 0x1e9a;
+ t.aring = 0x00e5;
+ t.aringacute = 0x01fb;
+ t.aringbelow = 0x1e01;
+ t.arrowboth = 0x2194;
+ t.arrowdashdown = 0x21e3;
+ t.arrowdashleft = 0x21e0;
+ t.arrowdashright = 0x21e2;
+ t.arrowdashup = 0x21e1;
+ t.arrowdblboth = 0x21d4;
+ t.arrowdbldown = 0x21d3;
+ t.arrowdblleft = 0x21d0;
+ t.arrowdblright = 0x21d2;
+ t.arrowdblup = 0x21d1;
+ t.arrowdown = 0x2193;
+ t.arrowdownleft = 0x2199;
+ t.arrowdownright = 0x2198;
+ t.arrowdownwhite = 0x21e9;
+ t.arrowheaddownmod = 0x02c5;
+ t.arrowheadleftmod = 0x02c2;
+ t.arrowheadrightmod = 0x02c3;
+ t.arrowheadupmod = 0x02c4;
+ t.arrowhorizex = 0xf8e7;
+ t.arrowleft = 0x2190;
+ t.arrowleftdbl = 0x21d0;
+ t.arrowleftdblstroke = 0x21cd;
+ t.arrowleftoverright = 0x21c6;
+ t.arrowleftwhite = 0x21e6;
+ t.arrowright = 0x2192;
+ t.arrowrightdblstroke = 0x21cf;
+ t.arrowrightheavy = 0x279e;
+ t.arrowrightoverleft = 0x21c4;
+ t.arrowrightwhite = 0x21e8;
+ t.arrowtableft = 0x21e4;
+ t.arrowtabright = 0x21e5;
+ t.arrowup = 0x2191;
+ t.arrowupdn = 0x2195;
+ t.arrowupdnbse = 0x21a8;
+ t.arrowupdownbase = 0x21a8;
+ t.arrowupleft = 0x2196;
+ t.arrowupleftofdown = 0x21c5;
+ t.arrowupright = 0x2197;
+ t.arrowupwhite = 0x21e7;
+ t.arrowvertex = 0xf8e6;
+ t.asciicircum = 0x005e;
+ t.asciicircummonospace = 0xff3e;
+ t.asciitilde = 0x007e;
+ t.asciitildemonospace = 0xff5e;
+ t.ascript = 0x0251;
+ t.ascriptturned = 0x0252;
+ t.asmallhiragana = 0x3041;
+ t.asmallkatakana = 0x30a1;
+ t.asmallkatakanahalfwidth = 0xff67;
+ t.asterisk = 0x002a;
+ t.asteriskaltonearabic = 0x066d;
+ t.asteriskarabic = 0x066d;
+ t.asteriskmath = 0x2217;
+ t.asteriskmonospace = 0xff0a;
+ t.asterisksmall = 0xfe61;
+ t.asterism = 0x2042;
+ t.asuperior = 0xf6e9;
+ t.asymptoticallyequal = 0x2243;
+ t.at = 0x0040;
+ t.atilde = 0x00e3;
+ t.atmonospace = 0xff20;
+ t.atsmall = 0xfe6b;
+ t.aturned = 0x0250;
+ t.aubengali = 0x0994;
+ t.aubopomofo = 0x3120;
+ t.audeva = 0x0914;
+ t.augujarati = 0x0a94;
+ t.augurmukhi = 0x0a14;
+ t.aulengthmarkbengali = 0x09d7;
+ t.aumatragurmukhi = 0x0a4c;
+ t.auvowelsignbengali = 0x09cc;
+ t.auvowelsigndeva = 0x094c;
+ t.auvowelsigngujarati = 0x0acc;
+ t.avagrahadeva = 0x093d;
+ t.aybarmenian = 0x0561;
+ t.ayin = 0x05e2;
+ t.ayinaltonehebrew = 0xfb20;
+ t.ayinhebrew = 0x05e2;
+ t.b = 0x0062;
+ t.babengali = 0x09ac;
+ t.backslash = 0x005c;
+ t.backslashmonospace = 0xff3c;
+ t.badeva = 0x092c;
+ t.bagujarati = 0x0aac;
+ t.bagurmukhi = 0x0a2c;
+ t.bahiragana = 0x3070;
+ t.bahtthai = 0x0e3f;
+ t.bakatakana = 0x30d0;
+ t.bar = 0x007c;
+ t.barmonospace = 0xff5c;
+ t.bbopomofo = 0x3105;
+ t.bcircle = 0x24d1;
+ t.bdotaccent = 0x1e03;
+ t.bdotbelow = 0x1e05;
+ t.beamedsixteenthnotes = 0x266c;
+ t.because = 0x2235;
+ t.becyrillic = 0x0431;
+ t.beharabic = 0x0628;
+ t.behfinalarabic = 0xfe90;
+ t.behinitialarabic = 0xfe91;
+ t.behiragana = 0x3079;
+ t.behmedialarabic = 0xfe92;
+ t.behmeeminitialarabic = 0xfc9f;
+ t.behmeemisolatedarabic = 0xfc08;
+ t.behnoonfinalarabic = 0xfc6d;
+ t.bekatakana = 0x30d9;
+ t.benarmenian = 0x0562;
+ t.bet = 0x05d1;
+ t.beta = 0x03b2;
+ t.betasymbolgreek = 0x03d0;
+ t.betdagesh = 0xfb31;
+ t.betdageshhebrew = 0xfb31;
+ t.bethebrew = 0x05d1;
+ t.betrafehebrew = 0xfb4c;
+ t.bhabengali = 0x09ad;
+ t.bhadeva = 0x092d;
+ t.bhagujarati = 0x0aad;
+ t.bhagurmukhi = 0x0a2d;
+ t.bhook = 0x0253;
+ t.bihiragana = 0x3073;
+ t.bikatakana = 0x30d3;
+ t.bilabialclick = 0x0298;
+ t.bindigurmukhi = 0x0a02;
+ t.birusquare = 0x3331;
+ t.blackcircle = 0x25cf;
+ t.blackdiamond = 0x25c6;
+ t.blackdownpointingtriangle = 0x25bc;
+ t.blackleftpointingpointer = 0x25c4;
+ t.blackleftpointingtriangle = 0x25c0;
+ t.blacklenticularbracketleft = 0x3010;
+ t.blacklenticularbracketleftvertical = 0xfe3b;
+ t.blacklenticularbracketright = 0x3011;
+ t.blacklenticularbracketrightvertical = 0xfe3c;
+ t.blacklowerlefttriangle = 0x25e3;
+ t.blacklowerrighttriangle = 0x25e2;
+ t.blackrectangle = 0x25ac;
+ t.blackrightpointingpointer = 0x25ba;
+ t.blackrightpointingtriangle = 0x25b6;
+ t.blacksmallsquare = 0x25aa;
+ t.blacksmilingface = 0x263b;
+ t.blacksquare = 0x25a0;
+ t.blackstar = 0x2605;
+ t.blackupperlefttriangle = 0x25e4;
+ t.blackupperrighttriangle = 0x25e5;
+ t.blackuppointingsmalltriangle = 0x25b4;
+ t.blackuppointingtriangle = 0x25b2;
+ t.blank = 0x2423;
+ t.blinebelow = 0x1e07;
+ t.block = 0x2588;
+ t.bmonospace = 0xff42;
+ t.bobaimaithai = 0x0e1a;
+ t.bohiragana = 0x307c;
+ t.bokatakana = 0x30dc;
+ t.bparen = 0x249d;
+ t.bqsquare = 0x33c3;
+ t.braceex = 0xf8f4;
+ t.braceleft = 0x007b;
+ t.braceleftbt = 0xf8f3;
+ t.braceleftmid = 0xf8f2;
+ t.braceleftmonospace = 0xff5b;
+ t.braceleftsmall = 0xfe5b;
+ t.bracelefttp = 0xf8f1;
+ t.braceleftvertical = 0xfe37;
+ t.braceright = 0x007d;
+ t.bracerightbt = 0xf8fe;
+ t.bracerightmid = 0xf8fd;
+ t.bracerightmonospace = 0xff5d;
+ t.bracerightsmall = 0xfe5c;
+ t.bracerighttp = 0xf8fc;
+ t.bracerightvertical = 0xfe38;
+ t.bracketleft = 0x005b;
+ t.bracketleftbt = 0xf8f0;
+ t.bracketleftex = 0xf8ef;
+ t.bracketleftmonospace = 0xff3b;
+ t.bracketlefttp = 0xf8ee;
+ t.bracketright = 0x005d;
+ t.bracketrightbt = 0xf8fb;
+ t.bracketrightex = 0xf8fa;
+ t.bracketrightmonospace = 0xff3d;
+ t.bracketrighttp = 0xf8f9;
+ t.breve = 0x02d8;
+ t.brevebelowcmb = 0x032e;
+ t.brevecmb = 0x0306;
+ t.breveinvertedbelowcmb = 0x032f;
+ t.breveinvertedcmb = 0x0311;
+ t.breveinverteddoublecmb = 0x0361;
+ t.bridgebelowcmb = 0x032a;
+ t.bridgeinvertedbelowcmb = 0x033a;
+ t.brokenbar = 0x00a6;
+ t.bstroke = 0x0180;
+ t.bsuperior = 0xf6ea;
+ t.btopbar = 0x0183;
+ t.buhiragana = 0x3076;
+ t.bukatakana = 0x30d6;
+ t.bullet = 0x2022;
+ t.bulletinverse = 0x25d8;
+ t.bulletoperator = 0x2219;
+ t.bullseye = 0x25ce;
+ t.c = 0x0063;
+ t.caarmenian = 0x056e;
+ t.cabengali = 0x099a;
+ t.cacute = 0x0107;
+ t.cadeva = 0x091a;
+ t.cagujarati = 0x0a9a;
+ t.cagurmukhi = 0x0a1a;
+ t.calsquare = 0x3388;
+ t.candrabindubengali = 0x0981;
+ t.candrabinducmb = 0x0310;
+ t.candrabindudeva = 0x0901;
+ t.candrabindugujarati = 0x0a81;
+ t.capslock = 0x21ea;
+ t.careof = 0x2105;
+ t.caron = 0x02c7;
+ t.caronbelowcmb = 0x032c;
+ t.caroncmb = 0x030c;
+ t.carriagereturn = 0x21b5;
+ t.cbopomofo = 0x3118;
+ t.ccaron = 0x010d;
+ t.ccedilla = 0x00e7;
+ t.ccedillaacute = 0x1e09;
+ t.ccircle = 0x24d2;
+ t.ccircumflex = 0x0109;
+ t.ccurl = 0x0255;
+ t.cdot = 0x010b;
+ t.cdotaccent = 0x010b;
+ t.cdsquare = 0x33c5;
+ t.cedilla = 0x00b8;
+ t.cedillacmb = 0x0327;
+ t.cent = 0x00a2;
+ t.centigrade = 0x2103;
+ t.centinferior = 0xf6df;
+ t.centmonospace = 0xffe0;
+ t.centoldstyle = 0xf7a2;
+ t.centsuperior = 0xf6e0;
+ t.chaarmenian = 0x0579;
+ t.chabengali = 0x099b;
+ t.chadeva = 0x091b;
+ t.chagujarati = 0x0a9b;
+ t.chagurmukhi = 0x0a1b;
+ t.chbopomofo = 0x3114;
+ t.cheabkhasiancyrillic = 0x04bd;
+ t.checkmark = 0x2713;
+ t.checyrillic = 0x0447;
+ t.chedescenderabkhasiancyrillic = 0x04bf;
+ t.chedescendercyrillic = 0x04b7;
+ t.chedieresiscyrillic = 0x04f5;
+ t.cheharmenian = 0x0573;
+ t.chekhakassiancyrillic = 0x04cc;
+ t.cheverticalstrokecyrillic = 0x04b9;
+ t.chi = 0x03c7;
+ t.chieuchacirclekorean = 0x3277;
+ t.chieuchaparenkorean = 0x3217;
+ t.chieuchcirclekorean = 0x3269;
+ t.chieuchkorean = 0x314a;
+ t.chieuchparenkorean = 0x3209;
+ t.chochangthai = 0x0e0a;
+ t.chochanthai = 0x0e08;
+ t.chochingthai = 0x0e09;
+ t.chochoethai = 0x0e0c;
+ t.chook = 0x0188;
+ t.cieucacirclekorean = 0x3276;
+ t.cieucaparenkorean = 0x3216;
+ t.cieuccirclekorean = 0x3268;
+ t.cieuckorean = 0x3148;
+ t.cieucparenkorean = 0x3208;
+ t.cieucuparenkorean = 0x321c;
+ t.circle = 0x25cb;
+ t.circlecopyrt = 0x00a9;
+ t.circlemultiply = 0x2297;
+ t.circleot = 0x2299;
+ t.circleplus = 0x2295;
+ t.circlepostalmark = 0x3036;
+ t.circlewithlefthalfblack = 0x25d0;
+ t.circlewithrighthalfblack = 0x25d1;
+ t.circumflex = 0x02c6;
+ t.circumflexbelowcmb = 0x032d;
+ t.circumflexcmb = 0x0302;
+ t.clear = 0x2327;
+ t.clickalveolar = 0x01c2;
+ t.clickdental = 0x01c0;
+ t.clicklateral = 0x01c1;
+ t.clickretroflex = 0x01c3;
+ t.club = 0x2663;
+ t.clubsuitblack = 0x2663;
+ t.clubsuitwhite = 0x2667;
+ t.cmcubedsquare = 0x33a4;
+ t.cmonospace = 0xff43;
+ t.cmsquaredsquare = 0x33a0;
+ t.coarmenian = 0x0581;
+ t.colon = 0x003a;
+ t.colonmonetary = 0x20a1;
+ t.colonmonospace = 0xff1a;
+ t.colonsign = 0x20a1;
+ t.colonsmall = 0xfe55;
+ t.colontriangularhalfmod = 0x02d1;
+ t.colontriangularmod = 0x02d0;
+ t.comma = 0x002c;
+ t.commaabovecmb = 0x0313;
+ t.commaaboverightcmb = 0x0315;
+ t.commaaccent = 0xf6c3;
+ t.commaarabic = 0x060c;
+ t.commaarmenian = 0x055d;
+ t.commainferior = 0xf6e1;
+ t.commamonospace = 0xff0c;
+ t.commareversedabovecmb = 0x0314;
+ t.commareversedmod = 0x02bd;
+ t.commasmall = 0xfe50;
+ t.commasuperior = 0xf6e2;
+ t.commaturnedabovecmb = 0x0312;
+ t.commaturnedmod = 0x02bb;
+ t.compass = 0x263c;
+ t.congruent = 0x2245;
+ t.contourintegral = 0x222e;
+ t.control = 0x2303;
+ t.controlACK = 0x0006;
+ t.controlBEL = 0x0007;
+ t.controlBS = 0x0008;
+ t.controlCAN = 0x0018;
+ t.controlCR = 0x000d;
+ t.controlDC1 = 0x0011;
+ t.controlDC2 = 0x0012;
+ t.controlDC3 = 0x0013;
+ t.controlDC4 = 0x0014;
+ t.controlDEL = 0x007f;
+ t.controlDLE = 0x0010;
+ t.controlEM = 0x0019;
+ t.controlENQ = 0x0005;
+ t.controlEOT = 0x0004;
+ t.controlESC = 0x001b;
+ t.controlETB = 0x0017;
+ t.controlETX = 0x0003;
+ t.controlFF = 0x000c;
+ t.controlFS = 0x001c;
+ t.controlGS = 0x001d;
+ t.controlHT = 0x0009;
+ t.controlLF = 0x000a;
+ t.controlNAK = 0x0015;
+ t.controlNULL = 0x0000;
+ t.controlRS = 0x001e;
+ t.controlSI = 0x000f;
+ t.controlSO = 0x000e;
+ t.controlSOT = 0x0002;
+ t.controlSTX = 0x0001;
+ t.controlSUB = 0x001a;
+ t.controlSYN = 0x0016;
+ t.controlUS = 0x001f;
+ t.controlVT = 0x000b;
+ t.copyright = 0x00a9;
+ t.copyrightsans = 0xf8e9;
+ t.copyrightserif = 0xf6d9;
+ t.cornerbracketleft = 0x300c;
+ t.cornerbracketlefthalfwidth = 0xff62;
+ t.cornerbracketleftvertical = 0xfe41;
+ t.cornerbracketright = 0x300d;
+ t.cornerbracketrighthalfwidth = 0xff63;
+ t.cornerbracketrightvertical = 0xfe42;
+ t.corporationsquare = 0x337f;
+ t.cosquare = 0x33c7;
+ t.coverkgsquare = 0x33c6;
+ t.cparen = 0x249e;
+ t.cruzeiro = 0x20a2;
+ t.cstretched = 0x0297;
+ t.curlyand = 0x22cf;
+ t.curlyor = 0x22ce;
+ t.currency = 0x00a4;
+ t.cyrBreve = 0xf6d1;
+ t.cyrFlex = 0xf6d2;
+ t.cyrbreve = 0xf6d4;
+ t.cyrflex = 0xf6d5;
+ t.d = 0x0064;
+ t.daarmenian = 0x0564;
+ t.dabengali = 0x09a6;
+ t.dadarabic = 0x0636;
+ t.dadeva = 0x0926;
+ t.dadfinalarabic = 0xfebe;
+ t.dadinitialarabic = 0xfebf;
+ t.dadmedialarabic = 0xfec0;
+ t.dagesh = 0x05bc;
+ t.dageshhebrew = 0x05bc;
+ t.dagger = 0x2020;
+ t.daggerdbl = 0x2021;
+ t.dagujarati = 0x0aa6;
+ t.dagurmukhi = 0x0a26;
+ t.dahiragana = 0x3060;
+ t.dakatakana = 0x30c0;
+ t.dalarabic = 0x062f;
+ t.dalet = 0x05d3;
+ t.daletdagesh = 0xfb33;
+ t.daletdageshhebrew = 0xfb33;
+ t.dalethebrew = 0x05d3;
+ t.dalfinalarabic = 0xfeaa;
+ t.dammaarabic = 0x064f;
+ t.dammalowarabic = 0x064f;
+ t.dammatanaltonearabic = 0x064c;
+ t.dammatanarabic = 0x064c;
+ t.danda = 0x0964;
+ t.dargahebrew = 0x05a7;
+ t.dargalefthebrew = 0x05a7;
+ t.dasiapneumatacyrilliccmb = 0x0485;
+ t.dblGrave = 0xf6d3;
+ t.dblanglebracketleft = 0x300a;
+ t.dblanglebracketleftvertical = 0xfe3d;
+ t.dblanglebracketright = 0x300b;
+ t.dblanglebracketrightvertical = 0xfe3e;
+ t.dblarchinvertedbelowcmb = 0x032b;
+ t.dblarrowleft = 0x21d4;
+ t.dblarrowright = 0x21d2;
+ t.dbldanda = 0x0965;
+ t.dblgrave = 0xf6d6;
+ t.dblgravecmb = 0x030f;
+ t.dblintegral = 0x222c;
+ t.dbllowline = 0x2017;
+ t.dbllowlinecmb = 0x0333;
+ t.dbloverlinecmb = 0x033f;
+ t.dblprimemod = 0x02ba;
+ t.dblverticalbar = 0x2016;
+ t.dblverticallineabovecmb = 0x030e;
+ t.dbopomofo = 0x3109;
+ t.dbsquare = 0x33c8;
+ t.dcaron = 0x010f;
+ t.dcedilla = 0x1e11;
+ t.dcircle = 0x24d3;
+ t.dcircumflexbelow = 0x1e13;
+ t.dcroat = 0x0111;
+ t.ddabengali = 0x09a1;
+ t.ddadeva = 0x0921;
+ t.ddagujarati = 0x0aa1;
+ t.ddagurmukhi = 0x0a21;
+ t.ddalarabic = 0x0688;
+ t.ddalfinalarabic = 0xfb89;
+ t.dddhadeva = 0x095c;
+ t.ddhabengali = 0x09a2;
+ t.ddhadeva = 0x0922;
+ t.ddhagujarati = 0x0aa2;
+ t.ddhagurmukhi = 0x0a22;
+ t.ddotaccent = 0x1e0b;
+ t.ddotbelow = 0x1e0d;
+ t.decimalseparatorarabic = 0x066b;
+ t.decimalseparatorpersian = 0x066b;
+ t.decyrillic = 0x0434;
+ t.degree = 0x00b0;
+ t.dehihebrew = 0x05ad;
+ t.dehiragana = 0x3067;
+ t.deicoptic = 0x03ef;
+ t.dekatakana = 0x30c7;
+ t.deleteleft = 0x232b;
+ t.deleteright = 0x2326;
+ t.delta = 0x03b4;
+ t.deltaturned = 0x018d;
+ t.denominatorminusonenumeratorbengali = 0x09f8;
+ t.dezh = 0x02a4;
+ t.dhabengali = 0x09a7;
+ t.dhadeva = 0x0927;
+ t.dhagujarati = 0x0aa7;
+ t.dhagurmukhi = 0x0a27;
+ t.dhook = 0x0257;
+ t.dialytikatonos = 0x0385;
+ t.dialytikatonoscmb = 0x0344;
+ t.diamond = 0x2666;
+ t.diamondsuitwhite = 0x2662;
+ t.dieresis = 0x00a8;
+ t.dieresisacute = 0xf6d7;
+ t.dieresisbelowcmb = 0x0324;
+ t.dieresiscmb = 0x0308;
+ t.dieresisgrave = 0xf6d8;
+ t.dieresistonos = 0x0385;
+ t.dihiragana = 0x3062;
+ t.dikatakana = 0x30c2;
+ t.dittomark = 0x3003;
+ t.divide = 0x00f7;
+ t.divides = 0x2223;
+ t.divisionslash = 0x2215;
+ t.djecyrillic = 0x0452;
+ t.dkshade = 0x2593;
+ t.dlinebelow = 0x1e0f;
+ t.dlsquare = 0x3397;
+ t.dmacron = 0x0111;
+ t.dmonospace = 0xff44;
+ t.dnblock = 0x2584;
+ t.dochadathai = 0x0e0e;
+ t.dodekthai = 0x0e14;
+ t.dohiragana = 0x3069;
+ t.dokatakana = 0x30c9;
+ t.dollar = 0x0024;
+ t.dollarinferior = 0xf6e3;
+ t.dollarmonospace = 0xff04;
+ t.dollaroldstyle = 0xf724;
+ t.dollarsmall = 0xfe69;
+ t.dollarsuperior = 0xf6e4;
+ t.dong = 0x20ab;
+ t.dorusquare = 0x3326;
+ t.dotaccent = 0x02d9;
+ t.dotaccentcmb = 0x0307;
+ t.dotbelowcmb = 0x0323;
+ t.dotbelowcomb = 0x0323;
+ t.dotkatakana = 0x30fb;
+ t.dotlessi = 0x0131;
+ t.dotlessj = 0xf6be;
+ t.dotlessjstrokehook = 0x0284;
+ t.dotmath = 0x22c5;
+ t.dottedcircle = 0x25cc;
+ t.doubleyodpatah = 0xfb1f;
+ t.doubleyodpatahhebrew = 0xfb1f;
+ t.downtackbelowcmb = 0x031e;
+ t.downtackmod = 0x02d5;
+ t.dparen = 0x249f;
+ t.dsuperior = 0xf6eb;
+ t.dtail = 0x0256;
+ t.dtopbar = 0x018c;
+ t.duhiragana = 0x3065;
+ t.dukatakana = 0x30c5;
+ t.dz = 0x01f3;
+ t.dzaltone = 0x02a3;
+ t.dzcaron = 0x01c6;
+ t.dzcurl = 0x02a5;
+ t.dzeabkhasiancyrillic = 0x04e1;
+ t.dzecyrillic = 0x0455;
+ t.dzhecyrillic = 0x045f;
+ t.e = 0x0065;
+ t.eacute = 0x00e9;
+ t.earth = 0x2641;
+ t.ebengali = 0x098f;
+ t.ebopomofo = 0x311c;
+ t.ebreve = 0x0115;
+ t.ecandradeva = 0x090d;
+ t.ecandragujarati = 0x0a8d;
+ t.ecandravowelsigndeva = 0x0945;
+ t.ecandravowelsigngujarati = 0x0ac5;
+ t.ecaron = 0x011b;
+ t.ecedillabreve = 0x1e1d;
+ t.echarmenian = 0x0565;
+ t.echyiwnarmenian = 0x0587;
+ t.ecircle = 0x24d4;
+ t.ecircumflex = 0x00ea;
+ t.ecircumflexacute = 0x1ebf;
+ t.ecircumflexbelow = 0x1e19;
+ t.ecircumflexdotbelow = 0x1ec7;
+ t.ecircumflexgrave = 0x1ec1;
+ t.ecircumflexhookabove = 0x1ec3;
+ t.ecircumflextilde = 0x1ec5;
+ t.ecyrillic = 0x0454;
+ t.edblgrave = 0x0205;
+ t.edeva = 0x090f;
+ t.edieresis = 0x00eb;
+ t.edot = 0x0117;
+ t.edotaccent = 0x0117;
+ t.edotbelow = 0x1eb9;
+ t.eegurmukhi = 0x0a0f;
+ t.eematragurmukhi = 0x0a47;
+ t.efcyrillic = 0x0444;
+ t.egrave = 0x00e8;
+ t.egujarati = 0x0a8f;
+ t.eharmenian = 0x0567;
+ t.ehbopomofo = 0x311d;
+ t.ehiragana = 0x3048;
+ t.ehookabove = 0x1ebb;
+ t.eibopomofo = 0x311f;
+ t.eight = 0x0038;
+ t.eightarabic = 0x0668;
+ t.eightbengali = 0x09ee;
+ t.eightcircle = 0x2467;
+ t.eightcircleinversesansserif = 0x2791;
+ t.eightdeva = 0x096e;
+ t.eighteencircle = 0x2471;
+ t.eighteenparen = 0x2485;
+ t.eighteenperiod = 0x2499;
+ t.eightgujarati = 0x0aee;
+ t.eightgurmukhi = 0x0a6e;
+ t.eighthackarabic = 0x0668;
+ t.eighthangzhou = 0x3028;
+ t.eighthnotebeamed = 0x266b;
+ t.eightideographicparen = 0x3227;
+ t.eightinferior = 0x2088;
+ t.eightmonospace = 0xff18;
+ t.eightoldstyle = 0xf738;
+ t.eightparen = 0x247b;
+ t.eightperiod = 0x248f;
+ t.eightpersian = 0x06f8;
+ t.eightroman = 0x2177;
+ t.eightsuperior = 0x2078;
+ t.eightthai = 0x0e58;
+ t.einvertedbreve = 0x0207;
+ t.eiotifiedcyrillic = 0x0465;
+ t.ekatakana = 0x30a8;
+ t.ekatakanahalfwidth = 0xff74;
+ t.ekonkargurmukhi = 0x0a74;
+ t.ekorean = 0x3154;
+ t.elcyrillic = 0x043b;
+ t.element = 0x2208;
+ t.elevencircle = 0x246a;
+ t.elevenparen = 0x247e;
+ t.elevenperiod = 0x2492;
+ t.elevenroman = 0x217a;
+ t.ellipsis = 0x2026;
+ t.ellipsisvertical = 0x22ee;
+ t.emacron = 0x0113;
+ t.emacronacute = 0x1e17;
+ t.emacrongrave = 0x1e15;
+ t.emcyrillic = 0x043c;
+ t.emdash = 0x2014;
+ t.emdashvertical = 0xfe31;
+ t.emonospace = 0xff45;
+ t.emphasismarkarmenian = 0x055b;
+ t.emptyset = 0x2205;
+ t.enbopomofo = 0x3123;
+ t.encyrillic = 0x043d;
+ t.endash = 0x2013;
+ t.endashvertical = 0xfe32;
+ t.endescendercyrillic = 0x04a3;
+ t.eng = 0x014b;
+ t.engbopomofo = 0x3125;
+ t.enghecyrillic = 0x04a5;
+ t.enhookcyrillic = 0x04c8;
+ t.enspace = 0x2002;
+ t.eogonek = 0x0119;
+ t.eokorean = 0x3153;
+ t.eopen = 0x025b;
+ t.eopenclosed = 0x029a;
+ t.eopenreversed = 0x025c;
+ t.eopenreversedclosed = 0x025e;
+ t.eopenreversedhook = 0x025d;
+ t.eparen = 0x24a0;
+ t.epsilon = 0x03b5;
+ t.epsilontonos = 0x03ad;
+ t.equal = 0x003d;
+ t.equalmonospace = 0xff1d;
+ t.equalsmall = 0xfe66;
+ t.equalsuperior = 0x207c;
+ t.equivalence = 0x2261;
+ t.erbopomofo = 0x3126;
+ t.ercyrillic = 0x0440;
+ t.ereversed = 0x0258;
+ t.ereversedcyrillic = 0x044d;
+ t.escyrillic = 0x0441;
+ t.esdescendercyrillic = 0x04ab;
+ t.esh = 0x0283;
+ t.eshcurl = 0x0286;
+ t.eshortdeva = 0x090e;
+ t.eshortvowelsigndeva = 0x0946;
+ t.eshreversedloop = 0x01aa;
+ t.eshsquatreversed = 0x0285;
+ t.esmallhiragana = 0x3047;
+ t.esmallkatakana = 0x30a7;
+ t.esmallkatakanahalfwidth = 0xff6a;
+ t.estimated = 0x212e;
+ t.esuperior = 0xf6ec;
+ t.eta = 0x03b7;
+ t.etarmenian = 0x0568;
+ t.etatonos = 0x03ae;
+ t.eth = 0x00f0;
+ t.etilde = 0x1ebd;
+ t.etildebelow = 0x1e1b;
+ t.etnahtafoukhhebrew = 0x0591;
+ t.etnahtafoukhlefthebrew = 0x0591;
+ t.etnahtahebrew = 0x0591;
+ t.etnahtalefthebrew = 0x0591;
+ t.eturned = 0x01dd;
+ t.eukorean = 0x3161;
+ t.euro = 0x20ac;
+ t.evowelsignbengali = 0x09c7;
+ t.evowelsigndeva = 0x0947;
+ t.evowelsigngujarati = 0x0ac7;
+ t.exclam = 0x0021;
+ t.exclamarmenian = 0x055c;
+ t.exclamdbl = 0x203c;
+ t.exclamdown = 0x00a1;
+ t.exclamdownsmall = 0xf7a1;
+ t.exclammonospace = 0xff01;
+ t.exclamsmall = 0xf721;
+ t.existential = 0x2203;
+ t.ezh = 0x0292;
+ t.ezhcaron = 0x01ef;
+ t.ezhcurl = 0x0293;
+ t.ezhreversed = 0x01b9;
+ t.ezhtail = 0x01ba;
+ t.f = 0x0066;
+ t.fadeva = 0x095e;
+ t.fagurmukhi = 0x0a5e;
+ t.fahrenheit = 0x2109;
+ t.fathaarabic = 0x064e;
+ t.fathalowarabic = 0x064e;
+ t.fathatanarabic = 0x064b;
+ t.fbopomofo = 0x3108;
+ t.fcircle = 0x24d5;
+ t.fdotaccent = 0x1e1f;
+ t.feharabic = 0x0641;
+ t.feharmenian = 0x0586;
+ t.fehfinalarabic = 0xfed2;
+ t.fehinitialarabic = 0xfed3;
+ t.fehmedialarabic = 0xfed4;
+ t.feicoptic = 0x03e5;
+ t.female = 0x2640;
+ t.ff = 0xfb00;
+ t.f_f = 0xfb00;
+ t.ffi = 0xfb03;
+ t.f_f_i = 0xfb03;
+ t.ffl = 0xfb04;
+ t.f_f_l = 0xfb04;
+ t.fi = 0xfb01;
+ t.f_i = 0xfb01;
+ t.fifteencircle = 0x246e;
+ t.fifteenparen = 0x2482;
+ t.fifteenperiod = 0x2496;
+ t.figuredash = 0x2012;
+ t.filledbox = 0x25a0;
+ t.filledrect = 0x25ac;
+ t.finalkaf = 0x05da;
+ t.finalkafdagesh = 0xfb3a;
+ t.finalkafdageshhebrew = 0xfb3a;
+ t.finalkafhebrew = 0x05da;
+ t.finalmem = 0x05dd;
+ t.finalmemhebrew = 0x05dd;
+ t.finalnun = 0x05df;
+ t.finalnunhebrew = 0x05df;
+ t.finalpe = 0x05e3;
+ t.finalpehebrew = 0x05e3;
+ t.finaltsadi = 0x05e5;
+ t.finaltsadihebrew = 0x05e5;
+ t.firsttonechinese = 0x02c9;
+ t.fisheye = 0x25c9;
+ t.fitacyrillic = 0x0473;
+ t.five = 0x0035;
+ t.fivearabic = 0x0665;
+ t.fivebengali = 0x09eb;
+ t.fivecircle = 0x2464;
+ t.fivecircleinversesansserif = 0x278e;
+ t.fivedeva = 0x096b;
+ t.fiveeighths = 0x215d;
+ t.fivegujarati = 0x0aeb;
+ t.fivegurmukhi = 0x0a6b;
+ t.fivehackarabic = 0x0665;
+ t.fivehangzhou = 0x3025;
+ t.fiveideographicparen = 0x3224;
+ t.fiveinferior = 0x2085;
+ t.fivemonospace = 0xff15;
+ t.fiveoldstyle = 0xf735;
+ t.fiveparen = 0x2478;
+ t.fiveperiod = 0x248c;
+ t.fivepersian = 0x06f5;
+ t.fiveroman = 0x2174;
+ t.fivesuperior = 0x2075;
+ t.fivethai = 0x0e55;
+ t.fl = 0xfb02;
+ t.f_l = 0xfb02;
+ t.florin = 0x0192;
+ t.fmonospace = 0xff46;
+ t.fmsquare = 0x3399;
+ t.fofanthai = 0x0e1f;
+ t.fofathai = 0x0e1d;
+ t.fongmanthai = 0x0e4f;
+ t.forall = 0x2200;
+ t.four = 0x0034;
+ t.fourarabic = 0x0664;
+ t.fourbengali = 0x09ea;
+ t.fourcircle = 0x2463;
+ t.fourcircleinversesansserif = 0x278d;
+ t.fourdeva = 0x096a;
+ t.fourgujarati = 0x0aea;
+ t.fourgurmukhi = 0x0a6a;
+ t.fourhackarabic = 0x0664;
+ t.fourhangzhou = 0x3024;
+ t.fourideographicparen = 0x3223;
+ t.fourinferior = 0x2084;
+ t.fourmonospace = 0xff14;
+ t.fournumeratorbengali = 0x09f7;
+ t.fouroldstyle = 0xf734;
+ t.fourparen = 0x2477;
+ t.fourperiod = 0x248b;
+ t.fourpersian = 0x06f4;
+ t.fourroman = 0x2173;
+ t.foursuperior = 0x2074;
+ t.fourteencircle = 0x246d;
+ t.fourteenparen = 0x2481;
+ t.fourteenperiod = 0x2495;
+ t.fourthai = 0x0e54;
+ t.fourthtonechinese = 0x02cb;
+ t.fparen = 0x24a1;
+ t.fraction = 0x2044;
+ t.franc = 0x20a3;
+ t.g = 0x0067;
+ t.gabengali = 0x0997;
+ t.gacute = 0x01f5;
+ t.gadeva = 0x0917;
+ t.gafarabic = 0x06af;
+ t.gaffinalarabic = 0xfb93;
+ t.gafinitialarabic = 0xfb94;
+ t.gafmedialarabic = 0xfb95;
+ t.gagujarati = 0x0a97;
+ t.gagurmukhi = 0x0a17;
+ t.gahiragana = 0x304c;
+ t.gakatakana = 0x30ac;
+ t.gamma = 0x03b3;
+ t.gammalatinsmall = 0x0263;
+ t.gammasuperior = 0x02e0;
+ t.gangiacoptic = 0x03eb;
+ t.gbopomofo = 0x310d;
+ t.gbreve = 0x011f;
+ t.gcaron = 0x01e7;
+ t.gcedilla = 0x0123;
+ t.gcircle = 0x24d6;
+ t.gcircumflex = 0x011d;
+ t.gcommaaccent = 0x0123;
+ t.gdot = 0x0121;
+ t.gdotaccent = 0x0121;
+ t.gecyrillic = 0x0433;
+ t.gehiragana = 0x3052;
+ t.gekatakana = 0x30b2;
+ t.geometricallyequal = 0x2251;
+ t.gereshaccenthebrew = 0x059c;
+ t.gereshhebrew = 0x05f3;
+ t.gereshmuqdamhebrew = 0x059d;
+ t.germandbls = 0x00df;
+ t.gershayimaccenthebrew = 0x059e;
+ t.gershayimhebrew = 0x05f4;
+ t.getamark = 0x3013;
+ t.ghabengali = 0x0998;
+ t.ghadarmenian = 0x0572;
+ t.ghadeva = 0x0918;
+ t.ghagujarati = 0x0a98;
+ t.ghagurmukhi = 0x0a18;
+ t.ghainarabic = 0x063a;
+ t.ghainfinalarabic = 0xfece;
+ t.ghaininitialarabic = 0xfecf;
+ t.ghainmedialarabic = 0xfed0;
+ t.ghemiddlehookcyrillic = 0x0495;
+ t.ghestrokecyrillic = 0x0493;
+ t.gheupturncyrillic = 0x0491;
+ t.ghhadeva = 0x095a;
+ t.ghhagurmukhi = 0x0a5a;
+ t.ghook = 0x0260;
+ t.ghzsquare = 0x3393;
+ t.gihiragana = 0x304e;
+ t.gikatakana = 0x30ae;
+ t.gimarmenian = 0x0563;
+ t.gimel = 0x05d2;
+ t.gimeldagesh = 0xfb32;
+ t.gimeldageshhebrew = 0xfb32;
+ t.gimelhebrew = 0x05d2;
+ t.gjecyrillic = 0x0453;
+ t.glottalinvertedstroke = 0x01be;
+ t.glottalstop = 0x0294;
+ t.glottalstopinverted = 0x0296;
+ t.glottalstopmod = 0x02c0;
+ t.glottalstopreversed = 0x0295;
+ t.glottalstopreversedmod = 0x02c1;
+ t.glottalstopreversedsuperior = 0x02e4;
+ t.glottalstopstroke = 0x02a1;
+ t.glottalstopstrokereversed = 0x02a2;
+ t.gmacron = 0x1e21;
+ t.gmonospace = 0xff47;
+ t.gohiragana = 0x3054;
+ t.gokatakana = 0x30b4;
+ t.gparen = 0x24a2;
+ t.gpasquare = 0x33ac;
+ t.gradient = 0x2207;
+ t.grave = 0x0060;
+ t.gravebelowcmb = 0x0316;
+ t.gravecmb = 0x0300;
+ t.gravecomb = 0x0300;
+ t.gravedeva = 0x0953;
+ t.gravelowmod = 0x02ce;
+ t.gravemonospace = 0xff40;
+ t.gravetonecmb = 0x0340;
+ t.greater = 0x003e;
+ t.greaterequal = 0x2265;
+ t.greaterequalorless = 0x22db;
+ t.greatermonospace = 0xff1e;
+ t.greaterorequivalent = 0x2273;
+ t.greaterorless = 0x2277;
+ t.greateroverequal = 0x2267;
+ t.greatersmall = 0xfe65;
+ t.gscript = 0x0261;
+ t.gstroke = 0x01e5;
+ t.guhiragana = 0x3050;
+ t.guillemotleft = 0x00ab;
+ t.guillemotright = 0x00bb;
+ t.guilsinglleft = 0x2039;
+ t.guilsinglright = 0x203a;
+ t.gukatakana = 0x30b0;
+ t.guramusquare = 0x3318;
+ t.gysquare = 0x33c9;
+ t.h = 0x0068;
+ t.haabkhasiancyrillic = 0x04a9;
+ t.haaltonearabic = 0x06c1;
+ t.habengali = 0x09b9;
+ t.hadescendercyrillic = 0x04b3;
+ t.hadeva = 0x0939;
+ t.hagujarati = 0x0ab9;
+ t.hagurmukhi = 0x0a39;
+ t.haharabic = 0x062d;
+ t.hahfinalarabic = 0xfea2;
+ t.hahinitialarabic = 0xfea3;
+ t.hahiragana = 0x306f;
+ t.hahmedialarabic = 0xfea4;
+ t.haitusquare = 0x332a;
+ t.hakatakana = 0x30cf;
+ t.hakatakanahalfwidth = 0xff8a;
+ t.halantgurmukhi = 0x0a4d;
+ t.hamzaarabic = 0x0621;
+ t.hamzalowarabic = 0x0621;
+ t.hangulfiller = 0x3164;
+ t.hardsigncyrillic = 0x044a;
+ t.harpoonleftbarbup = 0x21bc;
+ t.harpoonrightbarbup = 0x21c0;
+ t.hasquare = 0x33ca;
+ t.hatafpatah = 0x05b2;
+ t.hatafpatah16 = 0x05b2;
+ t.hatafpatah23 = 0x05b2;
+ t.hatafpatah2f = 0x05b2;
+ t.hatafpatahhebrew = 0x05b2;
+ t.hatafpatahnarrowhebrew = 0x05b2;
+ t.hatafpatahquarterhebrew = 0x05b2;
+ t.hatafpatahwidehebrew = 0x05b2;
+ t.hatafqamats = 0x05b3;
+ t.hatafqamats1b = 0x05b3;
+ t.hatafqamats28 = 0x05b3;
+ t.hatafqamats34 = 0x05b3;
+ t.hatafqamatshebrew = 0x05b3;
+ t.hatafqamatsnarrowhebrew = 0x05b3;
+ t.hatafqamatsquarterhebrew = 0x05b3;
+ t.hatafqamatswidehebrew = 0x05b3;
+ t.hatafsegol = 0x05b1;
+ t.hatafsegol17 = 0x05b1;
+ t.hatafsegol24 = 0x05b1;
+ t.hatafsegol30 = 0x05b1;
+ t.hatafsegolhebrew = 0x05b1;
+ t.hatafsegolnarrowhebrew = 0x05b1;
+ t.hatafsegolquarterhebrew = 0x05b1;
+ t.hatafsegolwidehebrew = 0x05b1;
+ t.hbar = 0x0127;
+ t.hbopomofo = 0x310f;
+ t.hbrevebelow = 0x1e2b;
+ t.hcedilla = 0x1e29;
+ t.hcircle = 0x24d7;
+ t.hcircumflex = 0x0125;
+ t.hdieresis = 0x1e27;
+ t.hdotaccent = 0x1e23;
+ t.hdotbelow = 0x1e25;
+ t.he = 0x05d4;
+ t.heart = 0x2665;
+ t.heartsuitblack = 0x2665;
+ t.heartsuitwhite = 0x2661;
+ t.hedagesh = 0xfb34;
+ t.hedageshhebrew = 0xfb34;
+ t.hehaltonearabic = 0x06c1;
+ t.heharabic = 0x0647;
+ t.hehebrew = 0x05d4;
+ t.hehfinalaltonearabic = 0xfba7;
+ t.hehfinalalttwoarabic = 0xfeea;
+ t.hehfinalarabic = 0xfeea;
+ t.hehhamzaabovefinalarabic = 0xfba5;
+ t.hehhamzaaboveisolatedarabic = 0xfba4;
+ t.hehinitialaltonearabic = 0xfba8;
+ t.hehinitialarabic = 0xfeeb;
+ t.hehiragana = 0x3078;
+ t.hehmedialaltonearabic = 0xfba9;
+ t.hehmedialarabic = 0xfeec;
+ t.heiseierasquare = 0x337b;
+ t.hekatakana = 0x30d8;
+ t.hekatakanahalfwidth = 0xff8d;
+ t.hekutaarusquare = 0x3336;
+ t.henghook = 0x0267;
+ t.herutusquare = 0x3339;
+ t.het = 0x05d7;
+ t.hethebrew = 0x05d7;
+ t.hhook = 0x0266;
+ t.hhooksuperior = 0x02b1;
+ t.hieuhacirclekorean = 0x327b;
+ t.hieuhaparenkorean = 0x321b;
+ t.hieuhcirclekorean = 0x326d;
+ t.hieuhkorean = 0x314e;
+ t.hieuhparenkorean = 0x320d;
+ t.hihiragana = 0x3072;
+ t.hikatakana = 0x30d2;
+ t.hikatakanahalfwidth = 0xff8b;
+ t.hiriq = 0x05b4;
+ t.hiriq14 = 0x05b4;
+ t.hiriq21 = 0x05b4;
+ t.hiriq2d = 0x05b4;
+ t.hiriqhebrew = 0x05b4;
+ t.hiriqnarrowhebrew = 0x05b4;
+ t.hiriqquarterhebrew = 0x05b4;
+ t.hiriqwidehebrew = 0x05b4;
+ t.hlinebelow = 0x1e96;
+ t.hmonospace = 0xff48;
+ t.hoarmenian = 0x0570;
+ t.hohipthai = 0x0e2b;
+ t.hohiragana = 0x307b;
+ t.hokatakana = 0x30db;
+ t.hokatakanahalfwidth = 0xff8e;
+ t.holam = 0x05b9;
+ t.holam19 = 0x05b9;
+ t.holam26 = 0x05b9;
+ t.holam32 = 0x05b9;
+ t.holamhebrew = 0x05b9;
+ t.holamnarrowhebrew = 0x05b9;
+ t.holamquarterhebrew = 0x05b9;
+ t.holamwidehebrew = 0x05b9;
+ t.honokhukthai = 0x0e2e;
+ t.hookabovecomb = 0x0309;
+ t.hookcmb = 0x0309;
+ t.hookpalatalizedbelowcmb = 0x0321;
+ t.hookretroflexbelowcmb = 0x0322;
+ t.hoonsquare = 0x3342;
+ t.horicoptic = 0x03e9;
+ t.horizontalbar = 0x2015;
+ t.horncmb = 0x031b;
+ t.hotsprings = 0x2668;
+ t.house = 0x2302;
+ t.hparen = 0x24a3;
+ t.hsuperior = 0x02b0;
+ t.hturned = 0x0265;
+ t.huhiragana = 0x3075;
+ t.huiitosquare = 0x3333;
+ t.hukatakana = 0x30d5;
+ t.hukatakanahalfwidth = 0xff8c;
+ t.hungarumlaut = 0x02dd;
+ t.hungarumlautcmb = 0x030b;
+ t.hv = 0x0195;
+ t.hyphen = 0x002d;
+ t.hypheninferior = 0xf6e5;
+ t.hyphenmonospace = 0xff0d;
+ t.hyphensmall = 0xfe63;
+ t.hyphensuperior = 0xf6e6;
+ t.hyphentwo = 0x2010;
+ t.i = 0x0069;
+ t.iacute = 0x00ed;
+ t.iacyrillic = 0x044f;
+ t.ibengali = 0x0987;
+ t.ibopomofo = 0x3127;
+ t.ibreve = 0x012d;
+ t.icaron = 0x01d0;
+ t.icircle = 0x24d8;
+ t.icircumflex = 0x00ee;
+ t.icyrillic = 0x0456;
+ t.idblgrave = 0x0209;
+ t.ideographearthcircle = 0x328f;
+ t.ideographfirecircle = 0x328b;
+ t.ideographicallianceparen = 0x323f;
+ t.ideographiccallparen = 0x323a;
+ t.ideographiccentrecircle = 0x32a5;
+ t.ideographicclose = 0x3006;
+ t.ideographiccomma = 0x3001;
+ t.ideographiccommaleft = 0xff64;
+ t.ideographiccongratulationparen = 0x3237;
+ t.ideographiccorrectcircle = 0x32a3;
+ t.ideographicearthparen = 0x322f;
+ t.ideographicenterpriseparen = 0x323d;
+ t.ideographicexcellentcircle = 0x329d;
+ t.ideographicfestivalparen = 0x3240;
+ t.ideographicfinancialcircle = 0x3296;
+ t.ideographicfinancialparen = 0x3236;
+ t.ideographicfireparen = 0x322b;
+ t.ideographichaveparen = 0x3232;
+ t.ideographichighcircle = 0x32a4;
+ t.ideographiciterationmark = 0x3005;
+ t.ideographiclaborcircle = 0x3298;
+ t.ideographiclaborparen = 0x3238;
+ t.ideographicleftcircle = 0x32a7;
+ t.ideographiclowcircle = 0x32a6;
+ t.ideographicmedicinecircle = 0x32a9;
+ t.ideographicmetalparen = 0x322e;
+ t.ideographicmoonparen = 0x322a;
+ t.ideographicnameparen = 0x3234;
+ t.ideographicperiod = 0x3002;
+ t.ideographicprintcircle = 0x329e;
+ t.ideographicreachparen = 0x3243;
+ t.ideographicrepresentparen = 0x3239;
+ t.ideographicresourceparen = 0x323e;
+ t.ideographicrightcircle = 0x32a8;
+ t.ideographicsecretcircle = 0x3299;
+ t.ideographicselfparen = 0x3242;
+ t.ideographicsocietyparen = 0x3233;
+ t.ideographicspace = 0x3000;
+ t.ideographicspecialparen = 0x3235;
+ t.ideographicstockparen = 0x3231;
+ t.ideographicstudyparen = 0x323b;
+ t.ideographicsunparen = 0x3230;
+ t.ideographicsuperviseparen = 0x323c;
+ t.ideographicwaterparen = 0x322c;
+ t.ideographicwoodparen = 0x322d;
+ t.ideographiczero = 0x3007;
+ t.ideographmetalcircle = 0x328e;
+ t.ideographmooncircle = 0x328a;
+ t.ideographnamecircle = 0x3294;
+ t.ideographsuncircle = 0x3290;
+ t.ideographwatercircle = 0x328c;
+ t.ideographwoodcircle = 0x328d;
+ t.ideva = 0x0907;
+ t.idieresis = 0x00ef;
+ t.idieresisacute = 0x1e2f;
+ t.idieresiscyrillic = 0x04e5;
+ t.idotbelow = 0x1ecb;
+ t.iebrevecyrillic = 0x04d7;
+ t.iecyrillic = 0x0435;
+ t.ieungacirclekorean = 0x3275;
+ t.ieungaparenkorean = 0x3215;
+ t.ieungcirclekorean = 0x3267;
+ t.ieungkorean = 0x3147;
+ t.ieungparenkorean = 0x3207;
+ t.igrave = 0x00ec;
+ t.igujarati = 0x0a87;
+ t.igurmukhi = 0x0a07;
+ t.ihiragana = 0x3044;
+ t.ihookabove = 0x1ec9;
+ t.iibengali = 0x0988;
+ t.iicyrillic = 0x0438;
+ t.iideva = 0x0908;
+ t.iigujarati = 0x0a88;
+ t.iigurmukhi = 0x0a08;
+ t.iimatragurmukhi = 0x0a40;
+ t.iinvertedbreve = 0x020b;
+ t.iishortcyrillic = 0x0439;
+ t.iivowelsignbengali = 0x09c0;
+ t.iivowelsigndeva = 0x0940;
+ t.iivowelsigngujarati = 0x0ac0;
+ t.ij = 0x0133;
+ t.ikatakana = 0x30a4;
+ t.ikatakanahalfwidth = 0xff72;
+ t.ikorean = 0x3163;
+ t.ilde = 0x02dc;
+ t.iluyhebrew = 0x05ac;
+ t.imacron = 0x012b;
+ t.imacroncyrillic = 0x04e3;
+ t.imageorapproximatelyequal = 0x2253;
+ t.imatragurmukhi = 0x0a3f;
+ t.imonospace = 0xff49;
+ t.increment = 0x2206;
+ t.infinity = 0x221e;
+ t.iniarmenian = 0x056b;
+ t.integral = 0x222b;
+ t.integralbottom = 0x2321;
+ t.integralbt = 0x2321;
+ t.integralex = 0xf8f5;
+ t.integraltop = 0x2320;
+ t.integraltp = 0x2320;
+ t.intersection = 0x2229;
+ t.intisquare = 0x3305;
+ t.invbullet = 0x25d8;
+ t.invcircle = 0x25d9;
+ t.invsmileface = 0x263b;
+ t.iocyrillic = 0x0451;
+ t.iogonek = 0x012f;
+ t.iota = 0x03b9;
+ t.iotadieresis = 0x03ca;
+ t.iotadieresistonos = 0x0390;
+ t.iotalatin = 0x0269;
+ t.iotatonos = 0x03af;
+ t.iparen = 0x24a4;
+ t.irigurmukhi = 0x0a72;
+ t.ismallhiragana = 0x3043;
+ t.ismallkatakana = 0x30a3;
+ t.ismallkatakanahalfwidth = 0xff68;
+ t.issharbengali = 0x09fa;
+ t.istroke = 0x0268;
+ t.isuperior = 0xf6ed;
+ t.iterationhiragana = 0x309d;
+ t.iterationkatakana = 0x30fd;
+ t.itilde = 0x0129;
+ t.itildebelow = 0x1e2d;
+ t.iubopomofo = 0x3129;
+ t.iucyrillic = 0x044e;
+ t.ivowelsignbengali = 0x09bf;
+ t.ivowelsigndeva = 0x093f;
+ t.ivowelsigngujarati = 0x0abf;
+ t.izhitsacyrillic = 0x0475;
+ t.izhitsadblgravecyrillic = 0x0477;
+ t.j = 0x006a;
+ t.jaarmenian = 0x0571;
+ t.jabengali = 0x099c;
+ t.jadeva = 0x091c;
+ t.jagujarati = 0x0a9c;
+ t.jagurmukhi = 0x0a1c;
+ t.jbopomofo = 0x3110;
+ t.jcaron = 0x01f0;
+ t.jcircle = 0x24d9;
+ t.jcircumflex = 0x0135;
+ t.jcrossedtail = 0x029d;
+ t.jdotlessstroke = 0x025f;
+ t.jecyrillic = 0x0458;
+ t.jeemarabic = 0x062c;
+ t.jeemfinalarabic = 0xfe9e;
+ t.jeeminitialarabic = 0xfe9f;
+ t.jeemmedialarabic = 0xfea0;
+ t.jeharabic = 0x0698;
+ t.jehfinalarabic = 0xfb8b;
+ t.jhabengali = 0x099d;
+ t.jhadeva = 0x091d;
+ t.jhagujarati = 0x0a9d;
+ t.jhagurmukhi = 0x0a1d;
+ t.jheharmenian = 0x057b;
+ t.jis = 0x3004;
+ t.jmonospace = 0xff4a;
+ t.jparen = 0x24a5;
+ t.jsuperior = 0x02b2;
+ t.k = 0x006b;
+ t.kabashkircyrillic = 0x04a1;
+ t.kabengali = 0x0995;
+ t.kacute = 0x1e31;
+ t.kacyrillic = 0x043a;
+ t.kadescendercyrillic = 0x049b;
+ t.kadeva = 0x0915;
+ t.kaf = 0x05db;
+ t.kafarabic = 0x0643;
+ t.kafdagesh = 0xfb3b;
+ t.kafdageshhebrew = 0xfb3b;
+ t.kaffinalarabic = 0xfeda;
+ t.kafhebrew = 0x05db;
+ t.kafinitialarabic = 0xfedb;
+ t.kafmedialarabic = 0xfedc;
+ t.kafrafehebrew = 0xfb4d;
+ t.kagujarati = 0x0a95;
+ t.kagurmukhi = 0x0a15;
+ t.kahiragana = 0x304b;
+ t.kahookcyrillic = 0x04c4;
+ t.kakatakana = 0x30ab;
+ t.kakatakanahalfwidth = 0xff76;
+ t.kappa = 0x03ba;
+ t.kappasymbolgreek = 0x03f0;
+ t.kapyeounmieumkorean = 0x3171;
+ t.kapyeounphieuphkorean = 0x3184;
+ t.kapyeounpieupkorean = 0x3178;
+ t.kapyeounssangpieupkorean = 0x3179;
+ t.karoriisquare = 0x330d;
+ t.kashidaautoarabic = 0x0640;
+ t.kashidaautonosidebearingarabic = 0x0640;
+ t.kasmallkatakana = 0x30f5;
+ t.kasquare = 0x3384;
+ t.kasraarabic = 0x0650;
+ t.kasratanarabic = 0x064d;
+ t.kastrokecyrillic = 0x049f;
+ t.katahiraprolongmarkhalfwidth = 0xff70;
+ t.kaverticalstrokecyrillic = 0x049d;
+ t.kbopomofo = 0x310e;
+ t.kcalsquare = 0x3389;
+ t.kcaron = 0x01e9;
+ t.kcedilla = 0x0137;
+ t.kcircle = 0x24da;
+ t.kcommaaccent = 0x0137;
+ t.kdotbelow = 0x1e33;
+ t.keharmenian = 0x0584;
+ t.kehiragana = 0x3051;
+ t.kekatakana = 0x30b1;
+ t.kekatakanahalfwidth = 0xff79;
+ t.kenarmenian = 0x056f;
+ t.kesmallkatakana = 0x30f6;
+ t.kgreenlandic = 0x0138;
+ t.khabengali = 0x0996;
+ t.khacyrillic = 0x0445;
+ t.khadeva = 0x0916;
+ t.khagujarati = 0x0a96;
+ t.khagurmukhi = 0x0a16;
+ t.khaharabic = 0x062e;
+ t.khahfinalarabic = 0xfea6;
+ t.khahinitialarabic = 0xfea7;
+ t.khahmedialarabic = 0xfea8;
+ t.kheicoptic = 0x03e7;
+ t.khhadeva = 0x0959;
+ t.khhagurmukhi = 0x0a59;
+ t.khieukhacirclekorean = 0x3278;
+ t.khieukhaparenkorean = 0x3218;
+ t.khieukhcirclekorean = 0x326a;
+ t.khieukhkorean = 0x314b;
+ t.khieukhparenkorean = 0x320a;
+ t.khokhaithai = 0x0e02;
+ t.khokhonthai = 0x0e05;
+ t.khokhuatthai = 0x0e03;
+ t.khokhwaithai = 0x0e04;
+ t.khomutthai = 0x0e5b;
+ t.khook = 0x0199;
+ t.khorakhangthai = 0x0e06;
+ t.khzsquare = 0x3391;
+ t.kihiragana = 0x304d;
+ t.kikatakana = 0x30ad;
+ t.kikatakanahalfwidth = 0xff77;
+ t.kiroguramusquare = 0x3315;
+ t.kiromeetorusquare = 0x3316;
+ t.kirosquare = 0x3314;
+ t.kiyeokacirclekorean = 0x326e;
+ t.kiyeokaparenkorean = 0x320e;
+ t.kiyeokcirclekorean = 0x3260;
+ t.kiyeokkorean = 0x3131;
+ t.kiyeokparenkorean = 0x3200;
+ t.kiyeoksioskorean = 0x3133;
+ t.kjecyrillic = 0x045c;
+ t.klinebelow = 0x1e35;
+ t.klsquare = 0x3398;
+ t.kmcubedsquare = 0x33a6;
+ t.kmonospace = 0xff4b;
+ t.kmsquaredsquare = 0x33a2;
+ t.kohiragana = 0x3053;
+ t.kohmsquare = 0x33c0;
+ t.kokaithai = 0x0e01;
+ t.kokatakana = 0x30b3;
+ t.kokatakanahalfwidth = 0xff7a;
+ t.kooposquare = 0x331e;
+ t.koppacyrillic = 0x0481;
+ t.koreanstandardsymbol = 0x327f;
+ t.koroniscmb = 0x0343;
+ t.kparen = 0x24a6;
+ t.kpasquare = 0x33aa;
+ t.ksicyrillic = 0x046f;
+ t.ktsquare = 0x33cf;
+ t.kturned = 0x029e;
+ t.kuhiragana = 0x304f;
+ t.kukatakana = 0x30af;
+ t.kukatakanahalfwidth = 0xff78;
+ t.kvsquare = 0x33b8;
+ t.kwsquare = 0x33be;
+ t.l = 0x006c;
+ t.labengali = 0x09b2;
+ t.lacute = 0x013a;
+ t.ladeva = 0x0932;
+ t.lagujarati = 0x0ab2;
+ t.lagurmukhi = 0x0a32;
+ t.lakkhangyaothai = 0x0e45;
+ t.lamaleffinalarabic = 0xfefc;
+ t.lamalefhamzaabovefinalarabic = 0xfef8;
+ t.lamalefhamzaaboveisolatedarabic = 0xfef7;
+ t.lamalefhamzabelowfinalarabic = 0xfefa;
+ t.lamalefhamzabelowisolatedarabic = 0xfef9;
+ t.lamalefisolatedarabic = 0xfefb;
+ t.lamalefmaddaabovefinalarabic = 0xfef6;
+ t.lamalefmaddaaboveisolatedarabic = 0xfef5;
+ t.lamarabic = 0x0644;
+ t.lambda = 0x03bb;
+ t.lambdastroke = 0x019b;
+ t.lamed = 0x05dc;
+ t.lameddagesh = 0xfb3c;
+ t.lameddageshhebrew = 0xfb3c;
+ t.lamedhebrew = 0x05dc;
+ t.lamfinalarabic = 0xfede;
+ t.lamhahinitialarabic = 0xfcca;
+ t.laminitialarabic = 0xfedf;
+ t.lamjeeminitialarabic = 0xfcc9;
+ t.lamkhahinitialarabic = 0xfccb;
+ t.lamlamhehisolatedarabic = 0xfdf2;
+ t.lammedialarabic = 0xfee0;
+ t.lammeemhahinitialarabic = 0xfd88;
+ t.lammeeminitialarabic = 0xfccc;
+ t.largecircle = 0x25ef;
+ t.lbar = 0x019a;
+ t.lbelt = 0x026c;
+ t.lbopomofo = 0x310c;
+ t.lcaron = 0x013e;
+ t.lcedilla = 0x013c;
+ t.lcircle = 0x24db;
+ t.lcircumflexbelow = 0x1e3d;
+ t.lcommaaccent = 0x013c;
+ t.ldot = 0x0140;
+ t.ldotaccent = 0x0140;
+ t.ldotbelow = 0x1e37;
+ t.ldotbelowmacron = 0x1e39;
+ t.leftangleabovecmb = 0x031a;
+ t.lefttackbelowcmb = 0x0318;
+ t.less = 0x003c;
+ t.lessequal = 0x2264;
+ t.lessequalorgreater = 0x22da;
+ t.lessmonospace = 0xff1c;
+ t.lessorequivalent = 0x2272;
+ t.lessorgreater = 0x2276;
+ t.lessoverequal = 0x2266;
+ t.lesssmall = 0xfe64;
+ t.lezh = 0x026e;
+ t.lfblock = 0x258c;
+ t.lhookretroflex = 0x026d;
+ t.lira = 0x20a4;
+ t.liwnarmenian = 0x056c;
+ t.lj = 0x01c9;
+ t.ljecyrillic = 0x0459;
+ t.ll = 0xf6c0;
+ t.lladeva = 0x0933;
+ t.llagujarati = 0x0ab3;
+ t.llinebelow = 0x1e3b;
+ t.llladeva = 0x0934;
+ t.llvocalicbengali = 0x09e1;
+ t.llvocalicdeva = 0x0961;
+ t.llvocalicvowelsignbengali = 0x09e3;
+ t.llvocalicvowelsigndeva = 0x0963;
+ t.lmiddletilde = 0x026b;
+ t.lmonospace = 0xff4c;
+ t.lmsquare = 0x33d0;
+ t.lochulathai = 0x0e2c;
+ t.logicaland = 0x2227;
+ t.logicalnot = 0x00ac;
+ t.logicalnotreversed = 0x2310;
+ t.logicalor = 0x2228;
+ t.lolingthai = 0x0e25;
+ t.longs = 0x017f;
+ t.lowlinecenterline = 0xfe4e;
+ t.lowlinecmb = 0x0332;
+ t.lowlinedashed = 0xfe4d;
+ t.lozenge = 0x25ca;
+ t.lparen = 0x24a7;
+ t.lslash = 0x0142;
+ t.lsquare = 0x2113;
+ t.lsuperior = 0xf6ee;
+ t.ltshade = 0x2591;
+ t.luthai = 0x0e26;
+ t.lvocalicbengali = 0x098c;
+ t.lvocalicdeva = 0x090c;
+ t.lvocalicvowelsignbengali = 0x09e2;
+ t.lvocalicvowelsigndeva = 0x0962;
+ t.lxsquare = 0x33d3;
+ t.m = 0x006d;
+ t.mabengali = 0x09ae;
+ t.macron = 0x00af;
+ t.macronbelowcmb = 0x0331;
+ t.macroncmb = 0x0304;
+ t.macronlowmod = 0x02cd;
+ t.macronmonospace = 0xffe3;
+ t.macute = 0x1e3f;
+ t.madeva = 0x092e;
+ t.magujarati = 0x0aae;
+ t.magurmukhi = 0x0a2e;
+ t.mahapakhhebrew = 0x05a4;
+ t.mahapakhlefthebrew = 0x05a4;
+ t.mahiragana = 0x307e;
+ t.maichattawalowleftthai = 0xf895;
+ t.maichattawalowrightthai = 0xf894;
+ t.maichattawathai = 0x0e4b;
+ t.maichattawaupperleftthai = 0xf893;
+ t.maieklowleftthai = 0xf88c;
+ t.maieklowrightthai = 0xf88b;
+ t.maiekthai = 0x0e48;
+ t.maiekupperleftthai = 0xf88a;
+ t.maihanakatleftthai = 0xf884;
+ t.maihanakatthai = 0x0e31;
+ t.maitaikhuleftthai = 0xf889;
+ t.maitaikhuthai = 0x0e47;
+ t.maitholowleftthai = 0xf88f;
+ t.maitholowrightthai = 0xf88e;
+ t.maithothai = 0x0e49;
+ t.maithoupperleftthai = 0xf88d;
+ t.maitrilowleftthai = 0xf892;
+ t.maitrilowrightthai = 0xf891;
+ t.maitrithai = 0x0e4a;
+ t.maitriupperleftthai = 0xf890;
+ t.maiyamokthai = 0x0e46;
+ t.makatakana = 0x30de;
+ t.makatakanahalfwidth = 0xff8f;
+ t.male = 0x2642;
+ t.mansyonsquare = 0x3347;
+ t.maqafhebrew = 0x05be;
+ t.mars = 0x2642;
+ t.masoracirclehebrew = 0x05af;
+ t.masquare = 0x3383;
+ t.mbopomofo = 0x3107;
+ t.mbsquare = 0x33d4;
+ t.mcircle = 0x24dc;
+ t.mcubedsquare = 0x33a5;
+ t.mdotaccent = 0x1e41;
+ t.mdotbelow = 0x1e43;
+ t.meemarabic = 0x0645;
+ t.meemfinalarabic = 0xfee2;
+ t.meeminitialarabic = 0xfee3;
+ t.meemmedialarabic = 0xfee4;
+ t.meemmeeminitialarabic = 0xfcd1;
+ t.meemmeemisolatedarabic = 0xfc48;
+ t.meetorusquare = 0x334d;
+ t.mehiragana = 0x3081;
+ t.meizierasquare = 0x337e;
+ t.mekatakana = 0x30e1;
+ t.mekatakanahalfwidth = 0xff92;
+ t.mem = 0x05de;
+ t.memdagesh = 0xfb3e;
+ t.memdageshhebrew = 0xfb3e;
+ t.memhebrew = 0x05de;
+ t.menarmenian = 0x0574;
+ t.merkhahebrew = 0x05a5;
+ t.merkhakefulahebrew = 0x05a6;
+ t.merkhakefulalefthebrew = 0x05a6;
+ t.merkhalefthebrew = 0x05a5;
+ t.mhook = 0x0271;
+ t.mhzsquare = 0x3392;
+ t.middledotkatakanahalfwidth = 0xff65;
+ t.middot = 0x00b7;
+ t.mieumacirclekorean = 0x3272;
+ t.mieumaparenkorean = 0x3212;
+ t.mieumcirclekorean = 0x3264;
+ t.mieumkorean = 0x3141;
+ t.mieumpansioskorean = 0x3170;
+ t.mieumparenkorean = 0x3204;
+ t.mieumpieupkorean = 0x316e;
+ t.mieumsioskorean = 0x316f;
+ t.mihiragana = 0x307f;
+ t.mikatakana = 0x30df;
+ t.mikatakanahalfwidth = 0xff90;
+ t.minus = 0x2212;
+ t.minusbelowcmb = 0x0320;
+ t.minuscircle = 0x2296;
+ t.minusmod = 0x02d7;
+ t.minusplus = 0x2213;
+ t.minute = 0x2032;
+ t.miribaarusquare = 0x334a;
+ t.mirisquare = 0x3349;
+ t.mlonglegturned = 0x0270;
+ t.mlsquare = 0x3396;
+ t.mmcubedsquare = 0x33a3;
+ t.mmonospace = 0xff4d;
+ t.mmsquaredsquare = 0x339f;
+ t.mohiragana = 0x3082;
+ t.mohmsquare = 0x33c1;
+ t.mokatakana = 0x30e2;
+ t.mokatakanahalfwidth = 0xff93;
+ t.molsquare = 0x33d6;
+ t.momathai = 0x0e21;
+ t.moverssquare = 0x33a7;
+ t.moverssquaredsquare = 0x33a8;
+ t.mparen = 0x24a8;
+ t.mpasquare = 0x33ab;
+ t.mssquare = 0x33b3;
+ t.msuperior = 0xf6ef;
+ t.mturned = 0x026f;
+ t.mu = 0x00b5;
+ t.mu1 = 0x00b5;
+ t.muasquare = 0x3382;
+ t.muchgreater = 0x226b;
+ t.muchless = 0x226a;
+ t.mufsquare = 0x338c;
+ t.mugreek = 0x03bc;
+ t.mugsquare = 0x338d;
+ t.muhiragana = 0x3080;
+ t.mukatakana = 0x30e0;
+ t.mukatakanahalfwidth = 0xff91;
+ t.mulsquare = 0x3395;
+ t.multiply = 0x00d7;
+ t.mumsquare = 0x339b;
+ t.munahhebrew = 0x05a3;
+ t.munahlefthebrew = 0x05a3;
+ t.musicalnote = 0x266a;
+ t.musicalnotedbl = 0x266b;
+ t.musicflatsign = 0x266d;
+ t.musicsharpsign = 0x266f;
+ t.mussquare = 0x33b2;
+ t.muvsquare = 0x33b6;
+ t.muwsquare = 0x33bc;
+ t.mvmegasquare = 0x33b9;
+ t.mvsquare = 0x33b7;
+ t.mwmegasquare = 0x33bf;
+ t.mwsquare = 0x33bd;
+ t.n = 0x006e;
+ t.nabengali = 0x09a8;
+ t.nabla = 0x2207;
+ t.nacute = 0x0144;
+ t.nadeva = 0x0928;
+ t.nagujarati = 0x0aa8;
+ t.nagurmukhi = 0x0a28;
+ t.nahiragana = 0x306a;
+ t.nakatakana = 0x30ca;
+ t.nakatakanahalfwidth = 0xff85;
+ t.napostrophe = 0x0149;
+ t.nasquare = 0x3381;
+ t.nbopomofo = 0x310b;
+ t.nbspace = 0x00a0;
+ t.ncaron = 0x0148;
+ t.ncedilla = 0x0146;
+ t.ncircle = 0x24dd;
+ t.ncircumflexbelow = 0x1e4b;
+ t.ncommaaccent = 0x0146;
+ t.ndotaccent = 0x1e45;
+ t.ndotbelow = 0x1e47;
+ t.nehiragana = 0x306d;
+ t.nekatakana = 0x30cd;
+ t.nekatakanahalfwidth = 0xff88;
+ t.newsheqelsign = 0x20aa;
+ t.nfsquare = 0x338b;
+ t.ngabengali = 0x0999;
+ t.ngadeva = 0x0919;
+ t.ngagujarati = 0x0a99;
+ t.ngagurmukhi = 0x0a19;
+ t.ngonguthai = 0x0e07;
+ t.nhiragana = 0x3093;
+ t.nhookleft = 0x0272;
+ t.nhookretroflex = 0x0273;
+ t.nieunacirclekorean = 0x326f;
+ t.nieunaparenkorean = 0x320f;
+ t.nieuncieuckorean = 0x3135;
+ t.nieuncirclekorean = 0x3261;
+ t.nieunhieuhkorean = 0x3136;
+ t.nieunkorean = 0x3134;
+ t.nieunpansioskorean = 0x3168;
+ t.nieunparenkorean = 0x3201;
+ t.nieunsioskorean = 0x3167;
+ t.nieuntikeutkorean = 0x3166;
+ t.nihiragana = 0x306b;
+ t.nikatakana = 0x30cb;
+ t.nikatakanahalfwidth = 0xff86;
+ t.nikhahitleftthai = 0xf899;
+ t.nikhahitthai = 0x0e4d;
+ t.nine = 0x0039;
+ t.ninearabic = 0x0669;
+ t.ninebengali = 0x09ef;
+ t.ninecircle = 0x2468;
+ t.ninecircleinversesansserif = 0x2792;
+ t.ninedeva = 0x096f;
+ t.ninegujarati = 0x0aef;
+ t.ninegurmukhi = 0x0a6f;
+ t.ninehackarabic = 0x0669;
+ t.ninehangzhou = 0x3029;
+ t.nineideographicparen = 0x3228;
+ t.nineinferior = 0x2089;
+ t.ninemonospace = 0xff19;
+ t.nineoldstyle = 0xf739;
+ t.nineparen = 0x247c;
+ t.nineperiod = 0x2490;
+ t.ninepersian = 0x06f9;
+ t.nineroman = 0x2178;
+ t.ninesuperior = 0x2079;
+ t.nineteencircle = 0x2472;
+ t.nineteenparen = 0x2486;
+ t.nineteenperiod = 0x249a;
+ t.ninethai = 0x0e59;
+ t.nj = 0x01cc;
+ t.njecyrillic = 0x045a;
+ t.nkatakana = 0x30f3;
+ t.nkatakanahalfwidth = 0xff9d;
+ t.nlegrightlong = 0x019e;
+ t.nlinebelow = 0x1e49;
+ t.nmonospace = 0xff4e;
+ t.nmsquare = 0x339a;
+ t.nnabengali = 0x09a3;
+ t.nnadeva = 0x0923;
+ t.nnagujarati = 0x0aa3;
+ t.nnagurmukhi = 0x0a23;
+ t.nnnadeva = 0x0929;
+ t.nohiragana = 0x306e;
+ t.nokatakana = 0x30ce;
+ t.nokatakanahalfwidth = 0xff89;
+ t.nonbreakingspace = 0x00a0;
+ t.nonenthai = 0x0e13;
+ t.nonuthai = 0x0e19;
+ t.noonarabic = 0x0646;
+ t.noonfinalarabic = 0xfee6;
+ t.noonghunnaarabic = 0x06ba;
+ t.noonghunnafinalarabic = 0xfb9f;
+ t.nooninitialarabic = 0xfee7;
+ t.noonjeeminitialarabic = 0xfcd2;
+ t.noonjeemisolatedarabic = 0xfc4b;
+ t.noonmedialarabic = 0xfee8;
+ t.noonmeeminitialarabic = 0xfcd5;
+ t.noonmeemisolatedarabic = 0xfc4e;
+ t.noonnoonfinalarabic = 0xfc8d;
+ t.notcontains = 0x220c;
+ t.notelement = 0x2209;
+ t.notelementof = 0x2209;
+ t.notequal = 0x2260;
+ t.notgreater = 0x226f;
+ t.notgreaternorequal = 0x2271;
+ t.notgreaternorless = 0x2279;
+ t.notidentical = 0x2262;
+ t.notless = 0x226e;
+ t.notlessnorequal = 0x2270;
+ t.notparallel = 0x2226;
+ t.notprecedes = 0x2280;
+ t.notsubset = 0x2284;
+ t.notsucceeds = 0x2281;
+ t.notsuperset = 0x2285;
+ t.nowarmenian = 0x0576;
+ t.nparen = 0x24a9;
+ t.nssquare = 0x33b1;
+ t.nsuperior = 0x207f;
+ t.ntilde = 0x00f1;
+ t.nu = 0x03bd;
+ t.nuhiragana = 0x306c;
+ t.nukatakana = 0x30cc;
+ t.nukatakanahalfwidth = 0xff87;
+ t.nuktabengali = 0x09bc;
+ t.nuktadeva = 0x093c;
+ t.nuktagujarati = 0x0abc;
+ t.nuktagurmukhi = 0x0a3c;
+ t.numbersign = 0x0023;
+ t.numbersignmonospace = 0xff03;
+ t.numbersignsmall = 0xfe5f;
+ t.numeralsigngreek = 0x0374;
+ t.numeralsignlowergreek = 0x0375;
+ t.numero = 0x2116;
+ t.nun = 0x05e0;
+ t.nundagesh = 0xfb40;
+ t.nundageshhebrew = 0xfb40;
+ t.nunhebrew = 0x05e0;
+ t.nvsquare = 0x33b5;
+ t.nwsquare = 0x33bb;
+ t.nyabengali = 0x099e;
+ t.nyadeva = 0x091e;
+ t.nyagujarati = 0x0a9e;
+ t.nyagurmukhi = 0x0a1e;
+ t.o = 0x006f;
+ t.oacute = 0x00f3;
+ t.oangthai = 0x0e2d;
+ t.obarred = 0x0275;
+ t.obarredcyrillic = 0x04e9;
+ t.obarreddieresiscyrillic = 0x04eb;
+ t.obengali = 0x0993;
+ t.obopomofo = 0x311b;
+ t.obreve = 0x014f;
+ t.ocandradeva = 0x0911;
+ t.ocandragujarati = 0x0a91;
+ t.ocandravowelsigndeva = 0x0949;
+ t.ocandravowelsigngujarati = 0x0ac9;
+ t.ocaron = 0x01d2;
+ t.ocircle = 0x24de;
+ t.ocircumflex = 0x00f4;
+ t.ocircumflexacute = 0x1ed1;
+ t.ocircumflexdotbelow = 0x1ed9;
+ t.ocircumflexgrave = 0x1ed3;
+ t.ocircumflexhookabove = 0x1ed5;
+ t.ocircumflextilde = 0x1ed7;
+ t.ocyrillic = 0x043e;
+ t.odblacute = 0x0151;
+ t.odblgrave = 0x020d;
+ t.odeva = 0x0913;
+ t.odieresis = 0x00f6;
+ t.odieresiscyrillic = 0x04e7;
+ t.odotbelow = 0x1ecd;
+ t.oe = 0x0153;
+ t.oekorean = 0x315a;
+ t.ogonek = 0x02db;
+ t.ogonekcmb = 0x0328;
+ t.ograve = 0x00f2;
+ t.ogujarati = 0x0a93;
+ t.oharmenian = 0x0585;
+ t.ohiragana = 0x304a;
+ t.ohookabove = 0x1ecf;
+ t.ohorn = 0x01a1;
+ t.ohornacute = 0x1edb;
+ t.ohorndotbelow = 0x1ee3;
+ t.ohorngrave = 0x1edd;
+ t.ohornhookabove = 0x1edf;
+ t.ohorntilde = 0x1ee1;
+ t.ohungarumlaut = 0x0151;
+ t.oi = 0x01a3;
+ t.oinvertedbreve = 0x020f;
+ t.okatakana = 0x30aa;
+ t.okatakanahalfwidth = 0xff75;
+ t.okorean = 0x3157;
+ t.olehebrew = 0x05ab;
+ t.omacron = 0x014d;
+ t.omacronacute = 0x1e53;
+ t.omacrongrave = 0x1e51;
+ t.omdeva = 0x0950;
+ t.omega = 0x03c9;
+ t.omega1 = 0x03d6;
+ t.omegacyrillic = 0x0461;
+ t.omegalatinclosed = 0x0277;
+ t.omegaroundcyrillic = 0x047b;
+ t.omegatitlocyrillic = 0x047d;
+ t.omegatonos = 0x03ce;
+ t.omgujarati = 0x0ad0;
+ t.omicron = 0x03bf;
+ t.omicrontonos = 0x03cc;
+ t.omonospace = 0xff4f;
+ t.one = 0x0031;
+ t.onearabic = 0x0661;
+ t.onebengali = 0x09e7;
+ t.onecircle = 0x2460;
+ t.onecircleinversesansserif = 0x278a;
+ t.onedeva = 0x0967;
+ t.onedotenleader = 0x2024;
+ t.oneeighth = 0x215b;
+ t.onefitted = 0xf6dc;
+ t.onegujarati = 0x0ae7;
+ t.onegurmukhi = 0x0a67;
+ t.onehackarabic = 0x0661;
+ t.onehalf = 0x00bd;
+ t.onehangzhou = 0x3021;
+ t.oneideographicparen = 0x3220;
+ t.oneinferior = 0x2081;
+ t.onemonospace = 0xff11;
+ t.onenumeratorbengali = 0x09f4;
+ t.oneoldstyle = 0xf731;
+ t.oneparen = 0x2474;
+ t.oneperiod = 0x2488;
+ t.onepersian = 0x06f1;
+ t.onequarter = 0x00bc;
+ t.oneroman = 0x2170;
+ t.onesuperior = 0x00b9;
+ t.onethai = 0x0e51;
+ t.onethird = 0x2153;
+ t.oogonek = 0x01eb;
+ t.oogonekmacron = 0x01ed;
+ t.oogurmukhi = 0x0a13;
+ t.oomatragurmukhi = 0x0a4b;
+ t.oopen = 0x0254;
+ t.oparen = 0x24aa;
+ t.openbullet = 0x25e6;
+ t.option = 0x2325;
+ t.ordfeminine = 0x00aa;
+ t.ordmasculine = 0x00ba;
+ t.orthogonal = 0x221f;
+ t.oshortdeva = 0x0912;
+ t.oshortvowelsigndeva = 0x094a;
+ t.oslash = 0x00f8;
+ t.oslashacute = 0x01ff;
+ t.osmallhiragana = 0x3049;
+ t.osmallkatakana = 0x30a9;
+ t.osmallkatakanahalfwidth = 0xff6b;
+ t.ostrokeacute = 0x01ff;
+ t.osuperior = 0xf6f0;
+ t.otcyrillic = 0x047f;
+ t.otilde = 0x00f5;
+ t.otildeacute = 0x1e4d;
+ t.otildedieresis = 0x1e4f;
+ t.oubopomofo = 0x3121;
+ t.overline = 0x203e;
+ t.overlinecenterline = 0xfe4a;
+ t.overlinecmb = 0x0305;
+ t.overlinedashed = 0xfe49;
+ t.overlinedblwavy = 0xfe4c;
+ t.overlinewavy = 0xfe4b;
+ t.overscore = 0x00af;
+ t.ovowelsignbengali = 0x09cb;
+ t.ovowelsigndeva = 0x094b;
+ t.ovowelsigngujarati = 0x0acb;
+ t.p = 0x0070;
+ t.paampssquare = 0x3380;
+ t.paasentosquare = 0x332b;
+ t.pabengali = 0x09aa;
+ t.pacute = 0x1e55;
+ t.padeva = 0x092a;
+ t.pagedown = 0x21df;
+ t.pageup = 0x21de;
+ t.pagujarati = 0x0aaa;
+ t.pagurmukhi = 0x0a2a;
+ t.pahiragana = 0x3071;
+ t.paiyannoithai = 0x0e2f;
+ t.pakatakana = 0x30d1;
+ t.palatalizationcyrilliccmb = 0x0484;
+ t.palochkacyrillic = 0x04c0;
+ t.pansioskorean = 0x317f;
+ t.paragraph = 0x00b6;
+ t.parallel = 0x2225;
+ t.parenleft = 0x0028;
+ t.parenleftaltonearabic = 0xfd3e;
+ t.parenleftbt = 0xf8ed;
+ t.parenleftex = 0xf8ec;
+ t.parenleftinferior = 0x208d;
+ t.parenleftmonospace = 0xff08;
+ t.parenleftsmall = 0xfe59;
+ t.parenleftsuperior = 0x207d;
+ t.parenlefttp = 0xf8eb;
+ t.parenleftvertical = 0xfe35;
+ t.parenright = 0x0029;
+ t.parenrightaltonearabic = 0xfd3f;
+ t.parenrightbt = 0xf8f8;
+ t.parenrightex = 0xf8f7;
+ t.parenrightinferior = 0x208e;
+ t.parenrightmonospace = 0xff09;
+ t.parenrightsmall = 0xfe5a;
+ t.parenrightsuperior = 0x207e;
+ t.parenrighttp = 0xf8f6;
+ t.parenrightvertical = 0xfe36;
+ t.partialdiff = 0x2202;
+ t.paseqhebrew = 0x05c0;
+ t.pashtahebrew = 0x0599;
+ t.pasquare = 0x33a9;
+ t.patah = 0x05b7;
+ t.patah11 = 0x05b7;
+ t.patah1d = 0x05b7;
+ t.patah2a = 0x05b7;
+ t.patahhebrew = 0x05b7;
+ t.patahnarrowhebrew = 0x05b7;
+ t.patahquarterhebrew = 0x05b7;
+ t.patahwidehebrew = 0x05b7;
+ t.pazerhebrew = 0x05a1;
+ t.pbopomofo = 0x3106;
+ t.pcircle = 0x24df;
+ t.pdotaccent = 0x1e57;
+ t.pe = 0x05e4;
+ t.pecyrillic = 0x043f;
+ t.pedagesh = 0xfb44;
+ t.pedageshhebrew = 0xfb44;
+ t.peezisquare = 0x333b;
+ t.pefinaldageshhebrew = 0xfb43;
+ t.peharabic = 0x067e;
+ t.peharmenian = 0x057a;
+ t.pehebrew = 0x05e4;
+ t.pehfinalarabic = 0xfb57;
+ t.pehinitialarabic = 0xfb58;
+ t.pehiragana = 0x307a;
+ t.pehmedialarabic = 0xfb59;
+ t.pekatakana = 0x30da;
+ t.pemiddlehookcyrillic = 0x04a7;
+ t.perafehebrew = 0xfb4e;
+ t.percent = 0x0025;
+ t.percentarabic = 0x066a;
+ t.percentmonospace = 0xff05;
+ t.percentsmall = 0xfe6a;
+ t.period = 0x002e;
+ t.periodarmenian = 0x0589;
+ t.periodcentered = 0x00b7;
+ t.periodhalfwidth = 0xff61;
+ t.periodinferior = 0xf6e7;
+ t.periodmonospace = 0xff0e;
+ t.periodsmall = 0xfe52;
+ t.periodsuperior = 0xf6e8;
+ t.perispomenigreekcmb = 0x0342;
+ t.perpendicular = 0x22a5;
+ t.perthousand = 0x2030;
+ t.peseta = 0x20a7;
+ t.pfsquare = 0x338a;
+ t.phabengali = 0x09ab;
+ t.phadeva = 0x092b;
+ t.phagujarati = 0x0aab;
+ t.phagurmukhi = 0x0a2b;
+ t.phi = 0x03c6;
+ t.phi1 = 0x03d5;
+ t.phieuphacirclekorean = 0x327a;
+ t.phieuphaparenkorean = 0x321a;
+ t.phieuphcirclekorean = 0x326c;
+ t.phieuphkorean = 0x314d;
+ t.phieuphparenkorean = 0x320c;
+ t.philatin = 0x0278;
+ t.phinthuthai = 0x0e3a;
+ t.phisymbolgreek = 0x03d5;
+ t.phook = 0x01a5;
+ t.phophanthai = 0x0e1e;
+ t.phophungthai = 0x0e1c;
+ t.phosamphaothai = 0x0e20;
+ t.pi = 0x03c0;
+ t.pieupacirclekorean = 0x3273;
+ t.pieupaparenkorean = 0x3213;
+ t.pieupcieuckorean = 0x3176;
+ t.pieupcirclekorean = 0x3265;
+ t.pieupkiyeokkorean = 0x3172;
+ t.pieupkorean = 0x3142;
+ t.pieupparenkorean = 0x3205;
+ t.pieupsioskiyeokkorean = 0x3174;
+ t.pieupsioskorean = 0x3144;
+ t.pieupsiostikeutkorean = 0x3175;
+ t.pieupthieuthkorean = 0x3177;
+ t.pieuptikeutkorean = 0x3173;
+ t.pihiragana = 0x3074;
+ t.pikatakana = 0x30d4;
+ t.pisymbolgreek = 0x03d6;
+ t.piwrarmenian = 0x0583;
+ t.planckover2pi = 0x210f;
+ t.planckover2pi1 = 0x210f;
+ t.plus = 0x002b;
+ t.plusbelowcmb = 0x031f;
+ t.pluscircle = 0x2295;
+ t.plusminus = 0x00b1;
+ t.plusmod = 0x02d6;
+ t.plusmonospace = 0xff0b;
+ t.plussmall = 0xfe62;
+ t.plussuperior = 0x207a;
+ t.pmonospace = 0xff50;
+ t.pmsquare = 0x33d8;
+ t.pohiragana = 0x307d;
+ t.pointingindexdownwhite = 0x261f;
+ t.pointingindexleftwhite = 0x261c;
+ t.pointingindexrightwhite = 0x261e;
+ t.pointingindexupwhite = 0x261d;
+ t.pokatakana = 0x30dd;
+ t.poplathai = 0x0e1b;
+ t.postalmark = 0x3012;
+ t.postalmarkface = 0x3020;
+ t.pparen = 0x24ab;
+ t.precedes = 0x227a;
+ t.prescription = 0x211e;
+ t.primemod = 0x02b9;
+ t.primereversed = 0x2035;
+ t.product = 0x220f;
+ t.projective = 0x2305;
+ t.prolongedkana = 0x30fc;
+ t.propellor = 0x2318;
+ t.propersubset = 0x2282;
+ t.propersuperset = 0x2283;
+ t.proportion = 0x2237;
+ t.proportional = 0x221d;
+ t.psi = 0x03c8;
+ t.psicyrillic = 0x0471;
+ t.psilipneumatacyrilliccmb = 0x0486;
+ t.pssquare = 0x33b0;
+ t.puhiragana = 0x3077;
+ t.pukatakana = 0x30d7;
+ t.pvsquare = 0x33b4;
+ t.pwsquare = 0x33ba;
+ t.q = 0x0071;
+ t.qadeva = 0x0958;
+ t.qadmahebrew = 0x05a8;
+ t.qafarabic = 0x0642;
+ t.qaffinalarabic = 0xfed6;
+ t.qafinitialarabic = 0xfed7;
+ t.qafmedialarabic = 0xfed8;
+ t.qamats = 0x05b8;
+ t.qamats10 = 0x05b8;
+ t.qamats1a = 0x05b8;
+ t.qamats1c = 0x05b8;
+ t.qamats27 = 0x05b8;
+ t.qamats29 = 0x05b8;
+ t.qamats33 = 0x05b8;
+ t.qamatsde = 0x05b8;
+ t.qamatshebrew = 0x05b8;
+ t.qamatsnarrowhebrew = 0x05b8;
+ t.qamatsqatanhebrew = 0x05b8;
+ t.qamatsqatannarrowhebrew = 0x05b8;
+ t.qamatsqatanquarterhebrew = 0x05b8;
+ t.qamatsqatanwidehebrew = 0x05b8;
+ t.qamatsquarterhebrew = 0x05b8;
+ t.qamatswidehebrew = 0x05b8;
+ t.qarneyparahebrew = 0x059f;
+ t.qbopomofo = 0x3111;
+ t.qcircle = 0x24e0;
+ t.qhook = 0x02a0;
+ t.qmonospace = 0xff51;
+ t.qof = 0x05e7;
+ t.qofdagesh = 0xfb47;
+ t.qofdageshhebrew = 0xfb47;
+ t.qofhebrew = 0x05e7;
+ t.qparen = 0x24ac;
+ t.quarternote = 0x2669;
+ t.qubuts = 0x05bb;
+ t.qubuts18 = 0x05bb;
+ t.qubuts25 = 0x05bb;
+ t.qubuts31 = 0x05bb;
+ t.qubutshebrew = 0x05bb;
+ t.qubutsnarrowhebrew = 0x05bb;
+ t.qubutsquarterhebrew = 0x05bb;
+ t.qubutswidehebrew = 0x05bb;
+ t.question = 0x003f;
+ t.questionarabic = 0x061f;
+ t.questionarmenian = 0x055e;
+ t.questiondown = 0x00bf;
+ t.questiondownsmall = 0xf7bf;
+ t.questiongreek = 0x037e;
+ t.questionmonospace = 0xff1f;
+ t.questionsmall = 0xf73f;
+ t.quotedbl = 0x0022;
+ t.quotedblbase = 0x201e;
+ t.quotedblleft = 0x201c;
+ t.quotedblmonospace = 0xff02;
+ t.quotedblprime = 0x301e;
+ t.quotedblprimereversed = 0x301d;
+ t.quotedblright = 0x201d;
+ t.quoteleft = 0x2018;
+ t.quoteleftreversed = 0x201b;
+ t.quotereversed = 0x201b;
+ t.quoteright = 0x2019;
+ t.quoterightn = 0x0149;
+ t.quotesinglbase = 0x201a;
+ t.quotesingle = 0x0027;
+ t.quotesinglemonospace = 0xff07;
+ t.r = 0x0072;
+ t.raarmenian = 0x057c;
+ t.rabengali = 0x09b0;
+ t.racute = 0x0155;
+ t.radeva = 0x0930;
+ t.radical = 0x221a;
+ t.radicalex = 0xf8e5;
+ t.radoverssquare = 0x33ae;
+ t.radoverssquaredsquare = 0x33af;
+ t.radsquare = 0x33ad;
+ t.rafe = 0x05bf;
+ t.rafehebrew = 0x05bf;
+ t.ragujarati = 0x0ab0;
+ t.ragurmukhi = 0x0a30;
+ t.rahiragana = 0x3089;
+ t.rakatakana = 0x30e9;
+ t.rakatakanahalfwidth = 0xff97;
+ t.ralowerdiagonalbengali = 0x09f1;
+ t.ramiddlediagonalbengali = 0x09f0;
+ t.ramshorn = 0x0264;
+ t.ratio = 0x2236;
+ t.rbopomofo = 0x3116;
+ t.rcaron = 0x0159;
+ t.rcedilla = 0x0157;
+ t.rcircle = 0x24e1;
+ t.rcommaaccent = 0x0157;
+ t.rdblgrave = 0x0211;
+ t.rdotaccent = 0x1e59;
+ t.rdotbelow = 0x1e5b;
+ t.rdotbelowmacron = 0x1e5d;
+ t.referencemark = 0x203b;
+ t.reflexsubset = 0x2286;
+ t.reflexsuperset = 0x2287;
+ t.registered = 0x00ae;
+ t.registersans = 0xf8e8;
+ t.registerserif = 0xf6da;
+ t.reharabic = 0x0631;
+ t.reharmenian = 0x0580;
+ t.rehfinalarabic = 0xfeae;
+ t.rehiragana = 0x308c;
+ t.rekatakana = 0x30ec;
+ t.rekatakanahalfwidth = 0xff9a;
+ t.resh = 0x05e8;
+ t.reshdageshhebrew = 0xfb48;
+ t.reshhebrew = 0x05e8;
+ t.reversedtilde = 0x223d;
+ t.reviahebrew = 0x0597;
+ t.reviamugrashhebrew = 0x0597;
+ t.revlogicalnot = 0x2310;
+ t.rfishhook = 0x027e;
+ t.rfishhookreversed = 0x027f;
+ t.rhabengali = 0x09dd;
+ t.rhadeva = 0x095d;
+ t.rho = 0x03c1;
+ t.rhook = 0x027d;
+ t.rhookturned = 0x027b;
+ t.rhookturnedsuperior = 0x02b5;
+ t.rhosymbolgreek = 0x03f1;
+ t.rhotichookmod = 0x02de;
+ t.rieulacirclekorean = 0x3271;
+ t.rieulaparenkorean = 0x3211;
+ t.rieulcirclekorean = 0x3263;
+ t.rieulhieuhkorean = 0x3140;
+ t.rieulkiyeokkorean = 0x313a;
+ t.rieulkiyeoksioskorean = 0x3169;
+ t.rieulkorean = 0x3139;
+ t.rieulmieumkorean = 0x313b;
+ t.rieulpansioskorean = 0x316c;
+ t.rieulparenkorean = 0x3203;
+ t.rieulphieuphkorean = 0x313f;
+ t.rieulpieupkorean = 0x313c;
+ t.rieulpieupsioskorean = 0x316b;
+ t.rieulsioskorean = 0x313d;
+ t.rieulthieuthkorean = 0x313e;
+ t.rieultikeutkorean = 0x316a;
+ t.rieulyeorinhieuhkorean = 0x316d;
+ t.rightangle = 0x221f;
+ t.righttackbelowcmb = 0x0319;
+ t.righttriangle = 0x22bf;
+ t.rihiragana = 0x308a;
+ t.rikatakana = 0x30ea;
+ t.rikatakanahalfwidth = 0xff98;
+ t.ring = 0x02da;
+ t.ringbelowcmb = 0x0325;
+ t.ringcmb = 0x030a;
+ t.ringhalfleft = 0x02bf;
+ t.ringhalfleftarmenian = 0x0559;
+ t.ringhalfleftbelowcmb = 0x031c;
+ t.ringhalfleftcentered = 0x02d3;
+ t.ringhalfright = 0x02be;
+ t.ringhalfrightbelowcmb = 0x0339;
+ t.ringhalfrightcentered = 0x02d2;
+ t.rinvertedbreve = 0x0213;
+ t.rittorusquare = 0x3351;
+ t.rlinebelow = 0x1e5f;
+ t.rlongleg = 0x027c;
+ t.rlonglegturned = 0x027a;
+ t.rmonospace = 0xff52;
+ t.rohiragana = 0x308d;
+ t.rokatakana = 0x30ed;
+ t.rokatakanahalfwidth = 0xff9b;
+ t.roruathai = 0x0e23;
+ t.rparen = 0x24ad;
+ t.rrabengali = 0x09dc;
+ t.rradeva = 0x0931;
+ t.rragurmukhi = 0x0a5c;
+ t.rreharabic = 0x0691;
+ t.rrehfinalarabic = 0xfb8d;
+ t.rrvocalicbengali = 0x09e0;
+ t.rrvocalicdeva = 0x0960;
+ t.rrvocalicgujarati = 0x0ae0;
+ t.rrvocalicvowelsignbengali = 0x09c4;
+ t.rrvocalicvowelsigndeva = 0x0944;
+ t.rrvocalicvowelsigngujarati = 0x0ac4;
+ t.rsuperior = 0xf6f1;
+ t.rtblock = 0x2590;
+ t.rturned = 0x0279;
+ t.rturnedsuperior = 0x02b4;
+ t.ruhiragana = 0x308b;
+ t.rukatakana = 0x30eb;
+ t.rukatakanahalfwidth = 0xff99;
+ t.rupeemarkbengali = 0x09f2;
+ t.rupeesignbengali = 0x09f3;
+ t.rupiah = 0xf6dd;
+ t.ruthai = 0x0e24;
+ t.rvocalicbengali = 0x098b;
+ t.rvocalicdeva = 0x090b;
+ t.rvocalicgujarati = 0x0a8b;
+ t.rvocalicvowelsignbengali = 0x09c3;
+ t.rvocalicvowelsigndeva = 0x0943;
+ t.rvocalicvowelsigngujarati = 0x0ac3;
+ t.s = 0x0073;
+ t.sabengali = 0x09b8;
+ t.sacute = 0x015b;
+ t.sacutedotaccent = 0x1e65;
+ t.sadarabic = 0x0635;
+ t.sadeva = 0x0938;
+ t.sadfinalarabic = 0xfeba;
+ t.sadinitialarabic = 0xfebb;
+ t.sadmedialarabic = 0xfebc;
+ t.sagujarati = 0x0ab8;
+ t.sagurmukhi = 0x0a38;
+ t.sahiragana = 0x3055;
+ t.sakatakana = 0x30b5;
+ t.sakatakanahalfwidth = 0xff7b;
+ t.sallallahoualayhewasallamarabic = 0xfdfa;
+ t.samekh = 0x05e1;
+ t.samekhdagesh = 0xfb41;
+ t.samekhdageshhebrew = 0xfb41;
+ t.samekhhebrew = 0x05e1;
+ t.saraaathai = 0x0e32;
+ t.saraaethai = 0x0e41;
+ t.saraaimaimalaithai = 0x0e44;
+ t.saraaimaimuanthai = 0x0e43;
+ t.saraamthai = 0x0e33;
+ t.saraathai = 0x0e30;
+ t.saraethai = 0x0e40;
+ t.saraiileftthai = 0xf886;
+ t.saraiithai = 0x0e35;
+ t.saraileftthai = 0xf885;
+ t.saraithai = 0x0e34;
+ t.saraothai = 0x0e42;
+ t.saraueeleftthai = 0xf888;
+ t.saraueethai = 0x0e37;
+ t.saraueleftthai = 0xf887;
+ t.sarauethai = 0x0e36;
+ t.sarauthai = 0x0e38;
+ t.sarauuthai = 0x0e39;
+ t.sbopomofo = 0x3119;
+ t.scaron = 0x0161;
+ t.scarondotaccent = 0x1e67;
+ t.scedilla = 0x015f;
+ t.schwa = 0x0259;
+ t.schwacyrillic = 0x04d9;
+ t.schwadieresiscyrillic = 0x04db;
+ t.schwahook = 0x025a;
+ t.scircle = 0x24e2;
+ t.scircumflex = 0x015d;
+ t.scommaaccent = 0x0219;
+ t.sdotaccent = 0x1e61;
+ t.sdotbelow = 0x1e63;
+ t.sdotbelowdotaccent = 0x1e69;
+ t.seagullbelowcmb = 0x033c;
+ t.second = 0x2033;
+ t.secondtonechinese = 0x02ca;
+ t.section = 0x00a7;
+ t.seenarabic = 0x0633;
+ t.seenfinalarabic = 0xfeb2;
+ t.seeninitialarabic = 0xfeb3;
+ t.seenmedialarabic = 0xfeb4;
+ t.segol = 0x05b6;
+ t.segol13 = 0x05b6;
+ t.segol1f = 0x05b6;
+ t.segol2c = 0x05b6;
+ t.segolhebrew = 0x05b6;
+ t.segolnarrowhebrew = 0x05b6;
+ t.segolquarterhebrew = 0x05b6;
+ t.segoltahebrew = 0x0592;
+ t.segolwidehebrew = 0x05b6;
+ t.seharmenian = 0x057d;
+ t.sehiragana = 0x305b;
+ t.sekatakana = 0x30bb;
+ t.sekatakanahalfwidth = 0xff7e;
+ t.semicolon = 0x003b;
+ t.semicolonarabic = 0x061b;
+ t.semicolonmonospace = 0xff1b;
+ t.semicolonsmall = 0xfe54;
+ t.semivoicedmarkkana = 0x309c;
+ t.semivoicedmarkkanahalfwidth = 0xff9f;
+ t.sentisquare = 0x3322;
+ t.sentosquare = 0x3323;
+ t.seven = 0x0037;
+ t.sevenarabic = 0x0667;
+ t.sevenbengali = 0x09ed;
+ t.sevencircle = 0x2466;
+ t.sevencircleinversesansserif = 0x2790;
+ t.sevendeva = 0x096d;
+ t.seveneighths = 0x215e;
+ t.sevengujarati = 0x0aed;
+ t.sevengurmukhi = 0x0a6d;
+ t.sevenhackarabic = 0x0667;
+ t.sevenhangzhou = 0x3027;
+ t.sevenideographicparen = 0x3226;
+ t.seveninferior = 0x2087;
+ t.sevenmonospace = 0xff17;
+ t.sevenoldstyle = 0xf737;
+ t.sevenparen = 0x247a;
+ t.sevenperiod = 0x248e;
+ t.sevenpersian = 0x06f7;
+ t.sevenroman = 0x2176;
+ t.sevensuperior = 0x2077;
+ t.seventeencircle = 0x2470;
+ t.seventeenparen = 0x2484;
+ t.seventeenperiod = 0x2498;
+ t.seventhai = 0x0e57;
+ t.sfthyphen = 0x00ad;
+ t.shaarmenian = 0x0577;
+ t.shabengali = 0x09b6;
+ t.shacyrillic = 0x0448;
+ t.shaddaarabic = 0x0651;
+ t.shaddadammaarabic = 0xfc61;
+ t.shaddadammatanarabic = 0xfc5e;
+ t.shaddafathaarabic = 0xfc60;
+ t.shaddakasraarabic = 0xfc62;
+ t.shaddakasratanarabic = 0xfc5f;
+ t.shade = 0x2592;
+ t.shadedark = 0x2593;
+ t.shadelight = 0x2591;
+ t.shademedium = 0x2592;
+ t.shadeva = 0x0936;
+ t.shagujarati = 0x0ab6;
+ t.shagurmukhi = 0x0a36;
+ t.shalshelethebrew = 0x0593;
+ t.shbopomofo = 0x3115;
+ t.shchacyrillic = 0x0449;
+ t.sheenarabic = 0x0634;
+ t.sheenfinalarabic = 0xfeb6;
+ t.sheeninitialarabic = 0xfeb7;
+ t.sheenmedialarabic = 0xfeb8;
+ t.sheicoptic = 0x03e3;
+ t.sheqel = 0x20aa;
+ t.sheqelhebrew = 0x20aa;
+ t.sheva = 0x05b0;
+ t.sheva115 = 0x05b0;
+ t.sheva15 = 0x05b0;
+ t.sheva22 = 0x05b0;
+ t.sheva2e = 0x05b0;
+ t.shevahebrew = 0x05b0;
+ t.shevanarrowhebrew = 0x05b0;
+ t.shevaquarterhebrew = 0x05b0;
+ t.shevawidehebrew = 0x05b0;
+ t.shhacyrillic = 0x04bb;
+ t.shimacoptic = 0x03ed;
+ t.shin = 0x05e9;
+ t.shindagesh = 0xfb49;
+ t.shindageshhebrew = 0xfb49;
+ t.shindageshshindot = 0xfb2c;
+ t.shindageshshindothebrew = 0xfb2c;
+ t.shindageshsindot = 0xfb2d;
+ t.shindageshsindothebrew = 0xfb2d;
+ t.shindothebrew = 0x05c1;
+ t.shinhebrew = 0x05e9;
+ t.shinshindot = 0xfb2a;
+ t.shinshindothebrew = 0xfb2a;
+ t.shinsindot = 0xfb2b;
+ t.shinsindothebrew = 0xfb2b;
+ t.shook = 0x0282;
+ t.sigma = 0x03c3;
+ t.sigma1 = 0x03c2;
+ t.sigmafinal = 0x03c2;
+ t.sigmalunatesymbolgreek = 0x03f2;
+ t.sihiragana = 0x3057;
+ t.sikatakana = 0x30b7;
+ t.sikatakanahalfwidth = 0xff7c;
+ t.siluqhebrew = 0x05bd;
+ t.siluqlefthebrew = 0x05bd;
+ t.similar = 0x223c;
+ t.sindothebrew = 0x05c2;
+ t.siosacirclekorean = 0x3274;
+ t.siosaparenkorean = 0x3214;
+ t.sioscieuckorean = 0x317e;
+ t.sioscirclekorean = 0x3266;
+ t.sioskiyeokkorean = 0x317a;
+ t.sioskorean = 0x3145;
+ t.siosnieunkorean = 0x317b;
+ t.siosparenkorean = 0x3206;
+ t.siospieupkorean = 0x317d;
+ t.siostikeutkorean = 0x317c;
+ t.six = 0x0036;
+ t.sixarabic = 0x0666;
+ t.sixbengali = 0x09ec;
+ t.sixcircle = 0x2465;
+ t.sixcircleinversesansserif = 0x278f;
+ t.sixdeva = 0x096c;
+ t.sixgujarati = 0x0aec;
+ t.sixgurmukhi = 0x0a6c;
+ t.sixhackarabic = 0x0666;
+ t.sixhangzhou = 0x3026;
+ t.sixideographicparen = 0x3225;
+ t.sixinferior = 0x2086;
+ t.sixmonospace = 0xff16;
+ t.sixoldstyle = 0xf736;
+ t.sixparen = 0x2479;
+ t.sixperiod = 0x248d;
+ t.sixpersian = 0x06f6;
+ t.sixroman = 0x2175;
+ t.sixsuperior = 0x2076;
+ t.sixteencircle = 0x246f;
+ t.sixteencurrencydenominatorbengali = 0x09f9;
+ t.sixteenparen = 0x2483;
+ t.sixteenperiod = 0x2497;
+ t.sixthai = 0x0e56;
+ t.slash = 0x002f;
+ t.slashmonospace = 0xff0f;
+ t.slong = 0x017f;
+ t.slongdotaccent = 0x1e9b;
+ t.smileface = 0x263a;
+ t.smonospace = 0xff53;
+ t.sofpasuqhebrew = 0x05c3;
+ t.softhyphen = 0x00ad;
+ t.softsigncyrillic = 0x044c;
+ t.sohiragana = 0x305d;
+ t.sokatakana = 0x30bd;
+ t.sokatakanahalfwidth = 0xff7f;
+ t.soliduslongoverlaycmb = 0x0338;
+ t.solidusshortoverlaycmb = 0x0337;
+ t.sorusithai = 0x0e29;
+ t.sosalathai = 0x0e28;
+ t.sosothai = 0x0e0b;
+ t.sosuathai = 0x0e2a;
+ t.space = 0x0020;
+ t.spacehackarabic = 0x0020;
+ t.spade = 0x2660;
+ t.spadesuitblack = 0x2660;
+ t.spadesuitwhite = 0x2664;
+ t.sparen = 0x24ae;
+ t.squarebelowcmb = 0x033b;
+ t.squarecc = 0x33c4;
+ t.squarecm = 0x339d;
+ t.squarediagonalcrosshatchfill = 0x25a9;
+ t.squarehorizontalfill = 0x25a4;
+ t.squarekg = 0x338f;
+ t.squarekm = 0x339e;
+ t.squarekmcapital = 0x33ce;
+ t.squareln = 0x33d1;
+ t.squarelog = 0x33d2;
+ t.squaremg = 0x338e;
+ t.squaremil = 0x33d5;
+ t.squaremm = 0x339c;
+ t.squaremsquared = 0x33a1;
+ t.squareorthogonalcrosshatchfill = 0x25a6;
+ t.squareupperlefttolowerrightfill = 0x25a7;
+ t.squareupperrighttolowerleftfill = 0x25a8;
+ t.squareverticalfill = 0x25a5;
+ t.squarewhitewithsmallblack = 0x25a3;
+ t.srsquare = 0x33db;
+ t.ssabengali = 0x09b7;
+ t.ssadeva = 0x0937;
+ t.ssagujarati = 0x0ab7;
+ t.ssangcieuckorean = 0x3149;
+ t.ssanghieuhkorean = 0x3185;
+ t.ssangieungkorean = 0x3180;
+ t.ssangkiyeokkorean = 0x3132;
+ t.ssangnieunkorean = 0x3165;
+ t.ssangpieupkorean = 0x3143;
+ t.ssangsioskorean = 0x3146;
+ t.ssangtikeutkorean = 0x3138;
+ t.ssuperior = 0xf6f2;
+ t.sterling = 0x00a3;
+ t.sterlingmonospace = 0xffe1;
+ t.strokelongoverlaycmb = 0x0336;
+ t.strokeshortoverlaycmb = 0x0335;
+ t.subset = 0x2282;
+ t.subsetnotequal = 0x228a;
+ t.subsetorequal = 0x2286;
+ t.succeeds = 0x227b;
+ t.suchthat = 0x220b;
+ t.suhiragana = 0x3059;
+ t.sukatakana = 0x30b9;
+ t.sukatakanahalfwidth = 0xff7d;
+ t.sukunarabic = 0x0652;
+ t.summation = 0x2211;
+ t.sun = 0x263c;
+ t.superset = 0x2283;
+ t.supersetnotequal = 0x228b;
+ t.supersetorequal = 0x2287;
+ t.svsquare = 0x33dc;
+ t.syouwaerasquare = 0x337c;
+ t.t = 0x0074;
+ t.tabengali = 0x09a4;
+ t.tackdown = 0x22a4;
+ t.tackleft = 0x22a3;
+ t.tadeva = 0x0924;
+ t.tagujarati = 0x0aa4;
+ t.tagurmukhi = 0x0a24;
+ t.taharabic = 0x0637;
+ t.tahfinalarabic = 0xfec2;
+ t.tahinitialarabic = 0xfec3;
+ t.tahiragana = 0x305f;
+ t.tahmedialarabic = 0xfec4;
+ t.taisyouerasquare = 0x337d;
+ t.takatakana = 0x30bf;
+ t.takatakanahalfwidth = 0xff80;
+ t.tatweelarabic = 0x0640;
+ t.tau = 0x03c4;
+ t.tav = 0x05ea;
+ t.tavdages = 0xfb4a;
+ t.tavdagesh = 0xfb4a;
+ t.tavdageshhebrew = 0xfb4a;
+ t.tavhebrew = 0x05ea;
+ t.tbar = 0x0167;
+ t.tbopomofo = 0x310a;
+ t.tcaron = 0x0165;
+ t.tccurl = 0x02a8;
+ t.tcedilla = 0x0163;
+ t.tcheharabic = 0x0686;
+ t.tchehfinalarabic = 0xfb7b;
+ t.tchehinitialarabic = 0xfb7c;
+ t.tchehmedialarabic = 0xfb7d;
+ t.tcircle = 0x24e3;
+ t.tcircumflexbelow = 0x1e71;
+ t.tcommaaccent = 0x0163;
+ t.tdieresis = 0x1e97;
+ t.tdotaccent = 0x1e6b;
+ t.tdotbelow = 0x1e6d;
+ t.tecyrillic = 0x0442;
+ t.tedescendercyrillic = 0x04ad;
+ t.teharabic = 0x062a;
+ t.tehfinalarabic = 0xfe96;
+ t.tehhahinitialarabic = 0xfca2;
+ t.tehhahisolatedarabic = 0xfc0c;
+ t.tehinitialarabic = 0xfe97;
+ t.tehiragana = 0x3066;
+ t.tehjeeminitialarabic = 0xfca1;
+ t.tehjeemisolatedarabic = 0xfc0b;
+ t.tehmarbutaarabic = 0x0629;
+ t.tehmarbutafinalarabic = 0xfe94;
+ t.tehmedialarabic = 0xfe98;
+ t.tehmeeminitialarabic = 0xfca4;
+ t.tehmeemisolatedarabic = 0xfc0e;
+ t.tehnoonfinalarabic = 0xfc73;
+ t.tekatakana = 0x30c6;
+ t.tekatakanahalfwidth = 0xff83;
+ t.telephone = 0x2121;
+ t.telephoneblack = 0x260e;
+ t.telishagedolahebrew = 0x05a0;
+ t.telishaqetanahebrew = 0x05a9;
+ t.tencircle = 0x2469;
+ t.tenideographicparen = 0x3229;
+ t.tenparen = 0x247d;
+ t.tenperiod = 0x2491;
+ t.tenroman = 0x2179;
+ t.tesh = 0x02a7;
+ t.tet = 0x05d8;
+ t.tetdagesh = 0xfb38;
+ t.tetdageshhebrew = 0xfb38;
+ t.tethebrew = 0x05d8;
+ t.tetsecyrillic = 0x04b5;
+ t.tevirhebrew = 0x059b;
+ t.tevirlefthebrew = 0x059b;
+ t.thabengali = 0x09a5;
+ t.thadeva = 0x0925;
+ t.thagujarati = 0x0aa5;
+ t.thagurmukhi = 0x0a25;
+ t.thalarabic = 0x0630;
+ t.thalfinalarabic = 0xfeac;
+ t.thanthakhatlowleftthai = 0xf898;
+ t.thanthakhatlowrightthai = 0xf897;
+ t.thanthakhatthai = 0x0e4c;
+ t.thanthakhatupperleftthai = 0xf896;
+ t.theharabic = 0x062b;
+ t.thehfinalarabic = 0xfe9a;
+ t.thehinitialarabic = 0xfe9b;
+ t.thehmedialarabic = 0xfe9c;
+ t.thereexists = 0x2203;
+ t.therefore = 0x2234;
+ t.theta = 0x03b8;
+ t.theta1 = 0x03d1;
+ t.thetasymbolgreek = 0x03d1;
+ t.thieuthacirclekorean = 0x3279;
+ t.thieuthaparenkorean = 0x3219;
+ t.thieuthcirclekorean = 0x326b;
+ t.thieuthkorean = 0x314c;
+ t.thieuthparenkorean = 0x320b;
+ t.thirteencircle = 0x246c;
+ t.thirteenparen = 0x2480;
+ t.thirteenperiod = 0x2494;
+ t.thonangmonthothai = 0x0e11;
+ t.thook = 0x01ad;
+ t.thophuthaothai = 0x0e12;
+ t.thorn = 0x00fe;
+ t.thothahanthai = 0x0e17;
+ t.thothanthai = 0x0e10;
+ t.thothongthai = 0x0e18;
+ t.thothungthai = 0x0e16;
+ t.thousandcyrillic = 0x0482;
+ t.thousandsseparatorarabic = 0x066c;
+ t.thousandsseparatorpersian = 0x066c;
+ t.three = 0x0033;
+ t.threearabic = 0x0663;
+ t.threebengali = 0x09e9;
+ t.threecircle = 0x2462;
+ t.threecircleinversesansserif = 0x278c;
+ t.threedeva = 0x0969;
+ t.threeeighths = 0x215c;
+ t.threegujarati = 0x0ae9;
+ t.threegurmukhi = 0x0a69;
+ t.threehackarabic = 0x0663;
+ t.threehangzhou = 0x3023;
+ t.threeideographicparen = 0x3222;
+ t.threeinferior = 0x2083;
+ t.threemonospace = 0xff13;
+ t.threenumeratorbengali = 0x09f6;
+ t.threeoldstyle = 0xf733;
+ t.threeparen = 0x2476;
+ t.threeperiod = 0x248a;
+ t.threepersian = 0x06f3;
+ t.threequarters = 0x00be;
+ t.threequartersemdash = 0xf6de;
+ t.threeroman = 0x2172;
+ t.threesuperior = 0x00b3;
+ t.threethai = 0x0e53;
+ t.thzsquare = 0x3394;
+ t.tihiragana = 0x3061;
+ t.tikatakana = 0x30c1;
+ t.tikatakanahalfwidth = 0xff81;
+ t.tikeutacirclekorean = 0x3270;
+ t.tikeutaparenkorean = 0x3210;
+ t.tikeutcirclekorean = 0x3262;
+ t.tikeutkorean = 0x3137;
+ t.tikeutparenkorean = 0x3202;
+ t.tilde = 0x02dc;
+ t.tildebelowcmb = 0x0330;
+ t.tildecmb = 0x0303;
+ t.tildecomb = 0x0303;
+ t.tildedoublecmb = 0x0360;
+ t.tildeoperator = 0x223c;
+ t.tildeoverlaycmb = 0x0334;
+ t.tildeverticalcmb = 0x033e;
+ t.timescircle = 0x2297;
+ t.tipehahebrew = 0x0596;
+ t.tipehalefthebrew = 0x0596;
+ t.tippigurmukhi = 0x0a70;
+ t.titlocyrilliccmb = 0x0483;
+ t.tiwnarmenian = 0x057f;
+ t.tlinebelow = 0x1e6f;
+ t.tmonospace = 0xff54;
+ t.toarmenian = 0x0569;
+ t.tohiragana = 0x3068;
+ t.tokatakana = 0x30c8;
+ t.tokatakanahalfwidth = 0xff84;
+ t.tonebarextrahighmod = 0x02e5;
+ t.tonebarextralowmod = 0x02e9;
+ t.tonebarhighmod = 0x02e6;
+ t.tonebarlowmod = 0x02e8;
+ t.tonebarmidmod = 0x02e7;
+ t.tonefive = 0x01bd;
+ t.tonesix = 0x0185;
+ t.tonetwo = 0x01a8;
+ t.tonos = 0x0384;
+ t.tonsquare = 0x3327;
+ t.topatakthai = 0x0e0f;
+ t.tortoiseshellbracketleft = 0x3014;
+ t.tortoiseshellbracketleftsmall = 0xfe5d;
+ t.tortoiseshellbracketleftvertical = 0xfe39;
+ t.tortoiseshellbracketright = 0x3015;
+ t.tortoiseshellbracketrightsmall = 0xfe5e;
+ t.tortoiseshellbracketrightvertical = 0xfe3a;
+ t.totaothai = 0x0e15;
+ t.tpalatalhook = 0x01ab;
+ t.tparen = 0x24af;
+ t.trademark = 0x2122;
+ t.trademarksans = 0xf8ea;
+ t.trademarkserif = 0xf6db;
+ t.tretroflexhook = 0x0288;
+ t.triagdn = 0x25bc;
+ t.triaglf = 0x25c4;
+ t.triagrt = 0x25ba;
+ t.triagup = 0x25b2;
+ t.ts = 0x02a6;
+ t.tsadi = 0x05e6;
+ t.tsadidagesh = 0xfb46;
+ t.tsadidageshhebrew = 0xfb46;
+ t.tsadihebrew = 0x05e6;
+ t.tsecyrillic = 0x0446;
+ t.tsere = 0x05b5;
+ t.tsere12 = 0x05b5;
+ t.tsere1e = 0x05b5;
+ t.tsere2b = 0x05b5;
+ t.tserehebrew = 0x05b5;
+ t.tserenarrowhebrew = 0x05b5;
+ t.tserequarterhebrew = 0x05b5;
+ t.tserewidehebrew = 0x05b5;
+ t.tshecyrillic = 0x045b;
+ t.tsuperior = 0xf6f3;
+ t.ttabengali = 0x099f;
+ t.ttadeva = 0x091f;
+ t.ttagujarati = 0x0a9f;
+ t.ttagurmukhi = 0x0a1f;
+ t.tteharabic = 0x0679;
+ t.ttehfinalarabic = 0xfb67;
+ t.ttehinitialarabic = 0xfb68;
+ t.ttehmedialarabic = 0xfb69;
+ t.tthabengali = 0x09a0;
+ t.tthadeva = 0x0920;
+ t.tthagujarati = 0x0aa0;
+ t.tthagurmukhi = 0x0a20;
+ t.tturned = 0x0287;
+ t.tuhiragana = 0x3064;
+ t.tukatakana = 0x30c4;
+ t.tukatakanahalfwidth = 0xff82;
+ t.tusmallhiragana = 0x3063;
+ t.tusmallkatakana = 0x30c3;
+ t.tusmallkatakanahalfwidth = 0xff6f;
+ t.twelvecircle = 0x246b;
+ t.twelveparen = 0x247f;
+ t.twelveperiod = 0x2493;
+ t.twelveroman = 0x217b;
+ t.twentycircle = 0x2473;
+ t.twentyhangzhou = 0x5344;
+ t.twentyparen = 0x2487;
+ t.twentyperiod = 0x249b;
+ t.two = 0x0032;
+ t.twoarabic = 0x0662;
+ t.twobengali = 0x09e8;
+ t.twocircle = 0x2461;
+ t.twocircleinversesansserif = 0x278b;
+ t.twodeva = 0x0968;
+ t.twodotenleader = 0x2025;
+ t.twodotleader = 0x2025;
+ t.twodotleadervertical = 0xfe30;
+ t.twogujarati = 0x0ae8;
+ t.twogurmukhi = 0x0a68;
+ t.twohackarabic = 0x0662;
+ t.twohangzhou = 0x3022;
+ t.twoideographicparen = 0x3221;
+ t.twoinferior = 0x2082;
+ t.twomonospace = 0xff12;
+ t.twonumeratorbengali = 0x09f5;
+ t.twooldstyle = 0xf732;
+ t.twoparen = 0x2475;
+ t.twoperiod = 0x2489;
+ t.twopersian = 0x06f2;
+ t.tworoman = 0x2171;
+ t.twostroke = 0x01bb;
+ t.twosuperior = 0x00b2;
+ t.twothai = 0x0e52;
+ t.twothirds = 0x2154;
+ t.u = 0x0075;
+ t.uacute = 0x00fa;
+ t.ubar = 0x0289;
+ t.ubengali = 0x0989;
+ t.ubopomofo = 0x3128;
+ t.ubreve = 0x016d;
+ t.ucaron = 0x01d4;
+ t.ucircle = 0x24e4;
+ t.ucircumflex = 0x00fb;
+ t.ucircumflexbelow = 0x1e77;
+ t.ucyrillic = 0x0443;
+ t.udattadeva = 0x0951;
+ t.udblacute = 0x0171;
+ t.udblgrave = 0x0215;
+ t.udeva = 0x0909;
+ t.udieresis = 0x00fc;
+ t.udieresisacute = 0x01d8;
+ t.udieresisbelow = 0x1e73;
+ t.udieresiscaron = 0x01da;
+ t.udieresiscyrillic = 0x04f1;
+ t.udieresisgrave = 0x01dc;
+ t.udieresismacron = 0x01d6;
+ t.udotbelow = 0x1ee5;
+ t.ugrave = 0x00f9;
+ t.ugujarati = 0x0a89;
+ t.ugurmukhi = 0x0a09;
+ t.uhiragana = 0x3046;
+ t.uhookabove = 0x1ee7;
+ t.uhorn = 0x01b0;
+ t.uhornacute = 0x1ee9;
+ t.uhorndotbelow = 0x1ef1;
+ t.uhorngrave = 0x1eeb;
+ t.uhornhookabove = 0x1eed;
+ t.uhorntilde = 0x1eef;
+ t.uhungarumlaut = 0x0171;
+ t.uhungarumlautcyrillic = 0x04f3;
+ t.uinvertedbreve = 0x0217;
+ t.ukatakana = 0x30a6;
+ t.ukatakanahalfwidth = 0xff73;
+ t.ukcyrillic = 0x0479;
+ t.ukorean = 0x315c;
+ t.umacron = 0x016b;
+ t.umacroncyrillic = 0x04ef;
+ t.umacrondieresis = 0x1e7b;
+ t.umatragurmukhi = 0x0a41;
+ t.umonospace = 0xff55;
+ t.underscore = 0x005f;
+ t.underscoredbl = 0x2017;
+ t.underscoremonospace = 0xff3f;
+ t.underscorevertical = 0xfe33;
+ t.underscorewavy = 0xfe4f;
+ t.union = 0x222a;
+ t.universal = 0x2200;
+ t.uogonek = 0x0173;
+ t.uparen = 0x24b0;
+ t.upblock = 0x2580;
+ t.upperdothebrew = 0x05c4;
+ t.upsilon = 0x03c5;
+ t.upsilondieresis = 0x03cb;
+ t.upsilondieresistonos = 0x03b0;
+ t.upsilonlatin = 0x028a;
+ t.upsilontonos = 0x03cd;
+ t.uptackbelowcmb = 0x031d;
+ t.uptackmod = 0x02d4;
+ t.uragurmukhi = 0x0a73;
+ t.uring = 0x016f;
+ t.ushortcyrillic = 0x045e;
+ t.usmallhiragana = 0x3045;
+ t.usmallkatakana = 0x30a5;
+ t.usmallkatakanahalfwidth = 0xff69;
+ t.ustraightcyrillic = 0x04af;
+ t.ustraightstrokecyrillic = 0x04b1;
+ t.utilde = 0x0169;
+ t.utildeacute = 0x1e79;
+ t.utildebelow = 0x1e75;
+ t.uubengali = 0x098a;
+ t.uudeva = 0x090a;
+ t.uugujarati = 0x0a8a;
+ t.uugurmukhi = 0x0a0a;
+ t.uumatragurmukhi = 0x0a42;
+ t.uuvowelsignbengali = 0x09c2;
+ t.uuvowelsigndeva = 0x0942;
+ t.uuvowelsigngujarati = 0x0ac2;
+ t.uvowelsignbengali = 0x09c1;
+ t.uvowelsigndeva = 0x0941;
+ t.uvowelsigngujarati = 0x0ac1;
+ t.v = 0x0076;
+ t.vadeva = 0x0935;
+ t.vagujarati = 0x0ab5;
+ t.vagurmukhi = 0x0a35;
+ t.vakatakana = 0x30f7;
+ t.vav = 0x05d5;
+ t.vavdagesh = 0xfb35;
+ t.vavdagesh65 = 0xfb35;
+ t.vavdageshhebrew = 0xfb35;
+ t.vavhebrew = 0x05d5;
+ t.vavholam = 0xfb4b;
+ t.vavholamhebrew = 0xfb4b;
+ t.vavvavhebrew = 0x05f0;
+ t.vavyodhebrew = 0x05f1;
+ t.vcircle = 0x24e5;
+ t.vdotbelow = 0x1e7f;
+ t.vecyrillic = 0x0432;
+ t.veharabic = 0x06a4;
+ t.vehfinalarabic = 0xfb6b;
+ t.vehinitialarabic = 0xfb6c;
+ t.vehmedialarabic = 0xfb6d;
+ t.vekatakana = 0x30f9;
+ t.venus = 0x2640;
+ t.verticalbar = 0x007c;
+ t.verticallineabovecmb = 0x030d;
+ t.verticallinebelowcmb = 0x0329;
+ t.verticallinelowmod = 0x02cc;
+ t.verticallinemod = 0x02c8;
+ t.vewarmenian = 0x057e;
+ t.vhook = 0x028b;
+ t.vikatakana = 0x30f8;
+ t.viramabengali = 0x09cd;
+ t.viramadeva = 0x094d;
+ t.viramagujarati = 0x0acd;
+ t.visargabengali = 0x0983;
+ t.visargadeva = 0x0903;
+ t.visargagujarati = 0x0a83;
+ t.vmonospace = 0xff56;
+ t.voarmenian = 0x0578;
+ t.voicediterationhiragana = 0x309e;
+ t.voicediterationkatakana = 0x30fe;
+ t.voicedmarkkana = 0x309b;
+ t.voicedmarkkanahalfwidth = 0xff9e;
+ t.vokatakana = 0x30fa;
+ t.vparen = 0x24b1;
+ t.vtilde = 0x1e7d;
+ t.vturned = 0x028c;
+ t.vuhiragana = 0x3094;
+ t.vukatakana = 0x30f4;
+ t.w = 0x0077;
+ t.wacute = 0x1e83;
+ t.waekorean = 0x3159;
+ t.wahiragana = 0x308f;
+ t.wakatakana = 0x30ef;
+ t.wakatakanahalfwidth = 0xff9c;
+ t.wakorean = 0x3158;
+ t.wasmallhiragana = 0x308e;
+ t.wasmallkatakana = 0x30ee;
+ t.wattosquare = 0x3357;
+ t.wavedash = 0x301c;
+ t.wavyunderscorevertical = 0xfe34;
+ t.wawarabic = 0x0648;
+ t.wawfinalarabic = 0xfeee;
+ t.wawhamzaabovearabic = 0x0624;
+ t.wawhamzaabovefinalarabic = 0xfe86;
+ t.wbsquare = 0x33dd;
+ t.wcircle = 0x24e6;
+ t.wcircumflex = 0x0175;
+ t.wdieresis = 0x1e85;
+ t.wdotaccent = 0x1e87;
+ t.wdotbelow = 0x1e89;
+ t.wehiragana = 0x3091;
+ t.weierstrass = 0x2118;
+ t.wekatakana = 0x30f1;
+ t.wekorean = 0x315e;
+ t.weokorean = 0x315d;
+ t.wgrave = 0x1e81;
+ t.whitebullet = 0x25e6;
+ t.whitecircle = 0x25cb;
+ t.whitecircleinverse = 0x25d9;
+ t.whitecornerbracketleft = 0x300e;
+ t.whitecornerbracketleftvertical = 0xfe43;
+ t.whitecornerbracketright = 0x300f;
+ t.whitecornerbracketrightvertical = 0xfe44;
+ t.whitediamond = 0x25c7;
+ t.whitediamondcontainingblacksmalldiamond = 0x25c8;
+ t.whitedownpointingsmalltriangle = 0x25bf;
+ t.whitedownpointingtriangle = 0x25bd;
+ t.whiteleftpointingsmalltriangle = 0x25c3;
+ t.whiteleftpointingtriangle = 0x25c1;
+ t.whitelenticularbracketleft = 0x3016;
+ t.whitelenticularbracketright = 0x3017;
+ t.whiterightpointingsmalltriangle = 0x25b9;
+ t.whiterightpointingtriangle = 0x25b7;
+ t.whitesmallsquare = 0x25ab;
+ t.whitesmilingface = 0x263a;
+ t.whitesquare = 0x25a1;
+ t.whitestar = 0x2606;
+ t.whitetelephone = 0x260f;
+ t.whitetortoiseshellbracketleft = 0x3018;
+ t.whitetortoiseshellbracketright = 0x3019;
+ t.whiteuppointingsmalltriangle = 0x25b5;
+ t.whiteuppointingtriangle = 0x25b3;
+ t.wihiragana = 0x3090;
+ t.wikatakana = 0x30f0;
+ t.wikorean = 0x315f;
+ t.wmonospace = 0xff57;
+ t.wohiragana = 0x3092;
+ t.wokatakana = 0x30f2;
+ t.wokatakanahalfwidth = 0xff66;
+ t.won = 0x20a9;
+ t.wonmonospace = 0xffe6;
+ t.wowaenthai = 0x0e27;
+ t.wparen = 0x24b2;
+ t.wring = 0x1e98;
+ t.wsuperior = 0x02b7;
+ t.wturned = 0x028d;
+ t.wynn = 0x01bf;
+ t.x = 0x0078;
+ t.xabovecmb = 0x033d;
+ t.xbopomofo = 0x3112;
+ t.xcircle = 0x24e7;
+ t.xdieresis = 0x1e8d;
+ t.xdotaccent = 0x1e8b;
+ t.xeharmenian = 0x056d;
+ t.xi = 0x03be;
+ t.xmonospace = 0xff58;
+ t.xparen = 0x24b3;
+ t.xsuperior = 0x02e3;
+ t.y = 0x0079;
+ t.yaadosquare = 0x334e;
+ t.yabengali = 0x09af;
+ t.yacute = 0x00fd;
+ t.yadeva = 0x092f;
+ t.yaekorean = 0x3152;
+ t.yagujarati = 0x0aaf;
+ t.yagurmukhi = 0x0a2f;
+ t.yahiragana = 0x3084;
+ t.yakatakana = 0x30e4;
+ t.yakatakanahalfwidth = 0xff94;
+ t.yakorean = 0x3151;
+ t.yamakkanthai = 0x0e4e;
+ t.yasmallhiragana = 0x3083;
+ t.yasmallkatakana = 0x30e3;
+ t.yasmallkatakanahalfwidth = 0xff6c;
+ t.yatcyrillic = 0x0463;
+ t.ycircle = 0x24e8;
+ t.ycircumflex = 0x0177;
+ t.ydieresis = 0x00ff;
+ t.ydotaccent = 0x1e8f;
+ t.ydotbelow = 0x1ef5;
+ t.yeharabic = 0x064a;
+ t.yehbarreearabic = 0x06d2;
+ t.yehbarreefinalarabic = 0xfbaf;
+ t.yehfinalarabic = 0xfef2;
+ t.yehhamzaabovearabic = 0x0626;
+ t.yehhamzaabovefinalarabic = 0xfe8a;
+ t.yehhamzaaboveinitialarabic = 0xfe8b;
+ t.yehhamzaabovemedialarabic = 0xfe8c;
+ t.yehinitialarabic = 0xfef3;
+ t.yehmedialarabic = 0xfef4;
+ t.yehmeeminitialarabic = 0xfcdd;
+ t.yehmeemisolatedarabic = 0xfc58;
+ t.yehnoonfinalarabic = 0xfc94;
+ t.yehthreedotsbelowarabic = 0x06d1;
+ t.yekorean = 0x3156;
+ t.yen = 0x00a5;
+ t.yenmonospace = 0xffe5;
+ t.yeokorean = 0x3155;
+ t.yeorinhieuhkorean = 0x3186;
+ t.yerahbenyomohebrew = 0x05aa;
+ t.yerahbenyomolefthebrew = 0x05aa;
+ t.yericyrillic = 0x044b;
+ t.yerudieresiscyrillic = 0x04f9;
+ t.yesieungkorean = 0x3181;
+ t.yesieungpansioskorean = 0x3183;
+ t.yesieungsioskorean = 0x3182;
+ t.yetivhebrew = 0x059a;
+ t.ygrave = 0x1ef3;
+ t.yhook = 0x01b4;
+ t.yhookabove = 0x1ef7;
+ t.yiarmenian = 0x0575;
+ t.yicyrillic = 0x0457;
+ t.yikorean = 0x3162;
+ t.yinyang = 0x262f;
+ t.yiwnarmenian = 0x0582;
+ t.ymonospace = 0xff59;
+ t.yod = 0x05d9;
+ t.yoddagesh = 0xfb39;
+ t.yoddageshhebrew = 0xfb39;
+ t.yodhebrew = 0x05d9;
+ t.yodyodhebrew = 0x05f2;
+ t.yodyodpatahhebrew = 0xfb1f;
+ t.yohiragana = 0x3088;
+ t.yoikorean = 0x3189;
+ t.yokatakana = 0x30e8;
+ t.yokatakanahalfwidth = 0xff96;
+ t.yokorean = 0x315b;
+ t.yosmallhiragana = 0x3087;
+ t.yosmallkatakana = 0x30e7;
+ t.yosmallkatakanahalfwidth = 0xff6e;
+ t.yotgreek = 0x03f3;
+ t.yoyaekorean = 0x3188;
+ t.yoyakorean = 0x3187;
+ t.yoyakthai = 0x0e22;
+ t.yoyingthai = 0x0e0d;
+ t.yparen = 0x24b4;
+ t.ypogegrammeni = 0x037a;
+ t.ypogegrammenigreekcmb = 0x0345;
+ t.yr = 0x01a6;
+ t.yring = 0x1e99;
+ t.ysuperior = 0x02b8;
+ t.ytilde = 0x1ef9;
+ t.yturned = 0x028e;
+ t.yuhiragana = 0x3086;
+ t.yuikorean = 0x318c;
+ t.yukatakana = 0x30e6;
+ t.yukatakanahalfwidth = 0xff95;
+ t.yukorean = 0x3160;
+ t.yusbigcyrillic = 0x046b;
+ t.yusbigiotifiedcyrillic = 0x046d;
+ t.yuslittlecyrillic = 0x0467;
+ t.yuslittleiotifiedcyrillic = 0x0469;
+ t.yusmallhiragana = 0x3085;
+ t.yusmallkatakana = 0x30e5;
+ t.yusmallkatakanahalfwidth = 0xff6d;
+ t.yuyekorean = 0x318b;
+ t.yuyeokorean = 0x318a;
+ t.yyabengali = 0x09df;
+ t.yyadeva = 0x095f;
+ t.z = 0x007a;
+ t.zaarmenian = 0x0566;
+ t.zacute = 0x017a;
+ t.zadeva = 0x095b;
+ t.zagurmukhi = 0x0a5b;
+ t.zaharabic = 0x0638;
+ t.zahfinalarabic = 0xfec6;
+ t.zahinitialarabic = 0xfec7;
+ t.zahiragana = 0x3056;
+ t.zahmedialarabic = 0xfec8;
+ t.zainarabic = 0x0632;
+ t.zainfinalarabic = 0xfeb0;
+ t.zakatakana = 0x30b6;
+ t.zaqefgadolhebrew = 0x0595;
+ t.zaqefqatanhebrew = 0x0594;
+ t.zarqahebrew = 0x0598;
+ t.zayin = 0x05d6;
+ t.zayindagesh = 0xfb36;
+ t.zayindageshhebrew = 0xfb36;
+ t.zayinhebrew = 0x05d6;
+ t.zbopomofo = 0x3117;
+ t.zcaron = 0x017e;
+ t.zcircle = 0x24e9;
+ t.zcircumflex = 0x1e91;
+ t.zcurl = 0x0291;
+ t.zdot = 0x017c;
+ t.zdotaccent = 0x017c;
+ t.zdotbelow = 0x1e93;
+ t.zecyrillic = 0x0437;
+ t.zedescendercyrillic = 0x0499;
+ t.zedieresiscyrillic = 0x04df;
+ t.zehiragana = 0x305c;
+ t.zekatakana = 0x30bc;
+ t.zero = 0x0030;
+ t.zeroarabic = 0x0660;
+ t.zerobengali = 0x09e6;
+ t.zerodeva = 0x0966;
+ t.zerogujarati = 0x0ae6;
+ t.zerogurmukhi = 0x0a66;
+ t.zerohackarabic = 0x0660;
+ t.zeroinferior = 0x2080;
+ t.zeromonospace = 0xff10;
+ t.zerooldstyle = 0xf730;
+ t.zeropersian = 0x06f0;
+ t.zerosuperior = 0x2070;
+ t.zerothai = 0x0e50;
+ t.zerowidthjoiner = 0xfeff;
+ t.zerowidthnonjoiner = 0x200c;
+ t.zerowidthspace = 0x200b;
+ t.zeta = 0x03b6;
+ t.zhbopomofo = 0x3113;
+ t.zhearmenian = 0x056a;
+ t.zhebrevecyrillic = 0x04c2;
+ t.zhecyrillic = 0x0436;
+ t.zhedescendercyrillic = 0x0497;
+ t.zhedieresiscyrillic = 0x04dd;
+ t.zihiragana = 0x3058;
+ t.zikatakana = 0x30b8;
+ t.zinorhebrew = 0x05ae;
+ t.zlinebelow = 0x1e95;
+ t.zmonospace = 0xff5a;
+ t.zohiragana = 0x305e;
+ t.zokatakana = 0x30be;
+ t.zparen = 0x24b5;
+ t.zretroflexhook = 0x0290;
+ t.zstroke = 0x01b6;
+ t.zuhiragana = 0x305a;
+ t.zukatakana = 0x30ba;
+ t[".notdef"] = 0x0000;
+ t.angbracketleftbig = 0x2329;
+ t.angbracketleftBig = 0x2329;
+ t.angbracketleftbigg = 0x2329;
+ t.angbracketleftBigg = 0x2329;
+ t.angbracketrightBig = 0x232a;
+ t.angbracketrightbig = 0x232a;
+ t.angbracketrightBigg = 0x232a;
+ t.angbracketrightbigg = 0x232a;
+ t.arrowhookleft = 0x21aa;
+ t.arrowhookright = 0x21a9;
+ t.arrowlefttophalf = 0x21bc;
+ t.arrowleftbothalf = 0x21bd;
+ t.arrownortheast = 0x2197;
+ t.arrownorthwest = 0x2196;
+ t.arrowrighttophalf = 0x21c0;
+ t.arrowrightbothalf = 0x21c1;
+ t.arrowsoutheast = 0x2198;
+ t.arrowsouthwest = 0x2199;
+ t.backslashbig = 0x2216;
+ t.backslashBig = 0x2216;
+ t.backslashBigg = 0x2216;
+ t.backslashbigg = 0x2216;
+ t.bardbl = 0x2016;
+ t.bracehtipdownleft = 0xfe37;
+ t.bracehtipdownright = 0xfe37;
+ t.bracehtipupleft = 0xfe38;
+ t.bracehtipupright = 0xfe38;
+ t.braceleftBig = 0x007b;
+ t.braceleftbig = 0x007b;
+ t.braceleftbigg = 0x007b;
+ t.braceleftBigg = 0x007b;
+ t.bracerightBig = 0x007d;
+ t.bracerightbig = 0x007d;
+ t.bracerightbigg = 0x007d;
+ t.bracerightBigg = 0x007d;
+ t.bracketleftbig = 0x005b;
+ t.bracketleftBig = 0x005b;
+ t.bracketleftbigg = 0x005b;
+ t.bracketleftBigg = 0x005b;
+ t.bracketrightBig = 0x005d;
+ t.bracketrightbig = 0x005d;
+ t.bracketrightbigg = 0x005d;
+ t.bracketrightBigg = 0x005d;
+ t.ceilingleftbig = 0x2308;
+ t.ceilingleftBig = 0x2308;
+ t.ceilingleftBigg = 0x2308;
+ t.ceilingleftbigg = 0x2308;
+ t.ceilingrightbig = 0x2309;
+ t.ceilingrightBig = 0x2309;
+ t.ceilingrightbigg = 0x2309;
+ t.ceilingrightBigg = 0x2309;
+ t.circledotdisplay = 0x2299;
+ t.circledottext = 0x2299;
+ t.circlemultiplydisplay = 0x2297;
+ t.circlemultiplytext = 0x2297;
+ t.circleplusdisplay = 0x2295;
+ t.circleplustext = 0x2295;
+ t.contintegraldisplay = 0x222e;
+ t.contintegraltext = 0x222e;
+ t.coproductdisplay = 0x2210;
+ t.coproducttext = 0x2210;
+ t.floorleftBig = 0x230a;
+ t.floorleftbig = 0x230a;
+ t.floorleftbigg = 0x230a;
+ t.floorleftBigg = 0x230a;
+ t.floorrightbig = 0x230b;
+ t.floorrightBig = 0x230b;
+ t.floorrightBigg = 0x230b;
+ t.floorrightbigg = 0x230b;
+ t.hatwide = 0x0302;
+ t.hatwider = 0x0302;
+ t.hatwidest = 0x0302;
+ t.intercal = 0x1d40;
+ t.integraldisplay = 0x222b;
+ t.integraltext = 0x222b;
+ t.intersectiondisplay = 0x22c2;
+ t.intersectiontext = 0x22c2;
+ t.logicalanddisplay = 0x2227;
+ t.logicalandtext = 0x2227;
+ t.logicalordisplay = 0x2228;
+ t.logicalortext = 0x2228;
+ t.parenleftBig = 0x0028;
+ t.parenleftbig = 0x0028;
+ t.parenleftBigg = 0x0028;
+ t.parenleftbigg = 0x0028;
+ t.parenrightBig = 0x0029;
+ t.parenrightbig = 0x0029;
+ t.parenrightBigg = 0x0029;
+ t.parenrightbigg = 0x0029;
+ t.prime = 0x2032;
+ t.productdisplay = 0x220f;
+ t.producttext = 0x220f;
+ t.radicalbig = 0x221a;
+ t.radicalBig = 0x221a;
+ t.radicalBigg = 0x221a;
+ t.radicalbigg = 0x221a;
+ t.radicalbt = 0x221a;
+ t.radicaltp = 0x221a;
+ t.radicalvertex = 0x221a;
+ t.slashbig = 0x002f;
+ t.slashBig = 0x002f;
+ t.slashBigg = 0x002f;
+ t.slashbigg = 0x002f;
+ t.summationdisplay = 0x2211;
+ t.summationtext = 0x2211;
+ t.tildewide = 0x02dc;
+ t.tildewider = 0x02dc;
+ t.tildewidest = 0x02dc;
+ t.uniondisplay = 0x22c3;
+ t.unionmultidisplay = 0x228e;
+ t.unionmultitext = 0x228e;
+ t.unionsqdisplay = 0x2294;
+ t.unionsqtext = 0x2294;
+ t.uniontext = 0x22c3;
+ t.vextenddouble = 0x2225;
+ t.vextendsingle = 0x2223;
+});
+const getDingbatsGlyphsUnicode = getLookupTableFactory(function (t) {
+ t.space = 0x0020;
+ t.a1 = 0x2701;
+ t.a2 = 0x2702;
+ t.a202 = 0x2703;
+ t.a3 = 0x2704;
+ t.a4 = 0x260e;
+ t.a5 = 0x2706;
+ t.a119 = 0x2707;
+ t.a118 = 0x2708;
+ t.a117 = 0x2709;
+ t.a11 = 0x261b;
+ t.a12 = 0x261e;
+ t.a13 = 0x270c;
+ t.a14 = 0x270d;
+ t.a15 = 0x270e;
+ t.a16 = 0x270f;
+ t.a105 = 0x2710;
+ t.a17 = 0x2711;
+ t.a18 = 0x2712;
+ t.a19 = 0x2713;
+ t.a20 = 0x2714;
+ t.a21 = 0x2715;
+ t.a22 = 0x2716;
+ t.a23 = 0x2717;
+ t.a24 = 0x2718;
+ t.a25 = 0x2719;
+ t.a26 = 0x271a;
+ t.a27 = 0x271b;
+ t.a28 = 0x271c;
+ t.a6 = 0x271d;
+ t.a7 = 0x271e;
+ t.a8 = 0x271f;
+ t.a9 = 0x2720;
+ t.a10 = 0x2721;
+ t.a29 = 0x2722;
+ t.a30 = 0x2723;
+ t.a31 = 0x2724;
+ t.a32 = 0x2725;
+ t.a33 = 0x2726;
+ t.a34 = 0x2727;
+ t.a35 = 0x2605;
+ t.a36 = 0x2729;
+ t.a37 = 0x272a;
+ t.a38 = 0x272b;
+ t.a39 = 0x272c;
+ t.a40 = 0x272d;
+ t.a41 = 0x272e;
+ t.a42 = 0x272f;
+ t.a43 = 0x2730;
+ t.a44 = 0x2731;
+ t.a45 = 0x2732;
+ t.a46 = 0x2733;
+ t.a47 = 0x2734;
+ t.a48 = 0x2735;
+ t.a49 = 0x2736;
+ t.a50 = 0x2737;
+ t.a51 = 0x2738;
+ t.a52 = 0x2739;
+ t.a53 = 0x273a;
+ t.a54 = 0x273b;
+ t.a55 = 0x273c;
+ t.a56 = 0x273d;
+ t.a57 = 0x273e;
+ t.a58 = 0x273f;
+ t.a59 = 0x2740;
+ t.a60 = 0x2741;
+ t.a61 = 0x2742;
+ t.a62 = 0x2743;
+ t.a63 = 0x2744;
+ t.a64 = 0x2745;
+ t.a65 = 0x2746;
+ t.a66 = 0x2747;
+ t.a67 = 0x2748;
+ t.a68 = 0x2749;
+ t.a69 = 0x274a;
+ t.a70 = 0x274b;
+ t.a71 = 0x25cf;
+ t.a72 = 0x274d;
+ t.a73 = 0x25a0;
+ t.a74 = 0x274f;
+ t.a203 = 0x2750;
+ t.a75 = 0x2751;
+ t.a204 = 0x2752;
+ t.a76 = 0x25b2;
+ t.a77 = 0x25bc;
+ t.a78 = 0x25c6;
+ t.a79 = 0x2756;
+ t.a81 = 0x25d7;
+ t.a82 = 0x2758;
+ t.a83 = 0x2759;
+ t.a84 = 0x275a;
+ t.a97 = 0x275b;
+ t.a98 = 0x275c;
+ t.a99 = 0x275d;
+ t.a100 = 0x275e;
+ t.a101 = 0x2761;
+ t.a102 = 0x2762;
+ t.a103 = 0x2763;
+ t.a104 = 0x2764;
+ t.a106 = 0x2765;
+ t.a107 = 0x2766;
+ t.a108 = 0x2767;
+ t.a112 = 0x2663;
+ t.a111 = 0x2666;
+ t.a110 = 0x2665;
+ t.a109 = 0x2660;
+ t.a120 = 0x2460;
+ t.a121 = 0x2461;
+ t.a122 = 0x2462;
+ t.a123 = 0x2463;
+ t.a124 = 0x2464;
+ t.a125 = 0x2465;
+ t.a126 = 0x2466;
+ t.a127 = 0x2467;
+ t.a128 = 0x2468;
+ t.a129 = 0x2469;
+ t.a130 = 0x2776;
+ t.a131 = 0x2777;
+ t.a132 = 0x2778;
+ t.a133 = 0x2779;
+ t.a134 = 0x277a;
+ t.a135 = 0x277b;
+ t.a136 = 0x277c;
+ t.a137 = 0x277d;
+ t.a138 = 0x277e;
+ t.a139 = 0x277f;
+ t.a140 = 0x2780;
+ t.a141 = 0x2781;
+ t.a142 = 0x2782;
+ t.a143 = 0x2783;
+ t.a144 = 0x2784;
+ t.a145 = 0x2785;
+ t.a146 = 0x2786;
+ t.a147 = 0x2787;
+ t.a148 = 0x2788;
+ t.a149 = 0x2789;
+ t.a150 = 0x278a;
+ t.a151 = 0x278b;
+ t.a152 = 0x278c;
+ t.a153 = 0x278d;
+ t.a154 = 0x278e;
+ t.a155 = 0x278f;
+ t.a156 = 0x2790;
+ t.a157 = 0x2791;
+ t.a158 = 0x2792;
+ t.a159 = 0x2793;
+ t.a160 = 0x2794;
+ t.a161 = 0x2192;
+ t.a163 = 0x2194;
+ t.a164 = 0x2195;
+ t.a196 = 0x2798;
+ t.a165 = 0x2799;
+ t.a192 = 0x279a;
+ t.a166 = 0x279b;
+ t.a167 = 0x279c;
+ t.a168 = 0x279d;
+ t.a169 = 0x279e;
+ t.a170 = 0x279f;
+ t.a171 = 0x27a0;
+ t.a172 = 0x27a1;
+ t.a173 = 0x27a2;
+ t.a162 = 0x27a3;
+ t.a174 = 0x27a4;
+ t.a175 = 0x27a5;
+ t.a176 = 0x27a6;
+ t.a177 = 0x27a7;
+ t.a178 = 0x27a8;
+ t.a179 = 0x27a9;
+ t.a193 = 0x27aa;
+ t.a180 = 0x27ab;
+ t.a199 = 0x27ac;
+ t.a181 = 0x27ad;
+ t.a200 = 0x27ae;
+ t.a182 = 0x27af;
+ t.a201 = 0x27b1;
+ t.a183 = 0x27b2;
+ t.a184 = 0x27b3;
+ t.a197 = 0x27b4;
+ t.a185 = 0x27b5;
+ t.a194 = 0x27b6;
+ t.a198 = 0x27b7;
+ t.a186 = 0x27b8;
+ t.a195 = 0x27b9;
+ t.a187 = 0x27ba;
+ t.a188 = 0x27bb;
+ t.a189 = 0x27bc;
+ t.a190 = 0x27bd;
+ t.a191 = 0x27be;
+ t.a89 = 0x2768;
+ t.a90 = 0x2769;
+ t.a93 = 0x276a;
+ t.a94 = 0x276b;
+ t.a91 = 0x276c;
+ t.a92 = 0x276d;
+ t.a205 = 0x276e;
+ t.a85 = 0x276f;
+ t.a206 = 0x2770;
+ t.a86 = 0x2771;
+ t.a87 = 0x2772;
+ t.a88 = 0x2773;
+ t.a95 = 0x2774;
+ t.a96 = 0x2775;
+ t[".notdef"] = 0x0000;
+});
+
+;// CONCATENATED MODULE: ./src/core/unicode.js
+
+const getSpecialPUASymbols = getLookupTableFactory(function (t) {
+ t[63721] = 0x00a9;
+ t[63193] = 0x00a9;
+ t[63720] = 0x00ae;
+ t[63194] = 0x00ae;
+ t[63722] = 0x2122;
+ t[63195] = 0x2122;
+ t[63729] = 0x23a7;
+ t[63730] = 0x23a8;
+ t[63731] = 0x23a9;
+ t[63740] = 0x23ab;
+ t[63741] = 0x23ac;
+ t[63742] = 0x23ad;
+ t[63726] = 0x23a1;
+ t[63727] = 0x23a2;
+ t[63728] = 0x23a3;
+ t[63737] = 0x23a4;
+ t[63738] = 0x23a5;
+ t[63739] = 0x23a6;
+ t[63723] = 0x239b;
+ t[63724] = 0x239c;
+ t[63725] = 0x239d;
+ t[63734] = 0x239e;
+ t[63735] = 0x239f;
+ t[63736] = 0x23a0;
+});
+function mapSpecialUnicodeValues(code) {
+ if (code >= 0xfff0 && code <= 0xffff) {
+ return 0;
+ } else if (code >= 0xf600 && code <= 0xf8ff) {
+ return getSpecialPUASymbols()[code] || code;
+ } else if (code === 0x00ad) {
+ return 0x002d;
+ }
+ return code;
+}
+function getUnicodeForGlyph(name, glyphsUnicodeMap) {
+ let unicode = glyphsUnicodeMap[name];
+ if (unicode !== undefined) {
+ return unicode;
+ }
+ if (!name) {
+ return -1;
+ }
+ if (name[0] === "u") {
+ const nameLen = name.length;
+ let hexStr;
+ if (nameLen === 7 && name[1] === "n" && name[2] === "i") {
+ hexStr = name.substring(3);
+ } else if (nameLen >= 5 && nameLen <= 7) {
+ hexStr = name.substring(1);
+ } else {
+ return -1;
+ }
+ if (hexStr === hexStr.toUpperCase()) {
+ unicode = parseInt(hexStr, 16);
+ if (unicode >= 0) {
+ return unicode;
+ }
+ }
+ }
+ return -1;
+}
+const UnicodeRanges = [[0x0000, 0x007f], [0x0080, 0x00ff], [0x0100, 0x017f], [0x0180, 0x024f], [0x0250, 0x02af, 0x1d00, 0x1d7f, 0x1d80, 0x1dbf], [0x02b0, 0x02ff, 0xa700, 0xa71f], [0x0300, 0x036f, 0x1dc0, 0x1dff], [0x0370, 0x03ff], [0x2c80, 0x2cff], [0x0400, 0x04ff, 0x0500, 0x052f, 0x2de0, 0x2dff, 0xa640, 0xa69f], [0x0530, 0x058f], [0x0590, 0x05ff], [0xa500, 0xa63f], [0x0600, 0x06ff, 0x0750, 0x077f], [0x07c0, 0x07ff], [0x0900, 0x097f], [0x0980, 0x09ff], [0x0a00, 0x0a7f], [0x0a80, 0x0aff], [0x0b00, 0x0b7f], [0x0b80, 0x0bff], [0x0c00, 0x0c7f], [0x0c80, 0x0cff], [0x0d00, 0x0d7f], [0x0e00, 0x0e7f], [0x0e80, 0x0eff], [0x10a0, 0x10ff, 0x2d00, 0x2d2f], [0x1b00, 0x1b7f], [0x1100, 0x11ff], [0x1e00, 0x1eff, 0x2c60, 0x2c7f, 0xa720, 0xa7ff], [0x1f00, 0x1fff], [0x2000, 0x206f, 0x2e00, 0x2e7f], [0x2070, 0x209f], [0x20a0, 0x20cf], [0x20d0, 0x20ff], [0x2100, 0x214f], [0x2150, 0x218f], [0x2190, 0x21ff, 0x27f0, 0x27ff, 0x2900, 0x297f, 0x2b00, 0x2bff], [0x2200, 0x22ff, 0x2a00, 0x2aff, 0x27c0, 0x27ef, 0x2980, 0x29ff], [0x2300, 0x23ff], [0x2400, 0x243f], [0x2440, 0x245f], [0x2460, 0x24ff], [0x2500, 0x257f], [0x2580, 0x259f], [0x25a0, 0x25ff], [0x2600, 0x26ff], [0x2700, 0x27bf], [0x3000, 0x303f], [0x3040, 0x309f], [0x30a0, 0x30ff, 0x31f0, 0x31ff], [0x3100, 0x312f, 0x31a0, 0x31bf], [0x3130, 0x318f], [0xa840, 0xa87f], [0x3200, 0x32ff], [0x3300, 0x33ff], [0xac00, 0xd7af], [0xd800, 0xdfff], [0x10900, 0x1091f], [0x4e00, 0x9fff, 0x2e80, 0x2eff, 0x2f00, 0x2fdf, 0x2ff0, 0x2fff, 0x3400, 0x4dbf, 0x20000, 0x2a6df, 0x3190, 0x319f], [0xe000, 0xf8ff], [0x31c0, 0x31ef, 0xf900, 0xfaff, 0x2f800, 0x2fa1f], [0xfb00, 0xfb4f], [0xfb50, 0xfdff], [0xfe20, 0xfe2f], [0xfe10, 0xfe1f], [0xfe50, 0xfe6f], [0xfe70, 0xfeff], [0xff00, 0xffef], [0xfff0, 0xffff], [0x0f00, 0x0fff], [0x0700, 0x074f], [0x0780, 0x07bf], [0x0d80, 0x0dff], [0x1000, 0x109f], [0x1200, 0x137f, 0x1380, 0x139f, 0x2d80, 0x2ddf], [0x13a0, 0x13ff], [0x1400, 0x167f], [0x1680, 0x169f], [0x16a0, 0x16ff], [0x1780, 0x17ff], [0x1800, 0x18af], [0x2800, 0x28ff], [0xa000, 0xa48f], [0x1700, 0x171f, 0x1720, 0x173f, 0x1740, 0x175f, 0x1760, 0x177f], [0x10300, 0x1032f], [0x10330, 0x1034f], [0x10400, 0x1044f], [0x1d000, 0x1d0ff, 0x1d100, 0x1d1ff, 0x1d200, 0x1d24f], [0x1d400, 0x1d7ff], [0xff000, 0xffffd], [0xfe00, 0xfe0f, 0xe0100, 0xe01ef], [0xe0000, 0xe007f], [0x1900, 0x194f], [0x1950, 0x197f], [0x1980, 0x19df], [0x1a00, 0x1a1f], [0x2c00, 0x2c5f], [0x2d30, 0x2d7f], [0x4dc0, 0x4dff], [0xa800, 0xa82f], [0x10000, 0x1007f, 0x10080, 0x100ff, 0x10100, 0x1013f], [0x10140, 0x1018f], [0x10380, 0x1039f], [0x103a0, 0x103df], [0x10450, 0x1047f], [0x10480, 0x104af], [0x10800, 0x1083f], [0x10a00, 0x10a5f], [0x1d300, 0x1d35f], [0x12000, 0x123ff, 0x12400, 0x1247f], [0x1d360, 0x1d37f], [0x1b80, 0x1bbf], [0x1c00, 0x1c4f], [0x1c50, 0x1c7f], [0xa880, 0xa8df], [0xa900, 0xa92f], [0xa930, 0xa95f], [0xaa00, 0xaa5f], [0x10190, 0x101cf], [0x101d0, 0x101ff], [0x102a0, 0x102df, 0x10280, 0x1029f, 0x10920, 0x1093f], [0x1f030, 0x1f09f, 0x1f000, 0x1f02f]];
+function getUnicodeRangeFor(value, lastPosition = -1) {
+ if (lastPosition !== -1) {
+ const range = UnicodeRanges[lastPosition];
+ for (let i = 0, ii = range.length; i < ii; i += 2) {
+ if (value >= range[i] && value <= range[i + 1]) {
+ return lastPosition;
+ }
+ }
+ }
+ for (let i = 0, ii = UnicodeRanges.length; i < ii; i++) {
+ const range = UnicodeRanges[i];
+ for (let j = 0, jj = range.length; j < jj; j += 2) {
+ if (value >= range[j] && value <= range[j + 1]) {
+ return i;
+ }
+ }
+ }
+ return -1;
+}
+const SpecialCharRegExp = new RegExp("^(\\s)|(\\p{Mn})|(\\p{Cf})$", "u");
+const CategoryCache = new Map();
+function getCharUnicodeCategory(char) {
+ const cachedCategory = CategoryCache.get(char);
+ if (cachedCategory) {
+ return cachedCategory;
+ }
+ const groups = char.match(SpecialCharRegExp);
+ const category = {
+ isWhitespace: !!groups?.[1],
+ isZeroWidthDiacritic: !!groups?.[2],
+ isInvisibleFormatMark: !!groups?.[3]
+ };
+ CategoryCache.set(char, category);
+ return category;
+}
+function clearUnicodeCaches() {
+ CategoryCache.clear();
+}
+
+;// CONCATENATED MODULE: ./src/core/fonts_utils.js
+
+
+
+
+const SEAC_ANALYSIS_ENABLED = true;
+const FontFlags = {
+ FixedPitch: 1,
+ Serif: 2,
+ Symbolic: 4,
+ Script: 8,
+ Nonsymbolic: 32,
+ Italic: 64,
+ AllCap: 65536,
+ SmallCap: 131072,
+ ForceBold: 262144
+};
+const MacStandardGlyphOrdering = [".notdef", ".null", "nonmarkingreturn", "space", "exclam", "quotedbl", "numbersign", "dollar", "percent", "ampersand", "quotesingle", "parenleft", "parenright", "asterisk", "plus", "comma", "hyphen", "period", "slash", "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "colon", "semicolon", "less", "equal", "greater", "question", "at", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "bracketleft", "backslash", "bracketright", "asciicircum", "underscore", "grave", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "braceleft", "bar", "braceright", "asciitilde", "Adieresis", "Aring", "Ccedilla", "Eacute", "Ntilde", "Odieresis", "Udieresis", "aacute", "agrave", "acircumflex", "adieresis", "atilde", "aring", "ccedilla", "eacute", "egrave", "ecircumflex", "edieresis", "iacute", "igrave", "icircumflex", "idieresis", "ntilde", "oacute", "ograve", "ocircumflex", "odieresis", "otilde", "uacute", "ugrave", "ucircumflex", "udieresis", "dagger", "degree", "cent", "sterling", "section", "bullet", "paragraph", "germandbls", "registered", "copyright", "trademark", "acute", "dieresis", "notequal", "AE", "Oslash", "infinity", "plusminus", "lessequal", "greaterequal", "yen", "mu", "partialdiff", "summation", "product", "pi", "integral", "ordfeminine", "ordmasculine", "Omega", "ae", "oslash", "questiondown", "exclamdown", "logicalnot", "radical", "florin", "approxequal", "Delta", "guillemotleft", "guillemotright", "ellipsis", "nonbreakingspace", "Agrave", "Atilde", "Otilde", "OE", "oe", "endash", "emdash", "quotedblleft", "quotedblright", "quoteleft", "quoteright", "divide", "lozenge", "ydieresis", "Ydieresis", "fraction", "currency", "guilsinglleft", "guilsinglright", "fi", "fl", "daggerdbl", "periodcentered", "quotesinglbase", "quotedblbase", "perthousand", "Acircumflex", "Ecircumflex", "Aacute", "Edieresis", "Egrave", "Iacute", "Icircumflex", "Idieresis", "Igrave", "Oacute", "Ocircumflex", "apple", "Ograve", "Uacute", "Ucircumflex", "Ugrave", "dotlessi", "circumflex", "tilde", "macron", "breve", "dotaccent", "ring", "cedilla", "hungarumlaut", "ogonek", "caron", "Lslash", "lslash", "Scaron", "scaron", "Zcaron", "zcaron", "brokenbar", "Eth", "eth", "Yacute", "yacute", "Thorn", "thorn", "minus", "multiply", "onesuperior", "twosuperior", "threesuperior", "onehalf", "onequarter", "threequarters", "franc", "Gbreve", "gbreve", "Idotaccent", "Scedilla", "scedilla", "Cacute", "cacute", "Ccaron", "ccaron", "dcroat"];
+function recoverGlyphName(name, glyphsUnicodeMap) {
+ if (glyphsUnicodeMap[name] !== undefined) {
+ return name;
+ }
+ const unicode = getUnicodeForGlyph(name, glyphsUnicodeMap);
+ if (unicode !== -1) {
+ for (const key in glyphsUnicodeMap) {
+ if (glyphsUnicodeMap[key] === unicode) {
+ return key;
+ }
+ }
+ }
+ info("Unable to recover a standard glyph name for: " + name);
+ return name;
+}
+function type1FontGlyphMapping(properties, builtInEncoding, glyphNames) {
+ const charCodeToGlyphId = Object.create(null);
+ let glyphId, charCode, baseEncoding;
+ const isSymbolicFont = !!(properties.flags & FontFlags.Symbolic);
+ if (properties.isInternalFont) {
+ baseEncoding = builtInEncoding;
+ for (charCode = 0; charCode < baseEncoding.length; charCode++) {
+ glyphId = glyphNames.indexOf(baseEncoding[charCode]);
+ charCodeToGlyphId[charCode] = glyphId >= 0 ? glyphId : 0;
+ }
+ } else if (properties.baseEncodingName) {
+ baseEncoding = getEncoding(properties.baseEncodingName);
+ for (charCode = 0; charCode < baseEncoding.length; charCode++) {
+ glyphId = glyphNames.indexOf(baseEncoding[charCode]);
+ charCodeToGlyphId[charCode] = glyphId >= 0 ? glyphId : 0;
+ }
+ } else if (isSymbolicFont) {
+ for (charCode in builtInEncoding) {
+ charCodeToGlyphId[charCode] = builtInEncoding[charCode];
+ }
+ } else {
+ baseEncoding = StandardEncoding;
+ for (charCode = 0; charCode < baseEncoding.length; charCode++) {
+ glyphId = glyphNames.indexOf(baseEncoding[charCode]);
+ charCodeToGlyphId[charCode] = glyphId >= 0 ? glyphId : 0;
+ }
+ }
+ const differences = properties.differences;
+ let glyphsUnicodeMap;
+ if (differences) {
+ for (charCode in differences) {
+ const glyphName = differences[charCode];
+ glyphId = glyphNames.indexOf(glyphName);
+ if (glyphId === -1) {
+ if (!glyphsUnicodeMap) {
+ glyphsUnicodeMap = getGlyphsUnicode();
+ }
+ const standardGlyphName = recoverGlyphName(glyphName, glyphsUnicodeMap);
+ if (standardGlyphName !== glyphName) {
+ glyphId = glyphNames.indexOf(standardGlyphName);
+ }
+ }
+ charCodeToGlyphId[charCode] = glyphId >= 0 ? glyphId : 0;
+ }
+ }
+ return charCodeToGlyphId;
+}
+function normalizeFontName(name) {
+ return name.replaceAll(/[,_]/g, "-").replaceAll(/\s/g, "");
+}
+
+;// CONCATENATED MODULE: ./src/core/standard_fonts.js
+
+
+const getStdFontMap = getLookupTableFactory(function (t) {
+ t["Times-Roman"] = "Times-Roman";
+ t.Helvetica = "Helvetica";
+ t.Courier = "Courier";
+ t.Symbol = "Symbol";
+ t["Times-Bold"] = "Times-Bold";
+ t["Helvetica-Bold"] = "Helvetica-Bold";
+ t["Courier-Bold"] = "Courier-Bold";
+ t.ZapfDingbats = "ZapfDingbats";
+ t["Times-Italic"] = "Times-Italic";
+ t["Helvetica-Oblique"] = "Helvetica-Oblique";
+ t["Courier-Oblique"] = "Courier-Oblique";
+ t["Times-BoldItalic"] = "Times-BoldItalic";
+ t["Helvetica-BoldOblique"] = "Helvetica-BoldOblique";
+ t["Courier-BoldOblique"] = "Courier-BoldOblique";
+ t.ArialNarrow = "Helvetica";
+ t["ArialNarrow-Bold"] = "Helvetica-Bold";
+ t["ArialNarrow-BoldItalic"] = "Helvetica-BoldOblique";
+ t["ArialNarrow-Italic"] = "Helvetica-Oblique";
+ t.ArialBlack = "Helvetica";
+ t["ArialBlack-Bold"] = "Helvetica-Bold";
+ t["ArialBlack-BoldItalic"] = "Helvetica-BoldOblique";
+ t["ArialBlack-Italic"] = "Helvetica-Oblique";
+ t["Arial-Black"] = "Helvetica";
+ t["Arial-Black-Bold"] = "Helvetica-Bold";
+ t["Arial-Black-BoldItalic"] = "Helvetica-BoldOblique";
+ t["Arial-Black-Italic"] = "Helvetica-Oblique";
+ t.Arial = "Helvetica";
+ t["Arial-Bold"] = "Helvetica-Bold";
+ t["Arial-BoldItalic"] = "Helvetica-BoldOblique";
+ t["Arial-Italic"] = "Helvetica-Oblique";
+ t.ArialMT = "Helvetica";
+ t["Arial-BoldItalicMT"] = "Helvetica-BoldOblique";
+ t["Arial-BoldMT"] = "Helvetica-Bold";
+ t["Arial-ItalicMT"] = "Helvetica-Oblique";
+ t["Arial-BoldItalicMT-BoldItalic"] = "Helvetica-BoldOblique";
+ t["Arial-BoldMT-Bold"] = "Helvetica-Bold";
+ t["Arial-ItalicMT-Italic"] = "Helvetica-Oblique";
+ t.ArialUnicodeMS = "Helvetica";
+ t["ArialUnicodeMS-Bold"] = "Helvetica-Bold";
+ t["ArialUnicodeMS-BoldItalic"] = "Helvetica-BoldOblique";
+ t["ArialUnicodeMS-Italic"] = "Helvetica-Oblique";
+ t["Courier-BoldItalic"] = "Courier-BoldOblique";
+ t["Courier-Italic"] = "Courier-Oblique";
+ t.CourierNew = "Courier";
+ t["CourierNew-Bold"] = "Courier-Bold";
+ t["CourierNew-BoldItalic"] = "Courier-BoldOblique";
+ t["CourierNew-Italic"] = "Courier-Oblique";
+ t["CourierNewPS-BoldItalicMT"] = "Courier-BoldOblique";
+ t["CourierNewPS-BoldMT"] = "Courier-Bold";
+ t["CourierNewPS-ItalicMT"] = "Courier-Oblique";
+ t.CourierNewPSMT = "Courier";
+ t["Helvetica-BoldItalic"] = "Helvetica-BoldOblique";
+ t["Helvetica-Italic"] = "Helvetica-Oblique";
+ t["Symbol-Bold"] = "Symbol";
+ t["Symbol-BoldItalic"] = "Symbol";
+ t["Symbol-Italic"] = "Symbol";
+ t.TimesNewRoman = "Times-Roman";
+ t["TimesNewRoman-Bold"] = "Times-Bold";
+ t["TimesNewRoman-BoldItalic"] = "Times-BoldItalic";
+ t["TimesNewRoman-Italic"] = "Times-Italic";
+ t.TimesNewRomanPS = "Times-Roman";
+ t["TimesNewRomanPS-Bold"] = "Times-Bold";
+ t["TimesNewRomanPS-BoldItalic"] = "Times-BoldItalic";
+ t["TimesNewRomanPS-BoldItalicMT"] = "Times-BoldItalic";
+ t["TimesNewRomanPS-BoldMT"] = "Times-Bold";
+ t["TimesNewRomanPS-Italic"] = "Times-Italic";
+ t["TimesNewRomanPS-ItalicMT"] = "Times-Italic";
+ t.TimesNewRomanPSMT = "Times-Roman";
+ t["TimesNewRomanPSMT-Bold"] = "Times-Bold";
+ t["TimesNewRomanPSMT-BoldItalic"] = "Times-BoldItalic";
+ t["TimesNewRomanPSMT-Italic"] = "Times-Italic";
+});
+const getFontNameToFileMap = getLookupTableFactory(function (t) {
+ t.Courier = "FoxitFixed.pfb";
+ t["Courier-Bold"] = "FoxitFixedBold.pfb";
+ t["Courier-BoldOblique"] = "FoxitFixedBoldItalic.pfb";
+ t["Courier-Oblique"] = "FoxitFixedItalic.pfb";
+ t.Helvetica = "LiberationSans-Regular.ttf";
+ t["Helvetica-Bold"] = "LiberationSans-Bold.ttf";
+ t["Helvetica-BoldOblique"] = "LiberationSans-BoldItalic.ttf";
+ t["Helvetica-Oblique"] = "LiberationSans-Italic.ttf";
+ t["Times-Roman"] = "FoxitSerif.pfb";
+ t["Times-Bold"] = "FoxitSerifBold.pfb";
+ t["Times-BoldItalic"] = "FoxitSerifBoldItalic.pfb";
+ t["Times-Italic"] = "FoxitSerifItalic.pfb";
+ t.Symbol = "FoxitSymbol.pfb";
+ t.ZapfDingbats = "FoxitDingbats.pfb";
+ t["LiberationSans-Regular"] = "LiberationSans-Regular.ttf";
+ t["LiberationSans-Bold"] = "LiberationSans-Bold.ttf";
+ t["LiberationSans-Italic"] = "LiberationSans-Italic.ttf";
+ t["LiberationSans-BoldItalic"] = "LiberationSans-BoldItalic.ttf";
+});
+const getNonStdFontMap = getLookupTableFactory(function (t) {
+ t.Calibri = "Helvetica";
+ t["Calibri-Bold"] = "Helvetica-Bold";
+ t["Calibri-BoldItalic"] = "Helvetica-BoldOblique";
+ t["Calibri-Italic"] = "Helvetica-Oblique";
+ t.CenturyGothic = "Helvetica";
+ t["CenturyGothic-Bold"] = "Helvetica-Bold";
+ t["CenturyGothic-BoldItalic"] = "Helvetica-BoldOblique";
+ t["CenturyGothic-Italic"] = "Helvetica-Oblique";
+ t.ComicSansMS = "Comic Sans MS";
+ t["ComicSansMS-Bold"] = "Comic Sans MS-Bold";
+ t["ComicSansMS-BoldItalic"] = "Comic Sans MS-BoldItalic";
+ t["ComicSansMS-Italic"] = "Comic Sans MS-Italic";
+ t.Impact = "Helvetica";
+ t["ItcSymbol-Bold"] = "Helvetica-Bold";
+ t["ItcSymbol-BoldItalic"] = "Helvetica-BoldOblique";
+ t["ItcSymbol-Book"] = "Helvetica";
+ t["ItcSymbol-BookItalic"] = "Helvetica-Oblique";
+ t["ItcSymbol-Medium"] = "Helvetica";
+ t["ItcSymbol-MediumItalic"] = "Helvetica-Oblique";
+ t.LucidaConsole = "Courier";
+ t["LucidaConsole-Bold"] = "Courier-Bold";
+ t["LucidaConsole-BoldItalic"] = "Courier-BoldOblique";
+ t["LucidaConsole-Italic"] = "Courier-Oblique";
+ t["LucidaSans-Demi"] = "Helvetica-Bold";
+ t["MS-Gothic"] = "MS Gothic";
+ t["MS-Gothic-Bold"] = "MS Gothic-Bold";
+ t["MS-Gothic-BoldItalic"] = "MS Gothic-BoldItalic";
+ t["MS-Gothic-Italic"] = "MS Gothic-Italic";
+ t["MS-Mincho"] = "MS Mincho";
+ t["MS-Mincho-Bold"] = "MS Mincho-Bold";
+ t["MS-Mincho-BoldItalic"] = "MS Mincho-BoldItalic";
+ t["MS-Mincho-Italic"] = "MS Mincho-Italic";
+ t["MS-PGothic"] = "MS PGothic";
+ t["MS-PGothic-Bold"] = "MS PGothic-Bold";
+ t["MS-PGothic-BoldItalic"] = "MS PGothic-BoldItalic";
+ t["MS-PGothic-Italic"] = "MS PGothic-Italic";
+ t["MS-PMincho"] = "MS PMincho";
+ t["MS-PMincho-Bold"] = "MS PMincho-Bold";
+ t["MS-PMincho-BoldItalic"] = "MS PMincho-BoldItalic";
+ t["MS-PMincho-Italic"] = "MS PMincho-Italic";
+ t.NuptialScript = "Times-Italic";
+ t.SegoeUISymbol = "Helvetica";
+});
+const getSerifFonts = getLookupTableFactory(function (t) {
+ t["Adobe Jenson"] = true;
+ t["Adobe Text"] = true;
+ t.Albertus = true;
+ t.Aldus = true;
+ t.Alexandria = true;
+ t.Algerian = true;
+ t["American Typewriter"] = true;
+ t.Antiqua = true;
+ t.Apex = true;
+ t.Arno = true;
+ t.Aster = true;
+ t.Aurora = true;
+ t.Baskerville = true;
+ t.Bell = true;
+ t.Bembo = true;
+ t["Bembo Schoolbook"] = true;
+ t.Benguiat = true;
+ t["Berkeley Old Style"] = true;
+ t["Bernhard Modern"] = true;
+ t["Berthold City"] = true;
+ t.Bodoni = true;
+ t["Bauer Bodoni"] = true;
+ t["Book Antiqua"] = true;
+ t.Bookman = true;
+ t["Bordeaux Roman"] = true;
+ t["Californian FB"] = true;
+ t.Calisto = true;
+ t.Calvert = true;
+ t.Capitals = true;
+ t.Cambria = true;
+ t.Cartier = true;
+ t.Caslon = true;
+ t.Catull = true;
+ t.Centaur = true;
+ t["Century Old Style"] = true;
+ t["Century Schoolbook"] = true;
+ t.Chaparral = true;
+ t["Charis SIL"] = true;
+ t.Cheltenham = true;
+ t["Cholla Slab"] = true;
+ t.Clarendon = true;
+ t.Clearface = true;
+ t.Cochin = true;
+ t.Colonna = true;
+ t["Computer Modern"] = true;
+ t["Concrete Roman"] = true;
+ t.Constantia = true;
+ t["Cooper Black"] = true;
+ t.Corona = true;
+ t.Ecotype = true;
+ t.Egyptienne = true;
+ t.Elephant = true;
+ t.Excelsior = true;
+ t.Fairfield = true;
+ t["FF Scala"] = true;
+ t.Folkard = true;
+ t.Footlight = true;
+ t.FreeSerif = true;
+ t["Friz Quadrata"] = true;
+ t.Garamond = true;
+ t.Gentium = true;
+ t.Georgia = true;
+ t.Gloucester = true;
+ t["Goudy Old Style"] = true;
+ t["Goudy Schoolbook"] = true;
+ t["Goudy Pro Font"] = true;
+ t.Granjon = true;
+ t["Guardian Egyptian"] = true;
+ t.Heather = true;
+ t.Hercules = true;
+ t["High Tower Text"] = true;
+ t.Hiroshige = true;
+ t["Hoefler Text"] = true;
+ t["Humana Serif"] = true;
+ t.Imprint = true;
+ t["Ionic No. 5"] = true;
+ t.Janson = true;
+ t.Joanna = true;
+ t.Korinna = true;
+ t.Lexicon = true;
+ t.LiberationSerif = true;
+ t["Liberation Serif"] = true;
+ t["Linux Libertine"] = true;
+ t.Literaturnaya = true;
+ t.Lucida = true;
+ t["Lucida Bright"] = true;
+ t.Melior = true;
+ t.Memphis = true;
+ t.Miller = true;
+ t.Minion = true;
+ t.Modern = true;
+ t["Mona Lisa"] = true;
+ t["Mrs Eaves"] = true;
+ t["MS Serif"] = true;
+ t["Museo Slab"] = true;
+ t["New York"] = true;
+ t["Nimbus Roman"] = true;
+ t["NPS Rawlinson Roadway"] = true;
+ t.NuptialScript = true;
+ t.Palatino = true;
+ t.Perpetua = true;
+ t.Plantin = true;
+ t["Plantin Schoolbook"] = true;
+ t.Playbill = true;
+ t["Poor Richard"] = true;
+ t["Rawlinson Roadway"] = true;
+ t.Renault = true;
+ t.Requiem = true;
+ t.Rockwell = true;
+ t.Roman = true;
+ t["Rotis Serif"] = true;
+ t.Sabon = true;
+ t.Scala = true;
+ t.Seagull = true;
+ t.Sistina = true;
+ t.Souvenir = true;
+ t.STIX = true;
+ t["Stone Informal"] = true;
+ t["Stone Serif"] = true;
+ t.Sylfaen = true;
+ t.Times = true;
+ t.Trajan = true;
+ t["Trinité"] = true;
+ t["Trump Mediaeval"] = true;
+ t.Utopia = true;
+ t["Vale Type"] = true;
+ t["Bitstream Vera"] = true;
+ t["Vera Serif"] = true;
+ t.Versailles = true;
+ t.Wanted = true;
+ t.Weiss = true;
+ t["Wide Latin"] = true;
+ t.Windsor = true;
+ t.XITS = true;
+});
+const getSymbolsFonts = getLookupTableFactory(function (t) {
+ t.Dingbats = true;
+ t.Symbol = true;
+ t.ZapfDingbats = true;
+ t.Wingdings = true;
+ t["Wingdings-Bold"] = true;
+ t["Wingdings-Regular"] = true;
+});
+const getGlyphMapForStandardFonts = getLookupTableFactory(function (t) {
+ t[2] = 10;
+ t[3] = 32;
+ t[4] = 33;
+ t[5] = 34;
+ t[6] = 35;
+ t[7] = 36;
+ t[8] = 37;
+ t[9] = 38;
+ t[10] = 39;
+ t[11] = 40;
+ t[12] = 41;
+ t[13] = 42;
+ t[14] = 43;
+ t[15] = 44;
+ t[16] = 45;
+ t[17] = 46;
+ t[18] = 47;
+ t[19] = 48;
+ t[20] = 49;
+ t[21] = 50;
+ t[22] = 51;
+ t[23] = 52;
+ t[24] = 53;
+ t[25] = 54;
+ t[26] = 55;
+ t[27] = 56;
+ t[28] = 57;
+ t[29] = 58;
+ t[30] = 894;
+ t[31] = 60;
+ t[32] = 61;
+ t[33] = 62;
+ t[34] = 63;
+ t[35] = 64;
+ t[36] = 65;
+ t[37] = 66;
+ t[38] = 67;
+ t[39] = 68;
+ t[40] = 69;
+ t[41] = 70;
+ t[42] = 71;
+ t[43] = 72;
+ t[44] = 73;
+ t[45] = 74;
+ t[46] = 75;
+ t[47] = 76;
+ t[48] = 77;
+ t[49] = 78;
+ t[50] = 79;
+ t[51] = 80;
+ t[52] = 81;
+ t[53] = 82;
+ t[54] = 83;
+ t[55] = 84;
+ t[56] = 85;
+ t[57] = 86;
+ t[58] = 87;
+ t[59] = 88;
+ t[60] = 89;
+ t[61] = 90;
+ t[62] = 91;
+ t[63] = 92;
+ t[64] = 93;
+ t[65] = 94;
+ t[66] = 95;
+ t[67] = 96;
+ t[68] = 97;
+ t[69] = 98;
+ t[70] = 99;
+ t[71] = 100;
+ t[72] = 101;
+ t[73] = 102;
+ t[74] = 103;
+ t[75] = 104;
+ t[76] = 105;
+ t[77] = 106;
+ t[78] = 107;
+ t[79] = 108;
+ t[80] = 109;
+ t[81] = 110;
+ t[82] = 111;
+ t[83] = 112;
+ t[84] = 113;
+ t[85] = 114;
+ t[86] = 115;
+ t[87] = 116;
+ t[88] = 117;
+ t[89] = 118;
+ t[90] = 119;
+ t[91] = 120;
+ t[92] = 121;
+ t[93] = 122;
+ t[94] = 123;
+ t[95] = 124;
+ t[96] = 125;
+ t[97] = 126;
+ t[98] = 196;
+ t[99] = 197;
+ t[100] = 199;
+ t[101] = 201;
+ t[102] = 209;
+ t[103] = 214;
+ t[104] = 220;
+ t[105] = 225;
+ t[106] = 224;
+ t[107] = 226;
+ t[108] = 228;
+ t[109] = 227;
+ t[110] = 229;
+ t[111] = 231;
+ t[112] = 233;
+ t[113] = 232;
+ t[114] = 234;
+ t[115] = 235;
+ t[116] = 237;
+ t[117] = 236;
+ t[118] = 238;
+ t[119] = 239;
+ t[120] = 241;
+ t[121] = 243;
+ t[122] = 242;
+ t[123] = 244;
+ t[124] = 246;
+ t[125] = 245;
+ t[126] = 250;
+ t[127] = 249;
+ t[128] = 251;
+ t[129] = 252;
+ t[130] = 8224;
+ t[131] = 176;
+ t[132] = 162;
+ t[133] = 163;
+ t[134] = 167;
+ t[135] = 8226;
+ t[136] = 182;
+ t[137] = 223;
+ t[138] = 174;
+ t[139] = 169;
+ t[140] = 8482;
+ t[141] = 180;
+ t[142] = 168;
+ t[143] = 8800;
+ t[144] = 198;
+ t[145] = 216;
+ t[146] = 8734;
+ t[147] = 177;
+ t[148] = 8804;
+ t[149] = 8805;
+ t[150] = 165;
+ t[151] = 181;
+ t[152] = 8706;
+ t[153] = 8721;
+ t[154] = 8719;
+ t[156] = 8747;
+ t[157] = 170;
+ t[158] = 186;
+ t[159] = 8486;
+ t[160] = 230;
+ t[161] = 248;
+ t[162] = 191;
+ t[163] = 161;
+ t[164] = 172;
+ t[165] = 8730;
+ t[166] = 402;
+ t[167] = 8776;
+ t[168] = 8710;
+ t[169] = 171;
+ t[170] = 187;
+ t[171] = 8230;
+ t[179] = 8220;
+ t[180] = 8221;
+ t[181] = 8216;
+ t[182] = 8217;
+ t[200] = 193;
+ t[203] = 205;
+ t[207] = 211;
+ t[210] = 218;
+ t[223] = 711;
+ t[224] = 321;
+ t[225] = 322;
+ t[226] = 352;
+ t[227] = 353;
+ t[228] = 381;
+ t[229] = 382;
+ t[233] = 221;
+ t[234] = 253;
+ t[252] = 263;
+ t[253] = 268;
+ t[254] = 269;
+ t[258] = 258;
+ t[260] = 260;
+ t[261] = 261;
+ t[265] = 280;
+ t[266] = 281;
+ t[267] = 282;
+ t[268] = 283;
+ t[269] = 313;
+ t[275] = 323;
+ t[276] = 324;
+ t[278] = 328;
+ t[283] = 344;
+ t[284] = 345;
+ t[285] = 346;
+ t[286] = 347;
+ t[292] = 367;
+ t[295] = 377;
+ t[296] = 378;
+ t[298] = 380;
+ t[305] = 963;
+ t[306] = 964;
+ t[307] = 966;
+ t[308] = 8215;
+ t[309] = 8252;
+ t[310] = 8319;
+ t[311] = 8359;
+ t[312] = 8592;
+ t[313] = 8593;
+ t[337] = 9552;
+ t[493] = 1039;
+ t[494] = 1040;
+ t[672] = 1488;
+ t[673] = 1489;
+ t[674] = 1490;
+ t[675] = 1491;
+ t[676] = 1492;
+ t[677] = 1493;
+ t[678] = 1494;
+ t[679] = 1495;
+ t[680] = 1496;
+ t[681] = 1497;
+ t[682] = 1498;
+ t[683] = 1499;
+ t[684] = 1500;
+ t[685] = 1501;
+ t[686] = 1502;
+ t[687] = 1503;
+ t[688] = 1504;
+ t[689] = 1505;
+ t[690] = 1506;
+ t[691] = 1507;
+ t[692] = 1508;
+ t[693] = 1509;
+ t[694] = 1510;
+ t[695] = 1511;
+ t[696] = 1512;
+ t[697] = 1513;
+ t[698] = 1514;
+ t[705] = 1524;
+ t[706] = 8362;
+ t[710] = 64288;
+ t[711] = 64298;
+ t[759] = 1617;
+ t[761] = 1776;
+ t[763] = 1778;
+ t[775] = 1652;
+ t[777] = 1764;
+ t[778] = 1780;
+ t[779] = 1781;
+ t[780] = 1782;
+ t[782] = 771;
+ t[783] = 64726;
+ t[786] = 8363;
+ t[788] = 8532;
+ t[790] = 768;
+ t[791] = 769;
+ t[792] = 768;
+ t[795] = 803;
+ t[797] = 64336;
+ t[798] = 64337;
+ t[799] = 64342;
+ t[800] = 64343;
+ t[801] = 64344;
+ t[802] = 64345;
+ t[803] = 64362;
+ t[804] = 64363;
+ t[805] = 64364;
+ t[2424] = 7821;
+ t[2425] = 7822;
+ t[2426] = 7823;
+ t[2427] = 7824;
+ t[2428] = 7825;
+ t[2429] = 7826;
+ t[2430] = 7827;
+ t[2433] = 7682;
+ t[2678] = 8045;
+ t[2679] = 8046;
+ t[2830] = 1552;
+ t[2838] = 686;
+ t[2840] = 751;
+ t[2842] = 753;
+ t[2843] = 754;
+ t[2844] = 755;
+ t[2846] = 757;
+ t[2856] = 767;
+ t[2857] = 848;
+ t[2858] = 849;
+ t[2862] = 853;
+ t[2863] = 854;
+ t[2864] = 855;
+ t[2865] = 861;
+ t[2866] = 862;
+ t[2906] = 7460;
+ t[2908] = 7462;
+ t[2909] = 7463;
+ t[2910] = 7464;
+ t[2912] = 7466;
+ t[2913] = 7467;
+ t[2914] = 7468;
+ t[2916] = 7470;
+ t[2917] = 7471;
+ t[2918] = 7472;
+ t[2920] = 7474;
+ t[2921] = 7475;
+ t[2922] = 7476;
+ t[2924] = 7478;
+ t[2925] = 7479;
+ t[2926] = 7480;
+ t[2928] = 7482;
+ t[2929] = 7483;
+ t[2930] = 7484;
+ t[2932] = 7486;
+ t[2933] = 7487;
+ t[2934] = 7488;
+ t[2936] = 7490;
+ t[2937] = 7491;
+ t[2938] = 7492;
+ t[2940] = 7494;
+ t[2941] = 7495;
+ t[2942] = 7496;
+ t[2944] = 7498;
+ t[2946] = 7500;
+ t[2948] = 7502;
+ t[2950] = 7504;
+ t[2951] = 7505;
+ t[2952] = 7506;
+ t[2954] = 7508;
+ t[2955] = 7509;
+ t[2956] = 7510;
+ t[2958] = 7512;
+ t[2959] = 7513;
+ t[2960] = 7514;
+ t[2962] = 7516;
+ t[2963] = 7517;
+ t[2964] = 7518;
+ t[2966] = 7520;
+ t[2967] = 7521;
+ t[2968] = 7522;
+ t[2970] = 7524;
+ t[2971] = 7525;
+ t[2972] = 7526;
+ t[2974] = 7528;
+ t[2975] = 7529;
+ t[2976] = 7530;
+ t[2978] = 1537;
+ t[2979] = 1538;
+ t[2980] = 1539;
+ t[2982] = 1549;
+ t[2983] = 1551;
+ t[2984] = 1552;
+ t[2986] = 1554;
+ t[2987] = 1555;
+ t[2988] = 1556;
+ t[2990] = 1623;
+ t[2991] = 1624;
+ t[2995] = 1775;
+ t[2999] = 1791;
+ t[3002] = 64290;
+ t[3003] = 64291;
+ t[3004] = 64292;
+ t[3006] = 64294;
+ t[3007] = 64295;
+ t[3008] = 64296;
+ t[3011] = 1900;
+ t[3014] = 8223;
+ t[3015] = 8244;
+ t[3017] = 7532;
+ t[3018] = 7533;
+ t[3019] = 7534;
+ t[3075] = 7590;
+ t[3076] = 7591;
+ t[3079] = 7594;
+ t[3080] = 7595;
+ t[3083] = 7598;
+ t[3084] = 7599;
+ t[3087] = 7602;
+ t[3088] = 7603;
+ t[3091] = 7606;
+ t[3092] = 7607;
+ t[3095] = 7610;
+ t[3096] = 7611;
+ t[3099] = 7614;
+ t[3100] = 7615;
+ t[3103] = 7618;
+ t[3104] = 7619;
+ t[3107] = 8337;
+ t[3108] = 8338;
+ t[3116] = 1884;
+ t[3119] = 1885;
+ t[3120] = 1885;
+ t[3123] = 1886;
+ t[3124] = 1886;
+ t[3127] = 1887;
+ t[3128] = 1887;
+ t[3131] = 1888;
+ t[3132] = 1888;
+ t[3135] = 1889;
+ t[3136] = 1889;
+ t[3139] = 1890;
+ t[3140] = 1890;
+ t[3143] = 1891;
+ t[3144] = 1891;
+ t[3147] = 1892;
+ t[3148] = 1892;
+ t[3153] = 580;
+ t[3154] = 581;
+ t[3157] = 584;
+ t[3158] = 585;
+ t[3161] = 588;
+ t[3162] = 589;
+ t[3165] = 891;
+ t[3166] = 892;
+ t[3169] = 1274;
+ t[3170] = 1275;
+ t[3173] = 1278;
+ t[3174] = 1279;
+ t[3181] = 7622;
+ t[3182] = 7623;
+ t[3282] = 11799;
+ t[3316] = 578;
+ t[3379] = 42785;
+ t[3393] = 1159;
+ t[3416] = 8377;
+});
+const getSupplementalGlyphMapForArialBlack = getLookupTableFactory(function (t) {
+ t[227] = 322;
+ t[264] = 261;
+ t[291] = 346;
+});
+const getSupplementalGlyphMapForCalibri = getLookupTableFactory(function (t) {
+ t[1] = 32;
+ t[4] = 65;
+ t[5] = 192;
+ t[6] = 193;
+ t[9] = 196;
+ t[17] = 66;
+ t[18] = 67;
+ t[21] = 268;
+ t[24] = 68;
+ t[28] = 69;
+ t[29] = 200;
+ t[30] = 201;
+ t[32] = 282;
+ t[38] = 70;
+ t[39] = 71;
+ t[44] = 72;
+ t[47] = 73;
+ t[48] = 204;
+ t[49] = 205;
+ t[58] = 74;
+ t[60] = 75;
+ t[62] = 76;
+ t[68] = 77;
+ t[69] = 78;
+ t[75] = 79;
+ t[76] = 210;
+ t[80] = 214;
+ t[87] = 80;
+ t[89] = 81;
+ t[90] = 82;
+ t[92] = 344;
+ t[94] = 83;
+ t[97] = 352;
+ t[100] = 84;
+ t[104] = 85;
+ t[109] = 220;
+ t[115] = 86;
+ t[116] = 87;
+ t[121] = 88;
+ t[122] = 89;
+ t[124] = 221;
+ t[127] = 90;
+ t[129] = 381;
+ t[258] = 97;
+ t[259] = 224;
+ t[260] = 225;
+ t[263] = 228;
+ t[268] = 261;
+ t[271] = 98;
+ t[272] = 99;
+ t[273] = 263;
+ t[275] = 269;
+ t[282] = 100;
+ t[286] = 101;
+ t[287] = 232;
+ t[288] = 233;
+ t[290] = 283;
+ t[295] = 281;
+ t[296] = 102;
+ t[336] = 103;
+ t[346] = 104;
+ t[349] = 105;
+ t[350] = 236;
+ t[351] = 237;
+ t[361] = 106;
+ t[364] = 107;
+ t[367] = 108;
+ t[371] = 322;
+ t[373] = 109;
+ t[374] = 110;
+ t[381] = 111;
+ t[382] = 242;
+ t[383] = 243;
+ t[386] = 246;
+ t[393] = 112;
+ t[395] = 113;
+ t[396] = 114;
+ t[398] = 345;
+ t[400] = 115;
+ t[401] = 347;
+ t[403] = 353;
+ t[410] = 116;
+ t[437] = 117;
+ t[442] = 252;
+ t[448] = 118;
+ t[449] = 119;
+ t[454] = 120;
+ t[455] = 121;
+ t[457] = 253;
+ t[460] = 122;
+ t[462] = 382;
+ t[463] = 380;
+ t[853] = 44;
+ t[855] = 58;
+ t[856] = 46;
+ t[876] = 47;
+ t[878] = 45;
+ t[882] = 45;
+ t[894] = 40;
+ t[895] = 41;
+ t[896] = 91;
+ t[897] = 93;
+ t[923] = 64;
+ t[1004] = 48;
+ t[1005] = 49;
+ t[1006] = 50;
+ t[1007] = 51;
+ t[1008] = 52;
+ t[1009] = 53;
+ t[1010] = 54;
+ t[1011] = 55;
+ t[1012] = 56;
+ t[1013] = 57;
+ t[1081] = 37;
+ t[1085] = 43;
+ t[1086] = 45;
+});
+function getStandardFontName(name) {
+ const fontName = normalizeFontName(name);
+ const stdFontMap = getStdFontMap();
+ return stdFontMap[fontName];
+}
+function isKnownFontName(name) {
+ const fontName = normalizeFontName(name);
+ return !!(getStdFontMap()[fontName] || getNonStdFontMap()[fontName] || getSerifFonts()[fontName] || getSymbolsFonts()[fontName]);
+}
+
+;// CONCATENATED MODULE: ./src/core/to_unicode_map.js
+
+class ToUnicodeMap {
+ constructor(cmap = []) {
+ this._map = cmap;
+ }
+ get length() {
+ return this._map.length;
+ }
+ forEach(callback) {
+ for (const charCode in this._map) {
+ callback(charCode, this._map[charCode].charCodeAt(0));
+ }
+ }
+ has(i) {
+ return this._map[i] !== undefined;
+ }
+ get(i) {
+ return this._map[i];
+ }
+ charCodeOf(value) {
+ const map = this._map;
+ if (map.length <= 0x10000) {
+ return map.indexOf(value);
+ }
+ for (const charCode in map) {
+ if (map[charCode] === value) {
+ return charCode | 0;
+ }
+ }
+ return -1;
+ }
+ amend(map) {
+ for (const charCode in map) {
+ this._map[charCode] = map[charCode];
+ }
+ }
+}
+class IdentityToUnicodeMap {
+ constructor(firstChar, lastChar) {
+ this.firstChar = firstChar;
+ this.lastChar = lastChar;
+ }
+ get length() {
+ return this.lastChar + 1 - this.firstChar;
+ }
+ forEach(callback) {
+ for (let i = this.firstChar, ii = this.lastChar; i <= ii; i++) {
+ callback(i, i);
+ }
+ }
+ has(i) {
+ return this.firstChar <= i && i <= this.lastChar;
+ }
+ get(i) {
+ if (this.firstChar <= i && i <= this.lastChar) {
+ return String.fromCharCode(i);
+ }
+ return undefined;
+ }
+ charCodeOf(v) {
+ return Number.isInteger(v) && v >= this.firstChar && v <= this.lastChar ? v : -1;
+ }
+ amend(map) {
+ unreachable("Should not call amend()");
+ }
+}
+
+;// CONCATENATED MODULE: ./src/core/cff_font.js
+
+
+
+class CFFFont {
+ constructor(file, properties) {
+ this.properties = properties;
+ const parser = new CFFParser(file, properties, SEAC_ANALYSIS_ENABLED);
+ this.cff = parser.parse();
+ this.cff.duplicateFirstGlyph();
+ const compiler = new CFFCompiler(this.cff);
+ this.seacs = this.cff.seacs;
+ try {
+ this.data = compiler.compile();
+ } catch {
+ warn("Failed to compile font " + properties.loadedName);
+ this.data = file;
+ }
+ this._createBuiltInEncoding();
+ }
+ get numGlyphs() {
+ return this.cff.charStrings.count;
+ }
+ getCharset() {
+ return this.cff.charset.charset;
+ }
+ getGlyphMapping() {
+ const cff = this.cff;
+ const properties = this.properties;
+ const {
+ cidToGidMap,
+ cMap
+ } = properties;
+ const charsets = cff.charset.charset;
+ let charCodeToGlyphId;
+ let glyphId;
+ if (properties.composite) {
+ let invCidToGidMap;
+ if (cidToGidMap?.length > 0) {
+ invCidToGidMap = Object.create(null);
+ for (let i = 0, ii = cidToGidMap.length; i < ii; i++) {
+ const gid = cidToGidMap[i];
+ if (gid !== undefined) {
+ invCidToGidMap[gid] = i;
+ }
+ }
+ }
+ charCodeToGlyphId = Object.create(null);
+ let charCode;
+ if (cff.isCIDFont) {
+ for (glyphId = 0; glyphId < charsets.length; glyphId++) {
+ const cid = charsets[glyphId];
+ charCode = cMap.charCodeOf(cid);
+ if (invCidToGidMap?.[charCode] !== undefined) {
+ charCode = invCidToGidMap[charCode];
+ }
+ charCodeToGlyphId[charCode] = glyphId;
+ }
+ } else {
+ for (glyphId = 0; glyphId < cff.charStrings.count; glyphId++) {
+ charCode = cMap.charCodeOf(glyphId);
+ charCodeToGlyphId[charCode] = glyphId;
+ }
+ }
+ return charCodeToGlyphId;
+ }
+ let encoding = cff.encoding ? cff.encoding.encoding : null;
+ if (properties.isInternalFont) {
+ encoding = properties.defaultEncoding;
+ }
+ charCodeToGlyphId = type1FontGlyphMapping(properties, encoding, charsets);
+ return charCodeToGlyphId;
+ }
+ hasGlyphId(id) {
+ return this.cff.hasGlyphId(id);
+ }
+ _createBuiltInEncoding() {
+ const {
+ charset,
+ encoding
+ } = this.cff;
+ if (!charset || !encoding) {
+ return;
+ }
+ const charsets = charset.charset,
+ encodings = encoding.encoding;
+ const map = [];
+ for (const charCode in encodings) {
+ const glyphId = encodings[charCode];
+ if (glyphId >= 0) {
+ const glyphName = charsets[glyphId];
+ if (glyphName) {
+ map[charCode] = glyphName;
+ }
+ }
+ }
+ if (map.length > 0) {
+ this.properties.builtInEncoding = map;
+ }
+ }
+}
+
+;// CONCATENATED MODULE: ./src/core/font_renderer.js
+
+
+
+
+
+function getUint32(data, offset) {
+ return (data[offset] << 24 | data[offset + 1] << 16 | data[offset + 2] << 8 | data[offset + 3]) >>> 0;
+}
+function getUint16(data, offset) {
+ return data[offset] << 8 | data[offset + 1];
+}
+function getInt16(data, offset) {
+ return (data[offset] << 24 | data[offset + 1] << 16) >> 16;
+}
+function getInt8(data, offset) {
+ return data[offset] << 24 >> 24;
+}
+function getFloat214(data, offset) {
+ return getInt16(data, offset) / 16384;
+}
+function getSubroutineBias(subrs) {
+ const numSubrs = subrs.length;
+ let bias = 32768;
+ if (numSubrs < 1240) {
+ bias = 107;
+ } else if (numSubrs < 33900) {
+ bias = 1131;
+ }
+ return bias;
+}
+function parseCmap(data, start, end) {
+ const offset = getUint16(data, start + 2) === 1 ? getUint32(data, start + 8) : getUint32(data, start + 16);
+ const format = getUint16(data, start + offset);
+ let ranges, p, i;
+ if (format === 4) {
+ getUint16(data, start + offset + 2);
+ const segCount = getUint16(data, start + offset + 6) >> 1;
+ p = start + offset + 14;
+ ranges = [];
+ for (i = 0; i < segCount; i++, p += 2) {
+ ranges[i] = {
+ end: getUint16(data, p)
+ };
+ }
+ p += 2;
+ for (i = 0; i < segCount; i++, p += 2) {
+ ranges[i].start = getUint16(data, p);
+ }
+ for (i = 0; i < segCount; i++, p += 2) {
+ ranges[i].idDelta = getUint16(data, p);
+ }
+ for (i = 0; i < segCount; i++, p += 2) {
+ let idOffset = getUint16(data, p);
+ if (idOffset === 0) {
+ continue;
+ }
+ ranges[i].ids = [];
+ for (let j = 0, jj = ranges[i].end - ranges[i].start + 1; j < jj; j++) {
+ ranges[i].ids[j] = getUint16(data, p + idOffset);
+ idOffset += 2;
+ }
+ }
+ return ranges;
+ } else if (format === 12) {
+ const groups = getUint32(data, start + offset + 12);
+ p = start + offset + 16;
+ ranges = [];
+ for (i = 0; i < groups; i++) {
+ start = getUint32(data, p);
+ ranges.push({
+ start,
+ end: getUint32(data, p + 4),
+ idDelta: getUint32(data, p + 8) - start
+ });
+ p += 12;
+ }
+ return ranges;
+ }
+ throw new FormatError(`unsupported cmap: ${format}`);
+}
+function parseCff(data, start, end, seacAnalysisEnabled) {
+ const properties = {};
+ const parser = new CFFParser(new Stream(data, start, end - start), properties, seacAnalysisEnabled);
+ const cff = parser.parse();
+ return {
+ glyphs: cff.charStrings.objects,
+ subrs: cff.topDict.privateDict?.subrsIndex?.objects,
+ gsubrs: cff.globalSubrIndex?.objects,
+ isCFFCIDFont: cff.isCIDFont,
+ fdSelect: cff.fdSelect,
+ fdArray: cff.fdArray
+ };
+}
+function parseGlyfTable(glyf, loca, isGlyphLocationsLong) {
+ let itemSize, itemDecode;
+ if (isGlyphLocationsLong) {
+ itemSize = 4;
+ itemDecode = getUint32;
+ } else {
+ itemSize = 2;
+ itemDecode = (data, offset) => 2 * getUint16(data, offset);
+ }
+ const glyphs = [];
+ let startOffset = itemDecode(loca, 0);
+ for (let j = itemSize; j < loca.length; j += itemSize) {
+ const endOffset = itemDecode(loca, j);
+ glyphs.push(glyf.subarray(startOffset, endOffset));
+ startOffset = endOffset;
+ }
+ return glyphs;
+}
+function lookupCmap(ranges, unicode) {
+ const code = unicode.codePointAt(0);
+ let gid = 0,
+ l = 0,
+ r = ranges.length - 1;
+ while (l < r) {
+ const c = l + r + 1 >> 1;
+ if (code < ranges[c].start) {
+ r = c - 1;
+ } else {
+ l = c;
+ }
+ }
+ if (ranges[l].start <= code && code <= ranges[l].end) {
+ gid = ranges[l].idDelta + (ranges[l].ids ? ranges[l].ids[code - ranges[l].start] : code) & 0xffff;
+ }
+ return {
+ charCode: code,
+ glyphId: gid
+ };
+}
+function compileGlyf(code, cmds, font) {
+ function moveTo(x, y) {
+ cmds.push({
+ cmd: "moveTo",
+ args: [x, y]
+ });
+ }
+ function lineTo(x, y) {
+ cmds.push({
+ cmd: "lineTo",
+ args: [x, y]
+ });
+ }
+ function quadraticCurveTo(xa, ya, x, y) {
+ cmds.push({
+ cmd: "quadraticCurveTo",
+ args: [xa, ya, x, y]
+ });
+ }
+ let i = 0;
+ const numberOfContours = getInt16(code, i);
+ let flags;
+ let x = 0,
+ y = 0;
+ i += 10;
+ if (numberOfContours < 0) {
+ do {
+ flags = getUint16(code, i);
+ const glyphIndex = getUint16(code, i + 2);
+ i += 4;
+ let arg1, arg2;
+ if (flags & 0x01) {
+ if (flags & 0x02) {
+ arg1 = getInt16(code, i);
+ arg2 = getInt16(code, i + 2);
+ } else {
+ arg1 = getUint16(code, i);
+ arg2 = getUint16(code, i + 2);
+ }
+ i += 4;
+ } else if (flags & 0x02) {
+ arg1 = getInt8(code, i++);
+ arg2 = getInt8(code, i++);
+ } else {
+ arg1 = code[i++];
+ arg2 = code[i++];
+ }
+ if (flags & 0x02) {
+ x = arg1;
+ y = arg2;
+ } else {
+ x = 0;
+ y = 0;
+ }
+ let scaleX = 1,
+ scaleY = 1,
+ scale01 = 0,
+ scale10 = 0;
+ if (flags & 0x08) {
+ scaleX = scaleY = getFloat214(code, i);
+ i += 2;
+ } else if (flags & 0x40) {
+ scaleX = getFloat214(code, i);
+ scaleY = getFloat214(code, i + 2);
+ i += 4;
+ } else if (flags & 0x80) {
+ scaleX = getFloat214(code, i);
+ scale01 = getFloat214(code, i + 2);
+ scale10 = getFloat214(code, i + 4);
+ scaleY = getFloat214(code, i + 6);
+ i += 8;
+ }
+ const subglyph = font.glyphs[glyphIndex];
+ if (subglyph) {
+ cmds.push({
+ cmd: "save"
+ }, {
+ cmd: "transform",
+ args: [scaleX, scale01, scale10, scaleY, x, y]
+ });
+ if (!(flags & 0x02)) {}
+ compileGlyf(subglyph, cmds, font);
+ cmds.push({
+ cmd: "restore"
+ });
+ }
+ } while (flags & 0x20);
+ } else {
+ const endPtsOfContours = [];
+ let j, jj;
+ for (j = 0; j < numberOfContours; j++) {
+ endPtsOfContours.push(getUint16(code, i));
+ i += 2;
+ }
+ const instructionLength = getUint16(code, i);
+ i += 2 + instructionLength;
+ const numberOfPoints = endPtsOfContours.at(-1) + 1;
+ const points = [];
+ while (points.length < numberOfPoints) {
+ flags = code[i++];
+ let repeat = 1;
+ if (flags & 0x08) {
+ repeat += code[i++];
+ }
+ while (repeat-- > 0) {
+ points.push({
+ flags
+ });
+ }
+ }
+ for (j = 0; j < numberOfPoints; j++) {
+ switch (points[j].flags & 0x12) {
+ case 0x00:
+ x += getInt16(code, i);
+ i += 2;
+ break;
+ case 0x02:
+ x -= code[i++];
+ break;
+ case 0x12:
+ x += code[i++];
+ break;
+ }
+ points[j].x = x;
+ }
+ for (j = 0; j < numberOfPoints; j++) {
+ switch (points[j].flags & 0x24) {
+ case 0x00:
+ y += getInt16(code, i);
+ i += 2;
+ break;
+ case 0x04:
+ y -= code[i++];
+ break;
+ case 0x24:
+ y += code[i++];
+ break;
+ }
+ points[j].y = y;
+ }
+ let startPoint = 0;
+ for (i = 0; i < numberOfContours; i++) {
+ const endPoint = endPtsOfContours[i];
+ const contour = points.slice(startPoint, endPoint + 1);
+ if (contour[0].flags & 1) {
+ contour.push(contour[0]);
+ } else if (contour.at(-1).flags & 1) {
+ contour.unshift(contour.at(-1));
+ } else {
+ const p = {
+ flags: 1,
+ x: (contour[0].x + contour.at(-1).x) / 2,
+ y: (contour[0].y + contour.at(-1).y) / 2
+ };
+ contour.unshift(p);
+ contour.push(p);
+ }
+ moveTo(contour[0].x, contour[0].y);
+ for (j = 1, jj = contour.length; j < jj; j++) {
+ if (contour[j].flags & 1) {
+ lineTo(contour[j].x, contour[j].y);
+ } else if (contour[j + 1].flags & 1) {
+ quadraticCurveTo(contour[j].x, contour[j].y, contour[j + 1].x, contour[j + 1].y);
+ j++;
+ } else {
+ quadraticCurveTo(contour[j].x, contour[j].y, (contour[j].x + contour[j + 1].x) / 2, (contour[j].y + contour[j + 1].y) / 2);
+ }
+ }
+ startPoint = endPoint + 1;
+ }
+ }
+}
+function compileCharString(charStringCode, cmds, font, glyphId) {
+ function moveTo(x, y) {
+ cmds.push({
+ cmd: "moveTo",
+ args: [x, y]
+ });
+ }
+ function lineTo(x, y) {
+ cmds.push({
+ cmd: "lineTo",
+ args: [x, y]
+ });
+ }
+ function bezierCurveTo(x1, y1, x2, y2, x, y) {
+ cmds.push({
+ cmd: "bezierCurveTo",
+ args: [x1, y1, x2, y2, x, y]
+ });
+ }
+ const stack = [];
+ let x = 0,
+ y = 0;
+ let stems = 0;
+ function parse(code) {
+ let i = 0;
+ while (i < code.length) {
+ let stackClean = false;
+ let v = code[i++];
+ let xa, xb, ya, yb, y1, y2, y3, n, subrCode;
+ switch (v) {
+ case 1:
+ stems += stack.length >> 1;
+ stackClean = true;
+ break;
+ case 3:
+ stems += stack.length >> 1;
+ stackClean = true;
+ break;
+ case 4:
+ y += stack.pop();
+ moveTo(x, y);
+ stackClean = true;
+ break;
+ case 5:
+ while (stack.length > 0) {
+ x += stack.shift();
+ y += stack.shift();
+ lineTo(x, y);
+ }
+ break;
+ case 6:
+ while (stack.length > 0) {
+ x += stack.shift();
+ lineTo(x, y);
+ if (stack.length === 0) {
+ break;
+ }
+ y += stack.shift();
+ lineTo(x, y);
+ }
+ break;
+ case 7:
+ while (stack.length > 0) {
+ y += stack.shift();
+ lineTo(x, y);
+ if (stack.length === 0) {
+ break;
+ }
+ x += stack.shift();
+ lineTo(x, y);
+ }
+ break;
+ case 8:
+ while (stack.length > 0) {
+ xa = x + stack.shift();
+ ya = y + stack.shift();
+ xb = xa + stack.shift();
+ yb = ya + stack.shift();
+ x = xb + stack.shift();
+ y = yb + stack.shift();
+ bezierCurveTo(xa, ya, xb, yb, x, y);
+ }
+ break;
+ case 10:
+ n = stack.pop();
+ subrCode = null;
+ if (font.isCFFCIDFont) {
+ const fdIndex = font.fdSelect.getFDIndex(glyphId);
+ if (fdIndex >= 0 && fdIndex < font.fdArray.length) {
+ const fontDict = font.fdArray[fdIndex];
+ let subrs;
+ if (fontDict.privateDict?.subrsIndex) {
+ subrs = fontDict.privateDict.subrsIndex.objects;
+ }
+ if (subrs) {
+ n += getSubroutineBias(subrs);
+ subrCode = subrs[n];
+ }
+ } else {
+ warn("Invalid fd index for glyph index.");
+ }
+ } else {
+ subrCode = font.subrs[n + font.subrsBias];
+ }
+ if (subrCode) {
+ parse(subrCode);
+ }
+ break;
+ case 11:
+ return;
+ case 12:
+ v = code[i++];
+ switch (v) {
+ case 34:
+ xa = x + stack.shift();
+ xb = xa + stack.shift();
+ y1 = y + stack.shift();
+ x = xb + stack.shift();
+ bezierCurveTo(xa, y, xb, y1, x, y1);
+ xa = x + stack.shift();
+ xb = xa + stack.shift();
+ x = xb + stack.shift();
+ bezierCurveTo(xa, y1, xb, y, x, y);
+ break;
+ case 35:
+ xa = x + stack.shift();
+ ya = y + stack.shift();
+ xb = xa + stack.shift();
+ yb = ya + stack.shift();
+ x = xb + stack.shift();
+ y = yb + stack.shift();
+ bezierCurveTo(xa, ya, xb, yb, x, y);
+ xa = x + stack.shift();
+ ya = y + stack.shift();
+ xb = xa + stack.shift();
+ yb = ya + stack.shift();
+ x = xb + stack.shift();
+ y = yb + stack.shift();
+ bezierCurveTo(xa, ya, xb, yb, x, y);
+ stack.pop();
+ break;
+ case 36:
+ xa = x + stack.shift();
+ y1 = y + stack.shift();
+ xb = xa + stack.shift();
+ y2 = y1 + stack.shift();
+ x = xb + stack.shift();
+ bezierCurveTo(xa, y1, xb, y2, x, y2);
+ xa = x + stack.shift();
+ xb = xa + stack.shift();
+ y3 = y2 + stack.shift();
+ x = xb + stack.shift();
+ bezierCurveTo(xa, y2, xb, y3, x, y);
+ break;
+ case 37:
+ const x0 = x,
+ y0 = y;
+ xa = x + stack.shift();
+ ya = y + stack.shift();
+ xb = xa + stack.shift();
+ yb = ya + stack.shift();
+ x = xb + stack.shift();
+ y = yb + stack.shift();
+ bezierCurveTo(xa, ya, xb, yb, x, y);
+ xa = x + stack.shift();
+ ya = y + stack.shift();
+ xb = xa + stack.shift();
+ yb = ya + stack.shift();
+ x = xb;
+ y = yb;
+ if (Math.abs(x - x0) > Math.abs(y - y0)) {
+ x += stack.shift();
+ } else {
+ y += stack.shift();
+ }
+ bezierCurveTo(xa, ya, xb, yb, x, y);
+ break;
+ default:
+ throw new FormatError(`unknown operator: 12 ${v}`);
+ }
+ break;
+ case 14:
+ if (stack.length >= 4) {
+ const achar = stack.pop();
+ const bchar = stack.pop();
+ y = stack.pop();
+ x = stack.pop();
+ cmds.push({
+ cmd: "save"
+ }, {
+ cmd: "translate",
+ args: [x, y]
+ });
+ let cmap = lookupCmap(font.cmap, String.fromCharCode(font.glyphNameMap[StandardEncoding[achar]]));
+ compileCharString(font.glyphs[cmap.glyphId], cmds, font, cmap.glyphId);
+ cmds.push({
+ cmd: "restore"
+ });
+ cmap = lookupCmap(font.cmap, String.fromCharCode(font.glyphNameMap[StandardEncoding[bchar]]));
+ compileCharString(font.glyphs[cmap.glyphId], cmds, font, cmap.glyphId);
+ }
+ return;
+ case 18:
+ stems += stack.length >> 1;
+ stackClean = true;
+ break;
+ case 19:
+ stems += stack.length >> 1;
+ i += stems + 7 >> 3;
+ stackClean = true;
+ break;
+ case 20:
+ stems += stack.length >> 1;
+ i += stems + 7 >> 3;
+ stackClean = true;
+ break;
+ case 21:
+ y += stack.pop();
+ x += stack.pop();
+ moveTo(x, y);
+ stackClean = true;
+ break;
+ case 22:
+ x += stack.pop();
+ moveTo(x, y);
+ stackClean = true;
+ break;
+ case 23:
+ stems += stack.length >> 1;
+ stackClean = true;
+ break;
+ case 24:
+ while (stack.length > 2) {
+ xa = x + stack.shift();
+ ya = y + stack.shift();
+ xb = xa + stack.shift();
+ yb = ya + stack.shift();
+ x = xb + stack.shift();
+ y = yb + stack.shift();
+ bezierCurveTo(xa, ya, xb, yb, x, y);
+ }
+ x += stack.shift();
+ y += stack.shift();
+ lineTo(x, y);
+ break;
+ case 25:
+ while (stack.length > 6) {
+ x += stack.shift();
+ y += stack.shift();
+ lineTo(x, y);
+ }
+ xa = x + stack.shift();
+ ya = y + stack.shift();
+ xb = xa + stack.shift();
+ yb = ya + stack.shift();
+ x = xb + stack.shift();
+ y = yb + stack.shift();
+ bezierCurveTo(xa, ya, xb, yb, x, y);
+ break;
+ case 26:
+ if (stack.length % 2) {
+ x += stack.shift();
+ }
+ while (stack.length > 0) {
+ xa = x;
+ ya = y + stack.shift();
+ xb = xa + stack.shift();
+ yb = ya + stack.shift();
+ x = xb;
+ y = yb + stack.shift();
+ bezierCurveTo(xa, ya, xb, yb, x, y);
+ }
+ break;
+ case 27:
+ if (stack.length % 2) {
+ y += stack.shift();
+ }
+ while (stack.length > 0) {
+ xa = x + stack.shift();
+ ya = y;
+ xb = xa + stack.shift();
+ yb = ya + stack.shift();
+ x = xb + stack.shift();
+ y = yb;
+ bezierCurveTo(xa, ya, xb, yb, x, y);
+ }
+ break;
+ case 28:
+ stack.push((code[i] << 24 | code[i + 1] << 16) >> 16);
+ i += 2;
+ break;
+ case 29:
+ n = stack.pop() + font.gsubrsBias;
+ subrCode = font.gsubrs[n];
+ if (subrCode) {
+ parse(subrCode);
+ }
+ break;
+ case 30:
+ while (stack.length > 0) {
+ xa = x;
+ ya = y + stack.shift();
+ xb = xa + stack.shift();
+ yb = ya + stack.shift();
+ x = xb + stack.shift();
+ y = yb + (stack.length === 1 ? stack.shift() : 0);
+ bezierCurveTo(xa, ya, xb, yb, x, y);
+ if (stack.length === 0) {
+ break;
+ }
+ xa = x + stack.shift();
+ ya = y;
+ xb = xa + stack.shift();
+ yb = ya + stack.shift();
+ y = yb + stack.shift();
+ x = xb + (stack.length === 1 ? stack.shift() : 0);
+ bezierCurveTo(xa, ya, xb, yb, x, y);
+ }
+ break;
+ case 31:
+ while (stack.length > 0) {
+ xa = x + stack.shift();
+ ya = y;
+ xb = xa + stack.shift();
+ yb = ya + stack.shift();
+ y = yb + stack.shift();
+ x = xb + (stack.length === 1 ? stack.shift() : 0);
+ bezierCurveTo(xa, ya, xb, yb, x, y);
+ if (stack.length === 0) {
+ break;
+ }
+ xa = x;
+ ya = y + stack.shift();
+ xb = xa + stack.shift();
+ yb = ya + stack.shift();
+ x = xb + stack.shift();
+ y = yb + (stack.length === 1 ? stack.shift() : 0);
+ bezierCurveTo(xa, ya, xb, yb, x, y);
+ }
+ break;
+ default:
+ if (v < 32) {
+ throw new FormatError(`unknown operator: ${v}`);
+ }
+ if (v < 247) {
+ stack.push(v - 139);
+ } else if (v < 251) {
+ stack.push((v - 247) * 256 + code[i++] + 108);
+ } else if (v < 255) {
+ stack.push(-(v - 251) * 256 - code[i++] - 108);
+ } else {
+ stack.push((code[i] << 24 | code[i + 1] << 16 | code[i + 2] << 8 | code[i + 3]) / 65536);
+ i += 4;
+ }
+ break;
+ }
+ if (stackClean) {
+ stack.length = 0;
+ }
+ }
+ }
+ parse(charStringCode);
+}
+const NOOP = [];
+class CompiledFont {
+ constructor(fontMatrix) {
+ if (this.constructor === CompiledFont) {
+ unreachable("Cannot initialize CompiledFont.");
+ }
+ this.fontMatrix = fontMatrix;
+ this.compiledGlyphs = Object.create(null);
+ this.compiledCharCodeToGlyphId = Object.create(null);
+ }
+ getPathJs(unicode) {
+ const {
+ charCode,
+ glyphId
+ } = lookupCmap(this.cmap, unicode);
+ let fn = this.compiledGlyphs[glyphId];
+ if (!fn) {
+ try {
+ fn = this.compileGlyph(this.glyphs[glyphId], glyphId);
+ this.compiledGlyphs[glyphId] = fn;
+ } catch (ex) {
+ this.compiledGlyphs[glyphId] = NOOP;
+ if (this.compiledCharCodeToGlyphId[charCode] === undefined) {
+ this.compiledCharCodeToGlyphId[charCode] = glyphId;
+ }
+ throw ex;
+ }
+ }
+ if (this.compiledCharCodeToGlyphId[charCode] === undefined) {
+ this.compiledCharCodeToGlyphId[charCode] = glyphId;
+ }
+ return fn;
+ }
+ compileGlyph(code, glyphId) {
+ if (!code || code.length === 0 || code[0] === 14) {
+ return NOOP;
+ }
+ let fontMatrix = this.fontMatrix;
+ if (this.isCFFCIDFont) {
+ const fdIndex = this.fdSelect.getFDIndex(glyphId);
+ if (fdIndex >= 0 && fdIndex < this.fdArray.length) {
+ const fontDict = this.fdArray[fdIndex];
+ fontMatrix = fontDict.getByName("FontMatrix") || FONT_IDENTITY_MATRIX;
+ } else {
+ warn("Invalid fd index for glyph index.");
+ }
+ }
+ const cmds = [{
+ cmd: "save"
+ }, {
+ cmd: "transform",
+ args: fontMatrix.slice()
+ }, {
+ cmd: "scale",
+ args: ["size", "-size"]
+ }];
+ this.compileGlyphImpl(code, cmds, glyphId);
+ cmds.push({
+ cmd: "restore"
+ });
+ return cmds;
+ }
+ compileGlyphImpl() {
+ unreachable("Children classes should implement this.");
+ }
+ hasBuiltPath(unicode) {
+ const {
+ charCode,
+ glyphId
+ } = lookupCmap(this.cmap, unicode);
+ return this.compiledGlyphs[glyphId] !== undefined && this.compiledCharCodeToGlyphId[charCode] !== undefined;
+ }
+}
+class TrueTypeCompiled extends CompiledFont {
+ constructor(glyphs, cmap, fontMatrix) {
+ super(fontMatrix || [0.000488, 0, 0, 0.000488, 0, 0]);
+ this.glyphs = glyphs;
+ this.cmap = cmap;
+ }
+ compileGlyphImpl(code, cmds) {
+ compileGlyf(code, cmds, this);
+ }
+}
+class Type2Compiled extends CompiledFont {
+ constructor(cffInfo, cmap, fontMatrix, glyphNameMap) {
+ super(fontMatrix || [0.001, 0, 0, 0.001, 0, 0]);
+ this.glyphs = cffInfo.glyphs;
+ this.gsubrs = cffInfo.gsubrs || [];
+ this.subrs = cffInfo.subrs || [];
+ this.cmap = cmap;
+ this.glyphNameMap = glyphNameMap || getGlyphsUnicode();
+ this.gsubrsBias = getSubroutineBias(this.gsubrs);
+ this.subrsBias = getSubroutineBias(this.subrs);
+ this.isCFFCIDFont = cffInfo.isCFFCIDFont;
+ this.fdSelect = cffInfo.fdSelect;
+ this.fdArray = cffInfo.fdArray;
+ }
+ compileGlyphImpl(code, cmds, glyphId) {
+ compileCharString(code, cmds, this, glyphId);
+ }
+}
+class FontRendererFactory {
+ static create(font, seacAnalysisEnabled) {
+ const data = new Uint8Array(font.data);
+ let cmap, glyf, loca, cff, indexToLocFormat, unitsPerEm;
+ const numTables = getUint16(data, 4);
+ for (let i = 0, p = 12; i < numTables; i++, p += 16) {
+ const tag = bytesToString(data.subarray(p, p + 4));
+ const offset = getUint32(data, p + 8);
+ const length = getUint32(data, p + 12);
+ switch (tag) {
+ case "cmap":
+ cmap = parseCmap(data, offset, offset + length);
+ break;
+ case "glyf":
+ glyf = data.subarray(offset, offset + length);
+ break;
+ case "loca":
+ loca = data.subarray(offset, offset + length);
+ break;
+ case "head":
+ unitsPerEm = getUint16(data, offset + 18);
+ indexToLocFormat = getUint16(data, offset + 50);
+ break;
+ case "CFF ":
+ cff = parseCff(data, offset, offset + length, seacAnalysisEnabled);
+ break;
+ }
+ }
+ if (glyf) {
+ const fontMatrix = !unitsPerEm ? font.fontMatrix : [1 / unitsPerEm, 0, 0, 1 / unitsPerEm, 0, 0];
+ return new TrueTypeCompiled(parseGlyfTable(glyf, loca, indexToLocFormat), cmap, fontMatrix);
+ }
+ return new Type2Compiled(cff, cmap, font.fontMatrix, font.glyphNameMap);
+ }
+}
+
+;// CONCATENATED MODULE: ./src/core/metrics.js
+
+const getMetrics = getLookupTableFactory(function (t) {
+ t.Courier = 600;
+ t["Courier-Bold"] = 600;
+ t["Courier-BoldOblique"] = 600;
+ t["Courier-Oblique"] = 600;
+ t.Helvetica = getLookupTableFactory(function (t) {
+ t.space = 278;
+ t.exclam = 278;
+ t.quotedbl = 355;
+ t.numbersign = 556;
+ t.dollar = 556;
+ t.percent = 889;
+ t.ampersand = 667;
+ t.quoteright = 222;
+ t.parenleft = 333;
+ t.parenright = 333;
+ t.asterisk = 389;
+ t.plus = 584;
+ t.comma = 278;
+ t.hyphen = 333;
+ t.period = 278;
+ t.slash = 278;
+ t.zero = 556;
+ t.one = 556;
+ t.two = 556;
+ t.three = 556;
+ t.four = 556;
+ t.five = 556;
+ t.six = 556;
+ t.seven = 556;
+ t.eight = 556;
+ t.nine = 556;
+ t.colon = 278;
+ t.semicolon = 278;
+ t.less = 584;
+ t.equal = 584;
+ t.greater = 584;
+ t.question = 556;
+ t.at = 1015;
+ t.A = 667;
+ t.B = 667;
+ t.C = 722;
+ t.D = 722;
+ t.E = 667;
+ t.F = 611;
+ t.G = 778;
+ t.H = 722;
+ t.I = 278;
+ t.J = 500;
+ t.K = 667;
+ t.L = 556;
+ t.M = 833;
+ t.N = 722;
+ t.O = 778;
+ t.P = 667;
+ t.Q = 778;
+ t.R = 722;
+ t.S = 667;
+ t.T = 611;
+ t.U = 722;
+ t.V = 667;
+ t.W = 944;
+ t.X = 667;
+ t.Y = 667;
+ t.Z = 611;
+ t.bracketleft = 278;
+ t.backslash = 278;
+ t.bracketright = 278;
+ t.asciicircum = 469;
+ t.underscore = 556;
+ t.quoteleft = 222;
+ t.a = 556;
+ t.b = 556;
+ t.c = 500;
+ t.d = 556;
+ t.e = 556;
+ t.f = 278;
+ t.g = 556;
+ t.h = 556;
+ t.i = 222;
+ t.j = 222;
+ t.k = 500;
+ t.l = 222;
+ t.m = 833;
+ t.n = 556;
+ t.o = 556;
+ t.p = 556;
+ t.q = 556;
+ t.r = 333;
+ t.s = 500;
+ t.t = 278;
+ t.u = 556;
+ t.v = 500;
+ t.w = 722;
+ t.x = 500;
+ t.y = 500;
+ t.z = 500;
+ t.braceleft = 334;
+ t.bar = 260;
+ t.braceright = 334;
+ t.asciitilde = 584;
+ t.exclamdown = 333;
+ t.cent = 556;
+ t.sterling = 556;
+ t.fraction = 167;
+ t.yen = 556;
+ t.florin = 556;
+ t.section = 556;
+ t.currency = 556;
+ t.quotesingle = 191;
+ t.quotedblleft = 333;
+ t.guillemotleft = 556;
+ t.guilsinglleft = 333;
+ t.guilsinglright = 333;
+ t.fi = 500;
+ t.fl = 500;
+ t.endash = 556;
+ t.dagger = 556;
+ t.daggerdbl = 556;
+ t.periodcentered = 278;
+ t.paragraph = 537;
+ t.bullet = 350;
+ t.quotesinglbase = 222;
+ t.quotedblbase = 333;
+ t.quotedblright = 333;
+ t.guillemotright = 556;
+ t.ellipsis = 1000;
+ t.perthousand = 1000;
+ t.questiondown = 611;
+ t.grave = 333;
+ t.acute = 333;
+ t.circumflex = 333;
+ t.tilde = 333;
+ t.macron = 333;
+ t.breve = 333;
+ t.dotaccent = 333;
+ t.dieresis = 333;
+ t.ring = 333;
+ t.cedilla = 333;
+ t.hungarumlaut = 333;
+ t.ogonek = 333;
+ t.caron = 333;
+ t.emdash = 1000;
+ t.AE = 1000;
+ t.ordfeminine = 370;
+ t.Lslash = 556;
+ t.Oslash = 778;
+ t.OE = 1000;
+ t.ordmasculine = 365;
+ t.ae = 889;
+ t.dotlessi = 278;
+ t.lslash = 222;
+ t.oslash = 611;
+ t.oe = 944;
+ t.germandbls = 611;
+ t.Idieresis = 278;
+ t.eacute = 556;
+ t.abreve = 556;
+ t.uhungarumlaut = 556;
+ t.ecaron = 556;
+ t.Ydieresis = 667;
+ t.divide = 584;
+ t.Yacute = 667;
+ t.Acircumflex = 667;
+ t.aacute = 556;
+ t.Ucircumflex = 722;
+ t.yacute = 500;
+ t.scommaaccent = 500;
+ t.ecircumflex = 556;
+ t.Uring = 722;
+ t.Udieresis = 722;
+ t.aogonek = 556;
+ t.Uacute = 722;
+ t.uogonek = 556;
+ t.Edieresis = 667;
+ t.Dcroat = 722;
+ t.commaaccent = 250;
+ t.copyright = 737;
+ t.Emacron = 667;
+ t.ccaron = 500;
+ t.aring = 556;
+ t.Ncommaaccent = 722;
+ t.lacute = 222;
+ t.agrave = 556;
+ t.Tcommaaccent = 611;
+ t.Cacute = 722;
+ t.atilde = 556;
+ t.Edotaccent = 667;
+ t.scaron = 500;
+ t.scedilla = 500;
+ t.iacute = 278;
+ t.lozenge = 471;
+ t.Rcaron = 722;
+ t.Gcommaaccent = 778;
+ t.ucircumflex = 556;
+ t.acircumflex = 556;
+ t.Amacron = 667;
+ t.rcaron = 333;
+ t.ccedilla = 500;
+ t.Zdotaccent = 611;
+ t.Thorn = 667;
+ t.Omacron = 778;
+ t.Racute = 722;
+ t.Sacute = 667;
+ t.dcaron = 643;
+ t.Umacron = 722;
+ t.uring = 556;
+ t.threesuperior = 333;
+ t.Ograve = 778;
+ t.Agrave = 667;
+ t.Abreve = 667;
+ t.multiply = 584;
+ t.uacute = 556;
+ t.Tcaron = 611;
+ t.partialdiff = 476;
+ t.ydieresis = 500;
+ t.Nacute = 722;
+ t.icircumflex = 278;
+ t.Ecircumflex = 667;
+ t.adieresis = 556;
+ t.edieresis = 556;
+ t.cacute = 500;
+ t.nacute = 556;
+ t.umacron = 556;
+ t.Ncaron = 722;
+ t.Iacute = 278;
+ t.plusminus = 584;
+ t.brokenbar = 260;
+ t.registered = 737;
+ t.Gbreve = 778;
+ t.Idotaccent = 278;
+ t.summation = 600;
+ t.Egrave = 667;
+ t.racute = 333;
+ t.omacron = 556;
+ t.Zacute = 611;
+ t.Zcaron = 611;
+ t.greaterequal = 549;
+ t.Eth = 722;
+ t.Ccedilla = 722;
+ t.lcommaaccent = 222;
+ t.tcaron = 317;
+ t.eogonek = 556;
+ t.Uogonek = 722;
+ t.Aacute = 667;
+ t.Adieresis = 667;
+ t.egrave = 556;
+ t.zacute = 500;
+ t.iogonek = 222;
+ t.Oacute = 778;
+ t.oacute = 556;
+ t.amacron = 556;
+ t.sacute = 500;
+ t.idieresis = 278;
+ t.Ocircumflex = 778;
+ t.Ugrave = 722;
+ t.Delta = 612;
+ t.thorn = 556;
+ t.twosuperior = 333;
+ t.Odieresis = 778;
+ t.mu = 556;
+ t.igrave = 278;
+ t.ohungarumlaut = 556;
+ t.Eogonek = 667;
+ t.dcroat = 556;
+ t.threequarters = 834;
+ t.Scedilla = 667;
+ t.lcaron = 299;
+ t.Kcommaaccent = 667;
+ t.Lacute = 556;
+ t.trademark = 1000;
+ t.edotaccent = 556;
+ t.Igrave = 278;
+ t.Imacron = 278;
+ t.Lcaron = 556;
+ t.onehalf = 834;
+ t.lessequal = 549;
+ t.ocircumflex = 556;
+ t.ntilde = 556;
+ t.Uhungarumlaut = 722;
+ t.Eacute = 667;
+ t.emacron = 556;
+ t.gbreve = 556;
+ t.onequarter = 834;
+ t.Scaron = 667;
+ t.Scommaaccent = 667;
+ t.Ohungarumlaut = 778;
+ t.degree = 400;
+ t.ograve = 556;
+ t.Ccaron = 722;
+ t.ugrave = 556;
+ t.radical = 453;
+ t.Dcaron = 722;
+ t.rcommaaccent = 333;
+ t.Ntilde = 722;
+ t.otilde = 556;
+ t.Rcommaaccent = 722;
+ t.Lcommaaccent = 556;
+ t.Atilde = 667;
+ t.Aogonek = 667;
+ t.Aring = 667;
+ t.Otilde = 778;
+ t.zdotaccent = 500;
+ t.Ecaron = 667;
+ t.Iogonek = 278;
+ t.kcommaaccent = 500;
+ t.minus = 584;
+ t.Icircumflex = 278;
+ t.ncaron = 556;
+ t.tcommaaccent = 278;
+ t.logicalnot = 584;
+ t.odieresis = 556;
+ t.udieresis = 556;
+ t.notequal = 549;
+ t.gcommaaccent = 556;
+ t.eth = 556;
+ t.zcaron = 500;
+ t.ncommaaccent = 556;
+ t.onesuperior = 333;
+ t.imacron = 278;
+ t.Euro = 556;
+ });
+ t["Helvetica-Bold"] = getLookupTableFactory(function (t) {
+ t.space = 278;
+ t.exclam = 333;
+ t.quotedbl = 474;
+ t.numbersign = 556;
+ t.dollar = 556;
+ t.percent = 889;
+ t.ampersand = 722;
+ t.quoteright = 278;
+ t.parenleft = 333;
+ t.parenright = 333;
+ t.asterisk = 389;
+ t.plus = 584;
+ t.comma = 278;
+ t.hyphen = 333;
+ t.period = 278;
+ t.slash = 278;
+ t.zero = 556;
+ t.one = 556;
+ t.two = 556;
+ t.three = 556;
+ t.four = 556;
+ t.five = 556;
+ t.six = 556;
+ t.seven = 556;
+ t.eight = 556;
+ t.nine = 556;
+ t.colon = 333;
+ t.semicolon = 333;
+ t.less = 584;
+ t.equal = 584;
+ t.greater = 584;
+ t.question = 611;
+ t.at = 975;
+ t.A = 722;
+ t.B = 722;
+ t.C = 722;
+ t.D = 722;
+ t.E = 667;
+ t.F = 611;
+ t.G = 778;
+ t.H = 722;
+ t.I = 278;
+ t.J = 556;
+ t.K = 722;
+ t.L = 611;
+ t.M = 833;
+ t.N = 722;
+ t.O = 778;
+ t.P = 667;
+ t.Q = 778;
+ t.R = 722;
+ t.S = 667;
+ t.T = 611;
+ t.U = 722;
+ t.V = 667;
+ t.W = 944;
+ t.X = 667;
+ t.Y = 667;
+ t.Z = 611;
+ t.bracketleft = 333;
+ t.backslash = 278;
+ t.bracketright = 333;
+ t.asciicircum = 584;
+ t.underscore = 556;
+ t.quoteleft = 278;
+ t.a = 556;
+ t.b = 611;
+ t.c = 556;
+ t.d = 611;
+ t.e = 556;
+ t.f = 333;
+ t.g = 611;
+ t.h = 611;
+ t.i = 278;
+ t.j = 278;
+ t.k = 556;
+ t.l = 278;
+ t.m = 889;
+ t.n = 611;
+ t.o = 611;
+ t.p = 611;
+ t.q = 611;
+ t.r = 389;
+ t.s = 556;
+ t.t = 333;
+ t.u = 611;
+ t.v = 556;
+ t.w = 778;
+ t.x = 556;
+ t.y = 556;
+ t.z = 500;
+ t.braceleft = 389;
+ t.bar = 280;
+ t.braceright = 389;
+ t.asciitilde = 584;
+ t.exclamdown = 333;
+ t.cent = 556;
+ t.sterling = 556;
+ t.fraction = 167;
+ t.yen = 556;
+ t.florin = 556;
+ t.section = 556;
+ t.currency = 556;
+ t.quotesingle = 238;
+ t.quotedblleft = 500;
+ t.guillemotleft = 556;
+ t.guilsinglleft = 333;
+ t.guilsinglright = 333;
+ t.fi = 611;
+ t.fl = 611;
+ t.endash = 556;
+ t.dagger = 556;
+ t.daggerdbl = 556;
+ t.periodcentered = 278;
+ t.paragraph = 556;
+ t.bullet = 350;
+ t.quotesinglbase = 278;
+ t.quotedblbase = 500;
+ t.quotedblright = 500;
+ t.guillemotright = 556;
+ t.ellipsis = 1000;
+ t.perthousand = 1000;
+ t.questiondown = 611;
+ t.grave = 333;
+ t.acute = 333;
+ t.circumflex = 333;
+ t.tilde = 333;
+ t.macron = 333;
+ t.breve = 333;
+ t.dotaccent = 333;
+ t.dieresis = 333;
+ t.ring = 333;
+ t.cedilla = 333;
+ t.hungarumlaut = 333;
+ t.ogonek = 333;
+ t.caron = 333;
+ t.emdash = 1000;
+ t.AE = 1000;
+ t.ordfeminine = 370;
+ t.Lslash = 611;
+ t.Oslash = 778;
+ t.OE = 1000;
+ t.ordmasculine = 365;
+ t.ae = 889;
+ t.dotlessi = 278;
+ t.lslash = 278;
+ t.oslash = 611;
+ t.oe = 944;
+ t.germandbls = 611;
+ t.Idieresis = 278;
+ t.eacute = 556;
+ t.abreve = 556;
+ t.uhungarumlaut = 611;
+ t.ecaron = 556;
+ t.Ydieresis = 667;
+ t.divide = 584;
+ t.Yacute = 667;
+ t.Acircumflex = 722;
+ t.aacute = 556;
+ t.Ucircumflex = 722;
+ t.yacute = 556;
+ t.scommaaccent = 556;
+ t.ecircumflex = 556;
+ t.Uring = 722;
+ t.Udieresis = 722;
+ t.aogonek = 556;
+ t.Uacute = 722;
+ t.uogonek = 611;
+ t.Edieresis = 667;
+ t.Dcroat = 722;
+ t.commaaccent = 250;
+ t.copyright = 737;
+ t.Emacron = 667;
+ t.ccaron = 556;
+ t.aring = 556;
+ t.Ncommaaccent = 722;
+ t.lacute = 278;
+ t.agrave = 556;
+ t.Tcommaaccent = 611;
+ t.Cacute = 722;
+ t.atilde = 556;
+ t.Edotaccent = 667;
+ t.scaron = 556;
+ t.scedilla = 556;
+ t.iacute = 278;
+ t.lozenge = 494;
+ t.Rcaron = 722;
+ t.Gcommaaccent = 778;
+ t.ucircumflex = 611;
+ t.acircumflex = 556;
+ t.Amacron = 722;
+ t.rcaron = 389;
+ t.ccedilla = 556;
+ t.Zdotaccent = 611;
+ t.Thorn = 667;
+ t.Omacron = 778;
+ t.Racute = 722;
+ t.Sacute = 667;
+ t.dcaron = 743;
+ t.Umacron = 722;
+ t.uring = 611;
+ t.threesuperior = 333;
+ t.Ograve = 778;
+ t.Agrave = 722;
+ t.Abreve = 722;
+ t.multiply = 584;
+ t.uacute = 611;
+ t.Tcaron = 611;
+ t.partialdiff = 494;
+ t.ydieresis = 556;
+ t.Nacute = 722;
+ t.icircumflex = 278;
+ t.Ecircumflex = 667;
+ t.adieresis = 556;
+ t.edieresis = 556;
+ t.cacute = 556;
+ t.nacute = 611;
+ t.umacron = 611;
+ t.Ncaron = 722;
+ t.Iacute = 278;
+ t.plusminus = 584;
+ t.brokenbar = 280;
+ t.registered = 737;
+ t.Gbreve = 778;
+ t.Idotaccent = 278;
+ t.summation = 600;
+ t.Egrave = 667;
+ t.racute = 389;
+ t.omacron = 611;
+ t.Zacute = 611;
+ t.Zcaron = 611;
+ t.greaterequal = 549;
+ t.Eth = 722;
+ t.Ccedilla = 722;
+ t.lcommaaccent = 278;
+ t.tcaron = 389;
+ t.eogonek = 556;
+ t.Uogonek = 722;
+ t.Aacute = 722;
+ t.Adieresis = 722;
+ t.egrave = 556;
+ t.zacute = 500;
+ t.iogonek = 278;
+ t.Oacute = 778;
+ t.oacute = 611;
+ t.amacron = 556;
+ t.sacute = 556;
+ t.idieresis = 278;
+ t.Ocircumflex = 778;
+ t.Ugrave = 722;
+ t.Delta = 612;
+ t.thorn = 611;
+ t.twosuperior = 333;
+ t.Odieresis = 778;
+ t.mu = 611;
+ t.igrave = 278;
+ t.ohungarumlaut = 611;
+ t.Eogonek = 667;
+ t.dcroat = 611;
+ t.threequarters = 834;
+ t.Scedilla = 667;
+ t.lcaron = 400;
+ t.Kcommaaccent = 722;
+ t.Lacute = 611;
+ t.trademark = 1000;
+ t.edotaccent = 556;
+ t.Igrave = 278;
+ t.Imacron = 278;
+ t.Lcaron = 611;
+ t.onehalf = 834;
+ t.lessequal = 549;
+ t.ocircumflex = 611;
+ t.ntilde = 611;
+ t.Uhungarumlaut = 722;
+ t.Eacute = 667;
+ t.emacron = 556;
+ t.gbreve = 611;
+ t.onequarter = 834;
+ t.Scaron = 667;
+ t.Scommaaccent = 667;
+ t.Ohungarumlaut = 778;
+ t.degree = 400;
+ t.ograve = 611;
+ t.Ccaron = 722;
+ t.ugrave = 611;
+ t.radical = 549;
+ t.Dcaron = 722;
+ t.rcommaaccent = 389;
+ t.Ntilde = 722;
+ t.otilde = 611;
+ t.Rcommaaccent = 722;
+ t.Lcommaaccent = 611;
+ t.Atilde = 722;
+ t.Aogonek = 722;
+ t.Aring = 722;
+ t.Otilde = 778;
+ t.zdotaccent = 500;
+ t.Ecaron = 667;
+ t.Iogonek = 278;
+ t.kcommaaccent = 556;
+ t.minus = 584;
+ t.Icircumflex = 278;
+ t.ncaron = 611;
+ t.tcommaaccent = 333;
+ t.logicalnot = 584;
+ t.odieresis = 611;
+ t.udieresis = 611;
+ t.notequal = 549;
+ t.gcommaaccent = 611;
+ t.eth = 611;
+ t.zcaron = 500;
+ t.ncommaaccent = 611;
+ t.onesuperior = 333;
+ t.imacron = 278;
+ t.Euro = 556;
+ });
+ t["Helvetica-BoldOblique"] = getLookupTableFactory(function (t) {
+ t.space = 278;
+ t.exclam = 333;
+ t.quotedbl = 474;
+ t.numbersign = 556;
+ t.dollar = 556;
+ t.percent = 889;
+ t.ampersand = 722;
+ t.quoteright = 278;
+ t.parenleft = 333;
+ t.parenright = 333;
+ t.asterisk = 389;
+ t.plus = 584;
+ t.comma = 278;
+ t.hyphen = 333;
+ t.period = 278;
+ t.slash = 278;
+ t.zero = 556;
+ t.one = 556;
+ t.two = 556;
+ t.three = 556;
+ t.four = 556;
+ t.five = 556;
+ t.six = 556;
+ t.seven = 556;
+ t.eight = 556;
+ t.nine = 556;
+ t.colon = 333;
+ t.semicolon = 333;
+ t.less = 584;
+ t.equal = 584;
+ t.greater = 584;
+ t.question = 611;
+ t.at = 975;
+ t.A = 722;
+ t.B = 722;
+ t.C = 722;
+ t.D = 722;
+ t.E = 667;
+ t.F = 611;
+ t.G = 778;
+ t.H = 722;
+ t.I = 278;
+ t.J = 556;
+ t.K = 722;
+ t.L = 611;
+ t.M = 833;
+ t.N = 722;
+ t.O = 778;
+ t.P = 667;
+ t.Q = 778;
+ t.R = 722;
+ t.S = 667;
+ t.T = 611;
+ t.U = 722;
+ t.V = 667;
+ t.W = 944;
+ t.X = 667;
+ t.Y = 667;
+ t.Z = 611;
+ t.bracketleft = 333;
+ t.backslash = 278;
+ t.bracketright = 333;
+ t.asciicircum = 584;
+ t.underscore = 556;
+ t.quoteleft = 278;
+ t.a = 556;
+ t.b = 611;
+ t.c = 556;
+ t.d = 611;
+ t.e = 556;
+ t.f = 333;
+ t.g = 611;
+ t.h = 611;
+ t.i = 278;
+ t.j = 278;
+ t.k = 556;
+ t.l = 278;
+ t.m = 889;
+ t.n = 611;
+ t.o = 611;
+ t.p = 611;
+ t.q = 611;
+ t.r = 389;
+ t.s = 556;
+ t.t = 333;
+ t.u = 611;
+ t.v = 556;
+ t.w = 778;
+ t.x = 556;
+ t.y = 556;
+ t.z = 500;
+ t.braceleft = 389;
+ t.bar = 280;
+ t.braceright = 389;
+ t.asciitilde = 584;
+ t.exclamdown = 333;
+ t.cent = 556;
+ t.sterling = 556;
+ t.fraction = 167;
+ t.yen = 556;
+ t.florin = 556;
+ t.section = 556;
+ t.currency = 556;
+ t.quotesingle = 238;
+ t.quotedblleft = 500;
+ t.guillemotleft = 556;
+ t.guilsinglleft = 333;
+ t.guilsinglright = 333;
+ t.fi = 611;
+ t.fl = 611;
+ t.endash = 556;
+ t.dagger = 556;
+ t.daggerdbl = 556;
+ t.periodcentered = 278;
+ t.paragraph = 556;
+ t.bullet = 350;
+ t.quotesinglbase = 278;
+ t.quotedblbase = 500;
+ t.quotedblright = 500;
+ t.guillemotright = 556;
+ t.ellipsis = 1000;
+ t.perthousand = 1000;
+ t.questiondown = 611;
+ t.grave = 333;
+ t.acute = 333;
+ t.circumflex = 333;
+ t.tilde = 333;
+ t.macron = 333;
+ t.breve = 333;
+ t.dotaccent = 333;
+ t.dieresis = 333;
+ t.ring = 333;
+ t.cedilla = 333;
+ t.hungarumlaut = 333;
+ t.ogonek = 333;
+ t.caron = 333;
+ t.emdash = 1000;
+ t.AE = 1000;
+ t.ordfeminine = 370;
+ t.Lslash = 611;
+ t.Oslash = 778;
+ t.OE = 1000;
+ t.ordmasculine = 365;
+ t.ae = 889;
+ t.dotlessi = 278;
+ t.lslash = 278;
+ t.oslash = 611;
+ t.oe = 944;
+ t.germandbls = 611;
+ t.Idieresis = 278;
+ t.eacute = 556;
+ t.abreve = 556;
+ t.uhungarumlaut = 611;
+ t.ecaron = 556;
+ t.Ydieresis = 667;
+ t.divide = 584;
+ t.Yacute = 667;
+ t.Acircumflex = 722;
+ t.aacute = 556;
+ t.Ucircumflex = 722;
+ t.yacute = 556;
+ t.scommaaccent = 556;
+ t.ecircumflex = 556;
+ t.Uring = 722;
+ t.Udieresis = 722;
+ t.aogonek = 556;
+ t.Uacute = 722;
+ t.uogonek = 611;
+ t.Edieresis = 667;
+ t.Dcroat = 722;
+ t.commaaccent = 250;
+ t.copyright = 737;
+ t.Emacron = 667;
+ t.ccaron = 556;
+ t.aring = 556;
+ t.Ncommaaccent = 722;
+ t.lacute = 278;
+ t.agrave = 556;
+ t.Tcommaaccent = 611;
+ t.Cacute = 722;
+ t.atilde = 556;
+ t.Edotaccent = 667;
+ t.scaron = 556;
+ t.scedilla = 556;
+ t.iacute = 278;
+ t.lozenge = 494;
+ t.Rcaron = 722;
+ t.Gcommaaccent = 778;
+ t.ucircumflex = 611;
+ t.acircumflex = 556;
+ t.Amacron = 722;
+ t.rcaron = 389;
+ t.ccedilla = 556;
+ t.Zdotaccent = 611;
+ t.Thorn = 667;
+ t.Omacron = 778;
+ t.Racute = 722;
+ t.Sacute = 667;
+ t.dcaron = 743;
+ t.Umacron = 722;
+ t.uring = 611;
+ t.threesuperior = 333;
+ t.Ograve = 778;
+ t.Agrave = 722;
+ t.Abreve = 722;
+ t.multiply = 584;
+ t.uacute = 611;
+ t.Tcaron = 611;
+ t.partialdiff = 494;
+ t.ydieresis = 556;
+ t.Nacute = 722;
+ t.icircumflex = 278;
+ t.Ecircumflex = 667;
+ t.adieresis = 556;
+ t.edieresis = 556;
+ t.cacute = 556;
+ t.nacute = 611;
+ t.umacron = 611;
+ t.Ncaron = 722;
+ t.Iacute = 278;
+ t.plusminus = 584;
+ t.brokenbar = 280;
+ t.registered = 737;
+ t.Gbreve = 778;
+ t.Idotaccent = 278;
+ t.summation = 600;
+ t.Egrave = 667;
+ t.racute = 389;
+ t.omacron = 611;
+ t.Zacute = 611;
+ t.Zcaron = 611;
+ t.greaterequal = 549;
+ t.Eth = 722;
+ t.Ccedilla = 722;
+ t.lcommaaccent = 278;
+ t.tcaron = 389;
+ t.eogonek = 556;
+ t.Uogonek = 722;
+ t.Aacute = 722;
+ t.Adieresis = 722;
+ t.egrave = 556;
+ t.zacute = 500;
+ t.iogonek = 278;
+ t.Oacute = 778;
+ t.oacute = 611;
+ t.amacron = 556;
+ t.sacute = 556;
+ t.idieresis = 278;
+ t.Ocircumflex = 778;
+ t.Ugrave = 722;
+ t.Delta = 612;
+ t.thorn = 611;
+ t.twosuperior = 333;
+ t.Odieresis = 778;
+ t.mu = 611;
+ t.igrave = 278;
+ t.ohungarumlaut = 611;
+ t.Eogonek = 667;
+ t.dcroat = 611;
+ t.threequarters = 834;
+ t.Scedilla = 667;
+ t.lcaron = 400;
+ t.Kcommaaccent = 722;
+ t.Lacute = 611;
+ t.trademark = 1000;
+ t.edotaccent = 556;
+ t.Igrave = 278;
+ t.Imacron = 278;
+ t.Lcaron = 611;
+ t.onehalf = 834;
+ t.lessequal = 549;
+ t.ocircumflex = 611;
+ t.ntilde = 611;
+ t.Uhungarumlaut = 722;
+ t.Eacute = 667;
+ t.emacron = 556;
+ t.gbreve = 611;
+ t.onequarter = 834;
+ t.Scaron = 667;
+ t.Scommaaccent = 667;
+ t.Ohungarumlaut = 778;
+ t.degree = 400;
+ t.ograve = 611;
+ t.Ccaron = 722;
+ t.ugrave = 611;
+ t.radical = 549;
+ t.Dcaron = 722;
+ t.rcommaaccent = 389;
+ t.Ntilde = 722;
+ t.otilde = 611;
+ t.Rcommaaccent = 722;
+ t.Lcommaaccent = 611;
+ t.Atilde = 722;
+ t.Aogonek = 722;
+ t.Aring = 722;
+ t.Otilde = 778;
+ t.zdotaccent = 500;
+ t.Ecaron = 667;
+ t.Iogonek = 278;
+ t.kcommaaccent = 556;
+ t.minus = 584;
+ t.Icircumflex = 278;
+ t.ncaron = 611;
+ t.tcommaaccent = 333;
+ t.logicalnot = 584;
+ t.odieresis = 611;
+ t.udieresis = 611;
+ t.notequal = 549;
+ t.gcommaaccent = 611;
+ t.eth = 611;
+ t.zcaron = 500;
+ t.ncommaaccent = 611;
+ t.onesuperior = 333;
+ t.imacron = 278;
+ t.Euro = 556;
+ });
+ t["Helvetica-Oblique"] = getLookupTableFactory(function (t) {
+ t.space = 278;
+ t.exclam = 278;
+ t.quotedbl = 355;
+ t.numbersign = 556;
+ t.dollar = 556;
+ t.percent = 889;
+ t.ampersand = 667;
+ t.quoteright = 222;
+ t.parenleft = 333;
+ t.parenright = 333;
+ t.asterisk = 389;
+ t.plus = 584;
+ t.comma = 278;
+ t.hyphen = 333;
+ t.period = 278;
+ t.slash = 278;
+ t.zero = 556;
+ t.one = 556;
+ t.two = 556;
+ t.three = 556;
+ t.four = 556;
+ t.five = 556;
+ t.six = 556;
+ t.seven = 556;
+ t.eight = 556;
+ t.nine = 556;
+ t.colon = 278;
+ t.semicolon = 278;
+ t.less = 584;
+ t.equal = 584;
+ t.greater = 584;
+ t.question = 556;
+ t.at = 1015;
+ t.A = 667;
+ t.B = 667;
+ t.C = 722;
+ t.D = 722;
+ t.E = 667;
+ t.F = 611;
+ t.G = 778;
+ t.H = 722;
+ t.I = 278;
+ t.J = 500;
+ t.K = 667;
+ t.L = 556;
+ t.M = 833;
+ t.N = 722;
+ t.O = 778;
+ t.P = 667;
+ t.Q = 778;
+ t.R = 722;
+ t.S = 667;
+ t.T = 611;
+ t.U = 722;
+ t.V = 667;
+ t.W = 944;
+ t.X = 667;
+ t.Y = 667;
+ t.Z = 611;
+ t.bracketleft = 278;
+ t.backslash = 278;
+ t.bracketright = 278;
+ t.asciicircum = 469;
+ t.underscore = 556;
+ t.quoteleft = 222;
+ t.a = 556;
+ t.b = 556;
+ t.c = 500;
+ t.d = 556;
+ t.e = 556;
+ t.f = 278;
+ t.g = 556;
+ t.h = 556;
+ t.i = 222;
+ t.j = 222;
+ t.k = 500;
+ t.l = 222;
+ t.m = 833;
+ t.n = 556;
+ t.o = 556;
+ t.p = 556;
+ t.q = 556;
+ t.r = 333;
+ t.s = 500;
+ t.t = 278;
+ t.u = 556;
+ t.v = 500;
+ t.w = 722;
+ t.x = 500;
+ t.y = 500;
+ t.z = 500;
+ t.braceleft = 334;
+ t.bar = 260;
+ t.braceright = 334;
+ t.asciitilde = 584;
+ t.exclamdown = 333;
+ t.cent = 556;
+ t.sterling = 556;
+ t.fraction = 167;
+ t.yen = 556;
+ t.florin = 556;
+ t.section = 556;
+ t.currency = 556;
+ t.quotesingle = 191;
+ t.quotedblleft = 333;
+ t.guillemotleft = 556;
+ t.guilsinglleft = 333;
+ t.guilsinglright = 333;
+ t.fi = 500;
+ t.fl = 500;
+ t.endash = 556;
+ t.dagger = 556;
+ t.daggerdbl = 556;
+ t.periodcentered = 278;
+ t.paragraph = 537;
+ t.bullet = 350;
+ t.quotesinglbase = 222;
+ t.quotedblbase = 333;
+ t.quotedblright = 333;
+ t.guillemotright = 556;
+ t.ellipsis = 1000;
+ t.perthousand = 1000;
+ t.questiondown = 611;
+ t.grave = 333;
+ t.acute = 333;
+ t.circumflex = 333;
+ t.tilde = 333;
+ t.macron = 333;
+ t.breve = 333;
+ t.dotaccent = 333;
+ t.dieresis = 333;
+ t.ring = 333;
+ t.cedilla = 333;
+ t.hungarumlaut = 333;
+ t.ogonek = 333;
+ t.caron = 333;
+ t.emdash = 1000;
+ t.AE = 1000;
+ t.ordfeminine = 370;
+ t.Lslash = 556;
+ t.Oslash = 778;
+ t.OE = 1000;
+ t.ordmasculine = 365;
+ t.ae = 889;
+ t.dotlessi = 278;
+ t.lslash = 222;
+ t.oslash = 611;
+ t.oe = 944;
+ t.germandbls = 611;
+ t.Idieresis = 278;
+ t.eacute = 556;
+ t.abreve = 556;
+ t.uhungarumlaut = 556;
+ t.ecaron = 556;
+ t.Ydieresis = 667;
+ t.divide = 584;
+ t.Yacute = 667;
+ t.Acircumflex = 667;
+ t.aacute = 556;
+ t.Ucircumflex = 722;
+ t.yacute = 500;
+ t.scommaaccent = 500;
+ t.ecircumflex = 556;
+ t.Uring = 722;
+ t.Udieresis = 722;
+ t.aogonek = 556;
+ t.Uacute = 722;
+ t.uogonek = 556;
+ t.Edieresis = 667;
+ t.Dcroat = 722;
+ t.commaaccent = 250;
+ t.copyright = 737;
+ t.Emacron = 667;
+ t.ccaron = 500;
+ t.aring = 556;
+ t.Ncommaaccent = 722;
+ t.lacute = 222;
+ t.agrave = 556;
+ t.Tcommaaccent = 611;
+ t.Cacute = 722;
+ t.atilde = 556;
+ t.Edotaccent = 667;
+ t.scaron = 500;
+ t.scedilla = 500;
+ t.iacute = 278;
+ t.lozenge = 471;
+ t.Rcaron = 722;
+ t.Gcommaaccent = 778;
+ t.ucircumflex = 556;
+ t.acircumflex = 556;
+ t.Amacron = 667;
+ t.rcaron = 333;
+ t.ccedilla = 500;
+ t.Zdotaccent = 611;
+ t.Thorn = 667;
+ t.Omacron = 778;
+ t.Racute = 722;
+ t.Sacute = 667;
+ t.dcaron = 643;
+ t.Umacron = 722;
+ t.uring = 556;
+ t.threesuperior = 333;
+ t.Ograve = 778;
+ t.Agrave = 667;
+ t.Abreve = 667;
+ t.multiply = 584;
+ t.uacute = 556;
+ t.Tcaron = 611;
+ t.partialdiff = 476;
+ t.ydieresis = 500;
+ t.Nacute = 722;
+ t.icircumflex = 278;
+ t.Ecircumflex = 667;
+ t.adieresis = 556;
+ t.edieresis = 556;
+ t.cacute = 500;
+ t.nacute = 556;
+ t.umacron = 556;
+ t.Ncaron = 722;
+ t.Iacute = 278;
+ t.plusminus = 584;
+ t.brokenbar = 260;
+ t.registered = 737;
+ t.Gbreve = 778;
+ t.Idotaccent = 278;
+ t.summation = 600;
+ t.Egrave = 667;
+ t.racute = 333;
+ t.omacron = 556;
+ t.Zacute = 611;
+ t.Zcaron = 611;
+ t.greaterequal = 549;
+ t.Eth = 722;
+ t.Ccedilla = 722;
+ t.lcommaaccent = 222;
+ t.tcaron = 317;
+ t.eogonek = 556;
+ t.Uogonek = 722;
+ t.Aacute = 667;
+ t.Adieresis = 667;
+ t.egrave = 556;
+ t.zacute = 500;
+ t.iogonek = 222;
+ t.Oacute = 778;
+ t.oacute = 556;
+ t.amacron = 556;
+ t.sacute = 500;
+ t.idieresis = 278;
+ t.Ocircumflex = 778;
+ t.Ugrave = 722;
+ t.Delta = 612;
+ t.thorn = 556;
+ t.twosuperior = 333;
+ t.Odieresis = 778;
+ t.mu = 556;
+ t.igrave = 278;
+ t.ohungarumlaut = 556;
+ t.Eogonek = 667;
+ t.dcroat = 556;
+ t.threequarters = 834;
+ t.Scedilla = 667;
+ t.lcaron = 299;
+ t.Kcommaaccent = 667;
+ t.Lacute = 556;
+ t.trademark = 1000;
+ t.edotaccent = 556;
+ t.Igrave = 278;
+ t.Imacron = 278;
+ t.Lcaron = 556;
+ t.onehalf = 834;
+ t.lessequal = 549;
+ t.ocircumflex = 556;
+ t.ntilde = 556;
+ t.Uhungarumlaut = 722;
+ t.Eacute = 667;
+ t.emacron = 556;
+ t.gbreve = 556;
+ t.onequarter = 834;
+ t.Scaron = 667;
+ t.Scommaaccent = 667;
+ t.Ohungarumlaut = 778;
+ t.degree = 400;
+ t.ograve = 556;
+ t.Ccaron = 722;
+ t.ugrave = 556;
+ t.radical = 453;
+ t.Dcaron = 722;
+ t.rcommaaccent = 333;
+ t.Ntilde = 722;
+ t.otilde = 556;
+ t.Rcommaaccent = 722;
+ t.Lcommaaccent = 556;
+ t.Atilde = 667;
+ t.Aogonek = 667;
+ t.Aring = 667;
+ t.Otilde = 778;
+ t.zdotaccent = 500;
+ t.Ecaron = 667;
+ t.Iogonek = 278;
+ t.kcommaaccent = 500;
+ t.minus = 584;
+ t.Icircumflex = 278;
+ t.ncaron = 556;
+ t.tcommaaccent = 278;
+ t.logicalnot = 584;
+ t.odieresis = 556;
+ t.udieresis = 556;
+ t.notequal = 549;
+ t.gcommaaccent = 556;
+ t.eth = 556;
+ t.zcaron = 500;
+ t.ncommaaccent = 556;
+ t.onesuperior = 333;
+ t.imacron = 278;
+ t.Euro = 556;
+ });
+ t.Symbol = getLookupTableFactory(function (t) {
+ t.space = 250;
+ t.exclam = 333;
+ t.universal = 713;
+ t.numbersign = 500;
+ t.existential = 549;
+ t.percent = 833;
+ t.ampersand = 778;
+ t.suchthat = 439;
+ t.parenleft = 333;
+ t.parenright = 333;
+ t.asteriskmath = 500;
+ t.plus = 549;
+ t.comma = 250;
+ t.minus = 549;
+ t.period = 250;
+ t.slash = 278;
+ t.zero = 500;
+ t.one = 500;
+ t.two = 500;
+ t.three = 500;
+ t.four = 500;
+ t.five = 500;
+ t.six = 500;
+ t.seven = 500;
+ t.eight = 500;
+ t.nine = 500;
+ t.colon = 278;
+ t.semicolon = 278;
+ t.less = 549;
+ t.equal = 549;
+ t.greater = 549;
+ t.question = 444;
+ t.congruent = 549;
+ t.Alpha = 722;
+ t.Beta = 667;
+ t.Chi = 722;
+ t.Delta = 612;
+ t.Epsilon = 611;
+ t.Phi = 763;
+ t.Gamma = 603;
+ t.Eta = 722;
+ t.Iota = 333;
+ t.theta1 = 631;
+ t.Kappa = 722;
+ t.Lambda = 686;
+ t.Mu = 889;
+ t.Nu = 722;
+ t.Omicron = 722;
+ t.Pi = 768;
+ t.Theta = 741;
+ t.Rho = 556;
+ t.Sigma = 592;
+ t.Tau = 611;
+ t.Upsilon = 690;
+ t.sigma1 = 439;
+ t.Omega = 768;
+ t.Xi = 645;
+ t.Psi = 795;
+ t.Zeta = 611;
+ t.bracketleft = 333;
+ t.therefore = 863;
+ t.bracketright = 333;
+ t.perpendicular = 658;
+ t.underscore = 500;
+ t.radicalex = 500;
+ t.alpha = 631;
+ t.beta = 549;
+ t.chi = 549;
+ t.delta = 494;
+ t.epsilon = 439;
+ t.phi = 521;
+ t.gamma = 411;
+ t.eta = 603;
+ t.iota = 329;
+ t.phi1 = 603;
+ t.kappa = 549;
+ t.lambda = 549;
+ t.mu = 576;
+ t.nu = 521;
+ t.omicron = 549;
+ t.pi = 549;
+ t.theta = 521;
+ t.rho = 549;
+ t.sigma = 603;
+ t.tau = 439;
+ t.upsilon = 576;
+ t.omega1 = 713;
+ t.omega = 686;
+ t.xi = 493;
+ t.psi = 686;
+ t.zeta = 494;
+ t.braceleft = 480;
+ t.bar = 200;
+ t.braceright = 480;
+ t.similar = 549;
+ t.Euro = 750;
+ t.Upsilon1 = 620;
+ t.minute = 247;
+ t.lessequal = 549;
+ t.fraction = 167;
+ t.infinity = 713;
+ t.florin = 500;
+ t.club = 753;
+ t.diamond = 753;
+ t.heart = 753;
+ t.spade = 753;
+ t.arrowboth = 1042;
+ t.arrowleft = 987;
+ t.arrowup = 603;
+ t.arrowright = 987;
+ t.arrowdown = 603;
+ t.degree = 400;
+ t.plusminus = 549;
+ t.second = 411;
+ t.greaterequal = 549;
+ t.multiply = 549;
+ t.proportional = 713;
+ t.partialdiff = 494;
+ t.bullet = 460;
+ t.divide = 549;
+ t.notequal = 549;
+ t.equivalence = 549;
+ t.approxequal = 549;
+ t.ellipsis = 1000;
+ t.arrowvertex = 603;
+ t.arrowhorizex = 1000;
+ t.carriagereturn = 658;
+ t.aleph = 823;
+ t.Ifraktur = 686;
+ t.Rfraktur = 795;
+ t.weierstrass = 987;
+ t.circlemultiply = 768;
+ t.circleplus = 768;
+ t.emptyset = 823;
+ t.intersection = 768;
+ t.union = 768;
+ t.propersuperset = 713;
+ t.reflexsuperset = 713;
+ t.notsubset = 713;
+ t.propersubset = 713;
+ t.reflexsubset = 713;
+ t.element = 713;
+ t.notelement = 713;
+ t.angle = 768;
+ t.gradient = 713;
+ t.registerserif = 790;
+ t.copyrightserif = 790;
+ t.trademarkserif = 890;
+ t.product = 823;
+ t.radical = 549;
+ t.dotmath = 250;
+ t.logicalnot = 713;
+ t.logicaland = 603;
+ t.logicalor = 603;
+ t.arrowdblboth = 1042;
+ t.arrowdblleft = 987;
+ t.arrowdblup = 603;
+ t.arrowdblright = 987;
+ t.arrowdbldown = 603;
+ t.lozenge = 494;
+ t.angleleft = 329;
+ t.registersans = 790;
+ t.copyrightsans = 790;
+ t.trademarksans = 786;
+ t.summation = 713;
+ t.parenlefttp = 384;
+ t.parenleftex = 384;
+ t.parenleftbt = 384;
+ t.bracketlefttp = 384;
+ t.bracketleftex = 384;
+ t.bracketleftbt = 384;
+ t.bracelefttp = 494;
+ t.braceleftmid = 494;
+ t.braceleftbt = 494;
+ t.braceex = 494;
+ t.angleright = 329;
+ t.integral = 274;
+ t.integraltp = 686;
+ t.integralex = 686;
+ t.integralbt = 686;
+ t.parenrighttp = 384;
+ t.parenrightex = 384;
+ t.parenrightbt = 384;
+ t.bracketrighttp = 384;
+ t.bracketrightex = 384;
+ t.bracketrightbt = 384;
+ t.bracerighttp = 494;
+ t.bracerightmid = 494;
+ t.bracerightbt = 494;
+ t.apple = 790;
+ });
+ t["Times-Roman"] = getLookupTableFactory(function (t) {
+ t.space = 250;
+ t.exclam = 333;
+ t.quotedbl = 408;
+ t.numbersign = 500;
+ t.dollar = 500;
+ t.percent = 833;
+ t.ampersand = 778;
+ t.quoteright = 333;
+ t.parenleft = 333;
+ t.parenright = 333;
+ t.asterisk = 500;
+ t.plus = 564;
+ t.comma = 250;
+ t.hyphen = 333;
+ t.period = 250;
+ t.slash = 278;
+ t.zero = 500;
+ t.one = 500;
+ t.two = 500;
+ t.three = 500;
+ t.four = 500;
+ t.five = 500;
+ t.six = 500;
+ t.seven = 500;
+ t.eight = 500;
+ t.nine = 500;
+ t.colon = 278;
+ t.semicolon = 278;
+ t.less = 564;
+ t.equal = 564;
+ t.greater = 564;
+ t.question = 444;
+ t.at = 921;
+ t.A = 722;
+ t.B = 667;
+ t.C = 667;
+ t.D = 722;
+ t.E = 611;
+ t.F = 556;
+ t.G = 722;
+ t.H = 722;
+ t.I = 333;
+ t.J = 389;
+ t.K = 722;
+ t.L = 611;
+ t.M = 889;
+ t.N = 722;
+ t.O = 722;
+ t.P = 556;
+ t.Q = 722;
+ t.R = 667;
+ t.S = 556;
+ t.T = 611;
+ t.U = 722;
+ t.V = 722;
+ t.W = 944;
+ t.X = 722;
+ t.Y = 722;
+ t.Z = 611;
+ t.bracketleft = 333;
+ t.backslash = 278;
+ t.bracketright = 333;
+ t.asciicircum = 469;
+ t.underscore = 500;
+ t.quoteleft = 333;
+ t.a = 444;
+ t.b = 500;
+ t.c = 444;
+ t.d = 500;
+ t.e = 444;
+ t.f = 333;
+ t.g = 500;
+ t.h = 500;
+ t.i = 278;
+ t.j = 278;
+ t.k = 500;
+ t.l = 278;
+ t.m = 778;
+ t.n = 500;
+ t.o = 500;
+ t.p = 500;
+ t.q = 500;
+ t.r = 333;
+ t.s = 389;
+ t.t = 278;
+ t.u = 500;
+ t.v = 500;
+ t.w = 722;
+ t.x = 500;
+ t.y = 500;
+ t.z = 444;
+ t.braceleft = 480;
+ t.bar = 200;
+ t.braceright = 480;
+ t.asciitilde = 541;
+ t.exclamdown = 333;
+ t.cent = 500;
+ t.sterling = 500;
+ t.fraction = 167;
+ t.yen = 500;
+ t.florin = 500;
+ t.section = 500;
+ t.currency = 500;
+ t.quotesingle = 180;
+ t.quotedblleft = 444;
+ t.guillemotleft = 500;
+ t.guilsinglleft = 333;
+ t.guilsinglright = 333;
+ t.fi = 556;
+ t.fl = 556;
+ t.endash = 500;
+ t.dagger = 500;
+ t.daggerdbl = 500;
+ t.periodcentered = 250;
+ t.paragraph = 453;
+ t.bullet = 350;
+ t.quotesinglbase = 333;
+ t.quotedblbase = 444;
+ t.quotedblright = 444;
+ t.guillemotright = 500;
+ t.ellipsis = 1000;
+ t.perthousand = 1000;
+ t.questiondown = 444;
+ t.grave = 333;
+ t.acute = 333;
+ t.circumflex = 333;
+ t.tilde = 333;
+ t.macron = 333;
+ t.breve = 333;
+ t.dotaccent = 333;
+ t.dieresis = 333;
+ t.ring = 333;
+ t.cedilla = 333;
+ t.hungarumlaut = 333;
+ t.ogonek = 333;
+ t.caron = 333;
+ t.emdash = 1000;
+ t.AE = 889;
+ t.ordfeminine = 276;
+ t.Lslash = 611;
+ t.Oslash = 722;
+ t.OE = 889;
+ t.ordmasculine = 310;
+ t.ae = 667;
+ t.dotlessi = 278;
+ t.lslash = 278;
+ t.oslash = 500;
+ t.oe = 722;
+ t.germandbls = 500;
+ t.Idieresis = 333;
+ t.eacute = 444;
+ t.abreve = 444;
+ t.uhungarumlaut = 500;
+ t.ecaron = 444;
+ t.Ydieresis = 722;
+ t.divide = 564;
+ t.Yacute = 722;
+ t.Acircumflex = 722;
+ t.aacute = 444;
+ t.Ucircumflex = 722;
+ t.yacute = 500;
+ t.scommaaccent = 389;
+ t.ecircumflex = 444;
+ t.Uring = 722;
+ t.Udieresis = 722;
+ t.aogonek = 444;
+ t.Uacute = 722;
+ t.uogonek = 500;
+ t.Edieresis = 611;
+ t.Dcroat = 722;
+ t.commaaccent = 250;
+ t.copyright = 760;
+ t.Emacron = 611;
+ t.ccaron = 444;
+ t.aring = 444;
+ t.Ncommaaccent = 722;
+ t.lacute = 278;
+ t.agrave = 444;
+ t.Tcommaaccent = 611;
+ t.Cacute = 667;
+ t.atilde = 444;
+ t.Edotaccent = 611;
+ t.scaron = 389;
+ t.scedilla = 389;
+ t.iacute = 278;
+ t.lozenge = 471;
+ t.Rcaron = 667;
+ t.Gcommaaccent = 722;
+ t.ucircumflex = 500;
+ t.acircumflex = 444;
+ t.Amacron = 722;
+ t.rcaron = 333;
+ t.ccedilla = 444;
+ t.Zdotaccent = 611;
+ t.Thorn = 556;
+ t.Omacron = 722;
+ t.Racute = 667;
+ t.Sacute = 556;
+ t.dcaron = 588;
+ t.Umacron = 722;
+ t.uring = 500;
+ t.threesuperior = 300;
+ t.Ograve = 722;
+ t.Agrave = 722;
+ t.Abreve = 722;
+ t.multiply = 564;
+ t.uacute = 500;
+ t.Tcaron = 611;
+ t.partialdiff = 476;
+ t.ydieresis = 500;
+ t.Nacute = 722;
+ t.icircumflex = 278;
+ t.Ecircumflex = 611;
+ t.adieresis = 444;
+ t.edieresis = 444;
+ t.cacute = 444;
+ t.nacute = 500;
+ t.umacron = 500;
+ t.Ncaron = 722;
+ t.Iacute = 333;
+ t.plusminus = 564;
+ t.brokenbar = 200;
+ t.registered = 760;
+ t.Gbreve = 722;
+ t.Idotaccent = 333;
+ t.summation = 600;
+ t.Egrave = 611;
+ t.racute = 333;
+ t.omacron = 500;
+ t.Zacute = 611;
+ t.Zcaron = 611;
+ t.greaterequal = 549;
+ t.Eth = 722;
+ t.Ccedilla = 667;
+ t.lcommaaccent = 278;
+ t.tcaron = 326;
+ t.eogonek = 444;
+ t.Uogonek = 722;
+ t.Aacute = 722;
+ t.Adieresis = 722;
+ t.egrave = 444;
+ t.zacute = 444;
+ t.iogonek = 278;
+ t.Oacute = 722;
+ t.oacute = 500;
+ t.amacron = 444;
+ t.sacute = 389;
+ t.idieresis = 278;
+ t.Ocircumflex = 722;
+ t.Ugrave = 722;
+ t.Delta = 612;
+ t.thorn = 500;
+ t.twosuperior = 300;
+ t.Odieresis = 722;
+ t.mu = 500;
+ t.igrave = 278;
+ t.ohungarumlaut = 500;
+ t.Eogonek = 611;
+ t.dcroat = 500;
+ t.threequarters = 750;
+ t.Scedilla = 556;
+ t.lcaron = 344;
+ t.Kcommaaccent = 722;
+ t.Lacute = 611;
+ t.trademark = 980;
+ t.edotaccent = 444;
+ t.Igrave = 333;
+ t.Imacron = 333;
+ t.Lcaron = 611;
+ t.onehalf = 750;
+ t.lessequal = 549;
+ t.ocircumflex = 500;
+ t.ntilde = 500;
+ t.Uhungarumlaut = 722;
+ t.Eacute = 611;
+ t.emacron = 444;
+ t.gbreve = 500;
+ t.onequarter = 750;
+ t.Scaron = 556;
+ t.Scommaaccent = 556;
+ t.Ohungarumlaut = 722;
+ t.degree = 400;
+ t.ograve = 500;
+ t.Ccaron = 667;
+ t.ugrave = 500;
+ t.radical = 453;
+ t.Dcaron = 722;
+ t.rcommaaccent = 333;
+ t.Ntilde = 722;
+ t.otilde = 500;
+ t.Rcommaaccent = 667;
+ t.Lcommaaccent = 611;
+ t.Atilde = 722;
+ t.Aogonek = 722;
+ t.Aring = 722;
+ t.Otilde = 722;
+ t.zdotaccent = 444;
+ t.Ecaron = 611;
+ t.Iogonek = 333;
+ t.kcommaaccent = 500;
+ t.minus = 564;
+ t.Icircumflex = 333;
+ t.ncaron = 500;
+ t.tcommaaccent = 278;
+ t.logicalnot = 564;
+ t.odieresis = 500;
+ t.udieresis = 500;
+ t.notequal = 549;
+ t.gcommaaccent = 500;
+ t.eth = 500;
+ t.zcaron = 444;
+ t.ncommaaccent = 500;
+ t.onesuperior = 300;
+ t.imacron = 278;
+ t.Euro = 500;
+ });
+ t["Times-Bold"] = getLookupTableFactory(function (t) {
+ t.space = 250;
+ t.exclam = 333;
+ t.quotedbl = 555;
+ t.numbersign = 500;
+ t.dollar = 500;
+ t.percent = 1000;
+ t.ampersand = 833;
+ t.quoteright = 333;
+ t.parenleft = 333;
+ t.parenright = 333;
+ t.asterisk = 500;
+ t.plus = 570;
+ t.comma = 250;
+ t.hyphen = 333;
+ t.period = 250;
+ t.slash = 278;
+ t.zero = 500;
+ t.one = 500;
+ t.two = 500;
+ t.three = 500;
+ t.four = 500;
+ t.five = 500;
+ t.six = 500;
+ t.seven = 500;
+ t.eight = 500;
+ t.nine = 500;
+ t.colon = 333;
+ t.semicolon = 333;
+ t.less = 570;
+ t.equal = 570;
+ t.greater = 570;
+ t.question = 500;
+ t.at = 930;
+ t.A = 722;
+ t.B = 667;
+ t.C = 722;
+ t.D = 722;
+ t.E = 667;
+ t.F = 611;
+ t.G = 778;
+ t.H = 778;
+ t.I = 389;
+ t.J = 500;
+ t.K = 778;
+ t.L = 667;
+ t.M = 944;
+ t.N = 722;
+ t.O = 778;
+ t.P = 611;
+ t.Q = 778;
+ t.R = 722;
+ t.S = 556;
+ t.T = 667;
+ t.U = 722;
+ t.V = 722;
+ t.W = 1000;
+ t.X = 722;
+ t.Y = 722;
+ t.Z = 667;
+ t.bracketleft = 333;
+ t.backslash = 278;
+ t.bracketright = 333;
+ t.asciicircum = 581;
+ t.underscore = 500;
+ t.quoteleft = 333;
+ t.a = 500;
+ t.b = 556;
+ t.c = 444;
+ t.d = 556;
+ t.e = 444;
+ t.f = 333;
+ t.g = 500;
+ t.h = 556;
+ t.i = 278;
+ t.j = 333;
+ t.k = 556;
+ t.l = 278;
+ t.m = 833;
+ t.n = 556;
+ t.o = 500;
+ t.p = 556;
+ t.q = 556;
+ t.r = 444;
+ t.s = 389;
+ t.t = 333;
+ t.u = 556;
+ t.v = 500;
+ t.w = 722;
+ t.x = 500;
+ t.y = 500;
+ t.z = 444;
+ t.braceleft = 394;
+ t.bar = 220;
+ t.braceright = 394;
+ t.asciitilde = 520;
+ t.exclamdown = 333;
+ t.cent = 500;
+ t.sterling = 500;
+ t.fraction = 167;
+ t.yen = 500;
+ t.florin = 500;
+ t.section = 500;
+ t.currency = 500;
+ t.quotesingle = 278;
+ t.quotedblleft = 500;
+ t.guillemotleft = 500;
+ t.guilsinglleft = 333;
+ t.guilsinglright = 333;
+ t.fi = 556;
+ t.fl = 556;
+ t.endash = 500;
+ t.dagger = 500;
+ t.daggerdbl = 500;
+ t.periodcentered = 250;
+ t.paragraph = 540;
+ t.bullet = 350;
+ t.quotesinglbase = 333;
+ t.quotedblbase = 500;
+ t.quotedblright = 500;
+ t.guillemotright = 500;
+ t.ellipsis = 1000;
+ t.perthousand = 1000;
+ t.questiondown = 500;
+ t.grave = 333;
+ t.acute = 333;
+ t.circumflex = 333;
+ t.tilde = 333;
+ t.macron = 333;
+ t.breve = 333;
+ t.dotaccent = 333;
+ t.dieresis = 333;
+ t.ring = 333;
+ t.cedilla = 333;
+ t.hungarumlaut = 333;
+ t.ogonek = 333;
+ t.caron = 333;
+ t.emdash = 1000;
+ t.AE = 1000;
+ t.ordfeminine = 300;
+ t.Lslash = 667;
+ t.Oslash = 778;
+ t.OE = 1000;
+ t.ordmasculine = 330;
+ t.ae = 722;
+ t.dotlessi = 278;
+ t.lslash = 278;
+ t.oslash = 500;
+ t.oe = 722;
+ t.germandbls = 556;
+ t.Idieresis = 389;
+ t.eacute = 444;
+ t.abreve = 500;
+ t.uhungarumlaut = 556;
+ t.ecaron = 444;
+ t.Ydieresis = 722;
+ t.divide = 570;
+ t.Yacute = 722;
+ t.Acircumflex = 722;
+ t.aacute = 500;
+ t.Ucircumflex = 722;
+ t.yacute = 500;
+ t.scommaaccent = 389;
+ t.ecircumflex = 444;
+ t.Uring = 722;
+ t.Udieresis = 722;
+ t.aogonek = 500;
+ t.Uacute = 722;
+ t.uogonek = 556;
+ t.Edieresis = 667;
+ t.Dcroat = 722;
+ t.commaaccent = 250;
+ t.copyright = 747;
+ t.Emacron = 667;
+ t.ccaron = 444;
+ t.aring = 500;
+ t.Ncommaaccent = 722;
+ t.lacute = 278;
+ t.agrave = 500;
+ t.Tcommaaccent = 667;
+ t.Cacute = 722;
+ t.atilde = 500;
+ t.Edotaccent = 667;
+ t.scaron = 389;
+ t.scedilla = 389;
+ t.iacute = 278;
+ t.lozenge = 494;
+ t.Rcaron = 722;
+ t.Gcommaaccent = 778;
+ t.ucircumflex = 556;
+ t.acircumflex = 500;
+ t.Amacron = 722;
+ t.rcaron = 444;
+ t.ccedilla = 444;
+ t.Zdotaccent = 667;
+ t.Thorn = 611;
+ t.Omacron = 778;
+ t.Racute = 722;
+ t.Sacute = 556;
+ t.dcaron = 672;
+ t.Umacron = 722;
+ t.uring = 556;
+ t.threesuperior = 300;
+ t.Ograve = 778;
+ t.Agrave = 722;
+ t.Abreve = 722;
+ t.multiply = 570;
+ t.uacute = 556;
+ t.Tcaron = 667;
+ t.partialdiff = 494;
+ t.ydieresis = 500;
+ t.Nacute = 722;
+ t.icircumflex = 278;
+ t.Ecircumflex = 667;
+ t.adieresis = 500;
+ t.edieresis = 444;
+ t.cacute = 444;
+ t.nacute = 556;
+ t.umacron = 556;
+ t.Ncaron = 722;
+ t.Iacute = 389;
+ t.plusminus = 570;
+ t.brokenbar = 220;
+ t.registered = 747;
+ t.Gbreve = 778;
+ t.Idotaccent = 389;
+ t.summation = 600;
+ t.Egrave = 667;
+ t.racute = 444;
+ t.omacron = 500;
+ t.Zacute = 667;
+ t.Zcaron = 667;
+ t.greaterequal = 549;
+ t.Eth = 722;
+ t.Ccedilla = 722;
+ t.lcommaaccent = 278;
+ t.tcaron = 416;
+ t.eogonek = 444;
+ t.Uogonek = 722;
+ t.Aacute = 722;
+ t.Adieresis = 722;
+ t.egrave = 444;
+ t.zacute = 444;
+ t.iogonek = 278;
+ t.Oacute = 778;
+ t.oacute = 500;
+ t.amacron = 500;
+ t.sacute = 389;
+ t.idieresis = 278;
+ t.Ocircumflex = 778;
+ t.Ugrave = 722;
+ t.Delta = 612;
+ t.thorn = 556;
+ t.twosuperior = 300;
+ t.Odieresis = 778;
+ t.mu = 556;
+ t.igrave = 278;
+ t.ohungarumlaut = 500;
+ t.Eogonek = 667;
+ t.dcroat = 556;
+ t.threequarters = 750;
+ t.Scedilla = 556;
+ t.lcaron = 394;
+ t.Kcommaaccent = 778;
+ t.Lacute = 667;
+ t.trademark = 1000;
+ t.edotaccent = 444;
+ t.Igrave = 389;
+ t.Imacron = 389;
+ t.Lcaron = 667;
+ t.onehalf = 750;
+ t.lessequal = 549;
+ t.ocircumflex = 500;
+ t.ntilde = 556;
+ t.Uhungarumlaut = 722;
+ t.Eacute = 667;
+ t.emacron = 444;
+ t.gbreve = 500;
+ t.onequarter = 750;
+ t.Scaron = 556;
+ t.Scommaaccent = 556;
+ t.Ohungarumlaut = 778;
+ t.degree = 400;
+ t.ograve = 500;
+ t.Ccaron = 722;
+ t.ugrave = 556;
+ t.radical = 549;
+ t.Dcaron = 722;
+ t.rcommaaccent = 444;
+ t.Ntilde = 722;
+ t.otilde = 500;
+ t.Rcommaaccent = 722;
+ t.Lcommaaccent = 667;
+ t.Atilde = 722;
+ t.Aogonek = 722;
+ t.Aring = 722;
+ t.Otilde = 778;
+ t.zdotaccent = 444;
+ t.Ecaron = 667;
+ t.Iogonek = 389;
+ t.kcommaaccent = 556;
+ t.minus = 570;
+ t.Icircumflex = 389;
+ t.ncaron = 556;
+ t.tcommaaccent = 333;
+ t.logicalnot = 570;
+ t.odieresis = 500;
+ t.udieresis = 556;
+ t.notequal = 549;
+ t.gcommaaccent = 500;
+ t.eth = 500;
+ t.zcaron = 444;
+ t.ncommaaccent = 556;
+ t.onesuperior = 300;
+ t.imacron = 278;
+ t.Euro = 500;
+ });
+ t["Times-BoldItalic"] = getLookupTableFactory(function (t) {
+ t.space = 250;
+ t.exclam = 389;
+ t.quotedbl = 555;
+ t.numbersign = 500;
+ t.dollar = 500;
+ t.percent = 833;
+ t.ampersand = 778;
+ t.quoteright = 333;
+ t.parenleft = 333;
+ t.parenright = 333;
+ t.asterisk = 500;
+ t.plus = 570;
+ t.comma = 250;
+ t.hyphen = 333;
+ t.period = 250;
+ t.slash = 278;
+ t.zero = 500;
+ t.one = 500;
+ t.two = 500;
+ t.three = 500;
+ t.four = 500;
+ t.five = 500;
+ t.six = 500;
+ t.seven = 500;
+ t.eight = 500;
+ t.nine = 500;
+ t.colon = 333;
+ t.semicolon = 333;
+ t.less = 570;
+ t.equal = 570;
+ t.greater = 570;
+ t.question = 500;
+ t.at = 832;
+ t.A = 667;
+ t.B = 667;
+ t.C = 667;
+ t.D = 722;
+ t.E = 667;
+ t.F = 667;
+ t.G = 722;
+ t.H = 778;
+ t.I = 389;
+ t.J = 500;
+ t.K = 667;
+ t.L = 611;
+ t.M = 889;
+ t.N = 722;
+ t.O = 722;
+ t.P = 611;
+ t.Q = 722;
+ t.R = 667;
+ t.S = 556;
+ t.T = 611;
+ t.U = 722;
+ t.V = 667;
+ t.W = 889;
+ t.X = 667;
+ t.Y = 611;
+ t.Z = 611;
+ t.bracketleft = 333;
+ t.backslash = 278;
+ t.bracketright = 333;
+ t.asciicircum = 570;
+ t.underscore = 500;
+ t.quoteleft = 333;
+ t.a = 500;
+ t.b = 500;
+ t.c = 444;
+ t.d = 500;
+ t.e = 444;
+ t.f = 333;
+ t.g = 500;
+ t.h = 556;
+ t.i = 278;
+ t.j = 278;
+ t.k = 500;
+ t.l = 278;
+ t.m = 778;
+ t.n = 556;
+ t.o = 500;
+ t.p = 500;
+ t.q = 500;
+ t.r = 389;
+ t.s = 389;
+ t.t = 278;
+ t.u = 556;
+ t.v = 444;
+ t.w = 667;
+ t.x = 500;
+ t.y = 444;
+ t.z = 389;
+ t.braceleft = 348;
+ t.bar = 220;
+ t.braceright = 348;
+ t.asciitilde = 570;
+ t.exclamdown = 389;
+ t.cent = 500;
+ t.sterling = 500;
+ t.fraction = 167;
+ t.yen = 500;
+ t.florin = 500;
+ t.section = 500;
+ t.currency = 500;
+ t.quotesingle = 278;
+ t.quotedblleft = 500;
+ t.guillemotleft = 500;
+ t.guilsinglleft = 333;
+ t.guilsinglright = 333;
+ t.fi = 556;
+ t.fl = 556;
+ t.endash = 500;
+ t.dagger = 500;
+ t.daggerdbl = 500;
+ t.periodcentered = 250;
+ t.paragraph = 500;
+ t.bullet = 350;
+ t.quotesinglbase = 333;
+ t.quotedblbase = 500;
+ t.quotedblright = 500;
+ t.guillemotright = 500;
+ t.ellipsis = 1000;
+ t.perthousand = 1000;
+ t.questiondown = 500;
+ t.grave = 333;
+ t.acute = 333;
+ t.circumflex = 333;
+ t.tilde = 333;
+ t.macron = 333;
+ t.breve = 333;
+ t.dotaccent = 333;
+ t.dieresis = 333;
+ t.ring = 333;
+ t.cedilla = 333;
+ t.hungarumlaut = 333;
+ t.ogonek = 333;
+ t.caron = 333;
+ t.emdash = 1000;
+ t.AE = 944;
+ t.ordfeminine = 266;
+ t.Lslash = 611;
+ t.Oslash = 722;
+ t.OE = 944;
+ t.ordmasculine = 300;
+ t.ae = 722;
+ t.dotlessi = 278;
+ t.lslash = 278;
+ t.oslash = 500;
+ t.oe = 722;
+ t.germandbls = 500;
+ t.Idieresis = 389;
+ t.eacute = 444;
+ t.abreve = 500;
+ t.uhungarumlaut = 556;
+ t.ecaron = 444;
+ t.Ydieresis = 611;
+ t.divide = 570;
+ t.Yacute = 611;
+ t.Acircumflex = 667;
+ t.aacute = 500;
+ t.Ucircumflex = 722;
+ t.yacute = 444;
+ t.scommaaccent = 389;
+ t.ecircumflex = 444;
+ t.Uring = 722;
+ t.Udieresis = 722;
+ t.aogonek = 500;
+ t.Uacute = 722;
+ t.uogonek = 556;
+ t.Edieresis = 667;
+ t.Dcroat = 722;
+ t.commaaccent = 250;
+ t.copyright = 747;
+ t.Emacron = 667;
+ t.ccaron = 444;
+ t.aring = 500;
+ t.Ncommaaccent = 722;
+ t.lacute = 278;
+ t.agrave = 500;
+ t.Tcommaaccent = 611;
+ t.Cacute = 667;
+ t.atilde = 500;
+ t.Edotaccent = 667;
+ t.scaron = 389;
+ t.scedilla = 389;
+ t.iacute = 278;
+ t.lozenge = 494;
+ t.Rcaron = 667;
+ t.Gcommaaccent = 722;
+ t.ucircumflex = 556;
+ t.acircumflex = 500;
+ t.Amacron = 667;
+ t.rcaron = 389;
+ t.ccedilla = 444;
+ t.Zdotaccent = 611;
+ t.Thorn = 611;
+ t.Omacron = 722;
+ t.Racute = 667;
+ t.Sacute = 556;
+ t.dcaron = 608;
+ t.Umacron = 722;
+ t.uring = 556;
+ t.threesuperior = 300;
+ t.Ograve = 722;
+ t.Agrave = 667;
+ t.Abreve = 667;
+ t.multiply = 570;
+ t.uacute = 556;
+ t.Tcaron = 611;
+ t.partialdiff = 494;
+ t.ydieresis = 444;
+ t.Nacute = 722;
+ t.icircumflex = 278;
+ t.Ecircumflex = 667;
+ t.adieresis = 500;
+ t.edieresis = 444;
+ t.cacute = 444;
+ t.nacute = 556;
+ t.umacron = 556;
+ t.Ncaron = 722;
+ t.Iacute = 389;
+ t.plusminus = 570;
+ t.brokenbar = 220;
+ t.registered = 747;
+ t.Gbreve = 722;
+ t.Idotaccent = 389;
+ t.summation = 600;
+ t.Egrave = 667;
+ t.racute = 389;
+ t.omacron = 500;
+ t.Zacute = 611;
+ t.Zcaron = 611;
+ t.greaterequal = 549;
+ t.Eth = 722;
+ t.Ccedilla = 667;
+ t.lcommaaccent = 278;
+ t.tcaron = 366;
+ t.eogonek = 444;
+ t.Uogonek = 722;
+ t.Aacute = 667;
+ t.Adieresis = 667;
+ t.egrave = 444;
+ t.zacute = 389;
+ t.iogonek = 278;
+ t.Oacute = 722;
+ t.oacute = 500;
+ t.amacron = 500;
+ t.sacute = 389;
+ t.idieresis = 278;
+ t.Ocircumflex = 722;
+ t.Ugrave = 722;
+ t.Delta = 612;
+ t.thorn = 500;
+ t.twosuperior = 300;
+ t.Odieresis = 722;
+ t.mu = 576;
+ t.igrave = 278;
+ t.ohungarumlaut = 500;
+ t.Eogonek = 667;
+ t.dcroat = 500;
+ t.threequarters = 750;
+ t.Scedilla = 556;
+ t.lcaron = 382;
+ t.Kcommaaccent = 667;
+ t.Lacute = 611;
+ t.trademark = 1000;
+ t.edotaccent = 444;
+ t.Igrave = 389;
+ t.Imacron = 389;
+ t.Lcaron = 611;
+ t.onehalf = 750;
+ t.lessequal = 549;
+ t.ocircumflex = 500;
+ t.ntilde = 556;
+ t.Uhungarumlaut = 722;
+ t.Eacute = 667;
+ t.emacron = 444;
+ t.gbreve = 500;
+ t.onequarter = 750;
+ t.Scaron = 556;
+ t.Scommaaccent = 556;
+ t.Ohungarumlaut = 722;
+ t.degree = 400;
+ t.ograve = 500;
+ t.Ccaron = 667;
+ t.ugrave = 556;
+ t.radical = 549;
+ t.Dcaron = 722;
+ t.rcommaaccent = 389;
+ t.Ntilde = 722;
+ t.otilde = 500;
+ t.Rcommaaccent = 667;
+ t.Lcommaaccent = 611;
+ t.Atilde = 667;
+ t.Aogonek = 667;
+ t.Aring = 667;
+ t.Otilde = 722;
+ t.zdotaccent = 389;
+ t.Ecaron = 667;
+ t.Iogonek = 389;
+ t.kcommaaccent = 500;
+ t.minus = 606;
+ t.Icircumflex = 389;
+ t.ncaron = 556;
+ t.tcommaaccent = 278;
+ t.logicalnot = 606;
+ t.odieresis = 500;
+ t.udieresis = 556;
+ t.notequal = 549;
+ t.gcommaaccent = 500;
+ t.eth = 500;
+ t.zcaron = 389;
+ t.ncommaaccent = 556;
+ t.onesuperior = 300;
+ t.imacron = 278;
+ t.Euro = 500;
+ });
+ t["Times-Italic"] = getLookupTableFactory(function (t) {
+ t.space = 250;
+ t.exclam = 333;
+ t.quotedbl = 420;
+ t.numbersign = 500;
+ t.dollar = 500;
+ t.percent = 833;
+ t.ampersand = 778;
+ t.quoteright = 333;
+ t.parenleft = 333;
+ t.parenright = 333;
+ t.asterisk = 500;
+ t.plus = 675;
+ t.comma = 250;
+ t.hyphen = 333;
+ t.period = 250;
+ t.slash = 278;
+ t.zero = 500;
+ t.one = 500;
+ t.two = 500;
+ t.three = 500;
+ t.four = 500;
+ t.five = 500;
+ t.six = 500;
+ t.seven = 500;
+ t.eight = 500;
+ t.nine = 500;
+ t.colon = 333;
+ t.semicolon = 333;
+ t.less = 675;
+ t.equal = 675;
+ t.greater = 675;
+ t.question = 500;
+ t.at = 920;
+ t.A = 611;
+ t.B = 611;
+ t.C = 667;
+ t.D = 722;
+ t.E = 611;
+ t.F = 611;
+ t.G = 722;
+ t.H = 722;
+ t.I = 333;
+ t.J = 444;
+ t.K = 667;
+ t.L = 556;
+ t.M = 833;
+ t.N = 667;
+ t.O = 722;
+ t.P = 611;
+ t.Q = 722;
+ t.R = 611;
+ t.S = 500;
+ t.T = 556;
+ t.U = 722;
+ t.V = 611;
+ t.W = 833;
+ t.X = 611;
+ t.Y = 556;
+ t.Z = 556;
+ t.bracketleft = 389;
+ t.backslash = 278;
+ t.bracketright = 389;
+ t.asciicircum = 422;
+ t.underscore = 500;
+ t.quoteleft = 333;
+ t.a = 500;
+ t.b = 500;
+ t.c = 444;
+ t.d = 500;
+ t.e = 444;
+ t.f = 278;
+ t.g = 500;
+ t.h = 500;
+ t.i = 278;
+ t.j = 278;
+ t.k = 444;
+ t.l = 278;
+ t.m = 722;
+ t.n = 500;
+ t.o = 500;
+ t.p = 500;
+ t.q = 500;
+ t.r = 389;
+ t.s = 389;
+ t.t = 278;
+ t.u = 500;
+ t.v = 444;
+ t.w = 667;
+ t.x = 444;
+ t.y = 444;
+ t.z = 389;
+ t.braceleft = 400;
+ t.bar = 275;
+ t.braceright = 400;
+ t.asciitilde = 541;
+ t.exclamdown = 389;
+ t.cent = 500;
+ t.sterling = 500;
+ t.fraction = 167;
+ t.yen = 500;
+ t.florin = 500;
+ t.section = 500;
+ t.currency = 500;
+ t.quotesingle = 214;
+ t.quotedblleft = 556;
+ t.guillemotleft = 500;
+ t.guilsinglleft = 333;
+ t.guilsinglright = 333;
+ t.fi = 500;
+ t.fl = 500;
+ t.endash = 500;
+ t.dagger = 500;
+ t.daggerdbl = 500;
+ t.periodcentered = 250;
+ t.paragraph = 523;
+ t.bullet = 350;
+ t.quotesinglbase = 333;
+ t.quotedblbase = 556;
+ t.quotedblright = 556;
+ t.guillemotright = 500;
+ t.ellipsis = 889;
+ t.perthousand = 1000;
+ t.questiondown = 500;
+ t.grave = 333;
+ t.acute = 333;
+ t.circumflex = 333;
+ t.tilde = 333;
+ t.macron = 333;
+ t.breve = 333;
+ t.dotaccent = 333;
+ t.dieresis = 333;
+ t.ring = 333;
+ t.cedilla = 333;
+ t.hungarumlaut = 333;
+ t.ogonek = 333;
+ t.caron = 333;
+ t.emdash = 889;
+ t.AE = 889;
+ t.ordfeminine = 276;
+ t.Lslash = 556;
+ t.Oslash = 722;
+ t.OE = 944;
+ t.ordmasculine = 310;
+ t.ae = 667;
+ t.dotlessi = 278;
+ t.lslash = 278;
+ t.oslash = 500;
+ t.oe = 667;
+ t.germandbls = 500;
+ t.Idieresis = 333;
+ t.eacute = 444;
+ t.abreve = 500;
+ t.uhungarumlaut = 500;
+ t.ecaron = 444;
+ t.Ydieresis = 556;
+ t.divide = 675;
+ t.Yacute = 556;
+ t.Acircumflex = 611;
+ t.aacute = 500;
+ t.Ucircumflex = 722;
+ t.yacute = 444;
+ t.scommaaccent = 389;
+ t.ecircumflex = 444;
+ t.Uring = 722;
+ t.Udieresis = 722;
+ t.aogonek = 500;
+ t.Uacute = 722;
+ t.uogonek = 500;
+ t.Edieresis = 611;
+ t.Dcroat = 722;
+ t.commaaccent = 250;
+ t.copyright = 760;
+ t.Emacron = 611;
+ t.ccaron = 444;
+ t.aring = 500;
+ t.Ncommaaccent = 667;
+ t.lacute = 278;
+ t.agrave = 500;
+ t.Tcommaaccent = 556;
+ t.Cacute = 667;
+ t.atilde = 500;
+ t.Edotaccent = 611;
+ t.scaron = 389;
+ t.scedilla = 389;
+ t.iacute = 278;
+ t.lozenge = 471;
+ t.Rcaron = 611;
+ t.Gcommaaccent = 722;
+ t.ucircumflex = 500;
+ t.acircumflex = 500;
+ t.Amacron = 611;
+ t.rcaron = 389;
+ t.ccedilla = 444;
+ t.Zdotaccent = 556;
+ t.Thorn = 611;
+ t.Omacron = 722;
+ t.Racute = 611;
+ t.Sacute = 500;
+ t.dcaron = 544;
+ t.Umacron = 722;
+ t.uring = 500;
+ t.threesuperior = 300;
+ t.Ograve = 722;
+ t.Agrave = 611;
+ t.Abreve = 611;
+ t.multiply = 675;
+ t.uacute = 500;
+ t.Tcaron = 556;
+ t.partialdiff = 476;
+ t.ydieresis = 444;
+ t.Nacute = 667;
+ t.icircumflex = 278;
+ t.Ecircumflex = 611;
+ t.adieresis = 500;
+ t.edieresis = 444;
+ t.cacute = 444;
+ t.nacute = 500;
+ t.umacron = 500;
+ t.Ncaron = 667;
+ t.Iacute = 333;
+ t.plusminus = 675;
+ t.brokenbar = 275;
+ t.registered = 760;
+ t.Gbreve = 722;
+ t.Idotaccent = 333;
+ t.summation = 600;
+ t.Egrave = 611;
+ t.racute = 389;
+ t.omacron = 500;
+ t.Zacute = 556;
+ t.Zcaron = 556;
+ t.greaterequal = 549;
+ t.Eth = 722;
+ t.Ccedilla = 667;
+ t.lcommaaccent = 278;
+ t.tcaron = 300;
+ t.eogonek = 444;
+ t.Uogonek = 722;
+ t.Aacute = 611;
+ t.Adieresis = 611;
+ t.egrave = 444;
+ t.zacute = 389;
+ t.iogonek = 278;
+ t.Oacute = 722;
+ t.oacute = 500;
+ t.amacron = 500;
+ t.sacute = 389;
+ t.idieresis = 278;
+ t.Ocircumflex = 722;
+ t.Ugrave = 722;
+ t.Delta = 612;
+ t.thorn = 500;
+ t.twosuperior = 300;
+ t.Odieresis = 722;
+ t.mu = 500;
+ t.igrave = 278;
+ t.ohungarumlaut = 500;
+ t.Eogonek = 611;
+ t.dcroat = 500;
+ t.threequarters = 750;
+ t.Scedilla = 500;
+ t.lcaron = 300;
+ t.Kcommaaccent = 667;
+ t.Lacute = 556;
+ t.trademark = 980;
+ t.edotaccent = 444;
+ t.Igrave = 333;
+ t.Imacron = 333;
+ t.Lcaron = 611;
+ t.onehalf = 750;
+ t.lessequal = 549;
+ t.ocircumflex = 500;
+ t.ntilde = 500;
+ t.Uhungarumlaut = 722;
+ t.Eacute = 611;
+ t.emacron = 444;
+ t.gbreve = 500;
+ t.onequarter = 750;
+ t.Scaron = 500;
+ t.Scommaaccent = 500;
+ t.Ohungarumlaut = 722;
+ t.degree = 400;
+ t.ograve = 500;
+ t.Ccaron = 667;
+ t.ugrave = 500;
+ t.radical = 453;
+ t.Dcaron = 722;
+ t.rcommaaccent = 389;
+ t.Ntilde = 667;
+ t.otilde = 500;
+ t.Rcommaaccent = 611;
+ t.Lcommaaccent = 556;
+ t.Atilde = 611;
+ t.Aogonek = 611;
+ t.Aring = 611;
+ t.Otilde = 722;
+ t.zdotaccent = 389;
+ t.Ecaron = 611;
+ t.Iogonek = 333;
+ t.kcommaaccent = 444;
+ t.minus = 675;
+ t.Icircumflex = 333;
+ t.ncaron = 500;
+ t.tcommaaccent = 278;
+ t.logicalnot = 675;
+ t.odieresis = 500;
+ t.udieresis = 500;
+ t.notequal = 549;
+ t.gcommaaccent = 500;
+ t.eth = 500;
+ t.zcaron = 389;
+ t.ncommaaccent = 500;
+ t.onesuperior = 300;
+ t.imacron = 278;
+ t.Euro = 500;
+ });
+ t.ZapfDingbats = getLookupTableFactory(function (t) {
+ t.space = 278;
+ t.a1 = 974;
+ t.a2 = 961;
+ t.a202 = 974;
+ t.a3 = 980;
+ t.a4 = 719;
+ t.a5 = 789;
+ t.a119 = 790;
+ t.a118 = 791;
+ t.a117 = 690;
+ t.a11 = 960;
+ t.a12 = 939;
+ t.a13 = 549;
+ t.a14 = 855;
+ t.a15 = 911;
+ t.a16 = 933;
+ t.a105 = 911;
+ t.a17 = 945;
+ t.a18 = 974;
+ t.a19 = 755;
+ t.a20 = 846;
+ t.a21 = 762;
+ t.a22 = 761;
+ t.a23 = 571;
+ t.a24 = 677;
+ t.a25 = 763;
+ t.a26 = 760;
+ t.a27 = 759;
+ t.a28 = 754;
+ t.a6 = 494;
+ t.a7 = 552;
+ t.a8 = 537;
+ t.a9 = 577;
+ t.a10 = 692;
+ t.a29 = 786;
+ t.a30 = 788;
+ t.a31 = 788;
+ t.a32 = 790;
+ t.a33 = 793;
+ t.a34 = 794;
+ t.a35 = 816;
+ t.a36 = 823;
+ t.a37 = 789;
+ t.a38 = 841;
+ t.a39 = 823;
+ t.a40 = 833;
+ t.a41 = 816;
+ t.a42 = 831;
+ t.a43 = 923;
+ t.a44 = 744;
+ t.a45 = 723;
+ t.a46 = 749;
+ t.a47 = 790;
+ t.a48 = 792;
+ t.a49 = 695;
+ t.a50 = 776;
+ t.a51 = 768;
+ t.a52 = 792;
+ t.a53 = 759;
+ t.a54 = 707;
+ t.a55 = 708;
+ t.a56 = 682;
+ t.a57 = 701;
+ t.a58 = 826;
+ t.a59 = 815;
+ t.a60 = 789;
+ t.a61 = 789;
+ t.a62 = 707;
+ t.a63 = 687;
+ t.a64 = 696;
+ t.a65 = 689;
+ t.a66 = 786;
+ t.a67 = 787;
+ t.a68 = 713;
+ t.a69 = 791;
+ t.a70 = 785;
+ t.a71 = 791;
+ t.a72 = 873;
+ t.a73 = 761;
+ t.a74 = 762;
+ t.a203 = 762;
+ t.a75 = 759;
+ t.a204 = 759;
+ t.a76 = 892;
+ t.a77 = 892;
+ t.a78 = 788;
+ t.a79 = 784;
+ t.a81 = 438;
+ t.a82 = 138;
+ t.a83 = 277;
+ t.a84 = 415;
+ t.a97 = 392;
+ t.a98 = 392;
+ t.a99 = 668;
+ t.a100 = 668;
+ t.a89 = 390;
+ t.a90 = 390;
+ t.a93 = 317;
+ t.a94 = 317;
+ t.a91 = 276;
+ t.a92 = 276;
+ t.a205 = 509;
+ t.a85 = 509;
+ t.a206 = 410;
+ t.a86 = 410;
+ t.a87 = 234;
+ t.a88 = 234;
+ t.a95 = 334;
+ t.a96 = 334;
+ t.a101 = 732;
+ t.a102 = 544;
+ t.a103 = 544;
+ t.a104 = 910;
+ t.a106 = 667;
+ t.a107 = 760;
+ t.a108 = 760;
+ t.a112 = 776;
+ t.a111 = 595;
+ t.a110 = 694;
+ t.a109 = 626;
+ t.a120 = 788;
+ t.a121 = 788;
+ t.a122 = 788;
+ t.a123 = 788;
+ t.a124 = 788;
+ t.a125 = 788;
+ t.a126 = 788;
+ t.a127 = 788;
+ t.a128 = 788;
+ t.a129 = 788;
+ t.a130 = 788;
+ t.a131 = 788;
+ t.a132 = 788;
+ t.a133 = 788;
+ t.a134 = 788;
+ t.a135 = 788;
+ t.a136 = 788;
+ t.a137 = 788;
+ t.a138 = 788;
+ t.a139 = 788;
+ t.a140 = 788;
+ t.a141 = 788;
+ t.a142 = 788;
+ t.a143 = 788;
+ t.a144 = 788;
+ t.a145 = 788;
+ t.a146 = 788;
+ t.a147 = 788;
+ t.a148 = 788;
+ t.a149 = 788;
+ t.a150 = 788;
+ t.a151 = 788;
+ t.a152 = 788;
+ t.a153 = 788;
+ t.a154 = 788;
+ t.a155 = 788;
+ t.a156 = 788;
+ t.a157 = 788;
+ t.a158 = 788;
+ t.a159 = 788;
+ t.a160 = 894;
+ t.a161 = 838;
+ t.a163 = 1016;
+ t.a164 = 458;
+ t.a196 = 748;
+ t.a165 = 924;
+ t.a192 = 748;
+ t.a166 = 918;
+ t.a167 = 927;
+ t.a168 = 928;
+ t.a169 = 928;
+ t.a170 = 834;
+ t.a171 = 873;
+ t.a172 = 828;
+ t.a173 = 924;
+ t.a162 = 924;
+ t.a174 = 917;
+ t.a175 = 930;
+ t.a176 = 931;
+ t.a177 = 463;
+ t.a178 = 883;
+ t.a179 = 836;
+ t.a193 = 836;
+ t.a180 = 867;
+ t.a199 = 867;
+ t.a181 = 696;
+ t.a200 = 696;
+ t.a182 = 874;
+ t.a201 = 874;
+ t.a183 = 760;
+ t.a184 = 946;
+ t.a197 = 771;
+ t.a185 = 865;
+ t.a194 = 771;
+ t.a198 = 888;
+ t.a186 = 967;
+ t.a195 = 888;
+ t.a187 = 831;
+ t.a188 = 873;
+ t.a189 = 927;
+ t.a190 = 970;
+ t.a191 = 918;
+ });
+});
+const getFontBasicMetrics = getLookupTableFactory(function (t) {
+ t.Courier = {
+ ascent: 629,
+ descent: -157,
+ capHeight: 562,
+ xHeight: -426
+ };
+ t["Courier-Bold"] = {
+ ascent: 629,
+ descent: -157,
+ capHeight: 562,
+ xHeight: 439
+ };
+ t["Courier-Oblique"] = {
+ ascent: 629,
+ descent: -157,
+ capHeight: 562,
+ xHeight: 426
+ };
+ t["Courier-BoldOblique"] = {
+ ascent: 629,
+ descent: -157,
+ capHeight: 562,
+ xHeight: 426
+ };
+ t.Helvetica = {
+ ascent: 718,
+ descent: -207,
+ capHeight: 718,
+ xHeight: 523
+ };
+ t["Helvetica-Bold"] = {
+ ascent: 718,
+ descent: -207,
+ capHeight: 718,
+ xHeight: 532
+ };
+ t["Helvetica-Oblique"] = {
+ ascent: 718,
+ descent: -207,
+ capHeight: 718,
+ xHeight: 523
+ };
+ t["Helvetica-BoldOblique"] = {
+ ascent: 718,
+ descent: -207,
+ capHeight: 718,
+ xHeight: 532
+ };
+ t["Times-Roman"] = {
+ ascent: 683,
+ descent: -217,
+ capHeight: 662,
+ xHeight: 450
+ };
+ t["Times-Bold"] = {
+ ascent: 683,
+ descent: -217,
+ capHeight: 676,
+ xHeight: 461
+ };
+ t["Times-Italic"] = {
+ ascent: 683,
+ descent: -217,
+ capHeight: 653,
+ xHeight: 441
+ };
+ t["Times-BoldItalic"] = {
+ ascent: 683,
+ descent: -217,
+ capHeight: 669,
+ xHeight: 462
+ };
+ t.Symbol = {
+ ascent: Math.NaN,
+ descent: Math.NaN,
+ capHeight: Math.NaN,
+ xHeight: Math.NaN
+ };
+ t.ZapfDingbats = {
+ ascent: Math.NaN,
+ descent: Math.NaN,
+ capHeight: Math.NaN,
+ xHeight: Math.NaN
+ };
+});
+
+;// CONCATENATED MODULE: ./src/core/glyf.js
+const ON_CURVE_POINT = 1 << 0;
+const X_SHORT_VECTOR = 1 << 1;
+const Y_SHORT_VECTOR = 1 << 2;
+const REPEAT_FLAG = 1 << 3;
+const X_IS_SAME_OR_POSITIVE_X_SHORT_VECTOR = 1 << 4;
+const Y_IS_SAME_OR_POSITIVE_Y_SHORT_VECTOR = 1 << 5;
+const OVERLAP_SIMPLE = 1 << 6;
+const ARG_1_AND_2_ARE_WORDS = 1 << 0;
+const ARGS_ARE_XY_VALUES = 1 << 1;
+const WE_HAVE_A_SCALE = 1 << 3;
+const MORE_COMPONENTS = 1 << 5;
+const WE_HAVE_AN_X_AND_Y_SCALE = 1 << 6;
+const WE_HAVE_A_TWO_BY_TWO = 1 << 7;
+const WE_HAVE_INSTRUCTIONS = 1 << 8;
+class GlyfTable {
+ constructor({
+ glyfTable,
+ isGlyphLocationsLong,
+ locaTable,
+ numGlyphs
+ }) {
+ this.glyphs = [];
+ const loca = new DataView(locaTable.buffer, locaTable.byteOffset, locaTable.byteLength);
+ const glyf = new DataView(glyfTable.buffer, glyfTable.byteOffset, glyfTable.byteLength);
+ const offsetSize = isGlyphLocationsLong ? 4 : 2;
+ let prev = isGlyphLocationsLong ? loca.getUint32(0) : 2 * loca.getUint16(0);
+ let pos = 0;
+ for (let i = 0; i < numGlyphs; i++) {
+ pos += offsetSize;
+ const next = isGlyphLocationsLong ? loca.getUint32(pos) : 2 * loca.getUint16(pos);
+ if (next === prev) {
+ this.glyphs.push(new Glyph({}));
+ continue;
+ }
+ const glyph = Glyph.parse(prev, glyf);
+ this.glyphs.push(glyph);
+ prev = next;
+ }
+ }
+ getSize() {
+ return this.glyphs.reduce((a, g) => {
+ const size = g.getSize();
+ return a + (size + 3 & ~3);
+ }, 0);
+ }
+ write() {
+ const totalSize = this.getSize();
+ const glyfTable = new DataView(new ArrayBuffer(totalSize));
+ const isLocationLong = totalSize > 0x1fffe;
+ const offsetSize = isLocationLong ? 4 : 2;
+ const locaTable = new DataView(new ArrayBuffer((this.glyphs.length + 1) * offsetSize));
+ if (isLocationLong) {
+ locaTable.setUint32(0, 0);
+ } else {
+ locaTable.setUint16(0, 0);
+ }
+ let pos = 0;
+ let locaIndex = 0;
+ for (const glyph of this.glyphs) {
+ pos += glyph.write(pos, glyfTable);
+ pos = pos + 3 & ~3;
+ locaIndex += offsetSize;
+ if (isLocationLong) {
+ locaTable.setUint32(locaIndex, pos);
+ } else {
+ locaTable.setUint16(locaIndex, pos >> 1);
+ }
+ }
+ return {
+ isLocationLong,
+ loca: new Uint8Array(locaTable.buffer),
+ glyf: new Uint8Array(glyfTable.buffer)
+ };
+ }
+ scale(factors) {
+ for (let i = 0, ii = this.glyphs.length; i < ii; i++) {
+ this.glyphs[i].scale(factors[i]);
+ }
+ }
+}
+class Glyph {
+ constructor({
+ header = null,
+ simple = null,
+ composites = null
+ }) {
+ this.header = header;
+ this.simple = simple;
+ this.composites = composites;
+ }
+ static parse(pos, glyf) {
+ const [read, header] = GlyphHeader.parse(pos, glyf);
+ pos += read;
+ if (header.numberOfContours < 0) {
+ const composites = [];
+ while (true) {
+ const [n, composite] = CompositeGlyph.parse(pos, glyf);
+ pos += n;
+ composites.push(composite);
+ if (!(composite.flags & MORE_COMPONENTS)) {
+ break;
+ }
+ }
+ return new Glyph({
+ header,
+ composites
+ });
+ }
+ const simple = SimpleGlyph.parse(pos, glyf, header.numberOfContours);
+ return new Glyph({
+ header,
+ simple
+ });
+ }
+ getSize() {
+ if (!this.header) {
+ return 0;
+ }
+ const size = this.simple ? this.simple.getSize() : this.composites.reduce((a, c) => a + c.getSize(), 0);
+ return this.header.getSize() + size;
+ }
+ write(pos, buf) {
+ if (!this.header) {
+ return 0;
+ }
+ const spos = pos;
+ pos += this.header.write(pos, buf);
+ if (this.simple) {
+ pos += this.simple.write(pos, buf);
+ } else {
+ for (const composite of this.composites) {
+ pos += composite.write(pos, buf);
+ }
+ }
+ return pos - spos;
+ }
+ scale(factor) {
+ if (!this.header) {
+ return;
+ }
+ const xMiddle = (this.header.xMin + this.header.xMax) / 2;
+ this.header.scale(xMiddle, factor);
+ if (this.simple) {
+ this.simple.scale(xMiddle, factor);
+ } else {
+ for (const composite of this.composites) {
+ composite.scale(xMiddle, factor);
+ }
+ }
+ }
+}
+class GlyphHeader {
+ constructor({
+ numberOfContours,
+ xMin,
+ yMin,
+ xMax,
+ yMax
+ }) {
+ this.numberOfContours = numberOfContours;
+ this.xMin = xMin;
+ this.yMin = yMin;
+ this.xMax = xMax;
+ this.yMax = yMax;
+ }
+ static parse(pos, glyf) {
+ return [10, new GlyphHeader({
+ numberOfContours: glyf.getInt16(pos),
+ xMin: glyf.getInt16(pos + 2),
+ yMin: glyf.getInt16(pos + 4),
+ xMax: glyf.getInt16(pos + 6),
+ yMax: glyf.getInt16(pos + 8)
+ })];
+ }
+ getSize() {
+ return 10;
+ }
+ write(pos, buf) {
+ buf.setInt16(pos, this.numberOfContours);
+ buf.setInt16(pos + 2, this.xMin);
+ buf.setInt16(pos + 4, this.yMin);
+ buf.setInt16(pos + 6, this.xMax);
+ buf.setInt16(pos + 8, this.yMax);
+ return 10;
+ }
+ scale(x, factor) {
+ this.xMin = Math.round(x + (this.xMin - x) * factor);
+ this.xMax = Math.round(x + (this.xMax - x) * factor);
+ }
+}
+class Contour {
+ constructor({
+ flags,
+ xCoordinates,
+ yCoordinates
+ }) {
+ this.xCoordinates = xCoordinates;
+ this.yCoordinates = yCoordinates;
+ this.flags = flags;
+ }
+}
+class SimpleGlyph {
+ constructor({
+ contours,
+ instructions
+ }) {
+ this.contours = contours;
+ this.instructions = instructions;
+ }
+ static parse(pos, glyf, numberOfContours) {
+ const endPtsOfContours = [];
+ for (let i = 0; i < numberOfContours; i++) {
+ const endPt = glyf.getUint16(pos);
+ pos += 2;
+ endPtsOfContours.push(endPt);
+ }
+ const numberOfPt = endPtsOfContours[numberOfContours - 1] + 1;
+ const instructionLength = glyf.getUint16(pos);
+ pos += 2;
+ const instructions = new Uint8Array(glyf).slice(pos, pos + instructionLength);
+ pos += instructionLength;
+ const flags = [];
+ for (let i = 0; i < numberOfPt; pos++, i++) {
+ let flag = glyf.getUint8(pos);
+ flags.push(flag);
+ if (flag & REPEAT_FLAG) {
+ const count = glyf.getUint8(++pos);
+ flag ^= REPEAT_FLAG;
+ for (let m = 0; m < count; m++) {
+ flags.push(flag);
+ }
+ i += count;
+ }
+ }
+ const allXCoordinates = [];
+ let xCoordinates = [];
+ let yCoordinates = [];
+ let pointFlags = [];
+ const contours = [];
+ let endPtsOfContoursIndex = 0;
+ let lastCoordinate = 0;
+ for (let i = 0; i < numberOfPt; i++) {
+ const flag = flags[i];
+ if (flag & X_SHORT_VECTOR) {
+ const x = glyf.getUint8(pos++);
+ lastCoordinate += flag & X_IS_SAME_OR_POSITIVE_X_SHORT_VECTOR ? x : -x;
+ xCoordinates.push(lastCoordinate);
+ } else if (flag & X_IS_SAME_OR_POSITIVE_X_SHORT_VECTOR) {
+ xCoordinates.push(lastCoordinate);
+ } else {
+ lastCoordinate += glyf.getInt16(pos);
+ pos += 2;
+ xCoordinates.push(lastCoordinate);
+ }
+ if (endPtsOfContours[endPtsOfContoursIndex] === i) {
+ endPtsOfContoursIndex++;
+ allXCoordinates.push(xCoordinates);
+ xCoordinates = [];
+ }
+ }
+ lastCoordinate = 0;
+ endPtsOfContoursIndex = 0;
+ for (let i = 0; i < numberOfPt; i++) {
+ const flag = flags[i];
+ if (flag & Y_SHORT_VECTOR) {
+ const y = glyf.getUint8(pos++);
+ lastCoordinate += flag & Y_IS_SAME_OR_POSITIVE_Y_SHORT_VECTOR ? y : -y;
+ yCoordinates.push(lastCoordinate);
+ } else if (flag & Y_IS_SAME_OR_POSITIVE_Y_SHORT_VECTOR) {
+ yCoordinates.push(lastCoordinate);
+ } else {
+ lastCoordinate += glyf.getInt16(pos);
+ pos += 2;
+ yCoordinates.push(lastCoordinate);
+ }
+ pointFlags.push(flag & ON_CURVE_POINT | flag & OVERLAP_SIMPLE);
+ if (endPtsOfContours[endPtsOfContoursIndex] === i) {
+ xCoordinates = allXCoordinates[endPtsOfContoursIndex];
+ endPtsOfContoursIndex++;
+ contours.push(new Contour({
+ flags: pointFlags,
+ xCoordinates,
+ yCoordinates
+ }));
+ yCoordinates = [];
+ pointFlags = [];
+ }
+ }
+ return new SimpleGlyph({
+ contours,
+ instructions
+ });
+ }
+ getSize() {
+ let size = this.contours.length * 2 + 2 + this.instructions.length;
+ let lastX = 0;
+ let lastY = 0;
+ for (const contour of this.contours) {
+ size += contour.flags.length;
+ for (let i = 0, ii = contour.xCoordinates.length; i < ii; i++) {
+ const x = contour.xCoordinates[i];
+ const y = contour.yCoordinates[i];
+ let abs = Math.abs(x - lastX);
+ if (abs > 255) {
+ size += 2;
+ } else if (abs > 0) {
+ size += 1;
+ }
+ lastX = x;
+ abs = Math.abs(y - lastY);
+ if (abs > 255) {
+ size += 2;
+ } else if (abs > 0) {
+ size += 1;
+ }
+ lastY = y;
+ }
+ }
+ return size;
+ }
+ write(pos, buf) {
+ const spos = pos;
+ const xCoordinates = [];
+ const yCoordinates = [];
+ const flags = [];
+ let lastX = 0;
+ let lastY = 0;
+ for (const contour of this.contours) {
+ for (let i = 0, ii = contour.xCoordinates.length; i < ii; i++) {
+ let flag = contour.flags[i];
+ const x = contour.xCoordinates[i];
+ let delta = x - lastX;
+ if (delta === 0) {
+ flag |= X_IS_SAME_OR_POSITIVE_X_SHORT_VECTOR;
+ xCoordinates.push(0);
+ } else {
+ const abs = Math.abs(delta);
+ if (abs <= 255) {
+ flag |= delta >= 0 ? X_SHORT_VECTOR | X_IS_SAME_OR_POSITIVE_X_SHORT_VECTOR : X_SHORT_VECTOR;
+ xCoordinates.push(abs);
+ } else {
+ xCoordinates.push(delta);
+ }
+ }
+ lastX = x;
+ const y = contour.yCoordinates[i];
+ delta = y - lastY;
+ if (delta === 0) {
+ flag |= Y_IS_SAME_OR_POSITIVE_Y_SHORT_VECTOR;
+ yCoordinates.push(0);
+ } else {
+ const abs = Math.abs(delta);
+ if (abs <= 255) {
+ flag |= delta >= 0 ? Y_SHORT_VECTOR | Y_IS_SAME_OR_POSITIVE_Y_SHORT_VECTOR : Y_SHORT_VECTOR;
+ yCoordinates.push(abs);
+ } else {
+ yCoordinates.push(delta);
+ }
+ }
+ lastY = y;
+ flags.push(flag);
+ }
+ buf.setUint16(pos, xCoordinates.length - 1);
+ pos += 2;
+ }
+ buf.setUint16(pos, this.instructions.length);
+ pos += 2;
+ if (this.instructions.length) {
+ new Uint8Array(buf.buffer, 0, buf.buffer.byteLength).set(this.instructions, pos);
+ pos += this.instructions.length;
+ }
+ for (const flag of flags) {
+ buf.setUint8(pos++, flag);
+ }
+ for (let i = 0, ii = xCoordinates.length; i < ii; i++) {
+ const x = xCoordinates[i];
+ const flag = flags[i];
+ if (flag & X_SHORT_VECTOR) {
+ buf.setUint8(pos++, x);
+ } else if (!(flag & X_IS_SAME_OR_POSITIVE_X_SHORT_VECTOR)) {
+ buf.setInt16(pos, x);
+ pos += 2;
+ }
+ }
+ for (let i = 0, ii = yCoordinates.length; i < ii; i++) {
+ const y = yCoordinates[i];
+ const flag = flags[i];
+ if (flag & Y_SHORT_VECTOR) {
+ buf.setUint8(pos++, y);
+ } else if (!(flag & Y_IS_SAME_OR_POSITIVE_Y_SHORT_VECTOR)) {
+ buf.setInt16(pos, y);
+ pos += 2;
+ }
+ }
+ return pos - spos;
+ }
+ scale(x, factor) {
+ for (const contour of this.contours) {
+ if (contour.xCoordinates.length === 0) {
+ continue;
+ }
+ for (let i = 0, ii = contour.xCoordinates.length; i < ii; i++) {
+ contour.xCoordinates[i] = Math.round(x + (contour.xCoordinates[i] - x) * factor);
+ }
+ }
+ }
+}
+class CompositeGlyph {
+ constructor({
+ flags,
+ glyphIndex,
+ argument1,
+ argument2,
+ transf,
+ instructions
+ }) {
+ this.flags = flags;
+ this.glyphIndex = glyphIndex;
+ this.argument1 = argument1;
+ this.argument2 = argument2;
+ this.transf = transf;
+ this.instructions = instructions;
+ }
+ static parse(pos, glyf) {
+ const spos = pos;
+ const transf = [];
+ let flags = glyf.getUint16(pos);
+ const glyphIndex = glyf.getUint16(pos + 2);
+ pos += 4;
+ let argument1, argument2;
+ if (flags & ARG_1_AND_2_ARE_WORDS) {
+ if (flags & ARGS_ARE_XY_VALUES) {
+ argument1 = glyf.getInt16(pos);
+ argument2 = glyf.getInt16(pos + 2);
+ } else {
+ argument1 = glyf.getUint16(pos);
+ argument2 = glyf.getUint16(pos + 2);
+ }
+ pos += 4;
+ flags ^= ARG_1_AND_2_ARE_WORDS;
+ } else {
+ if (flags & ARGS_ARE_XY_VALUES) {
+ argument1 = glyf.getInt8(pos);
+ argument2 = glyf.getInt8(pos + 1);
+ } else {
+ argument1 = glyf.getUint8(pos);
+ argument2 = glyf.getUint8(pos + 1);
+ }
+ pos += 2;
+ }
+ if (flags & WE_HAVE_A_SCALE) {
+ transf.push(glyf.getUint16(pos));
+ pos += 2;
+ } else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) {
+ transf.push(glyf.getUint16(pos), glyf.getUint16(pos + 2));
+ pos += 4;
+ } else if (flags & WE_HAVE_A_TWO_BY_TWO) {
+ transf.push(glyf.getUint16(pos), glyf.getUint16(pos + 2), glyf.getUint16(pos + 4), glyf.getUint16(pos + 6));
+ pos += 8;
+ }
+ let instructions = null;
+ if (flags & WE_HAVE_INSTRUCTIONS) {
+ const instructionLength = glyf.getUint16(pos);
+ pos += 2;
+ instructions = new Uint8Array(glyf).slice(pos, pos + instructionLength);
+ pos += instructionLength;
+ }
+ return [pos - spos, new CompositeGlyph({
+ flags,
+ glyphIndex,
+ argument1,
+ argument2,
+ transf,
+ instructions
+ })];
+ }
+ getSize() {
+ let size = 2 + 2 + this.transf.length * 2;
+ if (this.flags & WE_HAVE_INSTRUCTIONS) {
+ size += 2 + this.instructions.length;
+ }
+ size += 2;
+ if (this.flags & 2) {
+ if (!(this.argument1 >= -128 && this.argument1 <= 127 && this.argument2 >= -128 && this.argument2 <= 127)) {
+ size += 2;
+ }
+ } else if (!(this.argument1 >= 0 && this.argument1 <= 255 && this.argument2 >= 0 && this.argument2 <= 255)) {
+ size += 2;
+ }
+ return size;
+ }
+ write(pos, buf) {
+ const spos = pos;
+ if (this.flags & ARGS_ARE_XY_VALUES) {
+ if (!(this.argument1 >= -128 && this.argument1 <= 127 && this.argument2 >= -128 && this.argument2 <= 127)) {
+ this.flags |= ARG_1_AND_2_ARE_WORDS;
+ }
+ } else if (!(this.argument1 >= 0 && this.argument1 <= 255 && this.argument2 >= 0 && this.argument2 <= 255)) {
+ this.flags |= ARG_1_AND_2_ARE_WORDS;
+ }
+ buf.setUint16(pos, this.flags);
+ buf.setUint16(pos + 2, this.glyphIndex);
+ pos += 4;
+ if (this.flags & ARG_1_AND_2_ARE_WORDS) {
+ if (this.flags & ARGS_ARE_XY_VALUES) {
+ buf.setInt16(pos, this.argument1);
+ buf.setInt16(pos + 2, this.argument2);
+ } else {
+ buf.setUint16(pos, this.argument1);
+ buf.setUint16(pos + 2, this.argument2);
+ }
+ pos += 4;
+ } else {
+ buf.setUint8(pos, this.argument1);
+ buf.setUint8(pos + 1, this.argument2);
+ pos += 2;
+ }
+ if (this.flags & WE_HAVE_INSTRUCTIONS) {
+ buf.setUint16(pos, this.instructions.length);
+ pos += 2;
+ if (this.instructions.length) {
+ new Uint8Array(buf.buffer, 0, buf.buffer.byteLength).set(this.instructions, pos);
+ pos += this.instructions.length;
+ }
+ }
+ return pos - spos;
+ }
+ scale(x, factor) {}
+}
+
+;// CONCATENATED MODULE: ./src/core/opentype_file_builder.js
+
+
+function writeInt16(dest, offset, num) {
+ dest[offset] = num >> 8 & 0xff;
+ dest[offset + 1] = num & 0xff;
+}
+function writeInt32(dest, offset, num) {
+ dest[offset] = num >> 24 & 0xff;
+ dest[offset + 1] = num >> 16 & 0xff;
+ dest[offset + 2] = num >> 8 & 0xff;
+ dest[offset + 3] = num & 0xff;
+}
+function writeData(dest, offset, data) {
+ if (data instanceof Uint8Array) {
+ dest.set(data, offset);
+ } else if (typeof data === "string") {
+ for (let i = 0, ii = data.length; i < ii; i++) {
+ dest[offset++] = data.charCodeAt(i) & 0xff;
+ }
+ } else {
+ for (const num of data) {
+ dest[offset++] = num & 0xff;
+ }
+ }
+}
+const OTF_HEADER_SIZE = 12;
+const OTF_TABLE_ENTRY_SIZE = 16;
+class OpenTypeFileBuilder {
+ constructor(sfnt) {
+ this.sfnt = sfnt;
+ this.tables = Object.create(null);
+ }
+ static getSearchParams(entriesCount, entrySize) {
+ let maxPower2 = 1,
+ log2 = 0;
+ while ((maxPower2 ^ entriesCount) > maxPower2) {
+ maxPower2 <<= 1;
+ log2++;
+ }
+ const searchRange = maxPower2 * entrySize;
+ return {
+ range: searchRange,
+ entry: log2,
+ rangeShift: entrySize * entriesCount - searchRange
+ };
+ }
+ toArray() {
+ let sfnt = this.sfnt;
+ const tables = this.tables;
+ const tablesNames = Object.keys(tables);
+ tablesNames.sort();
+ const numTables = tablesNames.length;
+ let i, j, jj, table, tableName;
+ let offset = OTF_HEADER_SIZE + numTables * OTF_TABLE_ENTRY_SIZE;
+ const tableOffsets = [offset];
+ for (i = 0; i < numTables; i++) {
+ table = tables[tablesNames[i]];
+ const paddedLength = (table.length + 3 & ~3) >>> 0;
+ offset += paddedLength;
+ tableOffsets.push(offset);
+ }
+ const file = new Uint8Array(offset);
+ for (i = 0; i < numTables; i++) {
+ table = tables[tablesNames[i]];
+ writeData(file, tableOffsets[i], table);
+ }
+ if (sfnt === "true") {
+ sfnt = string32(0x00010000);
+ }
+ file[0] = sfnt.charCodeAt(0) & 0xff;
+ file[1] = sfnt.charCodeAt(1) & 0xff;
+ file[2] = sfnt.charCodeAt(2) & 0xff;
+ file[3] = sfnt.charCodeAt(3) & 0xff;
+ writeInt16(file, 4, numTables);
+ const searchParams = OpenTypeFileBuilder.getSearchParams(numTables, 16);
+ writeInt16(file, 6, searchParams.range);
+ writeInt16(file, 8, searchParams.entry);
+ writeInt16(file, 10, searchParams.rangeShift);
+ offset = OTF_HEADER_SIZE;
+ for (i = 0; i < numTables; i++) {
+ tableName = tablesNames[i];
+ file[offset] = tableName.charCodeAt(0) & 0xff;
+ file[offset + 1] = tableName.charCodeAt(1) & 0xff;
+ file[offset + 2] = tableName.charCodeAt(2) & 0xff;
+ file[offset + 3] = tableName.charCodeAt(3) & 0xff;
+ let checksum = 0;
+ for (j = tableOffsets[i], jj = tableOffsets[i + 1]; j < jj; j += 4) {
+ const quad = readUint32(file, j);
+ checksum = checksum + quad >>> 0;
+ }
+ writeInt32(file, offset + 4, checksum);
+ writeInt32(file, offset + 8, tableOffsets[i]);
+ writeInt32(file, offset + 12, tables[tableName].length);
+ offset += OTF_TABLE_ENTRY_SIZE;
+ }
+ return file;
+ }
+ addTable(tag, data) {
+ if (tag in this.tables) {
+ throw new Error("Table " + tag + " already exists");
+ }
+ this.tables[tag] = data;
+ }
+}
+
+;// CONCATENATED MODULE: ./src/core/type1_parser.js
+
+
+
+
+const HINTING_ENABLED = false;
+const COMMAND_MAP = {
+ hstem: [1],
+ vstem: [3],
+ vmoveto: [4],
+ rlineto: [5],
+ hlineto: [6],
+ vlineto: [7],
+ rrcurveto: [8],
+ callsubr: [10],
+ flex: [12, 35],
+ drop: [12, 18],
+ endchar: [14],
+ rmoveto: [21],
+ hmoveto: [22],
+ vhcurveto: [30],
+ hvcurveto: [31]
+};
+class Type1CharString {
+ constructor() {
+ this.width = 0;
+ this.lsb = 0;
+ this.flexing = false;
+ this.output = [];
+ this.stack = [];
+ }
+ convert(encoded, subrs, seacAnalysisEnabled) {
+ const count = encoded.length;
+ let error = false;
+ let wx, sbx, subrNumber;
+ for (let i = 0; i < count; i++) {
+ let value = encoded[i];
+ if (value < 32) {
+ if (value === 12) {
+ value = (value << 8) + encoded[++i];
+ }
+ switch (value) {
+ case 1:
+ if (!HINTING_ENABLED) {
+ this.stack = [];
+ break;
+ }
+ error = this.executeCommand(2, COMMAND_MAP.hstem);
+ break;
+ case 3:
+ if (!HINTING_ENABLED) {
+ this.stack = [];
+ break;
+ }
+ error = this.executeCommand(2, COMMAND_MAP.vstem);
+ break;
+ case 4:
+ if (this.flexing) {
+ if (this.stack.length < 1) {
+ error = true;
+ break;
+ }
+ const dy = this.stack.pop();
+ this.stack.push(0, dy);
+ break;
+ }
+ error = this.executeCommand(1, COMMAND_MAP.vmoveto);
+ break;
+ case 5:
+ error = this.executeCommand(2, COMMAND_MAP.rlineto);
+ break;
+ case 6:
+ error = this.executeCommand(1, COMMAND_MAP.hlineto);
+ break;
+ case 7:
+ error = this.executeCommand(1, COMMAND_MAP.vlineto);
+ break;
+ case 8:
+ error = this.executeCommand(6, COMMAND_MAP.rrcurveto);
+ break;
+ case 9:
+ this.stack = [];
+ break;
+ case 10:
+ if (this.stack.length < 1) {
+ error = true;
+ break;
+ }
+ subrNumber = this.stack.pop();
+ if (!subrs[subrNumber]) {
+ error = true;
+ break;
+ }
+ error = this.convert(subrs[subrNumber], subrs, seacAnalysisEnabled);
+ break;
+ case 11:
+ return error;
+ case 13:
+ if (this.stack.length < 2) {
+ error = true;
+ break;
+ }
+ wx = this.stack.pop();
+ sbx = this.stack.pop();
+ this.lsb = sbx;
+ this.width = wx;
+ this.stack.push(wx, sbx);
+ error = this.executeCommand(2, COMMAND_MAP.hmoveto);
+ break;
+ case 14:
+ this.output.push(COMMAND_MAP.endchar[0]);
+ break;
+ case 21:
+ if (this.flexing) {
+ break;
+ }
+ error = this.executeCommand(2, COMMAND_MAP.rmoveto);
+ break;
+ case 22:
+ if (this.flexing) {
+ this.stack.push(0);
+ break;
+ }
+ error = this.executeCommand(1, COMMAND_MAP.hmoveto);
+ break;
+ case 30:
+ error = this.executeCommand(4, COMMAND_MAP.vhcurveto);
+ break;
+ case 31:
+ error = this.executeCommand(4, COMMAND_MAP.hvcurveto);
+ break;
+ case (12 << 8) + 0:
+ this.stack = [];
+ break;
+ case (12 << 8) + 1:
+ if (!HINTING_ENABLED) {
+ this.stack = [];
+ break;
+ }
+ error = this.executeCommand(2, COMMAND_MAP.vstem);
+ break;
+ case (12 << 8) + 2:
+ if (!HINTING_ENABLED) {
+ this.stack = [];
+ break;
+ }
+ error = this.executeCommand(2, COMMAND_MAP.hstem);
+ break;
+ case (12 << 8) + 6:
+ if (seacAnalysisEnabled) {
+ const asb = this.stack.at(-5);
+ this.seac = this.stack.splice(-4, 4);
+ this.seac[0] += this.lsb - asb;
+ error = this.executeCommand(0, COMMAND_MAP.endchar);
+ } else {
+ error = this.executeCommand(4, COMMAND_MAP.endchar);
+ }
+ break;
+ case (12 << 8) + 7:
+ if (this.stack.length < 4) {
+ error = true;
+ break;
+ }
+ this.stack.pop();
+ wx = this.stack.pop();
+ const sby = this.stack.pop();
+ sbx = this.stack.pop();
+ this.lsb = sbx;
+ this.width = wx;
+ this.stack.push(wx, sbx, sby);
+ error = this.executeCommand(3, COMMAND_MAP.rmoveto);
+ break;
+ case (12 << 8) + 12:
+ if (this.stack.length < 2) {
+ error = true;
+ break;
+ }
+ const num2 = this.stack.pop();
+ const num1 = this.stack.pop();
+ this.stack.push(num1 / num2);
+ break;
+ case (12 << 8) + 16:
+ if (this.stack.length < 2) {
+ error = true;
+ break;
+ }
+ subrNumber = this.stack.pop();
+ const numArgs = this.stack.pop();
+ if (subrNumber === 0 && numArgs === 3) {
+ const flexArgs = this.stack.splice(-17, 17);
+ this.stack.push(flexArgs[2] + flexArgs[0], flexArgs[3] + flexArgs[1], flexArgs[4], flexArgs[5], flexArgs[6], flexArgs[7], flexArgs[8], flexArgs[9], flexArgs[10], flexArgs[11], flexArgs[12], flexArgs[13], flexArgs[14]);
+ error = this.executeCommand(13, COMMAND_MAP.flex, true);
+ this.flexing = false;
+ this.stack.push(flexArgs[15], flexArgs[16]);
+ } else if (subrNumber === 1 && numArgs === 0) {
+ this.flexing = true;
+ }
+ break;
+ case (12 << 8) + 17:
+ break;
+ case (12 << 8) + 33:
+ this.stack = [];
+ break;
+ default:
+ warn('Unknown type 1 charstring command of "' + value + '"');
+ break;
+ }
+ if (error) {
+ break;
+ }
+ continue;
+ } else if (value <= 246) {
+ value -= 139;
+ } else if (value <= 250) {
+ value = (value - 247) * 256 + encoded[++i] + 108;
+ } else if (value <= 254) {
+ value = -((value - 251) * 256) - encoded[++i] - 108;
+ } else {
+ value = (encoded[++i] & 0xff) << 24 | (encoded[++i] & 0xff) << 16 | (encoded[++i] & 0xff) << 8 | (encoded[++i] & 0xff) << 0;
+ }
+ this.stack.push(value);
+ }
+ return error;
+ }
+ executeCommand(howManyArgs, command, keepStack) {
+ const stackLength = this.stack.length;
+ if (howManyArgs > stackLength) {
+ return true;
+ }
+ const start = stackLength - howManyArgs;
+ for (let i = start; i < stackLength; i++) {
+ let value = this.stack[i];
+ if (Number.isInteger(value)) {
+ this.output.push(28, value >> 8 & 0xff, value & 0xff);
+ } else {
+ value = 65536 * value | 0;
+ this.output.push(255, value >> 24 & 0xff, value >> 16 & 0xff, value >> 8 & 0xff, value & 0xff);
+ }
+ }
+ this.output.push(...command);
+ if (keepStack) {
+ this.stack.splice(start, howManyArgs);
+ } else {
+ this.stack.length = 0;
+ }
+ return false;
+ }
+}
+const EEXEC_ENCRYPT_KEY = 55665;
+const CHAR_STRS_ENCRYPT_KEY = 4330;
+function isHexDigit(code) {
+ return code >= 48 && code <= 57 || code >= 65 && code <= 70 || code >= 97 && code <= 102;
+}
+function decrypt(data, key, discardNumber) {
+ if (discardNumber >= data.length) {
+ return new Uint8Array(0);
+ }
+ const c1 = 52845,
+ c2 = 22719;
+ let r = key | 0,
+ i,
+ j;
+ for (i = 0; i < discardNumber; i++) {
+ r = (data[i] + r) * c1 + c2 & (1 << 16) - 1;
+ }
+ const count = data.length - discardNumber;
+ const decrypted = new Uint8Array(count);
+ for (i = discardNumber, j = 0; j < count; i++, j++) {
+ const value = data[i];
+ decrypted[j] = value ^ r >> 8;
+ r = (value + r) * c1 + c2 & (1 << 16) - 1;
+ }
+ return decrypted;
+}
+function decryptAscii(data, key, discardNumber) {
+ const c1 = 52845,
+ c2 = 22719;
+ let r = key | 0;
+ const count = data.length,
+ maybeLength = count >>> 1;
+ const decrypted = new Uint8Array(maybeLength);
+ let i, j;
+ for (i = 0, j = 0; i < count; i++) {
+ const digit1 = data[i];
+ if (!isHexDigit(digit1)) {
+ continue;
+ }
+ i++;
+ let digit2;
+ while (i < count && !isHexDigit(digit2 = data[i])) {
+ i++;
+ }
+ if (i < count) {
+ const value = parseInt(String.fromCharCode(digit1, digit2), 16);
+ decrypted[j++] = value ^ r >> 8;
+ r = (value + r) * c1 + c2 & (1 << 16) - 1;
+ }
+ }
+ return decrypted.slice(discardNumber, j);
+}
+function isSpecial(c) {
+ return c === 0x2f || c === 0x5b || c === 0x5d || c === 0x7b || c === 0x7d || c === 0x28 || c === 0x29;
+}
+class Type1Parser {
+ constructor(stream, encrypted, seacAnalysisEnabled) {
+ if (encrypted) {
+ const data = stream.getBytes();
+ const isBinary = !((isHexDigit(data[0]) || isWhiteSpace(data[0])) && isHexDigit(data[1]) && isHexDigit(data[2]) && isHexDigit(data[3]) && isHexDigit(data[4]) && isHexDigit(data[5]) && isHexDigit(data[6]) && isHexDigit(data[7]));
+ stream = new Stream(isBinary ? decrypt(data, EEXEC_ENCRYPT_KEY, 4) : decryptAscii(data, EEXEC_ENCRYPT_KEY, 4));
+ }
+ this.seacAnalysisEnabled = !!seacAnalysisEnabled;
+ this.stream = stream;
+ this.nextChar();
+ }
+ readNumberArray() {
+ this.getToken();
+ const array = [];
+ while (true) {
+ const token = this.getToken();
+ if (token === null || token === "]" || token === "}") {
+ break;
+ }
+ array.push(parseFloat(token || 0));
+ }
+ return array;
+ }
+ readNumber() {
+ const token = this.getToken();
+ return parseFloat(token || 0);
+ }
+ readInt() {
+ const token = this.getToken();
+ return parseInt(token || 0, 10) | 0;
+ }
+ readBoolean() {
+ const token = this.getToken();
+ return token === "true" ? 1 : 0;
+ }
+ nextChar() {
+ return this.currentChar = this.stream.getByte();
+ }
+ prevChar() {
+ this.stream.skip(-2);
+ return this.currentChar = this.stream.getByte();
+ }
+ getToken() {
+ let comment = false;
+ let ch = this.currentChar;
+ while (true) {
+ if (ch === -1) {
+ return null;
+ }
+ if (comment) {
+ if (ch === 0x0a || ch === 0x0d) {
+ comment = false;
+ }
+ } else if (ch === 0x25) {
+ comment = true;
+ } else if (!isWhiteSpace(ch)) {
+ break;
+ }
+ ch = this.nextChar();
+ }
+ if (isSpecial(ch)) {
+ this.nextChar();
+ return String.fromCharCode(ch);
+ }
+ let token = "";
+ do {
+ token += String.fromCharCode(ch);
+ ch = this.nextChar();
+ } while (ch >= 0 && !isWhiteSpace(ch) && !isSpecial(ch));
+ return token;
+ }
+ readCharStrings(bytes, lenIV) {
+ if (lenIV === -1) {
+ return bytes;
+ }
+ return decrypt(bytes, CHAR_STRS_ENCRYPT_KEY, lenIV);
+ }
+ extractFontProgram(properties) {
+ const stream = this.stream;
+ const subrs = [],
+ charstrings = [];
+ const privateData = Object.create(null);
+ privateData.lenIV = 4;
+ const program = {
+ subrs: [],
+ charstrings: [],
+ properties: {
+ privateData
+ }
+ };
+ let token, length, data, lenIV;
+ while ((token = this.getToken()) !== null) {
+ if (token !== "/") {
+ continue;
+ }
+ token = this.getToken();
+ switch (token) {
+ case "CharStrings":
+ this.getToken();
+ this.getToken();
+ this.getToken();
+ this.getToken();
+ while (true) {
+ token = this.getToken();
+ if (token === null || token === "end") {
+ break;
+ }
+ if (token !== "/") {
+ continue;
+ }
+ const glyph = this.getToken();
+ length = this.readInt();
+ this.getToken();
+ data = length > 0 ? stream.getBytes(length) : new Uint8Array(0);
+ lenIV = program.properties.privateData.lenIV;
+ const encoded = this.readCharStrings(data, lenIV);
+ this.nextChar();
+ token = this.getToken();
+ if (token === "noaccess") {
+ this.getToken();
+ } else if (token === "/") {
+ this.prevChar();
+ }
+ charstrings.push({
+ glyph,
+ encoded
+ });
+ }
+ break;
+ case "Subrs":
+ this.readInt();
+ this.getToken();
+ while (this.getToken() === "dup") {
+ const index = this.readInt();
+ length = this.readInt();
+ this.getToken();
+ data = length > 0 ? stream.getBytes(length) : new Uint8Array(0);
+ lenIV = program.properties.privateData.lenIV;
+ const encoded = this.readCharStrings(data, lenIV);
+ this.nextChar();
+ token = this.getToken();
+ if (token === "noaccess") {
+ this.getToken();
+ }
+ subrs[index] = encoded;
+ }
+ break;
+ case "BlueValues":
+ case "OtherBlues":
+ case "FamilyBlues":
+ case "FamilyOtherBlues":
+ const blueArray = this.readNumberArray();
+ if (blueArray.length > 0 && blueArray.length % 2 === 0 && HINTING_ENABLED) {
+ program.properties.privateData[token] = blueArray;
+ }
+ break;
+ case "StemSnapH":
+ case "StemSnapV":
+ program.properties.privateData[token] = this.readNumberArray();
+ break;
+ case "StdHW":
+ case "StdVW":
+ program.properties.privateData[token] = this.readNumberArray()[0];
+ break;
+ case "BlueShift":
+ case "lenIV":
+ case "BlueFuzz":
+ case "BlueScale":
+ case "LanguageGroup":
+ program.properties.privateData[token] = this.readNumber();
+ break;
+ case "ExpansionFactor":
+ program.properties.privateData[token] = this.readNumber() || 0.06;
+ break;
+ case "ForceBold":
+ program.properties.privateData[token] = this.readBoolean();
+ break;
+ }
+ }
+ for (const {
+ encoded,
+ glyph
+ } of charstrings) {
+ const charString = new Type1CharString();
+ const error = charString.convert(encoded, subrs, this.seacAnalysisEnabled);
+ let output = charString.output;
+ if (error) {
+ output = [14];
+ }
+ const charStringObject = {
+ glyphName: glyph,
+ charstring: output,
+ width: charString.width,
+ lsb: charString.lsb,
+ seac: charString.seac
+ };
+ if (glyph === ".notdef") {
+ program.charstrings.unshift(charStringObject);
+ } else {
+ program.charstrings.push(charStringObject);
+ }
+ if (properties.builtInEncoding) {
+ const index = properties.builtInEncoding.indexOf(glyph);
+ if (index > -1 && properties.widths[index] === undefined && index >= properties.firstChar && index <= properties.lastChar) {
+ properties.widths[index] = charString.width;
+ }
+ }
+ }
+ return program;
+ }
+ extractFontHeader(properties) {
+ let token;
+ while ((token = this.getToken()) !== null) {
+ if (token !== "/") {
+ continue;
+ }
+ token = this.getToken();
+ switch (token) {
+ case "FontMatrix":
+ const matrix = this.readNumberArray();
+ properties.fontMatrix = matrix;
+ break;
+ case "Encoding":
+ const encodingArg = this.getToken();
+ let encoding;
+ if (!/^\d+$/.test(encodingArg)) {
+ encoding = getEncoding(encodingArg);
+ } else {
+ encoding = [];
+ const size = parseInt(encodingArg, 10) | 0;
+ this.getToken();
+ for (let j = 0; j < size; j++) {
+ token = this.getToken();
+ while (token !== "dup" && token !== "def") {
+ token = this.getToken();
+ if (token === null) {
+ return;
+ }
+ }
+ if (token === "def") {
+ break;
+ }
+ const index = this.readInt();
+ this.getToken();
+ const glyph = this.getToken();
+ encoding[index] = glyph;
+ this.getToken();
+ }
+ }
+ properties.builtInEncoding = encoding;
+ break;
+ case "FontBBox":
+ const fontBBox = this.readNumberArray();
+ properties.ascent = Math.max(fontBBox[3], fontBBox[1]);
+ properties.descent = Math.min(fontBBox[1], fontBBox[3]);
+ properties.ascentScaled = true;
+ break;
+ }
+ }
+ }
+}
+
+;// CONCATENATED MODULE: ./src/core/type1_font.js
+
+
+
+
+
+
+function findBlock(streamBytes, signature, startIndex) {
+ const streamBytesLength = streamBytes.length;
+ const signatureLength = signature.length;
+ const scanLength = streamBytesLength - signatureLength;
+ let i = startIndex,
+ found = false;
+ while (i < scanLength) {
+ let j = 0;
+ while (j < signatureLength && streamBytes[i + j] === signature[j]) {
+ j++;
+ }
+ if (j >= signatureLength) {
+ i += j;
+ while (i < streamBytesLength && isWhiteSpace(streamBytes[i])) {
+ i++;
+ }
+ found = true;
+ break;
+ }
+ i++;
+ }
+ return {
+ found,
+ length: i
+ };
+}
+function getHeaderBlock(stream, suggestedLength) {
+ const EEXEC_SIGNATURE = [0x65, 0x65, 0x78, 0x65, 0x63];
+ const streamStartPos = stream.pos;
+ let headerBytes, headerBytesLength, block;
+ try {
+ headerBytes = stream.getBytes(suggestedLength);
+ headerBytesLength = headerBytes.length;
+ } catch {}
+ if (headerBytesLength === suggestedLength) {
+ block = findBlock(headerBytes, EEXEC_SIGNATURE, suggestedLength - 2 * EEXEC_SIGNATURE.length);
+ if (block.found && block.length === suggestedLength) {
+ return {
+ stream: new Stream(headerBytes),
+ length: suggestedLength
+ };
+ }
+ }
+ warn('Invalid "Length1" property in Type1 font -- trying to recover.');
+ stream.pos = streamStartPos;
+ const SCAN_BLOCK_LENGTH = 2048;
+ let actualLength;
+ while (true) {
+ const scanBytes = stream.peekBytes(SCAN_BLOCK_LENGTH);
+ block = findBlock(scanBytes, EEXEC_SIGNATURE, 0);
+ if (block.length === 0) {
+ break;
+ }
+ stream.pos += block.length;
+ if (block.found) {
+ actualLength = stream.pos - streamStartPos;
+ break;
+ }
+ }
+ stream.pos = streamStartPos;
+ if (actualLength) {
+ return {
+ stream: new Stream(stream.getBytes(actualLength)),
+ length: actualLength
+ };
+ }
+ warn('Unable to recover "Length1" property in Type1 font -- using as is.');
+ return {
+ stream: new Stream(stream.getBytes(suggestedLength)),
+ length: suggestedLength
+ };
+}
+function getEexecBlock(stream, suggestedLength) {
+ const eexecBytes = stream.getBytes();
+ if (eexecBytes.length === 0) {
+ throw new FormatError("getEexecBlock - no font program found.");
+ }
+ return {
+ stream: new Stream(eexecBytes),
+ length: eexecBytes.length
+ };
+}
+class Type1Font {
+ constructor(name, file, properties) {
+ const PFB_HEADER_SIZE = 6;
+ let headerBlockLength = properties.length1;
+ let eexecBlockLength = properties.length2;
+ let pfbHeader = file.peekBytes(PFB_HEADER_SIZE);
+ const pfbHeaderPresent = pfbHeader[0] === 0x80 && pfbHeader[1] === 0x01;
+ if (pfbHeaderPresent) {
+ file.skip(PFB_HEADER_SIZE);
+ headerBlockLength = pfbHeader[5] << 24 | pfbHeader[4] << 16 | pfbHeader[3] << 8 | pfbHeader[2];
+ }
+ const headerBlock = getHeaderBlock(file, headerBlockLength);
+ const headerBlockParser = new Type1Parser(headerBlock.stream, false, SEAC_ANALYSIS_ENABLED);
+ headerBlockParser.extractFontHeader(properties);
+ if (pfbHeaderPresent) {
+ pfbHeader = file.getBytes(PFB_HEADER_SIZE);
+ eexecBlockLength = pfbHeader[5] << 24 | pfbHeader[4] << 16 | pfbHeader[3] << 8 | pfbHeader[2];
+ }
+ const eexecBlock = getEexecBlock(file, eexecBlockLength);
+ const eexecBlockParser = new Type1Parser(eexecBlock.stream, true, SEAC_ANALYSIS_ENABLED);
+ const data = eexecBlockParser.extractFontProgram(properties);
+ for (const key in data.properties) {
+ properties[key] = data.properties[key];
+ }
+ const charstrings = data.charstrings;
+ const type2Charstrings = this.getType2Charstrings(charstrings);
+ const subrs = this.getType2Subrs(data.subrs);
+ this.charstrings = charstrings;
+ this.data = this.wrap(name, type2Charstrings, this.charstrings, subrs, properties);
+ this.seacs = this.getSeacs(data.charstrings);
+ }
+ get numGlyphs() {
+ return this.charstrings.length + 1;
+ }
+ getCharset() {
+ const charset = [".notdef"];
+ for (const {
+ glyphName
+ } of this.charstrings) {
+ charset.push(glyphName);
+ }
+ return charset;
+ }
+ getGlyphMapping(properties) {
+ const charstrings = this.charstrings;
+ if (properties.composite) {
+ const charCodeToGlyphId = Object.create(null);
+ for (let glyphId = 0, charstringsLen = charstrings.length; glyphId < charstringsLen; glyphId++) {
+ const charCode = properties.cMap.charCodeOf(glyphId);
+ charCodeToGlyphId[charCode] = glyphId + 1;
+ }
+ return charCodeToGlyphId;
+ }
+ const glyphNames = [".notdef"];
+ let builtInEncoding, glyphId;
+ for (glyphId = 0; glyphId < charstrings.length; glyphId++) {
+ glyphNames.push(charstrings[glyphId].glyphName);
+ }
+ const encoding = properties.builtInEncoding;
+ if (encoding) {
+ builtInEncoding = Object.create(null);
+ for (const charCode in encoding) {
+ glyphId = glyphNames.indexOf(encoding[charCode]);
+ if (glyphId >= 0) {
+ builtInEncoding[charCode] = glyphId;
+ }
+ }
+ }
+ return type1FontGlyphMapping(properties, builtInEncoding, glyphNames);
+ }
+ hasGlyphId(id) {
+ if (id < 0 || id >= this.numGlyphs) {
+ return false;
+ }
+ if (id === 0) {
+ return true;
+ }
+ const glyph = this.charstrings[id - 1];
+ return glyph.charstring.length > 0;
+ }
+ getSeacs(charstrings) {
+ const seacMap = [];
+ for (let i = 0, ii = charstrings.length; i < ii; i++) {
+ const charstring = charstrings[i];
+ if (charstring.seac) {
+ seacMap[i + 1] = charstring.seac;
+ }
+ }
+ return seacMap;
+ }
+ getType2Charstrings(type1Charstrings) {
+ const type2Charstrings = [];
+ for (const type1Charstring of type1Charstrings) {
+ type2Charstrings.push(type1Charstring.charstring);
+ }
+ return type2Charstrings;
+ }
+ getType2Subrs(type1Subrs) {
+ let bias = 0;
+ const count = type1Subrs.length;
+ if (count < 1133) {
+ bias = 107;
+ } else if (count < 33769) {
+ bias = 1131;
+ } else {
+ bias = 32768;
+ }
+ const type2Subrs = [];
+ let i;
+ for (i = 0; i < bias; i++) {
+ type2Subrs.push([0x0b]);
+ }
+ for (i = 0; i < count; i++) {
+ type2Subrs.push(type1Subrs[i]);
+ }
+ return type2Subrs;
+ }
+ wrap(name, glyphs, charstrings, subrs, properties) {
+ const cff = new CFF();
+ cff.header = new CFFHeader(1, 0, 4, 4);
+ cff.names = [name];
+ const topDict = new CFFTopDict();
+ topDict.setByName("version", 391);
+ topDict.setByName("Notice", 392);
+ topDict.setByName("FullName", 393);
+ topDict.setByName("FamilyName", 394);
+ topDict.setByName("Weight", 395);
+ topDict.setByName("Encoding", null);
+ topDict.setByName("FontMatrix", properties.fontMatrix);
+ topDict.setByName("FontBBox", properties.bbox);
+ topDict.setByName("charset", null);
+ topDict.setByName("CharStrings", null);
+ topDict.setByName("Private", null);
+ cff.topDict = topDict;
+ const strings = new CFFStrings();
+ strings.add("Version 0.11");
+ strings.add("See original notice");
+ strings.add(name);
+ strings.add(name);
+ strings.add("Medium");
+ cff.strings = strings;
+ cff.globalSubrIndex = new CFFIndex();
+ const count = glyphs.length;
+ const charsetArray = [".notdef"];
+ let i, ii;
+ for (i = 0; i < count; i++) {
+ const glyphName = charstrings[i].glyphName;
+ const index = CFFStandardStrings.indexOf(glyphName);
+ if (index === -1) {
+ strings.add(glyphName);
+ }
+ charsetArray.push(glyphName);
+ }
+ cff.charset = new CFFCharset(false, 0, charsetArray);
+ const charStringsIndex = new CFFIndex();
+ charStringsIndex.add([0x8b, 0x0e]);
+ for (i = 0; i < count; i++) {
+ charStringsIndex.add(glyphs[i]);
+ }
+ cff.charStrings = charStringsIndex;
+ const privateDict = new CFFPrivateDict();
+ privateDict.setByName("Subrs", null);
+ const fields = ["BlueValues", "OtherBlues", "FamilyBlues", "FamilyOtherBlues", "StemSnapH", "StemSnapV", "BlueShift", "BlueFuzz", "BlueScale", "LanguageGroup", "ExpansionFactor", "ForceBold", "StdHW", "StdVW"];
+ for (i = 0, ii = fields.length; i < ii; i++) {
+ const field = fields[i];
+ if (!(field in properties.privateData)) {
+ continue;
+ }
+ const value = properties.privateData[field];
+ if (Array.isArray(value)) {
+ for (let j = value.length - 1; j > 0; j--) {
+ value[j] -= value[j - 1];
+ }
+ }
+ privateDict.setByName(field, value);
+ }
+ cff.topDict.privateDict = privateDict;
+ const subrIndex = new CFFIndex();
+ for (i = 0, ii = subrs.length; i < ii; i++) {
+ subrIndex.add(subrs[i]);
+ }
+ privateDict.subrsIndex = subrIndex;
+ const compiler = new CFFCompiler(cff);
+ return compiler.compile();
+ }
+}
+
+;// CONCATENATED MODULE: ./src/core/fonts.js
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+const PRIVATE_USE_AREAS = [[0xe000, 0xf8ff], [0x100000, 0x10fffd]];
+const PDF_GLYPH_SPACE_UNITS = 1000;
+const EXPORT_DATA_PROPERTIES = ["ascent", "bbox", "black", "bold", "charProcOperatorList", "composite", "cssFontInfo", "data", "defaultVMetrics", "defaultWidth", "descent", "fallbackName", "fontMatrix", "isInvalidPDFjsFont", "isType3Font", "italic", "loadedName", "mimetype", "missingFile", "name", "remeasure", "subtype", "systemFontInfo", "type", "vertical"];
+const EXPORT_DATA_EXTRA_PROPERTIES = ["cMap", "defaultEncoding", "differences", "isMonospace", "isSerifFont", "isSymbolicFont", "seacMap", "toFontChar", "toUnicode", "vmetrics", "widths"];
+function adjustWidths(properties) {
+ if (!properties.fontMatrix) {
+ return;
+ }
+ if (properties.fontMatrix[0] === FONT_IDENTITY_MATRIX[0]) {
+ return;
+ }
+ const scale = 0.001 / properties.fontMatrix[0];
+ const glyphsWidths = properties.widths;
+ for (const glyph in glyphsWidths) {
+ glyphsWidths[glyph] *= scale;
+ }
+ properties.defaultWidth *= scale;
+}
+function adjustTrueTypeToUnicode(properties, isSymbolicFont, nameRecords) {
+ if (properties.isInternalFont) {
+ return;
+ }
+ if (properties.hasIncludedToUnicodeMap) {
+ return;
+ }
+ if (properties.hasEncoding) {
+ return;
+ }
+ if (properties.toUnicode instanceof IdentityToUnicodeMap) {
+ return;
+ }
+ if (!isSymbolicFont) {
+ return;
+ }
+ if (nameRecords.length === 0) {
+ return;
+ }
+ if (properties.defaultEncoding === WinAnsiEncoding) {
+ return;
+ }
+ for (const r of nameRecords) {
+ if (!isWinNameRecord(r)) {
+ return;
+ }
+ }
+ const encoding = WinAnsiEncoding;
+ const toUnicode = [],
+ glyphsUnicodeMap = getGlyphsUnicode();
+ for (const charCode in encoding) {
+ const glyphName = encoding[charCode];
+ if (glyphName === "") {
+ continue;
+ }
+ const unicode = glyphsUnicodeMap[glyphName];
+ if (unicode === undefined) {
+ continue;
+ }
+ toUnicode[charCode] = String.fromCharCode(unicode);
+ }
+ if (toUnicode.length > 0) {
+ properties.toUnicode.amend(toUnicode);
+ }
+}
+function adjustType1ToUnicode(properties, builtInEncoding) {
+ if (properties.isInternalFont) {
+ return;
+ }
+ if (properties.hasIncludedToUnicodeMap) {
+ return;
+ }
+ if (builtInEncoding === properties.defaultEncoding) {
+ return;
+ }
+ if (properties.toUnicode instanceof IdentityToUnicodeMap) {
+ return;
+ }
+ const toUnicode = [],
+ glyphsUnicodeMap = getGlyphsUnicode();
+ for (const charCode in builtInEncoding) {
+ if (properties.hasEncoding) {
+ if (properties.baseEncodingName || properties.differences[charCode] !== undefined) {
+ continue;
+ }
+ }
+ const glyphName = builtInEncoding[charCode];
+ const unicode = getUnicodeForGlyph(glyphName, glyphsUnicodeMap);
+ if (unicode !== -1) {
+ toUnicode[charCode] = String.fromCharCode(unicode);
+ }
+ }
+ if (toUnicode.length > 0) {
+ properties.toUnicode.amend(toUnicode);
+ }
+}
+function amendFallbackToUnicode(properties) {
+ if (!properties.fallbackToUnicode) {
+ return;
+ }
+ if (properties.toUnicode instanceof IdentityToUnicodeMap) {
+ return;
+ }
+ const toUnicode = [];
+ for (const charCode in properties.fallbackToUnicode) {
+ if (properties.toUnicode.has(charCode)) {
+ continue;
+ }
+ toUnicode[charCode] = properties.fallbackToUnicode[charCode];
+ }
+ if (toUnicode.length > 0) {
+ properties.toUnicode.amend(toUnicode);
+ }
+}
+class fonts_Glyph {
+ constructor(originalCharCode, fontChar, unicode, accent, width, vmetric, operatorListId, isSpace, isInFont) {
+ this.originalCharCode = originalCharCode;
+ this.fontChar = fontChar;
+ this.unicode = unicode;
+ this.accent = accent;
+ this.width = width;
+ this.vmetric = vmetric;
+ this.operatorListId = operatorListId;
+ this.isSpace = isSpace;
+ this.isInFont = isInFont;
+ }
+ get category() {
+ return shadow(this, "category", getCharUnicodeCategory(this.unicode), true);
+ }
+}
+function int16(b0, b1) {
+ return (b0 << 8) + b1;
+}
+function writeSignedInt16(bytes, index, value) {
+ bytes[index + 1] = value;
+ bytes[index] = value >>> 8;
+}
+function signedInt16(b0, b1) {
+ const value = (b0 << 8) + b1;
+ return value & 1 << 15 ? value - 0x10000 : value;
+}
+function writeUint32(bytes, index, value) {
+ bytes[index + 3] = value & 0xff;
+ bytes[index + 2] = value >>> 8;
+ bytes[index + 1] = value >>> 16;
+ bytes[index] = value >>> 24;
+}
+function int32(b0, b1, b2, b3) {
+ return (b0 << 24) + (b1 << 16) + (b2 << 8) + b3;
+}
+function string16(value) {
+ return String.fromCharCode(value >> 8 & 0xff, value & 0xff);
+}
+function safeString16(value) {
+ if (value > 0x7fff) {
+ value = 0x7fff;
+ } else if (value < -0x8000) {
+ value = -0x8000;
+ }
+ return String.fromCharCode(value >> 8 & 0xff, value & 0xff);
+}
+function isTrueTypeFile(file) {
+ const header = file.peekBytes(4);
+ return readUint32(header, 0) === 0x00010000 || bytesToString(header) === "true";
+}
+function isTrueTypeCollectionFile(file) {
+ const header = file.peekBytes(4);
+ return bytesToString(header) === "ttcf";
+}
+function isOpenTypeFile(file) {
+ const header = file.peekBytes(4);
+ return bytesToString(header) === "OTTO";
+}
+function isType1File(file) {
+ const header = file.peekBytes(2);
+ if (header[0] === 0x25 && header[1] === 0x21) {
+ return true;
+ }
+ if (header[0] === 0x80 && header[1] === 0x01) {
+ return true;
+ }
+ return false;
+}
+function isCFFFile(file) {
+ const header = file.peekBytes(4);
+ if (header[0] >= 1 && header[3] >= 1 && header[3] <= 4) {
+ return true;
+ }
+ return false;
+}
+function getFontFileType(file, {
+ type,
+ subtype,
+ composite
+}) {
+ let fileType, fileSubtype;
+ if (isTrueTypeFile(file) || isTrueTypeCollectionFile(file)) {
+ fileType = composite ? "CIDFontType2" : "TrueType";
+ } else if (isOpenTypeFile(file)) {
+ fileType = composite ? "CIDFontType2" : "OpenType";
+ } else if (isType1File(file)) {
+ if (composite) {
+ fileType = "CIDFontType0";
+ } else {
+ fileType = type === "MMType1" ? "MMType1" : "Type1";
+ }
+ } else if (isCFFFile(file)) {
+ if (composite) {
+ fileType = "CIDFontType0";
+ fileSubtype = "CIDFontType0C";
+ } else {
+ fileType = type === "MMType1" ? "MMType1" : "Type1";
+ fileSubtype = "Type1C";
+ }
+ } else {
+ warn("getFontFileType: Unable to detect correct font file Type/Subtype.");
+ fileType = type;
+ fileSubtype = subtype;
+ }
+ return [fileType, fileSubtype];
+}
+function applyStandardFontGlyphMap(map, glyphMap) {
+ for (const charCode in glyphMap) {
+ map[+charCode] = glyphMap[charCode];
+ }
+}
+function buildToFontChar(encoding, glyphsUnicodeMap, differences) {
+ const toFontChar = [];
+ let unicode;
+ for (let i = 0, ii = encoding.length; i < ii; i++) {
+ unicode = getUnicodeForGlyph(encoding[i], glyphsUnicodeMap);
+ if (unicode !== -1) {
+ toFontChar[i] = unicode;
+ }
+ }
+ for (const charCode in differences) {
+ unicode = getUnicodeForGlyph(differences[charCode], glyphsUnicodeMap);
+ if (unicode !== -1) {
+ toFontChar[+charCode] = unicode;
+ }
+ }
+ return toFontChar;
+}
+function isMacNameRecord(r) {
+ return r.platform === 1 && r.encoding === 0 && r.language === 0;
+}
+function isWinNameRecord(r) {
+ return r.platform === 3 && r.encoding === 1 && r.language === 0x409;
+}
+function convertCidString(charCode, cid, shouldThrow = false) {
+ switch (cid.length) {
+ case 1:
+ return cid.charCodeAt(0);
+ case 2:
+ return cid.charCodeAt(0) << 8 | cid.charCodeAt(1);
+ }
+ const msg = `Unsupported CID string (charCode ${charCode}): "${cid}".`;
+ if (shouldThrow) {
+ throw new FormatError(msg);
+ }
+ warn(msg);
+ return cid;
+}
+function adjustMapping(charCodeToGlyphId, hasGlyph, newGlyphZeroId, toUnicode) {
+ const newMap = Object.create(null);
+ const toUnicodeExtraMap = new Map();
+ const toFontChar = [];
+ const usedGlyphIds = new Set();
+ let privateUseAreaIndex = 0;
+ const privateUseOffetStart = PRIVATE_USE_AREAS[privateUseAreaIndex][0];
+ let nextAvailableFontCharCode = privateUseOffetStart;
+ let privateUseOffetEnd = PRIVATE_USE_AREAS[privateUseAreaIndex][1];
+ const isInPrivateArea = code => PRIVATE_USE_AREAS[0][0] <= code && code <= PRIVATE_USE_AREAS[0][1] || PRIVATE_USE_AREAS[1][0] <= code && code <= PRIVATE_USE_AREAS[1][1];
+ for (let originalCharCode in charCodeToGlyphId) {
+ originalCharCode |= 0;
+ let glyphId = charCodeToGlyphId[originalCharCode];
+ if (!hasGlyph(glyphId)) {
+ continue;
+ }
+ if (nextAvailableFontCharCode > privateUseOffetEnd) {
+ privateUseAreaIndex++;
+ if (privateUseAreaIndex >= PRIVATE_USE_AREAS.length) {
+ warn("Ran out of space in font private use area.");
+ break;
+ }
+ nextAvailableFontCharCode = PRIVATE_USE_AREAS[privateUseAreaIndex][0];
+ privateUseOffetEnd = PRIVATE_USE_AREAS[privateUseAreaIndex][1];
+ }
+ const fontCharCode = nextAvailableFontCharCode++;
+ if (glyphId === 0) {
+ glyphId = newGlyphZeroId;
+ }
+ let unicode = toUnicode.get(originalCharCode);
+ if (typeof unicode === "string") {
+ unicode = unicode.codePointAt(0);
+ }
+ if (unicode && !isInPrivateArea(unicode) && !usedGlyphIds.has(glyphId)) {
+ toUnicodeExtraMap.set(unicode, glyphId);
+ usedGlyphIds.add(glyphId);
+ }
+ newMap[fontCharCode] = glyphId;
+ toFontChar[originalCharCode] = fontCharCode;
+ }
+ return {
+ toFontChar,
+ charCodeToGlyphId: newMap,
+ toUnicodeExtraMap,
+ nextAvailableFontCharCode
+ };
+}
+function getRanges(glyphs, toUnicodeExtraMap, numGlyphs) {
+ const codes = [];
+ for (const charCode in glyphs) {
+ if (glyphs[charCode] >= numGlyphs) {
+ continue;
+ }
+ codes.push({
+ fontCharCode: charCode | 0,
+ glyphId: glyphs[charCode]
+ });
+ }
+ if (toUnicodeExtraMap) {
+ for (const [unicode, glyphId] of toUnicodeExtraMap) {
+ if (glyphId >= numGlyphs) {
+ continue;
+ }
+ codes.push({
+ fontCharCode: unicode,
+ glyphId
+ });
+ }
+ }
+ if (codes.length === 0) {
+ codes.push({
+ fontCharCode: 0,
+ glyphId: 0
+ });
+ }
+ codes.sort(function fontGetRangesSort(a, b) {
+ return a.fontCharCode - b.fontCharCode;
+ });
+ const ranges = [];
+ const length = codes.length;
+ for (let n = 0; n < length;) {
+ const start = codes[n].fontCharCode;
+ const codeIndices = [codes[n].glyphId];
+ ++n;
+ let end = start;
+ while (n < length && end + 1 === codes[n].fontCharCode) {
+ codeIndices.push(codes[n].glyphId);
+ ++end;
+ ++n;
+ if (end === 0xffff) {
+ break;
+ }
+ }
+ ranges.push([start, end, codeIndices]);
+ }
+ return ranges;
+}
+function createCmapTable(glyphs, toUnicodeExtraMap, numGlyphs) {
+ const ranges = getRanges(glyphs, toUnicodeExtraMap, numGlyphs);
+ const numTables = ranges.at(-1)[1] > 0xffff ? 2 : 1;
+ let cmap = "\x00\x00" + string16(numTables) + "\x00\x03" + "\x00\x01" + string32(4 + numTables * 8);
+ let i, ii, j, jj;
+ for (i = ranges.length - 1; i >= 0; --i) {
+ if (ranges[i][0] <= 0xffff) {
+ break;
+ }
+ }
+ const bmpLength = i + 1;
+ if (ranges[i][0] < 0xffff && ranges[i][1] === 0xffff) {
+ ranges[i][1] = 0xfffe;
+ }
+ const trailingRangesCount = ranges[i][1] < 0xffff ? 1 : 0;
+ const segCount = bmpLength + trailingRangesCount;
+ const searchParams = OpenTypeFileBuilder.getSearchParams(segCount, 2);
+ let startCount = "";
+ let endCount = "";
+ let idDeltas = "";
+ let idRangeOffsets = "";
+ let glyphsIds = "";
+ let bias = 0;
+ let range, start, end, codes;
+ for (i = 0, ii = bmpLength; i < ii; i++) {
+ range = ranges[i];
+ start = range[0];
+ end = range[1];
+ startCount += string16(start);
+ endCount += string16(end);
+ codes = range[2];
+ let contiguous = true;
+ for (j = 1, jj = codes.length; j < jj; ++j) {
+ if (codes[j] !== codes[j - 1] + 1) {
+ contiguous = false;
+ break;
+ }
+ }
+ if (!contiguous) {
+ const offset = (segCount - i) * 2 + bias * 2;
+ bias += end - start + 1;
+ idDeltas += string16(0);
+ idRangeOffsets += string16(offset);
+ for (j = 0, jj = codes.length; j < jj; ++j) {
+ glyphsIds += string16(codes[j]);
+ }
+ } else {
+ const startCode = codes[0];
+ idDeltas += string16(startCode - start & 0xffff);
+ idRangeOffsets += string16(0);
+ }
+ }
+ if (trailingRangesCount > 0) {
+ endCount += "\xFF\xFF";
+ startCount += "\xFF\xFF";
+ idDeltas += "\x00\x01";
+ idRangeOffsets += "\x00\x00";
+ }
+ const format314 = "\x00\x00" + string16(2 * segCount) + string16(searchParams.range) + string16(searchParams.entry) + string16(searchParams.rangeShift) + endCount + "\x00\x00" + startCount + idDeltas + idRangeOffsets + glyphsIds;
+ let format31012 = "";
+ let header31012 = "";
+ if (numTables > 1) {
+ cmap += "\x00\x03" + "\x00\x0A" + string32(4 + numTables * 8 + 4 + format314.length);
+ format31012 = "";
+ for (i = 0, ii = ranges.length; i < ii; i++) {
+ range = ranges[i];
+ start = range[0];
+ codes = range[2];
+ let code = codes[0];
+ for (j = 1, jj = codes.length; j < jj; ++j) {
+ if (codes[j] !== codes[j - 1] + 1) {
+ end = range[0] + j - 1;
+ format31012 += string32(start) + string32(end) + string32(code);
+ start = end + 1;
+ code = codes[j];
+ }
+ }
+ format31012 += string32(start) + string32(range[1]) + string32(code);
+ }
+ header31012 = "\x00\x0C" + "\x00\x00" + string32(format31012.length + 16) + "\x00\x00\x00\x00" + string32(format31012.length / 12);
+ }
+ return cmap + "\x00\x04" + string16(format314.length + 4) + format314 + header31012 + format31012;
+}
+function validateOS2Table(os2, file) {
+ file.pos = (file.start || 0) + os2.offset;
+ const version = file.getUint16();
+ file.skip(60);
+ const selection = file.getUint16();
+ if (version < 4 && selection & 0x0300) {
+ return false;
+ }
+ const firstChar = file.getUint16();
+ const lastChar = file.getUint16();
+ if (firstChar > lastChar) {
+ return false;
+ }
+ file.skip(6);
+ const usWinAscent = file.getUint16();
+ if (usWinAscent === 0) {
+ return false;
+ }
+ os2.data[8] = os2.data[9] = 0;
+ return true;
+}
+function createOS2Table(properties, charstrings, override) {
+ override ||= {
+ unitsPerEm: 0,
+ yMax: 0,
+ yMin: 0,
+ ascent: 0,
+ descent: 0
+ };
+ let ulUnicodeRange1 = 0;
+ let ulUnicodeRange2 = 0;
+ let ulUnicodeRange3 = 0;
+ let ulUnicodeRange4 = 0;
+ let firstCharIndex = null;
+ let lastCharIndex = 0;
+ let position = -1;
+ if (charstrings) {
+ for (let code in charstrings) {
+ code |= 0;
+ if (firstCharIndex > code || !firstCharIndex) {
+ firstCharIndex = code;
+ }
+ if (lastCharIndex < code) {
+ lastCharIndex = code;
+ }
+ position = getUnicodeRangeFor(code, position);
+ if (position < 32) {
+ ulUnicodeRange1 |= 1 << position;
+ } else if (position < 64) {
+ ulUnicodeRange2 |= 1 << position - 32;
+ } else if (position < 96) {
+ ulUnicodeRange3 |= 1 << position - 64;
+ } else if (position < 123) {
+ ulUnicodeRange4 |= 1 << position - 96;
+ } else {
+ throw new FormatError("Unicode ranges Bits > 123 are reserved for internal usage");
+ }
+ }
+ if (lastCharIndex > 0xffff) {
+ lastCharIndex = 0xffff;
+ }
+ } else {
+ firstCharIndex = 0;
+ lastCharIndex = 255;
+ }
+ const bbox = properties.bbox || [0, 0, 0, 0];
+ const unitsPerEm = override.unitsPerEm || 1 / (properties.fontMatrix || FONT_IDENTITY_MATRIX)[0];
+ const scale = properties.ascentScaled ? 1.0 : unitsPerEm / PDF_GLYPH_SPACE_UNITS;
+ const typoAscent = override.ascent || Math.round(scale * (properties.ascent || bbox[3]));
+ let typoDescent = override.descent || Math.round(scale * (properties.descent || bbox[1]));
+ if (typoDescent > 0 && properties.descent > 0 && bbox[1] < 0) {
+ typoDescent = -typoDescent;
+ }
+ const winAscent = override.yMax || typoAscent;
+ const winDescent = -override.yMin || -typoDescent;
+ return "\x00\x03" + "\x02\x24" + "\x01\xF4" + "\x00\x05" + "\x00\x00" + "\x02\x8A" + "\x02\xBB" + "\x00\x00" + "\x00\x8C" + "\x02\x8A" + "\x02\xBB" + "\x00\x00" + "\x01\xDF" + "\x00\x31" + "\x01\x02" + "\x00\x00" + "\x00\x00\x06" + String.fromCharCode(properties.fixedPitch ? 0x09 : 0x00) + "\x00\x00\x00\x00\x00\x00" + string32(ulUnicodeRange1) + string32(ulUnicodeRange2) + string32(ulUnicodeRange3) + string32(ulUnicodeRange4) + "\x2A\x32\x31\x2A" + string16(properties.italicAngle ? 1 : 0) + string16(firstCharIndex || properties.firstChar) + string16(lastCharIndex || properties.lastChar) + string16(typoAscent) + string16(typoDescent) + "\x00\x64" + string16(winAscent) + string16(winDescent) + "\x00\x00\x00\x00" + "\x00\x00\x00\x00" + string16(properties.xHeight) + string16(properties.capHeight) + string16(0) + string16(firstCharIndex || properties.firstChar) + "\x00\x03";
+}
+function createPostTable(properties) {
+ const angle = Math.floor(properties.italicAngle * 2 ** 16);
+ return "\x00\x03\x00\x00" + string32(angle) + "\x00\x00" + "\x00\x00" + string32(properties.fixedPitch ? 1 : 0) + "\x00\x00\x00\x00" + "\x00\x00\x00\x00" + "\x00\x00\x00\x00" + "\x00\x00\x00\x00";
+}
+function createPostscriptName(name) {
+ return name.replaceAll(/[^\x21-\x7E]|[[\](){}<>/%]/g, "").slice(0, 63);
+}
+function createNameTable(name, proto) {
+ if (!proto) {
+ proto = [[], []];
+ }
+ const strings = [proto[0][0] || "Original licence", proto[0][1] || name, proto[0][2] || "Unknown", proto[0][3] || "uniqueID", proto[0][4] || name, proto[0][5] || "Version 0.11", proto[0][6] || createPostscriptName(name), proto[0][7] || "Unknown", proto[0][8] || "Unknown", proto[0][9] || "Unknown"];
+ const stringsUnicode = [];
+ let i, ii, j, jj, str;
+ for (i = 0, ii = strings.length; i < ii; i++) {
+ str = proto[1][i] || strings[i];
+ const strBufUnicode = [];
+ for (j = 0, jj = str.length; j < jj; j++) {
+ strBufUnicode.push(string16(str.charCodeAt(j)));
+ }
+ stringsUnicode.push(strBufUnicode.join(""));
+ }
+ const names = [strings, stringsUnicode];
+ const platforms = ["\x00\x01", "\x00\x03"];
+ const encodings = ["\x00\x00", "\x00\x01"];
+ const languages = ["\x00\x00", "\x04\x09"];
+ const namesRecordCount = strings.length * platforms.length;
+ let nameTable = "\x00\x00" + string16(namesRecordCount) + string16(namesRecordCount * 12 + 6);
+ let strOffset = 0;
+ for (i = 0, ii = platforms.length; i < ii; i++) {
+ const strs = names[i];
+ for (j = 0, jj = strs.length; j < jj; j++) {
+ str = strs[j];
+ const nameRecord = platforms[i] + encodings[i] + languages[i] + string16(j) + string16(str.length) + string16(strOffset);
+ nameTable += nameRecord;
+ strOffset += str.length;
+ }
+ }
+ nameTable += strings.join("") + stringsUnicode.join("");
+ return nameTable;
+}
+class Font {
+ constructor(name, file, properties) {
+ this.name = name;
+ this.psName = null;
+ this.mimetype = null;
+ this.disableFontFace = false;
+ this.loadedName = properties.loadedName;
+ this.isType3Font = properties.isType3Font;
+ this.missingFile = false;
+ this.cssFontInfo = properties.cssFontInfo;
+ this._charsCache = Object.create(null);
+ this._glyphCache = Object.create(null);
+ let isSerifFont = !!(properties.flags & FontFlags.Serif);
+ if (!isSerifFont && !properties.isSimulatedFlags) {
+ const baseName = name.replaceAll(/[,_]/g, "-").split("-", 1)[0],
+ serifFonts = getSerifFonts();
+ for (const namePart of baseName.split("+")) {
+ if (serifFonts[namePart]) {
+ isSerifFont = true;
+ break;
+ }
+ }
+ }
+ this.isSerifFont = isSerifFont;
+ this.isSymbolicFont = !!(properties.flags & FontFlags.Symbolic);
+ this.isMonospace = !!(properties.flags & FontFlags.FixedPitch);
+ let {
+ type,
+ subtype
+ } = properties;
+ this.type = type;
+ this.subtype = subtype;
+ this.systemFontInfo = properties.systemFontInfo;
+ const matches = name.match(/^InvalidPDFjsFont_(.*)_\d+$/);
+ this.isInvalidPDFjsFont = !!matches;
+ if (this.isInvalidPDFjsFont) {
+ this.fallbackName = matches[1];
+ } else if (this.isMonospace) {
+ this.fallbackName = "monospace";
+ } else if (this.isSerifFont) {
+ this.fallbackName = "serif";
+ } else {
+ this.fallbackName = "sans-serif";
+ }
+ if (this.systemFontInfo?.guessFallback) {
+ this.systemFontInfo.guessFallback = false;
+ this.systemFontInfo.css += `,${this.fallbackName}`;
+ }
+ this.differences = properties.differences;
+ this.widths = properties.widths;
+ this.defaultWidth = properties.defaultWidth;
+ this.composite = properties.composite;
+ this.cMap = properties.cMap;
+ this.capHeight = properties.capHeight / PDF_GLYPH_SPACE_UNITS;
+ this.ascent = properties.ascent / PDF_GLYPH_SPACE_UNITS;
+ this.descent = properties.descent / PDF_GLYPH_SPACE_UNITS;
+ this.lineHeight = this.ascent - this.descent;
+ this.fontMatrix = properties.fontMatrix;
+ this.bbox = properties.bbox;
+ this.defaultEncoding = properties.defaultEncoding;
+ this.toUnicode = properties.toUnicode;
+ this.toFontChar = [];
+ if (properties.type === "Type3") {
+ for (let charCode = 0; charCode < 256; charCode++) {
+ this.toFontChar[charCode] = this.differences[charCode] || properties.defaultEncoding[charCode];
+ }
+ return;
+ }
+ this.cidEncoding = properties.cidEncoding || "";
+ this.vertical = !!properties.vertical;
+ if (this.vertical) {
+ this.vmetrics = properties.vmetrics;
+ this.defaultVMetrics = properties.defaultVMetrics;
+ }
+ if (!file || file.isEmpty) {
+ if (file) {
+ warn('Font file is empty in "' + name + '" (' + this.loadedName + ")");
+ }
+ this.fallbackToSystemFont(properties);
+ return;
+ }
+ [type, subtype] = getFontFileType(file, properties);
+ if (type !== this.type || subtype !== this.subtype) {
+ info("Inconsistent font file Type/SubType, expected: " + `${this.type}/${this.subtype} but found: ${type}/${subtype}.`);
+ }
+ let data;
+ try {
+ switch (type) {
+ case "MMType1":
+ info("MMType1 font (" + name + "), falling back to Type1.");
+ case "Type1":
+ case "CIDFontType0":
+ this.mimetype = "font/opentype";
+ const cff = subtype === "Type1C" || subtype === "CIDFontType0C" ? new CFFFont(file, properties) : new Type1Font(name, file, properties);
+ adjustWidths(properties);
+ data = this.convert(name, cff, properties);
+ break;
+ case "OpenType":
+ case "TrueType":
+ case "CIDFontType2":
+ this.mimetype = "font/opentype";
+ data = this.checkAndRepair(name, file, properties);
+ if (this.isOpenType) {
+ adjustWidths(properties);
+ type = "OpenType";
+ }
+ break;
+ default:
+ throw new FormatError(`Font ${type} is not supported`);
+ }
+ } catch (e) {
+ warn(e);
+ this.fallbackToSystemFont(properties);
+ return;
+ }
+ amendFallbackToUnicode(properties);
+ this.data = data;
+ this.type = type;
+ this.subtype = subtype;
+ this.fontMatrix = properties.fontMatrix;
+ this.widths = properties.widths;
+ this.defaultWidth = properties.defaultWidth;
+ this.toUnicode = properties.toUnicode;
+ this.seacMap = properties.seacMap;
+ }
+ get renderer() {
+ const renderer = FontRendererFactory.create(this, SEAC_ANALYSIS_ENABLED);
+ return shadow(this, "renderer", renderer);
+ }
+ exportData(extraProperties = false) {
+ const exportDataProperties = extraProperties ? [...EXPORT_DATA_PROPERTIES, ...EXPORT_DATA_EXTRA_PROPERTIES] : EXPORT_DATA_PROPERTIES;
+ const data = Object.create(null);
+ let property, value;
+ for (property of exportDataProperties) {
+ value = this[property];
+ if (value !== undefined) {
+ data[property] = value;
+ }
+ }
+ return data;
+ }
+ fallbackToSystemFont(properties) {
+ this.missingFile = true;
+ const {
+ name,
+ type
+ } = this;
+ let fontName = normalizeFontName(name);
+ const stdFontMap = getStdFontMap(),
+ nonStdFontMap = getNonStdFontMap();
+ const isStandardFont = !!stdFontMap[fontName];
+ const isMappedToStandardFont = !!(nonStdFontMap[fontName] && stdFontMap[nonStdFontMap[fontName]]);
+ fontName = stdFontMap[fontName] || nonStdFontMap[fontName] || fontName;
+ const fontBasicMetricsMap = getFontBasicMetrics();
+ const metrics = fontBasicMetricsMap[fontName];
+ if (metrics) {
+ if (isNaN(this.ascent)) {
+ this.ascent = metrics.ascent / PDF_GLYPH_SPACE_UNITS;
+ }
+ if (isNaN(this.descent)) {
+ this.descent = metrics.descent / PDF_GLYPH_SPACE_UNITS;
+ }
+ if (isNaN(this.capHeight)) {
+ this.capHeight = metrics.capHeight / PDF_GLYPH_SPACE_UNITS;
+ }
+ }
+ this.bold = /bold/gi.test(fontName);
+ this.italic = /oblique|italic/gi.test(fontName);
+ this.black = /Black/g.test(name);
+ const isNarrow = /Narrow/g.test(name);
+ this.remeasure = (!isStandardFont || isNarrow) && Object.keys(this.widths).length > 0;
+ if ((isStandardFont || isMappedToStandardFont) && type === "CIDFontType2" && this.cidEncoding.startsWith("Identity-")) {
+ const cidToGidMap = properties.cidToGidMap;
+ const map = [];
+ applyStandardFontGlyphMap(map, getGlyphMapForStandardFonts());
+ if (/Arial-?Black/i.test(name)) {
+ applyStandardFontGlyphMap(map, getSupplementalGlyphMapForArialBlack());
+ } else if (/Calibri/i.test(name)) {
+ applyStandardFontGlyphMap(map, getSupplementalGlyphMapForCalibri());
+ }
+ if (cidToGidMap) {
+ for (const charCode in map) {
+ const cid = map[charCode];
+ if (cidToGidMap[cid] !== undefined) {
+ map[+charCode] = cidToGidMap[cid];
+ }
+ }
+ if (cidToGidMap.length !== this.toUnicode.length && properties.hasIncludedToUnicodeMap && this.toUnicode instanceof IdentityToUnicodeMap) {
+ this.toUnicode.forEach(function (charCode, unicodeCharCode) {
+ const cid = map[charCode];
+ if (cidToGidMap[cid] === undefined) {
+ map[+charCode] = unicodeCharCode;
+ }
+ });
+ }
+ }
+ if (!(this.toUnicode instanceof IdentityToUnicodeMap)) {
+ this.toUnicode.forEach(function (charCode, unicodeCharCode) {
+ map[+charCode] = unicodeCharCode;
+ });
+ }
+ this.toFontChar = map;
+ this.toUnicode = new ToUnicodeMap(map);
+ } else if (/Symbol/i.test(fontName)) {
+ this.toFontChar = buildToFontChar(SymbolSetEncoding, getGlyphsUnicode(), this.differences);
+ } else if (/Dingbats/i.test(fontName)) {
+ this.toFontChar = buildToFontChar(ZapfDingbatsEncoding, getDingbatsGlyphsUnicode(), this.differences);
+ } else if (isStandardFont) {
+ const map = buildToFontChar(this.defaultEncoding, getGlyphsUnicode(), this.differences);
+ if (type === "CIDFontType2" && !this.cidEncoding.startsWith("Identity-") && !(this.toUnicode instanceof IdentityToUnicodeMap)) {
+ this.toUnicode.forEach(function (charCode, unicodeCharCode) {
+ map[+charCode] = unicodeCharCode;
+ });
+ }
+ this.toFontChar = map;
+ } else {
+ const glyphsUnicodeMap = getGlyphsUnicode();
+ const map = [];
+ this.toUnicode.forEach((charCode, unicodeCharCode) => {
+ if (!this.composite) {
+ const glyphName = this.differences[charCode] || this.defaultEncoding[charCode];
+ const unicode = getUnicodeForGlyph(glyphName, glyphsUnicodeMap);
+ if (unicode !== -1) {
+ unicodeCharCode = unicode;
+ }
+ }
+ map[+charCode] = unicodeCharCode;
+ });
+ if (this.composite && this.toUnicode instanceof IdentityToUnicodeMap) {
+ if (/Tahoma|Verdana/i.test(name)) {
+ applyStandardFontGlyphMap(map, getGlyphMapForStandardFonts());
+ }
+ }
+ this.toFontChar = map;
+ }
+ amendFallbackToUnicode(properties);
+ this.loadedName = fontName.split("-", 1)[0];
+ }
+ checkAndRepair(name, font, properties) {
+ const VALID_TABLES = ["OS/2", "cmap", "head", "hhea", "hmtx", "maxp", "name", "post", "loca", "glyf", "fpgm", "prep", "cvt ", "CFF "];
+ function readTables(file, numTables) {
+ const tables = Object.create(null);
+ tables["OS/2"] = null;
+ tables.cmap = null;
+ tables.head = null;
+ tables.hhea = null;
+ tables.hmtx = null;
+ tables.maxp = null;
+ tables.name = null;
+ tables.post = null;
+ for (let i = 0; i < numTables; i++) {
+ const table = readTableEntry(file);
+ if (!VALID_TABLES.includes(table.tag)) {
+ continue;
+ }
+ if (table.length === 0) {
+ continue;
+ }
+ tables[table.tag] = table;
+ }
+ return tables;
+ }
+ function readTableEntry(file) {
+ const tag = file.getString(4);
+ const checksum = file.getInt32() >>> 0;
+ const offset = file.getInt32() >>> 0;
+ const length = file.getInt32() >>> 0;
+ const previousPosition = file.pos;
+ file.pos = file.start || 0;
+ file.skip(offset);
+ const data = file.getBytes(length);
+ file.pos = previousPosition;
+ if (tag === "head") {
+ data[8] = data[9] = data[10] = data[11] = 0;
+ data[17] |= 0x20;
+ }
+ return {
+ tag,
+ checksum,
+ length,
+ offset,
+ data
+ };
+ }
+ function readOpenTypeHeader(ttf) {
+ return {
+ version: ttf.getString(4),
+ numTables: ttf.getUint16(),
+ searchRange: ttf.getUint16(),
+ entrySelector: ttf.getUint16(),
+ rangeShift: ttf.getUint16()
+ };
+ }
+ function readTrueTypeCollectionHeader(ttc) {
+ const ttcTag = ttc.getString(4);
+ assert(ttcTag === "ttcf", "Must be a TrueType Collection font.");
+ const majorVersion = ttc.getUint16();
+ const minorVersion = ttc.getUint16();
+ const numFonts = ttc.getInt32() >>> 0;
+ const offsetTable = [];
+ for (let i = 0; i < numFonts; i++) {
+ offsetTable.push(ttc.getInt32() >>> 0);
+ }
+ const header = {
+ ttcTag,
+ majorVersion,
+ minorVersion,
+ numFonts,
+ offsetTable
+ };
+ switch (majorVersion) {
+ case 1:
+ return header;
+ case 2:
+ header.dsigTag = ttc.getInt32() >>> 0;
+ header.dsigLength = ttc.getInt32() >>> 0;
+ header.dsigOffset = ttc.getInt32() >>> 0;
+ return header;
+ }
+ throw new FormatError(`Invalid TrueType Collection majorVersion: ${majorVersion}.`);
+ }
+ function readTrueTypeCollectionData(ttc, fontName) {
+ const {
+ numFonts,
+ offsetTable
+ } = readTrueTypeCollectionHeader(ttc);
+ const fontNameParts = fontName.split("+");
+ let fallbackData;
+ for (let i = 0; i < numFonts; i++) {
+ ttc.pos = (ttc.start || 0) + offsetTable[i];
+ const potentialHeader = readOpenTypeHeader(ttc);
+ const potentialTables = readTables(ttc, potentialHeader.numTables);
+ if (!potentialTables.name) {
+ throw new FormatError('TrueType Collection font must contain a "name" table.');
+ }
+ const [nameTable] = readNameTable(potentialTables.name);
+ for (let j = 0, jj = nameTable.length; j < jj; j++) {
+ for (let k = 0, kk = nameTable[j].length; k < kk; k++) {
+ const nameEntry = nameTable[j][k]?.replaceAll(/\s/g, "");
+ if (!nameEntry) {
+ continue;
+ }
+ if (nameEntry === fontName) {
+ return {
+ header: potentialHeader,
+ tables: potentialTables
+ };
+ }
+ if (fontNameParts.length < 2) {
+ continue;
+ }
+ for (const part of fontNameParts) {
+ if (nameEntry === part) {
+ fallbackData = {
+ name: part,
+ header: potentialHeader,
+ tables: potentialTables
+ };
+ }
+ }
+ }
+ }
+ }
+ if (fallbackData) {
+ warn(`TrueType Collection does not contain "${fontName}" font, ` + `falling back to "${fallbackData.name}" font instead.`);
+ return {
+ header: fallbackData.header,
+ tables: fallbackData.tables
+ };
+ }
+ throw new FormatError(`TrueType Collection does not contain "${fontName}" font.`);
+ }
+ function readCmapTable(cmap, file, isSymbolicFont, hasEncoding) {
+ if (!cmap) {
+ warn("No cmap table available.");
+ return {
+ platformId: -1,
+ encodingId: -1,
+ mappings: [],
+ hasShortCmap: false
+ };
+ }
+ let segment;
+ let start = (file.start || 0) + cmap.offset;
+ file.pos = start;
+ file.skip(2);
+ const numTables = file.getUint16();
+ let potentialTable;
+ let canBreak = false;
+ for (let i = 0; i < numTables; i++) {
+ const platformId = file.getUint16();
+ const encodingId = file.getUint16();
+ const offset = file.getInt32() >>> 0;
+ let useTable = false;
+ if (potentialTable?.platformId === platformId && potentialTable?.encodingId === encodingId) {
+ continue;
+ }
+ if (platformId === 0 && (encodingId === 0 || encodingId === 1 || encodingId === 3)) {
+ useTable = true;
+ } else if (platformId === 1 && encodingId === 0) {
+ useTable = true;
+ } else if (platformId === 3 && encodingId === 1 && (hasEncoding || !potentialTable)) {
+ useTable = true;
+ if (!isSymbolicFont) {
+ canBreak = true;
+ }
+ } else if (isSymbolicFont && platformId === 3 && encodingId === 0) {
+ useTable = true;
+ let correctlySorted = true;
+ if (i < numTables - 1) {
+ const nextBytes = file.peekBytes(2),
+ nextPlatformId = int16(nextBytes[0], nextBytes[1]);
+ if (nextPlatformId < platformId) {
+ correctlySorted = false;
+ }
+ }
+ if (correctlySorted) {
+ canBreak = true;
+ }
+ }
+ if (useTable) {
+ potentialTable = {
+ platformId,
+ encodingId,
+ offset
+ };
+ }
+ if (canBreak) {
+ break;
+ }
+ }
+ if (potentialTable) {
+ file.pos = start + potentialTable.offset;
+ }
+ if (!potentialTable || file.peekByte() === -1) {
+ warn("Could not find a preferred cmap table.");
+ return {
+ platformId: -1,
+ encodingId: -1,
+ mappings: [],
+ hasShortCmap: false
+ };
+ }
+ const format = file.getUint16();
+ let hasShortCmap = false;
+ const mappings = [];
+ let j, glyphId;
+ if (format === 0) {
+ file.skip(2 + 2);
+ for (j = 0; j < 256; j++) {
+ const index = file.getByte();
+ if (!index) {
+ continue;
+ }
+ mappings.push({
+ charCode: j,
+ glyphId: index
+ });
+ }
+ hasShortCmap = true;
+ } else if (format === 2) {
+ file.skip(2 + 2);
+ const subHeaderKeys = [];
+ let maxSubHeaderKey = 0;
+ for (let i = 0; i < 256; i++) {
+ const subHeaderKey = file.getUint16() >> 3;
+ subHeaderKeys.push(subHeaderKey);
+ maxSubHeaderKey = Math.max(subHeaderKey, maxSubHeaderKey);
+ }
+ const subHeaders = [];
+ for (let i = 0; i <= maxSubHeaderKey; i++) {
+ subHeaders.push({
+ firstCode: file.getUint16(),
+ entryCount: file.getUint16(),
+ idDelta: signedInt16(file.getByte(), file.getByte()),
+ idRangePos: file.pos + file.getUint16()
+ });
+ }
+ for (let i = 0; i < 256; i++) {
+ if (subHeaderKeys[i] === 0) {
+ file.pos = subHeaders[0].idRangePos + 2 * i;
+ glyphId = file.getUint16();
+ mappings.push({
+ charCode: i,
+ glyphId
+ });
+ } else {
+ const s = subHeaders[subHeaderKeys[i]];
+ for (j = 0; j < s.entryCount; j++) {
+ const charCode = (i << 8) + j + s.firstCode;
+ file.pos = s.idRangePos + 2 * j;
+ glyphId = file.getUint16();
+ if (glyphId !== 0) {
+ glyphId = (glyphId + s.idDelta) % 65536;
+ }
+ mappings.push({
+ charCode,
+ glyphId
+ });
+ }
+ }
+ }
+ } else if (format === 4) {
+ file.skip(2 + 2);
+ const segCount = file.getUint16() >> 1;
+ file.skip(6);
+ const segments = [];
+ let segIndex;
+ for (segIndex = 0; segIndex < segCount; segIndex++) {
+ segments.push({
+ end: file.getUint16()
+ });
+ }
+ file.skip(2);
+ for (segIndex = 0; segIndex < segCount; segIndex++) {
+ segments[segIndex].start = file.getUint16();
+ }
+ for (segIndex = 0; segIndex < segCount; segIndex++) {
+ segments[segIndex].delta = file.getUint16();
+ }
+ let offsetsCount = 0,
+ offsetIndex;
+ for (segIndex = 0; segIndex < segCount; segIndex++) {
+ segment = segments[segIndex];
+ const rangeOffset = file.getUint16();
+ if (!rangeOffset) {
+ segment.offsetIndex = -1;
+ continue;
+ }
+ offsetIndex = (rangeOffset >> 1) - (segCount - segIndex);
+ segment.offsetIndex = offsetIndex;
+ offsetsCount = Math.max(offsetsCount, offsetIndex + segment.end - segment.start + 1);
+ }
+ const offsets = [];
+ for (j = 0; j < offsetsCount; j++) {
+ offsets.push(file.getUint16());
+ }
+ for (segIndex = 0; segIndex < segCount; segIndex++) {
+ segment = segments[segIndex];
+ start = segment.start;
+ const end = segment.end;
+ const delta = segment.delta;
+ offsetIndex = segment.offsetIndex;
+ for (j = start; j <= end; j++) {
+ if (j === 0xffff) {
+ continue;
+ }
+ glyphId = offsetIndex < 0 ? j : offsets[offsetIndex + j - start];
+ glyphId = glyphId + delta & 0xffff;
+ mappings.push({
+ charCode: j,
+ glyphId
+ });
+ }
+ }
+ } else if (format === 6) {
+ file.skip(2 + 2);
+ const firstCode = file.getUint16();
+ const entryCount = file.getUint16();
+ for (j = 0; j < entryCount; j++) {
+ glyphId = file.getUint16();
+ const charCode = firstCode + j;
+ mappings.push({
+ charCode,
+ glyphId
+ });
+ }
+ } else if (format === 12) {
+ file.skip(2 + 4 + 4);
+ const nGroups = file.getInt32() >>> 0;
+ for (j = 0; j < nGroups; j++) {
+ const startCharCode = file.getInt32() >>> 0;
+ const endCharCode = file.getInt32() >>> 0;
+ let glyphCode = file.getInt32() >>> 0;
+ for (let charCode = startCharCode; charCode <= endCharCode; charCode++) {
+ mappings.push({
+ charCode,
+ glyphId: glyphCode++
+ });
+ }
+ }
+ } else {
+ warn("cmap table has unsupported format: " + format);
+ return {
+ platformId: -1,
+ encodingId: -1,
+ mappings: [],
+ hasShortCmap: false
+ };
+ }
+ mappings.sort(function (a, b) {
+ return a.charCode - b.charCode;
+ });
+ for (let i = 1; i < mappings.length; i++) {
+ if (mappings[i - 1].charCode === mappings[i].charCode) {
+ mappings.splice(i, 1);
+ i--;
+ }
+ }
+ return {
+ platformId: potentialTable.platformId,
+ encodingId: potentialTable.encodingId,
+ mappings,
+ hasShortCmap
+ };
+ }
+ function sanitizeMetrics(file, header, metrics, headTable, numGlyphs, dupFirstEntry) {
+ if (!header) {
+ if (metrics) {
+ metrics.data = null;
+ }
+ return;
+ }
+ file.pos = (file.start || 0) + header.offset;
+ file.pos += 4;
+ file.pos += 2;
+ file.pos += 2;
+ file.pos += 2;
+ file.pos += 2;
+ file.pos += 2;
+ file.pos += 2;
+ file.pos += 2;
+ file.pos += 2;
+ file.pos += 2;
+ const caretOffset = file.getUint16();
+ file.pos += 8;
+ file.pos += 2;
+ let numOfMetrics = file.getUint16();
+ if (caretOffset !== 0) {
+ const macStyle = int16(headTable.data[44], headTable.data[45]);
+ if (!(macStyle & 2)) {
+ header.data[22] = 0;
+ header.data[23] = 0;
+ }
+ }
+ if (numOfMetrics > numGlyphs) {
+ info(`The numOfMetrics (${numOfMetrics}) should not be ` + `greater than the numGlyphs (${numGlyphs}).`);
+ numOfMetrics = numGlyphs;
+ header.data[34] = (numOfMetrics & 0xff00) >> 8;
+ header.data[35] = numOfMetrics & 0x00ff;
+ }
+ const numOfSidebearings = numGlyphs - numOfMetrics;
+ const numMissing = numOfSidebearings - (metrics.length - numOfMetrics * 4 >> 1);
+ if (numMissing > 0) {
+ const entries = new Uint8Array(metrics.length + numMissing * 2);
+ entries.set(metrics.data);
+ if (dupFirstEntry) {
+ entries[metrics.length] = metrics.data[2];
+ entries[metrics.length + 1] = metrics.data[3];
+ }
+ metrics.data = entries;
+ }
+ }
+ function sanitizeGlyph(source, sourceStart, sourceEnd, dest, destStart, hintsValid) {
+ const glyphProfile = {
+ length: 0,
+ sizeOfInstructions: 0
+ };
+ if (sourceStart < 0 || sourceStart >= source.length || sourceEnd > source.length || sourceEnd - sourceStart <= 12) {
+ return glyphProfile;
+ }
+ const glyf = source.subarray(sourceStart, sourceEnd);
+ const xMin = signedInt16(glyf[2], glyf[3]);
+ const yMin = signedInt16(glyf[4], glyf[5]);
+ const xMax = signedInt16(glyf[6], glyf[7]);
+ const yMax = signedInt16(glyf[8], glyf[9]);
+ if (xMin > xMax) {
+ writeSignedInt16(glyf, 2, xMax);
+ writeSignedInt16(glyf, 6, xMin);
+ }
+ if (yMin > yMax) {
+ writeSignedInt16(glyf, 4, yMax);
+ writeSignedInt16(glyf, 8, yMin);
+ }
+ const contoursCount = signedInt16(glyf[0], glyf[1]);
+ if (contoursCount < 0) {
+ if (contoursCount < -1) {
+ return glyphProfile;
+ }
+ dest.set(glyf, destStart);
+ glyphProfile.length = glyf.length;
+ return glyphProfile;
+ }
+ let i,
+ j = 10,
+ flagsCount = 0;
+ for (i = 0; i < contoursCount; i++) {
+ const endPoint = glyf[j] << 8 | glyf[j + 1];
+ flagsCount = endPoint + 1;
+ j += 2;
+ }
+ const instructionsStart = j;
+ const instructionsLength = glyf[j] << 8 | glyf[j + 1];
+ glyphProfile.sizeOfInstructions = instructionsLength;
+ j += 2 + instructionsLength;
+ const instructionsEnd = j;
+ let coordinatesLength = 0;
+ for (i = 0; i < flagsCount; i++) {
+ const flag = glyf[j++];
+ if (flag & 0xc0) {
+ glyf[j - 1] = flag & 0x3f;
+ }
+ let xLength = 2;
+ if (flag & 2) {
+ xLength = 1;
+ } else if (flag & 16) {
+ xLength = 0;
+ }
+ let yLength = 2;
+ if (flag & 4) {
+ yLength = 1;
+ } else if (flag & 32) {
+ yLength = 0;
+ }
+ const xyLength = xLength + yLength;
+ coordinatesLength += xyLength;
+ if (flag & 8) {
+ const repeat = glyf[j++];
+ if (repeat === 0) {
+ glyf[j - 1] ^= 8;
+ }
+ i += repeat;
+ coordinatesLength += repeat * xyLength;
+ }
+ }
+ if (coordinatesLength === 0) {
+ return glyphProfile;
+ }
+ let glyphDataLength = j + coordinatesLength;
+ if (glyphDataLength > glyf.length) {
+ return glyphProfile;
+ }
+ if (!hintsValid && instructionsLength > 0) {
+ dest.set(glyf.subarray(0, instructionsStart), destStart);
+ dest.set([0, 0], destStart + instructionsStart);
+ dest.set(glyf.subarray(instructionsEnd, glyphDataLength), destStart + instructionsStart + 2);
+ glyphDataLength -= instructionsLength;
+ if (glyf.length - glyphDataLength > 3) {
+ glyphDataLength = glyphDataLength + 3 & ~3;
+ }
+ glyphProfile.length = glyphDataLength;
+ return glyphProfile;
+ }
+ if (glyf.length - glyphDataLength > 3) {
+ glyphDataLength = glyphDataLength + 3 & ~3;
+ dest.set(glyf.subarray(0, glyphDataLength), destStart);
+ glyphProfile.length = glyphDataLength;
+ return glyphProfile;
+ }
+ dest.set(glyf, destStart);
+ glyphProfile.length = glyf.length;
+ return glyphProfile;
+ }
+ function sanitizeHead(head, numGlyphs, locaLength) {
+ const data = head.data;
+ const version = int32(data[0], data[1], data[2], data[3]);
+ if (version >> 16 !== 1) {
+ info("Attempting to fix invalid version in head table: " + version);
+ data[0] = 0;
+ data[1] = 1;
+ data[2] = 0;
+ data[3] = 0;
+ }
+ const indexToLocFormat = int16(data[50], data[51]);
+ if (indexToLocFormat < 0 || indexToLocFormat > 1) {
+ info("Attempting to fix invalid indexToLocFormat in head table: " + indexToLocFormat);
+ const numGlyphsPlusOne = numGlyphs + 1;
+ if (locaLength === numGlyphsPlusOne << 1) {
+ data[50] = 0;
+ data[51] = 0;
+ } else if (locaLength === numGlyphsPlusOne << 2) {
+ data[50] = 0;
+ data[51] = 1;
+ } else {
+ throw new FormatError("Could not fix indexToLocFormat: " + indexToLocFormat);
+ }
+ }
+ }
+ function sanitizeGlyphLocations(loca, glyf, numGlyphs, isGlyphLocationsLong, hintsValid, dupFirstEntry, maxSizeOfInstructions) {
+ let itemSize, itemDecode, itemEncode;
+ if (isGlyphLocationsLong) {
+ itemSize = 4;
+ itemDecode = function fontItemDecodeLong(data, offset) {
+ return data[offset] << 24 | data[offset + 1] << 16 | data[offset + 2] << 8 | data[offset + 3];
+ };
+ itemEncode = function fontItemEncodeLong(data, offset, value) {
+ data[offset] = value >>> 24 & 0xff;
+ data[offset + 1] = value >> 16 & 0xff;
+ data[offset + 2] = value >> 8 & 0xff;
+ data[offset + 3] = value & 0xff;
+ };
+ } else {
+ itemSize = 2;
+ itemDecode = function fontItemDecode(data, offset) {
+ return data[offset] << 9 | data[offset + 1] << 1;
+ };
+ itemEncode = function fontItemEncode(data, offset, value) {
+ data[offset] = value >> 9 & 0xff;
+ data[offset + 1] = value >> 1 & 0xff;
+ };
+ }
+ const numGlyphsOut = dupFirstEntry ? numGlyphs + 1 : numGlyphs;
+ const locaDataSize = itemSize * (1 + numGlyphsOut);
+ const locaData = new Uint8Array(locaDataSize);
+ locaData.set(loca.data.subarray(0, locaDataSize));
+ loca.data = locaData;
+ const oldGlyfData = glyf.data;
+ const oldGlyfDataLength = oldGlyfData.length;
+ const newGlyfData = new Uint8Array(oldGlyfDataLength);
+ let i, j;
+ const locaEntries = [];
+ for (i = 0, j = 0; i < numGlyphs + 1; i++, j += itemSize) {
+ let offset = itemDecode(locaData, j);
+ if (offset > oldGlyfDataLength) {
+ offset = oldGlyfDataLength;
+ }
+ locaEntries.push({
+ index: i,
+ offset,
+ endOffset: 0
+ });
+ }
+ locaEntries.sort((a, b) => a.offset - b.offset);
+ for (i = 0; i < numGlyphs; i++) {
+ locaEntries[i].endOffset = locaEntries[i + 1].offset;
+ }
+ locaEntries.sort((a, b) => a.index - b.index);
+ for (i = 0; i < numGlyphs; i++) {
+ const {
+ offset,
+ endOffset
+ } = locaEntries[i];
+ if (offset !== 0 || endOffset !== 0) {
+ break;
+ }
+ const nextOffset = locaEntries[i + 1].offset;
+ if (nextOffset === 0) {
+ continue;
+ }
+ locaEntries[i].endOffset = nextOffset;
+ break;
+ }
+ const last = locaEntries.at(-2);
+ if (last.offset !== 0 && last.endOffset === 0) {
+ last.endOffset = oldGlyfDataLength;
+ }
+ const missingGlyphs = Object.create(null);
+ let writeOffset = 0;
+ itemEncode(locaData, 0, writeOffset);
+ for (i = 0, j = itemSize; i < numGlyphs; i++, j += itemSize) {
+ const glyphProfile = sanitizeGlyph(oldGlyfData, locaEntries[i].offset, locaEntries[i].endOffset, newGlyfData, writeOffset, hintsValid);
+ const newLength = glyphProfile.length;
+ if (newLength === 0) {
+ missingGlyphs[i] = true;
+ }
+ if (glyphProfile.sizeOfInstructions > maxSizeOfInstructions) {
+ maxSizeOfInstructions = glyphProfile.sizeOfInstructions;
+ }
+ writeOffset += newLength;
+ itemEncode(locaData, j, writeOffset);
+ }
+ if (writeOffset === 0) {
+ const simpleGlyph = new Uint8Array([0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 0]);
+ for (i = 0, j = itemSize; i < numGlyphsOut; i++, j += itemSize) {
+ itemEncode(locaData, j, simpleGlyph.length);
+ }
+ glyf.data = simpleGlyph;
+ } else if (dupFirstEntry) {
+ const firstEntryLength = itemDecode(locaData, itemSize);
+ if (newGlyfData.length > firstEntryLength + writeOffset) {
+ glyf.data = newGlyfData.subarray(0, firstEntryLength + writeOffset);
+ } else {
+ glyf.data = new Uint8Array(firstEntryLength + writeOffset);
+ glyf.data.set(newGlyfData.subarray(0, writeOffset));
+ }
+ glyf.data.set(newGlyfData.subarray(0, firstEntryLength), writeOffset);
+ itemEncode(loca.data, locaData.length - itemSize, writeOffset + firstEntryLength);
+ } else {
+ glyf.data = newGlyfData.subarray(0, writeOffset);
+ }
+ return {
+ missingGlyphs,
+ maxSizeOfInstructions
+ };
+ }
+ function readPostScriptTable(post, propertiesObj, maxpNumGlyphs) {
+ const start = (font.start || 0) + post.offset;
+ font.pos = start;
+ const length = post.length,
+ end = start + length;
+ const version = font.getInt32();
+ font.skip(28);
+ let glyphNames;
+ let valid = true;
+ let i;
+ switch (version) {
+ case 0x00010000:
+ glyphNames = MacStandardGlyphOrdering;
+ break;
+ case 0x00020000:
+ const numGlyphs = font.getUint16();
+ if (numGlyphs !== maxpNumGlyphs) {
+ valid = false;
+ break;
+ }
+ const glyphNameIndexes = [];
+ for (i = 0; i < numGlyphs; ++i) {
+ const index = font.getUint16();
+ if (index >= 32768) {
+ valid = false;
+ break;
+ }
+ glyphNameIndexes.push(index);
+ }
+ if (!valid) {
+ break;
+ }
+ const customNames = [],
+ strBuf = [];
+ while (font.pos < end) {
+ const stringLength = font.getByte();
+ strBuf.length = stringLength;
+ for (i = 0; i < stringLength; ++i) {
+ strBuf[i] = String.fromCharCode(font.getByte());
+ }
+ customNames.push(strBuf.join(""));
+ }
+ glyphNames = [];
+ for (i = 0; i < numGlyphs; ++i) {
+ const j = glyphNameIndexes[i];
+ if (j < 258) {
+ glyphNames.push(MacStandardGlyphOrdering[j]);
+ continue;
+ }
+ glyphNames.push(customNames[j - 258]);
+ }
+ break;
+ case 0x00030000:
+ break;
+ default:
+ warn("Unknown/unsupported post table version " + version);
+ valid = false;
+ if (propertiesObj.defaultEncoding) {
+ glyphNames = propertiesObj.defaultEncoding;
+ }
+ break;
+ }
+ propertiesObj.glyphNames = glyphNames;
+ return valid;
+ }
+ function readNameTable(nameTable) {
+ const start = (font.start || 0) + nameTable.offset;
+ font.pos = start;
+ const names = [[], []],
+ records = [];
+ const length = nameTable.length,
+ end = start + length;
+ const format = font.getUint16();
+ const FORMAT_0_HEADER_LENGTH = 6;
+ if (format !== 0 || length < FORMAT_0_HEADER_LENGTH) {
+ return [names, records];
+ }
+ const numRecords = font.getUint16();
+ const stringsStart = font.getUint16();
+ const NAME_RECORD_LENGTH = 12;
+ let i, ii;
+ for (i = 0; i < numRecords && font.pos + NAME_RECORD_LENGTH <= end; i++) {
+ const r = {
+ platform: font.getUint16(),
+ encoding: font.getUint16(),
+ language: font.getUint16(),
+ name: font.getUint16(),
+ length: font.getUint16(),
+ offset: font.getUint16()
+ };
+ if (isMacNameRecord(r) || isWinNameRecord(r)) {
+ records.push(r);
+ }
+ }
+ for (i = 0, ii = records.length; i < ii; i++) {
+ const record = records[i];
+ if (record.length <= 0) {
+ continue;
+ }
+ const pos = start + stringsStart + record.offset;
+ if (pos + record.length > end) {
+ continue;
+ }
+ font.pos = pos;
+ const nameIndex = record.name;
+ if (record.encoding) {
+ let str = "";
+ for (let j = 0, jj = record.length; j < jj; j += 2) {
+ str += String.fromCharCode(font.getUint16());
+ }
+ names[1][nameIndex] = str;
+ } else {
+ names[0][nameIndex] = font.getString(record.length);
+ }
+ }
+ return [names, records];
+ }
+ const TTOpsStackDeltas = [0, 0, 0, 0, 0, 0, 0, 0, -2, -2, -2, -2, 0, 0, -2, -5, -1, -1, -1, -1, -1, -1, -1, -1, 0, 0, -1, 0, -1, -1, -1, -1, 1, -1, -999, 0, 1, 0, -1, -2, 0, -1, -2, -1, -1, 0, -1, -1, 0, 0, -999, -999, -1, -1, -1, -1, -2, -999, -2, -2, -999, 0, -2, -2, 0, 0, -2, 0, -2, 0, 0, 0, -2, -1, -1, 1, 1, 0, 0, -1, -1, -1, -1, -1, -1, -1, 0, 0, -1, 0, -1, -1, 0, -999, -1, -1, -1, -1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2, -999, -999, -999, -999, -999, -1, -1, -2, -2, 0, 0, 0, 0, -1, -1, -999, -2, -2, 0, 0, -1, -2, -2, 0, 0, 0, -1, -1, -1, -2];
+ function sanitizeTTProgram(table, ttContext) {
+ let data = table.data;
+ let i = 0,
+ j,
+ n,
+ b,
+ funcId,
+ pc,
+ lastEndf = 0,
+ lastDeff = 0;
+ const stack = [];
+ const callstack = [];
+ const functionsCalled = [];
+ let tooComplexToFollowFunctions = ttContext.tooComplexToFollowFunctions;
+ let inFDEF = false,
+ ifLevel = 0,
+ inELSE = 0;
+ for (let ii = data.length; i < ii;) {
+ const op = data[i++];
+ if (op === 0x40) {
+ n = data[i++];
+ if (inFDEF || inELSE) {
+ i += n;
+ } else {
+ for (j = 0; j < n; j++) {
+ stack.push(data[i++]);
+ }
+ }
+ } else if (op === 0x41) {
+ n = data[i++];
+ if (inFDEF || inELSE) {
+ i += n * 2;
+ } else {
+ for (j = 0; j < n; j++) {
+ b = data[i++];
+ stack.push(b << 8 | data[i++]);
+ }
+ }
+ } else if ((op & 0xf8) === 0xb0) {
+ n = op - 0xb0 + 1;
+ if (inFDEF || inELSE) {
+ i += n;
+ } else {
+ for (j = 0; j < n; j++) {
+ stack.push(data[i++]);
+ }
+ }
+ } else if ((op & 0xf8) === 0xb8) {
+ n = op - 0xb8 + 1;
+ if (inFDEF || inELSE) {
+ i += n * 2;
+ } else {
+ for (j = 0; j < n; j++) {
+ b = data[i++];
+ stack.push(b << 8 | data[i++]);
+ }
+ }
+ } else if (op === 0x2b && !tooComplexToFollowFunctions) {
+ if (!inFDEF && !inELSE) {
+ funcId = stack.at(-1);
+ if (isNaN(funcId)) {
+ info("TT: CALL empty stack (or invalid entry).");
+ } else {
+ ttContext.functionsUsed[funcId] = true;
+ if (funcId in ttContext.functionsStackDeltas) {
+ const newStackLength = stack.length + ttContext.functionsStackDeltas[funcId];
+ if (newStackLength < 0) {
+ warn("TT: CALL invalid functions stack delta.");
+ ttContext.hintsValid = false;
+ return;
+ }
+ stack.length = newStackLength;
+ } else if (funcId in ttContext.functionsDefined && !functionsCalled.includes(funcId)) {
+ callstack.push({
+ data,
+ i,
+ stackTop: stack.length - 1
+ });
+ functionsCalled.push(funcId);
+ pc = ttContext.functionsDefined[funcId];
+ if (!pc) {
+ warn("TT: CALL non-existent function");
+ ttContext.hintsValid = false;
+ return;
+ }
+ data = pc.data;
+ i = pc.i;
+ }
+ }
+ }
+ } else if (op === 0x2c && !tooComplexToFollowFunctions) {
+ if (inFDEF || inELSE) {
+ warn("TT: nested FDEFs not allowed");
+ tooComplexToFollowFunctions = true;
+ }
+ inFDEF = true;
+ lastDeff = i;
+ funcId = stack.pop();
+ ttContext.functionsDefined[funcId] = {
+ data,
+ i
+ };
+ } else if (op === 0x2d) {
+ if (inFDEF) {
+ inFDEF = false;
+ lastEndf = i;
+ } else {
+ pc = callstack.pop();
+ if (!pc) {
+ warn("TT: ENDF bad stack");
+ ttContext.hintsValid = false;
+ return;
+ }
+ funcId = functionsCalled.pop();
+ data = pc.data;
+ i = pc.i;
+ ttContext.functionsStackDeltas[funcId] = stack.length - pc.stackTop;
+ }
+ } else if (op === 0x89) {
+ if (inFDEF || inELSE) {
+ warn("TT: nested IDEFs not allowed");
+ tooComplexToFollowFunctions = true;
+ }
+ inFDEF = true;
+ lastDeff = i;
+ } else if (op === 0x58) {
+ ++ifLevel;
+ } else if (op === 0x1b) {
+ inELSE = ifLevel;
+ } else if (op === 0x59) {
+ if (inELSE === ifLevel) {
+ inELSE = 0;
+ }
+ --ifLevel;
+ } else if (op === 0x1c) {
+ if (!inFDEF && !inELSE) {
+ const offset = stack.at(-1);
+ if (offset > 0) {
+ i += offset - 1;
+ }
+ }
+ }
+ if (!inFDEF && !inELSE) {
+ let stackDelta = 0;
+ if (op <= 0x8e) {
+ stackDelta = TTOpsStackDeltas[op];
+ } else if (op >= 0xc0 && op <= 0xdf) {
+ stackDelta = -1;
+ } else if (op >= 0xe0) {
+ stackDelta = -2;
+ }
+ if (op >= 0x71 && op <= 0x75) {
+ n = stack.pop();
+ if (!isNaN(n)) {
+ stackDelta = -n * 2;
+ }
+ }
+ while (stackDelta < 0 && stack.length > 0) {
+ stack.pop();
+ stackDelta++;
+ }
+ while (stackDelta > 0) {
+ stack.push(NaN);
+ stackDelta--;
+ }
+ }
+ }
+ ttContext.tooComplexToFollowFunctions = tooComplexToFollowFunctions;
+ const content = [data];
+ if (i > data.length) {
+ content.push(new Uint8Array(i - data.length));
+ }
+ if (lastDeff > lastEndf) {
+ warn("TT: complementing a missing function tail");
+ content.push(new Uint8Array([0x22, 0x2d]));
+ }
+ foldTTTable(table, content);
+ }
+ function checkInvalidFunctions(ttContext, maxFunctionDefs) {
+ if (ttContext.tooComplexToFollowFunctions) {
+ return;
+ }
+ if (ttContext.functionsDefined.length > maxFunctionDefs) {
+ warn("TT: more functions defined than expected");
+ ttContext.hintsValid = false;
+ return;
+ }
+ for (let j = 0, jj = ttContext.functionsUsed.length; j < jj; j++) {
+ if (j > maxFunctionDefs) {
+ warn("TT: invalid function id: " + j);
+ ttContext.hintsValid = false;
+ return;
+ }
+ if (ttContext.functionsUsed[j] && !ttContext.functionsDefined[j]) {
+ warn("TT: undefined function: " + j);
+ ttContext.hintsValid = false;
+ return;
+ }
+ }
+ }
+ function foldTTTable(table, content) {
+ if (content.length > 1) {
+ let newLength = 0;
+ let j, jj;
+ for (j = 0, jj = content.length; j < jj; j++) {
+ newLength += content[j].length;
+ }
+ newLength = newLength + 3 & ~3;
+ const result = new Uint8Array(newLength);
+ let pos = 0;
+ for (j = 0, jj = content.length; j < jj; j++) {
+ result.set(content[j], pos);
+ pos += content[j].length;
+ }
+ table.data = result;
+ table.length = newLength;
+ }
+ }
+ function sanitizeTTPrograms(fpgm, prep, cvt, maxFunctionDefs) {
+ const ttContext = {
+ functionsDefined: [],
+ functionsUsed: [],
+ functionsStackDeltas: [],
+ tooComplexToFollowFunctions: false,
+ hintsValid: true
+ };
+ if (fpgm) {
+ sanitizeTTProgram(fpgm, ttContext);
+ }
+ if (prep) {
+ sanitizeTTProgram(prep, ttContext);
+ }
+ if (fpgm) {
+ checkInvalidFunctions(ttContext, maxFunctionDefs);
+ }
+ if (cvt && cvt.length & 1) {
+ const cvtData = new Uint8Array(cvt.length + 1);
+ cvtData.set(cvt.data);
+ cvt.data = cvtData;
+ }
+ return ttContext.hintsValid;
+ }
+ font = new Stream(new Uint8Array(font.getBytes()));
+ let header, tables;
+ if (isTrueTypeCollectionFile(font)) {
+ const ttcData = readTrueTypeCollectionData(font, this.name);
+ header = ttcData.header;
+ tables = ttcData.tables;
+ } else {
+ header = readOpenTypeHeader(font);
+ tables = readTables(font, header.numTables);
+ }
+ let cff, cffFile;
+ const isTrueType = !tables["CFF "];
+ if (!isTrueType) {
+ const isComposite = properties.composite && (properties.cidToGidMap?.length > 0 || !(properties.cMap instanceof IdentityCMap));
+ if (header.version === "OTTO" && !isComposite || !tables.head || !tables.hhea || !tables.maxp || !tables.post) {
+ cffFile = new Stream(tables["CFF "].data);
+ cff = new CFFFont(cffFile, properties);
+ adjustWidths(properties);
+ return this.convert(name, cff, properties);
+ }
+ delete tables.glyf;
+ delete tables.loca;
+ delete tables.fpgm;
+ delete tables.prep;
+ delete tables["cvt "];
+ this.isOpenType = true;
+ } else {
+ if (!tables.loca) {
+ throw new FormatError('Required "loca" table is not found');
+ }
+ if (!tables.glyf) {
+ warn('Required "glyf" table is not found -- trying to recover.');
+ tables.glyf = {
+ tag: "glyf",
+ data: new Uint8Array(0)
+ };
+ }
+ this.isOpenType = false;
+ }
+ if (!tables.maxp) {
+ throw new FormatError('Required "maxp" table is not found');
+ }
+ font.pos = (font.start || 0) + tables.maxp.offset;
+ let version = font.getInt32();
+ const numGlyphs = font.getUint16();
+ if (version !== 0x00010000 && version !== 0x00005000) {
+ if (tables.maxp.length === 6) {
+ version = 0x0005000;
+ } else if (tables.maxp.length >= 32) {
+ version = 0x00010000;
+ } else {
+ throw new FormatError(`"maxp" table has a wrong version number`);
+ }
+ writeUint32(tables.maxp.data, 0, version);
+ }
+ if (properties.scaleFactors?.length === numGlyphs && isTrueType) {
+ const {
+ scaleFactors
+ } = properties;
+ const isGlyphLocationsLong = int16(tables.head.data[50], tables.head.data[51]);
+ const glyphs = new GlyfTable({
+ glyfTable: tables.glyf.data,
+ isGlyphLocationsLong,
+ locaTable: tables.loca.data,
+ numGlyphs
+ });
+ glyphs.scale(scaleFactors);
+ const {
+ glyf,
+ loca,
+ isLocationLong
+ } = glyphs.write();
+ tables.glyf.data = glyf;
+ tables.loca.data = loca;
+ if (isLocationLong !== !!isGlyphLocationsLong) {
+ tables.head.data[50] = 0;
+ tables.head.data[51] = isLocationLong ? 1 : 0;
+ }
+ const metrics = tables.hmtx.data;
+ for (let i = 0; i < numGlyphs; i++) {
+ const j = 4 * i;
+ const advanceWidth = Math.round(scaleFactors[i] * int16(metrics[j], metrics[j + 1]));
+ metrics[j] = advanceWidth >> 8 & 0xff;
+ metrics[j + 1] = advanceWidth & 0xff;
+ const lsb = Math.round(scaleFactors[i] * signedInt16(metrics[j + 2], metrics[j + 3]));
+ writeSignedInt16(metrics, j + 2, lsb);
+ }
+ }
+ let numGlyphsOut = numGlyphs + 1;
+ let dupFirstEntry = true;
+ if (numGlyphsOut > 0xffff) {
+ dupFirstEntry = false;
+ numGlyphsOut = numGlyphs;
+ warn("Not enough space in glyfs to duplicate first glyph.");
+ }
+ let maxFunctionDefs = 0;
+ let maxSizeOfInstructions = 0;
+ if (version >= 0x00010000 && tables.maxp.length >= 32) {
+ font.pos += 8;
+ const maxZones = font.getUint16();
+ if (maxZones > 2) {
+ tables.maxp.data[14] = 0;
+ tables.maxp.data[15] = 2;
+ }
+ font.pos += 4;
+ maxFunctionDefs = font.getUint16();
+ font.pos += 4;
+ maxSizeOfInstructions = font.getUint16();
+ }
+ tables.maxp.data[4] = numGlyphsOut >> 8;
+ tables.maxp.data[5] = numGlyphsOut & 255;
+ const hintsValid = sanitizeTTPrograms(tables.fpgm, tables.prep, tables["cvt "], maxFunctionDefs);
+ if (!hintsValid) {
+ delete tables.fpgm;
+ delete tables.prep;
+ delete tables["cvt "];
+ }
+ sanitizeMetrics(font, tables.hhea, tables.hmtx, tables.head, numGlyphsOut, dupFirstEntry);
+ if (!tables.head) {
+ throw new FormatError('Required "head" table is not found');
+ }
+ sanitizeHead(tables.head, numGlyphs, isTrueType ? tables.loca.length : 0);
+ let missingGlyphs = Object.create(null);
+ if (isTrueType) {
+ const isGlyphLocationsLong = int16(tables.head.data[50], tables.head.data[51]);
+ const glyphsInfo = sanitizeGlyphLocations(tables.loca, tables.glyf, numGlyphs, isGlyphLocationsLong, hintsValid, dupFirstEntry, maxSizeOfInstructions);
+ missingGlyphs = glyphsInfo.missingGlyphs;
+ if (version >= 0x00010000 && tables.maxp.length >= 32) {
+ tables.maxp.data[26] = glyphsInfo.maxSizeOfInstructions >> 8;
+ tables.maxp.data[27] = glyphsInfo.maxSizeOfInstructions & 255;
+ }
+ }
+ if (!tables.hhea) {
+ throw new FormatError('Required "hhea" table is not found');
+ }
+ if (tables.hhea.data[10] === 0 && tables.hhea.data[11] === 0) {
+ tables.hhea.data[10] = 0xff;
+ tables.hhea.data[11] = 0xff;
+ }
+ const metricsOverride = {
+ unitsPerEm: int16(tables.head.data[18], tables.head.data[19]),
+ yMax: signedInt16(tables.head.data[42], tables.head.data[43]),
+ yMin: signedInt16(tables.head.data[38], tables.head.data[39]),
+ ascent: signedInt16(tables.hhea.data[4], tables.hhea.data[5]),
+ descent: signedInt16(tables.hhea.data[6], tables.hhea.data[7]),
+ lineGap: signedInt16(tables.hhea.data[8], tables.hhea.data[9])
+ };
+ this.ascent = metricsOverride.ascent / metricsOverride.unitsPerEm;
+ this.descent = metricsOverride.descent / metricsOverride.unitsPerEm;
+ this.lineGap = metricsOverride.lineGap / metricsOverride.unitsPerEm;
+ if (this.cssFontInfo?.lineHeight) {
+ this.lineHeight = this.cssFontInfo.metrics.lineHeight;
+ this.lineGap = this.cssFontInfo.metrics.lineGap;
+ } else {
+ this.lineHeight = this.ascent - this.descent + this.lineGap;
+ }
+ if (tables.post) {
+ readPostScriptTable(tables.post, properties, numGlyphs);
+ }
+ tables.post = {
+ tag: "post",
+ data: createPostTable(properties)
+ };
+ const charCodeToGlyphId = [];
+ function hasGlyph(glyphId) {
+ return !missingGlyphs[glyphId];
+ }
+ if (properties.composite) {
+ const cidToGidMap = properties.cidToGidMap || [];
+ const isCidToGidMapEmpty = cidToGidMap.length === 0;
+ properties.cMap.forEach(function (charCode, cid) {
+ if (typeof cid === "string") {
+ cid = convertCidString(charCode, cid, true);
+ }
+ if (cid > 0xffff) {
+ throw new FormatError("Max size of CID is 65,535");
+ }
+ let glyphId = -1;
+ if (isCidToGidMapEmpty) {
+ glyphId = cid;
+ } else if (cidToGidMap[cid] !== undefined) {
+ glyphId = cidToGidMap[cid];
+ }
+ if (glyphId >= 0 && glyphId < numGlyphs && hasGlyph(glyphId)) {
+ charCodeToGlyphId[charCode] = glyphId;
+ }
+ });
+ } else {
+ const cmapTable = readCmapTable(tables.cmap, font, this.isSymbolicFont, properties.hasEncoding);
+ const cmapPlatformId = cmapTable.platformId;
+ const cmapEncodingId = cmapTable.encodingId;
+ const cmapMappings = cmapTable.mappings;
+ let baseEncoding = [],
+ forcePostTable = false;
+ if (properties.hasEncoding && (properties.baseEncodingName === "MacRomanEncoding" || properties.baseEncodingName === "WinAnsiEncoding")) {
+ baseEncoding = getEncoding(properties.baseEncodingName);
+ }
+ if (properties.hasEncoding && !this.isSymbolicFont && (cmapPlatformId === 3 && cmapEncodingId === 1 || cmapPlatformId === 1 && cmapEncodingId === 0)) {
+ const glyphsUnicodeMap = getGlyphsUnicode();
+ for (let charCode = 0; charCode < 256; charCode++) {
+ let glyphName;
+ if (this.differences[charCode] !== undefined) {
+ glyphName = this.differences[charCode];
+ } else if (baseEncoding.length && baseEncoding[charCode] !== "") {
+ glyphName = baseEncoding[charCode];
+ } else {
+ glyphName = StandardEncoding[charCode];
+ }
+ if (!glyphName) {
+ continue;
+ }
+ const standardGlyphName = recoverGlyphName(glyphName, glyphsUnicodeMap);
+ let unicodeOrCharCode;
+ if (cmapPlatformId === 3 && cmapEncodingId === 1) {
+ unicodeOrCharCode = glyphsUnicodeMap[standardGlyphName];
+ } else if (cmapPlatformId === 1 && cmapEncodingId === 0) {
+ unicodeOrCharCode = MacRomanEncoding.indexOf(standardGlyphName);
+ }
+ if (unicodeOrCharCode === undefined) {
+ if (!properties.glyphNames && properties.hasIncludedToUnicodeMap && !(this.toUnicode instanceof IdentityToUnicodeMap)) {
+ const unicode = this.toUnicode.get(charCode);
+ if (unicode) {
+ unicodeOrCharCode = unicode.codePointAt(0);
+ }
+ }
+ if (unicodeOrCharCode === undefined) {
+ continue;
+ }
+ }
+ for (const mapping of cmapMappings) {
+ if (mapping.charCode !== unicodeOrCharCode) {
+ continue;
+ }
+ charCodeToGlyphId[charCode] = mapping.glyphId;
+ break;
+ }
+ }
+ } else if (cmapPlatformId === 0) {
+ for (const mapping of cmapMappings) {
+ charCodeToGlyphId[mapping.charCode] = mapping.glyphId;
+ }
+ forcePostTable = true;
+ } else {
+ for (const mapping of cmapMappings) {
+ let charCode = mapping.charCode;
+ if (cmapPlatformId === 3 && charCode >= 0xf000 && charCode <= 0xf0ff) {
+ charCode &= 0xff;
+ }
+ charCodeToGlyphId[charCode] = mapping.glyphId;
+ }
+ }
+ if (properties.glyphNames && (baseEncoding.length || this.differences.length)) {
+ for (let i = 0; i < 256; ++i) {
+ if (!forcePostTable && charCodeToGlyphId[i] !== undefined) {
+ continue;
+ }
+ const glyphName = this.differences[i] || baseEncoding[i];
+ if (!glyphName) {
+ continue;
+ }
+ const glyphId = properties.glyphNames.indexOf(glyphName);
+ if (glyphId > 0 && hasGlyph(glyphId)) {
+ charCodeToGlyphId[i] = glyphId;
+ }
+ }
+ }
+ }
+ if (charCodeToGlyphId.length === 0) {
+ charCodeToGlyphId[0] = 0;
+ }
+ let glyphZeroId = numGlyphsOut - 1;
+ if (!dupFirstEntry) {
+ glyphZeroId = 0;
+ }
+ if (!properties.cssFontInfo) {
+ const newMapping = adjustMapping(charCodeToGlyphId, hasGlyph, glyphZeroId, this.toUnicode);
+ this.toFontChar = newMapping.toFontChar;
+ tables.cmap = {
+ tag: "cmap",
+ data: createCmapTable(newMapping.charCodeToGlyphId, newMapping.toUnicodeExtraMap, numGlyphsOut)
+ };
+ if (!tables["OS/2"] || !validateOS2Table(tables["OS/2"], font)) {
+ tables["OS/2"] = {
+ tag: "OS/2",
+ data: createOS2Table(properties, newMapping.charCodeToGlyphId, metricsOverride)
+ };
+ }
+ }
+ if (!isTrueType) {
+ try {
+ cffFile = new Stream(tables["CFF "].data);
+ const parser = new CFFParser(cffFile, properties, SEAC_ANALYSIS_ENABLED);
+ cff = parser.parse();
+ cff.duplicateFirstGlyph();
+ const compiler = new CFFCompiler(cff);
+ tables["CFF "].data = compiler.compile();
+ } catch {
+ warn("Failed to compile font " + properties.loadedName);
+ }
+ }
+ if (!tables.name) {
+ tables.name = {
+ tag: "name",
+ data: createNameTable(this.name)
+ };
+ } else {
+ const [namePrototype, nameRecords] = readNameTable(tables.name);
+ tables.name.data = createNameTable(name, namePrototype);
+ this.psName = namePrototype[0][6] || null;
+ if (!properties.composite) {
+ adjustTrueTypeToUnicode(properties, this.isSymbolicFont, nameRecords);
+ }
+ }
+ const builder = new OpenTypeFileBuilder(header.version);
+ for (const tableTag in tables) {
+ builder.addTable(tableTag, tables[tableTag].data);
+ }
+ return builder.toArray();
+ }
+ convert(fontName, font, properties) {
+ properties.fixedPitch = false;
+ if (properties.builtInEncoding) {
+ adjustType1ToUnicode(properties, properties.builtInEncoding);
+ }
+ let glyphZeroId = 1;
+ if (font instanceof CFFFont) {
+ glyphZeroId = font.numGlyphs - 1;
+ }
+ const mapping = font.getGlyphMapping(properties);
+ let newMapping = null;
+ let newCharCodeToGlyphId = mapping;
+ let toUnicodeExtraMap = null;
+ if (!properties.cssFontInfo) {
+ newMapping = adjustMapping(mapping, font.hasGlyphId.bind(font), glyphZeroId, this.toUnicode);
+ this.toFontChar = newMapping.toFontChar;
+ newCharCodeToGlyphId = newMapping.charCodeToGlyphId;
+ toUnicodeExtraMap = newMapping.toUnicodeExtraMap;
+ }
+ const numGlyphs = font.numGlyphs;
+ function getCharCodes(charCodeToGlyphId, glyphId) {
+ let charCodes = null;
+ for (const charCode in charCodeToGlyphId) {
+ if (glyphId === charCodeToGlyphId[charCode]) {
+ (charCodes ||= []).push(charCode | 0);
+ }
+ }
+ return charCodes;
+ }
+ function createCharCode(charCodeToGlyphId, glyphId) {
+ for (const charCode in charCodeToGlyphId) {
+ if (glyphId === charCodeToGlyphId[charCode]) {
+ return charCode | 0;
+ }
+ }
+ newMapping.charCodeToGlyphId[newMapping.nextAvailableFontCharCode] = glyphId;
+ return newMapping.nextAvailableFontCharCode++;
+ }
+ const seacs = font.seacs;
+ if (newMapping && SEAC_ANALYSIS_ENABLED && seacs?.length) {
+ const matrix = properties.fontMatrix || FONT_IDENTITY_MATRIX;
+ const charset = font.getCharset();
+ const seacMap = Object.create(null);
+ for (let glyphId in seacs) {
+ glyphId |= 0;
+ const seac = seacs[glyphId];
+ const baseGlyphName = StandardEncoding[seac[2]];
+ const accentGlyphName = StandardEncoding[seac[3]];
+ const baseGlyphId = charset.indexOf(baseGlyphName);
+ const accentGlyphId = charset.indexOf(accentGlyphName);
+ if (baseGlyphId < 0 || accentGlyphId < 0) {
+ continue;
+ }
+ const accentOffset = {
+ x: seac[0] * matrix[0] + seac[1] * matrix[2] + matrix[4],
+ y: seac[0] * matrix[1] + seac[1] * matrix[3] + matrix[5]
+ };
+ const charCodes = getCharCodes(mapping, glyphId);
+ if (!charCodes) {
+ continue;
+ }
+ for (const charCode of charCodes) {
+ const charCodeToGlyphId = newMapping.charCodeToGlyphId;
+ const baseFontCharCode = createCharCode(charCodeToGlyphId, baseGlyphId);
+ const accentFontCharCode = createCharCode(charCodeToGlyphId, accentGlyphId);
+ seacMap[charCode] = {
+ baseFontCharCode,
+ accentFontCharCode,
+ accentOffset
+ };
+ }
+ }
+ properties.seacMap = seacMap;
+ }
+ const unitsPerEm = 1 / (properties.fontMatrix || FONT_IDENTITY_MATRIX)[0];
+ const builder = new OpenTypeFileBuilder("\x4F\x54\x54\x4F");
+ builder.addTable("CFF ", font.data);
+ builder.addTable("OS/2", createOS2Table(properties, newCharCodeToGlyphId));
+ builder.addTable("cmap", createCmapTable(newCharCodeToGlyphId, toUnicodeExtraMap, numGlyphs));
+ builder.addTable("head", "\x00\x01\x00\x00" + "\x00\x00\x10\x00" + "\x00\x00\x00\x00" + "\x5F\x0F\x3C\xF5" + "\x00\x00" + safeString16(unitsPerEm) + "\x00\x00\x00\x00\x9e\x0b\x7e\x27" + "\x00\x00\x00\x00\x9e\x0b\x7e\x27" + "\x00\x00" + safeString16(properties.descent) + "\x0F\xFF" + safeString16(properties.ascent) + string16(properties.italicAngle ? 2 : 0) + "\x00\x11" + "\x00\x00" + "\x00\x00" + "\x00\x00");
+ builder.addTable("hhea", "\x00\x01\x00\x00" + safeString16(properties.ascent) + safeString16(properties.descent) + "\x00\x00" + "\xFF\xFF" + "\x00\x00" + "\x00\x00" + "\x00\x00" + safeString16(properties.capHeight) + safeString16(Math.tan(properties.italicAngle) * properties.xHeight) + "\x00\x00" + "\x00\x00" + "\x00\x00" + "\x00\x00" + "\x00\x00" + "\x00\x00" + string16(numGlyphs));
+ builder.addTable("hmtx", function fontFieldsHmtx() {
+ const charstrings = font.charstrings;
+ const cffWidths = font.cff ? font.cff.widths : null;
+ let hmtx = "\x00\x00\x00\x00";
+ for (let i = 1, ii = numGlyphs; i < ii; i++) {
+ let width = 0;
+ if (charstrings) {
+ const charstring = charstrings[i - 1];
+ width = "width" in charstring ? charstring.width : 0;
+ } else if (cffWidths) {
+ width = Math.ceil(cffWidths[i] || 0);
+ }
+ hmtx += string16(width) + string16(0);
+ }
+ return hmtx;
+ }());
+ builder.addTable("maxp", "\x00\x00\x50\x00" + string16(numGlyphs));
+ builder.addTable("name", createNameTable(fontName));
+ builder.addTable("post", createPostTable(properties));
+ return builder.toArray();
+ }
+ get spaceWidth() {
+ const possibleSpaceReplacements = ["space", "minus", "one", "i", "I"];
+ let width;
+ for (const glyphName of possibleSpaceReplacements) {
+ if (glyphName in this.widths) {
+ width = this.widths[glyphName];
+ break;
+ }
+ const glyphsUnicodeMap = getGlyphsUnicode();
+ const glyphUnicode = glyphsUnicodeMap[glyphName];
+ let charcode = 0;
+ if (this.composite && this.cMap.contains(glyphUnicode)) {
+ charcode = this.cMap.lookup(glyphUnicode);
+ if (typeof charcode === "string") {
+ charcode = convertCidString(glyphUnicode, charcode);
+ }
+ }
+ if (!charcode && this.toUnicode) {
+ charcode = this.toUnicode.charCodeOf(glyphUnicode);
+ }
+ if (charcode <= 0) {
+ charcode = glyphUnicode;
+ }
+ width = this.widths[charcode];
+ if (width) {
+ break;
+ }
+ }
+ return shadow(this, "spaceWidth", width || this.defaultWidth);
+ }
+ _charToGlyph(charcode, isSpace = false) {
+ let glyph = this._glyphCache[charcode];
+ if (glyph?.isSpace === isSpace) {
+ return glyph;
+ }
+ let fontCharCode, width, operatorListId;
+ let widthCode = charcode;
+ if (this.cMap?.contains(charcode)) {
+ widthCode = this.cMap.lookup(charcode);
+ if (typeof widthCode === "string") {
+ widthCode = convertCidString(charcode, widthCode);
+ }
+ }
+ width = this.widths[widthCode];
+ if (typeof width !== "number") {
+ width = this.defaultWidth;
+ }
+ const vmetric = this.vmetrics?.[widthCode];
+ let unicode = this.toUnicode.get(charcode) || charcode;
+ if (typeof unicode === "number") {
+ unicode = String.fromCharCode(unicode);
+ }
+ let isInFont = this.toFontChar[charcode] !== undefined;
+ fontCharCode = this.toFontChar[charcode] || charcode;
+ if (this.missingFile) {
+ const glyphName = this.differences[charcode] || this.defaultEncoding[charcode];
+ if ((glyphName === ".notdef" || glyphName === "") && this.type === "Type1") {
+ fontCharCode = 0x20;
+ }
+ fontCharCode = mapSpecialUnicodeValues(fontCharCode);
+ }
+ if (this.isType3Font) {
+ operatorListId = fontCharCode;
+ }
+ let accent = null;
+ if (this.seacMap?.[charcode]) {
+ isInFont = true;
+ const seac = this.seacMap[charcode];
+ fontCharCode = seac.baseFontCharCode;
+ accent = {
+ fontChar: String.fromCodePoint(seac.accentFontCharCode),
+ offset: seac.accentOffset
+ };
+ }
+ let fontChar = "";
+ if (typeof fontCharCode === "number") {
+ if (fontCharCode <= 0x10ffff) {
+ fontChar = String.fromCodePoint(fontCharCode);
+ } else {
+ warn(`charToGlyph - invalid fontCharCode: ${fontCharCode}`);
+ }
+ }
+ glyph = new fonts_Glyph(charcode, fontChar, unicode, accent, width, vmetric, operatorListId, isSpace, isInFont);
+ return this._glyphCache[charcode] = glyph;
+ }
+ charsToGlyphs(chars) {
+ let glyphs = this._charsCache[chars];
+ if (glyphs) {
+ return glyphs;
+ }
+ glyphs = [];
+ if (this.cMap) {
+ const c = Object.create(null),
+ ii = chars.length;
+ let i = 0;
+ while (i < ii) {
+ this.cMap.readCharCode(chars, i, c);
+ const {
+ charcode,
+ length
+ } = c;
+ i += length;
+ const glyph = this._charToGlyph(charcode, length === 1 && chars.charCodeAt(i - 1) === 0x20);
+ glyphs.push(glyph);
+ }
+ } else {
+ for (let i = 0, ii = chars.length; i < ii; ++i) {
+ const charcode = chars.charCodeAt(i);
+ const glyph = this._charToGlyph(charcode, charcode === 0x20);
+ glyphs.push(glyph);
+ }
+ }
+ return this._charsCache[chars] = glyphs;
+ }
+ getCharPositions(chars) {
+ const positions = [];
+ if (this.cMap) {
+ const c = Object.create(null);
+ let i = 0;
+ while (i < chars.length) {
+ this.cMap.readCharCode(chars, i, c);
+ const length = c.length;
+ positions.push([i, i + length]);
+ i += length;
+ }
+ } else {
+ for (let i = 0, ii = chars.length; i < ii; ++i) {
+ positions.push([i, i + 1]);
+ }
+ }
+ return positions;
+ }
+ get glyphCacheValues() {
+ return Object.values(this._glyphCache);
+ }
+ encodeString(str) {
+ const buffers = [];
+ const currentBuf = [];
+ const hasCurrentBufErrors = () => buffers.length % 2 === 1;
+ const getCharCode = this.toUnicode instanceof IdentityToUnicodeMap ? unicode => this.toUnicode.charCodeOf(unicode) : unicode => this.toUnicode.charCodeOf(String.fromCodePoint(unicode));
+ for (let i = 0, ii = str.length; i < ii; i++) {
+ const unicode = str.codePointAt(i);
+ if (unicode > 0xd7ff && (unicode < 0xe000 || unicode > 0xfffd)) {
+ i++;
+ }
+ if (this.toUnicode) {
+ const charCode = getCharCode(unicode);
+ if (charCode !== -1) {
+ if (hasCurrentBufErrors()) {
+ buffers.push(currentBuf.join(""));
+ currentBuf.length = 0;
+ }
+ const charCodeLength = this.cMap ? this.cMap.getCharCodeLength(charCode) : 1;
+ for (let j = charCodeLength - 1; j >= 0; j--) {
+ currentBuf.push(String.fromCharCode(charCode >> 8 * j & 0xff));
+ }
+ continue;
+ }
+ }
+ if (!hasCurrentBufErrors()) {
+ buffers.push(currentBuf.join(""));
+ currentBuf.length = 0;
+ }
+ currentBuf.push(String.fromCodePoint(unicode));
+ }
+ buffers.push(currentBuf.join(""));
+ return buffers;
+ }
+}
+class ErrorFont {
+ constructor(error) {
+ this.error = error;
+ this.loadedName = "g_font_error";
+ this.missingFile = true;
+ }
+ charsToGlyphs() {
+ return [];
+ }
+ encodeString(chars) {
+ return [chars];
+ }
+ exportData(extraProperties = false) {
+ return {
+ error: this.error
+ };
+ }
+}
+
+;// CONCATENATED MODULE: ./src/core/pattern.js
+
+
+
+
+const ShadingType = {
+ FUNCTION_BASED: 1,
+ AXIAL: 2,
+ RADIAL: 3,
+ FREE_FORM_MESH: 4,
+ LATTICE_FORM_MESH: 5,
+ COONS_PATCH_MESH: 6,
+ TENSOR_PATCH_MESH: 7
+};
+class Pattern {
+ constructor() {
+ unreachable("Cannot initialize Pattern.");
+ }
+ static parseShading(shading, xref, res, pdfFunctionFactory, localColorSpaceCache) {
+ const dict = shading instanceof BaseStream ? shading.dict : shading;
+ const type = dict.get("ShadingType");
+ try {
+ switch (type) {
+ case ShadingType.AXIAL:
+ case ShadingType.RADIAL:
+ return new RadialAxialShading(dict, xref, res, pdfFunctionFactory, localColorSpaceCache);
+ case ShadingType.FREE_FORM_MESH:
+ case ShadingType.LATTICE_FORM_MESH:
+ case ShadingType.COONS_PATCH_MESH:
+ case ShadingType.TENSOR_PATCH_MESH:
+ return new MeshShading(shading, xref, res, pdfFunctionFactory, localColorSpaceCache);
+ default:
+ throw new FormatError("Unsupported ShadingType: " + type);
+ }
+ } catch (ex) {
+ if (ex instanceof MissingDataException) {
+ throw ex;
+ }
+ warn(ex);
+ return new DummyShading();
+ }
+ }
+}
+class BaseShading {
+ static SMALL_NUMBER = 1e-6;
+ constructor() {
+ if (this.constructor === BaseShading) {
+ unreachable("Cannot initialize BaseShading.");
+ }
+ }
+ getIR() {
+ unreachable("Abstract method `getIR` called.");
+ }
+}
+class RadialAxialShading extends BaseShading {
+ constructor(dict, xref, resources, pdfFunctionFactory, localColorSpaceCache) {
+ super();
+ this.coordsArr = dict.getArray("Coords");
+ this.shadingType = dict.get("ShadingType");
+ const cs = ColorSpace.parse({
+ cs: dict.getRaw("CS") || dict.getRaw("ColorSpace"),
+ xref,
+ resources,
+ pdfFunctionFactory,
+ localColorSpaceCache
+ });
+ const bbox = dict.getArray("BBox");
+ this.bbox = Array.isArray(bbox) && bbox.length === 4 ? Util.normalizeRect(bbox) : null;
+ let t0 = 0.0,
+ t1 = 1.0;
+ if (dict.has("Domain")) {
+ const domainArr = dict.getArray("Domain");
+ t0 = domainArr[0];
+ t1 = domainArr[1];
+ }
+ let extendStart = false,
+ extendEnd = false;
+ if (dict.has("Extend")) {
+ const extendArr = dict.getArray("Extend");
+ extendStart = extendArr[0];
+ extendEnd = extendArr[1];
+ }
+ if (this.shadingType === ShadingType.RADIAL && (!extendStart || !extendEnd)) {
+ const [x1, y1, r1, x2, y2, r2] = this.coordsArr;
+ const distance = Math.hypot(x1 - x2, y1 - y2);
+ if (r1 <= r2 + distance && r2 <= r1 + distance) {
+ warn("Unsupported radial gradient.");
+ }
+ }
+ this.extendStart = extendStart;
+ this.extendEnd = extendEnd;
+ const fnObj = dict.getRaw("Function");
+ const fn = pdfFunctionFactory.createFromArray(fnObj);
+ const NUMBER_OF_SAMPLES = 840;
+ const step = (t1 - t0) / NUMBER_OF_SAMPLES;
+ const colorStops = this.colorStops = [];
+ if (t0 >= t1 || step <= 0) {
+ info("Bad shading domain.");
+ return;
+ }
+ const color = new Float32Array(cs.numComps),
+ ratio = new Float32Array(1);
+ let rgbColor;
+ let iBase = 0;
+ ratio[0] = t0;
+ fn(ratio, 0, color, 0);
+ let rgbBase = cs.getRgb(color, 0);
+ const cssColorBase = Util.makeHexColor(rgbBase[0], rgbBase[1], rgbBase[2]);
+ colorStops.push([0, cssColorBase]);
+ let iPrev = 1;
+ ratio[0] = t0 + step;
+ fn(ratio, 0, color, 0);
+ let rgbPrev = cs.getRgb(color, 0);
+ let maxSlopeR = rgbPrev[0] - rgbBase[0] + 1;
+ let maxSlopeG = rgbPrev[1] - rgbBase[1] + 1;
+ let maxSlopeB = rgbPrev[2] - rgbBase[2] + 1;
+ let minSlopeR = rgbPrev[0] - rgbBase[0] - 1;
+ let minSlopeG = rgbPrev[1] - rgbBase[1] - 1;
+ let minSlopeB = rgbPrev[2] - rgbBase[2] - 1;
+ for (let i = 2; i < NUMBER_OF_SAMPLES; i++) {
+ ratio[0] = t0 + i * step;
+ fn(ratio, 0, color, 0);
+ rgbColor = cs.getRgb(color, 0);
+ const run = i - iBase;
+ maxSlopeR = Math.min(maxSlopeR, (rgbColor[0] - rgbBase[0] + 1) / run);
+ maxSlopeG = Math.min(maxSlopeG, (rgbColor[1] - rgbBase[1] + 1) / run);
+ maxSlopeB = Math.min(maxSlopeB, (rgbColor[2] - rgbBase[2] + 1) / run);
+ minSlopeR = Math.max(minSlopeR, (rgbColor[0] - rgbBase[0] - 1) / run);
+ minSlopeG = Math.max(minSlopeG, (rgbColor[1] - rgbBase[1] - 1) / run);
+ minSlopeB = Math.max(minSlopeB, (rgbColor[2] - rgbBase[2] - 1) / run);
+ const slopesExist = minSlopeR <= maxSlopeR && minSlopeG <= maxSlopeG && minSlopeB <= maxSlopeB;
+ if (!slopesExist) {
+ const cssColor = Util.makeHexColor(rgbPrev[0], rgbPrev[1], rgbPrev[2]);
+ colorStops.push([iPrev / NUMBER_OF_SAMPLES, cssColor]);
+ maxSlopeR = rgbColor[0] - rgbPrev[0] + 1;
+ maxSlopeG = rgbColor[1] - rgbPrev[1] + 1;
+ maxSlopeB = rgbColor[2] - rgbPrev[2] + 1;
+ minSlopeR = rgbColor[0] - rgbPrev[0] - 1;
+ minSlopeG = rgbColor[1] - rgbPrev[1] - 1;
+ minSlopeB = rgbColor[2] - rgbPrev[2] - 1;
+ iBase = iPrev;
+ rgbBase = rgbPrev;
+ }
+ iPrev = i;
+ rgbPrev = rgbColor;
+ }
+ const cssColor = Util.makeHexColor(rgbPrev[0], rgbPrev[1], rgbPrev[2]);
+ colorStops.push([1, cssColor]);
+ let background = "transparent";
+ if (dict.has("Background")) {
+ rgbColor = cs.getRgb(dict.get("Background"), 0);
+ background = Util.makeHexColor(rgbColor[0], rgbColor[1], rgbColor[2]);
+ }
+ if (!extendStart) {
+ colorStops.unshift([0, background]);
+ colorStops[1][0] += BaseShading.SMALL_NUMBER;
+ }
+ if (!extendEnd) {
+ colorStops.at(-1)[0] -= BaseShading.SMALL_NUMBER;
+ colorStops.push([1, background]);
+ }
+ this.colorStops = colorStops;
+ }
+ getIR() {
+ const coordsArr = this.coordsArr;
+ const shadingType = this.shadingType;
+ let type, p0, p1, r0, r1;
+ if (shadingType === ShadingType.AXIAL) {
+ p0 = [coordsArr[0], coordsArr[1]];
+ p1 = [coordsArr[2], coordsArr[3]];
+ r0 = null;
+ r1 = null;
+ type = "axial";
+ } else if (shadingType === ShadingType.RADIAL) {
+ p0 = [coordsArr[0], coordsArr[1]];
+ p1 = [coordsArr[3], coordsArr[4]];
+ r0 = coordsArr[2];
+ r1 = coordsArr[5];
+ type = "radial";
+ } else {
+ unreachable(`getPattern type unknown: ${shadingType}`);
+ }
+ return ["RadialAxial", type, this.bbox, this.colorStops, p0, p1, r0, r1];
+ }
+}
+class MeshStreamReader {
+ constructor(stream, context) {
+ this.stream = stream;
+ this.context = context;
+ this.buffer = 0;
+ this.bufferLength = 0;
+ const numComps = context.numComps;
+ this.tmpCompsBuf = new Float32Array(numComps);
+ const csNumComps = context.colorSpace.numComps;
+ this.tmpCsCompsBuf = context.colorFn ? new Float32Array(csNumComps) : this.tmpCompsBuf;
+ }
+ get hasData() {
+ if (this.stream.end) {
+ return this.stream.pos < this.stream.end;
+ }
+ if (this.bufferLength > 0) {
+ return true;
+ }
+ const nextByte = this.stream.getByte();
+ if (nextByte < 0) {
+ return false;
+ }
+ this.buffer = nextByte;
+ this.bufferLength = 8;
+ return true;
+ }
+ readBits(n) {
+ let buffer = this.buffer;
+ let bufferLength = this.bufferLength;
+ if (n === 32) {
+ if (bufferLength === 0) {
+ return (this.stream.getByte() << 24 | this.stream.getByte() << 16 | this.stream.getByte() << 8 | this.stream.getByte()) >>> 0;
+ }
+ buffer = buffer << 24 | this.stream.getByte() << 16 | this.stream.getByte() << 8 | this.stream.getByte();
+ const nextByte = this.stream.getByte();
+ this.buffer = nextByte & (1 << bufferLength) - 1;
+ return (buffer << 8 - bufferLength | (nextByte & 0xff) >> bufferLength) >>> 0;
+ }
+ if (n === 8 && bufferLength === 0) {
+ return this.stream.getByte();
+ }
+ while (bufferLength < n) {
+ buffer = buffer << 8 | this.stream.getByte();
+ bufferLength += 8;
+ }
+ bufferLength -= n;
+ this.bufferLength = bufferLength;
+ this.buffer = buffer & (1 << bufferLength) - 1;
+ return buffer >> bufferLength;
+ }
+ align() {
+ this.buffer = 0;
+ this.bufferLength = 0;
+ }
+ readFlag() {
+ return this.readBits(this.context.bitsPerFlag);
+ }
+ readCoordinate() {
+ const bitsPerCoordinate = this.context.bitsPerCoordinate;
+ const xi = this.readBits(bitsPerCoordinate);
+ const yi = this.readBits(bitsPerCoordinate);
+ const decode = this.context.decode;
+ const scale = bitsPerCoordinate < 32 ? 1 / ((1 << bitsPerCoordinate) - 1) : 2.3283064365386963e-10;
+ return [xi * scale * (decode[1] - decode[0]) + decode[0], yi * scale * (decode[3] - decode[2]) + decode[2]];
+ }
+ readComponents() {
+ const numComps = this.context.numComps;
+ const bitsPerComponent = this.context.bitsPerComponent;
+ const scale = bitsPerComponent < 32 ? 1 / ((1 << bitsPerComponent) - 1) : 2.3283064365386963e-10;
+ const decode = this.context.decode;
+ const components = this.tmpCompsBuf;
+ for (let i = 0, j = 4; i < numComps; i++, j += 2) {
+ const ci = this.readBits(bitsPerComponent);
+ components[i] = ci * scale * (decode[j + 1] - decode[j]) + decode[j];
+ }
+ const color = this.tmpCsCompsBuf;
+ if (this.context.colorFn) {
+ this.context.colorFn(components, 0, color, 0);
+ }
+ return this.context.colorSpace.getRgb(color, 0);
+ }
+}
+let bCache = Object.create(null);
+function buildB(count) {
+ const lut = [];
+ for (let i = 0; i <= count; i++) {
+ const t = i / count,
+ t_ = 1 - t;
+ lut.push(new Float32Array([t_ ** 3, 3 * t * t_ ** 2, 3 * t ** 2 * t_, t ** 3]));
+ }
+ return lut;
+}
+function getB(count) {
+ return bCache[count] ||= buildB(count);
+}
+function clearPatternCaches() {
+ bCache = Object.create(null);
+}
+class MeshShading extends BaseShading {
+ static MIN_SPLIT_PATCH_CHUNKS_AMOUNT = 3;
+ static MAX_SPLIT_PATCH_CHUNKS_AMOUNT = 20;
+ static TRIANGLE_DENSITY = 20;
+ constructor(stream, xref, resources, pdfFunctionFactory, localColorSpaceCache) {
+ super();
+ if (!(stream instanceof BaseStream)) {
+ throw new FormatError("Mesh data is not a stream");
+ }
+ const dict = stream.dict;
+ this.shadingType = dict.get("ShadingType");
+ const bbox = dict.getArray("BBox");
+ this.bbox = Array.isArray(bbox) && bbox.length === 4 ? Util.normalizeRect(bbox) : null;
+ const cs = ColorSpace.parse({
+ cs: dict.getRaw("CS") || dict.getRaw("ColorSpace"),
+ xref,
+ resources,
+ pdfFunctionFactory,
+ localColorSpaceCache
+ });
+ this.background = dict.has("Background") ? cs.getRgb(dict.get("Background"), 0) : null;
+ const fnObj = dict.getRaw("Function");
+ const fn = fnObj ? pdfFunctionFactory.createFromArray(fnObj) : null;
+ this.coords = [];
+ this.colors = [];
+ this.figures = [];
+ const decodeContext = {
+ bitsPerCoordinate: dict.get("BitsPerCoordinate"),
+ bitsPerComponent: dict.get("BitsPerComponent"),
+ bitsPerFlag: dict.get("BitsPerFlag"),
+ decode: dict.getArray("Decode"),
+ colorFn: fn,
+ colorSpace: cs,
+ numComps: fn ? 1 : cs.numComps
+ };
+ const reader = new MeshStreamReader(stream, decodeContext);
+ let patchMesh = false;
+ switch (this.shadingType) {
+ case ShadingType.FREE_FORM_MESH:
+ this._decodeType4Shading(reader);
+ break;
+ case ShadingType.LATTICE_FORM_MESH:
+ const verticesPerRow = dict.get("VerticesPerRow") | 0;
+ if (verticesPerRow < 2) {
+ throw new FormatError("Invalid VerticesPerRow");
+ }
+ this._decodeType5Shading(reader, verticesPerRow);
+ break;
+ case ShadingType.COONS_PATCH_MESH:
+ this._decodeType6Shading(reader);
+ patchMesh = true;
+ break;
+ case ShadingType.TENSOR_PATCH_MESH:
+ this._decodeType7Shading(reader);
+ patchMesh = true;
+ break;
+ default:
+ unreachable("Unsupported mesh type.");
+ break;
+ }
+ if (patchMesh) {
+ this._updateBounds();
+ for (let i = 0, ii = this.figures.length; i < ii; i++) {
+ this._buildFigureFromPatch(i);
+ }
+ }
+ this._updateBounds();
+ this._packData();
+ }
+ _decodeType4Shading(reader) {
+ const coords = this.coords;
+ const colors = this.colors;
+ const operators = [];
+ const ps = [];
+ let verticesLeft = 0;
+ while (reader.hasData) {
+ const f = reader.readFlag();
+ const coord = reader.readCoordinate();
+ const color = reader.readComponents();
+ if (verticesLeft === 0) {
+ if (!(0 <= f && f <= 2)) {
+ throw new FormatError("Unknown type4 flag");
+ }
+ switch (f) {
+ case 0:
+ verticesLeft = 3;
+ break;
+ case 1:
+ ps.push(ps.at(-2), ps.at(-1));
+ verticesLeft = 1;
+ break;
+ case 2:
+ ps.push(ps.at(-3), ps.at(-1));
+ verticesLeft = 1;
+ break;
+ }
+ operators.push(f);
+ }
+ ps.push(coords.length);
+ coords.push(coord);
+ colors.push(color);
+ verticesLeft--;
+ reader.align();
+ }
+ this.figures.push({
+ type: "triangles",
+ coords: new Int32Array(ps),
+ colors: new Int32Array(ps)
+ });
+ }
+ _decodeType5Shading(reader, verticesPerRow) {
+ const coords = this.coords;
+ const colors = this.colors;
+ const ps = [];
+ while (reader.hasData) {
+ const coord = reader.readCoordinate();
+ const color = reader.readComponents();
+ ps.push(coords.length);
+ coords.push(coord);
+ colors.push(color);
+ }
+ this.figures.push({
+ type: "lattice",
+ coords: new Int32Array(ps),
+ colors: new Int32Array(ps),
+ verticesPerRow
+ });
+ }
+ _decodeType6Shading(reader) {
+ const coords = this.coords;
+ const colors = this.colors;
+ const ps = new Int32Array(16);
+ const cs = new Int32Array(4);
+ while (reader.hasData) {
+ const f = reader.readFlag();
+ if (!(0 <= f && f <= 3)) {
+ throw new FormatError("Unknown type6 flag");
+ }
+ const pi = coords.length;
+ for (let i = 0, ii = f !== 0 ? 8 : 12; i < ii; i++) {
+ coords.push(reader.readCoordinate());
+ }
+ const ci = colors.length;
+ for (let i = 0, ii = f !== 0 ? 2 : 4; i < ii; i++) {
+ colors.push(reader.readComponents());
+ }
+ let tmp1, tmp2, tmp3, tmp4;
+ switch (f) {
+ case 0:
+ ps[12] = pi + 3;
+ ps[13] = pi + 4;
+ ps[14] = pi + 5;
+ ps[15] = pi + 6;
+ ps[8] = pi + 2;
+ ps[11] = pi + 7;
+ ps[4] = pi + 1;
+ ps[7] = pi + 8;
+ ps[0] = pi;
+ ps[1] = pi + 11;
+ ps[2] = pi + 10;
+ ps[3] = pi + 9;
+ cs[2] = ci + 1;
+ cs[3] = ci + 2;
+ cs[0] = ci;
+ cs[1] = ci + 3;
+ break;
+ case 1:
+ tmp1 = ps[12];
+ tmp2 = ps[13];
+ tmp3 = ps[14];
+ tmp4 = ps[15];
+ ps[12] = tmp4;
+ ps[13] = pi + 0;
+ ps[14] = pi + 1;
+ ps[15] = pi + 2;
+ ps[8] = tmp3;
+ ps[11] = pi + 3;
+ ps[4] = tmp2;
+ ps[7] = pi + 4;
+ ps[0] = tmp1;
+ ps[1] = pi + 7;
+ ps[2] = pi + 6;
+ ps[3] = pi + 5;
+ tmp1 = cs[2];
+ tmp2 = cs[3];
+ cs[2] = tmp2;
+ cs[3] = ci;
+ cs[0] = tmp1;
+ cs[1] = ci + 1;
+ break;
+ case 2:
+ tmp1 = ps[15];
+ tmp2 = ps[11];
+ ps[12] = ps[3];
+ ps[13] = pi + 0;
+ ps[14] = pi + 1;
+ ps[15] = pi + 2;
+ ps[8] = ps[7];
+ ps[11] = pi + 3;
+ ps[4] = tmp2;
+ ps[7] = pi + 4;
+ ps[0] = tmp1;
+ ps[1] = pi + 7;
+ ps[2] = pi + 6;
+ ps[3] = pi + 5;
+ tmp1 = cs[3];
+ cs[2] = cs[1];
+ cs[3] = ci;
+ cs[0] = tmp1;
+ cs[1] = ci + 1;
+ break;
+ case 3:
+ ps[12] = ps[0];
+ ps[13] = pi + 0;
+ ps[14] = pi + 1;
+ ps[15] = pi + 2;
+ ps[8] = ps[1];
+ ps[11] = pi + 3;
+ ps[4] = ps[2];
+ ps[7] = pi + 4;
+ ps[0] = ps[3];
+ ps[1] = pi + 7;
+ ps[2] = pi + 6;
+ ps[3] = pi + 5;
+ cs[2] = cs[0];
+ cs[3] = ci;
+ cs[0] = cs[1];
+ cs[1] = ci + 1;
+ break;
+ }
+ ps[5] = coords.length;
+ coords.push([(-4 * coords[ps[0]][0] - coords[ps[15]][0] + 6 * (coords[ps[4]][0] + coords[ps[1]][0]) - 2 * (coords[ps[12]][0] + coords[ps[3]][0]) + 3 * (coords[ps[13]][0] + coords[ps[7]][0])) / 9, (-4 * coords[ps[0]][1] - coords[ps[15]][1] + 6 * (coords[ps[4]][1] + coords[ps[1]][1]) - 2 * (coords[ps[12]][1] + coords[ps[3]][1]) + 3 * (coords[ps[13]][1] + coords[ps[7]][1])) / 9]);
+ ps[6] = coords.length;
+ coords.push([(-4 * coords[ps[3]][0] - coords[ps[12]][0] + 6 * (coords[ps[2]][0] + coords[ps[7]][0]) - 2 * (coords[ps[0]][0] + coords[ps[15]][0]) + 3 * (coords[ps[4]][0] + coords[ps[14]][0])) / 9, (-4 * coords[ps[3]][1] - coords[ps[12]][1] + 6 * (coords[ps[2]][1] + coords[ps[7]][1]) - 2 * (coords[ps[0]][1] + coords[ps[15]][1]) + 3 * (coords[ps[4]][1] + coords[ps[14]][1])) / 9]);
+ ps[9] = coords.length;
+ coords.push([(-4 * coords[ps[12]][0] - coords[ps[3]][0] + 6 * (coords[ps[8]][0] + coords[ps[13]][0]) - 2 * (coords[ps[0]][0] + coords[ps[15]][0]) + 3 * (coords[ps[11]][0] + coords[ps[1]][0])) / 9, (-4 * coords[ps[12]][1] - coords[ps[3]][1] + 6 * (coords[ps[8]][1] + coords[ps[13]][1]) - 2 * (coords[ps[0]][1] + coords[ps[15]][1]) + 3 * (coords[ps[11]][1] + coords[ps[1]][1])) / 9]);
+ ps[10] = coords.length;
+ coords.push([(-4 * coords[ps[15]][0] - coords[ps[0]][0] + 6 * (coords[ps[11]][0] + coords[ps[14]][0]) - 2 * (coords[ps[12]][0] + coords[ps[3]][0]) + 3 * (coords[ps[2]][0] + coords[ps[8]][0])) / 9, (-4 * coords[ps[15]][1] - coords[ps[0]][1] + 6 * (coords[ps[11]][1] + coords[ps[14]][1]) - 2 * (coords[ps[12]][1] + coords[ps[3]][1]) + 3 * (coords[ps[2]][1] + coords[ps[8]][1])) / 9]);
+ this.figures.push({
+ type: "patch",
+ coords: new Int32Array(ps),
+ colors: new Int32Array(cs)
+ });
+ }
+ }
+ _decodeType7Shading(reader) {
+ const coords = this.coords;
+ const colors = this.colors;
+ const ps = new Int32Array(16);
+ const cs = new Int32Array(4);
+ while (reader.hasData) {
+ const f = reader.readFlag();
+ if (!(0 <= f && f <= 3)) {
+ throw new FormatError("Unknown type7 flag");
+ }
+ const pi = coords.length;
+ for (let i = 0, ii = f !== 0 ? 12 : 16; i < ii; i++) {
+ coords.push(reader.readCoordinate());
+ }
+ const ci = colors.length;
+ for (let i = 0, ii = f !== 0 ? 2 : 4; i < ii; i++) {
+ colors.push(reader.readComponents());
+ }
+ let tmp1, tmp2, tmp3, tmp4;
+ switch (f) {
+ case 0:
+ ps[12] = pi + 3;
+ ps[13] = pi + 4;
+ ps[14] = pi + 5;
+ ps[15] = pi + 6;
+ ps[8] = pi + 2;
+ ps[9] = pi + 13;
+ ps[10] = pi + 14;
+ ps[11] = pi + 7;
+ ps[4] = pi + 1;
+ ps[5] = pi + 12;
+ ps[6] = pi + 15;
+ ps[7] = pi + 8;
+ ps[0] = pi;
+ ps[1] = pi + 11;
+ ps[2] = pi + 10;
+ ps[3] = pi + 9;
+ cs[2] = ci + 1;
+ cs[3] = ci + 2;
+ cs[0] = ci;
+ cs[1] = ci + 3;
+ break;
+ case 1:
+ tmp1 = ps[12];
+ tmp2 = ps[13];
+ tmp3 = ps[14];
+ tmp4 = ps[15];
+ ps[12] = tmp4;
+ ps[13] = pi + 0;
+ ps[14] = pi + 1;
+ ps[15] = pi + 2;
+ ps[8] = tmp3;
+ ps[9] = pi + 9;
+ ps[10] = pi + 10;
+ ps[11] = pi + 3;
+ ps[4] = tmp2;
+ ps[5] = pi + 8;
+ ps[6] = pi + 11;
+ ps[7] = pi + 4;
+ ps[0] = tmp1;
+ ps[1] = pi + 7;
+ ps[2] = pi + 6;
+ ps[3] = pi + 5;
+ tmp1 = cs[2];
+ tmp2 = cs[3];
+ cs[2] = tmp2;
+ cs[3] = ci;
+ cs[0] = tmp1;
+ cs[1] = ci + 1;
+ break;
+ case 2:
+ tmp1 = ps[15];
+ tmp2 = ps[11];
+ ps[12] = ps[3];
+ ps[13] = pi + 0;
+ ps[14] = pi + 1;
+ ps[15] = pi + 2;
+ ps[8] = ps[7];
+ ps[9] = pi + 9;
+ ps[10] = pi + 10;
+ ps[11] = pi + 3;
+ ps[4] = tmp2;
+ ps[5] = pi + 8;
+ ps[6] = pi + 11;
+ ps[7] = pi + 4;
+ ps[0] = tmp1;
+ ps[1] = pi + 7;
+ ps[2] = pi + 6;
+ ps[3] = pi + 5;
+ tmp1 = cs[3];
+ cs[2] = cs[1];
+ cs[3] = ci;
+ cs[0] = tmp1;
+ cs[1] = ci + 1;
+ break;
+ case 3:
+ ps[12] = ps[0];
+ ps[13] = pi + 0;
+ ps[14] = pi + 1;
+ ps[15] = pi + 2;
+ ps[8] = ps[1];
+ ps[9] = pi + 9;
+ ps[10] = pi + 10;
+ ps[11] = pi + 3;
+ ps[4] = ps[2];
+ ps[5] = pi + 8;
+ ps[6] = pi + 11;
+ ps[7] = pi + 4;
+ ps[0] = ps[3];
+ ps[1] = pi + 7;
+ ps[2] = pi + 6;
+ ps[3] = pi + 5;
+ cs[2] = cs[0];
+ cs[3] = ci;
+ cs[0] = cs[1];
+ cs[1] = ci + 1;
+ break;
+ }
+ this.figures.push({
+ type: "patch",
+ coords: new Int32Array(ps),
+ colors: new Int32Array(cs)
+ });
+ }
+ }
+ _buildFigureFromPatch(index) {
+ const figure = this.figures[index];
+ assert(figure.type === "patch", "Unexpected patch mesh figure");
+ const coords = this.coords,
+ colors = this.colors;
+ const pi = figure.coords;
+ const ci = figure.colors;
+ const figureMinX = Math.min(coords[pi[0]][0], coords[pi[3]][0], coords[pi[12]][0], coords[pi[15]][0]);
+ const figureMinY = Math.min(coords[pi[0]][1], coords[pi[3]][1], coords[pi[12]][1], coords[pi[15]][1]);
+ const figureMaxX = Math.max(coords[pi[0]][0], coords[pi[3]][0], coords[pi[12]][0], coords[pi[15]][0]);
+ const figureMaxY = Math.max(coords[pi[0]][1], coords[pi[3]][1], coords[pi[12]][1], coords[pi[15]][1]);
+ let splitXBy = Math.ceil((figureMaxX - figureMinX) * MeshShading.TRIANGLE_DENSITY / (this.bounds[2] - this.bounds[0]));
+ splitXBy = Math.max(MeshShading.MIN_SPLIT_PATCH_CHUNKS_AMOUNT, Math.min(MeshShading.MAX_SPLIT_PATCH_CHUNKS_AMOUNT, splitXBy));
+ let splitYBy = Math.ceil((figureMaxY - figureMinY) * MeshShading.TRIANGLE_DENSITY / (this.bounds[3] - this.bounds[1]));
+ splitYBy = Math.max(MeshShading.MIN_SPLIT_PATCH_CHUNKS_AMOUNT, Math.min(MeshShading.MAX_SPLIT_PATCH_CHUNKS_AMOUNT, splitYBy));
+ const verticesPerRow = splitXBy + 1;
+ const figureCoords = new Int32Array((splitYBy + 1) * verticesPerRow);
+ const figureColors = new Int32Array((splitYBy + 1) * verticesPerRow);
+ let k = 0;
+ const cl = new Uint8Array(3),
+ cr = new Uint8Array(3);
+ const c0 = colors[ci[0]],
+ c1 = colors[ci[1]],
+ c2 = colors[ci[2]],
+ c3 = colors[ci[3]];
+ const bRow = getB(splitYBy),
+ bCol = getB(splitXBy);
+ for (let row = 0; row <= splitYBy; row++) {
+ cl[0] = (c0[0] * (splitYBy - row) + c2[0] * row) / splitYBy | 0;
+ cl[1] = (c0[1] * (splitYBy - row) + c2[1] * row) / splitYBy | 0;
+ cl[2] = (c0[2] * (splitYBy - row) + c2[2] * row) / splitYBy | 0;
+ cr[0] = (c1[0] * (splitYBy - row) + c3[0] * row) / splitYBy | 0;
+ cr[1] = (c1[1] * (splitYBy - row) + c3[1] * row) / splitYBy | 0;
+ cr[2] = (c1[2] * (splitYBy - row) + c3[2] * row) / splitYBy | 0;
+ for (let col = 0; col <= splitXBy; col++, k++) {
+ if ((row === 0 || row === splitYBy) && (col === 0 || col === splitXBy)) {
+ continue;
+ }
+ let x = 0,
+ y = 0;
+ let q = 0;
+ for (let i = 0; i <= 3; i++) {
+ for (let j = 0; j <= 3; j++, q++) {
+ const m = bRow[row][i] * bCol[col][j];
+ x += coords[pi[q]][0] * m;
+ y += coords[pi[q]][1] * m;
+ }
+ }
+ figureCoords[k] = coords.length;
+ coords.push([x, y]);
+ figureColors[k] = colors.length;
+ const newColor = new Uint8Array(3);
+ newColor[0] = (cl[0] * (splitXBy - col) + cr[0] * col) / splitXBy | 0;
+ newColor[1] = (cl[1] * (splitXBy - col) + cr[1] * col) / splitXBy | 0;
+ newColor[2] = (cl[2] * (splitXBy - col) + cr[2] * col) / splitXBy | 0;
+ colors.push(newColor);
+ }
+ }
+ figureCoords[0] = pi[0];
+ figureColors[0] = ci[0];
+ figureCoords[splitXBy] = pi[3];
+ figureColors[splitXBy] = ci[1];
+ figureCoords[verticesPerRow * splitYBy] = pi[12];
+ figureColors[verticesPerRow * splitYBy] = ci[2];
+ figureCoords[verticesPerRow * splitYBy + splitXBy] = pi[15];
+ figureColors[verticesPerRow * splitYBy + splitXBy] = ci[3];
+ this.figures[index] = {
+ type: "lattice",
+ coords: figureCoords,
+ colors: figureColors,
+ verticesPerRow
+ };
+ }
+ _updateBounds() {
+ let minX = this.coords[0][0],
+ minY = this.coords[0][1],
+ maxX = minX,
+ maxY = minY;
+ for (let i = 1, ii = this.coords.length; i < ii; i++) {
+ const x = this.coords[i][0],
+ y = this.coords[i][1];
+ minX = minX > x ? x : minX;
+ minY = minY > y ? y : minY;
+ maxX = maxX < x ? x : maxX;
+ maxY = maxY < y ? y : maxY;
+ }
+ this.bounds = [minX, minY, maxX, maxY];
+ }
+ _packData() {
+ let i, ii, j, jj;
+ const coords = this.coords;
+ const coordsPacked = new Float32Array(coords.length * 2);
+ for (i = 0, j = 0, ii = coords.length; i < ii; i++) {
+ const xy = coords[i];
+ coordsPacked[j++] = xy[0];
+ coordsPacked[j++] = xy[1];
+ }
+ this.coords = coordsPacked;
+ const colors = this.colors;
+ const colorsPacked = new Uint8Array(colors.length * 3);
+ for (i = 0, j = 0, ii = colors.length; i < ii; i++) {
+ const c = colors[i];
+ colorsPacked[j++] = c[0];
+ colorsPacked[j++] = c[1];
+ colorsPacked[j++] = c[2];
+ }
+ this.colors = colorsPacked;
+ const figures = this.figures;
+ for (i = 0, ii = figures.length; i < ii; i++) {
+ const figure = figures[i],
+ ps = figure.coords,
+ cs = figure.colors;
+ for (j = 0, jj = ps.length; j < jj; j++) {
+ ps[j] *= 2;
+ cs[j] *= 3;
+ }
+ }
+ }
+ getIR() {
+ return ["Mesh", this.shadingType, this.coords, this.colors, this.figures, this.bounds, this.bbox, this.background];
+ }
+}
+class DummyShading extends BaseShading {
+ getIR() {
+ return ["Dummy"];
+ }
+}
+function getTilingPatternIR(operatorList, dict, color) {
+ const matrix = dict.getArray("Matrix");
+ const bbox = Util.normalizeRect(dict.getArray("BBox"));
+ const xstep = dict.get("XStep");
+ const ystep = dict.get("YStep");
+ const paintType = dict.get("PaintType");
+ const tilingType = dict.get("TilingType");
+ if (bbox[2] - bbox[0] === 0 || bbox[3] - bbox[1] === 0) {
+ throw new FormatError(`Invalid getTilingPatternIR /BBox array: [${bbox}].`);
+ }
+ return ["TilingPattern", color, operatorList, matrix, bbox, xstep, ystep, paintType, tilingType];
+}
+
+;// CONCATENATED MODULE: ./src/core/calibri_factors.js
+const CalibriBoldFactors = [1.3877, 1, 1, 1, 0.97801, 0.92482, 0.89552, 0.91133, 0.81988, 0.97566, 0.98152, 0.93548, 0.93548, 1.2798, 0.85284, 0.92794, 1, 0.96134, 1.54657, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.82845, 0.82845, 0.85284, 0.85284, 0.85284, 0.75859, 0.92138, 0.83908, 0.7762, 0.73293, 0.87289, 0.73133, 0.7514, 0.81921, 0.87356, 0.95958, 0.59526, 0.75727, 0.69225, 1.04924, 0.9121, 0.86943, 0.79795, 0.88198, 0.77958, 0.70864, 0.81055, 0.90399, 0.88653, 0.96017, 0.82577, 0.77892, 0.78257, 0.97507, 1.54657, 0.97507, 0.85284, 0.89552, 0.90176, 0.88762, 0.8785, 0.75241, 0.8785, 0.90518, 0.95015, 0.77618, 0.8785, 0.88401, 0.91916, 0.86304, 0.88401, 0.91488, 0.8785, 0.8801, 0.8785, 0.8785, 0.91343, 0.7173, 1.04106, 0.8785, 0.85075, 0.95794, 0.82616, 0.85162, 0.79492, 0.88331, 1.69808, 0.88331, 0.85284, 0.97801, 0.89552, 0.91133, 0.89552, 0.91133, 1.7801, 0.89552, 1.24487, 1.13254, 1.12401, 0.96839, 0.85284, 0.68787, 0.70645, 0.85592, 0.90747, 1.01466, 1.0088, 0.90323, 1, 1.07463, 1, 0.91056, 0.75806, 1.19118, 0.96839, 0.78864, 0.82845, 0.84133, 0.75859, 0.83908, 0.83908, 0.83908, 0.83908, 0.83908, 0.83908, 0.77539, 0.73293, 0.73133, 0.73133, 0.73133, 0.73133, 0.95958, 0.95958, 0.95958, 0.95958, 0.88506, 0.9121, 0.86943, 0.86943, 0.86943, 0.86943, 0.86943, 0.85284, 0.87508, 0.90399, 0.90399, 0.90399, 0.90399, 0.77892, 0.79795, 0.90807, 0.88762, 0.88762, 0.88762, 0.88762, 0.88762, 0.88762, 0.8715, 0.75241, 0.90518, 0.90518, 0.90518, 0.90518, 0.88401, 0.88401, 0.88401, 0.88401, 0.8785, 0.8785, 0.8801, 0.8801, 0.8801, 0.8801, 0.8801, 0.90747, 0.89049, 0.8785, 0.8785, 0.8785, 0.8785, 0.85162, 0.8785, 0.85162, 0.83908, 0.88762, 0.83908, 0.88762, 0.83908, 0.88762, 0.73293, 0.75241, 0.73293, 0.75241, 0.73293, 0.75241, 0.73293, 0.75241, 0.87289, 0.83016, 0.88506, 0.93125, 0.73133, 0.90518, 0.73133, 0.90518, 0.73133, 0.90518, 0.73133, 0.90518, 0.73133, 0.90518, 0.81921, 0.77618, 0.81921, 0.77618, 0.81921, 0.77618, 1, 1, 0.87356, 0.8785, 0.91075, 0.89608, 0.95958, 0.88401, 0.95958, 0.88401, 0.95958, 0.88401, 0.95958, 0.88401, 0.95958, 0.88401, 0.76229, 0.90167, 0.59526, 0.91916, 1, 1, 0.86304, 0.69225, 0.88401, 1, 1, 0.70424, 0.79468, 0.91926, 0.88175, 0.70823, 0.94903, 0.9121, 0.8785, 1, 1, 0.9121, 0.8785, 0.87802, 0.88656, 0.8785, 0.86943, 0.8801, 0.86943, 0.8801, 0.86943, 0.8801, 0.87402, 0.89291, 0.77958, 0.91343, 1, 1, 0.77958, 0.91343, 0.70864, 0.7173, 0.70864, 0.7173, 0.70864, 0.7173, 0.70864, 0.7173, 1, 1, 0.81055, 0.75841, 0.81055, 1.06452, 0.90399, 0.8785, 0.90399, 0.8785, 0.90399, 0.8785, 0.90399, 0.8785, 0.90399, 0.8785, 0.90399, 0.8785, 0.96017, 0.95794, 0.77892, 0.85162, 0.77892, 0.78257, 0.79492, 0.78257, 0.79492, 0.78257, 0.79492, 0.9297, 0.56892, 0.83908, 0.88762, 0.77539, 0.8715, 0.87508, 0.89049, 1, 1, 0.81055, 1.04106, 1.20528, 1.20528, 1, 1.15543, 0.70674, 0.98387, 0.94721, 1.33431, 1.45894, 0.95161, 1.06303, 0.83908, 0.80352, 0.57184, 0.6965, 0.56289, 0.82001, 0.56029, 0.81235, 1.02988, 0.83908, 0.7762, 0.68156, 0.80367, 0.73133, 0.78257, 0.87356, 0.86943, 0.95958, 0.75727, 0.89019, 1.04924, 0.9121, 0.7648, 0.86943, 0.87356, 0.79795, 0.78275, 0.81055, 0.77892, 0.9762, 0.82577, 0.99819, 0.84896, 0.95958, 0.77892, 0.96108, 1.01407, 0.89049, 1.02988, 0.94211, 0.96108, 0.8936, 0.84021, 0.87842, 0.96399, 0.79109, 0.89049, 1.00813, 1.02988, 0.86077, 0.87445, 0.92099, 0.84723, 0.86513, 0.8801, 0.75638, 0.85714, 0.78216, 0.79586, 0.87965, 0.94211, 0.97747, 0.78287, 0.97926, 0.84971, 1.02988, 0.94211, 0.8801, 0.94211, 0.84971, 0.73133, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.90264, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.90518, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.90548, 1, 1, 1, 1, 1, 1, 0.96017, 0.95794, 0.96017, 0.95794, 0.96017, 0.95794, 0.77892, 0.85162, 1, 1, 0.89552, 0.90527, 1, 0.90363, 0.92794, 0.92794, 0.92794, 0.92794, 0.87012, 0.87012, 0.87012, 0.89552, 0.89552, 1.42259, 0.71143, 1.06152, 1, 1, 1.03372, 1.03372, 0.97171, 1.4956, 2.2807, 0.93835, 0.83406, 0.91133, 0.84107, 0.91133, 1, 1, 1, 0.72021, 1, 1.23108, 0.83489, 0.88525, 0.88525, 0.81499, 0.90527, 1.81055, 0.90527, 1.81055, 1.31006, 1.53711, 0.94434, 1.08696, 1, 0.95018, 0.77192, 0.85284, 0.90747, 1.17534, 0.69825, 0.9716, 1.37077, 0.90747, 0.90747, 0.85356, 0.90747, 0.90747, 1.44947, 0.85284, 0.8941, 0.8941, 0.70572, 0.8, 0.70572, 0.70572, 0.70572, 0.70572, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.99862, 0.99862, 1, 1, 1, 1, 1, 1.08004, 0.91027, 1, 1, 1, 0.99862, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.90727, 0.90727, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1];
+const CalibriBoldMetrics = {
+ lineHeight: 1.2207,
+ lineGap: 0.2207
+};
+const CalibriBoldItalicFactors = [1.3877, 1, 1, 1, 0.97801, 0.92482, 0.89552, 0.91133, 0.81988, 0.97566, 0.98152, 0.93548, 0.93548, 1.2798, 0.85284, 0.92794, 1, 0.96134, 1.56239, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.82845, 0.82845, 0.85284, 0.85284, 0.85284, 0.75859, 0.92138, 0.83908, 0.7762, 0.71805, 0.87289, 0.73133, 0.7514, 0.81921, 0.87356, 0.95958, 0.59526, 0.75727, 0.69225, 1.04924, 0.90872, 0.85938, 0.79795, 0.87068, 0.77958, 0.69766, 0.81055, 0.90399, 0.88653, 0.96068, 0.82577, 0.77892, 0.78257, 0.97507, 1.529, 0.97507, 0.85284, 0.89552, 0.90176, 0.94908, 0.86411, 0.74012, 0.86411, 0.88323, 0.95015, 0.86411, 0.86331, 0.88401, 0.91916, 0.86304, 0.88401, 0.9039, 0.86331, 0.86331, 0.86411, 0.86411, 0.90464, 0.70852, 1.04106, 0.86331, 0.84372, 0.95794, 0.82616, 0.84548, 0.79492, 0.88331, 1.69808, 0.88331, 0.85284, 0.97801, 0.89552, 0.91133, 0.89552, 0.91133, 1.7801, 0.89552, 1.24487, 1.13254, 1.19129, 0.96839, 0.85284, 0.68787, 0.70645, 0.85592, 0.90747, 1.01466, 1.0088, 0.90323, 1, 1.07463, 1, 0.91056, 0.75806, 1.19118, 0.96839, 0.78864, 0.82845, 0.84133, 0.75859, 0.83908, 0.83908, 0.83908, 0.83908, 0.83908, 0.83908, 0.77539, 0.71805, 0.73133, 0.73133, 0.73133, 0.73133, 0.95958, 0.95958, 0.95958, 0.95958, 0.88506, 0.90872, 0.85938, 0.85938, 0.85938, 0.85938, 0.85938, 0.85284, 0.87068, 0.90399, 0.90399, 0.90399, 0.90399, 0.77892, 0.79795, 0.90807, 0.94908, 0.94908, 0.94908, 0.94908, 0.94908, 0.94908, 0.85887, 0.74012, 0.88323, 0.88323, 0.88323, 0.88323, 0.88401, 0.88401, 0.88401, 0.88401, 0.8785, 0.86331, 0.86331, 0.86331, 0.86331, 0.86331, 0.86331, 0.90747, 0.89049, 0.86331, 0.86331, 0.86331, 0.86331, 0.84548, 0.86411, 0.84548, 0.83908, 0.94908, 0.83908, 0.94908, 0.83908, 0.94908, 0.71805, 0.74012, 0.71805, 0.74012, 0.71805, 0.74012, 0.71805, 0.74012, 0.87289, 0.79538, 0.88506, 0.92726, 0.73133, 0.88323, 0.73133, 0.88323, 0.73133, 0.88323, 0.73133, 0.88323, 0.73133, 0.88323, 0.81921, 0.86411, 0.81921, 0.86411, 0.81921, 0.86411, 1, 1, 0.87356, 0.86331, 0.91075, 0.8777, 0.95958, 0.88401, 0.95958, 0.88401, 0.95958, 0.88401, 0.95958, 0.88401, 0.95958, 0.88401, 0.76467, 0.90167, 0.59526, 0.91916, 1, 1, 0.86304, 0.69225, 0.88401, 1, 1, 0.70424, 0.77312, 0.91926, 0.88175, 0.70823, 0.94903, 0.90872, 0.86331, 1, 1, 0.90872, 0.86331, 0.86906, 0.88116, 0.86331, 0.85938, 0.86331, 0.85938, 0.86331, 0.85938, 0.86331, 0.87402, 0.86549, 0.77958, 0.90464, 1, 1, 0.77958, 0.90464, 0.69766, 0.70852, 0.69766, 0.70852, 0.69766, 0.70852, 0.69766, 0.70852, 1, 1, 0.81055, 0.75841, 0.81055, 1.06452, 0.90399, 0.86331, 0.90399, 0.86331, 0.90399, 0.86331, 0.90399, 0.86331, 0.90399, 0.86331, 0.90399, 0.86331, 0.96068, 0.95794, 0.77892, 0.84548, 0.77892, 0.78257, 0.79492, 0.78257, 0.79492, 0.78257, 0.79492, 0.9297, 0.56892, 0.83908, 0.94908, 0.77539, 0.85887, 0.87068, 0.89049, 1, 1, 0.81055, 1.04106, 1.20528, 1.20528, 1, 1.15543, 0.70088, 0.98387, 0.94721, 1.33431, 1.45894, 0.95161, 1.48387, 0.83908, 0.80352, 0.57118, 0.6965, 0.56347, 0.79179, 0.55853, 0.80346, 1.02988, 0.83908, 0.7762, 0.67174, 0.86036, 0.73133, 0.78257, 0.87356, 0.86441, 0.95958, 0.75727, 0.89019, 1.04924, 0.90872, 0.74889, 0.85938, 0.87891, 0.79795, 0.7957, 0.81055, 0.77892, 0.97447, 0.82577, 0.97466, 0.87179, 0.95958, 0.77892, 0.94252, 0.95612, 0.8753, 1.02988, 0.92733, 0.94252, 0.87411, 0.84021, 0.8728, 0.95612, 0.74081, 0.8753, 1.02189, 1.02988, 0.84814, 0.87445, 0.91822, 0.84723, 0.85668, 0.86331, 0.81344, 0.87581, 0.76422, 0.82046, 0.96057, 0.92733, 0.99375, 0.78022, 0.95452, 0.86015, 1.02988, 0.92733, 0.86331, 0.92733, 0.86015, 0.73133, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.90631, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.88323, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.85174, 1, 1, 1, 1, 1, 1, 0.96068, 0.95794, 0.96068, 0.95794, 0.96068, 0.95794, 0.77892, 0.84548, 1, 1, 0.89552, 0.90527, 1, 0.90363, 0.92794, 0.92794, 0.92794, 0.89807, 0.87012, 0.87012, 0.87012, 0.89552, 0.89552, 1.42259, 0.71094, 1.06152, 1, 1, 1.03372, 1.03372, 0.97171, 1.4956, 2.2807, 0.92972, 0.83406, 0.91133, 0.83326, 0.91133, 1, 1, 1, 0.72021, 1, 1.23108, 0.83489, 0.88525, 0.88525, 0.81499, 0.90616, 1.81055, 0.90527, 1.81055, 1.3107, 1.53711, 0.94434, 1.08696, 1, 0.95018, 0.77192, 0.85284, 0.90747, 1.17534, 0.69825, 0.9716, 1.37077, 0.90747, 0.90747, 0.85356, 0.90747, 0.90747, 1.44947, 0.85284, 0.8941, 0.8941, 0.70572, 0.8, 0.70572, 0.70572, 0.70572, 0.70572, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.99862, 0.99862, 1, 1, 1, 1, 1, 1.08004, 0.91027, 1, 1, 1, 0.99862, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.90727, 0.90727, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1];
+const CalibriBoldItalicMetrics = {
+ lineHeight: 1.2207,
+ lineGap: 0.2207
+};
+const CalibriItalicFactors = [1.3877, 1, 1, 1, 1.17223, 1.1293, 0.89552, 0.91133, 0.80395, 1.02269, 1.15601, 0.91056, 0.91056, 1.2798, 0.85284, 0.89807, 1, 0.90861, 1.39543, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.96309, 0.96309, 0.85284, 0.85284, 0.85284, 0.83319, 0.88071, 0.8675, 0.81552, 0.72346, 0.85193, 0.73206, 0.7522, 0.81105, 0.86275, 0.90685, 0.6377, 0.77892, 0.75593, 1.02638, 0.89249, 0.84118, 0.77452, 0.85374, 0.75186, 0.67789, 0.79776, 0.88844, 0.85066, 0.94309, 0.77818, 0.7306, 0.76659, 1.10369, 1.38313, 1.10369, 1.06139, 0.89552, 0.8739, 0.9245, 0.9245, 0.83203, 0.9245, 0.85865, 1.09842, 0.9245, 0.9245, 1.03297, 1.07692, 0.90918, 1.03297, 0.94959, 0.9245, 0.92274, 0.9245, 0.9245, 1.02933, 0.77832, 1.20562, 0.9245, 0.8916, 0.98986, 0.86621, 0.89453, 0.79004, 0.94152, 1.77256, 0.94152, 0.85284, 0.97801, 0.89552, 0.91133, 0.89552, 0.91133, 1.91729, 0.89552, 1.17889, 1.13254, 1.16359, 0.92098, 0.85284, 0.68787, 0.71353, 0.84737, 0.90747, 1.0088, 1.0044, 0.87683, 1, 1.09091, 1, 0.92229, 0.739, 1.15642, 0.92098, 0.76288, 0.80504, 0.80972, 0.75859, 0.8675, 0.8675, 0.8675, 0.8675, 0.8675, 0.8675, 0.76318, 0.72346, 0.73206, 0.73206, 0.73206, 0.73206, 0.90685, 0.90685, 0.90685, 0.90685, 0.86477, 0.89249, 0.84118, 0.84118, 0.84118, 0.84118, 0.84118, 0.85284, 0.84557, 0.88844, 0.88844, 0.88844, 0.88844, 0.7306, 0.77452, 0.86331, 0.9245, 0.9245, 0.9245, 0.9245, 0.9245, 0.9245, 0.84843, 0.83203, 0.85865, 0.85865, 0.85865, 0.85865, 0.82601, 0.82601, 0.82601, 0.82601, 0.94469, 0.9245, 0.92274, 0.92274, 0.92274, 0.92274, 0.92274, 0.90747, 0.86651, 0.9245, 0.9245, 0.9245, 0.9245, 0.89453, 0.9245, 0.89453, 0.8675, 0.9245, 0.8675, 0.9245, 0.8675, 0.9245, 0.72346, 0.83203, 0.72346, 0.83203, 0.72346, 0.83203, 0.72346, 0.83203, 0.85193, 0.8875, 0.86477, 0.99034, 0.73206, 0.85865, 0.73206, 0.85865, 0.73206, 0.85865, 0.73206, 0.85865, 0.73206, 0.85865, 0.81105, 0.9245, 0.81105, 0.9245, 0.81105, 0.9245, 1, 1, 0.86275, 0.9245, 0.90872, 0.93591, 0.90685, 0.82601, 0.90685, 0.82601, 0.90685, 0.82601, 0.90685, 1.03297, 0.90685, 0.82601, 0.77896, 1.05611, 0.6377, 1.07692, 1, 1, 0.90918, 0.75593, 1.03297, 1, 1, 0.76032, 0.9375, 0.98156, 0.93407, 0.77261, 1.11429, 0.89249, 0.9245, 1, 1, 0.89249, 0.9245, 0.92534, 0.86698, 0.9245, 0.84118, 0.92274, 0.84118, 0.92274, 0.84118, 0.92274, 0.8667, 0.86291, 0.75186, 1.02933, 1, 1, 0.75186, 1.02933, 0.67789, 0.77832, 0.67789, 0.77832, 0.67789, 0.77832, 0.67789, 0.77832, 1, 1, 0.79776, 0.97655, 0.79776, 1.23023, 0.88844, 0.9245, 0.88844, 0.9245, 0.88844, 0.9245, 0.88844, 0.9245, 0.88844, 0.9245, 0.88844, 0.9245, 0.94309, 0.98986, 0.7306, 0.89453, 0.7306, 0.76659, 0.79004, 0.76659, 0.79004, 0.76659, 0.79004, 1.09231, 0.54873, 0.8675, 0.9245, 0.76318, 0.84843, 0.84557, 0.86651, 1, 1, 0.79776, 1.20562, 1.18622, 1.18622, 1, 1.1437, 0.67009, 0.96334, 0.93695, 1.35191, 1.40909, 0.95161, 1.48387, 0.8675, 0.90861, 0.6192, 0.7363, 0.64824, 0.82411, 0.56321, 0.85696, 1.23516, 0.8675, 0.81552, 0.7286, 0.84134, 0.73206, 0.76659, 0.86275, 0.84369, 0.90685, 0.77892, 0.85871, 1.02638, 0.89249, 0.75828, 0.84118, 0.85984, 0.77452, 0.76466, 0.79776, 0.7306, 0.90782, 0.77818, 0.903, 0.87291, 0.90685, 0.7306, 0.99058, 1.03667, 0.94635, 1.23516, 0.9849, 0.99058, 0.92393, 0.8916, 0.942, 1.03667, 0.75026, 0.94635, 1.0297, 1.23516, 0.90918, 0.94048, 0.98217, 0.89746, 0.84153, 0.92274, 0.82507, 0.88832, 0.84438, 0.88178, 1.03525, 0.9849, 1.00225, 0.78086, 0.97248, 0.89404, 1.23516, 0.9849, 0.92274, 0.9849, 0.89404, 0.73206, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.89693, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.85865, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.90933, 1, 1, 1, 1, 1, 1, 0.94309, 0.98986, 0.94309, 0.98986, 0.94309, 0.98986, 0.7306, 0.89453, 1, 1, 0.89552, 0.90527, 1, 0.90186, 1.12308, 1.12308, 1.12308, 1.12308, 1.2566, 1.2566, 1.2566, 0.89552, 0.89552, 1.42259, 0.68994, 1.03809, 1, 1, 1.0176, 1.0176, 1.11523, 1.4956, 2.01462, 0.97858, 0.82616, 0.91133, 0.83437, 0.91133, 1, 1, 1, 0.70508, 1, 1.23108, 0.79801, 0.84426, 0.84426, 0.774, 0.90572, 1.81055, 0.90749, 1.81055, 1.28809, 1.55469, 0.94434, 1.07806, 1, 0.97094, 0.7589, 0.85284, 0.90747, 1.19658, 0.69825, 0.97622, 1.33512, 0.90747, 0.90747, 0.85284, 0.90747, 0.90747, 1.44947, 0.85284, 0.8941, 0.8941, 0.70572, 0.8, 0.70572, 0.70572, 0.70572, 0.70572, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.99862, 0.99862, 1, 1, 1, 1, 1, 1.0336, 0.91027, 1, 1, 1, 0.99862, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.05859, 1.05859, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1];
+const CalibriItalicMetrics = {
+ lineHeight: 1.2207,
+ lineGap: 0.2207
+};
+const CalibriRegularFactors = [1.3877, 1, 1, 1, 1.17223, 1.1293, 0.89552, 0.91133, 0.80395, 1.02269, 1.15601, 0.91056, 0.91056, 1.2798, 0.85284, 0.89807, 1, 0.90861, 1.39016, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.96309, 0.96309, 0.85284, 0.85284, 0.85284, 0.83319, 0.88071, 0.8675, 0.81552, 0.73834, 0.85193, 0.73206, 0.7522, 0.81105, 0.86275, 0.90685, 0.6377, 0.77892, 0.75593, 1.02638, 0.89385, 0.85122, 0.77452, 0.86503, 0.75186, 0.68887, 0.79776, 0.88844, 0.85066, 0.94258, 0.77818, 0.7306, 0.76659, 1.10369, 1.39016, 1.10369, 1.06139, 0.89552, 0.8739, 0.86128, 0.94469, 0.8457, 0.94469, 0.89464, 1.09842, 0.84636, 0.94469, 1.03297, 1.07692, 0.90918, 1.03297, 0.95897, 0.94469, 0.9482, 0.94469, 0.94469, 1.04692, 0.78223, 1.20562, 0.94469, 0.90332, 0.98986, 0.86621, 0.90527, 0.79004, 0.94152, 1.77256, 0.94152, 0.85284, 0.97801, 0.89552, 0.91133, 0.89552, 0.91133, 1.91729, 0.89552, 1.17889, 1.13254, 1.08707, 0.92098, 0.85284, 0.68787, 0.71353, 0.84737, 0.90747, 1.0088, 1.0044, 0.87683, 1, 1.09091, 1, 0.92229, 0.739, 1.15642, 0.92098, 0.76288, 0.80504, 0.80972, 0.75859, 0.8675, 0.8675, 0.8675, 0.8675, 0.8675, 0.8675, 0.76318, 0.73834, 0.73206, 0.73206, 0.73206, 0.73206, 0.90685, 0.90685, 0.90685, 0.90685, 0.86477, 0.89385, 0.85122, 0.85122, 0.85122, 0.85122, 0.85122, 0.85284, 0.85311, 0.88844, 0.88844, 0.88844, 0.88844, 0.7306, 0.77452, 0.86331, 0.86128, 0.86128, 0.86128, 0.86128, 0.86128, 0.86128, 0.8693, 0.8457, 0.89464, 0.89464, 0.89464, 0.89464, 0.82601, 0.82601, 0.82601, 0.82601, 0.94469, 0.94469, 0.9482, 0.9482, 0.9482, 0.9482, 0.9482, 0.90747, 0.86651, 0.94469, 0.94469, 0.94469, 0.94469, 0.90527, 0.94469, 0.90527, 0.8675, 0.86128, 0.8675, 0.86128, 0.8675, 0.86128, 0.73834, 0.8457, 0.73834, 0.8457, 0.73834, 0.8457, 0.73834, 0.8457, 0.85193, 0.92454, 0.86477, 0.9921, 0.73206, 0.89464, 0.73206, 0.89464, 0.73206, 0.89464, 0.73206, 0.89464, 0.73206, 0.89464, 0.81105, 0.84636, 0.81105, 0.84636, 0.81105, 0.84636, 1, 1, 0.86275, 0.94469, 0.90872, 0.95786, 0.90685, 0.82601, 0.90685, 0.82601, 0.90685, 0.82601, 0.90685, 1.03297, 0.90685, 0.82601, 0.77741, 1.05611, 0.6377, 1.07692, 1, 1, 0.90918, 0.75593, 1.03297, 1, 1, 0.76032, 0.90452, 0.98156, 1.11842, 0.77261, 1.11429, 0.89385, 0.94469, 1, 1, 0.89385, 0.94469, 0.95877, 0.86901, 0.94469, 0.85122, 0.9482, 0.85122, 0.9482, 0.85122, 0.9482, 0.8667, 0.90016, 0.75186, 1.04692, 1, 1, 0.75186, 1.04692, 0.68887, 0.78223, 0.68887, 0.78223, 0.68887, 0.78223, 0.68887, 0.78223, 1, 1, 0.79776, 0.92188, 0.79776, 1.23023, 0.88844, 0.94469, 0.88844, 0.94469, 0.88844, 0.94469, 0.88844, 0.94469, 0.88844, 0.94469, 0.88844, 0.94469, 0.94258, 0.98986, 0.7306, 0.90527, 0.7306, 0.76659, 0.79004, 0.76659, 0.79004, 0.76659, 0.79004, 1.09231, 0.54873, 0.8675, 0.86128, 0.76318, 0.8693, 0.85311, 0.86651, 1, 1, 0.79776, 1.20562, 1.18622, 1.18622, 1, 1.1437, 0.67742, 0.96334, 0.93695, 1.35191, 1.40909, 0.95161, 1.48387, 0.86686, 0.90861, 0.62267, 0.74359, 0.65649, 0.85498, 0.56963, 0.88254, 1.23516, 0.8675, 0.81552, 0.75443, 0.84503, 0.73206, 0.76659, 0.86275, 0.85122, 0.90685, 0.77892, 0.85746, 1.02638, 0.89385, 0.75657, 0.85122, 0.86275, 0.77452, 0.74171, 0.79776, 0.7306, 0.95165, 0.77818, 0.89772, 0.88831, 0.90685, 0.7306, 0.98142, 1.02191, 0.96576, 1.23516, 0.99018, 0.98142, 0.9236, 0.89258, 0.94035, 1.02191, 0.78848, 0.96576, 0.9561, 1.23516, 0.90918, 0.92578, 0.95424, 0.89746, 0.83969, 0.9482, 0.80113, 0.89442, 0.85208, 0.86155, 0.98022, 0.99018, 1.00452, 0.81209, 0.99247, 0.89181, 1.23516, 0.99018, 0.9482, 0.99018, 0.89181, 0.73206, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.88844, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.89464, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.96766, 1, 1, 1, 1, 1, 1, 0.94258, 0.98986, 0.94258, 0.98986, 0.94258, 0.98986, 0.7306, 0.90527, 1, 1, 0.89552, 0.90527, 1, 0.90186, 1.12308, 1.12308, 1.12308, 1.12308, 1.2566, 1.2566, 1.2566, 0.89552, 0.89552, 1.42259, 0.69043, 1.03809, 1, 1, 1.0176, 1.0176, 1.11523, 1.4956, 2.01462, 0.99331, 0.82616, 0.91133, 0.84286, 0.91133, 1, 1, 1, 0.70508, 1, 1.23108, 0.79801, 0.84426, 0.84426, 0.774, 0.90527, 1.81055, 0.90527, 1.81055, 1.28809, 1.55469, 0.94434, 1.07806, 1, 0.97094, 0.7589, 0.85284, 0.90747, 1.19658, 0.69825, 0.97622, 1.33512, 0.90747, 0.90747, 0.85356, 0.90747, 0.90747, 1.44947, 0.85284, 0.8941, 0.8941, 0.70572, 0.8, 0.70572, 0.70572, 0.70572, 0.70572, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.99862, 0.99862, 1, 1, 1, 1, 1, 1.0336, 0.91027, 1, 1, 1, 0.99862, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.05859, 1.05859, 1, 1, 1, 1.07185, 0.99413, 0.96334, 1.08065, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1];
+const CalibriRegularMetrics = {
+ lineHeight: 1.2207,
+ lineGap: 0.2207
+};
+
+;// CONCATENATED MODULE: ./src/core/helvetica_factors.js
+const HelveticaBoldFactors = [0.76116, 1, 1, 1.0006, 0.99998, 0.99974, 0.99973, 0.99973, 0.99982, 0.99977, 1.00087, 0.99998, 0.99998, 0.99959, 1.00003, 1.0006, 0.99998, 1.0006, 1.0006, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99998, 1, 1.00003, 1.00003, 1.00003, 1.00026, 0.9999, 0.99977, 0.99977, 0.99977, 0.99977, 1.00001, 1.00026, 1.00022, 0.99977, 1.0006, 0.99973, 0.99977, 1.00026, 0.99999, 0.99977, 1.00022, 1.00001, 1.00022, 0.99977, 1.00001, 1.00026, 0.99977, 1.00001, 1.00016, 1.00001, 1.00001, 1.00026, 0.99998, 1.0006, 0.99998, 1.00003, 0.99973, 0.99998, 0.99973, 1.00026, 0.99973, 1.00026, 0.99973, 0.99998, 1.00026, 1.00026, 1.0006, 1.0006, 0.99973, 1.0006, 0.99982, 1.00026, 1.00026, 1.00026, 1.00026, 0.99959, 0.99973, 0.99998, 1.00026, 0.99973, 1.00022, 0.99973, 0.99973, 1, 0.99959, 1.00077, 0.99959, 1.00003, 0.99998, 0.99973, 0.99973, 0.99973, 0.99973, 1.00077, 0.99973, 0.99998, 1.00025, 0.99968, 0.99973, 1.00003, 1.00025, 0.60299, 1.00024, 1.06409, 1, 1, 0.99998, 1, 0.99973, 1.0006, 0.99998, 1, 0.99936, 0.99973, 1.00002, 1.00002, 1.00002, 1.00026, 0.99977, 0.99977, 0.99977, 0.99977, 0.99977, 0.99977, 1, 0.99977, 1.00001, 1.00001, 1.00001, 1.00001, 1.0006, 1.0006, 1.0006, 1.0006, 0.99977, 0.99977, 1.00022, 1.00022, 1.00022, 1.00022, 1.00022, 1.00003, 1.00022, 0.99977, 0.99977, 0.99977, 0.99977, 1.00001, 1.00001, 1.00026, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99982, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 1.0006, 1.0006, 1.0006, 1.0006, 1.00026, 1.00026, 1.00026, 1.00026, 1.00026, 1.00026, 1.00026, 1.06409, 1.00026, 1.00026, 1.00026, 1.00026, 1.00026, 0.99973, 1.00026, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 1.03374, 0.99977, 1.00026, 1.00001, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 1.00022, 1.00026, 1.00022, 1.00026, 1.00022, 1.00026, 1.00022, 1.00026, 0.99977, 1.00026, 0.99977, 1.00026, 1.0006, 1.0006, 1.0006, 1.0006, 1.0006, 1.0006, 1.0006, 1.0006, 1.0006, 1.0006, 1.00042, 0.99973, 0.99973, 1.0006, 0.99977, 0.99973, 0.99973, 1.00026, 1.0006, 1.00026, 1.0006, 1.00026, 1.03828, 1.00026, 0.99999, 1.00026, 1.0006, 0.99977, 1.00026, 0.99977, 1.00026, 0.99977, 1.00026, 0.9993, 0.9998, 1.00026, 1.00022, 1.00026, 1.00022, 1.00026, 1.00022, 1.00026, 1, 1.00016, 0.99977, 0.99959, 0.99977, 0.99959, 0.99977, 0.99959, 1.00001, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 1.00026, 0.99998, 1.00026, 0.8121, 1.00026, 0.99998, 0.99977, 1.00026, 0.99977, 1.00026, 0.99977, 1.00026, 0.99977, 1.00026, 0.99977, 1.00026, 0.99977, 1.00026, 1.00016, 1.00022, 1.00001, 0.99973, 1.00001, 1.00026, 1, 1.00026, 1, 1.00026, 1, 1.0006, 0.99973, 0.99977, 0.99973, 1, 0.99982, 1.00022, 1.00026, 1.00001, 0.99973, 1.00026, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 1.00034, 0.99977, 1, 0.99997, 1.00026, 1.00078, 1.00036, 0.99973, 1.00013, 1.0006, 0.99977, 0.99977, 0.99988, 0.85148, 1.00001, 1.00026, 0.99977, 1.00022, 1.0006, 0.99977, 1.00001, 0.99999, 0.99977, 1.00069, 1.00022, 0.99977, 1.00001, 0.99984, 1.00026, 1.00001, 1.00024, 1.00001, 0.9999, 1, 1.0006, 1.00001, 1.00041, 0.99962, 1.00026, 1.0006, 0.99995, 1.00041, 0.99942, 0.99973, 0.99927, 1.00082, 0.99902, 1.00026, 1.00087, 1.0006, 1.00069, 0.99973, 0.99867, 0.99973, 0.9993, 1.00026, 1.00049, 1.00056, 1, 0.99988, 0.99935, 0.99995, 0.99954, 1.00055, 0.99945, 1.00032, 1.0006, 0.99995, 1.00026, 0.99995, 1.00032, 1.00001, 1.00008, 0.99971, 1.00019, 0.9994, 1.00001, 1.0006, 1.00044, 0.99973, 1.00023, 1.00047, 1, 0.99942, 0.99561, 0.99989, 1.00035, 0.99977, 1.00035, 0.99977, 1.00019, 0.99944, 1.00001, 1.00021, 0.99926, 1.00035, 1.00035, 0.99942, 1.00048, 0.99999, 0.99977, 1.00022, 1.00035, 1.00001, 0.99977, 1.00026, 0.99989, 1.00057, 1.00001, 0.99936, 1.00052, 1.00012, 0.99996, 1.00043, 1, 1.00035, 0.9994, 0.99976, 1.00035, 0.99973, 1.00052, 1.00041, 1.00119, 1.00037, 0.99973, 1.00002, 0.99986, 1.00041, 1.00041, 0.99902, 0.9996, 1.00034, 0.99999, 1.00026, 0.99999, 1.00026, 0.99973, 1.00052, 0.99973, 1, 0.99973, 1.00041, 1.00075, 0.9994, 1.0003, 0.99999, 1, 1.00041, 0.99955, 1, 0.99915, 0.99973, 0.99973, 1.00026, 1.00119, 0.99955, 0.99973, 1.0006, 0.99911, 1.0006, 1.00026, 0.99972, 1.00026, 0.99902, 1.00041, 0.99973, 0.99999, 1, 1, 1.00038, 1.0005, 1.00016, 1.00022, 1.00016, 1.00022, 1.00016, 1.00022, 1.00001, 0.99973, 1, 1, 0.99973, 1, 1, 0.99955, 1.0006, 1.0006, 1.0006, 1.0006, 1, 1, 1, 0.99973, 0.99973, 0.99972, 1, 1, 1.00106, 0.99999, 0.99998, 0.99998, 0.99999, 0.99998, 1.66475, 1, 0.99973, 0.99973, 1.00023, 0.99973, 0.99971, 1.00047, 1.00023, 1, 0.99991, 0.99984, 1.00002, 1.00002, 1.00002, 1.00002, 1, 1, 1, 1, 1, 1, 1, 0.99972, 1, 1.20985, 1.39713, 1.00003, 1.00031, 1.00015, 1, 0.99561, 1.00027, 1.00031, 1.00031, 0.99915, 1.00031, 1.00031, 0.99999, 1.00003, 0.99999, 0.99999, 1.41144, 1.6, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.40579, 1.40579, 1.36625, 0.99999, 1, 0.99861, 0.99861, 1, 1.00026, 1.00026, 1.00026, 1.00026, 0.99972, 0.99999, 0.99999, 0.99999, 0.99999, 1.40483, 1, 0.99977, 1.00054, 1, 1, 0.99953, 0.99962, 1.00042, 0.9995, 1, 1, 1, 1, 1, 1, 1, 1, 0.99998, 0.99998, 0.99998, 0.99998, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1];
+const HelveticaBoldMetrics = {
+ lineHeight: 1.2,
+ lineGap: 0.2
+};
+const HelveticaBoldItalicFactors = [0.76116, 1, 1, 1.0006, 0.99998, 0.99974, 0.99973, 0.99973, 0.99982, 0.99977, 1.00087, 0.99998, 0.99998, 0.99959, 1.00003, 1.0006, 0.99998, 1.0006, 1.0006, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99998, 1, 1.00003, 1.00003, 1.00003, 1.00026, 0.9999, 0.99977, 0.99977, 0.99977, 0.99977, 1.00001, 1.00026, 1.00022, 0.99977, 1.0006, 0.99973, 0.99977, 1.00026, 0.99999, 0.99977, 1.00022, 1.00001, 1.00022, 0.99977, 1.00001, 1.00026, 0.99977, 1.00001, 1.00016, 1.00001, 1.00001, 1.00026, 0.99998, 1.0006, 0.99998, 1.00003, 0.99973, 0.99998, 0.99973, 1.00026, 0.99973, 1.00026, 0.99973, 0.99998, 1.00026, 1.00026, 1.0006, 1.0006, 0.99973, 1.0006, 0.99982, 1.00026, 1.00026, 1.00026, 1.00026, 0.99959, 0.99973, 0.99998, 1.00026, 0.99973, 1.00022, 0.99973, 0.99973, 1, 0.99959, 1.00077, 0.99959, 1.00003, 0.99998, 0.99973, 0.99973, 0.99973, 0.99973, 1.00077, 0.99973, 0.99998, 1.00025, 0.99968, 0.99973, 1.00003, 1.00025, 0.60299, 1.00024, 1.06409, 1, 1, 0.99998, 1, 0.99973, 1.0006, 0.99998, 1, 0.99936, 0.99973, 1.00002, 1.00002, 1.00002, 1.00026, 0.99977, 0.99977, 0.99977, 0.99977, 0.99977, 0.99977, 1, 0.99977, 1.00001, 1.00001, 1.00001, 1.00001, 1.0006, 1.0006, 1.0006, 1.0006, 0.99977, 0.99977, 1.00022, 1.00022, 1.00022, 1.00022, 1.00022, 1.00003, 1.00022, 0.99977, 0.99977, 0.99977, 0.99977, 1.00001, 1.00001, 1.00026, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99982, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 1.0006, 1.0006, 1.0006, 1.0006, 1.00026, 1.00026, 1.00026, 1.00026, 1.00026, 1.00026, 1.00026, 1.06409, 1.00026, 1.00026, 1.00026, 1.00026, 1.00026, 0.99973, 1.00026, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 1.0044, 0.99977, 1.00026, 1.00001, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 1.00022, 1.00026, 1.00022, 1.00026, 1.00022, 1.00026, 1.00022, 1.00026, 0.99977, 1.00026, 0.99977, 1.00026, 1.0006, 1.0006, 1.0006, 1.0006, 1.0006, 1.0006, 1.0006, 1.0006, 1.0006, 1.0006, 0.99971, 0.99973, 0.99973, 1.0006, 0.99977, 0.99973, 0.99973, 1.00026, 1.0006, 1.00026, 1.0006, 1.00026, 1.01011, 1.00026, 0.99999, 1.00026, 1.0006, 0.99977, 1.00026, 0.99977, 1.00026, 0.99977, 1.00026, 0.9993, 0.9998, 1.00026, 1.00022, 1.00026, 1.00022, 1.00026, 1.00022, 1.00026, 1, 1.00016, 0.99977, 0.99959, 0.99977, 0.99959, 0.99977, 0.99959, 1.00001, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 1.00026, 0.99998, 1.00026, 0.8121, 1.00026, 0.99998, 0.99977, 1.00026, 0.99977, 1.00026, 0.99977, 1.00026, 0.99977, 1.00026, 0.99977, 1.00026, 0.99977, 1.00026, 1.00016, 1.00022, 1.00001, 0.99973, 1.00001, 1.00026, 1, 1.00026, 1, 1.00026, 1, 1.0006, 0.99973, 0.99977, 0.99973, 1, 0.99982, 1.00022, 1.00026, 1.00001, 0.99973, 1.00026, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99977, 1, 1, 1.00026, 0.99969, 0.99972, 0.99981, 0.9998, 1.0006, 0.99977, 0.99977, 1.00022, 0.91155, 1.00001, 1.00026, 0.99977, 1.00022, 1.0006, 0.99977, 1.00001, 0.99999, 0.99977, 0.99966, 1.00022, 1.00032, 1.00001, 0.99944, 1.00026, 1.00001, 0.99968, 1.00001, 1.00047, 1, 1.0006, 1.00001, 0.99981, 1.00101, 1.00026, 1.0006, 0.99948, 0.99981, 1.00064, 0.99973, 0.99942, 1.00101, 1.00061, 1.00026, 1.00069, 1.0006, 1.00014, 0.99973, 1.01322, 0.99973, 1.00065, 1.00026, 1.00012, 0.99923, 1, 1.00064, 1.00076, 0.99948, 1.00055, 1.00063, 1.00007, 0.99943, 1.0006, 0.99948, 1.00026, 0.99948, 0.99943, 1.00001, 1.00001, 1.00029, 1.00038, 1.00035, 1.00001, 1.0006, 1.0006, 0.99973, 0.99978, 1.00001, 1.00057, 0.99989, 0.99967, 0.99964, 0.99967, 0.99977, 0.99999, 0.99977, 1.00038, 0.99977, 1.00001, 0.99973, 1.00066, 0.99967, 0.99967, 1.00041, 0.99998, 0.99999, 0.99977, 1.00022, 0.99967, 1.00001, 0.99977, 1.00026, 0.99964, 1.00031, 1.00001, 0.99999, 0.99999, 1, 1.00023, 1, 1, 0.99999, 1.00035, 1.00001, 0.99999, 0.99973, 0.99977, 0.99999, 1.00058, 0.99973, 0.99973, 0.99955, 0.9995, 1.00026, 1.00026, 1.00032, 0.99989, 1.00034, 0.99999, 1.00026, 1.00026, 1.00026, 0.99973, 0.45998, 0.99973, 1.00026, 0.99973, 1.00001, 0.99999, 0.99982, 0.99994, 0.99996, 1, 1.00042, 1.00044, 1.00029, 1.00023, 0.99973, 0.99973, 1.00026, 0.99949, 1.00002, 0.99973, 1.0006, 1.0006, 1.0006, 0.99975, 1.00026, 1.00026, 1.00032, 0.98685, 0.99973, 1.00026, 1, 1, 0.99966, 1.00044, 1.00016, 1.00022, 1.00016, 1.00022, 1.00016, 1.00022, 1.00001, 0.99973, 1, 1, 0.99973, 1, 1, 0.99955, 1.0006, 1.0006, 1.0006, 1.0006, 1, 1, 1, 0.99973, 0.99973, 0.99972, 1, 1, 1.00106, 0.99999, 0.99998, 0.99998, 0.99999, 0.99998, 1.66475, 1, 0.99973, 0.99973, 1, 0.99973, 0.99971, 0.99978, 1, 1, 0.99991, 0.99984, 1.00002, 1.00002, 1.00002, 1.00002, 1.00098, 1, 1, 1, 1.00049, 1, 1, 0.99972, 1, 1.20985, 1.39713, 1.00003, 1.00031, 1.00015, 1, 0.99561, 1.00027, 1.00031, 1.00031, 0.99915, 1.00031, 1.00031, 0.99999, 1.00003, 0.99999, 0.99999, 1.41144, 1.6, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.40579, 1.40579, 1.36625, 0.99999, 1, 0.99861, 0.99861, 1, 1.00026, 1.00026, 1.00026, 1.00026, 0.99972, 0.99999, 0.99999, 0.99999, 0.99999, 1.40483, 1, 0.99977, 1.00054, 1, 1, 0.99953, 0.99962, 1.00042, 0.9995, 1, 1, 1, 1, 1, 1, 1, 1, 0.99998, 0.99998, 0.99998, 0.99998, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1];
+const HelveticaBoldItalicMetrics = {
+ lineHeight: 1.35,
+ lineGap: 0.2
+};
+const HelveticaItalicFactors = [0.76116, 1, 1, 1.0006, 1.0006, 1.00006, 0.99973, 0.99973, 0.99982, 1.00001, 1.00043, 0.99998, 0.99998, 0.99959, 1.00003, 1.0006, 0.99998, 1.0006, 1.0006, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 1.0006, 1, 1.00003, 1.00003, 1.00003, 0.99973, 0.99987, 1.00001, 1.00001, 0.99977, 0.99977, 1.00001, 1.00026, 1.00022, 0.99977, 1.0006, 1, 1.00001, 0.99973, 0.99999, 0.99977, 1.00022, 1.00001, 1.00022, 0.99977, 1.00001, 1.00026, 0.99977, 1.00001, 1.00016, 1.00001, 1.00001, 1.00026, 1.0006, 1.0006, 1.0006, 0.99949, 0.99973, 0.99998, 0.99973, 0.99973, 1, 0.99973, 0.99973, 1.0006, 0.99973, 0.99973, 0.99924, 0.99924, 1, 0.99924, 0.99999, 0.99973, 0.99973, 0.99973, 0.99973, 0.99998, 1, 1.0006, 0.99973, 1, 0.99977, 1, 1, 1, 1.00005, 1.0009, 1.00005, 1.00003, 0.99998, 0.99973, 0.99973, 0.99973, 0.99973, 1.0009, 0.99973, 0.99998, 1.00025, 0.99968, 0.99973, 1.00003, 1.00025, 0.60299, 1.00024, 1.06409, 1, 1, 0.99998, 1, 0.9998, 1.0006, 0.99998, 1, 0.99936, 0.99973, 1.00002, 1.00002, 1.00002, 1.00026, 1.00001, 1.00001, 1.00001, 1.00001, 1.00001, 1.00001, 1, 0.99977, 1.00001, 1.00001, 1.00001, 1.00001, 1.0006, 1.0006, 1.0006, 1.0006, 0.99977, 0.99977, 1.00022, 1.00022, 1.00022, 1.00022, 1.00022, 1.00003, 1.00022, 0.99977, 0.99977, 0.99977, 0.99977, 1.00001, 1.00001, 1.00026, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99982, 1, 0.99973, 0.99973, 0.99973, 0.99973, 1.0006, 1.0006, 1.0006, 1.0006, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 1.06409, 1.00026, 0.99973, 0.99973, 0.99973, 0.99973, 1, 0.99973, 1, 1.00001, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 0.99977, 1, 0.99977, 1, 0.99977, 1, 0.99977, 1, 0.99977, 1.0288, 0.99977, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 1.00022, 0.99973, 1.00022, 0.99973, 1.00022, 0.99973, 1.00022, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 1.0006, 1.0006, 1.0006, 1.0006, 1.0006, 1.0006, 1.0006, 0.99924, 1.0006, 1.0006, 0.99946, 1.00034, 1, 0.99924, 1.00001, 1, 1, 0.99973, 0.99924, 0.99973, 0.99924, 0.99973, 1.06311, 0.99973, 1.00024, 0.99973, 0.99924, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 1.00041, 0.9998, 0.99973, 1.00022, 0.99973, 1.00022, 0.99973, 1.00022, 0.99973, 1, 1.00016, 0.99977, 0.99998, 0.99977, 0.99998, 0.99977, 0.99998, 1.00001, 1, 1.00001, 1, 1.00001, 1, 1.00001, 1, 1.00026, 1.0006, 1.00026, 0.89547, 1.00026, 1.0006, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 1.00016, 0.99977, 1.00001, 1, 1.00001, 1.00026, 1, 1.00026, 1, 1.00026, 1, 0.99924, 0.99973, 1.00001, 0.99973, 1, 0.99982, 1.00022, 1.00026, 1.00001, 1, 1.00026, 1.0006, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 1.00001, 1, 1.00054, 0.99977, 1.00084, 1.00007, 0.99973, 1.00013, 0.99924, 1.00001, 1.00001, 0.99945, 0.91221, 1.00001, 1.00026, 0.99977, 1.00022, 1.0006, 1.00001, 1.00001, 0.99999, 0.99977, 0.99933, 1.00022, 1.00054, 1.00001, 1.00065, 1.00026, 1.00001, 1.0001, 1.00001, 1.00052, 1, 1.0006, 1.00001, 0.99945, 0.99897, 0.99968, 0.99924, 1.00036, 0.99945, 0.99949, 1, 1.0006, 0.99897, 0.99918, 0.99968, 0.99911, 0.99924, 1, 0.99962, 1.01487, 1, 1.0005, 0.99973, 1.00012, 1.00043, 1, 0.99995, 0.99994, 1.00036, 0.99947, 1.00019, 1.00063, 1.00025, 0.99924, 1.00036, 0.99973, 1.00036, 1.00025, 1.00001, 1.00001, 1.00027, 1.0001, 1.00068, 1.00001, 1.0006, 1.0006, 1, 1.00008, 0.99957, 0.99972, 0.9994, 0.99954, 0.99975, 1.00051, 1.00001, 1.00019, 1.00001, 1.0001, 0.99986, 1.00001, 1.00001, 1.00038, 0.99954, 0.99954, 0.9994, 1.00066, 0.99999, 0.99977, 1.00022, 1.00054, 1.00001, 0.99977, 1.00026, 0.99975, 1.0001, 1.00001, 0.99993, 0.9995, 0.99955, 1.00016, 0.99978, 0.99974, 1.00019, 1.00022, 0.99955, 1.00053, 0.99973, 1.00089, 1.00005, 0.99967, 1.00048, 0.99973, 1.00002, 1.00034, 0.99973, 0.99973, 0.99964, 1.00006, 1.00066, 0.99947, 0.99973, 0.98894, 0.99973, 1, 0.44898, 1, 0.99946, 1, 1.00039, 1.00082, 0.99991, 0.99991, 0.99985, 1.00022, 1.00023, 1.00061, 1.00006, 0.99966, 0.99973, 0.99973, 0.99973, 1.00019, 1.0008, 1, 0.99924, 0.99924, 0.99924, 0.99983, 1.00044, 0.99973, 0.99964, 0.98332, 1, 0.99973, 1, 1, 0.99962, 0.99895, 1.00016, 0.99977, 1.00016, 0.99977, 1.00016, 0.99977, 1.00001, 1, 1, 1, 0.99973, 1, 1, 0.99955, 0.99924, 0.99924, 0.99924, 0.99924, 0.99998, 0.99998, 0.99998, 0.99973, 0.99973, 0.99972, 1, 1, 1.00267, 0.99999, 0.99998, 0.99998, 1, 0.99998, 1.66475, 1, 0.99973, 0.99973, 1.00023, 0.99973, 1.00423, 0.99925, 0.99999, 1, 0.99991, 0.99984, 1.00002, 1.00002, 1.00002, 1.00002, 1.00049, 1, 1.00245, 1, 1, 1, 1, 0.96329, 1, 1.20985, 1.39713, 1.00003, 0.8254, 1.00015, 1, 1.00035, 1.00027, 1.00031, 1.00031, 1.00003, 1.00031, 1.00031, 0.99999, 1.00003, 0.99999, 0.99999, 1.41144, 1.6, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.40579, 1.40579, 1.36625, 0.99999, 1, 0.99861, 0.99861, 1, 1.00026, 1.00026, 1.00026, 1.00026, 0.95317, 0.99999, 0.99999, 0.99999, 0.99999, 1.40483, 1, 0.99977, 1.00054, 1, 1, 0.99953, 0.99962, 1.00042, 0.9995, 1, 1, 1, 1, 1, 1, 1, 1, 0.99998, 0.99998, 0.99998, 0.99998, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1];
+const HelveticaItalicMetrics = {
+ lineHeight: 1.35,
+ lineGap: 0.2
+};
+const HelveticaRegularFactors = [0.76116, 1, 1, 1.0006, 1.0006, 1.00006, 0.99973, 0.99973, 0.99982, 1.00001, 1.00043, 0.99998, 0.99998, 0.99959, 1.00003, 1.0006, 0.99998, 1.0006, 1.0006, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 1.0006, 1, 1.00003, 1.00003, 1.00003, 0.99973, 0.99987, 1.00001, 1.00001, 0.99977, 0.99977, 1.00001, 1.00026, 1.00022, 0.99977, 1.0006, 1, 1.00001, 0.99973, 0.99999, 0.99977, 1.00022, 1.00001, 1.00022, 0.99977, 1.00001, 1.00026, 0.99977, 1.00001, 1.00016, 1.00001, 1.00001, 1.00026, 1.0006, 1.0006, 1.0006, 0.99949, 0.99973, 0.99998, 0.99973, 0.99973, 1, 0.99973, 0.99973, 1.0006, 0.99973, 0.99973, 0.99924, 0.99924, 1, 0.99924, 0.99999, 0.99973, 0.99973, 0.99973, 0.99973, 0.99998, 1, 1.0006, 0.99973, 1, 0.99977, 1, 1, 1, 1.00005, 1.0009, 1.00005, 1.00003, 0.99998, 0.99973, 0.99973, 0.99973, 0.99973, 1.0009, 0.99973, 0.99998, 1.00025, 0.99968, 0.99973, 1.00003, 1.00025, 0.60299, 1.00024, 1.06409, 1, 1, 0.99998, 1, 0.9998, 1.0006, 0.99998, 1, 0.99936, 0.99973, 1.00002, 1.00002, 1.00002, 1.00026, 1.00001, 1.00001, 1.00001, 1.00001, 1.00001, 1.00001, 1, 0.99977, 1.00001, 1.00001, 1.00001, 1.00001, 1.0006, 1.0006, 1.0006, 1.0006, 0.99977, 0.99977, 1.00022, 1.00022, 1.00022, 1.00022, 1.00022, 1.00003, 1.00022, 0.99977, 0.99977, 0.99977, 0.99977, 1.00001, 1.00001, 1.00026, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99982, 1, 0.99973, 0.99973, 0.99973, 0.99973, 1.0006, 1.0006, 1.0006, 1.0006, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 1.06409, 1.00026, 0.99973, 0.99973, 0.99973, 0.99973, 1, 0.99973, 1, 1.00001, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 0.99977, 1, 0.99977, 1, 0.99977, 1, 0.99977, 1, 0.99977, 1.04596, 0.99977, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 1.00022, 0.99973, 1.00022, 0.99973, 1.00022, 0.99973, 1.00022, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 1.0006, 1.0006, 1.0006, 1.0006, 1.0006, 1.0006, 1.0006, 0.99924, 1.0006, 1.0006, 1.00019, 1.00034, 1, 0.99924, 1.00001, 1, 1, 0.99973, 0.99924, 0.99973, 0.99924, 0.99973, 1.02572, 0.99973, 1.00005, 0.99973, 0.99924, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 0.99999, 0.9998, 0.99973, 1.00022, 0.99973, 1.00022, 0.99973, 1.00022, 0.99973, 1, 1.00016, 0.99977, 0.99998, 0.99977, 0.99998, 0.99977, 0.99998, 1.00001, 1, 1.00001, 1, 1.00001, 1, 1.00001, 1, 1.00026, 1.0006, 1.00026, 0.84533, 1.00026, 1.0006, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 1.00016, 0.99977, 1.00001, 1, 1.00001, 1.00026, 1, 1.00026, 1, 1.00026, 1, 0.99924, 0.99973, 1.00001, 0.99973, 1, 0.99982, 1.00022, 1.00026, 1.00001, 1, 1.00026, 1.0006, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99928, 1, 0.99977, 1.00013, 1.00055, 0.99947, 0.99945, 0.99941, 0.99924, 1.00001, 1.00001, 1.0004, 0.91621, 1.00001, 1.00026, 0.99977, 1.00022, 1.0006, 1.00001, 1.00005, 0.99999, 0.99977, 1.00015, 1.00022, 0.99977, 1.00001, 0.99973, 1.00026, 1.00001, 1.00019, 1.00001, 0.99946, 1, 1.0006, 1.00001, 0.99978, 1.00045, 0.99973, 0.99924, 1.00023, 0.99978, 0.99966, 1, 1.00065, 1.00045, 1.00019, 0.99973, 0.99973, 0.99924, 1, 1, 0.96499, 1, 1.00055, 0.99973, 1.00008, 1.00027, 1, 0.9997, 0.99995, 1.00023, 0.99933, 1.00019, 1.00015, 1.00031, 0.99924, 1.00023, 0.99973, 1.00023, 1.00031, 1.00001, 0.99928, 1.00029, 1.00092, 1.00035, 1.00001, 1.0006, 1.0006, 1, 0.99988, 0.99975, 1, 1.00082, 0.99561, 0.9996, 1.00035, 1.00001, 0.99962, 1.00001, 1.00092, 0.99964, 1.00001, 0.99963, 0.99999, 1.00035, 1.00035, 1.00082, 0.99962, 0.99999, 0.99977, 1.00022, 1.00035, 1.00001, 0.99977, 1.00026, 0.9996, 0.99967, 1.00001, 1.00034, 1.00074, 1.00054, 1.00053, 1.00063, 0.99971, 0.99962, 1.00035, 0.99975, 0.99977, 0.99973, 1.00043, 0.99953, 1.0007, 0.99915, 0.99973, 1.00008, 0.99892, 1.00073, 1.00073, 1.00114, 0.99915, 1.00073, 0.99955, 0.99973, 1.00092, 0.99973, 1, 0.99998, 1, 1.0003, 1, 1.00043, 1.00001, 0.99969, 1.0003, 1, 1.00035, 1.00001, 0.9995, 1, 1.00092, 0.99973, 0.99973, 0.99973, 1.0007, 0.9995, 1, 0.99924, 1.0006, 0.99924, 0.99972, 1.00062, 0.99973, 1.00114, 1.00073, 1, 0.99955, 1, 1, 1.00047, 0.99968, 1.00016, 0.99977, 1.00016, 0.99977, 1.00016, 0.99977, 1.00001, 1, 1, 1, 0.99973, 1, 1, 0.99955, 0.99924, 0.99924, 0.99924, 0.99924, 0.99998, 0.99998, 0.99998, 0.99973, 0.99973, 0.99972, 1, 1, 1.00267, 0.99999, 0.99998, 0.99998, 1, 0.99998, 1.66475, 1, 0.99973, 0.99973, 1.00023, 0.99973, 0.99971, 0.99925, 1.00023, 1, 0.99991, 0.99984, 1.00002, 1.00002, 1.00002, 1.00002, 1, 1, 1, 1, 1, 1, 1, 0.96329, 1, 1.20985, 1.39713, 1.00003, 0.8254, 1.00015, 1, 1.00035, 1.00027, 1.00031, 1.00031, 0.99915, 1.00031, 1.00031, 0.99999, 1.00003, 0.99999, 0.99999, 1.41144, 1.6, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.40579, 1.40579, 1.36625, 0.99999, 1, 0.99861, 0.99861, 1, 1.00026, 1.00026, 1.00026, 1.00026, 0.95317, 0.99999, 0.99999, 0.99999, 0.99999, 1.40483, 1, 0.99977, 1.00054, 1, 1, 0.99953, 0.99962, 1.00042, 0.9995, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1];
+const HelveticaRegularMetrics = {
+ lineHeight: 1.2,
+ lineGap: 0.2
+};
+
+;// CONCATENATED MODULE: ./src/core/liberationsans_widths.js
+const LiberationSansBoldWidths = [365, 0, 333, 278, 333, 474, 556, 556, 889, 722, 238, 333, 333, 389, 584, 278, 333, 278, 278, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 333, 333, 584, 584, 584, 611, 975, 722, 722, 722, 722, 667, 611, 778, 722, 278, 556, 722, 611, 833, 722, 778, 667, 778, 722, 667, 611, 722, 667, 944, 667, 667, 611, 333, 278, 333, 584, 556, 333, 556, 611, 556, 611, 556, 333, 611, 611, 278, 278, 556, 278, 889, 611, 611, 611, 611, 389, 556, 333, 611, 556, 778, 556, 556, 500, 389, 280, 389, 584, 333, 556, 556, 556, 556, 280, 556, 333, 737, 370, 556, 584, 737, 552, 400, 549, 333, 333, 333, 576, 556, 278, 333, 333, 365, 556, 834, 834, 834, 611, 722, 722, 722, 722, 722, 722, 1000, 722, 667, 667, 667, 667, 278, 278, 278, 278, 722, 722, 778, 778, 778, 778, 778, 584, 778, 722, 722, 722, 722, 667, 667, 611, 556, 556, 556, 556, 556, 556, 889, 556, 556, 556, 556, 556, 278, 278, 278, 278, 611, 611, 611, 611, 611, 611, 611, 549, 611, 611, 611, 611, 611, 556, 611, 556, 722, 556, 722, 556, 722, 556, 722, 556, 722, 556, 722, 556, 722, 556, 722, 719, 722, 611, 667, 556, 667, 556, 667, 556, 667, 556, 667, 556, 778, 611, 778, 611, 778, 611, 778, 611, 722, 611, 722, 611, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 785, 556, 556, 278, 722, 556, 556, 611, 278, 611, 278, 611, 385, 611, 479, 611, 278, 722, 611, 722, 611, 722, 611, 708, 723, 611, 778, 611, 778, 611, 778, 611, 1000, 944, 722, 389, 722, 389, 722, 389, 667, 556, 667, 556, 667, 556, 667, 556, 611, 333, 611, 479, 611, 333, 722, 611, 722, 611, 722, 611, 722, 611, 722, 611, 722, 611, 944, 778, 667, 556, 667, 611, 500, 611, 500, 611, 500, 278, 556, 722, 556, 1000, 889, 778, 611, 667, 556, 611, 333, 333, 333, 333, 333, 333, 333, 333, 333, 333, 333, 465, 722, 333, 853, 906, 474, 825, 927, 838, 278, 722, 722, 601, 719, 667, 611, 722, 778, 278, 722, 667, 833, 722, 644, 778, 722, 667, 600, 611, 667, 821, 667, 809, 802, 278, 667, 615, 451, 611, 278, 582, 615, 610, 556, 606, 475, 460, 611, 541, 278, 558, 556, 612, 556, 445, 611, 766, 619, 520, 684, 446, 582, 715, 576, 753, 845, 278, 582, 611, 582, 845, 667, 669, 885, 567, 711, 667, 278, 276, 556, 1094, 1062, 875, 610, 722, 622, 719, 722, 719, 722, 567, 712, 667, 904, 626, 719, 719, 610, 702, 833, 722, 778, 719, 667, 722, 611, 622, 854, 667, 730, 703, 1005, 1019, 870, 979, 719, 711, 1031, 719, 556, 618, 615, 417, 635, 556, 709, 497, 615, 615, 500, 635, 740, 604, 611, 604, 611, 556, 490, 556, 875, 556, 615, 581, 833, 844, 729, 854, 615, 552, 854, 583, 556, 556, 611, 417, 552, 556, 278, 281, 278, 969, 906, 611, 500, 615, 556, 604, 778, 611, 487, 447, 944, 778, 944, 778, 944, 778, 667, 556, 333, 333, 556, 1000, 1000, 552, 278, 278, 278, 278, 500, 500, 500, 556, 556, 350, 1000, 1000, 240, 479, 333, 333, 604, 333, 167, 396, 556, 556, 1094, 556, 885, 489, 1115, 1000, 768, 600, 834, 834, 834, 834, 1000, 500, 1000, 500, 1000, 500, 500, 494, 612, 823, 713, 584, 549, 713, 979, 722, 274, 549, 549, 583, 549, 549, 604, 584, 604, 604, 708, 625, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 729, 604, 604, 354, 354, 1000, 990, 990, 990, 990, 494, 604, 604, 604, 604, 354, 1021, 1052, 917, 750, 750, 531, 656, 594, 510, 500, 750, 750, 611, 611, 333, 333, 333, 333, 333, 333, 333, 333, 222, 222, 333, 333, 333, 333, 333, 333, 333, 333];
+const LiberationSansBoldMapping = [-1, -1, -1, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 402, 506, 507, 508, 509, 510, 511, 536, 537, 538, 539, 710, 711, 713, 728, 729, 730, 731, 732, 733, 900, 901, 902, 903, 904, 905, 906, 908, 910, 911, 912, 913, 914, 915, 916, 917, 918, 919, 920, 921, 922, 923, 924, 925, 926, 927, 928, 929, 931, 932, 933, 934, 935, 936, 937, 938, 939, 940, 941, 942, 943, 944, 945, 946, 947, 948, 949, 950, 951, 952, 953, 954, 955, 956, 957, 958, 959, 960, 961, 962, 963, 964, 965, 966, 967, 968, 969, 970, 971, 972, 973, 974, 1024, 1025, 1026, 1027, 1028, 1029, 1030, 1031, 1032, 1033, 1034, 1035, 1036, 1037, 1038, 1039, 1040, 1041, 1042, 1043, 1044, 1045, 1046, 1047, 1048, 1049, 1050, 1051, 1052, 1053, 1054, 1055, 1056, 1057, 1058, 1059, 1060, 1061, 1062, 1063, 1064, 1065, 1066, 1067, 1068, 1069, 1070, 1071, 1072, 1073, 1074, 1075, 1076, 1077, 1078, 1079, 1080, 1081, 1082, 1083, 1084, 1085, 1086, 1087, 1088, 1089, 1090, 1091, 1092, 1093, 1094, 1095, 1096, 1097, 1098, 1099, 1100, 1101, 1102, 1103, 1104, 1105, 1106, 1107, 1108, 1109, 1110, 1111, 1112, 1113, 1114, 1115, 1116, 1117, 1118, 1119, 1138, 1139, 1168, 1169, 7808, 7809, 7810, 7811, 7812, 7813, 7922, 7923, 8208, 8209, 8211, 8212, 8213, 8215, 8216, 8217, 8218, 8219, 8220, 8221, 8222, 8224, 8225, 8226, 8230, 8240, 8242, 8243, 8249, 8250, 8252, 8254, 8260, 8319, 8355, 8356, 8359, 8364, 8453, 8467, 8470, 8482, 8486, 8494, 8539, 8540, 8541, 8542, 8592, 8593, 8594, 8595, 8596, 8597, 8616, 8706, 8710, 8719, 8721, 8722, 8730, 8734, 8735, 8745, 8747, 8776, 8800, 8801, 8804, 8805, 8962, 8976, 8992, 8993, 9472, 9474, 9484, 9488, 9492, 9496, 9500, 9508, 9516, 9524, 9532, 9552, 9553, 9554, 9555, 9556, 9557, 9558, 9559, 9560, 9561, 9562, 9563, 9564, 9565, 9566, 9567, 9568, 9569, 9570, 9571, 9572, 9573, 9574, 9575, 9576, 9577, 9578, 9579, 9580, 9600, 9604, 9608, 9612, 9616, 9617, 9618, 9619, 9632, 9633, 9642, 9643, 9644, 9650, 9658, 9660, 9668, 9674, 9675, 9679, 9688, 9689, 9702, 9786, 9787, 9788, 9792, 9794, 9824, 9827, 9829, 9830, 9834, 9835, 9836, 61441, 61442, 61445, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1];
+const LiberationSansBoldItalicWidths = [365, 0, 333, 278, 333, 474, 556, 556, 889, 722, 238, 333, 333, 389, 584, 278, 333, 278, 278, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 333, 333, 584, 584, 584, 611, 975, 722, 722, 722, 722, 667, 611, 778, 722, 278, 556, 722, 611, 833, 722, 778, 667, 778, 722, 667, 611, 722, 667, 944, 667, 667, 611, 333, 278, 333, 584, 556, 333, 556, 611, 556, 611, 556, 333, 611, 611, 278, 278, 556, 278, 889, 611, 611, 611, 611, 389, 556, 333, 611, 556, 778, 556, 556, 500, 389, 280, 389, 584, 333, 556, 556, 556, 556, 280, 556, 333, 737, 370, 556, 584, 737, 552, 400, 549, 333, 333, 333, 576, 556, 278, 333, 333, 365, 556, 834, 834, 834, 611, 722, 722, 722, 722, 722, 722, 1000, 722, 667, 667, 667, 667, 278, 278, 278, 278, 722, 722, 778, 778, 778, 778, 778, 584, 778, 722, 722, 722, 722, 667, 667, 611, 556, 556, 556, 556, 556, 556, 889, 556, 556, 556, 556, 556, 278, 278, 278, 278, 611, 611, 611, 611, 611, 611, 611, 549, 611, 611, 611, 611, 611, 556, 611, 556, 722, 556, 722, 556, 722, 556, 722, 556, 722, 556, 722, 556, 722, 556, 722, 740, 722, 611, 667, 556, 667, 556, 667, 556, 667, 556, 667, 556, 778, 611, 778, 611, 778, 611, 778, 611, 722, 611, 722, 611, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 782, 556, 556, 278, 722, 556, 556, 611, 278, 611, 278, 611, 396, 611, 479, 611, 278, 722, 611, 722, 611, 722, 611, 708, 723, 611, 778, 611, 778, 611, 778, 611, 1000, 944, 722, 389, 722, 389, 722, 389, 667, 556, 667, 556, 667, 556, 667, 556, 611, 333, 611, 479, 611, 333, 722, 611, 722, 611, 722, 611, 722, 611, 722, 611, 722, 611, 944, 778, 667, 556, 667, 611, 500, 611, 500, 611, 500, 278, 556, 722, 556, 1000, 889, 778, 611, 667, 556, 611, 333, 333, 333, 333, 333, 333, 333, 333, 333, 333, 333, 333, 722, 333, 854, 906, 473, 844, 930, 847, 278, 722, 722, 610, 671, 667, 611, 722, 778, 278, 722, 667, 833, 722, 657, 778, 718, 667, 590, 611, 667, 822, 667, 829, 781, 278, 667, 620, 479, 611, 278, 591, 620, 621, 556, 610, 479, 492, 611, 558, 278, 566, 556, 603, 556, 450, 611, 712, 605, 532, 664, 409, 591, 704, 578, 773, 834, 278, 591, 611, 591, 834, 667, 667, 886, 614, 719, 667, 278, 278, 556, 1094, 1042, 854, 622, 719, 677, 719, 722, 708, 722, 614, 722, 667, 927, 643, 719, 719, 615, 687, 833, 722, 778, 719, 667, 722, 611, 677, 781, 667, 729, 708, 979, 989, 854, 1000, 708, 719, 1042, 729, 556, 619, 604, 534, 618, 556, 736, 510, 611, 611, 507, 622, 740, 604, 611, 611, 611, 556, 889, 556, 885, 556, 646, 583, 889, 935, 707, 854, 594, 552, 865, 589, 556, 556, 611, 469, 563, 556, 278, 278, 278, 969, 906, 611, 507, 619, 556, 611, 778, 611, 575, 467, 944, 778, 944, 778, 944, 778, 667, 556, 333, 333, 556, 1000, 1000, 552, 278, 278, 278, 278, 500, 500, 500, 556, 556, 350, 1000, 1000, 240, 479, 333, 333, 604, 333, 167, 396, 556, 556, 1104, 556, 885, 516, 1146, 1000, 768, 600, 834, 834, 834, 834, 999, 500, 1000, 500, 1000, 500, 500, 494, 612, 823, 713, 584, 549, 713, 979, 722, 274, 549, 549, 583, 549, 549, 604, 584, 604, 604, 708, 625, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 729, 604, 604, 354, 354, 1000, 990, 990, 990, 990, 494, 604, 604, 604, 604, 354, 1021, 1052, 917, 750, 750, 531, 656, 594, 510, 500, 750, 750, 611, 611, 333, 333, 333, 333, 333, 333, 333, 333, 222, 222, 333, 333, 333, 333, 333, 333, 333, 333];
+const LiberationSansBoldItalicMapping = [-1, -1, -1, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 402, 506, 507, 508, 509, 510, 511, 536, 537, 538, 539, 710, 711, 713, 728, 729, 730, 731, 732, 733, 900, 901, 902, 903, 904, 905, 906, 908, 910, 911, 912, 913, 914, 915, 916, 917, 918, 919, 920, 921, 922, 923, 924, 925, 926, 927, 928, 929, 931, 932, 933, 934, 935, 936, 937, 938, 939, 940, 941, 942, 943, 944, 945, 946, 947, 948, 949, 950, 951, 952, 953, 954, 955, 956, 957, 958, 959, 960, 961, 962, 963, 964, 965, 966, 967, 968, 969, 970, 971, 972, 973, 974, 1024, 1025, 1026, 1027, 1028, 1029, 1030, 1031, 1032, 1033, 1034, 1035, 1036, 1037, 1038, 1039, 1040, 1041, 1042, 1043, 1044, 1045, 1046, 1047, 1048, 1049, 1050, 1051, 1052, 1053, 1054, 1055, 1056, 1057, 1058, 1059, 1060, 1061, 1062, 1063, 1064, 1065, 1066, 1067, 1068, 1069, 1070, 1071, 1072, 1073, 1074, 1075, 1076, 1077, 1078, 1079, 1080, 1081, 1082, 1083, 1084, 1085, 1086, 1087, 1088, 1089, 1090, 1091, 1092, 1093, 1094, 1095, 1096, 1097, 1098, 1099, 1100, 1101, 1102, 1103, 1104, 1105, 1106, 1107, 1108, 1109, 1110, 1111, 1112, 1113, 1114, 1115, 1116, 1117, 1118, 1119, 1138, 1139, 1168, 1169, 7808, 7809, 7810, 7811, 7812, 7813, 7922, 7923, 8208, 8209, 8211, 8212, 8213, 8215, 8216, 8217, 8218, 8219, 8220, 8221, 8222, 8224, 8225, 8226, 8230, 8240, 8242, 8243, 8249, 8250, 8252, 8254, 8260, 8319, 8355, 8356, 8359, 8364, 8453, 8467, 8470, 8482, 8486, 8494, 8539, 8540, 8541, 8542, 8592, 8593, 8594, 8595, 8596, 8597, 8616, 8706, 8710, 8719, 8721, 8722, 8730, 8734, 8735, 8745, 8747, 8776, 8800, 8801, 8804, 8805, 8962, 8976, 8992, 8993, 9472, 9474, 9484, 9488, 9492, 9496, 9500, 9508, 9516, 9524, 9532, 9552, 9553, 9554, 9555, 9556, 9557, 9558, 9559, 9560, 9561, 9562, 9563, 9564, 9565, 9566, 9567, 9568, 9569, 9570, 9571, 9572, 9573, 9574, 9575, 9576, 9577, 9578, 9579, 9580, 9600, 9604, 9608, 9612, 9616, 9617, 9618, 9619, 9632, 9633, 9642, 9643, 9644, 9650, 9658, 9660, 9668, 9674, 9675, 9679, 9688, 9689, 9702, 9786, 9787, 9788, 9792, 9794, 9824, 9827, 9829, 9830, 9834, 9835, 9836, 61441, 61442, 61445, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1];
+const LiberationSansItalicWidths = [365, 0, 333, 278, 278, 355, 556, 556, 889, 667, 191, 333, 333, 389, 584, 278, 333, 278, 278, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 278, 278, 584, 584, 584, 556, 1015, 667, 667, 722, 722, 667, 611, 778, 722, 278, 500, 667, 556, 833, 722, 778, 667, 778, 722, 667, 611, 722, 667, 944, 667, 667, 611, 278, 278, 278, 469, 556, 333, 556, 556, 500, 556, 556, 278, 556, 556, 222, 222, 500, 222, 833, 556, 556, 556, 556, 333, 500, 278, 556, 500, 722, 500, 500, 500, 334, 260, 334, 584, 333, 556, 556, 556, 556, 260, 556, 333, 737, 370, 556, 584, 737, 552, 400, 549, 333, 333, 333, 576, 537, 278, 333, 333, 365, 556, 834, 834, 834, 611, 667, 667, 667, 667, 667, 667, 1000, 722, 667, 667, 667, 667, 278, 278, 278, 278, 722, 722, 778, 778, 778, 778, 778, 584, 778, 722, 722, 722, 722, 667, 667, 611, 556, 556, 556, 556, 556, 556, 889, 500, 556, 556, 556, 556, 278, 278, 278, 278, 556, 556, 556, 556, 556, 556, 556, 549, 611, 556, 556, 556, 556, 500, 556, 500, 667, 556, 667, 556, 667, 556, 722, 500, 722, 500, 722, 500, 722, 500, 722, 625, 722, 556, 667, 556, 667, 556, 667, 556, 667, 556, 667, 556, 778, 556, 778, 556, 778, 556, 778, 556, 722, 556, 722, 556, 278, 278, 278, 278, 278, 278, 278, 222, 278, 278, 733, 444, 500, 222, 667, 500, 500, 556, 222, 556, 222, 556, 281, 556, 400, 556, 222, 722, 556, 722, 556, 722, 556, 615, 723, 556, 778, 556, 778, 556, 778, 556, 1000, 944, 722, 333, 722, 333, 722, 333, 667, 500, 667, 500, 667, 500, 667, 500, 611, 278, 611, 354, 611, 278, 722, 556, 722, 556, 722, 556, 722, 556, 722, 556, 722, 556, 944, 722, 667, 500, 667, 611, 500, 611, 500, 611, 500, 222, 556, 667, 556, 1000, 889, 778, 611, 667, 500, 611, 278, 333, 333, 333, 333, 333, 333, 333, 333, 333, 333, 333, 667, 278, 789, 846, 389, 794, 865, 775, 222, 667, 667, 570, 671, 667, 611, 722, 778, 278, 667, 667, 833, 722, 648, 778, 725, 667, 600, 611, 667, 837, 667, 831, 761, 278, 667, 570, 439, 555, 222, 550, 570, 571, 500, 556, 439, 463, 555, 542, 222, 500, 492, 548, 500, 447, 556, 670, 573, 486, 603, 374, 550, 652, 546, 728, 779, 222, 550, 556, 550, 779, 667, 667, 843, 544, 708, 667, 278, 278, 500, 1066, 982, 844, 589, 715, 639, 724, 667, 651, 667, 544, 704, 667, 917, 614, 715, 715, 589, 686, 833, 722, 778, 725, 667, 722, 611, 639, 795, 667, 727, 673, 920, 923, 805, 886, 651, 694, 1022, 682, 556, 562, 522, 493, 553, 556, 688, 465, 556, 556, 472, 564, 686, 550, 556, 556, 556, 500, 833, 500, 835, 500, 572, 518, 830, 851, 621, 736, 526, 492, 752, 534, 556, 556, 556, 378, 496, 500, 222, 222, 222, 910, 828, 556, 472, 565, 500, 556, 778, 556, 492, 339, 944, 722, 944, 722, 944, 722, 667, 500, 333, 333, 556, 1000, 1000, 552, 222, 222, 222, 222, 333, 333, 333, 556, 556, 350, 1000, 1000, 188, 354, 333, 333, 500, 333, 167, 365, 556, 556, 1094, 556, 885, 323, 1083, 1000, 768, 600, 834, 834, 834, 834, 1000, 500, 998, 500, 1000, 500, 500, 494, 612, 823, 713, 584, 549, 713, 979, 719, 274, 549, 549, 584, 549, 549, 604, 584, 604, 604, 708, 625, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 729, 604, 604, 354, 354, 1000, 990, 990, 990, 990, 494, 604, 604, 604, 604, 354, 1021, 1052, 917, 750, 750, 531, 656, 594, 510, 500, 750, 750, 500, 500, 333, 333, 333, 333, 333, 333, 333, 333, 222, 222, 294, 294, 324, 324, 316, 328, 398, 285];
+const LiberationSansItalicMapping = [-1, -1, -1, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 402, 506, 507, 508, 509, 510, 511, 536, 537, 538, 539, 710, 711, 713, 728, 729, 730, 731, 732, 733, 900, 901, 902, 903, 904, 905, 906, 908, 910, 911, 912, 913, 914, 915, 916, 917, 918, 919, 920, 921, 922, 923, 924, 925, 926, 927, 928, 929, 931, 932, 933, 934, 935, 936, 937, 938, 939, 940, 941, 942, 943, 944, 945, 946, 947, 948, 949, 950, 951, 952, 953, 954, 955, 956, 957, 958, 959, 960, 961, 962, 963, 964, 965, 966, 967, 968, 969, 970, 971, 972, 973, 974, 1024, 1025, 1026, 1027, 1028, 1029, 1030, 1031, 1032, 1033, 1034, 1035, 1036, 1037, 1038, 1039, 1040, 1041, 1042, 1043, 1044, 1045, 1046, 1047, 1048, 1049, 1050, 1051, 1052, 1053, 1054, 1055, 1056, 1057, 1058, 1059, 1060, 1061, 1062, 1063, 1064, 1065, 1066, 1067, 1068, 1069, 1070, 1071, 1072, 1073, 1074, 1075, 1076, 1077, 1078, 1079, 1080, 1081, 1082, 1083, 1084, 1085, 1086, 1087, 1088, 1089, 1090, 1091, 1092, 1093, 1094, 1095, 1096, 1097, 1098, 1099, 1100, 1101, 1102, 1103, 1104, 1105, 1106, 1107, 1108, 1109, 1110, 1111, 1112, 1113, 1114, 1115, 1116, 1117, 1118, 1119, 1138, 1139, 1168, 1169, 7808, 7809, 7810, 7811, 7812, 7813, 7922, 7923, 8208, 8209, 8211, 8212, 8213, 8215, 8216, 8217, 8218, 8219, 8220, 8221, 8222, 8224, 8225, 8226, 8230, 8240, 8242, 8243, 8249, 8250, 8252, 8254, 8260, 8319, 8355, 8356, 8359, 8364, 8453, 8467, 8470, 8482, 8486, 8494, 8539, 8540, 8541, 8542, 8592, 8593, 8594, 8595, 8596, 8597, 8616, 8706, 8710, 8719, 8721, 8722, 8730, 8734, 8735, 8745, 8747, 8776, 8800, 8801, 8804, 8805, 8962, 8976, 8992, 8993, 9472, 9474, 9484, 9488, 9492, 9496, 9500, 9508, 9516, 9524, 9532, 9552, 9553, 9554, 9555, 9556, 9557, 9558, 9559, 9560, 9561, 9562, 9563, 9564, 9565, 9566, 9567, 9568, 9569, 9570, 9571, 9572, 9573, 9574, 9575, 9576, 9577, 9578, 9579, 9580, 9600, 9604, 9608, 9612, 9616, 9617, 9618, 9619, 9632, 9633, 9642, 9643, 9644, 9650, 9658, 9660, 9668, 9674, 9675, 9679, 9688, 9689, 9702, 9786, 9787, 9788, 9792, 9794, 9824, 9827, 9829, 9830, 9834, 9835, 9836, 61441, 61442, 61445, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1];
+const LiberationSansRegularWidths = [365, 0, 333, 278, 278, 355, 556, 556, 889, 667, 191, 333, 333, 389, 584, 278, 333, 278, 278, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 278, 278, 584, 584, 584, 556, 1015, 667, 667, 722, 722, 667, 611, 778, 722, 278, 500, 667, 556, 833, 722, 778, 667, 778, 722, 667, 611, 722, 667, 944, 667, 667, 611, 278, 278, 278, 469, 556, 333, 556, 556, 500, 556, 556, 278, 556, 556, 222, 222, 500, 222, 833, 556, 556, 556, 556, 333, 500, 278, 556, 500, 722, 500, 500, 500, 334, 260, 334, 584, 333, 556, 556, 556, 556, 260, 556, 333, 737, 370, 556, 584, 737, 552, 400, 549, 333, 333, 333, 576, 537, 278, 333, 333, 365, 556, 834, 834, 834, 611, 667, 667, 667, 667, 667, 667, 1000, 722, 667, 667, 667, 667, 278, 278, 278, 278, 722, 722, 778, 778, 778, 778, 778, 584, 778, 722, 722, 722, 722, 667, 667, 611, 556, 556, 556, 556, 556, 556, 889, 500, 556, 556, 556, 556, 278, 278, 278, 278, 556, 556, 556, 556, 556, 556, 556, 549, 611, 556, 556, 556, 556, 500, 556, 500, 667, 556, 667, 556, 667, 556, 722, 500, 722, 500, 722, 500, 722, 500, 722, 615, 722, 556, 667, 556, 667, 556, 667, 556, 667, 556, 667, 556, 778, 556, 778, 556, 778, 556, 778, 556, 722, 556, 722, 556, 278, 278, 278, 278, 278, 278, 278, 222, 278, 278, 735, 444, 500, 222, 667, 500, 500, 556, 222, 556, 222, 556, 292, 556, 334, 556, 222, 722, 556, 722, 556, 722, 556, 604, 723, 556, 778, 556, 778, 556, 778, 556, 1000, 944, 722, 333, 722, 333, 722, 333, 667, 500, 667, 500, 667, 500, 667, 500, 611, 278, 611, 375, 611, 278, 722, 556, 722, 556, 722, 556, 722, 556, 722, 556, 722, 556, 944, 722, 667, 500, 667, 611, 500, 611, 500, 611, 500, 222, 556, 667, 556, 1000, 889, 778, 611, 667, 500, 611, 278, 333, 333, 333, 333, 333, 333, 333, 333, 333, 333, 333, 667, 278, 784, 838, 384, 774, 855, 752, 222, 667, 667, 551, 668, 667, 611, 722, 778, 278, 667, 668, 833, 722, 650, 778, 722, 667, 618, 611, 667, 798, 667, 835, 748, 278, 667, 578, 446, 556, 222, 547, 578, 575, 500, 557, 446, 441, 556, 556, 222, 500, 500, 576, 500, 448, 556, 690, 569, 482, 617, 395, 547, 648, 525, 713, 781, 222, 547, 556, 547, 781, 667, 667, 865, 542, 719, 667, 278, 278, 500, 1057, 1010, 854, 583, 722, 635, 719, 667, 656, 667, 542, 677, 667, 923, 604, 719, 719, 583, 656, 833, 722, 778, 719, 667, 722, 611, 635, 760, 667, 740, 667, 917, 938, 792, 885, 656, 719, 1010, 722, 556, 573, 531, 365, 583, 556, 669, 458, 559, 559, 438, 583, 688, 552, 556, 542, 556, 500, 458, 500, 823, 500, 573, 521, 802, 823, 625, 719, 521, 510, 750, 542, 556, 556, 556, 365, 510, 500, 222, 278, 222, 906, 812, 556, 438, 559, 500, 552, 778, 556, 489, 411, 944, 722, 944, 722, 944, 722, 667, 500, 333, 333, 556, 1000, 1000, 552, 222, 222, 222, 222, 333, 333, 333, 556, 556, 350, 1000, 1000, 188, 354, 333, 333, 500, 333, 167, 365, 556, 556, 1094, 556, 885, 323, 1073, 1000, 768, 600, 834, 834, 834, 834, 1000, 500, 1000, 500, 1000, 500, 500, 494, 612, 823, 713, 584, 549, 713, 979, 719, 274, 549, 549, 583, 549, 549, 604, 584, 604, 604, 708, 625, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 729, 604, 604, 354, 354, 1000, 990, 990, 990, 990, 494, 604, 604, 604, 604, 354, 1021, 1052, 917, 750, 750, 531, 656, 594, 510, 500, 750, 750, 500, 500, 333, 333, 333, 333, 333, 333, 333, 333, 222, 222, 294, 294, 324, 324, 316, 328, 398, 285];
+const LiberationSansRegularMapping = [-1, -1, -1, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 402, 506, 507, 508, 509, 510, 511, 536, 537, 538, 539, 710, 711, 713, 728, 729, 730, 731, 732, 733, 900, 901, 902, 903, 904, 905, 906, 908, 910, 911, 912, 913, 914, 915, 916, 917, 918, 919, 920, 921, 922, 923, 924, 925, 926, 927, 928, 929, 931, 932, 933, 934, 935, 936, 937, 938, 939, 940, 941, 942, 943, 944, 945, 946, 947, 948, 949, 950, 951, 952, 953, 954, 955, 956, 957, 958, 959, 960, 961, 962, 963, 964, 965, 966, 967, 968, 969, 970, 971, 972, 973, 974, 1024, 1025, 1026, 1027, 1028, 1029, 1030, 1031, 1032, 1033, 1034, 1035, 1036, 1037, 1038, 1039, 1040, 1041, 1042, 1043, 1044, 1045, 1046, 1047, 1048, 1049, 1050, 1051, 1052, 1053, 1054, 1055, 1056, 1057, 1058, 1059, 1060, 1061, 1062, 1063, 1064, 1065, 1066, 1067, 1068, 1069, 1070, 1071, 1072, 1073, 1074, 1075, 1076, 1077, 1078, 1079, 1080, 1081, 1082, 1083, 1084, 1085, 1086, 1087, 1088, 1089, 1090, 1091, 1092, 1093, 1094, 1095, 1096, 1097, 1098, 1099, 1100, 1101, 1102, 1103, 1104, 1105, 1106, 1107, 1108, 1109, 1110, 1111, 1112, 1113, 1114, 1115, 1116, 1117, 1118, 1119, 1138, 1139, 1168, 1169, 7808, 7809, 7810, 7811, 7812, 7813, 7922, 7923, 8208, 8209, 8211, 8212, 8213, 8215, 8216, 8217, 8218, 8219, 8220, 8221, 8222, 8224, 8225, 8226, 8230, 8240, 8242, 8243, 8249, 8250, 8252, 8254, 8260, 8319, 8355, 8356, 8359, 8364, 8453, 8467, 8470, 8482, 8486, 8494, 8539, 8540, 8541, 8542, 8592, 8593, 8594, 8595, 8596, 8597, 8616, 8706, 8710, 8719, 8721, 8722, 8730, 8734, 8735, 8745, 8747, 8776, 8800, 8801, 8804, 8805, 8962, 8976, 8992, 8993, 9472, 9474, 9484, 9488, 9492, 9496, 9500, 9508, 9516, 9524, 9532, 9552, 9553, 9554, 9555, 9556, 9557, 9558, 9559, 9560, 9561, 9562, 9563, 9564, 9565, 9566, 9567, 9568, 9569, 9570, 9571, 9572, 9573, 9574, 9575, 9576, 9577, 9578, 9579, 9580, 9600, 9604, 9608, 9612, 9616, 9617, 9618, 9619, 9632, 9633, 9642, 9643, 9644, 9650, 9658, 9660, 9668, 9674, 9675, 9679, 9688, 9689, 9702, 9786, 9787, 9788, 9792, 9794, 9824, 9827, 9829, 9830, 9834, 9835, 9836, 61441, 61442, 61445, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1];
+
+;// CONCATENATED MODULE: ./src/core/myriadpro_factors.js
+const MyriadProBoldFactors = [1.36898, 1, 1, 0.72706, 0.80479, 0.83734, 0.98894, 0.99793, 0.9897, 0.93884, 0.86209, 0.94292, 0.94292, 1.16661, 1.02058, 0.93582, 0.96694, 0.93582, 1.19137, 0.99793, 0.99793, 0.99793, 0.99793, 0.99793, 0.99793, 0.99793, 0.99793, 0.99793, 0.99793, 0.78076, 0.78076, 1.02058, 1.02058, 1.02058, 0.72851, 0.78966, 0.90838, 0.83637, 0.82391, 0.96376, 0.80061, 0.86275, 0.8768, 0.95407, 1.0258, 0.73901, 0.85022, 0.83655, 1.0156, 0.95546, 0.92179, 0.87107, 0.92179, 0.82114, 0.8096, 0.89713, 0.94438, 0.95353, 0.94083, 0.91905, 0.90406, 0.9446, 0.94292, 1.18777, 0.94292, 1.02058, 0.89903, 0.90088, 0.94938, 0.97898, 0.81093, 0.97571, 0.94938, 1.024, 0.9577, 0.95933, 0.98621, 1.0474, 0.97455, 0.98981, 0.9672, 0.95933, 0.9446, 0.97898, 0.97407, 0.97646, 0.78036, 1.10208, 0.95442, 0.95298, 0.97579, 0.9332, 0.94039, 0.938, 0.80687, 1.01149, 0.80687, 1.02058, 0.80479, 0.99793, 0.99793, 0.99793, 0.99793, 1.01149, 1.00872, 0.90088, 0.91882, 1.0213, 0.8361, 1.02058, 0.62295, 0.54324, 0.89022, 1.08595, 1, 1, 0.90088, 1, 0.97455, 0.93582, 0.90088, 1, 1.05686, 0.8361, 0.99642, 0.99642, 0.99642, 0.72851, 0.90838, 0.90838, 0.90838, 0.90838, 0.90838, 0.90838, 0.868, 0.82391, 0.80061, 0.80061, 0.80061, 0.80061, 1.0258, 1.0258, 1.0258, 1.0258, 0.97484, 0.95546, 0.92179, 0.92179, 0.92179, 0.92179, 0.92179, 1.02058, 0.92179, 0.94438, 0.94438, 0.94438, 0.94438, 0.90406, 0.86958, 0.98225, 0.94938, 0.94938, 0.94938, 0.94938, 0.94938, 0.94938, 0.9031, 0.81093, 0.94938, 0.94938, 0.94938, 0.94938, 0.98621, 0.98621, 0.98621, 0.98621, 0.93969, 0.95933, 0.9446, 0.9446, 0.9446, 0.9446, 0.9446, 1.08595, 0.9446, 0.95442, 0.95442, 0.95442, 0.95442, 0.94039, 0.97898, 0.94039, 0.90838, 0.94938, 0.90838, 0.94938, 0.90838, 0.94938, 0.82391, 0.81093, 0.82391, 0.81093, 0.82391, 0.81093, 0.82391, 0.81093, 0.96376, 0.84313, 0.97484, 0.97571, 0.80061, 0.94938, 0.80061, 0.94938, 0.80061, 0.94938, 0.80061, 0.94938, 0.80061, 0.94938, 0.8768, 0.9577, 0.8768, 0.9577, 0.8768, 0.9577, 1, 1, 0.95407, 0.95933, 0.97069, 0.95933, 1.0258, 0.98621, 1.0258, 0.98621, 1.0258, 0.98621, 1.0258, 0.98621, 1.0258, 0.98621, 0.887, 1.01591, 0.73901, 1.0474, 1, 1, 0.97455, 0.83655, 0.98981, 1, 1, 0.83655, 0.73977, 0.83655, 0.73903, 0.84638, 1.033, 0.95546, 0.95933, 1, 1, 0.95546, 0.95933, 0.8271, 0.95417, 0.95933, 0.92179, 0.9446, 0.92179, 0.9446, 0.92179, 0.9446, 0.936, 0.91964, 0.82114, 0.97646, 1, 1, 0.82114, 0.97646, 0.8096, 0.78036, 0.8096, 0.78036, 1, 1, 0.8096, 0.78036, 1, 1, 0.89713, 0.77452, 0.89713, 1.10208, 0.94438, 0.95442, 0.94438, 0.95442, 0.94438, 0.95442, 0.94438, 0.95442, 0.94438, 0.95442, 0.94438, 0.95442, 0.94083, 0.97579, 0.90406, 0.94039, 0.90406, 0.9446, 0.938, 0.9446, 0.938, 0.9446, 0.938, 1, 0.99793, 0.90838, 0.94938, 0.868, 0.9031, 0.92179, 0.9446, 1, 1, 0.89713, 1.10208, 0.90088, 0.90088, 0.90088, 0.90088, 0.90088, 0.90088, 0.90088, 0.90088, 0.90088, 0.90989, 0.9358, 0.91945, 0.83181, 0.75261, 0.87992, 0.82976, 0.96034, 0.83689, 0.97268, 1.0078, 0.90838, 0.83637, 0.8019, 0.90157, 0.80061, 0.9446, 0.95407, 0.92436, 1.0258, 0.85022, 0.97153, 1.0156, 0.95546, 0.89192, 0.92179, 0.92361, 0.87107, 0.96318, 0.89713, 0.93704, 0.95638, 0.91905, 0.91709, 0.92796, 1.0258, 0.93704, 0.94836, 1.0373, 0.95933, 1.0078, 0.95871, 0.94836, 0.96174, 0.92601, 0.9498, 0.98607, 0.95776, 0.95933, 1.05453, 1.0078, 0.98275, 0.9314, 0.95617, 0.91701, 1.05993, 0.9446, 0.78367, 0.9553, 1, 0.86832, 1.0128, 0.95871, 0.99394, 0.87548, 0.96361, 0.86774, 1.0078, 0.95871, 0.9446, 0.95871, 0.86774, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.94083, 0.97579, 0.94083, 0.97579, 0.94083, 0.97579, 0.90406, 0.94039, 0.96694, 1, 0.89903, 1, 1, 1, 0.93582, 0.93582, 0.93582, 1, 0.908, 0.908, 0.918, 0.94219, 0.94219, 0.96544, 1, 1.285, 1, 1, 0.81079, 0.81079, 1, 1, 0.74854, 1, 1, 1, 1, 0.99793, 1, 1, 1, 0.65, 1, 1.36145, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.17173, 1, 0.80535, 0.76169, 1.02058, 1.0732, 1.05486, 1, 1, 1.30692, 1.08595, 1.08595, 1, 1.08595, 1.08595, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.16161, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1];
+const MyriadProBoldMetrics = {
+ lineHeight: 1.2,
+ lineGap: 0.2
+};
+const MyriadProBoldItalicFactors = [1.36898, 1, 1, 0.66227, 0.80779, 0.81625, 0.97276, 0.97276, 0.97733, 0.92222, 0.83266, 0.94292, 0.94292, 1.16148, 1.02058, 0.93582, 0.96694, 0.93582, 1.17337, 0.97276, 0.97276, 0.97276, 0.97276, 0.97276, 0.97276, 0.97276, 0.97276, 0.97276, 0.97276, 0.78076, 0.78076, 1.02058, 1.02058, 1.02058, 0.71541, 0.76813, 0.85576, 0.80591, 0.80729, 0.94299, 0.77512, 0.83655, 0.86523, 0.92222, 0.98621, 0.71743, 0.81698, 0.79726, 0.98558, 0.92222, 0.90637, 0.83809, 0.90637, 0.80729, 0.76463, 0.86275, 0.90699, 0.91605, 0.9154, 0.85308, 0.85458, 0.90531, 0.94292, 1.21296, 0.94292, 1.02058, 0.89903, 1.18616, 0.99613, 0.91677, 0.78216, 0.91677, 0.90083, 0.98796, 0.9135, 0.92168, 0.95381, 0.98981, 0.95298, 0.95381, 0.93459, 0.92168, 0.91513, 0.92004, 0.91677, 0.95077, 0.748, 1.04502, 0.91677, 0.92061, 0.94236, 0.89544, 0.89364, 0.9, 0.80687, 0.8578, 0.80687, 1.02058, 0.80779, 0.97276, 0.97276, 0.97276, 0.97276, 0.8578, 0.99973, 1.18616, 0.91339, 1.08074, 0.82891, 1.02058, 0.55509, 0.71526, 0.89022, 1.08595, 1, 1, 1.18616, 1, 0.96736, 0.93582, 1.18616, 1, 1.04864, 0.82711, 0.99043, 0.99043, 0.99043, 0.71541, 0.85576, 0.85576, 0.85576, 0.85576, 0.85576, 0.85576, 0.845, 0.80729, 0.77512, 0.77512, 0.77512, 0.77512, 0.98621, 0.98621, 0.98621, 0.98621, 0.95961, 0.92222, 0.90637, 0.90637, 0.90637, 0.90637, 0.90637, 1.02058, 0.90251, 0.90699, 0.90699, 0.90699, 0.90699, 0.85458, 0.83659, 0.94951, 0.99613, 0.99613, 0.99613, 0.99613, 0.99613, 0.99613, 0.85811, 0.78216, 0.90083, 0.90083, 0.90083, 0.90083, 0.95381, 0.95381, 0.95381, 0.95381, 0.9135, 0.92168, 0.91513, 0.91513, 0.91513, 0.91513, 0.91513, 1.08595, 0.91677, 0.91677, 0.91677, 0.91677, 0.91677, 0.89364, 0.92332, 0.89364, 0.85576, 0.99613, 0.85576, 0.99613, 0.85576, 0.99613, 0.80729, 0.78216, 0.80729, 0.78216, 0.80729, 0.78216, 0.80729, 0.78216, 0.94299, 0.76783, 0.95961, 0.91677, 0.77512, 0.90083, 0.77512, 0.90083, 0.77512, 0.90083, 0.77512, 0.90083, 0.77512, 0.90083, 0.86523, 0.9135, 0.86523, 0.9135, 0.86523, 0.9135, 1, 1, 0.92222, 0.92168, 0.92222, 0.92168, 0.98621, 0.95381, 0.98621, 0.95381, 0.98621, 0.95381, 0.98621, 0.95381, 0.98621, 0.95381, 0.86036, 0.97096, 0.71743, 0.98981, 1, 1, 0.95298, 0.79726, 0.95381, 1, 1, 0.79726, 0.6894, 0.79726, 0.74321, 0.81691, 1.0006, 0.92222, 0.92168, 1, 1, 0.92222, 0.92168, 0.79464, 0.92098, 0.92168, 0.90637, 0.91513, 0.90637, 0.91513, 0.90637, 0.91513, 0.909, 0.87514, 0.80729, 0.95077, 1, 1, 0.80729, 0.95077, 0.76463, 0.748, 0.76463, 0.748, 1, 1, 0.76463, 0.748, 1, 1, 0.86275, 0.72651, 0.86275, 1.04502, 0.90699, 0.91677, 0.90699, 0.91677, 0.90699, 0.91677, 0.90699, 0.91677, 0.90699, 0.91677, 0.90699, 0.91677, 0.9154, 0.94236, 0.85458, 0.89364, 0.85458, 0.90531, 0.9, 0.90531, 0.9, 0.90531, 0.9, 1, 0.97276, 0.85576, 0.99613, 0.845, 0.85811, 0.90251, 0.91677, 1, 1, 0.86275, 1.04502, 1.18616, 1.18616, 1.18616, 1.18616, 1.18616, 1.18616, 1.18616, 1.18616, 1.18616, 1.00899, 1.30628, 0.85576, 0.80178, 0.66862, 0.7927, 0.69323, 0.88127, 0.72459, 0.89711, 0.95381, 0.85576, 0.80591, 0.7805, 0.94729, 0.77512, 0.90531, 0.92222, 0.90637, 0.98621, 0.81698, 0.92655, 0.98558, 0.92222, 0.85359, 0.90637, 0.90976, 0.83809, 0.94523, 0.86275, 0.83509, 0.93157, 0.85308, 0.83392, 0.92346, 0.98621, 0.83509, 0.92886, 0.91324, 0.92168, 0.95381, 0.90646, 0.92886, 0.90557, 0.86847, 0.90276, 0.91324, 0.86842, 0.92168, 0.99531, 0.95381, 0.9224, 0.85408, 0.92699, 0.86847, 1.0051, 0.91513, 0.80487, 0.93481, 1, 0.88159, 1.05214, 0.90646, 0.97355, 0.81539, 0.89398, 0.85923, 0.95381, 0.90646, 0.91513, 0.90646, 0.85923, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.9154, 0.94236, 0.9154, 0.94236, 0.9154, 0.94236, 0.85458, 0.89364, 0.96694, 1, 0.89903, 1, 1, 1, 0.91782, 0.91782, 0.91782, 1, 0.896, 0.896, 0.896, 0.9332, 0.9332, 0.95973, 1, 1.26, 1, 1, 0.80479, 0.80178, 1, 1, 0.85633, 1, 1, 1, 1, 0.97276, 1, 1, 1, 0.698, 1, 1.36145, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.14542, 1, 0.79199, 0.78694, 1.02058, 1.03493, 1.05486, 1, 1, 1.23026, 1.08595, 1.08595, 1, 1.08595, 1.08595, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.20006, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1];
+const MyriadProBoldItalicMetrics = {
+ lineHeight: 1.2,
+ lineGap: 0.2
+};
+const MyriadProItalicFactors = [1.36898, 1, 1, 0.65507, 0.84943, 0.85639, 0.88465, 0.88465, 0.86936, 0.88307, 0.86948, 0.85283, 0.85283, 1.06383, 1.02058, 0.75945, 0.9219, 0.75945, 1.17337, 0.88465, 0.88465, 0.88465, 0.88465, 0.88465, 0.88465, 0.88465, 0.88465, 0.88465, 0.88465, 0.75945, 0.75945, 1.02058, 1.02058, 1.02058, 0.69046, 0.70926, 0.85158, 0.77812, 0.76852, 0.89591, 0.70466, 0.76125, 0.80094, 0.86822, 0.83864, 0.728, 0.77212, 0.79475, 0.93637, 0.87514, 0.8588, 0.76013, 0.8588, 0.72421, 0.69866, 0.77598, 0.85991, 0.80811, 0.87832, 0.78112, 0.77512, 0.8562, 1.0222, 1.18417, 1.0222, 1.27014, 0.89903, 1.15012, 0.93859, 0.94399, 0.846, 0.94399, 0.81453, 1.0186, 0.94219, 0.96017, 1.03075, 1.02175, 0.912, 1.03075, 0.96998, 0.96017, 0.93859, 0.94399, 0.94399, 0.95493, 0.746, 1.12658, 0.94578, 0.91, 0.979, 0.882, 0.882, 0.83, 0.85034, 0.83537, 0.85034, 1.02058, 0.70869, 0.88465, 0.88465, 0.88465, 0.88465, 0.83537, 0.90083, 1.15012, 0.9161, 0.94565, 0.73541, 1.02058, 0.53609, 0.69353, 0.79519, 1.08595, 1, 1, 1.15012, 1, 0.91974, 0.75945, 1.15012, 1, 0.9446, 0.73361, 0.9005, 0.9005, 0.9005, 0.62864, 0.85158, 0.85158, 0.85158, 0.85158, 0.85158, 0.85158, 0.773, 0.76852, 0.70466, 0.70466, 0.70466, 0.70466, 0.83864, 0.83864, 0.83864, 0.83864, 0.90561, 0.87514, 0.8588, 0.8588, 0.8588, 0.8588, 0.8588, 1.02058, 0.85751, 0.85991, 0.85991, 0.85991, 0.85991, 0.77512, 0.76013, 0.88075, 0.93859, 0.93859, 0.93859, 0.93859, 0.93859, 0.93859, 0.8075, 0.846, 0.81453, 0.81453, 0.81453, 0.81453, 0.82424, 0.82424, 0.82424, 0.82424, 0.9278, 0.96017, 0.93859, 0.93859, 0.93859, 0.93859, 0.93859, 1.08595, 0.8562, 0.94578, 0.94578, 0.94578, 0.94578, 0.882, 0.94578, 0.882, 0.85158, 0.93859, 0.85158, 0.93859, 0.85158, 0.93859, 0.76852, 0.846, 0.76852, 0.846, 0.76852, 0.846, 0.76852, 0.846, 0.89591, 0.8544, 0.90561, 0.94399, 0.70466, 0.81453, 0.70466, 0.81453, 0.70466, 0.81453, 0.70466, 0.81453, 0.70466, 0.81453, 0.80094, 0.94219, 0.80094, 0.94219, 0.80094, 0.94219, 1, 1, 0.86822, 0.96017, 0.86822, 0.96017, 0.83864, 0.82424, 0.83864, 0.82424, 0.83864, 0.82424, 0.83864, 1.03075, 0.83864, 0.82424, 0.81402, 1.02738, 0.728, 1.02175, 1, 1, 0.912, 0.79475, 1.03075, 1, 1, 0.79475, 0.83911, 0.79475, 0.66266, 0.80553, 1.06676, 0.87514, 0.96017, 1, 1, 0.87514, 0.96017, 0.86865, 0.87396, 0.96017, 0.8588, 0.93859, 0.8588, 0.93859, 0.8588, 0.93859, 0.867, 0.84759, 0.72421, 0.95493, 1, 1, 0.72421, 0.95493, 0.69866, 0.746, 0.69866, 0.746, 1, 1, 0.69866, 0.746, 1, 1, 0.77598, 0.88417, 0.77598, 1.12658, 0.85991, 0.94578, 0.85991, 0.94578, 0.85991, 0.94578, 0.85991, 0.94578, 0.85991, 0.94578, 0.85991, 0.94578, 0.87832, 0.979, 0.77512, 0.882, 0.77512, 0.8562, 0.83, 0.8562, 0.83, 0.8562, 0.83, 1, 0.88465, 0.85158, 0.93859, 0.773, 0.8075, 0.85751, 0.8562, 1, 1, 0.77598, 1.12658, 1.15012, 1.15012, 1.15012, 1.15012, 1.15012, 1.15313, 1.15012, 1.15012, 1.15012, 1.08106, 1.03901, 0.85158, 0.77025, 0.62264, 0.7646, 0.65351, 0.86026, 0.69461, 0.89947, 1.03075, 0.85158, 0.77812, 0.76449, 0.88836, 0.70466, 0.8562, 0.86822, 0.8588, 0.83864, 0.77212, 0.85308, 0.93637, 0.87514, 0.82352, 0.8588, 0.85701, 0.76013, 0.89058, 0.77598, 0.8156, 0.82565, 0.78112, 0.77899, 0.89386, 0.83864, 0.8156, 0.9486, 0.92388, 0.96186, 1.03075, 0.91123, 0.9486, 0.93298, 0.878, 0.93942, 0.92388, 0.84596, 0.96186, 0.95119, 1.03075, 0.922, 0.88787, 0.95829, 0.88, 0.93559, 0.93859, 0.78815, 0.93758, 1, 0.89217, 1.03737, 0.91123, 0.93969, 0.77487, 0.85769, 0.86799, 1.03075, 0.91123, 0.93859, 0.91123, 0.86799, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.87832, 0.979, 0.87832, 0.979, 0.87832, 0.979, 0.77512, 0.882, 0.9219, 1, 0.89903, 1, 1, 1, 0.87321, 0.87321, 0.87321, 1, 1.027, 1.027, 1.027, 0.86847, 0.86847, 0.79121, 1, 1.124, 1, 1, 0.73572, 0.73572, 1, 1, 0.85034, 1, 1, 1, 1, 0.88465, 1, 1, 1, 0.669, 1, 1.36145, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.04828, 1, 0.74948, 0.75187, 1.02058, 0.98391, 1.02119, 1, 1, 1.06233, 1.08595, 1.08595, 1, 1.08595, 1.08595, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.05233, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1];
+const MyriadProItalicMetrics = {
+ lineHeight: 1.2,
+ lineGap: 0.2
+};
+const MyriadProRegularFactors = [1.36898, 1, 1, 0.76305, 0.82784, 0.94935, 0.89364, 0.92241, 0.89073, 0.90706, 0.98472, 0.85283, 0.85283, 1.0664, 1.02058, 0.74505, 0.9219, 0.74505, 1.23456, 0.92241, 0.92241, 0.92241, 0.92241, 0.92241, 0.92241, 0.92241, 0.92241, 0.92241, 0.92241, 0.74505, 0.74505, 1.02058, 1.02058, 1.02058, 0.73002, 0.72601, 0.91755, 0.8126, 0.80314, 0.92222, 0.73764, 0.79726, 0.83051, 0.90284, 0.86023, 0.74, 0.8126, 0.84869, 0.96518, 0.91115, 0.8858, 0.79761, 0.8858, 0.74498, 0.73914, 0.81363, 0.89591, 0.83659, 0.89633, 0.85608, 0.8111, 0.90531, 1.0222, 1.22736, 1.0222, 1.27014, 0.89903, 0.90088, 0.86667, 1.0231, 0.896, 1.01411, 0.90083, 1.05099, 1.00512, 0.99793, 1.05326, 1.09377, 0.938, 1.06226, 1.00119, 0.99793, 0.98714, 1.0231, 1.01231, 0.98196, 0.792, 1.19137, 0.99074, 0.962, 1.01915, 0.926, 0.942, 0.856, 0.85034, 0.92006, 0.85034, 1.02058, 0.69067, 0.92241, 0.92241, 0.92241, 0.92241, 0.92006, 0.9332, 0.90088, 0.91882, 0.93484, 0.75339, 1.02058, 0.56866, 0.54324, 0.79519, 1.08595, 1, 1, 0.90088, 1, 0.95325, 0.74505, 0.90088, 1, 0.97198, 0.75339, 0.91009, 0.91009, 0.91009, 0.66466, 0.91755, 0.91755, 0.91755, 0.91755, 0.91755, 0.91755, 0.788, 0.80314, 0.73764, 0.73764, 0.73764, 0.73764, 0.86023, 0.86023, 0.86023, 0.86023, 0.92915, 0.91115, 0.8858, 0.8858, 0.8858, 0.8858, 0.8858, 1.02058, 0.8858, 0.89591, 0.89591, 0.89591, 0.89591, 0.8111, 0.79611, 0.89713, 0.86667, 0.86667, 0.86667, 0.86667, 0.86667, 0.86667, 0.86936, 0.896, 0.90083, 0.90083, 0.90083, 0.90083, 0.84224, 0.84224, 0.84224, 0.84224, 0.97276, 0.99793, 0.98714, 0.98714, 0.98714, 0.98714, 0.98714, 1.08595, 0.89876, 0.99074, 0.99074, 0.99074, 0.99074, 0.942, 1.0231, 0.942, 0.91755, 0.86667, 0.91755, 0.86667, 0.91755, 0.86667, 0.80314, 0.896, 0.80314, 0.896, 0.80314, 0.896, 0.80314, 0.896, 0.92222, 0.93372, 0.92915, 1.01411, 0.73764, 0.90083, 0.73764, 0.90083, 0.73764, 0.90083, 0.73764, 0.90083, 0.73764, 0.90083, 0.83051, 1.00512, 0.83051, 1.00512, 0.83051, 1.00512, 1, 1, 0.90284, 0.99793, 0.90976, 0.99793, 0.86023, 0.84224, 0.86023, 0.84224, 0.86023, 0.84224, 0.86023, 1.05326, 0.86023, 0.84224, 0.82873, 1.07469, 0.74, 1.09377, 1, 1, 0.938, 0.84869, 1.06226, 1, 1, 0.84869, 0.83704, 0.84869, 0.81441, 0.85588, 1.08927, 0.91115, 0.99793, 1, 1, 0.91115, 0.99793, 0.91887, 0.90991, 0.99793, 0.8858, 0.98714, 0.8858, 0.98714, 0.8858, 0.98714, 0.894, 0.91434, 0.74498, 0.98196, 1, 1, 0.74498, 0.98196, 0.73914, 0.792, 0.73914, 0.792, 1, 1, 0.73914, 0.792, 1, 1, 0.81363, 0.904, 0.81363, 1.19137, 0.89591, 0.99074, 0.89591, 0.99074, 0.89591, 0.99074, 0.89591, 0.99074, 0.89591, 0.99074, 0.89591, 0.99074, 0.89633, 1.01915, 0.8111, 0.942, 0.8111, 0.90531, 0.856, 0.90531, 0.856, 0.90531, 0.856, 1, 0.92241, 0.91755, 0.86667, 0.788, 0.86936, 0.8858, 0.89876, 1, 1, 0.81363, 1.19137, 0.90088, 0.90088, 0.90088, 0.90088, 0.90088, 0.90088, 0.90088, 0.90088, 0.90088, 0.90388, 1.03901, 0.92138, 0.78105, 0.7154, 0.86169, 0.80513, 0.94007, 0.82528, 0.98612, 1.06226, 0.91755, 0.8126, 0.81884, 0.92819, 0.73764, 0.90531, 0.90284, 0.8858, 0.86023, 0.8126, 0.91172, 0.96518, 0.91115, 0.83089, 0.8858, 0.87791, 0.79761, 0.89297, 0.81363, 0.88157, 0.89992, 0.85608, 0.81992, 0.94307, 0.86023, 0.88157, 0.95308, 0.98699, 0.99793, 1.06226, 0.95817, 0.95308, 0.97358, 0.928, 0.98088, 0.98699, 0.92761, 0.99793, 0.96017, 1.06226, 0.986, 0.944, 0.95978, 0.938, 0.96705, 0.98714, 0.80442, 0.98972, 1, 0.89762, 1.04552, 0.95817, 0.99007, 0.87064, 0.91879, 0.88888, 1.06226, 0.95817, 0.98714, 0.95817, 0.88888, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.89633, 1.01915, 0.89633, 1.01915, 0.89633, 1.01915, 0.8111, 0.942, 0.9219, 1, 0.89903, 1, 1, 1, 0.93173, 0.93173, 0.93173, 1, 1.06304, 1.06304, 1.06904, 0.89903, 0.89903, 0.80549, 1, 1.156, 1, 1, 0.76575, 0.76575, 1, 1, 0.72458, 1, 1, 1, 1, 0.92241, 1, 1, 1, 0.619, 1, 1.36145, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.07257, 1, 0.74705, 0.71119, 1.02058, 1.024, 1.02119, 1, 1, 1.1536, 1.08595, 1.08595, 1, 1.08595, 1.08595, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.05638, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1];
+const MyriadProRegularMetrics = {
+ lineHeight: 1.2,
+ lineGap: 0.2
+};
+
+;// CONCATENATED MODULE: ./src/core/segoeui_factors.js
+const SegoeuiBoldFactors = [1.76738, 1, 1, 0.99297, 0.9824, 1.04016, 1.06497, 1.03424, 0.97529, 1.17647, 1.23203, 1.1085, 1.1085, 1.16939, 1.2107, 0.9754, 1.21408, 0.9754, 1.59578, 1.03424, 1.03424, 1.03424, 1.03424, 1.03424, 1.03424, 1.03424, 1.03424, 1.03424, 1.03424, 0.81378, 0.81378, 1.2107, 1.2107, 1.2107, 0.71703, 0.97847, 0.97363, 0.88776, 0.8641, 1.02096, 0.79795, 0.85132, 0.914, 1.06085, 1.1406, 0.8007, 0.89858, 0.83693, 1.14889, 1.09398, 0.97489, 0.92094, 0.97489, 0.90399, 0.84041, 0.95923, 1.00135, 1, 1.06467, 0.98243, 0.90996, 0.99361, 1.1085, 1.56942, 1.1085, 1.2107, 0.74627, 0.94282, 0.96752, 1.01519, 0.86304, 1.01359, 0.97278, 1.15103, 1.01359, 0.98561, 1.02285, 1.02285, 1.00527, 1.02285, 1.0302, 0.99041, 1.0008, 1.01519, 1.01359, 1.02258, 0.79104, 1.16862, 0.99041, 0.97454, 1.02511, 0.99298, 0.96752, 0.95801, 0.94856, 1.16579, 0.94856, 1.2107, 0.9824, 1.03424, 1.03424, 1, 1.03424, 1.16579, 0.8727, 1.3871, 1.18622, 1.10818, 1.04478, 1.2107, 1.18622, 0.75155, 0.94994, 1.28826, 1.21408, 1.21408, 0.91056, 1, 0.91572, 0.9754, 0.64663, 1.18328, 1.24866, 1.04478, 1.14169, 1.15749, 1.17389, 0.71703, 0.97363, 0.97363, 0.97363, 0.97363, 0.97363, 0.97363, 0.93506, 0.8641, 0.79795, 0.79795, 0.79795, 0.79795, 1.1406, 1.1406, 1.1406, 1.1406, 1.02096, 1.09398, 0.97426, 0.97426, 0.97426, 0.97426, 0.97426, 1.2107, 0.97489, 1.00135, 1.00135, 1.00135, 1.00135, 0.90996, 0.92094, 1.02798, 0.96752, 0.96752, 0.96752, 0.96752, 0.96752, 0.96752, 0.93136, 0.86304, 0.97278, 0.97278, 0.97278, 0.97278, 1.02285, 1.02285, 1.02285, 1.02285, 0.97122, 0.99041, 1, 1, 1, 1, 1, 1.28826, 1.0008, 0.99041, 0.99041, 0.99041, 0.99041, 0.96752, 1.01519, 0.96752, 0.97363, 0.96752, 0.97363, 0.96752, 0.97363, 0.96752, 0.8641, 0.86304, 0.8641, 0.86304, 0.8641, 0.86304, 0.8641, 0.86304, 1.02096, 1.03057, 1.02096, 1.03517, 0.79795, 0.97278, 0.79795, 0.97278, 0.79795, 0.97278, 0.79795, 0.97278, 0.79795, 0.97278, 0.914, 1.01359, 0.914, 1.01359, 0.914, 1.01359, 1, 1, 1.06085, 0.98561, 1.06085, 1.00879, 1.1406, 1.02285, 1.1406, 1.02285, 1.1406, 1.02285, 1.1406, 1.02285, 1.1406, 1.02285, 0.97138, 1.08692, 0.8007, 1.02285, 1, 1, 1.00527, 0.83693, 1.02285, 1, 1, 0.83693, 0.9455, 0.83693, 0.90418, 0.83693, 1.13005, 1.09398, 0.99041, 1, 1, 1.09398, 0.99041, 0.96692, 1.09251, 0.99041, 0.97489, 1.0008, 0.97489, 1.0008, 0.97489, 1.0008, 0.93994, 0.97931, 0.90399, 1.02258, 1, 1, 0.90399, 1.02258, 0.84041, 0.79104, 0.84041, 0.79104, 0.84041, 0.79104, 0.84041, 0.79104, 1, 1, 0.95923, 1.07034, 0.95923, 1.16862, 1.00135, 0.99041, 1.00135, 0.99041, 1.00135, 0.99041, 1.00135, 0.99041, 1.00135, 0.99041, 1.00135, 0.99041, 1.06467, 1.02511, 0.90996, 0.96752, 0.90996, 0.99361, 0.95801, 0.99361, 0.95801, 0.99361, 0.95801, 1.07733, 1.03424, 0.97363, 0.96752, 0.93506, 0.93136, 0.97489, 1.0008, 1, 1, 0.95923, 1.16862, 1.15103, 1.15103, 1.01173, 1.03959, 0.75953, 0.81378, 0.79912, 1.15103, 1.21994, 0.95161, 0.87815, 1.01149, 0.81525, 0.7676, 0.98167, 1.01134, 1.02546, 0.84097, 1.03089, 1.18102, 0.97363, 0.88776, 0.85134, 0.97826, 0.79795, 0.99361, 1.06085, 0.97489, 1.1406, 0.89858, 1.0388, 1.14889, 1.09398, 0.86039, 0.97489, 1.0595, 0.92094, 0.94793, 0.95923, 0.90996, 0.99346, 0.98243, 1.02112, 0.95493, 1.1406, 0.90996, 1.03574, 1.02597, 1.0008, 1.18102, 1.06628, 1.03574, 1.0192, 1.01932, 1.00886, 0.97531, 1.0106, 1.0008, 1.13189, 1.18102, 1.02277, 0.98683, 1.0016, 0.99561, 1.07237, 1.0008, 0.90434, 0.99921, 0.93803, 0.8965, 1.23085, 1.06628, 1.04983, 0.96268, 1.0499, 0.98439, 1.18102, 1.06628, 1.0008, 1.06628, 0.98439, 0.79795, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.09466, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.97278, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.02065, 1, 1, 1, 1, 1, 1, 1.06467, 1.02511, 1.06467, 1.02511, 1.06467, 1.02511, 0.90996, 0.96752, 1, 1.21408, 0.89903, 1, 1, 0.75155, 1.04394, 1.04394, 1.04394, 1.04394, 0.98633, 0.98633, 0.98633, 0.73047, 0.73047, 1.20642, 0.91211, 1.25635, 1.222, 1.02956, 1.03372, 1.03372, 0.96039, 1.24633, 1, 1.12454, 0.93503, 1.03424, 1.19687, 1.03424, 1, 1, 1, 0.771, 1, 1, 1.15749, 1.15749, 1.15749, 1.10948, 0.86279, 0.94434, 0.86279, 0.94434, 0.86182, 1, 1, 1.16897, 1, 0.96085, 0.90137, 1.2107, 1.18416, 1.13973, 0.69825, 0.9716, 2.10339, 1.29004, 1.29004, 1.21172, 1.29004, 1.29004, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.42603, 1, 0.99862, 0.99862, 1, 0.87025, 0.87025, 0.87025, 0.87025, 1.18874, 1.42603, 1, 1.42603, 1.42603, 0.99862, 1, 1, 1, 1, 1, 1.2886, 1.04315, 1.15296, 1.34163, 1, 1, 1, 1.09193, 1.09193, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1];
+const SegoeuiBoldMetrics = {
+ lineHeight: 1.33008,
+ lineGap: 0
+};
+const SegoeuiBoldItalicFactors = [1.76738, 1, 1, 0.98946, 1.03959, 1.04016, 1.02809, 1.036, 0.97639, 1.10953, 1.23203, 1.11144, 1.11144, 1.16939, 1.21237, 0.9754, 1.21261, 0.9754, 1.59754, 1.036, 1.036, 1.036, 1.036, 1.036, 1.036, 1.036, 1.036, 1.036, 1.036, 0.81378, 0.81378, 1.21237, 1.21237, 1.21237, 0.73541, 0.97847, 0.97363, 0.89723, 0.87897, 1.0426, 0.79429, 0.85292, 0.91149, 1.05815, 1.1406, 0.79631, 0.90128, 0.83853, 1.04396, 1.10615, 0.97552, 0.94436, 0.97552, 0.88641, 0.80527, 0.96083, 1.00135, 1, 1.06777, 0.9817, 0.91142, 0.99361, 1.11144, 1.57293, 1.11144, 1.21237, 0.74627, 1.31818, 1.06585, 0.97042, 0.83055, 0.97042, 0.93503, 1.1261, 0.97042, 0.97922, 1.14236, 0.94552, 1.01054, 1.14236, 1.02471, 0.97922, 0.94165, 0.97042, 0.97042, 1.0276, 0.78929, 1.1261, 0.97922, 0.95874, 1.02197, 0.98507, 0.96752, 0.97168, 0.95107, 1.16579, 0.95107, 1.21237, 1.03959, 1.036, 1.036, 1, 1.036, 1.16579, 0.87357, 1.31818, 1.18754, 1.26781, 1.05356, 1.21237, 1.18622, 0.79487, 0.94994, 1.29004, 1.24047, 1.24047, 1.31818, 1, 0.91484, 0.9754, 1.31818, 1.1349, 1.24866, 1.05356, 1.13934, 1.15574, 1.17389, 0.73541, 0.97363, 0.97363, 0.97363, 0.97363, 0.97363, 0.97363, 0.94385, 0.87897, 0.79429, 0.79429, 0.79429, 0.79429, 1.1406, 1.1406, 1.1406, 1.1406, 1.0426, 1.10615, 0.97552, 0.97552, 0.97552, 0.97552, 0.97552, 1.21237, 0.97552, 1.00135, 1.00135, 1.00135, 1.00135, 0.91142, 0.94436, 0.98721, 1.06585, 1.06585, 1.06585, 1.06585, 1.06585, 1.06585, 0.96705, 0.83055, 0.93503, 0.93503, 0.93503, 0.93503, 1.14236, 1.14236, 1.14236, 1.14236, 0.93125, 0.97922, 0.94165, 0.94165, 0.94165, 0.94165, 0.94165, 1.29004, 0.94165, 0.97922, 0.97922, 0.97922, 0.97922, 0.96752, 0.97042, 0.96752, 0.97363, 1.06585, 0.97363, 1.06585, 0.97363, 1.06585, 0.87897, 0.83055, 0.87897, 0.83055, 0.87897, 0.83055, 0.87897, 0.83055, 1.0426, 1.0033, 1.0426, 0.97042, 0.79429, 0.93503, 0.79429, 0.93503, 0.79429, 0.93503, 0.79429, 0.93503, 0.79429, 0.93503, 0.91149, 0.97042, 0.91149, 0.97042, 0.91149, 0.97042, 1, 1, 1.05815, 0.97922, 1.05815, 0.97922, 1.1406, 1.14236, 1.1406, 1.14236, 1.1406, 1.14236, 1.1406, 1.14236, 1.1406, 1.14236, 0.97441, 1.04302, 0.79631, 1.01582, 1, 1, 1.01054, 0.83853, 1.14236, 1, 1, 0.83853, 1.09125, 0.83853, 0.90418, 0.83853, 1.19508, 1.10615, 0.97922, 1, 1, 1.10615, 0.97922, 1.01034, 1.10466, 0.97922, 0.97552, 0.94165, 0.97552, 0.94165, 0.97552, 0.94165, 0.91602, 0.91981, 0.88641, 1.0276, 1, 1, 0.88641, 1.0276, 0.80527, 0.78929, 0.80527, 0.78929, 0.80527, 0.78929, 0.80527, 0.78929, 1, 1, 0.96083, 1.05403, 0.95923, 1.16862, 1.00135, 0.97922, 1.00135, 0.97922, 1.00135, 0.97922, 1.00135, 0.97922, 1.00135, 0.97922, 1.00135, 0.97922, 1.06777, 1.02197, 0.91142, 0.96752, 0.91142, 0.99361, 0.97168, 0.99361, 0.97168, 0.99361, 0.97168, 1.23199, 1.036, 0.97363, 1.06585, 0.94385, 0.96705, 0.97552, 0.94165, 1, 1, 0.96083, 1.1261, 1.31818, 1.31818, 1.31818, 1.31818, 1.31818, 1.31818, 1.31818, 1.31818, 1.31818, 0.95161, 1.27126, 1.00811, 0.83284, 0.77702, 0.99137, 0.95253, 1.0347, 0.86142, 1.07205, 1.14236, 0.97363, 0.89723, 0.86869, 1.09818, 0.79429, 0.99361, 1.05815, 0.97552, 1.1406, 0.90128, 1.06662, 1.04396, 1.10615, 0.84918, 0.97552, 1.04694, 0.94436, 0.98015, 0.96083, 0.91142, 1.00356, 0.9817, 1.01945, 0.98999, 1.1406, 0.91142, 1.04961, 0.9898, 1.00639, 1.14236, 1.07514, 1.04961, 0.99607, 1.02897, 1.008, 0.9898, 0.95134, 1.00639, 1.11121, 1.14236, 1.00518, 0.97981, 1.02186, 1, 1.08578, 0.94165, 0.99314, 0.98387, 0.93028, 0.93377, 1.35125, 1.07514, 1.10687, 0.93491, 1.04232, 1.00351, 1.14236, 1.07514, 0.94165, 1.07514, 1.00351, 0.79429, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.09097, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.93503, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.96609, 1, 1, 1, 1, 1, 1, 1.06777, 1.02197, 1.06777, 1.02197, 1.06777, 1.02197, 0.91142, 0.96752, 1, 1.21261, 0.89903, 1, 1, 0.75155, 1.04745, 1.04745, 1.04745, 1.04394, 0.98633, 0.98633, 0.98633, 0.72959, 0.72959, 1.20502, 0.91406, 1.26514, 1.222, 1.02956, 1.03372, 1.03372, 0.96039, 1.24633, 1, 1.09125, 0.93327, 1.03336, 1.16541, 1.036, 1, 1, 1, 0.771, 1, 1, 1.15574, 1.15574, 1.15574, 1.15574, 0.86364, 0.94434, 0.86279, 0.94434, 0.86224, 1, 1, 1.16798, 1, 0.96085, 0.90068, 1.21237, 1.18416, 1.13904, 0.69825, 0.9716, 2.10339, 1.29004, 1.29004, 1.21339, 1.29004, 1.29004, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.42603, 1, 0.99862, 0.99862, 1, 0.87025, 0.87025, 0.87025, 0.87025, 1.18775, 1.42603, 1, 1.42603, 1.42603, 0.99862, 1, 1, 1, 1, 1, 1.2886, 1.04315, 1.15296, 1.34163, 1, 1, 1, 1.13269, 1.13269, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1];
+const SegoeuiBoldItalicMetrics = {
+ lineHeight: 1.33008,
+ lineGap: 0
+};
+const SegoeuiItalicFactors = [1.76738, 1, 1, 0.98946, 1.14763, 1.05365, 1.06234, 0.96927, 0.92586, 1.15373, 1.18414, 0.91349, 0.91349, 1.07403, 1.17308, 0.78383, 1.20088, 0.78383, 1.42531, 0.96927, 0.96927, 0.96927, 0.96927, 0.96927, 0.96927, 0.96927, 0.96927, 0.96927, 0.96927, 0.78383, 0.78383, 1.17308, 1.17308, 1.17308, 0.77349, 0.94565, 0.94729, 0.85944, 0.88506, 0.9858, 0.74817, 0.80016, 0.88449, 0.98039, 0.95782, 0.69238, 0.89898, 0.83231, 0.98183, 1.03989, 0.96924, 0.86237, 0.96924, 0.80595, 0.74524, 0.86091, 0.95402, 0.94143, 0.98448, 0.8858, 0.83089, 0.93285, 1.0949, 1.39016, 1.0949, 1.45994, 0.74627, 1.04839, 0.97454, 0.97454, 0.87207, 0.97454, 0.87533, 1.06151, 0.97454, 1.00176, 1.16484, 1.08132, 0.98047, 1.16484, 1.02989, 1.01054, 0.96225, 0.97454, 0.97454, 1.06598, 0.79004, 1.16344, 1.00351, 0.94629, 0.9973, 0.91016, 0.96777, 0.9043, 0.91082, 0.92481, 0.91082, 1.17308, 0.95748, 0.96927, 0.96927, 1, 0.96927, 0.92481, 0.80597, 1.04839, 1.23393, 1.1781, 0.9245, 1.17308, 1.20808, 0.63218, 0.94261, 1.24822, 1.09971, 1.09971, 1.04839, 1, 0.85273, 0.78032, 1.04839, 1.09971, 1.22326, 0.9245, 1.09836, 1.13525, 1.15222, 0.70424, 0.94729, 0.94729, 0.94729, 0.94729, 0.94729, 0.94729, 0.85498, 0.88506, 0.74817, 0.74817, 0.74817, 0.74817, 0.95782, 0.95782, 0.95782, 0.95782, 0.9858, 1.03989, 0.96924, 0.96924, 0.96924, 0.96924, 0.96924, 1.17308, 0.96924, 0.95402, 0.95402, 0.95402, 0.95402, 0.83089, 0.86237, 0.88409, 0.97454, 0.97454, 0.97454, 0.97454, 0.97454, 0.97454, 0.92916, 0.87207, 0.87533, 0.87533, 0.87533, 0.87533, 0.93146, 0.93146, 0.93146, 0.93146, 0.93854, 1.01054, 0.96225, 0.96225, 0.96225, 0.96225, 0.96225, 1.24822, 0.8761, 1.00351, 1.00351, 1.00351, 1.00351, 0.96777, 0.97454, 0.96777, 0.94729, 0.97454, 0.94729, 0.97454, 0.94729, 0.97454, 0.88506, 0.87207, 0.88506, 0.87207, 0.88506, 0.87207, 0.88506, 0.87207, 0.9858, 0.95391, 0.9858, 0.97454, 0.74817, 0.87533, 0.74817, 0.87533, 0.74817, 0.87533, 0.74817, 0.87533, 0.74817, 0.87533, 0.88449, 0.97454, 0.88449, 0.97454, 0.88449, 0.97454, 1, 1, 0.98039, 1.00176, 0.98039, 1.00176, 0.95782, 0.93146, 0.95782, 0.93146, 0.95782, 0.93146, 0.95782, 1.16484, 0.95782, 0.93146, 0.84421, 1.12761, 0.69238, 1.08132, 1, 1, 0.98047, 0.83231, 1.16484, 1, 1, 0.84723, 1.04861, 0.84723, 0.78755, 0.83231, 1.23736, 1.03989, 1.01054, 1, 1, 1.03989, 1.01054, 0.9857, 1.03849, 1.01054, 0.96924, 0.96225, 0.96924, 0.96225, 0.96924, 0.96225, 0.92383, 0.90171, 0.80595, 1.06598, 1, 1, 0.80595, 1.06598, 0.74524, 0.79004, 0.74524, 0.79004, 0.74524, 0.79004, 0.74524, 0.79004, 1, 1, 0.86091, 1.02759, 0.85771, 1.16344, 0.95402, 1.00351, 0.95402, 1.00351, 0.95402, 1.00351, 0.95402, 1.00351, 0.95402, 1.00351, 0.95402, 1.00351, 0.98448, 0.9973, 0.83089, 0.96777, 0.83089, 0.93285, 0.9043, 0.93285, 0.9043, 0.93285, 0.9043, 1.31868, 0.96927, 0.94729, 0.97454, 0.85498, 0.92916, 0.96924, 0.8761, 1, 1, 0.86091, 1.16344, 1.04839, 1.04839, 1.04839, 1.04839, 1.04839, 1.04839, 1.04839, 1.04839, 1.04839, 0.81965, 0.81965, 0.94729, 0.78032, 0.71022, 0.90883, 0.84171, 0.99877, 0.77596, 1.05734, 1.2, 0.94729, 0.85944, 0.82791, 0.9607, 0.74817, 0.93285, 0.98039, 0.96924, 0.95782, 0.89898, 0.98316, 0.98183, 1.03989, 0.78614, 0.96924, 0.97642, 0.86237, 0.86075, 0.86091, 0.83089, 0.90082, 0.8858, 0.97296, 1.01284, 0.95782, 0.83089, 1.0976, 1.04, 1.03342, 1.2, 1.0675, 1.0976, 0.98205, 1.03809, 1.05097, 1.04, 0.95364, 1.03342, 1.05401, 1.2, 1.02148, 1.0119, 1.04724, 1.0127, 1.02732, 0.96225, 0.8965, 0.97783, 0.93574, 0.94818, 1.30679, 1.0675, 1.11826, 0.99821, 1.0557, 1.0326, 1.2, 1.0675, 0.96225, 1.0675, 1.0326, 0.74817, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.03754, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.87533, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.98705, 1, 1, 1, 1, 1, 1, 0.98448, 0.9973, 0.98448, 0.9973, 0.98448, 0.9973, 0.83089, 0.96777, 1, 1.20088, 0.89903, 1, 1, 0.75155, 0.94945, 0.94945, 0.94945, 0.94945, 1.12317, 1.12317, 1.12317, 0.67603, 0.67603, 1.15621, 0.73584, 1.21191, 1.22135, 1.06483, 0.94868, 0.94868, 0.95996, 1.24633, 1, 1.07497, 0.87709, 0.96927, 1.01473, 0.96927, 1, 1, 1, 0.77295, 1, 1, 1.09836, 1.09836, 1.09836, 1.01522, 0.86321, 0.94434, 0.8649, 0.94434, 0.86182, 1, 1, 1.083, 1, 0.91578, 0.86438, 1.17308, 1.18416, 1.14589, 0.69825, 0.97622, 1.96791, 1.24822, 1.24822, 1.17308, 1.24822, 1.24822, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.42603, 1, 0.99862, 0.99862, 1, 0.87025, 0.87025, 0.87025, 0.87025, 1.17984, 1.42603, 1, 1.42603, 1.42603, 0.99862, 1, 1, 1, 1, 1, 1.2886, 1.04315, 1.15296, 1.34163, 1, 1, 1, 1.10742, 1.10742, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1];
+const SegoeuiItalicMetrics = {
+ lineHeight: 1.33008,
+ lineGap: 0
+};
+const SegoeuiRegularFactors = [1.76738, 1, 1, 0.98594, 1.02285, 1.10454, 1.06234, 0.96927, 0.92037, 1.19985, 1.2046, 0.90616, 0.90616, 1.07152, 1.1714, 0.78032, 1.20088, 0.78032, 1.40246, 0.96927, 0.96927, 0.96927, 0.96927, 0.96927, 0.96927, 0.96927, 0.96927, 0.96927, 0.96927, 0.78032, 0.78032, 1.1714, 1.1714, 1.1714, 0.80597, 0.94084, 0.96706, 0.85944, 0.85734, 0.97093, 0.75842, 0.79936, 0.88198, 0.9831, 0.95782, 0.71387, 0.86969, 0.84636, 1.07796, 1.03584, 0.96924, 0.83968, 0.96924, 0.82826, 0.79649, 0.85771, 0.95132, 0.93119, 0.98965, 0.88433, 0.8287, 0.93365, 1.08612, 1.3638, 1.08612, 1.45786, 0.74627, 0.80499, 0.91484, 1.05707, 0.92383, 1.05882, 0.9403, 1.12654, 1.05882, 1.01756, 1.09011, 1.09011, 0.99414, 1.09011, 1.034, 1.01756, 1.05356, 1.05707, 1.05882, 1.04399, 0.84863, 1.21968, 1.01756, 0.95801, 1.00068, 0.91797, 0.96777, 0.9043, 0.90351, 0.92105, 0.90351, 1.1714, 0.85337, 0.96927, 0.96927, 0.99912, 0.96927, 0.92105, 0.80597, 1.2434, 1.20808, 1.05937, 0.90957, 1.1714, 1.20808, 0.75155, 0.94261, 1.24644, 1.09971, 1.09971, 0.84751, 1, 0.85273, 0.78032, 0.61584, 1.05425, 1.17914, 0.90957, 1.08665, 1.11593, 1.14169, 0.73381, 0.96706, 0.96706, 0.96706, 0.96706, 0.96706, 0.96706, 0.86035, 0.85734, 0.75842, 0.75842, 0.75842, 0.75842, 0.95782, 0.95782, 0.95782, 0.95782, 0.97093, 1.03584, 0.96924, 0.96924, 0.96924, 0.96924, 0.96924, 1.1714, 0.96924, 0.95132, 0.95132, 0.95132, 0.95132, 0.8287, 0.83968, 0.89049, 0.91484, 0.91484, 0.91484, 0.91484, 0.91484, 0.91484, 0.93575, 0.92383, 0.9403, 0.9403, 0.9403, 0.9403, 0.8717, 0.8717, 0.8717, 0.8717, 1.00527, 1.01756, 1.05356, 1.05356, 1.05356, 1.05356, 1.05356, 1.24644, 0.95923, 1.01756, 1.01756, 1.01756, 1.01756, 0.96777, 1.05707, 0.96777, 0.96706, 0.91484, 0.96706, 0.91484, 0.96706, 0.91484, 0.85734, 0.92383, 0.85734, 0.92383, 0.85734, 0.92383, 0.85734, 0.92383, 0.97093, 1.0969, 0.97093, 1.05882, 0.75842, 0.9403, 0.75842, 0.9403, 0.75842, 0.9403, 0.75842, 0.9403, 0.75842, 0.9403, 0.88198, 1.05882, 0.88198, 1.05882, 0.88198, 1.05882, 1, 1, 0.9831, 1.01756, 0.9831, 1.01756, 0.95782, 0.8717, 0.95782, 0.8717, 0.95782, 0.8717, 0.95782, 1.09011, 0.95782, 0.8717, 0.84784, 1.11551, 0.71387, 1.09011, 1, 1, 0.99414, 0.84636, 1.09011, 1, 1, 0.84636, 1.0536, 0.84636, 0.94298, 0.84636, 1.23297, 1.03584, 1.01756, 1, 1, 1.03584, 1.01756, 1.00323, 1.03444, 1.01756, 0.96924, 1.05356, 0.96924, 1.05356, 0.96924, 1.05356, 0.93066, 0.98293, 0.82826, 1.04399, 1, 1, 0.82826, 1.04399, 0.79649, 0.84863, 0.79649, 0.84863, 0.79649, 0.84863, 0.79649, 0.84863, 1, 1, 0.85771, 1.17318, 0.85771, 1.21968, 0.95132, 1.01756, 0.95132, 1.01756, 0.95132, 1.01756, 0.95132, 1.01756, 0.95132, 1.01756, 0.95132, 1.01756, 0.98965, 1.00068, 0.8287, 0.96777, 0.8287, 0.93365, 0.9043, 0.93365, 0.9043, 0.93365, 0.9043, 1.08571, 0.96927, 0.96706, 0.91484, 0.86035, 0.93575, 0.96924, 0.95923, 1, 1, 0.85771, 1.21968, 1.11437, 1.11437, 0.93109, 0.91202, 0.60411, 0.84164, 0.55572, 1.01173, 0.97361, 0.81818, 0.81818, 0.96635, 0.78032, 0.72727, 0.92366, 0.98601, 1.03405, 0.77968, 1.09799, 1.2, 0.96706, 0.85944, 0.85638, 0.96491, 0.75842, 0.93365, 0.9831, 0.96924, 0.95782, 0.86969, 0.94152, 1.07796, 1.03584, 0.78437, 0.96924, 0.98715, 0.83968, 0.83491, 0.85771, 0.8287, 0.94492, 0.88433, 0.9287, 1.0098, 0.95782, 0.8287, 1.0625, 0.98248, 1.03424, 1.2, 1.01071, 1.0625, 0.95246, 1.03809, 1.04912, 0.98248, 1.00221, 1.03424, 1.05443, 1.2, 1.04785, 0.99609, 1.00169, 1.05176, 0.99346, 1.05356, 0.9087, 1.03004, 0.95542, 0.93117, 1.23362, 1.01071, 1.07831, 1.02512, 1.05205, 1.03502, 1.2, 1.01071, 1.05356, 1.01071, 1.03502, 0.75842, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.03719, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.9403, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.04021, 1, 1, 1, 1, 1, 1, 0.98965, 1.00068, 0.98965, 1.00068, 0.98965, 1.00068, 0.8287, 0.96777, 1, 1.20088, 0.89903, 1, 1, 0.75155, 1.03077, 1.03077, 1.03077, 1.03077, 1.13196, 1.13196, 1.13196, 0.67428, 0.67428, 1.16039, 0.73291, 1.20996, 1.22135, 1.06483, 0.94868, 0.94868, 0.95996, 1.24633, 1, 1.07497, 0.87796, 0.96927, 1.01518, 0.96927, 1, 1, 1, 0.77295, 1, 1, 1.10539, 1.10539, 1.11358, 1.06967, 0.86279, 0.94434, 0.86279, 0.94434, 0.86182, 1, 1, 1.083, 1, 0.91578, 0.86507, 1.1714, 1.18416, 1.14589, 0.69825, 0.97622, 1.9697, 1.24822, 1.24822, 1.17238, 1.24822, 1.24822, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.42603, 1, 0.99862, 0.99862, 1, 0.87025, 0.87025, 0.87025, 0.87025, 1.18083, 1.42603, 1, 1.42603, 1.42603, 0.99862, 1, 1, 1, 1, 1, 1.2886, 1.04315, 1.15296, 1.34163, 1, 1, 1, 1.10938, 1.10938, 1, 1, 1, 1.05425, 1.09971, 1.09971, 1.09971, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1];
+const SegoeuiRegularMetrics = {
+ lineHeight: 1.33008,
+ lineGap: 0
+};
+
+;// CONCATENATED MODULE: ./src/core/xfa_fonts.js
+
+
+
+
+
+
+
+
+const getXFAFontMap = getLookupTableFactory(function (t) {
+ t["MyriadPro-Regular"] = t["PdfJS-Fallback-Regular"] = {
+ name: "LiberationSans-Regular",
+ factors: MyriadProRegularFactors,
+ baseWidths: LiberationSansRegularWidths,
+ baseMapping: LiberationSansRegularMapping,
+ metrics: MyriadProRegularMetrics
+ };
+ t["MyriadPro-Bold"] = t["PdfJS-Fallback-Bold"] = {
+ name: "LiberationSans-Bold",
+ factors: MyriadProBoldFactors,
+ baseWidths: LiberationSansBoldWidths,
+ baseMapping: LiberationSansBoldMapping,
+ metrics: MyriadProBoldMetrics
+ };
+ t["MyriadPro-It"] = t["MyriadPro-Italic"] = t["PdfJS-Fallback-Italic"] = {
+ name: "LiberationSans-Italic",
+ factors: MyriadProItalicFactors,
+ baseWidths: LiberationSansItalicWidths,
+ baseMapping: LiberationSansItalicMapping,
+ metrics: MyriadProItalicMetrics
+ };
+ t["MyriadPro-BoldIt"] = t["MyriadPro-BoldItalic"] = t["PdfJS-Fallback-BoldItalic"] = {
+ name: "LiberationSans-BoldItalic",
+ factors: MyriadProBoldItalicFactors,
+ baseWidths: LiberationSansBoldItalicWidths,
+ baseMapping: LiberationSansBoldItalicMapping,
+ metrics: MyriadProBoldItalicMetrics
+ };
+ t.ArialMT = t.Arial = t["Arial-Regular"] = {
+ name: "LiberationSans-Regular",
+ baseWidths: LiberationSansRegularWidths,
+ baseMapping: LiberationSansRegularMapping
+ };
+ t["Arial-BoldMT"] = t["Arial-Bold"] = {
+ name: "LiberationSans-Bold",
+ baseWidths: LiberationSansBoldWidths,
+ baseMapping: LiberationSansBoldMapping
+ };
+ t["Arial-ItalicMT"] = t["Arial-Italic"] = {
+ name: "LiberationSans-Italic",
+ baseWidths: LiberationSansItalicWidths,
+ baseMapping: LiberationSansItalicMapping
+ };
+ t["Arial-BoldItalicMT"] = t["Arial-BoldItalic"] = {
+ name: "LiberationSans-BoldItalic",
+ baseWidths: LiberationSansBoldItalicWidths,
+ baseMapping: LiberationSansBoldItalicMapping
+ };
+ t["Calibri-Regular"] = {
+ name: "LiberationSans-Regular",
+ factors: CalibriRegularFactors,
+ baseWidths: LiberationSansRegularWidths,
+ baseMapping: LiberationSansRegularMapping,
+ metrics: CalibriRegularMetrics
+ };
+ t["Calibri-Bold"] = {
+ name: "LiberationSans-Bold",
+ factors: CalibriBoldFactors,
+ baseWidths: LiberationSansBoldWidths,
+ baseMapping: LiberationSansBoldMapping,
+ metrics: CalibriBoldMetrics
+ };
+ t["Calibri-Italic"] = {
+ name: "LiberationSans-Italic",
+ factors: CalibriItalicFactors,
+ baseWidths: LiberationSansItalicWidths,
+ baseMapping: LiberationSansItalicMapping,
+ metrics: CalibriItalicMetrics
+ };
+ t["Calibri-BoldItalic"] = {
+ name: "LiberationSans-BoldItalic",
+ factors: CalibriBoldItalicFactors,
+ baseWidths: LiberationSansBoldItalicWidths,
+ baseMapping: LiberationSansBoldItalicMapping,
+ metrics: CalibriBoldItalicMetrics
+ };
+ t["Segoeui-Regular"] = {
+ name: "LiberationSans-Regular",
+ factors: SegoeuiRegularFactors,
+ baseWidths: LiberationSansRegularWidths,
+ baseMapping: LiberationSansRegularMapping,
+ metrics: SegoeuiRegularMetrics
+ };
+ t["Segoeui-Bold"] = {
+ name: "LiberationSans-Bold",
+ factors: SegoeuiBoldFactors,
+ baseWidths: LiberationSansBoldWidths,
+ baseMapping: LiberationSansBoldMapping,
+ metrics: SegoeuiBoldMetrics
+ };
+ t["Segoeui-Italic"] = {
+ name: "LiberationSans-Italic",
+ factors: SegoeuiItalicFactors,
+ baseWidths: LiberationSansItalicWidths,
+ baseMapping: LiberationSansItalicMapping,
+ metrics: SegoeuiItalicMetrics
+ };
+ t["Segoeui-BoldItalic"] = {
+ name: "LiberationSans-BoldItalic",
+ factors: SegoeuiBoldItalicFactors,
+ baseWidths: LiberationSansBoldItalicWidths,
+ baseMapping: LiberationSansBoldItalicMapping,
+ metrics: SegoeuiBoldItalicMetrics
+ };
+ t["Helvetica-Regular"] = t.Helvetica = {
+ name: "LiberationSans-Regular",
+ factors: HelveticaRegularFactors,
+ baseWidths: LiberationSansRegularWidths,
+ baseMapping: LiberationSansRegularMapping,
+ metrics: HelveticaRegularMetrics
+ };
+ t["Helvetica-Bold"] = {
+ name: "LiberationSans-Bold",
+ factors: HelveticaBoldFactors,
+ baseWidths: LiberationSansBoldWidths,
+ baseMapping: LiberationSansBoldMapping,
+ metrics: HelveticaBoldMetrics
+ };
+ t["Helvetica-Italic"] = {
+ name: "LiberationSans-Italic",
+ factors: HelveticaItalicFactors,
+ baseWidths: LiberationSansItalicWidths,
+ baseMapping: LiberationSansItalicMapping,
+ metrics: HelveticaItalicMetrics
+ };
+ t["Helvetica-BoldItalic"] = {
+ name: "LiberationSans-BoldItalic",
+ factors: HelveticaBoldItalicFactors,
+ baseWidths: LiberationSansBoldItalicWidths,
+ baseMapping: LiberationSansBoldItalicMapping,
+ metrics: HelveticaBoldItalicMetrics
+ };
+});
+function getXfaFontName(name) {
+ const fontName = normalizeFontName(name);
+ const fontMap = getXFAFontMap();
+ return fontMap[fontName];
+}
+function getXfaFontWidths(name) {
+ const info = getXfaFontName(name);
+ if (!info) {
+ return null;
+ }
+ const {
+ baseWidths,
+ baseMapping,
+ factors
+ } = info;
+ const rescaledBaseWidths = !factors ? baseWidths : baseWidths.map((w, i) => w * factors[i]);
+ let currentCode = -2;
+ let currentArray;
+ const newWidths = [];
+ for (const [unicode, glyphIndex] of baseMapping.map((charUnicode, index) => [charUnicode, index]).sort(([unicode1], [unicode2]) => unicode1 - unicode2)) {
+ if (unicode === -1) {
+ continue;
+ }
+ if (unicode === currentCode + 1) {
+ currentArray.push(rescaledBaseWidths[glyphIndex]);
+ currentCode += 1;
+ } else {
+ currentCode = unicode;
+ currentArray = [rescaledBaseWidths[glyphIndex]];
+ newWidths.push(unicode, currentArray);
+ }
+ }
+ return newWidths;
+}
+function getXfaFontDict(name) {
+ const widths = getXfaFontWidths(name);
+ const dict = new Dict(null);
+ dict.set("BaseFont", Name.get(name));
+ dict.set("Type", Name.get("Font"));
+ dict.set("Subtype", Name.get("CIDFontType2"));
+ dict.set("Encoding", Name.get("Identity-H"));
+ dict.set("CIDToGIDMap", Name.get("Identity"));
+ dict.set("W", widths);
+ dict.set("FirstChar", widths[0]);
+ dict.set("LastChar", widths.at(-2) + widths.at(-1).length - 1);
+ const descriptor = new Dict(null);
+ dict.set("FontDescriptor", descriptor);
+ const systemInfo = new Dict(null);
+ systemInfo.set("Ordering", "Identity");
+ systemInfo.set("Registry", "Adobe");
+ systemInfo.set("Supplement", 0);
+ dict.set("CIDSystemInfo", systemInfo);
+ return dict;
+}
+
+;// CONCATENATED MODULE: ./src/core/ps_parser.js
+
+
+
+class PostScriptParser {
+ constructor(lexer) {
+ this.lexer = lexer;
+ this.operators = [];
+ this.token = null;
+ this.prev = null;
+ }
+ nextToken() {
+ this.prev = this.token;
+ this.token = this.lexer.getToken();
+ }
+ accept(type) {
+ if (this.token.type === type) {
+ this.nextToken();
+ return true;
+ }
+ return false;
+ }
+ expect(type) {
+ if (this.accept(type)) {
+ return true;
+ }
+ throw new FormatError(`Unexpected symbol: found ${this.token.type} expected ${type}.`);
+ }
+ parse() {
+ this.nextToken();
+ this.expect(PostScriptTokenTypes.LBRACE);
+ this.parseBlock();
+ this.expect(PostScriptTokenTypes.RBRACE);
+ return this.operators;
+ }
+ parseBlock() {
+ while (true) {
+ if (this.accept(PostScriptTokenTypes.NUMBER)) {
+ this.operators.push(this.prev.value);
+ } else if (this.accept(PostScriptTokenTypes.OPERATOR)) {
+ this.operators.push(this.prev.value);
+ } else if (this.accept(PostScriptTokenTypes.LBRACE)) {
+ this.parseCondition();
+ } else {
+ return;
+ }
+ }
+ }
+ parseCondition() {
+ const conditionLocation = this.operators.length;
+ this.operators.push(null, null);
+ this.parseBlock();
+ this.expect(PostScriptTokenTypes.RBRACE);
+ if (this.accept(PostScriptTokenTypes.IF)) {
+ this.operators[conditionLocation] = this.operators.length;
+ this.operators[conditionLocation + 1] = "jz";
+ } else if (this.accept(PostScriptTokenTypes.LBRACE)) {
+ const jumpLocation = this.operators.length;
+ this.operators.push(null, null);
+ const endOfTrue = this.operators.length;
+ this.parseBlock();
+ this.expect(PostScriptTokenTypes.RBRACE);
+ this.expect(PostScriptTokenTypes.IFELSE);
+ this.operators[jumpLocation] = this.operators.length;
+ this.operators[jumpLocation + 1] = "j";
+ this.operators[conditionLocation] = endOfTrue;
+ this.operators[conditionLocation + 1] = "jz";
+ } else {
+ throw new FormatError("PS Function: error parsing conditional.");
+ }
+ }
+}
+const PostScriptTokenTypes = {
+ LBRACE: 0,
+ RBRACE: 1,
+ NUMBER: 2,
+ OPERATOR: 3,
+ IF: 4,
+ IFELSE: 5
+};
+class PostScriptToken {
+ static get opCache() {
+ return shadow(this, "opCache", Object.create(null));
+ }
+ constructor(type, value) {
+ this.type = type;
+ this.value = value;
+ }
+ static getOperator(op) {
+ return PostScriptToken.opCache[op] ||= new PostScriptToken(PostScriptTokenTypes.OPERATOR, op);
+ }
+ static get LBRACE() {
+ return shadow(this, "LBRACE", new PostScriptToken(PostScriptTokenTypes.LBRACE, "{"));
+ }
+ static get RBRACE() {
+ return shadow(this, "RBRACE", new PostScriptToken(PostScriptTokenTypes.RBRACE, "}"));
+ }
+ static get IF() {
+ return shadow(this, "IF", new PostScriptToken(PostScriptTokenTypes.IF, "IF"));
+ }
+ static get IFELSE() {
+ return shadow(this, "IFELSE", new PostScriptToken(PostScriptTokenTypes.IFELSE, "IFELSE"));
+ }
+}
+class PostScriptLexer {
+ constructor(stream) {
+ this.stream = stream;
+ this.nextChar();
+ this.strBuf = [];
+ }
+ nextChar() {
+ return this.currentChar = this.stream.getByte();
+ }
+ getToken() {
+ let comment = false;
+ let ch = this.currentChar;
+ while (true) {
+ if (ch < 0) {
+ return EOF;
+ }
+ if (comment) {
+ if (ch === 0x0a || ch === 0x0d) {
+ comment = false;
+ }
+ } else if (ch === 0x25) {
+ comment = true;
+ } else if (!isWhiteSpace(ch)) {
+ break;
+ }
+ ch = this.nextChar();
+ }
+ switch (ch | 0) {
+ case 0x30:
+ case 0x31:
+ case 0x32:
+ case 0x33:
+ case 0x34:
+ case 0x35:
+ case 0x36:
+ case 0x37:
+ case 0x38:
+ case 0x39:
+ case 0x2b:
+ case 0x2d:
+ case 0x2e:
+ return new PostScriptToken(PostScriptTokenTypes.NUMBER, this.getNumber());
+ case 0x7b:
+ this.nextChar();
+ return PostScriptToken.LBRACE;
+ case 0x7d:
+ this.nextChar();
+ return PostScriptToken.RBRACE;
+ }
+ const strBuf = this.strBuf;
+ strBuf.length = 0;
+ strBuf[0] = String.fromCharCode(ch);
+ while ((ch = this.nextChar()) >= 0 && (ch >= 0x41 && ch <= 0x5a || ch >= 0x61 && ch <= 0x7a)) {
+ strBuf.push(String.fromCharCode(ch));
+ }
+ const str = strBuf.join("");
+ switch (str.toLowerCase()) {
+ case "if":
+ return PostScriptToken.IF;
+ case "ifelse":
+ return PostScriptToken.IFELSE;
+ default:
+ return PostScriptToken.getOperator(str);
+ }
+ }
+ getNumber() {
+ let ch = this.currentChar;
+ const strBuf = this.strBuf;
+ strBuf.length = 0;
+ strBuf[0] = String.fromCharCode(ch);
+ while ((ch = this.nextChar()) >= 0) {
+ if (ch >= 0x30 && ch <= 0x39 || ch === 0x2d || ch === 0x2e) {
+ strBuf.push(String.fromCharCode(ch));
+ } else {
+ break;
+ }
+ }
+ const value = parseFloat(strBuf.join(""));
+ if (isNaN(value)) {
+ throw new FormatError(`Invalid floating point number: ${value}`);
+ }
+ return value;
+ }
+}
+
+;// CONCATENATED MODULE: ./src/core/image_utils.js
+
+
+class BaseLocalCache {
+ constructor(options) {
+ if (this.constructor === BaseLocalCache) {
+ unreachable("Cannot initialize BaseLocalCache.");
+ }
+ this._onlyRefs = options?.onlyRefs === true;
+ if (!this._onlyRefs) {
+ this._nameRefMap = new Map();
+ this._imageMap = new Map();
+ }
+ this._imageCache = new RefSetCache();
+ }
+ getByName(name) {
+ if (this._onlyRefs) {
+ unreachable("Should not call `getByName` method.");
+ }
+ const ref = this._nameRefMap.get(name);
+ if (ref) {
+ return this.getByRef(ref);
+ }
+ return this._imageMap.get(name) || null;
+ }
+ getByRef(ref) {
+ return this._imageCache.get(ref) || null;
+ }
+ set(name, ref, data) {
+ unreachable("Abstract method `set` called.");
+ }
+}
+class LocalImageCache extends BaseLocalCache {
+ set(name, ref = null, data) {
+ if (typeof name !== "string") {
+ throw new Error('LocalImageCache.set - expected "name" argument.');
+ }
+ if (ref) {
+ if (this._imageCache.has(ref)) {
+ return;
+ }
+ this._nameRefMap.set(name, ref);
+ this._imageCache.put(ref, data);
+ return;
+ }
+ if (this._imageMap.has(name)) {
+ return;
+ }
+ this._imageMap.set(name, data);
+ }
+}
+class LocalColorSpaceCache extends BaseLocalCache {
+ set(name = null, ref = null, data) {
+ if (typeof name !== "string" && !ref) {
+ throw new Error('LocalColorSpaceCache.set - expected "name" and/or "ref" argument.');
+ }
+ if (ref) {
+ if (this._imageCache.has(ref)) {
+ return;
+ }
+ if (name !== null) {
+ this._nameRefMap.set(name, ref);
+ }
+ this._imageCache.put(ref, data);
+ return;
+ }
+ if (this._imageMap.has(name)) {
+ return;
+ }
+ this._imageMap.set(name, data);
+ }
+}
+class LocalFunctionCache extends BaseLocalCache {
+ constructor(options) {
+ super({
+ onlyRefs: true
+ });
+ }
+ set(name = null, ref, data) {
+ if (!ref) {
+ throw new Error('LocalFunctionCache.set - expected "ref" argument.');
+ }
+ if (this._imageCache.has(ref)) {
+ return;
+ }
+ this._imageCache.put(ref, data);
+ }
+}
+class LocalGStateCache extends BaseLocalCache {
+ set(name, ref = null, data) {
+ if (typeof name !== "string") {
+ throw new Error('LocalGStateCache.set - expected "name" argument.');
+ }
+ if (ref) {
+ if (this._imageCache.has(ref)) {
+ return;
+ }
+ this._nameRefMap.set(name, ref);
+ this._imageCache.put(ref, data);
+ return;
+ }
+ if (this._imageMap.has(name)) {
+ return;
+ }
+ this._imageMap.set(name, data);
+ }
+}
+class LocalTilingPatternCache extends BaseLocalCache {
+ constructor(options) {
+ super({
+ onlyRefs: true
+ });
+ }
+ set(name = null, ref, data) {
+ if (!ref) {
+ throw new Error('LocalTilingPatternCache.set - expected "ref" argument.');
+ }
+ if (this._imageCache.has(ref)) {
+ return;
+ }
+ this._imageCache.put(ref, data);
+ }
+}
+class RegionalImageCache extends BaseLocalCache {
+ constructor(options) {
+ super({
+ onlyRefs: true
+ });
+ }
+ set(name = null, ref, data) {
+ if (!ref) {
+ throw new Error('RegionalImageCache.set - expected "ref" argument.');
+ }
+ if (this._imageCache.has(ref)) {
+ return;
+ }
+ this._imageCache.put(ref, data);
+ }
+}
+class GlobalImageCache {
+ static NUM_PAGES_THRESHOLD = 2;
+ static MIN_IMAGES_TO_CACHE = 10;
+ static MAX_BYTE_SIZE = 5 * MAX_IMAGE_SIZE_TO_CACHE;
+ constructor() {
+ this._refCache = new RefSetCache();
+ this._imageCache = new RefSetCache();
+ }
+ get _byteSize() {
+ let byteSize = 0;
+ for (const imageData of this._imageCache) {
+ byteSize += imageData.byteSize;
+ }
+ return byteSize;
+ }
+ get _cacheLimitReached() {
+ if (this._imageCache.size < GlobalImageCache.MIN_IMAGES_TO_CACHE) {
+ return false;
+ }
+ if (this._byteSize < GlobalImageCache.MAX_BYTE_SIZE) {
+ return false;
+ }
+ return true;
+ }
+ shouldCache(ref, pageIndex) {
+ let pageIndexSet = this._refCache.get(ref);
+ if (!pageIndexSet) {
+ pageIndexSet = new Set();
+ this._refCache.put(ref, pageIndexSet);
+ }
+ pageIndexSet.add(pageIndex);
+ if (pageIndexSet.size < GlobalImageCache.NUM_PAGES_THRESHOLD) {
+ return false;
+ }
+ if (!this._imageCache.has(ref) && this._cacheLimitReached) {
+ return false;
+ }
+ return true;
+ }
+ addByteSize(ref, byteSize) {
+ const imageData = this._imageCache.get(ref);
+ if (!imageData) {
+ return;
+ }
+ if (imageData.byteSize) {
+ return;
+ }
+ imageData.byteSize = byteSize;
+ }
+ getData(ref, pageIndex) {
+ const pageIndexSet = this._refCache.get(ref);
+ if (!pageIndexSet) {
+ return null;
+ }
+ if (pageIndexSet.size < GlobalImageCache.NUM_PAGES_THRESHOLD) {
+ return null;
+ }
+ const imageData = this._imageCache.get(ref);
+ if (!imageData) {
+ return null;
+ }
+ pageIndexSet.add(pageIndex);
+ return imageData;
+ }
+ setData(ref, data) {
+ if (!this._refCache.has(ref)) {
+ throw new Error('GlobalImageCache.setData - expected "shouldCache" to have been called.');
+ }
+ if (this._imageCache.has(ref)) {
+ return;
+ }
+ if (this._cacheLimitReached) {
+ warn("GlobalImageCache.setData - cache limit reached.");
+ return;
+ }
+ this._imageCache.put(ref, data);
+ }
+ clear(onlyData = false) {
+ if (!onlyData) {
+ this._refCache.clear();
+ }
+ this._imageCache.clear();
+ }
+}
+
+;// CONCATENATED MODULE: ./src/core/function.js
+
+
+
+
+
+class PDFFunctionFactory {
+ constructor({
+ xref,
+ isEvalSupported = true
+ }) {
+ this.xref = xref;
+ this.isEvalSupported = isEvalSupported !== false;
+ }
+ create(fn) {
+ const cachedFunction = this.getCached(fn);
+ if (cachedFunction) {
+ return cachedFunction;
+ }
+ const parsedFunction = PDFFunction.parse({
+ xref: this.xref,
+ isEvalSupported: this.isEvalSupported,
+ fn: fn instanceof Ref ? this.xref.fetch(fn) : fn
+ });
+ this._cache(fn, parsedFunction);
+ return parsedFunction;
+ }
+ createFromArray(fnObj) {
+ const cachedFunction = this.getCached(fnObj);
+ if (cachedFunction) {
+ return cachedFunction;
+ }
+ const parsedFunction = PDFFunction.parseArray({
+ xref: this.xref,
+ isEvalSupported: this.isEvalSupported,
+ fnObj: fnObj instanceof Ref ? this.xref.fetch(fnObj) : fnObj
+ });
+ this._cache(fnObj, parsedFunction);
+ return parsedFunction;
+ }
+ getCached(cacheKey) {
+ let fnRef;
+ if (cacheKey instanceof Ref) {
+ fnRef = cacheKey;
+ } else if (cacheKey instanceof Dict) {
+ fnRef = cacheKey.objId;
+ } else if (cacheKey instanceof BaseStream) {
+ fnRef = cacheKey.dict?.objId;
+ }
+ if (fnRef) {
+ const localFunction = this._localFunctionCache.getByRef(fnRef);
+ if (localFunction) {
+ return localFunction;
+ }
+ }
+ return null;
+ }
+ _cache(cacheKey, parsedFunction) {
+ if (!parsedFunction) {
+ throw new Error('PDFFunctionFactory._cache - expected "parsedFunction" argument.');
+ }
+ let fnRef;
+ if (cacheKey instanceof Ref) {
+ fnRef = cacheKey;
+ } else if (cacheKey instanceof Dict) {
+ fnRef = cacheKey.objId;
+ } else if (cacheKey instanceof BaseStream) {
+ fnRef = cacheKey.dict?.objId;
+ }
+ if (fnRef) {
+ this._localFunctionCache.set(null, fnRef, parsedFunction);
+ }
+ }
+ get _localFunctionCache() {
+ return shadow(this, "_localFunctionCache", new LocalFunctionCache());
+ }
+}
+function toNumberArray(arr) {
+ if (!Array.isArray(arr)) {
+ return null;
+ }
+ const length = arr.length;
+ for (let i = 0; i < length; i++) {
+ if (typeof arr[i] !== "number") {
+ const result = new Array(length);
+ for (let j = 0; j < length; j++) {
+ result[j] = +arr[j];
+ }
+ return result;
+ }
+ }
+ return arr;
+}
+class PDFFunction {
+ static getSampleArray(size, outputSize, bps, stream) {
+ let i, ii;
+ let length = 1;
+ for (i = 0, ii = size.length; i < ii; i++) {
+ length *= size[i];
+ }
+ length *= outputSize;
+ const array = new Array(length);
+ let codeSize = 0;
+ let codeBuf = 0;
+ const sampleMul = 1.0 / (2.0 ** bps - 1);
+ const strBytes = stream.getBytes((length * bps + 7) / 8);
+ let strIdx = 0;
+ for (i = 0; i < length; i++) {
+ while (codeSize < bps) {
+ codeBuf <<= 8;
+ codeBuf |= strBytes[strIdx++];
+ codeSize += 8;
+ }
+ codeSize -= bps;
+ array[i] = (codeBuf >> codeSize) * sampleMul;
+ codeBuf &= (1 << codeSize) - 1;
+ }
+ return array;
+ }
+ static parse({
+ xref,
+ isEvalSupported,
+ fn
+ }) {
+ const dict = fn.dict || fn;
+ const typeNum = dict.get("FunctionType");
+ switch (typeNum) {
+ case 0:
+ return this.constructSampled({
+ xref,
+ isEvalSupported,
+ fn,
+ dict
+ });
+ case 1:
+ break;
+ case 2:
+ return this.constructInterpolated({
+ xref,
+ isEvalSupported,
+ dict
+ });
+ case 3:
+ return this.constructStiched({
+ xref,
+ isEvalSupported,
+ dict
+ });
+ case 4:
+ return this.constructPostScript({
+ xref,
+ isEvalSupported,
+ fn,
+ dict
+ });
+ }
+ throw new FormatError("Unknown type of function");
+ }
+ static parseArray({
+ xref,
+ isEvalSupported,
+ fnObj
+ }) {
+ if (!Array.isArray(fnObj)) {
+ return this.parse({
+ xref,
+ isEvalSupported,
+ fn: fnObj
+ });
+ }
+ const fnArray = [];
+ for (const fn of fnObj) {
+ fnArray.push(this.parse({
+ xref,
+ isEvalSupported,
+ fn: xref.fetchIfRef(fn)
+ }));
+ }
+ return function (src, srcOffset, dest, destOffset) {
+ for (let i = 0, ii = fnArray.length; i < ii; i++) {
+ fnArray[i](src, srcOffset, dest, destOffset + i);
+ }
+ };
+ }
+ static constructSampled({
+ xref,
+ isEvalSupported,
+ fn,
+ dict
+ }) {
+ function toMultiArray(arr) {
+ const inputLength = arr.length;
+ const out = [];
+ let index = 0;
+ for (let i = 0; i < inputLength; i += 2) {
+ out[index++] = [arr[i], arr[i + 1]];
+ }
+ return out;
+ }
+ function interpolate(x, xmin, xmax, ymin, ymax) {
+ return ymin + (x - xmin) * ((ymax - ymin) / (xmax - xmin));
+ }
+ let domain = toNumberArray(dict.getArray("Domain"));
+ let range = toNumberArray(dict.getArray("Range"));
+ if (!domain || !range) {
+ throw new FormatError("No domain or range");
+ }
+ const inputSize = domain.length / 2;
+ const outputSize = range.length / 2;
+ domain = toMultiArray(domain);
+ range = toMultiArray(range);
+ const size = toNumberArray(dict.getArray("Size"));
+ const bps = dict.get("BitsPerSample");
+ const order = dict.get("Order") || 1;
+ if (order !== 1) {
+ info("No support for cubic spline interpolation: " + order);
+ }
+ let encode = toNumberArray(dict.getArray("Encode"));
+ if (!encode) {
+ encode = [];
+ for (let i = 0; i < inputSize; ++i) {
+ encode.push([0, size[i] - 1]);
+ }
+ } else {
+ encode = toMultiArray(encode);
+ }
+ let decode = toNumberArray(dict.getArray("Decode"));
+ decode = !decode ? range : toMultiArray(decode);
+ const samples = this.getSampleArray(size, outputSize, bps, fn);
+ return function constructSampledFn(src, srcOffset, dest, destOffset) {
+ const cubeVertices = 1 << inputSize;
+ const cubeN = new Float64Array(cubeVertices);
+ const cubeVertex = new Uint32Array(cubeVertices);
+ let i, j;
+ for (j = 0; j < cubeVertices; j++) {
+ cubeN[j] = 1;
+ }
+ let k = outputSize,
+ pos = 1;
+ for (i = 0; i < inputSize; ++i) {
+ const domain_2i = domain[i][0];
+ const domain_2i_1 = domain[i][1];
+ const xi = Math.min(Math.max(src[srcOffset + i], domain_2i), domain_2i_1);
+ let e = interpolate(xi, domain_2i, domain_2i_1, encode[i][0], encode[i][1]);
+ const size_i = size[i];
+ e = Math.min(Math.max(e, 0), size_i - 1);
+ const e0 = e < size_i - 1 ? Math.floor(e) : e - 1;
+ const n0 = e0 + 1 - e;
+ const n1 = e - e0;
+ const offset0 = e0 * k;
+ const offset1 = offset0 + k;
+ for (j = 0; j < cubeVertices; j++) {
+ if (j & pos) {
+ cubeN[j] *= n1;
+ cubeVertex[j] += offset1;
+ } else {
+ cubeN[j] *= n0;
+ cubeVertex[j] += offset0;
+ }
+ }
+ k *= size_i;
+ pos <<= 1;
+ }
+ for (j = 0; j < outputSize; ++j) {
+ let rj = 0;
+ for (i = 0; i < cubeVertices; i++) {
+ rj += samples[cubeVertex[i] + j] * cubeN[i];
+ }
+ rj = interpolate(rj, 0, 1, decode[j][0], decode[j][1]);
+ dest[destOffset + j] = Math.min(Math.max(rj, range[j][0]), range[j][1]);
+ }
+ };
+ }
+ static constructInterpolated({
+ xref,
+ isEvalSupported,
+ dict
+ }) {
+ const c0 = toNumberArray(dict.getArray("C0")) || [0];
+ const c1 = toNumberArray(dict.getArray("C1")) || [1];
+ const n = dict.get("N");
+ const diff = [];
+ for (let i = 0, ii = c0.length; i < ii; ++i) {
+ diff.push(c1[i] - c0[i]);
+ }
+ const length = diff.length;
+ return function constructInterpolatedFn(src, srcOffset, dest, destOffset) {
+ const x = n === 1 ? src[srcOffset] : src[srcOffset] ** n;
+ for (let j = 0; j < length; ++j) {
+ dest[destOffset + j] = c0[j] + x * diff[j];
+ }
+ };
+ }
+ static constructStiched({
+ xref,
+ isEvalSupported,
+ dict
+ }) {
+ const domain = toNumberArray(dict.getArray("Domain"));
+ if (!domain) {
+ throw new FormatError("No domain");
+ }
+ const inputSize = domain.length / 2;
+ if (inputSize !== 1) {
+ throw new FormatError("Bad domain for stiched function");
+ }
+ const fns = [];
+ for (const fn of dict.get("Functions")) {
+ fns.push(this.parse({
+ xref,
+ isEvalSupported,
+ fn: xref.fetchIfRef(fn)
+ }));
+ }
+ const bounds = toNumberArray(dict.getArray("Bounds"));
+ const encode = toNumberArray(dict.getArray("Encode"));
+ const tmpBuf = new Float32Array(1);
+ return function constructStichedFn(src, srcOffset, dest, destOffset) {
+ const clip = function constructStichedFromIRClip(v, min, max) {
+ if (v > max) {
+ v = max;
+ } else if (v < min) {
+ v = min;
+ }
+ return v;
+ };
+ const v = clip(src[srcOffset], domain[0], domain[1]);
+ const length = bounds.length;
+ let i;
+ for (i = 0; i < length; ++i) {
+ if (v < bounds[i]) {
+ break;
+ }
+ }
+ let dmin = domain[0];
+ if (i > 0) {
+ dmin = bounds[i - 1];
+ }
+ let dmax = domain[1];
+ if (i < bounds.length) {
+ dmax = bounds[i];
+ }
+ const rmin = encode[2 * i];
+ const rmax = encode[2 * i + 1];
+ tmpBuf[0] = dmin === dmax ? rmin : rmin + (v - dmin) * (rmax - rmin) / (dmax - dmin);
+ fns[i](tmpBuf, 0, dest, destOffset);
+ };
+ }
+ static constructPostScript({
+ xref,
+ isEvalSupported,
+ fn,
+ dict
+ }) {
+ const domain = toNumberArray(dict.getArray("Domain"));
+ const range = toNumberArray(dict.getArray("Range"));
+ if (!domain) {
+ throw new FormatError("No domain.");
+ }
+ if (!range) {
+ throw new FormatError("No range.");
+ }
+ const lexer = new PostScriptLexer(fn);
+ const parser = new PostScriptParser(lexer);
+ const code = parser.parse();
+ if (isEvalSupported && FeatureTest.isEvalSupported) {
+ const compiled = new PostScriptCompiler().compile(code, domain, range);
+ if (compiled) {
+ return new Function("src", "srcOffset", "dest", "destOffset", compiled);
+ }
+ }
+ info("Unable to compile PS function");
+ const numOutputs = range.length >> 1;
+ const numInputs = domain.length >> 1;
+ const evaluator = new PostScriptEvaluator(code);
+ const cache = Object.create(null);
+ const MAX_CACHE_SIZE = 2048 * 4;
+ let cache_available = MAX_CACHE_SIZE;
+ const tmpBuf = new Float32Array(numInputs);
+ return function constructPostScriptFn(src, srcOffset, dest, destOffset) {
+ let i, value;
+ let key = "";
+ const input = tmpBuf;
+ for (i = 0; i < numInputs; i++) {
+ value = src[srcOffset + i];
+ input[i] = value;
+ key += value + "_";
+ }
+ const cachedValue = cache[key];
+ if (cachedValue !== undefined) {
+ dest.set(cachedValue, destOffset);
+ return;
+ }
+ const output = new Float32Array(numOutputs);
+ const stack = evaluator.execute(input);
+ const stackIndex = stack.length - numOutputs;
+ for (i = 0; i < numOutputs; i++) {
+ value = stack[stackIndex + i];
+ let bound = range[i * 2];
+ if (value < bound) {
+ value = bound;
+ } else {
+ bound = range[i * 2 + 1];
+ if (value > bound) {
+ value = bound;
+ }
+ }
+ output[i] = value;
+ }
+ if (cache_available > 0) {
+ cache_available--;
+ cache[key] = output;
+ }
+ dest.set(output, destOffset);
+ };
+ }
+}
+function isPDFFunction(v) {
+ let fnDict;
+ if (v instanceof Dict) {
+ fnDict = v;
+ } else if (v instanceof BaseStream) {
+ fnDict = v.dict;
+ } else {
+ return false;
+ }
+ return fnDict.has("FunctionType");
+}
+class PostScriptStack {
+ static MAX_STACK_SIZE = 100;
+ constructor(initialStack) {
+ this.stack = initialStack ? Array.from(initialStack) : [];
+ }
+ push(value) {
+ if (this.stack.length >= PostScriptStack.MAX_STACK_SIZE) {
+ throw new Error("PostScript function stack overflow.");
+ }
+ this.stack.push(value);
+ }
+ pop() {
+ if (this.stack.length <= 0) {
+ throw new Error("PostScript function stack underflow.");
+ }
+ return this.stack.pop();
+ }
+ copy(n) {
+ if (this.stack.length + n >= PostScriptStack.MAX_STACK_SIZE) {
+ throw new Error("PostScript function stack overflow.");
+ }
+ const stack = this.stack;
+ for (let i = stack.length - n, j = n - 1; j >= 0; j--, i++) {
+ stack.push(stack[i]);
+ }
+ }
+ index(n) {
+ this.push(this.stack[this.stack.length - n - 1]);
+ }
+ roll(n, p) {
+ const stack = this.stack;
+ const l = stack.length - n;
+ const r = stack.length - 1;
+ const c = l + (p - Math.floor(p / n) * n);
+ for (let i = l, j = r; i < j; i++, j--) {
+ const t = stack[i];
+ stack[i] = stack[j];
+ stack[j] = t;
+ }
+ for (let i = l, j = c - 1; i < j; i++, j--) {
+ const t = stack[i];
+ stack[i] = stack[j];
+ stack[j] = t;
+ }
+ for (let i = c, j = r; i < j; i++, j--) {
+ const t = stack[i];
+ stack[i] = stack[j];
+ stack[j] = t;
+ }
+ }
+}
+class PostScriptEvaluator {
+ constructor(operators) {
+ this.operators = operators;
+ }
+ execute(initialStack) {
+ const stack = new PostScriptStack(initialStack);
+ let counter = 0;
+ const operators = this.operators;
+ const length = operators.length;
+ let operator, a, b;
+ while (counter < length) {
+ operator = operators[counter++];
+ if (typeof operator === "number") {
+ stack.push(operator);
+ continue;
+ }
+ switch (operator) {
+ case "jz":
+ b = stack.pop();
+ a = stack.pop();
+ if (!a) {
+ counter = b;
+ }
+ break;
+ case "j":
+ a = stack.pop();
+ counter = a;
+ break;
+ case "abs":
+ a = stack.pop();
+ stack.push(Math.abs(a));
+ break;
+ case "add":
+ b = stack.pop();
+ a = stack.pop();
+ stack.push(a + b);
+ break;
+ case "and":
+ b = stack.pop();
+ a = stack.pop();
+ if (typeof a === "boolean" && typeof b === "boolean") {
+ stack.push(a && b);
+ } else {
+ stack.push(a & b);
+ }
+ break;
+ case "atan":
+ b = stack.pop();
+ a = stack.pop();
+ a = Math.atan2(a, b) / Math.PI * 180;
+ if (a < 0) {
+ a += 360;
+ }
+ stack.push(a);
+ break;
+ case "bitshift":
+ b = stack.pop();
+ a = stack.pop();
+ if (a > 0) {
+ stack.push(a << b);
+ } else {
+ stack.push(a >> b);
+ }
+ break;
+ case "ceiling":
+ a = stack.pop();
+ stack.push(Math.ceil(a));
+ break;
+ case "copy":
+ a = stack.pop();
+ stack.copy(a);
+ break;
+ case "cos":
+ a = stack.pop();
+ stack.push(Math.cos(a % 360 / 180 * Math.PI));
+ break;
+ case "cvi":
+ a = stack.pop() | 0;
+ stack.push(a);
+ break;
+ case "cvr":
+ break;
+ case "div":
+ b = stack.pop();
+ a = stack.pop();
+ stack.push(a / b);
+ break;
+ case "dup":
+ stack.copy(1);
+ break;
+ case "eq":
+ b = stack.pop();
+ a = stack.pop();
+ stack.push(a === b);
+ break;
+ case "exch":
+ stack.roll(2, 1);
+ break;
+ case "exp":
+ b = stack.pop();
+ a = stack.pop();
+ stack.push(a ** b);
+ break;
+ case "false":
+ stack.push(false);
+ break;
+ case "floor":
+ a = stack.pop();
+ stack.push(Math.floor(a));
+ break;
+ case "ge":
+ b = stack.pop();
+ a = stack.pop();
+ stack.push(a >= b);
+ break;
+ case "gt":
+ b = stack.pop();
+ a = stack.pop();
+ stack.push(a > b);
+ break;
+ case "idiv":
+ b = stack.pop();
+ a = stack.pop();
+ stack.push(a / b | 0);
+ break;
+ case "index":
+ a = stack.pop();
+ stack.index(a);
+ break;
+ case "le":
+ b = stack.pop();
+ a = stack.pop();
+ stack.push(a <= b);
+ break;
+ case "ln":
+ a = stack.pop();
+ stack.push(Math.log(a));
+ break;
+ case "log":
+ a = stack.pop();
+ stack.push(Math.log10(a));
+ break;
+ case "lt":
+ b = stack.pop();
+ a = stack.pop();
+ stack.push(a < b);
+ break;
+ case "mod":
+ b = stack.pop();
+ a = stack.pop();
+ stack.push(a % b);
+ break;
+ case "mul":
+ b = stack.pop();
+ a = stack.pop();
+ stack.push(a * b);
+ break;
+ case "ne":
+ b = stack.pop();
+ a = stack.pop();
+ stack.push(a !== b);
+ break;
+ case "neg":
+ a = stack.pop();
+ stack.push(-a);
+ break;
+ case "not":
+ a = stack.pop();
+ if (typeof a === "boolean") {
+ stack.push(!a);
+ } else {
+ stack.push(~a);
+ }
+ break;
+ case "or":
+ b = stack.pop();
+ a = stack.pop();
+ if (typeof a === "boolean" && typeof b === "boolean") {
+ stack.push(a || b);
+ } else {
+ stack.push(a | b);
+ }
+ break;
+ case "pop":
+ stack.pop();
+ break;
+ case "roll":
+ b = stack.pop();
+ a = stack.pop();
+ stack.roll(a, b);
+ break;
+ case "round":
+ a = stack.pop();
+ stack.push(Math.round(a));
+ break;
+ case "sin":
+ a = stack.pop();
+ stack.push(Math.sin(a % 360 / 180 * Math.PI));
+ break;
+ case "sqrt":
+ a = stack.pop();
+ stack.push(Math.sqrt(a));
+ break;
+ case "sub":
+ b = stack.pop();
+ a = stack.pop();
+ stack.push(a - b);
+ break;
+ case "true":
+ stack.push(true);
+ break;
+ case "truncate":
+ a = stack.pop();
+ a = a < 0 ? Math.ceil(a) : Math.floor(a);
+ stack.push(a);
+ break;
+ case "xor":
+ b = stack.pop();
+ a = stack.pop();
+ if (typeof a === "boolean" && typeof b === "boolean") {
+ stack.push(a !== b);
+ } else {
+ stack.push(a ^ b);
+ }
+ break;
+ default:
+ throw new FormatError(`Unknown operator ${operator}`);
+ }
+ }
+ return stack.stack;
+ }
+}
+class AstNode {
+ constructor(type) {
+ this.type = type;
+ }
+ visit(visitor) {
+ unreachable("abstract method");
+ }
+}
+class AstArgument extends AstNode {
+ constructor(index, min, max) {
+ super("args");
+ this.index = index;
+ this.min = min;
+ this.max = max;
+ }
+ visit(visitor) {
+ visitor.visitArgument(this);
+ }
+}
+class AstLiteral extends AstNode {
+ constructor(number) {
+ super("literal");
+ this.number = number;
+ this.min = number;
+ this.max = number;
+ }
+ visit(visitor) {
+ visitor.visitLiteral(this);
+ }
+}
+class AstBinaryOperation extends AstNode {
+ constructor(op, arg1, arg2, min, max) {
+ super("binary");
+ this.op = op;
+ this.arg1 = arg1;
+ this.arg2 = arg2;
+ this.min = min;
+ this.max = max;
+ }
+ visit(visitor) {
+ visitor.visitBinaryOperation(this);
+ }
+}
+class AstMin extends AstNode {
+ constructor(arg, max) {
+ super("max");
+ this.arg = arg;
+ this.min = arg.min;
+ this.max = max;
+ }
+ visit(visitor) {
+ visitor.visitMin(this);
+ }
+}
+class AstVariable extends AstNode {
+ constructor(index, min, max) {
+ super("var");
+ this.index = index;
+ this.min = min;
+ this.max = max;
+ }
+ visit(visitor) {
+ visitor.visitVariable(this);
+ }
+}
+class AstVariableDefinition extends AstNode {
+ constructor(variable, arg) {
+ super("definition");
+ this.variable = variable;
+ this.arg = arg;
+ }
+ visit(visitor) {
+ visitor.visitVariableDefinition(this);
+ }
+}
+class ExpressionBuilderVisitor {
+ constructor() {
+ this.parts = [];
+ }
+ visitArgument(arg) {
+ this.parts.push("Math.max(", arg.min, ", Math.min(", arg.max, ", src[srcOffset + ", arg.index, "]))");
+ }
+ visitVariable(variable) {
+ this.parts.push("v", variable.index);
+ }
+ visitLiteral(literal) {
+ this.parts.push(literal.number);
+ }
+ visitBinaryOperation(operation) {
+ this.parts.push("(");
+ operation.arg1.visit(this);
+ this.parts.push(" ", operation.op, " ");
+ operation.arg2.visit(this);
+ this.parts.push(")");
+ }
+ visitVariableDefinition(definition) {
+ this.parts.push("var ");
+ definition.variable.visit(this);
+ this.parts.push(" = ");
+ definition.arg.visit(this);
+ this.parts.push(";");
+ }
+ visitMin(max) {
+ this.parts.push("Math.min(");
+ max.arg.visit(this);
+ this.parts.push(", ", max.max, ")");
+ }
+ toString() {
+ return this.parts.join("");
+ }
+}
+function buildAddOperation(num1, num2) {
+ if (num2.type === "literal" && num2.number === 0) {
+ return num1;
+ }
+ if (num1.type === "literal" && num1.number === 0) {
+ return num2;
+ }
+ if (num2.type === "literal" && num1.type === "literal") {
+ return new AstLiteral(num1.number + num2.number);
+ }
+ return new AstBinaryOperation("+", num1, num2, num1.min + num2.min, num1.max + num2.max);
+}
+function buildMulOperation(num1, num2) {
+ if (num2.type === "literal") {
+ if (num2.number === 0) {
+ return new AstLiteral(0);
+ } else if (num2.number === 1) {
+ return num1;
+ } else if (num1.type === "literal") {
+ return new AstLiteral(num1.number * num2.number);
+ }
+ }
+ if (num1.type === "literal") {
+ if (num1.number === 0) {
+ return new AstLiteral(0);
+ } else if (num1.number === 1) {
+ return num2;
+ }
+ }
+ const min = Math.min(num1.min * num2.min, num1.min * num2.max, num1.max * num2.min, num1.max * num2.max);
+ const max = Math.max(num1.min * num2.min, num1.min * num2.max, num1.max * num2.min, num1.max * num2.max);
+ return new AstBinaryOperation("*", num1, num2, min, max);
+}
+function buildSubOperation(num1, num2) {
+ if (num2.type === "literal") {
+ if (num2.number === 0) {
+ return num1;
+ } else if (num1.type === "literal") {
+ return new AstLiteral(num1.number - num2.number);
+ }
+ }
+ if (num2.type === "binary" && num2.op === "-" && num1.type === "literal" && num1.number === 1 && num2.arg1.type === "literal" && num2.arg1.number === 1) {
+ return num2.arg2;
+ }
+ return new AstBinaryOperation("-", num1, num2, num1.min - num2.max, num1.max - num2.min);
+}
+function buildMinOperation(num1, max) {
+ if (num1.min >= max) {
+ return new AstLiteral(max);
+ } else if (num1.max <= max) {
+ return num1;
+ }
+ return new AstMin(num1, max);
+}
+class PostScriptCompiler {
+ compile(code, domain, range) {
+ const stack = [];
+ const instructions = [];
+ const inputSize = domain.length >> 1,
+ outputSize = range.length >> 1;
+ let lastRegister = 0;
+ let n, j;
+ let num1, num2, ast1, ast2, tmpVar, item;
+ for (let i = 0; i < inputSize; i++) {
+ stack.push(new AstArgument(i, domain[i * 2], domain[i * 2 + 1]));
+ }
+ for (let i = 0, ii = code.length; i < ii; i++) {
+ item = code[i];
+ if (typeof item === "number") {
+ stack.push(new AstLiteral(item));
+ continue;
+ }
+ switch (item) {
+ case "add":
+ if (stack.length < 2) {
+ return null;
+ }
+ num2 = stack.pop();
+ num1 = stack.pop();
+ stack.push(buildAddOperation(num1, num2));
+ break;
+ case "cvr":
+ if (stack.length < 1) {
+ return null;
+ }
+ break;
+ case "mul":
+ if (stack.length < 2) {
+ return null;
+ }
+ num2 = stack.pop();
+ num1 = stack.pop();
+ stack.push(buildMulOperation(num1, num2));
+ break;
+ case "sub":
+ if (stack.length < 2) {
+ return null;
+ }
+ num2 = stack.pop();
+ num1 = stack.pop();
+ stack.push(buildSubOperation(num1, num2));
+ break;
+ case "exch":
+ if (stack.length < 2) {
+ return null;
+ }
+ ast1 = stack.pop();
+ ast2 = stack.pop();
+ stack.push(ast1, ast2);
+ break;
+ case "pop":
+ if (stack.length < 1) {
+ return null;
+ }
+ stack.pop();
+ break;
+ case "index":
+ if (stack.length < 1) {
+ return null;
+ }
+ num1 = stack.pop();
+ if (num1.type !== "literal") {
+ return null;
+ }
+ n = num1.number;
+ if (n < 0 || !Number.isInteger(n) || stack.length < n) {
+ return null;
+ }
+ ast1 = stack[stack.length - n - 1];
+ if (ast1.type === "literal" || ast1.type === "var") {
+ stack.push(ast1);
+ break;
+ }
+ tmpVar = new AstVariable(lastRegister++, ast1.min, ast1.max);
+ stack[stack.length - n - 1] = tmpVar;
+ stack.push(tmpVar);
+ instructions.push(new AstVariableDefinition(tmpVar, ast1));
+ break;
+ case "dup":
+ if (stack.length < 1) {
+ return null;
+ }
+ if (typeof code[i + 1] === "number" && code[i + 2] === "gt" && code[i + 3] === i + 7 && code[i + 4] === "jz" && code[i + 5] === "pop" && code[i + 6] === code[i + 1]) {
+ num1 = stack.pop();
+ stack.push(buildMinOperation(num1, code[i + 1]));
+ i += 6;
+ break;
+ }
+ ast1 = stack.at(-1);
+ if (ast1.type === "literal" || ast1.type === "var") {
+ stack.push(ast1);
+ break;
+ }
+ tmpVar = new AstVariable(lastRegister++, ast1.min, ast1.max);
+ stack[stack.length - 1] = tmpVar;
+ stack.push(tmpVar);
+ instructions.push(new AstVariableDefinition(tmpVar, ast1));
+ break;
+ case "roll":
+ if (stack.length < 2) {
+ return null;
+ }
+ num2 = stack.pop();
+ num1 = stack.pop();
+ if (num2.type !== "literal" || num1.type !== "literal") {
+ return null;
+ }
+ j = num2.number;
+ n = num1.number;
+ if (n <= 0 || !Number.isInteger(n) || !Number.isInteger(j) || stack.length < n) {
+ return null;
+ }
+ j = (j % n + n) % n;
+ if (j === 0) {
+ break;
+ }
+ stack.push(...stack.splice(stack.length - n, n - j));
+ break;
+ default:
+ return null;
+ }
+ }
+ if (stack.length !== outputSize) {
+ return null;
+ }
+ const result = [];
+ for (const instruction of instructions) {
+ const statementBuilder = new ExpressionBuilderVisitor();
+ instruction.visit(statementBuilder);
+ result.push(statementBuilder.toString());
+ }
+ for (let i = 0, ii = stack.length; i < ii; i++) {
+ const expr = stack[i],
+ statementBuilder = new ExpressionBuilderVisitor();
+ expr.visit(statementBuilder);
+ const min = range[i * 2],
+ max = range[i * 2 + 1];
+ const out = [statementBuilder.toString()];
+ if (min > expr.min) {
+ out.unshift("Math.max(", min, ", ");
+ out.push(")");
+ }
+ if (max < expr.max) {
+ out.unshift("Math.min(", max, ", ");
+ out.push(")");
+ }
+ out.unshift("dest[destOffset + ", i, "] = ");
+ out.push(";");
+ result.push(out.join(""));
+ }
+ return result.join("\n");
+ }
+}
+
+;// CONCATENATED MODULE: ./src/core/bidi.js
+
+const baseTypes = ["BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "S", "B", "S", "WS", "B", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "B", "B", "B", "S", "WS", "ON", "ON", "ET", "ET", "ET", "ON", "ON", "ON", "ON", "ON", "ES", "CS", "ES", "CS", "CS", "EN", "EN", "EN", "EN", "EN", "EN", "EN", "EN", "EN", "EN", "CS", "ON", "ON", "ON", "ON", "ON", "ON", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "ON", "ON", "ON", "ON", "ON", "ON", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "ON", "ON", "ON", "ON", "BN", "BN", "BN", "BN", "BN", "BN", "B", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "CS", "ON", "ET", "ET", "ET", "ET", "ON", "ON", "ON", "ON", "L", "ON", "ON", "BN", "ON", "ON", "ET", "ET", "EN", "EN", "ON", "L", "ON", "ON", "ON", "EN", "L", "ON", "ON", "ON", "ON", "ON", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "ON", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "ON", "L", "L", "L", "L", "L", "L", "L", "L"];
+const arabicTypes = ["AN", "AN", "AN", "AN", "AN", "AN", "ON", "ON", "AL", "ET", "ET", "AL", "CS", "AL", "ON", "ON", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "AL", "AL", "", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "AN", "AN", "AN", "AN", "AN", "AN", "AN", "AN", "AN", "AN", "ET", "AN", "AN", "AL", "AL", "AL", "NSM", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "AN", "ON", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "AL", "AL", "NSM", "NSM", "ON", "NSM", "NSM", "NSM", "NSM", "AL", "AL", "EN", "EN", "EN", "EN", "EN", "EN", "EN", "EN", "EN", "EN", "AL", "AL", "AL", "AL", "AL", "AL"];
+function isOdd(i) {
+ return (i & 1) !== 0;
+}
+function isEven(i) {
+ return (i & 1) === 0;
+}
+function findUnequal(arr, start, value) {
+ let j, jj;
+ for (j = start, jj = arr.length; j < jj; ++j) {
+ if (arr[j] !== value) {
+ return j;
+ }
+ }
+ return j;
+}
+function setValues(arr, start, end, value) {
+ for (let j = start; j < end; ++j) {
+ arr[j] = value;
+ }
+}
+function reverseValues(arr, start, end) {
+ for (let i = start, j = end - 1; i < j; ++i, --j) {
+ const temp = arr[i];
+ arr[i] = arr[j];
+ arr[j] = temp;
+ }
+}
+function createBidiText(str, isLTR, vertical = false) {
+ let dir = "ltr";
+ if (vertical) {
+ dir = "ttb";
+ } else if (!isLTR) {
+ dir = "rtl";
+ }
+ return {
+ str,
+ dir
+ };
+}
+const chars = [];
+const types = [];
+function bidi(str, startLevel = -1, vertical = false) {
+ let isLTR = true;
+ const strLength = str.length;
+ if (strLength === 0 || vertical) {
+ return createBidiText(str, isLTR, vertical);
+ }
+ chars.length = strLength;
+ types.length = strLength;
+ let numBidi = 0;
+ let i, ii;
+ for (i = 0; i < strLength; ++i) {
+ chars[i] = str.charAt(i);
+ const charCode = str.charCodeAt(i);
+ let charType = "L";
+ if (charCode <= 0x00ff) {
+ charType = baseTypes[charCode];
+ } else if (0x0590 <= charCode && charCode <= 0x05f4) {
+ charType = "R";
+ } else if (0x0600 <= charCode && charCode <= 0x06ff) {
+ charType = arabicTypes[charCode & 0xff];
+ if (!charType) {
+ warn("Bidi: invalid Unicode character " + charCode.toString(16));
+ }
+ } else if (0x0700 <= charCode && charCode <= 0x08ac || 0xfb50 <= charCode && charCode <= 0xfdff || 0xfe70 <= charCode && charCode <= 0xfeff) {
+ charType = "AL";
+ }
+ if (charType === "R" || charType === "AL" || charType === "AN") {
+ numBidi++;
+ }
+ types[i] = charType;
+ }
+ if (numBidi === 0) {
+ isLTR = true;
+ return createBidiText(str, isLTR);
+ }
+ if (startLevel === -1) {
+ if (numBidi / strLength < 0.3 && strLength > 4) {
+ isLTR = true;
+ startLevel = 0;
+ } else {
+ isLTR = false;
+ startLevel = 1;
+ }
+ }
+ const levels = [];
+ for (i = 0; i < strLength; ++i) {
+ levels[i] = startLevel;
+ }
+ const e = isOdd(startLevel) ? "R" : "L";
+ const sor = e;
+ const eor = sor;
+ let lastType = sor;
+ for (i = 0; i < strLength; ++i) {
+ if (types[i] === "NSM") {
+ types[i] = lastType;
+ } else {
+ lastType = types[i];
+ }
+ }
+ lastType = sor;
+ let t;
+ for (i = 0; i < strLength; ++i) {
+ t = types[i];
+ if (t === "EN") {
+ types[i] = lastType === "AL" ? "AN" : "EN";
+ } else if (t === "R" || t === "L" || t === "AL") {
+ lastType = t;
+ }
+ }
+ for (i = 0; i < strLength; ++i) {
+ t = types[i];
+ if (t === "AL") {
+ types[i] = "R";
+ }
+ }
+ for (i = 1; i < strLength - 1; ++i) {
+ if (types[i] === "ES" && types[i - 1] === "EN" && types[i + 1] === "EN") {
+ types[i] = "EN";
+ }
+ if (types[i] === "CS" && (types[i - 1] === "EN" || types[i - 1] === "AN") && types[i + 1] === types[i - 1]) {
+ types[i] = types[i - 1];
+ }
+ }
+ for (i = 0; i < strLength; ++i) {
+ if (types[i] === "EN") {
+ for (let j = i - 1; j >= 0; --j) {
+ if (types[j] !== "ET") {
+ break;
+ }
+ types[j] = "EN";
+ }
+ for (let j = i + 1; j < strLength; ++j) {
+ if (types[j] !== "ET") {
+ break;
+ }
+ types[j] = "EN";
+ }
+ }
+ }
+ for (i = 0; i < strLength; ++i) {
+ t = types[i];
+ if (t === "WS" || t === "ES" || t === "ET" || t === "CS") {
+ types[i] = "ON";
+ }
+ }
+ lastType = sor;
+ for (i = 0; i < strLength; ++i) {
+ t = types[i];
+ if (t === "EN") {
+ types[i] = lastType === "L" ? "L" : "EN";
+ } else if (t === "R" || t === "L") {
+ lastType = t;
+ }
+ }
+ for (i = 0; i < strLength; ++i) {
+ if (types[i] === "ON") {
+ const end = findUnequal(types, i + 1, "ON");
+ let before = sor;
+ if (i > 0) {
+ before = types[i - 1];
+ }
+ let after = eor;
+ if (end + 1 < strLength) {
+ after = types[end + 1];
+ }
+ if (before !== "L") {
+ before = "R";
+ }
+ if (after !== "L") {
+ after = "R";
+ }
+ if (before === after) {
+ setValues(types, i, end, before);
+ }
+ i = end - 1;
+ }
+ }
+ for (i = 0; i < strLength; ++i) {
+ if (types[i] === "ON") {
+ types[i] = e;
+ }
+ }
+ for (i = 0; i < strLength; ++i) {
+ t = types[i];
+ if (isEven(levels[i])) {
+ if (t === "R") {
+ levels[i] += 1;
+ } else if (t === "AN" || t === "EN") {
+ levels[i] += 2;
+ }
+ } else if (t === "L" || t === "AN" || t === "EN") {
+ levels[i] += 1;
+ }
+ }
+ let highestLevel = -1;
+ let lowestOddLevel = 99;
+ let level;
+ for (i = 0, ii = levels.length; i < ii; ++i) {
+ level = levels[i];
+ if (highestLevel < level) {
+ highestLevel = level;
+ }
+ if (lowestOddLevel > level && isOdd(level)) {
+ lowestOddLevel = level;
+ }
+ }
+ for (level = highestLevel; level >= lowestOddLevel; --level) {
+ let start = -1;
+ for (i = 0, ii = levels.length; i < ii; ++i) {
+ if (levels[i] < level) {
+ if (start >= 0) {
+ reverseValues(chars, start, i);
+ start = -1;
+ }
+ } else if (start < 0) {
+ start = i;
+ }
+ }
+ if (start >= 0) {
+ reverseValues(chars, start, levels.length);
+ }
+ }
+ for (i = 0, ii = chars.length; i < ii; ++i) {
+ const ch = chars[i];
+ if (ch === "<" || ch === ">") {
+ chars[i] = "";
+ }
+ }
+ return createBidiText(chars.join(""), isLTR);
+}
+
+;// CONCATENATED MODULE: ./src/core/font_substitutions.js
+
+
+const NORMAL = {
+ style: "normal",
+ weight: "normal"
+};
+const BOLD = {
+ style: "normal",
+ weight: "bold"
+};
+const ITALIC = {
+ style: "italic",
+ weight: "normal"
+};
+const BOLDITALIC = {
+ style: "italic",
+ weight: "bold"
+};
+const substitutionMap = new Map([["Times-Roman", {
+ local: ["Times New Roman", "Times-Roman", "Times", "Liberation Serif", "Nimbus Roman", "Nimbus Roman L", "Tinos", "Thorndale", "TeX Gyre Termes", "FreeSerif", "Linux Libertine O", "Libertinus Serif", "DejaVu Serif", "Bitstream Vera Serif", "Ubuntu"],
+ style: NORMAL,
+ ultimate: "serif"
+}], ["Times-Bold", {
+ alias: "Times-Roman",
+ style: BOLD,
+ ultimate: "serif"
+}], ["Times-Italic", {
+ alias: "Times-Roman",
+ style: ITALIC,
+ ultimate: "serif"
+}], ["Times-BoldItalic", {
+ alias: "Times-Roman",
+ style: BOLDITALIC,
+ ultimate: "serif"
+}], ["Helvetica", {
+ local: ["Helvetica", "Helvetica Neue", "Arial", "Arial Nova", "Liberation Sans", "Arimo", "Nimbus Sans", "Nimbus Sans L", "A030", "TeX Gyre Heros", "FreeSans", "DejaVu Sans", "Albany", "Bitstream Vera Sans", "Arial Unicode MS", "Microsoft Sans Serif", "Apple Symbols", "Cantarell"],
+ path: "LiberationSans-Regular.ttf",
+ style: NORMAL,
+ ultimate: "sans-serif"
+}], ["Helvetica-Bold", {
+ alias: "Helvetica",
+ path: "LiberationSans-Bold.ttf",
+ style: BOLD,
+ ultimate: "sans-serif"
+}], ["Helvetica-Oblique", {
+ alias: "Helvetica",
+ path: "LiberationSans-Italic.ttf",
+ style: ITALIC,
+ ultimate: "sans-serif"
+}], ["Helvetica-BoldOblique", {
+ alias: "Helvetica",
+ path: "LiberationSans-BoldItalic.ttf",
+ style: BOLDITALIC,
+ ultimate: "sans-serif"
+}], ["Courier", {
+ local: ["Courier", "Courier New", "Liberation Mono", "Nimbus Mono", "Nimbus Mono L", "Cousine", "Cumberland", "TeX Gyre Cursor", "FreeMono", "Linux Libertine Mono O", "Libertinus Mono"],
+ style: NORMAL,
+ ultimate: "monospace"
+}], ["Courier-Bold", {
+ alias: "Courier",
+ style: BOLD,
+ ultimate: "monospace"
+}], ["Courier-Oblique", {
+ alias: "Courier",
+ style: ITALIC,
+ ultimate: "monospace"
+}], ["Courier-BoldOblique", {
+ alias: "Courier",
+ style: BOLDITALIC,
+ ultimate: "monospace"
+}], ["ArialBlack", {
+ local: ["Arial Black"],
+ style: {
+ style: "normal",
+ weight: "900"
+ },
+ fallback: "Helvetica-Bold"
+}], ["ArialBlack-Bold", {
+ alias: "ArialBlack"
+}], ["ArialBlack-Italic", {
+ alias: "ArialBlack",
+ style: {
+ style: "italic",
+ weight: "900"
+ },
+ fallback: "Helvetica-BoldOblique"
+}], ["ArialBlack-BoldItalic", {
+ alias: "ArialBlack-Italic"
+}], ["ArialNarrow", {
+ local: ["Arial Narrow", "Liberation Sans Narrow", "Helvetica Condensed", "Nimbus Sans Narrow", "TeX Gyre Heros Cn"],
+ style: NORMAL,
+ fallback: "Helvetica"
+}], ["ArialNarrow-Bold", {
+ alias: "ArialNarrow",
+ style: BOLD,
+ fallback: "Helvetica-Bold"
+}], ["ArialNarrow-Italic", {
+ alias: "ArialNarrow",
+ style: ITALIC,
+ fallback: "Helvetica-Oblique"
+}], ["ArialNarrow-BoldItalic", {
+ alias: "ArialNarrow",
+ style: BOLDITALIC,
+ fallback: "Helvetica-BoldOblique"
+}], ["Calibri", {
+ local: ["Calibri", "Carlito"],
+ style: NORMAL,
+ fallback: "Helvetica"
+}], ["Calibri-Bold", {
+ alias: "Calibri",
+ style: BOLD,
+ fallback: "Helvetica-Bold"
+}], ["Calibri-Italic", {
+ alias: "Calibri",
+ style: ITALIC,
+ fallback: "Helvetica-Oblique"
+}], ["Calibri-BoldItalic", {
+ alias: "Calibri",
+ style: BOLDITALIC,
+ fallback: "Helvetica-BoldOblique"
+}], ["Wingdings", {
+ local: ["Wingdings", "URW Dingbats"],
+ style: NORMAL
+}], ["Wingdings-Regular", {
+ alias: "Wingdings"
+}], ["Wingdings-Bold", {
+ alias: "Wingdings"
+}]]);
+const fontAliases = new Map([["Arial-Black", "ArialBlack"]]);
+function getStyleToAppend(style) {
+ switch (style) {
+ case BOLD:
+ return "Bold";
+ case ITALIC:
+ return "Italic";
+ case BOLDITALIC:
+ return "Bold Italic";
+ default:
+ if (style?.weight === "bold") {
+ return "Bold";
+ }
+ if (style?.style === "italic") {
+ return "Italic";
+ }
+ }
+ return "";
+}
+function getFamilyName(str) {
+ const keywords = new Set(["thin", "extralight", "ultralight", "demilight", "semilight", "light", "book", "regular", "normal", "medium", "demibold", "semibold", "bold", "extrabold", "ultrabold", "black", "heavy", "extrablack", "ultrablack", "roman", "italic", "oblique", "ultracondensed", "extracondensed", "condensed", "semicondensed", "normal", "semiexpanded", "expanded", "extraexpanded", "ultraexpanded", "bolditalic"]);
+ return str.split(/[- ,+]+/g).filter(tok => !keywords.has(tok.toLowerCase())).join(" ");
+}
+function generateFont({
+ alias,
+ local,
+ path,
+ fallback,
+ style,
+ ultimate
+}, src, localFontPath, useFallback = true, usePath = true, append = "") {
+ const result = {
+ style: null,
+ ultimate: null
+ };
+ if (local) {
+ const extra = append ? ` ${append}` : "";
+ for (const name of local) {
+ src.push(`local(${name}${extra})`);
+ }
+ }
+ if (alias) {
+ const substitution = substitutionMap.get(alias);
+ const aliasAppend = append || getStyleToAppend(style);
+ Object.assign(result, generateFont(substitution, src, localFontPath, useFallback && !fallback, usePath && !path, aliasAppend));
+ }
+ if (style) {
+ result.style = style;
+ }
+ if (ultimate) {
+ result.ultimate = ultimate;
+ }
+ if (useFallback && fallback) {
+ const fallbackInfo = substitutionMap.get(fallback);
+ const {
+ ultimate: fallbackUltimate
+ } = generateFont(fallbackInfo, src, localFontPath, useFallback, usePath && !path, append);
+ result.ultimate ||= fallbackUltimate;
+ }
+ if (usePath && path && localFontPath) {
+ src.push(`url(${localFontPath}${path})`);
+ }
+ return result;
+}
+function getFontSubstitution(systemFontCache, idFactory, localFontPath, baseFontName, standardFontName) {
+ if (baseFontName.startsWith("InvalidPDFjsFont_")) {
+ return null;
+ }
+ baseFontName = normalizeFontName(baseFontName);
+ const key = baseFontName;
+ let substitutionInfo = systemFontCache.get(key);
+ if (substitutionInfo) {
+ return substitutionInfo;
+ }
+ let substitution = substitutionMap.get(baseFontName);
+ if (!substitution) {
+ for (const [alias, subst] of fontAliases) {
+ if (baseFontName.startsWith(alias)) {
+ baseFontName = `${subst}${baseFontName.substring(alias.length)}`;
+ substitution = substitutionMap.get(baseFontName);
+ break;
+ }
+ }
+ }
+ let mustAddBaseFont = false;
+ if (!substitution) {
+ substitution = substitutionMap.get(standardFontName);
+ mustAddBaseFont = true;
+ }
+ const loadedName = `${idFactory.getDocId()}_s${idFactory.createFontId()}`;
+ if (!substitution) {
+ if (!validateFontName(baseFontName)) {
+ systemFontCache.set(key, null);
+ return null;
+ }
+ const bold = /bold/gi.test(baseFontName);
+ const italic = /oblique|italic/gi.test(baseFontName);
+ const style = bold && italic && BOLDITALIC || bold && BOLD || italic && ITALIC || NORMAL;
+ substitutionInfo = {
+ css: `"${getFamilyName(baseFontName)}",${loadedName}`,
+ guessFallback: true,
+ loadedName,
+ baseFontName,
+ src: `local(${baseFontName})`,
+ style
+ };
+ systemFontCache.set(key, substitutionInfo);
+ return substitutionInfo;
+ }
+ const src = [];
+ if (mustAddBaseFont && validateFontName(baseFontName)) {
+ src.push(`local(${baseFontName})`);
+ }
+ const {
+ style,
+ ultimate
+ } = generateFont(substitution, src, localFontPath);
+ const guessFallback = ultimate === null;
+ const fallback = guessFallback ? "" : `,${ultimate}`;
+ substitutionInfo = {
+ css: `"${getFamilyName(baseFontName)}",${loadedName}${fallback}`,
+ guessFallback,
+ loadedName,
+ baseFontName,
+ src: src.join(","),
+ style
+ };
+ systemFontCache.set(key, substitutionInfo);
+ return substitutionInfo;
+}
+
+;// CONCATENATED MODULE: ./src/core/image_resizer.js
+
+const MIN_IMAGE_DIM = 2048;
+const MAX_IMAGE_DIM = 65537;
+const MAX_ERROR = 128;
+class ImageResizer {
+ constructor(imgData, isMask) {
+ this._imgData = imgData;
+ this._isMask = isMask;
+ }
+ static needsToBeResized(width, height) {
+ if (width <= this._goodSquareLength && height <= this._goodSquareLength) {
+ return false;
+ }
+ const {
+ MAX_DIM
+ } = this;
+ if (width > MAX_DIM || height > MAX_DIM) {
+ return true;
+ }
+ const area = width * height;
+ if (this._hasMaxArea) {
+ return area > this.MAX_AREA;
+ }
+ if (area < this._goodSquareLength ** 2) {
+ return false;
+ }
+ if (this._areGoodDims(width, height)) {
+ this._goodSquareLength = Math.max(this._goodSquareLength, Math.floor(Math.sqrt(width * height)));
+ return false;
+ }
+ this._goodSquareLength = this._guessMax(this._goodSquareLength, MAX_DIM, MAX_ERROR, 0);
+ const maxArea = this.MAX_AREA = this._goodSquareLength ** 2;
+ return area > maxArea;
+ }
+ static get MAX_DIM() {
+ return shadow(this, "MAX_DIM", this._guessMax(MIN_IMAGE_DIM, MAX_IMAGE_DIM, 0, 1));
+ }
+ static get MAX_AREA() {
+ this._hasMaxArea = true;
+ return shadow(this, "MAX_AREA", this._guessMax(ImageResizer._goodSquareLength, this.MAX_DIM, MAX_ERROR, 0) ** 2);
+ }
+ static set MAX_AREA(area) {
+ if (area >= 0) {
+ this._hasMaxArea = true;
+ shadow(this, "MAX_AREA", area);
+ }
+ }
+ static setMaxArea(area) {
+ if (!this._hasMaxArea) {
+ this.MAX_AREA = area >> 2;
+ }
+ }
+ static _areGoodDims(width, height) {
+ try {
+ const canvas = new OffscreenCanvas(width, height);
+ const ctx = canvas.getContext("2d");
+ ctx.fillRect(0, 0, 1, 1);
+ const opacity = ctx.getImageData(0, 0, 1, 1).data[3];
+ canvas.width = canvas.height = 1;
+ return opacity !== 0;
+ } catch {
+ return false;
+ }
+ }
+ static _guessMax(start, end, tolerance, defaultHeight) {
+ while (start + tolerance + 1 < end) {
+ const middle = Math.floor((start + end) / 2);
+ const height = defaultHeight || middle;
+ if (this._areGoodDims(middle, height)) {
+ start = middle;
+ } else {
+ end = middle;
+ }
+ }
+ return start;
+ }
+ static async createImage(imgData, isMask = false) {
+ return new ImageResizer(imgData, isMask)._createImage();
+ }
+ async _createImage() {
+ const data = this._encodeBMP();
+ const blob = new Blob([data.buffer], {
+ type: "image/bmp"
+ });
+ const bitmapPromise = createImageBitmap(blob);
+ const {
+ MAX_AREA,
+ MAX_DIM
+ } = ImageResizer;
+ const {
+ _imgData: imgData
+ } = this;
+ const {
+ width,
+ height
+ } = imgData;
+ const minFactor = Math.max(width / MAX_DIM, height / MAX_DIM, Math.sqrt(width * height / MAX_AREA));
+ const firstFactor = Math.max(minFactor, 2);
+ const factor = Math.round(10 * (minFactor + 1.25)) / 10 / firstFactor;
+ const N = Math.floor(Math.log2(factor));
+ const steps = new Array(N + 2).fill(2);
+ steps[0] = firstFactor;
+ steps.splice(-1, 1, factor / (1 << N));
+ let newWidth = width;
+ let newHeight = height;
+ let bitmap = await bitmapPromise;
+ for (const step of steps) {
+ const prevWidth = newWidth;
+ const prevHeight = newHeight;
+ newWidth = Math.floor(newWidth / step) - 1;
+ newHeight = Math.floor(newHeight / step) - 1;
+ const canvas = new OffscreenCanvas(newWidth, newHeight);
+ const ctx = canvas.getContext("2d");
+ ctx.drawImage(bitmap, 0, 0, prevWidth, prevHeight, 0, 0, newWidth, newHeight);
+ bitmap = canvas.transferToImageBitmap();
+ }
+ imgData.data = null;
+ imgData.bitmap = bitmap;
+ imgData.width = newWidth;
+ imgData.height = newHeight;
+ return imgData;
+ }
+ _encodeBMP() {
+ const {
+ width,
+ height,
+ kind
+ } = this._imgData;
+ let data = this._imgData.data;
+ let bitPerPixel;
+ let colorTable = new Uint8Array(0);
+ let maskTable = colorTable;
+ let compression = 0;
+ switch (kind) {
+ case ImageKind.GRAYSCALE_1BPP:
+ {
+ bitPerPixel = 1;
+ colorTable = new Uint8Array(this._isMask ? [255, 255, 255, 255, 0, 0, 0, 0] : [0, 0, 0, 0, 255, 255, 255, 255]);
+ const rowLen = width + 7 >> 3;
+ const rowSize = rowLen + 3 & -4;
+ if (rowLen !== rowSize) {
+ const newData = new Uint8Array(rowSize * height);
+ let k = 0;
+ for (let i = 0, ii = height * rowLen; i < ii; i += rowLen, k += rowSize) {
+ newData.set(data.subarray(i, i + rowLen), k);
+ }
+ data = newData;
+ }
+ break;
+ }
+ case ImageKind.RGB_24BPP:
+ {
+ bitPerPixel = 24;
+ if (width & 3) {
+ const rowLen = 3 * width;
+ const rowSize = rowLen + 3 & -4;
+ const extraLen = rowSize - rowLen;
+ const newData = new Uint8Array(rowSize * height);
+ let k = 0;
+ for (let i = 0, ii = height * rowLen; i < ii; i += rowLen) {
+ const row = data.subarray(i, i + rowLen);
+ for (let j = 0; j < rowLen; j += 3) {
+ newData[k++] = row[j + 2];
+ newData[k++] = row[j + 1];
+ newData[k++] = row[j];
+ }
+ k += extraLen;
+ }
+ data = newData;
+ } else {
+ for (let i = 0, ii = data.length; i < ii; i += 3) {
+ const tmp = data[i];
+ data[i] = data[i + 2];
+ data[i + 2] = tmp;
+ }
+ }
+ break;
+ }
+ case ImageKind.RGBA_32BPP:
+ bitPerPixel = 32;
+ compression = 3;
+ maskTable = new Uint8Array(4 + 4 + 4 + 4 + 52);
+ const view = new DataView(maskTable.buffer);
+ if (FeatureTest.isLittleEndian) {
+ view.setUint32(0, 0x000000ff, true);
+ view.setUint32(4, 0x0000ff00, true);
+ view.setUint32(8, 0x00ff0000, true);
+ view.setUint32(12, 0xff000000, true);
+ } else {
+ view.setUint32(0, 0xff000000, true);
+ view.setUint32(4, 0x00ff0000, true);
+ view.setUint32(8, 0x0000ff00, true);
+ view.setUint32(12, 0x000000ff, true);
+ }
+ break;
+ default:
+ throw new Error("invalid format");
+ }
+ let i = 0;
+ const headerLength = 40 + maskTable.length;
+ const fileLength = 14 + headerLength + colorTable.length + data.length;
+ const bmpData = new Uint8Array(fileLength);
+ const view = new DataView(bmpData.buffer);
+ view.setUint16(i, 0x4d42, true);
+ i += 2;
+ view.setUint32(i, fileLength, true);
+ i += 4;
+ view.setUint32(i, 0, true);
+ i += 4;
+ view.setUint32(i, 14 + headerLength + colorTable.length, true);
+ i += 4;
+ view.setUint32(i, headerLength, true);
+ i += 4;
+ view.setInt32(i, width, true);
+ i += 4;
+ view.setInt32(i, -height, true);
+ i += 4;
+ view.setUint16(i, 1, true);
+ i += 2;
+ view.setUint16(i, bitPerPixel, true);
+ i += 2;
+ view.setUint32(i, compression, true);
+ i += 4;
+ view.setUint32(i, 0, true);
+ i += 4;
+ view.setInt32(i, 0, true);
+ i += 4;
+ view.setInt32(i, 0, true);
+ i += 4;
+ view.setUint32(i, colorTable.length / 4, true);
+ i += 4;
+ view.setUint32(i, 0, true);
+ i += 4;
+ bmpData.set(maskTable, i);
+ i += maskTable.length;
+ bmpData.set(colorTable, i);
+ i += colorTable.length;
+ bmpData.set(data, i);
+ return bmpData;
+ }
+}
+ImageResizer._goodSquareLength = MIN_IMAGE_DIM;
+
+;// CONCATENATED MODULE: ./src/shared/murmurhash3.js
+const SEED = 0xc3d2e1f0;
+const MASK_HIGH = 0xffff0000;
+const MASK_LOW = 0xffff;
+class MurmurHash3_64 {
+ constructor(seed) {
+ this.h1 = seed ? seed & 0xffffffff : SEED;
+ this.h2 = seed ? seed & 0xffffffff : SEED;
+ }
+ update(input) {
+ let data, length;
+ if (typeof input === "string") {
+ data = new Uint8Array(input.length * 2);
+ length = 0;
+ for (let i = 0, ii = input.length; i < ii; i++) {
+ const code = input.charCodeAt(i);
+ if (code <= 0xff) {
+ data[length++] = code;
+ } else {
+ data[length++] = code >>> 8;
+ data[length++] = code & 0xff;
+ }
+ }
+ } else if (ArrayBuffer.isView(input)) {
+ data = input.slice();
+ length = data.byteLength;
+ } else {
+ throw new Error("Invalid data format, must be a string or TypedArray.");
+ }
+ const blockCounts = length >> 2;
+ const tailLength = length - blockCounts * 4;
+ const dataUint32 = new Uint32Array(data.buffer, 0, blockCounts);
+ let k1 = 0,
+ k2 = 0;
+ let h1 = this.h1,
+ h2 = this.h2;
+ const C1 = 0xcc9e2d51,
+ C2 = 0x1b873593;
+ const C1_LOW = C1 & MASK_LOW,
+ C2_LOW = C2 & MASK_LOW;
+ for (let i = 0; i < blockCounts; i++) {
+ if (i & 1) {
+ k1 = dataUint32[i];
+ k1 = k1 * C1 & MASK_HIGH | k1 * C1_LOW & MASK_LOW;
+ k1 = k1 << 15 | k1 >>> 17;
+ k1 = k1 * C2 & MASK_HIGH | k1 * C2_LOW & MASK_LOW;
+ h1 ^= k1;
+ h1 = h1 << 13 | h1 >>> 19;
+ h1 = h1 * 5 + 0xe6546b64;
+ } else {
+ k2 = dataUint32[i];
+ k2 = k2 * C1 & MASK_HIGH | k2 * C1_LOW & MASK_LOW;
+ k2 = k2 << 15 | k2 >>> 17;
+ k2 = k2 * C2 & MASK_HIGH | k2 * C2_LOW & MASK_LOW;
+ h2 ^= k2;
+ h2 = h2 << 13 | h2 >>> 19;
+ h2 = h2 * 5 + 0xe6546b64;
+ }
+ }
+ k1 = 0;
+ switch (tailLength) {
+ case 3:
+ k1 ^= data[blockCounts * 4 + 2] << 16;
+ case 2:
+ k1 ^= data[blockCounts * 4 + 1] << 8;
+ case 1:
+ k1 ^= data[blockCounts * 4];
+ k1 = k1 * C1 & MASK_HIGH | k1 * C1_LOW & MASK_LOW;
+ k1 = k1 << 15 | k1 >>> 17;
+ k1 = k1 * C2 & MASK_HIGH | k1 * C2_LOW & MASK_LOW;
+ if (blockCounts & 1) {
+ h1 ^= k1;
+ } else {
+ h2 ^= k1;
+ }
+ }
+ this.h1 = h1;
+ this.h2 = h2;
+ }
+ hexdigest() {
+ let h1 = this.h1,
+ h2 = this.h2;
+ h1 ^= h2 >>> 1;
+ h1 = h1 * 0xed558ccd & MASK_HIGH | h1 * 0x8ccd & MASK_LOW;
+ h2 = h2 * 0xff51afd7 & MASK_HIGH | ((h2 << 16 | h1 >>> 16) * 0xafd7ed55 & MASK_HIGH) >>> 16;
+ h1 ^= h2 >>> 1;
+ h1 = h1 * 0x1a85ec53 & MASK_HIGH | h1 * 0xec53 & MASK_LOW;
+ h2 = h2 * 0xc4ceb9fe & MASK_HIGH | ((h2 << 16 | h1 >>> 16) * 0xb9fe1a85 & MASK_HIGH) >>> 16;
+ h1 ^= h2 >>> 1;
+ return (h1 >>> 0).toString(16).padStart(8, "0") + (h2 >>> 0).toString(16).padStart(8, "0");
+ }
+}
+
+;// CONCATENATED MODULE: ./src/core/operator_list.js
+
+function addState(parentState, pattern, checkFn, iterateFn, processFn) {
+ let state = parentState;
+ for (let i = 0, ii = pattern.length - 1; i < ii; i++) {
+ const item = pattern[i];
+ state = state[item] ||= [];
+ }
+ state[pattern.at(-1)] = {
+ checkFn,
+ iterateFn,
+ processFn
+ };
+}
+const InitialState = [];
+addState(InitialState, [OPS.save, OPS.transform, OPS.paintInlineImageXObject, OPS.restore], null, function iterateInlineImageGroup(context, i) {
+ const fnArray = context.fnArray;
+ const iFirstSave = context.iCurr - 3;
+ const pos = (i - iFirstSave) % 4;
+ switch (pos) {
+ case 0:
+ return fnArray[i] === OPS.save;
+ case 1:
+ return fnArray[i] === OPS.transform;
+ case 2:
+ return fnArray[i] === OPS.paintInlineImageXObject;
+ case 3:
+ return fnArray[i] === OPS.restore;
+ }
+ throw new Error(`iterateInlineImageGroup - invalid pos: ${pos}`);
+}, function foundInlineImageGroup(context, i) {
+ const MIN_IMAGES_IN_INLINE_IMAGES_BLOCK = 10;
+ const MAX_IMAGES_IN_INLINE_IMAGES_BLOCK = 200;
+ const MAX_WIDTH = 1000;
+ const IMAGE_PADDING = 1;
+ const fnArray = context.fnArray,
+ argsArray = context.argsArray;
+ const curr = context.iCurr;
+ const iFirstSave = curr - 3;
+ const iFirstTransform = curr - 2;
+ const iFirstPIIXO = curr - 1;
+ const count = Math.min(Math.floor((i - iFirstSave) / 4), MAX_IMAGES_IN_INLINE_IMAGES_BLOCK);
+ if (count < MIN_IMAGES_IN_INLINE_IMAGES_BLOCK) {
+ return i - (i - iFirstSave) % 4;
+ }
+ let maxX = 0;
+ const map = [];
+ let maxLineHeight = 0;
+ let currentX = IMAGE_PADDING,
+ currentY = IMAGE_PADDING;
+ for (let q = 0; q < count; q++) {
+ const transform = argsArray[iFirstTransform + (q << 2)];
+ const img = argsArray[iFirstPIIXO + (q << 2)][0];
+ if (currentX + img.width > MAX_WIDTH) {
+ maxX = Math.max(maxX, currentX);
+ currentY += maxLineHeight + 2 * IMAGE_PADDING;
+ currentX = 0;
+ maxLineHeight = 0;
+ }
+ map.push({
+ transform,
+ x: currentX,
+ y: currentY,
+ w: img.width,
+ h: img.height
+ });
+ currentX += img.width + 2 * IMAGE_PADDING;
+ maxLineHeight = Math.max(maxLineHeight, img.height);
+ }
+ const imgWidth = Math.max(maxX, currentX) + IMAGE_PADDING;
+ const imgHeight = currentY + maxLineHeight + IMAGE_PADDING;
+ const imgData = new Uint8Array(imgWidth * imgHeight * 4);
+ const imgRowSize = imgWidth << 2;
+ for (let q = 0; q < count; q++) {
+ const data = argsArray[iFirstPIIXO + (q << 2)][0].data;
+ const rowSize = map[q].w << 2;
+ let dataOffset = 0;
+ let offset = map[q].x + map[q].y * imgWidth << 2;
+ imgData.set(data.subarray(0, rowSize), offset - imgRowSize);
+ for (let k = 0, kk = map[q].h; k < kk; k++) {
+ imgData.set(data.subarray(dataOffset, dataOffset + rowSize), offset);
+ dataOffset += rowSize;
+ offset += imgRowSize;
+ }
+ imgData.set(data.subarray(dataOffset - rowSize, dataOffset), offset);
+ while (offset >= 0) {
+ data[offset - 4] = data[offset];
+ data[offset - 3] = data[offset + 1];
+ data[offset - 2] = data[offset + 2];
+ data[offset - 1] = data[offset + 3];
+ data[offset + rowSize] = data[offset + rowSize - 4];
+ data[offset + rowSize + 1] = data[offset + rowSize - 3];
+ data[offset + rowSize + 2] = data[offset + rowSize - 2];
+ data[offset + rowSize + 3] = data[offset + rowSize - 1];
+ offset -= imgRowSize;
+ }
+ }
+ const img = {
+ width: imgWidth,
+ height: imgHeight
+ };
+ if (context.isOffscreenCanvasSupported) {
+ const canvas = new OffscreenCanvas(imgWidth, imgHeight);
+ const ctx = canvas.getContext("2d");
+ ctx.putImageData(new ImageData(new Uint8ClampedArray(imgData.buffer), imgWidth, imgHeight), 0, 0);
+ img.bitmap = canvas.transferToImageBitmap();
+ img.data = null;
+ } else {
+ img.kind = ImageKind.RGBA_32BPP;
+ img.data = imgData;
+ }
+ fnArray.splice(iFirstSave, count * 4, OPS.paintInlineImageXObjectGroup);
+ argsArray.splice(iFirstSave, count * 4, [img, map]);
+ return iFirstSave + 1;
+});
+addState(InitialState, [OPS.save, OPS.transform, OPS.paintImageMaskXObject, OPS.restore], null, function iterateImageMaskGroup(context, i) {
+ const fnArray = context.fnArray;
+ const iFirstSave = context.iCurr - 3;
+ const pos = (i - iFirstSave) % 4;
+ switch (pos) {
+ case 0:
+ return fnArray[i] === OPS.save;
+ case 1:
+ return fnArray[i] === OPS.transform;
+ case 2:
+ return fnArray[i] === OPS.paintImageMaskXObject;
+ case 3:
+ return fnArray[i] === OPS.restore;
+ }
+ throw new Error(`iterateImageMaskGroup - invalid pos: ${pos}`);
+}, function foundImageMaskGroup(context, i) {
+ const MIN_IMAGES_IN_MASKS_BLOCK = 10;
+ const MAX_IMAGES_IN_MASKS_BLOCK = 100;
+ const MAX_SAME_IMAGES_IN_MASKS_BLOCK = 1000;
+ const fnArray = context.fnArray,
+ argsArray = context.argsArray;
+ const curr = context.iCurr;
+ const iFirstSave = curr - 3;
+ const iFirstTransform = curr - 2;
+ const iFirstPIMXO = curr - 1;
+ let count = Math.floor((i - iFirstSave) / 4);
+ if (count < MIN_IMAGES_IN_MASKS_BLOCK) {
+ return i - (i - iFirstSave) % 4;
+ }
+ let isSameImage = false;
+ let iTransform, transformArgs;
+ const firstPIMXOArg0 = argsArray[iFirstPIMXO][0];
+ const firstTransformArg0 = argsArray[iFirstTransform][0],
+ firstTransformArg1 = argsArray[iFirstTransform][1],
+ firstTransformArg2 = argsArray[iFirstTransform][2],
+ firstTransformArg3 = argsArray[iFirstTransform][3];
+ if (firstTransformArg1 === firstTransformArg2) {
+ isSameImage = true;
+ iTransform = iFirstTransform + 4;
+ let iPIMXO = iFirstPIMXO + 4;
+ for (let q = 1; q < count; q++, iTransform += 4, iPIMXO += 4) {
+ transformArgs = argsArray[iTransform];
+ if (argsArray[iPIMXO][0] !== firstPIMXOArg0 || transformArgs[0] !== firstTransformArg0 || transformArgs[1] !== firstTransformArg1 || transformArgs[2] !== firstTransformArg2 || transformArgs[3] !== firstTransformArg3) {
+ if (q < MIN_IMAGES_IN_MASKS_BLOCK) {
+ isSameImage = false;
+ } else {
+ count = q;
+ }
+ break;
+ }
+ }
+ }
+ if (isSameImage) {
+ count = Math.min(count, MAX_SAME_IMAGES_IN_MASKS_BLOCK);
+ const positions = new Float32Array(count * 2);
+ iTransform = iFirstTransform;
+ for (let q = 0; q < count; q++, iTransform += 4) {
+ transformArgs = argsArray[iTransform];
+ positions[q << 1] = transformArgs[4];
+ positions[(q << 1) + 1] = transformArgs[5];
+ }
+ fnArray.splice(iFirstSave, count * 4, OPS.paintImageMaskXObjectRepeat);
+ argsArray.splice(iFirstSave, count * 4, [firstPIMXOArg0, firstTransformArg0, firstTransformArg1, firstTransformArg2, firstTransformArg3, positions]);
+ } else {
+ count = Math.min(count, MAX_IMAGES_IN_MASKS_BLOCK);
+ const images = [];
+ for (let q = 0; q < count; q++) {
+ transformArgs = argsArray[iFirstTransform + (q << 2)];
+ const maskParams = argsArray[iFirstPIMXO + (q << 2)][0];
+ images.push({
+ data: maskParams.data,
+ width: maskParams.width,
+ height: maskParams.height,
+ interpolate: maskParams.interpolate,
+ count: maskParams.count,
+ transform: transformArgs
+ });
+ }
+ fnArray.splice(iFirstSave, count * 4, OPS.paintImageMaskXObjectGroup);
+ argsArray.splice(iFirstSave, count * 4, [images]);
+ }
+ return iFirstSave + 1;
+});
+addState(InitialState, [OPS.save, OPS.transform, OPS.paintImageXObject, OPS.restore], function (context) {
+ const argsArray = context.argsArray;
+ const iFirstTransform = context.iCurr - 2;
+ return argsArray[iFirstTransform][1] === 0 && argsArray[iFirstTransform][2] === 0;
+}, function iterateImageGroup(context, i) {
+ const fnArray = context.fnArray,
+ argsArray = context.argsArray;
+ const iFirstSave = context.iCurr - 3;
+ const pos = (i - iFirstSave) % 4;
+ switch (pos) {
+ case 0:
+ return fnArray[i] === OPS.save;
+ case 1:
+ if (fnArray[i] !== OPS.transform) {
+ return false;
+ }
+ const iFirstTransform = context.iCurr - 2;
+ const firstTransformArg0 = argsArray[iFirstTransform][0];
+ const firstTransformArg3 = argsArray[iFirstTransform][3];
+ if (argsArray[i][0] !== firstTransformArg0 || argsArray[i][1] !== 0 || argsArray[i][2] !== 0 || argsArray[i][3] !== firstTransformArg3) {
+ return false;
+ }
+ return true;
+ case 2:
+ if (fnArray[i] !== OPS.paintImageXObject) {
+ return false;
+ }
+ const iFirstPIXO = context.iCurr - 1;
+ const firstPIXOArg0 = argsArray[iFirstPIXO][0];
+ if (argsArray[i][0] !== firstPIXOArg0) {
+ return false;
+ }
+ return true;
+ case 3:
+ return fnArray[i] === OPS.restore;
+ }
+ throw new Error(`iterateImageGroup - invalid pos: ${pos}`);
+}, function (context, i) {
+ const MIN_IMAGES_IN_BLOCK = 3;
+ const MAX_IMAGES_IN_BLOCK = 1000;
+ const fnArray = context.fnArray,
+ argsArray = context.argsArray;
+ const curr = context.iCurr;
+ const iFirstSave = curr - 3;
+ const iFirstTransform = curr - 2;
+ const iFirstPIXO = curr - 1;
+ const firstPIXOArg0 = argsArray[iFirstPIXO][0];
+ const firstTransformArg0 = argsArray[iFirstTransform][0];
+ const firstTransformArg3 = argsArray[iFirstTransform][3];
+ const count = Math.min(Math.floor((i - iFirstSave) / 4), MAX_IMAGES_IN_BLOCK);
+ if (count < MIN_IMAGES_IN_BLOCK) {
+ return i - (i - iFirstSave) % 4;
+ }
+ const positions = new Float32Array(count * 2);
+ let iTransform = iFirstTransform;
+ for (let q = 0; q < count; q++, iTransform += 4) {
+ const transformArgs = argsArray[iTransform];
+ positions[q << 1] = transformArgs[4];
+ positions[(q << 1) + 1] = transformArgs[5];
+ }
+ const args = [firstPIXOArg0, firstTransformArg0, firstTransformArg3, positions];
+ fnArray.splice(iFirstSave, count * 4, OPS.paintImageXObjectRepeat);
+ argsArray.splice(iFirstSave, count * 4, args);
+ return iFirstSave + 1;
+});
+addState(InitialState, [OPS.beginText, OPS.setFont, OPS.setTextMatrix, OPS.showText, OPS.endText], null, function iterateShowTextGroup(context, i) {
+ const fnArray = context.fnArray,
+ argsArray = context.argsArray;
+ const iFirstSave = context.iCurr - 4;
+ const pos = (i - iFirstSave) % 5;
+ switch (pos) {
+ case 0:
+ return fnArray[i] === OPS.beginText;
+ case 1:
+ return fnArray[i] === OPS.setFont;
+ case 2:
+ return fnArray[i] === OPS.setTextMatrix;
+ case 3:
+ if (fnArray[i] !== OPS.showText) {
+ return false;
+ }
+ const iFirstSetFont = context.iCurr - 3;
+ const firstSetFontArg0 = argsArray[iFirstSetFont][0];
+ const firstSetFontArg1 = argsArray[iFirstSetFont][1];
+ if (argsArray[i][0] !== firstSetFontArg0 || argsArray[i][1] !== firstSetFontArg1) {
+ return false;
+ }
+ return true;
+ case 4:
+ return fnArray[i] === OPS.endText;
+ }
+ throw new Error(`iterateShowTextGroup - invalid pos: ${pos}`);
+}, function (context, i) {
+ const MIN_CHARS_IN_BLOCK = 3;
+ const MAX_CHARS_IN_BLOCK = 1000;
+ const fnArray = context.fnArray,
+ argsArray = context.argsArray;
+ const curr = context.iCurr;
+ const iFirstBeginText = curr - 4;
+ const iFirstSetFont = curr - 3;
+ const iFirstSetTextMatrix = curr - 2;
+ const iFirstShowText = curr - 1;
+ const iFirstEndText = curr;
+ const firstSetFontArg0 = argsArray[iFirstSetFont][0];
+ const firstSetFontArg1 = argsArray[iFirstSetFont][1];
+ let count = Math.min(Math.floor((i - iFirstBeginText) / 5), MAX_CHARS_IN_BLOCK);
+ if (count < MIN_CHARS_IN_BLOCK) {
+ return i - (i - iFirstBeginText) % 5;
+ }
+ let iFirst = iFirstBeginText;
+ if (iFirstBeginText >= 4 && fnArray[iFirstBeginText - 4] === fnArray[iFirstSetFont] && fnArray[iFirstBeginText - 3] === fnArray[iFirstSetTextMatrix] && fnArray[iFirstBeginText - 2] === fnArray[iFirstShowText] && fnArray[iFirstBeginText - 1] === fnArray[iFirstEndText] && argsArray[iFirstBeginText - 4][0] === firstSetFontArg0 && argsArray[iFirstBeginText - 4][1] === firstSetFontArg1) {
+ count++;
+ iFirst -= 5;
+ }
+ let iEndText = iFirst + 4;
+ for (let q = 1; q < count; q++) {
+ fnArray.splice(iEndText, 3);
+ argsArray.splice(iEndText, 3);
+ iEndText += 2;
+ }
+ return iEndText + 1;
+});
+class NullOptimizer {
+ constructor(queue) {
+ this.queue = queue;
+ }
+ _optimize() {}
+ push(fn, args) {
+ this.queue.fnArray.push(fn);
+ this.queue.argsArray.push(args);
+ this._optimize();
+ }
+ flush() {}
+ reset() {}
+}
+class QueueOptimizer extends NullOptimizer {
+ constructor(queue) {
+ super(queue);
+ this.state = null;
+ this.context = {
+ iCurr: 0,
+ fnArray: queue.fnArray,
+ argsArray: queue.argsArray,
+ isOffscreenCanvasSupported: false
+ };
+ this.match = null;
+ this.lastProcessed = 0;
+ }
+ set isOffscreenCanvasSupported(value) {
+ this.context.isOffscreenCanvasSupported = value;
+ }
+ _optimize() {
+ const fnArray = this.queue.fnArray;
+ let i = this.lastProcessed,
+ ii = fnArray.length;
+ let state = this.state;
+ let match = this.match;
+ if (!state && !match && i + 1 === ii && !InitialState[fnArray[i]]) {
+ this.lastProcessed = ii;
+ return;
+ }
+ const context = this.context;
+ while (i < ii) {
+ if (match) {
+ const iterate = (0, match.iterateFn)(context, i);
+ if (iterate) {
+ i++;
+ continue;
+ }
+ i = (0, match.processFn)(context, i + 1);
+ ii = fnArray.length;
+ match = null;
+ state = null;
+ if (i >= ii) {
+ break;
+ }
+ }
+ state = (state || InitialState)[fnArray[i]];
+ if (!state || Array.isArray(state)) {
+ i++;
+ continue;
+ }
+ context.iCurr = i;
+ i++;
+ if (state.checkFn && !(0, state.checkFn)(context)) {
+ state = null;
+ continue;
+ }
+ match = state;
+ state = null;
+ }
+ this.state = state;
+ this.match = match;
+ this.lastProcessed = i;
+ }
+ flush() {
+ while (this.match) {
+ const length = this.queue.fnArray.length;
+ this.lastProcessed = (0, this.match.processFn)(this.context, length);
+ this.match = null;
+ this.state = null;
+ this._optimize();
+ }
+ }
+ reset() {
+ this.state = null;
+ this.match = null;
+ this.lastProcessed = 0;
+ }
+}
+class OperatorList {
+ static CHUNK_SIZE = 1000;
+ static CHUNK_SIZE_ABOUT = this.CHUNK_SIZE - 5;
+ constructor(intent = 0, streamSink) {
+ this._streamSink = streamSink;
+ this.fnArray = [];
+ this.argsArray = [];
+ this.optimizer = streamSink && !(intent & RenderingIntentFlag.OPLIST) ? new QueueOptimizer(this) : new NullOptimizer(this);
+ this.dependencies = new Set();
+ this._totalLength = 0;
+ this.weight = 0;
+ this._resolved = streamSink ? null : Promise.resolve();
+ }
+ set isOffscreenCanvasSupported(value) {
+ this.optimizer.isOffscreenCanvasSupported = value;
+ }
+ get length() {
+ return this.argsArray.length;
+ }
+ get ready() {
+ return this._resolved || this._streamSink.ready;
+ }
+ get totalLength() {
+ return this._totalLength + this.length;
+ }
+ addOp(fn, args) {
+ this.optimizer.push(fn, args);
+ this.weight++;
+ if (this._streamSink) {
+ if (this.weight >= OperatorList.CHUNK_SIZE) {
+ this.flush();
+ } else if (this.weight >= OperatorList.CHUNK_SIZE_ABOUT && (fn === OPS.restore || fn === OPS.endText)) {
+ this.flush();
+ }
+ }
+ }
+ addImageOps(fn, args, optionalContent) {
+ if (optionalContent !== undefined) {
+ this.addOp(OPS.beginMarkedContentProps, ["OC", optionalContent]);
+ }
+ this.addOp(fn, args);
+ if (optionalContent !== undefined) {
+ this.addOp(OPS.endMarkedContent, []);
+ }
+ }
+ addDependency(dependency) {
+ if (this.dependencies.has(dependency)) {
+ return;
+ }
+ this.dependencies.add(dependency);
+ this.addOp(OPS.dependency, [dependency]);
+ }
+ addDependencies(dependencies) {
+ for (const dependency of dependencies) {
+ this.addDependency(dependency);
+ }
+ }
+ addOpList(opList) {
+ if (!(opList instanceof OperatorList)) {
+ warn('addOpList - ignoring invalid "opList" parameter.');
+ return;
+ }
+ for (const dependency of opList.dependencies) {
+ this.dependencies.add(dependency);
+ }
+ for (let i = 0, ii = opList.length; i < ii; i++) {
+ this.addOp(opList.fnArray[i], opList.argsArray[i]);
+ }
+ }
+ getIR() {
+ return {
+ fnArray: this.fnArray,
+ argsArray: this.argsArray,
+ length: this.length
+ };
+ }
+ get _transfers() {
+ const transfers = [];
+ const {
+ fnArray,
+ argsArray,
+ length
+ } = this;
+ for (let i = 0; i < length; i++) {
+ switch (fnArray[i]) {
+ case OPS.paintInlineImageXObject:
+ case OPS.paintInlineImageXObjectGroup:
+ case OPS.paintImageMaskXObject:
+ const arg = argsArray[i][0];
+ if (!arg.cached && arg.data?.buffer instanceof ArrayBuffer) {
+ transfers.push(arg.data.buffer);
+ }
+ break;
+ }
+ }
+ return transfers;
+ }
+ flush(lastChunk = false, separateAnnots = null) {
+ this.optimizer.flush();
+ const length = this.length;
+ this._totalLength += length;
+ this._streamSink.enqueue({
+ fnArray: this.fnArray,
+ argsArray: this.argsArray,
+ lastChunk,
+ separateAnnots,
+ length
+ }, 1, this._transfers);
+ this.dependencies.clear();
+ this.fnArray.length = 0;
+ this.argsArray.length = 0;
+ this.weight = 0;
+ this.optimizer.reset();
+ }
+}
+
+;// CONCATENATED MODULE: ./src/core/image.js
+
+
+
+
+
+
+
+
+
+function decodeAndClamp(value, addend, coefficient, max) {
+ value = addend + value * coefficient;
+ if (value < 0) {
+ value = 0;
+ } else if (value > max) {
+ value = max;
+ }
+ return value;
+}
+function resizeImageMask(src, bpc, w1, h1, w2, h2) {
+ const length = w2 * h2;
+ let dest;
+ if (bpc <= 8) {
+ dest = new Uint8Array(length);
+ } else if (bpc <= 16) {
+ dest = new Uint16Array(length);
+ } else {
+ dest = new Uint32Array(length);
+ }
+ const xRatio = w1 / w2;
+ const yRatio = h1 / h2;
+ let i,
+ j,
+ py,
+ newIndex = 0,
+ oldIndex;
+ const xScaled = new Uint16Array(w2);
+ const w1Scanline = w1;
+ for (i = 0; i < w2; i++) {
+ xScaled[i] = Math.floor(i * xRatio);
+ }
+ for (i = 0; i < h2; i++) {
+ py = Math.floor(i * yRatio) * w1Scanline;
+ for (j = 0; j < w2; j++) {
+ oldIndex = py + xScaled[j];
+ dest[newIndex++] = src[oldIndex];
+ }
+ }
+ return dest;
+}
+class PDFImage {
+ constructor({
+ xref,
+ res,
+ image,
+ isInline = false,
+ smask = null,
+ mask = null,
+ isMask = false,
+ pdfFunctionFactory,
+ localColorSpaceCache
+ }) {
+ this.image = image;
+ const dict = image.dict;
+ const filter = dict.get("F", "Filter");
+ let filterName;
+ if (filter instanceof Name) {
+ filterName = filter.name;
+ } else if (Array.isArray(filter)) {
+ const filterZero = xref.fetchIfRef(filter[0]);
+ if (filterZero instanceof Name) {
+ filterName = filterZero.name;
+ }
+ }
+ switch (filterName) {
+ case "JPXDecode":
+ const jpxImage = new JpxImage();
+ jpxImage.parseImageProperties(image.stream);
+ image.stream.reset();
+ image.width = jpxImage.width;
+ image.height = jpxImage.height;
+ image.bitsPerComponent = jpxImage.bitsPerComponent;
+ image.numComps = jpxImage.componentsCount;
+ break;
+ case "JBIG2Decode":
+ image.bitsPerComponent = 1;
+ image.numComps = 1;
+ break;
+ }
+ let width = dict.get("W", "Width");
+ let height = dict.get("H", "Height");
+ if (Number.isInteger(image.width) && image.width > 0 && Number.isInteger(image.height) && image.height > 0 && (image.width !== width || image.height !== height)) {
+ warn("PDFImage - using the Width/Height of the image data, " + "rather than the image dictionary.");
+ width = image.width;
+ height = image.height;
+ }
+ if (width < 1 || height < 1) {
+ throw new FormatError(`Invalid image width: ${width} or height: ${height}`);
+ }
+ this.width = width;
+ this.height = height;
+ this.interpolate = dict.get("I", "Interpolate");
+ this.imageMask = dict.get("IM", "ImageMask") || false;
+ this.matte = dict.get("Matte") || false;
+ let bitsPerComponent = image.bitsPerComponent;
+ if (!bitsPerComponent) {
+ bitsPerComponent = dict.get("BPC", "BitsPerComponent");
+ if (!bitsPerComponent) {
+ if (this.imageMask) {
+ bitsPerComponent = 1;
+ } else {
+ throw new FormatError(`Bits per component missing in image: ${this.imageMask}`);
+ }
+ }
+ }
+ this.bpc = bitsPerComponent;
+ if (!this.imageMask) {
+ let colorSpace = dict.getRaw("CS") || dict.getRaw("ColorSpace");
+ if (!colorSpace) {
+ info("JPX images (which do not require color spaces)");
+ switch (image.numComps) {
+ case 1:
+ colorSpace = Name.get("DeviceGray");
+ break;
+ case 3:
+ colorSpace = Name.get("DeviceRGB");
+ break;
+ case 4:
+ colorSpace = Name.get("DeviceCMYK");
+ break;
+ default:
+ throw new Error(`JPX images with ${image.numComps} color components not supported.`);
+ }
+ }
+ this.colorSpace = ColorSpace.parse({
+ cs: colorSpace,
+ xref,
+ resources: isInline ? res : null,
+ pdfFunctionFactory,
+ localColorSpaceCache
+ });
+ this.numComps = this.colorSpace.numComps;
+ }
+ this.decode = dict.getArray("D", "Decode");
+ this.needsDecode = false;
+ if (this.decode && (this.colorSpace && !this.colorSpace.isDefaultDecode(this.decode, bitsPerComponent) || isMask && !ColorSpace.isDefaultDecode(this.decode, 1))) {
+ this.needsDecode = true;
+ const max = (1 << bitsPerComponent) - 1;
+ this.decodeCoefficients = [];
+ this.decodeAddends = [];
+ const isIndexed = this.colorSpace?.name === "Indexed";
+ for (let i = 0, j = 0; i < this.decode.length; i += 2, ++j) {
+ const dmin = this.decode[i];
+ const dmax = this.decode[i + 1];
+ this.decodeCoefficients[j] = isIndexed ? (dmax - dmin) / max : dmax - dmin;
+ this.decodeAddends[j] = isIndexed ? dmin : max * dmin;
+ }
+ }
+ if (smask) {
+ this.smask = new PDFImage({
+ xref,
+ res,
+ image: smask,
+ isInline,
+ pdfFunctionFactory,
+ localColorSpaceCache
+ });
+ } else if (mask) {
+ if (mask instanceof BaseStream) {
+ const maskDict = mask.dict,
+ imageMask = maskDict.get("IM", "ImageMask");
+ if (!imageMask) {
+ warn("Ignoring /Mask in image without /ImageMask.");
+ } else {
+ this.mask = new PDFImage({
+ xref,
+ res,
+ image: mask,
+ isInline,
+ isMask: true,
+ pdfFunctionFactory,
+ localColorSpaceCache
+ });
+ }
+ } else {
+ this.mask = mask;
+ }
+ }
+ }
+ static async buildImage({
+ xref,
+ res,
+ image,
+ isInline = false,
+ pdfFunctionFactory,
+ localColorSpaceCache
+ }) {
+ const imageData = image;
+ let smaskData = null;
+ let maskData = null;
+ const smask = image.dict.get("SMask");
+ const mask = image.dict.get("Mask");
+ if (smask) {
+ if (smask instanceof BaseStream) {
+ smaskData = smask;
+ } else {
+ warn("Unsupported /SMask format.");
+ }
+ } else if (mask) {
+ if (mask instanceof BaseStream || Array.isArray(mask)) {
+ maskData = mask;
+ } else {
+ warn("Unsupported /Mask format.");
+ }
+ }
+ return new PDFImage({
+ xref,
+ res,
+ image: imageData,
+ isInline,
+ smask: smaskData,
+ mask: maskData,
+ pdfFunctionFactory,
+ localColorSpaceCache
+ });
+ }
+ static createRawMask({
+ imgArray,
+ width,
+ height,
+ imageIsFromDecodeStream,
+ inverseDecode,
+ interpolate
+ }) {
+ const computedLength = (width + 7 >> 3) * height;
+ const actualLength = imgArray.byteLength;
+ const haveFullData = computedLength === actualLength;
+ let data, i;
+ if (imageIsFromDecodeStream && (!inverseDecode || haveFullData)) {
+ data = imgArray;
+ } else if (!inverseDecode) {
+ data = new Uint8Array(imgArray);
+ } else {
+ data = new Uint8Array(computedLength);
+ data.set(imgArray);
+ data.fill(0xff, actualLength);
+ }
+ if (inverseDecode) {
+ for (i = 0; i < actualLength; i++) {
+ data[i] ^= 0xff;
+ }
+ }
+ return {
+ data,
+ width,
+ height,
+ interpolate
+ };
+ }
+ static async createMask({
+ imgArray,
+ width,
+ height,
+ imageIsFromDecodeStream,
+ inverseDecode,
+ interpolate,
+ isOffscreenCanvasSupported = false
+ }) {
+ const isSingleOpaquePixel = width === 1 && height === 1 && inverseDecode === (imgArray.length === 0 || !!(imgArray[0] & 128));
+ if (isSingleOpaquePixel) {
+ return {
+ isSingleOpaquePixel
+ };
+ }
+ if (isOffscreenCanvasSupported) {
+ if (ImageResizer.needsToBeResized(width, height)) {
+ const data = new Uint8ClampedArray(width * height * 4);
+ convertBlackAndWhiteToRGBA({
+ src: imgArray,
+ dest: data,
+ width,
+ height,
+ nonBlackColor: 0,
+ inverseDecode
+ });
+ return ImageResizer.createImage({
+ kind: ImageKind.RGBA_32BPP,
+ data,
+ width,
+ height,
+ interpolate
+ });
+ }
+ const canvas = new OffscreenCanvas(width, height);
+ const ctx = canvas.getContext("2d");
+ const imgData = ctx.createImageData(width, height);
+ convertBlackAndWhiteToRGBA({
+ src: imgArray,
+ dest: imgData.data,
+ width,
+ height,
+ nonBlackColor: 0,
+ inverseDecode
+ });
+ ctx.putImageData(imgData, 0, 0);
+ const bitmap = canvas.transferToImageBitmap();
+ return {
+ data: null,
+ width,
+ height,
+ interpolate,
+ bitmap
+ };
+ }
+ return this.createRawMask({
+ imgArray,
+ width,
+ height,
+ inverseDecode,
+ imageIsFromDecodeStream,
+ interpolate
+ });
+ }
+ get drawWidth() {
+ return Math.max(this.width, this.smask?.width || 0, this.mask?.width || 0);
+ }
+ get drawHeight() {
+ return Math.max(this.height, this.smask?.height || 0, this.mask?.height || 0);
+ }
+ decodeBuffer(buffer) {
+ const bpc = this.bpc;
+ const numComps = this.numComps;
+ const decodeAddends = this.decodeAddends;
+ const decodeCoefficients = this.decodeCoefficients;
+ const max = (1 << bpc) - 1;
+ let i, ii;
+ if (bpc === 1) {
+ for (i = 0, ii = buffer.length; i < ii; i++) {
+ buffer[i] = +!buffer[i];
+ }
+ return;
+ }
+ let index = 0;
+ for (i = 0, ii = this.width * this.height; i < ii; i++) {
+ for (let j = 0; j < numComps; j++) {
+ buffer[index] = decodeAndClamp(buffer[index], decodeAddends[j], decodeCoefficients[j], max);
+ index++;
+ }
+ }
+ }
+ getComponents(buffer) {
+ const bpc = this.bpc;
+ if (bpc === 8) {
+ return buffer;
+ }
+ const width = this.width;
+ const height = this.height;
+ const numComps = this.numComps;
+ const length = width * height * numComps;
+ let bufferPos = 0;
+ let output;
+ if (bpc <= 8) {
+ output = new Uint8Array(length);
+ } else if (bpc <= 16) {
+ output = new Uint16Array(length);
+ } else {
+ output = new Uint32Array(length);
+ }
+ const rowComps = width * numComps;
+ const max = (1 << bpc) - 1;
+ let i = 0,
+ ii,
+ buf;
+ if (bpc === 1) {
+ let mask, loop1End, loop2End;
+ for (let j = 0; j < height; j++) {
+ loop1End = i + (rowComps & ~7);
+ loop2End = i + rowComps;
+ while (i < loop1End) {
+ buf = buffer[bufferPos++];
+ output[i] = buf >> 7 & 1;
+ output[i + 1] = buf >> 6 & 1;
+ output[i + 2] = buf >> 5 & 1;
+ output[i + 3] = buf >> 4 & 1;
+ output[i + 4] = buf >> 3 & 1;
+ output[i + 5] = buf >> 2 & 1;
+ output[i + 6] = buf >> 1 & 1;
+ output[i + 7] = buf & 1;
+ i += 8;
+ }
+ if (i < loop2End) {
+ buf = buffer[bufferPos++];
+ mask = 128;
+ while (i < loop2End) {
+ output[i++] = +!!(buf & mask);
+ mask >>= 1;
+ }
+ }
+ }
+ } else {
+ let bits = 0;
+ buf = 0;
+ for (i = 0, ii = length; i < ii; ++i) {
+ if (i % rowComps === 0) {
+ buf = 0;
+ bits = 0;
+ }
+ while (bits < bpc) {
+ buf = buf << 8 | buffer[bufferPos++];
+ bits += 8;
+ }
+ const remainingBits = bits - bpc;
+ let value = buf >> remainingBits;
+ if (value < 0) {
+ value = 0;
+ } else if (value > max) {
+ value = max;
+ }
+ output[i] = value;
+ buf &= (1 << remainingBits) - 1;
+ bits = remainingBits;
+ }
+ }
+ return output;
+ }
+ fillOpacity(rgbaBuf, width, height, actualHeight, image) {
+ const smask = this.smask;
+ const mask = this.mask;
+ let alphaBuf, sw, sh, i, ii, j;
+ if (smask) {
+ sw = smask.width;
+ sh = smask.height;
+ alphaBuf = new Uint8ClampedArray(sw * sh);
+ smask.fillGrayBuffer(alphaBuf);
+ if (sw !== width || sh !== height) {
+ alphaBuf = resizeImageMask(alphaBuf, smask.bpc, sw, sh, width, height);
+ }
+ } else if (mask) {
+ if (mask instanceof PDFImage) {
+ sw = mask.width;
+ sh = mask.height;
+ alphaBuf = new Uint8ClampedArray(sw * sh);
+ mask.numComps = 1;
+ mask.fillGrayBuffer(alphaBuf);
+ for (i = 0, ii = sw * sh; i < ii; ++i) {
+ alphaBuf[i] = 255 - alphaBuf[i];
+ }
+ if (sw !== width || sh !== height) {
+ alphaBuf = resizeImageMask(alphaBuf, mask.bpc, sw, sh, width, height);
+ }
+ } else if (Array.isArray(mask)) {
+ alphaBuf = new Uint8ClampedArray(width * height);
+ const numComps = this.numComps;
+ for (i = 0, ii = width * height; i < ii; ++i) {
+ let opacity = 0;
+ const imageOffset = i * numComps;
+ for (j = 0; j < numComps; ++j) {
+ const color = image[imageOffset + j];
+ const maskOffset = j * 2;
+ if (color < mask[maskOffset] || color > mask[maskOffset + 1]) {
+ opacity = 255;
+ break;
+ }
+ }
+ alphaBuf[i] = opacity;
+ }
+ } else {
+ throw new FormatError("Unknown mask format.");
+ }
+ }
+ if (alphaBuf) {
+ for (i = 0, j = 3, ii = width * actualHeight; i < ii; ++i, j += 4) {
+ rgbaBuf[j] = alphaBuf[i];
+ }
+ } else {
+ for (i = 0, j = 3, ii = width * actualHeight; i < ii; ++i, j += 4) {
+ rgbaBuf[j] = 255;
+ }
+ }
+ }
+ undoPreblend(buffer, width, height) {
+ const matte = this.smask?.matte;
+ if (!matte) {
+ return;
+ }
+ const matteRgb = this.colorSpace.getRgb(matte, 0);
+ const matteR = matteRgb[0];
+ const matteG = matteRgb[1];
+ const matteB = matteRgb[2];
+ const length = width * height * 4;
+ for (let i = 0; i < length; i += 4) {
+ const alpha = buffer[i + 3];
+ if (alpha === 0) {
+ buffer[i] = 255;
+ buffer[i + 1] = 255;
+ buffer[i + 2] = 255;
+ continue;
+ }
+ const k = 255 / alpha;
+ buffer[i] = (buffer[i] - matteR) * k + matteR;
+ buffer[i + 1] = (buffer[i + 1] - matteG) * k + matteG;
+ buffer[i + 2] = (buffer[i + 2] - matteB) * k + matteB;
+ }
+ }
+ async createImageData(forceRGBA = false, isOffscreenCanvasSupported = false) {
+ const drawWidth = this.drawWidth;
+ const drawHeight = this.drawHeight;
+ const imgData = {
+ width: drawWidth,
+ height: drawHeight,
+ interpolate: this.interpolate,
+ kind: 0,
+ data: null
+ };
+ const numComps = this.numComps;
+ const originalWidth = this.width;
+ const originalHeight = this.height;
+ const bpc = this.bpc;
+ const rowBytes = originalWidth * numComps * bpc + 7 >> 3;
+ const mustBeResized = isOffscreenCanvasSupported && ImageResizer.needsToBeResized(drawWidth, drawHeight);
+ if (!forceRGBA) {
+ let kind;
+ if (this.colorSpace.name === "DeviceGray" && bpc === 1) {
+ kind = ImageKind.GRAYSCALE_1BPP;
+ } else if (this.colorSpace.name === "DeviceRGB" && bpc === 8 && !this.needsDecode) {
+ kind = ImageKind.RGB_24BPP;
+ }
+ if (kind && !this.smask && !this.mask && drawWidth === originalWidth && drawHeight === originalHeight) {
+ const data = this.getImageBytes(originalHeight * rowBytes, {});
+ if (isOffscreenCanvasSupported) {
+ if (mustBeResized) {
+ return ImageResizer.createImage({
+ data,
+ kind,
+ width: drawWidth,
+ height: drawHeight,
+ interpolate: this.interpolate
+ }, this.needsDecode);
+ }
+ return this.createBitmap(kind, originalWidth, originalHeight, data);
+ }
+ imgData.kind = kind;
+ imgData.data = data;
+ if (this.needsDecode) {
+ assert(kind === ImageKind.GRAYSCALE_1BPP, "PDFImage.createImageData: The image must be grayscale.");
+ const buffer = imgData.data;
+ for (let i = 0, ii = buffer.length; i < ii; i++) {
+ buffer[i] ^= 0xff;
+ }
+ }
+ return imgData;
+ }
+ if (this.image instanceof JpegStream && !this.smask && !this.mask && !this.needsDecode) {
+ let imageLength = originalHeight * rowBytes;
+ if (isOffscreenCanvasSupported && !mustBeResized) {
+ let isHandled = false;
+ switch (this.colorSpace.name) {
+ case "DeviceGray":
+ imageLength *= 4;
+ isHandled = true;
+ break;
+ case "DeviceRGB":
+ imageLength = imageLength / 3 * 4;
+ isHandled = true;
+ break;
+ case "DeviceCMYK":
+ isHandled = true;
+ break;
+ }
+ if (isHandled) {
+ const rgba = this.getImageBytes(imageLength, {
+ drawWidth,
+ drawHeight,
+ forceRGBA: true
+ });
+ return this.createBitmap(ImageKind.RGBA_32BPP, drawWidth, drawHeight, rgba);
+ }
+ } else {
+ switch (this.colorSpace.name) {
+ case "DeviceGray":
+ imageLength *= 3;
+ case "DeviceRGB":
+ case "DeviceCMYK":
+ imgData.kind = ImageKind.RGB_24BPP;
+ imgData.data = this.getImageBytes(imageLength, {
+ drawWidth,
+ drawHeight,
+ forceRGB: true
+ });
+ if (mustBeResized) {
+ return ImageResizer.createImage(imgData);
+ }
+ return imgData;
+ }
+ }
+ }
+ }
+ const imgArray = this.getImageBytes(originalHeight * rowBytes, {
+ internal: true
+ });
+ const actualHeight = 0 | imgArray.length / rowBytes * drawHeight / originalHeight;
+ const comps = this.getComponents(imgArray);
+ let alpha01, maybeUndoPreblend;
+ let canvas, ctx, canvasImgData, data;
+ if (isOffscreenCanvasSupported && !mustBeResized) {
+ canvas = new OffscreenCanvas(drawWidth, drawHeight);
+ ctx = canvas.getContext("2d");
+ canvasImgData = ctx.createImageData(drawWidth, drawHeight);
+ data = canvasImgData.data;
+ }
+ imgData.kind = ImageKind.RGBA_32BPP;
+ if (!forceRGBA && !this.smask && !this.mask) {
+ if (!isOffscreenCanvasSupported || mustBeResized) {
+ imgData.kind = ImageKind.RGB_24BPP;
+ data = new Uint8ClampedArray(drawWidth * drawHeight * 3);
+ alpha01 = 0;
+ } else {
+ const arr = new Uint32Array(data.buffer);
+ arr.fill(FeatureTest.isLittleEndian ? 0xff000000 : 0x000000ff);
+ alpha01 = 1;
+ }
+ maybeUndoPreblend = false;
+ } else {
+ if (!isOffscreenCanvasSupported || mustBeResized) {
+ data = new Uint8ClampedArray(drawWidth * drawHeight * 4);
+ }
+ alpha01 = 1;
+ maybeUndoPreblend = true;
+ this.fillOpacity(data, drawWidth, drawHeight, actualHeight, comps);
+ }
+ if (this.needsDecode) {
+ this.decodeBuffer(comps);
+ }
+ this.colorSpace.fillRgb(data, originalWidth, originalHeight, drawWidth, drawHeight, actualHeight, bpc, comps, alpha01);
+ if (maybeUndoPreblend) {
+ this.undoPreblend(data, drawWidth, actualHeight);
+ }
+ if (isOffscreenCanvasSupported && !mustBeResized) {
+ ctx.putImageData(canvasImgData, 0, 0);
+ const bitmap = canvas.transferToImageBitmap();
+ return {
+ data: null,
+ width: drawWidth,
+ height: drawHeight,
+ bitmap,
+ interpolate: this.interpolate
+ };
+ }
+ imgData.data = data;
+ if (mustBeResized) {
+ return ImageResizer.createImage(imgData);
+ }
+ return imgData;
+ }
+ fillGrayBuffer(buffer) {
+ const numComps = this.numComps;
+ if (numComps !== 1) {
+ throw new FormatError(`Reading gray scale from a color image: ${numComps}`);
+ }
+ const width = this.width;
+ const height = this.height;
+ const bpc = this.bpc;
+ const rowBytes = width * numComps * bpc + 7 >> 3;
+ const imgArray = this.getImageBytes(height * rowBytes, {
+ internal: true
+ });
+ const comps = this.getComponents(imgArray);
+ let i, length;
+ if (bpc === 1) {
+ length = width * height;
+ if (this.needsDecode) {
+ for (i = 0; i < length; ++i) {
+ buffer[i] = comps[i] - 1 & 255;
+ }
+ } else {
+ for (i = 0; i < length; ++i) {
+ buffer[i] = -comps[i] & 255;
+ }
+ }
+ return;
+ }
+ if (this.needsDecode) {
+ this.decodeBuffer(comps);
+ }
+ length = width * height;
+ const scale = 255 / ((1 << bpc) - 1);
+ for (i = 0; i < length; ++i) {
+ buffer[i] = scale * comps[i];
+ }
+ }
+ createBitmap(kind, width, height, src) {
+ const canvas = new OffscreenCanvas(width, height);
+ const ctx = canvas.getContext("2d");
+ let imgData;
+ if (kind === ImageKind.RGBA_32BPP) {
+ imgData = new ImageData(src, width, height);
+ } else {
+ imgData = ctx.createImageData(width, height);
+ convertToRGBA({
+ kind,
+ src,
+ dest: new Uint32Array(imgData.data.buffer),
+ width,
+ height,
+ inverseDecode: this.needsDecode
+ });
+ }
+ ctx.putImageData(imgData, 0, 0);
+ const bitmap = canvas.transferToImageBitmap();
+ return {
+ data: null,
+ width,
+ height,
+ bitmap,
+ interpolate: this.interpolate
+ };
+ }
+ getImageBytes(length, {
+ drawWidth,
+ drawHeight,
+ forceRGBA = false,
+ forceRGB = false,
+ internal = false
+ }) {
+ this.image.reset();
+ this.image.drawWidth = drawWidth || this.width;
+ this.image.drawHeight = drawHeight || this.height;
+ this.image.forceRGBA = !!forceRGBA;
+ this.image.forceRGB = !!forceRGB;
+ const imageBytes = this.image.getBytes(length);
+ if (internal || this.image instanceof DecodeStream) {
+ return imageBytes;
+ }
+ assert(imageBytes instanceof Uint8Array, 'PDFImage.getImageBytes: Unsupported "imageBytes" type.');
+ return new Uint8Array(imageBytes);
+ }
+}
+
+;// CONCATENATED MODULE: ./src/core/evaluator.js
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+const DefaultPartialEvaluatorOptions = Object.freeze({
+ maxImageSize: -1,
+ disableFontFace: false,
+ ignoreErrors: false,
+ isEvalSupported: true,
+ isOffscreenCanvasSupported: false,
+ canvasMaxAreaInBytes: -1,
+ fontExtraProperties: false,
+ useSystemFonts: true,
+ cMapUrl: null,
+ standardFontDataUrl: null
+});
+const PatternType = {
+ TILING: 1,
+ SHADING: 2
+};
+const TEXT_CHUNK_BATCH_SIZE = 10;
+const deferred = Promise.resolve();
+function normalizeBlendMode(value, parsingArray = false) {
+ if (Array.isArray(value)) {
+ for (const val of value) {
+ const maybeBM = normalizeBlendMode(val, true);
+ if (maybeBM) {
+ return maybeBM;
+ }
+ }
+ warn(`Unsupported blend mode Array: ${value}`);
+ return "source-over";
+ }
+ if (!(value instanceof Name)) {
+ if (parsingArray) {
+ return null;
+ }
+ return "source-over";
+ }
+ switch (value.name) {
+ case "Normal":
+ case "Compatible":
+ return "source-over";
+ case "Multiply":
+ return "multiply";
+ case "Screen":
+ return "screen";
+ case "Overlay":
+ return "overlay";
+ case "Darken":
+ return "darken";
+ case "Lighten":
+ return "lighten";
+ case "ColorDodge":
+ return "color-dodge";
+ case "ColorBurn":
+ return "color-burn";
+ case "HardLight":
+ return "hard-light";
+ case "SoftLight":
+ return "soft-light";
+ case "Difference":
+ return "difference";
+ case "Exclusion":
+ return "exclusion";
+ case "Hue":
+ return "hue";
+ case "Saturation":
+ return "saturation";
+ case "Color":
+ return "color";
+ case "Luminosity":
+ return "luminosity";
+ }
+ if (parsingArray) {
+ return null;
+ }
+ warn(`Unsupported blend mode: ${value.name}`);
+ return "source-over";
+}
+function incrementCachedImageMaskCount(data) {
+ if (data.fn === OPS.paintImageMaskXObject && data.args[0]?.count > 0) {
+ data.args[0].count++;
+ }
+}
+class TimeSlotManager {
+ static TIME_SLOT_DURATION_MS = 20;
+ static CHECK_TIME_EVERY = 100;
+ constructor() {
+ this.reset();
+ }
+ check() {
+ if (++this.checked < TimeSlotManager.CHECK_TIME_EVERY) {
+ return false;
+ }
+ this.checked = 0;
+ return this.endTime <= Date.now();
+ }
+ reset() {
+ this.endTime = Date.now() + TimeSlotManager.TIME_SLOT_DURATION_MS;
+ this.checked = 0;
+ }
+}
+class PartialEvaluator {
+ constructor({
+ xref,
+ handler,
+ pageIndex,
+ idFactory,
+ fontCache,
+ builtInCMapCache,
+ standardFontDataCache,
+ globalImageCache,
+ systemFontCache,
+ options = null
+ }) {
+ this.xref = xref;
+ this.handler = handler;
+ this.pageIndex = pageIndex;
+ this.idFactory = idFactory;
+ this.fontCache = fontCache;
+ this.builtInCMapCache = builtInCMapCache;
+ this.standardFontDataCache = standardFontDataCache;
+ this.globalImageCache = globalImageCache;
+ this.systemFontCache = systemFontCache;
+ this.options = options || DefaultPartialEvaluatorOptions;
+ this.parsingType3Font = false;
+ this._regionalImageCache = new RegionalImageCache();
+ this._fetchBuiltInCMapBound = this.fetchBuiltInCMap.bind(this);
+ ImageResizer.setMaxArea(this.options.canvasMaxAreaInBytes);
+ }
+ get _pdfFunctionFactory() {
+ const pdfFunctionFactory = new PDFFunctionFactory({
+ xref: this.xref,
+ isEvalSupported: this.options.isEvalSupported
+ });
+ return shadow(this, "_pdfFunctionFactory", pdfFunctionFactory);
+ }
+ clone(newOptions = null) {
+ const newEvaluator = Object.create(this);
+ newEvaluator.options = Object.assign(Object.create(null), this.options, newOptions);
+ return newEvaluator;
+ }
+ hasBlendModes(resources, nonBlendModesSet) {
+ if (!(resources instanceof Dict)) {
+ return false;
+ }
+ if (resources.objId && nonBlendModesSet.has(resources.objId)) {
+ return false;
+ }
+ const processed = new RefSet(nonBlendModesSet);
+ if (resources.objId) {
+ processed.put(resources.objId);
+ }
+ const nodes = [resources],
+ xref = this.xref;
+ while (nodes.length) {
+ const node = nodes.shift();
+ const graphicStates = node.get("ExtGState");
+ if (graphicStates instanceof Dict) {
+ for (let graphicState of graphicStates.getRawValues()) {
+ if (graphicState instanceof Ref) {
+ if (processed.has(graphicState)) {
+ continue;
+ }
+ try {
+ graphicState = xref.fetch(graphicState);
+ } catch (ex) {
+ processed.put(graphicState);
+ info(`hasBlendModes - ignoring ExtGState: "${ex}".`);
+ continue;
+ }
+ }
+ if (!(graphicState instanceof Dict)) {
+ continue;
+ }
+ if (graphicState.objId) {
+ processed.put(graphicState.objId);
+ }
+ const bm = graphicState.get("BM");
+ if (bm instanceof Name) {
+ if (bm.name !== "Normal") {
+ return true;
+ }
+ continue;
+ }
+ if (bm !== undefined && Array.isArray(bm)) {
+ for (const element of bm) {
+ if (element instanceof Name && element.name !== "Normal") {
+ return true;
+ }
+ }
+ }
+ }
+ }
+ const xObjects = node.get("XObject");
+ if (!(xObjects instanceof Dict)) {
+ continue;
+ }
+ for (let xObject of xObjects.getRawValues()) {
+ if (xObject instanceof Ref) {
+ if (processed.has(xObject)) {
+ continue;
+ }
+ try {
+ xObject = xref.fetch(xObject);
+ } catch (ex) {
+ processed.put(xObject);
+ info(`hasBlendModes - ignoring XObject: "${ex}".`);
+ continue;
+ }
+ }
+ if (!(xObject instanceof BaseStream)) {
+ continue;
+ }
+ if (xObject.dict.objId) {
+ processed.put(xObject.dict.objId);
+ }
+ const xResources = xObject.dict.get("Resources");
+ if (!(xResources instanceof Dict)) {
+ continue;
+ }
+ if (xResources.objId && processed.has(xResources.objId)) {
+ continue;
+ }
+ nodes.push(xResources);
+ if (xResources.objId) {
+ processed.put(xResources.objId);
+ }
+ }
+ }
+ for (const ref of processed) {
+ nonBlendModesSet.put(ref);
+ }
+ return false;
+ }
+ async fetchBuiltInCMap(name) {
+ const cachedData = this.builtInCMapCache.get(name);
+ if (cachedData) {
+ return cachedData;
+ }
+ let data;
+ if (this.options.cMapUrl !== null) {
+ const url = `${this.options.cMapUrl}${name}.bcmap`;
+ const response = await fetch(url);
+ if (!response.ok) {
+ throw new Error(`fetchBuiltInCMap: failed to fetch file "${url}" with "${response.statusText}".`);
+ }
+ data = {
+ cMapData: new Uint8Array(await response.arrayBuffer()),
+ compressionType: CMapCompressionType.BINARY
+ };
+ } else {
+ data = await this.handler.sendWithPromise("FetchBuiltInCMap", {
+ name
+ });
+ }
+ if (data.compressionType !== CMapCompressionType.NONE) {
+ this.builtInCMapCache.set(name, data);
+ }
+ return data;
+ }
+ async fetchStandardFontData(name) {
+ const cachedData = this.standardFontDataCache.get(name);
+ if (cachedData) {
+ return new Stream(cachedData);
+ }
+ if (this.options.useSystemFonts && name !== "Symbol" && name !== "ZapfDingbats") {
+ return null;
+ }
+ const standardFontNameToFileName = getFontNameToFileMap(),
+ filename = standardFontNameToFileName[name];
+ let data;
+ if (this.options.standardFontDataUrl !== null) {
+ const url = `${this.options.standardFontDataUrl}${filename}`;
+ const response = await fetch(url);
+ if (!response.ok) {
+ warn(`fetchStandardFontData: failed to fetch file "${url}" with "${response.statusText}".`);
+ } else {
+ data = new Uint8Array(await response.arrayBuffer());
+ }
+ } else {
+ try {
+ data = await this.handler.sendWithPromise("FetchStandardFontData", {
+ filename
+ });
+ } catch (e) {
+ warn(`fetchStandardFontData: failed to fetch file "${filename}" with "${e}".`);
+ }
+ }
+ if (!data) {
+ return null;
+ }
+ this.standardFontDataCache.set(name, data);
+ return new Stream(data);
+ }
+ async buildFormXObject(resources, xobj, smask, operatorList, task, initialState, localColorSpaceCache) {
+ const dict = xobj.dict;
+ const matrix = dict.getArray("Matrix");
+ let bbox = dict.getArray("BBox");
+ bbox = Array.isArray(bbox) && bbox.length === 4 ? Util.normalizeRect(bbox) : null;
+ let optionalContent, groupOptions;
+ if (dict.has("OC")) {
+ optionalContent = await this.parseMarkedContentProps(dict.get("OC"), resources);
+ }
+ if (optionalContent !== undefined) {
+ operatorList.addOp(OPS.beginMarkedContentProps, ["OC", optionalContent]);
+ }
+ const group = dict.get("Group");
+ if (group) {
+ groupOptions = {
+ matrix,
+ bbox,
+ smask,
+ isolated: false,
+ knockout: false
+ };
+ const groupSubtype = group.get("S");
+ let colorSpace = null;
+ if (isName(groupSubtype, "Transparency")) {
+ groupOptions.isolated = group.get("I") || false;
+ groupOptions.knockout = group.get("K") || false;
+ if (group.has("CS")) {
+ const cs = group.getRaw("CS");
+ const cachedColorSpace = ColorSpace.getCached(cs, this.xref, localColorSpaceCache);
+ if (cachedColorSpace) {
+ colorSpace = cachedColorSpace;
+ } else {
+ colorSpace = await this.parseColorSpace({
+ cs,
+ resources,
+ localColorSpaceCache
+ });
+ }
+ }
+ }
+ if (smask?.backdrop) {
+ colorSpace ||= ColorSpace.singletons.rgb;
+ smask.backdrop = colorSpace.getRgb(smask.backdrop, 0);
+ }
+ operatorList.addOp(OPS.beginGroup, [groupOptions]);
+ }
+ const args = group ? [matrix, null] : [matrix, bbox];
+ operatorList.addOp(OPS.paintFormXObjectBegin, args);
+ await this.getOperatorList({
+ stream: xobj,
+ task,
+ resources: dict.get("Resources") || resources,
+ operatorList,
+ initialState
+ });
+ operatorList.addOp(OPS.paintFormXObjectEnd, []);
+ if (group) {
+ operatorList.addOp(OPS.endGroup, [groupOptions]);
+ }
+ if (optionalContent !== undefined) {
+ operatorList.addOp(OPS.endMarkedContent, []);
+ }
+ }
+ _sendImgData(objId, imgData, cacheGlobally = false) {
+ const transfers = imgData ? [imgData.bitmap || imgData.data.buffer] : null;
+ if (this.parsingType3Font || cacheGlobally) {
+ return this.handler.send("commonobj", [objId, "Image", imgData], transfers);
+ }
+ return this.handler.send("obj", [objId, this.pageIndex, "Image", imgData], transfers);
+ }
+ async buildPaintImageXObject({
+ resources,
+ image,
+ isInline = false,
+ operatorList,
+ cacheKey,
+ localImageCache,
+ localColorSpaceCache
+ }) {
+ const dict = image.dict;
+ const imageRef = dict.objId;
+ const w = dict.get("W", "Width");
+ const h = dict.get("H", "Height");
+ if (!(w && typeof w === "number") || !(h && typeof h === "number")) {
+ warn("Image dimensions are missing, or not numbers.");
+ return;
+ }
+ const maxImageSize = this.options.maxImageSize;
+ if (maxImageSize !== -1 && w * h > maxImageSize) {
+ const msg = "Image exceeded maximum allowed size and was removed.";
+ if (this.options.ignoreErrors) {
+ warn(msg);
+ return;
+ }
+ throw new Error(msg);
+ }
+ let optionalContent;
+ if (dict.has("OC")) {
+ optionalContent = await this.parseMarkedContentProps(dict.get("OC"), resources);
+ }
+ const imageMask = dict.get("IM", "ImageMask") || false;
+ let imgData, args;
+ if (imageMask) {
+ const interpolate = dict.get("I", "Interpolate");
+ const bitStrideLength = w + 7 >> 3;
+ const imgArray = image.getBytes(bitStrideLength * h);
+ const decode = dict.getArray("D", "Decode");
+ if (this.parsingType3Font) {
+ imgData = PDFImage.createRawMask({
+ imgArray,
+ width: w,
+ height: h,
+ imageIsFromDecodeStream: image instanceof DecodeStream,
+ inverseDecode: decode?.[0] > 0,
+ interpolate
+ });
+ imgData.cached = !!cacheKey;
+ args = [imgData];
+ operatorList.addImageOps(OPS.paintImageMaskXObject, args, optionalContent);
+ if (cacheKey) {
+ const cacheData = {
+ fn: OPS.paintImageMaskXObject,
+ args,
+ optionalContent
+ };
+ localImageCache.set(cacheKey, imageRef, cacheData);
+ if (imageRef) {
+ this._regionalImageCache.set(null, imageRef, cacheData);
+ }
+ }
+ return;
+ }
+ imgData = await PDFImage.createMask({
+ imgArray,
+ width: w,
+ height: h,
+ imageIsFromDecodeStream: image instanceof DecodeStream,
+ inverseDecode: decode?.[0] > 0,
+ interpolate,
+ isOffscreenCanvasSupported: this.options.isOffscreenCanvasSupported
+ });
+ if (imgData.isSingleOpaquePixel) {
+ operatorList.addImageOps(OPS.paintSolidColorImageMask, [], optionalContent);
+ if (cacheKey) {
+ const cacheData = {
+ fn: OPS.paintSolidColorImageMask,
+ args: [],
+ optionalContent
+ };
+ localImageCache.set(cacheKey, imageRef, cacheData);
+ if (imageRef) {
+ this._regionalImageCache.set(null, imageRef, cacheData);
+ }
+ }
+ return;
+ }
+ const objId = `mask_${this.idFactory.createObjId()}`;
+ operatorList.addDependency(objId);
+ imgData.dataLen = imgData.bitmap ? imgData.width * imgData.height * 4 : imgData.data.length;
+ this._sendImgData(objId, imgData);
+ args = [{
+ data: objId,
+ width: imgData.width,
+ height: imgData.height,
+ interpolate: imgData.interpolate,
+ count: 1
+ }];
+ operatorList.addImageOps(OPS.paintImageMaskXObject, args, optionalContent);
+ if (cacheKey) {
+ const cacheData = {
+ fn: OPS.paintImageMaskXObject,
+ args,
+ optionalContent
+ };
+ localImageCache.set(cacheKey, imageRef, cacheData);
+ if (imageRef) {
+ this._regionalImageCache.set(null, imageRef, cacheData);
+ }
+ }
+ return;
+ }
+ const SMALL_IMAGE_DIMENSIONS = 200;
+ if (isInline && !dict.has("SMask") && !dict.has("Mask") && w + h < SMALL_IMAGE_DIMENSIONS) {
+ const imageObj = new PDFImage({
+ xref: this.xref,
+ res: resources,
+ image,
+ isInline,
+ pdfFunctionFactory: this._pdfFunctionFactory,
+ localColorSpaceCache
+ });
+ imgData = await imageObj.createImageData(true, false);
+ operatorList.isOffscreenCanvasSupported = this.options.isOffscreenCanvasSupported;
+ operatorList.addImageOps(OPS.paintInlineImageXObject, [imgData], optionalContent);
+ return;
+ }
+ let objId = `img_${this.idFactory.createObjId()}`,
+ cacheGlobally = false;
+ if (this.parsingType3Font) {
+ objId = `${this.idFactory.getDocId()}_type3_${objId}`;
+ } else if (cacheKey && imageRef) {
+ cacheGlobally = this.globalImageCache.shouldCache(imageRef, this.pageIndex);
+ if (cacheGlobally) {
+ assert(!isInline, "Cannot cache an inline image globally.");
+ objId = `${this.idFactory.getDocId()}_${objId}`;
+ }
+ }
+ operatorList.addDependency(objId);
+ args = [objId, w, h];
+ operatorList.addImageOps(OPS.paintImageXObject, args, optionalContent);
+ if (cacheGlobally && w * h > 250000) {
+ const localLength = await this.handler.sendWithPromise("commonobj", [objId, "CopyLocalImage", {
+ imageRef
+ }]);
+ if (localLength) {
+ this.globalImageCache.setData(imageRef, {
+ objId,
+ fn: OPS.paintImageXObject,
+ args,
+ optionalContent,
+ byteSize: 0
+ });
+ this.globalImageCache.addByteSize(imageRef, localLength);
+ return;
+ }
+ }
+ PDFImage.buildImage({
+ xref: this.xref,
+ res: resources,
+ image,
+ isInline,
+ pdfFunctionFactory: this._pdfFunctionFactory,
+ localColorSpaceCache
+ }).then(async imageObj => {
+ imgData = await imageObj.createImageData(false, this.options.isOffscreenCanvasSupported);
+ imgData.dataLen = imgData.bitmap ? imgData.width * imgData.height * 4 : imgData.data.length;
+ imgData.ref = imageRef;
+ if (cacheGlobally) {
+ this.globalImageCache.addByteSize(imageRef, imgData.dataLen);
+ }
+ return this._sendImgData(objId, imgData, cacheGlobally);
+ }).catch(reason => {
+ warn(`Unable to decode image "${objId}": "${reason}".`);
+ return this._sendImgData(objId, null, cacheGlobally);
+ });
+ if (cacheKey) {
+ const cacheData = {
+ fn: OPS.paintImageXObject,
+ args,
+ optionalContent
+ };
+ localImageCache.set(cacheKey, imageRef, cacheData);
+ if (imageRef) {
+ this._regionalImageCache.set(null, imageRef, cacheData);
+ if (cacheGlobally) {
+ this.globalImageCache.setData(imageRef, {
+ objId,
+ fn: OPS.paintImageXObject,
+ args,
+ optionalContent,
+ byteSize: 0
+ });
+ }
+ }
+ }
+ }
+ handleSMask(smask, resources, operatorList, task, stateManager, localColorSpaceCache) {
+ const smaskContent = smask.get("G");
+ const smaskOptions = {
+ subtype: smask.get("S").name,
+ backdrop: smask.get("BC")
+ };
+ const transferObj = smask.get("TR");
+ if (isPDFFunction(transferObj)) {
+ const transferFn = this._pdfFunctionFactory.create(transferObj);
+ const transferMap = new Uint8Array(256);
+ const tmp = new Float32Array(1);
+ for (let i = 0; i < 256; i++) {
+ tmp[0] = i / 255;
+ transferFn(tmp, 0, tmp, 0);
+ transferMap[i] = tmp[0] * 255 | 0;
+ }
+ smaskOptions.transferMap = transferMap;
+ }
+ return this.buildFormXObject(resources, smaskContent, smaskOptions, operatorList, task, stateManager.state.clone(), localColorSpaceCache);
+ }
+ handleTransferFunction(tr) {
+ let transferArray;
+ if (Array.isArray(tr)) {
+ transferArray = tr;
+ } else if (isPDFFunction(tr)) {
+ transferArray = [tr];
+ } else {
+ return null;
+ }
+ const transferMaps = [];
+ let numFns = 0,
+ numEffectfulFns = 0;
+ for (const entry of transferArray) {
+ const transferObj = this.xref.fetchIfRef(entry);
+ numFns++;
+ if (isName(transferObj, "Identity")) {
+ transferMaps.push(null);
+ continue;
+ } else if (!isPDFFunction(transferObj)) {
+ return null;
+ }
+ const transferFn = this._pdfFunctionFactory.create(transferObj);
+ const transferMap = new Uint8Array(256),
+ tmp = new Float32Array(1);
+ for (let j = 0; j < 256; j++) {
+ tmp[0] = j / 255;
+ transferFn(tmp, 0, tmp, 0);
+ transferMap[j] = tmp[0] * 255 | 0;
+ }
+ transferMaps.push(transferMap);
+ numEffectfulFns++;
+ }
+ if (!(numFns === 1 || numFns === 4)) {
+ return null;
+ }
+ if (numEffectfulFns === 0) {
+ return null;
+ }
+ return transferMaps;
+ }
+ handleTilingType(fn, color, resources, pattern, patternDict, operatorList, task, localTilingPatternCache) {
+ const tilingOpList = new OperatorList();
+ const patternResources = Dict.merge({
+ xref: this.xref,
+ dictArray: [patternDict.get("Resources"), resources]
+ });
+ return this.getOperatorList({
+ stream: pattern,
+ task,
+ resources: patternResources,
+ operatorList: tilingOpList
+ }).then(function () {
+ const operatorListIR = tilingOpList.getIR();
+ const tilingPatternIR = getTilingPatternIR(operatorListIR, patternDict, color);
+ operatorList.addDependencies(tilingOpList.dependencies);
+ operatorList.addOp(fn, tilingPatternIR);
+ if (patternDict.objId) {
+ localTilingPatternCache.set(null, patternDict.objId, {
+ operatorListIR,
+ dict: patternDict
+ });
+ }
+ }).catch(reason => {
+ if (reason instanceof AbortException) {
+ return;
+ }
+ if (this.options.ignoreErrors) {
+ warn(`handleTilingType - ignoring pattern: "${reason}".`);
+ return;
+ }
+ throw reason;
+ });
+ }
+ async handleSetFont(resources, fontArgs, fontRef, operatorList, task, state, fallbackFontDict = null, cssFontInfo = null) {
+ const fontName = fontArgs?.[0] instanceof Name ? fontArgs[0].name : null;
+ let translated = await this.loadFont(fontName, fontRef, resources, fallbackFontDict, cssFontInfo);
+ if (translated.font.isType3Font) {
+ try {
+ await translated.loadType3Data(this, resources, task);
+ operatorList.addDependencies(translated.type3Dependencies);
+ } catch (reason) {
+ translated = new TranslatedFont({
+ loadedName: "g_font_error",
+ font: new ErrorFont(`Type3 font load error: ${reason}`),
+ dict: translated.font,
+ evaluatorOptions: this.options
+ });
+ }
+ }
+ state.font = translated.font;
+ translated.send(this.handler);
+ return translated.loadedName;
+ }
+ handleText(chars, state) {
+ const font = state.font;
+ const glyphs = font.charsToGlyphs(chars);
+ if (font.data) {
+ const isAddToPathSet = !!(state.textRenderingMode & TextRenderingMode.ADD_TO_PATH_FLAG);
+ if (isAddToPathSet || state.fillColorSpace.name === "Pattern" || font.disableFontFace || this.options.disableFontFace) {
+ PartialEvaluator.buildFontPaths(font, glyphs, this.handler, this.options);
+ }
+ }
+ return glyphs;
+ }
+ ensureStateFont(state) {
+ if (state.font) {
+ return;
+ }
+ const reason = new FormatError("Missing setFont (Tf) operator before text rendering operator.");
+ if (this.options.ignoreErrors) {
+ warn(`ensureStateFont: "${reason}".`);
+ return;
+ }
+ throw reason;
+ }
+ async setGState({
+ resources,
+ gState,
+ operatorList,
+ cacheKey,
+ task,
+ stateManager,
+ localGStateCache,
+ localColorSpaceCache
+ }) {
+ const gStateRef = gState.objId;
+ let isSimpleGState = true;
+ const gStateObj = [];
+ let promise = Promise.resolve();
+ for (const key of gState.getKeys()) {
+ const value = gState.get(key);
+ switch (key) {
+ case "Type":
+ break;
+ case "LW":
+ case "LC":
+ case "LJ":
+ case "ML":
+ case "D":
+ case "RI":
+ case "FL":
+ case "CA":
+ case "ca":
+ gStateObj.push([key, value]);
+ break;
+ case "Font":
+ isSimpleGState = false;
+ promise = promise.then(() => this.handleSetFont(resources, null, value[0], operatorList, task, stateManager.state).then(function (loadedName) {
+ operatorList.addDependency(loadedName);
+ gStateObj.push([key, [loadedName, value[1]]]);
+ }));
+ break;
+ case "BM":
+ gStateObj.push([key, normalizeBlendMode(value)]);
+ break;
+ case "SMask":
+ if (isName(value, "None")) {
+ gStateObj.push([key, false]);
+ break;
+ }
+ if (value instanceof Dict) {
+ isSimpleGState = false;
+ promise = promise.then(() => this.handleSMask(value, resources, operatorList, task, stateManager, localColorSpaceCache));
+ gStateObj.push([key, true]);
+ } else {
+ warn("Unsupported SMask type");
+ }
+ break;
+ case "TR":
+ const transferMaps = this.handleTransferFunction(value);
+ gStateObj.push([key, transferMaps]);
+ break;
+ case "OP":
+ case "op":
+ case "OPM":
+ case "BG":
+ case "BG2":
+ case "UCR":
+ case "UCR2":
+ case "TR2":
+ case "HT":
+ case "SM":
+ case "SA":
+ case "AIS":
+ case "TK":
+ info("graphic state operator " + key);
+ break;
+ default:
+ info("Unknown graphic state operator " + key);
+ break;
+ }
+ }
+ await promise;
+ if (gStateObj.length > 0) {
+ operatorList.addOp(OPS.setGState, [gStateObj]);
+ }
+ if (isSimpleGState) {
+ localGStateCache.set(cacheKey, gStateRef, gStateObj);
+ }
+ }
+ loadFont(fontName, font, resources, fallbackFontDict = null, cssFontInfo = null) {
+ const errorFont = async () => {
+ return new TranslatedFont({
+ loadedName: "g_font_error",
+ font: new ErrorFont(`Font "${fontName}" is not available.`),
+ dict: font,
+ evaluatorOptions: this.options
+ });
+ };
+ let fontRef;
+ if (font) {
+ if (font instanceof Ref) {
+ fontRef = font;
+ }
+ } else {
+ const fontRes = resources.get("Font");
+ if (fontRes) {
+ fontRef = fontRes.getRaw(fontName);
+ }
+ }
+ if (fontRef) {
+ if (this.parsingType3Font && this.type3FontRefs.has(fontRef)) {
+ return errorFont();
+ }
+ if (this.fontCache.has(fontRef)) {
+ return this.fontCache.get(fontRef);
+ }
+ font = this.xref.fetchIfRef(fontRef);
+ }
+ if (!(font instanceof Dict)) {
+ if (!this.options.ignoreErrors && !this.parsingType3Font) {
+ warn(`Font "${fontName}" is not available.`);
+ return errorFont();
+ }
+ warn(`Font "${fontName}" is not available -- attempting to fallback to a default font.`);
+ font = fallbackFontDict || PartialEvaluator.fallbackFontDict;
+ }
+ if (font.cacheKey && this.fontCache.has(font.cacheKey)) {
+ return this.fontCache.get(font.cacheKey);
+ }
+ const fontCapability = new PromiseCapability();
+ let preEvaluatedFont;
+ try {
+ preEvaluatedFont = this.preEvaluateFont(font);
+ preEvaluatedFont.cssFontInfo = cssFontInfo;
+ } catch (reason) {
+ warn(`loadFont - preEvaluateFont failed: "${reason}".`);
+ return errorFont();
+ }
+ const {
+ descriptor,
+ hash
+ } = preEvaluatedFont;
+ const fontRefIsRef = fontRef instanceof Ref;
+ let fontID;
+ if (hash && descriptor instanceof Dict) {
+ const fontAliases = descriptor.fontAliases ||= Object.create(null);
+ if (fontAliases[hash]) {
+ const aliasFontRef = fontAliases[hash].aliasRef;
+ if (fontRefIsRef && aliasFontRef && this.fontCache.has(aliasFontRef)) {
+ this.fontCache.putAlias(fontRef, aliasFontRef);
+ return this.fontCache.get(fontRef);
+ }
+ } else {
+ fontAliases[hash] = {
+ fontID: this.idFactory.createFontId()
+ };
+ }
+ if (fontRefIsRef) {
+ fontAliases[hash].aliasRef = fontRef;
+ }
+ fontID = fontAliases[hash].fontID;
+ } else {
+ fontID = this.idFactory.createFontId();
+ }
+ assert(fontID?.startsWith("f"), 'The "fontID" must be (correctly) defined.');
+ if (fontRefIsRef) {
+ this.fontCache.put(fontRef, fontCapability.promise);
+ } else {
+ font.cacheKey = `cacheKey_${fontID}`;
+ this.fontCache.put(font.cacheKey, fontCapability.promise);
+ }
+ font.loadedName = `${this.idFactory.getDocId()}_${fontID}`;
+ this.translateFont(preEvaluatedFont).then(translatedFont => {
+ fontCapability.resolve(new TranslatedFont({
+ loadedName: font.loadedName,
+ font: translatedFont,
+ dict: font,
+ evaluatorOptions: this.options
+ }));
+ }).catch(reason => {
+ warn(`loadFont - translateFont failed: "${reason}".`);
+ fontCapability.resolve(new TranslatedFont({
+ loadedName: font.loadedName,
+ font: new ErrorFont(reason instanceof Error ? reason.message : reason),
+ dict: font,
+ evaluatorOptions: this.options
+ }));
+ });
+ return fontCapability.promise;
+ }
+ buildPath(operatorList, fn, args, parsingText = false) {
+ const lastIndex = operatorList.length - 1;
+ if (!args) {
+ args = [];
+ }
+ if (lastIndex < 0 || operatorList.fnArray[lastIndex] !== OPS.constructPath) {
+ if (parsingText) {
+ warn(`Encountered path operator "${fn}" inside of a text object.`);
+ operatorList.addOp(OPS.save, null);
+ }
+ let minMax;
+ switch (fn) {
+ case OPS.rectangle:
+ const x = args[0] + args[2];
+ const y = args[1] + args[3];
+ minMax = [Math.min(args[0], x), Math.min(args[1], y), Math.max(args[0], x), Math.max(args[1], y)];
+ break;
+ case OPS.moveTo:
+ case OPS.lineTo:
+ minMax = [args[0], args[1], args[0], args[1]];
+ break;
+ default:
+ minMax = [Infinity, Infinity, -Infinity, -Infinity];
+ break;
+ }
+ operatorList.addOp(OPS.constructPath, [[fn], args, minMax]);
+ if (parsingText) {
+ operatorList.addOp(OPS.restore, null);
+ }
+ } else {
+ const opArgs = operatorList.argsArray[lastIndex];
+ opArgs[0].push(fn);
+ opArgs[1].push(...args);
+ const minMax = opArgs[2];
+ switch (fn) {
+ case OPS.rectangle:
+ const x = args[0] + args[2];
+ const y = args[1] + args[3];
+ minMax[0] = Math.min(minMax[0], args[0], x);
+ minMax[1] = Math.min(minMax[1], args[1], y);
+ minMax[2] = Math.max(minMax[2], args[0], x);
+ minMax[3] = Math.max(minMax[3], args[1], y);
+ break;
+ case OPS.moveTo:
+ case OPS.lineTo:
+ minMax[0] = Math.min(minMax[0], args[0]);
+ minMax[1] = Math.min(minMax[1], args[1]);
+ minMax[2] = Math.max(minMax[2], args[0]);
+ minMax[3] = Math.max(minMax[3], args[1]);
+ break;
+ }
+ }
+ }
+ parseColorSpace({
+ cs,
+ resources,
+ localColorSpaceCache
+ }) {
+ return ColorSpace.parseAsync({
+ cs,
+ xref: this.xref,
+ resources,
+ pdfFunctionFactory: this._pdfFunctionFactory,
+ localColorSpaceCache
+ }).catch(reason => {
+ if (reason instanceof AbortException) {
+ return null;
+ }
+ if (this.options.ignoreErrors) {
+ warn(`parseColorSpace - ignoring ColorSpace: "${reason}".`);
+ return null;
+ }
+ throw reason;
+ });
+ }
+ parseShading({
+ shading,
+ resources,
+ localColorSpaceCache,
+ localShadingPatternCache
+ }) {
+ let id = localShadingPatternCache.get(shading);
+ if (!id) {
+ var shadingFill = Pattern.parseShading(shading, this.xref, resources, this._pdfFunctionFactory, localColorSpaceCache);
+ const patternIR = shadingFill.getIR();
+ id = `pattern_${this.idFactory.createObjId()}`;
+ if (this.parsingType3Font) {
+ id = `${this.idFactory.getDocId()}_type3_${id}`;
+ }
+ localShadingPatternCache.set(shading, id);
+ if (this.parsingType3Font) {
+ this.handler.send("commonobj", [id, "Pattern", patternIR]);
+ } else {
+ this.handler.send("obj", [id, this.pageIndex, "Pattern", patternIR]);
+ }
+ }
+ return id;
+ }
+ handleColorN(operatorList, fn, args, cs, patterns, resources, task, localColorSpaceCache, localTilingPatternCache, localShadingPatternCache) {
+ const patternName = args.pop();
+ if (patternName instanceof Name) {
+ const rawPattern = patterns.getRaw(patternName.name);
+ const localTilingPattern = rawPattern instanceof Ref && localTilingPatternCache.getByRef(rawPattern);
+ if (localTilingPattern) {
+ try {
+ const color = cs.base ? cs.base.getRgb(args, 0) : null;
+ const tilingPatternIR = getTilingPatternIR(localTilingPattern.operatorListIR, localTilingPattern.dict, color);
+ operatorList.addOp(fn, tilingPatternIR);
+ return undefined;
+ } catch {}
+ }
+ const pattern = this.xref.fetchIfRef(rawPattern);
+ if (pattern) {
+ const dict = pattern instanceof BaseStream ? pattern.dict : pattern;
+ const typeNum = dict.get("PatternType");
+ if (typeNum === PatternType.TILING) {
+ const color = cs.base ? cs.base.getRgb(args, 0) : null;
+ return this.handleTilingType(fn, color, resources, pattern, dict, operatorList, task, localTilingPatternCache);
+ } else if (typeNum === PatternType.SHADING) {
+ const shading = dict.get("Shading");
+ const matrix = dict.getArray("Matrix");
+ const objId = this.parseShading({
+ shading,
+ resources,
+ localColorSpaceCache,
+ localShadingPatternCache
+ });
+ operatorList.addOp(fn, ["Shading", objId, matrix]);
+ return undefined;
+ }
+ throw new FormatError(`Unknown PatternType: ${typeNum}`);
+ }
+ }
+ throw new FormatError(`Unknown PatternName: ${patternName}`);
+ }
+ _parseVisibilityExpression(array, nestingCounter, currentResult) {
+ const MAX_NESTING = 10;
+ if (++nestingCounter > MAX_NESTING) {
+ warn("Visibility expression is too deeply nested");
+ return;
+ }
+ const length = array.length;
+ const operator = this.xref.fetchIfRef(array[0]);
+ if (length < 2 || !(operator instanceof Name)) {
+ warn("Invalid visibility expression");
+ return;
+ }
+ switch (operator.name) {
+ case "And":
+ case "Or":
+ case "Not":
+ currentResult.push(operator.name);
+ break;
+ default:
+ warn(`Invalid operator ${operator.name} in visibility expression`);
+ return;
+ }
+ for (let i = 1; i < length; i++) {
+ const raw = array[i];
+ const object = this.xref.fetchIfRef(raw);
+ if (Array.isArray(object)) {
+ const nestedResult = [];
+ currentResult.push(nestedResult);
+ this._parseVisibilityExpression(object, nestingCounter, nestedResult);
+ } else if (raw instanceof Ref) {
+ currentResult.push(raw.toString());
+ }
+ }
+ }
+ async parseMarkedContentProps(contentProperties, resources) {
+ let optionalContent;
+ if (contentProperties instanceof Name) {
+ const properties = resources.get("Properties");
+ optionalContent = properties.get(contentProperties.name);
+ } else if (contentProperties instanceof Dict) {
+ optionalContent = contentProperties;
+ } else {
+ throw new FormatError("Optional content properties malformed.");
+ }
+ const optionalContentType = optionalContent.get("Type")?.name;
+ if (optionalContentType === "OCG") {
+ return {
+ type: optionalContentType,
+ id: optionalContent.objId
+ };
+ } else if (optionalContentType === "OCMD") {
+ const expression = optionalContent.get("VE");
+ if (Array.isArray(expression)) {
+ const result = [];
+ this._parseVisibilityExpression(expression, 0, result);
+ if (result.length > 0) {
+ return {
+ type: "OCMD",
+ expression: result
+ };
+ }
+ }
+ const optionalContentGroups = optionalContent.get("OCGs");
+ if (Array.isArray(optionalContentGroups) || optionalContentGroups instanceof Dict) {
+ const groupIds = [];
+ if (Array.isArray(optionalContentGroups)) {
+ for (const ocg of optionalContentGroups) {
+ groupIds.push(ocg.toString());
+ }
+ } else {
+ groupIds.push(optionalContentGroups.objId);
+ }
+ return {
+ type: optionalContentType,
+ ids: groupIds,
+ policy: optionalContent.get("P") instanceof Name ? optionalContent.get("P").name : null,
+ expression: null
+ };
+ } else if (optionalContentGroups instanceof Ref) {
+ return {
+ type: optionalContentType,
+ id: optionalContentGroups.toString()
+ };
+ }
+ }
+ return null;
+ }
+ getOperatorList({
+ stream,
+ task,
+ resources,
+ operatorList,
+ initialState = null,
+ fallbackFontDict = null
+ }) {
+ resources ||= Dict.empty;
+ initialState ||= new EvalState();
+ if (!operatorList) {
+ throw new Error('getOperatorList: missing "operatorList" parameter');
+ }
+ const self = this;
+ const xref = this.xref;
+ let parsingText = false;
+ const localImageCache = new LocalImageCache();
+ const localColorSpaceCache = new LocalColorSpaceCache();
+ const localGStateCache = new LocalGStateCache();
+ const localTilingPatternCache = new LocalTilingPatternCache();
+ const localShadingPatternCache = new Map();
+ const xobjs = resources.get("XObject") || Dict.empty;
+ const patterns = resources.get("Pattern") || Dict.empty;
+ const stateManager = new StateManager(initialState);
+ const preprocessor = new EvaluatorPreprocessor(stream, xref, stateManager);
+ const timeSlotManager = new TimeSlotManager();
+ function closePendingRestoreOPS(argument) {
+ for (let i = 0, ii = preprocessor.savedStatesDepth; i < ii; i++) {
+ operatorList.addOp(OPS.restore, []);
+ }
+ }
+ return new Promise(function promiseBody(resolve, reject) {
+ const next = function (promise) {
+ Promise.all([promise, operatorList.ready]).then(function () {
+ try {
+ promiseBody(resolve, reject);
+ } catch (ex) {
+ reject(ex);
+ }
+ }, reject);
+ };
+ task.ensureNotTerminated();
+ timeSlotManager.reset();
+ const operation = {};
+ let stop, i, ii, cs, name, isValidName;
+ while (!(stop = timeSlotManager.check())) {
+ operation.args = null;
+ if (!preprocessor.read(operation)) {
+ break;
+ }
+ let args = operation.args;
+ let fn = operation.fn;
+ switch (fn | 0) {
+ case OPS.paintXObject:
+ isValidName = args[0] instanceof Name;
+ name = args[0].name;
+ if (isValidName) {
+ const localImage = localImageCache.getByName(name);
+ if (localImage) {
+ operatorList.addImageOps(localImage.fn, localImage.args, localImage.optionalContent);
+ incrementCachedImageMaskCount(localImage);
+ args = null;
+ continue;
+ }
+ }
+ next(new Promise(function (resolveXObject, rejectXObject) {
+ if (!isValidName) {
+ throw new FormatError("XObject must be referred to by name.");
+ }
+ let xobj = xobjs.getRaw(name);
+ if (xobj instanceof Ref) {
+ const localImage = localImageCache.getByRef(xobj) || self._regionalImageCache.getByRef(xobj);
+ if (localImage) {
+ operatorList.addImageOps(localImage.fn, localImage.args, localImage.optionalContent);
+ incrementCachedImageMaskCount(localImage);
+ resolveXObject();
+ return;
+ }
+ const globalImage = self.globalImageCache.getData(xobj, self.pageIndex);
+ if (globalImage) {
+ operatorList.addDependency(globalImage.objId);
+ operatorList.addImageOps(globalImage.fn, globalImage.args, globalImage.optionalContent);
+ resolveXObject();
+ return;
+ }
+ xobj = xref.fetch(xobj);
+ }
+ if (!(xobj instanceof BaseStream)) {
+ throw new FormatError("XObject should be a stream");
+ }
+ const type = xobj.dict.get("Subtype");
+ if (!(type instanceof Name)) {
+ throw new FormatError("XObject should have a Name subtype");
+ }
+ if (type.name === "Form") {
+ stateManager.save();
+ self.buildFormXObject(resources, xobj, null, operatorList, task, stateManager.state.clone(), localColorSpaceCache).then(function () {
+ stateManager.restore();
+ resolveXObject();
+ }, rejectXObject);
+ return;
+ } else if (type.name === "Image") {
+ self.buildPaintImageXObject({
+ resources,
+ image: xobj,
+ operatorList,
+ cacheKey: name,
+ localImageCache,
+ localColorSpaceCache
+ }).then(resolveXObject, rejectXObject);
+ return;
+ } else if (type.name === "PS") {
+ info("Ignored XObject subtype PS");
+ } else {
+ throw new FormatError(`Unhandled XObject subtype ${type.name}`);
+ }
+ resolveXObject();
+ }).catch(function (reason) {
+ if (reason instanceof AbortException) {
+ return;
+ }
+ if (self.options.ignoreErrors) {
+ warn(`getOperatorList - ignoring XObject: "${reason}".`);
+ return;
+ }
+ throw reason;
+ }));
+ return;
+ case OPS.setFont:
+ var fontSize = args[1];
+ next(self.handleSetFont(resources, args, null, operatorList, task, stateManager.state, fallbackFontDict).then(function (loadedName) {
+ operatorList.addDependency(loadedName);
+ operatorList.addOp(OPS.setFont, [loadedName, fontSize]);
+ }));
+ return;
+ case OPS.beginText:
+ parsingText = true;
+ break;
+ case OPS.endText:
+ parsingText = false;
+ break;
+ case OPS.endInlineImage:
+ var cacheKey = args[0].cacheKey;
+ if (cacheKey) {
+ const localImage = localImageCache.getByName(cacheKey);
+ if (localImage) {
+ operatorList.addImageOps(localImage.fn, localImage.args, localImage.optionalContent);
+ incrementCachedImageMaskCount(localImage);
+ args = null;
+ continue;
+ }
+ }
+ next(self.buildPaintImageXObject({
+ resources,
+ image: args[0],
+ isInline: true,
+ operatorList,
+ cacheKey,
+ localImageCache,
+ localColorSpaceCache
+ }));
+ return;
+ case OPS.showText:
+ if (!stateManager.state.font) {
+ self.ensureStateFont(stateManager.state);
+ continue;
+ }
+ args[0] = self.handleText(args[0], stateManager.state);
+ break;
+ case OPS.showSpacedText:
+ if (!stateManager.state.font) {
+ self.ensureStateFont(stateManager.state);
+ continue;
+ }
+ var combinedGlyphs = [];
+ var state = stateManager.state;
+ for (const arrItem of args[0]) {
+ if (typeof arrItem === "string") {
+ combinedGlyphs.push(...self.handleText(arrItem, state));
+ } else if (typeof arrItem === "number") {
+ combinedGlyphs.push(arrItem);
+ }
+ }
+ args[0] = combinedGlyphs;
+ fn = OPS.showText;
+ break;
+ case OPS.nextLineShowText:
+ if (!stateManager.state.font) {
+ self.ensureStateFont(stateManager.state);
+ continue;
+ }
+ operatorList.addOp(OPS.nextLine);
+ args[0] = self.handleText(args[0], stateManager.state);
+ fn = OPS.showText;
+ break;
+ case OPS.nextLineSetSpacingShowText:
+ if (!stateManager.state.font) {
+ self.ensureStateFont(stateManager.state);
+ continue;
+ }
+ operatorList.addOp(OPS.nextLine);
+ operatorList.addOp(OPS.setWordSpacing, [args.shift()]);
+ operatorList.addOp(OPS.setCharSpacing, [args.shift()]);
+ args[0] = self.handleText(args[0], stateManager.state);
+ fn = OPS.showText;
+ break;
+ case OPS.setTextRenderingMode:
+ stateManager.state.textRenderingMode = args[0];
+ break;
+ case OPS.setFillColorSpace:
+ {
+ const cachedColorSpace = ColorSpace.getCached(args[0], xref, localColorSpaceCache);
+ if (cachedColorSpace) {
+ stateManager.state.fillColorSpace = cachedColorSpace;
+ continue;
+ }
+ next(self.parseColorSpace({
+ cs: args[0],
+ resources,
+ localColorSpaceCache
+ }).then(function (colorSpace) {
+ if (colorSpace) {
+ stateManager.state.fillColorSpace = colorSpace;
+ }
+ }));
+ return;
+ }
+ case OPS.setStrokeColorSpace:
+ {
+ const cachedColorSpace = ColorSpace.getCached(args[0], xref, localColorSpaceCache);
+ if (cachedColorSpace) {
+ stateManager.state.strokeColorSpace = cachedColorSpace;
+ continue;
+ }
+ next(self.parseColorSpace({
+ cs: args[0],
+ resources,
+ localColorSpaceCache
+ }).then(function (colorSpace) {
+ if (colorSpace) {
+ stateManager.state.strokeColorSpace = colorSpace;
+ }
+ }));
+ return;
+ }
+ case OPS.setFillColor:
+ cs = stateManager.state.fillColorSpace;
+ args = cs.getRgb(args, 0);
+ fn = OPS.setFillRGBColor;
+ break;
+ case OPS.setStrokeColor:
+ cs = stateManager.state.strokeColorSpace;
+ args = cs.getRgb(args, 0);
+ fn = OPS.setStrokeRGBColor;
+ break;
+ case OPS.setFillGray:
+ stateManager.state.fillColorSpace = ColorSpace.singletons.gray;
+ args = ColorSpace.singletons.gray.getRgb(args, 0);
+ fn = OPS.setFillRGBColor;
+ break;
+ case OPS.setStrokeGray:
+ stateManager.state.strokeColorSpace = ColorSpace.singletons.gray;
+ args = ColorSpace.singletons.gray.getRgb(args, 0);
+ fn = OPS.setStrokeRGBColor;
+ break;
+ case OPS.setFillCMYKColor:
+ stateManager.state.fillColorSpace = ColorSpace.singletons.cmyk;
+ args = ColorSpace.singletons.cmyk.getRgb(args, 0);
+ fn = OPS.setFillRGBColor;
+ break;
+ case OPS.setStrokeCMYKColor:
+ stateManager.state.strokeColorSpace = ColorSpace.singletons.cmyk;
+ args = ColorSpace.singletons.cmyk.getRgb(args, 0);
+ fn = OPS.setStrokeRGBColor;
+ break;
+ case OPS.setFillRGBColor:
+ stateManager.state.fillColorSpace = ColorSpace.singletons.rgb;
+ args = ColorSpace.singletons.rgb.getRgb(args, 0);
+ break;
+ case OPS.setStrokeRGBColor:
+ stateManager.state.strokeColorSpace = ColorSpace.singletons.rgb;
+ args = ColorSpace.singletons.rgb.getRgb(args, 0);
+ break;
+ case OPS.setFillColorN:
+ cs = stateManager.state.fillColorSpace;
+ if (cs.name === "Pattern") {
+ next(self.handleColorN(operatorList, OPS.setFillColorN, args, cs, patterns, resources, task, localColorSpaceCache, localTilingPatternCache, localShadingPatternCache));
+ return;
+ }
+ args = cs.getRgb(args, 0);
+ fn = OPS.setFillRGBColor;
+ break;
+ case OPS.setStrokeColorN:
+ cs = stateManager.state.strokeColorSpace;
+ if (cs.name === "Pattern") {
+ next(self.handleColorN(operatorList, OPS.setStrokeColorN, args, cs, patterns, resources, task, localColorSpaceCache, localTilingPatternCache, localShadingPatternCache));
+ return;
+ }
+ args = cs.getRgb(args, 0);
+ fn = OPS.setStrokeRGBColor;
+ break;
+ case OPS.shadingFill:
+ var shadingRes = resources.get("Shading");
+ if (!shadingRes) {
+ throw new FormatError("No shading resource found");
+ }
+ var shading = shadingRes.get(args[0].name);
+ if (!shading) {
+ throw new FormatError("No shading object found");
+ }
+ const patternId = self.parseShading({
+ shading,
+ resources,
+ localColorSpaceCache,
+ localShadingPatternCache
+ });
+ args = [patternId];
+ fn = OPS.shadingFill;
+ break;
+ case OPS.setGState:
+ isValidName = args[0] instanceof Name;
+ name = args[0].name;
+ if (isValidName) {
+ const localGStateObj = localGStateCache.getByName(name);
+ if (localGStateObj) {
+ if (localGStateObj.length > 0) {
+ operatorList.addOp(OPS.setGState, [localGStateObj]);
+ }
+ args = null;
+ continue;
+ }
+ }
+ next(new Promise(function (resolveGState, rejectGState) {
+ if (!isValidName) {
+ throw new FormatError("GState must be referred to by name.");
+ }
+ const extGState = resources.get("ExtGState");
+ if (!(extGState instanceof Dict)) {
+ throw new FormatError("ExtGState should be a dictionary.");
+ }
+ const gState = extGState.get(name);
+ if (!(gState instanceof Dict)) {
+ throw new FormatError("GState should be a dictionary.");
+ }
+ self.setGState({
+ resources,
+ gState,
+ operatorList,
+ cacheKey: name,
+ task,
+ stateManager,
+ localGStateCache,
+ localColorSpaceCache
+ }).then(resolveGState, rejectGState);
+ }).catch(function (reason) {
+ if (reason instanceof AbortException) {
+ return;
+ }
+ if (self.options.ignoreErrors) {
+ warn(`getOperatorList - ignoring ExtGState: "${reason}".`);
+ return;
+ }
+ throw reason;
+ }));
+ return;
+ case OPS.moveTo:
+ case OPS.lineTo:
+ case OPS.curveTo:
+ case OPS.curveTo2:
+ case OPS.curveTo3:
+ case OPS.closePath:
+ case OPS.rectangle:
+ self.buildPath(operatorList, fn, args, parsingText);
+ continue;
+ case OPS.markPoint:
+ case OPS.markPointProps:
+ case OPS.beginCompat:
+ case OPS.endCompat:
+ continue;
+ case OPS.beginMarkedContentProps:
+ if (!(args[0] instanceof Name)) {
+ warn(`Expected name for beginMarkedContentProps arg0=${args[0]}`);
+ operatorList.addOp(OPS.beginMarkedContentProps, ["OC", null]);
+ continue;
+ }
+ if (args[0].name === "OC") {
+ next(self.parseMarkedContentProps(args[1], resources).then(data => {
+ operatorList.addOp(OPS.beginMarkedContentProps, ["OC", data]);
+ }).catch(reason => {
+ if (reason instanceof AbortException) {
+ return;
+ }
+ if (self.options.ignoreErrors) {
+ warn(`getOperatorList - ignoring beginMarkedContentProps: "${reason}".`);
+ operatorList.addOp(OPS.beginMarkedContentProps, ["OC", null]);
+ return;
+ }
+ throw reason;
+ }));
+ return;
+ }
+ args = [args[0].name, args[1] instanceof Dict ? args[1].get("MCID") : null];
+ break;
+ case OPS.beginMarkedContent:
+ case OPS.endMarkedContent:
+ default:
+ if (args !== null) {
+ for (i = 0, ii = args.length; i < ii; i++) {
+ if (args[i] instanceof Dict) {
+ break;
+ }
+ }
+ if (i < ii) {
+ warn("getOperatorList - ignoring operator: " + fn);
+ continue;
+ }
+ }
+ }
+ operatorList.addOp(fn, args);
+ }
+ if (stop) {
+ next(deferred);
+ return;
+ }
+ closePendingRestoreOPS();
+ resolve();
+ }).catch(reason => {
+ if (reason instanceof AbortException) {
+ return;
+ }
+ if (this.options.ignoreErrors) {
+ warn(`getOperatorList - ignoring errors during "${task.name}" ` + `task: "${reason}".`);
+ closePendingRestoreOPS();
+ return;
+ }
+ throw reason;
+ });
+ }
+ getTextContent({
+ stream,
+ task,
+ resources,
+ stateManager = null,
+ includeMarkedContent = false,
+ sink,
+ seenStyles = new Set(),
+ viewBox,
+ markedContentData = null,
+ disableNormalization = false,
+ keepWhiteSpace = false
+ }) {
+ resources ||= Dict.empty;
+ stateManager ||= new StateManager(new TextState());
+ if (includeMarkedContent) {
+ markedContentData ||= {
+ level: 0
+ };
+ }
+ const textContent = {
+ items: [],
+ styles: Object.create(null)
+ };
+ const textContentItem = {
+ initialized: false,
+ str: [],
+ totalWidth: 0,
+ totalHeight: 0,
+ width: 0,
+ height: 0,
+ vertical: false,
+ prevTransform: null,
+ textAdvanceScale: 0,
+ spaceInFlowMin: 0,
+ spaceInFlowMax: 0,
+ trackingSpaceMin: Infinity,
+ negativeSpaceMax: -Infinity,
+ notASpace: -Infinity,
+ transform: null,
+ fontName: null,
+ hasEOL: false
+ };
+ const twoLastChars = [" ", " "];
+ let twoLastCharsPos = 0;
+ function saveLastChar(char) {
+ const nextPos = (twoLastCharsPos + 1) % 2;
+ const ret = twoLastChars[twoLastCharsPos] !== " " && twoLastChars[nextPos] === " ";
+ twoLastChars[twoLastCharsPos] = char;
+ twoLastCharsPos = nextPos;
+ return !keepWhiteSpace && ret;
+ }
+ function shouldAddWhitepsace() {
+ return !keepWhiteSpace && twoLastChars[twoLastCharsPos] !== " " && twoLastChars[(twoLastCharsPos + 1) % 2] === " ";
+ }
+ function resetLastChars() {
+ twoLastChars[0] = twoLastChars[1] = " ";
+ twoLastCharsPos = 0;
+ }
+ const TRACKING_SPACE_FACTOR = 0.102;
+ const NOT_A_SPACE_FACTOR = 0.03;
+ const NEGATIVE_SPACE_FACTOR = -0.2;
+ const SPACE_IN_FLOW_MIN_FACTOR = 0.102;
+ const SPACE_IN_FLOW_MAX_FACTOR = 0.6;
+ const VERTICAL_SHIFT_RATIO = 0.25;
+ const self = this;
+ const xref = this.xref;
+ const showSpacedTextBuffer = [];
+ let xobjs = null;
+ const emptyXObjectCache = new LocalImageCache();
+ const emptyGStateCache = new LocalGStateCache();
+ const preprocessor = new EvaluatorPreprocessor(stream, xref, stateManager);
+ let textState;
+ function pushWhitespace({
+ width = 0,
+ height = 0,
+ transform = textContentItem.prevTransform,
+ fontName = textContentItem.fontName
+ }) {
+ textContent.items.push({
+ str: " ",
+ dir: "ltr",
+ width,
+ height,
+ transform,
+ fontName,
+ hasEOL: false
+ });
+ }
+ function getCurrentTextTransform() {
+ const font = textState.font;
+ const tsm = [textState.fontSize * textState.textHScale, 0, 0, textState.fontSize, 0, textState.textRise];
+ if (font.isType3Font && (textState.fontSize <= 1 || font.isCharBBox) && !isArrayEqual(textState.fontMatrix, FONT_IDENTITY_MATRIX)) {
+ const glyphHeight = font.bbox[3] - font.bbox[1];
+ if (glyphHeight > 0) {
+ tsm[3] *= glyphHeight * textState.fontMatrix[3];
+ }
+ }
+ return Util.transform(textState.ctm, Util.transform(textState.textMatrix, tsm));
+ }
+ function ensureTextContentItem() {
+ if (textContentItem.initialized) {
+ return textContentItem;
+ }
+ const {
+ font,
+ loadedName
+ } = textState;
+ if (!seenStyles.has(loadedName)) {
+ seenStyles.add(loadedName);
+ textContent.styles[loadedName] = {
+ fontFamily: font.fallbackName,
+ ascent: font.ascent,
+ descent: font.descent,
+ vertical: font.vertical
+ };
+ if (self.options.fontExtraProperties && font.systemFontInfo) {
+ const style = textContent.styles[loadedName];
+ style.fontSubstitution = font.systemFontInfo.css;
+ style.fontSubstitutionLoadedName = font.systemFontInfo.loadedName;
+ }
+ }
+ textContentItem.fontName = loadedName;
+ const trm = textContentItem.transform = getCurrentTextTransform();
+ if (!font.vertical) {
+ textContentItem.width = textContentItem.totalWidth = 0;
+ textContentItem.height = textContentItem.totalHeight = Math.hypot(trm[2], trm[3]);
+ textContentItem.vertical = false;
+ } else {
+ textContentItem.width = textContentItem.totalWidth = Math.hypot(trm[0], trm[1]);
+ textContentItem.height = textContentItem.totalHeight = 0;
+ textContentItem.vertical = true;
+ }
+ const scaleLineX = Math.hypot(textState.textLineMatrix[0], textState.textLineMatrix[1]);
+ const scaleCtmX = Math.hypot(textState.ctm[0], textState.ctm[1]);
+ textContentItem.textAdvanceScale = scaleCtmX * scaleLineX;
+ const {
+ fontSize
+ } = textState;
+ textContentItem.trackingSpaceMin = fontSize * TRACKING_SPACE_FACTOR;
+ textContentItem.notASpace = fontSize * NOT_A_SPACE_FACTOR;
+ textContentItem.negativeSpaceMax = fontSize * NEGATIVE_SPACE_FACTOR;
+ textContentItem.spaceInFlowMin = fontSize * SPACE_IN_FLOW_MIN_FACTOR;
+ textContentItem.spaceInFlowMax = fontSize * SPACE_IN_FLOW_MAX_FACTOR;
+ textContentItem.hasEOL = false;
+ textContentItem.initialized = true;
+ return textContentItem;
+ }
+ function updateAdvanceScale() {
+ if (!textContentItem.initialized) {
+ return;
+ }
+ const scaleLineX = Math.hypot(textState.textLineMatrix[0], textState.textLineMatrix[1]);
+ const scaleCtmX = Math.hypot(textState.ctm[0], textState.ctm[1]);
+ const scaleFactor = scaleCtmX * scaleLineX;
+ if (scaleFactor === textContentItem.textAdvanceScale) {
+ return;
+ }
+ if (!textContentItem.vertical) {
+ textContentItem.totalWidth += textContentItem.width * textContentItem.textAdvanceScale;
+ textContentItem.width = 0;
+ } else {
+ textContentItem.totalHeight += textContentItem.height * textContentItem.textAdvanceScale;
+ textContentItem.height = 0;
+ }
+ textContentItem.textAdvanceScale = scaleFactor;
+ }
+ function runBidiTransform(textChunk) {
+ let text = textChunk.str.join("");
+ if (!disableNormalization) {
+ text = normalizeUnicode(text);
+ }
+ const bidiResult = bidi(text, -1, textChunk.vertical);
+ return {
+ str: bidiResult.str,
+ dir: bidiResult.dir,
+ width: Math.abs(textChunk.totalWidth),
+ height: Math.abs(textChunk.totalHeight),
+ transform: textChunk.transform,
+ fontName: textChunk.fontName,
+ hasEOL: textChunk.hasEOL
+ };
+ }
+ async function handleSetFont(fontName, fontRef) {
+ const translated = await self.loadFont(fontName, fontRef, resources);
+ if (translated.font.isType3Font) {
+ try {
+ await translated.loadType3Data(self, resources, task);
+ } catch {}
+ }
+ textState.loadedName = translated.loadedName;
+ textState.font = translated.font;
+ textState.fontMatrix = translated.font.fontMatrix || FONT_IDENTITY_MATRIX;
+ }
+ function applyInverseRotation(x, y, matrix) {
+ const scale = Math.hypot(matrix[0], matrix[1]);
+ return [(matrix[0] * x + matrix[1] * y) / scale, (matrix[2] * x + matrix[3] * y) / scale];
+ }
+ function compareWithLastPosition(glyphWidth) {
+ const currentTransform = getCurrentTextTransform();
+ let posX = currentTransform[4];
+ let posY = currentTransform[5];
+ if (textState.font?.vertical) {
+ if (posX < viewBox[0] || posX > viewBox[2] || posY + glyphWidth < viewBox[1] || posY > viewBox[3]) {
+ return false;
+ }
+ } else if (posX + glyphWidth < viewBox[0] || posX > viewBox[2] || posY < viewBox[1] || posY > viewBox[3]) {
+ return false;
+ }
+ if (!textState.font || !textContentItem.prevTransform) {
+ return true;
+ }
+ let lastPosX = textContentItem.prevTransform[4];
+ let lastPosY = textContentItem.prevTransform[5];
+ if (lastPosX === posX && lastPosY === posY) {
+ return true;
+ }
+ let rotate = -1;
+ if (currentTransform[0] && currentTransform[1] === 0 && currentTransform[2] === 0) {
+ rotate = currentTransform[0] > 0 ? 0 : 180;
+ } else if (currentTransform[1] && currentTransform[0] === 0 && currentTransform[3] === 0) {
+ rotate = currentTransform[1] > 0 ? 90 : 270;
+ }
+ switch (rotate) {
+ case 0:
+ break;
+ case 90:
+ [posX, posY] = [posY, posX];
+ [lastPosX, lastPosY] = [lastPosY, lastPosX];
+ break;
+ case 180:
+ [posX, posY, lastPosX, lastPosY] = [-posX, -posY, -lastPosX, -lastPosY];
+ break;
+ case 270:
+ [posX, posY] = [-posY, -posX];
+ [lastPosX, lastPosY] = [-lastPosY, -lastPosX];
+ break;
+ default:
+ [posX, posY] = applyInverseRotation(posX, posY, currentTransform);
+ [lastPosX, lastPosY] = applyInverseRotation(lastPosX, lastPosY, textContentItem.prevTransform);
+ }
+ if (textState.font.vertical) {
+ const advanceY = (lastPosY - posY) / textContentItem.textAdvanceScale;
+ const advanceX = posX - lastPosX;
+ const textOrientation = Math.sign(textContentItem.height);
+ if (advanceY < textOrientation * textContentItem.negativeSpaceMax) {
+ if (Math.abs(advanceX) > 0.5 * textContentItem.width) {
+ appendEOL();
+ return true;
+ }
+ resetLastChars();
+ flushTextContentItem();
+ return true;
+ }
+ if (Math.abs(advanceX) > textContentItem.width) {
+ appendEOL();
+ return true;
+ }
+ if (advanceY <= textOrientation * textContentItem.notASpace) {
+ resetLastChars();
+ }
+ if (advanceY <= textOrientation * textContentItem.trackingSpaceMin) {
+ if (shouldAddWhitepsace()) {
+ resetLastChars();
+ flushTextContentItem();
+ pushWhitespace({
+ height: Math.abs(advanceY)
+ });
+ } else {
+ textContentItem.height += advanceY;
+ }
+ } else if (!addFakeSpaces(advanceY, textContentItem.prevTransform, textOrientation)) {
+ if (textContentItem.str.length === 0) {
+ resetLastChars();
+ pushWhitespace({
+ height: Math.abs(advanceY)
+ });
+ } else {
+ textContentItem.height += advanceY;
+ }
+ }
+ if (Math.abs(advanceX) > textContentItem.width * VERTICAL_SHIFT_RATIO) {
+ flushTextContentItem();
+ }
+ return true;
+ }
+ const advanceX = (posX - lastPosX) / textContentItem.textAdvanceScale;
+ const advanceY = posY - lastPosY;
+ const textOrientation = Math.sign(textContentItem.width);
+ if (advanceX < textOrientation * textContentItem.negativeSpaceMax) {
+ if (Math.abs(advanceY) > 0.5 * textContentItem.height) {
+ appendEOL();
+ return true;
+ }
+ resetLastChars();
+ flushTextContentItem();
+ return true;
+ }
+ if (Math.abs(advanceY) > textContentItem.height) {
+ appendEOL();
+ return true;
+ }
+ if (advanceX <= textOrientation * textContentItem.notASpace) {
+ resetLastChars();
+ }
+ if (advanceX <= textOrientation * textContentItem.trackingSpaceMin) {
+ if (shouldAddWhitepsace()) {
+ resetLastChars();
+ flushTextContentItem();
+ pushWhitespace({
+ width: Math.abs(advanceX)
+ });
+ } else {
+ textContentItem.width += advanceX;
+ }
+ } else if (!addFakeSpaces(advanceX, textContentItem.prevTransform, textOrientation)) {
+ if (textContentItem.str.length === 0) {
+ resetLastChars();
+ pushWhitespace({
+ width: Math.abs(advanceX)
+ });
+ } else {
+ textContentItem.width += advanceX;
+ }
+ }
+ if (Math.abs(advanceY) > textContentItem.height * VERTICAL_SHIFT_RATIO) {
+ flushTextContentItem();
+ }
+ return true;
+ }
+ function buildTextContentItem({
+ chars,
+ extraSpacing
+ }) {
+ const font = textState.font;
+ if (!chars) {
+ const charSpacing = textState.charSpacing + extraSpacing;
+ if (charSpacing) {
+ if (!font.vertical) {
+ textState.translateTextMatrix(charSpacing * textState.textHScale, 0);
+ } else {
+ textState.translateTextMatrix(0, -charSpacing);
+ }
+ }
+ if (keepWhiteSpace) {
+ compareWithLastPosition(0);
+ }
+ return;
+ }
+ const glyphs = font.charsToGlyphs(chars);
+ const scale = textState.fontMatrix[0] * textState.fontSize;
+ for (let i = 0, ii = glyphs.length; i < ii; i++) {
+ const glyph = glyphs[i];
+ const {
+ category
+ } = glyph;
+ if (category.isInvisibleFormatMark) {
+ continue;
+ }
+ let charSpacing = textState.charSpacing + (i + 1 === ii ? extraSpacing : 0);
+ let glyphWidth = glyph.width;
+ if (font.vertical) {
+ glyphWidth = glyph.vmetric ? glyph.vmetric[0] : -glyphWidth;
+ }
+ let scaledDim = glyphWidth * scale;
+ if (!keepWhiteSpace && category.isWhitespace) {
+ if (!font.vertical) {
+ charSpacing += scaledDim + textState.wordSpacing;
+ textState.translateTextMatrix(charSpacing * textState.textHScale, 0);
+ } else {
+ charSpacing += -scaledDim + textState.wordSpacing;
+ textState.translateTextMatrix(0, -charSpacing);
+ }
+ saveLastChar(" ");
+ continue;
+ }
+ if (!category.isZeroWidthDiacritic && !compareWithLastPosition(scaledDim)) {
+ if (!font.vertical) {
+ textState.translateTextMatrix(scaledDim * textState.textHScale, 0);
+ } else {
+ textState.translateTextMatrix(0, scaledDim);
+ }
+ continue;
+ }
+ const textChunk = ensureTextContentItem();
+ if (category.isZeroWidthDiacritic) {
+ scaledDim = 0;
+ }
+ if (!font.vertical) {
+ scaledDim *= textState.textHScale;
+ textState.translateTextMatrix(scaledDim, 0);
+ textChunk.width += scaledDim;
+ } else {
+ textState.translateTextMatrix(0, scaledDim);
+ scaledDim = Math.abs(scaledDim);
+ textChunk.height += scaledDim;
+ }
+ if (scaledDim) {
+ textChunk.prevTransform = getCurrentTextTransform();
+ }
+ const glyphUnicode = glyph.unicode;
+ if (saveLastChar(glyphUnicode)) {
+ textChunk.str.push(" ");
+ }
+ textChunk.str.push(glyphUnicode);
+ if (charSpacing) {
+ if (!font.vertical) {
+ textState.translateTextMatrix(charSpacing * textState.textHScale, 0);
+ } else {
+ textState.translateTextMatrix(0, -charSpacing);
+ }
+ }
+ }
+ }
+ function appendEOL() {
+ resetLastChars();
+ if (textContentItem.initialized) {
+ textContentItem.hasEOL = true;
+ flushTextContentItem();
+ } else {
+ textContent.items.push({
+ str: "",
+ dir: "ltr",
+ width: 0,
+ height: 0,
+ transform: getCurrentTextTransform(),
+ fontName: textState.loadedName,
+ hasEOL: true
+ });
+ }
+ }
+ function addFakeSpaces(width, transf, textOrientation) {
+ if (textOrientation * textContentItem.spaceInFlowMin <= width && width <= textOrientation * textContentItem.spaceInFlowMax) {
+ if (textContentItem.initialized) {
+ resetLastChars();
+ textContentItem.str.push(" ");
+ }
+ return false;
+ }
+ const fontName = textContentItem.fontName;
+ let height = 0;
+ if (textContentItem.vertical) {
+ height = width;
+ width = 0;
+ }
+ flushTextContentItem();
+ resetLastChars();
+ pushWhitespace({
+ width: Math.abs(width),
+ height: Math.abs(height),
+ transform: transf || getCurrentTextTransform(),
+ fontName
+ });
+ return true;
+ }
+ function flushTextContentItem() {
+ if (!textContentItem.initialized || !textContentItem.str) {
+ return;
+ }
+ if (!textContentItem.vertical) {
+ textContentItem.totalWidth += textContentItem.width * textContentItem.textAdvanceScale;
+ } else {
+ textContentItem.totalHeight += textContentItem.height * textContentItem.textAdvanceScale;
+ }
+ textContent.items.push(runBidiTransform(textContentItem));
+ textContentItem.initialized = false;
+ textContentItem.str.length = 0;
+ }
+ function enqueueChunk(batch = false) {
+ const length = textContent.items.length;
+ if (length === 0) {
+ return;
+ }
+ if (batch && length < TEXT_CHUNK_BATCH_SIZE) {
+ return;
+ }
+ sink.enqueue(textContent, length);
+ textContent.items = [];
+ textContent.styles = Object.create(null);
+ }
+ const timeSlotManager = new TimeSlotManager();
+ return new Promise(function promiseBody(resolve, reject) {
+ const next = function (promise) {
+ enqueueChunk(true);
+ Promise.all([promise, sink.ready]).then(function () {
+ try {
+ promiseBody(resolve, reject);
+ } catch (ex) {
+ reject(ex);
+ }
+ }, reject);
+ };
+ task.ensureNotTerminated();
+ timeSlotManager.reset();
+ const operation = {};
+ let stop,
+ args = [];
+ while (!(stop = timeSlotManager.check())) {
+ args.length = 0;
+ operation.args = args;
+ if (!preprocessor.read(operation)) {
+ break;
+ }
+ const previousState = textState;
+ textState = stateManager.state;
+ const fn = operation.fn;
+ args = operation.args;
+ switch (fn | 0) {
+ case OPS.setFont:
+ var fontNameArg = args[0].name,
+ fontSizeArg = args[1];
+ if (textState.font && fontNameArg === textState.fontName && fontSizeArg === textState.fontSize) {
+ break;
+ }
+ flushTextContentItem();
+ textState.fontName = fontNameArg;
+ textState.fontSize = fontSizeArg;
+ next(handleSetFont(fontNameArg, null));
+ return;
+ case OPS.setTextRise:
+ textState.textRise = args[0];
+ break;
+ case OPS.setHScale:
+ textState.textHScale = args[0] / 100;
+ break;
+ case OPS.setLeading:
+ textState.leading = args[0];
+ break;
+ case OPS.moveText:
+ textState.translateTextLineMatrix(args[0], args[1]);
+ textState.textMatrix = textState.textLineMatrix.slice();
+ break;
+ case OPS.setLeadingMoveText:
+ textState.leading = -args[1];
+ textState.translateTextLineMatrix(args[0], args[1]);
+ textState.textMatrix = textState.textLineMatrix.slice();
+ break;
+ case OPS.nextLine:
+ textState.carriageReturn();
+ break;
+ case OPS.setTextMatrix:
+ textState.setTextMatrix(args[0], args[1], args[2], args[3], args[4], args[5]);
+ textState.setTextLineMatrix(args[0], args[1], args[2], args[3], args[4], args[5]);
+ updateAdvanceScale();
+ break;
+ case OPS.setCharSpacing:
+ textState.charSpacing = args[0];
+ break;
+ case OPS.setWordSpacing:
+ textState.wordSpacing = args[0];
+ break;
+ case OPS.beginText:
+ textState.textMatrix = IDENTITY_MATRIX.slice();
+ textState.textLineMatrix = IDENTITY_MATRIX.slice();
+ break;
+ case OPS.showSpacedText:
+ if (!stateManager.state.font) {
+ self.ensureStateFont(stateManager.state);
+ continue;
+ }
+ const spaceFactor = (textState.font.vertical ? 1 : -1) * textState.fontSize / 1000;
+ const elements = args[0];
+ for (let i = 0, ii = elements.length; i < ii; i++) {
+ const item = elements[i];
+ if (typeof item === "string") {
+ showSpacedTextBuffer.push(item);
+ } else if (typeof item === "number" && item !== 0) {
+ const str = showSpacedTextBuffer.join("");
+ showSpacedTextBuffer.length = 0;
+ buildTextContentItem({
+ chars: str,
+ extraSpacing: item * spaceFactor
+ });
+ }
+ }
+ if (showSpacedTextBuffer.length > 0) {
+ const str = showSpacedTextBuffer.join("");
+ showSpacedTextBuffer.length = 0;
+ buildTextContentItem({
+ chars: str,
+ extraSpacing: 0
+ });
+ }
+ break;
+ case OPS.showText:
+ if (!stateManager.state.font) {
+ self.ensureStateFont(stateManager.state);
+ continue;
+ }
+ buildTextContentItem({
+ chars: args[0],
+ extraSpacing: 0
+ });
+ break;
+ case OPS.nextLineShowText:
+ if (!stateManager.state.font) {
+ self.ensureStateFont(stateManager.state);
+ continue;
+ }
+ textState.carriageReturn();
+ buildTextContentItem({
+ chars: args[0],
+ extraSpacing: 0
+ });
+ break;
+ case OPS.nextLineSetSpacingShowText:
+ if (!stateManager.state.font) {
+ self.ensureStateFont(stateManager.state);
+ continue;
+ }
+ textState.wordSpacing = args[0];
+ textState.charSpacing = args[1];
+ textState.carriageReturn();
+ buildTextContentItem({
+ chars: args[2],
+ extraSpacing: 0
+ });
+ break;
+ case OPS.paintXObject:
+ flushTextContentItem();
+ if (!xobjs) {
+ xobjs = resources.get("XObject") || Dict.empty;
+ }
+ var isValidName = args[0] instanceof Name;
+ var name = args[0].name;
+ if (isValidName && emptyXObjectCache.getByName(name)) {
+ break;
+ }
+ next(new Promise(function (resolveXObject, rejectXObject) {
+ if (!isValidName) {
+ throw new FormatError("XObject must be referred to by name.");
+ }
+ let xobj = xobjs.getRaw(name);
+ if (xobj instanceof Ref) {
+ if (emptyXObjectCache.getByRef(xobj)) {
+ resolveXObject();
+ return;
+ }
+ const globalImage = self.globalImageCache.getData(xobj, self.pageIndex);
+ if (globalImage) {
+ resolveXObject();
+ return;
+ }
+ xobj = xref.fetch(xobj);
+ }
+ if (!(xobj instanceof BaseStream)) {
+ throw new FormatError("XObject should be a stream");
+ }
+ const type = xobj.dict.get("Subtype");
+ if (!(type instanceof Name)) {
+ throw new FormatError("XObject should have a Name subtype");
+ }
+ if (type.name !== "Form") {
+ emptyXObjectCache.set(name, xobj.dict.objId, true);
+ resolveXObject();
+ return;
+ }
+ const currentState = stateManager.state.clone();
+ const xObjStateManager = new StateManager(currentState);
+ const matrix = xobj.dict.getArray("Matrix");
+ if (Array.isArray(matrix) && matrix.length === 6) {
+ xObjStateManager.transform(matrix);
+ }
+ enqueueChunk();
+ const sinkWrapper = {
+ enqueueInvoked: false,
+ enqueue(chunk, size) {
+ this.enqueueInvoked = true;
+ sink.enqueue(chunk, size);
+ },
+ get desiredSize() {
+ return sink.desiredSize;
+ },
+ get ready() {
+ return sink.ready;
+ }
+ };
+ self.getTextContent({
+ stream: xobj,
+ task,
+ resources: xobj.dict.get("Resources") || resources,
+ stateManager: xObjStateManager,
+ includeMarkedContent,
+ sink: sinkWrapper,
+ seenStyles,
+ viewBox,
+ markedContentData,
+ disableNormalization,
+ keepWhiteSpace
+ }).then(function () {
+ if (!sinkWrapper.enqueueInvoked) {
+ emptyXObjectCache.set(name, xobj.dict.objId, true);
+ }
+ resolveXObject();
+ }, rejectXObject);
+ }).catch(function (reason) {
+ if (reason instanceof AbortException) {
+ return;
+ }
+ if (self.options.ignoreErrors) {
+ warn(`getTextContent - ignoring XObject: "${reason}".`);
+ return;
+ }
+ throw reason;
+ }));
+ return;
+ case OPS.setGState:
+ isValidName = args[0] instanceof Name;
+ name = args[0].name;
+ if (isValidName && emptyGStateCache.getByName(name)) {
+ break;
+ }
+ next(new Promise(function (resolveGState, rejectGState) {
+ if (!isValidName) {
+ throw new FormatError("GState must be referred to by name.");
+ }
+ const extGState = resources.get("ExtGState");
+ if (!(extGState instanceof Dict)) {
+ throw new FormatError("ExtGState should be a dictionary.");
+ }
+ const gState = extGState.get(name);
+ if (!(gState instanceof Dict)) {
+ throw new FormatError("GState should be a dictionary.");
+ }
+ const gStateFont = gState.get("Font");
+ if (!gStateFont) {
+ emptyGStateCache.set(name, gState.objId, true);
+ resolveGState();
+ return;
+ }
+ flushTextContentItem();
+ textState.fontName = null;
+ textState.fontSize = gStateFont[1];
+ handleSetFont(null, gStateFont[0]).then(resolveGState, rejectGState);
+ }).catch(function (reason) {
+ if (reason instanceof AbortException) {
+ return;
+ }
+ if (self.options.ignoreErrors) {
+ warn(`getTextContent - ignoring ExtGState: "${reason}".`);
+ return;
+ }
+ throw reason;
+ }));
+ return;
+ case OPS.beginMarkedContent:
+ flushTextContentItem();
+ if (includeMarkedContent) {
+ markedContentData.level++;
+ textContent.items.push({
+ type: "beginMarkedContent",
+ tag: args[0] instanceof Name ? args[0].name : null
+ });
+ }
+ break;
+ case OPS.beginMarkedContentProps:
+ flushTextContentItem();
+ if (includeMarkedContent) {
+ markedContentData.level++;
+ let mcid = null;
+ if (args[1] instanceof Dict) {
+ mcid = args[1].get("MCID");
+ }
+ textContent.items.push({
+ type: "beginMarkedContentProps",
+ id: Number.isInteger(mcid) ? `${self.idFactory.getPageObjId()}_mc${mcid}` : null,
+ tag: args[0] instanceof Name ? args[0].name : null
+ });
+ }
+ break;
+ case OPS.endMarkedContent:
+ flushTextContentItem();
+ if (includeMarkedContent) {
+ if (markedContentData.level === 0) {
+ break;
+ }
+ markedContentData.level--;
+ textContent.items.push({
+ type: "endMarkedContent"
+ });
+ }
+ break;
+ case OPS.restore:
+ if (previousState && (previousState.font !== textState.font || previousState.fontSize !== textState.fontSize || previousState.fontName !== textState.fontName)) {
+ flushTextContentItem();
+ }
+ break;
+ }
+ if (textContent.items.length >= sink.desiredSize) {
+ stop = true;
+ break;
+ }
+ }
+ if (stop) {
+ next(deferred);
+ return;
+ }
+ flushTextContentItem();
+ enqueueChunk();
+ resolve();
+ }).catch(reason => {
+ if (reason instanceof AbortException) {
+ return;
+ }
+ if (this.options.ignoreErrors) {
+ warn(`getTextContent - ignoring errors during "${task.name}" ` + `task: "${reason}".`);
+ flushTextContentItem();
+ enqueueChunk();
+ return;
+ }
+ throw reason;
+ });
+ }
+ async extractDataStructures(dict, properties) {
+ const xref = this.xref;
+ let cidToGidBytes;
+ const toUnicodePromise = this.readToUnicode(properties.toUnicode);
+ if (properties.composite) {
+ const cidSystemInfo = dict.get("CIDSystemInfo");
+ if (cidSystemInfo instanceof Dict) {
+ properties.cidSystemInfo = {
+ registry: stringToPDFString(cidSystemInfo.get("Registry")),
+ ordering: stringToPDFString(cidSystemInfo.get("Ordering")),
+ supplement: cidSystemInfo.get("Supplement")
+ };
+ }
+ try {
+ const cidToGidMap = dict.get("CIDToGIDMap");
+ if (cidToGidMap instanceof BaseStream) {
+ cidToGidBytes = cidToGidMap.getBytes();
+ }
+ } catch (ex) {
+ if (!this.options.ignoreErrors) {
+ throw ex;
+ }
+ warn(`extractDataStructures - ignoring CIDToGIDMap data: "${ex}".`);
+ }
+ }
+ const differences = [];
+ let baseEncodingName = null;
+ let encoding;
+ if (dict.has("Encoding")) {
+ encoding = dict.get("Encoding");
+ if (encoding instanceof Dict) {
+ baseEncodingName = encoding.get("BaseEncoding");
+ baseEncodingName = baseEncodingName instanceof Name ? baseEncodingName.name : null;
+ if (encoding.has("Differences")) {
+ const diffEncoding = encoding.get("Differences");
+ let index = 0;
+ for (const entry of diffEncoding) {
+ const data = xref.fetchIfRef(entry);
+ if (typeof data === "number") {
+ index = data;
+ } else if (data instanceof Name) {
+ differences[index++] = data.name;
+ } else {
+ throw new FormatError(`Invalid entry in 'Differences' array: ${data}`);
+ }
+ }
+ }
+ } else if (encoding instanceof Name) {
+ baseEncodingName = encoding.name;
+ } else {
+ const msg = "Encoding is not a Name nor a Dict";
+ if (!this.options.ignoreErrors) {
+ throw new FormatError(msg);
+ }
+ warn(msg);
+ }
+ if (baseEncodingName !== "MacRomanEncoding" && baseEncodingName !== "MacExpertEncoding" && baseEncodingName !== "WinAnsiEncoding") {
+ baseEncodingName = null;
+ }
+ }
+ const nonEmbeddedFont = !properties.file || properties.isInternalFont,
+ isSymbolsFontName = getSymbolsFonts()[properties.name];
+ if (baseEncodingName && nonEmbeddedFont && isSymbolsFontName) {
+ baseEncodingName = null;
+ }
+ if (baseEncodingName) {
+ properties.defaultEncoding = getEncoding(baseEncodingName);
+ } else {
+ const isSymbolicFont = !!(properties.flags & FontFlags.Symbolic);
+ const isNonsymbolicFont = !!(properties.flags & FontFlags.Nonsymbolic);
+ encoding = StandardEncoding;
+ if (properties.type === "TrueType" && !isNonsymbolicFont) {
+ encoding = WinAnsiEncoding;
+ }
+ if (isSymbolicFont || isSymbolsFontName) {
+ encoding = MacRomanEncoding;
+ if (nonEmbeddedFont) {
+ if (/Symbol/i.test(properties.name)) {
+ encoding = SymbolSetEncoding;
+ } else if (/Dingbats/i.test(properties.name)) {
+ encoding = ZapfDingbatsEncoding;
+ } else if (/Wingdings/i.test(properties.name)) {
+ encoding = WinAnsiEncoding;
+ }
+ }
+ }
+ properties.defaultEncoding = encoding;
+ }
+ properties.differences = differences;
+ properties.baseEncodingName = baseEncodingName;
+ properties.hasEncoding = !!baseEncodingName || differences.length > 0;
+ properties.dict = dict;
+ properties.toUnicode = await toUnicodePromise;
+ const builtToUnicode = await this.buildToUnicode(properties);
+ properties.toUnicode = builtToUnicode;
+ if (cidToGidBytes) {
+ properties.cidToGidMap = this.readCidToGidMap(cidToGidBytes, builtToUnicode);
+ }
+ return properties;
+ }
+ _simpleFontToUnicode(properties, forceGlyphs = false) {
+ assert(!properties.composite, "Must be a simple font.");
+ const toUnicode = [];
+ const encoding = properties.defaultEncoding.slice();
+ const baseEncodingName = properties.baseEncodingName;
+ const differences = properties.differences;
+ for (const charcode in differences) {
+ const glyphName = differences[charcode];
+ if (glyphName === ".notdef") {
+ continue;
+ }
+ encoding[charcode] = glyphName;
+ }
+ const glyphsUnicodeMap = getGlyphsUnicode();
+ for (const charcode in encoding) {
+ let glyphName = encoding[charcode];
+ if (glyphName === "") {
+ continue;
+ }
+ let unicode = glyphsUnicodeMap[glyphName];
+ if (unicode !== undefined) {
+ toUnicode[charcode] = String.fromCharCode(unicode);
+ continue;
+ }
+ let code = 0;
+ switch (glyphName[0]) {
+ case "G":
+ if (glyphName.length === 3) {
+ code = parseInt(glyphName.substring(1), 16);
+ }
+ break;
+ case "g":
+ if (glyphName.length === 5) {
+ code = parseInt(glyphName.substring(1), 16);
+ }
+ break;
+ case "C":
+ case "c":
+ if (glyphName.length >= 3 && glyphName.length <= 4) {
+ const codeStr = glyphName.substring(1);
+ if (forceGlyphs) {
+ code = parseInt(codeStr, 16);
+ break;
+ }
+ code = +codeStr;
+ if (Number.isNaN(code) && Number.isInteger(parseInt(codeStr, 16))) {
+ return this._simpleFontToUnicode(properties, true);
+ }
+ }
+ break;
+ case "u":
+ unicode = getUnicodeForGlyph(glyphName, glyphsUnicodeMap);
+ if (unicode !== -1) {
+ code = unicode;
+ }
+ break;
+ default:
+ switch (glyphName) {
+ case "f_h":
+ case "f_t":
+ case "T_h":
+ toUnicode[charcode] = glyphName.replaceAll("_", "");
+ continue;
+ }
+ break;
+ }
+ if (code > 0 && code <= 0x10ffff && Number.isInteger(code)) {
+ if (baseEncodingName && code === +charcode) {
+ const baseEncoding = getEncoding(baseEncodingName);
+ if (baseEncoding && (glyphName = baseEncoding[charcode])) {
+ toUnicode[charcode] = String.fromCharCode(glyphsUnicodeMap[glyphName]);
+ continue;
+ }
+ }
+ toUnicode[charcode] = String.fromCodePoint(code);
+ }
+ }
+ return toUnicode;
+ }
+ async buildToUnicode(properties) {
+ properties.hasIncludedToUnicodeMap = properties.toUnicode?.length > 0;
+ if (properties.hasIncludedToUnicodeMap) {
+ if (!properties.composite && properties.hasEncoding) {
+ properties.fallbackToUnicode = this._simpleFontToUnicode(properties);
+ }
+ return properties.toUnicode;
+ }
+ if (!properties.composite) {
+ return new ToUnicodeMap(this._simpleFontToUnicode(properties));
+ }
+ if (properties.composite && (properties.cMap.builtInCMap && !(properties.cMap instanceof IdentityCMap) || properties.cidSystemInfo?.registry === "Adobe" && (properties.cidSystemInfo.ordering === "GB1" || properties.cidSystemInfo.ordering === "CNS1" || properties.cidSystemInfo.ordering === "Japan1" || properties.cidSystemInfo.ordering === "Korea1"))) {
+ const {
+ registry,
+ ordering
+ } = properties.cidSystemInfo;
+ const ucs2CMapName = Name.get(`${registry}-${ordering}-UCS2`);
+ const ucs2CMap = await CMapFactory.create({
+ encoding: ucs2CMapName,
+ fetchBuiltInCMap: this._fetchBuiltInCMapBound,
+ useCMap: null
+ });
+ const toUnicode = [],
+ buf = [];
+ properties.cMap.forEach(function (charcode, cid) {
+ if (cid > 0xffff) {
+ throw new FormatError("Max size of CID is 65,535");
+ }
+ const ucs2 = ucs2CMap.lookup(cid);
+ if (ucs2) {
+ buf.length = 0;
+ for (let i = 0, ii = ucs2.length; i < ii; i += 2) {
+ buf.push((ucs2.charCodeAt(i) << 8) + ucs2.charCodeAt(i + 1));
+ }
+ toUnicode[charcode] = String.fromCharCode(...buf);
+ }
+ });
+ return new ToUnicodeMap(toUnicode);
+ }
+ return new IdentityToUnicodeMap(properties.firstChar, properties.lastChar);
+ }
+ async readToUnicode(cmapObj) {
+ if (!cmapObj) {
+ return null;
+ }
+ if (cmapObj instanceof Name) {
+ const cmap = await CMapFactory.create({
+ encoding: cmapObj,
+ fetchBuiltInCMap: this._fetchBuiltInCMapBound,
+ useCMap: null
+ });
+ if (cmap instanceof IdentityCMap) {
+ return new IdentityToUnicodeMap(0, 0xffff);
+ }
+ return new ToUnicodeMap(cmap.getMap());
+ }
+ if (cmapObj instanceof BaseStream) {
+ try {
+ const cmap = await CMapFactory.create({
+ encoding: cmapObj,
+ fetchBuiltInCMap: this._fetchBuiltInCMapBound,
+ useCMap: null
+ });
+ if (cmap instanceof IdentityCMap) {
+ return new IdentityToUnicodeMap(0, 0xffff);
+ }
+ const map = new Array(cmap.length);
+ cmap.forEach(function (charCode, token) {
+ if (typeof token === "number") {
+ map[charCode] = String.fromCodePoint(token);
+ return;
+ }
+ const str = [];
+ for (let k = 0; k < token.length; k += 2) {
+ const w1 = token.charCodeAt(k) << 8 | token.charCodeAt(k + 1);
+ if ((w1 & 0xf800) !== 0xd800) {
+ str.push(w1);
+ continue;
+ }
+ k += 2;
+ const w2 = token.charCodeAt(k) << 8 | token.charCodeAt(k + 1);
+ str.push(((w1 & 0x3ff) << 10) + (w2 & 0x3ff) + 0x10000);
+ }
+ map[charCode] = String.fromCodePoint(...str);
+ });
+ return new ToUnicodeMap(map);
+ } catch (reason) {
+ if (reason instanceof AbortException) {
+ return null;
+ }
+ if (this.options.ignoreErrors) {
+ warn(`readToUnicode - ignoring ToUnicode data: "${reason}".`);
+ return null;
+ }
+ throw reason;
+ }
+ }
+ return null;
+ }
+ readCidToGidMap(glyphsData, toUnicode) {
+ const result = [];
+ for (let j = 0, jj = glyphsData.length; j < jj; j++) {
+ const glyphID = glyphsData[j++] << 8 | glyphsData[j];
+ const code = j >> 1;
+ if (glyphID === 0 && !toUnicode.has(code)) {
+ continue;
+ }
+ result[code] = glyphID;
+ }
+ return result;
+ }
+ extractWidths(dict, descriptor, properties) {
+ const xref = this.xref;
+ let glyphsWidths = [];
+ let defaultWidth = 0;
+ const glyphsVMetrics = [];
+ let defaultVMetrics;
+ let i, ii, j, jj, start, code, widths;
+ if (properties.composite) {
+ defaultWidth = dict.has("DW") ? dict.get("DW") : 1000;
+ widths = dict.get("W");
+ if (widths) {
+ for (i = 0, ii = widths.length; i < ii; i++) {
+ start = xref.fetchIfRef(widths[i++]);
+ code = xref.fetchIfRef(widths[i]);
+ if (Array.isArray(code)) {
+ for (j = 0, jj = code.length; j < jj; j++) {
+ glyphsWidths[start++] = xref.fetchIfRef(code[j]);
+ }
+ } else {
+ const width = xref.fetchIfRef(widths[++i]);
+ for (j = start; j <= code; j++) {
+ glyphsWidths[j] = width;
+ }
+ }
+ }
+ }
+ if (properties.vertical) {
+ let vmetrics = dict.getArray("DW2") || [880, -1000];
+ defaultVMetrics = [vmetrics[1], defaultWidth * 0.5, vmetrics[0]];
+ vmetrics = dict.get("W2");
+ if (vmetrics) {
+ for (i = 0, ii = vmetrics.length; i < ii; i++) {
+ start = xref.fetchIfRef(vmetrics[i++]);
+ code = xref.fetchIfRef(vmetrics[i]);
+ if (Array.isArray(code)) {
+ for (j = 0, jj = code.length; j < jj; j++) {
+ glyphsVMetrics[start++] = [xref.fetchIfRef(code[j++]), xref.fetchIfRef(code[j++]), xref.fetchIfRef(code[j])];
+ }
+ } else {
+ const vmetric = [xref.fetchIfRef(vmetrics[++i]), xref.fetchIfRef(vmetrics[++i]), xref.fetchIfRef(vmetrics[++i])];
+ for (j = start; j <= code; j++) {
+ glyphsVMetrics[j] = vmetric;
+ }
+ }
+ }
+ }
+ }
+ } else {
+ const firstChar = properties.firstChar;
+ widths = dict.get("Widths");
+ if (widths) {
+ j = firstChar;
+ for (i = 0, ii = widths.length; i < ii; i++) {
+ glyphsWidths[j++] = xref.fetchIfRef(widths[i]);
+ }
+ defaultWidth = parseFloat(descriptor.get("MissingWidth")) || 0;
+ } else {
+ const baseFontName = dict.get("BaseFont");
+ if (baseFontName instanceof Name) {
+ const metrics = this.getBaseFontMetrics(baseFontName.name);
+ glyphsWidths = this.buildCharCodeToWidth(metrics.widths, properties);
+ defaultWidth = metrics.defaultWidth;
+ }
+ }
+ }
+ let isMonospace = true;
+ let firstWidth = defaultWidth;
+ for (const glyph in glyphsWidths) {
+ const glyphWidth = glyphsWidths[glyph];
+ if (!glyphWidth) {
+ continue;
+ }
+ if (!firstWidth) {
+ firstWidth = glyphWidth;
+ continue;
+ }
+ if (firstWidth !== glyphWidth) {
+ isMonospace = false;
+ break;
+ }
+ }
+ if (isMonospace) {
+ properties.flags |= FontFlags.FixedPitch;
+ } else {
+ properties.flags &= ~FontFlags.FixedPitch;
+ }
+ properties.defaultWidth = defaultWidth;
+ properties.widths = glyphsWidths;
+ properties.defaultVMetrics = defaultVMetrics;
+ properties.vmetrics = glyphsVMetrics;
+ }
+ isSerifFont(baseFontName) {
+ const fontNameWoStyle = baseFontName.split("-", 1)[0];
+ return fontNameWoStyle in getSerifFonts() || /serif/gi.test(fontNameWoStyle);
+ }
+ getBaseFontMetrics(name) {
+ let defaultWidth = 0;
+ let widths = Object.create(null);
+ let monospace = false;
+ const stdFontMap = getStdFontMap();
+ let lookupName = stdFontMap[name] || name;
+ const Metrics = getMetrics();
+ if (!(lookupName in Metrics)) {
+ lookupName = this.isSerifFont(name) ? "Times-Roman" : "Helvetica";
+ }
+ const glyphWidths = Metrics[lookupName];
+ if (typeof glyphWidths === "number") {
+ defaultWidth = glyphWidths;
+ monospace = true;
+ } else {
+ widths = glyphWidths();
+ }
+ return {
+ defaultWidth,
+ monospace,
+ widths
+ };
+ }
+ buildCharCodeToWidth(widthsByGlyphName, properties) {
+ const widths = Object.create(null);
+ const differences = properties.differences;
+ const encoding = properties.defaultEncoding;
+ for (let charCode = 0; charCode < 256; charCode++) {
+ if (charCode in differences && widthsByGlyphName[differences[charCode]]) {
+ widths[charCode] = widthsByGlyphName[differences[charCode]];
+ continue;
+ }
+ if (charCode in encoding && widthsByGlyphName[encoding[charCode]]) {
+ widths[charCode] = widthsByGlyphName[encoding[charCode]];
+ continue;
+ }
+ }
+ return widths;
+ }
+ preEvaluateFont(dict) {
+ const baseDict = dict;
+ let type = dict.get("Subtype");
+ if (!(type instanceof Name)) {
+ throw new FormatError("invalid font Subtype");
+ }
+ let composite = false;
+ let hash;
+ if (type.name === "Type0") {
+ const df = dict.get("DescendantFonts");
+ if (!df) {
+ throw new FormatError("Descendant fonts are not specified");
+ }
+ dict = Array.isArray(df) ? this.xref.fetchIfRef(df[0]) : df;
+ if (!(dict instanceof Dict)) {
+ throw new FormatError("Descendant font is not a dictionary.");
+ }
+ type = dict.get("Subtype");
+ if (!(type instanceof Name)) {
+ throw new FormatError("invalid font Subtype");
+ }
+ composite = true;
+ }
+ const firstChar = dict.get("FirstChar") || 0,
+ lastChar = dict.get("LastChar") || (composite ? 0xffff : 0xff);
+ const descriptor = dict.get("FontDescriptor");
+ const toUnicode = dict.get("ToUnicode") || baseDict.get("ToUnicode");
+ if (descriptor) {
+ hash = new MurmurHash3_64();
+ const encoding = baseDict.getRaw("Encoding");
+ if (encoding instanceof Name) {
+ hash.update(encoding.name);
+ } else if (encoding instanceof Ref) {
+ hash.update(encoding.toString());
+ } else if (encoding instanceof Dict) {
+ for (const entry of encoding.getRawValues()) {
+ if (entry instanceof Name) {
+ hash.update(entry.name);
+ } else if (entry instanceof Ref) {
+ hash.update(entry.toString());
+ } else if (Array.isArray(entry)) {
+ const diffLength = entry.length,
+ diffBuf = new Array(diffLength);
+ for (let j = 0; j < diffLength; j++) {
+ const diffEntry = entry[j];
+ if (diffEntry instanceof Name) {
+ diffBuf[j] = diffEntry.name;
+ } else if (typeof diffEntry === "number" || diffEntry instanceof Ref) {
+ diffBuf[j] = diffEntry.toString();
+ }
+ }
+ hash.update(diffBuf.join());
+ }
+ }
+ }
+ hash.update(`${firstChar}-${lastChar}`);
+ if (toUnicode instanceof BaseStream) {
+ const stream = toUnicode.str || toUnicode;
+ const uint8array = stream.buffer ? new Uint8Array(stream.buffer.buffer, 0, stream.bufferLength) : new Uint8Array(stream.bytes.buffer, stream.start, stream.end - stream.start);
+ hash.update(uint8array);
+ } else if (toUnicode instanceof Name) {
+ hash.update(toUnicode.name);
+ }
+ const widths = dict.get("Widths") || baseDict.get("Widths");
+ if (Array.isArray(widths)) {
+ const widthsBuf = [];
+ for (const entry of widths) {
+ if (typeof entry === "number" || entry instanceof Ref) {
+ widthsBuf.push(entry.toString());
+ }
+ }
+ hash.update(widthsBuf.join());
+ }
+ if (composite) {
+ hash.update("compositeFont");
+ const compositeWidths = dict.get("W") || baseDict.get("W");
+ if (Array.isArray(compositeWidths)) {
+ const widthsBuf = [];
+ for (const entry of compositeWidths) {
+ if (typeof entry === "number" || entry instanceof Ref) {
+ widthsBuf.push(entry.toString());
+ } else if (Array.isArray(entry)) {
+ const subWidthsBuf = [];
+ for (const element of entry) {
+ if (typeof element === "number" || element instanceof Ref) {
+ subWidthsBuf.push(element.toString());
+ }
+ }
+ widthsBuf.push(`[${subWidthsBuf.join()}]`);
+ }
+ }
+ hash.update(widthsBuf.join());
+ }
+ const cidToGidMap = dict.getRaw("CIDToGIDMap") || baseDict.getRaw("CIDToGIDMap");
+ if (cidToGidMap instanceof Name) {
+ hash.update(cidToGidMap.name);
+ } else if (cidToGidMap instanceof Ref) {
+ hash.update(cidToGidMap.toString());
+ } else if (cidToGidMap instanceof BaseStream) {
+ hash.update(cidToGidMap.peekBytes());
+ }
+ }
+ }
+ return {
+ descriptor,
+ dict,
+ baseDict,
+ composite,
+ type: type.name,
+ firstChar,
+ lastChar,
+ toUnicode,
+ hash: hash ? hash.hexdigest() : ""
+ };
+ }
+ async translateFont({
+ descriptor,
+ dict,
+ baseDict,
+ composite,
+ type,
+ firstChar,
+ lastChar,
+ toUnicode,
+ cssFontInfo
+ }) {
+ const isType3Font = type === "Type3";
+ if (!descriptor) {
+ if (isType3Font) {
+ descriptor = new Dict(null);
+ descriptor.set("FontName", Name.get(type));
+ descriptor.set("FontBBox", dict.getArray("FontBBox") || [0, 0, 0, 0]);
+ } else {
+ let baseFontName = dict.get("BaseFont");
+ if (!(baseFontName instanceof Name)) {
+ throw new FormatError("Base font is not specified");
+ }
+ baseFontName = baseFontName.name.replaceAll(/[,_]/g, "-");
+ const metrics = this.getBaseFontMetrics(baseFontName);
+ const fontNameWoStyle = baseFontName.split("-", 1)[0];
+ const flags = (this.isSerifFont(fontNameWoStyle) ? FontFlags.Serif : 0) | (metrics.monospace ? FontFlags.FixedPitch : 0) | (getSymbolsFonts()[fontNameWoStyle] ? FontFlags.Symbolic : FontFlags.Nonsymbolic);
+ const properties = {
+ type,
+ name: baseFontName,
+ loadedName: baseDict.loadedName,
+ systemFontInfo: null,
+ widths: metrics.widths,
+ defaultWidth: metrics.defaultWidth,
+ isSimulatedFlags: true,
+ flags,
+ firstChar,
+ lastChar,
+ toUnicode,
+ xHeight: 0,
+ capHeight: 0,
+ italicAngle: 0,
+ isType3Font
+ };
+ const widths = dict.get("Widths");
+ const standardFontName = getStandardFontName(baseFontName);
+ let file = null;
+ if (standardFontName) {
+ file = await this.fetchStandardFontData(standardFontName);
+ properties.isInternalFont = !!file;
+ }
+ if (!properties.isInternalFont && this.options.useSystemFonts) {
+ properties.systemFontInfo = getFontSubstitution(this.systemFontCache, this.idFactory, this.options.standardFontDataUrl, baseFontName, standardFontName);
+ }
+ const newProperties = await this.extractDataStructures(dict, properties);
+ if (widths) {
+ const glyphWidths = [];
+ let j = firstChar;
+ for (const width of widths) {
+ glyphWidths[j++] = this.xref.fetchIfRef(width);
+ }
+ newProperties.widths = glyphWidths;
+ } else {
+ newProperties.widths = this.buildCharCodeToWidth(metrics.widths, newProperties);
+ }
+ return new Font(baseFontName, file, newProperties);
+ }
+ }
+ let fontName = descriptor.get("FontName");
+ let baseFont = dict.get("BaseFont");
+ if (typeof fontName === "string") {
+ fontName = Name.get(fontName);
+ }
+ if (typeof baseFont === "string") {
+ baseFont = Name.get(baseFont);
+ }
+ const fontNameStr = fontName?.name;
+ const baseFontStr = baseFont?.name;
+ if (!isType3Font && fontNameStr !== baseFontStr) {
+ info(`The FontDescriptor's FontName is "${fontNameStr}" but ` + `should be the same as the Font's BaseFont "${baseFontStr}".`);
+ if (fontNameStr && baseFontStr && (baseFontStr.startsWith(fontNameStr) || !isKnownFontName(fontNameStr) && isKnownFontName(baseFontStr))) {
+ fontName = null;
+ }
+ }
+ fontName ||= baseFont;
+ if (!(fontName instanceof Name)) {
+ throw new FormatError("invalid font name");
+ }
+ let fontFile, subtype, length1, length2, length3;
+ try {
+ fontFile = descriptor.get("FontFile", "FontFile2", "FontFile3");
+ } catch (ex) {
+ if (!this.options.ignoreErrors) {
+ throw ex;
+ }
+ warn(`translateFont - fetching "${fontName.name}" font file: "${ex}".`);
+ fontFile = new NullStream();
+ }
+ let isInternalFont = false;
+ let glyphScaleFactors = null;
+ let systemFontInfo = null;
+ if (fontFile) {
+ if (fontFile.dict) {
+ const subtypeEntry = fontFile.dict.get("Subtype");
+ if (subtypeEntry instanceof Name) {
+ subtype = subtypeEntry.name;
+ }
+ length1 = fontFile.dict.get("Length1");
+ length2 = fontFile.dict.get("Length2");
+ length3 = fontFile.dict.get("Length3");
+ }
+ } else if (cssFontInfo) {
+ const standardFontName = getXfaFontName(fontName.name);
+ if (standardFontName) {
+ cssFontInfo.fontFamily = `${cssFontInfo.fontFamily}-PdfJS-XFA`;
+ cssFontInfo.metrics = standardFontName.metrics || null;
+ glyphScaleFactors = standardFontName.factors || null;
+ fontFile = await this.fetchStandardFontData(standardFontName.name);
+ isInternalFont = !!fontFile;
+ baseDict = dict = getXfaFontDict(fontName.name);
+ composite = true;
+ }
+ } else if (!isType3Font) {
+ const standardFontName = getStandardFontName(fontName.name);
+ if (standardFontName) {
+ fontFile = await this.fetchStandardFontData(standardFontName);
+ isInternalFont = !!fontFile;
+ }
+ if (!isInternalFont && this.options.useSystemFonts) {
+ systemFontInfo = getFontSubstitution(this.systemFontCache, this.idFactory, this.options.standardFontDataUrl, fontName.name, standardFontName);
+ }
+ }
+ const properties = {
+ type,
+ name: fontName.name,
+ subtype,
+ file: fontFile,
+ length1,
+ length2,
+ length3,
+ isInternalFont,
+ loadedName: baseDict.loadedName,
+ composite,
+ fixedPitch: false,
+ fontMatrix: dict.getArray("FontMatrix") || FONT_IDENTITY_MATRIX,
+ firstChar,
+ lastChar,
+ toUnicode,
+ bbox: descriptor.getArray("FontBBox") || dict.getArray("FontBBox"),
+ ascent: descriptor.get("Ascent"),
+ descent: descriptor.get("Descent"),
+ xHeight: descriptor.get("XHeight") || 0,
+ capHeight: descriptor.get("CapHeight") || 0,
+ flags: descriptor.get("Flags"),
+ italicAngle: descriptor.get("ItalicAngle") || 0,
+ isType3Font,
+ cssFontInfo,
+ scaleFactors: glyphScaleFactors,
+ systemFontInfo
+ };
+ if (composite) {
+ const cidEncoding = baseDict.get("Encoding");
+ if (cidEncoding instanceof Name) {
+ properties.cidEncoding = cidEncoding.name;
+ }
+ const cMap = await CMapFactory.create({
+ encoding: cidEncoding,
+ fetchBuiltInCMap: this._fetchBuiltInCMapBound,
+ useCMap: null
+ });
+ properties.cMap = cMap;
+ properties.vertical = properties.cMap.vertical;
+ }
+ const newProperties = await this.extractDataStructures(dict, properties);
+ this.extractWidths(dict, descriptor, newProperties);
+ return new Font(fontName.name, fontFile, newProperties);
+ }
+ static buildFontPaths(font, glyphs, handler, evaluatorOptions) {
+ function buildPath(fontChar) {
+ const glyphName = `${font.loadedName}_path_${fontChar}`;
+ try {
+ if (font.renderer.hasBuiltPath(fontChar)) {
+ return;
+ }
+ handler.send("commonobj", [glyphName, "FontPath", font.renderer.getPathJs(fontChar)]);
+ } catch (reason) {
+ if (evaluatorOptions.ignoreErrors) {
+ warn(`buildFontPaths - ignoring ${glyphName} glyph: "${reason}".`);
+ return;
+ }
+ throw reason;
+ }
+ }
+ for (const glyph of glyphs) {
+ buildPath(glyph.fontChar);
+ const accent = glyph.accent;
+ if (accent?.fontChar) {
+ buildPath(accent.fontChar);
+ }
+ }
+ }
+ static get fallbackFontDict() {
+ const dict = new Dict();
+ dict.set("BaseFont", Name.get("Helvetica"));
+ dict.set("Type", Name.get("FallbackType"));
+ dict.set("Subtype", Name.get("FallbackType"));
+ dict.set("Encoding", Name.get("WinAnsiEncoding"));
+ return shadow(this, "fallbackFontDict", dict);
+ }
+}
+class TranslatedFont {
+ constructor({
+ loadedName,
+ font,
+ dict,
+ evaluatorOptions
+ }) {
+ this.loadedName = loadedName;
+ this.font = font;
+ this.dict = dict;
+ this._evaluatorOptions = evaluatorOptions || DefaultPartialEvaluatorOptions;
+ this.type3Loaded = null;
+ this.type3Dependencies = font.isType3Font ? new Set() : null;
+ this.sent = false;
+ }
+ send(handler) {
+ if (this.sent) {
+ return;
+ }
+ this.sent = true;
+ handler.send("commonobj", [this.loadedName, "Font", this.font.exportData(this._evaluatorOptions.fontExtraProperties)]);
+ }
+ fallback(handler) {
+ if (!this.font.data) {
+ return;
+ }
+ this.font.disableFontFace = true;
+ PartialEvaluator.buildFontPaths(this.font, this.font.glyphCacheValues, handler, this._evaluatorOptions);
+ }
+ loadType3Data(evaluator, resources, task) {
+ if (this.type3Loaded) {
+ return this.type3Loaded;
+ }
+ if (!this.font.isType3Font) {
+ throw new Error("Must be a Type3 font.");
+ }
+ const type3Evaluator = evaluator.clone({
+ ignoreErrors: false
+ });
+ type3Evaluator.parsingType3Font = true;
+ const type3FontRefs = new RefSet(evaluator.type3FontRefs);
+ if (this.dict.objId && !type3FontRefs.has(this.dict.objId)) {
+ type3FontRefs.put(this.dict.objId);
+ }
+ type3Evaluator.type3FontRefs = type3FontRefs;
+ const translatedFont = this.font,
+ type3Dependencies = this.type3Dependencies;
+ let loadCharProcsPromise = Promise.resolve();
+ const charProcs = this.dict.get("CharProcs");
+ const fontResources = this.dict.get("Resources") || resources;
+ const charProcOperatorList = Object.create(null);
+ const fontBBox = Util.normalizeRect(translatedFont.bbox || [0, 0, 0, 0]),
+ width = fontBBox[2] - fontBBox[0],
+ height = fontBBox[3] - fontBBox[1];
+ const fontBBoxSize = Math.hypot(width, height);
+ for (const key of charProcs.getKeys()) {
+ loadCharProcsPromise = loadCharProcsPromise.then(() => {
+ const glyphStream = charProcs.get(key);
+ const operatorList = new OperatorList();
+ return type3Evaluator.getOperatorList({
+ stream: glyphStream,
+ task,
+ resources: fontResources,
+ operatorList
+ }).then(() => {
+ if (operatorList.fnArray[0] === OPS.setCharWidthAndBounds) {
+ this._removeType3ColorOperators(operatorList, fontBBoxSize);
+ }
+ charProcOperatorList[key] = operatorList.getIR();
+ for (const dependency of operatorList.dependencies) {
+ type3Dependencies.add(dependency);
+ }
+ }).catch(function (reason) {
+ warn(`Type3 font resource "${key}" is not available.`);
+ const dummyOperatorList = new OperatorList();
+ charProcOperatorList[key] = dummyOperatorList.getIR();
+ });
+ });
+ }
+ this.type3Loaded = loadCharProcsPromise.then(() => {
+ translatedFont.charProcOperatorList = charProcOperatorList;
+ if (this._bbox) {
+ translatedFont.isCharBBox = true;
+ translatedFont.bbox = this._bbox;
+ }
+ });
+ return this.type3Loaded;
+ }
+ _removeType3ColorOperators(operatorList, fontBBoxSize = NaN) {
+ const charBBox = Util.normalizeRect(operatorList.argsArray[0].slice(2)),
+ width = charBBox[2] - charBBox[0],
+ height = charBBox[3] - charBBox[1];
+ const charBBoxSize = Math.hypot(width, height);
+ if (width === 0 || height === 0) {
+ operatorList.fnArray.splice(0, 1);
+ operatorList.argsArray.splice(0, 1);
+ } else if (fontBBoxSize === 0 || Math.round(charBBoxSize / fontBBoxSize) >= 10) {
+ if (!this._bbox) {
+ this._bbox = [Infinity, Infinity, -Infinity, -Infinity];
+ }
+ this._bbox[0] = Math.min(this._bbox[0], charBBox[0]);
+ this._bbox[1] = Math.min(this._bbox[1], charBBox[1]);
+ this._bbox[2] = Math.max(this._bbox[2], charBBox[2]);
+ this._bbox[3] = Math.max(this._bbox[3], charBBox[3]);
+ }
+ let i = 0,
+ ii = operatorList.length;
+ while (i < ii) {
+ switch (operatorList.fnArray[i]) {
+ case OPS.setCharWidthAndBounds:
+ break;
+ case OPS.setStrokeColorSpace:
+ case OPS.setFillColorSpace:
+ case OPS.setStrokeColor:
+ case OPS.setStrokeColorN:
+ case OPS.setFillColor:
+ case OPS.setFillColorN:
+ case OPS.setStrokeGray:
+ case OPS.setFillGray:
+ case OPS.setStrokeRGBColor:
+ case OPS.setFillRGBColor:
+ case OPS.setStrokeCMYKColor:
+ case OPS.setFillCMYKColor:
+ case OPS.shadingFill:
+ case OPS.setRenderingIntent:
+ operatorList.fnArray.splice(i, 1);
+ operatorList.argsArray.splice(i, 1);
+ ii--;
+ continue;
+ case OPS.setGState:
+ const [gStateObj] = operatorList.argsArray[i];
+ let j = 0,
+ jj = gStateObj.length;
+ while (j < jj) {
+ const [gStateKey] = gStateObj[j];
+ switch (gStateKey) {
+ case "TR":
+ case "TR2":
+ case "HT":
+ case "BG":
+ case "BG2":
+ case "UCR":
+ case "UCR2":
+ gStateObj.splice(j, 1);
+ jj--;
+ continue;
+ }
+ j++;
+ }
+ break;
+ }
+ i++;
+ }
+ }
+}
+class StateManager {
+ constructor(initialState = new EvalState()) {
+ this.state = initialState;
+ this.stateStack = [];
+ }
+ save() {
+ const old = this.state;
+ this.stateStack.push(this.state);
+ this.state = old.clone();
+ }
+ restore() {
+ const prev = this.stateStack.pop();
+ if (prev) {
+ this.state = prev;
+ }
+ }
+ transform(args) {
+ this.state.ctm = Util.transform(this.state.ctm, args);
+ }
+}
+class TextState {
+ constructor() {
+ this.ctm = new Float32Array(IDENTITY_MATRIX);
+ this.fontName = null;
+ this.fontSize = 0;
+ this.loadedName = null;
+ this.font = null;
+ this.fontMatrix = FONT_IDENTITY_MATRIX;
+ this.textMatrix = IDENTITY_MATRIX.slice();
+ this.textLineMatrix = IDENTITY_MATRIX.slice();
+ this.charSpacing = 0;
+ this.wordSpacing = 0;
+ this.leading = 0;
+ this.textHScale = 1;
+ this.textRise = 0;
+ }
+ setTextMatrix(a, b, c, d, e, f) {
+ const m = this.textMatrix;
+ m[0] = a;
+ m[1] = b;
+ m[2] = c;
+ m[3] = d;
+ m[4] = e;
+ m[5] = f;
+ }
+ setTextLineMatrix(a, b, c, d, e, f) {
+ const m = this.textLineMatrix;
+ m[0] = a;
+ m[1] = b;
+ m[2] = c;
+ m[3] = d;
+ m[4] = e;
+ m[5] = f;
+ }
+ translateTextMatrix(x, y) {
+ const m = this.textMatrix;
+ m[4] = m[0] * x + m[2] * y + m[4];
+ m[5] = m[1] * x + m[3] * y + m[5];
+ }
+ translateTextLineMatrix(x, y) {
+ const m = this.textLineMatrix;
+ m[4] = m[0] * x + m[2] * y + m[4];
+ m[5] = m[1] * x + m[3] * y + m[5];
+ }
+ carriageReturn() {
+ this.translateTextLineMatrix(0, -this.leading);
+ this.textMatrix = this.textLineMatrix.slice();
+ }
+ clone() {
+ const clone = Object.create(this);
+ clone.textMatrix = this.textMatrix.slice();
+ clone.textLineMatrix = this.textLineMatrix.slice();
+ clone.fontMatrix = this.fontMatrix.slice();
+ return clone;
+ }
+}
+class EvalState {
+ constructor() {
+ this.ctm = new Float32Array(IDENTITY_MATRIX);
+ this.font = null;
+ this.textRenderingMode = TextRenderingMode.FILL;
+ this.fillColorSpace = ColorSpace.singletons.gray;
+ this.strokeColorSpace = ColorSpace.singletons.gray;
+ }
+ clone() {
+ return Object.create(this);
+ }
+}
+class EvaluatorPreprocessor {
+ static get opMap() {
+ return shadow(this, "opMap", Object.assign(Object.create(null), {
+ w: {
+ id: OPS.setLineWidth,
+ numArgs: 1,
+ variableArgs: false
+ },
+ J: {
+ id: OPS.setLineCap,
+ numArgs: 1,
+ variableArgs: false
+ },
+ j: {
+ id: OPS.setLineJoin,
+ numArgs: 1,
+ variableArgs: false
+ },
+ M: {
+ id: OPS.setMiterLimit,
+ numArgs: 1,
+ variableArgs: false
+ },
+ d: {
+ id: OPS.setDash,
+ numArgs: 2,
+ variableArgs: false
+ },
+ ri: {
+ id: OPS.setRenderingIntent,
+ numArgs: 1,
+ variableArgs: false
+ },
+ i: {
+ id: OPS.setFlatness,
+ numArgs: 1,
+ variableArgs: false
+ },
+ gs: {
+ id: OPS.setGState,
+ numArgs: 1,
+ variableArgs: false
+ },
+ q: {
+ id: OPS.save,
+ numArgs: 0,
+ variableArgs: false
+ },
+ Q: {
+ id: OPS.restore,
+ numArgs: 0,
+ variableArgs: false
+ },
+ cm: {
+ id: OPS.transform,
+ numArgs: 6,
+ variableArgs: false
+ },
+ m: {
+ id: OPS.moveTo,
+ numArgs: 2,
+ variableArgs: false
+ },
+ l: {
+ id: OPS.lineTo,
+ numArgs: 2,
+ variableArgs: false
+ },
+ c: {
+ id: OPS.curveTo,
+ numArgs: 6,
+ variableArgs: false
+ },
+ v: {
+ id: OPS.curveTo2,
+ numArgs: 4,
+ variableArgs: false
+ },
+ y: {
+ id: OPS.curveTo3,
+ numArgs: 4,
+ variableArgs: false
+ },
+ h: {
+ id: OPS.closePath,
+ numArgs: 0,
+ variableArgs: false
+ },
+ re: {
+ id: OPS.rectangle,
+ numArgs: 4,
+ variableArgs: false
+ },
+ S: {
+ id: OPS.stroke,
+ numArgs: 0,
+ variableArgs: false
+ },
+ s: {
+ id: OPS.closeStroke,
+ numArgs: 0,
+ variableArgs: false
+ },
+ f: {
+ id: OPS.fill,
+ numArgs: 0,
+ variableArgs: false
+ },
+ F: {
+ id: OPS.fill,
+ numArgs: 0,
+ variableArgs: false
+ },
+ "f*": {
+ id: OPS.eoFill,
+ numArgs: 0,
+ variableArgs: false
+ },
+ B: {
+ id: OPS.fillStroke,
+ numArgs: 0,
+ variableArgs: false
+ },
+ "B*": {
+ id: OPS.eoFillStroke,
+ numArgs: 0,
+ variableArgs: false
+ },
+ b: {
+ id: OPS.closeFillStroke,
+ numArgs: 0,
+ variableArgs: false
+ },
+ "b*": {
+ id: OPS.closeEOFillStroke,
+ numArgs: 0,
+ variableArgs: false
+ },
+ n: {
+ id: OPS.endPath,
+ numArgs: 0,
+ variableArgs: false
+ },
+ W: {
+ id: OPS.clip,
+ numArgs: 0,
+ variableArgs: false
+ },
+ "W*": {
+ id: OPS.eoClip,
+ numArgs: 0,
+ variableArgs: false
+ },
+ BT: {
+ id: OPS.beginText,
+ numArgs: 0,
+ variableArgs: false
+ },
+ ET: {
+ id: OPS.endText,
+ numArgs: 0,
+ variableArgs: false
+ },
+ Tc: {
+ id: OPS.setCharSpacing,
+ numArgs: 1,
+ variableArgs: false
+ },
+ Tw: {
+ id: OPS.setWordSpacing,
+ numArgs: 1,
+ variableArgs: false
+ },
+ Tz: {
+ id: OPS.setHScale,
+ numArgs: 1,
+ variableArgs: false
+ },
+ TL: {
+ id: OPS.setLeading,
+ numArgs: 1,
+ variableArgs: false
+ },
+ Tf: {
+ id: OPS.setFont,
+ numArgs: 2,
+ variableArgs: false
+ },
+ Tr: {
+ id: OPS.setTextRenderingMode,
+ numArgs: 1,
+ variableArgs: false
+ },
+ Ts: {
+ id: OPS.setTextRise,
+ numArgs: 1,
+ variableArgs: false
+ },
+ Td: {
+ id: OPS.moveText,
+ numArgs: 2,
+ variableArgs: false
+ },
+ TD: {
+ id: OPS.setLeadingMoveText,
+ numArgs: 2,
+ variableArgs: false
+ },
+ Tm: {
+ id: OPS.setTextMatrix,
+ numArgs: 6,
+ variableArgs: false
+ },
+ "T*": {
+ id: OPS.nextLine,
+ numArgs: 0,
+ variableArgs: false
+ },
+ Tj: {
+ id: OPS.showText,
+ numArgs: 1,
+ variableArgs: false
+ },
+ TJ: {
+ id: OPS.showSpacedText,
+ numArgs: 1,
+ variableArgs: false
+ },
+ "'": {
+ id: OPS.nextLineShowText,
+ numArgs: 1,
+ variableArgs: false
+ },
+ '"': {
+ id: OPS.nextLineSetSpacingShowText,
+ numArgs: 3,
+ variableArgs: false
+ },
+ d0: {
+ id: OPS.setCharWidth,
+ numArgs: 2,
+ variableArgs: false
+ },
+ d1: {
+ id: OPS.setCharWidthAndBounds,
+ numArgs: 6,
+ variableArgs: false
+ },
+ CS: {
+ id: OPS.setStrokeColorSpace,
+ numArgs: 1,
+ variableArgs: false
+ },
+ cs: {
+ id: OPS.setFillColorSpace,
+ numArgs: 1,
+ variableArgs: false
+ },
+ SC: {
+ id: OPS.setStrokeColor,
+ numArgs: 4,
+ variableArgs: true
+ },
+ SCN: {
+ id: OPS.setStrokeColorN,
+ numArgs: 33,
+ variableArgs: true
+ },
+ sc: {
+ id: OPS.setFillColor,
+ numArgs: 4,
+ variableArgs: true
+ },
+ scn: {
+ id: OPS.setFillColorN,
+ numArgs: 33,
+ variableArgs: true
+ },
+ G: {
+ id: OPS.setStrokeGray,
+ numArgs: 1,
+ variableArgs: false
+ },
+ g: {
+ id: OPS.setFillGray,
+ numArgs: 1,
+ variableArgs: false
+ },
+ RG: {
+ id: OPS.setStrokeRGBColor,
+ numArgs: 3,
+ variableArgs: false
+ },
+ rg: {
+ id: OPS.setFillRGBColor,
+ numArgs: 3,
+ variableArgs: false
+ },
+ K: {
+ id: OPS.setStrokeCMYKColor,
+ numArgs: 4,
+ variableArgs: false
+ },
+ k: {
+ id: OPS.setFillCMYKColor,
+ numArgs: 4,
+ variableArgs: false
+ },
+ sh: {
+ id: OPS.shadingFill,
+ numArgs: 1,
+ variableArgs: false
+ },
+ BI: {
+ id: OPS.beginInlineImage,
+ numArgs: 0,
+ variableArgs: false
+ },
+ ID: {
+ id: OPS.beginImageData,
+ numArgs: 0,
+ variableArgs: false
+ },
+ EI: {
+ id: OPS.endInlineImage,
+ numArgs: 1,
+ variableArgs: false
+ },
+ Do: {
+ id: OPS.paintXObject,
+ numArgs: 1,
+ variableArgs: false
+ },
+ MP: {
+ id: OPS.markPoint,
+ numArgs: 1,
+ variableArgs: false
+ },
+ DP: {
+ id: OPS.markPointProps,
+ numArgs: 2,
+ variableArgs: false
+ },
+ BMC: {
+ id: OPS.beginMarkedContent,
+ numArgs: 1,
+ variableArgs: false
+ },
+ BDC: {
+ id: OPS.beginMarkedContentProps,
+ numArgs: 2,
+ variableArgs: false
+ },
+ EMC: {
+ id: OPS.endMarkedContent,
+ numArgs: 0,
+ variableArgs: false
+ },
+ BX: {
+ id: OPS.beginCompat,
+ numArgs: 0,
+ variableArgs: false
+ },
+ EX: {
+ id: OPS.endCompat,
+ numArgs: 0,
+ variableArgs: false
+ },
+ BM: null,
+ BD: null,
+ true: null,
+ fa: null,
+ fal: null,
+ fals: null,
+ false: null,
+ nu: null,
+ nul: null,
+ null: null
+ }));
+ }
+ static MAX_INVALID_PATH_OPS = 10;
+ constructor(stream, xref, stateManager = new StateManager()) {
+ this.parser = new Parser({
+ lexer: new Lexer(stream, EvaluatorPreprocessor.opMap),
+ xref
+ });
+ this.stateManager = stateManager;
+ this.nonProcessedArgs = [];
+ this._isPathOp = false;
+ this._numInvalidPathOPS = 0;
+ }
+ get savedStatesDepth() {
+ return this.stateManager.stateStack.length;
+ }
+ read(operation) {
+ let args = operation.args;
+ while (true) {
+ const obj = this.parser.getObj();
+ if (obj instanceof Cmd) {
+ const cmd = obj.cmd;
+ const opSpec = EvaluatorPreprocessor.opMap[cmd];
+ if (!opSpec) {
+ warn(`Unknown command "${cmd}".`);
+ continue;
+ }
+ const fn = opSpec.id;
+ const numArgs = opSpec.numArgs;
+ let argsLength = args !== null ? args.length : 0;
+ if (!this._isPathOp) {
+ this._numInvalidPathOPS = 0;
+ }
+ this._isPathOp = fn >= OPS.moveTo && fn <= OPS.endPath;
+ if (!opSpec.variableArgs) {
+ if (argsLength !== numArgs) {
+ const nonProcessedArgs = this.nonProcessedArgs;
+ while (argsLength > numArgs) {
+ nonProcessedArgs.push(args.shift());
+ argsLength--;
+ }
+ while (argsLength < numArgs && nonProcessedArgs.length !== 0) {
+ if (args === null) {
+ args = [];
+ }
+ args.unshift(nonProcessedArgs.pop());
+ argsLength++;
+ }
+ }
+ if (argsLength < numArgs) {
+ const partialMsg = `command ${cmd}: expected ${numArgs} args, ` + `but received ${argsLength} args.`;
+ if (this._isPathOp && ++this._numInvalidPathOPS > EvaluatorPreprocessor.MAX_INVALID_PATH_OPS) {
+ throw new FormatError(`Invalid ${partialMsg}`);
+ }
+ warn(`Skipping ${partialMsg}`);
+ if (args !== null) {
+ args.length = 0;
+ }
+ continue;
+ }
+ } else if (argsLength > numArgs) {
+ info(`Command ${cmd}: expected [0, ${numArgs}] args, ` + `but received ${argsLength} args.`);
+ }
+ this.preprocessCommand(fn, args);
+ operation.fn = fn;
+ operation.args = args;
+ return true;
+ }
+ if (obj === EOF) {
+ return false;
+ }
+ if (obj !== null) {
+ if (args === null) {
+ args = [];
+ }
+ args.push(obj);
+ if (args.length > 33) {
+ throw new FormatError("Too many arguments");
+ }
+ }
+ }
+ }
+ preprocessCommand(fn, args) {
+ switch (fn | 0) {
+ case OPS.save:
+ this.stateManager.save();
+ break;
+ case OPS.restore:
+ this.stateManager.restore();
+ break;
+ case OPS.transform:
+ this.stateManager.transform(args);
+ break;
+ }
+ }
+}
+
+;// CONCATENATED MODULE: ./src/core/default_appearance.js
+
+
+
+
+
+
+
+
+class DefaultAppearanceEvaluator extends EvaluatorPreprocessor {
+ constructor(str) {
+ super(new StringStream(str));
+ }
+ parse() {
+ const operation = {
+ fn: 0,
+ args: []
+ };
+ const result = {
+ fontSize: 0,
+ fontName: "",
+ fontColor: new Uint8ClampedArray(3)
+ };
+ try {
+ while (true) {
+ operation.args.length = 0;
+ if (!this.read(operation)) {
+ break;
+ }
+ if (this.savedStatesDepth !== 0) {
+ continue;
+ }
+ const {
+ fn,
+ args
+ } = operation;
+ switch (fn | 0) {
+ case OPS.setFont:
+ const [fontName, fontSize] = args;
+ if (fontName instanceof Name) {
+ result.fontName = fontName.name;
+ }
+ if (typeof fontSize === "number" && fontSize > 0) {
+ result.fontSize = fontSize;
+ }
+ break;
+ case OPS.setFillRGBColor:
+ ColorSpace.singletons.rgb.getRgbItem(args, 0, result.fontColor, 0);
+ break;
+ case OPS.setFillGray:
+ ColorSpace.singletons.gray.getRgbItem(args, 0, result.fontColor, 0);
+ break;
+ case OPS.setFillCMYKColor:
+ ColorSpace.singletons.cmyk.getRgbItem(args, 0, result.fontColor, 0);
+ break;
+ }
+ }
+ } catch (reason) {
+ warn(`parseDefaultAppearance - ignoring errors: "${reason}".`);
+ }
+ return result;
+ }
+}
+function parseDefaultAppearance(str) {
+ return new DefaultAppearanceEvaluator(str).parse();
+}
+class AppearanceStreamEvaluator extends EvaluatorPreprocessor {
+ constructor(stream, evaluatorOptions, xref) {
+ super(stream);
+ this.stream = stream;
+ this.evaluatorOptions = evaluatorOptions;
+ this.xref = xref;
+ this.resources = stream.dict?.get("Resources");
+ }
+ parse() {
+ const operation = {
+ fn: 0,
+ args: []
+ };
+ let result = {
+ scaleFactor: 1,
+ fontSize: 0,
+ fontName: "",
+ fontColor: new Uint8ClampedArray(3),
+ fillColorSpace: ColorSpace.singletons.gray
+ };
+ let breakLoop = false;
+ const stack = [];
+ try {
+ while (true) {
+ operation.args.length = 0;
+ if (breakLoop || !this.read(operation)) {
+ break;
+ }
+ const {
+ fn,
+ args
+ } = operation;
+ switch (fn | 0) {
+ case OPS.save:
+ stack.push({
+ scaleFactor: result.scaleFactor,
+ fontSize: result.fontSize,
+ fontName: result.fontName,
+ fontColor: result.fontColor.slice(),
+ fillColorSpace: result.fillColorSpace
+ });
+ break;
+ case OPS.restore:
+ result = stack.pop() || result;
+ break;
+ case OPS.setTextMatrix:
+ result.scaleFactor *= Math.hypot(args[0], args[1]);
+ break;
+ case OPS.setFont:
+ const [fontName, fontSize] = args;
+ if (fontName instanceof Name) {
+ result.fontName = fontName.name;
+ }
+ if (typeof fontSize === "number" && fontSize > 0) {
+ result.fontSize = fontSize * result.scaleFactor;
+ }
+ break;
+ case OPS.setFillColorSpace:
+ result.fillColorSpace = ColorSpace.parse({
+ cs: args[0],
+ xref: this.xref,
+ resources: this.resources,
+ pdfFunctionFactory: this._pdfFunctionFactory,
+ localColorSpaceCache: this._localColorSpaceCache
+ });
+ break;
+ case OPS.setFillColor:
+ const cs = result.fillColorSpace;
+ cs.getRgbItem(args, 0, result.fontColor, 0);
+ break;
+ case OPS.setFillRGBColor:
+ ColorSpace.singletons.rgb.getRgbItem(args, 0, result.fontColor, 0);
+ break;
+ case OPS.setFillGray:
+ ColorSpace.singletons.gray.getRgbItem(args, 0, result.fontColor, 0);
+ break;
+ case OPS.setFillCMYKColor:
+ ColorSpace.singletons.cmyk.getRgbItem(args, 0, result.fontColor, 0);
+ break;
+ case OPS.showText:
+ case OPS.showSpacedText:
+ case OPS.nextLineShowText:
+ case OPS.nextLineSetSpacingShowText:
+ breakLoop = true;
+ break;
+ }
+ }
+ } catch (reason) {
+ warn(`parseAppearanceStream - ignoring errors: "${reason}".`);
+ }
+ this.stream.reset();
+ delete result.scaleFactor;
+ delete result.fillColorSpace;
+ return result;
+ }
+ get _localColorSpaceCache() {
+ return shadow(this, "_localColorSpaceCache", new LocalColorSpaceCache());
+ }
+ get _pdfFunctionFactory() {
+ const pdfFunctionFactory = new PDFFunctionFactory({
+ xref: this.xref,
+ isEvalSupported: this.evaluatorOptions.isEvalSupported
+ });
+ return shadow(this, "_pdfFunctionFactory", pdfFunctionFactory);
+ }
+}
+function parseAppearanceStream(stream, evaluatorOptions, xref) {
+ return new AppearanceStreamEvaluator(stream, evaluatorOptions, xref).parse();
+}
+function getPdfColor(color, isFill) {
+ if (color[0] === color[1] && color[1] === color[2]) {
+ const gray = color[0] / 255;
+ return `${numberToString(gray)} ${isFill ? "g" : "G"}`;
+ }
+ return Array.from(color, c => numberToString(c / 255)).join(" ") + ` ${isFill ? "rg" : "RG"}`;
+}
+function createDefaultAppearance({
+ fontSize,
+ fontName,
+ fontColor
+}) {
+ return `/${escapePDFName(fontName)} ${fontSize} Tf ${getPdfColor(fontColor, true)}`;
+}
+class FakeUnicodeFont {
+ constructor(xref, fontFamily) {
+ this.xref = xref;
+ this.widths = null;
+ this.firstChar = Infinity;
+ this.lastChar = -Infinity;
+ this.fontFamily = fontFamily;
+ const canvas = new OffscreenCanvas(1, 1);
+ this.ctxMeasure = canvas.getContext("2d");
+ if (!FakeUnicodeFont._fontNameId) {
+ FakeUnicodeFont._fontNameId = 1;
+ }
+ this.fontName = Name.get(`InvalidPDFjsFont_${fontFamily}_${FakeUnicodeFont._fontNameId++}`);
+ }
+ get fontDescriptorRef() {
+ if (!FakeUnicodeFont._fontDescriptorRef) {
+ const fontDescriptor = new Dict(this.xref);
+ fontDescriptor.set("Type", Name.get("FontDescriptor"));
+ fontDescriptor.set("FontName", this.fontName);
+ fontDescriptor.set("FontFamily", "MyriadPro Regular");
+ fontDescriptor.set("FontBBox", [0, 0, 0, 0]);
+ fontDescriptor.set("FontStretch", Name.get("Normal"));
+ fontDescriptor.set("FontWeight", 400);
+ fontDescriptor.set("ItalicAngle", 0);
+ FakeUnicodeFont._fontDescriptorRef = this.xref.getNewPersistentRef(fontDescriptor);
+ }
+ return FakeUnicodeFont._fontDescriptorRef;
+ }
+ get descendantFontRef() {
+ const descendantFont = new Dict(this.xref);
+ descendantFont.set("BaseFont", this.fontName);
+ descendantFont.set("Type", Name.get("Font"));
+ descendantFont.set("Subtype", Name.get("CIDFontType0"));
+ descendantFont.set("CIDToGIDMap", Name.get("Identity"));
+ descendantFont.set("FirstChar", this.firstChar);
+ descendantFont.set("LastChar", this.lastChar);
+ descendantFont.set("FontDescriptor", this.fontDescriptorRef);
+ descendantFont.set("DW", 1000);
+ const widths = [];
+ const chars = [...this.widths.entries()].sort();
+ let currentChar = null;
+ let currentWidths = null;
+ for (const [char, width] of chars) {
+ if (!currentChar) {
+ currentChar = char;
+ currentWidths = [width];
+ continue;
+ }
+ if (char === currentChar + currentWidths.length) {
+ currentWidths.push(width);
+ } else {
+ widths.push(currentChar, currentWidths);
+ currentChar = char;
+ currentWidths = [width];
+ }
+ }
+ if (currentChar) {
+ widths.push(currentChar, currentWidths);
+ }
+ descendantFont.set("W", widths);
+ const cidSystemInfo = new Dict(this.xref);
+ cidSystemInfo.set("Ordering", "Identity");
+ cidSystemInfo.set("Registry", "Adobe");
+ cidSystemInfo.set("Supplement", 0);
+ descendantFont.set("CIDSystemInfo", cidSystemInfo);
+ return this.xref.getNewPersistentRef(descendantFont);
+ }
+ get baseFontRef() {
+ const baseFont = new Dict(this.xref);
+ baseFont.set("BaseFont", this.fontName);
+ baseFont.set("Type", Name.get("Font"));
+ baseFont.set("Subtype", Name.get("Type0"));
+ baseFont.set("Encoding", Name.get("Identity-H"));
+ baseFont.set("DescendantFonts", [this.descendantFontRef]);
+ baseFont.set("ToUnicode", Name.get("Identity-H"));
+ return this.xref.getNewPersistentRef(baseFont);
+ }
+ get resources() {
+ const resources = new Dict(this.xref);
+ const font = new Dict(this.xref);
+ font.set(this.fontName.name, this.baseFontRef);
+ resources.set("Font", font);
+ return resources;
+ }
+ _createContext() {
+ this.widths = new Map();
+ this.ctxMeasure.font = `1000px ${this.fontFamily}`;
+ return this.ctxMeasure;
+ }
+ createFontResources(text) {
+ const ctx = this._createContext();
+ for (const line of text.split(/\r\n?|\n/)) {
+ for (const char of line.split("")) {
+ const code = char.charCodeAt(0);
+ if (this.widths.has(code)) {
+ continue;
+ }
+ const metrics = ctx.measureText(char);
+ const width = Math.ceil(metrics.width);
+ this.widths.set(code, width);
+ this.firstChar = Math.min(code, this.firstChar);
+ this.lastChar = Math.max(code, this.lastChar);
+ }
+ }
+ return this.resources;
+ }
+ static getFirstPositionInfo(rect, rotation, fontSize) {
+ const [x1, y1, x2, y2] = rect;
+ let w = x2 - x1;
+ let h = y2 - y1;
+ if (rotation % 180 !== 0) {
+ [w, h] = [h, w];
+ }
+ const lineHeight = LINE_FACTOR * fontSize;
+ const lineDescent = LINE_DESCENT_FACTOR * fontSize;
+ return {
+ coords: [0, h + lineDescent - lineHeight],
+ bbox: [0, 0, w, h],
+ matrix: rotation !== 0 ? getRotationMatrix(rotation, h, lineHeight) : undefined
+ };
+ }
+ createAppearance(text, rect, rotation, fontSize, bgColor, strokeAlpha) {
+ const ctx = this._createContext();
+ const lines = [];
+ let maxWidth = -Infinity;
+ for (const line of text.split(/\r\n?|\n/)) {
+ lines.push(line);
+ const lineWidth = ctx.measureText(line).width;
+ maxWidth = Math.max(maxWidth, lineWidth);
+ for (const code of codePointIter(line)) {
+ const char = String.fromCodePoint(code);
+ let width = this.widths.get(code);
+ if (width === undefined) {
+ const metrics = ctx.measureText(char);
+ width = Math.ceil(metrics.width);
+ this.widths.set(code, width);
+ this.firstChar = Math.min(code, this.firstChar);
+ this.lastChar = Math.max(code, this.lastChar);
+ }
+ }
+ }
+ maxWidth *= fontSize / 1000;
+ const [x1, y1, x2, y2] = rect;
+ let w = x2 - x1;
+ let h = y2 - y1;
+ if (rotation % 180 !== 0) {
+ [w, h] = [h, w];
+ }
+ let hscale = 1;
+ if (maxWidth > w) {
+ hscale = w / maxWidth;
+ }
+ let vscale = 1;
+ const lineHeight = LINE_FACTOR * fontSize;
+ const lineDescent = LINE_DESCENT_FACTOR * fontSize;
+ const maxHeight = lineHeight * lines.length;
+ if (maxHeight > h) {
+ vscale = h / maxHeight;
+ }
+ const fscale = Math.min(hscale, vscale);
+ const newFontSize = fontSize * fscale;
+ const buffer = ["q", `0 0 ${numberToString(w)} ${numberToString(h)} re W n`, `BT`, `1 0 0 1 0 ${numberToString(h + lineDescent)} Tm 0 Tc ${getPdfColor(bgColor, true)}`, `/${this.fontName.name} ${numberToString(newFontSize)} Tf`];
+ const {
+ resources
+ } = this;
+ strokeAlpha = typeof strokeAlpha === "number" && strokeAlpha >= 0 && strokeAlpha <= 1 ? strokeAlpha : 1;
+ if (strokeAlpha !== 1) {
+ buffer.push("/R0 gs");
+ const extGState = new Dict(this.xref);
+ const r0 = new Dict(this.xref);
+ r0.set("ca", strokeAlpha);
+ r0.set("CA", strokeAlpha);
+ r0.set("Type", Name.get("ExtGState"));
+ extGState.set("R0", r0);
+ resources.set("ExtGState", extGState);
+ }
+ const vShift = numberToString(lineHeight);
+ for (const line of lines) {
+ buffer.push(`0 -${vShift} Td <${stringToUTF16HexString(line)}> Tj`);
+ }
+ buffer.push("ET", "Q");
+ const appearance = buffer.join("\n");
+ const appearanceStreamDict = new Dict(this.xref);
+ appearanceStreamDict.set("Subtype", Name.get("Form"));
+ appearanceStreamDict.set("Type", Name.get("XObject"));
+ appearanceStreamDict.set("BBox", [0, 0, w, h]);
+ appearanceStreamDict.set("Length", appearance.length);
+ appearanceStreamDict.set("Resources", resources);
+ if (rotation) {
+ const matrix = getRotationMatrix(rotation, w, h);
+ appearanceStreamDict.set("Matrix", matrix);
+ }
+ const ap = new StringStream(appearance);
+ ap.dict = appearanceStreamDict;
+ return ap;
+ }
+}
+
+;// CONCATENATED MODULE: ./src/core/name_number_tree.js
+
+
+class NameOrNumberTree {
+ constructor(root, xref, type) {
+ if (this.constructor === NameOrNumberTree) {
+ unreachable("Cannot initialize NameOrNumberTree.");
+ }
+ this.root = root;
+ this.xref = xref;
+ this._type = type;
+ }
+ getAll() {
+ const map = new Map();
+ if (!this.root) {
+ return map;
+ }
+ const xref = this.xref;
+ const processed = new RefSet();
+ processed.put(this.root);
+ const queue = [this.root];
+ while (queue.length > 0) {
+ const obj = xref.fetchIfRef(queue.shift());
+ if (!(obj instanceof Dict)) {
+ continue;
+ }
+ if (obj.has("Kids")) {
+ const kids = obj.get("Kids");
+ if (!Array.isArray(kids)) {
+ continue;
+ }
+ for (const kid of kids) {
+ if (processed.has(kid)) {
+ throw new FormatError(`Duplicate entry in "${this._type}" tree.`);
+ }
+ queue.push(kid);
+ processed.put(kid);
+ }
+ continue;
+ }
+ const entries = obj.get(this._type);
+ if (!Array.isArray(entries)) {
+ continue;
+ }
+ for (let i = 0, ii = entries.length; i < ii; i += 2) {
+ map.set(xref.fetchIfRef(entries[i]), xref.fetchIfRef(entries[i + 1]));
+ }
+ }
+ return map;
+ }
+ get(key) {
+ if (!this.root) {
+ return null;
+ }
+ const xref = this.xref;
+ let kidsOrEntries = xref.fetchIfRef(this.root);
+ let loopCount = 0;
+ const MAX_LEVELS = 10;
+ while (kidsOrEntries.has("Kids")) {
+ if (++loopCount > MAX_LEVELS) {
+ warn(`Search depth limit reached for "${this._type}" tree.`);
+ return null;
+ }
+ const kids = kidsOrEntries.get("Kids");
+ if (!Array.isArray(kids)) {
+ return null;
+ }
+ let l = 0,
+ r = kids.length - 1;
+ while (l <= r) {
+ const m = l + r >> 1;
+ const kid = xref.fetchIfRef(kids[m]);
+ const limits = kid.get("Limits");
+ if (key < xref.fetchIfRef(limits[0])) {
+ r = m - 1;
+ } else if (key > xref.fetchIfRef(limits[1])) {
+ l = m + 1;
+ } else {
+ kidsOrEntries = kid;
+ break;
+ }
+ }
+ if (l > r) {
+ return null;
+ }
+ }
+ const entries = kidsOrEntries.get(this._type);
+ if (Array.isArray(entries)) {
+ let l = 0,
+ r = entries.length - 2;
+ while (l <= r) {
+ const tmp = l + r >> 1,
+ m = tmp + (tmp & 1);
+ const currentKey = xref.fetchIfRef(entries[m]);
+ if (key < currentKey) {
+ r = m - 2;
+ } else if (key > currentKey) {
+ l = m + 2;
+ } else {
+ return xref.fetchIfRef(entries[m + 1]);
+ }
+ }
+ }
+ return null;
+ }
+}
+class NameTree extends NameOrNumberTree {
+ constructor(root, xref) {
+ super(root, xref, "Names");
+ }
+}
+class NumberTree extends NameOrNumberTree {
+ constructor(root, xref) {
+ super(root, xref, "Nums");
+ }
+}
+
+;// CONCATENATED MODULE: ./src/core/cleanup_helper.js
+
+
+
+function clearGlobalCaches() {
+ clearPatternCaches();
+ clearPrimitiveCaches();
+ clearUnicodeCaches();
+}
+
+;// CONCATENATED MODULE: ./src/core/file_spec.js
+
+
+
+function pickPlatformItem(dict) {
+ if (dict.has("UF")) {
+ return dict.get("UF");
+ } else if (dict.has("F")) {
+ return dict.get("F");
+ } else if (dict.has("Unix")) {
+ return dict.get("Unix");
+ } else if (dict.has("Mac")) {
+ return dict.get("Mac");
+ } else if (dict.has("DOS")) {
+ return dict.get("DOS");
+ }
+ return null;
+}
+class FileSpec {
+ constructor(root, xref) {
+ if (!(root instanceof Dict)) {
+ return;
+ }
+ this.xref = xref;
+ this.root = root;
+ if (root.has("FS")) {
+ this.fs = root.get("FS");
+ }
+ this.description = root.has("Desc") ? stringToPDFString(root.get("Desc")) : "";
+ if (root.has("RF")) {
+ warn("Related file specifications are not supported");
+ }
+ this.contentAvailable = true;
+ if (!root.has("EF")) {
+ this.contentAvailable = false;
+ warn("Non-embedded file specifications are not supported");
+ }
+ }
+ get filename() {
+ if (!this._filename && this.root) {
+ const filename = pickPlatformItem(this.root) || "unnamed";
+ this._filename = stringToPDFString(filename).replaceAll("\\\\", "\\").replaceAll("\\/", "/").replaceAll("\\", "/");
+ }
+ return this._filename;
+ }
+ get content() {
+ if (!this.contentAvailable) {
+ return null;
+ }
+ if (!this.contentRef && this.root) {
+ this.contentRef = pickPlatformItem(this.root.get("EF"));
+ }
+ let content = null;
+ if (this.contentRef) {
+ const fileObj = this.xref.fetchIfRef(this.contentRef);
+ if (fileObj instanceof BaseStream) {
+ content = fileObj.getBytes();
+ } else {
+ warn("Embedded file specification points to non-existing/invalid content");
+ }
+ } else {
+ warn("Embedded file specification does not have a content");
+ }
+ return content;
+ }
+ get serializable() {
+ return {
+ filename: this.filename,
+ content: this.content
+ };
+ }
+}
+
+;// CONCATENATED MODULE: ./src/core/xml_parser.js
+
+const XMLParserErrorCode = {
+ NoError: 0,
+ EndOfDocument: -1,
+ UnterminatedCdat: -2,
+ UnterminatedXmlDeclaration: -3,
+ UnterminatedDoctypeDeclaration: -4,
+ UnterminatedComment: -5,
+ MalformedElement: -6,
+ OutOfMemory: -7,
+ UnterminatedAttributeValue: -8,
+ UnterminatedElement: -9,
+ ElementNeverBegun: -10
+};
+function isWhitespace(s, index) {
+ const ch = s[index];
+ return ch === " " || ch === "\n" || ch === "\r" || ch === "\t";
+}
+function isWhitespaceString(s) {
+ for (let i = 0, ii = s.length; i < ii; i++) {
+ if (!isWhitespace(s, i)) {
+ return false;
+ }
+ }
+ return true;
+}
+class XMLParserBase {
+ _resolveEntities(s) {
+ return s.replaceAll(/&([^;]+);/g, (all, entity) => {
+ if (entity.substring(0, 2) === "#x") {
+ return String.fromCodePoint(parseInt(entity.substring(2), 16));
+ } else if (entity.substring(0, 1) === "#") {
+ return String.fromCodePoint(parseInt(entity.substring(1), 10));
+ }
+ switch (entity) {
+ case "lt":
+ return "<";
+ case "gt":
+ return ">";
+ case "amp":
+ return "&";
+ case "quot":
+ return '"';
+ case "apos":
+ return "'";
+ }
+ return this.onResolveEntity(entity);
+ });
+ }
+ _parseContent(s, start) {
+ const attributes = [];
+ let pos = start;
+ function skipWs() {
+ while (pos < s.length && isWhitespace(s, pos)) {
+ ++pos;
+ }
+ }
+ while (pos < s.length && !isWhitespace(s, pos) && s[pos] !== ">" && s[pos] !== "/") {
+ ++pos;
+ }
+ const name = s.substring(start, pos);
+ skipWs();
+ while (pos < s.length && s[pos] !== ">" && s[pos] !== "/" && s[pos] !== "?") {
+ skipWs();
+ let attrName = "",
+ attrValue = "";
+ while (pos < s.length && !isWhitespace(s, pos) && s[pos] !== "=") {
+ attrName += s[pos];
+ ++pos;
+ }
+ skipWs();
+ if (s[pos] !== "=") {
+ return null;
+ }
+ ++pos;
+ skipWs();
+ const attrEndChar = s[pos];
+ if (attrEndChar !== '"' && attrEndChar !== "'") {
+ return null;
+ }
+ const attrEndIndex = s.indexOf(attrEndChar, ++pos);
+ if (attrEndIndex < 0) {
+ return null;
+ }
+ attrValue = s.substring(pos, attrEndIndex);
+ attributes.push({
+ name: attrName,
+ value: this._resolveEntities(attrValue)
+ });
+ pos = attrEndIndex + 1;
+ skipWs();
+ }
+ return {
+ name,
+ attributes,
+ parsed: pos - start
+ };
+ }
+ _parseProcessingInstruction(s, start) {
+ let pos = start;
+ function skipWs() {
+ while (pos < s.length && isWhitespace(s, pos)) {
+ ++pos;
+ }
+ }
+ while (pos < s.length && !isWhitespace(s, pos) && s[pos] !== ">" && s[pos] !== "?" && s[pos] !== "/") {
+ ++pos;
+ }
+ const name = s.substring(start, pos);
+ skipWs();
+ const attrStart = pos;
+ while (pos < s.length && (s[pos] !== "?" || s[pos + 1] !== ">")) {
+ ++pos;
+ }
+ const value = s.substring(attrStart, pos);
+ return {
+ name,
+ value,
+ parsed: pos - start
+ };
+ }
+ parseXml(s) {
+ let i = 0;
+ while (i < s.length) {
+ const ch = s[i];
+ let j = i;
+ if (ch === "<") {
+ ++j;
+ const ch2 = s[j];
+ let q;
+ switch (ch2) {
+ case "/":
+ ++j;
+ q = s.indexOf(">", j);
+ if (q < 0) {
+ this.onError(XMLParserErrorCode.UnterminatedElement);
+ return;
+ }
+ this.onEndElement(s.substring(j, q));
+ j = q + 1;
+ break;
+ case "?":
+ ++j;
+ const pi = this._parseProcessingInstruction(s, j);
+ if (s.substring(j + pi.parsed, j + pi.parsed + 2) !== "?>") {
+ this.onError(XMLParserErrorCode.UnterminatedXmlDeclaration);
+ return;
+ }
+ this.onPi(pi.name, pi.value);
+ j += pi.parsed + 2;
+ break;
+ case "!":
+ if (s.substring(j + 1, j + 3) === "--") {
+ q = s.indexOf("-->", j + 3);
+ if (q < 0) {
+ this.onError(XMLParserErrorCode.UnterminatedComment);
+ return;
+ }
+ this.onComment(s.substring(j + 3, q));
+ j = q + 3;
+ } else if (s.substring(j + 1, j + 8) === "[CDATA[") {
+ q = s.indexOf("]]>", j + 8);
+ if (q < 0) {
+ this.onError(XMLParserErrorCode.UnterminatedCdat);
+ return;
+ }
+ this.onCdata(s.substring(j + 8, q));
+ j = q + 3;
+ } else if (s.substring(j + 1, j + 8) === "DOCTYPE") {
+ const q2 = s.indexOf("[", j + 8);
+ let complexDoctype = false;
+ q = s.indexOf(">", j + 8);
+ if (q < 0) {
+ this.onError(XMLParserErrorCode.UnterminatedDoctypeDeclaration);
+ return;
+ }
+ if (q2 > 0 && q > q2) {
+ q = s.indexOf("]>", j + 8);
+ if (q < 0) {
+ this.onError(XMLParserErrorCode.UnterminatedDoctypeDeclaration);
+ return;
+ }
+ complexDoctype = true;
+ }
+ const doctypeContent = s.substring(j + 8, q + (complexDoctype ? 1 : 0));
+ this.onDoctype(doctypeContent);
+ j = q + (complexDoctype ? 2 : 1);
+ } else {
+ this.onError(XMLParserErrorCode.MalformedElement);
+ return;
+ }
+ break;
+ default:
+ const content = this._parseContent(s, j);
+ if (content === null) {
+ this.onError(XMLParserErrorCode.MalformedElement);
+ return;
+ }
+ let isClosed = false;
+ if (s.substring(j + content.parsed, j + content.parsed + 2) === "/>") {
+ isClosed = true;
+ } else if (s.substring(j + content.parsed, j + content.parsed + 1) !== ">") {
+ this.onError(XMLParserErrorCode.UnterminatedElement);
+ return;
+ }
+ this.onBeginElement(content.name, content.attributes, isClosed);
+ j += content.parsed + (isClosed ? 2 : 1);
+ break;
+ }
+ } else {
+ while (j < s.length && s[j] !== "<") {
+ j++;
+ }
+ const text = s.substring(i, j);
+ this.onText(this._resolveEntities(text));
+ }
+ i = j;
+ }
+ }
+ onResolveEntity(name) {
+ return `&${name};`;
+ }
+ onPi(name, value) {}
+ onComment(text) {}
+ onCdata(text) {}
+ onDoctype(doctypeContent) {}
+ onText(text) {}
+ onBeginElement(name, attributes, isEmpty) {}
+ onEndElement(name) {}
+ onError(code) {}
+}
+class SimpleDOMNode {
+ constructor(nodeName, nodeValue) {
+ this.nodeName = nodeName;
+ this.nodeValue = nodeValue;
+ Object.defineProperty(this, "parentNode", {
+ value: null,
+ writable: true
+ });
+ }
+ get firstChild() {
+ return this.childNodes?.[0];
+ }
+ get nextSibling() {
+ const childNodes = this.parentNode.childNodes;
+ if (!childNodes) {
+ return undefined;
+ }
+ const index = childNodes.indexOf(this);
+ if (index === -1) {
+ return undefined;
+ }
+ return childNodes[index + 1];
+ }
+ get textContent() {
+ if (!this.childNodes) {
+ return this.nodeValue || "";
+ }
+ return this.childNodes.map(function (child) {
+ return child.textContent;
+ }).join("");
+ }
+ get children() {
+ return this.childNodes || [];
+ }
+ hasChildNodes() {
+ return this.childNodes?.length > 0;
+ }
+ searchNode(paths, pos) {
+ if (pos >= paths.length) {
+ return this;
+ }
+ const component = paths[pos];
+ if (component.name.startsWith("#") && pos < paths.length - 1) {
+ return this.searchNode(paths, pos + 1);
+ }
+ const stack = [];
+ let node = this;
+ while (true) {
+ if (component.name === node.nodeName) {
+ if (component.pos === 0) {
+ const res = node.searchNode(paths, pos + 1);
+ if (res !== null) {
+ return res;
+ }
+ } else if (stack.length === 0) {
+ return null;
+ } else {
+ const [parent] = stack.pop();
+ let siblingPos = 0;
+ for (const child of parent.childNodes) {
+ if (component.name === child.nodeName) {
+ if (siblingPos === component.pos) {
+ return child.searchNode(paths, pos + 1);
+ }
+ siblingPos++;
+ }
+ }
+ return node.searchNode(paths, pos + 1);
+ }
+ }
+ if (node.childNodes?.length > 0) {
+ stack.push([node, 0]);
+ node = node.childNodes[0];
+ } else if (stack.length === 0) {
+ return null;
+ } else {
+ while (stack.length !== 0) {
+ const [parent, currentPos] = stack.pop();
+ const newPos = currentPos + 1;
+ if (newPos < parent.childNodes.length) {
+ stack.push([parent, newPos]);
+ node = parent.childNodes[newPos];
+ break;
+ }
+ }
+ if (stack.length === 0) {
+ return null;
+ }
+ }
+ }
+ }
+ dump(buffer) {
+ if (this.nodeName === "#text") {
+ buffer.push(encodeToXmlString(this.nodeValue));
+ return;
+ }
+ buffer.push(`<${this.nodeName}`);
+ if (this.attributes) {
+ for (const attribute of this.attributes) {
+ buffer.push(` ${attribute.name}="${encodeToXmlString(attribute.value)}"`);
+ }
+ }
+ if (this.hasChildNodes()) {
+ buffer.push(">");
+ for (const child of this.childNodes) {
+ child.dump(buffer);
+ }
+ buffer.push(`</${this.nodeName}>`);
+ } else if (this.nodeValue) {
+ buffer.push(`>${encodeToXmlString(this.nodeValue)}</${this.nodeName}>`);
+ } else {
+ buffer.push("/>");
+ }
+ }
+}
+class SimpleXMLParser extends XMLParserBase {
+ constructor({
+ hasAttributes = false,
+ lowerCaseName = false
+ }) {
+ super();
+ this._currentFragment = null;
+ this._stack = null;
+ this._errorCode = XMLParserErrorCode.NoError;
+ this._hasAttributes = hasAttributes;
+ this._lowerCaseName = lowerCaseName;
+ }
+ parseFromString(data) {
+ this._currentFragment = [];
+ this._stack = [];
+ this._errorCode = XMLParserErrorCode.NoError;
+ this.parseXml(data);
+ if (this._errorCode !== XMLParserErrorCode.NoError) {
+ return undefined;
+ }
+ const [documentElement] = this._currentFragment;
+ if (!documentElement) {
+ return undefined;
+ }
+ return {
+ documentElement
+ };
+ }
+ onText(text) {
+ if (isWhitespaceString(text)) {
+ return;
+ }
+ const node = new SimpleDOMNode("#text", text);
+ this._currentFragment.push(node);
+ }
+ onCdata(text) {
+ const node = new SimpleDOMNode("#text", text);
+ this._currentFragment.push(node);
+ }
+ onBeginElement(name, attributes, isEmpty) {
+ if (this._lowerCaseName) {
+ name = name.toLowerCase();
+ }
+ const node = new SimpleDOMNode(name);
+ node.childNodes = [];
+ if (this._hasAttributes) {
+ node.attributes = attributes;
+ }
+ this._currentFragment.push(node);
+ if (isEmpty) {
+ return;
+ }
+ this._stack.push(this._currentFragment);
+ this._currentFragment = node.childNodes;
+ }
+ onEndElement(name) {
+ this._currentFragment = this._stack.pop() || [];
+ const lastElement = this._currentFragment.at(-1);
+ if (!lastElement) {
+ return null;
+ }
+ for (const childNode of lastElement.childNodes) {
+ childNode.parentNode = lastElement;
+ }
+ return lastElement;
+ }
+ onError(code) {
+ this._errorCode = code;
+ }
+}
+
+;// CONCATENATED MODULE: ./src/core/metadata_parser.js
+
+class MetadataParser {
+ constructor(data) {
+ data = this._repair(data);
+ const parser = new SimpleXMLParser({
+ lowerCaseName: true
+ });
+ const xmlDocument = parser.parseFromString(data);
+ this._metadataMap = new Map();
+ this._data = data;
+ if (xmlDocument) {
+ this._parse(xmlDocument);
+ }
+ }
+ _repair(data) {
+ return data.replace(/^[^<]+/, "").replaceAll(/>\\376\\377([^<]+)/g, function (all, codes) {
+ const bytes = codes.replaceAll(/\\([0-3])([0-7])([0-7])/g, function (code, d1, d2, d3) {
+ return String.fromCharCode(d1 * 64 + d2 * 8 + d3 * 1);
+ }).replaceAll(/&(amp|apos|gt|lt|quot);/g, function (str, name) {
+ switch (name) {
+ case "amp":
+ return "&";
+ case "apos":
+ return "'";
+ case "gt":
+ return ">";
+ case "lt":
+ return "<";
+ case "quot":
+ return '"';
+ }
+ throw new Error(`_repair: ${name} isn't defined.`);
+ });
+ const charBuf = [">"];
+ for (let i = 0, ii = bytes.length; i < ii; i += 2) {
+ const code = bytes.charCodeAt(i) * 256 + bytes.charCodeAt(i + 1);
+ if (code >= 32 && code < 127 && code !== 60 && code !== 62 && code !== 38) {
+ charBuf.push(String.fromCharCode(code));
+ } else {
+ charBuf.push("&#x" + (0x10000 + code).toString(16).substring(1) + ";");
+ }
+ }
+ return charBuf.join("");
+ });
+ }
+ _getSequence(entry) {
+ const name = entry.nodeName;
+ if (name !== "rdf:bag" && name !== "rdf:seq" && name !== "rdf:alt") {
+ return null;
+ }
+ return entry.childNodes.filter(node => node.nodeName === "rdf:li");
+ }
+ _parseArray(entry) {
+ if (!entry.hasChildNodes()) {
+ return;
+ }
+ const [seqNode] = entry.childNodes;
+ const sequence = this._getSequence(seqNode) || [];
+ this._metadataMap.set(entry.nodeName, sequence.map(node => node.textContent.trim()));
+ }
+ _parse(xmlDocument) {
+ let rdf = xmlDocument.documentElement;
+ if (rdf.nodeName !== "rdf:rdf") {
+ rdf = rdf.firstChild;
+ while (rdf && rdf.nodeName !== "rdf:rdf") {
+ rdf = rdf.nextSibling;
+ }
+ }
+ if (!rdf || rdf.nodeName !== "rdf:rdf" || !rdf.hasChildNodes()) {
+ return;
+ }
+ for (const desc of rdf.childNodes) {
+ if (desc.nodeName !== "rdf:description") {
+ continue;
+ }
+ for (const entry of desc.childNodes) {
+ const name = entry.nodeName;
+ switch (name) {
+ case "#text":
+ continue;
+ case "dc:creator":
+ case "dc:subject":
+ this._parseArray(entry);
+ continue;
+ }
+ this._metadataMap.set(name, entry.textContent.trim());
+ }
+ }
+ }
+ get serializable() {
+ return {
+ parsedData: this._metadataMap,
+ rawData: this._data
+ };
+ }
+}
+
+;// CONCATENATED MODULE: ./src/core/decrypt_stream.js
+
+const chunkSize = 512;
+class DecryptStream extends DecodeStream {
+ constructor(str, maybeLength, decrypt) {
+ super(maybeLength);
+ this.str = str;
+ this.dict = str.dict;
+ this.decrypt = decrypt;
+ this.nextChunk = null;
+ this.initialized = false;
+ }
+ readBlock() {
+ let chunk;
+ if (this.initialized) {
+ chunk = this.nextChunk;
+ } else {
+ chunk = this.str.getBytes(chunkSize);
+ this.initialized = true;
+ }
+ if (!chunk || chunk.length === 0) {
+ this.eof = true;
+ return;
+ }
+ this.nextChunk = this.str.getBytes(chunkSize);
+ const hasMoreData = this.nextChunk?.length > 0;
+ const decrypt = this.decrypt;
+ chunk = decrypt(chunk, !hasMoreData);
+ const bufferLength = this.bufferLength,
+ newLength = bufferLength + chunk.length,
+ buffer = this.ensureBuffer(newLength);
+ buffer.set(chunk, bufferLength);
+ this.bufferLength = newLength;
+ }
+}
+
+;// CONCATENATED MODULE: ./src/core/crypto.js
+
+
+
+class ARCFourCipher {
+ constructor(key) {
+ this.a = 0;
+ this.b = 0;
+ const s = new Uint8Array(256);
+ const keyLength = key.length;
+ for (let i = 0; i < 256; ++i) {
+ s[i] = i;
+ }
+ for (let i = 0, j = 0; i < 256; ++i) {
+ const tmp = s[i];
+ j = j + tmp + key[i % keyLength] & 0xff;
+ s[i] = s[j];
+ s[j] = tmp;
+ }
+ this.s = s;
+ }
+ encryptBlock(data) {
+ let a = this.a,
+ b = this.b;
+ const s = this.s;
+ const n = data.length;
+ const output = new Uint8Array(n);
+ for (let i = 0; i < n; ++i) {
+ a = a + 1 & 0xff;
+ const tmp = s[a];
+ b = b + tmp & 0xff;
+ const tmp2 = s[b];
+ s[a] = tmp2;
+ s[b] = tmp;
+ output[i] = data[i] ^ s[tmp + tmp2 & 0xff];
+ }
+ this.a = a;
+ this.b = b;
+ return output;
+ }
+ decryptBlock(data) {
+ return this.encryptBlock(data);
+ }
+ encrypt(data) {
+ return this.encryptBlock(data);
+ }
+}
+const calculateMD5 = function calculateMD5Closure() {
+ const r = new Uint8Array([7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21]);
+ const k = new Int32Array([-680876936, -389564586, 606105819, -1044525330, -176418897, 1200080426, -1473231341, -45705983, 1770035416, -1958414417, -42063, -1990404162, 1804603682, -40341101, -1502002290, 1236535329, -165796510, -1069501632, 643717713, -373897302, -701558691, 38016083, -660478335, -405537848, 568446438, -1019803690, -187363961, 1163531501, -1444681467, -51403784, 1735328473, -1926607734, -378558, -2022574463, 1839030562, -35309556, -1530992060, 1272893353, -155497632, -1094730640, 681279174, -358537222, -722521979, 76029189, -640364487, -421815835, 530742520, -995338651, -198630844, 1126891415, -1416354905, -57434055, 1700485571, -1894986606, -1051523, -2054922799, 1873313359, -30611744, -1560198380, 1309151649, -145523070, -1120210379, 718787259, -343485551]);
+ function hash(data, offset, length) {
+ let h0 = 1732584193,
+ h1 = -271733879,
+ h2 = -1732584194,
+ h3 = 271733878;
+ const paddedLength = length + 72 & ~63;
+ const padded = new Uint8Array(paddedLength);
+ let i, j;
+ for (i = 0; i < length; ++i) {
+ padded[i] = data[offset++];
+ }
+ padded[i++] = 0x80;
+ const n = paddedLength - 8;
+ while (i < n) {
+ padded[i++] = 0;
+ }
+ padded[i++] = length << 3 & 0xff;
+ padded[i++] = length >> 5 & 0xff;
+ padded[i++] = length >> 13 & 0xff;
+ padded[i++] = length >> 21 & 0xff;
+ padded[i++] = length >>> 29 & 0xff;
+ padded[i++] = 0;
+ padded[i++] = 0;
+ padded[i++] = 0;
+ const w = new Int32Array(16);
+ for (i = 0; i < paddedLength;) {
+ for (j = 0; j < 16; ++j, i += 4) {
+ w[j] = padded[i] | padded[i + 1] << 8 | padded[i + 2] << 16 | padded[i + 3] << 24;
+ }
+ let a = h0,
+ b = h1,
+ c = h2,
+ d = h3,
+ f,
+ g;
+ for (j = 0; j < 64; ++j) {
+ if (j < 16) {
+ f = b & c | ~b & d;
+ g = j;
+ } else if (j < 32) {
+ f = d & b | ~d & c;
+ g = 5 * j + 1 & 15;
+ } else if (j < 48) {
+ f = b ^ c ^ d;
+ g = 3 * j + 5 & 15;
+ } else {
+ f = c ^ (b | ~d);
+ g = 7 * j & 15;
+ }
+ const tmp = d,
+ rotateArg = a + f + k[j] + w[g] | 0,
+ rotate = r[j];
+ d = c;
+ c = b;
+ b = b + (rotateArg << rotate | rotateArg >>> 32 - rotate) | 0;
+ a = tmp;
+ }
+ h0 = h0 + a | 0;
+ h1 = h1 + b | 0;
+ h2 = h2 + c | 0;
+ h3 = h3 + d | 0;
+ }
+ return new Uint8Array([h0 & 0xFF, h0 >> 8 & 0xFF, h0 >> 16 & 0xFF, h0 >>> 24 & 0xFF, h1 & 0xFF, h1 >> 8 & 0xFF, h1 >> 16 & 0xFF, h1 >>> 24 & 0xFF, h2 & 0xFF, h2 >> 8 & 0xFF, h2 >> 16 & 0xFF, h2 >>> 24 & 0xFF, h3 & 0xFF, h3 >> 8 & 0xFF, h3 >> 16 & 0xFF, h3 >>> 24 & 0xFF]);
+ }
+ return hash;
+}();
+class Word64 {
+ constructor(highInteger, lowInteger) {
+ this.high = highInteger | 0;
+ this.low = lowInteger | 0;
+ }
+ and(word) {
+ this.high &= word.high;
+ this.low &= word.low;
+ }
+ xor(word) {
+ this.high ^= word.high;
+ this.low ^= word.low;
+ }
+ or(word) {
+ this.high |= word.high;
+ this.low |= word.low;
+ }
+ shiftRight(places) {
+ if (places >= 32) {
+ this.low = this.high >>> places - 32 | 0;
+ this.high = 0;
+ } else {
+ this.low = this.low >>> places | this.high << 32 - places;
+ this.high = this.high >>> places | 0;
+ }
+ }
+ shiftLeft(places) {
+ if (places >= 32) {
+ this.high = this.low << places - 32;
+ this.low = 0;
+ } else {
+ this.high = this.high << places | this.low >>> 32 - places;
+ this.low <<= places;
+ }
+ }
+ rotateRight(places) {
+ let low, high;
+ if (places & 32) {
+ high = this.low;
+ low = this.high;
+ } else {
+ low = this.low;
+ high = this.high;
+ }
+ places &= 31;
+ this.low = low >>> places | high << 32 - places;
+ this.high = high >>> places | low << 32 - places;
+ }
+ not() {
+ this.high = ~this.high;
+ this.low = ~this.low;
+ }
+ add(word) {
+ const lowAdd = (this.low >>> 0) + (word.low >>> 0);
+ let highAdd = (this.high >>> 0) + (word.high >>> 0);
+ if (lowAdd > 0xffffffff) {
+ highAdd += 1;
+ }
+ this.low = lowAdd | 0;
+ this.high = highAdd | 0;
+ }
+ copyTo(bytes, offset) {
+ bytes[offset] = this.high >>> 24 & 0xff;
+ bytes[offset + 1] = this.high >> 16 & 0xff;
+ bytes[offset + 2] = this.high >> 8 & 0xff;
+ bytes[offset + 3] = this.high & 0xff;
+ bytes[offset + 4] = this.low >>> 24 & 0xff;
+ bytes[offset + 5] = this.low >> 16 & 0xff;
+ bytes[offset + 6] = this.low >> 8 & 0xff;
+ bytes[offset + 7] = this.low & 0xff;
+ }
+ assign(word) {
+ this.high = word.high;
+ this.low = word.low;
+ }
+}
+const calculateSHA256 = function calculateSHA256Closure() {
+ function rotr(x, n) {
+ return x >>> n | x << 32 - n;
+ }
+ function ch(x, y, z) {
+ return x & y ^ ~x & z;
+ }
+ function maj(x, y, z) {
+ return x & y ^ x & z ^ y & z;
+ }
+ function sigma(x) {
+ return rotr(x, 2) ^ rotr(x, 13) ^ rotr(x, 22);
+ }
+ function sigmaPrime(x) {
+ return rotr(x, 6) ^ rotr(x, 11) ^ rotr(x, 25);
+ }
+ function littleSigma(x) {
+ return rotr(x, 7) ^ rotr(x, 18) ^ x >>> 3;
+ }
+ function littleSigmaPrime(x) {
+ return rotr(x, 17) ^ rotr(x, 19) ^ x >>> 10;
+ }
+ const k = [0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2];
+ function hash(data, offset, length) {
+ let h0 = 0x6a09e667,
+ h1 = 0xbb67ae85,
+ h2 = 0x3c6ef372,
+ h3 = 0xa54ff53a,
+ h4 = 0x510e527f,
+ h5 = 0x9b05688c,
+ h6 = 0x1f83d9ab,
+ h7 = 0x5be0cd19;
+ const paddedLength = Math.ceil((length + 9) / 64) * 64;
+ const padded = new Uint8Array(paddedLength);
+ let i, j;
+ for (i = 0; i < length; ++i) {
+ padded[i] = data[offset++];
+ }
+ padded[i++] = 0x80;
+ const n = paddedLength - 8;
+ while (i < n) {
+ padded[i++] = 0;
+ }
+ padded[i++] = 0;
+ padded[i++] = 0;
+ padded[i++] = 0;
+ padded[i++] = length >>> 29 & 0xff;
+ padded[i++] = length >> 21 & 0xff;
+ padded[i++] = length >> 13 & 0xff;
+ padded[i++] = length >> 5 & 0xff;
+ padded[i++] = length << 3 & 0xff;
+ const w = new Uint32Array(64);
+ for (i = 0; i < paddedLength;) {
+ for (j = 0; j < 16; ++j) {
+ w[j] = padded[i] << 24 | padded[i + 1] << 16 | padded[i + 2] << 8 | padded[i + 3];
+ i += 4;
+ }
+ for (j = 16; j < 64; ++j) {
+ w[j] = littleSigmaPrime(w[j - 2]) + w[j - 7] + littleSigma(w[j - 15]) + w[j - 16] | 0;
+ }
+ let a = h0,
+ b = h1,
+ c = h2,
+ d = h3,
+ e = h4,
+ f = h5,
+ g = h6,
+ h = h7,
+ t1,
+ t2;
+ for (j = 0; j < 64; ++j) {
+ t1 = h + sigmaPrime(e) + ch(e, f, g) + k[j] + w[j];
+ t2 = sigma(a) + maj(a, b, c);
+ h = g;
+ g = f;
+ f = e;
+ e = d + t1 | 0;
+ d = c;
+ c = b;
+ b = a;
+ a = t1 + t2 | 0;
+ }
+ h0 = h0 + a | 0;
+ h1 = h1 + b | 0;
+ h2 = h2 + c | 0;
+ h3 = h3 + d | 0;
+ h4 = h4 + e | 0;
+ h5 = h5 + f | 0;
+ h6 = h6 + g | 0;
+ h7 = h7 + h | 0;
+ }
+ return new Uint8Array([h0 >> 24 & 0xFF, h0 >> 16 & 0xFF, h0 >> 8 & 0xFF, h0 & 0xFF, h1 >> 24 & 0xFF, h1 >> 16 & 0xFF, h1 >> 8 & 0xFF, h1 & 0xFF, h2 >> 24 & 0xFF, h2 >> 16 & 0xFF, h2 >> 8 & 0xFF, h2 & 0xFF, h3 >> 24 & 0xFF, h3 >> 16 & 0xFF, h3 >> 8 & 0xFF, h3 & 0xFF, h4 >> 24 & 0xFF, h4 >> 16 & 0xFF, h4 >> 8 & 0xFF, h4 & 0xFF, h5 >> 24 & 0xFF, h5 >> 16 & 0xFF, h5 >> 8 & 0xFF, h5 & 0xFF, h6 >> 24 & 0xFF, h6 >> 16 & 0xFF, h6 >> 8 & 0xFF, h6 & 0xFF, h7 >> 24 & 0xFF, h7 >> 16 & 0xFF, h7 >> 8 & 0xFF, h7 & 0xFF]);
+ }
+ return hash;
+}();
+const calculateSHA512 = function calculateSHA512Closure() {
+ function ch(result, x, y, z, tmp) {
+ result.assign(x);
+ result.and(y);
+ tmp.assign(x);
+ tmp.not();
+ tmp.and(z);
+ result.xor(tmp);
+ }
+ function maj(result, x, y, z, tmp) {
+ result.assign(x);
+ result.and(y);
+ tmp.assign(x);
+ tmp.and(z);
+ result.xor(tmp);
+ tmp.assign(y);
+ tmp.and(z);
+ result.xor(tmp);
+ }
+ function sigma(result, x, tmp) {
+ result.assign(x);
+ result.rotateRight(28);
+ tmp.assign(x);
+ tmp.rotateRight(34);
+ result.xor(tmp);
+ tmp.assign(x);
+ tmp.rotateRight(39);
+ result.xor(tmp);
+ }
+ function sigmaPrime(result, x, tmp) {
+ result.assign(x);
+ result.rotateRight(14);
+ tmp.assign(x);
+ tmp.rotateRight(18);
+ result.xor(tmp);
+ tmp.assign(x);
+ tmp.rotateRight(41);
+ result.xor(tmp);
+ }
+ function littleSigma(result, x, tmp) {
+ result.assign(x);
+ result.rotateRight(1);
+ tmp.assign(x);
+ tmp.rotateRight(8);
+ result.xor(tmp);
+ tmp.assign(x);
+ tmp.shiftRight(7);
+ result.xor(tmp);
+ }
+ function littleSigmaPrime(result, x, tmp) {
+ result.assign(x);
+ result.rotateRight(19);
+ tmp.assign(x);
+ tmp.rotateRight(61);
+ result.xor(tmp);
+ tmp.assign(x);
+ tmp.shiftRight(6);
+ result.xor(tmp);
+ }
+ const k = [new Word64(0x428a2f98, 0xd728ae22), new Word64(0x71374491, 0x23ef65cd), new Word64(0xb5c0fbcf, 0xec4d3b2f), new Word64(0xe9b5dba5, 0x8189dbbc), new Word64(0x3956c25b, 0xf348b538), new Word64(0x59f111f1, 0xb605d019), new Word64(0x923f82a4, 0xaf194f9b), new Word64(0xab1c5ed5, 0xda6d8118), new Word64(0xd807aa98, 0xa3030242), new Word64(0x12835b01, 0x45706fbe), new Word64(0x243185be, 0x4ee4b28c), new Word64(0x550c7dc3, 0xd5ffb4e2), new Word64(0x72be5d74, 0xf27b896f), new Word64(0x80deb1fe, 0x3b1696b1), new Word64(0x9bdc06a7, 0x25c71235), new Word64(0xc19bf174, 0xcf692694), new Word64(0xe49b69c1, 0x9ef14ad2), new Word64(0xefbe4786, 0x384f25e3), new Word64(0x0fc19dc6, 0x8b8cd5b5), new Word64(0x240ca1cc, 0x77ac9c65), new Word64(0x2de92c6f, 0x592b0275), new Word64(0x4a7484aa, 0x6ea6e483), new Word64(0x5cb0a9dc, 0xbd41fbd4), new Word64(0x76f988da, 0x831153b5), new Word64(0x983e5152, 0xee66dfab), new Word64(0xa831c66d, 0x2db43210), new Word64(0xb00327c8, 0x98fb213f), new Word64(0xbf597fc7, 0xbeef0ee4), new Word64(0xc6e00bf3, 0x3da88fc2), new Word64(0xd5a79147, 0x930aa725), new Word64(0x06ca6351, 0xe003826f), new Word64(0x14292967, 0x0a0e6e70), new Word64(0x27b70a85, 0x46d22ffc), new Word64(0x2e1b2138, 0x5c26c926), new Word64(0x4d2c6dfc, 0x5ac42aed), new Word64(0x53380d13, 0x9d95b3df), new Word64(0x650a7354, 0x8baf63de), new Word64(0x766a0abb, 0x3c77b2a8), new Word64(0x81c2c92e, 0x47edaee6), new Word64(0x92722c85, 0x1482353b), new Word64(0xa2bfe8a1, 0x4cf10364), new Word64(0xa81a664b, 0xbc423001), new Word64(0xc24b8b70, 0xd0f89791), new Word64(0xc76c51a3, 0x0654be30), new Word64(0xd192e819, 0xd6ef5218), new Word64(0xd6990624, 0x5565a910), new Word64(0xf40e3585, 0x5771202a), new Word64(0x106aa070, 0x32bbd1b8), new Word64(0x19a4c116, 0xb8d2d0c8), new Word64(0x1e376c08, 0x5141ab53), new Word64(0x2748774c, 0xdf8eeb99), new Word64(0x34b0bcb5, 0xe19b48a8), new Word64(0x391c0cb3, 0xc5c95a63), new Word64(0x4ed8aa4a, 0xe3418acb), new Word64(0x5b9cca4f, 0x7763e373), new Word64(0x682e6ff3, 0xd6b2b8a3), new Word64(0x748f82ee, 0x5defb2fc), new Word64(0x78a5636f, 0x43172f60), new Word64(0x84c87814, 0xa1f0ab72), new Word64(0x8cc70208, 0x1a6439ec), new Word64(0x90befffa, 0x23631e28), new Word64(0xa4506ceb, 0xde82bde9), new Word64(0xbef9a3f7, 0xb2c67915), new Word64(0xc67178f2, 0xe372532b), new Word64(0xca273ece, 0xea26619c), new Word64(0xd186b8c7, 0x21c0c207), new Word64(0xeada7dd6, 0xcde0eb1e), new Word64(0xf57d4f7f, 0xee6ed178), new Word64(0x06f067aa, 0x72176fba), new Word64(0x0a637dc5, 0xa2c898a6), new Word64(0x113f9804, 0xbef90dae), new Word64(0x1b710b35, 0x131c471b), new Word64(0x28db77f5, 0x23047d84), new Word64(0x32caab7b, 0x40c72493), new Word64(0x3c9ebe0a, 0x15c9bebc), new Word64(0x431d67c4, 0x9c100d4c), new Word64(0x4cc5d4be, 0xcb3e42b6), new Word64(0x597f299c, 0xfc657e2a), new Word64(0x5fcb6fab, 0x3ad6faec), new Word64(0x6c44198c, 0x4a475817)];
+ function hash(data, offset, length, mode384 = false) {
+ let h0, h1, h2, h3, h4, h5, h6, h7;
+ if (!mode384) {
+ h0 = new Word64(0x6a09e667, 0xf3bcc908);
+ h1 = new Word64(0xbb67ae85, 0x84caa73b);
+ h2 = new Word64(0x3c6ef372, 0xfe94f82b);
+ h3 = new Word64(0xa54ff53a, 0x5f1d36f1);
+ h4 = new Word64(0x510e527f, 0xade682d1);
+ h5 = new Word64(0x9b05688c, 0x2b3e6c1f);
+ h6 = new Word64(0x1f83d9ab, 0xfb41bd6b);
+ h7 = new Word64(0x5be0cd19, 0x137e2179);
+ } else {
+ h0 = new Word64(0xcbbb9d5d, 0xc1059ed8);
+ h1 = new Word64(0x629a292a, 0x367cd507);
+ h2 = new Word64(0x9159015a, 0x3070dd17);
+ h3 = new Word64(0x152fecd8, 0xf70e5939);
+ h4 = new Word64(0x67332667, 0xffc00b31);
+ h5 = new Word64(0x8eb44a87, 0x68581511);
+ h6 = new Word64(0xdb0c2e0d, 0x64f98fa7);
+ h7 = new Word64(0x47b5481d, 0xbefa4fa4);
+ }
+ const paddedLength = Math.ceil((length + 17) / 128) * 128;
+ const padded = new Uint8Array(paddedLength);
+ let i, j;
+ for (i = 0; i < length; ++i) {
+ padded[i] = data[offset++];
+ }
+ padded[i++] = 0x80;
+ const n = paddedLength - 16;
+ while (i < n) {
+ padded[i++] = 0;
+ }
+ padded[i++] = 0;
+ padded[i++] = 0;
+ padded[i++] = 0;
+ padded[i++] = 0;
+ padded[i++] = 0;
+ padded[i++] = 0;
+ padded[i++] = 0;
+ padded[i++] = 0;
+ padded[i++] = 0;
+ padded[i++] = 0;
+ padded[i++] = 0;
+ padded[i++] = length >>> 29 & 0xff;
+ padded[i++] = length >> 21 & 0xff;
+ padded[i++] = length >> 13 & 0xff;
+ padded[i++] = length >> 5 & 0xff;
+ padded[i++] = length << 3 & 0xff;
+ const w = new Array(80);
+ for (i = 0; i < 80; i++) {
+ w[i] = new Word64(0, 0);
+ }
+ let a = new Word64(0, 0),
+ b = new Word64(0, 0),
+ c = new Word64(0, 0);
+ let d = new Word64(0, 0),
+ e = new Word64(0, 0),
+ f = new Word64(0, 0);
+ let g = new Word64(0, 0),
+ h = new Word64(0, 0);
+ const t1 = new Word64(0, 0),
+ t2 = new Word64(0, 0);
+ const tmp1 = new Word64(0, 0),
+ tmp2 = new Word64(0, 0);
+ let tmp3;
+ for (i = 0; i < paddedLength;) {
+ for (j = 0; j < 16; ++j) {
+ w[j].high = padded[i] << 24 | padded[i + 1] << 16 | padded[i + 2] << 8 | padded[i + 3];
+ w[j].low = padded[i + 4] << 24 | padded[i + 5] << 16 | padded[i + 6] << 8 | padded[i + 7];
+ i += 8;
+ }
+ for (j = 16; j < 80; ++j) {
+ tmp3 = w[j];
+ littleSigmaPrime(tmp3, w[j - 2], tmp2);
+ tmp3.add(w[j - 7]);
+ littleSigma(tmp1, w[j - 15], tmp2);
+ tmp3.add(tmp1);
+ tmp3.add(w[j - 16]);
+ }
+ a.assign(h0);
+ b.assign(h1);
+ c.assign(h2);
+ d.assign(h3);
+ e.assign(h4);
+ f.assign(h5);
+ g.assign(h6);
+ h.assign(h7);
+ for (j = 0; j < 80; ++j) {
+ t1.assign(h);
+ sigmaPrime(tmp1, e, tmp2);
+ t1.add(tmp1);
+ ch(tmp1, e, f, g, tmp2);
+ t1.add(tmp1);
+ t1.add(k[j]);
+ t1.add(w[j]);
+ sigma(t2, a, tmp2);
+ maj(tmp1, a, b, c, tmp2);
+ t2.add(tmp1);
+ tmp3 = h;
+ h = g;
+ g = f;
+ f = e;
+ d.add(t1);
+ e = d;
+ d = c;
+ c = b;
+ b = a;
+ tmp3.assign(t1);
+ tmp3.add(t2);
+ a = tmp3;
+ }
+ h0.add(a);
+ h1.add(b);
+ h2.add(c);
+ h3.add(d);
+ h4.add(e);
+ h5.add(f);
+ h6.add(g);
+ h7.add(h);
+ }
+ let result;
+ if (!mode384) {
+ result = new Uint8Array(64);
+ h0.copyTo(result, 0);
+ h1.copyTo(result, 8);
+ h2.copyTo(result, 16);
+ h3.copyTo(result, 24);
+ h4.copyTo(result, 32);
+ h5.copyTo(result, 40);
+ h6.copyTo(result, 48);
+ h7.copyTo(result, 56);
+ } else {
+ result = new Uint8Array(48);
+ h0.copyTo(result, 0);
+ h1.copyTo(result, 8);
+ h2.copyTo(result, 16);
+ h3.copyTo(result, 24);
+ h4.copyTo(result, 32);
+ h5.copyTo(result, 40);
+ }
+ return result;
+ }
+ return hash;
+}();
+function calculateSHA384(data, offset, length) {
+ return calculateSHA512(data, offset, length, true);
+}
+class NullCipher {
+ decryptBlock(data) {
+ return data;
+ }
+ encrypt(data) {
+ return data;
+ }
+}
+class AESBaseCipher {
+ constructor() {
+ if (this.constructor === AESBaseCipher) {
+ unreachable("Cannot initialize AESBaseCipher.");
+ }
+ this._s = new Uint8Array([0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16]);
+ this._inv_s = new Uint8Array([0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d]);
+ this._mix = new Uint32Array([0x00000000, 0x0e090d0b, 0x1c121a16, 0x121b171d, 0x3824342c, 0x362d3927, 0x24362e3a, 0x2a3f2331, 0x70486858, 0x7e416553, 0x6c5a724e, 0x62537f45, 0x486c5c74, 0x4665517f, 0x547e4662, 0x5a774b69, 0xe090d0b0, 0xee99ddbb, 0xfc82caa6, 0xf28bc7ad, 0xd8b4e49c, 0xd6bde997, 0xc4a6fe8a, 0xcaaff381, 0x90d8b8e8, 0x9ed1b5e3, 0x8ccaa2fe, 0x82c3aff5, 0xa8fc8cc4, 0xa6f581cf, 0xb4ee96d2, 0xbae79bd9, 0xdb3bbb7b, 0xd532b670, 0xc729a16d, 0xc920ac66, 0xe31f8f57, 0xed16825c, 0xff0d9541, 0xf104984a, 0xab73d323, 0xa57ade28, 0xb761c935, 0xb968c43e, 0x9357e70f, 0x9d5eea04, 0x8f45fd19, 0x814cf012, 0x3bab6bcb, 0x35a266c0, 0x27b971dd, 0x29b07cd6, 0x038f5fe7, 0x0d8652ec, 0x1f9d45f1, 0x119448fa, 0x4be30393, 0x45ea0e98, 0x57f11985, 0x59f8148e, 0x73c737bf, 0x7dce3ab4, 0x6fd52da9, 0x61dc20a2, 0xad766df6, 0xa37f60fd, 0xb16477e0, 0xbf6d7aeb, 0x955259da, 0x9b5b54d1, 0x894043cc, 0x87494ec7, 0xdd3e05ae, 0xd33708a5, 0xc12c1fb8, 0xcf2512b3, 0xe51a3182, 0xeb133c89, 0xf9082b94, 0xf701269f, 0x4de6bd46, 0x43efb04d, 0x51f4a750, 0x5ffdaa5b, 0x75c2896a, 0x7bcb8461, 0x69d0937c, 0x67d99e77, 0x3daed51e, 0x33a7d815, 0x21bccf08, 0x2fb5c203, 0x058ae132, 0x0b83ec39, 0x1998fb24, 0x1791f62f, 0x764dd68d, 0x7844db86, 0x6a5fcc9b, 0x6456c190, 0x4e69e2a1, 0x4060efaa, 0x527bf8b7, 0x5c72f5bc, 0x0605bed5, 0x080cb3de, 0x1a17a4c3, 0x141ea9c8, 0x3e218af9, 0x302887f2, 0x223390ef, 0x2c3a9de4, 0x96dd063d, 0x98d40b36, 0x8acf1c2b, 0x84c61120, 0xaef93211, 0xa0f03f1a, 0xb2eb2807, 0xbce2250c, 0xe6956e65, 0xe89c636e, 0xfa877473, 0xf48e7978, 0xdeb15a49, 0xd0b85742, 0xc2a3405f, 0xccaa4d54, 0x41ecdaf7, 0x4fe5d7fc, 0x5dfec0e1, 0x53f7cdea, 0x79c8eedb, 0x77c1e3d0, 0x65daf4cd, 0x6bd3f9c6, 0x31a4b2af, 0x3fadbfa4, 0x2db6a8b9, 0x23bfa5b2, 0x09808683, 0x07898b88, 0x15929c95, 0x1b9b919e, 0xa17c0a47, 0xaf75074c, 0xbd6e1051, 0xb3671d5a, 0x99583e6b, 0x97513360, 0x854a247d, 0x8b432976, 0xd134621f, 0xdf3d6f14, 0xcd267809, 0xc32f7502, 0xe9105633, 0xe7195b38, 0xf5024c25, 0xfb0b412e, 0x9ad7618c, 0x94de6c87, 0x86c57b9a, 0x88cc7691, 0xa2f355a0, 0xacfa58ab, 0xbee14fb6, 0xb0e842bd, 0xea9f09d4, 0xe49604df, 0xf68d13c2, 0xf8841ec9, 0xd2bb3df8, 0xdcb230f3, 0xcea927ee, 0xc0a02ae5, 0x7a47b13c, 0x744ebc37, 0x6655ab2a, 0x685ca621, 0x42638510, 0x4c6a881b, 0x5e719f06, 0x5078920d, 0x0a0fd964, 0x0406d46f, 0x161dc372, 0x1814ce79, 0x322bed48, 0x3c22e043, 0x2e39f75e, 0x2030fa55, 0xec9ab701, 0xe293ba0a, 0xf088ad17, 0xfe81a01c, 0xd4be832d, 0xdab78e26, 0xc8ac993b, 0xc6a59430, 0x9cd2df59, 0x92dbd252, 0x80c0c54f, 0x8ec9c844, 0xa4f6eb75, 0xaaffe67e, 0xb8e4f163, 0xb6edfc68, 0x0c0a67b1, 0x02036aba, 0x10187da7, 0x1e1170ac, 0x342e539d, 0x3a275e96, 0x283c498b, 0x26354480, 0x7c420fe9, 0x724b02e2, 0x605015ff, 0x6e5918f4, 0x44663bc5, 0x4a6f36ce, 0x587421d3, 0x567d2cd8, 0x37a10c7a, 0x39a80171, 0x2bb3166c, 0x25ba1b67, 0x0f853856, 0x018c355d, 0x13972240, 0x1d9e2f4b, 0x47e96422, 0x49e06929, 0x5bfb7e34, 0x55f2733f, 0x7fcd500e, 0x71c45d05, 0x63df4a18, 0x6dd64713, 0xd731dcca, 0xd938d1c1, 0xcb23c6dc, 0xc52acbd7, 0xef15e8e6, 0xe11ce5ed, 0xf307f2f0, 0xfd0efffb, 0xa779b492, 0xa970b999, 0xbb6bae84, 0xb562a38f, 0x9f5d80be, 0x91548db5, 0x834f9aa8, 0x8d4697a3]);
+ this._mixCol = new Uint8Array(256);
+ for (let i = 0; i < 256; i++) {
+ this._mixCol[i] = i < 128 ? i << 1 : i << 1 ^ 0x1b;
+ }
+ this.buffer = new Uint8Array(16);
+ this.bufferPosition = 0;
+ }
+ _expandKey(cipherKey) {
+ unreachable("Cannot call `_expandKey` on the base class");
+ }
+ _decrypt(input, key) {
+ let t, u, v;
+ const state = new Uint8Array(16);
+ state.set(input);
+ for (let j = 0, k = this._keySize; j < 16; ++j, ++k) {
+ state[j] ^= key[k];
+ }
+ for (let i = this._cyclesOfRepetition - 1; i >= 1; --i) {
+ t = state[13];
+ state[13] = state[9];
+ state[9] = state[5];
+ state[5] = state[1];
+ state[1] = t;
+ t = state[14];
+ u = state[10];
+ state[14] = state[6];
+ state[10] = state[2];
+ state[6] = t;
+ state[2] = u;
+ t = state[15];
+ u = state[11];
+ v = state[7];
+ state[15] = state[3];
+ state[11] = t;
+ state[7] = u;
+ state[3] = v;
+ for (let j = 0; j < 16; ++j) {
+ state[j] = this._inv_s[state[j]];
+ }
+ for (let j = 0, k = i * 16; j < 16; ++j, ++k) {
+ state[j] ^= key[k];
+ }
+ for (let j = 0; j < 16; j += 4) {
+ const s0 = this._mix[state[j]];
+ const s1 = this._mix[state[j + 1]];
+ const s2 = this._mix[state[j + 2]];
+ const s3 = this._mix[state[j + 3]];
+ t = s0 ^ s1 >>> 8 ^ s1 << 24 ^ s2 >>> 16 ^ s2 << 16 ^ s3 >>> 24 ^ s3 << 8;
+ state[j] = t >>> 24 & 0xff;
+ state[j + 1] = t >> 16 & 0xff;
+ state[j + 2] = t >> 8 & 0xff;
+ state[j + 3] = t & 0xff;
+ }
+ }
+ t = state[13];
+ state[13] = state[9];
+ state[9] = state[5];
+ state[5] = state[1];
+ state[1] = t;
+ t = state[14];
+ u = state[10];
+ state[14] = state[6];
+ state[10] = state[2];
+ state[6] = t;
+ state[2] = u;
+ t = state[15];
+ u = state[11];
+ v = state[7];
+ state[15] = state[3];
+ state[11] = t;
+ state[7] = u;
+ state[3] = v;
+ for (let j = 0; j < 16; ++j) {
+ state[j] = this._inv_s[state[j]];
+ state[j] ^= key[j];
+ }
+ return state;
+ }
+ _encrypt(input, key) {
+ const s = this._s;
+ let t, u, v;
+ const state = new Uint8Array(16);
+ state.set(input);
+ for (let j = 0; j < 16; ++j) {
+ state[j] ^= key[j];
+ }
+ for (let i = 1; i < this._cyclesOfRepetition; i++) {
+ for (let j = 0; j < 16; ++j) {
+ state[j] = s[state[j]];
+ }
+ v = state[1];
+ state[1] = state[5];
+ state[5] = state[9];
+ state[9] = state[13];
+ state[13] = v;
+ v = state[2];
+ u = state[6];
+ state[2] = state[10];
+ state[6] = state[14];
+ state[10] = v;
+ state[14] = u;
+ v = state[3];
+ u = state[7];
+ t = state[11];
+ state[3] = state[15];
+ state[7] = v;
+ state[11] = u;
+ state[15] = t;
+ for (let j = 0; j < 16; j += 4) {
+ const s0 = state[j + 0];
+ const s1 = state[j + 1];
+ const s2 = state[j + 2];
+ const s3 = state[j + 3];
+ t = s0 ^ s1 ^ s2 ^ s3;
+ state[j + 0] ^= t ^ this._mixCol[s0 ^ s1];
+ state[j + 1] ^= t ^ this._mixCol[s1 ^ s2];
+ state[j + 2] ^= t ^ this._mixCol[s2 ^ s3];
+ state[j + 3] ^= t ^ this._mixCol[s3 ^ s0];
+ }
+ for (let j = 0, k = i * 16; j < 16; ++j, ++k) {
+ state[j] ^= key[k];
+ }
+ }
+ for (let j = 0; j < 16; ++j) {
+ state[j] = s[state[j]];
+ }
+ v = state[1];
+ state[1] = state[5];
+ state[5] = state[9];
+ state[9] = state[13];
+ state[13] = v;
+ v = state[2];
+ u = state[6];
+ state[2] = state[10];
+ state[6] = state[14];
+ state[10] = v;
+ state[14] = u;
+ v = state[3];
+ u = state[7];
+ t = state[11];
+ state[3] = state[15];
+ state[7] = v;
+ state[11] = u;
+ state[15] = t;
+ for (let j = 0, k = this._keySize; j < 16; ++j, ++k) {
+ state[j] ^= key[k];
+ }
+ return state;
+ }
+ _decryptBlock2(data, finalize) {
+ const sourceLength = data.length;
+ let buffer = this.buffer,
+ bufferLength = this.bufferPosition;
+ const result = [];
+ let iv = this.iv;
+ for (let i = 0; i < sourceLength; ++i) {
+ buffer[bufferLength] = data[i];
+ ++bufferLength;
+ if (bufferLength < 16) {
+ continue;
+ }
+ const plain = this._decrypt(buffer, this._key);
+ for (let j = 0; j < 16; ++j) {
+ plain[j] ^= iv[j];
+ }
+ iv = buffer;
+ result.push(plain);
+ buffer = new Uint8Array(16);
+ bufferLength = 0;
+ }
+ this.buffer = buffer;
+ this.bufferLength = bufferLength;
+ this.iv = iv;
+ if (result.length === 0) {
+ return new Uint8Array(0);
+ }
+ let outputLength = 16 * result.length;
+ if (finalize) {
+ const lastBlock = result.at(-1);
+ let psLen = lastBlock[15];
+ if (psLen <= 16) {
+ for (let i = 15, ii = 16 - psLen; i >= ii; --i) {
+ if (lastBlock[i] !== psLen) {
+ psLen = 0;
+ break;
+ }
+ }
+ outputLength -= psLen;
+ result[result.length - 1] = lastBlock.subarray(0, 16 - psLen);
+ }
+ }
+ const output = new Uint8Array(outputLength);
+ for (let i = 0, j = 0, ii = result.length; i < ii; ++i, j += 16) {
+ output.set(result[i], j);
+ }
+ return output;
+ }
+ decryptBlock(data, finalize, iv = null) {
+ const sourceLength = data.length;
+ const buffer = this.buffer;
+ let bufferLength = this.bufferPosition;
+ if (iv) {
+ this.iv = iv;
+ } else {
+ for (let i = 0; bufferLength < 16 && i < sourceLength; ++i, ++bufferLength) {
+ buffer[bufferLength] = data[i];
+ }
+ if (bufferLength < 16) {
+ this.bufferLength = bufferLength;
+ return new Uint8Array(0);
+ }
+ this.iv = buffer;
+ data = data.subarray(16);
+ }
+ this.buffer = new Uint8Array(16);
+ this.bufferLength = 0;
+ this.decryptBlock = this._decryptBlock2;
+ return this.decryptBlock(data, finalize);
+ }
+ encrypt(data, iv) {
+ const sourceLength = data.length;
+ let buffer = this.buffer,
+ bufferLength = this.bufferPosition;
+ const result = [];
+ if (!iv) {
+ iv = new Uint8Array(16);
+ }
+ for (let i = 0; i < sourceLength; ++i) {
+ buffer[bufferLength] = data[i];
+ ++bufferLength;
+ if (bufferLength < 16) {
+ continue;
+ }
+ for (let j = 0; j < 16; ++j) {
+ buffer[j] ^= iv[j];
+ }
+ const cipher = this._encrypt(buffer, this._key);
+ iv = cipher;
+ result.push(cipher);
+ buffer = new Uint8Array(16);
+ bufferLength = 0;
+ }
+ this.buffer = buffer;
+ this.bufferLength = bufferLength;
+ this.iv = iv;
+ if (result.length === 0) {
+ return new Uint8Array(0);
+ }
+ const outputLength = 16 * result.length;
+ const output = new Uint8Array(outputLength);
+ for (let i = 0, j = 0, ii = result.length; i < ii; ++i, j += 16) {
+ output.set(result[i], j);
+ }
+ return output;
+ }
+}
+class AES128Cipher extends AESBaseCipher {
+ constructor(key) {
+ super();
+ this._cyclesOfRepetition = 10;
+ this._keySize = 160;
+ this._rcon = new Uint8Array([0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d]);
+ this._key = this._expandKey(key);
+ }
+ _expandKey(cipherKey) {
+ const b = 176;
+ const s = this._s;
+ const rcon = this._rcon;
+ const result = new Uint8Array(b);
+ result.set(cipherKey);
+ for (let j = 16, i = 1; j < b; ++i) {
+ let t1 = result[j - 3];
+ let t2 = result[j - 2];
+ let t3 = result[j - 1];
+ let t4 = result[j - 4];
+ t1 = s[t1];
+ t2 = s[t2];
+ t3 = s[t3];
+ t4 = s[t4];
+ t1 ^= rcon[i];
+ for (let n = 0; n < 4; ++n) {
+ result[j] = t1 ^= result[j - 16];
+ j++;
+ result[j] = t2 ^= result[j - 16];
+ j++;
+ result[j] = t3 ^= result[j - 16];
+ j++;
+ result[j] = t4 ^= result[j - 16];
+ j++;
+ }
+ }
+ return result;
+ }
+}
+class AES256Cipher extends AESBaseCipher {
+ constructor(key) {
+ super();
+ this._cyclesOfRepetition = 14;
+ this._keySize = 224;
+ this._key = this._expandKey(key);
+ }
+ _expandKey(cipherKey) {
+ const b = 240;
+ const s = this._s;
+ const result = new Uint8Array(b);
+ result.set(cipherKey);
+ let r = 1;
+ let t1, t2, t3, t4;
+ for (let j = 32, i = 1; j < b; ++i) {
+ if (j % 32 === 16) {
+ t1 = s[t1];
+ t2 = s[t2];
+ t3 = s[t3];
+ t4 = s[t4];
+ } else if (j % 32 === 0) {
+ t1 = result[j - 3];
+ t2 = result[j - 2];
+ t3 = result[j - 1];
+ t4 = result[j - 4];
+ t1 = s[t1];
+ t2 = s[t2];
+ t3 = s[t3];
+ t4 = s[t4];
+ t1 ^= r;
+ if ((r <<= 1) >= 256) {
+ r = (r ^ 0x1b) & 0xff;
+ }
+ }
+ for (let n = 0; n < 4; ++n) {
+ result[j] = t1 ^= result[j - 32];
+ j++;
+ result[j] = t2 ^= result[j - 32];
+ j++;
+ result[j] = t3 ^= result[j - 32];
+ j++;
+ result[j] = t4 ^= result[j - 32];
+ j++;
+ }
+ }
+ return result;
+ }
+}
+class PDF17 {
+ checkOwnerPassword(password, ownerValidationSalt, userBytes, ownerPassword) {
+ const hashData = new Uint8Array(password.length + 56);
+ hashData.set(password, 0);
+ hashData.set(ownerValidationSalt, password.length);
+ hashData.set(userBytes, password.length + ownerValidationSalt.length);
+ const result = calculateSHA256(hashData, 0, hashData.length);
+ return isArrayEqual(result, ownerPassword);
+ }
+ checkUserPassword(password, userValidationSalt, userPassword) {
+ const hashData = new Uint8Array(password.length + 8);
+ hashData.set(password, 0);
+ hashData.set(userValidationSalt, password.length);
+ const result = calculateSHA256(hashData, 0, hashData.length);
+ return isArrayEqual(result, userPassword);
+ }
+ getOwnerKey(password, ownerKeySalt, userBytes, ownerEncryption) {
+ const hashData = new Uint8Array(password.length + 56);
+ hashData.set(password, 0);
+ hashData.set(ownerKeySalt, password.length);
+ hashData.set(userBytes, password.length + ownerKeySalt.length);
+ const key = calculateSHA256(hashData, 0, hashData.length);
+ const cipher = new AES256Cipher(key);
+ return cipher.decryptBlock(ownerEncryption, false, new Uint8Array(16));
+ }
+ getUserKey(password, userKeySalt, userEncryption) {
+ const hashData = new Uint8Array(password.length + 8);
+ hashData.set(password, 0);
+ hashData.set(userKeySalt, password.length);
+ const key = calculateSHA256(hashData, 0, hashData.length);
+ const cipher = new AES256Cipher(key);
+ return cipher.decryptBlock(userEncryption, false, new Uint8Array(16));
+ }
+}
+class PDF20 {
+ _hash(password, input, userBytes) {
+ let k = calculateSHA256(input, 0, input.length).subarray(0, 32);
+ let e = [0];
+ let i = 0;
+ while (i < 64 || e.at(-1) > i - 32) {
+ const combinedLength = password.length + k.length + userBytes.length,
+ combinedArray = new Uint8Array(combinedLength);
+ let writeOffset = 0;
+ combinedArray.set(password, writeOffset);
+ writeOffset += password.length;
+ combinedArray.set(k, writeOffset);
+ writeOffset += k.length;
+ combinedArray.set(userBytes, writeOffset);
+ const k1 = new Uint8Array(combinedLength * 64);
+ for (let j = 0, pos = 0; j < 64; j++, pos += combinedLength) {
+ k1.set(combinedArray, pos);
+ }
+ const cipher = new AES128Cipher(k.subarray(0, 16));
+ e = cipher.encrypt(k1, k.subarray(16, 32));
+ const remainder = e.slice(0, 16).reduce((a, b) => a + b, 0) % 3;
+ if (remainder === 0) {
+ k = calculateSHA256(e, 0, e.length);
+ } else if (remainder === 1) {
+ k = calculateSHA384(e, 0, e.length);
+ } else if (remainder === 2) {
+ k = calculateSHA512(e, 0, e.length);
+ }
+ i++;
+ }
+ return k.subarray(0, 32);
+ }
+ checkOwnerPassword(password, ownerValidationSalt, userBytes, ownerPassword) {
+ const hashData = new Uint8Array(password.length + 56);
+ hashData.set(password, 0);
+ hashData.set(ownerValidationSalt, password.length);
+ hashData.set(userBytes, password.length + ownerValidationSalt.length);
+ const result = this._hash(password, hashData, userBytes);
+ return isArrayEqual(result, ownerPassword);
+ }
+ checkUserPassword(password, userValidationSalt, userPassword) {
+ const hashData = new Uint8Array(password.length + 8);
+ hashData.set(password, 0);
+ hashData.set(userValidationSalt, password.length);
+ const result = this._hash(password, hashData, []);
+ return isArrayEqual(result, userPassword);
+ }
+ getOwnerKey(password, ownerKeySalt, userBytes, ownerEncryption) {
+ const hashData = new Uint8Array(password.length + 56);
+ hashData.set(password, 0);
+ hashData.set(ownerKeySalt, password.length);
+ hashData.set(userBytes, password.length + ownerKeySalt.length);
+ const key = this._hash(password, hashData, userBytes);
+ const cipher = new AES256Cipher(key);
+ return cipher.decryptBlock(ownerEncryption, false, new Uint8Array(16));
+ }
+ getUserKey(password, userKeySalt, userEncryption) {
+ const hashData = new Uint8Array(password.length + 8);
+ hashData.set(password, 0);
+ hashData.set(userKeySalt, password.length);
+ const key = this._hash(password, hashData, []);
+ const cipher = new AES256Cipher(key);
+ return cipher.decryptBlock(userEncryption, false, new Uint8Array(16));
+ }
+}
+class CipherTransform {
+ constructor(stringCipherConstructor, streamCipherConstructor) {
+ this.StringCipherConstructor = stringCipherConstructor;
+ this.StreamCipherConstructor = streamCipherConstructor;
+ }
+ createStream(stream, length) {
+ const cipher = new this.StreamCipherConstructor();
+ return new DecryptStream(stream, length, function cipherTransformDecryptStream(data, finalize) {
+ return cipher.decryptBlock(data, finalize);
+ });
+ }
+ decryptString(s) {
+ const cipher = new this.StringCipherConstructor();
+ let data = stringToBytes(s);
+ data = cipher.decryptBlock(data, true);
+ return bytesToString(data);
+ }
+ encryptString(s) {
+ const cipher = new this.StringCipherConstructor();
+ if (cipher instanceof AESBaseCipher) {
+ const strLen = s.length;
+ const pad = 16 - strLen % 16;
+ s += String.fromCharCode(pad).repeat(pad);
+ const iv = new Uint8Array(16);
+ if (typeof crypto !== "undefined") {
+ crypto.getRandomValues(iv);
+ } else {
+ for (let i = 0; i < 16; i++) {
+ iv[i] = Math.floor(256 * Math.random());
+ }
+ }
+ let data = stringToBytes(s);
+ data = cipher.encrypt(data, iv);
+ const buf = new Uint8Array(16 + data.length);
+ buf.set(iv);
+ buf.set(data, 16);
+ return bytesToString(buf);
+ }
+ let data = stringToBytes(s);
+ data = cipher.encrypt(data);
+ return bytesToString(data);
+ }
+}
+class CipherTransformFactory {
+ static #defaultPasswordBytes = new Uint8Array([0x28, 0xbf, 0x4e, 0x5e, 0x4e, 0x75, 0x8a, 0x41, 0x64, 0x00, 0x4e, 0x56, 0xff, 0xfa, 0x01, 0x08, 0x2e, 0x2e, 0x00, 0xb6, 0xd0, 0x68, 0x3e, 0x80, 0x2f, 0x0c, 0xa9, 0xfe, 0x64, 0x53, 0x69, 0x7a]);
+ #createEncryptionKey20(revision, password, ownerPassword, ownerValidationSalt, ownerKeySalt, uBytes, userPassword, userValidationSalt, userKeySalt, ownerEncryption, userEncryption, perms) {
+ if (password) {
+ const passwordLength = Math.min(127, password.length);
+ password = password.subarray(0, passwordLength);
+ } else {
+ password = [];
+ }
+ const pdfAlgorithm = revision === 6 ? new PDF20() : new PDF17();
+ if (pdfAlgorithm.checkUserPassword(password, userValidationSalt, userPassword)) {
+ return pdfAlgorithm.getUserKey(password, userKeySalt, userEncryption);
+ } else if (password.length && pdfAlgorithm.checkOwnerPassword(password, ownerValidationSalt, uBytes, ownerPassword)) {
+ return pdfAlgorithm.getOwnerKey(password, ownerKeySalt, uBytes, ownerEncryption);
+ }
+ return null;
+ }
+ #prepareKeyData(fileId, password, ownerPassword, userPassword, flags, revision, keyLength, encryptMetadata) {
+ const hashDataSize = 40 + ownerPassword.length + fileId.length;
+ const hashData = new Uint8Array(hashDataSize);
+ let i = 0,
+ j,
+ n;
+ if (password) {
+ n = Math.min(32, password.length);
+ for (; i < n; ++i) {
+ hashData[i] = password[i];
+ }
+ }
+ j = 0;
+ while (i < 32) {
+ hashData[i++] = CipherTransformFactory.#defaultPasswordBytes[j++];
+ }
+ for (j = 0, n = ownerPassword.length; j < n; ++j) {
+ hashData[i++] = ownerPassword[j];
+ }
+ hashData[i++] = flags & 0xff;
+ hashData[i++] = flags >> 8 & 0xff;
+ hashData[i++] = flags >> 16 & 0xff;
+ hashData[i++] = flags >>> 24 & 0xff;
+ for (j = 0, n = fileId.length; j < n; ++j) {
+ hashData[i++] = fileId[j];
+ }
+ if (revision >= 4 && !encryptMetadata) {
+ hashData[i++] = 0xff;
+ hashData[i++] = 0xff;
+ hashData[i++] = 0xff;
+ hashData[i++] = 0xff;
+ }
+ let hash = calculateMD5(hashData, 0, i);
+ const keyLengthInBytes = keyLength >> 3;
+ if (revision >= 3) {
+ for (j = 0; j < 50; ++j) {
+ hash = calculateMD5(hash, 0, keyLengthInBytes);
+ }
+ }
+ const encryptionKey = hash.subarray(0, keyLengthInBytes);
+ let cipher, checkData;
+ if (revision >= 3) {
+ for (i = 0; i < 32; ++i) {
+ hashData[i] = CipherTransformFactory.#defaultPasswordBytes[i];
+ }
+ for (j = 0, n = fileId.length; j < n; ++j) {
+ hashData[i++] = fileId[j];
+ }
+ cipher = new ARCFourCipher(encryptionKey);
+ checkData = cipher.encryptBlock(calculateMD5(hashData, 0, i));
+ n = encryptionKey.length;
+ const derivedKey = new Uint8Array(n);
+ for (j = 1; j <= 19; ++j) {
+ for (let k = 0; k < n; ++k) {
+ derivedKey[k] = encryptionKey[k] ^ j;
+ }
+ cipher = new ARCFourCipher(derivedKey);
+ checkData = cipher.encryptBlock(checkData);
+ }
+ for (j = 0, n = checkData.length; j < n; ++j) {
+ if (userPassword[j] !== checkData[j]) {
+ return null;
+ }
+ }
+ } else {
+ cipher = new ARCFourCipher(encryptionKey);
+ checkData = cipher.encryptBlock(CipherTransformFactory.#defaultPasswordBytes);
+ for (j = 0, n = checkData.length; j < n; ++j) {
+ if (userPassword[j] !== checkData[j]) {
+ return null;
+ }
+ }
+ }
+ return encryptionKey;
+ }
+ #decodeUserPassword(password, ownerPassword, revision, keyLength) {
+ const hashData = new Uint8Array(32);
+ let i = 0;
+ const n = Math.min(32, password.length);
+ for (; i < n; ++i) {
+ hashData[i] = password[i];
+ }
+ let j = 0;
+ while (i < 32) {
+ hashData[i++] = CipherTransformFactory.#defaultPasswordBytes[j++];
+ }
+ let hash = calculateMD5(hashData, 0, i);
+ const keyLengthInBytes = keyLength >> 3;
+ if (revision >= 3) {
+ for (j = 0; j < 50; ++j) {
+ hash = calculateMD5(hash, 0, hash.length);
+ }
+ }
+ let cipher, userPassword;
+ if (revision >= 3) {
+ userPassword = ownerPassword;
+ const derivedKey = new Uint8Array(keyLengthInBytes);
+ for (j = 19; j >= 0; j--) {
+ for (let k = 0; k < keyLengthInBytes; ++k) {
+ derivedKey[k] = hash[k] ^ j;
+ }
+ cipher = new ARCFourCipher(derivedKey);
+ userPassword = cipher.encryptBlock(userPassword);
+ }
+ } else {
+ cipher = new ARCFourCipher(hash.subarray(0, keyLengthInBytes));
+ userPassword = cipher.encryptBlock(ownerPassword);
+ }
+ return userPassword;
+ }
+ #buildObjectKey(num, gen, encryptionKey, isAes = false) {
+ const key = new Uint8Array(encryptionKey.length + 9);
+ const n = encryptionKey.length;
+ let i;
+ for (i = 0; i < n; ++i) {
+ key[i] = encryptionKey[i];
+ }
+ key[i++] = num & 0xff;
+ key[i++] = num >> 8 & 0xff;
+ key[i++] = num >> 16 & 0xff;
+ key[i++] = gen & 0xff;
+ key[i++] = gen >> 8 & 0xff;
+ if (isAes) {
+ key[i++] = 0x73;
+ key[i++] = 0x41;
+ key[i++] = 0x6c;
+ key[i++] = 0x54;
+ }
+ const hash = calculateMD5(key, 0, i);
+ return hash.subarray(0, Math.min(encryptionKey.length + 5, 16));
+ }
+ #buildCipherConstructor(cf, name, num, gen, key) {
+ if (!(name instanceof Name)) {
+ throw new FormatError("Invalid crypt filter name.");
+ }
+ const self = this;
+ const cryptFilter = cf.get(name.name);
+ const cfm = cryptFilter?.get("CFM");
+ if (!cfm || cfm.name === "None") {
+ return function () {
+ return new NullCipher();
+ };
+ }
+ if (cfm.name === "V2") {
+ return function () {
+ return new ARCFourCipher(self.#buildObjectKey(num, gen, key, false));
+ };
+ }
+ if (cfm.name === "AESV2") {
+ return function () {
+ return new AES128Cipher(self.#buildObjectKey(num, gen, key, true));
+ };
+ }
+ if (cfm.name === "AESV3") {
+ return function () {
+ return new AES256Cipher(key);
+ };
+ }
+ throw new FormatError("Unknown crypto method");
+ }
+ constructor(dict, fileId, password) {
+ const filter = dict.get("Filter");
+ if (!isName(filter, "Standard")) {
+ throw new FormatError("unknown encryption method");
+ }
+ this.filterName = filter.name;
+ this.dict = dict;
+ const algorithm = dict.get("V");
+ if (!Number.isInteger(algorithm) || algorithm !== 1 && algorithm !== 2 && algorithm !== 4 && algorithm !== 5) {
+ throw new FormatError("unsupported encryption algorithm");
+ }
+ this.algorithm = algorithm;
+ let keyLength = dict.get("Length");
+ if (!keyLength) {
+ if (algorithm <= 3) {
+ keyLength = 40;
+ } else {
+ const cfDict = dict.get("CF");
+ const streamCryptoName = dict.get("StmF");
+ if (cfDict instanceof Dict && streamCryptoName instanceof Name) {
+ cfDict.suppressEncryption = true;
+ const handlerDict = cfDict.get(streamCryptoName.name);
+ keyLength = handlerDict?.get("Length") || 128;
+ if (keyLength < 40) {
+ keyLength <<= 3;
+ }
+ }
+ }
+ }
+ if (!Number.isInteger(keyLength) || keyLength < 40 || keyLength % 8 !== 0) {
+ throw new FormatError("invalid key length");
+ }
+ const ownerBytes = stringToBytes(dict.get("O")),
+ userBytes = stringToBytes(dict.get("U"));
+ const ownerPassword = ownerBytes.subarray(0, 32);
+ const userPassword = userBytes.subarray(0, 32);
+ const flags = dict.get("P");
+ const revision = dict.get("R");
+ const encryptMetadata = (algorithm === 4 || algorithm === 5) && dict.get("EncryptMetadata") !== false;
+ this.encryptMetadata = encryptMetadata;
+ const fileIdBytes = stringToBytes(fileId);
+ let passwordBytes;
+ if (password) {
+ if (revision === 6) {
+ try {
+ password = utf8StringToString(password);
+ } catch {
+ warn("CipherTransformFactory: Unable to convert UTF8 encoded password.");
+ }
+ }
+ passwordBytes = stringToBytes(password);
+ }
+ let encryptionKey;
+ if (algorithm !== 5) {
+ encryptionKey = this.#prepareKeyData(fileIdBytes, passwordBytes, ownerPassword, userPassword, flags, revision, keyLength, encryptMetadata);
+ } else {
+ const ownerValidationSalt = ownerBytes.subarray(32, 40);
+ const ownerKeySalt = ownerBytes.subarray(40, 48);
+ const uBytes = userBytes.subarray(0, 48);
+ const userValidationSalt = userBytes.subarray(32, 40);
+ const userKeySalt = userBytes.subarray(40, 48);
+ const ownerEncryption = stringToBytes(dict.get("OE"));
+ const userEncryption = stringToBytes(dict.get("UE"));
+ const perms = stringToBytes(dict.get("Perms"));
+ encryptionKey = this.#createEncryptionKey20(revision, passwordBytes, ownerPassword, ownerValidationSalt, ownerKeySalt, uBytes, userPassword, userValidationSalt, userKeySalt, ownerEncryption, userEncryption, perms);
+ }
+ if (!encryptionKey && !password) {
+ throw new PasswordException("No password given", PasswordResponses.NEED_PASSWORD);
+ } else if (!encryptionKey && password) {
+ const decodedPassword = this.#decodeUserPassword(passwordBytes, ownerPassword, revision, keyLength);
+ encryptionKey = this.#prepareKeyData(fileIdBytes, decodedPassword, ownerPassword, userPassword, flags, revision, keyLength, encryptMetadata);
+ }
+ if (!encryptionKey) {
+ throw new PasswordException("Incorrect Password", PasswordResponses.INCORRECT_PASSWORD);
+ }
+ this.encryptionKey = encryptionKey;
+ if (algorithm >= 4) {
+ const cf = dict.get("CF");
+ if (cf instanceof Dict) {
+ cf.suppressEncryption = true;
+ }
+ this.cf = cf;
+ this.stmf = dict.get("StmF") || Name.get("Identity");
+ this.strf = dict.get("StrF") || Name.get("Identity");
+ this.eff = dict.get("EFF") || this.stmf;
+ }
+ }
+ createCipherTransform(num, gen) {
+ if (this.algorithm === 4 || this.algorithm === 5) {
+ return new CipherTransform(this.#buildCipherConstructor(this.cf, this.strf, num, gen, this.encryptionKey), this.#buildCipherConstructor(this.cf, this.stmf, num, gen, this.encryptionKey));
+ }
+ const key = this.#buildObjectKey(num, gen, this.encryptionKey, false);
+ const cipherConstructor = function () {
+ return new ARCFourCipher(key);
+ };
+ return new CipherTransform(cipherConstructor, cipherConstructor);
+ }
+}
+
+;// CONCATENATED MODULE: ./src/core/writer.js
+
+
+
+
+
+
+
+async function writeObject(ref, obj, buffer, {
+ encrypt = null
+}) {
+ const transform = encrypt?.createCipherTransform(ref.num, ref.gen);
+ buffer.push(`${ref.num} ${ref.gen} obj\n`);
+ if (obj instanceof Dict) {
+ await writeDict(obj, buffer, transform);
+ } else if (obj instanceof BaseStream) {
+ await writeStream(obj, buffer, transform);
+ } else if (Array.isArray(obj) || ArrayBuffer.isView(obj)) {
+ await writeArray(obj, buffer, transform);
+ }
+ buffer.push("\nendobj\n");
+}
+async function writeDict(dict, buffer, transform) {
+ buffer.push("<<");
+ for (const key of dict.getKeys()) {
+ buffer.push(` /${escapePDFName(key)} `);
+ await writeValue(dict.getRaw(key), buffer, transform);
+ }
+ buffer.push(">>");
+}
+async function writeStream(stream, buffer, transform) {
+ let bytes = stream.getBytes();
+ const {
+ dict
+ } = stream;
+ const [filter, params] = await Promise.all([dict.getAsync("Filter"), dict.getAsync("DecodeParms")]);
+ const filterZero = Array.isArray(filter) ? await dict.xref.fetchIfRefAsync(filter[0]) : filter;
+ const isFilterZeroFlateDecode = isName(filterZero, "FlateDecode");
+ const MIN_LENGTH_FOR_COMPRESSING = 256;
+ if (typeof CompressionStream !== "undefined" && (bytes.length >= MIN_LENGTH_FOR_COMPRESSING || isFilterZeroFlateDecode)) {
+ try {
+ const cs = new CompressionStream("deflate");
+ const writer = cs.writable.getWriter();
+ writer.write(bytes);
+ writer.close();
+ const buf = await new Response(cs.readable).arrayBuffer();
+ bytes = new Uint8Array(buf);
+ let newFilter, newParams;
+ if (!filter) {
+ newFilter = Name.get("FlateDecode");
+ } else if (!isFilterZeroFlateDecode) {
+ newFilter = Array.isArray(filter) ? [Name.get("FlateDecode"), ...filter] : [Name.get("FlateDecode"), filter];
+ if (params) {
+ newParams = Array.isArray(params) ? [null, ...params] : [null, params];
+ }
+ }
+ if (newFilter) {
+ dict.set("Filter", newFilter);
+ }
+ if (newParams) {
+ dict.set("DecodeParms", newParams);
+ }
+ } catch (ex) {
+ info(`writeStream - cannot compress data: "${ex}".`);
+ }
+ }
+ let string = bytesToString(bytes);
+ if (transform) {
+ string = transform.encryptString(string);
+ }
+ dict.set("Length", string.length);
+ await writeDict(dict, buffer, transform);
+ buffer.push(" stream\n", string, "\nendstream");
+}
+async function writeArray(array, buffer, transform) {
+ buffer.push("[");
+ let first = true;
+ for (const val of array) {
+ if (!first) {
+ buffer.push(" ");
+ } else {
+ first = false;
+ }
+ await writeValue(val, buffer, transform);
+ }
+ buffer.push("]");
+}
+async function writeValue(value, buffer, transform) {
+ if (value instanceof Name) {
+ buffer.push(`/${escapePDFName(value.name)}`);
+ } else if (value instanceof Ref) {
+ buffer.push(`${value.num} ${value.gen} R`);
+ } else if (Array.isArray(value) || ArrayBuffer.isView(value)) {
+ await writeArray(value, buffer, transform);
+ } else if (typeof value === "string") {
+ if (transform) {
+ value = transform.encryptString(value);
+ }
+ buffer.push(`(${escapeString(value)})`);
+ } else if (typeof value === "number") {
+ buffer.push(numberToString(value));
+ } else if (typeof value === "boolean") {
+ buffer.push(value.toString());
+ } else if (value instanceof Dict) {
+ await writeDict(value, buffer, transform);
+ } else if (value instanceof BaseStream) {
+ await writeStream(value, buffer, transform);
+ } else if (value === null) {
+ buffer.push("null");
+ } else {
+ warn(`Unhandled value in writer: ${typeof value}, please file a bug.`);
+ }
+}
+function writeInt(number, size, offset, buffer) {
+ for (let i = size + offset - 1; i > offset - 1; i--) {
+ buffer[i] = number & 0xff;
+ number >>= 8;
+ }
+ return offset + size;
+}
+function writeString(string, offset, buffer) {
+ for (let i = 0, len = string.length; i < len; i++) {
+ buffer[offset + i] = string.charCodeAt(i) & 0xff;
+ }
+}
+function computeMD5(filesize, xrefInfo) {
+ const time = Math.floor(Date.now() / 1000);
+ const filename = xrefInfo.filename || "";
+ const md5Buffer = [time.toString(), filename, filesize.toString()];
+ let md5BufferLen = md5Buffer.reduce((a, str) => a + str.length, 0);
+ for (const value of Object.values(xrefInfo.info)) {
+ md5Buffer.push(value);
+ md5BufferLen += value.length;
+ }
+ const array = new Uint8Array(md5BufferLen);
+ let offset = 0;
+ for (const str of md5Buffer) {
+ writeString(str, offset, array);
+ offset += str.length;
+ }
+ return bytesToString(calculateMD5(array));
+}
+function writeXFADataForAcroform(str, newRefs) {
+ const xml = new SimpleXMLParser({
+ hasAttributes: true
+ }).parseFromString(str);
+ for (const {
+ xfa
+ } of newRefs) {
+ if (!xfa) {
+ continue;
+ }
+ const {
+ path,
+ value
+ } = xfa;
+ if (!path) {
+ continue;
+ }
+ const nodePath = parseXFAPath(path);
+ let node = xml.documentElement.searchNode(nodePath, 0);
+ if (!node && nodePath.length > 1) {
+ node = xml.documentElement.searchNode([nodePath.at(-1)], 0);
+ }
+ if (node) {
+ node.childNodes = Array.isArray(value) ? value.map(val => new SimpleDOMNode("value", val)) : [new SimpleDOMNode("#text", value)];
+ } else {
+ warn(`Node not found for path: ${path}`);
+ }
+ }
+ const buffer = [];
+ xml.documentElement.dump(buffer);
+ return buffer.join("");
+}
+async function updateAcroform({
+ xref,
+ acroForm,
+ acroFormRef,
+ hasXfa,
+ hasXfaDatasetsEntry,
+ xfaDatasetsRef,
+ needAppearances,
+ newRefs
+}) {
+ if (hasXfa && !hasXfaDatasetsEntry && !xfaDatasetsRef) {
+ warn("XFA - Cannot save it");
+ }
+ if (!needAppearances && (!hasXfa || !xfaDatasetsRef || hasXfaDatasetsEntry)) {
+ return;
+ }
+ const dict = acroForm.clone();
+ if (hasXfa && !hasXfaDatasetsEntry) {
+ const newXfa = acroForm.get("XFA").slice();
+ newXfa.splice(2, 0, "datasets");
+ newXfa.splice(3, 0, xfaDatasetsRef);
+ dict.set("XFA", newXfa);
+ }
+ if (needAppearances) {
+ dict.set("NeedAppearances", true);
+ }
+ const buffer = [];
+ await writeObject(acroFormRef, dict, buffer, xref);
+ newRefs.push({
+ ref: acroFormRef,
+ data: buffer.join("")
+ });
+}
+function updateXFA({
+ xfaData,
+ xfaDatasetsRef,
+ newRefs,
+ xref
+}) {
+ if (xfaData === null) {
+ const datasets = xref.fetchIfRef(xfaDatasetsRef);
+ xfaData = writeXFADataForAcroform(datasets.getString(), newRefs);
+ }
+ const encrypt = xref.encrypt;
+ if (encrypt) {
+ const transform = encrypt.createCipherTransform(xfaDatasetsRef.num, xfaDatasetsRef.gen);
+ xfaData = transform.encryptString(xfaData);
+ }
+ const data = `${xfaDatasetsRef.num} ${xfaDatasetsRef.gen} obj\n` + `<< /Type /EmbeddedFile /Length ${xfaData.length}>>\nstream\n` + xfaData + "\nendstream\nendobj\n";
+ newRefs.push({
+ ref: xfaDatasetsRef,
+ data
+ });
+}
+async function getXRefTable(xrefInfo, baseOffset, newRefs, newXref, buffer) {
+ buffer.push("xref\n");
+ const indexes = getIndexes(newRefs);
+ let indexesPosition = 0;
+ for (const {
+ ref,
+ data
+ } of newRefs) {
+ if (ref.num === indexes[indexesPosition]) {
+ buffer.push(`${indexes[indexesPosition]} ${indexes[indexesPosition + 1]}\n`);
+ indexesPosition += 2;
+ }
+ buffer.push(`${baseOffset.toString().padStart(10, "0")} ${Math.min(ref.gen, 0xffff).toString().padStart(5, "0")} n\r\n`);
+ baseOffset += data.length;
+ }
+ computeIDs(baseOffset, xrefInfo, newXref);
+ buffer.push("trailer\n");
+ await writeDict(newXref, buffer);
+ buffer.push("\nstartxref\n", baseOffset.toString(), "\n%%EOF\n");
+}
+function getIndexes(newRefs) {
+ const indexes = [];
+ for (const {
+ ref
+ } of newRefs) {
+ if (ref.num === indexes.at(-2) + indexes.at(-1)) {
+ indexes[indexes.length - 1] += 1;
+ } else {
+ indexes.push(ref.num, 1);
+ }
+ }
+ return indexes;
+}
+async function getXRefStreamTable(xrefInfo, baseOffset, newRefs, newXref, buffer) {
+ const xrefTableData = [];
+ let maxOffset = 0;
+ let maxGen = 0;
+ for (const {
+ ref,
+ data
+ } of newRefs) {
+ maxOffset = Math.max(maxOffset, baseOffset);
+ const gen = Math.min(ref.gen, 0xffff);
+ maxGen = Math.max(maxGen, gen);
+ xrefTableData.push([1, baseOffset, gen]);
+ baseOffset += data.length;
+ }
+ newXref.set("Index", getIndexes(newRefs));
+ const offsetSize = getSizeInBytes(maxOffset);
+ const maxGenSize = getSizeInBytes(maxGen);
+ const sizes = [1, offsetSize, maxGenSize];
+ newXref.set("W", sizes);
+ computeIDs(baseOffset, xrefInfo, newXref);
+ const structSize = sizes.reduce((a, x) => a + x, 0);
+ const data = new Uint8Array(structSize * xrefTableData.length);
+ const stream = new Stream(data);
+ stream.dict = newXref;
+ let offset = 0;
+ for (const [type, objOffset, gen] of xrefTableData) {
+ offset = writeInt(type, sizes[0], offset, data);
+ offset = writeInt(objOffset, sizes[1], offset, data);
+ offset = writeInt(gen, sizes[2], offset, data);
+ }
+ await writeObject(xrefInfo.newRef, stream, buffer, {});
+ buffer.push("startxref\n", baseOffset.toString(), "\n%%EOF\n");
+}
+function computeIDs(baseOffset, xrefInfo, newXref) {
+ if (Array.isArray(xrefInfo.fileIds) && xrefInfo.fileIds.length > 0) {
+ const md5 = computeMD5(baseOffset, xrefInfo);
+ newXref.set("ID", [xrefInfo.fileIds[0], md5]);
+ }
+}
+function getTrailerDict(xrefInfo, newRefs, useXrefStream) {
+ const newXref = new Dict(null);
+ newXref.set("Prev", xrefInfo.startXRef);
+ const refForXrefTable = xrefInfo.newRef;
+ if (useXrefStream) {
+ newRefs.push({
+ ref: refForXrefTable,
+ data: ""
+ });
+ newXref.set("Size", refForXrefTable.num + 1);
+ newXref.set("Type", Name.get("XRef"));
+ } else {
+ newXref.set("Size", refForXrefTable.num);
+ }
+ if (xrefInfo.rootRef !== null) {
+ newXref.set("Root", xrefInfo.rootRef);
+ }
+ if (xrefInfo.infoRef !== null) {
+ newXref.set("Info", xrefInfo.infoRef);
+ }
+ if (xrefInfo.encryptRef !== null) {
+ newXref.set("Encrypt", xrefInfo.encryptRef);
+ }
+ return newXref;
+}
+async function incrementalUpdate({
+ originalData,
+ xrefInfo,
+ newRefs,
+ xref = null,
+ hasXfa = false,
+ xfaDatasetsRef = null,
+ hasXfaDatasetsEntry = false,
+ needAppearances,
+ acroFormRef = null,
+ acroForm = null,
+ xfaData = null,
+ useXrefStream = false
+}) {
+ await updateAcroform({
+ xref,
+ acroForm,
+ acroFormRef,
+ hasXfa,
+ hasXfaDatasetsEntry,
+ xfaDatasetsRef,
+ needAppearances,
+ newRefs
+ });
+ if (hasXfa) {
+ updateXFA({
+ xfaData,
+ xfaDatasetsRef,
+ newRefs,
+ xref
+ });
+ }
+ let buffer, baseOffset;
+ const lastByte = originalData.at(-1);
+ if (lastByte === 0x0a || lastByte === 0x0d) {
+ buffer = [];
+ baseOffset = originalData.length;
+ } else {
+ buffer = ["\n"];
+ baseOffset = originalData.length + 1;
+ }
+ const newXref = getTrailerDict(xrefInfo, newRefs, useXrefStream);
+ newRefs = newRefs.sort((a, b) => a.ref.num - b.ref.num);
+ for (const {
+ data
+ } of newRefs) {
+ buffer.push(data);
+ }
+ await (useXrefStream ? getXRefStreamTable(xrefInfo, baseOffset, newRefs, newXref, buffer) : getXRefTable(xrefInfo, baseOffset, newRefs, newXref, buffer));
+ const totalLength = buffer.reduce((a, str) => a + str.length, originalData.length);
+ const array = new Uint8Array(totalLength);
+ array.set(originalData);
+ let offset = originalData.length;
+ for (const str of buffer) {
+ writeString(str, offset, array);
+ offset += str.length;
+ }
+ return array;
+}
+
+;// CONCATENATED MODULE: ./src/core/struct_tree.js
+
+
+
+
+const MAX_DEPTH = 40;
+const StructElementType = {
+ PAGE_CONTENT: 1,
+ STREAM_CONTENT: 2,
+ OBJECT: 3,
+ ANNOTATION: 4,
+ ELEMENT: 5
+};
+class StructTreeRoot {
+ constructor(rootDict, rootRef) {
+ this.dict = rootDict;
+ this.ref = rootRef instanceof Ref ? rootRef : null;
+ this.roleMap = new Map();
+ this.structParentIds = null;
+ }
+ init() {
+ this.readRoleMap();
+ }
+ #addIdToPage(pageRef, id, type) {
+ if (!(pageRef instanceof Ref) || id < 0) {
+ return;
+ }
+ this.structParentIds ||= new RefSetCache();
+ let ids = this.structParentIds.get(pageRef);
+ if (!ids) {
+ ids = [];
+ this.structParentIds.put(pageRef, ids);
+ }
+ ids.push([id, type]);
+ }
+ addAnnotationIdToPage(pageRef, id) {
+ this.#addIdToPage(pageRef, id, StructElementType.ANNOTATION);
+ }
+ readRoleMap() {
+ const roleMapDict = this.dict.get("RoleMap");
+ if (!(roleMapDict instanceof Dict)) {
+ return;
+ }
+ roleMapDict.forEach((key, value) => {
+ if (!(value instanceof Name)) {
+ return;
+ }
+ this.roleMap.set(key, value.name);
+ });
+ }
+ static async canCreateStructureTree({
+ catalogRef,
+ pdfManager,
+ newAnnotationsByPage
+ }) {
+ if (!(catalogRef instanceof Ref)) {
+ warn("Cannot save the struct tree: no catalog reference.");
+ return false;
+ }
+ let nextKey = 0;
+ let hasNothingToUpdate = true;
+ for (const [pageIndex, elements] of newAnnotationsByPage) {
+ const {
+ ref: pageRef
+ } = await pdfManager.getPage(pageIndex);
+ if (!(pageRef instanceof Ref)) {
+ warn(`Cannot save the struct tree: page ${pageIndex} has no ref.`);
+ hasNothingToUpdate = true;
+ break;
+ }
+ for (const element of elements) {
+ if (element.accessibilityData?.type) {
+ element.parentTreeId = nextKey++;
+ hasNothingToUpdate = false;
+ }
+ }
+ }
+ if (hasNothingToUpdate) {
+ for (const elements of newAnnotationsByPage.values()) {
+ for (const element of elements) {
+ delete element.parentTreeId;
+ }
+ }
+ return false;
+ }
+ return true;
+ }
+ static async createStructureTree({
+ newAnnotationsByPage,
+ xref,
+ catalogRef,
+ pdfManager,
+ newRefs
+ }) {
+ const root = pdfManager.catalog.cloneDict();
+ const structTreeRootRef = xref.getNewTemporaryRef();
+ root.set("StructTreeRoot", structTreeRootRef);
+ const buffer = [];
+ await writeObject(catalogRef, root, buffer, xref);
+ newRefs.push({
+ ref: catalogRef,
+ data: buffer.join("")
+ });
+ const structTreeRoot = new Dict(xref);
+ structTreeRoot.set("Type", Name.get("StructTreeRoot"));
+ const parentTreeRef = xref.getNewTemporaryRef();
+ structTreeRoot.set("ParentTree", parentTreeRef);
+ const kids = [];
+ structTreeRoot.set("K", kids);
+ const parentTree = new Dict(xref);
+ const nums = [];
+ parentTree.set("Nums", nums);
+ const nextKey = await this.#writeKids({
+ newAnnotationsByPage,
+ structTreeRootRef,
+ kids,
+ nums,
+ xref,
+ pdfManager,
+ newRefs,
+ buffer
+ });
+ structTreeRoot.set("ParentTreeNextKey", nextKey);
+ buffer.length = 0;
+ await writeObject(parentTreeRef, parentTree, buffer, xref);
+ newRefs.push({
+ ref: parentTreeRef,
+ data: buffer.join("")
+ });
+ buffer.length = 0;
+ await writeObject(structTreeRootRef, structTreeRoot, buffer, xref);
+ newRefs.push({
+ ref: structTreeRootRef,
+ data: buffer.join("")
+ });
+ }
+ async canUpdateStructTree({
+ pdfManager,
+ xref,
+ newAnnotationsByPage
+ }) {
+ if (!this.ref) {
+ warn("Cannot update the struct tree: no root reference.");
+ return false;
+ }
+ let nextKey = this.dict.get("ParentTreeNextKey");
+ if (!Number.isInteger(nextKey) || nextKey < 0) {
+ warn("Cannot update the struct tree: invalid next key.");
+ return false;
+ }
+ const parentTree = this.dict.get("ParentTree");
+ if (!(parentTree instanceof Dict)) {
+ warn("Cannot update the struct tree: ParentTree isn't a dict.");
+ return false;
+ }
+ const nums = parentTree.get("Nums");
+ if (!Array.isArray(nums)) {
+ warn("Cannot update the struct tree: nums isn't an array.");
+ return false;
+ }
+ const numberTree = new NumberTree(parentTree, xref);
+ for (const pageIndex of newAnnotationsByPage.keys()) {
+ const {
+ pageDict
+ } = await pdfManager.getPage(pageIndex);
+ if (!pageDict.has("StructParents")) {
+ continue;
+ }
+ const id = pageDict.get("StructParents");
+ if (!Number.isInteger(id) || !Array.isArray(numberTree.get(id))) {
+ warn(`Cannot save the struct tree: page ${pageIndex} has a wrong id.`);
+ return false;
+ }
+ }
+ let hasNothingToUpdate = true;
+ for (const [pageIndex, elements] of newAnnotationsByPage) {
+ const {
+ pageDict
+ } = await pdfManager.getPage(pageIndex);
+ StructTreeRoot.#collectParents({
+ elements,
+ xref: this.dict.xref,
+ pageDict,
+ numberTree
+ });
+ for (const element of elements) {
+ if (element.accessibilityData?.type) {
+ element.parentTreeId = nextKey++;
+ hasNothingToUpdate = false;
+ }
+ }
+ }
+ if (hasNothingToUpdate) {
+ for (const elements of newAnnotationsByPage.values()) {
+ for (const element of elements) {
+ delete element.parentTreeId;
+ delete element.structTreeParent;
+ }
+ }
+ return false;
+ }
+ return true;
+ }
+ async updateStructureTree({
+ newAnnotationsByPage,
+ pdfManager,
+ newRefs
+ }) {
+ const xref = this.dict.xref;
+ const structTreeRoot = this.dict.clone();
+ const structTreeRootRef = this.ref;
+ let parentTreeRef = structTreeRoot.getRaw("ParentTree");
+ let parentTree;
+ if (parentTreeRef instanceof Ref) {
+ parentTree = xref.fetch(parentTreeRef);
+ } else {
+ parentTree = parentTreeRef;
+ parentTreeRef = xref.getNewTemporaryRef();
+ structTreeRoot.set("ParentTree", parentTreeRef);
+ }
+ parentTree = parentTree.clone();
+ let nums = parentTree.getRaw("Nums");
+ let numsRef = null;
+ if (nums instanceof Ref) {
+ numsRef = nums;
+ nums = xref.fetch(numsRef);
+ }
+ nums = nums.slice();
+ if (!numsRef) {
+ parentTree.set("Nums", nums);
+ }
+ let kids = structTreeRoot.getRaw("K");
+ let kidsRef = null;
+ if (kids instanceof Ref) {
+ kidsRef = kids;
+ kids = xref.fetch(kidsRef);
+ } else {
+ kidsRef = xref.getNewTemporaryRef();
+ structTreeRoot.set("K", kidsRef);
+ }
+ kids = Array.isArray(kids) ? kids.slice() : [kids];
+ const buffer = [];
+ const newNextkey = await StructTreeRoot.#writeKids({
+ newAnnotationsByPage,
+ structTreeRootRef,
+ kids,
+ nums,
+ xref,
+ pdfManager,
+ newRefs,
+ buffer
+ });
+ structTreeRoot.set("ParentTreeNextKey", newNextkey);
+ buffer.length = 0;
+ await writeObject(kidsRef, kids, buffer, xref);
+ newRefs.push({
+ ref: kidsRef,
+ data: buffer.join("")
+ });
+ if (numsRef) {
+ buffer.length = 0;
+ await writeObject(numsRef, nums, buffer, xref);
+ newRefs.push({
+ ref: numsRef,
+ data: buffer.join("")
+ });
+ }
+ buffer.length = 0;
+ await writeObject(parentTreeRef, parentTree, buffer, xref);
+ newRefs.push({
+ ref: parentTreeRef,
+ data: buffer.join("")
+ });
+ buffer.length = 0;
+ await writeObject(structTreeRootRef, structTreeRoot, buffer, xref);
+ newRefs.push({
+ ref: structTreeRootRef,
+ data: buffer.join("")
+ });
+ }
+ static async #writeKids({
+ newAnnotationsByPage,
+ structTreeRootRef,
+ kids,
+ nums,
+ xref,
+ pdfManager,
+ newRefs,
+ buffer
+ }) {
+ const objr = Name.get("OBJR");
+ let nextKey = -Infinity;
+ for (const [pageIndex, elements] of newAnnotationsByPage) {
+ const {
+ ref: pageRef
+ } = await pdfManager.getPage(pageIndex);
+ const isPageRef = pageRef instanceof Ref;
+ for (const {
+ accessibilityData,
+ ref,
+ parentTreeId,
+ structTreeParent
+ } of elements) {
+ if (!accessibilityData?.type) {
+ continue;
+ }
+ const {
+ type,
+ title,
+ lang,
+ alt,
+ expanded,
+ actualText
+ } = accessibilityData;
+ nextKey = Math.max(nextKey, parentTreeId);
+ const tagRef = xref.getNewTemporaryRef();
+ const tagDict = new Dict(xref);
+ tagDict.set("S", Name.get(type));
+ if (title) {
+ tagDict.set("T", title);
+ }
+ if (lang) {
+ tagDict.set("Lang", lang);
+ }
+ if (alt) {
+ tagDict.set("Alt", alt);
+ }
+ if (expanded) {
+ tagDict.set("E", expanded);
+ }
+ if (actualText) {
+ tagDict.set("ActualText", actualText);
+ }
+ if (structTreeParent) {
+ await this.#updateParentTag({
+ structTreeParent,
+ tagDict,
+ newTagRef: tagRef,
+ fallbackRef: structTreeRootRef,
+ xref,
+ newRefs,
+ buffer
+ });
+ } else {
+ tagDict.set("P", structTreeRootRef);
+ }
+ const objDict = new Dict(xref);
+ tagDict.set("K", objDict);
+ objDict.set("Type", objr);
+ if (isPageRef) {
+ objDict.set("Pg", pageRef);
+ }
+ objDict.set("Obj", ref);
+ buffer.length = 0;
+ await writeObject(tagRef, tagDict, buffer, xref);
+ newRefs.push({
+ ref: tagRef,
+ data: buffer.join("")
+ });
+ nums.push(parentTreeId, tagRef);
+ kids.push(tagRef);
+ }
+ }
+ return nextKey + 1;
+ }
+ static #collectParents({
+ elements,
+ xref,
+ pageDict,
+ numberTree
+ }) {
+ const idToElement = new Map();
+ for (const element of elements) {
+ if (element.structTreeParentId) {
+ const id = parseInt(element.structTreeParentId.split("_mc")[1], 10);
+ idToElement.set(id, element);
+ }
+ }
+ const id = pageDict.get("StructParents");
+ if (!Number.isInteger(id)) {
+ return;
+ }
+ const parentArray = numberTree.get(id);
+ const updateElement = (kid, pageKid, kidRef) => {
+ const element = idToElement.get(kid);
+ if (element) {
+ const parentRef = pageKid.getRaw("P");
+ const parentDict = xref.fetchIfRef(parentRef);
+ if (parentRef instanceof Ref && parentDict instanceof Dict) {
+ element.structTreeParent = {
+ ref: kidRef,
+ dict: pageKid
+ };
+ }
+ return true;
+ }
+ return false;
+ };
+ for (const kidRef of parentArray) {
+ if (!(kidRef instanceof Ref)) {
+ continue;
+ }
+ const pageKid = xref.fetch(kidRef);
+ const k = pageKid.get("K");
+ if (Number.isInteger(k)) {
+ updateElement(k, pageKid, kidRef);
+ continue;
+ }
+ if (!Array.isArray(k)) {
+ continue;
+ }
+ for (let kid of k) {
+ kid = xref.fetchIfRef(kid);
+ if (Number.isInteger(kid) && updateElement(kid, pageKid, kidRef)) {
+ break;
+ }
+ }
+ }
+ }
+ static async #updateParentTag({
+ structTreeParent: {
+ ref,
+ dict
+ },
+ tagDict,
+ newTagRef,
+ fallbackRef,
+ xref,
+ newRefs,
+ buffer
+ }) {
+ const parentRef = dict.getRaw("P");
+ let parentDict = xref.fetchIfRef(parentRef);
+ tagDict.set("P", parentRef);
+ let saveParentDict = false;
+ let parentKids;
+ let parentKidsRef = parentDict.getRaw("K");
+ if (!(parentKidsRef instanceof Ref)) {
+ parentKids = parentKidsRef;
+ parentKidsRef = xref.getNewTemporaryRef();
+ parentDict = parentDict.clone();
+ parentDict.set("K", parentKidsRef);
+ saveParentDict = true;
+ } else {
+ parentKids = xref.fetch(parentKidsRef);
+ }
+ if (Array.isArray(parentKids)) {
+ const index = parentKids.indexOf(ref);
+ if (index >= 0) {
+ parentKids = parentKids.slice();
+ parentKids.splice(index + 1, 0, newTagRef);
+ } else {
+ warn("Cannot update the struct tree: parent kid not found.");
+ tagDict.set("P", fallbackRef);
+ return;
+ }
+ } else if (parentKids instanceof Dict) {
+ parentKids = [parentKidsRef, newTagRef];
+ parentKidsRef = xref.getNewTemporaryRef();
+ parentDict.set("K", parentKidsRef);
+ saveParentDict = true;
+ }
+ buffer.length = 0;
+ await writeObject(parentKidsRef, parentKids, buffer, xref);
+ newRefs.push({
+ ref: parentKidsRef,
+ data: buffer.join("")
+ });
+ if (!saveParentDict) {
+ return;
+ }
+ buffer.length = 0;
+ await writeObject(parentRef, parentDict, buffer, xref);
+ newRefs.push({
+ ref: parentRef,
+ data: buffer.join("")
+ });
+ }
+}
+class StructElementNode {
+ constructor(tree, dict) {
+ this.tree = tree;
+ this.dict = dict;
+ this.kids = [];
+ this.parseKids();
+ }
+ get role() {
+ const nameObj = this.dict.get("S");
+ const name = nameObj instanceof Name ? nameObj.name : "";
+ const {
+ root
+ } = this.tree;
+ if (root.roleMap.has(name)) {
+ return root.roleMap.get(name);
+ }
+ return name;
+ }
+ parseKids() {
+ let pageObjId = null;
+ const objRef = this.dict.getRaw("Pg");
+ if (objRef instanceof Ref) {
+ pageObjId = objRef.toString();
+ }
+ const kids = this.dict.get("K");
+ if (Array.isArray(kids)) {
+ for (const kid of kids) {
+ const element = this.parseKid(pageObjId, kid);
+ if (element) {
+ this.kids.push(element);
+ }
+ }
+ } else {
+ const element = this.parseKid(pageObjId, kids);
+ if (element) {
+ this.kids.push(element);
+ }
+ }
+ }
+ parseKid(pageObjId, kid) {
+ if (Number.isInteger(kid)) {
+ if (this.tree.pageDict.objId !== pageObjId) {
+ return null;
+ }
+ return new StructElement({
+ type: StructElementType.PAGE_CONTENT,
+ mcid: kid,
+ pageObjId
+ });
+ }
+ let kidDict = null;
+ if (kid instanceof Ref) {
+ kidDict = this.dict.xref.fetch(kid);
+ } else if (kid instanceof Dict) {
+ kidDict = kid;
+ }
+ if (!kidDict) {
+ return null;
+ }
+ const pageRef = kidDict.getRaw("Pg");
+ if (pageRef instanceof Ref) {
+ pageObjId = pageRef.toString();
+ }
+ const type = kidDict.get("Type") instanceof Name ? kidDict.get("Type").name : null;
+ if (type === "MCR") {
+ if (this.tree.pageDict.objId !== pageObjId) {
+ return null;
+ }
+ const kidRef = kidDict.getRaw("Stm");
+ return new StructElement({
+ type: StructElementType.STREAM_CONTENT,
+ refObjId: kidRef instanceof Ref ? kidRef.toString() : null,
+ pageObjId,
+ mcid: kidDict.get("MCID")
+ });
+ }
+ if (type === "OBJR") {
+ if (this.tree.pageDict.objId !== pageObjId) {
+ return null;
+ }
+ const kidRef = kidDict.getRaw("Obj");
+ return new StructElement({
+ type: StructElementType.OBJECT,
+ refObjId: kidRef instanceof Ref ? kidRef.toString() : null,
+ pageObjId
+ });
+ }
+ return new StructElement({
+ type: StructElementType.ELEMENT,
+ dict: kidDict
+ });
+ }
+}
+class StructElement {
+ constructor({
+ type,
+ dict = null,
+ mcid = null,
+ pageObjId = null,
+ refObjId = null
+ }) {
+ this.type = type;
+ this.dict = dict;
+ this.mcid = mcid;
+ this.pageObjId = pageObjId;
+ this.refObjId = refObjId;
+ this.parentNode = null;
+ }
+}
+class StructTreePage {
+ constructor(structTreeRoot, pageDict) {
+ this.root = structTreeRoot;
+ this.rootDict = structTreeRoot ? structTreeRoot.dict : null;
+ this.pageDict = pageDict;
+ this.nodes = [];
+ }
+ parse(pageRef) {
+ if (!this.root || !this.rootDict) {
+ return;
+ }
+ const parentTree = this.rootDict.get("ParentTree");
+ if (!parentTree) {
+ return;
+ }
+ const id = this.pageDict.get("StructParents");
+ const ids = pageRef instanceof Ref && this.root.structParentIds?.get(pageRef);
+ if (!Number.isInteger(id) && !ids) {
+ return;
+ }
+ const map = new Map();
+ const numberTree = new NumberTree(parentTree, this.rootDict.xref);
+ if (Number.isInteger(id)) {
+ const parentArray = numberTree.get(id);
+ if (Array.isArray(parentArray)) {
+ for (const ref of parentArray) {
+ if (ref instanceof Ref) {
+ this.addNode(this.rootDict.xref.fetch(ref), map);
+ }
+ }
+ }
+ }
+ if (!ids) {
+ return;
+ }
+ for (const [elemId, type] of ids) {
+ const obj = numberTree.get(elemId);
+ if (obj) {
+ const elem = this.addNode(this.rootDict.xref.fetchIfRef(obj), map);
+ if (elem?.kids?.length === 1 && elem.kids[0].type === StructElementType.OBJECT) {
+ elem.kids[0].type = type;
+ }
+ }
+ }
+ }
+ addNode(dict, map, level = 0) {
+ if (level > MAX_DEPTH) {
+ warn("StructTree MAX_DEPTH reached.");
+ return null;
+ }
+ if (map.has(dict)) {
+ return map.get(dict);
+ }
+ const element = new StructElementNode(this, dict);
+ map.set(dict, element);
+ const parent = dict.get("P");
+ if (!parent || isName(parent.get("Type"), "StructTreeRoot")) {
+ if (!this.addTopLevelNode(dict, element)) {
+ map.delete(dict);
+ }
+ return element;
+ }
+ const parentNode = this.addNode(parent, map, level + 1);
+ if (!parentNode) {
+ return element;
+ }
+ let save = false;
+ for (const kid of parentNode.kids) {
+ if (kid.type === StructElementType.ELEMENT && kid.dict === dict) {
+ kid.parentNode = element;
+ save = true;
+ }
+ }
+ if (!save) {
+ map.delete(dict);
+ }
+ return element;
+ }
+ addTopLevelNode(dict, element) {
+ const obj = this.rootDict.get("K");
+ if (!obj) {
+ return false;
+ }
+ if (obj instanceof Dict) {
+ if (obj.objId !== dict.objId) {
+ return false;
+ }
+ this.nodes[0] = element;
+ return true;
+ }
+ if (!Array.isArray(obj)) {
+ return true;
+ }
+ let save = false;
+ for (let i = 0; i < obj.length; i++) {
+ const kidRef = obj[i];
+ if (kidRef?.toString() === dict.objId) {
+ this.nodes[i] = element;
+ save = true;
+ }
+ }
+ return save;
+ }
+ get serializable() {
+ function nodeToSerializable(node, parent, level = 0) {
+ if (level > MAX_DEPTH) {
+ warn("StructTree too deep to be fully serialized.");
+ return;
+ }
+ const obj = Object.create(null);
+ obj.role = node.role;
+ obj.children = [];
+ parent.children.push(obj);
+ const alt = node.dict.get("Alt");
+ if (typeof alt === "string") {
+ obj.alt = stringToPDFString(alt);
+ }
+ const lang = node.dict.get("Lang");
+ if (typeof lang === "string") {
+ obj.lang = stringToPDFString(lang);
+ }
+ for (const kid of node.kids) {
+ const kidElement = kid.type === StructElementType.ELEMENT ? kid.parentNode : null;
+ if (kidElement) {
+ nodeToSerializable(kidElement, obj, level + 1);
+ continue;
+ } else if (kid.type === StructElementType.PAGE_CONTENT || kid.type === StructElementType.STREAM_CONTENT) {
+ obj.children.push({
+ type: "content",
+ id: `p${kid.pageObjId}_mc${kid.mcid}`
+ });
+ } else if (kid.type === StructElementType.OBJECT) {
+ obj.children.push({
+ type: "object",
+ id: kid.refObjId
+ });
+ } else if (kid.type === StructElementType.ANNOTATION) {
+ obj.children.push({
+ type: "annotation",
+ id: `${AnnotationPrefix}${kid.refObjId}`
+ });
+ }
+ }
+ }
+ const root = Object.create(null);
+ root.children = [];
+ root.role = "Root";
+ for (const child of this.nodes) {
+ if (!child) {
+ continue;
+ }
+ nodeToSerializable(child, root);
+ }
+ return root;
+ }
+}
+
+;// CONCATENATED MODULE: ./src/core/catalog.js
+
+
+
+
+
+
+
+
+
+
+
+function fetchDestination(dest) {
+ if (dest instanceof Dict) {
+ dest = dest.get("D");
+ }
+ return Array.isArray(dest) ? dest : null;
+}
+function fetchRemoteDest(action) {
+ let dest = action.get("D");
+ if (dest) {
+ if (dest instanceof Name) {
+ dest = dest.name;
+ }
+ if (typeof dest === "string") {
+ return stringToPDFString(dest);
+ } else if (Array.isArray(dest)) {
+ return JSON.stringify(dest);
+ }
+ }
+ return null;
+}
+class Catalog {
+ constructor(pdfManager, xref) {
+ this.pdfManager = pdfManager;
+ this.xref = xref;
+ this._catDict = xref.getCatalogObj();
+ if (!(this._catDict instanceof Dict)) {
+ throw new FormatError("Catalog object is not a dictionary.");
+ }
+ this.toplevelPagesDict;
+ this._actualNumPages = null;
+ this.fontCache = new RefSetCache();
+ this.builtInCMapCache = new Map();
+ this.standardFontDataCache = new Map();
+ this.globalImageCache = new GlobalImageCache();
+ this.pageKidsCountCache = new RefSetCache();
+ this.pageIndexCache = new RefSetCache();
+ this.nonBlendModesSet = new RefSet();
+ this.systemFontCache = new Map();
+ }
+ cloneDict() {
+ return this._catDict.clone();
+ }
+ get version() {
+ const version = this._catDict.get("Version");
+ if (version instanceof Name) {
+ if (PDF_VERSION_REGEXP.test(version.name)) {
+ return shadow(this, "version", version.name);
+ }
+ warn(`Invalid PDF catalog version: ${version.name}`);
+ }
+ return shadow(this, "version", null);
+ }
+ get lang() {
+ const lang = this._catDict.get("Lang");
+ return shadow(this, "lang", typeof lang === "string" ? stringToPDFString(lang) : null);
+ }
+ get needsRendering() {
+ const needsRendering = this._catDict.get("NeedsRendering");
+ return shadow(this, "needsRendering", typeof needsRendering === "boolean" ? needsRendering : false);
+ }
+ get collection() {
+ let collection = null;
+ try {
+ const obj = this._catDict.get("Collection");
+ if (obj instanceof Dict && obj.size > 0) {
+ collection = obj;
+ }
+ } catch (ex) {
+ if (ex instanceof MissingDataException) {
+ throw ex;
+ }
+ info("Cannot fetch Collection entry; assuming no collection is present.");
+ }
+ return shadow(this, "collection", collection);
+ }
+ get acroForm() {
+ let acroForm = null;
+ try {
+ const obj = this._catDict.get("AcroForm");
+ if (obj instanceof Dict && obj.size > 0) {
+ acroForm = obj;
+ }
+ } catch (ex) {
+ if (ex instanceof MissingDataException) {
+ throw ex;
+ }
+ info("Cannot fetch AcroForm entry; assuming no forms are present.");
+ }
+ return shadow(this, "acroForm", acroForm);
+ }
+ get acroFormRef() {
+ const value = this._catDict.getRaw("AcroForm");
+ return shadow(this, "acroFormRef", value instanceof Ref ? value : null);
+ }
+ get metadata() {
+ const streamRef = this._catDict.getRaw("Metadata");
+ if (!(streamRef instanceof Ref)) {
+ return shadow(this, "metadata", null);
+ }
+ let metadata = null;
+ try {
+ const stream = this.xref.fetch(streamRef, !this.xref.encrypt?.encryptMetadata);
+ if (stream instanceof BaseStream && stream.dict instanceof Dict) {
+ const type = stream.dict.get("Type");
+ const subtype = stream.dict.get("Subtype");
+ if (isName(type, "Metadata") && isName(subtype, "XML")) {
+ const data = stringToUTF8String(stream.getString());
+ if (data) {
+ metadata = new MetadataParser(data).serializable;
+ }
+ }
+ }
+ } catch (ex) {
+ if (ex instanceof MissingDataException) {
+ throw ex;
+ }
+ info(`Skipping invalid Metadata: "${ex}".`);
+ }
+ return shadow(this, "metadata", metadata);
+ }
+ get markInfo() {
+ let markInfo = null;
+ try {
+ markInfo = this._readMarkInfo();
+ } catch (ex) {
+ if (ex instanceof MissingDataException) {
+ throw ex;
+ }
+ warn("Unable to read mark info.");
+ }
+ return shadow(this, "markInfo", markInfo);
+ }
+ _readMarkInfo() {
+ const obj = this._catDict.get("MarkInfo");
+ if (!(obj instanceof Dict)) {
+ return null;
+ }
+ const markInfo = {
+ Marked: false,
+ UserProperties: false,
+ Suspects: false
+ };
+ for (const key in markInfo) {
+ const value = obj.get(key);
+ if (typeof value === "boolean") {
+ markInfo[key] = value;
+ }
+ }
+ return markInfo;
+ }
+ get structTreeRoot() {
+ let structTree = null;
+ try {
+ structTree = this._readStructTreeRoot();
+ } catch (ex) {
+ if (ex instanceof MissingDataException) {
+ throw ex;
+ }
+ warn("Unable read to structTreeRoot info.");
+ }
+ return shadow(this, "structTreeRoot", structTree);
+ }
+ _readStructTreeRoot() {
+ const rawObj = this._catDict.getRaw("StructTreeRoot");
+ const obj = this.xref.fetchIfRef(rawObj);
+ if (!(obj instanceof Dict)) {
+ return null;
+ }
+ const root = new StructTreeRoot(obj, rawObj);
+ root.init();
+ return root;
+ }
+ get toplevelPagesDict() {
+ const pagesObj = this._catDict.get("Pages");
+ if (!(pagesObj instanceof Dict)) {
+ throw new FormatError("Invalid top-level pages dictionary.");
+ }
+ return shadow(this, "toplevelPagesDict", pagesObj);
+ }
+ get documentOutline() {
+ let obj = null;
+ try {
+ obj = this._readDocumentOutline();
+ } catch (ex) {
+ if (ex instanceof MissingDataException) {
+ throw ex;
+ }
+ warn("Unable to read document outline.");
+ }
+ return shadow(this, "documentOutline", obj);
+ }
+ _readDocumentOutline() {
+ let obj = this._catDict.get("Outlines");
+ if (!(obj instanceof Dict)) {
+ return null;
+ }
+ obj = obj.getRaw("First");
+ if (!(obj instanceof Ref)) {
+ return null;
+ }
+ const root = {
+ items: []
+ };
+ const queue = [{
+ obj,
+ parent: root
+ }];
+ const processed = new RefSet();
+ processed.put(obj);
+ const xref = this.xref,
+ blackColor = new Uint8ClampedArray(3);
+ while (queue.length > 0) {
+ const i = queue.shift();
+ const outlineDict = xref.fetchIfRef(i.obj);
+ if (outlineDict === null) {
+ continue;
+ }
+ if (!outlineDict.has("Title")) {
+ throw new FormatError("Invalid outline item encountered.");
+ }
+ const data = {
+ url: null,
+ dest: null,
+ action: null
+ };
+ Catalog.parseDestDictionary({
+ destDict: outlineDict,
+ resultObj: data,
+ docBaseUrl: this.baseUrl,
+ docAttachments: this.attachments
+ });
+ const title = outlineDict.get("Title");
+ const flags = outlineDict.get("F") || 0;
+ const color = outlineDict.getArray("C");
+ const count = outlineDict.get("Count");
+ let rgbColor = blackColor;
+ if (Array.isArray(color) && color.length === 3 && (color[0] !== 0 || color[1] !== 0 || color[2] !== 0)) {
+ rgbColor = ColorSpace.singletons.rgb.getRgb(color, 0);
+ }
+ const outlineItem = {
+ action: data.action,
+ attachment: data.attachment,
+ dest: data.dest,
+ url: data.url,
+ unsafeUrl: data.unsafeUrl,
+ newWindow: data.newWindow,
+ setOCGState: data.setOCGState,
+ title: stringToPDFString(title),
+ color: rgbColor,
+ count: Number.isInteger(count) ? count : undefined,
+ bold: !!(flags & 2),
+ italic: !!(flags & 1),
+ items: []
+ };
+ i.parent.items.push(outlineItem);
+ obj = outlineDict.getRaw("First");
+ if (obj instanceof Ref && !processed.has(obj)) {
+ queue.push({
+ obj,
+ parent: outlineItem
+ });
+ processed.put(obj);
+ }
+ obj = outlineDict.getRaw("Next");
+ if (obj instanceof Ref && !processed.has(obj)) {
+ queue.push({
+ obj,
+ parent: i.parent
+ });
+ processed.put(obj);
+ }
+ }
+ return root.items.length > 0 ? root.items : null;
+ }
+ get permissions() {
+ let permissions = null;
+ try {
+ permissions = this._readPermissions();
+ } catch (ex) {
+ if (ex instanceof MissingDataException) {
+ throw ex;
+ }
+ warn("Unable to read permissions.");
+ }
+ return shadow(this, "permissions", permissions);
+ }
+ _readPermissions() {
+ const encrypt = this.xref.trailer.get("Encrypt");
+ if (!(encrypt instanceof Dict)) {
+ return null;
+ }
+ let flags = encrypt.get("P");
+ if (typeof flags !== "number") {
+ return null;
+ }
+ flags += 2 ** 32;
+ const permissions = [];
+ for (const key in PermissionFlag) {
+ const value = PermissionFlag[key];
+ if (flags & value) {
+ permissions.push(value);
+ }
+ }
+ return permissions;
+ }
+ get optionalContentConfig() {
+ let config = null;
+ try {
+ const properties = this._catDict.get("OCProperties");
+ if (!properties) {
+ return shadow(this, "optionalContentConfig", null);
+ }
+ const defaultConfig = properties.get("D");
+ if (!defaultConfig) {
+ return shadow(this, "optionalContentConfig", null);
+ }
+ const groupsData = properties.get("OCGs");
+ if (!Array.isArray(groupsData)) {
+ return shadow(this, "optionalContentConfig", null);
+ }
+ const groups = [];
+ const groupRefs = new RefSet();
+ for (const groupRef of groupsData) {
+ if (!(groupRef instanceof Ref) || groupRefs.has(groupRef)) {
+ continue;
+ }
+ groupRefs.put(groupRef);
+ const group = this.xref.fetch(groupRef);
+ groups.push({
+ id: groupRef.toString(),
+ name: typeof group.get("Name") === "string" ? stringToPDFString(group.get("Name")) : null,
+ intent: typeof group.get("Intent") === "string" ? stringToPDFString(group.get("Intent")) : null
+ });
+ }
+ config = this._readOptionalContentConfig(defaultConfig, groupRefs);
+ config.groups = groups;
+ } catch (ex) {
+ if (ex instanceof MissingDataException) {
+ throw ex;
+ }
+ warn(`Unable to read optional content config: ${ex}`);
+ }
+ return shadow(this, "optionalContentConfig", config);
+ }
+ _readOptionalContentConfig(config, contentGroupRefs) {
+ function parseOnOff(refs) {
+ const onParsed = [];
+ if (Array.isArray(refs)) {
+ for (const value of refs) {
+ if (!(value instanceof Ref)) {
+ continue;
+ }
+ if (contentGroupRefs.has(value)) {
+ onParsed.push(value.toString());
+ }
+ }
+ }
+ return onParsed;
+ }
+ function parseOrder(refs, nestedLevels = 0) {
+ if (!Array.isArray(refs)) {
+ return null;
+ }
+ const order = [];
+ for (const value of refs) {
+ if (value instanceof Ref && contentGroupRefs.has(value)) {
+ parsedOrderRefs.put(value);
+ order.push(value.toString());
+ continue;
+ }
+ const nestedOrder = parseNestedOrder(value, nestedLevels);
+ if (nestedOrder) {
+ order.push(nestedOrder);
+ }
+ }
+ if (nestedLevels > 0) {
+ return order;
+ }
+ const hiddenGroups = [];
+ for (const groupRef of contentGroupRefs) {
+ if (parsedOrderRefs.has(groupRef)) {
+ continue;
+ }
+ hiddenGroups.push(groupRef.toString());
+ }
+ if (hiddenGroups.length) {
+ order.push({
+ name: null,
+ order: hiddenGroups
+ });
+ }
+ return order;
+ }
+ function parseNestedOrder(ref, nestedLevels) {
+ if (++nestedLevels > MAX_NESTED_LEVELS) {
+ warn("parseNestedOrder - reached MAX_NESTED_LEVELS.");
+ return null;
+ }
+ const value = xref.fetchIfRef(ref);
+ if (!Array.isArray(value)) {
+ return null;
+ }
+ const nestedName = xref.fetchIfRef(value[0]);
+ if (typeof nestedName !== "string") {
+ return null;
+ }
+ const nestedOrder = parseOrder(value.slice(1), nestedLevels);
+ if (!nestedOrder || !nestedOrder.length) {
+ return null;
+ }
+ return {
+ name: stringToPDFString(nestedName),
+ order: nestedOrder
+ };
+ }
+ const xref = this.xref,
+ parsedOrderRefs = new RefSet(),
+ MAX_NESTED_LEVELS = 10;
+ return {
+ name: typeof config.get("Name") === "string" ? stringToPDFString(config.get("Name")) : null,
+ creator: typeof config.get("Creator") === "string" ? stringToPDFString(config.get("Creator")) : null,
+ baseState: config.get("BaseState") instanceof Name ? config.get("BaseState").name : null,
+ on: parseOnOff(config.get("ON")),
+ off: parseOnOff(config.get("OFF")),
+ order: parseOrder(config.get("Order")),
+ groups: null
+ };
+ }
+ setActualNumPages(num = null) {
+ this._actualNumPages = num;
+ }
+ get hasActualNumPages() {
+ return this._actualNumPages !== null;
+ }
+ get _pagesCount() {
+ const obj = this.toplevelPagesDict.get("Count");
+ if (!Number.isInteger(obj)) {
+ throw new FormatError("Page count in top-level pages dictionary is not an integer.");
+ }
+ return shadow(this, "_pagesCount", obj);
+ }
+ get numPages() {
+ return this.hasActualNumPages ? this._actualNumPages : this._pagesCount;
+ }
+ get destinations() {
+ const obj = this._readDests(),
+ dests = Object.create(null);
+ if (obj instanceof NameTree) {
+ for (const [key, value] of obj.getAll()) {
+ const dest = fetchDestination(value);
+ if (dest) {
+ dests[stringToPDFString(key)] = dest;
+ }
+ }
+ } else if (obj instanceof Dict) {
+ obj.forEach(function (key, value) {
+ const dest = fetchDestination(value);
+ if (dest) {
+ dests[key] = dest;
+ }
+ });
+ }
+ return shadow(this, "destinations", dests);
+ }
+ getDestination(id) {
+ const obj = this._readDests();
+ if (obj instanceof NameTree) {
+ const dest = fetchDestination(obj.get(id));
+ if (dest) {
+ return dest;
+ }
+ const allDest = this.destinations[id];
+ if (allDest) {
+ warn(`Found "${id}" at an incorrect position in the NameTree.`);
+ return allDest;
+ }
+ } else if (obj instanceof Dict) {
+ const dest = fetchDestination(obj.get(id));
+ if (dest) {
+ return dest;
+ }
+ }
+ return null;
+ }
+ _readDests() {
+ const obj = this._catDict.get("Names");
+ if (obj?.has("Dests")) {
+ return new NameTree(obj.getRaw("Dests"), this.xref);
+ } else if (this._catDict.has("Dests")) {
+ return this._catDict.get("Dests");
+ }
+ return undefined;
+ }
+ get pageLabels() {
+ let obj = null;
+ try {
+ obj = this._readPageLabels();
+ } catch (ex) {
+ if (ex instanceof MissingDataException) {
+ throw ex;
+ }
+ warn("Unable to read page labels.");
+ }
+ return shadow(this, "pageLabels", obj);
+ }
+ _readPageLabels() {
+ const obj = this._catDict.getRaw("PageLabels");
+ if (!obj) {
+ return null;
+ }
+ const pageLabels = new Array(this.numPages);
+ let style = null,
+ prefix = "";
+ const numberTree = new NumberTree(obj, this.xref);
+ const nums = numberTree.getAll();
+ let currentLabel = "",
+ currentIndex = 1;
+ for (let i = 0, ii = this.numPages; i < ii; i++) {
+ const labelDict = nums.get(i);
+ if (labelDict !== undefined) {
+ if (!(labelDict instanceof Dict)) {
+ throw new FormatError("PageLabel is not a dictionary.");
+ }
+ if (labelDict.has("Type") && !isName(labelDict.get("Type"), "PageLabel")) {
+ throw new FormatError("Invalid type in PageLabel dictionary.");
+ }
+ if (labelDict.has("S")) {
+ const s = labelDict.get("S");
+ if (!(s instanceof Name)) {
+ throw new FormatError("Invalid style in PageLabel dictionary.");
+ }
+ style = s.name;
+ } else {
+ style = null;
+ }
+ if (labelDict.has("P")) {
+ const p = labelDict.get("P");
+ if (typeof p !== "string") {
+ throw new FormatError("Invalid prefix in PageLabel dictionary.");
+ }
+ prefix = stringToPDFString(p);
+ } else {
+ prefix = "";
+ }
+ if (labelDict.has("St")) {
+ const st = labelDict.get("St");
+ if (!(Number.isInteger(st) && st >= 1)) {
+ throw new FormatError("Invalid start in PageLabel dictionary.");
+ }
+ currentIndex = st;
+ } else {
+ currentIndex = 1;
+ }
+ }
+ switch (style) {
+ case "D":
+ currentLabel = currentIndex;
+ break;
+ case "R":
+ case "r":
+ currentLabel = toRomanNumerals(currentIndex, style === "r");
+ break;
+ case "A":
+ case "a":
+ const LIMIT = 26;
+ const A_UPPER_CASE = 0x41,
+ A_LOWER_CASE = 0x61;
+ const baseCharCode = style === "a" ? A_LOWER_CASE : A_UPPER_CASE;
+ const letterIndex = currentIndex - 1;
+ const character = String.fromCharCode(baseCharCode + letterIndex % LIMIT);
+ currentLabel = character.repeat(Math.floor(letterIndex / LIMIT) + 1);
+ break;
+ default:
+ if (style) {
+ throw new FormatError(`Invalid style "${style}" in PageLabel dictionary.`);
+ }
+ currentLabel = "";
+ }
+ pageLabels[i] = prefix + currentLabel;
+ currentIndex++;
+ }
+ return pageLabels;
+ }
+ get pageLayout() {
+ const obj = this._catDict.get("PageLayout");
+ let pageLayout = "";
+ if (obj instanceof Name) {
+ switch (obj.name) {
+ case "SinglePage":
+ case "OneColumn":
+ case "TwoColumnLeft":
+ case "TwoColumnRight":
+ case "TwoPageLeft":
+ case "TwoPageRight":
+ pageLayout = obj.name;
+ }
+ }
+ return shadow(this, "pageLayout", pageLayout);
+ }
+ get pageMode() {
+ const obj = this._catDict.get("PageMode");
+ let pageMode = "UseNone";
+ if (obj instanceof Name) {
+ switch (obj.name) {
+ case "UseNone":
+ case "UseOutlines":
+ case "UseThumbs":
+ case "FullScreen":
+ case "UseOC":
+ case "UseAttachments":
+ pageMode = obj.name;
+ }
+ }
+ return shadow(this, "pageMode", pageMode);
+ }
+ get viewerPreferences() {
+ const obj = this._catDict.get("ViewerPreferences");
+ if (!(obj instanceof Dict)) {
+ return shadow(this, "viewerPreferences", null);
+ }
+ let prefs = null;
+ for (const key of obj.getKeys()) {
+ const value = obj.get(key);
+ let prefValue;
+ switch (key) {
+ case "HideToolbar":
+ case "HideMenubar":
+ case "HideWindowUI":
+ case "FitWindow":
+ case "CenterWindow":
+ case "DisplayDocTitle":
+ case "PickTrayByPDFSize":
+ if (typeof value === "boolean") {
+ prefValue = value;
+ }
+ break;
+ case "NonFullScreenPageMode":
+ if (value instanceof Name) {
+ switch (value.name) {
+ case "UseNone":
+ case "UseOutlines":
+ case "UseThumbs":
+ case "UseOC":
+ prefValue = value.name;
+ break;
+ default:
+ prefValue = "UseNone";
+ }
+ }
+ break;
+ case "Direction":
+ if (value instanceof Name) {
+ switch (value.name) {
+ case "L2R":
+ case "R2L":
+ prefValue = value.name;
+ break;
+ default:
+ prefValue = "L2R";
+ }
+ }
+ break;
+ case "ViewArea":
+ case "ViewClip":
+ case "PrintArea":
+ case "PrintClip":
+ if (value instanceof Name) {
+ switch (value.name) {
+ case "MediaBox":
+ case "CropBox":
+ case "BleedBox":
+ case "TrimBox":
+ case "ArtBox":
+ prefValue = value.name;
+ break;
+ default:
+ prefValue = "CropBox";
+ }
+ }
+ break;
+ case "PrintScaling":
+ if (value instanceof Name) {
+ switch (value.name) {
+ case "None":
+ case "AppDefault":
+ prefValue = value.name;
+ break;
+ default:
+ prefValue = "AppDefault";
+ }
+ }
+ break;
+ case "Duplex":
+ if (value instanceof Name) {
+ switch (value.name) {
+ case "Simplex":
+ case "DuplexFlipShortEdge":
+ case "DuplexFlipLongEdge":
+ prefValue = value.name;
+ break;
+ default:
+ prefValue = "None";
+ }
+ }
+ break;
+ case "PrintPageRange":
+ if (Array.isArray(value) && value.length % 2 === 0) {
+ const isValid = value.every((page, i, arr) => Number.isInteger(page) && page > 0 && (i === 0 || page >= arr[i - 1]) && page <= this.numPages);
+ if (isValid) {
+ prefValue = value;
+ }
+ }
+ break;
+ case "NumCopies":
+ if (Number.isInteger(value) && value > 0) {
+ prefValue = value;
+ }
+ break;
+ default:
+ warn(`Ignoring non-standard key in ViewerPreferences: ${key}.`);
+ continue;
+ }
+ if (prefValue === undefined) {
+ warn(`Bad value, for key "${key}", in ViewerPreferences: ${value}.`);
+ continue;
+ }
+ if (!prefs) {
+ prefs = Object.create(null);
+ }
+ prefs[key] = prefValue;
+ }
+ return shadow(this, "viewerPreferences", prefs);
+ }
+ get openAction() {
+ const obj = this._catDict.get("OpenAction");
+ const openAction = Object.create(null);
+ if (obj instanceof Dict) {
+ const destDict = new Dict(this.xref);
+ destDict.set("A", obj);
+ const resultObj = {
+ url: null,
+ dest: null,
+ action: null
+ };
+ Catalog.parseDestDictionary({
+ destDict,
+ resultObj
+ });
+ if (Array.isArray(resultObj.dest)) {
+ openAction.dest = resultObj.dest;
+ } else if (resultObj.action) {
+ openAction.action = resultObj.action;
+ }
+ } else if (Array.isArray(obj)) {
+ openAction.dest = obj;
+ }
+ return shadow(this, "openAction", objectSize(openAction) > 0 ? openAction : null);
+ }
+ get attachments() {
+ const obj = this._catDict.get("Names");
+ let attachments = null;
+ if (obj instanceof Dict && obj.has("EmbeddedFiles")) {
+ const nameTree = new NameTree(obj.getRaw("EmbeddedFiles"), this.xref);
+ for (const [key, value] of nameTree.getAll()) {
+ const fs = new FileSpec(value, this.xref);
+ if (!attachments) {
+ attachments = Object.create(null);
+ }
+ attachments[stringToPDFString(key)] = fs.serializable;
+ }
+ }
+ return shadow(this, "attachments", attachments);
+ }
+ get xfaImages() {
+ const obj = this._catDict.get("Names");
+ let xfaImages = null;
+ if (obj instanceof Dict && obj.has("XFAImages")) {
+ const nameTree = new NameTree(obj.getRaw("XFAImages"), this.xref);
+ for (const [key, value] of nameTree.getAll()) {
+ if (!xfaImages) {
+ xfaImages = new Dict(this.xref);
+ }
+ xfaImages.set(stringToPDFString(key), value);
+ }
+ }
+ return shadow(this, "xfaImages", xfaImages);
+ }
+ _collectJavaScript() {
+ const obj = this._catDict.get("Names");
+ let javaScript = null;
+ function appendIfJavaScriptDict(name, jsDict) {
+ if (!(jsDict instanceof Dict)) {
+ return;
+ }
+ if (!isName(jsDict.get("S"), "JavaScript")) {
+ return;
+ }
+ let js = jsDict.get("JS");
+ if (js instanceof BaseStream) {
+ js = js.getString();
+ } else if (typeof js !== "string") {
+ return;
+ }
+ js = stringToPDFString(js).replaceAll("\x00", "");
+ if (js) {
+ (javaScript ||= new Map()).set(name, js);
+ }
+ }
+ if (obj instanceof Dict && obj.has("JavaScript")) {
+ const nameTree = new NameTree(obj.getRaw("JavaScript"), this.xref);
+ for (const [key, value] of nameTree.getAll()) {
+ appendIfJavaScriptDict(stringToPDFString(key), value);
+ }
+ }
+ const openAction = this._catDict.get("OpenAction");
+ if (openAction) {
+ appendIfJavaScriptDict("OpenAction", openAction);
+ }
+ return javaScript;
+ }
+ get jsActions() {
+ const javaScript = this._collectJavaScript();
+ let actions = collectActions(this.xref, this._catDict, DocumentActionEventType);
+ if (javaScript) {
+ actions ||= Object.create(null);
+ for (const [key, val] of javaScript) {
+ if (key in actions) {
+ actions[key].push(val);
+ } else {
+ actions[key] = [val];
+ }
+ }
+ }
+ return shadow(this, "jsActions", actions);
+ }
+ async fontFallback(id, handler) {
+ const translatedFonts = await Promise.all(this.fontCache);
+ for (const translatedFont of translatedFonts) {
+ if (translatedFont.loadedName === id) {
+ translatedFont.fallback(handler);
+ return;
+ }
+ }
+ }
+ async cleanup(manuallyTriggered = false) {
+ clearGlobalCaches();
+ this.globalImageCache.clear(manuallyTriggered);
+ this.pageKidsCountCache.clear();
+ this.pageIndexCache.clear();
+ this.nonBlendModesSet.clear();
+ const translatedFonts = await Promise.all(this.fontCache);
+ for (const {
+ dict
+ } of translatedFonts) {
+ delete dict.cacheKey;
+ }
+ this.fontCache.clear();
+ this.builtInCMapCache.clear();
+ this.standardFontDataCache.clear();
+ this.systemFontCache.clear();
+ }
+ async getPageDict(pageIndex) {
+ const nodesToVisit = [this.toplevelPagesDict];
+ const visitedNodes = new RefSet();
+ const pagesRef = this._catDict.getRaw("Pages");
+ if (pagesRef instanceof Ref) {
+ visitedNodes.put(pagesRef);
+ }
+ const xref = this.xref,
+ pageKidsCountCache = this.pageKidsCountCache,
+ pageIndexCache = this.pageIndexCache;
+ let currentPageIndex = 0;
+ while (nodesToVisit.length) {
+ const currentNode = nodesToVisit.pop();
+ if (currentNode instanceof Ref) {
+ const count = pageKidsCountCache.get(currentNode);
+ if (count >= 0 && currentPageIndex + count <= pageIndex) {
+ currentPageIndex += count;
+ continue;
+ }
+ if (visitedNodes.has(currentNode)) {
+ throw new FormatError("Pages tree contains circular reference.");
+ }
+ visitedNodes.put(currentNode);
+ const obj = await xref.fetchAsync(currentNode);
+ if (obj instanceof Dict) {
+ let type = obj.getRaw("Type");
+ if (type instanceof Ref) {
+ type = await xref.fetchAsync(type);
+ }
+ if (isName(type, "Page") || !obj.has("Kids")) {
+ if (!pageKidsCountCache.has(currentNode)) {
+ pageKidsCountCache.put(currentNode, 1);
+ }
+ if (!pageIndexCache.has(currentNode)) {
+ pageIndexCache.put(currentNode, currentPageIndex);
+ }
+ if (currentPageIndex === pageIndex) {
+ return [obj, currentNode];
+ }
+ currentPageIndex++;
+ continue;
+ }
+ }
+ nodesToVisit.push(obj);
+ continue;
+ }
+ if (!(currentNode instanceof Dict)) {
+ throw new FormatError("Page dictionary kid reference points to wrong type of object.");
+ }
+ const {
+ objId
+ } = currentNode;
+ let count = currentNode.getRaw("Count");
+ if (count instanceof Ref) {
+ count = await xref.fetchAsync(count);
+ }
+ if (Number.isInteger(count) && count >= 0) {
+ if (objId && !pageKidsCountCache.has(objId)) {
+ pageKidsCountCache.put(objId, count);
+ }
+ if (currentPageIndex + count <= pageIndex) {
+ currentPageIndex += count;
+ continue;
+ }
+ }
+ let kids = currentNode.getRaw("Kids");
+ if (kids instanceof Ref) {
+ kids = await xref.fetchAsync(kids);
+ }
+ if (!Array.isArray(kids)) {
+ let type = currentNode.getRaw("Type");
+ if (type instanceof Ref) {
+ type = await xref.fetchAsync(type);
+ }
+ if (isName(type, "Page") || !currentNode.has("Kids")) {
+ if (currentPageIndex === pageIndex) {
+ return [currentNode, null];
+ }
+ currentPageIndex++;
+ continue;
+ }
+ throw new FormatError("Page dictionary kids object is not an array.");
+ }
+ for (let last = kids.length - 1; last >= 0; last--) {
+ nodesToVisit.push(kids[last]);
+ }
+ }
+ throw new Error(`Page index ${pageIndex} not found.`);
+ }
+ async getAllPageDicts(recoveryMode = false) {
+ const {
+ ignoreErrors
+ } = this.pdfManager.evaluatorOptions;
+ const queue = [{
+ currentNode: this.toplevelPagesDict,
+ posInKids: 0
+ }];
+ const visitedNodes = new RefSet();
+ const pagesRef = this._catDict.getRaw("Pages");
+ if (pagesRef instanceof Ref) {
+ visitedNodes.put(pagesRef);
+ }
+ const map = new Map(),
+ xref = this.xref,
+ pageIndexCache = this.pageIndexCache;
+ let pageIndex = 0;
+ function addPageDict(pageDict, pageRef) {
+ if (pageRef && !pageIndexCache.has(pageRef)) {
+ pageIndexCache.put(pageRef, pageIndex);
+ }
+ map.set(pageIndex++, [pageDict, pageRef]);
+ }
+ function addPageError(error) {
+ if (error instanceof XRefEntryException && !recoveryMode) {
+ throw error;
+ }
+ if (recoveryMode && ignoreErrors && pageIndex === 0) {
+ warn(`getAllPageDicts - Skipping invalid first page: "${error}".`);
+ error = Dict.empty;
+ }
+ map.set(pageIndex++, [error, null]);
+ }
+ while (queue.length > 0) {
+ const queueItem = queue.at(-1);
+ const {
+ currentNode,
+ posInKids
+ } = queueItem;
+ let kids = currentNode.getRaw("Kids");
+ if (kids instanceof Ref) {
+ try {
+ kids = await xref.fetchAsync(kids);
+ } catch (ex) {
+ addPageError(ex);
+ break;
+ }
+ }
+ if (!Array.isArray(kids)) {
+ addPageError(new FormatError("Page dictionary kids object is not an array."));
+ break;
+ }
+ if (posInKids >= kids.length) {
+ queue.pop();
+ continue;
+ }
+ const kidObj = kids[posInKids];
+ let obj;
+ if (kidObj instanceof Ref) {
+ if (visitedNodes.has(kidObj)) {
+ addPageError(new FormatError("Pages tree contains circular reference."));
+ break;
+ }
+ visitedNodes.put(kidObj);
+ try {
+ obj = await xref.fetchAsync(kidObj);
+ } catch (ex) {
+ addPageError(ex);
+ break;
+ }
+ } else {
+ obj = kidObj;
+ }
+ if (!(obj instanceof Dict)) {
+ addPageError(new FormatError("Page dictionary kid reference points to wrong type of object."));
+ break;
+ }
+ let type = obj.getRaw("Type");
+ if (type instanceof Ref) {
+ try {
+ type = await xref.fetchAsync(type);
+ } catch (ex) {
+ addPageError(ex);
+ break;
+ }
+ }
+ if (isName(type, "Page") || !obj.has("Kids")) {
+ addPageDict(obj, kidObj instanceof Ref ? kidObj : null);
+ } else {
+ queue.push({
+ currentNode: obj,
+ posInKids: 0
+ });
+ }
+ queueItem.posInKids++;
+ }
+ return map;
+ }
+ getPageIndex(pageRef) {
+ const cachedPageIndex = this.pageIndexCache.get(pageRef);
+ if (cachedPageIndex !== undefined) {
+ return Promise.resolve(cachedPageIndex);
+ }
+ const xref = this.xref;
+ function pagesBeforeRef(kidRef) {
+ let total = 0,
+ parentRef;
+ return xref.fetchAsync(kidRef).then(function (node) {
+ if (isRefsEqual(kidRef, pageRef) && !isDict(node, "Page") && !(node instanceof Dict && !node.has("Type") && node.has("Contents"))) {
+ throw new FormatError("The reference does not point to a /Page dictionary.");
+ }
+ if (!node) {
+ return null;
+ }
+ if (!(node instanceof Dict)) {
+ throw new FormatError("Node must be a dictionary.");
+ }
+ parentRef = node.getRaw("Parent");
+ return node.getAsync("Parent");
+ }).then(function (parent) {
+ if (!parent) {
+ return null;
+ }
+ if (!(parent instanceof Dict)) {
+ throw new FormatError("Parent must be a dictionary.");
+ }
+ return parent.getAsync("Kids");
+ }).then(function (kids) {
+ if (!kids) {
+ return null;
+ }
+ const kidPromises = [];
+ let found = false;
+ for (const kid of kids) {
+ if (!(kid instanceof Ref)) {
+ throw new FormatError("Kid must be a reference.");
+ }
+ if (isRefsEqual(kid, kidRef)) {
+ found = true;
+ break;
+ }
+ kidPromises.push(xref.fetchAsync(kid).then(function (obj) {
+ if (!(obj instanceof Dict)) {
+ throw new FormatError("Kid node must be a dictionary.");
+ }
+ if (obj.has("Count")) {
+ total += obj.get("Count");
+ } else {
+ total++;
+ }
+ }));
+ }
+ if (!found) {
+ throw new FormatError("Kid reference not found in parent's kids.");
+ }
+ return Promise.all(kidPromises).then(function () {
+ return [total, parentRef];
+ });
+ });
+ }
+ let total = 0;
+ const next = ref => pagesBeforeRef(ref).then(args => {
+ if (!args) {
+ this.pageIndexCache.put(pageRef, total);
+ return total;
+ }
+ const [count, parentRef] = args;
+ total += count;
+ return next(parentRef);
+ });
+ return next(pageRef);
+ }
+ get baseUrl() {
+ const uri = this._catDict.get("URI");
+ if (uri instanceof Dict) {
+ const base = uri.get("Base");
+ if (typeof base === "string") {
+ const absoluteUrl = createValidAbsoluteUrl(base, null, {
+ tryConvertEncoding: true
+ });
+ if (absoluteUrl) {
+ return shadow(this, "baseUrl", absoluteUrl.href);
+ }
+ }
+ }
+ return shadow(this, "baseUrl", this.pdfManager.docBaseUrl);
+ }
+ static parseDestDictionary({
+ destDict,
+ resultObj,
+ docBaseUrl = null,
+ docAttachments = null
+ }) {
+ if (!(destDict instanceof Dict)) {
+ warn("parseDestDictionary: `destDict` must be a dictionary.");
+ return;
+ }
+ let action = destDict.get("A"),
+ url,
+ dest;
+ if (!(action instanceof Dict)) {
+ if (destDict.has("Dest")) {
+ action = destDict.get("Dest");
+ } else {
+ action = destDict.get("AA");
+ if (action instanceof Dict) {
+ if (action.has("D")) {
+ action = action.get("D");
+ } else if (action.has("U")) {
+ action = action.get("U");
+ }
+ }
+ }
+ }
+ if (action instanceof Dict) {
+ const actionType = action.get("S");
+ if (!(actionType instanceof Name)) {
+ warn("parseDestDictionary: Invalid type in Action dictionary.");
+ return;
+ }
+ const actionName = actionType.name;
+ switch (actionName) {
+ case "ResetForm":
+ const flags = action.get("Flags");
+ const include = ((typeof flags === "number" ? flags : 0) & 1) === 0;
+ const fields = [];
+ const refs = [];
+ for (const obj of action.get("Fields") || []) {
+ if (obj instanceof Ref) {
+ refs.push(obj.toString());
+ } else if (typeof obj === "string") {
+ fields.push(stringToPDFString(obj));
+ }
+ }
+ resultObj.resetForm = {
+ fields,
+ refs,
+ include
+ };
+ break;
+ case "URI":
+ url = action.get("URI");
+ if (url instanceof Name) {
+ url = "/" + url.name;
+ }
+ break;
+ case "GoTo":
+ dest = action.get("D");
+ break;
+ case "Launch":
+ case "GoToR":
+ const urlDict = action.get("F");
+ if (urlDict instanceof Dict) {
+ url = urlDict.get("F") || null;
+ } else if (typeof urlDict === "string") {
+ url = urlDict;
+ }
+ const remoteDest = fetchRemoteDest(action);
+ if (remoteDest && typeof url === "string") {
+ url = url.split("#", 1)[0] + "#" + remoteDest;
+ }
+ const newWindow = action.get("NewWindow");
+ if (typeof newWindow === "boolean") {
+ resultObj.newWindow = newWindow;
+ }
+ break;
+ case "GoToE":
+ const target = action.get("T");
+ let attachment;
+ if (docAttachments && target instanceof Dict) {
+ const relationship = target.get("R");
+ const name = target.get("N");
+ if (isName(relationship, "C") && typeof name === "string") {
+ attachment = docAttachments[stringToPDFString(name)];
+ }
+ }
+ if (attachment) {
+ resultObj.attachment = attachment;
+ const attachmentDest = fetchRemoteDest(action);
+ if (attachmentDest) {
+ resultObj.attachmentDest = attachmentDest;
+ }
+ } else {
+ warn(`parseDestDictionary - unimplemented "GoToE" action.`);
+ }
+ break;
+ case "Named":
+ const namedAction = action.get("N");
+ if (namedAction instanceof Name) {
+ resultObj.action = namedAction.name;
+ }
+ break;
+ case "SetOCGState":
+ const state = action.get("State");
+ const preserveRB = action.get("PreserveRB");
+ if (!Array.isArray(state) || state.length === 0) {
+ break;
+ }
+ const stateArr = [];
+ for (const elem of state) {
+ if (elem instanceof Name) {
+ switch (elem.name) {
+ case "ON":
+ case "OFF":
+ case "Toggle":
+ stateArr.push(elem.name);
+ break;
+ }
+ } else if (elem instanceof Ref) {
+ stateArr.push(elem.toString());
+ }
+ }
+ if (stateArr.length !== state.length) {
+ break;
+ }
+ resultObj.setOCGState = {
+ state: stateArr,
+ preserveRB: typeof preserveRB === "boolean" ? preserveRB : true
+ };
+ break;
+ case "JavaScript":
+ const jsAction = action.get("JS");
+ let js;
+ if (jsAction instanceof BaseStream) {
+ js = jsAction.getString();
+ } else if (typeof jsAction === "string") {
+ js = jsAction;
+ }
+ const jsURL = js && recoverJsURL(stringToPDFString(js));
+ if (jsURL) {
+ url = jsURL.url;
+ resultObj.newWindow = jsURL.newWindow;
+ break;
+ }
+ default:
+ if (actionName === "JavaScript" || actionName === "SubmitForm") {
+ break;
+ }
+ warn(`parseDestDictionary - unsupported action: "${actionName}".`);
+ break;
+ }
+ } else if (destDict.has("Dest")) {
+ dest = destDict.get("Dest");
+ }
+ if (typeof url === "string") {
+ const absoluteUrl = createValidAbsoluteUrl(url, docBaseUrl, {
+ addDefaultProtocol: true,
+ tryConvertEncoding: true
+ });
+ if (absoluteUrl) {
+ resultObj.url = absoluteUrl.href;
+ }
+ resultObj.unsafeUrl = url;
+ }
+ if (dest) {
+ if (dest instanceof Name) {
+ dest = dest.name;
+ }
+ if (typeof dest === "string") {
+ resultObj.dest = stringToPDFString(dest);
+ } else if (Array.isArray(dest)) {
+ resultObj.dest = dest;
+ }
+ }
+ }
+}
+
+;// CONCATENATED MODULE: ./src/core/object_loader.js
+
+
+
+
+function mayHaveChildren(value) {
+ return value instanceof Ref || value instanceof Dict || value instanceof BaseStream || Array.isArray(value);
+}
+function addChildren(node, nodesToVisit) {
+ if (node instanceof Dict) {
+ node = node.getRawValues();
+ } else if (node instanceof BaseStream) {
+ node = node.dict.getRawValues();
+ } else if (!Array.isArray(node)) {
+ return;
+ }
+ for (const rawValue of node) {
+ if (mayHaveChildren(rawValue)) {
+ nodesToVisit.push(rawValue);
+ }
+ }
+}
+class ObjectLoader {
+ constructor(dict, keys, xref) {
+ this.dict = dict;
+ this.keys = keys;
+ this.xref = xref;
+ this.refSet = null;
+ }
+ async load() {
+ if (this.xref.stream.isDataLoaded) {
+ return undefined;
+ }
+ const {
+ keys,
+ dict
+ } = this;
+ this.refSet = new RefSet();
+ const nodesToVisit = [];
+ for (const key of keys) {
+ const rawValue = dict.getRaw(key);
+ if (rawValue !== undefined) {
+ nodesToVisit.push(rawValue);
+ }
+ }
+ return this._walk(nodesToVisit);
+ }
+ async _walk(nodesToVisit) {
+ const nodesToRevisit = [];
+ const pendingRequests = [];
+ while (nodesToVisit.length) {
+ let currentNode = nodesToVisit.pop();
+ if (currentNode instanceof Ref) {
+ if (this.refSet.has(currentNode)) {
+ continue;
+ }
+ try {
+ this.refSet.put(currentNode);
+ currentNode = this.xref.fetch(currentNode);
+ } catch (ex) {
+ if (!(ex instanceof MissingDataException)) {
+ warn(`ObjectLoader._walk - requesting all data: "${ex}".`);
+ this.refSet = null;
+ const {
+ manager
+ } = this.xref.stream;
+ return manager.requestAllChunks();
+ }
+ nodesToRevisit.push(currentNode);
+ pendingRequests.push({
+ begin: ex.begin,
+ end: ex.end
+ });
+ }
+ }
+ if (currentNode instanceof BaseStream) {
+ const baseStreams = currentNode.getBaseStreams();
+ if (baseStreams) {
+ let foundMissingData = false;
+ for (const stream of baseStreams) {
+ if (stream.isDataLoaded) {
+ continue;
+ }
+ foundMissingData = true;
+ pendingRequests.push({
+ begin: stream.start,
+ end: stream.end
+ });
+ }
+ if (foundMissingData) {
+ nodesToRevisit.push(currentNode);
+ }
+ }
+ }
+ addChildren(currentNode, nodesToVisit);
+ }
+ if (pendingRequests.length) {
+ await this.xref.stream.manager.requestRanges(pendingRequests);
+ for (const node of nodesToRevisit) {
+ if (node instanceof Ref) {
+ this.refSet.remove(node);
+ }
+ }
+ return this._walk(nodesToRevisit);
+ }
+ this.refSet = null;
+ return undefined;
+ }
+}
+
+;// CONCATENATED MODULE: ./src/core/xfa/symbol_utils.js
+const $acceptWhitespace = Symbol();
+const $addHTML = Symbol();
+const $appendChild = Symbol();
+const $childrenToHTML = Symbol();
+const $clean = Symbol();
+const $cleanPage = Symbol();
+const $cleanup = Symbol();
+const $clone = Symbol();
+const $consumed = Symbol();
+const $content = Symbol("content");
+const $data = Symbol("data");
+const $dump = Symbol();
+const $extra = Symbol("extra");
+const $finalize = Symbol();
+const $flushHTML = Symbol();
+const $getAttributeIt = Symbol();
+const $getAttributes = Symbol();
+const $getAvailableSpace = Symbol();
+const $getChildrenByClass = Symbol();
+const $getChildrenByName = Symbol();
+const $getChildrenByNameIt = Symbol();
+const $getDataValue = Symbol();
+const $getExtra = Symbol();
+const $getRealChildrenByNameIt = Symbol();
+const $getChildren = Symbol();
+const $getContainedChildren = Symbol();
+const $getNextPage = Symbol();
+const $getSubformParent = Symbol();
+const $getParent = Symbol();
+const $getTemplateRoot = Symbol();
+const $globalData = Symbol();
+const $hasSettableValue = Symbol();
+const $ids = Symbol();
+const $indexOf = Symbol();
+const $insertAt = Symbol();
+const $isCDATAXml = Symbol();
+const $isBindable = Symbol();
+const $isDataValue = Symbol();
+const $isDescendent = Symbol();
+const $isNsAgnostic = Symbol();
+const $isSplittable = Symbol();
+const $isThereMoreWidth = Symbol();
+const $isTransparent = Symbol();
+const $isUsable = Symbol();
+const $lastAttribute = Symbol();
+const $namespaceId = Symbol("namespaceId");
+const $nodeName = Symbol("nodeName");
+const $nsAttributes = Symbol();
+const $onChild = Symbol();
+const $onChildCheck = Symbol();
+const $onText = Symbol();
+const $pushGlyphs = Symbol();
+const $popPara = Symbol();
+const $pushPara = Symbol();
+const $removeChild = Symbol();
+const $root = Symbol("root");
+const $resolvePrototypes = Symbol();
+const $searchNode = Symbol();
+const $setId = Symbol();
+const $setSetAttributes = Symbol();
+const $setValue = Symbol();
+const $tabIndex = Symbol();
+const $text = Symbol();
+const $toPages = Symbol();
+const $toHTML = Symbol();
+const $toString = Symbol();
+const $toStyle = Symbol();
+const $uid = Symbol("uid");
+
+;// CONCATENATED MODULE: ./src/core/xfa/namespaces.js
+const $buildXFAObject = Symbol();
+const NamespaceIds = {
+ config: {
+ id: 0,
+ check: ns => ns.startsWith("http://www.xfa.org/schema/xci/")
+ },
+ connectionSet: {
+ id: 1,
+ check: ns => ns.startsWith("http://www.xfa.org/schema/xfa-connection-set/")
+ },
+ datasets: {
+ id: 2,
+ check: ns => ns.startsWith("http://www.xfa.org/schema/xfa-data/")
+ },
+ form: {
+ id: 3,
+ check: ns => ns.startsWith("http://www.xfa.org/schema/xfa-form/")
+ },
+ localeSet: {
+ id: 4,
+ check: ns => ns.startsWith("http://www.xfa.org/schema/xfa-locale-set/")
+ },
+ pdf: {
+ id: 5,
+ check: ns => ns === "http://ns.adobe.com/xdp/pdf/"
+ },
+ signature: {
+ id: 6,
+ check: ns => ns === "http://www.w3.org/2000/09/xmldsig#"
+ },
+ sourceSet: {
+ id: 7,
+ check: ns => ns.startsWith("http://www.xfa.org/schema/xfa-source-set/")
+ },
+ stylesheet: {
+ id: 8,
+ check: ns => ns === "http://www.w3.org/1999/XSL/Transform"
+ },
+ template: {
+ id: 9,
+ check: ns => ns.startsWith("http://www.xfa.org/schema/xfa-template/")
+ },
+ xdc: {
+ id: 10,
+ check: ns => ns.startsWith("http://www.xfa.org/schema/xdc/")
+ },
+ xdp: {
+ id: 11,
+ check: ns => ns === "http://ns.adobe.com/xdp/"
+ },
+ xfdf: {
+ id: 12,
+ check: ns => ns === "http://ns.adobe.com/xfdf/"
+ },
+ xhtml: {
+ id: 13,
+ check: ns => ns === "http://www.w3.org/1999/xhtml"
+ },
+ xmpmeta: {
+ id: 14,
+ check: ns => ns === "http://ns.adobe.com/xmpmeta/"
+ }
+};
+
+;// CONCATENATED MODULE: ./src/core/xfa/utils.js
+
+const dimConverters = {
+ pt: x => x,
+ cm: x => x / 2.54 * 72,
+ mm: x => x / (10 * 2.54) * 72,
+ in: x => x * 72,
+ px: x => x
+};
+const measurementPattern = /([+-]?\d+\.?\d*)(.*)/;
+function stripQuotes(str) {
+ if (str.startsWith("'") || str.startsWith('"')) {
+ return str.slice(1, -1);
+ }
+ return str;
+}
+function getInteger({
+ data,
+ defaultValue,
+ validate
+}) {
+ if (!data) {
+ return defaultValue;
+ }
+ data = data.trim();
+ const n = parseInt(data, 10);
+ if (!isNaN(n) && validate(n)) {
+ return n;
+ }
+ return defaultValue;
+}
+function getFloat({
+ data,
+ defaultValue,
+ validate
+}) {
+ if (!data) {
+ return defaultValue;
+ }
+ data = data.trim();
+ const n = parseFloat(data);
+ if (!isNaN(n) && validate(n)) {
+ return n;
+ }
+ return defaultValue;
+}
+function getKeyword({
+ data,
+ defaultValue,
+ validate
+}) {
+ if (!data) {
+ return defaultValue;
+ }
+ data = data.trim();
+ if (validate(data)) {
+ return data;
+ }
+ return defaultValue;
+}
+function getStringOption(data, options) {
+ return getKeyword({
+ data,
+ defaultValue: options[0],
+ validate: k => options.includes(k)
+ });
+}
+function getMeasurement(str, def = "0") {
+ def ||= "0";
+ if (!str) {
+ return getMeasurement(def);
+ }
+ const match = str.trim().match(measurementPattern);
+ if (!match) {
+ return getMeasurement(def);
+ }
+ const [, valueStr, unit] = match;
+ const value = parseFloat(valueStr);
+ if (isNaN(value)) {
+ return getMeasurement(def);
+ }
+ if (value === 0) {
+ return 0;
+ }
+ const conv = dimConverters[unit];
+ if (conv) {
+ return conv(value);
+ }
+ return value;
+}
+function getRatio(data) {
+ if (!data) {
+ return {
+ num: 1,
+ den: 1
+ };
+ }
+ const ratio = data.trim().split(/\s*:\s*/).map(x => parseFloat(x)).filter(x => !isNaN(x));
+ if (ratio.length === 1) {
+ ratio.push(1);
+ }
+ if (ratio.length === 0) {
+ return {
+ num: 1,
+ den: 1
+ };
+ }
+ const [num, den] = ratio;
+ return {
+ num,
+ den
+ };
+}
+function getRelevant(data) {
+ if (!data) {
+ return [];
+ }
+ return data.trim().split(/\s+/).map(e => ({
+ excluded: e[0] === "-",
+ viewname: e.substring(1)
+ }));
+}
+function getColor(data, def = [0, 0, 0]) {
+ let [r, g, b] = def;
+ if (!data) {
+ return {
+ r,
+ g,
+ b
+ };
+ }
+ const color = data.trim().split(/\s*,\s*/).map(c => Math.min(Math.max(0, parseInt(c.trim(), 10)), 255)).map(c => isNaN(c) ? 0 : c);
+ if (color.length < 3) {
+ return {
+ r,
+ g,
+ b
+ };
+ }
+ [r, g, b] = color;
+ return {
+ r,
+ g,
+ b
+ };
+}
+function getBBox(data) {
+ const def = -1;
+ if (!data) {
+ return {
+ x: def,
+ y: def,
+ width: def,
+ height: def
+ };
+ }
+ const bbox = data.trim().split(/\s*,\s*/).map(m => getMeasurement(m, "-1"));
+ if (bbox.length < 4 || bbox[2] < 0 || bbox[3] < 0) {
+ return {
+ x: def,
+ y: def,
+ width: def,
+ height: def
+ };
+ }
+ const [x, y, width, height] = bbox;
+ return {
+ x,
+ y,
+ width,
+ height
+ };
+}
+class HTMLResult {
+ static get FAILURE() {
+ return shadow(this, "FAILURE", new HTMLResult(false, null, null, null));
+ }
+ static get EMPTY() {
+ return shadow(this, "EMPTY", new HTMLResult(true, null, null, null));
+ }
+ constructor(success, html, bbox, breakNode) {
+ this.success = success;
+ this.html = html;
+ this.bbox = bbox;
+ this.breakNode = breakNode;
+ }
+ isBreak() {
+ return !!this.breakNode;
+ }
+ static breakNode(node) {
+ return new HTMLResult(false, null, null, node);
+ }
+ static success(html, bbox = null) {
+ return new HTMLResult(true, html, bbox, null);
+ }
+}
+
+;// CONCATENATED MODULE: ./src/core/xfa/fonts.js
+
+
+
+class FontFinder {
+ constructor(pdfFonts) {
+ this.fonts = new Map();
+ this.cache = new Map();
+ this.warned = new Set();
+ this.defaultFont = null;
+ this.add(pdfFonts);
+ }
+ add(pdfFonts, reallyMissingFonts = null) {
+ for (const pdfFont of pdfFonts) {
+ this.addPdfFont(pdfFont);
+ }
+ for (const pdfFont of this.fonts.values()) {
+ if (!pdfFont.regular) {
+ pdfFont.regular = pdfFont.italic || pdfFont.bold || pdfFont.bolditalic;
+ }
+ }
+ if (!reallyMissingFonts || reallyMissingFonts.size === 0) {
+ return;
+ }
+ const myriad = this.fonts.get("PdfJS-Fallback-PdfJS-XFA");
+ for (const missing of reallyMissingFonts) {
+ this.fonts.set(missing, myriad);
+ }
+ }
+ addPdfFont(pdfFont) {
+ const cssFontInfo = pdfFont.cssFontInfo;
+ const name = cssFontInfo.fontFamily;
+ let font = this.fonts.get(name);
+ if (!font) {
+ font = Object.create(null);
+ this.fonts.set(name, font);
+ if (!this.defaultFont) {
+ this.defaultFont = font;
+ }
+ }
+ let property = "";
+ const fontWeight = parseFloat(cssFontInfo.fontWeight);
+ if (parseFloat(cssFontInfo.italicAngle) !== 0) {
+ property = fontWeight >= 700 ? "bolditalic" : "italic";
+ } else if (fontWeight >= 700) {
+ property = "bold";
+ }
+ if (!property) {
+ if (pdfFont.name.includes("Bold") || pdfFont.psName?.includes("Bold")) {
+ property = "bold";
+ }
+ if (pdfFont.name.includes("Italic") || pdfFont.name.endsWith("It") || pdfFont.psName?.includes("Italic") || pdfFont.psName?.endsWith("It")) {
+ property += "italic";
+ }
+ }
+ if (!property) {
+ property = "regular";
+ }
+ font[property] = pdfFont;
+ }
+ getDefault() {
+ return this.defaultFont;
+ }
+ find(fontName, mustWarn = true) {
+ let font = this.fonts.get(fontName) || this.cache.get(fontName);
+ if (font) {
+ return font;
+ }
+ const pattern = /,|-|_| |bolditalic|bold|italic|regular|it/gi;
+ let name = fontName.replaceAll(pattern, "");
+ font = this.fonts.get(name);
+ if (font) {
+ this.cache.set(fontName, font);
+ return font;
+ }
+ name = name.toLowerCase();
+ const maybe = [];
+ for (const [family, pdfFont] of this.fonts.entries()) {
+ if (family.replaceAll(pattern, "").toLowerCase().startsWith(name)) {
+ maybe.push(pdfFont);
+ }
+ }
+ if (maybe.length === 0) {
+ for (const [, pdfFont] of this.fonts.entries()) {
+ if (pdfFont.regular.name?.replaceAll(pattern, "").toLowerCase().startsWith(name)) {
+ maybe.push(pdfFont);
+ }
+ }
+ }
+ if (maybe.length === 0) {
+ name = name.replaceAll(/psmt|mt/gi, "");
+ for (const [family, pdfFont] of this.fonts.entries()) {
+ if (family.replaceAll(pattern, "").toLowerCase().startsWith(name)) {
+ maybe.push(pdfFont);
+ }
+ }
+ }
+ if (maybe.length === 0) {
+ for (const pdfFont of this.fonts.values()) {
+ if (pdfFont.regular.name?.replaceAll(pattern, "").toLowerCase().startsWith(name)) {
+ maybe.push(pdfFont);
+ }
+ }
+ }
+ if (maybe.length >= 1) {
+ if (maybe.length !== 1 && mustWarn) {
+ warn(`XFA - Too many choices to guess the correct font: ${fontName}`);
+ }
+ this.cache.set(fontName, maybe[0]);
+ return maybe[0];
+ }
+ if (mustWarn && !this.warned.has(fontName)) {
+ this.warned.add(fontName);
+ warn(`XFA - Cannot find the font: ${fontName}`);
+ }
+ return null;
+ }
+}
+function selectFont(xfaFont, typeface) {
+ if (xfaFont.posture === "italic") {
+ if (xfaFont.weight === "bold") {
+ return typeface.bolditalic;
+ }
+ return typeface.italic;
+ } else if (xfaFont.weight === "bold") {
+ return typeface.bold;
+ }
+ return typeface.regular;
+}
+function fonts_getMetrics(xfaFont, real = false) {
+ let pdfFont = null;
+ if (xfaFont) {
+ const name = stripQuotes(xfaFont.typeface);
+ const typeface = xfaFont[$globalData].fontFinder.find(name);
+ pdfFont = selectFont(xfaFont, typeface);
+ }
+ if (!pdfFont) {
+ return {
+ lineHeight: 12,
+ lineGap: 2,
+ lineNoGap: 10
+ };
+ }
+ const size = xfaFont.size || 10;
+ const lineHeight = pdfFont.lineHeight ? Math.max(real ? 0 : 1.2, pdfFont.lineHeight) : 1.2;
+ const lineGap = pdfFont.lineGap === undefined ? 0.2 : pdfFont.lineGap;
+ return {
+ lineHeight: lineHeight * size,
+ lineGap: lineGap * size,
+ lineNoGap: Math.max(1, lineHeight - lineGap) * size
+ };
+}
+
+;// CONCATENATED MODULE: ./src/core/xfa/text.js
+
+const WIDTH_FACTOR = 1.02;
+class FontInfo {
+ constructor(xfaFont, margin, lineHeight, fontFinder) {
+ this.lineHeight = lineHeight;
+ this.paraMargin = margin || {
+ top: 0,
+ bottom: 0,
+ left: 0,
+ right: 0
+ };
+ if (!xfaFont) {
+ [this.pdfFont, this.xfaFont] = this.defaultFont(fontFinder);
+ return;
+ }
+ this.xfaFont = {
+ typeface: xfaFont.typeface,
+ posture: xfaFont.posture,
+ weight: xfaFont.weight,
+ size: xfaFont.size,
+ letterSpacing: xfaFont.letterSpacing
+ };
+ const typeface = fontFinder.find(xfaFont.typeface);
+ if (!typeface) {
+ [this.pdfFont, this.xfaFont] = this.defaultFont(fontFinder);
+ return;
+ }
+ this.pdfFont = selectFont(xfaFont, typeface);
+ if (!this.pdfFont) {
+ [this.pdfFont, this.xfaFont] = this.defaultFont(fontFinder);
+ }
+ }
+ defaultFont(fontFinder) {
+ const font = fontFinder.find("Helvetica", false) || fontFinder.find("Myriad Pro", false) || fontFinder.find("Arial", false) || fontFinder.getDefault();
+ if (font?.regular) {
+ const pdfFont = font.regular;
+ const info = pdfFont.cssFontInfo;
+ const xfaFont = {
+ typeface: info.fontFamily,
+ posture: "normal",
+ weight: "normal",
+ size: 10,
+ letterSpacing: 0
+ };
+ return [pdfFont, xfaFont];
+ }
+ const xfaFont = {
+ typeface: "Courier",
+ posture: "normal",
+ weight: "normal",
+ size: 10,
+ letterSpacing: 0
+ };
+ return [null, xfaFont];
+ }
+}
+class FontSelector {
+ constructor(defaultXfaFont, defaultParaMargin, defaultLineHeight, fontFinder) {
+ this.fontFinder = fontFinder;
+ this.stack = [new FontInfo(defaultXfaFont, defaultParaMargin, defaultLineHeight, fontFinder)];
+ }
+ pushData(xfaFont, margin, lineHeight) {
+ const lastFont = this.stack.at(-1);
+ for (const name of ["typeface", "posture", "weight", "size", "letterSpacing"]) {
+ if (!xfaFont[name]) {
+ xfaFont[name] = lastFont.xfaFont[name];
+ }
+ }
+ for (const name of ["top", "bottom", "left", "right"]) {
+ if (isNaN(margin[name])) {
+ margin[name] = lastFont.paraMargin[name];
+ }
+ }
+ const fontInfo = new FontInfo(xfaFont, margin, lineHeight || lastFont.lineHeight, this.fontFinder);
+ if (!fontInfo.pdfFont) {
+ fontInfo.pdfFont = lastFont.pdfFont;
+ }
+ this.stack.push(fontInfo);
+ }
+ popFont() {
+ this.stack.pop();
+ }
+ topFont() {
+ return this.stack.at(-1);
+ }
+}
+class TextMeasure {
+ constructor(defaultXfaFont, defaultParaMargin, defaultLineHeight, fonts) {
+ this.glyphs = [];
+ this.fontSelector = new FontSelector(defaultXfaFont, defaultParaMargin, defaultLineHeight, fonts);
+ this.extraHeight = 0;
+ }
+ pushData(xfaFont, margin, lineHeight) {
+ this.fontSelector.pushData(xfaFont, margin, lineHeight);
+ }
+ popFont(xfaFont) {
+ return this.fontSelector.popFont();
+ }
+ addPara() {
+ const lastFont = this.fontSelector.topFont();
+ this.extraHeight += lastFont.paraMargin.top + lastFont.paraMargin.bottom;
+ }
+ addString(str) {
+ if (!str) {
+ return;
+ }
+ const lastFont = this.fontSelector.topFont();
+ const fontSize = lastFont.xfaFont.size;
+ if (lastFont.pdfFont) {
+ const letterSpacing = lastFont.xfaFont.letterSpacing;
+ const pdfFont = lastFont.pdfFont;
+ const fontLineHeight = pdfFont.lineHeight || 1.2;
+ const lineHeight = lastFont.lineHeight || Math.max(1.2, fontLineHeight) * fontSize;
+ const lineGap = pdfFont.lineGap === undefined ? 0.2 : pdfFont.lineGap;
+ const noGap = fontLineHeight - lineGap;
+ const firstLineHeight = Math.max(1, noGap) * fontSize;
+ const scale = fontSize / 1000;
+ const fallbackWidth = pdfFont.defaultWidth || pdfFont.charsToGlyphs(" ")[0].width;
+ for (const line of str.split(/[\u2029\n]/)) {
+ const encodedLine = pdfFont.encodeString(line).join("");
+ const glyphs = pdfFont.charsToGlyphs(encodedLine);
+ for (const glyph of glyphs) {
+ const width = glyph.width || fallbackWidth;
+ this.glyphs.push([width * scale + letterSpacing, lineHeight, firstLineHeight, glyph.unicode, false]);
+ }
+ this.glyphs.push([0, 0, 0, "\n", true]);
+ }
+ this.glyphs.pop();
+ return;
+ }
+ for (const line of str.split(/[\u2029\n]/)) {
+ for (const char of line.split("")) {
+ this.glyphs.push([fontSize, 1.2 * fontSize, fontSize, char, false]);
+ }
+ this.glyphs.push([0, 0, 0, "\n", true]);
+ }
+ this.glyphs.pop();
+ }
+ compute(maxWidth) {
+ let lastSpacePos = -1,
+ lastSpaceWidth = 0,
+ width = 0,
+ height = 0,
+ currentLineWidth = 0,
+ currentLineHeight = 0;
+ let isBroken = false;
+ let isFirstLine = true;
+ for (let i = 0, ii = this.glyphs.length; i < ii; i++) {
+ const [glyphWidth, lineHeight, firstLineHeight, char, isEOL] = this.glyphs[i];
+ const isSpace = char === " ";
+ const glyphHeight = isFirstLine ? firstLineHeight : lineHeight;
+ if (isEOL) {
+ width = Math.max(width, currentLineWidth);
+ currentLineWidth = 0;
+ height += currentLineHeight;
+ currentLineHeight = glyphHeight;
+ lastSpacePos = -1;
+ lastSpaceWidth = 0;
+ isFirstLine = false;
+ continue;
+ }
+ if (isSpace) {
+ if (currentLineWidth + glyphWidth > maxWidth) {
+ width = Math.max(width, currentLineWidth);
+ currentLineWidth = 0;
+ height += currentLineHeight;
+ currentLineHeight = glyphHeight;
+ lastSpacePos = -1;
+ lastSpaceWidth = 0;
+ isBroken = true;
+ isFirstLine = false;
+ } else {
+ currentLineHeight = Math.max(glyphHeight, currentLineHeight);
+ lastSpaceWidth = currentLineWidth;
+ currentLineWidth += glyphWidth;
+ lastSpacePos = i;
+ }
+ continue;
+ }
+ if (currentLineWidth + glyphWidth > maxWidth) {
+ height += currentLineHeight;
+ currentLineHeight = glyphHeight;
+ if (lastSpacePos !== -1) {
+ i = lastSpacePos;
+ width = Math.max(width, lastSpaceWidth);
+ currentLineWidth = 0;
+ lastSpacePos = -1;
+ lastSpaceWidth = 0;
+ } else {
+ width = Math.max(width, currentLineWidth);
+ currentLineWidth = glyphWidth;
+ }
+ isBroken = true;
+ isFirstLine = false;
+ continue;
+ }
+ currentLineWidth += glyphWidth;
+ currentLineHeight = Math.max(glyphHeight, currentLineHeight);
+ }
+ width = Math.max(width, currentLineWidth);
+ height += currentLineHeight + this.extraHeight;
+ return {
+ width: WIDTH_FACTOR * width,
+ height,
+ isBroken
+ };
+ }
+}
+
+;// CONCATENATED MODULE: ./src/core/xfa/som.js
+
+
+const namePattern = /^[^.[]+/;
+const indexPattern = /^[^\]]+/;
+const operators = {
+ dot: 0,
+ dotDot: 1,
+ dotHash: 2,
+ dotBracket: 3,
+ dotParen: 4
+};
+const shortcuts = new Map([["$data", (root, current) => root.datasets ? root.datasets.data : root], ["$record", (root, current) => (root.datasets ? root.datasets.data : root)[$getChildren]()[0]], ["$template", (root, current) => root.template], ["$connectionSet", (root, current) => root.connectionSet], ["$form", (root, current) => root.form], ["$layout", (root, current) => root.layout], ["$host", (root, current) => root.host], ["$dataWindow", (root, current) => root.dataWindow], ["$event", (root, current) => root.event], ["!", (root, current) => root.datasets], ["$xfa", (root, current) => root], ["xfa", (root, current) => root], ["$", (root, current) => current]]);
+const somCache = new WeakMap();
+function parseIndex(index) {
+ index = index.trim();
+ if (index === "*") {
+ return Infinity;
+ }
+ return parseInt(index, 10) || 0;
+}
+function parseExpression(expr, dotDotAllowed, noExpr = true) {
+ let match = expr.match(namePattern);
+ if (!match) {
+ return null;
+ }
+ let [name] = match;
+ const parsed = [{
+ name,
+ cacheName: "." + name,
+ index: 0,
+ js: null,
+ formCalc: null,
+ operator: operators.dot
+ }];
+ let pos = name.length;
+ while (pos < expr.length) {
+ const spos = pos;
+ const char = expr.charAt(pos++);
+ if (char === "[") {
+ match = expr.slice(pos).match(indexPattern);
+ if (!match) {
+ warn("XFA - Invalid index in SOM expression");
+ return null;
+ }
+ parsed.at(-1).index = parseIndex(match[0]);
+ pos += match[0].length + 1;
+ continue;
+ }
+ let operator;
+ switch (expr.charAt(pos)) {
+ case ".":
+ if (!dotDotAllowed) {
+ return null;
+ }
+ pos++;
+ operator = operators.dotDot;
+ break;
+ case "#":
+ pos++;
+ operator = operators.dotHash;
+ break;
+ case "[":
+ if (noExpr) {
+ warn("XFA - SOM expression contains a FormCalc subexpression which is not supported for now.");
+ return null;
+ }
+ operator = operators.dotBracket;
+ break;
+ case "(":
+ if (noExpr) {
+ warn("XFA - SOM expression contains a JavaScript subexpression which is not supported for now.");
+ return null;
+ }
+ operator = operators.dotParen;
+ break;
+ default:
+ operator = operators.dot;
+ break;
+ }
+ match = expr.slice(pos).match(namePattern);
+ if (!match) {
+ break;
+ }
+ [name] = match;
+ pos += name.length;
+ parsed.push({
+ name,
+ cacheName: expr.slice(spos, pos),
+ operator,
+ index: 0,
+ js: null,
+ formCalc: null
+ });
+ }
+ return parsed;
+}
+function searchNode(root, container, expr, dotDotAllowed = true, useCache = true) {
+ const parsed = parseExpression(expr, dotDotAllowed);
+ if (!parsed) {
+ return null;
+ }
+ const fn = shortcuts.get(parsed[0].name);
+ let i = 0;
+ let isQualified;
+ if (fn) {
+ isQualified = true;
+ root = [fn(root, container)];
+ i = 1;
+ } else {
+ isQualified = container === null;
+ root = [container || root];
+ }
+ for (let ii = parsed.length; i < ii; i++) {
+ const {
+ name,
+ cacheName,
+ operator,
+ index
+ } = parsed[i];
+ const nodes = [];
+ for (const node of root) {
+ if (!node.isXFAObject) {
+ continue;
+ }
+ let children, cached;
+ if (useCache) {
+ cached = somCache.get(node);
+ if (!cached) {
+ cached = new Map();
+ somCache.set(node, cached);
+ }
+ children = cached.get(cacheName);
+ }
+ if (!children) {
+ switch (operator) {
+ case operators.dot:
+ children = node[$getChildrenByName](name, false);
+ break;
+ case operators.dotDot:
+ children = node[$getChildrenByName](name, true);
+ break;
+ case operators.dotHash:
+ children = node[$getChildrenByClass](name);
+ children = children.isXFAObjectArray ? children.children : [children];
+ break;
+ default:
+ break;
+ }
+ if (useCache) {
+ cached.set(cacheName, children);
+ }
+ }
+ if (children.length > 0) {
+ nodes.push(children);
+ }
+ }
+ if (nodes.length === 0 && !isQualified && i === 0) {
+ const parent = container[$getParent]();
+ container = parent;
+ if (!container) {
+ return null;
+ }
+ i = -1;
+ root = [container];
+ continue;
+ }
+ root = isFinite(index) ? nodes.filter(node => index < node.length).map(node => node[index]) : nodes.flat();
+ }
+ if (root.length === 0) {
+ return null;
+ }
+ return root;
+}
+function createDataNode(root, container, expr) {
+ const parsed = parseExpression(expr);
+ if (!parsed) {
+ return null;
+ }
+ if (parsed.some(x => x.operator === operators.dotDot)) {
+ return null;
+ }
+ const fn = shortcuts.get(parsed[0].name);
+ let i = 0;
+ if (fn) {
+ root = fn(root, container);
+ i = 1;
+ } else {
+ root = container || root;
+ }
+ for (let ii = parsed.length; i < ii; i++) {
+ const {
+ name,
+ operator,
+ index
+ } = parsed[i];
+ if (!isFinite(index)) {
+ parsed[i].index = 0;
+ return root.createNodes(parsed.slice(i));
+ }
+ let children;
+ switch (operator) {
+ case operators.dot:
+ children = root[$getChildrenByName](name, false);
+ break;
+ case operators.dotDot:
+ children = root[$getChildrenByName](name, true);
+ break;
+ case operators.dotHash:
+ children = root[$getChildrenByClass](name);
+ children = children.isXFAObjectArray ? children.children : [children];
+ break;
+ default:
+ break;
+ }
+ if (children.length === 0) {
+ return root.createNodes(parsed.slice(i));
+ }
+ if (index < children.length) {
+ const child = children[index];
+ if (!child.isXFAObject) {
+ warn(`XFA - Cannot create a node.`);
+ return null;
+ }
+ root = child;
+ } else {
+ parsed[i].index = index - children.length;
+ return root.createNodes(parsed.slice(i));
+ }
+ }
+ return null;
+}
+
+;// CONCATENATED MODULE: ./src/core/xfa/xfa_object.js
+
+
+
+
+
+
+const _applyPrototype = Symbol();
+const _attributes = Symbol();
+const _attributeNames = Symbol();
+const _children = Symbol("_children");
+const _cloneAttribute = Symbol();
+const _dataValue = Symbol();
+const _defaultValue = Symbol();
+const _filteredChildrenGenerator = Symbol();
+const _getPrototype = Symbol();
+const _getUnsetAttributes = Symbol();
+const _hasChildren = Symbol();
+const _max = Symbol();
+const _options = Symbol();
+const _parent = Symbol("parent");
+const _resolvePrototypesHelper = Symbol();
+const _setAttributes = Symbol();
+const _validator = Symbol();
+let uid = 0;
+const NS_DATASETS = NamespaceIds.datasets.id;
+class XFAObject {
+ constructor(nsId, name, hasChildren = false) {
+ this[$namespaceId] = nsId;
+ this[$nodeName] = name;
+ this[_hasChildren] = hasChildren;
+ this[_parent] = null;
+ this[_children] = [];
+ this[$uid] = `${name}${uid++}`;
+ this[$globalData] = null;
+ }
+ get isXFAObject() {
+ return true;
+ }
+ get isXFAObjectArray() {
+ return false;
+ }
+ createNodes(path) {
+ let root = this,
+ node = null;
+ for (const {
+ name,
+ index
+ } of path) {
+ for (let i = 0, ii = isFinite(index) ? index : 0; i <= ii; i++) {
+ const nsId = root[$namespaceId] === NS_DATASETS ? -1 : root[$namespaceId];
+ node = new XmlObject(nsId, name);
+ root[$appendChild](node);
+ }
+ root = node;
+ }
+ return node;
+ }
+ [$onChild](child) {
+ if (!this[_hasChildren] || !this[$onChildCheck](child)) {
+ return false;
+ }
+ const name = child[$nodeName];
+ const node = this[name];
+ if (node instanceof XFAObjectArray) {
+ if (node.push(child)) {
+ this[$appendChild](child);
+ return true;
+ }
+ } else {
+ if (node !== null) {
+ this[$removeChild](node);
+ }
+ this[name] = child;
+ this[$appendChild](child);
+ return true;
+ }
+ let id = "";
+ if (this.id) {
+ id = ` (id: ${this.id})`;
+ } else if (this.name) {
+ id = ` (name: ${this.name} ${this.h.value})`;
+ }
+ warn(`XFA - node "${this[$nodeName]}"${id} has already enough "${name}"!`);
+ return false;
+ }
+ [$onChildCheck](child) {
+ return this.hasOwnProperty(child[$nodeName]) && child[$namespaceId] === this[$namespaceId];
+ }
+ [$isNsAgnostic]() {
+ return false;
+ }
+ [$acceptWhitespace]() {
+ return false;
+ }
+ [$isCDATAXml]() {
+ return false;
+ }
+ [$isBindable]() {
+ return false;
+ }
+ [$popPara]() {
+ if (this.para) {
+ this[$getTemplateRoot]()[$extra].paraStack.pop();
+ }
+ }
+ [$pushPara]() {
+ this[$getTemplateRoot]()[$extra].paraStack.push(this.para);
+ }
+ [$setId](ids) {
+ if (this.id && this[$namespaceId] === NamespaceIds.template.id) {
+ ids.set(this.id, this);
+ }
+ }
+ [$getTemplateRoot]() {
+ return this[$globalData].template;
+ }
+ [$isSplittable]() {
+ return false;
+ }
+ [$isThereMoreWidth]() {
+ return false;
+ }
+ [$appendChild](child) {
+ child[_parent] = this;
+ this[_children].push(child);
+ if (!child[$globalData] && this[$globalData]) {
+ child[$globalData] = this[$globalData];
+ }
+ }
+ [$removeChild](child) {
+ const i = this[_children].indexOf(child);
+ this[_children].splice(i, 1);
+ }
+ [$hasSettableValue]() {
+ return this.hasOwnProperty("value");
+ }
+ [$setValue](_) {}
+ [$onText](_) {}
+ [$finalize]() {}
+ [$clean](builder) {
+ delete this[_hasChildren];
+ if (this[$cleanup]) {
+ builder.clean(this[$cleanup]);
+ delete this[$cleanup];
+ }
+ }
+ [$indexOf](child) {
+ return this[_children].indexOf(child);
+ }
+ [$insertAt](i, child) {
+ child[_parent] = this;
+ this[_children].splice(i, 0, child);
+ if (!child[$globalData] && this[$globalData]) {
+ child[$globalData] = this[$globalData];
+ }
+ }
+ [$isTransparent]() {
+ return !this.name;
+ }
+ [$lastAttribute]() {
+ return "";
+ }
+ [$text]() {
+ if (this[_children].length === 0) {
+ return this[$content];
+ }
+ return this[_children].map(c => c[$text]()).join("");
+ }
+ get [_attributeNames]() {
+ const proto = Object.getPrototypeOf(this);
+ if (!proto._attributes) {
+ const attributes = proto._attributes = new Set();
+ for (const name of Object.getOwnPropertyNames(this)) {
+ if (this[name] === null || this[name] instanceof XFAObject || this[name] instanceof XFAObjectArray) {
+ break;
+ }
+ attributes.add(name);
+ }
+ }
+ return shadow(this, _attributeNames, proto._attributes);
+ }
+ [$isDescendent](parent) {
+ let node = this;
+ while (node) {
+ if (node === parent) {
+ return true;
+ }
+ node = node[$getParent]();
+ }
+ return false;
+ }
+ [$getParent]() {
+ return this[_parent];
+ }
+ [$getSubformParent]() {
+ return this[$getParent]();
+ }
+ [$getChildren](name = null) {
+ if (!name) {
+ return this[_children];
+ }
+ return this[name];
+ }
+ [$dump]() {
+ const dumped = Object.create(null);
+ if (this[$content]) {
+ dumped.$content = this[$content];
+ }
+ for (const name of Object.getOwnPropertyNames(this)) {
+ const value = this[name];
+ if (value === null) {
+ continue;
+ }
+ if (value instanceof XFAObject) {
+ dumped[name] = value[$dump]();
+ } else if (value instanceof XFAObjectArray) {
+ if (!value.isEmpty()) {
+ dumped[name] = value.dump();
+ }
+ } else {
+ dumped[name] = value;
+ }
+ }
+ return dumped;
+ }
+ [$toStyle]() {
+ return null;
+ }
+ [$toHTML]() {
+ return HTMLResult.EMPTY;
+ }
+ *[$getContainedChildren]() {
+ for (const node of this[$getChildren]()) {
+ yield node;
+ }
+ }
+ *[_filteredChildrenGenerator](filter, include) {
+ for (const node of this[$getContainedChildren]()) {
+ if (!filter || include === filter.has(node[$nodeName])) {
+ const availableSpace = this[$getAvailableSpace]();
+ const res = node[$toHTML](availableSpace);
+ if (!res.success) {
+ this[$extra].failingNode = node;
+ }
+ yield res;
+ }
+ }
+ }
+ [$flushHTML]() {
+ return null;
+ }
+ [$addHTML](html, bbox) {
+ this[$extra].children.push(html);
+ }
+ [$getAvailableSpace]() {}
+ [$childrenToHTML]({
+ filter = null,
+ include = true
+ }) {
+ if (!this[$extra].generator) {
+ this[$extra].generator = this[_filteredChildrenGenerator](filter, include);
+ } else {
+ const availableSpace = this[$getAvailableSpace]();
+ const res = this[$extra].failingNode[$toHTML](availableSpace);
+ if (!res.success) {
+ return res;
+ }
+ if (res.html) {
+ this[$addHTML](res.html, res.bbox);
+ }
+ delete this[$extra].failingNode;
+ }
+ while (true) {
+ const gen = this[$extra].generator.next();
+ if (gen.done) {
+ break;
+ }
+ const res = gen.value;
+ if (!res.success) {
+ return res;
+ }
+ if (res.html) {
+ this[$addHTML](res.html, res.bbox);
+ }
+ }
+ this[$extra].generator = null;
+ return HTMLResult.EMPTY;
+ }
+ [$setSetAttributes](attributes) {
+ this[_setAttributes] = new Set(Object.keys(attributes));
+ }
+ [_getUnsetAttributes](protoAttributes) {
+ const allAttr = this[_attributeNames];
+ const setAttr = this[_setAttributes];
+ return [...protoAttributes].filter(x => allAttr.has(x) && !setAttr.has(x));
+ }
+ [$resolvePrototypes](ids, ancestors = new Set()) {
+ for (const child of this[_children]) {
+ child[_resolvePrototypesHelper](ids, ancestors);
+ }
+ }
+ [_resolvePrototypesHelper](ids, ancestors) {
+ const proto = this[_getPrototype](ids, ancestors);
+ if (proto) {
+ this[_applyPrototype](proto, ids, ancestors);
+ } else {
+ this[$resolvePrototypes](ids, ancestors);
+ }
+ }
+ [_getPrototype](ids, ancestors) {
+ const {
+ use,
+ usehref
+ } = this;
+ if (!use && !usehref) {
+ return null;
+ }
+ let proto = null;
+ let somExpression = null;
+ let id = null;
+ let ref = use;
+ if (usehref) {
+ ref = usehref;
+ if (usehref.startsWith("#som(") && usehref.endsWith(")")) {
+ somExpression = usehref.slice("#som(".length, -1);
+ } else if (usehref.startsWith(".#som(") && usehref.endsWith(")")) {
+ somExpression = usehref.slice(".#som(".length, -1);
+ } else if (usehref.startsWith("#")) {
+ id = usehref.slice(1);
+ } else if (usehref.startsWith(".#")) {
+ id = usehref.slice(2);
+ }
+ } else if (use.startsWith("#")) {
+ id = use.slice(1);
+ } else {
+ somExpression = use;
+ }
+ this.use = this.usehref = "";
+ if (id) {
+ proto = ids.get(id);
+ } else {
+ proto = searchNode(ids.get($root), this, somExpression, true, false);
+ if (proto) {
+ proto = proto[0];
+ }
+ }
+ if (!proto) {
+ warn(`XFA - Invalid prototype reference: ${ref}.`);
+ return null;
+ }
+ if (proto[$nodeName] !== this[$nodeName]) {
+ warn(`XFA - Incompatible prototype: ${proto[$nodeName]} !== ${this[$nodeName]}.`);
+ return null;
+ }
+ if (ancestors.has(proto)) {
+ warn(`XFA - Cycle detected in prototypes use.`);
+ return null;
+ }
+ ancestors.add(proto);
+ const protoProto = proto[_getPrototype](ids, ancestors);
+ if (protoProto) {
+ proto[_applyPrototype](protoProto, ids, ancestors);
+ }
+ proto[$resolvePrototypes](ids, ancestors);
+ ancestors.delete(proto);
+ return proto;
+ }
+ [_applyPrototype](proto, ids, ancestors) {
+ if (ancestors.has(proto)) {
+ warn(`XFA - Cycle detected in prototypes use.`);
+ return;
+ }
+ if (!this[$content] && proto[$content]) {
+ this[$content] = proto[$content];
+ }
+ const newAncestors = new Set(ancestors);
+ newAncestors.add(proto);
+ for (const unsetAttrName of this[_getUnsetAttributes](proto[_setAttributes])) {
+ this[unsetAttrName] = proto[unsetAttrName];
+ if (this[_setAttributes]) {
+ this[_setAttributes].add(unsetAttrName);
+ }
+ }
+ for (const name of Object.getOwnPropertyNames(this)) {
+ if (this[_attributeNames].has(name)) {
+ continue;
+ }
+ const value = this[name];
+ const protoValue = proto[name];
+ if (value instanceof XFAObjectArray) {
+ for (const child of value[_children]) {
+ child[_resolvePrototypesHelper](ids, ancestors);
+ }
+ for (let i = value[_children].length, ii = protoValue[_children].length; i < ii; i++) {
+ const child = proto[_children][i][$clone]();
+ if (value.push(child)) {
+ child[_parent] = this;
+ this[_children].push(child);
+ child[_resolvePrototypesHelper](ids, ancestors);
+ } else {
+ break;
+ }
+ }
+ continue;
+ }
+ if (value !== null) {
+ value[$resolvePrototypes](ids, ancestors);
+ if (protoValue) {
+ value[_applyPrototype](protoValue, ids, ancestors);
+ }
+ continue;
+ }
+ if (protoValue !== null) {
+ const child = protoValue[$clone]();
+ child[_parent] = this;
+ this[name] = child;
+ this[_children].push(child);
+ child[_resolvePrototypesHelper](ids, ancestors);
+ }
+ }
+ }
+ static [_cloneAttribute](obj) {
+ if (Array.isArray(obj)) {
+ return obj.map(x => XFAObject[_cloneAttribute](x));
+ }
+ if (typeof obj === "object" && obj !== null) {
+ return Object.assign({}, obj);
+ }
+ return obj;
+ }
+ [$clone]() {
+ const clone = Object.create(Object.getPrototypeOf(this));
+ for (const $symbol of Object.getOwnPropertySymbols(this)) {
+ try {
+ clone[$symbol] = this[$symbol];
+ } catch {
+ shadow(clone, $symbol, this[$symbol]);
+ }
+ }
+ clone[$uid] = `${clone[$nodeName]}${uid++}`;
+ clone[_children] = [];
+ for (const name of Object.getOwnPropertyNames(this)) {
+ if (this[_attributeNames].has(name)) {
+ clone[name] = XFAObject[_cloneAttribute](this[name]);
+ continue;
+ }
+ const value = this[name];
+ clone[name] = value instanceof XFAObjectArray ? new XFAObjectArray(value[_max]) : null;
+ }
+ for (const child of this[_children]) {
+ const name = child[$nodeName];
+ const clonedChild = child[$clone]();
+ clone[_children].push(clonedChild);
+ clonedChild[_parent] = clone;
+ if (clone[name] === null) {
+ clone[name] = clonedChild;
+ } else {
+ clone[name][_children].push(clonedChild);
+ }
+ }
+ return clone;
+ }
+ [$getChildren](name = null) {
+ if (!name) {
+ return this[_children];
+ }
+ return this[_children].filter(c => c[$nodeName] === name);
+ }
+ [$getChildrenByClass](name) {
+ return this[name];
+ }
+ [$getChildrenByName](name, allTransparent, first = true) {
+ return Array.from(this[$getChildrenByNameIt](name, allTransparent, first));
+ }
+ *[$getChildrenByNameIt](name, allTransparent, first = true) {
+ if (name === "parent") {
+ yield this[_parent];
+ return;
+ }
+ for (const child of this[_children]) {
+ if (child[$nodeName] === name) {
+ yield child;
+ }
+ if (child.name === name) {
+ yield child;
+ }
+ if (allTransparent || child[$isTransparent]()) {
+ yield* child[$getChildrenByNameIt](name, allTransparent, false);
+ }
+ }
+ if (first && this[_attributeNames].has(name)) {
+ yield new XFAAttribute(this, name, this[name]);
+ }
+ }
+}
+class XFAObjectArray {
+ constructor(max = Infinity) {
+ this[_max] = max;
+ this[_children] = [];
+ }
+ get isXFAObject() {
+ return false;
+ }
+ get isXFAObjectArray() {
+ return true;
+ }
+ push(child) {
+ const len = this[_children].length;
+ if (len <= this[_max]) {
+ this[_children].push(child);
+ return true;
+ }
+ warn(`XFA - node "${child[$nodeName]}" accepts no more than ${this[_max]} children`);
+ return false;
+ }
+ isEmpty() {
+ return this[_children].length === 0;
+ }
+ dump() {
+ return this[_children].length === 1 ? this[_children][0][$dump]() : this[_children].map(x => x[$dump]());
+ }
+ [$clone]() {
+ const clone = new XFAObjectArray(this[_max]);
+ clone[_children] = this[_children].map(c => c[$clone]());
+ return clone;
+ }
+ get children() {
+ return this[_children];
+ }
+ clear() {
+ this[_children].length = 0;
+ }
+}
+class XFAAttribute {
+ constructor(node, name, value) {
+ this[_parent] = node;
+ this[$nodeName] = name;
+ this[$content] = value;
+ this[$consumed] = false;
+ this[$uid] = `attribute${uid++}`;
+ }
+ [$getParent]() {
+ return this[_parent];
+ }
+ [$isDataValue]() {
+ return true;
+ }
+ [$getDataValue]() {
+ return this[$content].trim();
+ }
+ [$setValue](value) {
+ value = value.value || "";
+ this[$content] = value.toString();
+ }
+ [$text]() {
+ return this[$content];
+ }
+ [$isDescendent](parent) {
+ return this[_parent] === parent || this[_parent][$isDescendent](parent);
+ }
+}
+class XmlObject extends XFAObject {
+ constructor(nsId, name, attributes = {}) {
+ super(nsId, name);
+ this[$content] = "";
+ this[_dataValue] = null;
+ if (name !== "#text") {
+ const map = new Map();
+ this[_attributes] = map;
+ for (const [attrName, value] of Object.entries(attributes)) {
+ map.set(attrName, new XFAAttribute(this, attrName, value));
+ }
+ if (attributes.hasOwnProperty($nsAttributes)) {
+ const dataNode = attributes[$nsAttributes].xfa.dataNode;
+ if (dataNode !== undefined) {
+ if (dataNode === "dataGroup") {
+ this[_dataValue] = false;
+ } else if (dataNode === "dataValue") {
+ this[_dataValue] = true;
+ }
+ }
+ }
+ }
+ this[$consumed] = false;
+ }
+ [$toString](buf) {
+ const tagName = this[$nodeName];
+ if (tagName === "#text") {
+ buf.push(encodeToXmlString(this[$content]));
+ return;
+ }
+ const utf8TagName = utf8StringToString(tagName);
+ const prefix = this[$namespaceId] === NS_DATASETS ? "xfa:" : "";
+ buf.push(`<${prefix}${utf8TagName}`);
+ for (const [name, value] of this[_attributes].entries()) {
+ const utf8Name = utf8StringToString(name);
+ buf.push(` ${utf8Name}="${encodeToXmlString(value[$content])}"`);
+ }
+ if (this[_dataValue] !== null) {
+ if (this[_dataValue]) {
+ buf.push(` xfa:dataNode="dataValue"`);
+ } else {
+ buf.push(` xfa:dataNode="dataGroup"`);
+ }
+ }
+ if (!this[$content] && this[_children].length === 0) {
+ buf.push("/>");
+ return;
+ }
+ buf.push(">");
+ if (this[$content]) {
+ if (typeof this[$content] === "string") {
+ buf.push(encodeToXmlString(this[$content]));
+ } else {
+ this[$content][$toString](buf);
+ }
+ } else {
+ for (const child of this[_children]) {
+ child[$toString](buf);
+ }
+ }
+ buf.push(`</${prefix}${utf8TagName}>`);
+ }
+ [$onChild](child) {
+ if (this[$content]) {
+ const node = new XmlObject(this[$namespaceId], "#text");
+ this[$appendChild](node);
+ node[$content] = this[$content];
+ this[$content] = "";
+ }
+ this[$appendChild](child);
+ return true;
+ }
+ [$onText](str) {
+ this[$content] += str;
+ }
+ [$finalize]() {
+ if (this[$content] && this[_children].length > 0) {
+ const node = new XmlObject(this[$namespaceId], "#text");
+ this[$appendChild](node);
+ node[$content] = this[$content];
+ delete this[$content];
+ }
+ }
+ [$toHTML]() {
+ if (this[$nodeName] === "#text") {
+ return HTMLResult.success({
+ name: "#text",
+ value: this[$content]
+ });
+ }
+ return HTMLResult.EMPTY;
+ }
+ [$getChildren](name = null) {
+ if (!name) {
+ return this[_children];
+ }
+ return this[_children].filter(c => c[$nodeName] === name);
+ }
+ [$getAttributes]() {
+ return this[_attributes];
+ }
+ [$getChildrenByClass](name) {
+ const value = this[_attributes].get(name);
+ if (value !== undefined) {
+ return value;
+ }
+ return this[$getChildren](name);
+ }
+ *[$getChildrenByNameIt](name, allTransparent) {
+ const value = this[_attributes].get(name);
+ if (value) {
+ yield value;
+ }
+ for (const child of this[_children]) {
+ if (child[$nodeName] === name) {
+ yield child;
+ }
+ if (allTransparent) {
+ yield* child[$getChildrenByNameIt](name, allTransparent);
+ }
+ }
+ }
+ *[$getAttributeIt](name, skipConsumed) {
+ const value = this[_attributes].get(name);
+ if (value && (!skipConsumed || !value[$consumed])) {
+ yield value;
+ }
+ for (const child of this[_children]) {
+ yield* child[$getAttributeIt](name, skipConsumed);
+ }
+ }
+ *[$getRealChildrenByNameIt](name, allTransparent, skipConsumed) {
+ for (const child of this[_children]) {
+ if (child[$nodeName] === name && (!skipConsumed || !child[$consumed])) {
+ yield child;
+ }
+ if (allTransparent) {
+ yield* child[$getRealChildrenByNameIt](name, allTransparent, skipConsumed);
+ }
+ }
+ }
+ [$isDataValue]() {
+ if (this[_dataValue] === null) {
+ return this[_children].length === 0 || this[_children][0][$namespaceId] === NamespaceIds.xhtml.id;
+ }
+ return this[_dataValue];
+ }
+ [$getDataValue]() {
+ if (this[_dataValue] === null) {
+ if (this[_children].length === 0) {
+ return this[$content].trim();
+ }
+ if (this[_children][0][$namespaceId] === NamespaceIds.xhtml.id) {
+ return this[_children][0][$text]().trim();
+ }
+ return null;
+ }
+ return this[$content].trim();
+ }
+ [$setValue](value) {
+ value = value.value || "";
+ this[$content] = value.toString();
+ }
+ [$dump](hasNS = false) {
+ const dumped = Object.create(null);
+ if (hasNS) {
+ dumped.$ns = this[$namespaceId];
+ }
+ if (this[$content]) {
+ dumped.$content = this[$content];
+ }
+ dumped.$name = this[$nodeName];
+ dumped.children = [];
+ for (const child of this[_children]) {
+ dumped.children.push(child[$dump](hasNS));
+ }
+ dumped.attributes = Object.create(null);
+ for (const [name, value] of this[_attributes]) {
+ dumped.attributes[name] = value[$content];
+ }
+ return dumped;
+ }
+}
+class ContentObject extends XFAObject {
+ constructor(nsId, name) {
+ super(nsId, name);
+ this[$content] = "";
+ }
+ [$onText](text) {
+ this[$content] += text;
+ }
+ [$finalize]() {}
+}
+class OptionObject extends ContentObject {
+ constructor(nsId, name, options) {
+ super(nsId, name);
+ this[_options] = options;
+ }
+ [$finalize]() {
+ this[$content] = getKeyword({
+ data: this[$content],
+ defaultValue: this[_options][0],
+ validate: k => this[_options].includes(k)
+ });
+ }
+ [$clean](builder) {
+ super[$clean](builder);
+ delete this[_options];
+ }
+}
+class StringObject extends ContentObject {
+ [$finalize]() {
+ this[$content] = this[$content].trim();
+ }
+}
+class IntegerObject extends ContentObject {
+ constructor(nsId, name, defaultValue, validator) {
+ super(nsId, name);
+ this[_defaultValue] = defaultValue;
+ this[_validator] = validator;
+ }
+ [$finalize]() {
+ this[$content] = getInteger({
+ data: this[$content],
+ defaultValue: this[_defaultValue],
+ validate: this[_validator]
+ });
+ }
+ [$clean](builder) {
+ super[$clean](builder);
+ delete this[_defaultValue];
+ delete this[_validator];
+ }
+}
+class Option01 extends IntegerObject {
+ constructor(nsId, name) {
+ super(nsId, name, 0, n => n === 1);
+ }
+}
+class Option10 extends IntegerObject {
+ constructor(nsId, name) {
+ super(nsId, name, 1, n => n === 0);
+ }
+}
+
+;// CONCATENATED MODULE: ./src/core/xfa/html_utils.js
+
+
+
+
+
+
+function measureToString(m) {
+ if (typeof m === "string") {
+ return "0px";
+ }
+ return Number.isInteger(m) ? `${m}px` : `${m.toFixed(2)}px`;
+}
+const converters = {
+ anchorType(node, style) {
+ const parent = node[$getSubformParent]();
+ if (!parent || parent.layout && parent.layout !== "position") {
+ return;
+ }
+ if (!("transform" in style)) {
+ style.transform = "";
+ }
+ switch (node.anchorType) {
+ case "bottomCenter":
+ style.transform += "translate(-50%, -100%)";
+ break;
+ case "bottomLeft":
+ style.transform += "translate(0,-100%)";
+ break;
+ case "bottomRight":
+ style.transform += "translate(-100%,-100%)";
+ break;
+ case "middleCenter":
+ style.transform += "translate(-50%,-50%)";
+ break;
+ case "middleLeft":
+ style.transform += "translate(0,-50%)";
+ break;
+ case "middleRight":
+ style.transform += "translate(-100%,-50%)";
+ break;
+ case "topCenter":
+ style.transform += "translate(-50%,0)";
+ break;
+ case "topRight":
+ style.transform += "translate(-100%,0)";
+ break;
+ }
+ },
+ dimensions(node, style) {
+ const parent = node[$getSubformParent]();
+ let width = node.w;
+ const height = node.h;
+ if (parent.layout?.includes("row")) {
+ const extra = parent[$extra];
+ const colSpan = node.colSpan;
+ let w;
+ if (colSpan === -1) {
+ w = extra.columnWidths.slice(extra.currentColumn).reduce((a, x) => a + x, 0);
+ extra.currentColumn = 0;
+ } else {
+ w = extra.columnWidths.slice(extra.currentColumn, extra.currentColumn + colSpan).reduce((a, x) => a + x, 0);
+ extra.currentColumn = (extra.currentColumn + node.colSpan) % extra.columnWidths.length;
+ }
+ if (!isNaN(w)) {
+ width = node.w = w;
+ }
+ }
+ style.width = width !== "" ? measureToString(width) : "auto";
+ style.height = height !== "" ? measureToString(height) : "auto";
+ },
+ position(node, style) {
+ const parent = node[$getSubformParent]();
+ if (parent?.layout && parent.layout !== "position") {
+ return;
+ }
+ style.position = "absolute";
+ style.left = measureToString(node.x);
+ style.top = measureToString(node.y);
+ },
+ rotate(node, style) {
+ if (node.rotate) {
+ if (!("transform" in style)) {
+ style.transform = "";
+ }
+ style.transform += `rotate(-${node.rotate}deg)`;
+ style.transformOrigin = "top left";
+ }
+ },
+ presence(node, style) {
+ switch (node.presence) {
+ case "invisible":
+ style.visibility = "hidden";
+ break;
+ case "hidden":
+ case "inactive":
+ style.display = "none";
+ break;
+ }
+ },
+ hAlign(node, style) {
+ if (node[$nodeName] === "para") {
+ switch (node.hAlign) {
+ case "justifyAll":
+ style.textAlign = "justify-all";
+ break;
+ case "radix":
+ style.textAlign = "left";
+ break;
+ default:
+ style.textAlign = node.hAlign;
+ }
+ } else {
+ switch (node.hAlign) {
+ case "left":
+ style.alignSelf = "start";
+ break;
+ case "center":
+ style.alignSelf = "center";
+ break;
+ case "right":
+ style.alignSelf = "end";
+ break;
+ }
+ }
+ },
+ margin(node, style) {
+ if (node.margin) {
+ style.margin = node.margin[$toStyle]().margin;
+ }
+ }
+};
+function setMinMaxDimensions(node, style) {
+ const parent = node[$getSubformParent]();
+ if (parent.layout === "position") {
+ if (node.minW > 0) {
+ style.minWidth = measureToString(node.minW);
+ }
+ if (node.maxW > 0) {
+ style.maxWidth = measureToString(node.maxW);
+ }
+ if (node.minH > 0) {
+ style.minHeight = measureToString(node.minH);
+ }
+ if (node.maxH > 0) {
+ style.maxHeight = measureToString(node.maxH);
+ }
+ }
+}
+function layoutText(text, xfaFont, margin, lineHeight, fontFinder, width) {
+ const measure = new TextMeasure(xfaFont, margin, lineHeight, fontFinder);
+ if (typeof text === "string") {
+ measure.addString(text);
+ } else {
+ text[$pushGlyphs](measure);
+ }
+ return measure.compute(width);
+}
+function layoutNode(node, availableSpace) {
+ let height = null;
+ let width = null;
+ let isBroken = false;
+ if ((!node.w || !node.h) && node.value) {
+ let marginH = 0;
+ let marginV = 0;
+ if (node.margin) {
+ marginH = node.margin.leftInset + node.margin.rightInset;
+ marginV = node.margin.topInset + node.margin.bottomInset;
+ }
+ let lineHeight = null;
+ let margin = null;
+ if (node.para) {
+ margin = Object.create(null);
+ lineHeight = node.para.lineHeight === "" ? null : node.para.lineHeight;
+ margin.top = node.para.spaceAbove === "" ? 0 : node.para.spaceAbove;
+ margin.bottom = node.para.spaceBelow === "" ? 0 : node.para.spaceBelow;
+ margin.left = node.para.marginLeft === "" ? 0 : node.para.marginLeft;
+ margin.right = node.para.marginRight === "" ? 0 : node.para.marginRight;
+ }
+ let font = node.font;
+ if (!font) {
+ const root = node[$getTemplateRoot]();
+ let parent = node[$getParent]();
+ while (parent && parent !== root) {
+ if (parent.font) {
+ font = parent.font;
+ break;
+ }
+ parent = parent[$getParent]();
+ }
+ }
+ const maxWidth = (node.w || availableSpace.width) - marginH;
+ const fontFinder = node[$globalData].fontFinder;
+ if (node.value.exData && node.value.exData[$content] && node.value.exData.contentType === "text/html") {
+ const res = layoutText(node.value.exData[$content], font, margin, lineHeight, fontFinder, maxWidth);
+ width = res.width;
+ height = res.height;
+ isBroken = res.isBroken;
+ } else {
+ const text = node.value[$text]();
+ if (text) {
+ const res = layoutText(text, font, margin, lineHeight, fontFinder, maxWidth);
+ width = res.width;
+ height = res.height;
+ isBroken = res.isBroken;
+ }
+ }
+ if (width !== null && !node.w) {
+ width += marginH;
+ }
+ if (height !== null && !node.h) {
+ height += marginV;
+ }
+ }
+ return {
+ w: width,
+ h: height,
+ isBroken
+ };
+}
+function computeBbox(node, html, availableSpace) {
+ let bbox;
+ if (node.w !== "" && node.h !== "") {
+ bbox = [node.x, node.y, node.w, node.h];
+ } else {
+ if (!availableSpace) {
+ return null;
+ }
+ let width = node.w;
+ if (width === "") {
+ if (node.maxW === 0) {
+ const parent = node[$getSubformParent]();
+ width = parent.layout === "position" && parent.w !== "" ? 0 : node.minW;
+ } else {
+ width = Math.min(node.maxW, availableSpace.width);
+ }
+ html.attributes.style.width = measureToString(width);
+ }
+ let height = node.h;
+ if (height === "") {
+ if (node.maxH === 0) {
+ const parent = node[$getSubformParent]();
+ height = parent.layout === "position" && parent.h !== "" ? 0 : node.minH;
+ } else {
+ height = Math.min(node.maxH, availableSpace.height);
+ }
+ html.attributes.style.height = measureToString(height);
+ }
+ bbox = [node.x, node.y, width, height];
+ }
+ return bbox;
+}
+function fixDimensions(node) {
+ const parent = node[$getSubformParent]();
+ if (parent.layout?.includes("row")) {
+ const extra = parent[$extra];
+ const colSpan = node.colSpan;
+ let width;
+ if (colSpan === -1) {
+ width = extra.columnWidths.slice(extra.currentColumn).reduce((a, w) => a + w, 0);
+ } else {
+ width = extra.columnWidths.slice(extra.currentColumn, extra.currentColumn + colSpan).reduce((a, w) => a + w, 0);
+ }
+ if (!isNaN(width)) {
+ node.w = width;
+ }
+ }
+ if (parent.layout && parent.layout !== "position") {
+ node.x = node.y = 0;
+ }
+ if (node.layout === "table") {
+ if (node.w === "" && Array.isArray(node.columnWidths)) {
+ node.w = node.columnWidths.reduce((a, x) => a + x, 0);
+ }
+ }
+}
+function layoutClass(node) {
+ switch (node.layout) {
+ case "position":
+ return "xfaPosition";
+ case "lr-tb":
+ return "xfaLrTb";
+ case "rl-row":
+ return "xfaRlRow";
+ case "rl-tb":
+ return "xfaRlTb";
+ case "row":
+ return "xfaRow";
+ case "table":
+ return "xfaTable";
+ case "tb":
+ return "xfaTb";
+ default:
+ return "xfaPosition";
+ }
+}
+function toStyle(node, ...names) {
+ const style = Object.create(null);
+ for (const name of names) {
+ const value = node[name];
+ if (value === null) {
+ continue;
+ }
+ if (converters.hasOwnProperty(name)) {
+ converters[name](node, style);
+ continue;
+ }
+ if (value instanceof XFAObject) {
+ const newStyle = value[$toStyle]();
+ if (newStyle) {
+ Object.assign(style, newStyle);
+ } else {
+ warn(`(DEBUG) - XFA - style for ${name} not implemented yet`);
+ }
+ }
+ }
+ return style;
+}
+function createWrapper(node, html) {
+ const {
+ attributes
+ } = html;
+ const {
+ style
+ } = attributes;
+ const wrapper = {
+ name: "div",
+ attributes: {
+ class: ["xfaWrapper"],
+ style: Object.create(null)
+ },
+ children: []
+ };
+ attributes.class.push("xfaWrapped");
+ if (node.border) {
+ const {
+ widths,
+ insets
+ } = node.border[$extra];
+ let width, height;
+ let top = insets[0];
+ let left = insets[3];
+ const insetsH = insets[0] + insets[2];
+ const insetsW = insets[1] + insets[3];
+ switch (node.border.hand) {
+ case "even":
+ top -= widths[0] / 2;
+ left -= widths[3] / 2;
+ width = `calc(100% + ${(widths[1] + widths[3]) / 2 - insetsW}px)`;
+ height = `calc(100% + ${(widths[0] + widths[2]) / 2 - insetsH}px)`;
+ break;
+ case "left":
+ top -= widths[0];
+ left -= widths[3];
+ width = `calc(100% + ${widths[1] + widths[3] - insetsW}px)`;
+ height = `calc(100% + ${widths[0] + widths[2] - insetsH}px)`;
+ break;
+ case "right":
+ width = insetsW ? `calc(100% - ${insetsW}px)` : "100%";
+ height = insetsH ? `calc(100% - ${insetsH}px)` : "100%";
+ break;
+ }
+ const classNames = ["xfaBorder"];
+ if (isPrintOnly(node.border)) {
+ classNames.push("xfaPrintOnly");
+ }
+ const border = {
+ name: "div",
+ attributes: {
+ class: classNames,
+ style: {
+ top: `${top}px`,
+ left: `${left}px`,
+ width,
+ height
+ }
+ },
+ children: []
+ };
+ for (const key of ["border", "borderWidth", "borderColor", "borderRadius", "borderStyle"]) {
+ if (style[key] !== undefined) {
+ border.attributes.style[key] = style[key];
+ delete style[key];
+ }
+ }
+ wrapper.children.push(border, html);
+ } else {
+ wrapper.children.push(html);
+ }
+ for (const key of ["background", "backgroundClip", "top", "left", "width", "height", "minWidth", "minHeight", "maxWidth", "maxHeight", "transform", "transformOrigin", "visibility"]) {
+ if (style[key] !== undefined) {
+ wrapper.attributes.style[key] = style[key];
+ delete style[key];
+ }
+ }
+ wrapper.attributes.style.position = style.position === "absolute" ? "absolute" : "relative";
+ delete style.position;
+ if (style.alignSelf) {
+ wrapper.attributes.style.alignSelf = style.alignSelf;
+ delete style.alignSelf;
+ }
+ return wrapper;
+}
+function fixTextIndent(styles) {
+ const indent = getMeasurement(styles.textIndent, "0px");
+ if (indent >= 0) {
+ return;
+ }
+ const align = styles.textAlign === "right" ? "right" : "left";
+ const name = "padding" + (align === "left" ? "Left" : "Right");
+ const padding = getMeasurement(styles[name], "0px");
+ styles[name] = `${padding - indent}px`;
+}
+function setAccess(node, classNames) {
+ switch (node.access) {
+ case "nonInteractive":
+ classNames.push("xfaNonInteractive");
+ break;
+ case "readOnly":
+ classNames.push("xfaReadOnly");
+ break;
+ case "protected":
+ classNames.push("xfaDisabled");
+ break;
+ }
+}
+function isPrintOnly(node) {
+ return node.relevant.length > 0 && !node.relevant[0].excluded && node.relevant[0].viewname === "print";
+}
+function getCurrentPara(node) {
+ const stack = node[$getTemplateRoot]()[$extra].paraStack;
+ return stack.length ? stack.at(-1) : null;
+}
+function setPara(node, nodeStyle, value) {
+ if (value.attributes.class?.includes("xfaRich")) {
+ if (nodeStyle) {
+ if (node.h === "") {
+ nodeStyle.height = "auto";
+ }
+ if (node.w === "") {
+ nodeStyle.width = "auto";
+ }
+ }
+ const para = getCurrentPara(node);
+ if (para) {
+ const valueStyle = value.attributes.style;
+ valueStyle.display = "flex";
+ valueStyle.flexDirection = "column";
+ switch (para.vAlign) {
+ case "top":
+ valueStyle.justifyContent = "start";
+ break;
+ case "bottom":
+ valueStyle.justifyContent = "end";
+ break;
+ case "middle":
+ valueStyle.justifyContent = "center";
+ break;
+ }
+ const paraStyle = para[$toStyle]();
+ for (const [key, val] of Object.entries(paraStyle)) {
+ if (!(key in valueStyle)) {
+ valueStyle[key] = val;
+ }
+ }
+ }
+ }
+}
+function setFontFamily(xfaFont, node, fontFinder, style) {
+ if (!fontFinder) {
+ delete style.fontFamily;
+ return;
+ }
+ const name = stripQuotes(xfaFont.typeface);
+ style.fontFamily = `"${name}"`;
+ const typeface = fontFinder.find(name);
+ if (typeface) {
+ const {
+ fontFamily
+ } = typeface.regular.cssFontInfo;
+ if (fontFamily !== name) {
+ style.fontFamily = `"${fontFamily}"`;
+ }
+ const para = getCurrentPara(node);
+ if (para && para.lineHeight !== "") {
+ return;
+ }
+ if (style.lineHeight) {
+ return;
+ }
+ const pdfFont = selectFont(xfaFont, typeface);
+ if (pdfFont) {
+ style.lineHeight = Math.max(1.2, pdfFont.lineHeight);
+ }
+ }
+}
+function fixURL(str) {
+ const absoluteUrl = createValidAbsoluteUrl(str, null, {
+ addDefaultProtocol: true,
+ tryConvertEncoding: true
+ });
+ return absoluteUrl ? absoluteUrl.href : null;
+}
+
+;// CONCATENATED MODULE: ./src/core/xfa/layout.js
+
+
+function createLine(node, children) {
+ return {
+ name: "div",
+ attributes: {
+ class: [node.layout === "lr-tb" ? "xfaLr" : "xfaRl"]
+ },
+ children
+ };
+}
+function flushHTML(node) {
+ if (!node[$extra]) {
+ return null;
+ }
+ const attributes = node[$extra].attributes;
+ const html = {
+ name: "div",
+ attributes,
+ children: node[$extra].children
+ };
+ if (node[$extra].failingNode) {
+ const htmlFromFailing = node[$extra].failingNode[$flushHTML]();
+ if (htmlFromFailing) {
+ if (node.layout.endsWith("-tb")) {
+ html.children.push(createLine(node, [htmlFromFailing]));
+ } else {
+ html.children.push(htmlFromFailing);
+ }
+ }
+ }
+ if (html.children.length === 0) {
+ return null;
+ }
+ return html;
+}
+function addHTML(node, html, bbox) {
+ const extra = node[$extra];
+ const availableSpace = extra.availableSpace;
+ const [x, y, w, h] = bbox;
+ switch (node.layout) {
+ case "position":
+ {
+ extra.width = Math.max(extra.width, x + w);
+ extra.height = Math.max(extra.height, y + h);
+ extra.children.push(html);
+ break;
+ }
+ case "lr-tb":
+ case "rl-tb":
+ if (!extra.line || extra.attempt === 1) {
+ extra.line = createLine(node, []);
+ extra.children.push(extra.line);
+ extra.numberInLine = 0;
+ }
+ extra.numberInLine += 1;
+ extra.line.children.push(html);
+ if (extra.attempt === 0) {
+ extra.currentWidth += w;
+ extra.height = Math.max(extra.height, extra.prevHeight + h);
+ } else {
+ extra.currentWidth = w;
+ extra.prevHeight = extra.height;
+ extra.height += h;
+ extra.attempt = 0;
+ }
+ extra.width = Math.max(extra.width, extra.currentWidth);
+ break;
+ case "rl-row":
+ case "row":
+ {
+ extra.children.push(html);
+ extra.width += w;
+ extra.height = Math.max(extra.height, h);
+ const height = measureToString(extra.height);
+ for (const child of extra.children) {
+ child.attributes.style.height = height;
+ }
+ break;
+ }
+ case "table":
+ {
+ extra.width = Math.min(availableSpace.width, Math.max(extra.width, w));
+ extra.height += h;
+ extra.children.push(html);
+ break;
+ }
+ case "tb":
+ {
+ extra.width = Math.min(availableSpace.width, Math.max(extra.width, w));
+ extra.height += h;
+ extra.children.push(html);
+ break;
+ }
+ }
+}
+function getAvailableSpace(node) {
+ const availableSpace = node[$extra].availableSpace;
+ const marginV = node.margin ? node.margin.topInset + node.margin.bottomInset : 0;
+ const marginH = node.margin ? node.margin.leftInset + node.margin.rightInset : 0;
+ switch (node.layout) {
+ case "lr-tb":
+ case "rl-tb":
+ if (node[$extra].attempt === 0) {
+ return {
+ width: availableSpace.width - marginH - node[$extra].currentWidth,
+ height: availableSpace.height - marginV - node[$extra].prevHeight
+ };
+ }
+ return {
+ width: availableSpace.width - marginH,
+ height: availableSpace.height - marginV - node[$extra].height
+ };
+ case "rl-row":
+ case "row":
+ const width = node[$extra].columnWidths.slice(node[$extra].currentColumn).reduce((a, x) => a + x);
+ return {
+ width,
+ height: availableSpace.height - marginH
+ };
+ case "table":
+ case "tb":
+ return {
+ width: availableSpace.width - marginH,
+ height: availableSpace.height - marginV - node[$extra].height
+ };
+ case "position":
+ default:
+ return availableSpace;
+ }
+}
+function getTransformedBBox(node) {
+ let w = node.w === "" ? NaN : node.w;
+ let h = node.h === "" ? NaN : node.h;
+ let [centerX, centerY] = [0, 0];
+ switch (node.anchorType || "") {
+ case "bottomCenter":
+ [centerX, centerY] = [w / 2, h];
+ break;
+ case "bottomLeft":
+ [centerX, centerY] = [0, h];
+ break;
+ case "bottomRight":
+ [centerX, centerY] = [w, h];
+ break;
+ case "middleCenter":
+ [centerX, centerY] = [w / 2, h / 2];
+ break;
+ case "middleLeft":
+ [centerX, centerY] = [0, h / 2];
+ break;
+ case "middleRight":
+ [centerX, centerY] = [w, h / 2];
+ break;
+ case "topCenter":
+ [centerX, centerY] = [w / 2, 0];
+ break;
+ case "topRight":
+ [centerX, centerY] = [w, 0];
+ break;
+ }
+ let x, y;
+ switch (node.rotate || 0) {
+ case 0:
+ [x, y] = [-centerX, -centerY];
+ break;
+ case 90:
+ [x, y] = [-centerY, centerX];
+ [w, h] = [h, -w];
+ break;
+ case 180:
+ [x, y] = [centerX, centerY];
+ [w, h] = [-w, -h];
+ break;
+ case 270:
+ [x, y] = [centerY, -centerX];
+ [w, h] = [-h, w];
+ break;
+ }
+ return [node.x + x + Math.min(0, w), node.y + y + Math.min(0, h), Math.abs(w), Math.abs(h)];
+}
+function checkDimensions(node, space) {
+ if (node[$getTemplateRoot]()[$extra].firstUnsplittable === null) {
+ return true;
+ }
+ if (node.w === 0 || node.h === 0) {
+ return true;
+ }
+ const ERROR = 2;
+ const parent = node[$getSubformParent]();
+ const attempt = parent[$extra]?.attempt || 0;
+ const [, y, w, h] = getTransformedBBox(node);
+ switch (parent.layout) {
+ case "lr-tb":
+ case "rl-tb":
+ if (attempt === 0) {
+ if (!node[$getTemplateRoot]()[$extra].noLayoutFailure) {
+ if (node.h !== "" && Math.round(h - space.height) > ERROR) {
+ return false;
+ }
+ if (node.w !== "") {
+ if (Math.round(w - space.width) <= ERROR) {
+ return true;
+ }
+ if (parent[$extra].numberInLine === 0) {
+ return space.height > ERROR;
+ }
+ return false;
+ }
+ return space.width > ERROR;
+ }
+ if (node.w !== "") {
+ return Math.round(w - space.width) <= ERROR;
+ }
+ return space.width > ERROR;
+ }
+ if (node[$getTemplateRoot]()[$extra].noLayoutFailure) {
+ return true;
+ }
+ if (node.h !== "" && Math.round(h - space.height) > ERROR) {
+ return false;
+ }
+ if (node.w === "" || Math.round(w - space.width) <= ERROR) {
+ return space.height > ERROR;
+ }
+ if (parent[$isThereMoreWidth]()) {
+ return false;
+ }
+ return space.height > ERROR;
+ case "table":
+ case "tb":
+ if (node[$getTemplateRoot]()[$extra].noLayoutFailure) {
+ return true;
+ }
+ if (node.h !== "" && !node[$isSplittable]()) {
+ return Math.round(h - space.height) <= ERROR;
+ }
+ if (node.w === "" || Math.round(w - space.width) <= ERROR) {
+ return space.height > ERROR;
+ }
+ if (parent[$isThereMoreWidth]()) {
+ return false;
+ }
+ return space.height > ERROR;
+ case "position":
+ if (node[$getTemplateRoot]()[$extra].noLayoutFailure) {
+ return true;
+ }
+ if (node.h === "" || Math.round(h + y - space.height) <= ERROR) {
+ return true;
+ }
+ const area = node[$getTemplateRoot]()[$extra].currentContentArea;
+ return h + y > area.h;
+ case "rl-row":
+ case "row":
+ if (node[$getTemplateRoot]()[$extra].noLayoutFailure) {
+ return true;
+ }
+ if (node.h !== "") {
+ return Math.round(h - space.height) <= ERROR;
+ }
+ return true;
+ default:
+ return true;
+ }
+}
+
+;// CONCATENATED MODULE: ./src/core/xfa/template.js
+
+
+
+
+
+
+
+
+
+
+const TEMPLATE_NS_ID = NamespaceIds.template.id;
+const SVG_NS = "http://www.w3.org/2000/svg";
+const MAX_ATTEMPTS_FOR_LRTB_LAYOUT = 2;
+const MAX_EMPTY_PAGES = 3;
+const DEFAULT_TAB_INDEX = 5000;
+const HEADING_PATTERN = /^H(\d+)$/;
+const MIMES = new Set(["image/gif", "image/jpeg", "image/jpg", "image/pjpeg", "image/png", "image/apng", "image/x-png", "image/bmp", "image/x-ms-bmp", "image/tiff", "image/tif", "application/octet-stream"]);
+const IMAGES_HEADERS = [[[0x42, 0x4d], "image/bmp"], [[0xff, 0xd8, 0xff], "image/jpeg"], [[0x49, 0x49, 0x2a, 0x00], "image/tiff"], [[0x4d, 0x4d, 0x00, 0x2a], "image/tiff"], [[0x47, 0x49, 0x46, 0x38, 0x39, 0x61], "image/gif"], [[0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a], "image/png"]];
+function getBorderDims(node) {
+ if (!node || !node.border) {
+ return {
+ w: 0,
+ h: 0
+ };
+ }
+ const borderExtra = node.border[$getExtra]();
+ if (!borderExtra) {
+ return {
+ w: 0,
+ h: 0
+ };
+ }
+ return {
+ w: borderExtra.widths[0] + borderExtra.widths[2] + borderExtra.insets[0] + borderExtra.insets[2],
+ h: borderExtra.widths[1] + borderExtra.widths[3] + borderExtra.insets[1] + borderExtra.insets[3]
+ };
+}
+function hasMargin(node) {
+ return node.margin && (node.margin.topInset || node.margin.rightInset || node.margin.bottomInset || node.margin.leftInset);
+}
+function _setValue(templateNode, value) {
+ if (!templateNode.value) {
+ const nodeValue = new Value({});
+ templateNode[$appendChild](nodeValue);
+ templateNode.value = nodeValue;
+ }
+ templateNode.value[$setValue](value);
+}
+function* getContainedChildren(node) {
+ for (const child of node[$getChildren]()) {
+ if (child instanceof SubformSet) {
+ yield* child[$getContainedChildren]();
+ continue;
+ }
+ yield child;
+ }
+}
+function isRequired(node) {
+ return node.validate?.nullTest === "error";
+}
+function setTabIndex(node) {
+ while (node) {
+ if (!node.traversal) {
+ node[$tabIndex] = node[$getParent]()[$tabIndex];
+ return;
+ }
+ if (node[$tabIndex]) {
+ return;
+ }
+ let next = null;
+ for (const child of node.traversal[$getChildren]()) {
+ if (child.operation === "next") {
+ next = child;
+ break;
+ }
+ }
+ if (!next || !next.ref) {
+ node[$tabIndex] = node[$getParent]()[$tabIndex];
+ return;
+ }
+ const root = node[$getTemplateRoot]();
+ node[$tabIndex] = ++root[$tabIndex];
+ const ref = root[$searchNode](next.ref, node);
+ if (!ref) {
+ return;
+ }
+ node = ref[0];
+ }
+}
+function applyAssist(obj, attributes) {
+ const assist = obj.assist;
+ if (assist) {
+ const assistTitle = assist[$toHTML]();
+ if (assistTitle) {
+ attributes.title = assistTitle;
+ }
+ const role = assist.role;
+ const match = role.match(HEADING_PATTERN);
+ if (match) {
+ const ariaRole = "heading";
+ const ariaLevel = match[1];
+ attributes.role = ariaRole;
+ attributes["aria-level"] = ariaLevel;
+ }
+ }
+ if (obj.layout === "table") {
+ attributes.role = "table";
+ } else if (obj.layout === "row") {
+ attributes.role = "row";
+ } else {
+ const parent = obj[$getParent]();
+ if (parent.layout === "row") {
+ attributes.role = parent.assist?.role === "TH" ? "columnheader" : "cell";
+ }
+ }
+}
+function ariaLabel(obj) {
+ if (!obj.assist) {
+ return null;
+ }
+ const assist = obj.assist;
+ if (assist.speak && assist.speak[$content] !== "") {
+ return assist.speak[$content];
+ }
+ if (assist.toolTip) {
+ return assist.toolTip[$content];
+ }
+ return null;
+}
+function valueToHtml(value) {
+ return HTMLResult.success({
+ name: "div",
+ attributes: {
+ class: ["xfaRich"],
+ style: Object.create(null)
+ },
+ children: [{
+ name: "span",
+ attributes: {
+ style: Object.create(null)
+ },
+ value
+ }]
+ });
+}
+function setFirstUnsplittable(node) {
+ const root = node[$getTemplateRoot]();
+ if (root[$extra].firstUnsplittable === null) {
+ root[$extra].firstUnsplittable = node;
+ root[$extra].noLayoutFailure = true;
+ }
+}
+function unsetFirstUnsplittable(node) {
+ const root = node[$getTemplateRoot]();
+ if (root[$extra].firstUnsplittable === node) {
+ root[$extra].noLayoutFailure = false;
+ }
+}
+function handleBreak(node) {
+ if (node[$extra]) {
+ return false;
+ }
+ node[$extra] = Object.create(null);
+ if (node.targetType === "auto") {
+ return false;
+ }
+ const root = node[$getTemplateRoot]();
+ let target = null;
+ if (node.target) {
+ target = root[$searchNode](node.target, node[$getParent]());
+ if (!target) {
+ return false;
+ }
+ target = target[0];
+ }
+ const {
+ currentPageArea,
+ currentContentArea
+ } = root[$extra];
+ if (node.targetType === "pageArea") {
+ if (!(target instanceof PageArea)) {
+ target = null;
+ }
+ if (node.startNew) {
+ node[$extra].target = target || currentPageArea;
+ return true;
+ } else if (target && target !== currentPageArea) {
+ node[$extra].target = target;
+ return true;
+ }
+ return false;
+ }
+ if (!(target instanceof ContentArea)) {
+ target = null;
+ }
+ const pageArea = target && target[$getParent]();
+ let index;
+ let nextPageArea = pageArea;
+ if (node.startNew) {
+ if (target) {
+ const contentAreas = pageArea.contentArea.children;
+ const indexForCurrent = contentAreas.indexOf(currentContentArea);
+ const indexForTarget = contentAreas.indexOf(target);
+ if (indexForCurrent !== -1 && indexForCurrent < indexForTarget) {
+ nextPageArea = null;
+ }
+ index = indexForTarget - 1;
+ } else {
+ index = currentPageArea.contentArea.children.indexOf(currentContentArea);
+ }
+ } else if (target && target !== currentContentArea) {
+ const contentAreas = pageArea.contentArea.children;
+ index = contentAreas.indexOf(target) - 1;
+ nextPageArea = pageArea === currentPageArea ? null : pageArea;
+ } else {
+ return false;
+ }
+ node[$extra].target = nextPageArea;
+ node[$extra].index = index;
+ return true;
+}
+function handleOverflow(node, extraNode, space) {
+ const root = node[$getTemplateRoot]();
+ const saved = root[$extra].noLayoutFailure;
+ const savedMethod = extraNode[$getSubformParent];
+ extraNode[$getSubformParent] = () => node;
+ root[$extra].noLayoutFailure = true;
+ const res = extraNode[$toHTML](space);
+ node[$addHTML](res.html, res.bbox);
+ root[$extra].noLayoutFailure = saved;
+ extraNode[$getSubformParent] = savedMethod;
+}
+class AppearanceFilter extends StringObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "appearanceFilter");
+ this.id = attributes.id || "";
+ this.type = getStringOption(attributes.type, ["optional", "required"]);
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ }
+}
+class Arc extends XFAObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "arc", true);
+ this.circular = getInteger({
+ data: attributes.circular,
+ defaultValue: 0,
+ validate: x => x === 1
+ });
+ this.hand = getStringOption(attributes.hand, ["even", "left", "right"]);
+ this.id = attributes.id || "";
+ this.startAngle = getFloat({
+ data: attributes.startAngle,
+ defaultValue: 0,
+ validate: x => true
+ });
+ this.sweepAngle = getFloat({
+ data: attributes.sweepAngle,
+ defaultValue: 360,
+ validate: x => true
+ });
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ this.edge = null;
+ this.fill = null;
+ }
+ [$toHTML]() {
+ const edge = this.edge || new Edge({});
+ const edgeStyle = edge[$toStyle]();
+ const style = Object.create(null);
+ if (this.fill?.presence === "visible") {
+ Object.assign(style, this.fill[$toStyle]());
+ } else {
+ style.fill = "transparent";
+ }
+ style.strokeWidth = measureToString(edge.presence === "visible" ? edge.thickness : 0);
+ style.stroke = edgeStyle.color;
+ let arc;
+ const attributes = {
+ xmlns: SVG_NS,
+ style: {
+ width: "100%",
+ height: "100%",
+ overflow: "visible"
+ }
+ };
+ if (this.sweepAngle === 360) {
+ arc = {
+ name: "ellipse",
+ attributes: {
+ xmlns: SVG_NS,
+ cx: "50%",
+ cy: "50%",
+ rx: "50%",
+ ry: "50%",
+ style
+ }
+ };
+ } else {
+ const startAngle = this.startAngle * Math.PI / 180;
+ const sweepAngle = this.sweepAngle * Math.PI / 180;
+ const largeArc = this.sweepAngle > 180 ? 1 : 0;
+ const [x1, y1, x2, y2] = [50 * (1 + Math.cos(startAngle)), 50 * (1 - Math.sin(startAngle)), 50 * (1 + Math.cos(startAngle + sweepAngle)), 50 * (1 - Math.sin(startAngle + sweepAngle))];
+ arc = {
+ name: "path",
+ attributes: {
+ xmlns: SVG_NS,
+ d: `M ${x1} ${y1} A 50 50 0 ${largeArc} 0 ${x2} ${y2}`,
+ vectorEffect: "non-scaling-stroke",
+ style
+ }
+ };
+ Object.assign(attributes, {
+ viewBox: "0 0 100 100",
+ preserveAspectRatio: "none"
+ });
+ }
+ const svg = {
+ name: "svg",
+ children: [arc],
+ attributes
+ };
+ const parent = this[$getParent]()[$getParent]();
+ if (hasMargin(parent)) {
+ return HTMLResult.success({
+ name: "div",
+ attributes: {
+ style: {
+ display: "inline",
+ width: "100%",
+ height: "100%"
+ }
+ },
+ children: [svg]
+ });
+ }
+ svg.attributes.style.position = "absolute";
+ return HTMLResult.success(svg);
+ }
+}
+class Area extends XFAObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "area", true);
+ this.colSpan = getInteger({
+ data: attributes.colSpan,
+ defaultValue: 1,
+ validate: n => n >= 1 || n === -1
+ });
+ this.id = attributes.id || "";
+ this.name = attributes.name || "";
+ this.relevant = getRelevant(attributes.relevant);
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ this.x = getMeasurement(attributes.x, "0pt");
+ this.y = getMeasurement(attributes.y, "0pt");
+ this.desc = null;
+ this.extras = null;
+ this.area = new XFAObjectArray();
+ this.draw = new XFAObjectArray();
+ this.exObject = new XFAObjectArray();
+ this.exclGroup = new XFAObjectArray();
+ this.field = new XFAObjectArray();
+ this.subform = new XFAObjectArray();
+ this.subformSet = new XFAObjectArray();
+ }
+ *[$getContainedChildren]() {
+ yield* getContainedChildren(this);
+ }
+ [$isTransparent]() {
+ return true;
+ }
+ [$isBindable]() {
+ return true;
+ }
+ [$addHTML](html, bbox) {
+ const [x, y, w, h] = bbox;
+ this[$extra].width = Math.max(this[$extra].width, x + w);
+ this[$extra].height = Math.max(this[$extra].height, y + h);
+ this[$extra].children.push(html);
+ }
+ [$getAvailableSpace]() {
+ return this[$extra].availableSpace;
+ }
+ [$toHTML](availableSpace) {
+ const style = toStyle(this, "position");
+ const attributes = {
+ style,
+ id: this[$uid],
+ class: ["xfaArea"]
+ };
+ if (isPrintOnly(this)) {
+ attributes.class.push("xfaPrintOnly");
+ }
+ if (this.name) {
+ attributes.xfaName = this.name;
+ }
+ const children = [];
+ this[$extra] = {
+ children,
+ width: 0,
+ height: 0,
+ availableSpace
+ };
+ const result = this[$childrenToHTML]({
+ filter: new Set(["area", "draw", "field", "exclGroup", "subform", "subformSet"]),
+ include: true
+ });
+ if (!result.success) {
+ if (result.isBreak()) {
+ return result;
+ }
+ delete this[$extra];
+ return HTMLResult.FAILURE;
+ }
+ style.width = measureToString(this[$extra].width);
+ style.height = measureToString(this[$extra].height);
+ const html = {
+ name: "div",
+ attributes,
+ children
+ };
+ const bbox = [this.x, this.y, this[$extra].width, this[$extra].height];
+ delete this[$extra];
+ return HTMLResult.success(html, bbox);
+ }
+}
+class Assist extends XFAObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "assist", true);
+ this.id = attributes.id || "";
+ this.role = attributes.role || "";
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ this.speak = null;
+ this.toolTip = null;
+ }
+ [$toHTML]() {
+ return this.toolTip?.[$content] || null;
+ }
+}
+class Barcode extends XFAObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "barcode", true);
+ this.charEncoding = getKeyword({
+ data: attributes.charEncoding ? attributes.charEncoding.toLowerCase() : "",
+ defaultValue: "",
+ validate: k => ["utf-8", "big-five", "fontspecific", "gbk", "gb-18030", "gb-2312", "ksc-5601", "none", "shift-jis", "ucs-2", "utf-16"].includes(k) || k.match(/iso-8859-\d{2}/)
+ });
+ this.checksum = getStringOption(attributes.checksum, ["none", "1mod10", "1mod10_1mod11", "2mod10", "auto"]);
+ this.dataColumnCount = getInteger({
+ data: attributes.dataColumnCount,
+ defaultValue: -1,
+ validate: x => x >= 0
+ });
+ this.dataLength = getInteger({
+ data: attributes.dataLength,
+ defaultValue: -1,
+ validate: x => x >= 0
+ });
+ this.dataPrep = getStringOption(attributes.dataPrep, ["none", "flateCompress"]);
+ this.dataRowCount = getInteger({
+ data: attributes.dataRowCount,
+ defaultValue: -1,
+ validate: x => x >= 0
+ });
+ this.endChar = attributes.endChar || "";
+ this.errorCorrectionLevel = getInteger({
+ data: attributes.errorCorrectionLevel,
+ defaultValue: -1,
+ validate: x => x >= 0 && x <= 8
+ });
+ this.id = attributes.id || "";
+ this.moduleHeight = getMeasurement(attributes.moduleHeight, "5mm");
+ this.moduleWidth = getMeasurement(attributes.moduleWidth, "0.25mm");
+ this.printCheckDigit = getInteger({
+ data: attributes.printCheckDigit,
+ defaultValue: 0,
+ validate: x => x === 1
+ });
+ this.rowColumnRatio = getRatio(attributes.rowColumnRatio);
+ this.startChar = attributes.startChar || "";
+ this.textLocation = getStringOption(attributes.textLocation, ["below", "above", "aboveEmbedded", "belowEmbedded", "none"]);
+ this.truncate = getInteger({
+ data: attributes.truncate,
+ defaultValue: 0,
+ validate: x => x === 1
+ });
+ this.type = getStringOption(attributes.type ? attributes.type.toLowerCase() : "", ["aztec", "codabar", "code2of5industrial", "code2of5interleaved", "code2of5matrix", "code2of5standard", "code3of9", "code3of9extended", "code11", "code49", "code93", "code128", "code128a", "code128b", "code128c", "code128sscc", "datamatrix", "ean8", "ean8add2", "ean8add5", "ean13", "ean13add2", "ean13add5", "ean13pwcd", "fim", "logmars", "maxicode", "msi", "pdf417", "pdf417macro", "plessey", "postauscust2", "postauscust3", "postausreplypaid", "postausstandard", "postukrm4scc", "postusdpbc", "postusimb", "postusstandard", "postus5zip", "qrcode", "rfid", "rss14", "rss14expanded", "rss14limited", "rss14stacked", "rss14stackedomni", "rss14truncated", "telepen", "ucc128", "ucc128random", "ucc128sscc", "upca", "upcaadd2", "upcaadd5", "upcapwcd", "upce", "upceadd2", "upceadd5", "upcean2", "upcean5", "upsmaxicode"]);
+ this.upsMode = getStringOption(attributes.upsMode, ["usCarrier", "internationalCarrier", "secureSymbol", "standardSymbol"]);
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ this.wideNarrowRatio = getRatio(attributes.wideNarrowRatio);
+ this.encrypt = null;
+ this.extras = null;
+ }
+}
+class Bind extends XFAObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "bind", true);
+ this.match = getStringOption(attributes.match, ["once", "dataRef", "global", "none"]);
+ this.ref = attributes.ref || "";
+ this.picture = null;
+ }
+}
+class BindItems extends XFAObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "bindItems");
+ this.connection = attributes.connection || "";
+ this.labelRef = attributes.labelRef || "";
+ this.ref = attributes.ref || "";
+ this.valueRef = attributes.valueRef || "";
+ }
+}
+class Bookend extends XFAObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "bookend");
+ this.id = attributes.id || "";
+ this.leader = attributes.leader || "";
+ this.trailer = attributes.trailer || "";
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ }
+}
+class BooleanElement extends Option01 {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "boolean");
+ this.id = attributes.id || "";
+ this.name = attributes.name || "";
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ }
+ [$toHTML](availableSpace) {
+ return valueToHtml(this[$content] === 1 ? "1" : "0");
+ }
+}
+class Border extends XFAObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "border", true);
+ this.break = getStringOption(attributes.break, ["close", "open"]);
+ this.hand = getStringOption(attributes.hand, ["even", "left", "right"]);
+ this.id = attributes.id || "";
+ this.presence = getStringOption(attributes.presence, ["visible", "hidden", "inactive", "invisible"]);
+ this.relevant = getRelevant(attributes.relevant);
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ this.corner = new XFAObjectArray(4);
+ this.edge = new XFAObjectArray(4);
+ this.extras = null;
+ this.fill = null;
+ this.margin = null;
+ }
+ [$getExtra]() {
+ if (!this[$extra]) {
+ const edges = this.edge.children.slice();
+ if (edges.length < 4) {
+ const defaultEdge = edges.at(-1) || new Edge({});
+ for (let i = edges.length; i < 4; i++) {
+ edges.push(defaultEdge);
+ }
+ }
+ const widths = edges.map(edge => edge.thickness);
+ const insets = [0, 0, 0, 0];
+ if (this.margin) {
+ insets[0] = this.margin.topInset;
+ insets[1] = this.margin.rightInset;
+ insets[2] = this.margin.bottomInset;
+ insets[3] = this.margin.leftInset;
+ }
+ this[$extra] = {
+ widths,
+ insets,
+ edges
+ };
+ }
+ return this[$extra];
+ }
+ [$toStyle]() {
+ const {
+ edges
+ } = this[$getExtra]();
+ const edgeStyles = edges.map(node => {
+ const style = node[$toStyle]();
+ style.color ||= "#000000";
+ return style;
+ });
+ const style = Object.create(null);
+ if (this.margin) {
+ Object.assign(style, this.margin[$toStyle]());
+ }
+ if (this.fill?.presence === "visible") {
+ Object.assign(style, this.fill[$toStyle]());
+ }
+ if (this.corner.children.some(node => node.radius !== 0)) {
+ const cornerStyles = this.corner.children.map(node => node[$toStyle]());
+ if (cornerStyles.length === 2 || cornerStyles.length === 3) {
+ const last = cornerStyles.at(-1);
+ for (let i = cornerStyles.length; i < 4; i++) {
+ cornerStyles.push(last);
+ }
+ }
+ style.borderRadius = cornerStyles.map(s => s.radius).join(" ");
+ }
+ switch (this.presence) {
+ case "invisible":
+ case "hidden":
+ style.borderStyle = "";
+ break;
+ case "inactive":
+ style.borderStyle = "none";
+ break;
+ default:
+ style.borderStyle = edgeStyles.map(s => s.style).join(" ");
+ break;
+ }
+ style.borderWidth = edgeStyles.map(s => s.width).join(" ");
+ style.borderColor = edgeStyles.map(s => s.color).join(" ");
+ return style;
+ }
+}
+class Break extends XFAObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "break", true);
+ this.after = getStringOption(attributes.after, ["auto", "contentArea", "pageArea", "pageEven", "pageOdd"]);
+ this.afterTarget = attributes.afterTarget || "";
+ this.before = getStringOption(attributes.before, ["auto", "contentArea", "pageArea", "pageEven", "pageOdd"]);
+ this.beforeTarget = attributes.beforeTarget || "";
+ this.bookendLeader = attributes.bookendLeader || "";
+ this.bookendTrailer = attributes.bookendTrailer || "";
+ this.id = attributes.id || "";
+ this.overflowLeader = attributes.overflowLeader || "";
+ this.overflowTarget = attributes.overflowTarget || "";
+ this.overflowTrailer = attributes.overflowTrailer || "";
+ this.startNew = getInteger({
+ data: attributes.startNew,
+ defaultValue: 0,
+ validate: x => x === 1
+ });
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ this.extras = null;
+ }
+}
+class BreakAfter extends XFAObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "breakAfter", true);
+ this.id = attributes.id || "";
+ this.leader = attributes.leader || "";
+ this.startNew = getInteger({
+ data: attributes.startNew,
+ defaultValue: 0,
+ validate: x => x === 1
+ });
+ this.target = attributes.target || "";
+ this.targetType = getStringOption(attributes.targetType, ["auto", "contentArea", "pageArea"]);
+ this.trailer = attributes.trailer || "";
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ this.script = null;
+ }
+}
+class BreakBefore extends XFAObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "breakBefore", true);
+ this.id = attributes.id || "";
+ this.leader = attributes.leader || "";
+ this.startNew = getInteger({
+ data: attributes.startNew,
+ defaultValue: 0,
+ validate: x => x === 1
+ });
+ this.target = attributes.target || "";
+ this.targetType = getStringOption(attributes.targetType, ["auto", "contentArea", "pageArea"]);
+ this.trailer = attributes.trailer || "";
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ this.script = null;
+ }
+ [$toHTML](availableSpace) {
+ this[$extra] = {};
+ return HTMLResult.FAILURE;
+ }
+}
+class Button extends XFAObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "button", true);
+ this.highlight = getStringOption(attributes.highlight, ["inverted", "none", "outline", "push"]);
+ this.id = attributes.id || "";
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ this.extras = null;
+ }
+ [$toHTML](availableSpace) {
+ const parent = this[$getParent]();
+ const grandpa = parent[$getParent]();
+ const htmlButton = {
+ name: "button",
+ attributes: {
+ id: this[$uid],
+ class: ["xfaButton"],
+ style: {}
+ },
+ children: []
+ };
+ for (const event of grandpa.event.children) {
+ if (event.activity !== "click" || !event.script) {
+ continue;
+ }
+ const jsURL = recoverJsURL(event.script[$content]);
+ if (!jsURL) {
+ continue;
+ }
+ const href = fixURL(jsURL.url);
+ if (!href) {
+ continue;
+ }
+ htmlButton.children.push({
+ name: "a",
+ attributes: {
+ id: "link" + this[$uid],
+ href,
+ newWindow: jsURL.newWindow,
+ class: ["xfaLink"],
+ style: {}
+ },
+ children: []
+ });
+ }
+ return HTMLResult.success(htmlButton);
+ }
+}
+class Calculate extends XFAObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "calculate", true);
+ this.id = attributes.id || "";
+ this.override = getStringOption(attributes.override, ["disabled", "error", "ignore", "warning"]);
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ this.extras = null;
+ this.message = null;
+ this.script = null;
+ }
+}
+class Caption extends XFAObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "caption", true);
+ this.id = attributes.id || "";
+ this.placement = getStringOption(attributes.placement, ["left", "bottom", "inline", "right", "top"]);
+ this.presence = getStringOption(attributes.presence, ["visible", "hidden", "inactive", "invisible"]);
+ this.reserve = Math.ceil(getMeasurement(attributes.reserve));
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ this.extras = null;
+ this.font = null;
+ this.margin = null;
+ this.para = null;
+ this.value = null;
+ }
+ [$setValue](value) {
+ _setValue(this, value);
+ }
+ [$getExtra](availableSpace) {
+ if (!this[$extra]) {
+ let {
+ width,
+ height
+ } = availableSpace;
+ switch (this.placement) {
+ case "left":
+ case "right":
+ case "inline":
+ width = this.reserve <= 0 ? width : this.reserve;
+ break;
+ case "top":
+ case "bottom":
+ height = this.reserve <= 0 ? height : this.reserve;
+ break;
+ }
+ this[$extra] = layoutNode(this, {
+ width,
+ height
+ });
+ }
+ return this[$extra];
+ }
+ [$toHTML](availableSpace) {
+ if (!this.value) {
+ return HTMLResult.EMPTY;
+ }
+ this[$pushPara]();
+ const value = this.value[$toHTML](availableSpace).html;
+ if (!value) {
+ this[$popPara]();
+ return HTMLResult.EMPTY;
+ }
+ const savedReserve = this.reserve;
+ if (this.reserve <= 0) {
+ const {
+ w,
+ h
+ } = this[$getExtra](availableSpace);
+ switch (this.placement) {
+ case "left":
+ case "right":
+ case "inline":
+ this.reserve = w;
+ break;
+ case "top":
+ case "bottom":
+ this.reserve = h;
+ break;
+ }
+ }
+ const children = [];
+ if (typeof value === "string") {
+ children.push({
+ name: "#text",
+ value
+ });
+ } else {
+ children.push(value);
+ }
+ const style = toStyle(this, "font", "margin", "visibility");
+ switch (this.placement) {
+ case "left":
+ case "right":
+ if (this.reserve > 0) {
+ style.width = measureToString(this.reserve);
+ }
+ break;
+ case "top":
+ case "bottom":
+ if (this.reserve > 0) {
+ style.height = measureToString(this.reserve);
+ }
+ break;
+ }
+ setPara(this, null, value);
+ this[$popPara]();
+ this.reserve = savedReserve;
+ return HTMLResult.success({
+ name: "div",
+ attributes: {
+ style,
+ class: ["xfaCaption"]
+ },
+ children
+ });
+ }
+}
+class Certificate extends StringObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "certificate");
+ this.id = attributes.id || "";
+ this.name = attributes.name || "";
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ }
+}
+class Certificates extends XFAObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "certificates", true);
+ this.credentialServerPolicy = getStringOption(attributes.credentialServerPolicy, ["optional", "required"]);
+ this.id = attributes.id || "";
+ this.url = attributes.url || "";
+ this.urlPolicy = attributes.urlPolicy || "";
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ this.encryption = null;
+ this.issuers = null;
+ this.keyUsage = null;
+ this.oids = null;
+ this.signing = null;
+ this.subjectDNs = null;
+ }
+}
+class CheckButton extends XFAObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "checkButton", true);
+ this.id = attributes.id || "";
+ this.mark = getStringOption(attributes.mark, ["default", "check", "circle", "cross", "diamond", "square", "star"]);
+ this.shape = getStringOption(attributes.shape, ["square", "round"]);
+ this.size = getMeasurement(attributes.size, "10pt");
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ this.border = null;
+ this.extras = null;
+ this.margin = null;
+ }
+ [$toHTML](availableSpace) {
+ const style = toStyle("margin");
+ const size = measureToString(this.size);
+ style.width = style.height = size;
+ let type;
+ let className;
+ let groupId;
+ const field = this[$getParent]()[$getParent]();
+ const items = field.items.children.length && field.items.children[0][$toHTML]().html || [];
+ const exportedValue = {
+ on: (items[0] !== undefined ? items[0] : "on").toString(),
+ off: (items[1] !== undefined ? items[1] : "off").toString()
+ };
+ const value = field.value?.[$text]() || "off";
+ const checked = value === exportedValue.on || undefined;
+ const container = field[$getSubformParent]();
+ const fieldId = field[$uid];
+ let dataId;
+ if (container instanceof ExclGroup) {
+ groupId = container[$uid];
+ type = "radio";
+ className = "xfaRadio";
+ dataId = container[$data]?.[$uid] || container[$uid];
+ } else {
+ type = "checkbox";
+ className = "xfaCheckbox";
+ dataId = field[$data]?.[$uid] || field[$uid];
+ }
+ const input = {
+ name: "input",
+ attributes: {
+ class: [className],
+ style,
+ fieldId,
+ dataId,
+ type,
+ checked,
+ xfaOn: exportedValue.on,
+ xfaOff: exportedValue.off,
+ "aria-label": ariaLabel(field),
+ "aria-required": false
+ }
+ };
+ if (groupId) {
+ input.attributes.name = groupId;
+ }
+ if (isRequired(field)) {
+ input.attributes["aria-required"] = true;
+ input.attributes.required = true;
+ }
+ return HTMLResult.success({
+ name: "label",
+ attributes: {
+ class: ["xfaLabel"]
+ },
+ children: [input]
+ });
+ }
+}
+class ChoiceList extends XFAObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "choiceList", true);
+ this.commitOn = getStringOption(attributes.commitOn, ["select", "exit"]);
+ this.id = attributes.id || "";
+ this.open = getStringOption(attributes.open, ["userControl", "always", "multiSelect", "onEntry"]);
+ this.textEntry = getInteger({
+ data: attributes.textEntry,
+ defaultValue: 0,
+ validate: x => x === 1
+ });
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ this.border = null;
+ this.extras = null;
+ this.margin = null;
+ }
+ [$toHTML](availableSpace) {
+ const style = toStyle(this, "border", "margin");
+ const ui = this[$getParent]();
+ const field = ui[$getParent]();
+ const fontSize = field.font?.size || 10;
+ const optionStyle = {
+ fontSize: `calc(${fontSize}px * var(--scale-factor))`
+ };
+ const children = [];
+ if (field.items.children.length > 0) {
+ const items = field.items;
+ let displayedIndex = 0;
+ let saveIndex = 0;
+ if (items.children.length === 2) {
+ displayedIndex = items.children[0].save;
+ saveIndex = 1 - displayedIndex;
+ }
+ const displayed = items.children[displayedIndex][$toHTML]().html;
+ const values = items.children[saveIndex][$toHTML]().html;
+ let selected = false;
+ const value = field.value?.[$text]() || "";
+ for (let i = 0, ii = displayed.length; i < ii; i++) {
+ const option = {
+ name: "option",
+ attributes: {
+ value: values[i] || displayed[i],
+ style: optionStyle
+ },
+ value: displayed[i]
+ };
+ if (values[i] === value) {
+ option.attributes.selected = selected = true;
+ }
+ children.push(option);
+ }
+ if (!selected) {
+ children.splice(0, 0, {
+ name: "option",
+ attributes: {
+ hidden: true,
+ selected: true
+ },
+ value: " "
+ });
+ }
+ }
+ const selectAttributes = {
+ class: ["xfaSelect"],
+ fieldId: field[$uid],
+ dataId: field[$data]?.[$uid] || field[$uid],
+ style,
+ "aria-label": ariaLabel(field),
+ "aria-required": false
+ };
+ if (isRequired(field)) {
+ selectAttributes["aria-required"] = true;
+ selectAttributes.required = true;
+ }
+ if (this.open === "multiSelect") {
+ selectAttributes.multiple = true;
+ }
+ return HTMLResult.success({
+ name: "label",
+ attributes: {
+ class: ["xfaLabel"]
+ },
+ children: [{
+ name: "select",
+ children,
+ attributes: selectAttributes
+ }]
+ });
+ }
+}
+class Color extends XFAObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "color", true);
+ this.cSpace = getStringOption(attributes.cSpace, ["SRGB"]);
+ this.id = attributes.id || "";
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ this.value = attributes.value ? getColor(attributes.value) : "";
+ this.extras = null;
+ }
+ [$hasSettableValue]() {
+ return false;
+ }
+ [$toStyle]() {
+ return this.value ? Util.makeHexColor(this.value.r, this.value.g, this.value.b) : null;
+ }
+}
+class Comb extends XFAObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "comb");
+ this.id = attributes.id || "";
+ this.numberOfCells = getInteger({
+ data: attributes.numberOfCells,
+ defaultValue: 0,
+ validate: x => x >= 0
+ });
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ }
+}
+class Connect extends XFAObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "connect", true);
+ this.connection = attributes.connection || "";
+ this.id = attributes.id || "";
+ this.ref = attributes.ref || "";
+ this.usage = getStringOption(attributes.usage, ["exportAndImport", "exportOnly", "importOnly"]);
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ this.picture = null;
+ }
+}
+class ContentArea extends XFAObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "contentArea", true);
+ this.h = getMeasurement(attributes.h);
+ this.id = attributes.id || "";
+ this.name = attributes.name || "";
+ this.relevant = getRelevant(attributes.relevant);
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ this.w = getMeasurement(attributes.w);
+ this.x = getMeasurement(attributes.x, "0pt");
+ this.y = getMeasurement(attributes.y, "0pt");
+ this.desc = null;
+ this.extras = null;
+ }
+ [$toHTML](availableSpace) {
+ const left = measureToString(this.x);
+ const top = measureToString(this.y);
+ const style = {
+ left,
+ top,
+ width: measureToString(this.w),
+ height: measureToString(this.h)
+ };
+ const classNames = ["xfaContentarea"];
+ if (isPrintOnly(this)) {
+ classNames.push("xfaPrintOnly");
+ }
+ return HTMLResult.success({
+ name: "div",
+ children: [],
+ attributes: {
+ style,
+ class: classNames,
+ id: this[$uid]
+ }
+ });
+ }
+}
+class Corner extends XFAObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "corner", true);
+ this.id = attributes.id || "";
+ this.inverted = getInteger({
+ data: attributes.inverted,
+ defaultValue: 0,
+ validate: x => x === 1
+ });
+ this.join = getStringOption(attributes.join, ["square", "round"]);
+ this.presence = getStringOption(attributes.presence, ["visible", "hidden", "inactive", "invisible"]);
+ this.radius = getMeasurement(attributes.radius);
+ this.stroke = getStringOption(attributes.stroke, ["solid", "dashDot", "dashDotDot", "dashed", "dotted", "embossed", "etched", "lowered", "raised"]);
+ this.thickness = getMeasurement(attributes.thickness, "0.5pt");
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ this.color = null;
+ this.extras = null;
+ }
+ [$toStyle]() {
+ const style = toStyle(this, "visibility");
+ style.radius = measureToString(this.join === "square" ? 0 : this.radius);
+ return style;
+ }
+}
+class DateElement extends ContentObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "date");
+ this.id = attributes.id || "";
+ this.name = attributes.name || "";
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ }
+ [$finalize]() {
+ const date = this[$content].trim();
+ this[$content] = date ? new Date(date) : null;
+ }
+ [$toHTML](availableSpace) {
+ return valueToHtml(this[$content] ? this[$content].toString() : "");
+ }
+}
+class DateTime extends ContentObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "dateTime");
+ this.id = attributes.id || "";
+ this.name = attributes.name || "";
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ }
+ [$finalize]() {
+ const date = this[$content].trim();
+ this[$content] = date ? new Date(date) : null;
+ }
+ [$toHTML](availableSpace) {
+ return valueToHtml(this[$content] ? this[$content].toString() : "");
+ }
+}
+class DateTimeEdit extends XFAObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "dateTimeEdit", true);
+ this.hScrollPolicy = getStringOption(attributes.hScrollPolicy, ["auto", "off", "on"]);
+ this.id = attributes.id || "";
+ this.picker = getStringOption(attributes.picker, ["host", "none"]);
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ this.border = null;
+ this.comb = null;
+ this.extras = null;
+ this.margin = null;
+ }
+ [$toHTML](availableSpace) {
+ const style = toStyle(this, "border", "font", "margin");
+ const field = this[$getParent]()[$getParent]();
+ const html = {
+ name: "input",
+ attributes: {
+ type: "text",
+ fieldId: field[$uid],
+ dataId: field[$data]?.[$uid] || field[$uid],
+ class: ["xfaTextfield"],
+ style,
+ "aria-label": ariaLabel(field),
+ "aria-required": false
+ }
+ };
+ if (isRequired(field)) {
+ html.attributes["aria-required"] = true;
+ html.attributes.required = true;
+ }
+ return HTMLResult.success({
+ name: "label",
+ attributes: {
+ class: ["xfaLabel"]
+ },
+ children: [html]
+ });
+ }
+}
+class Decimal extends ContentObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "decimal");
+ this.fracDigits = getInteger({
+ data: attributes.fracDigits,
+ defaultValue: 2,
+ validate: x => true
+ });
+ this.id = attributes.id || "";
+ this.leadDigits = getInteger({
+ data: attributes.leadDigits,
+ defaultValue: -1,
+ validate: x => true
+ });
+ this.name = attributes.name || "";
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ }
+ [$finalize]() {
+ const number = parseFloat(this[$content].trim());
+ this[$content] = isNaN(number) ? null : number;
+ }
+ [$toHTML](availableSpace) {
+ return valueToHtml(this[$content] !== null ? this[$content].toString() : "");
+ }
+}
+class DefaultUi extends XFAObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "defaultUi", true);
+ this.id = attributes.id || "";
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ this.extras = null;
+ }
+}
+class Desc extends XFAObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "desc", true);
+ this.id = attributes.id || "";
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ this.boolean = new XFAObjectArray();
+ this.date = new XFAObjectArray();
+ this.dateTime = new XFAObjectArray();
+ this.decimal = new XFAObjectArray();
+ this.exData = new XFAObjectArray();
+ this.float = new XFAObjectArray();
+ this.image = new XFAObjectArray();
+ this.integer = new XFAObjectArray();
+ this.text = new XFAObjectArray();
+ this.time = new XFAObjectArray();
+ }
+}
+class DigestMethod extends OptionObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "digestMethod", ["", "SHA1", "SHA256", "SHA512", "RIPEMD160"]);
+ this.id = attributes.id || "";
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ }
+}
+class DigestMethods extends XFAObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "digestMethods", true);
+ this.id = attributes.id || "";
+ this.type = getStringOption(attributes.type, ["optional", "required"]);
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ this.digestMethod = new XFAObjectArray();
+ }
+}
+class Draw extends XFAObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "draw", true);
+ this.anchorType = getStringOption(attributes.anchorType, ["topLeft", "bottomCenter", "bottomLeft", "bottomRight", "middleCenter", "middleLeft", "middleRight", "topCenter", "topRight"]);
+ this.colSpan = getInteger({
+ data: attributes.colSpan,
+ defaultValue: 1,
+ validate: n => n >= 1 || n === -1
+ });
+ this.h = attributes.h ? getMeasurement(attributes.h) : "";
+ this.hAlign = getStringOption(attributes.hAlign, ["left", "center", "justify", "justifyAll", "radix", "right"]);
+ this.id = attributes.id || "";
+ this.locale = attributes.locale || "";
+ this.maxH = getMeasurement(attributes.maxH, "0pt");
+ this.maxW = getMeasurement(attributes.maxW, "0pt");
+ this.minH = getMeasurement(attributes.minH, "0pt");
+ this.minW = getMeasurement(attributes.minW, "0pt");
+ this.name = attributes.name || "";
+ this.presence = getStringOption(attributes.presence, ["visible", "hidden", "inactive", "invisible"]);
+ this.relevant = getRelevant(attributes.relevant);
+ this.rotate = getInteger({
+ data: attributes.rotate,
+ defaultValue: 0,
+ validate: x => x % 90 === 0
+ });
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ this.w = attributes.w ? getMeasurement(attributes.w) : "";
+ this.x = getMeasurement(attributes.x, "0pt");
+ this.y = getMeasurement(attributes.y, "0pt");
+ this.assist = null;
+ this.border = null;
+ this.caption = null;
+ this.desc = null;
+ this.extras = null;
+ this.font = null;
+ this.keep = null;
+ this.margin = null;
+ this.para = null;
+ this.traversal = null;
+ this.ui = null;
+ this.value = null;
+ this.setProperty = new XFAObjectArray();
+ }
+ [$setValue](value) {
+ _setValue(this, value);
+ }
+ [$toHTML](availableSpace) {
+ setTabIndex(this);
+ if (this.presence === "hidden" || this.presence === "inactive") {
+ return HTMLResult.EMPTY;
+ }
+ fixDimensions(this);
+ this[$pushPara]();
+ const savedW = this.w;
+ const savedH = this.h;
+ const {
+ w,
+ h,
+ isBroken
+ } = layoutNode(this, availableSpace);
+ if (w && this.w === "") {
+ if (isBroken && this[$getSubformParent]()[$isThereMoreWidth]()) {
+ this[$popPara]();
+ return HTMLResult.FAILURE;
+ }
+ this.w = w;
+ }
+ if (h && this.h === "") {
+ this.h = h;
+ }
+ setFirstUnsplittable(this);
+ if (!checkDimensions(this, availableSpace)) {
+ this.w = savedW;
+ this.h = savedH;
+ this[$popPara]();
+ return HTMLResult.FAILURE;
+ }
+ unsetFirstUnsplittable(this);
+ const style = toStyle(this, "font", "hAlign", "dimensions", "position", "presence", "rotate", "anchorType", "border", "margin");
+ setMinMaxDimensions(this, style);
+ if (style.margin) {
+ style.padding = style.margin;
+ delete style.margin;
+ }
+ const classNames = ["xfaDraw"];
+ if (this.font) {
+ classNames.push("xfaFont");
+ }
+ if (isPrintOnly(this)) {
+ classNames.push("xfaPrintOnly");
+ }
+ const attributes = {
+ style,
+ id: this[$uid],
+ class: classNames
+ };
+ if (this.name) {
+ attributes.xfaName = this.name;
+ }
+ const html = {
+ name: "div",
+ attributes,
+ children: []
+ };
+ applyAssist(this, attributes);
+ const bbox = computeBbox(this, html, availableSpace);
+ const value = this.value ? this.value[$toHTML](availableSpace).html : null;
+ if (value === null) {
+ this.w = savedW;
+ this.h = savedH;
+ this[$popPara]();
+ return HTMLResult.success(createWrapper(this, html), bbox);
+ }
+ html.children.push(value);
+ setPara(this, style, value);
+ this.w = savedW;
+ this.h = savedH;
+ this[$popPara]();
+ return HTMLResult.success(createWrapper(this, html), bbox);
+ }
+}
+class Edge extends XFAObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "edge", true);
+ this.cap = getStringOption(attributes.cap, ["square", "butt", "round"]);
+ this.id = attributes.id || "";
+ this.presence = getStringOption(attributes.presence, ["visible", "hidden", "inactive", "invisible"]);
+ this.stroke = getStringOption(attributes.stroke, ["solid", "dashDot", "dashDotDot", "dashed", "dotted", "embossed", "etched", "lowered", "raised"]);
+ this.thickness = getMeasurement(attributes.thickness, "0.5pt");
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ this.color = null;
+ this.extras = null;
+ }
+ [$toStyle]() {
+ const style = toStyle(this, "visibility");
+ Object.assign(style, {
+ linecap: this.cap,
+ width: measureToString(this.thickness),
+ color: this.color ? this.color[$toStyle]() : "#000000",
+ style: ""
+ });
+ if (this.presence !== "visible") {
+ style.style = "none";
+ } else {
+ switch (this.stroke) {
+ case "solid":
+ style.style = "solid";
+ break;
+ case "dashDot":
+ style.style = "dashed";
+ break;
+ case "dashDotDot":
+ style.style = "dashed";
+ break;
+ case "dashed":
+ style.style = "dashed";
+ break;
+ case "dotted":
+ style.style = "dotted";
+ break;
+ case "embossed":
+ style.style = "ridge";
+ break;
+ case "etched":
+ style.style = "groove";
+ break;
+ case "lowered":
+ style.style = "inset";
+ break;
+ case "raised":
+ style.style = "outset";
+ break;
+ }
+ }
+ return style;
+ }
+}
+class Encoding extends OptionObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "encoding", ["adbe.x509.rsa_sha1", "adbe.pkcs7.detached", "adbe.pkcs7.sha1"]);
+ this.id = attributes.id || "";
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ }
+}
+class Encodings extends XFAObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "encodings", true);
+ this.id = attributes.id || "";
+ this.type = getStringOption(attributes.type, ["optional", "required"]);
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ this.encoding = new XFAObjectArray();
+ }
+}
+class Encrypt extends XFAObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "encrypt", true);
+ this.id = attributes.id || "";
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ this.certificate = null;
+ }
+}
+class EncryptData extends XFAObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "encryptData", true);
+ this.id = attributes.id || "";
+ this.operation = getStringOption(attributes.operation, ["encrypt", "decrypt"]);
+ this.target = attributes.target || "";
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ this.filter = null;
+ this.manifest = null;
+ }
+}
+class Encryption extends XFAObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "encryption", true);
+ this.id = attributes.id || "";
+ this.type = getStringOption(attributes.type, ["optional", "required"]);
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ this.certificate = new XFAObjectArray();
+ }
+}
+class EncryptionMethod extends OptionObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "encryptionMethod", ["", "AES256-CBC", "TRIPLEDES-CBC", "AES128-CBC", "AES192-CBC"]);
+ this.id = attributes.id || "";
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ }
+}
+class EncryptionMethods extends XFAObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "encryptionMethods", true);
+ this.id = attributes.id || "";
+ this.type = getStringOption(attributes.type, ["optional", "required"]);
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ this.encryptionMethod = new XFAObjectArray();
+ }
+}
+class Event extends XFAObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "event", true);
+ this.activity = getStringOption(attributes.activity, ["click", "change", "docClose", "docReady", "enter", "exit", "full", "indexChange", "initialize", "mouseDown", "mouseEnter", "mouseExit", "mouseUp", "postExecute", "postOpen", "postPrint", "postSave", "postSign", "postSubmit", "preExecute", "preOpen", "prePrint", "preSave", "preSign", "preSubmit", "ready", "validationState"]);
+ this.id = attributes.id || "";
+ this.listen = getStringOption(attributes.listen, ["refOnly", "refAndDescendents"]);
+ this.name = attributes.name || "";
+ this.ref = attributes.ref || "";
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ this.extras = null;
+ this.encryptData = null;
+ this.execute = null;
+ this.script = null;
+ this.signData = null;
+ this.submit = null;
+ }
+}
+class ExData extends ContentObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "exData");
+ this.contentType = attributes.contentType || "";
+ this.href = attributes.href || "";
+ this.id = attributes.id || "";
+ this.maxLength = getInteger({
+ data: attributes.maxLength,
+ defaultValue: -1,
+ validate: x => x >= -1
+ });
+ this.name = attributes.name || "";
+ this.rid = attributes.rid || "";
+ this.transferEncoding = getStringOption(attributes.transferEncoding, ["none", "base64", "package"]);
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ }
+ [$isCDATAXml]() {
+ return this.contentType === "text/html";
+ }
+ [$onChild](child) {
+ if (this.contentType === "text/html" && child[$namespaceId] === NamespaceIds.xhtml.id) {
+ this[$content] = child;
+ return true;
+ }
+ if (this.contentType === "text/xml") {
+ this[$content] = child;
+ return true;
+ }
+ return false;
+ }
+ [$toHTML](availableSpace) {
+ if (this.contentType !== "text/html" || !this[$content]) {
+ return HTMLResult.EMPTY;
+ }
+ return this[$content][$toHTML](availableSpace);
+ }
+}
+class ExObject extends XFAObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "exObject", true);
+ this.archive = attributes.archive || "";
+ this.classId = attributes.classId || "";
+ this.codeBase = attributes.codeBase || "";
+ this.codeType = attributes.codeType || "";
+ this.id = attributes.id || "";
+ this.name = attributes.name || "";
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ this.extras = null;
+ this.boolean = new XFAObjectArray();
+ this.date = new XFAObjectArray();
+ this.dateTime = new XFAObjectArray();
+ this.decimal = new XFAObjectArray();
+ this.exData = new XFAObjectArray();
+ this.exObject = new XFAObjectArray();
+ this.float = new XFAObjectArray();
+ this.image = new XFAObjectArray();
+ this.integer = new XFAObjectArray();
+ this.text = new XFAObjectArray();
+ this.time = new XFAObjectArray();
+ }
+}
+class ExclGroup extends XFAObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "exclGroup", true);
+ this.access = getStringOption(attributes.access, ["open", "nonInteractive", "protected", "readOnly"]);
+ this.accessKey = attributes.accessKey || "";
+ this.anchorType = getStringOption(attributes.anchorType, ["topLeft", "bottomCenter", "bottomLeft", "bottomRight", "middleCenter", "middleLeft", "middleRight", "topCenter", "topRight"]);
+ this.colSpan = getInteger({
+ data: attributes.colSpan,
+ defaultValue: 1,
+ validate: n => n >= 1 || n === -1
+ });
+ this.h = attributes.h ? getMeasurement(attributes.h) : "";
+ this.hAlign = getStringOption(attributes.hAlign, ["left", "center", "justify", "justifyAll", "radix", "right"]);
+ this.id = attributes.id || "";
+ this.layout = getStringOption(attributes.layout, ["position", "lr-tb", "rl-row", "rl-tb", "row", "table", "tb"]);
+ this.maxH = getMeasurement(attributes.maxH, "0pt");
+ this.maxW = getMeasurement(attributes.maxW, "0pt");
+ this.minH = getMeasurement(attributes.minH, "0pt");
+ this.minW = getMeasurement(attributes.minW, "0pt");
+ this.name = attributes.name || "";
+ this.presence = getStringOption(attributes.presence, ["visible", "hidden", "inactive", "invisible"]);
+ this.relevant = getRelevant(attributes.relevant);
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ this.w = attributes.w ? getMeasurement(attributes.w) : "";
+ this.x = getMeasurement(attributes.x, "0pt");
+ this.y = getMeasurement(attributes.y, "0pt");
+ this.assist = null;
+ this.bind = null;
+ this.border = null;
+ this.calculate = null;
+ this.caption = null;
+ this.desc = null;
+ this.extras = null;
+ this.margin = null;
+ this.para = null;
+ this.traversal = null;
+ this.validate = null;
+ this.connect = new XFAObjectArray();
+ this.event = new XFAObjectArray();
+ this.field = new XFAObjectArray();
+ this.setProperty = new XFAObjectArray();
+ }
+ [$isBindable]() {
+ return true;
+ }
+ [$hasSettableValue]() {
+ return true;
+ }
+ [$setValue](value) {
+ for (const field of this.field.children) {
+ if (!field.value) {
+ const nodeValue = new Value({});
+ field[$appendChild](nodeValue);
+ field.value = nodeValue;
+ }
+ field.value[$setValue](value);
+ }
+ }
+ [$isThereMoreWidth]() {
+ return this.layout.endsWith("-tb") && this[$extra].attempt === 0 && this[$extra].numberInLine > 0 || this[$getParent]()[$isThereMoreWidth]();
+ }
+ [$isSplittable]() {
+ const parent = this[$getSubformParent]();
+ if (!parent[$isSplittable]()) {
+ return false;
+ }
+ if (this[$extra]._isSplittable !== undefined) {
+ return this[$extra]._isSplittable;
+ }
+ if (this.layout === "position" || this.layout.includes("row")) {
+ this[$extra]._isSplittable = false;
+ return false;
+ }
+ if (parent.layout?.endsWith("-tb") && parent[$extra].numberInLine !== 0) {
+ return false;
+ }
+ this[$extra]._isSplittable = true;
+ return true;
+ }
+ [$flushHTML]() {
+ return flushHTML(this);
+ }
+ [$addHTML](html, bbox) {
+ addHTML(this, html, bbox);
+ }
+ [$getAvailableSpace]() {
+ return getAvailableSpace(this);
+ }
+ [$toHTML](availableSpace) {
+ setTabIndex(this);
+ if (this.presence === "hidden" || this.presence === "inactive" || this.h === 0 || this.w === 0) {
+ return HTMLResult.EMPTY;
+ }
+ fixDimensions(this);
+ const children = [];
+ const attributes = {
+ id: this[$uid],
+ class: []
+ };
+ setAccess(this, attributes.class);
+ if (!this[$extra]) {
+ this[$extra] = Object.create(null);
+ }
+ Object.assign(this[$extra], {
+ children,
+ attributes,
+ attempt: 0,
+ line: null,
+ numberInLine: 0,
+ availableSpace: {
+ width: Math.min(this.w || Infinity, availableSpace.width),
+ height: Math.min(this.h || Infinity, availableSpace.height)
+ },
+ width: 0,
+ height: 0,
+ prevHeight: 0,
+ currentWidth: 0
+ });
+ const isSplittable = this[$isSplittable]();
+ if (!isSplittable) {
+ setFirstUnsplittable(this);
+ }
+ if (!checkDimensions(this, availableSpace)) {
+ return HTMLResult.FAILURE;
+ }
+ const filter = new Set(["field"]);
+ if (this.layout.includes("row")) {
+ const columnWidths = this[$getSubformParent]().columnWidths;
+ if (Array.isArray(columnWidths) && columnWidths.length > 0) {
+ this[$extra].columnWidths = columnWidths;
+ this[$extra].currentColumn = 0;
+ }
+ }
+ const style = toStyle(this, "anchorType", "dimensions", "position", "presence", "border", "margin", "hAlign");
+ const classNames = ["xfaExclgroup"];
+ const cl = layoutClass(this);
+ if (cl) {
+ classNames.push(cl);
+ }
+ if (isPrintOnly(this)) {
+ classNames.push("xfaPrintOnly");
+ }
+ attributes.style = style;
+ attributes.class = classNames;
+ if (this.name) {
+ attributes.xfaName = this.name;
+ }
+ this[$pushPara]();
+ const isLrTb = this.layout === "lr-tb" || this.layout === "rl-tb";
+ const maxRun = isLrTb ? MAX_ATTEMPTS_FOR_LRTB_LAYOUT : 1;
+ for (; this[$extra].attempt < maxRun; this[$extra].attempt++) {
+ if (isLrTb && this[$extra].attempt === MAX_ATTEMPTS_FOR_LRTB_LAYOUT - 1) {
+ this[$extra].numberInLine = 0;
+ }
+ const result = this[$childrenToHTML]({
+ filter,
+ include: true
+ });
+ if (result.success) {
+ break;
+ }
+ if (result.isBreak()) {
+ this[$popPara]();
+ return result;
+ }
+ if (isLrTb && this[$extra].attempt === 0 && this[$extra].numberInLine === 0 && !this[$getTemplateRoot]()[$extra].noLayoutFailure) {
+ this[$extra].attempt = maxRun;
+ break;
+ }
+ }
+ this[$popPara]();
+ if (!isSplittable) {
+ unsetFirstUnsplittable(this);
+ }
+ if (this[$extra].attempt === maxRun) {
+ if (!isSplittable) {
+ delete this[$extra];
+ }
+ return HTMLResult.FAILURE;
+ }
+ let marginH = 0;
+ let marginV = 0;
+ if (this.margin) {
+ marginH = this.margin.leftInset + this.margin.rightInset;
+ marginV = this.margin.topInset + this.margin.bottomInset;
+ }
+ const width = Math.max(this[$extra].width + marginH, this.w || 0);
+ const height = Math.max(this[$extra].height + marginV, this.h || 0);
+ const bbox = [this.x, this.y, width, height];
+ if (this.w === "") {
+ style.width = measureToString(width);
+ }
+ if (this.h === "") {
+ style.height = measureToString(height);
+ }
+ const html = {
+ name: "div",
+ attributes,
+ children
+ };
+ applyAssist(this, attributes);
+ delete this[$extra];
+ return HTMLResult.success(createWrapper(this, html), bbox);
+ }
+}
+class Execute extends XFAObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "execute");
+ this.connection = attributes.connection || "";
+ this.executeType = getStringOption(attributes.executeType, ["import", "remerge"]);
+ this.id = attributes.id || "";
+ this.runAt = getStringOption(attributes.runAt, ["client", "both", "server"]);
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ }
+}
+class Extras extends XFAObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "extras", true);
+ this.id = attributes.id || "";
+ this.name = attributes.name || "";
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ this.boolean = new XFAObjectArray();
+ this.date = new XFAObjectArray();
+ this.dateTime = new XFAObjectArray();
+ this.decimal = new XFAObjectArray();
+ this.exData = new XFAObjectArray();
+ this.extras = new XFAObjectArray();
+ this.float = new XFAObjectArray();
+ this.image = new XFAObjectArray();
+ this.integer = new XFAObjectArray();
+ this.text = new XFAObjectArray();
+ this.time = new XFAObjectArray();
+ }
+}
+class Field extends XFAObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "field", true);
+ this.access = getStringOption(attributes.access, ["open", "nonInteractive", "protected", "readOnly"]);
+ this.accessKey = attributes.accessKey || "";
+ this.anchorType = getStringOption(attributes.anchorType, ["topLeft", "bottomCenter", "bottomLeft", "bottomRight", "middleCenter", "middleLeft", "middleRight", "topCenter", "topRight"]);
+ this.colSpan = getInteger({
+ data: attributes.colSpan,
+ defaultValue: 1,
+ validate: n => n >= 1 || n === -1
+ });
+ this.h = attributes.h ? getMeasurement(attributes.h) : "";
+ this.hAlign = getStringOption(attributes.hAlign, ["left", "center", "justify", "justifyAll", "radix", "right"]);
+ this.id = attributes.id || "";
+ this.locale = attributes.locale || "";
+ this.maxH = getMeasurement(attributes.maxH, "0pt");
+ this.maxW = getMeasurement(attributes.maxW, "0pt");
+ this.minH = getMeasurement(attributes.minH, "0pt");
+ this.minW = getMeasurement(attributes.minW, "0pt");
+ this.name = attributes.name || "";
+ this.presence = getStringOption(attributes.presence, ["visible", "hidden", "inactive", "invisible"]);
+ this.relevant = getRelevant(attributes.relevant);
+ this.rotate = getInteger({
+ data: attributes.rotate,
+ defaultValue: 0,
+ validate: x => x % 90 === 0
+ });
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ this.w = attributes.w ? getMeasurement(attributes.w) : "";
+ this.x = getMeasurement(attributes.x, "0pt");
+ this.y = getMeasurement(attributes.y, "0pt");
+ this.assist = null;
+ this.bind = null;
+ this.border = null;
+ this.calculate = null;
+ this.caption = null;
+ this.desc = null;
+ this.extras = null;
+ this.font = null;
+ this.format = null;
+ this.items = new XFAObjectArray(2);
+ this.keep = null;
+ this.margin = null;
+ this.para = null;
+ this.traversal = null;
+ this.ui = null;
+ this.validate = null;
+ this.value = null;
+ this.bindItems = new XFAObjectArray();
+ this.connect = new XFAObjectArray();
+ this.event = new XFAObjectArray();
+ this.setProperty = new XFAObjectArray();
+ }
+ [$isBindable]() {
+ return true;
+ }
+ [$setValue](value) {
+ _setValue(this, value);
+ }
+ [$toHTML](availableSpace) {
+ setTabIndex(this);
+ if (!this.ui) {
+ this.ui = new Ui({});
+ this.ui[$globalData] = this[$globalData];
+ this[$appendChild](this.ui);
+ let node;
+ switch (this.items.children.length) {
+ case 0:
+ node = new TextEdit({});
+ this.ui.textEdit = node;
+ break;
+ case 1:
+ node = new CheckButton({});
+ this.ui.checkButton = node;
+ break;
+ case 2:
+ node = new ChoiceList({});
+ this.ui.choiceList = node;
+ break;
+ }
+ this.ui[$appendChild](node);
+ }
+ if (!this.ui || this.presence === "hidden" || this.presence === "inactive" || this.h === 0 || this.w === 0) {
+ return HTMLResult.EMPTY;
+ }
+ if (this.caption) {
+ delete this.caption[$extra];
+ }
+ this[$pushPara]();
+ const caption = this.caption ? this.caption[$toHTML](availableSpace).html : null;
+ const savedW = this.w;
+ const savedH = this.h;
+ let marginH = 0;
+ let marginV = 0;
+ if (this.margin) {
+ marginH = this.margin.leftInset + this.margin.rightInset;
+ marginV = this.margin.topInset + this.margin.bottomInset;
+ }
+ let borderDims = null;
+ if (this.w === "" || this.h === "") {
+ let width = null;
+ let height = null;
+ let uiW = 0;
+ let uiH = 0;
+ if (this.ui.checkButton) {
+ uiW = uiH = this.ui.checkButton.size;
+ } else {
+ const {
+ w,
+ h
+ } = layoutNode(this, availableSpace);
+ if (w !== null) {
+ uiW = w;
+ uiH = h;
+ } else {
+ uiH = fonts_getMetrics(this.font, true).lineNoGap;
+ }
+ }
+ borderDims = getBorderDims(this.ui[$getExtra]());
+ uiW += borderDims.w;
+ uiH += borderDims.h;
+ if (this.caption) {
+ const {
+ w,
+ h,
+ isBroken
+ } = this.caption[$getExtra](availableSpace);
+ if (isBroken && this[$getSubformParent]()[$isThereMoreWidth]()) {
+ this[$popPara]();
+ return HTMLResult.FAILURE;
+ }
+ width = w;
+ height = h;
+ switch (this.caption.placement) {
+ case "left":
+ case "right":
+ case "inline":
+ width += uiW;
+ break;
+ case "top":
+ case "bottom":
+ height += uiH;
+ break;
+ }
+ } else {
+ width = uiW;
+ height = uiH;
+ }
+ if (width && this.w === "") {
+ width += marginH;
+ this.w = Math.min(this.maxW <= 0 ? Infinity : this.maxW, this.minW + 1 < width ? width : this.minW);
+ }
+ if (height && this.h === "") {
+ height += marginV;
+ this.h = Math.min(this.maxH <= 0 ? Infinity : this.maxH, this.minH + 1 < height ? height : this.minH);
+ }
+ }
+ this[$popPara]();
+ fixDimensions(this);
+ setFirstUnsplittable(this);
+ if (!checkDimensions(this, availableSpace)) {
+ this.w = savedW;
+ this.h = savedH;
+ this[$popPara]();
+ return HTMLResult.FAILURE;
+ }
+ unsetFirstUnsplittable(this);
+ const style = toStyle(this, "font", "dimensions", "position", "rotate", "anchorType", "presence", "margin", "hAlign");
+ setMinMaxDimensions(this, style);
+ const classNames = ["xfaField"];
+ if (this.font) {
+ classNames.push("xfaFont");
+ }
+ if (isPrintOnly(this)) {
+ classNames.push("xfaPrintOnly");
+ }
+ const attributes = {
+ style,
+ id: this[$uid],
+ class: classNames
+ };
+ if (style.margin) {
+ style.padding = style.margin;
+ delete style.margin;
+ }
+ setAccess(this, classNames);
+ if (this.name) {
+ attributes.xfaName = this.name;
+ }
+ const children = [];
+ const html = {
+ name: "div",
+ attributes,
+ children
+ };
+ applyAssist(this, attributes);
+ const borderStyle = this.border ? this.border[$toStyle]() : null;
+ const bbox = computeBbox(this, html, availableSpace);
+ const ui = this.ui[$toHTML]().html;
+ if (!ui) {
+ Object.assign(style, borderStyle);
+ return HTMLResult.success(createWrapper(this, html), bbox);
+ }
+ if (this[$tabIndex]) {
+ if (ui.children?.[0]) {
+ ui.children[0].attributes.tabindex = this[$tabIndex];
+ } else {
+ ui.attributes.tabindex = this[$tabIndex];
+ }
+ }
+ if (!ui.attributes.style) {
+ ui.attributes.style = Object.create(null);
+ }
+ let aElement = null;
+ if (this.ui.button) {
+ if (ui.children.length === 1) {
+ [aElement] = ui.children.splice(0, 1);
+ }
+ Object.assign(ui.attributes.style, borderStyle);
+ } else {
+ Object.assign(style, borderStyle);
+ }
+ children.push(ui);
+ if (this.value) {
+ if (this.ui.imageEdit) {
+ ui.children.push(this.value[$toHTML]().html);
+ } else if (!this.ui.button) {
+ let value = "";
+ if (this.value.exData) {
+ value = this.value.exData[$text]();
+ } else if (this.value.text) {
+ value = this.value.text[$getExtra]();
+ } else {
+ const htmlValue = this.value[$toHTML]().html;
+ if (htmlValue !== null) {
+ value = htmlValue.children[0].value;
+ }
+ }
+ if (this.ui.textEdit && this.value.text?.maxChars) {
+ ui.children[0].attributes.maxLength = this.value.text.maxChars;
+ }
+ if (value) {
+ if (this.ui.numericEdit) {
+ value = parseFloat(value);
+ value = isNaN(value) ? "" : value.toString();
+ }
+ if (ui.children[0].name === "textarea") {
+ ui.children[0].attributes.textContent = value;
+ } else {
+ ui.children[0].attributes.value = value;
+ }
+ }
+ }
+ }
+ if (!this.ui.imageEdit && ui.children?.[0] && this.h) {
+ borderDims = borderDims || getBorderDims(this.ui[$getExtra]());
+ let captionHeight = 0;
+ if (this.caption && ["top", "bottom"].includes(this.caption.placement)) {
+ captionHeight = this.caption.reserve;
+ if (captionHeight <= 0) {
+ captionHeight = this.caption[$getExtra](availableSpace).h;
+ }
+ const inputHeight = this.h - captionHeight - marginV - borderDims.h;
+ ui.children[0].attributes.style.height = measureToString(inputHeight);
+ } else {
+ ui.children[0].attributes.style.height = "100%";
+ }
+ }
+ if (aElement) {
+ ui.children.push(aElement);
+ }
+ if (!caption) {
+ if (ui.attributes.class) {
+ ui.attributes.class.push("xfaLeft");
+ }
+ this.w = savedW;
+ this.h = savedH;
+ return HTMLResult.success(createWrapper(this, html), bbox);
+ }
+ if (this.ui.button) {
+ if (style.padding) {
+ delete style.padding;
+ }
+ if (caption.name === "div") {
+ caption.name = "span";
+ }
+ ui.children.push(caption);
+ return HTMLResult.success(html, bbox);
+ } else if (this.ui.checkButton) {
+ caption.attributes.class[0] = "xfaCaptionForCheckButton";
+ }
+ if (!ui.attributes.class) {
+ ui.attributes.class = [];
+ }
+ ui.children.splice(0, 0, caption);
+ switch (this.caption.placement) {
+ case "left":
+ ui.attributes.class.push("xfaLeft");
+ break;
+ case "right":
+ ui.attributes.class.push("xfaRight");
+ break;
+ case "top":
+ ui.attributes.class.push("xfaTop");
+ break;
+ case "bottom":
+ ui.attributes.class.push("xfaBottom");
+ break;
+ case "inline":
+ ui.attributes.class.push("xfaLeft");
+ break;
+ }
+ this.w = savedW;
+ this.h = savedH;
+ return HTMLResult.success(createWrapper(this, html), bbox);
+ }
+}
+class Fill extends XFAObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "fill", true);
+ this.id = attributes.id || "";
+ this.presence = getStringOption(attributes.presence, ["visible", "hidden", "inactive", "invisible"]);
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ this.color = null;
+ this.extras = null;
+ this.linear = null;
+ this.pattern = null;
+ this.radial = null;
+ this.solid = null;
+ this.stipple = null;
+ }
+ [$toStyle]() {
+ const parent = this[$getParent]();
+ const grandpa = parent[$getParent]();
+ const ggrandpa = grandpa[$getParent]();
+ const style = Object.create(null);
+ let propName = "color";
+ let altPropName = propName;
+ if (parent instanceof Border) {
+ propName = "background-color";
+ altPropName = "background";
+ if (ggrandpa instanceof Ui) {
+ style.backgroundColor = "white";
+ }
+ }
+ if (parent instanceof Rectangle || parent instanceof Arc) {
+ propName = altPropName = "fill";
+ style.fill = "white";
+ }
+ for (const name of Object.getOwnPropertyNames(this)) {
+ if (name === "extras" || name === "color") {
+ continue;
+ }
+ const obj = this[name];
+ if (!(obj instanceof XFAObject)) {
+ continue;
+ }
+ const color = obj[$toStyle](this.color);
+ if (color) {
+ style[color.startsWith("#") ? propName : altPropName] = color;
+ }
+ return style;
+ }
+ if (this.color?.value) {
+ const color = this.color[$toStyle]();
+ style[color.startsWith("#") ? propName : altPropName] = color;
+ }
+ return style;
+ }
+}
+class Filter extends XFAObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "filter", true);
+ this.addRevocationInfo = getStringOption(attributes.addRevocationInfo, ["", "required", "optional", "none"]);
+ this.id = attributes.id || "";
+ this.name = attributes.name || "";
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ this.version = getInteger({
+ data: this.version,
+ defaultValue: 5,
+ validate: x => x >= 1 && x <= 5
+ });
+ this.appearanceFilter = null;
+ this.certificates = null;
+ this.digestMethods = null;
+ this.encodings = null;
+ this.encryptionMethods = null;
+ this.handler = null;
+ this.lockDocument = null;
+ this.mdp = null;
+ this.reasons = null;
+ this.timeStamp = null;
+ }
+}
+class Float extends ContentObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "float");
+ this.id = attributes.id || "";
+ this.name = attributes.name || "";
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ }
+ [$finalize]() {
+ const number = parseFloat(this[$content].trim());
+ this[$content] = isNaN(number) ? null : number;
+ }
+ [$toHTML](availableSpace) {
+ return valueToHtml(this[$content] !== null ? this[$content].toString() : "");
+ }
+}
+class template_Font extends XFAObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "font", true);
+ this.baselineShift = getMeasurement(attributes.baselineShift);
+ this.fontHorizontalScale = getFloat({
+ data: attributes.fontHorizontalScale,
+ defaultValue: 100,
+ validate: x => x >= 0
+ });
+ this.fontVerticalScale = getFloat({
+ data: attributes.fontVerticalScale,
+ defaultValue: 100,
+ validate: x => x >= 0
+ });
+ this.id = attributes.id || "";
+ this.kerningMode = getStringOption(attributes.kerningMode, ["none", "pair"]);
+ this.letterSpacing = getMeasurement(attributes.letterSpacing, "0");
+ this.lineThrough = getInteger({
+ data: attributes.lineThrough,
+ defaultValue: 0,
+ validate: x => x === 1 || x === 2
+ });
+ this.lineThroughPeriod = getStringOption(attributes.lineThroughPeriod, ["all", "word"]);
+ this.overline = getInteger({
+ data: attributes.overline,
+ defaultValue: 0,
+ validate: x => x === 1 || x === 2
+ });
+ this.overlinePeriod = getStringOption(attributes.overlinePeriod, ["all", "word"]);
+ this.posture = getStringOption(attributes.posture, ["normal", "italic"]);
+ this.size = getMeasurement(attributes.size, "10pt");
+ this.typeface = attributes.typeface || "Courier";
+ this.underline = getInteger({
+ data: attributes.underline,
+ defaultValue: 0,
+ validate: x => x === 1 || x === 2
+ });
+ this.underlinePeriod = getStringOption(attributes.underlinePeriod, ["all", "word"]);
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ this.weight = getStringOption(attributes.weight, ["normal", "bold"]);
+ this.extras = null;
+ this.fill = null;
+ }
+ [$clean](builder) {
+ super[$clean](builder);
+ this[$globalData].usedTypefaces.add(this.typeface);
+ }
+ [$toStyle]() {
+ const style = toStyle(this, "fill");
+ const color = style.color;
+ if (color) {
+ if (color === "#000000") {
+ delete style.color;
+ } else if (!color.startsWith("#")) {
+ style.background = color;
+ style.backgroundClip = "text";
+ style.color = "transparent";
+ }
+ }
+ if (this.baselineShift) {
+ style.verticalAlign = measureToString(this.baselineShift);
+ }
+ style.fontKerning = this.kerningMode === "none" ? "none" : "normal";
+ style.letterSpacing = measureToString(this.letterSpacing);
+ if (this.lineThrough !== 0) {
+ style.textDecoration = "line-through";
+ if (this.lineThrough === 2) {
+ style.textDecorationStyle = "double";
+ }
+ }
+ if (this.overline !== 0) {
+ style.textDecoration = "overline";
+ if (this.overline === 2) {
+ style.textDecorationStyle = "double";
+ }
+ }
+ style.fontStyle = this.posture;
+ style.fontSize = measureToString(0.99 * this.size);
+ setFontFamily(this, this, this[$globalData].fontFinder, style);
+ if (this.underline !== 0) {
+ style.textDecoration = "underline";
+ if (this.underline === 2) {
+ style.textDecorationStyle = "double";
+ }
+ }
+ style.fontWeight = this.weight;
+ return style;
+ }
+}
+class Format extends XFAObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "format", true);
+ this.id = attributes.id || "";
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ this.extras = null;
+ this.picture = null;
+ }
+}
+class Handler extends StringObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "handler");
+ this.id = attributes.id || "";
+ this.type = getStringOption(attributes.type, ["optional", "required"]);
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ }
+}
+class Hyphenation extends XFAObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "hyphenation");
+ this.excludeAllCaps = getInteger({
+ data: attributes.excludeAllCaps,
+ defaultValue: 0,
+ validate: x => x === 1
+ });
+ this.excludeInitialCap = getInteger({
+ data: attributes.excludeInitialCap,
+ defaultValue: 0,
+ validate: x => x === 1
+ });
+ this.hyphenate = getInteger({
+ data: attributes.hyphenate,
+ defaultValue: 0,
+ validate: x => x === 1
+ });
+ this.id = attributes.id || "";
+ this.pushCharacterCount = getInteger({
+ data: attributes.pushCharacterCount,
+ defaultValue: 3,
+ validate: x => x >= 0
+ });
+ this.remainCharacterCount = getInteger({
+ data: attributes.remainCharacterCount,
+ defaultValue: 3,
+ validate: x => x >= 0
+ });
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ this.wordCharacterCount = getInteger({
+ data: attributes.wordCharacterCount,
+ defaultValue: 7,
+ validate: x => x >= 0
+ });
+ }
+}
+class Image extends StringObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "image");
+ this.aspect = getStringOption(attributes.aspect, ["fit", "actual", "height", "none", "width"]);
+ this.contentType = attributes.contentType || "";
+ this.href = attributes.href || "";
+ this.id = attributes.id || "";
+ this.name = attributes.name || "";
+ this.transferEncoding = getStringOption(attributes.transferEncoding, ["base64", "none", "package"]);
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ }
+ [$toHTML]() {
+ if (this.contentType && !MIMES.has(this.contentType.toLowerCase())) {
+ return HTMLResult.EMPTY;
+ }
+ let buffer = this[$globalData].images && this[$globalData].images.get(this.href);
+ if (!buffer && (this.href || !this[$content])) {
+ return HTMLResult.EMPTY;
+ }
+ if (!buffer && this.transferEncoding === "base64") {
+ buffer = stringToBytes(atob(this[$content]));
+ }
+ if (!buffer) {
+ return HTMLResult.EMPTY;
+ }
+ if (!this.contentType) {
+ for (const [header, type] of IMAGES_HEADERS) {
+ if (buffer.length > header.length && header.every((x, i) => x === buffer[i])) {
+ this.contentType = type;
+ break;
+ }
+ }
+ if (!this.contentType) {
+ return HTMLResult.EMPTY;
+ }
+ }
+ const blob = new Blob([buffer], {
+ type: this.contentType
+ });
+ let style;
+ switch (this.aspect) {
+ case "fit":
+ case "actual":
+ break;
+ case "height":
+ style = {
+ height: "100%",
+ objectFit: "fill"
+ };
+ break;
+ case "none":
+ style = {
+ width: "100%",
+ height: "100%",
+ objectFit: "fill"
+ };
+ break;
+ case "width":
+ style = {
+ width: "100%",
+ objectFit: "fill"
+ };
+ break;
+ }
+ const parent = this[$getParent]();
+ return HTMLResult.success({
+ name: "img",
+ attributes: {
+ class: ["xfaImage"],
+ style,
+ src: URL.createObjectURL(blob),
+ alt: parent ? ariaLabel(parent[$getParent]()) : null
+ }
+ });
+ }
+}
+class ImageEdit extends XFAObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "imageEdit", true);
+ this.data = getStringOption(attributes.data, ["link", "embed"]);
+ this.id = attributes.id || "";
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ this.border = null;
+ this.extras = null;
+ this.margin = null;
+ }
+ [$toHTML](availableSpace) {
+ if (this.data === "embed") {
+ return HTMLResult.success({
+ name: "div",
+ children: [],
+ attributes: {}
+ });
+ }
+ return HTMLResult.EMPTY;
+ }
+}
+class Integer extends ContentObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "integer");
+ this.id = attributes.id || "";
+ this.name = attributes.name || "";
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ }
+ [$finalize]() {
+ const number = parseInt(this[$content].trim(), 10);
+ this[$content] = isNaN(number) ? null : number;
+ }
+ [$toHTML](availableSpace) {
+ return valueToHtml(this[$content] !== null ? this[$content].toString() : "");
+ }
+}
+class Issuers extends XFAObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "issuers", true);
+ this.id = attributes.id || "";
+ this.type = getStringOption(attributes.type, ["optional", "required"]);
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ this.certificate = new XFAObjectArray();
+ }
+}
+class Items extends XFAObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "items", true);
+ this.id = attributes.id || "";
+ this.name = attributes.name || "";
+ this.presence = getStringOption(attributes.presence, ["visible", "hidden", "inactive", "invisible"]);
+ this.ref = attributes.ref || "";
+ this.save = getInteger({
+ data: attributes.save,
+ defaultValue: 0,
+ validate: x => x === 1
+ });
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ this.boolean = new XFAObjectArray();
+ this.date = new XFAObjectArray();
+ this.dateTime = new XFAObjectArray();
+ this.decimal = new XFAObjectArray();
+ this.exData = new XFAObjectArray();
+ this.float = new XFAObjectArray();
+ this.image = new XFAObjectArray();
+ this.integer = new XFAObjectArray();
+ this.text = new XFAObjectArray();
+ this.time = new XFAObjectArray();
+ }
+ [$toHTML]() {
+ const output = [];
+ for (const child of this[$getChildren]()) {
+ output.push(child[$text]());
+ }
+ return HTMLResult.success(output);
+ }
+}
+class Keep extends XFAObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "keep", true);
+ this.id = attributes.id || "";
+ const options = ["none", "contentArea", "pageArea"];
+ this.intact = getStringOption(attributes.intact, options);
+ this.next = getStringOption(attributes.next, options);
+ this.previous = getStringOption(attributes.previous, options);
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ this.extras = null;
+ }
+}
+class KeyUsage extends XFAObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "keyUsage");
+ const options = ["", "yes", "no"];
+ this.crlSign = getStringOption(attributes.crlSign, options);
+ this.dataEncipherment = getStringOption(attributes.dataEncipherment, options);
+ this.decipherOnly = getStringOption(attributes.decipherOnly, options);
+ this.digitalSignature = getStringOption(attributes.digitalSignature, options);
+ this.encipherOnly = getStringOption(attributes.encipherOnly, options);
+ this.id = attributes.id || "";
+ this.keyAgreement = getStringOption(attributes.keyAgreement, options);
+ this.keyCertSign = getStringOption(attributes.keyCertSign, options);
+ this.keyEncipherment = getStringOption(attributes.keyEncipherment, options);
+ this.nonRepudiation = getStringOption(attributes.nonRepudiation, options);
+ this.type = getStringOption(attributes.type, ["optional", "required"]);
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ }
+}
+class Line extends XFAObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "line", true);
+ this.hand = getStringOption(attributes.hand, ["even", "left", "right"]);
+ this.id = attributes.id || "";
+ this.slope = getStringOption(attributes.slope, ["\\", "/"]);
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ this.edge = null;
+ }
+ [$toHTML]() {
+ const parent = this[$getParent]()[$getParent]();
+ const edge = this.edge || new Edge({});
+ const edgeStyle = edge[$toStyle]();
+ const style = Object.create(null);
+ const thickness = edge.presence === "visible" ? edge.thickness : 0;
+ style.strokeWidth = measureToString(thickness);
+ style.stroke = edgeStyle.color;
+ let x1, y1, x2, y2;
+ let width = "100%";
+ let height = "100%";
+ if (parent.w <= thickness) {
+ [x1, y1, x2, y2] = ["50%", 0, "50%", "100%"];
+ width = style.strokeWidth;
+ } else if (parent.h <= thickness) {
+ [x1, y1, x2, y2] = [0, "50%", "100%", "50%"];
+ height = style.strokeWidth;
+ } else if (this.slope === "\\") {
+ [x1, y1, x2, y2] = [0, 0, "100%", "100%"];
+ } else {
+ [x1, y1, x2, y2] = [0, "100%", "100%", 0];
+ }
+ const line = {
+ name: "line",
+ attributes: {
+ xmlns: SVG_NS,
+ x1,
+ y1,
+ x2,
+ y2,
+ style
+ }
+ };
+ const svg = {
+ name: "svg",
+ children: [line],
+ attributes: {
+ xmlns: SVG_NS,
+ width,
+ height,
+ style: {
+ overflow: "visible"
+ }
+ }
+ };
+ if (hasMargin(parent)) {
+ return HTMLResult.success({
+ name: "div",
+ attributes: {
+ style: {
+ display: "inline",
+ width: "100%",
+ height: "100%"
+ }
+ },
+ children: [svg]
+ });
+ }
+ svg.attributes.style.position = "absolute";
+ return HTMLResult.success(svg);
+ }
+}
+class Linear extends XFAObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "linear", true);
+ this.id = attributes.id || "";
+ this.type = getStringOption(attributes.type, ["toRight", "toBottom", "toLeft", "toTop"]);
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ this.color = null;
+ this.extras = null;
+ }
+ [$toStyle](startColor) {
+ startColor = startColor ? startColor[$toStyle]() : "#FFFFFF";
+ const transf = this.type.replace(/([RBLT])/, " $1").toLowerCase();
+ const endColor = this.color ? this.color[$toStyle]() : "#000000";
+ return `linear-gradient(${transf}, ${startColor}, ${endColor})`;
+ }
+}
+class LockDocument extends ContentObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "lockDocument");
+ this.id = attributes.id || "";
+ this.type = getStringOption(attributes.type, ["optional", "required"]);
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ }
+ [$finalize]() {
+ this[$content] = getStringOption(this[$content], ["auto", "0", "1"]);
+ }
+}
+class Manifest extends XFAObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "manifest", true);
+ this.action = getStringOption(attributes.action, ["include", "all", "exclude"]);
+ this.id = attributes.id || "";
+ this.name = attributes.name || "";
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ this.extras = null;
+ this.ref = new XFAObjectArray();
+ }
+}
+class Margin extends XFAObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "margin", true);
+ this.bottomInset = getMeasurement(attributes.bottomInset, "0");
+ this.id = attributes.id || "";
+ this.leftInset = getMeasurement(attributes.leftInset, "0");
+ this.rightInset = getMeasurement(attributes.rightInset, "0");
+ this.topInset = getMeasurement(attributes.topInset, "0");
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ this.extras = null;
+ }
+ [$toStyle]() {
+ return {
+ margin: measureToString(this.topInset) + " " + measureToString(this.rightInset) + " " + measureToString(this.bottomInset) + " " + measureToString(this.leftInset)
+ };
+ }
+}
+class Mdp extends XFAObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "mdp");
+ this.id = attributes.id || "";
+ this.permissions = getInteger({
+ data: attributes.permissions,
+ defaultValue: 2,
+ validate: x => x === 1 || x === 3
+ });
+ this.signatureType = getStringOption(attributes.signatureType, ["filler", "author"]);
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ }
+}
+class Medium extends XFAObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "medium");
+ this.id = attributes.id || "";
+ this.imagingBBox = getBBox(attributes.imagingBBox);
+ this.long = getMeasurement(attributes.long);
+ this.orientation = getStringOption(attributes.orientation, ["portrait", "landscape"]);
+ this.short = getMeasurement(attributes.short);
+ this.stock = attributes.stock || "";
+ this.trayIn = getStringOption(attributes.trayIn, ["auto", "delegate", "pageFront"]);
+ this.trayOut = getStringOption(attributes.trayOut, ["auto", "delegate"]);
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ }
+}
+class Message extends XFAObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "message", true);
+ this.id = attributes.id || "";
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ this.text = new XFAObjectArray();
+ }
+}
+class NumericEdit extends XFAObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "numericEdit", true);
+ this.hScrollPolicy = getStringOption(attributes.hScrollPolicy, ["auto", "off", "on"]);
+ this.id = attributes.id || "";
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ this.border = null;
+ this.comb = null;
+ this.extras = null;
+ this.margin = null;
+ }
+ [$toHTML](availableSpace) {
+ const style = toStyle(this, "border", "font", "margin");
+ const field = this[$getParent]()[$getParent]();
+ const html = {
+ name: "input",
+ attributes: {
+ type: "text",
+ fieldId: field[$uid],
+ dataId: field[$data]?.[$uid] || field[$uid],
+ class: ["xfaTextfield"],
+ style,
+ "aria-label": ariaLabel(field),
+ "aria-required": false
+ }
+ };
+ if (isRequired(field)) {
+ html.attributes["aria-required"] = true;
+ html.attributes.required = true;
+ }
+ return HTMLResult.success({
+ name: "label",
+ attributes: {
+ class: ["xfaLabel"]
+ },
+ children: [html]
+ });
+ }
+}
+class Occur extends XFAObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "occur", true);
+ this.id = attributes.id || "";
+ this.initial = attributes.initial !== "" ? getInteger({
+ data: attributes.initial,
+ defaultValue: "",
+ validate: x => true
+ }) : "";
+ this.max = attributes.max !== "" ? getInteger({
+ data: attributes.max,
+ defaultValue: 1,
+ validate: x => true
+ }) : "";
+ this.min = attributes.min !== "" ? getInteger({
+ data: attributes.min,
+ defaultValue: 1,
+ validate: x => true
+ }) : "";
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ this.extras = null;
+ }
+ [$clean]() {
+ const parent = this[$getParent]();
+ const originalMin = this.min;
+ if (this.min === "") {
+ this.min = parent instanceof PageArea || parent instanceof PageSet ? 0 : 1;
+ }
+ if (this.max === "") {
+ if (originalMin === "") {
+ this.max = parent instanceof PageArea || parent instanceof PageSet ? -1 : 1;
+ } else {
+ this.max = this.min;
+ }
+ }
+ if (this.max !== -1 && this.max < this.min) {
+ this.max = this.min;
+ }
+ if (this.initial === "") {
+ this.initial = parent instanceof Template ? 1 : this.min;
+ }
+ }
+}
+class Oid extends StringObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "oid");
+ this.id = attributes.id || "";
+ this.name = attributes.name || "";
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ }
+}
+class Oids extends XFAObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "oids", true);
+ this.id = attributes.id || "";
+ this.type = getStringOption(attributes.type, ["optional", "required"]);
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ this.oid = new XFAObjectArray();
+ }
+}
+class Overflow extends XFAObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "overflow");
+ this.id = attributes.id || "";
+ this.leader = attributes.leader || "";
+ this.target = attributes.target || "";
+ this.trailer = attributes.trailer || "";
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ }
+ [$getExtra]() {
+ if (!this[$extra]) {
+ const parent = this[$getParent]();
+ const root = this[$getTemplateRoot]();
+ const target = root[$searchNode](this.target, parent);
+ const leader = root[$searchNode](this.leader, parent);
+ const trailer = root[$searchNode](this.trailer, parent);
+ this[$extra] = {
+ target: target?.[0] || null,
+ leader: leader?.[0] || null,
+ trailer: trailer?.[0] || null,
+ addLeader: false,
+ addTrailer: false
+ };
+ }
+ return this[$extra];
+ }
+}
+class PageArea extends XFAObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "pageArea", true);
+ this.blankOrNotBlank = getStringOption(attributes.blankOrNotBlank, ["any", "blank", "notBlank"]);
+ this.id = attributes.id || "";
+ this.initialNumber = getInteger({
+ data: attributes.initialNumber,
+ defaultValue: 1,
+ validate: x => true
+ });
+ this.name = attributes.name || "";
+ this.numbered = getInteger({
+ data: attributes.numbered,
+ defaultValue: 1,
+ validate: x => true
+ });
+ this.oddOrEven = getStringOption(attributes.oddOrEven, ["any", "even", "odd"]);
+ this.pagePosition = getStringOption(attributes.pagePosition, ["any", "first", "last", "only", "rest"]);
+ this.relevant = getRelevant(attributes.relevant);
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ this.desc = null;
+ this.extras = null;
+ this.medium = null;
+ this.occur = null;
+ this.area = new XFAObjectArray();
+ this.contentArea = new XFAObjectArray();
+ this.draw = new XFAObjectArray();
+ this.exclGroup = new XFAObjectArray();
+ this.field = new XFAObjectArray();
+ this.subform = new XFAObjectArray();
+ }
+ [$isUsable]() {
+ if (!this[$extra]) {
+ this[$extra] = {
+ numberOfUse: 0
+ };
+ return true;
+ }
+ return !this.occur || this.occur.max === -1 || this[$extra].numberOfUse < this.occur.max;
+ }
+ [$cleanPage]() {
+ delete this[$extra];
+ }
+ [$getNextPage]() {
+ if (!this[$extra]) {
+ this[$extra] = {
+ numberOfUse: 0
+ };
+ }
+ const parent = this[$getParent]();
+ if (parent.relation === "orderedOccurrence") {
+ if (this[$isUsable]()) {
+ this[$extra].numberOfUse += 1;
+ return this;
+ }
+ }
+ return parent[$getNextPage]();
+ }
+ [$getAvailableSpace]() {
+ return this[$extra].space || {
+ width: 0,
+ height: 0
+ };
+ }
+ [$toHTML]() {
+ if (!this[$extra]) {
+ this[$extra] = {
+ numberOfUse: 1
+ };
+ }
+ const children = [];
+ this[$extra].children = children;
+ const style = Object.create(null);
+ if (this.medium && this.medium.short && this.medium.long) {
+ style.width = measureToString(this.medium.short);
+ style.height = measureToString(this.medium.long);
+ this[$extra].space = {
+ width: this.medium.short,
+ height: this.medium.long
+ };
+ if (this.medium.orientation === "landscape") {
+ const x = style.width;
+ style.width = style.height;
+ style.height = x;
+ this[$extra].space = {
+ width: this.medium.long,
+ height: this.medium.short
+ };
+ }
+ } else {
+ warn("XFA - No medium specified in pageArea: please file a bug.");
+ }
+ this[$childrenToHTML]({
+ filter: new Set(["area", "draw", "field", "subform"]),
+ include: true
+ });
+ this[$childrenToHTML]({
+ filter: new Set(["contentArea"]),
+ include: true
+ });
+ return HTMLResult.success({
+ name: "div",
+ children,
+ attributes: {
+ class: ["xfaPage"],
+ id: this[$uid],
+ style,
+ xfaName: this.name
+ }
+ });
+ }
+}
+class PageSet extends XFAObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "pageSet", true);
+ this.duplexImposition = getStringOption(attributes.duplexImposition, ["longEdge", "shortEdge"]);
+ this.id = attributes.id || "";
+ this.name = attributes.name || "";
+ this.relation = getStringOption(attributes.relation, ["orderedOccurrence", "duplexPaginated", "simplexPaginated"]);
+ this.relevant = getRelevant(attributes.relevant);
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ this.extras = null;
+ this.occur = null;
+ this.pageArea = new XFAObjectArray();
+ this.pageSet = new XFAObjectArray();
+ }
+ [$cleanPage]() {
+ for (const page of this.pageArea.children) {
+ page[$cleanPage]();
+ }
+ for (const page of this.pageSet.children) {
+ page[$cleanPage]();
+ }
+ }
+ [$isUsable]() {
+ return !this.occur || this.occur.max === -1 || this[$extra].numberOfUse < this.occur.max;
+ }
+ [$getNextPage]() {
+ if (!this[$extra]) {
+ this[$extra] = {
+ numberOfUse: 1,
+ pageIndex: -1,
+ pageSetIndex: -1
+ };
+ }
+ if (this.relation === "orderedOccurrence") {
+ if (this[$extra].pageIndex + 1 < this.pageArea.children.length) {
+ this[$extra].pageIndex += 1;
+ const pageArea = this.pageArea.children[this[$extra].pageIndex];
+ return pageArea[$getNextPage]();
+ }
+ if (this[$extra].pageSetIndex + 1 < this.pageSet.children.length) {
+ this[$extra].pageSetIndex += 1;
+ return this.pageSet.children[this[$extra].pageSetIndex][$getNextPage]();
+ }
+ if (this[$isUsable]()) {
+ this[$extra].numberOfUse += 1;
+ this[$extra].pageIndex = -1;
+ this[$extra].pageSetIndex = -1;
+ return this[$getNextPage]();
+ }
+ const parent = this[$getParent]();
+ if (parent instanceof PageSet) {
+ return parent[$getNextPage]();
+ }
+ this[$cleanPage]();
+ return this[$getNextPage]();
+ }
+ const pageNumber = this[$getTemplateRoot]()[$extra].pageNumber;
+ const parity = pageNumber % 2 === 0 ? "even" : "odd";
+ const position = pageNumber === 0 ? "first" : "rest";
+ let page = this.pageArea.children.find(p => p.oddOrEven === parity && p.pagePosition === position);
+ if (page) {
+ return page;
+ }
+ page = this.pageArea.children.find(p => p.oddOrEven === "any" && p.pagePosition === position);
+ if (page) {
+ return page;
+ }
+ page = this.pageArea.children.find(p => p.oddOrEven === "any" && p.pagePosition === "any");
+ if (page) {
+ return page;
+ }
+ return this.pageArea.children[0];
+ }
+}
+class Para extends XFAObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "para", true);
+ this.hAlign = getStringOption(attributes.hAlign, ["left", "center", "justify", "justifyAll", "radix", "right"]);
+ this.id = attributes.id || "";
+ this.lineHeight = attributes.lineHeight ? getMeasurement(attributes.lineHeight, "0pt") : "";
+ this.marginLeft = attributes.marginLeft ? getMeasurement(attributes.marginLeft, "0pt") : "";
+ this.marginRight = attributes.marginRight ? getMeasurement(attributes.marginRight, "0pt") : "";
+ this.orphans = getInteger({
+ data: attributes.orphans,
+ defaultValue: 0,
+ validate: x => x >= 0
+ });
+ this.preserve = attributes.preserve || "";
+ this.radixOffset = attributes.radixOffset ? getMeasurement(attributes.radixOffset, "0pt") : "";
+ this.spaceAbove = attributes.spaceAbove ? getMeasurement(attributes.spaceAbove, "0pt") : "";
+ this.spaceBelow = attributes.spaceBelow ? getMeasurement(attributes.spaceBelow, "0pt") : "";
+ this.tabDefault = attributes.tabDefault ? getMeasurement(this.tabDefault) : "";
+ this.tabStops = (attributes.tabStops || "").trim().split(/\s+/).map((x, i) => i % 2 === 1 ? getMeasurement(x) : x);
+ this.textIndent = attributes.textIndent ? getMeasurement(attributes.textIndent, "0pt") : "";
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ this.vAlign = getStringOption(attributes.vAlign, ["top", "bottom", "middle"]);
+ this.widows = getInteger({
+ data: attributes.widows,
+ defaultValue: 0,
+ validate: x => x >= 0
+ });
+ this.hyphenation = null;
+ }
+ [$toStyle]() {
+ const style = toStyle(this, "hAlign");
+ if (this.marginLeft !== "") {
+ style.paddingLeft = measureToString(this.marginLeft);
+ }
+ if (this.marginRight !== "") {
+ style.paddingight = measureToString(this.marginRight);
+ }
+ if (this.spaceAbove !== "") {
+ style.paddingTop = measureToString(this.spaceAbove);
+ }
+ if (this.spaceBelow !== "") {
+ style.paddingBottom = measureToString(this.spaceBelow);
+ }
+ if (this.textIndent !== "") {
+ style.textIndent = measureToString(this.textIndent);
+ fixTextIndent(style);
+ }
+ if (this.lineHeight > 0) {
+ style.lineHeight = measureToString(this.lineHeight);
+ }
+ if (this.tabDefault !== "") {
+ style.tabSize = measureToString(this.tabDefault);
+ }
+ if (this.tabStops.length > 0) {}
+ if (this.hyphenatation) {
+ Object.assign(style, this.hyphenatation[$toStyle]());
+ }
+ return style;
+ }
+}
+class PasswordEdit extends XFAObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "passwordEdit", true);
+ this.hScrollPolicy = getStringOption(attributes.hScrollPolicy, ["auto", "off", "on"]);
+ this.id = attributes.id || "";
+ this.passwordChar = attributes.passwordChar || "*";
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ this.border = null;
+ this.extras = null;
+ this.margin = null;
+ }
+}
+class template_Pattern extends XFAObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "pattern", true);
+ this.id = attributes.id || "";
+ this.type = getStringOption(attributes.type, ["crossHatch", "crossDiagonal", "diagonalLeft", "diagonalRight", "horizontal", "vertical"]);
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ this.color = null;
+ this.extras = null;
+ }
+ [$toStyle](startColor) {
+ startColor = startColor ? startColor[$toStyle]() : "#FFFFFF";
+ const endColor = this.color ? this.color[$toStyle]() : "#000000";
+ const width = 5;
+ const cmd = "repeating-linear-gradient";
+ const colors = `${startColor},${startColor} ${width}px,${endColor} ${width}px,${endColor} ${2 * width}px`;
+ switch (this.type) {
+ case "crossHatch":
+ return `${cmd}(to top,${colors}) ${cmd}(to right,${colors})`;
+ case "crossDiagonal":
+ return `${cmd}(45deg,${colors}) ${cmd}(-45deg,${colors})`;
+ case "diagonalLeft":
+ return `${cmd}(45deg,${colors})`;
+ case "diagonalRight":
+ return `${cmd}(-45deg,${colors})`;
+ case "horizontal":
+ return `${cmd}(to top,${colors})`;
+ case "vertical":
+ return `${cmd}(to right,${colors})`;
+ }
+ return "";
+ }
+}
+class Picture extends StringObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "picture");
+ this.id = attributes.id || "";
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ }
+}
+class Proto extends XFAObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "proto", true);
+ this.appearanceFilter = new XFAObjectArray();
+ this.arc = new XFAObjectArray();
+ this.area = new XFAObjectArray();
+ this.assist = new XFAObjectArray();
+ this.barcode = new XFAObjectArray();
+ this.bindItems = new XFAObjectArray();
+ this.bookend = new XFAObjectArray();
+ this.boolean = new XFAObjectArray();
+ this.border = new XFAObjectArray();
+ this.break = new XFAObjectArray();
+ this.breakAfter = new XFAObjectArray();
+ this.breakBefore = new XFAObjectArray();
+ this.button = new XFAObjectArray();
+ this.calculate = new XFAObjectArray();
+ this.caption = new XFAObjectArray();
+ this.certificate = new XFAObjectArray();
+ this.certificates = new XFAObjectArray();
+ this.checkButton = new XFAObjectArray();
+ this.choiceList = new XFAObjectArray();
+ this.color = new XFAObjectArray();
+ this.comb = new XFAObjectArray();
+ this.connect = new XFAObjectArray();
+ this.contentArea = new XFAObjectArray();
+ this.corner = new XFAObjectArray();
+ this.date = new XFAObjectArray();
+ this.dateTime = new XFAObjectArray();
+ this.dateTimeEdit = new XFAObjectArray();
+ this.decimal = new XFAObjectArray();
+ this.defaultUi = new XFAObjectArray();
+ this.desc = new XFAObjectArray();
+ this.digestMethod = new XFAObjectArray();
+ this.digestMethods = new XFAObjectArray();
+ this.draw = new XFAObjectArray();
+ this.edge = new XFAObjectArray();
+ this.encoding = new XFAObjectArray();
+ this.encodings = new XFAObjectArray();
+ this.encrypt = new XFAObjectArray();
+ this.encryptData = new XFAObjectArray();
+ this.encryption = new XFAObjectArray();
+ this.encryptionMethod = new XFAObjectArray();
+ this.encryptionMethods = new XFAObjectArray();
+ this.event = new XFAObjectArray();
+ this.exData = new XFAObjectArray();
+ this.exObject = new XFAObjectArray();
+ this.exclGroup = new XFAObjectArray();
+ this.execute = new XFAObjectArray();
+ this.extras = new XFAObjectArray();
+ this.field = new XFAObjectArray();
+ this.fill = new XFAObjectArray();
+ this.filter = new XFAObjectArray();
+ this.float = new XFAObjectArray();
+ this.font = new XFAObjectArray();
+ this.format = new XFAObjectArray();
+ this.handler = new XFAObjectArray();
+ this.hyphenation = new XFAObjectArray();
+ this.image = new XFAObjectArray();
+ this.imageEdit = new XFAObjectArray();
+ this.integer = new XFAObjectArray();
+ this.issuers = new XFAObjectArray();
+ this.items = new XFAObjectArray();
+ this.keep = new XFAObjectArray();
+ this.keyUsage = new XFAObjectArray();
+ this.line = new XFAObjectArray();
+ this.linear = new XFAObjectArray();
+ this.lockDocument = new XFAObjectArray();
+ this.manifest = new XFAObjectArray();
+ this.margin = new XFAObjectArray();
+ this.mdp = new XFAObjectArray();
+ this.medium = new XFAObjectArray();
+ this.message = new XFAObjectArray();
+ this.numericEdit = new XFAObjectArray();
+ this.occur = new XFAObjectArray();
+ this.oid = new XFAObjectArray();
+ this.oids = new XFAObjectArray();
+ this.overflow = new XFAObjectArray();
+ this.pageArea = new XFAObjectArray();
+ this.pageSet = new XFAObjectArray();
+ this.para = new XFAObjectArray();
+ this.passwordEdit = new XFAObjectArray();
+ this.pattern = new XFAObjectArray();
+ this.picture = new XFAObjectArray();
+ this.radial = new XFAObjectArray();
+ this.reason = new XFAObjectArray();
+ this.reasons = new XFAObjectArray();
+ this.rectangle = new XFAObjectArray();
+ this.ref = new XFAObjectArray();
+ this.script = new XFAObjectArray();
+ this.setProperty = new XFAObjectArray();
+ this.signData = new XFAObjectArray();
+ this.signature = new XFAObjectArray();
+ this.signing = new XFAObjectArray();
+ this.solid = new XFAObjectArray();
+ this.speak = new XFAObjectArray();
+ this.stipple = new XFAObjectArray();
+ this.subform = new XFAObjectArray();
+ this.subformSet = new XFAObjectArray();
+ this.subjectDN = new XFAObjectArray();
+ this.subjectDNs = new XFAObjectArray();
+ this.submit = new XFAObjectArray();
+ this.text = new XFAObjectArray();
+ this.textEdit = new XFAObjectArray();
+ this.time = new XFAObjectArray();
+ this.timeStamp = new XFAObjectArray();
+ this.toolTip = new XFAObjectArray();
+ this.traversal = new XFAObjectArray();
+ this.traverse = new XFAObjectArray();
+ this.ui = new XFAObjectArray();
+ this.validate = new XFAObjectArray();
+ this.value = new XFAObjectArray();
+ this.variables = new XFAObjectArray();
+ }
+}
+class Radial extends XFAObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "radial", true);
+ this.id = attributes.id || "";
+ this.type = getStringOption(attributes.type, ["toEdge", "toCenter"]);
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ this.color = null;
+ this.extras = null;
+ }
+ [$toStyle](startColor) {
+ startColor = startColor ? startColor[$toStyle]() : "#FFFFFF";
+ const endColor = this.color ? this.color[$toStyle]() : "#000000";
+ const colors = this.type === "toEdge" ? `${startColor},${endColor}` : `${endColor},${startColor}`;
+ return `radial-gradient(circle at center, ${colors})`;
+ }
+}
+class Reason extends StringObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "reason");
+ this.id = attributes.id || "";
+ this.name = attributes.name || "";
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ }
+}
+class Reasons extends XFAObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "reasons", true);
+ this.id = attributes.id || "";
+ this.type = getStringOption(attributes.type, ["optional", "required"]);
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ this.reason = new XFAObjectArray();
+ }
+}
+class Rectangle extends XFAObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "rectangle", true);
+ this.hand = getStringOption(attributes.hand, ["even", "left", "right"]);
+ this.id = attributes.id || "";
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ this.corner = new XFAObjectArray(4);
+ this.edge = new XFAObjectArray(4);
+ this.fill = null;
+ }
+ [$toHTML]() {
+ const edge = this.edge.children.length ? this.edge.children[0] : new Edge({});
+ const edgeStyle = edge[$toStyle]();
+ const style = Object.create(null);
+ if (this.fill?.presence === "visible") {
+ Object.assign(style, this.fill[$toStyle]());
+ } else {
+ style.fill = "transparent";
+ }
+ style.strokeWidth = measureToString(edge.presence === "visible" ? edge.thickness : 0);
+ style.stroke = edgeStyle.color;
+ const corner = this.corner.children.length ? this.corner.children[0] : new Corner({});
+ const cornerStyle = corner[$toStyle]();
+ const rect = {
+ name: "rect",
+ attributes: {
+ xmlns: SVG_NS,
+ width: "100%",
+ height: "100%",
+ x: 0,
+ y: 0,
+ rx: cornerStyle.radius,
+ ry: cornerStyle.radius,
+ style
+ }
+ };
+ const svg = {
+ name: "svg",
+ children: [rect],
+ attributes: {
+ xmlns: SVG_NS,
+ style: {
+ overflow: "visible"
+ },
+ width: "100%",
+ height: "100%"
+ }
+ };
+ const parent = this[$getParent]()[$getParent]();
+ if (hasMargin(parent)) {
+ return HTMLResult.success({
+ name: "div",
+ attributes: {
+ style: {
+ display: "inline",
+ width: "100%",
+ height: "100%"
+ }
+ },
+ children: [svg]
+ });
+ }
+ svg.attributes.style.position = "absolute";
+ return HTMLResult.success(svg);
+ }
+}
+class RefElement extends StringObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "ref");
+ this.id = attributes.id || "";
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ }
+}
+class Script extends StringObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "script");
+ this.binding = attributes.binding || "";
+ this.contentType = attributes.contentType || "";
+ this.id = attributes.id || "";
+ this.name = attributes.name || "";
+ this.runAt = getStringOption(attributes.runAt, ["client", "both", "server"]);
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ }
+}
+class SetProperty extends XFAObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "setProperty");
+ this.connection = attributes.connection || "";
+ this.ref = attributes.ref || "";
+ this.target = attributes.target || "";
+ }
+}
+class SignData extends XFAObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "signData", true);
+ this.id = attributes.id || "";
+ this.operation = getStringOption(attributes.operation, ["sign", "clear", "verify"]);
+ this.ref = attributes.ref || "";
+ this.target = attributes.target || "";
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ this.filter = null;
+ this.manifest = null;
+ }
+}
+class Signature extends XFAObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "signature", true);
+ this.id = attributes.id || "";
+ this.type = getStringOption(attributes.type, ["PDF1.3", "PDF1.6"]);
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ this.border = null;
+ this.extras = null;
+ this.filter = null;
+ this.manifest = null;
+ this.margin = null;
+ }
+}
+class Signing extends XFAObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "signing", true);
+ this.id = attributes.id || "";
+ this.type = getStringOption(attributes.type, ["optional", "required"]);
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ this.certificate = new XFAObjectArray();
+ }
+}
+class Solid extends XFAObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "solid", true);
+ this.id = attributes.id || "";
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ this.extras = null;
+ }
+ [$toStyle](startColor) {
+ return startColor ? startColor[$toStyle]() : "#FFFFFF";
+ }
+}
+class Speak extends StringObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "speak");
+ this.disable = getInteger({
+ data: attributes.disable,
+ defaultValue: 0,
+ validate: x => x === 1
+ });
+ this.id = attributes.id || "";
+ this.priority = getStringOption(attributes.priority, ["custom", "caption", "name", "toolTip"]);
+ this.rid = attributes.rid || "";
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ }
+}
+class Stipple extends XFAObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "stipple", true);
+ this.id = attributes.id || "";
+ this.rate = getInteger({
+ data: attributes.rate,
+ defaultValue: 50,
+ validate: x => x >= 0 && x <= 100
+ });
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ this.color = null;
+ this.extras = null;
+ }
+ [$toStyle](bgColor) {
+ const alpha = this.rate / 100;
+ return Util.makeHexColor(Math.round(bgColor.value.r * (1 - alpha) + this.value.r * alpha), Math.round(bgColor.value.g * (1 - alpha) + this.value.g * alpha), Math.round(bgColor.value.b * (1 - alpha) + this.value.b * alpha));
+ }
+}
+class Subform extends XFAObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "subform", true);
+ this.access = getStringOption(attributes.access, ["open", "nonInteractive", "protected", "readOnly"]);
+ this.allowMacro = getInteger({
+ data: attributes.allowMacro,
+ defaultValue: 0,
+ validate: x => x === 1
+ });
+ this.anchorType = getStringOption(attributes.anchorType, ["topLeft", "bottomCenter", "bottomLeft", "bottomRight", "middleCenter", "middleLeft", "middleRight", "topCenter", "topRight"]);
+ this.colSpan = getInteger({
+ data: attributes.colSpan,
+ defaultValue: 1,
+ validate: n => n >= 1 || n === -1
+ });
+ this.columnWidths = (attributes.columnWidths || "").trim().split(/\s+/).map(x => x === "-1" ? -1 : getMeasurement(x));
+ this.h = attributes.h ? getMeasurement(attributes.h) : "";
+ this.hAlign = getStringOption(attributes.hAlign, ["left", "center", "justify", "justifyAll", "radix", "right"]);
+ this.id = attributes.id || "";
+ this.layout = getStringOption(attributes.layout, ["position", "lr-tb", "rl-row", "rl-tb", "row", "table", "tb"]);
+ this.locale = attributes.locale || "";
+ this.maxH = getMeasurement(attributes.maxH, "0pt");
+ this.maxW = getMeasurement(attributes.maxW, "0pt");
+ this.mergeMode = getStringOption(attributes.mergeMode, ["consumeData", "matchTemplate"]);
+ this.minH = getMeasurement(attributes.minH, "0pt");
+ this.minW = getMeasurement(attributes.minW, "0pt");
+ this.name = attributes.name || "";
+ this.presence = getStringOption(attributes.presence, ["visible", "hidden", "inactive", "invisible"]);
+ this.relevant = getRelevant(attributes.relevant);
+ this.restoreState = getStringOption(attributes.restoreState, ["manual", "auto"]);
+ this.scope = getStringOption(attributes.scope, ["name", "none"]);
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ this.w = attributes.w ? getMeasurement(attributes.w) : "";
+ this.x = getMeasurement(attributes.x, "0pt");
+ this.y = getMeasurement(attributes.y, "0pt");
+ this.assist = null;
+ this.bind = null;
+ this.bookend = null;
+ this.border = null;
+ this.break = null;
+ this.calculate = null;
+ this.desc = null;
+ this.extras = null;
+ this.keep = null;
+ this.margin = null;
+ this.occur = null;
+ this.overflow = null;
+ this.pageSet = null;
+ this.para = null;
+ this.traversal = null;
+ this.validate = null;
+ this.variables = null;
+ this.area = new XFAObjectArray();
+ this.breakAfter = new XFAObjectArray();
+ this.breakBefore = new XFAObjectArray();
+ this.connect = new XFAObjectArray();
+ this.draw = new XFAObjectArray();
+ this.event = new XFAObjectArray();
+ this.exObject = new XFAObjectArray();
+ this.exclGroup = new XFAObjectArray();
+ this.field = new XFAObjectArray();
+ this.proto = new XFAObjectArray();
+ this.setProperty = new XFAObjectArray();
+ this.subform = new XFAObjectArray();
+ this.subformSet = new XFAObjectArray();
+ }
+ [$getSubformParent]() {
+ const parent = this[$getParent]();
+ if (parent instanceof SubformSet) {
+ return parent[$getSubformParent]();
+ }
+ return parent;
+ }
+ [$isBindable]() {
+ return true;
+ }
+ [$isThereMoreWidth]() {
+ return this.layout.endsWith("-tb") && this[$extra].attempt === 0 && this[$extra].numberInLine > 0 || this[$getParent]()[$isThereMoreWidth]();
+ }
+ *[$getContainedChildren]() {
+ yield* getContainedChildren(this);
+ }
+ [$flushHTML]() {
+ return flushHTML(this);
+ }
+ [$addHTML](html, bbox) {
+ addHTML(this, html, bbox);
+ }
+ [$getAvailableSpace]() {
+ return getAvailableSpace(this);
+ }
+ [$isSplittable]() {
+ const parent = this[$getSubformParent]();
+ if (!parent[$isSplittable]()) {
+ return false;
+ }
+ if (this[$extra]._isSplittable !== undefined) {
+ return this[$extra]._isSplittable;
+ }
+ if (this.layout === "position" || this.layout.includes("row")) {
+ this[$extra]._isSplittable = false;
+ return false;
+ }
+ if (this.keep && this.keep.intact !== "none") {
+ this[$extra]._isSplittable = false;
+ return false;
+ }
+ if (parent.layout?.endsWith("-tb") && parent[$extra].numberInLine !== 0) {
+ return false;
+ }
+ this[$extra]._isSplittable = true;
+ return true;
+ }
+ [$toHTML](availableSpace) {
+ setTabIndex(this);
+ if (this.break) {
+ if (this.break.after !== "auto" || this.break.afterTarget !== "") {
+ const node = new BreakAfter({
+ targetType: this.break.after,
+ target: this.break.afterTarget,
+ startNew: this.break.startNew.toString()
+ });
+ node[$globalData] = this[$globalData];
+ this[$appendChild](node);
+ this.breakAfter.push(node);
+ }
+ if (this.break.before !== "auto" || this.break.beforeTarget !== "") {
+ const node = new BreakBefore({
+ targetType: this.break.before,
+ target: this.break.beforeTarget,
+ startNew: this.break.startNew.toString()
+ });
+ node[$globalData] = this[$globalData];
+ this[$appendChild](node);
+ this.breakBefore.push(node);
+ }
+ if (this.break.overflowTarget !== "") {
+ const node = new Overflow({
+ target: this.break.overflowTarget,
+ leader: this.break.overflowLeader,
+ trailer: this.break.overflowTrailer
+ });
+ node[$globalData] = this[$globalData];
+ this[$appendChild](node);
+ this.overflow.push(node);
+ }
+ this[$removeChild](this.break);
+ this.break = null;
+ }
+ if (this.presence === "hidden" || this.presence === "inactive") {
+ return HTMLResult.EMPTY;
+ }
+ if (this.breakBefore.children.length > 1 || this.breakAfter.children.length > 1) {
+ warn("XFA - Several breakBefore or breakAfter in subforms: please file a bug.");
+ }
+ if (this.breakBefore.children.length >= 1) {
+ const breakBefore = this.breakBefore.children[0];
+ if (handleBreak(breakBefore)) {
+ return HTMLResult.breakNode(breakBefore);
+ }
+ }
+ if (this[$extra]?.afterBreakAfter) {
+ return HTMLResult.EMPTY;
+ }
+ fixDimensions(this);
+ const children = [];
+ const attributes = {
+ id: this[$uid],
+ class: []
+ };
+ setAccess(this, attributes.class);
+ if (!this[$extra]) {
+ this[$extra] = Object.create(null);
+ }
+ Object.assign(this[$extra], {
+ children,
+ line: null,
+ attributes,
+ attempt: 0,
+ numberInLine: 0,
+ availableSpace: {
+ width: Math.min(this.w || Infinity, availableSpace.width),
+ height: Math.min(this.h || Infinity, availableSpace.height)
+ },
+ width: 0,
+ height: 0,
+ prevHeight: 0,
+ currentWidth: 0
+ });
+ const root = this[$getTemplateRoot]();
+ const savedNoLayoutFailure = root[$extra].noLayoutFailure;
+ const isSplittable = this[$isSplittable]();
+ if (!isSplittable) {
+ setFirstUnsplittable(this);
+ }
+ if (!checkDimensions(this, availableSpace)) {
+ return HTMLResult.FAILURE;
+ }
+ const filter = new Set(["area", "draw", "exclGroup", "field", "subform", "subformSet"]);
+ if (this.layout.includes("row")) {
+ const columnWidths = this[$getSubformParent]().columnWidths;
+ if (Array.isArray(columnWidths) && columnWidths.length > 0) {
+ this[$extra].columnWidths = columnWidths;
+ this[$extra].currentColumn = 0;
+ }
+ }
+ const style = toStyle(this, "anchorType", "dimensions", "position", "presence", "border", "margin", "hAlign");
+ const classNames = ["xfaSubform"];
+ const cl = layoutClass(this);
+ if (cl) {
+ classNames.push(cl);
+ }
+ attributes.style = style;
+ attributes.class = classNames;
+ if (this.name) {
+ attributes.xfaName = this.name;
+ }
+ if (this.overflow) {
+ const overflowExtra = this.overflow[$getExtra]();
+ if (overflowExtra.addLeader) {
+ overflowExtra.addLeader = false;
+ handleOverflow(this, overflowExtra.leader, availableSpace);
+ }
+ }
+ this[$pushPara]();
+ const isLrTb = this.layout === "lr-tb" || this.layout === "rl-tb";
+ const maxRun = isLrTb ? MAX_ATTEMPTS_FOR_LRTB_LAYOUT : 1;
+ for (; this[$extra].attempt < maxRun; this[$extra].attempt++) {
+ if (isLrTb && this[$extra].attempt === MAX_ATTEMPTS_FOR_LRTB_LAYOUT - 1) {
+ this[$extra].numberInLine = 0;
+ }
+ const result = this[$childrenToHTML]({
+ filter,
+ include: true
+ });
+ if (result.success) {
+ break;
+ }
+ if (result.isBreak()) {
+ this[$popPara]();
+ return result;
+ }
+ if (isLrTb && this[$extra].attempt === 0 && this[$extra].numberInLine === 0 && !root[$extra].noLayoutFailure) {
+ this[$extra].attempt = maxRun;
+ break;
+ }
+ }
+ this[$popPara]();
+ if (!isSplittable) {
+ unsetFirstUnsplittable(this);
+ }
+ root[$extra].noLayoutFailure = savedNoLayoutFailure;
+ if (this[$extra].attempt === maxRun) {
+ if (this.overflow) {
+ this[$getTemplateRoot]()[$extra].overflowNode = this.overflow;
+ }
+ if (!isSplittable) {
+ delete this[$extra];
+ }
+ return HTMLResult.FAILURE;
+ }
+ if (this.overflow) {
+ const overflowExtra = this.overflow[$getExtra]();
+ if (overflowExtra.addTrailer) {
+ overflowExtra.addTrailer = false;
+ handleOverflow(this, overflowExtra.trailer, availableSpace);
+ }
+ }
+ let marginH = 0;
+ let marginV = 0;
+ if (this.margin) {
+ marginH = this.margin.leftInset + this.margin.rightInset;
+ marginV = this.margin.topInset + this.margin.bottomInset;
+ }
+ const width = Math.max(this[$extra].width + marginH, this.w || 0);
+ const height = Math.max(this[$extra].height + marginV, this.h || 0);
+ const bbox = [this.x, this.y, width, height];
+ if (this.w === "") {
+ style.width = measureToString(width);
+ }
+ if (this.h === "") {
+ style.height = measureToString(height);
+ }
+ if ((style.width === "0px" || style.height === "0px") && children.length === 0) {
+ return HTMLResult.EMPTY;
+ }
+ const html = {
+ name: "div",
+ attributes,
+ children
+ };
+ applyAssist(this, attributes);
+ const result = HTMLResult.success(createWrapper(this, html), bbox);
+ if (this.breakAfter.children.length >= 1) {
+ const breakAfter = this.breakAfter.children[0];
+ if (handleBreak(breakAfter)) {
+ this[$extra].afterBreakAfter = result;
+ return HTMLResult.breakNode(breakAfter);
+ }
+ }
+ delete this[$extra];
+ return result;
+ }
+}
+class SubformSet extends XFAObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "subformSet", true);
+ this.id = attributes.id || "";
+ this.name = attributes.name || "";
+ this.relation = getStringOption(attributes.relation, ["ordered", "choice", "unordered"]);
+ this.relevant = getRelevant(attributes.relevant);
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ this.bookend = null;
+ this.break = null;
+ this.desc = null;
+ this.extras = null;
+ this.occur = null;
+ this.overflow = null;
+ this.breakAfter = new XFAObjectArray();
+ this.breakBefore = new XFAObjectArray();
+ this.subform = new XFAObjectArray();
+ this.subformSet = new XFAObjectArray();
+ }
+ *[$getContainedChildren]() {
+ yield* getContainedChildren(this);
+ }
+ [$getSubformParent]() {
+ let parent = this[$getParent]();
+ while (!(parent instanceof Subform)) {
+ parent = parent[$getParent]();
+ }
+ return parent;
+ }
+ [$isBindable]() {
+ return true;
+ }
+}
+class SubjectDN extends ContentObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "subjectDN");
+ this.delimiter = attributes.delimiter || ",";
+ this.id = attributes.id || "";
+ this.name = attributes.name || "";
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ }
+ [$finalize]() {
+ this[$content] = new Map(this[$content].split(this.delimiter).map(kv => {
+ kv = kv.split("=", 2);
+ kv[0] = kv[0].trim();
+ return kv;
+ }));
+ }
+}
+class SubjectDNs extends XFAObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "subjectDNs", true);
+ this.id = attributes.id || "";
+ this.type = getStringOption(attributes.type, ["optional", "required"]);
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ this.subjectDN = new XFAObjectArray();
+ }
+}
+class Submit extends XFAObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "submit", true);
+ this.embedPDF = getInteger({
+ data: attributes.embedPDF,
+ defaultValue: 0,
+ validate: x => x === 1
+ });
+ this.format = getStringOption(attributes.format, ["xdp", "formdata", "pdf", "urlencoded", "xfd", "xml"]);
+ this.id = attributes.id || "";
+ this.target = attributes.target || "";
+ this.textEncoding = getKeyword({
+ data: attributes.textEncoding ? attributes.textEncoding.toLowerCase() : "",
+ defaultValue: "",
+ validate: k => ["utf-8", "big-five", "fontspecific", "gbk", "gb-18030", "gb-2312", "ksc-5601", "none", "shift-jis", "ucs-2", "utf-16"].includes(k) || k.match(/iso-8859-\d{2}/)
+ });
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ this.xdpContent = attributes.xdpContent || "";
+ this.encrypt = null;
+ this.encryptData = new XFAObjectArray();
+ this.signData = new XFAObjectArray();
+ }
+}
+class Template extends XFAObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "template", true);
+ this.baseProfile = getStringOption(attributes.baseProfile, ["full", "interactiveForms"]);
+ this.extras = null;
+ this.subform = new XFAObjectArray();
+ }
+ [$finalize]() {
+ if (this.subform.children.length === 0) {
+ warn("XFA - No subforms in template node.");
+ }
+ if (this.subform.children.length >= 2) {
+ warn("XFA - Several subforms in template node: please file a bug.");
+ }
+ this[$tabIndex] = DEFAULT_TAB_INDEX;
+ }
+ [$isSplittable]() {
+ return true;
+ }
+ [$searchNode](expr, container) {
+ if (expr.startsWith("#")) {
+ return [this[$ids].get(expr.slice(1))];
+ }
+ return searchNode(this, container, expr, true, true);
+ }
+ *[$toPages]() {
+ if (!this.subform.children.length) {
+ return HTMLResult.success({
+ name: "div",
+ children: []
+ });
+ }
+ this[$extra] = {
+ overflowNode: null,
+ firstUnsplittable: null,
+ currentContentArea: null,
+ currentPageArea: null,
+ noLayoutFailure: false,
+ pageNumber: 1,
+ pagePosition: "first",
+ oddOrEven: "odd",
+ blankOrNotBlank: "nonBlank",
+ paraStack: []
+ };
+ const root = this.subform.children[0];
+ root.pageSet[$cleanPage]();
+ const pageAreas = root.pageSet.pageArea.children;
+ const mainHtml = {
+ name: "div",
+ children: []
+ };
+ let pageArea = null;
+ let breakBefore = null;
+ let breakBeforeTarget = null;
+ if (root.breakBefore.children.length >= 1) {
+ breakBefore = root.breakBefore.children[0];
+ breakBeforeTarget = breakBefore.target;
+ } else if (root.subform.children.length >= 1 && root.subform.children[0].breakBefore.children.length >= 1) {
+ breakBefore = root.subform.children[0].breakBefore.children[0];
+ breakBeforeTarget = breakBefore.target;
+ } else if (root.break?.beforeTarget) {
+ breakBefore = root.break;
+ breakBeforeTarget = breakBefore.beforeTarget;
+ } else if (root.subform.children.length >= 1 && root.subform.children[0].break?.beforeTarget) {
+ breakBefore = root.subform.children[0].break;
+ breakBeforeTarget = breakBefore.beforeTarget;
+ }
+ if (breakBefore) {
+ const target = this[$searchNode](breakBeforeTarget, breakBefore[$getParent]());
+ if (target instanceof PageArea) {
+ pageArea = target;
+ breakBefore[$extra] = {};
+ }
+ }
+ if (!pageArea) {
+ pageArea = pageAreas[0];
+ }
+ pageArea[$extra] = {
+ numberOfUse: 1
+ };
+ const pageAreaParent = pageArea[$getParent]();
+ pageAreaParent[$extra] = {
+ numberOfUse: 1,
+ pageIndex: pageAreaParent.pageArea.children.indexOf(pageArea),
+ pageSetIndex: 0
+ };
+ let targetPageArea;
+ let leader = null;
+ let trailer = null;
+ let hasSomething = true;
+ let hasSomethingCounter = 0;
+ let startIndex = 0;
+ while (true) {
+ if (!hasSomething) {
+ mainHtml.children.pop();
+ if (++hasSomethingCounter === MAX_EMPTY_PAGES) {
+ warn("XFA - Something goes wrong: please file a bug.");
+ return mainHtml;
+ }
+ } else {
+ hasSomethingCounter = 0;
+ }
+ targetPageArea = null;
+ this[$extra].currentPageArea = pageArea;
+ const page = pageArea[$toHTML]().html;
+ mainHtml.children.push(page);
+ if (leader) {
+ this[$extra].noLayoutFailure = true;
+ page.children.push(leader[$toHTML](pageArea[$extra].space).html);
+ leader = null;
+ }
+ if (trailer) {
+ this[$extra].noLayoutFailure = true;
+ page.children.push(trailer[$toHTML](pageArea[$extra].space).html);
+ trailer = null;
+ }
+ const contentAreas = pageArea.contentArea.children;
+ const htmlContentAreas = page.children.filter(node => node.attributes.class.includes("xfaContentarea"));
+ hasSomething = false;
+ this[$extra].firstUnsplittable = null;
+ this[$extra].noLayoutFailure = false;
+ const flush = index => {
+ const html = root[$flushHTML]();
+ if (html) {
+ hasSomething ||= html.children?.length > 0;
+ htmlContentAreas[index].children.push(html);
+ }
+ };
+ for (let i = startIndex, ii = contentAreas.length; i < ii; i++) {
+ const contentArea = this[$extra].currentContentArea = contentAreas[i];
+ const space = {
+ width: contentArea.w,
+ height: contentArea.h
+ };
+ startIndex = 0;
+ if (leader) {
+ htmlContentAreas[i].children.push(leader[$toHTML](space).html);
+ leader = null;
+ }
+ if (trailer) {
+ htmlContentAreas[i].children.push(trailer[$toHTML](space).html);
+ trailer = null;
+ }
+ const html = root[$toHTML](space);
+ if (html.success) {
+ if (html.html) {
+ hasSomething ||= html.html.children?.length > 0;
+ htmlContentAreas[i].children.push(html.html);
+ } else if (!hasSomething && mainHtml.children.length > 1) {
+ mainHtml.children.pop();
+ }
+ return mainHtml;
+ }
+ if (html.isBreak()) {
+ const node = html.breakNode;
+ flush(i);
+ if (node.targetType === "auto") {
+ continue;
+ }
+ if (node.leader) {
+ leader = this[$searchNode](node.leader, node[$getParent]());
+ leader = leader ? leader[0] : null;
+ }
+ if (node.trailer) {
+ trailer = this[$searchNode](node.trailer, node[$getParent]());
+ trailer = trailer ? trailer[0] : null;
+ }
+ if (node.targetType === "pageArea") {
+ targetPageArea = node[$extra].target;
+ i = Infinity;
+ } else if (!node[$extra].target) {
+ i = node[$extra].index;
+ } else {
+ targetPageArea = node[$extra].target;
+ startIndex = node[$extra].index + 1;
+ i = Infinity;
+ }
+ continue;
+ }
+ if (this[$extra].overflowNode) {
+ const node = this[$extra].overflowNode;
+ this[$extra].overflowNode = null;
+ const overflowExtra = node[$getExtra]();
+ const target = overflowExtra.target;
+ overflowExtra.addLeader = overflowExtra.leader !== null;
+ overflowExtra.addTrailer = overflowExtra.trailer !== null;
+ flush(i);
+ const currentIndex = i;
+ i = Infinity;
+ if (target instanceof PageArea) {
+ targetPageArea = target;
+ } else if (target instanceof ContentArea) {
+ const index = contentAreas.indexOf(target);
+ if (index !== -1) {
+ if (index > currentIndex) {
+ i = index - 1;
+ } else {
+ startIndex = index;
+ }
+ } else {
+ targetPageArea = target[$getParent]();
+ startIndex = targetPageArea.contentArea.children.indexOf(target);
+ }
+ }
+ continue;
+ }
+ flush(i);
+ }
+ this[$extra].pageNumber += 1;
+ if (targetPageArea) {
+ if (targetPageArea[$isUsable]()) {
+ targetPageArea[$extra].numberOfUse += 1;
+ } else {
+ targetPageArea = null;
+ }
+ }
+ pageArea = targetPageArea || pageArea[$getNextPage]();
+ yield null;
+ }
+ }
+}
+class Text extends ContentObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "text");
+ this.id = attributes.id || "";
+ this.maxChars = getInteger({
+ data: attributes.maxChars,
+ defaultValue: 0,
+ validate: x => x >= 0
+ });
+ this.name = attributes.name || "";
+ this.rid = attributes.rid || "";
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ }
+ [$acceptWhitespace]() {
+ return true;
+ }
+ [$onChild](child) {
+ if (child[$namespaceId] === NamespaceIds.xhtml.id) {
+ this[$content] = child;
+ return true;
+ }
+ warn(`XFA - Invalid content in Text: ${child[$nodeName]}.`);
+ return false;
+ }
+ [$onText](str) {
+ if (this[$content] instanceof XFAObject) {
+ return;
+ }
+ super[$onText](str);
+ }
+ [$finalize]() {
+ if (typeof this[$content] === "string") {
+ this[$content] = this[$content].replaceAll("\r\n", "\n");
+ }
+ }
+ [$getExtra]() {
+ if (typeof this[$content] === "string") {
+ return this[$content].split(/[\u2029\u2028\n]/).reduce((acc, line) => {
+ if (line) {
+ acc.push(line);
+ }
+ return acc;
+ }, []).join("\n");
+ }
+ return this[$content][$text]();
+ }
+ [$toHTML](availableSpace) {
+ if (typeof this[$content] === "string") {
+ const html = valueToHtml(this[$content]).html;
+ if (this[$content].includes("\u2029")) {
+ html.name = "div";
+ html.children = [];
+ this[$content].split("\u2029").map(para => para.split(/[\u2028\n]/).reduce((acc, line) => {
+ acc.push({
+ name: "span",
+ value: line
+ }, {
+ name: "br"
+ });
+ return acc;
+ }, [])).forEach(lines => {
+ html.children.push({
+ name: "p",
+ children: lines
+ });
+ });
+ } else if (/[\u2028\n]/.test(this[$content])) {
+ html.name = "div";
+ html.children = [];
+ this[$content].split(/[\u2028\n]/).forEach(line => {
+ html.children.push({
+ name: "span",
+ value: line
+ }, {
+ name: "br"
+ });
+ });
+ }
+ return HTMLResult.success(html);
+ }
+ return this[$content][$toHTML](availableSpace);
+ }
+}
+class TextEdit extends XFAObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "textEdit", true);
+ this.allowRichText = getInteger({
+ data: attributes.allowRichText,
+ defaultValue: 0,
+ validate: x => x === 1
+ });
+ this.hScrollPolicy = getStringOption(attributes.hScrollPolicy, ["auto", "off", "on"]);
+ this.id = attributes.id || "";
+ this.multiLine = getInteger({
+ data: attributes.multiLine,
+ defaultValue: "",
+ validate: x => x === 0 || x === 1
+ });
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ this.vScrollPolicy = getStringOption(attributes.vScrollPolicy, ["auto", "off", "on"]);
+ this.border = null;
+ this.comb = null;
+ this.extras = null;
+ this.margin = null;
+ }
+ [$toHTML](availableSpace) {
+ const style = toStyle(this, "border", "font", "margin");
+ let html;
+ const field = this[$getParent]()[$getParent]();
+ if (this.multiLine === "") {
+ this.multiLine = field instanceof Draw ? 1 : 0;
+ }
+ if (this.multiLine === 1) {
+ html = {
+ name: "textarea",
+ attributes: {
+ dataId: field[$data]?.[$uid] || field[$uid],
+ fieldId: field[$uid],
+ class: ["xfaTextfield"],
+ style,
+ "aria-label": ariaLabel(field),
+ "aria-required": false
+ }
+ };
+ } else {
+ html = {
+ name: "input",
+ attributes: {
+ type: "text",
+ dataId: field[$data]?.[$uid] || field[$uid],
+ fieldId: field[$uid],
+ class: ["xfaTextfield"],
+ style,
+ "aria-label": ariaLabel(field),
+ "aria-required": false
+ }
+ };
+ }
+ if (isRequired(field)) {
+ html.attributes["aria-required"] = true;
+ html.attributes.required = true;
+ }
+ return HTMLResult.success({
+ name: "label",
+ attributes: {
+ class: ["xfaLabel"]
+ },
+ children: [html]
+ });
+ }
+}
+class Time extends StringObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "time");
+ this.id = attributes.id || "";
+ this.name = attributes.name || "";
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ }
+ [$finalize]() {
+ const date = this[$content].trim();
+ this[$content] = date ? new Date(date) : null;
+ }
+ [$toHTML](availableSpace) {
+ return valueToHtml(this[$content] ? this[$content].toString() : "");
+ }
+}
+class TimeStamp extends XFAObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "timeStamp");
+ this.id = attributes.id || "";
+ this.server = attributes.server || "";
+ this.type = getStringOption(attributes.type, ["optional", "required"]);
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ }
+}
+class ToolTip extends StringObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "toolTip");
+ this.id = attributes.id || "";
+ this.rid = attributes.rid || "";
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ }
+}
+class Traversal extends XFAObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "traversal", true);
+ this.id = attributes.id || "";
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ this.extras = null;
+ this.traverse = new XFAObjectArray();
+ }
+}
+class Traverse extends XFAObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "traverse", true);
+ this.id = attributes.id || "";
+ this.operation = getStringOption(attributes.operation, ["next", "back", "down", "first", "left", "right", "up"]);
+ this.ref = attributes.ref || "";
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ this.extras = null;
+ this.script = null;
+ }
+ get name() {
+ return this.operation;
+ }
+ [$isTransparent]() {
+ return false;
+ }
+}
+class Ui extends XFAObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "ui", true);
+ this.id = attributes.id || "";
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ this.extras = null;
+ this.picture = null;
+ this.barcode = null;
+ this.button = null;
+ this.checkButton = null;
+ this.choiceList = null;
+ this.dateTimeEdit = null;
+ this.defaultUi = null;
+ this.imageEdit = null;
+ this.numericEdit = null;
+ this.passwordEdit = null;
+ this.signature = null;
+ this.textEdit = null;
+ }
+ [$getExtra]() {
+ if (this[$extra] === undefined) {
+ for (const name of Object.getOwnPropertyNames(this)) {
+ if (name === "extras" || name === "picture") {
+ continue;
+ }
+ const obj = this[name];
+ if (!(obj instanceof XFAObject)) {
+ continue;
+ }
+ this[$extra] = obj;
+ return obj;
+ }
+ this[$extra] = null;
+ }
+ return this[$extra];
+ }
+ [$toHTML](availableSpace) {
+ const obj = this[$getExtra]();
+ if (obj) {
+ return obj[$toHTML](availableSpace);
+ }
+ return HTMLResult.EMPTY;
+ }
+}
+class Validate extends XFAObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "validate", true);
+ this.formatTest = getStringOption(attributes.formatTest, ["warning", "disabled", "error"]);
+ this.id = attributes.id || "";
+ this.nullTest = getStringOption(attributes.nullTest, ["disabled", "error", "warning"]);
+ this.scriptTest = getStringOption(attributes.scriptTest, ["error", "disabled", "warning"]);
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ this.extras = null;
+ this.message = null;
+ this.picture = null;
+ this.script = null;
+ }
+}
+class Value extends XFAObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "value", true);
+ this.id = attributes.id || "";
+ this.override = getInteger({
+ data: attributes.override,
+ defaultValue: 0,
+ validate: x => x === 1
+ });
+ this.relevant = getRelevant(attributes.relevant);
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ this.arc = null;
+ this.boolean = null;
+ this.date = null;
+ this.dateTime = null;
+ this.decimal = null;
+ this.exData = null;
+ this.float = null;
+ this.image = null;
+ this.integer = null;
+ this.line = null;
+ this.rectangle = null;
+ this.text = null;
+ this.time = null;
+ }
+ [$setValue](value) {
+ const parent = this[$getParent]();
+ if (parent instanceof Field) {
+ if (parent.ui?.imageEdit) {
+ if (!this.image) {
+ this.image = new Image({});
+ this[$appendChild](this.image);
+ }
+ this.image[$content] = value[$content];
+ return;
+ }
+ }
+ const valueName = value[$nodeName];
+ if (this[valueName] !== null) {
+ this[valueName][$content] = value[$content];
+ return;
+ }
+ for (const name of Object.getOwnPropertyNames(this)) {
+ const obj = this[name];
+ if (obj instanceof XFAObject) {
+ this[name] = null;
+ this[$removeChild](obj);
+ }
+ }
+ this[value[$nodeName]] = value;
+ this[$appendChild](value);
+ }
+ [$text]() {
+ if (this.exData) {
+ if (typeof this.exData[$content] === "string") {
+ return this.exData[$content].trim();
+ }
+ return this.exData[$content][$text]().trim();
+ }
+ for (const name of Object.getOwnPropertyNames(this)) {
+ if (name === "image") {
+ continue;
+ }
+ const obj = this[name];
+ if (obj instanceof XFAObject) {
+ return (obj[$content] || "").toString().trim();
+ }
+ }
+ return null;
+ }
+ [$toHTML](availableSpace) {
+ for (const name of Object.getOwnPropertyNames(this)) {
+ const obj = this[name];
+ if (!(obj instanceof XFAObject)) {
+ continue;
+ }
+ return obj[$toHTML](availableSpace);
+ }
+ return HTMLResult.EMPTY;
+ }
+}
+class Variables extends XFAObject {
+ constructor(attributes) {
+ super(TEMPLATE_NS_ID, "variables", true);
+ this.id = attributes.id || "";
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ this.boolean = new XFAObjectArray();
+ this.date = new XFAObjectArray();
+ this.dateTime = new XFAObjectArray();
+ this.decimal = new XFAObjectArray();
+ this.exData = new XFAObjectArray();
+ this.float = new XFAObjectArray();
+ this.image = new XFAObjectArray();
+ this.integer = new XFAObjectArray();
+ this.manifest = new XFAObjectArray();
+ this.script = new XFAObjectArray();
+ this.text = new XFAObjectArray();
+ this.time = new XFAObjectArray();
+ }
+ [$isTransparent]() {
+ return true;
+ }
+}
+class TemplateNamespace {
+ static [$buildXFAObject](name, attributes) {
+ if (TemplateNamespace.hasOwnProperty(name)) {
+ const node = TemplateNamespace[name](attributes);
+ node[$setSetAttributes](attributes);
+ return node;
+ }
+ return undefined;
+ }
+ static appearanceFilter(attrs) {
+ return new AppearanceFilter(attrs);
+ }
+ static arc(attrs) {
+ return new Arc(attrs);
+ }
+ static area(attrs) {
+ return new Area(attrs);
+ }
+ static assist(attrs) {
+ return new Assist(attrs);
+ }
+ static barcode(attrs) {
+ return new Barcode(attrs);
+ }
+ static bind(attrs) {
+ return new Bind(attrs);
+ }
+ static bindItems(attrs) {
+ return new BindItems(attrs);
+ }
+ static bookend(attrs) {
+ return new Bookend(attrs);
+ }
+ static boolean(attrs) {
+ return new BooleanElement(attrs);
+ }
+ static border(attrs) {
+ return new Border(attrs);
+ }
+ static break(attrs) {
+ return new Break(attrs);
+ }
+ static breakAfter(attrs) {
+ return new BreakAfter(attrs);
+ }
+ static breakBefore(attrs) {
+ return new BreakBefore(attrs);
+ }
+ static button(attrs) {
+ return new Button(attrs);
+ }
+ static calculate(attrs) {
+ return new Calculate(attrs);
+ }
+ static caption(attrs) {
+ return new Caption(attrs);
+ }
+ static certificate(attrs) {
+ return new Certificate(attrs);
+ }
+ static certificates(attrs) {
+ return new Certificates(attrs);
+ }
+ static checkButton(attrs) {
+ return new CheckButton(attrs);
+ }
+ static choiceList(attrs) {
+ return new ChoiceList(attrs);
+ }
+ static color(attrs) {
+ return new Color(attrs);
+ }
+ static comb(attrs) {
+ return new Comb(attrs);
+ }
+ static connect(attrs) {
+ return new Connect(attrs);
+ }
+ static contentArea(attrs) {
+ return new ContentArea(attrs);
+ }
+ static corner(attrs) {
+ return new Corner(attrs);
+ }
+ static date(attrs) {
+ return new DateElement(attrs);
+ }
+ static dateTime(attrs) {
+ return new DateTime(attrs);
+ }
+ static dateTimeEdit(attrs) {
+ return new DateTimeEdit(attrs);
+ }
+ static decimal(attrs) {
+ return new Decimal(attrs);
+ }
+ static defaultUi(attrs) {
+ return new DefaultUi(attrs);
+ }
+ static desc(attrs) {
+ return new Desc(attrs);
+ }
+ static digestMethod(attrs) {
+ return new DigestMethod(attrs);
+ }
+ static digestMethods(attrs) {
+ return new DigestMethods(attrs);
+ }
+ static draw(attrs) {
+ return new Draw(attrs);
+ }
+ static edge(attrs) {
+ return new Edge(attrs);
+ }
+ static encoding(attrs) {
+ return new Encoding(attrs);
+ }
+ static encodings(attrs) {
+ return new Encodings(attrs);
+ }
+ static encrypt(attrs) {
+ return new Encrypt(attrs);
+ }
+ static encryptData(attrs) {
+ return new EncryptData(attrs);
+ }
+ static encryption(attrs) {
+ return new Encryption(attrs);
+ }
+ static encryptionMethod(attrs) {
+ return new EncryptionMethod(attrs);
+ }
+ static encryptionMethods(attrs) {
+ return new EncryptionMethods(attrs);
+ }
+ static event(attrs) {
+ return new Event(attrs);
+ }
+ static exData(attrs) {
+ return new ExData(attrs);
+ }
+ static exObject(attrs) {
+ return new ExObject(attrs);
+ }
+ static exclGroup(attrs) {
+ return new ExclGroup(attrs);
+ }
+ static execute(attrs) {
+ return new Execute(attrs);
+ }
+ static extras(attrs) {
+ return new Extras(attrs);
+ }
+ static field(attrs) {
+ return new Field(attrs);
+ }
+ static fill(attrs) {
+ return new Fill(attrs);
+ }
+ static filter(attrs) {
+ return new Filter(attrs);
+ }
+ static float(attrs) {
+ return new Float(attrs);
+ }
+ static font(attrs) {
+ return new template_Font(attrs);
+ }
+ static format(attrs) {
+ return new Format(attrs);
+ }
+ static handler(attrs) {
+ return new Handler(attrs);
+ }
+ static hyphenation(attrs) {
+ return new Hyphenation(attrs);
+ }
+ static image(attrs) {
+ return new Image(attrs);
+ }
+ static imageEdit(attrs) {
+ return new ImageEdit(attrs);
+ }
+ static integer(attrs) {
+ return new Integer(attrs);
+ }
+ static issuers(attrs) {
+ return new Issuers(attrs);
+ }
+ static items(attrs) {
+ return new Items(attrs);
+ }
+ static keep(attrs) {
+ return new Keep(attrs);
+ }
+ static keyUsage(attrs) {
+ return new KeyUsage(attrs);
+ }
+ static line(attrs) {
+ return new Line(attrs);
+ }
+ static linear(attrs) {
+ return new Linear(attrs);
+ }
+ static lockDocument(attrs) {
+ return new LockDocument(attrs);
+ }
+ static manifest(attrs) {
+ return new Manifest(attrs);
+ }
+ static margin(attrs) {
+ return new Margin(attrs);
+ }
+ static mdp(attrs) {
+ return new Mdp(attrs);
+ }
+ static medium(attrs) {
+ return new Medium(attrs);
+ }
+ static message(attrs) {
+ return new Message(attrs);
+ }
+ static numericEdit(attrs) {
+ return new NumericEdit(attrs);
+ }
+ static occur(attrs) {
+ return new Occur(attrs);
+ }
+ static oid(attrs) {
+ return new Oid(attrs);
+ }
+ static oids(attrs) {
+ return new Oids(attrs);
+ }
+ static overflow(attrs) {
+ return new Overflow(attrs);
+ }
+ static pageArea(attrs) {
+ return new PageArea(attrs);
+ }
+ static pageSet(attrs) {
+ return new PageSet(attrs);
+ }
+ static para(attrs) {
+ return new Para(attrs);
+ }
+ static passwordEdit(attrs) {
+ return new PasswordEdit(attrs);
+ }
+ static pattern(attrs) {
+ return new template_Pattern(attrs);
+ }
+ static picture(attrs) {
+ return new Picture(attrs);
+ }
+ static proto(attrs) {
+ return new Proto(attrs);
+ }
+ static radial(attrs) {
+ return new Radial(attrs);
+ }
+ static reason(attrs) {
+ return new Reason(attrs);
+ }
+ static reasons(attrs) {
+ return new Reasons(attrs);
+ }
+ static rectangle(attrs) {
+ return new Rectangle(attrs);
+ }
+ static ref(attrs) {
+ return new RefElement(attrs);
+ }
+ static script(attrs) {
+ return new Script(attrs);
+ }
+ static setProperty(attrs) {
+ return new SetProperty(attrs);
+ }
+ static signData(attrs) {
+ return new SignData(attrs);
+ }
+ static signature(attrs) {
+ return new Signature(attrs);
+ }
+ static signing(attrs) {
+ return new Signing(attrs);
+ }
+ static solid(attrs) {
+ return new Solid(attrs);
+ }
+ static speak(attrs) {
+ return new Speak(attrs);
+ }
+ static stipple(attrs) {
+ return new Stipple(attrs);
+ }
+ static subform(attrs) {
+ return new Subform(attrs);
+ }
+ static subformSet(attrs) {
+ return new SubformSet(attrs);
+ }
+ static subjectDN(attrs) {
+ return new SubjectDN(attrs);
+ }
+ static subjectDNs(attrs) {
+ return new SubjectDNs(attrs);
+ }
+ static submit(attrs) {
+ return new Submit(attrs);
+ }
+ static template(attrs) {
+ return new Template(attrs);
+ }
+ static text(attrs) {
+ return new Text(attrs);
+ }
+ static textEdit(attrs) {
+ return new TextEdit(attrs);
+ }
+ static time(attrs) {
+ return new Time(attrs);
+ }
+ static timeStamp(attrs) {
+ return new TimeStamp(attrs);
+ }
+ static toolTip(attrs) {
+ return new ToolTip(attrs);
+ }
+ static traversal(attrs) {
+ return new Traversal(attrs);
+ }
+ static traverse(attrs) {
+ return new Traverse(attrs);
+ }
+ static ui(attrs) {
+ return new Ui(attrs);
+ }
+ static validate(attrs) {
+ return new Validate(attrs);
+ }
+ static value(attrs) {
+ return new Value(attrs);
+ }
+ static variables(attrs) {
+ return new Variables(attrs);
+ }
+}
+
+;// CONCATENATED MODULE: ./src/core/xfa/bind.js
+
+
+
+
+
+
+const bind_NS_DATASETS = NamespaceIds.datasets.id;
+function createText(content) {
+ const node = new Text({});
+ node[$content] = content;
+ return node;
+}
+class Binder {
+ constructor(root) {
+ this.root = root;
+ this.datasets = root.datasets;
+ this.data = root.datasets?.data || new XmlObject(NamespaceIds.datasets.id, "data");
+ this.emptyMerge = this.data[$getChildren]().length === 0;
+ this.root.form = this.form = root.template[$clone]();
+ }
+ _isConsumeData() {
+ return !this.emptyMerge && this._mergeMode;
+ }
+ _isMatchTemplate() {
+ return !this._isConsumeData();
+ }
+ bind() {
+ this._bindElement(this.form, this.data);
+ return this.form;
+ }
+ getData() {
+ return this.data;
+ }
+ _bindValue(formNode, data, picture) {
+ formNode[$data] = data;
+ if (formNode[$hasSettableValue]()) {
+ if (data[$isDataValue]()) {
+ const value = data[$getDataValue]();
+ formNode[$setValue](createText(value));
+ } else if (formNode instanceof Field && formNode.ui?.choiceList?.open === "multiSelect") {
+ const value = data[$getChildren]().map(child => child[$content].trim()).join("\n");
+ formNode[$setValue](createText(value));
+ } else if (this._isConsumeData()) {
+ warn(`XFA - Nodes haven't the same type.`);
+ }
+ } else if (!data[$isDataValue]() || this._isMatchTemplate()) {
+ this._bindElement(formNode, data);
+ } else {
+ warn(`XFA - Nodes haven't the same type.`);
+ }
+ }
+ _findDataByNameToConsume(name, isValue, dataNode, global) {
+ if (!name) {
+ return null;
+ }
+ let generator, match;
+ for (let i = 0; i < 3; i++) {
+ generator = dataNode[$getRealChildrenByNameIt](name, false, true);
+ while (true) {
+ match = generator.next().value;
+ if (!match) {
+ break;
+ }
+ if (isValue === match[$isDataValue]()) {
+ return match;
+ }
+ }
+ if (dataNode[$namespaceId] === NamespaceIds.datasets.id && dataNode[$nodeName] === "data") {
+ break;
+ }
+ dataNode = dataNode[$getParent]();
+ }
+ if (!global) {
+ return null;
+ }
+ generator = this.data[$getRealChildrenByNameIt](name, true, false);
+ match = generator.next().value;
+ if (match) {
+ return match;
+ }
+ generator = this.data[$getAttributeIt](name, true);
+ match = generator.next().value;
+ if (match?.[$isDataValue]()) {
+ return match;
+ }
+ return null;
+ }
+ _setProperties(formNode, dataNode) {
+ if (!formNode.hasOwnProperty("setProperty")) {
+ return;
+ }
+ for (const {
+ ref,
+ target,
+ connection
+ } of formNode.setProperty.children) {
+ if (connection) {
+ continue;
+ }
+ if (!ref) {
+ continue;
+ }
+ const nodes = searchNode(this.root, dataNode, ref, false, false);
+ if (!nodes) {
+ warn(`XFA - Invalid reference: ${ref}.`);
+ continue;
+ }
+ const [node] = nodes;
+ if (!node[$isDescendent](this.data)) {
+ warn(`XFA - Invalid node: must be a data node.`);
+ continue;
+ }
+ const targetNodes = searchNode(this.root, formNode, target, false, false);
+ if (!targetNodes) {
+ warn(`XFA - Invalid target: ${target}.`);
+ continue;
+ }
+ const [targetNode] = targetNodes;
+ if (!targetNode[$isDescendent](formNode)) {
+ warn(`XFA - Invalid target: must be a property or subproperty.`);
+ continue;
+ }
+ const targetParent = targetNode[$getParent]();
+ if (targetNode instanceof SetProperty || targetParent instanceof SetProperty) {
+ warn(`XFA - Invalid target: cannot be a setProperty or one of its properties.`);
+ continue;
+ }
+ if (targetNode instanceof BindItems || targetParent instanceof BindItems) {
+ warn(`XFA - Invalid target: cannot be a bindItems or one of its properties.`);
+ continue;
+ }
+ const content = node[$text]();
+ const name = targetNode[$nodeName];
+ if (targetNode instanceof XFAAttribute) {
+ const attrs = Object.create(null);
+ attrs[name] = content;
+ const obj = Reflect.construct(Object.getPrototypeOf(targetParent).constructor, [attrs]);
+ targetParent[name] = obj[name];
+ continue;
+ }
+ if (!targetNode.hasOwnProperty($content)) {
+ warn(`XFA - Invalid node to use in setProperty`);
+ continue;
+ }
+ targetNode[$data] = node;
+ targetNode[$content] = content;
+ targetNode[$finalize]();
+ }
+ }
+ _bindItems(formNode, dataNode) {
+ if (!formNode.hasOwnProperty("items") || !formNode.hasOwnProperty("bindItems") || formNode.bindItems.isEmpty()) {
+ return;
+ }
+ for (const item of formNode.items.children) {
+ formNode[$removeChild](item);
+ }
+ formNode.items.clear();
+ const labels = new Items({});
+ const values = new Items({});
+ formNode[$appendChild](labels);
+ formNode.items.push(labels);
+ formNode[$appendChild](values);
+ formNode.items.push(values);
+ for (const {
+ ref,
+ labelRef,
+ valueRef,
+ connection
+ } of formNode.bindItems.children) {
+ if (connection) {
+ continue;
+ }
+ if (!ref) {
+ continue;
+ }
+ const nodes = searchNode(this.root, dataNode, ref, false, false);
+ if (!nodes) {
+ warn(`XFA - Invalid reference: ${ref}.`);
+ continue;
+ }
+ for (const node of nodes) {
+ if (!node[$isDescendent](this.datasets)) {
+ warn(`XFA - Invalid ref (${ref}): must be a datasets child.`);
+ continue;
+ }
+ const labelNodes = searchNode(this.root, node, labelRef, true, false);
+ if (!labelNodes) {
+ warn(`XFA - Invalid label: ${labelRef}.`);
+ continue;
+ }
+ const [labelNode] = labelNodes;
+ if (!labelNode[$isDescendent](this.datasets)) {
+ warn(`XFA - Invalid label: must be a datasets child.`);
+ continue;
+ }
+ const valueNodes = searchNode(this.root, node, valueRef, true, false);
+ if (!valueNodes) {
+ warn(`XFA - Invalid value: ${valueRef}.`);
+ continue;
+ }
+ const [valueNode] = valueNodes;
+ if (!valueNode[$isDescendent](this.datasets)) {
+ warn(`XFA - Invalid value: must be a datasets child.`);
+ continue;
+ }
+ const label = createText(labelNode[$text]());
+ const value = createText(valueNode[$text]());
+ labels[$appendChild](label);
+ labels.text.push(label);
+ values[$appendChild](value);
+ values.text.push(value);
+ }
+ }
+ }
+ _bindOccurrences(formNode, matches, picture) {
+ let baseClone;
+ if (matches.length > 1) {
+ baseClone = formNode[$clone]();
+ baseClone[$removeChild](baseClone.occur);
+ baseClone.occur = null;
+ }
+ this._bindValue(formNode, matches[0], picture);
+ this._setProperties(formNode, matches[0]);
+ this._bindItems(formNode, matches[0]);
+ if (matches.length === 1) {
+ return;
+ }
+ const parent = formNode[$getParent]();
+ const name = formNode[$nodeName];
+ const pos = parent[$indexOf](formNode);
+ for (let i = 1, ii = matches.length; i < ii; i++) {
+ const match = matches[i];
+ const clone = baseClone[$clone]();
+ parent[name].push(clone);
+ parent[$insertAt](pos + i, clone);
+ this._bindValue(clone, match, picture);
+ this._setProperties(clone, match);
+ this._bindItems(clone, match);
+ }
+ }
+ _createOccurrences(formNode) {
+ if (!this.emptyMerge) {
+ return;
+ }
+ const {
+ occur
+ } = formNode;
+ if (!occur || occur.initial <= 1) {
+ return;
+ }
+ const parent = formNode[$getParent]();
+ const name = formNode[$nodeName];
+ if (!(parent[name] instanceof XFAObjectArray)) {
+ return;
+ }
+ let currentNumber;
+ if (formNode.name) {
+ currentNumber = parent[name].children.filter(e => e.name === formNode.name).length;
+ } else {
+ currentNumber = parent[name].children.length;
+ }
+ const pos = parent[$indexOf](formNode) + 1;
+ const ii = occur.initial - currentNumber;
+ if (ii) {
+ const nodeClone = formNode[$clone]();
+ nodeClone[$removeChild](nodeClone.occur);
+ nodeClone.occur = null;
+ parent[name].push(nodeClone);
+ parent[$insertAt](pos, nodeClone);
+ for (let i = 1; i < ii; i++) {
+ const clone = nodeClone[$clone]();
+ parent[name].push(clone);
+ parent[$insertAt](pos + i, clone);
+ }
+ }
+ }
+ _getOccurInfo(formNode) {
+ const {
+ name,
+ occur
+ } = formNode;
+ if (!occur || !name) {
+ return [1, 1];
+ }
+ const max = occur.max === -1 ? Infinity : occur.max;
+ return [occur.min, max];
+ }
+ _setAndBind(formNode, dataNode) {
+ this._setProperties(formNode, dataNode);
+ this._bindItems(formNode, dataNode);
+ this._bindElement(formNode, dataNode);
+ }
+ _bindElement(formNode, dataNode) {
+ const uselessNodes = [];
+ this._createOccurrences(formNode);
+ for (const child of formNode[$getChildren]()) {
+ if (child[$data]) {
+ continue;
+ }
+ if (this._mergeMode === undefined && child[$nodeName] === "subform") {
+ this._mergeMode = child.mergeMode === "consumeData";
+ const dataChildren = dataNode[$getChildren]();
+ if (dataChildren.length > 0) {
+ this._bindOccurrences(child, [dataChildren[0]], null);
+ } else if (this.emptyMerge) {
+ const nsId = dataNode[$namespaceId] === bind_NS_DATASETS ? -1 : dataNode[$namespaceId];
+ const dataChild = child[$data] = new XmlObject(nsId, child.name || "root");
+ dataNode[$appendChild](dataChild);
+ this._bindElement(child, dataChild);
+ }
+ continue;
+ }
+ if (!child[$isBindable]()) {
+ continue;
+ }
+ let global = false;
+ let picture = null;
+ let ref = null;
+ let match = null;
+ if (child.bind) {
+ switch (child.bind.match) {
+ case "none":
+ this._setAndBind(child, dataNode);
+ continue;
+ case "global":
+ global = true;
+ break;
+ case "dataRef":
+ if (!child.bind.ref) {
+ warn(`XFA - ref is empty in node ${child[$nodeName]}.`);
+ this._setAndBind(child, dataNode);
+ continue;
+ }
+ ref = child.bind.ref;
+ break;
+ default:
+ break;
+ }
+ if (child.bind.picture) {
+ picture = child.bind.picture[$content];
+ }
+ }
+ const [min, max] = this._getOccurInfo(child);
+ if (ref) {
+ match = searchNode(this.root, dataNode, ref, true, false);
+ if (match === null) {
+ match = createDataNode(this.data, dataNode, ref);
+ if (!match) {
+ continue;
+ }
+ if (this._isConsumeData()) {
+ match[$consumed] = true;
+ }
+ this._setAndBind(child, match);
+ continue;
+ } else {
+ if (this._isConsumeData()) {
+ match = match.filter(node => !node[$consumed]);
+ }
+ if (match.length > max) {
+ match = match.slice(0, max);
+ } else if (match.length === 0) {
+ match = null;
+ }
+ if (match && this._isConsumeData()) {
+ match.forEach(node => {
+ node[$consumed] = true;
+ });
+ }
+ }
+ } else {
+ if (!child.name) {
+ this._setAndBind(child, dataNode);
+ continue;
+ }
+ if (this._isConsumeData()) {
+ const matches = [];
+ while (matches.length < max) {
+ const found = this._findDataByNameToConsume(child.name, child[$hasSettableValue](), dataNode, global);
+ if (!found) {
+ break;
+ }
+ found[$consumed] = true;
+ matches.push(found);
+ }
+ match = matches.length > 0 ? matches : null;
+ } else {
+ match = dataNode[$getRealChildrenByNameIt](child.name, false, this.emptyMerge).next().value;
+ if (!match) {
+ if (min === 0) {
+ uselessNodes.push(child);
+ continue;
+ }
+ const nsId = dataNode[$namespaceId] === bind_NS_DATASETS ? -1 : dataNode[$namespaceId];
+ match = child[$data] = new XmlObject(nsId, child.name);
+ if (this.emptyMerge) {
+ match[$consumed] = true;
+ }
+ dataNode[$appendChild](match);
+ this._setAndBind(child, match);
+ continue;
+ }
+ if (this.emptyMerge) {
+ match[$consumed] = true;
+ }
+ match = [match];
+ }
+ }
+ if (match) {
+ this._bindOccurrences(child, match, picture);
+ } else if (min > 0) {
+ this._setAndBind(child, dataNode);
+ } else {
+ uselessNodes.push(child);
+ }
+ }
+ uselessNodes.forEach(node => node[$getParent]()[$removeChild](node));
+ }
+}
+
+;// CONCATENATED MODULE: ./src/core/xfa/data.js
+
+class DataHandler {
+ constructor(root, data) {
+ this.data = data;
+ this.dataset = root.datasets || null;
+ }
+ serialize(storage) {
+ const stack = [[-1, this.data[$getChildren]()]];
+ while (stack.length > 0) {
+ const last = stack.at(-1);
+ const [i, children] = last;
+ if (i + 1 === children.length) {
+ stack.pop();
+ continue;
+ }
+ const child = children[++last[0]];
+ const storageEntry = storage.get(child[$uid]);
+ if (storageEntry) {
+ child[$setValue](storageEntry);
+ } else {
+ const attributes = child[$getAttributes]();
+ for (const value of attributes.values()) {
+ const entry = storage.get(value[$uid]);
+ if (entry) {
+ value[$setValue](entry);
+ break;
+ }
+ }
+ }
+ const nodes = child[$getChildren]();
+ if (nodes.length > 0) {
+ stack.push([-1, nodes]);
+ }
+ }
+ const buf = [`<xfa:datasets xmlns:xfa="http://www.xfa.org/schema/xfa-data/1.0/">`];
+ if (this.dataset) {
+ for (const child of this.dataset[$getChildren]()) {
+ if (child[$nodeName] !== "data") {
+ child[$toString](buf);
+ }
+ }
+ }
+ this.data[$toString](buf);
+ buf.push("</xfa:datasets>");
+ return buf.join("");
+ }
+}
+
+;// CONCATENATED MODULE: ./src/core/xfa/config.js
+
+
+
+
+
+const CONFIG_NS_ID = NamespaceIds.config.id;
+class Acrobat extends XFAObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "acrobat", true);
+ this.acrobat7 = null;
+ this.autoSave = null;
+ this.common = null;
+ this.validate = null;
+ this.validateApprovalSignatures = null;
+ this.submitUrl = new XFAObjectArray();
+ }
+}
+class Acrobat7 extends XFAObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "acrobat7", true);
+ this.dynamicRender = null;
+ }
+}
+class ADBE_JSConsole extends OptionObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "ADBE_JSConsole", ["delegate", "Enable", "Disable"]);
+ }
+}
+class ADBE_JSDebugger extends OptionObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "ADBE_JSDebugger", ["delegate", "Enable", "Disable"]);
+ }
+}
+class AddSilentPrint extends Option01 {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "addSilentPrint");
+ }
+}
+class AddViewerPreferences extends Option01 {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "addViewerPreferences");
+ }
+}
+class AdjustData extends Option10 {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "adjustData");
+ }
+}
+class AdobeExtensionLevel extends IntegerObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "adobeExtensionLevel", 0, n => n >= 1 && n <= 8);
+ }
+}
+class Agent extends XFAObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "agent", true);
+ this.name = attributes.name ? attributes.name.trim() : "";
+ this.common = new XFAObjectArray();
+ }
+}
+class AlwaysEmbed extends ContentObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "alwaysEmbed");
+ }
+}
+class Amd extends StringObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "amd");
+ }
+}
+class config_Area extends XFAObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "area");
+ this.level = getInteger({
+ data: attributes.level,
+ defaultValue: 0,
+ validate: n => n >= 1 && n <= 3
+ });
+ this.name = getStringOption(attributes.name, ["", "barcode", "coreinit", "deviceDriver", "font", "general", "layout", "merge", "script", "signature", "sourceSet", "templateCache"]);
+ }
+}
+class Attributes extends OptionObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "attributes", ["preserve", "delegate", "ignore"]);
+ }
+}
+class AutoSave extends OptionObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "autoSave", ["disabled", "enabled"]);
+ }
+}
+class Base extends StringObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "base");
+ }
+}
+class BatchOutput extends XFAObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "batchOutput");
+ this.format = getStringOption(attributes.format, ["none", "concat", "zip", "zipCompress"]);
+ }
+}
+class BehaviorOverride extends ContentObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "behaviorOverride");
+ }
+ [$finalize]() {
+ this[$content] = new Map(this[$content].trim().split(/\s+/).filter(x => x.includes(":")).map(x => x.split(":", 2)));
+ }
+}
+class Cache extends XFAObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "cache", true);
+ this.templateCache = null;
+ }
+}
+class Change extends Option01 {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "change");
+ }
+}
+class Common extends XFAObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "common", true);
+ this.data = null;
+ this.locale = null;
+ this.localeSet = null;
+ this.messaging = null;
+ this.suppressBanner = null;
+ this.template = null;
+ this.validationMessaging = null;
+ this.versionControl = null;
+ this.log = new XFAObjectArray();
+ }
+}
+class Compress extends XFAObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "compress");
+ this.scope = getStringOption(attributes.scope, ["imageOnly", "document"]);
+ }
+}
+class CompressLogicalStructure extends Option01 {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "compressLogicalStructure");
+ }
+}
+class CompressObjectStream extends Option10 {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "compressObjectStream");
+ }
+}
+class Compression extends XFAObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "compression", true);
+ this.compressLogicalStructure = null;
+ this.compressObjectStream = null;
+ this.level = null;
+ this.type = null;
+ }
+}
+class Config extends XFAObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "config", true);
+ this.acrobat = null;
+ this.present = null;
+ this.trace = null;
+ this.agent = new XFAObjectArray();
+ }
+}
+class Conformance extends OptionObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "conformance", ["A", "B"]);
+ }
+}
+class ContentCopy extends Option01 {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "contentCopy");
+ }
+}
+class Copies extends IntegerObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "copies", 1, n => n >= 1);
+ }
+}
+class Creator extends StringObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "creator");
+ }
+}
+class CurrentPage extends IntegerObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "currentPage", 0, n => n >= 0);
+ }
+}
+class Data extends XFAObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "data", true);
+ this.adjustData = null;
+ this.attributes = null;
+ this.incrementalLoad = null;
+ this.outputXSL = null;
+ this.range = null;
+ this.record = null;
+ this.startNode = null;
+ this.uri = null;
+ this.window = null;
+ this.xsl = null;
+ this.excludeNS = new XFAObjectArray();
+ this.transform = new XFAObjectArray();
+ }
+}
+class Debug extends XFAObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "debug", true);
+ this.uri = null;
+ }
+}
+class DefaultTypeface extends ContentObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "defaultTypeface");
+ this.writingScript = getStringOption(attributes.writingScript, ["*", "Arabic", "Cyrillic", "EastEuropeanRoman", "Greek", "Hebrew", "Japanese", "Korean", "Roman", "SimplifiedChinese", "Thai", "TraditionalChinese", "Vietnamese"]);
+ }
+}
+class Destination extends OptionObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "destination", ["pdf", "pcl", "ps", "webClient", "zpl"]);
+ }
+}
+class DocumentAssembly extends Option01 {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "documentAssembly");
+ }
+}
+class Driver extends XFAObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "driver", true);
+ this.name = attributes.name ? attributes.name.trim() : "";
+ this.fontInfo = null;
+ this.xdc = null;
+ }
+}
+class DuplexOption extends OptionObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "duplexOption", ["simplex", "duplexFlipLongEdge", "duplexFlipShortEdge"]);
+ }
+}
+class DynamicRender extends OptionObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "dynamicRender", ["forbidden", "required"]);
+ }
+}
+class Embed extends Option01 {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "embed");
+ }
+}
+class config_Encrypt extends Option01 {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "encrypt");
+ }
+}
+class config_Encryption extends XFAObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "encryption", true);
+ this.encrypt = null;
+ this.encryptionLevel = null;
+ this.permissions = null;
+ }
+}
+class EncryptionLevel extends OptionObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "encryptionLevel", ["40bit", "128bit"]);
+ }
+}
+class Enforce extends StringObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "enforce");
+ }
+}
+class Equate extends XFAObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "equate");
+ this.force = getInteger({
+ data: attributes.force,
+ defaultValue: 1,
+ validate: n => n === 0
+ });
+ this.from = attributes.from || "";
+ this.to = attributes.to || "";
+ }
+}
+class EquateRange extends XFAObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "equateRange");
+ this.from = attributes.from || "";
+ this.to = attributes.to || "";
+ this._unicodeRange = attributes.unicodeRange || "";
+ }
+ get unicodeRange() {
+ const ranges = [];
+ const unicodeRegex = /U\+([0-9a-fA-F]+)/;
+ const unicodeRange = this._unicodeRange;
+ for (let range of unicodeRange.split(",").map(x => x.trim()).filter(x => !!x)) {
+ range = range.split("-", 2).map(x => {
+ const found = x.match(unicodeRegex);
+ if (!found) {
+ return 0;
+ }
+ return parseInt(found[1], 16);
+ });
+ if (range.length === 1) {
+ range.push(range[0]);
+ }
+ ranges.push(range);
+ }
+ return shadow(this, "unicodeRange", ranges);
+ }
+}
+class Exclude extends ContentObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "exclude");
+ }
+ [$finalize]() {
+ this[$content] = this[$content].trim().split(/\s+/).filter(x => x && ["calculate", "close", "enter", "exit", "initialize", "ready", "validate"].includes(x));
+ }
+}
+class ExcludeNS extends StringObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "excludeNS");
+ }
+}
+class FlipLabel extends OptionObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "flipLabel", ["usePrinterSetting", "on", "off"]);
+ }
+}
+class config_FontInfo extends XFAObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "fontInfo", true);
+ this.embed = null;
+ this.map = null;
+ this.subsetBelow = null;
+ this.alwaysEmbed = new XFAObjectArray();
+ this.defaultTypeface = new XFAObjectArray();
+ this.neverEmbed = new XFAObjectArray();
+ }
+}
+class FormFieldFilling extends Option01 {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "formFieldFilling");
+ }
+}
+class GroupParent extends StringObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "groupParent");
+ }
+}
+class IfEmpty extends OptionObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "ifEmpty", ["dataValue", "dataGroup", "ignore", "remove"]);
+ }
+}
+class IncludeXDPContent extends StringObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "includeXDPContent");
+ }
+}
+class IncrementalLoad extends OptionObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "incrementalLoad", ["none", "forwardOnly"]);
+ }
+}
+class IncrementalMerge extends Option01 {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "incrementalMerge");
+ }
+}
+class Interactive extends Option01 {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "interactive");
+ }
+}
+class Jog extends OptionObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "jog", ["usePrinterSetting", "none", "pageSet"]);
+ }
+}
+class LabelPrinter extends XFAObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "labelPrinter", true);
+ this.name = getStringOption(attributes.name, ["zpl", "dpl", "ipl", "tcpl"]);
+ this.batchOutput = null;
+ this.flipLabel = null;
+ this.fontInfo = null;
+ this.xdc = null;
+ }
+}
+class Layout extends OptionObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "layout", ["paginate", "panel"]);
+ }
+}
+class Level extends IntegerObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "level", 0, n => n > 0);
+ }
+}
+class Linearized extends Option01 {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "linearized");
+ }
+}
+class Locale extends StringObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "locale");
+ }
+}
+class LocaleSet extends StringObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "localeSet");
+ }
+}
+class Log extends XFAObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "log", true);
+ this.mode = null;
+ this.threshold = null;
+ this.to = null;
+ this.uri = null;
+ }
+}
+class MapElement extends XFAObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "map", true);
+ this.equate = new XFAObjectArray();
+ this.equateRange = new XFAObjectArray();
+ }
+}
+class MediumInfo extends XFAObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "mediumInfo", true);
+ this.map = null;
+ }
+}
+class config_Message extends XFAObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "message", true);
+ this.msgId = null;
+ this.severity = null;
+ }
+}
+class Messaging extends XFAObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "messaging", true);
+ this.message = new XFAObjectArray();
+ }
+}
+class Mode extends OptionObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "mode", ["append", "overwrite"]);
+ }
+}
+class ModifyAnnots extends Option01 {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "modifyAnnots");
+ }
+}
+class MsgId extends IntegerObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "msgId", 1, n => n >= 1);
+ }
+}
+class NameAttr extends StringObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "nameAttr");
+ }
+}
+class NeverEmbed extends ContentObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "neverEmbed");
+ }
+}
+class NumberOfCopies extends IntegerObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "numberOfCopies", null, n => n >= 2 && n <= 5);
+ }
+}
+class OpenAction extends XFAObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "openAction", true);
+ this.destination = null;
+ }
+}
+class Output extends XFAObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "output", true);
+ this.to = null;
+ this.type = null;
+ this.uri = null;
+ }
+}
+class OutputBin extends StringObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "outputBin");
+ }
+}
+class OutputXSL extends XFAObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "outputXSL", true);
+ this.uri = null;
+ }
+}
+class Overprint extends OptionObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "overprint", ["none", "both", "draw", "field"]);
+ }
+}
+class Packets extends StringObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "packets");
+ }
+ [$finalize]() {
+ if (this[$content] === "*") {
+ return;
+ }
+ this[$content] = this[$content].trim().split(/\s+/).filter(x => ["config", "datasets", "template", "xfdf", "xslt"].includes(x));
+ }
+}
+class PageOffset extends XFAObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "pageOffset");
+ this.x = getInteger({
+ data: attributes.x,
+ defaultValue: "useXDCSetting",
+ validate: n => true
+ });
+ this.y = getInteger({
+ data: attributes.y,
+ defaultValue: "useXDCSetting",
+ validate: n => true
+ });
+ }
+}
+class PageRange extends StringObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "pageRange");
+ }
+ [$finalize]() {
+ const numbers = this[$content].trim().split(/\s+/).map(x => parseInt(x, 10));
+ const ranges = [];
+ for (let i = 0, ii = numbers.length; i < ii; i += 2) {
+ ranges.push(numbers.slice(i, i + 2));
+ }
+ this[$content] = ranges;
+ }
+}
+class Pagination extends OptionObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "pagination", ["simplex", "duplexShortEdge", "duplexLongEdge"]);
+ }
+}
+class PaginationOverride extends OptionObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "paginationOverride", ["none", "forceDuplex", "forceDuplexLongEdge", "forceDuplexShortEdge", "forceSimplex"]);
+ }
+}
+class Part extends IntegerObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "part", 1, n => false);
+ }
+}
+class Pcl extends XFAObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "pcl", true);
+ this.name = attributes.name || "";
+ this.batchOutput = null;
+ this.fontInfo = null;
+ this.jog = null;
+ this.mediumInfo = null;
+ this.outputBin = null;
+ this.pageOffset = null;
+ this.staple = null;
+ this.xdc = null;
+ }
+}
+class Pdf extends XFAObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "pdf", true);
+ this.name = attributes.name || "";
+ this.adobeExtensionLevel = null;
+ this.batchOutput = null;
+ this.compression = null;
+ this.creator = null;
+ this.encryption = null;
+ this.fontInfo = null;
+ this.interactive = null;
+ this.linearized = null;
+ this.openAction = null;
+ this.pdfa = null;
+ this.producer = null;
+ this.renderPolicy = null;
+ this.scriptModel = null;
+ this.silentPrint = null;
+ this.submitFormat = null;
+ this.tagged = null;
+ this.version = null;
+ this.viewerPreferences = null;
+ this.xdc = null;
+ }
+}
+class Pdfa extends XFAObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "pdfa", true);
+ this.amd = null;
+ this.conformance = null;
+ this.includeXDPContent = null;
+ this.part = null;
+ }
+}
+class Permissions extends XFAObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "permissions", true);
+ this.accessibleContent = null;
+ this.change = null;
+ this.contentCopy = null;
+ this.documentAssembly = null;
+ this.formFieldFilling = null;
+ this.modifyAnnots = null;
+ this.plaintextMetadata = null;
+ this.print = null;
+ this.printHighQuality = null;
+ }
+}
+class PickTrayByPDFSize extends Option01 {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "pickTrayByPDFSize");
+ }
+}
+class config_Picture extends StringObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "picture");
+ }
+}
+class PlaintextMetadata extends Option01 {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "plaintextMetadata");
+ }
+}
+class Presence extends OptionObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "presence", ["preserve", "dissolve", "dissolveStructure", "ignore", "remove"]);
+ }
+}
+class Present extends XFAObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "present", true);
+ this.behaviorOverride = null;
+ this.cache = null;
+ this.common = null;
+ this.copies = null;
+ this.destination = null;
+ this.incrementalMerge = null;
+ this.layout = null;
+ this.output = null;
+ this.overprint = null;
+ this.pagination = null;
+ this.paginationOverride = null;
+ this.script = null;
+ this.validate = null;
+ this.xdp = null;
+ this.driver = new XFAObjectArray();
+ this.labelPrinter = new XFAObjectArray();
+ this.pcl = new XFAObjectArray();
+ this.pdf = new XFAObjectArray();
+ this.ps = new XFAObjectArray();
+ this.submitUrl = new XFAObjectArray();
+ this.webClient = new XFAObjectArray();
+ this.zpl = new XFAObjectArray();
+ }
+}
+class Print extends Option01 {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "print");
+ }
+}
+class PrintHighQuality extends Option01 {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "printHighQuality");
+ }
+}
+class PrintScaling extends OptionObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "printScaling", ["appdefault", "noScaling"]);
+ }
+}
+class PrinterName extends StringObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "printerName");
+ }
+}
+class Producer extends StringObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "producer");
+ }
+}
+class Ps extends XFAObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "ps", true);
+ this.name = attributes.name || "";
+ this.batchOutput = null;
+ this.fontInfo = null;
+ this.jog = null;
+ this.mediumInfo = null;
+ this.outputBin = null;
+ this.staple = null;
+ this.xdc = null;
+ }
+}
+class Range extends ContentObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "range");
+ }
+ [$finalize]() {
+ this[$content] = this[$content].trim().split(/\s*,\s*/, 2).map(range => range.split("-").map(x => parseInt(x.trim(), 10))).filter(range => range.every(x => !isNaN(x))).map(range => {
+ if (range.length === 1) {
+ range.push(range[0]);
+ }
+ return range;
+ });
+ }
+}
+class Record extends ContentObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "record");
+ }
+ [$finalize]() {
+ this[$content] = this[$content].trim();
+ const n = parseInt(this[$content], 10);
+ if (!isNaN(n) && n >= 0) {
+ this[$content] = n;
+ }
+ }
+}
+class Relevant extends ContentObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "relevant");
+ }
+ [$finalize]() {
+ this[$content] = this[$content].trim().split(/\s+/);
+ }
+}
+class Rename extends ContentObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "rename");
+ }
+ [$finalize]() {
+ this[$content] = this[$content].trim();
+ if (this[$content].toLowerCase().startsWith("xml") || new RegExp("[\\p{L}_][\\p{L}\\d._\\p{M}-]*", "u").test(this[$content])) {
+ warn("XFA - Rename: invalid XFA name");
+ }
+ }
+}
+class RenderPolicy extends OptionObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "renderPolicy", ["server", "client"]);
+ }
+}
+class RunScripts extends OptionObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "runScripts", ["both", "client", "none", "server"]);
+ }
+}
+class config_Script extends XFAObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "script", true);
+ this.currentPage = null;
+ this.exclude = null;
+ this.runScripts = null;
+ }
+}
+class ScriptModel extends OptionObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "scriptModel", ["XFA", "none"]);
+ }
+}
+class Severity extends OptionObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "severity", ["ignore", "error", "information", "trace", "warning"]);
+ }
+}
+class SilentPrint extends XFAObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "silentPrint", true);
+ this.addSilentPrint = null;
+ this.printerName = null;
+ }
+}
+class Staple extends XFAObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "staple");
+ this.mode = getStringOption(attributes.mode, ["usePrinterSetting", "on", "off"]);
+ }
+}
+class StartNode extends StringObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "startNode");
+ }
+}
+class StartPage extends IntegerObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "startPage", 0, n => true);
+ }
+}
+class SubmitFormat extends OptionObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "submitFormat", ["html", "delegate", "fdf", "xml", "pdf"]);
+ }
+}
+class SubmitUrl extends StringObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "submitUrl");
+ }
+}
+class SubsetBelow extends IntegerObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "subsetBelow", 100, n => n >= 0 && n <= 100);
+ }
+}
+class SuppressBanner extends Option01 {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "suppressBanner");
+ }
+}
+class Tagged extends Option01 {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "tagged");
+ }
+}
+class config_Template extends XFAObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "template", true);
+ this.base = null;
+ this.relevant = null;
+ this.startPage = null;
+ this.uri = null;
+ this.xsl = null;
+ }
+}
+class Threshold extends OptionObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "threshold", ["trace", "error", "information", "warning"]);
+ }
+}
+class To extends OptionObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "to", ["null", "memory", "stderr", "stdout", "system", "uri"]);
+ }
+}
+class TemplateCache extends XFAObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "templateCache");
+ this.maxEntries = getInteger({
+ data: attributes.maxEntries,
+ defaultValue: 5,
+ validate: n => n >= 0
+ });
+ }
+}
+class Trace extends XFAObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "trace", true);
+ this.area = new XFAObjectArray();
+ }
+}
+class config_Transform extends XFAObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "transform", true);
+ this.groupParent = null;
+ this.ifEmpty = null;
+ this.nameAttr = null;
+ this.picture = null;
+ this.presence = null;
+ this.rename = null;
+ this.whitespace = null;
+ }
+}
+class Type extends OptionObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "type", ["none", "ascii85", "asciiHex", "ccittfax", "flate", "lzw", "runLength", "native", "xdp", "mergedXDP"]);
+ }
+}
+class Uri extends StringObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "uri");
+ }
+}
+class config_Validate extends OptionObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "validate", ["preSubmit", "prePrint", "preExecute", "preSave"]);
+ }
+}
+class ValidateApprovalSignatures extends ContentObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "validateApprovalSignatures");
+ }
+ [$finalize]() {
+ this[$content] = this[$content].trim().split(/\s+/).filter(x => ["docReady", "postSign"].includes(x));
+ }
+}
+class ValidationMessaging extends OptionObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "validationMessaging", ["allMessagesIndividually", "allMessagesTogether", "firstMessageOnly", "noMessages"]);
+ }
+}
+class Version extends OptionObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "version", ["1.7", "1.6", "1.5", "1.4", "1.3", "1.2"]);
+ }
+}
+class VersionControl extends XFAObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "VersionControl");
+ this.outputBelow = getStringOption(attributes.outputBelow, ["warn", "error", "update"]);
+ this.sourceAbove = getStringOption(attributes.sourceAbove, ["warn", "error"]);
+ this.sourceBelow = getStringOption(attributes.sourceBelow, ["update", "maintain"]);
+ }
+}
+class ViewerPreferences extends XFAObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "viewerPreferences", true);
+ this.ADBE_JSConsole = null;
+ this.ADBE_JSDebugger = null;
+ this.addViewerPreferences = null;
+ this.duplexOption = null;
+ this.enforce = null;
+ this.numberOfCopies = null;
+ this.pageRange = null;
+ this.pickTrayByPDFSize = null;
+ this.printScaling = null;
+ }
+}
+class WebClient extends XFAObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "webClient", true);
+ this.name = attributes.name ? attributes.name.trim() : "";
+ this.fontInfo = null;
+ this.xdc = null;
+ }
+}
+class Whitespace extends OptionObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "whitespace", ["preserve", "ltrim", "normalize", "rtrim", "trim"]);
+ }
+}
+class Window extends ContentObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "window");
+ }
+ [$finalize]() {
+ const pair = this[$content].trim().split(/\s*,\s*/, 2).map(x => parseInt(x, 10));
+ if (pair.some(x => isNaN(x))) {
+ this[$content] = [0, 0];
+ return;
+ }
+ if (pair.length === 1) {
+ pair.push(pair[0]);
+ }
+ this[$content] = pair;
+ }
+}
+class Xdc extends XFAObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "xdc", true);
+ this.uri = new XFAObjectArray();
+ this.xsl = new XFAObjectArray();
+ }
+}
+class Xdp extends XFAObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "xdp", true);
+ this.packets = null;
+ }
+}
+class Xsl extends XFAObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "xsl", true);
+ this.debug = null;
+ this.uri = null;
+ }
+}
+class Zpl extends XFAObject {
+ constructor(attributes) {
+ super(CONFIG_NS_ID, "zpl", true);
+ this.name = attributes.name ? attributes.name.trim() : "";
+ this.batchOutput = null;
+ this.flipLabel = null;
+ this.fontInfo = null;
+ this.xdc = null;
+ }
+}
+class ConfigNamespace {
+ static [$buildXFAObject](name, attributes) {
+ if (ConfigNamespace.hasOwnProperty(name)) {
+ return ConfigNamespace[name](attributes);
+ }
+ return undefined;
+ }
+ static acrobat(attrs) {
+ return new Acrobat(attrs);
+ }
+ static acrobat7(attrs) {
+ return new Acrobat7(attrs);
+ }
+ static ADBE_JSConsole(attrs) {
+ return new ADBE_JSConsole(attrs);
+ }
+ static ADBE_JSDebugger(attrs) {
+ return new ADBE_JSDebugger(attrs);
+ }
+ static addSilentPrint(attrs) {
+ return new AddSilentPrint(attrs);
+ }
+ static addViewerPreferences(attrs) {
+ return new AddViewerPreferences(attrs);
+ }
+ static adjustData(attrs) {
+ return new AdjustData(attrs);
+ }
+ static adobeExtensionLevel(attrs) {
+ return new AdobeExtensionLevel(attrs);
+ }
+ static agent(attrs) {
+ return new Agent(attrs);
+ }
+ static alwaysEmbed(attrs) {
+ return new AlwaysEmbed(attrs);
+ }
+ static amd(attrs) {
+ return new Amd(attrs);
+ }
+ static area(attrs) {
+ return new config_Area(attrs);
+ }
+ static attributes(attrs) {
+ return new Attributes(attrs);
+ }
+ static autoSave(attrs) {
+ return new AutoSave(attrs);
+ }
+ static base(attrs) {
+ return new Base(attrs);
+ }
+ static batchOutput(attrs) {
+ return new BatchOutput(attrs);
+ }
+ static behaviorOverride(attrs) {
+ return new BehaviorOverride(attrs);
+ }
+ static cache(attrs) {
+ return new Cache(attrs);
+ }
+ static change(attrs) {
+ return new Change(attrs);
+ }
+ static common(attrs) {
+ return new Common(attrs);
+ }
+ static compress(attrs) {
+ return new Compress(attrs);
+ }
+ static compressLogicalStructure(attrs) {
+ return new CompressLogicalStructure(attrs);
+ }
+ static compressObjectStream(attrs) {
+ return new CompressObjectStream(attrs);
+ }
+ static compression(attrs) {
+ return new Compression(attrs);
+ }
+ static config(attrs) {
+ return new Config(attrs);
+ }
+ static conformance(attrs) {
+ return new Conformance(attrs);
+ }
+ static contentCopy(attrs) {
+ return new ContentCopy(attrs);
+ }
+ static copies(attrs) {
+ return new Copies(attrs);
+ }
+ static creator(attrs) {
+ return new Creator(attrs);
+ }
+ static currentPage(attrs) {
+ return new CurrentPage(attrs);
+ }
+ static data(attrs) {
+ return new Data(attrs);
+ }
+ static debug(attrs) {
+ return new Debug(attrs);
+ }
+ static defaultTypeface(attrs) {
+ return new DefaultTypeface(attrs);
+ }
+ static destination(attrs) {
+ return new Destination(attrs);
+ }
+ static documentAssembly(attrs) {
+ return new DocumentAssembly(attrs);
+ }
+ static driver(attrs) {
+ return new Driver(attrs);
+ }
+ static duplexOption(attrs) {
+ return new DuplexOption(attrs);
+ }
+ static dynamicRender(attrs) {
+ return new DynamicRender(attrs);
+ }
+ static embed(attrs) {
+ return new Embed(attrs);
+ }
+ static encrypt(attrs) {
+ return new config_Encrypt(attrs);
+ }
+ static encryption(attrs) {
+ return new config_Encryption(attrs);
+ }
+ static encryptionLevel(attrs) {
+ return new EncryptionLevel(attrs);
+ }
+ static enforce(attrs) {
+ return new Enforce(attrs);
+ }
+ static equate(attrs) {
+ return new Equate(attrs);
+ }
+ static equateRange(attrs) {
+ return new EquateRange(attrs);
+ }
+ static exclude(attrs) {
+ return new Exclude(attrs);
+ }
+ static excludeNS(attrs) {
+ return new ExcludeNS(attrs);
+ }
+ static flipLabel(attrs) {
+ return new FlipLabel(attrs);
+ }
+ static fontInfo(attrs) {
+ return new config_FontInfo(attrs);
+ }
+ static formFieldFilling(attrs) {
+ return new FormFieldFilling(attrs);
+ }
+ static groupParent(attrs) {
+ return new GroupParent(attrs);
+ }
+ static ifEmpty(attrs) {
+ return new IfEmpty(attrs);
+ }
+ static includeXDPContent(attrs) {
+ return new IncludeXDPContent(attrs);
+ }
+ static incrementalLoad(attrs) {
+ return new IncrementalLoad(attrs);
+ }
+ static incrementalMerge(attrs) {
+ return new IncrementalMerge(attrs);
+ }
+ static interactive(attrs) {
+ return new Interactive(attrs);
+ }
+ static jog(attrs) {
+ return new Jog(attrs);
+ }
+ static labelPrinter(attrs) {
+ return new LabelPrinter(attrs);
+ }
+ static layout(attrs) {
+ return new Layout(attrs);
+ }
+ static level(attrs) {
+ return new Level(attrs);
+ }
+ static linearized(attrs) {
+ return new Linearized(attrs);
+ }
+ static locale(attrs) {
+ return new Locale(attrs);
+ }
+ static localeSet(attrs) {
+ return new LocaleSet(attrs);
+ }
+ static log(attrs) {
+ return new Log(attrs);
+ }
+ static map(attrs) {
+ return new MapElement(attrs);
+ }
+ static mediumInfo(attrs) {
+ return new MediumInfo(attrs);
+ }
+ static message(attrs) {
+ return new config_Message(attrs);
+ }
+ static messaging(attrs) {
+ return new Messaging(attrs);
+ }
+ static mode(attrs) {
+ return new Mode(attrs);
+ }
+ static modifyAnnots(attrs) {
+ return new ModifyAnnots(attrs);
+ }
+ static msgId(attrs) {
+ return new MsgId(attrs);
+ }
+ static nameAttr(attrs) {
+ return new NameAttr(attrs);
+ }
+ static neverEmbed(attrs) {
+ return new NeverEmbed(attrs);
+ }
+ static numberOfCopies(attrs) {
+ return new NumberOfCopies(attrs);
+ }
+ static openAction(attrs) {
+ return new OpenAction(attrs);
+ }
+ static output(attrs) {
+ return new Output(attrs);
+ }
+ static outputBin(attrs) {
+ return new OutputBin(attrs);
+ }
+ static outputXSL(attrs) {
+ return new OutputXSL(attrs);
+ }
+ static overprint(attrs) {
+ return new Overprint(attrs);
+ }
+ static packets(attrs) {
+ return new Packets(attrs);
+ }
+ static pageOffset(attrs) {
+ return new PageOffset(attrs);
+ }
+ static pageRange(attrs) {
+ return new PageRange(attrs);
+ }
+ static pagination(attrs) {
+ return new Pagination(attrs);
+ }
+ static paginationOverride(attrs) {
+ return new PaginationOverride(attrs);
+ }
+ static part(attrs) {
+ return new Part(attrs);
+ }
+ static pcl(attrs) {
+ return new Pcl(attrs);
+ }
+ static pdf(attrs) {
+ return new Pdf(attrs);
+ }
+ static pdfa(attrs) {
+ return new Pdfa(attrs);
+ }
+ static permissions(attrs) {
+ return new Permissions(attrs);
+ }
+ static pickTrayByPDFSize(attrs) {
+ return new PickTrayByPDFSize(attrs);
+ }
+ static picture(attrs) {
+ return new config_Picture(attrs);
+ }
+ static plaintextMetadata(attrs) {
+ return new PlaintextMetadata(attrs);
+ }
+ static presence(attrs) {
+ return new Presence(attrs);
+ }
+ static present(attrs) {
+ return new Present(attrs);
+ }
+ static print(attrs) {
+ return new Print(attrs);
+ }
+ static printHighQuality(attrs) {
+ return new PrintHighQuality(attrs);
+ }
+ static printScaling(attrs) {
+ return new PrintScaling(attrs);
+ }
+ static printerName(attrs) {
+ return new PrinterName(attrs);
+ }
+ static producer(attrs) {
+ return new Producer(attrs);
+ }
+ static ps(attrs) {
+ return new Ps(attrs);
+ }
+ static range(attrs) {
+ return new Range(attrs);
+ }
+ static record(attrs) {
+ return new Record(attrs);
+ }
+ static relevant(attrs) {
+ return new Relevant(attrs);
+ }
+ static rename(attrs) {
+ return new Rename(attrs);
+ }
+ static renderPolicy(attrs) {
+ return new RenderPolicy(attrs);
+ }
+ static runScripts(attrs) {
+ return new RunScripts(attrs);
+ }
+ static script(attrs) {
+ return new config_Script(attrs);
+ }
+ static scriptModel(attrs) {
+ return new ScriptModel(attrs);
+ }
+ static severity(attrs) {
+ return new Severity(attrs);
+ }
+ static silentPrint(attrs) {
+ return new SilentPrint(attrs);
+ }
+ static staple(attrs) {
+ return new Staple(attrs);
+ }
+ static startNode(attrs) {
+ return new StartNode(attrs);
+ }
+ static startPage(attrs) {
+ return new StartPage(attrs);
+ }
+ static submitFormat(attrs) {
+ return new SubmitFormat(attrs);
+ }
+ static submitUrl(attrs) {
+ return new SubmitUrl(attrs);
+ }
+ static subsetBelow(attrs) {
+ return new SubsetBelow(attrs);
+ }
+ static suppressBanner(attrs) {
+ return new SuppressBanner(attrs);
+ }
+ static tagged(attrs) {
+ return new Tagged(attrs);
+ }
+ static template(attrs) {
+ return new config_Template(attrs);
+ }
+ static templateCache(attrs) {
+ return new TemplateCache(attrs);
+ }
+ static threshold(attrs) {
+ return new Threshold(attrs);
+ }
+ static to(attrs) {
+ return new To(attrs);
+ }
+ static trace(attrs) {
+ return new Trace(attrs);
+ }
+ static transform(attrs) {
+ return new config_Transform(attrs);
+ }
+ static type(attrs) {
+ return new Type(attrs);
+ }
+ static uri(attrs) {
+ return new Uri(attrs);
+ }
+ static validate(attrs) {
+ return new config_Validate(attrs);
+ }
+ static validateApprovalSignatures(attrs) {
+ return new ValidateApprovalSignatures(attrs);
+ }
+ static validationMessaging(attrs) {
+ return new ValidationMessaging(attrs);
+ }
+ static version(attrs) {
+ return new Version(attrs);
+ }
+ static versionControl(attrs) {
+ return new VersionControl(attrs);
+ }
+ static viewerPreferences(attrs) {
+ return new ViewerPreferences(attrs);
+ }
+ static webClient(attrs) {
+ return new WebClient(attrs);
+ }
+ static whitespace(attrs) {
+ return new Whitespace(attrs);
+ }
+ static window(attrs) {
+ return new Window(attrs);
+ }
+ static xdc(attrs) {
+ return new Xdc(attrs);
+ }
+ static xdp(attrs) {
+ return new Xdp(attrs);
+ }
+ static xsl(attrs) {
+ return new Xsl(attrs);
+ }
+ static zpl(attrs) {
+ return new Zpl(attrs);
+ }
+}
+
+;// CONCATENATED MODULE: ./src/core/xfa/connection_set.js
+
+
+const CONNECTION_SET_NS_ID = NamespaceIds.connectionSet.id;
+class ConnectionSet extends XFAObject {
+ constructor(attributes) {
+ super(CONNECTION_SET_NS_ID, "connectionSet", true);
+ this.wsdlConnection = new XFAObjectArray();
+ this.xmlConnection = new XFAObjectArray();
+ this.xsdConnection = new XFAObjectArray();
+ }
+}
+class EffectiveInputPolicy extends XFAObject {
+ constructor(attributes) {
+ super(CONNECTION_SET_NS_ID, "effectiveInputPolicy");
+ this.id = attributes.id || "";
+ this.name = attributes.name || "";
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ }
+}
+class EffectiveOutputPolicy extends XFAObject {
+ constructor(attributes) {
+ super(CONNECTION_SET_NS_ID, "effectiveOutputPolicy");
+ this.id = attributes.id || "";
+ this.name = attributes.name || "";
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ }
+}
+class Operation extends StringObject {
+ constructor(attributes) {
+ super(CONNECTION_SET_NS_ID, "operation");
+ this.id = attributes.id || "";
+ this.input = attributes.input || "";
+ this.name = attributes.name || "";
+ this.output = attributes.output || "";
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ }
+}
+class RootElement extends StringObject {
+ constructor(attributes) {
+ super(CONNECTION_SET_NS_ID, "rootElement");
+ this.id = attributes.id || "";
+ this.name = attributes.name || "";
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ }
+}
+class SoapAction extends StringObject {
+ constructor(attributes) {
+ super(CONNECTION_SET_NS_ID, "soapAction");
+ this.id = attributes.id || "";
+ this.name = attributes.name || "";
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ }
+}
+class SoapAddress extends StringObject {
+ constructor(attributes) {
+ super(CONNECTION_SET_NS_ID, "soapAddress");
+ this.id = attributes.id || "";
+ this.name = attributes.name || "";
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ }
+}
+class connection_set_Uri extends StringObject {
+ constructor(attributes) {
+ super(CONNECTION_SET_NS_ID, "uri");
+ this.id = attributes.id || "";
+ this.name = attributes.name || "";
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ }
+}
+class WsdlAddress extends StringObject {
+ constructor(attributes) {
+ super(CONNECTION_SET_NS_ID, "wsdlAddress");
+ this.id = attributes.id || "";
+ this.name = attributes.name || "";
+ this.use = attributes.use || "";
+ this.usehref = attributes.usehref || "";
+ }
+}
+class WsdlConnection extends XFAObject {
+ constructor(attributes) {
+ super(CONNECTION_SET_NS_ID, "wsdlConnection", true);
+ this.dataDescription = attributes.dataDescription || "";
+ this.name = attributes.name || "";
+ this.effectiveInputPolicy = null;
+ this.effectiveOutputPolicy = null;
+ this.operation = null;
+ this.soapAction = null;
+ this.soapAddress = null;
+ this.wsdlAddress = null;
+ }
+}
+class XmlConnection extends XFAObject {
+ constructor(attributes) {
+ super(CONNECTION_SET_NS_ID, "xmlConnection", true);
+ this.dataDescription = attributes.dataDescription || "";
+ this.name = attributes.name || "";
+ this.uri = null;
+ }
+}
+class XsdConnection extends XFAObject {
+ constructor(attributes) {
+ super(CONNECTION_SET_NS_ID, "xsdConnection", true);
+ this.dataDescription = attributes.dataDescription || "";
+ this.name = attributes.name || "";
+ this.rootElement = null;
+ this.uri = null;
+ }
+}
+class ConnectionSetNamespace {
+ static [$buildXFAObject](name, attributes) {
+ if (ConnectionSetNamespace.hasOwnProperty(name)) {
+ return ConnectionSetNamespace[name](attributes);
+ }
+ return undefined;
+ }
+ static connectionSet(attrs) {
+ return new ConnectionSet(attrs);
+ }
+ static effectiveInputPolicy(attrs) {
+ return new EffectiveInputPolicy(attrs);
+ }
+ static effectiveOutputPolicy(attrs) {
+ return new EffectiveOutputPolicy(attrs);
+ }
+ static operation(attrs) {
+ return new Operation(attrs);
+ }
+ static rootElement(attrs) {
+ return new RootElement(attrs);
+ }
+ static soapAction(attrs) {
+ return new SoapAction(attrs);
+ }
+ static soapAddress(attrs) {
+ return new SoapAddress(attrs);
+ }
+ static uri(attrs) {
+ return new connection_set_Uri(attrs);
+ }
+ static wsdlAddress(attrs) {
+ return new WsdlAddress(attrs);
+ }
+ static wsdlConnection(attrs) {
+ return new WsdlConnection(attrs);
+ }
+ static xmlConnection(attrs) {
+ return new XmlConnection(attrs);
+ }
+ static xsdConnection(attrs) {
+ return new XsdConnection(attrs);
+ }
+}
+
+;// CONCATENATED MODULE: ./src/core/xfa/datasets.js
+
+
+
+const DATASETS_NS_ID = NamespaceIds.datasets.id;
+class datasets_Data extends XmlObject {
+ constructor(attributes) {
+ super(DATASETS_NS_ID, "data", attributes);
+ }
+ [$isNsAgnostic]() {
+ return true;
+ }
+}
+class Datasets extends XFAObject {
+ constructor(attributes) {
+ super(DATASETS_NS_ID, "datasets", true);
+ this.data = null;
+ this.Signature = null;
+ }
+ [$onChild](child) {
+ const name = child[$nodeName];
+ if (name === "data" && child[$namespaceId] === DATASETS_NS_ID || name === "Signature" && child[$namespaceId] === NamespaceIds.signature.id) {
+ this[name] = child;
+ }
+ this[$appendChild](child);
+ }
+}
+class DatasetsNamespace {
+ static [$buildXFAObject](name, attributes) {
+ if (DatasetsNamespace.hasOwnProperty(name)) {
+ return DatasetsNamespace[name](attributes);
+ }
+ return undefined;
+ }
+ static datasets(attributes) {
+ return new Datasets(attributes);
+ }
+ static data(attributes) {
+ return new datasets_Data(attributes);
+ }
+}
+
+;// CONCATENATED MODULE: ./src/core/xfa/locale_set.js
+
+
+
+const LOCALE_SET_NS_ID = NamespaceIds.localeSet.id;
+class CalendarSymbols extends XFAObject {
+ constructor(attributes) {
+ super(LOCALE_SET_NS_ID, "calendarSymbols", true);
+ this.name = "gregorian";
+ this.dayNames = new XFAObjectArray(2);
+ this.eraNames = null;
+ this.meridiemNames = null;
+ this.monthNames = new XFAObjectArray(2);
+ }
+}
+class CurrencySymbol extends StringObject {
+ constructor(attributes) {
+ super(LOCALE_SET_NS_ID, "currencySymbol");
+ this.name = getStringOption(attributes.name, ["symbol", "isoname", "decimal"]);
+ }
+}
+class CurrencySymbols extends XFAObject {
+ constructor(attributes) {
+ super(LOCALE_SET_NS_ID, "currencySymbols", true);
+ this.currencySymbol = new XFAObjectArray(3);
+ }
+}
+class DatePattern extends StringObject {
+ constructor(attributes) {
+ super(LOCALE_SET_NS_ID, "datePattern");
+ this.name = getStringOption(attributes.name, ["full", "long", "med", "short"]);
+ }
+}
+class DatePatterns extends XFAObject {
+ constructor(attributes) {
+ super(LOCALE_SET_NS_ID, "datePatterns", true);
+ this.datePattern = new XFAObjectArray(4);
+ }
+}
+class DateTimeSymbols extends ContentObject {
+ constructor(attributes) {
+ super(LOCALE_SET_NS_ID, "dateTimeSymbols");
+ }
+}
+class Day extends StringObject {
+ constructor(attributes) {
+ super(LOCALE_SET_NS_ID, "day");
+ }
+}
+class DayNames extends XFAObject {
+ constructor(attributes) {
+ super(LOCALE_SET_NS_ID, "dayNames", true);
+ this.abbr = getInteger({
+ data: attributes.abbr,
+ defaultValue: 0,
+ validate: x => x === 1
+ });
+ this.day = new XFAObjectArray(7);
+ }
+}
+class Era extends StringObject {
+ constructor(attributes) {
+ super(LOCALE_SET_NS_ID, "era");
+ }
+}
+class EraNames extends XFAObject {
+ constructor(attributes) {
+ super(LOCALE_SET_NS_ID, "eraNames", true);
+ this.era = new XFAObjectArray(2);
+ }
+}
+class locale_set_Locale extends XFAObject {
+ constructor(attributes) {
+ super(LOCALE_SET_NS_ID, "locale", true);
+ this.desc = attributes.desc || "";
+ this.name = "isoname";
+ this.calendarSymbols = null;
+ this.currencySymbols = null;
+ this.datePatterns = null;
+ this.dateTimeSymbols = null;
+ this.numberPatterns = null;
+ this.numberSymbols = null;
+ this.timePatterns = null;
+ this.typeFaces = null;
+ }
+}
+class locale_set_LocaleSet extends XFAObject {
+ constructor(attributes) {
+ super(LOCALE_SET_NS_ID, "localeSet", true);
+ this.locale = new XFAObjectArray();
+ }
+}
+class Meridiem extends StringObject {
+ constructor(attributes) {
+ super(LOCALE_SET_NS_ID, "meridiem");
+ }
+}
+class MeridiemNames extends XFAObject {
+ constructor(attributes) {
+ super(LOCALE_SET_NS_ID, "meridiemNames", true);
+ this.meridiem = new XFAObjectArray(2);
+ }
+}
+class Month extends StringObject {
+ constructor(attributes) {
+ super(LOCALE_SET_NS_ID, "month");
+ }
+}
+class MonthNames extends XFAObject {
+ constructor(attributes) {
+ super(LOCALE_SET_NS_ID, "monthNames", true);
+ this.abbr = getInteger({
+ data: attributes.abbr,
+ defaultValue: 0,
+ validate: x => x === 1
+ });
+ this.month = new XFAObjectArray(12);
+ }
+}
+class NumberPattern extends StringObject {
+ constructor(attributes) {
+ super(LOCALE_SET_NS_ID, "numberPattern");
+ this.name = getStringOption(attributes.name, ["full", "long", "med", "short"]);
+ }
+}
+class NumberPatterns extends XFAObject {
+ constructor(attributes) {
+ super(LOCALE_SET_NS_ID, "numberPatterns", true);
+ this.numberPattern = new XFAObjectArray(4);
+ }
+}
+class NumberSymbol extends StringObject {
+ constructor(attributes) {
+ super(LOCALE_SET_NS_ID, "numberSymbol");
+ this.name = getStringOption(attributes.name, ["decimal", "grouping", "percent", "minus", "zero"]);
+ }
+}
+class NumberSymbols extends XFAObject {
+ constructor(attributes) {
+ super(LOCALE_SET_NS_ID, "numberSymbols", true);
+ this.numberSymbol = new XFAObjectArray(5);
+ }
+}
+class TimePattern extends StringObject {
+ constructor(attributes) {
+ super(LOCALE_SET_NS_ID, "timePattern");
+ this.name = getStringOption(attributes.name, ["full", "long", "med", "short"]);
+ }
+}
+class TimePatterns extends XFAObject {
+ constructor(attributes) {
+ super(LOCALE_SET_NS_ID, "timePatterns", true);
+ this.timePattern = new XFAObjectArray(4);
+ }
+}
+class TypeFace extends XFAObject {
+ constructor(attributes) {
+ super(LOCALE_SET_NS_ID, "typeFace", true);
+ this.name = attributes.name | "";
+ }
+}
+class TypeFaces extends XFAObject {
+ constructor(attributes) {
+ super(LOCALE_SET_NS_ID, "typeFaces", true);
+ this.typeFace = new XFAObjectArray();
+ }
+}
+class LocaleSetNamespace {
+ static [$buildXFAObject](name, attributes) {
+ if (LocaleSetNamespace.hasOwnProperty(name)) {
+ return LocaleSetNamespace[name](attributes);
+ }
+ return undefined;
+ }
+ static calendarSymbols(attrs) {
+ return new CalendarSymbols(attrs);
+ }
+ static currencySymbol(attrs) {
+ return new CurrencySymbol(attrs);
+ }
+ static currencySymbols(attrs) {
+ return new CurrencySymbols(attrs);
+ }
+ static datePattern(attrs) {
+ return new DatePattern(attrs);
+ }
+ static datePatterns(attrs) {
+ return new DatePatterns(attrs);
+ }
+ static dateTimeSymbols(attrs) {
+ return new DateTimeSymbols(attrs);
+ }
+ static day(attrs) {
+ return new Day(attrs);
+ }
+ static dayNames(attrs) {
+ return new DayNames(attrs);
+ }
+ static era(attrs) {
+ return new Era(attrs);
+ }
+ static eraNames(attrs) {
+ return new EraNames(attrs);
+ }
+ static locale(attrs) {
+ return new locale_set_Locale(attrs);
+ }
+ static localeSet(attrs) {
+ return new locale_set_LocaleSet(attrs);
+ }
+ static meridiem(attrs) {
+ return new Meridiem(attrs);
+ }
+ static meridiemNames(attrs) {
+ return new MeridiemNames(attrs);
+ }
+ static month(attrs) {
+ return new Month(attrs);
+ }
+ static monthNames(attrs) {
+ return new MonthNames(attrs);
+ }
+ static numberPattern(attrs) {
+ return new NumberPattern(attrs);
+ }
+ static numberPatterns(attrs) {
+ return new NumberPatterns(attrs);
+ }
+ static numberSymbol(attrs) {
+ return new NumberSymbol(attrs);
+ }
+ static numberSymbols(attrs) {
+ return new NumberSymbols(attrs);
+ }
+ static timePattern(attrs) {
+ return new TimePattern(attrs);
+ }
+ static timePatterns(attrs) {
+ return new TimePatterns(attrs);
+ }
+ static typeFace(attrs) {
+ return new TypeFace(attrs);
+ }
+ static typeFaces(attrs) {
+ return new TypeFaces(attrs);
+ }
+}
+
+;// CONCATENATED MODULE: ./src/core/xfa/signature.js
+
+
+const SIGNATURE_NS_ID = NamespaceIds.signature.id;
+class signature_Signature extends XFAObject {
+ constructor(attributes) {
+ super(SIGNATURE_NS_ID, "signature", true);
+ }
+}
+class SignatureNamespace {
+ static [$buildXFAObject](name, attributes) {
+ if (SignatureNamespace.hasOwnProperty(name)) {
+ return SignatureNamespace[name](attributes);
+ }
+ return undefined;
+ }
+ static signature(attributes) {
+ return new signature_Signature(attributes);
+ }
+}
+
+;// CONCATENATED MODULE: ./src/core/xfa/stylesheet.js
+
+
+const STYLESHEET_NS_ID = NamespaceIds.stylesheet.id;
+class Stylesheet extends XFAObject {
+ constructor(attributes) {
+ super(STYLESHEET_NS_ID, "stylesheet", true);
+ }
+}
+class StylesheetNamespace {
+ static [$buildXFAObject](name, attributes) {
+ if (StylesheetNamespace.hasOwnProperty(name)) {
+ return StylesheetNamespace[name](attributes);
+ }
+ return undefined;
+ }
+ static stylesheet(attributes) {
+ return new Stylesheet(attributes);
+ }
+}
+
+;// CONCATENATED MODULE: ./src/core/xfa/xdp.js
+
+
+
+const XDP_NS_ID = NamespaceIds.xdp.id;
+class xdp_Xdp extends XFAObject {
+ constructor(attributes) {
+ super(XDP_NS_ID, "xdp", true);
+ this.uuid = attributes.uuid || "";
+ this.timeStamp = attributes.timeStamp || "";
+ this.config = null;
+ this.connectionSet = null;
+ this.datasets = null;
+ this.localeSet = null;
+ this.stylesheet = new XFAObjectArray();
+ this.template = null;
+ }
+ [$onChildCheck](child) {
+ const ns = NamespaceIds[child[$nodeName]];
+ return ns && child[$namespaceId] === ns.id;
+ }
+}
+class XdpNamespace {
+ static [$buildXFAObject](name, attributes) {
+ if (XdpNamespace.hasOwnProperty(name)) {
+ return XdpNamespace[name](attributes);
+ }
+ return undefined;
+ }
+ static xdp(attributes) {
+ return new xdp_Xdp(attributes);
+ }
+}
+
+;// CONCATENATED MODULE: ./src/core/xfa/xhtml.js
+
+
+
+
+
+const XHTML_NS_ID = NamespaceIds.xhtml.id;
+const $richText = Symbol();
+const VALID_STYLES = new Set(["color", "font", "font-family", "font-size", "font-stretch", "font-style", "font-weight", "margin", "margin-bottom", "margin-left", "margin-right", "margin-top", "letter-spacing", "line-height", "orphans", "page-break-after", "page-break-before", "page-break-inside", "tab-interval", "tab-stop", "text-align", "text-decoration", "text-indent", "vertical-align", "widows", "kerning-mode", "xfa-font-horizontal-scale", "xfa-font-vertical-scale", "xfa-spacerun", "xfa-tab-stops"]);
+const StyleMapping = new Map([["page-break-after", "breakAfter"], ["page-break-before", "breakBefore"], ["page-break-inside", "breakInside"], ["kerning-mode", value => value === "none" ? "none" : "normal"], ["xfa-font-horizontal-scale", value => `scaleX(${Math.max(0, Math.min(parseInt(value) / 100)).toFixed(2)})`], ["xfa-font-vertical-scale", value => `scaleY(${Math.max(0, Math.min(parseInt(value) / 100)).toFixed(2)})`], ["xfa-spacerun", ""], ["xfa-tab-stops", ""], ["font-size", (value, original) => {
+ value = original.fontSize = getMeasurement(value);
+ return measureToString(0.99 * value);
+}], ["letter-spacing", value => measureToString(getMeasurement(value))], ["line-height", value => measureToString(getMeasurement(value))], ["margin", value => measureToString(getMeasurement(value))], ["margin-bottom", value => measureToString(getMeasurement(value))], ["margin-left", value => measureToString(getMeasurement(value))], ["margin-right", value => measureToString(getMeasurement(value))], ["margin-top", value => measureToString(getMeasurement(value))], ["text-indent", value => measureToString(getMeasurement(value))], ["font-family", value => value], ["vertical-align", value => measureToString(getMeasurement(value))]]);
+const spacesRegExp = /\s+/g;
+const crlfRegExp = /[\r\n]+/g;
+const crlfForRichTextRegExp = /\r\n?/g;
+function mapStyle(styleStr, node, richText) {
+ const style = Object.create(null);
+ if (!styleStr) {
+ return style;
+ }
+ const original = Object.create(null);
+ for (const [key, value] of styleStr.split(";").map(s => s.split(":", 2))) {
+ const mapping = StyleMapping.get(key);
+ if (mapping === "") {
+ continue;
+ }
+ let newValue = value;
+ if (mapping) {
+ newValue = typeof mapping === "string" ? mapping : mapping(value, original);
+ }
+ if (key.endsWith("scale")) {
+ style.transform = style.transform ? `${style[key]} ${newValue}` : newValue;
+ } else {
+ style[key.replaceAll(/-([a-zA-Z])/g, (_, x) => x.toUpperCase())] = newValue;
+ }
+ }
+ if (style.fontFamily) {
+ setFontFamily({
+ typeface: style.fontFamily,
+ weight: style.fontWeight || "normal",
+ posture: style.fontStyle || "normal",
+ size: original.fontSize || 0
+ }, node, node[$globalData].fontFinder, style);
+ }
+ if (richText && style.verticalAlign && style.verticalAlign !== "0px" && style.fontSize) {
+ const SUB_SUPER_SCRIPT_FACTOR = 0.583;
+ const VERTICAL_FACTOR = 0.333;
+ const fontSize = getMeasurement(style.fontSize);
+ style.fontSize = measureToString(fontSize * SUB_SUPER_SCRIPT_FACTOR);
+ style.verticalAlign = measureToString(Math.sign(getMeasurement(style.verticalAlign)) * fontSize * VERTICAL_FACTOR);
+ }
+ if (richText && style.fontSize) {
+ style.fontSize = `calc(${style.fontSize} * var(--scale-factor))`;
+ }
+ fixTextIndent(style);
+ return style;
+}
+function checkStyle(node) {
+ if (!node.style) {
+ return "";
+ }
+ return node.style.trim().split(/\s*;\s*/).filter(s => !!s).map(s => s.split(/\s*:\s*/, 2)).filter(([key, value]) => {
+ if (key === "font-family") {
+ node[$globalData].usedTypefaces.add(value);
+ }
+ return VALID_STYLES.has(key);
+ }).map(kv => kv.join(":")).join(";");
+}
+const NoWhites = new Set(["body", "html"]);
+class XhtmlObject extends XmlObject {
+ constructor(attributes, name) {
+ super(XHTML_NS_ID, name);
+ this[$richText] = false;
+ this.style = attributes.style || "";
+ }
+ [$clean](builder) {
+ super[$clean](builder);
+ this.style = checkStyle(this);
+ }
+ [$acceptWhitespace]() {
+ return !NoWhites.has(this[$nodeName]);
+ }
+ [$onText](str, richText = false) {
+ if (!richText) {
+ str = str.replaceAll(crlfRegExp, "");
+ if (!this.style.includes("xfa-spacerun:yes")) {
+ str = str.replaceAll(spacesRegExp, " ");
+ }
+ } else {
+ this[$richText] = true;
+ }
+ if (str) {
+ this[$content] += str;
+ }
+ }
+ [$pushGlyphs](measure, mustPop = true) {
+ const xfaFont = Object.create(null);
+ const margin = {
+ top: NaN,
+ bottom: NaN,
+ left: NaN,
+ right: NaN
+ };
+ let lineHeight = null;
+ for (const [key, value] of this.style.split(";").map(s => s.split(":", 2))) {
+ switch (key) {
+ case "font-family":
+ xfaFont.typeface = stripQuotes(value);
+ break;
+ case "font-size":
+ xfaFont.size = getMeasurement(value);
+ break;
+ case "font-weight":
+ xfaFont.weight = value;
+ break;
+ case "font-style":
+ xfaFont.posture = value;
+ break;
+ case "letter-spacing":
+ xfaFont.letterSpacing = getMeasurement(value);
+ break;
+ case "margin":
+ const values = value.split(/ \t/).map(x => getMeasurement(x));
+ switch (values.length) {
+ case 1:
+ margin.top = margin.bottom = margin.left = margin.right = values[0];
+ break;
+ case 2:
+ margin.top = margin.bottom = values[0];
+ margin.left = margin.right = values[1];
+ break;
+ case 3:
+ margin.top = values[0];
+ margin.bottom = values[2];
+ margin.left = margin.right = values[1];
+ break;
+ case 4:
+ margin.top = values[0];
+ margin.left = values[1];
+ margin.bottom = values[2];
+ margin.right = values[3];
+ break;
+ }
+ break;
+ case "margin-top":
+ margin.top = getMeasurement(value);
+ break;
+ case "margin-bottom":
+ margin.bottom = getMeasurement(value);
+ break;
+ case "margin-left":
+ margin.left = getMeasurement(value);
+ break;
+ case "margin-right":
+ margin.right = getMeasurement(value);
+ break;
+ case "line-height":
+ lineHeight = getMeasurement(value);
+ break;
+ }
+ }
+ measure.pushData(xfaFont, margin, lineHeight);
+ if (this[$content]) {
+ measure.addString(this[$content]);
+ } else {
+ for (const child of this[$getChildren]()) {
+ if (child[$nodeName] === "#text") {
+ measure.addString(child[$content]);
+ continue;
+ }
+ child[$pushGlyphs](measure);
+ }
+ }
+ if (mustPop) {
+ measure.popFont();
+ }
+ }
+ [$toHTML](availableSpace) {
+ const children = [];
+ this[$extra] = {
+ children
+ };
+ this[$childrenToHTML]({});
+ if (children.length === 0 && !this[$content]) {
+ return HTMLResult.EMPTY;
+ }
+ let value;
+ if (this[$richText]) {
+ value = this[$content] ? this[$content].replaceAll(crlfForRichTextRegExp, "\n") : undefined;
+ } else {
+ value = this[$content] || undefined;
+ }
+ return HTMLResult.success({
+ name: this[$nodeName],
+ attributes: {
+ href: this.href,
+ style: mapStyle(this.style, this, this[$richText])
+ },
+ children,
+ value
+ });
+ }
+}
+class A extends XhtmlObject {
+ constructor(attributes) {
+ super(attributes, "a");
+ this.href = fixURL(attributes.href) || "";
+ }
+}
+class B extends XhtmlObject {
+ constructor(attributes) {
+ super(attributes, "b");
+ }
+ [$pushGlyphs](measure) {
+ measure.pushFont({
+ weight: "bold"
+ });
+ super[$pushGlyphs](measure);
+ measure.popFont();
+ }
+}
+class Body extends XhtmlObject {
+ constructor(attributes) {
+ super(attributes, "body");
+ }
+ [$toHTML](availableSpace) {
+ const res = super[$toHTML](availableSpace);
+ const {
+ html
+ } = res;
+ if (!html) {
+ return HTMLResult.EMPTY;
+ }
+ html.name = "div";
+ html.attributes.class = ["xfaRich"];
+ return res;
+ }
+}
+class Br extends XhtmlObject {
+ constructor(attributes) {
+ super(attributes, "br");
+ }
+ [$text]() {
+ return "\n";
+ }
+ [$pushGlyphs](measure) {
+ measure.addString("\n");
+ }
+ [$toHTML](availableSpace) {
+ return HTMLResult.success({
+ name: "br"
+ });
+ }
+}
+class Html extends XhtmlObject {
+ constructor(attributes) {
+ super(attributes, "html");
+ }
+ [$toHTML](availableSpace) {
+ const children = [];
+ this[$extra] = {
+ children
+ };
+ this[$childrenToHTML]({});
+ if (children.length === 0) {
+ return HTMLResult.success({
+ name: "div",
+ attributes: {
+ class: ["xfaRich"],
+ style: {}
+ },
+ value: this[$content] || ""
+ });
+ }
+ if (children.length === 1) {
+ const child = children[0];
+ if (child.attributes?.class.includes("xfaRich")) {
+ return HTMLResult.success(child);
+ }
+ }
+ return HTMLResult.success({
+ name: "div",
+ attributes: {
+ class: ["xfaRich"],
+ style: {}
+ },
+ children
+ });
+ }
+}
+class I extends XhtmlObject {
+ constructor(attributes) {
+ super(attributes, "i");
+ }
+ [$pushGlyphs](measure) {
+ measure.pushFont({
+ posture: "italic"
+ });
+ super[$pushGlyphs](measure);
+ measure.popFont();
+ }
+}
+class Li extends XhtmlObject {
+ constructor(attributes) {
+ super(attributes, "li");
+ }
+}
+class Ol extends XhtmlObject {
+ constructor(attributes) {
+ super(attributes, "ol");
+ }
+}
+class P extends XhtmlObject {
+ constructor(attributes) {
+ super(attributes, "p");
+ }
+ [$pushGlyphs](measure) {
+ super[$pushGlyphs](measure, false);
+ measure.addString("\n");
+ measure.addPara();
+ measure.popFont();
+ }
+ [$text]() {
+ const siblings = this[$getParent]()[$getChildren]();
+ if (siblings.at(-1) === this) {
+ return super[$text]();
+ }
+ return super[$text]() + "\n";
+ }
+}
+class Span extends XhtmlObject {
+ constructor(attributes) {
+ super(attributes, "span");
+ }
+}
+class Sub extends XhtmlObject {
+ constructor(attributes) {
+ super(attributes, "sub");
+ }
+}
+class Sup extends XhtmlObject {
+ constructor(attributes) {
+ super(attributes, "sup");
+ }
+}
+class Ul extends XhtmlObject {
+ constructor(attributes) {
+ super(attributes, "ul");
+ }
+}
+class XhtmlNamespace {
+ static [$buildXFAObject](name, attributes) {
+ if (XhtmlNamespace.hasOwnProperty(name)) {
+ return XhtmlNamespace[name](attributes);
+ }
+ return undefined;
+ }
+ static a(attributes) {
+ return new A(attributes);
+ }
+ static b(attributes) {
+ return new B(attributes);
+ }
+ static body(attributes) {
+ return new Body(attributes);
+ }
+ static br(attributes) {
+ return new Br(attributes);
+ }
+ static html(attributes) {
+ return new Html(attributes);
+ }
+ static i(attributes) {
+ return new I(attributes);
+ }
+ static li(attributes) {
+ return new Li(attributes);
+ }
+ static ol(attributes) {
+ return new Ol(attributes);
+ }
+ static p(attributes) {
+ return new P(attributes);
+ }
+ static span(attributes) {
+ return new Span(attributes);
+ }
+ static sub(attributes) {
+ return new Sub(attributes);
+ }
+ static sup(attributes) {
+ return new Sup(attributes);
+ }
+ static ul(attributes) {
+ return new Ul(attributes);
+ }
+}
+
+;// CONCATENATED MODULE: ./src/core/xfa/setup.js
+
+
+
+
+
+
+
+
+
+const NamespaceSetUp = {
+ config: ConfigNamespace,
+ connection: ConnectionSetNamespace,
+ datasets: DatasetsNamespace,
+ localeSet: LocaleSetNamespace,
+ signature: SignatureNamespace,
+ stylesheet: StylesheetNamespace,
+ template: TemplateNamespace,
+ xdp: XdpNamespace,
+ xhtml: XhtmlNamespace
+};
+
+;// CONCATENATED MODULE: ./src/core/xfa/unknown.js
+
+
+class UnknownNamespace {
+ constructor(nsId) {
+ this.namespaceId = nsId;
+ }
+ [$buildXFAObject](name, attributes) {
+ return new XmlObject(this.namespaceId, name, attributes);
+ }
+}
+
+;// CONCATENATED MODULE: ./src/core/xfa/builder.js
+
+
+
+
+
+
+
+class Root extends XFAObject {
+ constructor(ids) {
+ super(-1, "root", Object.create(null));
+ this.element = null;
+ this[$ids] = ids;
+ }
+ [$onChild](child) {
+ this.element = child;
+ return true;
+ }
+ [$finalize]() {
+ super[$finalize]();
+ if (this.element.template instanceof Template) {
+ this[$ids].set($root, this.element);
+ this.element.template[$resolvePrototypes](this[$ids]);
+ this.element.template[$ids] = this[$ids];
+ }
+ }
+}
+class Empty extends XFAObject {
+ constructor() {
+ super(-1, "", Object.create(null));
+ }
+ [$onChild](_) {
+ return false;
+ }
+}
+class Builder {
+ constructor(rootNameSpace = null) {
+ this._namespaceStack = [];
+ this._nsAgnosticLevel = 0;
+ this._namespacePrefixes = new Map();
+ this._namespaces = new Map();
+ this._nextNsId = Math.max(...Object.values(NamespaceIds).map(({
+ id
+ }) => id));
+ this._currentNamespace = rootNameSpace || new UnknownNamespace(++this._nextNsId);
+ }
+ buildRoot(ids) {
+ return new Root(ids);
+ }
+ build({
+ nsPrefix,
+ name,
+ attributes,
+ namespace,
+ prefixes
+ }) {
+ const hasNamespaceDef = namespace !== null;
+ if (hasNamespaceDef) {
+ this._namespaceStack.push(this._currentNamespace);
+ this._currentNamespace = this._searchNamespace(namespace);
+ }
+ if (prefixes) {
+ this._addNamespacePrefix(prefixes);
+ }
+ if (attributes.hasOwnProperty($nsAttributes)) {
+ const dataTemplate = NamespaceSetUp.datasets;
+ const nsAttrs = attributes[$nsAttributes];
+ let xfaAttrs = null;
+ for (const [ns, attrs] of Object.entries(nsAttrs)) {
+ const nsToUse = this._getNamespaceToUse(ns);
+ if (nsToUse === dataTemplate) {
+ xfaAttrs = {
+ xfa: attrs
+ };
+ break;
+ }
+ }
+ if (xfaAttrs) {
+ attributes[$nsAttributes] = xfaAttrs;
+ } else {
+ delete attributes[$nsAttributes];
+ }
+ }
+ const namespaceToUse = this._getNamespaceToUse(nsPrefix);
+ const node = namespaceToUse?.[$buildXFAObject](name, attributes) || new Empty();
+ if (node[$isNsAgnostic]()) {
+ this._nsAgnosticLevel++;
+ }
+ if (hasNamespaceDef || prefixes || node[$isNsAgnostic]()) {
+ node[$cleanup] = {
+ hasNamespace: hasNamespaceDef,
+ prefixes,
+ nsAgnostic: node[$isNsAgnostic]()
+ };
+ }
+ return node;
+ }
+ isNsAgnostic() {
+ return this._nsAgnosticLevel > 0;
+ }
+ _searchNamespace(nsName) {
+ let ns = this._namespaces.get(nsName);
+ if (ns) {
+ return ns;
+ }
+ for (const [name, {
+ check
+ }] of Object.entries(NamespaceIds)) {
+ if (check(nsName)) {
+ ns = NamespaceSetUp[name];
+ if (ns) {
+ this._namespaces.set(nsName, ns);
+ return ns;
+ }
+ break;
+ }
+ }
+ ns = new UnknownNamespace(++this._nextNsId);
+ this._namespaces.set(nsName, ns);
+ return ns;
+ }
+ _addNamespacePrefix(prefixes) {
+ for (const {
+ prefix,
+ value
+ } of prefixes) {
+ const namespace = this._searchNamespace(value);
+ let prefixStack = this._namespacePrefixes.get(prefix);
+ if (!prefixStack) {
+ prefixStack = [];
+ this._namespacePrefixes.set(prefix, prefixStack);
+ }
+ prefixStack.push(namespace);
+ }
+ }
+ _getNamespaceToUse(prefix) {
+ if (!prefix) {
+ return this._currentNamespace;
+ }
+ const prefixStack = this._namespacePrefixes.get(prefix);
+ if (prefixStack?.length > 0) {
+ return prefixStack.at(-1);
+ }
+ warn(`Unknown namespace prefix: ${prefix}.`);
+ return null;
+ }
+ clean(data) {
+ const {
+ hasNamespace,
+ prefixes,
+ nsAgnostic
+ } = data;
+ if (hasNamespace) {
+ this._currentNamespace = this._namespaceStack.pop();
+ }
+ if (prefixes) {
+ prefixes.forEach(({
+ prefix
+ }) => {
+ this._namespacePrefixes.get(prefix).pop();
+ });
+ }
+ if (nsAgnostic) {
+ this._nsAgnosticLevel--;
+ }
+ }
+}
+
+;// CONCATENATED MODULE: ./src/core/xfa/parser.js
+
+
+
+
+class XFAParser extends XMLParserBase {
+ constructor(rootNameSpace = null, richText = false) {
+ super();
+ this._builder = new Builder(rootNameSpace);
+ this._stack = [];
+ this._globalData = {
+ usedTypefaces: new Set()
+ };
+ this._ids = new Map();
+ this._current = this._builder.buildRoot(this._ids);
+ this._errorCode = XMLParserErrorCode.NoError;
+ this._whiteRegex = /^\s+$/;
+ this._nbsps = /\xa0+/g;
+ this._richText = richText;
+ }
+ parse(data) {
+ this.parseXml(data);
+ if (this._errorCode !== XMLParserErrorCode.NoError) {
+ return undefined;
+ }
+ this._current[$finalize]();
+ return this._current.element;
+ }
+ onText(text) {
+ text = text.replace(this._nbsps, match => match.slice(1) + " ");
+ if (this._richText || this._current[$acceptWhitespace]()) {
+ this._current[$onText](text, this._richText);
+ return;
+ }
+ if (this._whiteRegex.test(text)) {
+ return;
+ }
+ this._current[$onText](text.trim());
+ }
+ onCdata(text) {
+ this._current[$onText](text);
+ }
+ _mkAttributes(attributes, tagName) {
+ let namespace = null;
+ let prefixes = null;
+ const attributeObj = Object.create({});
+ for (const {
+ name,
+ value
+ } of attributes) {
+ if (name === "xmlns") {
+ if (!namespace) {
+ namespace = value;
+ } else {
+ warn(`XFA - multiple namespace definition in <${tagName}>`);
+ }
+ } else if (name.startsWith("xmlns:")) {
+ const prefix = name.substring("xmlns:".length);
+ if (!prefixes) {
+ prefixes = [];
+ }
+ prefixes.push({
+ prefix,
+ value
+ });
+ } else {
+ const i = name.indexOf(":");
+ if (i === -1) {
+ attributeObj[name] = value;
+ } else {
+ let nsAttrs = attributeObj[$nsAttributes];
+ if (!nsAttrs) {
+ nsAttrs = attributeObj[$nsAttributes] = Object.create(null);
+ }
+ const [ns, attrName] = [name.slice(0, i), name.slice(i + 1)];
+ const attrs = nsAttrs[ns] ||= Object.create(null);
+ attrs[attrName] = value;
+ }
+ }
+ }
+ return [namespace, prefixes, attributeObj];
+ }
+ _getNameAndPrefix(name, nsAgnostic) {
+ const i = name.indexOf(":");
+ if (i === -1) {
+ return [name, null];
+ }
+ return [name.substring(i + 1), nsAgnostic ? "" : name.substring(0, i)];
+ }
+ onBeginElement(tagName, attributes, isEmpty) {
+ const [namespace, prefixes, attributesObj] = this._mkAttributes(attributes, tagName);
+ const [name, nsPrefix] = this._getNameAndPrefix(tagName, this._builder.isNsAgnostic());
+ const node = this._builder.build({
+ nsPrefix,
+ name,
+ attributes: attributesObj,
+ namespace,
+ prefixes
+ });
+ node[$globalData] = this._globalData;
+ if (isEmpty) {
+ node[$finalize]();
+ if (this._current[$onChild](node)) {
+ node[$setId](this._ids);
+ }
+ node[$clean](this._builder);
+ return;
+ }
+ this._stack.push(this._current);
+ this._current = node;
+ }
+ onEndElement(name) {
+ const node = this._current;
+ if (node[$isCDATAXml]() && typeof node[$content] === "string") {
+ const parser = new XFAParser();
+ parser._globalData = this._globalData;
+ const root = parser.parse(node[$content]);
+ node[$content] = null;
+ node[$onChild](root);
+ }
+ node[$finalize]();
+ this._current = this._stack.pop();
+ if (this._current[$onChild](node)) {
+ node[$setId](this._ids);
+ }
+ node[$clean](this._builder);
+ }
+ onError(code) {
+ this._errorCode = code;
+ }
+}
+
+;// CONCATENATED MODULE: ./src/core/xfa/factory.js
+
+
+
+
+
+
+
+
+class XFAFactory {
+ constructor(data) {
+ try {
+ this.root = new XFAParser().parse(XFAFactory._createDocument(data));
+ const binder = new Binder(this.root);
+ this.form = binder.bind();
+ this.dataHandler = new DataHandler(this.root, binder.getData());
+ this.form[$globalData].template = this.form;
+ } catch (e) {
+ warn(`XFA - an error occurred during parsing and binding: ${e}`);
+ }
+ }
+ isValid() {
+ return this.root && this.form;
+ }
+ _createPagesHelper() {
+ const iterator = this.form[$toPages]();
+ return new Promise((resolve, reject) => {
+ const nextIteration = () => {
+ try {
+ const value = iterator.next();
+ if (value.done) {
+ resolve(value.value);
+ } else {
+ setTimeout(nextIteration, 0);
+ }
+ } catch (e) {
+ reject(e);
+ }
+ };
+ setTimeout(nextIteration, 0);
+ });
+ }
+ async _createPages() {
+ try {
+ this.pages = await this._createPagesHelper();
+ this.dims = this.pages.children.map(c => {
+ const {
+ width,
+ height
+ } = c.attributes.style;
+ return [0, 0, parseInt(width), parseInt(height)];
+ });
+ } catch (e) {
+ warn(`XFA - an error occurred during layout: ${e}`);
+ }
+ }
+ getBoundingBox(pageIndex) {
+ return this.dims[pageIndex];
+ }
+ async getNumPages() {
+ if (!this.pages) {
+ await this._createPages();
+ }
+ return this.dims.length;
+ }
+ setImages(images) {
+ this.form[$globalData].images = images;
+ }
+ setFonts(fonts) {
+ this.form[$globalData].fontFinder = new FontFinder(fonts);
+ const missingFonts = [];
+ for (let typeface of this.form[$globalData].usedTypefaces) {
+ typeface = stripQuotes(typeface);
+ const font = this.form[$globalData].fontFinder.find(typeface);
+ if (!font) {
+ missingFonts.push(typeface);
+ }
+ }
+ if (missingFonts.length > 0) {
+ return missingFonts;
+ }
+ return null;
+ }
+ appendFonts(fonts, reallyMissingFonts) {
+ this.form[$globalData].fontFinder.add(fonts, reallyMissingFonts);
+ }
+ async getPages() {
+ if (!this.pages) {
+ await this._createPages();
+ }
+ const pages = this.pages;
+ this.pages = null;
+ return pages;
+ }
+ serializeData(storage) {
+ return this.dataHandler.serialize(storage);
+ }
+ static _createDocument(data) {
+ if (!data["/xdp:xdp"]) {
+ return data["xdp:xdp"];
+ }
+ return Object.values(data).join("");
+ }
+ static getRichTextAsHtml(rc) {
+ if (!rc || typeof rc !== "string") {
+ return null;
+ }
+ try {
+ let root = new XFAParser(XhtmlNamespace, true).parse(rc);
+ if (!["body", "xhtml"].includes(root[$nodeName])) {
+ const newRoot = XhtmlNamespace.body({});
+ newRoot[$appendChild](root);
+ root = newRoot;
+ }
+ const result = root[$toHTML]();
+ if (!result.success) {
+ return null;
+ }
+ const {
+ html
+ } = result;
+ const {
+ attributes
+ } = html;
+ if (attributes) {
+ if (attributes.class) {
+ attributes.class = attributes.class.filter(attr => !attr.startsWith("xfa"));
+ }
+ attributes.dir = "auto";
+ }
+ return {
+ html,
+ str: root[$text]()
+ };
+ } catch (e) {
+ warn(`XFA - an error occurred during parsing of rich text: ${e}`);
+ }
+ return null;
+ }
+}
+
+;// CONCATENATED MODULE: ./src/core/annotation.js
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+class AnnotationFactory {
+ static createGlobals(pdfManager) {
+ return Promise.all([pdfManager.ensureCatalog("acroForm"), pdfManager.ensureDoc("xfaDatasets"), pdfManager.ensureCatalog("structTreeRoot"), pdfManager.ensureCatalog("baseUrl"), pdfManager.ensureCatalog("attachments")]).then(([acroForm, xfaDatasets, structTreeRoot, baseUrl, attachments]) => {
+ return {
+ pdfManager,
+ acroForm: acroForm instanceof Dict ? acroForm : Dict.empty,
+ xfaDatasets,
+ structTreeRoot,
+ baseUrl,
+ attachments
+ };
+ }, reason => {
+ warn(`createGlobals: "${reason}".`);
+ return null;
+ });
+ }
+ static async create(xref, ref, annotationGlobals, idFactory, collectFields, pageRef) {
+ const pageIndex = collectFields ? await this._getPageIndex(xref, ref, annotationGlobals.pdfManager) : null;
+ return annotationGlobals.pdfManager.ensure(this, "_create", [xref, ref, annotationGlobals, idFactory, collectFields, pageIndex, pageRef]);
+ }
+ static _create(xref, ref, annotationGlobals, idFactory, collectFields = false, pageIndex = null, pageRef = null) {
+ const dict = xref.fetchIfRef(ref);
+ if (!(dict instanceof Dict)) {
+ return undefined;
+ }
+ const {
+ acroForm,
+ pdfManager
+ } = annotationGlobals;
+ const id = ref instanceof Ref ? ref.toString() : `annot_${idFactory.createObjId()}`;
+ let subtype = dict.get("Subtype");
+ subtype = subtype instanceof Name ? subtype.name : null;
+ const parameters = {
+ xref,
+ ref,
+ dict,
+ subtype,
+ id,
+ annotationGlobals,
+ collectFields,
+ needAppearances: !collectFields && acroForm.get("NeedAppearances") === true,
+ pageIndex,
+ evaluatorOptions: pdfManager.evaluatorOptions,
+ pageRef
+ };
+ switch (subtype) {
+ case "Link":
+ return new LinkAnnotation(parameters);
+ case "Text":
+ return new TextAnnotation(parameters);
+ case "Widget":
+ let fieldType = getInheritableProperty({
+ dict,
+ key: "FT"
+ });
+ fieldType = fieldType instanceof Name ? fieldType.name : null;
+ switch (fieldType) {
+ case "Tx":
+ return new TextWidgetAnnotation(parameters);
+ case "Btn":
+ return new ButtonWidgetAnnotation(parameters);
+ case "Ch":
+ return new ChoiceWidgetAnnotation(parameters);
+ case "Sig":
+ return new SignatureWidgetAnnotation(parameters);
+ }
+ warn(`Unimplemented widget field type "${fieldType}", ` + "falling back to base field type.");
+ return new WidgetAnnotation(parameters);
+ case "Popup":
+ return new PopupAnnotation(parameters);
+ case "FreeText":
+ return new FreeTextAnnotation(parameters);
+ case "Line":
+ return new LineAnnotation(parameters);
+ case "Square":
+ return new SquareAnnotation(parameters);
+ case "Circle":
+ return new CircleAnnotation(parameters);
+ case "PolyLine":
+ return new PolylineAnnotation(parameters);
+ case "Polygon":
+ return new PolygonAnnotation(parameters);
+ case "Caret":
+ return new CaretAnnotation(parameters);
+ case "Ink":
+ return new InkAnnotation(parameters);
+ case "Highlight":
+ return new HighlightAnnotation(parameters);
+ case "Underline":
+ return new UnderlineAnnotation(parameters);
+ case "Squiggly":
+ return new SquigglyAnnotation(parameters);
+ case "StrikeOut":
+ return new StrikeOutAnnotation(parameters);
+ case "Stamp":
+ return new StampAnnotation(parameters);
+ case "FileAttachment":
+ return new FileAttachmentAnnotation(parameters);
+ default:
+ if (!collectFields) {
+ if (!subtype) {
+ warn("Annotation is missing the required /Subtype.");
+ } else {
+ warn(`Unimplemented annotation type "${subtype}", ` + "falling back to base annotation.");
+ }
+ }
+ return new Annotation(parameters);
+ }
+ }
+ static async _getPageIndex(xref, ref, pdfManager) {
+ try {
+ const annotDict = await xref.fetchIfRefAsync(ref);
+ if (!(annotDict instanceof Dict)) {
+ return -1;
+ }
+ const pageRef = annotDict.getRaw("P");
+ if (pageRef instanceof Ref) {
+ try {
+ const pageIndex = await pdfManager.ensureCatalog("getPageIndex", [pageRef]);
+ return pageIndex;
+ } catch (ex) {
+ info(`_getPageIndex -- not a valid page reference: "${ex}".`);
+ }
+ }
+ if (annotDict.has("Kids")) {
+ return -1;
+ }
+ const numPages = await pdfManager.ensureDoc("numPages");
+ for (let pageIndex = 0; pageIndex < numPages; pageIndex++) {
+ const page = await pdfManager.getPage(pageIndex);
+ const annotations = await pdfManager.ensure(page, "annotations");
+ for (const annotRef of annotations) {
+ if (annotRef instanceof Ref && isRefsEqual(annotRef, ref)) {
+ return pageIndex;
+ }
+ }
+ }
+ } catch (ex) {
+ warn(`_getPageIndex: "${ex}".`);
+ }
+ return -1;
+ }
+ static generateImages(annotations, xref, isOffscreenCanvasSupported) {
+ if (!isOffscreenCanvasSupported) {
+ warn("generateImages: OffscreenCanvas is not supported, cannot save or print some annotations with images.");
+ return null;
+ }
+ let imagePromises;
+ for (const {
+ bitmapId,
+ bitmap
+ } of annotations) {
+ if (!bitmap) {
+ continue;
+ }
+ imagePromises ||= new Map();
+ imagePromises.set(bitmapId, StampAnnotation.createImage(bitmap, xref));
+ }
+ return imagePromises;
+ }
+ static async saveNewAnnotations(evaluator, task, annotations, imagePromises) {
+ const xref = evaluator.xref;
+ let baseFontRef;
+ const dependencies = [];
+ const promises = [];
+ const {
+ isOffscreenCanvasSupported
+ } = evaluator.options;
+ for (const annotation of annotations) {
+ if (annotation.deleted) {
+ continue;
+ }
+ switch (annotation.annotationType) {
+ case AnnotationEditorType.FREETEXT:
+ if (!baseFontRef) {
+ const baseFont = new Dict(xref);
+ baseFont.set("BaseFont", Name.get("Helvetica"));
+ baseFont.set("Type", Name.get("Font"));
+ baseFont.set("Subtype", Name.get("Type1"));
+ baseFont.set("Encoding", Name.get("WinAnsiEncoding"));
+ const buffer = [];
+ baseFontRef = xref.getNewTemporaryRef();
+ await writeObject(baseFontRef, baseFont, buffer, xref);
+ dependencies.push({
+ ref: baseFontRef,
+ data: buffer.join("")
+ });
+ }
+ promises.push(FreeTextAnnotation.createNewAnnotation(xref, annotation, dependencies, {
+ evaluator,
+ task,
+ baseFontRef
+ }));
+ break;
+ case AnnotationEditorType.HIGHLIGHT:
+ if (annotation.quadPoints) {
+ promises.push(HighlightAnnotation.createNewAnnotation(xref, annotation, dependencies));
+ } else {
+ promises.push(InkAnnotation.createNewAnnotation(xref, annotation, dependencies));
+ }
+ break;
+ case AnnotationEditorType.INK:
+ promises.push(InkAnnotation.createNewAnnotation(xref, annotation, dependencies));
+ break;
+ case AnnotationEditorType.STAMP:
+ if (!isOffscreenCanvasSupported) {
+ break;
+ }
+ const image = await imagePromises.get(annotation.bitmapId);
+ if (image.imageStream) {
+ const {
+ imageStream,
+ smaskStream
+ } = image;
+ const buffer = [];
+ if (smaskStream) {
+ const smaskRef = xref.getNewTemporaryRef();
+ await writeObject(smaskRef, smaskStream, buffer, xref);
+ dependencies.push({
+ ref: smaskRef,
+ data: buffer.join("")
+ });
+ imageStream.dict.set("SMask", smaskRef);
+ buffer.length = 0;
+ }
+ const imageRef = image.imageRef = xref.getNewTemporaryRef();
+ await writeObject(imageRef, imageStream, buffer, xref);
+ dependencies.push({
+ ref: imageRef,
+ data: buffer.join("")
+ });
+ image.imageStream = image.smaskStream = null;
+ }
+ promises.push(StampAnnotation.createNewAnnotation(xref, annotation, dependencies, {
+ image
+ }));
+ break;
+ }
+ }
+ return {
+ annotations: await Promise.all(promises),
+ dependencies
+ };
+ }
+ static async printNewAnnotations(annotationGlobals, evaluator, task, annotations, imagePromises) {
+ if (!annotations) {
+ return null;
+ }
+ const {
+ options,
+ xref
+ } = evaluator;
+ const promises = [];
+ for (const annotation of annotations) {
+ if (annotation.deleted) {
+ continue;
+ }
+ switch (annotation.annotationType) {
+ case AnnotationEditorType.FREETEXT:
+ promises.push(FreeTextAnnotation.createNewPrintAnnotation(annotationGlobals, xref, annotation, {
+ evaluator,
+ task,
+ evaluatorOptions: options
+ }));
+ break;
+ case AnnotationEditorType.HIGHLIGHT:
+ if (annotation.quadPoints) {
+ promises.push(HighlightAnnotation.createNewPrintAnnotation(annotationGlobals, xref, annotation, {
+ evaluatorOptions: options
+ }));
+ } else {
+ promises.push(InkAnnotation.createNewPrintAnnotation(annotationGlobals, xref, annotation, {
+ evaluatorOptions: options
+ }));
+ }
+ break;
+ case AnnotationEditorType.INK:
+ promises.push(InkAnnotation.createNewPrintAnnotation(annotationGlobals, xref, annotation, {
+ evaluatorOptions: options
+ }));
+ break;
+ case AnnotationEditorType.STAMP:
+ if (!options.isOffscreenCanvasSupported) {
+ break;
+ }
+ const image = await imagePromises.get(annotation.bitmapId);
+ if (image.imageStream) {
+ const {
+ imageStream,
+ smaskStream
+ } = image;
+ if (smaskStream) {
+ imageStream.dict.set("SMask", smaskStream);
+ }
+ image.imageRef = new JpegStream(imageStream, imageStream.length);
+ image.imageStream = image.smaskStream = null;
+ }
+ promises.push(StampAnnotation.createNewPrintAnnotation(annotationGlobals, xref, annotation, {
+ image,
+ evaluatorOptions: options
+ }));
+ break;
+ }
+ }
+ return Promise.all(promises);
+ }
+}
+function getRgbColor(color, defaultColor = new Uint8ClampedArray(3)) {
+ if (!Array.isArray(color)) {
+ return defaultColor;
+ }
+ const rgbColor = defaultColor || new Uint8ClampedArray(3);
+ switch (color.length) {
+ case 0:
+ return null;
+ case 1:
+ ColorSpace.singletons.gray.getRgbItem(color, 0, rgbColor, 0);
+ return rgbColor;
+ case 3:
+ ColorSpace.singletons.rgb.getRgbItem(color, 0, rgbColor, 0);
+ return rgbColor;
+ case 4:
+ ColorSpace.singletons.cmyk.getRgbItem(color, 0, rgbColor, 0);
+ return rgbColor;
+ default:
+ return defaultColor;
+ }
+}
+function getPdfColorArray(color) {
+ return Array.from(color, c => c / 255);
+}
+function getQuadPoints(dict, rect) {
+ const quadPoints = dict.getArray("QuadPoints");
+ if (!Array.isArray(quadPoints) || quadPoints.length === 0 || quadPoints.length % 8 > 0) {
+ return null;
+ }
+ const quadPointsLists = [];
+ for (let i = 0, ii = quadPoints.length / 8; i < ii; i++) {
+ let minX = Infinity,
+ maxX = -Infinity,
+ minY = Infinity,
+ maxY = -Infinity;
+ for (let j = i * 8, jj = i * 8 + 8; j < jj; j += 2) {
+ const x = quadPoints[j];
+ const y = quadPoints[j + 1];
+ minX = Math.min(x, minX);
+ maxX = Math.max(x, maxX);
+ minY = Math.min(y, minY);
+ maxY = Math.max(y, maxY);
+ }
+ if (rect !== null && (minX < rect[0] || maxX > rect[2] || minY < rect[1] || maxY > rect[3])) {
+ return null;
+ }
+ quadPointsLists.push([{
+ x: minX,
+ y: maxY
+ }, {
+ x: maxX,
+ y: maxY
+ }, {
+ x: minX,
+ y: minY
+ }, {
+ x: maxX,
+ y: minY
+ }]);
+ }
+ return quadPointsLists;
+}
+function getTransformMatrix(rect, bbox, matrix) {
+ const [minX, minY, maxX, maxY] = Util.getAxialAlignedBoundingBox(bbox, matrix);
+ if (minX === maxX || minY === maxY) {
+ return [1, 0, 0, 1, rect[0], rect[1]];
+ }
+ const xRatio = (rect[2] - rect[0]) / (maxX - minX);
+ const yRatio = (rect[3] - rect[1]) / (maxY - minY);
+ return [xRatio, 0, 0, yRatio, rect[0] - minX * xRatio, rect[1] - minY * yRatio];
+}
+class Annotation {
+ constructor(params) {
+ const {
+ dict,
+ xref,
+ annotationGlobals
+ } = params;
+ this.setTitle(dict.get("T"));
+ this.setContents(dict.get("Contents"));
+ this.setModificationDate(dict.get("M"));
+ this.setFlags(dict.get("F"));
+ this.setRectangle(dict.getArray("Rect"));
+ this.setColor(dict.getArray("C"));
+ this.setBorderStyle(dict);
+ this.setAppearance(dict);
+ this.setOptionalContent(dict);
+ const MK = dict.get("MK");
+ this.setBorderAndBackgroundColors(MK);
+ this.setRotation(MK, dict);
+ this.ref = params.ref instanceof Ref ? params.ref : null;
+ this._streams = [];
+ if (this.appearance) {
+ this._streams.push(this.appearance);
+ }
+ const isLocked = !!(this.flags & AnnotationFlag.LOCKED);
+ const isContentLocked = !!(this.flags & AnnotationFlag.LOCKEDCONTENTS);
+ if (annotationGlobals.structTreeRoot) {
+ let structParent = dict.get("StructParent");
+ structParent = Number.isInteger(structParent) && structParent >= 0 ? structParent : -1;
+ annotationGlobals.structTreeRoot.addAnnotationIdToPage(params.pageRef, structParent);
+ }
+ this.data = {
+ annotationFlags: this.flags,
+ borderStyle: this.borderStyle,
+ color: this.color,
+ backgroundColor: this.backgroundColor,
+ borderColor: this.borderColor,
+ rotation: this.rotation,
+ contentsObj: this._contents,
+ hasAppearance: !!this.appearance,
+ id: params.id,
+ modificationDate: this.modificationDate,
+ rect: this.rectangle,
+ subtype: params.subtype,
+ hasOwnCanvas: false,
+ noRotate: !!(this.flags & AnnotationFlag.NOROTATE),
+ noHTML: isLocked && isContentLocked
+ };
+ if (params.collectFields) {
+ const kids = dict.get("Kids");
+ if (Array.isArray(kids)) {
+ const kidIds = [];
+ for (const kid of kids) {
+ if (kid instanceof Ref) {
+ kidIds.push(kid.toString());
+ }
+ }
+ if (kidIds.length !== 0) {
+ this.data.kidIds = kidIds;
+ }
+ }
+ this.data.actions = collectActions(xref, dict, AnnotationActionEventType);
+ this.data.fieldName = this._constructFieldName(dict);
+ this.data.pageIndex = params.pageIndex;
+ }
+ this._isOffscreenCanvasSupported = params.evaluatorOptions.isOffscreenCanvasSupported;
+ this._fallbackFontDict = null;
+ this._needAppearances = false;
+ }
+ _hasFlag(flags, flag) {
+ return !!(flags & flag);
+ }
+ _isViewable(flags) {
+ return !this._hasFlag(flags, AnnotationFlag.INVISIBLE) && !this._hasFlag(flags, AnnotationFlag.NOVIEW);
+ }
+ _isPrintable(flags) {
+ return this._hasFlag(flags, AnnotationFlag.PRINT) && !this._hasFlag(flags, AnnotationFlag.HIDDEN) && !this._hasFlag(flags, AnnotationFlag.INVISIBLE);
+ }
+ mustBeViewed(annotationStorage, _renderForms) {
+ const noView = annotationStorage?.get(this.data.id)?.noView;
+ if (noView !== undefined) {
+ return !noView;
+ }
+ return this.viewable && !this._hasFlag(this.flags, AnnotationFlag.HIDDEN);
+ }
+ mustBePrinted(annotationStorage) {
+ const noPrint = annotationStorage?.get(this.data.id)?.noPrint;
+ if (noPrint !== undefined) {
+ return !noPrint;
+ }
+ return this.printable;
+ }
+ get viewable() {
+ if (this.data.quadPoints === null) {
+ return false;
+ }
+ if (this.flags === 0) {
+ return true;
+ }
+ return this._isViewable(this.flags);
+ }
+ get printable() {
+ if (this.data.quadPoints === null) {
+ return false;
+ }
+ if (this.flags === 0) {
+ return false;
+ }
+ return this._isPrintable(this.flags);
+ }
+ _parseStringHelper(data) {
+ const str = typeof data === "string" ? stringToPDFString(data) : "";
+ const dir = str && bidi(str).dir === "rtl" ? "rtl" : "ltr";
+ return {
+ str,
+ dir
+ };
+ }
+ setDefaultAppearance(params) {
+ const {
+ dict,
+ annotationGlobals
+ } = params;
+ const defaultAppearance = getInheritableProperty({
+ dict,
+ key: "DA"
+ }) || annotationGlobals.acroForm.get("DA");
+ this._defaultAppearance = typeof defaultAppearance === "string" ? defaultAppearance : "";
+ this.data.defaultAppearanceData = parseDefaultAppearance(this._defaultAppearance);
+ }
+ setTitle(title) {
+ this._title = this._parseStringHelper(title);
+ }
+ setContents(contents) {
+ this._contents = this._parseStringHelper(contents);
+ }
+ setModificationDate(modificationDate) {
+ this.modificationDate = typeof modificationDate === "string" ? modificationDate : null;
+ }
+ setFlags(flags) {
+ this.flags = Number.isInteger(flags) && flags > 0 ? flags : 0;
+ if (this.flags & AnnotationFlag.INVISIBLE && this.constructor.name !== "Annotation") {
+ this.flags ^= AnnotationFlag.INVISIBLE;
+ }
+ }
+ hasFlag(flag) {
+ return this._hasFlag(this.flags, flag);
+ }
+ setRectangle(rectangle) {
+ this.rectangle = Array.isArray(rectangle) && rectangle.length === 4 ? Util.normalizeRect(rectangle) : [0, 0, 0, 0];
+ }
+ setColor(color) {
+ this.color = getRgbColor(color);
+ }
+ setLineEndings(lineEndings) {
+ throw new Error("Not implemented: setLineEndings");
+ }
+ setRotation(mk, dict) {
+ this.rotation = 0;
+ let angle = mk instanceof Dict ? mk.get("R") || 0 : dict.get("Rotate") || 0;
+ if (Number.isInteger(angle) && angle !== 0) {
+ angle %= 360;
+ if (angle < 0) {
+ angle += 360;
+ }
+ if (angle % 90 === 0) {
+ this.rotation = angle;
+ }
+ }
+ }
+ setBorderAndBackgroundColors(mk) {
+ if (mk instanceof Dict) {
+ this.borderColor = getRgbColor(mk.getArray("BC"), null);
+ this.backgroundColor = getRgbColor(mk.getArray("BG"), null);
+ } else {
+ this.borderColor = this.backgroundColor = null;
+ }
+ }
+ setBorderStyle(borderStyle) {
+ this.borderStyle = new AnnotationBorderStyle();
+ if (!(borderStyle instanceof Dict)) {
+ return;
+ }
+ if (borderStyle.has("BS")) {
+ const dict = borderStyle.get("BS");
+ if (dict instanceof Dict) {
+ const dictType = dict.get("Type");
+ if (!dictType || isName(dictType, "Border")) {
+ this.borderStyle.setWidth(dict.get("W"), this.rectangle);
+ this.borderStyle.setStyle(dict.get("S"));
+ this.borderStyle.setDashArray(dict.getArray("D"));
+ }
+ }
+ } else if (borderStyle.has("Border")) {
+ const array = borderStyle.getArray("Border");
+ if (Array.isArray(array) && array.length >= 3) {
+ this.borderStyle.setHorizontalCornerRadius(array[0]);
+ this.borderStyle.setVerticalCornerRadius(array[1]);
+ this.borderStyle.setWidth(array[2], this.rectangle);
+ if (array.length === 4) {
+ this.borderStyle.setDashArray(array[3], true);
+ }
+ }
+ } else {
+ this.borderStyle.setWidth(0);
+ }
+ }
+ setAppearance(dict) {
+ this.appearance = null;
+ const appearanceStates = dict.get("AP");
+ if (!(appearanceStates instanceof Dict)) {
+ return;
+ }
+ const normalAppearanceState = appearanceStates.get("N");
+ if (normalAppearanceState instanceof BaseStream) {
+ this.appearance = normalAppearanceState;
+ return;
+ }
+ if (!(normalAppearanceState instanceof Dict)) {
+ return;
+ }
+ const as = dict.get("AS");
+ if (!(as instanceof Name) || !normalAppearanceState.has(as.name)) {
+ return;
+ }
+ const appearance = normalAppearanceState.get(as.name);
+ if (appearance instanceof BaseStream) {
+ this.appearance = appearance;
+ }
+ }
+ setOptionalContent(dict) {
+ this.oc = null;
+ const oc = dict.get("OC");
+ if (oc instanceof Name) {
+ warn("setOptionalContent: Support for /Name-entry is not implemented.");
+ } else if (oc instanceof Dict) {
+ this.oc = oc;
+ }
+ }
+ loadResources(keys, appearance) {
+ return appearance.dict.getAsync("Resources").then(resources => {
+ if (!resources) {
+ return undefined;
+ }
+ const objectLoader = new ObjectLoader(resources, keys, resources.xref);
+ return objectLoader.load().then(function () {
+ return resources;
+ });
+ });
+ }
+ async getOperatorList(evaluator, task, intent, renderForms, annotationStorage) {
+ const data = this.data;
+ let appearance = this.appearance;
+ const isUsingOwnCanvas = !!(this.data.hasOwnCanvas && intent & RenderingIntentFlag.DISPLAY);
+ if (!appearance) {
+ if (!isUsingOwnCanvas) {
+ return {
+ opList: new OperatorList(),
+ separateForm: false,
+ separateCanvas: false
+ };
+ }
+ appearance = new StringStream("");
+ appearance.dict = new Dict();
+ }
+ const appearanceDict = appearance.dict;
+ const resources = await this.loadResources(["ExtGState", "ColorSpace", "Pattern", "Shading", "XObject", "Font"], appearance);
+ const bbox = appearanceDict.getArray("BBox") || [0, 0, 1, 1];
+ const matrix = appearanceDict.getArray("Matrix") || [1, 0, 0, 1, 0, 0];
+ const transform = getTransformMatrix(data.rect, bbox, matrix);
+ const opList = new OperatorList();
+ let optionalContent;
+ if (this.oc) {
+ optionalContent = await evaluator.parseMarkedContentProps(this.oc, null);
+ }
+ if (optionalContent !== undefined) {
+ opList.addOp(OPS.beginMarkedContentProps, ["OC", optionalContent]);
+ }
+ opList.addOp(OPS.beginAnnotation, [data.id, data.rect, transform, matrix, isUsingOwnCanvas]);
+ await evaluator.getOperatorList({
+ stream: appearance,
+ task,
+ resources,
+ operatorList: opList,
+ fallbackFontDict: this._fallbackFontDict
+ });
+ opList.addOp(OPS.endAnnotation, []);
+ if (optionalContent !== undefined) {
+ opList.addOp(OPS.endMarkedContent, []);
+ }
+ this.reset();
+ return {
+ opList,
+ separateForm: false,
+ separateCanvas: isUsingOwnCanvas
+ };
+ }
+ async save(evaluator, task, annotationStorage) {
+ return null;
+ }
+ get hasTextContent() {
+ return false;
+ }
+ async extractTextContent(evaluator, task, viewBox) {
+ if (!this.appearance) {
+ return;
+ }
+ const resources = await this.loadResources(["ExtGState", "Font", "Properties", "XObject"], this.appearance);
+ const text = [];
+ const buffer = [];
+ let firstPosition = null;
+ const sink = {
+ desiredSize: Math.Infinity,
+ ready: true,
+ enqueue(chunk, size) {
+ for (const item of chunk.items) {
+ if (item.str === undefined) {
+ continue;
+ }
+ firstPosition ||= item.transform.slice(-2);
+ buffer.push(item.str);
+ if (item.hasEOL) {
+ text.push(buffer.join("").trimEnd());
+ buffer.length = 0;
+ }
+ }
+ }
+ };
+ await evaluator.getTextContent({
+ stream: this.appearance,
+ task,
+ resources,
+ includeMarkedContent: true,
+ keepWhiteSpace: true,
+ sink,
+ viewBox
+ });
+ this.reset();
+ if (buffer.length) {
+ text.push(buffer.join("").trimEnd());
+ }
+ if (text.length > 1 || text[0]) {
+ const appearanceDict = this.appearance.dict;
+ this.data.textPosition = this._transformPoint(firstPosition, appearanceDict.getArray("BBox"), appearanceDict.getArray("Matrix"));
+ this.data.textContent = text;
+ }
+ }
+ _transformPoint(coords, bbox, matrix) {
+ const {
+ rect
+ } = this.data;
+ bbox ||= [0, 0, 1, 1];
+ matrix ||= [1, 0, 0, 1, 0, 0];
+ const transform = getTransformMatrix(rect, bbox, matrix);
+ transform[4] -= rect[0];
+ transform[5] -= rect[1];
+ coords = Util.applyTransform(coords, transform);
+ return Util.applyTransform(coords, matrix);
+ }
+ getFieldObject() {
+ if (this.data.kidIds) {
+ return {
+ id: this.data.id,
+ actions: this.data.actions,
+ name: this.data.fieldName,
+ strokeColor: this.data.borderColor,
+ fillColor: this.data.backgroundColor,
+ type: "",
+ kidIds: this.data.kidIds,
+ page: this.data.pageIndex,
+ rotation: this.rotation
+ };
+ }
+ return null;
+ }
+ reset() {
+ for (const stream of this._streams) {
+ stream.reset();
+ }
+ }
+ _constructFieldName(dict) {
+ if (!dict.has("T") && !dict.has("Parent")) {
+ warn("Unknown field name, falling back to empty field name.");
+ return "";
+ }
+ if (!dict.has("Parent")) {
+ return stringToPDFString(dict.get("T"));
+ }
+ const fieldName = [];
+ if (dict.has("T")) {
+ fieldName.unshift(stringToPDFString(dict.get("T")));
+ }
+ let loopDict = dict;
+ const visited = new RefSet();
+ if (dict.objId) {
+ visited.put(dict.objId);
+ }
+ while (loopDict.has("Parent")) {
+ loopDict = loopDict.get("Parent");
+ if (!(loopDict instanceof Dict) || loopDict.objId && visited.has(loopDict.objId)) {
+ break;
+ }
+ if (loopDict.objId) {
+ visited.put(loopDict.objId);
+ }
+ if (loopDict.has("T")) {
+ fieldName.unshift(stringToPDFString(loopDict.get("T")));
+ }
+ }
+ return fieldName.join(".");
+ }
+}
+class AnnotationBorderStyle {
+ constructor() {
+ this.width = 1;
+ this.style = AnnotationBorderStyleType.SOLID;
+ this.dashArray = [3];
+ this.horizontalCornerRadius = 0;
+ this.verticalCornerRadius = 0;
+ }
+ setWidth(width, rect = [0, 0, 0, 0]) {
+ if (width instanceof Name) {
+ this.width = 0;
+ return;
+ }
+ if (typeof width === "number") {
+ if (width > 0) {
+ const maxWidth = (rect[2] - rect[0]) / 2;
+ const maxHeight = (rect[3] - rect[1]) / 2;
+ if (maxWidth > 0 && maxHeight > 0 && (width > maxWidth || width > maxHeight)) {
+ warn(`AnnotationBorderStyle.setWidth - ignoring width: ${width}`);
+ width = 1;
+ }
+ }
+ this.width = width;
+ }
+ }
+ setStyle(style) {
+ if (!(style instanceof Name)) {
+ return;
+ }
+ switch (style.name) {
+ case "S":
+ this.style = AnnotationBorderStyleType.SOLID;
+ break;
+ case "D":
+ this.style = AnnotationBorderStyleType.DASHED;
+ break;
+ case "B":
+ this.style = AnnotationBorderStyleType.BEVELED;
+ break;
+ case "I":
+ this.style = AnnotationBorderStyleType.INSET;
+ break;
+ case "U":
+ this.style = AnnotationBorderStyleType.UNDERLINE;
+ break;
+ default:
+ break;
+ }
+ }
+ setDashArray(dashArray, forceStyle = false) {
+ if (Array.isArray(dashArray) && dashArray.length > 0) {
+ let isValid = true;
+ let allZeros = true;
+ for (const element of dashArray) {
+ const validNumber = +element >= 0;
+ if (!validNumber) {
+ isValid = false;
+ break;
+ } else if (element > 0) {
+ allZeros = false;
+ }
+ }
+ if (isValid && !allZeros) {
+ this.dashArray = dashArray;
+ if (forceStyle) {
+ this.setStyle(Name.get("D"));
+ }
+ } else {
+ this.width = 0;
+ }
+ } else if (dashArray) {
+ this.width = 0;
+ }
+ }
+ setHorizontalCornerRadius(radius) {
+ if (Number.isInteger(radius)) {
+ this.horizontalCornerRadius = radius;
+ }
+ }
+ setVerticalCornerRadius(radius) {
+ if (Number.isInteger(radius)) {
+ this.verticalCornerRadius = radius;
+ }
+ }
+}
+class MarkupAnnotation extends Annotation {
+ constructor(params) {
+ super(params);
+ const {
+ dict
+ } = params;
+ if (dict.has("IRT")) {
+ const rawIRT = dict.getRaw("IRT");
+ this.data.inReplyTo = rawIRT instanceof Ref ? rawIRT.toString() : null;
+ const rt = dict.get("RT");
+ this.data.replyType = rt instanceof Name ? rt.name : AnnotationReplyType.REPLY;
+ }
+ let popupRef = null;
+ if (this.data.replyType === AnnotationReplyType.GROUP) {
+ const parent = dict.get("IRT");
+ this.setTitle(parent.get("T"));
+ this.data.titleObj = this._title;
+ this.setContents(parent.get("Contents"));
+ this.data.contentsObj = this._contents;
+ if (!parent.has("CreationDate")) {
+ this.data.creationDate = null;
+ } else {
+ this.setCreationDate(parent.get("CreationDate"));
+ this.data.creationDate = this.creationDate;
+ }
+ if (!parent.has("M")) {
+ this.data.modificationDate = null;
+ } else {
+ this.setModificationDate(parent.get("M"));
+ this.data.modificationDate = this.modificationDate;
+ }
+ popupRef = parent.getRaw("Popup");
+ if (!parent.has("C")) {
+ this.data.color = null;
+ } else {
+ this.setColor(parent.getArray("C"));
+ this.data.color = this.color;
+ }
+ } else {
+ this.data.titleObj = this._title;
+ this.setCreationDate(dict.get("CreationDate"));
+ this.data.creationDate = this.creationDate;
+ popupRef = dict.getRaw("Popup");
+ if (!dict.has("C")) {
+ this.data.color = null;
+ }
+ }
+ this.data.popupRef = popupRef instanceof Ref ? popupRef.toString() : null;
+ if (dict.has("RC")) {
+ this.data.richText = XFAFactory.getRichTextAsHtml(dict.get("RC"));
+ }
+ }
+ setCreationDate(creationDate) {
+ this.creationDate = typeof creationDate === "string" ? creationDate : null;
+ }
+ _setDefaultAppearance({
+ xref,
+ extra,
+ strokeColor,
+ fillColor,
+ blendMode,
+ strokeAlpha,
+ fillAlpha,
+ pointsCallback
+ }) {
+ let minX = Number.MAX_VALUE;
+ let minY = Number.MAX_VALUE;
+ let maxX = Number.MIN_VALUE;
+ let maxY = Number.MIN_VALUE;
+ const buffer = ["q"];
+ if (extra) {
+ buffer.push(extra);
+ }
+ if (strokeColor) {
+ buffer.push(`${strokeColor[0]} ${strokeColor[1]} ${strokeColor[2]} RG`);
+ }
+ if (fillColor) {
+ buffer.push(`${fillColor[0]} ${fillColor[1]} ${fillColor[2]} rg`);
+ }
+ let pointsArray = this.data.quadPoints;
+ if (!pointsArray) {
+ pointsArray = [[{
+ x: this.rectangle[0],
+ y: this.rectangle[3]
+ }, {
+ x: this.rectangle[2],
+ y: this.rectangle[3]
+ }, {
+ x: this.rectangle[0],
+ y: this.rectangle[1]
+ }, {
+ x: this.rectangle[2],
+ y: this.rectangle[1]
+ }]];
+ }
+ for (const points of pointsArray) {
+ const [mX, MX, mY, MY] = pointsCallback(buffer, points);
+ minX = Math.min(minX, mX);
+ maxX = Math.max(maxX, MX);
+ minY = Math.min(minY, mY);
+ maxY = Math.max(maxY, MY);
+ }
+ buffer.push("Q");
+ const formDict = new Dict(xref);
+ const appearanceStreamDict = new Dict(xref);
+ appearanceStreamDict.set("Subtype", Name.get("Form"));
+ const appearanceStream = new StringStream(buffer.join(" "));
+ appearanceStream.dict = appearanceStreamDict;
+ formDict.set("Fm0", appearanceStream);
+ const gsDict = new Dict(xref);
+ if (blendMode) {
+ gsDict.set("BM", Name.get(blendMode));
+ }
+ if (typeof strokeAlpha === "number") {
+ gsDict.set("CA", strokeAlpha);
+ }
+ if (typeof fillAlpha === "number") {
+ gsDict.set("ca", fillAlpha);
+ }
+ const stateDict = new Dict(xref);
+ stateDict.set("GS0", gsDict);
+ const resources = new Dict(xref);
+ resources.set("ExtGState", stateDict);
+ resources.set("XObject", formDict);
+ const appearanceDict = new Dict(xref);
+ appearanceDict.set("Resources", resources);
+ const bbox = this.data.rect = [minX, minY, maxX, maxY];
+ appearanceDict.set("BBox", bbox);
+ this.appearance = new StringStream("/GS0 gs /Fm0 Do");
+ this.appearance.dict = appearanceDict;
+ this._streams.push(this.appearance, appearanceStream);
+ }
+ static async createNewAnnotation(xref, annotation, dependencies, params) {
+ const annotationRef = annotation.ref ||= xref.getNewTemporaryRef();
+ const ap = await this.createNewAppearanceStream(annotation, xref, params);
+ const buffer = [];
+ let annotationDict;
+ if (ap) {
+ const apRef = xref.getNewTemporaryRef();
+ annotationDict = this.createNewDict(annotation, xref, {
+ apRef
+ });
+ await writeObject(apRef, ap, buffer, xref);
+ dependencies.push({
+ ref: apRef,
+ data: buffer.join("")
+ });
+ } else {
+ annotationDict = this.createNewDict(annotation, xref, {});
+ }
+ if (Number.isInteger(annotation.parentTreeId)) {
+ annotationDict.set("StructParent", annotation.parentTreeId);
+ }
+ buffer.length = 0;
+ await writeObject(annotationRef, annotationDict, buffer, xref);
+ return {
+ ref: annotationRef,
+ data: buffer.join("")
+ };
+ }
+ static async createNewPrintAnnotation(annotationGlobals, xref, annotation, params) {
+ const ap = await this.createNewAppearanceStream(annotation, xref, params);
+ const annotationDict = this.createNewDict(annotation, xref, {
+ ap
+ });
+ const newAnnotation = new this.prototype.constructor({
+ dict: annotationDict,
+ xref,
+ annotationGlobals,
+ evaluatorOptions: params.evaluatorOptions
+ });
+ if (annotation.ref) {
+ newAnnotation.ref = newAnnotation.refToReplace = annotation.ref;
+ }
+ return newAnnotation;
+ }
+}
+class WidgetAnnotation extends Annotation {
+ constructor(params) {
+ super(params);
+ const {
+ dict,
+ xref,
+ annotationGlobals
+ } = params;
+ const data = this.data;
+ this._needAppearances = params.needAppearances;
+ data.annotationType = AnnotationType.WIDGET;
+ if (data.fieldName === undefined) {
+ data.fieldName = this._constructFieldName(dict);
+ }
+ if (data.actions === undefined) {
+ data.actions = collectActions(xref, dict, AnnotationActionEventType);
+ }
+ let fieldValue = getInheritableProperty({
+ dict,
+ key: "V",
+ getArray: true
+ });
+ data.fieldValue = this._decodeFormValue(fieldValue);
+ const defaultFieldValue = getInheritableProperty({
+ dict,
+ key: "DV",
+ getArray: true
+ });
+ data.defaultFieldValue = this._decodeFormValue(defaultFieldValue);
+ if (fieldValue === undefined && annotationGlobals.xfaDatasets) {
+ const path = this._title.str;
+ if (path) {
+ this._hasValueFromXFA = true;
+ data.fieldValue = fieldValue = annotationGlobals.xfaDatasets.getValue(path);
+ }
+ }
+ if (fieldValue === undefined && data.defaultFieldValue !== null) {
+ data.fieldValue = data.defaultFieldValue;
+ }
+ data.alternativeText = stringToPDFString(dict.get("TU") || "");
+ this.setDefaultAppearance(params);
+ data.hasAppearance ||= this._needAppearances && data.fieldValue !== undefined && data.fieldValue !== null;
+ const fieldType = getInheritableProperty({
+ dict,
+ key: "FT"
+ });
+ data.fieldType = fieldType instanceof Name ? fieldType.name : null;
+ const localResources = getInheritableProperty({
+ dict,
+ key: "DR"
+ });
+ const acroFormResources = annotationGlobals.acroForm.get("DR");
+ const appearanceResources = this.appearance?.dict.get("Resources");
+ this._fieldResources = {
+ localResources,
+ acroFormResources,
+ appearanceResources,
+ mergedResources: Dict.merge({
+ xref,
+ dictArray: [localResources, appearanceResources, acroFormResources],
+ mergeSubDicts: true
+ })
+ };
+ data.fieldFlags = getInheritableProperty({
+ dict,
+ key: "Ff"
+ });
+ if (!Number.isInteger(data.fieldFlags) || data.fieldFlags < 0) {
+ data.fieldFlags = 0;
+ }
+ data.readOnly = this.hasFieldFlag(AnnotationFieldFlag.READONLY);
+ data.required = this.hasFieldFlag(AnnotationFieldFlag.REQUIRED);
+ data.hidden = this._hasFlag(data.annotationFlags, AnnotationFlag.HIDDEN) || this._hasFlag(data.annotationFlags, AnnotationFlag.NOVIEW);
+ }
+ _decodeFormValue(formValue) {
+ if (Array.isArray(formValue)) {
+ return formValue.filter(item => typeof item === "string").map(item => stringToPDFString(item));
+ } else if (formValue instanceof Name) {
+ return stringToPDFString(formValue.name);
+ } else if (typeof formValue === "string") {
+ return stringToPDFString(formValue);
+ }
+ return null;
+ }
+ hasFieldFlag(flag) {
+ return !!(this.data.fieldFlags & flag);
+ }
+ _isViewable(flags) {
+ return true;
+ }
+ mustBeViewed(annotationStorage, renderForms) {
+ if (renderForms) {
+ return this.viewable;
+ }
+ return super.mustBeViewed(annotationStorage, renderForms) && !this._hasFlag(this.flags, AnnotationFlag.NOVIEW);
+ }
+ getRotationMatrix(annotationStorage) {
+ let rotation = annotationStorage?.get(this.data.id)?.rotation;
+ if (rotation === undefined) {
+ rotation = this.rotation;
+ }
+ if (rotation === 0) {
+ return IDENTITY_MATRIX;
+ }
+ const width = this.data.rect[2] - this.data.rect[0];
+ const height = this.data.rect[3] - this.data.rect[1];
+ return getRotationMatrix(rotation, width, height);
+ }
+ getBorderAndBackgroundAppearances(annotationStorage) {
+ let rotation = annotationStorage?.get(this.data.id)?.rotation;
+ if (rotation === undefined) {
+ rotation = this.rotation;
+ }
+ if (!this.backgroundColor && !this.borderColor) {
+ return "";
+ }
+ const width = this.data.rect[2] - this.data.rect[0];
+ const height = this.data.rect[3] - this.data.rect[1];
+ const rect = rotation === 0 || rotation === 180 ? `0 0 ${width} ${height} re` : `0 0 ${height} ${width} re`;
+ let str = "";
+ if (this.backgroundColor) {
+ str = `${getPdfColor(this.backgroundColor, true)} ${rect} f `;
+ }
+ if (this.borderColor) {
+ const borderWidth = this.borderStyle.width || 1;
+ str += `${borderWidth} w ${getPdfColor(this.borderColor, false)} ${rect} S `;
+ }
+ return str;
+ }
+ async getOperatorList(evaluator, task, intent, renderForms, annotationStorage) {
+ if (renderForms && !(this instanceof SignatureWidgetAnnotation) && !this.data.noHTML && !this.data.hasOwnCanvas) {
+ return {
+ opList: new OperatorList(),
+ separateForm: true,
+ separateCanvas: false
+ };
+ }
+ if (!this._hasText) {
+ return super.getOperatorList(evaluator, task, intent, renderForms, annotationStorage);
+ }
+ const content = await this._getAppearance(evaluator, task, intent, annotationStorage);
+ if (this.appearance && content === null) {
+ return super.getOperatorList(evaluator, task, intent, renderForms, annotationStorage);
+ }
+ const opList = new OperatorList();
+ if (!this._defaultAppearance || content === null) {
+ return {
+ opList,
+ separateForm: false,
+ separateCanvas: false
+ };
+ }
+ const isUsingOwnCanvas = !!(this.data.hasOwnCanvas && intent & RenderingIntentFlag.DISPLAY);
+ const matrix = [1, 0, 0, 1, 0, 0];
+ const bbox = [0, 0, this.data.rect[2] - this.data.rect[0], this.data.rect[3] - this.data.rect[1]];
+ const transform = getTransformMatrix(this.data.rect, bbox, matrix);
+ let optionalContent;
+ if (this.oc) {
+ optionalContent = await evaluator.parseMarkedContentProps(this.oc, null);
+ }
+ if (optionalContent !== undefined) {
+ opList.addOp(OPS.beginMarkedContentProps, ["OC", optionalContent]);
+ }
+ opList.addOp(OPS.beginAnnotation, [this.data.id, this.data.rect, transform, this.getRotationMatrix(annotationStorage), isUsingOwnCanvas]);
+ const stream = new StringStream(content);
+ await evaluator.getOperatorList({
+ stream,
+ task,
+ resources: this._fieldResources.mergedResources,
+ operatorList: opList
+ });
+ opList.addOp(OPS.endAnnotation, []);
+ if (optionalContent !== undefined) {
+ opList.addOp(OPS.endMarkedContent, []);
+ }
+ return {
+ opList,
+ separateForm: false,
+ separateCanvas: isUsingOwnCanvas
+ };
+ }
+ _getMKDict(rotation) {
+ const mk = new Dict(null);
+ if (rotation) {
+ mk.set("R", rotation);
+ }
+ if (this.borderColor) {
+ mk.set("BC", getPdfColorArray(this.borderColor));
+ }
+ if (this.backgroundColor) {
+ mk.set("BG", getPdfColorArray(this.backgroundColor));
+ }
+ return mk.size > 0 ? mk : null;
+ }
+ amendSavedDict(annotationStorage, dict) {}
+ async save(evaluator, task, annotationStorage) {
+ const storageEntry = annotationStorage?.get(this.data.id);
+ let value = storageEntry?.value,
+ rotation = storageEntry?.rotation;
+ if (value === this.data.fieldValue || value === undefined) {
+ if (!this._hasValueFromXFA && rotation === undefined) {
+ return null;
+ }
+ value ||= this.data.fieldValue;
+ }
+ if (rotation === undefined && !this._hasValueFromXFA && Array.isArray(value) && Array.isArray(this.data.fieldValue) && value.length === this.data.fieldValue.length && value.every((x, i) => x === this.data.fieldValue[i])) {
+ return null;
+ }
+ if (rotation === undefined) {
+ rotation = this.rotation;
+ }
+ let appearance = null;
+ if (!this._needAppearances) {
+ appearance = await this._getAppearance(evaluator, task, RenderingIntentFlag.SAVE, annotationStorage);
+ if (appearance === null) {
+ return null;
+ }
+ } else {}
+ let needAppearances = false;
+ if (appearance?.needAppearances) {
+ needAppearances = true;
+ appearance = null;
+ }
+ const {
+ xref
+ } = evaluator;
+ const originalDict = xref.fetchIfRef(this.ref);
+ if (!(originalDict instanceof Dict)) {
+ return null;
+ }
+ const dict = new Dict(xref);
+ for (const key of originalDict.getKeys()) {
+ if (key !== "AP") {
+ dict.set(key, originalDict.getRaw(key));
+ }
+ }
+ const xfa = {
+ path: this.data.fieldName,
+ value
+ };
+ const encoder = val => isAscii(val) ? val : stringToUTF16String(val, true);
+ dict.set("V", Array.isArray(value) ? value.map(encoder) : encoder(value));
+ this.amendSavedDict(annotationStorage, dict);
+ const maybeMK = this._getMKDict(rotation);
+ if (maybeMK) {
+ dict.set("MK", maybeMK);
+ }
+ const buffer = [];
+ const changes = [{
+ ref: this.ref,
+ data: "",
+ xfa,
+ needAppearances
+ }];
+ if (appearance !== null) {
+ const newRef = xref.getNewTemporaryRef();
+ const AP = new Dict(xref);
+ dict.set("AP", AP);
+ AP.set("N", newRef);
+ const resources = this._getSaveFieldResources(xref);
+ const appearanceStream = new StringStream(appearance);
+ const appearanceDict = appearanceStream.dict = new Dict(xref);
+ appearanceDict.set("Subtype", Name.get("Form"));
+ appearanceDict.set("Resources", resources);
+ appearanceDict.set("BBox", [0, 0, this.data.rect[2] - this.data.rect[0], this.data.rect[3] - this.data.rect[1]]);
+ const rotationMatrix = this.getRotationMatrix(annotationStorage);
+ if (rotationMatrix !== IDENTITY_MATRIX) {
+ appearanceDict.set("Matrix", rotationMatrix);
+ }
+ await writeObject(newRef, appearanceStream, buffer, xref);
+ changes.push({
+ ref: newRef,
+ data: buffer.join(""),
+ xfa: null,
+ needAppearances: false
+ });
+ buffer.length = 0;
+ }
+ dict.set("M", `D:${getModificationDate()}`);
+ await writeObject(this.ref, dict, buffer, xref);
+ changes[0].data = buffer.join("");
+ return changes;
+ }
+ async _getAppearance(evaluator, task, intent, annotationStorage) {
+ const isPassword = this.hasFieldFlag(AnnotationFieldFlag.PASSWORD);
+ if (isPassword) {
+ return null;
+ }
+ const storageEntry = annotationStorage?.get(this.data.id);
+ let value, rotation;
+ if (storageEntry) {
+ value = storageEntry.formattedValue || storageEntry.value;
+ rotation = storageEntry.rotation;
+ }
+ if (rotation === undefined && value === undefined && !this._needAppearances) {
+ if (!this._hasValueFromXFA || this.appearance) {
+ return null;
+ }
+ }
+ const colors = this.getBorderAndBackgroundAppearances(annotationStorage);
+ if (value === undefined) {
+ value = this.data.fieldValue;
+ if (!value) {
+ return `/Tx BMC q ${colors}Q EMC`;
+ }
+ }
+ if (Array.isArray(value) && value.length === 1) {
+ value = value[0];
+ }
+ assert(typeof value === "string", "Expected `value` to be a string.");
+ value = value.trim();
+ if (this.data.combo) {
+ const option = this.data.options.find(({
+ exportValue
+ }) => value === exportValue);
+ value = option?.displayValue || value;
+ }
+ if (value === "") {
+ return `/Tx BMC q ${colors}Q EMC`;
+ }
+ if (rotation === undefined) {
+ rotation = this.rotation;
+ }
+ let lineCount = -1;
+ let lines;
+ if (this.data.multiLine) {
+ lines = value.split(/\r\n?|\n/).map(line => line.normalize("NFC"));
+ lineCount = lines.length;
+ } else {
+ lines = [value.replace(/\r\n?|\n/, "").normalize("NFC")];
+ }
+ const defaultPadding = 1;
+ const defaultHPadding = 2;
+ let totalHeight = this.data.rect[3] - this.data.rect[1];
+ let totalWidth = this.data.rect[2] - this.data.rect[0];
+ if (rotation === 90 || rotation === 270) {
+ [totalWidth, totalHeight] = [totalHeight, totalWidth];
+ }
+ if (!this._defaultAppearance) {
+ this.data.defaultAppearanceData = parseDefaultAppearance(this._defaultAppearance = "/Helvetica 0 Tf 0 g");
+ }
+ let font = await WidgetAnnotation._getFontData(evaluator, task, this.data.defaultAppearanceData, this._fieldResources.mergedResources);
+ let defaultAppearance, fontSize, lineHeight;
+ const encodedLines = [];
+ let encodingError = false;
+ for (const line of lines) {
+ const encodedString = font.encodeString(line);
+ if (encodedString.length > 1) {
+ encodingError = true;
+ }
+ encodedLines.push(encodedString.join(""));
+ }
+ if (encodingError && intent & RenderingIntentFlag.SAVE) {
+ return {
+ needAppearances: true
+ };
+ }
+ if (encodingError && this._isOffscreenCanvasSupported) {
+ const fontFamily = this.data.comb ? "monospace" : "sans-serif";
+ const fakeUnicodeFont = new FakeUnicodeFont(evaluator.xref, fontFamily);
+ const resources = fakeUnicodeFont.createFontResources(lines.join(""));
+ const newFont = resources.getRaw("Font");
+ if (this._fieldResources.mergedResources.has("Font")) {
+ const oldFont = this._fieldResources.mergedResources.get("Font");
+ for (const key of newFont.getKeys()) {
+ oldFont.set(key, newFont.getRaw(key));
+ }
+ } else {
+ this._fieldResources.mergedResources.set("Font", newFont);
+ }
+ const fontName = fakeUnicodeFont.fontName.name;
+ font = await WidgetAnnotation._getFontData(evaluator, task, {
+ fontName,
+ fontSize: 0
+ }, resources);
+ for (let i = 0, ii = encodedLines.length; i < ii; i++) {
+ encodedLines[i] = stringToUTF16String(lines[i]);
+ }
+ const savedDefaultAppearance = Object.assign(Object.create(null), this.data.defaultAppearanceData);
+ this.data.defaultAppearanceData.fontSize = 0;
+ this.data.defaultAppearanceData.fontName = fontName;
+ [defaultAppearance, fontSize, lineHeight] = this._computeFontSize(totalHeight - 2 * defaultPadding, totalWidth - 2 * defaultHPadding, value, font, lineCount);
+ this.data.defaultAppearanceData = savedDefaultAppearance;
+ } else {
+ if (!this._isOffscreenCanvasSupported) {
+ warn("_getAppearance: OffscreenCanvas is not supported, annotation may not render correctly.");
+ }
+ [defaultAppearance, fontSize, lineHeight] = this._computeFontSize(totalHeight - 2 * defaultPadding, totalWidth - 2 * defaultHPadding, value, font, lineCount);
+ }
+ let descent = font.descent;
+ if (isNaN(descent)) {
+ descent = BASELINE_FACTOR * lineHeight;
+ } else {
+ descent = Math.max(BASELINE_FACTOR * lineHeight, Math.abs(descent) * fontSize);
+ }
+ const defaultVPadding = Math.min(Math.floor((totalHeight - fontSize) / 2), defaultPadding);
+ const alignment = this.data.textAlignment;
+ if (this.data.multiLine) {
+ return this._getMultilineAppearance(defaultAppearance, encodedLines, font, fontSize, totalWidth, totalHeight, alignment, defaultHPadding, defaultVPadding, descent, lineHeight, annotationStorage);
+ }
+ if (this.data.comb) {
+ return this._getCombAppearance(defaultAppearance, font, encodedLines[0], fontSize, totalWidth, totalHeight, defaultHPadding, defaultVPadding, descent, lineHeight, annotationStorage);
+ }
+ const bottomPadding = defaultVPadding + descent;
+ if (alignment === 0 || alignment > 2) {
+ return `/Tx BMC q ${colors}BT ` + defaultAppearance + ` 1 0 0 1 ${numberToString(defaultHPadding)} ${numberToString(bottomPadding)} Tm (${escapeString(encodedLines[0])}) Tj` + " ET Q EMC";
+ }
+ const prevInfo = {
+ shift: 0
+ };
+ const renderedText = this._renderText(encodedLines[0], font, fontSize, totalWidth, alignment, prevInfo, defaultHPadding, bottomPadding);
+ return `/Tx BMC q ${colors}BT ` + defaultAppearance + ` 1 0 0 1 0 0 Tm ${renderedText}` + " ET Q EMC";
+ }
+ static async _getFontData(evaluator, task, appearanceData, resources) {
+ const operatorList = new OperatorList();
+ const initialState = {
+ font: null,
+ clone() {
+ return this;
+ }
+ };
+ const {
+ fontName,
+ fontSize
+ } = appearanceData;
+ await evaluator.handleSetFont(resources, [fontName && Name.get(fontName), fontSize], null, operatorList, task, initialState, null);
+ return initialState.font;
+ }
+ _getTextWidth(text, font) {
+ return font.charsToGlyphs(text).reduce((width, glyph) => width + glyph.width, 0) / 1000;
+ }
+ _computeFontSize(height, width, text, font, lineCount) {
+ let {
+ fontSize
+ } = this.data.defaultAppearanceData;
+ let lineHeight = (fontSize || 12) * LINE_FACTOR,
+ numberOfLines = Math.round(height / lineHeight);
+ if (!fontSize) {
+ const roundWithTwoDigits = x => Math.floor(x * 100) / 100;
+ if (lineCount === -1) {
+ const textWidth = this._getTextWidth(text, font);
+ fontSize = roundWithTwoDigits(Math.min(height / LINE_FACTOR, textWidth > width ? width / textWidth : Infinity));
+ numberOfLines = 1;
+ } else {
+ const lines = text.split(/\r\n?|\n/);
+ const cachedLines = [];
+ for (const line of lines) {
+ const encoded = font.encodeString(line).join("");
+ const glyphs = font.charsToGlyphs(encoded);
+ const positions = font.getCharPositions(encoded);
+ cachedLines.push({
+ line: encoded,
+ glyphs,
+ positions
+ });
+ }
+ const isTooBig = fsize => {
+ let totalHeight = 0;
+ for (const cache of cachedLines) {
+ const chunks = this._splitLine(null, font, fsize, width, cache);
+ totalHeight += chunks.length * fsize;
+ if (totalHeight > height) {
+ return true;
+ }
+ }
+ return false;
+ };
+ numberOfLines = Math.max(numberOfLines, lineCount);
+ while (true) {
+ lineHeight = height / numberOfLines;
+ fontSize = roundWithTwoDigits(lineHeight / LINE_FACTOR);
+ if (isTooBig(fontSize)) {
+ numberOfLines++;
+ continue;
+ }
+ break;
+ }
+ }
+ const {
+ fontName,
+ fontColor
+ } = this.data.defaultAppearanceData;
+ this._defaultAppearance = createDefaultAppearance({
+ fontSize,
+ fontName,
+ fontColor
+ });
+ }
+ return [this._defaultAppearance, fontSize, height / numberOfLines];
+ }
+ _renderText(text, font, fontSize, totalWidth, alignment, prevInfo, hPadding, vPadding) {
+ let shift;
+ if (alignment === 1) {
+ const width = this._getTextWidth(text, font) * fontSize;
+ shift = (totalWidth - width) / 2;
+ } else if (alignment === 2) {
+ const width = this._getTextWidth(text, font) * fontSize;
+ shift = totalWidth - width - hPadding;
+ } else {
+ shift = hPadding;
+ }
+ const shiftStr = numberToString(shift - prevInfo.shift);
+ prevInfo.shift = shift;
+ vPadding = numberToString(vPadding);
+ return `${shiftStr} ${vPadding} Td (${escapeString(text)}) Tj`;
+ }
+ _getSaveFieldResources(xref) {
+ const {
+ localResources,
+ appearanceResources,
+ acroFormResources
+ } = this._fieldResources;
+ const fontName = this.data.defaultAppearanceData?.fontName;
+ if (!fontName) {
+ return localResources || Dict.empty;
+ }
+ for (const resources of [localResources, appearanceResources]) {
+ if (resources instanceof Dict) {
+ const localFont = resources.get("Font");
+ if (localFont instanceof Dict && localFont.has(fontName)) {
+ return resources;
+ }
+ }
+ }
+ if (acroFormResources instanceof Dict) {
+ const acroFormFont = acroFormResources.get("Font");
+ if (acroFormFont instanceof Dict && acroFormFont.has(fontName)) {
+ const subFontDict = new Dict(xref);
+ subFontDict.set(fontName, acroFormFont.getRaw(fontName));
+ const subResourcesDict = new Dict(xref);
+ subResourcesDict.set("Font", subFontDict);
+ return Dict.merge({
+ xref,
+ dictArray: [subResourcesDict, localResources],
+ mergeSubDicts: true
+ });
+ }
+ }
+ return localResources || Dict.empty;
+ }
+ getFieldObject() {
+ return null;
+ }
+}
+class TextWidgetAnnotation extends WidgetAnnotation {
+ constructor(params) {
+ super(params);
+ this.data.hasOwnCanvas = this.data.readOnly && !this.data.noHTML;
+ this._hasText = true;
+ const dict = params.dict;
+ if (typeof this.data.fieldValue !== "string") {
+ this.data.fieldValue = "";
+ }
+ let alignment = getInheritableProperty({
+ dict,
+ key: "Q"
+ });
+ if (!Number.isInteger(alignment) || alignment < 0 || alignment > 2) {
+ alignment = null;
+ }
+ this.data.textAlignment = alignment;
+ let maximumLength = getInheritableProperty({
+ dict,
+ key: "MaxLen"
+ });
+ if (!Number.isInteger(maximumLength) || maximumLength < 0) {
+ maximumLength = 0;
+ }
+ this.data.maxLen = maximumLength;
+ this.data.multiLine = this.hasFieldFlag(AnnotationFieldFlag.MULTILINE);
+ this.data.comb = this.hasFieldFlag(AnnotationFieldFlag.COMB) && !this.hasFieldFlag(AnnotationFieldFlag.MULTILINE) && !this.hasFieldFlag(AnnotationFieldFlag.PASSWORD) && !this.hasFieldFlag(AnnotationFieldFlag.FILESELECT) && this.data.maxLen !== 0;
+ this.data.doNotScroll = this.hasFieldFlag(AnnotationFieldFlag.DONOTSCROLL);
+ }
+ get hasTextContent() {
+ return !!this.appearance && !this._needAppearances;
+ }
+ _getCombAppearance(defaultAppearance, font, text, fontSize, width, height, hPadding, vPadding, descent, lineHeight, annotationStorage) {
+ const combWidth = width / this.data.maxLen;
+ const colors = this.getBorderAndBackgroundAppearances(annotationStorage);
+ const buf = [];
+ const positions = font.getCharPositions(text);
+ for (const [start, end] of positions) {
+ buf.push(`(${escapeString(text.substring(start, end))}) Tj`);
+ }
+ const renderedComb = buf.join(` ${numberToString(combWidth)} 0 Td `);
+ return `/Tx BMC q ${colors}BT ` + defaultAppearance + ` 1 0 0 1 ${numberToString(hPadding)} ${numberToString(vPadding + descent)} Tm ${renderedComb}` + " ET Q EMC";
+ }
+ _getMultilineAppearance(defaultAppearance, lines, font, fontSize, width, height, alignment, hPadding, vPadding, descent, lineHeight, annotationStorage) {
+ const buf = [];
+ const totalWidth = width - 2 * hPadding;
+ const prevInfo = {
+ shift: 0
+ };
+ for (let i = 0, ii = lines.length; i < ii; i++) {
+ const line = lines[i];
+ const chunks = this._splitLine(line, font, fontSize, totalWidth);
+ for (let j = 0, jj = chunks.length; j < jj; j++) {
+ const chunk = chunks[j];
+ const vShift = i === 0 && j === 0 ? -vPadding - (lineHeight - descent) : -lineHeight;
+ buf.push(this._renderText(chunk, font, fontSize, width, alignment, prevInfo, hPadding, vShift));
+ }
+ }
+ const colors = this.getBorderAndBackgroundAppearances(annotationStorage);
+ const renderedText = buf.join("\n");
+ return `/Tx BMC q ${colors}BT ` + defaultAppearance + ` 1 0 0 1 0 ${numberToString(height)} Tm ${renderedText}` + " ET Q EMC";
+ }
+ _splitLine(line, font, fontSize, width, cache = {}) {
+ line = cache.line || line;
+ const glyphs = cache.glyphs || font.charsToGlyphs(line);
+ if (glyphs.length <= 1) {
+ return [line];
+ }
+ const positions = cache.positions || font.getCharPositions(line);
+ const scale = fontSize / 1000;
+ const chunks = [];
+ let lastSpacePosInStringStart = -1,
+ lastSpacePosInStringEnd = -1,
+ lastSpacePos = -1,
+ startChunk = 0,
+ currentWidth = 0;
+ for (let i = 0, ii = glyphs.length; i < ii; i++) {
+ const [start, end] = positions[i];
+ const glyph = glyphs[i];
+ const glyphWidth = glyph.width * scale;
+ if (glyph.unicode === " ") {
+ if (currentWidth + glyphWidth > width) {
+ chunks.push(line.substring(startChunk, start));
+ startChunk = start;
+ currentWidth = glyphWidth;
+ lastSpacePosInStringStart = -1;
+ lastSpacePos = -1;
+ } else {
+ currentWidth += glyphWidth;
+ lastSpacePosInStringStart = start;
+ lastSpacePosInStringEnd = end;
+ lastSpacePos = i;
+ }
+ } else if (currentWidth + glyphWidth > width) {
+ if (lastSpacePosInStringStart !== -1) {
+ chunks.push(line.substring(startChunk, lastSpacePosInStringEnd));
+ startChunk = lastSpacePosInStringEnd;
+ i = lastSpacePos + 1;
+ lastSpacePosInStringStart = -1;
+ currentWidth = 0;
+ } else {
+ chunks.push(line.substring(startChunk, start));
+ startChunk = start;
+ currentWidth = glyphWidth;
+ }
+ } else {
+ currentWidth += glyphWidth;
+ }
+ }
+ if (startChunk < line.length) {
+ chunks.push(line.substring(startChunk, line.length));
+ }
+ return chunks;
+ }
+ getFieldObject() {
+ return {
+ id: this.data.id,
+ value: this.data.fieldValue,
+ defaultValue: this.data.defaultFieldValue || "",
+ multiline: this.data.multiLine,
+ password: this.hasFieldFlag(AnnotationFieldFlag.PASSWORD),
+ charLimit: this.data.maxLen,
+ comb: this.data.comb,
+ editable: !this.data.readOnly,
+ hidden: this.data.hidden,
+ name: this.data.fieldName,
+ rect: this.data.rect,
+ actions: this.data.actions,
+ page: this.data.pageIndex,
+ strokeColor: this.data.borderColor,
+ fillColor: this.data.backgroundColor,
+ rotation: this.rotation,
+ type: "text"
+ };
+ }
+}
+class ButtonWidgetAnnotation extends WidgetAnnotation {
+ constructor(params) {
+ super(params);
+ this.checkedAppearance = null;
+ this.uncheckedAppearance = null;
+ this.data.checkBox = !this.hasFieldFlag(AnnotationFieldFlag.RADIO) && !this.hasFieldFlag(AnnotationFieldFlag.PUSHBUTTON);
+ this.data.radioButton = this.hasFieldFlag(AnnotationFieldFlag.RADIO) && !this.hasFieldFlag(AnnotationFieldFlag.PUSHBUTTON);
+ this.data.pushButton = this.hasFieldFlag(AnnotationFieldFlag.PUSHBUTTON);
+ this.data.isTooltipOnly = false;
+ if (this.data.checkBox) {
+ this._processCheckBox(params);
+ } else if (this.data.radioButton) {
+ this._processRadioButton(params);
+ } else if (this.data.pushButton) {
+ this.data.hasOwnCanvas = true;
+ this.data.noHTML = false;
+ this._processPushButton(params);
+ } else {
+ warn("Invalid field flags for button widget annotation");
+ }
+ }
+ async getOperatorList(evaluator, task, intent, renderForms, annotationStorage) {
+ if (this.data.pushButton) {
+ return super.getOperatorList(evaluator, task, intent, false, annotationStorage);
+ }
+ let value = null;
+ let rotation = null;
+ if (annotationStorage) {
+ const storageEntry = annotationStorage.get(this.data.id);
+ value = storageEntry ? storageEntry.value : null;
+ rotation = storageEntry ? storageEntry.rotation : null;
+ }
+ if (value === null && this.appearance) {
+ return super.getOperatorList(evaluator, task, intent, renderForms, annotationStorage);
+ }
+ if (value === null || value === undefined) {
+ value = this.data.checkBox ? this.data.fieldValue === this.data.exportValue : this.data.fieldValue === this.data.buttonValue;
+ }
+ const appearance = value ? this.checkedAppearance : this.uncheckedAppearance;
+ if (appearance) {
+ const savedAppearance = this.appearance;
+ const savedMatrix = appearance.dict.getArray("Matrix") || IDENTITY_MATRIX;
+ if (rotation) {
+ appearance.dict.set("Matrix", this.getRotationMatrix(annotationStorage));
+ }
+ this.appearance = appearance;
+ const operatorList = super.getOperatorList(evaluator, task, intent, renderForms, annotationStorage);
+ this.appearance = savedAppearance;
+ appearance.dict.set("Matrix", savedMatrix);
+ return operatorList;
+ }
+ return {
+ opList: new OperatorList(),
+ separateForm: false,
+ separateCanvas: false
+ };
+ }
+ async save(evaluator, task, annotationStorage) {
+ if (this.data.checkBox) {
+ return this._saveCheckbox(evaluator, task, annotationStorage);
+ }
+ if (this.data.radioButton) {
+ return this._saveRadioButton(evaluator, task, annotationStorage);
+ }
+ return null;
+ }
+ async _saveCheckbox(evaluator, task, annotationStorage) {
+ if (!annotationStorage) {
+ return null;
+ }
+ const storageEntry = annotationStorage.get(this.data.id);
+ let rotation = storageEntry?.rotation,
+ value = storageEntry?.value;
+ if (rotation === undefined) {
+ if (value === undefined) {
+ return null;
+ }
+ const defaultValue = this.data.fieldValue === this.data.exportValue;
+ if (defaultValue === value) {
+ return null;
+ }
+ }
+ const dict = evaluator.xref.fetchIfRef(this.ref);
+ if (!(dict instanceof Dict)) {
+ return null;
+ }
+ if (rotation === undefined) {
+ rotation = this.rotation;
+ }
+ if (value === undefined) {
+ value = this.data.fieldValue === this.data.exportValue;
+ }
+ const xfa = {
+ path: this.data.fieldName,
+ value: value ? this.data.exportValue : ""
+ };
+ const name = Name.get(value ? this.data.exportValue : "Off");
+ dict.set("V", name);
+ dict.set("AS", name);
+ dict.set("M", `D:${getModificationDate()}`);
+ const maybeMK = this._getMKDict(rotation);
+ if (maybeMK) {
+ dict.set("MK", maybeMK);
+ }
+ const buffer = [];
+ await writeObject(this.ref, dict, buffer, evaluator.xref);
+ return [{
+ ref: this.ref,
+ data: buffer.join(""),
+ xfa
+ }];
+ }
+ async _saveRadioButton(evaluator, task, annotationStorage) {
+ if (!annotationStorage) {
+ return null;
+ }
+ const storageEntry = annotationStorage.get(this.data.id);
+ let rotation = storageEntry?.rotation,
+ value = storageEntry?.value;
+ if (rotation === undefined) {
+ if (value === undefined) {
+ return null;
+ }
+ const defaultValue = this.data.fieldValue === this.data.buttonValue;
+ if (defaultValue === value) {
+ return null;
+ }
+ }
+ const dict = evaluator.xref.fetchIfRef(this.ref);
+ if (!(dict instanceof Dict)) {
+ return null;
+ }
+ if (value === undefined) {
+ value = this.data.fieldValue === this.data.buttonValue;
+ }
+ if (rotation === undefined) {
+ rotation = this.rotation;
+ }
+ const xfa = {
+ path: this.data.fieldName,
+ value: value ? this.data.buttonValue : ""
+ };
+ const name = Name.get(value ? this.data.buttonValue : "Off");
+ const buffer = [];
+ let parentData = null;
+ if (value) {
+ if (this.parent instanceof Ref) {
+ const parent = evaluator.xref.fetch(this.parent);
+ parent.set("V", name);
+ await writeObject(this.parent, parent, buffer, evaluator.xref);
+ parentData = buffer.join("");
+ buffer.length = 0;
+ } else if (this.parent instanceof Dict) {
+ this.parent.set("V", name);
+ }
+ }
+ dict.set("AS", name);
+ dict.set("M", `D:${getModificationDate()}`);
+ const maybeMK = this._getMKDict(rotation);
+ if (maybeMK) {
+ dict.set("MK", maybeMK);
+ }
+ await writeObject(this.ref, dict, buffer, evaluator.xref);
+ const newRefs = [{
+ ref: this.ref,
+ data: buffer.join(""),
+ xfa
+ }];
+ if (parentData) {
+ newRefs.push({
+ ref: this.parent,
+ data: parentData,
+ xfa: null
+ });
+ }
+ return newRefs;
+ }
+ _getDefaultCheckedAppearance(params, type) {
+ const width = this.data.rect[2] - this.data.rect[0];
+ const height = this.data.rect[3] - this.data.rect[1];
+ const bbox = [0, 0, width, height];
+ const FONT_RATIO = 0.8;
+ const fontSize = Math.min(width, height) * FONT_RATIO;
+ let metrics, char;
+ if (type === "check") {
+ metrics = {
+ width: 0.755 * fontSize,
+ height: 0.705 * fontSize
+ };
+ char = "\x33";
+ } else if (type === "disc") {
+ metrics = {
+ width: 0.791 * fontSize,
+ height: 0.705 * fontSize
+ };
+ char = "\x6C";
+ } else {
+ unreachable(`_getDefaultCheckedAppearance - unsupported type: ${type}`);
+ }
+ const xShift = numberToString((width - metrics.width) / 2);
+ const yShift = numberToString((height - metrics.height) / 2);
+ const appearance = `q BT /PdfJsZaDb ${fontSize} Tf 0 g ${xShift} ${yShift} Td (${char}) Tj ET Q`;
+ const appearanceStreamDict = new Dict(params.xref);
+ appearanceStreamDict.set("FormType", 1);
+ appearanceStreamDict.set("Subtype", Name.get("Form"));
+ appearanceStreamDict.set("Type", Name.get("XObject"));
+ appearanceStreamDict.set("BBox", bbox);
+ appearanceStreamDict.set("Matrix", [1, 0, 0, 1, 0, 0]);
+ appearanceStreamDict.set("Length", appearance.length);
+ const resources = new Dict(params.xref);
+ const font = new Dict(params.xref);
+ font.set("PdfJsZaDb", this.fallbackFontDict);
+ resources.set("Font", font);
+ appearanceStreamDict.set("Resources", resources);
+ this.checkedAppearance = new StringStream(appearance);
+ this.checkedAppearance.dict = appearanceStreamDict;
+ this._streams.push(this.checkedAppearance);
+ }
+ _processCheckBox(params) {
+ const customAppearance = params.dict.get("AP");
+ if (!(customAppearance instanceof Dict)) {
+ return;
+ }
+ const normalAppearance = customAppearance.get("N");
+ if (!(normalAppearance instanceof Dict)) {
+ return;
+ }
+ const asValue = this._decodeFormValue(params.dict.get("AS"));
+ if (typeof asValue === "string") {
+ this.data.fieldValue = asValue;
+ }
+ const yes = this.data.fieldValue !== null && this.data.fieldValue !== "Off" ? this.data.fieldValue : "Yes";
+ const exportValues = normalAppearance.getKeys();
+ if (exportValues.length === 0) {
+ exportValues.push("Off", yes);
+ } else if (exportValues.length === 1) {
+ if (exportValues[0] === "Off") {
+ exportValues.push(yes);
+ } else {
+ exportValues.unshift("Off");
+ }
+ } else if (exportValues.includes(yes)) {
+ exportValues.length = 0;
+ exportValues.push("Off", yes);
+ } else {
+ const otherYes = exportValues.find(v => v !== "Off");
+ exportValues.length = 0;
+ exportValues.push("Off", otherYes);
+ }
+ if (!exportValues.includes(this.data.fieldValue)) {
+ this.data.fieldValue = "Off";
+ }
+ this.data.exportValue = exportValues[1];
+ const checkedAppearance = normalAppearance.get(this.data.exportValue);
+ this.checkedAppearance = checkedAppearance instanceof BaseStream ? checkedAppearance : null;
+ const uncheckedAppearance = normalAppearance.get("Off");
+ this.uncheckedAppearance = uncheckedAppearance instanceof BaseStream ? uncheckedAppearance : null;
+ if (this.checkedAppearance) {
+ this._streams.push(this.checkedAppearance);
+ } else {
+ this._getDefaultCheckedAppearance(params, "check");
+ }
+ if (this.uncheckedAppearance) {
+ this._streams.push(this.uncheckedAppearance);
+ }
+ this._fallbackFontDict = this.fallbackFontDict;
+ if (this.data.defaultFieldValue === null) {
+ this.data.defaultFieldValue = "Off";
+ }
+ }
+ _processRadioButton(params) {
+ this.data.buttonValue = null;
+ const fieldParent = params.dict.get("Parent");
+ if (fieldParent instanceof Dict) {
+ this.parent = params.dict.getRaw("Parent");
+ const fieldParentValue = fieldParent.get("V");
+ if (fieldParentValue instanceof Name) {
+ this.data.fieldValue = this._decodeFormValue(fieldParentValue);
+ }
+ }
+ const appearanceStates = params.dict.get("AP");
+ if (!(appearanceStates instanceof Dict)) {
+ return;
+ }
+ const normalAppearance = appearanceStates.get("N");
+ if (!(normalAppearance instanceof Dict)) {
+ return;
+ }
+ for (const key of normalAppearance.getKeys()) {
+ if (key !== "Off") {
+ this.data.buttonValue = this._decodeFormValue(key);
+ break;
+ }
+ }
+ const checkedAppearance = normalAppearance.get(this.data.buttonValue);
+ this.checkedAppearance = checkedAppearance instanceof BaseStream ? checkedAppearance : null;
+ const uncheckedAppearance = normalAppearance.get("Off");
+ this.uncheckedAppearance = uncheckedAppearance instanceof BaseStream ? uncheckedAppearance : null;
+ if (this.checkedAppearance) {
+ this._streams.push(this.checkedAppearance);
+ } else {
+ this._getDefaultCheckedAppearance(params, "disc");
+ }
+ if (this.uncheckedAppearance) {
+ this._streams.push(this.uncheckedAppearance);
+ }
+ this._fallbackFontDict = this.fallbackFontDict;
+ if (this.data.defaultFieldValue === null) {
+ this.data.defaultFieldValue = "Off";
+ }
+ }
+ _processPushButton(params) {
+ const {
+ dict,
+ annotationGlobals
+ } = params;
+ if (!dict.has("A") && !dict.has("AA") && !this.data.alternativeText) {
+ warn("Push buttons without action dictionaries are not supported");
+ return;
+ }
+ this.data.isTooltipOnly = !dict.has("A") && !dict.has("AA");
+ Catalog.parseDestDictionary({
+ destDict: dict,
+ resultObj: this.data,
+ docBaseUrl: annotationGlobals.baseUrl,
+ docAttachments: annotationGlobals.attachments
+ });
+ }
+ getFieldObject() {
+ let type = "button";
+ let exportValues;
+ if (this.data.checkBox) {
+ type = "checkbox";
+ exportValues = this.data.exportValue;
+ } else if (this.data.radioButton) {
+ type = "radiobutton";
+ exportValues = this.data.buttonValue;
+ }
+ return {
+ id: this.data.id,
+ value: this.data.fieldValue || "Off",
+ defaultValue: this.data.defaultFieldValue,
+ exportValues,
+ editable: !this.data.readOnly,
+ name: this.data.fieldName,
+ rect: this.data.rect,
+ hidden: this.data.hidden,
+ actions: this.data.actions,
+ page: this.data.pageIndex,
+ strokeColor: this.data.borderColor,
+ fillColor: this.data.backgroundColor,
+ rotation: this.rotation,
+ type
+ };
+ }
+ get fallbackFontDict() {
+ const dict = new Dict();
+ dict.set("BaseFont", Name.get("ZapfDingbats"));
+ dict.set("Type", Name.get("FallbackType"));
+ dict.set("Subtype", Name.get("FallbackType"));
+ dict.set("Encoding", Name.get("ZapfDingbatsEncoding"));
+ return shadow(this, "fallbackFontDict", dict);
+ }
+}
+class ChoiceWidgetAnnotation extends WidgetAnnotation {
+ constructor(params) {
+ super(params);
+ const {
+ dict,
+ xref
+ } = params;
+ this.indices = dict.getArray("I");
+ this.hasIndices = Array.isArray(this.indices) && this.indices.length > 0;
+ this.data.options = [];
+ const options = getInheritableProperty({
+ dict,
+ key: "Opt"
+ });
+ if (Array.isArray(options)) {
+ for (let i = 0, ii = options.length; i < ii; i++) {
+ const option = xref.fetchIfRef(options[i]);
+ const isOptionArray = Array.isArray(option);
+ this.data.options[i] = {
+ exportValue: this._decodeFormValue(isOptionArray ? xref.fetchIfRef(option[0]) : option),
+ displayValue: this._decodeFormValue(isOptionArray ? xref.fetchIfRef(option[1]) : option)
+ };
+ }
+ }
+ if (!this.hasIndices) {
+ if (typeof this.data.fieldValue === "string") {
+ this.data.fieldValue = [this.data.fieldValue];
+ } else if (!this.data.fieldValue) {
+ this.data.fieldValue = [];
+ }
+ } else {
+ this.data.fieldValue = [];
+ const ii = this.data.options.length;
+ for (const i of this.indices) {
+ if (Number.isInteger(i) && i >= 0 && i < ii) {
+ this.data.fieldValue.push(this.data.options[i].exportValue);
+ }
+ }
+ }
+ this.data.combo = this.hasFieldFlag(AnnotationFieldFlag.COMBO);
+ this.data.multiSelect = this.hasFieldFlag(AnnotationFieldFlag.MULTISELECT);
+ this._hasText = true;
+ }
+ getFieldObject() {
+ const type = this.data.combo ? "combobox" : "listbox";
+ const value = this.data.fieldValue.length > 0 ? this.data.fieldValue[0] : null;
+ return {
+ id: this.data.id,
+ value,
+ defaultValue: this.data.defaultFieldValue,
+ editable: !this.data.readOnly,
+ name: this.data.fieldName,
+ rect: this.data.rect,
+ numItems: this.data.fieldValue.length,
+ multipleSelection: this.data.multiSelect,
+ hidden: this.data.hidden,
+ actions: this.data.actions,
+ items: this.data.options,
+ page: this.data.pageIndex,
+ strokeColor: this.data.borderColor,
+ fillColor: this.data.backgroundColor,
+ rotation: this.rotation,
+ type
+ };
+ }
+ amendSavedDict(annotationStorage, dict) {
+ if (!this.hasIndices) {
+ return;
+ }
+ let values = annotationStorage?.get(this.data.id)?.value;
+ if (!Array.isArray(values)) {
+ values = [values];
+ }
+ const indices = [];
+ const {
+ options
+ } = this.data;
+ for (let i = 0, j = 0, ii = options.length; i < ii; i++) {
+ if (options[i].exportValue === values[j]) {
+ indices.push(i);
+ j += 1;
+ }
+ }
+ dict.set("I", indices);
+ }
+ async _getAppearance(evaluator, task, intent, annotationStorage) {
+ if (this.data.combo) {
+ return super._getAppearance(evaluator, task, intent, annotationStorage);
+ }
+ let exportedValue, rotation;
+ const storageEntry = annotationStorage?.get(this.data.id);
+ if (storageEntry) {
+ rotation = storageEntry.rotation;
+ exportedValue = storageEntry.value;
+ }
+ if (rotation === undefined && exportedValue === undefined && !this._needAppearances) {
+ return null;
+ }
+ if (exportedValue === undefined) {
+ exportedValue = this.data.fieldValue;
+ } else if (!Array.isArray(exportedValue)) {
+ exportedValue = [exportedValue];
+ }
+ const defaultPadding = 1;
+ const defaultHPadding = 2;
+ let totalHeight = this.data.rect[3] - this.data.rect[1];
+ let totalWidth = this.data.rect[2] - this.data.rect[0];
+ if (rotation === 90 || rotation === 270) {
+ [totalWidth, totalHeight] = [totalHeight, totalWidth];
+ }
+ const lineCount = this.data.options.length;
+ const valueIndices = [];
+ for (let i = 0; i < lineCount; i++) {
+ const {
+ exportValue
+ } = this.data.options[i];
+ if (exportedValue.includes(exportValue)) {
+ valueIndices.push(i);
+ }
+ }
+ if (!this._defaultAppearance) {
+ this.data.defaultAppearanceData = parseDefaultAppearance(this._defaultAppearance = "/Helvetica 0 Tf 0 g");
+ }
+ const font = await WidgetAnnotation._getFontData(evaluator, task, this.data.defaultAppearanceData, this._fieldResources.mergedResources);
+ let defaultAppearance;
+ let {
+ fontSize
+ } = this.data.defaultAppearanceData;
+ if (!fontSize) {
+ const lineHeight = (totalHeight - defaultPadding) / lineCount;
+ let lineWidth = -1;
+ let value;
+ for (const {
+ displayValue
+ } of this.data.options) {
+ const width = this._getTextWidth(displayValue, font);
+ if (width > lineWidth) {
+ lineWidth = width;
+ value = displayValue;
+ }
+ }
+ [defaultAppearance, fontSize] = this._computeFontSize(lineHeight, totalWidth - 2 * defaultHPadding, value, font, -1);
+ } else {
+ defaultAppearance = this._defaultAppearance;
+ }
+ const lineHeight = fontSize * LINE_FACTOR;
+ const vPadding = (lineHeight - fontSize) / 2;
+ const numberOfVisibleLines = Math.floor(totalHeight / lineHeight);
+ let firstIndex = 0;
+ if (valueIndices.length > 0) {
+ const minIndex = Math.min(...valueIndices);
+ const maxIndex = Math.max(...valueIndices);
+ firstIndex = Math.max(0, maxIndex - numberOfVisibleLines + 1);
+ if (firstIndex > minIndex) {
+ firstIndex = minIndex;
+ }
+ }
+ const end = Math.min(firstIndex + numberOfVisibleLines + 1, lineCount);
+ const buf = ["/Tx BMC q", `1 1 ${totalWidth} ${totalHeight} re W n`];
+ if (valueIndices.length) {
+ buf.push("0.600006 0.756866 0.854904 rg");
+ for (const index of valueIndices) {
+ if (firstIndex <= index && index < end) {
+ buf.push(`1 ${totalHeight - (index - firstIndex + 1) * lineHeight} ${totalWidth} ${lineHeight} re f`);
+ }
+ }
+ }
+ buf.push("BT", defaultAppearance, `1 0 0 1 0 ${totalHeight} Tm`);
+ const prevInfo = {
+ shift: 0
+ };
+ for (let i = firstIndex; i < end; i++) {
+ const {
+ displayValue
+ } = this.data.options[i];
+ const vpadding = i === firstIndex ? vPadding : 0;
+ buf.push(this._renderText(displayValue, font, fontSize, totalWidth, 0, prevInfo, defaultHPadding, -lineHeight + vpadding));
+ }
+ buf.push("ET Q EMC");
+ return buf.join("\n");
+ }
+}
+class SignatureWidgetAnnotation extends WidgetAnnotation {
+ constructor(params) {
+ super(params);
+ this.data.fieldValue = null;
+ this.data.hasOwnCanvas = this.data.noRotate;
+ this.data.noHTML = !this.data.hasOwnCanvas;
+ }
+ getFieldObject() {
+ return {
+ id: this.data.id,
+ value: null,
+ page: this.data.pageIndex,
+ type: "signature"
+ };
+ }
+}
+class TextAnnotation extends MarkupAnnotation {
+ constructor(params) {
+ const DEFAULT_ICON_SIZE = 22;
+ super(params);
+ this.data.noRotate = true;
+ this.data.hasOwnCanvas = this.data.noRotate;
+ this.data.noHTML = false;
+ const {
+ dict
+ } = params;
+ this.data.annotationType = AnnotationType.TEXT;
+ if (this.data.hasAppearance) {
+ this.data.name = "NoIcon";
+ } else {
+ this.data.rect[1] = this.data.rect[3] - DEFAULT_ICON_SIZE;
+ this.data.rect[2] = this.data.rect[0] + DEFAULT_ICON_SIZE;
+ this.data.name = dict.has("Name") ? dict.get("Name").name : "Note";
+ }
+ if (dict.has("State")) {
+ this.data.state = dict.get("State") || null;
+ this.data.stateModel = dict.get("StateModel") || null;
+ } else {
+ this.data.state = null;
+ this.data.stateModel = null;
+ }
+ }
+}
+class LinkAnnotation extends Annotation {
+ constructor(params) {
+ super(params);
+ const {
+ dict,
+ annotationGlobals
+ } = params;
+ this.data.annotationType = AnnotationType.LINK;
+ this.data.noHTML = false;
+ const quadPoints = getQuadPoints(dict, this.rectangle);
+ if (quadPoints) {
+ this.data.quadPoints = quadPoints;
+ }
+ this.data.borderColor ||= this.data.color;
+ Catalog.parseDestDictionary({
+ destDict: dict,
+ resultObj: this.data,
+ docBaseUrl: annotationGlobals.baseUrl,
+ docAttachments: annotationGlobals.attachments
+ });
+ }
+}
+class PopupAnnotation extends Annotation {
+ constructor(params) {
+ super(params);
+ const {
+ dict
+ } = params;
+ this.data.annotationType = AnnotationType.POPUP;
+ this.data.noHTML = false;
+ if (this.data.rect[0] === this.data.rect[2] || this.data.rect[1] === this.data.rect[3]) {
+ this.data.rect = null;
+ }
+ let parentItem = dict.get("Parent");
+ if (!parentItem) {
+ warn("Popup annotation has a missing or invalid parent annotation.");
+ return;
+ }
+ const parentRect = parentItem.getArray("Rect");
+ this.data.parentRect = Array.isArray(parentRect) && parentRect.length === 4 ? Util.normalizeRect(parentRect) : null;
+ const rt = parentItem.get("RT");
+ if (isName(rt, AnnotationReplyType.GROUP)) {
+ parentItem = parentItem.get("IRT");
+ }
+ if (!parentItem.has("M")) {
+ this.data.modificationDate = null;
+ } else {
+ this.setModificationDate(parentItem.get("M"));
+ this.data.modificationDate = this.modificationDate;
+ }
+ if (!parentItem.has("C")) {
+ this.data.color = null;
+ } else {
+ this.setColor(parentItem.getArray("C"));
+ this.data.color = this.color;
+ }
+ if (!this.viewable) {
+ const parentFlags = parentItem.get("F");
+ if (this._isViewable(parentFlags)) {
+ this.setFlags(parentFlags);
+ }
+ }
+ this.setTitle(parentItem.get("T"));
+ this.data.titleObj = this._title;
+ this.setContents(parentItem.get("Contents"));
+ this.data.contentsObj = this._contents;
+ if (parentItem.has("RC")) {
+ this.data.richText = XFAFactory.getRichTextAsHtml(parentItem.get("RC"));
+ }
+ this.data.open = !!dict.get("Open");
+ }
+}
+class FreeTextAnnotation extends MarkupAnnotation {
+ constructor(params) {
+ super(params);
+ this.data.hasOwnCanvas = !this.data.noHTML;
+ this.data.noHTML = false;
+ const {
+ evaluatorOptions,
+ xref
+ } = params;
+ this.data.annotationType = AnnotationType.FREETEXT;
+ this.setDefaultAppearance(params);
+ this._hasAppearance = !!this.appearance;
+ if (this._hasAppearance) {
+ const {
+ fontColor,
+ fontSize
+ } = parseAppearanceStream(this.appearance, evaluatorOptions, xref);
+ this.data.defaultAppearanceData.fontColor = fontColor;
+ this.data.defaultAppearanceData.fontSize = fontSize || 10;
+ } else {
+ this.data.defaultAppearanceData.fontSize ||= 10;
+ const {
+ fontColor,
+ fontSize
+ } = this.data.defaultAppearanceData;
+ if (this._contents.str) {
+ this.data.textContent = this._contents.str.split(/\r\n?|\n/).map(line => line.trimEnd());
+ const {
+ coords,
+ bbox,
+ matrix
+ } = FakeUnicodeFont.getFirstPositionInfo(this.rectangle, this.rotation, fontSize);
+ this.data.textPosition = this._transformPoint(coords, bbox, matrix);
+ }
+ if (this._isOffscreenCanvasSupported) {
+ const strokeAlpha = params.dict.get("CA");
+ const fakeUnicodeFont = new FakeUnicodeFont(xref, "sans-serif");
+ this.appearance = fakeUnicodeFont.createAppearance(this._contents.str, this.rectangle, this.rotation, fontSize, fontColor, strokeAlpha);
+ this._streams.push(this.appearance);
+ } else {
+ warn("FreeTextAnnotation: OffscreenCanvas is not supported, annotation may not render correctly.");
+ }
+ }
+ }
+ get hasTextContent() {
+ return this._hasAppearance;
+ }
+ static createNewDict(annotation, xref, {
+ apRef,
+ ap
+ }) {
+ const {
+ color,
+ fontSize,
+ rect,
+ rotation,
+ user,
+ value
+ } = annotation;
+ const freetext = new Dict(xref);
+ freetext.set("Type", Name.get("Annot"));
+ freetext.set("Subtype", Name.get("FreeText"));
+ freetext.set("CreationDate", `D:${getModificationDate()}`);
+ freetext.set("Rect", rect);
+ const da = `/Helv ${fontSize} Tf ${getPdfColor(color, true)}`;
+ freetext.set("DA", da);
+ freetext.set("Contents", isAscii(value) ? value : stringToUTF16String(value, true));
+ freetext.set("F", 4);
+ freetext.set("Border", [0, 0, 0]);
+ freetext.set("Rotate", rotation);
+ if (user) {
+ freetext.set("T", isAscii(user) ? user : stringToUTF16String(user, true));
+ }
+ if (apRef || ap) {
+ const n = new Dict(xref);
+ freetext.set("AP", n);
+ if (apRef) {
+ n.set("N", apRef);
+ } else {
+ n.set("N", ap);
+ }
+ }
+ return freetext;
+ }
+ static async createNewAppearanceStream(annotation, xref, params) {
+ const {
+ baseFontRef,
+ evaluator,
+ task
+ } = params;
+ const {
+ color,
+ fontSize,
+ rect,
+ rotation,
+ value
+ } = annotation;
+ const resources = new Dict(xref);
+ const font = new Dict(xref);
+ if (baseFontRef) {
+ font.set("Helv", baseFontRef);
+ } else {
+ const baseFont = new Dict(xref);
+ baseFont.set("BaseFont", Name.get("Helvetica"));
+ baseFont.set("Type", Name.get("Font"));
+ baseFont.set("Subtype", Name.get("Type1"));
+ baseFont.set("Encoding", Name.get("WinAnsiEncoding"));
+ font.set("Helv", baseFont);
+ }
+ resources.set("Font", font);
+ const helv = await WidgetAnnotation._getFontData(evaluator, task, {
+ fontName: "Helv",
+ fontSize
+ }, resources);
+ const [x1, y1, x2, y2] = rect;
+ let w = x2 - x1;
+ let h = y2 - y1;
+ if (rotation % 180 !== 0) {
+ [w, h] = [h, w];
+ }
+ const lines = value.split("\n");
+ const scale = fontSize / 1000;
+ let totalWidth = -Infinity;
+ const encodedLines = [];
+ for (let line of lines) {
+ const encoded = helv.encodeString(line);
+ if (encoded.length > 1) {
+ return null;
+ }
+ line = encoded.join("");
+ encodedLines.push(line);
+ let lineWidth = 0;
+ const glyphs = helv.charsToGlyphs(line);
+ for (const glyph of glyphs) {
+ lineWidth += glyph.width * scale;
+ }
+ totalWidth = Math.max(totalWidth, lineWidth);
+ }
+ let hscale = 1;
+ if (totalWidth > w) {
+ hscale = w / totalWidth;
+ }
+ let vscale = 1;
+ const lineHeight = LINE_FACTOR * fontSize;
+ const lineAscent = (LINE_FACTOR - LINE_DESCENT_FACTOR) * fontSize;
+ const totalHeight = lineHeight * lines.length;
+ if (totalHeight > h) {
+ vscale = h / totalHeight;
+ }
+ const fscale = Math.min(hscale, vscale);
+ const newFontSize = fontSize * fscale;
+ let firstPoint, clipBox, matrix;
+ switch (rotation) {
+ case 0:
+ matrix = [1, 0, 0, 1];
+ clipBox = [rect[0], rect[1], w, h];
+ firstPoint = [rect[0], rect[3] - lineAscent];
+ break;
+ case 90:
+ matrix = [0, 1, -1, 0];
+ clipBox = [rect[1], -rect[2], w, h];
+ firstPoint = [rect[1], -rect[0] - lineAscent];
+ break;
+ case 180:
+ matrix = [-1, 0, 0, -1];
+ clipBox = [-rect[2], -rect[3], w, h];
+ firstPoint = [-rect[2], -rect[1] - lineAscent];
+ break;
+ case 270:
+ matrix = [0, -1, 1, 0];
+ clipBox = [-rect[3], rect[0], w, h];
+ firstPoint = [-rect[3], rect[2] - lineAscent];
+ break;
+ }
+ const buffer = ["q", `${matrix.join(" ")} 0 0 cm`, `${clipBox.join(" ")} re W n`, `BT`, `${getPdfColor(color, true)}`, `0 Tc /Helv ${numberToString(newFontSize)} Tf`];
+ buffer.push(`${firstPoint.join(" ")} Td (${escapeString(encodedLines[0])}) Tj`);
+ const vShift = numberToString(lineHeight);
+ for (let i = 1, ii = encodedLines.length; i < ii; i++) {
+ const line = encodedLines[i];
+ buffer.push(`0 -${vShift} Td (${escapeString(line)}) Tj`);
+ }
+ buffer.push("ET", "Q");
+ const appearance = buffer.join("\n");
+ const appearanceStreamDict = new Dict(xref);
+ appearanceStreamDict.set("FormType", 1);
+ appearanceStreamDict.set("Subtype", Name.get("Form"));
+ appearanceStreamDict.set("Type", Name.get("XObject"));
+ appearanceStreamDict.set("BBox", rect);
+ appearanceStreamDict.set("Resources", resources);
+ appearanceStreamDict.set("Matrix", [1, 0, 0, 1, -rect[0], -rect[1]]);
+ const ap = new StringStream(appearance);
+ ap.dict = appearanceStreamDict;
+ return ap;
+ }
+}
+class LineAnnotation extends MarkupAnnotation {
+ constructor(params) {
+ super(params);
+ const {
+ dict,
+ xref
+ } = params;
+ this.data.annotationType = AnnotationType.LINE;
+ this.data.hasOwnCanvas = this.data.noRotate;
+ this.data.noHTML = false;
+ const lineCoordinates = dict.getArray("L");
+ this.data.lineCoordinates = Util.normalizeRect(lineCoordinates);
+ if (!this.appearance) {
+ const strokeColor = this.color ? getPdfColorArray(this.color) : [0, 0, 0];
+ const strokeAlpha = dict.get("CA");
+ const interiorColor = getRgbColor(dict.getArray("IC"), null);
+ const fillColor = interiorColor ? getPdfColorArray(interiorColor) : null;
+ const fillAlpha = fillColor ? strokeAlpha : null;
+ const borderWidth = this.borderStyle.width || 1,
+ borderAdjust = 2 * borderWidth;
+ const bbox = [this.data.lineCoordinates[0] - borderAdjust, this.data.lineCoordinates[1] - borderAdjust, this.data.lineCoordinates[2] + borderAdjust, this.data.lineCoordinates[3] + borderAdjust];
+ if (!Util.intersect(this.rectangle, bbox)) {
+ this.rectangle = bbox;
+ }
+ this._setDefaultAppearance({
+ xref,
+ extra: `${borderWidth} w`,
+ strokeColor,
+ fillColor,
+ strokeAlpha,
+ fillAlpha,
+ pointsCallback: (buffer, points) => {
+ buffer.push(`${lineCoordinates[0]} ${lineCoordinates[1]} m`, `${lineCoordinates[2]} ${lineCoordinates[3]} l`, "S");
+ return [points[0].x - borderWidth, points[1].x + borderWidth, points[3].y - borderWidth, points[1].y + borderWidth];
+ }
+ });
+ }
+ }
+}
+class SquareAnnotation extends MarkupAnnotation {
+ constructor(params) {
+ super(params);
+ const {
+ dict,
+ xref
+ } = params;
+ this.data.annotationType = AnnotationType.SQUARE;
+ this.data.hasOwnCanvas = this.data.noRotate;
+ this.data.noHTML = false;
+ if (!this.appearance) {
+ const strokeColor = this.color ? getPdfColorArray(this.color) : [0, 0, 0];
+ const strokeAlpha = dict.get("CA");
+ const interiorColor = getRgbColor(dict.getArray("IC"), null);
+ const fillColor = interiorColor ? getPdfColorArray(interiorColor) : null;
+ const fillAlpha = fillColor ? strokeAlpha : null;
+ if (this.borderStyle.width === 0 && !fillColor) {
+ return;
+ }
+ this._setDefaultAppearance({
+ xref,
+ extra: `${this.borderStyle.width} w`,
+ strokeColor,
+ fillColor,
+ strokeAlpha,
+ fillAlpha,
+ pointsCallback: (buffer, points) => {
+ const x = points[2].x + this.borderStyle.width / 2;
+ const y = points[2].y + this.borderStyle.width / 2;
+ const width = points[3].x - points[2].x - this.borderStyle.width;
+ const height = points[1].y - points[3].y - this.borderStyle.width;
+ buffer.push(`${x} ${y} ${width} ${height} re`);
+ if (fillColor) {
+ buffer.push("B");
+ } else {
+ buffer.push("S");
+ }
+ return [points[0].x, points[1].x, points[3].y, points[1].y];
+ }
+ });
+ }
+ }
+}
+class CircleAnnotation extends MarkupAnnotation {
+ constructor(params) {
+ super(params);
+ const {
+ dict,
+ xref
+ } = params;
+ this.data.annotationType = AnnotationType.CIRCLE;
+ if (!this.appearance) {
+ const strokeColor = this.color ? getPdfColorArray(this.color) : [0, 0, 0];
+ const strokeAlpha = dict.get("CA");
+ const interiorColor = getRgbColor(dict.getArray("IC"), null);
+ const fillColor = interiorColor ? getPdfColorArray(interiorColor) : null;
+ const fillAlpha = fillColor ? strokeAlpha : null;
+ if (this.borderStyle.width === 0 && !fillColor) {
+ return;
+ }
+ const controlPointsDistance = 4 / 3 * Math.tan(Math.PI / (2 * 4));
+ this._setDefaultAppearance({
+ xref,
+ extra: `${this.borderStyle.width} w`,
+ strokeColor,
+ fillColor,
+ strokeAlpha,
+ fillAlpha,
+ pointsCallback: (buffer, points) => {
+ const x0 = points[0].x + this.borderStyle.width / 2;
+ const y0 = points[0].y - this.borderStyle.width / 2;
+ const x1 = points[3].x - this.borderStyle.width / 2;
+ const y1 = points[3].y + this.borderStyle.width / 2;
+ const xMid = x0 + (x1 - x0) / 2;
+ const yMid = y0 + (y1 - y0) / 2;
+ const xOffset = (x1 - x0) / 2 * controlPointsDistance;
+ const yOffset = (y1 - y0) / 2 * controlPointsDistance;
+ buffer.push(`${xMid} ${y1} m`, `${xMid + xOffset} ${y1} ${x1} ${yMid + yOffset} ${x1} ${yMid} c`, `${x1} ${yMid - yOffset} ${xMid + xOffset} ${y0} ${xMid} ${y0} c`, `${xMid - xOffset} ${y0} ${x0} ${yMid - yOffset} ${x0} ${yMid} c`, `${x0} ${yMid + yOffset} ${xMid - xOffset} ${y1} ${xMid} ${y1} c`, "h");
+ if (fillColor) {
+ buffer.push("B");
+ } else {
+ buffer.push("S");
+ }
+ return [points[0].x, points[1].x, points[3].y, points[1].y];
+ }
+ });
+ }
+ }
+}
+class PolylineAnnotation extends MarkupAnnotation {
+ constructor(params) {
+ super(params);
+ const {
+ dict,
+ xref
+ } = params;
+ this.data.annotationType = AnnotationType.POLYLINE;
+ this.data.hasOwnCanvas = this.data.noRotate;
+ this.data.noHTML = false;
+ this.data.vertices = [];
+ const rawVertices = dict.getArray("Vertices");
+ if (!Array.isArray(rawVertices)) {
+ return;
+ }
+ for (let i = 0, ii = rawVertices.length; i < ii; i += 2) {
+ this.data.vertices.push({
+ x: rawVertices[i],
+ y: rawVertices[i + 1]
+ });
+ }
+ if (!this.appearance) {
+ const strokeColor = this.color ? getPdfColorArray(this.color) : [0, 0, 0];
+ const strokeAlpha = dict.get("CA");
+ const borderWidth = this.borderStyle.width || 1,
+ borderAdjust = 2 * borderWidth;
+ const bbox = [Infinity, Infinity, -Infinity, -Infinity];
+ for (const vertex of this.data.vertices) {
+ bbox[0] = Math.min(bbox[0], vertex.x - borderAdjust);
+ bbox[1] = Math.min(bbox[1], vertex.y - borderAdjust);
+ bbox[2] = Math.max(bbox[2], vertex.x + borderAdjust);
+ bbox[3] = Math.max(bbox[3], vertex.y + borderAdjust);
+ }
+ if (!Util.intersect(this.rectangle, bbox)) {
+ this.rectangle = bbox;
+ }
+ this._setDefaultAppearance({
+ xref,
+ extra: `${borderWidth} w`,
+ strokeColor,
+ strokeAlpha,
+ pointsCallback: (buffer, points) => {
+ const vertices = this.data.vertices;
+ for (let i = 0, ii = vertices.length; i < ii; i++) {
+ buffer.push(`${vertices[i].x} ${vertices[i].y} ${i === 0 ? "m" : "l"}`);
+ }
+ buffer.push("S");
+ return [points[0].x, points[1].x, points[3].y, points[1].y];
+ }
+ });
+ }
+ }
+}
+class PolygonAnnotation extends PolylineAnnotation {
+ constructor(params) {
+ super(params);
+ this.data.annotationType = AnnotationType.POLYGON;
+ }
+}
+class CaretAnnotation extends MarkupAnnotation {
+ constructor(params) {
+ super(params);
+ this.data.annotationType = AnnotationType.CARET;
+ }
+}
+class InkAnnotation extends MarkupAnnotation {
+ constructor(params) {
+ super(params);
+ this.data.hasOwnCanvas = this.data.noRotate;
+ this.data.noHTML = false;
+ const {
+ dict,
+ xref
+ } = params;
+ this.data.annotationType = AnnotationType.INK;
+ this.data.inkLists = [];
+ const rawInkLists = dict.getArray("InkList");
+ if (!Array.isArray(rawInkLists)) {
+ return;
+ }
+ for (let i = 0, ii = rawInkLists.length; i < ii; ++i) {
+ this.data.inkLists.push([]);
+ for (let j = 0, jj = rawInkLists[i].length; j < jj; j += 2) {
+ this.data.inkLists[i].push({
+ x: xref.fetchIfRef(rawInkLists[i][j]),
+ y: xref.fetchIfRef(rawInkLists[i][j + 1])
+ });
+ }
+ }
+ if (!this.appearance) {
+ const strokeColor = this.color ? getPdfColorArray(this.color) : [0, 0, 0];
+ const strokeAlpha = dict.get("CA");
+ const borderWidth = this.borderStyle.width || 1,
+ borderAdjust = 2 * borderWidth;
+ const bbox = [Infinity, Infinity, -Infinity, -Infinity];
+ for (const inkLists of this.data.inkLists) {
+ for (const vertex of inkLists) {
+ bbox[0] = Math.min(bbox[0], vertex.x - borderAdjust);
+ bbox[1] = Math.min(bbox[1], vertex.y - borderAdjust);
+ bbox[2] = Math.max(bbox[2], vertex.x + borderAdjust);
+ bbox[3] = Math.max(bbox[3], vertex.y + borderAdjust);
+ }
+ }
+ if (!Util.intersect(this.rectangle, bbox)) {
+ this.rectangle = bbox;
+ }
+ this._setDefaultAppearance({
+ xref,
+ extra: `${borderWidth} w`,
+ strokeColor,
+ strokeAlpha,
+ pointsCallback: (buffer, points) => {
+ for (const inkList of this.data.inkLists) {
+ for (let i = 0, ii = inkList.length; i < ii; i++) {
+ buffer.push(`${inkList[i].x} ${inkList[i].y} ${i === 0 ? "m" : "l"}`);
+ }
+ buffer.push("S");
+ }
+ return [points[0].x, points[1].x, points[3].y, points[1].y];
+ }
+ });
+ }
+ }
+ static createNewDict(annotation, xref, {
+ apRef,
+ ap
+ }) {
+ const {
+ color,
+ opacity,
+ paths,
+ outlines,
+ rect,
+ rotation,
+ thickness
+ } = annotation;
+ const ink = new Dict(xref);
+ ink.set("Type", Name.get("Annot"));
+ ink.set("Subtype", Name.get("Ink"));
+ ink.set("CreationDate", `D:${getModificationDate()}`);
+ ink.set("Rect", rect);
+ ink.set("InkList", outlines?.points || paths.map(p => p.points));
+ ink.set("F", 4);
+ ink.set("Rotate", rotation);
+ if (outlines) {
+ ink.set("IT", Name.get("InkHighlight"));
+ }
+ const bs = new Dict(xref);
+ ink.set("BS", bs);
+ bs.set("W", thickness);
+ ink.set("C", Array.from(color, c => c / 255));
+ ink.set("CA", opacity);
+ const n = new Dict(xref);
+ ink.set("AP", n);
+ if (apRef) {
+ n.set("N", apRef);
+ } else {
+ n.set("N", ap);
+ }
+ return ink;
+ }
+ static async createNewAppearanceStream(annotation, xref, params) {
+ if (annotation.outlines) {
+ return this.createNewAppearanceStreamForHighlight(annotation, xref, params);
+ }
+ const {
+ color,
+ rect,
+ paths,
+ thickness,
+ opacity
+ } = annotation;
+ const appearanceBuffer = [`${thickness} w 1 J 1 j`, `${getPdfColor(color, false)}`];
+ if (opacity !== 1) {
+ appearanceBuffer.push("/R0 gs");
+ }
+ const buffer = [];
+ for (const {
+ bezier
+ } of paths) {
+ buffer.length = 0;
+ buffer.push(`${numberToString(bezier[0])} ${numberToString(bezier[1])} m`);
+ if (bezier.length === 2) {
+ buffer.push(`${numberToString(bezier[0])} ${numberToString(bezier[1])} l S`);
+ } else {
+ for (let i = 2, ii = bezier.length; i < ii; i += 6) {
+ const curve = bezier.slice(i, i + 6).map(numberToString).join(" ");
+ buffer.push(`${curve} c`);
+ }
+ buffer.push("S");
+ }
+ appearanceBuffer.push(buffer.join("\n"));
+ }
+ const appearance = appearanceBuffer.join("\n");
+ const appearanceStreamDict = new Dict(xref);
+ appearanceStreamDict.set("FormType", 1);
+ appearanceStreamDict.set("Subtype", Name.get("Form"));
+ appearanceStreamDict.set("Type", Name.get("XObject"));
+ appearanceStreamDict.set("BBox", rect);
+ appearanceStreamDict.set("Length", appearance.length);
+ if (opacity !== 1) {
+ const resources = new Dict(xref);
+ const extGState = new Dict(xref);
+ const r0 = new Dict(xref);
+ r0.set("CA", opacity);
+ r0.set("Type", Name.get("ExtGState"));
+ extGState.set("R0", r0);
+ resources.set("ExtGState", extGState);
+ appearanceStreamDict.set("Resources", resources);
+ }
+ const ap = new StringStream(appearance);
+ ap.dict = appearanceStreamDict;
+ return ap;
+ }
+ static async createNewAppearanceStreamForHighlight(annotation, xref, params) {
+ const {
+ color,
+ rect,
+ outlines: {
+ outline
+ },
+ opacity
+ } = annotation;
+ const appearanceBuffer = [`${getPdfColor(color, true)}`, "/R0 gs"];
+ appearanceBuffer.push(`${numberToString(outline[4])} ${numberToString(outline[5])} m`);
+ for (let i = 6, ii = outline.length; i < ii; i += 6) {
+ if (isNaN(outline[i]) || outline[i] === null) {
+ appearanceBuffer.push(`${numberToString(outline[i + 4])} ${numberToString(outline[i + 5])} l`);
+ } else {
+ const curve = outline.slice(i, i + 6).map(numberToString).join(" ");
+ appearanceBuffer.push(`${curve} c`);
+ }
+ }
+ appearanceBuffer.push("h f");
+ const appearance = appearanceBuffer.join("\n");
+ const appearanceStreamDict = new Dict(xref);
+ appearanceStreamDict.set("FormType", 1);
+ appearanceStreamDict.set("Subtype", Name.get("Form"));
+ appearanceStreamDict.set("Type", Name.get("XObject"));
+ appearanceStreamDict.set("BBox", rect);
+ appearanceStreamDict.set("Length", appearance.length);
+ const resources = new Dict(xref);
+ const extGState = new Dict(xref);
+ resources.set("ExtGState", extGState);
+ appearanceStreamDict.set("Resources", resources);
+ const r0 = new Dict(xref);
+ extGState.set("R0", r0);
+ r0.set("BM", Name.get("Multiply"));
+ if (opacity !== 1) {
+ r0.set("ca", opacity);
+ r0.set("Type", Name.get("ExtGState"));
+ }
+ const ap = new StringStream(appearance);
+ ap.dict = appearanceStreamDict;
+ return ap;
+ }
+}
+class HighlightAnnotation extends MarkupAnnotation {
+ constructor(params) {
+ super(params);
+ const {
+ dict,
+ xref
+ } = params;
+ this.data.annotationType = AnnotationType.HIGHLIGHT;
+ const quadPoints = this.data.quadPoints = getQuadPoints(dict, null);
+ if (quadPoints) {
+ const resources = this.appearance?.dict.get("Resources");
+ if (!this.appearance || !resources?.has("ExtGState")) {
+ if (this.appearance) {
+ warn("HighlightAnnotation - ignoring built-in appearance stream.");
+ }
+ const fillColor = this.color ? getPdfColorArray(this.color) : [1, 1, 0];
+ const fillAlpha = dict.get("CA");
+ this._setDefaultAppearance({
+ xref,
+ fillColor,
+ blendMode: "Multiply",
+ fillAlpha,
+ pointsCallback: (buffer, points) => {
+ buffer.push(`${points[0].x} ${points[0].y} m`, `${points[1].x} ${points[1].y} l`, `${points[3].x} ${points[3].y} l`, `${points[2].x} ${points[2].y} l`, "f");
+ return [points[0].x, points[1].x, points[3].y, points[1].y];
+ }
+ });
+ }
+ } else {
+ this.data.popupRef = null;
+ }
+ }
+ static createNewDict(annotation, xref, {
+ apRef,
+ ap
+ }) {
+ const {
+ color,
+ opacity,
+ rect,
+ rotation,
+ user,
+ quadPoints
+ } = annotation;
+ const highlight = new Dict(xref);
+ highlight.set("Type", Name.get("Annot"));
+ highlight.set("Subtype", Name.get("Highlight"));
+ highlight.set("CreationDate", `D:${getModificationDate()}`);
+ highlight.set("Rect", rect);
+ highlight.set("F", 4);
+ highlight.set("Border", [0, 0, 0]);
+ highlight.set("Rotate", rotation);
+ highlight.set("QuadPoints", quadPoints);
+ highlight.set("C", Array.from(color, c => c / 255));
+ highlight.set("CA", opacity);
+ if (user) {
+ highlight.set("T", isAscii(user) ? user : stringToUTF16String(user, true));
+ }
+ if (apRef || ap) {
+ const n = new Dict(xref);
+ highlight.set("AP", n);
+ n.set("N", apRef || ap);
+ }
+ return highlight;
+ }
+ static async createNewAppearanceStream(annotation, xref, params) {
+ const {
+ color,
+ rect,
+ outlines,
+ opacity
+ } = annotation;
+ const appearanceBuffer = [`${getPdfColor(color, true)}`, "/R0 gs"];
+ const buffer = [];
+ for (const outline of outlines) {
+ buffer.length = 0;
+ buffer.push(`${numberToString(outline[0])} ${numberToString(outline[1])} m`);
+ for (let i = 2, ii = outline.length; i < ii; i += 2) {
+ buffer.push(`${numberToString(outline[i])} ${numberToString(outline[i + 1])} l`);
+ }
+ buffer.push("h");
+ appearanceBuffer.push(buffer.join("\n"));
+ }
+ appearanceBuffer.push("f*");
+ const appearance = appearanceBuffer.join("\n");
+ const appearanceStreamDict = new Dict(xref);
+ appearanceStreamDict.set("FormType", 1);
+ appearanceStreamDict.set("Subtype", Name.get("Form"));
+ appearanceStreamDict.set("Type", Name.get("XObject"));
+ appearanceStreamDict.set("BBox", rect);
+ appearanceStreamDict.set("Length", appearance.length);
+ const resources = new Dict(xref);
+ const extGState = new Dict(xref);
+ resources.set("ExtGState", extGState);
+ appearanceStreamDict.set("Resources", resources);
+ const r0 = new Dict(xref);
+ extGState.set("R0", r0);
+ r0.set("BM", Name.get("Multiply"));
+ if (opacity !== 1) {
+ r0.set("ca", opacity);
+ r0.set("Type", Name.get("ExtGState"));
+ }
+ const ap = new StringStream(appearance);
+ ap.dict = appearanceStreamDict;
+ return ap;
+ }
+}
+class UnderlineAnnotation extends MarkupAnnotation {
+ constructor(params) {
+ super(params);
+ const {
+ dict,
+ xref
+ } = params;
+ this.data.annotationType = AnnotationType.UNDERLINE;
+ const quadPoints = this.data.quadPoints = getQuadPoints(dict, null);
+ if (quadPoints) {
+ if (!this.appearance) {
+ const strokeColor = this.color ? getPdfColorArray(this.color) : [0, 0, 0];
+ const strokeAlpha = dict.get("CA");
+ this._setDefaultAppearance({
+ xref,
+ extra: "[] 0 d 0.571 w",
+ strokeColor,
+ strokeAlpha,
+ pointsCallback: (buffer, points) => {
+ buffer.push(`${points[2].x} ${points[2].y + 1.3} m`, `${points[3].x} ${points[3].y + 1.3} l`, "S");
+ return [points[0].x, points[1].x, points[3].y, points[1].y];
+ }
+ });
+ }
+ } else {
+ this.data.popupRef = null;
+ }
+ }
+}
+class SquigglyAnnotation extends MarkupAnnotation {
+ constructor(params) {
+ super(params);
+ const {
+ dict,
+ xref
+ } = params;
+ this.data.annotationType = AnnotationType.SQUIGGLY;
+ const quadPoints = this.data.quadPoints = getQuadPoints(dict, null);
+ if (quadPoints) {
+ if (!this.appearance) {
+ const strokeColor = this.color ? getPdfColorArray(this.color) : [0, 0, 0];
+ const strokeAlpha = dict.get("CA");
+ this._setDefaultAppearance({
+ xref,
+ extra: "[] 0 d 1 w",
+ strokeColor,
+ strokeAlpha,
+ pointsCallback: (buffer, points) => {
+ const dy = (points[0].y - points[2].y) / 6;
+ let shift = dy;
+ let x = points[2].x;
+ const y = points[2].y;
+ const xEnd = points[3].x;
+ buffer.push(`${x} ${y + shift} m`);
+ do {
+ x += 2;
+ shift = shift === 0 ? dy : 0;
+ buffer.push(`${x} ${y + shift} l`);
+ } while (x < xEnd);
+ buffer.push("S");
+ return [points[2].x, xEnd, y - 2 * dy, y + 2 * dy];
+ }
+ });
+ }
+ } else {
+ this.data.popupRef = null;
+ }
+ }
+}
+class StrikeOutAnnotation extends MarkupAnnotation {
+ constructor(params) {
+ super(params);
+ const {
+ dict,
+ xref
+ } = params;
+ this.data.annotationType = AnnotationType.STRIKEOUT;
+ const quadPoints = this.data.quadPoints = getQuadPoints(dict, null);
+ if (quadPoints) {
+ if (!this.appearance) {
+ const strokeColor = this.color ? getPdfColorArray(this.color) : [0, 0, 0];
+ const strokeAlpha = dict.get("CA");
+ this._setDefaultAppearance({
+ xref,
+ extra: "[] 0 d 1 w",
+ strokeColor,
+ strokeAlpha,
+ pointsCallback: (buffer, points) => {
+ buffer.push(`${(points[0].x + points[2].x) / 2} ` + `${(points[0].y + points[2].y) / 2} m`, `${(points[1].x + points[3].x) / 2} ` + `${(points[1].y + points[3].y) / 2} l`, "S");
+ return [points[0].x, points[1].x, points[3].y, points[1].y];
+ }
+ });
+ }
+ } else {
+ this.data.popupRef = null;
+ }
+ }
+}
+class StampAnnotation extends MarkupAnnotation {
+ constructor(params) {
+ super(params);
+ this.data.annotationType = AnnotationType.STAMP;
+ this.data.hasOwnCanvas = this.data.noRotate;
+ this.data.noHTML = false;
+ }
+ static async createImage(bitmap, xref) {
+ const {
+ width,
+ height
+ } = bitmap;
+ const canvas = new OffscreenCanvas(width, height);
+ const ctx = canvas.getContext("2d", {
+ alpha: true
+ });
+ ctx.drawImage(bitmap, 0, 0);
+ const data = ctx.getImageData(0, 0, width, height).data;
+ const buf32 = new Uint32Array(data.buffer);
+ const hasAlpha = buf32.some(FeatureTest.isLittleEndian ? x => x >>> 24 !== 0xff : x => (x & 0xff) !== 0xff);
+ if (hasAlpha) {
+ ctx.fillStyle = "white";
+ ctx.fillRect(0, 0, width, height);
+ ctx.drawImage(bitmap, 0, 0);
+ }
+ const jpegBufferPromise = canvas.convertToBlob({
+ type: "image/jpeg",
+ quality: 1
+ }).then(blob => blob.arrayBuffer());
+ const xobjectName = Name.get("XObject");
+ const imageName = Name.get("Image");
+ const image = new Dict(xref);
+ image.set("Type", xobjectName);
+ image.set("Subtype", imageName);
+ image.set("BitsPerComponent", 8);
+ image.set("ColorSpace", Name.get("DeviceRGB"));
+ image.set("Filter", Name.get("DCTDecode"));
+ image.set("BBox", [0, 0, width, height]);
+ image.set("Width", width);
+ image.set("Height", height);
+ let smaskStream = null;
+ if (hasAlpha) {
+ const alphaBuffer = new Uint8Array(buf32.length);
+ if (FeatureTest.isLittleEndian) {
+ for (let i = 0, ii = buf32.length; i < ii; i++) {
+ alphaBuffer[i] = buf32[i] >>> 24;
+ }
+ } else {
+ for (let i = 0, ii = buf32.length; i < ii; i++) {
+ alphaBuffer[i] = buf32[i] & 0xff;
+ }
+ }
+ const smask = new Dict(xref);
+ smask.set("Type", xobjectName);
+ smask.set("Subtype", imageName);
+ smask.set("BitsPerComponent", 8);
+ smask.set("ColorSpace", Name.get("DeviceGray"));
+ smask.set("Width", width);
+ smask.set("Height", height);
+ smaskStream = new Stream(alphaBuffer, 0, 0, smask);
+ }
+ const imageStream = new Stream(await jpegBufferPromise, 0, 0, image);
+ return {
+ imageStream,
+ smaskStream,
+ width,
+ height
+ };
+ }
+ static createNewDict(annotation, xref, {
+ apRef,
+ ap
+ }) {
+ const {
+ rect,
+ rotation,
+ user
+ } = annotation;
+ const stamp = new Dict(xref);
+ stamp.set("Type", Name.get("Annot"));
+ stamp.set("Subtype", Name.get("Stamp"));
+ stamp.set("CreationDate", `D:${getModificationDate()}`);
+ stamp.set("Rect", rect);
+ stamp.set("F", 4);
+ stamp.set("Border", [0, 0, 0]);
+ stamp.set("Rotate", rotation);
+ if (user) {
+ stamp.set("T", isAscii(user) ? user : stringToUTF16String(user, true));
+ }
+ if (apRef || ap) {
+ const n = new Dict(xref);
+ stamp.set("AP", n);
+ if (apRef) {
+ n.set("N", apRef);
+ } else {
+ n.set("N", ap);
+ }
+ }
+ return stamp;
+ }
+ static async createNewAppearanceStream(annotation, xref, params) {
+ const {
+ rotation
+ } = annotation;
+ const {
+ imageRef,
+ width,
+ height
+ } = params.image;
+ const resources = new Dict(xref);
+ const xobject = new Dict(xref);
+ resources.set("XObject", xobject);
+ xobject.set("Im0", imageRef);
+ const appearance = `q ${width} 0 0 ${height} 0 0 cm /Im0 Do Q`;
+ const appearanceStreamDict = new Dict(xref);
+ appearanceStreamDict.set("FormType", 1);
+ appearanceStreamDict.set("Subtype", Name.get("Form"));
+ appearanceStreamDict.set("Type", Name.get("XObject"));
+ appearanceStreamDict.set("BBox", [0, 0, width, height]);
+ appearanceStreamDict.set("Resources", resources);
+ if (rotation) {
+ const matrix = getRotationMatrix(rotation, width, height);
+ appearanceStreamDict.set("Matrix", matrix);
+ }
+ const ap = new StringStream(appearance);
+ ap.dict = appearanceStreamDict;
+ return ap;
+ }
+}
+class FileAttachmentAnnotation extends MarkupAnnotation {
+ constructor(params) {
+ super(params);
+ const {
+ dict,
+ xref
+ } = params;
+ const file = new FileSpec(dict.get("FS"), xref);
+ this.data.annotationType = AnnotationType.FILEATTACHMENT;
+ this.data.hasOwnCanvas = this.data.noRotate;
+ this.data.noHTML = false;
+ this.data.file = file.serializable;
+ const name = dict.get("Name");
+ this.data.name = name instanceof Name ? stringToPDFString(name.name) : "PushPin";
+ const fillAlpha = dict.get("ca");
+ this.data.fillAlpha = typeof fillAlpha === "number" && fillAlpha >= 0 && fillAlpha <= 1 ? fillAlpha : null;
+ }
+}
+
+;// CONCATENATED MODULE: ./src/core/dataset_reader.js
+
+
+
+function decodeString(str) {
+ try {
+ return stringToUTF8String(str);
+ } catch (ex) {
+ warn(`UTF-8 decoding failed: "${ex}".`);
+ return str;
+ }
+}
+class DatasetXMLParser extends SimpleXMLParser {
+ constructor(options) {
+ super(options);
+ this.node = null;
+ }
+ onEndElement(name) {
+ const node = super.onEndElement(name);
+ if (node && name === "xfa:datasets") {
+ this.node = node;
+ throw new Error("Aborting DatasetXMLParser.");
+ }
+ }
+}
+class DatasetReader {
+ constructor(data) {
+ if (data.datasets) {
+ this.node = new SimpleXMLParser({
+ hasAttributes: true
+ }).parseFromString(data.datasets).documentElement;
+ } else {
+ const parser = new DatasetXMLParser({
+ hasAttributes: true
+ });
+ try {
+ parser.parseFromString(data["xdp:xdp"]);
+ } catch {}
+ this.node = parser.node;
+ }
+ }
+ getValue(path) {
+ if (!this.node || !path) {
+ return "";
+ }
+ const node = this.node.searchNode(parseXFAPath(path), 0);
+ if (!node) {
+ return "";
+ }
+ const first = node.firstChild;
+ if (first?.nodeName === "value") {
+ return node.children.map(child => decodeString(child.textContent));
+ }
+ return decodeString(node.textContent);
+ }
+}
+
+;// CONCATENATED MODULE: ./src/core/xref.js
+
+
+
+
+
+
+class XRef {
+ #firstXRefStmPos = null;
+ constructor(stream, pdfManager) {
+ this.stream = stream;
+ this.pdfManager = pdfManager;
+ this.entries = [];
+ this._xrefStms = new Set();
+ this._cacheMap = new Map();
+ this._pendingRefs = new RefSet();
+ this._newPersistentRefNum = null;
+ this._newTemporaryRefNum = null;
+ this._persistentRefsCache = null;
+ }
+ getNewPersistentRef(obj) {
+ if (this._newPersistentRefNum === null) {
+ this._newPersistentRefNum = this.entries.length || 1;
+ }
+ const num = this._newPersistentRefNum++;
+ this._cacheMap.set(num, obj);
+ return Ref.get(num, 0);
+ }
+ getNewTemporaryRef() {
+ if (this._newTemporaryRefNum === null) {
+ this._newTemporaryRefNum = this.entries.length || 1;
+ if (this._newPersistentRefNum) {
+ this._persistentRefsCache = new Map();
+ for (let i = this._newTemporaryRefNum; i < this._newPersistentRefNum; i++) {
+ this._persistentRefsCache.set(i, this._cacheMap.get(i));
+ this._cacheMap.delete(i);
+ }
+ }
+ }
+ return Ref.get(this._newTemporaryRefNum++, 0);
+ }
+ resetNewTemporaryRef() {
+ this._newTemporaryRefNum = null;
+ if (this._persistentRefsCache) {
+ for (const [num, obj] of this._persistentRefsCache) {
+ this._cacheMap.set(num, obj);
+ }
+ }
+ this._persistentRefsCache = null;
+ }
+ setStartXRef(startXRef) {
+ this.startXRefQueue = [startXRef];
+ }
+ parse(recoveryMode = false) {
+ let trailerDict;
+ if (!recoveryMode) {
+ trailerDict = this.readXRef();
+ } else {
+ warn("Indexing all PDF objects");
+ trailerDict = this.indexObjects();
+ }
+ trailerDict.assignXref(this);
+ this.trailer = trailerDict;
+ let encrypt;
+ try {
+ encrypt = trailerDict.get("Encrypt");
+ } catch (ex) {
+ if (ex instanceof MissingDataException) {
+ throw ex;
+ }
+ warn(`XRef.parse - Invalid "Encrypt" reference: "${ex}".`);
+ }
+ if (encrypt instanceof Dict) {
+ const ids = trailerDict.get("ID");
+ const fileId = ids?.length ? ids[0] : "";
+ encrypt.suppressEncryption = true;
+ this.encrypt = new CipherTransformFactory(encrypt, fileId, this.pdfManager.password);
+ }
+ let root;
+ try {
+ root = trailerDict.get("Root");
+ } catch (ex) {
+ if (ex instanceof MissingDataException) {
+ throw ex;
+ }
+ warn(`XRef.parse - Invalid "Root" reference: "${ex}".`);
+ }
+ if (root instanceof Dict) {
+ try {
+ const pages = root.get("Pages");
+ if (pages instanceof Dict) {
+ this.root = root;
+ return;
+ }
+ } catch (ex) {
+ if (ex instanceof MissingDataException) {
+ throw ex;
+ }
+ warn(`XRef.parse - Invalid "Pages" reference: "${ex}".`);
+ }
+ }
+ if (!recoveryMode) {
+ throw new XRefParseException();
+ }
+ throw new InvalidPDFException("Invalid Root reference.");
+ }
+ processXRefTable(parser) {
+ if (!("tableState" in this)) {
+ this.tableState = {
+ entryNum: 0,
+ streamPos: parser.lexer.stream.pos,
+ parserBuf1: parser.buf1,
+ parserBuf2: parser.buf2
+ };
+ }
+ const obj = this.readXRefTable(parser);
+ if (!isCmd(obj, "trailer")) {
+ throw new FormatError("Invalid XRef table: could not find trailer dictionary");
+ }
+ let dict = parser.getObj();
+ if (!(dict instanceof Dict) && dict.dict) {
+ dict = dict.dict;
+ }
+ if (!(dict instanceof Dict)) {
+ throw new FormatError("Invalid XRef table: could not parse trailer dictionary");
+ }
+ delete this.tableState;
+ return dict;
+ }
+ readXRefTable(parser) {
+ const stream = parser.lexer.stream;
+ const tableState = this.tableState;
+ stream.pos = tableState.streamPos;
+ parser.buf1 = tableState.parserBuf1;
+ parser.buf2 = tableState.parserBuf2;
+ let obj;
+ while (true) {
+ if (!("firstEntryNum" in tableState) || !("entryCount" in tableState)) {
+ if (isCmd(obj = parser.getObj(), "trailer")) {
+ break;
+ }
+ tableState.firstEntryNum = obj;
+ tableState.entryCount = parser.getObj();
+ }
+ let first = tableState.firstEntryNum;
+ const count = tableState.entryCount;
+ if (!Number.isInteger(first) || !Number.isInteger(count)) {
+ throw new FormatError("Invalid XRef table: wrong types in subsection header");
+ }
+ for (let i = tableState.entryNum; i < count; i++) {
+ tableState.streamPos = stream.pos;
+ tableState.entryNum = i;
+ tableState.parserBuf1 = parser.buf1;
+ tableState.parserBuf2 = parser.buf2;
+ const entry = {};
+ entry.offset = parser.getObj();
+ entry.gen = parser.getObj();
+ const type = parser.getObj();
+ if (type instanceof Cmd) {
+ switch (type.cmd) {
+ case "f":
+ entry.free = true;
+ break;
+ case "n":
+ entry.uncompressed = true;
+ break;
+ }
+ }
+ if (!Number.isInteger(entry.offset) || !Number.isInteger(entry.gen) || !(entry.free || entry.uncompressed)) {
+ throw new FormatError(`Invalid entry in XRef subsection: ${first}, ${count}`);
+ }
+ if (i === 0 && entry.free && first === 1) {
+ first = 0;
+ }
+ if (!this.entries[i + first]) {
+ this.entries[i + first] = entry;
+ }
+ }
+ tableState.entryNum = 0;
+ tableState.streamPos = stream.pos;
+ tableState.parserBuf1 = parser.buf1;
+ tableState.parserBuf2 = parser.buf2;
+ delete tableState.firstEntryNum;
+ delete tableState.entryCount;
+ }
+ if (this.entries[0] && !this.entries[0].free) {
+ throw new FormatError("Invalid XRef table: unexpected first object");
+ }
+ return obj;
+ }
+ processXRefStream(stream) {
+ if (!("streamState" in this)) {
+ const streamParameters = stream.dict;
+ const byteWidths = streamParameters.get("W");
+ let range = streamParameters.get("Index");
+ if (!range) {
+ range = [0, streamParameters.get("Size")];
+ }
+ this.streamState = {
+ entryRanges: range,
+ byteWidths,
+ entryNum: 0,
+ streamPos: stream.pos
+ };
+ }
+ this.readXRefStream(stream);
+ delete this.streamState;
+ return stream.dict;
+ }
+ readXRefStream(stream) {
+ const streamState = this.streamState;
+ stream.pos = streamState.streamPos;
+ const [typeFieldWidth, offsetFieldWidth, generationFieldWidth] = streamState.byteWidths;
+ const entryRanges = streamState.entryRanges;
+ while (entryRanges.length > 0) {
+ const [first, n] = entryRanges;
+ if (!Number.isInteger(first) || !Number.isInteger(n)) {
+ throw new FormatError(`Invalid XRef range fields: ${first}, ${n}`);
+ }
+ if (!Number.isInteger(typeFieldWidth) || !Number.isInteger(offsetFieldWidth) || !Number.isInteger(generationFieldWidth)) {
+ throw new FormatError(`Invalid XRef entry fields length: ${first}, ${n}`);
+ }
+ for (let i = streamState.entryNum; i < n; ++i) {
+ streamState.entryNum = i;
+ streamState.streamPos = stream.pos;
+ let type = 0,
+ offset = 0,
+ generation = 0;
+ for (let j = 0; j < typeFieldWidth; ++j) {
+ const typeByte = stream.getByte();
+ if (typeByte === -1) {
+ throw new FormatError("Invalid XRef byteWidths 'type'.");
+ }
+ type = type << 8 | typeByte;
+ }
+ if (typeFieldWidth === 0) {
+ type = 1;
+ }
+ for (let j = 0; j < offsetFieldWidth; ++j) {
+ const offsetByte = stream.getByte();
+ if (offsetByte === -1) {
+ throw new FormatError("Invalid XRef byteWidths 'offset'.");
+ }
+ offset = offset << 8 | offsetByte;
+ }
+ for (let j = 0; j < generationFieldWidth; ++j) {
+ const generationByte = stream.getByte();
+ if (generationByte === -1) {
+ throw new FormatError("Invalid XRef byteWidths 'generation'.");
+ }
+ generation = generation << 8 | generationByte;
+ }
+ const entry = {};
+ entry.offset = offset;
+ entry.gen = generation;
+ switch (type) {
+ case 0:
+ entry.free = true;
+ break;
+ case 1:
+ entry.uncompressed = true;
+ break;
+ case 2:
+ break;
+ default:
+ throw new FormatError(`Invalid XRef entry type: ${type}`);
+ }
+ if (!this.entries[first + i]) {
+ this.entries[first + i] = entry;
+ }
+ }
+ streamState.entryNum = 0;
+ streamState.streamPos = stream.pos;
+ entryRanges.splice(0, 2);
+ }
+ }
+ indexObjects() {
+ const TAB = 0x9,
+ LF = 0xa,
+ CR = 0xd,
+ SPACE = 0x20;
+ const PERCENT = 0x25,
+ LT = 0x3c;
+ function readToken(data, offset) {
+ let token = "",
+ ch = data[offset];
+ while (ch !== LF && ch !== CR && ch !== LT) {
+ if (++offset >= data.length) {
+ break;
+ }
+ token += String.fromCharCode(ch);
+ ch = data[offset];
+ }
+ return token;
+ }
+ function skipUntil(data, offset, what) {
+ const length = what.length,
+ dataLength = data.length;
+ let skipped = 0;
+ while (offset < dataLength) {
+ let i = 0;
+ while (i < length && data[offset + i] === what[i]) {
+ ++i;
+ }
+ if (i >= length) {
+ break;
+ }
+ offset++;
+ skipped++;
+ }
+ return skipped;
+ }
+ const gEndobjRegExp = /\b(endobj|\d+\s+\d+\s+obj|xref|trailer\s*<<)\b/g;
+ const gStartxrefRegExp = /\b(startxref|\d+\s+\d+\s+obj)\b/g;
+ const objRegExp = /^(\d+)\s+(\d+)\s+obj\b/;
+ const trailerBytes = new Uint8Array([116, 114, 97, 105, 108, 101, 114]);
+ const startxrefBytes = new Uint8Array([115, 116, 97, 114, 116, 120, 114, 101, 102]);
+ const xrefBytes = new Uint8Array([47, 88, 82, 101, 102]);
+ this.entries.length = 0;
+ this._cacheMap.clear();
+ const stream = this.stream;
+ stream.pos = 0;
+ const buffer = stream.getBytes(),
+ bufferStr = bytesToString(buffer),
+ length = buffer.length;
+ let position = stream.start;
+ const trailers = [],
+ xrefStms = [];
+ while (position < length) {
+ let ch = buffer[position];
+ if (ch === TAB || ch === LF || ch === CR || ch === SPACE) {
+ ++position;
+ continue;
+ }
+ if (ch === PERCENT) {
+ do {
+ ++position;
+ if (position >= length) {
+ break;
+ }
+ ch = buffer[position];
+ } while (ch !== LF && ch !== CR);
+ continue;
+ }
+ const token = readToken(buffer, position);
+ let m;
+ if (token.startsWith("xref") && (token.length === 4 || /\s/.test(token[4]))) {
+ position += skipUntil(buffer, position, trailerBytes);
+ trailers.push(position);
+ position += skipUntil(buffer, position, startxrefBytes);
+ } else if (m = objRegExp.exec(token)) {
+ const num = m[1] | 0,
+ gen = m[2] | 0;
+ const startPos = position + token.length;
+ let contentLength,
+ updateEntries = false;
+ if (!this.entries[num]) {
+ updateEntries = true;
+ } else if (this.entries[num].gen === gen) {
+ try {
+ const parser = new Parser({
+ lexer: new Lexer(stream.makeSubStream(startPos))
+ });
+ parser.getObj();
+ updateEntries = true;
+ } catch (ex) {
+ if (ex instanceof ParserEOFException) {
+ warn(`indexObjects -- checking object (${token}): "${ex}".`);
+ } else {
+ updateEntries = true;
+ }
+ }
+ }
+ if (updateEntries) {
+ this.entries[num] = {
+ offset: position - stream.start,
+ gen,
+ uncompressed: true
+ };
+ }
+ gEndobjRegExp.lastIndex = startPos;
+ const match = gEndobjRegExp.exec(bufferStr);
+ if (match) {
+ const endPos = gEndobjRegExp.lastIndex + 1;
+ contentLength = endPos - position;
+ if (match[1] !== "endobj") {
+ warn(`indexObjects: Found "${match[1]}" inside of another "obj", ` + 'caused by missing "endobj" -- trying to recover.');
+ contentLength -= match[1].length + 1;
+ }
+ } else {
+ contentLength = length - position;
+ }
+ const content = buffer.subarray(position, position + contentLength);
+ const xrefTagOffset = skipUntil(content, 0, xrefBytes);
+ if (xrefTagOffset < contentLength && content[xrefTagOffset + 5] < 64) {
+ xrefStms.push(position - stream.start);
+ this._xrefStms.add(position - stream.start);
+ }
+ position += contentLength;
+ } else if (token.startsWith("trailer") && (token.length === 7 || /\s/.test(token[7]))) {
+ trailers.push(position);
+ const startPos = position + token.length;
+ let contentLength;
+ gStartxrefRegExp.lastIndex = startPos;
+ const match = gStartxrefRegExp.exec(bufferStr);
+ if (match) {
+ const endPos = gStartxrefRegExp.lastIndex + 1;
+ contentLength = endPos - position;
+ if (match[1] !== "startxref") {
+ warn(`indexObjects: Found "${match[1]}" after "trailer", ` + 'caused by missing "startxref" -- trying to recover.');
+ contentLength -= match[1].length + 1;
+ }
+ } else {
+ contentLength = length - position;
+ }
+ position += contentLength;
+ } else {
+ position += token.length + 1;
+ }
+ }
+ for (const xrefStm of xrefStms) {
+ this.startXRefQueue.push(xrefStm);
+ this.readXRef(true);
+ }
+ const trailerDicts = [];
+ let isEncrypted = false;
+ for (const trailer of trailers) {
+ stream.pos = trailer;
+ const parser = new Parser({
+ lexer: new Lexer(stream),
+ xref: this,
+ allowStreams: true,
+ recoveryMode: true
+ });
+ const obj = parser.getObj();
+ if (!isCmd(obj, "trailer")) {
+ continue;
+ }
+ const dict = parser.getObj();
+ if (!(dict instanceof Dict)) {
+ continue;
+ }
+ trailerDicts.push(dict);
+ if (dict.has("Encrypt")) {
+ isEncrypted = true;
+ }
+ }
+ let trailerDict, trailerError;
+ for (const dict of [...trailerDicts, "genFallback", ...trailerDicts]) {
+ if (dict === "genFallback") {
+ if (!trailerError) {
+ break;
+ }
+ this._generationFallback = true;
+ continue;
+ }
+ let validPagesDict = false;
+ try {
+ const rootDict = dict.get("Root");
+ if (!(rootDict instanceof Dict)) {
+ continue;
+ }
+ const pagesDict = rootDict.get("Pages");
+ if (!(pagesDict instanceof Dict)) {
+ continue;
+ }
+ const pagesCount = pagesDict.get("Count");
+ if (Number.isInteger(pagesCount)) {
+ validPagesDict = true;
+ }
+ } catch (ex) {
+ trailerError = ex;
+ continue;
+ }
+ if (validPagesDict && (!isEncrypted || dict.has("Encrypt")) && dict.has("ID")) {
+ return dict;
+ }
+ trailerDict = dict;
+ }
+ if (trailerDict) {
+ return trailerDict;
+ }
+ if (this.topDict) {
+ return this.topDict;
+ }
+ throw new InvalidPDFException("Invalid PDF structure.");
+ }
+ readXRef(recoveryMode = false) {
+ const stream = this.stream;
+ const startXRefParsedCache = new Set();
+ while (this.startXRefQueue.length) {
+ try {
+ const startXRef = this.startXRefQueue[0];
+ if (startXRefParsedCache.has(startXRef)) {
+ warn("readXRef - skipping XRef table since it was already parsed.");
+ this.startXRefQueue.shift();
+ continue;
+ }
+ startXRefParsedCache.add(startXRef);
+ stream.pos = startXRef + stream.start;
+ const parser = new Parser({
+ lexer: new Lexer(stream),
+ xref: this,
+ allowStreams: true
+ });
+ let obj = parser.getObj();
+ let dict;
+ if (isCmd(obj, "xref")) {
+ dict = this.processXRefTable(parser);
+ if (!this.topDict) {
+ this.topDict = dict;
+ }
+ obj = dict.get("XRefStm");
+ if (Number.isInteger(obj) && !this._xrefStms.has(obj)) {
+ this._xrefStms.add(obj);
+ this.startXRefQueue.push(obj);
+ this.#firstXRefStmPos ??= obj;
+ }
+ } else if (Number.isInteger(obj)) {
+ if (!Number.isInteger(parser.getObj()) || !isCmd(parser.getObj(), "obj") || !((obj = parser.getObj()) instanceof BaseStream)) {
+ throw new FormatError("Invalid XRef stream");
+ }
+ dict = this.processXRefStream(obj);
+ if (!this.topDict) {
+ this.topDict = dict;
+ }
+ if (!dict) {
+ throw new FormatError("Failed to read XRef stream");
+ }
+ } else {
+ throw new FormatError("Invalid XRef stream header");
+ }
+ obj = dict.get("Prev");
+ if (Number.isInteger(obj)) {
+ this.startXRefQueue.push(obj);
+ } else if (obj instanceof Ref) {
+ this.startXRefQueue.push(obj.num);
+ }
+ } catch (e) {
+ if (e instanceof MissingDataException) {
+ throw e;
+ }
+ info("(while reading XRef): " + e);
+ }
+ this.startXRefQueue.shift();
+ }
+ if (this.topDict) {
+ return this.topDict;
+ }
+ if (recoveryMode) {
+ return undefined;
+ }
+ throw new XRefParseException();
+ }
+ get lastXRefStreamPos() {
+ return this.#firstXRefStmPos ?? (this._xrefStms.size > 0 ? Math.max(...this._xrefStms) : null);
+ }
+ getEntry(i) {
+ const xrefEntry = this.entries[i];
+ if (xrefEntry && !xrefEntry.free && xrefEntry.offset) {
+ return xrefEntry;
+ }
+ return null;
+ }
+ fetchIfRef(obj, suppressEncryption = false) {
+ if (obj instanceof Ref) {
+ return this.fetch(obj, suppressEncryption);
+ }
+ return obj;
+ }
+ fetch(ref, suppressEncryption = false) {
+ if (!(ref instanceof Ref)) {
+ throw new Error("ref object is not a reference");
+ }
+ const num = ref.num;
+ const cacheEntry = this._cacheMap.get(num);
+ if (cacheEntry !== undefined) {
+ if (cacheEntry instanceof Dict && !cacheEntry.objId) {
+ cacheEntry.objId = ref.toString();
+ }
+ return cacheEntry;
+ }
+ let xrefEntry = this.getEntry(num);
+ if (xrefEntry === null) {
+ this._cacheMap.set(num, xrefEntry);
+ return xrefEntry;
+ }
+ if (this._pendingRefs.has(ref)) {
+ this._pendingRefs.remove(ref);
+ warn(`Ignoring circular reference: ${ref}.`);
+ return CIRCULAR_REF;
+ }
+ this._pendingRefs.put(ref);
+ try {
+ xrefEntry = xrefEntry.uncompressed ? this.fetchUncompressed(ref, xrefEntry, suppressEncryption) : this.fetchCompressed(ref, xrefEntry, suppressEncryption);
+ this._pendingRefs.remove(ref);
+ } catch (ex) {
+ this._pendingRefs.remove(ref);
+ throw ex;
+ }
+ if (xrefEntry instanceof Dict) {
+ xrefEntry.objId = ref.toString();
+ } else if (xrefEntry instanceof BaseStream) {
+ xrefEntry.dict.objId = ref.toString();
+ }
+ return xrefEntry;
+ }
+ fetchUncompressed(ref, xrefEntry, suppressEncryption = false) {
+ const gen = ref.gen;
+ let num = ref.num;
+ if (xrefEntry.gen !== gen) {
+ const msg = `Inconsistent generation in XRef: ${ref}`;
+ if (this._generationFallback && xrefEntry.gen < gen) {
+ warn(msg);
+ return this.fetchUncompressed(Ref.get(num, xrefEntry.gen), xrefEntry, suppressEncryption);
+ }
+ throw new XRefEntryException(msg);
+ }
+ const stream = this.stream.makeSubStream(xrefEntry.offset + this.stream.start);
+ const parser = new Parser({
+ lexer: new Lexer(stream),
+ xref: this,
+ allowStreams: true
+ });
+ const obj1 = parser.getObj();
+ const obj2 = parser.getObj();
+ const obj3 = parser.getObj();
+ if (obj1 !== num || obj2 !== gen || !(obj3 instanceof Cmd)) {
+ throw new XRefEntryException(`Bad (uncompressed) XRef entry: ${ref}`);
+ }
+ if (obj3.cmd !== "obj") {
+ if (obj3.cmd.startsWith("obj")) {
+ num = parseInt(obj3.cmd.substring(3), 10);
+ if (!Number.isNaN(num)) {
+ return num;
+ }
+ }
+ throw new XRefEntryException(`Bad (uncompressed) XRef entry: ${ref}`);
+ }
+ xrefEntry = this.encrypt && !suppressEncryption ? parser.getObj(this.encrypt.createCipherTransform(num, gen)) : parser.getObj();
+ if (!(xrefEntry instanceof BaseStream)) {
+ this._cacheMap.set(num, xrefEntry);
+ }
+ return xrefEntry;
+ }
+ fetchCompressed(ref, xrefEntry, suppressEncryption = false) {
+ const tableOffset = xrefEntry.offset;
+ const stream = this.fetch(Ref.get(tableOffset, 0));
+ if (!(stream instanceof BaseStream)) {
+ throw new FormatError("bad ObjStm stream");
+ }
+ const first = stream.dict.get("First");
+ const n = stream.dict.get("N");
+ if (!Number.isInteger(first) || !Number.isInteger(n)) {
+ throw new FormatError("invalid first and n parameters for ObjStm stream");
+ }
+ let parser = new Parser({
+ lexer: new Lexer(stream),
+ xref: this,
+ allowStreams: true
+ });
+ const nums = new Array(n);
+ const offsets = new Array(n);
+ for (let i = 0; i < n; ++i) {
+ const num = parser.getObj();
+ if (!Number.isInteger(num)) {
+ throw new FormatError(`invalid object number in the ObjStm stream: ${num}`);
+ }
+ const offset = parser.getObj();
+ if (!Number.isInteger(offset)) {
+ throw new FormatError(`invalid object offset in the ObjStm stream: ${offset}`);
+ }
+ nums[i] = num;
+ offsets[i] = offset;
+ }
+ const start = (stream.start || 0) + first;
+ const entries = new Array(n);
+ for (let i = 0; i < n; ++i) {
+ const length = i < n - 1 ? offsets[i + 1] - offsets[i] : undefined;
+ if (length < 0) {
+ throw new FormatError("Invalid offset in the ObjStm stream.");
+ }
+ parser = new Parser({
+ lexer: new Lexer(stream.makeSubStream(start + offsets[i], length, stream.dict)),
+ xref: this,
+ allowStreams: true
+ });
+ const obj = parser.getObj();
+ entries[i] = obj;
+ if (obj instanceof BaseStream) {
+ continue;
+ }
+ const num = nums[i],
+ entry = this.entries[num];
+ if (entry && entry.offset === tableOffset && entry.gen === i) {
+ this._cacheMap.set(num, obj);
+ }
+ }
+ xrefEntry = entries[xrefEntry.gen];
+ if (xrefEntry === undefined) {
+ throw new XRefEntryException(`Bad (compressed) XRef entry: ${ref}`);
+ }
+ return xrefEntry;
+ }
+ async fetchIfRefAsync(obj, suppressEncryption) {
+ if (obj instanceof Ref) {
+ return this.fetchAsync(obj, suppressEncryption);
+ }
+ return obj;
+ }
+ async fetchAsync(ref, suppressEncryption) {
+ try {
+ return this.fetch(ref, suppressEncryption);
+ } catch (ex) {
+ if (!(ex instanceof MissingDataException)) {
+ throw ex;
+ }
+ await this.pdfManager.requestRange(ex.begin, ex.end);
+ return this.fetchAsync(ref, suppressEncryption);
+ }
+ }
+ getCatalogObj() {
+ return this.root;
+ }
+}
+
+;// CONCATENATED MODULE: ./src/core/document.js
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+const DEFAULT_USER_UNIT = 1.0;
+const LETTER_SIZE_MEDIABOX = [0, 0, 612, 792];
+class Page {
+ constructor({
+ pdfManager,
+ xref,
+ pageIndex,
+ pageDict,
+ ref,
+ globalIdFactory,
+ fontCache,
+ builtInCMapCache,
+ standardFontDataCache,
+ globalImageCache,
+ systemFontCache,
+ nonBlendModesSet,
+ xfaFactory
+ }) {
+ this.pdfManager = pdfManager;
+ this.pageIndex = pageIndex;
+ this.pageDict = pageDict;
+ this.xref = xref;
+ this.ref = ref;
+ this.fontCache = fontCache;
+ this.builtInCMapCache = builtInCMapCache;
+ this.standardFontDataCache = standardFontDataCache;
+ this.globalImageCache = globalImageCache;
+ this.systemFontCache = systemFontCache;
+ this.nonBlendModesSet = nonBlendModesSet;
+ this.evaluatorOptions = pdfManager.evaluatorOptions;
+ this.resourcesPromise = null;
+ this.xfaFactory = xfaFactory;
+ const idCounters = {
+ obj: 0
+ };
+ this._localIdFactory = class extends globalIdFactory {
+ static createObjId() {
+ return `p${pageIndex}_${++idCounters.obj}`;
+ }
+ static getPageObjId() {
+ return `p${ref.toString()}`;
+ }
+ };
+ }
+ _getInheritableProperty(key, getArray = false) {
+ const value = getInheritableProperty({
+ dict: this.pageDict,
+ key,
+ getArray,
+ stopWhenFound: false
+ });
+ if (!Array.isArray(value)) {
+ return value;
+ }
+ if (value.length === 1 || !(value[0] instanceof Dict)) {
+ return value[0];
+ }
+ return Dict.merge({
+ xref: this.xref,
+ dictArray: value
+ });
+ }
+ get content() {
+ return this.pageDict.getArray("Contents");
+ }
+ get resources() {
+ const resources = this._getInheritableProperty("Resources");
+ return shadow(this, "resources", resources instanceof Dict ? resources : Dict.empty);
+ }
+ _getBoundingBox(name) {
+ if (this.xfaData) {
+ return this.xfaData.bbox;
+ }
+ let box = this._getInheritableProperty(name, true);
+ if (Array.isArray(box) && box.length === 4) {
+ box = Util.normalizeRect(box);
+ if (box[2] - box[0] > 0 && box[3] - box[1] > 0) {
+ return box;
+ }
+ warn(`Empty, or invalid, /${name} entry.`);
+ }
+ return null;
+ }
+ get mediaBox() {
+ return shadow(this, "mediaBox", this._getBoundingBox("MediaBox") || LETTER_SIZE_MEDIABOX);
+ }
+ get cropBox() {
+ return shadow(this, "cropBox", this._getBoundingBox("CropBox") || this.mediaBox);
+ }
+ get userUnit() {
+ let obj = this.pageDict.get("UserUnit");
+ if (typeof obj !== "number" || obj <= 0) {
+ obj = DEFAULT_USER_UNIT;
+ }
+ return shadow(this, "userUnit", obj);
+ }
+ get view() {
+ const {
+ cropBox,
+ mediaBox
+ } = this;
+ if (cropBox !== mediaBox && !isArrayEqual(cropBox, mediaBox)) {
+ const box = Util.intersect(cropBox, mediaBox);
+ if (box && box[2] - box[0] > 0 && box[3] - box[1] > 0) {
+ return shadow(this, "view", box);
+ }
+ warn("Empty /CropBox and /MediaBox intersection.");
+ }
+ return shadow(this, "view", mediaBox);
+ }
+ get rotate() {
+ let rotate = this._getInheritableProperty("Rotate") || 0;
+ if (rotate % 90 !== 0) {
+ rotate = 0;
+ } else if (rotate >= 360) {
+ rotate %= 360;
+ } else if (rotate < 0) {
+ rotate = (rotate % 360 + 360) % 360;
+ }
+ return shadow(this, "rotate", rotate);
+ }
+ _onSubStreamError(reason, objId) {
+ if (this.evaluatorOptions.ignoreErrors) {
+ warn(`getContentStream - ignoring sub-stream (${objId}): "${reason}".`);
+ return;
+ }
+ throw reason;
+ }
+ getContentStream() {
+ return this.pdfManager.ensure(this, "content").then(content => {
+ if (content instanceof BaseStream) {
+ return content;
+ }
+ if (Array.isArray(content)) {
+ return new StreamsSequenceStream(content, this._onSubStreamError.bind(this));
+ }
+ return new NullStream();
+ });
+ }
+ get xfaData() {
+ return shadow(this, "xfaData", this.xfaFactory ? {
+ bbox: this.xfaFactory.getBoundingBox(this.pageIndex)
+ } : null);
+ }
+ #replaceIdByRef(annotations, deletedAnnotations, existingAnnotations) {
+ for (const annotation of annotations) {
+ if (annotation.id) {
+ const ref = Ref.fromString(annotation.id);
+ if (!ref) {
+ warn(`A non-linked annotation cannot be modified: ${annotation.id}`);
+ continue;
+ }
+ if (annotation.deleted) {
+ deletedAnnotations.put(ref);
+ continue;
+ }
+ existingAnnotations?.put(ref);
+ annotation.ref = ref;
+ delete annotation.id;
+ }
+ }
+ }
+ async saveNewAnnotations(handler, task, annotations, imagePromises) {
+ if (this.xfaFactory) {
+ throw new Error("XFA: Cannot save new annotations.");
+ }
+ const partialEvaluator = new PartialEvaluator({
+ xref: this.xref,
+ handler,
+ pageIndex: this.pageIndex,
+ idFactory: this._localIdFactory,
+ fontCache: this.fontCache,
+ builtInCMapCache: this.builtInCMapCache,
+ standardFontDataCache: this.standardFontDataCache,
+ globalImageCache: this.globalImageCache,
+ systemFontCache: this.systemFontCache,
+ options: this.evaluatorOptions
+ });
+ const deletedAnnotations = new RefSet();
+ const existingAnnotations = new RefSet();
+ this.#replaceIdByRef(annotations, deletedAnnotations, existingAnnotations);
+ const pageDict = this.pageDict;
+ const annotationsArray = this.annotations.filter(a => !(a instanceof Ref && deletedAnnotations.has(a)));
+ const newData = await AnnotationFactory.saveNewAnnotations(partialEvaluator, task, annotations, imagePromises);
+ for (const {
+ ref
+ } of newData.annotations) {
+ if (ref instanceof Ref && !existingAnnotations.has(ref)) {
+ annotationsArray.push(ref);
+ }
+ }
+ const savedDict = pageDict.get("Annots");
+ pageDict.set("Annots", annotationsArray);
+ const buffer = [];
+ await writeObject(this.ref, pageDict, buffer, this.xref);
+ if (savedDict) {
+ pageDict.set("Annots", savedDict);
+ }
+ const objects = newData.dependencies;
+ objects.push({
+ ref: this.ref,
+ data: buffer.join("")
+ }, ...newData.annotations);
+ return objects;
+ }
+ save(handler, task, annotationStorage) {
+ const partialEvaluator = new PartialEvaluator({
+ xref: this.xref,
+ handler,
+ pageIndex: this.pageIndex,
+ idFactory: this._localIdFactory,
+ fontCache: this.fontCache,
+ builtInCMapCache: this.builtInCMapCache,
+ standardFontDataCache: this.standardFontDataCache,
+ globalImageCache: this.globalImageCache,
+ systemFontCache: this.systemFontCache,
+ options: this.evaluatorOptions
+ });
+ return this._parsedAnnotations.then(function (annotations) {
+ const newRefsPromises = [];
+ for (const annotation of annotations) {
+ if (!annotation.mustBePrinted(annotationStorage)) {
+ continue;
+ }
+ newRefsPromises.push(annotation.save(partialEvaluator, task, annotationStorage).catch(function (reason) {
+ warn("save - ignoring annotation data during " + `"${task.name}" task: "${reason}".`);
+ return null;
+ }));
+ }
+ return Promise.all(newRefsPromises).then(function (newRefs) {
+ return newRefs.filter(newRef => !!newRef);
+ });
+ });
+ }
+ loadResources(keys) {
+ if (!this.resourcesPromise) {
+ this.resourcesPromise = this.pdfManager.ensure(this, "resources");
+ }
+ return this.resourcesPromise.then(() => {
+ const objectLoader = new ObjectLoader(this.resources, keys, this.xref);
+ return objectLoader.load();
+ });
+ }
+ getOperatorList({
+ handler,
+ sink,
+ task,
+ intent,
+ cacheKey,
+ annotationStorage = null
+ }) {
+ const contentStreamPromise = this.getContentStream();
+ const resourcesPromise = this.loadResources(["ColorSpace", "ExtGState", "Font", "Pattern", "Properties", "Shading", "XObject"]);
+ const partialEvaluator = new PartialEvaluator({
+ xref: this.xref,
+ handler,
+ pageIndex: this.pageIndex,
+ idFactory: this._localIdFactory,
+ fontCache: this.fontCache,
+ builtInCMapCache: this.builtInCMapCache,
+ standardFontDataCache: this.standardFontDataCache,
+ globalImageCache: this.globalImageCache,
+ systemFontCache: this.systemFontCache,
+ options: this.evaluatorOptions
+ });
+ const newAnnotationsByPage = !this.xfaFactory ? getNewAnnotationsMap(annotationStorage) : null;
+ let deletedAnnotations = null;
+ let newAnnotationsPromise = Promise.resolve(null);
+ if (newAnnotationsByPage) {
+ const newAnnotations = newAnnotationsByPage.get(this.pageIndex);
+ if (newAnnotations) {
+ const annotationGlobalsPromise = this.pdfManager.ensureDoc("annotationGlobals");
+ let imagePromises;
+ const missingBitmaps = new Set();
+ for (const {
+ bitmapId,
+ bitmap
+ } of newAnnotations) {
+ if (bitmapId && !bitmap && !missingBitmaps.has(bitmapId)) {
+ missingBitmaps.add(bitmapId);
+ }
+ }
+ const {
+ isOffscreenCanvasSupported
+ } = this.evaluatorOptions;
+ if (missingBitmaps.size > 0) {
+ const annotationWithBitmaps = newAnnotations.slice();
+ for (const [key, annotation] of annotationStorage) {
+ if (!key.startsWith(AnnotationEditorPrefix)) {
+ continue;
+ }
+ if (annotation.bitmap && missingBitmaps.has(annotation.bitmapId)) {
+ annotationWithBitmaps.push(annotation);
+ }
+ }
+ imagePromises = AnnotationFactory.generateImages(annotationWithBitmaps, this.xref, isOffscreenCanvasSupported);
+ } else {
+ imagePromises = AnnotationFactory.generateImages(newAnnotations, this.xref, isOffscreenCanvasSupported);
+ }
+ deletedAnnotations = new RefSet();
+ this.#replaceIdByRef(newAnnotations, deletedAnnotations, null);
+ newAnnotationsPromise = annotationGlobalsPromise.then(annotationGlobals => {
+ if (!annotationGlobals) {
+ return null;
+ }
+ return AnnotationFactory.printNewAnnotations(annotationGlobals, partialEvaluator, task, newAnnotations, imagePromises);
+ });
+ }
+ }
+ const dataPromises = Promise.all([contentStreamPromise, resourcesPromise]);
+ const pageListPromise = dataPromises.then(([contentStream]) => {
+ const opList = new OperatorList(intent, sink);
+ handler.send("StartRenderPage", {
+ transparency: partialEvaluator.hasBlendModes(this.resources, this.nonBlendModesSet),
+ pageIndex: this.pageIndex,
+ cacheKey
+ });
+ return partialEvaluator.getOperatorList({
+ stream: contentStream,
+ task,
+ resources: this.resources,
+ operatorList: opList
+ }).then(function () {
+ return opList;
+ });
+ });
+ return Promise.all([pageListPromise, this._parsedAnnotations, newAnnotationsPromise]).then(function ([pageOpList, annotations, newAnnotations]) {
+ if (newAnnotations) {
+ annotations = annotations.filter(a => !(a.ref && deletedAnnotations.has(a.ref)));
+ for (let i = 0, ii = newAnnotations.length; i < ii; i++) {
+ const newAnnotation = newAnnotations[i];
+ if (newAnnotation.refToReplace) {
+ const j = annotations.findIndex(a => a.ref && isRefsEqual(a.ref, newAnnotation.refToReplace));
+ if (j >= 0) {
+ annotations.splice(j, 1, newAnnotation);
+ newAnnotations.splice(i--, 1);
+ ii--;
+ }
+ }
+ }
+ annotations = annotations.concat(newAnnotations);
+ }
+ if (annotations.length === 0 || intent & RenderingIntentFlag.ANNOTATIONS_DISABLE) {
+ pageOpList.flush(true);
+ return {
+ length: pageOpList.totalLength
+ };
+ }
+ const renderForms = !!(intent & RenderingIntentFlag.ANNOTATIONS_FORMS),
+ intentAny = !!(intent & RenderingIntentFlag.ANY),
+ intentDisplay = !!(intent & RenderingIntentFlag.DISPLAY),
+ intentPrint = !!(intent & RenderingIntentFlag.PRINT);
+ const opListPromises = [];
+ for (const annotation of annotations) {
+ if (intentAny || intentDisplay && annotation.mustBeViewed(annotationStorage, renderForms) || intentPrint && annotation.mustBePrinted(annotationStorage)) {
+ opListPromises.push(annotation.getOperatorList(partialEvaluator, task, intent, renderForms, annotationStorage).catch(function (reason) {
+ warn("getOperatorList - ignoring annotation data during " + `"${task.name}" task: "${reason}".`);
+ return {
+ opList: null,
+ separateForm: false,
+ separateCanvas: false
+ };
+ }));
+ }
+ }
+ return Promise.all(opListPromises).then(function (opLists) {
+ let form = false,
+ canvas = false;
+ for (const {
+ opList,
+ separateForm,
+ separateCanvas
+ } of opLists) {
+ pageOpList.addOpList(opList);
+ form ||= separateForm;
+ canvas ||= separateCanvas;
+ }
+ pageOpList.flush(true, {
+ form,
+ canvas
+ });
+ return {
+ length: pageOpList.totalLength
+ };
+ });
+ });
+ }
+ extractTextContent({
+ handler,
+ task,
+ includeMarkedContent,
+ disableNormalization,
+ sink
+ }) {
+ const contentStreamPromise = this.getContentStream();
+ const resourcesPromise = this.loadResources(["ExtGState", "Font", "Properties", "XObject"]);
+ const dataPromises = Promise.all([contentStreamPromise, resourcesPromise]);
+ return dataPromises.then(([contentStream]) => {
+ const partialEvaluator = new PartialEvaluator({
+ xref: this.xref,
+ handler,
+ pageIndex: this.pageIndex,
+ idFactory: this._localIdFactory,
+ fontCache: this.fontCache,
+ builtInCMapCache: this.builtInCMapCache,
+ standardFontDataCache: this.standardFontDataCache,
+ globalImageCache: this.globalImageCache,
+ systemFontCache: this.systemFontCache,
+ options: this.evaluatorOptions
+ });
+ return partialEvaluator.getTextContent({
+ stream: contentStream,
+ task,
+ resources: this.resources,
+ includeMarkedContent,
+ disableNormalization,
+ sink,
+ viewBox: this.view
+ });
+ });
+ }
+ async getStructTree() {
+ const structTreeRoot = await this.pdfManager.ensureCatalog("structTreeRoot");
+ if (!structTreeRoot) {
+ return null;
+ }
+ await this._parsedAnnotations;
+ const structTree = await this.pdfManager.ensure(this, "_parseStructTree", [structTreeRoot]);
+ return structTree.serializable;
+ }
+ _parseStructTree(structTreeRoot) {
+ const tree = new StructTreePage(structTreeRoot, this.pageDict);
+ tree.parse(this.ref);
+ return tree;
+ }
+ async getAnnotationsData(handler, task, intent) {
+ const annotations = await this._parsedAnnotations;
+ if (annotations.length === 0) {
+ return annotations;
+ }
+ const annotationsData = [],
+ textContentPromises = [];
+ let partialEvaluator;
+ const intentAny = !!(intent & RenderingIntentFlag.ANY),
+ intentDisplay = !!(intent & RenderingIntentFlag.DISPLAY),
+ intentPrint = !!(intent & RenderingIntentFlag.PRINT);
+ for (const annotation of annotations) {
+ const isVisible = intentAny || intentDisplay && annotation.viewable;
+ if (isVisible || intentPrint && annotation.printable) {
+ annotationsData.push(annotation.data);
+ }
+ if (annotation.hasTextContent && isVisible) {
+ partialEvaluator ||= new PartialEvaluator({
+ xref: this.xref,
+ handler,
+ pageIndex: this.pageIndex,
+ idFactory: this._localIdFactory,
+ fontCache: this.fontCache,
+ builtInCMapCache: this.builtInCMapCache,
+ standardFontDataCache: this.standardFontDataCache,
+ globalImageCache: this.globalImageCache,
+ systemFontCache: this.systemFontCache,
+ options: this.evaluatorOptions
+ });
+ textContentPromises.push(annotation.extractTextContent(partialEvaluator, task, [-Infinity, -Infinity, Infinity, Infinity]).catch(function (reason) {
+ warn(`getAnnotationsData - ignoring textContent during "${task.name}" task: "${reason}".`);
+ }));
+ }
+ }
+ await Promise.all(textContentPromises);
+ return annotationsData;
+ }
+ get annotations() {
+ const annots = this._getInheritableProperty("Annots");
+ return shadow(this, "annotations", Array.isArray(annots) ? annots : []);
+ }
+ get _parsedAnnotations() {
+ const promise = this.pdfManager.ensure(this, "annotations").then(async annots => {
+ if (annots.length === 0) {
+ return annots;
+ }
+ const annotationGlobals = await this.pdfManager.ensureDoc("annotationGlobals");
+ if (!annotationGlobals) {
+ return [];
+ }
+ const annotationPromises = [];
+ for (const annotationRef of annots) {
+ annotationPromises.push(AnnotationFactory.create(this.xref, annotationRef, annotationGlobals, this._localIdFactory, false, this.ref).catch(function (reason) {
+ warn(`_parsedAnnotations: "${reason}".`);
+ return null;
+ }));
+ }
+ const sortedAnnotations = [];
+ let popupAnnotations;
+ for (const annotation of await Promise.all(annotationPromises)) {
+ if (!annotation) {
+ continue;
+ }
+ if (annotation instanceof PopupAnnotation) {
+ (popupAnnotations ||= []).push(annotation);
+ continue;
+ }
+ sortedAnnotations.push(annotation);
+ }
+ if (popupAnnotations) {
+ sortedAnnotations.push(...popupAnnotations);
+ }
+ return sortedAnnotations;
+ });
+ return shadow(this, "_parsedAnnotations", promise);
+ }
+ get jsActions() {
+ const actions = collectActions(this.xref, this.pageDict, PageActionEventType);
+ return shadow(this, "jsActions", actions);
+ }
+}
+const PDF_HEADER_SIGNATURE = new Uint8Array([0x25, 0x50, 0x44, 0x46, 0x2d]);
+const STARTXREF_SIGNATURE = new Uint8Array([0x73, 0x74, 0x61, 0x72, 0x74, 0x78, 0x72, 0x65, 0x66]);
+const ENDOBJ_SIGNATURE = new Uint8Array([0x65, 0x6e, 0x64, 0x6f, 0x62, 0x6a]);
+const FINGERPRINT_FIRST_BYTES = 1024;
+const EMPTY_FINGERPRINT = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
+function find(stream, signature, limit = 1024, backwards = false) {
+ const signatureLength = signature.length;
+ const scanBytes = stream.peekBytes(limit);
+ const scanLength = scanBytes.length - signatureLength;
+ if (scanLength <= 0) {
+ return false;
+ }
+ if (backwards) {
+ const signatureEnd = signatureLength - 1;
+ let pos = scanBytes.length - 1;
+ while (pos >= signatureEnd) {
+ let j = 0;
+ while (j < signatureLength && scanBytes[pos - j] === signature[signatureEnd - j]) {
+ j++;
+ }
+ if (j >= signatureLength) {
+ stream.pos += pos - signatureEnd;
+ return true;
+ }
+ pos--;
+ }
+ } else {
+ let pos = 0;
+ while (pos <= scanLength) {
+ let j = 0;
+ while (j < signatureLength && scanBytes[pos + j] === signature[j]) {
+ j++;
+ }
+ if (j >= signatureLength) {
+ stream.pos += pos;
+ return true;
+ }
+ pos++;
+ }
+ }
+ return false;
+}
+class PDFDocument {
+ constructor(pdfManager, stream) {
+ if (stream.length <= 0) {
+ throw new InvalidPDFException("The PDF file is empty, i.e. its size is zero bytes.");
+ }
+ this.pdfManager = pdfManager;
+ this.stream = stream;
+ this.xref = new XRef(stream, pdfManager);
+ this._pagePromises = new Map();
+ this._version = null;
+ const idCounters = {
+ font: 0
+ };
+ this._globalIdFactory = class {
+ static getDocId() {
+ return `g_${pdfManager.docId}`;
+ }
+ static createFontId() {
+ return `f${++idCounters.font}`;
+ }
+ static createObjId() {
+ unreachable("Abstract method `createObjId` called.");
+ }
+ static getPageObjId() {
+ unreachable("Abstract method `getPageObjId` called.");
+ }
+ };
+ }
+ parse(recoveryMode) {
+ this.xref.parse(recoveryMode);
+ this.catalog = new Catalog(this.pdfManager, this.xref);
+ }
+ get linearization() {
+ let linearization = null;
+ try {
+ linearization = Linearization.create(this.stream);
+ } catch (err) {
+ if (err instanceof MissingDataException) {
+ throw err;
+ }
+ info(err);
+ }
+ return shadow(this, "linearization", linearization);
+ }
+ get startXRef() {
+ const stream = this.stream;
+ let startXRef = 0;
+ if (this.linearization) {
+ stream.reset();
+ if (find(stream, ENDOBJ_SIGNATURE)) {
+ stream.skip(6);
+ let ch = stream.peekByte();
+ while (isWhiteSpace(ch)) {
+ stream.pos++;
+ ch = stream.peekByte();
+ }
+ startXRef = stream.pos - stream.start;
+ }
+ } else {
+ const step = 1024;
+ const startXRefLength = STARTXREF_SIGNATURE.length;
+ let found = false,
+ pos = stream.end;
+ while (!found && pos > 0) {
+ pos -= step - startXRefLength;
+ if (pos < 0) {
+ pos = 0;
+ }
+ stream.pos = pos;
+ found = find(stream, STARTXREF_SIGNATURE, step, true);
+ }
+ if (found) {
+ stream.skip(9);
+ let ch;
+ do {
+ ch = stream.getByte();
+ } while (isWhiteSpace(ch));
+ let str = "";
+ while (ch >= 0x20 && ch <= 0x39) {
+ str += String.fromCharCode(ch);
+ ch = stream.getByte();
+ }
+ startXRef = parseInt(str, 10);
+ if (isNaN(startXRef)) {
+ startXRef = 0;
+ }
+ }
+ }
+ return shadow(this, "startXRef", startXRef);
+ }
+ checkHeader() {
+ const stream = this.stream;
+ stream.reset();
+ if (!find(stream, PDF_HEADER_SIGNATURE)) {
+ return;
+ }
+ stream.moveStart();
+ stream.skip(PDF_HEADER_SIGNATURE.length);
+ let version = "",
+ ch;
+ while ((ch = stream.getByte()) > 0x20 && version.length < 7) {
+ version += String.fromCharCode(ch);
+ }
+ if (PDF_VERSION_REGEXP.test(version)) {
+ this._version = version;
+ } else {
+ warn(`Invalid PDF header version: ${version}`);
+ }
+ }
+ parseStartXRef() {
+ this.xref.setStartXRef(this.startXRef);
+ }
+ get numPages() {
+ let num = 0;
+ if (this.catalog.hasActualNumPages) {
+ num = this.catalog.numPages;
+ } else if (this.xfaFactory) {
+ num = this.xfaFactory.getNumPages();
+ } else if (this.linearization) {
+ num = this.linearization.numPages;
+ } else {
+ num = this.catalog.numPages;
+ }
+ return shadow(this, "numPages", num);
+ }
+ _hasOnlyDocumentSignatures(fields, recursionDepth = 0) {
+ const RECURSION_LIMIT = 10;
+ if (!Array.isArray(fields)) {
+ return false;
+ }
+ return fields.every(field => {
+ field = this.xref.fetchIfRef(field);
+ if (!(field instanceof Dict)) {
+ return false;
+ }
+ if (field.has("Kids")) {
+ if (++recursionDepth > RECURSION_LIMIT) {
+ warn("_hasOnlyDocumentSignatures: maximum recursion depth reached");
+ return false;
+ }
+ return this._hasOnlyDocumentSignatures(field.get("Kids"), recursionDepth);
+ }
+ const isSignature = isName(field.get("FT"), "Sig");
+ const rectangle = field.get("Rect");
+ const isInvisible = Array.isArray(rectangle) && rectangle.every(value => value === 0);
+ return isSignature && isInvisible;
+ });
+ }
+ get _xfaStreams() {
+ const acroForm = this.catalog.acroForm;
+ if (!acroForm) {
+ return null;
+ }
+ const xfa = acroForm.get("XFA");
+ const entries = {
+ "xdp:xdp": "",
+ template: "",
+ datasets: "",
+ config: "",
+ connectionSet: "",
+ localeSet: "",
+ stylesheet: "",
+ "/xdp:xdp": ""
+ };
+ if (xfa instanceof BaseStream && !xfa.isEmpty) {
+ entries["xdp:xdp"] = xfa;
+ return entries;
+ }
+ if (!Array.isArray(xfa) || xfa.length === 0) {
+ return null;
+ }
+ for (let i = 0, ii = xfa.length; i < ii; i += 2) {
+ let name;
+ if (i === 0) {
+ name = "xdp:xdp";
+ } else if (i === ii - 2) {
+ name = "/xdp:xdp";
+ } else {
+ name = xfa[i];
+ }
+ if (!entries.hasOwnProperty(name)) {
+ continue;
+ }
+ const data = this.xref.fetchIfRef(xfa[i + 1]);
+ if (!(data instanceof BaseStream) || data.isEmpty) {
+ continue;
+ }
+ entries[name] = data;
+ }
+ return entries;
+ }
+ get xfaDatasets() {
+ const streams = this._xfaStreams;
+ if (!streams) {
+ return shadow(this, "xfaDatasets", null);
+ }
+ for (const key of ["datasets", "xdp:xdp"]) {
+ const stream = streams[key];
+ if (!stream) {
+ continue;
+ }
+ try {
+ const str = stringToUTF8String(stream.getString());
+ const data = {
+ [key]: str
+ };
+ return shadow(this, "xfaDatasets", new DatasetReader(data));
+ } catch {
+ warn("XFA - Invalid utf-8 string.");
+ break;
+ }
+ }
+ return shadow(this, "xfaDatasets", null);
+ }
+ get xfaData() {
+ const streams = this._xfaStreams;
+ if (!streams) {
+ return null;
+ }
+ const data = Object.create(null);
+ for (const [key, stream] of Object.entries(streams)) {
+ if (!stream) {
+ continue;
+ }
+ try {
+ data[key] = stringToUTF8String(stream.getString());
+ } catch {
+ warn("XFA - Invalid utf-8 string.");
+ return null;
+ }
+ }
+ return data;
+ }
+ get xfaFactory() {
+ let data;
+ if (this.pdfManager.enableXfa && this.catalog.needsRendering && this.formInfo.hasXfa && !this.formInfo.hasAcroForm) {
+ data = this.xfaData;
+ }
+ return shadow(this, "xfaFactory", data ? new XFAFactory(data) : null);
+ }
+ get isPureXfa() {
+ return this.xfaFactory ? this.xfaFactory.isValid() : false;
+ }
+ get htmlForXfa() {
+ return this.xfaFactory ? this.xfaFactory.getPages() : null;
+ }
+ async loadXfaImages() {
+ const xfaImagesDict = await this.pdfManager.ensureCatalog("xfaImages");
+ if (!xfaImagesDict) {
+ return;
+ }
+ const keys = xfaImagesDict.getKeys();
+ const objectLoader = new ObjectLoader(xfaImagesDict, keys, this.xref);
+ await objectLoader.load();
+ const xfaImages = new Map();
+ for (const key of keys) {
+ const stream = xfaImagesDict.get(key);
+ if (stream instanceof BaseStream) {
+ xfaImages.set(key, stream.getBytes());
+ }
+ }
+ this.xfaFactory.setImages(xfaImages);
+ }
+ async loadXfaFonts(handler, task) {
+ const acroForm = await this.pdfManager.ensureCatalog("acroForm");
+ if (!acroForm) {
+ return;
+ }
+ const resources = await acroForm.getAsync("DR");
+ if (!(resources instanceof Dict)) {
+ return;
+ }
+ const objectLoader = new ObjectLoader(resources, ["Font"], this.xref);
+ await objectLoader.load();
+ const fontRes = resources.get("Font");
+ if (!(fontRes instanceof Dict)) {
+ return;
+ }
+ const options = Object.assign(Object.create(null), this.pdfManager.evaluatorOptions);
+ options.useSystemFonts = false;
+ const partialEvaluator = new PartialEvaluator({
+ xref: this.xref,
+ handler,
+ pageIndex: -1,
+ idFactory: this._globalIdFactory,
+ fontCache: this.catalog.fontCache,
+ builtInCMapCache: this.catalog.builtInCMapCache,
+ standardFontDataCache: this.catalog.standardFontDataCache,
+ options
+ });
+ const operatorList = new OperatorList();
+ const pdfFonts = [];
+ const initialState = {
+ get font() {
+ return pdfFonts.at(-1);
+ },
+ set font(font) {
+ pdfFonts.push(font);
+ },
+ clone() {
+ return this;
+ }
+ };
+ const fonts = new Map();
+ fontRes.forEach((fontName, font) => {
+ fonts.set(fontName, font);
+ });
+ const promises = [];
+ for (const [fontName, font] of fonts) {
+ const descriptor = font.get("FontDescriptor");
+ if (!(descriptor instanceof Dict)) {
+ continue;
+ }
+ let fontFamily = descriptor.get("FontFamily");
+ fontFamily = fontFamily.replaceAll(/[ ]+(\d)/g, "$1");
+ const fontWeight = descriptor.get("FontWeight");
+ const italicAngle = -descriptor.get("ItalicAngle");
+ const cssFontInfo = {
+ fontFamily,
+ fontWeight,
+ italicAngle
+ };
+ if (!validateCSSFont(cssFontInfo)) {
+ continue;
+ }
+ promises.push(partialEvaluator.handleSetFont(resources, [Name.get(fontName), 1], null, operatorList, task, initialState, null, cssFontInfo).catch(function (reason) {
+ warn(`loadXfaFonts: "${reason}".`);
+ return null;
+ }));
+ }
+ await Promise.all(promises);
+ const missingFonts = this.xfaFactory.setFonts(pdfFonts);
+ if (!missingFonts) {
+ return;
+ }
+ options.ignoreErrors = true;
+ promises.length = 0;
+ pdfFonts.length = 0;
+ const reallyMissingFonts = new Set();
+ for (const missing of missingFonts) {
+ if (!getXfaFontName(`${missing}-Regular`)) {
+ reallyMissingFonts.add(missing);
+ }
+ }
+ if (reallyMissingFonts.size) {
+ missingFonts.push("PdfJS-Fallback");
+ }
+ for (const missing of missingFonts) {
+ if (reallyMissingFonts.has(missing)) {
+ continue;
+ }
+ for (const fontInfo of [{
+ name: "Regular",
+ fontWeight: 400,
+ italicAngle: 0
+ }, {
+ name: "Bold",
+ fontWeight: 700,
+ italicAngle: 0
+ }, {
+ name: "Italic",
+ fontWeight: 400,
+ italicAngle: 12
+ }, {
+ name: "BoldItalic",
+ fontWeight: 700,
+ italicAngle: 12
+ }]) {
+ const name = `${missing}-${fontInfo.name}`;
+ const dict = getXfaFontDict(name);
+ promises.push(partialEvaluator.handleSetFont(resources, [Name.get(name), 1], null, operatorList, task, initialState, dict, {
+ fontFamily: missing,
+ fontWeight: fontInfo.fontWeight,
+ italicAngle: fontInfo.italicAngle
+ }).catch(function (reason) {
+ warn(`loadXfaFonts: "${reason}".`);
+ return null;
+ }));
+ }
+ }
+ await Promise.all(promises);
+ this.xfaFactory.appendFonts(pdfFonts, reallyMissingFonts);
+ }
+ async serializeXfaData(annotationStorage) {
+ return this.xfaFactory ? this.xfaFactory.serializeData(annotationStorage) : null;
+ }
+ get version() {
+ return this.catalog.version || this._version;
+ }
+ get formInfo() {
+ const formInfo = {
+ hasFields: false,
+ hasAcroForm: false,
+ hasXfa: false,
+ hasSignatures: false
+ };
+ const acroForm = this.catalog.acroForm;
+ if (!acroForm) {
+ return shadow(this, "formInfo", formInfo);
+ }
+ try {
+ const fields = acroForm.get("Fields");
+ const hasFields = Array.isArray(fields) && fields.length > 0;
+ formInfo.hasFields = hasFields;
+ const xfa = acroForm.get("XFA");
+ formInfo.hasXfa = Array.isArray(xfa) && xfa.length > 0 || xfa instanceof BaseStream && !xfa.isEmpty;
+ const sigFlags = acroForm.get("SigFlags");
+ const hasSignatures = !!(sigFlags & 0x1);
+ const hasOnlyDocumentSignatures = hasSignatures && this._hasOnlyDocumentSignatures(fields);
+ formInfo.hasAcroForm = hasFields && !hasOnlyDocumentSignatures;
+ formInfo.hasSignatures = hasSignatures;
+ } catch (ex) {
+ if (ex instanceof MissingDataException) {
+ throw ex;
+ }
+ warn(`Cannot fetch form information: "${ex}".`);
+ }
+ return shadow(this, "formInfo", formInfo);
+ }
+ get documentInfo() {
+ const docInfo = {
+ PDFFormatVersion: this.version,
+ Language: this.catalog.lang,
+ EncryptFilterName: this.xref.encrypt ? this.xref.encrypt.filterName : null,
+ IsLinearized: !!this.linearization,
+ IsAcroFormPresent: this.formInfo.hasAcroForm,
+ IsXFAPresent: this.formInfo.hasXfa,
+ IsCollectionPresent: !!this.catalog.collection,
+ IsSignaturesPresent: this.formInfo.hasSignatures
+ };
+ let infoDict;
+ try {
+ infoDict = this.xref.trailer.get("Info");
+ } catch (err) {
+ if (err instanceof MissingDataException) {
+ throw err;
+ }
+ info("The document information dictionary is invalid.");
+ }
+ if (!(infoDict instanceof Dict)) {
+ return shadow(this, "documentInfo", docInfo);
+ }
+ for (const key of infoDict.getKeys()) {
+ const value = infoDict.get(key);
+ switch (key) {
+ case "Title":
+ case "Author":
+ case "Subject":
+ case "Keywords":
+ case "Creator":
+ case "Producer":
+ case "CreationDate":
+ case "ModDate":
+ if (typeof value === "string") {
+ docInfo[key] = stringToPDFString(value);
+ continue;
+ }
+ break;
+ case "Trapped":
+ if (value instanceof Name) {
+ docInfo[key] = value;
+ continue;
+ }
+ break;
+ default:
+ let customValue;
+ switch (typeof value) {
+ case "string":
+ customValue = stringToPDFString(value);
+ break;
+ case "number":
+ case "boolean":
+ customValue = value;
+ break;
+ default:
+ if (value instanceof Name) {
+ customValue = value;
+ }
+ break;
+ }
+ if (customValue === undefined) {
+ warn(`Bad value, for custom key "${key}", in Info: ${value}.`);
+ continue;
+ }
+ if (!docInfo.Custom) {
+ docInfo.Custom = Object.create(null);
+ }
+ docInfo.Custom[key] = customValue;
+ continue;
+ }
+ warn(`Bad value, for key "${key}", in Info: ${value}.`);
+ }
+ return shadow(this, "documentInfo", docInfo);
+ }
+ get fingerprints() {
+ function validate(data) {
+ return typeof data === "string" && data.length > 0 && data !== EMPTY_FINGERPRINT;
+ }
+ function hexString(hash) {
+ const buf = [];
+ for (const num of hash) {
+ const hex = num.toString(16);
+ buf.push(hex.padStart(2, "0"));
+ }
+ return buf.join("");
+ }
+ const idArray = this.xref.trailer.get("ID");
+ let hashOriginal, hashModified;
+ if (Array.isArray(idArray) && validate(idArray[0])) {
+ hashOriginal = stringToBytes(idArray[0]);
+ if (idArray[1] !== idArray[0] && validate(idArray[1])) {
+ hashModified = stringToBytes(idArray[1]);
+ }
+ } else {
+ hashOriginal = calculateMD5(this.stream.getByteRange(0, FINGERPRINT_FIRST_BYTES), 0, FINGERPRINT_FIRST_BYTES);
+ }
+ return shadow(this, "fingerprints", [hexString(hashOriginal), hashModified ? hexString(hashModified) : null]);
+ }
+ async _getLinearizationPage(pageIndex) {
+ const {
+ catalog,
+ linearization,
+ xref
+ } = this;
+ const ref = Ref.get(linearization.objectNumberFirst, 0);
+ try {
+ const obj = await xref.fetchAsync(ref);
+ if (obj instanceof Dict) {
+ let type = obj.getRaw("Type");
+ if (type instanceof Ref) {
+ type = await xref.fetchAsync(type);
+ }
+ if (isName(type, "Page") || !obj.has("Type") && !obj.has("Kids")) {
+ if (!catalog.pageKidsCountCache.has(ref)) {
+ catalog.pageKidsCountCache.put(ref, 1);
+ }
+ if (!catalog.pageIndexCache.has(ref)) {
+ catalog.pageIndexCache.put(ref, 0);
+ }
+ return [obj, ref];
+ }
+ }
+ throw new FormatError("The Linearization dictionary doesn't point to a valid Page dictionary.");
+ } catch (reason) {
+ warn(`_getLinearizationPage: "${reason.message}".`);
+ return catalog.getPageDict(pageIndex);
+ }
+ }
+ getPage(pageIndex) {
+ const cachedPromise = this._pagePromises.get(pageIndex);
+ if (cachedPromise) {
+ return cachedPromise;
+ }
+ const {
+ catalog,
+ linearization,
+ xfaFactory
+ } = this;
+ let promise;
+ if (xfaFactory) {
+ promise = Promise.resolve([Dict.empty, null]);
+ } else if (linearization?.pageFirst === pageIndex) {
+ promise = this._getLinearizationPage(pageIndex);
+ } else {
+ promise = catalog.getPageDict(pageIndex);
+ }
+ promise = promise.then(([pageDict, ref]) => {
+ return new Page({
+ pdfManager: this.pdfManager,
+ xref: this.xref,
+ pageIndex,
+ pageDict,
+ ref,
+ globalIdFactory: this._globalIdFactory,
+ fontCache: catalog.fontCache,
+ builtInCMapCache: catalog.builtInCMapCache,
+ standardFontDataCache: catalog.standardFontDataCache,
+ globalImageCache: catalog.globalImageCache,
+ systemFontCache: catalog.systemFontCache,
+ nonBlendModesSet: catalog.nonBlendModesSet,
+ xfaFactory
+ });
+ });
+ this._pagePromises.set(pageIndex, promise);
+ return promise;
+ }
+ async checkFirstPage(recoveryMode = false) {
+ if (recoveryMode) {
+ return;
+ }
+ try {
+ await this.getPage(0);
+ } catch (reason) {
+ if (reason instanceof XRefEntryException) {
+ this._pagePromises.delete(0);
+ await this.cleanup();
+ throw new XRefParseException();
+ }
+ }
+ }
+ async checkLastPage(recoveryMode = false) {
+ const {
+ catalog,
+ pdfManager
+ } = this;
+ catalog.setActualNumPages();
+ let numPages;
+ try {
+ await Promise.all([pdfManager.ensureDoc("xfaFactory"), pdfManager.ensureDoc("linearization"), pdfManager.ensureCatalog("numPages")]);
+ if (this.xfaFactory) {
+ return;
+ } else if (this.linearization) {
+ numPages = this.linearization.numPages;
+ } else {
+ numPages = catalog.numPages;
+ }
+ if (!Number.isInteger(numPages)) {
+ throw new FormatError("Page count is not an integer.");
+ } else if (numPages <= 1) {
+ return;
+ }
+ await this.getPage(numPages - 1);
+ } catch (reason) {
+ this._pagePromises.delete(numPages - 1);
+ await this.cleanup();
+ if (reason instanceof XRefEntryException && !recoveryMode) {
+ throw new XRefParseException();
+ }
+ warn(`checkLastPage - invalid /Pages tree /Count: ${numPages}.`);
+ let pagesTree;
+ try {
+ pagesTree = await catalog.getAllPageDicts(recoveryMode);
+ } catch (reasonAll) {
+ if (reasonAll instanceof XRefEntryException && !recoveryMode) {
+ throw new XRefParseException();
+ }
+ catalog.setActualNumPages(1);
+ return;
+ }
+ for (const [pageIndex, [pageDict, ref]] of pagesTree) {
+ let promise;
+ if (pageDict instanceof Error) {
+ promise = Promise.reject(pageDict);
+ promise.catch(() => {});
+ } else {
+ promise = Promise.resolve(new Page({
+ pdfManager,
+ xref: this.xref,
+ pageIndex,
+ pageDict,
+ ref,
+ globalIdFactory: this._globalIdFactory,
+ fontCache: catalog.fontCache,
+ builtInCMapCache: catalog.builtInCMapCache,
+ standardFontDataCache: catalog.standardFontDataCache,
+ globalImageCache: catalog.globalImageCache,
+ systemFontCache: catalog.systemFontCache,
+ nonBlendModesSet: catalog.nonBlendModesSet,
+ xfaFactory: null
+ }));
+ }
+ this._pagePromises.set(pageIndex, promise);
+ }
+ catalog.setActualNumPages(pagesTree.size);
+ }
+ }
+ fontFallback(id, handler) {
+ return this.catalog.fontFallback(id, handler);
+ }
+ async cleanup(manuallyTriggered = false) {
+ return this.catalog ? this.catalog.cleanup(manuallyTriggered) : clearGlobalCaches();
+ }
+ async #collectFieldObjects(name, fieldRef, promises, annotationGlobals, visitedRefs) {
+ const {
+ xref
+ } = this;
+ if (!(fieldRef instanceof Ref) || visitedRefs.has(fieldRef)) {
+ return;
+ }
+ visitedRefs.put(fieldRef);
+ const field = await xref.fetchAsync(fieldRef);
+ if (!(field instanceof Dict)) {
+ return;
+ }
+ if (field.has("T")) {
+ const partName = stringToPDFString(await field.getAsync("T"));
+ name = name === "" ? partName : `${name}.${partName}`;
+ } else {
+ let obj = field;
+ while (true) {
+ obj = obj.getRaw("Parent");
+ if (obj instanceof Ref) {
+ if (visitedRefs.has(obj)) {
+ break;
+ }
+ obj = await xref.fetchAsync(obj);
+ }
+ if (!(obj instanceof Dict)) {
+ break;
+ }
+ if (obj.has("T")) {
+ const partName = stringToPDFString(await obj.getAsync("T"));
+ name = name === "" ? partName : `${name}.${partName}`;
+ break;
+ }
+ }
+ }
+ if (!promises.has(name)) {
+ promises.set(name, []);
+ }
+ promises.get(name).push(AnnotationFactory.create(xref, fieldRef, annotationGlobals, null, true, null).then(annotation => annotation?.getFieldObject()).catch(function (reason) {
+ warn(`#collectFieldObjects: "${reason}".`);
+ return null;
+ }));
+ if (!field.has("Kids")) {
+ return;
+ }
+ const kids = await field.getAsync("Kids");
+ if (Array.isArray(kids)) {
+ for (const kid of kids) {
+ await this.#collectFieldObjects(name, kid, promises, annotationGlobals, visitedRefs);
+ }
+ }
+ }
+ get fieldObjects() {
+ if (!this.formInfo.hasFields) {
+ return shadow(this, "fieldObjects", Promise.resolve(null));
+ }
+ const promise = Promise.all([this.pdfManager.ensureDoc("annotationGlobals"), this.pdfManager.ensureCatalog("acroForm")]).then(async ([annotationGlobals, acroForm]) => {
+ if (!annotationGlobals) {
+ return null;
+ }
+ const visitedRefs = new RefSet();
+ const allFields = Object.create(null);
+ const fieldPromises = new Map();
+ for (const fieldRef of await acroForm.getAsync("Fields")) {
+ await this.#collectFieldObjects("", fieldRef, fieldPromises, annotationGlobals, visitedRefs);
+ }
+ const allPromises = [];
+ for (const [name, promises] of fieldPromises) {
+ allPromises.push(Promise.all(promises).then(fields => {
+ fields = fields.filter(field => !!field);
+ if (fields.length > 0) {
+ allFields[name] = fields;
+ }
+ }));
+ }
+ await Promise.all(allPromises);
+ return allFields;
+ });
+ return shadow(this, "fieldObjects", promise);
+ }
+ get hasJSActions() {
+ const promise = this.pdfManager.ensureDoc("_parseHasJSActions");
+ return shadow(this, "hasJSActions", promise);
+ }
+ async _parseHasJSActions() {
+ const [catalogJsActions, fieldObjects] = await Promise.all([this.pdfManager.ensureCatalog("jsActions"), this.pdfManager.ensureDoc("fieldObjects")]);
+ if (catalogJsActions) {
+ return true;
+ }
+ if (fieldObjects) {
+ return Object.values(fieldObjects).some(fieldObject => fieldObject.some(object => object.actions !== null));
+ }
+ return false;
+ }
+ get calculationOrderIds() {
+ const acroForm = this.catalog.acroForm;
+ if (!acroForm?.has("CO")) {
+ return shadow(this, "calculationOrderIds", null);
+ }
+ const calculationOrder = acroForm.get("CO");
+ if (!Array.isArray(calculationOrder) || calculationOrder.length === 0) {
+ return shadow(this, "calculationOrderIds", null);
+ }
+ const ids = [];
+ for (const id of calculationOrder) {
+ if (id instanceof Ref) {
+ ids.push(id.toString());
+ }
+ }
+ if (ids.length === 0) {
+ return shadow(this, "calculationOrderIds", null);
+ }
+ return shadow(this, "calculationOrderIds", ids);
+ }
+ get annotationGlobals() {
+ return shadow(this, "annotationGlobals", AnnotationFactory.createGlobals(this.pdfManager));
+ }
+}
+
+;// CONCATENATED MODULE: ./src/core/pdf_manager.js
+
+
+
+
+
+function parseDocBaseUrl(url) {
+ if (url) {
+ const absoluteUrl = createValidAbsoluteUrl(url);
+ if (absoluteUrl) {
+ return absoluteUrl.href;
+ }
+ warn(`Invalid absolute docBaseUrl: "${url}".`);
+ }
+ return null;
+}
+class BasePdfManager {
+ constructor(args) {
+ if (this.constructor === BasePdfManager) {
+ unreachable("Cannot initialize BasePdfManager.");
+ }
+ this._docBaseUrl = parseDocBaseUrl(args.docBaseUrl);
+ this._docId = args.docId;
+ this._password = args.password;
+ this.enableXfa = args.enableXfa;
+ args.evaluatorOptions.isOffscreenCanvasSupported &&= FeatureTest.isOffscreenCanvasSupported;
+ this.evaluatorOptions = args.evaluatorOptions;
+ }
+ get docId() {
+ return this._docId;
+ }
+ get password() {
+ return this._password;
+ }
+ get docBaseUrl() {
+ return this._docBaseUrl;
+ }
+ get catalog() {
+ return this.pdfDocument.catalog;
+ }
+ ensureDoc(prop, args) {
+ return this.ensure(this.pdfDocument, prop, args);
+ }
+ ensureXRef(prop, args) {
+ return this.ensure(this.pdfDocument.xref, prop, args);
+ }
+ ensureCatalog(prop, args) {
+ return this.ensure(this.pdfDocument.catalog, prop, args);
+ }
+ getPage(pageIndex) {
+ return this.pdfDocument.getPage(pageIndex);
+ }
+ fontFallback(id, handler) {
+ return this.pdfDocument.fontFallback(id, handler);
+ }
+ loadXfaFonts(handler, task) {
+ return this.pdfDocument.loadXfaFonts(handler, task);
+ }
+ loadXfaImages() {
+ return this.pdfDocument.loadXfaImages();
+ }
+ serializeXfaData(annotationStorage) {
+ return this.pdfDocument.serializeXfaData(annotationStorage);
+ }
+ cleanup(manuallyTriggered = false) {
+ return this.pdfDocument.cleanup(manuallyTriggered);
+ }
+ async ensure(obj, prop, args) {
+ unreachable("Abstract method `ensure` called");
+ }
+ requestRange(begin, end) {
+ unreachable("Abstract method `requestRange` called");
+ }
+ requestLoadedStream(noFetch = false) {
+ unreachable("Abstract method `requestLoadedStream` called");
+ }
+ sendProgressiveData(chunk) {
+ unreachable("Abstract method `sendProgressiveData` called");
+ }
+ updatePassword(password) {
+ this._password = password;
+ }
+ terminate(reason) {
+ unreachable("Abstract method `terminate` called");
+ }
+}
+class LocalPdfManager extends BasePdfManager {
+ constructor(args) {
+ super(args);
+ const stream = new Stream(args.source);
+ this.pdfDocument = new PDFDocument(this, stream);
+ this._loadedStreamPromise = Promise.resolve(stream);
+ }
+ async ensure(obj, prop, args) {
+ const value = obj[prop];
+ if (typeof value === "function") {
+ return value.apply(obj, args);
+ }
+ return value;
+ }
+ requestRange(begin, end) {
+ return Promise.resolve();
+ }
+ requestLoadedStream(noFetch = false) {
+ return this._loadedStreamPromise;
+ }
+ terminate(reason) {}
+}
+class NetworkPdfManager extends BasePdfManager {
+ constructor(args) {
+ super(args);
+ this.streamManager = new ChunkedStreamManager(args.source, {
+ msgHandler: args.handler,
+ length: args.length,
+ disableAutoFetch: args.disableAutoFetch,
+ rangeChunkSize: args.rangeChunkSize
+ });
+ this.pdfDocument = new PDFDocument(this, this.streamManager.getStream());
+ }
+ async ensure(obj, prop, args) {
+ try {
+ const value = obj[prop];
+ if (typeof value === "function") {
+ return value.apply(obj, args);
+ }
+ return value;
+ } catch (ex) {
+ if (!(ex instanceof MissingDataException)) {
+ throw ex;
+ }
+ await this.requestRange(ex.begin, ex.end);
+ return this.ensure(obj, prop, args);
+ }
+ }
+ requestRange(begin, end) {
+ return this.streamManager.requestRange(begin, end);
+ }
+ requestLoadedStream(noFetch = false) {
+ return this.streamManager.requestAllChunks(noFetch);
+ }
+ sendProgressiveData(chunk) {
+ this.streamManager.onReceiveData({
+ chunk
+ });
+ }
+ terminate(reason) {
+ this.streamManager.abort(reason);
+ }
+}
+
+;// CONCATENATED MODULE: ./src/shared/message_handler.js
+
+const CallbackKind = {
+ UNKNOWN: 0,
+ DATA: 1,
+ ERROR: 2
+};
+const StreamKind = {
+ UNKNOWN: 0,
+ CANCEL: 1,
+ CANCEL_COMPLETE: 2,
+ CLOSE: 3,
+ ENQUEUE: 4,
+ ERROR: 5,
+ PULL: 6,
+ PULL_COMPLETE: 7,
+ START_COMPLETE: 8
+};
+function wrapReason(reason) {
+ if (!(reason instanceof Error || typeof reason === "object" && reason !== null)) {
+ unreachable('wrapReason: Expected "reason" to be a (possibly cloned) Error.');
+ }
+ switch (reason.name) {
+ case "AbortException":
+ return new AbortException(reason.message);
+ case "MissingPDFException":
+ return new MissingPDFException(reason.message);
+ case "PasswordException":
+ return new PasswordException(reason.message, reason.code);
+ case "UnexpectedResponseException":
+ return new UnexpectedResponseException(reason.message, reason.status);
+ case "UnknownErrorException":
+ return new UnknownErrorException(reason.message, reason.details);
+ default:
+ return new UnknownErrorException(reason.message, reason.toString());
+ }
+}
+class MessageHandler {
+ constructor(sourceName, targetName, comObj) {
+ this.sourceName = sourceName;
+ this.targetName = targetName;
+ this.comObj = comObj;
+ this.callbackId = 1;
+ this.streamId = 1;
+ this.streamSinks = Object.create(null);
+ this.streamControllers = Object.create(null);
+ this.callbackCapabilities = Object.create(null);
+ this.actionHandler = Object.create(null);
+ this._onComObjOnMessage = event => {
+ const data = event.data;
+ if (data.targetName !== this.sourceName) {
+ return;
+ }
+ if (data.stream) {
+ this.#processStreamMessage(data);
+ return;
+ }
+ if (data.callback) {
+ const callbackId = data.callbackId;
+ const capability = this.callbackCapabilities[callbackId];
+ if (!capability) {
+ throw new Error(`Cannot resolve callback ${callbackId}`);
+ }
+ delete this.callbackCapabilities[callbackId];
+ if (data.callback === CallbackKind.DATA) {
+ capability.resolve(data.data);
+ } else if (data.callback === CallbackKind.ERROR) {
+ capability.reject(wrapReason(data.reason));
+ } else {
+ throw new Error("Unexpected callback case");
+ }
+ return;
+ }
+ const action = this.actionHandler[data.action];
+ if (!action) {
+ throw new Error(`Unknown action from worker: ${data.action}`);
+ }
+ if (data.callbackId) {
+ const cbSourceName = this.sourceName;
+ const cbTargetName = data.sourceName;
+ new Promise(function (resolve) {
+ resolve(action(data.data));
+ }).then(function (result) {
+ comObj.postMessage({
+ sourceName: cbSourceName,
+ targetName: cbTargetName,
+ callback: CallbackKind.DATA,
+ callbackId: data.callbackId,
+ data: result
+ });
+ }, function (reason) {
+ comObj.postMessage({
+ sourceName: cbSourceName,
+ targetName: cbTargetName,
+ callback: CallbackKind.ERROR,
+ callbackId: data.callbackId,
+ reason: wrapReason(reason)
+ });
+ });
+ return;
+ }
+ if (data.streamId) {
+ this.#createStreamSink(data);
+ return;
+ }
+ action(data.data);
+ };
+ comObj.addEventListener("message", this._onComObjOnMessage);
+ }
+ on(actionName, handler) {
+ const ah = this.actionHandler;
+ if (ah[actionName]) {
+ throw new Error(`There is already an actionName called "${actionName}"`);
+ }
+ ah[actionName] = handler;
+ }
+ send(actionName, data, transfers) {
+ this.comObj.postMessage({
+ sourceName: this.sourceName,
+ targetName: this.targetName,
+ action: actionName,
+ data
+ }, transfers);
+ }
+ sendWithPromise(actionName, data, transfers) {
+ const callbackId = this.callbackId++;
+ const capability = new PromiseCapability();
+ this.callbackCapabilities[callbackId] = capability;
+ try {
+ this.comObj.postMessage({
+ sourceName: this.sourceName,
+ targetName: this.targetName,
+ action: actionName,
+ callbackId,
+ data
+ }, transfers);
+ } catch (ex) {
+ capability.reject(ex);
+ }
+ return capability.promise;
+ }
+ sendWithStream(actionName, data, queueingStrategy, transfers) {
+ const streamId = this.streamId++,
+ sourceName = this.sourceName,
+ targetName = this.targetName,
+ comObj = this.comObj;
+ return new ReadableStream({
+ start: controller => {
+ const startCapability = new PromiseCapability();
+ this.streamControllers[streamId] = {
+ controller,
+ startCall: startCapability,
+ pullCall: null,
+ cancelCall: null,
+ isClosed: false
+ };
+ comObj.postMessage({
+ sourceName,
+ targetName,
+ action: actionName,
+ streamId,
+ data,
+ desiredSize: controller.desiredSize
+ }, transfers);
+ return startCapability.promise;
+ },
+ pull: controller => {
+ const pullCapability = new PromiseCapability();
+ this.streamControllers[streamId].pullCall = pullCapability;
+ comObj.postMessage({
+ sourceName,
+ targetName,
+ stream: StreamKind.PULL,
+ streamId,
+ desiredSize: controller.desiredSize
+ });
+ return pullCapability.promise;
+ },
+ cancel: reason => {
+ assert(reason instanceof Error, "cancel must have a valid reason");
+ const cancelCapability = new PromiseCapability();
+ this.streamControllers[streamId].cancelCall = cancelCapability;
+ this.streamControllers[streamId].isClosed = true;
+ comObj.postMessage({
+ sourceName,
+ targetName,
+ stream: StreamKind.CANCEL,
+ streamId,
+ reason: wrapReason(reason)
+ });
+ return cancelCapability.promise;
+ }
+ }, queueingStrategy);
+ }
+ #createStreamSink(data) {
+ const streamId = data.streamId,
+ sourceName = this.sourceName,
+ targetName = data.sourceName,
+ comObj = this.comObj;
+ const self = this,
+ action = this.actionHandler[data.action];
+ const streamSink = {
+ enqueue(chunk, size = 1, transfers) {
+ if (this.isCancelled) {
+ return;
+ }
+ const lastDesiredSize = this.desiredSize;
+ this.desiredSize -= size;
+ if (lastDesiredSize > 0 && this.desiredSize <= 0) {
+ this.sinkCapability = new PromiseCapability();
+ this.ready = this.sinkCapability.promise;
+ }
+ comObj.postMessage({
+ sourceName,
+ targetName,
+ stream: StreamKind.ENQUEUE,
+ streamId,
+ chunk
+ }, transfers);
+ },
+ close() {
+ if (this.isCancelled) {
+ return;
+ }
+ this.isCancelled = true;
+ comObj.postMessage({
+ sourceName,
+ targetName,
+ stream: StreamKind.CLOSE,
+ streamId
+ });
+ delete self.streamSinks[streamId];
+ },
+ error(reason) {
+ assert(reason instanceof Error, "error must have a valid reason");
+ if (this.isCancelled) {
+ return;
+ }
+ this.isCancelled = true;
+ comObj.postMessage({
+ sourceName,
+ targetName,
+ stream: StreamKind.ERROR,
+ streamId,
+ reason: wrapReason(reason)
+ });
+ },
+ sinkCapability: new PromiseCapability(),
+ onPull: null,
+ onCancel: null,
+ isCancelled: false,
+ desiredSize: data.desiredSize,
+ ready: null
+ };
+ streamSink.sinkCapability.resolve();
+ streamSink.ready = streamSink.sinkCapability.promise;
+ this.streamSinks[streamId] = streamSink;
+ new Promise(function (resolve) {
+ resolve(action(data.data, streamSink));
+ }).then(function () {
+ comObj.postMessage({
+ sourceName,
+ targetName,
+ stream: StreamKind.START_COMPLETE,
+ streamId,
+ success: true
+ });
+ }, function (reason) {
+ comObj.postMessage({
+ sourceName,
+ targetName,
+ stream: StreamKind.START_COMPLETE,
+ streamId,
+ reason: wrapReason(reason)
+ });
+ });
+ }
+ #processStreamMessage(data) {
+ const streamId = data.streamId,
+ sourceName = this.sourceName,
+ targetName = data.sourceName,
+ comObj = this.comObj;
+ const streamController = this.streamControllers[streamId],
+ streamSink = this.streamSinks[streamId];
+ switch (data.stream) {
+ case StreamKind.START_COMPLETE:
+ if (data.success) {
+ streamController.startCall.resolve();
+ } else {
+ streamController.startCall.reject(wrapReason(data.reason));
+ }
+ break;
+ case StreamKind.PULL_COMPLETE:
+ if (data.success) {
+ streamController.pullCall.resolve();
+ } else {
+ streamController.pullCall.reject(wrapReason(data.reason));
+ }
+ break;
+ case StreamKind.PULL:
+ if (!streamSink) {
+ comObj.postMessage({
+ sourceName,
+ targetName,
+ stream: StreamKind.PULL_COMPLETE,
+ streamId,
+ success: true
+ });
+ break;
+ }
+ if (streamSink.desiredSize <= 0 && data.desiredSize > 0) {
+ streamSink.sinkCapability.resolve();
+ }
+ streamSink.desiredSize = data.desiredSize;
+ new Promise(function (resolve) {
+ resolve(streamSink.onPull?.());
+ }).then(function () {
+ comObj.postMessage({
+ sourceName,
+ targetName,
+ stream: StreamKind.PULL_COMPLETE,
+ streamId,
+ success: true
+ });
+ }, function (reason) {
+ comObj.postMessage({
+ sourceName,
+ targetName,
+ stream: StreamKind.PULL_COMPLETE,
+ streamId,
+ reason: wrapReason(reason)
+ });
+ });
+ break;
+ case StreamKind.ENQUEUE:
+ assert(streamController, "enqueue should have stream controller");
+ if (streamController.isClosed) {
+ break;
+ }
+ streamController.controller.enqueue(data.chunk);
+ break;
+ case StreamKind.CLOSE:
+ assert(streamController, "close should have stream controller");
+ if (streamController.isClosed) {
+ break;
+ }
+ streamController.isClosed = true;
+ streamController.controller.close();
+ this.#deleteStreamController(streamController, streamId);
+ break;
+ case StreamKind.ERROR:
+ assert(streamController, "error should have stream controller");
+ streamController.controller.error(wrapReason(data.reason));
+ this.#deleteStreamController(streamController, streamId);
+ break;
+ case StreamKind.CANCEL_COMPLETE:
+ if (data.success) {
+ streamController.cancelCall.resolve();
+ } else {
+ streamController.cancelCall.reject(wrapReason(data.reason));
+ }
+ this.#deleteStreamController(streamController, streamId);
+ break;
+ case StreamKind.CANCEL:
+ if (!streamSink) {
+ break;
+ }
+ new Promise(function (resolve) {
+ resolve(streamSink.onCancel?.(wrapReason(data.reason)));
+ }).then(function () {
+ comObj.postMessage({
+ sourceName,
+ targetName,
+ stream: StreamKind.CANCEL_COMPLETE,
+ streamId,
+ success: true
+ });
+ }, function (reason) {
+ comObj.postMessage({
+ sourceName,
+ targetName,
+ stream: StreamKind.CANCEL_COMPLETE,
+ streamId,
+ reason: wrapReason(reason)
+ });
+ });
+ streamSink.sinkCapability.reject(wrapReason(data.reason));
+ streamSink.isCancelled = true;
+ delete this.streamSinks[streamId];
+ break;
+ default:
+ throw new Error("Unexpected stream case");
+ }
+ }
+ async #deleteStreamController(streamController, streamId) {
+ await Promise.allSettled([streamController.startCall?.promise, streamController.pullCall?.promise, streamController.cancelCall?.promise]);
+ delete this.streamControllers[streamId];
+ }
+ destroy() {
+ this.comObj.removeEventListener("message", this._onComObjOnMessage);
+ }
+}
+
+;// CONCATENATED MODULE: ./src/core/worker_stream.js
+
+class PDFWorkerStream {
+ constructor(msgHandler) {
+ this._msgHandler = msgHandler;
+ this._contentLength = null;
+ this._fullRequestReader = null;
+ this._rangeRequestReaders = [];
+ }
+ getFullReader() {
+ assert(!this._fullRequestReader, "PDFWorkerStream.getFullReader can only be called once.");
+ this._fullRequestReader = new PDFWorkerStreamReader(this._msgHandler);
+ return this._fullRequestReader;
+ }
+ getRangeReader(begin, end) {
+ const reader = new PDFWorkerStreamRangeReader(begin, end, this._msgHandler);
+ this._rangeRequestReaders.push(reader);
+ return reader;
+ }
+ cancelAllRequests(reason) {
+ this._fullRequestReader?.cancel(reason);
+ for (const reader of this._rangeRequestReaders.slice(0)) {
+ reader.cancel(reason);
+ }
+ }
+}
+class PDFWorkerStreamReader {
+ constructor(msgHandler) {
+ this._msgHandler = msgHandler;
+ this.onProgress = null;
+ this._contentLength = null;
+ this._isRangeSupported = false;
+ this._isStreamingSupported = false;
+ const readableStream = this._msgHandler.sendWithStream("GetReader");
+ this._reader = readableStream.getReader();
+ this._headersReady = this._msgHandler.sendWithPromise("ReaderHeadersReady").then(data => {
+ this._isStreamingSupported = data.isStreamingSupported;
+ this._isRangeSupported = data.isRangeSupported;
+ this._contentLength = data.contentLength;
+ });
+ }
+ get headersReady() {
+ return this._headersReady;
+ }
+ get contentLength() {
+ return this._contentLength;
+ }
+ get isStreamingSupported() {
+ return this._isStreamingSupported;
+ }
+ get isRangeSupported() {
+ return this._isRangeSupported;
+ }
+ async read() {
+ const {
+ value,
+ done
+ } = await this._reader.read();
+ if (done) {
+ return {
+ value: undefined,
+ done: true
+ };
+ }
+ return {
+ value: value.buffer,
+ done: false
+ };
+ }
+ cancel(reason) {
+ this._reader.cancel(reason);
+ }
+}
+class PDFWorkerStreamRangeReader {
+ constructor(begin, end, msgHandler) {
+ this._msgHandler = msgHandler;
+ this.onProgress = null;
+ const readableStream = this._msgHandler.sendWithStream("GetRangeReader", {
+ begin,
+ end
+ });
+ this._reader = readableStream.getReader();
+ }
+ get isStreamingSupported() {
+ return false;
+ }
+ async read() {
+ const {
+ value,
+ done
+ } = await this._reader.read();
+ if (done) {
+ return {
+ value: undefined,
+ done: true
+ };
+ }
+ return {
+ value: value.buffer,
+ done: false
+ };
+ }
+ cancel(reason) {
+ this._reader.cancel(reason);
+ }
+}
+
+;// CONCATENATED MODULE: ./src/core/worker.js
+
+
+
+
+
+
+
+
+
+
+class WorkerTask {
+ constructor(name) {
+ this.name = name;
+ this.terminated = false;
+ this._capability = new PromiseCapability();
+ }
+ get finished() {
+ return this._capability.promise;
+ }
+ finish() {
+ this._capability.resolve();
+ }
+ terminate() {
+ this.terminated = true;
+ }
+ ensureNotTerminated() {
+ if (this.terminated) {
+ throw new Error("Worker task was terminated");
+ }
+ }
+}
+class WorkerMessageHandler {
+ static setup(handler, port) {
+ let testMessageProcessed = false;
+ handler.on("test", function (data) {
+ if (testMessageProcessed) {
+ return;
+ }
+ testMessageProcessed = true;
+ handler.send("test", data instanceof Uint8Array);
+ });
+ handler.on("configure", function (data) {
+ setVerbosityLevel(data.verbosity);
+ });
+ handler.on("GetDocRequest", function (data) {
+ return WorkerMessageHandler.createDocumentHandler(data, port);
+ });
+ }
+ static createDocumentHandler(docParams, port) {
+ let pdfManager;
+ let terminated = false;
+ let cancelXHRs = null;
+ const WorkerTasks = new Set();
+ const verbosity = getVerbosityLevel();
+ const {
+ docId,
+ apiVersion
+ } = docParams;
+ const workerVersion = "4.1.249";
+ if (apiVersion !== workerVersion) {
+ throw new Error(`The API version "${apiVersion}" does not match ` + `the Worker version "${workerVersion}".`);
+ }
+ const workerHandlerName = docId + "_worker";
+ let handler = new MessageHandler(workerHandlerName, docId, port);
+ function ensureNotTerminated() {
+ if (terminated) {
+ throw new Error("Worker was terminated");
+ }
+ }
+ function startWorkerTask(task) {
+ WorkerTasks.add(task);
+ }
+ function finishWorkerTask(task) {
+ task.finish();
+ WorkerTasks.delete(task);
+ }
+ async function loadDocument(recoveryMode) {
+ await pdfManager.ensureDoc("checkHeader");
+ await pdfManager.ensureDoc("parseStartXRef");
+ await pdfManager.ensureDoc("parse", [recoveryMode]);
+ await pdfManager.ensureDoc("checkFirstPage", [recoveryMode]);
+ await pdfManager.ensureDoc("checkLastPage", [recoveryMode]);
+ const isPureXfa = await pdfManager.ensureDoc("isPureXfa");
+ if (isPureXfa) {
+ const task = new WorkerTask("loadXfaFonts");
+ startWorkerTask(task);
+ await Promise.all([pdfManager.loadXfaFonts(handler, task).catch(reason => {}).then(() => finishWorkerTask(task)), pdfManager.loadXfaImages()]);
+ }
+ const [numPages, fingerprints] = await Promise.all([pdfManager.ensureDoc("numPages"), pdfManager.ensureDoc("fingerprints")]);
+ const htmlForXfa = isPureXfa ? await pdfManager.ensureDoc("htmlForXfa") : null;
+ return {
+ numPages,
+ fingerprints,
+ htmlForXfa
+ };
+ }
+ function getPdfManager({
+ data,
+ password,
+ disableAutoFetch,
+ rangeChunkSize,
+ length,
+ docBaseUrl,
+ enableXfa,
+ evaluatorOptions
+ }) {
+ const pdfManagerArgs = {
+ source: null,
+ disableAutoFetch,
+ docBaseUrl,
+ docId,
+ enableXfa,
+ evaluatorOptions,
+ handler,
+ length,
+ password,
+ rangeChunkSize
+ };
+ const pdfManagerCapability = new PromiseCapability();
+ let newPdfManager;
+ if (data) {
+ try {
+ pdfManagerArgs.source = data;
+ newPdfManager = new LocalPdfManager(pdfManagerArgs);
+ pdfManagerCapability.resolve(newPdfManager);
+ } catch (ex) {
+ pdfManagerCapability.reject(ex);
+ }
+ return pdfManagerCapability.promise;
+ }
+ let pdfStream,
+ cachedChunks = [];
+ try {
+ pdfStream = new PDFWorkerStream(handler);
+ } catch (ex) {
+ pdfManagerCapability.reject(ex);
+ return pdfManagerCapability.promise;
+ }
+ const fullRequest = pdfStream.getFullReader();
+ fullRequest.headersReady.then(function () {
+ if (!fullRequest.isRangeSupported) {
+ return;
+ }
+ pdfManagerArgs.source = pdfStream;
+ pdfManagerArgs.length = fullRequest.contentLength;
+ pdfManagerArgs.disableAutoFetch ||= fullRequest.isStreamingSupported;
+ newPdfManager = new NetworkPdfManager(pdfManagerArgs);
+ for (const chunk of cachedChunks) {
+ newPdfManager.sendProgressiveData(chunk);
+ }
+ cachedChunks = [];
+ pdfManagerCapability.resolve(newPdfManager);
+ cancelXHRs = null;
+ }).catch(function (reason) {
+ pdfManagerCapability.reject(reason);
+ cancelXHRs = null;
+ });
+ let loaded = 0;
+ const flushChunks = function () {
+ const pdfFile = arrayBuffersToBytes(cachedChunks);
+ if (length && pdfFile.length !== length) {
+ warn("reported HTTP length is different from actual");
+ }
+ try {
+ pdfManagerArgs.source = pdfFile;
+ newPdfManager = new LocalPdfManager(pdfManagerArgs);
+ pdfManagerCapability.resolve(newPdfManager);
+ } catch (ex) {
+ pdfManagerCapability.reject(ex);
+ }
+ cachedChunks = [];
+ };
+ new Promise(function (resolve, reject) {
+ const readChunk = function ({
+ value,
+ done
+ }) {
+ try {
+ ensureNotTerminated();
+ if (done) {
+ if (!newPdfManager) {
+ flushChunks();
+ }
+ cancelXHRs = null;
+ return;
+ }
+ loaded += value.byteLength;
+ if (!fullRequest.isStreamingSupported) {
+ handler.send("DocProgress", {
+ loaded,
+ total: Math.max(loaded, fullRequest.contentLength || 0)
+ });
+ }
+ if (newPdfManager) {
+ newPdfManager.sendProgressiveData(value);
+ } else {
+ cachedChunks.push(value);
+ }
+ fullRequest.read().then(readChunk, reject);
+ } catch (e) {
+ reject(e);
+ }
+ };
+ fullRequest.read().then(readChunk, reject);
+ }).catch(function (e) {
+ pdfManagerCapability.reject(e);
+ cancelXHRs = null;
+ });
+ cancelXHRs = function (reason) {
+ pdfStream.cancelAllRequests(reason);
+ };
+ return pdfManagerCapability.promise;
+ }
+ function setupDoc(data) {
+ function onSuccess(doc) {
+ ensureNotTerminated();
+ handler.send("GetDoc", {
+ pdfInfo: doc
+ });
+ }
+ function onFailure(ex) {
+ ensureNotTerminated();
+ if (ex instanceof PasswordException) {
+ const task = new WorkerTask(`PasswordException: response ${ex.code}`);
+ startWorkerTask(task);
+ handler.sendWithPromise("PasswordRequest", ex).then(function ({
+ password
+ }) {
+ finishWorkerTask(task);
+ pdfManager.updatePassword(password);
+ pdfManagerReady();
+ }).catch(function () {
+ finishWorkerTask(task);
+ handler.send("DocException", ex);
+ });
+ } else if (ex instanceof InvalidPDFException || ex instanceof MissingPDFException || ex instanceof UnexpectedResponseException || ex instanceof UnknownErrorException) {
+ handler.send("DocException", ex);
+ } else {
+ handler.send("DocException", new UnknownErrorException(ex.message, ex.toString()));
+ }
+ }
+ function pdfManagerReady() {
+ ensureNotTerminated();
+ loadDocument(false).then(onSuccess, function (reason) {
+ ensureNotTerminated();
+ if (!(reason instanceof XRefParseException)) {
+ onFailure(reason);
+ return;
+ }
+ pdfManager.requestLoadedStream().then(function () {
+ ensureNotTerminated();
+ loadDocument(true).then(onSuccess, onFailure);
+ });
+ });
+ }
+ ensureNotTerminated();
+ getPdfManager(data).then(function (newPdfManager) {
+ if (terminated) {
+ newPdfManager.terminate(new AbortException("Worker was terminated."));
+ throw new Error("Worker was terminated");
+ }
+ pdfManager = newPdfManager;
+ pdfManager.requestLoadedStream(true).then(stream => {
+ handler.send("DataLoaded", {
+ length: stream.bytes.byteLength
+ });
+ });
+ }).then(pdfManagerReady, onFailure);
+ }
+ handler.on("GetPage", function (data) {
+ return pdfManager.getPage(data.pageIndex).then(function (page) {
+ return Promise.all([pdfManager.ensure(page, "rotate"), pdfManager.ensure(page, "ref"), pdfManager.ensure(page, "userUnit"), pdfManager.ensure(page, "view")]).then(function ([rotate, ref, userUnit, view]) {
+ return {
+ rotate,
+ ref,
+ userUnit,
+ view
+ };
+ });
+ });
+ });
+ handler.on("GetPageIndex", function (data) {
+ const pageRef = Ref.get(data.num, data.gen);
+ return pdfManager.ensureCatalog("getPageIndex", [pageRef]);
+ });
+ handler.on("GetDestinations", function (data) {
+ return pdfManager.ensureCatalog("destinations");
+ });
+ handler.on("GetDestination", function (data) {
+ return pdfManager.ensureCatalog("getDestination", [data.id]);
+ });
+ handler.on("GetPageLabels", function (data) {
+ return pdfManager.ensureCatalog("pageLabels");
+ });
+ handler.on("GetPageLayout", function (data) {
+ return pdfManager.ensureCatalog("pageLayout");
+ });
+ handler.on("GetPageMode", function (data) {
+ return pdfManager.ensureCatalog("pageMode");
+ });
+ handler.on("GetViewerPreferences", function (data) {
+ return pdfManager.ensureCatalog("viewerPreferences");
+ });
+ handler.on("GetOpenAction", function (data) {
+ return pdfManager.ensureCatalog("openAction");
+ });
+ handler.on("GetAttachments", function (data) {
+ return pdfManager.ensureCatalog("attachments");
+ });
+ handler.on("GetDocJSActions", function (data) {
+ return pdfManager.ensureCatalog("jsActions");
+ });
+ handler.on("GetPageJSActions", function ({
+ pageIndex
+ }) {
+ return pdfManager.getPage(pageIndex).then(function (page) {
+ return pdfManager.ensure(page, "jsActions");
+ });
+ });
+ handler.on("GetOutline", function (data) {
+ return pdfManager.ensureCatalog("documentOutline");
+ });
+ handler.on("GetOptionalContentConfig", function (data) {
+ return pdfManager.ensureCatalog("optionalContentConfig");
+ });
+ handler.on("GetPermissions", function (data) {
+ return pdfManager.ensureCatalog("permissions");
+ });
+ handler.on("GetMetadata", function (data) {
+ return Promise.all([pdfManager.ensureDoc("documentInfo"), pdfManager.ensureCatalog("metadata")]);
+ });
+ handler.on("GetMarkInfo", function (data) {
+ return pdfManager.ensureCatalog("markInfo");
+ });
+ handler.on("GetData", function (data) {
+ return pdfManager.requestLoadedStream().then(function (stream) {
+ return stream.bytes;
+ });
+ });
+ handler.on("GetAnnotations", function ({
+ pageIndex,
+ intent
+ }) {
+ return pdfManager.getPage(pageIndex).then(function (page) {
+ const task = new WorkerTask(`GetAnnotations: page ${pageIndex}`);
+ startWorkerTask(task);
+ return page.getAnnotationsData(handler, task, intent).then(data => {
+ finishWorkerTask(task);
+ return data;
+ }, reason => {
+ finishWorkerTask(task);
+ throw reason;
+ });
+ });
+ });
+ handler.on("GetFieldObjects", function (data) {
+ return pdfManager.ensureDoc("fieldObjects");
+ });
+ handler.on("HasJSActions", function (data) {
+ return pdfManager.ensureDoc("hasJSActions");
+ });
+ handler.on("GetCalculationOrderIds", function (data) {
+ return pdfManager.ensureDoc("calculationOrderIds");
+ });
+ handler.on("SaveDocument", async function ({
+ isPureXfa,
+ numPages,
+ annotationStorage,
+ filename
+ }) {
+ const globalPromises = [pdfManager.requestLoadedStream(), pdfManager.ensureCatalog("acroForm"), pdfManager.ensureCatalog("acroFormRef"), pdfManager.ensureDoc("startXRef"), pdfManager.ensureDoc("xref"), pdfManager.ensureDoc("linearization"), pdfManager.ensureCatalog("structTreeRoot")];
+ const promises = [];
+ const newAnnotationsByPage = !isPureXfa ? getNewAnnotationsMap(annotationStorage) : null;
+ const [stream, acroForm, acroFormRef, startXRef, xref, linearization, _structTreeRoot] = await Promise.all(globalPromises);
+ const catalogRef = xref.trailer.getRaw("Root") || null;
+ let structTreeRoot;
+ if (newAnnotationsByPage) {
+ if (!_structTreeRoot) {
+ if (await StructTreeRoot.canCreateStructureTree({
+ catalogRef,
+ pdfManager,
+ newAnnotationsByPage
+ })) {
+ structTreeRoot = null;
+ }
+ } else if (await _structTreeRoot.canUpdateStructTree({
+ pdfManager,
+ xref,
+ newAnnotationsByPage
+ })) {
+ structTreeRoot = _structTreeRoot;
+ }
+ const imagePromises = AnnotationFactory.generateImages(annotationStorage.values(), xref, pdfManager.evaluatorOptions.isOffscreenCanvasSupported);
+ const newAnnotationPromises = structTreeRoot === undefined ? promises : [];
+ for (const [pageIndex, annotations] of newAnnotationsByPage) {
+ newAnnotationPromises.push(pdfManager.getPage(pageIndex).then(page => {
+ const task = new WorkerTask(`Save (editor): page ${pageIndex}`);
+ return page.saveNewAnnotations(handler, task, annotations, imagePromises).finally(function () {
+ finishWorkerTask(task);
+ });
+ }));
+ }
+ if (structTreeRoot === null) {
+ promises.push(Promise.all(newAnnotationPromises).then(async newRefs => {
+ await StructTreeRoot.createStructureTree({
+ newAnnotationsByPage,
+ xref,
+ catalogRef,
+ pdfManager,
+ newRefs
+ });
+ return newRefs;
+ }));
+ } else if (structTreeRoot) {
+ promises.push(Promise.all(newAnnotationPromises).then(async newRefs => {
+ await structTreeRoot.updateStructureTree({
+ newAnnotationsByPage,
+ pdfManager,
+ newRefs
+ });
+ return newRefs;
+ }));
+ }
+ }
+ if (isPureXfa) {
+ promises.push(pdfManager.serializeXfaData(annotationStorage));
+ } else {
+ for (let pageIndex = 0; pageIndex < numPages; pageIndex++) {
+ promises.push(pdfManager.getPage(pageIndex).then(function (page) {
+ const task = new WorkerTask(`Save: page ${pageIndex}`);
+ return page.save(handler, task, annotationStorage).finally(function () {
+ finishWorkerTask(task);
+ });
+ }));
+ }
+ }
+ const refs = await Promise.all(promises);
+ let newRefs = [];
+ let xfaData = null;
+ if (isPureXfa) {
+ xfaData = refs[0];
+ if (!xfaData) {
+ return stream.bytes;
+ }
+ } else {
+ newRefs = refs.flat(2);
+ if (newRefs.length === 0) {
+ return stream.bytes;
+ }
+ }
+ const needAppearances = acroFormRef && acroForm instanceof Dict && newRefs.some(ref => ref.needAppearances);
+ const xfa = acroForm instanceof Dict && acroForm.get("XFA") || null;
+ let xfaDatasetsRef = null;
+ let hasXfaDatasetsEntry = false;
+ if (Array.isArray(xfa)) {
+ for (let i = 0, ii = xfa.length; i < ii; i += 2) {
+ if (xfa[i] === "datasets") {
+ xfaDatasetsRef = xfa[i + 1];
+ hasXfaDatasetsEntry = true;
+ }
+ }
+ if (xfaDatasetsRef === null) {
+ xfaDatasetsRef = xref.getNewTemporaryRef();
+ }
+ } else if (xfa) {
+ warn("Unsupported XFA type.");
+ }
+ let newXrefInfo = Object.create(null);
+ if (xref.trailer) {
+ const infoObj = Object.create(null);
+ const xrefInfo = xref.trailer.get("Info") || null;
+ if (xrefInfo instanceof Dict) {
+ xrefInfo.forEach((key, value) => {
+ if (typeof value === "string") {
+ infoObj[key] = stringToPDFString(value);
+ }
+ });
+ }
+ newXrefInfo = {
+ rootRef: catalogRef,
+ encryptRef: xref.trailer.getRaw("Encrypt") || null,
+ newRef: xref.getNewTemporaryRef(),
+ infoRef: xref.trailer.getRaw("Info") || null,
+ info: infoObj,
+ fileIds: xref.trailer.get("ID") || null,
+ startXRef: linearization ? startXRef : xref.lastXRefStreamPos ?? startXRef,
+ filename
+ };
+ }
+ return incrementalUpdate({
+ originalData: stream.bytes,
+ xrefInfo: newXrefInfo,
+ newRefs,
+ xref,
+ hasXfa: !!xfa,
+ xfaDatasetsRef,
+ hasXfaDatasetsEntry,
+ needAppearances,
+ acroFormRef,
+ acroForm,
+ xfaData,
+ useXrefStream: isDict(xref.topDict, "XRef")
+ }).finally(() => {
+ xref.resetNewTemporaryRef();
+ });
+ });
+ handler.on("GetOperatorList", function (data, sink) {
+ const pageIndex = data.pageIndex;
+ pdfManager.getPage(pageIndex).then(function (page) {
+ const task = new WorkerTask(`GetOperatorList: page ${pageIndex}`);
+ startWorkerTask(task);
+ const start = verbosity >= VerbosityLevel.INFOS ? Date.now() : 0;
+ page.getOperatorList({
+ handler,
+ sink,
+ task,
+ intent: data.intent,
+ cacheKey: data.cacheKey,
+ annotationStorage: data.annotationStorage
+ }).then(function (operatorListInfo) {
+ finishWorkerTask(task);
+ if (start) {
+ info(`page=${pageIndex + 1} - getOperatorList: time=` + `${Date.now() - start}ms, len=${operatorListInfo.length}`);
+ }
+ sink.close();
+ }, function (reason) {
+ finishWorkerTask(task);
+ if (task.terminated) {
+ return;
+ }
+ sink.error(reason);
+ });
+ });
+ });
+ handler.on("GetTextContent", function (data, sink) {
+ const {
+ pageIndex,
+ includeMarkedContent,
+ disableNormalization
+ } = data;
+ pdfManager.getPage(pageIndex).then(function (page) {
+ const task = new WorkerTask("GetTextContent: page " + pageIndex);
+ startWorkerTask(task);
+ const start = verbosity >= VerbosityLevel.INFOS ? Date.now() : 0;
+ page.extractTextContent({
+ handler,
+ task,
+ sink,
+ includeMarkedContent,
+ disableNormalization
+ }).then(function () {
+ finishWorkerTask(task);
+ if (start) {
+ info(`page=${pageIndex + 1} - getTextContent: time=` + `${Date.now() - start}ms`);
+ }
+ sink.close();
+ }, function (reason) {
+ finishWorkerTask(task);
+ if (task.terminated) {
+ return;
+ }
+ sink.error(reason);
+ });
+ });
+ });
+ handler.on("GetStructTree", function (data) {
+ return pdfManager.getPage(data.pageIndex).then(function (page) {
+ return pdfManager.ensure(page, "getStructTree");
+ });
+ });
+ handler.on("FontFallback", function (data) {
+ return pdfManager.fontFallback(data.id, handler);
+ });
+ handler.on("Cleanup", function (data) {
+ return pdfManager.cleanup(true);
+ });
+ handler.on("Terminate", function (data) {
+ terminated = true;
+ const waitOn = [];
+ if (pdfManager) {
+ pdfManager.terminate(new AbortException("Worker was terminated."));
+ const cleanupPromise = pdfManager.cleanup();
+ waitOn.push(cleanupPromise);
+ pdfManager = null;
+ } else {
+ clearGlobalCaches();
+ }
+ if (cancelXHRs) {
+ cancelXHRs(new AbortException("Worker was terminated."));
+ }
+ for (const task of WorkerTasks) {
+ waitOn.push(task.finished);
+ task.terminate();
+ }
+ return Promise.all(waitOn).then(function () {
+ handler.destroy();
+ handler = null;
+ });
+ });
+ handler.on("Ready", function (data) {
+ setupDoc(docParams);
+ docParams = null;
+ });
+ return workerHandlerName;
+ }
+ static initializeFromPort(port) {
+ const handler = new MessageHandler("worker", "main", port);
+ WorkerMessageHandler.setup(handler, port);
+ handler.send("ready", null);
+ }
+}
+function isMessagePort(maybePort) {
+ return typeof maybePort.postMessage === "function" && "onmessage" in maybePort;
+}
+if (typeof window === "undefined" && !isNodeJS && typeof self !== "undefined" && isMessagePort(self)) {
+ WorkerMessageHandler.initializeFromPort(self);
+}
+
+;// CONCATENATED MODULE: ./src/pdf.worker.js
+
+const pdfjsVersion = "4.1.249";
+const pdfjsBuild = "d07f37f44";
+
+var __webpack_exports__WorkerMessageHandler = __webpack_exports__.WorkerMessageHandler;
+export { __webpack_exports__WorkerMessageHandler as WorkerMessageHandler };
diff --git a/toolkit/components/pdfjs/content/web/cmaps/78-EUC-H.bcmap b/toolkit/components/pdfjs/content/web/cmaps/78-EUC-H.bcmap
new file mode 100644
index 0000000000..2655fc70ae
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/78-EUC-H.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/78-EUC-V.bcmap b/toolkit/components/pdfjs/content/web/cmaps/78-EUC-V.bcmap
new file mode 100644
index 0000000000..f1ed853828
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/78-EUC-V.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/78-H.bcmap b/toolkit/components/pdfjs/content/web/cmaps/78-H.bcmap
new file mode 100644
index 0000000000..39e89d3339
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/78-H.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/78-RKSJ-H.bcmap b/toolkit/components/pdfjs/content/web/cmaps/78-RKSJ-H.bcmap
new file mode 100644
index 0000000000..e4167cb51f
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/78-RKSJ-H.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/78-RKSJ-V.bcmap b/toolkit/components/pdfjs/content/web/cmaps/78-RKSJ-V.bcmap
new file mode 100644
index 0000000000..50b1646e94
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/78-RKSJ-V.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/78-V.bcmap b/toolkit/components/pdfjs/content/web/cmaps/78-V.bcmap
new file mode 100644
index 0000000000..d7af99b5e2
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/78-V.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/78ms-RKSJ-H.bcmap b/toolkit/components/pdfjs/content/web/cmaps/78ms-RKSJ-H.bcmap
new file mode 100644
index 0000000000..37077d01e2
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/78ms-RKSJ-H.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/78ms-RKSJ-V.bcmap b/toolkit/components/pdfjs/content/web/cmaps/78ms-RKSJ-V.bcmap
new file mode 100644
index 0000000000..acf23231ae
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/78ms-RKSJ-V.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/83pv-RKSJ-H.bcmap b/toolkit/components/pdfjs/content/web/cmaps/83pv-RKSJ-H.bcmap
new file mode 100644
index 0000000000..2359bc529d
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/83pv-RKSJ-H.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/90ms-RKSJ-H.bcmap b/toolkit/components/pdfjs/content/web/cmaps/90ms-RKSJ-H.bcmap
new file mode 100644
index 0000000000..af8293829c
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/90ms-RKSJ-H.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/90ms-RKSJ-V.bcmap b/toolkit/components/pdfjs/content/web/cmaps/90ms-RKSJ-V.bcmap
new file mode 100644
index 0000000000..780549de19
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/90ms-RKSJ-V.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/90msp-RKSJ-H.bcmap b/toolkit/components/pdfjs/content/web/cmaps/90msp-RKSJ-H.bcmap
new file mode 100644
index 0000000000..bfd3119c62
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/90msp-RKSJ-H.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/90msp-RKSJ-V.bcmap b/toolkit/components/pdfjs/content/web/cmaps/90msp-RKSJ-V.bcmap
new file mode 100644
index 0000000000..25ef14ab4a
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/90msp-RKSJ-V.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/90pv-RKSJ-H.bcmap b/toolkit/components/pdfjs/content/web/cmaps/90pv-RKSJ-H.bcmap
new file mode 100644
index 0000000000..02f713bb83
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/90pv-RKSJ-H.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/90pv-RKSJ-V.bcmap b/toolkit/components/pdfjs/content/web/cmaps/90pv-RKSJ-V.bcmap
new file mode 100644
index 0000000000..d08e0cc5d9
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/90pv-RKSJ-V.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/Add-H.bcmap b/toolkit/components/pdfjs/content/web/cmaps/Add-H.bcmap
new file mode 100644
index 0000000000..59442acafb
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/Add-H.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/Add-RKSJ-H.bcmap b/toolkit/components/pdfjs/content/web/cmaps/Add-RKSJ-H.bcmap
new file mode 100644
index 0000000000..a3065e441a
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/Add-RKSJ-H.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/Add-RKSJ-V.bcmap b/toolkit/components/pdfjs/content/web/cmaps/Add-RKSJ-V.bcmap
new file mode 100644
index 0000000000..040014cfc0
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/Add-RKSJ-V.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/Add-V.bcmap b/toolkit/components/pdfjs/content/web/cmaps/Add-V.bcmap
new file mode 100644
index 0000000000..2f816d320f
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/Add-V.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/Adobe-CNS1-0.bcmap b/toolkit/components/pdfjs/content/web/cmaps/Adobe-CNS1-0.bcmap
new file mode 100644
index 0000000000..88ec04af49
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/Adobe-CNS1-0.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/Adobe-CNS1-1.bcmap b/toolkit/components/pdfjs/content/web/cmaps/Adobe-CNS1-1.bcmap
new file mode 100644
index 0000000000..03a501477c
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/Adobe-CNS1-1.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/Adobe-CNS1-2.bcmap b/toolkit/components/pdfjs/content/web/cmaps/Adobe-CNS1-2.bcmap
new file mode 100644
index 0000000000..2aa95141f9
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/Adobe-CNS1-2.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/Adobe-CNS1-3.bcmap b/toolkit/components/pdfjs/content/web/cmaps/Adobe-CNS1-3.bcmap
new file mode 100644
index 0000000000..86d8b8c79c
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/Adobe-CNS1-3.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/Adobe-CNS1-4.bcmap b/toolkit/components/pdfjs/content/web/cmaps/Adobe-CNS1-4.bcmap
new file mode 100644
index 0000000000..f50fc6c14e
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/Adobe-CNS1-4.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/Adobe-CNS1-5.bcmap b/toolkit/components/pdfjs/content/web/cmaps/Adobe-CNS1-5.bcmap
new file mode 100644
index 0000000000..6caf4a8314
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/Adobe-CNS1-5.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/Adobe-CNS1-6.bcmap b/toolkit/components/pdfjs/content/web/cmaps/Adobe-CNS1-6.bcmap
new file mode 100644
index 0000000000..b77fb0705c
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/Adobe-CNS1-6.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/Adobe-CNS1-UCS2.bcmap b/toolkit/components/pdfjs/content/web/cmaps/Adobe-CNS1-UCS2.bcmap
new file mode 100644
index 0000000000..69d79a2c2c
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/Adobe-CNS1-UCS2.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/Adobe-GB1-0.bcmap b/toolkit/components/pdfjs/content/web/cmaps/Adobe-GB1-0.bcmap
new file mode 100644
index 0000000000..36101083fa
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/Adobe-GB1-0.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/Adobe-GB1-1.bcmap b/toolkit/components/pdfjs/content/web/cmaps/Adobe-GB1-1.bcmap
new file mode 100644
index 0000000000..707bb1065c
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/Adobe-GB1-1.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/Adobe-GB1-2.bcmap b/toolkit/components/pdfjs/content/web/cmaps/Adobe-GB1-2.bcmap
new file mode 100644
index 0000000000..f7648cc3ff
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/Adobe-GB1-2.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/Adobe-GB1-3.bcmap b/toolkit/components/pdfjs/content/web/cmaps/Adobe-GB1-3.bcmap
new file mode 100644
index 0000000000..852145890e
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/Adobe-GB1-3.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/Adobe-GB1-4.bcmap b/toolkit/components/pdfjs/content/web/cmaps/Adobe-GB1-4.bcmap
new file mode 100644
index 0000000000..e40c63ab1e
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/Adobe-GB1-4.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/Adobe-GB1-5.bcmap b/toolkit/components/pdfjs/content/web/cmaps/Adobe-GB1-5.bcmap
new file mode 100644
index 0000000000..d7623b5002
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/Adobe-GB1-5.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/Adobe-GB1-UCS2.bcmap b/toolkit/components/pdfjs/content/web/cmaps/Adobe-GB1-UCS2.bcmap
new file mode 100644
index 0000000000..7586525936
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/Adobe-GB1-UCS2.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/Adobe-Japan1-0.bcmap b/toolkit/components/pdfjs/content/web/cmaps/Adobe-Japan1-0.bcmap
new file mode 100644
index 0000000000..f0e94ec196
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/Adobe-Japan1-0.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/Adobe-Japan1-1.bcmap b/toolkit/components/pdfjs/content/web/cmaps/Adobe-Japan1-1.bcmap
new file mode 100644
index 0000000000..dad42c5ad7
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/Adobe-Japan1-1.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/Adobe-Japan1-2.bcmap b/toolkit/components/pdfjs/content/web/cmaps/Adobe-Japan1-2.bcmap
new file mode 100644
index 0000000000..090819a064
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/Adobe-Japan1-2.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/Adobe-Japan1-3.bcmap b/toolkit/components/pdfjs/content/web/cmaps/Adobe-Japan1-3.bcmap
new file mode 100644
index 0000000000..087dfc1558
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/Adobe-Japan1-3.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/Adobe-Japan1-4.bcmap b/toolkit/components/pdfjs/content/web/cmaps/Adobe-Japan1-4.bcmap
new file mode 100644
index 0000000000..46aa9bffe5
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/Adobe-Japan1-4.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/Adobe-Japan1-5.bcmap b/toolkit/components/pdfjs/content/web/cmaps/Adobe-Japan1-5.bcmap
new file mode 100644
index 0000000000..5b4b65cc62
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/Adobe-Japan1-5.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/Adobe-Japan1-6.bcmap b/toolkit/components/pdfjs/content/web/cmaps/Adobe-Japan1-6.bcmap
new file mode 100644
index 0000000000..e77d699ab6
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/Adobe-Japan1-6.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/Adobe-Japan1-UCS2.bcmap b/toolkit/components/pdfjs/content/web/cmaps/Adobe-Japan1-UCS2.bcmap
new file mode 100644
index 0000000000..128a141077
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/Adobe-Japan1-UCS2.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/Adobe-Korea1-0.bcmap b/toolkit/components/pdfjs/content/web/cmaps/Adobe-Korea1-0.bcmap
new file mode 100644
index 0000000000..cef1a99851
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/Adobe-Korea1-0.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/Adobe-Korea1-1.bcmap b/toolkit/components/pdfjs/content/web/cmaps/Adobe-Korea1-1.bcmap
new file mode 100644
index 0000000000..11ffa36df8
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/Adobe-Korea1-1.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/Adobe-Korea1-2.bcmap b/toolkit/components/pdfjs/content/web/cmaps/Adobe-Korea1-2.bcmap
new file mode 100644
index 0000000000..3172308c79
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/Adobe-Korea1-2.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/Adobe-Korea1-UCS2.bcmap b/toolkit/components/pdfjs/content/web/cmaps/Adobe-Korea1-UCS2.bcmap
new file mode 100644
index 0000000000..f3371c0cbd
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/Adobe-Korea1-UCS2.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/B5-H.bcmap b/toolkit/components/pdfjs/content/web/cmaps/B5-H.bcmap
new file mode 100644
index 0000000000..beb4d22810
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/B5-H.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/B5-V.bcmap b/toolkit/components/pdfjs/content/web/cmaps/B5-V.bcmap
new file mode 100644
index 0000000000..2d4f87d503
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/B5-V.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/B5pc-H.bcmap b/toolkit/components/pdfjs/content/web/cmaps/B5pc-H.bcmap
new file mode 100644
index 0000000000..ce0013167f
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/B5pc-H.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/B5pc-V.bcmap b/toolkit/components/pdfjs/content/web/cmaps/B5pc-V.bcmap
new file mode 100644
index 0000000000..73b99ff2fb
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/B5pc-V.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/CNS-EUC-H.bcmap b/toolkit/components/pdfjs/content/web/cmaps/CNS-EUC-H.bcmap
new file mode 100644
index 0000000000..61d1d0cb00
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/CNS-EUC-H.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/CNS-EUC-V.bcmap b/toolkit/components/pdfjs/content/web/cmaps/CNS-EUC-V.bcmap
new file mode 100644
index 0000000000..1a393a51e0
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/CNS-EUC-V.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/CNS1-H.bcmap b/toolkit/components/pdfjs/content/web/cmaps/CNS1-H.bcmap
new file mode 100644
index 0000000000..f738e218ae
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/CNS1-H.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/CNS1-V.bcmap b/toolkit/components/pdfjs/content/web/cmaps/CNS1-V.bcmap
new file mode 100644
index 0000000000..9c3169f0d9
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/CNS1-V.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/CNS2-H.bcmap b/toolkit/components/pdfjs/content/web/cmaps/CNS2-H.bcmap
new file mode 100644
index 0000000000..c89b3527fe
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/CNS2-H.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/CNS2-V.bcmap b/toolkit/components/pdfjs/content/web/cmaps/CNS2-V.bcmap
new file mode 100644
index 0000000000..7588cec83e
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/CNS2-V.bcmap
@@ -0,0 +1,3 @@
+àRCopyright 1990-2009 Adobe Systems Incorporated.
+All rights reserved.
+See ./LICENSEáCNS2-H \ No newline at end of file
diff --git a/toolkit/components/pdfjs/content/web/cmaps/ETHK-B5-H.bcmap b/toolkit/components/pdfjs/content/web/cmaps/ETHK-B5-H.bcmap
new file mode 100644
index 0000000000..cb29415de4
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/ETHK-B5-H.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/ETHK-B5-V.bcmap b/toolkit/components/pdfjs/content/web/cmaps/ETHK-B5-V.bcmap
new file mode 100644
index 0000000000..f09aec6318
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/ETHK-B5-V.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/ETen-B5-H.bcmap b/toolkit/components/pdfjs/content/web/cmaps/ETen-B5-H.bcmap
new file mode 100644
index 0000000000..c2d77462d2
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/ETen-B5-H.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/ETen-B5-V.bcmap b/toolkit/components/pdfjs/content/web/cmaps/ETen-B5-V.bcmap
new file mode 100644
index 0000000000..89bff159ec
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/ETen-B5-V.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/ETenms-B5-H.bcmap b/toolkit/components/pdfjs/content/web/cmaps/ETenms-B5-H.bcmap
new file mode 100644
index 0000000000..a7d69db5e3
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/ETenms-B5-H.bcmap
@@ -0,0 +1,3 @@
+àRCopyright 1990-2009 Adobe Systems Incorporated.
+All rights reserved.
+See ./LICENSEá ETen-B5-H` ^ \ No newline at end of file
diff --git a/toolkit/components/pdfjs/content/web/cmaps/ETenms-B5-V.bcmap b/toolkit/components/pdfjs/content/web/cmaps/ETenms-B5-V.bcmap
new file mode 100644
index 0000000000..adc5d618d6
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/ETenms-B5-V.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/EUC-H.bcmap b/toolkit/components/pdfjs/content/web/cmaps/EUC-H.bcmap
new file mode 100644
index 0000000000..e92ea5b3b9
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/EUC-H.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/EUC-V.bcmap b/toolkit/components/pdfjs/content/web/cmaps/EUC-V.bcmap
new file mode 100644
index 0000000000..7a7c183228
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/EUC-V.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/Ext-H.bcmap b/toolkit/components/pdfjs/content/web/cmaps/Ext-H.bcmap
new file mode 100644
index 0000000000..3b5cde44db
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/Ext-H.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/Ext-RKSJ-H.bcmap b/toolkit/components/pdfjs/content/web/cmaps/Ext-RKSJ-H.bcmap
new file mode 100644
index 0000000000..ea4d2d97b8
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/Ext-RKSJ-H.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/Ext-RKSJ-V.bcmap b/toolkit/components/pdfjs/content/web/cmaps/Ext-RKSJ-V.bcmap
new file mode 100644
index 0000000000..3457c27709
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/Ext-RKSJ-V.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/Ext-V.bcmap b/toolkit/components/pdfjs/content/web/cmaps/Ext-V.bcmap
new file mode 100644
index 0000000000..4999ca4041
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/Ext-V.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/GB-EUC-H.bcmap b/toolkit/components/pdfjs/content/web/cmaps/GB-EUC-H.bcmap
new file mode 100644
index 0000000000..e39908b984
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/GB-EUC-H.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/GB-EUC-V.bcmap b/toolkit/components/pdfjs/content/web/cmaps/GB-EUC-V.bcmap
new file mode 100644
index 0000000000..d5be5446aa
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/GB-EUC-V.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/GB-H.bcmap b/toolkit/components/pdfjs/content/web/cmaps/GB-H.bcmap
new file mode 100644
index 0000000000..39189c54e3
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/GB-H.bcmap
@@ -0,0 +1,4 @@
+àRCopyright 1990-2009 Adobe Systems Incorporated.
+All rights reserved.
+See ./LICENSE!!º]aX!!]`21> p z$]‚"R‚d-Uƒ7*„ 4„%+ „Z „{/…%…<9K…b1]†."‡ ‰`]‡,"]ˆ
+"]ˆh"]‰F"]Š$"]‹"]‹`"]Œ>"]"]z"]ŽX"]6"]"]r"]‘P"]’."]“ "]“j"]”H"]•&"]–"]–b"]—@"]˜"]˜|"]™Z"]š8"]›"]›t"]œR"]0"]ž"]žl"]ŸJ"] ("]¡"]¡d"]¢B"]£ "X£~']¤W"]¥5"]¦"]¦q"]§O"]¨-"]© "]©i"]ªG"]«%"]¬"]¬a"]­?"]®"]®{"]¯Y"]°7"]±"]±s"]²Q"]³/"]´ "]´k"]µI"]¶'"]·"]·c"]¸A"]¹"]¹}"]º["]»9 \ No newline at end of file
diff --git a/toolkit/components/pdfjs/content/web/cmaps/GB-V.bcmap b/toolkit/components/pdfjs/content/web/cmaps/GB-V.bcmap
new file mode 100644
index 0000000000..310834512f
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/GB-V.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/GBK-EUC-H.bcmap b/toolkit/components/pdfjs/content/web/cmaps/GBK-EUC-H.bcmap
new file mode 100644
index 0000000000..05fff7e825
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/GBK-EUC-H.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/GBK-EUC-V.bcmap b/toolkit/components/pdfjs/content/web/cmaps/GBK-EUC-V.bcmap
new file mode 100644
index 0000000000..0cdf6bed6d
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/GBK-EUC-V.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/GBK2K-H.bcmap b/toolkit/components/pdfjs/content/web/cmaps/GBK2K-H.bcmap
new file mode 100644
index 0000000000..46f6ba5967
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/GBK2K-H.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/GBK2K-V.bcmap b/toolkit/components/pdfjs/content/web/cmaps/GBK2K-V.bcmap
new file mode 100644
index 0000000000..d9a9479843
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/GBK2K-V.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/GBKp-EUC-H.bcmap b/toolkit/components/pdfjs/content/web/cmaps/GBKp-EUC-H.bcmap
new file mode 100644
index 0000000000..5cb0af687e
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/GBKp-EUC-H.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/GBKp-EUC-V.bcmap b/toolkit/components/pdfjs/content/web/cmaps/GBKp-EUC-V.bcmap
new file mode 100644
index 0000000000..bca93b8efb
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/GBKp-EUC-V.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/GBT-EUC-H.bcmap b/toolkit/components/pdfjs/content/web/cmaps/GBT-EUC-H.bcmap
new file mode 100644
index 0000000000..4b4e2d3229
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/GBT-EUC-H.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/GBT-EUC-V.bcmap b/toolkit/components/pdfjs/content/web/cmaps/GBT-EUC-V.bcmap
new file mode 100644
index 0000000000..38f706699f
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/GBT-EUC-V.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/GBT-H.bcmap b/toolkit/components/pdfjs/content/web/cmaps/GBT-H.bcmap
new file mode 100644
index 0000000000..8437ac3377
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/GBT-H.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/GBT-V.bcmap b/toolkit/components/pdfjs/content/web/cmaps/GBT-V.bcmap
new file mode 100644
index 0000000000..697ab4a8e7
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/GBT-V.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/GBTpc-EUC-H.bcmap b/toolkit/components/pdfjs/content/web/cmaps/GBTpc-EUC-H.bcmap
new file mode 100644
index 0000000000..f6e50e8936
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/GBTpc-EUC-H.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/GBTpc-EUC-V.bcmap b/toolkit/components/pdfjs/content/web/cmaps/GBTpc-EUC-V.bcmap
new file mode 100644
index 0000000000..6c0d71a2d0
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/GBTpc-EUC-V.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/GBpc-EUC-H.bcmap b/toolkit/components/pdfjs/content/web/cmaps/GBpc-EUC-H.bcmap
new file mode 100644
index 0000000000..c9edf67cf6
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/GBpc-EUC-H.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/GBpc-EUC-V.bcmap b/toolkit/components/pdfjs/content/web/cmaps/GBpc-EUC-V.bcmap
new file mode 100644
index 0000000000..31450c97f6
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/GBpc-EUC-V.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/H.bcmap b/toolkit/components/pdfjs/content/web/cmaps/H.bcmap
new file mode 100644
index 0000000000..7b24ea4629
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/H.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/HKdla-B5-H.bcmap b/toolkit/components/pdfjs/content/web/cmaps/HKdla-B5-H.bcmap
new file mode 100644
index 0000000000..7d30c05005
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/HKdla-B5-H.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/HKdla-B5-V.bcmap b/toolkit/components/pdfjs/content/web/cmaps/HKdla-B5-V.bcmap
new file mode 100644
index 0000000000..78946940d6
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/HKdla-B5-V.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/HKdlb-B5-H.bcmap b/toolkit/components/pdfjs/content/web/cmaps/HKdlb-B5-H.bcmap
new file mode 100644
index 0000000000..d829a23101
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/HKdlb-B5-H.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/HKdlb-B5-V.bcmap b/toolkit/components/pdfjs/content/web/cmaps/HKdlb-B5-V.bcmap
new file mode 100644
index 0000000000..2b572b50a4
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/HKdlb-B5-V.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/HKgccs-B5-H.bcmap b/toolkit/components/pdfjs/content/web/cmaps/HKgccs-B5-H.bcmap
new file mode 100644
index 0000000000..971a4f23f7
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/HKgccs-B5-H.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/HKgccs-B5-V.bcmap b/toolkit/components/pdfjs/content/web/cmaps/HKgccs-B5-V.bcmap
new file mode 100644
index 0000000000..d353ca256b
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/HKgccs-B5-V.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/HKm314-B5-H.bcmap b/toolkit/components/pdfjs/content/web/cmaps/HKm314-B5-H.bcmap
new file mode 100644
index 0000000000..576dc01112
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/HKm314-B5-H.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/HKm314-B5-V.bcmap b/toolkit/components/pdfjs/content/web/cmaps/HKm314-B5-V.bcmap
new file mode 100644
index 0000000000..0e96d0e228
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/HKm314-B5-V.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/HKm471-B5-H.bcmap b/toolkit/components/pdfjs/content/web/cmaps/HKm471-B5-H.bcmap
new file mode 100644
index 0000000000..11d170c75e
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/HKm471-B5-H.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/HKm471-B5-V.bcmap b/toolkit/components/pdfjs/content/web/cmaps/HKm471-B5-V.bcmap
new file mode 100644
index 0000000000..54959bf9e7
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/HKm471-B5-V.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/HKscs-B5-H.bcmap b/toolkit/components/pdfjs/content/web/cmaps/HKscs-B5-H.bcmap
new file mode 100644
index 0000000000..6ef7857ad1
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/HKscs-B5-H.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/HKscs-B5-V.bcmap b/toolkit/components/pdfjs/content/web/cmaps/HKscs-B5-V.bcmap
new file mode 100644
index 0000000000..1fb2fa2a2e
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/HKscs-B5-V.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/Hankaku.bcmap b/toolkit/components/pdfjs/content/web/cmaps/Hankaku.bcmap
new file mode 100644
index 0000000000..4b8ec7fcef
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/Hankaku.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/Hiragana.bcmap b/toolkit/components/pdfjs/content/web/cmaps/Hiragana.bcmap
new file mode 100644
index 0000000000..17e983e772
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/Hiragana.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/KSC-EUC-H.bcmap b/toolkit/components/pdfjs/content/web/cmaps/KSC-EUC-H.bcmap
new file mode 100644
index 0000000000..a45c65f008
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/KSC-EUC-H.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/KSC-EUC-V.bcmap b/toolkit/components/pdfjs/content/web/cmaps/KSC-EUC-V.bcmap
new file mode 100644
index 0000000000..0e7b21f0a6
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/KSC-EUC-V.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/KSC-H.bcmap b/toolkit/components/pdfjs/content/web/cmaps/KSC-H.bcmap
new file mode 100644
index 0000000000..b9b22b6787
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/KSC-H.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/KSC-Johab-H.bcmap b/toolkit/components/pdfjs/content/web/cmaps/KSC-Johab-H.bcmap
new file mode 100644
index 0000000000..2531ffcf41
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/KSC-Johab-H.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/KSC-Johab-V.bcmap b/toolkit/components/pdfjs/content/web/cmaps/KSC-Johab-V.bcmap
new file mode 100644
index 0000000000..367ceb226a
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/KSC-Johab-V.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/KSC-V.bcmap b/toolkit/components/pdfjs/content/web/cmaps/KSC-V.bcmap
new file mode 100644
index 0000000000..6ae2f0b6b7
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/KSC-V.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/KSCms-UHC-H.bcmap b/toolkit/components/pdfjs/content/web/cmaps/KSCms-UHC-H.bcmap
new file mode 100644
index 0000000000..a8d4240e6a
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/KSCms-UHC-H.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/KSCms-UHC-HW-H.bcmap b/toolkit/components/pdfjs/content/web/cmaps/KSCms-UHC-HW-H.bcmap
new file mode 100644
index 0000000000..8b4ae18fd3
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/KSCms-UHC-HW-H.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/KSCms-UHC-HW-V.bcmap b/toolkit/components/pdfjs/content/web/cmaps/KSCms-UHC-HW-V.bcmap
new file mode 100644
index 0000000000..b655dbcfb1
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/KSCms-UHC-HW-V.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/KSCms-UHC-V.bcmap b/toolkit/components/pdfjs/content/web/cmaps/KSCms-UHC-V.bcmap
new file mode 100644
index 0000000000..21f97f65b4
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/KSCms-UHC-V.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/KSCpc-EUC-H.bcmap b/toolkit/components/pdfjs/content/web/cmaps/KSCpc-EUC-H.bcmap
new file mode 100644
index 0000000000..e06f361eb6
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/KSCpc-EUC-H.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/KSCpc-EUC-V.bcmap b/toolkit/components/pdfjs/content/web/cmaps/KSCpc-EUC-V.bcmap
new file mode 100644
index 0000000000..f3c9113fcf
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/KSCpc-EUC-V.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/Katakana.bcmap b/toolkit/components/pdfjs/content/web/cmaps/Katakana.bcmap
new file mode 100644
index 0000000000..524303c4f0
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/Katakana.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/LICENSE b/toolkit/components/pdfjs/content/web/cmaps/LICENSE
new file mode 100644
index 0000000000..b1ad168ad0
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/LICENSE
@@ -0,0 +1,36 @@
+%%Copyright: -----------------------------------------------------------
+%%Copyright: Copyright 1990-2009 Adobe Systems Incorporated.
+%%Copyright: All rights reserved.
+%%Copyright:
+%%Copyright: Redistribution and use in source and binary forms, with or
+%%Copyright: without modification, are permitted provided that the
+%%Copyright: following conditions are met:
+%%Copyright:
+%%Copyright: Redistributions of source code must retain the above
+%%Copyright: copyright notice, this list of conditions and the following
+%%Copyright: disclaimer.
+%%Copyright:
+%%Copyright: Redistributions in binary form must reproduce the above
+%%Copyright: copyright notice, this list of conditions and the following
+%%Copyright: disclaimer in the documentation and/or other materials
+%%Copyright: provided with the distribution.
+%%Copyright:
+%%Copyright: Neither the name of Adobe Systems Incorporated nor the names
+%%Copyright: of its contributors may be used to endorse or promote
+%%Copyright: products derived from this software without specific prior
+%%Copyright: written permission.
+%%Copyright:
+%%Copyright: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+%%Copyright: CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+%%Copyright: INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+%%Copyright: MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+%%Copyright: DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+%%Copyright: CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+%%Copyright: SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+%%Copyright: NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+%%Copyright: LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+%%Copyright: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+%%Copyright: CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+%%Copyright: OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+%%Copyright: SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+%%Copyright: -----------------------------------------------------------
diff --git a/toolkit/components/pdfjs/content/web/cmaps/NWP-H.bcmap b/toolkit/components/pdfjs/content/web/cmaps/NWP-H.bcmap
new file mode 100644
index 0000000000..afc5e4b05e
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/NWP-H.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/NWP-V.bcmap b/toolkit/components/pdfjs/content/web/cmaps/NWP-V.bcmap
new file mode 100644
index 0000000000..bb5785e327
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/NWP-V.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/RKSJ-H.bcmap b/toolkit/components/pdfjs/content/web/cmaps/RKSJ-H.bcmap
new file mode 100644
index 0000000000..fb8d298e9b
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/RKSJ-H.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/RKSJ-V.bcmap b/toolkit/components/pdfjs/content/web/cmaps/RKSJ-V.bcmap
new file mode 100644
index 0000000000..a2555a6c04
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/RKSJ-V.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/Roman.bcmap b/toolkit/components/pdfjs/content/web/cmaps/Roman.bcmap
new file mode 100644
index 0000000000..f896dcf1c7
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/Roman.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/UniCNS-UCS2-H.bcmap b/toolkit/components/pdfjs/content/web/cmaps/UniCNS-UCS2-H.bcmap
new file mode 100644
index 0000000000..d5db27c5cf
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/UniCNS-UCS2-H.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/UniCNS-UCS2-V.bcmap b/toolkit/components/pdfjs/content/web/cmaps/UniCNS-UCS2-V.bcmap
new file mode 100644
index 0000000000..1dc9b7a21b
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/UniCNS-UCS2-V.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/UniCNS-UTF16-H.bcmap b/toolkit/components/pdfjs/content/web/cmaps/UniCNS-UTF16-H.bcmap
new file mode 100644
index 0000000000..961afefb66
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/UniCNS-UTF16-H.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/UniCNS-UTF16-V.bcmap b/toolkit/components/pdfjs/content/web/cmaps/UniCNS-UTF16-V.bcmap
new file mode 100644
index 0000000000..df0cffe86b
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/UniCNS-UTF16-V.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/UniCNS-UTF32-H.bcmap b/toolkit/components/pdfjs/content/web/cmaps/UniCNS-UTF32-H.bcmap
new file mode 100644
index 0000000000..1ab18a1436
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/UniCNS-UTF32-H.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/UniCNS-UTF32-V.bcmap b/toolkit/components/pdfjs/content/web/cmaps/UniCNS-UTF32-V.bcmap
new file mode 100644
index 0000000000..ad14662e25
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/UniCNS-UTF32-V.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/UniCNS-UTF8-H.bcmap b/toolkit/components/pdfjs/content/web/cmaps/UniCNS-UTF8-H.bcmap
new file mode 100644
index 0000000000..83c6bd7c4f
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/UniCNS-UTF8-H.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/UniCNS-UTF8-V.bcmap b/toolkit/components/pdfjs/content/web/cmaps/UniCNS-UTF8-V.bcmap
new file mode 100644
index 0000000000..22a27e4ddb
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/UniCNS-UTF8-V.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/UniGB-UCS2-H.bcmap b/toolkit/components/pdfjs/content/web/cmaps/UniGB-UCS2-H.bcmap
new file mode 100644
index 0000000000..5bd6228ce6
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/UniGB-UCS2-H.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/UniGB-UCS2-V.bcmap b/toolkit/components/pdfjs/content/web/cmaps/UniGB-UCS2-V.bcmap
new file mode 100644
index 0000000000..53c534b7fe
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/UniGB-UCS2-V.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/UniGB-UTF16-H.bcmap b/toolkit/components/pdfjs/content/web/cmaps/UniGB-UTF16-H.bcmap
new file mode 100644
index 0000000000..b95045b400
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/UniGB-UTF16-H.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/UniGB-UTF16-V.bcmap b/toolkit/components/pdfjs/content/web/cmaps/UniGB-UTF16-V.bcmap
new file mode 100644
index 0000000000..51f023e0d6
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/UniGB-UTF16-V.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/UniGB-UTF32-H.bcmap b/toolkit/components/pdfjs/content/web/cmaps/UniGB-UTF32-H.bcmap
new file mode 100644
index 0000000000..f0dbd14f37
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/UniGB-UTF32-H.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/UniGB-UTF32-V.bcmap b/toolkit/components/pdfjs/content/web/cmaps/UniGB-UTF32-V.bcmap
new file mode 100644
index 0000000000..ce9c30a985
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/UniGB-UTF32-V.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/UniGB-UTF8-H.bcmap b/toolkit/components/pdfjs/content/web/cmaps/UniGB-UTF8-H.bcmap
new file mode 100644
index 0000000000..982ca462b1
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/UniGB-UTF8-H.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/UniGB-UTF8-V.bcmap b/toolkit/components/pdfjs/content/web/cmaps/UniGB-UTF8-V.bcmap
new file mode 100644
index 0000000000..f78020dd40
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/UniGB-UTF8-V.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/UniJIS-UCS2-H.bcmap b/toolkit/components/pdfjs/content/web/cmaps/UniJIS-UCS2-H.bcmap
new file mode 100644
index 0000000000..7daf56afab
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/UniJIS-UCS2-H.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/UniJIS-UCS2-HW-H.bcmap b/toolkit/components/pdfjs/content/web/cmaps/UniJIS-UCS2-HW-H.bcmap
new file mode 100644
index 0000000000..ac9975c585
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/UniJIS-UCS2-HW-H.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/UniJIS-UCS2-HW-V.bcmap b/toolkit/components/pdfjs/content/web/cmaps/UniJIS-UCS2-HW-V.bcmap
new file mode 100644
index 0000000000..3da0a1c62f
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/UniJIS-UCS2-HW-V.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/UniJIS-UCS2-V.bcmap b/toolkit/components/pdfjs/content/web/cmaps/UniJIS-UCS2-V.bcmap
new file mode 100644
index 0000000000..c50b9ddfde
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/UniJIS-UCS2-V.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/UniJIS-UTF16-H.bcmap b/toolkit/components/pdfjs/content/web/cmaps/UniJIS-UTF16-H.bcmap
new file mode 100644
index 0000000000..6761344639
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/UniJIS-UTF16-H.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/UniJIS-UTF16-V.bcmap b/toolkit/components/pdfjs/content/web/cmaps/UniJIS-UTF16-V.bcmap
new file mode 100644
index 0000000000..70bf90c0ef
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/UniJIS-UTF16-V.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/UniJIS-UTF32-H.bcmap b/toolkit/components/pdfjs/content/web/cmaps/UniJIS-UTF32-H.bcmap
new file mode 100644
index 0000000000..7a83d53ae7
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/UniJIS-UTF32-H.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/UniJIS-UTF32-V.bcmap b/toolkit/components/pdfjs/content/web/cmaps/UniJIS-UTF32-V.bcmap
new file mode 100644
index 0000000000..7a87135394
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/UniJIS-UTF32-V.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/UniJIS-UTF8-H.bcmap b/toolkit/components/pdfjs/content/web/cmaps/UniJIS-UTF8-H.bcmap
new file mode 100644
index 0000000000..9f0334cac7
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/UniJIS-UTF8-H.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/UniJIS-UTF8-V.bcmap b/toolkit/components/pdfjs/content/web/cmaps/UniJIS-UTF8-V.bcmap
new file mode 100644
index 0000000000..808a94f0fd
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/UniJIS-UTF8-V.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/UniJIS2004-UTF16-H.bcmap b/toolkit/components/pdfjs/content/web/cmaps/UniJIS2004-UTF16-H.bcmap
new file mode 100644
index 0000000000..d768bf811f
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/UniJIS2004-UTF16-H.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/UniJIS2004-UTF16-V.bcmap b/toolkit/components/pdfjs/content/web/cmaps/UniJIS2004-UTF16-V.bcmap
new file mode 100644
index 0000000000..3d5bf6fb4e
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/UniJIS2004-UTF16-V.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/UniJIS2004-UTF32-H.bcmap b/toolkit/components/pdfjs/content/web/cmaps/UniJIS2004-UTF32-H.bcmap
new file mode 100644
index 0000000000..09eee10d4f
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/UniJIS2004-UTF32-H.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/UniJIS2004-UTF32-V.bcmap b/toolkit/components/pdfjs/content/web/cmaps/UniJIS2004-UTF32-V.bcmap
new file mode 100644
index 0000000000..6c54600133
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/UniJIS2004-UTF32-V.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/UniJIS2004-UTF8-H.bcmap b/toolkit/components/pdfjs/content/web/cmaps/UniJIS2004-UTF8-H.bcmap
new file mode 100644
index 0000000000..1b1a64f50d
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/UniJIS2004-UTF8-H.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/UniJIS2004-UTF8-V.bcmap b/toolkit/components/pdfjs/content/web/cmaps/UniJIS2004-UTF8-V.bcmap
new file mode 100644
index 0000000000..994aa9ef9f
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/UniJIS2004-UTF8-V.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/UniJISPro-UCS2-HW-V.bcmap b/toolkit/components/pdfjs/content/web/cmaps/UniJISPro-UCS2-HW-V.bcmap
new file mode 100644
index 0000000000..643f921b65
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/UniJISPro-UCS2-HW-V.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/UniJISPro-UCS2-V.bcmap b/toolkit/components/pdfjs/content/web/cmaps/UniJISPro-UCS2-V.bcmap
new file mode 100644
index 0000000000..c148f67f5e
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/UniJISPro-UCS2-V.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/UniJISPro-UTF8-V.bcmap b/toolkit/components/pdfjs/content/web/cmaps/UniJISPro-UTF8-V.bcmap
new file mode 100644
index 0000000000..1849d809a6
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/UniJISPro-UTF8-V.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/UniJISX0213-UTF32-H.bcmap b/toolkit/components/pdfjs/content/web/cmaps/UniJISX0213-UTF32-H.bcmap
new file mode 100644
index 0000000000..a83a677c56
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/UniJISX0213-UTF32-H.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/UniJISX0213-UTF32-V.bcmap b/toolkit/components/pdfjs/content/web/cmaps/UniJISX0213-UTF32-V.bcmap
new file mode 100644
index 0000000000..f527248ad5
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/UniJISX0213-UTF32-V.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/UniJISX02132004-UTF32-H.bcmap b/toolkit/components/pdfjs/content/web/cmaps/UniJISX02132004-UTF32-H.bcmap
new file mode 100644
index 0000000000..e1a988dc9e
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/UniJISX02132004-UTF32-H.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/UniJISX02132004-UTF32-V.bcmap b/toolkit/components/pdfjs/content/web/cmaps/UniJISX02132004-UTF32-V.bcmap
new file mode 100644
index 0000000000..47e054a961
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/UniJISX02132004-UTF32-V.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/UniKS-UCS2-H.bcmap b/toolkit/components/pdfjs/content/web/cmaps/UniKS-UCS2-H.bcmap
new file mode 100644
index 0000000000..b5b94852a5
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/UniKS-UCS2-H.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/UniKS-UCS2-V.bcmap b/toolkit/components/pdfjs/content/web/cmaps/UniKS-UCS2-V.bcmap
new file mode 100644
index 0000000000..026adcaad4
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/UniKS-UCS2-V.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/UniKS-UTF16-H.bcmap b/toolkit/components/pdfjs/content/web/cmaps/UniKS-UTF16-H.bcmap
new file mode 100644
index 0000000000..fd4e66e81f
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/UniKS-UTF16-H.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/UniKS-UTF16-V.bcmap b/toolkit/components/pdfjs/content/web/cmaps/UniKS-UTF16-V.bcmap
new file mode 100644
index 0000000000..075efb7054
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/UniKS-UTF16-V.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/UniKS-UTF32-H.bcmap b/toolkit/components/pdfjs/content/web/cmaps/UniKS-UTF32-H.bcmap
new file mode 100644
index 0000000000..769d2142c0
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/UniKS-UTF32-H.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/UniKS-UTF32-V.bcmap b/toolkit/components/pdfjs/content/web/cmaps/UniKS-UTF32-V.bcmap
new file mode 100644
index 0000000000..bdab208b69
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/UniKS-UTF32-V.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/UniKS-UTF8-H.bcmap b/toolkit/components/pdfjs/content/web/cmaps/UniKS-UTF8-H.bcmap
new file mode 100644
index 0000000000..6ff8674af7
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/UniKS-UTF8-H.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/UniKS-UTF8-V.bcmap b/toolkit/components/pdfjs/content/web/cmaps/UniKS-UTF8-V.bcmap
new file mode 100644
index 0000000000..8dfa76a58e
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/UniKS-UTF8-V.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/V.bcmap b/toolkit/components/pdfjs/content/web/cmaps/V.bcmap
new file mode 100644
index 0000000000..fdec990662
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/V.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/cmaps/WP-Symbol.bcmap b/toolkit/components/pdfjs/content/web/cmaps/WP-Symbol.bcmap
new file mode 100644
index 0000000000..46729bbf30
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/cmaps/WP-Symbol.bcmap
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/debugger.css b/toolkit/components/pdfjs/content/web/debugger.css
new file mode 100644
index 0000000000..b9d9f81906
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/debugger.css
@@ -0,0 +1,111 @@
+/* Copyright 2014 Mozilla Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+:root {
+ --panel-width: 300px;
+}
+
+#PDFBug,
+#PDFBug :is(input, button, select) {
+ font: message-box;
+}
+#PDFBug {
+ background-color: rgb(255 255 255);
+ border: 1px solid rgb(102 102 102);
+ position: fixed;
+ top: 32px;
+ right: 0;
+ bottom: 0;
+ font-size: 10px;
+ padding: 0;
+ width: var(--panel-width);
+}
+#PDFBug .controls {
+ background: rgb(238 238 238);
+ border-bottom: 1px solid rgb(102 102 102);
+ padding: 3px;
+}
+#PDFBug .panels {
+ inset: 27px 0 0;
+ overflow: auto;
+ position: absolute;
+}
+#PDFBug .panels > div {
+ padding: 5px;
+}
+#PDFBug button.active {
+ font-weight: bold;
+}
+.debuggerShowText,
+.debuggerHideText:hover {
+ background-color: rgb(255 255 0 / 0.25);
+}
+#PDFBug .stats {
+ font-family: courier;
+ font-size: 10px;
+ white-space: pre;
+}
+#PDFBug .stats .title {
+ font-weight: bold;
+}
+#PDFBug table {
+ font-size: 10px;
+ white-space: pre;
+}
+#PDFBug table.showText {
+ border-collapse: collapse;
+ text-align: center;
+}
+#PDFBug table.showText,
+#PDFBug table.showText :is(tr, td) {
+ border: 1px solid black;
+ padding: 1px;
+}
+#PDFBug table.showText td.advance {
+ color: grey;
+}
+
+#viewer.textLayer-visible .textLayer {
+ opacity: 1;
+}
+
+#viewer.textLayer-visible .canvasWrapper {
+ background-color: rgb(128 255 128);
+}
+
+#viewer.textLayer-visible .canvasWrapper canvas {
+ mix-blend-mode: screen;
+}
+
+#viewer.textLayer-visible .textLayer span {
+ background-color: rgb(255 255 0 / 0.1);
+ color: rgb(0 0 0);
+ border: solid 1px rgb(255 0 0 / 0.5);
+ box-sizing: border-box;
+}
+
+#viewer.textLayer-visible .textLayer span[aria-owns] {
+ background-color: rgb(255 0 0 / 0.3);
+}
+
+#viewer.textLayer-hover .textLayer span:hover {
+ background-color: rgb(255 255 255);
+ color: rgb(0 0 0);
+}
+
+#viewer.textLayer-shadow .textLayer span {
+ background-color: rgb(255 255 255 / 0.6);
+ color: rgb(0 0 0);
+}
diff --git a/toolkit/components/pdfjs/content/web/debugger.mjs b/toolkit/components/pdfjs/content/web/debugger.mjs
new file mode 100644
index 0000000000..59c1871b3e
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/debugger.mjs
@@ -0,0 +1,623 @@
+/* Copyright 2012 Mozilla Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+const { OPS } = globalThis.pdfjsLib || (await import("pdfjs-lib"));
+
+const opMap = Object.create(null);
+for (const key in OPS) {
+ opMap[OPS[key]] = key;
+}
+
+const FontInspector = (function FontInspectorClosure() {
+ let fonts;
+ let active = false;
+ const fontAttribute = "data-font-name";
+ function removeSelection() {
+ const divs = document.querySelectorAll(`span[${fontAttribute}]`);
+ for (const div of divs) {
+ div.className = "";
+ }
+ }
+ function resetSelection() {
+ const divs = document.querySelectorAll(`span[${fontAttribute}]`);
+ for (const div of divs) {
+ div.className = "debuggerHideText";
+ }
+ }
+ function selectFont(fontName, show) {
+ const divs = document.querySelectorAll(
+ `span[${fontAttribute}=${fontName}]`
+ );
+ for (const div of divs) {
+ div.className = show ? "debuggerShowText" : "debuggerHideText";
+ }
+ }
+ function textLayerClick(e) {
+ if (
+ !e.target.dataset.fontName ||
+ e.target.tagName.toUpperCase() !== "SPAN"
+ ) {
+ return;
+ }
+ const fontName = e.target.dataset.fontName;
+ const selects = document.getElementsByTagName("input");
+ for (const select of selects) {
+ if (select.dataset.fontName !== fontName) {
+ continue;
+ }
+ select.checked = !select.checked;
+ selectFont(fontName, select.checked);
+ select.scrollIntoView();
+ }
+ }
+ return {
+ // Properties/functions needed by PDFBug.
+ id: "FontInspector",
+ name: "Font Inspector",
+ panel: null,
+ manager: null,
+ init() {
+ const panel = this.panel;
+ const tmp = document.createElement("button");
+ tmp.addEventListener("click", resetSelection);
+ tmp.textContent = "Refresh";
+ panel.append(tmp);
+
+ fonts = document.createElement("div");
+ panel.append(fonts);
+ },
+ cleanup() {
+ fonts.textContent = "";
+ },
+ enabled: false,
+ get active() {
+ return active;
+ },
+ set active(value) {
+ active = value;
+ if (active) {
+ document.body.addEventListener("click", textLayerClick, true);
+ resetSelection();
+ } else {
+ document.body.removeEventListener("click", textLayerClick, true);
+ removeSelection();
+ }
+ },
+ // FontInspector specific functions.
+ fontAdded(fontObj, url) {
+ function properties(obj, list) {
+ const moreInfo = document.createElement("table");
+ for (const entry of list) {
+ const tr = document.createElement("tr");
+ const td1 = document.createElement("td");
+ td1.textContent = entry;
+ tr.append(td1);
+ const td2 = document.createElement("td");
+ td2.textContent = obj[entry].toString();
+ tr.append(td2);
+ moreInfo.append(tr);
+ }
+ return moreInfo;
+ }
+
+ const moreInfo = fontObj.css
+ ? properties(fontObj, ["baseFontName"])
+ : properties(fontObj, ["name", "type"]);
+
+ const fontName = fontObj.loadedName;
+ const font = document.createElement("div");
+ const name = document.createElement("span");
+ name.textContent = fontName;
+ let download;
+ if (!fontObj.css) {
+ download = document.createElement("a");
+ if (url) {
+ url = /url\(['"]?([^)"']+)/.exec(url);
+ download.href = url[1];
+ } else if (fontObj.data) {
+ download.href = URL.createObjectURL(
+ new Blob([fontObj.data], { type: fontObj.mimetype })
+ );
+ }
+ download.textContent = "Download";
+ }
+
+ const logIt = document.createElement("a");
+ logIt.href = "";
+ logIt.textContent = "Log";
+ logIt.addEventListener("click", function (event) {
+ event.preventDefault();
+ console.log(fontObj);
+ });
+ const select = document.createElement("input");
+ select.setAttribute("type", "checkbox");
+ select.dataset.fontName = fontName;
+ select.addEventListener("click", function () {
+ selectFont(fontName, select.checked);
+ });
+ if (download) {
+ font.append(select, name, " ", download, " ", logIt, moreInfo);
+ } else {
+ font.append(select, name, " ", logIt, moreInfo);
+ }
+ fonts.append(font);
+ // Somewhat of a hack, should probably add a hook for when the text layer
+ // is done rendering.
+ setTimeout(() => {
+ if (this.active) {
+ resetSelection();
+ }
+ }, 2000);
+ },
+ };
+})();
+
+// Manages all the page steppers.
+const StepperManager = (function StepperManagerClosure() {
+ let steppers = [];
+ let stepperDiv = null;
+ let stepperControls = null;
+ let stepperChooser = null;
+ let breakPoints = Object.create(null);
+ return {
+ // Properties/functions needed by PDFBug.
+ id: "Stepper",
+ name: "Stepper",
+ panel: null,
+ manager: null,
+ init() {
+ const self = this;
+ stepperControls = document.createElement("div");
+ stepperChooser = document.createElement("select");
+ stepperChooser.addEventListener("change", function (event) {
+ self.selectStepper(this.value);
+ });
+ stepperControls.append(stepperChooser);
+ stepperDiv = document.createElement("div");
+ this.panel.append(stepperControls, stepperDiv);
+ if (sessionStorage.getItem("pdfjsBreakPoints")) {
+ breakPoints = JSON.parse(sessionStorage.getItem("pdfjsBreakPoints"));
+ }
+ },
+ cleanup() {
+ stepperChooser.textContent = "";
+ stepperDiv.textContent = "";
+ steppers = [];
+ },
+ enabled: false,
+ active: false,
+ // Stepper specific functions.
+ create(pageIndex) {
+ const debug = document.createElement("div");
+ debug.id = "stepper" + pageIndex;
+ debug.hidden = true;
+ debug.className = "stepper";
+ stepperDiv.append(debug);
+ const b = document.createElement("option");
+ b.textContent = "Page " + (pageIndex + 1);
+ b.value = pageIndex;
+ stepperChooser.append(b);
+ const initBreakPoints = breakPoints[pageIndex] || [];
+ const stepper = new Stepper(debug, pageIndex, initBreakPoints);
+ steppers.push(stepper);
+ if (steppers.length === 1) {
+ this.selectStepper(pageIndex, false);
+ }
+ return stepper;
+ },
+ selectStepper(pageIndex, selectPanel) {
+ pageIndex |= 0;
+ if (selectPanel) {
+ this.manager.selectPanel(this);
+ }
+ for (const stepper of steppers) {
+ stepper.panel.hidden = stepper.pageIndex !== pageIndex;
+ }
+ for (const option of stepperChooser.options) {
+ option.selected = (option.value | 0) === pageIndex;
+ }
+ },
+ saveBreakPoints(pageIndex, bps) {
+ breakPoints[pageIndex] = bps;
+ sessionStorage.setItem("pdfjsBreakPoints", JSON.stringify(breakPoints));
+ },
+ };
+})();
+
+// The stepper for each page's operatorList.
+class Stepper {
+ // Shorter way to create element and optionally set textContent.
+ #c(tag, textContent) {
+ const d = document.createElement(tag);
+ if (textContent) {
+ d.textContent = textContent;
+ }
+ return d;
+ }
+
+ #simplifyArgs(args) {
+ if (typeof args === "string") {
+ const MAX_STRING_LENGTH = 75;
+ return args.length <= MAX_STRING_LENGTH
+ ? args
+ : args.substring(0, MAX_STRING_LENGTH) + "...";
+ }
+ if (typeof args !== "object" || args === null) {
+ return args;
+ }
+ if ("length" in args) {
+ // array
+ const MAX_ITEMS = 10,
+ simpleArgs = [];
+ let i, ii;
+ for (i = 0, ii = Math.min(MAX_ITEMS, args.length); i < ii; i++) {
+ simpleArgs.push(this.#simplifyArgs(args[i]));
+ }
+ if (i < args.length) {
+ simpleArgs.push("...");
+ }
+ return simpleArgs;
+ }
+ const simpleObj = {};
+ for (const key in args) {
+ simpleObj[key] = this.#simplifyArgs(args[key]);
+ }
+ return simpleObj;
+ }
+
+ constructor(panel, pageIndex, initialBreakPoints) {
+ this.panel = panel;
+ this.breakPoint = 0;
+ this.nextBreakPoint = null;
+ this.pageIndex = pageIndex;
+ this.breakPoints = initialBreakPoints;
+ this.currentIdx = -1;
+ this.operatorListIdx = 0;
+ this.indentLevel = 0;
+ }
+
+ init(operatorList) {
+ const panel = this.panel;
+ const content = this.#c("div", "c=continue, s=step");
+ const table = this.#c("table");
+ content.append(table);
+ table.cellSpacing = 0;
+ const headerRow = this.#c("tr");
+ table.append(headerRow);
+ headerRow.append(
+ this.#c("th", "Break"),
+ this.#c("th", "Idx"),
+ this.#c("th", "fn"),
+ this.#c("th", "args")
+ );
+ panel.append(content);
+ this.table = table;
+ this.updateOperatorList(operatorList);
+ }
+
+ updateOperatorList(operatorList) {
+ const self = this;
+
+ function cboxOnClick() {
+ const x = +this.dataset.idx;
+ if (this.checked) {
+ self.breakPoints.push(x);
+ } else {
+ self.breakPoints.splice(self.breakPoints.indexOf(x), 1);
+ }
+ StepperManager.saveBreakPoints(self.pageIndex, self.breakPoints);
+ }
+
+ const MAX_OPERATORS_COUNT = 15000;
+ if (this.operatorListIdx > MAX_OPERATORS_COUNT) {
+ return;
+ }
+
+ const chunk = document.createDocumentFragment();
+ const operatorsToDisplay = Math.min(
+ MAX_OPERATORS_COUNT,
+ operatorList.fnArray.length
+ );
+ for (let i = this.operatorListIdx; i < operatorsToDisplay; i++) {
+ const line = this.#c("tr");
+ line.className = "line";
+ line.dataset.idx = i;
+ chunk.append(line);
+ const checked = this.breakPoints.includes(i);
+ const args = operatorList.argsArray[i] || [];
+
+ const breakCell = this.#c("td");
+ const cbox = this.#c("input");
+ cbox.type = "checkbox";
+ cbox.className = "points";
+ cbox.checked = checked;
+ cbox.dataset.idx = i;
+ cbox.onclick = cboxOnClick;
+
+ breakCell.append(cbox);
+ line.append(breakCell, this.#c("td", i.toString()));
+ const fn = opMap[operatorList.fnArray[i]];
+ let decArgs = args;
+ if (fn === "showText") {
+ const glyphs = args[0];
+ const charCodeRow = this.#c("tr");
+ const fontCharRow = this.#c("tr");
+ const unicodeRow = this.#c("tr");
+ for (const glyph of glyphs) {
+ if (typeof glyph === "object" && glyph !== null) {
+ charCodeRow.append(this.#c("td", glyph.originalCharCode));
+ fontCharRow.append(this.#c("td", glyph.fontChar));
+ unicodeRow.append(this.#c("td", glyph.unicode));
+ } else {
+ // null or number
+ const advanceEl = this.#c("td", glyph);
+ advanceEl.classList.add("advance");
+ charCodeRow.append(advanceEl);
+ fontCharRow.append(this.#c("td"));
+ unicodeRow.append(this.#c("td"));
+ }
+ }
+ decArgs = this.#c("td");
+ const table = this.#c("table");
+ table.classList.add("showText");
+ decArgs.append(table);
+ table.append(charCodeRow, fontCharRow, unicodeRow);
+ } else if (fn === "restore" && this.indentLevel > 0) {
+ this.indentLevel--;
+ }
+ line.append(this.#c("td", " ".repeat(this.indentLevel * 2) + fn));
+ if (fn === "save") {
+ this.indentLevel++;
+ }
+
+ if (decArgs instanceof HTMLElement) {
+ line.append(decArgs);
+ } else {
+ line.append(this.#c("td", JSON.stringify(this.#simplifyArgs(decArgs))));
+ }
+ }
+ if (operatorsToDisplay < operatorList.fnArray.length) {
+ const lastCell = this.#c("td", "...");
+ lastCell.colspan = 4;
+ chunk.append(lastCell);
+ }
+ this.operatorListIdx = operatorList.fnArray.length;
+ this.table.append(chunk);
+ }
+
+ getNextBreakPoint() {
+ this.breakPoints.sort(function (a, b) {
+ return a - b;
+ });
+ for (const breakPoint of this.breakPoints) {
+ if (breakPoint > this.currentIdx) {
+ return breakPoint;
+ }
+ }
+ return null;
+ }
+
+ breakIt(idx, callback) {
+ StepperManager.selectStepper(this.pageIndex, true);
+ this.currentIdx = idx;
+
+ const listener = evt => {
+ switch (evt.keyCode) {
+ case 83: // step
+ document.removeEventListener("keydown", listener);
+ this.nextBreakPoint = this.currentIdx + 1;
+ this.goTo(-1);
+ callback();
+ break;
+ case 67: // continue
+ document.removeEventListener("keydown", listener);
+ this.nextBreakPoint = this.getNextBreakPoint();
+ this.goTo(-1);
+ callback();
+ break;
+ }
+ };
+ document.addEventListener("keydown", listener);
+ this.goTo(idx);
+ }
+
+ goTo(idx) {
+ const allRows = this.panel.getElementsByClassName("line");
+ for (const row of allRows) {
+ if ((row.dataset.idx | 0) === idx) {
+ row.style.backgroundColor = "rgb(251,250,207)";
+ row.scrollIntoView();
+ } else {
+ row.style.backgroundColor = null;
+ }
+ }
+ }
+}
+
+const Stats = (function Stats() {
+ let stats = [];
+ function clear(node) {
+ node.textContent = ""; // Remove any `node` contents from the DOM.
+ }
+ function getStatIndex(pageNumber) {
+ for (const [i, stat] of stats.entries()) {
+ if (stat.pageNumber === pageNumber) {
+ return i;
+ }
+ }
+ return false;
+ }
+ return {
+ // Properties/functions needed by PDFBug.
+ id: "Stats",
+ name: "Stats",
+ panel: null,
+ manager: null,
+ init() {},
+ enabled: false,
+ active: false,
+ // Stats specific functions.
+ add(pageNumber, stat) {
+ if (!stat) {
+ return;
+ }
+ const statsIndex = getStatIndex(pageNumber);
+ if (statsIndex !== false) {
+ stats[statsIndex].div.remove();
+ stats.splice(statsIndex, 1);
+ }
+ const wrapper = document.createElement("div");
+ wrapper.className = "stats";
+ const title = document.createElement("div");
+ title.className = "title";
+ title.textContent = "Page: " + pageNumber;
+ const statsDiv = document.createElement("div");
+ statsDiv.textContent = stat.toString();
+ wrapper.append(title, statsDiv);
+ stats.push({ pageNumber, div: wrapper });
+ stats.sort(function (a, b) {
+ return a.pageNumber - b.pageNumber;
+ });
+ clear(this.panel);
+ for (const entry of stats) {
+ this.panel.append(entry.div);
+ }
+ },
+ cleanup() {
+ stats = [];
+ clear(this.panel);
+ },
+ };
+})();
+
+// Manages all the debugging tools.
+class PDFBug {
+ static #buttons = [];
+
+ static #activePanel = null;
+
+ static tools = [FontInspector, StepperManager, Stats];
+
+ static enable(ids) {
+ const all = ids.length === 1 && ids[0] === "all";
+ const tools = this.tools;
+ for (const tool of tools) {
+ if (all || ids.includes(tool.id)) {
+ tool.enabled = true;
+ }
+ }
+ if (!all) {
+ // Sort the tools by the order they are enabled.
+ tools.sort(function (a, b) {
+ let indexA = ids.indexOf(a.id);
+ indexA = indexA < 0 ? tools.length : indexA;
+ let indexB = ids.indexOf(b.id);
+ indexB = indexB < 0 ? tools.length : indexB;
+ return indexA - indexB;
+ });
+ }
+ }
+
+ static init(container, ids) {
+ this.loadCSS();
+ this.enable(ids);
+ /*
+ * Basic Layout:
+ * PDFBug
+ * Controls
+ * Panels
+ * Panel
+ * Panel
+ * ...
+ */
+ const ui = document.createElement("div");
+ ui.id = "PDFBug";
+
+ const controls = document.createElement("div");
+ controls.setAttribute("class", "controls");
+ ui.append(controls);
+
+ const panels = document.createElement("div");
+ panels.setAttribute("class", "panels");
+ ui.append(panels);
+
+ container.append(ui);
+ container.style.right = "var(--panel-width)";
+
+ // Initialize all the debugging tools.
+ for (const tool of this.tools) {
+ const panel = document.createElement("div");
+ const panelButton = document.createElement("button");
+ panelButton.textContent = tool.name;
+ panelButton.addEventListener("click", event => {
+ event.preventDefault();
+ this.selectPanel(tool);
+ });
+ controls.append(panelButton);
+ panels.append(panel);
+ tool.panel = panel;
+ tool.manager = this;
+ if (tool.enabled) {
+ tool.init();
+ } else {
+ panel.textContent =
+ `${tool.name} is disabled. To enable add "${tool.id}" to ` +
+ "the pdfBug parameter and refresh (separate multiple by commas).";
+ }
+ this.#buttons.push(panelButton);
+ }
+ this.selectPanel(0);
+ }
+
+ static loadCSS() {
+ const { url } = import.meta;
+
+ const link = document.createElement("link");
+ link.rel = "stylesheet";
+ link.href = url.replace(/\.mjs$/, ".css");
+
+ document.head.append(link);
+ }
+
+ static cleanup() {
+ for (const tool of this.tools) {
+ if (tool.enabled) {
+ tool.cleanup();
+ }
+ }
+ }
+
+ static selectPanel(index) {
+ if (typeof index !== "number") {
+ index = this.tools.indexOf(index);
+ }
+ if (index === this.#activePanel) {
+ return;
+ }
+ this.#activePanel = index;
+ for (const [j, tool] of this.tools.entries()) {
+ const isActive = j === index;
+ this.#buttons[j].classList.toggle("active", isActive);
+ tool.active = isActive;
+ tool.panel.hidden = !isActive;
+ }
+ }
+}
+
+globalThis.FontInspector = FontInspector;
+globalThis.StepperManager = StepperManager;
+globalThis.Stats = Stats;
+
+export { PDFBug };
diff --git a/toolkit/components/pdfjs/content/web/images/altText_add.svg b/toolkit/components/pdfjs/content/web/images/altText_add.svg
new file mode 100644
index 0000000000..3451b536ce
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/images/altText_add.svg
@@ -0,0 +1,3 @@
+<svg width="12" height="13" viewBox="0 0 12 13" fill="none" xmlns="http://www.w3.org/2000/svg">
+ <path d="M5.375 7.625V11.875C5.375 12.0408 5.44085 12.1997 5.55806 12.3169C5.67527 12.4342 5.83424 12.5 6 12.5C6.16576 12.5 6.32473 12.4342 6.44194 12.3169C6.55915 12.1997 6.625 12.0408 6.625 11.875V7.625L7.125 7.125H11.375C11.5408 7.125 11.6997 7.05915 11.8169 6.94194C11.9342 6.82473 12 6.66576 12 6.5C12 6.33424 11.9342 6.17527 11.8169 6.05806C11.6997 5.94085 11.5408 5.875 11.375 5.875H7.125L6.625 5.375V1.125C6.625 0.95924 6.55915 0.800269 6.44194 0.683058C6.32473 0.565848 6.16576 0.5 6 0.5C5.83424 0.5 5.67527 0.565848 5.55806 0.683058C5.44085 0.800269 5.375 0.95924 5.375 1.125V5.375L4.875 5.875H0.625C0.45924 5.875 0.300269 5.94085 0.183058 6.05806C0.065848 6.17527 0 6.33424 0 6.5C0 6.66576 0.065848 6.82473 0.183058 6.94194C0.300269 7.05915 0.45924 7.125 0.625 7.125H4.762L5.375 7.625Z" fill="black"/>
+</svg>
diff --git a/toolkit/components/pdfjs/content/web/images/altText_done.svg b/toolkit/components/pdfjs/content/web/images/altText_done.svg
new file mode 100644
index 0000000000..f54924ebf9
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/images/altText_done.svg
@@ -0,0 +1,3 @@
+<svg width="12" height="13" viewBox="0 0 12 13" fill="none" xmlns="http://www.w3.org/2000/svg">
+ <path d="M6 0.5C5.21207 0.5 4.43185 0.655195 3.7039 0.956723C2.97595 1.25825 2.31451 1.70021 1.75736 2.25736C1.20021 2.81451 0.758251 3.47595 0.456723 4.2039C0.155195 4.93185 0 5.71207 0 6.5C0 7.28793 0.155195 8.06815 0.456723 8.7961C0.758251 9.52405 1.20021 10.1855 1.75736 10.7426C2.31451 11.2998 2.97595 11.7417 3.7039 12.0433C4.43185 12.3448 5.21207 12.5 6 12.5C7.5913 12.5 9.11742 11.8679 10.2426 10.7426C11.3679 9.61742 12 8.0913 12 6.5C12 4.9087 11.3679 3.38258 10.2426 2.25736C9.11742 1.13214 7.5913 0.5 6 0.5ZM5.06 8.9L2.9464 6.7856C2.85273 6.69171 2.80018 6.56446 2.80033 6.43183C2.80048 6.29921 2.85331 6.17207 2.9472 6.0784C3.04109 5.98473 3.16834 5.93218 3.30097 5.93233C3.43359 5.93248 3.56073 5.98531 3.6544 6.0792L5.3112 7.7368L8.3464 4.7008C8.44109 4.6109 8.56715 4.56153 8.69771 4.56322C8.82827 4.56492 8.95301 4.61754 9.04534 4.70986C9.13766 4.80219 9.19028 4.92693 9.19198 5.05749C9.19367 5.18805 9.1443 5.31411 9.0544 5.4088L5.5624 8.9H5.06Z" fill="#FBFBFE"/>
+</svg>
diff --git a/toolkit/components/pdfjs/content/web/images/annotation-check.svg b/toolkit/components/pdfjs/content/web/images/annotation-check.svg
new file mode 100644
index 0000000000..71cd16df57
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/images/annotation-check.svg
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns="http://www.w3.org/2000/svg"
+ width="40"
+ height="40"
+ viewBox="0 0 40 40">
+ <path
+ d="M 1.5006714,23.536225 6.8925879,18.994244 14.585721,26.037937 34.019683,4.5410479 38.499329,9.2235032 14.585721,35.458952 z"
+ id="path4"
+ style="fill:#ffff00;fill-opacity:1;stroke:#000000;stroke-width:1.25402856;stroke-opacity:1" />
+</svg>
diff --git a/toolkit/components/pdfjs/content/web/images/annotation-comment.svg b/toolkit/components/pdfjs/content/web/images/annotation-comment.svg
new file mode 100644
index 0000000000..86f1f17249
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/images/annotation-comment.svg
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns="http://www.w3.org/2000/svg"
+ height="40"
+ width="40"
+ viewBox="0 0 40 40">
+ <rect
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ width="33.76017"
+ height="33.76017"
+ x="3.119915"
+ y="3.119915" />
+ <path
+ d="m 20.677967,8.54499 c -7.342801,0 -13.295293,4.954293 -13.295293,11.065751 0,2.088793 0.3647173,3.484376 1.575539,5.150563 L 6.0267418,31.45501 13.560595,29.011117 c 2.221262,1.387962 4.125932,1.665377 7.117372,1.665377 7.3428,0 13.295291,-4.954295 13.295291,-11.065753 0,-6.111458 -5.952491,-11.065751 -13.295291,-11.065751 z"
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.93031836;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"/>
+</svg>
diff --git a/toolkit/components/pdfjs/content/web/images/annotation-help.svg b/toolkit/components/pdfjs/content/web/images/annotation-help.svg
new file mode 100644
index 0000000000..00938fefe0
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/images/annotation-help.svg
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns="http://www.w3.org/2000/svg"
+ width="40"
+ height="40"
+ viewBox="0 0 40 40">
+ <g
+ transform="translate(0,-60)"
+ id="layer1">
+ <rect
+ width="36.460953"
+ height="34.805603"
+ x="1.7695236"
+ y="62.597198"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.30826771;stroke-opacity:1" />
+ <g
+ transform="matrix(0.88763677,0,0,0.88763677,2.2472646,8.9890584)">
+ <path
+ d="M 20,64.526342 C 11.454135,64.526342 4.5263421,71.454135 4.5263421,80 4.5263421,88.545865 11.454135,95.473658 20,95.473658 28.545865,95.473658 35.473658,88.545865 35.473658,80 35.473658,71.454135 28.545865,64.526342 20,64.526342 z m -0.408738,9.488564 c 3.527079,0 6.393832,2.84061 6.393832,6.335441 0,3.494831 -2.866753,6.335441 -6.393832,6.335441 -3.527079,0 -6.393832,-2.84061 -6.393832,-6.335441 0,-3.494831 2.866753,-6.335441 6.393832,-6.335441 z"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.02768445;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <path
+ d="m 7.2335209,71.819938 4.9702591,4.161823 c -1.679956,2.581606 -1.443939,6.069592 0.159325,8.677725 l -5.1263071,3.424463 c 0.67516,1.231452 3.0166401,3.547686 4.2331971,4.194757 l 3.907728,-4.567277 c 2.541952,1.45975 5.730694,1.392161 8.438683,-0.12614 l 3.469517,6.108336 c 1.129779,-0.44367 4.742234,-3.449633 5.416358,-5.003859 l -5.46204,-4.415541 c 1.44319,-2.424098 1.651175,-5.267515 0.557303,-7.748623 l 5.903195,-3.833951 C 33.14257,71.704996 30.616217,69.018606 29.02952,67.99296 l -4.118813,4.981678 C 22.411934,71.205099 18.900853,70.937534 16.041319,72.32916 l -3.595408,-5.322091 c -1.345962,0.579488 -4.1293881,2.921233 -5.2123901,4.812869 z m 8.1010311,3.426672 c 2.75284,-2.446266 6.769149,-2.144694 9.048998,0.420874 2.279848,2.56557 2.113919,6.596919 -0.638924,9.043185 -2.752841,2.446267 -6.775754,2.13726 -9.055604,-0.428308 -2.279851,-2.565568 -2.107313,-6.589485 0.64553,-9.035751 z"
+ style="fill:#000000;fill-opacity:1;stroke:none" />
+ </g>
+ </g>
+</svg>
diff --git a/toolkit/components/pdfjs/content/web/images/annotation-insert.svg b/toolkit/components/pdfjs/content/web/images/annotation-insert.svg
new file mode 100644
index 0000000000..519ef6826e
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/images/annotation-insert.svg
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns="http://www.w3.org/2000/svg"
+ width="64"
+ height="64"
+ viewBox="0 0 64 64">
+ <path
+ d="M 32.003143,1.4044602 57.432701,62.632577 6.5672991,62.627924 z"
+ style="fill:#ffff00;fill-opacity:0.94117647;fill-rule:nonzero;stroke:#000000;stroke-width:1.00493038;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+</svg>
diff --git a/toolkit/components/pdfjs/content/web/images/annotation-key.svg b/toolkit/components/pdfjs/content/web/images/annotation-key.svg
new file mode 100644
index 0000000000..8d09d5378d
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/images/annotation-key.svg
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns="http://www.w3.org/2000/svg"
+ width="64"
+ height="64"
+ viewBox="0 0 64 64">
+ <path
+ d="M 25.470843,9.4933766 C 25.30219,12.141818 30.139101,14.445969 34.704831,13.529144 40.62635,12.541995 41.398833,7.3856498 35.97505,5.777863 31.400921,4.1549155 25.157674,6.5445892 25.470843,9.4933766 z M 4.5246282,17.652051 C 4.068249,11.832873 9.2742983,5.9270407 18.437379,3.0977088 29.751911,-0.87185184 45.495663,1.4008022 53.603953,7.1104009 c 9.275765,6.1889221 7.158128,16.2079421 -3.171076,21.5939521 -1.784316,1.635815 -6.380222,1.21421 -7.068351,3.186186 -1.04003,0.972427 -1.288046,2.050158 -1.232864,3.168203 1.015111,2.000108 -3.831548,1.633216 -3.270553,3.759574 0.589477,5.264544 -0.179276,10.53738 -0.362842,15.806257 -0.492006,2.184998 1.163456,4.574232 -0.734888,6.610642 -2.482919,2.325184 -7.30604,2.189143 -9.193497,-0.274767 -2.733688,-1.740626 -8.254447,-3.615254 -6.104247,-6.339626 3.468112,-1.708686 -2.116197,-3.449897 0.431242,-5.080274 5.058402,-1.39256 -2.393215,-2.304318 -0.146889,-4.334645 3.069198,-0.977415 2.056986,-2.518352 -0.219121,-3.540397 1.876567,-1.807151 1.484149,-4.868919 -2.565455,-5.942205 0.150866,-1.805474 2.905737,-4.136876 -1.679967,-5.20493 C 10.260902,27.882167 4.6872697,22.95045 4.5245945,17.652051 z"
+ id="path604"
+ style="fill:#ffff00;fill-opacity:1;stroke:#000000;stroke-width:1.72665179;stroke-opacity:1" />
+</svg>
diff --git a/toolkit/components/pdfjs/content/web/images/annotation-newparagraph.svg b/toolkit/components/pdfjs/content/web/images/annotation-newparagraph.svg
new file mode 100644
index 0000000000..38d2497da9
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/images/annotation-newparagraph.svg
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns="http://www.w3.org/2000/svg"
+ width="64"
+ height="64"
+ viewBox="0 0 64 64">
+ <path
+ d="M 32.003143,10.913072 57.432701,53.086929 6.567299,53.083723 z"
+ id="path2985"
+ style="fill:#ffff00;fill-opacity:0.94117647;fill-rule:nonzero;stroke:#000000;stroke-width:0.83403099;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+</svg>
diff --git a/toolkit/components/pdfjs/content/web/images/annotation-noicon.svg b/toolkit/components/pdfjs/content/web/images/annotation-noicon.svg
new file mode 100644
index 0000000000..c07d108083
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/images/annotation-noicon.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns="http://www.w3.org/2000/svg"
+ width="40"
+ height="40"
+ viewBox="0 0 40 40">
+</svg>
diff --git a/toolkit/components/pdfjs/content/web/images/annotation-note.svg b/toolkit/components/pdfjs/content/web/images/annotation-note.svg
new file mode 100644
index 0000000000..70173651c7
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/images/annotation-note.svg
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns="http://www.w3.org/2000/svg"
+ width="40"
+ height="40"
+ viewBox="0 0 40 40">
+ <rect
+ width="36.075428"
+ height="31.096582"
+ x="1.962286"
+ y="4.4517088"
+ id="rect4"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.23004246;stroke-opacity:1" />
+ <rect
+ width="27.96859"
+ height="1.5012145"
+ x="6.0157046"
+ y="10.285"
+ id="rect6"
+ style="fill:#000000;fill-opacity:1;stroke:none" />
+ <rect
+ width="27.96859"
+ height="0.85783684"
+ x="6.0157056"
+ y="23.21689"
+ id="rect8"
+ style="fill:#000000;fill-opacity:1;stroke:none" />
+ <rect
+ width="27.96859"
+ height="0.85783684"
+ x="5.8130345"
+ y="28.964394"
+ id="rect10"
+ style="fill:#000000;fill-opacity:1;stroke:none" />
+ <rect
+ width="27.96859"
+ height="0.85783684"
+ x="6.0157046"
+ y="17.426493"
+ id="rect12"
+ style="fill:#000000;fill-opacity:1;stroke:none" />
+</svg>
diff --git a/toolkit/components/pdfjs/content/web/images/annotation-paperclip.svg b/toolkit/components/pdfjs/content/web/images/annotation-paperclip.svg
new file mode 100644
index 0000000000..2bed2250ae
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/images/annotation-paperclip.svg
@@ -0,0 +1,6 @@
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" height="40" width="40">
+ <path d="M9 3.5a1.5 1.5 0 0 0-3-.001v7.95C6 12.83 7.12 14 8.5 14s2.5-1.17 2.5-2.55V5.5a.5.5 0 0 1 1 0v6.03C11.955 13.427 10.405 15 8.5 15S5.044 13.426 5 11.53V3.5a2.5 2.5 0 0 1 5 0v7.003a1.5 1.5 0 0 1-3-.003v-5a.5.5 0 0 1 1 0v5a.5.5 0 0 0 1 0Z"/>
+</svg>
diff --git a/toolkit/components/pdfjs/content/web/images/annotation-paragraph.svg b/toolkit/components/pdfjs/content/web/images/annotation-paragraph.svg
new file mode 100644
index 0000000000..6ae5212b75
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/images/annotation-paragraph.svg
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns="http://www.w3.org/2000/svg"
+ width="40"
+ height="40"
+ viewBox="0 0 40 40">
+ <rect
+ width="33.76017"
+ height="33.76017"
+ x="3.119915"
+ y="3.119915"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <path
+ d="m 17.692678,34.50206 0,-16.182224 c -1.930515,-0.103225 -3.455824,-0.730383 -4.57593,-1.881473 -1.12011,-1.151067 -1.680164,-2.619596 -1.680164,-4.405591 0,-1.992435 0.621995,-3.5796849 1.865988,-4.7617553 1.243989,-1.1820288 3.06352,-1.7730536 5.458598,-1.7730764 l 9.802246,0 0,2.6789711 -2.229895,0 0,26.3251486 -2.632515,0 0,-26.3251486 -3.45324,0 0,26.3251486 z"
+ style="font-size:29.42051125px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.07795751;stroke-opacity:1;font-family:Arial;-inkscape-font-specification:Arial" />
+</svg>
diff --git a/toolkit/components/pdfjs/content/web/images/annotation-pushpin.svg b/toolkit/components/pdfjs/content/web/images/annotation-pushpin.svg
new file mode 100644
index 0000000000..6e0896cf4a
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/images/annotation-pushpin.svg
@@ -0,0 +1,7 @@
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" height="40" width="40">
+ <path d="M8.156 12.5a.99.99 0 0 0 .707-.294l.523-2.574L10.5 8.499l1.058-1.04 2.65-.601a.996.996 0 0 0 0-1.414l-3.657-3.658a.996.996 0 0 0-1.414 0l-.523 2.576L7.5 5.499 6.442 6.535l-2.65.6a.996.996 0 0 0 0 1.413l3.657 3.658a.999.999 0 0 0 .707.295z"/>
+ <path d="M9.842.996c-.386 0-.77.146-1.06.44a.5.5 0 0 0-.136.251l-.492 2.43-1.008 1.03-.953.933-2.511.566a.5.5 0 0 0-.243.133 1.505 1.505 0 0 0-.002 2.123l1.477 1.477-2.768 2.767a.5.5 0 0 0 0 .707.5.5 0 0 0 .708 0l2.767-2.767 1.475 1.474a1.494 1.494 0 0 0 2.123-.002.5.5 0 0 0 .135-.254l.492-2.427 1.008-1.024.953-.937 2.511-.57a.5.5 0 0 0 .243-.132c.586-.58.583-1.543.002-2.125l-3.659-3.656A1.501 1.501 0 0 0 9.842.996Zm.05 1.025a.394.394 0 0 1 .305.12l3.658 3.657c.18.18.141.432.002.627l-2.41.545a.5.5 0 0 0-.24.131L10.15 8.142a.5.5 0 0 0-.007.006L9.029 9.283a.5.5 0 0 0-.133.25l-.48 2.36c-.082.053-.165.109-.26.109a.492.492 0 0 1-.353-.149L4.145 8.195c-.18-.18-.141-.432-.002-.627l2.41-.545a.5.5 0 0 0 .238-.13L7.85 5.857a.5.5 0 0 0 .007-.008l1.114-1.138a.5.5 0 0 0 .133-.25l.472-2.323a.619.619 0 0 1 .317-.117Z"/>
+</svg>
diff --git a/toolkit/components/pdfjs/content/web/images/cursor-editorFreeHighlight.svg b/toolkit/components/pdfjs/content/web/images/cursor-editorFreeHighlight.svg
new file mode 100644
index 0000000000..513f6bdfda
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/images/cursor-editorFreeHighlight.svg
@@ -0,0 +1,6 @@
+<svg width="18" height="19" viewBox="0 0 18 19" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path fill-rule="evenodd" clip-rule="evenodd" d="M12.2 3.09C12.28 3.01 12.43 3 12.43 3C12.48 3 12.58 3.02 12.66 3.1L14.45 4.89C14.58 5.02 14.58 5.22 14.45 5.35L11.7713 8.02872L9.51628 5.77372L12.2 3.09ZM13.2658 5.12L11.7713 6.6145L10.9305 5.77372L12.425 4.27921L13.2658 5.12Z" fill="#FBFBFE"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M5.98 9.32L8.23 11.57L10.7106 9.08938L8.45562 6.83438L5.98 9.31V9.32ZM8.23 10.1558L9.29641 9.08938L8.45562 8.24859L7.38921 9.315L8.23 10.1558Z" fill="#FBFBFE"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M10.1526 13.1816L16.2125 7.1217C16.7576 6.58919 17.05 5.8707 17.05 5.12C17.05 4.36931 16.7576 3.65084 16.2126 3.11834L14.4317 1.33747C13.8992 0.79242 13.1807 0.5 12.43 0.5C11.6643 0.5 10.9529 0.812929 10.4329 1.33289L3.68289 8.08289C3.04127 8.72452 3.00459 9.75075 3.57288 10.4363L1.29187 12.7239C1.09186 12.9245 0.990263 13.1957 1.0007 13.4685L1 14.5C0.447715 14.5 0 14.9477 0 15.5V17.5C0 18.0523 0.447715 18.5 1 18.5H16C16.5523 18.5 17 18.0523 17 17.5V15.5C17 14.9477 16.5523 14.5 16 14.5H10.2325C9.83594 14.5 9.39953 13.9347 10.1526 13.1816ZM4.39 9.85L4.9807 10.4407L2.39762 13.0312H6.63877L7.10501 12.565L7.57125 13.0312H8.88875L15.51 6.41C15.86 6.07 16.05 5.61 16.05 5.12C16.05 4.63 15.86 4.17 15.51 3.83L13.72 2.04C13.38 1.69 12.92 1.5 12.43 1.5C11.94 1.5 11.48 1.7 11.14 2.04L4.39 8.79C4.1 9.08 4.1 9.56 4.39 9.85ZM16 17.5V15.5H1V17.5H16Z" fill="#FBFBFE"/>
+<path d="M15.1616 6.05136L15.1616 6.05132L15.1564 6.05645L8.40645 12.8064C8.35915 12.8537 8.29589 12.88 8.23 12.88C8.16411 12.88 8.10085 12.8537 8.05355 12.8064L7.45857 12.2115L7.10501 11.8579L6.75146 12.2115L6.03289 12.93H3.20465L5.33477 10.7937L5.6873 10.4402L5.33426 10.0871L4.74355 9.49645C4.64882 9.40171 4.64882 9.23829 4.74355 9.14355L11.4936 2.39355C11.7436 2.14354 12.0779 2 12.43 2C12.7883 2 13.1179 2.13776 13.3614 2.38839L13.3613 2.38843L13.3664 2.39355L15.1564 4.18355L15.1564 4.18359L15.1616 4.18864C15.4122 4.43211 15.55 4.76166 15.55 5.12C15.55 5.47834 15.4122 5.80789 15.1616 6.05136ZM7.87645 11.9236L8.23 12.2771L8.58355 11.9236L11.0642 9.44293L11.4177 9.08938L11.0642 8.73582L8.80918 6.48082L8.45562 6.12727L8.10207 6.48082L5.62645 8.95645L5.48 9.10289V9.31V9.32V9.52711L5.62645 9.67355L7.87645 11.9236ZM11.4177 8.38227L11.7713 8.73582L12.1248 8.38227L14.8036 5.70355C15.1288 5.37829 15.1288 4.86171 14.8036 4.53645L13.0136 2.74645C12.8186 2.55146 12.5792 2.5 12.43 2.5H12.4134L12.3967 2.50111L12.43 3C12.3967 2.50111 12.3966 2.50112 12.3965 2.50112L12.3963 2.50114L12.3957 2.50117L12.3947 2.50125L12.3924 2.50142L12.387 2.50184L12.3732 2.50311C12.3628 2.50416 12.3498 2.50567 12.3346 2.50784C12.3049 2.51208 12.2642 2.51925 12.2178 2.53146C12.1396 2.55202 11.9797 2.60317 11.8464 2.73645L9.16273 5.42016L8.80918 5.77372L9.16273 6.12727L11.4177 8.38227ZM1.5 16H15.5V17H1.5V16Z" stroke="#15141A"/>
+</svg>
diff --git a/toolkit/components/pdfjs/content/web/images/cursor-editorFreeText.svg b/toolkit/components/pdfjs/content/web/images/cursor-editorFreeText.svg
new file mode 100644
index 0000000000..de2838ef10
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/images/cursor-editorFreeText.svg
@@ -0,0 +1,3 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M12 2.75H12.5V2.25V1V0.5H12H10.358C9.91165 0.5 9.47731 0.625661 9.09989 0.860442L9.09886 0.861087L8 1.54837L6.89997 0.860979L6.89911 0.860443C6.5218 0.625734 6.08748 0.5 5.642 0.5H4H3.5V1V2.25V2.75H4H5.642C5.66478 2.75 5.6885 2.75641 5.71008 2.76968C5.71023 2.76977 5.71038 2.76986 5.71053 2.76995L6.817 3.461C6.81704 3.46103 6.81709 3.46105 6.81713 3.46108C6.81713 3.46108 6.81713 3.46108 6.81714 3.46109C6.8552 3.48494 6.876 3.52285 6.876 3.567V8V12.433C6.876 12.4771 6.85523 12.515 6.81722 12.5389C6.81715 12.5389 6.81707 12.539 6.817 12.539L5.70953 13.23C5.70941 13.2301 5.70929 13.2302 5.70917 13.2303C5.68723 13.2438 5.6644 13.25 5.641 13.25H4H3.5V13.75V15V15.5H4H5.642C6.08835 15.5 6.52269 15.3743 6.90011 15.1396L6.90086 15.1391L8 14.4526L9.10003 15.14L9.10089 15.1406C9.47831 15.3753 9.91265 15.501 10.359 15.501H12H12.5V15.001V13.751V13.251H12H10.358C10.3352 13.251 10.3115 13.2446 10.2899 13.2313C10.2897 13.2312 10.2896 13.2311 10.2895 13.231L9.183 12.54C9.18298 12.54 9.18295 12.54 9.18293 12.54C9.18291 12.5399 9.18288 12.5399 9.18286 12.5399C9.14615 12.5169 9.125 12.4797 9.125 12.434V8V3.567C9.125 3.52266 9.14603 3.48441 9.18364 3.4606C9.18377 3.46052 9.1839 3.46043 9.18404 3.46035L10.2895 2.76995C10.2896 2.76985 10.2898 2.76975 10.2899 2.76966C10.3119 2.75619 10.3346 2.75 10.358 2.75H12Z" fill="black" stroke="white"/>
+</svg>
diff --git a/toolkit/components/pdfjs/content/web/images/cursor-editorInk.svg b/toolkit/components/pdfjs/content/web/images/cursor-editorInk.svg
new file mode 100644
index 0000000000..1dadb5c015
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/images/cursor-editorInk.svg
@@ -0,0 +1,4 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M0.0189877 13.6645L0.612989 10.4635C0.687989 10.0545 0.884989 9.6805 1.18099 9.3825L9.98199 0.5805C10.756 -0.1925 12.015 -0.1945 12.792 0.5805L14.42 2.2085C15.194 2.9835 15.194 4.2435 14.42 5.0185L5.61599 13.8215C5.31999 14.1165 4.94599 14.3125 4.53799 14.3875L1.33599 14.9815C1.26599 14.9935 1.19799 15.0005 1.12999 15.0005C0.832989 15.0005 0.544988 14.8835 0.330988 14.6695C0.0679874 14.4055 -0.0490122 14.0305 0.0189877 13.6645Z" fill="white"/>
+<path d="M0.0189877 13.6645L0.612989 10.4635C0.687989 10.0545 0.884989 9.6805 1.18099 9.3825L9.98199 0.5805C10.756 -0.1925 12.015 -0.1945 12.792 0.5805L14.42 2.2085C15.194 2.9835 15.194 4.2435 14.42 5.0185L5.61599 13.8215C5.31999 14.1165 4.94599 14.3125 4.53799 14.3875L1.33599 14.9815C1.26599 14.9935 1.19799 15.0005 1.12999 15.0005C0.832989 15.0005 0.544988 14.8835 0.330988 14.6695C0.0679874 14.4055 -0.0490122 14.0305 0.0189877 13.6645ZM12.472 5.1965L13.632 4.0365L13.631 3.1885L11.811 1.3675L10.963 1.3685L9.80299 2.5285L12.472 5.1965ZM4.31099 13.1585C4.47099 13.1285 4.61799 13.0515 4.73399 12.9345L11.587 6.0815L8.91899 3.4135L2.06599 10.2655C1.94899 10.3835 1.87199 10.5305 1.84099 10.6915L1.36699 13.2485L1.75199 13.6335L4.31099 13.1585Z" fill="black"/>
+</svg>
diff --git a/toolkit/components/pdfjs/content/web/images/cursor-editorTextHighlight.svg b/toolkit/components/pdfjs/content/web/images/cursor-editorTextHighlight.svg
new file mode 100644
index 0000000000..800340cb5b
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/images/cursor-editorTextHighlight.svg
@@ -0,0 +1,8 @@
+<svg width="29" height="32" viewBox="0 0 29 32" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M28 16.75C28.2761 16.75 28.5 16.5261 28.5 16.25V15C28.5 14.7239 28.2761 14.5 28 14.5H26.358C25.9117 14.5 25.4773 14.6257 25.0999 14.8604L25.0989 14.8611L24 15.5484L22.9 14.861L22.8991 14.8604C22.5218 14.6257 22.0875 14.5 21.642 14.5H20C19.7239 14.5 19.5 14.7239 19.5 15V16.25C19.5 16.5261 19.7239 16.75 20 16.75H21.642C21.6648 16.75 21.6885 16.7564 21.7101 16.7697C21.7102 16.7698 21.7104 16.7699 21.7105 16.77L22.817 17.461C22.817 17.461 22.8171 17.4611 22.8171 17.4611C22.8171 17.4611 22.8171 17.4611 22.8171 17.4611C22.8552 17.4849 22.876 17.5229 22.876 17.567V22.625V27.683C22.876 27.7271 22.8552 27.765 22.8172 27.7889C22.8171 27.7889 22.8171 27.789 22.817 27.789L21.7095 28.48C21.7094 28.4801 21.7093 28.4802 21.7092 28.4803C21.6872 28.4938 21.6644 28.5 21.641 28.5H20C19.7239 28.5 19.5 28.7239 19.5 29V30.25C19.5 30.5261 19.7239 30.75 20 30.75H21.642C22.0883 30.75 22.5227 30.6243 22.9001 30.3896L22.9009 30.3891L24 29.7026L25.1 30.39L25.1009 30.3906C25.4783 30.6253 25.9127 30.751 26.359 30.751H28C28.2761 30.751 28.5 30.5271 28.5 30.251V29.001C28.5 28.7249 28.2761 28.501 28 28.501H26.358C26.3352 28.501 26.3115 28.4946 26.2899 28.4813C26.2897 28.4812 26.2896 28.4811 26.2895 28.481L25.183 27.79C25.183 27.79 25.183 27.79 25.1829 27.79C25.1829 27.7899 25.1829 27.7899 25.1829 27.7899C25.1462 27.7669 25.125 27.7297 25.125 27.684V22.625V17.567C25.125 17.5227 25.146 17.4844 25.1836 17.4606C25.1838 17.4605 25.1839 17.4604 25.184 17.4603L26.2895 16.77C26.2896 16.7699 26.2898 16.7698 26.2899 16.7697C26.3119 16.7562 26.3346 16.75 26.358 16.75H28Z" fill="black" stroke="#FBFBFE" stroke-linejoin="round"/>
+<path d="M24.625 17.567C24.625 17.35 24.735 17.152 24.918 17.037L26.026 16.345C26.126 16.283 26.24 16.25 26.358 16.25H28V15H26.358C26.006 15 25.663 15.099 25.364 15.285L24.256 15.978C24.161 16.037 24.081 16.113 24 16.187C23.918 16.113 23.839 16.037 23.744 15.978L22.635 15.285C22.336 15.099 21.993 15 21.642 15H20V16.25H21.642C21.759 16.25 21.874 16.283 21.974 16.345L23.082 17.037C23.266 17.152 23.376 17.35 23.376 17.567V22.625V27.683C23.376 27.9 23.266 28.098 23.082 28.213L21.973 28.905C21.873 28.967 21.759 29 21.641 29H20V30.25H21.642C21.994 30.25 22.337 30.151 22.636 29.965L23.744 29.273C23.84 29.213 23.919 29.137 24 29.064C24.081 29.137 24.161 29.213 24.256 29.273L25.365 29.966C25.664 30.152 26.007 30.251 26.359 30.251H28V29.001H26.358C26.241 29.001 26.126 28.968 26.026 28.906L24.918 28.214C24.734 28.099 24.625 27.901 24.625 27.684V22.625V17.567Z" fill="black"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M12.2 2.59C12.28 2.51 12.43 2.5 12.43 2.5C12.48 2.5 12.58 2.52 12.66 2.6L14.45 4.39C14.58 4.52 14.58 4.72 14.45 4.85L11.7713 7.52872L9.51628 5.27372L12.2 2.59ZM13.2658 4.62L11.7713 6.1145L10.9305 5.27372L12.425 3.77921L13.2658 4.62Z" fill="#FBFBFE"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M5.98 8.82L8.23 11.07L10.7106 8.58938L8.45562 6.33438L5.98 8.81V8.82ZM8.23 9.65579L9.29641 8.58938L8.45562 7.74859L7.38921 8.815L8.23 9.65579Z" fill="#FBFBFE"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M10.1526 12.6816L16.2125 6.6217C16.7576 6.08919 17.05 5.3707 17.05 4.62C17.05 3.86931 16.7576 3.15084 16.2126 2.61834L14.4317 0.837474C13.8992 0.29242 13.1807 0 12.43 0C11.6643 0 10.9529 0.312929 10.4329 0.832893L3.68289 7.58289C3.04127 8.22452 3.00459 9.25075 3.57288 9.93634L1.29187 12.2239C1.09186 12.4245 0.990263 12.6957 1.0007 12.9685L1 14C0.447715 14 0 14.4477 0 15V17C0 17.5523 0.447715 18 1 18H16C16.5523 18 17 17.5523 17 17V15C17 14.4477 16.5523 14 16 14H10.2325C9.83594 14 9.39953 13.4347 10.1526 12.6816ZM4.39 9.35L4.9807 9.9407L2.39762 12.5312H6.63877L7.10501 12.065L7.57125 12.5312H8.88875L15.51 5.91C15.86 5.57 16.05 5.11 16.05 4.62C16.05 4.13 15.86 3.67 15.51 3.33L13.72 1.54C13.38 1.19 12.92 1 12.43 1C11.94 1 11.48 1.2 11.14 1.54L4.39 8.29C4.1 8.58 4.1 9.06 4.39 9.35ZM16 17V15H1V17H16Z" fill="#FBFBFE"/>
+<path d="M15.1616 5.55136L15.1616 5.55132L15.1564 5.55645L8.40645 12.3064C8.35915 12.3537 8.29589 12.38 8.23 12.38C8.16411 12.38 8.10085 12.3537 8.05355 12.3064L7.45857 11.7115L7.10501 11.3579L6.75146 11.7115L6.03289 12.43H3.20465L5.33477 10.2937L5.6873 9.94019L5.33426 9.58715L4.74355 8.99645C4.64882 8.90171 4.64882 8.73829 4.74355 8.64355L11.4936 1.89355C11.7436 1.64354 12.0779 1.5 12.43 1.5C12.7883 1.5 13.1179 1.63776 13.3614 1.88839L13.3613 1.88843L13.3664 1.89355L15.1564 3.68355L15.1564 3.68359L15.1616 3.68864C15.4122 3.93211 15.55 4.26166 15.55 4.62C15.55 4.97834 15.4122 5.30789 15.1616 5.55136ZM5.48 8.82V9.02711L5.62645 9.17355L7.87645 11.4236L8.23 11.7771L8.58355 11.4236L11.0642 8.94293L11.4177 8.58938L11.0642 8.23582L8.80918 5.98082L8.45562 5.62727L8.10207 5.98082L5.62645 8.45645L5.48 8.60289V8.81V8.82ZM11.4177 7.88227L11.7713 8.23582L12.1248 7.88227L14.8036 5.20355C15.1288 4.87829 15.1288 4.36171 14.8036 4.03645L13.0136 2.24645C12.8186 2.05146 12.5792 2 12.43 2H12.4134L12.3967 2.00111L12.43 2.5C12.3967 2.00111 12.3966 2.00112 12.3965 2.00112L12.3963 2.00114L12.3957 2.00117L12.3947 2.00125L12.3924 2.00142L12.387 2.00184L12.3732 2.00311C12.3628 2.00416 12.3498 2.00567 12.3346 2.00784C12.3049 2.01208 12.2642 2.01925 12.2178 2.03146C12.1396 2.05202 11.9797 2.10317 11.8464 2.23645L9.16273 4.92016L8.80918 5.27372L9.16273 5.62727L11.4177 7.88227ZM1.5 16.5V15.5H15.5V16.5H1.5Z" stroke="#15141A"/>
+</svg>
diff --git a/toolkit/components/pdfjs/content/web/images/editor-toolbar-delete.svg b/toolkit/components/pdfjs/content/web/images/editor-toolbar-delete.svg
new file mode 100644
index 0000000000..f84520d85a
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/images/editor-toolbar-delete.svg
@@ -0,0 +1,5 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+ <path fill-rule="evenodd" clip-rule="evenodd"
+ d="M11 3H13.6C14 3 14.3 3.3 14.3 3.6C14.3 3.9 14 4.2 13.7 4.2H13.3V14C13.3 15.1 12.4 16 11.3 16H4.80005C3.70005 16 2.80005 15.1 2.80005 14V4.2H2.40005C2.00005 4.2 1.80005 4 1.80005 3.6C1.80005 3.2 2.00005 3 2.40005 3H5.00005V2C5.00005 0.9 5.90005 0 7.00005 0H9.00005C10.1 0 11 0.9 11 2V3ZM6.90005 1.2L6.30005 1.8V3H9.80005V1.8L9.20005 1.2H6.90005ZM11.4 14.7L12 14.1V4.2H4.00005V14.1L4.60005 14.7H11.4ZM7.00005 12.4C7.00005 12.7 6.70005 13 6.40005 13C6.10005 13 5.80005 12.7 5.80005 12.4V7.6C5.70005 7.3 6.00005 7 6.40005 7C6.80005 7 7.00005 7.3 7.00005 7.6V12.4ZM10.2001 12.4C10.2001 12.7 9.90006 13 9.60006 13C9.30006 13 9.00006 12.7 9.00006 12.4V7.6C9.00006 7.3 9.30006 7 9.60006 7C9.90006 7 10.2001 7.3 10.2001 7.6V12.4Z"
+ fill="black" />
+</svg> \ No newline at end of file
diff --git a/toolkit/components/pdfjs/content/web/images/findbarButton-next.svg b/toolkit/components/pdfjs/content/web/images/findbarButton-next.svg
new file mode 100644
index 0000000000..8cb39bec6f
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/images/findbarButton-next.svg
@@ -0,0 +1,3 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M10.999 8.352L5.534 13.818C5.41551 13.9303 5.25786 13.9918 5.09466 13.9895C4.93146 13.9872 4.77561 13.9212 4.66033 13.8057C4.54505 13.6902 4.47945 13.5342 4.47752 13.3709C4.47559 13.2077 4.53748 13.0502 4.65 12.932L9.585 7.998L4.651 3.067C4.53862 2.94864 4.47691 2.79106 4.47903 2.62786C4.48114 2.46466 4.54692 2.30874 4.66233 2.19333C4.77774 2.07792 4.93366 2.01215 5.09686 2.01003C5.26006 2.00792 5.41763 2.06962 5.536 2.182L11 7.647L10.999 8.352Z" fill="black"/>
+</svg>
diff --git a/toolkit/components/pdfjs/content/web/images/findbarButton-previous.svg b/toolkit/components/pdfjs/content/web/images/findbarButton-previous.svg
new file mode 100644
index 0000000000..b610879daf
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/images/findbarButton-previous.svg
@@ -0,0 +1,3 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M5.001 8.352L10.466 13.818C10.5845 13.9303 10.7421 13.9918 10.9053 13.9895C11.0685 13.9872 11.2244 13.9212 11.3397 13.8057C11.4549 13.6902 11.5205 13.5342 11.5225 13.3709C11.5244 13.2077 11.4625 13.0502 11.35 12.932L6.416 7.999L11.349 3.067C11.4614 2.94864 11.5231 2.79106 11.521 2.62786C11.5189 2.46466 11.4531 2.30874 11.3377 2.19333C11.2223 2.07792 11.0663 2.01215 10.9031 2.01003C10.7399 2.00792 10.5824 2.06962 10.464 2.182L5 7.647L5.001 8.352Z" fill="black"/>
+</svg>
diff --git a/toolkit/components/pdfjs/content/web/images/gv-toolbarButton-download.svg b/toolkit/components/pdfjs/content/web/images/gv-toolbarButton-download.svg
new file mode 100644
index 0000000000..d56cf3ce70
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/images/gv-toolbarButton-download.svg
@@ -0,0 +1,3 @@
+<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path fill-rule="evenodd" clip-rule="evenodd" d="M16.969 10.059C17.262 9.766 17.737 9.766 18.03 10.059C18.323 10.352 18.323 10.827 18.03 11.12L12.15 17H11.35L5.46896 11.12C5.17596 10.827 5.17596 10.352 5.46896 10.059C5.76196 9.766 6.23696 9.766 6.52996 10.059L11 14.529V2.75C11 2.336 11.336 2 11.75 2C12.164 2 12.5 2.336 12.499 2.75V14.529L16.969 10.059ZM4.98193 19.7L5.78193 20.5H17.7169L18.5169 19.7V17.75C18.5169 17.336 18.8529 17 19.2669 17C19.6809 17 20.0169 17.336 20.0169 17.75V19.5C20.0169 20.881 18.8979 22 17.5169 22H5.98193C4.60093 22 3.48193 20.881 3.48193 19.5V17.75C3.48193 17.336 3.81793 17 4.23193 17C4.64593 17 4.98193 17.336 4.98193 17.75V19.7Z" fill="black"/>
+</svg>
diff --git a/toolkit/components/pdfjs/content/web/images/gv-toolbarButton-openinapp.svg b/toolkit/components/pdfjs/content/web/images/gv-toolbarButton-openinapp.svg
new file mode 100644
index 0000000000..80ec891aad
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/images/gv-toolbarButton-openinapp.svg
@@ -0,0 +1,11 @@
+<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M4 4.5H6.5V7H4V4.5Z" fill="black"/>
+<path d="M6.5 10.5H4V13H6.5V10.5Z" fill="black"/>
+<path d="M13.25 10.5H10.75V13H13.25V10.5Z" fill="black"/>
+<path d="M17.5 10.5H20V13H17.5V10.5Z" fill="black"/>
+<path d="M6.5 16.5H4V19H6.5V16.5Z" fill="black"/>
+<path d="M10.75 16.5H13.25V19H10.75V16.5Z" fill="black"/>
+<path d="M20 16.5H17.5V19H20V16.5Z" fill="black"/>
+<path d="M13.25 4.5H10.75V7H13.25V4.5Z" fill="black"/>
+<path d="M17.5 4.5H20V7H17.5V4.5Z" fill="black"/>
+</svg>
diff --git a/toolkit/components/pdfjs/content/web/images/loading-icon.gif b/toolkit/components/pdfjs/content/web/images/loading-icon.gif
new file mode 100644
index 0000000000..1c72ebb554
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/images/loading-icon.gif
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/images/loading.svg b/toolkit/components/pdfjs/content/web/images/loading.svg
new file mode 100644
index 0000000000..0a15ff6885
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/images/loading.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" height="16" width="16" style="animation:spinLoadingIcon 1s steps(12,end) infinite"><style>@keyframes spinLoadingIcon{to{transform:rotate(360deg)}}</style><path d="M7 3V1s0-1 1-1 1 1 1 1v2s0 1-1 1-1-1-1-1z"/><path d="M4.63 4.1l-1-1.73S3.13 1.5 4 1c.87-.5 1.37.37 1.37.37l1 1.73s.5.87-.37 1.37c-.87.57-1.37-.37-1.37-.37z" fill-opacity=".93"/><path d="M3.1 6.37l-1.73-1S.5 4.87 1 4c.5-.87 1.37-.37 1.37-.37l1.73 1s.87.5.37 1.37c-.5.87-1.37.37-1.37.37z" fill-opacity=".86"/><path d="M3 9H1S0 9 0 8s1-1 1-1h2s1 0 1 1-1 1-1 1z" fill-opacity=".79"/><path d="M4.1 11.37l-1.73 1S1.5 12.87 1 12c-.5-.87.37-1.37.37-1.37l1.73-1s.87-.5 1.37.37c.5.87-.37 1.37-.37 1.37z" fill-opacity=".72"/><path d="M3.63 13.56l1-1.73s.5-.87 1.37-.37c.87.5.37 1.37.37 1.37l-1 1.73s-.5.87-1.37.37c-.87-.5-.37-1.37-.37-1.37z" fill-opacity=".65"/><path d="M7 15v-2s0-1 1-1 1 1 1 1v2s0 1-1 1-1-1-1-1z" fill-opacity=".58"/><path d="M10.63 14.56l-1-1.73s-.5-.87.37-1.37c.87-.5 1.37.37 1.37.37l1 1.73s.5.87-.37 1.37c-.87.5-1.37-.37-1.37-.37z" fill-opacity=".51"/><path d="M13.56 12.37l-1.73-1s-.87-.5-.37-1.37c.5-.87 1.37-.37 1.37-.37l1.73 1s.87.5.37 1.37c-.5.87-1.37.37-1.37.37z" fill-opacity=".44"/><path d="M15 9h-2s-1 0-1-1 1-1 1-1h2s1 0 1 1-1 1-1 1z" fill-opacity=".37"/><path d="M14.56 5.37l-1.73 1s-.87.5-1.37-.37c-.5-.87.37-1.37.37-1.37l1.73-1s.87-.5 1.37.37c.5.87-.37 1.37-.37 1.37z" fill-opacity=".3"/><path d="M9.64 3.1l.98-1.66s.5-.874 1.37-.37c.87.5.37 1.37.37 1.37l-1 1.73s-.5.87-1.37.37c-.87-.5-.37-1.37-.37-1.37z" fill-opacity=".23"/></svg> \ No newline at end of file
diff --git a/toolkit/components/pdfjs/content/web/images/secondaryToolbarButton-documentProperties.svg b/toolkit/components/pdfjs/content/web/images/secondaryToolbarButton-documentProperties.svg
new file mode 100644
index 0000000000..dd3917b91d
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/images/secondaryToolbarButton-documentProperties.svg
@@ -0,0 +1,3 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M8 1.5C4.41015 1.5 1.5 4.41015 1.5 8C1.5 11.5899 4.41015 14.5 8 14.5C11.5899 14.5 14.5 11.5899 14.5 8C14.5 4.41015 11.5899 1.5 8 1.5ZM0 8C0 3.58172 3.58172 0 8 0C12.4183 0 16 3.58172 16 8C16 12.4183 12.4183 16 8 16C3.58172 16 0 12.4183 0 8ZM8.75 4V5.5H7.25V4H8.75ZM8.75 12V7H7.25V12H8.75Z" fill="black"/>
+</svg>
diff --git a/toolkit/components/pdfjs/content/web/images/secondaryToolbarButton-firstPage.svg b/toolkit/components/pdfjs/content/web/images/secondaryToolbarButton-firstPage.svg
new file mode 100644
index 0000000000..f5c917f12a
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/images/secondaryToolbarButton-firstPage.svg
@@ -0,0 +1,3 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M14 3.5H2V5H14V3.5ZM8 8.811L12.939 13.75L14.001 12.689L8.531 7.219C8.238 6.926 7.763 6.926 7.47 7.219L2 12.689L3.061 13.75L8 8.811Z" fill="black"/>
+</svg>
diff --git a/toolkit/components/pdfjs/content/web/images/secondaryToolbarButton-handTool.svg b/toolkit/components/pdfjs/content/web/images/secondaryToolbarButton-handTool.svg
new file mode 100644
index 0000000000..b7073b5989
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/images/secondaryToolbarButton-handTool.svg
@@ -0,0 +1,3 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M7.75 2.125C7.75 1.78021 8.03021 1.5 8.375 1.5C8.71979 1.5 9 1.78021 9 2.125V3.125V8H10.5V3.125C10.5 2.78021 10.7802 2.5 11.125 2.5C11.4698 2.5 11.75 2.78021 11.75 3.125V4.625V8H13.25V4.625C13.25 4.28021 13.5302 4 13.875 4C14.2198 4 14.5 4.28021 14.5 4.625V12.0188L13.3802 13.6628C13.2954 13.7872 13.25 13.9344 13.25 14.085V16H14.75V14.3162L15.8698 12.6722C15.9546 12.5478 16 12.4006 16 12.25V4.625C16 3.45179 15.0482 2.5 13.875 2.5C13.6346 2.5 13.4035 2.53996 13.188 2.6136C12.959 1.68724 12.1219 1 11.125 1C10.8235 1 10.5366 1.06286 10.2768 1.17618C9.9281 0.478968 9.20726 0 8.375 0C7.54274 0 6.8219 0.478968 6.47323 1.17618C6.21337 1.06286 5.9265 1 5.625 1C4.45179 1 3.5 1.95179 3.5 3.125V7.25317C2.66504 6.54282 1.41035 6.58199 0.621672 7.37067C-0.208221 8.20056 -0.208221 9.54644 0.621672 10.3763L0.62188 10.3765L5.499 15.2498V16H6.999V14.939C6.999 14.74 6.9199 14.5491 6.77912 14.4085L1.68233 9.31567C1.43823 9.07156 1.43823 8.67544 1.68233 8.43133C1.92644 8.18722 2.32257 8.18722 2.56667 8.43133L3.71967 9.58433C3.93417 9.79883 4.25676 9.863 4.53701 9.74691C4.81727 9.63082 5 9.35735 5 9.054V3.125C5 2.78021 5.28022 2.5 5.625 2.5C5.96921 2.5 6.24906 2.77927 6.25 3.12326V8H7.75L7.75 3.125L7.75 3.12178V2.125Z" fill="black"/>
+</svg>
diff --git a/toolkit/components/pdfjs/content/web/images/secondaryToolbarButton-lastPage.svg b/toolkit/components/pdfjs/content/web/images/secondaryToolbarButton-lastPage.svg
new file mode 100644
index 0000000000..c04f65079c
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/images/secondaryToolbarButton-lastPage.svg
@@ -0,0 +1,3 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M8 8.189L12.939 3.25L14 4.311L8.531 9.781C8.238 10.074 7.763 10.074 7.47 9.781L2 4.311L3.061 3.25L8 8.189ZM14 13.5V12H2V13.5H14Z" fill="black"/>
+</svg>
diff --git a/toolkit/components/pdfjs/content/web/images/secondaryToolbarButton-rotateCcw.svg b/toolkit/components/pdfjs/content/web/images/secondaryToolbarButton-rotateCcw.svg
new file mode 100644
index 0000000000..da73a1b16b
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/images/secondaryToolbarButton-rotateCcw.svg
@@ -0,0 +1,3 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M3.4105 4.83612L4.77001 6.19601C5.06701 6.49201 4.85701 7.00001 4.43701 7.00001H0.862006C0.602006 7.00001 0.391006 6.78901 0.391006 6.52901V2.95401C0.391006 2.53401 0.899006 2.32401 1.19601 2.62101L2.32796 3.75328C3.67958 1.78973 5.9401 0.5 8.5 0.5C12.636 0.5 16 3.864 16 8C16 12.136 12.636 15.5 8.5 15.5C4.704 15.5 1.566 12.663 1.075 9H2.59C3.068 11.833 5.532 14 8.5 14C11.809 14 14.5 11.309 14.5 8C14.5 4.691 11.809 2 8.5 2C6.35262 2 4.46893 3.13503 3.4105 4.83612Z" fill="black"/>
+</svg>
diff --git a/toolkit/components/pdfjs/content/web/images/secondaryToolbarButton-rotateCw.svg b/toolkit/components/pdfjs/content/web/images/secondaryToolbarButton-rotateCw.svg
new file mode 100644
index 0000000000..c41ce7365e
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/images/secondaryToolbarButton-rotateCw.svg
@@ -0,0 +1,3 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M12.5895 4.83613L11.23 6.19601C10.933 6.49201 11.143 7.00001 11.563 7.00001H15.138C15.398 7.00001 15.609 6.78901 15.609 6.52901V2.95401C15.609 2.53401 15.101 2.32401 14.804 2.62101L13.672 3.75328C12.3204 1.78973 10.0599 0.5 7.5 0.5C3.364 0.5 0 3.864 0 8C0 12.136 3.364 15.5 7.5 15.5C11.296 15.5 14.434 12.663 14.925 9H13.41C12.932 11.833 10.468 14 7.5 14C4.191 14 1.5 11.309 1.5 8C1.5 4.691 4.191 2 7.5 2C9.64738 2 11.5311 3.13503 12.5895 4.83613Z" fill="black"/>
+</svg>
diff --git a/toolkit/components/pdfjs/content/web/images/secondaryToolbarButton-scrollHorizontal.svg b/toolkit/components/pdfjs/content/web/images/secondaryToolbarButton-scrollHorizontal.svg
new file mode 100644
index 0000000000..fb440b9465
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/images/secondaryToolbarButton-scrollHorizontal.svg
@@ -0,0 +1,3 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M3 3.78C3 2.7621 2.13279 2.11834 1.25 2.01476V2H1V3.5C1.18133 3.5 1.32279 3.5609 1.40708 3.63029C1.48961 3.69823 1.5 3.75458 1.5 3.78V11.72C1.5 11.7454 1.48961 11.8018 1.40708 11.8697C1.32279 11.9391 1.18133 12 1 12V13.5H1.25V13.4852C2.13279 13.3817 3 12.7379 3 11.72V3.78ZM10.5 4C10.5 3.72386 10.2761 3.5 10 3.5H6.5C6.22386 3.5 6 3.72386 6 4V11.5C6 11.7761 6.22386 12 6.5 12H10C10.2761 12 10.5 11.7761 10.5 11.5V4ZM10 2C11.1046 2 12 2.89543 12 4V11.5C12 12.6046 11.1046 13.5 10 13.5H6.5C5.39543 13.5 4.5 12.6046 4.5 11.5V4C4.5 2.89543 5.39543 2 6.5 2H10ZM15.5 2H15.25V2.01476C14.3672 2.11834 13.5 2.7621 13.5 3.78V11.72C13.5 12.7379 14.3672 13.3817 15.25 13.4852V13.5H15.5V12C15.3187 12 15.1772 11.9391 15.0929 11.8697C15.0104 11.8018 15 11.7454 15 11.72V3.78C15 3.75458 15.0104 3.69823 15.0929 3.63029C15.1772 3.5609 15.3187 3.5 15.5 3.5V2Z" fill="black"/>
+</svg>
diff --git a/toolkit/components/pdfjs/content/web/images/secondaryToolbarButton-scrollPage.svg b/toolkit/components/pdfjs/content/web/images/secondaryToolbarButton-scrollPage.svg
new file mode 100644
index 0000000000..64a9f50073
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/images/secondaryToolbarButton-scrollPage.svg
@@ -0,0 +1,3 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M3.5 2C3.5 1.72421 3.72421 1.5 4 1.5H12C12.2758 1.5 12.5 1.72421 12.5 2V14C12.5 14.2758 12.2758 14.5 12 14.5H4C3.72421 14.5 3.5 14.2758 3.5 14V2ZM4 0C2.89579 0 2 0.895786 2 2V14C2 15.1042 2.89579 16 4 16H12C13.1042 16 14 15.1042 14 14V2C14 0.895786 13.1042 0 12 0H4ZM5.89301 6H7.25V10H5.89301C5.54301 10 5.36801 10.423 5.61501 10.67L7.72101 12.776C7.87401 12.929 8.12301 12.929 8.27601 12.776L10.383 10.669C10.63 10.422 10.455 9.99902 10.105 9.99902H8.75V6H10.106C10.456 6 10.632 5.577 10.383 5.331L8.27601 3.224C8.12301 3.071 7.87401 3.071 7.72101 3.224L5.61501 5.33C5.36801 5.577 5.54301 6 5.89301 6Z" fill="black"/>
+</svg>
diff --git a/toolkit/components/pdfjs/content/web/images/secondaryToolbarButton-scrollVertical.svg b/toolkit/components/pdfjs/content/web/images/secondaryToolbarButton-scrollVertical.svg
new file mode 100644
index 0000000000..dc7e805200
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/images/secondaryToolbarButton-scrollVertical.svg
@@ -0,0 +1,3 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M2 1V1.25H2.01476C2.11834 2.13279 2.7621 3 3.78 3H11.72C12.7379 3 13.3817 2.13279 13.4852 1.25H13.5V1H12C12 1.18133 11.9391 1.32279 11.8697 1.40708C11.8018 1.48961 11.7454 1.5 11.72 1.5H3.78C3.75458 1.5 3.69823 1.48961 3.63029 1.40708C3.5609 1.32279 3.5 1.18133 3.5 1H2ZM4 6C3.72386 6 3.5 6.22386 3.5 6.5V10C3.5 10.2761 3.72386 10.5 4 10.5H11.5C11.7761 10.5 12 10.2761 12 10V6.5C12 6.22386 11.7761 6 11.5 6H4ZM2 6.5C2 5.39543 2.89543 4.5 4 4.5H11.5C12.6046 4.5 13.5 5.39543 13.5 6.5V10C13.5 11.1046 12.6046 12 11.5 12H4C2.89543 12 2 11.1046 2 10V6.5ZM3.78 13.5C2.7621 13.5 2.11834 14.3672 2.01476 15.25H2V15.5H3.5C3.5 15.3187 3.5609 15.1772 3.63029 15.0929C3.69823 15.0104 3.75458 15 3.78 15H11.72C11.7454 15 11.8018 15.0104 11.8697 15.0929C11.9391 15.1772 12 15.3187 12 15.5H13.5V15.25H13.4852C13.3817 14.3672 12.7379 13.5 11.72 13.5H3.78Z" fill="black"/>
+</svg>
diff --git a/toolkit/components/pdfjs/content/web/images/secondaryToolbarButton-scrollWrapped.svg b/toolkit/components/pdfjs/content/web/images/secondaryToolbarButton-scrollWrapped.svg
new file mode 100644
index 0000000000..75fe26bcfc
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/images/secondaryToolbarButton-scrollWrapped.svg
@@ -0,0 +1,3 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M2.5 1C2.5 1.27579 2.72421 1.5 3 1.5H5C5.27579 1.5 5.5 1.27579 5.5 1H7C7 2.10421 6.10421 3 5 3H3C1.89579 3 1 2.10421 1 1H2.5ZM2.5 6C2.5 5.72421 2.72421 5.5 3 5.5H5C5.27579 5.5 5.5 5.72421 5.5 6V10C5.5 10.2758 5.27579 10.5 5 10.5H3C2.72421 10.5 2.5 10.2758 2.5 10V6ZM3 4C1.89579 4 1 4.89579 1 6V10C1 11.1042 1.89579 12 3 12H5C6.10421 12 7 11.1042 7 10V6C7 4.89579 6.10421 4 5 4H3ZM10 6C10 5.72421 10.2242 5.5 10.5 5.5H12.5C12.7758 5.5 13 5.72421 13 6V10C13 10.2758 12.7758 10.5 12.5 10.5H10.5C10.2242 10.5 10 10.2758 10 10V6ZM10.5 4C9.39579 4 8.5 4.89579 8.5 6V10C8.5 11.1042 9.39579 12 10.5 12H12.5C13.6042 12 14.5 11.1042 14.5 10V6C14.5 4.89579 13.6042 4 12.5 4H10.5ZM3 14.5C2.72421 14.5 2.5 14.7242 2.5 15H1C1 13.8958 1.89579 13 3 13H5C6.10421 13 7 13.8958 7 15H5.5C5.5 14.7242 5.27579 14.5 5 14.5H3ZM10 15C10 14.7242 10.2242 14.5 10.5 14.5H12.5C12.7758 14.5 13 14.7242 13 15H14.5C14.5 13.8958 13.6042 13 12.5 13H10.5C9.39579 13 8.5 13.8958 8.5 15H10ZM10.5 1.5C10.2242 1.5 10 1.27579 10 1H8.5C8.5 2.10421 9.39579 3 10.5 3H12.5C13.6042 3 14.5 2.10421 14.5 1H13C13 1.27579 12.7758 1.5 12.5 1.5H10.5Z" fill="black"/>
+</svg>
diff --git a/toolkit/components/pdfjs/content/web/images/secondaryToolbarButton-selectTool.svg b/toolkit/components/pdfjs/content/web/images/secondaryToolbarButton-selectTool.svg
new file mode 100644
index 0000000000..94d51410dd
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/images/secondaryToolbarButton-selectTool.svg
@@ -0,0 +1,3 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M0.371588 2.93131C-0.203366 1.33422 1.3342 -0.20335 2.93129 0.371603L2.93263 0.372085L12.0716 3.68171C12.0718 3.68178 12.0714 3.68163 12.0716 3.68171C13.4459 4.17758 13.8478 5.9374 12.8076 6.9776L11.8079 7.97727L14.6876 10.8569C15.4705 11.6398 15.4705 12.9047 14.6876 13.6876L13.6476 14.7276C12.8647 15.5105 11.5998 15.5105 10.8169 14.7276L7.93725 11.8479L6.97758 12.8076C5.93739 13.8478 4.17779 13.4465 3.68192 12.0722C3.68184 12.072 3.682 12.0724 3.68192 12.0722L0.371588 2.93131ZM1.78292 2.42323C1.78298 2.4234 1.78286 2.42305 1.78292 2.42323L5.09281 11.5629C5.21725 11.9082 5.65728 12.0066 5.91692 11.7469L7.93725 9.72661L11.8776 13.6669C12.0747 13.864 12.3898 13.864 12.5869 13.6669L13.6269 12.6269C13.824 12.4298 13.824 12.1147 13.6269 11.9176L9.68659 7.97727L11.7469 5.91694C12.0066 5.65729 11.9081 5.21727 11.5629 5.09283L11.5619 5.09245L2.42321 1.78293C2.42304 1.78287 2.42339 1.783 2.42321 1.78293C2.02067 1.63847 1.63846 2.02069 1.78292 2.42323Z" fill="black"/>
+</svg>
diff --git a/toolkit/components/pdfjs/content/web/images/secondaryToolbarButton-spreadEven.svg b/toolkit/components/pdfjs/content/web/images/secondaryToolbarButton-spreadEven.svg
new file mode 100644
index 0000000000..ce201e33c0
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/images/secondaryToolbarButton-spreadEven.svg
@@ -0,0 +1,3 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path fill-rule="evenodd" d="M2 3.5C1.72421 3.5 1.5 3.72421 1.5 4V12.5C1.5 12.7758 1.72421 13 2 13H7.25V3.5H2ZM14 13H8.75V3.5H14C14.2758 3.5 14.5 3.72421 14.5 4V12.5C14.5 12.7758 14.2758 13 14 13ZM0 4C0 2.89579 0.895786 2 2 2H14C15.1042 2 16 2.89579 16 4V12.5C16 13.6042 15.1042 14.5 14 14.5H2C0.895786 14.5 0 13.6042 0 12.5V4ZM10 6.5H11.5V7.5H10V9H11.5V10H10V11.5H12.25C12.6642 11.5 13 11.1642 13 10.75V5.75C13 5.33579 12.6642 5 12.25 5H10V6.5ZM4.5 6.5H3V5H5.25C5.66421 5 6 5.33579 6 5.75V7.75C6 8.03408 5.8395 8.29378 5.58541 8.42082L4.5 8.96353V10H6V11.5H3.75C3.33579 11.5 3 11.1642 3 10.75V8.5C3 8.21592 3.1605 7.95622 3.41459 7.82918L4.5 7.28647V6.5Z" fill="black"/>
+</svg>
diff --git a/toolkit/components/pdfjs/content/web/images/secondaryToolbarButton-spreadNone.svg b/toolkit/components/pdfjs/content/web/images/secondaryToolbarButton-spreadNone.svg
new file mode 100644
index 0000000000..e8d487fa38
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/images/secondaryToolbarButton-spreadNone.svg
@@ -0,0 +1,3 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M4 1.5C3.72421 1.5 3.5 1.72421 3.5 2V14C3.5 14.2758 3.72421 14.5 4 14.5H12C12.2758 14.5 12.5 14.2758 12.5 14V2C12.5 1.72421 12.2758 1.5 12 1.5H4ZM2 2C2 0.895786 2.89579 0 4 0H12C13.1042 0 14 0.895786 14 2V14C14 15.1042 13.1042 16 12 16H4C2.89579 16 2 15.1042 2 14V2Z" fill="black"/>
+</svg>
diff --git a/toolkit/components/pdfjs/content/web/images/secondaryToolbarButton-spreadOdd.svg b/toolkit/components/pdfjs/content/web/images/secondaryToolbarButton-spreadOdd.svg
new file mode 100644
index 0000000000..9211a427bf
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/images/secondaryToolbarButton-spreadOdd.svg
@@ -0,0 +1,3 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M1.5 4C1.5 3.72421 1.72421 3.5 2 3.5H7.25V13H2C1.72421 13 1.5 12.7758 1.5 12.5V4ZM8.75 13V3.5H14C14.2758 3.5 14.5 3.72421 14.5 4V12.5C14.5 12.7758 14.2758 13 14 13H8.75ZM2 2C0.895786 2 0 2.89579 0 4V12.5C0 13.6042 0.895786 14.5 2 14.5H14C15.1042 14.5 16 13.6042 16 12.5V4C16 2.89579 15.1042 2 14 2H2ZM4.75 5H3V6.5H4V11.5H5.5V5.75C5.5 5.33579 5.16421 5 4.75 5ZM10 6.5H11.5V7.28647L10.4146 7.82918C10.1605 7.95622 10 8.21592 10 8.5V10.75C10 11.1642 10.3358 11.5 10.75 11.5H13V10H11.5V8.96353L12.5854 8.42082C12.8395 8.29378 13 8.03408 13 7.75V5.75C13 5.33579 12.6642 5 12.25 5H10V6.5Z" fill="black"/>
+</svg>
diff --git a/toolkit/components/pdfjs/content/web/images/toolbarButton-bookmark.svg b/toolkit/components/pdfjs/content/web/images/toolbarButton-bookmark.svg
new file mode 100644
index 0000000000..c4c37c9058
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/images/toolbarButton-bookmark.svg
@@ -0,0 +1,3 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M2 3.5C1.72421 3.5 1.5 3.72421 1.5 4V12C1.5 12.2758 1.72421 12.5 2 12.5H14C14.2758 12.5 14.5 12.2758 14.5 12V4C14.5 3.72421 14.2758 3.5 14 3.5H2ZM0 4C0 2.89579 0.895786 2 2 2H14C15.1042 2 16 2.89579 16 4V12C16 13.1042 15.1042 14 14 14H2C0.895786 14 0 13.1042 0 12V4ZM8.75 8.75H7.25V7.25H8.75V8.75ZM8.00001 4.625C5.91142 4.625 4.14736 5.94291 3.45159 7.77847L3.36761 8L3.45159 8.22153C4.14736 10.0571 5.91142 11.375 8.00001 11.375C10.0886 11.375 11.8527 10.0571 12.5484 8.22153L12.6324 8L12.5484 7.77847C11.8527 5.94291 10.0886 4.625 8.00001 4.625ZM8.00001 10.125C6.53912 10.125 5.28508 9.25455 4.71282 8C5.28508 6.74545 6.53912 5.875 8.00001 5.875C9.4609 5.875 10.7149 6.74545 11.2872 8C10.7149 9.25455 9.4609 10.125 8.00001 10.125Z" fill="black"/>
+</svg>
diff --git a/toolkit/components/pdfjs/content/web/images/toolbarButton-currentOutlineItem.svg b/toolkit/components/pdfjs/content/web/images/toolbarButton-currentOutlineItem.svg
new file mode 100644
index 0000000000..01e67623bf
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/images/toolbarButton-currentOutlineItem.svg
@@ -0,0 +1,3 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M10.803 4.74998V6.02436C10.803 6.39302 10.3571 6.57793 10.0967 6.31753L7.87716 4.098C7.71566 3.93649 7.71566 3.67434 7.87716 3.51283L10.0967 1.29329C10.3571 1.0329 10.8036 1.21722 10.8036 1.58588V3.24998H15V4.74998H10.803ZM8 1.24998H3V2.74998H6.5L8 1.24998ZM6.5 5.24998H3V6.74998H8L6.5 5.24998ZM3 13.25H15V14.75H3V13.25ZM6 9.24998H15V10.75H6V9.24998ZM1.5 5.24998H0V6.74998H1.5V5.24998ZM0 13.25H1.5V14.75H0V13.25ZM1.5 1.24998H0V2.74998H1.5V1.24998ZM3 9.24998H4.5V10.75H3V9.24998Z" fill="black"/>
+</svg>
diff --git a/toolkit/components/pdfjs/content/web/images/toolbarButton-download.svg b/toolkit/components/pdfjs/content/web/images/toolbarButton-download.svg
new file mode 100644
index 0000000000..e2e850adf7
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/images/toolbarButton-download.svg
@@ -0,0 +1,4 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M9.79407 7.31811H7.86307C7.41807 7.31811 7.19407 7.85711 7.50907 8.17211L10.1911 10.8541C10.3861 11.0491 10.7031 11.0491 10.8981 10.8541L13.5801 8.17211C13.8951 7.85711 13.6721 7.31811 13.2261 7.31811H11.2941V4.38211H11.2961V3.13211H11.2941V2.30811H9.79407V3.13211H9.79107V4.38211H9.79507V7.31811H9.79407Z" fill="black"/>
+<path d="M14 3.13208H12.796V4.38208H14C14.345 4.38208 14.625 4.66208 14.625 5.00708V13.0071C14.625 13.3521 14.345 13.6321 14 13.6321H2C1.655 13.6321 1.375 13.3521 1.375 13.0071V3.00708C1.375 2.66208 1.655 2.38208 2 2.38208H5.643C5.82 2.38208 5.989 2.45808 6.108 2.58908L7.536 4.17508C7.654 4.30708 7.823 4.38208 8 4.38208H8.291V3.13208H8.278L7.036 1.75208C6.681 1.35808 6.173 1.13208 5.642 1.13208H2C0.966 1.13208 0.125 1.97308 0.125 3.00708V13.0071C0.125 14.0411 0.966 14.8821 2 14.8821H14C15.034 14.8821 15.875 14.0411 15.875 13.0071V5.00708C15.875 3.97308 15.034 3.13208 14 3.13208Z" fill="black"/>
+</svg>
diff --git a/toolkit/components/pdfjs/content/web/images/toolbarButton-editorFreeText.svg b/toolkit/components/pdfjs/content/web/images/toolbarButton-editorFreeText.svg
new file mode 100644
index 0000000000..13a67bd9b6
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/images/toolbarButton-editorFreeText.svg
@@ -0,0 +1,5 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path fill-rule="evenodd" clip-rule="evenodd" d="M3 2.5C2.72421 2.5 2.5 2.72421 2.5 3V4.75H1V3C1 1.89579 1.89579 1 3 1H13C14.1042 1 15 1.89579 15 3V4.75H13.5V3C13.5 2.72421 13.2758 2.5 13 2.5H3Z" fill="black"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M11 15H5V13.5H11V15Z" fill="black"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M8.75 2.25V14.25H7.25V2.25H8.75Z" fill="black"/>
+</svg>
diff --git a/toolkit/components/pdfjs/content/web/images/toolbarButton-editorHighlight.svg b/toolkit/components/pdfjs/content/web/images/toolbarButton-editorHighlight.svg
new file mode 100644
index 0000000000..b3cd7fda9c
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/images/toolbarButton-editorHighlight.svg
@@ -0,0 +1,6 @@
+<svg width="17" height="16" viewBox="0 0 17 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+ <g>
+ <path fill-rule="evenodd" clip-rule="evenodd" d="M7.10918 11.66C7.24918 11.8 7.43918 11.88 7.63918 11.88C7.83918 11.88 8.02918 11.8 8.16918 11.66L14.9192 4.91C15.2692 4.57 15.4592 4.11 15.4592 3.62C15.4592 3.13 15.2692 2.67 14.9192 2.33L13.1292 0.54C12.7892 0.19 12.3292 0 11.8392 0C11.3492 0 10.8892 0.2 10.5492 0.54L3.79918 7.29C3.50918 7.58 3.50918 8.06 3.79918 8.35L4.38988 8.9407L1.40918 11.93H5.64918L6.51419 11.065L7.10918 11.66ZM7.63918 10.07L5.38918 7.82V7.81L7.8648 5.33438L10.1198 7.58938L7.63918 10.07ZM11.1805 6.52872L13.8592 3.85C13.9892 3.72 13.9892 3.52 13.8592 3.39L12.0692 1.6C11.9892 1.52 11.8892 1.5 11.8392 1.5C11.8392 1.5 11.6892 1.51 11.6092 1.59L8.92546 4.27372L11.1805 6.52872Z" fill="#000"/>
+ <path d="M0.40918 14H15.4092V16H0.40918V14Z" fill="#000"/>
+ </g>
+ </svg> \ No newline at end of file
diff --git a/toolkit/components/pdfjs/content/web/images/toolbarButton-editorInk.svg b/toolkit/components/pdfjs/content/web/images/toolbarButton-editorInk.svg
new file mode 100644
index 0000000000..b579eec7ee
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/images/toolbarButton-editorInk.svg
@@ -0,0 +1,4 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M2.49913 12.6251C2.61913 12.6251 2.73913 12.6051 2.85713 12.5661L6.29013 11.4201L13.2891 4.4221C14.0191 3.6911 14.0191 2.5011 13.2891 1.7701L12.2291 0.710098C11.4971 -0.0199023 10.3091 -0.0199023 9.57713 0.710098L2.57813 7.7091L1.43313 11.1451C1.29813 11.5511 1.40213 11.9931 1.70513 12.2951C1.92113 12.5101 2.20613 12.6251 2.49913 12.6251ZM10.4611 1.5951C10.7031 1.3511 11.1021 1.3511 11.3441 1.5951L12.4051 2.6561C12.6491 2.8991 12.6491 3.2961 12.4051 3.5391L11.3401 4.6051L9.39513 2.6601L10.4611 1.5951ZM3.67013 8.3851L8.51013 3.5451L10.4541 5.4891L5.61413 10.3301L2.69713 11.3031L3.67013 8.3851Z" fill="black"/>
+<path d="M14.8169 13.314L13.0229 13.862C12.3309 14.073 11.5909 14.111 10.8859 13.968L8.80391 13.551C7.58491 13.308 6.29791 13.48 5.18491 14.036C3.95291 14.652 2.46691 14.412 1.49191 13.436L1.44091 13.385L0.60791 14.321C1.46291 15.175 2.59991 15.625 3.75291 15.625C4.42891 15.625 5.10991 15.471 5.74391 15.153C6.60891 14.721 7.60891 14.586 8.55891 14.777L10.6409 15.194C11.5509 15.376 12.5009 15.327 13.3879 15.056L15.1819 14.508L14.8169 13.314Z" fill="black"/>
+</svg>
diff --git a/toolkit/components/pdfjs/content/web/images/toolbarButton-editorStamp.svg b/toolkit/components/pdfjs/content/web/images/toolbarButton-editorStamp.svg
new file mode 100644
index 0000000000..f0469b1b1a
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/images/toolbarButton-editorStamp.svg
@@ -0,0 +1,8 @@
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="context-fill" fill-opacity="context-fill-opacity">
+ <path d="M3 1a2 2 0 0 0-2 2l0 10a2 2 0 0 0 2 2l10 0a2 2 0 0 0 2-2l0-10a2 2 0 0 0-2-2L3 1zm10.75 12.15-.6.6-10.3 0-.6-.6 0-10.3.6-.6 10.3 0 .6.6 0 10.3z"/>
+ <path d="m11 12-6 0a1 1 0 0 1-1-1l0-1.321a.75.75 0 0 1 .218-.529L6.35 7.005a.75.75 0 0 1 1.061-.003l2.112 2.102.612-.577a.75.75 0 0 1 1.047.017l.6.605a.75.75 0 0 1 .218.529L12 11a1 1 0 0 1-1 1z"/>
+ <path d="m11.6 5-1.2 0-.4.4 0 1.2.4.4 1.2 0 .4-.4 0-1.2z"/>
+</svg>
diff --git a/toolkit/components/pdfjs/content/web/images/toolbarButton-menuArrow.svg b/toolkit/components/pdfjs/content/web/images/toolbarButton-menuArrow.svg
new file mode 100644
index 0000000000..82ffeaabb9
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/images/toolbarButton-menuArrow.svg
@@ -0,0 +1,3 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M8.23336 10.4664L11.8474 6.85339C11.894 6.8071 11.931 6.75203 11.9563 6.69136C11.9816 6.63069 11.9946 6.56562 11.9946 6.49989C11.9946 6.43417 11.9816 6.3691 11.9563 6.30843C11.931 6.24776 11.894 6.19269 11.8474 6.14639C11.7536 6.05266 11.6264 6 11.4939 6C11.3613 6 11.2341 6.05266 11.1404 6.14639L7.99236 9.29339L4.84736 6.14739C4.75305 6.05631 4.62675 6.00592 4.49566 6.00706C4.36456 6.0082 4.23915 6.06078 4.14645 6.15348C4.05374 6.24619 4.00116 6.37159 4.00002 6.50269C3.99888 6.63379 4.04928 6.76009 4.14036 6.85439L7.75236 10.4674L8.23336 10.4664Z" fill="black"/>
+</svg>
diff --git a/toolkit/components/pdfjs/content/web/images/toolbarButton-pageDown.svg b/toolkit/components/pdfjs/content/web/images/toolbarButton-pageDown.svg
new file mode 100644
index 0000000000..1fc12e733d
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/images/toolbarButton-pageDown.svg
@@ -0,0 +1,3 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M8.35176 10.9989L13.8178 5.53391C13.876 5.47594 13.9222 5.40702 13.9537 5.33113C13.9851 5.25524 14.0013 5.17387 14.0012 5.0917C14.0011 5.00954 13.9848 4.9282 13.9531 4.85238C13.9215 4.77656 13.8751 4.70775 13.8168 4.64991C13.6991 4.53309 13.5401 4.46753 13.3743 4.46753C13.2085 4.46753 13.0494 4.53309 12.9318 4.64991L7.99776 9.58491L3.06776 4.65091C2.9494 4.53853 2.79183 4.47682 2.62863 4.47894C2.46542 4.48106 2.3095 4.54683 2.19409 4.66224C2.07868 4.77765 2.01291 4.93357 2.01079 5.09677C2.00868 5.25997 2.07039 5.41754 2.18276 5.53591L7.64776 10.9999L8.35176 10.9989Z" fill="black"/>
+</svg>
diff --git a/toolkit/components/pdfjs/content/web/images/toolbarButton-pageUp.svg b/toolkit/components/pdfjs/content/web/images/toolbarButton-pageUp.svg
new file mode 100644
index 0000000000..0936b9a578
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/images/toolbarButton-pageUp.svg
@@ -0,0 +1,3 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M8.35179 5.001L13.8178 10.466C13.876 10.524 13.9222 10.5929 13.9537 10.6688C13.9852 10.7447 14.0013 10.826 14.0012 10.9082C14.0011 10.9904 13.9848 11.0717 13.9531 11.1475C13.9215 11.2234 13.8751 11.2922 13.8168 11.35C13.6991 11.4668 13.5401 11.5324 13.3743 11.5324C13.2085 11.5324 13.0494 11.4668 12.9318 11.35L7.99879 6.416L3.06679 11.349C2.94842 11.4614 2.79085 11.5231 2.62765 11.521C2.46445 11.5189 2.30853 11.4531 2.19312 11.3377C2.07771 11.2223 2.01193 11.0663 2.00982 10.9031C2.0077 10.7399 2.06941 10.5824 2.18179 10.464L7.64779 5L8.35179 5.001Z" fill="black"/>
+</svg>
diff --git a/toolkit/components/pdfjs/content/web/images/toolbarButton-presentationMode.svg b/toolkit/components/pdfjs/content/web/images/toolbarButton-presentationMode.svg
new file mode 100644
index 0000000000..901d5672bc
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/images/toolbarButton-presentationMode.svg
@@ -0,0 +1,3 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M1.5 3C1.5 2.72421 1.72421 2.5 2 2.5H14C14.2758 2.5 14.5 2.72421 14.5 3V11C14.5 11.2758 14.2758 11.5 14 11.5H2C1.72421 11.5 1.5 11.2758 1.5 11V3ZM2 1C0.895786 1 0 1.89579 0 3V11C0 12.1042 0.895786 13 2 13H2.64979L1.35052 15.2499L2.64949 16L4.38194 13H11.6391L13.3715 16L14.6705 15.2499L13.3712 13H14C15.1042 13 16 12.1042 16 11V3C16 1.89579 15.1042 1 14 1H2ZM5.79501 4.64401V9.35601C5.79501 9.85001 6.32901 10.159 6.75701 9.91401L10.88 7.55801C11.312 7.31201 11.312 6.68901 10.88 6.44201L6.75701 4.08601C6.32801 3.84101 5.79501 4.15001 5.79501 4.64401Z" fill="black"/>
+</svg>
diff --git a/toolkit/components/pdfjs/content/web/images/toolbarButton-print.svg b/toolkit/components/pdfjs/content/web/images/toolbarButton-print.svg
new file mode 100644
index 0000000000..97a390474d
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/images/toolbarButton-print.svg
@@ -0,0 +1,3 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M13 4H12V2C12 1.46957 11.7893 0.960859 11.4142 0.585786C11.0391 0.210714 10.5304 0 10 0L6 0C5.46957 0 4.96086 0.210714 4.58579 0.585786C4.21071 0.960859 4 1.46957 4 2V4H3C2.46957 4 1.96086 4.21071 1.58579 4.58579C1.21071 4.96086 1 5.46957 1 6V11C1 11.5304 1.21071 12.0391 1.58579 12.4142C1.96086 12.7893 2.46957 13 3 13H4V14C4 14.5304 4.21071 15.0391 4.58579 15.4142C4.96086 15.7893 5.46957 16 6 16H10C10.5304 16 11.0391 15.7893 11.4142 15.4142C11.7893 15.0391 12 14.5304 12 14V13H13C13.5304 13 14.0391 12.7893 14.4142 12.4142C14.7893 12.0391 15 11.5304 15 11V6C15 5.46957 14.7893 4.96086 14.4142 4.58579C14.0391 4.21071 13.5304 4 13 4V4ZM10.75 14.15L10.15 14.75H5.85L5.25 14.15V10H10.75V14.15ZM10.75 4H5.25V1.85L5.85 1.25H10.15L10.75 1.85V4V4ZM13 7.6L12.6 8H11.4L11 7.6V6.4L11.4 6H12.6L13 6.4V7.6Z" fill="black"/>
+</svg>
diff --git a/toolkit/components/pdfjs/content/web/images/toolbarButton-search.svg b/toolkit/components/pdfjs/content/web/images/toolbarButton-search.svg
new file mode 100644
index 0000000000..0cc7ae21ac
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/images/toolbarButton-search.svg
@@ -0,0 +1,3 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M10.089 10.973L13.934 14.817C13.9918 14.8754 14.0605 14.9218 14.1364 14.9534C14.2122 14.9851 14.2936 15.0013 14.3757 15.0012C14.4579 15.0011 14.5392 14.9847 14.6149 14.9529C14.6907 14.9211 14.7594 14.8746 14.817 14.816C14.875 14.7579 14.921 14.6889 14.9523 14.613C14.9836 14.5372 14.9997 14.4559 14.9996 14.3738C14.9995 14.2917 14.9833 14.2104 14.9518 14.1346C14.9203 14.0588 14.8741 13.99 14.816 13.932L10.983 10.1L10.989 9.67299C11.489 8.96674 11.8152 8.15249 11.9413 7.29642C12.0674 6.44034 11.9897 5.5666 11.7145 4.74621C11.4394 3.92582 10.9745 3.18192 10.3578 2.57498C9.74104 1.96804 8.98979 1.51519 8.16509 1.25322C7.34039 0.991255 6.46551 0.927572 5.61157 1.06735C4.75763 1.20712 3.94871 1.54641 3.25057 2.05764C2.55243 2.56887 1.98476 3.23761 1.59371 4.0095C1.20265 4.7814 0.999236 5.63468 1 6.49999C1 7.95868 1.57946 9.35763 2.61091 10.3891C3.64236 11.4205 5.04131 12 6.5 12C7.689 12 8.788 11.62 9.687 10.978L10.089 10.973V10.973ZM6.5 10.75C4.157 10.75 2.25 8.84299 2.25 6.49999C2.25 4.15699 4.157 2.24999 6.5 2.24999C8.843 2.24999 10.75 4.15699 10.75 6.49999C10.75 8.84299 8.843 10.75 6.5 10.75Z" fill="black"/>
+</svg>
diff --git a/toolkit/components/pdfjs/content/web/images/toolbarButton-secondaryToolbarToggle.svg b/toolkit/components/pdfjs/content/web/images/toolbarButton-secondaryToolbarToggle.svg
new file mode 100644
index 0000000000..cace863728
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/images/toolbarButton-secondaryToolbarToggle.svg
@@ -0,0 +1,3 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M2.53406 13.818L7.99906 8.35203L8.00006 7.64703L2.53606 2.18203C2.41769 2.06965 2.26012 2.00795 2.09692 2.01006C1.93372 2.01218 1.7778 2.07795 1.66239 2.19336C1.54698 2.30877 1.48121 2.46469 1.47909 2.62789C1.47697 2.79109 1.53868 2.94867 1.65106 3.06703L6.58506 7.99803L1.65006 12.932C1.53754 13.0503 1.47565 13.2078 1.47758 13.371C1.47951 13.5342 1.54511 13.6902 1.66039 13.8057C1.77567 13.9213 1.93152 13.9872 2.09472 13.9895C2.25792 13.9918 2.41557 13.9303 2.53406 13.818ZM8.53406 13.818L13.9991 8.35203L14.0001 7.64703L8.53606 2.18203C8.4177 2.06965 8.26012 2.00795 8.09692 2.01006C7.93372 2.01218 7.7778 2.07795 7.66239 2.19336C7.54698 2.30877 7.48121 2.46469 7.47909 2.62789C7.47697 2.79109 7.53868 2.94867 7.65106 3.06703L12.5851 7.99803L7.65006 12.932C7.53754 13.0503 7.47565 13.2078 7.47758 13.371C7.47951 13.5342 7.54511 13.6902 7.66039 13.8057C7.77567 13.9213 7.93152 13.9872 8.09472 13.9895C8.25792 13.9918 8.41557 13.9303 8.53406 13.818Z" fill="black"/>
+</svg>
diff --git a/toolkit/components/pdfjs/content/web/images/toolbarButton-sidebarToggle.svg b/toolkit/components/pdfjs/content/web/images/toolbarButton-sidebarToggle.svg
new file mode 100644
index 0000000000..1d8d0e4b23
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/images/toolbarButton-sidebarToggle.svg
@@ -0,0 +1,3 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path fill-rule="evenodd" d="M16 4V12.25C16 12.7804 15.7893 13.2891 15.4142 13.6642C15.0391 14.0393 14.5304 14.25 14 14.25H2C1.46957 14.25 0.960859 14.0393 0.585786 13.6642C0.210714 13.2891 0 12.7804 0 12.25V4C0 3.46957 0.210714 2.96086 0.585786 2.58579C0.960859 2.21071 1.46957 2 2 2H14C14.5304 2 15.0391 2.21071 15.4142 2.58579C15.7893 2.96086 16 3.46957 16 4ZM1.25 3.85V12.4L1.85 13H6.75V3.25H1.85L1.25 3.85ZM14.15 13H8V3.25H14.15L14.75 3.85V12.4L14.15 13ZM5.35355 10.1464C5.44732 10.2402 5.5 10.3674 5.5 10.5C5.5 10.6326 5.44732 10.7598 5.35355 10.8536C5.25979 10.9473 5.13261 11 5 11H3C2.86739 11 2.74021 10.9473 2.64645 10.8536C2.55268 10.7598 2.5 10.6326 2.5 10.5C2.5 10.3674 2.55268 10.2402 2.64645 10.1464C2.74021 10.0527 2.86739 10 3 10H5C5.13261 10 5.25979 10.0527 5.35355 10.1464ZM5.5 8C5.5 7.86739 5.44732 7.74021 5.35355 7.64645C5.25979 7.55268 5.13261 7.5 5 7.5H3C2.86739 7.5 2.74021 7.55268 2.64645 7.64645C2.55268 7.74021 2.5 7.86739 2.5 8C2.5 8.13261 2.55268 8.25979 2.64645 8.35355C2.74021 8.44732 2.86739 8.5 3 8.5H5C5.13261 8.5 5.25979 8.44732 5.35355 8.35355C5.44732 8.25979 5.5 8.13261 5.5 8ZM5.35355 5.14645C5.44732 5.24021 5.5 5.36739 5.5 5.5C5.5 5.63261 5.44732 5.75979 5.35355 5.85355C5.25979 5.94732 5.13261 6 5 6H3C2.86739 6 2.74021 5.94732 2.64645 5.85355C2.55268 5.75979 2.5 5.63261 2.5 5.5C2.5 5.36739 2.55268 5.24021 2.64645 5.14645C2.74021 5.05268 2.86739 5 3 5H5C5.13261 5 5.25979 5.05268 5.35355 5.14645Z" fill="black"/>
+</svg>
diff --git a/toolkit/components/pdfjs/content/web/images/toolbarButton-viewAttachments.svg b/toolkit/components/pdfjs/content/web/images/toolbarButton-viewAttachments.svg
new file mode 100644
index 0000000000..ab73f6e6e0
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/images/toolbarButton-viewAttachments.svg
@@ -0,0 +1,3 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M3.5 3.75C3.5 1.67879 5.17879 0 7.25 0C9.32121 0 11 1.67879 11 3.75V10.25C11 11.4922 9.99221 12.5 8.75 12.5C7.50779 12.5 6.5 11.4922 6.5 10.25V3.5H8V10.25C8 10.6638 8.33621 11 8.75 11C9.16379 11 9.5 10.6638 9.5 10.25V3.75C9.5 2.50721 8.49279 1.5 7.25 1.5C6.00721 1.5 5 2.50721 5 3.75V10.75C5 12.8208 6.67921 14.5 8.75 14.5C10.8208 14.5 12.5 12.8208 12.5 10.75V3.5H14V10.75C14 13.6492 11.6492 16 8.75 16C5.85079 16 3.5 13.6492 3.5 10.75V3.75Z" fill="black"/>
+</svg>
diff --git a/toolkit/components/pdfjs/content/web/images/toolbarButton-viewLayers.svg b/toolkit/components/pdfjs/content/web/images/toolbarButton-viewLayers.svg
new file mode 100644
index 0000000000..1d72668264
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/images/toolbarButton-viewLayers.svg
@@ -0,0 +1,3 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M8.36645 2.34562C8.13878 2.21813 7.86122 2.21813 7.63355 2.34562L1.38355 5.84562C1.14669 5.97826 1 6.22853 1 6.5C1 6.77147 1.14669 7.02174 1.38355 7.15438L7.63355 10.6544C7.86122 10.7819 8.13878 10.7819 8.36645 10.6544L14.6165 7.15438C14.8533 7.02174 15 6.77147 15 6.5C15 6.22853 14.8533 5.97826 14.6165 5.84562L8.36645 2.34562ZM8 9.14041L3.28499 6.5L8 3.85959L12.715 6.5L8 9.14041ZM1.63647 9.0766L7.99999 12.6404L14.3255 9.09761L15.0585 10.4063L8.36649 14.1543C8.13881 14.2818 7.86122 14.2819 7.63353 14.1543L0.903534 10.3853L1.63647 9.0766Z" fill="black"/>
+</svg>
diff --git a/toolkit/components/pdfjs/content/web/images/toolbarButton-viewOutline.svg b/toolkit/components/pdfjs/content/web/images/toolbarButton-viewOutline.svg
new file mode 100644
index 0000000000..7ed1bd97f2
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/images/toolbarButton-viewOutline.svg
@@ -0,0 +1,3 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M3 1.25H15V2.75H3V1.25ZM15 5.25H3V6.75H15V5.25ZM15 13.25H3V14.75H15V13.25ZM15 9.25H6V10.75H15V9.25ZM0 5.25H1.5V6.75H0V5.25ZM1.5 13.25H0V14.75H1.5V13.25ZM0 1.25H1.5V2.75H0V1.25ZM4.5 9.25H3V10.75H4.5V9.25Z" fill="black"/>
+</svg>
diff --git a/toolkit/components/pdfjs/content/web/images/toolbarButton-viewThumbnail.svg b/toolkit/components/pdfjs/content/web/images/toolbarButton-viewThumbnail.svg
new file mode 100644
index 0000000000..040d123266
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/images/toolbarButton-viewThumbnail.svg
@@ -0,0 +1,3 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M3.5 2C3.5 1.72421 3.72421 1.5 4 1.5H5.25C5.52579 1.5 5.75 1.72421 5.75 2V5.25C5.75 5.52579 5.52579 5.75 5.25 5.75H4C3.72421 5.75 3.5 5.52579 3.5 5.25V2ZM4 0C2.89579 0 2 0.895786 2 2V5.25C2 6.35421 2.89579 7.25 4 7.25H5.25C6.35421 7.25 7.25 6.35421 7.25 5.25V2C7.25 0.895786 6.35421 0 5.25 0H4ZM3.5 10.75C3.5 10.4742 3.72421 10.25 4 10.25H5.25C5.52579 10.25 5.75 10.4742 5.75 10.75V14C5.75 14.2758 5.52579 14.5 5.25 14.5H4C3.72421 14.5 3.5 14.2758 3.5 14V10.75ZM4 8.75C2.89579 8.75 2 9.64579 2 10.75V14C2 15.1042 2.89579 16 4 16H5.25C6.35421 16 7.25 15.1042 7.25 14V10.75C7.25 9.64579 6.35421 8.75 5.25 8.75H4ZM10.75 1.5C10.4742 1.5 10.25 1.72421 10.25 2V5.25C10.25 5.52579 10.4742 5.75 10.75 5.75H12C12.2758 5.75 12.5 5.52579 12.5 5.25V2C12.5 1.72421 12.2758 1.5 12 1.5H10.75ZM8.75 2C8.75 0.895786 9.64579 0 10.75 0H12C13.1042 0 14 0.895786 14 2V5.25C14 6.35421 13.1042 7.25 12 7.25H10.75C9.64579 7.25 8.75 6.35421 8.75 5.25V2ZM10.25 10.75C10.25 10.4742 10.4742 10.25 10.75 10.25H12C12.2758 10.25 12.5 10.4742 12.5 10.75V14C12.5 14.2758 12.2758 14.5 12 14.5H10.75C10.4742 14.5 10.25 14.2758 10.25 14V10.75ZM10.75 8.75C9.64579 8.75 8.75 9.64579 8.75 10.75V14C8.75 15.1042 9.64579 16 10.75 16H12C13.1042 16 14 15.1042 14 14V10.75C14 9.64579 13.1042 8.75 12 8.75H10.75Z" fill="black"/>
+</svg>
diff --git a/toolkit/components/pdfjs/content/web/images/toolbarButton-zoomIn.svg b/toolkit/components/pdfjs/content/web/images/toolbarButton-zoomIn.svg
new file mode 100644
index 0000000000..30ec51a2ff
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/images/toolbarButton-zoomIn.svg
@@ -0,0 +1,3 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M7.00488 9.75V14C7.00488 14.1658 7.07073 14.3247 7.18794 14.4419C7.30515 14.5592 7.46412 14.625 7.62988 14.625C7.79564 14.625 7.95461 14.5592 8.07183 14.4419C8.18904 14.3247 8.25488 14.1658 8.25488 14V9.75L8.75488 9.25H13.0049C13.1706 9.25 13.3296 9.18415 13.4468 9.06694C13.564 8.94973 13.6299 8.79076 13.6299 8.625C13.6299 8.45924 13.564 8.30027 13.4468 8.18306C13.3296 8.06585 13.1706 8 13.0049 8H8.75488L8.25488 7.5V3.25C8.25488 3.08424 8.18904 2.92527 8.07183 2.80806C7.95461 2.69085 7.79564 2.625 7.62988 2.625C7.46412 2.625 7.30515 2.69085 7.18794 2.80806C7.07073 2.92527 7.00488 3.08424 7.00488 3.25V7.5L6.50488 8H2.25488C2.08912 8 1.93015 8.06585 1.81294 8.18306C1.69573 8.30027 1.62988 8.45924 1.62988 8.625C1.62988 8.79076 1.69573 8.94973 1.81294 9.06694C1.93015 9.18415 2.08912 9.25 2.25488 9.25H6.39188L7.00488 9.75Z" fill="black"/>
+</svg>
diff --git a/toolkit/components/pdfjs/content/web/images/toolbarButton-zoomOut.svg b/toolkit/components/pdfjs/content/web/images/toolbarButton-zoomOut.svg
new file mode 100644
index 0000000000..f273b5995c
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/images/toolbarButton-zoomOut.svg
@@ -0,0 +1,3 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M13.375 9.25C13.5408 9.25 13.6997 9.18415 13.8169 9.06694C13.9342 8.94973 14 8.79076 14 8.625C14 8.45924 13.9342 8.30027 13.8169 8.18306C13.6997 8.06585 13.5408 8 13.375 8H2.625C2.45924 8 2.30027 8.06585 2.18306 8.18306C2.06585 8.30027 2 8.45924 2 8.625C2 8.79076 2.06585 8.94973 2.18306 9.06694C2.30027 9.18415 2.45924 9.25 2.625 9.25H13.375Z" fill="black"/>
+</svg>
diff --git a/toolkit/components/pdfjs/content/web/images/treeitem-collapsed.svg b/toolkit/components/pdfjs/content/web/images/treeitem-collapsed.svg
new file mode 100644
index 0000000000..831cddfc86
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/images/treeitem-collapsed.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path d="M13 9L6 5v8z"/></svg> \ No newline at end of file
diff --git a/toolkit/components/pdfjs/content/web/images/treeitem-expanded.svg b/toolkit/components/pdfjs/content/web/images/treeitem-expanded.svg
new file mode 100644
index 0000000000..2d45f0c8d1
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/images/treeitem-expanded.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path d="M10 13l4-7H6z"/></svg> \ No newline at end of file
diff --git a/toolkit/components/pdfjs/content/web/standard_fonts/FoxitDingbats.pfb b/toolkit/components/pdfjs/content/web/standard_fonts/FoxitDingbats.pfb
new file mode 100644
index 0000000000..30d52963e2
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/standard_fonts/FoxitDingbats.pfb
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/standard_fonts/FoxitFixed.pfb b/toolkit/components/pdfjs/content/web/standard_fonts/FoxitFixed.pfb
new file mode 100644
index 0000000000..f12dcbce52
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/standard_fonts/FoxitFixed.pfb
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/standard_fonts/FoxitFixedBold.pfb b/toolkit/components/pdfjs/content/web/standard_fonts/FoxitFixedBold.pfb
new file mode 100644
index 0000000000..cf8e24aee5
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/standard_fonts/FoxitFixedBold.pfb
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/standard_fonts/FoxitFixedBoldItalic.pfb b/toolkit/components/pdfjs/content/web/standard_fonts/FoxitFixedBoldItalic.pfb
new file mode 100644
index 0000000000..d2880017c2
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/standard_fonts/FoxitFixedBoldItalic.pfb
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/standard_fonts/FoxitFixedItalic.pfb b/toolkit/components/pdfjs/content/web/standard_fonts/FoxitFixedItalic.pfb
new file mode 100644
index 0000000000..d71697d4b6
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/standard_fonts/FoxitFixedItalic.pfb
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/standard_fonts/FoxitSerif.pfb b/toolkit/components/pdfjs/content/web/standard_fonts/FoxitSerif.pfb
new file mode 100644
index 0000000000..3fa682efbb
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/standard_fonts/FoxitSerif.pfb
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/standard_fonts/FoxitSerifBold.pfb b/toolkit/components/pdfjs/content/web/standard_fonts/FoxitSerifBold.pfb
new file mode 100644
index 0000000000..ff7c6ddecf
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/standard_fonts/FoxitSerifBold.pfb
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/standard_fonts/FoxitSerifBoldItalic.pfb b/toolkit/components/pdfjs/content/web/standard_fonts/FoxitSerifBoldItalic.pfb
new file mode 100644
index 0000000000..460231fb88
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/standard_fonts/FoxitSerifBoldItalic.pfb
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/standard_fonts/FoxitSerifItalic.pfb b/toolkit/components/pdfjs/content/web/standard_fonts/FoxitSerifItalic.pfb
new file mode 100644
index 0000000000..d03a7c781e
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/standard_fonts/FoxitSerifItalic.pfb
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/standard_fonts/FoxitSymbol.pfb b/toolkit/components/pdfjs/content/web/standard_fonts/FoxitSymbol.pfb
new file mode 100644
index 0000000000..c8f9bca78c
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/standard_fonts/FoxitSymbol.pfb
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/standard_fonts/LICENSE_FOXIT b/toolkit/components/pdfjs/content/web/standard_fonts/LICENSE_FOXIT
new file mode 100644
index 0000000000..8b4ed6dddf
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/standard_fonts/LICENSE_FOXIT
@@ -0,0 +1,27 @@
+// Copyright 2014 PDFium Authors. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/toolkit/components/pdfjs/content/web/standard_fonts/LICENSE_LIBERATION b/toolkit/components/pdfjs/content/web/standard_fonts/LICENSE_LIBERATION
new file mode 100644
index 0000000000..aba73e8a40
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/standard_fonts/LICENSE_LIBERATION
@@ -0,0 +1,102 @@
+Digitized data copyright (c) 2010 Google Corporation
+ with Reserved Font Arimo, Tinos and Cousine.
+Copyright (c) 2012 Red Hat, Inc.
+ with Reserved Font Name Liberation.
+
+This Font Software is licensed under the SIL Open Font License,
+Version 1.1.
+
+This license is copied below, and is also available with a FAQ at:
+http://scripts.sil.org/OFL
+
+SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
+
+PREAMBLE The goals of the Open Font License (OFL) are to stimulate
+worldwide development of collaborative font projects, to support the font
+creation efforts of academic and linguistic communities, and to provide
+a free and open framework in which fonts may be shared and improved in
+partnership with others.
+
+The OFL allows the licensed fonts to be used, studied, modified and
+redistributed freely as long as they are not sold by themselves.
+The fonts, including any derivative works, can be bundled, embedded,
+redistributed and/or sold with any software provided that any reserved
+names are not used by derivative works. The fonts and derivatives,
+however, cannot be released under any other type of license. The
+requirement for fonts to remain under this license does not apply to
+any document created using the fonts or their derivatives.
+
+
+
+DEFINITIONS
+"Font Software" refers to the set of files released by the Copyright
+Holder(s) under this license and clearly marked as such.
+This may include source files, build scripts and documentation.
+
+"Reserved Font Name" refers to any names specified as such after the
+copyright statement(s).
+
+"Original Version" refers to the collection of Font Software components
+as distributed by the Copyright Holder(s).
+
+"Modified Version" refers to any derivative made by adding to, deleting,
+or substituting ? in part or in whole ?
+any of the components of the Original Version, by changing formats or
+by porting the Font Software to a new environment.
+
+"Author" refers to any designer, engineer, programmer, technical writer
+or other person who contributed to the Font Software.
+
+
+PERMISSION & CONDITIONS
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of the Font Software, to use, study, copy, merge, embed, modify,
+redistribute, and sell modified and unmodified copies of the Font
+Software, subject to the following conditions:
+
+1) Neither the Font Software nor any of its individual components,in
+ Original or Modified Versions, may be sold by itself.
+
+2) Original or Modified Versions of the Font Software may be bundled,
+ redistributed and/or sold with any software, provided that each copy
+ contains the above copyright notice and this license. These can be
+ included either as stand-alone text files, human-readable headers or
+ in the appropriate machine-readable metadata fields within text or
+ binary files as long as those fields can be easily viewed by the user.
+
+3) No Modified Version of the Font Software may use the Reserved Font
+ Name(s) unless explicit written permission is granted by the
+ corresponding Copyright Holder. This restriction only applies to the
+ primary font name as presented to the users.
+
+4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
+ Software shall not be used to promote, endorse or advertise any
+ Modified Version, except to acknowledge the contribution(s) of the
+ Copyright Holder(s) and the Author(s) or with their explicit written
+ permission.
+
+5) The Font Software, modified or unmodified, in part or in whole, must
+ be distributed entirely under this license, and must not be distributed
+ under any other license. The requirement for fonts to remain under
+ this license does not apply to any document created using the Font
+ Software.
+
+
+
+TERMINATION
+This license becomes null and void if any of the above conditions are not met.
+
+
+
+DISCLAIMER
+THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
+DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER
+DEALINGS IN THE FONT SOFTWARE.
+
diff --git a/toolkit/components/pdfjs/content/web/standard_fonts/LiberationSans-Bold.ttf b/toolkit/components/pdfjs/content/web/standard_fonts/LiberationSans-Bold.ttf
new file mode 100644
index 0000000000..ee23715404
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/standard_fonts/LiberationSans-Bold.ttf
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/standard_fonts/LiberationSans-BoldItalic.ttf b/toolkit/components/pdfjs/content/web/standard_fonts/LiberationSans-BoldItalic.ttf
new file mode 100644
index 0000000000..42b5717ddb
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/standard_fonts/LiberationSans-BoldItalic.ttf
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/standard_fonts/LiberationSans-Italic.ttf b/toolkit/components/pdfjs/content/web/standard_fonts/LiberationSans-Italic.ttf
new file mode 100644
index 0000000000..0cf6126349
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/standard_fonts/LiberationSans-Italic.ttf
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/standard_fonts/LiberationSans-Regular.ttf b/toolkit/components/pdfjs/content/web/standard_fonts/LiberationSans-Regular.ttf
new file mode 100644
index 0000000000..366d1489cd
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/standard_fonts/LiberationSans-Regular.ttf
Binary files differ
diff --git a/toolkit/components/pdfjs/content/web/viewer-geckoview.css b/toolkit/components/pdfjs/content/web/viewer-geckoview.css
new file mode 100644
index 0000000000..16e27e4eac
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/viewer-geckoview.css
@@ -0,0 +1,1261 @@
+/* Copyright 2014 Mozilla Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+.textLayer{
+ position:absolute;
+ text-align:initial;
+ inset:0;
+ overflow:hidden;
+ opacity:1;
+ line-height:1;
+ text-size-adjust:none;
+ forced-color-adjust:none;
+ transform-origin:0 0;
+ z-index:2;
+ caret-color:CanvasText;
+
+ &.highlighting{
+ touch-action:none;
+ }
+
+ :is(span, br){
+ color:transparent;
+ position:absolute;
+ white-space:pre;
+ cursor:text;
+ transform-origin:0% 0%;
+ }
+
+ .highlight{
+ --highlight-bg-color:rgb(180 0 170 / 0.25);
+ --highlight-selected-bg-color:rgb(0 100 0 / 0.25);
+ --highlight-backdrop-filter:none;
+ --highlight-selected-backdrop-filter:none;
+
+ @media screen and (forced-colors: active){
+ --highlight-bg-color:transparent;
+ --highlight-selected-bg-color:transparent;
+ --highlight-backdrop-filter:var(--hcm-highlight-filter);
+ --highlight-selected-backdrop-filter:var(
+ --hcm-highlight-selected-filter
+ );
+ }
+
+ margin:-1px;
+ padding:1px;
+ background-color:var(--highlight-bg-color);
+ backdrop-filter:var(--highlight-backdrop-filter);
+ border-radius:4px;
+
+ &.appended{
+ position:initial;
+ }
+
+ &.begin{
+ border-radius:4px 0 0 4px;
+ }
+
+ &.end{
+ border-radius:0 4px 4px 0;
+ }
+
+ &.middle{
+ border-radius:0;
+ }
+
+ &.selected{
+ background-color:var(--highlight-selected-bg-color);
+ backdrop-filter:var(--highlight-selected-backdrop-filter);
+ }
+ }
+
+ ::selection{
+ background:color-mix(in srgb, AccentColor, transparent 75%);
+ }
+
+ .endOfContent{
+ display:block;
+ position:absolute;
+ inset:100% 0 0;
+ z-index:-1;
+ cursor:default;
+ user-select:none;
+
+ &.active{
+ top:0;
+ }
+ }
+}
+
+.annotationLayer{
+ --annotation-unfocused-field-background:url("data:image/svg+xml;charset=UTF-8,<svg width='1px' height='1px' xmlns='http://www.w3.org/2000/svg'><rect width='100%' height='100%' style='fill:rgba(0, 54, 255, 0.13);'/></svg>");
+ --input-focus-border-color:Highlight;
+ --input-focus-outline:1px solid Canvas;
+ --input-unfocused-border-color:transparent;
+ --input-disabled-border-color:transparent;
+ --input-hover-border-color:black;
+ --link-outline:none;
+
+ @media screen and (forced-colors: active){
+ --input-focus-border-color:CanvasText;
+ --input-unfocused-border-color:ActiveText;
+ --input-disabled-border-color:GrayText;
+ --input-hover-border-color:Highlight;
+ --link-outline:1.5px solid LinkText;
+
+ .textWidgetAnnotation :is(input, textarea):required,
+ .choiceWidgetAnnotation select:required,
+ .buttonWidgetAnnotation:is(.checkBox, .radioButton) input:required{
+ outline:1.5px solid selectedItem;
+ }
+
+ .linkAnnotation{
+ outline:var(--link-outline);
+
+ &:hover{
+ backdrop-filter:var(--hcm-highlight-filter);
+ }
+
+ & > a:hover{
+ opacity:0 !important;
+ background:none !important;
+ box-shadow:none;
+ }
+ }
+
+ .popupAnnotation .popup{
+ outline:calc(1.5px * var(--scale-factor)) solid CanvasText !important;
+ background-color:ButtonFace !important;
+ color:ButtonText !important;
+ }
+
+ .highlightArea:hover::after{
+ position:absolute;
+ top:0;
+ left:0;
+ width:100%;
+ height:100%;
+ backdrop-filter:var(--hcm-highlight-filter);
+ content:"";
+ pointer-events:none;
+ }
+
+ .popupAnnotation.focused .popup{
+ outline:calc(3px * var(--scale-factor)) solid Highlight !important;
+ }
+ }
+
+ position:absolute;
+ top:0;
+ left:0;
+ pointer-events:none;
+ transform-origin:0 0;
+ z-index:3;
+
+ &[data-main-rotation="90"] .norotate{
+ transform:rotate(270deg) translateX(-100%);
+ }
+ &[data-main-rotation="180"] .norotate{
+ transform:rotate(180deg) translate(-100%, -100%);
+ }
+ &[data-main-rotation="270"] .norotate{
+ transform:rotate(90deg) translateY(-100%);
+ }
+
+ &.disabled{
+ section,
+ .popup{
+ pointer-events:none;
+ }
+ }
+
+ canvas{
+ position:absolute;
+ width:100%;
+ height:100%;
+ pointer-events:none;
+ }
+
+ section{
+ position:absolute;
+ text-align:initial;
+ pointer-events:auto;
+ box-sizing:border-box;
+ transform-origin:0 0;
+ }
+
+ :is(.linkAnnotation, .buttonWidgetAnnotation.pushButton) > a{
+ position:absolute;
+ font-size:1em;
+ top:0;
+ left:0;
+ width:100%;
+ height:100%;
+ }
+
+ :is(.linkAnnotation, .buttonWidgetAnnotation.pushButton):not(.hasBorder)
+ > a:hover{
+ opacity:0.2;
+ background-color:rgb(255 255 0);
+ box-shadow:0 2px 10px rgb(255 255 0);
+ }
+
+ .linkAnnotation.hasBorder:hover{
+ background-color:rgb(255 255 0 / 0.2);
+ }
+
+ .hasBorder{
+ background-size:100% 100%;
+ }
+
+ .textAnnotation img{
+ position:absolute;
+ cursor:pointer;
+ width:100%;
+ height:100%;
+ top:0;
+ left:0;
+ }
+
+ .textWidgetAnnotation :is(input, textarea),
+ .choiceWidgetAnnotation select,
+ .buttonWidgetAnnotation:is(.checkBox, .radioButton) input{
+ background-image:var(--annotation-unfocused-field-background);
+ border:2px solid var(--input-unfocused-border-color);
+ box-sizing:border-box;
+ font:calc(9px * var(--scale-factor)) sans-serif;
+ height:100%;
+ margin:0;
+ vertical-align:top;
+ width:100%;
+ }
+
+ .textWidgetAnnotation :is(input, textarea):required,
+ .choiceWidgetAnnotation select:required,
+ .buttonWidgetAnnotation:is(.checkBox, .radioButton) input:required{
+ outline:1.5px solid red;
+ }
+
+ .choiceWidgetAnnotation select option{
+ padding:0;
+ }
+
+ .buttonWidgetAnnotation.radioButton input{
+ border-radius:50%;
+ }
+
+ .textWidgetAnnotation textarea{
+ resize:none;
+ }
+
+ .textWidgetAnnotation :is(input, textarea)[disabled],
+ .choiceWidgetAnnotation select[disabled],
+ .buttonWidgetAnnotation:is(.checkBox, .radioButton) input[disabled]{
+ background:none;
+ border:2px solid var(--input-disabled-border-color);
+ cursor:not-allowed;
+ }
+
+ .textWidgetAnnotation :is(input, textarea):hover,
+ .choiceWidgetAnnotation select:hover,
+ .buttonWidgetAnnotation:is(.checkBox, .radioButton) input:hover{
+ border:2px solid var(--input-hover-border-color);
+ }
+ .textWidgetAnnotation :is(input, textarea):hover,
+ .choiceWidgetAnnotation select:hover,
+ .buttonWidgetAnnotation.checkBox input:hover{
+ border-radius:2px;
+ }
+
+ .textWidgetAnnotation :is(input, textarea):focus,
+ .choiceWidgetAnnotation select:focus{
+ background:none;
+ border:2px solid var(--input-focus-border-color);
+ border-radius:2px;
+ outline:var(--input-focus-outline);
+ }
+
+ .buttonWidgetAnnotation:is(.checkBox, .radioButton) :focus{
+ background-image:none;
+ background-color:transparent;
+ }
+
+ .buttonWidgetAnnotation.checkBox :focus{
+ border:2px solid var(--input-focus-border-color);
+ border-radius:2px;
+ outline:var(--input-focus-outline);
+ }
+
+ .buttonWidgetAnnotation.radioButton :focus{
+ border:2px solid var(--input-focus-border-color);
+ outline:var(--input-focus-outline);
+ }
+
+ .buttonWidgetAnnotation.checkBox input:checked::before,
+ .buttonWidgetAnnotation.checkBox input:checked::after,
+ .buttonWidgetAnnotation.radioButton input:checked::before{
+ background-color:CanvasText;
+ content:"";
+ display:block;
+ position:absolute;
+ }
+
+ .buttonWidgetAnnotation.checkBox input:checked::before,
+ .buttonWidgetAnnotation.checkBox input:checked::after{
+ height:80%;
+ left:45%;
+ width:1px;
+ }
+
+ .buttonWidgetAnnotation.checkBox input:checked::before{
+ transform:rotate(45deg);
+ }
+
+ .buttonWidgetAnnotation.checkBox input:checked::after{
+ transform:rotate(-45deg);
+ }
+
+ .buttonWidgetAnnotation.radioButton input:checked::before{
+ border-radius:50%;
+ height:50%;
+ left:25%;
+ top:25%;
+ width:50%;
+ }
+
+ .textWidgetAnnotation input.comb{
+ font-family:monospace;
+ padding-left:2px;
+ padding-right:0;
+ }
+
+ .textWidgetAnnotation input.comb:focus{
+ width:103%;
+ }
+
+ .buttonWidgetAnnotation:is(.checkBox, .radioButton) input{
+ appearance:none;
+ }
+
+ .fileAttachmentAnnotation .popupTriggerArea{
+ height:100%;
+ width:100%;
+ }
+
+ .popupAnnotation{
+ position:absolute;
+ font-size:calc(9px * var(--scale-factor));
+ pointer-events:none;
+ width:max-content;
+ max-width:45%;
+ height:auto;
+ }
+
+ .popup{
+ background-color:rgb(255 255 153);
+ box-shadow:0 calc(2px * var(--scale-factor)) calc(5px * var(--scale-factor)) rgb(136 136 136);
+ border-radius:calc(2px * var(--scale-factor));
+ outline:1.5px solid rgb(255 255 74);
+ padding:calc(6px * var(--scale-factor));
+ cursor:pointer;
+ font:message-box;
+ white-space:normal;
+ word-wrap:break-word;
+ pointer-events:auto;
+ }
+
+ .popupAnnotation.focused .popup{
+ outline-width:3px;
+ }
+
+ .popup *{
+ font-size:calc(9px * var(--scale-factor));
+ }
+
+ .popup > .header{
+ display:inline-block;
+ }
+
+ .popup > .header h1{
+ display:inline;
+ }
+
+ .popup > .header .popupDate{
+ display:inline-block;
+ margin-left:calc(5px * var(--scale-factor));
+ width:-moz-fit-content;
+ width:fit-content;
+ }
+
+ .popupContent{
+ border-top:1px solid rgb(51 51 51);
+ margin-top:calc(2px * var(--scale-factor));
+ padding-top:calc(2px * var(--scale-factor));
+ }
+
+ .richText > *{
+ white-space:pre-wrap;
+ font-size:calc(9px * var(--scale-factor));
+ }
+
+ .popupTriggerArea{
+ cursor:pointer;
+ }
+
+ section svg{
+ position:absolute;
+ width:100%;
+ height:100%;
+ top:0;
+ left:0;
+ }
+
+ .annotationTextContent{
+ position:absolute;
+ width:100%;
+ height:100%;
+ opacity:0;
+ color:transparent;
+ user-select:none;
+ pointer-events:none;
+
+ span{
+ width:100%;
+ display:inline-block;
+ }
+ }
+
+ svg.quadrilateralsContainer{
+ contain:strict;
+ width:0;
+ height:0;
+ position:absolute;
+ top:0;
+ left:0;
+ z-index:-1;
+ }
+}
+
+:root{
+ --xfa-unfocused-field-background:url("data:image/svg+xml;charset=UTF-8,<svg width='1px' height='1px' xmlns='http://www.w3.org/2000/svg'><rect width='100%' height='100%' style='fill:rgba(0, 54, 255, 0.13);'/></svg>");
+ --xfa-focus-outline:auto;
+}
+
+@media screen and (forced-colors: active){
+ :root{
+ --xfa-focus-outline:2px solid CanvasText;
+ }
+ .xfaLayer *:required{
+ outline:1.5px solid selectedItem;
+ }
+}
+
+.xfaLayer{
+ background-color:transparent;
+}
+
+.xfaLayer .highlight{
+ margin:-1px;
+ padding:1px;
+ background-color:rgb(239 203 237);
+ border-radius:4px;
+}
+
+.xfaLayer .highlight.appended{
+ position:initial;
+}
+
+.xfaLayer .highlight.begin{
+ border-radius:4px 0 0 4px;
+}
+
+.xfaLayer .highlight.end{
+ border-radius:0 4px 4px 0;
+}
+
+.xfaLayer .highlight.middle{
+ border-radius:0;
+}
+
+.xfaLayer .highlight.selected{
+ background-color:rgb(203 223 203);
+}
+
+.xfaPage{
+ overflow:hidden;
+ position:relative;
+}
+
+.xfaContentarea{
+ position:absolute;
+}
+
+.xfaPrintOnly{
+ display:none;
+}
+
+.xfaLayer{
+ position:absolute;
+ text-align:initial;
+ top:0;
+ left:0;
+ transform-origin:0 0;
+ line-height:1.2;
+}
+
+.xfaLayer *{
+ color:inherit;
+ font:inherit;
+ font-style:inherit;
+ font-weight:inherit;
+ font-kerning:inherit;
+ letter-spacing:-0.01px;
+ text-align:inherit;
+ text-decoration:inherit;
+ box-sizing:border-box;
+ background-color:transparent;
+ padding:0;
+ margin:0;
+ pointer-events:auto;
+ line-height:inherit;
+}
+
+.xfaLayer *:required{
+ outline:1.5px solid red;
+}
+
+.xfaLayer div,
+.xfaLayer svg,
+.xfaLayer svg *{
+ pointer-events:none;
+}
+
+.xfaLayer a{
+ color:blue;
+}
+
+.xfaRich li{
+ margin-left:3em;
+}
+
+.xfaFont{
+ color:black;
+ font-weight:normal;
+ font-kerning:none;
+ font-size:10px;
+ font-style:normal;
+ letter-spacing:0;
+ text-decoration:none;
+ vertical-align:0;
+}
+
+.xfaCaption{
+ overflow:hidden;
+ flex:0 0 auto;
+}
+
+.xfaCaptionForCheckButton{
+ overflow:hidden;
+ flex:1 1 auto;
+}
+
+.xfaLabel{
+ height:100%;
+ width:100%;
+}
+
+.xfaLeft{
+ display:flex;
+ flex-direction:row;
+ align-items:center;
+}
+
+.xfaRight{
+ display:flex;
+ flex-direction:row-reverse;
+ align-items:center;
+}
+
+:is(.xfaLeft, .xfaRight) > :is(.xfaCaption, .xfaCaptionForCheckButton){
+ max-height:100%;
+}
+
+.xfaTop{
+ display:flex;
+ flex-direction:column;
+ align-items:flex-start;
+}
+
+.xfaBottom{
+ display:flex;
+ flex-direction:column-reverse;
+ align-items:flex-start;
+}
+
+:is(.xfaTop, .xfaBottom) > :is(.xfaCaption, .xfaCaptionForCheckButton){
+ width:100%;
+}
+
+.xfaBorder{
+ background-color:transparent;
+ position:absolute;
+ pointer-events:none;
+}
+
+.xfaWrapped{
+ width:100%;
+ height:100%;
+}
+
+:is(.xfaTextfield, .xfaSelect):focus{
+ background-image:none;
+ background-color:transparent;
+ outline:var(--xfa-focus-outline);
+ outline-offset:-1px;
+}
+
+:is(.xfaCheckbox, .xfaRadio):focus{
+ outline:var(--xfa-focus-outline);
+}
+
+.xfaTextfield,
+.xfaSelect{
+ height:100%;
+ width:100%;
+ flex:1 1 auto;
+ border:none;
+ resize:none;
+ background-image:var(--xfa-unfocused-field-background);
+}
+
+.xfaSelect{
+ padding-inline:2px;
+}
+
+:is(.xfaTop, .xfaBottom) > :is(.xfaTextfield, .xfaSelect){
+ flex:0 1 auto;
+}
+
+.xfaButton{
+ cursor:pointer;
+ width:100%;
+ height:100%;
+ border:none;
+ text-align:center;
+}
+
+.xfaLink{
+ width:100%;
+ height:100%;
+ position:absolute;
+ top:0;
+ left:0;
+}
+
+.xfaCheckbox,
+.xfaRadio{
+ width:100%;
+ height:100%;
+ flex:0 0 auto;
+ border:none;
+}
+
+.xfaRich{
+ white-space:pre-wrap;
+ width:100%;
+ height:100%;
+}
+
+.xfaImage{
+ object-position:left top;
+ object-fit:contain;
+ width:100%;
+ height:100%;
+}
+
+.xfaLrTb,
+.xfaRlTb,
+.xfaTb{
+ display:flex;
+ flex-direction:column;
+ align-items:stretch;
+}
+
+.xfaLr{
+ display:flex;
+ flex-direction:row;
+ align-items:stretch;
+}
+
+.xfaRl{
+ display:flex;
+ flex-direction:row-reverse;
+ align-items:stretch;
+}
+
+.xfaTb > div{
+ justify-content:left;
+}
+
+.xfaPosition{
+ position:relative;
+}
+
+.xfaArea{
+ position:relative;
+}
+
+.xfaValignMiddle{
+ display:flex;
+ align-items:center;
+}
+
+.xfaTable{
+ display:flex;
+ flex-direction:column;
+ align-items:stretch;
+}
+
+.xfaTable .xfaRow{
+ display:flex;
+ flex-direction:row;
+ align-items:stretch;
+}
+
+.xfaTable .xfaRlRow{
+ display:flex;
+ flex-direction:row-reverse;
+ align-items:stretch;
+ flex:1;
+}
+
+.xfaTable .xfaRlRow > div{
+ flex:1;
+}
+
+:is(.xfaNonInteractive, .xfaDisabled, .xfaReadOnly) :is(input, textarea){
+ background:initial;
+}
+
+@media print{
+ .xfaTextfield,
+ .xfaSelect{
+ background:transparent;
+ }
+
+ .xfaSelect{
+ appearance:none;
+ text-indent:1px;
+ text-overflow:"";
+ }
+}
+
+:root{
+ --viewer-container-height:0;
+ --pdfViewer-padding-bottom:0;
+ --page-margin:1px auto -8px;
+ --page-border:9px solid transparent;
+ --spreadHorizontalWrapped-margin-LR:-3.5px;
+ --loading-icon-delay:400ms;
+}
+
+@media screen and (forced-colors: active){
+ :root{
+ --pdfViewer-padding-bottom:9px;
+ --page-margin:8px auto -1px;
+ --page-border:1px solid CanvasText;
+ --spreadHorizontalWrapped-margin-LR:3.5px;
+ }
+}
+
+[data-main-rotation="90"]{
+ transform:rotate(90deg) translateY(-100%);
+}
+[data-main-rotation="180"]{
+ transform:rotate(180deg) translate(-100%, -100%);
+}
+[data-main-rotation="270"]{
+ transform:rotate(270deg) translateX(-100%);
+}
+
+#hiddenCopyElement,
+.hiddenCanvasElement{
+ position:absolute;
+ top:0;
+ left:0;
+ width:0;
+ height:0;
+ display:none;
+}
+
+.pdfViewer{
+ --scale-factor:1;
+
+ padding-bottom:var(--pdfViewer-padding-bottom);
+
+ --hcm-highlight-filter:none;
+ --hcm-highlight-selected-filter:none;
+
+ @media screen and (forced-colors: active){
+ --hcm-highlight-filter:invert(100%);
+ }
+}
+
+.pdfViewer .canvasWrapper{
+ overflow:hidden;
+ width:100%;
+ height:100%;
+ z-index:1;
+}
+
+.pdfViewer .page{
+ direction:ltr;
+ width:816px;
+ height:1056px;
+ margin:var(--page-margin);
+ position:relative;
+ overflow:visible;
+ border:var(--page-border);
+ background-clip:content-box;
+ background-color:rgb(255 255 255);
+}
+
+.pdfViewer .dummyPage{
+ position:relative;
+ width:0;
+ height:var(--viewer-container-height);
+}
+
+.pdfViewer.noUserSelect{
+ user-select:none;
+}
+
+.pdfViewer:is(.scrollHorizontal, .scrollWrapped),
+.spread{
+ margin-inline:3.5px;
+ text-align:center;
+}
+
+.pdfViewer.scrollHorizontal,
+.spread{
+ white-space:nowrap;
+}
+
+.pdfViewer:is(.scrollHorizontal, .scrollWrapped) .spread{
+ margin-inline:0;
+}
+
+.spread :is(.page, .dummyPage),
+.pdfViewer:is(.scrollHorizontal, .scrollWrapped) :is(.page, .spread){
+ display:inline-block;
+ vertical-align:middle;
+}
+
+.spread .page,
+.pdfViewer:is(.scrollHorizontal, .scrollWrapped) .page{
+ margin-inline:var(--spreadHorizontalWrapped-margin-LR);
+}
+
+.pdfViewer .page canvas{
+ margin:0;
+ display:block;
+}
+
+.pdfViewer .page canvas .structTree{
+ contain:strict;
+}
+
+.pdfViewer .page canvas[hidden]{
+ display:none;
+}
+
+.pdfViewer .page canvas[zooming]{
+ width:100%;
+ height:100%;
+}
+
+.pdfViewer .page.loadingIcon::after{
+ position:absolute;
+ top:0;
+ left:0;
+ content:"";
+ width:100%;
+ height:100%;
+ background:url("images/loading-icon.gif") center no-repeat;
+ display:none;
+ transition-property:display;
+ transition-delay:var(--loading-icon-delay);
+ z-index:5;
+ contain:strict;
+}
+
+.pdfViewer .page.loading::after{
+ display:block;
+}
+
+.pdfViewer .page:not(.loading)::after{
+ transition-property:none;
+ display:none;
+}
+
+.pdfPresentationMode .pdfViewer{
+ padding-bottom:0;
+}
+
+.pdfPresentationMode .spread{
+ margin:0;
+}
+
+.pdfPresentationMode .pdfViewer .page{
+ margin:0 auto;
+ border:2px solid transparent;
+}
+
+:root{
+ --dir-factor:1;
+ --scale-select-width:140px;
+
+ --toolbar-icon-opacity:1;
+ --doorhanger-icon-opacity:0.9;
+
+ --main-color:rgb(12 12 13);
+ --body-bg-color:rgb(212 212 215);
+ --scrollbar-color:auto;
+ --scrollbar-bg-color:auto;
+ --field-color:rgb(6 6 6);
+ --field-bg-color:rgb(255 255 255);
+ --field-border-color:rgb(187 187 188);
+ --doorhanger-bg-color:rgb(255 255 255);
+ --dialog-button-border:none;
+ --dialog-button-bg-color:rgb(12 12 13 / 0.1);
+ --dialog-button-hover-bg-color:rgb(12 12 13 / 0.3);
+
+ --toolbar-bg-color:#f9f9fb;
+ --toolbar-divider-color:#e0e0e6;
+ --toolbar-fg-color:#15141a;
+
+ --toolbarButton-download-icon:url(images/gv-toolbarButton-download.svg);
+ --toolbarButton-openinapp-icon:url(images/gv-toolbarButton-openinapp.svg);
+}
+
+:root:dir(rtl){
+ --dir-factor:-1;
+}
+
+@media (prefers-color-scheme: dark){
+ :root{
+ --main-color:rgb(249 249 250);
+ --body-bg-color:rgb(42 42 46);
+ --scrollbar-color:rgb(121 121 123);
+ --scrollbar-bg-color:rgb(35 35 39);
+ --field-color:rgb(250 250 250);
+ --field-bg-color:rgb(64 64 68);
+ --field-border-color:rgb(115 115 115);
+ --doorhanger-bg-color:rgb(74 74 79);
+ --dialog-button-bg-color:rgb(92 92 97);
+ --dialog-button-hover-bg-color:rgb(115 115 115);
+
+ --toolbar-bg-color:#2b2a33;
+ --toolbar-divider-color:#5b5b66;
+ --toolbar-fg-color:#fbfbfe;
+ }
+}
+
+@media screen and (forced-colors: active){
+ :root{
+ --dialog-button-border:1px solid Highlight;
+ --dialog-button-hover-bg-color:Highlight;
+ --dialog-button-hover-color:ButtonFace;
+ --field-border-color:ButtonText;
+ --main-color:CanvasText;
+ }
+}
+
+*{
+ padding:0;
+ margin:0;
+}
+
+html,
+body{
+ height:100%;
+ width:100%;
+}
+
+body{
+ background-color:var(--body-bg-color);
+ scrollbar-color:var(--scrollbar-color) var(--scrollbar-bg-color);
+}
+
+.hidden,
+[hidden]{
+ display:none !important;
+}
+
+#outerContainer{
+ width:100%;
+ height:100%;
+ position:relative;
+}
+
+#mainContainer{
+ position:absolute;
+ inset:0;
+ min-width:350px;
+}
+
+#viewerContainer{
+ overflow:auto;
+ position:absolute;
+ inset-block:41px 0;
+ inset-inline:0;
+ outline:none;
+}
+
+#viewerContainer.noToolbar{
+ inset-block-start:0;
+}
+
+.dialogButton{
+ border:none;
+ background:none;
+ width:28px;
+ height:28px;
+ outline:none;
+}
+
+.dialogButton:is(:hover, :focus-visible){
+ background-color:var(--dialog-button-hover-bg-color);
+}
+
+.dialogButton:is(:hover, :focus-visible) > span{
+ color:var(--dialog-button-hover-color);
+}
+
+.dialogButton[disabled]{
+ opacity:0.5;
+}
+
+.dialogButton{
+ min-width:16px;
+ margin:2px 1px;
+ padding:2px 6px 0;
+ border:none;
+ border-radius:2px;
+ color:var(--main-color);
+ font-size:12px;
+ line-height:14px;
+ user-select:none;
+ cursor:default;
+ box-sizing:border-box;
+}
+
+.toolbarField{
+ padding:4px 7px;
+ margin:3px 0;
+ border-radius:2px;
+ background-color:var(--field-bg-color);
+ background-clip:padding-box;
+ border:1px solid var(--field-border-color);
+ box-shadow:none;
+ color:var(--field-color);
+ font-size:12px;
+ line-height:16px;
+ outline:none;
+}
+
+.toolbarField:focus{
+ border-color:#0a84ff;
+}
+
+#floatingToolbar{
+ display:flex;
+ align-items:center;
+ position:absolute;
+ width:100%;
+ height:40px;
+ top:0;
+ left:0;
+ box-sizing:content-box;
+ border-block-end:solid 1px var(--toolbar-divider-color);
+ background-color:var(--toolbar-bg-color);
+}
+
+#floatingToolbar.show{
+ z-index:100000;
+ opacity:1;
+}
+
+#floatingToolbar:not(show){
+ z-index:-1;
+ opacity:0;
+}
+
+.toolbarButton{
+ display:flex;
+ align-items:center;
+ border-style:none;
+ user-select:none;
+ box-sizing:border-box;
+ background-color:transparent;
+ width:auto;
+ height:auto;
+ outline:none;
+ position:relative;
+}
+
+.toolbarButton > span{
+ color:var(--toolbar-fg-color);
+ width:auto;
+ height:auto;
+ overflow:hidden;
+}
+
+:is(.toolbarButton .dialogButton)[disabled]{
+ opacity:0.5;
+}
+
+.toolbarButton::before{
+ width:24px;
+ height:24px;
+ content:"";
+ background-color:var(--toolbar-fg-color);
+ mask-size:cover;
+ margin-inline:12px 8px;
+}
+
+#download::before{
+ mask-image:var(--toolbarButton-download-icon);
+}
+
+#openInApp::before{
+ mask-image:var(--toolbarButton-openinapp-icon);
+}
+
+.dialogButton{
+ width:auto;
+ margin:3px 4px 2px !important;
+ padding:2px 11px;
+ color:var(--main-color);
+ background-color:var(--dialog-button-bg-color);
+ border:var(--dialog-button-border) !important;
+}
+
+dialog{
+ margin:auto;
+ padding:15px;
+ border-spacing:4px;
+ color:var(--main-color);
+ font:message-box;
+ font-size:12px;
+ line-height:14px;
+ background-color:var(--doorhanger-bg-color);
+ border:1px solid rgb(0 0 0 / 0.5);
+ border-radius:4px;
+ box-shadow:0 1px 4px rgb(0 0 0 / 0.3);
+}
+dialog::backdrop{
+ background-color:rgb(0 0 0 / 0.2);
+}
+
+dialog > .row{
+ display:table-row;
+}
+
+dialog > .row > *{
+ display:table-cell;
+}
+
+dialog .toolbarField{
+ margin:5px 0;
+}
+
+dialog .separator{
+ display:block;
+ margin:4px 0;
+ height:1px;
+ width:100%;
+ background-color:var(--separator-color);
+}
+
+dialog .buttonRow{
+ text-align:center;
+ vertical-align:middle;
+}
+
+dialog :link{
+ color:rgb(255 255 255);
+}
+
+#passwordDialog{
+ text-align:center;
+}
+#passwordDialog .toolbarField{
+ width:200px;
+}
+
+@page{
+ margin:0;
+}
+
+#printContainer{
+ display:none;
+}
+
+@media print{
+ body{
+ background:rgb(0 0 0 / 0) none;
+ }
+ body[data-pdfjsprinting] #outerContainer{
+ display:none;
+ }
+ body[data-pdfjsprinting] #printContainer{
+ display:block;
+ }
+ #printContainer{
+ height:100%;
+ }
+ #printContainer > .printedPage{
+ page-break-after:always;
+ page-break-inside:avoid;
+ height:100%;
+ width:100%;
+
+ display:flex;
+ flex-direction:column;
+ justify-content:center;
+ align-items:center;
+ }
+
+ #printContainer > .xfaPrintedPage .xfaPage{
+ position:absolute;
+ }
+
+ #printContainer > .xfaPrintedPage{
+ page-break-after:always;
+ page-break-inside:avoid;
+ width:100%;
+ height:100%;
+ position:relative;
+ }
+
+ #printContainer > .printedPage :is(canvas, img){
+ max-width:100%;
+ max-height:100%;
+
+ direction:ltr;
+ display:block;
+ }
+}
diff --git a/toolkit/components/pdfjs/content/web/viewer-geckoview.html b/toolkit/components/pdfjs/content/web/viewer-geckoview.html
new file mode 100644
index 0000000000..1c0296a481
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/viewer-geckoview.html
@@ -0,0 +1,76 @@
+<!DOCTYPE html>
+<!--
+Copyright 2012 Mozilla Foundation
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+Adobe CMap resources are covered by their own copyright but the same license:
+
+ Copyright 1990-2015 Adobe Systems Incorporated.
+
+See https://github.com/adobe-type-tools/cmap-resources
+-->
+<html dir="ltr" mozdisallowselectionprint>
+ <head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
+ <title>PDF.js viewer</title>
+
+<!-- This snippet is used in the Firefox extension (included from viewer.html) -->
+<script src="resource://pdf.js/build/pdf.mjs" type="module"></script>
+
+ <link rel="stylesheet" href="resource://pdf.js/web/viewer.css">
+ <link rel="localization" href="toolkit/pdfviewer/viewer.ftl"/>
+
+ <script src="resource://pdf.js/web/viewer.mjs" type="module"></script>
+
+ </head>
+
+ <body tabindex="1">
+ <div id="outerContainer">
+
+ <div id="mainContainer">
+
+ <div id="floatingToolbar">
+ <button id="download" class="toolbarButton" title="Download" tabindex="31" data-l10n-id="pdfjs-download-button">
+ <span data-l10n-id="pdfjs-download-button-label">Download</span>
+ </button>
+ <button id="openInApp" class="toolbarButton" title="Open in app" tabindex="32" data-l10n-id="pdfjs-open-in-app-button">
+ <span data-l10n-id="pdfjs-open-in-app-button-label">Open in app</span>
+ </button>
+ </div>
+
+ <div id="viewerContainer" tabindex="0">
+ <div id="viewer" class="pdfViewer"></div>
+ </div>
+ </div> <!-- mainContainer -->
+
+ <div id="dialogContainer">
+ <dialog id="passwordDialog">
+ <div class="row">
+ <label for="password" id="passwordText" data-l10n-id="pdfjs-password-label">Enter the password to open this PDF file:</label>
+ </div>
+ <div class="row">
+ <input type="password" id="password" class="toolbarField">
+ </div>
+ <div class="buttonRow">
+ <button id="passwordCancel" class="dialogButton"><span data-l10n-id="pdfjs-password-cancel-button">Cancel</span></button>
+ <button id="passwordSubmit" class="dialogButton"><span data-l10n-id="pdfjs-password-ok-button">OK</span></button>
+ </div>
+ </dialog>
+ </div> <!-- dialogContainer -->
+
+ </div> <!-- outerContainer -->
+ <div id="printContainer"></div>
+ </body>
+</html>
diff --git a/toolkit/components/pdfjs/content/web/viewer-geckoview.mjs b/toolkit/components/pdfjs/content/web/viewer-geckoview.mjs
new file mode 100644
index 0000000000..8ba8147a9f
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/viewer-geckoview.mjs
@@ -0,0 +1,9554 @@
+/**
+ * @licstart The following is the entire license notice for the
+ * JavaScript code in this page
+ *
+ * Copyright 2023 Mozilla Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * @licend The above is the entire license notice for the
+ * JavaScript code in this page
+ */
+
+/******/ // The require scope
+/******/ var __webpack_require__ = {};
+/******/
+/************************************************************************/
+/******/ /* webpack/runtime/define property getters */
+/******/ (() => {
+/******/ // define getter functions for harmony exports
+/******/ __webpack_require__.d = (exports, definition) => {
+/******/ for(var key in definition) {
+/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
+/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
+/******/ }
+/******/ }
+/******/ };
+/******/ })();
+/******/
+/******/ /* webpack/runtime/hasOwnProperty shorthand */
+/******/ (() => {
+/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
+/******/ })();
+/******/
+/************************************************************************/
+var __webpack_exports__ = {};
+
+// EXPORTS
+__webpack_require__.d(__webpack_exports__, {
+ PDFViewerApplication: () => (/* reexport */ PDFViewerApplication),
+ PDFViewerApplicationConstants: () => (/* binding */ AppConstants),
+ PDFViewerApplicationOptions: () => (/* reexport */ AppOptions)
+});
+
+;// CONCATENATED MODULE: ./web/ui_utils.js
+const DEFAULT_SCALE_VALUE = "auto";
+const DEFAULT_SCALE = 1.0;
+const DEFAULT_SCALE_DELTA = 1.1;
+const MIN_SCALE = 0.1;
+const MAX_SCALE = 10.0;
+const UNKNOWN_SCALE = 0;
+const MAX_AUTO_SCALE = 1.25;
+const SCROLLBAR_PADDING = 40;
+const VERTICAL_PADDING = 5;
+const RenderingStates = {
+ INITIAL: 0,
+ RUNNING: 1,
+ PAUSED: 2,
+ FINISHED: 3
+};
+const PresentationModeState = {
+ UNKNOWN: 0,
+ NORMAL: 1,
+ CHANGING: 2,
+ FULLSCREEN: 3
+};
+const SidebarView = {
+ UNKNOWN: -1,
+ NONE: 0,
+ THUMBS: 1,
+ OUTLINE: 2,
+ ATTACHMENTS: 3,
+ LAYERS: 4
+};
+const TextLayerMode = {
+ DISABLE: 0,
+ ENABLE: 1,
+ ENABLE_PERMISSIONS: 2
+};
+const ScrollMode = {
+ UNKNOWN: -1,
+ VERTICAL: 0,
+ HORIZONTAL: 1,
+ WRAPPED: 2,
+ PAGE: 3
+};
+const SpreadMode = {
+ UNKNOWN: -1,
+ NONE: 0,
+ ODD: 1,
+ EVEN: 2
+};
+const CursorTool = {
+ SELECT: 0,
+ HAND: 1,
+ ZOOM: 2
+};
+const AutoPrintRegExp = /\bprint\s*\(/;
+class OutputScale {
+ constructor() {
+ const pixelRatio = window.devicePixelRatio || 1;
+ this.sx = pixelRatio;
+ this.sy = pixelRatio;
+ }
+ get scaled() {
+ return this.sx !== 1 || this.sy !== 1;
+ }
+}
+function scrollIntoView(element, spot, scrollMatches = false) {
+ let parent = element.offsetParent;
+ if (!parent) {
+ console.error("offsetParent is not set -- cannot scroll");
+ return;
+ }
+ let offsetY = element.offsetTop + element.clientTop;
+ let offsetX = element.offsetLeft + element.clientLeft;
+ while (parent.clientHeight === parent.scrollHeight && parent.clientWidth === parent.scrollWidth || scrollMatches && (parent.classList.contains("markedContent") || getComputedStyle(parent).overflow === "hidden")) {
+ offsetY += parent.offsetTop;
+ offsetX += parent.offsetLeft;
+ parent = parent.offsetParent;
+ if (!parent) {
+ return;
+ }
+ }
+ if (spot) {
+ if (spot.top !== undefined) {
+ offsetY += spot.top;
+ }
+ if (spot.left !== undefined) {
+ offsetX += spot.left;
+ parent.scrollLeft = offsetX;
+ }
+ }
+ parent.scrollTop = offsetY;
+}
+function watchScroll(viewAreaElement, callback) {
+ const debounceScroll = function (evt) {
+ if (rAF) {
+ return;
+ }
+ rAF = window.requestAnimationFrame(function viewAreaElementScrolled() {
+ rAF = null;
+ const currentX = viewAreaElement.scrollLeft;
+ const lastX = state.lastX;
+ if (currentX !== lastX) {
+ state.right = currentX > lastX;
+ }
+ state.lastX = currentX;
+ const currentY = viewAreaElement.scrollTop;
+ const lastY = state.lastY;
+ if (currentY !== lastY) {
+ state.down = currentY > lastY;
+ }
+ state.lastY = currentY;
+ callback(state);
+ });
+ };
+ const state = {
+ right: true,
+ down: true,
+ lastX: viewAreaElement.scrollLeft,
+ lastY: viewAreaElement.scrollTop,
+ _eventHandler: debounceScroll
+ };
+ let rAF = null;
+ viewAreaElement.addEventListener("scroll", debounceScroll, true);
+ return state;
+}
+function parseQueryString(query) {
+ const params = new Map();
+ for (const [key, value] of new URLSearchParams(query)) {
+ params.set(key.toLowerCase(), value);
+ }
+ return params;
+}
+const InvisibleCharsRegExp = /[\x00-\x1F]/g;
+function removeNullCharacters(str, replaceInvisible = false) {
+ if (!InvisibleCharsRegExp.test(str)) {
+ return str;
+ }
+ if (replaceInvisible) {
+ return str.replaceAll(InvisibleCharsRegExp, m => m === "\x00" ? "" : " ");
+ }
+ return str.replaceAll("\x00", "");
+}
+function binarySearchFirstItem(items, condition, start = 0) {
+ let minIndex = start;
+ let maxIndex = items.length - 1;
+ if (maxIndex < 0 || !condition(items[maxIndex])) {
+ return items.length;
+ }
+ if (condition(items[minIndex])) {
+ return minIndex;
+ }
+ while (minIndex < maxIndex) {
+ const currentIndex = minIndex + maxIndex >> 1;
+ const currentItem = items[currentIndex];
+ if (condition(currentItem)) {
+ maxIndex = currentIndex;
+ } else {
+ minIndex = currentIndex + 1;
+ }
+ }
+ return minIndex;
+}
+function approximateFraction(x) {
+ if (Math.floor(x) === x) {
+ return [x, 1];
+ }
+ const xinv = 1 / x;
+ const limit = 8;
+ if (xinv > limit) {
+ return [1, limit];
+ } else if (Math.floor(xinv) === xinv) {
+ return [1, xinv];
+ }
+ const x_ = x > 1 ? xinv : x;
+ let a = 0,
+ b = 1,
+ c = 1,
+ d = 1;
+ while (true) {
+ const p = a + c,
+ q = b + d;
+ if (q > limit) {
+ break;
+ }
+ if (x_ <= p / q) {
+ c = p;
+ d = q;
+ } else {
+ a = p;
+ b = q;
+ }
+ }
+ let result;
+ if (x_ - a / b < c / d - x_) {
+ result = x_ === x ? [a, b] : [b, a];
+ } else {
+ result = x_ === x ? [c, d] : [d, c];
+ }
+ return result;
+}
+function roundToDivide(x, div) {
+ const r = x % div;
+ return r === 0 ? x : Math.round(x - r + div);
+}
+function getPageSizeInches({
+ view,
+ userUnit,
+ rotate
+}) {
+ const [x1, y1, x2, y2] = view;
+ const changeOrientation = rotate % 180 !== 0;
+ const width = (x2 - x1) / 72 * userUnit;
+ const height = (y2 - y1) / 72 * userUnit;
+ return {
+ width: changeOrientation ? height : width,
+ height: changeOrientation ? width : height
+ };
+}
+function backtrackBeforeAllVisibleElements(index, views, top) {
+ if (index < 2) {
+ return index;
+ }
+ let elt = views[index].div;
+ let pageTop = elt.offsetTop + elt.clientTop;
+ if (pageTop >= top) {
+ elt = views[index - 1].div;
+ pageTop = elt.offsetTop + elt.clientTop;
+ }
+ for (let i = index - 2; i >= 0; --i) {
+ elt = views[i].div;
+ if (elt.offsetTop + elt.clientTop + elt.clientHeight <= pageTop) {
+ break;
+ }
+ index = i;
+ }
+ return index;
+}
+function getVisibleElements({
+ scrollEl,
+ views,
+ sortByVisibility = false,
+ horizontal = false,
+ rtl = false
+}) {
+ const top = scrollEl.scrollTop,
+ bottom = top + scrollEl.clientHeight;
+ const left = scrollEl.scrollLeft,
+ right = left + scrollEl.clientWidth;
+ function isElementBottomAfterViewTop(view) {
+ const element = view.div;
+ const elementBottom = element.offsetTop + element.clientTop + element.clientHeight;
+ return elementBottom > top;
+ }
+ function isElementNextAfterViewHorizontally(view) {
+ const element = view.div;
+ const elementLeft = element.offsetLeft + element.clientLeft;
+ const elementRight = elementLeft + element.clientWidth;
+ return rtl ? elementLeft < right : elementRight > left;
+ }
+ const visible = [],
+ ids = new Set(),
+ numViews = views.length;
+ let firstVisibleElementInd = binarySearchFirstItem(views, horizontal ? isElementNextAfterViewHorizontally : isElementBottomAfterViewTop);
+ if (firstVisibleElementInd > 0 && firstVisibleElementInd < numViews && !horizontal) {
+ firstVisibleElementInd = backtrackBeforeAllVisibleElements(firstVisibleElementInd, views, top);
+ }
+ let lastEdge = horizontal ? right : -1;
+ for (let i = firstVisibleElementInd; i < numViews; i++) {
+ const view = views[i],
+ element = view.div;
+ const currentWidth = element.offsetLeft + element.clientLeft;
+ const currentHeight = element.offsetTop + element.clientTop;
+ const viewWidth = element.clientWidth,
+ viewHeight = element.clientHeight;
+ const viewRight = currentWidth + viewWidth;
+ const viewBottom = currentHeight + viewHeight;
+ if (lastEdge === -1) {
+ if (viewBottom >= bottom) {
+ lastEdge = viewBottom;
+ }
+ } else if ((horizontal ? currentWidth : currentHeight) > lastEdge) {
+ break;
+ }
+ if (viewBottom <= top || currentHeight >= bottom || viewRight <= left || currentWidth >= right) {
+ continue;
+ }
+ const hiddenHeight = Math.max(0, top - currentHeight) + Math.max(0, viewBottom - bottom);
+ const hiddenWidth = Math.max(0, left - currentWidth) + Math.max(0, viewRight - right);
+ const fractionHeight = (viewHeight - hiddenHeight) / viewHeight,
+ fractionWidth = (viewWidth - hiddenWidth) / viewWidth;
+ const percent = fractionHeight * fractionWidth * 100 | 0;
+ visible.push({
+ id: view.id,
+ x: currentWidth,
+ y: currentHeight,
+ view,
+ percent,
+ widthPercent: fractionWidth * 100 | 0
+ });
+ ids.add(view.id);
+ }
+ const first = visible[0],
+ last = visible.at(-1);
+ if (sortByVisibility) {
+ visible.sort(function (a, b) {
+ const pc = a.percent - b.percent;
+ if (Math.abs(pc) > 0.001) {
+ return -pc;
+ }
+ return a.id - b.id;
+ });
+ }
+ return {
+ first,
+ last,
+ views: visible,
+ ids
+ };
+}
+function normalizeWheelEventDirection(evt) {
+ let delta = Math.hypot(evt.deltaX, evt.deltaY);
+ const angle = Math.atan2(evt.deltaY, evt.deltaX);
+ if (-0.25 * Math.PI < angle && angle < 0.75 * Math.PI) {
+ delta = -delta;
+ }
+ return delta;
+}
+function normalizeWheelEventDelta(evt) {
+ const deltaMode = evt.deltaMode;
+ let delta = normalizeWheelEventDirection(evt);
+ const MOUSE_PIXELS_PER_LINE = 30;
+ const MOUSE_LINES_PER_PAGE = 30;
+ if (deltaMode === WheelEvent.DOM_DELTA_PIXEL) {
+ delta /= MOUSE_PIXELS_PER_LINE * MOUSE_LINES_PER_PAGE;
+ } else if (deltaMode === WheelEvent.DOM_DELTA_LINE) {
+ delta /= MOUSE_LINES_PER_PAGE;
+ }
+ return delta;
+}
+function isValidRotation(angle) {
+ return Number.isInteger(angle) && angle % 90 === 0;
+}
+function isValidScrollMode(mode) {
+ return Number.isInteger(mode) && Object.values(ScrollMode).includes(mode) && mode !== ScrollMode.UNKNOWN;
+}
+function isValidSpreadMode(mode) {
+ return Number.isInteger(mode) && Object.values(SpreadMode).includes(mode) && mode !== SpreadMode.UNKNOWN;
+}
+function isPortraitOrientation(size) {
+ return size.width <= size.height;
+}
+const animationStarted = new Promise(function (resolve) {
+ window.requestAnimationFrame(resolve);
+});
+const docStyle = document.documentElement.style;
+function clamp(v, min, max) {
+ return Math.min(Math.max(v, min), max);
+}
+class ProgressBar {
+ #classList = null;
+ #disableAutoFetchTimeout = null;
+ #percent = 0;
+ #style = null;
+ #visible = true;
+ constructor(bar) {
+ this.#classList = bar.classList;
+ this.#style = bar.style;
+ }
+ get percent() {
+ return this.#percent;
+ }
+ set percent(val) {
+ this.#percent = clamp(val, 0, 100);
+ if (isNaN(val)) {
+ this.#classList.add("indeterminate");
+ return;
+ }
+ this.#classList.remove("indeterminate");
+ this.#style.setProperty("--progressBar-percent", `${this.#percent}%`);
+ }
+ setWidth(viewer) {
+ if (!viewer) {
+ return;
+ }
+ const container = viewer.parentNode;
+ const scrollbarWidth = container.offsetWidth - viewer.offsetWidth;
+ if (scrollbarWidth > 0) {
+ this.#style.setProperty("--progressBar-end-offset", `${scrollbarWidth}px`);
+ }
+ }
+ setDisableAutoFetch(delay = 5000) {
+ if (isNaN(this.#percent)) {
+ return;
+ }
+ if (this.#disableAutoFetchTimeout) {
+ clearTimeout(this.#disableAutoFetchTimeout);
+ }
+ this.show();
+ this.#disableAutoFetchTimeout = setTimeout(() => {
+ this.#disableAutoFetchTimeout = null;
+ this.hide();
+ }, delay);
+ }
+ hide() {
+ if (!this.#visible) {
+ return;
+ }
+ this.#visible = false;
+ this.#classList.add("hidden");
+ }
+ show() {
+ if (this.#visible) {
+ return;
+ }
+ this.#visible = true;
+ this.#classList.remove("hidden");
+ }
+}
+function getActiveOrFocusedElement() {
+ let curRoot = document;
+ let curActiveOrFocused = curRoot.activeElement || curRoot.querySelector(":focus");
+ while (curActiveOrFocused?.shadowRoot) {
+ curRoot = curActiveOrFocused.shadowRoot;
+ curActiveOrFocused = curRoot.activeElement || curRoot.querySelector(":focus");
+ }
+ return curActiveOrFocused;
+}
+function apiPageLayoutToViewerModes(layout) {
+ let scrollMode = ScrollMode.VERTICAL,
+ spreadMode = SpreadMode.NONE;
+ switch (layout) {
+ case "SinglePage":
+ scrollMode = ScrollMode.PAGE;
+ break;
+ case "OneColumn":
+ break;
+ case "TwoPageLeft":
+ scrollMode = ScrollMode.PAGE;
+ case "TwoColumnLeft":
+ spreadMode = SpreadMode.ODD;
+ break;
+ case "TwoPageRight":
+ scrollMode = ScrollMode.PAGE;
+ case "TwoColumnRight":
+ spreadMode = SpreadMode.EVEN;
+ break;
+ }
+ return {
+ scrollMode,
+ spreadMode
+ };
+}
+function apiPageModeToSidebarView(mode) {
+ switch (mode) {
+ case "UseNone":
+ return SidebarView.NONE;
+ case "UseThumbs":
+ return SidebarView.THUMBS;
+ case "UseOutlines":
+ return SidebarView.OUTLINE;
+ case "UseAttachments":
+ return SidebarView.ATTACHMENTS;
+ case "UseOC":
+ return SidebarView.LAYERS;
+ }
+ return SidebarView.NONE;
+}
+function toggleCheckedBtn(button, toggle, view = null) {
+ button.classList.toggle("toggled", toggle);
+ button.setAttribute("aria-checked", toggle);
+ view?.classList.toggle("hidden", !toggle);
+}
+function toggleExpandedBtn(button, toggle, view = null) {
+ button.classList.toggle("toggled", toggle);
+ button.setAttribute("aria-expanded", toggle);
+ view?.classList.toggle("hidden", !toggle);
+}
+
+;// CONCATENATED MODULE: ./web/app_options.js
+const compatibilityParams = Object.create(null);
+const OptionKind = {
+ BROWSER: 0x01,
+ VIEWER: 0x02,
+ API: 0x04,
+ WORKER: 0x08,
+ PREFERENCE: 0x80
+};
+const defaultOptions = {
+ canvasMaxAreaInBytes: {
+ value: -1,
+ kind: OptionKind.BROWSER + OptionKind.API
+ },
+ isInAutomation: {
+ value: false,
+ kind: OptionKind.BROWSER
+ },
+ supportsCaretBrowsingMode: {
+ value: false,
+ kind: OptionKind.BROWSER
+ },
+ supportsDocumentFonts: {
+ value: true,
+ kind: OptionKind.BROWSER
+ },
+ supportsIntegratedFind: {
+ value: false,
+ kind: OptionKind.BROWSER
+ },
+ supportsMouseWheelZoomCtrlKey: {
+ value: true,
+ kind: OptionKind.BROWSER
+ },
+ supportsMouseWheelZoomMetaKey: {
+ value: true,
+ kind: OptionKind.BROWSER
+ },
+ supportsPinchToZoom: {
+ value: true,
+ kind: OptionKind.BROWSER
+ },
+ annotationEditorMode: {
+ value: 0,
+ kind: OptionKind.VIEWER + OptionKind.PREFERENCE
+ },
+ annotationMode: {
+ value: 2,
+ kind: OptionKind.VIEWER + OptionKind.PREFERENCE
+ },
+ cursorToolOnLoad: {
+ value: 0,
+ kind: OptionKind.VIEWER + OptionKind.PREFERENCE
+ },
+ debuggerSrc: {
+ value: "./debugger.mjs",
+ kind: OptionKind.VIEWER
+ },
+ defaultZoomDelay: {
+ value: 400,
+ kind: OptionKind.VIEWER + OptionKind.PREFERENCE
+ },
+ defaultZoomValue: {
+ value: "",
+ kind: OptionKind.VIEWER + OptionKind.PREFERENCE
+ },
+ disableHistory: {
+ value: false,
+ kind: OptionKind.VIEWER
+ },
+ disablePageLabels: {
+ value: false,
+ kind: OptionKind.VIEWER + OptionKind.PREFERENCE
+ },
+ enableHighlightEditor: {
+ value: false,
+ kind: OptionKind.VIEWER + OptionKind.PREFERENCE
+ },
+ enableML: {
+ value: false,
+ kind: OptionKind.VIEWER + OptionKind.PREFERENCE
+ },
+ enablePermissions: {
+ value: false,
+ kind: OptionKind.VIEWER + OptionKind.PREFERENCE
+ },
+ enablePrintAutoRotate: {
+ value: true,
+ kind: OptionKind.VIEWER + OptionKind.PREFERENCE
+ },
+ enableScripting: {
+ value: true,
+ kind: OptionKind.VIEWER + OptionKind.PREFERENCE
+ },
+ enableStampEditor: {
+ value: true,
+ kind: OptionKind.VIEWER + OptionKind.PREFERENCE
+ },
+ externalLinkRel: {
+ value: "noopener noreferrer nofollow",
+ kind: OptionKind.VIEWER
+ },
+ externalLinkTarget: {
+ value: 0,
+ kind: OptionKind.VIEWER + OptionKind.PREFERENCE
+ },
+ highlightEditorColors: {
+ value: "yellow=#FFFF98,green=#53FFBC,blue=#80EBFF,pink=#FFCBE6,red=#FF4F5F",
+ kind: OptionKind.VIEWER + OptionKind.PREFERENCE
+ },
+ historyUpdateUrl: {
+ value: false,
+ kind: OptionKind.VIEWER + OptionKind.PREFERENCE
+ },
+ ignoreDestinationZoom: {
+ value: false,
+ kind: OptionKind.VIEWER + OptionKind.PREFERENCE
+ },
+ imageResourcesPath: {
+ value: "resource://pdf.js/web/images/",
+ kind: OptionKind.VIEWER
+ },
+ maxCanvasPixels: {
+ value: 16777216,
+ kind: OptionKind.VIEWER
+ },
+ forcePageColors: {
+ value: false,
+ kind: OptionKind.VIEWER + OptionKind.PREFERENCE
+ },
+ pageColorsBackground: {
+ value: "Canvas",
+ kind: OptionKind.VIEWER + OptionKind.PREFERENCE
+ },
+ pageColorsForeground: {
+ value: "CanvasText",
+ kind: OptionKind.VIEWER + OptionKind.PREFERENCE
+ },
+ pdfBugEnabled: {
+ value: false,
+ kind: OptionKind.VIEWER + OptionKind.PREFERENCE
+ },
+ printResolution: {
+ value: 150,
+ kind: OptionKind.VIEWER
+ },
+ sidebarViewOnLoad: {
+ value: -1,
+ kind: OptionKind.VIEWER + OptionKind.PREFERENCE
+ },
+ scrollModeOnLoad: {
+ value: -1,
+ kind: OptionKind.VIEWER + OptionKind.PREFERENCE
+ },
+ spreadModeOnLoad: {
+ value: -1,
+ kind: OptionKind.VIEWER + OptionKind.PREFERENCE
+ },
+ textLayerMode: {
+ value: 1,
+ kind: OptionKind.VIEWER + OptionKind.PREFERENCE
+ },
+ viewOnLoad: {
+ value: 0,
+ kind: OptionKind.VIEWER + OptionKind.PREFERENCE
+ },
+ cMapPacked: {
+ value: true,
+ kind: OptionKind.API
+ },
+ cMapUrl: {
+ value: "resource://pdf.js/web/cmaps/",
+ kind: OptionKind.API
+ },
+ disableAutoFetch: {
+ value: false,
+ kind: OptionKind.API + OptionKind.PREFERENCE
+ },
+ disableFontFace: {
+ value: false,
+ kind: OptionKind.API + OptionKind.PREFERENCE
+ },
+ disableRange: {
+ value: false,
+ kind: OptionKind.API + OptionKind.PREFERENCE
+ },
+ disableStream: {
+ value: false,
+ kind: OptionKind.API + OptionKind.PREFERENCE
+ },
+ docBaseUrl: {
+ value: "",
+ kind: OptionKind.API
+ },
+ enableXfa: {
+ value: true,
+ kind: OptionKind.API + OptionKind.PREFERENCE
+ },
+ fontExtraProperties: {
+ value: false,
+ kind: OptionKind.API
+ },
+ isEvalSupported: {
+ value: true,
+ kind: OptionKind.API
+ },
+ isOffscreenCanvasSupported: {
+ value: true,
+ kind: OptionKind.API
+ },
+ maxImageSize: {
+ value: -1,
+ kind: OptionKind.API
+ },
+ pdfBug: {
+ value: false,
+ kind: OptionKind.API
+ },
+ standardFontDataUrl: {
+ value: "resource://pdf.js/web/standard_fonts/",
+ kind: OptionKind.API
+ },
+ verbosity: {
+ value: 1,
+ kind: OptionKind.API
+ },
+ workerPort: {
+ value: null,
+ kind: OptionKind.WORKER
+ },
+ workerSrc: {
+ value: "resource://pdf.js/build/pdf.worker.mjs",
+ kind: OptionKind.WORKER
+ }
+};
+const userOptions = Object.create(null);
+class AppOptions {
+ constructor() {
+ throw new Error("Cannot initialize AppOptions.");
+ }
+ static get(name) {
+ const userOption = userOptions[name];
+ if (userOption !== undefined) {
+ return userOption;
+ }
+ const defaultOption = defaultOptions[name];
+ if (defaultOption !== undefined) {
+ return compatibilityParams[name] ?? defaultOption.value;
+ }
+ return undefined;
+ }
+ static getAll(kind = null) {
+ const options = Object.create(null);
+ for (const name in defaultOptions) {
+ const defaultOption = defaultOptions[name];
+ if (kind) {
+ if (!(kind & defaultOption.kind)) {
+ continue;
+ }
+ }
+ const userOption = userOptions[name];
+ options[name] = userOption !== undefined ? userOption : compatibilityParams[name] ?? defaultOption.value;
+ }
+ return options;
+ }
+ static set(name, value) {
+ userOptions[name] = value;
+ }
+ static setAll(options, init = false) {
+ for (const name in options) {
+ userOptions[name] = options[name];
+ }
+ }
+ static remove(name) {
+ delete userOptions[name];
+ }
+}
+
+;// CONCATENATED MODULE: ./web/pdf_link_service.js
+
+const DEFAULT_LINK_REL = "noopener noreferrer nofollow";
+const LinkTarget = {
+ NONE: 0,
+ SELF: 1,
+ BLANK: 2,
+ PARENT: 3,
+ TOP: 4
+};
+function addLinkAttributes(link, {
+ url,
+ target,
+ rel,
+ enabled = true
+} = {}) {
+ if (!url || typeof url !== "string") {
+ throw new Error('A valid "url" parameter must provided.');
+ }
+ if (enabled) {
+ link.href = link.title = url;
+ } else {
+ link.href = "";
+ link.title = `Disabled: ${url}`;
+ link.onclick = () => false;
+ }
+ let targetStr = "";
+ switch (target) {
+ case LinkTarget.NONE:
+ break;
+ case LinkTarget.SELF:
+ targetStr = "_self";
+ break;
+ case LinkTarget.BLANK:
+ targetStr = "_blank";
+ break;
+ case LinkTarget.PARENT:
+ targetStr = "_parent";
+ break;
+ case LinkTarget.TOP:
+ targetStr = "_top";
+ break;
+ }
+ link.target = targetStr;
+ link.rel = typeof rel === "string" ? rel : DEFAULT_LINK_REL;
+}
+class PDFLinkService {
+ #pagesRefCache = new Map();
+ constructor({
+ eventBus,
+ externalLinkTarget = null,
+ externalLinkRel = null,
+ ignoreDestinationZoom = false
+ } = {}) {
+ this.eventBus = eventBus;
+ this.externalLinkTarget = externalLinkTarget;
+ this.externalLinkRel = externalLinkRel;
+ this.externalLinkEnabled = true;
+ this._ignoreDestinationZoom = ignoreDestinationZoom;
+ this.baseUrl = null;
+ this.pdfDocument = null;
+ this.pdfViewer = null;
+ this.pdfHistory = null;
+ }
+ setDocument(pdfDocument, baseUrl = null) {
+ this.baseUrl = baseUrl;
+ this.pdfDocument = pdfDocument;
+ this.#pagesRefCache.clear();
+ }
+ setViewer(pdfViewer) {
+ this.pdfViewer = pdfViewer;
+ }
+ setHistory(pdfHistory) {
+ this.pdfHistory = pdfHistory;
+ }
+ get pagesCount() {
+ return this.pdfDocument ? this.pdfDocument.numPages : 0;
+ }
+ get page() {
+ return this.pdfViewer.currentPageNumber;
+ }
+ set page(value) {
+ this.pdfViewer.currentPageNumber = value;
+ }
+ get rotation() {
+ return this.pdfViewer.pagesRotation;
+ }
+ set rotation(value) {
+ this.pdfViewer.pagesRotation = value;
+ }
+ get isInPresentationMode() {
+ return this.pdfViewer.isInPresentationMode;
+ }
+ #goToDestinationHelper(rawDest, namedDest = null, explicitDest) {
+ const destRef = explicitDest[0];
+ let pageNumber;
+ if (typeof destRef === "object" && destRef !== null) {
+ pageNumber = this._cachedPageNumber(destRef);
+ if (!pageNumber) {
+ this.pdfDocument.getPageIndex(destRef).then(pageIndex => {
+ this.cachePageRef(pageIndex + 1, destRef);
+ this.#goToDestinationHelper(rawDest, namedDest, explicitDest);
+ }).catch(() => {
+ console.error(`PDFLinkService.#goToDestinationHelper: "${destRef}" is not ` + `a valid page reference, for dest="${rawDest}".`);
+ });
+ return;
+ }
+ } else if (Number.isInteger(destRef)) {
+ pageNumber = destRef + 1;
+ } else {
+ console.error(`PDFLinkService.#goToDestinationHelper: "${destRef}" is not ` + `a valid destination reference, for dest="${rawDest}".`);
+ return;
+ }
+ if (!pageNumber || pageNumber < 1 || pageNumber > this.pagesCount) {
+ console.error(`PDFLinkService.#goToDestinationHelper: "${pageNumber}" is not ` + `a valid page number, for dest="${rawDest}".`);
+ return;
+ }
+ if (this.pdfHistory) {
+ this.pdfHistory.pushCurrentPosition();
+ this.pdfHistory.push({
+ namedDest,
+ explicitDest,
+ pageNumber
+ });
+ }
+ this.pdfViewer.scrollPageIntoView({
+ pageNumber,
+ destArray: explicitDest,
+ ignoreDestinationZoom: this._ignoreDestinationZoom
+ });
+ }
+ async goToDestination(dest) {
+ if (!this.pdfDocument) {
+ return;
+ }
+ let namedDest, explicitDest;
+ if (typeof dest === "string") {
+ namedDest = dest;
+ explicitDest = await this.pdfDocument.getDestination(dest);
+ } else {
+ namedDest = null;
+ explicitDest = await dest;
+ }
+ if (!Array.isArray(explicitDest)) {
+ console.error(`PDFLinkService.goToDestination: "${explicitDest}" is not ` + `a valid destination array, for dest="${dest}".`);
+ return;
+ }
+ this.#goToDestinationHelper(dest, namedDest, explicitDest);
+ }
+ goToPage(val) {
+ if (!this.pdfDocument) {
+ return;
+ }
+ const pageNumber = typeof val === "string" && this.pdfViewer.pageLabelToPageNumber(val) || val | 0;
+ if (!(Number.isInteger(pageNumber) && pageNumber > 0 && pageNumber <= this.pagesCount)) {
+ console.error(`PDFLinkService.goToPage: "${val}" is not a valid page.`);
+ return;
+ }
+ if (this.pdfHistory) {
+ this.pdfHistory.pushCurrentPosition();
+ this.pdfHistory.pushPage(pageNumber);
+ }
+ this.pdfViewer.scrollPageIntoView({
+ pageNumber
+ });
+ }
+ addLinkAttributes(link, url, newWindow = false) {
+ addLinkAttributes(link, {
+ url,
+ target: newWindow ? LinkTarget.BLANK : this.externalLinkTarget,
+ rel: this.externalLinkRel,
+ enabled: this.externalLinkEnabled
+ });
+ }
+ getDestinationHash(dest) {
+ if (typeof dest === "string") {
+ if (dest.length > 0) {
+ return this.getAnchorUrl("#" + escape(dest));
+ }
+ } else if (Array.isArray(dest)) {
+ const str = JSON.stringify(dest);
+ if (str.length > 0) {
+ return this.getAnchorUrl("#" + escape(str));
+ }
+ }
+ return this.getAnchorUrl("");
+ }
+ getAnchorUrl(anchor) {
+ return this.baseUrl ? this.baseUrl + anchor : anchor;
+ }
+ setHash(hash) {
+ if (!this.pdfDocument) {
+ return;
+ }
+ let pageNumber, dest;
+ if (hash.includes("=")) {
+ const params = parseQueryString(hash);
+ if (params.has("search")) {
+ const query = params.get("search").replaceAll('"', ""),
+ phrase = params.get("phrase") === "true";
+ this.eventBus.dispatch("findfromurlhash", {
+ source: this,
+ query: phrase ? query : query.match(/\S+/g)
+ });
+ }
+ if (params.has("page")) {
+ pageNumber = params.get("page") | 0 || 1;
+ }
+ if (params.has("zoom")) {
+ const zoomArgs = params.get("zoom").split(",");
+ const zoomArg = zoomArgs[0];
+ const zoomArgNumber = parseFloat(zoomArg);
+ if (!zoomArg.includes("Fit")) {
+ dest = [null, {
+ name: "XYZ"
+ }, zoomArgs.length > 1 ? zoomArgs[1] | 0 : null, zoomArgs.length > 2 ? zoomArgs[2] | 0 : null, zoomArgNumber ? zoomArgNumber / 100 : zoomArg];
+ } else if (zoomArg === "Fit" || zoomArg === "FitB") {
+ dest = [null, {
+ name: zoomArg
+ }];
+ } else if (zoomArg === "FitH" || zoomArg === "FitBH" || zoomArg === "FitV" || zoomArg === "FitBV") {
+ dest = [null, {
+ name: zoomArg
+ }, zoomArgs.length > 1 ? zoomArgs[1] | 0 : null];
+ } else if (zoomArg === "FitR") {
+ if (zoomArgs.length !== 5) {
+ console.error('PDFLinkService.setHash: Not enough parameters for "FitR".');
+ } else {
+ dest = [null, {
+ name: zoomArg
+ }, zoomArgs[1] | 0, zoomArgs[2] | 0, zoomArgs[3] | 0, zoomArgs[4] | 0];
+ }
+ } else {
+ console.error(`PDFLinkService.setHash: "${zoomArg}" is not a valid zoom value.`);
+ }
+ }
+ if (dest) {
+ this.pdfViewer.scrollPageIntoView({
+ pageNumber: pageNumber || this.page,
+ destArray: dest,
+ allowNegativeOffset: true
+ });
+ } else if (pageNumber) {
+ this.page = pageNumber;
+ }
+ if (params.has("pagemode")) {
+ this.eventBus.dispatch("pagemode", {
+ source: this,
+ mode: params.get("pagemode")
+ });
+ }
+ if (params.has("nameddest")) {
+ this.goToDestination(params.get("nameddest"));
+ }
+ if (!params.has("filename") || !params.has("filedest")) {
+ return;
+ }
+ hash = params.get("filedest");
+ }
+ dest = unescape(hash);
+ try {
+ dest = JSON.parse(dest);
+ if (!Array.isArray(dest)) {
+ dest = dest.toString();
+ }
+ } catch {}
+ if (typeof dest === "string" || PDFLinkService.#isValidExplicitDestination(dest)) {
+ this.goToDestination(dest);
+ return;
+ }
+ console.error(`PDFLinkService.setHash: "${unescape(hash)}" is not a valid destination.`);
+ }
+ executeNamedAction(action) {
+ switch (action) {
+ case "GoBack":
+ this.pdfHistory?.back();
+ break;
+ case "GoForward":
+ this.pdfHistory?.forward();
+ break;
+ case "NextPage":
+ this.pdfViewer.nextPage();
+ break;
+ case "PrevPage":
+ this.pdfViewer.previousPage();
+ break;
+ case "LastPage":
+ this.page = this.pagesCount;
+ break;
+ case "FirstPage":
+ this.page = 1;
+ break;
+ default:
+ break;
+ }
+ this.eventBus.dispatch("namedaction", {
+ source: this,
+ action
+ });
+ }
+ async executeSetOCGState(action) {
+ const pdfDocument = this.pdfDocument;
+ const optionalContentConfig = await this.pdfViewer.optionalContentConfigPromise;
+ if (pdfDocument !== this.pdfDocument) {
+ return;
+ }
+ let operator;
+ for (const elem of action.state) {
+ switch (elem) {
+ case "ON":
+ case "OFF":
+ case "Toggle":
+ operator = elem;
+ continue;
+ }
+ switch (operator) {
+ case "ON":
+ optionalContentConfig.setVisibility(elem, true);
+ break;
+ case "OFF":
+ optionalContentConfig.setVisibility(elem, false);
+ break;
+ case "Toggle":
+ const group = optionalContentConfig.getGroup(elem);
+ if (group) {
+ optionalContentConfig.setVisibility(elem, !group.visible);
+ }
+ break;
+ }
+ }
+ this.pdfViewer.optionalContentConfigPromise = Promise.resolve(optionalContentConfig);
+ }
+ cachePageRef(pageNum, pageRef) {
+ if (!pageRef) {
+ return;
+ }
+ const refStr = pageRef.gen === 0 ? `${pageRef.num}R` : `${pageRef.num}R${pageRef.gen}`;
+ this.#pagesRefCache.set(refStr, pageNum);
+ }
+ _cachedPageNumber(pageRef) {
+ if (!pageRef) {
+ return null;
+ }
+ const refStr = pageRef.gen === 0 ? `${pageRef.num}R` : `${pageRef.num}R${pageRef.gen}`;
+ return this.#pagesRefCache.get(refStr) || null;
+ }
+ static #isValidExplicitDestination(dest) {
+ if (!Array.isArray(dest)) {
+ return false;
+ }
+ const destLength = dest.length;
+ if (destLength < 2) {
+ return false;
+ }
+ const page = dest[0];
+ if (!(typeof page === "object" && Number.isInteger(page.num) && Number.isInteger(page.gen)) && !(Number.isInteger(page) && page >= 0)) {
+ return false;
+ }
+ const zoom = dest[1];
+ if (!(typeof zoom === "object" && typeof zoom.name === "string")) {
+ return false;
+ }
+ let allowNull = true;
+ switch (zoom.name) {
+ case "XYZ":
+ if (destLength !== 5) {
+ return false;
+ }
+ break;
+ case "Fit":
+ case "FitB":
+ return destLength === 2;
+ case "FitH":
+ case "FitBH":
+ case "FitV":
+ case "FitBV":
+ if (destLength !== 3) {
+ return false;
+ }
+ break;
+ case "FitR":
+ if (destLength !== 6) {
+ return false;
+ }
+ allowNull = false;
+ break;
+ default:
+ return false;
+ }
+ for (let i = 2; i < destLength; i++) {
+ const param = dest[i];
+ if (!(typeof param === "number" || allowNull && param === null)) {
+ return false;
+ }
+ }
+ return true;
+ }
+}
+class SimpleLinkService {
+ constructor() {
+ this.externalLinkEnabled = true;
+ }
+ get pagesCount() {
+ return 0;
+ }
+ get page() {
+ return 0;
+ }
+ set page(value) {}
+ get rotation() {
+ return 0;
+ }
+ set rotation(value) {}
+ get isInPresentationMode() {
+ return false;
+ }
+ async goToDestination(dest) {}
+ goToPage(val) {}
+ addLinkAttributes(link, url, newWindow = false) {
+ addLinkAttributes(link, {
+ url,
+ enabled: this.externalLinkEnabled
+ });
+ }
+ getDestinationHash(dest) {
+ return "#";
+ }
+ getAnchorUrl(hash) {
+ return "#";
+ }
+ setHash(hash) {}
+ executeNamedAction(action) {}
+ executeSetOCGState(action) {}
+ cachePageRef(pageNum, pageRef) {}
+}
+
+;// CONCATENATED MODULE: ./web/pdfjs.js
+const {
+ AbortException,
+ AnnotationEditorLayer,
+ AnnotationEditorParamsType,
+ AnnotationEditorType,
+ AnnotationEditorUIManager,
+ AnnotationLayer,
+ AnnotationMode,
+ build,
+ CMapCompressionType,
+ ColorPicker,
+ createValidAbsoluteUrl,
+ DOMSVGFactory,
+ DrawLayer,
+ FeatureTest,
+ fetchData,
+ getDocument,
+ getFilenameFromUrl,
+ getPdfFilenameFromUrl,
+ getXfaPageViewport,
+ GlobalWorkerOptions,
+ ImageKind,
+ InvalidPDFException,
+ isDataScheme,
+ isPdfFile,
+ MissingPDFException,
+ noContextMenu,
+ normalizeUnicode,
+ OPS,
+ Outliner,
+ PasswordResponses,
+ PDFDataRangeTransport,
+ PDFDateString,
+ PDFWorker,
+ PermissionFlag,
+ PixelsPerInch,
+ PromiseCapability,
+ RenderingCancelledException,
+ renderTextLayer,
+ setLayerDimensions,
+ shadow,
+ UnexpectedResponseException,
+ updateTextLayer,
+ Util,
+ VerbosityLevel,
+ version,
+ XfaLayer
+} = globalThis.pdfjsLib;
+
+;// CONCATENATED MODULE: ./web/event_utils.js
+const WaitOnType = {
+ EVENT: "event",
+ TIMEOUT: "timeout"
+};
+function waitOnEventOrTimeout({
+ target,
+ name,
+ delay = 0
+}) {
+ return new Promise(function (resolve, reject) {
+ if (typeof target !== "object" || !(name && typeof name === "string") || !(Number.isInteger(delay) && delay >= 0)) {
+ throw new Error("waitOnEventOrTimeout - invalid parameters.");
+ }
+ function handler(type) {
+ if (target instanceof EventBus) {
+ target._off(name, eventHandler);
+ } else {
+ target.removeEventListener(name, eventHandler);
+ }
+ if (timeout) {
+ clearTimeout(timeout);
+ }
+ resolve(type);
+ }
+ const eventHandler = handler.bind(null, WaitOnType.EVENT);
+ if (target instanceof EventBus) {
+ target._on(name, eventHandler);
+ } else {
+ target.addEventListener(name, eventHandler);
+ }
+ const timeoutHandler = handler.bind(null, WaitOnType.TIMEOUT);
+ const timeout = setTimeout(timeoutHandler, delay);
+ });
+}
+class EventBus {
+ #listeners = Object.create(null);
+ on(eventName, listener, options = null) {
+ this._on(eventName, listener, {
+ external: true,
+ once: options?.once
+ });
+ }
+ off(eventName, listener, options = null) {
+ this._off(eventName, listener, {
+ external: true,
+ once: options?.once
+ });
+ }
+ dispatch(eventName, data) {
+ const eventListeners = this.#listeners[eventName];
+ if (!eventListeners || eventListeners.length === 0) {
+ return;
+ }
+ let externalListeners;
+ for (const {
+ listener,
+ external,
+ once
+ } of eventListeners.slice(0)) {
+ if (once) {
+ this._off(eventName, listener);
+ }
+ if (external) {
+ (externalListeners ||= []).push(listener);
+ continue;
+ }
+ listener(data);
+ }
+ if (externalListeners) {
+ for (const listener of externalListeners) {
+ listener(data);
+ }
+ externalListeners = null;
+ }
+ }
+ _on(eventName, listener, options = null) {
+ const eventListeners = this.#listeners[eventName] ||= [];
+ eventListeners.push({
+ listener,
+ external: options?.external === true,
+ once: options?.once === true
+ });
+ }
+ _off(eventName, listener, options = null) {
+ const eventListeners = this.#listeners[eventName];
+ if (!eventListeners) {
+ return;
+ }
+ for (let i = 0, ii = eventListeners.length; i < ii; i++) {
+ if (eventListeners[i].listener === listener) {
+ eventListeners.splice(i, 1);
+ return;
+ }
+ }
+ }
+}
+class AutomationEventBus extends EventBus {
+ dispatch(eventName, data) {
+ super.dispatch(eventName, data);
+ const detail = Object.create(null);
+ if (data) {
+ for (const key in data) {
+ const value = data[key];
+ if (key === "source") {
+ if (value === window || value === document) {
+ return;
+ }
+ continue;
+ }
+ detail[key] = value;
+ }
+ }
+ const event = new CustomEvent(eventName, {
+ bubbles: true,
+ cancelable: true,
+ detail
+ });
+ document.dispatchEvent(event);
+ }
+}
+
+;// CONCATENATED MODULE: ./web/external_services.js
+class BaseExternalServices {
+ constructor() {
+ if (this.constructor === BaseExternalServices) {
+ throw new Error("Cannot initialize BaseExternalServices.");
+ }
+ }
+ updateFindControlState(data) {}
+ updateFindMatchesCount(data) {}
+ initPassiveLoading(callbacks) {}
+ reportTelemetry(data) {}
+ async createL10n() {
+ throw new Error("Not implemented: createL10n");
+ }
+ createScripting() {
+ throw new Error("Not implemented: createScripting");
+ }
+ updateEditorStates(data) {
+ throw new Error("Not implemented: updateEditorStates");
+ }
+ async getNimbusExperimentData() {}
+}
+
+;// CONCATENATED MODULE: ./web/preferences.js
+
+class BasePreferences {
+ #defaults = Object.freeze({
+ annotationEditorMode: 0,
+ annotationMode: 2,
+ cursorToolOnLoad: 0,
+ defaultZoomDelay: 400,
+ defaultZoomValue: "",
+ disablePageLabels: false,
+ enableHighlightEditor: false,
+ enableML: false,
+ enablePermissions: false,
+ enablePrintAutoRotate: true,
+ enableScripting: true,
+ enableStampEditor: true,
+ externalLinkTarget: 0,
+ highlightEditorColors: "yellow=#FFFF98,green=#53FFBC,blue=#80EBFF,pink=#FFCBE6,red=#FF4F5F",
+ historyUpdateUrl: false,
+ ignoreDestinationZoom: false,
+ forcePageColors: false,
+ pageColorsBackground: "Canvas",
+ pageColorsForeground: "CanvasText",
+ pdfBugEnabled: false,
+ sidebarViewOnLoad: -1,
+ scrollModeOnLoad: -1,
+ spreadModeOnLoad: -1,
+ textLayerMode: 1,
+ viewOnLoad: 0,
+ disableAutoFetch: false,
+ disableFontFace: false,
+ disableRange: false,
+ disableStream: false,
+ enableXfa: true
+ });
+ #prefs = Object.create(null);
+ #initializedPromise = null;
+ constructor() {
+ if (this.constructor === BasePreferences) {
+ throw new Error("Cannot initialize BasePreferences.");
+ }
+ this.#initializedPromise = this._readFromStorage(this.#defaults).then(({
+ browserPrefs,
+ prefs
+ }) => {
+ const BROWSER_PREFS = {
+ canvasMaxAreaInBytes: -1,
+ isInAutomation: false,
+ supportsCaretBrowsingMode: false,
+ supportsDocumentFonts: true,
+ supportsIntegratedFind: false,
+ supportsMouseWheelZoomCtrlKey: true,
+ supportsMouseWheelZoomMetaKey: true,
+ supportsPinchToZoom: true
+ };
+ const options = Object.create(null);
+ for (const [name, defaultVal] of Object.entries(BROWSER_PREFS)) {
+ const prefVal = browserPrefs?.[name];
+ options[name] = typeof prefVal === typeof defaultVal ? prefVal : defaultVal;
+ }
+ for (const [name, defaultVal] of Object.entries(this.#defaults)) {
+ const prefVal = prefs?.[name];
+ options[name] = this.#prefs[name] = typeof prefVal === typeof defaultVal ? prefVal : defaultVal;
+ }
+ AppOptions.setAll(options, true);
+ });
+ }
+ async _writeToStorage(prefObj) {
+ throw new Error("Not implemented: _writeToStorage");
+ }
+ async _readFromStorage(prefObj) {
+ throw new Error("Not implemented: _readFromStorage");
+ }
+ async reset() {
+ throw new Error("Please use `about:config` to change preferences.");
+ }
+ async set(name, value) {
+ throw new Error("Please use `about:config` to change preferences.");
+ }
+ async get(name) {
+ await this.#initializedPromise;
+ const defaultValue = this.#defaults[name];
+ if (defaultValue === undefined) {
+ throw new Error(`Get preference: "${name}" is undefined.`);
+ }
+ return this.#prefs[name] ?? defaultValue;
+ }
+ get initializedPromise() {
+ return this.#initializedPromise;
+ }
+}
+
+;// CONCATENATED MODULE: ./web/l10n.js
+class L10n {
+ #dir;
+ #lang;
+ #l10n;
+ constructor({
+ lang,
+ isRTL
+ }, l10n = null) {
+ this.#lang = L10n.#fixupLangCode(lang);
+ this.#l10n = l10n;
+ this.#dir = isRTL ?? L10n.#isRTL(this.#lang) ? "rtl" : "ltr";
+ }
+ _setL10n(l10n) {
+ this.#l10n = l10n;
+ }
+ getLanguage() {
+ return this.#lang;
+ }
+ getDirection() {
+ return this.#dir;
+ }
+ async get(ids, args = null, fallback) {
+ if (Array.isArray(ids)) {
+ ids = ids.map(id => ({
+ id
+ }));
+ const messages = await this.#l10n.formatMessages(ids);
+ return messages.map(message => message.value);
+ }
+ const messages = await this.#l10n.formatMessages([{
+ id: ids,
+ args
+ }]);
+ return messages?.[0].value || fallback;
+ }
+ async translate(element) {
+ try {
+ this.#l10n.connectRoot(element);
+ await this.#l10n.translateRoots();
+ } catch {}
+ }
+ pause() {
+ this.#l10n.pauseObserving();
+ }
+ resume() {
+ this.#l10n.resumeObserving();
+ }
+ static #fixupLangCode(langCode) {
+ langCode = langCode?.toLowerCase() || "en-us";
+ const PARTIAL_LANG_CODES = {
+ en: "en-us",
+ es: "es-es",
+ fy: "fy-nl",
+ ga: "ga-ie",
+ gu: "gu-in",
+ hi: "hi-in",
+ hy: "hy-am",
+ nb: "nb-no",
+ ne: "ne-np",
+ nn: "nn-no",
+ pa: "pa-in",
+ pt: "pt-pt",
+ sv: "sv-se",
+ zh: "zh-cn"
+ };
+ return PARTIAL_LANG_CODES[langCode] || langCode;
+ }
+ static #isRTL(lang) {
+ const shortCode = lang.split("-", 1)[0];
+ return ["ar", "he", "fa", "ps", "ur"].includes(shortCode);
+ }
+}
+const GenericL10n = null;
+
+;// CONCATENATED MODULE: ./web/firefoxcom.js
+
+
+
+
+
+let viewerApp = {
+ initialized: false
+};
+function initCom(app) {
+ viewerApp = app;
+}
+class FirefoxCom {
+ static requestAsync(action, data) {
+ return new Promise(resolve => {
+ this.request(action, data, resolve);
+ });
+ }
+ static request(action, data, callback = null) {
+ const request = document.createTextNode("");
+ if (callback) {
+ request.addEventListener("pdf.js.response", event => {
+ const response = event.detail.response;
+ event.target.remove();
+ callback(response);
+ }, {
+ once: true
+ });
+ }
+ document.documentElement.append(request);
+ const sender = new CustomEvent("pdf.js.message", {
+ bubbles: true,
+ cancelable: false,
+ detail: {
+ action,
+ data,
+ responseExpected: !!callback
+ }
+ });
+ request.dispatchEvent(sender);
+ }
+}
+class DownloadManager {
+ #openBlobUrls = new WeakMap();
+ downloadUrl(url, filename, options = {}) {
+ FirefoxCom.request("download", {
+ originalUrl: url,
+ filename,
+ options
+ });
+ }
+ downloadData(data, filename, contentType) {
+ const blobUrl = URL.createObjectURL(new Blob([data], {
+ type: contentType
+ }));
+ FirefoxCom.request("download", {
+ blobUrl,
+ originalUrl: blobUrl,
+ filename,
+ isAttachment: true
+ });
+ }
+ openOrDownloadData(data, filename, dest = null) {
+ const isPdfData = isPdfFile(filename);
+ const contentType = isPdfData ? "application/pdf" : "";
+ if (isPdfData) {
+ let blobUrl = this.#openBlobUrls.get(data);
+ if (!blobUrl) {
+ blobUrl = URL.createObjectURL(new Blob([data], {
+ type: contentType
+ }));
+ this.#openBlobUrls.set(data, blobUrl);
+ }
+ let viewerUrl = blobUrl + "#filename=" + encodeURIComponent(filename);
+ if (dest) {
+ viewerUrl += `&filedest=${escape(dest)}`;
+ }
+ try {
+ window.open(viewerUrl);
+ return true;
+ } catch (ex) {
+ console.error(`openOrDownloadData: ${ex}`);
+ URL.revokeObjectURL(blobUrl);
+ this.#openBlobUrls.delete(data);
+ }
+ }
+ this.downloadData(data, filename, contentType);
+ return false;
+ }
+ download(blob, url, filename, options = {}) {
+ const blobUrl = URL.createObjectURL(blob);
+ FirefoxCom.request("download", {
+ blobUrl,
+ originalUrl: url,
+ filename,
+ options
+ });
+ }
+}
+class Preferences extends BasePreferences {
+ async _readFromStorage(prefObj) {
+ return FirefoxCom.requestAsync("getPreferences", prefObj);
+ }
+}
+(function listenFindEvents() {
+ const events = ["find", "findagain", "findhighlightallchange", "findcasesensitivitychange", "findentirewordchange", "findbarclose", "finddiacriticmatchingchange"];
+ const findLen = "find".length;
+ const handleEvent = function ({
+ type,
+ detail
+ }) {
+ if (!viewerApp.initialized) {
+ return;
+ }
+ if (type === "findbarclose") {
+ viewerApp.eventBus.dispatch(type, {
+ source: window
+ });
+ return;
+ }
+ viewerApp.eventBus.dispatch("find", {
+ source: window,
+ type: type.substring(findLen),
+ query: detail.query,
+ caseSensitive: !!detail.caseSensitive,
+ entireWord: !!detail.entireWord,
+ highlightAll: !!detail.highlightAll,
+ findPrevious: !!detail.findPrevious,
+ matchDiacritics: !!detail.matchDiacritics
+ });
+ };
+ for (const event of events) {
+ window.addEventListener(event, handleEvent);
+ }
+})();
+(function listenZoomEvents() {
+ const events = ["zoomin", "zoomout", "zoomreset"];
+ const handleEvent = function ({
+ type,
+ detail
+ }) {
+ if (!viewerApp.initialized) {
+ return;
+ }
+ if (type === "zoomreset" && viewerApp.pdfViewer.currentScaleValue === DEFAULT_SCALE_VALUE) {
+ return;
+ }
+ viewerApp.eventBus.dispatch(type, {
+ source: window
+ });
+ };
+ for (const event of events) {
+ window.addEventListener(event, handleEvent);
+ }
+})();
+(function listenSaveEvent() {
+ const handleEvent = function ({
+ type,
+ detail
+ }) {
+ if (!viewerApp.initialized) {
+ return;
+ }
+ viewerApp.eventBus.dispatch("download", {
+ source: window
+ });
+ };
+ window.addEventListener("save", handleEvent);
+})();
+(function listenEditingEvent() {
+ const handleEvent = function ({
+ detail
+ }) {
+ if (!viewerApp.initialized) {
+ return;
+ }
+ viewerApp.eventBus.dispatch("editingaction", {
+ source: window,
+ name: detail.name
+ });
+ };
+ window.addEventListener("editingaction", handleEvent);
+})();
+{
+ (function listenQueryEvents() {
+ window.addEventListener("pdf.js.query", async ({
+ detail: {
+ queryId
+ }
+ }) => {
+ let result = null;
+ if (viewerApp.initialized && queryId === "canDownloadInsteadOfPrint") {
+ result = false;
+ const {
+ pdfDocument,
+ pdfViewer
+ } = viewerApp;
+ if (pdfDocument) {
+ try {
+ const hasUnchangedAnnotations = pdfDocument.annotationStorage.size === 0;
+ const hasWillPrint = pdfViewer.enableScripting && !!(await pdfDocument.getJSActions())?.WillPrint;
+ const hasUnchangedOptionalContent = (await pdfViewer.optionalContentConfigPromise).hasInitialVisibility;
+ result = hasUnchangedAnnotations && !hasWillPrint && hasUnchangedOptionalContent;
+ } catch {
+ console.warn("Unable to check if the document can be downloaded.");
+ }
+ }
+ }
+ window.dispatchEvent(new CustomEvent("pdf.js.query.answer", {
+ bubbles: true,
+ cancelable: false,
+ detail: {
+ queryId,
+ value: result
+ }
+ }));
+ });
+ })();
+}
+class FirefoxComDataRangeTransport extends PDFDataRangeTransport {
+ requestDataRange(begin, end) {
+ FirefoxCom.request("requestDataRange", {
+ begin,
+ end
+ });
+ }
+ abort() {
+ FirefoxCom.request("abortLoading", null);
+ }
+}
+class FirefoxScripting {
+ static async createSandbox(data) {
+ const success = await FirefoxCom.requestAsync("createSandbox", data);
+ if (!success) {
+ throw new Error("Cannot create sandbox.");
+ }
+ }
+ static async dispatchEventInSandbox(event) {
+ FirefoxCom.request("dispatchEventInSandbox", event);
+ }
+ static async destroySandbox() {
+ FirefoxCom.request("destroySandbox", null);
+ }
+}
+class MLManager {
+ guess(data) {
+ return FirefoxCom.requestAsync("mlGuess", data);
+ }
+}
+class ExternalServices extends BaseExternalServices {
+ updateFindControlState(data) {
+ FirefoxCom.request("updateFindControlState", data);
+ }
+ updateFindMatchesCount(data) {
+ FirefoxCom.request("updateFindMatchesCount", data);
+ }
+ initPassiveLoading(callbacks) {
+ let pdfDataRangeTransport;
+ window.addEventListener("message", function windowMessage(e) {
+ if (e.source !== null) {
+ console.warn("Rejected untrusted message from " + e.origin);
+ return;
+ }
+ const args = e.data;
+ if (typeof args !== "object" || !("pdfjsLoadAction" in args)) {
+ return;
+ }
+ switch (args.pdfjsLoadAction) {
+ case "supportsRangedLoading":
+ if (args.done && !args.data) {
+ callbacks.onError();
+ break;
+ }
+ pdfDataRangeTransport = new FirefoxComDataRangeTransport(args.length, args.data, args.done, args.filename);
+ callbacks.onOpenWithTransport(pdfDataRangeTransport);
+ break;
+ case "range":
+ pdfDataRangeTransport.onDataRange(args.begin, args.chunk);
+ break;
+ case "rangeProgress":
+ pdfDataRangeTransport.onDataProgress(args.loaded);
+ break;
+ case "progressiveRead":
+ pdfDataRangeTransport.onDataProgressiveRead(args.chunk);
+ pdfDataRangeTransport.onDataProgress(args.loaded, args.total);
+ break;
+ case "progressiveDone":
+ pdfDataRangeTransport?.onDataProgressiveDone();
+ break;
+ case "progress":
+ callbacks.onProgress(args.loaded, args.total);
+ break;
+ case "complete":
+ if (!args.data) {
+ callbacks.onError(args.errorCode);
+ break;
+ }
+ callbacks.onOpenWithData(args.data, args.filename);
+ break;
+ }
+ });
+ FirefoxCom.request("initPassiveLoading", null);
+ }
+ reportTelemetry(data) {
+ FirefoxCom.request("reportTelemetry", JSON.stringify(data));
+ }
+ updateEditorStates(data) {
+ FirefoxCom.request("updateEditorStates", data);
+ }
+ async createL10n() {
+ const [localeProperties] = await Promise.all([FirefoxCom.requestAsync("getLocaleProperties", null), document.l10n.ready]);
+ return new L10n(localeProperties, document.l10n);
+ }
+ createScripting() {
+ return FirefoxScripting;
+ }
+ async getNimbusExperimentData() {
+ const nimbusData = await FirefoxCom.requestAsync("getNimbusExperimentData", null);
+ return nimbusData && JSON.parse(nimbusData);
+ }
+}
+
+;// CONCATENATED MODULE: ./web/stubs-geckoview.js
+const AltTextManager = null;
+const AnnotationEditorParams = null;
+const PDFAttachmentViewer = null;
+const PDFCursorTools = null;
+const PDFDocumentProperties = null;
+const PDFFindBar = null;
+const PDFLayerViewer = null;
+const PDFOutlineViewer = null;
+const PDFPresentationMode = null;
+const PDFSidebar = null;
+const PDFThumbnailViewer = null;
+const SecondaryToolbar = null;
+
+;// CONCATENATED MODULE: ./web/caret_browsing.js
+const PRECISION = 1e-1;
+class CaretBrowsingMode {
+ #mainContainer;
+ #toolBarHeight;
+ #viewerContainer;
+ constructor(mainContainer, viewerContainer, toolbarContainer) {
+ this.#mainContainer = mainContainer;
+ this.#viewerContainer = viewerContainer;
+ this.#toolBarHeight = toolbarContainer?.getBoundingClientRect().height ?? 0;
+ }
+ #isOnSameLine(rect1, rect2) {
+ const top1 = rect1.y;
+ const bot1 = rect1.bottom;
+ const mid1 = rect1.y + rect1.height / 2;
+ const top2 = rect2.y;
+ const bot2 = rect2.bottom;
+ const mid2 = rect2.y + rect2.height / 2;
+ return top1 <= mid2 && mid2 <= bot1 || top2 <= mid1 && mid1 <= bot2;
+ }
+ #isUnderOver(rect, x, y, isUp) {
+ const midY = rect.y + rect.height / 2;
+ return (isUp ? y >= midY : y <= midY) && rect.x - PRECISION <= x && x <= rect.right + PRECISION;
+ }
+ #isVisible(rect) {
+ return rect.top >= this.#toolBarHeight && rect.left >= 0 && rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) && rect.right <= (window.innerWidth || document.documentElement.clientWidth);
+ }
+ #getCaretPosition(selection, isUp) {
+ const {
+ focusNode,
+ focusOffset
+ } = selection;
+ const range = document.createRange();
+ range.setStart(focusNode, focusOffset);
+ range.setEnd(focusNode, focusOffset);
+ const rect = range.getBoundingClientRect();
+ return [rect.x, isUp ? rect.top : rect.bottom];
+ }
+ static #caretPositionFromPoint(x, y) {
+ return document.caretPositionFromPoint(x, y);
+ }
+ #setCaretPositionHelper(selection, caretX, select, element, rect) {
+ rect ||= element.getBoundingClientRect();
+ if (caretX <= rect.x + PRECISION) {
+ if (select) {
+ selection.extend(element.firstChild, 0);
+ } else {
+ selection.setPosition(element.firstChild, 0);
+ }
+ return;
+ }
+ if (rect.right - PRECISION <= caretX) {
+ const {
+ lastChild
+ } = element;
+ if (select) {
+ selection.extend(lastChild, lastChild.length);
+ } else {
+ selection.setPosition(lastChild, lastChild.length);
+ }
+ return;
+ }
+ const midY = rect.y + rect.height / 2;
+ let caretPosition = CaretBrowsingMode.#caretPositionFromPoint(caretX, midY);
+ let parentElement = caretPosition.offsetNode?.parentElement;
+ if (parentElement && parentElement !== element) {
+ const elementsAtPoint = document.elementsFromPoint(caretX, midY);
+ const savedVisibilities = [];
+ for (const el of elementsAtPoint) {
+ if (el === element) {
+ break;
+ }
+ const {
+ style
+ } = el;
+ savedVisibilities.push([el, style.visibility]);
+ style.visibility = "hidden";
+ }
+ caretPosition = CaretBrowsingMode.#caretPositionFromPoint(caretX, midY);
+ parentElement = caretPosition.offsetNode?.parentElement;
+ for (const [el, visibility] of savedVisibilities) {
+ el.style.visibility = visibility;
+ }
+ }
+ if (parentElement !== element) {
+ if (select) {
+ selection.extend(element.firstChild, 0);
+ } else {
+ selection.setPosition(element.firstChild, 0);
+ }
+ return;
+ }
+ if (select) {
+ selection.extend(caretPosition.offsetNode, caretPosition.offset);
+ } else {
+ selection.setPosition(caretPosition.offsetNode, caretPosition.offset);
+ }
+ }
+ #setCaretPosition(select, selection, newLineElement, newLineElementRect, caretX) {
+ if (this.#isVisible(newLineElementRect)) {
+ this.#setCaretPositionHelper(selection, caretX, select, newLineElement, newLineElementRect);
+ return;
+ }
+ this.#mainContainer.addEventListener("scrollend", this.#setCaretPositionHelper.bind(this, selection, caretX, select, newLineElement, null), {
+ once: true
+ });
+ newLineElement.scrollIntoView();
+ }
+ #getNodeOnNextPage(textLayer, isUp) {
+ while (true) {
+ const page = textLayer.closest(".page");
+ const pageNumber = parseInt(page.getAttribute("data-page-number"));
+ const nextPage = isUp ? pageNumber - 1 : pageNumber + 1;
+ textLayer = this.#viewerContainer.querySelector(`.page[data-page-number="${nextPage}"] .textLayer`);
+ if (!textLayer) {
+ return null;
+ }
+ const walker = document.createTreeWalker(textLayer, NodeFilter.SHOW_TEXT);
+ const node = isUp ? walker.lastChild() : walker.firstChild();
+ if (node) {
+ return node;
+ }
+ }
+ }
+ moveCaret(isUp, select) {
+ const selection = document.getSelection();
+ if (selection.rangeCount === 0) {
+ return;
+ }
+ const {
+ focusNode
+ } = selection;
+ const focusElement = focusNode.nodeType !== Node.ELEMENT_NODE ? focusNode.parentElement : focusNode;
+ const root = focusElement.closest(".textLayer");
+ if (!root) {
+ return;
+ }
+ const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT);
+ walker.currentNode = focusNode;
+ const focusRect = focusElement.getBoundingClientRect();
+ let newLineElement = null;
+ const nodeIterator = (isUp ? walker.previousSibling : walker.nextSibling).bind(walker);
+ while (nodeIterator()) {
+ const element = walker.currentNode.parentElement;
+ if (!this.#isOnSameLine(focusRect, element.getBoundingClientRect())) {
+ newLineElement = element;
+ break;
+ }
+ }
+ if (!newLineElement) {
+ const node = this.#getNodeOnNextPage(root, isUp);
+ if (!node) {
+ return;
+ }
+ if (select) {
+ const lastNode = (isUp ? walker.firstChild() : walker.lastChild()) || focusNode;
+ selection.extend(lastNode, isUp ? 0 : lastNode.length);
+ const range = document.createRange();
+ range.setStart(node, isUp ? node.length : 0);
+ range.setEnd(node, isUp ? node.length : 0);
+ selection.addRange(range);
+ return;
+ }
+ const [caretX] = this.#getCaretPosition(selection, isUp);
+ const {
+ parentElement
+ } = node;
+ this.#setCaretPosition(select, selection, parentElement, parentElement.getBoundingClientRect(), caretX);
+ return;
+ }
+ const [caretX, caretY] = this.#getCaretPosition(selection, isUp);
+ const newLineElementRect = newLineElement.getBoundingClientRect();
+ if (this.#isUnderOver(newLineElementRect, caretX, caretY, isUp)) {
+ this.#setCaretPosition(select, selection, newLineElement, newLineElementRect, caretX);
+ return;
+ }
+ while (nodeIterator()) {
+ const element = walker.currentNode.parentElement;
+ const elementRect = element.getBoundingClientRect();
+ if (!this.#isOnSameLine(newLineElementRect, elementRect)) {
+ break;
+ }
+ if (this.#isUnderOver(elementRect, caretX, caretY, isUp)) {
+ this.#setCaretPosition(select, selection, element, elementRect, caretX);
+ return;
+ }
+ }
+ this.#setCaretPosition(select, selection, newLineElement, newLineElementRect, caretX);
+ }
+}
+
+;// CONCATENATED MODULE: ./web/overlay_manager.js
+class OverlayManager {
+ #overlays = new WeakMap();
+ #active = null;
+ get active() {
+ return this.#active;
+ }
+ async register(dialog, canForceClose = false) {
+ if (typeof dialog !== "object") {
+ throw new Error("Not enough parameters.");
+ } else if (this.#overlays.has(dialog)) {
+ throw new Error("The overlay is already registered.");
+ }
+ this.#overlays.set(dialog, {
+ canForceClose
+ });
+ dialog.addEventListener("cancel", evt => {
+ this.#active = null;
+ });
+ }
+ async open(dialog) {
+ if (!this.#overlays.has(dialog)) {
+ throw new Error("The overlay does not exist.");
+ } else if (this.#active) {
+ if (this.#active === dialog) {
+ throw new Error("The overlay is already active.");
+ } else if (this.#overlays.get(dialog).canForceClose) {
+ await this.close();
+ } else {
+ throw new Error("Another overlay is currently active.");
+ }
+ }
+ this.#active = dialog;
+ dialog.showModal();
+ }
+ async close(dialog = this.#active) {
+ if (!this.#overlays.has(dialog)) {
+ throw new Error("The overlay does not exist.");
+ } else if (!this.#active) {
+ throw new Error("The overlay is currently not active.");
+ } else if (this.#active !== dialog) {
+ throw new Error("Another overlay is currently active.");
+ }
+ dialog.close();
+ this.#active = null;
+ }
+}
+
+;// CONCATENATED MODULE: ./web/password_prompt.js
+
+class PasswordPrompt {
+ #activeCapability = null;
+ #updateCallback = null;
+ #reason = null;
+ constructor(options, overlayManager, isViewerEmbedded = false) {
+ this.dialog = options.dialog;
+ this.label = options.label;
+ this.input = options.input;
+ this.submitButton = options.submitButton;
+ this.cancelButton = options.cancelButton;
+ this.overlayManager = overlayManager;
+ this._isViewerEmbedded = isViewerEmbedded;
+ this.submitButton.addEventListener("click", this.#verify.bind(this));
+ this.cancelButton.addEventListener("click", this.close.bind(this));
+ this.input.addEventListener("keydown", e => {
+ if (e.keyCode === 13) {
+ this.#verify();
+ }
+ });
+ this.overlayManager.register(this.dialog, true);
+ this.dialog.addEventListener("close", this.#cancel.bind(this));
+ }
+ async open() {
+ if (this.#activeCapability) {
+ await this.#activeCapability.promise;
+ }
+ this.#activeCapability = new PromiseCapability();
+ try {
+ await this.overlayManager.open(this.dialog);
+ } catch (ex) {
+ this.#activeCapability.resolve();
+ throw ex;
+ }
+ const passwordIncorrect = this.#reason === PasswordResponses.INCORRECT_PASSWORD;
+ if (!this._isViewerEmbedded || passwordIncorrect) {
+ this.input.focus();
+ }
+ this.label.setAttribute("data-l10n-id", `pdfjs-password-${passwordIncorrect ? "invalid" : "label"}`);
+ }
+ async close() {
+ if (this.overlayManager.active === this.dialog) {
+ this.overlayManager.close(this.dialog);
+ }
+ }
+ #verify() {
+ const password = this.input.value;
+ if (password?.length > 0) {
+ this.#invokeCallback(password);
+ }
+ }
+ #cancel() {
+ this.#invokeCallback(new Error("PasswordPrompt cancelled."));
+ this.#activeCapability.resolve();
+ }
+ #invokeCallback(password) {
+ if (!this.#updateCallback) {
+ return;
+ }
+ this.close();
+ this.input.value = "";
+ this.#updateCallback(password);
+ this.#updateCallback = null;
+ }
+ async setUpdateCallback(updateCallback, reason) {
+ if (this.#activeCapability) {
+ await this.#activeCapability.promise;
+ }
+ this.#updateCallback = updateCallback;
+ this.#reason = reason;
+ }
+}
+
+;// CONCATENATED MODULE: ./web/pdf_find_utils.js
+const CharacterType = {
+ SPACE: 0,
+ ALPHA_LETTER: 1,
+ PUNCT: 2,
+ HAN_LETTER: 3,
+ KATAKANA_LETTER: 4,
+ HIRAGANA_LETTER: 5,
+ HALFWIDTH_KATAKANA_LETTER: 6,
+ THAI_LETTER: 7
+};
+function isAlphabeticalScript(charCode) {
+ return charCode < 0x2e80;
+}
+function isAscii(charCode) {
+ return (charCode & 0xff80) === 0;
+}
+function isAsciiAlpha(charCode) {
+ return charCode >= 0x61 && charCode <= 0x7a || charCode >= 0x41 && charCode <= 0x5a;
+}
+function isAsciiDigit(charCode) {
+ return charCode >= 0x30 && charCode <= 0x39;
+}
+function isAsciiSpace(charCode) {
+ return charCode === 0x20 || charCode === 0x09 || charCode === 0x0d || charCode === 0x0a;
+}
+function isHan(charCode) {
+ return charCode >= 0x3400 && charCode <= 0x9fff || charCode >= 0xf900 && charCode <= 0xfaff;
+}
+function isKatakana(charCode) {
+ return charCode >= 0x30a0 && charCode <= 0x30ff;
+}
+function isHiragana(charCode) {
+ return charCode >= 0x3040 && charCode <= 0x309f;
+}
+function isHalfwidthKatakana(charCode) {
+ return charCode >= 0xff60 && charCode <= 0xff9f;
+}
+function isThai(charCode) {
+ return (charCode & 0xff80) === 0x0e00;
+}
+function getCharacterType(charCode) {
+ if (isAlphabeticalScript(charCode)) {
+ if (isAscii(charCode)) {
+ if (isAsciiSpace(charCode)) {
+ return CharacterType.SPACE;
+ } else if (isAsciiAlpha(charCode) || isAsciiDigit(charCode) || charCode === 0x5f) {
+ return CharacterType.ALPHA_LETTER;
+ }
+ return CharacterType.PUNCT;
+ } else if (isThai(charCode)) {
+ return CharacterType.THAI_LETTER;
+ } else if (charCode === 0xa0) {
+ return CharacterType.SPACE;
+ }
+ return CharacterType.ALPHA_LETTER;
+ }
+ if (isHan(charCode)) {
+ return CharacterType.HAN_LETTER;
+ } else if (isKatakana(charCode)) {
+ return CharacterType.KATAKANA_LETTER;
+ } else if (isHiragana(charCode)) {
+ return CharacterType.HIRAGANA_LETTER;
+ } else if (isHalfwidthKatakana(charCode)) {
+ return CharacterType.HALFWIDTH_KATAKANA_LETTER;
+ }
+ return CharacterType.ALPHA_LETTER;
+}
+let NormalizeWithNFKC;
+function getNormalizeWithNFKC() {
+ NormalizeWithNFKC ||= ` ¨ª¯²-µ¸-º¼-¾IJ-ijĿ-ŀʼnſDŽ-njDZ-dzʰ-ʸ˘-ËË -ˤʹͺ;΄-΅·Ï-Ï–Ï°-ϲϴ-ϵϹևٵ-ٸक़-य़ড়-à§à§Ÿà¨³à¨¶à©™-ਜ਼ਫ਼ଡ଼-à­à¸³àº³à»œ-à»à¼Œà½ƒà½à½’བྷཛྷཀྵჼᴬ-ᴮᴰ-ᴺᴼ-áµáµ-ᵪᵸᶛ-ᶿẚ-ẛάέήίόύώΆ᾽-á¿á¿‰á¿‹á¿-á¿á¿“á¿›á¿-῟ΰΎ῭-`ΌΏ´-῾ - ‑‗․-… ″-‴‶-‷‼‾â‡-â‰â—âŸâ°-â±â´-â‚Žâ‚-ₜ₨℀-℃℅-ℇ℉-â„“â„•-â„–â„™-â„â„ -™ℤΩℨK-ℭℯ-ℱℳ-ℹ℻-⅀ⅅ-â…‰â…-ⅿ↉∬-∭∯-∰〈-〉①-⓪⨌⩴-⩶⫝̸ⱼ-ⱽⵯ⺟⻳⼀-⿕ 〶〸-〺゛-゜ゟヿㄱ-ㆎ㆒-㆟㈀-㈞㈠-㉇ã‰-㉾㊀-ã¿êšœ-êšê°êŸ²-ꟴꟸ-ꟹꭜ-ꭟꭩ豈-ï¨ï¨ï¨’凞-羽蘒諸逸-都飯-ï©­ï©°-龎ff-stﬓ-ﬗï¬ï¬Ÿ-זּטּ-לּמּנּ-ï­ï­ƒ-ï­„ï­†-ﮱﯓ-ï´½ïµ-ï¶ï¶’-ﷇﷰ-ï·¼ï¸-︙︰-﹄﹇-ï¹’ï¹”-﹦﹨-﹫ﹰ-ﹲﹴﹶ-ﻼï¼-하-ᅦᅧ-ï¿ï¿’-ï¿—ï¿š-ᅵ¢-₩`;
+ return NormalizeWithNFKC;
+}
+
+;// CONCATENATED MODULE: ./web/pdf_find_controller.js
+
+
+
+const FindState = {
+ FOUND: 0,
+ NOT_FOUND: 1,
+ WRAPPED: 2,
+ PENDING: 3
+};
+const FIND_TIMEOUT = 250;
+const MATCH_SCROLL_OFFSET_TOP = -50;
+const MATCH_SCROLL_OFFSET_LEFT = -400;
+const CHARACTERS_TO_NORMALIZE = {
+ "\u2010": "-",
+ "\u2018": "'",
+ "\u2019": "'",
+ "\u201A": "'",
+ "\u201B": "'",
+ "\u201C": '"',
+ "\u201D": '"',
+ "\u201E": '"',
+ "\u201F": '"',
+ "\u00BC": "1/4",
+ "\u00BD": "1/2",
+ "\u00BE": "3/4"
+};
+const DIACRITICS_EXCEPTION = new Set([0x3099, 0x309a, 0x094d, 0x09cd, 0x0a4d, 0x0acd, 0x0b4d, 0x0bcd, 0x0c4d, 0x0ccd, 0x0d3b, 0x0d3c, 0x0d4d, 0x0dca, 0x0e3a, 0x0eba, 0x0f84, 0x1039, 0x103a, 0x1714, 0x1734, 0x17d2, 0x1a60, 0x1b44, 0x1baa, 0x1bab, 0x1bf2, 0x1bf3, 0x2d7f, 0xa806, 0xa82c, 0xa8c4, 0xa953, 0xa9c0, 0xaaf6, 0xabed, 0x0c56, 0x0f71, 0x0f72, 0x0f7a, 0x0f7b, 0x0f7c, 0x0f7d, 0x0f80, 0x0f74]);
+let DIACRITICS_EXCEPTION_STR;
+const DIACRITICS_REG_EXP = /\p{M}+/gu;
+const SPECIAL_CHARS_REG_EXP = /([.*+?^${}()|[\]\\])|(\p{P})|(\s+)|(\p{M})|(\p{L})/gu;
+const NOT_DIACRITIC_FROM_END_REG_EXP = /([^\p{M}])\p{M}*$/u;
+const NOT_DIACRITIC_FROM_START_REG_EXP = /^\p{M}*([^\p{M}])/u;
+const SYLLABLES_REG_EXP = /[\uAC00-\uD7AF\uFA6C\uFACF-\uFAD1\uFAD5-\uFAD7]+/g;
+const SYLLABLES_LENGTHS = new Map();
+const FIRST_CHAR_SYLLABLES_REG_EXP = "[\\u1100-\\u1112\\ud7a4-\\ud7af\\ud84a\\ud84c\\ud850\\ud854\\ud857\\ud85f]";
+const NFKC_CHARS_TO_NORMALIZE = new Map();
+let noSyllablesRegExp = null;
+let withSyllablesRegExp = null;
+function normalize(text) {
+ const syllablePositions = [];
+ let m;
+ while ((m = SYLLABLES_REG_EXP.exec(text)) !== null) {
+ let {
+ index
+ } = m;
+ for (const char of m[0]) {
+ let len = SYLLABLES_LENGTHS.get(char);
+ if (!len) {
+ len = char.normalize("NFD").length;
+ SYLLABLES_LENGTHS.set(char, len);
+ }
+ syllablePositions.push([len, index++]);
+ }
+ }
+ let normalizationRegex;
+ if (syllablePositions.length === 0 && noSyllablesRegExp) {
+ normalizationRegex = noSyllablesRegExp;
+ } else if (syllablePositions.length > 0 && withSyllablesRegExp) {
+ normalizationRegex = withSyllablesRegExp;
+ } else {
+ const replace = Object.keys(CHARACTERS_TO_NORMALIZE).join("");
+ const toNormalizeWithNFKC = getNormalizeWithNFKC();
+ const CJK = "(?:\\p{Ideographic}|[\u3040-\u30FF])";
+ const HKDiacritics = "(?:\u3099|\u309A)";
+ const regexp = `([${replace}])|([${toNormalizeWithNFKC}])|(${HKDiacritics}\\n)|(\\p{M}+(?:-\\n)?)|(\\S-\\n)|(${CJK}\\n)|(\\n)`;
+ if (syllablePositions.length === 0) {
+ normalizationRegex = noSyllablesRegExp = new RegExp(regexp + "|(\\u0000)", "gum");
+ } else {
+ normalizationRegex = withSyllablesRegExp = new RegExp(regexp + `|(${FIRST_CHAR_SYLLABLES_REG_EXP})`, "gum");
+ }
+ }
+ const rawDiacriticsPositions = [];
+ while ((m = DIACRITICS_REG_EXP.exec(text)) !== null) {
+ rawDiacriticsPositions.push([m[0].length, m.index]);
+ }
+ let normalized = text.normalize("NFD");
+ const positions = [[0, 0]];
+ let rawDiacriticsIndex = 0;
+ let syllableIndex = 0;
+ let shift = 0;
+ let shiftOrigin = 0;
+ let eol = 0;
+ let hasDiacritics = false;
+ normalized = normalized.replace(normalizationRegex, (match, p1, p2, p3, p4, p5, p6, p7, p8, i) => {
+ i -= shiftOrigin;
+ if (p1) {
+ const replacement = CHARACTERS_TO_NORMALIZE[p1];
+ const jj = replacement.length;
+ for (let j = 1; j < jj; j++) {
+ positions.push([i - shift + j, shift - j]);
+ }
+ shift -= jj - 1;
+ return replacement;
+ }
+ if (p2) {
+ let replacement = NFKC_CHARS_TO_NORMALIZE.get(p2);
+ if (!replacement) {
+ replacement = p2.normalize("NFKC");
+ NFKC_CHARS_TO_NORMALIZE.set(p2, replacement);
+ }
+ const jj = replacement.length;
+ for (let j = 1; j < jj; j++) {
+ positions.push([i - shift + j, shift - j]);
+ }
+ shift -= jj - 1;
+ return replacement;
+ }
+ if (p3) {
+ hasDiacritics = true;
+ if (i + eol === rawDiacriticsPositions[rawDiacriticsIndex]?.[1]) {
+ ++rawDiacriticsIndex;
+ } else {
+ positions.push([i - 1 - shift + 1, shift - 1]);
+ shift -= 1;
+ shiftOrigin += 1;
+ }
+ positions.push([i - shift + 1, shift]);
+ shiftOrigin += 1;
+ eol += 1;
+ return p3.charAt(0);
+ }
+ if (p4) {
+ const hasTrailingDashEOL = p4.endsWith("\n");
+ const len = hasTrailingDashEOL ? p4.length - 2 : p4.length;
+ hasDiacritics = true;
+ let jj = len;
+ if (i + eol === rawDiacriticsPositions[rawDiacriticsIndex]?.[1]) {
+ jj -= rawDiacriticsPositions[rawDiacriticsIndex][0];
+ ++rawDiacriticsIndex;
+ }
+ for (let j = 1; j <= jj; j++) {
+ positions.push([i - 1 - shift + j, shift - j]);
+ }
+ shift -= jj;
+ shiftOrigin += jj;
+ if (hasTrailingDashEOL) {
+ i += len - 1;
+ positions.push([i - shift + 1, 1 + shift]);
+ shift += 1;
+ shiftOrigin += 1;
+ eol += 1;
+ return p4.slice(0, len);
+ }
+ return p4;
+ }
+ if (p5) {
+ const len = p5.length - 2;
+ positions.push([i - shift + len, 1 + shift]);
+ shift += 1;
+ shiftOrigin += 1;
+ eol += 1;
+ return p5.slice(0, -2);
+ }
+ if (p6) {
+ const len = p6.length - 1;
+ positions.push([i - shift + len, shift]);
+ shiftOrigin += 1;
+ eol += 1;
+ return p6.slice(0, -1);
+ }
+ if (p7) {
+ positions.push([i - shift + 1, shift - 1]);
+ shift -= 1;
+ shiftOrigin += 1;
+ eol += 1;
+ return " ";
+ }
+ if (i + eol === syllablePositions[syllableIndex]?.[1]) {
+ const newCharLen = syllablePositions[syllableIndex][0] - 1;
+ ++syllableIndex;
+ for (let j = 1; j <= newCharLen; j++) {
+ positions.push([i - (shift - j), shift - j]);
+ }
+ shift -= newCharLen;
+ shiftOrigin += newCharLen;
+ }
+ return p8;
+ });
+ positions.push([normalized.length, shift]);
+ return [normalized, positions, hasDiacritics];
+}
+function getOriginalIndex(diffs, pos, len) {
+ if (!diffs) {
+ return [pos, len];
+ }
+ const start = pos;
+ const end = pos + len - 1;
+ let i = binarySearchFirstItem(diffs, x => x[0] >= start);
+ if (diffs[i][0] > start) {
+ --i;
+ }
+ let j = binarySearchFirstItem(diffs, x => x[0] >= end, i);
+ if (diffs[j][0] > end) {
+ --j;
+ }
+ const oldStart = start + diffs[i][1];
+ const oldEnd = end + diffs[j][1];
+ const oldLen = oldEnd + 1 - oldStart;
+ return [oldStart, oldLen];
+}
+class PDFFindController {
+ #state = null;
+ #updateMatchesCountOnProgress = true;
+ #visitedPagesCount = 0;
+ constructor({
+ linkService,
+ eventBus,
+ updateMatchesCountOnProgress = true
+ }) {
+ this._linkService = linkService;
+ this._eventBus = eventBus;
+ this.#updateMatchesCountOnProgress = updateMatchesCountOnProgress;
+ this.onIsPageVisible = null;
+ this.#reset();
+ eventBus._on("find", this.#onFind.bind(this));
+ eventBus._on("findbarclose", this.#onFindBarClose.bind(this));
+ }
+ get highlightMatches() {
+ return this._highlightMatches;
+ }
+ get pageMatches() {
+ return this._pageMatches;
+ }
+ get pageMatchesLength() {
+ return this._pageMatchesLength;
+ }
+ get selected() {
+ return this._selected;
+ }
+ get state() {
+ return this.#state;
+ }
+ setDocument(pdfDocument) {
+ if (this._pdfDocument) {
+ this.#reset();
+ }
+ if (!pdfDocument) {
+ return;
+ }
+ this._pdfDocument = pdfDocument;
+ this._firstPageCapability.resolve();
+ }
+ #onFind(state) {
+ if (!state) {
+ return;
+ }
+ const pdfDocument = this._pdfDocument;
+ const {
+ type
+ } = state;
+ if (this.#state === null || this.#shouldDirtyMatch(state)) {
+ this._dirtyMatch = true;
+ }
+ this.#state = state;
+ if (type !== "highlightallchange") {
+ this.#updateUIState(FindState.PENDING);
+ }
+ this._firstPageCapability.promise.then(() => {
+ if (!this._pdfDocument || pdfDocument && this._pdfDocument !== pdfDocument) {
+ return;
+ }
+ this.#extractText();
+ const findbarClosed = !this._highlightMatches;
+ const pendingTimeout = !!this._findTimeout;
+ if (this._findTimeout) {
+ clearTimeout(this._findTimeout);
+ this._findTimeout = null;
+ }
+ if (!type) {
+ this._findTimeout = setTimeout(() => {
+ this.#nextMatch();
+ this._findTimeout = null;
+ }, FIND_TIMEOUT);
+ } else if (this._dirtyMatch) {
+ this.#nextMatch();
+ } else if (type === "again") {
+ this.#nextMatch();
+ if (findbarClosed && this.#state.highlightAll) {
+ this.#updateAllPages();
+ }
+ } else if (type === "highlightallchange") {
+ if (pendingTimeout) {
+ this.#nextMatch();
+ } else {
+ this._highlightMatches = true;
+ }
+ this.#updateAllPages();
+ } else {
+ this.#nextMatch();
+ }
+ });
+ }
+ scrollMatchIntoView({
+ element = null,
+ selectedLeft = 0,
+ pageIndex = -1,
+ matchIndex = -1
+ }) {
+ if (!this._scrollMatches || !element) {
+ return;
+ } else if (matchIndex === -1 || matchIndex !== this._selected.matchIdx) {
+ return;
+ } else if (pageIndex === -1 || pageIndex !== this._selected.pageIdx) {
+ return;
+ }
+ this._scrollMatches = false;
+ const spot = {
+ top: MATCH_SCROLL_OFFSET_TOP,
+ left: selectedLeft + MATCH_SCROLL_OFFSET_LEFT
+ };
+ scrollIntoView(element, spot, true);
+ }
+ #reset() {
+ this._highlightMatches = false;
+ this._scrollMatches = false;
+ this._pdfDocument = null;
+ this._pageMatches = [];
+ this._pageMatchesLength = [];
+ this.#visitedPagesCount = 0;
+ this.#state = null;
+ this._selected = {
+ pageIdx: -1,
+ matchIdx: -1
+ };
+ this._offset = {
+ pageIdx: null,
+ matchIdx: null,
+ wrapped: false
+ };
+ this._extractTextPromises = [];
+ this._pageContents = [];
+ this._pageDiffs = [];
+ this._hasDiacritics = [];
+ this._matchesCountTotal = 0;
+ this._pagesToSearch = null;
+ this._pendingFindMatches = new Set();
+ this._resumePageIdx = null;
+ this._dirtyMatch = false;
+ clearTimeout(this._findTimeout);
+ this._findTimeout = null;
+ this._firstPageCapability = new PromiseCapability();
+ }
+ get #query() {
+ const {
+ query
+ } = this.#state;
+ if (typeof query === "string") {
+ if (query !== this._rawQuery) {
+ this._rawQuery = query;
+ [this._normalizedQuery] = normalize(query);
+ }
+ return this._normalizedQuery;
+ }
+ return (query || []).filter(q => !!q).map(q => normalize(q)[0]);
+ }
+ #shouldDirtyMatch(state) {
+ const newQuery = state.query,
+ prevQuery = this.#state.query;
+ const newType = typeof newQuery,
+ prevType = typeof prevQuery;
+ if (newType !== prevType) {
+ return true;
+ }
+ if (newType === "string") {
+ if (newQuery !== prevQuery) {
+ return true;
+ }
+ } else if (JSON.stringify(newQuery) !== JSON.stringify(prevQuery)) {
+ return true;
+ }
+ switch (state.type) {
+ case "again":
+ const pageNumber = this._selected.pageIdx + 1;
+ const linkService = this._linkService;
+ return pageNumber >= 1 && pageNumber <= linkService.pagesCount && pageNumber !== linkService.page && !(this.onIsPageVisible?.(pageNumber) ?? true);
+ case "highlightallchange":
+ return false;
+ }
+ return true;
+ }
+ #isEntireWord(content, startIdx, length) {
+ let match = content.slice(0, startIdx).match(NOT_DIACRITIC_FROM_END_REG_EXP);
+ if (match) {
+ const first = content.charCodeAt(startIdx);
+ const limit = match[1].charCodeAt(0);
+ if (getCharacterType(first) === getCharacterType(limit)) {
+ return false;
+ }
+ }
+ match = content.slice(startIdx + length).match(NOT_DIACRITIC_FROM_START_REG_EXP);
+ if (match) {
+ const last = content.charCodeAt(startIdx + length - 1);
+ const limit = match[1].charCodeAt(0);
+ if (getCharacterType(last) === getCharacterType(limit)) {
+ return false;
+ }
+ }
+ return true;
+ }
+ #calculateRegExpMatch(query, entireWord, pageIndex, pageContent) {
+ const matches = this._pageMatches[pageIndex] = [];
+ const matchesLength = this._pageMatchesLength[pageIndex] = [];
+ if (!query) {
+ return;
+ }
+ const diffs = this._pageDiffs[pageIndex];
+ let match;
+ while ((match = query.exec(pageContent)) !== null) {
+ if (entireWord && !this.#isEntireWord(pageContent, match.index, match[0].length)) {
+ continue;
+ }
+ const [matchPos, matchLen] = getOriginalIndex(diffs, match.index, match[0].length);
+ if (matchLen) {
+ matches.push(matchPos);
+ matchesLength.push(matchLen);
+ }
+ }
+ }
+ #convertToRegExpString(query, hasDiacritics) {
+ const {
+ matchDiacritics
+ } = this.#state;
+ let isUnicode = false;
+ query = query.replaceAll(SPECIAL_CHARS_REG_EXP, (match, p1, p2, p3, p4, p5) => {
+ if (p1) {
+ return `[ ]*\\${p1}[ ]*`;
+ }
+ if (p2) {
+ return `[ ]*${p2}[ ]*`;
+ }
+ if (p3) {
+ return "[ ]+";
+ }
+ if (matchDiacritics) {
+ return p4 || p5;
+ }
+ if (p4) {
+ return DIACRITICS_EXCEPTION.has(p4.charCodeAt(0)) ? p4 : "";
+ }
+ if (hasDiacritics) {
+ isUnicode = true;
+ return `${p5}\\p{M}*`;
+ }
+ return p5;
+ });
+ const trailingSpaces = "[ ]*";
+ if (query.endsWith(trailingSpaces)) {
+ query = query.slice(0, query.length - trailingSpaces.length);
+ }
+ if (matchDiacritics) {
+ if (hasDiacritics) {
+ DIACRITICS_EXCEPTION_STR ||= String.fromCharCode(...DIACRITICS_EXCEPTION);
+ isUnicode = true;
+ query = `${query}(?=[${DIACRITICS_EXCEPTION_STR}]|[^\\p{M}]|$)`;
+ }
+ }
+ return [isUnicode, query];
+ }
+ #calculateMatch(pageIndex) {
+ let query = this.#query;
+ if (query.length === 0) {
+ return;
+ }
+ const {
+ caseSensitive,
+ entireWord
+ } = this.#state;
+ const pageContent = this._pageContents[pageIndex];
+ const hasDiacritics = this._hasDiacritics[pageIndex];
+ let isUnicode = false;
+ if (typeof query === "string") {
+ [isUnicode, query] = this.#convertToRegExpString(query, hasDiacritics);
+ } else {
+ query = query.sort().reverse().map(q => {
+ const [isUnicodePart, queryPart] = this.#convertToRegExpString(q, hasDiacritics);
+ isUnicode ||= isUnicodePart;
+ return `(${queryPart})`;
+ }).join("|");
+ }
+ const flags = `g${isUnicode ? "u" : ""}${caseSensitive ? "" : "i"}`;
+ query = query ? new RegExp(query, flags) : null;
+ this.#calculateRegExpMatch(query, entireWord, pageIndex, pageContent);
+ if (this.#state.highlightAll) {
+ this.#updatePage(pageIndex);
+ }
+ if (this._resumePageIdx === pageIndex) {
+ this._resumePageIdx = null;
+ this.#nextPageMatch();
+ }
+ const pageMatchesCount = this._pageMatches[pageIndex].length;
+ this._matchesCountTotal += pageMatchesCount;
+ if (this.#updateMatchesCountOnProgress) {
+ if (pageMatchesCount > 0) {
+ this.#updateUIResultsCount();
+ }
+ } else if (++this.#visitedPagesCount === this._linkService.pagesCount) {
+ this.#updateUIResultsCount();
+ }
+ }
+ #extractText() {
+ if (this._extractTextPromises.length > 0) {
+ return;
+ }
+ let promise = Promise.resolve();
+ const textOptions = {
+ disableNormalization: true
+ };
+ for (let i = 0, ii = this._linkService.pagesCount; i < ii; i++) {
+ const extractTextCapability = new PromiseCapability();
+ this._extractTextPromises[i] = extractTextCapability.promise;
+ promise = promise.then(() => {
+ return this._pdfDocument.getPage(i + 1).then(pdfPage => pdfPage.getTextContent(textOptions)).then(textContent => {
+ const strBuf = [];
+ for (const textItem of textContent.items) {
+ strBuf.push(textItem.str);
+ if (textItem.hasEOL) {
+ strBuf.push("\n");
+ }
+ }
+ [this._pageContents[i], this._pageDiffs[i], this._hasDiacritics[i]] = normalize(strBuf.join(""));
+ extractTextCapability.resolve();
+ }, reason => {
+ console.error(`Unable to get text content for page ${i + 1}`, reason);
+ this._pageContents[i] = "";
+ this._pageDiffs[i] = null;
+ this._hasDiacritics[i] = false;
+ extractTextCapability.resolve();
+ });
+ });
+ }
+ }
+ #updatePage(index) {
+ if (this._scrollMatches && this._selected.pageIdx === index) {
+ this._linkService.page = index + 1;
+ }
+ this._eventBus.dispatch("updatetextlayermatches", {
+ source: this,
+ pageIndex: index
+ });
+ }
+ #updateAllPages() {
+ this._eventBus.dispatch("updatetextlayermatches", {
+ source: this,
+ pageIndex: -1
+ });
+ }
+ #nextMatch() {
+ const previous = this.#state.findPrevious;
+ const currentPageIndex = this._linkService.page - 1;
+ const numPages = this._linkService.pagesCount;
+ this._highlightMatches = true;
+ if (this._dirtyMatch) {
+ this._dirtyMatch = false;
+ this._selected.pageIdx = this._selected.matchIdx = -1;
+ this._offset.pageIdx = currentPageIndex;
+ this._offset.matchIdx = null;
+ this._offset.wrapped = false;
+ this._resumePageIdx = null;
+ this._pageMatches.length = 0;
+ this._pageMatchesLength.length = 0;
+ this.#visitedPagesCount = 0;
+ this._matchesCountTotal = 0;
+ this.#updateAllPages();
+ for (let i = 0; i < numPages; i++) {
+ if (this._pendingFindMatches.has(i)) {
+ continue;
+ }
+ this._pendingFindMatches.add(i);
+ this._extractTextPromises[i].then(() => {
+ this._pendingFindMatches.delete(i);
+ this.#calculateMatch(i);
+ });
+ }
+ }
+ const query = this.#query;
+ if (query.length === 0) {
+ this.#updateUIState(FindState.FOUND);
+ return;
+ }
+ if (this._resumePageIdx) {
+ return;
+ }
+ const offset = this._offset;
+ this._pagesToSearch = numPages;
+ if (offset.matchIdx !== null) {
+ const numPageMatches = this._pageMatches[offset.pageIdx].length;
+ if (!previous && offset.matchIdx + 1 < numPageMatches || previous && offset.matchIdx > 0) {
+ offset.matchIdx = previous ? offset.matchIdx - 1 : offset.matchIdx + 1;
+ this.#updateMatch(true);
+ return;
+ }
+ this.#advanceOffsetPage(previous);
+ }
+ this.#nextPageMatch();
+ }
+ #matchesReady(matches) {
+ const offset = this._offset;
+ const numMatches = matches.length;
+ const previous = this.#state.findPrevious;
+ if (numMatches) {
+ offset.matchIdx = previous ? numMatches - 1 : 0;
+ this.#updateMatch(true);
+ return true;
+ }
+ this.#advanceOffsetPage(previous);
+ if (offset.wrapped) {
+ offset.matchIdx = null;
+ if (this._pagesToSearch < 0) {
+ this.#updateMatch(false);
+ return true;
+ }
+ }
+ return false;
+ }
+ #nextPageMatch() {
+ if (this._resumePageIdx !== null) {
+ console.error("There can only be one pending page.");
+ }
+ let matches = null;
+ do {
+ const pageIdx = this._offset.pageIdx;
+ matches = this._pageMatches[pageIdx];
+ if (!matches) {
+ this._resumePageIdx = pageIdx;
+ break;
+ }
+ } while (!this.#matchesReady(matches));
+ }
+ #advanceOffsetPage(previous) {
+ const offset = this._offset;
+ const numPages = this._linkService.pagesCount;
+ offset.pageIdx = previous ? offset.pageIdx - 1 : offset.pageIdx + 1;
+ offset.matchIdx = null;
+ this._pagesToSearch--;
+ if (offset.pageIdx >= numPages || offset.pageIdx < 0) {
+ offset.pageIdx = previous ? numPages - 1 : 0;
+ offset.wrapped = true;
+ }
+ }
+ #updateMatch(found = false) {
+ let state = FindState.NOT_FOUND;
+ const wrapped = this._offset.wrapped;
+ this._offset.wrapped = false;
+ if (found) {
+ const previousPage = this._selected.pageIdx;
+ this._selected.pageIdx = this._offset.pageIdx;
+ this._selected.matchIdx = this._offset.matchIdx;
+ state = wrapped ? FindState.WRAPPED : FindState.FOUND;
+ if (previousPage !== -1 && previousPage !== this._selected.pageIdx) {
+ this.#updatePage(previousPage);
+ }
+ }
+ this.#updateUIState(state, this.#state.findPrevious);
+ if (this._selected.pageIdx !== -1) {
+ this._scrollMatches = true;
+ this.#updatePage(this._selected.pageIdx);
+ }
+ }
+ #onFindBarClose(evt) {
+ const pdfDocument = this._pdfDocument;
+ this._firstPageCapability.promise.then(() => {
+ if (!this._pdfDocument || pdfDocument && this._pdfDocument !== pdfDocument) {
+ return;
+ }
+ if (this._findTimeout) {
+ clearTimeout(this._findTimeout);
+ this._findTimeout = null;
+ }
+ if (this._resumePageIdx) {
+ this._resumePageIdx = null;
+ this._dirtyMatch = true;
+ }
+ this.#updateUIState(FindState.FOUND);
+ this._highlightMatches = false;
+ this.#updateAllPages();
+ });
+ }
+ #requestMatchesCount() {
+ const {
+ pageIdx,
+ matchIdx
+ } = this._selected;
+ let current = 0,
+ total = this._matchesCountTotal;
+ if (matchIdx !== -1) {
+ for (let i = 0; i < pageIdx; i++) {
+ current += this._pageMatches[i]?.length || 0;
+ }
+ current += matchIdx + 1;
+ }
+ if (current < 1 || current > total) {
+ current = total = 0;
+ }
+ return {
+ current,
+ total
+ };
+ }
+ #updateUIResultsCount() {
+ this._eventBus.dispatch("updatefindmatchescount", {
+ source: this,
+ matchesCount: this.#requestMatchesCount()
+ });
+ }
+ #updateUIState(state, previous = false) {
+ if (!this.#updateMatchesCountOnProgress && (this.#visitedPagesCount !== this._linkService.pagesCount || state === FindState.PENDING)) {
+ return;
+ }
+ this._eventBus.dispatch("updatefindcontrolstate", {
+ source: this,
+ state,
+ previous,
+ matchesCount: this.#requestMatchesCount(),
+ rawQuery: this.#state?.query ?? null
+ });
+ }
+}
+
+;// CONCATENATED MODULE: ./web/pdf_history.js
+
+
+const HASH_CHANGE_TIMEOUT = 1000;
+const POSITION_UPDATED_THRESHOLD = 50;
+const UPDATE_VIEWAREA_TIMEOUT = 1000;
+function getCurrentHash() {
+ return document.location.hash;
+}
+class PDFHistory {
+ constructor({
+ linkService,
+ eventBus
+ }) {
+ this.linkService = linkService;
+ this.eventBus = eventBus;
+ this._initialized = false;
+ this._fingerprint = "";
+ this.reset();
+ this._boundEvents = null;
+ this.eventBus._on("pagesinit", () => {
+ this._isPagesLoaded = false;
+ this.eventBus._on("pagesloaded", evt => {
+ this._isPagesLoaded = !!evt.pagesCount;
+ }, {
+ once: true
+ });
+ });
+ }
+ initialize({
+ fingerprint,
+ resetHistory = false,
+ updateUrl = false
+ }) {
+ if (!fingerprint || typeof fingerprint !== "string") {
+ console.error('PDFHistory.initialize: The "fingerprint" must be a non-empty string.');
+ return;
+ }
+ if (this._initialized) {
+ this.reset();
+ }
+ const reInitialized = this._fingerprint !== "" && this._fingerprint !== fingerprint;
+ this._fingerprint = fingerprint;
+ this._updateUrl = updateUrl === true;
+ this._initialized = true;
+ this._bindEvents();
+ const state = window.history.state;
+ this._popStateInProgress = false;
+ this._blockHashChange = 0;
+ this._currentHash = getCurrentHash();
+ this._numPositionUpdates = 0;
+ this._uid = this._maxUid = 0;
+ this._destination = null;
+ this._position = null;
+ if (!this._isValidState(state, true) || resetHistory) {
+ const {
+ hash,
+ page,
+ rotation
+ } = this._parseCurrentHash(true);
+ if (!hash || reInitialized || resetHistory) {
+ this._pushOrReplaceState(null, true);
+ return;
+ }
+ this._pushOrReplaceState({
+ hash,
+ page,
+ rotation
+ }, true);
+ return;
+ }
+ const destination = state.destination;
+ this._updateInternalState(destination, state.uid, true);
+ if (destination.rotation !== undefined) {
+ this._initialRotation = destination.rotation;
+ }
+ if (destination.dest) {
+ this._initialBookmark = JSON.stringify(destination.dest);
+ this._destination.page = null;
+ } else if (destination.hash) {
+ this._initialBookmark = destination.hash;
+ } else if (destination.page) {
+ this._initialBookmark = `page=${destination.page}`;
+ }
+ }
+ reset() {
+ if (this._initialized) {
+ this._pageHide();
+ this._initialized = false;
+ this._unbindEvents();
+ }
+ if (this._updateViewareaTimeout) {
+ clearTimeout(this._updateViewareaTimeout);
+ this._updateViewareaTimeout = null;
+ }
+ this._initialBookmark = null;
+ this._initialRotation = null;
+ }
+ push({
+ namedDest = null,
+ explicitDest,
+ pageNumber
+ }) {
+ if (!this._initialized) {
+ return;
+ }
+ if (namedDest && typeof namedDest !== "string") {
+ console.error("PDFHistory.push: " + `"${namedDest}" is not a valid namedDest parameter.`);
+ return;
+ } else if (!Array.isArray(explicitDest)) {
+ console.error("PDFHistory.push: " + `"${explicitDest}" is not a valid explicitDest parameter.`);
+ return;
+ } else if (!this._isValidPage(pageNumber)) {
+ if (pageNumber !== null || this._destination) {
+ console.error("PDFHistory.push: " + `"${pageNumber}" is not a valid pageNumber parameter.`);
+ return;
+ }
+ }
+ const hash = namedDest || JSON.stringify(explicitDest);
+ if (!hash) {
+ return;
+ }
+ let forceReplace = false;
+ if (this._destination && (isDestHashesEqual(this._destination.hash, hash) || isDestArraysEqual(this._destination.dest, explicitDest))) {
+ if (this._destination.page) {
+ return;
+ }
+ forceReplace = true;
+ }
+ if (this._popStateInProgress && !forceReplace) {
+ return;
+ }
+ this._pushOrReplaceState({
+ dest: explicitDest,
+ hash,
+ page: pageNumber,
+ rotation: this.linkService.rotation
+ }, forceReplace);
+ if (!this._popStateInProgress) {
+ this._popStateInProgress = true;
+ Promise.resolve().then(() => {
+ this._popStateInProgress = false;
+ });
+ }
+ }
+ pushPage(pageNumber) {
+ if (!this._initialized) {
+ return;
+ }
+ if (!this._isValidPage(pageNumber)) {
+ console.error(`PDFHistory.pushPage: "${pageNumber}" is not a valid page number.`);
+ return;
+ }
+ if (this._destination?.page === pageNumber) {
+ return;
+ }
+ if (this._popStateInProgress) {
+ return;
+ }
+ this._pushOrReplaceState({
+ dest: null,
+ hash: `page=${pageNumber}`,
+ page: pageNumber,
+ rotation: this.linkService.rotation
+ });
+ if (!this._popStateInProgress) {
+ this._popStateInProgress = true;
+ Promise.resolve().then(() => {
+ this._popStateInProgress = false;
+ });
+ }
+ }
+ pushCurrentPosition() {
+ if (!this._initialized || this._popStateInProgress) {
+ return;
+ }
+ this._tryPushCurrentPosition();
+ }
+ back() {
+ if (!this._initialized || this._popStateInProgress) {
+ return;
+ }
+ const state = window.history.state;
+ if (this._isValidState(state) && state.uid > 0) {
+ window.history.back();
+ }
+ }
+ forward() {
+ if (!this._initialized || this._popStateInProgress) {
+ return;
+ }
+ const state = window.history.state;
+ if (this._isValidState(state) && state.uid < this._maxUid) {
+ window.history.forward();
+ }
+ }
+ get popStateInProgress() {
+ return this._initialized && (this._popStateInProgress || this._blockHashChange > 0);
+ }
+ get initialBookmark() {
+ return this._initialized ? this._initialBookmark : null;
+ }
+ get initialRotation() {
+ return this._initialized ? this._initialRotation : null;
+ }
+ _pushOrReplaceState(destination, forceReplace = false) {
+ const shouldReplace = forceReplace || !this._destination;
+ const newState = {
+ fingerprint: this._fingerprint,
+ uid: shouldReplace ? this._uid : this._uid + 1,
+ destination
+ };
+ this._updateInternalState(destination, newState.uid);
+ let newUrl;
+ if (this._updateUrl && destination?.hash) {
+ const baseUrl = document.location.href.split("#", 1)[0];
+ if (!baseUrl.startsWith("file://")) {
+ newUrl = `${baseUrl}#${destination.hash}`;
+ }
+ }
+ if (shouldReplace) {
+ window.history.replaceState(newState, "", newUrl);
+ } else {
+ window.history.pushState(newState, "", newUrl);
+ }
+ }
+ _tryPushCurrentPosition(temporary = false) {
+ if (!this._position) {
+ return;
+ }
+ let position = this._position;
+ if (temporary) {
+ position = Object.assign(Object.create(null), this._position);
+ position.temporary = true;
+ }
+ if (!this._destination) {
+ this._pushOrReplaceState(position);
+ return;
+ }
+ if (this._destination.temporary) {
+ this._pushOrReplaceState(position, true);
+ return;
+ }
+ if (this._destination.hash === position.hash) {
+ return;
+ }
+ if (!this._destination.page && (POSITION_UPDATED_THRESHOLD <= 0 || this._numPositionUpdates <= POSITION_UPDATED_THRESHOLD)) {
+ return;
+ }
+ let forceReplace = false;
+ if (this._destination.page >= position.first && this._destination.page <= position.page) {
+ if (this._destination.dest !== undefined || !this._destination.first) {
+ return;
+ }
+ forceReplace = true;
+ }
+ this._pushOrReplaceState(position, forceReplace);
+ }
+ _isValidPage(val) {
+ return Number.isInteger(val) && val > 0 && val <= this.linkService.pagesCount;
+ }
+ _isValidState(state, checkReload = false) {
+ if (!state) {
+ return false;
+ }
+ if (state.fingerprint !== this._fingerprint) {
+ if (checkReload) {
+ if (typeof state.fingerprint !== "string" || state.fingerprint.length !== this._fingerprint.length) {
+ return false;
+ }
+ const [perfEntry] = performance.getEntriesByType("navigation");
+ if (perfEntry?.type !== "reload") {
+ return false;
+ }
+ } else {
+ return false;
+ }
+ }
+ if (!Number.isInteger(state.uid) || state.uid < 0) {
+ return false;
+ }
+ if (state.destination === null || typeof state.destination !== "object") {
+ return false;
+ }
+ return true;
+ }
+ _updateInternalState(destination, uid, removeTemporary = false) {
+ if (this._updateViewareaTimeout) {
+ clearTimeout(this._updateViewareaTimeout);
+ this._updateViewareaTimeout = null;
+ }
+ if (removeTemporary && destination?.temporary) {
+ delete destination.temporary;
+ }
+ this._destination = destination;
+ this._uid = uid;
+ this._maxUid = Math.max(this._maxUid, uid);
+ this._numPositionUpdates = 0;
+ }
+ _parseCurrentHash(checkNameddest = false) {
+ const hash = unescape(getCurrentHash()).substring(1);
+ const params = parseQueryString(hash);
+ const nameddest = params.get("nameddest") || "";
+ let page = params.get("page") | 0;
+ if (!this._isValidPage(page) || checkNameddest && nameddest.length > 0) {
+ page = null;
+ }
+ return {
+ hash,
+ page,
+ rotation: this.linkService.rotation
+ };
+ }
+ _updateViewarea({
+ location
+ }) {
+ if (this._updateViewareaTimeout) {
+ clearTimeout(this._updateViewareaTimeout);
+ this._updateViewareaTimeout = null;
+ }
+ this._position = {
+ hash: location.pdfOpenParams.substring(1),
+ page: this.linkService.page,
+ first: location.pageNumber,
+ rotation: location.rotation
+ };
+ if (this._popStateInProgress) {
+ return;
+ }
+ if (POSITION_UPDATED_THRESHOLD > 0 && this._isPagesLoaded && this._destination && !this._destination.page) {
+ this._numPositionUpdates++;
+ }
+ if (UPDATE_VIEWAREA_TIMEOUT > 0) {
+ this._updateViewareaTimeout = setTimeout(() => {
+ if (!this._popStateInProgress) {
+ this._tryPushCurrentPosition(true);
+ }
+ this._updateViewareaTimeout = null;
+ }, UPDATE_VIEWAREA_TIMEOUT);
+ }
+ }
+ _popState({
+ state
+ }) {
+ const newHash = getCurrentHash(),
+ hashChanged = this._currentHash !== newHash;
+ this._currentHash = newHash;
+ if (!state) {
+ this._uid++;
+ const {
+ hash,
+ page,
+ rotation
+ } = this._parseCurrentHash();
+ this._pushOrReplaceState({
+ hash,
+ page,
+ rotation
+ }, true);
+ return;
+ }
+ if (!this._isValidState(state)) {
+ return;
+ }
+ this._popStateInProgress = true;
+ if (hashChanged) {
+ this._blockHashChange++;
+ waitOnEventOrTimeout({
+ target: window,
+ name: "hashchange",
+ delay: HASH_CHANGE_TIMEOUT
+ }).then(() => {
+ this._blockHashChange--;
+ });
+ }
+ const destination = state.destination;
+ this._updateInternalState(destination, state.uid, true);
+ if (isValidRotation(destination.rotation)) {
+ this.linkService.rotation = destination.rotation;
+ }
+ if (destination.dest) {
+ this.linkService.goToDestination(destination.dest);
+ } else if (destination.hash) {
+ this.linkService.setHash(destination.hash);
+ } else if (destination.page) {
+ this.linkService.page = destination.page;
+ }
+ Promise.resolve().then(() => {
+ this._popStateInProgress = false;
+ });
+ }
+ _pageHide() {
+ if (!this._destination || this._destination.temporary) {
+ this._tryPushCurrentPosition();
+ }
+ }
+ _bindEvents() {
+ if (this._boundEvents) {
+ return;
+ }
+ this._boundEvents = {
+ updateViewarea: this._updateViewarea.bind(this),
+ popState: this._popState.bind(this),
+ pageHide: this._pageHide.bind(this)
+ };
+ this.eventBus._on("updateviewarea", this._boundEvents.updateViewarea);
+ window.addEventListener("popstate", this._boundEvents.popState);
+ window.addEventListener("pagehide", this._boundEvents.pageHide);
+ }
+ _unbindEvents() {
+ if (!this._boundEvents) {
+ return;
+ }
+ this.eventBus._off("updateviewarea", this._boundEvents.updateViewarea);
+ window.removeEventListener("popstate", this._boundEvents.popState);
+ window.removeEventListener("pagehide", this._boundEvents.pageHide);
+ this._boundEvents = null;
+ }
+}
+function isDestHashesEqual(destHash, pushHash) {
+ if (typeof destHash !== "string" || typeof pushHash !== "string") {
+ return false;
+ }
+ if (destHash === pushHash) {
+ return true;
+ }
+ const nameddest = parseQueryString(destHash).get("nameddest");
+ if (nameddest === pushHash) {
+ return true;
+ }
+ return false;
+}
+function isDestArraysEqual(firstDest, secondDest) {
+ function isEntryEqual(first, second) {
+ if (typeof first !== typeof second) {
+ return false;
+ }
+ if (Array.isArray(first) || Array.isArray(second)) {
+ return false;
+ }
+ if (first !== null && typeof first === "object" && second !== null) {
+ if (Object.keys(first).length !== Object.keys(second).length) {
+ return false;
+ }
+ for (const key in first) {
+ if (!isEntryEqual(first[key], second[key])) {
+ return false;
+ }
+ }
+ return true;
+ }
+ return first === second || Number.isNaN(first) && Number.isNaN(second);
+ }
+ if (!(Array.isArray(firstDest) && Array.isArray(secondDest))) {
+ return false;
+ }
+ if (firstDest.length !== secondDest.length) {
+ return false;
+ }
+ for (let i = 0, ii = firstDest.length; i < ii; i++) {
+ if (!isEntryEqual(firstDest[i], secondDest[i])) {
+ return false;
+ }
+ }
+ return true;
+}
+
+;// CONCATENATED MODULE: ./web/xfa_layer_builder.js
+
+class XfaLayerBuilder {
+ constructor({
+ pdfPage,
+ annotationStorage = null,
+ linkService,
+ xfaHtml = null
+ }) {
+ this.pdfPage = pdfPage;
+ this.annotationStorage = annotationStorage;
+ this.linkService = linkService;
+ this.xfaHtml = xfaHtml;
+ this.div = null;
+ this._cancelled = false;
+ }
+ async render(viewport, intent = "display") {
+ if (intent === "print") {
+ const parameters = {
+ viewport: viewport.clone({
+ dontFlip: true
+ }),
+ div: this.div,
+ xfaHtml: this.xfaHtml,
+ annotationStorage: this.annotationStorage,
+ linkService: this.linkService,
+ intent
+ };
+ this.div = document.createElement("div");
+ parameters.div = this.div;
+ return XfaLayer.render(parameters);
+ }
+ const xfaHtml = await this.pdfPage.getXfa();
+ if (this._cancelled || !xfaHtml) {
+ return {
+ textDivs: []
+ };
+ }
+ const parameters = {
+ viewport: viewport.clone({
+ dontFlip: true
+ }),
+ div: this.div,
+ xfaHtml,
+ annotationStorage: this.annotationStorage,
+ linkService: this.linkService,
+ intent
+ };
+ if (this.div) {
+ return XfaLayer.update(parameters);
+ }
+ this.div = document.createElement("div");
+ parameters.div = this.div;
+ return XfaLayer.render(parameters);
+ }
+ cancel() {
+ this._cancelled = true;
+ }
+ hide() {
+ if (!this.div) {
+ return;
+ }
+ this.div.hidden = true;
+ }
+}
+
+;// CONCATENATED MODULE: ./web/print_utils.js
+
+
+
+function getXfaHtmlForPrinting(printContainer, pdfDocument) {
+ const xfaHtml = pdfDocument.allXfaHtml;
+ const linkService = new SimpleLinkService();
+ const scale = Math.round(PixelsPerInch.PDF_TO_CSS_UNITS * 100) / 100;
+ for (const xfaPage of xfaHtml.children) {
+ const page = document.createElement("div");
+ page.className = "xfaPrintedPage";
+ printContainer.append(page);
+ const builder = new XfaLayerBuilder({
+ pdfPage: null,
+ annotationStorage: pdfDocument.annotationStorage,
+ linkService,
+ xfaHtml: xfaPage
+ });
+ const viewport = getXfaPageViewport(xfaPage, {
+ scale
+ });
+ builder.render(viewport, "print");
+ page.append(builder.div);
+ }
+}
+
+;// CONCATENATED MODULE: ./web/firefox_print_service.js
+
+
+function composePage(pdfDocument, pageNumber, size, printContainer, printResolution, optionalContentConfigPromise, printAnnotationStoragePromise) {
+ const canvas = document.createElement("canvas");
+ const PRINT_UNITS = printResolution / PixelsPerInch.PDF;
+ canvas.width = Math.floor(size.width * PRINT_UNITS);
+ canvas.height = Math.floor(size.height * PRINT_UNITS);
+ const canvasWrapper = document.createElement("div");
+ canvasWrapper.className = "printedPage";
+ canvasWrapper.append(canvas);
+ printContainer.append(canvasWrapper);
+ let currentRenderTask = null;
+ canvas.mozPrintCallback = function (obj) {
+ const ctx = obj.context;
+ ctx.save();
+ ctx.fillStyle = "rgb(255, 255, 255)";
+ ctx.fillRect(0, 0, canvas.width, canvas.height);
+ ctx.restore();
+ let thisRenderTask = null;
+ Promise.all([pdfDocument.getPage(pageNumber), printAnnotationStoragePromise]).then(function ([pdfPage, printAnnotationStorage]) {
+ if (currentRenderTask) {
+ currentRenderTask.cancel();
+ currentRenderTask = null;
+ }
+ const renderContext = {
+ canvasContext: ctx,
+ transform: [PRINT_UNITS, 0, 0, PRINT_UNITS, 0, 0],
+ viewport: pdfPage.getViewport({
+ scale: 1,
+ rotation: size.rotation
+ }),
+ intent: "print",
+ annotationMode: AnnotationMode.ENABLE_STORAGE,
+ optionalContentConfigPromise,
+ printAnnotationStorage
+ };
+ currentRenderTask = thisRenderTask = pdfPage.render(renderContext);
+ return thisRenderTask.promise;
+ }).then(function () {
+ if (currentRenderTask === thisRenderTask) {
+ currentRenderTask = null;
+ }
+ obj.done();
+ }, function (reason) {
+ if (!(reason instanceof RenderingCancelledException)) {
+ console.error(reason);
+ }
+ if (currentRenderTask === thisRenderTask) {
+ currentRenderTask.cancel();
+ currentRenderTask = null;
+ }
+ if ("abort" in obj) {
+ obj.abort();
+ } else {
+ obj.done();
+ }
+ });
+ };
+}
+class FirefoxPrintService {
+ constructor({
+ pdfDocument,
+ pagesOverview,
+ printContainer,
+ printResolution,
+ optionalContentConfigPromise = null,
+ printAnnotationStoragePromise = null
+ }) {
+ this.pdfDocument = pdfDocument;
+ this.pagesOverview = pagesOverview;
+ this.printContainer = printContainer;
+ this._printResolution = printResolution || 150;
+ this._optionalContentConfigPromise = optionalContentConfigPromise || pdfDocument.getOptionalContentConfig();
+ this._printAnnotationStoragePromise = printAnnotationStoragePromise || Promise.resolve();
+ }
+ layout() {
+ const {
+ pdfDocument,
+ pagesOverview,
+ printContainer,
+ _printResolution,
+ _optionalContentConfigPromise,
+ _printAnnotationStoragePromise
+ } = this;
+ const body = document.querySelector("body");
+ body.setAttribute("data-pdfjsprinting", true);
+ const {
+ width,
+ height
+ } = this.pagesOverview[0];
+ const hasEqualPageSizes = this.pagesOverview.every(size => size.width === width && size.height === height);
+ if (!hasEqualPageSizes) {
+ console.warn("Not all pages have the same size. The printed result may be incorrect!");
+ }
+ this.pageStyleSheet = document.createElement("style");
+ this.pageStyleSheet.textContent = `@page { size: ${width}pt ${height}pt;}`;
+ body.append(this.pageStyleSheet);
+ if (pdfDocument.isPureXfa) {
+ getXfaHtmlForPrinting(printContainer, pdfDocument);
+ return;
+ }
+ for (let i = 0, ii = pagesOverview.length; i < ii; ++i) {
+ composePage(pdfDocument, i + 1, pagesOverview[i], printContainer, _printResolution, _optionalContentConfigPromise, _printAnnotationStoragePromise);
+ }
+ }
+ destroy() {
+ this.printContainer.textContent = "";
+ const body = document.querySelector("body");
+ body.removeAttribute("data-pdfjsprinting");
+ if (this.pageStyleSheet) {
+ this.pageStyleSheet.remove();
+ this.pageStyleSheet = null;
+ }
+ }
+}
+class PDFPrintServiceFactory {
+ static get supportsPrinting() {
+ const canvas = document.createElement("canvas");
+ return shadow(this, "supportsPrinting", "mozPrintCallback" in canvas);
+ }
+ static createPrintService(params) {
+ return new FirefoxPrintService(params);
+ }
+}
+
+;// CONCATENATED MODULE: ./web/pdf_rendering_queue.js
+
+
+const CLEANUP_TIMEOUT = 30000;
+class PDFRenderingQueue {
+ constructor() {
+ this.pdfViewer = null;
+ this.pdfThumbnailViewer = null;
+ this.onIdle = null;
+ this.highestPriorityPage = null;
+ this.idleTimeout = null;
+ this.printing = false;
+ this.isThumbnailViewEnabled = false;
+ }
+ setViewer(pdfViewer) {
+ this.pdfViewer = pdfViewer;
+ }
+ setThumbnailViewer(pdfThumbnailViewer) {
+ this.pdfThumbnailViewer = pdfThumbnailViewer;
+ }
+ isHighestPriority(view) {
+ return this.highestPriorityPage === view.renderingId;
+ }
+ renderHighestPriority(currentlyVisiblePages) {
+ if (this.idleTimeout) {
+ clearTimeout(this.idleTimeout);
+ this.idleTimeout = null;
+ }
+ if (this.pdfViewer.forceRendering(currentlyVisiblePages)) {
+ return;
+ }
+ if (this.isThumbnailViewEnabled && this.pdfThumbnailViewer?.forceRendering()) {
+ return;
+ }
+ if (this.printing) {
+ return;
+ }
+ if (this.onIdle) {
+ this.idleTimeout = setTimeout(this.onIdle.bind(this), CLEANUP_TIMEOUT);
+ }
+ }
+ getHighestPriority(visible, views, scrolledDown, preRenderExtra = false) {
+ const visibleViews = visible.views,
+ numVisible = visibleViews.length;
+ if (numVisible === 0) {
+ return null;
+ }
+ for (let i = 0; i < numVisible; i++) {
+ const view = visibleViews[i].view;
+ if (!this.isViewFinished(view)) {
+ return view;
+ }
+ }
+ const firstId = visible.first.id,
+ lastId = visible.last.id;
+ if (lastId - firstId + 1 > numVisible) {
+ const visibleIds = visible.ids;
+ for (let i = 1, ii = lastId - firstId; i < ii; i++) {
+ const holeId = scrolledDown ? firstId + i : lastId - i;
+ if (visibleIds.has(holeId)) {
+ continue;
+ }
+ const holeView = views[holeId - 1];
+ if (!this.isViewFinished(holeView)) {
+ return holeView;
+ }
+ }
+ }
+ let preRenderIndex = scrolledDown ? lastId : firstId - 2;
+ let preRenderView = views[preRenderIndex];
+ if (preRenderView && !this.isViewFinished(preRenderView)) {
+ return preRenderView;
+ }
+ if (preRenderExtra) {
+ preRenderIndex += scrolledDown ? 1 : -1;
+ preRenderView = views[preRenderIndex];
+ if (preRenderView && !this.isViewFinished(preRenderView)) {
+ return preRenderView;
+ }
+ }
+ return null;
+ }
+ isViewFinished(view) {
+ return view.renderingState === RenderingStates.FINISHED;
+ }
+ renderView(view) {
+ switch (view.renderingState) {
+ case RenderingStates.FINISHED:
+ return false;
+ case RenderingStates.PAUSED:
+ this.highestPriorityPage = view.renderingId;
+ view.resume();
+ break;
+ case RenderingStates.RUNNING:
+ this.highestPriorityPage = view.renderingId;
+ break;
+ case RenderingStates.INITIAL:
+ this.highestPriorityPage = view.renderingId;
+ view.draw().finally(() => {
+ this.renderHighestPriority();
+ }).catch(reason => {
+ if (reason instanceof RenderingCancelledException) {
+ return;
+ }
+ console.error(`renderView: "${reason}"`);
+ });
+ break;
+ }
+ return true;
+ }
+}
+
+;// CONCATENATED MODULE: ./web/pdf_scripting_manager.js
+
+
+class PDFScriptingManager {
+ #closeCapability = null;
+ #destroyCapability = null;
+ #docProperties = null;
+ #eventBus = null;
+ #externalServices = null;
+ #pdfDocument = null;
+ #pdfViewer = null;
+ #ready = false;
+ #scripting = null;
+ #willPrintCapability = null;
+ constructor({
+ eventBus,
+ externalServices = null,
+ docProperties = null
+ }) {
+ this.#eventBus = eventBus;
+ this.#externalServices = externalServices;
+ this.#docProperties = docProperties;
+ }
+ setViewer(pdfViewer) {
+ this.#pdfViewer = pdfViewer;
+ }
+ async setDocument(pdfDocument) {
+ if (this.#pdfDocument) {
+ await this.#destroyScripting();
+ }
+ this.#pdfDocument = pdfDocument;
+ if (!pdfDocument) {
+ return;
+ }
+ const [objects, calculationOrder, docActions] = await Promise.all([pdfDocument.getFieldObjects(), pdfDocument.getCalculationOrderIds(), pdfDocument.getJSActions()]);
+ if (!objects && !docActions) {
+ await this.#destroyScripting();
+ return;
+ }
+ if (pdfDocument !== this.#pdfDocument) {
+ return;
+ }
+ try {
+ this.#scripting = this.#initScripting();
+ } catch (error) {
+ console.error(`setDocument: "${error.message}".`);
+ await this.#destroyScripting();
+ return;
+ }
+ this._internalEvents.set("updatefromsandbox", event => {
+ if (event?.source === window) {
+ this.#updateFromSandbox(event.detail);
+ }
+ });
+ this._internalEvents.set("dispatcheventinsandbox", event => {
+ this.#scripting?.dispatchEventInSandbox(event.detail);
+ });
+ this._internalEvents.set("pagechanging", ({
+ pageNumber,
+ previous
+ }) => {
+ if (pageNumber === previous) {
+ return;
+ }
+ this.#dispatchPageClose(previous);
+ this.#dispatchPageOpen(pageNumber);
+ });
+ this._internalEvents.set("pagerendered", ({
+ pageNumber
+ }) => {
+ if (!this._pageOpenPending.has(pageNumber)) {
+ return;
+ }
+ if (pageNumber !== this.#pdfViewer.currentPageNumber) {
+ return;
+ }
+ this.#dispatchPageOpen(pageNumber);
+ });
+ this._internalEvents.set("pagesdestroy", async () => {
+ await this.#dispatchPageClose(this.#pdfViewer.currentPageNumber);
+ await this.#scripting?.dispatchEventInSandbox({
+ id: "doc",
+ name: "WillClose"
+ });
+ this.#closeCapability?.resolve();
+ });
+ for (const [name, listener] of this._internalEvents) {
+ this.#eventBus._on(name, listener);
+ }
+ try {
+ const docProperties = await this.#docProperties(pdfDocument);
+ if (pdfDocument !== this.#pdfDocument) {
+ return;
+ }
+ await this.#scripting.createSandbox({
+ objects,
+ calculationOrder,
+ appInfo: {
+ platform: navigator.platform,
+ language: navigator.language
+ },
+ docInfo: {
+ ...docProperties,
+ actions: docActions
+ }
+ });
+ this.#eventBus.dispatch("sandboxcreated", {
+ source: this
+ });
+ } catch (error) {
+ console.error(`setDocument: "${error.message}".`);
+ await this.#destroyScripting();
+ return;
+ }
+ await this.#scripting?.dispatchEventInSandbox({
+ id: "doc",
+ name: "Open"
+ });
+ await this.#dispatchPageOpen(this.#pdfViewer.currentPageNumber, true);
+ Promise.resolve().then(() => {
+ if (pdfDocument === this.#pdfDocument) {
+ this.#ready = true;
+ }
+ });
+ }
+ async dispatchWillSave() {
+ return this.#scripting?.dispatchEventInSandbox({
+ id: "doc",
+ name: "WillSave"
+ });
+ }
+ async dispatchDidSave() {
+ return this.#scripting?.dispatchEventInSandbox({
+ id: "doc",
+ name: "DidSave"
+ });
+ }
+ async dispatchWillPrint() {
+ if (!this.#scripting) {
+ return;
+ }
+ await this.#willPrintCapability?.promise;
+ this.#willPrintCapability = new PromiseCapability();
+ try {
+ await this.#scripting.dispatchEventInSandbox({
+ id: "doc",
+ name: "WillPrint"
+ });
+ } catch (ex) {
+ this.#willPrintCapability.resolve();
+ this.#willPrintCapability = null;
+ throw ex;
+ }
+ await this.#willPrintCapability.promise;
+ }
+ async dispatchDidPrint() {
+ return this.#scripting?.dispatchEventInSandbox({
+ id: "doc",
+ name: "DidPrint"
+ });
+ }
+ get destroyPromise() {
+ return this.#destroyCapability?.promise || null;
+ }
+ get ready() {
+ return this.#ready;
+ }
+ get _internalEvents() {
+ return shadow(this, "_internalEvents", new Map());
+ }
+ get _pageOpenPending() {
+ return shadow(this, "_pageOpenPending", new Set());
+ }
+ get _visitedPages() {
+ return shadow(this, "_visitedPages", new Map());
+ }
+ async #updateFromSandbox(detail) {
+ const pdfViewer = this.#pdfViewer;
+ const isInPresentationMode = pdfViewer.isInPresentationMode || pdfViewer.isChangingPresentationMode;
+ const {
+ id,
+ siblings,
+ command,
+ value
+ } = detail;
+ if (!id) {
+ switch (command) {
+ case "clear":
+ console.clear();
+ break;
+ case "error":
+ console.error(value);
+ break;
+ case "layout":
+ if (!isInPresentationMode) {
+ const modes = apiPageLayoutToViewerModes(value);
+ pdfViewer.spreadMode = modes.spreadMode;
+ }
+ break;
+ case "page-num":
+ pdfViewer.currentPageNumber = value + 1;
+ break;
+ case "print":
+ await pdfViewer.pagesPromise;
+ this.#eventBus.dispatch("print", {
+ source: this
+ });
+ break;
+ case "println":
+ console.log(value);
+ break;
+ case "zoom":
+ if (!isInPresentationMode) {
+ pdfViewer.currentScaleValue = value;
+ }
+ break;
+ case "SaveAs":
+ this.#eventBus.dispatch("download", {
+ source: this
+ });
+ break;
+ case "FirstPage":
+ pdfViewer.currentPageNumber = 1;
+ break;
+ case "LastPage":
+ pdfViewer.currentPageNumber = pdfViewer.pagesCount;
+ break;
+ case "NextPage":
+ pdfViewer.nextPage();
+ break;
+ case "PrevPage":
+ pdfViewer.previousPage();
+ break;
+ case "ZoomViewIn":
+ if (!isInPresentationMode) {
+ pdfViewer.increaseScale();
+ }
+ break;
+ case "ZoomViewOut":
+ if (!isInPresentationMode) {
+ pdfViewer.decreaseScale();
+ }
+ break;
+ case "WillPrintFinished":
+ this.#willPrintCapability?.resolve();
+ this.#willPrintCapability = null;
+ break;
+ }
+ return;
+ }
+ if (isInPresentationMode && detail.focus) {
+ return;
+ }
+ delete detail.id;
+ delete detail.siblings;
+ const ids = siblings ? [id, ...siblings] : [id];
+ for (const elementId of ids) {
+ const element = document.querySelector(`[data-element-id="${elementId}"]`);
+ if (element) {
+ element.dispatchEvent(new CustomEvent("updatefromsandbox", {
+ detail
+ }));
+ } else {
+ this.#pdfDocument?.annotationStorage.setValue(elementId, detail);
+ }
+ }
+ }
+ async #dispatchPageOpen(pageNumber, initialize = false) {
+ const pdfDocument = this.#pdfDocument,
+ visitedPages = this._visitedPages;
+ if (initialize) {
+ this.#closeCapability = new PromiseCapability();
+ }
+ if (!this.#closeCapability) {
+ return;
+ }
+ const pageView = this.#pdfViewer.getPageView(pageNumber - 1);
+ if (pageView?.renderingState !== RenderingStates.FINISHED) {
+ this._pageOpenPending.add(pageNumber);
+ return;
+ }
+ this._pageOpenPending.delete(pageNumber);
+ const actionsPromise = (async () => {
+ const actions = await (!visitedPages.has(pageNumber) ? pageView.pdfPage?.getJSActions() : null);
+ if (pdfDocument !== this.#pdfDocument) {
+ return;
+ }
+ await this.#scripting?.dispatchEventInSandbox({
+ id: "page",
+ name: "PageOpen",
+ pageNumber,
+ actions
+ });
+ })();
+ visitedPages.set(pageNumber, actionsPromise);
+ }
+ async #dispatchPageClose(pageNumber) {
+ const pdfDocument = this.#pdfDocument,
+ visitedPages = this._visitedPages;
+ if (!this.#closeCapability) {
+ return;
+ }
+ if (this._pageOpenPending.has(pageNumber)) {
+ return;
+ }
+ const actionsPromise = visitedPages.get(pageNumber);
+ if (!actionsPromise) {
+ return;
+ }
+ visitedPages.set(pageNumber, null);
+ await actionsPromise;
+ if (pdfDocument !== this.#pdfDocument) {
+ return;
+ }
+ await this.#scripting?.dispatchEventInSandbox({
+ id: "page",
+ name: "PageClose",
+ pageNumber
+ });
+ }
+ #initScripting() {
+ this.#destroyCapability = new PromiseCapability();
+ if (this.#scripting) {
+ throw new Error("#initScripting: Scripting already exists.");
+ }
+ return this.#externalServices.createScripting();
+ }
+ async #destroyScripting() {
+ if (!this.#scripting) {
+ this.#pdfDocument = null;
+ this.#destroyCapability?.resolve();
+ return;
+ }
+ if (this.#closeCapability) {
+ await Promise.race([this.#closeCapability.promise, new Promise(resolve => {
+ setTimeout(resolve, 1000);
+ })]).catch(() => {});
+ this.#closeCapability = null;
+ }
+ this.#pdfDocument = null;
+ try {
+ await this.#scripting.destroySandbox();
+ } catch {}
+ this.#willPrintCapability?.reject(new Error("Scripting destroyed."));
+ this.#willPrintCapability = null;
+ for (const [name, listener] of this._internalEvents) {
+ this.#eventBus._off(name, listener);
+ }
+ this._internalEvents.clear();
+ this._pageOpenPending.clear();
+ this._visitedPages.clear();
+ this.#scripting = null;
+ this.#ready = false;
+ this.#destroyCapability?.resolve();
+ }
+}
+
+;// CONCATENATED MODULE: ./web/annotation_editor_layer_builder.js
+
+
+class AnnotationEditorLayerBuilder {
+ #annotationLayer = null;
+ #drawLayer = null;
+ #textLayer = null;
+ #uiManager;
+ constructor(options) {
+ this.pageDiv = options.pageDiv;
+ this.pdfPage = options.pdfPage;
+ this.accessibilityManager = options.accessibilityManager;
+ this.l10n = options.l10n;
+ this.annotationEditorLayer = null;
+ this.div = null;
+ this._cancelled = false;
+ this.#uiManager = options.uiManager;
+ this.#annotationLayer = options.annotationLayer || null;
+ this.#textLayer = options.textLayer || null;
+ this.#drawLayer = options.drawLayer || null;
+ }
+ async render(viewport, intent = "display") {
+ if (intent !== "display") {
+ return;
+ }
+ if (this._cancelled) {
+ return;
+ }
+ const clonedViewport = viewport.clone({
+ dontFlip: true
+ });
+ if (this.div) {
+ this.annotationEditorLayer.update({
+ viewport: clonedViewport
+ });
+ this.show();
+ return;
+ }
+ const div = this.div = document.createElement("div");
+ div.className = "annotationEditorLayer";
+ div.tabIndex = 0;
+ div.hidden = true;
+ div.dir = this.#uiManager.direction;
+ this.pageDiv.append(div);
+ this.annotationEditorLayer = new AnnotationEditorLayer({
+ uiManager: this.#uiManager,
+ div,
+ accessibilityManager: this.accessibilityManager,
+ pageIndex: this.pdfPage.pageNumber - 1,
+ l10n: this.l10n,
+ viewport: clonedViewport,
+ annotationLayer: this.#annotationLayer,
+ textLayer: this.#textLayer,
+ drawLayer: this.#drawLayer
+ });
+ const parameters = {
+ viewport: clonedViewport,
+ div,
+ annotations: null,
+ intent
+ };
+ this.annotationEditorLayer.render(parameters);
+ this.show();
+ }
+ cancel() {
+ this._cancelled = true;
+ if (!this.div) {
+ return;
+ }
+ this.pageDiv = null;
+ this.annotationEditorLayer.destroy();
+ this.div.remove();
+ }
+ hide() {
+ if (!this.div) {
+ return;
+ }
+ this.div.hidden = true;
+ }
+ show() {
+ if (!this.div || this.annotationEditorLayer.isEmpty) {
+ return;
+ }
+ this.div.hidden = false;
+ }
+}
+
+;// CONCATENATED MODULE: ./web/annotation_layer_builder.js
+
+
+class AnnotationLayerBuilder {
+ #onPresentationModeChanged = null;
+ constructor({
+ pageDiv,
+ pdfPage,
+ linkService,
+ downloadManager,
+ annotationStorage = null,
+ imageResourcesPath = "",
+ renderForms = true,
+ enableScripting = false,
+ hasJSActionsPromise = null,
+ fieldObjectsPromise = null,
+ annotationCanvasMap = null,
+ accessibilityManager = null
+ }) {
+ this.pageDiv = pageDiv;
+ this.pdfPage = pdfPage;
+ this.linkService = linkService;
+ this.downloadManager = downloadManager;
+ this.imageResourcesPath = imageResourcesPath;
+ this.renderForms = renderForms;
+ this.annotationStorage = annotationStorage;
+ this.enableScripting = enableScripting;
+ this._hasJSActionsPromise = hasJSActionsPromise || Promise.resolve(false);
+ this._fieldObjectsPromise = fieldObjectsPromise || Promise.resolve(null);
+ this._annotationCanvasMap = annotationCanvasMap;
+ this._accessibilityManager = accessibilityManager;
+ this.annotationLayer = null;
+ this.div = null;
+ this._cancelled = false;
+ this._eventBus = linkService.eventBus;
+ }
+ async render(viewport, intent = "display") {
+ if (this.div) {
+ if (this._cancelled || !this.annotationLayer) {
+ return;
+ }
+ this.annotationLayer.update({
+ viewport: viewport.clone({
+ dontFlip: true
+ })
+ });
+ return;
+ }
+ const [annotations, hasJSActions, fieldObjects] = await Promise.all([this.pdfPage.getAnnotations({
+ intent
+ }), this._hasJSActionsPromise, this._fieldObjectsPromise]);
+ if (this._cancelled) {
+ return;
+ }
+ const div = this.div = document.createElement("div");
+ div.className = "annotationLayer";
+ this.pageDiv.append(div);
+ if (annotations.length === 0) {
+ this.hide();
+ return;
+ }
+ this.annotationLayer = new AnnotationLayer({
+ div,
+ accessibilityManager: this._accessibilityManager,
+ annotationCanvasMap: this._annotationCanvasMap,
+ page: this.pdfPage,
+ viewport: viewport.clone({
+ dontFlip: true
+ })
+ });
+ await this.annotationLayer.render({
+ annotations,
+ imageResourcesPath: this.imageResourcesPath,
+ renderForms: this.renderForms,
+ linkService: this.linkService,
+ downloadManager: this.downloadManager,
+ annotationStorage: this.annotationStorage,
+ enableScripting: this.enableScripting,
+ hasJSActions,
+ fieldObjects
+ });
+ if (this.linkService.isInPresentationMode) {
+ this.#updatePresentationModeState(PresentationModeState.FULLSCREEN);
+ }
+ if (!this.#onPresentationModeChanged) {
+ this.#onPresentationModeChanged = evt => {
+ this.#updatePresentationModeState(evt.state);
+ };
+ this._eventBus?._on("presentationmodechanged", this.#onPresentationModeChanged);
+ }
+ }
+ cancel() {
+ this._cancelled = true;
+ if (this.#onPresentationModeChanged) {
+ this._eventBus?._off("presentationmodechanged", this.#onPresentationModeChanged);
+ this.#onPresentationModeChanged = null;
+ }
+ }
+ hide() {
+ if (!this.div) {
+ return;
+ }
+ this.div.hidden = true;
+ }
+ #updatePresentationModeState(state) {
+ if (!this.div) {
+ return;
+ }
+ let disableFormElements = false;
+ switch (state) {
+ case PresentationModeState.FULLSCREEN:
+ disableFormElements = true;
+ break;
+ case PresentationModeState.NORMAL:
+ break;
+ default:
+ return;
+ }
+ for (const section of this.div.childNodes) {
+ if (section.hasAttribute("data-internal-link")) {
+ continue;
+ }
+ section.inert = disableFormElements;
+ }
+ }
+}
+
+;// CONCATENATED MODULE: ./web/draw_layer_builder.js
+
+class DrawLayerBuilder {
+ #drawLayer = null;
+ constructor(options) {
+ this.pageIndex = options.pageIndex;
+ }
+ async render(intent = "display") {
+ if (intent !== "display" || this.#drawLayer || this._cancelled) {
+ return;
+ }
+ this.#drawLayer = new DrawLayer({
+ pageIndex: this.pageIndex
+ });
+ }
+ cancel() {
+ this._cancelled = true;
+ if (!this.#drawLayer) {
+ return;
+ }
+ this.#drawLayer.destroy();
+ this.#drawLayer = null;
+ }
+ setParent(parent) {
+ this.#drawLayer?.setParent(parent);
+ }
+ getDrawLayer() {
+ return this.#drawLayer;
+ }
+}
+
+;// CONCATENATED MODULE: ./web/struct_tree_layer_builder.js
+
+const PDF_ROLE_TO_HTML_ROLE = {
+ Document: null,
+ DocumentFragment: null,
+ Part: "group",
+ Sect: "group",
+ Div: "group",
+ Aside: "note",
+ NonStruct: "none",
+ P: null,
+ H: "heading",
+ Title: null,
+ FENote: "note",
+ Sub: "group",
+ Lbl: null,
+ Span: null,
+ Em: null,
+ Strong: null,
+ Link: "link",
+ Annot: "note",
+ Form: "form",
+ Ruby: null,
+ RB: null,
+ RT: null,
+ RP: null,
+ Warichu: null,
+ WT: null,
+ WP: null,
+ L: "list",
+ LI: "listitem",
+ LBody: null,
+ Table: "table",
+ TR: "row",
+ TH: "columnheader",
+ TD: "cell",
+ THead: "columnheader",
+ TBody: null,
+ TFoot: null,
+ Caption: null,
+ Figure: "figure",
+ Formula: null,
+ Artifact: null
+};
+const HEADING_PATTERN = /^H(\d+)$/;
+class StructTreeLayerBuilder {
+ #treeDom = undefined;
+ get renderingDone() {
+ return this.#treeDom !== undefined;
+ }
+ render(structTree) {
+ if (this.#treeDom !== undefined) {
+ return this.#treeDom;
+ }
+ const treeDom = this.#walk(structTree);
+ treeDom?.classList.add("structTree");
+ return this.#treeDom = treeDom;
+ }
+ hide() {
+ if (this.#treeDom && !this.#treeDom.hidden) {
+ this.#treeDom.hidden = true;
+ }
+ }
+ show() {
+ if (this.#treeDom?.hidden) {
+ this.#treeDom.hidden = false;
+ }
+ }
+ #setAttributes(structElement, htmlElement) {
+ const {
+ alt,
+ id,
+ lang
+ } = structElement;
+ if (alt !== undefined) {
+ htmlElement.setAttribute("aria-label", removeNullCharacters(alt));
+ }
+ if (id !== undefined) {
+ htmlElement.setAttribute("aria-owns", id);
+ }
+ if (lang !== undefined) {
+ htmlElement.setAttribute("lang", removeNullCharacters(lang, true));
+ }
+ }
+ #walk(node) {
+ if (!node) {
+ return null;
+ }
+ const element = document.createElement("span");
+ if ("role" in node) {
+ const {
+ role
+ } = node;
+ const match = role.match(HEADING_PATTERN);
+ if (match) {
+ element.setAttribute("role", "heading");
+ element.setAttribute("aria-level", match[1]);
+ } else if (PDF_ROLE_TO_HTML_ROLE[role]) {
+ element.setAttribute("role", PDF_ROLE_TO_HTML_ROLE[role]);
+ }
+ }
+ this.#setAttributes(node, element);
+ if (node.children) {
+ if (node.children.length === 1 && "id" in node.children[0]) {
+ this.#setAttributes(node.children[0], element);
+ } else {
+ for (const kid of node.children) {
+ element.append(this.#walk(kid));
+ }
+ }
+ }
+ return element;
+ }
+}
+
+;// CONCATENATED MODULE: ./web/text_accessibility.js
+
+class TextAccessibilityManager {
+ #enabled = false;
+ #textChildren = null;
+ #textNodes = new Map();
+ #waitingElements = new Map();
+ setTextMapping(textDivs) {
+ this.#textChildren = textDivs;
+ }
+ static #compareElementPositions(e1, e2) {
+ const rect1 = e1.getBoundingClientRect();
+ const rect2 = e2.getBoundingClientRect();
+ if (rect1.width === 0 && rect1.height === 0) {
+ return +1;
+ }
+ if (rect2.width === 0 && rect2.height === 0) {
+ return -1;
+ }
+ const top1 = rect1.y;
+ const bot1 = rect1.y + rect1.height;
+ const mid1 = rect1.y + rect1.height / 2;
+ const top2 = rect2.y;
+ const bot2 = rect2.y + rect2.height;
+ const mid2 = rect2.y + rect2.height / 2;
+ if (mid1 <= top2 && mid2 >= bot1) {
+ return -1;
+ }
+ if (mid2 <= top1 && mid1 >= bot2) {
+ return +1;
+ }
+ const centerX1 = rect1.x + rect1.width / 2;
+ const centerX2 = rect2.x + rect2.width / 2;
+ return centerX1 - centerX2;
+ }
+ enable() {
+ if (this.#enabled) {
+ throw new Error("TextAccessibilityManager is already enabled.");
+ }
+ if (!this.#textChildren) {
+ throw new Error("Text divs and strings have not been set.");
+ }
+ this.#enabled = true;
+ this.#textChildren = this.#textChildren.slice();
+ this.#textChildren.sort(TextAccessibilityManager.#compareElementPositions);
+ if (this.#textNodes.size > 0) {
+ const textChildren = this.#textChildren;
+ for (const [id, nodeIndex] of this.#textNodes) {
+ const element = document.getElementById(id);
+ if (!element) {
+ this.#textNodes.delete(id);
+ continue;
+ }
+ this.#addIdToAriaOwns(id, textChildren[nodeIndex]);
+ }
+ }
+ for (const [element, isRemovable] of this.#waitingElements) {
+ this.addPointerInTextLayer(element, isRemovable);
+ }
+ this.#waitingElements.clear();
+ }
+ disable() {
+ if (!this.#enabled) {
+ return;
+ }
+ this.#waitingElements.clear();
+ this.#textChildren = null;
+ this.#enabled = false;
+ }
+ removePointerInTextLayer(element) {
+ if (!this.#enabled) {
+ this.#waitingElements.delete(element);
+ return;
+ }
+ const children = this.#textChildren;
+ if (!children || children.length === 0) {
+ return;
+ }
+ const {
+ id
+ } = element;
+ const nodeIndex = this.#textNodes.get(id);
+ if (nodeIndex === undefined) {
+ return;
+ }
+ const node = children[nodeIndex];
+ this.#textNodes.delete(id);
+ let owns = node.getAttribute("aria-owns");
+ if (owns?.includes(id)) {
+ owns = owns.split(" ").filter(x => x !== id).join(" ");
+ if (owns) {
+ node.setAttribute("aria-owns", owns);
+ } else {
+ node.removeAttribute("aria-owns");
+ node.setAttribute("role", "presentation");
+ }
+ }
+ }
+ #addIdToAriaOwns(id, node) {
+ const owns = node.getAttribute("aria-owns");
+ if (!owns?.includes(id)) {
+ node.setAttribute("aria-owns", owns ? `${owns} ${id}` : id);
+ }
+ node.removeAttribute("role");
+ }
+ addPointerInTextLayer(element, isRemovable) {
+ const {
+ id
+ } = element;
+ if (!id) {
+ return null;
+ }
+ if (!this.#enabled) {
+ this.#waitingElements.set(element, isRemovable);
+ return null;
+ }
+ if (isRemovable) {
+ this.removePointerInTextLayer(element);
+ }
+ const children = this.#textChildren;
+ if (!children || children.length === 0) {
+ return null;
+ }
+ const index = binarySearchFirstItem(children, node => TextAccessibilityManager.#compareElementPositions(element, node) < 0);
+ const nodeIndex = Math.max(0, index - 1);
+ const child = children[nodeIndex];
+ this.#addIdToAriaOwns(id, child);
+ this.#textNodes.set(id, nodeIndex);
+ const parent = child.parentNode;
+ return parent?.classList.contains("markedContent") ? parent.id : null;
+ }
+ moveElementInDOM(container, element, contentElement, isRemovable) {
+ const id = this.addPointerInTextLayer(contentElement, isRemovable);
+ if (!container.hasChildNodes()) {
+ container.append(element);
+ return id;
+ }
+ const children = Array.from(container.childNodes).filter(node => node !== element);
+ if (children.length === 0) {
+ return id;
+ }
+ const elementToCompare = contentElement || element;
+ const index = binarySearchFirstItem(children, node => TextAccessibilityManager.#compareElementPositions(elementToCompare, node) < 0);
+ if (index === 0) {
+ children[0].before(element);
+ } else {
+ children[index - 1].after(element);
+ }
+ return id;
+ }
+}
+
+;// CONCATENATED MODULE: ./web/text_highlighter.js
+class TextHighlighter {
+ constructor({
+ findController,
+ eventBus,
+ pageIndex
+ }) {
+ this.findController = findController;
+ this.matches = [];
+ this.eventBus = eventBus;
+ this.pageIdx = pageIndex;
+ this._onUpdateTextLayerMatches = null;
+ this.textDivs = null;
+ this.textContentItemsStr = null;
+ this.enabled = false;
+ }
+ setTextMapping(divs, texts) {
+ this.textDivs = divs;
+ this.textContentItemsStr = texts;
+ }
+ enable() {
+ if (!this.textDivs || !this.textContentItemsStr) {
+ throw new Error("Text divs and strings have not been set.");
+ }
+ if (this.enabled) {
+ throw new Error("TextHighlighter is already enabled.");
+ }
+ this.enabled = true;
+ if (!this._onUpdateTextLayerMatches) {
+ this._onUpdateTextLayerMatches = evt => {
+ if (evt.pageIndex === this.pageIdx || evt.pageIndex === -1) {
+ this._updateMatches();
+ }
+ };
+ this.eventBus._on("updatetextlayermatches", this._onUpdateTextLayerMatches);
+ }
+ this._updateMatches();
+ }
+ disable() {
+ if (!this.enabled) {
+ return;
+ }
+ this.enabled = false;
+ if (this._onUpdateTextLayerMatches) {
+ this.eventBus._off("updatetextlayermatches", this._onUpdateTextLayerMatches);
+ this._onUpdateTextLayerMatches = null;
+ }
+ this._updateMatches(true);
+ }
+ _convertMatches(matches, matchesLength) {
+ if (!matches) {
+ return [];
+ }
+ const {
+ textContentItemsStr
+ } = this;
+ let i = 0,
+ iIndex = 0;
+ const end = textContentItemsStr.length - 1;
+ const result = [];
+ for (let m = 0, mm = matches.length; m < mm; m++) {
+ let matchIdx = matches[m];
+ while (i !== end && matchIdx >= iIndex + textContentItemsStr[i].length) {
+ iIndex += textContentItemsStr[i].length;
+ i++;
+ }
+ if (i === textContentItemsStr.length) {
+ console.error("Could not find a matching mapping");
+ }
+ const match = {
+ begin: {
+ divIdx: i,
+ offset: matchIdx - iIndex
+ }
+ };
+ matchIdx += matchesLength[m];
+ while (i !== end && matchIdx > iIndex + textContentItemsStr[i].length) {
+ iIndex += textContentItemsStr[i].length;
+ i++;
+ }
+ match.end = {
+ divIdx: i,
+ offset: matchIdx - iIndex
+ };
+ result.push(match);
+ }
+ return result;
+ }
+ _renderMatches(matches) {
+ if (matches.length === 0) {
+ return;
+ }
+ const {
+ findController,
+ pageIdx
+ } = this;
+ const {
+ textContentItemsStr,
+ textDivs
+ } = this;
+ const isSelectedPage = pageIdx === findController.selected.pageIdx;
+ const selectedMatchIdx = findController.selected.matchIdx;
+ const highlightAll = findController.state.highlightAll;
+ let prevEnd = null;
+ const infinity = {
+ divIdx: -1,
+ offset: undefined
+ };
+ function beginText(begin, className) {
+ const divIdx = begin.divIdx;
+ textDivs[divIdx].textContent = "";
+ return appendTextToDiv(divIdx, 0, begin.offset, className);
+ }
+ function appendTextToDiv(divIdx, fromOffset, toOffset, className) {
+ let div = textDivs[divIdx];
+ if (div.nodeType === Node.TEXT_NODE) {
+ const span = document.createElement("span");
+ div.before(span);
+ span.append(div);
+ textDivs[divIdx] = span;
+ div = span;
+ }
+ const content = textContentItemsStr[divIdx].substring(fromOffset, toOffset);
+ const node = document.createTextNode(content);
+ if (className) {
+ const span = document.createElement("span");
+ span.className = `${className} appended`;
+ span.append(node);
+ div.append(span);
+ return className.includes("selected") ? span.offsetLeft : 0;
+ }
+ div.append(node);
+ return 0;
+ }
+ let i0 = selectedMatchIdx,
+ i1 = i0 + 1;
+ if (highlightAll) {
+ i0 = 0;
+ i1 = matches.length;
+ } else if (!isSelectedPage) {
+ return;
+ }
+ let lastDivIdx = -1;
+ let lastOffset = -1;
+ for (let i = i0; i < i1; i++) {
+ const match = matches[i];
+ const begin = match.begin;
+ if (begin.divIdx === lastDivIdx && begin.offset === lastOffset) {
+ continue;
+ }
+ lastDivIdx = begin.divIdx;
+ lastOffset = begin.offset;
+ const end = match.end;
+ const isSelected = isSelectedPage && i === selectedMatchIdx;
+ const highlightSuffix = isSelected ? " selected" : "";
+ let selectedLeft = 0;
+ if (!prevEnd || begin.divIdx !== prevEnd.divIdx) {
+ if (prevEnd !== null) {
+ appendTextToDiv(prevEnd.divIdx, prevEnd.offset, infinity.offset);
+ }
+ beginText(begin);
+ } else {
+ appendTextToDiv(prevEnd.divIdx, prevEnd.offset, begin.offset);
+ }
+ if (begin.divIdx === end.divIdx) {
+ selectedLeft = appendTextToDiv(begin.divIdx, begin.offset, end.offset, "highlight" + highlightSuffix);
+ } else {
+ selectedLeft = appendTextToDiv(begin.divIdx, begin.offset, infinity.offset, "highlight begin" + highlightSuffix);
+ for (let n0 = begin.divIdx + 1, n1 = end.divIdx; n0 < n1; n0++) {
+ textDivs[n0].className = "highlight middle" + highlightSuffix;
+ }
+ beginText(end, "highlight end" + highlightSuffix);
+ }
+ prevEnd = end;
+ if (isSelected) {
+ findController.scrollMatchIntoView({
+ element: textDivs[begin.divIdx],
+ selectedLeft,
+ pageIndex: pageIdx,
+ matchIndex: selectedMatchIdx
+ });
+ }
+ }
+ if (prevEnd) {
+ appendTextToDiv(prevEnd.divIdx, prevEnd.offset, infinity.offset);
+ }
+ }
+ _updateMatches(reset = false) {
+ if (!this.enabled && !reset) {
+ return;
+ }
+ const {
+ findController,
+ matches,
+ pageIdx
+ } = this;
+ const {
+ textContentItemsStr,
+ textDivs
+ } = this;
+ let clearedUntilDivIdx = -1;
+ for (const match of matches) {
+ const begin = Math.max(clearedUntilDivIdx, match.begin.divIdx);
+ for (let n = begin, end = match.end.divIdx; n <= end; n++) {
+ const div = textDivs[n];
+ div.textContent = textContentItemsStr[n];
+ div.className = "";
+ }
+ clearedUntilDivIdx = match.end.divIdx + 1;
+ }
+ if (!findController?.highlightMatches || reset) {
+ return;
+ }
+ const pageMatches = findController.pageMatches[pageIdx] || null;
+ const pageMatchesLength = findController.pageMatchesLength[pageIdx] || null;
+ this.matches = this._convertMatches(pageMatches, pageMatchesLength);
+ this._renderMatches(this.matches);
+ }
+}
+
+;// CONCATENATED MODULE: ./web/text_layer_builder.js
+
+
+class TextLayerBuilder {
+ #enablePermissions = false;
+ #rotation = 0;
+ #scale = 0;
+ #textContentSource = null;
+ constructor({
+ highlighter = null,
+ accessibilityManager = null,
+ enablePermissions = false
+ }) {
+ this.textContentItemsStr = [];
+ this.renderingDone = false;
+ this.textDivs = [];
+ this.textDivProperties = new WeakMap();
+ this.textLayerRenderTask = null;
+ this.highlighter = highlighter;
+ this.accessibilityManager = accessibilityManager;
+ this.#enablePermissions = enablePermissions === true;
+ this.onAppend = null;
+ this.div = document.createElement("div");
+ this.div.className = "textLayer";
+ }
+ #finishRendering() {
+ this.renderingDone = true;
+ const endOfContent = document.createElement("div");
+ endOfContent.className = "endOfContent";
+ this.div.append(endOfContent);
+ this.#bindMouse();
+ }
+ get numTextDivs() {
+ return this.textDivs.length;
+ }
+ async render(viewport) {
+ if (!this.#textContentSource) {
+ throw new Error('No "textContentSource" parameter specified.');
+ }
+ const scale = viewport.scale * (globalThis.devicePixelRatio || 1);
+ const {
+ rotation
+ } = viewport;
+ if (this.renderingDone) {
+ const mustRotate = rotation !== this.#rotation;
+ const mustRescale = scale !== this.#scale;
+ if (mustRotate || mustRescale) {
+ this.hide();
+ updateTextLayer({
+ container: this.div,
+ viewport,
+ textDivs: this.textDivs,
+ textDivProperties: this.textDivProperties,
+ mustRescale,
+ mustRotate
+ });
+ this.#scale = scale;
+ this.#rotation = rotation;
+ }
+ this.show();
+ return;
+ }
+ this.cancel();
+ this.highlighter?.setTextMapping(this.textDivs, this.textContentItemsStr);
+ this.accessibilityManager?.setTextMapping(this.textDivs);
+ this.textLayerRenderTask = renderTextLayer({
+ textContentSource: this.#textContentSource,
+ container: this.div,
+ viewport,
+ textDivs: this.textDivs,
+ textDivProperties: this.textDivProperties,
+ textContentItemsStr: this.textContentItemsStr
+ });
+ await this.textLayerRenderTask.promise;
+ this.#finishRendering();
+ this.#scale = scale;
+ this.#rotation = rotation;
+ this.onAppend(this.div);
+ this.highlighter?.enable();
+ this.accessibilityManager?.enable();
+ }
+ hide() {
+ if (!this.div.hidden && this.renderingDone) {
+ this.highlighter?.disable();
+ this.div.hidden = true;
+ }
+ }
+ show() {
+ if (this.div.hidden && this.renderingDone) {
+ this.div.hidden = false;
+ this.highlighter?.enable();
+ }
+ }
+ cancel() {
+ if (this.textLayerRenderTask) {
+ this.textLayerRenderTask.cancel();
+ this.textLayerRenderTask = null;
+ }
+ this.highlighter?.disable();
+ this.accessibilityManager?.disable();
+ this.textContentItemsStr.length = 0;
+ this.textDivs.length = 0;
+ this.textDivProperties = new WeakMap();
+ }
+ setTextContentSource(source) {
+ this.cancel();
+ this.#textContentSource = source;
+ }
+ #bindMouse() {
+ const {
+ div
+ } = this;
+ div.addEventListener("mousedown", evt => {
+ const end = div.querySelector(".endOfContent");
+ if (!end) {
+ return;
+ }
+ end.classList.add("active");
+ });
+ div.addEventListener("mouseup", () => {
+ const end = div.querySelector(".endOfContent");
+ if (!end) {
+ return;
+ }
+ end.classList.remove("active");
+ });
+ div.addEventListener("copy", event => {
+ if (!this.#enablePermissions) {
+ const selection = document.getSelection();
+ event.clipboardData.setData("text/plain", removeNullCharacters(normalizeUnicode(selection.toString())));
+ }
+ event.preventDefault();
+ event.stopPropagation();
+ });
+ }
+}
+
+;// CONCATENATED MODULE: ./web/pdf_page_view.js
+
+
+
+
+
+
+
+
+
+
+
+
+
+const MAX_CANVAS_PIXELS = compatibilityParams.maxCanvasPixels || 16777216;
+const DEFAULT_LAYER_PROPERTIES = null;
+class PDFPageView {
+ #annotationMode = AnnotationMode.ENABLE_FORMS;
+ #hasRestrictedScaling = false;
+ #layerProperties = null;
+ #loadingId = null;
+ #previousRotation = null;
+ #renderError = null;
+ #renderingState = RenderingStates.INITIAL;
+ #textLayerMode = TextLayerMode.ENABLE;
+ #useThumbnailCanvas = {
+ directDrawing: true,
+ initialOptionalContent: true,
+ regularAnnotations: true
+ };
+ #viewportMap = new WeakMap();
+ constructor(options) {
+ const container = options.container;
+ const defaultViewport = options.defaultViewport;
+ this.id = options.id;
+ this.renderingId = "page" + this.id;
+ this.#layerProperties = options.layerProperties || DEFAULT_LAYER_PROPERTIES;
+ this.pdfPage = null;
+ this.pageLabel = null;
+ this.rotation = 0;
+ this.scale = options.scale || DEFAULT_SCALE;
+ this.viewport = defaultViewport;
+ this.pdfPageRotate = defaultViewport.rotation;
+ this._optionalContentConfigPromise = options.optionalContentConfigPromise || null;
+ this.#textLayerMode = options.textLayerMode ?? TextLayerMode.ENABLE;
+ this.#annotationMode = options.annotationMode ?? AnnotationMode.ENABLE_FORMS;
+ this.imageResourcesPath = options.imageResourcesPath || "";
+ this.maxCanvasPixels = options.maxCanvasPixels ?? MAX_CANVAS_PIXELS;
+ this.pageColors = options.pageColors || null;
+ this.eventBus = options.eventBus;
+ this.renderingQueue = options.renderingQueue;
+ this.l10n = options.l10n;
+ this.renderTask = null;
+ this.resume = null;
+ this._annotationCanvasMap = null;
+ this.annotationLayer = null;
+ this.annotationEditorLayer = null;
+ this.textLayer = null;
+ this.zoomLayer = null;
+ this.xfaLayer = null;
+ this.structTreeLayer = null;
+ this.drawLayer = null;
+ const div = document.createElement("div");
+ div.className = "page";
+ div.setAttribute("data-page-number", this.id);
+ div.setAttribute("role", "region");
+ div.setAttribute("data-l10n-id", "pdfjs-page-landmark");
+ div.setAttribute("data-l10n-args", JSON.stringify({
+ page: this.id
+ }));
+ this.div = div;
+ this.#setDimensions();
+ container?.append(div);
+ }
+ get renderingState() {
+ return this.#renderingState;
+ }
+ set renderingState(state) {
+ if (state === this.#renderingState) {
+ return;
+ }
+ this.#renderingState = state;
+ if (this.#loadingId) {
+ clearTimeout(this.#loadingId);
+ this.#loadingId = null;
+ }
+ switch (state) {
+ case RenderingStates.PAUSED:
+ this.div.classList.remove("loading");
+ break;
+ case RenderingStates.RUNNING:
+ this.div.classList.add("loadingIcon");
+ this.#loadingId = setTimeout(() => {
+ this.div.classList.add("loading");
+ this.#loadingId = null;
+ }, 0);
+ break;
+ case RenderingStates.INITIAL:
+ case RenderingStates.FINISHED:
+ this.div.classList.remove("loadingIcon", "loading");
+ break;
+ }
+ }
+ #setDimensions() {
+ const {
+ viewport
+ } = this;
+ if (this.pdfPage) {
+ if (this.#previousRotation === viewport.rotation) {
+ return;
+ }
+ this.#previousRotation = viewport.rotation;
+ }
+ setLayerDimensions(this.div, viewport, true, false);
+ }
+ setPdfPage(pdfPage) {
+ this.pdfPage = pdfPage;
+ this.pdfPageRotate = pdfPage.rotate;
+ const totalRotation = (this.rotation + this.pdfPageRotate) % 360;
+ this.viewport = pdfPage.getViewport({
+ scale: this.scale * PixelsPerInch.PDF_TO_CSS_UNITS,
+ rotation: totalRotation
+ });
+ this.#setDimensions();
+ this.reset();
+ }
+ destroy() {
+ this.reset();
+ this.pdfPage?.cleanup();
+ }
+ get _textHighlighter() {
+ return shadow(this, "_textHighlighter", new TextHighlighter({
+ pageIndex: this.id - 1,
+ eventBus: this.eventBus,
+ findController: this.#layerProperties.findController
+ }));
+ }
+ async #renderAnnotationLayer() {
+ let error = null;
+ try {
+ await this.annotationLayer.render(this.viewport, "display");
+ } catch (ex) {
+ console.error(`#renderAnnotationLayer: "${ex}".`);
+ error = ex;
+ } finally {
+ this.eventBus.dispatch("annotationlayerrendered", {
+ source: this,
+ pageNumber: this.id,
+ error
+ });
+ }
+ }
+ async #renderAnnotationEditorLayer() {
+ let error = null;
+ try {
+ await this.annotationEditorLayer.render(this.viewport, "display");
+ } catch (ex) {
+ console.error(`#renderAnnotationEditorLayer: "${ex}".`);
+ error = ex;
+ } finally {
+ this.eventBus.dispatch("annotationeditorlayerrendered", {
+ source: this,
+ pageNumber: this.id,
+ error
+ });
+ }
+ }
+ async #renderDrawLayer() {
+ try {
+ await this.drawLayer.render("display");
+ } catch (ex) {
+ console.error(`#renderDrawLayer: "${ex}".`);
+ }
+ }
+ async #renderXfaLayer() {
+ let error = null;
+ try {
+ const result = await this.xfaLayer.render(this.viewport, "display");
+ if (result?.textDivs && this._textHighlighter) {
+ this.#buildXfaTextContentItems(result.textDivs);
+ }
+ } catch (ex) {
+ console.error(`#renderXfaLayer: "${ex}".`);
+ error = ex;
+ } finally {
+ if (this.xfaLayer?.div) {
+ this.l10n.pause();
+ this.div.append(this.xfaLayer.div);
+ this.l10n.resume();
+ }
+ this.eventBus.dispatch("xfalayerrendered", {
+ source: this,
+ pageNumber: this.id,
+ error
+ });
+ }
+ }
+ async #renderTextLayer() {
+ const {
+ pdfPage,
+ textLayer,
+ viewport
+ } = this;
+ if (!textLayer) {
+ return;
+ }
+ let error = null;
+ try {
+ if (!textLayer.renderingDone) {
+ const readableStream = pdfPage.streamTextContent({
+ includeMarkedContent: true,
+ disableNormalization: true
+ });
+ textLayer.setTextContentSource(readableStream);
+ }
+ await textLayer.render(viewport);
+ } catch (ex) {
+ if (ex instanceof AbortException) {
+ return;
+ }
+ console.error(`#renderTextLayer: "${ex}".`);
+ error = ex;
+ }
+ this.eventBus.dispatch("textlayerrendered", {
+ source: this,
+ pageNumber: this.id,
+ numTextDivs: textLayer.numTextDivs,
+ error
+ });
+ this.#renderStructTreeLayer();
+ }
+ async #renderStructTreeLayer() {
+ if (!this.textLayer) {
+ return;
+ }
+ this.structTreeLayer ||= new StructTreeLayerBuilder();
+ const tree = await (!this.structTreeLayer.renderingDone ? this.pdfPage.getStructTree() : null);
+ const treeDom = this.structTreeLayer?.render(tree);
+ if (treeDom) {
+ this.l10n.pause();
+ this.canvas?.append(treeDom);
+ this.l10n.resume();
+ }
+ this.structTreeLayer?.show();
+ }
+ async #buildXfaTextContentItems(textDivs) {
+ const text = await this.pdfPage.getTextContent();
+ const items = [];
+ for (const item of text.items) {
+ items.push(item.str);
+ }
+ this._textHighlighter.setTextMapping(textDivs, items);
+ this._textHighlighter.enable();
+ }
+ _resetZoomLayer(removeFromDOM = false) {
+ if (!this.zoomLayer) {
+ return;
+ }
+ const zoomLayerCanvas = this.zoomLayer.firstChild;
+ this.#viewportMap.delete(zoomLayerCanvas);
+ zoomLayerCanvas.width = 0;
+ zoomLayerCanvas.height = 0;
+ if (removeFromDOM) {
+ this.zoomLayer.remove();
+ }
+ this.zoomLayer = null;
+ }
+ reset({
+ keepZoomLayer = false,
+ keepAnnotationLayer = false,
+ keepAnnotationEditorLayer = false,
+ keepXfaLayer = false,
+ keepTextLayer = false
+ } = {}) {
+ this.cancelRendering({
+ keepAnnotationLayer,
+ keepAnnotationEditorLayer,
+ keepXfaLayer,
+ keepTextLayer
+ });
+ this.renderingState = RenderingStates.INITIAL;
+ const div = this.div;
+ const childNodes = div.childNodes,
+ zoomLayerNode = keepZoomLayer && this.zoomLayer || null,
+ annotationLayerNode = keepAnnotationLayer && this.annotationLayer?.div || null,
+ annotationEditorLayerNode = keepAnnotationEditorLayer && this.annotationEditorLayer?.div || null,
+ xfaLayerNode = keepXfaLayer && this.xfaLayer?.div || null,
+ textLayerNode = keepTextLayer && this.textLayer?.div || null;
+ for (let i = childNodes.length - 1; i >= 0; i--) {
+ const node = childNodes[i];
+ switch (node) {
+ case zoomLayerNode:
+ case annotationLayerNode:
+ case annotationEditorLayerNode:
+ case xfaLayerNode:
+ case textLayerNode:
+ continue;
+ }
+ node.remove();
+ }
+ div.removeAttribute("data-loaded");
+ if (annotationLayerNode) {
+ this.annotationLayer.hide();
+ }
+ if (annotationEditorLayerNode) {
+ this.annotationEditorLayer.hide();
+ }
+ if (xfaLayerNode) {
+ this.xfaLayer.hide();
+ }
+ if (textLayerNode) {
+ this.textLayer.hide();
+ }
+ this.structTreeLayer?.hide();
+ if (!zoomLayerNode) {
+ if (this.canvas) {
+ this.#viewportMap.delete(this.canvas);
+ this.canvas.width = 0;
+ this.canvas.height = 0;
+ delete this.canvas;
+ }
+ this._resetZoomLayer();
+ }
+ }
+ update({
+ scale = 0,
+ rotation = null,
+ optionalContentConfigPromise = null,
+ drawingDelay = -1
+ }) {
+ this.scale = scale || this.scale;
+ if (typeof rotation === "number") {
+ this.rotation = rotation;
+ }
+ if (optionalContentConfigPromise instanceof Promise) {
+ this._optionalContentConfigPromise = optionalContentConfigPromise;
+ optionalContentConfigPromise.then(optionalContentConfig => {
+ if (optionalContentConfigPromise !== this._optionalContentConfigPromise) {
+ return;
+ }
+ this.#useThumbnailCanvas.initialOptionalContent = optionalContentConfig.hasInitialVisibility;
+ });
+ }
+ this.#useThumbnailCanvas.directDrawing = true;
+ const totalRotation = (this.rotation + this.pdfPageRotate) % 360;
+ this.viewport = this.viewport.clone({
+ scale: this.scale * PixelsPerInch.PDF_TO_CSS_UNITS,
+ rotation: totalRotation
+ });
+ this.#setDimensions();
+ if (this.canvas) {
+ let onlyCssZoom = false;
+ if (this.#hasRestrictedScaling) {
+ if (this.maxCanvasPixels > 0) {
+ const {
+ width,
+ height
+ } = this.viewport;
+ const {
+ sx,
+ sy
+ } = this.outputScale;
+ onlyCssZoom = (Math.floor(width) * sx | 0) * (Math.floor(height) * sy | 0) > this.maxCanvasPixels;
+ }
+ }
+ const postponeDrawing = !onlyCssZoom && drawingDelay >= 0 && drawingDelay < 1000;
+ if (postponeDrawing || onlyCssZoom) {
+ if (postponeDrawing && this.renderingState !== RenderingStates.FINISHED) {
+ this.cancelRendering({
+ keepZoomLayer: true,
+ keepAnnotationLayer: true,
+ keepAnnotationEditorLayer: true,
+ keepXfaLayer: true,
+ keepTextLayer: true,
+ cancelExtraDelay: drawingDelay
+ });
+ this.renderingState = RenderingStates.FINISHED;
+ this.#useThumbnailCanvas.directDrawing = false;
+ }
+ this.cssTransform({
+ target: this.canvas,
+ redrawAnnotationLayer: true,
+ redrawAnnotationEditorLayer: true,
+ redrawXfaLayer: true,
+ redrawTextLayer: !postponeDrawing,
+ hideTextLayer: postponeDrawing
+ });
+ if (postponeDrawing) {
+ return;
+ }
+ this.eventBus.dispatch("pagerendered", {
+ source: this,
+ pageNumber: this.id,
+ cssTransform: true,
+ timestamp: performance.now(),
+ error: this.#renderError
+ });
+ return;
+ }
+ if (!this.zoomLayer && !this.canvas.hidden) {
+ this.zoomLayer = this.canvas.parentNode;
+ this.zoomLayer.style.position = "absolute";
+ }
+ }
+ if (this.zoomLayer) {
+ this.cssTransform({
+ target: this.zoomLayer.firstChild
+ });
+ }
+ this.reset({
+ keepZoomLayer: true,
+ keepAnnotationLayer: true,
+ keepAnnotationEditorLayer: true,
+ keepXfaLayer: true,
+ keepTextLayer: true
+ });
+ }
+ cancelRendering({
+ keepAnnotationLayer = false,
+ keepAnnotationEditorLayer = false,
+ keepXfaLayer = false,
+ keepTextLayer = false,
+ cancelExtraDelay = 0
+ } = {}) {
+ if (this.renderTask) {
+ this.renderTask.cancel(cancelExtraDelay);
+ this.renderTask = null;
+ }
+ this.resume = null;
+ if (this.textLayer && (!keepTextLayer || !this.textLayer.div)) {
+ this.textLayer.cancel();
+ this.textLayer = null;
+ }
+ if (this.structTreeLayer && !this.textLayer) {
+ this.structTreeLayer = null;
+ }
+ if (this.annotationLayer && (!keepAnnotationLayer || !this.annotationLayer.div)) {
+ this.annotationLayer.cancel();
+ this.annotationLayer = null;
+ this._annotationCanvasMap = null;
+ }
+ if (this.annotationEditorLayer && (!keepAnnotationEditorLayer || !this.annotationEditorLayer.div)) {
+ if (this.drawLayer) {
+ this.drawLayer.cancel();
+ this.drawLayer = null;
+ }
+ this.annotationEditorLayer.cancel();
+ this.annotationEditorLayer = null;
+ }
+ if (this.xfaLayer && (!keepXfaLayer || !this.xfaLayer.div)) {
+ this.xfaLayer.cancel();
+ this.xfaLayer = null;
+ this._textHighlighter?.disable();
+ }
+ }
+ cssTransform({
+ target,
+ redrawAnnotationLayer = false,
+ redrawAnnotationEditorLayer = false,
+ redrawXfaLayer = false,
+ redrawTextLayer = false,
+ hideTextLayer = false
+ }) {
+ if (!target.hasAttribute("zooming")) {
+ target.setAttribute("zooming", true);
+ const {
+ style
+ } = target;
+ style.width = style.height = "";
+ }
+ const originalViewport = this.#viewportMap.get(target);
+ if (this.viewport !== originalViewport) {
+ const relativeRotation = this.viewport.rotation - originalViewport.rotation;
+ const absRotation = Math.abs(relativeRotation);
+ let scaleX = 1,
+ scaleY = 1;
+ if (absRotation === 90 || absRotation === 270) {
+ const {
+ width,
+ height
+ } = this.viewport;
+ scaleX = height / width;
+ scaleY = width / height;
+ }
+ target.style.transform = `rotate(${relativeRotation}deg) scale(${scaleX}, ${scaleY})`;
+ }
+ if (redrawAnnotationLayer && this.annotationLayer) {
+ this.#renderAnnotationLayer();
+ }
+ if (redrawAnnotationEditorLayer && this.annotationEditorLayer) {
+ if (this.drawLayer) {
+ this.#renderDrawLayer();
+ }
+ this.#renderAnnotationEditorLayer();
+ }
+ if (redrawXfaLayer && this.xfaLayer) {
+ this.#renderXfaLayer();
+ }
+ if (this.textLayer) {
+ if (hideTextLayer) {
+ this.textLayer.hide();
+ this.structTreeLayer?.hide();
+ } else if (redrawTextLayer) {
+ this.#renderTextLayer();
+ }
+ }
+ }
+ get width() {
+ return this.viewport.width;
+ }
+ get height() {
+ return this.viewport.height;
+ }
+ getPagePoint(x, y) {
+ return this.viewport.convertToPdfPoint(x, y);
+ }
+ async #finishRenderTask(renderTask, error = null) {
+ if (renderTask === this.renderTask) {
+ this.renderTask = null;
+ }
+ if (error instanceof RenderingCancelledException) {
+ this.#renderError = null;
+ return;
+ }
+ this.#renderError = error;
+ this.renderingState = RenderingStates.FINISHED;
+ this._resetZoomLayer(true);
+ this.#useThumbnailCanvas.regularAnnotations = !renderTask.separateAnnots;
+ this.eventBus.dispatch("pagerendered", {
+ source: this,
+ pageNumber: this.id,
+ cssTransform: false,
+ timestamp: performance.now(),
+ error: this.#renderError
+ });
+ if (error) {
+ throw error;
+ }
+ }
+ async draw() {
+ if (this.renderingState !== RenderingStates.INITIAL) {
+ console.error("Must be in new state before drawing");
+ this.reset();
+ }
+ const {
+ div,
+ l10n,
+ pageColors,
+ pdfPage,
+ viewport
+ } = this;
+ if (!pdfPage) {
+ this.renderingState = RenderingStates.FINISHED;
+ throw new Error("pdfPage is not loaded");
+ }
+ this.renderingState = RenderingStates.RUNNING;
+ const canvasWrapper = document.createElement("div");
+ canvasWrapper.classList.add("canvasWrapper");
+ div.append(canvasWrapper);
+ if (!this.textLayer && this.#textLayerMode !== TextLayerMode.DISABLE && !pdfPage.isPureXfa) {
+ this._accessibilityManager ||= new TextAccessibilityManager();
+ this.textLayer = new TextLayerBuilder({
+ highlighter: this._textHighlighter,
+ accessibilityManager: this._accessibilityManager,
+ enablePermissions: this.#textLayerMode === TextLayerMode.ENABLE_PERMISSIONS
+ });
+ this.textLayer.onAppend = textLayerDiv => {
+ this.l10n.pause();
+ this.div.append(textLayerDiv);
+ this.l10n.resume();
+ };
+ }
+ if (!this.annotationLayer && this.#annotationMode !== AnnotationMode.DISABLE) {
+ const {
+ annotationStorage,
+ downloadManager,
+ enableScripting,
+ fieldObjectsPromise,
+ hasJSActionsPromise,
+ linkService
+ } = this.#layerProperties;
+ this._annotationCanvasMap ||= new Map();
+ this.annotationLayer = new AnnotationLayerBuilder({
+ pageDiv: div,
+ pdfPage,
+ annotationStorage,
+ imageResourcesPath: this.imageResourcesPath,
+ renderForms: this.#annotationMode === AnnotationMode.ENABLE_FORMS,
+ linkService,
+ downloadManager,
+ enableScripting,
+ hasJSActionsPromise,
+ fieldObjectsPromise,
+ annotationCanvasMap: this._annotationCanvasMap,
+ accessibilityManager: this._accessibilityManager
+ });
+ }
+ const renderContinueCallback = cont => {
+ showCanvas?.(false);
+ if (this.renderingQueue && !this.renderingQueue.isHighestPriority(this)) {
+ this.renderingState = RenderingStates.PAUSED;
+ this.resume = () => {
+ this.renderingState = RenderingStates.RUNNING;
+ cont();
+ };
+ return;
+ }
+ cont();
+ };
+ const {
+ width,
+ height
+ } = viewport;
+ const canvas = document.createElement("canvas");
+ canvas.setAttribute("role", "presentation");
+ canvas.hidden = true;
+ const hasHCM = !!(pageColors?.background && pageColors?.foreground);
+ let showCanvas = isLastShow => {
+ if (!hasHCM || isLastShow) {
+ canvas.hidden = false;
+ showCanvas = null;
+ }
+ };
+ canvasWrapper.append(canvas);
+ this.canvas = canvas;
+ const ctx = canvas.getContext("2d", {
+ alpha: false
+ });
+ const outputScale = this.outputScale = new OutputScale();
+ if (this.maxCanvasPixels > 0) {
+ const pixelsInViewport = width * height;
+ const maxScale = Math.sqrt(this.maxCanvasPixels / pixelsInViewport);
+ if (outputScale.sx > maxScale || outputScale.sy > maxScale) {
+ outputScale.sx = maxScale;
+ outputScale.sy = maxScale;
+ this.#hasRestrictedScaling = true;
+ } else {
+ this.#hasRestrictedScaling = false;
+ }
+ }
+ const sfx = approximateFraction(outputScale.sx);
+ const sfy = approximateFraction(outputScale.sy);
+ canvas.width = roundToDivide(width * outputScale.sx, sfx[0]);
+ canvas.height = roundToDivide(height * outputScale.sy, sfy[0]);
+ const {
+ style
+ } = canvas;
+ style.width = roundToDivide(width, sfx[1]) + "px";
+ style.height = roundToDivide(height, sfy[1]) + "px";
+ this.#viewportMap.set(canvas, viewport);
+ const transform = outputScale.scaled ? [outputScale.sx, 0, 0, outputScale.sy, 0, 0] : null;
+ const renderContext = {
+ canvasContext: ctx,
+ transform,
+ viewport,
+ annotationMode: this.#annotationMode,
+ optionalContentConfigPromise: this._optionalContentConfigPromise,
+ annotationCanvasMap: this._annotationCanvasMap,
+ pageColors
+ };
+ const renderTask = this.renderTask = this.pdfPage.render(renderContext);
+ renderTask.onContinue = renderContinueCallback;
+ const resultPromise = renderTask.promise.then(async () => {
+ showCanvas?.(true);
+ await this.#finishRenderTask(renderTask);
+ this.#renderTextLayer();
+ if (this.annotationLayer) {
+ await this.#renderAnnotationLayer();
+ }
+ const {
+ annotationEditorUIManager
+ } = this.#layerProperties;
+ if (!annotationEditorUIManager) {
+ return;
+ }
+ this.drawLayer ||= new DrawLayerBuilder({
+ pageIndex: this.id
+ });
+ await this.#renderDrawLayer();
+ this.drawLayer.setParent(canvasWrapper);
+ if (!this.annotationEditorLayer) {
+ this.annotationEditorLayer = new AnnotationEditorLayerBuilder({
+ uiManager: annotationEditorUIManager,
+ pageDiv: div,
+ pdfPage,
+ l10n,
+ accessibilityManager: this._accessibilityManager,
+ annotationLayer: this.annotationLayer?.annotationLayer,
+ textLayer: this.textLayer,
+ drawLayer: this.drawLayer.getDrawLayer()
+ });
+ }
+ this.#renderAnnotationEditorLayer();
+ }, error => {
+ if (!(error instanceof RenderingCancelledException)) {
+ showCanvas?.(true);
+ }
+ return this.#finishRenderTask(renderTask, error);
+ });
+ if (pdfPage.isPureXfa) {
+ if (!this.xfaLayer) {
+ const {
+ annotationStorage,
+ linkService
+ } = this.#layerProperties;
+ this.xfaLayer = new XfaLayerBuilder({
+ pdfPage,
+ annotationStorage,
+ linkService
+ });
+ }
+ this.#renderXfaLayer();
+ }
+ div.setAttribute("data-loaded", true);
+ this.eventBus.dispatch("pagerender", {
+ source: this,
+ pageNumber: this.id
+ });
+ return resultPromise;
+ }
+ setPageLabel(label) {
+ this.pageLabel = typeof label === "string" ? label : null;
+ this.div.setAttribute("data-l10n-args", JSON.stringify({
+ page: this.pageLabel ?? this.id
+ }));
+ if (this.pageLabel !== null) {
+ this.div.setAttribute("data-page-label", this.pageLabel);
+ } else {
+ this.div.removeAttribute("data-page-label");
+ }
+ }
+ get thumbnailCanvas() {
+ const {
+ directDrawing,
+ initialOptionalContent,
+ regularAnnotations
+ } = this.#useThumbnailCanvas;
+ return directDrawing && initialOptionalContent && regularAnnotations ? this.canvas : null;
+ }
+}
+
+;// CONCATENATED MODULE: ./web/pdf_viewer.js
+
+
+
+
+
+
+const DEFAULT_CACHE_SIZE = 10;
+const PagesCountLimit = {
+ FORCE_SCROLL_MODE_PAGE: 15000,
+ FORCE_LAZY_PAGE_INIT: 7500,
+ PAUSE_EAGER_PAGE_INIT: 250
+};
+function isValidAnnotationEditorMode(mode) {
+ return Object.values(AnnotationEditorType).includes(mode) && mode !== AnnotationEditorType.DISABLE;
+}
+class PDFPageViewBuffer {
+ #buf = new Set();
+ #size = 0;
+ constructor(size) {
+ this.#size = size;
+ }
+ push(view) {
+ const buf = this.#buf;
+ if (buf.has(view)) {
+ buf.delete(view);
+ }
+ buf.add(view);
+ if (buf.size > this.#size) {
+ this.#destroyFirstView();
+ }
+ }
+ resize(newSize, idsToKeep = null) {
+ this.#size = newSize;
+ const buf = this.#buf;
+ if (idsToKeep) {
+ const ii = buf.size;
+ let i = 1;
+ for (const view of buf) {
+ if (idsToKeep.has(view.id)) {
+ buf.delete(view);
+ buf.add(view);
+ }
+ if (++i > ii) {
+ break;
+ }
+ }
+ }
+ while (buf.size > this.#size) {
+ this.#destroyFirstView();
+ }
+ }
+ has(view) {
+ return this.#buf.has(view);
+ }
+ [Symbol.iterator]() {
+ return this.#buf.keys();
+ }
+ #destroyFirstView() {
+ const firstView = this.#buf.keys().next().value;
+ firstView?.destroy();
+ this.#buf.delete(firstView);
+ }
+}
+class PDFViewer {
+ #buffer = null;
+ #altTextManager = null;
+ #annotationEditorHighlightColors = null;
+ #annotationEditorMode = AnnotationEditorType.NONE;
+ #annotationEditorUIManager = null;
+ #annotationMode = AnnotationMode.ENABLE_FORMS;
+ #containerTopLeft = null;
+ #copyCallbackBound = null;
+ #enablePermissions = false;
+ #mlManager = null;
+ #getAllTextInProgress = false;
+ #hiddenCopyElement = null;
+ #interruptCopyCondition = false;
+ #previousContainerHeight = 0;
+ #resizeObserver = new ResizeObserver(this.#resizeObserverCallback.bind(this));
+ #scrollModePageState = null;
+ #onVisibilityChange = null;
+ #scaleTimeoutId = null;
+ #textLayerMode = TextLayerMode.ENABLE;
+ constructor(options) {
+ const viewerVersion = "4.1.249";
+ if (version !== viewerVersion) {
+ throw new Error(`The API version "${version}" does not match the Viewer version "${viewerVersion}".`);
+ }
+ this.container = options.container;
+ this.viewer = options.viewer || options.container.firstElementChild;
+ this.#resizeObserver.observe(this.container);
+ this.eventBus = options.eventBus;
+ this.linkService = options.linkService || new SimpleLinkService();
+ this.downloadManager = options.downloadManager || null;
+ this.findController = options.findController || null;
+ this.#altTextManager = options.altTextManager || null;
+ if (this.findController) {
+ this.findController.onIsPageVisible = pageNumber => this._getVisiblePages().ids.has(pageNumber);
+ }
+ this._scriptingManager = options.scriptingManager || null;
+ this.#textLayerMode = options.textLayerMode ?? TextLayerMode.ENABLE;
+ this.#annotationMode = options.annotationMode ?? AnnotationMode.ENABLE_FORMS;
+ this.#annotationEditorMode = options.annotationEditorMode ?? AnnotationEditorType.NONE;
+ this.#annotationEditorHighlightColors = options.annotationEditorHighlightColors || null;
+ this.imageResourcesPath = options.imageResourcesPath || "";
+ this.enablePrintAutoRotate = options.enablePrintAutoRotate || false;
+ this.maxCanvasPixels = options.maxCanvasPixels;
+ this.l10n = options.l10n;
+ this.#enablePermissions = options.enablePermissions || false;
+ this.pageColors = options.pageColors || null;
+ this.#mlManager = options.mlManager || null;
+ this.defaultRenderingQueue = !options.renderingQueue;
+ this.renderingQueue = options.renderingQueue;
+ this.scroll = watchScroll(this.container, this._scrollUpdate.bind(this));
+ this.presentationModeState = PresentationModeState.UNKNOWN;
+ this._onBeforeDraw = this._onAfterDraw = null;
+ this._resetView();
+ this.#updateContainerHeightCss();
+ this.eventBus._on("thumbnailrendered", ({
+ pageNumber,
+ pdfPage
+ }) => {
+ const pageView = this._pages[pageNumber - 1];
+ if (!this.#buffer.has(pageView)) {
+ pdfPage?.cleanup();
+ }
+ });
+ }
+ get pagesCount() {
+ return this._pages.length;
+ }
+ getPageView(index) {
+ return this._pages[index];
+ }
+ getCachedPageViews() {
+ return new Set(this.#buffer);
+ }
+ get pageViewsReady() {
+ return this._pagesCapability.settled && this._pages.every(pageView => pageView?.pdfPage);
+ }
+ get renderForms() {
+ return this.#annotationMode === AnnotationMode.ENABLE_FORMS;
+ }
+ get enableScripting() {
+ return !!this._scriptingManager;
+ }
+ get currentPageNumber() {
+ return this._currentPageNumber;
+ }
+ set currentPageNumber(val) {
+ if (!Number.isInteger(val)) {
+ throw new Error("Invalid page number.");
+ }
+ if (!this.pdfDocument) {
+ return;
+ }
+ if (!this._setCurrentPageNumber(val, true)) {
+ console.error(`currentPageNumber: "${val}" is not a valid page.`);
+ }
+ }
+ _setCurrentPageNumber(val, resetCurrentPageView = false) {
+ if (this._currentPageNumber === val) {
+ if (resetCurrentPageView) {
+ this.#resetCurrentPageView();
+ }
+ return true;
+ }
+ if (!(0 < val && val <= this.pagesCount)) {
+ return false;
+ }
+ const previous = this._currentPageNumber;
+ this._currentPageNumber = val;
+ this.eventBus.dispatch("pagechanging", {
+ source: this,
+ pageNumber: val,
+ pageLabel: this._pageLabels?.[val - 1] ?? null,
+ previous
+ });
+ if (resetCurrentPageView) {
+ this.#resetCurrentPageView();
+ }
+ return true;
+ }
+ get currentPageLabel() {
+ return this._pageLabels?.[this._currentPageNumber - 1] ?? null;
+ }
+ set currentPageLabel(val) {
+ if (!this.pdfDocument) {
+ return;
+ }
+ let page = val | 0;
+ if (this._pageLabels) {
+ const i = this._pageLabels.indexOf(val);
+ if (i >= 0) {
+ page = i + 1;
+ }
+ }
+ if (!this._setCurrentPageNumber(page, true)) {
+ console.error(`currentPageLabel: "${val}" is not a valid page.`);
+ }
+ }
+ get currentScale() {
+ return this._currentScale !== UNKNOWN_SCALE ? this._currentScale : DEFAULT_SCALE;
+ }
+ set currentScale(val) {
+ if (isNaN(val)) {
+ throw new Error("Invalid numeric scale.");
+ }
+ if (!this.pdfDocument) {
+ return;
+ }
+ this.#setScale(val, {
+ noScroll: false
+ });
+ }
+ get currentScaleValue() {
+ return this._currentScaleValue;
+ }
+ set currentScaleValue(val) {
+ if (!this.pdfDocument) {
+ return;
+ }
+ this.#setScale(val, {
+ noScroll: false
+ });
+ }
+ get pagesRotation() {
+ return this._pagesRotation;
+ }
+ set pagesRotation(rotation) {
+ if (!isValidRotation(rotation)) {
+ throw new Error("Invalid pages rotation angle.");
+ }
+ if (!this.pdfDocument) {
+ return;
+ }
+ rotation %= 360;
+ if (rotation < 0) {
+ rotation += 360;
+ }
+ if (this._pagesRotation === rotation) {
+ return;
+ }
+ this._pagesRotation = rotation;
+ const pageNumber = this._currentPageNumber;
+ this.refresh(true, {
+ rotation
+ });
+ if (this._currentScaleValue) {
+ this.#setScale(this._currentScaleValue, {
+ noScroll: true
+ });
+ }
+ this.eventBus.dispatch("rotationchanging", {
+ source: this,
+ pagesRotation: rotation,
+ pageNumber
+ });
+ if (this.defaultRenderingQueue) {
+ this.update();
+ }
+ }
+ get firstPagePromise() {
+ return this.pdfDocument ? this._firstPageCapability.promise : null;
+ }
+ get onePageRendered() {
+ return this.pdfDocument ? this._onePageRenderedCapability.promise : null;
+ }
+ get pagesPromise() {
+ return this.pdfDocument ? this._pagesCapability.promise : null;
+ }
+ get _layerProperties() {
+ const self = this;
+ return shadow(this, "_layerProperties", {
+ get annotationEditorUIManager() {
+ return self.#annotationEditorUIManager;
+ },
+ get annotationStorage() {
+ return self.pdfDocument?.annotationStorage;
+ },
+ get downloadManager() {
+ return self.downloadManager;
+ },
+ get enableScripting() {
+ return !!self._scriptingManager;
+ },
+ get fieldObjectsPromise() {
+ return self.pdfDocument?.getFieldObjects();
+ },
+ get findController() {
+ return self.findController;
+ },
+ get hasJSActionsPromise() {
+ return self.pdfDocument?.hasJSActions();
+ },
+ get linkService() {
+ return self.linkService;
+ }
+ });
+ }
+ #initializePermissions(permissions) {
+ const params = {
+ annotationEditorMode: this.#annotationEditorMode,
+ annotationMode: this.#annotationMode,
+ textLayerMode: this.#textLayerMode
+ };
+ if (!permissions) {
+ return params;
+ }
+ if (!permissions.includes(PermissionFlag.COPY) && this.#textLayerMode === TextLayerMode.ENABLE) {
+ params.textLayerMode = TextLayerMode.ENABLE_PERMISSIONS;
+ }
+ if (!permissions.includes(PermissionFlag.MODIFY_CONTENTS)) {
+ params.annotationEditorMode = AnnotationEditorType.DISABLE;
+ }
+ if (!permissions.includes(PermissionFlag.MODIFY_ANNOTATIONS) && !permissions.includes(PermissionFlag.FILL_INTERACTIVE_FORMS) && this.#annotationMode === AnnotationMode.ENABLE_FORMS) {
+ params.annotationMode = AnnotationMode.ENABLE;
+ }
+ return params;
+ }
+ async #onePageRenderedOrForceFetch() {
+ if (document.visibilityState === "hidden" || !this.container.offsetParent || this._getVisiblePages().views.length === 0) {
+ return;
+ }
+ const visibilityChangePromise = new Promise(resolve => {
+ this.#onVisibilityChange = () => {
+ if (document.visibilityState !== "hidden") {
+ return;
+ }
+ resolve();
+ };
+ document.addEventListener("visibilitychange", this.#onVisibilityChange);
+ });
+ await Promise.race([this._onePageRenderedCapability.promise, visibilityChangePromise]);
+ document.removeEventListener("visibilitychange", this.#onVisibilityChange);
+ this.#onVisibilityChange = null;
+ }
+ async getAllText() {
+ const texts = [];
+ const buffer = [];
+ for (let pageNum = 1, pagesCount = this.pdfDocument.numPages; pageNum <= pagesCount; ++pageNum) {
+ if (this.#interruptCopyCondition) {
+ return null;
+ }
+ buffer.length = 0;
+ const page = await this.pdfDocument.getPage(pageNum);
+ const {
+ items
+ } = await page.getTextContent();
+ for (const item of items) {
+ if (item.str) {
+ buffer.push(item.str);
+ }
+ if (item.hasEOL) {
+ buffer.push("\n");
+ }
+ }
+ texts.push(removeNullCharacters(buffer.join("")));
+ }
+ return texts.join("\n");
+ }
+ #copyCallback(textLayerMode, event) {
+ const selection = document.getSelection();
+ const {
+ focusNode,
+ anchorNode
+ } = selection;
+ if (anchorNode && focusNode && selection.containsNode(this.#hiddenCopyElement)) {
+ if (this.#getAllTextInProgress || textLayerMode === TextLayerMode.ENABLE_PERMISSIONS) {
+ event.preventDefault();
+ event.stopPropagation();
+ return;
+ }
+ this.#getAllTextInProgress = true;
+ const savedCursor = this.container.style.cursor;
+ this.container.style.cursor = "wait";
+ const interruptCopy = ev => this.#interruptCopyCondition = ev.key === "Escape";
+ window.addEventListener("keydown", interruptCopy);
+ this.getAllText().then(async text => {
+ if (text !== null) {
+ await navigator.clipboard.writeText(text);
+ }
+ }).catch(reason => {
+ console.warn(`Something goes wrong when extracting the text: ${reason.message}`);
+ }).finally(() => {
+ this.#getAllTextInProgress = false;
+ this.#interruptCopyCondition = false;
+ window.removeEventListener("keydown", interruptCopy);
+ this.container.style.cursor = savedCursor;
+ });
+ event.preventDefault();
+ event.stopPropagation();
+ }
+ }
+ setDocument(pdfDocument) {
+ if (this.pdfDocument) {
+ this.eventBus.dispatch("pagesdestroy", {
+ source: this
+ });
+ this._cancelRendering();
+ this._resetView();
+ this.findController?.setDocument(null);
+ this._scriptingManager?.setDocument(null);
+ if (this.#annotationEditorUIManager) {
+ this.#annotationEditorUIManager.destroy();
+ this.#annotationEditorUIManager = null;
+ }
+ }
+ this.pdfDocument = pdfDocument;
+ if (!pdfDocument) {
+ return;
+ }
+ const pagesCount = pdfDocument.numPages;
+ const firstPagePromise = pdfDocument.getPage(1);
+ const optionalContentConfigPromise = pdfDocument.getOptionalContentConfig();
+ const permissionsPromise = this.#enablePermissions ? pdfDocument.getPermissions() : Promise.resolve();
+ if (pagesCount > PagesCountLimit.FORCE_SCROLL_MODE_PAGE) {
+ console.warn("Forcing PAGE-scrolling for performance reasons, given the length of the document.");
+ const mode = this._scrollMode = ScrollMode.PAGE;
+ this.eventBus.dispatch("scrollmodechanged", {
+ source: this,
+ mode
+ });
+ }
+ this._pagesCapability.promise.then(() => {
+ this.eventBus.dispatch("pagesloaded", {
+ source: this,
+ pagesCount
+ });
+ }, () => {});
+ this._onBeforeDraw = evt => {
+ const pageView = this._pages[evt.pageNumber - 1];
+ if (!pageView) {
+ return;
+ }
+ this.#buffer.push(pageView);
+ };
+ this.eventBus._on("pagerender", this._onBeforeDraw);
+ this._onAfterDraw = evt => {
+ if (evt.cssTransform || this._onePageRenderedCapability.settled) {
+ return;
+ }
+ this._onePageRenderedCapability.resolve({
+ timestamp: evt.timestamp
+ });
+ this.eventBus._off("pagerendered", this._onAfterDraw);
+ this._onAfterDraw = null;
+ };
+ this.eventBus._on("pagerendered", this._onAfterDraw);
+ Promise.all([firstPagePromise, permissionsPromise]).then(([firstPdfPage, permissions]) => {
+ if (pdfDocument !== this.pdfDocument) {
+ return;
+ }
+ this._firstPageCapability.resolve(firstPdfPage);
+ this._optionalContentConfigPromise = optionalContentConfigPromise;
+ const {
+ annotationEditorMode,
+ annotationMode,
+ textLayerMode
+ } = this.#initializePermissions(permissions);
+ if (textLayerMode !== TextLayerMode.DISABLE) {
+ const element = this.#hiddenCopyElement = document.createElement("div");
+ element.id = "hiddenCopyElement";
+ this.viewer.before(element);
+ }
+ if (annotationEditorMode !== AnnotationEditorType.DISABLE) {
+ const mode = annotationEditorMode;
+ if (pdfDocument.isPureXfa) {
+ console.warn("Warning: XFA-editing is not implemented.");
+ } else if (isValidAnnotationEditorMode(mode)) {
+ this.#annotationEditorUIManager = new AnnotationEditorUIManager(this.container, this.viewer, this.#altTextManager, this.eventBus, pdfDocument, this.pageColors, this.#annotationEditorHighlightColors, this.#mlManager);
+ this.eventBus.dispatch("annotationeditoruimanager", {
+ source: this,
+ uiManager: this.#annotationEditorUIManager
+ });
+ if (mode !== AnnotationEditorType.NONE) {
+ this.#annotationEditorUIManager.updateMode(mode);
+ }
+ } else {
+ console.error(`Invalid AnnotationEditor mode: ${mode}`);
+ }
+ }
+ const viewerElement = this._scrollMode === ScrollMode.PAGE ? null : this.viewer;
+ const scale = this.currentScale;
+ const viewport = firstPdfPage.getViewport({
+ scale: scale * PixelsPerInch.PDF_TO_CSS_UNITS
+ });
+ this.viewer.style.setProperty("--scale-factor", viewport.scale);
+ if (this.pageColors?.foreground === "CanvasText" || this.pageColors?.background === "Canvas") {
+ this.viewer.style.setProperty("--hcm-highlight-filter", pdfDocument.filterFactory.addHighlightHCMFilter("highlight", "CanvasText", "Canvas", "HighlightText", "Highlight"));
+ this.viewer.style.setProperty("--hcm-highlight-selected-filter", pdfDocument.filterFactory.addHighlightHCMFilter("highlight_selected", "CanvasText", "Canvas", "HighlightText", "ButtonText"));
+ }
+ for (let pageNum = 1; pageNum <= pagesCount; ++pageNum) {
+ const pageView = new PDFPageView({
+ container: viewerElement,
+ eventBus: this.eventBus,
+ id: pageNum,
+ scale,
+ defaultViewport: viewport.clone(),
+ optionalContentConfigPromise,
+ renderingQueue: this.renderingQueue,
+ textLayerMode,
+ annotationMode,
+ imageResourcesPath: this.imageResourcesPath,
+ maxCanvasPixels: this.maxCanvasPixels,
+ pageColors: this.pageColors,
+ l10n: this.l10n,
+ layerProperties: this._layerProperties
+ });
+ this._pages.push(pageView);
+ }
+ const firstPageView = this._pages[0];
+ if (firstPageView) {
+ firstPageView.setPdfPage(firstPdfPage);
+ this.linkService.cachePageRef(1, firstPdfPage.ref);
+ }
+ if (this._scrollMode === ScrollMode.PAGE) {
+ this.#ensurePageViewVisible();
+ } else if (this._spreadMode !== SpreadMode.NONE) {
+ this._updateSpreadMode();
+ }
+ this.#onePageRenderedOrForceFetch().then(async () => {
+ this.findController?.setDocument(pdfDocument);
+ this._scriptingManager?.setDocument(pdfDocument);
+ if (this.#hiddenCopyElement) {
+ this.#copyCallbackBound = this.#copyCallback.bind(this, textLayerMode);
+ document.addEventListener("copy", this.#copyCallbackBound);
+ }
+ if (this.#annotationEditorUIManager) {
+ this.eventBus.dispatch("annotationeditormodechanged", {
+ source: this,
+ mode: this.#annotationEditorMode
+ });
+ }
+ if (pdfDocument.loadingParams.disableAutoFetch || pagesCount > PagesCountLimit.FORCE_LAZY_PAGE_INIT) {
+ this._pagesCapability.resolve();
+ return;
+ }
+ let getPagesLeft = pagesCount - 1;
+ if (getPagesLeft <= 0) {
+ this._pagesCapability.resolve();
+ return;
+ }
+ for (let pageNum = 2; pageNum <= pagesCount; ++pageNum) {
+ const promise = pdfDocument.getPage(pageNum).then(pdfPage => {
+ const pageView = this._pages[pageNum - 1];
+ if (!pageView.pdfPage) {
+ pageView.setPdfPage(pdfPage);
+ }
+ this.linkService.cachePageRef(pageNum, pdfPage.ref);
+ if (--getPagesLeft === 0) {
+ this._pagesCapability.resolve();
+ }
+ }, reason => {
+ console.error(`Unable to get page ${pageNum} to initialize viewer`, reason);
+ if (--getPagesLeft === 0) {
+ this._pagesCapability.resolve();
+ }
+ });
+ if (pageNum % PagesCountLimit.PAUSE_EAGER_PAGE_INIT === 0) {
+ await promise;
+ }
+ }
+ });
+ this.eventBus.dispatch("pagesinit", {
+ source: this
+ });
+ pdfDocument.getMetadata().then(({
+ info
+ }) => {
+ if (pdfDocument !== this.pdfDocument) {
+ return;
+ }
+ if (info.Language) {
+ this.viewer.lang = info.Language;
+ }
+ });
+ if (this.defaultRenderingQueue) {
+ this.update();
+ }
+ }).catch(reason => {
+ console.error("Unable to initialize viewer", reason);
+ this._pagesCapability.reject(reason);
+ });
+ }
+ setPageLabels(labels) {
+ if (!this.pdfDocument) {
+ return;
+ }
+ if (!labels) {
+ this._pageLabels = null;
+ } else if (!(Array.isArray(labels) && this.pdfDocument.numPages === labels.length)) {
+ this._pageLabels = null;
+ console.error(`setPageLabels: Invalid page labels.`);
+ } else {
+ this._pageLabels = labels;
+ }
+ for (let i = 0, ii = this._pages.length; i < ii; i++) {
+ this._pages[i].setPageLabel(this._pageLabels?.[i] ?? null);
+ }
+ }
+ _resetView() {
+ this._pages = [];
+ this._currentPageNumber = 1;
+ this._currentScale = UNKNOWN_SCALE;
+ this._currentScaleValue = null;
+ this._pageLabels = null;
+ this.#buffer = new PDFPageViewBuffer(DEFAULT_CACHE_SIZE);
+ this._location = null;
+ this._pagesRotation = 0;
+ this._optionalContentConfigPromise = null;
+ this._firstPageCapability = new PromiseCapability();
+ this._onePageRenderedCapability = new PromiseCapability();
+ this._pagesCapability = new PromiseCapability();
+ this._scrollMode = ScrollMode.VERTICAL;
+ this._previousScrollMode = ScrollMode.UNKNOWN;
+ this._spreadMode = SpreadMode.NONE;
+ this.#scrollModePageState = {
+ previousPageNumber: 1,
+ scrollDown: true,
+ pages: []
+ };
+ if (this._onBeforeDraw) {
+ this.eventBus._off("pagerender", this._onBeforeDraw);
+ this._onBeforeDraw = null;
+ }
+ if (this._onAfterDraw) {
+ this.eventBus._off("pagerendered", this._onAfterDraw);
+ this._onAfterDraw = null;
+ }
+ if (this.#onVisibilityChange) {
+ document.removeEventListener("visibilitychange", this.#onVisibilityChange);
+ this.#onVisibilityChange = null;
+ }
+ this.viewer.textContent = "";
+ this._updateScrollMode();
+ this.viewer.removeAttribute("lang");
+ if (this.#hiddenCopyElement) {
+ document.removeEventListener("copy", this.#copyCallbackBound);
+ this.#copyCallbackBound = null;
+ this.#hiddenCopyElement.remove();
+ this.#hiddenCopyElement = null;
+ }
+ }
+ #ensurePageViewVisible() {
+ if (this._scrollMode !== ScrollMode.PAGE) {
+ throw new Error("#ensurePageViewVisible: Invalid scrollMode value.");
+ }
+ const pageNumber = this._currentPageNumber,
+ state = this.#scrollModePageState,
+ viewer = this.viewer;
+ viewer.textContent = "";
+ state.pages.length = 0;
+ if (this._spreadMode === SpreadMode.NONE && !this.isInPresentationMode) {
+ const pageView = this._pages[pageNumber - 1];
+ viewer.append(pageView.div);
+ state.pages.push(pageView);
+ } else {
+ const pageIndexSet = new Set(),
+ parity = this._spreadMode - 1;
+ if (parity === -1) {
+ pageIndexSet.add(pageNumber - 1);
+ } else if (pageNumber % 2 !== parity) {
+ pageIndexSet.add(pageNumber - 1);
+ pageIndexSet.add(pageNumber);
+ } else {
+ pageIndexSet.add(pageNumber - 2);
+ pageIndexSet.add(pageNumber - 1);
+ }
+ const spread = document.createElement("div");
+ spread.className = "spread";
+ if (this.isInPresentationMode) {
+ const dummyPage = document.createElement("div");
+ dummyPage.className = "dummyPage";
+ spread.append(dummyPage);
+ }
+ for (const i of pageIndexSet) {
+ const pageView = this._pages[i];
+ if (!pageView) {
+ continue;
+ }
+ spread.append(pageView.div);
+ state.pages.push(pageView);
+ }
+ viewer.append(spread);
+ }
+ state.scrollDown = pageNumber >= state.previousPageNumber;
+ state.previousPageNumber = pageNumber;
+ }
+ _scrollUpdate() {
+ if (this.pagesCount === 0) {
+ return;
+ }
+ this.update();
+ }
+ #scrollIntoView(pageView, pageSpot = null) {
+ const {
+ div,
+ id
+ } = pageView;
+ if (this._currentPageNumber !== id) {
+ this._setCurrentPageNumber(id);
+ }
+ if (this._scrollMode === ScrollMode.PAGE) {
+ this.#ensurePageViewVisible();
+ this.update();
+ }
+ if (!pageSpot && !this.isInPresentationMode) {
+ const left = div.offsetLeft + div.clientLeft,
+ right = left + div.clientWidth;
+ const {
+ scrollLeft,
+ clientWidth
+ } = this.container;
+ if (this._scrollMode === ScrollMode.HORIZONTAL || left < scrollLeft || right > scrollLeft + clientWidth) {
+ pageSpot = {
+ left: 0,
+ top: 0
+ };
+ }
+ }
+ scrollIntoView(div, pageSpot);
+ if (!this._currentScaleValue && this._location) {
+ this._location = null;
+ }
+ }
+ #isSameScale(newScale) {
+ return newScale === this._currentScale || Math.abs(newScale - this._currentScale) < 1e-15;
+ }
+ #setScaleUpdatePages(newScale, newValue, {
+ noScroll = false,
+ preset = false,
+ drawingDelay = -1
+ }) {
+ this._currentScaleValue = newValue.toString();
+ if (this.#isSameScale(newScale)) {
+ if (preset) {
+ this.eventBus.dispatch("scalechanging", {
+ source: this,
+ scale: newScale,
+ presetValue: newValue
+ });
+ }
+ return;
+ }
+ this.viewer.style.setProperty("--scale-factor", newScale * PixelsPerInch.PDF_TO_CSS_UNITS);
+ const postponeDrawing = drawingDelay >= 0 && drawingDelay < 1000;
+ this.refresh(true, {
+ scale: newScale,
+ drawingDelay: postponeDrawing ? drawingDelay : -1
+ });
+ if (postponeDrawing) {
+ this.#scaleTimeoutId = setTimeout(() => {
+ this.#scaleTimeoutId = null;
+ this.refresh();
+ }, drawingDelay);
+ }
+ this._currentScale = newScale;
+ if (!noScroll) {
+ let page = this._currentPageNumber,
+ dest;
+ if (this._location && !(this.isInPresentationMode || this.isChangingPresentationMode)) {
+ page = this._location.pageNumber;
+ dest = [null, {
+ name: "XYZ"
+ }, this._location.left, this._location.top, null];
+ }
+ this.scrollPageIntoView({
+ pageNumber: page,
+ destArray: dest,
+ allowNegativeOffset: true
+ });
+ }
+ this.eventBus.dispatch("scalechanging", {
+ source: this,
+ scale: newScale,
+ presetValue: preset ? newValue : undefined
+ });
+ if (this.defaultRenderingQueue) {
+ this.update();
+ }
+ }
+ get #pageWidthScaleFactor() {
+ if (this._spreadMode !== SpreadMode.NONE && this._scrollMode !== ScrollMode.HORIZONTAL) {
+ return 2;
+ }
+ return 1;
+ }
+ #setScale(value, options) {
+ let scale = parseFloat(value);
+ if (scale > 0) {
+ options.preset = false;
+ this.#setScaleUpdatePages(scale, value, options);
+ } else {
+ const currentPage = this._pages[this._currentPageNumber - 1];
+ if (!currentPage) {
+ return;
+ }
+ let hPadding = SCROLLBAR_PADDING,
+ vPadding = VERTICAL_PADDING;
+ if (this.isInPresentationMode) {
+ hPadding = vPadding = 4;
+ if (this._spreadMode !== SpreadMode.NONE) {
+ hPadding *= 2;
+ }
+ } else if (this._scrollMode === ScrollMode.HORIZONTAL) {
+ [hPadding, vPadding] = [vPadding, hPadding];
+ }
+ const pageWidthScale = (this.container.clientWidth - hPadding) / currentPage.width * currentPage.scale / this.#pageWidthScaleFactor;
+ const pageHeightScale = (this.container.clientHeight - vPadding) / currentPage.height * currentPage.scale;
+ switch (value) {
+ case "page-actual":
+ scale = 1;
+ break;
+ case "page-width":
+ scale = pageWidthScale;
+ break;
+ case "page-height":
+ scale = pageHeightScale;
+ break;
+ case "page-fit":
+ scale = Math.min(pageWidthScale, pageHeightScale);
+ break;
+ case "auto":
+ const horizontalScale = isPortraitOrientation(currentPage) ? pageWidthScale : Math.min(pageHeightScale, pageWidthScale);
+ scale = Math.min(MAX_AUTO_SCALE, horizontalScale);
+ break;
+ default:
+ console.error(`#setScale: "${value}" is an unknown zoom value.`);
+ return;
+ }
+ options.preset = true;
+ this.#setScaleUpdatePages(scale, value, options);
+ }
+ }
+ #resetCurrentPageView() {
+ const pageView = this._pages[this._currentPageNumber - 1];
+ if (this.isInPresentationMode) {
+ this.#setScale(this._currentScaleValue, {
+ noScroll: true
+ });
+ }
+ this.#scrollIntoView(pageView);
+ }
+ pageLabelToPageNumber(label) {
+ if (!this._pageLabels) {
+ return null;
+ }
+ const i = this._pageLabels.indexOf(label);
+ if (i < 0) {
+ return null;
+ }
+ return i + 1;
+ }
+ scrollPageIntoView({
+ pageNumber,
+ destArray = null,
+ allowNegativeOffset = false,
+ ignoreDestinationZoom = false
+ }) {
+ if (!this.pdfDocument) {
+ return;
+ }
+ const pageView = Number.isInteger(pageNumber) && this._pages[pageNumber - 1];
+ if (!pageView) {
+ console.error(`scrollPageIntoView: "${pageNumber}" is not a valid pageNumber parameter.`);
+ return;
+ }
+ if (this.isInPresentationMode || !destArray) {
+ this._setCurrentPageNumber(pageNumber, true);
+ return;
+ }
+ let x = 0,
+ y = 0;
+ let width = 0,
+ height = 0,
+ widthScale,
+ heightScale;
+ const changeOrientation = pageView.rotation % 180 !== 0;
+ const pageWidth = (changeOrientation ? pageView.height : pageView.width) / pageView.scale / PixelsPerInch.PDF_TO_CSS_UNITS;
+ const pageHeight = (changeOrientation ? pageView.width : pageView.height) / pageView.scale / PixelsPerInch.PDF_TO_CSS_UNITS;
+ let scale = 0;
+ switch (destArray[1].name) {
+ case "XYZ":
+ x = destArray[2];
+ y = destArray[3];
+ scale = destArray[4];
+ x = x !== null ? x : 0;
+ y = y !== null ? y : pageHeight;
+ break;
+ case "Fit":
+ case "FitB":
+ scale = "page-fit";
+ break;
+ case "FitH":
+ case "FitBH":
+ y = destArray[2];
+ scale = "page-width";
+ if (y === null && this._location) {
+ x = this._location.left;
+ y = this._location.top;
+ } else if (typeof y !== "number" || y < 0) {
+ y = pageHeight;
+ }
+ break;
+ case "FitV":
+ case "FitBV":
+ x = destArray[2];
+ width = pageWidth;
+ height = pageHeight;
+ scale = "page-height";
+ break;
+ case "FitR":
+ x = destArray[2];
+ y = destArray[3];
+ width = destArray[4] - x;
+ height = destArray[5] - y;
+ let hPadding = SCROLLBAR_PADDING,
+ vPadding = VERTICAL_PADDING;
+ widthScale = (this.container.clientWidth - hPadding) / width / PixelsPerInch.PDF_TO_CSS_UNITS;
+ heightScale = (this.container.clientHeight - vPadding) / height / PixelsPerInch.PDF_TO_CSS_UNITS;
+ scale = Math.min(Math.abs(widthScale), Math.abs(heightScale));
+ break;
+ default:
+ console.error(`scrollPageIntoView: "${destArray[1].name}" is not a valid destination type.`);
+ return;
+ }
+ if (!ignoreDestinationZoom) {
+ if (scale && scale !== this._currentScale) {
+ this.currentScaleValue = scale;
+ } else if (this._currentScale === UNKNOWN_SCALE) {
+ this.currentScaleValue = DEFAULT_SCALE_VALUE;
+ }
+ }
+ if (scale === "page-fit" && !destArray[4]) {
+ this.#scrollIntoView(pageView);
+ return;
+ }
+ const boundingRect = [pageView.viewport.convertToViewportPoint(x, y), pageView.viewport.convertToViewportPoint(x + width, y + height)];
+ let left = Math.min(boundingRect[0][0], boundingRect[1][0]);
+ let top = Math.min(boundingRect[0][1], boundingRect[1][1]);
+ if (!allowNegativeOffset) {
+ left = Math.max(left, 0);
+ top = Math.max(top, 0);
+ }
+ this.#scrollIntoView(pageView, {
+ left,
+ top
+ });
+ }
+ _updateLocation(firstPage) {
+ const currentScale = this._currentScale;
+ const currentScaleValue = this._currentScaleValue;
+ const normalizedScaleValue = parseFloat(currentScaleValue) === currentScale ? Math.round(currentScale * 10000) / 100 : currentScaleValue;
+ const pageNumber = firstPage.id;
+ const currentPageView = this._pages[pageNumber - 1];
+ const container = this.container;
+ const topLeft = currentPageView.getPagePoint(container.scrollLeft - firstPage.x, container.scrollTop - firstPage.y);
+ const intLeft = Math.round(topLeft[0]);
+ const intTop = Math.round(topLeft[1]);
+ let pdfOpenParams = `#page=${pageNumber}`;
+ if (!this.isInPresentationMode) {
+ pdfOpenParams += `&zoom=${normalizedScaleValue},${intLeft},${intTop}`;
+ }
+ this._location = {
+ pageNumber,
+ scale: normalizedScaleValue,
+ top: intTop,
+ left: intLeft,
+ rotation: this._pagesRotation,
+ pdfOpenParams
+ };
+ }
+ update() {
+ const visible = this._getVisiblePages();
+ const visiblePages = visible.views,
+ numVisiblePages = visiblePages.length;
+ if (numVisiblePages === 0) {
+ return;
+ }
+ const newCacheSize = Math.max(DEFAULT_CACHE_SIZE, 2 * numVisiblePages + 1);
+ this.#buffer.resize(newCacheSize, visible.ids);
+ this.renderingQueue.renderHighestPriority(visible);
+ const isSimpleLayout = this._spreadMode === SpreadMode.NONE && (this._scrollMode === ScrollMode.PAGE || this._scrollMode === ScrollMode.VERTICAL);
+ const currentId = this._currentPageNumber;
+ let stillFullyVisible = false;
+ for (const page of visiblePages) {
+ if (page.percent < 100) {
+ break;
+ }
+ if (page.id === currentId && isSimpleLayout) {
+ stillFullyVisible = true;
+ break;
+ }
+ }
+ this._setCurrentPageNumber(stillFullyVisible ? currentId : visiblePages[0].id);
+ this._updateLocation(visible.first);
+ this.eventBus.dispatch("updateviewarea", {
+ source: this,
+ location: this._location
+ });
+ }
+ containsElement(element) {
+ return this.container.contains(element);
+ }
+ focus() {
+ this.container.focus();
+ }
+ get _isContainerRtl() {
+ return getComputedStyle(this.container).direction === "rtl";
+ }
+ get isInPresentationMode() {
+ return this.presentationModeState === PresentationModeState.FULLSCREEN;
+ }
+ get isChangingPresentationMode() {
+ return this.presentationModeState === PresentationModeState.CHANGING;
+ }
+ get isHorizontalScrollbarEnabled() {
+ return this.isInPresentationMode ? false : this.container.scrollWidth > this.container.clientWidth;
+ }
+ get isVerticalScrollbarEnabled() {
+ return this.isInPresentationMode ? false : this.container.scrollHeight > this.container.clientHeight;
+ }
+ _getVisiblePages() {
+ const views = this._scrollMode === ScrollMode.PAGE ? this.#scrollModePageState.pages : this._pages,
+ horizontal = this._scrollMode === ScrollMode.HORIZONTAL,
+ rtl = horizontal && this._isContainerRtl;
+ return getVisibleElements({
+ scrollEl: this.container,
+ views,
+ sortByVisibility: true,
+ horizontal,
+ rtl
+ });
+ }
+ cleanup() {
+ for (const pageView of this._pages) {
+ if (pageView.renderingState !== RenderingStates.FINISHED) {
+ pageView.reset();
+ }
+ }
+ }
+ _cancelRendering() {
+ for (const pageView of this._pages) {
+ pageView.cancelRendering();
+ }
+ }
+ async #ensurePdfPageLoaded(pageView) {
+ if (pageView.pdfPage) {
+ return pageView.pdfPage;
+ }
+ try {
+ const pdfPage = await this.pdfDocument.getPage(pageView.id);
+ if (!pageView.pdfPage) {
+ pageView.setPdfPage(pdfPage);
+ }
+ if (!this.linkService._cachedPageNumber?.(pdfPage.ref)) {
+ this.linkService.cachePageRef(pageView.id, pdfPage.ref);
+ }
+ return pdfPage;
+ } catch (reason) {
+ console.error("Unable to get page for page view", reason);
+ return null;
+ }
+ }
+ #getScrollAhead(visible) {
+ if (visible.first?.id === 1) {
+ return true;
+ } else if (visible.last?.id === this.pagesCount) {
+ return false;
+ }
+ switch (this._scrollMode) {
+ case ScrollMode.PAGE:
+ return this.#scrollModePageState.scrollDown;
+ case ScrollMode.HORIZONTAL:
+ return this.scroll.right;
+ }
+ return this.scroll.down;
+ }
+ forceRendering(currentlyVisiblePages) {
+ const visiblePages = currentlyVisiblePages || this._getVisiblePages();
+ const scrollAhead = this.#getScrollAhead(visiblePages);
+ const preRenderExtra = this._spreadMode !== SpreadMode.NONE && this._scrollMode !== ScrollMode.HORIZONTAL;
+ const pageView = this.renderingQueue.getHighestPriority(visiblePages, this._pages, scrollAhead, preRenderExtra);
+ if (pageView) {
+ this.#ensurePdfPageLoaded(pageView).then(() => {
+ this.renderingQueue.renderView(pageView);
+ });
+ return true;
+ }
+ return false;
+ }
+ get hasEqualPageSizes() {
+ const firstPageView = this._pages[0];
+ for (let i = 1, ii = this._pages.length; i < ii; ++i) {
+ const pageView = this._pages[i];
+ if (pageView.width !== firstPageView.width || pageView.height !== firstPageView.height) {
+ return false;
+ }
+ }
+ return true;
+ }
+ getPagesOverview() {
+ let initialOrientation;
+ return this._pages.map(pageView => {
+ const viewport = pageView.pdfPage.getViewport({
+ scale: 1
+ });
+ const orientation = isPortraitOrientation(viewport);
+ if (initialOrientation === undefined) {
+ initialOrientation = orientation;
+ } else if (this.enablePrintAutoRotate && orientation !== initialOrientation) {
+ return {
+ width: viewport.height,
+ height: viewport.width,
+ rotation: (viewport.rotation - 90) % 360
+ };
+ }
+ return {
+ width: viewport.width,
+ height: viewport.height,
+ rotation: viewport.rotation
+ };
+ });
+ }
+ get optionalContentConfigPromise() {
+ if (!this.pdfDocument) {
+ return Promise.resolve(null);
+ }
+ if (!this._optionalContentConfigPromise) {
+ console.error("optionalContentConfigPromise: Not initialized yet.");
+ return this.pdfDocument.getOptionalContentConfig();
+ }
+ return this._optionalContentConfigPromise;
+ }
+ set optionalContentConfigPromise(promise) {
+ if (!(promise instanceof Promise)) {
+ throw new Error(`Invalid optionalContentConfigPromise: ${promise}`);
+ }
+ if (!this.pdfDocument) {
+ return;
+ }
+ if (!this._optionalContentConfigPromise) {
+ return;
+ }
+ this._optionalContentConfigPromise = promise;
+ this.refresh(false, {
+ optionalContentConfigPromise: promise
+ });
+ this.eventBus.dispatch("optionalcontentconfigchanged", {
+ source: this,
+ promise
+ });
+ }
+ get scrollMode() {
+ return this._scrollMode;
+ }
+ set scrollMode(mode) {}
+ _updateScrollMode(pageNumber = null) {
+ const scrollMode = this._scrollMode,
+ viewer = this.viewer;
+ viewer.classList.toggle("scrollHorizontal", scrollMode === ScrollMode.HORIZONTAL);
+ viewer.classList.toggle("scrollWrapped", scrollMode === ScrollMode.WRAPPED);
+ if (!this.pdfDocument || !pageNumber) {
+ return;
+ }
+ if (scrollMode === ScrollMode.PAGE) {
+ this.#ensurePageViewVisible();
+ } else if (this._previousScrollMode === ScrollMode.PAGE) {
+ this._updateSpreadMode();
+ }
+ if (this._currentScaleValue && isNaN(this._currentScaleValue)) {
+ this.#setScale(this._currentScaleValue, {
+ noScroll: true
+ });
+ }
+ this._setCurrentPageNumber(pageNumber, true);
+ this.update();
+ }
+ get spreadMode() {
+ return this._spreadMode;
+ }
+ set spreadMode(mode) {}
+ _updateSpreadMode(pageNumber = null) {
+ if (!this.pdfDocument) {
+ return;
+ }
+ const viewer = this.viewer,
+ pages = this._pages;
+ if (this._scrollMode === ScrollMode.PAGE) {
+ this.#ensurePageViewVisible();
+ } else {
+ viewer.textContent = "";
+ if (this._spreadMode === SpreadMode.NONE) {
+ for (const pageView of this._pages) {
+ viewer.append(pageView.div);
+ }
+ } else {
+ const parity = this._spreadMode - 1;
+ let spread = null;
+ for (let i = 0, ii = pages.length; i < ii; ++i) {
+ if (spread === null) {
+ spread = document.createElement("div");
+ spread.className = "spread";
+ viewer.append(spread);
+ } else if (i % 2 === parity) {
+ spread = spread.cloneNode(false);
+ viewer.append(spread);
+ }
+ spread.append(pages[i].div);
+ }
+ }
+ }
+ if (!pageNumber) {
+ return;
+ }
+ if (this._currentScaleValue && isNaN(this._currentScaleValue)) {
+ this.#setScale(this._currentScaleValue, {
+ noScroll: true
+ });
+ }
+ this._setCurrentPageNumber(pageNumber, true);
+ this.update();
+ }
+ _getPageAdvance(currentPageNumber, previous = false) {
+ switch (this._scrollMode) {
+ case ScrollMode.WRAPPED:
+ {
+ const {
+ views
+ } = this._getVisiblePages(),
+ pageLayout = new Map();
+ for (const {
+ id,
+ y,
+ percent,
+ widthPercent
+ } of views) {
+ if (percent === 0 || widthPercent < 100) {
+ continue;
+ }
+ let yArray = pageLayout.get(y);
+ if (!yArray) {
+ pageLayout.set(y, yArray ||= []);
+ }
+ yArray.push(id);
+ }
+ for (const yArray of pageLayout.values()) {
+ const currentIndex = yArray.indexOf(currentPageNumber);
+ if (currentIndex === -1) {
+ continue;
+ }
+ const numPages = yArray.length;
+ if (numPages === 1) {
+ break;
+ }
+ if (previous) {
+ for (let i = currentIndex - 1, ii = 0; i >= ii; i--) {
+ const currentId = yArray[i],
+ expectedId = yArray[i + 1] - 1;
+ if (currentId < expectedId) {
+ return currentPageNumber - expectedId;
+ }
+ }
+ } else {
+ for (let i = currentIndex + 1, ii = numPages; i < ii; i++) {
+ const currentId = yArray[i],
+ expectedId = yArray[i - 1] + 1;
+ if (currentId > expectedId) {
+ return expectedId - currentPageNumber;
+ }
+ }
+ }
+ if (previous) {
+ const firstId = yArray[0];
+ if (firstId < currentPageNumber) {
+ return currentPageNumber - firstId + 1;
+ }
+ } else {
+ const lastId = yArray[numPages - 1];
+ if (lastId > currentPageNumber) {
+ return lastId - currentPageNumber + 1;
+ }
+ }
+ break;
+ }
+ break;
+ }
+ case ScrollMode.HORIZONTAL:
+ {
+ break;
+ }
+ case ScrollMode.PAGE:
+ case ScrollMode.VERTICAL:
+ {
+ if (this._spreadMode === SpreadMode.NONE) {
+ break;
+ }
+ const parity = this._spreadMode - 1;
+ if (previous && currentPageNumber % 2 !== parity) {
+ break;
+ } else if (!previous && currentPageNumber % 2 === parity) {
+ break;
+ }
+ const {
+ views
+ } = this._getVisiblePages(),
+ expectedId = previous ? currentPageNumber - 1 : currentPageNumber + 1;
+ for (const {
+ id,
+ percent,
+ widthPercent
+ } of views) {
+ if (id !== expectedId) {
+ continue;
+ }
+ if (percent > 0 && widthPercent === 100) {
+ return 2;
+ }
+ break;
+ }
+ break;
+ }
+ }
+ return 1;
+ }
+ nextPage() {
+ const currentPageNumber = this._currentPageNumber,
+ pagesCount = this.pagesCount;
+ if (currentPageNumber >= pagesCount) {
+ return false;
+ }
+ const advance = this._getPageAdvance(currentPageNumber, false) || 1;
+ this.currentPageNumber = Math.min(currentPageNumber + advance, pagesCount);
+ return true;
+ }
+ previousPage() {
+ const currentPageNumber = this._currentPageNumber;
+ if (currentPageNumber <= 1) {
+ return false;
+ }
+ const advance = this._getPageAdvance(currentPageNumber, true) || 1;
+ this.currentPageNumber = Math.max(currentPageNumber - advance, 1);
+ return true;
+ }
+ increaseScale({
+ drawingDelay,
+ scaleFactor,
+ steps
+ } = {}) {
+ if (!this.pdfDocument) {
+ return;
+ }
+ let newScale = this._currentScale;
+ if (scaleFactor > 1) {
+ newScale = Math.round(newScale * scaleFactor * 100) / 100;
+ } else {
+ steps ??= 1;
+ do {
+ newScale = Math.ceil((newScale * DEFAULT_SCALE_DELTA).toFixed(2) * 10) / 10;
+ } while (--steps > 0 && newScale < MAX_SCALE);
+ }
+ this.#setScale(Math.min(MAX_SCALE, newScale), {
+ noScroll: false,
+ drawingDelay
+ });
+ }
+ decreaseScale({
+ drawingDelay,
+ scaleFactor,
+ steps
+ } = {}) {
+ if (!this.pdfDocument) {
+ return;
+ }
+ let newScale = this._currentScale;
+ if (scaleFactor > 0 && scaleFactor < 1) {
+ newScale = Math.round(newScale * scaleFactor * 100) / 100;
+ } else {
+ steps ??= 1;
+ do {
+ newScale = Math.floor((newScale / DEFAULT_SCALE_DELTA).toFixed(2) * 10) / 10;
+ } while (--steps > 0 && newScale > MIN_SCALE);
+ }
+ this.#setScale(Math.max(MIN_SCALE, newScale), {
+ noScroll: false,
+ drawingDelay
+ });
+ }
+ #updateContainerHeightCss(height = this.container.clientHeight) {
+ if (height !== this.#previousContainerHeight) {
+ this.#previousContainerHeight = height;
+ docStyle.setProperty("--viewer-container-height", `${height}px`);
+ }
+ }
+ #resizeObserverCallback(entries) {
+ for (const entry of entries) {
+ if (entry.target === this.container) {
+ this.#updateContainerHeightCss(Math.floor(entry.borderBoxSize[0].blockSize));
+ this.#containerTopLeft = null;
+ break;
+ }
+ }
+ }
+ get containerTopLeft() {
+ return this.#containerTopLeft ||= [this.container.offsetTop, this.container.offsetLeft];
+ }
+ get annotationEditorMode() {
+ return this.#annotationEditorUIManager ? this.#annotationEditorMode : AnnotationEditorType.DISABLE;
+ }
+ set annotationEditorMode({
+ mode,
+ editId = null,
+ isFromKeyboard = false
+ }) {
+ if (!this.#annotationEditorUIManager) {
+ throw new Error(`The AnnotationEditor is not enabled.`);
+ }
+ if (this.#annotationEditorMode === mode) {
+ return;
+ }
+ if (!isValidAnnotationEditorMode(mode)) {
+ throw new Error(`Invalid AnnotationEditor mode: ${mode}`);
+ }
+ if (!this.pdfDocument) {
+ return;
+ }
+ this.#annotationEditorMode = mode;
+ this.eventBus.dispatch("annotationeditormodechanged", {
+ source: this,
+ mode
+ });
+ this.#annotationEditorUIManager.updateMode(mode, editId, isFromKeyboard);
+ }
+ set annotationEditorParams({
+ type,
+ value
+ }) {
+ if (!this.#annotationEditorUIManager) {
+ throw new Error(`The AnnotationEditor is not enabled.`);
+ }
+ this.#annotationEditorUIManager.updateParams(type, value);
+ }
+ refresh(noUpdate = false, updateArgs = Object.create(null)) {
+ if (!this.pdfDocument) {
+ return;
+ }
+ for (const pageView of this._pages) {
+ pageView.update(updateArgs);
+ }
+ if (this.#scaleTimeoutId !== null) {
+ clearTimeout(this.#scaleTimeoutId);
+ this.#scaleTimeoutId = null;
+ }
+ if (!noUpdate) {
+ this.update();
+ }
+ }
+}
+
+;// CONCATENATED MODULE: ./web/toolbar-geckoview.js
+class Toolbar {
+ #buttons;
+ #eventBus;
+ constructor(options, eventBus, nimbusData) {
+ this.#eventBus = eventBus;
+ const buttons = [{
+ element: options.download,
+ eventName: "download",
+ nimbusName: "download-button"
+ }, {
+ element: options.openInApp,
+ eventName: "openinexternalapp",
+ nimbusName: "open-in-app-button"
+ }];
+ if (nimbusData) {
+ this.#buttons = [];
+ for (const button of buttons) {
+ if (nimbusData[button.nimbusName]) {
+ this.#buttons.push(button);
+ } else {
+ button.element.remove();
+ }
+ }
+ if (this.#buttons.length > 0) {
+ options.container.classList.add("show");
+ } else {
+ options.container.remove();
+ options.mainContainer.classList.add("noToolbar");
+ }
+ } else {
+ options.container.classList.add("show");
+ this.#buttons = buttons;
+ }
+ this.#bindListeners(options);
+ }
+ setPageNumber(pageNumber, pageLabel) {}
+ setPagesCount(pagesCount, hasPageLabels) {}
+ setPageScale(pageScaleValue, pageScale) {}
+ reset() {}
+ #bindListeners(options) {
+ for (const {
+ element,
+ eventName,
+ eventDetails
+ } of this.#buttons) {
+ element.addEventListener("click", evt => {
+ if (eventName !== null) {
+ this.#eventBus.dispatch(eventName, {
+ source: this,
+ ...eventDetails
+ });
+ this.#eventBus.dispatch("reporttelemetry", {
+ source: this,
+ details: {
+ type: "gv-buttons",
+ data: {
+ id: `${element.id}_tapped`
+ }
+ }
+ });
+ }
+ });
+ }
+ }
+ updateLoadingIndicatorState(loading = false) {}
+}
+
+;// CONCATENATED MODULE: ./web/view_history.js
+const DEFAULT_VIEW_HISTORY_CACHE_SIZE = 20;
+class ViewHistory {
+ constructor(fingerprint, cacheSize = DEFAULT_VIEW_HISTORY_CACHE_SIZE) {
+ this.fingerprint = fingerprint;
+ this.cacheSize = cacheSize;
+ this._initializedPromise = this._readFromStorage().then(databaseStr => {
+ const database = JSON.parse(databaseStr || "{}");
+ let index = -1;
+ if (!Array.isArray(database.files)) {
+ database.files = [];
+ } else {
+ while (database.files.length >= this.cacheSize) {
+ database.files.shift();
+ }
+ for (let i = 0, ii = database.files.length; i < ii; i++) {
+ const branch = database.files[i];
+ if (branch.fingerprint === this.fingerprint) {
+ index = i;
+ break;
+ }
+ }
+ }
+ if (index === -1) {
+ index = database.files.push({
+ fingerprint: this.fingerprint
+ }) - 1;
+ }
+ this.file = database.files[index];
+ this.database = database;
+ });
+ }
+ async _writeToStorage() {
+ const databaseStr = JSON.stringify(this.database);
+ sessionStorage.setItem("pdfjs.history", databaseStr);
+ }
+ async _readFromStorage() {
+ return sessionStorage.getItem("pdfjs.history");
+ }
+ async set(name, val) {
+ await this._initializedPromise;
+ this.file[name] = val;
+ return this._writeToStorage();
+ }
+ async setMultiple(properties) {
+ await this._initializedPromise;
+ for (const name in properties) {
+ this.file[name] = properties[name];
+ }
+ return this._writeToStorage();
+ }
+ async get(name, defaultValue) {
+ await this._initializedPromise;
+ const val = this.file[name];
+ return val !== undefined ? val : defaultValue;
+ }
+ async getMultiple(properties) {
+ await this._initializedPromise;
+ const values = Object.create(null);
+ for (const name in properties) {
+ const val = this.file[name];
+ values[name] = val !== undefined ? val : properties[name];
+ }
+ return values;
+ }
+}
+
+;// CONCATENATED MODULE: ./web/app.js
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+const FORCE_PAGES_LOADED_TIMEOUT = 10000;
+const WHEEL_ZOOM_DISABLED_TIMEOUT = 1000;
+const ViewOnLoad = {
+ UNKNOWN: -1,
+ PREVIOUS: 0,
+ INITIAL: 1
+};
+const PDFViewerApplication = {
+ initialBookmark: document.location.hash.substring(1),
+ _initializedCapability: new PromiseCapability(),
+ appConfig: null,
+ pdfDocument: null,
+ pdfLoadingTask: null,
+ printService: null,
+ pdfViewer: null,
+ pdfThumbnailViewer: null,
+ pdfRenderingQueue: null,
+ pdfPresentationMode: null,
+ pdfDocumentProperties: null,
+ pdfLinkService: null,
+ pdfHistory: null,
+ pdfSidebar: null,
+ pdfOutlineViewer: null,
+ pdfAttachmentViewer: null,
+ pdfLayerViewer: null,
+ pdfCursorTools: null,
+ pdfScriptingManager: null,
+ store: null,
+ downloadManager: null,
+ overlayManager: null,
+ preferences: null,
+ toolbar: null,
+ secondaryToolbar: null,
+ eventBus: null,
+ l10n: null,
+ annotationEditorParams: null,
+ isInitialViewSet: false,
+ downloadComplete: false,
+ isViewerEmbedded: window.parent !== window,
+ url: "",
+ baseUrl: "",
+ _downloadUrl: "",
+ _boundEvents: Object.create(null),
+ documentInfo: null,
+ metadata: null,
+ _contentDispositionFilename: null,
+ _contentLength: null,
+ _saveInProgress: false,
+ _wheelUnusedTicks: 0,
+ _wheelUnusedFactor: 1,
+ _touchUnusedTicks: 0,
+ _touchUnusedFactor: 1,
+ _PDFBug: null,
+ _hasAnnotationEditors: false,
+ _title: document.title,
+ _printAnnotationStoragePromise: null,
+ _touchInfo: null,
+ _isCtrlKeyDown: false,
+ _nimbusDataPromise: null,
+ _caretBrowsing: null,
+ _isScrolling: false,
+ _lastScrollTop: 0,
+ _lastScrollLeft: 0,
+ async initialize(appConfig) {
+ let l10nPromise;
+ l10nPromise = this.externalServices.createL10n();
+ this.appConfig = appConfig;
+ this._nimbusDataPromise = this.externalServices.getNimbusExperimentData();
+ try {
+ await this.preferences.initializedPromise;
+ } catch (ex) {
+ console.error(`initialize: "${ex.message}".`);
+ }
+ if (AppOptions.get("pdfBugEnabled")) {
+ await this._parseHashParams();
+ }
+ this.l10n = await l10nPromise;
+ document.getElementsByTagName("html")[0].dir = this.l10n.getDirection();
+ if (this.isViewerEmbedded && AppOptions.get("externalLinkTarget") === LinkTarget.NONE) {
+ AppOptions.set("externalLinkTarget", LinkTarget.TOP);
+ }
+ await this._initializeViewerComponents();
+ this.bindEvents();
+ this.bindWindowEvents();
+ this._initializedCapability.resolve();
+ },
+ async _parseHashParams() {
+ const hash = document.location.hash.substring(1);
+ if (!hash) {
+ return;
+ }
+ const {
+ mainContainer,
+ viewerContainer
+ } = this.appConfig,
+ params = parseQueryString(hash);
+ if (params.get("disableworker") === "true") {
+ try {
+ await loadFakeWorker();
+ } catch (ex) {
+ console.error(`_parseHashParams: "${ex.message}".`);
+ }
+ }
+ if (params.has("disablerange")) {
+ AppOptions.set("disableRange", params.get("disablerange") === "true");
+ }
+ if (params.has("disablestream")) {
+ AppOptions.set("disableStream", params.get("disablestream") === "true");
+ }
+ if (params.has("disableautofetch")) {
+ AppOptions.set("disableAutoFetch", params.get("disableautofetch") === "true");
+ }
+ if (params.has("disablefontface")) {
+ AppOptions.set("disableFontFace", params.get("disablefontface") === "true");
+ }
+ if (params.has("disablehistory")) {
+ AppOptions.set("disableHistory", params.get("disablehistory") === "true");
+ }
+ if (params.has("verbosity")) {
+ AppOptions.set("verbosity", params.get("verbosity") | 0);
+ }
+ if (params.has("textlayer")) {
+ switch (params.get("textlayer")) {
+ case "off":
+ AppOptions.set("textLayerMode", TextLayerMode.DISABLE);
+ break;
+ case "visible":
+ case "shadow":
+ case "hover":
+ viewerContainer.classList.add(`textLayer-${params.get("textlayer")}`);
+ try {
+ await loadPDFBug(this);
+ this._PDFBug.loadCSS();
+ } catch (ex) {
+ console.error(`_parseHashParams: "${ex.message}".`);
+ }
+ break;
+ }
+ }
+ if (params.has("pdfbug")) {
+ AppOptions.set("pdfBug", true);
+ AppOptions.set("fontExtraProperties", true);
+ const enabled = params.get("pdfbug").split(",");
+ try {
+ await loadPDFBug(this);
+ this._PDFBug.init(mainContainer, enabled);
+ } catch (ex) {
+ console.error(`_parseHashParams: "${ex.message}".`);
+ }
+ }
+ },
+ async _initializeViewerComponents() {
+ const {
+ appConfig,
+ externalServices,
+ l10n
+ } = this;
+ const eventBus = AppOptions.get("isInAutomation") ? new AutomationEventBus() : new EventBus();
+ this.eventBus = eventBus;
+ this.overlayManager = new OverlayManager();
+ const pdfRenderingQueue = new PDFRenderingQueue();
+ pdfRenderingQueue.onIdle = this._cleanup.bind(this);
+ this.pdfRenderingQueue = pdfRenderingQueue;
+ const pdfLinkService = new PDFLinkService({
+ eventBus,
+ externalLinkTarget: AppOptions.get("externalLinkTarget"),
+ externalLinkRel: AppOptions.get("externalLinkRel"),
+ ignoreDestinationZoom: AppOptions.get("ignoreDestinationZoom")
+ });
+ this.pdfLinkService = pdfLinkService;
+ const downloadManager = this.downloadManager = new DownloadManager();
+ const findController = new PDFFindController({
+ linkService: pdfLinkService,
+ eventBus,
+ updateMatchesCountOnProgress: false
+ });
+ this.findController = findController;
+ const pdfScriptingManager = new PDFScriptingManager({
+ eventBus,
+ externalServices,
+ docProperties: this._scriptingDocProperties.bind(this)
+ });
+ this.pdfScriptingManager = pdfScriptingManager;
+ const container = appConfig.mainContainer,
+ viewer = appConfig.viewerContainer;
+ const annotationEditorMode = AppOptions.get("annotationEditorMode");
+ const isOffscreenCanvasSupported = AppOptions.get("isOffscreenCanvasSupported") && FeatureTest.isOffscreenCanvasSupported;
+ const pageColors = AppOptions.get("forcePageColors") || window.matchMedia("(forced-colors: active)").matches ? {
+ background: AppOptions.get("pageColorsBackground"),
+ foreground: AppOptions.get("pageColorsForeground")
+ } : null;
+ const altTextManager = appConfig.altTextDialog ? new AltTextManager(appConfig.altTextDialog, container, this.overlayManager, eventBus) : null;
+ const pdfViewer = new PDFViewer({
+ container,
+ viewer,
+ eventBus,
+ renderingQueue: pdfRenderingQueue,
+ linkService: pdfLinkService,
+ downloadManager,
+ altTextManager,
+ findController,
+ scriptingManager: AppOptions.get("enableScripting") && pdfScriptingManager,
+ l10n,
+ textLayerMode: AppOptions.get("textLayerMode"),
+ annotationMode: AppOptions.get("annotationMode"),
+ annotationEditorMode,
+ annotationEditorHighlightColors: AppOptions.get("highlightEditorColors"),
+ imageResourcesPath: AppOptions.get("imageResourcesPath"),
+ enablePrintAutoRotate: AppOptions.get("enablePrintAutoRotate"),
+ maxCanvasPixels: AppOptions.get("maxCanvasPixels"),
+ enablePermissions: AppOptions.get("enablePermissions"),
+ pageColors,
+ mlManager: this.mlManager
+ });
+ this.pdfViewer = pdfViewer;
+ pdfRenderingQueue.setViewer(pdfViewer);
+ pdfLinkService.setViewer(pdfViewer);
+ pdfScriptingManager.setViewer(pdfViewer);
+ if (appConfig.sidebar?.thumbnailView) {
+ this.pdfThumbnailViewer = new PDFThumbnailViewer({
+ container: appConfig.sidebar.thumbnailView,
+ eventBus,
+ renderingQueue: pdfRenderingQueue,
+ linkService: pdfLinkService,
+ pageColors
+ });
+ pdfRenderingQueue.setThumbnailViewer(this.pdfThumbnailViewer);
+ }
+ if (!this.isViewerEmbedded && !AppOptions.get("disableHistory")) {
+ this.pdfHistory = new PDFHistory({
+ linkService: pdfLinkService,
+ eventBus
+ });
+ pdfLinkService.setHistory(this.pdfHistory);
+ }
+ if (!this.supportsIntegratedFind && appConfig.findBar) {
+ this.findBar = new PDFFindBar(appConfig.findBar, eventBus);
+ }
+ if (appConfig.annotationEditorParams) {
+ if (annotationEditorMode !== AnnotationEditorType.DISABLE) {
+ if (AppOptions.get("enableStampEditor") && isOffscreenCanvasSupported) {
+ appConfig.toolbar?.editorStampButton?.classList.remove("hidden");
+ }
+ const editorHighlightButton = appConfig.toolbar?.editorHighlightButton;
+ if (editorHighlightButton && AppOptions.get("enableHighlightEditor")) {
+ editorHighlightButton.hidden = false;
+ }
+ this.annotationEditorParams = new AnnotationEditorParams(appConfig.annotationEditorParams, eventBus);
+ } else {
+ for (const id of ["editorModeButtons", "editorModeSeparator"]) {
+ document.getElementById(id)?.classList.add("hidden");
+ }
+ }
+ }
+ if (appConfig.documentProperties) {
+ this.pdfDocumentProperties = new PDFDocumentProperties(appConfig.documentProperties, this.overlayManager, eventBus, l10n, () => this._docFilename);
+ }
+ if (appConfig.secondaryToolbar?.cursorHandToolButton) {
+ this.pdfCursorTools = new PDFCursorTools({
+ container,
+ eventBus,
+ cursorToolOnLoad: AppOptions.get("cursorToolOnLoad")
+ });
+ }
+ if (appConfig.toolbar) {
+ this.toolbar = new Toolbar(appConfig.toolbar, eventBus, await this._nimbusDataPromise);
+ }
+ if (appConfig.secondaryToolbar) {
+ this.secondaryToolbar = new SecondaryToolbar(appConfig.secondaryToolbar, eventBus);
+ }
+ if (this.supportsFullscreen && appConfig.secondaryToolbar?.presentationModeButton) {
+ this.pdfPresentationMode = new PDFPresentationMode({
+ container,
+ pdfViewer,
+ eventBus
+ });
+ }
+ if (appConfig.passwordOverlay) {
+ this.passwordPrompt = new PasswordPrompt(appConfig.passwordOverlay, this.overlayManager, this.isViewerEmbedded);
+ }
+ if (appConfig.sidebar?.outlineView) {
+ this.pdfOutlineViewer = new PDFOutlineViewer({
+ container: appConfig.sidebar.outlineView,
+ eventBus,
+ l10n,
+ linkService: pdfLinkService,
+ downloadManager
+ });
+ }
+ if (appConfig.sidebar?.attachmentsView) {
+ this.pdfAttachmentViewer = new PDFAttachmentViewer({
+ container: appConfig.sidebar.attachmentsView,
+ eventBus,
+ l10n,
+ downloadManager
+ });
+ }
+ if (appConfig.sidebar?.layersView) {
+ this.pdfLayerViewer = new PDFLayerViewer({
+ container: appConfig.sidebar.layersView,
+ eventBus,
+ l10n
+ });
+ }
+ if (appConfig.sidebar) {
+ this.pdfSidebar = new PDFSidebar({
+ elements: appConfig.sidebar,
+ eventBus,
+ l10n
+ });
+ this.pdfSidebar.onToggled = this.forceRendering.bind(this);
+ this.pdfSidebar.onUpdateThumbnails = () => {
+ for (const pageView of pdfViewer.getCachedPageViews()) {
+ if (pageView.renderingState === RenderingStates.FINISHED) {
+ this.pdfThumbnailViewer.getThumbnail(pageView.id - 1)?.setImage(pageView);
+ }
+ }
+ this.pdfThumbnailViewer.scrollThumbnailIntoView(pdfViewer.currentPageNumber);
+ };
+ }
+ },
+ async run(config) {
+ this.preferences = new Preferences();
+ await this.initialize(config);
+ const {
+ appConfig,
+ eventBus
+ } = this;
+ let file;
+ file = window.location.href;
+ if (!AppOptions.get("supportsDocumentFonts")) {
+ AppOptions.set("disableFontFace", true);
+ this.l10n.get("pdfjs-web-fonts-disabled").then(msg => {
+ console.warn(msg);
+ });
+ }
+ if (!this.supportsPrinting) {
+ appConfig.toolbar?.print?.classList.add("hidden");
+ appConfig.secondaryToolbar?.printButton.classList.add("hidden");
+ }
+ if (!this.supportsFullscreen) {
+ appConfig.secondaryToolbar?.presentationModeButton.classList.add("hidden");
+ }
+ if (this.supportsIntegratedFind) {
+ appConfig.toolbar?.viewFind?.classList.add("hidden");
+ }
+ this.initPassiveLoading(file);
+ const {
+ mainContainer
+ } = appConfig;
+ ({
+ scrollTop: this._lastScrollTop,
+ scrollLeft: this._lastScrollLeft
+ } = mainContainer);
+ const scroll = () => {
+ if (this._lastScrollTop === mainContainer.scrollTop && this._lastScrollLeft === mainContainer.scrollLeft) {
+ return;
+ }
+ mainContainer.removeEventListener("scroll", scroll, {
+ passive: true
+ });
+ this._isScrolling = true;
+ const scrollend = () => {
+ ({
+ scrollTop: this._lastScrollTop,
+ scrollLeft: this._lastScrollLeft
+ } = mainContainer);
+ this._isScrolling = false;
+ mainContainer.addEventListener("scroll", scroll, {
+ passive: true
+ });
+ mainContainer.removeEventListener("scrollend", scrollend);
+ mainContainer.removeEventListener("blur", scrollend);
+ };
+ mainContainer.addEventListener("scrollend", scrollend);
+ mainContainer.addEventListener("blur", scrollend);
+ };
+ mainContainer.addEventListener("scroll", scroll, {
+ passive: true
+ });
+ },
+ get externalServices() {
+ return shadow(this, "externalServices", new ExternalServices());
+ },
+ get mlManager() {
+ return shadow(this, "mlManager", AppOptions.get("enableML") === true ? new MLManager() : null);
+ },
+ get initialized() {
+ return this._initializedCapability.settled;
+ },
+ get initializedPromise() {
+ return this._initializedCapability.promise;
+ },
+ zoomIn(steps, scaleFactor) {
+ if (this.pdfViewer.isInPresentationMode) {
+ return;
+ }
+ this.pdfViewer.increaseScale({
+ drawingDelay: AppOptions.get("defaultZoomDelay"),
+ steps,
+ scaleFactor
+ });
+ },
+ zoomOut(steps, scaleFactor) {
+ if (this.pdfViewer.isInPresentationMode) {
+ return;
+ }
+ this.pdfViewer.decreaseScale({
+ drawingDelay: AppOptions.get("defaultZoomDelay"),
+ steps,
+ scaleFactor
+ });
+ },
+ zoomReset() {
+ if (this.pdfViewer.isInPresentationMode) {
+ return;
+ }
+ this.pdfViewer.currentScaleValue = DEFAULT_SCALE_VALUE;
+ },
+ get pagesCount() {
+ return this.pdfDocument ? this.pdfDocument.numPages : 0;
+ },
+ get page() {
+ return this.pdfViewer.currentPageNumber;
+ },
+ set page(val) {
+ this.pdfViewer.currentPageNumber = val;
+ },
+ get supportsPrinting() {
+ return PDFPrintServiceFactory.supportsPrinting;
+ },
+ get supportsFullscreen() {
+ return shadow(this, "supportsFullscreen", document.fullscreenEnabled);
+ },
+ get supportsPinchToZoom() {
+ return shadow(this, "supportsPinchToZoom", AppOptions.get("supportsPinchToZoom"));
+ },
+ get supportsIntegratedFind() {
+ return shadow(this, "supportsIntegratedFind", AppOptions.get("supportsIntegratedFind"));
+ },
+ get loadingBar() {
+ const barElement = document.getElementById("loadingBar");
+ const bar = barElement ? new ProgressBar(barElement) : null;
+ return shadow(this, "loadingBar", bar);
+ },
+ get supportsMouseWheelZoomCtrlKey() {
+ return shadow(this, "supportsMouseWheelZoomCtrlKey", AppOptions.get("supportsMouseWheelZoomCtrlKey"));
+ },
+ get supportsMouseWheelZoomMetaKey() {
+ return shadow(this, "supportsMouseWheelZoomMetaKey", AppOptions.get("supportsMouseWheelZoomMetaKey"));
+ },
+ get supportsCaretBrowsingMode() {
+ return shadow(this, "supportsCaretBrowsingMode", AppOptions.get("supportsCaretBrowsingMode"));
+ },
+ moveCaret(isUp, select) {
+ this._caretBrowsing ||= new CaretBrowsingMode(this.appConfig.mainContainer, this.appConfig.viewerContainer, this.appConfig.toolbar?.container);
+ this._caretBrowsing.moveCaret(isUp, select);
+ },
+ initPassiveLoading(file) {
+ this.setTitleUsingUrl(file, file);
+ this.externalServices.initPassiveLoading({
+ onOpenWithTransport: range => {
+ this.open({
+ range
+ });
+ },
+ onOpenWithData: (data, contentDispositionFilename) => {
+ if (isPdfFile(contentDispositionFilename)) {
+ this._contentDispositionFilename = contentDispositionFilename;
+ }
+ this.open({
+ data
+ });
+ },
+ onOpenWithURL: (url, length, originalUrl) => {
+ this.open({
+ url,
+ length,
+ originalUrl
+ });
+ },
+ onError: err => {
+ this.l10n.get("pdfjs-loading-error").then(msg => {
+ this._documentError(msg, err);
+ });
+ },
+ onProgress: (loaded, total) => {
+ this.progress(loaded / total);
+ }
+ });
+ },
+ setTitleUsingUrl(url = "", downloadUrl = null) {
+ this.url = url;
+ this.baseUrl = url.split("#", 1)[0];
+ if (downloadUrl) {
+ this._downloadUrl = downloadUrl === url ? this.baseUrl : downloadUrl.split("#", 1)[0];
+ }
+ if (isDataScheme(url)) {
+ this._hideViewBookmark();
+ }
+ let title = getPdfFilenameFromUrl(url, "");
+ if (!title) {
+ try {
+ title = decodeURIComponent(getFilenameFromUrl(url)) || url;
+ } catch {
+ title = url;
+ }
+ }
+ this.setTitle(title);
+ },
+ setTitle(title = this._title) {
+ this._title = title;
+ if (this.isViewerEmbedded) {
+ return;
+ }
+ const editorIndicator = this._hasAnnotationEditors && !this.pdfRenderingQueue.printing;
+ document.title = `${editorIndicator ? "* " : ""}${title}`;
+ },
+ get _docFilename() {
+ return this._contentDispositionFilename || getPdfFilenameFromUrl(this.url);
+ },
+ _hideViewBookmark() {
+ const {
+ secondaryToolbar
+ } = this.appConfig;
+ secondaryToolbar?.viewBookmarkButton.classList.add("hidden");
+ if (secondaryToolbar?.presentationModeButton.classList.contains("hidden")) {
+ document.getElementById("viewBookmarkSeparator")?.classList.add("hidden");
+ }
+ },
+ async close() {
+ this._unblockDocumentLoadEvent();
+ this._hideViewBookmark();
+ if (!this.pdfLoadingTask) {
+ return;
+ }
+ const promises = [];
+ promises.push(this.pdfLoadingTask.destroy());
+ this.pdfLoadingTask = null;
+ if (this.pdfDocument) {
+ this.pdfDocument = null;
+ this.pdfThumbnailViewer?.setDocument(null);
+ this.pdfViewer.setDocument(null);
+ this.pdfLinkService.setDocument(null);
+ this.pdfDocumentProperties?.setDocument(null);
+ }
+ this.pdfLinkService.externalLinkEnabled = true;
+ this.store = null;
+ this.isInitialViewSet = false;
+ this.downloadComplete = false;
+ this.url = "";
+ this.baseUrl = "";
+ this._downloadUrl = "";
+ this.documentInfo = null;
+ this.metadata = null;
+ this._contentDispositionFilename = null;
+ this._contentLength = null;
+ this._saveInProgress = false;
+ this._hasAnnotationEditors = false;
+ promises.push(this.pdfScriptingManager.destroyPromise, this.passwordPrompt.close());
+ this.setTitle();
+ this.pdfSidebar?.reset();
+ this.pdfOutlineViewer?.reset();
+ this.pdfAttachmentViewer?.reset();
+ this.pdfLayerViewer?.reset();
+ this.pdfHistory?.reset();
+ this.findBar?.reset();
+ this.toolbar?.reset();
+ this.secondaryToolbar?.reset();
+ this._PDFBug?.cleanup();
+ await Promise.all(promises);
+ },
+ async open(args) {
+ if (this.pdfLoadingTask) {
+ await this.close();
+ }
+ const workerParams = AppOptions.getAll(OptionKind.WORKER);
+ Object.assign(GlobalWorkerOptions, workerParams);
+ AppOptions.set("docBaseUrl", this.baseUrl);
+ const apiParams = AppOptions.getAll(OptionKind.API);
+ const loadingTask = getDocument({
+ ...apiParams,
+ ...args
+ });
+ this.pdfLoadingTask = loadingTask;
+ loadingTask.onPassword = (updateCallback, reason) => {
+ if (this.isViewerEmbedded) {
+ this._unblockDocumentLoadEvent();
+ }
+ this.pdfLinkService.externalLinkEnabled = false;
+ this.passwordPrompt.setUpdateCallback(updateCallback, reason);
+ this.passwordPrompt.open();
+ };
+ loadingTask.onProgress = ({
+ loaded,
+ total
+ }) => {
+ this.progress(loaded / total);
+ };
+ return loadingTask.promise.then(pdfDocument => {
+ this.load(pdfDocument);
+ }, reason => {
+ if (loadingTask !== this.pdfLoadingTask) {
+ return undefined;
+ }
+ let key = "pdfjs-loading-error";
+ if (reason instanceof InvalidPDFException) {
+ key = "pdfjs-invalid-file-error";
+ } else if (reason instanceof MissingPDFException) {
+ key = "pdfjs-missing-file-error";
+ } else if (reason instanceof UnexpectedResponseException) {
+ key = "pdfjs-unexpected-response-error";
+ }
+ return this.l10n.get(key).then(msg => {
+ this._documentError(msg, {
+ message: reason?.message
+ });
+ throw reason;
+ });
+ });
+ },
+ _ensureDownloadComplete() {
+ if (this.pdfDocument && this.downloadComplete) {
+ return;
+ }
+ throw new Error("PDF document not downloaded.");
+ },
+ async download(options = {}) {
+ const url = this._downloadUrl,
+ filename = this._docFilename;
+ try {
+ this._ensureDownloadComplete();
+ const data = await this.pdfDocument.getData();
+ const blob = new Blob([data], {
+ type: "application/pdf"
+ });
+ await this.downloadManager.download(blob, url, filename, options);
+ } catch {
+ await this.downloadManager.downloadUrl(url, filename, options);
+ }
+ },
+ async save(options = {}) {
+ if (this._saveInProgress) {
+ return;
+ }
+ this._saveInProgress = true;
+ await this.pdfScriptingManager.dispatchWillSave();
+ const url = this._downloadUrl,
+ filename = this._docFilename;
+ try {
+ this._ensureDownloadComplete();
+ const data = await this.pdfDocument.saveDocument();
+ const blob = new Blob([data], {
+ type: "application/pdf"
+ });
+ await this.downloadManager.download(blob, url, filename, options);
+ } catch (reason) {
+ console.error(`Error when saving the document: ${reason.message}`);
+ await this.download(options);
+ } finally {
+ await this.pdfScriptingManager.dispatchDidSave();
+ this._saveInProgress = false;
+ }
+ if (this._hasAnnotationEditors) {
+ this.externalServices.reportTelemetry({
+ type: "editing",
+ data: {
+ type: "save",
+ stats: this.pdfDocument?.annotationStorage.editorStats
+ }
+ });
+ }
+ },
+ downloadOrSave(options = {}) {
+ if (this.pdfDocument?.annotationStorage.size > 0) {
+ this.save(options);
+ } else {
+ this.download(options);
+ }
+ },
+ openInExternalApp() {
+ this.downloadOrSave({
+ openInExternalApp: true
+ });
+ },
+ _documentError(message, moreInfo = null) {
+ this._unblockDocumentLoadEvent();
+ this._otherError(message, moreInfo);
+ this.eventBus.dispatch("documenterror", {
+ source: this,
+ message,
+ reason: moreInfo?.message ?? null
+ });
+ },
+ _otherError(message, moreInfo = null) {
+ const moreInfoText = [`PDF.js v${version || "?"} (build: ${build || "?"})`];
+ if (moreInfo) {
+ moreInfoText.push(`Message: ${moreInfo.message}`);
+ if (moreInfo.stack) {
+ moreInfoText.push(`Stack: ${moreInfo.stack}`);
+ } else {
+ if (moreInfo.filename) {
+ moreInfoText.push(`File: ${moreInfo.filename}`);
+ }
+ if (moreInfo.lineNumber) {
+ moreInfoText.push(`Line: ${moreInfo.lineNumber}`);
+ }
+ }
+ }
+ console.error(`${message}\n\n${moreInfoText.join("\n")}`);
+ },
+ progress(level) {
+ if (!this.loadingBar || this.downloadComplete) {
+ return;
+ }
+ const percent = Math.round(level * 100);
+ if (percent <= this.loadingBar.percent) {
+ return;
+ }
+ this.loadingBar.percent = percent;
+ if (this.pdfDocument?.loadingParams.disableAutoFetch ?? AppOptions.get("disableAutoFetch")) {
+ this.loadingBar.setDisableAutoFetch();
+ }
+ },
+ load(pdfDocument) {
+ this.pdfDocument = pdfDocument;
+ pdfDocument.getDownloadInfo().then(({
+ length
+ }) => {
+ this._contentLength = length;
+ this.downloadComplete = true;
+ this.loadingBar?.hide();
+ firstPagePromise.then(() => {
+ this.eventBus.dispatch("documentloaded", {
+ source: this
+ });
+ });
+ });
+ const pageLayoutPromise = pdfDocument.getPageLayout().catch(() => {});
+ const pageModePromise = pdfDocument.getPageMode().catch(() => {});
+ const openActionPromise = pdfDocument.getOpenAction().catch(() => {});
+ this.toolbar?.setPagesCount(pdfDocument.numPages, false);
+ this.secondaryToolbar?.setPagesCount(pdfDocument.numPages);
+ this.pdfLinkService.setDocument(pdfDocument);
+ this.pdfDocumentProperties?.setDocument(pdfDocument);
+ const pdfViewer = this.pdfViewer;
+ pdfViewer.setDocument(pdfDocument);
+ const {
+ firstPagePromise,
+ onePageRendered,
+ pagesPromise
+ } = pdfViewer;
+ this.pdfThumbnailViewer?.setDocument(pdfDocument);
+ const storedPromise = (this.store = new ViewHistory(pdfDocument.fingerprints[0])).getMultiple({
+ page: null,
+ zoom: DEFAULT_SCALE_VALUE,
+ scrollLeft: "0",
+ scrollTop: "0",
+ rotation: null,
+ sidebarView: SidebarView.UNKNOWN,
+ scrollMode: ScrollMode.UNKNOWN,
+ spreadMode: SpreadMode.UNKNOWN
+ }).catch(() => {});
+ firstPagePromise.then(pdfPage => {
+ this.loadingBar?.setWidth(this.appConfig.viewerContainer);
+ this._initializeAnnotationStorageCallbacks(pdfDocument);
+ Promise.all([animationStarted, storedPromise, pageLayoutPromise, pageModePromise, openActionPromise]).then(async ([timeStamp, stored, pageLayout, pageMode, openAction]) => {
+ const viewOnLoad = AppOptions.get("viewOnLoad");
+ this._initializePdfHistory({
+ fingerprint: pdfDocument.fingerprints[0],
+ viewOnLoad,
+ initialDest: openAction?.dest
+ });
+ const initialBookmark = this.initialBookmark;
+ const zoom = AppOptions.get("defaultZoomValue");
+ let hash = zoom ? `zoom=${zoom}` : null;
+ let rotation = null;
+ let sidebarView = AppOptions.get("sidebarViewOnLoad");
+ let scrollMode = AppOptions.get("scrollModeOnLoad");
+ let spreadMode = AppOptions.get("spreadModeOnLoad");
+ if (stored?.page && viewOnLoad !== ViewOnLoad.INITIAL) {
+ hash = `page=${stored.page}&zoom=${zoom || stored.zoom},` + `${stored.scrollLeft},${stored.scrollTop}`;
+ rotation = parseInt(stored.rotation, 10);
+ if (sidebarView === SidebarView.UNKNOWN) {
+ sidebarView = stored.sidebarView | 0;
+ }
+ if (scrollMode === ScrollMode.UNKNOWN) {
+ scrollMode = stored.scrollMode | 0;
+ }
+ if (spreadMode === SpreadMode.UNKNOWN) {
+ spreadMode = stored.spreadMode | 0;
+ }
+ }
+ if (pageMode && sidebarView === SidebarView.UNKNOWN) {
+ sidebarView = apiPageModeToSidebarView(pageMode);
+ }
+ if (pageLayout && scrollMode === ScrollMode.UNKNOWN && spreadMode === SpreadMode.UNKNOWN) {
+ const modes = apiPageLayoutToViewerModes(pageLayout);
+ spreadMode = modes.spreadMode;
+ }
+ this.setInitialView(hash, {
+ rotation,
+ sidebarView,
+ scrollMode,
+ spreadMode
+ });
+ this.eventBus.dispatch("documentinit", {
+ source: this
+ });
+ if (!this.isViewerEmbedded) {
+ pdfViewer.focus();
+ }
+ await Promise.race([pagesPromise, new Promise(resolve => {
+ setTimeout(resolve, FORCE_PAGES_LOADED_TIMEOUT);
+ })]);
+ if (!initialBookmark && !hash) {
+ return;
+ }
+ if (pdfViewer.hasEqualPageSizes) {
+ return;
+ }
+ this.initialBookmark = initialBookmark;
+ pdfViewer.currentScaleValue = pdfViewer.currentScaleValue;
+ this.setInitialView(hash);
+ }).catch(() => {
+ this.setInitialView();
+ }).then(function () {
+ pdfViewer.update();
+ });
+ });
+ pagesPromise.then(() => {
+ this._unblockDocumentLoadEvent();
+ this._initializeAutoPrint(pdfDocument, openActionPromise);
+ }, reason => {
+ this.l10n.get("pdfjs-loading-error").then(msg => {
+ this._documentError(msg, {
+ message: reason?.message
+ });
+ });
+ });
+ onePageRendered.then(data => {
+ this.externalServices.reportTelemetry({
+ type: "pageInfo",
+ timestamp: data.timestamp
+ });
+ if (this.pdfOutlineViewer) {
+ pdfDocument.getOutline().then(outline => {
+ if (pdfDocument !== this.pdfDocument) {
+ return;
+ }
+ this.pdfOutlineViewer.render({
+ outline,
+ pdfDocument
+ });
+ });
+ }
+ if (this.pdfAttachmentViewer) {
+ pdfDocument.getAttachments().then(attachments => {
+ if (pdfDocument !== this.pdfDocument) {
+ return;
+ }
+ this.pdfAttachmentViewer.render({
+ attachments
+ });
+ });
+ }
+ if (this.pdfLayerViewer) {
+ pdfViewer.optionalContentConfigPromise.then(optionalContentConfig => {
+ if (pdfDocument !== this.pdfDocument) {
+ return;
+ }
+ this.pdfLayerViewer.render({
+ optionalContentConfig,
+ pdfDocument
+ });
+ });
+ }
+ });
+ this._initializePageLabels(pdfDocument);
+ this._initializeMetadata(pdfDocument);
+ },
+ async _scriptingDocProperties(pdfDocument) {
+ if (!this.documentInfo) {
+ await new Promise(resolve => {
+ this.eventBus._on("metadataloaded", resolve, {
+ once: true
+ });
+ });
+ if (pdfDocument !== this.pdfDocument) {
+ return null;
+ }
+ }
+ if (!this._contentLength) {
+ await new Promise(resolve => {
+ this.eventBus._on("documentloaded", resolve, {
+ once: true
+ });
+ });
+ if (pdfDocument !== this.pdfDocument) {
+ return null;
+ }
+ }
+ return {
+ ...this.documentInfo,
+ baseURL: this.baseUrl,
+ filesize: this._contentLength,
+ filename: this._docFilename,
+ metadata: this.metadata?.getRaw(),
+ authors: this.metadata?.get("dc:creator"),
+ numPages: this.pagesCount,
+ URL: this.url
+ };
+ },
+ async _initializeAutoPrint(pdfDocument, openActionPromise) {
+ const [openAction, jsActions] = await Promise.all([openActionPromise, this.pdfViewer.enableScripting ? null : pdfDocument.getJSActions()]);
+ if (pdfDocument !== this.pdfDocument) {
+ return;
+ }
+ let triggerAutoPrint = openAction?.action === "Print";
+ if (jsActions) {
+ console.warn("Warning: JavaScript support is not enabled");
+ for (const name in jsActions) {
+ if (triggerAutoPrint) {
+ break;
+ }
+ switch (name) {
+ case "WillClose":
+ case "WillSave":
+ case "DidSave":
+ case "WillPrint":
+ case "DidPrint":
+ continue;
+ }
+ triggerAutoPrint = jsActions[name].some(js => AutoPrintRegExp.test(js));
+ }
+ }
+ if (triggerAutoPrint) {
+ this.triggerPrinting();
+ }
+ },
+ async _initializeMetadata(pdfDocument) {
+ const {
+ info,
+ metadata,
+ contentDispositionFilename,
+ contentLength
+ } = await pdfDocument.getMetadata();
+ if (pdfDocument !== this.pdfDocument) {
+ return;
+ }
+ this.documentInfo = info;
+ this.metadata = metadata;
+ this._contentDispositionFilename ??= contentDispositionFilename;
+ this._contentLength ??= contentLength;
+ console.log(`PDF ${pdfDocument.fingerprints[0]} [${info.PDFFormatVersion} ` + `${(info.Producer || "-").trim()} / ${(info.Creator || "-").trim()}] ` + `(PDF.js: ${version || "?"} [${build || "?"}])`);
+ let pdfTitle = info.Title;
+ const metadataTitle = metadata?.get("dc:title");
+ if (metadataTitle) {
+ if (metadataTitle !== "Untitled" && !/[\uFFF0-\uFFFF]/g.test(metadataTitle)) {
+ pdfTitle = metadataTitle;
+ }
+ }
+ if (pdfTitle) {
+ this.setTitle(`${pdfTitle} - ${this._contentDispositionFilename || this._title}`);
+ } else if (this._contentDispositionFilename) {
+ this.setTitle(this._contentDispositionFilename);
+ }
+ if (info.IsXFAPresent && !info.IsAcroFormPresent && !pdfDocument.isPureXfa) {
+ if (pdfDocument.loadingParams.enableXfa) {
+ console.warn("Warning: XFA Foreground documents are not supported");
+ } else {
+ console.warn("Warning: XFA support is not enabled");
+ }
+ } else if ((info.IsAcroFormPresent || info.IsXFAPresent) && !this.pdfViewer.renderForms) {
+ console.warn("Warning: Interactive form support is not enabled");
+ }
+ if (info.IsSignaturesPresent) {
+ console.warn("Warning: Digital signatures validation is not supported");
+ }
+ this.eventBus.dispatch("metadataloaded", {
+ source: this
+ });
+ },
+ async _initializePageLabels(pdfDocument) {},
+ _initializePdfHistory({
+ fingerprint,
+ viewOnLoad,
+ initialDest = null
+ }) {
+ if (!this.pdfHistory) {
+ return;
+ }
+ this.pdfHistory.initialize({
+ fingerprint,
+ resetHistory: viewOnLoad === ViewOnLoad.INITIAL,
+ updateUrl: AppOptions.get("historyUpdateUrl")
+ });
+ if (this.pdfHistory.initialBookmark) {
+ this.initialBookmark = this.pdfHistory.initialBookmark;
+ this.initialRotation = this.pdfHistory.initialRotation;
+ }
+ if (initialDest && !this.initialBookmark && viewOnLoad === ViewOnLoad.UNKNOWN) {
+ this.initialBookmark = JSON.stringify(initialDest);
+ this.pdfHistory.push({
+ explicitDest: initialDest,
+ pageNumber: null
+ });
+ }
+ },
+ _initializeAnnotationStorageCallbacks(pdfDocument) {
+ if (pdfDocument !== this.pdfDocument) {
+ return;
+ }
+ const {
+ annotationStorage
+ } = pdfDocument;
+ annotationStorage.onSetModified = () => {
+ window.addEventListener("beforeunload", beforeUnload);
+ };
+ annotationStorage.onResetModified = () => {
+ window.removeEventListener("beforeunload", beforeUnload);
+ };
+ annotationStorage.onAnnotationEditor = typeStr => {
+ this._hasAnnotationEditors = !!typeStr;
+ this.setTitle();
+ };
+ },
+ setInitialView(storedHash, {
+ rotation,
+ sidebarView,
+ scrollMode,
+ spreadMode
+ } = {}) {
+ const setRotation = angle => {
+ if (isValidRotation(angle)) {
+ this.pdfViewer.pagesRotation = angle;
+ }
+ };
+ const setViewerModes = (scroll, spread) => {
+ if (isValidScrollMode(scroll)) {
+ this.pdfViewer.scrollMode = scroll;
+ }
+ if (isValidSpreadMode(spread)) {
+ this.pdfViewer.spreadMode = spread;
+ }
+ };
+ this.isInitialViewSet = true;
+ this.pdfSidebar?.setInitialView(sidebarView);
+ setViewerModes(scrollMode, spreadMode);
+ if (this.initialBookmark) {
+ setRotation(this.initialRotation);
+ delete this.initialRotation;
+ this.pdfLinkService.setHash(this.initialBookmark);
+ this.initialBookmark = null;
+ } else if (storedHash) {
+ setRotation(rotation);
+ this.pdfLinkService.setHash(storedHash);
+ }
+ this.toolbar?.setPageNumber(this.pdfViewer.currentPageNumber, this.pdfViewer.currentPageLabel);
+ this.secondaryToolbar?.setPageNumber(this.pdfViewer.currentPageNumber);
+ if (!this.pdfViewer.currentScaleValue) {
+ this.pdfViewer.currentScaleValue = DEFAULT_SCALE_VALUE;
+ }
+ },
+ _cleanup() {
+ if (!this.pdfDocument) {
+ return;
+ }
+ this.pdfViewer.cleanup();
+ this.pdfThumbnailViewer?.cleanup();
+ this.pdfDocument.cleanup(AppOptions.get("fontExtraProperties"));
+ },
+ forceRendering() {
+ this.pdfRenderingQueue.printing = !!this.printService;
+ this.pdfRenderingQueue.isThumbnailViewEnabled = this.pdfSidebar?.visibleView === SidebarView.THUMBS;
+ this.pdfRenderingQueue.renderHighestPriority();
+ },
+ beforePrint() {
+ this._printAnnotationStoragePromise = this.pdfScriptingManager.dispatchWillPrint().catch(() => {}).then(() => this.pdfDocument?.annotationStorage.print);
+ if (this.printService) {
+ return;
+ }
+ if (!this.supportsPrinting) {
+ this.l10n.get("pdfjs-printing-not-supported").then(msg => {
+ this._otherError(msg);
+ });
+ return;
+ }
+ if (!this.pdfViewer.pageViewsReady) {
+ this.l10n.get("pdfjs-printing-not-ready").then(msg => {
+ window.alert(msg);
+ });
+ return;
+ }
+ this.printService = PDFPrintServiceFactory.createPrintService({
+ pdfDocument: this.pdfDocument,
+ pagesOverview: this.pdfViewer.getPagesOverview(),
+ printContainer: this.appConfig.printContainer,
+ printResolution: AppOptions.get("printResolution"),
+ optionalContentConfigPromise: this.pdfViewer.optionalContentConfigPromise,
+ printAnnotationStoragePromise: this._printAnnotationStoragePromise
+ });
+ this.forceRendering();
+ this.setTitle();
+ this.printService.layout();
+ if (this._hasAnnotationEditors) {
+ this.externalServices.reportTelemetry({
+ type: "editing",
+ data: {
+ type: "print",
+ stats: this.pdfDocument?.annotationStorage.editorStats
+ }
+ });
+ }
+ },
+ afterPrint() {
+ if (this._printAnnotationStoragePromise) {
+ this._printAnnotationStoragePromise.then(() => {
+ this.pdfScriptingManager.dispatchDidPrint();
+ });
+ this._printAnnotationStoragePromise = null;
+ }
+ if (this.printService) {
+ this.printService.destroy();
+ this.printService = null;
+ this.pdfDocument?.annotationStorage.resetModified();
+ }
+ this.forceRendering();
+ this.setTitle();
+ },
+ rotatePages(delta) {
+ this.pdfViewer.pagesRotation += delta;
+ },
+ requestPresentationMode() {
+ this.pdfPresentationMode?.request();
+ },
+ triggerPrinting() {
+ if (!this.supportsPrinting) {
+ return;
+ }
+ window.print();
+ },
+ bindEvents() {
+ const {
+ eventBus,
+ _boundEvents
+ } = this;
+ _boundEvents.beforePrint = this.beforePrint.bind(this);
+ _boundEvents.afterPrint = this.afterPrint.bind(this);
+ eventBus._on("resize", webViewerResize);
+ eventBus._on("hashchange", webViewerHashchange);
+ eventBus._on("beforeprint", _boundEvents.beforePrint);
+ eventBus._on("afterprint", _boundEvents.afterPrint);
+ eventBus._on("pagerender", webViewerPageRender);
+ eventBus._on("pagerendered", webViewerPageRendered);
+ eventBus._on("updateviewarea", webViewerUpdateViewarea);
+ eventBus._on("pagechanging", webViewerPageChanging);
+ eventBus._on("scalechanging", webViewerScaleChanging);
+ eventBus._on("rotationchanging", webViewerRotationChanging);
+ eventBus._on("sidebarviewchanged", webViewerSidebarViewChanged);
+ eventBus._on("pagemode", webViewerPageMode);
+ eventBus._on("namedaction", webViewerNamedAction);
+ eventBus._on("presentationmodechanged", webViewerPresentationModeChanged);
+ eventBus._on("presentationmode", webViewerPresentationMode);
+ eventBus._on("switchannotationeditormode", webViewerSwitchAnnotationEditorMode);
+ eventBus._on("switchannotationeditorparams", webViewerSwitchAnnotationEditorParams);
+ eventBus._on("print", webViewerPrint);
+ eventBus._on("download", webViewerDownload);
+ eventBus._on("openinexternalapp", webViewerOpenInExternalApp);
+ eventBus._on("firstpage", webViewerFirstPage);
+ eventBus._on("lastpage", webViewerLastPage);
+ eventBus._on("nextpage", webViewerNextPage);
+ eventBus._on("previouspage", webViewerPreviousPage);
+ eventBus._on("zoomin", webViewerZoomIn);
+ eventBus._on("zoomout", webViewerZoomOut);
+ eventBus._on("zoomreset", webViewerZoomReset);
+ eventBus._on("pagenumberchanged", webViewerPageNumberChanged);
+ eventBus._on("scalechanged", webViewerScaleChanged);
+ eventBus._on("rotatecw", webViewerRotateCw);
+ eventBus._on("rotateccw", webViewerRotateCcw);
+ eventBus._on("optionalcontentconfig", webViewerOptionalContentConfig);
+ eventBus._on("switchscrollmode", webViewerSwitchScrollMode);
+ eventBus._on("scrollmodechanged", webViewerScrollModeChanged);
+ eventBus._on("switchspreadmode", webViewerSwitchSpreadMode);
+ eventBus._on("spreadmodechanged", webViewerSpreadModeChanged);
+ eventBus._on("documentproperties", webViewerDocumentProperties);
+ eventBus._on("findfromurlhash", webViewerFindFromUrlHash);
+ eventBus._on("updatefindmatchescount", webViewerUpdateFindMatchesCount);
+ eventBus._on("updatefindcontrolstate", webViewerUpdateFindControlState);
+ if (AppOptions.get("pdfBug")) {
+ _boundEvents.reportPageStatsPDFBug = reportPageStatsPDFBug;
+ eventBus._on("pagerendered", _boundEvents.reportPageStatsPDFBug);
+ eventBus._on("pagechanging", _boundEvents.reportPageStatsPDFBug);
+ }
+ eventBus._on("annotationeditorstateschanged", webViewerAnnotationEditorStatesChanged);
+ eventBus._on("reporttelemetry", webViewerReportTelemetry);
+ },
+ bindWindowEvents() {
+ const {
+ eventBus,
+ _boundEvents
+ } = this;
+ function addWindowResolutionChange(evt = null) {
+ if (evt) {
+ webViewerResolutionChange(evt);
+ }
+ const mediaQueryList = window.matchMedia(`(resolution: ${window.devicePixelRatio || 1}dppx)`);
+ mediaQueryList.addEventListener("change", addWindowResolutionChange, {
+ once: true
+ });
+ }
+ addWindowResolutionChange();
+ _boundEvents.windowResize = () => {
+ eventBus.dispatch("resize", {
+ source: window
+ });
+ };
+ _boundEvents.windowHashChange = () => {
+ eventBus.dispatch("hashchange", {
+ source: window,
+ hash: document.location.hash.substring(1)
+ });
+ };
+ _boundEvents.windowBeforePrint = () => {
+ eventBus.dispatch("beforeprint", {
+ source: window
+ });
+ };
+ _boundEvents.windowAfterPrint = () => {
+ eventBus.dispatch("afterprint", {
+ source: window
+ });
+ };
+ _boundEvents.windowUpdateFromSandbox = event => {
+ eventBus.dispatch("updatefromsandbox", {
+ source: window,
+ detail: event.detail
+ });
+ };
+ window.addEventListener("visibilitychange", webViewerVisibilityChange);
+ window.addEventListener("wheel", webViewerWheel, {
+ passive: false
+ });
+ window.addEventListener("touchstart", webViewerTouchStart, {
+ passive: false
+ });
+ window.addEventListener("touchmove", webViewerTouchMove, {
+ passive: false
+ });
+ window.addEventListener("touchend", webViewerTouchEnd, {
+ passive: false
+ });
+ window.addEventListener("click", webViewerClick);
+ window.addEventListener("keydown", webViewerKeyDown);
+ window.addEventListener("keyup", webViewerKeyUp);
+ window.addEventListener("resize", _boundEvents.windowResize);
+ window.addEventListener("hashchange", _boundEvents.windowHashChange);
+ window.addEventListener("beforeprint", _boundEvents.windowBeforePrint);
+ window.addEventListener("afterprint", _boundEvents.windowAfterPrint);
+ window.addEventListener("updatefromsandbox", _boundEvents.windowUpdateFromSandbox);
+ },
+ unbindEvents() {
+ throw new Error("Not implemented: unbindEvents");
+ },
+ unbindWindowEvents() {
+ throw new Error("Not implemented: unbindWindowEvents");
+ },
+ _accumulateTicks(ticks, prop) {
+ if (this[prop] > 0 && ticks < 0 || this[prop] < 0 && ticks > 0) {
+ this[prop] = 0;
+ }
+ this[prop] += ticks;
+ const wholeTicks = Math.trunc(this[prop]);
+ this[prop] -= wholeTicks;
+ return wholeTicks;
+ },
+ _accumulateFactor(previousScale, factor, prop) {
+ if (factor === 1) {
+ return 1;
+ }
+ if (this[prop] > 1 && factor < 1 || this[prop] < 1 && factor > 1) {
+ this[prop] = 1;
+ }
+ const newFactor = Math.floor(previousScale * factor * this[prop] * 100) / (100 * previousScale);
+ this[prop] = factor / newFactor;
+ return newFactor;
+ },
+ _centerAtPos(previousScale, x, y) {
+ const {
+ pdfViewer
+ } = this;
+ const scaleDiff = pdfViewer.currentScale / previousScale - 1;
+ if (scaleDiff !== 0) {
+ const [top, left] = pdfViewer.containerTopLeft;
+ pdfViewer.container.scrollLeft += (x - left) * scaleDiff;
+ pdfViewer.container.scrollTop += (y - top) * scaleDiff;
+ }
+ },
+ _unblockDocumentLoadEvent() {
+ document.blockUnblockOnload?.(false);
+ this._unblockDocumentLoadEvent = () => {};
+ },
+ get scriptingReady() {
+ return this.pdfScriptingManager.ready;
+ }
+};
+initCom(PDFViewerApplication);
+async function loadFakeWorker() {
+ GlobalWorkerOptions.workerSrc ||= AppOptions.get("workerSrc");
+ await import( /*webpackIgnore: true*/PDFWorker.workerSrc);
+}
+async function loadPDFBug(self) {
+ const {
+ PDFBug
+ } = await import( /*webpackIgnore: true*/AppOptions.get("debuggerSrc"));
+ self._PDFBug = PDFBug;
+}
+function reportPageStatsPDFBug({
+ pageNumber
+}) {
+ if (!globalThis.Stats?.enabled) {
+ return;
+ }
+ const pageView = PDFViewerApplication.pdfViewer.getPageView(pageNumber - 1);
+ globalThis.Stats.add(pageNumber, pageView?.pdfPage?.stats);
+}
+function webViewerPageRender({
+ pageNumber
+}) {
+ if (pageNumber === PDFViewerApplication.page) {
+ PDFViewerApplication.toolbar?.updateLoadingIndicatorState(true);
+ }
+}
+function webViewerPageRendered({
+ pageNumber,
+ error
+}) {
+ if (pageNumber === PDFViewerApplication.page) {
+ PDFViewerApplication.toolbar?.updateLoadingIndicatorState(false);
+ }
+ if (PDFViewerApplication.pdfSidebar?.visibleView === SidebarView.THUMBS) {
+ const pageView = PDFViewerApplication.pdfViewer.getPageView(pageNumber - 1);
+ const thumbnailView = PDFViewerApplication.pdfThumbnailViewer?.getThumbnail(pageNumber - 1);
+ if (pageView) {
+ thumbnailView?.setImage(pageView);
+ }
+ }
+ if (error) {
+ PDFViewerApplication.l10n.get("pdfjs-rendering-error").then(msg => {
+ PDFViewerApplication._otherError(msg, error);
+ });
+ }
+}
+function webViewerPageMode({
+ mode
+}) {
+ let view;
+ switch (mode) {
+ case "thumbs":
+ view = SidebarView.THUMBS;
+ break;
+ case "bookmarks":
+ case "outline":
+ view = SidebarView.OUTLINE;
+ break;
+ case "attachments":
+ view = SidebarView.ATTACHMENTS;
+ break;
+ case "layers":
+ view = SidebarView.LAYERS;
+ break;
+ case "none":
+ view = SidebarView.NONE;
+ break;
+ default:
+ console.error('Invalid "pagemode" hash parameter: ' + mode);
+ return;
+ }
+ PDFViewerApplication.pdfSidebar?.switchView(view, true);
+}
+function webViewerNamedAction(evt) {
+ switch (evt.action) {
+ case "GoToPage":
+ PDFViewerApplication.appConfig.toolbar?.pageNumber.select();
+ break;
+ case "Find":
+ if (!PDFViewerApplication.supportsIntegratedFind) {
+ PDFViewerApplication.findBar?.toggle();
+ }
+ break;
+ case "Print":
+ PDFViewerApplication.triggerPrinting();
+ break;
+ case "SaveAs":
+ PDFViewerApplication.downloadOrSave();
+ break;
+ }
+}
+function webViewerPresentationModeChanged(evt) {
+ PDFViewerApplication.pdfViewer.presentationModeState = evt.state;
+}
+function webViewerSidebarViewChanged({
+ view
+}) {
+ PDFViewerApplication.pdfRenderingQueue.isThumbnailViewEnabled = view === SidebarView.THUMBS;
+ if (PDFViewerApplication.isInitialViewSet) {
+ PDFViewerApplication.store?.set("sidebarView", view).catch(() => {});
+ }
+}
+function webViewerUpdateViewarea({
+ location
+}) {
+ if (PDFViewerApplication.isInitialViewSet) {
+ PDFViewerApplication.store?.setMultiple({
+ page: location.pageNumber,
+ zoom: location.scale,
+ scrollLeft: location.left,
+ scrollTop: location.top,
+ rotation: location.rotation
+ }).catch(() => {});
+ }
+ if (PDFViewerApplication.appConfig.secondaryToolbar) {
+ const href = PDFViewerApplication.pdfLinkService.getAnchorUrl(location.pdfOpenParams);
+ PDFViewerApplication.appConfig.secondaryToolbar.viewBookmarkButton.href = href;
+ }
+}
+function webViewerScrollModeChanged(evt) {
+ if (PDFViewerApplication.isInitialViewSet && !PDFViewerApplication.pdfViewer.isInPresentationMode) {
+ PDFViewerApplication.store?.set("scrollMode", evt.mode).catch(() => {});
+ }
+}
+function webViewerSpreadModeChanged(evt) {
+ if (PDFViewerApplication.isInitialViewSet && !PDFViewerApplication.pdfViewer.isInPresentationMode) {
+ PDFViewerApplication.store?.set("spreadMode", evt.mode).catch(() => {});
+ }
+}
+function webViewerResize() {
+ const {
+ pdfDocument,
+ pdfViewer,
+ pdfRenderingQueue
+ } = PDFViewerApplication;
+ if (pdfRenderingQueue.printing && window.matchMedia("print").matches) {
+ return;
+ }
+ if (!pdfDocument) {
+ return;
+ }
+ const currentScaleValue = pdfViewer.currentScaleValue;
+ if (currentScaleValue === "auto" || currentScaleValue === "page-fit" || currentScaleValue === "page-width") {
+ pdfViewer.currentScaleValue = currentScaleValue;
+ }
+ pdfViewer.update();
+}
+function webViewerHashchange(evt) {
+ const hash = evt.hash;
+ if (!hash) {
+ return;
+ }
+ if (!PDFViewerApplication.isInitialViewSet) {
+ PDFViewerApplication.initialBookmark = hash;
+ } else if (!PDFViewerApplication.pdfHistory?.popStateInProgress) {
+ PDFViewerApplication.pdfLinkService.setHash(hash);
+ }
+}
+function webViewerPresentationMode() {
+ PDFViewerApplication.requestPresentationMode();
+}
+function webViewerSwitchAnnotationEditorMode(evt) {
+ PDFViewerApplication.pdfViewer.annotationEditorMode = evt;
+}
+function webViewerSwitchAnnotationEditorParams(evt) {
+ PDFViewerApplication.pdfViewer.annotationEditorParams = evt;
+}
+function webViewerPrint() {
+ PDFViewerApplication.triggerPrinting();
+}
+function webViewerDownload() {
+ PDFViewerApplication.downloadOrSave();
+}
+function webViewerOpenInExternalApp() {
+ PDFViewerApplication.openInExternalApp();
+}
+function webViewerFirstPage() {
+ PDFViewerApplication.page = 1;
+}
+function webViewerLastPage() {
+ PDFViewerApplication.page = PDFViewerApplication.pagesCount;
+}
+function webViewerNextPage() {
+ PDFViewerApplication.pdfViewer.nextPage();
+}
+function webViewerPreviousPage() {
+ PDFViewerApplication.pdfViewer.previousPage();
+}
+function webViewerZoomIn() {
+ PDFViewerApplication.zoomIn();
+}
+function webViewerZoomOut() {
+ PDFViewerApplication.zoomOut();
+}
+function webViewerZoomReset() {
+ PDFViewerApplication.zoomReset();
+}
+function webViewerPageNumberChanged(evt) {
+ const pdfViewer = PDFViewerApplication.pdfViewer;
+ if (evt.value !== "") {
+ PDFViewerApplication.pdfLinkService.goToPage(evt.value);
+ }
+ if (evt.value !== pdfViewer.currentPageNumber.toString() && evt.value !== pdfViewer.currentPageLabel) {
+ PDFViewerApplication.toolbar?.setPageNumber(pdfViewer.currentPageNumber, pdfViewer.currentPageLabel);
+ }
+}
+function webViewerScaleChanged(evt) {
+ PDFViewerApplication.pdfViewer.currentScaleValue = evt.value;
+}
+function webViewerRotateCw() {
+ PDFViewerApplication.rotatePages(90);
+}
+function webViewerRotateCcw() {
+ PDFViewerApplication.rotatePages(-90);
+}
+function webViewerOptionalContentConfig(evt) {
+ PDFViewerApplication.pdfViewer.optionalContentConfigPromise = evt.promise;
+}
+function webViewerSwitchScrollMode(evt) {
+ PDFViewerApplication.pdfViewer.scrollMode = evt.mode;
+}
+function webViewerSwitchSpreadMode(evt) {
+ PDFViewerApplication.pdfViewer.spreadMode = evt.mode;
+}
+function webViewerDocumentProperties() {
+ PDFViewerApplication.pdfDocumentProperties?.open();
+}
+function webViewerFindFromUrlHash(evt) {
+ PDFViewerApplication.eventBus.dispatch("find", {
+ source: evt.source,
+ type: "",
+ query: evt.query,
+ caseSensitive: false,
+ entireWord: false,
+ highlightAll: true,
+ findPrevious: false,
+ matchDiacritics: true
+ });
+}
+function webViewerUpdateFindMatchesCount({
+ matchesCount
+}) {
+ if (PDFViewerApplication.supportsIntegratedFind) {
+ PDFViewerApplication.externalServices.updateFindMatchesCount(matchesCount);
+ } else {
+ PDFViewerApplication.findBar?.updateResultsCount(matchesCount);
+ }
+}
+function webViewerUpdateFindControlState({
+ state,
+ previous,
+ matchesCount,
+ rawQuery
+}) {
+ if (PDFViewerApplication.supportsIntegratedFind) {
+ PDFViewerApplication.externalServices.updateFindControlState({
+ result: state,
+ findPrevious: previous,
+ matchesCount,
+ rawQuery
+ });
+ } else {
+ PDFViewerApplication.findBar?.updateUIState(state, previous, matchesCount);
+ }
+}
+function webViewerScaleChanging(evt) {
+ PDFViewerApplication.toolbar?.setPageScale(evt.presetValue, evt.scale);
+ PDFViewerApplication.pdfViewer.update();
+}
+function webViewerRotationChanging(evt) {
+ if (PDFViewerApplication.pdfThumbnailViewer) {
+ PDFViewerApplication.pdfThumbnailViewer.pagesRotation = evt.pagesRotation;
+ }
+ PDFViewerApplication.forceRendering();
+ PDFViewerApplication.pdfViewer.currentPageNumber = evt.pageNumber;
+}
+function webViewerPageChanging({
+ pageNumber,
+ pageLabel
+}) {
+ PDFViewerApplication.toolbar?.setPageNumber(pageNumber, pageLabel);
+ PDFViewerApplication.secondaryToolbar?.setPageNumber(pageNumber);
+ if (PDFViewerApplication.pdfSidebar?.visibleView === SidebarView.THUMBS) {
+ PDFViewerApplication.pdfThumbnailViewer?.scrollThumbnailIntoView(pageNumber);
+ }
+ const currentPage = PDFViewerApplication.pdfViewer.getPageView(pageNumber - 1);
+ PDFViewerApplication.toolbar?.updateLoadingIndicatorState(currentPage?.renderingState === RenderingStates.RUNNING);
+}
+function webViewerResolutionChange(evt) {
+ PDFViewerApplication.pdfViewer.refresh();
+}
+function webViewerVisibilityChange(evt) {
+ if (document.visibilityState === "visible") {
+ setZoomDisabledTimeout();
+ }
+}
+let zoomDisabledTimeout = null;
+function setZoomDisabledTimeout() {
+ if (zoomDisabledTimeout) {
+ clearTimeout(zoomDisabledTimeout);
+ }
+ zoomDisabledTimeout = setTimeout(function () {
+ zoomDisabledTimeout = null;
+ }, WHEEL_ZOOM_DISABLED_TIMEOUT);
+}
+function webViewerWheel(evt) {
+ const {
+ pdfViewer,
+ supportsMouseWheelZoomCtrlKey,
+ supportsMouseWheelZoomMetaKey,
+ supportsPinchToZoom
+ } = PDFViewerApplication;
+ if (pdfViewer.isInPresentationMode) {
+ return;
+ }
+ const deltaMode = evt.deltaMode;
+ let scaleFactor = Math.exp(-evt.deltaY / 100);
+ const isBuiltInMac = FeatureTest.platform.isMac;
+ const isPinchToZoom = evt.ctrlKey && !PDFViewerApplication._isCtrlKeyDown && deltaMode === WheelEvent.DOM_DELTA_PIXEL && evt.deltaX === 0 && (Math.abs(scaleFactor - 1) < 0.05 || isBuiltInMac) && evt.deltaZ === 0;
+ if (isPinchToZoom || evt.ctrlKey && supportsMouseWheelZoomCtrlKey || evt.metaKey && supportsMouseWheelZoomMetaKey) {
+ evt.preventDefault();
+ if (PDFViewerApplication._isScrolling || zoomDisabledTimeout || document.visibilityState === "hidden" || PDFViewerApplication.overlayManager.active) {
+ return;
+ }
+ const previousScale = pdfViewer.currentScale;
+ if (isPinchToZoom && supportsPinchToZoom) {
+ scaleFactor = PDFViewerApplication._accumulateFactor(previousScale, scaleFactor, "_wheelUnusedFactor");
+ if (scaleFactor < 1) {
+ PDFViewerApplication.zoomOut(null, scaleFactor);
+ } else if (scaleFactor > 1) {
+ PDFViewerApplication.zoomIn(null, scaleFactor);
+ } else {
+ return;
+ }
+ } else {
+ const delta = normalizeWheelEventDirection(evt);
+ let ticks = 0;
+ if (deltaMode === WheelEvent.DOM_DELTA_LINE || deltaMode === WheelEvent.DOM_DELTA_PAGE) {
+ if (Math.abs(delta) >= 1) {
+ ticks = Math.sign(delta);
+ } else {
+ ticks = PDFViewerApplication._accumulateTicks(delta, "_wheelUnusedTicks");
+ }
+ } else {
+ const PIXELS_PER_LINE_SCALE = 30;
+ ticks = PDFViewerApplication._accumulateTicks(delta / PIXELS_PER_LINE_SCALE, "_wheelUnusedTicks");
+ }
+ if (ticks < 0) {
+ PDFViewerApplication.zoomOut(-ticks);
+ } else if (ticks > 0) {
+ PDFViewerApplication.zoomIn(ticks);
+ } else {
+ return;
+ }
+ }
+ PDFViewerApplication._centerAtPos(previousScale, evt.clientX, evt.clientY);
+ }
+}
+function webViewerTouchStart(evt) {
+ if (PDFViewerApplication.pdfViewer.isInPresentationMode || evt.touches.length < 2) {
+ return;
+ }
+ evt.preventDefault();
+ if (evt.touches.length !== 2 || PDFViewerApplication.overlayManager.active) {
+ PDFViewerApplication._touchInfo = null;
+ return;
+ }
+ let [touch0, touch1] = evt.touches;
+ if (touch0.identifier > touch1.identifier) {
+ [touch0, touch1] = [touch1, touch0];
+ }
+ PDFViewerApplication._touchInfo = {
+ touch0X: touch0.pageX,
+ touch0Y: touch0.pageY,
+ touch1X: touch1.pageX,
+ touch1Y: touch1.pageY
+ };
+}
+function webViewerTouchMove(evt) {
+ if (!PDFViewerApplication._touchInfo || evt.touches.length !== 2) {
+ return;
+ }
+ const {
+ pdfViewer,
+ _touchInfo,
+ supportsPinchToZoom
+ } = PDFViewerApplication;
+ let [touch0, touch1] = evt.touches;
+ if (touch0.identifier > touch1.identifier) {
+ [touch0, touch1] = [touch1, touch0];
+ }
+ const {
+ pageX: page0X,
+ pageY: page0Y
+ } = touch0;
+ const {
+ pageX: page1X,
+ pageY: page1Y
+ } = touch1;
+ const {
+ touch0X: pTouch0X,
+ touch0Y: pTouch0Y,
+ touch1X: pTouch1X,
+ touch1Y: pTouch1Y
+ } = _touchInfo;
+ if (Math.abs(pTouch0X - page0X) <= 1 && Math.abs(pTouch0Y - page0Y) <= 1 && Math.abs(pTouch1X - page1X) <= 1 && Math.abs(pTouch1Y - page1Y) <= 1) {
+ return;
+ }
+ _touchInfo.touch0X = page0X;
+ _touchInfo.touch0Y = page0Y;
+ _touchInfo.touch1X = page1X;
+ _touchInfo.touch1Y = page1Y;
+ if (pTouch0X === page0X && pTouch0Y === page0Y) {
+ const v1X = pTouch1X - page0X;
+ const v1Y = pTouch1Y - page0Y;
+ const v2X = page1X - page0X;
+ const v2Y = page1Y - page0Y;
+ const det = v1X * v2Y - v1Y * v2X;
+ if (Math.abs(det) > 0.02 * Math.hypot(v1X, v1Y) * Math.hypot(v2X, v2Y)) {
+ return;
+ }
+ } else if (pTouch1X === page1X && pTouch1Y === page1Y) {
+ const v1X = pTouch0X - page1X;
+ const v1Y = pTouch0Y - page1Y;
+ const v2X = page0X - page1X;
+ const v2Y = page0Y - page1Y;
+ const det = v1X * v2Y - v1Y * v2X;
+ if (Math.abs(det) > 0.02 * Math.hypot(v1X, v1Y) * Math.hypot(v2X, v2Y)) {
+ return;
+ }
+ } else {
+ const diff0X = page0X - pTouch0X;
+ const diff1X = page1X - pTouch1X;
+ const diff0Y = page0Y - pTouch0Y;
+ const diff1Y = page1Y - pTouch1Y;
+ const dotProduct = diff0X * diff1X + diff0Y * diff1Y;
+ if (dotProduct >= 0) {
+ return;
+ }
+ }
+ evt.preventDefault();
+ const distance = Math.hypot(page0X - page1X, page0Y - page1Y) || 1;
+ const pDistance = Math.hypot(pTouch0X - pTouch1X, pTouch0Y - pTouch1Y) || 1;
+ const previousScale = pdfViewer.currentScale;
+ if (supportsPinchToZoom) {
+ const newScaleFactor = PDFViewerApplication._accumulateFactor(previousScale, distance / pDistance, "_touchUnusedFactor");
+ if (newScaleFactor < 1) {
+ PDFViewerApplication.zoomOut(null, newScaleFactor);
+ } else if (newScaleFactor > 1) {
+ PDFViewerApplication.zoomIn(null, newScaleFactor);
+ } else {
+ return;
+ }
+ } else {
+ const PIXELS_PER_LINE_SCALE = 30;
+ const ticks = PDFViewerApplication._accumulateTicks((distance - pDistance) / PIXELS_PER_LINE_SCALE, "_touchUnusedTicks");
+ if (ticks < 0) {
+ PDFViewerApplication.zoomOut(-ticks);
+ } else if (ticks > 0) {
+ PDFViewerApplication.zoomIn(ticks);
+ } else {
+ return;
+ }
+ }
+ PDFViewerApplication._centerAtPos(previousScale, (page0X + page1X) / 2, (page0Y + page1Y) / 2);
+}
+function webViewerTouchEnd(evt) {
+ if (!PDFViewerApplication._touchInfo) {
+ return;
+ }
+ evt.preventDefault();
+ PDFViewerApplication._touchInfo = null;
+ PDFViewerApplication._touchUnusedTicks = 0;
+ PDFViewerApplication._touchUnusedFactor = 1;
+}
+function webViewerClick(evt) {
+ if (!PDFViewerApplication.secondaryToolbar?.isOpen) {
+ return;
+ }
+ const appConfig = PDFViewerApplication.appConfig;
+ if (PDFViewerApplication.pdfViewer.containsElement(evt.target) || appConfig.toolbar?.container.contains(evt.target) && evt.target !== appConfig.secondaryToolbar?.toggleButton) {
+ PDFViewerApplication.secondaryToolbar.close();
+ }
+}
+function webViewerKeyUp(evt) {
+ if (evt.key === "Control") {
+ PDFViewerApplication._isCtrlKeyDown = false;
+ }
+}
+function webViewerKeyDown(evt) {
+ PDFViewerApplication._isCtrlKeyDown = evt.key === "Control";
+ if (PDFViewerApplication.overlayManager.active) {
+ return;
+ }
+ const {
+ eventBus,
+ pdfViewer
+ } = PDFViewerApplication;
+ const isViewerInPresentationMode = pdfViewer.isInPresentationMode;
+ let handled = false,
+ ensureViewerFocused = false;
+ const cmd = (evt.ctrlKey ? 1 : 0) | (evt.altKey ? 2 : 0) | (evt.shiftKey ? 4 : 0) | (evt.metaKey ? 8 : 0);
+ if (cmd === 1 || cmd === 8 || cmd === 5 || cmd === 12) {
+ switch (evt.keyCode) {
+ case 70:
+ if (!PDFViewerApplication.supportsIntegratedFind && !evt.shiftKey) {
+ PDFViewerApplication.findBar?.open();
+ handled = true;
+ }
+ break;
+ case 71:
+ if (!PDFViewerApplication.supportsIntegratedFind) {
+ const {
+ state
+ } = PDFViewerApplication.findController;
+ if (state) {
+ const newState = {
+ source: window,
+ type: "again",
+ findPrevious: cmd === 5 || cmd === 12
+ };
+ eventBus.dispatch("find", {
+ ...state,
+ ...newState
+ });
+ }
+ handled = true;
+ }
+ break;
+ case 61:
+ case 107:
+ case 187:
+ case 171:
+ PDFViewerApplication.zoomIn();
+ handled = true;
+ break;
+ case 173:
+ case 109:
+ case 189:
+ PDFViewerApplication.zoomOut();
+ handled = true;
+ break;
+ case 48:
+ case 96:
+ if (!isViewerInPresentationMode) {
+ setTimeout(function () {
+ PDFViewerApplication.zoomReset();
+ });
+ handled = false;
+ }
+ break;
+ case 38:
+ if (isViewerInPresentationMode || PDFViewerApplication.page > 1) {
+ PDFViewerApplication.page = 1;
+ handled = true;
+ ensureViewerFocused = true;
+ }
+ break;
+ case 40:
+ if (isViewerInPresentationMode || PDFViewerApplication.page < PDFViewerApplication.pagesCount) {
+ PDFViewerApplication.page = PDFViewerApplication.pagesCount;
+ handled = true;
+ ensureViewerFocused = true;
+ }
+ break;
+ }
+ }
+ if (cmd === 3 || cmd === 10) {
+ switch (evt.keyCode) {
+ case 80:
+ PDFViewerApplication.requestPresentationMode();
+ handled = true;
+ PDFViewerApplication.externalServices.reportTelemetry({
+ type: "buttons",
+ data: {
+ id: "presentationModeKeyboard"
+ }
+ });
+ break;
+ case 71:
+ if (PDFViewerApplication.appConfig.toolbar) {
+ PDFViewerApplication.appConfig.toolbar.pageNumber.select();
+ handled = true;
+ }
+ break;
+ }
+ }
+ if (handled) {
+ if (ensureViewerFocused && !isViewerInPresentationMode) {
+ pdfViewer.focus();
+ }
+ evt.preventDefault();
+ return;
+ }
+ const curElement = getActiveOrFocusedElement();
+ const curElementTagName = curElement?.tagName.toUpperCase();
+ if (curElementTagName === "INPUT" || curElementTagName === "TEXTAREA" || curElementTagName === "SELECT" || curElementTagName === "BUTTON" && (evt.keyCode === 13 || evt.keyCode === 32) || curElement?.isContentEditable) {
+ if (evt.keyCode !== 27) {
+ return;
+ }
+ }
+ if (cmd === 0) {
+ let turnPage = 0,
+ turnOnlyIfPageFit = false;
+ switch (evt.keyCode) {
+ case 38:
+ if (PDFViewerApplication.supportsCaretBrowsingMode) {
+ PDFViewerApplication.moveCaret(true, false);
+ handled = true;
+ break;
+ }
+ case 33:
+ if (pdfViewer.isVerticalScrollbarEnabled) {
+ turnOnlyIfPageFit = true;
+ }
+ turnPage = -1;
+ break;
+ case 8:
+ if (!isViewerInPresentationMode) {
+ turnOnlyIfPageFit = true;
+ }
+ turnPage = -1;
+ break;
+ case 37:
+ if (PDFViewerApplication.supportsCaretBrowsingMode) {
+ return;
+ }
+ if (pdfViewer.isHorizontalScrollbarEnabled) {
+ turnOnlyIfPageFit = true;
+ }
+ case 75:
+ case 80:
+ turnPage = -1;
+ break;
+ case 27:
+ if (PDFViewerApplication.secondaryToolbar?.isOpen) {
+ PDFViewerApplication.secondaryToolbar.close();
+ handled = true;
+ }
+ if (!PDFViewerApplication.supportsIntegratedFind && PDFViewerApplication.findBar?.opened) {
+ PDFViewerApplication.findBar.close();
+ handled = true;
+ }
+ break;
+ case 40:
+ if (PDFViewerApplication.supportsCaretBrowsingMode) {
+ PDFViewerApplication.moveCaret(false, false);
+ handled = true;
+ break;
+ }
+ case 34:
+ if (pdfViewer.isVerticalScrollbarEnabled) {
+ turnOnlyIfPageFit = true;
+ }
+ turnPage = 1;
+ break;
+ case 13:
+ case 32:
+ if (!isViewerInPresentationMode) {
+ turnOnlyIfPageFit = true;
+ }
+ turnPage = 1;
+ break;
+ case 39:
+ if (PDFViewerApplication.supportsCaretBrowsingMode) {
+ return;
+ }
+ if (pdfViewer.isHorizontalScrollbarEnabled) {
+ turnOnlyIfPageFit = true;
+ }
+ case 74:
+ case 78:
+ turnPage = 1;
+ break;
+ case 36:
+ if (isViewerInPresentationMode || PDFViewerApplication.page > 1) {
+ PDFViewerApplication.page = 1;
+ handled = true;
+ ensureViewerFocused = true;
+ }
+ break;
+ case 35:
+ if (isViewerInPresentationMode || PDFViewerApplication.page < PDFViewerApplication.pagesCount) {
+ PDFViewerApplication.page = PDFViewerApplication.pagesCount;
+ handled = true;
+ ensureViewerFocused = true;
+ }
+ break;
+ case 83:
+ PDFViewerApplication.pdfCursorTools?.switchTool(CursorTool.SELECT);
+ break;
+ case 72:
+ PDFViewerApplication.pdfCursorTools?.switchTool(CursorTool.HAND);
+ break;
+ case 82:
+ PDFViewerApplication.rotatePages(90);
+ break;
+ case 115:
+ PDFViewerApplication.pdfSidebar?.toggle();
+ break;
+ }
+ if (turnPage !== 0 && (!turnOnlyIfPageFit || pdfViewer.currentScaleValue === "page-fit")) {
+ if (turnPage > 0) {
+ pdfViewer.nextPage();
+ } else {
+ pdfViewer.previousPage();
+ }
+ handled = true;
+ }
+ }
+ if (cmd === 4) {
+ switch (evt.keyCode) {
+ case 13:
+ case 32:
+ if (!isViewerInPresentationMode && pdfViewer.currentScaleValue !== "page-fit") {
+ break;
+ }
+ pdfViewer.previousPage();
+ handled = true;
+ break;
+ case 38:
+ PDFViewerApplication.moveCaret(true, true);
+ handled = true;
+ break;
+ case 40:
+ PDFViewerApplication.moveCaret(false, true);
+ handled = true;
+ break;
+ case 82:
+ PDFViewerApplication.rotatePages(-90);
+ break;
+ }
+ }
+ if (!handled && !isViewerInPresentationMode) {
+ if (evt.keyCode >= 33 && evt.keyCode <= 40 || evt.keyCode === 32 && curElementTagName !== "BUTTON") {
+ ensureViewerFocused = true;
+ }
+ }
+ if (ensureViewerFocused && !pdfViewer.containsElement(curElement)) {
+ pdfViewer.focus();
+ }
+ if (handled) {
+ evt.preventDefault();
+ }
+}
+function beforeUnload(evt) {
+ evt.preventDefault();
+ evt.returnValue = "";
+ return false;
+}
+function webViewerAnnotationEditorStatesChanged(data) {
+ PDFViewerApplication.externalServices.updateEditorStates(data);
+}
+function webViewerReportTelemetry({
+ details
+}) {
+ PDFViewerApplication.externalServices.reportTelemetry(details);
+}
+
+;// CONCATENATED MODULE: ./web/viewer-geckoview.js
+
+
+
+
+const pdfjsVersion = "4.1.249";
+const pdfjsBuild = "d07f37f44";
+const AppConstants = null;
+window.PDFViewerApplication = PDFViewerApplication;
+window.PDFViewerApplicationConstants = AppConstants;
+window.PDFViewerApplicationOptions = AppOptions;
+function getViewerConfiguration() {
+ const mainContainer = document.getElementById("viewerContainer");
+ return {
+ appContainer: document.body,
+ mainContainer,
+ viewerContainer: document.getElementById("viewer"),
+ toolbar: {
+ mainContainer,
+ container: document.getElementById("floatingToolbar"),
+ download: document.getElementById("download"),
+ openInApp: document.getElementById("openInApp")
+ },
+ passwordOverlay: {
+ dialog: document.getElementById("passwordDialog"),
+ label: document.getElementById("passwordText"),
+ input: document.getElementById("password"),
+ submitButton: document.getElementById("passwordSubmit"),
+ cancelButton: document.getElementById("passwordCancel")
+ },
+ printContainer: document.getElementById("printContainer")
+ };
+}
+function webViewerLoad() {
+ const config = getViewerConfiguration();
+ PDFViewerApplication.run(config);
+}
+document.blockUnblockOnload?.(true);
+if (document.readyState === "interactive" || document.readyState === "complete") {
+ webViewerLoad();
+} else {
+ document.addEventListener("DOMContentLoaded", webViewerLoad, true);
+}
+
+var __webpack_exports__PDFViewerApplication = __webpack_exports__.PDFViewerApplication;
+var __webpack_exports__PDFViewerApplicationConstants = __webpack_exports__.PDFViewerApplicationConstants;
+var __webpack_exports__PDFViewerApplicationOptions = __webpack_exports__.PDFViewerApplicationOptions;
+export { __webpack_exports__PDFViewerApplication as PDFViewerApplication, __webpack_exports__PDFViewerApplicationConstants as PDFViewerApplicationConstants, __webpack_exports__PDFViewerApplicationOptions as PDFViewerApplicationOptions };
diff --git a/toolkit/components/pdfjs/content/web/viewer.css b/toolkit/components/pdfjs/content/web/viewer.css
new file mode 100644
index 0000000000..238df7ce7f
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/viewer.css
@@ -0,0 +1,3648 @@
+/* Copyright 2014 Mozilla Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+.textLayer{
+ position:absolute;
+ text-align:initial;
+ inset:0;
+ overflow:hidden;
+ opacity:1;
+ line-height:1;
+ text-size-adjust:none;
+ forced-color-adjust:none;
+ transform-origin:0 0;
+ z-index:2;
+ caret-color:CanvasText;
+
+ &.highlighting{
+ touch-action:none;
+ }
+
+ :is(span, br){
+ color:transparent;
+ position:absolute;
+ white-space:pre;
+ cursor:text;
+ transform-origin:0% 0%;
+ }
+
+ .highlight{
+ --highlight-bg-color:rgb(180 0 170 / 0.25);
+ --highlight-selected-bg-color:rgb(0 100 0 / 0.25);
+ --highlight-backdrop-filter:none;
+ --highlight-selected-backdrop-filter:none;
+
+ @media screen and (forced-colors: active){
+ --highlight-bg-color:transparent;
+ --highlight-selected-bg-color:transparent;
+ --highlight-backdrop-filter:var(--hcm-highlight-filter);
+ --highlight-selected-backdrop-filter:var(
+ --hcm-highlight-selected-filter
+ );
+ }
+
+ margin:-1px;
+ padding:1px;
+ background-color:var(--highlight-bg-color);
+ backdrop-filter:var(--highlight-backdrop-filter);
+ border-radius:4px;
+
+ &.appended{
+ position:initial;
+ }
+
+ &.begin{
+ border-radius:4px 0 0 4px;
+ }
+
+ &.end{
+ border-radius:0 4px 4px 0;
+ }
+
+ &.middle{
+ border-radius:0;
+ }
+
+ &.selected{
+ background-color:var(--highlight-selected-bg-color);
+ backdrop-filter:var(--highlight-selected-backdrop-filter);
+ }
+ }
+
+ ::selection{
+ background:color-mix(in srgb, AccentColor, transparent 75%);
+ }
+
+ .endOfContent{
+ display:block;
+ position:absolute;
+ inset:100% 0 0;
+ z-index:-1;
+ cursor:default;
+ user-select:none;
+
+ &.active{
+ top:0;
+ }
+ }
+}
+
+.annotationLayer{
+ --annotation-unfocused-field-background:url("data:image/svg+xml;charset=UTF-8,<svg width='1px' height='1px' xmlns='http://www.w3.org/2000/svg'><rect width='100%' height='100%' style='fill:rgba(0, 54, 255, 0.13);'/></svg>");
+ --input-focus-border-color:Highlight;
+ --input-focus-outline:1px solid Canvas;
+ --input-unfocused-border-color:transparent;
+ --input-disabled-border-color:transparent;
+ --input-hover-border-color:black;
+ --link-outline:none;
+
+ @media screen and (forced-colors: active){
+ --input-focus-border-color:CanvasText;
+ --input-unfocused-border-color:ActiveText;
+ --input-disabled-border-color:GrayText;
+ --input-hover-border-color:Highlight;
+ --link-outline:1.5px solid LinkText;
+
+ .textWidgetAnnotation :is(input, textarea):required,
+ .choiceWidgetAnnotation select:required,
+ .buttonWidgetAnnotation:is(.checkBox, .radioButton) input:required{
+ outline:1.5px solid selectedItem;
+ }
+
+ .linkAnnotation{
+ outline:var(--link-outline);
+
+ &:hover{
+ backdrop-filter:var(--hcm-highlight-filter);
+ }
+
+ & > a:hover{
+ opacity:0 !important;
+ background:none !important;
+ box-shadow:none;
+ }
+ }
+
+ .popupAnnotation .popup{
+ outline:calc(1.5px * var(--scale-factor)) solid CanvasText !important;
+ background-color:ButtonFace !important;
+ color:ButtonText !important;
+ }
+
+ .highlightArea:hover::after{
+ position:absolute;
+ top:0;
+ left:0;
+ width:100%;
+ height:100%;
+ backdrop-filter:var(--hcm-highlight-filter);
+ content:"";
+ pointer-events:none;
+ }
+
+ .popupAnnotation.focused .popup{
+ outline:calc(3px * var(--scale-factor)) solid Highlight !important;
+ }
+ }
+
+ position:absolute;
+ top:0;
+ left:0;
+ pointer-events:none;
+ transform-origin:0 0;
+ z-index:3;
+
+ &[data-main-rotation="90"] .norotate{
+ transform:rotate(270deg) translateX(-100%);
+ }
+ &[data-main-rotation="180"] .norotate{
+ transform:rotate(180deg) translate(-100%, -100%);
+ }
+ &[data-main-rotation="270"] .norotate{
+ transform:rotate(90deg) translateY(-100%);
+ }
+
+ &.disabled{
+ section,
+ .popup{
+ pointer-events:none;
+ }
+ }
+
+ canvas{
+ position:absolute;
+ width:100%;
+ height:100%;
+ pointer-events:none;
+ }
+
+ section{
+ position:absolute;
+ text-align:initial;
+ pointer-events:auto;
+ box-sizing:border-box;
+ transform-origin:0 0;
+ }
+
+ :is(.linkAnnotation, .buttonWidgetAnnotation.pushButton) > a{
+ position:absolute;
+ font-size:1em;
+ top:0;
+ left:0;
+ width:100%;
+ height:100%;
+ }
+
+ :is(.linkAnnotation, .buttonWidgetAnnotation.pushButton):not(.hasBorder)
+ > a:hover{
+ opacity:0.2;
+ background-color:rgb(255 255 0);
+ box-shadow:0 2px 10px rgb(255 255 0);
+ }
+
+ .linkAnnotation.hasBorder:hover{
+ background-color:rgb(255 255 0 / 0.2);
+ }
+
+ .hasBorder{
+ background-size:100% 100%;
+ }
+
+ .textAnnotation img{
+ position:absolute;
+ cursor:pointer;
+ width:100%;
+ height:100%;
+ top:0;
+ left:0;
+ }
+
+ .textWidgetAnnotation :is(input, textarea),
+ .choiceWidgetAnnotation select,
+ .buttonWidgetAnnotation:is(.checkBox, .radioButton) input{
+ background-image:var(--annotation-unfocused-field-background);
+ border:2px solid var(--input-unfocused-border-color);
+ box-sizing:border-box;
+ font:calc(9px * var(--scale-factor)) sans-serif;
+ height:100%;
+ margin:0;
+ vertical-align:top;
+ width:100%;
+ }
+
+ .textWidgetAnnotation :is(input, textarea):required,
+ .choiceWidgetAnnotation select:required,
+ .buttonWidgetAnnotation:is(.checkBox, .radioButton) input:required{
+ outline:1.5px solid red;
+ }
+
+ .choiceWidgetAnnotation select option{
+ padding:0;
+ }
+
+ .buttonWidgetAnnotation.radioButton input{
+ border-radius:50%;
+ }
+
+ .textWidgetAnnotation textarea{
+ resize:none;
+ }
+
+ .textWidgetAnnotation :is(input, textarea)[disabled],
+ .choiceWidgetAnnotation select[disabled],
+ .buttonWidgetAnnotation:is(.checkBox, .radioButton) input[disabled]{
+ background:none;
+ border:2px solid var(--input-disabled-border-color);
+ cursor:not-allowed;
+ }
+
+ .textWidgetAnnotation :is(input, textarea):hover,
+ .choiceWidgetAnnotation select:hover,
+ .buttonWidgetAnnotation:is(.checkBox, .radioButton) input:hover{
+ border:2px solid var(--input-hover-border-color);
+ }
+ .textWidgetAnnotation :is(input, textarea):hover,
+ .choiceWidgetAnnotation select:hover,
+ .buttonWidgetAnnotation.checkBox input:hover{
+ border-radius:2px;
+ }
+
+ .textWidgetAnnotation :is(input, textarea):focus,
+ .choiceWidgetAnnotation select:focus{
+ background:none;
+ border:2px solid var(--input-focus-border-color);
+ border-radius:2px;
+ outline:var(--input-focus-outline);
+ }
+
+ .buttonWidgetAnnotation:is(.checkBox, .radioButton) :focus{
+ background-image:none;
+ background-color:transparent;
+ }
+
+ .buttonWidgetAnnotation.checkBox :focus{
+ border:2px solid var(--input-focus-border-color);
+ border-radius:2px;
+ outline:var(--input-focus-outline);
+ }
+
+ .buttonWidgetAnnotation.radioButton :focus{
+ border:2px solid var(--input-focus-border-color);
+ outline:var(--input-focus-outline);
+ }
+
+ .buttonWidgetAnnotation.checkBox input:checked::before,
+ .buttonWidgetAnnotation.checkBox input:checked::after,
+ .buttonWidgetAnnotation.radioButton input:checked::before{
+ background-color:CanvasText;
+ content:"";
+ display:block;
+ position:absolute;
+ }
+
+ .buttonWidgetAnnotation.checkBox input:checked::before,
+ .buttonWidgetAnnotation.checkBox input:checked::after{
+ height:80%;
+ left:45%;
+ width:1px;
+ }
+
+ .buttonWidgetAnnotation.checkBox input:checked::before{
+ transform:rotate(45deg);
+ }
+
+ .buttonWidgetAnnotation.checkBox input:checked::after{
+ transform:rotate(-45deg);
+ }
+
+ .buttonWidgetAnnotation.radioButton input:checked::before{
+ border-radius:50%;
+ height:50%;
+ left:25%;
+ top:25%;
+ width:50%;
+ }
+
+ .textWidgetAnnotation input.comb{
+ font-family:monospace;
+ padding-left:2px;
+ padding-right:0;
+ }
+
+ .textWidgetAnnotation input.comb:focus{
+ width:103%;
+ }
+
+ .buttonWidgetAnnotation:is(.checkBox, .radioButton) input{
+ appearance:none;
+ }
+
+ .fileAttachmentAnnotation .popupTriggerArea{
+ height:100%;
+ width:100%;
+ }
+
+ .popupAnnotation{
+ position:absolute;
+ font-size:calc(9px * var(--scale-factor));
+ pointer-events:none;
+ width:max-content;
+ max-width:45%;
+ height:auto;
+ }
+
+ .popup{
+ background-color:rgb(255 255 153);
+ box-shadow:0 calc(2px * var(--scale-factor)) calc(5px * var(--scale-factor)) rgb(136 136 136);
+ border-radius:calc(2px * var(--scale-factor));
+ outline:1.5px solid rgb(255 255 74);
+ padding:calc(6px * var(--scale-factor));
+ cursor:pointer;
+ font:message-box;
+ white-space:normal;
+ word-wrap:break-word;
+ pointer-events:auto;
+ }
+
+ .popupAnnotation.focused .popup{
+ outline-width:3px;
+ }
+
+ .popup *{
+ font-size:calc(9px * var(--scale-factor));
+ }
+
+ .popup > .header{
+ display:inline-block;
+ }
+
+ .popup > .header h1{
+ display:inline;
+ }
+
+ .popup > .header .popupDate{
+ display:inline-block;
+ margin-left:calc(5px * var(--scale-factor));
+ width:-moz-fit-content;
+ width:fit-content;
+ }
+
+ .popupContent{
+ border-top:1px solid rgb(51 51 51);
+ margin-top:calc(2px * var(--scale-factor));
+ padding-top:calc(2px * var(--scale-factor));
+ }
+
+ .richText > *{
+ white-space:pre-wrap;
+ font-size:calc(9px * var(--scale-factor));
+ }
+
+ .popupTriggerArea{
+ cursor:pointer;
+ }
+
+ section svg{
+ position:absolute;
+ width:100%;
+ height:100%;
+ top:0;
+ left:0;
+ }
+
+ .annotationTextContent{
+ position:absolute;
+ width:100%;
+ height:100%;
+ opacity:0;
+ color:transparent;
+ user-select:none;
+ pointer-events:none;
+
+ span{
+ width:100%;
+ display:inline-block;
+ }
+ }
+
+ svg.quadrilateralsContainer{
+ contain:strict;
+ width:0;
+ height:0;
+ position:absolute;
+ top:0;
+ left:0;
+ z-index:-1;
+ }
+}
+
+:root{
+ --xfa-unfocused-field-background:url("data:image/svg+xml;charset=UTF-8,<svg width='1px' height='1px' xmlns='http://www.w3.org/2000/svg'><rect width='100%' height='100%' style='fill:rgba(0, 54, 255, 0.13);'/></svg>");
+ --xfa-focus-outline:auto;
+}
+
+@media screen and (forced-colors: active){
+ :root{
+ --xfa-focus-outline:2px solid CanvasText;
+ }
+ .xfaLayer *:required{
+ outline:1.5px solid selectedItem;
+ }
+}
+
+.xfaLayer{
+ background-color:transparent;
+}
+
+.xfaLayer .highlight{
+ margin:-1px;
+ padding:1px;
+ background-color:rgb(239 203 237);
+ border-radius:4px;
+}
+
+.xfaLayer .highlight.appended{
+ position:initial;
+}
+
+.xfaLayer .highlight.begin{
+ border-radius:4px 0 0 4px;
+}
+
+.xfaLayer .highlight.end{
+ border-radius:0 4px 4px 0;
+}
+
+.xfaLayer .highlight.middle{
+ border-radius:0;
+}
+
+.xfaLayer .highlight.selected{
+ background-color:rgb(203 223 203);
+}
+
+.xfaPage{
+ overflow:hidden;
+ position:relative;
+}
+
+.xfaContentarea{
+ position:absolute;
+}
+
+.xfaPrintOnly{
+ display:none;
+}
+
+.xfaLayer{
+ position:absolute;
+ text-align:initial;
+ top:0;
+ left:0;
+ transform-origin:0 0;
+ line-height:1.2;
+}
+
+.xfaLayer *{
+ color:inherit;
+ font:inherit;
+ font-style:inherit;
+ font-weight:inherit;
+ font-kerning:inherit;
+ letter-spacing:-0.01px;
+ text-align:inherit;
+ text-decoration:inherit;
+ box-sizing:border-box;
+ background-color:transparent;
+ padding:0;
+ margin:0;
+ pointer-events:auto;
+ line-height:inherit;
+}
+
+.xfaLayer *:required{
+ outline:1.5px solid red;
+}
+
+.xfaLayer div,
+.xfaLayer svg,
+.xfaLayer svg *{
+ pointer-events:none;
+}
+
+.xfaLayer a{
+ color:blue;
+}
+
+.xfaRich li{
+ margin-left:3em;
+}
+
+.xfaFont{
+ color:black;
+ font-weight:normal;
+ font-kerning:none;
+ font-size:10px;
+ font-style:normal;
+ letter-spacing:0;
+ text-decoration:none;
+ vertical-align:0;
+}
+
+.xfaCaption{
+ overflow:hidden;
+ flex:0 0 auto;
+}
+
+.xfaCaptionForCheckButton{
+ overflow:hidden;
+ flex:1 1 auto;
+}
+
+.xfaLabel{
+ height:100%;
+ width:100%;
+}
+
+.xfaLeft{
+ display:flex;
+ flex-direction:row;
+ align-items:center;
+}
+
+.xfaRight{
+ display:flex;
+ flex-direction:row-reverse;
+ align-items:center;
+}
+
+:is(.xfaLeft, .xfaRight) > :is(.xfaCaption, .xfaCaptionForCheckButton){
+ max-height:100%;
+}
+
+.xfaTop{
+ display:flex;
+ flex-direction:column;
+ align-items:flex-start;
+}
+
+.xfaBottom{
+ display:flex;
+ flex-direction:column-reverse;
+ align-items:flex-start;
+}
+
+:is(.xfaTop, .xfaBottom) > :is(.xfaCaption, .xfaCaptionForCheckButton){
+ width:100%;
+}
+
+.xfaBorder{
+ background-color:transparent;
+ position:absolute;
+ pointer-events:none;
+}
+
+.xfaWrapped{
+ width:100%;
+ height:100%;
+}
+
+:is(.xfaTextfield, .xfaSelect):focus{
+ background-image:none;
+ background-color:transparent;
+ outline:var(--xfa-focus-outline);
+ outline-offset:-1px;
+}
+
+:is(.xfaCheckbox, .xfaRadio):focus{
+ outline:var(--xfa-focus-outline);
+}
+
+.xfaTextfield,
+.xfaSelect{
+ height:100%;
+ width:100%;
+ flex:1 1 auto;
+ border:none;
+ resize:none;
+ background-image:var(--xfa-unfocused-field-background);
+}
+
+.xfaSelect{
+ padding-inline:2px;
+}
+
+:is(.xfaTop, .xfaBottom) > :is(.xfaTextfield, .xfaSelect){
+ flex:0 1 auto;
+}
+
+.xfaButton{
+ cursor:pointer;
+ width:100%;
+ height:100%;
+ border:none;
+ text-align:center;
+}
+
+.xfaLink{
+ width:100%;
+ height:100%;
+ position:absolute;
+ top:0;
+ left:0;
+}
+
+.xfaCheckbox,
+.xfaRadio{
+ width:100%;
+ height:100%;
+ flex:0 0 auto;
+ border:none;
+}
+
+.xfaRich{
+ white-space:pre-wrap;
+ width:100%;
+ height:100%;
+}
+
+.xfaImage{
+ object-position:left top;
+ object-fit:contain;
+ width:100%;
+ height:100%;
+}
+
+.xfaLrTb,
+.xfaRlTb,
+.xfaTb{
+ display:flex;
+ flex-direction:column;
+ align-items:stretch;
+}
+
+.xfaLr{
+ display:flex;
+ flex-direction:row;
+ align-items:stretch;
+}
+
+.xfaRl{
+ display:flex;
+ flex-direction:row-reverse;
+ align-items:stretch;
+}
+
+.xfaTb > div{
+ justify-content:left;
+}
+
+.xfaPosition{
+ position:relative;
+}
+
+.xfaArea{
+ position:relative;
+}
+
+.xfaValignMiddle{
+ display:flex;
+ align-items:center;
+}
+
+.xfaTable{
+ display:flex;
+ flex-direction:column;
+ align-items:stretch;
+}
+
+.xfaTable .xfaRow{
+ display:flex;
+ flex-direction:row;
+ align-items:stretch;
+}
+
+.xfaTable .xfaRlRow{
+ display:flex;
+ flex-direction:row-reverse;
+ align-items:stretch;
+ flex:1;
+}
+
+.xfaTable .xfaRlRow > div{
+ flex:1;
+}
+
+:is(.xfaNonInteractive, .xfaDisabled, .xfaReadOnly) :is(input, textarea){
+ background:initial;
+}
+
+@media print{
+ .xfaTextfield,
+ .xfaSelect{
+ background:transparent;
+ }
+
+ .xfaSelect{
+ appearance:none;
+ text-indent:1px;
+ text-overflow:"";
+ }
+}
+
+.canvasWrapper{
+ svg{
+ transform:none;
+
+ &[data-main-rotation="90"]{
+ mask,
+ use:not(.clip, .mask){
+ transform:matrix(0, 1, -1, 0, 1, 0);
+ }
+ }
+
+ &[data-main-rotation="180"]{
+ mask,
+ use:not(.clip, .mask){
+ transform:matrix(-1, 0, 0, -1, 1, 1);
+ }
+ }
+
+ &[data-main-rotation="270"]{
+ mask,
+ use:not(.clip, .mask){
+ transform:matrix(0, -1, 1, 0, 0, 1);
+ }
+ }
+
+ &.highlight{
+ --blend-mode:multiply;
+
+ @media screen and (forced-colors: active){
+ --blend-mode:difference;
+ }
+
+ position:absolute;
+ mix-blend-mode:var(--blend-mode);
+
+ &:not(.free){
+ fill-rule:evenodd;
+ }
+ }
+
+ &.highlightOutline{
+ position:absolute;
+ mix-blend-mode:normal;
+ fill-rule:evenodd;
+ fill:none;
+
+ &:not(.free){
+ &.hovered:not(.selected){
+ stroke:var(--hover-outline-color);
+ stroke-width:var(--outline-width);
+ }
+
+ &.selected{
+ .mainOutline{
+ stroke:var(--outline-around-color);
+ stroke-width:calc(
+ var(--outline-width) + 2 * var(--outline-around-width)
+ );
+ }
+
+ .secondaryOutline{
+ stroke:var(--outline-color);
+ stroke-width:var(--outline-width);
+ }
+ }
+ }
+
+ &.free{
+ &.hovered:not(.selected){
+ stroke:var(--hover-outline-color);
+ stroke-width:calc(2 * var(--outline-width));
+ }
+
+ &.selected{
+ .mainOutline{
+ stroke:var(--outline-around-color);
+ stroke-width:calc(
+ 2 * (var(--outline-width) + var(--outline-around-width))
+ );
+ }
+
+ .secondaryOutline{
+ stroke:var(--outline-color);
+ stroke-width:calc(2 * var(--outline-width));
+ }
+ }
+ }
+ }
+ }
+}
+
+:root{
+ --outline-width:2px;
+ --outline-color:#0060df;
+ --outline-around-width:1px;
+ --outline-around-color:#f0f0f4;
+ --hover-outline-around-color:var(--outline-around-color);
+ --focus-outline:solid var(--outline-width) var(--outline-color);
+ --unfocus-outline:solid var(--outline-width) transparent;
+ --focus-outline-around:solid var(--outline-around-width) var(--outline-around-color);
+ --hover-outline-color:#8f8f9d;
+ --hover-outline:solid var(--outline-width) var(--hover-outline-color);
+ --hover-outline-around:solid var(--outline-around-width) var(--hover-outline-around-color);
+ --freetext-line-height:1.35;
+ --freetext-padding:2px;
+ --resizer-bg-color:var(--outline-color);
+ --resizer-size:6px;
+ --resizer-shift:calc(
+ 0px - (var(--outline-width) + var(--resizer-size)) / 2 -
+ var(--outline-around-width)
+ );
+ --editorFreeText-editing-cursor:text;
+ --editorInk-editing-cursor:url(images/cursor-editorInk.svg) 0 16, pointer;
+ --editorHighlight-editing-cursor:url(images/cursor-editorTextHighlight.svg) 24 24, text;
+ --editorFreeHighlight-editing-cursor:url(images/cursor-editorFreeHighlight.svg) 1 18, pointer;
+}
+
+.textLayer.highlighting{
+ cursor:var(--editorFreeHighlight-editing-cursor);
+
+ &:not(.free) span{
+ cursor:var(--editorHighlight-editing-cursor);
+ }
+
+ &.free span{
+ cursor:var(--editorFreeHighlight-editing-cursor);
+ }
+}
+
+@media (min-resolution: 1.1dppx){
+ :root{
+ --editorFreeText-editing-cursor:url(images/cursor-editorFreeText.svg) 0 16, text;
+ }
+}
+
+@media screen and (forced-colors: active){
+ :root{
+ --outline-color:CanvasText;
+ --outline-around-color:ButtonFace;
+ --resizer-bg-color:ButtonText;
+ --hover-outline-color:Highlight;
+ --hover-outline-around-color:SelectedItemText;
+ }
+}
+
+[data-editor-rotation="90"]{
+ transform:rotate(90deg);
+}
+
+[data-editor-rotation="180"]{
+ transform:rotate(180deg);
+}
+
+[data-editor-rotation="270"]{
+ transform:rotate(270deg);
+}
+
+.annotationEditorLayer{
+ background:transparent;
+ position:absolute;
+ inset:0;
+ font-size:calc(100px * var(--scale-factor));
+ transform-origin:0 0;
+ cursor:auto;
+ z-index:4;
+}
+
+.annotationEditorLayer.waiting{
+ content:"";
+ cursor:wait;
+ position:absolute;
+ inset:0;
+ width:100%;
+ height:100%;
+}
+
+.annotationEditorLayer.disabled{
+ pointer-events:none;
+}
+
+.annotationEditorLayer.freetextEditing{
+ cursor:var(--editorFreeText-editing-cursor);
+}
+
+.annotationEditorLayer.inkEditing{
+ cursor:var(--editorInk-editing-cursor);
+}
+
+.annotationEditorLayer :is(.freeTextEditor, .inkEditor, .stampEditor){
+ position:absolute;
+ background:transparent;
+ z-index:1;
+ transform-origin:0 0;
+ cursor:auto;
+ max-width:100%;
+ max-height:100%;
+ border:var(--unfocus-outline);
+
+ &.draggable.selectedEditor{
+ cursor:move;
+ }
+
+ &.moving{
+ touch-action:none;
+ }
+
+ &.selectedEditor{
+ border:var(--focus-outline);
+ outline:var(--focus-outline-around);
+
+ &::before{
+ content:"";
+ position:absolute;
+ inset:0;
+ border:var(--focus-outline-around);
+ pointer-events:none;
+ }
+ }
+
+ &:hover:not(.selectedEditor){
+ border:var(--hover-outline);
+ outline:var(--hover-outline-around);
+
+ &::before{
+ content:"";
+ position:absolute;
+ inset:0;
+ border:var(--focus-outline-around);
+ }
+ }
+}
+
+.annotationEditorLayer
+ :is(.freeTextEditor, .inkEditor, .stampEditor, .highlightEditor){
+ .editToolbar{
+ --editor-toolbar-delete-image:url(images/editor-toolbar-delete.svg);
+ --editor-toolbar-bg-color:#f0f0f4;
+ --editor-toolbar-fg-color:#2e2e56;
+ --editor-toolbar-border-color:#8f8f9d;
+ --editor-toolbar-hover-border-color:var(--editor-toolbar-border-color);
+ --editor-toolbar-hover-bg-color:#e0e0e6;
+ --editor-toolbar-hover-fg-color:var(--editor-toolbar-fg-color);
+ --editor-toolbar-hover-outline:none;
+ --editor-toolbar-focus-outline-color:#0060df;
+ --editor-toolbar-shadow:0 2px 6px 0 rgb(58 57 68 / 0.2);
+ --editor-toolbar-vert-offset:6px;
+ --editor-toolbar-height:28px;
+ --editor-toolbar-padding:2px;
+
+ @media (prefers-color-scheme: dark){
+ --editor-toolbar-bg-color:#2b2a33;
+ --editor-toolbar-fg-color:#fbfbfe;
+ --editor-toolbar-hover-bg-color:#52525e;
+ --editor-toolbar-focus-outline-color:#0df;
+ }
+
+ @media screen and (forced-colors: active){
+ --editor-toolbar-bg-color:ButtonFace;
+ --editor-toolbar-fg-color:ButtonText;
+ --editor-toolbar-border-color:ButtonText;
+ --editor-toolbar-hover-border-color:AccentColor;
+ --editor-toolbar-hover-bg-color:ButtonFace;
+ --editor-toolbar-hover-fg-color:AccentColor;
+ --editor-toolbar-hover-outline:2px solid var(--editor-toolbar-hover-border-color);
+ --editor-toolbar-focus-outline-color:ButtonBorder;
+ --editor-toolbar-shadow:none;
+ }
+
+ display:flex;
+ width:-moz-fit-content;
+ width:fit-content;
+ height:var(--editor-toolbar-height);
+ flex-direction:column;
+ justify-content:center;
+ align-items:center;
+ cursor:default;
+ pointer-events:auto;
+ box-sizing:content-box;
+ padding:var(--editor-toolbar-padding);
+
+ position:absolute;
+ inset-inline-end:0;
+ inset-block-start:calc(100% + var(--editor-toolbar-vert-offset));
+
+ border-radius:6px;
+ background-color:var(--editor-toolbar-bg-color);
+ border:1px solid var(--editor-toolbar-border-color);
+ box-shadow:var(--editor-toolbar-shadow);
+
+ &.hidden{
+ display:none;
+ }
+
+ &:has(:focus-visible){
+ border-color:transparent;
+ }
+
+ &:dir(ltr){
+ transform-origin:100% 0;
+ }
+
+ &:dir(rtl){
+ transform-origin:0 0;
+ }
+
+ .buttons{
+ display:flex;
+ justify-content:center;
+ align-items:center;
+ gap:0;
+ height:100%;
+
+ .divider{
+ width:1px;
+ height:calc(
+ 2 * var(--editor-toolbar-padding) + var(--editor-toolbar-height)
+ );
+ background-color:var(--editor-toolbar-border-color);
+ display:inline-block;
+ margin-inline:2px;
+ }
+
+ .delete{
+ width:var(--editor-toolbar-height);
+
+ &::before{
+ content:"";
+ mask-image:var(--editor-toolbar-delete-image);
+ mask-repeat:no-repeat;
+ mask-position:center;
+ display:inline-block;
+ background-color:var(--editor-toolbar-fg-color);
+ width:100%;
+ height:100%;
+ }
+
+ &:hover::before{
+ background-color:var(--editor-toolbar-hover-fg-color);
+ }
+ }
+
+ > *{
+ height:var(--editor-toolbar-height);
+ }
+
+ > :not(.divider){
+ border:none;
+ background-color:transparent;
+ cursor:pointer;
+
+ &:hover{
+ border-radius:2px;
+ background-color:var(--editor-toolbar-hover-bg-color);
+ color:var(--editor-toolbar-hover-fg-color);
+ outline:var(--editor-toolbar-hover-outline);
+ outline-offset:1px;
+
+ &:active{
+ outline:none;
+ }
+ }
+
+ &:focus-visible{
+ border-radius:2px;
+ outline:2px solid var(--editor-toolbar-focus-outline-color);
+ }
+ }
+
+ .altText{
+ --alt-text-add-image:url(images/altText_add.svg);
+ --alt-text-done-image:url(images/altText_done.svg);
+
+ display:flex;
+ align-items:center;
+ justify-content:center;
+ width:max-content;
+ padding-inline:8px;
+ pointer-events:all;
+ font:menu;
+ font-weight:590;
+ font-size:12px;
+ color:var(--editor-toolbar-fg-color);
+
+ &:disabled{
+ pointer-events:none;
+ }
+
+ &::before{
+ content:"";
+ mask-image:var(--alt-text-add-image);
+ mask-repeat:no-repeat;
+ mask-position:center;
+ display:inline-block;
+ width:12px;
+ height:13px;
+ background-color:var(--editor-toolbar-fg-color);
+ margin-inline-end:4px;
+ }
+
+ &:hover::before{
+ background-color:var(--editor-toolbar-hover-fg-color);
+ }
+
+ &.done::before{
+ mask-image:var(--alt-text-done-image);
+ }
+
+ .tooltip{
+ display:none;
+
+ &.show{
+ --alt-text-tooltip-bg:#f0f0f4;
+ --alt-text-tooltip-fg:#15141a;
+ --alt-text-tooltip-border:#8f8f9d;
+ --alt-text-tooltip-shadow:0px 2px 6px 0px rgb(58 57 68 / 0.2);
+
+ @media (prefers-color-scheme: dark){
+ --alt-text-tooltip-bg:#1c1b22;
+ --alt-text-tooltip-fg:#fbfbfe;
+ --alt-text-tooltip-shadow:0px 2px 6px 0px #15141a;
+ }
+
+ @media screen and (forced-colors: active){
+ --alt-text-tooltip-bg:Canvas;
+ --alt-text-tooltip-fg:CanvasText;
+ --alt-text-tooltip-border:CanvasText;
+ --alt-text-tooltip-shadow:none;
+ }
+
+ display:inline-flex;
+ flex-direction:column;
+ align-items:center;
+ justify-content:center;
+ position:absolute;
+ top:calc(100% + 2px);
+ inset-inline-start:0;
+ padding-block:2px 3px;
+ padding-inline:3px;
+ max-width:300px;
+ width:max-content;
+ height:auto;
+ font-size:12px;
+
+ border:0.5px solid var(--alt-text-tooltip-border);
+ background:var(--alt-text-tooltip-bg);
+ box-shadow:var(--alt-text-tooltip-shadow);
+ color:var(--alt-text-tooltip-fg);
+
+ pointer-events:none;
+ }
+ }
+ }
+ }
+ }
+}
+
+.annotationEditorLayer .freeTextEditor{
+ padding:calc(var(--freetext-padding) * var(--scale-factor));
+ width:auto;
+ height:auto;
+ touch-action:none;
+}
+
+.annotationEditorLayer .freeTextEditor .internal{
+ background:transparent;
+ border:none;
+ inset:0;
+ overflow:visible;
+ white-space:nowrap;
+ font:10px sans-serif;
+ line-height:var(--freetext-line-height);
+ user-select:none;
+}
+
+.annotationEditorLayer .freeTextEditor .overlay{
+ position:absolute;
+ display:none;
+ background:transparent;
+ inset:0;
+ width:100%;
+ height:100%;
+}
+
+.annotationEditorLayer freeTextEditor .overlay.enabled{
+ display:block;
+}
+
+.annotationEditorLayer .freeTextEditor .internal:empty::before{
+ content:attr(default-content);
+ color:gray;
+}
+
+.annotationEditorLayer .freeTextEditor .internal:focus{
+ outline:none;
+ user-select:auto;
+}
+
+.annotationEditorLayer .inkEditor{
+ width:100%;
+ height:100%;
+}
+
+.annotationEditorLayer .inkEditor.editing{
+ cursor:inherit;
+}
+
+.annotationEditorLayer .inkEditor .inkEditorCanvas{
+ position:absolute;
+ inset:0;
+ width:100%;
+ height:100%;
+ touch-action:none;
+}
+
+.annotationEditorLayer .stampEditor{
+ width:auto;
+ height:auto;
+}
+
+.annotationEditorLayer .stampEditor canvas{
+ width:100%;
+ height:100%;
+}
+
+.annotationEditorLayer{
+ :is(.freeTextEditor, .inkEditor, .stampEditor){
+ & > .resizers{
+ position:absolute;
+ inset:0;
+
+ &.hidden{
+ display:none;
+ }
+
+ & > .resizer{
+ width:var(--resizer-size);
+ height:var(--resizer-size);
+ background:content-box var(--resizer-bg-color);
+ border:var(--focus-outline-around);
+ border-radius:2px;
+ position:absolute;
+
+ &.topLeft{
+ top:var(--resizer-shift);
+ left:var(--resizer-shift);
+ }
+
+ &.topMiddle{
+ top:var(--resizer-shift);
+ left:calc(50% + var(--resizer-shift));
+ }
+
+ &.topRight{
+ top:var(--resizer-shift);
+ right:var(--resizer-shift);
+ }
+
+ &.middleRight{
+ top:calc(50% + var(--resizer-shift));
+ right:var(--resizer-shift);
+ }
+
+ &.bottomRight{
+ bottom:var(--resizer-shift);
+ right:var(--resizer-shift);
+ }
+
+ &.bottomMiddle{
+ bottom:var(--resizer-shift);
+ left:calc(50% + var(--resizer-shift));
+ }
+
+ &.bottomLeft{
+ bottom:var(--resizer-shift);
+ left:var(--resizer-shift);
+ }
+
+ &.middleLeft{
+ top:calc(50% + var(--resizer-shift));
+ left:var(--resizer-shift);
+ }
+ }
+ }
+ }
+
+ &[data-main-rotation="0"]
+ :is([data-editor-rotation="0"], [data-editor-rotation="180"]),
+ &[data-main-rotation="90"]
+ :is([data-editor-rotation="270"], [data-editor-rotation="90"]),
+ &[data-main-rotation="180"]
+ :is([data-editor-rotation="180"], [data-editor-rotation="0"]),
+ &[data-main-rotation="270"]
+ :is([data-editor-rotation="90"], [data-editor-rotation="270"]){
+ & > .resizers > .resizer{
+ &.topLeft,
+ &.bottomRight{
+ cursor:nwse-resize;
+ }
+
+ &.topMiddle,
+ &.bottomMiddle{
+ cursor:ns-resize;
+ }
+
+ &.topRight,
+ &.bottomLeft{
+ cursor:nesw-resize;
+ }
+
+ &.middleRight,
+ &.middleLeft{
+ cursor:ew-resize;
+ }
+ }
+ }
+
+ &[data-main-rotation="0"]
+ :is([data-editor-rotation="90"], [data-editor-rotation="270"]),
+ &[data-main-rotation="90"]
+ :is([data-editor-rotation="0"], [data-editor-rotation="180"]),
+ &[data-main-rotation="180"]
+ :is([data-editor-rotation="270"], [data-editor-rotation="90"]),
+ &[data-main-rotation="270"]
+ :is([data-editor-rotation="180"], [data-editor-rotation="0"]){
+ & > .resizers > .resizer{
+ &.topLeft,
+ &.bottomRight{
+ cursor:nesw-resize;
+ }
+
+ &.topMiddle,
+ &.bottomMiddle{
+ cursor:ew-resize;
+ }
+
+ &.topRight,
+ &.bottomLeft{
+ cursor:nwse-resize;
+ }
+
+ &.middleRight,
+ &.middleLeft{
+ cursor:ns-resize;
+ }
+ }
+ }
+
+ &
+ :is(
+ [data-main-rotation="0"] [data-editor-rotation="90"],
+ [data-main-rotation="90"] [data-editor-rotation="0"],
+ [data-main-rotation="180"] [data-editor-rotation="270"],
+ [data-main-rotation="270"] [data-editor-rotation="180"]
+ ){
+ .editToolbar{
+ rotate:270deg;
+
+ &:dir(ltr){
+ inset-inline-end:calc(0px - var(--editor-toolbar-vert-offset));
+ inset-block-start:0;
+ }
+
+ &:dir(rtl){
+ inset-inline-end:calc(100% + var(--editor-toolbar-vert-offset));
+ inset-block-start:0;
+ }
+ }
+ }
+
+ &
+ :is(
+ [data-main-rotation="0"] [data-editor-rotation="180"],
+ [data-main-rotation="90"] [data-editor-rotation="90"],
+ [data-main-rotation="180"] [data-editor-rotation="0"],
+ [data-main-rotation="270"] [data-editor-rotation="270"]
+ ){
+ .editToolbar{
+ rotate:180deg;
+ inset-inline-end:100%;
+ inset-block-start:calc(0pc - var(--editor-toolbar-vert-offset));
+ }
+ }
+
+ &
+ :is(
+ [data-main-rotation="0"] [data-editor-rotation="270"],
+ [data-main-rotation="90"] [data-editor-rotation="180"],
+ [data-main-rotation="180"] [data-editor-rotation="90"],
+ [data-main-rotation="270"] [data-editor-rotation="0"]
+ ){
+ .editToolbar{
+ rotate:90deg;
+
+ &:dir(ltr){
+ inset-inline-end:calc(100% + var(--editor-toolbar-vert-offset));
+ inset-block-start:100%;
+ }
+
+ &:dir(rtl){
+ inset-inline-start:calc(0px - var(--editor-toolbar-vert-offset));
+ inset-block-start:0;
+ }
+ }
+ }
+}
+
+#altTextDialog{
+ --dialog-bg-color:white;
+ --dialog-border-color:white;
+ --dialog-shadow:0 2px 14px 0 rgb(58 57 68 / 0.2);
+ --text-primary-color:#15141a;
+ --text-secondary-color:#5b5b66;
+ --hover-filter:brightness(0.9);
+ --focus-ring-color:#0060df;
+ --focus-ring-outline:2px solid var(--focus-ring-color);
+
+ --textarea-border-color:#8f8f9d;
+ --textarea-bg-color:white;
+ --textarea-fg-color:var(--text-secondary-color);
+
+ --radio-bg-color:#f0f0f4;
+ --radio-checked-bg-color:#fbfbfe;
+ --radio-border-color:#8f8f9d;
+ --radio-checked-border-color:#0060df;
+
+ --button-cancel-bg-color:#f0f0f4;
+ --button-cancel-fg-color:var(--text-primary-color);
+ --button-cancel-border-color:var(--button-cancel-bg-color);
+ --button-cancel-hover-bg-color:var(--button-cancel-bg-color);
+ --button-cancel-hover-fg-color:var(--button-cancel-fg-color);
+ --button-cancel-hover-border-color:var(--button-cancel-hover-bg-color);
+
+ --button-save-bg-color:#0060df;
+ --button-save-fg-color:#fbfbfe;
+ --button-save-hover-bg-color:var(--button-save-bg-color);
+ --button-save-hover-fg-color:var(--button-save-fg-color);
+ --button-save-hover-border-color:var(--button-save-hover-bg-color);
+
+ @media (prefers-color-scheme: dark){
+ --dialog-bg-color:#1c1b22;
+ --dialog-border-color:#1c1b22;
+ --dialog-shadow:0 2px 14px 0 #15141a;
+ --text-primary-color:#fbfbfe;
+ --text-secondary-color:#cfcfd8;
+ --focus-ring-color:#0df;
+ --hover-filter:brightness(1.4);
+
+ --textarea-bg-color:#42414d;
+
+ --radio-bg-color:#2b2a33;
+ --radio-checked-bg-color:#15141a;
+ --radio-checked-border-color:#0df;
+
+ --button-cancel-bg-color:#2b2a33;
+ --button-save-bg-color:#0df;
+ --button-save-fg-color:#15141a;
+ }
+
+ @media screen and (forced-colors: active){
+ --dialog-bg-color:Canvas;
+ --dialog-border-color:CanvasText;
+ --dialog-shadow:none;
+ --text-primary-color:CanvasText;
+ --text-secondary-color:CanvasText;
+ --hover-filter:none;
+ --focus-ring-color:ButtonBorder;
+
+ --textarea-border-color:ButtonBorder;
+ --textarea-bg-color:Field;
+ --textarea-fg-color:ButtonText;
+
+ --radio-bg-color:ButtonFace;
+ --radio-checked-bg-color:ButtonFace;
+ --radio-border-color:ButtonText;
+ --radio-checked-border-color:ButtonText;
+
+ --button-cancel-bg-color:ButtonFace;
+ --button-cancel-fg-color:ButtonText;
+ --button-cancel-border-color:ButtonText;
+ --button-cancel-hover-bg-color:AccentColor;
+ --button-cancel-hover-fg-color:AccentColorText;
+
+ --button-save-bg-color:ButtonText;
+ --button-save-fg-color:ButtonFace;
+ --button-save-hover-bg-color:AccentColor;
+ --button-save-hover-fg-color:AccentColorText;
+ }
+
+ font:message-box;
+ font-size:13px;
+ font-weight:400;
+ line-height:150%;
+ border-radius:4px;
+ padding:12px 16px;
+ border:1px solid var(--dialog-border-color);
+ background:var(--dialog-bg-color);
+ color:var(--text-primary-color);
+ box-shadow:var(--dialog-shadow);
+
+ &::backdrop{
+ mask:url(#alttext-manager-mask);
+ }
+
+ &.positioned{
+ margin:0;
+ }
+
+ & #altTextContainer{
+ width:300px;
+ height:-moz-fit-content;
+ height:fit-content;
+ display:inline-flex;
+ flex-direction:column;
+ align-items:flex-start;
+ gap:16px;
+
+ & *:focus-visible{
+ outline:var(--focus-ring-outline);
+ outline-offset:2px;
+ }
+
+ & .radio{
+ display:flex;
+ flex-direction:column;
+ align-items:flex-start;
+ gap:4px;
+
+ & .radioButton{
+ display:flex;
+ gap:8px;
+ align-self:stretch;
+ align-items:center;
+
+ & input{
+ appearance:none;
+ box-sizing:border-box;
+ width:16px;
+ height:16px;
+ border-radius:50%;
+ background-color:var(--radio-bg-color);
+ border:1px solid var(--radio-border-color);
+
+ &:hover{
+ filter:var(--hover-filter);
+ }
+
+ &:checked{
+ background-color:var(--radio-checked-bg-color);
+ border:4px solid var(--radio-checked-border-color);
+ }
+ }
+ }
+
+ & .radioLabel{
+ display:flex;
+ padding-inline-start:24px;
+ align-items:flex-start;
+ gap:10px;
+ align-self:stretch;
+
+ & span{
+ flex:1 0 0;
+ font-size:11px;
+ color:var(--text-secondary-color);
+ }
+ }
+ }
+
+ & #overallDescription{
+ display:flex;
+ flex-direction:column;
+ align-items:flex-start;
+ gap:4px;
+ align-self:stretch;
+
+ & span{
+ align-self:stretch;
+ }
+
+ & .title{
+ font-size:13px;
+ font-style:normal;
+ font-weight:590;
+ }
+ }
+
+ & #addDescription{
+ display:flex;
+ flex-direction:column;
+ align-items:stretch;
+ gap:8px;
+
+ & .descriptionArea{
+ flex:1;
+ padding-inline:24px 10px;
+
+ textarea{
+ font:inherit;
+ width:100%;
+ min-height:75px;
+ padding:8px;
+ resize:none;
+ margin:0;
+ box-sizing:border-box;
+ border-radius:4px;
+ border:1px solid var(--textarea-border-color);
+ background:var(--textarea-bg-color);
+ color:var(--textarea-fg-color);
+
+ &:focus{
+ outline-offset:0;
+ border-color:transparent;
+ }
+
+ &:disabled{
+ pointer-events:none;
+ opacity:0.4;
+ }
+ }
+ }
+ }
+
+ & #buttons{
+ display:flex;
+ justify-content:flex-end;
+ align-items:flex-start;
+ gap:8px;
+ align-self:stretch;
+
+ button{
+ border-radius:4px;
+ border:1px solid;
+ font:menu;
+ font-weight:600;
+ padding:4px 16px;
+ width:auto;
+ height:32px;
+
+ &:hover{
+ cursor:pointer;
+ filter:var(--hover-filter);
+ }
+
+ &#altTextCancel{
+ color:var(--button-cancel-fg-color);
+ background-color:var(--button-cancel-bg-color);
+ border-color:var(--button-cancel-border-color);
+
+ &:hover{
+ color:var(--button-cancel-hover-fg-color);
+ background-color:var(--button-cancel-hover-bg-color);
+ border-color:var(--button-cancel-hover-border-color);
+ }
+ }
+
+ &#altTextSave{
+ color:var(--button-save-hover-fg-color);
+ background-color:var(--button-save-hover-bg-color);
+ border-color:var(--button-save-hover-border-color);
+ opacity:1;
+
+ &:hover{
+ color:var(--button-save-hover-fg-color);
+ background-color:var(--button-save-hover-bg-color);
+ border-color:var(--button-save-hover-border-color);
+ }
+ }
+ }
+ }
+ }
+}
+
+.colorPicker{
+ --hover-outline-color:#0250bb;
+ --selected-outline-color:#0060df;
+ --swatch-border-color:#cfcfd8;
+
+ @media (prefers-color-scheme: dark){
+ --hover-outline-color:#80ebff;
+ --selected-outline-color:#aaf2ff;
+ --swatch-border-color:#52525e;
+ }
+
+ @media screen and (forced-colors: active){
+ --hover-outline-color:Highlight;
+ --selected-outline-color:var(--hover-outline-color);
+ --swatch-border-color:ButtonText;
+ }
+
+ .swatch{
+ width:16px;
+ height:16px;
+ border:1px solid var(--swatch-border-color);
+ border-radius:100%;
+ outline-offset:2px;
+ box-sizing:border-box;
+ forced-color-adjust:none;
+ }
+
+ button:is(:hover, .selected) > .swatch{
+ border:none;
+ }
+}
+
+.annotationEditorLayer{
+ &[data-main-rotation="0"]{
+ .highlightEditor:not(.free) > .editToolbar{
+ rotate:0deg;
+ }
+ }
+
+ &[data-main-rotation="90"]{
+ .highlightEditor:not(.free) > .editToolbar{
+ rotate:270deg;
+ }
+ }
+
+ &[data-main-rotation="180"]{
+ .highlightEditor:not(.free) > .editToolbar{
+ rotate:180deg;
+ }
+ }
+
+ &[data-main-rotation="270"]{
+ .highlightEditor:not(.free) > .editToolbar{
+ rotate:90deg;
+ }
+ }
+
+ .highlightEditor{
+ position:absolute;
+ background:transparent;
+ z-index:1;
+ cursor:auto;
+ max-width:100%;
+ max-height:100%;
+ border:none;
+ outline:none;
+ pointer-events:none;
+ transform-origin:0 0;
+
+ &:not(.free){
+ transform:none;
+ }
+
+ .internal{
+ position:absolute;
+ top:0;
+ left:0;
+ width:100%;
+ height:100%;
+ pointer-events:auto;
+ }
+
+ &.disabled .internal{
+ pointer-events:none;
+ }
+
+ &.selectedEditor{
+ .internal{
+ cursor:pointer;
+ }
+ }
+
+ .editToolbar{
+ --editor-toolbar-colorpicker-arrow-image:url(images/toolbarButton-menuArrow.svg);
+
+ transform-origin:center !important;
+
+ .buttons{
+ .colorPicker{
+ position:relative;
+ width:auto;
+ display:flex;
+ justify-content:center;
+ align-items:center;
+ gap:4px;
+ padding:4px;
+
+ &::after{
+ content:"";
+ mask-image:var(--editor-toolbar-colorpicker-arrow-image);
+ mask-repeat:no-repeat;
+ mask-position:center;
+ display:inline-block;
+ background-color:var(--editor-toolbar-fg-color);
+ width:12px;
+ height:12px;
+ }
+
+ &:hover::after{
+ background-color:var(--editor-toolbar-hover-fg-color);
+ }
+
+ &:has(.dropdown:not(.hidden)){
+ background-color:var(--editor-toolbar-hover-bg-color);
+
+ &::after{
+ scale:-1;
+ }
+ }
+
+ .dropdown{
+ position:absolute;
+ display:flex;
+ justify-content:center;
+ align-items:center;
+ flex-direction:column;
+ gap:11px;
+ padding-block:8px;
+ border-radius:6px;
+ background-color:var(--editor-toolbar-bg-color);
+ border:1px solid var(--editor-toolbar-border-color);
+ box-shadow:var(--editor-toolbar-shadow);
+ inset-block-start:calc(100% + 4px);
+ width:calc(100% + 2 * var(--editor-toolbar-padding));
+
+ button{
+ width:100%;
+ height:auto;
+ border:none;
+ cursor:pointer;
+ display:flex;
+ justify-content:center;
+ align-items:center;
+ background:none;
+
+ &:is(:active, :focus-visible){
+ outline:none;
+ }
+
+ > .swatch{
+ outline-offset:2px;
+ }
+
+ &[aria-selected="true"] > .swatch{
+ outline:2px solid var(--selected-outline-color);
+ }
+
+ &:is(:hover, :active, :focus-visible) > .swatch{
+ outline:2px solid var(--hover-outline-color);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+.editorParamsToolbar:has(#highlightParamsToolbarContainer){
+ padding:unset;
+}
+
+#highlightParamsToolbarContainer{
+ height:auto;
+ padding-inline:10px;
+ padding-block:10px 16px;
+ gap:16px;
+ display:flex;
+ flex-direction:column;
+ box-sizing:border-box;
+
+ .editorParamsLabel{
+ width:-moz-fit-content;
+ width:fit-content;
+ inset-inline-start:0;
+ }
+
+ .colorPicker{
+ display:flex;
+ flex-direction:column;
+ gap:8px;
+
+ .dropdown{
+ display:flex;
+ justify-content:space-between;
+ align-items:center;
+ flex-direction:row;
+ height:auto;
+
+ button{
+ width:auto;
+ height:auto;
+ border:none;
+ cursor:pointer;
+ display:flex;
+ justify-content:center;
+ align-items:center;
+ background:none;
+ flex:0 0 auto;
+
+ .swatch{
+ width:24px;
+ height:24px;
+ }
+
+ &:is(:active, :focus-visible){
+ outline:none;
+ }
+
+ &[aria-selected="true"] > .swatch{
+ outline:2px solid var(--selected-outline-color);
+ }
+
+ &:is(:hover, :active, :focus-visible) > .swatch{
+ outline:2px solid var(--hover-outline-color);
+ }
+ }
+ }
+ }
+
+ #editorHighlightThickness{
+ display:flex;
+ flex-direction:column;
+ align-items:center;
+ gap:4px;
+ align-self:stretch;
+
+ .editorParamsLabel{
+ width:100%;
+ height:auto;
+ align-self:stretch;
+ }
+
+ .thicknessPicker{
+ display:flex;
+ justify-content:space-between;
+ align-items:center;
+ align-self:stretch;
+
+ --example-color:#bfbfc9;
+
+ @media (prefers-color-scheme: dark){
+ --example-color:#80808e;
+ }
+
+ @media screen and (forced-colors: active){
+ --example-color:CanvasText;
+ }
+
+ &::before{
+ content:"";
+ width:8px;
+ aspect-ratio:1;
+ display:block;
+ border-radius:100%;
+ background-color:var(--example-color);
+ }
+
+ .editorParamsSlider{
+ width:unset;
+ height:14px;
+ }
+
+ &::after{
+ content:"";
+ width:24px;
+ aspect-ratio:1;
+ display:block;
+ border-radius:100%;
+ background-color:var(--example-color);
+ }
+ }
+ }
+}
+
+:root{
+ --viewer-container-height:0;
+ --pdfViewer-padding-bottom:0;
+ --page-margin:1px auto -8px;
+ --page-border:9px solid transparent;
+ --spreadHorizontalWrapped-margin-LR:-3.5px;
+ --loading-icon-delay:400ms;
+}
+
+@media screen and (forced-colors: active){
+ :root{
+ --pdfViewer-padding-bottom:9px;
+ --page-margin:8px auto -1px;
+ --page-border:1px solid CanvasText;
+ --spreadHorizontalWrapped-margin-LR:3.5px;
+ }
+}
+
+[data-main-rotation="90"]{
+ transform:rotate(90deg) translateY(-100%);
+}
+[data-main-rotation="180"]{
+ transform:rotate(180deg) translate(-100%, -100%);
+}
+[data-main-rotation="270"]{
+ transform:rotate(270deg) translateX(-100%);
+}
+
+#hiddenCopyElement,
+.hiddenCanvasElement{
+ position:absolute;
+ top:0;
+ left:0;
+ width:0;
+ height:0;
+ display:none;
+}
+
+.pdfViewer{
+ --scale-factor:1;
+
+ padding-bottom:var(--pdfViewer-padding-bottom);
+
+ --hcm-highlight-filter:none;
+ --hcm-highlight-selected-filter:none;
+
+ @media screen and (forced-colors: active){
+ --hcm-highlight-filter:invert(100%);
+ }
+}
+
+.pdfViewer .canvasWrapper{
+ overflow:hidden;
+ width:100%;
+ height:100%;
+ z-index:1;
+}
+
+.pdfViewer .page{
+ direction:ltr;
+ width:816px;
+ height:1056px;
+ margin:var(--page-margin);
+ position:relative;
+ overflow:visible;
+ border:var(--page-border);
+ background-clip:content-box;
+ background-color:rgb(255 255 255);
+}
+
+.pdfViewer .dummyPage{
+ position:relative;
+ width:0;
+ height:var(--viewer-container-height);
+}
+
+.pdfViewer.noUserSelect{
+ user-select:none;
+}
+
+.pdfViewer:is(.scrollHorizontal, .scrollWrapped),
+.spread{
+ margin-inline:3.5px;
+ text-align:center;
+}
+
+.pdfViewer.scrollHorizontal,
+.spread{
+ white-space:nowrap;
+}
+
+.pdfViewer:is(.scrollHorizontal, .scrollWrapped) .spread{
+ margin-inline:0;
+}
+
+.spread :is(.page, .dummyPage),
+.pdfViewer:is(.scrollHorizontal, .scrollWrapped) :is(.page, .spread){
+ display:inline-block;
+ vertical-align:middle;
+}
+
+.spread .page,
+.pdfViewer:is(.scrollHorizontal, .scrollWrapped) .page{
+ margin-inline:var(--spreadHorizontalWrapped-margin-LR);
+}
+
+.pdfViewer .page canvas{
+ margin:0;
+ display:block;
+}
+
+.pdfViewer .page canvas .structTree{
+ contain:strict;
+}
+
+.pdfViewer .page canvas[hidden]{
+ display:none;
+}
+
+.pdfViewer .page canvas[zooming]{
+ width:100%;
+ height:100%;
+}
+
+.pdfViewer .page.loadingIcon::after{
+ position:absolute;
+ top:0;
+ left:0;
+ content:"";
+ width:100%;
+ height:100%;
+ background:url("images/loading-icon.gif") center no-repeat;
+ display:none;
+ transition-property:display;
+ transition-delay:var(--loading-icon-delay);
+ z-index:5;
+ contain:strict;
+}
+
+.pdfViewer .page.loading::after{
+ display:block;
+}
+
+.pdfViewer .page:not(.loading)::after{
+ transition-property:none;
+ display:none;
+}
+
+.pdfPresentationMode .pdfViewer{
+ padding-bottom:0;
+}
+
+.pdfPresentationMode .spread{
+ margin:0;
+}
+
+.pdfPresentationMode .pdfViewer .page{
+ margin:0 auto;
+ border:2px solid transparent;
+}
+
+:root{
+ --dir-factor:1;
+
+ --sidebar-width:200px;
+ --sidebar-transition-duration:200ms;
+ --sidebar-transition-timing-function:ease;
+
+ --toolbar-icon-opacity:0.7;
+ --doorhanger-icon-opacity:0.9;
+ --editor-toolbar-base-offset:105px;
+
+ --main-color:rgb(12 12 13);
+ --body-bg-color:rgb(212 212 215);
+ --progressBar-color:rgb(10 132 255);
+ --progressBar-bg-color:rgb(221 221 222);
+ --progressBar-blend-color:rgb(116 177 239);
+ --scrollbar-color:auto;
+ --scrollbar-bg-color:auto;
+ --toolbar-icon-bg-color:rgb(0 0 0);
+ --toolbar-icon-hover-bg-color:rgb(0 0 0);
+
+ --sidebar-narrow-bg-color:rgb(212 212 215 / 0.9);
+ --sidebar-toolbar-bg-color:rgb(245 246 247);
+ --toolbar-bg-color:rgb(249 249 250);
+ --toolbar-border-color:rgb(184 184 184);
+ --toolbar-box-shadow:0 1px 0 var(--toolbar-border-color);
+ --toolbar-border-bottom:none;
+ --toolbarSidebar-box-shadow:inset calc(-1px * var(--dir-factor)) 0 0 rgb(0 0 0 / 0.25), 0 1px 0 rgb(0 0 0 / 0.15), 0 0 1px rgb(0 0 0 / 0.1);
+ --toolbarSidebar-border-bottom:none;
+ --button-hover-color:rgb(221 222 223);
+ --toggled-btn-color:rgb(0 0 0);
+ --toggled-btn-bg-color:rgb(0 0 0 / 0.3);
+ --toggled-hover-active-btn-color:rgb(0 0 0 / 0.4);
+ --toggled-hover-btn-outline:none;
+ --dropdown-btn-bg-color:rgb(215 215 219);
+ --dropdown-btn-border:none;
+ --separator-color:rgb(0 0 0 / 0.3);
+ --field-color:rgb(6 6 6);
+ --field-bg-color:rgb(255 255 255);
+ --field-border-color:rgb(187 187 188);
+ --treeitem-color:rgb(0 0 0 / 0.8);
+ --treeitem-bg-color:rgb(0 0 0 / 0.15);
+ --treeitem-hover-color:rgb(0 0 0 / 0.9);
+ --treeitem-selected-color:rgb(0 0 0 / 0.9);
+ --treeitem-selected-bg-color:rgb(0 0 0 / 0.25);
+ --thumbnail-hover-color:rgb(0 0 0 / 0.1);
+ --thumbnail-selected-color:rgb(0 0 0 / 0.2);
+ --doorhanger-bg-color:rgb(255 255 255);
+ --doorhanger-border-color:rgb(12 12 13 / 0.2);
+ --doorhanger-hover-color:rgb(12 12 13);
+ --doorhanger-hover-bg-color:rgb(237 237 237);
+ --doorhanger-separator-color:rgb(222 222 222);
+ --dialog-button-border:none;
+ --dialog-button-bg-color:rgb(12 12 13 / 0.1);
+ --dialog-button-hover-bg-color:rgb(12 12 13 / 0.3);
+
+ --loading-icon:url(images/loading.svg);
+ --treeitem-expanded-icon:url(images/treeitem-expanded.svg);
+ --treeitem-collapsed-icon:url(images/treeitem-collapsed.svg);
+ --toolbarButton-editorFreeText-icon:url(images/toolbarButton-editorFreeText.svg);
+ --toolbarButton-editorHighlight-icon:url(images/toolbarButton-editorHighlight.svg);
+ --toolbarButton-editorInk-icon:url(images/toolbarButton-editorInk.svg);
+ --toolbarButton-editorStamp-icon:url(images/toolbarButton-editorStamp.svg);
+ --toolbarButton-menuArrow-icon:url(images/toolbarButton-menuArrow.svg);
+ --toolbarButton-sidebarToggle-icon:url(images/toolbarButton-sidebarToggle.svg);
+ --toolbarButton-secondaryToolbarToggle-icon:url(images/toolbarButton-secondaryToolbarToggle.svg);
+ --toolbarButton-pageUp-icon:url(images/toolbarButton-pageUp.svg);
+ --toolbarButton-pageDown-icon:url(images/toolbarButton-pageDown.svg);
+ --toolbarButton-zoomOut-icon:url(images/toolbarButton-zoomOut.svg);
+ --toolbarButton-zoomIn-icon:url(images/toolbarButton-zoomIn.svg);
+ --toolbarButton-presentationMode-icon:url(images/toolbarButton-presentationMode.svg);
+ --toolbarButton-print-icon:url(images/toolbarButton-print.svg);
+ --toolbarButton-download-icon:url(images/toolbarButton-download.svg);
+ --toolbarButton-bookmark-icon:url(images/toolbarButton-bookmark.svg);
+ --toolbarButton-viewThumbnail-icon:url(images/toolbarButton-viewThumbnail.svg);
+ --toolbarButton-viewOutline-icon:url(images/toolbarButton-viewOutline.svg);
+ --toolbarButton-viewAttachments-icon:url(images/toolbarButton-viewAttachments.svg);
+ --toolbarButton-viewLayers-icon:url(images/toolbarButton-viewLayers.svg);
+ --toolbarButton-currentOutlineItem-icon:url(images/toolbarButton-currentOutlineItem.svg);
+ --toolbarButton-search-icon:url(images/toolbarButton-search.svg);
+ --findbarButton-previous-icon:url(images/findbarButton-previous.svg);
+ --findbarButton-next-icon:url(images/findbarButton-next.svg);
+ --secondaryToolbarButton-firstPage-icon:url(images/secondaryToolbarButton-firstPage.svg);
+ --secondaryToolbarButton-lastPage-icon:url(images/secondaryToolbarButton-lastPage.svg);
+ --secondaryToolbarButton-rotateCcw-icon:url(images/secondaryToolbarButton-rotateCcw.svg);
+ --secondaryToolbarButton-rotateCw-icon:url(images/secondaryToolbarButton-rotateCw.svg);
+ --secondaryToolbarButton-selectTool-icon:url(images/secondaryToolbarButton-selectTool.svg);
+ --secondaryToolbarButton-handTool-icon:url(images/secondaryToolbarButton-handTool.svg);
+ --secondaryToolbarButton-scrollPage-icon:url(images/secondaryToolbarButton-scrollPage.svg);
+ --secondaryToolbarButton-scrollVertical-icon:url(images/secondaryToolbarButton-scrollVertical.svg);
+ --secondaryToolbarButton-scrollHorizontal-icon:url(images/secondaryToolbarButton-scrollHorizontal.svg);
+ --secondaryToolbarButton-scrollWrapped-icon:url(images/secondaryToolbarButton-scrollWrapped.svg);
+ --secondaryToolbarButton-spreadNone-icon:url(images/secondaryToolbarButton-spreadNone.svg);
+ --secondaryToolbarButton-spreadOdd-icon:url(images/secondaryToolbarButton-spreadOdd.svg);
+ --secondaryToolbarButton-spreadEven-icon:url(images/secondaryToolbarButton-spreadEven.svg);
+ --secondaryToolbarButton-documentProperties-icon:url(images/secondaryToolbarButton-documentProperties.svg);
+ --editorParams-stampAddImage-icon:url(images/toolbarButton-zoomIn.svg);
+}
+
+:root:dir(rtl){
+ --dir-factor:-1;
+}
+
+@media (prefers-color-scheme: dark){
+ :root{
+ --main-color:rgb(249 249 250);
+ --body-bg-color:rgb(42 42 46);
+ --progressBar-color:rgb(0 96 223);
+ --progressBar-bg-color:rgb(40 40 43);
+ --progressBar-blend-color:rgb(20 68 133);
+ --scrollbar-color:rgb(121 121 123);
+ --scrollbar-bg-color:rgb(35 35 39);
+ --toolbar-icon-bg-color:rgb(255 255 255);
+ --toolbar-icon-hover-bg-color:rgb(255 255 255);
+
+ --sidebar-narrow-bg-color:rgb(42 42 46 / 0.9);
+ --sidebar-toolbar-bg-color:rgb(50 50 52);
+ --toolbar-bg-color:rgb(56 56 61);
+ --toolbar-border-color:rgb(12 12 13);
+ --button-hover-color:rgb(102 102 103);
+ --toggled-btn-color:rgb(255 255 255);
+ --toggled-btn-bg-color:rgb(0 0 0 / 0.3);
+ --toggled-hover-active-btn-color:rgb(0 0 0 / 0.4);
+ --dropdown-btn-bg-color:rgb(74 74 79);
+ --separator-color:rgb(0 0 0 / 0.3);
+ --field-color:rgb(250 250 250);
+ --field-bg-color:rgb(64 64 68);
+ --field-border-color:rgb(115 115 115);
+ --treeitem-color:rgb(255 255 255 / 0.8);
+ --treeitem-bg-color:rgb(255 255 255 / 0.15);
+ --treeitem-hover-color:rgb(255 255 255 / 0.9);
+ --treeitem-selected-color:rgb(255 255 255 / 0.9);
+ --treeitem-selected-bg-color:rgb(255 255 255 / 0.25);
+ --thumbnail-hover-color:rgb(255 255 255 / 0.1);
+ --thumbnail-selected-color:rgb(255 255 255 / 0.2);
+ --doorhanger-bg-color:rgb(74 74 79);
+ --doorhanger-border-color:rgb(39 39 43);
+ --doorhanger-hover-color:rgb(249 249 250);
+ --doorhanger-hover-bg-color:rgb(93 94 98);
+ --doorhanger-separator-color:rgb(92 92 97);
+ --dialog-button-bg-color:rgb(92 92 97);
+ --dialog-button-hover-bg-color:rgb(115 115 115);
+ }
+}
+
+@media screen and (forced-colors: active){
+ :root{
+ --button-hover-color:Highlight;
+ --doorhanger-hover-bg-color:Highlight;
+ --toolbar-icon-opacity:1;
+ --toolbar-icon-bg-color:ButtonText;
+ --toolbar-icon-hover-bg-color:ButtonFace;
+ --toggled-hover-active-btn-color:ButtonText;
+ --toggled-hover-btn-outline:2px solid ButtonBorder;
+ --toolbar-border-color:CanvasText;
+ --toolbar-border-bottom:1px solid var(--toolbar-border-color);
+ --toolbar-box-shadow:none;
+ --toggled-btn-color:HighlightText;
+ --toggled-btn-bg-color:LinkText;
+ --doorhanger-hover-color:ButtonFace;
+ --doorhanger-border-color-whcm:1px solid ButtonText;
+ --doorhanger-triangle-opacity-whcm:0;
+ --dialog-button-border:1px solid Highlight;
+ --dialog-button-hover-bg-color:Highlight;
+ --dialog-button-hover-color:ButtonFace;
+ --dropdown-btn-border:1px solid ButtonText;
+ --field-border-color:ButtonText;
+ --main-color:CanvasText;
+ --separator-color:GrayText;
+ --doorhanger-separator-color:GrayText;
+ --toolbarSidebar-box-shadow:none;
+ --toolbarSidebar-border-bottom:1px solid var(--toolbar-border-color);
+ }
+}
+
+@media screen and (prefers-reduced-motion: reduce){
+ :root{
+ --sidebar-transition-duration:0;
+ }
+}
+
+*{
+ padding:0;
+ margin:0;
+}
+
+html,
+body{
+ height:100%;
+ width:100%;
+}
+
+body{
+ background-color:var(--body-bg-color);
+ scrollbar-color:var(--scrollbar-color) var(--scrollbar-bg-color);
+}
+
+.hidden,
+[hidden]{
+ display:none !important;
+}
+
+#viewerContainer.pdfPresentationMode:fullscreen{
+ top:0;
+ background-color:rgb(0 0 0);
+ width:100%;
+ height:100%;
+ overflow:hidden;
+ cursor:none;
+ user-select:none;
+}
+
+.pdfPresentationMode:fullscreen section:not([data-internal-link]){
+ pointer-events:none;
+}
+
+.pdfPresentationMode:fullscreen .textLayer span{
+ cursor:none;
+}
+
+.pdfPresentationMode.pdfPresentationModeControls > *,
+.pdfPresentationMode.pdfPresentationModeControls .textLayer span{
+ cursor:default;
+}
+
+#outerContainer{
+ width:100%;
+ height:100%;
+ position:relative;
+}
+
+#sidebarContainer{
+ position:absolute;
+ inset-block:32px 0;
+ inset-inline-start:calc(-1 * var(--sidebar-width));
+ width:var(--sidebar-width);
+ visibility:hidden;
+ z-index:100;
+ font:message-box;
+ border-top:1px solid rgb(51 51 51);
+ border-inline-end:var(--doorhanger-border-color-whcm);
+ transition-property:inset-inline-start;
+ transition-duration:var(--sidebar-transition-duration);
+ transition-timing-function:var(--sidebar-transition-timing-function);
+}
+
+#outerContainer:is(.sidebarMoving, .sidebarOpen) #sidebarContainer{
+ visibility:visible;
+}
+#outerContainer.sidebarOpen #sidebarContainer{
+ inset-inline-start:0;
+}
+
+#mainContainer{
+ position:absolute;
+ inset:0;
+ min-width:350px;
+}
+
+#sidebarContent{
+ inset-block:32px 0;
+ inset-inline-start:0;
+ overflow:auto;
+ position:absolute;
+ width:100%;
+ box-shadow:inset calc(-1px * var(--dir-factor)) 0 0 rgb(0 0 0 / 0.25);
+}
+
+#viewerContainer{
+ overflow:auto;
+ position:absolute;
+ inset:32px 0 0;
+ outline:none;
+}
+#viewerContainer:not(.pdfPresentationMode){
+ transition-duration:var(--sidebar-transition-duration);
+ transition-timing-function:var(--sidebar-transition-timing-function);
+}
+
+#outerContainer.sidebarOpen #viewerContainer:not(.pdfPresentationMode){
+ inset-inline-start:var(--sidebar-width);
+ transition-property:inset-inline-start;
+}
+
+.toolbar{
+ position:relative;
+ inset-inline:0;
+ z-index:9999;
+ cursor:default;
+ font:message-box;
+}
+
+:is(.toolbar, .editorParamsToolbar, .findbar, #sidebarContainer)
+ :is(input, button, select),
+.secondaryToolbar :is(input, button, a, select){
+ outline:none;
+ font:message-box;
+}
+
+#toolbarContainer{
+ width:100%;
+}
+
+#toolbarSidebar{
+ width:100%;
+ height:32px;
+ background-color:var(--sidebar-toolbar-bg-color);
+ box-shadow:var(--toolbarSidebar-box-shadow);
+ border-bottom:var(--toolbarSidebar-border-bottom);
+}
+
+#sidebarResizer{
+ position:absolute;
+ inset-block:0;
+ inset-inline-end:-6px;
+ width:6px;
+ z-index:200;
+ cursor:ew-resize;
+}
+
+#toolbarContainer,
+.findbar,
+.secondaryToolbar,
+.editorParamsToolbar{
+ position:relative;
+ height:32px;
+ background-color:var(--toolbar-bg-color);
+ box-shadow:var(--toolbar-box-shadow);
+ border-bottom:var(--toolbar-border-bottom);
+}
+
+#toolbarViewer{
+ height:32px;
+}
+
+#loadingBar{
+ --progressBar-percent:0%;
+ --progressBar-end-offset:0;
+
+ position:absolute;
+ inset-inline:0 var(--progressBar-end-offset);
+ height:4px;
+ background-color:var(--progressBar-bg-color);
+ border-bottom:1px solid var(--toolbar-border-color);
+ transition-property:inset-inline-start;
+ transition-duration:var(--sidebar-transition-duration);
+ transition-timing-function:var(--sidebar-transition-timing-function);
+}
+
+#outerContainer.sidebarOpen #loadingBar{
+ inset-inline-start:var(--sidebar-width);
+}
+
+#loadingBar .progress{
+ position:absolute;
+ top:0;
+ inset-inline-start:0;
+ width:100%;
+ transform:scaleX(var(--progressBar-percent));
+ transform-origin:calc(50% - 50% * var(--dir-factor)) 0;
+ height:100%;
+ background-color:var(--progressBar-color);
+ overflow:hidden;
+ transition:transform 200ms;
+}
+
+@keyframes progressIndeterminate{
+ 0%{
+ transform:translateX(calc(-142px * var(--dir-factor)));
+ }
+ 100%{
+ transform:translateX(0);
+ }
+}
+
+#loadingBar.indeterminate .progress{
+ transform:none;
+ background-color:var(--progressBar-bg-color);
+ transition:none;
+}
+
+#loadingBar.indeterminate .progress .glimmer{
+ position:absolute;
+ top:0;
+ inset-inline-start:0;
+ height:100%;
+ width:calc(100% + 150px);
+ background:repeating-linear-gradient(
+ 135deg,
+ var(--progressBar-blend-color) 0,
+ var(--progressBar-bg-color) 5px,
+ var(--progressBar-bg-color) 45px,
+ var(--progressBar-color) 55px,
+ var(--progressBar-color) 95px,
+ var(--progressBar-blend-color) 100px
+ );
+ animation:progressIndeterminate 1s linear infinite;
+}
+
+#outerContainer.sidebarResizing
+ :is(#sidebarContainer, #viewerContainer, #loadingBar){
+ transition-duration:0s;
+}
+
+.findbar,
+.secondaryToolbar,
+.editorParamsToolbar{
+ top:32px;
+ position:absolute;
+ z-index:30000;
+ height:auto;
+ padding:0 4px;
+ margin:4px 2px;
+ font:message-box;
+ font-size:12px;
+ line-height:14px;
+ text-align:left;
+ cursor:default;
+}
+
+.findbar{
+ inset-inline-start:64px;
+ min-width:300px;
+ background-color:var(--toolbar-bg-color);
+}
+.findbar > div{
+ height:32px;
+}
+.findbar > div#findbarInputContainer{
+ margin-inline-end:4px;
+}
+.findbar.wrapContainers > div,
+.findbar.wrapContainers > div#findbarMessageContainer > *{
+ clear:both;
+}
+.findbar.wrapContainers > div#findbarMessageContainer{
+ height:auto;
+}
+
+.findbar input[type="checkbox"]{
+ pointer-events:none;
+}
+
+.findbar label{
+ user-select:none;
+}
+
+.findbar label:hover,
+.findbar input:focus-visible + label{
+ color:var(--toggled-btn-color);
+ background-color:var(--button-hover-color);
+}
+
+.findbar .toolbarField[type="checkbox"]:checked + .toolbarLabel{
+ background-color:var(--toggled-btn-bg-color) !important;
+ color:var(--toggled-btn-color);
+}
+
+#findInput{
+ width:200px;
+
+ &::placeholder{
+ font-style:normal;
+ }
+ .loadingInput:has(> &[data-status="pending"])::after{
+ visibility:visible;
+ }
+ &[data-status="notFound"]{
+ background-color:rgb(255 102 102);
+ }
+}
+
+.secondaryToolbar,
+.editorParamsToolbar{
+ padding:6px 0 10px;
+ inset-inline-end:4px;
+ height:auto;
+ background-color:var(--doorhanger-bg-color);
+}
+
+.editorParamsToolbarContainer{
+ width:220px;
+ margin-bottom:-4px;
+}
+
+.editorParamsToolbarContainer > .editorParamsSetter{
+ min-height:26px;
+ display:flex;
+ align-items:center;
+ justify-content:space-between;
+ padding-inline:10px;
+}
+
+.editorParamsToolbarContainer .editorParamsLabel{
+ padding-inline-end:10px;
+ flex:none;
+ font:menu;
+ font-size:13px;
+ font-style:normal;
+ font-weight:400;
+ line-height:150%;
+ color:var(--main-color);
+}
+
+.editorParamsToolbarContainer .editorParamsColor{
+ width:32px;
+ height:32px;
+ flex:none;
+}
+
+.editorParamsToolbarContainer .editorParamsSlider{
+ background-color:transparent;
+ width:90px;
+ flex:0 1 0;
+}
+
+.editorParamsToolbarContainer .editorParamsSlider::-moz-range-progress{
+ background-color:black;
+}
+
+.editorParamsToolbarContainer .editorParamsSlider::-moz-range-track{
+ background-color:black;
+}
+
+.editorParamsToolbarContainer .editorParamsSlider::-moz-range-thumb{
+ background-color:white;
+}
+
+#secondaryToolbarButtonContainer{
+ max-width:220px;
+ min-height:26px;
+ max-height:calc(var(--viewer-container-height) - 40px);
+ overflow-y:auto;
+ margin-bottom:-4px;
+}
+
+#editorStampParamsToolbar{
+ inset-inline-end:calc(var(--editor-toolbar-base-offset) + 0px);
+}
+
+#editorInkParamsToolbar{
+ inset-inline-end:calc(var(--editor-toolbar-base-offset) + 28px);
+}
+
+#editorFreeTextParamsToolbar{
+ inset-inline-end:calc(var(--editor-toolbar-base-offset) + 56px);
+}
+
+#editorHighlightParamsToolbar{
+ inset-inline-end:calc(var(--editor-toolbar-base-offset) + 84px);
+}
+
+#editorStampAddImage::before{
+ mask-image:var(--editorParams-stampAddImage-icon);
+}
+
+.doorHanger,
+.doorHangerRight{
+ border-radius:2px;
+ box-shadow:0 1px 5px var(--doorhanger-border-color), 0 0 0 1px var(--doorhanger-border-color);
+ border:var(--doorhanger-border-color-whcm);
+}
+:is(.doorHanger, .doorHangerRight)::after,
+:is(.doorHanger, .doorHangerRight)::before{
+ bottom:100%;
+ border:8px solid rgb(0 0 0 / 0);
+ content:" ";
+ height:0;
+ width:0;
+ position:absolute;
+ pointer-events:none;
+ opacity:var(--doorhanger-triangle-opacity-whcm);
+}
+.doorHanger::after{
+ inset-inline-start:10px;
+ margin-inline-start:-8px;
+ border-bottom-color:var(--toolbar-bg-color);
+}
+.doorHangerRight::after{
+ inset-inline-end:10px;
+ margin-inline-end:-8px;
+ border-bottom-color:var(--doorhanger-bg-color);
+}
+:is(.doorHanger, .doorHangerRight)::before{
+ border-bottom-color:var(--doorhanger-border-color);
+ border-width:9px;
+}
+.doorHanger::before{
+ inset-inline-start:10px;
+ margin-inline-start:-9px;
+}
+.doorHangerRight::before{
+ inset-inline-end:10px;
+ margin-inline-end:-9px;
+}
+
+#findResultsCount{
+ background-color:rgb(217 217 217);
+ color:rgb(82 82 82);
+ text-align:center;
+ padding:4px 5px;
+ margin:5px;
+}
+
+#findMsg[data-status="notFound"]{
+ font-weight:bold;
+}
+
+:is(#findResultsCount, #findMsg):empty{
+ display:none;
+}
+
+#toolbarViewerMiddle{
+ position:absolute;
+ left:50%;
+ transform:translateX(-50%);
+}
+
+#toolbarViewerLeft,
+#toolbarSidebarLeft{
+ float:inline-start;
+}
+#toolbarViewerRight,
+#toolbarSidebarRight{
+ float:inline-end;
+}
+
+#toolbarViewerLeft > *,
+#toolbarViewerMiddle > *,
+#toolbarViewerRight > *,
+#toolbarSidebarLeft *,
+#toolbarSidebarRight *,
+.findbar *{
+ position:relative;
+ float:inline-start;
+}
+
+#toolbarViewerLeft{
+ padding-inline-start:1px;
+}
+#toolbarViewerRight{
+ padding-inline-end:1px;
+}
+#toolbarSidebarRight{
+ padding-inline-end:2px;
+}
+
+.splitToolbarButton{
+ margin:2px;
+ display:inline-block;
+}
+.splitToolbarButton > .toolbarButton{
+ float:inline-start;
+}
+
+.toolbarButton,
+.secondaryToolbarButton,
+.dialogButton{
+ border:none;
+ background:none;
+ width:28px;
+ height:28px;
+ outline:none;
+}
+
+.dialogButton:is(:hover, :focus-visible){
+ background-color:var(--dialog-button-hover-bg-color);
+}
+
+.dialogButton:is(:hover, :focus-visible) > span{
+ color:var(--dialog-button-hover-color);
+}
+
+.toolbarButton > span{
+ display:inline-block;
+ width:0;
+ height:0;
+ overflow:hidden;
+}
+
+:is(.toolbarButton, .secondaryToolbarButton, .dialogButton)[disabled]{
+ opacity:0.5;
+}
+
+.splitToolbarButton > .toolbarButton:is(:hover, :focus-visible),
+.dropdownToolbarButton:hover{
+ background-color:var(--button-hover-color);
+}
+.splitToolbarButton > .toolbarButton{
+ position:relative;
+ margin:0;
+}
+#toolbarSidebar .splitToolbarButton > .toolbarButton{
+ margin-inline-end:2px;
+}
+
+.splitToolbarButtonSeparator{
+ float:inline-start;
+ margin:4px 0;
+ width:1px;
+ height:20px;
+ background-color:var(--separator-color);
+}
+
+.toolbarButton,
+.dropdownToolbarButton,
+.secondaryToolbarButton,
+.dialogButton{
+ min-width:16px;
+ margin:2px 1px;
+ padding:2px 6px 0;
+ border:none;
+ border-radius:2px;
+ color:var(--main-color);
+ font-size:12px;
+ line-height:14px;
+ user-select:none;
+ cursor:default;
+ box-sizing:border-box;
+}
+
+.toolbarButton:is(:hover, :focus-visible){
+ background-color:var(--button-hover-color);
+}
+.secondaryToolbarButton:is(:hover, :focus-visible){
+ background-color:var(--doorhanger-hover-bg-color);
+ color:var(--doorhanger-hover-color);
+}
+
+:is(.toolbarButton, .secondaryToolbarButton).toggled,
+.splitToolbarButton.toggled > .toolbarButton.toggled{
+ background-color:var(--toggled-btn-bg-color);
+ color:var(--toggled-btn-color);
+}
+
+:is(.toolbarButton, .secondaryToolbarButton).toggled:hover,
+.splitToolbarButton.toggled > .toolbarButton.toggled:hover{
+ outline:var(--toggled-hover-btn-outline) !important;
+}
+
+:is(.toolbarButton, .secondaryToolbarButton).toggled::before{
+ background-color:var(--toggled-btn-color);
+}
+
+:is(.toolbarButton, .secondaryToolbarButton).toggled:hover:active,
+.splitToolbarButton.toggled > .toolbarButton.toggled:hover:active{
+ background-color:var(--toggled-hover-active-btn-color);
+}
+
+.dropdownToolbarButton{
+ display:flex;
+ width:-moz-fit-content;
+ width:fit-content;
+ min-width:140px;
+ padding:0;
+ background-color:var(--dropdown-btn-bg-color);
+ border:var(--dropdown-btn-border);
+}
+.dropdownToolbarButton::after{
+ top:6px;
+ inset-inline-end:6px;
+ pointer-events:none;
+ mask-image:var(--toolbarButton-menuArrow-icon);
+}
+
+.dropdownToolbarButton > select{
+ appearance:none;
+ width:inherit;
+ min-width:inherit;
+ height:28px;
+ font-size:12px;
+ color:var(--main-color);
+ margin:0;
+ padding-block:1px 2px;
+ padding-inline:6px 38px;
+ border:none;
+ background-color:var(--dropdown-btn-bg-color);
+}
+.dropdownToolbarButton > select:is(:hover, :focus-visible){
+ background-color:var(--button-hover-color);
+ color:var(--toggled-btn-color);
+}
+.dropdownToolbarButton > select > option{
+ background:var(--doorhanger-bg-color);
+ color:var(--main-color);
+}
+
+.toolbarButtonSpacer{
+ width:30px;
+ display:inline-block;
+ height:1px;
+}
+
+:is(.toolbarButton, .secondaryToolbarButton, .treeItemToggler)::before,
+.dropdownToolbarButton::after{
+ position:absolute;
+ display:inline-block;
+ width:16px;
+ height:16px;
+
+ content:"";
+ background-color:var(--toolbar-icon-bg-color);
+ mask-size:cover;
+}
+
+.dropdownToolbarButton:is(:hover, :focus-visible, :active)::after{
+ background-color:var(--toolbar-icon-hover-bg-color);
+}
+
+.toolbarButton::before{
+ opacity:var(--toolbar-icon-opacity);
+ top:6px;
+ left:6px;
+}
+
+.toolbarButton:is(:hover, :focus-visible)::before,
+.secondaryToolbarButton:is(:hover, :focus-visible)::before{
+ background-color:var(--toolbar-icon-hover-bg-color);
+}
+
+.secondaryToolbarButton::before{
+ opacity:var(--doorhanger-icon-opacity);
+ top:5px;
+ inset-inline-start:12px;
+}
+
+#sidebarToggle::before{
+ mask-image:var(--toolbarButton-sidebarToggle-icon);
+ transform:scaleX(var(--dir-factor));
+}
+
+#secondaryToolbarToggle::before{
+ mask-image:var(--toolbarButton-secondaryToolbarToggle-icon);
+ transform:scaleX(var(--dir-factor));
+}
+
+#findPrevious::before{
+ mask-image:var(--findbarButton-previous-icon);
+}
+
+#findNext::before{
+ mask-image:var(--findbarButton-next-icon);
+}
+
+#previous::before{
+ mask-image:var(--toolbarButton-pageUp-icon);
+}
+
+#next::before{
+ mask-image:var(--toolbarButton-pageDown-icon);
+}
+
+#zoomOut::before{
+ mask-image:var(--toolbarButton-zoomOut-icon);
+}
+
+#zoomIn::before{
+ mask-image:var(--toolbarButton-zoomIn-icon);
+}
+
+#presentationMode::before{
+ mask-image:var(--toolbarButton-presentationMode-icon);
+}
+
+#editorFreeText::before{
+ mask-image:var(--toolbarButton-editorFreeText-icon);
+}
+
+#editorHighlight::before{
+ mask-image:var(--toolbarButton-editorHighlight-icon);
+}
+
+#editorInk::before{
+ mask-image:var(--toolbarButton-editorInk-icon);
+}
+
+#editorStamp::before{
+ mask-image:var(--toolbarButton-editorStamp-icon);
+}
+
+:is(#print, #secondaryPrint)::before{
+ mask-image:var(--toolbarButton-print-icon);
+}
+
+:is(#download, #secondaryDownload)::before{
+ mask-image:var(--toolbarButton-download-icon);
+}
+
+a.secondaryToolbarButton{
+ padding-top:5px;
+ text-decoration:none;
+}
+a:is(.toolbarButton, .secondaryToolbarButton)[href="#"]{
+ opacity:0.5;
+ pointer-events:none;
+}
+
+#viewBookmark::before{
+ mask-image:var(--toolbarButton-bookmark-icon);
+}
+
+#viewThumbnail::before{
+ mask-image:var(--toolbarButton-viewThumbnail-icon);
+}
+
+#viewOutline::before{
+ mask-image:var(--toolbarButton-viewOutline-icon);
+ transform:scaleX(var(--dir-factor));
+}
+
+#viewAttachments::before{
+ mask-image:var(--toolbarButton-viewAttachments-icon);
+}
+
+#viewLayers::before{
+ mask-image:var(--toolbarButton-viewLayers-icon);
+}
+
+#currentOutlineItem::before{
+ mask-image:var(--toolbarButton-currentOutlineItem-icon);
+ transform:scaleX(var(--dir-factor));
+}
+
+#viewFind::before{
+ mask-image:var(--toolbarButton-search-icon);
+}
+
+.pdfSidebarNotification::after{
+ position:absolute;
+ display:inline-block;
+ top:2px;
+ inset-inline-end:2px;
+ content:"";
+ background-color:rgb(112 219 85);
+ height:9px;
+ width:9px;
+ border-radius:50%;
+}
+
+.secondaryToolbarButton{
+ position:relative;
+ margin:0;
+ padding:0 0 1px;
+ padding-inline-start:36px;
+ height:auto;
+ min-height:26px;
+ width:auto;
+ min-width:100%;
+ text-align:start;
+ white-space:normal;
+ border-radius:0;
+ box-sizing:border-box;
+ display:inline-block;
+}
+.secondaryToolbarButton > span{
+ padding-inline-end:4px;
+}
+
+#firstPage::before{
+ mask-image:var(--secondaryToolbarButton-firstPage-icon);
+}
+
+#lastPage::before{
+ mask-image:var(--secondaryToolbarButton-lastPage-icon);
+}
+
+#pageRotateCcw::before{
+ mask-image:var(--secondaryToolbarButton-rotateCcw-icon);
+}
+
+#pageRotateCw::before{
+ mask-image:var(--secondaryToolbarButton-rotateCw-icon);
+}
+
+#cursorSelectTool::before{
+ mask-image:var(--secondaryToolbarButton-selectTool-icon);
+}
+
+#cursorHandTool::before{
+ mask-image:var(--secondaryToolbarButton-handTool-icon);
+}
+
+#scrollPage::before{
+ mask-image:var(--secondaryToolbarButton-scrollPage-icon);
+}
+
+#scrollVertical::before{
+ mask-image:var(--secondaryToolbarButton-scrollVertical-icon);
+}
+
+#scrollHorizontal::before{
+ mask-image:var(--secondaryToolbarButton-scrollHorizontal-icon);
+}
+
+#scrollWrapped::before{
+ mask-image:var(--secondaryToolbarButton-scrollWrapped-icon);
+}
+
+#spreadNone::before{
+ mask-image:var(--secondaryToolbarButton-spreadNone-icon);
+}
+
+#spreadOdd::before{
+ mask-image:var(--secondaryToolbarButton-spreadOdd-icon);
+}
+
+#spreadEven::before{
+ mask-image:var(--secondaryToolbarButton-spreadEven-icon);
+}
+
+#documentProperties::before{
+ mask-image:var(--secondaryToolbarButton-documentProperties-icon);
+}
+
+.verticalToolbarSeparator{
+ display:block;
+ margin:5px 2px;
+ width:1px;
+ height:22px;
+ background-color:var(--separator-color);
+}
+.horizontalToolbarSeparator{
+ display:block;
+ margin:6px 0;
+ height:1px;
+ width:100%;
+ background-color:var(--doorhanger-separator-color);
+}
+
+.toolbarField{
+ padding:4px 7px;
+ margin:3px 0;
+ border-radius:2px;
+ background-color:var(--field-bg-color);
+ background-clip:padding-box;
+ border:1px solid var(--field-border-color);
+ box-shadow:none;
+ color:var(--field-color);
+ font-size:12px;
+ line-height:16px;
+ outline:none;
+}
+
+.toolbarField[type="checkbox"]{
+ opacity:0;
+ position:absolute !important;
+ left:0;
+ margin:10px 0 3px;
+ margin-inline-start:7px;
+}
+
+#pageNumber{
+ -moz-appearance:textfield;
+ text-align:end;
+ width:40px;
+ background-size:0 0;
+ transition-property:none;
+
+ .loadingInput:has(> &.loading)::after{
+ visibility:visible;
+
+ transition-property:visibility;
+ transition-delay:var(--loading-icon-delay);
+ }
+}
+
+.loadingInput{
+ &::after{
+ position:absolute;
+ visibility:hidden;
+ top:calc(50% - 8px);
+ width:16px;
+ height:16px;
+
+ content:"";
+ background-color:var(--toolbar-icon-bg-color);
+ mask-size:cover;
+ mask-image:var(--loading-icon);
+ }
+
+ &.start::after{
+ inset-inline-start:4px;
+ }
+ &.end::after{
+ inset-inline-end:4px;
+ }
+}
+
+.toolbarField:focus{
+ border-color:#0a84ff;
+}
+
+.toolbarLabel{
+ min-width:16px;
+ padding:7px;
+ margin:2px;
+ border-radius:2px;
+ color:var(--main-color);
+ font-size:12px;
+ line-height:14px;
+ text-align:left;
+ user-select:none;
+ cursor:default;
+}
+
+#numPages.toolbarLabel{
+ padding-inline-start:3px;
+}
+
+#thumbnailView,
+#outlineView,
+#attachmentsView,
+#layersView{
+ position:absolute;
+ width:calc(100% - 8px);
+ inset-block:0;
+ padding:4px 4px 0;
+ overflow:auto;
+ user-select:none;
+}
+#thumbnailView{
+ width:calc(100% - 60px);
+ padding:10px 30px 0;
+}
+
+#thumbnailView > a:is(:active, :focus){
+ outline:0;
+}
+
+.thumbnail{
+ --thumbnail-width:0;
+ --thumbnail-height:0;
+
+ float:inline-start;
+ width:var(--thumbnail-width);
+ height:var(--thumbnail-height);
+ margin:0 10px 5px;
+ padding:1px;
+ border:7px solid transparent;
+ border-radius:2px;
+}
+
+#thumbnailView > a:last-of-type > .thumbnail{
+ margin-bottom:10px;
+}
+
+a:focus > .thumbnail,
+.thumbnail:hover{
+ border-color:var(--thumbnail-hover-color);
+}
+.thumbnail.selected{
+ border-color:var(--thumbnail-selected-color) !important;
+}
+
+.thumbnailImage{
+ width:var(--thumbnail-width);
+ height:var(--thumbnail-height);
+ opacity:0.9;
+}
+a:focus > .thumbnail > .thumbnailImage,
+.thumbnail:hover > .thumbnailImage{
+ opacity:0.95;
+}
+.thumbnail.selected > .thumbnailImage{
+ opacity:1 !important;
+}
+
+.thumbnail:not([data-loaded]) > .thumbnailImage{
+ width:calc(var(--thumbnail-width) - 2px);
+ height:calc(var(--thumbnail-height) - 2px);
+ border:1px dashed rgb(132 132 132);
+}
+
+.treeWithDeepNesting > .treeItem,
+.treeItem > .treeItems{
+ margin-inline-start:20px;
+}
+
+.treeItem > a{
+ text-decoration:none;
+ display:inline-block;
+ min-width:calc(100% - 4px);
+ height:auto;
+ margin-bottom:1px;
+ padding:2px 0 5px;
+ padding-inline-start:4px;
+ border-radius:2px;
+ color:var(--treeitem-color);
+ font-size:13px;
+ line-height:15px;
+ user-select:none;
+ white-space:normal;
+ cursor:pointer;
+}
+
+#layersView .treeItem > a *{
+ cursor:pointer;
+}
+#layersView .treeItem > a > label{
+ padding-inline-start:4px;
+}
+#layersView .treeItem > a > label > input{
+ float:inline-start;
+ margin-top:1px;
+}
+
+.treeItemToggler{
+ position:relative;
+ float:inline-start;
+ height:0;
+ width:0;
+ color:rgb(255 255 255 / 0.5);
+}
+.treeItemToggler::before{
+ inset-inline-end:4px;
+ mask-image:var(--treeitem-expanded-icon);
+}
+.treeItemToggler.treeItemsHidden::before{
+ mask-image:var(--treeitem-collapsed-icon);
+ transform:scaleX(var(--dir-factor));
+}
+.treeItemToggler.treeItemsHidden ~ .treeItems{
+ display:none;
+}
+
+.treeItem.selected > a{
+ background-color:var(--treeitem-selected-bg-color);
+ color:var(--treeitem-selected-color);
+}
+
+.treeItemToggler:hover,
+.treeItemToggler:hover + a,
+.treeItemToggler:hover ~ .treeItems,
+.treeItem > a:hover{
+ background-color:var(--treeitem-bg-color);
+ background-clip:padding-box;
+ border-radius:2px;
+ color:var(--treeitem-hover-color);
+}
+
+#outlineOptionsContainer{
+ display:none;
+
+ #sidebarContainer:has(#outlineView:not(.hidden)) &{
+ display:inherit;
+ }
+}
+
+.dialogButton{
+ width:auto;
+ margin:3px 4px 2px !important;
+ padding:2px 11px;
+ color:var(--main-color);
+ background-color:var(--dialog-button-bg-color);
+ border:var(--dialog-button-border) !important;
+}
+
+dialog{
+ margin:auto;
+ padding:15px;
+ border-spacing:4px;
+ color:var(--main-color);
+ font:message-box;
+ font-size:12px;
+ line-height:14px;
+ background-color:var(--doorhanger-bg-color);
+ border:1px solid rgb(0 0 0 / 0.5);
+ border-radius:4px;
+ box-shadow:0 1px 4px rgb(0 0 0 / 0.3);
+}
+dialog::backdrop{
+ background-color:rgb(0 0 0 / 0.2);
+}
+
+dialog > .row{
+ display:table-row;
+}
+
+dialog > .row > *{
+ display:table-cell;
+}
+
+dialog .toolbarField{
+ margin:5px 0;
+}
+
+dialog .separator{
+ display:block;
+ margin:4px 0;
+ height:1px;
+ width:100%;
+ background-color:var(--separator-color);
+}
+
+dialog .buttonRow{
+ text-align:center;
+ vertical-align:middle;
+}
+
+dialog :link{
+ color:rgb(255 255 255);
+}
+
+#passwordDialog{
+ text-align:center;
+}
+#passwordDialog .toolbarField{
+ width:200px;
+}
+
+#documentPropertiesDialog{
+ text-align:left;
+}
+#documentPropertiesDialog .row > *{
+ min-width:100px;
+ text-align:start;
+}
+#documentPropertiesDialog .row > span{
+ width:125px;
+ word-wrap:break-word;
+}
+#documentPropertiesDialog .row > p{
+ max-width:225px;
+ word-wrap:break-word;
+}
+#documentPropertiesDialog .buttonRow{
+ margin-top:10px;
+}
+
+.grab-to-pan-grab{
+ cursor:grab !important;
+}
+.grab-to-pan-grab
+ *:not(input):not(textarea):not(button):not(select):not(:link){
+ cursor:inherit !important;
+}
+.grab-to-pan-grab:active,
+.grab-to-pan-grabbing{
+ cursor:grabbing !important;
+}
+.grab-to-pan-grabbing{
+ position:fixed;
+ background:rgb(0 0 0 / 0);
+ display:block;
+ inset:0;
+ overflow:hidden;
+ z-index:50000;
+}
+
+@page{
+ margin:0;
+}
+
+#printContainer{
+ display:none;
+}
+
+@media print{
+ body{
+ background:rgb(0 0 0 / 0) none;
+ }
+ body[data-pdfjsprinting] #outerContainer{
+ display:none;
+ }
+ body[data-pdfjsprinting] #printContainer{
+ display:block;
+ }
+ #printContainer{
+ height:100%;
+ }
+ #printContainer > .printedPage{
+ page-break-after:always;
+ page-break-inside:avoid;
+ height:100%;
+ width:100%;
+
+ display:flex;
+ flex-direction:column;
+ justify-content:center;
+ align-items:center;
+ }
+
+ #printContainer > .xfaPrintedPage .xfaPage{
+ position:absolute;
+ }
+
+ #printContainer > .xfaPrintedPage{
+ page-break-after:always;
+ page-break-inside:avoid;
+ width:100%;
+ height:100%;
+ position:relative;
+ }
+
+ #printContainer > .printedPage :is(canvas, img){
+ max-width:100%;
+ max-height:100%;
+
+ direction:ltr;
+ display:block;
+ }
+}
+
+.visibleMediumView{
+ display:none;
+}
+
+@media all and (max-width: 900px){
+ #toolbarViewerMiddle{
+ display:table;
+ margin:auto;
+ left:auto;
+ position:inherit;
+ transform:none;
+ }
+}
+
+@media all and (max-width: 840px){
+ #sidebarContainer{
+ background-color:var(--sidebar-narrow-bg-color);
+ }
+ #outerContainer.sidebarOpen #viewerContainer{
+ inset-inline-start:0 !important;
+ }
+}
+
+@media all and (max-width: 750px){
+ :root{
+ --editor-toolbar-base-offset:40px;
+ }
+ #outerContainer .hiddenMediumView{
+ display:none;
+ }
+ #outerContainer .visibleMediumView{
+ display:inherit;
+ }
+}
+
+@media all and (max-width: 690px){
+ .hiddenSmallView,
+ .hiddenSmallView *{
+ display:none;
+ }
+ .toolbarButtonSpacer{
+ width:0;
+ }
+ .findbar{
+ inset-inline-start:34px;
+ }
+}
+
+@media all and (max-width: 560px){
+ #scaleSelectContainer{
+ display:none;
+ }
+}
diff --git a/toolkit/components/pdfjs/content/web/viewer.html b/toolkit/components/pdfjs/content/web/viewer.html
new file mode 100644
index 0000000000..59438b64b4
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/viewer.html
@@ -0,0 +1,485 @@
+<!DOCTYPE html>
+<!--
+Copyright 2012 Mozilla Foundation
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+Adobe CMap resources are covered by their own copyright but the same license:
+
+ Copyright 1990-2015 Adobe Systems Incorporated.
+
+See https://github.com/adobe-type-tools/cmap-resources
+-->
+<html dir="ltr" mozdisallowselectionprint>
+ <head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
+ <title>PDF.js viewer</title>
+
+<!-- This snippet is used in the Firefox extension (included from viewer.html) -->
+<script src="resource://pdf.js/build/pdf.mjs" type="module"></script>
+
+ <link rel="stylesheet" href="resource://pdf.js/web/viewer.css">
+ <link rel="localization" href="toolkit/pdfviewer/viewer.ftl"/>
+
+ <script src="resource://pdf.js/web/viewer.mjs" type="module"></script>
+ </head>
+
+ <body tabindex="1">
+ <div id="outerContainer">
+
+ <div id="sidebarContainer">
+ <div id="toolbarSidebar">
+ <div id="toolbarSidebarLeft">
+ <div id="sidebarViewButtons" class="splitToolbarButton toggled" role="radiogroup">
+ <button id="viewThumbnail" class="toolbarButton toggled" title="Show Thumbnails" tabindex="2" data-l10n-id="pdfjs-thumbs-button" role="radio" aria-checked="true" aria-controls="thumbnailView">
+ <span data-l10n-id="pdfjs-thumbs-button-label">Thumbnails</span>
+ </button>
+ <button id="viewOutline" class="toolbarButton" title="Show Document Outline (double-click to expand/collapse all items)" tabindex="3" data-l10n-id="pdfjs-document-outline-button" role="radio" aria-checked="false" aria-controls="outlineView">
+ <span data-l10n-id="pdfjs-document-outline-button-label">Document Outline</span>
+ </button>
+ <button id="viewAttachments" class="toolbarButton" title="Show Attachments" tabindex="4" data-l10n-id="pdfjs-attachments-button" role="radio" aria-checked="false" aria-controls="attachmentsView">
+ <span data-l10n-id="pdfjs-attachments-button-label">Attachments</span>
+ </button>
+ <button id="viewLayers" class="toolbarButton" title="Show Layers (double-click to reset all layers to the default state)" tabindex="5" data-l10n-id="pdfjs-layers-button" role="radio" aria-checked="false" aria-controls="layersView">
+ <span data-l10n-id="pdfjs-layers-button-label">Layers</span>
+ </button>
+ </div>
+ </div>
+
+ <div id="toolbarSidebarRight">
+ <div id="outlineOptionsContainer">
+ <div class="verticalToolbarSeparator"></div>
+
+ <button id="currentOutlineItem" class="toolbarButton" disabled="disabled" title="Find Current Outline Item" tabindex="6" data-l10n-id="pdfjs-current-outline-item-button">
+ <span data-l10n-id="pdfjs-current-outline-item-button-label">Current Outline Item</span>
+ </button>
+ </div>
+ </div>
+ </div>
+ <div id="sidebarContent">
+ <div id="thumbnailView">
+ </div>
+ <div id="outlineView" class="hidden">
+ </div>
+ <div id="attachmentsView" class="hidden">
+ </div>
+ <div id="layersView" class="hidden">
+ </div>
+ </div>
+ <div id="sidebarResizer"></div>
+ </div> <!-- sidebarContainer -->
+
+ <div id="mainContainer">
+ <div class="findbar hidden doorHanger" id="findbar">
+ <div id="findbarInputContainer">
+ <span class="loadingInput end">
+ <input id="findInput" class="toolbarField" title="Find" placeholder="Find in document…" tabindex="91" data-l10n-id="pdfjs-find-input" aria-invalid="false">
+ </span>
+ <div class="splitToolbarButton">
+ <button id="findPrevious" class="toolbarButton" title="Find the previous occurrence of the phrase" tabindex="92" data-l10n-id="pdfjs-find-previous-button">
+ <span data-l10n-id="pdfjs-find-previous-button-label">Previous</span>
+ </button>
+ <div class="splitToolbarButtonSeparator"></div>
+ <button id="findNext" class="toolbarButton" title="Find the next occurrence of the phrase" tabindex="93" data-l10n-id="pdfjs-find-next-button">
+ <span data-l10n-id="pdfjs-find-next-button-label">Next</span>
+ </button>
+ </div>
+ </div>
+
+ <div id="findbarOptionsOneContainer">
+ <input type="checkbox" id="findHighlightAll" class="toolbarField" tabindex="94">
+ <label for="findHighlightAll" class="toolbarLabel" data-l10n-id="pdfjs-find-highlight-checkbox">Highlight All</label>
+ <input type="checkbox" id="findMatchCase" class="toolbarField" tabindex="95">
+ <label for="findMatchCase" class="toolbarLabel" data-l10n-id="pdfjs-find-match-case-checkbox-label">Match Case</label>
+ </div>
+ <div id="findbarOptionsTwoContainer">
+ <input type="checkbox" id="findMatchDiacritics" class="toolbarField" tabindex="96">
+ <label for="findMatchDiacritics" class="toolbarLabel" data-l10n-id="pdfjs-find-match-diacritics-checkbox-label">Match Diacritics</label>
+ <input type="checkbox" id="findEntireWord" class="toolbarField" tabindex="97">
+ <label for="findEntireWord" class="toolbarLabel" data-l10n-id="pdfjs-find-entire-word-checkbox-label">Whole Words</label>
+ </div>
+
+ <div id="findbarMessageContainer" aria-live="polite">
+ <span id="findResultsCount" class="toolbarLabel"></span>
+ <span id="findMsg" class="toolbarLabel"></span>
+ </div>
+ </div> <!-- findbar -->
+
+ <div class="editorParamsToolbar hidden doorHangerRight" id="editorHighlightParamsToolbar">
+ <div id="highlightParamsToolbarContainer" class="editorParamsToolbarContainer">
+ <div id="editorHighlightColorPicker" class="colorPicker">
+ <span id="highlightColorPickerLabel" class="editorParamsLabel" data-l10n-id="pdfjs-editor-highlight-colorpicker-label">Highlight color</span>
+ </div>
+ <div id="editorHighlightThickness">
+ <label for="editorFreeHighlightThickness" class="editorParamsLabel" data-l10n-id="pdfjs-editor-free-highlight-thickness-input">Thickness</label>
+ <div class="thicknessPicker">
+ <input type="range" id="editorFreeHighlightThickness" class="editorParamsSlider" data-l10n-id="pdfjs-editor-free-highlight-thickness-title" value="12" min="8" max="24" step="1" tabindex="101">
+ </div>
+ </div>
+ </div>
+ </div>
+
+ <div class="editorParamsToolbar hidden doorHangerRight" id="editorFreeTextParamsToolbar">
+ <div class="editorParamsToolbarContainer">
+ <div class="editorParamsSetter">
+ <label for="editorFreeTextColor" class="editorParamsLabel" data-l10n-id="pdfjs-editor-free-text-color-input">Color</label>
+ <input type="color" id="editorFreeTextColor" class="editorParamsColor" tabindex="102">
+ </div>
+ <div class="editorParamsSetter">
+ <label for="editorFreeTextFontSize" class="editorParamsLabel" data-l10n-id="pdfjs-editor-free-text-size-input">Size</label>
+ <input type="range" id="editorFreeTextFontSize" class="editorParamsSlider" value="10" min="5" max="100" step="1" tabindex="103">
+ </div>
+ </div>
+ </div>
+
+ <div class="editorParamsToolbar hidden doorHangerRight" id="editorInkParamsToolbar">
+ <div class="editorParamsToolbarContainer">
+ <div class="editorParamsSetter">
+ <label for="editorInkColor" class="editorParamsLabel" data-l10n-id="pdfjs-editor-ink-color-input">Color</label>
+ <input type="color" id="editorInkColor" class="editorParamsColor" tabindex="104">
+ </div>
+ <div class="editorParamsSetter">
+ <label for="editorInkThickness" class="editorParamsLabel" data-l10n-id="pdfjs-editor-ink-thickness-input">Thickness</label>
+ <input type="range" id="editorInkThickness" class="editorParamsSlider" value="1" min="1" max="20" step="1" tabindex="105">
+ </div>
+ <div class="editorParamsSetter">
+ <label for="editorInkOpacity" class="editorParamsLabel" data-l10n-id="pdfjs-editor-ink-opacity-input">Opacity</label>
+ <input type="range" id="editorInkOpacity" class="editorParamsSlider" value="100" min="1" max="100" step="1" tabindex="106">
+ </div>
+ </div>
+ </div>
+
+ <div class="editorParamsToolbar hidden doorHangerRight" id="editorStampParamsToolbar">
+ <div class="editorParamsToolbarContainer">
+ <button id="editorStampAddImage" class="secondaryToolbarButton" title="Add image" tabindex="107" data-l10n-id="pdfjs-editor-stamp-add-image-button">
+ <span class="editorParamsLabel" data-l10n-id="pdfjs-editor-stamp-add-image-button-label">Add image</span>
+ </button>
+ </div>
+ </div>
+
+ <div id="secondaryToolbar" class="secondaryToolbar hidden doorHangerRight">
+ <div id="secondaryToolbarButtonContainer">
+
+ <button id="secondaryPrint" class="secondaryToolbarButton visibleMediumView" title="Print" tabindex="52" data-l10n-id="pdfjs-print-button">
+ <span data-l10n-id="pdfjs-print-button-label">Print</span>
+ </button>
+
+ <button id="secondaryDownload" class="secondaryToolbarButton visibleMediumView" title="Save" tabindex="53" data-l10n-id="pdfjs-save-button">
+ <span data-l10n-id="pdfjs-save-button-label">Save</span>
+ </button>
+
+ <div class="horizontalToolbarSeparator visibleMediumView"></div>
+
+ <button id="presentationMode" class="secondaryToolbarButton" title="Switch to Presentation Mode" tabindex="54" data-l10n-id="pdfjs-presentation-mode-button">
+ <span data-l10n-id="pdfjs-presentation-mode-button-label">Presentation Mode</span>
+ </button>
+
+ <a href="#" id="viewBookmark" class="secondaryToolbarButton" title="Current Page (View URL from Current Page)" tabindex="55" data-l10n-id="pdfjs-bookmark-button">
+ <span data-l10n-id="pdfjs-bookmark-button-label">Current Page</span>
+ </a>
+
+ <div id="viewBookmarkSeparator" class="horizontalToolbarSeparator"></div>
+
+ <button id="firstPage" class="secondaryToolbarButton" title="Go to First Page" tabindex="56" data-l10n-id="pdfjs-first-page-button">
+ <span data-l10n-id="pdfjs-first-page-button-label">Go to First Page</span>
+ </button>
+ <button id="lastPage" class="secondaryToolbarButton" title="Go to Last Page" tabindex="57" data-l10n-id="pdfjs-last-page-button">
+ <span data-l10n-id="pdfjs-last-page-button-label">Go to Last Page</span>
+ </button>
+
+ <div class="horizontalToolbarSeparator"></div>
+
+ <button id="pageRotateCw" class="secondaryToolbarButton" title="Rotate Clockwise" tabindex="58" data-l10n-id="pdfjs-page-rotate-cw-button">
+ <span data-l10n-id="pdfjs-page-rotate-cw-button-label">Rotate Clockwise</span>
+ </button>
+ <button id="pageRotateCcw" class="secondaryToolbarButton" title="Rotate Counterclockwise" tabindex="59" data-l10n-id="pdfjs-page-rotate-ccw-button">
+ <span data-l10n-id="pdfjs-page-rotate-ccw-button-label">Rotate Counterclockwise</span>
+ </button>
+
+ <div class="horizontalToolbarSeparator"></div>
+
+ <div id="cursorToolButtons" role="radiogroup">
+ <button id="cursorSelectTool" class="secondaryToolbarButton toggled" title="Enable Text Selection Tool" tabindex="60" data-l10n-id="pdfjs-cursor-text-select-tool-button" role="radio" aria-checked="true">
+ <span data-l10n-id="pdfjs-cursor-text-select-tool-button-label">Text Selection Tool</span>
+ </button>
+ <button id="cursorHandTool" class="secondaryToolbarButton" title="Enable Hand Tool" tabindex="61" data-l10n-id="pdfjs-cursor-hand-tool-button" role="radio" aria-checked="false">
+ <span data-l10n-id="pdfjs-cursor-hand-tool-button-label">Hand Tool</span>
+ </button>
+ </div>
+
+ <div class="horizontalToolbarSeparator"></div>
+
+ <div id="scrollModeButtons" role="radiogroup">
+ <button id="scrollPage" class="secondaryToolbarButton" title="Use Page Scrolling" tabindex="62" data-l10n-id="pdfjs-scroll-page-button" role="radio" aria-checked="false">
+ <span data-l10n-id="pdfjs-scroll-page-button-label">Page Scrolling</span>
+ </button>
+ <button id="scrollVertical" class="secondaryToolbarButton toggled" title="Use Vertical Scrolling" tabindex="63" data-l10n-id="pdfjs-scroll-vertical-button" role="radio" aria-checked="true">
+ <span data-l10n-id="pdfjs-scroll-vertical-button-label" >Vertical Scrolling</span>
+ </button>
+ <button id="scrollHorizontal" class="secondaryToolbarButton" title="Use Horizontal Scrolling" tabindex="64" data-l10n-id="pdfjs-scroll-horizontal-button" role="radio" aria-checked="false">
+ <span data-l10n-id="pdfjs-scroll-horizontal-button-label">Horizontal Scrolling</span>
+ </button>
+ <button id="scrollWrapped" class="secondaryToolbarButton" title="Use Wrapped Scrolling" tabindex="65" data-l10n-id="pdfjs-scroll-wrapped-button" role="radio" aria-checked="false">
+ <span data-l10n-id="pdfjs-scroll-wrapped-button-label">Wrapped Scrolling</span>
+ </button>
+ </div>
+
+ <div class="horizontalToolbarSeparator"></div>
+
+ <div id="spreadModeButtons" role="radiogroup">
+ <button id="spreadNone" class="secondaryToolbarButton toggled" title="Do not join page spreads" tabindex="66" data-l10n-id="pdfjs-spread-none-button" role="radio" aria-checked="true">
+ <span data-l10n-id="pdfjs-spread-none-button-label">No Spreads</span>
+ </button>
+ <button id="spreadOdd" class="secondaryToolbarButton" title="Join page spreads starting with odd-numbered pages" tabindex="67" data-l10n-id="pdfjs-spread-odd-button" role="radio" aria-checked="false">
+ <span data-l10n-id="pdfjs-spread-odd-button-label">Odd Spreads</span>
+ </button>
+ <button id="spreadEven" class="secondaryToolbarButton" title="Join page spreads starting with even-numbered pages" tabindex="68" data-l10n-id="pdfjs-spread-even-button" role="radio" aria-checked="false">
+ <span data-l10n-id="pdfjs-spread-even-button-label">Even Spreads</span>
+ </button>
+ </div>
+
+ <div class="horizontalToolbarSeparator"></div>
+
+ <button id="documentProperties" class="secondaryToolbarButton" title="Document Properties…" tabindex="69" data-l10n-id="pdfjs-document-properties-button" aria-controls="documentPropertiesDialog">
+ <span data-l10n-id="pdfjs-document-properties-button-label">Document Properties…</span>
+ </button>
+ </div>
+ </div> <!-- secondaryToolbar -->
+
+ <div class="toolbar">
+ <div id="toolbarContainer">
+ <div id="toolbarViewer">
+ <div id="toolbarViewerLeft">
+ <button id="sidebarToggle" class="toolbarButton" title="Toggle Sidebar" tabindex="11" data-l10n-id="pdfjs-toggle-sidebar-button" aria-expanded="false" aria-controls="sidebarContainer">
+ <span data-l10n-id="pdfjs-toggle-sidebar-button-label">Toggle Sidebar</span>
+ </button>
+ <div class="toolbarButtonSpacer"></div>
+ <button id="viewFind" class="toolbarButton" title="Find in Document" tabindex="12" data-l10n-id="pdfjs-findbar-button" aria-expanded="false" aria-controls="findbar">
+ <span data-l10n-id="pdfjs-findbar-button-label">Find</span>
+ </button>
+ <div class="splitToolbarButton hiddenSmallView">
+ <button class="toolbarButton" title="Previous Page" id="previous" tabindex="13" data-l10n-id="pdfjs-previous-button">
+ <span data-l10n-id="pdfjs-previous-button-label">Previous</span>
+ </button>
+ <div class="splitToolbarButtonSeparator"></div>
+ <button class="toolbarButton" title="Next Page" id="next" tabindex="14" data-l10n-id="pdfjs-next-button">
+ <span data-l10n-id="pdfjs-next-button-label">Next</span>
+ </button>
+ </div>
+ <span class="loadingInput start">
+ <input type="number" id="pageNumber" class="toolbarField" title="Page" value="1" min="1" tabindex="15" data-l10n-id="pdfjs-page-input" autocomplete="off">
+ </span>
+ <span id="numPages" class="toolbarLabel"></span>
+ </div>
+ <div id="toolbarViewerRight">
+ <div id="editorModeButtons" class="splitToolbarButton toggled" role="radiogroup">
+ <button id="editorHighlight" class="toolbarButton" hidden="true" disabled="disabled" title="Highlight" role="radio" aria-checked="false" aria-controls="editorHighlightParamsToolbar" tabindex="31" data-l10n-id="pdfjs-editor-highlight-button">
+ <span data-l10n-id="pdfjs-editor-highlight-button-label">Highlight</span>
+ </button>
+ <button id="editorFreeText" class="toolbarButton" disabled="disabled" title="Text" role="radio" aria-checked="false" aria-controls="editorFreeTextParamsToolbar" tabindex="32" data-l10n-id="pdfjs-editor-free-text-button">
+ <span data-l10n-id="pdfjs-editor-free-text-button-label">Text</span>
+ </button>
+ <button id="editorInk" class="toolbarButton" disabled="disabled" title="Draw" role="radio" aria-checked="false" aria-controls="editorInkParamsToolbar" tabindex="33" data-l10n-id="pdfjs-editor-ink-button">
+ <span data-l10n-id="pdfjs-editor-ink-button-label">Draw</span>
+ </button>
+ <button id="editorStamp" class="toolbarButton hidden" disabled="disabled" title="Add or edit images" role="radio" aria-checked="false" aria-controls="editorStampParamsToolbar" tabindex="34" data-l10n-id="pdfjs-editor-stamp-button">
+ <span data-l10n-id="pdfjs-editor-stamp-button-label">Add or edit images</span>
+ </button>
+ </div>
+
+ <div id="editorModeSeparator" class="verticalToolbarSeparator"></div>
+
+ <button id="print" class="toolbarButton hiddenMediumView" title="Print" tabindex="41" data-l10n-id="pdfjs-print-button">
+ <span data-l10n-id="pdfjs-print-button-label">Print</span>
+ </button>
+
+ <button id="download" class="toolbarButton hiddenMediumView" title="Save" tabindex="42" data-l10n-id="pdfjs-save-button">
+ <span data-l10n-id="pdfjs-save-button-label">Save</span>
+ </button>
+
+ <div class="verticalToolbarSeparator hiddenMediumView"></div>
+
+ <button id="secondaryToolbarToggle" class="toolbarButton" title="Tools" tabindex="43" data-l10n-id="pdfjs-tools-button" aria-expanded="false" aria-controls="secondaryToolbar">
+ <span data-l10n-id="pdfjs-tools-button-label">Tools</span>
+ </button>
+ </div>
+ <div id="toolbarViewerMiddle">
+ <div class="splitToolbarButton">
+ <button id="zoomOut" class="toolbarButton" title="Zoom Out" tabindex="21" data-l10n-id="pdfjs-zoom-out-button">
+ <span data-l10n-id="pdfjs-zoom-out-button-label">Zoom Out</span>
+ </button>
+ <div class="splitToolbarButtonSeparator"></div>
+ <button id="zoomIn" class="toolbarButton" title="Zoom In" tabindex="22" data-l10n-id="pdfjs-zoom-in-button">
+ <span data-l10n-id="pdfjs-zoom-in-button-label">Zoom In</span>
+ </button>
+ </div>
+ <span id="scaleSelectContainer" class="dropdownToolbarButton">
+ <select id="scaleSelect" title="Zoom" tabindex="23" data-l10n-id="pdfjs-zoom-select">
+ <option id="pageAutoOption" title="" value="auto" selected="selected" data-l10n-id="pdfjs-page-scale-auto">Automatic Zoom</option>
+ <option id="pageActualOption" title="" value="page-actual" data-l10n-id="pdfjs-page-scale-actual">Actual Size</option>
+ <option id="pageFitOption" title="" value="page-fit" data-l10n-id="pdfjs-page-scale-fit">Page Fit</option>
+ <option id="pageWidthOption" title="" value="page-width" data-l10n-id="pdfjs-page-scale-width">Page Width</option>
+ <option id="customScaleOption" title="" value="custom" disabled="disabled" hidden="true" data-l10n-id="pdfjs-page-scale-percent" data-l10n-args='{ "scale": 0 }'>0%</option>
+ <option title="" value="0.5" data-l10n-id="pdfjs-page-scale-percent" data-l10n-args='{ "scale": 50 }'>50%</option>
+ <option title="" value="0.75" data-l10n-id="pdfjs-page-scale-percent" data-l10n-args='{ "scale": 75 }'>75%</option>
+ <option title="" value="1" data-l10n-id="pdfjs-page-scale-percent" data-l10n-args='{ "scale": 100 }'>100%</option>
+ <option title="" value="1.25" data-l10n-id="pdfjs-page-scale-percent" data-l10n-args='{ "scale": 125 }'>125%</option>
+ <option title="" value="1.5" data-l10n-id="pdfjs-page-scale-percent" data-l10n-args='{ "scale": 150 }'>150%</option>
+ <option title="" value="2" data-l10n-id="pdfjs-page-scale-percent" data-l10n-args='{ "scale": 200 }'>200%</option>
+ <option title="" value="3" data-l10n-id="pdfjs-page-scale-percent" data-l10n-args='{ "scale": 300 }'>300%</option>
+ <option title="" value="4" data-l10n-id="pdfjs-page-scale-percent" data-l10n-args='{ "scale": 400 }'>400%</option>
+ </select>
+ </span>
+ </div>
+ </div>
+ <div id="loadingBar">
+ <div class="progress">
+ <div class="glimmer">
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+
+ <div id="viewerContainer" tabindex="0">
+ <div id="viewer" class="pdfViewer"></div>
+ </div>
+ </div> <!-- mainContainer -->
+
+ <div id="dialogContainer">
+ <dialog id="passwordDialog">
+ <div class="row">
+ <label for="password" id="passwordText" data-l10n-id="pdfjs-password-label">Enter the password to open this PDF file:</label>
+ </div>
+ <div class="row">
+ <input type="password" id="password" class="toolbarField">
+ </div>
+ <div class="buttonRow">
+ <button id="passwordCancel" class="dialogButton"><span data-l10n-id="pdfjs-password-cancel-button">Cancel</span></button>
+ <button id="passwordSubmit" class="dialogButton"><span data-l10n-id="pdfjs-password-ok-button">OK</span></button>
+ </div>
+ </dialog>
+ <dialog id="documentPropertiesDialog">
+ <div class="row">
+ <span id="fileNameLabel" data-l10n-id="pdfjs-document-properties-file-name">File name:</span>
+ <p id="fileNameField" aria-labelledby="fileNameLabel">-</p>
+ </div>
+ <div class="row">
+ <span id="fileSizeLabel" data-l10n-id="pdfjs-document-properties-file-size">File size:</span>
+ <p id="fileSizeField" aria-labelledby="fileSizeLabel">-</p>
+ </div>
+ <div class="separator"></div>
+ <div class="row">
+ <span id="titleLabel" data-l10n-id="pdfjs-document-properties-title">Title:</span>
+ <p id="titleField" aria-labelledby="titleLabel">-</p>
+ </div>
+ <div class="row">
+ <span id="authorLabel" data-l10n-id="pdfjs-document-properties-author">Author:</span>
+ <p id="authorField" aria-labelledby="authorLabel">-</p>
+ </div>
+ <div class="row">
+ <span id="subjectLabel" data-l10n-id="pdfjs-document-properties-subject">Subject:</span>
+ <p id="subjectField" aria-labelledby="subjectLabel">-</p>
+ </div>
+ <div class="row">
+ <span id="keywordsLabel" data-l10n-id="pdfjs-document-properties-keywords">Keywords:</span>
+ <p id="keywordsField" aria-labelledby="keywordsLabel">-</p>
+ </div>
+ <div class="row">
+ <span id="creationDateLabel" data-l10n-id="pdfjs-document-properties-creation-date">Creation Date:</span>
+ <p id="creationDateField" aria-labelledby="creationDateLabel">-</p>
+ </div>
+ <div class="row">
+ <span id="modificationDateLabel" data-l10n-id="pdfjs-document-properties-modification-date">Modification Date:</span>
+ <p id="modificationDateField" aria-labelledby="modificationDateLabel">-</p>
+ </div>
+ <div class="row">
+ <span id="creatorLabel" data-l10n-id="pdfjs-document-properties-creator">Creator:</span>
+ <p id="creatorField" aria-labelledby="creatorLabel">-</p>
+ </div>
+ <div class="separator"></div>
+ <div class="row">
+ <span id="producerLabel" data-l10n-id="pdfjs-document-properties-producer">PDF Producer:</span>
+ <p id="producerField" aria-labelledby="producerLabel">-</p>
+ </div>
+ <div class="row">
+ <span id="versionLabel" data-l10n-id="pdfjs-document-properties-version">PDF Version:</span>
+ <p id="versionField" aria-labelledby="versionLabel">-</p>
+ </div>
+ <div class="row">
+ <span id="pageCountLabel" data-l10n-id="pdfjs-document-properties-page-count">Page Count:</span>
+ <p id="pageCountField" aria-labelledby="pageCountLabel">-</p>
+ </div>
+ <div class="row">
+ <span id="pageSizeLabel" data-l10n-id="pdfjs-document-properties-page-size">Page Size:</span>
+ <p id="pageSizeField" aria-labelledby="pageSizeLabel">-</p>
+ </div>
+ <div class="separator"></div>
+ <div class="row">
+ <span id="linearizedLabel" data-l10n-id="pdfjs-document-properties-linearized">Fast Web View:</span>
+ <p id="linearizedField" aria-labelledby="linearizedLabel">-</p>
+ </div>
+ <div class="buttonRow">
+ <button id="documentPropertiesClose" class="dialogButton"><span data-l10n-id="pdfjs-document-properties-close-button">Close</span></button>
+ </div>
+ </dialog>
+ <dialog id="altTextDialog" aria-labelledby="dialogLabel" aria-describedby="dialogDescription">
+ <div id="altTextContainer">
+ <div id="overallDescription">
+ <span id="dialogLabel" data-l10n-id="pdfjs-editor-alt-text-dialog-label" class="title">Choose an option</span>
+ <span id="dialogDescription" data-l10n-id="pdfjs-editor-alt-text-dialog-description">
+ Alt text (alternative text) helps when people can’t see the image or when it doesn’t load.
+ </span>
+ </div>
+ <div id="addDescription">
+ <div class="radio">
+ <div class="radioButton">
+ <input type="radio" id="descriptionButton" name="altTextOption" tabindex="0" aria-describedby="descriptionAreaLabel" checked>
+ <label for="descriptionButton" data-l10n-id="pdfjs-editor-alt-text-add-description-label">Add a description</label>
+ </div>
+ <div class="radioLabel">
+ <span id="descriptionAreaLabel" data-l10n-id="pdfjs-editor-alt-text-add-description-description">
+ Aim for 1-2 sentences that describe the subject, setting, or actions.
+ </span>
+ </div>
+ </div>
+ <div class="descriptionArea">
+ <textarea id="descriptionTextarea" placeholder="For example, “A young man sits down at a table to eat a mealâ€" aria-labelledby="descriptionAreaLabel" data-l10n-id="pdfjs-editor-alt-text-textarea" tabindex="0"></textarea>
+ </div>
+ </div>
+ <div id="markAsDecorative">
+ <div class="radio">
+ <div class="radioButton">
+ <input type="radio" id="decorativeButton" name="altTextOption" aria-describedby="decorativeLabel">
+ <label for="decorativeButton" data-l10n-id="pdfjs-editor-alt-text-mark-decorative-label">Mark as decorative</label>
+ </div>
+ <div class="radioLabel">
+ <span id="decorativeLabel" data-l10n-id="pdfjs-editor-alt-text-mark-decorative-description">
+ This is used for ornamental images, like borders or watermarks.
+ </span>
+ </div>
+ </div>
+ </div>
+ <div id="buttons">
+ <button id="altTextCancel" tabindex="0"><span data-l10n-id="pdfjs-editor-alt-text-cancel-button">Cancel</span></button>
+ <button id="altTextSave" tabindex="0"><span data-l10n-id="pdfjs-editor-alt-text-save-button">Save</span></button>
+ </div>
+ </div>
+ </dialog>
+ </div> <!-- dialogContainer -->
+
+ </div> <!-- outerContainer -->
+ <div id="printContainer"></div>
+ </body>
+</html>
diff --git a/toolkit/components/pdfjs/content/web/viewer.mjs b/toolkit/components/pdfjs/content/web/viewer.mjs
new file mode 100644
index 0000000000..a047a9f7c1
--- /dev/null
+++ b/toolkit/components/pdfjs/content/web/viewer.mjs
@@ -0,0 +1,12740 @@
+/**
+ * @licstart The following is the entire license notice for the
+ * JavaScript code in this page
+ *
+ * Copyright 2023 Mozilla Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * @licend The above is the entire license notice for the
+ * JavaScript code in this page
+ */
+
+/******/ // The require scope
+/******/ var __webpack_require__ = {};
+/******/
+/************************************************************************/
+/******/ /* webpack/runtime/define property getters */
+/******/ (() => {
+/******/ // define getter functions for harmony exports
+/******/ __webpack_require__.d = (exports, definition) => {
+/******/ for(var key in definition) {
+/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
+/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
+/******/ }
+/******/ }
+/******/ };
+/******/ })();
+/******/
+/******/ /* webpack/runtime/hasOwnProperty shorthand */
+/******/ (() => {
+/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
+/******/ })();
+/******/
+/************************************************************************/
+var __webpack_exports__ = {};
+
+// EXPORTS
+__webpack_require__.d(__webpack_exports__, {
+ PDFViewerApplication: () => (/* reexport */ PDFViewerApplication),
+ PDFViewerApplicationConstants: () => (/* binding */ AppConstants),
+ PDFViewerApplicationOptions: () => (/* reexport */ AppOptions)
+});
+
+;// CONCATENATED MODULE: ./web/ui_utils.js
+const DEFAULT_SCALE_VALUE = "auto";
+const DEFAULT_SCALE = 1.0;
+const DEFAULT_SCALE_DELTA = 1.1;
+const MIN_SCALE = 0.1;
+const MAX_SCALE = 10.0;
+const UNKNOWN_SCALE = 0;
+const MAX_AUTO_SCALE = 1.25;
+const SCROLLBAR_PADDING = 40;
+const VERTICAL_PADDING = 5;
+const RenderingStates = {
+ INITIAL: 0,
+ RUNNING: 1,
+ PAUSED: 2,
+ FINISHED: 3
+};
+const PresentationModeState = {
+ UNKNOWN: 0,
+ NORMAL: 1,
+ CHANGING: 2,
+ FULLSCREEN: 3
+};
+const SidebarView = {
+ UNKNOWN: -1,
+ NONE: 0,
+ THUMBS: 1,
+ OUTLINE: 2,
+ ATTACHMENTS: 3,
+ LAYERS: 4
+};
+const TextLayerMode = {
+ DISABLE: 0,
+ ENABLE: 1,
+ ENABLE_PERMISSIONS: 2
+};
+const ScrollMode = {
+ UNKNOWN: -1,
+ VERTICAL: 0,
+ HORIZONTAL: 1,
+ WRAPPED: 2,
+ PAGE: 3
+};
+const SpreadMode = {
+ UNKNOWN: -1,
+ NONE: 0,
+ ODD: 1,
+ EVEN: 2
+};
+const CursorTool = {
+ SELECT: 0,
+ HAND: 1,
+ ZOOM: 2
+};
+const AutoPrintRegExp = /\bprint\s*\(/;
+class OutputScale {
+ constructor() {
+ const pixelRatio = window.devicePixelRatio || 1;
+ this.sx = pixelRatio;
+ this.sy = pixelRatio;
+ }
+ get scaled() {
+ return this.sx !== 1 || this.sy !== 1;
+ }
+}
+function scrollIntoView(element, spot, scrollMatches = false) {
+ let parent = element.offsetParent;
+ if (!parent) {
+ console.error("offsetParent is not set -- cannot scroll");
+ return;
+ }
+ let offsetY = element.offsetTop + element.clientTop;
+ let offsetX = element.offsetLeft + element.clientLeft;
+ while (parent.clientHeight === parent.scrollHeight && parent.clientWidth === parent.scrollWidth || scrollMatches && (parent.classList.contains("markedContent") || getComputedStyle(parent).overflow === "hidden")) {
+ offsetY += parent.offsetTop;
+ offsetX += parent.offsetLeft;
+ parent = parent.offsetParent;
+ if (!parent) {
+ return;
+ }
+ }
+ if (spot) {
+ if (spot.top !== undefined) {
+ offsetY += spot.top;
+ }
+ if (spot.left !== undefined) {
+ offsetX += spot.left;
+ parent.scrollLeft = offsetX;
+ }
+ }
+ parent.scrollTop = offsetY;
+}
+function watchScroll(viewAreaElement, callback) {
+ const debounceScroll = function (evt) {
+ if (rAF) {
+ return;
+ }
+ rAF = window.requestAnimationFrame(function viewAreaElementScrolled() {
+ rAF = null;
+ const currentX = viewAreaElement.scrollLeft;
+ const lastX = state.lastX;
+ if (currentX !== lastX) {
+ state.right = currentX > lastX;
+ }
+ state.lastX = currentX;
+ const currentY = viewAreaElement.scrollTop;
+ const lastY = state.lastY;
+ if (currentY !== lastY) {
+ state.down = currentY > lastY;
+ }
+ state.lastY = currentY;
+ callback(state);
+ });
+ };
+ const state = {
+ right: true,
+ down: true,
+ lastX: viewAreaElement.scrollLeft,
+ lastY: viewAreaElement.scrollTop,
+ _eventHandler: debounceScroll
+ };
+ let rAF = null;
+ viewAreaElement.addEventListener("scroll", debounceScroll, true);
+ return state;
+}
+function parseQueryString(query) {
+ const params = new Map();
+ for (const [key, value] of new URLSearchParams(query)) {
+ params.set(key.toLowerCase(), value);
+ }
+ return params;
+}
+const InvisibleCharsRegExp = /[\x00-\x1F]/g;
+function removeNullCharacters(str, replaceInvisible = false) {
+ if (!InvisibleCharsRegExp.test(str)) {
+ return str;
+ }
+ if (replaceInvisible) {
+ return str.replaceAll(InvisibleCharsRegExp, m => m === "\x00" ? "" : " ");
+ }
+ return str.replaceAll("\x00", "");
+}
+function binarySearchFirstItem(items, condition, start = 0) {
+ let minIndex = start;
+ let maxIndex = items.length - 1;
+ if (maxIndex < 0 || !condition(items[maxIndex])) {
+ return items.length;
+ }
+ if (condition(items[minIndex])) {
+ return minIndex;
+ }
+ while (minIndex < maxIndex) {
+ const currentIndex = minIndex + maxIndex >> 1;
+ const currentItem = items[currentIndex];
+ if (condition(currentItem)) {
+ maxIndex = currentIndex;
+ } else {
+ minIndex = currentIndex + 1;
+ }
+ }
+ return minIndex;
+}
+function approximateFraction(x) {
+ if (Math.floor(x) === x) {
+ return [x, 1];
+ }
+ const xinv = 1 / x;
+ const limit = 8;
+ if (xinv > limit) {
+ return [1, limit];
+ } else if (Math.floor(xinv) === xinv) {
+ return [1, xinv];
+ }
+ const x_ = x > 1 ? xinv : x;
+ let a = 0,
+ b = 1,
+ c = 1,
+ d = 1;
+ while (true) {
+ const p = a + c,
+ q = b + d;
+ if (q > limit) {
+ break;
+ }
+ if (x_ <= p / q) {
+ c = p;
+ d = q;
+ } else {
+ a = p;
+ b = q;
+ }
+ }
+ let result;
+ if (x_ - a / b < c / d - x_) {
+ result = x_ === x ? [a, b] : [b, a];
+ } else {
+ result = x_ === x ? [c, d] : [d, c];
+ }
+ return result;
+}
+function roundToDivide(x, div) {
+ const r = x % div;
+ return r === 0 ? x : Math.round(x - r + div);
+}
+function getPageSizeInches({
+ view,
+ userUnit,
+ rotate
+}) {
+ const [x1, y1, x2, y2] = view;
+ const changeOrientation = rotate % 180 !== 0;
+ const width = (x2 - x1) / 72 * userUnit;
+ const height = (y2 - y1) / 72 * userUnit;
+ return {
+ width: changeOrientation ? height : width,
+ height: changeOrientation ? width : height
+ };
+}
+function backtrackBeforeAllVisibleElements(index, views, top) {
+ if (index < 2) {
+ return index;
+ }
+ let elt = views[index].div;
+ let pageTop = elt.offsetTop + elt.clientTop;
+ if (pageTop >= top) {
+ elt = views[index - 1].div;
+ pageTop = elt.offsetTop + elt.clientTop;
+ }
+ for (let i = index - 2; i >= 0; --i) {
+ elt = views[i].div;
+ if (elt.offsetTop + elt.clientTop + elt.clientHeight <= pageTop) {
+ break;
+ }
+ index = i;
+ }
+ return index;
+}
+function getVisibleElements({
+ scrollEl,
+ views,
+ sortByVisibility = false,
+ horizontal = false,
+ rtl = false
+}) {
+ const top = scrollEl.scrollTop,
+ bottom = top + scrollEl.clientHeight;
+ const left = scrollEl.scrollLeft,
+ right = left + scrollEl.clientWidth;
+ function isElementBottomAfterViewTop(view) {
+ const element = view.div;
+ const elementBottom = element.offsetTop + element.clientTop + element.clientHeight;
+ return elementBottom > top;
+ }
+ function isElementNextAfterViewHorizontally(view) {
+ const element = view.div;
+ const elementLeft = element.offsetLeft + element.clientLeft;
+ const elementRight = elementLeft + element.clientWidth;
+ return rtl ? elementLeft < right : elementRight > left;
+ }
+ const visible = [],
+ ids = new Set(),
+ numViews = views.length;
+ let firstVisibleElementInd = binarySearchFirstItem(views, horizontal ? isElementNextAfterViewHorizontally : isElementBottomAfterViewTop);
+ if (firstVisibleElementInd > 0 && firstVisibleElementInd < numViews && !horizontal) {
+ firstVisibleElementInd = backtrackBeforeAllVisibleElements(firstVisibleElementInd, views, top);
+ }
+ let lastEdge = horizontal ? right : -1;
+ for (let i = firstVisibleElementInd; i < numViews; i++) {
+ const view = views[i],
+ element = view.div;
+ const currentWidth = element.offsetLeft + element.clientLeft;
+ const currentHeight = element.offsetTop + element.clientTop;
+ const viewWidth = element.clientWidth,
+ viewHeight = element.clientHeight;
+ const viewRight = currentWidth + viewWidth;
+ const viewBottom = currentHeight + viewHeight;
+ if (lastEdge === -1) {
+ if (viewBottom >= bottom) {
+ lastEdge = viewBottom;
+ }
+ } else if ((horizontal ? currentWidth : currentHeight) > lastEdge) {
+ break;
+ }
+ if (viewBottom <= top || currentHeight >= bottom || viewRight <= left || currentWidth >= right) {
+ continue;
+ }
+ const hiddenHeight = Math.max(0, top - currentHeight) + Math.max(0, viewBottom - bottom);
+ const hiddenWidth = Math.max(0, left - currentWidth) + Math.max(0, viewRight - right);
+ const fractionHeight = (viewHeight - hiddenHeight) / viewHeight,
+ fractionWidth = (viewWidth - hiddenWidth) / viewWidth;
+ const percent = fractionHeight * fractionWidth * 100 | 0;
+ visible.push({
+ id: view.id,
+ x: currentWidth,
+ y: currentHeight,
+ view,
+ percent,
+ widthPercent: fractionWidth * 100 | 0
+ });
+ ids.add(view.id);
+ }
+ const first = visible[0],
+ last = visible.at(-1);
+ if (sortByVisibility) {
+ visible.sort(function (a, b) {
+ const pc = a.percent - b.percent;
+ if (Math.abs(pc) > 0.001) {
+ return -pc;
+ }
+ return a.id - b.id;
+ });
+ }
+ return {
+ first,
+ last,
+ views: visible,
+ ids
+ };
+}
+function normalizeWheelEventDirection(evt) {
+ let delta = Math.hypot(evt.deltaX, evt.deltaY);
+ const angle = Math.atan2(evt.deltaY, evt.deltaX);
+ if (-0.25 * Math.PI < angle && angle < 0.75 * Math.PI) {
+ delta = -delta;
+ }
+ return delta;
+}
+function normalizeWheelEventDelta(evt) {
+ const deltaMode = evt.deltaMode;
+ let delta = normalizeWheelEventDirection(evt);
+ const MOUSE_PIXELS_PER_LINE = 30;
+ const MOUSE_LINES_PER_PAGE = 30;
+ if (deltaMode === WheelEvent.DOM_DELTA_PIXEL) {
+ delta /= MOUSE_PIXELS_PER_LINE * MOUSE_LINES_PER_PAGE;
+ } else if (deltaMode === WheelEvent.DOM_DELTA_LINE) {
+ delta /= MOUSE_LINES_PER_PAGE;
+ }
+ return delta;
+}
+function isValidRotation(angle) {
+ return Number.isInteger(angle) && angle % 90 === 0;
+}
+function isValidScrollMode(mode) {
+ return Number.isInteger(mode) && Object.values(ScrollMode).includes(mode) && mode !== ScrollMode.UNKNOWN;
+}
+function isValidSpreadMode(mode) {
+ return Number.isInteger(mode) && Object.values(SpreadMode).includes(mode) && mode !== SpreadMode.UNKNOWN;
+}
+function isPortraitOrientation(size) {
+ return size.width <= size.height;
+}
+const animationStarted = new Promise(function (resolve) {
+ window.requestAnimationFrame(resolve);
+});
+const docStyle = document.documentElement.style;
+function clamp(v, min, max) {
+ return Math.min(Math.max(v, min), max);
+}
+class ProgressBar {
+ #classList = null;
+ #disableAutoFetchTimeout = null;
+ #percent = 0;
+ #style = null;
+ #visible = true;
+ constructor(bar) {
+ this.#classList = bar.classList;
+ this.#style = bar.style;
+ }
+ get percent() {
+ return this.#percent;
+ }
+ set percent(val) {
+ this.#percent = clamp(val, 0, 100);
+ if (isNaN(val)) {
+ this.#classList.add("indeterminate");
+ return;
+ }
+ this.#classList.remove("indeterminate");
+ this.#style.setProperty("--progressBar-percent", `${this.#percent}%`);
+ }
+ setWidth(viewer) {
+ if (!viewer) {
+ return;
+ }
+ const container = viewer.parentNode;
+ const scrollbarWidth = container.offsetWidth - viewer.offsetWidth;
+ if (scrollbarWidth > 0) {
+ this.#style.setProperty("--progressBar-end-offset", `${scrollbarWidth}px`);
+ }
+ }
+ setDisableAutoFetch(delay = 5000) {
+ if (isNaN(this.#percent)) {
+ return;
+ }
+ if (this.#disableAutoFetchTimeout) {
+ clearTimeout(this.#disableAutoFetchTimeout);
+ }
+ this.show();
+ this.#disableAutoFetchTimeout = setTimeout(() => {
+ this.#disableAutoFetchTimeout = null;
+ this.hide();
+ }, delay);
+ }
+ hide() {
+ if (!this.#visible) {
+ return;
+ }
+ this.#visible = false;
+ this.#classList.add("hidden");
+ }
+ show() {
+ if (this.#visible) {
+ return;
+ }
+ this.#visible = true;
+ this.#classList.remove("hidden");
+ }
+}
+function getActiveOrFocusedElement() {
+ let curRoot = document;
+ let curActiveOrFocused = curRoot.activeElement || curRoot.querySelector(":focus");
+ while (curActiveOrFocused?.shadowRoot) {
+ curRoot = curActiveOrFocused.shadowRoot;
+ curActiveOrFocused = curRoot.activeElement || curRoot.querySelector(":focus");
+ }
+ return curActiveOrFocused;
+}
+function apiPageLayoutToViewerModes(layout) {
+ let scrollMode = ScrollMode.VERTICAL,
+ spreadMode = SpreadMode.NONE;
+ switch (layout) {
+ case "SinglePage":
+ scrollMode = ScrollMode.PAGE;
+ break;
+ case "OneColumn":
+ break;
+ case "TwoPageLeft":
+ scrollMode = ScrollMode.PAGE;
+ case "TwoColumnLeft":
+ spreadMode = SpreadMode.ODD;
+ break;
+ case "TwoPageRight":
+ scrollMode = ScrollMode.PAGE;
+ case "TwoColumnRight":
+ spreadMode = SpreadMode.EVEN;
+ break;
+ }
+ return {
+ scrollMode,
+ spreadMode
+ };
+}
+function apiPageModeToSidebarView(mode) {
+ switch (mode) {
+ case "UseNone":
+ return SidebarView.NONE;
+ case "UseThumbs":
+ return SidebarView.THUMBS;
+ case "UseOutlines":
+ return SidebarView.OUTLINE;
+ case "UseAttachments":
+ return SidebarView.ATTACHMENTS;
+ case "UseOC":
+ return SidebarView.LAYERS;
+ }
+ return SidebarView.NONE;
+}
+function toggleCheckedBtn(button, toggle, view = null) {
+ button.classList.toggle("toggled", toggle);
+ button.setAttribute("aria-checked", toggle);
+ view?.classList.toggle("hidden", !toggle);
+}
+function toggleExpandedBtn(button, toggle, view = null) {
+ button.classList.toggle("toggled", toggle);
+ button.setAttribute("aria-expanded", toggle);
+ view?.classList.toggle("hidden", !toggle);
+}
+
+;// CONCATENATED MODULE: ./web/app_options.js
+const compatibilityParams = Object.create(null);
+const OptionKind = {
+ BROWSER: 0x01,
+ VIEWER: 0x02,
+ API: 0x04,
+ WORKER: 0x08,
+ PREFERENCE: 0x80
+};
+const defaultOptions = {
+ canvasMaxAreaInBytes: {
+ value: -1,
+ kind: OptionKind.BROWSER + OptionKind.API
+ },
+ isInAutomation: {
+ value: false,
+ kind: OptionKind.BROWSER
+ },
+ supportsCaretBrowsingMode: {
+ value: false,
+ kind: OptionKind.BROWSER
+ },
+ supportsDocumentFonts: {
+ value: true,
+ kind: OptionKind.BROWSER
+ },
+ supportsIntegratedFind: {
+ value: false,
+ kind: OptionKind.BROWSER
+ },
+ supportsMouseWheelZoomCtrlKey: {
+ value: true,
+ kind: OptionKind.BROWSER
+ },
+ supportsMouseWheelZoomMetaKey: {
+ value: true,
+ kind: OptionKind.BROWSER
+ },
+ supportsPinchToZoom: {
+ value: true,
+ kind: OptionKind.BROWSER
+ },
+ annotationEditorMode: {
+ value: 0,
+ kind: OptionKind.VIEWER + OptionKind.PREFERENCE
+ },
+ annotationMode: {
+ value: 2,
+ kind: OptionKind.VIEWER + OptionKind.PREFERENCE
+ },
+ cursorToolOnLoad: {
+ value: 0,
+ kind: OptionKind.VIEWER + OptionKind.PREFERENCE
+ },
+ debuggerSrc: {
+ value: "./debugger.mjs",
+ kind: OptionKind.VIEWER
+ },
+ defaultZoomDelay: {
+ value: 400,
+ kind: OptionKind.VIEWER + OptionKind.PREFERENCE
+ },
+ defaultZoomValue: {
+ value: "",
+ kind: OptionKind.VIEWER + OptionKind.PREFERENCE
+ },
+ disableHistory: {
+ value: false,
+ kind: OptionKind.VIEWER
+ },
+ disablePageLabels: {
+ value: false,
+ kind: OptionKind.VIEWER + OptionKind.PREFERENCE
+ },
+ enableHighlightEditor: {
+ value: false,
+ kind: OptionKind.VIEWER + OptionKind.PREFERENCE
+ },
+ enableML: {
+ value: false,
+ kind: OptionKind.VIEWER + OptionKind.PREFERENCE
+ },
+ enablePermissions: {
+ value: false,
+ kind: OptionKind.VIEWER + OptionKind.PREFERENCE
+ },
+ enablePrintAutoRotate: {
+ value: true,
+ kind: OptionKind.VIEWER + OptionKind.PREFERENCE
+ },
+ enableScripting: {
+ value: true,
+ kind: OptionKind.VIEWER + OptionKind.PREFERENCE
+ },
+ enableStampEditor: {
+ value: true,
+ kind: OptionKind.VIEWER + OptionKind.PREFERENCE
+ },
+ externalLinkRel: {
+ value: "noopener noreferrer nofollow",
+ kind: OptionKind.VIEWER
+ },
+ externalLinkTarget: {
+ value: 0,
+ kind: OptionKind.VIEWER + OptionKind.PREFERENCE
+ },
+ highlightEditorColors: {
+ value: "yellow=#FFFF98,green=#53FFBC,blue=#80EBFF,pink=#FFCBE6,red=#FF4F5F",
+ kind: OptionKind.VIEWER + OptionKind.PREFERENCE
+ },
+ historyUpdateUrl: {
+ value: false,
+ kind: OptionKind.VIEWER + OptionKind.PREFERENCE
+ },
+ ignoreDestinationZoom: {
+ value: false,
+ kind: OptionKind.VIEWER + OptionKind.PREFERENCE
+ },
+ imageResourcesPath: {
+ value: "resource://pdf.js/web/images/",
+ kind: OptionKind.VIEWER
+ },
+ maxCanvasPixels: {
+ value: 16777216,
+ kind: OptionKind.VIEWER
+ },
+ forcePageColors: {
+ value: false,
+ kind: OptionKind.VIEWER + OptionKind.PREFERENCE
+ },
+ pageColorsBackground: {
+ value: "Canvas",
+ kind: OptionKind.VIEWER + OptionKind.PREFERENCE
+ },
+ pageColorsForeground: {
+ value: "CanvasText",
+ kind: OptionKind.VIEWER + OptionKind.PREFERENCE
+ },
+ pdfBugEnabled: {
+ value: false,
+ kind: OptionKind.VIEWER + OptionKind.PREFERENCE
+ },
+ printResolution: {
+ value: 150,
+ kind: OptionKind.VIEWER
+ },
+ sidebarViewOnLoad: {
+ value: -1,
+ kind: OptionKind.VIEWER + OptionKind.PREFERENCE
+ },
+ scrollModeOnLoad: {
+ value: -1,
+ kind: OptionKind.VIEWER + OptionKind.PREFERENCE
+ },
+ spreadModeOnLoad: {
+ value: -1,
+ kind: OptionKind.VIEWER + OptionKind.PREFERENCE
+ },
+ textLayerMode: {
+ value: 1,
+ kind: OptionKind.VIEWER + OptionKind.PREFERENCE
+ },
+ viewOnLoad: {
+ value: 0,
+ kind: OptionKind.VIEWER + OptionKind.PREFERENCE
+ },
+ cMapPacked: {
+ value: true,
+ kind: OptionKind.API
+ },
+ cMapUrl: {
+ value: "resource://pdf.js/web/cmaps/",
+ kind: OptionKind.API
+ },
+ disableAutoFetch: {
+ value: false,
+ kind: OptionKind.API + OptionKind.PREFERENCE
+ },
+ disableFontFace: {
+ value: false,
+ kind: OptionKind.API + OptionKind.PREFERENCE
+ },
+ disableRange: {
+ value: false,
+ kind: OptionKind.API + OptionKind.PREFERENCE
+ },
+ disableStream: {
+ value: false,
+ kind: OptionKind.API + OptionKind.PREFERENCE
+ },
+ docBaseUrl: {
+ value: "",
+ kind: OptionKind.API
+ },
+ enableXfa: {
+ value: true,
+ kind: OptionKind.API + OptionKind.PREFERENCE
+ },
+ fontExtraProperties: {
+ value: false,
+ kind: OptionKind.API
+ },
+ isEvalSupported: {
+ value: true,
+ kind: OptionKind.API
+ },
+ isOffscreenCanvasSupported: {
+ value: true,
+ kind: OptionKind.API
+ },
+ maxImageSize: {
+ value: -1,
+ kind: OptionKind.API
+ },
+ pdfBug: {
+ value: false,
+ kind: OptionKind.API
+ },
+ standardFontDataUrl: {
+ value: "resource://pdf.js/web/standard_fonts/",
+ kind: OptionKind.API
+ },
+ verbosity: {
+ value: 1,
+ kind: OptionKind.API
+ },
+ workerPort: {
+ value: null,
+ kind: OptionKind.WORKER
+ },
+ workerSrc: {
+ value: "resource://pdf.js/build/pdf.worker.mjs",
+ kind: OptionKind.WORKER
+ }
+};
+const userOptions = Object.create(null);
+class AppOptions {
+ constructor() {
+ throw new Error("Cannot initialize AppOptions.");
+ }
+ static get(name) {
+ const userOption = userOptions[name];
+ if (userOption !== undefined) {
+ return userOption;
+ }
+ const defaultOption = defaultOptions[name];
+ if (defaultOption !== undefined) {
+ return compatibilityParams[name] ?? defaultOption.value;
+ }
+ return undefined;
+ }
+ static getAll(kind = null) {
+ const options = Object.create(null);
+ for (const name in defaultOptions) {
+ const defaultOption = defaultOptions[name];
+ if (kind) {
+ if (!(kind & defaultOption.kind)) {
+ continue;
+ }
+ }
+ const userOption = userOptions[name];
+ options[name] = userOption !== undefined ? userOption : compatibilityParams[name] ?? defaultOption.value;
+ }
+ return options;
+ }
+ static set(name, value) {
+ userOptions[name] = value;
+ }
+ static setAll(options, init = false) {
+ for (const name in options) {
+ userOptions[name] = options[name];
+ }
+ }
+ static remove(name) {
+ delete userOptions[name];
+ }
+}
+
+;// CONCATENATED MODULE: ./web/pdf_link_service.js
+
+const DEFAULT_LINK_REL = "noopener noreferrer nofollow";
+const LinkTarget = {
+ NONE: 0,
+ SELF: 1,
+ BLANK: 2,
+ PARENT: 3,
+ TOP: 4
+};
+function addLinkAttributes(link, {
+ url,
+ target,
+ rel,
+ enabled = true
+} = {}) {
+ if (!url || typeof url !== "string") {
+ throw new Error('A valid "url" parameter must provided.');
+ }
+ if (enabled) {
+ link.href = link.title = url;
+ } else {
+ link.href = "";
+ link.title = `Disabled: ${url}`;
+ link.onclick = () => false;
+ }
+ let targetStr = "";
+ switch (target) {
+ case LinkTarget.NONE:
+ break;
+ case LinkTarget.SELF:
+ targetStr = "_self";
+ break;
+ case LinkTarget.BLANK:
+ targetStr = "_blank";
+ break;
+ case LinkTarget.PARENT:
+ targetStr = "_parent";
+ break;
+ case LinkTarget.TOP:
+ targetStr = "_top";
+ break;
+ }
+ link.target = targetStr;
+ link.rel = typeof rel === "string" ? rel : DEFAULT_LINK_REL;
+}
+class PDFLinkService {
+ #pagesRefCache = new Map();
+ constructor({
+ eventBus,
+ externalLinkTarget = null,
+ externalLinkRel = null,
+ ignoreDestinationZoom = false
+ } = {}) {
+ this.eventBus = eventBus;
+ this.externalLinkTarget = externalLinkTarget;
+ this.externalLinkRel = externalLinkRel;
+ this.externalLinkEnabled = true;
+ this._ignoreDestinationZoom = ignoreDestinationZoom;
+ this.baseUrl = null;
+ this.pdfDocument = null;
+ this.pdfViewer = null;
+ this.pdfHistory = null;
+ }
+ setDocument(pdfDocument, baseUrl = null) {
+ this.baseUrl = baseUrl;
+ this.pdfDocument = pdfDocument;
+ this.#pagesRefCache.clear();
+ }
+ setViewer(pdfViewer) {
+ this.pdfViewer = pdfViewer;
+ }
+ setHistory(pdfHistory) {
+ this.pdfHistory = pdfHistory;
+ }
+ get pagesCount() {
+ return this.pdfDocument ? this.pdfDocument.numPages : 0;
+ }
+ get page() {
+ return this.pdfViewer.currentPageNumber;
+ }
+ set page(value) {
+ this.pdfViewer.currentPageNumber = value;
+ }
+ get rotation() {
+ return this.pdfViewer.pagesRotation;
+ }
+ set rotation(value) {
+ this.pdfViewer.pagesRotation = value;
+ }
+ get isInPresentationMode() {
+ return this.pdfViewer.isInPresentationMode;
+ }
+ #goToDestinationHelper(rawDest, namedDest = null, explicitDest) {
+ const destRef = explicitDest[0];
+ let pageNumber;
+ if (typeof destRef === "object" && destRef !== null) {
+ pageNumber = this._cachedPageNumber(destRef);
+ if (!pageNumber) {
+ this.pdfDocument.getPageIndex(destRef).then(pageIndex => {
+ this.cachePageRef(pageIndex + 1, destRef);
+ this.#goToDestinationHelper(rawDest, namedDest, explicitDest);
+ }).catch(() => {
+ console.error(`PDFLinkService.#goToDestinationHelper: "${destRef}" is not ` + `a valid page reference, for dest="${rawDest}".`);
+ });
+ return;
+ }
+ } else if (Number.isInteger(destRef)) {
+ pageNumber = destRef + 1;
+ } else {
+ console.error(`PDFLinkService.#goToDestinationHelper: "${destRef}" is not ` + `a valid destination reference, for dest="${rawDest}".`);
+ return;
+ }
+ if (!pageNumber || pageNumber < 1 || pageNumber > this.pagesCount) {
+ console.error(`PDFLinkService.#goToDestinationHelper: "${pageNumber}" is not ` + `a valid page number, for dest="${rawDest}".`);
+ return;
+ }
+ if (this.pdfHistory) {
+ this.pdfHistory.pushCurrentPosition();
+ this.pdfHistory.push({
+ namedDest,
+ explicitDest,
+ pageNumber
+ });
+ }
+ this.pdfViewer.scrollPageIntoView({
+ pageNumber,
+ destArray: explicitDest,
+ ignoreDestinationZoom: this._ignoreDestinationZoom
+ });
+ }
+ async goToDestination(dest) {
+ if (!this.pdfDocument) {
+ return;
+ }
+ let namedDest, explicitDest;
+ if (typeof dest === "string") {
+ namedDest = dest;
+ explicitDest = await this.pdfDocument.getDestination(dest);
+ } else {
+ namedDest = null;
+ explicitDest = await dest;
+ }
+ if (!Array.isArray(explicitDest)) {
+ console.error(`PDFLinkService.goToDestination: "${explicitDest}" is not ` + `a valid destination array, for dest="${dest}".`);
+ return;
+ }
+ this.#goToDestinationHelper(dest, namedDest, explicitDest);
+ }
+ goToPage(val) {
+ if (!this.pdfDocument) {
+ return;
+ }
+ const pageNumber = typeof val === "string" && this.pdfViewer.pageLabelToPageNumber(val) || val | 0;
+ if (!(Number.isInteger(pageNumber) && pageNumber > 0 && pageNumber <= this.pagesCount)) {
+ console.error(`PDFLinkService.goToPage: "${val}" is not a valid page.`);
+ return;
+ }
+ if (this.pdfHistory) {
+ this.pdfHistory.pushCurrentPosition();
+ this.pdfHistory.pushPage(pageNumber);
+ }
+ this.pdfViewer.scrollPageIntoView({
+ pageNumber
+ });
+ }
+ addLinkAttributes(link, url, newWindow = false) {
+ addLinkAttributes(link, {
+ url,
+ target: newWindow ? LinkTarget.BLANK : this.externalLinkTarget,
+ rel: this.externalLinkRel,
+ enabled: this.externalLinkEnabled
+ });
+ }
+ getDestinationHash(dest) {
+ if (typeof dest === "string") {
+ if (dest.length > 0) {
+ return this.getAnchorUrl("#" + escape(dest));
+ }
+ } else if (Array.isArray(dest)) {
+ const str = JSON.stringify(dest);
+ if (str.length > 0) {
+ return this.getAnchorUrl("#" + escape(str));
+ }
+ }
+ return this.getAnchorUrl("");
+ }
+ getAnchorUrl(anchor) {
+ return this.baseUrl ? this.baseUrl + anchor : anchor;
+ }
+ setHash(hash) {
+ if (!this.pdfDocument) {
+ return;
+ }
+ let pageNumber, dest;
+ if (hash.includes("=")) {
+ const params = parseQueryString(hash);
+ if (params.has("search")) {
+ const query = params.get("search").replaceAll('"', ""),
+ phrase = params.get("phrase") === "true";
+ this.eventBus.dispatch("findfromurlhash", {
+ source: this,
+ query: phrase ? query : query.match(/\S+/g)
+ });
+ }
+ if (params.has("page")) {
+ pageNumber = params.get("page") | 0 || 1;
+ }
+ if (params.has("zoom")) {
+ const zoomArgs = params.get("zoom").split(",");
+ const zoomArg = zoomArgs[0];
+ const zoomArgNumber = parseFloat(zoomArg);
+ if (!zoomArg.includes("Fit")) {
+ dest = [null, {
+ name: "XYZ"
+ }, zoomArgs.length > 1 ? zoomArgs[1] | 0 : null, zoomArgs.length > 2 ? zoomArgs[2] | 0 : null, zoomArgNumber ? zoomArgNumber / 100 : zoomArg];
+ } else if (zoomArg === "Fit" || zoomArg === "FitB") {
+ dest = [null, {
+ name: zoomArg
+ }];
+ } else if (zoomArg === "FitH" || zoomArg === "FitBH" || zoomArg === "FitV" || zoomArg === "FitBV") {
+ dest = [null, {
+ name: zoomArg
+ }, zoomArgs.length > 1 ? zoomArgs[1] | 0 : null];
+ } else if (zoomArg === "FitR") {
+ if (zoomArgs.length !== 5) {
+ console.error('PDFLinkService.setHash: Not enough parameters for "FitR".');
+ } else {
+ dest = [null, {
+ name: zoomArg
+ }, zoomArgs[1] | 0, zoomArgs[2] | 0, zoomArgs[3] | 0, zoomArgs[4] | 0];
+ }
+ } else {
+ console.error(`PDFLinkService.setHash: "${zoomArg}" is not a valid zoom value.`);
+ }
+ }
+ if (dest) {
+ this.pdfViewer.scrollPageIntoView({
+ pageNumber: pageNumber || this.page,
+ destArray: dest,
+ allowNegativeOffset: true
+ });
+ } else if (pageNumber) {
+ this.page = pageNumber;
+ }
+ if (params.has("pagemode")) {
+ this.eventBus.dispatch("pagemode", {
+ source: this,
+ mode: params.get("pagemode")
+ });
+ }
+ if (params.has("nameddest")) {
+ this.goToDestination(params.get("nameddest"));
+ }
+ if (!params.has("filename") || !params.has("filedest")) {
+ return;
+ }
+ hash = params.get("filedest");
+ }
+ dest = unescape(hash);
+ try {
+ dest = JSON.parse(dest);
+ if (!Array.isArray(dest)) {
+ dest = dest.toString();
+ }
+ } catch {}
+ if (typeof dest === "string" || PDFLinkService.#isValidExplicitDestination(dest)) {
+ this.goToDestination(dest);
+ return;
+ }
+ console.error(`PDFLinkService.setHash: "${unescape(hash)}" is not a valid destination.`);
+ }
+ executeNamedAction(action) {
+ switch (action) {
+ case "GoBack":
+ this.pdfHistory?.back();
+ break;
+ case "GoForward":
+ this.pdfHistory?.forward();
+ break;
+ case "NextPage":
+ this.pdfViewer.nextPage();
+ break;
+ case "PrevPage":
+ this.pdfViewer.previousPage();
+ break;
+ case "LastPage":
+ this.page = this.pagesCount;
+ break;
+ case "FirstPage":
+ this.page = 1;
+ break;
+ default:
+ break;
+ }
+ this.eventBus.dispatch("namedaction", {
+ source: this,
+ action
+ });
+ }
+ async executeSetOCGState(action) {
+ const pdfDocument = this.pdfDocument;
+ const optionalContentConfig = await this.pdfViewer.optionalContentConfigPromise;
+ if (pdfDocument !== this.pdfDocument) {
+ return;
+ }
+ let operator;
+ for (const elem of action.state) {
+ switch (elem) {
+ case "ON":
+ case "OFF":
+ case "Toggle":
+ operator = elem;
+ continue;
+ }
+ switch (operator) {
+ case "ON":
+ optionalContentConfig.setVisibility(elem, true);
+ break;
+ case "OFF":
+ optionalContentConfig.setVisibility(elem, false);
+ break;
+ case "Toggle":
+ const group = optionalContentConfig.getGroup(elem);
+ if (group) {
+ optionalContentConfig.setVisibility(elem, !group.visible);
+ }
+ break;
+ }
+ }
+ this.pdfViewer.optionalContentConfigPromise = Promise.resolve(optionalContentConfig);
+ }
+ cachePageRef(pageNum, pageRef) {
+ if (!pageRef) {
+ return;
+ }
+ const refStr = pageRef.gen === 0 ? `${pageRef.num}R` : `${pageRef.num}R${pageRef.gen}`;
+ this.#pagesRefCache.set(refStr, pageNum);
+ }
+ _cachedPageNumber(pageRef) {
+ if (!pageRef) {
+ return null;
+ }
+ const refStr = pageRef.gen === 0 ? `${pageRef.num}R` : `${pageRef.num}R${pageRef.gen}`;
+ return this.#pagesRefCache.get(refStr) || null;
+ }
+ static #isValidExplicitDestination(dest) {
+ if (!Array.isArray(dest)) {
+ return false;
+ }
+ const destLength = dest.length;
+ if (destLength < 2) {
+ return false;
+ }
+ const page = dest[0];
+ if (!(typeof page === "object" && Number.isInteger(page.num) && Number.isInteger(page.gen)) && !(Number.isInteger(page) && page >= 0)) {
+ return false;
+ }
+ const zoom = dest[1];
+ if (!(typeof zoom === "object" && typeof zoom.name === "string")) {
+ return false;
+ }
+ let allowNull = true;
+ switch (zoom.name) {
+ case "XYZ":
+ if (destLength !== 5) {
+ return false;
+ }
+ break;
+ case "Fit":
+ case "FitB":
+ return destLength === 2;
+ case "FitH":
+ case "FitBH":
+ case "FitV":
+ case "FitBV":
+ if (destLength !== 3) {
+ return false;
+ }
+ break;
+ case "FitR":
+ if (destLength !== 6) {
+ return false;
+ }
+ allowNull = false;
+ break;
+ default:
+ return false;
+ }
+ for (let i = 2; i < destLength; i++) {
+ const param = dest[i];
+ if (!(typeof param === "number" || allowNull && param === null)) {
+ return false;
+ }
+ }
+ return true;
+ }
+}
+class SimpleLinkService {
+ constructor() {
+ this.externalLinkEnabled = true;
+ }
+ get pagesCount() {
+ return 0;
+ }
+ get page() {
+ return 0;
+ }
+ set page(value) {}
+ get rotation() {
+ return 0;
+ }
+ set rotation(value) {}
+ get isInPresentationMode() {
+ return false;
+ }
+ async goToDestination(dest) {}
+ goToPage(val) {}
+ addLinkAttributes(link, url, newWindow = false) {
+ addLinkAttributes(link, {
+ url,
+ enabled: this.externalLinkEnabled
+ });
+ }
+ getDestinationHash(dest) {
+ return "#";
+ }
+ getAnchorUrl(hash) {
+ return "#";
+ }
+ setHash(hash) {}
+ executeNamedAction(action) {}
+ executeSetOCGState(action) {}
+ cachePageRef(pageNum, pageRef) {}
+}
+
+;// CONCATENATED MODULE: ./web/pdfjs.js
+const {
+ AbortException,
+ AnnotationEditorLayer,
+ AnnotationEditorParamsType,
+ AnnotationEditorType,
+ AnnotationEditorUIManager,
+ AnnotationLayer,
+ AnnotationMode,
+ build,
+ CMapCompressionType,
+ ColorPicker,
+ createValidAbsoluteUrl,
+ DOMSVGFactory,
+ DrawLayer,
+ FeatureTest,
+ fetchData,
+ getDocument,
+ getFilenameFromUrl,
+ getPdfFilenameFromUrl,
+ getXfaPageViewport,
+ GlobalWorkerOptions,
+ ImageKind,
+ InvalidPDFException,
+ isDataScheme,
+ isPdfFile,
+ MissingPDFException,
+ noContextMenu,
+ normalizeUnicode,
+ OPS,
+ Outliner,
+ PasswordResponses,
+ PDFDataRangeTransport,
+ PDFDateString,
+ PDFWorker,
+ PermissionFlag,
+ PixelsPerInch,
+ PromiseCapability,
+ RenderingCancelledException,
+ renderTextLayer,
+ setLayerDimensions,
+ shadow,
+ UnexpectedResponseException,
+ updateTextLayer,
+ Util,
+ VerbosityLevel,
+ version,
+ XfaLayer
+} = globalThis.pdfjsLib;
+
+;// CONCATENATED MODULE: ./web/event_utils.js
+const WaitOnType = {
+ EVENT: "event",
+ TIMEOUT: "timeout"
+};
+function waitOnEventOrTimeout({
+ target,
+ name,
+ delay = 0
+}) {
+ return new Promise(function (resolve, reject) {
+ if (typeof target !== "object" || !(name && typeof name === "string") || !(Number.isInteger(delay) && delay >= 0)) {
+ throw new Error("waitOnEventOrTimeout - invalid parameters.");
+ }
+ function handler(type) {
+ if (target instanceof EventBus) {
+ target._off(name, eventHandler);
+ } else {
+ target.removeEventListener(name, eventHandler);
+ }
+ if (timeout) {
+ clearTimeout(timeout);
+ }
+ resolve(type);
+ }
+ const eventHandler = handler.bind(null, WaitOnType.EVENT);
+ if (target instanceof EventBus) {
+ target._on(name, eventHandler);
+ } else {
+ target.addEventListener(name, eventHandler);
+ }
+ const timeoutHandler = handler.bind(null, WaitOnType.TIMEOUT);
+ const timeout = setTimeout(timeoutHandler, delay);
+ });
+}
+class EventBus {
+ #listeners = Object.create(null);
+ on(eventName, listener, options = null) {
+ this._on(eventName, listener, {
+ external: true,
+ once: options?.once
+ });
+ }
+ off(eventName, listener, options = null) {
+ this._off(eventName, listener, {
+ external: true,
+ once: options?.once
+ });
+ }
+ dispatch(eventName, data) {
+ const eventListeners = this.#listeners[eventName];
+ if (!eventListeners || eventListeners.length === 0) {
+ return;
+ }
+ let externalListeners;
+ for (const {
+ listener,
+ external,
+ once
+ } of eventListeners.slice(0)) {
+ if (once) {
+ this._off(eventName, listener);
+ }
+ if (external) {
+ (externalListeners ||= []).push(listener);
+ continue;
+ }
+ listener(data);
+ }
+ if (externalListeners) {
+ for (const listener of externalListeners) {
+ listener(data);
+ }
+ externalListeners = null;
+ }
+ }
+ _on(eventName, listener, options = null) {
+ const eventListeners = this.#listeners[eventName] ||= [];
+ eventListeners.push({
+ listener,
+ external: options?.external === true,
+ once: options?.once === true
+ });
+ }
+ _off(eventName, listener, options = null) {
+ const eventListeners = this.#listeners[eventName];
+ if (!eventListeners) {
+ return;
+ }
+ for (let i = 0, ii = eventListeners.length; i < ii; i++) {
+ if (eventListeners[i].listener === listener) {
+ eventListeners.splice(i, 1);
+ return;
+ }
+ }
+ }
+}
+class AutomationEventBus extends EventBus {
+ dispatch(eventName, data) {
+ super.dispatch(eventName, data);
+ const detail = Object.create(null);
+ if (data) {
+ for (const key in data) {
+ const value = data[key];
+ if (key === "source") {
+ if (value === window || value === document) {
+ return;
+ }
+ continue;
+ }
+ detail[key] = value;
+ }
+ }
+ const event = new CustomEvent(eventName, {
+ bubbles: true,
+ cancelable: true,
+ detail
+ });
+ document.dispatchEvent(event);
+ }
+}
+
+;// CONCATENATED MODULE: ./web/external_services.js
+class BaseExternalServices {
+ constructor() {
+ if (this.constructor === BaseExternalServices) {
+ throw new Error("Cannot initialize BaseExternalServices.");
+ }
+ }
+ updateFindControlState(data) {}
+ updateFindMatchesCount(data) {}
+ initPassiveLoading(callbacks) {}
+ reportTelemetry(data) {}
+ async createL10n() {
+ throw new Error("Not implemented: createL10n");
+ }
+ createScripting() {
+ throw new Error("Not implemented: createScripting");
+ }
+ updateEditorStates(data) {
+ throw new Error("Not implemented: updateEditorStates");
+ }
+ async getNimbusExperimentData() {}
+}
+
+;// CONCATENATED MODULE: ./web/preferences.js
+
+class BasePreferences {
+ #defaults = Object.freeze({
+ annotationEditorMode: 0,
+ annotationMode: 2,
+ cursorToolOnLoad: 0,
+ defaultZoomDelay: 400,
+ defaultZoomValue: "",
+ disablePageLabels: false,
+ enableHighlightEditor: false,
+ enableML: false,
+ enablePermissions: false,
+ enablePrintAutoRotate: true,
+ enableScripting: true,
+ enableStampEditor: true,
+ externalLinkTarget: 0,
+ highlightEditorColors: "yellow=#FFFF98,green=#53FFBC,blue=#80EBFF,pink=#FFCBE6,red=#FF4F5F",
+ historyUpdateUrl: false,
+ ignoreDestinationZoom: false,
+ forcePageColors: false,
+ pageColorsBackground: "Canvas",
+ pageColorsForeground: "CanvasText",
+ pdfBugEnabled: false,
+ sidebarViewOnLoad: -1,
+ scrollModeOnLoad: -1,
+ spreadModeOnLoad: -1,
+ textLayerMode: 1,
+ viewOnLoad: 0,
+ disableAutoFetch: false,
+ disableFontFace: false,
+ disableRange: false,
+ disableStream: false,
+ enableXfa: true
+ });
+ #prefs = Object.create(null);
+ #initializedPromise = null;
+ constructor() {
+ if (this.constructor === BasePreferences) {
+ throw new Error("Cannot initialize BasePreferences.");
+ }
+ this.#initializedPromise = this._readFromStorage(this.#defaults).then(({
+ browserPrefs,
+ prefs
+ }) => {
+ const BROWSER_PREFS = {
+ canvasMaxAreaInBytes: -1,
+ isInAutomation: false,
+ supportsCaretBrowsingMode: false,
+ supportsDocumentFonts: true,
+ supportsIntegratedFind: false,
+ supportsMouseWheelZoomCtrlKey: true,
+ supportsMouseWheelZoomMetaKey: true,
+ supportsPinchToZoom: true
+ };
+ const options = Object.create(null);
+ for (const [name, defaultVal] of Object.entries(BROWSER_PREFS)) {
+ const prefVal = browserPrefs?.[name];
+ options[name] = typeof prefVal === typeof defaultVal ? prefVal : defaultVal;
+ }
+ for (const [name, defaultVal] of Object.entries(this.#defaults)) {
+ const prefVal = prefs?.[name];
+ options[name] = this.#prefs[name] = typeof prefVal === typeof defaultVal ? prefVal : defaultVal;
+ }
+ AppOptions.setAll(options, true);
+ });
+ }
+ async _writeToStorage(prefObj) {
+ throw new Error("Not implemented: _writeToStorage");
+ }
+ async _readFromStorage(prefObj) {
+ throw new Error("Not implemented: _readFromStorage");
+ }
+ async reset() {
+ throw new Error("Please use `about:config` to change preferences.");
+ }
+ async set(name, value) {
+ throw new Error("Please use `about:config` to change preferences.");
+ }
+ async get(name) {
+ await this.#initializedPromise;
+ const defaultValue = this.#defaults[name];
+ if (defaultValue === undefined) {
+ throw new Error(`Get preference: "${name}" is undefined.`);
+ }
+ return this.#prefs[name] ?? defaultValue;
+ }
+ get initializedPromise() {
+ return this.#initializedPromise;
+ }
+}
+
+;// CONCATENATED MODULE: ./web/l10n.js
+class L10n {
+ #dir;
+ #lang;
+ #l10n;
+ constructor({
+ lang,
+ isRTL
+ }, l10n = null) {
+ this.#lang = L10n.#fixupLangCode(lang);
+ this.#l10n = l10n;
+ this.#dir = isRTL ?? L10n.#isRTL(this.#lang) ? "rtl" : "ltr";
+ }
+ _setL10n(l10n) {
+ this.#l10n = l10n;
+ }
+ getLanguage() {
+ return this.#lang;
+ }
+ getDirection() {
+ return this.#dir;
+ }
+ async get(ids, args = null, fallback) {
+ if (Array.isArray(ids)) {
+ ids = ids.map(id => ({
+ id
+ }));
+ const messages = await this.#l10n.formatMessages(ids);
+ return messages.map(message => message.value);
+ }
+ const messages = await this.#l10n.formatMessages([{
+ id: ids,
+ args
+ }]);
+ return messages?.[0].value || fallback;
+ }
+ async translate(element) {
+ try {
+ this.#l10n.connectRoot(element);
+ await this.#l10n.translateRoots();
+ } catch {}
+ }
+ pause() {
+ this.#l10n.pauseObserving();
+ }
+ resume() {
+ this.#l10n.resumeObserving();
+ }
+ static #fixupLangCode(langCode) {
+ langCode = langCode?.toLowerCase() || "en-us";
+ const PARTIAL_LANG_CODES = {
+ en: "en-us",
+ es: "es-es",
+ fy: "fy-nl",
+ ga: "ga-ie",
+ gu: "gu-in",
+ hi: "hi-in",
+ hy: "hy-am",
+ nb: "nb-no",
+ ne: "ne-np",
+ nn: "nn-no",
+ pa: "pa-in",
+ pt: "pt-pt",
+ sv: "sv-se",
+ zh: "zh-cn"
+ };
+ return PARTIAL_LANG_CODES[langCode] || langCode;
+ }
+ static #isRTL(lang) {
+ const shortCode = lang.split("-", 1)[0];
+ return ["ar", "he", "fa", "ps", "ur"].includes(shortCode);
+ }
+}
+const GenericL10n = null;
+
+;// CONCATENATED MODULE: ./web/firefoxcom.js
+
+
+
+
+
+let viewerApp = {
+ initialized: false
+};
+function initCom(app) {
+ viewerApp = app;
+}
+class FirefoxCom {
+ static requestAsync(action, data) {
+ return new Promise(resolve => {
+ this.request(action, data, resolve);
+ });
+ }
+ static request(action, data, callback = null) {
+ const request = document.createTextNode("");
+ if (callback) {
+ request.addEventListener("pdf.js.response", event => {
+ const response = event.detail.response;
+ event.target.remove();
+ callback(response);
+ }, {
+ once: true
+ });
+ }
+ document.documentElement.append(request);
+ const sender = new CustomEvent("pdf.js.message", {
+ bubbles: true,
+ cancelable: false,
+ detail: {
+ action,
+ data,
+ responseExpected: !!callback
+ }
+ });
+ request.dispatchEvent(sender);
+ }
+}
+class DownloadManager {
+ #openBlobUrls = new WeakMap();
+ downloadUrl(url, filename, options = {}) {
+ FirefoxCom.request("download", {
+ originalUrl: url,
+ filename,
+ options
+ });
+ }
+ downloadData(data, filename, contentType) {
+ const blobUrl = URL.createObjectURL(new Blob([data], {
+ type: contentType
+ }));
+ FirefoxCom.request("download", {
+ blobUrl,
+ originalUrl: blobUrl,
+ filename,
+ isAttachment: true
+ });
+ }
+ openOrDownloadData(data, filename, dest = null) {
+ const isPdfData = isPdfFile(filename);
+ const contentType = isPdfData ? "application/pdf" : "";
+ if (isPdfData) {
+ let blobUrl = this.#openBlobUrls.get(data);
+ if (!blobUrl) {
+ blobUrl = URL.createObjectURL(new Blob([data], {
+ type: contentType
+ }));
+ this.#openBlobUrls.set(data, blobUrl);
+ }
+ let viewerUrl = blobUrl + "#filename=" + encodeURIComponent(filename);
+ if (dest) {
+ viewerUrl += `&filedest=${escape(dest)}`;
+ }
+ try {
+ window.open(viewerUrl);
+ return true;
+ } catch (ex) {
+ console.error(`openOrDownloadData: ${ex}`);
+ URL.revokeObjectURL(blobUrl);
+ this.#openBlobUrls.delete(data);
+ }
+ }
+ this.downloadData(data, filename, contentType);
+ return false;
+ }
+ download(blob, url, filename, options = {}) {
+ const blobUrl = URL.createObjectURL(blob);
+ FirefoxCom.request("download", {
+ blobUrl,
+ originalUrl: url,
+ filename,
+ options
+ });
+ }
+}
+class Preferences extends BasePreferences {
+ async _readFromStorage(prefObj) {
+ return FirefoxCom.requestAsync("getPreferences", prefObj);
+ }
+}
+(function listenFindEvents() {
+ const events = ["find", "findagain", "findhighlightallchange", "findcasesensitivitychange", "findentirewordchange", "findbarclose", "finddiacriticmatchingchange"];
+ const findLen = "find".length;
+ const handleEvent = function ({
+ type,
+ detail
+ }) {
+ if (!viewerApp.initialized) {
+ return;
+ }
+ if (type === "findbarclose") {
+ viewerApp.eventBus.dispatch(type, {
+ source: window
+ });
+ return;
+ }
+ viewerApp.eventBus.dispatch("find", {
+ source: window,
+ type: type.substring(findLen),
+ query: detail.query,
+ caseSensitive: !!detail.caseSensitive,
+ entireWord: !!detail.entireWord,
+ highlightAll: !!detail.highlightAll,
+ findPrevious: !!detail.findPrevious,
+ matchDiacritics: !!detail.matchDiacritics
+ });
+ };
+ for (const event of events) {
+ window.addEventListener(event, handleEvent);
+ }
+})();
+(function listenZoomEvents() {
+ const events = ["zoomin", "zoomout", "zoomreset"];
+ const handleEvent = function ({
+ type,
+ detail
+ }) {
+ if (!viewerApp.initialized) {
+ return;
+ }
+ if (type === "zoomreset" && viewerApp.pdfViewer.currentScaleValue === DEFAULT_SCALE_VALUE) {
+ return;
+ }
+ viewerApp.eventBus.dispatch(type, {
+ source: window
+ });
+ };
+ for (const event of events) {
+ window.addEventListener(event, handleEvent);
+ }
+})();
+(function listenSaveEvent() {
+ const handleEvent = function ({
+ type,
+ detail
+ }) {
+ if (!viewerApp.initialized) {
+ return;
+ }
+ viewerApp.eventBus.dispatch("download", {
+ source: window
+ });
+ };
+ window.addEventListener("save", handleEvent);
+})();
+(function listenEditingEvent() {
+ const handleEvent = function ({
+ detail
+ }) {
+ if (!viewerApp.initialized) {
+ return;
+ }
+ viewerApp.eventBus.dispatch("editingaction", {
+ source: window,
+ name: detail.name
+ });
+ };
+ window.addEventListener("editingaction", handleEvent);
+})();
+class FirefoxComDataRangeTransport extends PDFDataRangeTransport {
+ requestDataRange(begin, end) {
+ FirefoxCom.request("requestDataRange", {
+ begin,
+ end
+ });
+ }
+ abort() {
+ FirefoxCom.request("abortLoading", null);
+ }
+}
+class FirefoxScripting {
+ static async createSandbox(data) {
+ const success = await FirefoxCom.requestAsync("createSandbox", data);
+ if (!success) {
+ throw new Error("Cannot create sandbox.");
+ }
+ }
+ static async dispatchEventInSandbox(event) {
+ FirefoxCom.request("dispatchEventInSandbox", event);
+ }
+ static async destroySandbox() {
+ FirefoxCom.request("destroySandbox", null);
+ }
+}
+class MLManager {
+ guess(data) {
+ return FirefoxCom.requestAsync("mlGuess", data);
+ }
+}
+class ExternalServices extends BaseExternalServices {
+ updateFindControlState(data) {
+ FirefoxCom.request("updateFindControlState", data);
+ }
+ updateFindMatchesCount(data) {
+ FirefoxCom.request("updateFindMatchesCount", data);
+ }
+ initPassiveLoading(callbacks) {
+ let pdfDataRangeTransport;
+ window.addEventListener("message", function windowMessage(e) {
+ if (e.source !== null) {
+ console.warn("Rejected untrusted message from " + e.origin);
+ return;
+ }
+ const args = e.data;
+ if (typeof args !== "object" || !("pdfjsLoadAction" in args)) {
+ return;
+ }
+ switch (args.pdfjsLoadAction) {
+ case "supportsRangedLoading":
+ if (args.done && !args.data) {
+ callbacks.onError();
+ break;
+ }
+ pdfDataRangeTransport = new FirefoxComDataRangeTransport(args.length, args.data, args.done, args.filename);
+ callbacks.onOpenWithTransport(pdfDataRangeTransport);
+ break;
+ case "range":
+ pdfDataRangeTransport.onDataRange(args.begin, args.chunk);
+ break;
+ case "rangeProgress":
+ pdfDataRangeTransport.onDataProgress(args.loaded);
+ break;
+ case "progressiveRead":
+ pdfDataRangeTransport.onDataProgressiveRead(args.chunk);
+ pdfDataRangeTransport.onDataProgress(args.loaded, args.total);
+ break;
+ case "progressiveDone":
+ pdfDataRangeTransport?.onDataProgressiveDone();
+ break;
+ case "progress":
+ callbacks.onProgress(args.loaded, args.total);
+ break;
+ case "complete":
+ if (!args.data) {
+ callbacks.onError(args.errorCode);
+ break;
+ }
+ callbacks.onOpenWithData(args.data, args.filename);
+ break;
+ }
+ });
+ FirefoxCom.request("initPassiveLoading", null);
+ }
+ reportTelemetry(data) {
+ FirefoxCom.request("reportTelemetry", JSON.stringify(data));
+ }
+ updateEditorStates(data) {
+ FirefoxCom.request("updateEditorStates", data);
+ }
+ async createL10n() {
+ const [localeProperties] = await Promise.all([FirefoxCom.requestAsync("getLocaleProperties", null), document.l10n.ready]);
+ return new L10n(localeProperties, document.l10n);
+ }
+ createScripting() {
+ return FirefoxScripting;
+ }
+ async getNimbusExperimentData() {
+ return null;
+ }
+}
+
+;// CONCATENATED MODULE: ./web/alt_text_manager.js
+
+class AltTextManager {
+ #boundUpdateUIState = this.#updateUIState.bind(this);
+ #boundSetPosition = this.#setPosition.bind(this);
+ #boundOnClick = this.#onClick.bind(this);
+ #currentEditor = null;
+ #cancelButton;
+ #dialog;
+ #eventBus;
+ #hasUsedPointer = false;
+ #optionDescription;
+ #optionDecorative;
+ #overlayManager;
+ #saveButton;
+ #textarea;
+ #uiManager;
+ #previousAltText = null;
+ #svgElement = null;
+ #rectElement = null;
+ #container;
+ #telemetryData = null;
+ constructor({
+ dialog,
+ optionDescription,
+ optionDecorative,
+ textarea,
+ cancelButton,
+ saveButton
+ }, container, overlayManager, eventBus) {
+ this.#dialog = dialog;
+ this.#optionDescription = optionDescription;
+ this.#optionDecorative = optionDecorative;
+ this.#textarea = textarea;
+ this.#cancelButton = cancelButton;
+ this.#saveButton = saveButton;
+ this.#overlayManager = overlayManager;
+ this.#eventBus = eventBus;
+ this.#container = container;
+ dialog.addEventListener("close", this.#close.bind(this));
+ dialog.addEventListener("contextmenu", event => {
+ if (event.target !== this.#textarea) {
+ event.preventDefault();
+ }
+ });
+ cancelButton.addEventListener("click", this.#finish.bind(this));
+ saveButton.addEventListener("click", this.#save.bind(this));
+ optionDescription.addEventListener("change", this.#boundUpdateUIState);
+ optionDecorative.addEventListener("change", this.#boundUpdateUIState);
+ this.#overlayManager.register(dialog);
+ }
+ get _elements() {
+ return shadow(this, "_elements", [this.#optionDescription, this.#optionDecorative, this.#textarea, this.#saveButton, this.#cancelButton]);
+ }
+ #createSVGElement() {
+ if (this.#svgElement) {
+ return;
+ }
+ const svgFactory = new DOMSVGFactory();
+ const svg = this.#svgElement = svgFactory.createElement("svg");
+ svg.setAttribute("width", "0");
+ svg.setAttribute("height", "0");
+ const defs = svgFactory.createElement("defs");
+ svg.append(defs);
+ const mask = svgFactory.createElement("mask");
+ defs.append(mask);
+ mask.setAttribute("id", "alttext-manager-mask");
+ mask.setAttribute("maskContentUnits", "objectBoundingBox");
+ let rect = svgFactory.createElement("rect");
+ mask.append(rect);
+ rect.setAttribute("fill", "white");
+ rect.setAttribute("width", "1");
+ rect.setAttribute("height", "1");
+ rect.setAttribute("x", "0");
+ rect.setAttribute("y", "0");
+ rect = this.#rectElement = svgFactory.createElement("rect");
+ mask.append(rect);
+ rect.setAttribute("fill", "black");
+ this.#dialog.append(svg);
+ }
+ async editAltText(uiManager, editor) {
+ if (this.#currentEditor || !editor) {
+ return;
+ }
+ this.#createSVGElement();
+ this.#hasUsedPointer = false;
+ for (const element of this._elements) {
+ element.addEventListener("click", this.#boundOnClick);
+ }
+ const {
+ altText,
+ decorative
+ } = editor.altTextData;
+ if (decorative === true) {
+ this.#optionDecorative.checked = true;
+ this.#optionDescription.checked = false;
+ } else {
+ this.#optionDecorative.checked = false;
+ this.#optionDescription.checked = true;
+ }
+ this.#previousAltText = this.#textarea.value = altText?.trim() || "";
+ this.#updateUIState();
+ this.#currentEditor = editor;
+ this.#uiManager = uiManager;
+ this.#uiManager.removeEditListeners();
+ this.#eventBus._on("resize", this.#boundSetPosition);
+ try {
+ await this.#overlayManager.open(this.#dialog);
+ this.#setPosition();
+ } catch (ex) {
+ this.#close();
+ throw ex;
+ }
+ }
+ #setPosition() {
+ if (!this.#currentEditor) {
+ return;
+ }
+ const dialog = this.#dialog;
+ const {
+ style
+ } = dialog;
+ const {
+ x: containerX,
+ y: containerY,
+ width: containerW,
+ height: containerH
+ } = this.#container.getBoundingClientRect();
+ const {
+ innerWidth: windowW,
+ innerHeight: windowH
+ } = window;
+ const {
+ width: dialogW,
+ height: dialogH
+ } = dialog.getBoundingClientRect();
+ const {
+ x,
+ y,
+ width,
+ height
+ } = this.#currentEditor.getClientDimensions();
+ const MARGIN = 10;
+ const isLTR = this.#uiManager.direction === "ltr";
+ const xs = Math.max(x, containerX);
+ const xe = Math.min(x + width, containerX + containerW);
+ const ys = Math.max(y, containerY);
+ const ye = Math.min(y + height, containerY + containerH);
+ this.#rectElement.setAttribute("width", `${(xe - xs) / windowW}`);
+ this.#rectElement.setAttribute("height", `${(ye - ys) / windowH}`);
+ this.#rectElement.setAttribute("x", `${xs / windowW}`);
+ this.#rectElement.setAttribute("y", `${ys / windowH}`);
+ let left = null;
+ let top = Math.max(y, 0);
+ top += Math.min(windowH - (top + dialogH), 0);
+ if (isLTR) {
+ if (x + width + MARGIN + dialogW < windowW) {
+ left = x + width + MARGIN;
+ } else if (x > dialogW + MARGIN) {
+ left = x - dialogW - MARGIN;
+ }
+ } else if (x > dialogW + MARGIN) {
+ left = x - dialogW - MARGIN;
+ } else if (x + width + MARGIN + dialogW < windowW) {
+ left = x + width + MARGIN;
+ }
+ if (left === null) {
+ top = null;
+ left = Math.max(x, 0);
+ left += Math.min(windowW - (left + dialogW), 0);
+ if (y > dialogH + MARGIN) {
+ top = y - dialogH - MARGIN;
+ } else if (y + height + MARGIN + dialogH < windowH) {
+ top = y + height + MARGIN;
+ }
+ }
+ if (top !== null) {
+ dialog.classList.add("positioned");
+ if (isLTR) {
+ style.left = `${left}px`;
+ } else {
+ style.right = `${windowW - left - dialogW}px`;
+ }
+ style.top = `${top}px`;
+ } else {
+ dialog.classList.remove("positioned");
+ style.left = "";
+ style.top = "";
+ }
+ }
+ #finish() {
+ if (this.#overlayManager.active === this.#dialog) {
+ this.#overlayManager.close(this.#dialog);
+ }
+ }
+ #close() {
+ this.#currentEditor._reportTelemetry(this.#telemetryData || {
+ action: "alt_text_cancel",
+ alt_text_keyboard: !this.#hasUsedPointer
+ });
+ this.#telemetryData = null;
+ this.#removeOnClickListeners();
+ this.#uiManager?.addEditListeners();
+ this.#eventBus._off("resize", this.#boundSetPosition);
+ this.#currentEditor.altTextFinish();
+ this.#currentEditor = null;
+ this.#uiManager = null;
+ }
+ #updateUIState() {
+ this.#textarea.disabled = this.#optionDecorative.checked;
+ }
+ #save() {
+ const altText = this.#textarea.value.trim();
+ const decorative = this.#optionDecorative.checked;
+ this.#currentEditor.altTextData = {
+ altText,
+ decorative
+ };
+ this.#telemetryData = {
+ action: "alt_text_save",
+ alt_text_description: !!altText,
+ alt_text_edit: !!this.#previousAltText && this.#previousAltText !== altText,
+ alt_text_decorative: decorative,
+ alt_text_keyboard: !this.#hasUsedPointer
+ };
+ this.#finish();
+ }
+ #onClick(evt) {
+ if (evt.detail === 0) {
+ return;
+ }
+ this.#hasUsedPointer = true;
+ this.#removeOnClickListeners();
+ }
+ #removeOnClickListeners() {
+ for (const element of this._elements) {
+ element.removeEventListener("click", this.#boundOnClick);
+ }
+ }
+ destroy() {
+ this.#uiManager = null;
+ this.#finish();
+ this.#svgElement?.remove();
+ this.#svgElement = this.#rectElement = null;
+ }
+}
+
+;// CONCATENATED MODULE: ./web/annotation_editor_params.js
+
+class AnnotationEditorParams {
+ constructor(options, eventBus) {
+ this.eventBus = eventBus;
+ this.#bindListeners(options);
+ }
+ #bindListeners({
+ editorFreeTextFontSize,
+ editorFreeTextColor,
+ editorInkColor,
+ editorInkThickness,
+ editorInkOpacity,
+ editorStampAddImage,
+ editorFreeHighlightThickness
+ }) {
+ const dispatchEvent = (typeStr, value) => {
+ this.eventBus.dispatch("switchannotationeditorparams", {
+ source: this,
+ type: AnnotationEditorParamsType[typeStr],
+ value
+ });
+ };
+ editorFreeTextFontSize.addEventListener("input", function () {
+ dispatchEvent("FREETEXT_SIZE", this.valueAsNumber);
+ });
+ editorFreeTextColor.addEventListener("input", function () {
+ dispatchEvent("FREETEXT_COLOR", this.value);
+ });
+ editorInkColor.addEventListener("input", function () {
+ dispatchEvent("INK_COLOR", this.value);
+ });
+ editorInkThickness.addEventListener("input", function () {
+ dispatchEvent("INK_THICKNESS", this.valueAsNumber);
+ });
+ editorInkOpacity.addEventListener("input", function () {
+ dispatchEvent("INK_OPACITY", this.valueAsNumber);
+ });
+ editorStampAddImage.addEventListener("click", () => {
+ dispatchEvent("CREATE");
+ });
+ editorFreeHighlightThickness.addEventListener("input", function () {
+ dispatchEvent("HIGHLIGHT_THICKNESS", this.valueAsNumber);
+ });
+ this.eventBus._on("annotationeditorparamschanged", evt => {
+ for (const [type, value] of evt.details) {
+ switch (type) {
+ case AnnotationEditorParamsType.FREETEXT_SIZE:
+ editorFreeTextFontSize.value = value;
+ break;
+ case AnnotationEditorParamsType.FREETEXT_COLOR:
+ editorFreeTextColor.value = value;
+ break;
+ case AnnotationEditorParamsType.INK_COLOR:
+ editorInkColor.value = value;
+ break;
+ case AnnotationEditorParamsType.INK_THICKNESS:
+ editorInkThickness.value = value;
+ break;
+ case AnnotationEditorParamsType.INK_OPACITY:
+ editorInkOpacity.value = value;
+ break;
+ case AnnotationEditorParamsType.HIGHLIGHT_THICKNESS:
+ editorFreeHighlightThickness.value = value;
+ break;
+ case AnnotationEditorParamsType.HIGHLIGHT_FREE:
+ editorFreeHighlightThickness.disabled = !value;
+ break;
+ }
+ }
+ });
+ }
+}
+
+;// CONCATENATED MODULE: ./web/caret_browsing.js
+const PRECISION = 1e-1;
+class CaretBrowsingMode {
+ #mainContainer;
+ #toolBarHeight;
+ #viewerContainer;
+ constructor(mainContainer, viewerContainer, toolbarContainer) {
+ this.#mainContainer = mainContainer;
+ this.#viewerContainer = viewerContainer;
+ this.#toolBarHeight = toolbarContainer?.getBoundingClientRect().height ?? 0;
+ }
+ #isOnSameLine(rect1, rect2) {
+ const top1 = rect1.y;
+ const bot1 = rect1.bottom;
+ const mid1 = rect1.y + rect1.height / 2;
+ const top2 = rect2.y;
+ const bot2 = rect2.bottom;
+ const mid2 = rect2.y + rect2.height / 2;
+ return top1 <= mid2 && mid2 <= bot1 || top2 <= mid1 && mid1 <= bot2;
+ }
+ #isUnderOver(rect, x, y, isUp) {
+ const midY = rect.y + rect.height / 2;
+ return (isUp ? y >= midY : y <= midY) && rect.x - PRECISION <= x && x <= rect.right + PRECISION;
+ }
+ #isVisible(rect) {
+ return rect.top >= this.#toolBarHeight && rect.left >= 0 && rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) && rect.right <= (window.innerWidth || document.documentElement.clientWidth);
+ }
+ #getCaretPosition(selection, isUp) {
+ const {
+ focusNode,
+ focusOffset
+ } = selection;
+ const range = document.createRange();
+ range.setStart(focusNode, focusOffset);
+ range.setEnd(focusNode, focusOffset);
+ const rect = range.getBoundingClientRect();
+ return [rect.x, isUp ? rect.top : rect.bottom];
+ }
+ static #caretPositionFromPoint(x, y) {
+ return document.caretPositionFromPoint(x, y);
+ }
+ #setCaretPositionHelper(selection, caretX, select, element, rect) {
+ rect ||= element.getBoundingClientRect();
+ if (caretX <= rect.x + PRECISION) {
+ if (select) {
+ selection.extend(element.firstChild, 0);
+ } else {
+ selection.setPosition(element.firstChild, 0);
+ }
+ return;
+ }
+ if (rect.right - PRECISION <= caretX) {
+ const {
+ lastChild
+ } = element;
+ if (select) {
+ selection.extend(lastChild, lastChild.length);
+ } else {
+ selection.setPosition(lastChild, lastChild.length);
+ }
+ return;
+ }
+ const midY = rect.y + rect.height / 2;
+ let caretPosition = CaretBrowsingMode.#caretPositionFromPoint(caretX, midY);
+ let parentElement = caretPosition.offsetNode?.parentElement;
+ if (parentElement && parentElement !== element) {
+ const elementsAtPoint = document.elementsFromPoint(caretX, midY);
+ const savedVisibilities = [];
+ for (const el of elementsAtPoint) {
+ if (el === element) {
+ break;
+ }
+ const {
+ style
+ } = el;
+ savedVisibilities.push([el, style.visibility]);
+ style.visibility = "hidden";
+ }
+ caretPosition = CaretBrowsingMode.#caretPositionFromPoint(caretX, midY);
+ parentElement = caretPosition.offsetNode?.parentElement;
+ for (const [el, visibility] of savedVisibilities) {
+ el.style.visibility = visibility;
+ }
+ }
+ if (parentElement !== element) {
+ if (select) {
+ selection.extend(element.firstChild, 0);
+ } else {
+ selection.setPosition(element.firstChild, 0);
+ }
+ return;
+ }
+ if (select) {
+ selection.extend(caretPosition.offsetNode, caretPosition.offset);
+ } else {
+ selection.setPosition(caretPosition.offsetNode, caretPosition.offset);
+ }
+ }
+ #setCaretPosition(select, selection, newLineElement, newLineElementRect, caretX) {
+ if (this.#isVisible(newLineElementRect)) {
+ this.#setCaretPositionHelper(selection, caretX, select, newLineElement, newLineElementRect);
+ return;
+ }
+ this.#mainContainer.addEventListener("scrollend", this.#setCaretPositionHelper.bind(this, selection, caretX, select, newLineElement, null), {
+ once: true
+ });
+ newLineElement.scrollIntoView();
+ }
+ #getNodeOnNextPage(textLayer, isUp) {
+ while (true) {
+ const page = textLayer.closest(".page");
+ const pageNumber = parseInt(page.getAttribute("data-page-number"));
+ const nextPage = isUp ? pageNumber - 1 : pageNumber + 1;
+ textLayer = this.#viewerContainer.querySelector(`.page[data-page-number="${nextPage}"] .textLayer`);
+ if (!textLayer) {
+ return null;
+ }
+ const walker = document.createTreeWalker(textLayer, NodeFilter.SHOW_TEXT);
+ const node = isUp ? walker.lastChild() : walker.firstChild();
+ if (node) {
+ return node;
+ }
+ }
+ }
+ moveCaret(isUp, select) {
+ const selection = document.getSelection();
+ if (selection.rangeCount === 0) {
+ return;
+ }
+ const {
+ focusNode
+ } = selection;
+ const focusElement = focusNode.nodeType !== Node.ELEMENT_NODE ? focusNode.parentElement : focusNode;
+ const root = focusElement.closest(".textLayer");
+ if (!root) {
+ return;
+ }
+ const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT);
+ walker.currentNode = focusNode;
+ const focusRect = focusElement.getBoundingClientRect();
+ let newLineElement = null;
+ const nodeIterator = (isUp ? walker.previousSibling : walker.nextSibling).bind(walker);
+ while (nodeIterator()) {
+ const element = walker.currentNode.parentElement;
+ if (!this.#isOnSameLine(focusRect, element.getBoundingClientRect())) {
+ newLineElement = element;
+ break;
+ }
+ }
+ if (!newLineElement) {
+ const node = this.#getNodeOnNextPage(root, isUp);
+ if (!node) {
+ return;
+ }
+ if (select) {
+ const lastNode = (isUp ? walker.firstChild() : walker.lastChild()) || focusNode;
+ selection.extend(lastNode, isUp ? 0 : lastNode.length);
+ const range = document.createRange();
+ range.setStart(node, isUp ? node.length : 0);
+ range.setEnd(node, isUp ? node.length : 0);
+ selection.addRange(range);
+ return;
+ }
+ const [caretX] = this.#getCaretPosition(selection, isUp);
+ const {
+ parentElement
+ } = node;
+ this.#setCaretPosition(select, selection, parentElement, parentElement.getBoundingClientRect(), caretX);
+ return;
+ }
+ const [caretX, caretY] = this.#getCaretPosition(selection, isUp);
+ const newLineElementRect = newLineElement.getBoundingClientRect();
+ if (this.#isUnderOver(newLineElementRect, caretX, caretY, isUp)) {
+ this.#setCaretPosition(select, selection, newLineElement, newLineElementRect, caretX);
+ return;
+ }
+ while (nodeIterator()) {
+ const element = walker.currentNode.parentElement;
+ const elementRect = element.getBoundingClientRect();
+ if (!this.#isOnSameLine(newLineElementRect, elementRect)) {
+ break;
+ }
+ if (this.#isUnderOver(elementRect, caretX, caretY, isUp)) {
+ this.#setCaretPosition(select, selection, element, elementRect, caretX);
+ return;
+ }
+ }
+ this.#setCaretPosition(select, selection, newLineElement, newLineElementRect, caretX);
+ }
+}
+
+;// CONCATENATED MODULE: ./web/overlay_manager.js
+class OverlayManager {
+ #overlays = new WeakMap();
+ #active = null;
+ get active() {
+ return this.#active;
+ }
+ async register(dialog, canForceClose = false) {
+ if (typeof dialog !== "object") {
+ throw new Error("Not enough parameters.");
+ } else if (this.#overlays.has(dialog)) {
+ throw new Error("The overlay is already registered.");
+ }
+ this.#overlays.set(dialog, {
+ canForceClose
+ });
+ dialog.addEventListener("cancel", evt => {
+ this.#active = null;
+ });
+ }
+ async open(dialog) {
+ if (!this.#overlays.has(dialog)) {
+ throw new Error("The overlay does not exist.");
+ } else if (this.#active) {
+ if (this.#active === dialog) {
+ throw new Error("The overlay is already active.");
+ } else if (this.#overlays.get(dialog).canForceClose) {
+ await this.close();
+ } else {
+ throw new Error("Another overlay is currently active.");
+ }
+ }
+ this.#active = dialog;
+ dialog.showModal();
+ }
+ async close(dialog = this.#active) {
+ if (!this.#overlays.has(dialog)) {
+ throw new Error("The overlay does not exist.");
+ } else if (!this.#active) {
+ throw new Error("The overlay is currently not active.");
+ } else if (this.#active !== dialog) {
+ throw new Error("Another overlay is currently active.");
+ }
+ dialog.close();
+ this.#active = null;
+ }
+}
+
+;// CONCATENATED MODULE: ./web/password_prompt.js
+
+class PasswordPrompt {
+ #activeCapability = null;
+ #updateCallback = null;
+ #reason = null;
+ constructor(options, overlayManager, isViewerEmbedded = false) {
+ this.dialog = options.dialog;
+ this.label = options.label;
+ this.input = options.input;
+ this.submitButton = options.submitButton;
+ this.cancelButton = options.cancelButton;
+ this.overlayManager = overlayManager;
+ this._isViewerEmbedded = isViewerEmbedded;
+ this.submitButton.addEventListener("click", this.#verify.bind(this));
+ this.cancelButton.addEventListener("click", this.close.bind(this));
+ this.input.addEventListener("keydown", e => {
+ if (e.keyCode === 13) {
+ this.#verify();
+ }
+ });
+ this.overlayManager.register(this.dialog, true);
+ this.dialog.addEventListener("close", this.#cancel.bind(this));
+ }
+ async open() {
+ if (this.#activeCapability) {
+ await this.#activeCapability.promise;
+ }
+ this.#activeCapability = new PromiseCapability();
+ try {
+ await this.overlayManager.open(this.dialog);
+ } catch (ex) {
+ this.#activeCapability.resolve();
+ throw ex;
+ }
+ const passwordIncorrect = this.#reason === PasswordResponses.INCORRECT_PASSWORD;
+ if (!this._isViewerEmbedded || passwordIncorrect) {
+ this.input.focus();
+ }
+ this.label.setAttribute("data-l10n-id", `pdfjs-password-${passwordIncorrect ? "invalid" : "label"}`);
+ }
+ async close() {
+ if (this.overlayManager.active === this.dialog) {
+ this.overlayManager.close(this.dialog);
+ }
+ }
+ #verify() {
+ const password = this.input.value;
+ if (password?.length > 0) {
+ this.#invokeCallback(password);
+ }
+ }
+ #cancel() {
+ this.#invokeCallback(new Error("PasswordPrompt cancelled."));
+ this.#activeCapability.resolve();
+ }
+ #invokeCallback(password) {
+ if (!this.#updateCallback) {
+ return;
+ }
+ this.close();
+ this.input.value = "";
+ this.#updateCallback(password);
+ this.#updateCallback = null;
+ }
+ async setUpdateCallback(updateCallback, reason) {
+ if (this.#activeCapability) {
+ await this.#activeCapability.promise;
+ }
+ this.#updateCallback = updateCallback;
+ this.#reason = reason;
+ }
+}
+
+;// CONCATENATED MODULE: ./web/base_tree_viewer.js
+
+const TREEITEM_OFFSET_TOP = -100;
+const TREEITEM_SELECTED_CLASS = "selected";
+class BaseTreeViewer {
+ constructor(options) {
+ if (this.constructor === BaseTreeViewer) {
+ throw new Error("Cannot initialize BaseTreeViewer.");
+ }
+ this.container = options.container;
+ this.eventBus = options.eventBus;
+ this._l10n = options.l10n;
+ this.reset();
+ }
+ reset() {
+ this._pdfDocument = null;
+ this._lastToggleIsShow = true;
+ this._currentTreeItem = null;
+ this.container.textContent = "";
+ this.container.classList.remove("treeWithDeepNesting");
+ }
+ _dispatchEvent(count) {
+ throw new Error("Not implemented: _dispatchEvent");
+ }
+ _bindLink(element, params) {
+ throw new Error("Not implemented: _bindLink");
+ }
+ _normalizeTextContent(str) {
+ return removeNullCharacters(str, true) || "\u2013";
+ }
+ _addToggleButton(div, hidden = false) {
+ const toggler = document.createElement("div");
+ toggler.className = "treeItemToggler";
+ if (hidden) {
+ toggler.classList.add("treeItemsHidden");
+ }
+ toggler.onclick = evt => {
+ evt.stopPropagation();
+ toggler.classList.toggle("treeItemsHidden");
+ if (evt.shiftKey) {
+ const shouldShowAll = !toggler.classList.contains("treeItemsHidden");
+ this._toggleTreeItem(div, shouldShowAll);
+ }
+ };
+ div.prepend(toggler);
+ }
+ _toggleTreeItem(root, show = false) {
+ this._l10n.pause();
+ this._lastToggleIsShow = show;
+ for (const toggler of root.querySelectorAll(".treeItemToggler")) {
+ toggler.classList.toggle("treeItemsHidden", !show);
+ }
+ this._l10n.resume();
+ }
+ _toggleAllTreeItems() {
+ this._toggleTreeItem(this.container, !this._lastToggleIsShow);
+ }
+ _finishRendering(fragment, count, hasAnyNesting = false) {
+ if (hasAnyNesting) {
+ this.container.classList.add("treeWithDeepNesting");
+ this._lastToggleIsShow = !fragment.querySelector(".treeItemsHidden");
+ }
+ this._l10n.pause();
+ this.container.append(fragment);
+ this._l10n.resume();
+ this._dispatchEvent(count);
+ }
+ render(params) {
+ throw new Error("Not implemented: render");
+ }
+ _updateCurrentTreeItem(treeItem = null) {
+ if (this._currentTreeItem) {
+ this._currentTreeItem.classList.remove(TREEITEM_SELECTED_CLASS);
+ this._currentTreeItem = null;
+ }
+ if (treeItem) {
+ treeItem.classList.add(TREEITEM_SELECTED_CLASS);
+ this._currentTreeItem = treeItem;
+ }
+ }
+ _scrollToCurrentTreeItem(treeItem) {
+ if (!treeItem) {
+ return;
+ }
+ this._l10n.pause();
+ let currentNode = treeItem.parentNode;
+ while (currentNode && currentNode !== this.container) {
+ if (currentNode.classList.contains("treeItem")) {
+ const toggler = currentNode.firstElementChild;
+ toggler?.classList.remove("treeItemsHidden");
+ }
+ currentNode = currentNode.parentNode;
+ }
+ this._l10n.resume();
+ this._updateCurrentTreeItem(treeItem);
+ this.container.scrollTo(treeItem.offsetLeft, treeItem.offsetTop + TREEITEM_OFFSET_TOP);
+ }
+}
+
+;// CONCATENATED MODULE: ./web/pdf_attachment_viewer.js
+
+
+
+class PDFAttachmentViewer extends BaseTreeViewer {
+ constructor(options) {
+ super(options);
+ this.downloadManager = options.downloadManager;
+ this.eventBus._on("fileattachmentannotation", this.#appendAttachment.bind(this));
+ }
+ reset(keepRenderedCapability = false) {
+ super.reset();
+ this._attachments = null;
+ if (!keepRenderedCapability) {
+ this._renderedCapability = new PromiseCapability();
+ }
+ this._pendingDispatchEvent = false;
+ }
+ async _dispatchEvent(attachmentsCount) {
+ this._renderedCapability.resolve();
+ if (attachmentsCount === 0 && !this._pendingDispatchEvent) {
+ this._pendingDispatchEvent = true;
+ await waitOnEventOrTimeout({
+ target: this.eventBus,
+ name: "annotationlayerrendered",
+ delay: 1000
+ });
+ if (!this._pendingDispatchEvent) {
+ return;
+ }
+ }
+ this._pendingDispatchEvent = false;
+ this.eventBus.dispatch("attachmentsloaded", {
+ source: this,
+ attachmentsCount
+ });
+ }
+ _bindLink(element, {
+ content,
+ filename
+ }) {
+ element.onclick = () => {
+ this.downloadManager.openOrDownloadData(content, filename);
+ return false;
+ };
+ }
+ render({
+ attachments,
+ keepRenderedCapability = false
+ }) {
+ if (this._attachments) {
+ this.reset(keepRenderedCapability);
+ }
+ this._attachments = attachments || null;
+ if (!attachments) {
+ this._dispatchEvent(0);
+ return;
+ }
+ const fragment = document.createDocumentFragment();
+ let attachmentsCount = 0;
+ for (const name in attachments) {
+ const item = attachments[name];
+ const content = item.content,
+ filename = getFilenameFromUrl(item.filename, true);
+ const div = document.createElement("div");
+ div.className = "treeItem";
+ const element = document.createElement("a");
+ this._bindLink(element, {
+ content,
+ filename
+ });
+ element.textContent = this._normalizeTextContent(filename);
+ div.append(element);
+ fragment.append(div);
+ attachmentsCount++;
+ }
+ this._finishRendering(fragment, attachmentsCount);
+ }
+ #appendAttachment({
+ filename,
+ content
+ }) {
+ const renderedPromise = this._renderedCapability.promise;
+ renderedPromise.then(() => {
+ if (renderedPromise !== this._renderedCapability.promise) {
+ return;
+ }
+ const attachments = this._attachments || Object.create(null);
+ for (const name in attachments) {
+ if (filename === name) {
+ return;
+ }
+ }
+ attachments[filename] = {
+ filename,
+ content
+ };
+ this.render({
+ attachments,
+ keepRenderedCapability: true
+ });
+ });
+ }
+}
+
+;// CONCATENATED MODULE: ./web/grab_to_pan.js
+const CSS_CLASS_GRAB = "grab-to-pan-grab";
+class GrabToPan {
+ constructor({
+ element
+ }) {
+ this.element = element;
+ this.document = element.ownerDocument;
+ this.activate = this.activate.bind(this);
+ this.deactivate = this.deactivate.bind(this);
+ this.toggle = this.toggle.bind(this);
+ this._onMouseDown = this.#onMouseDown.bind(this);
+ this._onMouseMove = this.#onMouseMove.bind(this);
+ this._endPan = this.#endPan.bind(this);
+ const overlay = this.overlay = document.createElement("div");
+ overlay.className = "grab-to-pan-grabbing";
+ }
+ activate() {
+ if (!this.active) {
+ this.active = true;
+ this.element.addEventListener("mousedown", this._onMouseDown, true);
+ this.element.classList.add(CSS_CLASS_GRAB);
+ }
+ }
+ deactivate() {
+ if (this.active) {
+ this.active = false;
+ this.element.removeEventListener("mousedown", this._onMouseDown, true);
+ this._endPan();
+ this.element.classList.remove(CSS_CLASS_GRAB);
+ }
+ }
+ toggle() {
+ if (this.active) {
+ this.deactivate();
+ } else {
+ this.activate();
+ }
+ }
+ ignoreTarget(node) {
+ return node.matches("a[href], a[href] *, input, textarea, button, button *, select, option");
+ }
+ #onMouseDown(event) {
+ if (event.button !== 0 || this.ignoreTarget(event.target)) {
+ return;
+ }
+ if (event.originalTarget) {
+ try {
+ event.originalTarget.tagName;
+ } catch {
+ return;
+ }
+ }
+ this.scrollLeftStart = this.element.scrollLeft;
+ this.scrollTopStart = this.element.scrollTop;
+ this.clientXStart = event.clientX;
+ this.clientYStart = event.clientY;
+ this.document.addEventListener("mousemove", this._onMouseMove, true);
+ this.document.addEventListener("mouseup", this._endPan, true);
+ this.element.addEventListener("scroll", this._endPan, true);
+ event.preventDefault();
+ event.stopPropagation();
+ const focusedElement = document.activeElement;
+ if (focusedElement && !focusedElement.contains(event.target)) {
+ focusedElement.blur();
+ }
+ }
+ #onMouseMove(event) {
+ this.element.removeEventListener("scroll", this._endPan, true);
+ if (!(event.buttons & 1)) {
+ this._endPan();
+ return;
+ }
+ const xDiff = event.clientX - this.clientXStart;
+ const yDiff = event.clientY - this.clientYStart;
+ this.element.scrollTo({
+ top: this.scrollTopStart - yDiff,
+ left: this.scrollLeftStart - xDiff,
+ behavior: "instant"
+ });
+ if (!this.overlay.parentNode) {
+ document.body.append(this.overlay);
+ }
+ }
+ #endPan() {
+ this.element.removeEventListener("scroll", this._endPan, true);
+ this.document.removeEventListener("mousemove", this._onMouseMove, true);
+ this.document.removeEventListener("mouseup", this._endPan, true);
+ this.overlay.remove();
+ }
+}
+
+;// CONCATENATED MODULE: ./web/pdf_cursor_tools.js
+
+
+
+class PDFCursorTools {
+ #active = CursorTool.SELECT;
+ #prevActive = null;
+ constructor({
+ container,
+ eventBus,
+ cursorToolOnLoad = CursorTool.SELECT
+ }) {
+ this.container = container;
+ this.eventBus = eventBus;
+ this.#addEventListeners();
+ Promise.resolve().then(() => {
+ this.switchTool(cursorToolOnLoad);
+ });
+ }
+ get activeTool() {
+ return this.#active;
+ }
+ switchTool(tool) {
+ if (this.#prevActive !== null) {
+ return;
+ }
+ if (tool === this.#active) {
+ return;
+ }
+ const disableActiveTool = () => {
+ switch (this.#active) {
+ case CursorTool.SELECT:
+ break;
+ case CursorTool.HAND:
+ this._handTool.deactivate();
+ break;
+ case CursorTool.ZOOM:
+ }
+ };
+ switch (tool) {
+ case CursorTool.SELECT:
+ disableActiveTool();
+ break;
+ case CursorTool.HAND:
+ disableActiveTool();
+ this._handTool.activate();
+ break;
+ case CursorTool.ZOOM:
+ default:
+ console.error(`switchTool: "${tool}" is an unsupported value.`);
+ return;
+ }
+ this.#active = tool;
+ this.eventBus.dispatch("cursortoolchanged", {
+ source: this,
+ tool
+ });
+ }
+ #addEventListeners() {
+ this.eventBus._on("switchcursortool", evt => {
+ this.switchTool(evt.tool);
+ });
+ let annotationEditorMode = AnnotationEditorType.NONE,
+ presentationModeState = PresentationModeState.NORMAL;
+ const disableActive = () => {
+ const prevActive = this.#active;
+ this.switchTool(CursorTool.SELECT);
+ this.#prevActive ??= prevActive;
+ };
+ const enableActive = () => {
+ const prevActive = this.#prevActive;
+ if (prevActive !== null && annotationEditorMode === AnnotationEditorType.NONE && presentationModeState === PresentationModeState.NORMAL) {
+ this.#prevActive = null;
+ this.switchTool(prevActive);
+ }
+ };
+ this.eventBus._on("secondarytoolbarreset", evt => {
+ if (this.#prevActive !== null) {
+ annotationEditorMode = AnnotationEditorType.NONE;
+ presentationModeState = PresentationModeState.NORMAL;
+ enableActive();
+ }
+ });
+ this.eventBus._on("annotationeditormodechanged", ({
+ mode
+ }) => {
+ annotationEditorMode = mode;
+ if (mode === AnnotationEditorType.NONE) {
+ enableActive();
+ } else {
+ disableActive();
+ }
+ });
+ this.eventBus._on("presentationmodechanged", ({
+ state
+ }) => {
+ presentationModeState = state;
+ if (state === PresentationModeState.NORMAL) {
+ enableActive();
+ } else if (state === PresentationModeState.FULLSCREEN) {
+ disableActive();
+ }
+ });
+ }
+ get _handTool() {
+ return shadow(this, "_handTool", new GrabToPan({
+ element: this.container
+ }));
+ }
+}
+
+;// CONCATENATED MODULE: ./web/pdf_document_properties.js
+
+
+const DEFAULT_FIELD_CONTENT = "-";
+const NON_METRIC_LOCALES = ["en-us", "en-lr", "my"];
+const US_PAGE_NAMES = {
+ "8.5x11": "letter",
+ "8.5x14": "legal"
+};
+const METRIC_PAGE_NAMES = {
+ "297x420": "a-three",
+ "210x297": "a-four"
+};
+function getPageName(size, isPortrait, pageNames) {
+ const width = isPortrait ? size.width : size.height;
+ const height = isPortrait ? size.height : size.width;
+ return pageNames[`${width}x${height}`];
+}
+class PDFDocumentProperties {
+ #fieldData = null;
+ constructor({
+ dialog,
+ fields,
+ closeButton
+ }, overlayManager, eventBus, l10n, fileNameLookup) {
+ this.dialog = dialog;
+ this.fields = fields;
+ this.overlayManager = overlayManager;
+ this.l10n = l10n;
+ this._fileNameLookup = fileNameLookup;
+ this.#reset();
+ closeButton.addEventListener("click", this.close.bind(this));
+ this.overlayManager.register(this.dialog);
+ eventBus._on("pagechanging", evt => {
+ this._currentPageNumber = evt.pageNumber;
+ });
+ eventBus._on("rotationchanging", evt => {
+ this._pagesRotation = evt.pagesRotation;
+ });
+ this._isNonMetricLocale = NON_METRIC_LOCALES.includes(l10n.getLanguage());
+ }
+ async open() {
+ await Promise.all([this.overlayManager.open(this.dialog), this._dataAvailableCapability.promise]);
+ const currentPageNumber = this._currentPageNumber;
+ const pagesRotation = this._pagesRotation;
+ if (this.#fieldData && currentPageNumber === this.#fieldData._currentPageNumber && pagesRotation === this.#fieldData._pagesRotation) {
+ this.#updateUI();
+ return;
+ }
+ const {
+ info,
+ contentLength
+ } = await this.pdfDocument.getMetadata();
+ const [fileName, fileSize, creationDate, modificationDate, pageSize, isLinearized] = await Promise.all([this._fileNameLookup(), this.#parseFileSize(contentLength), this.#parseDate(info.CreationDate), this.#parseDate(info.ModDate), this.pdfDocument.getPage(currentPageNumber).then(pdfPage => {
+ return this.#parsePageSize(getPageSizeInches(pdfPage), pagesRotation);
+ }), this.#parseLinearization(info.IsLinearized)]);
+ this.#fieldData = Object.freeze({
+ fileName,
+ fileSize,
+ title: info.Title,
+ author: info.Author,
+ subject: info.Subject,
+ keywords: info.Keywords,
+ creationDate,
+ modificationDate,
+ creator: info.Creator,
+ producer: info.Producer,
+ version: info.PDFFormatVersion,
+ pageCount: this.pdfDocument.numPages,
+ pageSize,
+ linearized: isLinearized,
+ _currentPageNumber: currentPageNumber,
+ _pagesRotation: pagesRotation
+ });
+ this.#updateUI();
+ const {
+ length
+ } = await this.pdfDocument.getDownloadInfo();
+ if (contentLength === length) {
+ return;
+ }
+ const data = Object.assign(Object.create(null), this.#fieldData);
+ data.fileSize = await this.#parseFileSize(length);
+ this.#fieldData = Object.freeze(data);
+ this.#updateUI();
+ }
+ async close() {
+ this.overlayManager.close(this.dialog);
+ }
+ setDocument(pdfDocument) {
+ if (this.pdfDocument) {
+ this.#reset();
+ this.#updateUI(true);
+ }
+ if (!pdfDocument) {
+ return;
+ }
+ this.pdfDocument = pdfDocument;
+ this._dataAvailableCapability.resolve();
+ }
+ #reset() {
+ this.pdfDocument = null;
+ this.#fieldData = null;
+ this._dataAvailableCapability = new PromiseCapability();
+ this._currentPageNumber = 1;
+ this._pagesRotation = 0;
+ }
+ #updateUI(reset = false) {
+ if (reset || !this.#fieldData) {
+ for (const id in this.fields) {
+ this.fields[id].textContent = DEFAULT_FIELD_CONTENT;
+ }
+ return;
+ }
+ if (this.overlayManager.active !== this.dialog) {
+ return;
+ }
+ for (const id in this.fields) {
+ const content = this.#fieldData[id];
+ this.fields[id].textContent = content || content === 0 ? content : DEFAULT_FIELD_CONTENT;
+ }
+ }
+ async #parseFileSize(fileSize = 0) {
+ const kb = fileSize / 1024,
+ mb = kb / 1024;
+ if (!kb) {
+ return undefined;
+ }
+ return this.l10n.get(`pdfjs-document-properties-${mb >= 1 ? "mb" : "kb"}`, {
+ size_mb: mb >= 1 && (+mb.toPrecision(3)).toLocaleString(),
+ size_kb: mb < 1 && (+kb.toPrecision(3)).toLocaleString(),
+ size_b: fileSize.toLocaleString()
+ });
+ }
+ async #parsePageSize(pageSizeInches, pagesRotation) {
+ if (!pageSizeInches) {
+ return undefined;
+ }
+ if (pagesRotation % 180 !== 0) {
+ pageSizeInches = {
+ width: pageSizeInches.height,
+ height: pageSizeInches.width
+ };
+ }
+ const isPortrait = isPortraitOrientation(pageSizeInches);
+ let sizeInches = {
+ width: Math.round(pageSizeInches.width * 100) / 100,
+ height: Math.round(pageSizeInches.height * 100) / 100
+ };
+ let sizeMillimeters = {
+ width: Math.round(pageSizeInches.width * 25.4 * 10) / 10,
+ height: Math.round(pageSizeInches.height * 25.4 * 10) / 10
+ };
+ let rawName = getPageName(sizeInches, isPortrait, US_PAGE_NAMES) || getPageName(sizeMillimeters, isPortrait, METRIC_PAGE_NAMES);
+ if (!rawName && !(Number.isInteger(sizeMillimeters.width) && Number.isInteger(sizeMillimeters.height))) {
+ const exactMillimeters = {
+ width: pageSizeInches.width * 25.4,
+ height: pageSizeInches.height * 25.4
+ };
+ const intMillimeters = {
+ width: Math.round(sizeMillimeters.width),
+ height: Math.round(sizeMillimeters.height)
+ };
+ if (Math.abs(exactMillimeters.width - intMillimeters.width) < 0.1 && Math.abs(exactMillimeters.height - intMillimeters.height) < 0.1) {
+ rawName = getPageName(intMillimeters, isPortrait, METRIC_PAGE_NAMES);
+ if (rawName) {
+ sizeInches = {
+ width: Math.round(intMillimeters.width / 25.4 * 100) / 100,
+ height: Math.round(intMillimeters.height / 25.4 * 100) / 100
+ };
+ sizeMillimeters = intMillimeters;
+ }
+ }
+ }
+ const [{
+ width,
+ height
+ }, unit, name, orientation] = await Promise.all([this._isNonMetricLocale ? sizeInches : sizeMillimeters, this.l10n.get(`pdfjs-document-properties-page-size-unit-${this._isNonMetricLocale ? "inches" : "millimeters"}`), rawName && this.l10n.get(`pdfjs-document-properties-page-size-name-${rawName}`), this.l10n.get(`pdfjs-document-properties-page-size-orientation-${isPortrait ? "portrait" : "landscape"}`)]);
+ return this.l10n.get(`pdfjs-document-properties-page-size-dimension-${name ? "name-" : ""}string`, {
+ width: width.toLocaleString(),
+ height: height.toLocaleString(),
+ unit,
+ name,
+ orientation
+ });
+ }
+ async #parseDate(inputDate) {
+ const dateObject = PDFDateString.toDateObject(inputDate);
+ if (!dateObject) {
+ return undefined;
+ }
+ return this.l10n.get("pdfjs-document-properties-date-string", {
+ date: dateObject.toLocaleDateString(),
+ time: dateObject.toLocaleTimeString()
+ });
+ }
+ #parseLinearization(isLinearized) {
+ return this.l10n.get(`pdfjs-document-properties-linearized-${isLinearized ? "yes" : "no"}`);
+ }
+}
+
+;// CONCATENATED MODULE: ./web/pdf_find_utils.js
+const CharacterType = {
+ SPACE: 0,
+ ALPHA_LETTER: 1,
+ PUNCT: 2,
+ HAN_LETTER: 3,
+ KATAKANA_LETTER: 4,
+ HIRAGANA_LETTER: 5,
+ HALFWIDTH_KATAKANA_LETTER: 6,
+ THAI_LETTER: 7
+};
+function isAlphabeticalScript(charCode) {
+ return charCode < 0x2e80;
+}
+function isAscii(charCode) {
+ return (charCode & 0xff80) === 0;
+}
+function isAsciiAlpha(charCode) {
+ return charCode >= 0x61 && charCode <= 0x7a || charCode >= 0x41 && charCode <= 0x5a;
+}
+function isAsciiDigit(charCode) {
+ return charCode >= 0x30 && charCode <= 0x39;
+}
+function isAsciiSpace(charCode) {
+ return charCode === 0x20 || charCode === 0x09 || charCode === 0x0d || charCode === 0x0a;
+}
+function isHan(charCode) {
+ return charCode >= 0x3400 && charCode <= 0x9fff || charCode >= 0xf900 && charCode <= 0xfaff;
+}
+function isKatakana(charCode) {
+ return charCode >= 0x30a0 && charCode <= 0x30ff;
+}
+function isHiragana(charCode) {
+ return charCode >= 0x3040 && charCode <= 0x309f;
+}
+function isHalfwidthKatakana(charCode) {
+ return charCode >= 0xff60 && charCode <= 0xff9f;
+}
+function isThai(charCode) {
+ return (charCode & 0xff80) === 0x0e00;
+}
+function getCharacterType(charCode) {
+ if (isAlphabeticalScript(charCode)) {
+ if (isAscii(charCode)) {
+ if (isAsciiSpace(charCode)) {
+ return CharacterType.SPACE;
+ } else if (isAsciiAlpha(charCode) || isAsciiDigit(charCode) || charCode === 0x5f) {
+ return CharacterType.ALPHA_LETTER;
+ }
+ return CharacterType.PUNCT;
+ } else if (isThai(charCode)) {
+ return CharacterType.THAI_LETTER;
+ } else if (charCode === 0xa0) {
+ return CharacterType.SPACE;
+ }
+ return CharacterType.ALPHA_LETTER;
+ }
+ if (isHan(charCode)) {
+ return CharacterType.HAN_LETTER;
+ } else if (isKatakana(charCode)) {
+ return CharacterType.KATAKANA_LETTER;
+ } else if (isHiragana(charCode)) {
+ return CharacterType.HIRAGANA_LETTER;
+ } else if (isHalfwidthKatakana(charCode)) {
+ return CharacterType.HALFWIDTH_KATAKANA_LETTER;
+ }
+ return CharacterType.ALPHA_LETTER;
+}
+let NormalizeWithNFKC;
+function getNormalizeWithNFKC() {
+ NormalizeWithNFKC ||= ` ¨ª¯²-µ¸-º¼-¾IJ-ijĿ-ŀʼnſDŽ-njDZ-dzʰ-ʸ˘-ËË -ˤʹͺ;΄-΅·Ï-Ï–Ï°-ϲϴ-ϵϹևٵ-ٸक़-य़ড়-à§à§Ÿà¨³à¨¶à©™-ਜ਼ਫ਼ଡ଼-à­à¸³àº³à»œ-à»à¼Œà½ƒà½à½’བྷཛྷཀྵჼᴬ-ᴮᴰ-ᴺᴼ-áµáµ-ᵪᵸᶛ-ᶿẚ-ẛάέήίόύώΆ᾽-á¿á¿‰á¿‹á¿-á¿á¿“á¿›á¿-῟ΰΎ῭-`ΌΏ´-῾ - ‑‗․-… ″-‴‶-‷‼‾â‡-â‰â—âŸâ°-â±â´-â‚Žâ‚-ₜ₨℀-℃℅-ℇ℉-â„“â„•-â„–â„™-â„â„ -™ℤΩℨK-ℭℯ-ℱℳ-ℹ℻-⅀ⅅ-â…‰â…-ⅿ↉∬-∭∯-∰〈-〉①-⓪⨌⩴-⩶⫝̸ⱼ-ⱽⵯ⺟⻳⼀-⿕ 〶〸-〺゛-゜ゟヿㄱ-ㆎ㆒-㆟㈀-㈞㈠-㉇ã‰-㉾㊀-ã¿êšœ-êšê°êŸ²-ꟴꟸ-ꟹꭜ-ꭟꭩ豈-ï¨ï¨ï¨’凞-羽蘒諸逸-都飯-ï©­ï©°-龎ff-stﬓ-ﬗï¬ï¬Ÿ-זּטּ-לּמּנּ-ï­ï­ƒ-ï­„ï­†-ﮱﯓ-ï´½ïµ-ï¶ï¶’-ﷇﷰ-ï·¼ï¸-︙︰-﹄﹇-ï¹’ï¹”-﹦﹨-﹫ﹰ-ﹲﹴﹶ-ﻼï¼-하-ᅦᅧ-ï¿ï¿’-ï¿—ï¿š-ᅵ¢-₩`;
+ return NormalizeWithNFKC;
+}
+
+;// CONCATENATED MODULE: ./web/pdf_find_controller.js
+
+
+
+const FindState = {
+ FOUND: 0,
+ NOT_FOUND: 1,
+ WRAPPED: 2,
+ PENDING: 3
+};
+const FIND_TIMEOUT = 250;
+const MATCH_SCROLL_OFFSET_TOP = -50;
+const MATCH_SCROLL_OFFSET_LEFT = -400;
+const CHARACTERS_TO_NORMALIZE = {
+ "\u2010": "-",
+ "\u2018": "'",
+ "\u2019": "'",
+ "\u201A": "'",
+ "\u201B": "'",
+ "\u201C": '"',
+ "\u201D": '"',
+ "\u201E": '"',
+ "\u201F": '"',
+ "\u00BC": "1/4",
+ "\u00BD": "1/2",
+ "\u00BE": "3/4"
+};
+const DIACRITICS_EXCEPTION = new Set([0x3099, 0x309a, 0x094d, 0x09cd, 0x0a4d, 0x0acd, 0x0b4d, 0x0bcd, 0x0c4d, 0x0ccd, 0x0d3b, 0x0d3c, 0x0d4d, 0x0dca, 0x0e3a, 0x0eba, 0x0f84, 0x1039, 0x103a, 0x1714, 0x1734, 0x17d2, 0x1a60, 0x1b44, 0x1baa, 0x1bab, 0x1bf2, 0x1bf3, 0x2d7f, 0xa806, 0xa82c, 0xa8c4, 0xa953, 0xa9c0, 0xaaf6, 0xabed, 0x0c56, 0x0f71, 0x0f72, 0x0f7a, 0x0f7b, 0x0f7c, 0x0f7d, 0x0f80, 0x0f74]);
+let DIACRITICS_EXCEPTION_STR;
+const DIACRITICS_REG_EXP = /\p{M}+/gu;
+const SPECIAL_CHARS_REG_EXP = /([.*+?^${}()|[\]\\])|(\p{P})|(\s+)|(\p{M})|(\p{L})/gu;
+const NOT_DIACRITIC_FROM_END_REG_EXP = /([^\p{M}])\p{M}*$/u;
+const NOT_DIACRITIC_FROM_START_REG_EXP = /^\p{M}*([^\p{M}])/u;
+const SYLLABLES_REG_EXP = /[\uAC00-\uD7AF\uFA6C\uFACF-\uFAD1\uFAD5-\uFAD7]+/g;
+const SYLLABLES_LENGTHS = new Map();
+const FIRST_CHAR_SYLLABLES_REG_EXP = "[\\u1100-\\u1112\\ud7a4-\\ud7af\\ud84a\\ud84c\\ud850\\ud854\\ud857\\ud85f]";
+const NFKC_CHARS_TO_NORMALIZE = new Map();
+let noSyllablesRegExp = null;
+let withSyllablesRegExp = null;
+function normalize(text) {
+ const syllablePositions = [];
+ let m;
+ while ((m = SYLLABLES_REG_EXP.exec(text)) !== null) {
+ let {
+ index
+ } = m;
+ for (const char of m[0]) {
+ let len = SYLLABLES_LENGTHS.get(char);
+ if (!len) {
+ len = char.normalize("NFD").length;
+ SYLLABLES_LENGTHS.set(char, len);
+ }
+ syllablePositions.push([len, index++]);
+ }
+ }
+ let normalizationRegex;
+ if (syllablePositions.length === 0 && noSyllablesRegExp) {
+ normalizationRegex = noSyllablesRegExp;
+ } else if (syllablePositions.length > 0 && withSyllablesRegExp) {
+ normalizationRegex = withSyllablesRegExp;
+ } else {
+ const replace = Object.keys(CHARACTERS_TO_NORMALIZE).join("");
+ const toNormalizeWithNFKC = getNormalizeWithNFKC();
+ const CJK = "(?:\\p{Ideographic}|[\u3040-\u30FF])";
+ const HKDiacritics = "(?:\u3099|\u309A)";
+ const regexp = `([${replace}])|([${toNormalizeWithNFKC}])|(${HKDiacritics}\\n)|(\\p{M}+(?:-\\n)?)|(\\S-\\n)|(${CJK}\\n)|(\\n)`;
+ if (syllablePositions.length === 0) {
+ normalizationRegex = noSyllablesRegExp = new RegExp(regexp + "|(\\u0000)", "gum");
+ } else {
+ normalizationRegex = withSyllablesRegExp = new RegExp(regexp + `|(${FIRST_CHAR_SYLLABLES_REG_EXP})`, "gum");
+ }
+ }
+ const rawDiacriticsPositions = [];
+ while ((m = DIACRITICS_REG_EXP.exec(text)) !== null) {
+ rawDiacriticsPositions.push([m[0].length, m.index]);
+ }
+ let normalized = text.normalize("NFD");
+ const positions = [[0, 0]];
+ let rawDiacriticsIndex = 0;
+ let syllableIndex = 0;
+ let shift = 0;
+ let shiftOrigin = 0;
+ let eol = 0;
+ let hasDiacritics = false;
+ normalized = normalized.replace(normalizationRegex, (match, p1, p2, p3, p4, p5, p6, p7, p8, i) => {
+ i -= shiftOrigin;
+ if (p1) {
+ const replacement = CHARACTERS_TO_NORMALIZE[p1];
+ const jj = replacement.length;
+ for (let j = 1; j < jj; j++) {
+ positions.push([i - shift + j, shift - j]);
+ }
+ shift -= jj - 1;
+ return replacement;
+ }
+ if (p2) {
+ let replacement = NFKC_CHARS_TO_NORMALIZE.get(p2);
+ if (!replacement) {
+ replacement = p2.normalize("NFKC");
+ NFKC_CHARS_TO_NORMALIZE.set(p2, replacement);
+ }
+ const jj = replacement.length;
+ for (let j = 1; j < jj; j++) {
+ positions.push([i - shift + j, shift - j]);
+ }
+ shift -= jj - 1;
+ return replacement;
+ }
+ if (p3) {
+ hasDiacritics = true;
+ if (i + eol === rawDiacriticsPositions[rawDiacriticsIndex]?.[1]) {
+ ++rawDiacriticsIndex;
+ } else {
+ positions.push([i - 1 - shift + 1, shift - 1]);
+ shift -= 1;
+ shiftOrigin += 1;
+ }
+ positions.push([i - shift + 1, shift]);
+ shiftOrigin += 1;
+ eol += 1;
+ return p3.charAt(0);
+ }
+ if (p4) {
+ const hasTrailingDashEOL = p4.endsWith("\n");
+ const len = hasTrailingDashEOL ? p4.length - 2 : p4.length;
+ hasDiacritics = true;
+ let jj = len;
+ if (i + eol === rawDiacriticsPositions[rawDiacriticsIndex]?.[1]) {
+ jj -= rawDiacriticsPositions[rawDiacriticsIndex][0];
+ ++rawDiacriticsIndex;
+ }
+ for (let j = 1; j <= jj; j++) {
+ positions.push([i - 1 - shift + j, shift - j]);
+ }
+ shift -= jj;
+ shiftOrigin += jj;
+ if (hasTrailingDashEOL) {
+ i += len - 1;
+ positions.push([i - shift + 1, 1 + shift]);
+ shift += 1;
+ shiftOrigin += 1;
+ eol += 1;
+ return p4.slice(0, len);
+ }
+ return p4;
+ }
+ if (p5) {
+ const len = p5.length - 2;
+ positions.push([i - shift + len, 1 + shift]);
+ shift += 1;
+ shiftOrigin += 1;
+ eol += 1;
+ return p5.slice(0, -2);
+ }
+ if (p6) {
+ const len = p6.length - 1;
+ positions.push([i - shift + len, shift]);
+ shiftOrigin += 1;
+ eol += 1;
+ return p6.slice(0, -1);
+ }
+ if (p7) {
+ positions.push([i - shift + 1, shift - 1]);
+ shift -= 1;
+ shiftOrigin += 1;
+ eol += 1;
+ return " ";
+ }
+ if (i + eol === syllablePositions[syllableIndex]?.[1]) {
+ const newCharLen = syllablePositions[syllableIndex][0] - 1;
+ ++syllableIndex;
+ for (let j = 1; j <= newCharLen; j++) {
+ positions.push([i - (shift - j), shift - j]);
+ }
+ shift -= newCharLen;
+ shiftOrigin += newCharLen;
+ }
+ return p8;
+ });
+ positions.push([normalized.length, shift]);
+ return [normalized, positions, hasDiacritics];
+}
+function getOriginalIndex(diffs, pos, len) {
+ if (!diffs) {
+ return [pos, len];
+ }
+ const start = pos;
+ const end = pos + len - 1;
+ let i = binarySearchFirstItem(diffs, x => x[0] >= start);
+ if (diffs[i][0] > start) {
+ --i;
+ }
+ let j = binarySearchFirstItem(diffs, x => x[0] >= end, i);
+ if (diffs[j][0] > end) {
+ --j;
+ }
+ const oldStart = start + diffs[i][1];
+ const oldEnd = end + diffs[j][1];
+ const oldLen = oldEnd + 1 - oldStart;
+ return [oldStart, oldLen];
+}
+class PDFFindController {
+ #state = null;
+ #updateMatchesCountOnProgress = true;
+ #visitedPagesCount = 0;
+ constructor({
+ linkService,
+ eventBus,
+ updateMatchesCountOnProgress = true
+ }) {
+ this._linkService = linkService;
+ this._eventBus = eventBus;
+ this.#updateMatchesCountOnProgress = updateMatchesCountOnProgress;
+ this.onIsPageVisible = null;
+ this.#reset();
+ eventBus._on("find", this.#onFind.bind(this));
+ eventBus._on("findbarclose", this.#onFindBarClose.bind(this));
+ }
+ get highlightMatches() {
+ return this._highlightMatches;
+ }
+ get pageMatches() {
+ return this._pageMatches;
+ }
+ get pageMatchesLength() {
+ return this._pageMatchesLength;
+ }
+ get selected() {
+ return this._selected;
+ }
+ get state() {
+ return this.#state;
+ }
+ setDocument(pdfDocument) {
+ if (this._pdfDocument) {
+ this.#reset();
+ }
+ if (!pdfDocument) {
+ return;
+ }
+ this._pdfDocument = pdfDocument;
+ this._firstPageCapability.resolve();
+ }
+ #onFind(state) {
+ if (!state) {
+ return;
+ }
+ const pdfDocument = this._pdfDocument;
+ const {
+ type
+ } = state;
+ if (this.#state === null || this.#shouldDirtyMatch(state)) {
+ this._dirtyMatch = true;
+ }
+ this.#state = state;
+ if (type !== "highlightallchange") {
+ this.#updateUIState(FindState.PENDING);
+ }
+ this._firstPageCapability.promise.then(() => {
+ if (!this._pdfDocument || pdfDocument && this._pdfDocument !== pdfDocument) {
+ return;
+ }
+ this.#extractText();
+ const findbarClosed = !this._highlightMatches;
+ const pendingTimeout = !!this._findTimeout;
+ if (this._findTimeout) {
+ clearTimeout(this._findTimeout);
+ this._findTimeout = null;
+ }
+ if (!type) {
+ this._findTimeout = setTimeout(() => {
+ this.#nextMatch();
+ this._findTimeout = null;
+ }, FIND_TIMEOUT);
+ } else if (this._dirtyMatch) {
+ this.#nextMatch();
+ } else if (type === "again") {
+ this.#nextMatch();
+ if (findbarClosed && this.#state.highlightAll) {
+ this.#updateAllPages();
+ }
+ } else if (type === "highlightallchange") {
+ if (pendingTimeout) {
+ this.#nextMatch();
+ } else {
+ this._highlightMatches = true;
+ }
+ this.#updateAllPages();
+ } else {
+ this.#nextMatch();
+ }
+ });
+ }
+ scrollMatchIntoView({
+ element = null,
+ selectedLeft = 0,
+ pageIndex = -1,
+ matchIndex = -1
+ }) {
+ if (!this._scrollMatches || !element) {
+ return;
+ } else if (matchIndex === -1 || matchIndex !== this._selected.matchIdx) {
+ return;
+ } else if (pageIndex === -1 || pageIndex !== this._selected.pageIdx) {
+ return;
+ }
+ this._scrollMatches = false;
+ const spot = {
+ top: MATCH_SCROLL_OFFSET_TOP,
+ left: selectedLeft + MATCH_SCROLL_OFFSET_LEFT
+ };
+ scrollIntoView(element, spot, true);
+ }
+ #reset() {
+ this._highlightMatches = false;
+ this._scrollMatches = false;
+ this._pdfDocument = null;
+ this._pageMatches = [];
+ this._pageMatchesLength = [];
+ this.#visitedPagesCount = 0;
+ this.#state = null;
+ this._selected = {
+ pageIdx: -1,
+ matchIdx: -1
+ };
+ this._offset = {
+ pageIdx: null,
+ matchIdx: null,
+ wrapped: false
+ };
+ this._extractTextPromises = [];
+ this._pageContents = [];
+ this._pageDiffs = [];
+ this._hasDiacritics = [];
+ this._matchesCountTotal = 0;
+ this._pagesToSearch = null;
+ this._pendingFindMatches = new Set();
+ this._resumePageIdx = null;
+ this._dirtyMatch = false;
+ clearTimeout(this._findTimeout);
+ this._findTimeout = null;
+ this._firstPageCapability = new PromiseCapability();
+ }
+ get #query() {
+ const {
+ query
+ } = this.#state;
+ if (typeof query === "string") {
+ if (query !== this._rawQuery) {
+ this._rawQuery = query;
+ [this._normalizedQuery] = normalize(query);
+ }
+ return this._normalizedQuery;
+ }
+ return (query || []).filter(q => !!q).map(q => normalize(q)[0]);
+ }
+ #shouldDirtyMatch(state) {
+ const newQuery = state.query,
+ prevQuery = this.#state.query;
+ const newType = typeof newQuery,
+ prevType = typeof prevQuery;
+ if (newType !== prevType) {
+ return true;
+ }
+ if (newType === "string") {
+ if (newQuery !== prevQuery) {
+ return true;
+ }
+ } else if (JSON.stringify(newQuery) !== JSON.stringify(prevQuery)) {
+ return true;
+ }
+ switch (state.type) {
+ case "again":
+ const pageNumber = this._selected.pageIdx + 1;
+ const linkService = this._linkService;
+ return pageNumber >= 1 && pageNumber <= linkService.pagesCount && pageNumber !== linkService.page && !(this.onIsPageVisible?.(pageNumber) ?? true);
+ case "highlightallchange":
+ return false;
+ }
+ return true;
+ }
+ #isEntireWord(content, startIdx, length) {
+ let match = content.slice(0, startIdx).match(NOT_DIACRITIC_FROM_END_REG_EXP);
+ if (match) {
+ const first = content.charCodeAt(startIdx);
+ const limit = match[1].charCodeAt(0);
+ if (getCharacterType(first) === getCharacterType(limit)) {
+ return false;
+ }
+ }
+ match = content.slice(startIdx + length).match(NOT_DIACRITIC_FROM_START_REG_EXP);
+ if (match) {
+ const last = content.charCodeAt(startIdx + length - 1);
+ const limit = match[1].charCodeAt(0);
+ if (getCharacterType(last) === getCharacterType(limit)) {
+ return false;
+ }
+ }
+ return true;
+ }
+ #calculateRegExpMatch(query, entireWord, pageIndex, pageContent) {
+ const matches = this._pageMatches[pageIndex] = [];
+ const matchesLength = this._pageMatchesLength[pageIndex] = [];
+ if (!query) {
+ return;
+ }
+ const diffs = this._pageDiffs[pageIndex];
+ let match;
+ while ((match = query.exec(pageContent)) !== null) {
+ if (entireWord && !this.#isEntireWord(pageContent, match.index, match[0].length)) {
+ continue;
+ }
+ const [matchPos, matchLen] = getOriginalIndex(diffs, match.index, match[0].length);
+ if (matchLen) {
+ matches.push(matchPos);
+ matchesLength.push(matchLen);
+ }
+ }
+ }
+ #convertToRegExpString(query, hasDiacritics) {
+ const {
+ matchDiacritics
+ } = this.#state;
+ let isUnicode = false;
+ query = query.replaceAll(SPECIAL_CHARS_REG_EXP, (match, p1, p2, p3, p4, p5) => {
+ if (p1) {
+ return `[ ]*\\${p1}[ ]*`;
+ }
+ if (p2) {
+ return `[ ]*${p2}[ ]*`;
+ }
+ if (p3) {
+ return "[ ]+";
+ }
+ if (matchDiacritics) {
+ return p4 || p5;
+ }
+ if (p4) {
+ return DIACRITICS_EXCEPTION.has(p4.charCodeAt(0)) ? p4 : "";
+ }
+ if (hasDiacritics) {
+ isUnicode = true;
+ return `${p5}\\p{M}*`;
+ }
+ return p5;
+ });
+ const trailingSpaces = "[ ]*";
+ if (query.endsWith(trailingSpaces)) {
+ query = query.slice(0, query.length - trailingSpaces.length);
+ }
+ if (matchDiacritics) {
+ if (hasDiacritics) {
+ DIACRITICS_EXCEPTION_STR ||= String.fromCharCode(...DIACRITICS_EXCEPTION);
+ isUnicode = true;
+ query = `${query}(?=[${DIACRITICS_EXCEPTION_STR}]|[^\\p{M}]|$)`;
+ }
+ }
+ return [isUnicode, query];
+ }
+ #calculateMatch(pageIndex) {
+ let query = this.#query;
+ if (query.length === 0) {
+ return;
+ }
+ const {
+ caseSensitive,
+ entireWord
+ } = this.#state;
+ const pageContent = this._pageContents[pageIndex];
+ const hasDiacritics = this._hasDiacritics[pageIndex];
+ let isUnicode = false;
+ if (typeof query === "string") {
+ [isUnicode, query] = this.#convertToRegExpString(query, hasDiacritics);
+ } else {
+ query = query.sort().reverse().map(q => {
+ const [isUnicodePart, queryPart] = this.#convertToRegExpString(q, hasDiacritics);
+ isUnicode ||= isUnicodePart;
+ return `(${queryPart})`;
+ }).join("|");
+ }
+ const flags = `g${isUnicode ? "u" : ""}${caseSensitive ? "" : "i"}`;
+ query = query ? new RegExp(query, flags) : null;
+ this.#calculateRegExpMatch(query, entireWord, pageIndex, pageContent);
+ if (this.#state.highlightAll) {
+ this.#updatePage(pageIndex);
+ }
+ if (this._resumePageIdx === pageIndex) {
+ this._resumePageIdx = null;
+ this.#nextPageMatch();
+ }
+ const pageMatchesCount = this._pageMatches[pageIndex].length;
+ this._matchesCountTotal += pageMatchesCount;
+ if (this.#updateMatchesCountOnProgress) {
+ if (pageMatchesCount > 0) {
+ this.#updateUIResultsCount();
+ }
+ } else if (++this.#visitedPagesCount === this._linkService.pagesCount) {
+ this.#updateUIResultsCount();
+ }
+ }
+ #extractText() {
+ if (this._extractTextPromises.length > 0) {
+ return;
+ }
+ let promise = Promise.resolve();
+ const textOptions = {
+ disableNormalization: true
+ };
+ for (let i = 0, ii = this._linkService.pagesCount; i < ii; i++) {
+ const extractTextCapability = new PromiseCapability();
+ this._extractTextPromises[i] = extractTextCapability.promise;
+ promise = promise.then(() => {
+ return this._pdfDocument.getPage(i + 1).then(pdfPage => pdfPage.getTextContent(textOptions)).then(textContent => {
+ const strBuf = [];
+ for (const textItem of textContent.items) {
+ strBuf.push(textItem.str);
+ if (textItem.hasEOL) {
+ strBuf.push("\n");
+ }
+ }
+ [this._pageContents[i], this._pageDiffs[i], this._hasDiacritics[i]] = normalize(strBuf.join(""));
+ extractTextCapability.resolve();
+ }, reason => {
+ console.error(`Unable to get text content for page ${i + 1}`, reason);
+ this._pageContents[i] = "";
+ this._pageDiffs[i] = null;
+ this._hasDiacritics[i] = false;
+ extractTextCapability.resolve();
+ });
+ });
+ }
+ }
+ #updatePage(index) {
+ if (this._scrollMatches && this._selected.pageIdx === index) {
+ this._linkService.page = index + 1;
+ }
+ this._eventBus.dispatch("updatetextlayermatches", {
+ source: this,
+ pageIndex: index
+ });
+ }
+ #updateAllPages() {
+ this._eventBus.dispatch("updatetextlayermatches", {
+ source: this,
+ pageIndex: -1
+ });
+ }
+ #nextMatch() {
+ const previous = this.#state.findPrevious;
+ const currentPageIndex = this._linkService.page - 1;
+ const numPages = this._linkService.pagesCount;
+ this._highlightMatches = true;
+ if (this._dirtyMatch) {
+ this._dirtyMatch = false;
+ this._selected.pageIdx = this._selected.matchIdx = -1;
+ this._offset.pageIdx = currentPageIndex;
+ this._offset.matchIdx = null;
+ this._offset.wrapped = false;
+ this._resumePageIdx = null;
+ this._pageMatches.length = 0;
+ this._pageMatchesLength.length = 0;
+ this.#visitedPagesCount = 0;
+ this._matchesCountTotal = 0;
+ this.#updateAllPages();
+ for (let i = 0; i < numPages; i++) {
+ if (this._pendingFindMatches.has(i)) {
+ continue;
+ }
+ this._pendingFindMatches.add(i);
+ this._extractTextPromises[i].then(() => {
+ this._pendingFindMatches.delete(i);
+ this.#calculateMatch(i);
+ });
+ }
+ }
+ const query = this.#query;
+ if (query.length === 0) {
+ this.#updateUIState(FindState.FOUND);
+ return;
+ }
+ if (this._resumePageIdx) {
+ return;
+ }
+ const offset = this._offset;
+ this._pagesToSearch = numPages;
+ if (offset.matchIdx !== null) {
+ const numPageMatches = this._pageMatches[offset.pageIdx].length;
+ if (!previous && offset.matchIdx + 1 < numPageMatches || previous && offset.matchIdx > 0) {
+ offset.matchIdx = previous ? offset.matchIdx - 1 : offset.matchIdx + 1;
+ this.#updateMatch(true);
+ return;
+ }
+ this.#advanceOffsetPage(previous);
+ }
+ this.#nextPageMatch();
+ }
+ #matchesReady(matches) {
+ const offset = this._offset;
+ const numMatches = matches.length;
+ const previous = this.#state.findPrevious;
+ if (numMatches) {
+ offset.matchIdx = previous ? numMatches - 1 : 0;
+ this.#updateMatch(true);
+ return true;
+ }
+ this.#advanceOffsetPage(previous);
+ if (offset.wrapped) {
+ offset.matchIdx = null;
+ if (this._pagesToSearch < 0) {
+ this.#updateMatch(false);
+ return true;
+ }
+ }
+ return false;
+ }
+ #nextPageMatch() {
+ if (this._resumePageIdx !== null) {
+ console.error("There can only be one pending page.");
+ }
+ let matches = null;
+ do {
+ const pageIdx = this._offset.pageIdx;
+ matches = this._pageMatches[pageIdx];
+ if (!matches) {
+ this._resumePageIdx = pageIdx;
+ break;
+ }
+ } while (!this.#matchesReady(matches));
+ }
+ #advanceOffsetPage(previous) {
+ const offset = this._offset;
+ const numPages = this._linkService.pagesCount;
+ offset.pageIdx = previous ? offset.pageIdx - 1 : offset.pageIdx + 1;
+ offset.matchIdx = null;
+ this._pagesToSearch--;
+ if (offset.pageIdx >= numPages || offset.pageIdx < 0) {
+ offset.pageIdx = previous ? numPages - 1 : 0;
+ offset.wrapped = true;
+ }
+ }
+ #updateMatch(found = false) {
+ let state = FindState.NOT_FOUND;
+ const wrapped = this._offset.wrapped;
+ this._offset.wrapped = false;
+ if (found) {
+ const previousPage = this._selected.pageIdx;
+ this._selected.pageIdx = this._offset.pageIdx;
+ this._selected.matchIdx = this._offset.matchIdx;
+ state = wrapped ? FindState.WRAPPED : FindState.FOUND;
+ if (previousPage !== -1 && previousPage !== this._selected.pageIdx) {
+ this.#updatePage(previousPage);
+ }
+ }
+ this.#updateUIState(state, this.#state.findPrevious);
+ if (this._selected.pageIdx !== -1) {
+ this._scrollMatches = true;
+ this.#updatePage(this._selected.pageIdx);
+ }
+ }
+ #onFindBarClose(evt) {
+ const pdfDocument = this._pdfDocument;
+ this._firstPageCapability.promise.then(() => {
+ if (!this._pdfDocument || pdfDocument && this._pdfDocument !== pdfDocument) {
+ return;
+ }
+ if (this._findTimeout) {
+ clearTimeout(this._findTimeout);
+ this._findTimeout = null;
+ }
+ if (this._resumePageIdx) {
+ this._resumePageIdx = null;
+ this._dirtyMatch = true;
+ }
+ this.#updateUIState(FindState.FOUND);
+ this._highlightMatches = false;
+ this.#updateAllPages();
+ });
+ }
+ #requestMatchesCount() {
+ const {
+ pageIdx,
+ matchIdx
+ } = this._selected;
+ let current = 0,
+ total = this._matchesCountTotal;
+ if (matchIdx !== -1) {
+ for (let i = 0; i < pageIdx; i++) {
+ current += this._pageMatches[i]?.length || 0;
+ }
+ current += matchIdx + 1;
+ }
+ if (current < 1 || current > total) {
+ current = total = 0;
+ }
+ return {
+ current,
+ total
+ };
+ }
+ #updateUIResultsCount() {
+ this._eventBus.dispatch("updatefindmatchescount", {
+ source: this,
+ matchesCount: this.#requestMatchesCount()
+ });
+ }
+ #updateUIState(state, previous = false) {
+ if (!this.#updateMatchesCountOnProgress && (this.#visitedPagesCount !== this._linkService.pagesCount || state === FindState.PENDING)) {
+ return;
+ }
+ this._eventBus.dispatch("updatefindcontrolstate", {
+ source: this,
+ state,
+ previous,
+ matchesCount: this.#requestMatchesCount(),
+ rawQuery: this.#state?.query ?? null
+ });
+ }
+}
+
+;// CONCATENATED MODULE: ./web/pdf_find_bar.js
+
+
+const MATCHES_COUNT_LIMIT = 1000;
+class PDFFindBar {
+ #resizeObserver = new ResizeObserver(this.#resizeObserverCallback.bind(this));
+ constructor(options, eventBus) {
+ this.opened = false;
+ this.bar = options.bar;
+ this.toggleButton = options.toggleButton;
+ this.findField = options.findField;
+ this.highlightAll = options.highlightAllCheckbox;
+ this.caseSensitive = options.caseSensitiveCheckbox;
+ this.matchDiacritics = options.matchDiacriticsCheckbox;
+ this.entireWord = options.entireWordCheckbox;
+ this.findMsg = options.findMsg;
+ this.findResultsCount = options.findResultsCount;
+ this.findPreviousButton = options.findPreviousButton;
+ this.findNextButton = options.findNextButton;
+ this.eventBus = eventBus;
+ this.toggleButton.addEventListener("click", () => {
+ this.toggle();
+ });
+ this.findField.addEventListener("input", () => {
+ this.dispatchEvent("");
+ });
+ this.bar.addEventListener("keydown", e => {
+ switch (e.keyCode) {
+ case 13:
+ if (e.target === this.findField) {
+ this.dispatchEvent("again", e.shiftKey);
+ }
+ break;
+ case 27:
+ this.close();
+ break;
+ }
+ });
+ this.findPreviousButton.addEventListener("click", () => {
+ this.dispatchEvent("again", true);
+ });
+ this.findNextButton.addEventListener("click", () => {
+ this.dispatchEvent("again", false);
+ });
+ this.highlightAll.addEventListener("click", () => {
+ this.dispatchEvent("highlightallchange");
+ });
+ this.caseSensitive.addEventListener("click", () => {
+ this.dispatchEvent("casesensitivitychange");
+ });
+ this.entireWord.addEventListener("click", () => {
+ this.dispatchEvent("entirewordchange");
+ });
+ this.matchDiacritics.addEventListener("click", () => {
+ this.dispatchEvent("diacriticmatchingchange");
+ });
+ }
+ reset() {
+ this.updateUIState();
+ }
+ dispatchEvent(type, findPrev = false) {
+ this.eventBus.dispatch("find", {
+ source: this,
+ type,
+ query: this.findField.value,
+ caseSensitive: this.caseSensitive.checked,
+ entireWord: this.entireWord.checked,
+ highlightAll: this.highlightAll.checked,
+ findPrevious: findPrev,
+ matchDiacritics: this.matchDiacritics.checked
+ });
+ }
+ updateUIState(state, previous, matchesCount) {
+ const {
+ findField,
+ findMsg
+ } = this;
+ let findMsgId = "",
+ status = "";
+ switch (state) {
+ case FindState.FOUND:
+ break;
+ case FindState.PENDING:
+ status = "pending";
+ break;
+ case FindState.NOT_FOUND:
+ findMsgId = "pdfjs-find-not-found";
+ status = "notFound";
+ break;
+ case FindState.WRAPPED:
+ findMsgId = `pdfjs-find-reached-${previous ? "top" : "bottom"}`;
+ break;
+ }
+ findField.setAttribute("data-status", status);
+ findField.setAttribute("aria-invalid", state === FindState.NOT_FOUND);
+ findMsg.setAttribute("data-status", status);
+ if (findMsgId) {
+ findMsg.setAttribute("data-l10n-id", findMsgId);
+ } else {
+ findMsg.removeAttribute("data-l10n-id");
+ findMsg.textContent = "";
+ }
+ this.updateResultsCount(matchesCount);
+ }
+ updateResultsCount({
+ current = 0,
+ total = 0
+ } = {}) {
+ const {
+ findResultsCount
+ } = this;
+ if (total > 0) {
+ const limit = MATCHES_COUNT_LIMIT;
+ findResultsCount.setAttribute("data-l10n-id", `pdfjs-find-match-count${total > limit ? "-limit" : ""}`);
+ findResultsCount.setAttribute("data-l10n-args", JSON.stringify({
+ limit,
+ current,
+ total
+ }));
+ } else {
+ findResultsCount.removeAttribute("data-l10n-id");
+ findResultsCount.textContent = "";
+ }
+ }
+ open() {
+ if (!this.opened) {
+ this.#resizeObserver.observe(this.bar.parentNode);
+ this.#resizeObserver.observe(this.bar);
+ this.opened = true;
+ toggleExpandedBtn(this.toggleButton, true, this.bar);
+ }
+ this.findField.select();
+ this.findField.focus();
+ }
+ close() {
+ if (!this.opened) {
+ return;
+ }
+ this.#resizeObserver.disconnect();
+ this.opened = false;
+ toggleExpandedBtn(this.toggleButton, false, this.bar);
+ this.eventBus.dispatch("findbarclose", {
+ source: this
+ });
+ }
+ toggle() {
+ if (this.opened) {
+ this.close();
+ } else {
+ this.open();
+ }
+ }
+ #resizeObserverCallback(entries) {
+ const {
+ bar
+ } = this;
+ bar.classList.remove("wrapContainers");
+ const findbarHeight = bar.clientHeight;
+ const inputContainerHeight = bar.firstElementChild.clientHeight;
+ if (findbarHeight > inputContainerHeight) {
+ bar.classList.add("wrapContainers");
+ }
+ }
+}
+
+;// CONCATENATED MODULE: ./web/pdf_history.js
+
+
+const HASH_CHANGE_TIMEOUT = 1000;
+const POSITION_UPDATED_THRESHOLD = 50;
+const UPDATE_VIEWAREA_TIMEOUT = 1000;
+function getCurrentHash() {
+ return document.location.hash;
+}
+class PDFHistory {
+ constructor({
+ linkService,
+ eventBus
+ }) {
+ this.linkService = linkService;
+ this.eventBus = eventBus;
+ this._initialized = false;
+ this._fingerprint = "";
+ this.reset();
+ this._boundEvents = null;
+ this.eventBus._on("pagesinit", () => {
+ this._isPagesLoaded = false;
+ this.eventBus._on("pagesloaded", evt => {
+ this._isPagesLoaded = !!evt.pagesCount;
+ }, {
+ once: true
+ });
+ });
+ }
+ initialize({
+ fingerprint,
+ resetHistory = false,
+ updateUrl = false
+ }) {
+ if (!fingerprint || typeof fingerprint !== "string") {
+ console.error('PDFHistory.initialize: The "fingerprint" must be a non-empty string.');
+ return;
+ }
+ if (this._initialized) {
+ this.reset();
+ }
+ const reInitialized = this._fingerprint !== "" && this._fingerprint !== fingerprint;
+ this._fingerprint = fingerprint;
+ this._updateUrl = updateUrl === true;
+ this._initialized = true;
+ this._bindEvents();
+ const state = window.history.state;
+ this._popStateInProgress = false;
+ this._blockHashChange = 0;
+ this._currentHash = getCurrentHash();
+ this._numPositionUpdates = 0;
+ this._uid = this._maxUid = 0;
+ this._destination = null;
+ this._position = null;
+ if (!this._isValidState(state, true) || resetHistory) {
+ const {
+ hash,
+ page,
+ rotation
+ } = this._parseCurrentHash(true);
+ if (!hash || reInitialized || resetHistory) {
+ this._pushOrReplaceState(null, true);
+ return;
+ }
+ this._pushOrReplaceState({
+ hash,
+ page,
+ rotation
+ }, true);
+ return;
+ }
+ const destination = state.destination;
+ this._updateInternalState(destination, state.uid, true);
+ if (destination.rotation !== undefined) {
+ this._initialRotation = destination.rotation;
+ }
+ if (destination.dest) {
+ this._initialBookmark = JSON.stringify(destination.dest);
+ this._destination.page = null;
+ } else if (destination.hash) {
+ this._initialBookmark = destination.hash;
+ } else if (destination.page) {
+ this._initialBookmark = `page=${destination.page}`;
+ }
+ }
+ reset() {
+ if (this._initialized) {
+ this._pageHide();
+ this._initialized = false;
+ this._unbindEvents();
+ }
+ if (this._updateViewareaTimeout) {
+ clearTimeout(this._updateViewareaTimeout);
+ this._updateViewareaTimeout = null;
+ }
+ this._initialBookmark = null;
+ this._initialRotation = null;
+ }
+ push({
+ namedDest = null,
+ explicitDest,
+ pageNumber
+ }) {
+ if (!this._initialized) {
+ return;
+ }
+ if (namedDest && typeof namedDest !== "string") {
+ console.error("PDFHistory.push: " + `"${namedDest}" is not a valid namedDest parameter.`);
+ return;
+ } else if (!Array.isArray(explicitDest)) {
+ console.error("PDFHistory.push: " + `"${explicitDest}" is not a valid explicitDest parameter.`);
+ return;
+ } else if (!this._isValidPage(pageNumber)) {
+ if (pageNumber !== null || this._destination) {
+ console.error("PDFHistory.push: " + `"${pageNumber}" is not a valid pageNumber parameter.`);
+ return;
+ }
+ }
+ const hash = namedDest || JSON.stringify(explicitDest);
+ if (!hash) {
+ return;
+ }
+ let forceReplace = false;
+ if (this._destination && (isDestHashesEqual(this._destination.hash, hash) || isDestArraysEqual(this._destination.dest, explicitDest))) {
+ if (this._destination.page) {
+ return;
+ }
+ forceReplace = true;
+ }
+ if (this._popStateInProgress && !forceReplace) {
+ return;
+ }
+ this._pushOrReplaceState({
+ dest: explicitDest,
+ hash,
+ page: pageNumber,
+ rotation: this.linkService.rotation
+ }, forceReplace);
+ if (!this._popStateInProgress) {
+ this._popStateInProgress = true;
+ Promise.resolve().then(() => {
+ this._popStateInProgress = false;
+ });
+ }
+ }
+ pushPage(pageNumber) {
+ if (!this._initialized) {
+ return;
+ }
+ if (!this._isValidPage(pageNumber)) {
+ console.error(`PDFHistory.pushPage: "${pageNumber}" is not a valid page number.`);
+ return;
+ }
+ if (this._destination?.page === pageNumber) {
+ return;
+ }
+ if (this._popStateInProgress) {
+ return;
+ }
+ this._pushOrReplaceState({
+ dest: null,
+ hash: `page=${pageNumber}`,
+ page: pageNumber,
+ rotation: this.linkService.rotation
+ });
+ if (!this._popStateInProgress) {
+ this._popStateInProgress = true;
+ Promise.resolve().then(() => {
+ this._popStateInProgress = false;
+ });
+ }
+ }
+ pushCurrentPosition() {
+ if (!this._initialized || this._popStateInProgress) {
+ return;
+ }
+ this._tryPushCurrentPosition();
+ }
+ back() {
+ if (!this._initialized || this._popStateInProgress) {
+ return;
+ }
+ const state = window.history.state;
+ if (this._isValidState(state) && state.uid > 0) {
+ window.history.back();
+ }
+ }
+ forward() {
+ if (!this._initialized || this._popStateInProgress) {
+ return;
+ }
+ const state = window.history.state;
+ if (this._isValidState(state) && state.uid < this._maxUid) {
+ window.history.forward();
+ }
+ }
+ get popStateInProgress() {
+ return this._initialized && (this._popStateInProgress || this._blockHashChange > 0);
+ }
+ get initialBookmark() {
+ return this._initialized ? this._initialBookmark : null;
+ }
+ get initialRotation() {
+ return this._initialized ? this._initialRotation : null;
+ }
+ _pushOrReplaceState(destination, forceReplace = false) {
+ const shouldReplace = forceReplace || !this._destination;
+ const newState = {
+ fingerprint: this._fingerprint,
+ uid: shouldReplace ? this._uid : this._uid + 1,
+ destination
+ };
+ this._updateInternalState(destination, newState.uid);
+ let newUrl;
+ if (this._updateUrl && destination?.hash) {
+ const baseUrl = document.location.href.split("#", 1)[0];
+ if (!baseUrl.startsWith("file://")) {
+ newUrl = `${baseUrl}#${destination.hash}`;
+ }
+ }
+ if (shouldReplace) {
+ window.history.replaceState(newState, "", newUrl);
+ } else {
+ window.history.pushState(newState, "", newUrl);
+ }
+ }
+ _tryPushCurrentPosition(temporary = false) {
+ if (!this._position) {
+ return;
+ }
+ let position = this._position;
+ if (temporary) {
+ position = Object.assign(Object.create(null), this._position);
+ position.temporary = true;
+ }
+ if (!this._destination) {
+ this._pushOrReplaceState(position);
+ return;
+ }
+ if (this._destination.temporary) {
+ this._pushOrReplaceState(position, true);
+ return;
+ }
+ if (this._destination.hash === position.hash) {
+ return;
+ }
+ if (!this._destination.page && (POSITION_UPDATED_THRESHOLD <= 0 || this._numPositionUpdates <= POSITION_UPDATED_THRESHOLD)) {
+ return;
+ }
+ let forceReplace = false;
+ if (this._destination.page >= position.first && this._destination.page <= position.page) {
+ if (this._destination.dest !== undefined || !this._destination.first) {
+ return;
+ }
+ forceReplace = true;
+ }
+ this._pushOrReplaceState(position, forceReplace);
+ }
+ _isValidPage(val) {
+ return Number.isInteger(val) && val > 0 && val <= this.linkService.pagesCount;
+ }
+ _isValidState(state, checkReload = false) {
+ if (!state) {
+ return false;
+ }
+ if (state.fingerprint !== this._fingerprint) {
+ if (checkReload) {
+ if (typeof state.fingerprint !== "string" || state.fingerprint.length !== this._fingerprint.length) {
+ return false;
+ }
+ const [perfEntry] = performance.getEntriesByType("navigation");
+ if (perfEntry?.type !== "reload") {
+ return false;
+ }
+ } else {
+ return false;
+ }
+ }
+ if (!Number.isInteger(state.uid) || state.uid < 0) {
+ return false;
+ }
+ if (state.destination === null || typeof state.destination !== "object") {
+ return false;
+ }
+ return true;
+ }
+ _updateInternalState(destination, uid, removeTemporary = false) {
+ if (this._updateViewareaTimeout) {
+ clearTimeout(this._updateViewareaTimeout);
+ this._updateViewareaTimeout = null;
+ }
+ if (removeTemporary && destination?.temporary) {
+ delete destination.temporary;
+ }
+ this._destination = destination;
+ this._uid = uid;
+ this._maxUid = Math.max(this._maxUid, uid);
+ this._numPositionUpdates = 0;
+ }
+ _parseCurrentHash(checkNameddest = false) {
+ const hash = unescape(getCurrentHash()).substring(1);
+ const params = parseQueryString(hash);
+ const nameddest = params.get("nameddest") || "";
+ let page = params.get("page") | 0;
+ if (!this._isValidPage(page) || checkNameddest && nameddest.length > 0) {
+ page = null;
+ }
+ return {
+ hash,
+ page,
+ rotation: this.linkService.rotation
+ };
+ }
+ _updateViewarea({
+ location
+ }) {
+ if (this._updateViewareaTimeout) {
+ clearTimeout(this._updateViewareaTimeout);
+ this._updateViewareaTimeout = null;
+ }
+ this._position = {
+ hash: location.pdfOpenParams.substring(1),
+ page: this.linkService.page,
+ first: location.pageNumber,
+ rotation: location.rotation
+ };
+ if (this._popStateInProgress) {
+ return;
+ }
+ if (POSITION_UPDATED_THRESHOLD > 0 && this._isPagesLoaded && this._destination && !this._destination.page) {
+ this._numPositionUpdates++;
+ }
+ if (UPDATE_VIEWAREA_TIMEOUT > 0) {
+ this._updateViewareaTimeout = setTimeout(() => {
+ if (!this._popStateInProgress) {
+ this._tryPushCurrentPosition(true);
+ }
+ this._updateViewareaTimeout = null;
+ }, UPDATE_VIEWAREA_TIMEOUT);
+ }
+ }
+ _popState({
+ state
+ }) {
+ const newHash = getCurrentHash(),
+ hashChanged = this._currentHash !== newHash;
+ this._currentHash = newHash;
+ if (!state) {
+ this._uid++;
+ const {
+ hash,
+ page,
+ rotation
+ } = this._parseCurrentHash();
+ this._pushOrReplaceState({
+ hash,
+ page,
+ rotation
+ }, true);
+ return;
+ }
+ if (!this._isValidState(state)) {
+ return;
+ }
+ this._popStateInProgress = true;
+ if (hashChanged) {
+ this._blockHashChange++;
+ waitOnEventOrTimeout({
+ target: window,
+ name: "hashchange",
+ delay: HASH_CHANGE_TIMEOUT
+ }).then(() => {
+ this._blockHashChange--;
+ });
+ }
+ const destination = state.destination;
+ this._updateInternalState(destination, state.uid, true);
+ if (isValidRotation(destination.rotation)) {
+ this.linkService.rotation = destination.rotation;
+ }
+ if (destination.dest) {
+ this.linkService.goToDestination(destination.dest);
+ } else if (destination.hash) {
+ this.linkService.setHash(destination.hash);
+ } else if (destination.page) {
+ this.linkService.page = destination.page;
+ }
+ Promise.resolve().then(() => {
+ this._popStateInProgress = false;
+ });
+ }
+ _pageHide() {
+ if (!this._destination || this._destination.temporary) {
+ this._tryPushCurrentPosition();
+ }
+ }
+ _bindEvents() {
+ if (this._boundEvents) {
+ return;
+ }
+ this._boundEvents = {
+ updateViewarea: this._updateViewarea.bind(this),
+ popState: this._popState.bind(this),
+ pageHide: this._pageHide.bind(this)
+ };
+ this.eventBus._on("updateviewarea", this._boundEvents.updateViewarea);
+ window.addEventListener("popstate", this._boundEvents.popState);
+ window.addEventListener("pagehide", this._boundEvents.pageHide);
+ }
+ _unbindEvents() {
+ if (!this._boundEvents) {
+ return;
+ }
+ this.eventBus._off("updateviewarea", this._boundEvents.updateViewarea);
+ window.removeEventListener("popstate", this._boundEvents.popState);
+ window.removeEventListener("pagehide", this._boundEvents.pageHide);
+ this._boundEvents = null;
+ }
+}
+function isDestHashesEqual(destHash, pushHash) {
+ if (typeof destHash !== "string" || typeof pushHash !== "string") {
+ return false;
+ }
+ if (destHash === pushHash) {
+ return true;
+ }
+ const nameddest = parseQueryString(destHash).get("nameddest");
+ if (nameddest === pushHash) {
+ return true;
+ }
+ return false;
+}
+function isDestArraysEqual(firstDest, secondDest) {
+ function isEntryEqual(first, second) {
+ if (typeof first !== typeof second) {
+ return false;
+ }
+ if (Array.isArray(first) || Array.isArray(second)) {
+ return false;
+ }
+ if (first !== null && typeof first === "object" && second !== null) {
+ if (Object.keys(first).length !== Object.keys(second).length) {
+ return false;
+ }
+ for (const key in first) {
+ if (!isEntryEqual(first[key], second[key])) {
+ return false;
+ }
+ }
+ return true;
+ }
+ return first === second || Number.isNaN(first) && Number.isNaN(second);
+ }
+ if (!(Array.isArray(firstDest) && Array.isArray(secondDest))) {
+ return false;
+ }
+ if (firstDest.length !== secondDest.length) {
+ return false;
+ }
+ for (let i = 0, ii = firstDest.length; i < ii; i++) {
+ if (!isEntryEqual(firstDest[i], secondDest[i])) {
+ return false;
+ }
+ }
+ return true;
+}
+
+;// CONCATENATED MODULE: ./web/pdf_layer_viewer.js
+
+class PDFLayerViewer extends BaseTreeViewer {
+ constructor(options) {
+ super(options);
+ this.eventBus._on("optionalcontentconfigchanged", evt => {
+ this.#updateLayers(evt.promise);
+ });
+ this.eventBus._on("resetlayers", () => {
+ this.#updateLayers();
+ });
+ this.eventBus._on("togglelayerstree", this._toggleAllTreeItems.bind(this));
+ }
+ reset() {
+ super.reset();
+ this._optionalContentConfig = null;
+ this._optionalContentHash = null;
+ }
+ _dispatchEvent(layersCount) {
+ this.eventBus.dispatch("layersloaded", {
+ source: this,
+ layersCount
+ });
+ }
+ _bindLink(element, {
+ groupId,
+ input
+ }) {
+ const setVisibility = () => {
+ this._optionalContentConfig.setVisibility(groupId, input.checked);
+ this._optionalContentHash = this._optionalContentConfig.getHash();
+ this.eventBus.dispatch("optionalcontentconfig", {
+ source: this,
+ promise: Promise.resolve(this._optionalContentConfig)
+ });
+ };
+ element.onclick = evt => {
+ if (evt.target === input) {
+ setVisibility();
+ return true;
+ } else if (evt.target !== element) {
+ return true;
+ }
+ input.checked = !input.checked;
+ setVisibility();
+ return false;
+ };
+ }
+ async _setNestedName(element, {
+ name = null
+ }) {
+ if (typeof name === "string") {
+ element.textContent = this._normalizeTextContent(name);
+ return;
+ }
+ element.textContent = await this._l10n.get("pdfjs-additional-layers");
+ element.style.fontStyle = "italic";
+ }
+ _addToggleButton(div, {
+ name = null
+ }) {
+ super._addToggleButton(div, name === null);
+ }
+ _toggleAllTreeItems() {
+ if (!this._optionalContentConfig) {
+ return;
+ }
+ super._toggleAllTreeItems();
+ }
+ render({
+ optionalContentConfig,
+ pdfDocument
+ }) {
+ if (this._optionalContentConfig) {
+ this.reset();
+ }
+ this._optionalContentConfig = optionalContentConfig || null;
+ this._pdfDocument = pdfDocument || null;
+ const groups = optionalContentConfig?.getOrder();
+ if (!groups) {
+ this._dispatchEvent(0);
+ return;
+ }
+ this._optionalContentHash = optionalContentConfig.getHash();
+ const fragment = document.createDocumentFragment(),
+ queue = [{
+ parent: fragment,
+ groups
+ }];
+ let layersCount = 0,
+ hasAnyNesting = false;
+ while (queue.length > 0) {
+ const levelData = queue.shift();
+ for (const groupId of levelData.groups) {
+ const div = document.createElement("div");
+ div.className = "treeItem";
+ const element = document.createElement("a");
+ div.append(element);
+ if (typeof groupId === "object") {
+ hasAnyNesting = true;
+ this._addToggleButton(div, groupId);
+ this._setNestedName(element, groupId);
+ const itemsDiv = document.createElement("div");
+ itemsDiv.className = "treeItems";
+ div.append(itemsDiv);
+ queue.push({
+ parent: itemsDiv,
+ groups: groupId.order
+ });
+ } else {
+ const group = optionalContentConfig.getGroup(groupId);
+ const input = document.createElement("input");
+ this._bindLink(element, {
+ groupId,
+ input
+ });
+ input.type = "checkbox";
+ input.checked = group.visible;
+ const label = document.createElement("label");
+ label.textContent = this._normalizeTextContent(group.name);
+ label.append(input);
+ element.append(label);
+ layersCount++;
+ }
+ levelData.parent.append(div);
+ }
+ }
+ this._finishRendering(fragment, layersCount, hasAnyNesting);
+ }
+ async #updateLayers(promise = null) {
+ if (!this._optionalContentConfig) {
+ return;
+ }
+ const pdfDocument = this._pdfDocument;
+ const optionalContentConfig = await (promise || pdfDocument.getOptionalContentConfig());
+ if (pdfDocument !== this._pdfDocument) {
+ return;
+ }
+ if (promise) {
+ if (optionalContentConfig.getHash() === this._optionalContentHash) {
+ return;
+ }
+ } else {
+ this.eventBus.dispatch("optionalcontentconfig", {
+ source: this,
+ promise: Promise.resolve(optionalContentConfig)
+ });
+ }
+ this.render({
+ optionalContentConfig,
+ pdfDocument: this._pdfDocument
+ });
+ }
+}
+
+;// CONCATENATED MODULE: ./web/pdf_outline_viewer.js
+
+
+
+class PDFOutlineViewer extends BaseTreeViewer {
+ constructor(options) {
+ super(options);
+ this.linkService = options.linkService;
+ this.downloadManager = options.downloadManager;
+ this.eventBus._on("toggleoutlinetree", this._toggleAllTreeItems.bind(this));
+ this.eventBus._on("currentoutlineitem", this._currentOutlineItem.bind(this));
+ this.eventBus._on("pagechanging", evt => {
+ this._currentPageNumber = evt.pageNumber;
+ });
+ this.eventBus._on("pagesloaded", evt => {
+ this._isPagesLoaded = !!evt.pagesCount;
+ if (this._currentOutlineItemCapability && !this._currentOutlineItemCapability.settled) {
+ this._currentOutlineItemCapability.resolve(this._isPagesLoaded);
+ }
+ });
+ this.eventBus._on("sidebarviewchanged", evt => {
+ this._sidebarView = evt.view;
+ });
+ }
+ reset() {
+ super.reset();
+ this._outline = null;
+ this._pageNumberToDestHashCapability = null;
+ this._currentPageNumber = 1;
+ this._isPagesLoaded = null;
+ if (this._currentOutlineItemCapability && !this._currentOutlineItemCapability.settled) {
+ this._currentOutlineItemCapability.resolve(false);
+ }
+ this._currentOutlineItemCapability = null;
+ }
+ _dispatchEvent(outlineCount) {
+ this._currentOutlineItemCapability = new PromiseCapability();
+ if (outlineCount === 0 || this._pdfDocument?.loadingParams.disableAutoFetch) {
+ this._currentOutlineItemCapability.resolve(false);
+ } else if (this._isPagesLoaded !== null) {
+ this._currentOutlineItemCapability.resolve(this._isPagesLoaded);
+ }
+ this.eventBus.dispatch("outlineloaded", {
+ source: this,
+ outlineCount,
+ currentOutlineItemPromise: this._currentOutlineItemCapability.promise
+ });
+ }
+ _bindLink(element, {
+ url,
+ newWindow,
+ action,
+ attachment,
+ dest,
+ setOCGState
+ }) {
+ const {
+ linkService
+ } = this;
+ if (url) {
+ linkService.addLinkAttributes(element, url, newWindow);
+ return;
+ }
+ if (action) {
+ element.href = linkService.getAnchorUrl("");
+ element.onclick = () => {
+ linkService.executeNamedAction(action);
+ return false;
+ };
+ return;
+ }
+ if (attachment) {
+ element.href = linkService.getAnchorUrl("");
+ element.onclick = () => {
+ this.downloadManager.openOrDownloadData(attachment.content, attachment.filename);
+ return false;
+ };
+ return;
+ }
+ if (setOCGState) {
+ element.href = linkService.getAnchorUrl("");
+ element.onclick = () => {
+ linkService.executeSetOCGState(setOCGState);
+ return false;
+ };
+ return;
+ }
+ element.href = linkService.getDestinationHash(dest);
+ element.onclick = evt => {
+ this._updateCurrentTreeItem(evt.target.parentNode);
+ if (dest) {
+ linkService.goToDestination(dest);
+ }
+ return false;
+ };
+ }
+ _setStyles(element, {
+ bold,
+ italic
+ }) {
+ if (bold) {
+ element.style.fontWeight = "bold";
+ }
+ if (italic) {
+ element.style.fontStyle = "italic";
+ }
+ }
+ _addToggleButton(div, {
+ count,
+ items
+ }) {
+ let hidden = false;
+ if (count < 0) {
+ let totalCount = items.length;
+ if (totalCount > 0) {
+ const queue = [...items];
+ while (queue.length > 0) {
+ const {
+ count: nestedCount,
+ items: nestedItems
+ } = queue.shift();
+ if (nestedCount > 0 && nestedItems.length > 0) {
+ totalCount += nestedItems.length;
+ queue.push(...nestedItems);
+ }
+ }
+ }
+ if (Math.abs(count) === totalCount) {
+ hidden = true;
+ }
+ }
+ super._addToggleButton(div, hidden);
+ }
+ _toggleAllTreeItems() {
+ if (!this._outline) {
+ return;
+ }
+ super._toggleAllTreeItems();
+ }
+ render({
+ outline,
+ pdfDocument
+ }) {
+ if (this._outline) {
+ this.reset();
+ }
+ this._outline = outline || null;
+ this._pdfDocument = pdfDocument || null;
+ if (!outline) {
+ this._dispatchEvent(0);
+ return;
+ }
+ const fragment = document.createDocumentFragment();
+ const queue = [{
+ parent: fragment,
+ items: outline
+ }];
+ let outlineCount = 0,
+ hasAnyNesting = false;
+ while (queue.length > 0) {
+ const levelData = queue.shift();
+ for (const item of levelData.items) {
+ const div = document.createElement("div");
+ div.className = "treeItem";
+ const element = document.createElement("a");
+ this._bindLink(element, item);
+ this._setStyles(element, item);
+ element.textContent = this._normalizeTextContent(item.title);
+ div.append(element);
+ if (item.items.length > 0) {
+ hasAnyNesting = true;
+ this._addToggleButton(div, item);
+ const itemsDiv = document.createElement("div");
+ itemsDiv.className = "treeItems";
+ div.append(itemsDiv);
+ queue.push({
+ parent: itemsDiv,
+ items: item.items
+ });
+ }
+ levelData.parent.append(div);
+ outlineCount++;
+ }
+ }
+ this._finishRendering(fragment, outlineCount, hasAnyNesting);
+ }
+ async _currentOutlineItem() {
+ if (!this._isPagesLoaded) {
+ throw new Error("_currentOutlineItem: All pages have not been loaded.");
+ }
+ if (!this._outline || !this._pdfDocument) {
+ return;
+ }
+ const pageNumberToDestHash = await this._getPageNumberToDestHash(this._pdfDocument);
+ if (!pageNumberToDestHash) {
+ return;
+ }
+ this._updateCurrentTreeItem(null);
+ if (this._sidebarView !== SidebarView.OUTLINE) {
+ return;
+ }
+ for (let i = this._currentPageNumber; i > 0; i--) {
+ const destHash = pageNumberToDestHash.get(i);
+ if (!destHash) {
+ continue;
+ }
+ const linkElement = this.container.querySelector(`a[href="${destHash}"]`);
+ if (!linkElement) {
+ continue;
+ }
+ this._scrollToCurrentTreeItem(linkElement.parentNode);
+ break;
+ }
+ }
+ async _getPageNumberToDestHash(pdfDocument) {
+ if (this._pageNumberToDestHashCapability) {
+ return this._pageNumberToDestHashCapability.promise;
+ }
+ this._pageNumberToDestHashCapability = new PromiseCapability();
+ const pageNumberToDestHash = new Map(),
+ pageNumberNesting = new Map();
+ const queue = [{
+ nesting: 0,
+ items: this._outline
+ }];
+ while (queue.length > 0) {
+ const levelData = queue.shift(),
+ currentNesting = levelData.nesting;
+ for (const {
+ dest,
+ items
+ } of levelData.items) {
+ let explicitDest, pageNumber;
+ if (typeof dest === "string") {
+ explicitDest = await pdfDocument.getDestination(dest);
+ if (pdfDocument !== this._pdfDocument) {
+ return null;
+ }
+ } else {
+ explicitDest = dest;
+ }
+ if (Array.isArray(explicitDest)) {
+ const [destRef] = explicitDest;
+ if (typeof destRef === "object" && destRef !== null) {
+ pageNumber = this.linkService._cachedPageNumber(destRef);
+ if (!pageNumber) {
+ try {
+ pageNumber = (await pdfDocument.getPageIndex(destRef)) + 1;
+ if (pdfDocument !== this._pdfDocument) {
+ return null;
+ }
+ this.linkService.cachePageRef(pageNumber, destRef);
+ } catch {}
+ }
+ } else if (Number.isInteger(destRef)) {
+ pageNumber = destRef + 1;
+ }
+ if (Number.isInteger(pageNumber) && (!pageNumberToDestHash.has(pageNumber) || currentNesting > pageNumberNesting.get(pageNumber))) {
+ const destHash = this.linkService.getDestinationHash(dest);
+ pageNumberToDestHash.set(pageNumber, destHash);
+ pageNumberNesting.set(pageNumber, currentNesting);
+ }
+ }
+ if (items.length > 0) {
+ queue.push({
+ nesting: currentNesting + 1,
+ items
+ });
+ }
+ }
+ }
+ this._pageNumberToDestHashCapability.resolve(pageNumberToDestHash.size > 0 ? pageNumberToDestHash : null);
+ return this._pageNumberToDestHashCapability.promise;
+ }
+}
+
+;// CONCATENATED MODULE: ./web/pdf_presentation_mode.js
+
+
+const DELAY_BEFORE_HIDING_CONTROLS = 3000;
+const ACTIVE_SELECTOR = "pdfPresentationMode";
+const CONTROLS_SELECTOR = "pdfPresentationModeControls";
+const MOUSE_SCROLL_COOLDOWN_TIME = 50;
+const PAGE_SWITCH_THRESHOLD = 0.1;
+const SWIPE_MIN_DISTANCE_THRESHOLD = 50;
+const SWIPE_ANGLE_THRESHOLD = Math.PI / 6;
+class PDFPresentationMode {
+ #state = PresentationModeState.UNKNOWN;
+ #args = null;
+ constructor({
+ container,
+ pdfViewer,
+ eventBus
+ }) {
+ this.container = container;
+ this.pdfViewer = pdfViewer;
+ this.eventBus = eventBus;
+ this.contextMenuOpen = false;
+ this.mouseScrollTimeStamp = 0;
+ this.mouseScrollDelta = 0;
+ this.touchSwipeState = null;
+ }
+ async request() {
+ const {
+ container,
+ pdfViewer
+ } = this;
+ if (this.active || !pdfViewer.pagesCount || !container.requestFullscreen) {
+ return false;
+ }
+ this.#addFullscreenChangeListeners();
+ this.#notifyStateChange(PresentationModeState.CHANGING);
+ const promise = container.requestFullscreen();
+ this.#args = {
+ pageNumber: pdfViewer.currentPageNumber,
+ scaleValue: pdfViewer.currentScaleValue,
+ scrollMode: pdfViewer.scrollMode,
+ spreadMode: null,
+ annotationEditorMode: null
+ };
+ if (pdfViewer.spreadMode !== SpreadMode.NONE && !(pdfViewer.pageViewsReady && pdfViewer.hasEqualPageSizes)) {
+ console.warn("Ignoring Spread modes when entering PresentationMode, " + "since the document may contain varying page sizes.");
+ this.#args.spreadMode = pdfViewer.spreadMode;
+ }
+ if (pdfViewer.annotationEditorMode !== AnnotationEditorType.DISABLE) {
+ this.#args.annotationEditorMode = pdfViewer.annotationEditorMode;
+ }
+ try {
+ await promise;
+ pdfViewer.focus();
+ return true;
+ } catch {
+ this.#removeFullscreenChangeListeners();
+ this.#notifyStateChange(PresentationModeState.NORMAL);
+ }
+ return false;
+ }
+ get active() {
+ return this.#state === PresentationModeState.CHANGING || this.#state === PresentationModeState.FULLSCREEN;
+ }
+ #mouseWheel(evt) {
+ if (!this.active) {
+ return;
+ }
+ evt.preventDefault();
+ const delta = normalizeWheelEventDelta(evt);
+ const currentTime = Date.now();
+ const storedTime = this.mouseScrollTimeStamp;
+ if (currentTime > storedTime && currentTime - storedTime < MOUSE_SCROLL_COOLDOWN_TIME) {
+ return;
+ }
+ if (this.mouseScrollDelta > 0 && delta < 0 || this.mouseScrollDelta < 0 && delta > 0) {
+ this.#resetMouseScrollState();
+ }
+ this.mouseScrollDelta += delta;
+ if (Math.abs(this.mouseScrollDelta) >= PAGE_SWITCH_THRESHOLD) {
+ const totalDelta = this.mouseScrollDelta;
+ this.#resetMouseScrollState();
+ const success = totalDelta > 0 ? this.pdfViewer.previousPage() : this.pdfViewer.nextPage();
+ if (success) {
+ this.mouseScrollTimeStamp = currentTime;
+ }
+ }
+ }
+ #notifyStateChange(state) {
+ this.#state = state;
+ this.eventBus.dispatch("presentationmodechanged", {
+ source: this,
+ state
+ });
+ }
+ #enter() {
+ this.#notifyStateChange(PresentationModeState.FULLSCREEN);
+ this.container.classList.add(ACTIVE_SELECTOR);
+ setTimeout(() => {
+ this.pdfViewer.scrollMode = ScrollMode.PAGE;
+ if (this.#args.spreadMode !== null) {
+ this.pdfViewer.spreadMode = SpreadMode.NONE;
+ }
+ this.pdfViewer.currentPageNumber = this.#args.pageNumber;
+ this.pdfViewer.currentScaleValue = "page-fit";
+ if (this.#args.annotationEditorMode !== null) {
+ this.pdfViewer.annotationEditorMode = {
+ mode: AnnotationEditorType.NONE
+ };
+ }
+ }, 0);
+ this.#addWindowListeners();
+ this.#showControls();
+ this.contextMenuOpen = false;
+ document.getSelection().empty();
+ }
+ #exit() {
+ const pageNumber = this.pdfViewer.currentPageNumber;
+ this.container.classList.remove(ACTIVE_SELECTOR);
+ setTimeout(() => {
+ this.#removeFullscreenChangeListeners();
+ this.#notifyStateChange(PresentationModeState.NORMAL);
+ this.pdfViewer.scrollMode = this.#args.scrollMode;
+ if (this.#args.spreadMode !== null) {
+ this.pdfViewer.spreadMode = this.#args.spreadMode;
+ }
+ this.pdfViewer.currentScaleValue = this.#args.scaleValue;
+ this.pdfViewer.currentPageNumber = pageNumber;
+ if (this.#args.annotationEditorMode !== null) {
+ this.pdfViewer.annotationEditorMode = {
+ mode: this.#args.annotationEditorMode
+ };
+ }
+ this.#args = null;
+ }, 0);
+ this.#removeWindowListeners();
+ this.#hideControls();
+ this.#resetMouseScrollState();
+ this.contextMenuOpen = false;
+ }
+ #mouseDown(evt) {
+ if (this.contextMenuOpen) {
+ this.contextMenuOpen = false;
+ evt.preventDefault();
+ return;
+ }
+ if (evt.button !== 0) {
+ return;
+ }
+ if (evt.target.href && evt.target.parentNode?.hasAttribute("data-internal-link")) {
+ return;
+ }
+ evt.preventDefault();
+ if (evt.shiftKey) {
+ this.pdfViewer.previousPage();
+ } else {
+ this.pdfViewer.nextPage();
+ }
+ }
+ #contextMenu() {
+ this.contextMenuOpen = true;
+ }
+ #showControls() {
+ if (this.controlsTimeout) {
+ clearTimeout(this.controlsTimeout);
+ } else {
+ this.container.classList.add(CONTROLS_SELECTOR);
+ }
+ this.controlsTimeout = setTimeout(() => {
+ this.container.classList.remove(CONTROLS_SELECTOR);
+ delete this.controlsTimeout;
+ }, DELAY_BEFORE_HIDING_CONTROLS);
+ }
+ #hideControls() {
+ if (!this.controlsTimeout) {
+ return;
+ }
+ clearTimeout(this.controlsTimeout);
+ this.container.classList.remove(CONTROLS_SELECTOR);
+ delete this.controlsTimeout;
+ }
+ #resetMouseScrollState() {
+ this.mouseScrollTimeStamp = 0;
+ this.mouseScrollDelta = 0;
+ }
+ #touchSwipe(evt) {
+ if (!this.active) {
+ return;
+ }
+ if (evt.touches.length > 1) {
+ this.touchSwipeState = null;
+ return;
+ }
+ switch (evt.type) {
+ case "touchstart":
+ this.touchSwipeState = {
+ startX: evt.touches[0].pageX,
+ startY: evt.touches[0].pageY,
+ endX: evt.touches[0].pageX,
+ endY: evt.touches[0].pageY
+ };
+ break;
+ case "touchmove":
+ if (this.touchSwipeState === null) {
+ return;
+ }
+ this.touchSwipeState.endX = evt.touches[0].pageX;
+ this.touchSwipeState.endY = evt.touches[0].pageY;
+ evt.preventDefault();
+ break;
+ case "touchend":
+ if (this.touchSwipeState === null) {
+ return;
+ }
+ let delta = 0;
+ const dx = this.touchSwipeState.endX - this.touchSwipeState.startX;
+ const dy = this.touchSwipeState.endY - this.touchSwipeState.startY;
+ const absAngle = Math.abs(Math.atan2(dy, dx));
+ if (Math.abs(dx) > SWIPE_MIN_DISTANCE_THRESHOLD && (absAngle <= SWIPE_ANGLE_THRESHOLD || absAngle >= Math.PI - SWIPE_ANGLE_THRESHOLD)) {
+ delta = dx;
+ } else if (Math.abs(dy) > SWIPE_MIN_DISTANCE_THRESHOLD && Math.abs(absAngle - Math.PI / 2) <= SWIPE_ANGLE_THRESHOLD) {
+ delta = dy;
+ }
+ if (delta > 0) {
+ this.pdfViewer.previousPage();
+ } else if (delta < 0) {
+ this.pdfViewer.nextPage();
+ }
+ break;
+ }
+ }
+ #addWindowListeners() {
+ this.showControlsBind = this.#showControls.bind(this);
+ this.mouseDownBind = this.#mouseDown.bind(this);
+ this.mouseWheelBind = this.#mouseWheel.bind(this);
+ this.resetMouseScrollStateBind = this.#resetMouseScrollState.bind(this);
+ this.contextMenuBind = this.#contextMenu.bind(this);
+ this.touchSwipeBind = this.#touchSwipe.bind(this);
+ window.addEventListener("mousemove", this.showControlsBind);
+ window.addEventListener("mousedown", this.mouseDownBind);
+ window.addEventListener("wheel", this.mouseWheelBind, {
+ passive: false
+ });
+ window.addEventListener("keydown", this.resetMouseScrollStateBind);
+ window.addEventListener("contextmenu", this.contextMenuBind);
+ window.addEventListener("touchstart", this.touchSwipeBind);
+ window.addEventListener("touchmove", this.touchSwipeBind);
+ window.addEventListener("touchend", this.touchSwipeBind);
+ }
+ #removeWindowListeners() {
+ window.removeEventListener("mousemove", this.showControlsBind);
+ window.removeEventListener("mousedown", this.mouseDownBind);
+ window.removeEventListener("wheel", this.mouseWheelBind, {
+ passive: false
+ });
+ window.removeEventListener("keydown", this.resetMouseScrollStateBind);
+ window.removeEventListener("contextmenu", this.contextMenuBind);
+ window.removeEventListener("touchstart", this.touchSwipeBind);
+ window.removeEventListener("touchmove", this.touchSwipeBind);
+ window.removeEventListener("touchend", this.touchSwipeBind);
+ delete this.showControlsBind;
+ delete this.mouseDownBind;
+ delete this.mouseWheelBind;
+ delete this.resetMouseScrollStateBind;
+ delete this.contextMenuBind;
+ delete this.touchSwipeBind;
+ }
+ #fullscreenChange() {
+ if (document.fullscreenElement) {
+ this.#enter();
+ } else {
+ this.#exit();
+ }
+ }
+ #addFullscreenChangeListeners() {
+ this.fullscreenChangeBind = this.#fullscreenChange.bind(this);
+ window.addEventListener("fullscreenchange", this.fullscreenChangeBind);
+ }
+ #removeFullscreenChangeListeners() {
+ window.removeEventListener("fullscreenchange", this.fullscreenChangeBind);
+ delete this.fullscreenChangeBind;
+ }
+}
+
+;// CONCATENATED MODULE: ./web/xfa_layer_builder.js
+
+class XfaLayerBuilder {
+ constructor({
+ pdfPage,
+ annotationStorage = null,
+ linkService,
+ xfaHtml = null
+ }) {
+ this.pdfPage = pdfPage;
+ this.annotationStorage = annotationStorage;
+ this.linkService = linkService;
+ this.xfaHtml = xfaHtml;
+ this.div = null;
+ this._cancelled = false;
+ }
+ async render(viewport, intent = "display") {
+ if (intent === "print") {
+ const parameters = {
+ viewport: viewport.clone({
+ dontFlip: true
+ }),
+ div: this.div,
+ xfaHtml: this.xfaHtml,
+ annotationStorage: this.annotationStorage,
+ linkService: this.linkService,
+ intent
+ };
+ this.div = document.createElement("div");
+ parameters.div = this.div;
+ return XfaLayer.render(parameters);
+ }
+ const xfaHtml = await this.pdfPage.getXfa();
+ if (this._cancelled || !xfaHtml) {
+ return {
+ textDivs: []
+ };
+ }
+ const parameters = {
+ viewport: viewport.clone({
+ dontFlip: true
+ }),
+ div: this.div,
+ xfaHtml,
+ annotationStorage: this.annotationStorage,
+ linkService: this.linkService,
+ intent
+ };
+ if (this.div) {
+ return XfaLayer.update(parameters);
+ }
+ this.div = document.createElement("div");
+ parameters.div = this.div;
+ return XfaLayer.render(parameters);
+ }
+ cancel() {
+ this._cancelled = true;
+ }
+ hide() {
+ if (!this.div) {
+ return;
+ }
+ this.div.hidden = true;
+ }
+}
+
+;// CONCATENATED MODULE: ./web/print_utils.js
+
+
+
+function getXfaHtmlForPrinting(printContainer, pdfDocument) {
+ const xfaHtml = pdfDocument.allXfaHtml;
+ const linkService = new SimpleLinkService();
+ const scale = Math.round(PixelsPerInch.PDF_TO_CSS_UNITS * 100) / 100;
+ for (const xfaPage of xfaHtml.children) {
+ const page = document.createElement("div");
+ page.className = "xfaPrintedPage";
+ printContainer.append(page);
+ const builder = new XfaLayerBuilder({
+ pdfPage: null,
+ annotationStorage: pdfDocument.annotationStorage,
+ linkService,
+ xfaHtml: xfaPage
+ });
+ const viewport = getXfaPageViewport(xfaPage, {
+ scale
+ });
+ builder.render(viewport, "print");
+ page.append(builder.div);
+ }
+}
+
+;// CONCATENATED MODULE: ./web/firefox_print_service.js
+
+
+function composePage(pdfDocument, pageNumber, size, printContainer, printResolution, optionalContentConfigPromise, printAnnotationStoragePromise) {
+ const canvas = document.createElement("canvas");
+ const PRINT_UNITS = printResolution / PixelsPerInch.PDF;
+ canvas.width = Math.floor(size.width * PRINT_UNITS);
+ canvas.height = Math.floor(size.height * PRINT_UNITS);
+ const canvasWrapper = document.createElement("div");
+ canvasWrapper.className = "printedPage";
+ canvasWrapper.append(canvas);
+ printContainer.append(canvasWrapper);
+ let currentRenderTask = null;
+ canvas.mozPrintCallback = function (obj) {
+ const ctx = obj.context;
+ ctx.save();
+ ctx.fillStyle = "rgb(255, 255, 255)";
+ ctx.fillRect(0, 0, canvas.width, canvas.height);
+ ctx.restore();
+ let thisRenderTask = null;
+ Promise.all([pdfDocument.getPage(pageNumber), printAnnotationStoragePromise]).then(function ([pdfPage, printAnnotationStorage]) {
+ if (currentRenderTask) {
+ currentRenderTask.cancel();
+ currentRenderTask = null;
+ }
+ const renderContext = {
+ canvasContext: ctx,
+ transform: [PRINT_UNITS, 0, 0, PRINT_UNITS, 0, 0],
+ viewport: pdfPage.getViewport({
+ scale: 1,
+ rotation: size.rotation
+ }),
+ intent: "print",
+ annotationMode: AnnotationMode.ENABLE_STORAGE,
+ optionalContentConfigPromise,
+ printAnnotationStorage
+ };
+ currentRenderTask = thisRenderTask = pdfPage.render(renderContext);
+ return thisRenderTask.promise;
+ }).then(function () {
+ if (currentRenderTask === thisRenderTask) {
+ currentRenderTask = null;
+ }
+ obj.done();
+ }, function (reason) {
+ if (!(reason instanceof RenderingCancelledException)) {
+ console.error(reason);
+ }
+ if (currentRenderTask === thisRenderTask) {
+ currentRenderTask.cancel();
+ currentRenderTask = null;
+ }
+ if ("abort" in obj) {
+ obj.abort();
+ } else {
+ obj.done();
+ }
+ });
+ };
+}
+class FirefoxPrintService {
+ constructor({
+ pdfDocument,
+ pagesOverview,
+ printContainer,
+ printResolution,
+ optionalContentConfigPromise = null,
+ printAnnotationStoragePromise = null
+ }) {
+ this.pdfDocument = pdfDocument;
+ this.pagesOverview = pagesOverview;
+ this.printContainer = printContainer;
+ this._printResolution = printResolution || 150;
+ this._optionalContentConfigPromise = optionalContentConfigPromise || pdfDocument.getOptionalContentConfig();
+ this._printAnnotationStoragePromise = printAnnotationStoragePromise || Promise.resolve();
+ }
+ layout() {
+ const {
+ pdfDocument,
+ pagesOverview,
+ printContainer,
+ _printResolution,
+ _optionalContentConfigPromise,
+ _printAnnotationStoragePromise
+ } = this;
+ const body = document.querySelector("body");
+ body.setAttribute("data-pdfjsprinting", true);
+ const {
+ width,
+ height
+ } = this.pagesOverview[0];
+ const hasEqualPageSizes = this.pagesOverview.every(size => size.width === width && size.height === height);
+ if (!hasEqualPageSizes) {
+ console.warn("Not all pages have the same size. The printed result may be incorrect!");
+ }
+ this.pageStyleSheet = document.createElement("style");
+ this.pageStyleSheet.textContent = `@page { size: ${width}pt ${height}pt;}`;
+ body.append(this.pageStyleSheet);
+ if (pdfDocument.isPureXfa) {
+ getXfaHtmlForPrinting(printContainer, pdfDocument);
+ return;
+ }
+ for (let i = 0, ii = pagesOverview.length; i < ii; ++i) {
+ composePage(pdfDocument, i + 1, pagesOverview[i], printContainer, _printResolution, _optionalContentConfigPromise, _printAnnotationStoragePromise);
+ }
+ }
+ destroy() {
+ this.printContainer.textContent = "";
+ const body = document.querySelector("body");
+ body.removeAttribute("data-pdfjsprinting");
+ if (this.pageStyleSheet) {
+ this.pageStyleSheet.remove();
+ this.pageStyleSheet = null;
+ }
+ }
+}
+class PDFPrintServiceFactory {
+ static get supportsPrinting() {
+ const canvas = document.createElement("canvas");
+ return shadow(this, "supportsPrinting", "mozPrintCallback" in canvas);
+ }
+ static createPrintService(params) {
+ return new FirefoxPrintService(params);
+ }
+}
+
+;// CONCATENATED MODULE: ./web/pdf_rendering_queue.js
+
+
+const CLEANUP_TIMEOUT = 30000;
+class PDFRenderingQueue {
+ constructor() {
+ this.pdfViewer = null;
+ this.pdfThumbnailViewer = null;
+ this.onIdle = null;
+ this.highestPriorityPage = null;
+ this.idleTimeout = null;
+ this.printing = false;
+ this.isThumbnailViewEnabled = false;
+ }
+ setViewer(pdfViewer) {
+ this.pdfViewer = pdfViewer;
+ }
+ setThumbnailViewer(pdfThumbnailViewer) {
+ this.pdfThumbnailViewer = pdfThumbnailViewer;
+ }
+ isHighestPriority(view) {
+ return this.highestPriorityPage === view.renderingId;
+ }
+ renderHighestPriority(currentlyVisiblePages) {
+ if (this.idleTimeout) {
+ clearTimeout(this.idleTimeout);
+ this.idleTimeout = null;
+ }
+ if (this.pdfViewer.forceRendering(currentlyVisiblePages)) {
+ return;
+ }
+ if (this.isThumbnailViewEnabled && this.pdfThumbnailViewer?.forceRendering()) {
+ return;
+ }
+ if (this.printing) {
+ return;
+ }
+ if (this.onIdle) {
+ this.idleTimeout = setTimeout(this.onIdle.bind(this), CLEANUP_TIMEOUT);
+ }
+ }
+ getHighestPriority(visible, views, scrolledDown, preRenderExtra = false) {
+ const visibleViews = visible.views,
+ numVisible = visibleViews.length;
+ if (numVisible === 0) {
+ return null;
+ }
+ for (let i = 0; i < numVisible; i++) {
+ const view = visibleViews[i].view;
+ if (!this.isViewFinished(view)) {
+ return view;
+ }
+ }
+ const firstId = visible.first.id,
+ lastId = visible.last.id;
+ if (lastId - firstId + 1 > numVisible) {
+ const visibleIds = visible.ids;
+ for (let i = 1, ii = lastId - firstId; i < ii; i++) {
+ const holeId = scrolledDown ? firstId + i : lastId - i;
+ if (visibleIds.has(holeId)) {
+ continue;
+ }
+ const holeView = views[holeId - 1];
+ if (!this.isViewFinished(holeView)) {
+ return holeView;
+ }
+ }
+ }
+ let preRenderIndex = scrolledDown ? lastId : firstId - 2;
+ let preRenderView = views[preRenderIndex];
+ if (preRenderView && !this.isViewFinished(preRenderView)) {
+ return preRenderView;
+ }
+ if (preRenderExtra) {
+ preRenderIndex += scrolledDown ? 1 : -1;
+ preRenderView = views[preRenderIndex];
+ if (preRenderView && !this.isViewFinished(preRenderView)) {
+ return preRenderView;
+ }
+ }
+ return null;
+ }
+ isViewFinished(view) {
+ return view.renderingState === RenderingStates.FINISHED;
+ }
+ renderView(view) {
+ switch (view.renderingState) {
+ case RenderingStates.FINISHED:
+ return false;
+ case RenderingStates.PAUSED:
+ this.highestPriorityPage = view.renderingId;
+ view.resume();
+ break;
+ case RenderingStates.RUNNING:
+ this.highestPriorityPage = view.renderingId;
+ break;
+ case RenderingStates.INITIAL:
+ this.highestPriorityPage = view.renderingId;
+ view.draw().finally(() => {
+ this.renderHighestPriority();
+ }).catch(reason => {
+ if (reason instanceof RenderingCancelledException) {
+ return;
+ }
+ console.error(`renderView: "${reason}"`);
+ });
+ break;
+ }
+ return true;
+ }
+}
+
+;// CONCATENATED MODULE: ./web/pdf_scripting_manager.js
+
+
+class PDFScriptingManager {
+ #closeCapability = null;
+ #destroyCapability = null;
+ #docProperties = null;
+ #eventBus = null;
+ #externalServices = null;
+ #pdfDocument = null;
+ #pdfViewer = null;
+ #ready = false;
+ #scripting = null;
+ #willPrintCapability = null;
+ constructor({
+ eventBus,
+ externalServices = null,
+ docProperties = null
+ }) {
+ this.#eventBus = eventBus;
+ this.#externalServices = externalServices;
+ this.#docProperties = docProperties;
+ }
+ setViewer(pdfViewer) {
+ this.#pdfViewer = pdfViewer;
+ }
+ async setDocument(pdfDocument) {
+ if (this.#pdfDocument) {
+ await this.#destroyScripting();
+ }
+ this.#pdfDocument = pdfDocument;
+ if (!pdfDocument) {
+ return;
+ }
+ const [objects, calculationOrder, docActions] = await Promise.all([pdfDocument.getFieldObjects(), pdfDocument.getCalculationOrderIds(), pdfDocument.getJSActions()]);
+ if (!objects && !docActions) {
+ await this.#destroyScripting();
+ return;
+ }
+ if (pdfDocument !== this.#pdfDocument) {
+ return;
+ }
+ try {
+ this.#scripting = this.#initScripting();
+ } catch (error) {
+ console.error(`setDocument: "${error.message}".`);
+ await this.#destroyScripting();
+ return;
+ }
+ this._internalEvents.set("updatefromsandbox", event => {
+ if (event?.source === window) {
+ this.#updateFromSandbox(event.detail);
+ }
+ });
+ this._internalEvents.set("dispatcheventinsandbox", event => {
+ this.#scripting?.dispatchEventInSandbox(event.detail);
+ });
+ this._internalEvents.set("pagechanging", ({
+ pageNumber,
+ previous
+ }) => {
+ if (pageNumber === previous) {
+ return;
+ }
+ this.#dispatchPageClose(previous);
+ this.#dispatchPageOpen(pageNumber);
+ });
+ this._internalEvents.set("pagerendered", ({
+ pageNumber
+ }) => {
+ if (!this._pageOpenPending.has(pageNumber)) {
+ return;
+ }
+ if (pageNumber !== this.#pdfViewer.currentPageNumber) {
+ return;
+ }
+ this.#dispatchPageOpen(pageNumber);
+ });
+ this._internalEvents.set("pagesdestroy", async () => {
+ await this.#dispatchPageClose(this.#pdfViewer.currentPageNumber);
+ await this.#scripting?.dispatchEventInSandbox({
+ id: "doc",
+ name: "WillClose"
+ });
+ this.#closeCapability?.resolve();
+ });
+ for (const [name, listener] of this._internalEvents) {
+ this.#eventBus._on(name, listener);
+ }
+ try {
+ const docProperties = await this.#docProperties(pdfDocument);
+ if (pdfDocument !== this.#pdfDocument) {
+ return;
+ }
+ await this.#scripting.createSandbox({
+ objects,
+ calculationOrder,
+ appInfo: {
+ platform: navigator.platform,
+ language: navigator.language
+ },
+ docInfo: {
+ ...docProperties,
+ actions: docActions
+ }
+ });
+ this.#eventBus.dispatch("sandboxcreated", {
+ source: this
+ });
+ } catch (error) {
+ console.error(`setDocument: "${error.message}".`);
+ await this.#destroyScripting();
+ return;
+ }
+ await this.#scripting?.dispatchEventInSandbox({
+ id: "doc",
+ name: "Open"
+ });
+ await this.#dispatchPageOpen(this.#pdfViewer.currentPageNumber, true);
+ Promise.resolve().then(() => {
+ if (pdfDocument === this.#pdfDocument) {
+ this.#ready = true;
+ }
+ });
+ }
+ async dispatchWillSave() {
+ return this.#scripting?.dispatchEventInSandbox({
+ id: "doc",
+ name: "WillSave"
+ });
+ }
+ async dispatchDidSave() {
+ return this.#scripting?.dispatchEventInSandbox({
+ id: "doc",
+ name: "DidSave"
+ });
+ }
+ async dispatchWillPrint() {
+ if (!this.#scripting) {
+ return;
+ }
+ await this.#willPrintCapability?.promise;
+ this.#willPrintCapability = new PromiseCapability();
+ try {
+ await this.#scripting.dispatchEventInSandbox({
+ id: "doc",
+ name: "WillPrint"
+ });
+ } catch (ex) {
+ this.#willPrintCapability.resolve();
+ this.#willPrintCapability = null;
+ throw ex;
+ }
+ await this.#willPrintCapability.promise;
+ }
+ async dispatchDidPrint() {
+ return this.#scripting?.dispatchEventInSandbox({
+ id: "doc",
+ name: "DidPrint"
+ });
+ }
+ get destroyPromise() {
+ return this.#destroyCapability?.promise || null;
+ }
+ get ready() {
+ return this.#ready;
+ }
+ get _internalEvents() {
+ return shadow(this, "_internalEvents", new Map());
+ }
+ get _pageOpenPending() {
+ return shadow(this, "_pageOpenPending", new Set());
+ }
+ get _visitedPages() {
+ return shadow(this, "_visitedPages", new Map());
+ }
+ async #updateFromSandbox(detail) {
+ const pdfViewer = this.#pdfViewer;
+ const isInPresentationMode = pdfViewer.isInPresentationMode || pdfViewer.isChangingPresentationMode;
+ const {
+ id,
+ siblings,
+ command,
+ value
+ } = detail;
+ if (!id) {
+ switch (command) {
+ case "clear":
+ console.clear();
+ break;
+ case "error":
+ console.error(value);
+ break;
+ case "layout":
+ if (!isInPresentationMode) {
+ const modes = apiPageLayoutToViewerModes(value);
+ pdfViewer.spreadMode = modes.spreadMode;
+ }
+ break;
+ case "page-num":
+ pdfViewer.currentPageNumber = value + 1;
+ break;
+ case "print":
+ await pdfViewer.pagesPromise;
+ this.#eventBus.dispatch("print", {
+ source: this
+ });
+ break;
+ case "println":
+ console.log(value);
+ break;
+ case "zoom":
+ if (!isInPresentationMode) {
+ pdfViewer.currentScaleValue = value;
+ }
+ break;
+ case "SaveAs":
+ this.#eventBus.dispatch("download", {
+ source: this
+ });
+ break;
+ case "FirstPage":
+ pdfViewer.currentPageNumber = 1;
+ break;
+ case "LastPage":
+ pdfViewer.currentPageNumber = pdfViewer.pagesCount;
+ break;
+ case "NextPage":
+ pdfViewer.nextPage();
+ break;
+ case "PrevPage":
+ pdfViewer.previousPage();
+ break;
+ case "ZoomViewIn":
+ if (!isInPresentationMode) {
+ pdfViewer.increaseScale();
+ }
+ break;
+ case "ZoomViewOut":
+ if (!isInPresentationMode) {
+ pdfViewer.decreaseScale();
+ }
+ break;
+ case "WillPrintFinished":
+ this.#willPrintCapability?.resolve();
+ this.#willPrintCapability = null;
+ break;
+ }
+ return;
+ }
+ if (isInPresentationMode && detail.focus) {
+ return;
+ }
+ delete detail.id;
+ delete detail.siblings;
+ const ids = siblings ? [id, ...siblings] : [id];
+ for (const elementId of ids) {
+ const element = document.querySelector(`[data-element-id="${elementId}"]`);
+ if (element) {
+ element.dispatchEvent(new CustomEvent("updatefromsandbox", {
+ detail
+ }));
+ } else {
+ this.#pdfDocument?.annotationStorage.setValue(elementId, detail);
+ }
+ }
+ }
+ async #dispatchPageOpen(pageNumber, initialize = false) {
+ const pdfDocument = this.#pdfDocument,
+ visitedPages = this._visitedPages;
+ if (initialize) {
+ this.#closeCapability = new PromiseCapability();
+ }
+ if (!this.#closeCapability) {
+ return;
+ }
+ const pageView = this.#pdfViewer.getPageView(pageNumber - 1);
+ if (pageView?.renderingState !== RenderingStates.FINISHED) {
+ this._pageOpenPending.add(pageNumber);
+ return;
+ }
+ this._pageOpenPending.delete(pageNumber);
+ const actionsPromise = (async () => {
+ const actions = await (!visitedPages.has(pageNumber) ? pageView.pdfPage?.getJSActions() : null);
+ if (pdfDocument !== this.#pdfDocument) {
+ return;
+ }
+ await this.#scripting?.dispatchEventInSandbox({
+ id: "page",
+ name: "PageOpen",
+ pageNumber,
+ actions
+ });
+ })();
+ visitedPages.set(pageNumber, actionsPromise);
+ }
+ async #dispatchPageClose(pageNumber) {
+ const pdfDocument = this.#pdfDocument,
+ visitedPages = this._visitedPages;
+ if (!this.#closeCapability) {
+ return;
+ }
+ if (this._pageOpenPending.has(pageNumber)) {
+ return;
+ }
+ const actionsPromise = visitedPages.get(pageNumber);
+ if (!actionsPromise) {
+ return;
+ }
+ visitedPages.set(pageNumber, null);
+ await actionsPromise;
+ if (pdfDocument !== this.#pdfDocument) {
+ return;
+ }
+ await this.#scripting?.dispatchEventInSandbox({
+ id: "page",
+ name: "PageClose",
+ pageNumber
+ });
+ }
+ #initScripting() {
+ this.#destroyCapability = new PromiseCapability();
+ if (this.#scripting) {
+ throw new Error("#initScripting: Scripting already exists.");
+ }
+ return this.#externalServices.createScripting();
+ }
+ async #destroyScripting() {
+ if (!this.#scripting) {
+ this.#pdfDocument = null;
+ this.#destroyCapability?.resolve();
+ return;
+ }
+ if (this.#closeCapability) {
+ await Promise.race([this.#closeCapability.promise, new Promise(resolve => {
+ setTimeout(resolve, 1000);
+ })]).catch(() => {});
+ this.#closeCapability = null;
+ }
+ this.#pdfDocument = null;
+ try {
+ await this.#scripting.destroySandbox();
+ } catch {}
+ this.#willPrintCapability?.reject(new Error("Scripting destroyed."));
+ this.#willPrintCapability = null;
+ for (const [name, listener] of this._internalEvents) {
+ this.#eventBus._off(name, listener);
+ }
+ this._internalEvents.clear();
+ this._pageOpenPending.clear();
+ this._visitedPages.clear();
+ this.#scripting = null;
+ this.#ready = false;
+ this.#destroyCapability?.resolve();
+ }
+}
+
+;// CONCATENATED MODULE: ./web/pdf_sidebar.js
+
+const SIDEBAR_WIDTH_VAR = "--sidebar-width";
+const SIDEBAR_MIN_WIDTH = 200;
+const SIDEBAR_RESIZING_CLASS = "sidebarResizing";
+const UI_NOTIFICATION_CLASS = "pdfSidebarNotification";
+class PDFSidebar {
+ #isRTL = false;
+ #mouseMoveBound = this.#mouseMove.bind(this);
+ #mouseUpBound = this.#mouseUp.bind(this);
+ #outerContainerWidth = null;
+ #width = null;
+ constructor({
+ elements,
+ eventBus,
+ l10n
+ }) {
+ this.isOpen = false;
+ this.active = SidebarView.THUMBS;
+ this.isInitialViewSet = false;
+ this.isInitialEventDispatched = false;
+ this.onToggled = null;
+ this.onUpdateThumbnails = null;
+ this.outerContainer = elements.outerContainer;
+ this.sidebarContainer = elements.sidebarContainer;
+ this.toggleButton = elements.toggleButton;
+ this.resizer = elements.resizer;
+ this.thumbnailButton = elements.thumbnailButton;
+ this.outlineButton = elements.outlineButton;
+ this.attachmentsButton = elements.attachmentsButton;
+ this.layersButton = elements.layersButton;
+ this.thumbnailView = elements.thumbnailView;
+ this.outlineView = elements.outlineView;
+ this.attachmentsView = elements.attachmentsView;
+ this.layersView = elements.layersView;
+ this._currentOutlineItemButton = elements.currentOutlineItemButton;
+ this.eventBus = eventBus;
+ this.#isRTL = l10n.getDirection() === "rtl";
+ this.#addEventListeners();
+ }
+ reset() {
+ this.isInitialViewSet = false;
+ this.isInitialEventDispatched = false;
+ this.#hideUINotification(true);
+ this.switchView(SidebarView.THUMBS);
+ this.outlineButton.disabled = false;
+ this.attachmentsButton.disabled = false;
+ this.layersButton.disabled = false;
+ this._currentOutlineItemButton.disabled = true;
+ }
+ get visibleView() {
+ return this.isOpen ? this.active : SidebarView.NONE;
+ }
+ setInitialView(view = SidebarView.NONE) {
+ if (this.isInitialViewSet) {
+ return;
+ }
+ this.isInitialViewSet = true;
+ if (view === SidebarView.NONE || view === SidebarView.UNKNOWN) {
+ this.#dispatchEvent();
+ return;
+ }
+ this.switchView(view, true);
+ if (!this.isInitialEventDispatched) {
+ this.#dispatchEvent();
+ }
+ }
+ switchView(view, forceOpen = false) {
+ const isViewChanged = view !== this.active;
+ let forceRendering = false;
+ switch (view) {
+ case SidebarView.NONE:
+ if (this.isOpen) {
+ this.close();
+ }
+ return;
+ case SidebarView.THUMBS:
+ if (this.isOpen && isViewChanged) {
+ forceRendering = true;
+ }
+ break;
+ case SidebarView.OUTLINE:
+ if (this.outlineButton.disabled) {
+ return;
+ }
+ break;
+ case SidebarView.ATTACHMENTS:
+ if (this.attachmentsButton.disabled) {
+ return;
+ }
+ break;
+ case SidebarView.LAYERS:
+ if (this.layersButton.disabled) {
+ return;
+ }
+ break;
+ default:
+ console.error(`PDFSidebar.switchView: "${view}" is not a valid view.`);
+ return;
+ }
+ this.active = view;
+ toggleCheckedBtn(this.thumbnailButton, view === SidebarView.THUMBS, this.thumbnailView);
+ toggleCheckedBtn(this.outlineButton, view === SidebarView.OUTLINE, this.outlineView);
+ toggleCheckedBtn(this.attachmentsButton, view === SidebarView.ATTACHMENTS, this.attachmentsView);
+ toggleCheckedBtn(this.layersButton, view === SidebarView.LAYERS, this.layersView);
+ if (forceOpen && !this.isOpen) {
+ this.open();
+ return;
+ }
+ if (forceRendering) {
+ this.onUpdateThumbnails();
+ this.onToggled();
+ }
+ if (isViewChanged) {
+ this.#dispatchEvent();
+ }
+ }
+ open() {
+ if (this.isOpen) {
+ return;
+ }
+ this.isOpen = true;
+ toggleExpandedBtn(this.toggleButton, true);
+ this.outerContainer.classList.add("sidebarMoving", "sidebarOpen");
+ if (this.active === SidebarView.THUMBS) {
+ this.onUpdateThumbnails();
+ }
+ this.onToggled();
+ this.#dispatchEvent();
+ this.#hideUINotification();
+ }
+ close(evt = null) {
+ if (!this.isOpen) {
+ return;
+ }
+ this.isOpen = false;
+ toggleExpandedBtn(this.toggleButton, false);
+ this.outerContainer.classList.add("sidebarMoving");
+ this.outerContainer.classList.remove("sidebarOpen");
+ this.onToggled();
+ this.#dispatchEvent();
+ if (evt?.detail > 0) {
+ this.toggleButton.blur();
+ }
+ }
+ toggle(evt = null) {
+ if (this.isOpen) {
+ this.close(evt);
+ } else {
+ this.open();
+ }
+ }
+ #dispatchEvent() {
+ if (this.isInitialViewSet) {
+ this.isInitialEventDispatched ||= true;
+ }
+ this.eventBus.dispatch("sidebarviewchanged", {
+ source: this,
+ view: this.visibleView
+ });
+ }
+ #showUINotification() {
+ this.toggleButton.setAttribute("data-l10n-id", "pdfjs-toggle-sidebar-notification-button");
+ if (!this.isOpen) {
+ this.toggleButton.classList.add(UI_NOTIFICATION_CLASS);
+ }
+ }
+ #hideUINotification(reset = false) {
+ if (this.isOpen || reset) {
+ this.toggleButton.classList.remove(UI_NOTIFICATION_CLASS);
+ }
+ if (reset) {
+ this.toggleButton.setAttribute("data-l10n-id", "pdfjs-toggle-sidebar-button");
+ }
+ }
+ #addEventListeners() {
+ this.sidebarContainer.addEventListener("transitionend", evt => {
+ if (evt.target === this.sidebarContainer) {
+ this.outerContainer.classList.remove("sidebarMoving");
+ this.eventBus.dispatch("resize", {
+ source: this
+ });
+ }
+ });
+ this.toggleButton.addEventListener("click", evt => {
+ this.toggle(evt);
+ });
+ this.thumbnailButton.addEventListener("click", () => {
+ this.switchView(SidebarView.THUMBS);
+ });
+ this.outlineButton.addEventListener("click", () => {
+ this.switchView(SidebarView.OUTLINE);
+ });
+ this.outlineButton.addEventListener("dblclick", () => {
+ this.eventBus.dispatch("toggleoutlinetree", {
+ source: this
+ });
+ });
+ this.attachmentsButton.addEventListener("click", () => {
+ this.switchView(SidebarView.ATTACHMENTS);
+ });
+ this.layersButton.addEventListener("click", () => {
+ this.switchView(SidebarView.LAYERS);
+ });
+ this.layersButton.addEventListener("dblclick", () => {
+ this.eventBus.dispatch("resetlayers", {
+ source: this
+ });
+ });
+ this._currentOutlineItemButton.addEventListener("click", () => {
+ this.eventBus.dispatch("currentoutlineitem", {
+ source: this
+ });
+ });
+ const onTreeLoaded = (count, button, view) => {
+ button.disabled = !count;
+ if (count) {
+ this.#showUINotification();
+ } else if (this.active === view) {
+ this.switchView(SidebarView.THUMBS);
+ }
+ };
+ this.eventBus._on("outlineloaded", evt => {
+ onTreeLoaded(evt.outlineCount, this.outlineButton, SidebarView.OUTLINE);
+ evt.currentOutlineItemPromise.then(enabled => {
+ if (!this.isInitialViewSet) {
+ return;
+ }
+ this._currentOutlineItemButton.disabled = !enabled;
+ });
+ });
+ this.eventBus._on("attachmentsloaded", evt => {
+ onTreeLoaded(evt.attachmentsCount, this.attachmentsButton, SidebarView.ATTACHMENTS);
+ });
+ this.eventBus._on("layersloaded", evt => {
+ onTreeLoaded(evt.layersCount, this.layersButton, SidebarView.LAYERS);
+ });
+ this.eventBus._on("presentationmodechanged", evt => {
+ if (evt.state === PresentationModeState.NORMAL && this.visibleView === SidebarView.THUMBS) {
+ this.onUpdateThumbnails();
+ }
+ });
+ this.resizer.addEventListener("mousedown", evt => {
+ if (evt.button !== 0) {
+ return;
+ }
+ this.outerContainer.classList.add(SIDEBAR_RESIZING_CLASS);
+ window.addEventListener("mousemove", this.#mouseMoveBound);
+ window.addEventListener("mouseup", this.#mouseUpBound);
+ });
+ this.eventBus._on("resize", evt => {
+ if (evt.source !== window) {
+ return;
+ }
+ this.#outerContainerWidth = null;
+ if (!this.#width) {
+ return;
+ }
+ if (!this.isOpen) {
+ this.#updateWidth(this.#width);
+ return;
+ }
+ this.outerContainer.classList.add(SIDEBAR_RESIZING_CLASS);
+ const updated = this.#updateWidth(this.#width);
+ Promise.resolve().then(() => {
+ this.outerContainer.classList.remove(SIDEBAR_RESIZING_CLASS);
+ if (updated) {
+ this.eventBus.dispatch("resize", {
+ source: this
+ });
+ }
+ });
+ });
+ }
+ get outerContainerWidth() {
+ return this.#outerContainerWidth ||= this.outerContainer.clientWidth;
+ }
+ #updateWidth(width = 0) {
+ const maxWidth = Math.floor(this.outerContainerWidth / 2);
+ if (width > maxWidth) {
+ width = maxWidth;
+ }
+ if (width < SIDEBAR_MIN_WIDTH) {
+ width = SIDEBAR_MIN_WIDTH;
+ }
+ if (width === this.#width) {
+ return false;
+ }
+ this.#width = width;
+ docStyle.setProperty(SIDEBAR_WIDTH_VAR, `${width}px`);
+ return true;
+ }
+ #mouseMove(evt) {
+ let width = evt.clientX;
+ if (this.#isRTL) {
+ width = this.outerContainerWidth - width;
+ }
+ this.#updateWidth(width);
+ }
+ #mouseUp(evt) {
+ this.outerContainer.classList.remove(SIDEBAR_RESIZING_CLASS);
+ this.eventBus.dispatch("resize", {
+ source: this
+ });
+ window.removeEventListener("mousemove", this.#mouseMoveBound);
+ window.removeEventListener("mouseup", this.#mouseUpBound);
+ }
+}
+
+;// CONCATENATED MODULE: ./web/pdf_thumbnail_view.js
+
+
+const DRAW_UPSCALE_FACTOR = 2;
+const MAX_NUM_SCALING_STEPS = 3;
+const THUMBNAIL_WIDTH = 98;
+class TempImageFactory {
+ static #tempCanvas = null;
+ static getCanvas(width, height) {
+ const tempCanvas = this.#tempCanvas ||= document.createElement("canvas");
+ tempCanvas.width = width;
+ tempCanvas.height = height;
+ const ctx = tempCanvas.getContext("2d", {
+ alpha: false
+ });
+ ctx.save();
+ ctx.fillStyle = "rgb(255, 255, 255)";
+ ctx.fillRect(0, 0, width, height);
+ ctx.restore();
+ return [tempCanvas, tempCanvas.getContext("2d")];
+ }
+ static destroyCanvas() {
+ const tempCanvas = this.#tempCanvas;
+ if (tempCanvas) {
+ tempCanvas.width = 0;
+ tempCanvas.height = 0;
+ }
+ this.#tempCanvas = null;
+ }
+}
+class PDFThumbnailView {
+ constructor({
+ container,
+ eventBus,
+ id,
+ defaultViewport,
+ optionalContentConfigPromise,
+ linkService,
+ renderingQueue,
+ pageColors
+ }) {
+ this.id = id;
+ this.renderingId = "thumbnail" + id;
+ this.pageLabel = null;
+ this.pdfPage = null;
+ this.rotation = 0;
+ this.viewport = defaultViewport;
+ this.pdfPageRotate = defaultViewport.rotation;
+ this._optionalContentConfigPromise = optionalContentConfigPromise || null;
+ this.pageColors = pageColors || null;
+ this.eventBus = eventBus;
+ this.linkService = linkService;
+ this.renderingQueue = renderingQueue;
+ this.renderTask = null;
+ this.renderingState = RenderingStates.INITIAL;
+ this.resume = null;
+ const anchor = document.createElement("a");
+ anchor.href = linkService.getAnchorUrl("#page=" + id);
+ anchor.setAttribute("data-l10n-id", "pdfjs-thumb-page-title");
+ anchor.setAttribute("data-l10n-args", this.#pageL10nArgs);
+ anchor.onclick = function () {
+ linkService.goToPage(id);
+ return false;
+ };
+ this.anchor = anchor;
+ const div = document.createElement("div");
+ div.className = "thumbnail";
+ div.setAttribute("data-page-number", this.id);
+ this.div = div;
+ this.#updateDims();
+ const img = document.createElement("div");
+ img.className = "thumbnailImage";
+ this._placeholderImg = img;
+ div.append(img);
+ anchor.append(div);
+ container.append(anchor);
+ }
+ #updateDims() {
+ const {
+ width,
+ height
+ } = this.viewport;
+ const ratio = width / height;
+ this.canvasWidth = THUMBNAIL_WIDTH;
+ this.canvasHeight = this.canvasWidth / ratio | 0;
+ this.scale = this.canvasWidth / width;
+ const {
+ style
+ } = this.div;
+ style.setProperty("--thumbnail-width", `${this.canvasWidth}px`);
+ style.setProperty("--thumbnail-height", `${this.canvasHeight}px`);
+ }
+ setPdfPage(pdfPage) {
+ this.pdfPage = pdfPage;
+ this.pdfPageRotate = pdfPage.rotate;
+ const totalRotation = (this.rotation + this.pdfPageRotate) % 360;
+ this.viewport = pdfPage.getViewport({
+ scale: 1,
+ rotation: totalRotation
+ });
+ this.reset();
+ }
+ reset() {
+ this.cancelRendering();
+ this.renderingState = RenderingStates.INITIAL;
+ this.div.removeAttribute("data-loaded");
+ this.image?.replaceWith(this._placeholderImg);
+ this.#updateDims();
+ if (this.image) {
+ this.image.removeAttribute("src");
+ delete this.image;
+ }
+ }
+ update({
+ rotation = null
+ }) {
+ if (typeof rotation === "number") {
+ this.rotation = rotation;
+ }
+ const totalRotation = (this.rotation + this.pdfPageRotate) % 360;
+ this.viewport = this.viewport.clone({
+ scale: 1,
+ rotation: totalRotation
+ });
+ this.reset();
+ }
+ cancelRendering() {
+ if (this.renderTask) {
+ this.renderTask.cancel();
+ this.renderTask = null;
+ }
+ this.resume = null;
+ }
+ _getPageDrawContext(upscaleFactor = 1) {
+ const canvas = document.createElement("canvas");
+ const ctx = canvas.getContext("2d", {
+ alpha: false
+ });
+ const outputScale = new OutputScale();
+ canvas.width = upscaleFactor * this.canvasWidth * outputScale.sx | 0;
+ canvas.height = upscaleFactor * this.canvasHeight * outputScale.sy | 0;
+ const transform = outputScale.scaled ? [outputScale.sx, 0, 0, outputScale.sy, 0, 0] : null;
+ return {
+ ctx,
+ canvas,
+ transform
+ };
+ }
+ _convertCanvasToImage(canvas) {
+ if (this.renderingState !== RenderingStates.FINISHED) {
+ throw new Error("_convertCanvasToImage: Rendering has not finished.");
+ }
+ const reducedCanvas = this._reduceImage(canvas);
+ const image = document.createElement("img");
+ image.className = "thumbnailImage";
+ image.setAttribute("data-l10n-id", "pdfjs-thumb-page-canvas");
+ image.setAttribute("data-l10n-args", this.#pageL10nArgs);
+ image.src = reducedCanvas.toDataURL();
+ this.image = image;
+ this.div.setAttribute("data-loaded", true);
+ this._placeholderImg.replaceWith(image);
+ reducedCanvas.width = 0;
+ reducedCanvas.height = 0;
+ }
+ async #finishRenderTask(renderTask, canvas, error = null) {
+ if (renderTask === this.renderTask) {
+ this.renderTask = null;
+ }
+ if (error instanceof RenderingCancelledException) {
+ return;
+ }
+ this.renderingState = RenderingStates.FINISHED;
+ this._convertCanvasToImage(canvas);
+ if (error) {
+ throw error;
+ }
+ }
+ async draw() {
+ if (this.renderingState !== RenderingStates.INITIAL) {
+ console.error("Must be in new state before drawing");
+ return undefined;
+ }
+ const {
+ pdfPage
+ } = this;
+ if (!pdfPage) {
+ this.renderingState = RenderingStates.FINISHED;
+ throw new Error("pdfPage is not loaded");
+ }
+ this.renderingState = RenderingStates.RUNNING;
+ const {
+ ctx,
+ canvas,
+ transform
+ } = this._getPageDrawContext(DRAW_UPSCALE_FACTOR);
+ const drawViewport = this.viewport.clone({
+ scale: DRAW_UPSCALE_FACTOR * this.scale
+ });
+ const renderContinueCallback = cont => {
+ if (!this.renderingQueue.isHighestPriority(this)) {
+ this.renderingState = RenderingStates.PAUSED;
+ this.resume = () => {
+ this.renderingState = RenderingStates.RUNNING;
+ cont();
+ };
+ return;
+ }
+ cont();
+ };
+ const renderContext = {
+ canvasContext: ctx,
+ transform,
+ viewport: drawViewport,
+ optionalContentConfigPromise: this._optionalContentConfigPromise,
+ pageColors: this.pageColors
+ };
+ const renderTask = this.renderTask = pdfPage.render(renderContext);
+ renderTask.onContinue = renderContinueCallback;
+ const resultPromise = renderTask.promise.then(() => this.#finishRenderTask(renderTask, canvas), error => this.#finishRenderTask(renderTask, canvas, error));
+ resultPromise.finally(() => {
+ canvas.width = 0;
+ canvas.height = 0;
+ this.eventBus.dispatch("thumbnailrendered", {
+ source: this,
+ pageNumber: this.id,
+ pdfPage: this.pdfPage
+ });
+ });
+ return resultPromise;
+ }
+ setImage(pageView) {
+ if (this.renderingState !== RenderingStates.INITIAL) {
+ return;
+ }
+ const {
+ thumbnailCanvas: canvas,
+ pdfPage,
+ scale
+ } = pageView;
+ if (!canvas) {
+ return;
+ }
+ if (!this.pdfPage) {
+ this.setPdfPage(pdfPage);
+ }
+ if (scale < this.scale) {
+ return;
+ }
+ this.renderingState = RenderingStates.FINISHED;
+ this._convertCanvasToImage(canvas);
+ }
+ _reduceImage(img) {
+ const {
+ ctx,
+ canvas
+ } = this._getPageDrawContext();
+ if (img.width <= 2 * canvas.width) {
+ ctx.drawImage(img, 0, 0, img.width, img.height, 0, 0, canvas.width, canvas.height);
+ return canvas;
+ }
+ let reducedWidth = canvas.width << MAX_NUM_SCALING_STEPS;
+ let reducedHeight = canvas.height << MAX_NUM_SCALING_STEPS;
+ const [reducedImage, reducedImageCtx] = TempImageFactory.getCanvas(reducedWidth, reducedHeight);
+ while (reducedWidth > img.width || reducedHeight > img.height) {
+ reducedWidth >>= 1;
+ reducedHeight >>= 1;
+ }
+ reducedImageCtx.drawImage(img, 0, 0, img.width, img.height, 0, 0, reducedWidth, reducedHeight);
+ while (reducedWidth > 2 * canvas.width) {
+ reducedImageCtx.drawImage(reducedImage, 0, 0, reducedWidth, reducedHeight, 0, 0, reducedWidth >> 1, reducedHeight >> 1);
+ reducedWidth >>= 1;
+ reducedHeight >>= 1;
+ }
+ ctx.drawImage(reducedImage, 0, 0, reducedWidth, reducedHeight, 0, 0, canvas.width, canvas.height);
+ return canvas;
+ }
+ get #pageL10nArgs() {
+ return JSON.stringify({
+ page: this.pageLabel ?? this.id
+ });
+ }
+ setPageLabel(label) {
+ this.pageLabel = typeof label === "string" ? label : null;
+ this.anchor.setAttribute("data-l10n-args", this.#pageL10nArgs);
+ if (this.renderingState !== RenderingStates.FINISHED) {
+ return;
+ }
+ this.image?.setAttribute("data-l10n-args", this.#pageL10nArgs);
+ }
+}
+
+;// CONCATENATED MODULE: ./web/pdf_thumbnail_viewer.js
+
+
+const THUMBNAIL_SCROLL_MARGIN = -19;
+const THUMBNAIL_SELECTED_CLASS = "selected";
+class PDFThumbnailViewer {
+ constructor({
+ container,
+ eventBus,
+ linkService,
+ renderingQueue,
+ pageColors
+ }) {
+ this.container = container;
+ this.eventBus = eventBus;
+ this.linkService = linkService;
+ this.renderingQueue = renderingQueue;
+ this.pageColors = pageColors || null;
+ this.scroll = watchScroll(this.container, this._scrollUpdated.bind(this));
+ this._resetView();
+ }
+ _scrollUpdated() {
+ this.renderingQueue.renderHighestPriority();
+ }
+ getThumbnail(index) {
+ return this._thumbnails[index];
+ }
+ _getVisibleThumbs() {
+ return getVisibleElements({
+ scrollEl: this.container,
+ views: this._thumbnails
+ });
+ }
+ scrollThumbnailIntoView(pageNumber) {
+ if (!this.pdfDocument) {
+ return;
+ }
+ const thumbnailView = this._thumbnails[pageNumber - 1];
+ if (!thumbnailView) {
+ console.error('scrollThumbnailIntoView: Invalid "pageNumber" parameter.');
+ return;
+ }
+ if (pageNumber !== this._currentPageNumber) {
+ const prevThumbnailView = this._thumbnails[this._currentPageNumber - 1];
+ prevThumbnailView.div.classList.remove(THUMBNAIL_SELECTED_CLASS);
+ thumbnailView.div.classList.add(THUMBNAIL_SELECTED_CLASS);
+ }
+ const {
+ first,
+ last,
+ views
+ } = this._getVisibleThumbs();
+ if (views.length > 0) {
+ let shouldScroll = false;
+ if (pageNumber <= first.id || pageNumber >= last.id) {
+ shouldScroll = true;
+ } else {
+ for (const {
+ id,
+ percent
+ } of views) {
+ if (id !== pageNumber) {
+ continue;
+ }
+ shouldScroll = percent < 100;
+ break;
+ }
+ }
+ if (shouldScroll) {
+ scrollIntoView(thumbnailView.div, {
+ top: THUMBNAIL_SCROLL_MARGIN
+ });
+ }
+ }
+ this._currentPageNumber = pageNumber;
+ }
+ get pagesRotation() {
+ return this._pagesRotation;
+ }
+ set pagesRotation(rotation) {
+ if (!isValidRotation(rotation)) {
+ throw new Error("Invalid thumbnails rotation angle.");
+ }
+ if (!this.pdfDocument) {
+ return;
+ }
+ if (this._pagesRotation === rotation) {
+ return;
+ }
+ this._pagesRotation = rotation;
+ const updateArgs = {
+ rotation
+ };
+ for (const thumbnail of this._thumbnails) {
+ thumbnail.update(updateArgs);
+ }
+ }
+ cleanup() {
+ for (const thumbnail of this._thumbnails) {
+ if (thumbnail.renderingState !== RenderingStates.FINISHED) {
+ thumbnail.reset();
+ }
+ }
+ TempImageFactory.destroyCanvas();
+ }
+ _resetView() {
+ this._thumbnails = [];
+ this._currentPageNumber = 1;
+ this._pageLabels = null;
+ this._pagesRotation = 0;
+ this.container.textContent = "";
+ }
+ setDocument(pdfDocument) {
+ if (this.pdfDocument) {
+ this._cancelRendering();
+ this._resetView();
+ }
+ this.pdfDocument = pdfDocument;
+ if (!pdfDocument) {
+ return;
+ }
+ const firstPagePromise = pdfDocument.getPage(1);
+ const optionalContentConfigPromise = pdfDocument.getOptionalContentConfig();
+ firstPagePromise.then(firstPdfPage => {
+ const pagesCount = pdfDocument.numPages;
+ const viewport = firstPdfPage.getViewport({
+ scale: 1
+ });
+ for (let pageNum = 1; pageNum <= pagesCount; ++pageNum) {
+ const thumbnail = new PDFThumbnailView({
+ container: this.container,
+ eventBus: this.eventBus,
+ id: pageNum,
+ defaultViewport: viewport.clone(),
+ optionalContentConfigPromise,
+ linkService: this.linkService,
+ renderingQueue: this.renderingQueue,
+ pageColors: this.pageColors
+ });
+ this._thumbnails.push(thumbnail);
+ }
+ this._thumbnails[0]?.setPdfPage(firstPdfPage);
+ const thumbnailView = this._thumbnails[this._currentPageNumber - 1];
+ thumbnailView.div.classList.add(THUMBNAIL_SELECTED_CLASS);
+ }).catch(reason => {
+ console.error("Unable to initialize thumbnail viewer", reason);
+ });
+ }
+ _cancelRendering() {
+ for (const thumbnail of this._thumbnails) {
+ thumbnail.cancelRendering();
+ }
+ }
+ setPageLabels(labels) {
+ if (!this.pdfDocument) {
+ return;
+ }
+ if (!labels) {
+ this._pageLabels = null;
+ } else if (!(Array.isArray(labels) && this.pdfDocument.numPages === labels.length)) {
+ this._pageLabels = null;
+ console.error("PDFThumbnailViewer_setPageLabels: Invalid page labels.");
+ } else {
+ this._pageLabels = labels;
+ }
+ for (let i = 0, ii = this._thumbnails.length; i < ii; i++) {
+ this._thumbnails[i].setPageLabel(this._pageLabels?.[i] ?? null);
+ }
+ }
+ async #ensurePdfPageLoaded(thumbView) {
+ if (thumbView.pdfPage) {
+ return thumbView.pdfPage;
+ }
+ try {
+ const pdfPage = await this.pdfDocument.getPage(thumbView.id);
+ if (!thumbView.pdfPage) {
+ thumbView.setPdfPage(pdfPage);
+ }
+ return pdfPage;
+ } catch (reason) {
+ console.error("Unable to get page for thumb view", reason);
+ return null;
+ }
+ }
+ #getScrollAhead(visible) {
+ if (visible.first?.id === 1) {
+ return true;
+ } else if (visible.last?.id === this._thumbnails.length) {
+ return false;
+ }
+ return this.scroll.down;
+ }
+ forceRendering() {
+ const visibleThumbs = this._getVisibleThumbs();
+ const scrollAhead = this.#getScrollAhead(visibleThumbs);
+ const thumbView = this.renderingQueue.getHighestPriority(visibleThumbs, this._thumbnails, scrollAhead);
+ if (thumbView) {
+ this.#ensurePdfPageLoaded(thumbView).then(() => {
+ this.renderingQueue.renderView(thumbView);
+ });
+ return true;
+ }
+ return false;
+ }
+}
+
+;// CONCATENATED MODULE: ./web/annotation_editor_layer_builder.js
+
+
+class AnnotationEditorLayerBuilder {
+ #annotationLayer = null;
+ #drawLayer = null;
+ #textLayer = null;
+ #uiManager;
+ constructor(options) {
+ this.pageDiv = options.pageDiv;
+ this.pdfPage = options.pdfPage;
+ this.accessibilityManager = options.accessibilityManager;
+ this.l10n = options.l10n;
+ this.annotationEditorLayer = null;
+ this.div = null;
+ this._cancelled = false;
+ this.#uiManager = options.uiManager;
+ this.#annotationLayer = options.annotationLayer || null;
+ this.#textLayer = options.textLayer || null;
+ this.#drawLayer = options.drawLayer || null;
+ }
+ async render(viewport, intent = "display") {
+ if (intent !== "display") {
+ return;
+ }
+ if (this._cancelled) {
+ return;
+ }
+ const clonedViewport = viewport.clone({
+ dontFlip: true
+ });
+ if (this.div) {
+ this.annotationEditorLayer.update({
+ viewport: clonedViewport
+ });
+ this.show();
+ return;
+ }
+ const div = this.div = document.createElement("div");
+ div.className = "annotationEditorLayer";
+ div.tabIndex = 0;
+ div.hidden = true;
+ div.dir = this.#uiManager.direction;
+ this.pageDiv.append(div);
+ this.annotationEditorLayer = new AnnotationEditorLayer({
+ uiManager: this.#uiManager,
+ div,
+ accessibilityManager: this.accessibilityManager,
+ pageIndex: this.pdfPage.pageNumber - 1,
+ l10n: this.l10n,
+ viewport: clonedViewport,
+ annotationLayer: this.#annotationLayer,
+ textLayer: this.#textLayer,
+ drawLayer: this.#drawLayer
+ });
+ const parameters = {
+ viewport: clonedViewport,
+ div,
+ annotations: null,
+ intent
+ };
+ this.annotationEditorLayer.render(parameters);
+ this.show();
+ }
+ cancel() {
+ this._cancelled = true;
+ if (!this.div) {
+ return;
+ }
+ this.pageDiv = null;
+ this.annotationEditorLayer.destroy();
+ this.div.remove();
+ }
+ hide() {
+ if (!this.div) {
+ return;
+ }
+ this.div.hidden = true;
+ }
+ show() {
+ if (!this.div || this.annotationEditorLayer.isEmpty) {
+ return;
+ }
+ this.div.hidden = false;
+ }
+}
+
+;// CONCATENATED MODULE: ./web/annotation_layer_builder.js
+
+
+class AnnotationLayerBuilder {
+ #onPresentationModeChanged = null;
+ constructor({
+ pageDiv,
+ pdfPage,
+ linkService,
+ downloadManager,
+ annotationStorage = null,
+ imageResourcesPath = "",
+ renderForms = true,
+ enableScripting = false,
+ hasJSActionsPromise = null,
+ fieldObjectsPromise = null,
+ annotationCanvasMap = null,
+ accessibilityManager = null
+ }) {
+ this.pageDiv = pageDiv;
+ this.pdfPage = pdfPage;
+ this.linkService = linkService;
+ this.downloadManager = downloadManager;
+ this.imageResourcesPath = imageResourcesPath;
+ this.renderForms = renderForms;
+ this.annotationStorage = annotationStorage;
+ this.enableScripting = enableScripting;
+ this._hasJSActionsPromise = hasJSActionsPromise || Promise.resolve(false);
+ this._fieldObjectsPromise = fieldObjectsPromise || Promise.resolve(null);
+ this._annotationCanvasMap = annotationCanvasMap;
+ this._accessibilityManager = accessibilityManager;
+ this.annotationLayer = null;
+ this.div = null;
+ this._cancelled = false;
+ this._eventBus = linkService.eventBus;
+ }
+ async render(viewport, intent = "display") {
+ if (this.div) {
+ if (this._cancelled || !this.annotationLayer) {
+ return;
+ }
+ this.annotationLayer.update({
+ viewport: viewport.clone({
+ dontFlip: true
+ })
+ });
+ return;
+ }
+ const [annotations, hasJSActions, fieldObjects] = await Promise.all([this.pdfPage.getAnnotations({
+ intent
+ }), this._hasJSActionsPromise, this._fieldObjectsPromise]);
+ if (this._cancelled) {
+ return;
+ }
+ const div = this.div = document.createElement("div");
+ div.className = "annotationLayer";
+ this.pageDiv.append(div);
+ if (annotations.length === 0) {
+ this.hide();
+ return;
+ }
+ this.annotationLayer = new AnnotationLayer({
+ div,
+ accessibilityManager: this._accessibilityManager,
+ annotationCanvasMap: this._annotationCanvasMap,
+ page: this.pdfPage,
+ viewport: viewport.clone({
+ dontFlip: true
+ })
+ });
+ await this.annotationLayer.render({
+ annotations,
+ imageResourcesPath: this.imageResourcesPath,
+ renderForms: this.renderForms,
+ linkService: this.linkService,
+ downloadManager: this.downloadManager,
+ annotationStorage: this.annotationStorage,
+ enableScripting: this.enableScripting,
+ hasJSActions,
+ fieldObjects
+ });
+ if (this.linkService.isInPresentationMode) {
+ this.#updatePresentationModeState(PresentationModeState.FULLSCREEN);
+ }
+ if (!this.#onPresentationModeChanged) {
+ this.#onPresentationModeChanged = evt => {
+ this.#updatePresentationModeState(evt.state);
+ };
+ this._eventBus?._on("presentationmodechanged", this.#onPresentationModeChanged);
+ }
+ }
+ cancel() {
+ this._cancelled = true;
+ if (this.#onPresentationModeChanged) {
+ this._eventBus?._off("presentationmodechanged", this.#onPresentationModeChanged);
+ this.#onPresentationModeChanged = null;
+ }
+ }
+ hide() {
+ if (!this.div) {
+ return;
+ }
+ this.div.hidden = true;
+ }
+ #updatePresentationModeState(state) {
+ if (!this.div) {
+ return;
+ }
+ let disableFormElements = false;
+ switch (state) {
+ case PresentationModeState.FULLSCREEN:
+ disableFormElements = true;
+ break;
+ case PresentationModeState.NORMAL:
+ break;
+ default:
+ return;
+ }
+ for (const section of this.div.childNodes) {
+ if (section.hasAttribute("data-internal-link")) {
+ continue;
+ }
+ section.inert = disableFormElements;
+ }
+ }
+}
+
+;// CONCATENATED MODULE: ./web/draw_layer_builder.js
+
+class DrawLayerBuilder {
+ #drawLayer = null;
+ constructor(options) {
+ this.pageIndex = options.pageIndex;
+ }
+ async render(intent = "display") {
+ if (intent !== "display" || this.#drawLayer || this._cancelled) {
+ return;
+ }
+ this.#drawLayer = new DrawLayer({
+ pageIndex: this.pageIndex
+ });
+ }
+ cancel() {
+ this._cancelled = true;
+ if (!this.#drawLayer) {
+ return;
+ }
+ this.#drawLayer.destroy();
+ this.#drawLayer = null;
+ }
+ setParent(parent) {
+ this.#drawLayer?.setParent(parent);
+ }
+ getDrawLayer() {
+ return this.#drawLayer;
+ }
+}
+
+;// CONCATENATED MODULE: ./web/struct_tree_layer_builder.js
+
+const PDF_ROLE_TO_HTML_ROLE = {
+ Document: null,
+ DocumentFragment: null,
+ Part: "group",
+ Sect: "group",
+ Div: "group",
+ Aside: "note",
+ NonStruct: "none",
+ P: null,
+ H: "heading",
+ Title: null,
+ FENote: "note",
+ Sub: "group",
+ Lbl: null,
+ Span: null,
+ Em: null,
+ Strong: null,
+ Link: "link",
+ Annot: "note",
+ Form: "form",
+ Ruby: null,
+ RB: null,
+ RT: null,
+ RP: null,
+ Warichu: null,
+ WT: null,
+ WP: null,
+ L: "list",
+ LI: "listitem",
+ LBody: null,
+ Table: "table",
+ TR: "row",
+ TH: "columnheader",
+ TD: "cell",
+ THead: "columnheader",
+ TBody: null,
+ TFoot: null,
+ Caption: null,
+ Figure: "figure",
+ Formula: null,
+ Artifact: null
+};
+const HEADING_PATTERN = /^H(\d+)$/;
+class StructTreeLayerBuilder {
+ #treeDom = undefined;
+ get renderingDone() {
+ return this.#treeDom !== undefined;
+ }
+ render(structTree) {
+ if (this.#treeDom !== undefined) {
+ return this.#treeDom;
+ }
+ const treeDom = this.#walk(structTree);
+ treeDom?.classList.add("structTree");
+ return this.#treeDom = treeDom;
+ }
+ hide() {
+ if (this.#treeDom && !this.#treeDom.hidden) {
+ this.#treeDom.hidden = true;
+ }
+ }
+ show() {
+ if (this.#treeDom?.hidden) {
+ this.#treeDom.hidden = false;
+ }
+ }
+ #setAttributes(structElement, htmlElement) {
+ const {
+ alt,
+ id,
+ lang
+ } = structElement;
+ if (alt !== undefined) {
+ htmlElement.setAttribute("aria-label", removeNullCharacters(alt));
+ }
+ if (id !== undefined) {
+ htmlElement.setAttribute("aria-owns", id);
+ }
+ if (lang !== undefined) {
+ htmlElement.setAttribute("lang", removeNullCharacters(lang, true));
+ }
+ }
+ #walk(node) {
+ if (!node) {
+ return null;
+ }
+ const element = document.createElement("span");
+ if ("role" in node) {
+ const {
+ role
+ } = node;
+ const match = role.match(HEADING_PATTERN);
+ if (match) {
+ element.setAttribute("role", "heading");
+ element.setAttribute("aria-level", match[1]);
+ } else if (PDF_ROLE_TO_HTML_ROLE[role]) {
+ element.setAttribute("role", PDF_ROLE_TO_HTML_ROLE[role]);
+ }
+ }
+ this.#setAttributes(node, element);
+ if (node.children) {
+ if (node.children.length === 1 && "id" in node.children[0]) {
+ this.#setAttributes(node.children[0], element);
+ } else {
+ for (const kid of node.children) {
+ element.append(this.#walk(kid));
+ }
+ }
+ }
+ return element;
+ }
+}
+
+;// CONCATENATED MODULE: ./web/text_accessibility.js
+
+class TextAccessibilityManager {
+ #enabled = false;
+ #textChildren = null;
+ #textNodes = new Map();
+ #waitingElements = new Map();
+ setTextMapping(textDivs) {
+ this.#textChildren = textDivs;
+ }
+ static #compareElementPositions(e1, e2) {
+ const rect1 = e1.getBoundingClientRect();
+ const rect2 = e2.getBoundingClientRect();
+ if (rect1.width === 0 && rect1.height === 0) {
+ return +1;
+ }
+ if (rect2.width === 0 && rect2.height === 0) {
+ return -1;
+ }
+ const top1 = rect1.y;
+ const bot1 = rect1.y + rect1.height;
+ const mid1 = rect1.y + rect1.height / 2;
+ const top2 = rect2.y;
+ const bot2 = rect2.y + rect2.height;
+ const mid2 = rect2.y + rect2.height / 2;
+ if (mid1 <= top2 && mid2 >= bot1) {
+ return -1;
+ }
+ if (mid2 <= top1 && mid1 >= bot2) {
+ return +1;
+ }
+ const centerX1 = rect1.x + rect1.width / 2;
+ const centerX2 = rect2.x + rect2.width / 2;
+ return centerX1 - centerX2;
+ }
+ enable() {
+ if (this.#enabled) {
+ throw new Error("TextAccessibilityManager is already enabled.");
+ }
+ if (!this.#textChildren) {
+ throw new Error("Text divs and strings have not been set.");
+ }
+ this.#enabled = true;
+ this.#textChildren = this.#textChildren.slice();
+ this.#textChildren.sort(TextAccessibilityManager.#compareElementPositions);
+ if (this.#textNodes.size > 0) {
+ const textChildren = this.#textChildren;
+ for (const [id, nodeIndex] of this.#textNodes) {
+ const element = document.getElementById(id);
+ if (!element) {
+ this.#textNodes.delete(id);
+ continue;
+ }
+ this.#addIdToAriaOwns(id, textChildren[nodeIndex]);
+ }
+ }
+ for (const [element, isRemovable] of this.#waitingElements) {
+ this.addPointerInTextLayer(element, isRemovable);
+ }
+ this.#waitingElements.clear();
+ }
+ disable() {
+ if (!this.#enabled) {
+ return;
+ }
+ this.#waitingElements.clear();
+ this.#textChildren = null;
+ this.#enabled = false;
+ }
+ removePointerInTextLayer(element) {
+ if (!this.#enabled) {
+ this.#waitingElements.delete(element);
+ return;
+ }
+ const children = this.#textChildren;
+ if (!children || children.length === 0) {
+ return;
+ }
+ const {
+ id
+ } = element;
+ const nodeIndex = this.#textNodes.get(id);
+ if (nodeIndex === undefined) {
+ return;
+ }
+ const node = children[nodeIndex];
+ this.#textNodes.delete(id);
+ let owns = node.getAttribute("aria-owns");
+ if (owns?.includes(id)) {
+ owns = owns.split(" ").filter(x => x !== id).join(" ");
+ if (owns) {
+ node.setAttribute("aria-owns", owns);
+ } else {
+ node.removeAttribute("aria-owns");
+ node.setAttribute("role", "presentation");
+ }
+ }
+ }
+ #addIdToAriaOwns(id, node) {
+ const owns = node.getAttribute("aria-owns");
+ if (!owns?.includes(id)) {
+ node.setAttribute("aria-owns", owns ? `${owns} ${id}` : id);
+ }
+ node.removeAttribute("role");
+ }
+ addPointerInTextLayer(element, isRemovable) {
+ const {
+ id
+ } = element;
+ if (!id) {
+ return null;
+ }
+ if (!this.#enabled) {
+ this.#waitingElements.set(element, isRemovable);
+ return null;
+ }
+ if (isRemovable) {
+ this.removePointerInTextLayer(element);
+ }
+ const children = this.#textChildren;
+ if (!children || children.length === 0) {
+ return null;
+ }
+ const index = binarySearchFirstItem(children, node => TextAccessibilityManager.#compareElementPositions(element, node) < 0);
+ const nodeIndex = Math.max(0, index - 1);
+ const child = children[nodeIndex];
+ this.#addIdToAriaOwns(id, child);
+ this.#textNodes.set(id, nodeIndex);
+ const parent = child.parentNode;
+ return parent?.classList.contains("markedContent") ? parent.id : null;
+ }
+ moveElementInDOM(container, element, contentElement, isRemovable) {
+ const id = this.addPointerInTextLayer(contentElement, isRemovable);
+ if (!container.hasChildNodes()) {
+ container.append(element);
+ return id;
+ }
+ const children = Array.from(container.childNodes).filter(node => node !== element);
+ if (children.length === 0) {
+ return id;
+ }
+ const elementToCompare = contentElement || element;
+ const index = binarySearchFirstItem(children, node => TextAccessibilityManager.#compareElementPositions(elementToCompare, node) < 0);
+ if (index === 0) {
+ children[0].before(element);
+ } else {
+ children[index - 1].after(element);
+ }
+ return id;
+ }
+}
+
+;// CONCATENATED MODULE: ./web/text_highlighter.js
+class TextHighlighter {
+ constructor({
+ findController,
+ eventBus,
+ pageIndex
+ }) {
+ this.findController = findController;
+ this.matches = [];
+ this.eventBus = eventBus;
+ this.pageIdx = pageIndex;
+ this._onUpdateTextLayerMatches = null;
+ this.textDivs = null;
+ this.textContentItemsStr = null;
+ this.enabled = false;
+ }
+ setTextMapping(divs, texts) {
+ this.textDivs = divs;
+ this.textContentItemsStr = texts;
+ }
+ enable() {
+ if (!this.textDivs || !this.textContentItemsStr) {
+ throw new Error("Text divs and strings have not been set.");
+ }
+ if (this.enabled) {
+ throw new Error("TextHighlighter is already enabled.");
+ }
+ this.enabled = true;
+ if (!this._onUpdateTextLayerMatches) {
+ this._onUpdateTextLayerMatches = evt => {
+ if (evt.pageIndex === this.pageIdx || evt.pageIndex === -1) {
+ this._updateMatches();
+ }
+ };
+ this.eventBus._on("updatetextlayermatches", this._onUpdateTextLayerMatches);
+ }
+ this._updateMatches();
+ }
+ disable() {
+ if (!this.enabled) {
+ return;
+ }
+ this.enabled = false;
+ if (this._onUpdateTextLayerMatches) {
+ this.eventBus._off("updatetextlayermatches", this._onUpdateTextLayerMatches);
+ this._onUpdateTextLayerMatches = null;
+ }
+ this._updateMatches(true);
+ }
+ _convertMatches(matches, matchesLength) {
+ if (!matches) {
+ return [];
+ }
+ const {
+ textContentItemsStr
+ } = this;
+ let i = 0,
+ iIndex = 0;
+ const end = textContentItemsStr.length - 1;
+ const result = [];
+ for (let m = 0, mm = matches.length; m < mm; m++) {
+ let matchIdx = matches[m];
+ while (i !== end && matchIdx >= iIndex + textContentItemsStr[i].length) {
+ iIndex += textContentItemsStr[i].length;
+ i++;
+ }
+ if (i === textContentItemsStr.length) {
+ console.error("Could not find a matching mapping");
+ }
+ const match = {
+ begin: {
+ divIdx: i,
+ offset: matchIdx - iIndex
+ }
+ };
+ matchIdx += matchesLength[m];
+ while (i !== end && matchIdx > iIndex + textContentItemsStr[i].length) {
+ iIndex += textContentItemsStr[i].length;
+ i++;
+ }
+ match.end = {
+ divIdx: i,
+ offset: matchIdx - iIndex
+ };
+ result.push(match);
+ }
+ return result;
+ }
+ _renderMatches(matches) {
+ if (matches.length === 0) {
+ return;
+ }
+ const {
+ findController,
+ pageIdx
+ } = this;
+ const {
+ textContentItemsStr,
+ textDivs
+ } = this;
+ const isSelectedPage = pageIdx === findController.selected.pageIdx;
+ const selectedMatchIdx = findController.selected.matchIdx;
+ const highlightAll = findController.state.highlightAll;
+ let prevEnd = null;
+ const infinity = {
+ divIdx: -1,
+ offset: undefined
+ };
+ function beginText(begin, className) {
+ const divIdx = begin.divIdx;
+ textDivs[divIdx].textContent = "";
+ return appendTextToDiv(divIdx, 0, begin.offset, className);
+ }
+ function appendTextToDiv(divIdx, fromOffset, toOffset, className) {
+ let div = textDivs[divIdx];
+ if (div.nodeType === Node.TEXT_NODE) {
+ const span = document.createElement("span");
+ div.before(span);
+ span.append(div);
+ textDivs[divIdx] = span;
+ div = span;
+ }
+ const content = textContentItemsStr[divIdx].substring(fromOffset, toOffset);
+ const node = document.createTextNode(content);
+ if (className) {
+ const span = document.createElement("span");
+ span.className = `${className} appended`;
+ span.append(node);
+ div.append(span);
+ return className.includes("selected") ? span.offsetLeft : 0;
+ }
+ div.append(node);
+ return 0;
+ }
+ let i0 = selectedMatchIdx,
+ i1 = i0 + 1;
+ if (highlightAll) {
+ i0 = 0;
+ i1 = matches.length;
+ } else if (!isSelectedPage) {
+ return;
+ }
+ let lastDivIdx = -1;
+ let lastOffset = -1;
+ for (let i = i0; i < i1; i++) {
+ const match = matches[i];
+ const begin = match.begin;
+ if (begin.divIdx === lastDivIdx && begin.offset === lastOffset) {
+ continue;
+ }
+ lastDivIdx = begin.divIdx;
+ lastOffset = begin.offset;
+ const end = match.end;
+ const isSelected = isSelectedPage && i === selectedMatchIdx;
+ const highlightSuffix = isSelected ? " selected" : "";
+ let selectedLeft = 0;
+ if (!prevEnd || begin.divIdx !== prevEnd.divIdx) {
+ if (prevEnd !== null) {
+ appendTextToDiv(prevEnd.divIdx, prevEnd.offset, infinity.offset);
+ }
+ beginText(begin);
+ } else {
+ appendTextToDiv(prevEnd.divIdx, prevEnd.offset, begin.offset);
+ }
+ if (begin.divIdx === end.divIdx) {
+ selectedLeft = appendTextToDiv(begin.divIdx, begin.offset, end.offset, "highlight" + highlightSuffix);
+ } else {
+ selectedLeft = appendTextToDiv(begin.divIdx, begin.offset, infinity.offset, "highlight begin" + highlightSuffix);
+ for (let n0 = begin.divIdx + 1, n1 = end.divIdx; n0 < n1; n0++) {
+ textDivs[n0].className = "highlight middle" + highlightSuffix;
+ }
+ beginText(end, "highlight end" + highlightSuffix);
+ }
+ prevEnd = end;
+ if (isSelected) {
+ findController.scrollMatchIntoView({
+ element: textDivs[begin.divIdx],
+ selectedLeft,
+ pageIndex: pageIdx,
+ matchIndex: selectedMatchIdx
+ });
+ }
+ }
+ if (prevEnd) {
+ appendTextToDiv(prevEnd.divIdx, prevEnd.offset, infinity.offset);
+ }
+ }
+ _updateMatches(reset = false) {
+ if (!this.enabled && !reset) {
+ return;
+ }
+ const {
+ findController,
+ matches,
+ pageIdx
+ } = this;
+ const {
+ textContentItemsStr,
+ textDivs
+ } = this;
+ let clearedUntilDivIdx = -1;
+ for (const match of matches) {
+ const begin = Math.max(clearedUntilDivIdx, match.begin.divIdx);
+ for (let n = begin, end = match.end.divIdx; n <= end; n++) {
+ const div = textDivs[n];
+ div.textContent = textContentItemsStr[n];
+ div.className = "";
+ }
+ clearedUntilDivIdx = match.end.divIdx + 1;
+ }
+ if (!findController?.highlightMatches || reset) {
+ return;
+ }
+ const pageMatches = findController.pageMatches[pageIdx] || null;
+ const pageMatchesLength = findController.pageMatchesLength[pageIdx] || null;
+ this.matches = this._convertMatches(pageMatches, pageMatchesLength);
+ this._renderMatches(this.matches);
+ }
+}
+
+;// CONCATENATED MODULE: ./web/text_layer_builder.js
+
+
+class TextLayerBuilder {
+ #enablePermissions = false;
+ #rotation = 0;
+ #scale = 0;
+ #textContentSource = null;
+ constructor({
+ highlighter = null,
+ accessibilityManager = null,
+ enablePermissions = false
+ }) {
+ this.textContentItemsStr = [];
+ this.renderingDone = false;
+ this.textDivs = [];
+ this.textDivProperties = new WeakMap();
+ this.textLayerRenderTask = null;
+ this.highlighter = highlighter;
+ this.accessibilityManager = accessibilityManager;
+ this.#enablePermissions = enablePermissions === true;
+ this.onAppend = null;
+ this.div = document.createElement("div");
+ this.div.className = "textLayer";
+ }
+ #finishRendering() {
+ this.renderingDone = true;
+ const endOfContent = document.createElement("div");
+ endOfContent.className = "endOfContent";
+ this.div.append(endOfContent);
+ this.#bindMouse();
+ }
+ get numTextDivs() {
+ return this.textDivs.length;
+ }
+ async render(viewport) {
+ if (!this.#textContentSource) {
+ throw new Error('No "textContentSource" parameter specified.');
+ }
+ const scale = viewport.scale * (globalThis.devicePixelRatio || 1);
+ const {
+ rotation
+ } = viewport;
+ if (this.renderingDone) {
+ const mustRotate = rotation !== this.#rotation;
+ const mustRescale = scale !== this.#scale;
+ if (mustRotate || mustRescale) {
+ this.hide();
+ updateTextLayer({
+ container: this.div,
+ viewport,
+ textDivs: this.textDivs,
+ textDivProperties: this.textDivProperties,
+ mustRescale,
+ mustRotate
+ });
+ this.#scale = scale;
+ this.#rotation = rotation;
+ }
+ this.show();
+ return;
+ }
+ this.cancel();
+ this.highlighter?.setTextMapping(this.textDivs, this.textContentItemsStr);
+ this.accessibilityManager?.setTextMapping(this.textDivs);
+ this.textLayerRenderTask = renderTextLayer({
+ textContentSource: this.#textContentSource,
+ container: this.div,
+ viewport,
+ textDivs: this.textDivs,
+ textDivProperties: this.textDivProperties,
+ textContentItemsStr: this.textContentItemsStr
+ });
+ await this.textLayerRenderTask.promise;
+ this.#finishRendering();
+ this.#scale = scale;
+ this.#rotation = rotation;
+ this.onAppend(this.div);
+ this.highlighter?.enable();
+ this.accessibilityManager?.enable();
+ }
+ hide() {
+ if (!this.div.hidden && this.renderingDone) {
+ this.highlighter?.disable();
+ this.div.hidden = true;
+ }
+ }
+ show() {
+ if (this.div.hidden && this.renderingDone) {
+ this.div.hidden = false;
+ this.highlighter?.enable();
+ }
+ }
+ cancel() {
+ if (this.textLayerRenderTask) {
+ this.textLayerRenderTask.cancel();
+ this.textLayerRenderTask = null;
+ }
+ this.highlighter?.disable();
+ this.accessibilityManager?.disable();
+ this.textContentItemsStr.length = 0;
+ this.textDivs.length = 0;
+ this.textDivProperties = new WeakMap();
+ }
+ setTextContentSource(source) {
+ this.cancel();
+ this.#textContentSource = source;
+ }
+ #bindMouse() {
+ const {
+ div
+ } = this;
+ div.addEventListener("mousedown", evt => {
+ const end = div.querySelector(".endOfContent");
+ if (!end) {
+ return;
+ }
+ end.classList.add("active");
+ });
+ div.addEventListener("mouseup", () => {
+ const end = div.querySelector(".endOfContent");
+ if (!end) {
+ return;
+ }
+ end.classList.remove("active");
+ });
+ div.addEventListener("copy", event => {
+ if (!this.#enablePermissions) {
+ const selection = document.getSelection();
+ event.clipboardData.setData("text/plain", removeNullCharacters(normalizeUnicode(selection.toString())));
+ }
+ event.preventDefault();
+ event.stopPropagation();
+ });
+ }
+}
+
+;// CONCATENATED MODULE: ./web/pdf_page_view.js
+
+
+
+
+
+
+
+
+
+
+
+
+
+const MAX_CANVAS_PIXELS = compatibilityParams.maxCanvasPixels || 16777216;
+const DEFAULT_LAYER_PROPERTIES = null;
+class PDFPageView {
+ #annotationMode = AnnotationMode.ENABLE_FORMS;
+ #hasRestrictedScaling = false;
+ #layerProperties = null;
+ #loadingId = null;
+ #previousRotation = null;
+ #renderError = null;
+ #renderingState = RenderingStates.INITIAL;
+ #textLayerMode = TextLayerMode.ENABLE;
+ #useThumbnailCanvas = {
+ directDrawing: true,
+ initialOptionalContent: true,
+ regularAnnotations: true
+ };
+ #viewportMap = new WeakMap();
+ constructor(options) {
+ const container = options.container;
+ const defaultViewport = options.defaultViewport;
+ this.id = options.id;
+ this.renderingId = "page" + this.id;
+ this.#layerProperties = options.layerProperties || DEFAULT_LAYER_PROPERTIES;
+ this.pdfPage = null;
+ this.pageLabel = null;
+ this.rotation = 0;
+ this.scale = options.scale || DEFAULT_SCALE;
+ this.viewport = defaultViewport;
+ this.pdfPageRotate = defaultViewport.rotation;
+ this._optionalContentConfigPromise = options.optionalContentConfigPromise || null;
+ this.#textLayerMode = options.textLayerMode ?? TextLayerMode.ENABLE;
+ this.#annotationMode = options.annotationMode ?? AnnotationMode.ENABLE_FORMS;
+ this.imageResourcesPath = options.imageResourcesPath || "";
+ this.maxCanvasPixels = options.maxCanvasPixels ?? MAX_CANVAS_PIXELS;
+ this.pageColors = options.pageColors || null;
+ this.eventBus = options.eventBus;
+ this.renderingQueue = options.renderingQueue;
+ this.l10n = options.l10n;
+ this.renderTask = null;
+ this.resume = null;
+ this._annotationCanvasMap = null;
+ this.annotationLayer = null;
+ this.annotationEditorLayer = null;
+ this.textLayer = null;
+ this.zoomLayer = null;
+ this.xfaLayer = null;
+ this.structTreeLayer = null;
+ this.drawLayer = null;
+ const div = document.createElement("div");
+ div.className = "page";
+ div.setAttribute("data-page-number", this.id);
+ div.setAttribute("role", "region");
+ div.setAttribute("data-l10n-id", "pdfjs-page-landmark");
+ div.setAttribute("data-l10n-args", JSON.stringify({
+ page: this.id
+ }));
+ this.div = div;
+ this.#setDimensions();
+ container?.append(div);
+ }
+ get renderingState() {
+ return this.#renderingState;
+ }
+ set renderingState(state) {
+ if (state === this.#renderingState) {
+ return;
+ }
+ this.#renderingState = state;
+ if (this.#loadingId) {
+ clearTimeout(this.#loadingId);
+ this.#loadingId = null;
+ }
+ switch (state) {
+ case RenderingStates.PAUSED:
+ this.div.classList.remove("loading");
+ break;
+ case RenderingStates.RUNNING:
+ this.div.classList.add("loadingIcon");
+ this.#loadingId = setTimeout(() => {
+ this.div.classList.add("loading");
+ this.#loadingId = null;
+ }, 0);
+ break;
+ case RenderingStates.INITIAL:
+ case RenderingStates.FINISHED:
+ this.div.classList.remove("loadingIcon", "loading");
+ break;
+ }
+ }
+ #setDimensions() {
+ const {
+ viewport
+ } = this;
+ if (this.pdfPage) {
+ if (this.#previousRotation === viewport.rotation) {
+ return;
+ }
+ this.#previousRotation = viewport.rotation;
+ }
+ setLayerDimensions(this.div, viewport, true, false);
+ }
+ setPdfPage(pdfPage) {
+ this.pdfPage = pdfPage;
+ this.pdfPageRotate = pdfPage.rotate;
+ const totalRotation = (this.rotation + this.pdfPageRotate) % 360;
+ this.viewport = pdfPage.getViewport({
+ scale: this.scale * PixelsPerInch.PDF_TO_CSS_UNITS,
+ rotation: totalRotation
+ });
+ this.#setDimensions();
+ this.reset();
+ }
+ destroy() {
+ this.reset();
+ this.pdfPage?.cleanup();
+ }
+ get _textHighlighter() {
+ return shadow(this, "_textHighlighter", new TextHighlighter({
+ pageIndex: this.id - 1,
+ eventBus: this.eventBus,
+ findController: this.#layerProperties.findController
+ }));
+ }
+ async #renderAnnotationLayer() {
+ let error = null;
+ try {
+ await this.annotationLayer.render(this.viewport, "display");
+ } catch (ex) {
+ console.error(`#renderAnnotationLayer: "${ex}".`);
+ error = ex;
+ } finally {
+ this.eventBus.dispatch("annotationlayerrendered", {
+ source: this,
+ pageNumber: this.id,
+ error
+ });
+ }
+ }
+ async #renderAnnotationEditorLayer() {
+ let error = null;
+ try {
+ await this.annotationEditorLayer.render(this.viewport, "display");
+ } catch (ex) {
+ console.error(`#renderAnnotationEditorLayer: "${ex}".`);
+ error = ex;
+ } finally {
+ this.eventBus.dispatch("annotationeditorlayerrendered", {
+ source: this,
+ pageNumber: this.id,
+ error
+ });
+ }
+ }
+ async #renderDrawLayer() {
+ try {
+ await this.drawLayer.render("display");
+ } catch (ex) {
+ console.error(`#renderDrawLayer: "${ex}".`);
+ }
+ }
+ async #renderXfaLayer() {
+ let error = null;
+ try {
+ const result = await this.xfaLayer.render(this.viewport, "display");
+ if (result?.textDivs && this._textHighlighter) {
+ this.#buildXfaTextContentItems(result.textDivs);
+ }
+ } catch (ex) {
+ console.error(`#renderXfaLayer: "${ex}".`);
+ error = ex;
+ } finally {
+ if (this.xfaLayer?.div) {
+ this.l10n.pause();
+ this.div.append(this.xfaLayer.div);
+ this.l10n.resume();
+ }
+ this.eventBus.dispatch("xfalayerrendered", {
+ source: this,
+ pageNumber: this.id,
+ error
+ });
+ }
+ }
+ async #renderTextLayer() {
+ const {
+ pdfPage,
+ textLayer,
+ viewport
+ } = this;
+ if (!textLayer) {
+ return;
+ }
+ let error = null;
+ try {
+ if (!textLayer.renderingDone) {
+ const readableStream = pdfPage.streamTextContent({
+ includeMarkedContent: true,
+ disableNormalization: true
+ });
+ textLayer.setTextContentSource(readableStream);
+ }
+ await textLayer.render(viewport);
+ } catch (ex) {
+ if (ex instanceof AbortException) {
+ return;
+ }
+ console.error(`#renderTextLayer: "${ex}".`);
+ error = ex;
+ }
+ this.eventBus.dispatch("textlayerrendered", {
+ source: this,
+ pageNumber: this.id,
+ numTextDivs: textLayer.numTextDivs,
+ error
+ });
+ this.#renderStructTreeLayer();
+ }
+ async #renderStructTreeLayer() {
+ if (!this.textLayer) {
+ return;
+ }
+ this.structTreeLayer ||= new StructTreeLayerBuilder();
+ const tree = await (!this.structTreeLayer.renderingDone ? this.pdfPage.getStructTree() : null);
+ const treeDom = this.structTreeLayer?.render(tree);
+ if (treeDom) {
+ this.l10n.pause();
+ this.canvas?.append(treeDom);
+ this.l10n.resume();
+ }
+ this.structTreeLayer?.show();
+ }
+ async #buildXfaTextContentItems(textDivs) {
+ const text = await this.pdfPage.getTextContent();
+ const items = [];
+ for (const item of text.items) {
+ items.push(item.str);
+ }
+ this._textHighlighter.setTextMapping(textDivs, items);
+ this._textHighlighter.enable();
+ }
+ _resetZoomLayer(removeFromDOM = false) {
+ if (!this.zoomLayer) {
+ return;
+ }
+ const zoomLayerCanvas = this.zoomLayer.firstChild;
+ this.#viewportMap.delete(zoomLayerCanvas);
+ zoomLayerCanvas.width = 0;
+ zoomLayerCanvas.height = 0;
+ if (removeFromDOM) {
+ this.zoomLayer.remove();
+ }
+ this.zoomLayer = null;
+ }
+ reset({
+ keepZoomLayer = false,
+ keepAnnotationLayer = false,
+ keepAnnotationEditorLayer = false,
+ keepXfaLayer = false,
+ keepTextLayer = false
+ } = {}) {
+ this.cancelRendering({
+ keepAnnotationLayer,
+ keepAnnotationEditorLayer,
+ keepXfaLayer,
+ keepTextLayer
+ });
+ this.renderingState = RenderingStates.INITIAL;
+ const div = this.div;
+ const childNodes = div.childNodes,
+ zoomLayerNode = keepZoomLayer && this.zoomLayer || null,
+ annotationLayerNode = keepAnnotationLayer && this.annotationLayer?.div || null,
+ annotationEditorLayerNode = keepAnnotationEditorLayer && this.annotationEditorLayer?.div || null,
+ xfaLayerNode = keepXfaLayer && this.xfaLayer?.div || null,
+ textLayerNode = keepTextLayer && this.textLayer?.div || null;
+ for (let i = childNodes.length - 1; i >= 0; i--) {
+ const node = childNodes[i];
+ switch (node) {
+ case zoomLayerNode:
+ case annotationLayerNode:
+ case annotationEditorLayerNode:
+ case xfaLayerNode:
+ case textLayerNode:
+ continue;
+ }
+ node.remove();
+ }
+ div.removeAttribute("data-loaded");
+ if (annotationLayerNode) {
+ this.annotationLayer.hide();
+ }
+ if (annotationEditorLayerNode) {
+ this.annotationEditorLayer.hide();
+ }
+ if (xfaLayerNode) {
+ this.xfaLayer.hide();
+ }
+ if (textLayerNode) {
+ this.textLayer.hide();
+ }
+ this.structTreeLayer?.hide();
+ if (!zoomLayerNode) {
+ if (this.canvas) {
+ this.#viewportMap.delete(this.canvas);
+ this.canvas.width = 0;
+ this.canvas.height = 0;
+ delete this.canvas;
+ }
+ this._resetZoomLayer();
+ }
+ }
+ update({
+ scale = 0,
+ rotation = null,
+ optionalContentConfigPromise = null,
+ drawingDelay = -1
+ }) {
+ this.scale = scale || this.scale;
+ if (typeof rotation === "number") {
+ this.rotation = rotation;
+ }
+ if (optionalContentConfigPromise instanceof Promise) {
+ this._optionalContentConfigPromise = optionalContentConfigPromise;
+ optionalContentConfigPromise.then(optionalContentConfig => {
+ if (optionalContentConfigPromise !== this._optionalContentConfigPromise) {
+ return;
+ }
+ this.#useThumbnailCanvas.initialOptionalContent = optionalContentConfig.hasInitialVisibility;
+ });
+ }
+ this.#useThumbnailCanvas.directDrawing = true;
+ const totalRotation = (this.rotation + this.pdfPageRotate) % 360;
+ this.viewport = this.viewport.clone({
+ scale: this.scale * PixelsPerInch.PDF_TO_CSS_UNITS,
+ rotation: totalRotation
+ });
+ this.#setDimensions();
+ if (this.canvas) {
+ let onlyCssZoom = false;
+ if (this.#hasRestrictedScaling) {
+ if (this.maxCanvasPixels > 0) {
+ const {
+ width,
+ height
+ } = this.viewport;
+ const {
+ sx,
+ sy
+ } = this.outputScale;
+ onlyCssZoom = (Math.floor(width) * sx | 0) * (Math.floor(height) * sy | 0) > this.maxCanvasPixels;
+ }
+ }
+ const postponeDrawing = !onlyCssZoom && drawingDelay >= 0 && drawingDelay < 1000;
+ if (postponeDrawing || onlyCssZoom) {
+ if (postponeDrawing && this.renderingState !== RenderingStates.FINISHED) {
+ this.cancelRendering({
+ keepZoomLayer: true,
+ keepAnnotationLayer: true,
+ keepAnnotationEditorLayer: true,
+ keepXfaLayer: true,
+ keepTextLayer: true,
+ cancelExtraDelay: drawingDelay
+ });
+ this.renderingState = RenderingStates.FINISHED;
+ this.#useThumbnailCanvas.directDrawing = false;
+ }
+ this.cssTransform({
+ target: this.canvas,
+ redrawAnnotationLayer: true,
+ redrawAnnotationEditorLayer: true,
+ redrawXfaLayer: true,
+ redrawTextLayer: !postponeDrawing,
+ hideTextLayer: postponeDrawing
+ });
+ if (postponeDrawing) {
+ return;
+ }
+ this.eventBus.dispatch("pagerendered", {
+ source: this,
+ pageNumber: this.id,
+ cssTransform: true,
+ timestamp: performance.now(),
+ error: this.#renderError
+ });
+ return;
+ }
+ if (!this.zoomLayer && !this.canvas.hidden) {
+ this.zoomLayer = this.canvas.parentNode;
+ this.zoomLayer.style.position = "absolute";
+ }
+ }
+ if (this.zoomLayer) {
+ this.cssTransform({
+ target: this.zoomLayer.firstChild
+ });
+ }
+ this.reset({
+ keepZoomLayer: true,
+ keepAnnotationLayer: true,
+ keepAnnotationEditorLayer: true,
+ keepXfaLayer: true,
+ keepTextLayer: true
+ });
+ }
+ cancelRendering({
+ keepAnnotationLayer = false,
+ keepAnnotationEditorLayer = false,
+ keepXfaLayer = false,
+ keepTextLayer = false,
+ cancelExtraDelay = 0
+ } = {}) {
+ if (this.renderTask) {
+ this.renderTask.cancel(cancelExtraDelay);
+ this.renderTask = null;
+ }
+ this.resume = null;
+ if (this.textLayer && (!keepTextLayer || !this.textLayer.div)) {
+ this.textLayer.cancel();
+ this.textLayer = null;
+ }
+ if (this.structTreeLayer && !this.textLayer) {
+ this.structTreeLayer = null;
+ }
+ if (this.annotationLayer && (!keepAnnotationLayer || !this.annotationLayer.div)) {
+ this.annotationLayer.cancel();
+ this.annotationLayer = null;
+ this._annotationCanvasMap = null;
+ }
+ if (this.annotationEditorLayer && (!keepAnnotationEditorLayer || !this.annotationEditorLayer.div)) {
+ if (this.drawLayer) {
+ this.drawLayer.cancel();
+ this.drawLayer = null;
+ }
+ this.annotationEditorLayer.cancel();
+ this.annotationEditorLayer = null;
+ }
+ if (this.xfaLayer && (!keepXfaLayer || !this.xfaLayer.div)) {
+ this.xfaLayer.cancel();
+ this.xfaLayer = null;
+ this._textHighlighter?.disable();
+ }
+ }
+ cssTransform({
+ target,
+ redrawAnnotationLayer = false,
+ redrawAnnotationEditorLayer = false,
+ redrawXfaLayer = false,
+ redrawTextLayer = false,
+ hideTextLayer = false
+ }) {
+ if (!target.hasAttribute("zooming")) {
+ target.setAttribute("zooming", true);
+ const {
+ style
+ } = target;
+ style.width = style.height = "";
+ }
+ const originalViewport = this.#viewportMap.get(target);
+ if (this.viewport !== originalViewport) {
+ const relativeRotation = this.viewport.rotation - originalViewport.rotation;
+ const absRotation = Math.abs(relativeRotation);
+ let scaleX = 1,
+ scaleY = 1;
+ if (absRotation === 90 || absRotation === 270) {
+ const {
+ width,
+ height
+ } = this.viewport;
+ scaleX = height / width;
+ scaleY = width / height;
+ }
+ target.style.transform = `rotate(${relativeRotation}deg) scale(${scaleX}, ${scaleY})`;
+ }
+ if (redrawAnnotationLayer && this.annotationLayer) {
+ this.#renderAnnotationLayer();
+ }
+ if (redrawAnnotationEditorLayer && this.annotationEditorLayer) {
+ if (this.drawLayer) {
+ this.#renderDrawLayer();
+ }
+ this.#renderAnnotationEditorLayer();
+ }
+ if (redrawXfaLayer && this.xfaLayer) {
+ this.#renderXfaLayer();
+ }
+ if (this.textLayer) {
+ if (hideTextLayer) {
+ this.textLayer.hide();
+ this.structTreeLayer?.hide();
+ } else if (redrawTextLayer) {
+ this.#renderTextLayer();
+ }
+ }
+ }
+ get width() {
+ return this.viewport.width;
+ }
+ get height() {
+ return this.viewport.height;
+ }
+ getPagePoint(x, y) {
+ return this.viewport.convertToPdfPoint(x, y);
+ }
+ async #finishRenderTask(renderTask, error = null) {
+ if (renderTask === this.renderTask) {
+ this.renderTask = null;
+ }
+ if (error instanceof RenderingCancelledException) {
+ this.#renderError = null;
+ return;
+ }
+ this.#renderError = error;
+ this.renderingState = RenderingStates.FINISHED;
+ this._resetZoomLayer(true);
+ this.#useThumbnailCanvas.regularAnnotations = !renderTask.separateAnnots;
+ this.eventBus.dispatch("pagerendered", {
+ source: this,
+ pageNumber: this.id,
+ cssTransform: false,
+ timestamp: performance.now(),
+ error: this.#renderError
+ });
+ if (error) {
+ throw error;
+ }
+ }
+ async draw() {
+ if (this.renderingState !== RenderingStates.INITIAL) {
+ console.error("Must be in new state before drawing");
+ this.reset();
+ }
+ const {
+ div,
+ l10n,
+ pageColors,
+ pdfPage,
+ viewport
+ } = this;
+ if (!pdfPage) {
+ this.renderingState = RenderingStates.FINISHED;
+ throw new Error("pdfPage is not loaded");
+ }
+ this.renderingState = RenderingStates.RUNNING;
+ const canvasWrapper = document.createElement("div");
+ canvasWrapper.classList.add("canvasWrapper");
+ div.append(canvasWrapper);
+ if (!this.textLayer && this.#textLayerMode !== TextLayerMode.DISABLE && !pdfPage.isPureXfa) {
+ this._accessibilityManager ||= new TextAccessibilityManager();
+ this.textLayer = new TextLayerBuilder({
+ highlighter: this._textHighlighter,
+ accessibilityManager: this._accessibilityManager,
+ enablePermissions: this.#textLayerMode === TextLayerMode.ENABLE_PERMISSIONS
+ });
+ this.textLayer.onAppend = textLayerDiv => {
+ this.l10n.pause();
+ this.div.append(textLayerDiv);
+ this.l10n.resume();
+ };
+ }
+ if (!this.annotationLayer && this.#annotationMode !== AnnotationMode.DISABLE) {
+ const {
+ annotationStorage,
+ downloadManager,
+ enableScripting,
+ fieldObjectsPromise,
+ hasJSActionsPromise,
+ linkService
+ } = this.#layerProperties;
+ this._annotationCanvasMap ||= new Map();
+ this.annotationLayer = new AnnotationLayerBuilder({
+ pageDiv: div,
+ pdfPage,
+ annotationStorage,
+ imageResourcesPath: this.imageResourcesPath,
+ renderForms: this.#annotationMode === AnnotationMode.ENABLE_FORMS,
+ linkService,
+ downloadManager,
+ enableScripting,
+ hasJSActionsPromise,
+ fieldObjectsPromise,
+ annotationCanvasMap: this._annotationCanvasMap,
+ accessibilityManager: this._accessibilityManager
+ });
+ }
+ const renderContinueCallback = cont => {
+ showCanvas?.(false);
+ if (this.renderingQueue && !this.renderingQueue.isHighestPriority(this)) {
+ this.renderingState = RenderingStates.PAUSED;
+ this.resume = () => {
+ this.renderingState = RenderingStates.RUNNING;
+ cont();
+ };
+ return;
+ }
+ cont();
+ };
+ const {
+ width,
+ height
+ } = viewport;
+ const canvas = document.createElement("canvas");
+ canvas.setAttribute("role", "presentation");
+ canvas.hidden = true;
+ const hasHCM = !!(pageColors?.background && pageColors?.foreground);
+ let showCanvas = isLastShow => {
+ if (!hasHCM || isLastShow) {
+ canvas.hidden = false;
+ showCanvas = null;
+ }
+ };
+ canvasWrapper.append(canvas);
+ this.canvas = canvas;
+ const ctx = canvas.getContext("2d", {
+ alpha: false
+ });
+ const outputScale = this.outputScale = new OutputScale();
+ if (this.maxCanvasPixels > 0) {
+ const pixelsInViewport = width * height;
+ const maxScale = Math.sqrt(this.maxCanvasPixels / pixelsInViewport);
+ if (outputScale.sx > maxScale || outputScale.sy > maxScale) {
+ outputScale.sx = maxScale;
+ outputScale.sy = maxScale;
+ this.#hasRestrictedScaling = true;
+ } else {
+ this.#hasRestrictedScaling = false;
+ }
+ }
+ const sfx = approximateFraction(outputScale.sx);
+ const sfy = approximateFraction(outputScale.sy);
+ canvas.width = roundToDivide(width * outputScale.sx, sfx[0]);
+ canvas.height = roundToDivide(height * outputScale.sy, sfy[0]);
+ const {
+ style
+ } = canvas;
+ style.width = roundToDivide(width, sfx[1]) + "px";
+ style.height = roundToDivide(height, sfy[1]) + "px";
+ this.#viewportMap.set(canvas, viewport);
+ const transform = outputScale.scaled ? [outputScale.sx, 0, 0, outputScale.sy, 0, 0] : null;
+ const renderContext = {
+ canvasContext: ctx,
+ transform,
+ viewport,
+ annotationMode: this.#annotationMode,
+ optionalContentConfigPromise: this._optionalContentConfigPromise,
+ annotationCanvasMap: this._annotationCanvasMap,
+ pageColors
+ };
+ const renderTask = this.renderTask = this.pdfPage.render(renderContext);
+ renderTask.onContinue = renderContinueCallback;
+ const resultPromise = renderTask.promise.then(async () => {
+ showCanvas?.(true);
+ await this.#finishRenderTask(renderTask);
+ this.#renderTextLayer();
+ if (this.annotationLayer) {
+ await this.#renderAnnotationLayer();
+ }
+ const {
+ annotationEditorUIManager
+ } = this.#layerProperties;
+ if (!annotationEditorUIManager) {
+ return;
+ }
+ this.drawLayer ||= new DrawLayerBuilder({
+ pageIndex: this.id
+ });
+ await this.#renderDrawLayer();
+ this.drawLayer.setParent(canvasWrapper);
+ if (!this.annotationEditorLayer) {
+ this.annotationEditorLayer = new AnnotationEditorLayerBuilder({
+ uiManager: annotationEditorUIManager,
+ pageDiv: div,
+ pdfPage,
+ l10n,
+ accessibilityManager: this._accessibilityManager,
+ annotationLayer: this.annotationLayer?.annotationLayer,
+ textLayer: this.textLayer,
+ drawLayer: this.drawLayer.getDrawLayer()
+ });
+ }
+ this.#renderAnnotationEditorLayer();
+ }, error => {
+ if (!(error instanceof RenderingCancelledException)) {
+ showCanvas?.(true);
+ }
+ return this.#finishRenderTask(renderTask, error);
+ });
+ if (pdfPage.isPureXfa) {
+ if (!this.xfaLayer) {
+ const {
+ annotationStorage,
+ linkService
+ } = this.#layerProperties;
+ this.xfaLayer = new XfaLayerBuilder({
+ pdfPage,
+ annotationStorage,
+ linkService
+ });
+ }
+ this.#renderXfaLayer();
+ }
+ div.setAttribute("data-loaded", true);
+ this.eventBus.dispatch("pagerender", {
+ source: this,
+ pageNumber: this.id
+ });
+ return resultPromise;
+ }
+ setPageLabel(label) {
+ this.pageLabel = typeof label === "string" ? label : null;
+ this.div.setAttribute("data-l10n-args", JSON.stringify({
+ page: this.pageLabel ?? this.id
+ }));
+ if (this.pageLabel !== null) {
+ this.div.setAttribute("data-page-label", this.pageLabel);
+ } else {
+ this.div.removeAttribute("data-page-label");
+ }
+ }
+ get thumbnailCanvas() {
+ const {
+ directDrawing,
+ initialOptionalContent,
+ regularAnnotations
+ } = this.#useThumbnailCanvas;
+ return directDrawing && initialOptionalContent && regularAnnotations ? this.canvas : null;
+ }
+}
+
+;// CONCATENATED MODULE: ./web/pdf_viewer.js
+
+
+
+
+
+
+const DEFAULT_CACHE_SIZE = 10;
+const PagesCountLimit = {
+ FORCE_SCROLL_MODE_PAGE: 15000,
+ FORCE_LAZY_PAGE_INIT: 7500,
+ PAUSE_EAGER_PAGE_INIT: 250
+};
+function isValidAnnotationEditorMode(mode) {
+ return Object.values(AnnotationEditorType).includes(mode) && mode !== AnnotationEditorType.DISABLE;
+}
+class PDFPageViewBuffer {
+ #buf = new Set();
+ #size = 0;
+ constructor(size) {
+ this.#size = size;
+ }
+ push(view) {
+ const buf = this.#buf;
+ if (buf.has(view)) {
+ buf.delete(view);
+ }
+ buf.add(view);
+ if (buf.size > this.#size) {
+ this.#destroyFirstView();
+ }
+ }
+ resize(newSize, idsToKeep = null) {
+ this.#size = newSize;
+ const buf = this.#buf;
+ if (idsToKeep) {
+ const ii = buf.size;
+ let i = 1;
+ for (const view of buf) {
+ if (idsToKeep.has(view.id)) {
+ buf.delete(view);
+ buf.add(view);
+ }
+ if (++i > ii) {
+ break;
+ }
+ }
+ }
+ while (buf.size > this.#size) {
+ this.#destroyFirstView();
+ }
+ }
+ has(view) {
+ return this.#buf.has(view);
+ }
+ [Symbol.iterator]() {
+ return this.#buf.keys();
+ }
+ #destroyFirstView() {
+ const firstView = this.#buf.keys().next().value;
+ firstView?.destroy();
+ this.#buf.delete(firstView);
+ }
+}
+class PDFViewer {
+ #buffer = null;
+ #altTextManager = null;
+ #annotationEditorHighlightColors = null;
+ #annotationEditorMode = AnnotationEditorType.NONE;
+ #annotationEditorUIManager = null;
+ #annotationMode = AnnotationMode.ENABLE_FORMS;
+ #containerTopLeft = null;
+ #copyCallbackBound = null;
+ #enablePermissions = false;
+ #mlManager = null;
+ #getAllTextInProgress = false;
+ #hiddenCopyElement = null;
+ #interruptCopyCondition = false;
+ #previousContainerHeight = 0;
+ #resizeObserver = new ResizeObserver(this.#resizeObserverCallback.bind(this));
+ #scrollModePageState = null;
+ #onVisibilityChange = null;
+ #scaleTimeoutId = null;
+ #textLayerMode = TextLayerMode.ENABLE;
+ constructor(options) {
+ const viewerVersion = "4.1.249";
+ if (version !== viewerVersion) {
+ throw new Error(`The API version "${version}" does not match the Viewer version "${viewerVersion}".`);
+ }
+ this.container = options.container;
+ this.viewer = options.viewer || options.container.firstElementChild;
+ this.#resizeObserver.observe(this.container);
+ this.eventBus = options.eventBus;
+ this.linkService = options.linkService || new SimpleLinkService();
+ this.downloadManager = options.downloadManager || null;
+ this.findController = options.findController || null;
+ this.#altTextManager = options.altTextManager || null;
+ if (this.findController) {
+ this.findController.onIsPageVisible = pageNumber => this._getVisiblePages().ids.has(pageNumber);
+ }
+ this._scriptingManager = options.scriptingManager || null;
+ this.#textLayerMode = options.textLayerMode ?? TextLayerMode.ENABLE;
+ this.#annotationMode = options.annotationMode ?? AnnotationMode.ENABLE_FORMS;
+ this.#annotationEditorMode = options.annotationEditorMode ?? AnnotationEditorType.NONE;
+ this.#annotationEditorHighlightColors = options.annotationEditorHighlightColors || null;
+ this.imageResourcesPath = options.imageResourcesPath || "";
+ this.enablePrintAutoRotate = options.enablePrintAutoRotate || false;
+ this.maxCanvasPixels = options.maxCanvasPixels;
+ this.l10n = options.l10n;
+ this.#enablePermissions = options.enablePermissions || false;
+ this.pageColors = options.pageColors || null;
+ this.#mlManager = options.mlManager || null;
+ this.defaultRenderingQueue = !options.renderingQueue;
+ this.renderingQueue = options.renderingQueue;
+ this.scroll = watchScroll(this.container, this._scrollUpdate.bind(this));
+ this.presentationModeState = PresentationModeState.UNKNOWN;
+ this._onBeforeDraw = this._onAfterDraw = null;
+ this._resetView();
+ this.#updateContainerHeightCss();
+ this.eventBus._on("thumbnailrendered", ({
+ pageNumber,
+ pdfPage
+ }) => {
+ const pageView = this._pages[pageNumber - 1];
+ if (!this.#buffer.has(pageView)) {
+ pdfPage?.cleanup();
+ }
+ });
+ }
+ get pagesCount() {
+ return this._pages.length;
+ }
+ getPageView(index) {
+ return this._pages[index];
+ }
+ getCachedPageViews() {
+ return new Set(this.#buffer);
+ }
+ get pageViewsReady() {
+ return this._pagesCapability.settled && this._pages.every(pageView => pageView?.pdfPage);
+ }
+ get renderForms() {
+ return this.#annotationMode === AnnotationMode.ENABLE_FORMS;
+ }
+ get enableScripting() {
+ return !!this._scriptingManager;
+ }
+ get currentPageNumber() {
+ return this._currentPageNumber;
+ }
+ set currentPageNumber(val) {
+ if (!Number.isInteger(val)) {
+ throw new Error("Invalid page number.");
+ }
+ if (!this.pdfDocument) {
+ return;
+ }
+ if (!this._setCurrentPageNumber(val, true)) {
+ console.error(`currentPageNumber: "${val}" is not a valid page.`);
+ }
+ }
+ _setCurrentPageNumber(val, resetCurrentPageView = false) {
+ if (this._currentPageNumber === val) {
+ if (resetCurrentPageView) {
+ this.#resetCurrentPageView();
+ }
+ return true;
+ }
+ if (!(0 < val && val <= this.pagesCount)) {
+ return false;
+ }
+ const previous = this._currentPageNumber;
+ this._currentPageNumber = val;
+ this.eventBus.dispatch("pagechanging", {
+ source: this,
+ pageNumber: val,
+ pageLabel: this._pageLabels?.[val - 1] ?? null,
+ previous
+ });
+ if (resetCurrentPageView) {
+ this.#resetCurrentPageView();
+ }
+ return true;
+ }
+ get currentPageLabel() {
+ return this._pageLabels?.[this._currentPageNumber - 1] ?? null;
+ }
+ set currentPageLabel(val) {
+ if (!this.pdfDocument) {
+ return;
+ }
+ let page = val | 0;
+ if (this._pageLabels) {
+ const i = this._pageLabels.indexOf(val);
+ if (i >= 0) {
+ page = i + 1;
+ }
+ }
+ if (!this._setCurrentPageNumber(page, true)) {
+ console.error(`currentPageLabel: "${val}" is not a valid page.`);
+ }
+ }
+ get currentScale() {
+ return this._currentScale !== UNKNOWN_SCALE ? this._currentScale : DEFAULT_SCALE;
+ }
+ set currentScale(val) {
+ if (isNaN(val)) {
+ throw new Error("Invalid numeric scale.");
+ }
+ if (!this.pdfDocument) {
+ return;
+ }
+ this.#setScale(val, {
+ noScroll: false
+ });
+ }
+ get currentScaleValue() {
+ return this._currentScaleValue;
+ }
+ set currentScaleValue(val) {
+ if (!this.pdfDocument) {
+ return;
+ }
+ this.#setScale(val, {
+ noScroll: false
+ });
+ }
+ get pagesRotation() {
+ return this._pagesRotation;
+ }
+ set pagesRotation(rotation) {
+ if (!isValidRotation(rotation)) {
+ throw new Error("Invalid pages rotation angle.");
+ }
+ if (!this.pdfDocument) {
+ return;
+ }
+ rotation %= 360;
+ if (rotation < 0) {
+ rotation += 360;
+ }
+ if (this._pagesRotation === rotation) {
+ return;
+ }
+ this._pagesRotation = rotation;
+ const pageNumber = this._currentPageNumber;
+ this.refresh(true, {
+ rotation
+ });
+ if (this._currentScaleValue) {
+ this.#setScale(this._currentScaleValue, {
+ noScroll: true
+ });
+ }
+ this.eventBus.dispatch("rotationchanging", {
+ source: this,
+ pagesRotation: rotation,
+ pageNumber
+ });
+ if (this.defaultRenderingQueue) {
+ this.update();
+ }
+ }
+ get firstPagePromise() {
+ return this.pdfDocument ? this._firstPageCapability.promise : null;
+ }
+ get onePageRendered() {
+ return this.pdfDocument ? this._onePageRenderedCapability.promise : null;
+ }
+ get pagesPromise() {
+ return this.pdfDocument ? this._pagesCapability.promise : null;
+ }
+ get _layerProperties() {
+ const self = this;
+ return shadow(this, "_layerProperties", {
+ get annotationEditorUIManager() {
+ return self.#annotationEditorUIManager;
+ },
+ get annotationStorage() {
+ return self.pdfDocument?.annotationStorage;
+ },
+ get downloadManager() {
+ return self.downloadManager;
+ },
+ get enableScripting() {
+ return !!self._scriptingManager;
+ },
+ get fieldObjectsPromise() {
+ return self.pdfDocument?.getFieldObjects();
+ },
+ get findController() {
+ return self.findController;
+ },
+ get hasJSActionsPromise() {
+ return self.pdfDocument?.hasJSActions();
+ },
+ get linkService() {
+ return self.linkService;
+ }
+ });
+ }
+ #initializePermissions(permissions) {
+ const params = {
+ annotationEditorMode: this.#annotationEditorMode,
+ annotationMode: this.#annotationMode,
+ textLayerMode: this.#textLayerMode
+ };
+ if (!permissions) {
+ return params;
+ }
+ if (!permissions.includes(PermissionFlag.COPY) && this.#textLayerMode === TextLayerMode.ENABLE) {
+ params.textLayerMode = TextLayerMode.ENABLE_PERMISSIONS;
+ }
+ if (!permissions.includes(PermissionFlag.MODIFY_CONTENTS)) {
+ params.annotationEditorMode = AnnotationEditorType.DISABLE;
+ }
+ if (!permissions.includes(PermissionFlag.MODIFY_ANNOTATIONS) && !permissions.includes(PermissionFlag.FILL_INTERACTIVE_FORMS) && this.#annotationMode === AnnotationMode.ENABLE_FORMS) {
+ params.annotationMode = AnnotationMode.ENABLE;
+ }
+ return params;
+ }
+ async #onePageRenderedOrForceFetch() {
+ if (document.visibilityState === "hidden" || !this.container.offsetParent || this._getVisiblePages().views.length === 0) {
+ return;
+ }
+ const visibilityChangePromise = new Promise(resolve => {
+ this.#onVisibilityChange = () => {
+ if (document.visibilityState !== "hidden") {
+ return;
+ }
+ resolve();
+ };
+ document.addEventListener("visibilitychange", this.#onVisibilityChange);
+ });
+ await Promise.race([this._onePageRenderedCapability.promise, visibilityChangePromise]);
+ document.removeEventListener("visibilitychange", this.#onVisibilityChange);
+ this.#onVisibilityChange = null;
+ }
+ async getAllText() {
+ const texts = [];
+ const buffer = [];
+ for (let pageNum = 1, pagesCount = this.pdfDocument.numPages; pageNum <= pagesCount; ++pageNum) {
+ if (this.#interruptCopyCondition) {
+ return null;
+ }
+ buffer.length = 0;
+ const page = await this.pdfDocument.getPage(pageNum);
+ const {
+ items
+ } = await page.getTextContent();
+ for (const item of items) {
+ if (item.str) {
+ buffer.push(item.str);
+ }
+ if (item.hasEOL) {
+ buffer.push("\n");
+ }
+ }
+ texts.push(removeNullCharacters(buffer.join("")));
+ }
+ return texts.join("\n");
+ }
+ #copyCallback(textLayerMode, event) {
+ const selection = document.getSelection();
+ const {
+ focusNode,
+ anchorNode
+ } = selection;
+ if (anchorNode && focusNode && selection.containsNode(this.#hiddenCopyElement)) {
+ if (this.#getAllTextInProgress || textLayerMode === TextLayerMode.ENABLE_PERMISSIONS) {
+ event.preventDefault();
+ event.stopPropagation();
+ return;
+ }
+ this.#getAllTextInProgress = true;
+ const savedCursor = this.container.style.cursor;
+ this.container.style.cursor = "wait";
+ const interruptCopy = ev => this.#interruptCopyCondition = ev.key === "Escape";
+ window.addEventListener("keydown", interruptCopy);
+ this.getAllText().then(async text => {
+ if (text !== null) {
+ await navigator.clipboard.writeText(text);
+ }
+ }).catch(reason => {
+ console.warn(`Something goes wrong when extracting the text: ${reason.message}`);
+ }).finally(() => {
+ this.#getAllTextInProgress = false;
+ this.#interruptCopyCondition = false;
+ window.removeEventListener("keydown", interruptCopy);
+ this.container.style.cursor = savedCursor;
+ });
+ event.preventDefault();
+ event.stopPropagation();
+ }
+ }
+ setDocument(pdfDocument) {
+ if (this.pdfDocument) {
+ this.eventBus.dispatch("pagesdestroy", {
+ source: this
+ });
+ this._cancelRendering();
+ this._resetView();
+ this.findController?.setDocument(null);
+ this._scriptingManager?.setDocument(null);
+ if (this.#annotationEditorUIManager) {
+ this.#annotationEditorUIManager.destroy();
+ this.#annotationEditorUIManager = null;
+ }
+ }
+ this.pdfDocument = pdfDocument;
+ if (!pdfDocument) {
+ return;
+ }
+ const pagesCount = pdfDocument.numPages;
+ const firstPagePromise = pdfDocument.getPage(1);
+ const optionalContentConfigPromise = pdfDocument.getOptionalContentConfig();
+ const permissionsPromise = this.#enablePermissions ? pdfDocument.getPermissions() : Promise.resolve();
+ if (pagesCount > PagesCountLimit.FORCE_SCROLL_MODE_PAGE) {
+ console.warn("Forcing PAGE-scrolling for performance reasons, given the length of the document.");
+ const mode = this._scrollMode = ScrollMode.PAGE;
+ this.eventBus.dispatch("scrollmodechanged", {
+ source: this,
+ mode
+ });
+ }
+ this._pagesCapability.promise.then(() => {
+ this.eventBus.dispatch("pagesloaded", {
+ source: this,
+ pagesCount
+ });
+ }, () => {});
+ this._onBeforeDraw = evt => {
+ const pageView = this._pages[evt.pageNumber - 1];
+ if (!pageView) {
+ return;
+ }
+ this.#buffer.push(pageView);
+ };
+ this.eventBus._on("pagerender", this._onBeforeDraw);
+ this._onAfterDraw = evt => {
+ if (evt.cssTransform || this._onePageRenderedCapability.settled) {
+ return;
+ }
+ this._onePageRenderedCapability.resolve({
+ timestamp: evt.timestamp
+ });
+ this.eventBus._off("pagerendered", this._onAfterDraw);
+ this._onAfterDraw = null;
+ };
+ this.eventBus._on("pagerendered", this._onAfterDraw);
+ Promise.all([firstPagePromise, permissionsPromise]).then(([firstPdfPage, permissions]) => {
+ if (pdfDocument !== this.pdfDocument) {
+ return;
+ }
+ this._firstPageCapability.resolve(firstPdfPage);
+ this._optionalContentConfigPromise = optionalContentConfigPromise;
+ const {
+ annotationEditorMode,
+ annotationMode,
+ textLayerMode
+ } = this.#initializePermissions(permissions);
+ if (textLayerMode !== TextLayerMode.DISABLE) {
+ const element = this.#hiddenCopyElement = document.createElement("div");
+ element.id = "hiddenCopyElement";
+ this.viewer.before(element);
+ }
+ if (annotationEditorMode !== AnnotationEditorType.DISABLE) {
+ const mode = annotationEditorMode;
+ if (pdfDocument.isPureXfa) {
+ console.warn("Warning: XFA-editing is not implemented.");
+ } else if (isValidAnnotationEditorMode(mode)) {
+ this.#annotationEditorUIManager = new AnnotationEditorUIManager(this.container, this.viewer, this.#altTextManager, this.eventBus, pdfDocument, this.pageColors, this.#annotationEditorHighlightColors, this.#mlManager);
+ this.eventBus.dispatch("annotationeditoruimanager", {
+ source: this,
+ uiManager: this.#annotationEditorUIManager
+ });
+ if (mode !== AnnotationEditorType.NONE) {
+ this.#annotationEditorUIManager.updateMode(mode);
+ }
+ } else {
+ console.error(`Invalid AnnotationEditor mode: ${mode}`);
+ }
+ }
+ const viewerElement = this._scrollMode === ScrollMode.PAGE ? null : this.viewer;
+ const scale = this.currentScale;
+ const viewport = firstPdfPage.getViewport({
+ scale: scale * PixelsPerInch.PDF_TO_CSS_UNITS
+ });
+ this.viewer.style.setProperty("--scale-factor", viewport.scale);
+ if (this.pageColors?.foreground === "CanvasText" || this.pageColors?.background === "Canvas") {
+ this.viewer.style.setProperty("--hcm-highlight-filter", pdfDocument.filterFactory.addHighlightHCMFilter("highlight", "CanvasText", "Canvas", "HighlightText", "Highlight"));
+ this.viewer.style.setProperty("--hcm-highlight-selected-filter", pdfDocument.filterFactory.addHighlightHCMFilter("highlight_selected", "CanvasText", "Canvas", "HighlightText", "ButtonText"));
+ }
+ for (let pageNum = 1; pageNum <= pagesCount; ++pageNum) {
+ const pageView = new PDFPageView({
+ container: viewerElement,
+ eventBus: this.eventBus,
+ id: pageNum,
+ scale,
+ defaultViewport: viewport.clone(),
+ optionalContentConfigPromise,
+ renderingQueue: this.renderingQueue,
+ textLayerMode,
+ annotationMode,
+ imageResourcesPath: this.imageResourcesPath,
+ maxCanvasPixels: this.maxCanvasPixels,
+ pageColors: this.pageColors,
+ l10n: this.l10n,
+ layerProperties: this._layerProperties
+ });
+ this._pages.push(pageView);
+ }
+ const firstPageView = this._pages[0];
+ if (firstPageView) {
+ firstPageView.setPdfPage(firstPdfPage);
+ this.linkService.cachePageRef(1, firstPdfPage.ref);
+ }
+ if (this._scrollMode === ScrollMode.PAGE) {
+ this.#ensurePageViewVisible();
+ } else if (this._spreadMode !== SpreadMode.NONE) {
+ this._updateSpreadMode();
+ }
+ this.#onePageRenderedOrForceFetch().then(async () => {
+ this.findController?.setDocument(pdfDocument);
+ this._scriptingManager?.setDocument(pdfDocument);
+ if (this.#hiddenCopyElement) {
+ this.#copyCallbackBound = this.#copyCallback.bind(this, textLayerMode);
+ document.addEventListener("copy", this.#copyCallbackBound);
+ }
+ if (this.#annotationEditorUIManager) {
+ this.eventBus.dispatch("annotationeditormodechanged", {
+ source: this,
+ mode: this.#annotationEditorMode
+ });
+ }
+ if (pdfDocument.loadingParams.disableAutoFetch || pagesCount > PagesCountLimit.FORCE_LAZY_PAGE_INIT) {
+ this._pagesCapability.resolve();
+ return;
+ }
+ let getPagesLeft = pagesCount - 1;
+ if (getPagesLeft <= 0) {
+ this._pagesCapability.resolve();
+ return;
+ }
+ for (let pageNum = 2; pageNum <= pagesCount; ++pageNum) {
+ const promise = pdfDocument.getPage(pageNum).then(pdfPage => {
+ const pageView = this._pages[pageNum - 1];
+ if (!pageView.pdfPage) {
+ pageView.setPdfPage(pdfPage);
+ }
+ this.linkService.cachePageRef(pageNum, pdfPage.ref);
+ if (--getPagesLeft === 0) {
+ this._pagesCapability.resolve();
+ }
+ }, reason => {
+ console.error(`Unable to get page ${pageNum} to initialize viewer`, reason);
+ if (--getPagesLeft === 0) {
+ this._pagesCapability.resolve();
+ }
+ });
+ if (pageNum % PagesCountLimit.PAUSE_EAGER_PAGE_INIT === 0) {
+ await promise;
+ }
+ }
+ });
+ this.eventBus.dispatch("pagesinit", {
+ source: this
+ });
+ pdfDocument.getMetadata().then(({
+ info
+ }) => {
+ if (pdfDocument !== this.pdfDocument) {
+ return;
+ }
+ if (info.Language) {
+ this.viewer.lang = info.Language;
+ }
+ });
+ if (this.defaultRenderingQueue) {
+ this.update();
+ }
+ }).catch(reason => {
+ console.error("Unable to initialize viewer", reason);
+ this._pagesCapability.reject(reason);
+ });
+ }
+ setPageLabels(labels) {
+ if (!this.pdfDocument) {
+ return;
+ }
+ if (!labels) {
+ this._pageLabels = null;
+ } else if (!(Array.isArray(labels) && this.pdfDocument.numPages === labels.length)) {
+ this._pageLabels = null;
+ console.error(`setPageLabels: Invalid page labels.`);
+ } else {
+ this._pageLabels = labels;
+ }
+ for (let i = 0, ii = this._pages.length; i < ii; i++) {
+ this._pages[i].setPageLabel(this._pageLabels?.[i] ?? null);
+ }
+ }
+ _resetView() {
+ this._pages = [];
+ this._currentPageNumber = 1;
+ this._currentScale = UNKNOWN_SCALE;
+ this._currentScaleValue = null;
+ this._pageLabels = null;
+ this.#buffer = new PDFPageViewBuffer(DEFAULT_CACHE_SIZE);
+ this._location = null;
+ this._pagesRotation = 0;
+ this._optionalContentConfigPromise = null;
+ this._firstPageCapability = new PromiseCapability();
+ this._onePageRenderedCapability = new PromiseCapability();
+ this._pagesCapability = new PromiseCapability();
+ this._scrollMode = ScrollMode.VERTICAL;
+ this._previousScrollMode = ScrollMode.UNKNOWN;
+ this._spreadMode = SpreadMode.NONE;
+ this.#scrollModePageState = {
+ previousPageNumber: 1,
+ scrollDown: true,
+ pages: []
+ };
+ if (this._onBeforeDraw) {
+ this.eventBus._off("pagerender", this._onBeforeDraw);
+ this._onBeforeDraw = null;
+ }
+ if (this._onAfterDraw) {
+ this.eventBus._off("pagerendered", this._onAfterDraw);
+ this._onAfterDraw = null;
+ }
+ if (this.#onVisibilityChange) {
+ document.removeEventListener("visibilitychange", this.#onVisibilityChange);
+ this.#onVisibilityChange = null;
+ }
+ this.viewer.textContent = "";
+ this._updateScrollMode();
+ this.viewer.removeAttribute("lang");
+ if (this.#hiddenCopyElement) {
+ document.removeEventListener("copy", this.#copyCallbackBound);
+ this.#copyCallbackBound = null;
+ this.#hiddenCopyElement.remove();
+ this.#hiddenCopyElement = null;
+ }
+ }
+ #ensurePageViewVisible() {
+ if (this._scrollMode !== ScrollMode.PAGE) {
+ throw new Error("#ensurePageViewVisible: Invalid scrollMode value.");
+ }
+ const pageNumber = this._currentPageNumber,
+ state = this.#scrollModePageState,
+ viewer = this.viewer;
+ viewer.textContent = "";
+ state.pages.length = 0;
+ if (this._spreadMode === SpreadMode.NONE && !this.isInPresentationMode) {
+ const pageView = this._pages[pageNumber - 1];
+ viewer.append(pageView.div);
+ state.pages.push(pageView);
+ } else {
+ const pageIndexSet = new Set(),
+ parity = this._spreadMode - 1;
+ if (parity === -1) {
+ pageIndexSet.add(pageNumber - 1);
+ } else if (pageNumber % 2 !== parity) {
+ pageIndexSet.add(pageNumber - 1);
+ pageIndexSet.add(pageNumber);
+ } else {
+ pageIndexSet.add(pageNumber - 2);
+ pageIndexSet.add(pageNumber - 1);
+ }
+ const spread = document.createElement("div");
+ spread.className = "spread";
+ if (this.isInPresentationMode) {
+ const dummyPage = document.createElement("div");
+ dummyPage.className = "dummyPage";
+ spread.append(dummyPage);
+ }
+ for (const i of pageIndexSet) {
+ const pageView = this._pages[i];
+ if (!pageView) {
+ continue;
+ }
+ spread.append(pageView.div);
+ state.pages.push(pageView);
+ }
+ viewer.append(spread);
+ }
+ state.scrollDown = pageNumber >= state.previousPageNumber;
+ state.previousPageNumber = pageNumber;
+ }
+ _scrollUpdate() {
+ if (this.pagesCount === 0) {
+ return;
+ }
+ this.update();
+ }
+ #scrollIntoView(pageView, pageSpot = null) {
+ const {
+ div,
+ id
+ } = pageView;
+ if (this._currentPageNumber !== id) {
+ this._setCurrentPageNumber(id);
+ }
+ if (this._scrollMode === ScrollMode.PAGE) {
+ this.#ensurePageViewVisible();
+ this.update();
+ }
+ if (!pageSpot && !this.isInPresentationMode) {
+ const left = div.offsetLeft + div.clientLeft,
+ right = left + div.clientWidth;
+ const {
+ scrollLeft,
+ clientWidth
+ } = this.container;
+ if (this._scrollMode === ScrollMode.HORIZONTAL || left < scrollLeft || right > scrollLeft + clientWidth) {
+ pageSpot = {
+ left: 0,
+ top: 0
+ };
+ }
+ }
+ scrollIntoView(div, pageSpot);
+ if (!this._currentScaleValue && this._location) {
+ this._location = null;
+ }
+ }
+ #isSameScale(newScale) {
+ return newScale === this._currentScale || Math.abs(newScale - this._currentScale) < 1e-15;
+ }
+ #setScaleUpdatePages(newScale, newValue, {
+ noScroll = false,
+ preset = false,
+ drawingDelay = -1
+ }) {
+ this._currentScaleValue = newValue.toString();
+ if (this.#isSameScale(newScale)) {
+ if (preset) {
+ this.eventBus.dispatch("scalechanging", {
+ source: this,
+ scale: newScale,
+ presetValue: newValue
+ });
+ }
+ return;
+ }
+ this.viewer.style.setProperty("--scale-factor", newScale * PixelsPerInch.PDF_TO_CSS_UNITS);
+ const postponeDrawing = drawingDelay >= 0 && drawingDelay < 1000;
+ this.refresh(true, {
+ scale: newScale,
+ drawingDelay: postponeDrawing ? drawingDelay : -1
+ });
+ if (postponeDrawing) {
+ this.#scaleTimeoutId = setTimeout(() => {
+ this.#scaleTimeoutId = null;
+ this.refresh();
+ }, drawingDelay);
+ }
+ this._currentScale = newScale;
+ if (!noScroll) {
+ let page = this._currentPageNumber,
+ dest;
+ if (this._location && !(this.isInPresentationMode || this.isChangingPresentationMode)) {
+ page = this._location.pageNumber;
+ dest = [null, {
+ name: "XYZ"
+ }, this._location.left, this._location.top, null];
+ }
+ this.scrollPageIntoView({
+ pageNumber: page,
+ destArray: dest,
+ allowNegativeOffset: true
+ });
+ }
+ this.eventBus.dispatch("scalechanging", {
+ source: this,
+ scale: newScale,
+ presetValue: preset ? newValue : undefined
+ });
+ if (this.defaultRenderingQueue) {
+ this.update();
+ }
+ }
+ get #pageWidthScaleFactor() {
+ if (this._spreadMode !== SpreadMode.NONE && this._scrollMode !== ScrollMode.HORIZONTAL) {
+ return 2;
+ }
+ return 1;
+ }
+ #setScale(value, options) {
+ let scale = parseFloat(value);
+ if (scale > 0) {
+ options.preset = false;
+ this.#setScaleUpdatePages(scale, value, options);
+ } else {
+ const currentPage = this._pages[this._currentPageNumber - 1];
+ if (!currentPage) {
+ return;
+ }
+ let hPadding = SCROLLBAR_PADDING,
+ vPadding = VERTICAL_PADDING;
+ if (this.isInPresentationMode) {
+ hPadding = vPadding = 4;
+ if (this._spreadMode !== SpreadMode.NONE) {
+ hPadding *= 2;
+ }
+ } else if (this._scrollMode === ScrollMode.HORIZONTAL) {
+ [hPadding, vPadding] = [vPadding, hPadding];
+ }
+ const pageWidthScale = (this.container.clientWidth - hPadding) / currentPage.width * currentPage.scale / this.#pageWidthScaleFactor;
+ const pageHeightScale = (this.container.clientHeight - vPadding) / currentPage.height * currentPage.scale;
+ switch (value) {
+ case "page-actual":
+ scale = 1;
+ break;
+ case "page-width":
+ scale = pageWidthScale;
+ break;
+ case "page-height":
+ scale = pageHeightScale;
+ break;
+ case "page-fit":
+ scale = Math.min(pageWidthScale, pageHeightScale);
+ break;
+ case "auto":
+ const horizontalScale = isPortraitOrientation(currentPage) ? pageWidthScale : Math.min(pageHeightScale, pageWidthScale);
+ scale = Math.min(MAX_AUTO_SCALE, horizontalScale);
+ break;
+ default:
+ console.error(`#setScale: "${value}" is an unknown zoom value.`);
+ return;
+ }
+ options.preset = true;
+ this.#setScaleUpdatePages(scale, value, options);
+ }
+ }
+ #resetCurrentPageView() {
+ const pageView = this._pages[this._currentPageNumber - 1];
+ if (this.isInPresentationMode) {
+ this.#setScale(this._currentScaleValue, {
+ noScroll: true
+ });
+ }
+ this.#scrollIntoView(pageView);
+ }
+ pageLabelToPageNumber(label) {
+ if (!this._pageLabels) {
+ return null;
+ }
+ const i = this._pageLabels.indexOf(label);
+ if (i < 0) {
+ return null;
+ }
+ return i + 1;
+ }
+ scrollPageIntoView({
+ pageNumber,
+ destArray = null,
+ allowNegativeOffset = false,
+ ignoreDestinationZoom = false
+ }) {
+ if (!this.pdfDocument) {
+ return;
+ }
+ const pageView = Number.isInteger(pageNumber) && this._pages[pageNumber - 1];
+ if (!pageView) {
+ console.error(`scrollPageIntoView: "${pageNumber}" is not a valid pageNumber parameter.`);
+ return;
+ }
+ if (this.isInPresentationMode || !destArray) {
+ this._setCurrentPageNumber(pageNumber, true);
+ return;
+ }
+ let x = 0,
+ y = 0;
+ let width = 0,
+ height = 0,
+ widthScale,
+ heightScale;
+ const changeOrientation = pageView.rotation % 180 !== 0;
+ const pageWidth = (changeOrientation ? pageView.height : pageView.width) / pageView.scale / PixelsPerInch.PDF_TO_CSS_UNITS;
+ const pageHeight = (changeOrientation ? pageView.width : pageView.height) / pageView.scale / PixelsPerInch.PDF_TO_CSS_UNITS;
+ let scale = 0;
+ switch (destArray[1].name) {
+ case "XYZ":
+ x = destArray[2];
+ y = destArray[3];
+ scale = destArray[4];
+ x = x !== null ? x : 0;
+ y = y !== null ? y : pageHeight;
+ break;
+ case "Fit":
+ case "FitB":
+ scale = "page-fit";
+ break;
+ case "FitH":
+ case "FitBH":
+ y = destArray[2];
+ scale = "page-width";
+ if (y === null && this._location) {
+ x = this._location.left;
+ y = this._location.top;
+ } else if (typeof y !== "number" || y < 0) {
+ y = pageHeight;
+ }
+ break;
+ case "FitV":
+ case "FitBV":
+ x = destArray[2];
+ width = pageWidth;
+ height = pageHeight;
+ scale = "page-height";
+ break;
+ case "FitR":
+ x = destArray[2];
+ y = destArray[3];
+ width = destArray[4] - x;
+ height = destArray[5] - y;
+ let hPadding = SCROLLBAR_PADDING,
+ vPadding = VERTICAL_PADDING;
+ widthScale = (this.container.clientWidth - hPadding) / width / PixelsPerInch.PDF_TO_CSS_UNITS;
+ heightScale = (this.container.clientHeight - vPadding) / height / PixelsPerInch.PDF_TO_CSS_UNITS;
+ scale = Math.min(Math.abs(widthScale), Math.abs(heightScale));
+ break;
+ default:
+ console.error(`scrollPageIntoView: "${destArray[1].name}" is not a valid destination type.`);
+ return;
+ }
+ if (!ignoreDestinationZoom) {
+ if (scale && scale !== this._currentScale) {
+ this.currentScaleValue = scale;
+ } else if (this._currentScale === UNKNOWN_SCALE) {
+ this.currentScaleValue = DEFAULT_SCALE_VALUE;
+ }
+ }
+ if (scale === "page-fit" && !destArray[4]) {
+ this.#scrollIntoView(pageView);
+ return;
+ }
+ const boundingRect = [pageView.viewport.convertToViewportPoint(x, y), pageView.viewport.convertToViewportPoint(x + width, y + height)];
+ let left = Math.min(boundingRect[0][0], boundingRect[1][0]);
+ let top = Math.min(boundingRect[0][1], boundingRect[1][1]);
+ if (!allowNegativeOffset) {
+ left = Math.max(left, 0);
+ top = Math.max(top, 0);
+ }
+ this.#scrollIntoView(pageView, {
+ left,
+ top
+ });
+ }
+ _updateLocation(firstPage) {
+ const currentScale = this._currentScale;
+ const currentScaleValue = this._currentScaleValue;
+ const normalizedScaleValue = parseFloat(currentScaleValue) === currentScale ? Math.round(currentScale * 10000) / 100 : currentScaleValue;
+ const pageNumber = firstPage.id;
+ const currentPageView = this._pages[pageNumber - 1];
+ const container = this.container;
+ const topLeft = currentPageView.getPagePoint(container.scrollLeft - firstPage.x, container.scrollTop - firstPage.y);
+ const intLeft = Math.round(topLeft[0]);
+ const intTop = Math.round(topLeft[1]);
+ let pdfOpenParams = `#page=${pageNumber}`;
+ if (!this.isInPresentationMode) {
+ pdfOpenParams += `&zoom=${normalizedScaleValue},${intLeft},${intTop}`;
+ }
+ this._location = {
+ pageNumber,
+ scale: normalizedScaleValue,
+ top: intTop,
+ left: intLeft,
+ rotation: this._pagesRotation,
+ pdfOpenParams
+ };
+ }
+ update() {
+ const visible = this._getVisiblePages();
+ const visiblePages = visible.views,
+ numVisiblePages = visiblePages.length;
+ if (numVisiblePages === 0) {
+ return;
+ }
+ const newCacheSize = Math.max(DEFAULT_CACHE_SIZE, 2 * numVisiblePages + 1);
+ this.#buffer.resize(newCacheSize, visible.ids);
+ this.renderingQueue.renderHighestPriority(visible);
+ const isSimpleLayout = this._spreadMode === SpreadMode.NONE && (this._scrollMode === ScrollMode.PAGE || this._scrollMode === ScrollMode.VERTICAL);
+ const currentId = this._currentPageNumber;
+ let stillFullyVisible = false;
+ for (const page of visiblePages) {
+ if (page.percent < 100) {
+ break;
+ }
+ if (page.id === currentId && isSimpleLayout) {
+ stillFullyVisible = true;
+ break;
+ }
+ }
+ this._setCurrentPageNumber(stillFullyVisible ? currentId : visiblePages[0].id);
+ this._updateLocation(visible.first);
+ this.eventBus.dispatch("updateviewarea", {
+ source: this,
+ location: this._location
+ });
+ }
+ containsElement(element) {
+ return this.container.contains(element);
+ }
+ focus() {
+ this.container.focus();
+ }
+ get _isContainerRtl() {
+ return getComputedStyle(this.container).direction === "rtl";
+ }
+ get isInPresentationMode() {
+ return this.presentationModeState === PresentationModeState.FULLSCREEN;
+ }
+ get isChangingPresentationMode() {
+ return this.presentationModeState === PresentationModeState.CHANGING;
+ }
+ get isHorizontalScrollbarEnabled() {
+ return this.isInPresentationMode ? false : this.container.scrollWidth > this.container.clientWidth;
+ }
+ get isVerticalScrollbarEnabled() {
+ return this.isInPresentationMode ? false : this.container.scrollHeight > this.container.clientHeight;
+ }
+ _getVisiblePages() {
+ const views = this._scrollMode === ScrollMode.PAGE ? this.#scrollModePageState.pages : this._pages,
+ horizontal = this._scrollMode === ScrollMode.HORIZONTAL,
+ rtl = horizontal && this._isContainerRtl;
+ return getVisibleElements({
+ scrollEl: this.container,
+ views,
+ sortByVisibility: true,
+ horizontal,
+ rtl
+ });
+ }
+ cleanup() {
+ for (const pageView of this._pages) {
+ if (pageView.renderingState !== RenderingStates.FINISHED) {
+ pageView.reset();
+ }
+ }
+ }
+ _cancelRendering() {
+ for (const pageView of this._pages) {
+ pageView.cancelRendering();
+ }
+ }
+ async #ensurePdfPageLoaded(pageView) {
+ if (pageView.pdfPage) {
+ return pageView.pdfPage;
+ }
+ try {
+ const pdfPage = await this.pdfDocument.getPage(pageView.id);
+ if (!pageView.pdfPage) {
+ pageView.setPdfPage(pdfPage);
+ }
+ if (!this.linkService._cachedPageNumber?.(pdfPage.ref)) {
+ this.linkService.cachePageRef(pageView.id, pdfPage.ref);
+ }
+ return pdfPage;
+ } catch (reason) {
+ console.error("Unable to get page for page view", reason);
+ return null;
+ }
+ }
+ #getScrollAhead(visible) {
+ if (visible.first?.id === 1) {
+ return true;
+ } else if (visible.last?.id === this.pagesCount) {
+ return false;
+ }
+ switch (this._scrollMode) {
+ case ScrollMode.PAGE:
+ return this.#scrollModePageState.scrollDown;
+ case ScrollMode.HORIZONTAL:
+ return this.scroll.right;
+ }
+ return this.scroll.down;
+ }
+ forceRendering(currentlyVisiblePages) {
+ const visiblePages = currentlyVisiblePages || this._getVisiblePages();
+ const scrollAhead = this.#getScrollAhead(visiblePages);
+ const preRenderExtra = this._spreadMode !== SpreadMode.NONE && this._scrollMode !== ScrollMode.HORIZONTAL;
+ const pageView = this.renderingQueue.getHighestPriority(visiblePages, this._pages, scrollAhead, preRenderExtra);
+ if (pageView) {
+ this.#ensurePdfPageLoaded(pageView).then(() => {
+ this.renderingQueue.renderView(pageView);
+ });
+ return true;
+ }
+ return false;
+ }
+ get hasEqualPageSizes() {
+ const firstPageView = this._pages[0];
+ for (let i = 1, ii = this._pages.length; i < ii; ++i) {
+ const pageView = this._pages[i];
+ if (pageView.width !== firstPageView.width || pageView.height !== firstPageView.height) {
+ return false;
+ }
+ }
+ return true;
+ }
+ getPagesOverview() {
+ let initialOrientation;
+ return this._pages.map(pageView => {
+ const viewport = pageView.pdfPage.getViewport({
+ scale: 1
+ });
+ const orientation = isPortraitOrientation(viewport);
+ if (initialOrientation === undefined) {
+ initialOrientation = orientation;
+ } else if (this.enablePrintAutoRotate && orientation !== initialOrientation) {
+ return {
+ width: viewport.height,
+ height: viewport.width,
+ rotation: (viewport.rotation - 90) % 360
+ };
+ }
+ return {
+ width: viewport.width,
+ height: viewport.height,
+ rotation: viewport.rotation
+ };
+ });
+ }
+ get optionalContentConfigPromise() {
+ if (!this.pdfDocument) {
+ return Promise.resolve(null);
+ }
+ if (!this._optionalContentConfigPromise) {
+ console.error("optionalContentConfigPromise: Not initialized yet.");
+ return this.pdfDocument.getOptionalContentConfig();
+ }
+ return this._optionalContentConfigPromise;
+ }
+ set optionalContentConfigPromise(promise) {
+ if (!(promise instanceof Promise)) {
+ throw new Error(`Invalid optionalContentConfigPromise: ${promise}`);
+ }
+ if (!this.pdfDocument) {
+ return;
+ }
+ if (!this._optionalContentConfigPromise) {
+ return;
+ }
+ this._optionalContentConfigPromise = promise;
+ this.refresh(false, {
+ optionalContentConfigPromise: promise
+ });
+ this.eventBus.dispatch("optionalcontentconfigchanged", {
+ source: this,
+ promise
+ });
+ }
+ get scrollMode() {
+ return this._scrollMode;
+ }
+ set scrollMode(mode) {
+ if (this._scrollMode === mode) {
+ return;
+ }
+ if (!isValidScrollMode(mode)) {
+ throw new Error(`Invalid scroll mode: ${mode}`);
+ }
+ if (this.pagesCount > PagesCountLimit.FORCE_SCROLL_MODE_PAGE) {
+ return;
+ }
+ this._previousScrollMode = this._scrollMode;
+ this._scrollMode = mode;
+ this.eventBus.dispatch("scrollmodechanged", {
+ source: this,
+ mode
+ });
+ this._updateScrollMode(this._currentPageNumber);
+ }
+ _updateScrollMode(pageNumber = null) {
+ const scrollMode = this._scrollMode,
+ viewer = this.viewer;
+ viewer.classList.toggle("scrollHorizontal", scrollMode === ScrollMode.HORIZONTAL);
+ viewer.classList.toggle("scrollWrapped", scrollMode === ScrollMode.WRAPPED);
+ if (!this.pdfDocument || !pageNumber) {
+ return;
+ }
+ if (scrollMode === ScrollMode.PAGE) {
+ this.#ensurePageViewVisible();
+ } else if (this._previousScrollMode === ScrollMode.PAGE) {
+ this._updateSpreadMode();
+ }
+ if (this._currentScaleValue && isNaN(this._currentScaleValue)) {
+ this.#setScale(this._currentScaleValue, {
+ noScroll: true
+ });
+ }
+ this._setCurrentPageNumber(pageNumber, true);
+ this.update();
+ }
+ get spreadMode() {
+ return this._spreadMode;
+ }
+ set spreadMode(mode) {
+ if (this._spreadMode === mode) {
+ return;
+ }
+ if (!isValidSpreadMode(mode)) {
+ throw new Error(`Invalid spread mode: ${mode}`);
+ }
+ this._spreadMode = mode;
+ this.eventBus.dispatch("spreadmodechanged", {
+ source: this,
+ mode
+ });
+ this._updateSpreadMode(this._currentPageNumber);
+ }
+ _updateSpreadMode(pageNumber = null) {
+ if (!this.pdfDocument) {
+ return;
+ }
+ const viewer = this.viewer,
+ pages = this._pages;
+ if (this._scrollMode === ScrollMode.PAGE) {
+ this.#ensurePageViewVisible();
+ } else {
+ viewer.textContent = "";
+ if (this._spreadMode === SpreadMode.NONE) {
+ for (const pageView of this._pages) {
+ viewer.append(pageView.div);
+ }
+ } else {
+ const parity = this._spreadMode - 1;
+ let spread = null;
+ for (let i = 0, ii = pages.length; i < ii; ++i) {
+ if (spread === null) {
+ spread = document.createElement("div");
+ spread.className = "spread";
+ viewer.append(spread);
+ } else if (i % 2 === parity) {
+ spread = spread.cloneNode(false);
+ viewer.append(spread);
+ }
+ spread.append(pages[i].div);
+ }
+ }
+ }
+ if (!pageNumber) {
+ return;
+ }
+ if (this._currentScaleValue && isNaN(this._currentScaleValue)) {
+ this.#setScale(this._currentScaleValue, {
+ noScroll: true
+ });
+ }
+ this._setCurrentPageNumber(pageNumber, true);
+ this.update();
+ }
+ _getPageAdvance(currentPageNumber, previous = false) {
+ switch (this._scrollMode) {
+ case ScrollMode.WRAPPED:
+ {
+ const {
+ views
+ } = this._getVisiblePages(),
+ pageLayout = new Map();
+ for (const {
+ id,
+ y,
+ percent,
+ widthPercent
+ } of views) {
+ if (percent === 0 || widthPercent < 100) {
+ continue;
+ }
+ let yArray = pageLayout.get(y);
+ if (!yArray) {
+ pageLayout.set(y, yArray ||= []);
+ }
+ yArray.push(id);
+ }
+ for (const yArray of pageLayout.values()) {
+ const currentIndex = yArray.indexOf(currentPageNumber);
+ if (currentIndex === -1) {
+ continue;
+ }
+ const numPages = yArray.length;
+ if (numPages === 1) {
+ break;
+ }
+ if (previous) {
+ for (let i = currentIndex - 1, ii = 0; i >= ii; i--) {
+ const currentId = yArray[i],
+ expectedId = yArray[i + 1] - 1;
+ if (currentId < expectedId) {
+ return currentPageNumber - expectedId;
+ }
+ }
+ } else {
+ for (let i = currentIndex + 1, ii = numPages; i < ii; i++) {
+ const currentId = yArray[i],
+ expectedId = yArray[i - 1] + 1;
+ if (currentId > expectedId) {
+ return expectedId - currentPageNumber;
+ }
+ }
+ }
+ if (previous) {
+ const firstId = yArray[0];
+ if (firstId < currentPageNumber) {
+ return currentPageNumber - firstId + 1;
+ }
+ } else {
+ const lastId = yArray[numPages - 1];
+ if (lastId > currentPageNumber) {
+ return lastId - currentPageNumber + 1;
+ }
+ }
+ break;
+ }
+ break;
+ }
+ case ScrollMode.HORIZONTAL:
+ {
+ break;
+ }
+ case ScrollMode.PAGE:
+ case ScrollMode.VERTICAL:
+ {
+ if (this._spreadMode === SpreadMode.NONE) {
+ break;
+ }
+ const parity = this._spreadMode - 1;
+ if (previous && currentPageNumber % 2 !== parity) {
+ break;
+ } else if (!previous && currentPageNumber % 2 === parity) {
+ break;
+ }
+ const {
+ views
+ } = this._getVisiblePages(),
+ expectedId = previous ? currentPageNumber - 1 : currentPageNumber + 1;
+ for (const {
+ id,
+ percent,
+ widthPercent
+ } of views) {
+ if (id !== expectedId) {
+ continue;
+ }
+ if (percent > 0 && widthPercent === 100) {
+ return 2;
+ }
+ break;
+ }
+ break;
+ }
+ }
+ return 1;
+ }
+ nextPage() {
+ const currentPageNumber = this._currentPageNumber,
+ pagesCount = this.pagesCount;
+ if (currentPageNumber >= pagesCount) {
+ return false;
+ }
+ const advance = this._getPageAdvance(currentPageNumber, false) || 1;
+ this.currentPageNumber = Math.min(currentPageNumber + advance, pagesCount);
+ return true;
+ }
+ previousPage() {
+ const currentPageNumber = this._currentPageNumber;
+ if (currentPageNumber <= 1) {
+ return false;
+ }
+ const advance = this._getPageAdvance(currentPageNumber, true) || 1;
+ this.currentPageNumber = Math.max(currentPageNumber - advance, 1);
+ return true;
+ }
+ increaseScale({
+ drawingDelay,
+ scaleFactor,
+ steps
+ } = {}) {
+ if (!this.pdfDocument) {
+ return;
+ }
+ let newScale = this._currentScale;
+ if (scaleFactor > 1) {
+ newScale = Math.round(newScale * scaleFactor * 100) / 100;
+ } else {
+ steps ??= 1;
+ do {
+ newScale = Math.ceil((newScale * DEFAULT_SCALE_DELTA).toFixed(2) * 10) / 10;
+ } while (--steps > 0 && newScale < MAX_SCALE);
+ }
+ this.#setScale(Math.min(MAX_SCALE, newScale), {
+ noScroll: false,
+ drawingDelay
+ });
+ }
+ decreaseScale({
+ drawingDelay,
+ scaleFactor,
+ steps
+ } = {}) {
+ if (!this.pdfDocument) {
+ return;
+ }
+ let newScale = this._currentScale;
+ if (scaleFactor > 0 && scaleFactor < 1) {
+ newScale = Math.round(newScale * scaleFactor * 100) / 100;
+ } else {
+ steps ??= 1;
+ do {
+ newScale = Math.floor((newScale / DEFAULT_SCALE_DELTA).toFixed(2) * 10) / 10;
+ } while (--steps > 0 && newScale > MIN_SCALE);
+ }
+ this.#setScale(Math.max(MIN_SCALE, newScale), {
+ noScroll: false,
+ drawingDelay
+ });
+ }
+ #updateContainerHeightCss(height = this.container.clientHeight) {
+ if (height !== this.#previousContainerHeight) {
+ this.#previousContainerHeight = height;
+ docStyle.setProperty("--viewer-container-height", `${height}px`);
+ }
+ }
+ #resizeObserverCallback(entries) {
+ for (const entry of entries) {
+ if (entry.target === this.container) {
+ this.#updateContainerHeightCss(Math.floor(entry.borderBoxSize[0].blockSize));
+ this.#containerTopLeft = null;
+ break;
+ }
+ }
+ }
+ get containerTopLeft() {
+ return this.#containerTopLeft ||= [this.container.offsetTop, this.container.offsetLeft];
+ }
+ get annotationEditorMode() {
+ return this.#annotationEditorUIManager ? this.#annotationEditorMode : AnnotationEditorType.DISABLE;
+ }
+ set annotationEditorMode({
+ mode,
+ editId = null,
+ isFromKeyboard = false
+ }) {
+ if (!this.#annotationEditorUIManager) {
+ throw new Error(`The AnnotationEditor is not enabled.`);
+ }
+ if (this.#annotationEditorMode === mode) {
+ return;
+ }
+ if (!isValidAnnotationEditorMode(mode)) {
+ throw new Error(`Invalid AnnotationEditor mode: ${mode}`);
+ }
+ if (!this.pdfDocument) {
+ return;
+ }
+ this.#annotationEditorMode = mode;
+ this.eventBus.dispatch("annotationeditormodechanged", {
+ source: this,
+ mode
+ });
+ this.#annotationEditorUIManager.updateMode(mode, editId, isFromKeyboard);
+ }
+ set annotationEditorParams({
+ type,
+ value
+ }) {
+ if (!this.#annotationEditorUIManager) {
+ throw new Error(`The AnnotationEditor is not enabled.`);
+ }
+ this.#annotationEditorUIManager.updateParams(type, value);
+ }
+ refresh(noUpdate = false, updateArgs = Object.create(null)) {
+ if (!this.pdfDocument) {
+ return;
+ }
+ for (const pageView of this._pages) {
+ pageView.update(updateArgs);
+ }
+ if (this.#scaleTimeoutId !== null) {
+ clearTimeout(this.#scaleTimeoutId);
+ this.#scaleTimeoutId = null;
+ }
+ if (!noUpdate) {
+ this.update();
+ }
+ }
+}
+
+;// CONCATENATED MODULE: ./web/secondary_toolbar.js
+
+
+class SecondaryToolbar {
+ #opts;
+ constructor(options, eventBus) {
+ this.#opts = options;
+ const buttons = [{
+ element: options.presentationModeButton,
+ eventName: "presentationmode",
+ close: true
+ }, {
+ element: options.printButton,
+ eventName: "print",
+ close: true
+ }, {
+ element: options.downloadButton,
+ eventName: "download",
+ close: true
+ }, {
+ element: options.viewBookmarkButton,
+ eventName: null,
+ close: true
+ }, {
+ element: options.firstPageButton,
+ eventName: "firstpage",
+ close: true
+ }, {
+ element: options.lastPageButton,
+ eventName: "lastpage",
+ close: true
+ }, {
+ element: options.pageRotateCwButton,
+ eventName: "rotatecw",
+ close: false
+ }, {
+ element: options.pageRotateCcwButton,
+ eventName: "rotateccw",
+ close: false
+ }, {
+ element: options.cursorSelectToolButton,
+ eventName: "switchcursortool",
+ eventDetails: {
+ tool: CursorTool.SELECT
+ },
+ close: true
+ }, {
+ element: options.cursorHandToolButton,
+ eventName: "switchcursortool",
+ eventDetails: {
+ tool: CursorTool.HAND
+ },
+ close: true
+ }, {
+ element: options.scrollPageButton,
+ eventName: "switchscrollmode",
+ eventDetails: {
+ mode: ScrollMode.PAGE
+ },
+ close: true
+ }, {
+ element: options.scrollVerticalButton,
+ eventName: "switchscrollmode",
+ eventDetails: {
+ mode: ScrollMode.VERTICAL
+ },
+ close: true
+ }, {
+ element: options.scrollHorizontalButton,
+ eventName: "switchscrollmode",
+ eventDetails: {
+ mode: ScrollMode.HORIZONTAL
+ },
+ close: true
+ }, {
+ element: options.scrollWrappedButton,
+ eventName: "switchscrollmode",
+ eventDetails: {
+ mode: ScrollMode.WRAPPED
+ },
+ close: true
+ }, {
+ element: options.spreadNoneButton,
+ eventName: "switchspreadmode",
+ eventDetails: {
+ mode: SpreadMode.NONE
+ },
+ close: true
+ }, {
+ element: options.spreadOddButton,
+ eventName: "switchspreadmode",
+ eventDetails: {
+ mode: SpreadMode.ODD
+ },
+ close: true
+ }, {
+ element: options.spreadEvenButton,
+ eventName: "switchspreadmode",
+ eventDetails: {
+ mode: SpreadMode.EVEN
+ },
+ close: true
+ }, {
+ element: options.documentPropertiesButton,
+ eventName: "documentproperties",
+ close: true
+ }];
+ this.eventBus = eventBus;
+ this.opened = false;
+ this.#bindListeners(buttons);
+ this.reset();
+ }
+ get isOpen() {
+ return this.opened;
+ }
+ setPageNumber(pageNumber) {
+ this.pageNumber = pageNumber;
+ this.#updateUIState();
+ }
+ setPagesCount(pagesCount) {
+ this.pagesCount = pagesCount;
+ this.#updateUIState();
+ }
+ reset() {
+ this.pageNumber = 0;
+ this.pagesCount = 0;
+ this.#updateUIState();
+ this.#scrollModeChanged({
+ mode: ScrollMode.VERTICAL
+ });
+ this.#spreadModeChanged({
+ mode: SpreadMode.NONE
+ });
+ }
+ #updateUIState() {
+ const {
+ firstPageButton,
+ lastPageButton,
+ pageRotateCwButton,
+ pageRotateCcwButton
+ } = this.#opts;
+ firstPageButton.disabled = this.pageNumber <= 1;
+ lastPageButton.disabled = this.pageNumber >= this.pagesCount;
+ pageRotateCwButton.disabled = this.pagesCount === 0;
+ pageRotateCcwButton.disabled = this.pagesCount === 0;
+ }
+ #bindListeners(buttons) {
+ const {
+ eventBus
+ } = this;
+ const {
+ toggleButton
+ } = this.#opts;
+ toggleButton.addEventListener("click", this.toggle.bind(this));
+ for (const {
+ element,
+ eventName,
+ close,
+ eventDetails
+ } of buttons) {
+ element.addEventListener("click", evt => {
+ if (eventName !== null) {
+ eventBus.dispatch(eventName, {
+ source: this,
+ ...eventDetails
+ });
+ }
+ if (close) {
+ this.close();
+ }
+ eventBus.dispatch("reporttelemetry", {
+ source: this,
+ details: {
+ type: "buttons",
+ data: {
+ id: element.id
+ }
+ }
+ });
+ });
+ }
+ eventBus._on("cursortoolchanged", this.#cursorToolChanged.bind(this));
+ eventBus._on("scrollmodechanged", this.#scrollModeChanged.bind(this));
+ eventBus._on("spreadmodechanged", this.#spreadModeChanged.bind(this));
+ }
+ #cursorToolChanged({
+ tool
+ }) {
+ const {
+ cursorSelectToolButton,
+ cursorHandToolButton
+ } = this.#opts;
+ toggleCheckedBtn(cursorSelectToolButton, tool === CursorTool.SELECT);
+ toggleCheckedBtn(cursorHandToolButton, tool === CursorTool.HAND);
+ }
+ #scrollModeChanged({
+ mode
+ }) {
+ const {
+ scrollPageButton,
+ scrollVerticalButton,
+ scrollHorizontalButton,
+ scrollWrappedButton,
+ spreadNoneButton,
+ spreadOddButton,
+ spreadEvenButton
+ } = this.#opts;
+ toggleCheckedBtn(scrollPageButton, mode === ScrollMode.PAGE);
+ toggleCheckedBtn(scrollVerticalButton, mode === ScrollMode.VERTICAL);
+ toggleCheckedBtn(scrollHorizontalButton, mode === ScrollMode.HORIZONTAL);
+ toggleCheckedBtn(scrollWrappedButton, mode === ScrollMode.WRAPPED);
+ const forceScrollModePage = this.pagesCount > PagesCountLimit.FORCE_SCROLL_MODE_PAGE;
+ scrollPageButton.disabled = forceScrollModePage;
+ scrollVerticalButton.disabled = forceScrollModePage;
+ scrollHorizontalButton.disabled = forceScrollModePage;
+ scrollWrappedButton.disabled = forceScrollModePage;
+ const isHorizontal = mode === ScrollMode.HORIZONTAL;
+ spreadNoneButton.disabled = isHorizontal;
+ spreadOddButton.disabled = isHorizontal;
+ spreadEvenButton.disabled = isHorizontal;
+ }
+ #spreadModeChanged({
+ mode
+ }) {
+ const {
+ spreadNoneButton,
+ spreadOddButton,
+ spreadEvenButton
+ } = this.#opts;
+ toggleCheckedBtn(spreadNoneButton, mode === SpreadMode.NONE);
+ toggleCheckedBtn(spreadOddButton, mode === SpreadMode.ODD);
+ toggleCheckedBtn(spreadEvenButton, mode === SpreadMode.EVEN);
+ }
+ open() {
+ if (this.opened) {
+ return;
+ }
+ this.opened = true;
+ const {
+ toggleButton,
+ toolbar
+ } = this.#opts;
+ toggleExpandedBtn(toggleButton, true, toolbar);
+ }
+ close() {
+ if (!this.opened) {
+ return;
+ }
+ this.opened = false;
+ const {
+ toggleButton,
+ toolbar
+ } = this.#opts;
+ toggleExpandedBtn(toggleButton, false, toolbar);
+ }
+ toggle() {
+ if (this.opened) {
+ this.close();
+ } else {
+ this.open();
+ }
+ }
+}
+
+;// CONCATENATED MODULE: ./web/toolbar.js
+
+
+class Toolbar {
+ #opts;
+ constructor(options, eventBus) {
+ this.#opts = options;
+ this.eventBus = eventBus;
+ const buttons = [{
+ element: options.previous,
+ eventName: "previouspage"
+ }, {
+ element: options.next,
+ eventName: "nextpage"
+ }, {
+ element: options.zoomIn,
+ eventName: "zoomin"
+ }, {
+ element: options.zoomOut,
+ eventName: "zoomout"
+ }, {
+ element: options.print,
+ eventName: "print"
+ }, {
+ element: options.download,
+ eventName: "download"
+ }, {
+ element: options.editorFreeTextButton,
+ eventName: "switchannotationeditormode",
+ eventDetails: {
+ get mode() {
+ const {
+ classList
+ } = options.editorFreeTextButton;
+ return classList.contains("toggled") ? AnnotationEditorType.NONE : AnnotationEditorType.FREETEXT;
+ }
+ }
+ }, {
+ element: options.editorHighlightButton,
+ eventName: "switchannotationeditormode",
+ eventDetails: {
+ get mode() {
+ const {
+ classList
+ } = options.editorHighlightButton;
+ return classList.contains("toggled") ? AnnotationEditorType.NONE : AnnotationEditorType.HIGHLIGHT;
+ }
+ }
+ }, {
+ element: options.editorInkButton,
+ eventName: "switchannotationeditormode",
+ eventDetails: {
+ get mode() {
+ const {
+ classList
+ } = options.editorInkButton;
+ return classList.contains("toggled") ? AnnotationEditorType.NONE : AnnotationEditorType.INK;
+ }
+ }
+ }, {
+ element: options.editorStampButton,
+ eventName: "switchannotationeditormode",
+ eventDetails: {
+ get mode() {
+ const {
+ classList
+ } = options.editorStampButton;
+ return classList.contains("toggled") ? AnnotationEditorType.NONE : AnnotationEditorType.STAMP;
+ }
+ }
+ }];
+ this.#bindListeners(buttons);
+ if (options.editorHighlightColorPicker) {
+ eventBus._on("annotationeditoruimanager", ({
+ uiManager
+ }) => {
+ this.#setAnnotationEditorUIManager(uiManager, options.editorHighlightColorPicker);
+ }, {
+ once: true
+ });
+ }
+ eventBus._on("showannotationeditorui", ({
+ mode
+ }) => {
+ switch (mode) {
+ case AnnotationEditorType.HIGHLIGHT:
+ options.editorHighlightButton.click();
+ break;
+ }
+ });
+ this.reset();
+ }
+ #setAnnotationEditorUIManager(uiManager, parentContainer) {
+ const colorPicker = new ColorPicker({
+ uiManager
+ });
+ uiManager.setMainHighlightColorPicker(colorPicker);
+ parentContainer.append(colorPicker.renderMainDropdown());
+ }
+ setPageNumber(pageNumber, pageLabel) {
+ this.pageNumber = pageNumber;
+ this.pageLabel = pageLabel;
+ this.#updateUIState(false);
+ }
+ setPagesCount(pagesCount, hasPageLabels) {
+ this.pagesCount = pagesCount;
+ this.hasPageLabels = hasPageLabels;
+ this.#updateUIState(true);
+ }
+ setPageScale(pageScaleValue, pageScale) {
+ this.pageScaleValue = (pageScaleValue || pageScale).toString();
+ this.pageScale = pageScale;
+ this.#updateUIState(false);
+ }
+ reset() {
+ this.pageNumber = 0;
+ this.pageLabel = null;
+ this.hasPageLabels = false;
+ this.pagesCount = 0;
+ this.pageScaleValue = DEFAULT_SCALE_VALUE;
+ this.pageScale = DEFAULT_SCALE;
+ this.#updateUIState(true);
+ this.updateLoadingIndicatorState();
+ this.#editorModeChanged({
+ mode: AnnotationEditorType.DISABLE
+ });
+ }
+ #bindListeners(buttons) {
+ const {
+ eventBus
+ } = this;
+ const {
+ pageNumber,
+ scaleSelect
+ } = this.#opts;
+ const self = this;
+ for (const {
+ element,
+ eventName,
+ eventDetails
+ } of buttons) {
+ element.addEventListener("click", evt => {
+ if (eventName !== null) {
+ eventBus.dispatch(eventName, {
+ source: this,
+ ...eventDetails,
+ isFromKeyboard: evt.detail === 0
+ });
+ }
+ });
+ }
+ pageNumber.addEventListener("click", function () {
+ this.select();
+ });
+ pageNumber.addEventListener("change", function () {
+ eventBus.dispatch("pagenumberchanged", {
+ source: self,
+ value: this.value
+ });
+ });
+ scaleSelect.addEventListener("change", function () {
+ if (this.value === "custom") {
+ return;
+ }
+ eventBus.dispatch("scalechanged", {
+ source: self,
+ value: this.value
+ });
+ });
+ scaleSelect.addEventListener("click", function ({
+ target
+ }) {
+ if (this.value === self.pageScaleValue && target.tagName.toUpperCase() === "OPTION") {
+ this.blur();
+ }
+ });
+ scaleSelect.oncontextmenu = noContextMenu;
+ eventBus._on("annotationeditormodechanged", this.#editorModeChanged.bind(this));
+ }
+ #editorModeChanged({
+ mode
+ }) {
+ const {
+ editorFreeTextButton,
+ editorFreeTextParamsToolbar,
+ editorHighlightButton,
+ editorHighlightParamsToolbar,
+ editorInkButton,
+ editorInkParamsToolbar,
+ editorStampButton,
+ editorStampParamsToolbar
+ } = this.#opts;
+ toggleCheckedBtn(editorFreeTextButton, mode === AnnotationEditorType.FREETEXT, editorFreeTextParamsToolbar);
+ toggleCheckedBtn(editorHighlightButton, mode === AnnotationEditorType.HIGHLIGHT, editorHighlightParamsToolbar);
+ toggleCheckedBtn(editorInkButton, mode === AnnotationEditorType.INK, editorInkParamsToolbar);
+ toggleCheckedBtn(editorStampButton, mode === AnnotationEditorType.STAMP, editorStampParamsToolbar);
+ const isDisable = mode === AnnotationEditorType.DISABLE;
+ editorFreeTextButton.disabled = isDisable;
+ editorHighlightButton.disabled = isDisable;
+ editorInkButton.disabled = isDisable;
+ editorStampButton.disabled = isDisable;
+ }
+ #updateUIState(resetNumPages = false) {
+ const {
+ pageNumber,
+ pagesCount,
+ pageScaleValue,
+ pageScale
+ } = this;
+ const opts = this.#opts;
+ if (resetNumPages) {
+ if (this.hasPageLabels) {
+ opts.pageNumber.type = "text";
+ opts.numPages.setAttribute("data-l10n-id", "pdfjs-page-of-pages");
+ } else {
+ opts.pageNumber.type = "number";
+ opts.numPages.setAttribute("data-l10n-id", "pdfjs-of-pages");
+ opts.numPages.setAttribute("data-l10n-args", JSON.stringify({
+ pagesCount
+ }));
+ }
+ opts.pageNumber.max = pagesCount;
+ }
+ if (this.hasPageLabels) {
+ opts.pageNumber.value = this.pageLabel;
+ opts.numPages.setAttribute("data-l10n-args", JSON.stringify({
+ pageNumber,
+ pagesCount
+ }));
+ } else {
+ opts.pageNumber.value = pageNumber;
+ }
+ opts.previous.disabled = pageNumber <= 1;
+ opts.next.disabled = pageNumber >= pagesCount;
+ opts.zoomOut.disabled = pageScale <= MIN_SCALE;
+ opts.zoomIn.disabled = pageScale >= MAX_SCALE;
+ let predefinedValueFound = false;
+ for (const option of opts.scaleSelect.options) {
+ if (option.value !== pageScaleValue) {
+ option.selected = false;
+ continue;
+ }
+ option.selected = true;
+ predefinedValueFound = true;
+ }
+ if (!predefinedValueFound) {
+ opts.customScaleOption.selected = true;
+ opts.customScaleOption.setAttribute("data-l10n-args", JSON.stringify({
+ scale: Math.round(pageScale * 10000) / 100
+ }));
+ }
+ }
+ updateLoadingIndicatorState(loading = false) {
+ const {
+ pageNumber
+ } = this.#opts;
+ pageNumber.classList.toggle("loading", loading);
+ }
+}
+
+;// CONCATENATED MODULE: ./web/view_history.js
+const DEFAULT_VIEW_HISTORY_CACHE_SIZE = 20;
+class ViewHistory {
+ constructor(fingerprint, cacheSize = DEFAULT_VIEW_HISTORY_CACHE_SIZE) {
+ this.fingerprint = fingerprint;
+ this.cacheSize = cacheSize;
+ this._initializedPromise = this._readFromStorage().then(databaseStr => {
+ const database = JSON.parse(databaseStr || "{}");
+ let index = -1;
+ if (!Array.isArray(database.files)) {
+ database.files = [];
+ } else {
+ while (database.files.length >= this.cacheSize) {
+ database.files.shift();
+ }
+ for (let i = 0, ii = database.files.length; i < ii; i++) {
+ const branch = database.files[i];
+ if (branch.fingerprint === this.fingerprint) {
+ index = i;
+ break;
+ }
+ }
+ }
+ if (index === -1) {
+ index = database.files.push({
+ fingerprint: this.fingerprint
+ }) - 1;
+ }
+ this.file = database.files[index];
+ this.database = database;
+ });
+ }
+ async _writeToStorage() {
+ const databaseStr = JSON.stringify(this.database);
+ sessionStorage.setItem("pdfjs.history", databaseStr);
+ }
+ async _readFromStorage() {
+ return sessionStorage.getItem("pdfjs.history");
+ }
+ async set(name, val) {
+ await this._initializedPromise;
+ this.file[name] = val;
+ return this._writeToStorage();
+ }
+ async setMultiple(properties) {
+ await this._initializedPromise;
+ for (const name in properties) {
+ this.file[name] = properties[name];
+ }
+ return this._writeToStorage();
+ }
+ async get(name, defaultValue) {
+ await this._initializedPromise;
+ const val = this.file[name];
+ return val !== undefined ? val : defaultValue;
+ }
+ async getMultiple(properties) {
+ await this._initializedPromise;
+ const values = Object.create(null);
+ for (const name in properties) {
+ const val = this.file[name];
+ values[name] = val !== undefined ? val : properties[name];
+ }
+ return values;
+ }
+}
+
+;// CONCATENATED MODULE: ./web/app.js
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+const FORCE_PAGES_LOADED_TIMEOUT = 10000;
+const WHEEL_ZOOM_DISABLED_TIMEOUT = 1000;
+const ViewOnLoad = {
+ UNKNOWN: -1,
+ PREVIOUS: 0,
+ INITIAL: 1
+};
+const PDFViewerApplication = {
+ initialBookmark: document.location.hash.substring(1),
+ _initializedCapability: new PromiseCapability(),
+ appConfig: null,
+ pdfDocument: null,
+ pdfLoadingTask: null,
+ printService: null,
+ pdfViewer: null,
+ pdfThumbnailViewer: null,
+ pdfRenderingQueue: null,
+ pdfPresentationMode: null,
+ pdfDocumentProperties: null,
+ pdfLinkService: null,
+ pdfHistory: null,
+ pdfSidebar: null,
+ pdfOutlineViewer: null,
+ pdfAttachmentViewer: null,
+ pdfLayerViewer: null,
+ pdfCursorTools: null,
+ pdfScriptingManager: null,
+ store: null,
+ downloadManager: null,
+ overlayManager: null,
+ preferences: null,
+ toolbar: null,
+ secondaryToolbar: null,
+ eventBus: null,
+ l10n: null,
+ annotationEditorParams: null,
+ isInitialViewSet: false,
+ downloadComplete: false,
+ isViewerEmbedded: window.parent !== window,
+ url: "",
+ baseUrl: "",
+ _downloadUrl: "",
+ _boundEvents: Object.create(null),
+ documentInfo: null,
+ metadata: null,
+ _contentDispositionFilename: null,
+ _contentLength: null,
+ _saveInProgress: false,
+ _wheelUnusedTicks: 0,
+ _wheelUnusedFactor: 1,
+ _touchUnusedTicks: 0,
+ _touchUnusedFactor: 1,
+ _PDFBug: null,
+ _hasAnnotationEditors: false,
+ _title: document.title,
+ _printAnnotationStoragePromise: null,
+ _touchInfo: null,
+ _isCtrlKeyDown: false,
+ _nimbusDataPromise: null,
+ _caretBrowsing: null,
+ _isScrolling: false,
+ _lastScrollTop: 0,
+ _lastScrollLeft: 0,
+ async initialize(appConfig) {
+ let l10nPromise;
+ l10nPromise = this.externalServices.createL10n();
+ this.appConfig = appConfig;
+ try {
+ await this.preferences.initializedPromise;
+ } catch (ex) {
+ console.error(`initialize: "${ex.message}".`);
+ }
+ if (AppOptions.get("pdfBugEnabled")) {
+ await this._parseHashParams();
+ }
+ this.l10n = await l10nPromise;
+ document.getElementsByTagName("html")[0].dir = this.l10n.getDirection();
+ if (this.isViewerEmbedded && AppOptions.get("externalLinkTarget") === LinkTarget.NONE) {
+ AppOptions.set("externalLinkTarget", LinkTarget.TOP);
+ }
+ await this._initializeViewerComponents();
+ this.bindEvents();
+ this.bindWindowEvents();
+ this._initializedCapability.resolve();
+ },
+ async _parseHashParams() {
+ const hash = document.location.hash.substring(1);
+ if (!hash) {
+ return;
+ }
+ const {
+ mainContainer,
+ viewerContainer
+ } = this.appConfig,
+ params = parseQueryString(hash);
+ if (params.get("disableworker") === "true") {
+ try {
+ await loadFakeWorker();
+ } catch (ex) {
+ console.error(`_parseHashParams: "${ex.message}".`);
+ }
+ }
+ if (params.has("disablerange")) {
+ AppOptions.set("disableRange", params.get("disablerange") === "true");
+ }
+ if (params.has("disablestream")) {
+ AppOptions.set("disableStream", params.get("disablestream") === "true");
+ }
+ if (params.has("disableautofetch")) {
+ AppOptions.set("disableAutoFetch", params.get("disableautofetch") === "true");
+ }
+ if (params.has("disablefontface")) {
+ AppOptions.set("disableFontFace", params.get("disablefontface") === "true");
+ }
+ if (params.has("disablehistory")) {
+ AppOptions.set("disableHistory", params.get("disablehistory") === "true");
+ }
+ if (params.has("verbosity")) {
+ AppOptions.set("verbosity", params.get("verbosity") | 0);
+ }
+ if (params.has("textlayer")) {
+ switch (params.get("textlayer")) {
+ case "off":
+ AppOptions.set("textLayerMode", TextLayerMode.DISABLE);
+ break;
+ case "visible":
+ case "shadow":
+ case "hover":
+ viewerContainer.classList.add(`textLayer-${params.get("textlayer")}`);
+ try {
+ await loadPDFBug(this);
+ this._PDFBug.loadCSS();
+ } catch (ex) {
+ console.error(`_parseHashParams: "${ex.message}".`);
+ }
+ break;
+ }
+ }
+ if (params.has("pdfbug")) {
+ AppOptions.set("pdfBug", true);
+ AppOptions.set("fontExtraProperties", true);
+ const enabled = params.get("pdfbug").split(",");
+ try {
+ await loadPDFBug(this);
+ this._PDFBug.init(mainContainer, enabled);
+ } catch (ex) {
+ console.error(`_parseHashParams: "${ex.message}".`);
+ }
+ }
+ },
+ async _initializeViewerComponents() {
+ const {
+ appConfig,
+ externalServices,
+ l10n
+ } = this;
+ const eventBus = AppOptions.get("isInAutomation") ? new AutomationEventBus() : new EventBus();
+ this.eventBus = eventBus;
+ this.overlayManager = new OverlayManager();
+ const pdfRenderingQueue = new PDFRenderingQueue();
+ pdfRenderingQueue.onIdle = this._cleanup.bind(this);
+ this.pdfRenderingQueue = pdfRenderingQueue;
+ const pdfLinkService = new PDFLinkService({
+ eventBus,
+ externalLinkTarget: AppOptions.get("externalLinkTarget"),
+ externalLinkRel: AppOptions.get("externalLinkRel"),
+ ignoreDestinationZoom: AppOptions.get("ignoreDestinationZoom")
+ });
+ this.pdfLinkService = pdfLinkService;
+ const downloadManager = this.downloadManager = new DownloadManager();
+ const findController = new PDFFindController({
+ linkService: pdfLinkService,
+ eventBus,
+ updateMatchesCountOnProgress: true
+ });
+ this.findController = findController;
+ const pdfScriptingManager = new PDFScriptingManager({
+ eventBus,
+ externalServices,
+ docProperties: this._scriptingDocProperties.bind(this)
+ });
+ this.pdfScriptingManager = pdfScriptingManager;
+ const container = appConfig.mainContainer,
+ viewer = appConfig.viewerContainer;
+ const annotationEditorMode = AppOptions.get("annotationEditorMode");
+ const isOffscreenCanvasSupported = AppOptions.get("isOffscreenCanvasSupported") && FeatureTest.isOffscreenCanvasSupported;
+ const pageColors = AppOptions.get("forcePageColors") || window.matchMedia("(forced-colors: active)").matches ? {
+ background: AppOptions.get("pageColorsBackground"),
+ foreground: AppOptions.get("pageColorsForeground")
+ } : null;
+ const altTextManager = appConfig.altTextDialog ? new AltTextManager(appConfig.altTextDialog, container, this.overlayManager, eventBus) : null;
+ const pdfViewer = new PDFViewer({
+ container,
+ viewer,
+ eventBus,
+ renderingQueue: pdfRenderingQueue,
+ linkService: pdfLinkService,
+ downloadManager,
+ altTextManager,
+ findController,
+ scriptingManager: AppOptions.get("enableScripting") && pdfScriptingManager,
+ l10n,
+ textLayerMode: AppOptions.get("textLayerMode"),
+ annotationMode: AppOptions.get("annotationMode"),
+ annotationEditorMode,
+ annotationEditorHighlightColors: AppOptions.get("highlightEditorColors"),
+ imageResourcesPath: AppOptions.get("imageResourcesPath"),
+ enablePrintAutoRotate: AppOptions.get("enablePrintAutoRotate"),
+ maxCanvasPixels: AppOptions.get("maxCanvasPixels"),
+ enablePermissions: AppOptions.get("enablePermissions"),
+ pageColors,
+ mlManager: this.mlManager
+ });
+ this.pdfViewer = pdfViewer;
+ pdfRenderingQueue.setViewer(pdfViewer);
+ pdfLinkService.setViewer(pdfViewer);
+ pdfScriptingManager.setViewer(pdfViewer);
+ if (appConfig.sidebar?.thumbnailView) {
+ this.pdfThumbnailViewer = new PDFThumbnailViewer({
+ container: appConfig.sidebar.thumbnailView,
+ eventBus,
+ renderingQueue: pdfRenderingQueue,
+ linkService: pdfLinkService,
+ pageColors
+ });
+ pdfRenderingQueue.setThumbnailViewer(this.pdfThumbnailViewer);
+ }
+ if (!this.isViewerEmbedded && !AppOptions.get("disableHistory")) {
+ this.pdfHistory = new PDFHistory({
+ linkService: pdfLinkService,
+ eventBus
+ });
+ pdfLinkService.setHistory(this.pdfHistory);
+ }
+ if (!this.supportsIntegratedFind && appConfig.findBar) {
+ this.findBar = new PDFFindBar(appConfig.findBar, eventBus);
+ }
+ if (appConfig.annotationEditorParams) {
+ if (annotationEditorMode !== AnnotationEditorType.DISABLE) {
+ if (AppOptions.get("enableStampEditor") && isOffscreenCanvasSupported) {
+ appConfig.toolbar?.editorStampButton?.classList.remove("hidden");
+ }
+ const editorHighlightButton = appConfig.toolbar?.editorHighlightButton;
+ if (editorHighlightButton && AppOptions.get("enableHighlightEditor")) {
+ editorHighlightButton.hidden = false;
+ }
+ this.annotationEditorParams = new AnnotationEditorParams(appConfig.annotationEditorParams, eventBus);
+ } else {
+ for (const id of ["editorModeButtons", "editorModeSeparator"]) {
+ document.getElementById(id)?.classList.add("hidden");
+ }
+ }
+ }
+ if (appConfig.documentProperties) {
+ this.pdfDocumentProperties = new PDFDocumentProperties(appConfig.documentProperties, this.overlayManager, eventBus, l10n, () => this._docFilename);
+ }
+ if (appConfig.secondaryToolbar?.cursorHandToolButton) {
+ this.pdfCursorTools = new PDFCursorTools({
+ container,
+ eventBus,
+ cursorToolOnLoad: AppOptions.get("cursorToolOnLoad")
+ });
+ }
+ if (appConfig.toolbar) {
+ this.toolbar = new Toolbar(appConfig.toolbar, eventBus);
+ }
+ if (appConfig.secondaryToolbar) {
+ this.secondaryToolbar = new SecondaryToolbar(appConfig.secondaryToolbar, eventBus);
+ }
+ if (this.supportsFullscreen && appConfig.secondaryToolbar?.presentationModeButton) {
+ this.pdfPresentationMode = new PDFPresentationMode({
+ container,
+ pdfViewer,
+ eventBus
+ });
+ }
+ if (appConfig.passwordOverlay) {
+ this.passwordPrompt = new PasswordPrompt(appConfig.passwordOverlay, this.overlayManager, this.isViewerEmbedded);
+ }
+ if (appConfig.sidebar?.outlineView) {
+ this.pdfOutlineViewer = new PDFOutlineViewer({
+ container: appConfig.sidebar.outlineView,
+ eventBus,
+ l10n,
+ linkService: pdfLinkService,
+ downloadManager
+ });
+ }
+ if (appConfig.sidebar?.attachmentsView) {
+ this.pdfAttachmentViewer = new PDFAttachmentViewer({
+ container: appConfig.sidebar.attachmentsView,
+ eventBus,
+ l10n,
+ downloadManager
+ });
+ }
+ if (appConfig.sidebar?.layersView) {
+ this.pdfLayerViewer = new PDFLayerViewer({
+ container: appConfig.sidebar.layersView,
+ eventBus,
+ l10n
+ });
+ }
+ if (appConfig.sidebar) {
+ this.pdfSidebar = new PDFSidebar({
+ elements: appConfig.sidebar,
+ eventBus,
+ l10n
+ });
+ this.pdfSidebar.onToggled = this.forceRendering.bind(this);
+ this.pdfSidebar.onUpdateThumbnails = () => {
+ for (const pageView of pdfViewer.getCachedPageViews()) {
+ if (pageView.renderingState === RenderingStates.FINISHED) {
+ this.pdfThumbnailViewer.getThumbnail(pageView.id - 1)?.setImage(pageView);
+ }
+ }
+ this.pdfThumbnailViewer.scrollThumbnailIntoView(pdfViewer.currentPageNumber);
+ };
+ }
+ },
+ async run(config) {
+ this.preferences = new Preferences();
+ await this.initialize(config);
+ const {
+ appConfig,
+ eventBus
+ } = this;
+ let file;
+ file = window.location.href;
+ if (!AppOptions.get("supportsDocumentFonts")) {
+ AppOptions.set("disableFontFace", true);
+ this.l10n.get("pdfjs-web-fonts-disabled").then(msg => {
+ console.warn(msg);
+ });
+ }
+ if (!this.supportsPrinting) {
+ appConfig.toolbar?.print?.classList.add("hidden");
+ appConfig.secondaryToolbar?.printButton.classList.add("hidden");
+ }
+ if (!this.supportsFullscreen) {
+ appConfig.secondaryToolbar?.presentationModeButton.classList.add("hidden");
+ }
+ if (this.supportsIntegratedFind) {
+ appConfig.toolbar?.viewFind?.classList.add("hidden");
+ }
+ this.initPassiveLoading(file);
+ const {
+ mainContainer
+ } = appConfig;
+ ({
+ scrollTop: this._lastScrollTop,
+ scrollLeft: this._lastScrollLeft
+ } = mainContainer);
+ const scroll = () => {
+ if (this._lastScrollTop === mainContainer.scrollTop && this._lastScrollLeft === mainContainer.scrollLeft) {
+ return;
+ }
+ mainContainer.removeEventListener("scroll", scroll, {
+ passive: true
+ });
+ this._isScrolling = true;
+ const scrollend = () => {
+ ({
+ scrollTop: this._lastScrollTop,
+ scrollLeft: this._lastScrollLeft
+ } = mainContainer);
+ this._isScrolling = false;
+ mainContainer.addEventListener("scroll", scroll, {
+ passive: true
+ });
+ mainContainer.removeEventListener("scrollend", scrollend);
+ mainContainer.removeEventListener("blur", scrollend);
+ };
+ mainContainer.addEventListener("scrollend", scrollend);
+ mainContainer.addEventListener("blur", scrollend);
+ };
+ mainContainer.addEventListener("scroll", scroll, {
+ passive: true
+ });
+ },
+ get externalServices() {
+ return shadow(this, "externalServices", new ExternalServices());
+ },
+ get mlManager() {
+ return shadow(this, "mlManager", AppOptions.get("enableML") === true ? new MLManager() : null);
+ },
+ get initialized() {
+ return this._initializedCapability.settled;
+ },
+ get initializedPromise() {
+ return this._initializedCapability.promise;
+ },
+ zoomIn(steps, scaleFactor) {
+ if (this.pdfViewer.isInPresentationMode) {
+ return;
+ }
+ this.pdfViewer.increaseScale({
+ drawingDelay: AppOptions.get("defaultZoomDelay"),
+ steps,
+ scaleFactor
+ });
+ },
+ zoomOut(steps, scaleFactor) {
+ if (this.pdfViewer.isInPresentationMode) {
+ return;
+ }
+ this.pdfViewer.decreaseScale({
+ drawingDelay: AppOptions.get("defaultZoomDelay"),
+ steps,
+ scaleFactor
+ });
+ },
+ zoomReset() {
+ if (this.pdfViewer.isInPresentationMode) {
+ return;
+ }
+ this.pdfViewer.currentScaleValue = DEFAULT_SCALE_VALUE;
+ },
+ get pagesCount() {
+ return this.pdfDocument ? this.pdfDocument.numPages : 0;
+ },
+ get page() {
+ return this.pdfViewer.currentPageNumber;
+ },
+ set page(val) {
+ this.pdfViewer.currentPageNumber = val;
+ },
+ get supportsPrinting() {
+ return PDFPrintServiceFactory.supportsPrinting;
+ },
+ get supportsFullscreen() {
+ return shadow(this, "supportsFullscreen", document.fullscreenEnabled);
+ },
+ get supportsPinchToZoom() {
+ return shadow(this, "supportsPinchToZoom", AppOptions.get("supportsPinchToZoom"));
+ },
+ get supportsIntegratedFind() {
+ return shadow(this, "supportsIntegratedFind", AppOptions.get("supportsIntegratedFind"));
+ },
+ get loadingBar() {
+ const barElement = document.getElementById("loadingBar");
+ const bar = barElement ? new ProgressBar(barElement) : null;
+ return shadow(this, "loadingBar", bar);
+ },
+ get supportsMouseWheelZoomCtrlKey() {
+ return shadow(this, "supportsMouseWheelZoomCtrlKey", AppOptions.get("supportsMouseWheelZoomCtrlKey"));
+ },
+ get supportsMouseWheelZoomMetaKey() {
+ return shadow(this, "supportsMouseWheelZoomMetaKey", AppOptions.get("supportsMouseWheelZoomMetaKey"));
+ },
+ get supportsCaretBrowsingMode() {
+ return shadow(this, "supportsCaretBrowsingMode", AppOptions.get("supportsCaretBrowsingMode"));
+ },
+ moveCaret(isUp, select) {
+ this._caretBrowsing ||= new CaretBrowsingMode(this.appConfig.mainContainer, this.appConfig.viewerContainer, this.appConfig.toolbar?.container);
+ this._caretBrowsing.moveCaret(isUp, select);
+ },
+ initPassiveLoading(file) {
+ this.setTitleUsingUrl(file, file);
+ this.externalServices.initPassiveLoading({
+ onOpenWithTransport: range => {
+ this.open({
+ range
+ });
+ },
+ onOpenWithData: (data, contentDispositionFilename) => {
+ if (isPdfFile(contentDispositionFilename)) {
+ this._contentDispositionFilename = contentDispositionFilename;
+ }
+ this.open({
+ data
+ });
+ },
+ onOpenWithURL: (url, length, originalUrl) => {
+ this.open({
+ url,
+ length,
+ originalUrl
+ });
+ },
+ onError: err => {
+ this.l10n.get("pdfjs-loading-error").then(msg => {
+ this._documentError(msg, err);
+ });
+ },
+ onProgress: (loaded, total) => {
+ this.progress(loaded / total);
+ }
+ });
+ },
+ setTitleUsingUrl(url = "", downloadUrl = null) {
+ this.url = url;
+ this.baseUrl = url.split("#", 1)[0];
+ if (downloadUrl) {
+ this._downloadUrl = downloadUrl === url ? this.baseUrl : downloadUrl.split("#", 1)[0];
+ }
+ if (isDataScheme(url)) {
+ this._hideViewBookmark();
+ }
+ let title = getPdfFilenameFromUrl(url, "");
+ if (!title) {
+ try {
+ title = decodeURIComponent(getFilenameFromUrl(url)) || url;
+ } catch {
+ title = url;
+ }
+ }
+ this.setTitle(title);
+ },
+ setTitle(title = this._title) {
+ this._title = title;
+ if (this.isViewerEmbedded) {
+ return;
+ }
+ const editorIndicator = this._hasAnnotationEditors && !this.pdfRenderingQueue.printing;
+ document.title = `${editorIndicator ? "* " : ""}${title}`;
+ },
+ get _docFilename() {
+ return this._contentDispositionFilename || getPdfFilenameFromUrl(this.url);
+ },
+ _hideViewBookmark() {
+ const {
+ secondaryToolbar
+ } = this.appConfig;
+ secondaryToolbar?.viewBookmarkButton.classList.add("hidden");
+ if (secondaryToolbar?.presentationModeButton.classList.contains("hidden")) {
+ document.getElementById("viewBookmarkSeparator")?.classList.add("hidden");
+ }
+ },
+ async close() {
+ this._unblockDocumentLoadEvent();
+ this._hideViewBookmark();
+ if (!this.pdfLoadingTask) {
+ return;
+ }
+ const promises = [];
+ promises.push(this.pdfLoadingTask.destroy());
+ this.pdfLoadingTask = null;
+ if (this.pdfDocument) {
+ this.pdfDocument = null;
+ this.pdfThumbnailViewer?.setDocument(null);
+ this.pdfViewer.setDocument(null);
+ this.pdfLinkService.setDocument(null);
+ this.pdfDocumentProperties?.setDocument(null);
+ }
+ this.pdfLinkService.externalLinkEnabled = true;
+ this.store = null;
+ this.isInitialViewSet = false;
+ this.downloadComplete = false;
+ this.url = "";
+ this.baseUrl = "";
+ this._downloadUrl = "";
+ this.documentInfo = null;
+ this.metadata = null;
+ this._contentDispositionFilename = null;
+ this._contentLength = null;
+ this._saveInProgress = false;
+ this._hasAnnotationEditors = false;
+ promises.push(this.pdfScriptingManager.destroyPromise, this.passwordPrompt.close());
+ this.setTitle();
+ this.pdfSidebar?.reset();
+ this.pdfOutlineViewer?.reset();
+ this.pdfAttachmentViewer?.reset();
+ this.pdfLayerViewer?.reset();
+ this.pdfHistory?.reset();
+ this.findBar?.reset();
+ this.toolbar?.reset();
+ this.secondaryToolbar?.reset();
+ this._PDFBug?.cleanup();
+ await Promise.all(promises);
+ },
+ async open(args) {
+ if (this.pdfLoadingTask) {
+ await this.close();
+ }
+ const workerParams = AppOptions.getAll(OptionKind.WORKER);
+ Object.assign(GlobalWorkerOptions, workerParams);
+ AppOptions.set("docBaseUrl", this.baseUrl);
+ const apiParams = AppOptions.getAll(OptionKind.API);
+ const loadingTask = getDocument({
+ ...apiParams,
+ ...args
+ });
+ this.pdfLoadingTask = loadingTask;
+ loadingTask.onPassword = (updateCallback, reason) => {
+ if (this.isViewerEmbedded) {
+ this._unblockDocumentLoadEvent();
+ }
+ this.pdfLinkService.externalLinkEnabled = false;
+ this.passwordPrompt.setUpdateCallback(updateCallback, reason);
+ this.passwordPrompt.open();
+ };
+ loadingTask.onProgress = ({
+ loaded,
+ total
+ }) => {
+ this.progress(loaded / total);
+ };
+ return loadingTask.promise.then(pdfDocument => {
+ this.load(pdfDocument);
+ }, reason => {
+ if (loadingTask !== this.pdfLoadingTask) {
+ return undefined;
+ }
+ let key = "pdfjs-loading-error";
+ if (reason instanceof InvalidPDFException) {
+ key = "pdfjs-invalid-file-error";
+ } else if (reason instanceof MissingPDFException) {
+ key = "pdfjs-missing-file-error";
+ } else if (reason instanceof UnexpectedResponseException) {
+ key = "pdfjs-unexpected-response-error";
+ }
+ return this.l10n.get(key).then(msg => {
+ this._documentError(msg, {
+ message: reason?.message
+ });
+ throw reason;
+ });
+ });
+ },
+ _ensureDownloadComplete() {
+ if (this.pdfDocument && this.downloadComplete) {
+ return;
+ }
+ throw new Error("PDF document not downloaded.");
+ },
+ async download(options = {}) {
+ const url = this._downloadUrl,
+ filename = this._docFilename;
+ try {
+ this._ensureDownloadComplete();
+ const data = await this.pdfDocument.getData();
+ const blob = new Blob([data], {
+ type: "application/pdf"
+ });
+ await this.downloadManager.download(blob, url, filename, options);
+ } catch {
+ await this.downloadManager.downloadUrl(url, filename, options);
+ }
+ },
+ async save(options = {}) {
+ if (this._saveInProgress) {
+ return;
+ }
+ this._saveInProgress = true;
+ await this.pdfScriptingManager.dispatchWillSave();
+ const url = this._downloadUrl,
+ filename = this._docFilename;
+ try {
+ this._ensureDownloadComplete();
+ const data = await this.pdfDocument.saveDocument();
+ const blob = new Blob([data], {
+ type: "application/pdf"
+ });
+ await this.downloadManager.download(blob, url, filename, options);
+ } catch (reason) {
+ console.error(`Error when saving the document: ${reason.message}`);
+ await this.download(options);
+ } finally {
+ await this.pdfScriptingManager.dispatchDidSave();
+ this._saveInProgress = false;
+ }
+ if (this._hasAnnotationEditors) {
+ this.externalServices.reportTelemetry({
+ type: "editing",
+ data: {
+ type: "save",
+ stats: this.pdfDocument?.annotationStorage.editorStats
+ }
+ });
+ }
+ },
+ downloadOrSave(options = {}) {
+ if (this.pdfDocument?.annotationStorage.size > 0) {
+ this.save(options);
+ } else {
+ this.download(options);
+ }
+ },
+ openInExternalApp() {
+ this.downloadOrSave({
+ openInExternalApp: true
+ });
+ },
+ _documentError(message, moreInfo = null) {
+ this._unblockDocumentLoadEvent();
+ this._otherError(message, moreInfo);
+ this.eventBus.dispatch("documenterror", {
+ source: this,
+ message,
+ reason: moreInfo?.message ?? null
+ });
+ },
+ _otherError(message, moreInfo = null) {
+ const moreInfoText = [`PDF.js v${version || "?"} (build: ${build || "?"})`];
+ if (moreInfo) {
+ moreInfoText.push(`Message: ${moreInfo.message}`);
+ if (moreInfo.stack) {
+ moreInfoText.push(`Stack: ${moreInfo.stack}`);
+ } else {
+ if (moreInfo.filename) {
+ moreInfoText.push(`File: ${moreInfo.filename}`);
+ }
+ if (moreInfo.lineNumber) {
+ moreInfoText.push(`Line: ${moreInfo.lineNumber}`);
+ }
+ }
+ }
+ console.error(`${message}\n\n${moreInfoText.join("\n")}`);
+ },
+ progress(level) {
+ if (!this.loadingBar || this.downloadComplete) {
+ return;
+ }
+ const percent = Math.round(level * 100);
+ if (percent <= this.loadingBar.percent) {
+ return;
+ }
+ this.loadingBar.percent = percent;
+ if (this.pdfDocument?.loadingParams.disableAutoFetch ?? AppOptions.get("disableAutoFetch")) {
+ this.loadingBar.setDisableAutoFetch();
+ }
+ },
+ load(pdfDocument) {
+ this.pdfDocument = pdfDocument;
+ pdfDocument.getDownloadInfo().then(({
+ length
+ }) => {
+ this._contentLength = length;
+ this.downloadComplete = true;
+ this.loadingBar?.hide();
+ firstPagePromise.then(() => {
+ this.eventBus.dispatch("documentloaded", {
+ source: this
+ });
+ });
+ });
+ const pageLayoutPromise = pdfDocument.getPageLayout().catch(() => {});
+ const pageModePromise = pdfDocument.getPageMode().catch(() => {});
+ const openActionPromise = pdfDocument.getOpenAction().catch(() => {});
+ this.toolbar?.setPagesCount(pdfDocument.numPages, false);
+ this.secondaryToolbar?.setPagesCount(pdfDocument.numPages);
+ this.pdfLinkService.setDocument(pdfDocument);
+ this.pdfDocumentProperties?.setDocument(pdfDocument);
+ const pdfViewer = this.pdfViewer;
+ pdfViewer.setDocument(pdfDocument);
+ const {
+ firstPagePromise,
+ onePageRendered,
+ pagesPromise
+ } = pdfViewer;
+ this.pdfThumbnailViewer?.setDocument(pdfDocument);
+ const storedPromise = (this.store = new ViewHistory(pdfDocument.fingerprints[0])).getMultiple({
+ page: null,
+ zoom: DEFAULT_SCALE_VALUE,
+ scrollLeft: "0",
+ scrollTop: "0",
+ rotation: null,
+ sidebarView: SidebarView.UNKNOWN,
+ scrollMode: ScrollMode.UNKNOWN,
+ spreadMode: SpreadMode.UNKNOWN
+ }).catch(() => {});
+ firstPagePromise.then(pdfPage => {
+ this.loadingBar?.setWidth(this.appConfig.viewerContainer);
+ this._initializeAnnotationStorageCallbacks(pdfDocument);
+ Promise.all([animationStarted, storedPromise, pageLayoutPromise, pageModePromise, openActionPromise]).then(async ([timeStamp, stored, pageLayout, pageMode, openAction]) => {
+ const viewOnLoad = AppOptions.get("viewOnLoad");
+ this._initializePdfHistory({
+ fingerprint: pdfDocument.fingerprints[0],
+ viewOnLoad,
+ initialDest: openAction?.dest
+ });
+ const initialBookmark = this.initialBookmark;
+ const zoom = AppOptions.get("defaultZoomValue");
+ let hash = zoom ? `zoom=${zoom}` : null;
+ let rotation = null;
+ let sidebarView = AppOptions.get("sidebarViewOnLoad");
+ let scrollMode = AppOptions.get("scrollModeOnLoad");
+ let spreadMode = AppOptions.get("spreadModeOnLoad");
+ if (stored?.page && viewOnLoad !== ViewOnLoad.INITIAL) {
+ hash = `page=${stored.page}&zoom=${zoom || stored.zoom},` + `${stored.scrollLeft},${stored.scrollTop}`;
+ rotation = parseInt(stored.rotation, 10);
+ if (sidebarView === SidebarView.UNKNOWN) {
+ sidebarView = stored.sidebarView | 0;
+ }
+ if (scrollMode === ScrollMode.UNKNOWN) {
+ scrollMode = stored.scrollMode | 0;
+ }
+ if (spreadMode === SpreadMode.UNKNOWN) {
+ spreadMode = stored.spreadMode | 0;
+ }
+ }
+ if (pageMode && sidebarView === SidebarView.UNKNOWN) {
+ sidebarView = apiPageModeToSidebarView(pageMode);
+ }
+ if (pageLayout && scrollMode === ScrollMode.UNKNOWN && spreadMode === SpreadMode.UNKNOWN) {
+ const modes = apiPageLayoutToViewerModes(pageLayout);
+ spreadMode = modes.spreadMode;
+ }
+ this.setInitialView(hash, {
+ rotation,
+ sidebarView,
+ scrollMode,
+ spreadMode
+ });
+ this.eventBus.dispatch("documentinit", {
+ source: this
+ });
+ if (!this.isViewerEmbedded) {
+ pdfViewer.focus();
+ }
+ await Promise.race([pagesPromise, new Promise(resolve => {
+ setTimeout(resolve, FORCE_PAGES_LOADED_TIMEOUT);
+ })]);
+ if (!initialBookmark && !hash) {
+ return;
+ }
+ if (pdfViewer.hasEqualPageSizes) {
+ return;
+ }
+ this.initialBookmark = initialBookmark;
+ pdfViewer.currentScaleValue = pdfViewer.currentScaleValue;
+ this.setInitialView(hash);
+ }).catch(() => {
+ this.setInitialView();
+ }).then(function () {
+ pdfViewer.update();
+ });
+ });
+ pagesPromise.then(() => {
+ this._unblockDocumentLoadEvent();
+ this._initializeAutoPrint(pdfDocument, openActionPromise);
+ }, reason => {
+ this.l10n.get("pdfjs-loading-error").then(msg => {
+ this._documentError(msg, {
+ message: reason?.message
+ });
+ });
+ });
+ onePageRendered.then(data => {
+ this.externalServices.reportTelemetry({
+ type: "pageInfo",
+ timestamp: data.timestamp
+ });
+ if (this.pdfOutlineViewer) {
+ pdfDocument.getOutline().then(outline => {
+ if (pdfDocument !== this.pdfDocument) {
+ return;
+ }
+ this.pdfOutlineViewer.render({
+ outline,
+ pdfDocument
+ });
+ });
+ }
+ if (this.pdfAttachmentViewer) {
+ pdfDocument.getAttachments().then(attachments => {
+ if (pdfDocument !== this.pdfDocument) {
+ return;
+ }
+ this.pdfAttachmentViewer.render({
+ attachments
+ });
+ });
+ }
+ if (this.pdfLayerViewer) {
+ pdfViewer.optionalContentConfigPromise.then(optionalContentConfig => {
+ if (pdfDocument !== this.pdfDocument) {
+ return;
+ }
+ this.pdfLayerViewer.render({
+ optionalContentConfig,
+ pdfDocument
+ });
+ });
+ }
+ });
+ this._initializePageLabels(pdfDocument);
+ this._initializeMetadata(pdfDocument);
+ },
+ async _scriptingDocProperties(pdfDocument) {
+ if (!this.documentInfo) {
+ await new Promise(resolve => {
+ this.eventBus._on("metadataloaded", resolve, {
+ once: true
+ });
+ });
+ if (pdfDocument !== this.pdfDocument) {
+ return null;
+ }
+ }
+ if (!this._contentLength) {
+ await new Promise(resolve => {
+ this.eventBus._on("documentloaded", resolve, {
+ once: true
+ });
+ });
+ if (pdfDocument !== this.pdfDocument) {
+ return null;
+ }
+ }
+ return {
+ ...this.documentInfo,
+ baseURL: this.baseUrl,
+ filesize: this._contentLength,
+ filename: this._docFilename,
+ metadata: this.metadata?.getRaw(),
+ authors: this.metadata?.get("dc:creator"),
+ numPages: this.pagesCount,
+ URL: this.url
+ };
+ },
+ async _initializeAutoPrint(pdfDocument, openActionPromise) {
+ const [openAction, jsActions] = await Promise.all([openActionPromise, this.pdfViewer.enableScripting ? null : pdfDocument.getJSActions()]);
+ if (pdfDocument !== this.pdfDocument) {
+ return;
+ }
+ let triggerAutoPrint = openAction?.action === "Print";
+ if (jsActions) {
+ console.warn("Warning: JavaScript support is not enabled");
+ for (const name in jsActions) {
+ if (triggerAutoPrint) {
+ break;
+ }
+ switch (name) {
+ case "WillClose":
+ case "WillSave":
+ case "DidSave":
+ case "WillPrint":
+ case "DidPrint":
+ continue;
+ }
+ triggerAutoPrint = jsActions[name].some(js => AutoPrintRegExp.test(js));
+ }
+ }
+ if (triggerAutoPrint) {
+ this.triggerPrinting();
+ }
+ },
+ async _initializeMetadata(pdfDocument) {
+ const {
+ info,
+ metadata,
+ contentDispositionFilename,
+ contentLength
+ } = await pdfDocument.getMetadata();
+ if (pdfDocument !== this.pdfDocument) {
+ return;
+ }
+ this.documentInfo = info;
+ this.metadata = metadata;
+ this._contentDispositionFilename ??= contentDispositionFilename;
+ this._contentLength ??= contentLength;
+ console.log(`PDF ${pdfDocument.fingerprints[0]} [${info.PDFFormatVersion} ` + `${(info.Producer || "-").trim()} / ${(info.Creator || "-").trim()}] ` + `(PDF.js: ${version || "?"} [${build || "?"}])`);
+ let pdfTitle = info.Title;
+ const metadataTitle = metadata?.get("dc:title");
+ if (metadataTitle) {
+ if (metadataTitle !== "Untitled" && !/[\uFFF0-\uFFFF]/g.test(metadataTitle)) {
+ pdfTitle = metadataTitle;
+ }
+ }
+ if (pdfTitle) {
+ this.setTitle(`${pdfTitle} - ${this._contentDispositionFilename || this._title}`);
+ } else if (this._contentDispositionFilename) {
+ this.setTitle(this._contentDispositionFilename);
+ }
+ if (info.IsXFAPresent && !info.IsAcroFormPresent && !pdfDocument.isPureXfa) {
+ if (pdfDocument.loadingParams.enableXfa) {
+ console.warn("Warning: XFA Foreground documents are not supported");
+ } else {
+ console.warn("Warning: XFA support is not enabled");
+ }
+ } else if ((info.IsAcroFormPresent || info.IsXFAPresent) && !this.pdfViewer.renderForms) {
+ console.warn("Warning: Interactive form support is not enabled");
+ }
+ if (info.IsSignaturesPresent) {
+ console.warn("Warning: Digital signatures validation is not supported");
+ }
+ this.eventBus.dispatch("metadataloaded", {
+ source: this
+ });
+ },
+ async _initializePageLabels(pdfDocument) {
+ const labels = await pdfDocument.getPageLabels();
+ if (pdfDocument !== this.pdfDocument) {
+ return;
+ }
+ if (!labels || AppOptions.get("disablePageLabels")) {
+ return;
+ }
+ const numLabels = labels.length;
+ let standardLabels = 0,
+ emptyLabels = 0;
+ for (let i = 0; i < numLabels; i++) {
+ const label = labels[i];
+ if (label === (i + 1).toString()) {
+ standardLabels++;
+ } else if (label === "") {
+ emptyLabels++;
+ } else {
+ break;
+ }
+ }
+ if (standardLabels >= numLabels || emptyLabels >= numLabels) {
+ return;
+ }
+ const {
+ pdfViewer,
+ pdfThumbnailViewer,
+ toolbar
+ } = this;
+ pdfViewer.setPageLabels(labels);
+ pdfThumbnailViewer?.setPageLabels(labels);
+ toolbar?.setPagesCount(numLabels, true);
+ toolbar?.setPageNumber(pdfViewer.currentPageNumber, pdfViewer.currentPageLabel);
+ },
+ _initializePdfHistory({
+ fingerprint,
+ viewOnLoad,
+ initialDest = null
+ }) {
+ if (!this.pdfHistory) {
+ return;
+ }
+ this.pdfHistory.initialize({
+ fingerprint,
+ resetHistory: viewOnLoad === ViewOnLoad.INITIAL,
+ updateUrl: AppOptions.get("historyUpdateUrl")
+ });
+ if (this.pdfHistory.initialBookmark) {
+ this.initialBookmark = this.pdfHistory.initialBookmark;
+ this.initialRotation = this.pdfHistory.initialRotation;
+ }
+ if (initialDest && !this.initialBookmark && viewOnLoad === ViewOnLoad.UNKNOWN) {
+ this.initialBookmark = JSON.stringify(initialDest);
+ this.pdfHistory.push({
+ explicitDest: initialDest,
+ pageNumber: null
+ });
+ }
+ },
+ _initializeAnnotationStorageCallbacks(pdfDocument) {
+ if (pdfDocument !== this.pdfDocument) {
+ return;
+ }
+ const {
+ annotationStorage
+ } = pdfDocument;
+ annotationStorage.onSetModified = () => {
+ window.addEventListener("beforeunload", beforeUnload);
+ };
+ annotationStorage.onResetModified = () => {
+ window.removeEventListener("beforeunload", beforeUnload);
+ };
+ annotationStorage.onAnnotationEditor = typeStr => {
+ this._hasAnnotationEditors = !!typeStr;
+ this.setTitle();
+ };
+ },
+ setInitialView(storedHash, {
+ rotation,
+ sidebarView,
+ scrollMode,
+ spreadMode
+ } = {}) {
+ const setRotation = angle => {
+ if (isValidRotation(angle)) {
+ this.pdfViewer.pagesRotation = angle;
+ }
+ };
+ const setViewerModes = (scroll, spread) => {
+ if (isValidScrollMode(scroll)) {
+ this.pdfViewer.scrollMode = scroll;
+ }
+ if (isValidSpreadMode(spread)) {
+ this.pdfViewer.spreadMode = spread;
+ }
+ };
+ this.isInitialViewSet = true;
+ this.pdfSidebar?.setInitialView(sidebarView);
+ setViewerModes(scrollMode, spreadMode);
+ if (this.initialBookmark) {
+ setRotation(this.initialRotation);
+ delete this.initialRotation;
+ this.pdfLinkService.setHash(this.initialBookmark);
+ this.initialBookmark = null;
+ } else if (storedHash) {
+ setRotation(rotation);
+ this.pdfLinkService.setHash(storedHash);
+ }
+ this.toolbar?.setPageNumber(this.pdfViewer.currentPageNumber, this.pdfViewer.currentPageLabel);
+ this.secondaryToolbar?.setPageNumber(this.pdfViewer.currentPageNumber);
+ if (!this.pdfViewer.currentScaleValue) {
+ this.pdfViewer.currentScaleValue = DEFAULT_SCALE_VALUE;
+ }
+ },
+ _cleanup() {
+ if (!this.pdfDocument) {
+ return;
+ }
+ this.pdfViewer.cleanup();
+ this.pdfThumbnailViewer?.cleanup();
+ this.pdfDocument.cleanup(AppOptions.get("fontExtraProperties"));
+ },
+ forceRendering() {
+ this.pdfRenderingQueue.printing = !!this.printService;
+ this.pdfRenderingQueue.isThumbnailViewEnabled = this.pdfSidebar?.visibleView === SidebarView.THUMBS;
+ this.pdfRenderingQueue.renderHighestPriority();
+ },
+ beforePrint() {
+ this._printAnnotationStoragePromise = this.pdfScriptingManager.dispatchWillPrint().catch(() => {}).then(() => this.pdfDocument?.annotationStorage.print);
+ if (this.printService) {
+ return;
+ }
+ if (!this.supportsPrinting) {
+ this.l10n.get("pdfjs-printing-not-supported").then(msg => {
+ this._otherError(msg);
+ });
+ return;
+ }
+ if (!this.pdfViewer.pageViewsReady) {
+ this.l10n.get("pdfjs-printing-not-ready").then(msg => {
+ window.alert(msg);
+ });
+ return;
+ }
+ this.printService = PDFPrintServiceFactory.createPrintService({
+ pdfDocument: this.pdfDocument,
+ pagesOverview: this.pdfViewer.getPagesOverview(),
+ printContainer: this.appConfig.printContainer,
+ printResolution: AppOptions.get("printResolution"),
+ optionalContentConfigPromise: this.pdfViewer.optionalContentConfigPromise,
+ printAnnotationStoragePromise: this._printAnnotationStoragePromise
+ });
+ this.forceRendering();
+ this.setTitle();
+ this.printService.layout();
+ if (this._hasAnnotationEditors) {
+ this.externalServices.reportTelemetry({
+ type: "editing",
+ data: {
+ type: "print",
+ stats: this.pdfDocument?.annotationStorage.editorStats
+ }
+ });
+ }
+ },
+ afterPrint() {
+ if (this._printAnnotationStoragePromise) {
+ this._printAnnotationStoragePromise.then(() => {
+ this.pdfScriptingManager.dispatchDidPrint();
+ });
+ this._printAnnotationStoragePromise = null;
+ }
+ if (this.printService) {
+ this.printService.destroy();
+ this.printService = null;
+ this.pdfDocument?.annotationStorage.resetModified();
+ }
+ this.forceRendering();
+ this.setTitle();
+ },
+ rotatePages(delta) {
+ this.pdfViewer.pagesRotation += delta;
+ },
+ requestPresentationMode() {
+ this.pdfPresentationMode?.request();
+ },
+ triggerPrinting() {
+ if (!this.supportsPrinting) {
+ return;
+ }
+ window.print();
+ },
+ bindEvents() {
+ const {
+ eventBus,
+ _boundEvents
+ } = this;
+ _boundEvents.beforePrint = this.beforePrint.bind(this);
+ _boundEvents.afterPrint = this.afterPrint.bind(this);
+ eventBus._on("resize", webViewerResize);
+ eventBus._on("hashchange", webViewerHashchange);
+ eventBus._on("beforeprint", _boundEvents.beforePrint);
+ eventBus._on("afterprint", _boundEvents.afterPrint);
+ eventBus._on("pagerender", webViewerPageRender);
+ eventBus._on("pagerendered", webViewerPageRendered);
+ eventBus._on("updateviewarea", webViewerUpdateViewarea);
+ eventBus._on("pagechanging", webViewerPageChanging);
+ eventBus._on("scalechanging", webViewerScaleChanging);
+ eventBus._on("rotationchanging", webViewerRotationChanging);
+ eventBus._on("sidebarviewchanged", webViewerSidebarViewChanged);
+ eventBus._on("pagemode", webViewerPageMode);
+ eventBus._on("namedaction", webViewerNamedAction);
+ eventBus._on("presentationmodechanged", webViewerPresentationModeChanged);
+ eventBus._on("presentationmode", webViewerPresentationMode);
+ eventBus._on("switchannotationeditormode", webViewerSwitchAnnotationEditorMode);
+ eventBus._on("switchannotationeditorparams", webViewerSwitchAnnotationEditorParams);
+ eventBus._on("print", webViewerPrint);
+ eventBus._on("download", webViewerDownload);
+ eventBus._on("openinexternalapp", webViewerOpenInExternalApp);
+ eventBus._on("firstpage", webViewerFirstPage);
+ eventBus._on("lastpage", webViewerLastPage);
+ eventBus._on("nextpage", webViewerNextPage);
+ eventBus._on("previouspage", webViewerPreviousPage);
+ eventBus._on("zoomin", webViewerZoomIn);
+ eventBus._on("zoomout", webViewerZoomOut);
+ eventBus._on("zoomreset", webViewerZoomReset);
+ eventBus._on("pagenumberchanged", webViewerPageNumberChanged);
+ eventBus._on("scalechanged", webViewerScaleChanged);
+ eventBus._on("rotatecw", webViewerRotateCw);
+ eventBus._on("rotateccw", webViewerRotateCcw);
+ eventBus._on("optionalcontentconfig", webViewerOptionalContentConfig);
+ eventBus._on("switchscrollmode", webViewerSwitchScrollMode);
+ eventBus._on("scrollmodechanged", webViewerScrollModeChanged);
+ eventBus._on("switchspreadmode", webViewerSwitchSpreadMode);
+ eventBus._on("spreadmodechanged", webViewerSpreadModeChanged);
+ eventBus._on("documentproperties", webViewerDocumentProperties);
+ eventBus._on("findfromurlhash", webViewerFindFromUrlHash);
+ eventBus._on("updatefindmatchescount", webViewerUpdateFindMatchesCount);
+ eventBus._on("updatefindcontrolstate", webViewerUpdateFindControlState);
+ if (AppOptions.get("pdfBug")) {
+ _boundEvents.reportPageStatsPDFBug = reportPageStatsPDFBug;
+ eventBus._on("pagerendered", _boundEvents.reportPageStatsPDFBug);
+ eventBus._on("pagechanging", _boundEvents.reportPageStatsPDFBug);
+ }
+ eventBus._on("annotationeditorstateschanged", webViewerAnnotationEditorStatesChanged);
+ eventBus._on("reporttelemetry", webViewerReportTelemetry);
+ },
+ bindWindowEvents() {
+ const {
+ eventBus,
+ _boundEvents
+ } = this;
+ function addWindowResolutionChange(evt = null) {
+ if (evt) {
+ webViewerResolutionChange(evt);
+ }
+ const mediaQueryList = window.matchMedia(`(resolution: ${window.devicePixelRatio || 1}dppx)`);
+ mediaQueryList.addEventListener("change", addWindowResolutionChange, {
+ once: true
+ });
+ }
+ addWindowResolutionChange();
+ _boundEvents.windowResize = () => {
+ eventBus.dispatch("resize", {
+ source: window
+ });
+ };
+ _boundEvents.windowHashChange = () => {
+ eventBus.dispatch("hashchange", {
+ source: window,
+ hash: document.location.hash.substring(1)
+ });
+ };
+ _boundEvents.windowBeforePrint = () => {
+ eventBus.dispatch("beforeprint", {
+ source: window
+ });
+ };
+ _boundEvents.windowAfterPrint = () => {
+ eventBus.dispatch("afterprint", {
+ source: window
+ });
+ };
+ _boundEvents.windowUpdateFromSandbox = event => {
+ eventBus.dispatch("updatefromsandbox", {
+ source: window,
+ detail: event.detail
+ });
+ };
+ window.addEventListener("visibilitychange", webViewerVisibilityChange);
+ window.addEventListener("wheel", webViewerWheel, {
+ passive: false
+ });
+ window.addEventListener("touchstart", webViewerTouchStart, {
+ passive: false
+ });
+ window.addEventListener("touchmove", webViewerTouchMove, {
+ passive: false
+ });
+ window.addEventListener("touchend", webViewerTouchEnd, {
+ passive: false
+ });
+ window.addEventListener("click", webViewerClick);
+ window.addEventListener("keydown", webViewerKeyDown);
+ window.addEventListener("keyup", webViewerKeyUp);
+ window.addEventListener("resize", _boundEvents.windowResize);
+ window.addEventListener("hashchange", _boundEvents.windowHashChange);
+ window.addEventListener("beforeprint", _boundEvents.windowBeforePrint);
+ window.addEventListener("afterprint", _boundEvents.windowAfterPrint);
+ window.addEventListener("updatefromsandbox", _boundEvents.windowUpdateFromSandbox);
+ },
+ unbindEvents() {
+ throw new Error("Not implemented: unbindEvents");
+ },
+ unbindWindowEvents() {
+ throw new Error("Not implemented: unbindWindowEvents");
+ },
+ _accumulateTicks(ticks, prop) {
+ if (this[prop] > 0 && ticks < 0 || this[prop] < 0 && ticks > 0) {
+ this[prop] = 0;
+ }
+ this[prop] += ticks;
+ const wholeTicks = Math.trunc(this[prop]);
+ this[prop] -= wholeTicks;
+ return wholeTicks;
+ },
+ _accumulateFactor(previousScale, factor, prop) {
+ if (factor === 1) {
+ return 1;
+ }
+ if (this[prop] > 1 && factor < 1 || this[prop] < 1 && factor > 1) {
+ this[prop] = 1;
+ }
+ const newFactor = Math.floor(previousScale * factor * this[prop] * 100) / (100 * previousScale);
+ this[prop] = factor / newFactor;
+ return newFactor;
+ },
+ _centerAtPos(previousScale, x, y) {
+ const {
+ pdfViewer
+ } = this;
+ const scaleDiff = pdfViewer.currentScale / previousScale - 1;
+ if (scaleDiff !== 0) {
+ const [top, left] = pdfViewer.containerTopLeft;
+ pdfViewer.container.scrollLeft += (x - left) * scaleDiff;
+ pdfViewer.container.scrollTop += (y - top) * scaleDiff;
+ }
+ },
+ _unblockDocumentLoadEvent() {
+ document.blockUnblockOnload?.(false);
+ this._unblockDocumentLoadEvent = () => {};
+ },
+ get scriptingReady() {
+ return this.pdfScriptingManager.ready;
+ }
+};
+initCom(PDFViewerApplication);
+async function loadFakeWorker() {
+ GlobalWorkerOptions.workerSrc ||= AppOptions.get("workerSrc");
+ await import( /*webpackIgnore: true*/PDFWorker.workerSrc);
+}
+async function loadPDFBug(self) {
+ const {
+ PDFBug
+ } = await import( /*webpackIgnore: true*/AppOptions.get("debuggerSrc"));
+ self._PDFBug = PDFBug;
+}
+function reportPageStatsPDFBug({
+ pageNumber
+}) {
+ if (!globalThis.Stats?.enabled) {
+ return;
+ }
+ const pageView = PDFViewerApplication.pdfViewer.getPageView(pageNumber - 1);
+ globalThis.Stats.add(pageNumber, pageView?.pdfPage?.stats);
+}
+function webViewerPageRender({
+ pageNumber
+}) {
+ if (pageNumber === PDFViewerApplication.page) {
+ PDFViewerApplication.toolbar?.updateLoadingIndicatorState(true);
+ }
+}
+function webViewerPageRendered({
+ pageNumber,
+ error
+}) {
+ if (pageNumber === PDFViewerApplication.page) {
+ PDFViewerApplication.toolbar?.updateLoadingIndicatorState(false);
+ }
+ if (PDFViewerApplication.pdfSidebar?.visibleView === SidebarView.THUMBS) {
+ const pageView = PDFViewerApplication.pdfViewer.getPageView(pageNumber - 1);
+ const thumbnailView = PDFViewerApplication.pdfThumbnailViewer?.getThumbnail(pageNumber - 1);
+ if (pageView) {
+ thumbnailView?.setImage(pageView);
+ }
+ }
+ if (error) {
+ PDFViewerApplication.l10n.get("pdfjs-rendering-error").then(msg => {
+ PDFViewerApplication._otherError(msg, error);
+ });
+ }
+}
+function webViewerPageMode({
+ mode
+}) {
+ let view;
+ switch (mode) {
+ case "thumbs":
+ view = SidebarView.THUMBS;
+ break;
+ case "bookmarks":
+ case "outline":
+ view = SidebarView.OUTLINE;
+ break;
+ case "attachments":
+ view = SidebarView.ATTACHMENTS;
+ break;
+ case "layers":
+ view = SidebarView.LAYERS;
+ break;
+ case "none":
+ view = SidebarView.NONE;
+ break;
+ default:
+ console.error('Invalid "pagemode" hash parameter: ' + mode);
+ return;
+ }
+ PDFViewerApplication.pdfSidebar?.switchView(view, true);
+}
+function webViewerNamedAction(evt) {
+ switch (evt.action) {
+ case "GoToPage":
+ PDFViewerApplication.appConfig.toolbar?.pageNumber.select();
+ break;
+ case "Find":
+ if (!PDFViewerApplication.supportsIntegratedFind) {
+ PDFViewerApplication.findBar?.toggle();
+ }
+ break;
+ case "Print":
+ PDFViewerApplication.triggerPrinting();
+ break;
+ case "SaveAs":
+ PDFViewerApplication.downloadOrSave();
+ break;
+ }
+}
+function webViewerPresentationModeChanged(evt) {
+ PDFViewerApplication.pdfViewer.presentationModeState = evt.state;
+}
+function webViewerSidebarViewChanged({
+ view
+}) {
+ PDFViewerApplication.pdfRenderingQueue.isThumbnailViewEnabled = view === SidebarView.THUMBS;
+ if (PDFViewerApplication.isInitialViewSet) {
+ PDFViewerApplication.store?.set("sidebarView", view).catch(() => {});
+ }
+}
+function webViewerUpdateViewarea({
+ location
+}) {
+ if (PDFViewerApplication.isInitialViewSet) {
+ PDFViewerApplication.store?.setMultiple({
+ page: location.pageNumber,
+ zoom: location.scale,
+ scrollLeft: location.left,
+ scrollTop: location.top,
+ rotation: location.rotation
+ }).catch(() => {});
+ }
+ if (PDFViewerApplication.appConfig.secondaryToolbar) {
+ const href = PDFViewerApplication.pdfLinkService.getAnchorUrl(location.pdfOpenParams);
+ PDFViewerApplication.appConfig.secondaryToolbar.viewBookmarkButton.href = href;
+ }
+}
+function webViewerScrollModeChanged(evt) {
+ if (PDFViewerApplication.isInitialViewSet && !PDFViewerApplication.pdfViewer.isInPresentationMode) {
+ PDFViewerApplication.store?.set("scrollMode", evt.mode).catch(() => {});
+ }
+}
+function webViewerSpreadModeChanged(evt) {
+ if (PDFViewerApplication.isInitialViewSet && !PDFViewerApplication.pdfViewer.isInPresentationMode) {
+ PDFViewerApplication.store?.set("spreadMode", evt.mode).catch(() => {});
+ }
+}
+function webViewerResize() {
+ const {
+ pdfDocument,
+ pdfViewer,
+ pdfRenderingQueue
+ } = PDFViewerApplication;
+ if (pdfRenderingQueue.printing && window.matchMedia("print").matches) {
+ return;
+ }
+ if (!pdfDocument) {
+ return;
+ }
+ const currentScaleValue = pdfViewer.currentScaleValue;
+ if (currentScaleValue === "auto" || currentScaleValue === "page-fit" || currentScaleValue === "page-width") {
+ pdfViewer.currentScaleValue = currentScaleValue;
+ }
+ pdfViewer.update();
+}
+function webViewerHashchange(evt) {
+ const hash = evt.hash;
+ if (!hash) {
+ return;
+ }
+ if (!PDFViewerApplication.isInitialViewSet) {
+ PDFViewerApplication.initialBookmark = hash;
+ } else if (!PDFViewerApplication.pdfHistory?.popStateInProgress) {
+ PDFViewerApplication.pdfLinkService.setHash(hash);
+ }
+}
+function webViewerPresentationMode() {
+ PDFViewerApplication.requestPresentationMode();
+}
+function webViewerSwitchAnnotationEditorMode(evt) {
+ PDFViewerApplication.pdfViewer.annotationEditorMode = evt;
+}
+function webViewerSwitchAnnotationEditorParams(evt) {
+ PDFViewerApplication.pdfViewer.annotationEditorParams = evt;
+}
+function webViewerPrint() {
+ PDFViewerApplication.triggerPrinting();
+}
+function webViewerDownload() {
+ PDFViewerApplication.downloadOrSave();
+}
+function webViewerOpenInExternalApp() {
+ PDFViewerApplication.openInExternalApp();
+}
+function webViewerFirstPage() {
+ PDFViewerApplication.page = 1;
+}
+function webViewerLastPage() {
+ PDFViewerApplication.page = PDFViewerApplication.pagesCount;
+}
+function webViewerNextPage() {
+ PDFViewerApplication.pdfViewer.nextPage();
+}
+function webViewerPreviousPage() {
+ PDFViewerApplication.pdfViewer.previousPage();
+}
+function webViewerZoomIn() {
+ PDFViewerApplication.zoomIn();
+}
+function webViewerZoomOut() {
+ PDFViewerApplication.zoomOut();
+}
+function webViewerZoomReset() {
+ PDFViewerApplication.zoomReset();
+}
+function webViewerPageNumberChanged(evt) {
+ const pdfViewer = PDFViewerApplication.pdfViewer;
+ if (evt.value !== "") {
+ PDFViewerApplication.pdfLinkService.goToPage(evt.value);
+ }
+ if (evt.value !== pdfViewer.currentPageNumber.toString() && evt.value !== pdfViewer.currentPageLabel) {
+ PDFViewerApplication.toolbar?.setPageNumber(pdfViewer.currentPageNumber, pdfViewer.currentPageLabel);
+ }
+}
+function webViewerScaleChanged(evt) {
+ PDFViewerApplication.pdfViewer.currentScaleValue = evt.value;
+}
+function webViewerRotateCw() {
+ PDFViewerApplication.rotatePages(90);
+}
+function webViewerRotateCcw() {
+ PDFViewerApplication.rotatePages(-90);
+}
+function webViewerOptionalContentConfig(evt) {
+ PDFViewerApplication.pdfViewer.optionalContentConfigPromise = evt.promise;
+}
+function webViewerSwitchScrollMode(evt) {
+ PDFViewerApplication.pdfViewer.scrollMode = evt.mode;
+}
+function webViewerSwitchSpreadMode(evt) {
+ PDFViewerApplication.pdfViewer.spreadMode = evt.mode;
+}
+function webViewerDocumentProperties() {
+ PDFViewerApplication.pdfDocumentProperties?.open();
+}
+function webViewerFindFromUrlHash(evt) {
+ PDFViewerApplication.eventBus.dispatch("find", {
+ source: evt.source,
+ type: "",
+ query: evt.query,
+ caseSensitive: false,
+ entireWord: false,
+ highlightAll: true,
+ findPrevious: false,
+ matchDiacritics: true
+ });
+}
+function webViewerUpdateFindMatchesCount({
+ matchesCount
+}) {
+ if (PDFViewerApplication.supportsIntegratedFind) {
+ PDFViewerApplication.externalServices.updateFindMatchesCount(matchesCount);
+ } else {
+ PDFViewerApplication.findBar?.updateResultsCount(matchesCount);
+ }
+}
+function webViewerUpdateFindControlState({
+ state,
+ previous,
+ matchesCount,
+ rawQuery
+}) {
+ if (PDFViewerApplication.supportsIntegratedFind) {
+ PDFViewerApplication.externalServices.updateFindControlState({
+ result: state,
+ findPrevious: previous,
+ matchesCount,
+ rawQuery
+ });
+ } else {
+ PDFViewerApplication.findBar?.updateUIState(state, previous, matchesCount);
+ }
+}
+function webViewerScaleChanging(evt) {
+ PDFViewerApplication.toolbar?.setPageScale(evt.presetValue, evt.scale);
+ PDFViewerApplication.pdfViewer.update();
+}
+function webViewerRotationChanging(evt) {
+ if (PDFViewerApplication.pdfThumbnailViewer) {
+ PDFViewerApplication.pdfThumbnailViewer.pagesRotation = evt.pagesRotation;
+ }
+ PDFViewerApplication.forceRendering();
+ PDFViewerApplication.pdfViewer.currentPageNumber = evt.pageNumber;
+}
+function webViewerPageChanging({
+ pageNumber,
+ pageLabel
+}) {
+ PDFViewerApplication.toolbar?.setPageNumber(pageNumber, pageLabel);
+ PDFViewerApplication.secondaryToolbar?.setPageNumber(pageNumber);
+ if (PDFViewerApplication.pdfSidebar?.visibleView === SidebarView.THUMBS) {
+ PDFViewerApplication.pdfThumbnailViewer?.scrollThumbnailIntoView(pageNumber);
+ }
+ const currentPage = PDFViewerApplication.pdfViewer.getPageView(pageNumber - 1);
+ PDFViewerApplication.toolbar?.updateLoadingIndicatorState(currentPage?.renderingState === RenderingStates.RUNNING);
+}
+function webViewerResolutionChange(evt) {
+ PDFViewerApplication.pdfViewer.refresh();
+}
+function webViewerVisibilityChange(evt) {
+ if (document.visibilityState === "visible") {
+ setZoomDisabledTimeout();
+ }
+}
+let zoomDisabledTimeout = null;
+function setZoomDisabledTimeout() {
+ if (zoomDisabledTimeout) {
+ clearTimeout(zoomDisabledTimeout);
+ }
+ zoomDisabledTimeout = setTimeout(function () {
+ zoomDisabledTimeout = null;
+ }, WHEEL_ZOOM_DISABLED_TIMEOUT);
+}
+function webViewerWheel(evt) {
+ const {
+ pdfViewer,
+ supportsMouseWheelZoomCtrlKey,
+ supportsMouseWheelZoomMetaKey,
+ supportsPinchToZoom
+ } = PDFViewerApplication;
+ if (pdfViewer.isInPresentationMode) {
+ return;
+ }
+ const deltaMode = evt.deltaMode;
+ let scaleFactor = Math.exp(-evt.deltaY / 100);
+ const isBuiltInMac = FeatureTest.platform.isMac;
+ const isPinchToZoom = evt.ctrlKey && !PDFViewerApplication._isCtrlKeyDown && deltaMode === WheelEvent.DOM_DELTA_PIXEL && evt.deltaX === 0 && (Math.abs(scaleFactor - 1) < 0.05 || isBuiltInMac) && evt.deltaZ === 0;
+ if (isPinchToZoom || evt.ctrlKey && supportsMouseWheelZoomCtrlKey || evt.metaKey && supportsMouseWheelZoomMetaKey) {
+ evt.preventDefault();
+ if (PDFViewerApplication._isScrolling || zoomDisabledTimeout || document.visibilityState === "hidden" || PDFViewerApplication.overlayManager.active) {
+ return;
+ }
+ const previousScale = pdfViewer.currentScale;
+ if (isPinchToZoom && supportsPinchToZoom) {
+ scaleFactor = PDFViewerApplication._accumulateFactor(previousScale, scaleFactor, "_wheelUnusedFactor");
+ if (scaleFactor < 1) {
+ PDFViewerApplication.zoomOut(null, scaleFactor);
+ } else if (scaleFactor > 1) {
+ PDFViewerApplication.zoomIn(null, scaleFactor);
+ } else {
+ return;
+ }
+ } else {
+ const delta = normalizeWheelEventDirection(evt);
+ let ticks = 0;
+ if (deltaMode === WheelEvent.DOM_DELTA_LINE || deltaMode === WheelEvent.DOM_DELTA_PAGE) {
+ if (Math.abs(delta) >= 1) {
+ ticks = Math.sign(delta);
+ } else {
+ ticks = PDFViewerApplication._accumulateTicks(delta, "_wheelUnusedTicks");
+ }
+ } else {
+ const PIXELS_PER_LINE_SCALE = 30;
+ ticks = PDFViewerApplication._accumulateTicks(delta / PIXELS_PER_LINE_SCALE, "_wheelUnusedTicks");
+ }
+ if (ticks < 0) {
+ PDFViewerApplication.zoomOut(-ticks);
+ } else if (ticks > 0) {
+ PDFViewerApplication.zoomIn(ticks);
+ } else {
+ return;
+ }
+ }
+ PDFViewerApplication._centerAtPos(previousScale, evt.clientX, evt.clientY);
+ }
+}
+function webViewerTouchStart(evt) {
+ if (PDFViewerApplication.pdfViewer.isInPresentationMode || evt.touches.length < 2) {
+ return;
+ }
+ evt.preventDefault();
+ if (evt.touches.length !== 2 || PDFViewerApplication.overlayManager.active) {
+ PDFViewerApplication._touchInfo = null;
+ return;
+ }
+ let [touch0, touch1] = evt.touches;
+ if (touch0.identifier > touch1.identifier) {
+ [touch0, touch1] = [touch1, touch0];
+ }
+ PDFViewerApplication._touchInfo = {
+ touch0X: touch0.pageX,
+ touch0Y: touch0.pageY,
+ touch1X: touch1.pageX,
+ touch1Y: touch1.pageY
+ };
+}
+function webViewerTouchMove(evt) {
+ if (!PDFViewerApplication._touchInfo || evt.touches.length !== 2) {
+ return;
+ }
+ const {
+ pdfViewer,
+ _touchInfo,
+ supportsPinchToZoom
+ } = PDFViewerApplication;
+ let [touch0, touch1] = evt.touches;
+ if (touch0.identifier > touch1.identifier) {
+ [touch0, touch1] = [touch1, touch0];
+ }
+ const {
+ pageX: page0X,
+ pageY: page0Y
+ } = touch0;
+ const {
+ pageX: page1X,
+ pageY: page1Y
+ } = touch1;
+ const {
+ touch0X: pTouch0X,
+ touch0Y: pTouch0Y,
+ touch1X: pTouch1X,
+ touch1Y: pTouch1Y
+ } = _touchInfo;
+ if (Math.abs(pTouch0X - page0X) <= 1 && Math.abs(pTouch0Y - page0Y) <= 1 && Math.abs(pTouch1X - page1X) <= 1 && Math.abs(pTouch1Y - page1Y) <= 1) {
+ return;
+ }
+ _touchInfo.touch0X = page0X;
+ _touchInfo.touch0Y = page0Y;
+ _touchInfo.touch1X = page1X;
+ _touchInfo.touch1Y = page1Y;
+ if (pTouch0X === page0X && pTouch0Y === page0Y) {
+ const v1X = pTouch1X - page0X;
+ const v1Y = pTouch1Y - page0Y;
+ const v2X = page1X - page0X;
+ const v2Y = page1Y - page0Y;
+ const det = v1X * v2Y - v1Y * v2X;
+ if (Math.abs(det) > 0.02 * Math.hypot(v1X, v1Y) * Math.hypot(v2X, v2Y)) {
+ return;
+ }
+ } else if (pTouch1X === page1X && pTouch1Y === page1Y) {
+ const v1X = pTouch0X - page1X;
+ const v1Y = pTouch0Y - page1Y;
+ const v2X = page0X - page1X;
+ const v2Y = page0Y - page1Y;
+ const det = v1X * v2Y - v1Y * v2X;
+ if (Math.abs(det) > 0.02 * Math.hypot(v1X, v1Y) * Math.hypot(v2X, v2Y)) {
+ return;
+ }
+ } else {
+ const diff0X = page0X - pTouch0X;
+ const diff1X = page1X - pTouch1X;
+ const diff0Y = page0Y - pTouch0Y;
+ const diff1Y = page1Y - pTouch1Y;
+ const dotProduct = diff0X * diff1X + diff0Y * diff1Y;
+ if (dotProduct >= 0) {
+ return;
+ }
+ }
+ evt.preventDefault();
+ const distance = Math.hypot(page0X - page1X, page0Y - page1Y) || 1;
+ const pDistance = Math.hypot(pTouch0X - pTouch1X, pTouch0Y - pTouch1Y) || 1;
+ const previousScale = pdfViewer.currentScale;
+ if (supportsPinchToZoom) {
+ const newScaleFactor = PDFViewerApplication._accumulateFactor(previousScale, distance / pDistance, "_touchUnusedFactor");
+ if (newScaleFactor < 1) {
+ PDFViewerApplication.zoomOut(null, newScaleFactor);
+ } else if (newScaleFactor > 1) {
+ PDFViewerApplication.zoomIn(null, newScaleFactor);
+ } else {
+ return;
+ }
+ } else {
+ const PIXELS_PER_LINE_SCALE = 30;
+ const ticks = PDFViewerApplication._accumulateTicks((distance - pDistance) / PIXELS_PER_LINE_SCALE, "_touchUnusedTicks");
+ if (ticks < 0) {
+ PDFViewerApplication.zoomOut(-ticks);
+ } else if (ticks > 0) {
+ PDFViewerApplication.zoomIn(ticks);
+ } else {
+ return;
+ }
+ }
+ PDFViewerApplication._centerAtPos(previousScale, (page0X + page1X) / 2, (page0Y + page1Y) / 2);
+}
+function webViewerTouchEnd(evt) {
+ if (!PDFViewerApplication._touchInfo) {
+ return;
+ }
+ evt.preventDefault();
+ PDFViewerApplication._touchInfo = null;
+ PDFViewerApplication._touchUnusedTicks = 0;
+ PDFViewerApplication._touchUnusedFactor = 1;
+}
+function webViewerClick(evt) {
+ if (!PDFViewerApplication.secondaryToolbar?.isOpen) {
+ return;
+ }
+ const appConfig = PDFViewerApplication.appConfig;
+ if (PDFViewerApplication.pdfViewer.containsElement(evt.target) || appConfig.toolbar?.container.contains(evt.target) && evt.target !== appConfig.secondaryToolbar?.toggleButton) {
+ PDFViewerApplication.secondaryToolbar.close();
+ }
+}
+function webViewerKeyUp(evt) {
+ if (evt.key === "Control") {
+ PDFViewerApplication._isCtrlKeyDown = false;
+ }
+}
+function webViewerKeyDown(evt) {
+ PDFViewerApplication._isCtrlKeyDown = evt.key === "Control";
+ if (PDFViewerApplication.overlayManager.active) {
+ return;
+ }
+ const {
+ eventBus,
+ pdfViewer
+ } = PDFViewerApplication;
+ const isViewerInPresentationMode = pdfViewer.isInPresentationMode;
+ let handled = false,
+ ensureViewerFocused = false;
+ const cmd = (evt.ctrlKey ? 1 : 0) | (evt.altKey ? 2 : 0) | (evt.shiftKey ? 4 : 0) | (evt.metaKey ? 8 : 0);
+ if (cmd === 1 || cmd === 8 || cmd === 5 || cmd === 12) {
+ switch (evt.keyCode) {
+ case 70:
+ if (!PDFViewerApplication.supportsIntegratedFind && !evt.shiftKey) {
+ PDFViewerApplication.findBar?.open();
+ handled = true;
+ }
+ break;
+ case 71:
+ if (!PDFViewerApplication.supportsIntegratedFind) {
+ const {
+ state
+ } = PDFViewerApplication.findController;
+ if (state) {
+ const newState = {
+ source: window,
+ type: "again",
+ findPrevious: cmd === 5 || cmd === 12
+ };
+ eventBus.dispatch("find", {
+ ...state,
+ ...newState
+ });
+ }
+ handled = true;
+ }
+ break;
+ case 61:
+ case 107:
+ case 187:
+ case 171:
+ PDFViewerApplication.zoomIn();
+ handled = true;
+ break;
+ case 173:
+ case 109:
+ case 189:
+ PDFViewerApplication.zoomOut();
+ handled = true;
+ break;
+ case 48:
+ case 96:
+ if (!isViewerInPresentationMode) {
+ setTimeout(function () {
+ PDFViewerApplication.zoomReset();
+ });
+ handled = false;
+ }
+ break;
+ case 38:
+ if (isViewerInPresentationMode || PDFViewerApplication.page > 1) {
+ PDFViewerApplication.page = 1;
+ handled = true;
+ ensureViewerFocused = true;
+ }
+ break;
+ case 40:
+ if (isViewerInPresentationMode || PDFViewerApplication.page < PDFViewerApplication.pagesCount) {
+ PDFViewerApplication.page = PDFViewerApplication.pagesCount;
+ handled = true;
+ ensureViewerFocused = true;
+ }
+ break;
+ }
+ }
+ if (cmd === 3 || cmd === 10) {
+ switch (evt.keyCode) {
+ case 80:
+ PDFViewerApplication.requestPresentationMode();
+ handled = true;
+ PDFViewerApplication.externalServices.reportTelemetry({
+ type: "buttons",
+ data: {
+ id: "presentationModeKeyboard"
+ }
+ });
+ break;
+ case 71:
+ if (PDFViewerApplication.appConfig.toolbar) {
+ PDFViewerApplication.appConfig.toolbar.pageNumber.select();
+ handled = true;
+ }
+ break;
+ }
+ }
+ if (handled) {
+ if (ensureViewerFocused && !isViewerInPresentationMode) {
+ pdfViewer.focus();
+ }
+ evt.preventDefault();
+ return;
+ }
+ const curElement = getActiveOrFocusedElement();
+ const curElementTagName = curElement?.tagName.toUpperCase();
+ if (curElementTagName === "INPUT" || curElementTagName === "TEXTAREA" || curElementTagName === "SELECT" || curElementTagName === "BUTTON" && (evt.keyCode === 13 || evt.keyCode === 32) || curElement?.isContentEditable) {
+ if (evt.keyCode !== 27) {
+ return;
+ }
+ }
+ if (cmd === 0) {
+ let turnPage = 0,
+ turnOnlyIfPageFit = false;
+ switch (evt.keyCode) {
+ case 38:
+ if (PDFViewerApplication.supportsCaretBrowsingMode) {
+ PDFViewerApplication.moveCaret(true, false);
+ handled = true;
+ break;
+ }
+ case 33:
+ if (pdfViewer.isVerticalScrollbarEnabled) {
+ turnOnlyIfPageFit = true;
+ }
+ turnPage = -1;
+ break;
+ case 8:
+ if (!isViewerInPresentationMode) {
+ turnOnlyIfPageFit = true;
+ }
+ turnPage = -1;
+ break;
+ case 37:
+ if (PDFViewerApplication.supportsCaretBrowsingMode) {
+ return;
+ }
+ if (pdfViewer.isHorizontalScrollbarEnabled) {
+ turnOnlyIfPageFit = true;
+ }
+ case 75:
+ case 80:
+ turnPage = -1;
+ break;
+ case 27:
+ if (PDFViewerApplication.secondaryToolbar?.isOpen) {
+ PDFViewerApplication.secondaryToolbar.close();
+ handled = true;
+ }
+ if (!PDFViewerApplication.supportsIntegratedFind && PDFViewerApplication.findBar?.opened) {
+ PDFViewerApplication.findBar.close();
+ handled = true;
+ }
+ break;
+ case 40:
+ if (PDFViewerApplication.supportsCaretBrowsingMode) {
+ PDFViewerApplication.moveCaret(false, false);
+ handled = true;
+ break;
+ }
+ case 34:
+ if (pdfViewer.isVerticalScrollbarEnabled) {
+ turnOnlyIfPageFit = true;
+ }
+ turnPage = 1;
+ break;
+ case 13:
+ case 32:
+ if (!isViewerInPresentationMode) {
+ turnOnlyIfPageFit = true;
+ }
+ turnPage = 1;
+ break;
+ case 39:
+ if (PDFViewerApplication.supportsCaretBrowsingMode) {
+ return;
+ }
+ if (pdfViewer.isHorizontalScrollbarEnabled) {
+ turnOnlyIfPageFit = true;
+ }
+ case 74:
+ case 78:
+ turnPage = 1;
+ break;
+ case 36:
+ if (isViewerInPresentationMode || PDFViewerApplication.page > 1) {
+ PDFViewerApplication.page = 1;
+ handled = true;
+ ensureViewerFocused = true;
+ }
+ break;
+ case 35:
+ if (isViewerInPresentationMode || PDFViewerApplication.page < PDFViewerApplication.pagesCount) {
+ PDFViewerApplication.page = PDFViewerApplication.pagesCount;
+ handled = true;
+ ensureViewerFocused = true;
+ }
+ break;
+ case 83:
+ PDFViewerApplication.pdfCursorTools?.switchTool(CursorTool.SELECT);
+ break;
+ case 72:
+ PDFViewerApplication.pdfCursorTools?.switchTool(CursorTool.HAND);
+ break;
+ case 82:
+ PDFViewerApplication.rotatePages(90);
+ break;
+ case 115:
+ PDFViewerApplication.pdfSidebar?.toggle();
+ break;
+ }
+ if (turnPage !== 0 && (!turnOnlyIfPageFit || pdfViewer.currentScaleValue === "page-fit")) {
+ if (turnPage > 0) {
+ pdfViewer.nextPage();
+ } else {
+ pdfViewer.previousPage();
+ }
+ handled = true;
+ }
+ }
+ if (cmd === 4) {
+ switch (evt.keyCode) {
+ case 13:
+ case 32:
+ if (!isViewerInPresentationMode && pdfViewer.currentScaleValue !== "page-fit") {
+ break;
+ }
+ pdfViewer.previousPage();
+ handled = true;
+ break;
+ case 38:
+ PDFViewerApplication.moveCaret(true, true);
+ handled = true;
+ break;
+ case 40:
+ PDFViewerApplication.moveCaret(false, true);
+ handled = true;
+ break;
+ case 82:
+ PDFViewerApplication.rotatePages(-90);
+ break;
+ }
+ }
+ if (!handled && !isViewerInPresentationMode) {
+ if (evt.keyCode >= 33 && evt.keyCode <= 40 || evt.keyCode === 32 && curElementTagName !== "BUTTON") {
+ ensureViewerFocused = true;
+ }
+ }
+ if (ensureViewerFocused && !pdfViewer.containsElement(curElement)) {
+ pdfViewer.focus();
+ }
+ if (handled) {
+ evt.preventDefault();
+ }
+}
+function beforeUnload(evt) {
+ evt.preventDefault();
+ evt.returnValue = "";
+ return false;
+}
+function webViewerAnnotationEditorStatesChanged(data) {
+ PDFViewerApplication.externalServices.updateEditorStates(data);
+}
+function webViewerReportTelemetry({
+ details
+}) {
+ PDFViewerApplication.externalServices.reportTelemetry(details);
+}
+
+;// CONCATENATED MODULE: ./web/viewer.js
+
+
+
+
+const pdfjsVersion = "4.1.249";
+const pdfjsBuild = "d07f37f44";
+const AppConstants = null;
+window.PDFViewerApplication = PDFViewerApplication;
+window.PDFViewerApplicationConstants = AppConstants;
+window.PDFViewerApplicationOptions = AppOptions;
+function getViewerConfiguration() {
+ return {
+ appContainer: document.body,
+ mainContainer: document.getElementById("viewerContainer"),
+ viewerContainer: document.getElementById("viewer"),
+ toolbar: {
+ container: document.getElementById("toolbarViewer"),
+ numPages: document.getElementById("numPages"),
+ pageNumber: document.getElementById("pageNumber"),
+ scaleSelect: document.getElementById("scaleSelect"),
+ customScaleOption: document.getElementById("customScaleOption"),
+ previous: document.getElementById("previous"),
+ next: document.getElementById("next"),
+ zoomIn: document.getElementById("zoomIn"),
+ zoomOut: document.getElementById("zoomOut"),
+ viewFind: document.getElementById("viewFind"),
+ print: document.getElementById("print"),
+ editorFreeTextButton: document.getElementById("editorFreeText"),
+ editorFreeTextParamsToolbar: document.getElementById("editorFreeTextParamsToolbar"),
+ editorHighlightButton: document.getElementById("editorHighlight"),
+ editorHighlightParamsToolbar: document.getElementById("editorHighlightParamsToolbar"),
+ editorHighlightColorPicker: document.getElementById("editorHighlightColorPicker"),
+ editorInkButton: document.getElementById("editorInk"),
+ editorInkParamsToolbar: document.getElementById("editorInkParamsToolbar"),
+ editorStampButton: document.getElementById("editorStamp"),
+ editorStampParamsToolbar: document.getElementById("editorStampParamsToolbar"),
+ download: document.getElementById("download")
+ },
+ secondaryToolbar: {
+ toolbar: document.getElementById("secondaryToolbar"),
+ toggleButton: document.getElementById("secondaryToolbarToggle"),
+ presentationModeButton: document.getElementById("presentationMode"),
+ openFileButton: null,
+ printButton: document.getElementById("secondaryPrint"),
+ downloadButton: document.getElementById("secondaryDownload"),
+ viewBookmarkButton: document.getElementById("viewBookmark"),
+ firstPageButton: document.getElementById("firstPage"),
+ lastPageButton: document.getElementById("lastPage"),
+ pageRotateCwButton: document.getElementById("pageRotateCw"),
+ pageRotateCcwButton: document.getElementById("pageRotateCcw"),
+ cursorSelectToolButton: document.getElementById("cursorSelectTool"),
+ cursorHandToolButton: document.getElementById("cursorHandTool"),
+ scrollPageButton: document.getElementById("scrollPage"),
+ scrollVerticalButton: document.getElementById("scrollVertical"),
+ scrollHorizontalButton: document.getElementById("scrollHorizontal"),
+ scrollWrappedButton: document.getElementById("scrollWrapped"),
+ spreadNoneButton: document.getElementById("spreadNone"),
+ spreadOddButton: document.getElementById("spreadOdd"),
+ spreadEvenButton: document.getElementById("spreadEven"),
+ documentPropertiesButton: document.getElementById("documentProperties")
+ },
+ sidebar: {
+ outerContainer: document.getElementById("outerContainer"),
+ sidebarContainer: document.getElementById("sidebarContainer"),
+ toggleButton: document.getElementById("sidebarToggle"),
+ resizer: document.getElementById("sidebarResizer"),
+ thumbnailButton: document.getElementById("viewThumbnail"),
+ outlineButton: document.getElementById("viewOutline"),
+ attachmentsButton: document.getElementById("viewAttachments"),
+ layersButton: document.getElementById("viewLayers"),
+ thumbnailView: document.getElementById("thumbnailView"),
+ outlineView: document.getElementById("outlineView"),
+ attachmentsView: document.getElementById("attachmentsView"),
+ layersView: document.getElementById("layersView"),
+ currentOutlineItemButton: document.getElementById("currentOutlineItem")
+ },
+ findBar: {
+ bar: document.getElementById("findbar"),
+ toggleButton: document.getElementById("viewFind"),
+ findField: document.getElementById("findInput"),
+ highlightAllCheckbox: document.getElementById("findHighlightAll"),
+ caseSensitiveCheckbox: document.getElementById("findMatchCase"),
+ matchDiacriticsCheckbox: document.getElementById("findMatchDiacritics"),
+ entireWordCheckbox: document.getElementById("findEntireWord"),
+ findMsg: document.getElementById("findMsg"),
+ findResultsCount: document.getElementById("findResultsCount"),
+ findPreviousButton: document.getElementById("findPrevious"),
+ findNextButton: document.getElementById("findNext")
+ },
+ passwordOverlay: {
+ dialog: document.getElementById("passwordDialog"),
+ label: document.getElementById("passwordText"),
+ input: document.getElementById("password"),
+ submitButton: document.getElementById("passwordSubmit"),
+ cancelButton: document.getElementById("passwordCancel")
+ },
+ documentProperties: {
+ dialog: document.getElementById("documentPropertiesDialog"),
+ closeButton: document.getElementById("documentPropertiesClose"),
+ fields: {
+ fileName: document.getElementById("fileNameField"),
+ fileSize: document.getElementById("fileSizeField"),
+ title: document.getElementById("titleField"),
+ author: document.getElementById("authorField"),
+ subject: document.getElementById("subjectField"),
+ keywords: document.getElementById("keywordsField"),
+ creationDate: document.getElementById("creationDateField"),
+ modificationDate: document.getElementById("modificationDateField"),
+ creator: document.getElementById("creatorField"),
+ producer: document.getElementById("producerField"),
+ version: document.getElementById("versionField"),
+ pageCount: document.getElementById("pageCountField"),
+ pageSize: document.getElementById("pageSizeField"),
+ linearized: document.getElementById("linearizedField")
+ }
+ },
+ altTextDialog: {
+ dialog: document.getElementById("altTextDialog"),
+ optionDescription: document.getElementById("descriptionButton"),
+ optionDecorative: document.getElementById("decorativeButton"),
+ textarea: document.getElementById("descriptionTextarea"),
+ cancelButton: document.getElementById("altTextCancel"),
+ saveButton: document.getElementById("altTextSave")
+ },
+ annotationEditorParams: {
+ editorFreeTextFontSize: document.getElementById("editorFreeTextFontSize"),
+ editorFreeTextColor: document.getElementById("editorFreeTextColor"),
+ editorInkColor: document.getElementById("editorInkColor"),
+ editorInkThickness: document.getElementById("editorInkThickness"),
+ editorInkOpacity: document.getElementById("editorInkOpacity"),
+ editorStampAddImage: document.getElementById("editorStampAddImage"),
+ editorFreeHighlightThickness: document.getElementById("editorFreeHighlightThickness")
+ },
+ printContainer: document.getElementById("printContainer")
+ };
+}
+function webViewerLoad() {
+ const config = getViewerConfiguration();
+ PDFViewerApplication.run(config);
+}
+document.blockUnblockOnload?.(true);
+if (document.readyState === "interactive" || document.readyState === "complete") {
+ webViewerLoad();
+} else {
+ document.addEventListener("DOMContentLoaded", webViewerLoad, true);
+}
+
+var __webpack_exports__PDFViewerApplication = __webpack_exports__.PDFViewerApplication;
+var __webpack_exports__PDFViewerApplicationConstants = __webpack_exports__.PDFViewerApplicationConstants;
+var __webpack_exports__PDFViewerApplicationOptions = __webpack_exports__.PDFViewerApplicationOptions;
+export { __webpack_exports__PDFViewerApplication as PDFViewerApplication, __webpack_exports__PDFViewerApplicationConstants as PDFViewerApplicationConstants, __webpack_exports__PDFViewerApplicationOptions as PDFViewerApplicationOptions };
diff --git a/toolkit/components/pdfjs/jar.mn b/toolkit/components/pdfjs/jar.mn
new file mode 100644
index 0000000000..e41afee7e1
--- /dev/null
+++ b/toolkit/components/pdfjs/jar.mn
@@ -0,0 +1,38 @@
+pdfjs.jar:
+% resource pdf.js %content/
+ content/PdfJs.sys.mjs (content/PdfJs.sys.mjs)
+ content/PdfJsDefaultPreferences.sys.mjs (content/PdfJsDefaultPreferences.sys.mjs)
+ content/PdfJsNetwork.sys.mjs (content/PdfJsNetwork.sys.mjs)
+ content/PdfJsTelemetry.sys.mjs (content/PdfJsTelemetry.sys.mjs)
+ content/PdfSandbox.sys.mjs (content/PdfSandbox.sys.mjs)
+ content/PdfStreamConverter.sys.mjs (content/PdfStreamConverter.sys.mjs)
+ content/build/ (content/build/*)
+ content/web/cmaps/ (content/web/cmaps/*)
+ content/web/standard_fonts/ (content/web/standard_fonts/*)
+ content/web/images/ (content/web/images/annotation-*.svg)
+ content/web/images/loading-icon.gif (content/web/images/loading-icon.gif)
+#ifdef ANDROID
+ content/GeckoViewPdfjsParent.sys.mjs (content/GeckoViewPdfjsParent.sys.mjs)
+ content/GeckoViewPdfjsChild.sys.mjs (content/GeckoViewPdfjsChild.sys.mjs)
+ content/web/viewer.html (content/web/viewer-geckoview.html)
+ content/web/viewer.css (content/web/viewer-geckoview.css)
+ content/web/viewer.mjs (content/web/viewer-geckoview.mjs)
+ content/web/images/gv-toolbarButton-download.svg (content/web/images/gv-toolbarButton-download.svg)
+ content/web/images/gv-toolbarButton-openinapp.svg (content/web/images/gv-toolbarButton-openinapp.svg)
+#else
+ content/PdfjsParent.sys.mjs (content/PdfjsParent.sys.mjs)
+ content/PdfjsChild.sys.mjs (content/PdfjsChild.sys.mjs)
+ content/web/viewer.html (content/web/viewer.html)
+ content/web/viewer.css (content/web/viewer.css)
+ content/web/viewer.mjs (content/web/viewer.mjs)
+ content/web/debugger.css (content/web/debugger.css)
+ content/web/debugger.mjs (content/web/debugger.mjs)
+ content/web/images/ (content/web/images/secondaryToolbarButton*.svg)
+ content/web/images/ (content/web/images/toolbarButton*.svg)
+ content/web/images/ (content/web/images/treeitem*.svg)
+ content/web/images/ (content/web/images/cursor*.svg)
+ content/web/images/ (content/web/images/findbar*.svg)
+ content/web/images/ (content/web/images/loading*.svg)
+ content/web/images/ (content/web/images/altText*.svg)
+ content/web/images/ (content/web/images/editor-toolbar-*.svg)
+#endif
diff --git a/toolkit/components/pdfjs/metrics.yaml b/toolkit/components/pdfjs/metrics.yaml
new file mode 100644
index 0000000000..be61c831f7
--- /dev/null
+++ b/toolkit/components/pdfjs/metrics.yaml
@@ -0,0 +1,334 @@
+# This Source Code Form is subject to the terms of the Mozilla Public↩
+# License, v. 2.0. If a copy of the MPL was not distributed with this↩
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.↩
+
+# Adding a new metric? We have docs for that!↩
+# https://firefox-source-docs.mozilla.org/toolkit/components/glean/user/new_definitions_file.html↩
+
+---
+$schema: moz://mozilla.org/schemas/glean/metrics/2-0-0
+$tags:
+ - 'Firefox :: PDF Viewer'
+
+
+pdfjs:
+ editing:
+ type: labeled_counter
+ labels:
+ - ink
+ - freetext
+ - stamp
+ - save
+ - print
+ description: >
+ Counts the number of times some PDF editing features are used.
+ bugs:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1782254
+ data_reviews:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1782254#c4
+ data_sensitivity:
+ - interaction
+ notification_emails:
+ - cdenizet@mozilla.com
+ - mcastelluccio@mozilla.com
+ expires: never
+ stamp:
+ type: labeled_counter
+ labels:
+ - inserted_image
+ - alt_text_save
+ - alt_text_cancel
+ - alt_text_tooltip
+ - alt_text_edit
+ - alt_text_description
+ - alt_text_decorative
+ - alt_text_keyboard
+ description: >
+ Counts the number of times some PDF editing features are used.
+ bugs:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1853960
+ data_reviews:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1853960#c1
+ data_sensitivity:
+ - interaction
+ notification_emails:
+ - cdenizet@mozilla.com
+ - mcastelluccio@mozilla.com
+ expires: never
+ buttons:
+ type: labeled_counter
+ labels:
+ - presentation_mode
+ - presentation_mode_keyboard
+ - view_bookmark
+ - first_page
+ - last_page
+ - page_rotate_cw
+ - page_rotate_ccw
+ - cursor_select_tool
+ - cursor_hand_tool
+ - scroll_page
+ - scroll_vertical
+ - scroll_horizontal
+ - scroll_wrapped
+ - spread_none
+ - spread_odd
+ - spread_even
+ - document_properties
+ description: >
+ Counts the number of times some actions are executed in the PDF viewer.
+ bugs:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1789883
+ data_reviews:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1789883#2
+ data_sensitivity:
+ - interaction
+ notification_emails:
+ - cdenizet@mozilla.com
+ - mcastelluccio@mozilla.com
+ expires: never
+ geckoview:
+ type: labeled_counter
+ labels:
+ - download_tapped
+ - open_in_app_tapped
+ - open_in_app_just_once
+ - open_in_app_always
+ - download_failed
+ - download_succeeded
+ - save_as_pdf_tapped
+ description: >
+ Counts the number of times some actions are executed in the PDF viewer.
+ bugs:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1829216
+ data_reviews:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1829216#2
+ data_sensitivity:
+ - interaction
+ notification_emails:
+ - cdenizet@mozilla.com
+ - mcastelluccio@mozilla.com
+ expires: never
+ used:
+ bugs:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1566882
+ data_reviews:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1566882#c2
+ description: >
+ How many times PDF Viewer was used.
+ expires: never
+ type: counter
+ notification_emails:
+ - cdenizet@mozilla.com
+ - mcastelluccio@mozilla.com
+ time_to_view:
+ type: custom_distribution
+ bugs:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1566882
+ data_reviews:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1566882#c2
+ description: >
+ Time spent to display first page in PDF Viewer (ms).
+ expires: never
+ range_min: 1
+ range_max: 10000
+ bucket_count: 50
+ histogram_type: exponential
+ unit: ms
+ data_sensitivity:
+ - interaction
+ notification_emails:
+ - cdenizet@mozilla.com
+ - mcastelluccio@mozilla.com
+pdfjs.editing.highlight:
+ kind:
+ type: labeled_counter
+ labels:
+ - free_highlight
+ - highlight
+ description: >
+ Counts the number of times a given kind is used to highlight.
+ bugs:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1866437
+ data_reviews:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1866437#c1
+ data_sensitivity:
+ - interaction
+ notification_emails:
+ - pdfjs-team@mozilla.com
+ expires: never
+
+ method:
+ type: labeled_counter
+ labels:
+ - context_menu
+ - main_toolbar
+ - floating_button
+ description: >
+ Counts the number of times a given method is used to highlight.
+ bugs:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1866437
+ data_reviews:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1866437#c1
+ data_sensitivity:
+ - interaction
+ notification_emails:
+ - pdfjs-team@mozilla.com
+ expires: never
+
+ color:
+ type: labeled_counter
+ labels:
+ - yellow
+ - green
+ - blue
+ - pink
+ - red
+ description: >
+ Counts the number of times a given color is used to highlight.
+ bugs:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1866437
+ data_reviews:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1866437#c1
+ data_sensitivity:
+ - interaction
+ notification_emails:
+ - pdfjs-team@mozilla.com
+ expires: never
+
+ color_changed:
+ type: counter
+ description: >
+ Counts the number of times the user changes the color of a highlight.
+ bugs:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1866437
+ data_reviews:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1866437#c1
+ data_sensitivity:
+ - interaction
+ notification_emails:
+ - pdfjs-team@mozilla.com
+ expires: never
+
+ number_of_colors:
+ type: labeled_counter
+ labels:
+ - one
+ - two
+ - three
+ - four
+ - five
+ description: >
+ Counts the number of different colors used to highlight.
+ bugs:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1866437
+ data_reviews:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1866437#c1
+ data_sensitivity:
+ - interaction
+ notification_emails:
+ - pdfjs-team@mozilla.com
+ expires: never
+
+ thickness:
+ type: custom_distribution
+ range_min: 8
+ range_max: 24
+ bucket_count: 17
+ histogram_type: linear
+ unit: pixels
+ description: >
+ The thickness used to draw a free highlight.
+ bugs:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1866437
+ data_reviews:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1866437#c1
+ data_sensitivity:
+ - interaction
+ notification_emails:
+ - pdfjs-team@mozilla.com
+ expires: never
+
+ thickness_changed:
+ type: counter
+ description: >
+ Counts the number of times the user changes the thickness of a free highlight.
+ bugs:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1866437
+ data_reviews:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1866437#c1
+ data_sensitivity:
+ - interaction
+ notification_emails:
+ - pdfjs-team@mozilla.com
+ expires: never
+
+ save:
+ type: counter
+ description: >
+ Counts the number of times the user saves a PDF with highlights.
+ bugs:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1866437
+ data_reviews:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1866437#c1
+ data_sensitivity:
+ - interaction
+ notification_emails:
+ - pdfjs-team@mozilla.com
+ expires: never
+
+ print:
+ type: counter
+ description: >
+ Counts the number of times the user prints a PDF with highlights.
+ bugs:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1866437
+ data_reviews:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1866437#c1
+ data_sensitivity:
+ - interaction
+ notification_emails:
+ - pdfjs-team@mozilla.com
+ expires: never
+
+ edited:
+ type: counter
+ description: >
+ Counts the number of times the user edits highlights.
+ bugs:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1866437
+ data_reviews:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1866437#c1
+ data_sensitivity:
+ - interaction
+ notification_emails:
+ - pdfjs-team@mozilla.com
+ expires: never
+
+ deleted:
+ type: counter
+ description: >
+ Counts the number of times the user deletes highlights.
+ bugs:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1866437
+ data_reviews:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1866437#c1
+ data_sensitivity:
+ - interaction
+ notification_emails:
+ - pdfjs-team@mozilla.com
+ expires: never
+
+ toggle_visibility:
+ type: counter
+ description: >
+ Counts the number of times the user toggles the visibility of highlights.
+ bugs:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1866437
+ data_reviews:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1866437#c1
+ data_sensitivity:
+ - interaction
+ notification_emails:
+ - pdfjs-team@mozilla.com
+ expires: never
diff --git a/toolkit/components/pdfjs/moz.build b/toolkit/components/pdfjs/moz.build
new file mode 100644
index 0000000000..0757e480a3
--- /dev/null
+++ b/toolkit/components/pdfjs/moz.build
@@ -0,0 +1,21 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+with Files("**"):
+ BUG_COMPONENT = ("Firefox", "PDF Viewer")
+
+BROWSER_CHROME_MANIFESTS += ["test/browser.toml"]
+MOCHITEST_MANIFESTS += ["test/mochitest.toml"]
+
+JAR_MANIFESTS += ["jar.mn"]
+
+EXTRA_JS_MODULES += [
+ "pdfjs.sys.mjs",
+]
+
+XPCOM_MANIFESTS += [
+ "components.conf",
+]
diff --git a/toolkit/components/pdfjs/moz.yaml b/toolkit/components/pdfjs/moz.yaml
new file mode 100644
index 0000000000..4d22740080
--- /dev/null
+++ b/toolkit/components/pdfjs/moz.yaml
@@ -0,0 +1,61 @@
+# Version of this schema
+schema: 1
+
+bugzilla:
+ # Bugzilla product and component for this directory and subdirectories
+ product: Firefox
+ component: PDF Viewer
+
+# Document the source of externally hosted code
+origin:
+
+ # Short name of the package/library
+ name: PDF.js
+
+ description: Portable Document Format (PDF) viewer that is built with HTML5
+
+ # Full URL for the package's homepage/etc
+ # Usually different from repository url
+ url: https://github.com/mozilla/pdf.js
+
+ # Human-readable identifier for this version/release
+ # Generally "version NNN", "tag SSS", "bookmark SSS"
+ release: 29c493d36bb5a44251804e9204973211172e0412 (2024-03-01T12:08:44Z).
+ revision: 29c493d36bb5a44251804e9204973211172e0412
+
+ # The package's license, where possible using the mnemonic from
+ # https://spdx.org/licenses/
+ # Multiple licenses can be specified (as a YAML list)
+ # A "LICENSE" file must exist containing the full license text
+ license: Apache-2.0
+
+vendoring:
+ url: https://github.com/mozilla/pdf.js
+ source-hosting: github
+ skip-vendoring-steps: ['fetch', 'update-moz-build']
+
+ keep:
+ - chrome.manifest
+ - components.conf
+ - jar.mn
+ - update.sh
+ - test
+
+ update-actions:
+ - action: run-script
+ script: 'update.sh'
+ cwd: '{yaml_dir}'
+ args: ['{revision}']
+
+updatebot:
+ maintainer-phab: "#pdfjs-reviewers"
+ maintainer-bz: cdenizet@mozilla.com
+ fuzzy-query: "'debug | 'opt !san !android"
+ fuzzy-paths:
+ - toolkit/components/pdfjs/test
+ - browser/base/content/test/static
+ tasks:
+ - type: vendoring
+ enabled: true
+ frequency: "1 week, 3 commits"
+ blocking: 1626408
diff --git a/toolkit/components/pdfjs/pdfjs.sys.mjs b/toolkit/components/pdfjs/pdfjs.sys.mjs
new file mode 100644
index 0000000000..00ffd6c9b8
--- /dev/null
+++ b/toolkit/components/pdfjs/pdfjs.sys.mjs
@@ -0,0 +1,28 @@
+/* Copyright 2018 Mozilla Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+const lazy = {};
+
+ChromeUtils.defineESModuleGetters(lazy, {
+ PdfStreamConverter: "resource://pdf.js/PdfStreamConverter.sys.mjs",
+});
+
+// Register/unregister a constructor as a factory.
+export function StreamConverterFactory() {
+ if (!Services.prefs.getBoolPref("pdfjs.disabled", false)) {
+ return new lazy.PdfStreamConverter();
+ }
+ throw Components.Exception("", Cr.NS_ERROR_FACTORY_NOT_REGISTERED);
+}
diff --git a/toolkit/components/pdfjs/test/browser.toml b/toolkit/components/pdfjs/test/browser.toml
new file mode 100644
index 0000000000..4d045fd33e
--- /dev/null
+++ b/toolkit/components/pdfjs/test/browser.toml
@@ -0,0 +1,83 @@
+[DEFAULT]
+support-files = [
+ "file_pdfjs_test.pdf",
+ "head.js",
+]
+
+["browser_pdfjs_download_button.js"]
+
+["browser_pdfjs_editing_contextmenu.js"]
+skip-if = ["headless"] # the headless clipboard only recognizes unicode mime type
+
+["browser_pdfjs_editing_telemetry.js"]
+
+["browser_pdfjs_fill_login.js"]
+support-files = ["file_pdfjs_form.pdf"]
+
+["browser_pdfjs_filters.js"]
+support-files = ["file_pdfjs_transfer_map.pdf"]
+
+["browser_pdfjs_find.js"]
+support-files = [
+ "file_pdfjs_object_stream.pdf",
+ "file_pdfjs_object_stream.pdf^headers^",
+]
+
+["browser_pdfjs_force_opening_files.js"]
+
+["browser_pdfjs_form.js"]
+support-files = ["file_pdfjs_form.pdf"]
+
+["browser_pdfjs_fullscreen.js"]
+
+["browser_pdfjs_hcm.js"]
+support-files = ["file_pdfjs_hcm.pdf"]
+
+["browser_pdfjs_highlight_telemetry.js"]
+skip-if = ["true"]
+
+["browser_pdfjs_js.js"]
+support-files = ["file_pdfjs_js.pdf"]
+
+["browser_pdfjs_load_telemetry.js"]
+
+["browser_pdfjs_main.js"]
+
+["browser_pdfjs_minimum_font_size.js"]
+
+["browser_pdfjs_navigation.js"]
+
+["browser_pdfjs_nonpdf_filename.js"]
+support-files = ["file_pdf_download_link.html"]
+
+["browser_pdfjs_not_default.js"]
+support-files = [
+ "file_pdfjs_object_stream.pdf",
+ "file_pdfjs_object_stream.pdf^headers^",
+]
+
+["browser_pdfjs_octet_stream.js"]
+skip-if = ["os == 'linux' && bits == 64"] # Bug 1773830
+support-files = [
+ "file_pdfjs_object_stream.pdf",
+ "file_pdfjs_object_stream.pdf^headers^",
+]
+
+["browser_pdfjs_saveas.js"]
+support-files = [
+ "!/toolkit/content/tests/browser/common/mockTransfer.js",
+ "file_pdf_download_link.html",
+]
+
+["browser_pdfjs_savedialog.js"]
+skip-if = ["verify"]
+
+["browser_pdfjs_secondary_toolbar_telemetry.js"]
+
+["browser_pdfjs_stamp_telemetry.js"]
+support-files = ["moz.png"]
+
+["browser_pdfjs_views.js"]
+
+["browser_pdfjs_zoom.js"]
+skip-if = ["verify && debug && os == 'win'"]
diff --git a/toolkit/components/pdfjs/test/browser_pdfjs_download_button.js b/toolkit/components/pdfjs/test/browser_pdfjs_download_button.js
new file mode 100644
index 0000000000..1e3c00620c
--- /dev/null
+++ b/toolkit/components/pdfjs/test/browser_pdfjs_download_button.js
@@ -0,0 +1,125 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+const RELATIVE_DIR = "toolkit/components/pdfjs/test/";
+const TESTROOT = "https://example.com/browser/" + RELATIVE_DIR;
+
+var MockFilePicker = SpecialPowers.MockFilePicker;
+MockFilePicker.init(window);
+MockFilePicker.returnValue = MockFilePicker.returnOK;
+
+var tempDir;
+
+async function promiseDownloadFinished(list) {
+ return new Promise(resolve => {
+ list.addView({
+ onDownloadChanged(download) {
+ download.launchWhenSucceeded = false;
+ if (download.succeeded || download.error) {
+ list.removeView(this);
+ resolve(download);
+ }
+ },
+ });
+ });
+}
+
+function createPromiseForFilePicker() {
+ return new Promise(resolve => {
+ MockFilePicker.showCallback = fp => {
+ let destFile = tempDir.clone();
+ destFile.append(fp.defaultString);
+ if (destFile.exists()) {
+ destFile.remove(false);
+ }
+ MockFilePicker.setFiles([destFile]);
+ MockFilePicker.filterIndex = 0; // kSaveAsType_Complete
+ resolve();
+ };
+ });
+}
+
+add_setup(async function () {
+ tempDir = createTemporarySaveDirectory();
+ MockFilePicker.displayDirectory = tempDir;
+
+ registerCleanupFunction(async function () {
+ MockFilePicker.cleanup();
+ await cleanupDownloads();
+ tempDir.remove(true);
+ });
+});
+
+/**
+ * Check clicking the download button saves the file and doesn't open a new viewer
+ */
+add_task(async function test_downloading_pdf_nonprivate_window() {
+ const pdfUrl = TESTROOT + "file_pdfjs_test.pdf";
+
+ await SpecialPowers.pushPrefEnv({
+ set: [["browser.download.always_ask_before_handling_new_types", false]],
+ });
+
+ await BrowserTestUtils.withNewTab(
+ { gBrowser, url: "about:blank" },
+ async function (browser) {
+ await waitForPdfJS(browser, pdfUrl);
+
+ const tabCount = gBrowser.tabs.length;
+ info(`${tabCount} tabs are open at the start of the test`);
+
+ let downloadList = await Downloads.getList(Downloads.PUBLIC);
+
+ let filePickerShown = createPromiseForFilePicker();
+
+ let downloadFinishedPromise = promiseDownloadFinished(downloadList);
+
+ info("Clicking on the download button...");
+ await SpecialPowers.spawn(browser, [], () => {
+ content.document.querySelector("#download").click();
+ });
+ info("Waiting for a filename to be picked from the file picker");
+ await filePickerShown;
+
+ await downloadFinishedPromise;
+ ok(true, "A download was added when we clicked download");
+
+ // See bug 1739348 - don't show panel for downloads that opened dialogs
+ ok(
+ !DownloadsPanel.isPanelShowing,
+ "The download panel did not open, since the file picker was shown already"
+ );
+
+ const allDownloads = await downloadList.getAll();
+ const dl = allDownloads.find(dl => dl.source.originalUrl === pdfUrl);
+ ok(!!dl, "The pdf download has the correct url in source.originalUrl");
+
+ SpecialPowers.clipboardCopyString("");
+ DownloadsCommon.copyDownloadLink(dl);
+ const copiedUrl = SpecialPowers.getClipboardData("text/plain");
+ is(copiedUrl, pdfUrl, "The copied url must be the original one");
+
+ is(
+ gBrowser.tabs.length,
+ tabCount,
+ "No new tab was opened to view the downloaded PDF"
+ );
+
+ SpecialPowers.clipboardCopyString("");
+ const downloadsLoaded = BrowserTestUtils.waitForEvent(
+ browser,
+ "InitialDownloadsLoaded",
+ true
+ );
+ BrowserTestUtils.startLoadingURIString(browser, "about:downloads");
+ await downloadsLoaded;
+
+ info("Wait for the clipboard to contain the url of the pdf");
+ await SimpleTest.promiseClipboardChange(pdfUrl, () => {
+ goDoCommand("cmd_copy");
+ });
+ }
+ );
+});
diff --git a/toolkit/components/pdfjs/test/browser_pdfjs_editing_contextmenu.js b/toolkit/components/pdfjs/test/browser_pdfjs_editing_contextmenu.js
new file mode 100644
index 0000000000..d857bb6aac
--- /dev/null
+++ b/toolkit/components/pdfjs/test/browser_pdfjs_editing_contextmenu.js
@@ -0,0 +1,381 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+const RELATIVE_DIR = "toolkit/components/pdfjs/test/";
+const TESTROOT = "http://example.com/browser/" + RELATIVE_DIR;
+
+// This is a modified version from browser_contextmenuFillLogins.js.
+async function openContextMenuAt(browser, x, y) {
+ const contextMenu = document.getElementById("contentAreaContextMenu");
+
+ const contextMenuShownPromise = BrowserTestUtils.waitForEvent(
+ contextMenu,
+ "popupshown"
+ );
+
+ // Synthesize a contextmenu event to actually open the context menu.
+ await BrowserTestUtils.synthesizeMouseAtPoint(
+ x,
+ y,
+ {
+ type: "contextmenu",
+ button: 2,
+ },
+ browser
+ );
+
+ await contextMenuShownPromise;
+ return contextMenu;
+}
+
+/**
+ * Open a context menu and get the pdfjs entries
+ * @param {Object} browser
+ * @param {Object} box
+ * @returns {Map<string,HTMLElement>} the pdfjs menu entries.
+ */
+async function getContextMenuItems(browser, box) {
+ return new Promise(resolve => {
+ setTimeout(async () => {
+ const { x, y, width, height } = box;
+ const menuitems = [
+ "context-pdfjs-undo",
+ "context-pdfjs-redo",
+ "context-sep-pdfjs-redo",
+ "context-pdfjs-cut",
+ "context-pdfjs-copy",
+ "context-pdfjs-paste",
+ "context-pdfjs-delete",
+ "context-pdfjs-selectall",
+ "context-sep-pdfjs-selectall",
+ ];
+
+ await openContextMenuAt(browser, x + width / 2, y + height / 2);
+ const results = new Map();
+ const doc = browser.ownerDocument;
+ for (const menuitem of menuitems) {
+ const item = doc.getElementById(menuitem);
+ results.set(menuitem, item || null);
+ }
+
+ resolve(results);
+ }, 0);
+ });
+}
+
+/**
+ * Open a context menu on the element corresponding to the given selector
+ * and returs the pdfjs menu entries.
+ * @param {Object} browser
+ * @param {string} selector
+ * @returns {Map<string,HTMLElement>} the pdfjs menu entries.
+ */
+async function getContextMenuItemsOn(browser, selector) {
+ const box = await SpecialPowers.spawn(
+ browser,
+ [selector],
+ async function (selector) {
+ const element = content.document.querySelector(selector);
+ const { x, y, width, height } = element.getBoundingClientRect();
+ return { x, y, width, height };
+ }
+ );
+ return getContextMenuItems(browser, box);
+}
+
+/**
+ * Hide the context menu.
+ * @param {Object} browser
+ */
+async function hideContextMenu(browser) {
+ await new Promise(resolve =>
+ setTimeout(async () => {
+ const doc = browser.ownerDocument;
+ const contextMenu = doc.getElementById("contentAreaContextMenu");
+
+ const popupHiddenPromise = BrowserTestUtils.waitForEvent(
+ contextMenu,
+ "popuphidden"
+ );
+ contextMenu.hidePopup();
+ await popupHiddenPromise;
+ resolve();
+ }, 0)
+ );
+}
+
+async function clickOnItem(browser, items, entry) {
+ const editingPromise = BrowserTestUtils.waitForContentEvent(
+ browser,
+ "editingaction",
+ false,
+ null,
+ true
+ );
+ const contextMenu = document.getElementById("contentAreaContextMenu");
+ contextMenu.activateItem(items.get(entry));
+ await editingPromise;
+}
+
+/**
+ * Asserts that the enabled pdfjs menuitems are the expected ones.
+ * @param {Map<string,HTMLElement>} menuitems
+ * @param {Array<string>} expected
+ */
+function assertMenuitems(menuitems, expected) {
+ Assert.deepEqual(
+ [...menuitems.values()]
+ .filter(
+ elmt =>
+ !elmt.id.includes("-sep-") &&
+ !elmt.hidden &&
+ elmt.getAttribute("disabled") === "false"
+ )
+ .map(elmt => elmt.id),
+ expected
+ );
+}
+
+// Text copy, paste, undo, redo, delete and select all in using the context
+// menu.
+add_task(async function test() {
+ let mimeService = Cc["@mozilla.org/mime;1"].getService(Ci.nsIMIMEService);
+ let handlerInfo = mimeService.getFromTypeAndExtension(
+ "application/pdf",
+ "pdf"
+ );
+
+ // Make sure pdf.js is the default handler.
+ is(
+ handlerInfo.alwaysAskBeforeHandling,
+ false,
+ "pdf handler defaults to always-ask is false"
+ );
+ is(
+ handlerInfo.preferredAction,
+ Ci.nsIHandlerInfo.handleInternally,
+ "pdf handler defaults to internal"
+ );
+
+ info("Pref action: " + handlerInfo.preferredAction);
+
+ await BrowserTestUtils.withNewTab(
+ { gBrowser, url: "about:blank" },
+ async function (browser) {
+ SpecialPowers.clipboardCopyString("");
+
+ await SpecialPowers.pushPrefEnv({
+ set: [["pdfjs.annotationEditorMode", 0]],
+ });
+
+ // check that PDF is opened with internal viewer
+ await waitForPdfJSAllLayers(browser, TESTROOT + "file_pdfjs_test.pdf", [
+ [
+ "annotationEditorLayer",
+ "annotationLayer",
+ "textLayer",
+ "canvasWrapper",
+ ],
+ ["annotationEditorLayer", "textLayer", "canvasWrapper"],
+ ]);
+
+ const spanBox = await getSpanBox(browser, "and found references");
+ let menuitems = await getContextMenuItems(browser, spanBox);
+
+ // Nothing have been edited, hence the context menu doesn't contain any
+ // pdf entries.
+ Assert.ok(
+ [...menuitems.values()].every(elmt => elmt.hidden),
+ "No visible pdf menuitem"
+ );
+ await hideContextMenu(browser);
+
+ await enableEditor(browser, "FreeText");
+ await addFreeText(browser, "hello", spanBox);
+
+ await BrowserTestUtils.waitForCondition(
+ async () => (await countElements(browser, ".freeTextEditor")) !== 0
+ );
+
+ await TestUtils.waitForTick();
+
+ // The PDF already has a text annotation.
+ Assert.equal(await countElements(browser, ".freeTextEditor"), 2);
+
+ // Unselect.
+ await escape(browser);
+
+ await BrowserTestUtils.waitForCondition(
+ async () => (await countElements(browser, ".selectedEditor")) !== 1
+ );
+
+ Assert.equal(await countElements(browser, ".selectedEditor"), 0);
+
+ menuitems = await getContextMenuItems(browser, spanBox);
+ assertMenuitems(menuitems, [
+ "context-pdfjs-undo", // Last created editor is undoable
+ "context-pdfjs-selectall", // and selectable.
+ ]);
+ // Undo.
+ await clickOnItem(browser, menuitems, "context-pdfjs-undo");
+
+ await BrowserTestUtils.waitForCondition(
+ async () => (await countElements(browser, ".freeTextEditor")) !== 2
+ );
+
+ Assert.equal(
+ await countElements(browser, ".freeTextEditor"),
+ 1,
+ "The FreeText editor must have been removed"
+ );
+
+ menuitems = await getContextMenuItems(browser, spanBox);
+
+ // The editor removed thanks to "undo" is now redoable
+ assertMenuitems(menuitems, [
+ "context-pdfjs-redo",
+ "context-pdfjs-selectall",
+ ]);
+ await clickOnItem(browser, menuitems, "context-pdfjs-redo");
+
+ await BrowserTestUtils.waitForCondition(
+ async () => (await countElements(browser, ".freeTextEditor")) !== 1
+ );
+
+ Assert.equal(
+ await countElements(browser, ".freeTextEditor"),
+ 2,
+ "The FreeText editor must have been added back"
+ );
+
+ await clickOn(browser, "#pdfjs_internal_editor_0");
+ menuitems = await getContextMenuItemsOn(
+ browser,
+ "#pdfjs_internal_editor_0"
+ );
+
+ assertMenuitems(menuitems, [
+ "context-pdfjs-undo",
+ "context-pdfjs-cut",
+ "context-pdfjs-copy",
+ "context-pdfjs-delete",
+ "context-pdfjs-selectall",
+ ]);
+
+ await clickOnItem(browser, menuitems, "context-pdfjs-cut");
+
+ await BrowserTestUtils.waitForCondition(
+ async () => (await countElements(browser, ".freeTextEditor")) !== 2
+ );
+
+ Assert.equal(
+ await countElements(browser, ".freeTextEditor"),
+ 1,
+ "The FreeText editor must have been cut"
+ );
+
+ menuitems = await getContextMenuItems(browser, spanBox);
+ assertMenuitems(menuitems, [
+ "context-pdfjs-undo",
+ "context-pdfjs-paste",
+ "context-pdfjs-selectall",
+ ]);
+
+ await clickOnItem(browser, menuitems, "context-pdfjs-paste");
+
+ await BrowserTestUtils.waitForCondition(
+ async () => (await countElements(browser, ".freeTextEditor")) !== 1
+ );
+
+ Assert.equal(
+ await countElements(browser, ".freeTextEditor"),
+ 2,
+ "The FreeText editor must have been pasted"
+ );
+
+ await clickOn(browser, "#pdfjs_internal_editor_1");
+ menuitems = await getContextMenuItemsOn(
+ browser,
+ "#pdfjs_internal_editor_1"
+ );
+
+ assertMenuitems(menuitems, [
+ "context-pdfjs-undo",
+ "context-pdfjs-cut",
+ "context-pdfjs-copy",
+ "context-pdfjs-paste",
+ "context-pdfjs-delete",
+ "context-pdfjs-selectall",
+ ]);
+
+ await clickOnItem(browser, menuitems, "context-pdfjs-delete");
+
+ await BrowserTestUtils.waitForCondition(
+ async () => (await countElements(browser, ".freeTextEditor")) !== 2
+ );
+
+ Assert.equal(
+ await countElements(browser, ".freeTextEditor"),
+ 1,
+ "The FreeText editor must have been deleted"
+ );
+
+ menuitems = await getContextMenuItems(browser, spanBox);
+ await clickOnItem(browser, menuitems, "context-pdfjs-paste");
+
+ await BrowserTestUtils.waitForCondition(
+ async () => (await countElements(browser, ".freeTextEditor")) !== 1
+ );
+
+ Assert.equal(
+ await countElements(browser, ".freeTextEditor"),
+ 2,
+ "The FreeText editor must have been pasted"
+ );
+
+ await clickOn(browser, "#pdfjs_internal_editor_2");
+ menuitems = await getContextMenuItemsOn(
+ browser,
+ "#pdfjs_internal_editor_2"
+ );
+
+ await clickOnItem(browser, menuitems, "context-pdfjs-copy");
+
+ menuitems = await getContextMenuItemsOn(
+ browser,
+ "#pdfjs_internal_editor_2"
+ );
+ await clickOnItem(browser, menuitems, "context-pdfjs-paste");
+
+ await BrowserTestUtils.waitForCondition(
+ async () => (await countElements(browser, ".freeTextEditor")) !== 2
+ );
+
+ Assert.equal(
+ await countElements(browser, ".freeTextEditor"),
+ 3,
+ "The FreeText editor must have been pasted"
+ );
+
+ menuitems = await getContextMenuItems(browser, spanBox);
+ await clickOnItem(browser, menuitems, "context-pdfjs-selectall");
+ menuitems = await getContextMenuItems(browser, spanBox);
+ await clickOnItem(browser, menuitems, "context-pdfjs-delete");
+
+ await BrowserTestUtils.waitForCondition(
+ async () => (await countElements(browser, ".freeTextEditor")) !== 3
+ );
+
+ Assert.equal(
+ await countElements(browser, ".freeTextEditor"),
+ 0,
+ "All the FreeText editors must have been deleted"
+ );
+
+ await SpecialPowers.spawn(browser, [], async function () {
+ var viewer = content.wrappedJSObject.PDFViewerApplication;
+ await viewer.close();
+ });
+ }
+ );
+});
diff --git a/toolkit/components/pdfjs/test/browser_pdfjs_editing_telemetry.js b/toolkit/components/pdfjs/test/browser_pdfjs_editing_telemetry.js
new file mode 100644
index 0000000000..f05b28c917
--- /dev/null
+++ b/toolkit/components/pdfjs/test/browser_pdfjs_editing_telemetry.js
@@ -0,0 +1,96 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+const RELATIVE_DIR = "toolkit/components/pdfjs/test/";
+const TESTROOT = "http://example.com/browser/" + RELATIVE_DIR;
+
+// Test telemetry.
+add_task(async function test() {
+ let mimeService = Cc["@mozilla.org/mime;1"].getService(Ci.nsIMIMEService);
+ let handlerInfo = mimeService.getFromTypeAndExtension(
+ "application/pdf",
+ "pdf"
+ );
+
+ // Make sure pdf.js is the default handler.
+ is(
+ handlerInfo.alwaysAskBeforeHandling,
+ false,
+ "pdf handler defaults to always-ask is false"
+ );
+ is(
+ handlerInfo.preferredAction,
+ Ci.nsIHandlerInfo.handleInternally,
+ "pdf handler defaults to internal"
+ );
+
+ info("Pref action: " + handlerInfo.preferredAction);
+
+ await BrowserTestUtils.withNewTab(
+ { gBrowser, url: "about:blank" },
+ async function (browser) {
+ await SpecialPowers.pushPrefEnv({
+ set: [["pdfjs.annotationEditorMode", 0]],
+ });
+
+ Services.fog.testResetFOG();
+
+ // check that PDF is opened with internal viewer
+ await waitForPdfJSAllLayers(browser, TESTROOT + "file_pdfjs_test.pdf", [
+ [
+ "annotationEditorLayer",
+ "annotationLayer",
+ "textLayer",
+ "canvasWrapper",
+ ],
+ ["annotationEditorLayer", "textLayer", "canvasWrapper"],
+ ]);
+
+ let spanBox = await getSpanBox(browser, "and found references");
+
+ await Services.fog.testFlushAllChildren();
+ Assert.equal(Glean.pdfjs.editing.freetext.testGetValue() || 0, 0);
+
+ await enableEditor(browser, "FreeText");
+ await addFreeText(browser, "hello", spanBox);
+
+ await BrowserTestUtils.waitForCondition(
+ async () => (await countElements(browser, ".freeTextEditor")) !== 0
+ );
+ Assert.equal(await countElements(browser, ".freeTextEditor"), 2);
+
+ await Services.fog.testFlushAllChildren();
+
+ Assert.equal(Glean.pdfjs.editing.freetext.testGetValue(), 2);
+
+ spanBox = await getSpanBox(browser, "forums and ask questions");
+ await addFreeText(browser, "world", spanBox);
+
+ await BrowserTestUtils.waitForCondition(
+ async () => (await countElements(browser, ".freeTextEditor")) !== 1
+ );
+ Assert.equal(await countElements(browser, ".freeTextEditor"), 3);
+
+ await Services.fog.testFlushAllChildren();
+
+ Assert.equal(Glean.pdfjs.editing.freetext.testGetValue(), 3);
+
+ Assert.equal(Glean.pdfjs.editing.print.testGetValue() || 0, 0);
+ document.getElementById("cmd_print").doCommand();
+ await BrowserTestUtils.waitForCondition(() => {
+ let preview = document.querySelector(".printPreviewBrowser");
+ return preview && BrowserTestUtils.isVisible(preview);
+ });
+ EventUtils.synthesizeKey("KEY_Escape");
+
+ await Services.fog.testFlushAllChildren();
+
+ Assert.equal(Glean.pdfjs.editing.print.testGetValue(), 1);
+
+ await SpecialPowers.spawn(browser, [], async function () {
+ var viewer = content.wrappedJSObject.PDFViewerApplication;
+ await viewer.close();
+ });
+ }
+ );
+});
diff --git a/toolkit/components/pdfjs/test/browser_pdfjs_fill_login.js b/toolkit/components/pdfjs/test/browser_pdfjs_fill_login.js
new file mode 100644
index 0000000000..b31b9b607c
--- /dev/null
+++ b/toolkit/components/pdfjs/test/browser_pdfjs_fill_login.js
@@ -0,0 +1,108 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+const RELATIVE_DIR = "toolkit/components/pdfjs/test/";
+const TESTROOT = "http://example.com/browser/" + RELATIVE_DIR;
+
+// This is a modified version from browser_contextmenuFillLogins.js.
+async function openContextMenuForSelector(browser, selector) {
+ const doc = browser.ownerDocument;
+ const CONTEXT_MENU = doc.getElementById("contentAreaContextMenu");
+
+ let contextMenuShownPromise = BrowserTestUtils.waitForEvent(
+ CONTEXT_MENU,
+ "popupshown"
+ );
+
+ let inputCoords = await SpecialPowers.spawn(
+ browser,
+ [selector],
+ async selector => {
+ let input = content.document.querySelector(selector);
+ input.focus();
+ let inputRect = input.getBoundingClientRect();
+
+ // listen for the contextmenu event so we can assert on receiving it
+ // and examine the target
+ content.contextmenuPromise = new Promise(resolve => {
+ content.document.body.addEventListener(
+ "contextmenu",
+ event => {
+ info(
+ `Received event on target: ${event.target.nodeName}, type: ${event.target.type}`
+ );
+ content.console.log("got contextmenu event: ", event);
+ resolve(event);
+ },
+ { once: true }
+ );
+ });
+
+ let coords = {
+ x: inputRect.x + inputRect.width / 2,
+ y: inputRect.y + inputRect.height / 2,
+ };
+ return coords;
+ }
+ );
+
+ // add the offsets of the <browser> in the chrome window
+ let browserOffsets = browser.getBoundingClientRect();
+ let offsetX = browserOffsets.x + inputCoords.x;
+ let offsetY = browserOffsets.y + inputCoords.y;
+
+ // Synthesize a right mouse click over the input element, we have to trigger
+ // both events because formfill code relies on this event happening before the contextmenu
+ // (which it does for real user input) in order to not show the password autocomplete.
+ let eventDetails = { type: "mousedown", button: 2 };
+ await EventUtils.synthesizeMouseAtPoint(offsetX, offsetY, eventDetails);
+
+ // Synthesize a contextmenu event to actually open the context menu.
+ eventDetails = { type: "contextmenu", button: 2 };
+ await EventUtils.synthesizeMouseAtPoint(offsetX, offsetY, eventDetails);
+
+ await SpecialPowers.spawn(browser, [], async () => {
+ await content.contextmenuPromise;
+ });
+
+ info("waiting for contextMenuShownPromise");
+
+ await contextMenuShownPromise;
+ return CONTEXT_MENU;
+}
+
+/**
+ * Ensure the fill login context menu is not shown for PDF.js forms.
+ */
+add_task(async function test_filllogin() {
+ await SpecialPowers.pushPrefEnv({
+ set: [["pdfjs.renderInteractiveForms", true]],
+ });
+
+ await BrowserTestUtils.withNewTab(
+ { gBrowser, url: "about:blank" },
+ async function (browser) {
+ await waitForPdfJSAnnotationLayer(
+ browser,
+ TESTROOT + "file_pdfjs_form.pdf"
+ );
+
+ let contextMenu = await openContextMenuForSelector(
+ browser,
+ "#viewerContainer input"
+ );
+ let fillItem = contextMenu.querySelector("#fill-login");
+ ok(fillItem, "fill menu item exists");
+ ok(fillItem && EventUtils.isHidden(fillItem), "fill menu item is hidden");
+
+ let promiseHidden = BrowserTestUtils.waitForEvent(
+ contextMenu,
+ "popuphidden"
+ );
+ info("Calling hidePopup on contextMenu");
+ contextMenu.hidePopup();
+ info("waiting for promiseHidden");
+ await promiseHidden;
+ }
+ );
+});
diff --git a/toolkit/components/pdfjs/test/browser_pdfjs_filters.js b/toolkit/components/pdfjs/test/browser_pdfjs_filters.js
new file mode 100644
index 0000000000..87d1104a84
--- /dev/null
+++ b/toolkit/components/pdfjs/test/browser_pdfjs_filters.js
@@ -0,0 +1,81 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+const RELATIVE_DIR = "toolkit/components/pdfjs/test/";
+const TESTROOT = "https://example.com/browser/" + RELATIVE_DIR;
+
+/**
+ * Get the number of red pixels in the canvas.
+ * @param {Object} browser
+ * @returns {Object}
+ */
+async function getRedPixels(browser) {
+ return SpecialPowers.spawn(browser, [], async function () {
+ const { document } = content;
+ const canvas = document.querySelector("canvas");
+
+ Assert.ok(!!canvas, "We must have a canvas");
+
+ const data = canvas
+ .getContext("2d")
+ .getImageData(0, 0, canvas.width, canvas.height).data;
+
+ let redPixels = 0;
+ let total = 0;
+
+ for (let i = 0, ii = data.length; i < ii; i += 4) {
+ const R = data[i];
+ const G = data[i + 1];
+ const B = data[i + 2];
+
+ if (R > 128 && R > 4 * G && R > 4 * B) {
+ redPixels += 1;
+ }
+ total += 1;
+ }
+
+ return [redPixels, total];
+ });
+}
+
+/**
+ * Test that the pdf has the correct color thanks to the SVG filters.
+ */
+add_task(async function test() {
+ let mimeService = Cc["@mozilla.org/mime;1"].getService(Ci.nsIMIMEService);
+ let handlerInfo = mimeService.getFromTypeAndExtension(
+ "application/pdf",
+ "pdf"
+ );
+
+ // Make sure pdf.js is the default handler.
+ is(
+ handlerInfo.alwaysAskBeforeHandling,
+ false,
+ "pdf handler defaults to always-ask is false"
+ );
+ is(
+ handlerInfo.preferredAction,
+ Ci.nsIHandlerInfo.handleInternally,
+ "pdf handler defaults to internal"
+ );
+
+ info("Pref action: " + handlerInfo.preferredAction);
+
+ await BrowserTestUtils.withNewTab(
+ { gBrowser, url: "about:blank" },
+ async function (browser) {
+ // check that PDF is opened with internal viewer
+ await waitForPdfJSCanvas(
+ browser,
+ `${TESTROOT}file_pdfjs_transfer_map.pdf#zoom=100`
+ );
+
+ const [redPixels, total] = await getRedPixels(browser);
+ Assert.ok(
+ redPixels / total >= 0.1,
+ `Not enough red pixels: only ${redPixels} / ${total} red pixels!`
+ );
+ }
+ );
+});
diff --git a/toolkit/components/pdfjs/test/browser_pdfjs_find.js b/toolkit/components/pdfjs/test/browser_pdfjs_find.js
new file mode 100644
index 0000000000..24a3a50967
--- /dev/null
+++ b/toolkit/components/pdfjs/test/browser_pdfjs_find.js
@@ -0,0 +1,137 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+const TESTROOT = getRootDirectory(gTestPath).replace(
+ "chrome://mochitests/content/",
+ "http://mochi.test:8888/"
+);
+
+// Get a ref to the pdfs we want to open.
+const OS_PDF_URL = TESTROOT + "file_pdfjs_object_stream.pdf";
+const TEST_PDF_URL = TESTROOT + "file_pdfjs_test.pdf";
+
+add_task(async function test_find_octet_stream_pdf() {
+ await BrowserTestUtils.withNewTab(OS_PDF_URL, async browser => {
+ let findEls = ["cmd_find", "cmd_findAgain", "cmd_findPrevious"].map(id =>
+ document.getElementById(id)
+ );
+ for (let el of findEls) {
+ ok(!el.hasAttribute("disabled"), `${el.id} should be enabled`);
+ }
+ });
+});
+
+// This code is roughly based on `promiseFindFinished` from
+// `toolkit/content/tests/browser/head.js`.
+function waitForFinderResult(findbar) {
+ return new Promise(resolve => {
+ let resultListener = {
+ onFindResult(data) {
+ findbar.browser.finder.removeResultListener(resultListener);
+ resolve(data);
+ },
+ onCurrentSelection() {},
+ onMatchesCountResult() {},
+ onHighlightFinished() {},
+ };
+ findbar.browser.finder.addResultListener(resultListener);
+ });
+}
+
+function waitForPdfjsResult(findbar) {
+ // FIXME: This is a pretty sketchy way to intercept the results from pdfjs...
+ return new Promise(resolve => {
+ let oldUpdateControlState = findbar.updateControlState;
+ function updateControlState(result, findPrevious) {
+ if (result !== Ci.nsITypeAheadFind.FIND_PENDING) {
+ resolve({ result, findPrevious });
+ if (this.updateControlState === updateControlState) {
+ this.updateControlState = oldUpdateControlState;
+ }
+ }
+ return oldUpdateControlState.call(this, result, findPrevious);
+ }
+ findbar.updateControlState = updateControlState;
+ });
+}
+
+// This code is roughly based on `promiseFindFinished` from
+// `toolkit/content/tests/browser/head.js`.
+async function doFind(findbar, searchText, waitFunc) {
+ info(`performing a find for ${searchText}`);
+ findbar.startFind(findbar.FIND_NORMAL);
+ let highlightElement = findbar.getElement("highlight");
+ if (highlightElement.checked) {
+ highlightElement.click();
+ }
+ await new Promise(resolve => executeSoon(resolve));
+ findbar._findField.value = searchText;
+ let promise = waitFunc(findbar);
+ findbar._find();
+ return promise;
+}
+
+add_task(async function test_findbar_in_pdf() {
+ let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, TEST_PDF_URL);
+ let findbar = await gBrowser.getFindBar(tab);
+ let findResult = await doFind(findbar, "Mozilla", waitForPdfjsResult);
+ is(
+ findResult.result,
+ Ci.nsITypeAheadFind.FIND_FOUND,
+ "The Mozilla string was found in the PDF document"
+ );
+ BrowserTestUtils.removeTab(tab);
+});
+
+add_task(async function test_findbar_in_pdf_after_adopt() {
+ let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, TEST_PDF_URL);
+ let newWindow = await BrowserTestUtils.openNewBrowserWindow();
+
+ info("adopting tab into new window");
+ let newTab = newWindow.gBrowser.adoptTab(tab);
+
+ let findbar = await newWindow.gBrowser.getFindBar(newTab);
+ let findResult = await doFind(findbar, "Mozilla", waitForPdfjsResult);
+ is(
+ findResult.result,
+ Ci.nsITypeAheadFind.FIND_FOUND,
+ "The Mozilla string was found in the PDF document"
+ );
+ await BrowserTestUtils.closeWindow(newWindow);
+});
+
+// Make sure that performing a find in the browser continues to work after
+// navigating to another page (i.e. Pdfjs disables its pdfjs interception
+// listeners).
+add_task(async function test_findbar_after_navigate() {
+ await BrowserTestUtils.withNewTab(TEST_PDF_URL, async browser => {
+ let tab = gBrowser.getTabForBrowser(browser);
+
+ ok(
+ !gBrowser.isFindBarInitialized(tab),
+ "Findbar shouldn't be initialized yet"
+ );
+
+ info("navigating to a webpage");
+ BrowserTestUtils.startLoadingURIString(
+ browser,
+ "http://mochi.test:8888/document-builder.sjs?html=<h1>hello, world!</h1>"
+ );
+ await BrowserTestUtils.browserLoaded(browser);
+
+ ok(
+ !gBrowser.isFindBarInitialized(tab),
+ "Findbar still shouldn't be initialized after navigation"
+ );
+
+ let findbar = await gBrowser.getFindBar(tab);
+ let findResult = await doFind(findbar, "hello", waitForFinderResult);
+ is(
+ findResult.result,
+ Ci.nsITypeAheadFind.FIND_FOUND,
+ "The hello string was found in the HTML document"
+ );
+ });
+});
diff --git a/toolkit/components/pdfjs/test/browser_pdfjs_force_opening_files.js b/toolkit/components/pdfjs/test/browser_pdfjs_force_opening_files.js
new file mode 100644
index 0000000000..0490a6eec3
--- /dev/null
+++ b/toolkit/components/pdfjs/test/browser_pdfjs_force_opening_files.js
@@ -0,0 +1,89 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+add_task(async function test_file_opening() {
+ // Get a ref to the pdf we want to open.
+ let dirFileObj = getChromeDir(getResolvedURI(gTestPath));
+ dirFileObj.append("file_pdfjs_test.pdf");
+
+ // Change the defaults.
+ var oldAction = changeMimeHandler(Ci.nsIHandlerInfo.useSystemDefault, true);
+
+ // Test: "Open with" dialog should not come up, despite pdf.js not being
+ // the default - because files from disk should always use pdfjs, unless
+ // it is forcibly disabled.
+ let openedWindow = false;
+ let windowOpenedPromise = new Promise((resolve, reject) => {
+ addWindowListener(
+ "chrome://mozapps/content/downloads/unknownContentType.xhtml",
+ () => {
+ openedWindow = true;
+ resolve();
+ }
+ );
+ });
+
+ // Open the tab with a system principal:
+ var tab = BrowserTestUtils.addTab(gBrowser, dirFileObj.path);
+
+ let pdfjsLoadedPromise = TestUtils.waitForCondition(() => {
+ let { contentPrincipal } = tab.linkedBrowser;
+ return (contentPrincipal?.URI?.spec || "").endsWith("viewer.html");
+ });
+ await Promise.race([pdfjsLoadedPromise, windowOpenedPromise]);
+ ok(!openedWindow, "Shouldn't open an unknownContentType window!");
+
+ BrowserTestUtils.removeTab(tab);
+
+ // Now try opening it from the file directory:
+ tab = await BrowserTestUtils.openNewForegroundTab(
+ gBrowser,
+ dirFileObj.parent.path
+ );
+ pdfjsLoadedPromise = BrowserTestUtils.browserLoaded(
+ tab.linkedBrowser,
+ false,
+ url => url.endsWith("test.pdf")
+ );
+ await SpecialPowers.spawn(tab.linkedBrowser, [], () => {
+ content.document.querySelector("a[href$='test.pdf']").click();
+ });
+ await Promise.race([pdfjsLoadedPromise, windowOpenedPromise]);
+ ok(
+ !openedWindow,
+ "Shouldn't open an unknownContentType window for PDFs from file: links!"
+ );
+
+ registerCleanupFunction(function () {
+ if (listenerCleanup) {
+ listenerCleanup();
+ }
+ changeMimeHandler(oldAction[0], oldAction[1]);
+ gBrowser.removeTab(tab);
+ });
+});
+
+let listenerCleanup;
+function addWindowListener(aURL, aCallback) {
+ let listener = {
+ onOpenWindow(aXULWindow) {
+ info("window opened, waiting for focus");
+ listenerCleanup();
+ listenerCleanup = null;
+
+ var domwindow = aXULWindow.docShell.domWindow;
+ waitForFocus(function () {
+ is(
+ domwindow.document.location.href,
+ aURL,
+ "should have seen the right window open"
+ );
+ domwindow.close();
+ aCallback();
+ }, domwindow);
+ },
+ onCloseWindow(aXULWindow) {},
+ };
+ Services.wm.addListener(listener);
+ listenerCleanup = () => Services.wm.removeListener(listener);
+}
diff --git a/toolkit/components/pdfjs/test/browser_pdfjs_form.js b/toolkit/components/pdfjs/test/browser_pdfjs_form.js
new file mode 100644
index 0000000000..380c812b8b
--- /dev/null
+++ b/toolkit/components/pdfjs/test/browser_pdfjs_form.js
@@ -0,0 +1,85 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+const RELATIVE_DIR = "toolkit/components/pdfjs/test/";
+const TESTROOT = "http://example.com/browser/" + RELATIVE_DIR;
+
+async function checkFormState(formsEnabled) {
+ ok(
+ content.document.querySelector("div#viewer"),
+ "document content has viewer UI"
+ );
+
+ let formInput = content.document.querySelector("#viewerContainer input");
+
+ if (formsEnabled) {
+ ok(formInput, "Form input available");
+ } else {
+ ok(!formInput, "Form input not available");
+ }
+ let viewer = content.wrappedJSObject.PDFViewerApplication;
+ await viewer.close();
+}
+
+add_task(async function test_defaults() {
+ // Ensure the default preference is set to the expected value.
+ let defaultBranch = Services.prefs.getDefaultBranch("pdfjs.");
+ let prefType = defaultBranch.getPrefType("annotationMode");
+ let renderForms = Services.prefs.getIntPref("pdfjs.annotationMode") === 2;
+
+ is(
+ prefType,
+ Ci.nsIPrefBranch.PREF_INT,
+ "The form pref is defined by default"
+ );
+
+ ok(renderForms, "Forms are enabled");
+
+ // Test that the forms state matches the pref.
+ await BrowserTestUtils.withNewTab(
+ { gBrowser, url: "about:blank" },
+ async function (browser) {
+ await waitForPdfJSAnnotationLayer(
+ browser,
+ TESTROOT + "file_pdfjs_form.pdf"
+ );
+
+ await SpecialPowers.spawn(browser, [true], checkFormState);
+ }
+ );
+});
+
+// Test disabling forms with pref.
+add_task(async function test_disabling() {
+ await BrowserTestUtils.withNewTab(
+ { gBrowser, url: "about:blank" },
+ async function (browser) {
+ // First, make sure they are enabled.
+ await SpecialPowers.pushPrefEnv({
+ set: [["pdfjs.annotationMode", 2]],
+ });
+ await waitForPdfJSAnnotationLayer(
+ browser,
+ TESTROOT + "file_pdfjs_form.pdf"
+ );
+ await SpecialPowers.spawn(
+ browser,
+ [true /* formsEnabled */],
+ checkFormState
+ );
+ // Now disable the forms.
+ await SpecialPowers.pushPrefEnv({
+ set: [["pdfjs.annotationMode", 1]],
+ });
+ await waitForPdfJSAnnotationLayer(
+ browser,
+ TESTROOT + "file_pdfjs_form.pdf"
+ );
+ await SpecialPowers.spawn(
+ browser,
+ [false /* formsEnabled */],
+ checkFormState
+ );
+ }
+ );
+});
diff --git a/toolkit/components/pdfjs/test/browser_pdfjs_fullscreen.js b/toolkit/components/pdfjs/test/browser_pdfjs_fullscreen.js
new file mode 100644
index 0000000000..d53e4cfa74
--- /dev/null
+++ b/toolkit/components/pdfjs/test/browser_pdfjs_fullscreen.js
@@ -0,0 +1,84 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+const RELATIVE_DIR = "toolkit/components/pdfjs/test/";
+const TESTROOT = "https://example.com/browser/" + RELATIVE_DIR;
+
+function waitForFullScreenState(browser, state) {
+ return new Promise(resolve => {
+ let eventReceived = false;
+
+ let observe = (subject, topic, data) => {
+ if (!eventReceived) {
+ return;
+ }
+ Services.obs.removeObserver(observe, "fullscreen-painted");
+ resolve();
+ };
+ Services.obs.addObserver(observe, "fullscreen-painted");
+
+ browser.ownerGlobal.addEventListener(
+ `MozDOMFullscreen:${state ? "Entered" : "Exited"}`,
+ () => {
+ eventReceived = true;
+ },
+ { once: true }
+ );
+ });
+}
+
+/**
+ * Test that we can enter in presentation mode in using the keyboard shortcut
+ * without having to interact with the pdf.
+ */
+add_task(async function test() {
+ let mimeService = Cc["@mozilla.org/mime;1"].getService(Ci.nsIMIMEService);
+ let handlerInfo = mimeService.getFromTypeAndExtension(
+ "application/pdf",
+ "pdf"
+ );
+
+ // Make sure pdf.js is the default handler.
+ is(
+ handlerInfo.alwaysAskBeforeHandling,
+ false,
+ "pdf handler defaults to always-ask is false"
+ );
+ is(
+ handlerInfo.preferredAction,
+ Ci.nsIHandlerInfo.handleInternally,
+ "pdf handler defaults to internal"
+ );
+
+ info("Pref action: " + handlerInfo.preferredAction);
+
+ await BrowserTestUtils.withNewTab(
+ { gBrowser, url: "about:blank" },
+ async function (browser) {
+ // check that PDF is opened with internal viewer
+ await waitForPdfJSCanvas(browser, `${TESTROOT}file_pdfjs_test.pdf`);
+
+ const fullscreenPromise = waitForFullScreenState(browser, true);
+
+ await SpecialPowers.spawn(browser, [], async function () {
+ const { ContentTaskUtils } = ChromeUtils.importESModule(
+ "resource://testing-common/ContentTaskUtils.sys.mjs"
+ );
+ const EventUtils = ContentTaskUtils.getEventUtils(content);
+ await EventUtils.synthesizeKey(
+ "p",
+ { ctrlKey: true, altKey: true },
+ content
+ );
+ });
+
+ await fullscreenPromise;
+ ok(true, "Should be in fullscreen");
+
+ await SpecialPowers.spawn(browser, [], async function () {
+ const viewer = content.wrappedJSObject.PDFViewerApplication;
+ await viewer.close();
+ });
+ }
+ );
+});
diff --git a/toolkit/components/pdfjs/test/browser_pdfjs_hcm.js b/toolkit/components/pdfjs/test/browser_pdfjs_hcm.js
new file mode 100644
index 0000000000..cc5f098f1e
--- /dev/null
+++ b/toolkit/components/pdfjs/test/browser_pdfjs_hcm.js
@@ -0,0 +1,104 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+const RELATIVE_DIR = "toolkit/components/pdfjs/test/";
+const TESTROOT = "http://example.com/browser/" + RELATIVE_DIR;
+
+/**
+ * Get the first and last pixels on the drawn canvas.
+ * @param {Object} browser
+ * @returns {Object}
+ */
+async function getFirstLastPixels(browser) {
+ return SpecialPowers.spawn(browser, [], async function () {
+ const { document } = content;
+ const canvas = document.querySelector("canvas");
+
+ Assert.ok(!!canvas, "We must have a canvas");
+
+ const data = Array.from(
+ canvas.getContext("2d").getImageData(0, 0, canvas.width, canvas.height)
+ .data
+ );
+
+ return {
+ first: data.slice(0, 3),
+ last: data.slice(-4, -1),
+ };
+ });
+}
+
+/**
+ * Test that the pdf has the correct color depending on the high contrast mode.
+ */
+add_task(async function test() {
+ let mimeService = Cc["@mozilla.org/mime;1"].getService(Ci.nsIMIMEService);
+ let handlerInfo = mimeService.getFromTypeAndExtension(
+ "application/pdf",
+ "pdf"
+ );
+
+ // Make sure pdf.js is the default handler.
+ is(
+ handlerInfo.alwaysAskBeforeHandling,
+ false,
+ "pdf handler defaults to always-ask is false"
+ );
+ is(
+ handlerInfo.preferredAction,
+ Ci.nsIHandlerInfo.handleInternally,
+ "pdf handler defaults to internal"
+ );
+
+ info("Pref action: " + handlerInfo.preferredAction);
+
+ await SpecialPowers.pushPrefEnv({
+ set: [
+ ["browser.display.document_color_use", 0],
+ ["browser.display.background_color", "#ff0000"],
+ ["browser.display.foreground_color", "#00ff00"],
+ ["browser.display.use_system_colors", false],
+ ],
+ });
+
+ await BrowserTestUtils.withNewTab(
+ { gBrowser, url: "about:blank" },
+ async function (browser) {
+ // check that PDF is opened with internal viewer
+ await waitForPdfJSCanvas(
+ browser,
+ `${TESTROOT}file_pdfjs_hcm.pdf#zoom=800`
+ );
+
+ const { first, last } = await getFirstLastPixels(browser);
+ // The first pixel must be black and not green.
+ Assert.deepEqual(first, [0, 0, 0]);
+
+ // The last pixel must be white and not red.
+ Assert.deepEqual(last, [255, 255, 255]);
+ }
+ );
+
+ // Enable HCM.
+ await SpecialPowers.pushPrefEnv({
+ set: [["ui.useAccessibilityTheme", 1]],
+ });
+
+ await BrowserTestUtils.withNewTab(
+ { gBrowser, url: "about:blank" },
+ async function (browser) {
+ // check that PDF is opened with internal viewer
+ await waitForPdfJSCanvas(
+ browser,
+ `${TESTROOT}file_pdfjs_hcm.pdf#zoom=800`
+ );
+
+ const { first, last } = await getFirstLastPixels(browser);
+ // The first pixel must be green.
+ Assert.deepEqual(first, [0, 255, 0]);
+
+ // The last pixel must be red.
+ Assert.deepEqual(last, [255, 0, 0]);
+ }
+ );
+});
diff --git a/toolkit/components/pdfjs/test/browser_pdfjs_highlight_telemetry.js b/toolkit/components/pdfjs/test/browser_pdfjs_highlight_telemetry.js
new file mode 100644
index 0000000000..83b72245d8
--- /dev/null
+++ b/toolkit/components/pdfjs/test/browser_pdfjs_highlight_telemetry.js
@@ -0,0 +1,234 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+const RELATIVE_DIR = "toolkit/components/pdfjs/test/";
+const TESTROOT = "https://example.com/browser/" + RELATIVE_DIR;
+
+// Test telemetry.
+add_task(async function test() {
+ let mimeService = Cc["@mozilla.org/mime;1"].getService(Ci.nsIMIMEService);
+ let handlerInfo = mimeService.getFromTypeAndExtension(
+ "application/pdf",
+ "pdf"
+ );
+
+ // Make sure pdf.js is the default handler.
+ is(
+ handlerInfo.alwaysAskBeforeHandling,
+ false,
+ "pdf handler defaults to always-ask is false"
+ );
+ is(
+ handlerInfo.preferredAction,
+ Ci.nsIHandlerInfo.handleInternally,
+ "pdf handler defaults to internal"
+ );
+
+ info("Pref action: " + handlerInfo.preferredAction);
+
+ await BrowserTestUtils.withNewTab(
+ { gBrowser, url: "about:blank" },
+ async function (browser) {
+ await SpecialPowers.pushPrefEnv({
+ set: [
+ ["pdfjs.annotationEditorMode", 0],
+ ["pdfjs.enableHighlight", true],
+ ],
+ });
+
+ Services.fog.testResetFOG();
+
+ // check that PDF is opened with internal viewer
+ await waitForPdfJSAllLayers(browser, TESTROOT + "file_pdfjs_test.pdf", [
+ [
+ "annotationEditorLayer",
+ "annotationLayer",
+ "textLayer",
+ "canvasWrapper",
+ ],
+ ["annotationEditorLayer", "textLayer", "canvasWrapper"],
+ ]);
+
+ await Services.fog.testFlushAllChildren();
+ Assert.equal(
+ (Glean.pdfjsEditingHighlight.kind.freeHighlight.testGetValue() || 0) +
+ (Glean.pdfjsEditingHighlight.kind.highlight.testGetValue() || 0),
+ 0,
+ "Should have no highlight"
+ );
+
+ await enableEditor(browser, "Highlight");
+ const strs = ["In production", "buildbot automation"];
+ for (let i = 0; i < strs.length; i++) {
+ const str = strs[i];
+ const N = i + 1;
+ const spanBox = await getSpanBox(browser, str);
+ await clickAt(
+ browser,
+ spanBox.x + 0.75 * spanBox.width,
+ spanBox.y + 0.5 * spanBox.height,
+ 2
+ );
+ await waitForEditors(browser, ".highlightEditor", N);
+ await Services.fog.testFlushAllChildren();
+
+ Assert.equal(
+ Glean.pdfjsEditingHighlight.kind.highlight.testGetValue(),
+ N,
+ `Should have ${N} highlights`
+ );
+ Assert.equal(
+ Glean.pdfjsEditingHighlight.color.yellow.testGetValue(),
+ N,
+ `Should have ${N} yellow highlights`
+ );
+ Assert.equal(
+ Glean.pdfjsEditingHighlight.method.main_toolbar.testGetValue(),
+ N,
+ `Should have ${N} highlights created from the toolbar`
+ );
+
+ await EventUtils.synthesizeKey("KEY_Escape");
+ await waitForSelector(browser, ".highlightEditor:not(.selectedEditor)");
+
+ document.getElementById("cmd_print").doCommand();
+ await BrowserTestUtils.waitForCondition(() => {
+ let preview = document.querySelector(".printPreviewBrowser");
+ return preview && BrowserTestUtils.isVisible(preview);
+ });
+ await EventUtils.synthesizeKey("KEY_Escape");
+
+ await Services.fog.testFlushAllChildren();
+
+ Assert.equal(Glean.pdfjs.editing.print.testGetValue(), N);
+ Assert.equal(Glean.pdfjsEditingHighlight.print.testGetValue(), N);
+ Assert.equal(
+ Glean.pdfjsEditingHighlight.numberOfColors.one.testGetValue(),
+ N
+ );
+ }
+
+ await click(
+ browser,
+ "#highlightParamsToolbarContainer button[title='Green']"
+ );
+ const spanBox = await getSpanBox(browser, "Mozilla automated testing");
+ await BrowserTestUtils.synthesizeMouseAtPoint(
+ spanBox.x - 10,
+ spanBox.y + spanBox.height / 2,
+ {
+ type: "mousedown",
+ button: 0,
+ },
+ browser
+ );
+ await BrowserTestUtils.synthesizeMouseAtPoint(
+ spanBox.x + spanBox.width,
+ spanBox.y + spanBox.height / 2,
+ {
+ type: "mousemove",
+ button: 0,
+ },
+ browser
+ );
+ await BrowserTestUtils.synthesizeMouseAtPoint(
+ spanBox.x + spanBox.width,
+ spanBox.y + spanBox.height / 2,
+ {
+ type: "mouseup",
+ button: 0,
+ },
+ browser
+ );
+ await waitForEditors(browser, ".highlightEditor", 3);
+
+ await Services.fog.testFlushAllChildren();
+ Assert.equal(Glean.pdfjsEditingHighlight.color.green.testGetValue(), 1);
+ Assert.equal(
+ Glean.pdfjsEditingHighlight.kind.free_highlight.testGetValue(),
+ 1
+ );
+
+ let telemetryPromise = waitForTelemetry(browser);
+ await focus(browser, "#editorFreeHighlightThickness");
+ await EventUtils.synthesizeKey("KEY_ArrowRight");
+
+ await telemetryPromise;
+
+ await Services.fog.testFlushAllChildren();
+ Assert.equal(
+ Glean.pdfjsEditingHighlight.thickness.testGetValue().values[12],
+ 1
+ );
+ Assert.equal(
+ Glean.pdfjsEditingHighlight.thickness.testGetValue().values[13],
+ 1
+ );
+ Assert.equal(
+ Glean.pdfjsEditingHighlight.thicknessChanged.testGetValue(),
+ 1
+ );
+
+ document.getElementById("cmd_print").doCommand();
+ await BrowserTestUtils.waitForCondition(() => {
+ let preview = document.querySelector(".printPreviewBrowser");
+ return preview && BrowserTestUtils.isVisible(preview);
+ });
+ await EventUtils.synthesizeKey("KEY_Escape");
+
+ await Services.fog.testFlushAllChildren();
+
+ Assert.equal(Glean.pdfjs.editing.print.testGetValue(), 3);
+ Assert.equal(Glean.pdfjsEditingHighlight.print.testGetValue(), 3);
+ Assert.equal(
+ Glean.pdfjsEditingHighlight.numberOfColors.one.testGetValue(),
+ 2
+ );
+ Assert.equal(
+ Glean.pdfjsEditingHighlight.numberOfColors.two.testGetValue(),
+ 1
+ );
+
+ await click(browser, ".highlightEditor.free button.colorPicker");
+ telemetryPromise = waitForTelemetry(browser);
+ await click(
+ browser,
+ ".highlightEditor.free button.colorPicker button[title='Red']"
+ );
+ await telemetryPromise;
+
+ await Services.fog.testFlushAllChildren();
+ Assert.equal(Glean.pdfjsEditingHighlight.colorChanged.testGetValue(), 1);
+
+ document.getElementById("cmd_print").doCommand();
+ await BrowserTestUtils.waitForCondition(() => {
+ let preview = document.querySelector(".printPreviewBrowser");
+ return preview && BrowserTestUtils.isVisible(preview);
+ });
+ await EventUtils.synthesizeKey("KEY_Escape");
+
+ await Services.fog.testFlushAllChildren();
+ Assert.equal(
+ Glean.pdfjsEditingHighlight.numberOfColors.one.testGetValue(),
+ 2
+ );
+ Assert.equal(
+ Glean.pdfjsEditingHighlight.numberOfColors.two.testGetValue(),
+ 2
+ );
+
+ telemetryPromise = waitForTelemetry(browser);
+ await EventUtils.synthesizeKey("KEY_Delete");
+ await telemetryPromise;
+
+ await Services.fog.testFlushAllChildren();
+ Assert.equal(Glean.pdfjsEditingHighlight.deleted.testGetValue(), 1);
+
+ await SpecialPowers.spawn(browser, [], async function () {
+ const viewer = content.wrappedJSObject.PDFViewerApplication;
+ viewer.pdfDocument.annotationStorage.resetModified();
+ await viewer.close();
+ });
+ }
+ );
+});
diff --git a/toolkit/components/pdfjs/test/browser_pdfjs_js.js b/toolkit/components/pdfjs/test/browser_pdfjs_js.js
new file mode 100644
index 0000000000..67909623cd
--- /dev/null
+++ b/toolkit/components/pdfjs/test/browser_pdfjs_js.js
@@ -0,0 +1,49 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+const RELATIVE_DIR = "toolkit/components/pdfjs/test/";
+const TESTROOT = "http://example.com/browser/" + RELATIVE_DIR;
+
+// Test js in pdf file.
+add_task(async function test_js_sandbox() {
+ await BrowserTestUtils.withNewTab(
+ { gBrowser, url: "about:blank" },
+ async function (browser) {
+ await SpecialPowers.pushPrefEnv({
+ set: [["pdfjs.enableScripting", true]],
+ });
+
+ await Promise.all([
+ waitForPdfJSAnnotationLayer(browser, TESTROOT + "file_pdfjs_js.pdf"),
+ waitForPdfJSSandbox(browser),
+ ]);
+
+ await SpecialPowers.spawn(browser, [], async () => {
+ const { PdfSandbox } = ChromeUtils.importESModule(
+ "resource://pdf.js/PdfSandbox.sys.mjs"
+ );
+
+ let sandboxDestroyCount = 0;
+ const originalDestroy = PdfSandbox.prototype.destroy;
+ PdfSandbox.prototype.destroy = function () {
+ const obj = this.sandbox.eval("({})");
+ originalDestroy.apply(this, arguments);
+ sandboxDestroyCount++;
+ ok(Cu.isDeadWrapper(obj), "Sandbox must have been nuked");
+ };
+
+ const document = content.document;
+ const button = document.querySelector("[data-annotation-id='16R'] a");
+ button.dispatchEvent(new content.Event("click"));
+
+ const text = document.querySelector(`[data-element-id="15R"]`);
+
+ is(text.value, "test", "Text field must containt 'test' string");
+
+ content.addEventListener("unload", () => {
+ is(sandboxDestroyCount, 1, "Sandbox must have been destroyed");
+ });
+ });
+ }
+ );
+});
diff --git a/toolkit/components/pdfjs/test/browser_pdfjs_load_telemetry.js b/toolkit/components/pdfjs/test/browser_pdfjs_load_telemetry.js
new file mode 100644
index 0000000000..61a4dba290
--- /dev/null
+++ b/toolkit/components/pdfjs/test/browser_pdfjs_load_telemetry.js
@@ -0,0 +1,51 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+const RELATIVE_DIR = "toolkit/components/pdfjs/test/";
+const TESTROOT = "https://example.com/browser/" + RELATIVE_DIR;
+
+// Test telemetry.
+add_task(async function test() {
+ let mimeService = Cc["@mozilla.org/mime;1"].getService(Ci.nsIMIMEService);
+ let handlerInfo = mimeService.getFromTypeAndExtension(
+ "application/pdf",
+ "pdf"
+ );
+
+ // Make sure pdf.js is the default handler.
+ is(
+ handlerInfo.alwaysAskBeforeHandling,
+ false,
+ "pdf handler defaults to always-ask is false"
+ );
+ is(
+ handlerInfo.preferredAction,
+ Ci.nsIHandlerInfo.handleInternally,
+ "pdf handler defaults to internal"
+ );
+
+ info("Pref action: " + handlerInfo.preferredAction);
+
+ await BrowserTestUtils.withNewTab(
+ { gBrowser, url: "about:blank" },
+ async function (browser) {
+ Services.fog.testResetFOG();
+
+ await Services.fog.testFlushAllChildren();
+ Assert.equal(Glean.pdfjs.timeToView.testGetValue(), undefined);
+ Assert.equal(Glean.pdfjs.used.testGetValue() || 0, 0);
+
+ // check that PDF is opened with internal viewer
+ await waitForPdfJSCanvas(browser, TESTROOT + "file_pdfjs_test.pdf");
+
+ await Services.fog.testFlushAllChildren();
+ Assert.ok(Glean.pdfjs.timeToView.testGetValue().sum !== 0);
+ Assert.equal(Glean.pdfjs.used.testGetValue(), 1);
+
+ await SpecialPowers.spawn(browser, [], async function () {
+ var viewer = content.wrappedJSObject.PDFViewerApplication;
+ await viewer.close();
+ });
+ }
+ );
+});
diff --git a/toolkit/components/pdfjs/test/browser_pdfjs_main.js b/toolkit/components/pdfjs/test/browser_pdfjs_main.js
new file mode 100644
index 0000000000..c2f2122268
--- /dev/null
+++ b/toolkit/components/pdfjs/test/browser_pdfjs_main.js
@@ -0,0 +1,72 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+const RELATIVE_DIR = "toolkit/components/pdfjs/test/";
+const TESTROOT = "http://example.com/browser/" + RELATIVE_DIR;
+
+add_task(async function test() {
+ let mimeService = Cc["@mozilla.org/mime;1"].getService(Ci.nsIMIMEService);
+ let handlerInfo = mimeService.getFromTypeAndExtension(
+ "application/pdf",
+ "pdf"
+ );
+
+ // Make sure pdf.js is the default handler.
+ is(
+ handlerInfo.alwaysAskBeforeHandling,
+ false,
+ "pdf handler defaults to always-ask is false"
+ );
+ is(
+ handlerInfo.preferredAction,
+ Ci.nsIHandlerInfo.handleInternally,
+ "pdf handler defaults to internal"
+ );
+
+ info("Pref action: " + handlerInfo.preferredAction);
+
+ await BrowserTestUtils.withNewTab(
+ { gBrowser, url: "about:blank" },
+ async function (newTabBrowser) {
+ await waitForPdfJS(newTabBrowser, TESTROOT + "file_pdfjs_test.pdf");
+
+ await SpecialPowers.spawn(newTabBrowser, [], async function () {
+ // Overall sanity tests
+ Assert.ok(
+ content.document.querySelector("div#viewer"),
+ "document content has viewer UI"
+ );
+
+ // Sidebar: open
+ var sidebar = content.document.querySelector("button#sidebarToggle"),
+ outerContainer = content.document.querySelector("div#outerContainer");
+
+ sidebar.click();
+ Assert.ok(
+ outerContainer.classList.contains("sidebarOpen"),
+ "sidebar opens on click"
+ );
+
+ // Sidebar: close
+ sidebar.click();
+ Assert.ok(
+ !outerContainer.classList.contains("sidebarOpen"),
+ "sidebar closes on click"
+ );
+
+ // Verify that initial page is 1
+ var pgNumber = content.document.querySelector("input#pageNumber").value;
+ Assert.equal(parseInt(pgNumber, 10), 1, "initial page is 1");
+
+ // Bookmark button
+ var viewBookmark = content.document.querySelector("a#viewBookmark");
+ viewBookmark.click();
+
+ Assert.ok(!!viewBookmark.href.length, "viewBookmark button has href");
+
+ var viewer = content.wrappedJSObject.PDFViewerApplication;
+ await viewer.close();
+ });
+ }
+ );
+});
diff --git a/toolkit/components/pdfjs/test/browser_pdfjs_minimum_font_size.js b/toolkit/components/pdfjs/test/browser_pdfjs_minimum_font_size.js
new file mode 100644
index 0000000000..f85e0c3ec6
--- /dev/null
+++ b/toolkit/components/pdfjs/test/browser_pdfjs_minimum_font_size.js
@@ -0,0 +1,70 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+const RELATIVE_DIR = "toolkit/components/pdfjs/test/";
+const TESTROOT = "https://example.com/browser/" + RELATIVE_DIR;
+
+/**
+ * Test that the pdf doesn't use the minimum font size.
+ */
+add_task(async function test() {
+ let mimeService = Cc["@mozilla.org/mime;1"].getService(Ci.nsIMIMEService);
+ let handlerInfo = mimeService.getFromTypeAndExtension(
+ "application/pdf",
+ "pdf"
+ );
+
+ // Make sure pdf.js is the default handler.
+ is(
+ handlerInfo.alwaysAskBeforeHandling,
+ false,
+ "pdf handler defaults to always-ask is false"
+ );
+ is(
+ handlerInfo.preferredAction,
+ Ci.nsIHandlerInfo.handleInternally,
+ "pdf handler defaults to internal"
+ );
+
+ info("Pref action: " + handlerInfo.preferredAction);
+
+ await SpecialPowers.pushPrefEnv({
+ set: [["font.minimum-size.x-western", 56]],
+ });
+
+ await BrowserTestUtils.withNewTab(
+ { gBrowser, url: "about:blank" },
+ async function (browser) {
+ // check that PDF is opened with internal viewer
+ await waitForPdfJSAllLayers(
+ browser,
+ `${TESTROOT}file_pdfjs_test.pdf#zoom=10`,
+ []
+ );
+
+ await SpecialPowers.spawn(browser, [true], () => {
+ const pageNumberInput = content.document.querySelector("#pageNumber");
+ const { style } = pageNumberInput;
+ const baseHeight =
+ content.document.defaultView.getComputedStyle(pageNumberInput).height;
+
+ style.fontSize = "1px";
+ const height =
+ content.document.defaultView.getComputedStyle(pageNumberInput).height;
+
+ // Changing the font size should change the height of the input
+ // element. If the minimum font size is used, the height won't change.
+ Assert.notEqual(
+ baseHeight,
+ height,
+ "The pdf viewer musn't use the minimum font size."
+ );
+ });
+
+ await SpecialPowers.spawn(browser, [], async function () {
+ var viewer = content.wrappedJSObject.PDFViewerApplication;
+ await viewer.close();
+ });
+ }
+ );
+});
diff --git a/toolkit/components/pdfjs/test/browser_pdfjs_navigation.js b/toolkit/components/pdfjs/test/browser_pdfjs_navigation.js
new file mode 100644
index 0000000000..9851150e80
--- /dev/null
+++ b/toolkit/components/pdfjs/test/browser_pdfjs_navigation.js
@@ -0,0 +1,314 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+/* eslint-disable mozilla/no-arbitrary-setTimeout */
+
+requestLongerTimeout(2);
+
+const RELATIVE_DIR = "toolkit/components/pdfjs/test/";
+const TESTROOT = "http://example.com/browser/" + RELATIVE_DIR;
+
+const PDF_OUTLINE_ITEMS = 17;
+const TESTS = [
+ {
+ action: {
+ selector: "button#next",
+ event: "click",
+ },
+ expectedPage: 2,
+ message: "navigated to next page using NEXT button",
+ },
+ {
+ action: {
+ selector: "button#previous",
+ event: "click",
+ },
+ expectedPage: 1,
+ message: "navigated to previous page using PREV button",
+ },
+ {
+ action: {
+ selector: "button#next",
+ event: "click",
+ },
+ expectedPage: 2,
+ message: "navigated to next page using NEXT button",
+ },
+ {
+ action: {
+ selector: "input#pageNumber",
+ value: 1,
+ event: "change",
+ },
+ expectedPage: 1,
+ message: "navigated to first page using pagenumber",
+ },
+ {
+ action: {
+ selector: "#thumbnailView a:nth-child(4)",
+ event: "click",
+ },
+ expectedPage: 4,
+ message: "navigated to 4th page using thumbnail view",
+ },
+ {
+ action: {
+ selector: "#thumbnailView a:nth-child(2)",
+ event: "click",
+ },
+ expectedPage: 2,
+ message: "navigated to 2nd page using thumbnail view",
+ },
+ {
+ action: {
+ selector: "#viewer",
+ event: "keydown",
+ keyCode: 36,
+ },
+ expectedPage: 1,
+ message: "navigated to 1st page using 'home' key",
+ },
+ {
+ action: {
+ selector: "#viewer",
+ event: "keydown",
+ keyCode: 34,
+ },
+ expectedPage: 2,
+ message: "navigated to 2nd page using 'Page Down' key",
+ },
+ {
+ action: {
+ selector: "#viewer",
+ event: "keydown",
+ keyCode: 33,
+ },
+ expectedPage: 1,
+ message: "navigated to 1st page using 'Page Up' key",
+ },
+ {
+ action: {
+ selector: "#viewer",
+ event: "keydown",
+ keyCode: 39,
+ },
+ expectedPage: 2,
+ message: "navigated to 2nd page using 'right' key",
+ },
+ {
+ action: {
+ selector: "#viewer",
+ event: "keydown",
+ keyCode: 37,
+ },
+ expectedPage: 1,
+ message: "navigated to 1st page using 'left' key",
+ },
+ {
+ action: {
+ selector: "#viewer",
+ event: "keydown",
+ keyCode: 35,
+ },
+ expectedPage: 5,
+ message: "navigated to last page using 'home' key",
+ },
+ {
+ action: {
+ selector: "#outlineView .treeItem:nth-child(1) a",
+ event: "click",
+ },
+ expectedPage: 1,
+ message: "navigated to 1st page using outline view",
+ },
+ {
+ action: {
+ selector: "#outlineView .treeItem:nth-child(" + PDF_OUTLINE_ITEMS + ") a",
+ event: "click",
+ },
+ expectedPage: 4,
+ message: "navigated to 4th page using outline view",
+ },
+ {
+ action: {
+ selector: "input#pageNumber",
+ value: 5,
+ event: "change",
+ },
+ expectedPage: 5,
+ message: "navigated to 5th page using pagenumber",
+ },
+];
+
+add_task(async function test() {
+ let mimeService = Cc["@mozilla.org/mime;1"].getService(Ci.nsIMIMEService);
+ let handlerInfo = mimeService.getFromTypeAndExtension(
+ "application/pdf",
+ "pdf"
+ );
+
+ // Make sure pdf.js is the default handler.
+ is(
+ handlerInfo.alwaysAskBeforeHandling,
+ false,
+ "pdf handler defaults to always-ask is false"
+ );
+ is(
+ handlerInfo.preferredAction,
+ Ci.nsIHandlerInfo.handleInternally,
+ "pdf handler defaults to internal"
+ );
+
+ info("Pref action: " + handlerInfo.preferredAction);
+
+ await BrowserTestUtils.withNewTab(
+ { gBrowser, url: "about:blank" },
+ async function (newTabBrowser) {
+ await waitForPdfJS(newTabBrowser, TESTROOT + "file_pdfjs_test.pdf");
+
+ await SpecialPowers.spawn(newTabBrowser, [], async function () {
+ // Check if PDF is opened with internal viewer
+ Assert.ok(
+ content.document.querySelector("div#viewer"),
+ "document content has viewer UI"
+ );
+ });
+
+ await SpecialPowers.spawn(newTabBrowser, [], contentSetUp);
+
+ await runTests(newTabBrowser);
+
+ await SpecialPowers.spawn(newTabBrowser, [], async function () {
+ let pageNumber = content.document.querySelector("input#pageNumber");
+ Assert.equal(
+ pageNumber.value,
+ pageNumber.max,
+ "Document is left on the last page"
+ );
+ });
+ }
+ );
+});
+
+async function contentSetUp() {
+ /**
+ * Outline Items gets appended to the document later on we have to
+ * wait for them before we start to navigate though document
+ *
+ * @param document
+ * @returns {deferred.promise|*}
+ */
+ function waitForOutlineItems(document) {
+ return new Promise((resolve, reject) => {
+ document.addEventListener(
+ "outlineloaded",
+ function (evt) {
+ var outlineCount = evt.detail.outlineCount;
+
+ if (
+ document.querySelectorAll("#outlineView .treeItem").length ===
+ outlineCount
+ ) {
+ resolve();
+ } else {
+ reject("Unable to find outline items.");
+ }
+ },
+ { once: true }
+ );
+ });
+ }
+
+ /**
+ * The key navigation has to happen in page-fit, otherwise it won't scroll
+ * through a complete page
+ *
+ * @param document
+ * @returns {deferred.promise|*}
+ */
+ function setZoomToPageFit(document) {
+ return new Promise(resolve => {
+ document.addEventListener(
+ "pagerendered",
+ function (e) {
+ document.querySelector("#viewer").click();
+ resolve();
+ },
+ { once: true }
+ );
+
+ var select = document.querySelector("select#scaleSelect");
+ select.selectedIndex = 2;
+ select.dispatchEvent(new content.Event("change"));
+ });
+ }
+
+ await waitForOutlineItems(content.document);
+ await setZoomToPageFit(content.document);
+}
+
+/**
+ * As the page changes asynchronously, we have to wait for the event after
+ * we trigger the action so we will be at the expected page number after each action
+ *
+ * @param document
+ * @param window
+ * @param test
+ * @param callback
+ */
+async function runTests(browser) {
+ await SpecialPowers.spawn(browser, [TESTS], async function (contentTESTS) {
+ let window = content;
+ let document = window.document;
+
+ for (let test of contentTESTS) {
+ let deferred = {};
+ deferred.promise = new Promise((resolve, reject) => {
+ deferred.resolve = resolve;
+ deferred.reject = reject;
+ });
+
+ let pageNumber = document.querySelector("input#pageNumber");
+
+ // Add an event-listener to wait for page to change, afterwards resolve the promise
+ let timeout = window.setTimeout(() => deferred.reject(), 5000);
+ window.addEventListener("pagechanging", function pageChange() {
+ if (pageNumber.value == test.expectedPage) {
+ window.removeEventListener("pagechanging", pageChange);
+ window.clearTimeout(timeout);
+ deferred.resolve(+pageNumber.value);
+ }
+ });
+
+ // Get the element and trigger the action for changing the page
+ var el = document.querySelector(test.action.selector);
+ Assert.ok(el, "Element '" + test.action.selector + "' has been found");
+
+ // The value option is for input case
+ if (test.action.value) {
+ el.value = test.action.value;
+ }
+
+ // Dispatch the event for changing the page
+ var ev;
+ if (test.action.event == "keydown") {
+ ev = new window.KeyboardEvent("keydown", {
+ bubbles: true,
+ cancelable: true,
+ view: null,
+ keyCode: test.action.keyCode,
+ charCode: 0,
+ });
+ el.dispatchEvent(ev);
+ } else {
+ ev = new content.Event(test.action.event);
+ }
+ el.dispatchEvent(ev);
+
+ let pgNumber = await deferred.promise;
+ Assert.equal(pgNumber, test.expectedPage, test.message);
+ }
+
+ var viewer = content.wrappedJSObject.PDFViewerApplication;
+ await viewer.close();
+ });
+}
diff --git a/toolkit/components/pdfjs/test/browser_pdfjs_nonpdf_filename.js b/toolkit/components/pdfjs/test/browser_pdfjs_nonpdf_filename.js
new file mode 100644
index 0000000000..ee08cd45d1
--- /dev/null
+++ b/toolkit/components/pdfjs/test/browser_pdfjs_nonpdf_filename.js
@@ -0,0 +1,73 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+const TESTROOT = getRootDirectory(gTestPath).replace(
+ "chrome://mochitests/content/",
+ "https://example.com/"
+);
+
+// The page we use to open the PDF.
+const LINK_PAGE_URL = TESTROOT + "file_pdf_download_link.html";
+
+add_task(async function test_filename_nonpdf_extension() {
+ var MockFilePicker = SpecialPowers.MockFilePicker;
+ MockFilePicker.init(window);
+ let filepickerNamePromise = new Promise(resolve => {
+ MockFilePicker.showCallback = function (fp) {
+ resolve(fp.defaultString);
+ return MockFilePicker.returnCancel;
+ };
+ });
+ registerCleanupFunction(() => MockFilePicker.cleanup());
+
+ await SpecialPowers.pushPrefEnv({
+ set: [["browser.download.open_pdf_attachments_inline", true]],
+ });
+
+ await BrowserTestUtils.withNewTab(
+ { gBrowser, url: LINK_PAGE_URL },
+ async function (browser) {
+ await SpecialPowers.spawn(browser, [], async () => {
+ let link = content.document.getElementById("custom_filename");
+ let response = await content.fetch(link.href, {
+ method: "GET",
+ headers: {
+ "Content-Type": "application/pdf",
+ },
+ });
+ let blob = await response.blob();
+ const url = content.URL.createObjectURL(blob);
+ link.href = url;
+ link.download = "Fido-2022-04-28";
+ link.rel = "noopener";
+ });
+
+ let pdfLoaded = BrowserTestUtils.waitForNewTab(
+ gBrowser,
+ url => url.startsWith("blob:"),
+ true
+ );
+ await BrowserTestUtils.synthesizeMouseAtCenter(
+ "#custom_filename",
+ {},
+ browser
+ );
+ let newTab = await pdfLoaded;
+
+ info("Clicking on the download button...");
+ await SpecialPowers.spawn(newTab.linkedBrowser, [], () => {
+ content.document.getElementById("download").click();
+ });
+ info("Waiting for a filename to be picked from the file picker");
+ let defaultName = await filepickerNamePromise;
+ is(
+ defaultName,
+ "Fido-2022-04-28.pdf",
+ "Should have gotten the provided filename with pdf suffixed."
+ );
+ BrowserTestUtils.removeTab(newTab);
+ }
+ );
+});
diff --git a/toolkit/components/pdfjs/test/browser_pdfjs_not_default.js b/toolkit/components/pdfjs/test/browser_pdfjs_not_default.js
new file mode 100644
index 0000000000..ea05348bc9
--- /dev/null
+++ b/toolkit/components/pdfjs/test/browser_pdfjs_not_default.js
@@ -0,0 +1,26 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+add_task(async function test_pdfjs_not_default() {
+ var oldAction = changeMimeHandler(Ci.nsIHandlerInfo.useSystemDefault, true);
+ let dirFileObj = getChromeDir(getResolvedURI(gTestPath));
+ dirFileObj.append("file_pdfjs_test.pdf");
+
+ let tab = await BrowserTestUtils.openNewForegroundTab(
+ gBrowser,
+ dirFileObj.path
+ );
+
+ // If we don't have the Pdfjs actor loaded, this will throw
+ await getPdfjsActor();
+
+ changeMimeHandler(oldAction[0], oldAction[1]);
+
+ gBrowser.removeTab(tab);
+});
+
+function getPdfjsActor() {
+ let win = Services.wm.getMostRecentWindow("navigator:browser");
+ let selectedBrowser = win.gBrowser.selectedBrowser;
+ return selectedBrowser.browsingContext.currentWindowGlobal.getActor("Pdfjs");
+}
diff --git a/toolkit/components/pdfjs/test/browser_pdfjs_octet_stream.js b/toolkit/components/pdfjs/test/browser_pdfjs_octet_stream.js
new file mode 100644
index 0000000000..d2b4fe310f
--- /dev/null
+++ b/toolkit/components/pdfjs/test/browser_pdfjs_octet_stream.js
@@ -0,0 +1,146 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+const TESTROOT = getRootDirectory(gTestPath).replace(
+ "chrome://mochitests/content/",
+ "http://mochi.test:8888/"
+);
+
+// Get a ref to the pdf we want to open.
+const PDF_URL = TESTROOT + "file_pdfjs_object_stream.pdf";
+
+var gMIMEService = Cc["@mozilla.org/mime;1"].getService(Ci.nsIMIMEService);
+
+/**
+ * Check that if we open a PDF with octet-stream mimetype, it can load
+ * PDF.js .
+ */
+add_task(async function test_octet_stream_opens_pdfjs() {
+ await SpecialPowers.pushPrefEnv({ set: [["pdfjs.handleOctetStream", true]] });
+ let handlerInfo = gMIMEService.getFromTypeAndExtension(
+ "application/pdf",
+ "pdf"
+ );
+
+ // Make sure pdf.js is the default handler.
+ is(
+ handlerInfo.alwaysAskBeforeHandling,
+ false,
+ "pdf handler defaults to always-ask is false"
+ );
+ is(
+ handlerInfo.preferredAction,
+ Ci.nsIHandlerInfo.handleInternally,
+ "pdf handler defaults to internal"
+ );
+
+ await BrowserTestUtils.withNewTab(
+ { gBrowser, url: "about:blank" },
+ async function (newTabBrowser) {
+ await waitForPdfJS(newTabBrowser, PDF_URL);
+ is(newTabBrowser.currentURI.spec, PDF_URL, "Should load pdfjs");
+ }
+ );
+});
+
+/**
+ * Check that if the octet-stream thing is in a frame, we don't load it inside PDF.js
+ */
+add_task(async function test_octet_stream_in_frame() {
+ await SpecialPowers.pushPrefEnv({
+ set: [["pdfjs.handleOctetStream", true]],
+ });
+
+ let handlerInfo = gMIMEService.getFromTypeAndExtension(
+ "application/pdf",
+ "pdf"
+ );
+
+ // Make sure pdf.js is the default handler.
+ is(
+ handlerInfo.alwaysAskBeforeHandling,
+ false,
+ "pdf handler defaults to always-ask is false"
+ );
+ is(
+ handlerInfo.preferredAction,
+ Ci.nsIHandlerInfo.handleInternally,
+ "pdf handler defaults to internal"
+ );
+
+ let downloadsPanelPromise = BrowserTestUtils.waitForEvent(
+ DownloadsPanel.panel,
+ "popupshown"
+ );
+
+ // Once downloaded, the PDF will be opened as a file:// URI in a new tab
+ let previewTabPromise = BrowserTestUtils.waitForNewTab(
+ gBrowser,
+ url => {
+ let uri = NetUtil.newURI(url);
+ return uri.scheme == "file" && uri.spec.endsWith(".pdf");
+ },
+ false, // dont wait for load
+ true // any tab, not just the next one
+ );
+
+ await BrowserTestUtils.withNewTab(
+ { gBrowser, url: `data:text/html,<iframe src='${PDF_URL}'>` },
+ async function (newTabBrowser) {
+ // wait until downloadsPanel opens before continuing with test
+ info("Waiting for download panel to open");
+ await downloadsPanelPromise;
+ is(
+ DownloadsPanel.panel.state,
+ "open",
+ "Check the download panel state is 'open'"
+ );
+ let downloadList = await Downloads.getList(Downloads.PUBLIC);
+ let [download] = downloadList._downloads;
+
+ // Verify the downloaded PDF opened in a new tab,
+ // with its download file URI
+ info("Waiting for preview tab");
+ let previewTab = await previewTabPromise;
+ ok(previewTab, "PDF opened in a new tab");
+
+ is(DownloadsPanel.isPanelShowing, true, "DownloadsPanel should be open.");
+ is(
+ downloadList._downloads.length,
+ 1,
+ "File should be successfully downloaded."
+ );
+
+ await BrowserTestUtils.removeTab(previewTab);
+
+ info("cleaning up downloads");
+ try {
+ if (Services.appinfo.OS === "WINNT") {
+ // We need to make the file writable to delete it on Windows.
+ await IOUtils.setPermissions(download.target.path, 0o600);
+ }
+ await IOUtils.remove(download.target.path);
+ } catch (error) {
+ info("The file " + download.target.path + " is not removed, " + error);
+ }
+ await downloadList.remove(download);
+ await download.finalize();
+
+ if (DownloadsPanel.panel.state !== "closed") {
+ let hiddenPromise = BrowserTestUtils.waitForEvent(
+ DownloadsPanel.panel,
+ "popuphidden"
+ );
+ DownloadsPanel.hidePanel();
+ await hiddenPromise;
+ }
+ is(
+ DownloadsPanel.panel.state,
+ "closed",
+ "Check that the download panel is closed"
+ );
+ }
+ );
+});
diff --git a/toolkit/components/pdfjs/test/browser_pdfjs_saveas.js b/toolkit/components/pdfjs/test/browser_pdfjs_saveas.js
new file mode 100644
index 0000000000..a1bfc18a91
--- /dev/null
+++ b/toolkit/components/pdfjs/test/browser_pdfjs_saveas.js
@@ -0,0 +1,216 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+const RELATIVE_DIR = "toolkit/components/pdfjs/test/";
+const TESTROOT = "http://example.com/browser/" + RELATIVE_DIR;
+
+var MockFilePicker = SpecialPowers.MockFilePicker;
+MockFilePicker.init(window);
+
+Services.scriptloader.loadSubScript(
+ "chrome://mochitests/content/browser/toolkit/content/tests/browser/common/mockTransfer.js",
+ this
+);
+
+function createPromiseForTransferComplete(expectedFileName, destFile) {
+ return new Promise(resolve => {
+ MockFilePicker.showCallback = fp => {
+ info("Filepicker shown, checking filename");
+ is(fp.defaultString, expectedFileName, "Filename should be correct.");
+ let fileName = fp.defaultString;
+ destFile.append(fileName);
+
+ MockFilePicker.setFiles([destFile]);
+ MockFilePicker.filterIndex = 0; // kSaveAsType_Complete
+
+ MockFilePicker.showCallback = null;
+ mockTransferCallback = function (downloadSuccess) {
+ ok(downloadSuccess, "File should have been downloaded successfully");
+ mockTransferCallback = () => {};
+ resolve();
+ };
+ };
+ });
+}
+
+let tempDir = createTemporarySaveDirectory();
+
+add_setup(async function () {
+ mockTransferRegisterer.register();
+ registerCleanupFunction(function () {
+ mockTransferRegisterer.unregister();
+ MockFilePicker.cleanup();
+ tempDir.remove(true);
+ });
+});
+
+/**
+ * Check triggering "Save Page As" on a non-forms PDF opens the "Save As" dialog
+ * and successfully saves the file.
+ */
+add_task(async function test_pdf_saveas() {
+ await BrowserTestUtils.withNewTab(
+ { gBrowser, url: "about:blank" },
+ async function (browser) {
+ await waitForPdfJS(browser, TESTROOT + "file_pdfjs_test.pdf");
+ let destFile = tempDir.clone();
+ MockFilePicker.displayDirectory = tempDir;
+ let fileSavedPromise = createPromiseForTransferComplete(
+ "file_pdfjs_test.pdf",
+ destFile
+ );
+ saveBrowser(browser);
+ await fileSavedPromise;
+ }
+ );
+});
+
+/**
+ * Check triggering "Save Page As" on a PDF with forms that has been modified
+ * does the following:
+ * 1) opens the "Save As" dialog
+ * 2) successfully saves the file
+ * 3) the new file contains the new form data
+ */
+add_task(async function test_pdf_saveas_forms() {
+ await SpecialPowers.pushPrefEnv({
+ set: [["pdfjs.renderInteractiveForms", true]],
+ });
+ let destFile = tempDir.clone();
+ await BrowserTestUtils.withNewTab(
+ { gBrowser, url: "about:blank" },
+ async function (browser) {
+ await waitForPdfJSAnnotationLayer(
+ browser,
+ TESTROOT + "file_pdfjs_form.pdf"
+ );
+ // Fill in the form input field.
+ await SpecialPowers.spawn(browser, [], async function () {
+ let formInput = content.document.querySelector(
+ "#viewerContainer input"
+ );
+ ok(formInput, "PDF contains text field.");
+ is(formInput.value, "", "Text field is empty to start.");
+ formInput.value = "test";
+ formInput.dispatchEvent(new content.window.Event("input"));
+ });
+
+ MockFilePicker.displayDirectory = tempDir;
+ let fileSavedPromise = createPromiseForTransferComplete(
+ "file_pdfjs_form.pdf",
+ destFile
+ );
+ saveBrowser(browser);
+ await fileSavedPromise;
+ }
+ );
+
+ // Now that the file has been modified and saved, load it to verify the form
+ // data persisted.
+ await BrowserTestUtils.withNewTab(
+ { gBrowser, url: "about:blank" },
+ async function (browser) {
+ await waitForPdfJSAnnotationLayer(browser, NetUtil.newURI(destFile).spec);
+ await SpecialPowers.spawn(browser, [], async function () {
+ let formInput = content.document.querySelector(
+ "#viewerContainer input"
+ );
+ ok(formInput, "PDF contains text field.");
+ is(formInput.value, "test", "Text field is filled in.");
+ });
+ }
+ );
+});
+
+/**
+ * Check triggering "Save Page As" on a PDF which was loaded with a custom
+ * content disposition filename defaults to using the provided filename.
+ */
+add_task(async function test_pdf_saveas_customname() {
+ await SpecialPowers.pushPrefEnv({
+ set: [
+ ["browser.helperApps.showOpenOptionForPdfJS", true],
+ ["browser.helperApps.showOpenOptionForViewableInternally", true],
+ ["browser.download.always_ask_before_handling_new_types", false],
+ ["browser.download.open_pdf_attachments_inline", true],
+ ],
+ });
+ await BrowserTestUtils.withNewTab(
+ { gBrowser, url: TESTROOT + "file_pdf_download_link.html" },
+ async function (browser) {
+ // Click on the download link in the loaded file. This will create a new
+ // tab with the PDF loaded in it.
+ BrowserTestUtils.synthesizeMouseAtCenter("#custom_filename", {}, browser);
+ let tab = await BrowserTestUtils.waitForNewTab(gBrowser);
+ info("tab created");
+
+ // Wait for the PDF's metadata to be fully loaded before downloading, as
+ // otherwise it won't be aware of the content disposition filename yet.
+ await BrowserTestUtils.waitForContentEvent(
+ tab.linkedBrowser,
+ "metadataloaded",
+ false,
+ null,
+ true
+ );
+ info("metadata loaded");
+
+ let destFile = tempDir.clone();
+ MockFilePicker.displayDirectory = tempDir;
+ let fileSavedPromise = createPromiseForTransferComplete(
+ "custom_filename.pdf",
+ destFile
+ );
+ saveBrowser(tab.linkedBrowser);
+ await fileSavedPromise;
+ BrowserTestUtils.removeTab(tab);
+ }
+ );
+ await SpecialPowers.popPrefEnv();
+});
+
+/**
+ * Check if the directory where the pdfs are saved is based on the original
+ * domain (see bug 1768383).
+ */
+add_task(async function () {
+ await BrowserTestUtils.withNewTab(
+ { gBrowser, url: "about:blank" },
+ async function (browser) {
+ const downloadLastDir = new DownloadLastDir(null);
+ const destDirs = [];
+ for (let i = 1; i <= 2; i++) {
+ const destDir = createTemporarySaveDirectory(i);
+ destDirs.push(destDir);
+ const url = `http://test${i}.example.com/browser/${RELATIVE_DIR}file_pdfjs_test.pdf`;
+ downloadLastDir.setFile(url, destDir);
+ await TestUtils.waitForTick();
+ }
+
+ const url = `http://test1.example.com/browser/${RELATIVE_DIR}file_pdfjs_hcm.pdf`;
+ await waitForPdfJS(browser, url);
+
+ const fileSavedPromise = new Promise(resolve => {
+ MockFilePicker.showCallback = fp => {
+ MockFilePicker.setFiles([]);
+ MockFilePicker.showCallback = null;
+ resolve(fp.displayDirectory.path);
+ };
+ });
+ registerCleanupFunction(() => {
+ for (const destDir of destDirs) {
+ destDir.remove(true);
+ }
+ });
+ saveBrowser(browser);
+ const dirPath = await fileSavedPromise;
+ is(
+ dirPath,
+ destDirs[0].path,
+ "Proposed directory must be based on the domain"
+ );
+ }
+ );
+});
diff --git a/toolkit/components/pdfjs/test/browser_pdfjs_savedialog.js b/toolkit/components/pdfjs/test/browser_pdfjs_savedialog.js
new file mode 100644
index 0000000000..4f0c952ebb
--- /dev/null
+++ b/toolkit/components/pdfjs/test/browser_pdfjs_savedialog.js
@@ -0,0 +1,53 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+const RELATIVE_DIR = "toolkit/components/pdfjs/test/";
+const TESTROOT = "http://example.com/browser/" + RELATIVE_DIR;
+
+function test() {
+ // When the always ask pref is disabled, we expect the PDF to be simply
+ // downloaded without a prompt, so ensure the pref is enabled here.
+ Services.prefs.setBoolPref(
+ "browser.download.always_ask_before_handling_new_types",
+ true
+ );
+ var oldAction = changeMimeHandler(Ci.nsIHandlerInfo.useSystemDefault, true);
+ var tab = BrowserTestUtils.addTab(gBrowser, TESTROOT + "file_pdfjs_test.pdf");
+
+ // Test: "Open with" dialog comes up when pdf.js is not selected as the default
+ // handler.
+ addWindowListener(
+ "chrome://mozapps/content/downloads/unknownContentType.xhtml",
+ finish
+ );
+
+ waitForExplicitFinish();
+ registerCleanupFunction(function () {
+ Services.prefs.clearUserPref(
+ "browser.download.always_ask_before_handling_new_types"
+ );
+ changeMimeHandler(oldAction[0], oldAction[1]);
+ gBrowser.removeTab(tab);
+ });
+}
+
+function addWindowListener(aURL, aCallback) {
+ Services.wm.addListener({
+ onOpenWindow(aXULWindow) {
+ info("window opened, waiting for focus");
+ Services.wm.removeListener(this);
+
+ var domwindow = aXULWindow.docShell.domWindow;
+ waitForFocus(function () {
+ is(
+ domwindow.document.location.href,
+ aURL,
+ "should have seen the right window open"
+ );
+ domwindow.close();
+ aCallback();
+ }, domwindow);
+ },
+ onCloseWindow(aXULWindow) {},
+ });
+}
diff --git a/toolkit/components/pdfjs/test/browser_pdfjs_secondary_toolbar_telemetry.js b/toolkit/components/pdfjs/test/browser_pdfjs_secondary_toolbar_telemetry.js
new file mode 100644
index 0000000000..136b9c310d
--- /dev/null
+++ b/toolkit/components/pdfjs/test/browser_pdfjs_secondary_toolbar_telemetry.js
@@ -0,0 +1,67 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+const RELATIVE_DIR = "toolkit/components/pdfjs/test/";
+const TESTROOT = "https://example.com/browser/" + RELATIVE_DIR;
+
+// Test telemetry.
+add_task(async function test() {
+ let mimeService = Cc["@mozilla.org/mime;1"].getService(Ci.nsIMIMEService);
+ let handlerInfo = mimeService.getFromTypeAndExtension(
+ "application/pdf",
+ "pdf"
+ );
+
+ // Make sure pdf.js is the default handler.
+ is(
+ handlerInfo.alwaysAskBeforeHandling,
+ false,
+ "pdf handler defaults to always-ask is false"
+ );
+ is(
+ handlerInfo.preferredAction,
+ Ci.nsIHandlerInfo.handleInternally,
+ "pdf handler defaults to internal"
+ );
+
+ info("Pref action: " + handlerInfo.preferredAction);
+
+ await BrowserTestUtils.withNewTab(
+ { gBrowser, url: "about:blank" },
+ async function (browser) {
+ Services.fog.testResetFOG();
+
+ // check that PDF is opened with internal viewer
+ await waitForPdfJS(browser, TESTROOT + "file_pdfjs_test.pdf");
+
+ await Services.fog.testFlushAllChildren();
+ Assert.equal(Glean.pdfjs.buttons.cursor_hand_tool.testGetValue() || 0, 0);
+
+ info("Clicking on the secondary toolbar button...");
+ await SpecialPowers.spawn(browser, [], () => {
+ content.document.querySelector("#secondaryToolbarToggle").click();
+ });
+
+ await BrowserTestUtils.waitForCondition(async () =>
+ SpecialPowers.spawn(browser, [], async function () {
+ return !content.document
+ .querySelector("#secondaryToolbar")
+ .classList.contains("hidden");
+ })
+ );
+
+ info("Clicking on the cursor handtool button...");
+ await SpecialPowers.spawn(browser, [], () => {
+ content.document.querySelector("#cursorHandTool").click();
+ });
+
+ await Services.fog.testFlushAllChildren();
+ Assert.equal(Glean.pdfjs.buttons.cursor_hand_tool.testGetValue(), 1);
+
+ await SpecialPowers.spawn(browser, [], async function () {
+ var viewer = content.wrappedJSObject.PDFViewerApplication;
+ await viewer.close();
+ });
+ }
+ );
+});
diff --git a/toolkit/components/pdfjs/test/browser_pdfjs_stamp_telemetry.js b/toolkit/components/pdfjs/test/browser_pdfjs_stamp_telemetry.js
new file mode 100644
index 0000000000..b8955f77e3
--- /dev/null
+++ b/toolkit/components/pdfjs/test/browser_pdfjs_stamp_telemetry.js
@@ -0,0 +1,219 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+const RELATIVE_DIR = "toolkit/components/pdfjs/test/";
+const TESTROOT = "https://example.com/browser/" + RELATIVE_DIR;
+
+Services.scriptloader.loadSubScript(
+ "chrome://mochitests/content/browser/toolkit/content/tests/browser/common/mockTransfer.js",
+ this
+);
+
+const MockFilePicker = SpecialPowers.MockFilePicker;
+MockFilePicker.init(window);
+MockFilePicker.returnValue = MockFilePicker.returnOK;
+const file = new FileUtils.File(getTestFilePath("moz.png"));
+MockFilePicker.setFiles([file]);
+
+// Test telemetry.
+add_task(async function test() {
+ let mimeService = Cc["@mozilla.org/mime;1"].getService(Ci.nsIMIMEService);
+ let handlerInfo = mimeService.getFromTypeAndExtension(
+ "application/pdf",
+ "pdf"
+ );
+
+ // Make sure pdf.js is the default handler.
+ is(
+ handlerInfo.alwaysAskBeforeHandling,
+ false,
+ "pdf handler defaults to always-ask is false"
+ );
+ is(
+ handlerInfo.preferredAction,
+ Ci.nsIHandlerInfo.handleInternally,
+ "pdf handler defaults to internal"
+ );
+
+ info("Pref action: " + handlerInfo.preferredAction);
+
+ await BrowserTestUtils.withNewTab(
+ { gBrowser, url: "about:blank" },
+ async function (browser) {
+ await SpecialPowers.pushPrefEnv({
+ set: [["pdfjs.annotationEditorMode", 0]],
+ });
+
+ Services.fog.testResetFOG();
+
+ // check that PDF is opened with internal viewer
+ await waitForPdfJSAllLayers(browser, TESTROOT + "file_pdfjs_test.pdf", [
+ [
+ "annotationEditorLayer",
+ "annotationLayer",
+ "textLayer",
+ "canvasWrapper",
+ ],
+ ["annotationEditorLayer", "textLayer", "canvasWrapper"],
+ ]);
+
+ await Services.fog.testFlushAllChildren();
+ Assert.equal(
+ Glean.pdfjs.editing.stamp.testGetValue() || 0,
+ 0,
+ "Should have no stamp"
+ );
+
+ await enableEditor(browser, "Stamp");
+ await clickOn(browser, `#editorStampAddImage`);
+ await waitForSelector(browser, ".altText");
+
+ await Services.fog.testFlushAllChildren();
+
+ Assert.equal(
+ Glean.pdfjs.editing.stamp.testGetValue(),
+ 1,
+ "Should have 1 stamp"
+ );
+ Assert.equal(
+ Glean.pdfjs.stamp.inserted_image.testGetValue(),
+ 1,
+ "Should have 1 inserted_image"
+ );
+
+ await clickOn(browser, ".altText");
+ await waitForSelector(
+ browser,
+ "#altTextDialog",
+ "Wait for the dialog to be visible"
+ );
+
+ await clickOn(browser, "#descriptionTextarea");
+ await write(browser, "Hello World");
+
+ await clickOn(browser, "#altTextSave");
+ await TestUtils.waitForTick();
+ await Services.fog.testFlushAllChildren();
+
+ Assert.equal(
+ Glean.pdfjs.stamp.alt_text_save.testGetValue(),
+ 1,
+ "Should have 1 alt_text_save"
+ );
+ Assert.equal(
+ Glean.pdfjs.stamp.alt_text_description.testGetValue(),
+ 1,
+ "Should have 1 alt_text_description"
+ );
+
+ await SpecialPowers.spawn(browser, [], async () => {
+ const altText = content.document.querySelector(".altText");
+ await EventUtils.synthesizeMouseAtCenter(
+ altText,
+ { type: "mousemove" },
+ content
+ );
+ await ContentTaskUtils.waitForCondition(
+ () => ContentTaskUtils.isVisible(altText.querySelector(".tooltip")),
+ "Wait for tooltip"
+ );
+ });
+
+ await TestUtils.waitForTick();
+ await Services.fog.testFlushAllChildren();
+ Assert.equal(
+ Glean.pdfjs.stamp.alt_text_tooltip.testGetValue(),
+ 1,
+ "Should have 1 alt_text_tooltip"
+ );
+
+ await clickOn(browser, ".altText");
+ await waitForSelector(
+ browser,
+ "#altTextDialog",
+ "Wait for the dialog to be visible"
+ );
+ await clickOn(browser, "#altTextCancel");
+ await TestUtils.waitForTick();
+
+ await Services.fog.testFlushAllChildren();
+
+ Assert.equal(
+ Glean.pdfjs.stamp.alt_text_cancel.testGetValue(),
+ 1,
+ "Should have 1 alt_text_cancel"
+ );
+
+ await clickOn(browser, ".altText");
+ await waitForSelector(
+ browser,
+ "#altTextDialog",
+ "Wait for the dialog to be visible"
+ );
+ await clickOn(browser, "#descriptionTextarea");
+ await write(browser, "Hello World");
+
+ await clickOn(browser, "#altTextSave");
+ await TestUtils.waitForTick();
+ await Services.fog.testFlushAllChildren();
+
+ Assert.equal(
+ Glean.pdfjs.stamp.alt_text_save.testGetValue(),
+ 2,
+ "Should have 2 alt_text_save"
+ );
+ Assert.equal(
+ Glean.pdfjs.stamp.alt_text_description.testGetValue(),
+ 2,
+ "Should have 2 alt_text_description"
+ );
+ Assert.equal(
+ Glean.pdfjs.stamp.alt_text_edit.testGetValue(),
+ 1,
+ "Should have 1 alt_text_edit"
+ );
+
+ await clickOn(browser, ".altText");
+ await waitForSelector(
+ browser,
+ "#altTextDialog",
+ "Wait for the dialog to be visible"
+ );
+ await clickOn(browser, "#decorativeButton");
+ await TestUtils.waitForTick();
+ await clickOn(browser, "#altTextSave");
+ await TestUtils.waitForTick();
+ await Services.fog.testFlushAllChildren();
+
+ Assert.equal(
+ Glean.pdfjs.stamp.alt_text_decorative.testGetValue(),
+ 1,
+ "Should have 1 alt_text_decorative"
+ );
+ Assert.equal(
+ Glean.pdfjs.stamp.alt_text_keyboard.testGetValue() || 0,
+ 0,
+ "Should have 0 alt_text_keyboard"
+ );
+
+ await click(browser, ".altText");
+ await click(browser, "#descriptionButton");
+ await click(browser, "#altTextSave");
+
+ await TestUtils.waitForTick();
+ await Services.fog.testFlushAllChildren();
+
+ Assert.equal(
+ Glean.pdfjs.stamp.alt_text_keyboard.testGetValue(),
+ 1,
+ "Should have 1 alt_text_keyboard"
+ );
+
+ await SpecialPowers.spawn(browser, [], async function () {
+ const viewer = content.wrappedJSObject.PDFViewerApplication;
+ viewer.pdfDocument.annotationStorage.resetModified();
+ await viewer.close();
+ });
+ }
+ );
+});
diff --git a/toolkit/components/pdfjs/test/browser_pdfjs_views.js b/toolkit/components/pdfjs/test/browser_pdfjs_views.js
new file mode 100644
index 0000000000..16757aff78
--- /dev/null
+++ b/toolkit/components/pdfjs/test/browser_pdfjs_views.js
@@ -0,0 +1,106 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+const RELATIVE_DIR = "toolkit/components/pdfjs/test/";
+const TESTROOT = "http://example.com/browser/" + RELATIVE_DIR;
+
+add_task(async function test() {
+ let mimeService = Cc["@mozilla.org/mime;1"].getService(Ci.nsIMIMEService);
+ let handlerInfo = mimeService.getFromTypeAndExtension(
+ "application/pdf",
+ "pdf"
+ );
+
+ // Make sure pdf.js is the default handler.
+ is(
+ handlerInfo.alwaysAskBeforeHandling,
+ false,
+ "pdf handler defaults to always-ask is false"
+ );
+ is(
+ handlerInfo.preferredAction,
+ Ci.nsIHandlerInfo.handleInternally,
+ "pdf handler defaults to internal"
+ );
+
+ info("Pref action: " + handlerInfo.preferredAction);
+
+ await BrowserTestUtils.withNewTab(
+ { gBrowser, url: "about:blank" },
+ async function (browser) {
+ // check that PDF is opened with internal viewer
+ await waitForPdfJS(browser, TESTROOT + "file_pdfjs_test.pdf");
+
+ await SpecialPowers.spawn(browser, [], async function () {
+ Assert.ok(
+ content.document.querySelector("div#viewer"),
+ "document content has viewer UI"
+ );
+
+ // open sidebar
+ var sidebar = content.document.querySelector("button#sidebarToggle");
+ var outerContainer =
+ content.document.querySelector("div#outerContainer");
+
+ sidebar.click();
+ Assert.ok(
+ outerContainer.classList.contains("sidebarOpen"),
+ "sidebar opens on click"
+ );
+
+ // check that thumbnail view is open
+ var thumbnailView = content.document.querySelector("div#thumbnailView");
+ var outlineView = content.document.querySelector("div#outlineView");
+
+ Assert.equal(
+ thumbnailView.getAttribute("class"),
+ null,
+ "Initial view is thumbnail view"
+ );
+ Assert.equal(
+ outlineView.getAttribute("class"),
+ "hidden",
+ "Outline view is hidden initially"
+ );
+
+ // switch to outline view
+ var viewOutlineButton =
+ content.document.querySelector("button#viewOutline");
+ viewOutlineButton.click();
+
+ Assert.equal(
+ thumbnailView.getAttribute("class"),
+ "hidden",
+ "Thumbnail view is hidden when outline is selected"
+ );
+ Assert.equal(
+ outlineView.getAttribute("class"),
+ "",
+ "Outline view is visible when selected"
+ );
+
+ // switch back to thumbnail view
+ var viewThumbnailButton = content.document.querySelector(
+ "button#viewThumbnail"
+ );
+ viewThumbnailButton.click();
+
+ Assert.equal(
+ thumbnailView.getAttribute("class"),
+ "",
+ "Thumbnail view is visible when selected"
+ );
+ Assert.equal(
+ outlineView.getAttribute("class"),
+ "hidden",
+ "Outline view is hidden when thumbnail is selected"
+ );
+
+ sidebar.click();
+
+ var viewer = content.wrappedJSObject.PDFViewerApplication;
+ await viewer.close();
+ });
+ }
+ );
+});
diff --git a/toolkit/components/pdfjs/test/browser_pdfjs_zoom.js b/toolkit/components/pdfjs/test/browser_pdfjs_zoom.js
new file mode 100644
index 0000000000..e00dede422
--- /dev/null
+++ b/toolkit/components/pdfjs/test/browser_pdfjs_zoom.js
@@ -0,0 +1,279 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+requestLongerTimeout(2);
+
+const RELATIVE_DIR = "toolkit/components/pdfjs/test/";
+const TESTROOT = "http://example.com/browser/" + RELATIVE_DIR;
+
+const TESTS = [
+ {
+ action: {
+ selector: "button#zoomIn",
+ event: "click",
+ },
+ expectedZoom: 1, // 1 - zoom in
+ message: "Zoomed in using the '+' (zoom in) button",
+ },
+
+ {
+ action: {
+ selector: "button#zoomOut",
+ event: "click",
+ },
+ expectedZoom: -1, // -1 - zoom out
+ message: "Zoomed out using the '-' (zoom out) button",
+ },
+
+ {
+ action: {
+ keyboard: true,
+ keyCode: 61,
+ event: "+",
+ },
+ expectedZoom: 1, // 1 - zoom in
+ message: "Zoomed in using the CTRL++ keys",
+ },
+
+ {
+ action: {
+ keyboard: true,
+ keyCode: 109,
+ event: "-",
+ },
+ expectedZoom: -1, // -1 - zoom out
+ message: "Zoomed out using the CTRL+- keys",
+ },
+
+ {
+ action: {
+ selector: "select#scaleSelect",
+ index: 5,
+ event: "change",
+ },
+ expectedZoom: -1, // -1 - zoom out
+ message: "Zoomed using the zoom picker",
+ },
+];
+
+add_task(async function test() {
+ let mimeService = Cc["@mozilla.org/mime;1"].getService(Ci.nsIMIMEService);
+ let handlerInfo = mimeService.getFromTypeAndExtension(
+ "application/pdf",
+ "pdf"
+ );
+
+ // Make sure pdf.js is the default handler.
+ is(
+ handlerInfo.alwaysAskBeforeHandling,
+ false,
+ "pdf handler defaults to always-ask is false"
+ );
+ is(
+ handlerInfo.preferredAction,
+ Ci.nsIHandlerInfo.handleInternally,
+ "pdf handler defaults to internal"
+ );
+
+ info("Pref action: " + handlerInfo.preferredAction);
+
+ await BrowserTestUtils.withNewTab(
+ { gBrowser, url: "about:blank" },
+ async function (newTabBrowser) {
+ await waitForPdfJS(
+ newTabBrowser,
+ TESTROOT + "file_pdfjs_test.pdf#zoom=100"
+ );
+
+ await SpecialPowers.spawn(
+ newTabBrowser,
+ [TESTS],
+ async function (contentTESTS) {
+ let document = content.document;
+
+ function waitForRender() {
+ return new Promise(resolve => {
+ document.addEventListener(
+ "pagerendered",
+ function onPageRendered(e) {
+ if (e.detail.pageNumber !== 1) {
+ return;
+ }
+
+ document.removeEventListener(
+ "pagerendered",
+ onPageRendered,
+ true
+ );
+ resolve();
+ },
+ true
+ );
+ });
+ }
+
+ // check that PDF is opened with internal viewer
+ Assert.ok(
+ content.document.querySelector("div#viewer"),
+ "document content has viewer UI"
+ );
+
+ let initialWidth, previousWidth;
+ initialWidth = previousWidth = parseInt(
+ content.getComputedStyle(
+ content.document.querySelector("div.page[data-page-number='1']")
+ ).width
+ );
+
+ for (let subTest of contentTESTS) {
+ // We zoom using an UI element
+ var ev;
+ if (subTest.action.selector) {
+ // Get the element and trigger the action for changing the zoom
+ var el = document.querySelector(subTest.action.selector);
+ Assert.ok(
+ el,
+ "Element '" + subTest.action.selector + "' has been found"
+ );
+
+ if (subTest.action.index) {
+ el.selectedIndex = subTest.action.index;
+ }
+
+ // Dispatch the event for changing the zoom
+ ev = new content.Event(subTest.action.event);
+ } else {
+ // We zoom using keyboard
+ // Simulate key press
+ ev = new content.KeyboardEvent("keydown", {
+ key: subTest.action.event,
+ keyCode: subTest.action.keyCode,
+ ctrlKey: true,
+ });
+ el = content;
+ }
+
+ el.dispatchEvent(ev);
+ await waitForRender();
+
+ var pageZoomScale =
+ content.document.querySelector("select#scaleSelect");
+
+ // The zoom value displayed in the zoom select
+ var zoomValue =
+ pageZoomScale.options[pageZoomScale.selectedIndex].innerHTML;
+
+ let pageContainer = content.document.querySelector(
+ "div.page[data-page-number='1']"
+ );
+ let actualWidth = parseInt(
+ content.getComputedStyle(pageContainer).width
+ );
+
+ // the actual zoom of the PDF document
+ let computedZoomValue =
+ parseInt((actualWidth / initialWidth).toFixed(2) * 100) + "%";
+ Assert.equal(
+ computedZoomValue,
+ zoomValue,
+ "Content has correct zoom"
+ );
+
+ // Check that document zooms in the expected way (in/out)
+ let zoom = (actualWidth - previousWidth) * subTest.expectedZoom;
+ Assert.ok(zoom > 0, subTest.message);
+
+ previousWidth = actualWidth;
+ }
+
+ var viewer = content.wrappedJSObject.PDFViewerApplication;
+ await viewer.close();
+ }
+ );
+ }
+ );
+});
+
+// Performs a SpecialPowers.spawn round-trip to ensure that any setup
+// that needs to be done in the content process by any pending tasks has
+// a chance to complete before continuing.
+function waitForRoundTrip(browser) {
+ return SpecialPowers.spawn(browser, [], () => {});
+}
+
+async function waitForRenderAndGetWidth(newTabBrowser) {
+ return SpecialPowers.spawn(newTabBrowser, [], async function () {
+ function waitForRender(document) {
+ return new Promise(resolve => {
+ document.addEventListener(
+ "pagerendered",
+ function onPageRendered(e) {
+ if (e.detail.pageNumber !== 1) {
+ return;
+ }
+
+ document.removeEventListener("pagerendered", onPageRendered, true);
+ resolve();
+ },
+ true
+ );
+ });
+ }
+ // check that PDF is opened with internal viewer
+ Assert.ok(
+ content.document.querySelector("div#viewer"),
+ "document content has viewer UI"
+ );
+
+ await waitForRender(content.document);
+
+ return parseInt(
+ content.getComputedStyle(
+ content.document.querySelector("div.page[data-page-number='1']")
+ ).width
+ );
+ });
+}
+
+add_task(async function test_browser_zoom() {
+ await BrowserTestUtils.withNewTab(
+ { gBrowser, url: "about:blank" },
+ async function (newTabBrowser) {
+ await waitForPdfJS(newTabBrowser, TESTROOT + "file_pdfjs_test.pdf");
+
+ const initialWidth = await waitForRenderAndGetWidth(newTabBrowser);
+
+ // Zoom in
+ let newWidthPromise = waitForRenderAndGetWidth(newTabBrowser);
+ await waitForRoundTrip(newTabBrowser);
+ FullZoom.enlarge();
+ Assert.greater(
+ await newWidthPromise,
+ initialWidth,
+ "Zoom in makes the page bigger."
+ );
+
+ // Reset
+ newWidthPromise = waitForRenderAndGetWidth(newTabBrowser);
+ await waitForRoundTrip(newTabBrowser);
+ FullZoom.reset();
+ is(await newWidthPromise, initialWidth, "Zoom reset restores page.");
+
+ // Zoom out
+ newWidthPromise = waitForRenderAndGetWidth(newTabBrowser);
+ await waitForRoundTrip(newTabBrowser);
+ FullZoom.reduce();
+ Assert.less(
+ await newWidthPromise,
+ initialWidth,
+ "Zoom out makes the page smaller."
+ );
+
+ // Clean-up after the PDF viewer.
+ await SpecialPowers.spawn(newTabBrowser, [], function () {
+ const viewer = content.wrappedJSObject.PDFViewerApplication;
+ return viewer.close();
+ });
+ }
+ );
+});
diff --git a/toolkit/components/pdfjs/test/file_pdf_download_link.html b/toolkit/components/pdfjs/test/file_pdf_download_link.html
new file mode 100644
index 0000000000..8b458b7a4c
--- /dev/null
+++ b/toolkit/components/pdfjs/test/file_pdf_download_link.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<body>
+<a id="custom_filename" href="file_pdfjs_test.pdf" download="custom_filename.pdf">custom_filename.pdf</a>
+</body>
diff --git a/toolkit/components/pdfjs/test/file_pdfjs_form.pdf b/toolkit/components/pdfjs/test/file_pdfjs_form.pdf
new file mode 100644
index 0000000000..c6eff988a6
--- /dev/null
+++ b/toolkit/components/pdfjs/test/file_pdfjs_form.pdf
Binary files differ
diff --git a/toolkit/components/pdfjs/test/file_pdfjs_hcm.pdf b/toolkit/components/pdfjs/test/file_pdfjs_hcm.pdf
new file mode 100644
index 0000000000..611cbc6309
--- /dev/null
+++ b/toolkit/components/pdfjs/test/file_pdfjs_hcm.pdf
@@ -0,0 +1,24 @@
+%PDF-1.4
+1 0 obj <</Type /Catalog /Pages 2 0 R>>
+endobj
+2 0 obj <</Type /Pages /Kids [3 0 R] /Count 1>>
+endobj
+3 0 obj<</Type /Page /Parent 2 0 R /MediaBox [0 0 3 3] /Contents 4 0 R>>
+endobj
+4 0 obj
+<</Length 12>>
+stream
+0.5 w 0 0 0 RG 0 2.75 m 0.5 2.75 l s
+endstream
+endobj
+xref
+0 5
+0000000000 65535 f
+0000000009 00000 n
+0000000056 00000 n
+0000000111 00000 n
+0000000191 00000 n
+trailer <</Size 5/Root 1 0 R>>
+startxref
+275
+%%EOF
diff --git a/toolkit/components/pdfjs/test/file_pdfjs_js.pdf b/toolkit/components/pdfjs/test/file_pdfjs_js.pdf
new file mode 100644
index 0000000000..78aab95fd3
--- /dev/null
+++ b/toolkit/components/pdfjs/test/file_pdfjs_js.pdf
Binary files differ
diff --git a/toolkit/components/pdfjs/test/file_pdfjs_object_stream.pdf b/toolkit/components/pdfjs/test/file_pdfjs_object_stream.pdf
new file mode 100644
index 0000000000..89066463f1
--- /dev/null
+++ b/toolkit/components/pdfjs/test/file_pdfjs_object_stream.pdf
Binary files differ
diff --git a/toolkit/components/pdfjs/test/file_pdfjs_object_stream.pdf^headers^ b/toolkit/components/pdfjs/test/file_pdfjs_object_stream.pdf^headers^
new file mode 100644
index 0000000000..ff8fb3126e
--- /dev/null
+++ b/toolkit/components/pdfjs/test/file_pdfjs_object_stream.pdf^headers^
@@ -0,0 +1,2 @@
+Content-Type: application/octet-stream
+
diff --git a/toolkit/components/pdfjs/test/file_pdfjs_test.pdf b/toolkit/components/pdfjs/test/file_pdfjs_test.pdf
new file mode 100644
index 0000000000..7ad87e3c2e
--- /dev/null
+++ b/toolkit/components/pdfjs/test/file_pdfjs_test.pdf
Binary files differ
diff --git a/toolkit/components/pdfjs/test/file_pdfjs_transfer_map.pdf b/toolkit/components/pdfjs/test/file_pdfjs_transfer_map.pdf
new file mode 100644
index 0000000000..1b0c240881
--- /dev/null
+++ b/toolkit/components/pdfjs/test/file_pdfjs_transfer_map.pdf
Binary files differ
diff --git a/toolkit/components/pdfjs/test/head.js b/toolkit/components/pdfjs/test/head.js
new file mode 100644
index 0000000000..04c9543b5d
--- /dev/null
+++ b/toolkit/components/pdfjs/test/head.js
@@ -0,0 +1,428 @@
+async function waitForPdfJS(browser, url) {
+ // Runs tests after all "load" event handlers have fired off
+ let loadPromise = BrowserTestUtils.waitForContentEvent(
+ browser,
+ "documentloaded",
+ false,
+ null,
+ true
+ );
+ BrowserTestUtils.startLoadingURIString(browser, url);
+ return loadPromise;
+}
+
+async function waitForPdfJSAnnotationLayer(browser, url) {
+ let loadPromise = BrowserTestUtils.waitForContentEvent(
+ browser,
+ "annotationlayerrendered",
+ false,
+ null,
+ true
+ );
+ BrowserTestUtils.startLoadingURIString(browser, url);
+ return loadPromise;
+}
+
+async function waitForPdfJSAllLayers(browser, url, layers) {
+ let loadPromise = BrowserTestUtils.waitForContentEvent(
+ browser,
+ "textlayerrendered",
+ false,
+ null,
+ true
+ );
+ let annotationPromise = BrowserTestUtils.waitForContentEvent(
+ browser,
+ "annotationlayerrendered",
+ false,
+ null,
+ true
+ );
+ let annotationEditorPromise = BrowserTestUtils.waitForContentEvent(
+ browser,
+ "annotationeditorlayerrendered",
+ false,
+ null,
+ true
+ );
+
+ BrowserTestUtils.startLoadingURIString(browser, url);
+ await Promise.all([loadPromise, annotationPromise, annotationEditorPromise]);
+
+ await SpecialPowers.spawn(browser, [layers], async function (layers) {
+ const { ContentTaskUtils } = ChromeUtils.importESModule(
+ "resource://testing-common/ContentTaskUtils.sys.mjs"
+ );
+ const { document } = content;
+
+ for (let i = 0; i < layers.length; i++) {
+ await ContentTaskUtils.waitForCondition(
+ () =>
+ layers[i].every(
+ name =>
+ !!document.querySelector(
+ `.page[data-page-number='${i + 1}'] .${name}`
+ )
+ ),
+ `All the layers must be displayed on page ${i}`
+ );
+ }
+ });
+
+ await TestUtils.waitForTick();
+}
+
+async function waitForPdfJSCanvas(browser, url) {
+ let loadPromise = BrowserTestUtils.waitForContentEvent(
+ browser,
+ "pagerendered",
+ false,
+ null,
+ true
+ );
+ BrowserTestUtils.startLoadingURIString(browser, url);
+ return loadPromise;
+}
+
+async function waitForPdfJSSandbox(browser) {
+ let loadPromise = BrowserTestUtils.waitForContentEvent(
+ browser,
+ "sandboxcreated",
+ false,
+ null,
+ true
+ );
+ return loadPromise;
+}
+
+async function waitForSelector(browser, selector, message) {
+ return SpecialPowers.spawn(
+ browser,
+ [selector, message],
+ async function (sel, msg) {
+ const { ContentTaskUtils } = ChromeUtils.importESModule(
+ "resource://testing-common/ContentTaskUtils.sys.mjs"
+ );
+ const { document } = content;
+
+ await ContentTaskUtils.waitForCondition(
+ () => !!document.querySelector(sel),
+ `${sel} must be displayed`
+ );
+
+ await ContentTaskUtils.waitForCondition(
+ () => ContentTaskUtils.isVisible(document.querySelector(sel)),
+ msg
+ );
+ }
+ );
+}
+
+async function click(browser, selector) {
+ await waitForSelector(browser, selector);
+ await SpecialPowers.spawn(browser, [selector], async function (sel) {
+ const el = content.document.querySelector(sel);
+ await new Promise(r => {
+ el.addEventListener("click", r, { once: true });
+ el.click();
+ });
+ });
+}
+
+async function waitForTelemetry(browser) {
+ await BrowserTestUtils.waitForContentEvent(
+ browser,
+ "reporttelemetry",
+ false,
+ null,
+ true
+ );
+ await TestUtils.waitForTick();
+}
+
+/**
+ * Enable an editor (Ink, FreeText, ...).
+ * @param {Object} browser
+ * @param {string} name
+ */
+async function enableEditor(browser, name) {
+ const editingModePromise = BrowserTestUtils.waitForContentEvent(
+ browser,
+ "annotationeditormodechanged",
+ false,
+ null,
+ true
+ );
+ const editingStatePromise = BrowserTestUtils.waitForContentEvent(
+ browser,
+ "annotationeditorstateschanged",
+ false,
+ null,
+ true
+ );
+ await clickOn(browser, `#editor${name}`);
+ await editingModePromise;
+ await editingStatePromise;
+ await TestUtils.waitForTick();
+}
+
+/**
+ * The text layer contains some spans with the text of the pdf.
+ * @param {Object} browser
+ * @param {string} text
+ * @returns {Object} the bbox of the span containing the text.
+ */
+async function getSpanBox(browser, text, pageNumber = 1) {
+ return SpecialPowers.spawn(
+ browser,
+ [text, pageNumber],
+ async function (text, number) {
+ const { ContentTaskUtils } = ChromeUtils.importESModule(
+ "resource://testing-common/ContentTaskUtils.sys.mjs"
+ );
+ const { document } = content;
+
+ await ContentTaskUtils.waitForCondition(
+ () =>
+ !!document.querySelector(
+ `.page[data-page-number='${number}'] .textLayer .endOfContent`
+ ),
+ "The text layer must be displayed"
+ );
+
+ let targetSpan = null;
+ for (const span of document.querySelectorAll(
+ `.page[data-page-number='${number}'] .textLayer span`
+ )) {
+ if (span.innerText.includes(text)) {
+ targetSpan = span;
+ break;
+ }
+ }
+
+ Assert.ok(!!targetSpan, `document must have a span containing '${text}'`);
+
+ const { x, y, width, height } = targetSpan.getBoundingClientRect();
+ return { x, y, width, height };
+ }
+ );
+}
+
+/**
+ * Count the number of elements corresponding to the given selector.
+ * @param {Object} browser
+ * @param {string} selector
+ * @returns
+ */
+async function countElements(browser, selector) {
+ return SpecialPowers.spawn(browser, [selector], async function (selector) {
+ return new Promise(resolve => {
+ content.setTimeout(() => {
+ resolve(content.document.querySelectorAll(selector).length);
+ }, 0);
+ });
+ });
+}
+
+/**
+ * Click at the given coordinates.
+ * @param {Object} browser
+ * @param {number} x
+ * @param {number} y
+ * @param {number} n
+ */
+async function clickAt(browser, x, y, n = 1) {
+ await BrowserTestUtils.synthesizeMouseAtPoint(
+ x,
+ y,
+ {
+ type: "mousedown",
+ button: 0,
+ clickCount: n,
+ },
+ browser
+ );
+ await BrowserTestUtils.synthesizeMouseAtPoint(
+ x,
+ y,
+ {
+ type: "mouseup",
+ button: 0,
+ clickCount: n,
+ },
+ browser
+ );
+ await TestUtils.waitForTick();
+}
+
+/**
+ * Click on the element corresponding to the given selector.
+ * @param {Object} browser
+ * @param {string} selector
+ */
+async function clickOn(browser, selector) {
+ await waitForSelector(browser, selector);
+ const [x, y] = await SpecialPowers.spawn(
+ browser,
+ [selector],
+ async selector => {
+ const element = content.document.querySelector(selector);
+ Assert.ok(
+ !!element,
+ `Element "${selector}" must be available in order to be clicked`
+ );
+ const { x, y, width, height } = element.getBoundingClientRect();
+ return [x + width / 2, y + height / 2];
+ }
+ );
+ await clickAt(browser, x, y);
+}
+
+function focusEditorLayer(browser) {
+ return focus(browser, ".annotationEditorLayer");
+}
+
+/**
+ * Focus an element corresponding to the given selector.
+ * @param {Object} browser
+ * @param {string} selector
+ * @returns
+ */
+async function focus(browser, selector) {
+ return SpecialPowers.spawn(browser, [selector], function (sel) {
+ const el = content.document.querySelector(sel);
+ if (el === content.document.activeElement) {
+ return Promise.resolve();
+ }
+ const promise = new Promise(resolve => {
+ const listener = () => {
+ el.removeEventListener("focus", listener);
+ resolve();
+ };
+ el.addEventListener("focus", listener);
+ });
+ el.focus();
+ return promise;
+ });
+}
+
+/**
+ * Hit a key.
+ */
+async function hitKey(browser, char) {
+ await SpecialPowers.spawn(browser, [char], async function (char) {
+ const { ContentTaskUtils } = ChromeUtils.importESModule(
+ "resource://testing-common/ContentTaskUtils.sys.mjs"
+ );
+ const EventUtils = ContentTaskUtils.getEventUtils(content);
+ await EventUtils.synthesizeKey(char, {}, content);
+ });
+ await TestUtils.waitForTick();
+}
+
+/**
+ * Write some text using the keyboard.
+ * @param {Object} browser
+ * @param {string} text
+ */
+async function write(browser, text) {
+ for (const char of text.split("")) {
+ hitKey(browser, char);
+ }
+}
+
+/**
+ * Hit escape key.
+ */
+async function escape(browser) {
+ await hitKey(browser, "KEY_Escape");
+}
+
+/**
+ * Add a FreeText annotation and write some text inside.
+ * @param {Object} browser
+ * @param {string} text
+ * @param {Object} box
+ */
+async function addFreeText(browser, text, box) {
+ const { x, y, width, height } = box;
+ const count = await countElements(browser, ".freeTextEditor");
+ await focusEditorLayer(browser);
+ await clickAt(browser, x + 0.1 * width, y + 0.5 * height);
+ await waitForEditors(browser, ".freeTextEditor", count + 1);
+
+ await write(browser, text);
+ await escape(browser);
+}
+
+async function waitForEditors(browser, selector, count) {
+ await BrowserTestUtils.waitForCondition(
+ async () => (await countElements(browser, selector)) === count
+ );
+}
+
+function changeMimeHandler(preferredAction, alwaysAskBeforeHandling) {
+ let handlerService = Cc[
+ "@mozilla.org/uriloader/handler-service;1"
+ ].getService(Ci.nsIHandlerService);
+ let mimeService = Cc["@mozilla.org/mime;1"].getService(Ci.nsIMIMEService);
+ let handlerInfo = mimeService.getFromTypeAndExtension(
+ "application/pdf",
+ "pdf"
+ );
+ var oldAction = [
+ handlerInfo.preferredAction,
+ handlerInfo.alwaysAskBeforeHandling,
+ ];
+
+ // Change and save mime handler settings
+ handlerInfo.alwaysAskBeforeHandling = alwaysAskBeforeHandling;
+ handlerInfo.preferredAction = preferredAction;
+ handlerService.store(handlerInfo);
+
+ // Refresh data
+ handlerInfo = mimeService.getFromTypeAndExtension("application/pdf", "pdf");
+
+ // Test: Mime handler was updated
+ is(
+ handlerInfo.alwaysAskBeforeHandling,
+ alwaysAskBeforeHandling,
+ "always-ask prompt change successful"
+ );
+ is(
+ handlerInfo.preferredAction,
+ preferredAction,
+ "mime handler change successful"
+ );
+
+ return oldAction;
+}
+
+function createTemporarySaveDirectory(id = "") {
+ var saveDir = Services.dirsvc.get("TmpD", Ci.nsIFile);
+ saveDir.append(`testsavedir${id}`);
+ if (!saveDir.exists()) {
+ saveDir.create(Ci.nsIFile.DIRECTORY_TYPE, 0o755);
+ }
+ return saveDir;
+}
+
+async function cleanupDownloads(listId = Downloads.PUBLIC) {
+ info("cleaning up downloads");
+ let downloadList = await Downloads.getList(listId);
+ for (let download of await downloadList.getAll()) {
+ await download.finalize(true);
+ try {
+ if (Services.appinfo.OS === "WINNT") {
+ // We need to make the file writable to delete it on Windows.
+ await IOUtils.setPermissions(download.target.path, 0o600);
+ }
+ await IOUtils.remove(download.target.path);
+ } catch (error) {
+ info("The file " + download.target.path + " is not removed, " + error);
+ }
+
+ await downloadList.remove(download);
+ await download.finalize();
+ }
+}
diff --git a/toolkit/components/pdfjs/test/mochitest.toml b/toolkit/components/pdfjs/test/mochitest.toml
new file mode 100644
index 0000000000..52b40ce6f3
--- /dev/null
+++ b/toolkit/components/pdfjs/test/mochitest.toml
@@ -0,0 +1,7 @@
+[DEFAULT]
+
+["test_pdf_file_in_iframe.html"]
+skip-if = [
+ "os == 'android' && !nightly_build"
+]
+support-files = ["file_pdfjs_test.pdf"]
diff --git a/toolkit/components/pdfjs/test/moz.png b/toolkit/components/pdfjs/test/moz.png
new file mode 100644
index 0000000000..769c636340
--- /dev/null
+++ b/toolkit/components/pdfjs/test/moz.png
Binary files differ
diff --git a/toolkit/components/pdfjs/test/test_pdf_file_in_iframe.html b/toolkit/components/pdfjs/test/test_pdf_file_in_iframe.html
new file mode 100644
index 0000000000..81410c535f
--- /dev/null
+++ b/toolkit/components/pdfjs/test/test_pdf_file_in_iframe.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+ <meta charset="utf-8">
+ <title>PDFjs: Load a PDF in an iframe.</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+
+<body>
+ <pre id="test">
+ <script type="text/javascript">
+ "use strict";
+
+ async function test() {
+ await SpecialPowers.pushPrefEnv({
+ "set": [
+ ["pdfjs.disabled", false],
+ ["pdfjs.enableFloatingToolbar", false],
+ ],
+ });
+
+ const iframe = document.createElement("iframe");
+ document.body.append(iframe);
+ iframe.src = "file_pdfjs_test.pdf";
+ iframe.onload = async () => {
+ const hasViewerContainer = await SpecialPowers.spawn(
+ iframe.contentWindow,
+ [],
+ () => !!this.content.document.getElementById("viewerContainer")
+ );
+ ok(
+ hasViewerContainer,
+ "The iframe with a pdf must have a `viewerContainer`"
+ );
+ SimpleTest.finish();
+ };
+ }
+
+ window.onload = () => {
+ SimpleTest.waitForExplicitFinish();
+ test();
+ };
+ </script>
+ </pre>
+</body>
+
+</html>
diff --git a/toolkit/components/pdfjs/update.sh b/toolkit/components/pdfjs/update.sh
new file mode 100755
index 0000000000..3673f68784
--- /dev/null
+++ b/toolkit/components/pdfjs/update.sh
@@ -0,0 +1,49 @@
+#!/bin/bash
+
+set +vex
+
+if [ $# -lt 1 ]; then
+ echo update.sh "<revision to update to>"
+ exit 1
+fi
+
+if [ ! -f "$GECKO_PATH/mach" ]; then
+ echo "GECKO_PATH ($GECKO_PATH) does not appear to be a mozilla-central checkout"
+ exit 1
+fi
+
+if [ -v TASK_ID ]; then
+ # if we are running in taskcluster, then use the pre-obtained pdfjs checkout
+ export ROOT=/builds/worker/pdf.js
+elif [ -v PDFJS_CHECKOUT ]; then
+ export ROOT=$PDFJS_CHECKOUT
+else
+ PDFJS_TMPDIR="/tmp/pdfjs-$(date +%s)"
+ git clone https://github.com/mozilla/pdf.js "$PDFJS_TMPDIR"
+ export ROOT=$PDFJS_TMPDIR
+fi
+
+pushd "$ROOT" || exit
+git fetch origin
+git checkout "$1"
+
+npm install --legacy-peer-deps --ignore-scripts
+
+gulp mozcentral
+
+popd || exit
+
+
+mkdir -p "$ROOT/build/mozcentral/browser/extensions/pdfjs/"
+
+cp "$ROOT/build/mozcentral/browser/extensions/pdfjs/content/LICENSE" "$GECKO_PATH/toolkit/components/pdfjs/"
+cp "$ROOT/build/mozcentral/browser/extensions/pdfjs/content/PdfJsDefaultPreferences.sys.mjs" "$GECKO_PATH/toolkit/components/pdfjs/content/PdfJsDefaultPreferences.sys.mjs"
+rsync -a -v --delete "$ROOT/build/mozcentral/browser/extensions/pdfjs/content/build/" "$GECKO_PATH/toolkit/components/pdfjs/content/build/"
+rsync -a -v --delete "$ROOT/build/mozcentral/browser/extensions/pdfjs/content/web/" "$GECKO_PATH/toolkit/components/pdfjs/content/web/"
+
+ls -R "$ROOT/build/mozcentral/browser/"
+cp "$ROOT"/build/mozcentral/browser/locales/en-US/pdfviewer/*.ftl "$GECKO_PATH/toolkit/locales/en-US/toolkit/pdfviewer/" || true
+
+if [ -v PDFJS_TMPDIR ]; then
+ rm -rf "$PDFJS_TMPDIR"
+fi \ No newline at end of file