annotation_spec.js 45 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086
  1. /* Copyright 2017 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. 'use strict';
  16. var corePrimitives = require('../../core/primitives.js');
  17. var coreAnnotation = require('../../core/annotation.js');
  18. var coreStream = require('../../core/stream.js');
  19. var coreParser = require('../../core/parser.js');
  20. var sharedUtil = require('../../shared/util.js');
  21. var Annotation = coreAnnotation.Annotation;
  22. var AnnotationBorderStyle = coreAnnotation.AnnotationBorderStyle;
  23. var AnnotationFactory = coreAnnotation.AnnotationFactory;
  24. var Lexer = coreParser.Lexer;
  25. var Parser = coreParser.Parser;
  26. var isRef = corePrimitives.isRef;
  27. var Dict = corePrimitives.Dict;
  28. var Name = corePrimitives.Name;
  29. var Ref = corePrimitives.Ref;
  30. var StringStream = coreStream.StringStream;
  31. var AnnotationType = sharedUtil.AnnotationType;
  32. var AnnotationFlag = sharedUtil.AnnotationFlag;
  33. var AnnotationBorderStyleType = sharedUtil.AnnotationBorderStyleType;
  34. var AnnotationFieldFlag = sharedUtil.AnnotationFieldFlag;
  35. var stringToBytes = sharedUtil.stringToBytes;
  36. var stringToUTF8String = sharedUtil.stringToUTF8String;
  37. describe('annotation', function () {
  38. function XRefMock(array) {
  39. this.map = Object.create(null);
  40. for (var elem in array) {
  41. var obj = array[elem];
  42. var ref = obj.ref,
  43. data = obj.data;
  44. this.map[ref.toString()] = data;
  45. }
  46. }
  47. XRefMock.prototype = {
  48. fetch: function (ref) {
  49. return this.map[ref.toString()];
  50. },
  51. fetchIfRef: function (obj) {
  52. if (!isRef(obj)) {
  53. return obj;
  54. }
  55. return this.fetch(obj);
  56. }
  57. };
  58. function PDFManagerMock(params) {
  59. this.docBaseUrl = params.docBaseUrl || null;
  60. }
  61. PDFManagerMock.prototype = {};
  62. function IdFactoryMock(params) {
  63. var uniquePrefix = params.prefix || 'p0_';
  64. var idCounters = { obj: params.startObjId || 0 };
  65. return {
  66. createObjId: function () {
  67. return uniquePrefix + ++idCounters.obj;
  68. }
  69. };
  70. }
  71. IdFactoryMock.prototype = {};
  72. var annotationFactory, pdfManagerMock, idFactoryMock;
  73. beforeAll(function (done) {
  74. annotationFactory = new AnnotationFactory();
  75. pdfManagerMock = new PDFManagerMock({ docBaseUrl: null });
  76. idFactoryMock = new IdFactoryMock({});
  77. done();
  78. });
  79. afterAll(function () {
  80. annotationFactory = null;
  81. pdfManagerMock = null;
  82. idFactoryMock = null;
  83. });
  84. describe('AnnotationFactory', function () {
  85. it('should get id for annotation', function () {
  86. var annotationDict = new Dict();
  87. annotationDict.set('Type', Name.get('Annot'));
  88. annotationDict.set('Subtype', Name.get('Link'));
  89. var annotationRef = new Ref(10, 0);
  90. var xref = new XRefMock([{
  91. ref: annotationRef,
  92. data: annotationDict
  93. }]);
  94. var annotation = annotationFactory.create(xref, annotationRef, pdfManagerMock, idFactoryMock);
  95. var data = annotation.data;
  96. expect(data.annotationType).toEqual(AnnotationType.LINK);
  97. expect(data.id).toEqual('10R');
  98. });
  99. it('should handle, and get fallback id\'s for, annotations that are not ' + 'indirect objects (issue 7569)', function () {
  100. var annotationDict = new Dict();
  101. annotationDict.set('Type', Name.get('Annot'));
  102. annotationDict.set('Subtype', Name.get('Link'));
  103. var xref = new XRefMock();
  104. var idFactory = new IdFactoryMock({
  105. prefix: 'p0_',
  106. startObjId: 0
  107. });
  108. var annotation1 = annotationFactory.create(xref, annotationDict, pdfManagerMock, idFactory);
  109. var annotation2 = annotationFactory.create(xref, annotationDict, pdfManagerMock, idFactory);
  110. var data1 = annotation1.data,
  111. data2 = annotation2.data;
  112. expect(data1.annotationType).toEqual(AnnotationType.LINK);
  113. expect(data2.annotationType).toEqual(AnnotationType.LINK);
  114. expect(data1.id).toEqual('annot_p0_1');
  115. expect(data2.id).toEqual('annot_p0_2');
  116. });
  117. it('should handle missing /Subtype', function () {
  118. var annotationDict = new Dict();
  119. annotationDict.set('Type', Name.get('Annot'));
  120. var annotationRef = new Ref(1, 0);
  121. var xref = new XRefMock([{
  122. ref: annotationRef,
  123. data: annotationDict
  124. }]);
  125. var annotation = annotationFactory.create(xref, annotationRef, pdfManagerMock, idFactoryMock);
  126. var data = annotation.data;
  127. expect(data.annotationType).toBeUndefined();
  128. });
  129. });
  130. describe('Annotation', function () {
  131. var dict, ref;
  132. beforeAll(function (done) {
  133. dict = new Dict();
  134. ref = new Ref(1, 0);
  135. done();
  136. });
  137. afterAll(function () {
  138. dict = ref = null;
  139. });
  140. it('should set and get flags', function () {
  141. var annotation = new Annotation({
  142. dict: dict,
  143. ref: ref
  144. });
  145. annotation.setFlags(13);
  146. expect(annotation.hasFlag(AnnotationFlag.INVISIBLE)).toEqual(true);
  147. expect(annotation.hasFlag(AnnotationFlag.NOZOOM)).toEqual(true);
  148. expect(annotation.hasFlag(AnnotationFlag.PRINT)).toEqual(true);
  149. expect(annotation.hasFlag(AnnotationFlag.READONLY)).toEqual(false);
  150. });
  151. it('should be viewable and not printable by default', function () {
  152. var annotation = new Annotation({
  153. dict: dict,
  154. ref: ref
  155. });
  156. expect(annotation.viewable).toEqual(true);
  157. expect(annotation.printable).toEqual(false);
  158. });
  159. it('should set and get a valid rectangle', function () {
  160. var annotation = new Annotation({
  161. dict: dict,
  162. ref: ref
  163. });
  164. annotation.setRectangle([117, 694, 164.298, 720]);
  165. expect(annotation.rectangle).toEqual([117, 694, 164.298, 720]);
  166. });
  167. it('should not set and get an invalid rectangle', function () {
  168. var annotation = new Annotation({
  169. dict: dict,
  170. ref: ref
  171. });
  172. annotation.setRectangle([117, 694, 164.298]);
  173. expect(annotation.rectangle).toEqual([0, 0, 0, 0]);
  174. });
  175. it('should reject a color if it is not an array', function () {
  176. var annotation = new Annotation({
  177. dict: dict,
  178. ref: ref
  179. });
  180. annotation.setColor('red');
  181. expect(annotation.color).toEqual(new Uint8Array([0, 0, 0]));
  182. });
  183. it('should set and get a transparent color', function () {
  184. var annotation = new Annotation({
  185. dict: dict,
  186. ref: ref
  187. });
  188. annotation.setColor([]);
  189. expect(annotation.color).toEqual(null);
  190. });
  191. it('should set and get a grayscale color', function () {
  192. var annotation = new Annotation({
  193. dict: dict,
  194. ref: ref
  195. });
  196. annotation.setColor([0.4]);
  197. expect(annotation.color).toEqual(new Uint8Array([102, 102, 102]));
  198. });
  199. it('should set and get an RGB color', function () {
  200. var annotation = new Annotation({
  201. dict: dict,
  202. ref: ref
  203. });
  204. annotation.setColor([0, 0, 1]);
  205. expect(annotation.color).toEqual(new Uint8Array([0, 0, 255]));
  206. });
  207. it('should set and get a CMYK color', function () {
  208. var annotation = new Annotation({
  209. dict: dict,
  210. ref: ref
  211. });
  212. annotation.setColor([0.1, 0.92, 0.84, 0.02]);
  213. expect(annotation.color).toEqual(new Uint8Array([233, 59, 47]));
  214. });
  215. it('should not set and get an invalid color', function () {
  216. var annotation = new Annotation({
  217. dict: dict,
  218. ref: ref
  219. });
  220. annotation.setColor([0.4, 0.6]);
  221. expect(annotation.color).toEqual(new Uint8Array([0, 0, 0]));
  222. });
  223. });
  224. describe('AnnotationBorderStyle', function () {
  225. it('should set and get a valid width', function () {
  226. var borderStyle = new AnnotationBorderStyle();
  227. borderStyle.setWidth(3);
  228. expect(borderStyle.width).toEqual(3);
  229. });
  230. it('should not set and get an invalid width', function () {
  231. var borderStyle = new AnnotationBorderStyle();
  232. borderStyle.setWidth('three');
  233. expect(borderStyle.width).toEqual(1);
  234. });
  235. it('should set and get a valid style', function () {
  236. var borderStyle = new AnnotationBorderStyle();
  237. borderStyle.setStyle(Name.get('D'));
  238. expect(borderStyle.style).toEqual(AnnotationBorderStyleType.DASHED);
  239. });
  240. it('should not set and get an invalid style', function () {
  241. var borderStyle = new AnnotationBorderStyle();
  242. borderStyle.setStyle('Dashed');
  243. expect(borderStyle.style).toEqual(AnnotationBorderStyleType.SOLID);
  244. });
  245. it('should set and get a valid dash array', function () {
  246. var borderStyle = new AnnotationBorderStyle();
  247. borderStyle.setDashArray([1, 2, 3]);
  248. expect(borderStyle.dashArray).toEqual([1, 2, 3]);
  249. });
  250. it('should not set and get an invalid dash array', function () {
  251. var borderStyle = new AnnotationBorderStyle();
  252. borderStyle.setDashArray([0, 0]);
  253. expect(borderStyle.dashArray).toEqual([3]);
  254. });
  255. it('should set and get a valid horizontal corner radius', function () {
  256. var borderStyle = new AnnotationBorderStyle();
  257. borderStyle.setHorizontalCornerRadius(3);
  258. expect(borderStyle.horizontalCornerRadius).toEqual(3);
  259. });
  260. it('should not set and get an invalid horizontal corner radius', function () {
  261. var borderStyle = new AnnotationBorderStyle();
  262. borderStyle.setHorizontalCornerRadius('three');
  263. expect(borderStyle.horizontalCornerRadius).toEqual(0);
  264. });
  265. it('should set and get a valid vertical corner radius', function () {
  266. var borderStyle = new AnnotationBorderStyle();
  267. borderStyle.setVerticalCornerRadius(3);
  268. expect(borderStyle.verticalCornerRadius).toEqual(3);
  269. });
  270. it('should not set and get an invalid horizontal corner radius', function () {
  271. var borderStyle = new AnnotationBorderStyle();
  272. borderStyle.setVerticalCornerRadius('three');
  273. expect(borderStyle.verticalCornerRadius).toEqual(0);
  274. });
  275. });
  276. describe('LinkAnnotation', function () {
  277. it('should correctly parse a URI action', function () {
  278. var actionDict = new Dict();
  279. actionDict.set('Type', Name.get('Action'));
  280. actionDict.set('S', Name.get('URI'));
  281. actionDict.set('URI', 'http://www.ctan.org/tex-archive/info/lshort');
  282. var annotationDict = new Dict();
  283. annotationDict.set('Type', Name.get('Annot'));
  284. annotationDict.set('Subtype', Name.get('Link'));
  285. annotationDict.set('A', actionDict);
  286. var annotationRef = new Ref(820, 0);
  287. var xref = new XRefMock([{
  288. ref: annotationRef,
  289. data: annotationDict
  290. }]);
  291. var annotation = annotationFactory.create(xref, annotationRef, pdfManagerMock, idFactoryMock);
  292. var data = annotation.data;
  293. expect(data.annotationType).toEqual(AnnotationType.LINK);
  294. expect(data.url).toEqual('http://www.ctan.org/tex-archive/info/lshort');
  295. expect(data.unsafeUrl).toEqual('http://www.ctan.org/tex-archive/info/lshort');
  296. expect(data.dest).toBeUndefined();
  297. });
  298. it('should correctly parse a URI action, where the URI entry ' + 'is missing a protocol', function () {
  299. var actionDict = new Dict();
  300. actionDict.set('Type', Name.get('Action'));
  301. actionDict.set('S', Name.get('URI'));
  302. actionDict.set('URI', 'www.hmrc.gov.uk');
  303. var annotationDict = new Dict();
  304. annotationDict.set('Type', Name.get('Annot'));
  305. annotationDict.set('Subtype', Name.get('Link'));
  306. annotationDict.set('A', actionDict);
  307. var annotationRef = new Ref(353, 0);
  308. var xref = new XRefMock([{
  309. ref: annotationRef,
  310. data: annotationDict
  311. }]);
  312. var annotation = annotationFactory.create(xref, annotationRef, pdfManagerMock, idFactoryMock);
  313. var data = annotation.data;
  314. expect(data.annotationType).toEqual(AnnotationType.LINK);
  315. expect(data.url).toEqual('http://www.hmrc.gov.uk/');
  316. expect(data.unsafeUrl).toEqual('http://www.hmrc.gov.uk');
  317. expect(data.dest).toBeUndefined();
  318. });
  319. it('should correctly parse a URI action, where the URI entry ' + 'has an incorrect encoding (bug 1122280)', function () {
  320. var actionStream = new StringStream('<<\n' + '/Type /Action\n' + '/S /URI\n' + '/URI (http://www.example.com/\\303\\274\\303\\266\\303\\244)\n' + '>>\n');
  321. var lexer = new Lexer(actionStream);
  322. var parser = new Parser(lexer);
  323. var actionDict = parser.getObj();
  324. var annotationDict = new Dict();
  325. annotationDict.set('Type', Name.get('Annot'));
  326. annotationDict.set('Subtype', Name.get('Link'));
  327. annotationDict.set('A', actionDict);
  328. var annotationRef = new Ref(8, 0);
  329. var xref = new XRefMock([{
  330. ref: annotationRef,
  331. data: annotationDict
  332. }]);
  333. var annotation = annotationFactory.create(xref, annotationRef, pdfManagerMock, idFactoryMock);
  334. var data = annotation.data;
  335. expect(data.annotationType).toEqual(AnnotationType.LINK);
  336. expect(data.url).toEqual(new URL(stringToUTF8String('http://www.example.com/\xC3\xBC\xC3\xB6\xC3\xA4')).href);
  337. expect(data.unsafeUrl).toEqual(stringToUTF8String('http://www.example.com/\xC3\xBC\xC3\xB6\xC3\xA4'));
  338. expect(data.dest).toBeUndefined();
  339. });
  340. it('should correctly parse a GoTo action', function () {
  341. var actionDict = new Dict();
  342. actionDict.set('Type', Name.get('Action'));
  343. actionDict.set('S', Name.get('GoTo'));
  344. actionDict.set('D', 'page.157');
  345. var annotationDict = new Dict();
  346. annotationDict.set('Type', Name.get('Annot'));
  347. annotationDict.set('Subtype', Name.get('Link'));
  348. annotationDict.set('A', actionDict);
  349. var annotationRef = new Ref(798, 0);
  350. var xref = new XRefMock([{
  351. ref: annotationRef,
  352. data: annotationDict
  353. }]);
  354. var annotation = annotationFactory.create(xref, annotationRef, pdfManagerMock, idFactoryMock);
  355. var data = annotation.data;
  356. expect(data.annotationType).toEqual(AnnotationType.LINK);
  357. expect(data.url).toBeUndefined();
  358. expect(data.unsafeUrl).toBeUndefined();
  359. expect(data.dest).toEqual('page.157');
  360. });
  361. it('should correctly parse a GoToR action, where the FileSpec entry ' + 'is a string containing a relative URL', function () {
  362. var actionDict = new Dict();
  363. actionDict.set('Type', Name.get('Action'));
  364. actionDict.set('S', Name.get('GoToR'));
  365. actionDict.set('F', '../../0013/001346/134685E.pdf');
  366. actionDict.set('D', '4.3');
  367. actionDict.set('NewWindow', true);
  368. var annotationDict = new Dict();
  369. annotationDict.set('Type', Name.get('Annot'));
  370. annotationDict.set('Subtype', Name.get('Link'));
  371. annotationDict.set('A', actionDict);
  372. var annotationRef = new Ref(489, 0);
  373. var xref = new XRefMock([{
  374. ref: annotationRef,
  375. data: annotationDict
  376. }]);
  377. var annotation = annotationFactory.create(xref, annotationRef, pdfManagerMock, idFactoryMock);
  378. var data = annotation.data;
  379. expect(data.annotationType).toEqual(AnnotationType.LINK);
  380. expect(data.url).toBeUndefined();
  381. expect(data.unsafeUrl).toEqual('../../0013/001346/134685E.pdf#4.3');
  382. expect(data.dest).toBeUndefined();
  383. expect(data.newWindow).toEqual(true);
  384. });
  385. it('should correctly parse a GoToR action, containing a relative URL, ' + 'with the "docBaseUrl" parameter specified', function () {
  386. var actionDict = new Dict();
  387. actionDict.set('Type', Name.get('Action'));
  388. actionDict.set('S', Name.get('GoToR'));
  389. actionDict.set('F', '../../0013/001346/134685E.pdf');
  390. actionDict.set('D', '4.3');
  391. var annotationDict = new Dict();
  392. annotationDict.set('Type', Name.get('Annot'));
  393. annotationDict.set('Subtype', Name.get('Link'));
  394. annotationDict.set('A', actionDict);
  395. var annotationRef = new Ref(489, 0);
  396. var xref = new XRefMock([{
  397. ref: annotationRef,
  398. data: annotationDict
  399. }]);
  400. var pdfManager = new PDFManagerMock({ docBaseUrl: 'http://www.example.com/test/pdfs/qwerty.pdf' });
  401. var annotation = annotationFactory.create(xref, annotationRef, pdfManager, idFactoryMock);
  402. var data = annotation.data;
  403. expect(data.annotationType).toEqual(AnnotationType.LINK);
  404. expect(data.url).toEqual('http://www.example.com/0013/001346/134685E.pdf#4.3');
  405. expect(data.unsafeUrl).toEqual('../../0013/001346/134685E.pdf#4.3');
  406. expect(data.dest).toBeUndefined();
  407. });
  408. it('should correctly parse a GoToR action, with named destination', function () {
  409. var actionDict = new Dict();
  410. actionDict.set('Type', Name.get('Action'));
  411. actionDict.set('S', Name.get('GoToR'));
  412. actionDict.set('F', 'http://www.example.com/test.pdf');
  413. actionDict.set('D', '15');
  414. var annotationDict = new Dict();
  415. annotationDict.set('Type', Name.get('Annot'));
  416. annotationDict.set('Subtype', Name.get('Link'));
  417. annotationDict.set('A', actionDict);
  418. var annotationRef = new Ref(495, 0);
  419. var xref = new XRefMock([{
  420. ref: annotationRef,
  421. data: annotationDict
  422. }]);
  423. var annotation = annotationFactory.create(xref, annotationRef, pdfManagerMock, idFactoryMock);
  424. var data = annotation.data;
  425. expect(data.annotationType).toEqual(AnnotationType.LINK);
  426. expect(data.url).toEqual('http://www.example.com/test.pdf#nameddest=15');
  427. expect(data.unsafeUrl).toEqual('http://www.example.com/test.pdf#nameddest=15');
  428. expect(data.dest).toBeUndefined();
  429. expect(data.newWindow).toBeFalsy();
  430. });
  431. it('should correctly parse a GoToR action, with explicit destination array', function () {
  432. var actionDict = new Dict();
  433. actionDict.set('Type', Name.get('Action'));
  434. actionDict.set('S', Name.get('GoToR'));
  435. actionDict.set('F', 'http://www.example.com/test.pdf');
  436. actionDict.set('D', [14, Name.get('XYZ'), null, 298.043, null]);
  437. var annotationDict = new Dict();
  438. annotationDict.set('Type', Name.get('Annot'));
  439. annotationDict.set('Subtype', Name.get('Link'));
  440. annotationDict.set('A', actionDict);
  441. var annotationRef = new Ref(489, 0);
  442. var xref = new XRefMock([{
  443. ref: annotationRef,
  444. data: annotationDict
  445. }]);
  446. var annotation = annotationFactory.create(xref, annotationRef, pdfManagerMock, idFactoryMock);
  447. var data = annotation.data;
  448. expect(data.annotationType).toEqual(AnnotationType.LINK);
  449. expect(data.url).toEqual(new URL('http://www.example.com/test.pdf#' + '[14,{"name":"XYZ"},null,298.043,null]').href);
  450. expect(data.unsafeUrl).toEqual('http://www.example.com/test.pdf#' + '[14,{"name":"XYZ"},null,298.043,null]');
  451. expect(data.dest).toBeUndefined();
  452. expect(data.newWindow).toBeFalsy();
  453. });
  454. it('should correctly parse a Launch action, where the FileSpec dict ' + 'contains a relative URL, with the "docBaseUrl" parameter specified', function () {
  455. var fileSpecDict = new Dict();
  456. fileSpecDict.set('Type', Name.get('FileSpec'));
  457. fileSpecDict.set('F', 'Part II/Part II.pdf');
  458. fileSpecDict.set('UF', 'Part II/Part II.pdf');
  459. var actionDict = new Dict();
  460. actionDict.set('Type', Name.get('Action'));
  461. actionDict.set('S', Name.get('Launch'));
  462. actionDict.set('F', fileSpecDict);
  463. actionDict.set('NewWindow', true);
  464. var annotationDict = new Dict();
  465. annotationDict.set('Type', Name.get('Annot'));
  466. annotationDict.set('Subtype', Name.get('Link'));
  467. annotationDict.set('A', actionDict);
  468. var annotationRef = new Ref(88, 0);
  469. var xref = new XRefMock([{
  470. ref: annotationRef,
  471. data: annotationDict
  472. }]);
  473. var pdfManager = new PDFManagerMock({ docBaseUrl: 'http://www.example.com/test/pdfs/qwerty.pdf' });
  474. var annotation = annotationFactory.create(xref, annotationRef, pdfManager, idFactoryMock);
  475. var data = annotation.data;
  476. expect(data.annotationType).toEqual(AnnotationType.LINK);
  477. expect(data.url).toEqual(new URL('http://www.example.com/test/pdfs/Part II/Part II.pdf').href);
  478. expect(data.unsafeUrl).toEqual('Part II/Part II.pdf');
  479. expect(data.dest).toBeUndefined();
  480. expect(data.newWindow).toEqual(true);
  481. });
  482. it('should recover valid URLs from JavaScript actions having certain ' + 'white-listed formats', function () {
  483. function checkJsAction(params) {
  484. var jsEntry = params.jsEntry;
  485. var expectedUrl = params.expectedUrl;
  486. var expectedUnsafeUrl = params.expectedUnsafeUrl;
  487. var expectedNewWindow = params.expectedNewWindow;
  488. var actionDict = new Dict();
  489. actionDict.set('Type', Name.get('Action'));
  490. actionDict.set('S', Name.get('JavaScript'));
  491. actionDict.set('JS', jsEntry);
  492. var annotationDict = new Dict();
  493. annotationDict.set('Type', Name.get('Annot'));
  494. annotationDict.set('Subtype', Name.get('Link'));
  495. annotationDict.set('A', actionDict);
  496. var annotationRef = new Ref(46, 0);
  497. var xref = new XRefMock([{
  498. ref: annotationRef,
  499. data: annotationDict
  500. }]);
  501. var annotation = annotationFactory.create(xref, annotationRef, pdfManagerMock, idFactoryMock);
  502. var data = annotation.data;
  503. expect(data.annotationType).toEqual(AnnotationType.LINK);
  504. expect(data.url).toEqual(expectedUrl);
  505. expect(data.unsafeUrl).toEqual(expectedUnsafeUrl);
  506. expect(data.dest).toBeUndefined();
  507. expect(data.newWindow).toEqual(expectedNewWindow);
  508. }
  509. checkJsAction({
  510. jsEntry: 'function someFun() { return "qwerty"; } someFun();',
  511. expectedUrl: undefined,
  512. expectedUnsafeUrl: undefined,
  513. expectedNewWindow: undefined
  514. });
  515. checkJsAction({
  516. jsEntry: 'window.open(\'http://www.example.com/test.pdf\')',
  517. expectedUrl: new URL('http://www.example.com/test.pdf').href,
  518. expectedUnsafeUrl: 'http://www.example.com/test.pdf',
  519. expectedNewWindow: undefined
  520. });
  521. checkJsAction({
  522. jsEntry: new StringStream('app.launchURL("http://www.example.com/test.pdf", true)'),
  523. expectedUrl: new URL('http://www.example.com/test.pdf').href,
  524. expectedUnsafeUrl: 'http://www.example.com/test.pdf',
  525. expectedNewWindow: true
  526. });
  527. });
  528. it('should correctly parse a Named action', function () {
  529. var actionDict = new Dict();
  530. actionDict.set('Type', Name.get('Action'));
  531. actionDict.set('S', Name.get('Named'));
  532. actionDict.set('N', Name.get('GoToPage'));
  533. var annotationDict = new Dict();
  534. annotationDict.set('Type', Name.get('Annot'));
  535. annotationDict.set('Subtype', Name.get('Link'));
  536. annotationDict.set('A', actionDict);
  537. var annotationRef = new Ref(12, 0);
  538. var xref = new XRefMock([{
  539. ref: annotationRef,
  540. data: annotationDict
  541. }]);
  542. var annotation = annotationFactory.create(xref, annotationRef, pdfManagerMock, idFactoryMock);
  543. var data = annotation.data;
  544. expect(data.annotationType).toEqual(AnnotationType.LINK);
  545. expect(data.url).toBeUndefined();
  546. expect(data.unsafeUrl).toBeUndefined();
  547. expect(data.action).toEqual('GoToPage');
  548. });
  549. it('should correctly parse a simple Dest', function () {
  550. var annotationDict = new Dict();
  551. annotationDict.set('Type', Name.get('Annot'));
  552. annotationDict.set('Subtype', Name.get('Link'));
  553. annotationDict.set('Dest', Name.get('LI0'));
  554. var annotationRef = new Ref(583, 0);
  555. var xref = new XRefMock([{
  556. ref: annotationRef,
  557. data: annotationDict
  558. }]);
  559. var annotation = annotationFactory.create(xref, annotationRef, pdfManagerMock, idFactoryMock);
  560. var data = annotation.data;
  561. expect(data.annotationType).toEqual(AnnotationType.LINK);
  562. expect(data.url).toBeUndefined();
  563. expect(data.unsafeUrl).toBeUndefined();
  564. expect(data.dest).toEqual('LI0');
  565. });
  566. it('should correctly parse a simple Dest, with explicit destination array', function () {
  567. var annotationDict = new Dict();
  568. annotationDict.set('Type', Name.get('Annot'));
  569. annotationDict.set('Subtype', Name.get('Link'));
  570. annotationDict.set('Dest', [new Ref(17, 0), Name.get('XYZ'), 0, 841.89, null]);
  571. var annotationRef = new Ref(10, 0);
  572. var xref = new XRefMock([{
  573. ref: annotationRef,
  574. data: annotationDict
  575. }]);
  576. var annotation = annotationFactory.create(xref, annotationRef, pdfManagerMock, idFactoryMock);
  577. var data = annotation.data;
  578. expect(data.annotationType).toEqual(AnnotationType.LINK);
  579. expect(data.url).toBeUndefined();
  580. expect(data.unsafeUrl).toBeUndefined();
  581. expect(data.dest).toEqual([{
  582. num: 17,
  583. gen: 0
  584. }, { name: 'XYZ' }, 0, 841.89, null]);
  585. });
  586. });
  587. describe('WidgetAnnotation', function () {
  588. var widgetDict;
  589. beforeEach(function (done) {
  590. widgetDict = new Dict();
  591. widgetDict.set('Type', Name.get('Annot'));
  592. widgetDict.set('Subtype', Name.get('Widget'));
  593. done();
  594. });
  595. afterEach(function () {
  596. widgetDict = null;
  597. });
  598. it('should handle unknown field names', function () {
  599. var widgetRef = new Ref(20, 0);
  600. var xref = new XRefMock([{
  601. ref: widgetRef,
  602. data: widgetDict
  603. }]);
  604. var annotation = annotationFactory.create(xref, widgetRef, pdfManagerMock, idFactoryMock);
  605. var data = annotation.data;
  606. expect(data.annotationType).toEqual(AnnotationType.WIDGET);
  607. expect(data.fieldName).toEqual('');
  608. });
  609. it('should construct the field name when there are no ancestors', function () {
  610. widgetDict.set('T', 'foo');
  611. var widgetRef = new Ref(21, 0);
  612. var xref = new XRefMock([{
  613. ref: widgetRef,
  614. data: widgetDict
  615. }]);
  616. var annotation = annotationFactory.create(xref, widgetRef, pdfManagerMock, idFactoryMock);
  617. var data = annotation.data;
  618. expect(data.annotationType).toEqual(AnnotationType.WIDGET);
  619. expect(data.fieldName).toEqual('foo');
  620. });
  621. it('should construct the field name when there are ancestors', function () {
  622. var firstParent = new Dict();
  623. firstParent.set('T', 'foo');
  624. var secondParent = new Dict();
  625. secondParent.set('Parent', firstParent);
  626. secondParent.set('T', 'bar');
  627. widgetDict.set('Parent', secondParent);
  628. widgetDict.set('T', 'baz');
  629. var widgetRef = new Ref(22, 0);
  630. var xref = new XRefMock([{
  631. ref: widgetRef,
  632. data: widgetDict
  633. }]);
  634. var annotation = annotationFactory.create(xref, widgetRef, pdfManagerMock, idFactoryMock);
  635. var data = annotation.data;
  636. expect(data.annotationType).toEqual(AnnotationType.WIDGET);
  637. expect(data.fieldName).toEqual('foo.bar.baz');
  638. });
  639. it('should construct the field name if a parent is not a dictionary ' + '(issue 8143)', function () {
  640. var parentDict = new Dict();
  641. parentDict.set('Parent', null);
  642. parentDict.set('T', 'foo');
  643. widgetDict.set('Parent', parentDict);
  644. widgetDict.set('T', 'bar');
  645. var widgetRef = new Ref(22, 0);
  646. var xref = new XRefMock([{
  647. ref: widgetRef,
  648. data: widgetDict
  649. }]);
  650. var annotation = annotationFactory.create(xref, widgetRef, pdfManagerMock, idFactoryMock);
  651. var data = annotation.data;
  652. expect(data.annotationType).toEqual(AnnotationType.WIDGET);
  653. expect(data.fieldName).toEqual('foo.bar');
  654. });
  655. });
  656. describe('TextWidgetAnnotation', function () {
  657. var textWidgetDict;
  658. beforeEach(function (done) {
  659. textWidgetDict = new Dict();
  660. textWidgetDict.set('Type', Name.get('Annot'));
  661. textWidgetDict.set('Subtype', Name.get('Widget'));
  662. textWidgetDict.set('FT', Name.get('Tx'));
  663. done();
  664. });
  665. afterEach(function () {
  666. textWidgetDict = null;
  667. });
  668. it('should handle unknown text alignment, maximum length and flags', function () {
  669. var textWidgetRef = new Ref(124, 0);
  670. var xref = new XRefMock([{
  671. ref: textWidgetRef,
  672. data: textWidgetDict
  673. }]);
  674. var annotation = annotationFactory.create(xref, textWidgetRef, pdfManagerMock, idFactoryMock);
  675. var data = annotation.data;
  676. expect(data.annotationType).toEqual(AnnotationType.WIDGET);
  677. expect(data.textAlignment).toEqual(null);
  678. expect(data.maxLen).toEqual(null);
  679. expect(data.readOnly).toEqual(false);
  680. expect(data.multiLine).toEqual(false);
  681. expect(data.comb).toEqual(false);
  682. });
  683. it('should not set invalid text alignment, maximum length and flags', function () {
  684. textWidgetDict.set('Q', 'center');
  685. textWidgetDict.set('MaxLen', 'five');
  686. textWidgetDict.set('Ff', 'readonly');
  687. var textWidgetRef = new Ref(43, 0);
  688. var xref = new XRefMock([{
  689. ref: textWidgetRef,
  690. data: textWidgetDict
  691. }]);
  692. var annotation = annotationFactory.create(xref, textWidgetRef, pdfManagerMock, idFactoryMock);
  693. var data = annotation.data;
  694. expect(data.annotationType).toEqual(AnnotationType.WIDGET);
  695. expect(data.textAlignment).toEqual(null);
  696. expect(data.maxLen).toEqual(null);
  697. expect(data.readOnly).toEqual(false);
  698. expect(data.multiLine).toEqual(false);
  699. expect(data.comb).toEqual(false);
  700. });
  701. it('should set valid text alignment, maximum length and flags', function () {
  702. textWidgetDict.set('Q', 1);
  703. textWidgetDict.set('MaxLen', 20);
  704. textWidgetDict.set('Ff', AnnotationFieldFlag.READONLY + AnnotationFieldFlag.MULTILINE);
  705. var textWidgetRef = new Ref(84, 0);
  706. var xref = new XRefMock([{
  707. ref: textWidgetRef,
  708. data: textWidgetDict
  709. }]);
  710. var annotation = annotationFactory.create(xref, textWidgetRef, pdfManagerMock, idFactoryMock);
  711. var data = annotation.data;
  712. expect(data.annotationType).toEqual(AnnotationType.WIDGET);
  713. expect(data.textAlignment).toEqual(1);
  714. expect(data.maxLen).toEqual(20);
  715. expect(data.readOnly).toEqual(true);
  716. expect(data.multiLine).toEqual(true);
  717. });
  718. it('should reject comb fields without a maximum length', function () {
  719. textWidgetDict.set('Ff', AnnotationFieldFlag.COMB);
  720. var textWidgetRef = new Ref(46, 0);
  721. var xref = new XRefMock([{
  722. ref: textWidgetRef,
  723. data: textWidgetDict
  724. }]);
  725. var annotation = annotationFactory.create(xref, textWidgetRef, pdfManagerMock, idFactoryMock);
  726. var data = annotation.data;
  727. expect(data.annotationType).toEqual(AnnotationType.WIDGET);
  728. expect(data.comb).toEqual(false);
  729. });
  730. it('should accept comb fields with a maximum length', function () {
  731. textWidgetDict.set('MaxLen', 20);
  732. textWidgetDict.set('Ff', AnnotationFieldFlag.COMB);
  733. var textWidgetRef = new Ref(46, 0);
  734. var xref = new XRefMock([{
  735. ref: textWidgetRef,
  736. data: textWidgetDict
  737. }]);
  738. var annotation = annotationFactory.create(xref, textWidgetRef, pdfManagerMock, idFactoryMock);
  739. var data = annotation.data;
  740. expect(data.annotationType).toEqual(AnnotationType.WIDGET);
  741. expect(data.comb).toEqual(true);
  742. });
  743. it('should only accept comb fields when the flags are valid', function () {
  744. var invalidFieldFlags = [AnnotationFieldFlag.MULTILINE, AnnotationFieldFlag.PASSWORD, AnnotationFieldFlag.FILESELECT];
  745. var flags = AnnotationFieldFlag.COMB + AnnotationFieldFlag.MULTILINE + AnnotationFieldFlag.PASSWORD + AnnotationFieldFlag.FILESELECT;
  746. for (var i = 0, ii = invalidFieldFlags.length; i <= ii; i++) {
  747. textWidgetDict.set('MaxLen', 20);
  748. textWidgetDict.set('Ff', flags);
  749. var textWidgetRef = new Ref(93, 0);
  750. var xref = new XRefMock([{
  751. ref: textWidgetRef,
  752. data: textWidgetDict
  753. }]);
  754. var annotation = annotationFactory.create(xref, textWidgetRef, pdfManagerMock, idFactoryMock);
  755. var data = annotation.data;
  756. expect(data.annotationType).toEqual(AnnotationType.WIDGET);
  757. var valid = invalidFieldFlags.length === 0;
  758. expect(data.comb).toEqual(valid);
  759. if (!valid) {
  760. flags -= invalidFieldFlags.splice(-1, 1);
  761. }
  762. }
  763. });
  764. });
  765. describe('ButtonWidgetAnnotation', function () {
  766. var buttonWidgetDict;
  767. beforeEach(function (done) {
  768. buttonWidgetDict = new Dict();
  769. buttonWidgetDict.set('Type', Name.get('Annot'));
  770. buttonWidgetDict.set('Subtype', Name.get('Widget'));
  771. buttonWidgetDict.set('FT', Name.get('Btn'));
  772. done();
  773. });
  774. afterEach(function () {
  775. buttonWidgetDict = null;
  776. });
  777. it('should handle checkboxes', function () {
  778. buttonWidgetDict.set('V', Name.get('1'));
  779. var buttonWidgetRef = new Ref(124, 0);
  780. var xref = new XRefMock([{
  781. ref: buttonWidgetRef,
  782. data: buttonWidgetDict
  783. }]);
  784. var annotation = annotationFactory.create(xref, buttonWidgetRef, pdfManagerMock, idFactoryMock);
  785. var data = annotation.data;
  786. expect(data.annotationType).toEqual(AnnotationType.WIDGET);
  787. expect(data.checkBox).toEqual(true);
  788. expect(data.fieldValue).toEqual('1');
  789. expect(data.radioButton).toEqual(false);
  790. });
  791. it('should handle radio buttons with a field value', function () {
  792. var parentDict = new Dict();
  793. parentDict.set('V', Name.get('1'));
  794. var normalAppearanceStateDict = new Dict();
  795. normalAppearanceStateDict.set('2', null);
  796. var appearanceStatesDict = new Dict();
  797. appearanceStatesDict.set('N', normalAppearanceStateDict);
  798. buttonWidgetDict.set('Ff', AnnotationFieldFlag.RADIO);
  799. buttonWidgetDict.set('Parent', parentDict);
  800. buttonWidgetDict.set('AP', appearanceStatesDict);
  801. var buttonWidgetRef = new Ref(124, 0);
  802. var xref = new XRefMock([{
  803. ref: buttonWidgetRef,
  804. data: buttonWidgetDict
  805. }]);
  806. var annotation = annotationFactory.create(xref, buttonWidgetRef, pdfManagerMock, idFactoryMock);
  807. var data = annotation.data;
  808. expect(data.annotationType).toEqual(AnnotationType.WIDGET);
  809. expect(data.checkBox).toEqual(false);
  810. expect(data.radioButton).toEqual(true);
  811. expect(data.fieldValue).toEqual('1');
  812. expect(data.buttonValue).toEqual('2');
  813. });
  814. it('should handle radio buttons without a field value', function () {
  815. var normalAppearanceStateDict = new Dict();
  816. normalAppearanceStateDict.set('2', null);
  817. var appearanceStatesDict = new Dict();
  818. appearanceStatesDict.set('N', normalAppearanceStateDict);
  819. buttonWidgetDict.set('Ff', AnnotationFieldFlag.RADIO);
  820. buttonWidgetDict.set('AP', appearanceStatesDict);
  821. var buttonWidgetRef = new Ref(124, 0);
  822. var xref = new XRefMock([{
  823. ref: buttonWidgetRef,
  824. data: buttonWidgetDict
  825. }]);
  826. var annotation = annotationFactory.create(xref, buttonWidgetRef, pdfManagerMock, idFactoryMock);
  827. var data = annotation.data;
  828. expect(data.annotationType).toEqual(AnnotationType.WIDGET);
  829. expect(data.checkBox).toEqual(false);
  830. expect(data.radioButton).toEqual(true);
  831. expect(data.fieldValue).toEqual(null);
  832. expect(data.buttonValue).toEqual('2');
  833. });
  834. });
  835. describe('ChoiceWidgetAnnotation', function () {
  836. var choiceWidgetDict;
  837. beforeEach(function (done) {
  838. choiceWidgetDict = new Dict();
  839. choiceWidgetDict.set('Type', Name.get('Annot'));
  840. choiceWidgetDict.set('Subtype', Name.get('Widget'));
  841. choiceWidgetDict.set('FT', Name.get('Ch'));
  842. done();
  843. });
  844. afterEach(function () {
  845. choiceWidgetDict = null;
  846. });
  847. it('should handle missing option arrays', function () {
  848. var choiceWidgetRef = new Ref(122, 0);
  849. var xref = new XRefMock([{
  850. ref: choiceWidgetRef,
  851. data: choiceWidgetDict
  852. }]);
  853. var annotation = annotationFactory.create(xref, choiceWidgetRef, pdfManagerMock, idFactoryMock);
  854. var data = annotation.data;
  855. expect(data.annotationType).toEqual(AnnotationType.WIDGET);
  856. expect(data.options).toEqual([]);
  857. });
  858. it('should handle option arrays with array elements', function () {
  859. var optionBarRef = new Ref(20, 0);
  860. var optionBarStr = 'Bar';
  861. var optionOneRef = new Ref(10, 0);
  862. var optionOneArr = ['bar_export', optionBarRef];
  863. var options = [['foo_export', 'Foo'], optionOneRef];
  864. var expected = [{
  865. exportValue: 'foo_export',
  866. displayValue: 'Foo'
  867. }, {
  868. exportValue: 'bar_export',
  869. displayValue: 'Bar'
  870. }];
  871. choiceWidgetDict.set('Opt', options);
  872. var choiceWidgetRef = new Ref(123, 0);
  873. var xref = new XRefMock([{
  874. ref: choiceWidgetRef,
  875. data: choiceWidgetDict
  876. }, {
  877. ref: optionBarRef,
  878. data: optionBarStr
  879. }, {
  880. ref: optionOneRef,
  881. data: optionOneArr
  882. }]);
  883. var annotation = annotationFactory.create(xref, choiceWidgetRef, pdfManagerMock, idFactoryMock);
  884. var data = annotation.data;
  885. expect(data.annotationType).toEqual(AnnotationType.WIDGET);
  886. expect(data.options).toEqual(expected);
  887. });
  888. it('should handle option arrays with string elements', function () {
  889. var optionBarRef = new Ref(10, 0);
  890. var optionBarStr = 'Bar';
  891. var options = ['Foo', optionBarRef];
  892. var expected = [{
  893. exportValue: 'Foo',
  894. displayValue: 'Foo'
  895. }, {
  896. exportValue: 'Bar',
  897. displayValue: 'Bar'
  898. }];
  899. choiceWidgetDict.set('Opt', options);
  900. var choiceWidgetRef = new Ref(981, 0);
  901. var xref = new XRefMock([{
  902. ref: choiceWidgetRef,
  903. data: choiceWidgetDict
  904. }, {
  905. ref: optionBarRef,
  906. data: optionBarStr
  907. }]);
  908. var annotation = annotationFactory.create(xref, choiceWidgetRef, pdfManagerMock, idFactoryMock);
  909. var data = annotation.data;
  910. expect(data.annotationType).toEqual(AnnotationType.WIDGET);
  911. expect(data.options).toEqual(expected);
  912. });
  913. it('should handle inherited option arrays (issue 8094)', function () {
  914. var options = [['Value1', 'Description1'], ['Value2', 'Description2']];
  915. var expected = [{
  916. exportValue: 'Value1',
  917. displayValue: 'Description1'
  918. }, {
  919. exportValue: 'Value2',
  920. displayValue: 'Description2'
  921. }];
  922. var parentDict = new Dict();
  923. parentDict.set('Opt', options);
  924. choiceWidgetDict.set('Parent', parentDict);
  925. var choiceWidgetRef = new Ref(123, 0);
  926. var xref = new XRefMock([{
  927. ref: choiceWidgetRef,
  928. data: choiceWidgetDict
  929. }]);
  930. var annotation = annotationFactory.create(xref, choiceWidgetRef, pdfManagerMock, idFactoryMock);
  931. var data = annotation.data;
  932. expect(data.annotationType).toEqual(AnnotationType.WIDGET);
  933. expect(data.options).toEqual(expected);
  934. });
  935. it('should handle array field values', function () {
  936. var fieldValue = ['Foo', 'Bar'];
  937. choiceWidgetDict.set('V', fieldValue);
  938. var choiceWidgetRef = new Ref(968, 0);
  939. var xref = new XRefMock([{
  940. ref: choiceWidgetRef,
  941. data: choiceWidgetDict
  942. }]);
  943. var annotation = annotationFactory.create(xref, choiceWidgetRef, pdfManagerMock, idFactoryMock);
  944. var data = annotation.data;
  945. expect(data.annotationType).toEqual(AnnotationType.WIDGET);
  946. expect(data.fieldValue).toEqual(fieldValue);
  947. });
  948. it('should handle string field values', function () {
  949. var fieldValue = 'Foo';
  950. choiceWidgetDict.set('V', fieldValue);
  951. var choiceWidgetRef = new Ref(978, 0);
  952. var xref = new XRefMock([{
  953. ref: choiceWidgetRef,
  954. data: choiceWidgetDict
  955. }]);
  956. var annotation = annotationFactory.create(xref, choiceWidgetRef, pdfManagerMock, idFactoryMock);
  957. var data = annotation.data;
  958. expect(data.annotationType).toEqual(AnnotationType.WIDGET);
  959. expect(data.fieldValue).toEqual([fieldValue]);
  960. });
  961. it('should handle unknown flags', function () {
  962. var choiceWidgetRef = new Ref(166, 0);
  963. var xref = new XRefMock([{
  964. ref: choiceWidgetRef,
  965. data: choiceWidgetDict
  966. }]);
  967. var annotation = annotationFactory.create(xref, choiceWidgetRef, pdfManagerMock, idFactoryMock);
  968. var data = annotation.data;
  969. expect(data.annotationType).toEqual(AnnotationType.WIDGET);
  970. expect(data.readOnly).toEqual(false);
  971. expect(data.combo).toEqual(false);
  972. expect(data.multiSelect).toEqual(false);
  973. });
  974. it('should not set invalid flags', function () {
  975. choiceWidgetDict.set('Ff', 'readonly');
  976. var choiceWidgetRef = new Ref(165, 0);
  977. var xref = new XRefMock([{
  978. ref: choiceWidgetRef,
  979. data: choiceWidgetDict
  980. }]);
  981. var annotation = annotationFactory.create(xref, choiceWidgetRef, pdfManagerMock, idFactoryMock);
  982. var data = annotation.data;
  983. expect(data.annotationType).toEqual(AnnotationType.WIDGET);
  984. expect(data.readOnly).toEqual(false);
  985. expect(data.combo).toEqual(false);
  986. expect(data.multiSelect).toEqual(false);
  987. });
  988. it('should set valid flags', function () {
  989. choiceWidgetDict.set('Ff', AnnotationFieldFlag.READONLY + AnnotationFieldFlag.COMBO + AnnotationFieldFlag.MULTISELECT);
  990. var choiceWidgetRef = new Ref(512, 0);
  991. var xref = new XRefMock([{
  992. ref: choiceWidgetRef,
  993. data: choiceWidgetDict
  994. }]);
  995. var annotation = annotationFactory.create(xref, choiceWidgetRef, pdfManagerMock, idFactoryMock);
  996. var data = annotation.data;
  997. expect(data.annotationType).toEqual(AnnotationType.WIDGET);
  998. expect(data.readOnly).toEqual(true);
  999. expect(data.combo).toEqual(true);
  1000. expect(data.multiSelect).toEqual(true);
  1001. });
  1002. });
  1003. describe('LineAnnotation', function () {
  1004. it('should set the line coordinates', function () {
  1005. var lineDict = new Dict();
  1006. lineDict.set('Type', Name.get('Annot'));
  1007. lineDict.set('Subtype', Name.get('Line'));
  1008. lineDict.set('L', [1, 2, 3, 4]);
  1009. var lineRef = new Ref(122, 0);
  1010. var xref = new XRefMock([{
  1011. ref: lineRef,
  1012. data: lineDict
  1013. }]);
  1014. var annotation = annotationFactory.create(xref, lineRef, pdfManagerMock, idFactoryMock);
  1015. var data = annotation.data;
  1016. expect(data.annotationType).toEqual(AnnotationType.LINE);
  1017. expect(data.lineCoordinates).toEqual([1, 2, 3, 4]);
  1018. });
  1019. });
  1020. describe('FileAttachmentAnnotation', function () {
  1021. it('should correctly parse a file attachment', function () {
  1022. var fileStream = new StringStream('<<\n' + '/Type /EmbeddedFile\n' + '/Subtype /text#2Fplain\n' + '>>\n' + 'stream\n' + 'Test attachment' + 'endstream\n');
  1023. var lexer = new Lexer(fileStream);
  1024. var parser = new Parser(lexer, true);
  1025. var fileStreamRef = new Ref(18, 0);
  1026. var fileStreamDict = parser.getObj();
  1027. var embeddedFileDict = new Dict();
  1028. embeddedFileDict.set('F', fileStreamRef);
  1029. var fileSpecRef = new Ref(19, 0);
  1030. var fileSpecDict = new Dict();
  1031. fileSpecDict.set('Type', Name.get('Filespec'));
  1032. fileSpecDict.set('Desc', '');
  1033. fileSpecDict.set('EF', embeddedFileDict);
  1034. fileSpecDict.set('UF', 'Test.txt');
  1035. var fileAttachmentRef = new Ref(20, 0);
  1036. var fileAttachmentDict = new Dict();
  1037. fileAttachmentDict.set('Type', Name.get('Annot'));
  1038. fileAttachmentDict.set('Subtype', Name.get('FileAttachment'));
  1039. fileAttachmentDict.set('FS', fileSpecRef);
  1040. fileAttachmentDict.set('T', 'Topic');
  1041. fileAttachmentDict.set('Contents', 'Test.txt');
  1042. var xref = new XRefMock([{
  1043. ref: fileStreamRef,
  1044. data: fileStreamDict
  1045. }, {
  1046. ref: fileSpecRef,
  1047. data: fileSpecDict
  1048. }, {
  1049. ref: fileAttachmentRef,
  1050. data: fileAttachmentDict
  1051. }]);
  1052. embeddedFileDict.assignXref(xref);
  1053. fileSpecDict.assignXref(xref);
  1054. fileAttachmentDict.assignXref(xref);
  1055. var annotation = annotationFactory.create(xref, fileAttachmentRef, pdfManagerMock, idFactoryMock);
  1056. var data = annotation.data;
  1057. expect(data.annotationType).toEqual(AnnotationType.FILEATTACHMENT);
  1058. expect(data.file.filename).toEqual('Test.txt');
  1059. expect(data.file.content).toEqual(stringToBytes('Test attachment'));
  1060. });
  1061. });
  1062. describe('PopupAnnotation', function () {
  1063. it('should inherit the parent flags when the Popup is not viewable, ' + 'but the parent is (PR 7352)', function () {
  1064. var parentDict = new Dict();
  1065. parentDict.set('Type', Name.get('Annot'));
  1066. parentDict.set('Subtype', Name.get('Text'));
  1067. parentDict.set('F', 28);
  1068. var popupDict = new Dict();
  1069. popupDict.set('Type', Name.get('Annot'));
  1070. popupDict.set('Subtype', Name.get('Popup'));
  1071. popupDict.set('F', 25);
  1072. popupDict.set('Parent', parentDict);
  1073. var popupRef = new Ref(13, 0);
  1074. var xref = new XRefMock([{
  1075. ref: popupRef,
  1076. data: popupDict
  1077. }]);
  1078. var annotation = annotationFactory.create(xref, popupRef, pdfManagerMock, idFactoryMock);
  1079. var data = annotation.data;
  1080. expect(data.annotationType).toEqual(AnnotationType.POPUP);
  1081. expect(data.annotationFlags).toEqual(25);
  1082. expect(annotation.viewable).toEqual(true);
  1083. });
  1084. });
  1085. });