document.js 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764
  1. /**
  2. * @licstart The following is the entire license notice for the
  3. * Javascript code in this page
  4. *
  5. * Copyright 2020 Mozilla Foundation
  6. *
  7. * Licensed under the Apache License, Version 2.0 (the "License");
  8. * you may not use this file except in compliance with the License.
  9. * You may obtain a copy of the License at
  10. *
  11. * http://www.apache.org/licenses/LICENSE-2.0
  12. *
  13. * Unless required by applicable law or agreed to in writing, software
  14. * distributed under the License is distributed on an "AS IS" BASIS,
  15. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  16. * See the License for the specific language governing permissions and
  17. * limitations under the License.
  18. *
  19. * @licend The above is the entire license notice for the
  20. * Javascript code in this page
  21. */
  22. "use strict";
  23. Object.defineProperty(exports, "__esModule", {
  24. value: true
  25. });
  26. exports.PDFDocument = exports.Page = void 0;
  27. var _util = require("../shared/util.js");
  28. var _obj = require("./obj.js");
  29. var _primitives = require("./primitives.js");
  30. var _core_utils = require("./core_utils.js");
  31. var _stream = require("./stream.js");
  32. var _annotation = require("./annotation.js");
  33. var _crypto = require("./crypto.js");
  34. var _parser = require("./parser.js");
  35. var _operator_list = require("./operator_list.js");
  36. var _evaluator = require("./evaluator.js");
  37. var _function = require("./function.js");
  38. const DEFAULT_USER_UNIT = 1.0;
  39. const LETTER_SIZE_MEDIABOX = [0, 0, 612, 792];
  40. function isAnnotationRenderable(annotation, intent) {
  41. return intent === "display" && annotation.viewable || intent === "print" && annotation.printable;
  42. }
  43. class Page {
  44. constructor({
  45. pdfManager,
  46. xref,
  47. pageIndex,
  48. pageDict,
  49. ref,
  50. fontCache,
  51. builtInCMapCache,
  52. globalImageCache,
  53. pdfFunctionFactory
  54. }) {
  55. this.pdfManager = pdfManager;
  56. this.pageIndex = pageIndex;
  57. this.pageDict = pageDict;
  58. this.xref = xref;
  59. this.ref = ref;
  60. this.fontCache = fontCache;
  61. this.builtInCMapCache = builtInCMapCache;
  62. this.globalImageCache = globalImageCache;
  63. this.pdfFunctionFactory = pdfFunctionFactory;
  64. this.evaluatorOptions = pdfManager.evaluatorOptions;
  65. this.resourcesPromise = null;
  66. const idCounters = {
  67. obj: 0
  68. };
  69. this.idFactory = {
  70. createObjId() {
  71. return `p${pageIndex}_${++idCounters.obj}`;
  72. },
  73. getDocId() {
  74. return `g_${pdfManager.docId}`;
  75. }
  76. };
  77. }
  78. _getInheritableProperty(key, getArray = false) {
  79. const value = (0, _core_utils.getInheritableProperty)({
  80. dict: this.pageDict,
  81. key,
  82. getArray,
  83. stopWhenFound: false
  84. });
  85. if (!Array.isArray(value)) {
  86. return value;
  87. }
  88. if (value.length === 1 || !(0, _primitives.isDict)(value[0])) {
  89. return value[0];
  90. }
  91. return _primitives.Dict.merge(this.xref, value);
  92. }
  93. get content() {
  94. return this.pageDict.get("Contents");
  95. }
  96. get resources() {
  97. return (0, _util.shadow)(this, "resources", this._getInheritableProperty("Resources") || _primitives.Dict.empty);
  98. }
  99. _getBoundingBox(name) {
  100. const box = this._getInheritableProperty(name, true);
  101. if (Array.isArray(box) && box.length === 4) {
  102. if (box[2] - box[0] !== 0 && box[3] - box[1] !== 0) {
  103. return box;
  104. }
  105. (0, _util.warn)(`Empty /${name} entry.`);
  106. }
  107. return null;
  108. }
  109. get mediaBox() {
  110. return (0, _util.shadow)(this, "mediaBox", this._getBoundingBox("MediaBox") || LETTER_SIZE_MEDIABOX);
  111. }
  112. get cropBox() {
  113. return (0, _util.shadow)(this, "cropBox", this._getBoundingBox("CropBox") || this.mediaBox);
  114. }
  115. get userUnit() {
  116. let obj = this.pageDict.get("UserUnit");
  117. if (!(0, _util.isNum)(obj) || obj <= 0) {
  118. obj = DEFAULT_USER_UNIT;
  119. }
  120. return (0, _util.shadow)(this, "userUnit", obj);
  121. }
  122. get view() {
  123. const {
  124. cropBox,
  125. mediaBox
  126. } = this;
  127. let view;
  128. if (cropBox === mediaBox || (0, _util.isArrayEqual)(cropBox, mediaBox)) {
  129. view = mediaBox;
  130. } else {
  131. const box = _util.Util.intersect(cropBox, mediaBox);
  132. if (box && box[2] - box[0] !== 0 && box[3] - box[1] !== 0) {
  133. view = box;
  134. } else {
  135. (0, _util.warn)("Empty /CropBox and /MediaBox intersection.");
  136. }
  137. }
  138. return (0, _util.shadow)(this, "view", view || mediaBox);
  139. }
  140. get rotate() {
  141. let rotate = this._getInheritableProperty("Rotate") || 0;
  142. if (rotate % 90 !== 0) {
  143. rotate = 0;
  144. } else if (rotate >= 360) {
  145. rotate = rotate % 360;
  146. } else if (rotate < 0) {
  147. rotate = (rotate % 360 + 360) % 360;
  148. }
  149. return (0, _util.shadow)(this, "rotate", rotate);
  150. }
  151. getContentStream() {
  152. const content = this.content;
  153. let stream;
  154. if (Array.isArray(content)) {
  155. const xref = this.xref;
  156. const streams = [];
  157. for (const subStream of content) {
  158. streams.push(xref.fetchIfRef(subStream));
  159. }
  160. stream = new _stream.StreamsSequenceStream(streams);
  161. } else if ((0, _primitives.isStream)(content)) {
  162. stream = content;
  163. } else {
  164. stream = new _stream.NullStream();
  165. }
  166. return stream;
  167. }
  168. loadResources(keys) {
  169. if (!this.resourcesPromise) {
  170. this.resourcesPromise = this.pdfManager.ensure(this, "resources");
  171. }
  172. return this.resourcesPromise.then(() => {
  173. const objectLoader = new _obj.ObjectLoader(this.resources, keys, this.xref);
  174. return objectLoader.load();
  175. });
  176. }
  177. getOperatorList({
  178. handler,
  179. sink,
  180. task,
  181. intent,
  182. renderInteractiveForms
  183. }) {
  184. const contentStreamPromise = this.pdfManager.ensure(this, "getContentStream");
  185. const resourcesPromise = this.loadResources(["ExtGState", "ColorSpace", "Pattern", "Shading", "XObject", "Font"]);
  186. const partialEvaluator = new _evaluator.PartialEvaluator({
  187. xref: this.xref,
  188. handler,
  189. pageIndex: this.pageIndex,
  190. idFactory: this.idFactory,
  191. fontCache: this.fontCache,
  192. builtInCMapCache: this.builtInCMapCache,
  193. globalImageCache: this.globalImageCache,
  194. options: this.evaluatorOptions,
  195. pdfFunctionFactory: this.pdfFunctionFactory
  196. });
  197. const dataPromises = Promise.all([contentStreamPromise, resourcesPromise]);
  198. const pageListPromise = dataPromises.then(([contentStream]) => {
  199. const opList = new _operator_list.OperatorList(intent, sink, this.pageIndex);
  200. handler.send("StartRenderPage", {
  201. transparency: partialEvaluator.hasBlendModes(this.resources),
  202. pageIndex: this.pageIndex,
  203. intent
  204. });
  205. return partialEvaluator.getOperatorList({
  206. stream: contentStream,
  207. task,
  208. resources: this.resources,
  209. operatorList: opList
  210. }).then(function () {
  211. return opList;
  212. });
  213. });
  214. return Promise.all([pageListPromise, this._parsedAnnotations]).then(function ([pageOpList, annotations]) {
  215. if (annotations.length === 0) {
  216. pageOpList.flush(true);
  217. return {
  218. length: pageOpList.totalLength
  219. };
  220. }
  221. const opListPromises = [];
  222. for (const annotation of annotations) {
  223. if (isAnnotationRenderable(annotation, intent)) {
  224. opListPromises.push(annotation.getOperatorList(partialEvaluator, task, renderInteractiveForms).catch(function (reason) {
  225. (0, _util.warn)("getOperatorList - ignoring annotation data during " + `"${task.name}" task: "${reason}".`);
  226. return null;
  227. }));
  228. }
  229. }
  230. return Promise.all(opListPromises).then(function (opLists) {
  231. pageOpList.addOp(_util.OPS.beginAnnotations, []);
  232. for (const opList of opLists) {
  233. pageOpList.addOpList(opList);
  234. }
  235. pageOpList.addOp(_util.OPS.endAnnotations, []);
  236. pageOpList.flush(true);
  237. return {
  238. length: pageOpList.totalLength
  239. };
  240. });
  241. });
  242. }
  243. extractTextContent({
  244. handler,
  245. task,
  246. normalizeWhitespace,
  247. sink,
  248. combineTextItems
  249. }) {
  250. const contentStreamPromise = this.pdfManager.ensure(this, "getContentStream");
  251. const resourcesPromise = this.loadResources(["ExtGState", "XObject", "Font"]);
  252. const dataPromises = Promise.all([contentStreamPromise, resourcesPromise]);
  253. return dataPromises.then(([contentStream]) => {
  254. const partialEvaluator = new _evaluator.PartialEvaluator({
  255. xref: this.xref,
  256. handler,
  257. pageIndex: this.pageIndex,
  258. idFactory: this.idFactory,
  259. fontCache: this.fontCache,
  260. builtInCMapCache: this.builtInCMapCache,
  261. globalImageCache: this.globalImageCache,
  262. options: this.evaluatorOptions,
  263. pdfFunctionFactory: this.pdfFunctionFactory
  264. });
  265. return partialEvaluator.getTextContent({
  266. stream: contentStream,
  267. task,
  268. resources: this.resources,
  269. normalizeWhitespace,
  270. combineTextItems,
  271. sink
  272. });
  273. });
  274. }
  275. getAnnotationsData(intent) {
  276. return this._parsedAnnotations.then(function (annotations) {
  277. const annotationsData = [];
  278. for (let i = 0, ii = annotations.length; i < ii; i++) {
  279. if (!intent || isAnnotationRenderable(annotations[i], intent)) {
  280. annotationsData.push(annotations[i].data);
  281. }
  282. }
  283. return annotationsData;
  284. });
  285. }
  286. get annotations() {
  287. return (0, _util.shadow)(this, "annotations", this._getInheritableProperty("Annots") || []);
  288. }
  289. get _parsedAnnotations() {
  290. const parsedAnnotations = this.pdfManager.ensure(this, "annotations").then(() => {
  291. const annotationPromises = [];
  292. for (const annotationRef of this.annotations) {
  293. annotationPromises.push(_annotation.AnnotationFactory.create(this.xref, annotationRef, this.pdfManager, this.idFactory).catch(function (reason) {
  294. (0, _util.warn)(`_parsedAnnotations: "${reason}".`);
  295. return null;
  296. }));
  297. }
  298. return Promise.all(annotationPromises).then(function (annotations) {
  299. return annotations.filter(annotation => !!annotation);
  300. });
  301. });
  302. return (0, _util.shadow)(this, "_parsedAnnotations", parsedAnnotations);
  303. }
  304. }
  305. exports.Page = Page;
  306. const PDF_HEADER_SIGNATURE = new Uint8Array([0x25, 0x50, 0x44, 0x46, 0x2d]);
  307. const STARTXREF_SIGNATURE = new Uint8Array([0x73, 0x74, 0x61, 0x72, 0x74, 0x78, 0x72, 0x65, 0x66]);
  308. const ENDOBJ_SIGNATURE = new Uint8Array([0x65, 0x6e, 0x64, 0x6f, 0x62, 0x6a]);
  309. const FINGERPRINT_FIRST_BYTES = 1024;
  310. const EMPTY_FINGERPRINT = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
  311. const PDF_HEADER_VERSION_REGEXP = /^[1-9]\.[0-9]$/;
  312. function find(stream, signature, limit = 1024, backwards = false) {
  313. const signatureLength = signature.length;
  314. const scanBytes = stream.peekBytes(limit);
  315. const scanLength = scanBytes.length - signatureLength;
  316. if (scanLength <= 0) {
  317. return false;
  318. }
  319. if (backwards) {
  320. const signatureEnd = signatureLength - 1;
  321. let pos = scanBytes.length - 1;
  322. while (pos >= signatureEnd) {
  323. let j = 0;
  324. while (j < signatureLength && scanBytes[pos - j] === signature[signatureEnd - j]) {
  325. j++;
  326. }
  327. if (j >= signatureLength) {
  328. stream.pos += pos - signatureEnd;
  329. return true;
  330. }
  331. pos--;
  332. }
  333. } else {
  334. let pos = 0;
  335. while (pos <= scanLength) {
  336. let j = 0;
  337. while (j < signatureLength && scanBytes[pos + j] === signature[j]) {
  338. j++;
  339. }
  340. if (j >= signatureLength) {
  341. stream.pos += pos;
  342. return true;
  343. }
  344. pos++;
  345. }
  346. }
  347. return false;
  348. }
  349. class PDFDocument {
  350. constructor(pdfManager, arg) {
  351. let stream;
  352. if ((0, _primitives.isStream)(arg)) {
  353. stream = arg;
  354. } else if ((0, _util.isArrayBuffer)(arg)) {
  355. stream = new _stream.Stream(arg);
  356. } else {
  357. throw new Error("PDFDocument: Unknown argument type");
  358. }
  359. if (stream.length <= 0) {
  360. throw new _util.InvalidPDFException("The PDF file is empty, i.e. its size is zero bytes.");
  361. }
  362. this.pdfManager = pdfManager;
  363. this.stream = stream;
  364. this.xref = new _obj.XRef(stream, pdfManager);
  365. this.pdfFunctionFactory = new _function.PDFFunctionFactory({
  366. xref: this.xref,
  367. isEvalSupported: pdfManager.evaluatorOptions.isEvalSupported
  368. });
  369. this._pagePromises = [];
  370. }
  371. parse(recoveryMode) {
  372. this.setup(recoveryMode);
  373. const version = this.catalog.catDict.get("Version");
  374. if ((0, _primitives.isName)(version)) {
  375. this.pdfFormatVersion = version.name;
  376. }
  377. try {
  378. this.acroForm = this.catalog.catDict.get("AcroForm");
  379. if (this.acroForm) {
  380. this.xfa = this.acroForm.get("XFA");
  381. const fields = this.acroForm.get("Fields");
  382. if ((!Array.isArray(fields) || fields.length === 0) && !this.xfa) {
  383. this.acroForm = null;
  384. }
  385. }
  386. } catch (ex) {
  387. if (ex instanceof _core_utils.MissingDataException) {
  388. throw ex;
  389. }
  390. (0, _util.info)("Cannot fetch AcroForm entry; assuming no AcroForms are present");
  391. this.acroForm = null;
  392. }
  393. try {
  394. const collection = this.catalog.catDict.get("Collection");
  395. if ((0, _primitives.isDict)(collection) && collection.getKeys().length > 0) {
  396. this.collection = collection;
  397. }
  398. } catch (ex) {
  399. if (ex instanceof _core_utils.MissingDataException) {
  400. throw ex;
  401. }
  402. (0, _util.info)("Cannot fetch Collection dictionary.");
  403. }
  404. }
  405. get linearization() {
  406. let linearization = null;
  407. try {
  408. linearization = _parser.Linearization.create(this.stream);
  409. } catch (err) {
  410. if (err instanceof _core_utils.MissingDataException) {
  411. throw err;
  412. }
  413. (0, _util.info)(err);
  414. }
  415. return (0, _util.shadow)(this, "linearization", linearization);
  416. }
  417. get startXRef() {
  418. const stream = this.stream;
  419. let startXRef = 0;
  420. if (this.linearization) {
  421. stream.reset();
  422. if (find(stream, ENDOBJ_SIGNATURE)) {
  423. startXRef = stream.pos + 6 - stream.start;
  424. }
  425. } else {
  426. const step = 1024;
  427. const startXRefLength = STARTXREF_SIGNATURE.length;
  428. let found = false,
  429. pos = stream.end;
  430. while (!found && pos > 0) {
  431. pos -= step - startXRefLength;
  432. if (pos < 0) {
  433. pos = 0;
  434. }
  435. stream.pos = pos;
  436. found = find(stream, STARTXREF_SIGNATURE, step, true);
  437. }
  438. if (found) {
  439. stream.skip(9);
  440. let ch;
  441. do {
  442. ch = stream.getByte();
  443. } while ((0, _core_utils.isWhiteSpace)(ch));
  444. let str = "";
  445. while (ch >= 0x20 && ch <= 0x39) {
  446. str += String.fromCharCode(ch);
  447. ch = stream.getByte();
  448. }
  449. startXRef = parseInt(str, 10);
  450. if (isNaN(startXRef)) {
  451. startXRef = 0;
  452. }
  453. }
  454. }
  455. return (0, _util.shadow)(this, "startXRef", startXRef);
  456. }
  457. checkHeader() {
  458. const stream = this.stream;
  459. stream.reset();
  460. if (!find(stream, PDF_HEADER_SIGNATURE)) {
  461. return;
  462. }
  463. stream.moveStart();
  464. const MAX_PDF_VERSION_LENGTH = 12;
  465. let version = "",
  466. ch;
  467. while ((ch = stream.getByte()) > 0x20) {
  468. if (version.length >= MAX_PDF_VERSION_LENGTH) {
  469. break;
  470. }
  471. version += String.fromCharCode(ch);
  472. }
  473. if (!this.pdfFormatVersion) {
  474. this.pdfFormatVersion = version.substring(5);
  475. }
  476. }
  477. parseStartXRef() {
  478. this.xref.setStartXRef(this.startXRef);
  479. }
  480. setup(recoveryMode) {
  481. this.xref.parse(recoveryMode);
  482. this.catalog = new _obj.Catalog(this.pdfManager, this.xref);
  483. }
  484. get numPages() {
  485. const linearization = this.linearization;
  486. const num = linearization ? linearization.numPages : this.catalog.numPages;
  487. return (0, _util.shadow)(this, "numPages", num);
  488. }
  489. get documentInfo() {
  490. const DocumentInfoValidators = {
  491. Title: _util.isString,
  492. Author: _util.isString,
  493. Subject: _util.isString,
  494. Keywords: _util.isString,
  495. Creator: _util.isString,
  496. Producer: _util.isString,
  497. CreationDate: _util.isString,
  498. ModDate: _util.isString,
  499. Trapped: _primitives.isName
  500. };
  501. let version = this.pdfFormatVersion;
  502. if (typeof version !== "string" || !PDF_HEADER_VERSION_REGEXP.test(version)) {
  503. (0, _util.warn)(`Invalid PDF header version number: ${version}`);
  504. version = null;
  505. }
  506. const docInfo = {
  507. PDFFormatVersion: version,
  508. IsLinearized: !!this.linearization,
  509. IsAcroFormPresent: !!this.acroForm,
  510. IsXFAPresent: !!this.xfa,
  511. IsCollectionPresent: !!this.collection
  512. };
  513. let infoDict;
  514. try {
  515. infoDict = this.xref.trailer.get("Info");
  516. } catch (err) {
  517. if (err instanceof _core_utils.MissingDataException) {
  518. throw err;
  519. }
  520. (0, _util.info)("The document information dictionary is invalid.");
  521. }
  522. if ((0, _primitives.isDict)(infoDict)) {
  523. for (const key of infoDict.getKeys()) {
  524. const value = infoDict.get(key);
  525. if (DocumentInfoValidators[key]) {
  526. if (DocumentInfoValidators[key](value)) {
  527. docInfo[key] = typeof value !== "string" ? value : (0, _util.stringToPDFString)(value);
  528. } else {
  529. (0, _util.info)(`Bad value in document info for "${key}".`);
  530. }
  531. } else if (typeof key === "string") {
  532. let customValue;
  533. if ((0, _util.isString)(value)) {
  534. customValue = (0, _util.stringToPDFString)(value);
  535. } else if ((0, _primitives.isName)(value) || (0, _util.isNum)(value) || (0, _util.isBool)(value)) {
  536. customValue = value;
  537. } else {
  538. (0, _util.info)(`Unsupported value in document info for (custom) "${key}".`);
  539. continue;
  540. }
  541. if (!docInfo.Custom) {
  542. docInfo.Custom = Object.create(null);
  543. }
  544. docInfo.Custom[key] = customValue;
  545. }
  546. }
  547. }
  548. return (0, _util.shadow)(this, "documentInfo", docInfo);
  549. }
  550. get fingerprint() {
  551. let hash;
  552. const idArray = this.xref.trailer.get("ID");
  553. if (Array.isArray(idArray) && idArray[0] && (0, _util.isString)(idArray[0]) && idArray[0] !== EMPTY_FINGERPRINT) {
  554. hash = (0, _util.stringToBytes)(idArray[0]);
  555. } else {
  556. hash = (0, _crypto.calculateMD5)(this.stream.getByteRange(0, FINGERPRINT_FIRST_BYTES), 0, FINGERPRINT_FIRST_BYTES);
  557. }
  558. const fingerprintBuf = [];
  559. for (let i = 0, ii = hash.length; i < ii; i++) {
  560. const hex = hash[i].toString(16);
  561. fingerprintBuf.push(hex.padStart(2, "0"));
  562. }
  563. return (0, _util.shadow)(this, "fingerprint", fingerprintBuf.join(""));
  564. }
  565. _getLinearizationPage(pageIndex) {
  566. const {
  567. catalog,
  568. linearization
  569. } = this;
  570. const ref = _primitives.Ref.get(linearization.objectNumberFirst, 0);
  571. return this.xref.fetchAsync(ref).then(obj => {
  572. if ((0, _primitives.isDict)(obj, "Page") || (0, _primitives.isDict)(obj) && !obj.has("Type") && obj.has("Contents")) {
  573. if (ref && !catalog.pageKidsCountCache.has(ref)) {
  574. catalog.pageKidsCountCache.put(ref, 1);
  575. }
  576. return [obj, ref];
  577. }
  578. throw new _util.FormatError("The Linearization dictionary doesn't point " + "to a valid Page dictionary.");
  579. }).catch(reason => {
  580. (0, _util.info)(reason);
  581. return catalog.getPageDict(pageIndex);
  582. });
  583. }
  584. getPage(pageIndex) {
  585. if (this._pagePromises[pageIndex] !== undefined) {
  586. return this._pagePromises[pageIndex];
  587. }
  588. const {
  589. catalog,
  590. linearization
  591. } = this;
  592. const promise = linearization && linearization.pageFirst === pageIndex ? this._getLinearizationPage(pageIndex) : catalog.getPageDict(pageIndex);
  593. return this._pagePromises[pageIndex] = promise.then(([pageDict, ref]) => {
  594. return new Page({
  595. pdfManager: this.pdfManager,
  596. xref: this.xref,
  597. pageIndex,
  598. pageDict,
  599. ref,
  600. fontCache: catalog.fontCache,
  601. builtInCMapCache: catalog.builtInCMapCache,
  602. globalImageCache: catalog.globalImageCache,
  603. pdfFunctionFactory: this.pdfFunctionFactory
  604. });
  605. });
  606. }
  607. checkFirstPage() {
  608. return this.getPage(0).catch(async reason => {
  609. if (reason instanceof _core_utils.XRefEntryException) {
  610. this._pagePromises.length = 0;
  611. await this.cleanup();
  612. throw new _core_utils.XRefParseException();
  613. }
  614. });
  615. }
  616. fontFallback(id, handler) {
  617. return this.catalog.fontFallback(id, handler);
  618. }
  619. async cleanup(manuallyTriggered = false) {
  620. return this.catalog ? this.catalog.cleanup(manuallyTriggered) : (0, _primitives.clearPrimitiveCaches)();
  621. }
  622. }
  623. exports.PDFDocument = PDFDocument;