annotation_spec.js 44 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069
  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('FileAttachmentAnnotation', function () {
  1004. it('should correctly parse a file attachment', function () {
  1005. var fileStream = new StringStream('<<\n' + '/Type /EmbeddedFile\n' + '/Subtype /text#2Fplain\n' + '>>\n' + 'stream\n' + 'Test attachment' + 'endstream\n');
  1006. var lexer = new Lexer(fileStream);
  1007. var parser = new Parser(lexer, true);
  1008. var fileStreamRef = new Ref(18, 0);
  1009. var fileStreamDict = parser.getObj();
  1010. var embeddedFileDict = new Dict();
  1011. embeddedFileDict.set('F', fileStreamRef);
  1012. var fileSpecRef = new Ref(19, 0);
  1013. var fileSpecDict = new Dict();
  1014. fileSpecDict.set('Type', Name.get('Filespec'));
  1015. fileSpecDict.set('Desc', '');
  1016. fileSpecDict.set('EF', embeddedFileDict);
  1017. fileSpecDict.set('UF', 'Test.txt');
  1018. var fileAttachmentRef = new Ref(20, 0);
  1019. var fileAttachmentDict = new Dict();
  1020. fileAttachmentDict.set('Type', Name.get('Annot'));
  1021. fileAttachmentDict.set('Subtype', Name.get('FileAttachment'));
  1022. fileAttachmentDict.set('FS', fileSpecRef);
  1023. fileAttachmentDict.set('T', 'Topic');
  1024. fileAttachmentDict.set('Contents', 'Test.txt');
  1025. var xref = new XRefMock([{
  1026. ref: fileStreamRef,
  1027. data: fileStreamDict
  1028. }, {
  1029. ref: fileSpecRef,
  1030. data: fileSpecDict
  1031. }, {
  1032. ref: fileAttachmentRef,
  1033. data: fileAttachmentDict
  1034. }]);
  1035. embeddedFileDict.assignXref(xref);
  1036. fileSpecDict.assignXref(xref);
  1037. fileAttachmentDict.assignXref(xref);
  1038. var annotation = annotationFactory.create(xref, fileAttachmentRef, pdfManagerMock, idFactoryMock);
  1039. var data = annotation.data;
  1040. expect(data.annotationType).toEqual(AnnotationType.FILEATTACHMENT);
  1041. expect(data.file.filename).toEqual('Test.txt');
  1042. expect(data.file.content).toEqual(stringToBytes('Test attachment'));
  1043. });
  1044. });
  1045. describe('PopupAnnotation', function () {
  1046. it('should inherit the parent flags when the Popup is not viewable, ' + 'but the parent is (PR 7352)', function () {
  1047. var parentDict = new Dict();
  1048. parentDict.set('Type', Name.get('Annot'));
  1049. parentDict.set('Subtype', Name.get('Text'));
  1050. parentDict.set('F', 28);
  1051. var popupDict = new Dict();
  1052. popupDict.set('Type', Name.get('Annot'));
  1053. popupDict.set('Subtype', Name.get('Popup'));
  1054. popupDict.set('F', 25);
  1055. popupDict.set('Parent', parentDict);
  1056. var popupRef = new Ref(13, 0);
  1057. var xref = new XRefMock([{
  1058. ref: popupRef,
  1059. data: popupDict
  1060. }]);
  1061. var annotation = annotationFactory.create(xref, popupRef, pdfManagerMock, idFactoryMock);
  1062. var data = annotation.data;
  1063. expect(data.annotationType).toEqual(AnnotationType.POPUP);
  1064. expect(data.annotationFlags).toEqual(25);
  1065. expect(annotation.viewable).toEqual(true);
  1066. });
  1067. });
  1068. });