Source: shared/util.js

  1. /* Copyright 2012 Mozilla Foundation
  2. *
  3. * Licensed under the Apache License, Version 2.0 (the "License");
  4. * you may not use this file except in compliance with the License.
  5. * You may obtain a copy of the License at
  6. *
  7. * http://www.apache.org/licenses/LICENSE-2.0
  8. *
  9. * Unless required by applicable law or agreed to in writing, software
  10. * distributed under the License is distributed on an "AS IS" BASIS,
  11. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. * See the License for the specific language governing permissions and
  13. * limitations under the License.
  14. */
  15. /* globals global, process, __pdfjsdev_webpack__ */
  16. import './compatibility';
  17. import { ReadableStream } from '../../external/streams/streams-lib';
  18. var globalScope = (typeof window !== 'undefined') ? window :
  19. (typeof global !== 'undefined') ? global :
  20. (typeof self !== 'undefined') ? self : this;
  21. var FONT_IDENTITY_MATRIX = [0.001, 0, 0, 0.001, 0, 0];
  22. const NativeImageDecoding = {
  23. NONE: 'none',
  24. DECODE: 'decode',
  25. DISPLAY: 'display',
  26. };
  27. var TextRenderingMode = {
  28. FILL: 0,
  29. STROKE: 1,
  30. FILL_STROKE: 2,
  31. INVISIBLE: 3,
  32. FILL_ADD_TO_PATH: 4,
  33. STROKE_ADD_TO_PATH: 5,
  34. FILL_STROKE_ADD_TO_PATH: 6,
  35. ADD_TO_PATH: 7,
  36. FILL_STROKE_MASK: 3,
  37. ADD_TO_PATH_FLAG: 4,
  38. };
  39. var ImageKind = {
  40. GRAYSCALE_1BPP: 1,
  41. RGB_24BPP: 2,
  42. RGBA_32BPP: 3,
  43. };
  44. var AnnotationType = {
  45. TEXT: 1,
  46. LINK: 2,
  47. FREETEXT: 3,
  48. LINE: 4,
  49. SQUARE: 5,
  50. CIRCLE: 6,
  51. POLYGON: 7,
  52. POLYLINE: 8,
  53. HIGHLIGHT: 9,
  54. UNDERLINE: 10,
  55. SQUIGGLY: 11,
  56. STRIKEOUT: 12,
  57. STAMP: 13,
  58. CARET: 14,
  59. INK: 15,
  60. POPUP: 16,
  61. FILEATTACHMENT: 17,
  62. SOUND: 18,
  63. MOVIE: 19,
  64. WIDGET: 20,
  65. SCREEN: 21,
  66. PRINTERMARK: 22,
  67. TRAPNET: 23,
  68. WATERMARK: 24,
  69. THREED: 25,
  70. REDACT: 26,
  71. };
  72. var AnnotationFlag = {
  73. INVISIBLE: 0x01,
  74. HIDDEN: 0x02,
  75. PRINT: 0x04,
  76. NOZOOM: 0x08,
  77. NOROTATE: 0x10,
  78. NOVIEW: 0x20,
  79. READONLY: 0x40,
  80. LOCKED: 0x80,
  81. TOGGLENOVIEW: 0x100,
  82. LOCKEDCONTENTS: 0x200,
  83. };
  84. var AnnotationFieldFlag = {
  85. READONLY: 0x0000001,
  86. REQUIRED: 0x0000002,
  87. NOEXPORT: 0x0000004,
  88. MULTILINE: 0x0001000,
  89. PASSWORD: 0x0002000,
  90. NOTOGGLETOOFF: 0x0004000,
  91. RADIO: 0x0008000,
  92. PUSHBUTTON: 0x0010000,
  93. COMBO: 0x0020000,
  94. EDIT: 0x0040000,
  95. SORT: 0x0080000,
  96. FILESELECT: 0x0100000,
  97. MULTISELECT: 0x0200000,
  98. DONOTSPELLCHECK: 0x0400000,
  99. DONOTSCROLL: 0x0800000,
  100. COMB: 0x1000000,
  101. RICHTEXT: 0x2000000,
  102. RADIOSINUNISON: 0x2000000,
  103. COMMITONSELCHANGE: 0x4000000,
  104. };
  105. var AnnotationBorderStyleType = {
  106. SOLID: 1,
  107. DASHED: 2,
  108. BEVELED: 3,
  109. INSET: 4,
  110. UNDERLINE: 5,
  111. };
  112. var StreamType = {
  113. UNKNOWN: 0,
  114. FLATE: 1,
  115. LZW: 2,
  116. DCT: 3,
  117. JPX: 4,
  118. JBIG: 5,
  119. A85: 6,
  120. AHX: 7,
  121. CCF: 8,
  122. RL: 9,
  123. };
  124. var FontType = {
  125. UNKNOWN: 0,
  126. TYPE1: 1,
  127. TYPE1C: 2,
  128. CIDFONTTYPE0: 3,
  129. CIDFONTTYPE0C: 4,
  130. TRUETYPE: 5,
  131. CIDFONTTYPE2: 6,
  132. TYPE3: 7,
  133. OPENTYPE: 8,
  134. TYPE0: 9,
  135. MMTYPE1: 10,
  136. };
  137. var VERBOSITY_LEVELS = {
  138. errors: 0,
  139. warnings: 1,
  140. infos: 5,
  141. };
  142. var CMapCompressionType = {
  143. NONE: 0,
  144. BINARY: 1,
  145. STREAM: 2,
  146. };
  147. // All the possible operations for an operator list.
  148. var OPS = {
  149. // Intentionally start from 1 so it is easy to spot bad operators that will be
  150. // 0's.
  151. dependency: 1,
  152. setLineWidth: 2,
  153. setLineCap: 3,
  154. setLineJoin: 4,
  155. setMiterLimit: 5,
  156. setDash: 6,
  157. setRenderingIntent: 7,
  158. setFlatness: 8,
  159. setGState: 9,
  160. save: 10,
  161. restore: 11,
  162. transform: 12,
  163. moveTo: 13,
  164. lineTo: 14,
  165. curveTo: 15,
  166. curveTo2: 16,
  167. curveTo3: 17,
  168. closePath: 18,
  169. rectangle: 19,
  170. stroke: 20,
  171. closeStroke: 21,
  172. fill: 22,
  173. eoFill: 23,
  174. fillStroke: 24,
  175. eoFillStroke: 25,
  176. closeFillStroke: 26,
  177. closeEOFillStroke: 27,
  178. endPath: 28,
  179. clip: 29,
  180. eoClip: 30,
  181. beginText: 31,
  182. endText: 32,
  183. setCharSpacing: 33,
  184. setWordSpacing: 34,
  185. setHScale: 35,
  186. setLeading: 36,
  187. setFont: 37,
  188. setTextRenderingMode: 38,
  189. setTextRise: 39,
  190. moveText: 40,
  191. setLeadingMoveText: 41,
  192. setTextMatrix: 42,
  193. nextLine: 43,
  194. showText: 44,
  195. showSpacedText: 45,
  196. nextLineShowText: 46,
  197. nextLineSetSpacingShowText: 47,
  198. setCharWidth: 48,
  199. setCharWidthAndBounds: 49,
  200. setStrokeColorSpace: 50,
  201. setFillColorSpace: 51,
  202. setStrokeColor: 52,
  203. setStrokeColorN: 53,
  204. setFillColor: 54,
  205. setFillColorN: 55,
  206. setStrokeGray: 56,
  207. setFillGray: 57,
  208. setStrokeRGBColor: 58,
  209. setFillRGBColor: 59,
  210. setStrokeCMYKColor: 60,
  211. setFillCMYKColor: 61,
  212. shadingFill: 62,
  213. beginInlineImage: 63,
  214. beginImageData: 64,
  215. endInlineImage: 65,
  216. paintXObject: 66,
  217. markPoint: 67,
  218. markPointProps: 68,
  219. beginMarkedContent: 69,
  220. beginMarkedContentProps: 70,
  221. endMarkedContent: 71,
  222. beginCompat: 72,
  223. endCompat: 73,
  224. paintFormXObjectBegin: 74,
  225. paintFormXObjectEnd: 75,
  226. beginGroup: 76,
  227. endGroup: 77,
  228. beginAnnotations: 78,
  229. endAnnotations: 79,
  230. beginAnnotation: 80,
  231. endAnnotation: 81,
  232. paintJpegXObject: 82,
  233. paintImageMaskXObject: 83,
  234. paintImageMaskXObjectGroup: 84,
  235. paintImageXObject: 85,
  236. paintInlineImageXObject: 86,
  237. paintInlineImageXObjectGroup: 87,
  238. paintImageXObjectRepeat: 88,
  239. paintImageMaskXObjectRepeat: 89,
  240. paintSolidColorImageMask: 90,
  241. constructPath: 91,
  242. };
  243. var verbosity = VERBOSITY_LEVELS.warnings;
  244. function setVerbosityLevel(level) {
  245. verbosity = level;
  246. }
  247. function getVerbosityLevel() {
  248. return verbosity;
  249. }
  250. // A notice for devs. These are good for things that are helpful to devs, such
  251. // as warning that Workers were disabled, which is important to devs but not
  252. // end users.
  253. function info(msg) {
  254. if (verbosity >= VERBOSITY_LEVELS.infos) {
  255. console.log('Info: ' + msg);
  256. }
  257. }
  258. // Non-fatal warnings.
  259. function warn(msg) {
  260. if (verbosity >= VERBOSITY_LEVELS.warnings) {
  261. console.log('Warning: ' + msg);
  262. }
  263. }
  264. // Deprecated API function -- display regardless of the PDFJS.verbosity setting.
  265. function deprecated(details) {
  266. console.log('Deprecated API usage: ' + details);
  267. }
  268. // Fatal errors that should trigger the fallback UI and halt execution by
  269. // throwing an exception.
  270. function error(msg) {
  271. if (verbosity >= VERBOSITY_LEVELS.errors) {
  272. console.log('Error: ' + msg);
  273. console.log(backtrace());
  274. }
  275. throw new Error(msg);
  276. }
  277. function backtrace() {
  278. try {
  279. throw new Error();
  280. } catch (e) {
  281. return e.stack ? e.stack.split('\n').slice(2).join('\n') : '';
  282. }
  283. }
  284. function assert(cond, msg) {
  285. if (!cond) {
  286. error(msg);
  287. }
  288. }
  289. var UNSUPPORTED_FEATURES = {
  290. unknown: 'unknown',
  291. forms: 'forms',
  292. javaScript: 'javaScript',
  293. smask: 'smask',
  294. shadingPattern: 'shadingPattern',
  295. font: 'font',
  296. };
  297. // Checks if URLs have the same origin. For non-HTTP based URLs, returns false.
  298. function isSameOrigin(baseUrl, otherUrl) {
  299. try {
  300. var base = new URL(baseUrl);
  301. if (!base.origin || base.origin === 'null') {
  302. return false; // non-HTTP url
  303. }
  304. } catch (e) {
  305. return false;
  306. }
  307. var other = new URL(otherUrl, base);
  308. return base.origin === other.origin;
  309. }
  310. // Checks if URLs use one of the whitelisted protocols, e.g. to avoid XSS.
  311. function isValidProtocol(url) {
  312. if (!url) {
  313. return false;
  314. }
  315. switch (url.protocol) {
  316. case 'http:':
  317. case 'https:':
  318. case 'ftp:':
  319. case 'mailto:':
  320. case 'tel:':
  321. return true;
  322. default:
  323. return false;
  324. }
  325. }
  326. /**
  327. * Attempts to create a valid absolute URL (utilizing `isValidProtocol`).
  328. * @param {URL|string} url - An absolute, or relative, URL.
  329. * @param {URL|string} baseUrl - An absolute URL.
  330. * @returns Either a valid {URL}, or `null` otherwise.
  331. */
  332. function createValidAbsoluteUrl(url, baseUrl) {
  333. if (!url) {
  334. return null;
  335. }
  336. try {
  337. var absoluteUrl = baseUrl ? new URL(url, baseUrl) : new URL(url);
  338. if (isValidProtocol(absoluteUrl)) {
  339. return absoluteUrl;
  340. }
  341. } catch (ex) { /* `new URL()` will throw on incorrect data. */ }
  342. return null;
  343. }
  344. function shadow(obj, prop, value) {
  345. Object.defineProperty(obj, prop, { value,
  346. enumerable: true,
  347. configurable: true,
  348. writable: false, });
  349. return value;
  350. }
  351. function getLookupTableFactory(initializer) {
  352. var lookup;
  353. return function () {
  354. if (initializer) {
  355. lookup = Object.create(null);
  356. initializer(lookup);
  357. initializer = null;
  358. }
  359. return lookup;
  360. };
  361. }
  362. var PasswordResponses = {
  363. NEED_PASSWORD: 1,
  364. INCORRECT_PASSWORD: 2,
  365. };
  366. var PasswordException = (function PasswordExceptionClosure() {
  367. function PasswordException(msg, code) {
  368. this.name = 'PasswordException';
  369. this.message = msg;
  370. this.code = code;
  371. }
  372. PasswordException.prototype = new Error();
  373. PasswordException.constructor = PasswordException;
  374. return PasswordException;
  375. })();
  376. var UnknownErrorException = (function UnknownErrorExceptionClosure() {
  377. function UnknownErrorException(msg, details) {
  378. this.name = 'UnknownErrorException';
  379. this.message = msg;
  380. this.details = details;
  381. }
  382. UnknownErrorException.prototype = new Error();
  383. UnknownErrorException.constructor = UnknownErrorException;
  384. return UnknownErrorException;
  385. })();
  386. var InvalidPDFException = (function InvalidPDFExceptionClosure() {
  387. function InvalidPDFException(msg) {
  388. this.name = 'InvalidPDFException';
  389. this.message = msg;
  390. }
  391. InvalidPDFException.prototype = new Error();
  392. InvalidPDFException.constructor = InvalidPDFException;
  393. return InvalidPDFException;
  394. })();
  395. var MissingPDFException = (function MissingPDFExceptionClosure() {
  396. function MissingPDFException(msg) {
  397. this.name = 'MissingPDFException';
  398. this.message = msg;
  399. }
  400. MissingPDFException.prototype = new Error();
  401. MissingPDFException.constructor = MissingPDFException;
  402. return MissingPDFException;
  403. })();
  404. var UnexpectedResponseException =
  405. (function UnexpectedResponseExceptionClosure() {
  406. function UnexpectedResponseException(msg, status) {
  407. this.name = 'UnexpectedResponseException';
  408. this.message = msg;
  409. this.status = status;
  410. }
  411. UnexpectedResponseException.prototype = new Error();
  412. UnexpectedResponseException.constructor = UnexpectedResponseException;
  413. return UnexpectedResponseException;
  414. })();
  415. var NotImplementedException = (function NotImplementedExceptionClosure() {
  416. function NotImplementedException(msg) {
  417. this.message = msg;
  418. }
  419. NotImplementedException.prototype = new Error();
  420. NotImplementedException.prototype.name = 'NotImplementedException';
  421. NotImplementedException.constructor = NotImplementedException;
  422. return NotImplementedException;
  423. })();
  424. var MissingDataException = (function MissingDataExceptionClosure() {
  425. function MissingDataException(begin, end) {
  426. this.begin = begin;
  427. this.end = end;
  428. this.message = 'Missing data [' + begin + ', ' + end + ')';
  429. }
  430. MissingDataException.prototype = new Error();
  431. MissingDataException.prototype.name = 'MissingDataException';
  432. MissingDataException.constructor = MissingDataException;
  433. return MissingDataException;
  434. })();
  435. var XRefParseException = (function XRefParseExceptionClosure() {
  436. function XRefParseException(msg) {
  437. this.message = msg;
  438. }
  439. XRefParseException.prototype = new Error();
  440. XRefParseException.prototype.name = 'XRefParseException';
  441. XRefParseException.constructor = XRefParseException;
  442. return XRefParseException;
  443. })();
  444. var NullCharactersRegExp = /\x00/g;
  445. function removeNullCharacters(str) {
  446. if (typeof str !== 'string') {
  447. warn('The argument for removeNullCharacters must be a string.');
  448. return str;
  449. }
  450. return str.replace(NullCharactersRegExp, '');
  451. }
  452. function bytesToString(bytes) {
  453. assert(bytes !== null && typeof bytes === 'object' &&
  454. bytes.length !== undefined, 'Invalid argument for bytesToString');
  455. var length = bytes.length;
  456. var MAX_ARGUMENT_COUNT = 8192;
  457. if (length < MAX_ARGUMENT_COUNT) {
  458. return String.fromCharCode.apply(null, bytes);
  459. }
  460. var strBuf = [];
  461. for (var i = 0; i < length; i += MAX_ARGUMENT_COUNT) {
  462. var chunkEnd = Math.min(i + MAX_ARGUMENT_COUNT, length);
  463. var chunk = bytes.subarray(i, chunkEnd);
  464. strBuf.push(String.fromCharCode.apply(null, chunk));
  465. }
  466. return strBuf.join('');
  467. }
  468. function stringToBytes(str) {
  469. assert(typeof str === 'string', 'Invalid argument for stringToBytes');
  470. var length = str.length;
  471. var bytes = new Uint8Array(length);
  472. for (var i = 0; i < length; ++i) {
  473. bytes[i] = str.charCodeAt(i) & 0xFF;
  474. }
  475. return bytes;
  476. }
  477. /**
  478. * Gets length of the array (Array, Uint8Array, or string) in bytes.
  479. * @param {Array|Uint8Array|string} arr
  480. * @returns {number}
  481. */
  482. function arrayByteLength(arr) {
  483. if (arr.length !== undefined) {
  484. return arr.length;
  485. }
  486. assert(arr.byteLength !== undefined);
  487. return arr.byteLength;
  488. }
  489. /**
  490. * Combines array items (arrays) into single Uint8Array object.
  491. * @param {Array} arr - the array of the arrays (Array, Uint8Array, or string).
  492. * @returns {Uint8Array}
  493. */
  494. function arraysToBytes(arr) {
  495. // Shortcut: if first and only item is Uint8Array, return it.
  496. if (arr.length === 1 && (arr[0] instanceof Uint8Array)) {
  497. return arr[0];
  498. }
  499. var resultLength = 0;
  500. var i, ii = arr.length;
  501. var item, itemLength;
  502. for (i = 0; i < ii; i++) {
  503. item = arr[i];
  504. itemLength = arrayByteLength(item);
  505. resultLength += itemLength;
  506. }
  507. var pos = 0;
  508. var data = new Uint8Array(resultLength);
  509. for (i = 0; i < ii; i++) {
  510. item = arr[i];
  511. if (!(item instanceof Uint8Array)) {
  512. if (typeof item === 'string') {
  513. item = stringToBytes(item);
  514. } else {
  515. item = new Uint8Array(item);
  516. }
  517. }
  518. itemLength = item.byteLength;
  519. data.set(item, pos);
  520. pos += itemLength;
  521. }
  522. return data;
  523. }
  524. function string32(value) {
  525. return String.fromCharCode((value >> 24) & 0xff, (value >> 16) & 0xff,
  526. (value >> 8) & 0xff, value & 0xff);
  527. }
  528. function log2(x) {
  529. var n = 1, i = 0;
  530. while (x > n) {
  531. n <<= 1;
  532. i++;
  533. }
  534. return i;
  535. }
  536. function readInt8(data, start) {
  537. return (data[start] << 24) >> 24;
  538. }
  539. function readUint16(data, offset) {
  540. return (data[offset] << 8) | data[offset + 1];
  541. }
  542. function readUint32(data, offset) {
  543. return ((data[offset] << 24) | (data[offset + 1] << 16) |
  544. (data[offset + 2] << 8) | data[offset + 3]) >>> 0;
  545. }
  546. // Lazy test the endianness of the platform
  547. // NOTE: This will be 'true' for simulated TypedArrays
  548. function isLittleEndian() {
  549. var buffer8 = new Uint8Array(4);
  550. buffer8[0] = 1;
  551. var view32 = new Uint32Array(buffer8.buffer, 0, 1);
  552. return (view32[0] === 1);
  553. }
  554. // Checks if it's possible to eval JS expressions.
  555. function isEvalSupported() {
  556. try {
  557. new Function(''); // eslint-disable-line no-new, no-new-func
  558. return true;
  559. } catch (e) {
  560. return false;
  561. }
  562. }
  563. var IDENTITY_MATRIX = [1, 0, 0, 1, 0, 0];
  564. var Util = (function UtilClosure() {
  565. function Util() {}
  566. var rgbBuf = ['rgb(', 0, ',', 0, ',', 0, ')'];
  567. // makeCssRgb() can be called thousands of times. Using |rgbBuf| avoids
  568. // creating many intermediate strings.
  569. Util.makeCssRgb = function Util_makeCssRgb(r, g, b) {
  570. rgbBuf[1] = r;
  571. rgbBuf[3] = g;
  572. rgbBuf[5] = b;
  573. return rgbBuf.join('');
  574. };
  575. // Concatenates two transformation matrices together and returns the result.
  576. Util.transform = function Util_transform(m1, m2) {
  577. return [
  578. m1[0] * m2[0] + m1[2] * m2[1],
  579. m1[1] * m2[0] + m1[3] * m2[1],
  580. m1[0] * m2[2] + m1[2] * m2[3],
  581. m1[1] * m2[2] + m1[3] * m2[3],
  582. m1[0] * m2[4] + m1[2] * m2[5] + m1[4],
  583. m1[1] * m2[4] + m1[3] * m2[5] + m1[5]
  584. ];
  585. };
  586. // For 2d affine transforms
  587. Util.applyTransform = function Util_applyTransform(p, m) {
  588. var xt = p[0] * m[0] + p[1] * m[2] + m[4];
  589. var yt = p[0] * m[1] + p[1] * m[3] + m[5];
  590. return [xt, yt];
  591. };
  592. Util.applyInverseTransform = function Util_applyInverseTransform(p, m) {
  593. var d = m[0] * m[3] - m[1] * m[2];
  594. var xt = (p[0] * m[3] - p[1] * m[2] + m[2] * m[5] - m[4] * m[3]) / d;
  595. var yt = (-p[0] * m[1] + p[1] * m[0] + m[4] * m[1] - m[5] * m[0]) / d;
  596. return [xt, yt];
  597. };
  598. // Applies the transform to the rectangle and finds the minimum axially
  599. // aligned bounding box.
  600. Util.getAxialAlignedBoundingBox =
  601. function Util_getAxialAlignedBoundingBox(r, m) {
  602. var p1 = Util.applyTransform(r, m);
  603. var p2 = Util.applyTransform(r.slice(2, 4), m);
  604. var p3 = Util.applyTransform([r[0], r[3]], m);
  605. var p4 = Util.applyTransform([r[2], r[1]], m);
  606. return [
  607. Math.min(p1[0], p2[0], p3[0], p4[0]),
  608. Math.min(p1[1], p2[1], p3[1], p4[1]),
  609. Math.max(p1[0], p2[0], p3[0], p4[0]),
  610. Math.max(p1[1], p2[1], p3[1], p4[1])
  611. ];
  612. };
  613. Util.inverseTransform = function Util_inverseTransform(m) {
  614. var d = m[0] * m[3] - m[1] * m[2];
  615. return [m[3] / d, -m[1] / d, -m[2] / d, m[0] / d,
  616. (m[2] * m[5] - m[4] * m[3]) / d, (m[4] * m[1] - m[5] * m[0]) / d];
  617. };
  618. // Apply a generic 3d matrix M on a 3-vector v:
  619. // | a b c | | X |
  620. // | d e f | x | Y |
  621. // | g h i | | Z |
  622. // M is assumed to be serialized as [a,b,c,d,e,f,g,h,i],
  623. // with v as [X,Y,Z]
  624. Util.apply3dTransform = function Util_apply3dTransform(m, v) {
  625. return [
  626. m[0] * v[0] + m[1] * v[1] + m[2] * v[2],
  627. m[3] * v[0] + m[4] * v[1] + m[5] * v[2],
  628. m[6] * v[0] + m[7] * v[1] + m[8] * v[2]
  629. ];
  630. };
  631. // This calculation uses Singular Value Decomposition.
  632. // The SVD can be represented with formula A = USV. We are interested in the
  633. // matrix S here because it represents the scale values.
  634. Util.singularValueDecompose2dScale =
  635. function Util_singularValueDecompose2dScale(m) {
  636. var transpose = [m[0], m[2], m[1], m[3]];
  637. // Multiply matrix m with its transpose.
  638. var a = m[0] * transpose[0] + m[1] * transpose[2];
  639. var b = m[0] * transpose[1] + m[1] * transpose[3];
  640. var c = m[2] * transpose[0] + m[3] * transpose[2];
  641. var d = m[2] * transpose[1] + m[3] * transpose[3];
  642. // Solve the second degree polynomial to get roots.
  643. var first = (a + d) / 2;
  644. var second = Math.sqrt((a + d) * (a + d) - 4 * (a * d - c * b)) / 2;
  645. var sx = first + second || 1;
  646. var sy = first - second || 1;
  647. // Scale values are the square roots of the eigenvalues.
  648. return [Math.sqrt(sx), Math.sqrt(sy)];
  649. };
  650. // Normalize rectangle rect=[x1, y1, x2, y2] so that (x1,y1) < (x2,y2)
  651. // For coordinate systems whose origin lies in the bottom-left, this
  652. // means normalization to (BL,TR) ordering. For systems with origin in the
  653. // top-left, this means (TL,BR) ordering.
  654. Util.normalizeRect = function Util_normalizeRect(rect) {
  655. var r = rect.slice(0); // clone rect
  656. if (rect[0] > rect[2]) {
  657. r[0] = rect[2];
  658. r[2] = rect[0];
  659. }
  660. if (rect[1] > rect[3]) {
  661. r[1] = rect[3];
  662. r[3] = rect[1];
  663. }
  664. return r;
  665. };
  666. // Returns a rectangle [x1, y1, x2, y2] corresponding to the
  667. // intersection of rect1 and rect2. If no intersection, returns 'false'
  668. // The rectangle coordinates of rect1, rect2 should be [x1, y1, x2, y2]
  669. Util.intersect = function Util_intersect(rect1, rect2) {
  670. function compare(a, b) {
  671. return a - b;
  672. }
  673. // Order points along the axes
  674. var orderedX = [rect1[0], rect1[2], rect2[0], rect2[2]].sort(compare),
  675. orderedY = [rect1[1], rect1[3], rect2[1], rect2[3]].sort(compare),
  676. result = [];
  677. rect1 = Util.normalizeRect(rect1);
  678. rect2 = Util.normalizeRect(rect2);
  679. // X: first and second points belong to different rectangles?
  680. if ((orderedX[0] === rect1[0] && orderedX[1] === rect2[0]) ||
  681. (orderedX[0] === rect2[0] && orderedX[1] === rect1[0])) {
  682. // Intersection must be between second and third points
  683. result[0] = orderedX[1];
  684. result[2] = orderedX[2];
  685. } else {
  686. return false;
  687. }
  688. // Y: first and second points belong to different rectangles?
  689. if ((orderedY[0] === rect1[1] && orderedY[1] === rect2[1]) ||
  690. (orderedY[0] === rect2[1] && orderedY[1] === rect1[1])) {
  691. // Intersection must be between second and third points
  692. result[1] = orderedY[1];
  693. result[3] = orderedY[2];
  694. } else {
  695. return false;
  696. }
  697. return result;
  698. };
  699. Util.sign = function Util_sign(num) {
  700. return num < 0 ? -1 : 1;
  701. };
  702. var ROMAN_NUMBER_MAP = [
  703. '', 'C', 'CC', 'CCC', 'CD', 'D', 'DC', 'DCC', 'DCCC', 'CM',
  704. '', 'X', 'XX', 'XXX', 'XL', 'L', 'LX', 'LXX', 'LXXX', 'XC',
  705. '', 'I', 'II', 'III', 'IV', 'V', 'VI', 'VII', 'VIII', 'IX'
  706. ];
  707. /**
  708. * Converts positive integers to (upper case) Roman numerals.
  709. * @param {integer} number - The number that should be converted.
  710. * @param {boolean} lowerCase - Indicates if the result should be converted
  711. * to lower case letters. The default is false.
  712. * @return {string} The resulting Roman number.
  713. */
  714. Util.toRoman = function Util_toRoman(number, lowerCase) {
  715. assert(isInt(number) && number > 0,
  716. 'The number should be a positive integer.');
  717. var pos, romanBuf = [];
  718. // Thousands
  719. while (number >= 1000) {
  720. number -= 1000;
  721. romanBuf.push('M');
  722. }
  723. // Hundreds
  724. pos = (number / 100) | 0;
  725. number %= 100;
  726. romanBuf.push(ROMAN_NUMBER_MAP[pos]);
  727. // Tens
  728. pos = (number / 10) | 0;
  729. number %= 10;
  730. romanBuf.push(ROMAN_NUMBER_MAP[10 + pos]);
  731. // Ones
  732. romanBuf.push(ROMAN_NUMBER_MAP[20 + number]);
  733. var romanStr = romanBuf.join('');
  734. return (lowerCase ? romanStr.toLowerCase() : romanStr);
  735. };
  736. Util.appendToArray = function Util_appendToArray(arr1, arr2) {
  737. Array.prototype.push.apply(arr1, arr2);
  738. };
  739. Util.prependToArray = function Util_prependToArray(arr1, arr2) {
  740. Array.prototype.unshift.apply(arr1, arr2);
  741. };
  742. Util.extendObj = function extendObj(obj1, obj2) {
  743. for (var key in obj2) {
  744. obj1[key] = obj2[key];
  745. }
  746. };
  747. Util.getInheritableProperty =
  748. function Util_getInheritableProperty(dict, name, getArray) {
  749. while (dict && !dict.has(name)) {
  750. dict = dict.get('Parent');
  751. }
  752. if (!dict) {
  753. return null;
  754. }
  755. return getArray ? dict.getArray(name) : dict.get(name);
  756. };
  757. Util.inherit = function Util_inherit(sub, base, prototype) {
  758. sub.prototype = Object.create(base.prototype);
  759. sub.prototype.constructor = sub;
  760. for (var prop in prototype) {
  761. sub.prototype[prop] = prototype[prop];
  762. }
  763. };
  764. Util.loadScript = function Util_loadScript(src, callback) {
  765. var script = document.createElement('script');
  766. var loaded = false;
  767. script.setAttribute('src', src);
  768. if (callback) {
  769. script.onload = function() {
  770. if (!loaded) {
  771. callback();
  772. }
  773. loaded = true;
  774. };
  775. }
  776. document.getElementsByTagName('head')[0].appendChild(script);
  777. };
  778. return Util;
  779. })();
  780. /**
  781. * PDF page viewport created based on scale, rotation and offset.
  782. * @class
  783. * @alias PageViewport
  784. */
  785. var PageViewport = (function PageViewportClosure() {
  786. /**
  787. * @constructor
  788. * @private
  789. * @param viewBox {Array} xMin, yMin, xMax and yMax coordinates.
  790. * @param scale {number} scale of the viewport.
  791. * @param rotation {number} rotations of the viewport in degrees.
  792. * @param offsetX {number} offset X
  793. * @param offsetY {number} offset Y
  794. * @param dontFlip {boolean} if true, axis Y will not be flipped.
  795. */
  796. function PageViewport(viewBox, scale, rotation, offsetX, offsetY, dontFlip) {
  797. this.viewBox = viewBox;
  798. this.scale = scale;
  799. this.rotation = rotation;
  800. this.offsetX = offsetX;
  801. this.offsetY = offsetY;
  802. // creating transform to convert pdf coordinate system to the normal
  803. // canvas like coordinates taking in account scale and rotation
  804. var centerX = (viewBox[2] + viewBox[0]) / 2;
  805. var centerY = (viewBox[3] + viewBox[1]) / 2;
  806. var rotateA, rotateB, rotateC, rotateD;
  807. rotation = rotation % 360;
  808. rotation = rotation < 0 ? rotation + 360 : rotation;
  809. switch (rotation) {
  810. case 180:
  811. rotateA = -1; rotateB = 0; rotateC = 0; rotateD = 1;
  812. break;
  813. case 90:
  814. rotateA = 0; rotateB = 1; rotateC = 1; rotateD = 0;
  815. break;
  816. case 270:
  817. rotateA = 0; rotateB = -1; rotateC = -1; rotateD = 0;
  818. break;
  819. // case 0:
  820. default:
  821. rotateA = 1; rotateB = 0; rotateC = 0; rotateD = -1;
  822. break;
  823. }
  824. if (dontFlip) {
  825. rotateC = -rotateC; rotateD = -rotateD;
  826. }
  827. var offsetCanvasX, offsetCanvasY;
  828. var width, height;
  829. if (rotateA === 0) {
  830. offsetCanvasX = Math.abs(centerY - viewBox[1]) * scale + offsetX;
  831. offsetCanvasY = Math.abs(centerX - viewBox[0]) * scale + offsetY;
  832. width = Math.abs(viewBox[3] - viewBox[1]) * scale;
  833. height = Math.abs(viewBox[2] - viewBox[0]) * scale;
  834. } else {
  835. offsetCanvasX = Math.abs(centerX - viewBox[0]) * scale + offsetX;
  836. offsetCanvasY = Math.abs(centerY - viewBox[1]) * scale + offsetY;
  837. width = Math.abs(viewBox[2] - viewBox[0]) * scale;
  838. height = Math.abs(viewBox[3] - viewBox[1]) * scale;
  839. }
  840. // creating transform for the following operations:
  841. // translate(-centerX, -centerY), rotate and flip vertically,
  842. // scale, and translate(offsetCanvasX, offsetCanvasY)
  843. this.transform = [
  844. rotateA * scale,
  845. rotateB * scale,
  846. rotateC * scale,
  847. rotateD * scale,
  848. offsetCanvasX - rotateA * scale * centerX - rotateC * scale * centerY,
  849. offsetCanvasY - rotateB * scale * centerX - rotateD * scale * centerY
  850. ];
  851. this.width = width;
  852. this.height = height;
  853. this.fontScale = scale;
  854. }
  855. PageViewport.prototype = /** @lends PageViewport.prototype */ {
  856. /**
  857. * Clones viewport with additional properties.
  858. * @param args {Object} (optional) If specified, may contain the 'scale' or
  859. * 'rotation' properties to override the corresponding properties in
  860. * the cloned viewport.
  861. * @returns {PageViewport} Cloned viewport.
  862. */
  863. clone: function PageViewPort_clone(args) {
  864. args = args || {};
  865. var scale = 'scale' in args ? args.scale : this.scale;
  866. var rotation = 'rotation' in args ? args.rotation : this.rotation;
  867. return new PageViewport(this.viewBox.slice(), scale, rotation,
  868. this.offsetX, this.offsetY, args.dontFlip);
  869. },
  870. /**
  871. * Converts PDF point to the viewport coordinates. For examples, useful for
  872. * converting PDF location into canvas pixel coordinates.
  873. * @param x {number} X coordinate.
  874. * @param y {number} Y coordinate.
  875. * @returns {Object} Object that contains 'x' and 'y' properties of the
  876. * point in the viewport coordinate space.
  877. * @see {@link convertToPdfPoint}
  878. * @see {@link convertToViewportRectangle}
  879. */
  880. convertToViewportPoint: function PageViewport_convertToViewportPoint(x, y) {
  881. return Util.applyTransform([x, y], this.transform);
  882. },
  883. /**
  884. * Converts PDF rectangle to the viewport coordinates.
  885. * @param rect {Array} xMin, yMin, xMax and yMax coordinates.
  886. * @returns {Array} Contains corresponding coordinates of the rectangle
  887. * in the viewport coordinate space.
  888. * @see {@link convertToViewportPoint}
  889. */
  890. convertToViewportRectangle:
  891. function PageViewport_convertToViewportRectangle(rect) {
  892. var tl = Util.applyTransform([rect[0], rect[1]], this.transform);
  893. var br = Util.applyTransform([rect[2], rect[3]], this.transform);
  894. return [tl[0], tl[1], br[0], br[1]];
  895. },
  896. /**
  897. * Converts viewport coordinates to the PDF location. For examples, useful
  898. * for converting canvas pixel location into PDF one.
  899. * @param x {number} X coordinate.
  900. * @param y {number} Y coordinate.
  901. * @returns {Object} Object that contains 'x' and 'y' properties of the
  902. * point in the PDF coordinate space.
  903. * @see {@link convertToViewportPoint}
  904. */
  905. convertToPdfPoint: function PageViewport_convertToPdfPoint(x, y) {
  906. return Util.applyInverseTransform([x, y], this.transform);
  907. },
  908. };
  909. return PageViewport;
  910. })();
  911. var PDFStringTranslateTable = [
  912. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  913. 0x2D8, 0x2C7, 0x2C6, 0x2D9, 0x2DD, 0x2DB, 0x2DA, 0x2DC, 0, 0, 0, 0, 0, 0, 0,
  914. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  915. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  916. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  917. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x2022, 0x2020, 0x2021, 0x2026, 0x2014,
  918. 0x2013, 0x192, 0x2044, 0x2039, 0x203A, 0x2212, 0x2030, 0x201E, 0x201C,
  919. 0x201D, 0x2018, 0x2019, 0x201A, 0x2122, 0xFB01, 0xFB02, 0x141, 0x152, 0x160,
  920. 0x178, 0x17D, 0x131, 0x142, 0x153, 0x161, 0x17E, 0, 0x20AC
  921. ];
  922. function stringToPDFString(str) {
  923. var i, n = str.length, strBuf = [];
  924. if (str[0] === '\xFE' && str[1] === '\xFF') {
  925. // UTF16BE BOM
  926. for (i = 2; i < n; i += 2) {
  927. strBuf.push(String.fromCharCode(
  928. (str.charCodeAt(i) << 8) | str.charCodeAt(i + 1)));
  929. }
  930. } else {
  931. for (i = 0; i < n; ++i) {
  932. var code = PDFStringTranslateTable[str.charCodeAt(i)];
  933. strBuf.push(code ? String.fromCharCode(code) : str.charAt(i));
  934. }
  935. }
  936. return strBuf.join('');
  937. }
  938. function stringToUTF8String(str) {
  939. return decodeURIComponent(escape(str));
  940. }
  941. function utf8StringToString(str) {
  942. return unescape(encodeURIComponent(str));
  943. }
  944. function isEmptyObj(obj) {
  945. for (var key in obj) {
  946. return false;
  947. }
  948. return true;
  949. }
  950. function isBool(v) {
  951. return typeof v === 'boolean';
  952. }
  953. function isInt(v) {
  954. return typeof v === 'number' && ((v | 0) === v);
  955. }
  956. function isNum(v) {
  957. return typeof v === 'number';
  958. }
  959. function isString(v) {
  960. return typeof v === 'string';
  961. }
  962. function isArray(v) {
  963. return v instanceof Array;
  964. }
  965. function isArrayBuffer(v) {
  966. return typeof v === 'object' && v !== null && v.byteLength !== undefined;
  967. }
  968. // Checks if ch is one of the following characters: SPACE, TAB, CR or LF.
  969. function isSpace(ch) {
  970. return (ch === 0x20 || ch === 0x09 || ch === 0x0D || ch === 0x0A);
  971. }
  972. function isNodeJS() {
  973. // The if below protected by __pdfjsdev_webpack__ check from webpack parsing.
  974. if (typeof __pdfjsdev_webpack__ === 'undefined') {
  975. return typeof process === 'object' && process + '' === '[object process]';
  976. }
  977. return false;
  978. }
  979. /**
  980. * Promise Capability object.
  981. *
  982. * @typedef {Object} PromiseCapability
  983. * @property {Promise} promise - A promise object.
  984. * @property {function} resolve - Fulfills the promise.
  985. * @property {function} reject - Rejects the promise.
  986. */
  987. /**
  988. * Creates a promise capability object.
  989. * @alias createPromiseCapability
  990. *
  991. * @return {PromiseCapability} A capability object contains:
  992. * - a Promise, resolve and reject methods.
  993. */
  994. function createPromiseCapability() {
  995. var capability = {};
  996. capability.promise = new Promise(function (resolve, reject) {
  997. capability.resolve = resolve;
  998. capability.reject = reject;
  999. });
  1000. return capability;
  1001. }
  1002. var StatTimer = (function StatTimerClosure() {
  1003. function rpad(str, pad, length) {
  1004. while (str.length < length) {
  1005. str += pad;
  1006. }
  1007. return str;
  1008. }
  1009. function StatTimer() {
  1010. this.started = Object.create(null);
  1011. this.times = [];
  1012. this.enabled = true;
  1013. }
  1014. StatTimer.prototype = {
  1015. time: function StatTimer_time(name) {
  1016. if (!this.enabled) {
  1017. return;
  1018. }
  1019. if (name in this.started) {
  1020. warn('Timer is already running for ' + name);
  1021. }
  1022. this.started[name] = Date.now();
  1023. },
  1024. timeEnd: function StatTimer_timeEnd(name) {
  1025. if (!this.enabled) {
  1026. return;
  1027. }
  1028. if (!(name in this.started)) {
  1029. warn('Timer has not been started for ' + name);
  1030. }
  1031. this.times.push({
  1032. 'name': name,
  1033. 'start': this.started[name],
  1034. 'end': Date.now(),
  1035. });
  1036. // Remove timer from started so it can be called again.
  1037. delete this.started[name];
  1038. },
  1039. toString: function StatTimer_toString() {
  1040. var i, ii;
  1041. var times = this.times;
  1042. var out = '';
  1043. // Find the longest name for padding purposes.
  1044. var longest = 0;
  1045. for (i = 0, ii = times.length; i < ii; ++i) {
  1046. var name = times[i]['name'];
  1047. if (name.length > longest) {
  1048. longest = name.length;
  1049. }
  1050. }
  1051. for (i = 0, ii = times.length; i < ii; ++i) {
  1052. var span = times[i];
  1053. var duration = span.end - span.start;
  1054. out += rpad(span['name'], ' ', longest) + ' ' + duration + 'ms\n';
  1055. }
  1056. return out;
  1057. },
  1058. };
  1059. return StatTimer;
  1060. })();
  1061. var createBlob = function createBlob(data, contentType) {
  1062. if (typeof Blob !== 'undefined') {
  1063. return new Blob([data], { type: contentType, });
  1064. }
  1065. throw new Error('The "Blob" constructor is not supported.');
  1066. };
  1067. var createObjectURL = (function createObjectURLClosure() {
  1068. // Blob/createObjectURL is not available, falling back to data schema.
  1069. var digits =
  1070. 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
  1071. return function createObjectURL(data, contentType, forceDataSchema = false) {
  1072. if (!forceDataSchema && URL.createObjectURL) {
  1073. var blob = createBlob(data, contentType);
  1074. return URL.createObjectURL(blob);
  1075. }
  1076. var buffer = 'data:' + contentType + ';base64,';
  1077. for (var i = 0, ii = data.length; i < ii; i += 3) {
  1078. var b1 = data[i] & 0xFF;
  1079. var b2 = data[i + 1] & 0xFF;
  1080. var b3 = data[i + 2] & 0xFF;
  1081. var d1 = b1 >> 2, d2 = ((b1 & 3) << 4) | (b2 >> 4);
  1082. var d3 = i + 1 < ii ? ((b2 & 0xF) << 2) | (b3 >> 6) : 64;
  1083. var d4 = i + 2 < ii ? (b3 & 0x3F) : 64;
  1084. buffer += digits[d1] + digits[d2] + digits[d3] + digits[d4];
  1085. }
  1086. return buffer;
  1087. };
  1088. })();
  1089. function resolveCall(fn, args, thisArg = null) {
  1090. if (!fn) {
  1091. return Promise.resolve(undefined);
  1092. }
  1093. return new Promise((resolve, reject) => {
  1094. resolve(fn.apply(thisArg, args));
  1095. });
  1096. }
  1097. function resolveOrReject(capability, success, reason) {
  1098. if (success) {
  1099. capability.resolve();
  1100. } else {
  1101. capability.reject(reason);
  1102. }
  1103. }
  1104. function finalize(promise) {
  1105. return Promise.resolve(promise).catch(() => {});
  1106. }
  1107. function MessageHandler(sourceName, targetName, comObj) {
  1108. this.sourceName = sourceName;
  1109. this.targetName = targetName;
  1110. this.comObj = comObj;
  1111. this.callbackId = 1;
  1112. this.streamId = 1;
  1113. this.postMessageTransfers = true;
  1114. this.streamSinks = Object.create(null);
  1115. this.streamControllers = Object.create(null);
  1116. let callbacksCapabilities = this.callbacksCapabilities = Object.create(null);
  1117. let ah = this.actionHandler = Object.create(null);
  1118. this._onComObjOnMessage = (event) => {
  1119. let data = event.data;
  1120. if (data.targetName !== this.sourceName) {
  1121. return;
  1122. }
  1123. if (data.stream) {
  1124. this._processStreamMessage(data);
  1125. } else if (data.isReply) {
  1126. let callbackId = data.callbackId;
  1127. if (data.callbackId in callbacksCapabilities) {
  1128. let callback = callbacksCapabilities[callbackId];
  1129. delete callbacksCapabilities[callbackId];
  1130. if ('error' in data) {
  1131. callback.reject(data.error);
  1132. } else {
  1133. callback.resolve(data.data);
  1134. }
  1135. } else {
  1136. error('Cannot resolve callback ' + callbackId);
  1137. }
  1138. } else if (data.action in ah) {
  1139. let action = ah[data.action];
  1140. if (data.callbackId) {
  1141. let sourceName = this.sourceName;
  1142. let targetName = data.sourceName;
  1143. Promise.resolve().then(function () {
  1144. return action[0].call(action[1], data.data);
  1145. }).then((result) => {
  1146. comObj.postMessage({
  1147. sourceName,
  1148. targetName,
  1149. isReply: true,
  1150. callbackId: data.callbackId,
  1151. data: result,
  1152. });
  1153. }, (reason) => {
  1154. if (reason instanceof Error) {
  1155. // Serialize error to avoid "DataCloneError"
  1156. reason = reason + '';
  1157. }
  1158. comObj.postMessage({
  1159. sourceName,
  1160. targetName,
  1161. isReply: true,
  1162. callbackId: data.callbackId,
  1163. error: reason,
  1164. });
  1165. });
  1166. } else if (data.streamId) {
  1167. this._createStreamSink(data);
  1168. } else {
  1169. action[0].call(action[1], data.data);
  1170. }
  1171. } else {
  1172. error('Unknown action from worker: ' + data.action);
  1173. }
  1174. };
  1175. comObj.addEventListener('message', this._onComObjOnMessage);
  1176. }
  1177. MessageHandler.prototype = {
  1178. on(actionName, handler, scope) {
  1179. var ah = this.actionHandler;
  1180. if (ah[actionName]) {
  1181. error('There is already an actionName called "' + actionName + '"');
  1182. }
  1183. ah[actionName] = [handler, scope];
  1184. },
  1185. /**
  1186. * Sends a message to the comObj to invoke the action with the supplied data.
  1187. * @param {String} actionName - Action to call.
  1188. * @param {JSON} data - JSON data to send.
  1189. * @param {Array} [transfers] - Optional list of transfers/ArrayBuffers
  1190. */
  1191. send(actionName, data, transfers) {
  1192. var message = {
  1193. sourceName: this.sourceName,
  1194. targetName: this.targetName,
  1195. action: actionName,
  1196. data,
  1197. };
  1198. this.postMessage(message, transfers);
  1199. },
  1200. /**
  1201. * Sends a message to the comObj to invoke the action with the supplied data.
  1202. * Expects that the other side will callback with the response.
  1203. * @param {String} actionName - Action to call.
  1204. * @param {JSON} data - JSON data to send.
  1205. * @param {Array} [transfers] - Optional list of transfers/ArrayBuffers.
  1206. * @returns {Promise} Promise to be resolved with response data.
  1207. */
  1208. sendWithPromise(actionName, data, transfers) {
  1209. var callbackId = this.callbackId++;
  1210. var message = {
  1211. sourceName: this.sourceName,
  1212. targetName: this.targetName,
  1213. action: actionName,
  1214. data,
  1215. callbackId,
  1216. };
  1217. var capability = createPromiseCapability();
  1218. this.callbacksCapabilities[callbackId] = capability;
  1219. try {
  1220. this.postMessage(message, transfers);
  1221. } catch (e) {
  1222. capability.reject(e);
  1223. }
  1224. return capability.promise;
  1225. },
  1226. /**
  1227. * Sends a message to the comObj to invoke the action with the supplied data.
  1228. * Expect that the other side will callback to signal 'start_complete'.
  1229. * @param {String} actionName - Action to call.
  1230. * @param {JSON} data - JSON data to send.
  1231. * @param {Object} queueingStrategy - strategy to signal backpressure based on
  1232. * internal queue.
  1233. * @param {Array} [transfers] - Optional list of transfers/ArrayBuffers.
  1234. * @return {ReadableStream} ReadableStream to read data in chunks.
  1235. */
  1236. sendWithStream(actionName, data, queueingStrategy, transfers) {
  1237. let streamId = this.streamId++;
  1238. let sourceName = this.sourceName;
  1239. let targetName = this.targetName;
  1240. return new ReadableStream({
  1241. start: (controller) => {
  1242. let startCapability = createPromiseCapability();
  1243. this.streamControllers[streamId] = {
  1244. controller,
  1245. startCall: startCapability,
  1246. };
  1247. this.postMessage({
  1248. sourceName,
  1249. targetName,
  1250. action: actionName,
  1251. streamId,
  1252. data,
  1253. desiredSize: controller.desiredSize,
  1254. });
  1255. // Return Promise for Async process, to signal success/failure.
  1256. return startCapability.promise;
  1257. },
  1258. pull: (controller) => {
  1259. let pullCapability = createPromiseCapability();
  1260. this.streamControllers[streamId].pullCall = pullCapability;
  1261. this.postMessage({
  1262. sourceName,
  1263. targetName,
  1264. stream: 'pull',
  1265. streamId,
  1266. desiredSize: controller.desiredSize,
  1267. });
  1268. // Returning Promise will not call "pull"
  1269. // again until current pull is resolved.
  1270. return pullCapability.promise;
  1271. },
  1272. cancel: (reason) => {
  1273. let cancelCapability = createPromiseCapability();
  1274. this.streamControllers[streamId].cancelCall = cancelCapability;
  1275. this.postMessage({
  1276. sourceName,
  1277. targetName,
  1278. stream: 'cancel',
  1279. reason,
  1280. streamId,
  1281. });
  1282. // Return Promise to signal success or failure.
  1283. return cancelCapability.promise;
  1284. },
  1285. }, queueingStrategy);
  1286. },
  1287. _createStreamSink(data) {
  1288. let self = this;
  1289. let action = this.actionHandler[data.action];
  1290. let streamId = data.streamId;
  1291. let desiredSize = data.desiredSize;
  1292. let sourceName = this.sourceName;
  1293. let targetName = data.sourceName;
  1294. let capability = createPromiseCapability();
  1295. let sendStreamRequest = ({ stream, chunk, success, reason, }) => {
  1296. this.comObj.postMessage({ sourceName, targetName, stream, streamId,
  1297. chunk, success, reason, });
  1298. };
  1299. let streamSink = {
  1300. enqueue(chunk, size = 1) {
  1301. let lastDesiredSize = this.desiredSize;
  1302. this.desiredSize -= size;
  1303. // Enqueue decreases the desiredSize property of sink,
  1304. // so when it changes from positive to negative,
  1305. // set ready as unresolved promise.
  1306. if (lastDesiredSize > 0 && this.desiredSize <= 0) {
  1307. this.sinkCapability = createPromiseCapability();
  1308. this.ready = this.sinkCapability.promise;
  1309. }
  1310. sendStreamRequest({ stream: 'enqueue', chunk, });
  1311. },
  1312. close() {
  1313. sendStreamRequest({ stream: 'close', });
  1314. delete self.streamSinks[streamId];
  1315. },
  1316. error(reason) {
  1317. sendStreamRequest({ stream: 'error', reason, });
  1318. },
  1319. sinkCapability: capability,
  1320. onPull: null,
  1321. onCancel: null,
  1322. desiredSize,
  1323. ready: null,
  1324. };
  1325. streamSink.sinkCapability.resolve();
  1326. streamSink.ready = streamSink.sinkCapability.promise;
  1327. this.streamSinks[streamId] = streamSink;
  1328. resolveCall(action[0], [data.data, streamSink], action[1]).then(() => {
  1329. sendStreamRequest({ stream: 'start_complete', success: true, });
  1330. }, (reason) => {
  1331. sendStreamRequest({ stream: 'start_complete', success: false, reason, });
  1332. });
  1333. },
  1334. _processStreamMessage(data) {
  1335. let sourceName = this.sourceName;
  1336. let targetName = data.sourceName;
  1337. let streamId = data.streamId;
  1338. let sendStreamResponse = ({ stream, success, reason, }) => {
  1339. this.comObj.postMessage({ sourceName, targetName, stream,
  1340. success, streamId, reason, });
  1341. };
  1342. let deleteStreamController = () => {
  1343. // Delete streamController only when start, pull and
  1344. // cancel callbacks are resolved, to avoid "TypeError".
  1345. Promise.all([
  1346. this.streamControllers[data.streamId].startCall,
  1347. this.streamControllers[data.streamId].pullCall,
  1348. this.streamControllers[data.streamId].cancelCall
  1349. ].map(function(capability) {
  1350. return capability && finalize(capability.promise);
  1351. })).then(() => {
  1352. delete this.streamControllers[data.streamId];
  1353. });
  1354. };
  1355. switch (data.stream) {
  1356. case 'start_complete':
  1357. resolveOrReject(this.streamControllers[data.streamId].startCall,
  1358. data.success, data.reason);
  1359. break;
  1360. case 'pull_complete':
  1361. resolveOrReject(this.streamControllers[data.streamId].pullCall,
  1362. data.success, data.reason);
  1363. break;
  1364. case 'pull':
  1365. // Ignore any pull after close is called.
  1366. if (!this.streamSinks[data.streamId]) {
  1367. sendStreamResponse({ stream: 'pull_complete', success: true, });
  1368. break;
  1369. }
  1370. // Pull increases the desiredSize property of sink,
  1371. // so when it changes from negative to positive,
  1372. // set ready property as resolved promise.
  1373. if (this.streamSinks[data.streamId].desiredSize <= 0 &&
  1374. data.desiredSize > 0) {
  1375. this.streamSinks[data.streamId].sinkCapability.resolve();
  1376. }
  1377. // Reset desiredSize property of sink on every pull.
  1378. this.streamSinks[data.streamId].desiredSize = data.desiredSize;
  1379. resolveCall(this.streamSinks[data.streamId].onPull).then(() => {
  1380. sendStreamResponse({ stream: 'pull_complete', success: true, });
  1381. }, (reason) => {
  1382. sendStreamResponse({ stream: 'pull_complete',
  1383. success: false, reason, });
  1384. });
  1385. break;
  1386. case 'enqueue':
  1387. this.streamControllers[data.streamId].controller.enqueue(data.chunk);
  1388. break;
  1389. case 'close':
  1390. this.streamControllers[data.streamId].controller.close();
  1391. deleteStreamController();
  1392. break;
  1393. case 'error':
  1394. this.streamControllers[data.streamId].controller.error(data.reason);
  1395. deleteStreamController();
  1396. break;
  1397. case 'cancel_complete':
  1398. resolveOrReject(this.streamControllers[data.streamId].cancelCall,
  1399. data.success, data.reason);
  1400. deleteStreamController();
  1401. break;
  1402. case 'cancel':
  1403. resolveCall(this.streamSinks[data.streamId].onCancel,
  1404. [data.reason]).then(() => {
  1405. sendStreamResponse({ stream: 'cancel_complete', success: true, });
  1406. }, (reason) => {
  1407. sendStreamResponse({ stream: 'cancel_complete',
  1408. success: false, reason, });
  1409. });
  1410. delete this.streamSinks[data.streamId];
  1411. break;
  1412. default:
  1413. throw new Error('Unexpected stream case');
  1414. }
  1415. },
  1416. /**
  1417. * Sends raw message to the comObj.
  1418. * @private
  1419. * @param {Object} message - Raw message.
  1420. * @param transfers List of transfers/ArrayBuffers, or undefined.
  1421. */
  1422. postMessage(message, transfers) {
  1423. if (transfers && this.postMessageTransfers) {
  1424. this.comObj.postMessage(message, transfers);
  1425. } else {
  1426. this.comObj.postMessage(message);
  1427. }
  1428. },
  1429. destroy() {
  1430. this.comObj.removeEventListener('message', this._onComObjOnMessage);
  1431. },
  1432. };
  1433. function loadJpegStream(id, imageUrl, objs) {
  1434. var img = new Image();
  1435. img.onload = (function loadJpegStream_onloadClosure() {
  1436. objs.resolve(id, img);
  1437. });
  1438. img.onerror = (function loadJpegStream_onerrorClosure() {
  1439. objs.resolve(id, null);
  1440. warn('Error during JPEG image loading');
  1441. });
  1442. img.src = imageUrl;
  1443. }
  1444. export {
  1445. FONT_IDENTITY_MATRIX,
  1446. IDENTITY_MATRIX,
  1447. OPS,
  1448. VERBOSITY_LEVELS,
  1449. UNSUPPORTED_FEATURES,
  1450. AnnotationBorderStyleType,
  1451. AnnotationFieldFlag,
  1452. AnnotationFlag,
  1453. AnnotationType,
  1454. FontType,
  1455. ImageKind,
  1456. CMapCompressionType,
  1457. InvalidPDFException,
  1458. MessageHandler,
  1459. MissingDataException,
  1460. MissingPDFException,
  1461. NativeImageDecoding,
  1462. NotImplementedException,
  1463. PageViewport,
  1464. PasswordException,
  1465. PasswordResponses,
  1466. StatTimer,
  1467. StreamType,
  1468. TextRenderingMode,
  1469. UnexpectedResponseException,
  1470. UnknownErrorException,
  1471. Util,
  1472. XRefParseException,
  1473. arrayByteLength,
  1474. arraysToBytes,
  1475. assert,
  1476. bytesToString,
  1477. createBlob,
  1478. createPromiseCapability,
  1479. createObjectURL,
  1480. deprecated,
  1481. error,
  1482. getLookupTableFactory,
  1483. getVerbosityLevel,
  1484. globalScope,
  1485. info,
  1486. isArray,
  1487. isArrayBuffer,
  1488. isBool,
  1489. isEmptyObj,
  1490. isInt,
  1491. isNum,
  1492. isString,
  1493. isSpace,
  1494. isNodeJS,
  1495. isSameOrigin,
  1496. createValidAbsoluteUrl,
  1497. isLittleEndian,
  1498. isEvalSupported,
  1499. loadJpegStream,
  1500. log2,
  1501. readInt8,
  1502. readUint16,
  1503. readUint32,
  1504. removeNullCharacters,
  1505. ReadableStream,
  1506. setVerbosityLevel,
  1507. shadow,
  1508. string32,
  1509. stringToBytes,
  1510. stringToPDFString,
  1511. stringToUTF8String,
  1512. utf8StringToString,
  1513. warn,
  1514. };