2
0

annotation.js 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098
  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.getQuadPoints = getQuadPoints;
  27. exports.MarkupAnnotation = exports.AnnotationFactory = exports.AnnotationBorderStyle = exports.Annotation = void 0;
  28. var _util = require("../shared/util.js");
  29. var _obj = require("./obj.js");
  30. var _primitives = require("./primitives.js");
  31. var _colorspace = require("./colorspace.js");
  32. var _core_utils = require("./core_utils.js");
  33. var _operator_list = require("./operator_list.js");
  34. var _stream = require("./stream.js");
  35. class AnnotationFactory {
  36. static create(xref, ref, pdfManager, idFactory) {
  37. return pdfManager.ensure(this, "_create", [xref, ref, pdfManager, idFactory]);
  38. }
  39. static _create(xref, ref, pdfManager, idFactory) {
  40. const dict = xref.fetchIfRef(ref);
  41. if (!(0, _primitives.isDict)(dict)) {
  42. return undefined;
  43. }
  44. const id = (0, _primitives.isRef)(ref) ? ref.toString() : `annot_${idFactory.createObjId()}`;
  45. let subtype = dict.get("Subtype");
  46. subtype = (0, _primitives.isName)(subtype) ? subtype.name : null;
  47. const parameters = {
  48. xref,
  49. dict,
  50. subtype,
  51. id,
  52. pdfManager
  53. };
  54. switch (subtype) {
  55. case "Link":
  56. return new LinkAnnotation(parameters);
  57. case "Text":
  58. return new TextAnnotation(parameters);
  59. case "Widget":
  60. let fieldType = (0, _core_utils.getInheritableProperty)({
  61. dict,
  62. key: "FT"
  63. });
  64. fieldType = (0, _primitives.isName)(fieldType) ? fieldType.name : null;
  65. switch (fieldType) {
  66. case "Tx":
  67. return new TextWidgetAnnotation(parameters);
  68. case "Btn":
  69. return new ButtonWidgetAnnotation(parameters);
  70. case "Ch":
  71. return new ChoiceWidgetAnnotation(parameters);
  72. }
  73. (0, _util.warn)('Unimplemented widget field type "' + fieldType + '", ' + "falling back to base field type.");
  74. return new WidgetAnnotation(parameters);
  75. case "Popup":
  76. return new PopupAnnotation(parameters);
  77. case "FreeText":
  78. return new FreeTextAnnotation(parameters);
  79. case "Line":
  80. return new LineAnnotation(parameters);
  81. case "Square":
  82. return new SquareAnnotation(parameters);
  83. case "Circle":
  84. return new CircleAnnotation(parameters);
  85. case "PolyLine":
  86. return new PolylineAnnotation(parameters);
  87. case "Polygon":
  88. return new PolygonAnnotation(parameters);
  89. case "Caret":
  90. return new CaretAnnotation(parameters);
  91. case "Ink":
  92. return new InkAnnotation(parameters);
  93. case "Highlight":
  94. return new HighlightAnnotation(parameters);
  95. case "Underline":
  96. return new UnderlineAnnotation(parameters);
  97. case "Squiggly":
  98. return new SquigglyAnnotation(parameters);
  99. case "StrikeOut":
  100. return new StrikeOutAnnotation(parameters);
  101. case "Stamp":
  102. return new StampAnnotation(parameters);
  103. case "FileAttachment":
  104. return new FileAttachmentAnnotation(parameters);
  105. default:
  106. if (!subtype) {
  107. (0, _util.warn)("Annotation is missing the required /Subtype.");
  108. } else {
  109. (0, _util.warn)('Unimplemented annotation type "' + subtype + '", ' + "falling back to base annotation.");
  110. }
  111. return new Annotation(parameters);
  112. }
  113. }
  114. }
  115. exports.AnnotationFactory = AnnotationFactory;
  116. function getQuadPoints(dict, rect) {
  117. if (!dict.has("QuadPoints")) {
  118. return null;
  119. }
  120. const quadPoints = dict.getArray("QuadPoints");
  121. if (!Array.isArray(quadPoints) || quadPoints.length % 8 > 0) {
  122. return null;
  123. }
  124. const quadPointsLists = [];
  125. for (let i = 0, ii = quadPoints.length / 8; i < ii; i++) {
  126. quadPointsLists.push([]);
  127. for (let j = i * 8, jj = i * 8 + 8; j < jj; j += 2) {
  128. const x = quadPoints[j];
  129. const y = quadPoints[j + 1];
  130. if (x < rect[0] || x > rect[2] || y < rect[1] || y > rect[3]) {
  131. return null;
  132. }
  133. quadPointsLists[i].push({
  134. x,
  135. y
  136. });
  137. }
  138. }
  139. return quadPointsLists;
  140. }
  141. function getTransformMatrix(rect, bbox, matrix) {
  142. const [minX, minY, maxX, maxY] = _util.Util.getAxialAlignedBoundingBox(bbox, matrix);
  143. if (minX === maxX || minY === maxY) {
  144. return [1, 0, 0, 1, rect[0], rect[1]];
  145. }
  146. const xRatio = (rect[2] - rect[0]) / (maxX - minX);
  147. const yRatio = (rect[3] - rect[1]) / (maxY - minY);
  148. return [xRatio, 0, 0, yRatio, rect[0] - minX * xRatio, rect[1] - minY * yRatio];
  149. }
  150. class Annotation {
  151. constructor(params) {
  152. const dict = params.dict;
  153. this.setContents(dict.get("Contents"));
  154. this.setModificationDate(dict.get("M"));
  155. this.setFlags(dict.get("F"));
  156. this.setRectangle(dict.getArray("Rect"));
  157. this.setColor(dict.getArray("C"));
  158. this.setBorderStyle(dict);
  159. this.setAppearance(dict);
  160. this.data = {
  161. annotationFlags: this.flags,
  162. borderStyle: this.borderStyle,
  163. color: this.color,
  164. contents: this.contents,
  165. hasAppearance: !!this.appearance,
  166. id: params.id,
  167. modificationDate: this.modificationDate,
  168. rect: this.rectangle,
  169. subtype: params.subtype
  170. };
  171. }
  172. _hasFlag(flags, flag) {
  173. return !!(flags & flag);
  174. }
  175. _isViewable(flags) {
  176. return !this._hasFlag(flags, _util.AnnotationFlag.INVISIBLE) && !this._hasFlag(flags, _util.AnnotationFlag.HIDDEN) && !this._hasFlag(flags, _util.AnnotationFlag.NOVIEW);
  177. }
  178. _isPrintable(flags) {
  179. return this._hasFlag(flags, _util.AnnotationFlag.PRINT) && !this._hasFlag(flags, _util.AnnotationFlag.INVISIBLE) && !this._hasFlag(flags, _util.AnnotationFlag.HIDDEN);
  180. }
  181. get viewable() {
  182. if (this.flags === 0) {
  183. return true;
  184. }
  185. return this._isViewable(this.flags);
  186. }
  187. get printable() {
  188. if (this.flags === 0) {
  189. return false;
  190. }
  191. return this._isPrintable(this.flags);
  192. }
  193. setContents(contents) {
  194. this.contents = (0, _util.stringToPDFString)(contents || "");
  195. }
  196. setModificationDate(modificationDate) {
  197. this.modificationDate = (0, _util.isString)(modificationDate) ? modificationDate : null;
  198. }
  199. setFlags(flags) {
  200. this.flags = Number.isInteger(flags) && flags > 0 ? flags : 0;
  201. }
  202. hasFlag(flag) {
  203. return this._hasFlag(this.flags, flag);
  204. }
  205. setRectangle(rectangle) {
  206. if (Array.isArray(rectangle) && rectangle.length === 4) {
  207. this.rectangle = _util.Util.normalizeRect(rectangle);
  208. } else {
  209. this.rectangle = [0, 0, 0, 0];
  210. }
  211. }
  212. setColor(color) {
  213. const rgbColor = new Uint8ClampedArray(3);
  214. if (!Array.isArray(color)) {
  215. this.color = rgbColor;
  216. return;
  217. }
  218. switch (color.length) {
  219. case 0:
  220. this.color = null;
  221. break;
  222. case 1:
  223. _colorspace.ColorSpace.singletons.gray.getRgbItem(color, 0, rgbColor, 0);
  224. this.color = rgbColor;
  225. break;
  226. case 3:
  227. _colorspace.ColorSpace.singletons.rgb.getRgbItem(color, 0, rgbColor, 0);
  228. this.color = rgbColor;
  229. break;
  230. case 4:
  231. _colorspace.ColorSpace.singletons.cmyk.getRgbItem(color, 0, rgbColor, 0);
  232. this.color = rgbColor;
  233. break;
  234. default:
  235. this.color = rgbColor;
  236. break;
  237. }
  238. }
  239. setBorderStyle(borderStyle) {
  240. this.borderStyle = new AnnotationBorderStyle();
  241. if (!(0, _primitives.isDict)(borderStyle)) {
  242. return;
  243. }
  244. if (borderStyle.has("BS")) {
  245. const dict = borderStyle.get("BS");
  246. const dictType = dict.get("Type");
  247. if (!dictType || (0, _primitives.isName)(dictType, "Border")) {
  248. this.borderStyle.setWidth(dict.get("W"), this.rectangle);
  249. this.borderStyle.setStyle(dict.get("S"));
  250. this.borderStyle.setDashArray(dict.getArray("D"));
  251. }
  252. } else if (borderStyle.has("Border")) {
  253. const array = borderStyle.getArray("Border");
  254. if (Array.isArray(array) && array.length >= 3) {
  255. this.borderStyle.setHorizontalCornerRadius(array[0]);
  256. this.borderStyle.setVerticalCornerRadius(array[1]);
  257. this.borderStyle.setWidth(array[2], this.rectangle);
  258. if (array.length === 4) {
  259. this.borderStyle.setDashArray(array[3]);
  260. }
  261. }
  262. } else {
  263. this.borderStyle.setWidth(0);
  264. }
  265. }
  266. setAppearance(dict) {
  267. this.appearance = null;
  268. const appearanceStates = dict.get("AP");
  269. if (!(0, _primitives.isDict)(appearanceStates)) {
  270. return;
  271. }
  272. const normalAppearanceState = appearanceStates.get("N");
  273. if ((0, _primitives.isStream)(normalAppearanceState)) {
  274. this.appearance = normalAppearanceState;
  275. return;
  276. }
  277. if (!(0, _primitives.isDict)(normalAppearanceState)) {
  278. return;
  279. }
  280. const as = dict.get("AS");
  281. if (!(0, _primitives.isName)(as) || !normalAppearanceState.has(as.name)) {
  282. return;
  283. }
  284. this.appearance = normalAppearanceState.get(as.name);
  285. }
  286. loadResources(keys) {
  287. return this.appearance.dict.getAsync("Resources").then(resources => {
  288. if (!resources) {
  289. return undefined;
  290. }
  291. const objectLoader = new _obj.ObjectLoader(resources, keys, resources.xref);
  292. return objectLoader.load().then(function () {
  293. return resources;
  294. });
  295. });
  296. }
  297. getOperatorList(evaluator, task, renderForms) {
  298. if (!this.appearance) {
  299. return Promise.resolve(new _operator_list.OperatorList());
  300. }
  301. const data = this.data;
  302. const appearanceDict = this.appearance.dict;
  303. const resourcesPromise = this.loadResources(["ExtGState", "ColorSpace", "Pattern", "Shading", "XObject", "Font"]);
  304. const bbox = appearanceDict.getArray("BBox") || [0, 0, 1, 1];
  305. const matrix = appearanceDict.getArray("Matrix") || [1, 0, 0, 1, 0, 0];
  306. const transform = getTransformMatrix(data.rect, bbox, matrix);
  307. return resourcesPromise.then(resources => {
  308. const opList = new _operator_list.OperatorList();
  309. opList.addOp(_util.OPS.beginAnnotation, [data.rect, transform, matrix]);
  310. return evaluator.getOperatorList({
  311. stream: this.appearance,
  312. task,
  313. resources,
  314. operatorList: opList
  315. }).then(() => {
  316. opList.addOp(_util.OPS.endAnnotation, []);
  317. this.appearance.reset();
  318. return opList;
  319. });
  320. });
  321. }
  322. }
  323. exports.Annotation = Annotation;
  324. class AnnotationBorderStyle {
  325. constructor() {
  326. this.width = 1;
  327. this.style = _util.AnnotationBorderStyleType.SOLID;
  328. this.dashArray = [3];
  329. this.horizontalCornerRadius = 0;
  330. this.verticalCornerRadius = 0;
  331. }
  332. setWidth(width, rect = [0, 0, 0, 0]) {
  333. if ((0, _primitives.isName)(width)) {
  334. this.width = 0;
  335. return;
  336. }
  337. if (Number.isInteger(width)) {
  338. if (width > 0) {
  339. const maxWidth = (rect[2] - rect[0]) / 2;
  340. const maxHeight = (rect[3] - rect[1]) / 2;
  341. if (maxWidth > 0 && maxHeight > 0 && (width > maxWidth || width > maxHeight)) {
  342. (0, _util.warn)(`AnnotationBorderStyle.setWidth - ignoring width: ${width}`);
  343. width = 1;
  344. }
  345. }
  346. this.width = width;
  347. }
  348. }
  349. setStyle(style) {
  350. if (!(0, _primitives.isName)(style)) {
  351. return;
  352. }
  353. switch (style.name) {
  354. case "S":
  355. this.style = _util.AnnotationBorderStyleType.SOLID;
  356. break;
  357. case "D":
  358. this.style = _util.AnnotationBorderStyleType.DASHED;
  359. break;
  360. case "B":
  361. this.style = _util.AnnotationBorderStyleType.BEVELED;
  362. break;
  363. case "I":
  364. this.style = _util.AnnotationBorderStyleType.INSET;
  365. break;
  366. case "U":
  367. this.style = _util.AnnotationBorderStyleType.UNDERLINE;
  368. break;
  369. default:
  370. break;
  371. }
  372. }
  373. setDashArray(dashArray) {
  374. if (Array.isArray(dashArray) && dashArray.length > 0) {
  375. let isValid = true;
  376. let allZeros = true;
  377. for (const element of dashArray) {
  378. const validNumber = +element >= 0;
  379. if (!validNumber) {
  380. isValid = false;
  381. break;
  382. } else if (element > 0) {
  383. allZeros = false;
  384. }
  385. }
  386. if (isValid && !allZeros) {
  387. this.dashArray = dashArray;
  388. } else {
  389. this.width = 0;
  390. }
  391. } else if (dashArray) {
  392. this.width = 0;
  393. }
  394. }
  395. setHorizontalCornerRadius(radius) {
  396. if (Number.isInteger(radius)) {
  397. this.horizontalCornerRadius = radius;
  398. }
  399. }
  400. setVerticalCornerRadius(radius) {
  401. if (Number.isInteger(radius)) {
  402. this.verticalCornerRadius = radius;
  403. }
  404. }
  405. }
  406. exports.AnnotationBorderStyle = AnnotationBorderStyle;
  407. class MarkupAnnotation extends Annotation {
  408. constructor(parameters) {
  409. super(parameters);
  410. const dict = parameters.dict;
  411. if (dict.has("IRT")) {
  412. const rawIRT = dict.getRaw("IRT");
  413. this.data.inReplyTo = (0, _primitives.isRef)(rawIRT) ? rawIRT.toString() : null;
  414. const rt = dict.get("RT");
  415. this.data.replyType = (0, _primitives.isName)(rt) ? rt.name : _util.AnnotationReplyType.REPLY;
  416. }
  417. if (this.data.replyType === _util.AnnotationReplyType.GROUP) {
  418. const parent = dict.get("IRT");
  419. this.data.title = (0, _util.stringToPDFString)(parent.get("T") || "");
  420. this.setContents(parent.get("Contents"));
  421. this.data.contents = this.contents;
  422. if (!parent.has("CreationDate")) {
  423. this.data.creationDate = null;
  424. } else {
  425. this.setCreationDate(parent.get("CreationDate"));
  426. this.data.creationDate = this.creationDate;
  427. }
  428. if (!parent.has("M")) {
  429. this.data.modificationDate = null;
  430. } else {
  431. this.setModificationDate(parent.get("M"));
  432. this.data.modificationDate = this.modificationDate;
  433. }
  434. this.data.hasPopup = parent.has("Popup");
  435. if (!parent.has("C")) {
  436. this.data.color = null;
  437. } else {
  438. this.setColor(parent.getArray("C"));
  439. this.data.color = this.color;
  440. }
  441. } else {
  442. this.data.title = (0, _util.stringToPDFString)(dict.get("T") || "");
  443. this.setCreationDate(dict.get("CreationDate"));
  444. this.data.creationDate = this.creationDate;
  445. this.data.hasPopup = dict.has("Popup");
  446. if (!dict.has("C")) {
  447. this.data.color = null;
  448. }
  449. }
  450. }
  451. setCreationDate(creationDate) {
  452. this.creationDate = (0, _util.isString)(creationDate) ? creationDate : null;
  453. }
  454. }
  455. exports.MarkupAnnotation = MarkupAnnotation;
  456. class WidgetAnnotation extends Annotation {
  457. constructor(params) {
  458. super(params);
  459. const dict = params.dict;
  460. const data = this.data;
  461. data.annotationType = _util.AnnotationType.WIDGET;
  462. data.fieldName = this._constructFieldName(dict);
  463. data.fieldValue = (0, _core_utils.getInheritableProperty)({
  464. dict,
  465. key: "V",
  466. getArray: true
  467. });
  468. data.alternativeText = (0, _util.stringToPDFString)(dict.get("TU") || "");
  469. data.defaultAppearance = (0, _core_utils.getInheritableProperty)({
  470. dict,
  471. key: "DA"
  472. }) || "";
  473. const fieldType = (0, _core_utils.getInheritableProperty)({
  474. dict,
  475. key: "FT"
  476. });
  477. data.fieldType = (0, _primitives.isName)(fieldType) ? fieldType.name : null;
  478. this.fieldResources = (0, _core_utils.getInheritableProperty)({
  479. dict,
  480. key: "DR"
  481. }) || _primitives.Dict.empty;
  482. data.fieldFlags = (0, _core_utils.getInheritableProperty)({
  483. dict,
  484. key: "Ff"
  485. });
  486. if (!Number.isInteger(data.fieldFlags) || data.fieldFlags < 0) {
  487. data.fieldFlags = 0;
  488. }
  489. data.readOnly = this.hasFieldFlag(_util.AnnotationFieldFlag.READONLY);
  490. if (data.fieldType === "Sig") {
  491. data.fieldValue = null;
  492. this.setFlags(_util.AnnotationFlag.HIDDEN);
  493. }
  494. }
  495. _constructFieldName(dict) {
  496. if (!dict.has("T") && !dict.has("Parent")) {
  497. (0, _util.warn)("Unknown field name, falling back to empty field name.");
  498. return "";
  499. }
  500. if (!dict.has("Parent")) {
  501. return (0, _util.stringToPDFString)(dict.get("T"));
  502. }
  503. const fieldName = [];
  504. if (dict.has("T")) {
  505. fieldName.unshift((0, _util.stringToPDFString)(dict.get("T")));
  506. }
  507. let loopDict = dict;
  508. while (loopDict.has("Parent")) {
  509. loopDict = loopDict.get("Parent");
  510. if (!(0, _primitives.isDict)(loopDict)) {
  511. break;
  512. }
  513. if (loopDict.has("T")) {
  514. fieldName.unshift((0, _util.stringToPDFString)(loopDict.get("T")));
  515. }
  516. }
  517. return fieldName.join(".");
  518. }
  519. hasFieldFlag(flag) {
  520. return !!(this.data.fieldFlags & flag);
  521. }
  522. getOperatorList(evaluator, task, renderForms) {
  523. if (renderForms) {
  524. return Promise.resolve(new _operator_list.OperatorList());
  525. }
  526. return super.getOperatorList(evaluator, task, renderForms);
  527. }
  528. }
  529. class TextWidgetAnnotation extends WidgetAnnotation {
  530. constructor(params) {
  531. super(params);
  532. const dict = params.dict;
  533. this.data.fieldValue = (0, _util.stringToPDFString)(this.data.fieldValue || "");
  534. let alignment = (0, _core_utils.getInheritableProperty)({
  535. dict,
  536. key: "Q"
  537. });
  538. if (!Number.isInteger(alignment) || alignment < 0 || alignment > 2) {
  539. alignment = null;
  540. }
  541. this.data.textAlignment = alignment;
  542. let maximumLength = (0, _core_utils.getInheritableProperty)({
  543. dict,
  544. key: "MaxLen"
  545. });
  546. if (!Number.isInteger(maximumLength) || maximumLength < 0) {
  547. maximumLength = null;
  548. }
  549. this.data.maxLen = maximumLength;
  550. this.data.multiLine = this.hasFieldFlag(_util.AnnotationFieldFlag.MULTILINE);
  551. this.data.comb = this.hasFieldFlag(_util.AnnotationFieldFlag.COMB) && !this.hasFieldFlag(_util.AnnotationFieldFlag.MULTILINE) && !this.hasFieldFlag(_util.AnnotationFieldFlag.PASSWORD) && !this.hasFieldFlag(_util.AnnotationFieldFlag.FILESELECT) && this.data.maxLen !== null;
  552. }
  553. getOperatorList(evaluator, task, renderForms) {
  554. if (renderForms || this.appearance) {
  555. return super.getOperatorList(evaluator, task, renderForms);
  556. }
  557. const operatorList = new _operator_list.OperatorList();
  558. if (!this.data.defaultAppearance) {
  559. return Promise.resolve(operatorList);
  560. }
  561. const stream = new _stream.Stream((0, _util.stringToBytes)(this.data.defaultAppearance));
  562. return evaluator.getOperatorList({
  563. stream,
  564. task,
  565. resources: this.fieldResources,
  566. operatorList
  567. }).then(function () {
  568. return operatorList;
  569. });
  570. }
  571. }
  572. class ButtonWidgetAnnotation extends WidgetAnnotation {
  573. constructor(params) {
  574. super(params);
  575. this.data.checkBox = !this.hasFieldFlag(_util.AnnotationFieldFlag.RADIO) && !this.hasFieldFlag(_util.AnnotationFieldFlag.PUSHBUTTON);
  576. this.data.radioButton = this.hasFieldFlag(_util.AnnotationFieldFlag.RADIO) && !this.hasFieldFlag(_util.AnnotationFieldFlag.PUSHBUTTON);
  577. this.data.pushButton = this.hasFieldFlag(_util.AnnotationFieldFlag.PUSHBUTTON);
  578. if (this.data.checkBox) {
  579. this._processCheckBox(params);
  580. } else if (this.data.radioButton) {
  581. this._processRadioButton(params);
  582. } else if (this.data.pushButton) {
  583. this._processPushButton(params);
  584. } else {
  585. (0, _util.warn)("Invalid field flags for button widget annotation");
  586. }
  587. }
  588. _processCheckBox(params) {
  589. if ((0, _primitives.isName)(this.data.fieldValue)) {
  590. this.data.fieldValue = this.data.fieldValue.name;
  591. }
  592. const customAppearance = params.dict.get("AP");
  593. if (!(0, _primitives.isDict)(customAppearance)) {
  594. return;
  595. }
  596. const exportValueOptionsDict = customAppearance.get("D");
  597. if (!(0, _primitives.isDict)(exportValueOptionsDict)) {
  598. return;
  599. }
  600. const exportValues = exportValueOptionsDict.getKeys();
  601. const hasCorrectOptionCount = exportValues.length === 2;
  602. if (!hasCorrectOptionCount) {
  603. return;
  604. }
  605. this.data.exportValue = exportValues[0] === "Off" ? exportValues[1] : exportValues[0];
  606. }
  607. _processRadioButton(params) {
  608. this.data.fieldValue = this.data.buttonValue = null;
  609. const fieldParent = params.dict.get("Parent");
  610. if ((0, _primitives.isDict)(fieldParent) && fieldParent.has("V")) {
  611. const fieldParentValue = fieldParent.get("V");
  612. if ((0, _primitives.isName)(fieldParentValue)) {
  613. this.data.fieldValue = fieldParentValue.name;
  614. }
  615. }
  616. const appearanceStates = params.dict.get("AP");
  617. if (!(0, _primitives.isDict)(appearanceStates)) {
  618. return;
  619. }
  620. const normalAppearanceState = appearanceStates.get("N");
  621. if (!(0, _primitives.isDict)(normalAppearanceState)) {
  622. return;
  623. }
  624. for (const key of normalAppearanceState.getKeys()) {
  625. if (key !== "Off") {
  626. this.data.buttonValue = key;
  627. break;
  628. }
  629. }
  630. }
  631. _processPushButton(params) {
  632. if (!params.dict.has("A")) {
  633. (0, _util.warn)("Push buttons without action dictionaries are not supported");
  634. return;
  635. }
  636. _obj.Catalog.parseDestDictionary({
  637. destDict: params.dict,
  638. resultObj: this.data,
  639. docBaseUrl: params.pdfManager.docBaseUrl
  640. });
  641. }
  642. }
  643. class ChoiceWidgetAnnotation extends WidgetAnnotation {
  644. constructor(params) {
  645. super(params);
  646. this.data.options = [];
  647. const options = (0, _core_utils.getInheritableProperty)({
  648. dict: params.dict,
  649. key: "Opt"
  650. });
  651. if (Array.isArray(options)) {
  652. const xref = params.xref;
  653. for (let i = 0, ii = options.length; i < ii; i++) {
  654. const option = xref.fetchIfRef(options[i]);
  655. const isOptionArray = Array.isArray(option);
  656. this.data.options[i] = {
  657. exportValue: isOptionArray ? xref.fetchIfRef(option[0]) : option,
  658. displayValue: (0, _util.stringToPDFString)(isOptionArray ? xref.fetchIfRef(option[1]) : option)
  659. };
  660. }
  661. }
  662. if (!Array.isArray(this.data.fieldValue)) {
  663. this.data.fieldValue = [this.data.fieldValue];
  664. }
  665. this.data.combo = this.hasFieldFlag(_util.AnnotationFieldFlag.COMBO);
  666. this.data.multiSelect = this.hasFieldFlag(_util.AnnotationFieldFlag.MULTISELECT);
  667. }
  668. }
  669. class TextAnnotation extends MarkupAnnotation {
  670. constructor(parameters) {
  671. const DEFAULT_ICON_SIZE = 22;
  672. super(parameters);
  673. const dict = parameters.dict;
  674. this.data.annotationType = _util.AnnotationType.TEXT;
  675. if (this.data.hasAppearance) {
  676. this.data.name = "NoIcon";
  677. } else {
  678. this.data.rect[1] = this.data.rect[3] - DEFAULT_ICON_SIZE;
  679. this.data.rect[2] = this.data.rect[0] + DEFAULT_ICON_SIZE;
  680. this.data.name = dict.has("Name") ? dict.get("Name").name : "Note";
  681. }
  682. if (dict.has("State")) {
  683. this.data.state = dict.get("State") || null;
  684. this.data.stateModel = dict.get("StateModel") || null;
  685. } else {
  686. this.data.state = null;
  687. this.data.stateModel = null;
  688. }
  689. }
  690. }
  691. class LinkAnnotation extends Annotation {
  692. constructor(params) {
  693. super(params);
  694. this.data.annotationType = _util.AnnotationType.LINK;
  695. const quadPoints = getQuadPoints(params.dict, this.rectangle);
  696. if (quadPoints) {
  697. this.data.quadPoints = quadPoints;
  698. }
  699. _obj.Catalog.parseDestDictionary({
  700. destDict: params.dict,
  701. resultObj: this.data,
  702. docBaseUrl: params.pdfManager.docBaseUrl
  703. });
  704. }
  705. }
  706. class PopupAnnotation extends Annotation {
  707. constructor(parameters) {
  708. super(parameters);
  709. this.data.annotationType = _util.AnnotationType.POPUP;
  710. let parentItem = parameters.dict.get("Parent");
  711. if (!parentItem) {
  712. (0, _util.warn)("Popup annotation has a missing or invalid parent annotation.");
  713. return;
  714. }
  715. const parentSubtype = parentItem.get("Subtype");
  716. this.data.parentType = (0, _primitives.isName)(parentSubtype) ? parentSubtype.name : null;
  717. const rawParent = parameters.dict.getRaw("Parent");
  718. this.data.parentId = (0, _primitives.isRef)(rawParent) ? rawParent.toString() : null;
  719. const rt = parentItem.get("RT");
  720. if ((0, _primitives.isName)(rt, _util.AnnotationReplyType.GROUP)) {
  721. parentItem = parentItem.get("IRT");
  722. }
  723. if (!parentItem.has("M")) {
  724. this.data.modificationDate = null;
  725. } else {
  726. this.setModificationDate(parentItem.get("M"));
  727. this.data.modificationDate = this.modificationDate;
  728. }
  729. if (!parentItem.has("C")) {
  730. this.data.color = null;
  731. } else {
  732. this.setColor(parentItem.getArray("C"));
  733. this.data.color = this.color;
  734. }
  735. if (!this.viewable) {
  736. const parentFlags = parentItem.get("F");
  737. if (this._isViewable(parentFlags)) {
  738. this.setFlags(parentFlags);
  739. }
  740. }
  741. this.data.title = (0, _util.stringToPDFString)(parentItem.get("T") || "");
  742. this.data.contents = (0, _util.stringToPDFString)(parentItem.get("Contents") || "");
  743. }
  744. }
  745. class FreeTextAnnotation extends MarkupAnnotation {
  746. constructor(parameters) {
  747. super(parameters);
  748. this.data.annotationType = _util.AnnotationType.FREETEXT;
  749. }
  750. }
  751. class LineAnnotation extends MarkupAnnotation {
  752. constructor(parameters) {
  753. super(parameters);
  754. this.data.annotationType = _util.AnnotationType.LINE;
  755. this.data.lineCoordinates = _util.Util.normalizeRect(parameters.dict.getArray("L"));
  756. }
  757. }
  758. class SquareAnnotation extends MarkupAnnotation {
  759. constructor(parameters) {
  760. super(parameters);
  761. this.data.annotationType = _util.AnnotationType.SQUARE;
  762. }
  763. }
  764. class CircleAnnotation extends MarkupAnnotation {
  765. constructor(parameters) {
  766. super(parameters);
  767. this.data.annotationType = _util.AnnotationType.CIRCLE;
  768. }
  769. }
  770. class PolylineAnnotation extends MarkupAnnotation {
  771. constructor(parameters) {
  772. super(parameters);
  773. this.data.annotationType = _util.AnnotationType.POLYLINE;
  774. const rawVertices = parameters.dict.getArray("Vertices");
  775. this.data.vertices = [];
  776. for (let i = 0, ii = rawVertices.length; i < ii; i += 2) {
  777. this.data.vertices.push({
  778. x: rawVertices[i],
  779. y: rawVertices[i + 1]
  780. });
  781. }
  782. }
  783. }
  784. class PolygonAnnotation extends PolylineAnnotation {
  785. constructor(parameters) {
  786. super(parameters);
  787. this.data.annotationType = _util.AnnotationType.POLYGON;
  788. }
  789. }
  790. class CaretAnnotation extends MarkupAnnotation {
  791. constructor(parameters) {
  792. super(parameters);
  793. this.data.annotationType = _util.AnnotationType.CARET;
  794. }
  795. }
  796. class InkAnnotation extends MarkupAnnotation {
  797. constructor(parameters) {
  798. super(parameters);
  799. this.data.annotationType = _util.AnnotationType.INK;
  800. const xref = parameters.xref;
  801. const originalInkLists = parameters.dict.getArray("InkList");
  802. this.data.inkLists = [];
  803. for (let i = 0, ii = originalInkLists.length; i < ii; ++i) {
  804. this.data.inkLists.push([]);
  805. for (let j = 0, jj = originalInkLists[i].length; j < jj; j += 2) {
  806. this.data.inkLists[i].push({
  807. x: xref.fetchIfRef(originalInkLists[i][j]),
  808. y: xref.fetchIfRef(originalInkLists[i][j + 1])
  809. });
  810. }
  811. }
  812. }
  813. }
  814. class HighlightAnnotation extends MarkupAnnotation {
  815. constructor(parameters) {
  816. super(parameters);
  817. this.data.annotationType = _util.AnnotationType.HIGHLIGHT;
  818. const quadPoints = getQuadPoints(parameters.dict, this.rectangle);
  819. if (quadPoints) {
  820. this.data.quadPoints = quadPoints;
  821. }
  822. }
  823. }
  824. class UnderlineAnnotation extends MarkupAnnotation {
  825. constructor(parameters) {
  826. super(parameters);
  827. this.data.annotationType = _util.AnnotationType.UNDERLINE;
  828. const quadPoints = getQuadPoints(parameters.dict, this.rectangle);
  829. if (quadPoints) {
  830. this.data.quadPoints = quadPoints;
  831. }
  832. }
  833. }
  834. class SquigglyAnnotation extends MarkupAnnotation {
  835. constructor(parameters) {
  836. super(parameters);
  837. this.data.annotationType = _util.AnnotationType.SQUIGGLY;
  838. const quadPoints = getQuadPoints(parameters.dict, this.rectangle);
  839. if (quadPoints) {
  840. this.data.quadPoints = quadPoints;
  841. }
  842. }
  843. }
  844. class StrikeOutAnnotation extends MarkupAnnotation {
  845. constructor(parameters) {
  846. super(parameters);
  847. this.data.annotationType = _util.AnnotationType.STRIKEOUT;
  848. const quadPoints = getQuadPoints(parameters.dict, this.rectangle);
  849. if (quadPoints) {
  850. this.data.quadPoints = quadPoints;
  851. }
  852. }
  853. }
  854. class StampAnnotation extends MarkupAnnotation {
  855. constructor(parameters) {
  856. super(parameters);
  857. this.data.annotationType = _util.AnnotationType.STAMP;
  858. }
  859. }
  860. class FileAttachmentAnnotation extends MarkupAnnotation {
  861. constructor(parameters) {
  862. super(parameters);
  863. const file = new _obj.FileSpec(parameters.dict.get("FS"), parameters.xref);
  864. this.data.annotationType = _util.AnnotationType.FILEATTACHMENT;
  865. this.data.file = file.serializable;
  866. }
  867. }