annotation_spec.js 41 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178
  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. });
  718. describe('TextWidgetAnnotation', function () {
  719. var textWidgetDict;
  720. beforeEach(function (done) {
  721. textWidgetDict = new Dict();
  722. textWidgetDict.set('Type', Name.get('Annot'));
  723. textWidgetDict.set('Subtype', Name.get('Widget'));
  724. textWidgetDict.set('FT', Name.get('Tx'));
  725. done();
  726. });
  727. afterEach(function () {
  728. textWidgetDict = null;
  729. });
  730. it('should handle unknown text alignment, maximum length and flags', function () {
  731. var textWidgetRef = new Ref(124, 0);
  732. var xref = new XRefMock([{
  733. ref: textWidgetRef,
  734. data: textWidgetDict
  735. }]);
  736. var annotation = annotationFactory.create(xref, textWidgetRef, pdfManagerMock, idFactoryMock);
  737. var data = annotation.data;
  738. expect(data.annotationType).toEqual(AnnotationType.WIDGET);
  739. expect(data.textAlignment).toEqual(null);
  740. expect(data.maxLen).toEqual(null);
  741. expect(data.readOnly).toEqual(false);
  742. expect(data.multiLine).toEqual(false);
  743. expect(data.comb).toEqual(false);
  744. });
  745. it('should not set invalid text alignment, maximum length and flags', function () {
  746. textWidgetDict.set('Q', 'center');
  747. textWidgetDict.set('MaxLen', 'five');
  748. textWidgetDict.set('Ff', 'readonly');
  749. var textWidgetRef = new Ref(43, 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. expect(data.textAlignment).toEqual(null);
  758. expect(data.maxLen).toEqual(null);
  759. expect(data.readOnly).toEqual(false);
  760. expect(data.multiLine).toEqual(false);
  761. expect(data.comb).toEqual(false);
  762. });
  763. it('should set valid text alignment, maximum length and flags', function () {
  764. textWidgetDict.set('Q', 1);
  765. textWidgetDict.set('MaxLen', 20);
  766. textWidgetDict.set('Ff', AnnotationFieldFlag.READONLY + AnnotationFieldFlag.MULTILINE);
  767. var textWidgetRef = new Ref(84, 0);
  768. var xref = new XRefMock([{
  769. ref: textWidgetRef,
  770. data: textWidgetDict
  771. }]);
  772. var annotation = annotationFactory.create(xref, textWidgetRef, pdfManagerMock, idFactoryMock);
  773. var data = annotation.data;
  774. expect(data.annotationType).toEqual(AnnotationType.WIDGET);
  775. expect(data.textAlignment).toEqual(1);
  776. expect(data.maxLen).toEqual(20);
  777. expect(data.readOnly).toEqual(true);
  778. expect(data.multiLine).toEqual(true);
  779. });
  780. it('should reject comb fields without a maximum length', function () {
  781. textWidgetDict.set('Ff', AnnotationFieldFlag.COMB);
  782. var textWidgetRef = new Ref(46, 0);
  783. var xref = new XRefMock([{
  784. ref: textWidgetRef,
  785. data: textWidgetDict
  786. }]);
  787. var annotation = annotationFactory.create(xref, textWidgetRef, pdfManagerMock, idFactoryMock);
  788. var data = annotation.data;
  789. expect(data.annotationType).toEqual(AnnotationType.WIDGET);
  790. expect(data.comb).toEqual(false);
  791. });
  792. it('should accept comb fields with a maximum length', function () {
  793. textWidgetDict.set('MaxLen', 20);
  794. textWidgetDict.set('Ff', AnnotationFieldFlag.COMB);
  795. var textWidgetRef = new Ref(46, 0);
  796. var xref = new XRefMock([{
  797. ref: textWidgetRef,
  798. data: textWidgetDict
  799. }]);
  800. var annotation = annotationFactory.create(xref, textWidgetRef, pdfManagerMock, idFactoryMock);
  801. var data = annotation.data;
  802. expect(data.annotationType).toEqual(AnnotationType.WIDGET);
  803. expect(data.comb).toEqual(true);
  804. });
  805. it('should only accept comb fields when the flags are valid', function () {
  806. var invalidFieldFlags = [
  807. AnnotationFieldFlag.MULTILINE,
  808. AnnotationFieldFlag.PASSWORD,
  809. AnnotationFieldFlag.FILESELECT
  810. ];
  811. var flags = AnnotationFieldFlag.COMB + AnnotationFieldFlag.MULTILINE + AnnotationFieldFlag.PASSWORD + AnnotationFieldFlag.FILESELECT;
  812. for (var i = 0, ii = invalidFieldFlags.length; i <= ii; i++) {
  813. textWidgetDict.set('MaxLen', 20);
  814. textWidgetDict.set('Ff', flags);
  815. var textWidgetRef = new Ref(93, 0);
  816. var xref = new XRefMock([{
  817. ref: textWidgetRef,
  818. data: textWidgetDict
  819. }]);
  820. var annotation = annotationFactory.create(xref, textWidgetRef, pdfManagerMock, idFactoryMock);
  821. var data = annotation.data;
  822. expect(data.annotationType).toEqual(AnnotationType.WIDGET);
  823. var valid = invalidFieldFlags.length === 0;
  824. expect(data.comb).toEqual(valid);
  825. if (!valid) {
  826. flags -= invalidFieldFlags.splice(-1, 1);
  827. }
  828. }
  829. });
  830. });
  831. describe('ButtonWidgetAnnotation', function () {
  832. var buttonWidgetDict;
  833. beforeEach(function (done) {
  834. buttonWidgetDict = new Dict();
  835. buttonWidgetDict.set('Type', Name.get('Annot'));
  836. buttonWidgetDict.set('Subtype', Name.get('Widget'));
  837. buttonWidgetDict.set('FT', Name.get('Btn'));
  838. done();
  839. });
  840. afterEach(function () {
  841. buttonWidgetDict = null;
  842. });
  843. it('should handle checkboxes', function () {
  844. buttonWidgetDict.set('V', Name.get('1'));
  845. var buttonWidgetRef = new Ref(124, 0);
  846. var xref = new XRefMock([{
  847. ref: buttonWidgetRef,
  848. data: buttonWidgetDict
  849. }]);
  850. var annotation = annotationFactory.create(xref, buttonWidgetRef, pdfManagerMock, idFactoryMock);
  851. var data = annotation.data;
  852. expect(data.annotationType).toEqual(AnnotationType.WIDGET);
  853. expect(data.checkBox).toEqual(true);
  854. expect(data.fieldValue).toEqual('1');
  855. expect(data.radioButton).toEqual(false);
  856. });
  857. it('should handle radio buttons with a field value', function () {
  858. var parentDict = new Dict();
  859. parentDict.set('V', Name.get('1'));
  860. var normalAppearanceStateDict = new Dict();
  861. normalAppearanceStateDict.set('2', null);
  862. var appearanceStatesDict = new Dict();
  863. appearanceStatesDict.set('N', normalAppearanceStateDict);
  864. buttonWidgetDict.set('Ff', AnnotationFieldFlag.RADIO);
  865. buttonWidgetDict.set('Parent', parentDict);
  866. buttonWidgetDict.set('AP', appearanceStatesDict);
  867. var buttonWidgetRef = new Ref(124, 0);
  868. var xref = new XRefMock([{
  869. ref: buttonWidgetRef,
  870. data: buttonWidgetDict
  871. }]);
  872. var annotation = annotationFactory.create(xref, buttonWidgetRef, pdfManagerMock, idFactoryMock);
  873. var data = annotation.data;
  874. expect(data.annotationType).toEqual(AnnotationType.WIDGET);
  875. expect(data.checkBox).toEqual(false);
  876. expect(data.radioButton).toEqual(true);
  877. expect(data.fieldValue).toEqual('1');
  878. expect(data.buttonValue).toEqual('2');
  879. });
  880. it('should handle radio buttons without a field value', function () {
  881. var normalAppearanceStateDict = new Dict();
  882. normalAppearanceStateDict.set('2', null);
  883. var appearanceStatesDict = new Dict();
  884. appearanceStatesDict.set('N', normalAppearanceStateDict);
  885. buttonWidgetDict.set('Ff', AnnotationFieldFlag.RADIO);
  886. buttonWidgetDict.set('AP', appearanceStatesDict);
  887. var buttonWidgetRef = new Ref(124, 0);
  888. var xref = new XRefMock([{
  889. ref: buttonWidgetRef,
  890. data: buttonWidgetDict
  891. }]);
  892. var annotation = annotationFactory.create(xref, buttonWidgetRef, pdfManagerMock, idFactoryMock);
  893. var data = annotation.data;
  894. expect(data.annotationType).toEqual(AnnotationType.WIDGET);
  895. expect(data.checkBox).toEqual(false);
  896. expect(data.radioButton).toEqual(true);
  897. expect(data.fieldValue).toEqual(null);
  898. expect(data.buttonValue).toEqual('2');
  899. });
  900. });
  901. describe('ChoiceWidgetAnnotation', function () {
  902. var choiceWidgetDict;
  903. beforeEach(function (done) {
  904. choiceWidgetDict = new Dict();
  905. choiceWidgetDict.set('Type', Name.get('Annot'));
  906. choiceWidgetDict.set('Subtype', Name.get('Widget'));
  907. choiceWidgetDict.set('FT', Name.get('Ch'));
  908. done();
  909. });
  910. afterEach(function () {
  911. choiceWidgetDict = null;
  912. });
  913. it('should handle missing option arrays', function () {
  914. var choiceWidgetRef = new Ref(122, 0);
  915. var xref = new XRefMock([{
  916. ref: choiceWidgetRef,
  917. data: choiceWidgetDict
  918. }]);
  919. var annotation = annotationFactory.create(xref, choiceWidgetRef, pdfManagerMock, idFactoryMock);
  920. var data = annotation.data;
  921. expect(data.annotationType).toEqual(AnnotationType.WIDGET);
  922. expect(data.options).toEqual([]);
  923. });
  924. it('should handle option arrays with array elements', function () {
  925. var optionBarRef = new Ref(20, 0);
  926. var optionBarStr = 'Bar';
  927. var optionOneRef = new Ref(10, 0);
  928. var optionOneArr = [
  929. 'bar_export',
  930. optionBarRef
  931. ];
  932. var options = [
  933. [
  934. 'foo_export',
  935. 'Foo'
  936. ],
  937. optionOneRef
  938. ];
  939. var expected = [
  940. {
  941. exportValue: 'foo_export',
  942. displayValue: 'Foo'
  943. },
  944. {
  945. exportValue: 'bar_export',
  946. displayValue: 'Bar'
  947. }
  948. ];
  949. choiceWidgetDict.set('Opt', options);
  950. var choiceWidgetRef = new Ref(123, 0);
  951. var xref = new XRefMock([
  952. {
  953. ref: choiceWidgetRef,
  954. data: choiceWidgetDict
  955. },
  956. {
  957. ref: optionBarRef,
  958. data: optionBarStr
  959. },
  960. {
  961. ref: optionOneRef,
  962. data: optionOneArr
  963. }
  964. ]);
  965. var annotation = annotationFactory.create(xref, choiceWidgetRef, pdfManagerMock, idFactoryMock);
  966. var data = annotation.data;
  967. expect(data.annotationType).toEqual(AnnotationType.WIDGET);
  968. expect(data.options).toEqual(expected);
  969. });
  970. it('should handle option arrays with string elements', function () {
  971. var optionBarRef = new Ref(10, 0);
  972. var optionBarStr = 'Bar';
  973. var options = [
  974. 'Foo',
  975. optionBarRef
  976. ];
  977. var expected = [
  978. {
  979. exportValue: 'Foo',
  980. displayValue: 'Foo'
  981. },
  982. {
  983. exportValue: 'Bar',
  984. displayValue: 'Bar'
  985. }
  986. ];
  987. choiceWidgetDict.set('Opt', options);
  988. var choiceWidgetRef = new Ref(981, 0);
  989. var xref = new XRefMock([
  990. {
  991. ref: choiceWidgetRef,
  992. data: choiceWidgetDict
  993. },
  994. {
  995. ref: optionBarRef,
  996. data: optionBarStr
  997. }
  998. ]);
  999. var annotation = annotationFactory.create(xref, choiceWidgetRef, pdfManagerMock, idFactoryMock);
  1000. var data = annotation.data;
  1001. expect(data.annotationType).toEqual(AnnotationType.WIDGET);
  1002. expect(data.options).toEqual(expected);
  1003. });
  1004. it('should handle inherited option arrays (issue 8094)', function () {
  1005. var options = [
  1006. [
  1007. 'Value1',
  1008. 'Description1'
  1009. ],
  1010. [
  1011. 'Value2',
  1012. 'Description2'
  1013. ]
  1014. ];
  1015. var expected = [
  1016. {
  1017. exportValue: 'Value1',
  1018. displayValue: 'Description1'
  1019. },
  1020. {
  1021. exportValue: 'Value2',
  1022. displayValue: 'Description2'
  1023. }
  1024. ];
  1025. var parentDict = new Dict();
  1026. parentDict.set('Opt', options);
  1027. choiceWidgetDict.set('Parent', parentDict);
  1028. var choiceWidgetRef = new Ref(123, 0);
  1029. var xref = new XRefMock([{
  1030. ref: choiceWidgetRef,
  1031. data: choiceWidgetDict
  1032. }]);
  1033. var annotation = annotationFactory.create(xref, choiceWidgetRef, pdfManagerMock, idFactoryMock);
  1034. var data = annotation.data;
  1035. expect(data.annotationType).toEqual(AnnotationType.WIDGET);
  1036. expect(data.options).toEqual(expected);
  1037. });
  1038. it('should handle array field values', function () {
  1039. var fieldValue = [
  1040. 'Foo',
  1041. 'Bar'
  1042. ];
  1043. choiceWidgetDict.set('V', fieldValue);
  1044. var choiceWidgetRef = new Ref(968, 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.fieldValue).toEqual(fieldValue);
  1053. });
  1054. it('should handle string field values', function () {
  1055. var fieldValue = 'Foo';
  1056. choiceWidgetDict.set('V', fieldValue);
  1057. var choiceWidgetRef = new Ref(978, 0);
  1058. var xref = new XRefMock([{
  1059. ref: choiceWidgetRef,
  1060. data: choiceWidgetDict
  1061. }]);
  1062. var annotation = annotationFactory.create(xref, choiceWidgetRef, pdfManagerMock, idFactoryMock);
  1063. var data = annotation.data;
  1064. expect(data.annotationType).toEqual(AnnotationType.WIDGET);
  1065. expect(data.fieldValue).toEqual([fieldValue]);
  1066. });
  1067. it('should handle unknown flags', function () {
  1068. var choiceWidgetRef = new Ref(166, 0);
  1069. var xref = new XRefMock([{
  1070. ref: choiceWidgetRef,
  1071. data: choiceWidgetDict
  1072. }]);
  1073. var annotation = annotationFactory.create(xref, choiceWidgetRef, pdfManagerMock, idFactoryMock);
  1074. var data = annotation.data;
  1075. expect(data.annotationType).toEqual(AnnotationType.WIDGET);
  1076. expect(data.readOnly).toEqual(false);
  1077. expect(data.combo).toEqual(false);
  1078. expect(data.multiSelect).toEqual(false);
  1079. });
  1080. it('should not set invalid flags', function () {
  1081. choiceWidgetDict.set('Ff', 'readonly');
  1082. var choiceWidgetRef = new Ref(165, 0);
  1083. var xref = new XRefMock([{
  1084. ref: choiceWidgetRef,
  1085. data: choiceWidgetDict
  1086. }]);
  1087. var annotation = annotationFactory.create(xref, choiceWidgetRef, pdfManagerMock, idFactoryMock);
  1088. var data = annotation.data;
  1089. expect(data.annotationType).toEqual(AnnotationType.WIDGET);
  1090. expect(data.readOnly).toEqual(false);
  1091. expect(data.combo).toEqual(false);
  1092. expect(data.multiSelect).toEqual(false);
  1093. });
  1094. it('should set valid flags', function () {
  1095. choiceWidgetDict.set('Ff', AnnotationFieldFlag.READONLY + AnnotationFieldFlag.COMBO + AnnotationFieldFlag.MULTISELECT);
  1096. var choiceWidgetRef = new Ref(512, 0);
  1097. var xref = new XRefMock([{
  1098. ref: choiceWidgetRef,
  1099. data: choiceWidgetDict
  1100. }]);
  1101. var annotation = annotationFactory.create(xref, choiceWidgetRef, pdfManagerMock, idFactoryMock);
  1102. var data = annotation.data;
  1103. expect(data.annotationType).toEqual(AnnotationType.WIDGET);
  1104. expect(data.readOnly).toEqual(true);
  1105. expect(data.combo).toEqual(true);
  1106. expect(data.multiSelect).toEqual(true);
  1107. });
  1108. });
  1109. describe('FileAttachmentAnnotation', function () {
  1110. it('should correctly parse a file attachment', function () {
  1111. var fileStream = new StringStream('<<\n' + '/Type /EmbeddedFile\n' + '/Subtype /text#2Fplain\n' + '>>\n' + 'stream\n' + 'Test attachment' + 'endstream\n');
  1112. var lexer = new Lexer(fileStream);
  1113. var parser = new Parser(lexer, true);
  1114. var fileStreamRef = new Ref(18, 0);
  1115. var fileStreamDict = parser.getObj();
  1116. var embeddedFileDict = new Dict();
  1117. embeddedFileDict.set('F', fileStreamRef);
  1118. var fileSpecRef = new Ref(19, 0);
  1119. var fileSpecDict = new Dict();
  1120. fileSpecDict.set('Type', Name.get('Filespec'));
  1121. fileSpecDict.set('Desc', '');
  1122. fileSpecDict.set('EF', embeddedFileDict);
  1123. fileSpecDict.set('UF', 'Test.txt');
  1124. var fileAttachmentRef = new Ref(20, 0);
  1125. var fileAttachmentDict = new Dict();
  1126. fileAttachmentDict.set('Type', Name.get('Annot'));
  1127. fileAttachmentDict.set('Subtype', Name.get('FileAttachment'));
  1128. fileAttachmentDict.set('FS', fileSpecRef);
  1129. fileAttachmentDict.set('T', 'Topic');
  1130. fileAttachmentDict.set('Contents', 'Test.txt');
  1131. var xref = new XRefMock([
  1132. {
  1133. ref: fileStreamRef,
  1134. data: fileStreamDict
  1135. },
  1136. {
  1137. ref: fileSpecRef,
  1138. data: fileSpecDict
  1139. },
  1140. {
  1141. ref: fileAttachmentRef,
  1142. data: fileAttachmentDict
  1143. }
  1144. ]);
  1145. embeddedFileDict.assignXref(xref);
  1146. fileSpecDict.assignXref(xref);
  1147. fileAttachmentDict.assignXref(xref);
  1148. var annotation = annotationFactory.create(xref, fileAttachmentRef, pdfManagerMock, idFactoryMock);
  1149. var data = annotation.data;
  1150. expect(data.annotationType).toEqual(AnnotationType.FILEATTACHMENT);
  1151. expect(data.file.filename).toEqual('Test.txt');
  1152. expect(data.file.content).toEqual(stringToBytes('Test attachment'));
  1153. });
  1154. });
  1155. describe('PopupAnnotation', function () {
  1156. it('should inherit the parent flags when the Popup is not viewable, ' + 'but the parent is (PR 7352)', function () {
  1157. var parentDict = new Dict();
  1158. parentDict.set('Type', Name.get('Annot'));
  1159. parentDict.set('Subtype', Name.get('Text'));
  1160. parentDict.set('F', 28);
  1161. var popupDict = new Dict();
  1162. popupDict.set('Type', Name.get('Annot'));
  1163. popupDict.set('Subtype', Name.get('Popup'));
  1164. popupDict.set('F', 25);
  1165. popupDict.set('Parent', parentDict);
  1166. var popupRef = new Ref(13, 0);
  1167. var xref = new XRefMock([{
  1168. ref: popupRef,
  1169. data: popupDict
  1170. }]);
  1171. var annotation = annotationFactory.create(xref, popupRef, pdfManagerMock, idFactoryMock);
  1172. var data = annotation.data;
  1173. expect(data.annotationType).toEqual(AnnotationType.POPUP);
  1174. expect(data.annotationFlags).toEqual(25);
  1175. expect(annotation.viewable).toEqual(true);
  1176. });
  1177. });
  1178. });