2
0

annotation_spec.js 42 KB

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