util.js 29 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192
  1. /* Copyright 2012 Mozilla Foundation
  2. *
  3. * Licensed under the Apache License, Version 2.0 (the "License");
  4. * you may not use this file except in compliance with the License.
  5. * You may obtain a copy of the License at
  6. *
  7. * http://www.apache.org/licenses/LICENSE-2.0
  8. *
  9. * Unless required by applicable law or agreed to in writing, software
  10. * distributed under the License is distributed on an "AS IS" BASIS,
  11. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. * See the License for the specific language governing permissions and
  13. * limitations under the License.
  14. */
  15. // Skip compatibility checks for modern builds and if we already ran the module.
  16. if (
  17. typeof PDFJSDev !== "undefined" &&
  18. !PDFJSDev.test("SKIP_BABEL") &&
  19. !globalThis._pdfjsCompatibilityChecked
  20. ) {
  21. globalThis._pdfjsCompatibilityChecked = true;
  22. require("./compatibility.js");
  23. }
  24. const IDENTITY_MATRIX = [1, 0, 0, 1, 0, 0];
  25. const FONT_IDENTITY_MATRIX = [0.001, 0, 0, 0.001, 0, 0];
  26. // Represent the percentage of the height of a single-line field over
  27. // the font size. Acrobat seems to use this value.
  28. const LINE_FACTOR = 1.35;
  29. const LINE_DESCENT_FACTOR = 0.35;
  30. const BASELINE_FACTOR = LINE_DESCENT_FACTOR / LINE_FACTOR;
  31. /**
  32. * Refer to the `WorkerTransport.getRenderingIntent`-method in the API, to see
  33. * how these flags are being used:
  34. * - ANY, DISPLAY, and PRINT are the normal rendering intents, note the
  35. * `PDFPageProxy.{render, getOperatorList, getAnnotations}`-methods.
  36. * - ANNOTATIONS_FORMS, ANNOTATIONS_STORAGE, ANNOTATIONS_DISABLE control which
  37. * annotations are rendered onto the canvas (i.e. by being included in the
  38. * operatorList), note the `PDFPageProxy.{render, getOperatorList}`-methods
  39. * and their `annotationMode`-option.
  40. * - OPLIST is used with the `PDFPageProxy.getOperatorList`-method, note the
  41. * `OperatorList`-constructor (on the worker-thread).
  42. */
  43. const RenderingIntentFlag = {
  44. ANY: 0x01,
  45. DISPLAY: 0x02,
  46. PRINT: 0x04,
  47. SAVE: 0x08,
  48. ANNOTATIONS_FORMS: 0x10,
  49. ANNOTATIONS_STORAGE: 0x20,
  50. ANNOTATIONS_DISABLE: 0x40,
  51. OPLIST: 0x100,
  52. };
  53. const AnnotationMode = {
  54. DISABLE: 0,
  55. ENABLE: 1,
  56. ENABLE_FORMS: 2,
  57. ENABLE_STORAGE: 3,
  58. };
  59. const AnnotationEditorPrefix = "pdfjs_internal_editor_";
  60. const AnnotationEditorType = {
  61. DISABLE: -1,
  62. NONE: 0,
  63. FREETEXT: 3,
  64. INK: 15,
  65. };
  66. const AnnotationEditorParamsType = {
  67. FREETEXT_SIZE: 1,
  68. FREETEXT_COLOR: 2,
  69. FREETEXT_OPACITY: 3,
  70. INK_COLOR: 11,
  71. INK_THICKNESS: 12,
  72. INK_OPACITY: 13,
  73. };
  74. // Permission flags from Table 22, Section 7.6.3.2 of the PDF specification.
  75. const PermissionFlag = {
  76. PRINT: 0x04,
  77. MODIFY_CONTENTS: 0x08,
  78. COPY: 0x10,
  79. MODIFY_ANNOTATIONS: 0x20,
  80. FILL_INTERACTIVE_FORMS: 0x100,
  81. COPY_FOR_ACCESSIBILITY: 0x200,
  82. ASSEMBLE: 0x400,
  83. PRINT_HIGH_QUALITY: 0x800,
  84. };
  85. const TextRenderingMode = {
  86. FILL: 0,
  87. STROKE: 1,
  88. FILL_STROKE: 2,
  89. INVISIBLE: 3,
  90. FILL_ADD_TO_PATH: 4,
  91. STROKE_ADD_TO_PATH: 5,
  92. FILL_STROKE_ADD_TO_PATH: 6,
  93. ADD_TO_PATH: 7,
  94. FILL_STROKE_MASK: 3,
  95. ADD_TO_PATH_FLAG: 4,
  96. };
  97. const ImageKind = {
  98. GRAYSCALE_1BPP: 1,
  99. RGB_24BPP: 2,
  100. RGBA_32BPP: 3,
  101. };
  102. const AnnotationType = {
  103. TEXT: 1,
  104. LINK: 2,
  105. FREETEXT: 3,
  106. LINE: 4,
  107. SQUARE: 5,
  108. CIRCLE: 6,
  109. POLYGON: 7,
  110. POLYLINE: 8,
  111. HIGHLIGHT: 9,
  112. UNDERLINE: 10,
  113. SQUIGGLY: 11,
  114. STRIKEOUT: 12,
  115. STAMP: 13,
  116. CARET: 14,
  117. INK: 15,
  118. POPUP: 16,
  119. FILEATTACHMENT: 17,
  120. SOUND: 18,
  121. MOVIE: 19,
  122. WIDGET: 20,
  123. SCREEN: 21,
  124. PRINTERMARK: 22,
  125. TRAPNET: 23,
  126. WATERMARK: 24,
  127. THREED: 25,
  128. REDACT: 26,
  129. };
  130. const AnnotationStateModelType = {
  131. MARKED: "Marked",
  132. REVIEW: "Review",
  133. };
  134. const AnnotationMarkedState = {
  135. MARKED: "Marked",
  136. UNMARKED: "Unmarked",
  137. };
  138. const AnnotationReviewState = {
  139. ACCEPTED: "Accepted",
  140. REJECTED: "Rejected",
  141. CANCELLED: "Cancelled",
  142. COMPLETED: "Completed",
  143. NONE: "None",
  144. };
  145. const AnnotationReplyType = {
  146. GROUP: "Group",
  147. REPLY: "R",
  148. };
  149. const AnnotationFlag = {
  150. INVISIBLE: 0x01,
  151. HIDDEN: 0x02,
  152. PRINT: 0x04,
  153. NOZOOM: 0x08,
  154. NOROTATE: 0x10,
  155. NOVIEW: 0x20,
  156. READONLY: 0x40,
  157. LOCKED: 0x80,
  158. TOGGLENOVIEW: 0x100,
  159. LOCKEDCONTENTS: 0x200,
  160. };
  161. const AnnotationFieldFlag = {
  162. READONLY: 0x0000001,
  163. REQUIRED: 0x0000002,
  164. NOEXPORT: 0x0000004,
  165. MULTILINE: 0x0001000,
  166. PASSWORD: 0x0002000,
  167. NOTOGGLETOOFF: 0x0004000,
  168. RADIO: 0x0008000,
  169. PUSHBUTTON: 0x0010000,
  170. COMBO: 0x0020000,
  171. EDIT: 0x0040000,
  172. SORT: 0x0080000,
  173. FILESELECT: 0x0100000,
  174. MULTISELECT: 0x0200000,
  175. DONOTSPELLCHECK: 0x0400000,
  176. DONOTSCROLL: 0x0800000,
  177. COMB: 0x1000000,
  178. RICHTEXT: 0x2000000,
  179. RADIOSINUNISON: 0x2000000,
  180. COMMITONSELCHANGE: 0x4000000,
  181. };
  182. const AnnotationBorderStyleType = {
  183. SOLID: 1,
  184. DASHED: 2,
  185. BEVELED: 3,
  186. INSET: 4,
  187. UNDERLINE: 5,
  188. };
  189. const AnnotationActionEventType = {
  190. E: "Mouse Enter",
  191. X: "Mouse Exit",
  192. D: "Mouse Down",
  193. U: "Mouse Up",
  194. Fo: "Focus",
  195. Bl: "Blur",
  196. PO: "PageOpen",
  197. PC: "PageClose",
  198. PV: "PageVisible",
  199. PI: "PageInvisible",
  200. K: "Keystroke",
  201. F: "Format",
  202. V: "Validate",
  203. C: "Calculate",
  204. };
  205. const DocumentActionEventType = {
  206. WC: "WillClose",
  207. WS: "WillSave",
  208. DS: "DidSave",
  209. WP: "WillPrint",
  210. DP: "DidPrint",
  211. };
  212. const PageActionEventType = {
  213. O: "PageOpen",
  214. C: "PageClose",
  215. };
  216. const StreamType = {
  217. UNKNOWN: "UNKNOWN",
  218. FLATE: "FLATE",
  219. LZW: "LZW",
  220. DCT: "DCT",
  221. JPX: "JPX",
  222. JBIG: "JBIG",
  223. A85: "A85",
  224. AHX: "AHX",
  225. CCF: "CCF",
  226. RLX: "RLX", // PDF short name is 'RL', but telemetry requires three chars.
  227. };
  228. const FontType = {
  229. UNKNOWN: "UNKNOWN",
  230. TYPE1: "TYPE1",
  231. TYPE1STANDARD: "TYPE1STANDARD",
  232. TYPE1C: "TYPE1C",
  233. CIDFONTTYPE0: "CIDFONTTYPE0",
  234. CIDFONTTYPE0C: "CIDFONTTYPE0C",
  235. TRUETYPE: "TRUETYPE",
  236. CIDFONTTYPE2: "CIDFONTTYPE2",
  237. TYPE3: "TYPE3",
  238. OPENTYPE: "OPENTYPE",
  239. TYPE0: "TYPE0",
  240. MMTYPE1: "MMTYPE1",
  241. };
  242. const VerbosityLevel = {
  243. ERRORS: 0,
  244. WARNINGS: 1,
  245. INFOS: 5,
  246. };
  247. const CMapCompressionType = {
  248. NONE: 0,
  249. BINARY: 1,
  250. };
  251. // All the possible operations for an operator list.
  252. const OPS = {
  253. // Intentionally start from 1 so it is easy to spot bad operators that will be
  254. // 0's.
  255. // PLEASE NOTE: We purposely keep any removed operators commented out, since
  256. // re-numbering the list would risk breaking third-party users.
  257. dependency: 1,
  258. setLineWidth: 2,
  259. setLineCap: 3,
  260. setLineJoin: 4,
  261. setMiterLimit: 5,
  262. setDash: 6,
  263. setRenderingIntent: 7,
  264. setFlatness: 8,
  265. setGState: 9,
  266. save: 10,
  267. restore: 11,
  268. transform: 12,
  269. moveTo: 13,
  270. lineTo: 14,
  271. curveTo: 15,
  272. curveTo2: 16,
  273. curveTo3: 17,
  274. closePath: 18,
  275. rectangle: 19,
  276. stroke: 20,
  277. closeStroke: 21,
  278. fill: 22,
  279. eoFill: 23,
  280. fillStroke: 24,
  281. eoFillStroke: 25,
  282. closeFillStroke: 26,
  283. closeEOFillStroke: 27,
  284. endPath: 28,
  285. clip: 29,
  286. eoClip: 30,
  287. beginText: 31,
  288. endText: 32,
  289. setCharSpacing: 33,
  290. setWordSpacing: 34,
  291. setHScale: 35,
  292. setLeading: 36,
  293. setFont: 37,
  294. setTextRenderingMode: 38,
  295. setTextRise: 39,
  296. moveText: 40,
  297. setLeadingMoveText: 41,
  298. setTextMatrix: 42,
  299. nextLine: 43,
  300. showText: 44,
  301. showSpacedText: 45,
  302. nextLineShowText: 46,
  303. nextLineSetSpacingShowText: 47,
  304. setCharWidth: 48,
  305. setCharWidthAndBounds: 49,
  306. setStrokeColorSpace: 50,
  307. setFillColorSpace: 51,
  308. setStrokeColor: 52,
  309. setStrokeColorN: 53,
  310. setFillColor: 54,
  311. setFillColorN: 55,
  312. setStrokeGray: 56,
  313. setFillGray: 57,
  314. setStrokeRGBColor: 58,
  315. setFillRGBColor: 59,
  316. setStrokeCMYKColor: 60,
  317. setFillCMYKColor: 61,
  318. shadingFill: 62,
  319. beginInlineImage: 63,
  320. beginImageData: 64,
  321. endInlineImage: 65,
  322. paintXObject: 66,
  323. markPoint: 67,
  324. markPointProps: 68,
  325. beginMarkedContent: 69,
  326. beginMarkedContentProps: 70,
  327. endMarkedContent: 71,
  328. beginCompat: 72,
  329. endCompat: 73,
  330. paintFormXObjectBegin: 74,
  331. paintFormXObjectEnd: 75,
  332. beginGroup: 76,
  333. endGroup: 77,
  334. // beginAnnotations: 78,
  335. // endAnnotations: 79,
  336. beginAnnotation: 80,
  337. endAnnotation: 81,
  338. // paintJpegXObject: 82,
  339. paintImageMaskXObject: 83,
  340. paintImageMaskXObjectGroup: 84,
  341. paintImageXObject: 85,
  342. paintInlineImageXObject: 86,
  343. paintInlineImageXObjectGroup: 87,
  344. paintImageXObjectRepeat: 88,
  345. paintImageMaskXObjectRepeat: 89,
  346. paintSolidColorImageMask: 90,
  347. constructPath: 91,
  348. };
  349. const UNSUPPORTED_FEATURES = {
  350. forms: "forms",
  351. javaScript: "javaScript",
  352. signatures: "signatures",
  353. smask: "smask",
  354. shadingPattern: "shadingPattern",
  355. errorTilingPattern: "errorTilingPattern",
  356. errorExtGState: "errorExtGState",
  357. errorXObject: "errorXObject",
  358. errorFontLoadType3: "errorFontLoadType3",
  359. errorFontState: "errorFontState",
  360. errorFontMissing: "errorFontMissing",
  361. errorFontTranslate: "errorFontTranslate",
  362. errorColorSpace: "errorColorSpace",
  363. errorOperatorList: "errorOperatorList",
  364. errorFontToUnicode: "errorFontToUnicode",
  365. errorFontLoadNative: "errorFontLoadNative",
  366. errorFontBuildPath: "errorFontBuildPath",
  367. errorFontGetPath: "errorFontGetPath",
  368. errorMarkedContent: "errorMarkedContent",
  369. errorContentSubStream: "errorContentSubStream",
  370. };
  371. const PasswordResponses = {
  372. NEED_PASSWORD: 1,
  373. INCORRECT_PASSWORD: 2,
  374. };
  375. let verbosity = VerbosityLevel.WARNINGS;
  376. function setVerbosityLevel(level) {
  377. if (Number.isInteger(level)) {
  378. verbosity = level;
  379. }
  380. }
  381. function getVerbosityLevel() {
  382. return verbosity;
  383. }
  384. // A notice for devs. These are good for things that are helpful to devs, such
  385. // as warning that Workers were disabled, which is important to devs but not
  386. // end users.
  387. function info(msg) {
  388. if (verbosity >= VerbosityLevel.INFOS) {
  389. console.log(`Info: ${msg}`);
  390. }
  391. }
  392. // Non-fatal warnings.
  393. function warn(msg) {
  394. if (verbosity >= VerbosityLevel.WARNINGS) {
  395. console.log(`Warning: ${msg}`);
  396. }
  397. }
  398. function unreachable(msg) {
  399. throw new Error(msg);
  400. }
  401. function assert(cond, msg) {
  402. if (!cond) {
  403. unreachable(msg);
  404. }
  405. }
  406. // Checks if URLs use one of the allowed protocols, e.g. to avoid XSS.
  407. function _isValidProtocol(url) {
  408. if (!url) {
  409. return false;
  410. }
  411. switch (url.protocol) {
  412. case "http:":
  413. case "https:":
  414. case "ftp:":
  415. case "mailto:":
  416. case "tel:":
  417. return true;
  418. default:
  419. return false;
  420. }
  421. }
  422. /**
  423. * Attempts to create a valid absolute URL.
  424. *
  425. * @param {URL|string} url - An absolute, or relative, URL.
  426. * @param {URL|string} [baseUrl] - An absolute URL.
  427. * @param {Object} [options]
  428. * @returns Either a valid {URL}, or `null` otherwise.
  429. */
  430. function createValidAbsoluteUrl(url, baseUrl = null, options = null) {
  431. if (!url) {
  432. return null;
  433. }
  434. try {
  435. if (options && typeof url === "string") {
  436. // Let URLs beginning with "www." default to using the "http://" protocol.
  437. if (options.addDefaultProtocol && url.startsWith("www.")) {
  438. const dots = url.match(/\./g);
  439. // Avoid accidentally matching a *relative* URL pointing to a file named
  440. // e.g. "www.pdf" or similar.
  441. if (dots && dots.length >= 2) {
  442. url = `http://${url}`;
  443. }
  444. }
  445. // According to ISO 32000-1:2008, section 12.6.4.7, URIs should be encoded
  446. // in 7-bit ASCII. Some bad PDFs use UTF-8 encoding; see bug 1122280.
  447. if (options.tryConvertEncoding) {
  448. try {
  449. url = stringToUTF8String(url);
  450. } catch (ex) {}
  451. }
  452. }
  453. const absoluteUrl = baseUrl ? new URL(url, baseUrl) : new URL(url);
  454. if (_isValidProtocol(absoluteUrl)) {
  455. return absoluteUrl;
  456. }
  457. } catch (ex) {
  458. /* `new URL()` will throw on incorrect data. */
  459. }
  460. return null;
  461. }
  462. function shadow(obj, prop, value, nonSerializable = false) {
  463. if (
  464. typeof PDFJSDev === "undefined" ||
  465. PDFJSDev.test("!PRODUCTION || TESTING")
  466. ) {
  467. assert(
  468. prop in obj,
  469. `shadow: Property "${prop && prop.toString()}" not found in object.`
  470. );
  471. }
  472. Object.defineProperty(obj, prop, {
  473. value,
  474. enumerable: !nonSerializable,
  475. configurable: true,
  476. writable: false,
  477. });
  478. return value;
  479. }
  480. /**
  481. * @type {any}
  482. */
  483. const BaseException = (function BaseExceptionClosure() {
  484. // eslint-disable-next-line no-shadow
  485. function BaseException(message, name) {
  486. if (this.constructor === BaseException) {
  487. unreachable("Cannot initialize BaseException.");
  488. }
  489. this.message = message;
  490. this.name = name;
  491. }
  492. BaseException.prototype = new Error();
  493. BaseException.constructor = BaseException;
  494. return BaseException;
  495. })();
  496. class PasswordException extends BaseException {
  497. constructor(msg, code) {
  498. super(msg, "PasswordException");
  499. this.code = code;
  500. }
  501. }
  502. class UnknownErrorException extends BaseException {
  503. constructor(msg, details) {
  504. super(msg, "UnknownErrorException");
  505. this.details = details;
  506. }
  507. }
  508. class InvalidPDFException extends BaseException {
  509. constructor(msg) {
  510. super(msg, "InvalidPDFException");
  511. }
  512. }
  513. class MissingPDFException extends BaseException {
  514. constructor(msg) {
  515. super(msg, "MissingPDFException");
  516. }
  517. }
  518. class UnexpectedResponseException extends BaseException {
  519. constructor(msg, status) {
  520. super(msg, "UnexpectedResponseException");
  521. this.status = status;
  522. }
  523. }
  524. /**
  525. * Error caused during parsing PDF data.
  526. */
  527. class FormatError extends BaseException {
  528. constructor(msg) {
  529. super(msg, "FormatError");
  530. }
  531. }
  532. /**
  533. * Error used to indicate task cancellation.
  534. */
  535. class AbortException extends BaseException {
  536. constructor(msg) {
  537. super(msg, "AbortException");
  538. }
  539. }
  540. function bytesToString(bytes) {
  541. if (
  542. typeof bytes !== "object" ||
  543. bytes === null ||
  544. bytes.length === undefined
  545. ) {
  546. unreachable("Invalid argument for bytesToString");
  547. }
  548. const length = bytes.length;
  549. const MAX_ARGUMENT_COUNT = 8192;
  550. if (length < MAX_ARGUMENT_COUNT) {
  551. return String.fromCharCode.apply(null, bytes);
  552. }
  553. const strBuf = [];
  554. for (let i = 0; i < length; i += MAX_ARGUMENT_COUNT) {
  555. const chunkEnd = Math.min(i + MAX_ARGUMENT_COUNT, length);
  556. const chunk = bytes.subarray(i, chunkEnd);
  557. strBuf.push(String.fromCharCode.apply(null, chunk));
  558. }
  559. return strBuf.join("");
  560. }
  561. function stringToBytes(str) {
  562. if (typeof str !== "string") {
  563. unreachable("Invalid argument for stringToBytes");
  564. }
  565. const length = str.length;
  566. const bytes = new Uint8Array(length);
  567. for (let i = 0; i < length; ++i) {
  568. bytes[i] = str.charCodeAt(i) & 0xff;
  569. }
  570. return bytes;
  571. }
  572. /**
  573. * Gets length of the array (Array, Uint8Array, or string) in bytes.
  574. * @param {Array<any>|Uint8Array|string} arr
  575. * @returns {number}
  576. */
  577. // eslint-disable-next-line consistent-return
  578. function arrayByteLength(arr) {
  579. if (arr.length !== undefined) {
  580. return arr.length;
  581. }
  582. if (arr.byteLength !== undefined) {
  583. return arr.byteLength;
  584. }
  585. unreachable("Invalid argument for arrayByteLength");
  586. }
  587. /**
  588. * Combines array items (arrays) into single Uint8Array object.
  589. * @param {Array<Array<any>|Uint8Array|string>} arr - the array of the arrays
  590. * (Array, Uint8Array, or string).
  591. * @returns {Uint8Array}
  592. */
  593. function arraysToBytes(arr) {
  594. const length = arr.length;
  595. // Shortcut: if first and only item is Uint8Array, return it.
  596. if (length === 1 && arr[0] instanceof Uint8Array) {
  597. return arr[0];
  598. }
  599. let resultLength = 0;
  600. for (let i = 0; i < length; i++) {
  601. resultLength += arrayByteLength(arr[i]);
  602. }
  603. let pos = 0;
  604. const data = new Uint8Array(resultLength);
  605. for (let i = 0; i < length; i++) {
  606. let item = arr[i];
  607. if (!(item instanceof Uint8Array)) {
  608. if (typeof item === "string") {
  609. item = stringToBytes(item);
  610. } else {
  611. item = new Uint8Array(item);
  612. }
  613. }
  614. const itemLength = item.byteLength;
  615. data.set(item, pos);
  616. pos += itemLength;
  617. }
  618. return data;
  619. }
  620. function string32(value) {
  621. if (
  622. typeof PDFJSDev === "undefined" ||
  623. PDFJSDev.test("!PRODUCTION || TESTING")
  624. ) {
  625. assert(
  626. typeof value === "number" && Math.abs(value) < 2 ** 32,
  627. `string32: Unexpected input "${value}".`
  628. );
  629. }
  630. return String.fromCharCode(
  631. (value >> 24) & 0xff,
  632. (value >> 16) & 0xff,
  633. (value >> 8) & 0xff,
  634. value & 0xff
  635. );
  636. }
  637. function objectSize(obj) {
  638. return Object.keys(obj).length;
  639. }
  640. // Ensure that the returned Object has a `null` prototype; hence why
  641. // `Object.fromEntries(...)` is not used.
  642. function objectFromMap(map) {
  643. const obj = Object.create(null);
  644. for (const [key, value] of map) {
  645. obj[key] = value;
  646. }
  647. return obj;
  648. }
  649. // Checks the endianness of the platform.
  650. function isLittleEndian() {
  651. const buffer8 = new Uint8Array(4);
  652. buffer8[0] = 1;
  653. const view32 = new Uint32Array(buffer8.buffer, 0, 1);
  654. return view32[0] === 1;
  655. }
  656. // Checks if it's possible to eval JS expressions.
  657. function isEvalSupported() {
  658. try {
  659. new Function(""); // eslint-disable-line no-new, no-new-func
  660. return true;
  661. } catch (e) {
  662. return false;
  663. }
  664. }
  665. class FeatureTest {
  666. static get isLittleEndian() {
  667. return shadow(this, "isLittleEndian", isLittleEndian());
  668. }
  669. static get isEvalSupported() {
  670. return shadow(this, "isEvalSupported", isEvalSupported());
  671. }
  672. static get isOffscreenCanvasSupported() {
  673. return shadow(
  674. this,
  675. "isOffscreenCanvasSupported",
  676. typeof OffscreenCanvas !== "undefined"
  677. );
  678. }
  679. static get platform() {
  680. if (
  681. (typeof PDFJSDev === "undefined" || PDFJSDev.test("GENERIC")) &&
  682. typeof navigator === "undefined"
  683. ) {
  684. return shadow(this, "platform", { isWin: false, isMac: false });
  685. }
  686. return shadow(this, "platform", {
  687. isWin: navigator.platform.includes("Win"),
  688. isMac: navigator.platform.includes("Mac"),
  689. });
  690. }
  691. }
  692. const hexNumbers = [...Array(256).keys()].map(n =>
  693. n.toString(16).padStart(2, "0")
  694. );
  695. class Util {
  696. static makeHexColor(r, g, b) {
  697. return `#${hexNumbers[r]}${hexNumbers[g]}${hexNumbers[b]}`;
  698. }
  699. // Apply a scaling matrix to some min/max values.
  700. // If a scaling factor is negative then min and max must be
  701. // swaped.
  702. static scaleMinMax(transform, minMax) {
  703. let temp;
  704. if (transform[0]) {
  705. if (transform[0] < 0) {
  706. temp = minMax[0];
  707. minMax[0] = minMax[1];
  708. minMax[1] = temp;
  709. }
  710. minMax[0] *= transform[0];
  711. minMax[1] *= transform[0];
  712. if (transform[3] < 0) {
  713. temp = minMax[2];
  714. minMax[2] = minMax[3];
  715. minMax[3] = temp;
  716. }
  717. minMax[2] *= transform[3];
  718. minMax[3] *= transform[3];
  719. } else {
  720. temp = minMax[0];
  721. minMax[0] = minMax[2];
  722. minMax[2] = temp;
  723. temp = minMax[1];
  724. minMax[1] = minMax[3];
  725. minMax[3] = temp;
  726. if (transform[1] < 0) {
  727. temp = minMax[2];
  728. minMax[2] = minMax[3];
  729. minMax[3] = temp;
  730. }
  731. minMax[2] *= transform[1];
  732. minMax[3] *= transform[1];
  733. if (transform[2] < 0) {
  734. temp = minMax[0];
  735. minMax[0] = minMax[1];
  736. minMax[1] = temp;
  737. }
  738. minMax[0] *= transform[2];
  739. minMax[1] *= transform[2];
  740. }
  741. minMax[0] += transform[4];
  742. minMax[1] += transform[4];
  743. minMax[2] += transform[5];
  744. minMax[3] += transform[5];
  745. }
  746. // Concatenates two transformation matrices together and returns the result.
  747. static transform(m1, m2) {
  748. return [
  749. m1[0] * m2[0] + m1[2] * m2[1],
  750. m1[1] * m2[0] + m1[3] * m2[1],
  751. m1[0] * m2[2] + m1[2] * m2[3],
  752. m1[1] * m2[2] + m1[3] * m2[3],
  753. m1[0] * m2[4] + m1[2] * m2[5] + m1[4],
  754. m1[1] * m2[4] + m1[3] * m2[5] + m1[5],
  755. ];
  756. }
  757. // For 2d affine transforms
  758. static applyTransform(p, m) {
  759. const xt = p[0] * m[0] + p[1] * m[2] + m[4];
  760. const yt = p[0] * m[1] + p[1] * m[3] + m[5];
  761. return [xt, yt];
  762. }
  763. static applyInverseTransform(p, m) {
  764. const d = m[0] * m[3] - m[1] * m[2];
  765. const xt = (p[0] * m[3] - p[1] * m[2] + m[2] * m[5] - m[4] * m[3]) / d;
  766. const yt = (-p[0] * m[1] + p[1] * m[0] + m[4] * m[1] - m[5] * m[0]) / d;
  767. return [xt, yt];
  768. }
  769. // Applies the transform to the rectangle and finds the minimum axially
  770. // aligned bounding box.
  771. static getAxialAlignedBoundingBox(r, m) {
  772. const p1 = Util.applyTransform(r, m);
  773. const p2 = Util.applyTransform(r.slice(2, 4), m);
  774. const p3 = Util.applyTransform([r[0], r[3]], m);
  775. const p4 = Util.applyTransform([r[2], r[1]], m);
  776. return [
  777. Math.min(p1[0], p2[0], p3[0], p4[0]),
  778. Math.min(p1[1], p2[1], p3[1], p4[1]),
  779. Math.max(p1[0], p2[0], p3[0], p4[0]),
  780. Math.max(p1[1], p2[1], p3[1], p4[1]),
  781. ];
  782. }
  783. static inverseTransform(m) {
  784. const d = m[0] * m[3] - m[1] * m[2];
  785. return [
  786. m[3] / d,
  787. -m[1] / d,
  788. -m[2] / d,
  789. m[0] / d,
  790. (m[2] * m[5] - m[4] * m[3]) / d,
  791. (m[4] * m[1] - m[5] * m[0]) / d,
  792. ];
  793. }
  794. // This calculation uses Singular Value Decomposition.
  795. // The SVD can be represented with formula A = USV. We are interested in the
  796. // matrix S here because it represents the scale values.
  797. static singularValueDecompose2dScale(m) {
  798. const transpose = [m[0], m[2], m[1], m[3]];
  799. // Multiply matrix m with its transpose.
  800. const a = m[0] * transpose[0] + m[1] * transpose[2];
  801. const b = m[0] * transpose[1] + m[1] * transpose[3];
  802. const c = m[2] * transpose[0] + m[3] * transpose[2];
  803. const d = m[2] * transpose[1] + m[3] * transpose[3];
  804. // Solve the second degree polynomial to get roots.
  805. const first = (a + d) / 2;
  806. const second = Math.sqrt((a + d) ** 2 - 4 * (a * d - c * b)) / 2;
  807. const sx = first + second || 1;
  808. const sy = first - second || 1;
  809. // Scale values are the square roots of the eigenvalues.
  810. return [Math.sqrt(sx), Math.sqrt(sy)];
  811. }
  812. // Normalize rectangle rect=[x1, y1, x2, y2] so that (x1,y1) < (x2,y2)
  813. // For coordinate systems whose origin lies in the bottom-left, this
  814. // means normalization to (BL,TR) ordering. For systems with origin in the
  815. // top-left, this means (TL,BR) ordering.
  816. static normalizeRect(rect) {
  817. const r = rect.slice(0); // clone rect
  818. if (rect[0] > rect[2]) {
  819. r[0] = rect[2];
  820. r[2] = rect[0];
  821. }
  822. if (rect[1] > rect[3]) {
  823. r[1] = rect[3];
  824. r[3] = rect[1];
  825. }
  826. return r;
  827. }
  828. // Returns a rectangle [x1, y1, x2, y2] corresponding to the
  829. // intersection of rect1 and rect2. If no intersection, returns 'null'
  830. // The rectangle coordinates of rect1, rect2 should be [x1, y1, x2, y2]
  831. static intersect(rect1, rect2) {
  832. const xLow = Math.max(
  833. Math.min(rect1[0], rect1[2]),
  834. Math.min(rect2[0], rect2[2])
  835. );
  836. const xHigh = Math.min(
  837. Math.max(rect1[0], rect1[2]),
  838. Math.max(rect2[0], rect2[2])
  839. );
  840. if (xLow > xHigh) {
  841. return null;
  842. }
  843. const yLow = Math.max(
  844. Math.min(rect1[1], rect1[3]),
  845. Math.min(rect2[1], rect2[3])
  846. );
  847. const yHigh = Math.min(
  848. Math.max(rect1[1], rect1[3]),
  849. Math.max(rect2[1], rect2[3])
  850. );
  851. if (yLow > yHigh) {
  852. return null;
  853. }
  854. return [xLow, yLow, xHigh, yHigh];
  855. }
  856. // From https://github.com/adobe-webplatform/Snap.svg/blob/b365287722a72526000ac4bfcf0ce4cac2faa015/src/path.js#L852
  857. static bezierBoundingBox(x0, y0, x1, y1, x2, y2, x3, y3) {
  858. const tvalues = [],
  859. bounds = [[], []];
  860. let a, b, c, t, t1, t2, b2ac, sqrtb2ac;
  861. for (let i = 0; i < 2; ++i) {
  862. if (i === 0) {
  863. b = 6 * x0 - 12 * x1 + 6 * x2;
  864. a = -3 * x0 + 9 * x1 - 9 * x2 + 3 * x3;
  865. c = 3 * x1 - 3 * x0;
  866. } else {
  867. b = 6 * y0 - 12 * y1 + 6 * y2;
  868. a = -3 * y0 + 9 * y1 - 9 * y2 + 3 * y3;
  869. c = 3 * y1 - 3 * y0;
  870. }
  871. if (Math.abs(a) < 1e-12) {
  872. if (Math.abs(b) < 1e-12) {
  873. continue;
  874. }
  875. t = -c / b;
  876. if (0 < t && t < 1) {
  877. tvalues.push(t);
  878. }
  879. continue;
  880. }
  881. b2ac = b * b - 4 * c * a;
  882. sqrtb2ac = Math.sqrt(b2ac);
  883. if (b2ac < 0) {
  884. continue;
  885. }
  886. t1 = (-b + sqrtb2ac) / (2 * a);
  887. if (0 < t1 && t1 < 1) {
  888. tvalues.push(t1);
  889. }
  890. t2 = (-b - sqrtb2ac) / (2 * a);
  891. if (0 < t2 && t2 < 1) {
  892. tvalues.push(t2);
  893. }
  894. }
  895. let j = tvalues.length,
  896. mt;
  897. const jlen = j;
  898. while (j--) {
  899. t = tvalues[j];
  900. mt = 1 - t;
  901. bounds[0][j] =
  902. mt * mt * mt * x0 +
  903. 3 * mt * mt * t * x1 +
  904. 3 * mt * t * t * x2 +
  905. t * t * t * x3;
  906. bounds[1][j] =
  907. mt * mt * mt * y0 +
  908. 3 * mt * mt * t * y1 +
  909. 3 * mt * t * t * y2 +
  910. t * t * t * y3;
  911. }
  912. bounds[0][jlen] = x0;
  913. bounds[1][jlen] = y0;
  914. bounds[0][jlen + 1] = x3;
  915. bounds[1][jlen + 1] = y3;
  916. bounds[0].length = bounds[1].length = jlen + 2;
  917. return [
  918. Math.min(...bounds[0]),
  919. Math.min(...bounds[1]),
  920. Math.max(...bounds[0]),
  921. Math.max(...bounds[1]),
  922. ];
  923. }
  924. }
  925. const PDFStringTranslateTable = [
  926. 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,
  927. 0x2c7, 0x2c6, 0x2d9, 0x2dd, 0x2db, 0x2da, 0x2dc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  928. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  929. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  930. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  931. 0, 0, 0, 0, 0, 0, 0, 0, 0x2022, 0x2020, 0x2021, 0x2026, 0x2014, 0x2013, 0x192,
  932. 0x2044, 0x2039, 0x203a, 0x2212, 0x2030, 0x201e, 0x201c, 0x201d, 0x2018,
  933. 0x2019, 0x201a, 0x2122, 0xfb01, 0xfb02, 0x141, 0x152, 0x160, 0x178, 0x17d,
  934. 0x131, 0x142, 0x153, 0x161, 0x17e, 0, 0x20ac,
  935. ];
  936. function stringToPDFString(str) {
  937. if (str[0] >= "\xEF") {
  938. let encoding;
  939. if (str[0] === "\xFE" && str[1] === "\xFF") {
  940. encoding = "utf-16be";
  941. } else if (str[0] === "\xFF" && str[1] === "\xFE") {
  942. encoding = "utf-16le";
  943. } else if (str[0] === "\xEF" && str[1] === "\xBB" && str[2] === "\xBF") {
  944. encoding = "utf-8";
  945. }
  946. if (encoding) {
  947. try {
  948. const decoder = new TextDecoder(encoding, { fatal: true });
  949. const buffer = stringToBytes(str);
  950. return decoder.decode(buffer);
  951. } catch (ex) {
  952. warn(`stringToPDFString: "${ex}".`);
  953. }
  954. }
  955. }
  956. // ISO Latin 1
  957. const strBuf = [];
  958. for (let i = 0, ii = str.length; i < ii; i++) {
  959. const code = PDFStringTranslateTable[str.charCodeAt(i)];
  960. strBuf.push(code ? String.fromCharCode(code) : str.charAt(i));
  961. }
  962. return strBuf.join("");
  963. }
  964. function stringToUTF8String(str) {
  965. return decodeURIComponent(escape(str));
  966. }
  967. function utf8StringToString(str) {
  968. return unescape(encodeURIComponent(str));
  969. }
  970. function isArrayBuffer(v) {
  971. return typeof v === "object" && v !== null && v.byteLength !== undefined;
  972. }
  973. function isArrayEqual(arr1, arr2) {
  974. if (arr1.length !== arr2.length) {
  975. return false;
  976. }
  977. for (let i = 0, ii = arr1.length; i < ii; i++) {
  978. if (arr1[i] !== arr2[i]) {
  979. return false;
  980. }
  981. }
  982. return true;
  983. }
  984. function getModificationDate(date = new Date()) {
  985. const buffer = [
  986. date.getUTCFullYear().toString(),
  987. (date.getUTCMonth() + 1).toString().padStart(2, "0"),
  988. date.getUTCDate().toString().padStart(2, "0"),
  989. date.getUTCHours().toString().padStart(2, "0"),
  990. date.getUTCMinutes().toString().padStart(2, "0"),
  991. date.getUTCSeconds().toString().padStart(2, "0"),
  992. ];
  993. return buffer.join("");
  994. }
  995. /**
  996. * Promise Capability object.
  997. *
  998. * @typedef {Object} PromiseCapability
  999. * @property {Promise<any>} promise - A Promise object.
  1000. * @property {boolean} settled - If the Promise has been fulfilled/rejected.
  1001. * @property {function} resolve - Fulfills the Promise.
  1002. * @property {function} reject - Rejects the Promise.
  1003. */
  1004. /**
  1005. * Creates a promise capability object.
  1006. * @alias createPromiseCapability
  1007. *
  1008. * @returns {PromiseCapability}
  1009. */
  1010. function createPromiseCapability() {
  1011. const capability = Object.create(null);
  1012. let isSettled = false;
  1013. Object.defineProperty(capability, "settled", {
  1014. get() {
  1015. return isSettled;
  1016. },
  1017. });
  1018. capability.promise = new Promise(function (resolve, reject) {
  1019. capability.resolve = function (data) {
  1020. isSettled = true;
  1021. resolve(data);
  1022. };
  1023. capability.reject = function (reason) {
  1024. isSettled = true;
  1025. reject(reason);
  1026. };
  1027. });
  1028. return capability;
  1029. }
  1030. export {
  1031. AbortException,
  1032. AnnotationActionEventType,
  1033. AnnotationBorderStyleType,
  1034. AnnotationEditorParamsType,
  1035. AnnotationEditorPrefix,
  1036. AnnotationEditorType,
  1037. AnnotationFieldFlag,
  1038. AnnotationFlag,
  1039. AnnotationMarkedState,
  1040. AnnotationMode,
  1041. AnnotationReplyType,
  1042. AnnotationReviewState,
  1043. AnnotationStateModelType,
  1044. AnnotationType,
  1045. arrayByteLength,
  1046. arraysToBytes,
  1047. assert,
  1048. BaseException,
  1049. BASELINE_FACTOR,
  1050. bytesToString,
  1051. CMapCompressionType,
  1052. createPromiseCapability,
  1053. createValidAbsoluteUrl,
  1054. DocumentActionEventType,
  1055. FeatureTest,
  1056. FONT_IDENTITY_MATRIX,
  1057. FontType,
  1058. FormatError,
  1059. getModificationDate,
  1060. getVerbosityLevel,
  1061. IDENTITY_MATRIX,
  1062. ImageKind,
  1063. info,
  1064. InvalidPDFException,
  1065. isArrayBuffer,
  1066. isArrayEqual,
  1067. LINE_DESCENT_FACTOR,
  1068. LINE_FACTOR,
  1069. MissingPDFException,
  1070. objectFromMap,
  1071. objectSize,
  1072. OPS,
  1073. PageActionEventType,
  1074. PasswordException,
  1075. PasswordResponses,
  1076. PermissionFlag,
  1077. RenderingIntentFlag,
  1078. setVerbosityLevel,
  1079. shadow,
  1080. StreamType,
  1081. string32,
  1082. stringToBytes,
  1083. stringToPDFString,
  1084. stringToUTF8String,
  1085. TextRenderingMode,
  1086. UnexpectedResponseException,
  1087. UnknownErrorException,
  1088. unreachable,
  1089. UNSUPPORTED_FEATURES,
  1090. utf8StringToString,
  1091. Util,
  1092. VerbosityLevel,
  1093. warn,
  1094. };