plugins_acroform.js.html 58 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="utf-8">
  5. <title>plugins/acroform.js - Documentation</title>
  6. <script src="scripts/prettify/prettify.js"></script>
  7. <script src="scripts/prettify/lang-css.js"></script>
  8. <!--[if lt IE 9]>
  9. <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
  10. <![endif]-->
  11. <link type="text/css" rel="stylesheet" href="styles/prettify.css">
  12. <link type="text/css" rel="stylesheet" href="styles/jsdoc.css">
  13. </head>
  14. <body>
  15. <input type="checkbox" id="nav-trigger" class="nav-trigger" />
  16. <label for="nav-trigger" class="navicon-button x">
  17. <div class="navicon"></div>
  18. </label>
  19. <label for="nav-trigger" class="overlay"></label>
  20. <nav>
  21. <h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="jsPDF.html">jsPDF</a></li></ul><h3>Global</h3><ul><li><a href="global.html#addFont">addFont</a></li><li><a href="global.html#addHTML">addHTML</a></li><li><a href="global.html#addMetadata">addMetadata</a></li><li><a href="global.html#addPage">addPage</a></li><li><a href="global.html#autoPrint">autoPrint</a></li><li><a href="global.html#CapJoinStyles">CapJoinStyles</a></li><li><a href="global.html#circle">circle</a></li><li><a href="global.html#ellipse">ellipse</a></li><li><a href="global.html#getFontList">getFontList</a></li><li><a href="global.html#lines">lines</a></li><li><a href="global.html#lstext">lstext</a></li><li><a href="global.html#output">output</a></li><li><a href="global.html#rect">rect</a></li><li><a href="global.html#roundedRect">roundedRect</a></li><li><a href="global.html#save">save</a></li><li><a href="global.html#setDisplayMode">setDisplayMode</a></li><li><a href="global.html#setDrawColor">setDrawColor</a></li><li><a href="global.html#setFillColor">setFillColor</a></li><li><a href="global.html#setFont">setFont</a></li><li><a href="global.html#setFontSize">setFontSize</a></li><li><a href="global.html#setFontStyle">setFontStyle</a></li><li><a href="global.html#setLineCap">setLineCap</a></li><li><a href="global.html#setLineJoin">setLineJoin</a></li><li><a href="global.html#setLineWidth">setLineWidth</a></li><li><a href="global.html#setPage">setPage</a></li><li><a href="global.html#setProperties">setProperties</a></li><li><a href="global.html#setTextColor">setTextColor</a></li><li><a href="global.html#text">text</a></li><li><a href="global.html#triangle">triangle</a></li></ul>
  22. </nav>
  23. <div id="main">
  24. <h1 class="page-title">plugins/acroform.js</h1>
  25. <section>
  26. <article>
  27. <pre class="prettyprint source linenums"><code>/**
  28. * jsPDF AcroForm Plugin
  29. * Copyright (c) 2016 Alexander Weidt, https://github.com/BiggA94
  30. *
  31. * Licensed under the MIT License.
  32. * http://opensource.org/licenses/mit-license
  33. */
  34. (window.AcroForm = function (jsPDFAPI) {
  35. 'use strict';
  36. var AcroForm = window.AcroForm;
  37. AcroForm.scale = function (x) {
  38. return (x * (acroformPlugin.internal.scaleFactor / 1));// 1 = (96 / 72)
  39. };
  40. AcroForm.antiScale = function (x) {
  41. return ((1 / acroformPlugin.internal.scaleFactor ) * x);
  42. };
  43. var acroformPlugin = {
  44. fields: [],
  45. xForms: [],
  46. /**
  47. * acroFormDictionaryRoot contains information about the AcroForm Dictionary
  48. * 0: The Event-Token, the AcroFormDictionaryCallback has
  49. * 1: The Object ID of the Root
  50. */
  51. acroFormDictionaryRoot: null,
  52. /**
  53. * After the PDF gets evaluated, the reference to the root has to be reset,
  54. * this indicates, whether the root has already been printed out
  55. */
  56. printedOut: false,
  57. internal: null
  58. };
  59. jsPDF.API.acroformPlugin = acroformPlugin;
  60. var annotReferenceCallback = function () {
  61. for (var i in this.acroformPlugin.acroFormDictionaryRoot.Fields) {
  62. var formObject = this.acroformPlugin.acroFormDictionaryRoot.Fields[i];
  63. // add Annot Reference!
  64. if (formObject.hasAnnotation) {
  65. // If theres an Annotation Widget in the Form Object, put the Reference in the /Annot array
  66. createAnnotationReference.call(this, formObject);
  67. }
  68. }
  69. };
  70. var createAcroForm = function () {
  71. if (this.acroformPlugin.acroFormDictionaryRoot) {
  72. //return;
  73. throw new Error("Exception while creating AcroformDictionary");
  74. }
  75. // The Object Number of the AcroForm Dictionary
  76. this.acroformPlugin.acroFormDictionaryRoot = new AcroForm.AcroFormDictionary();
  77. this.acroformPlugin.internal = this.internal;
  78. // add Callback for creating the AcroForm Dictionary
  79. this.acroformPlugin.acroFormDictionaryRoot._eventID = this.internal.events.subscribe('postPutResources', AcroFormDictionaryCallback);
  80. this.internal.events.subscribe('buildDocument', annotReferenceCallback); //buildDocument
  81. // Register event, that is triggered when the DocumentCatalog is written, in order to add /AcroForm
  82. this.internal.events.subscribe('putCatalog', putCatalogCallback);
  83. // Register event, that creates all Fields
  84. this.internal.events.subscribe('postPutPages', createFieldCallback);
  85. };
  86. /**
  87. * Create the Reference to the widgetAnnotation, so that it gets referenced in the Annot[] int the+
  88. * (Requires the Annotation Plugin)
  89. */
  90. var createAnnotationReference = function (object) {
  91. var options = {
  92. type: 'reference',
  93. object: object
  94. };
  95. jsPDF.API.annotationPlugin.annotations[this.internal.getPageInfo(object.page).pageNumber].push(options);
  96. };
  97. var putForm = function (formObject) {
  98. if (this.acroformPlugin.printedOut) {
  99. this.acroformPlugin.printedOut = false;
  100. this.acroformPlugin.acroFormDictionaryRoot = null;
  101. }
  102. if (!this.acroformPlugin.acroFormDictionaryRoot) {
  103. createAcroForm.call(this);
  104. }
  105. this.acroformPlugin.acroFormDictionaryRoot.Fields.push(formObject);
  106. };
  107. // Callbacks
  108. var putCatalogCallback = function () {
  109. //Put reference to AcroForm to DocumentCatalog
  110. if (typeof this.acroformPlugin.acroFormDictionaryRoot != 'undefined') { // for safety, shouldn't normally be the case
  111. this.internal.write('/AcroForm ' + this.acroformPlugin.acroFormDictionaryRoot.objId + ' '
  112. + 0 + ' R');
  113. } else {
  114. console.log('Root missing...');
  115. }
  116. };
  117. /**
  118. * Adds /Acroform X 0 R to Document Catalog,
  119. * and creates the AcroForm Dictionary
  120. */
  121. var AcroFormDictionaryCallback = function () {
  122. // Remove event
  123. this.internal.events.unsubscribe(this.acroformPlugin.acroFormDictionaryRoot._eventID);
  124. delete this.acroformPlugin.acroFormDictionaryRoot._eventID;
  125. this.acroformPlugin.printedOut = true;
  126. };
  127. /**
  128. * Creates the single Fields and writes them into the Document
  129. *
  130. * If fieldArray is set, use the fields that are inside it instead of the fields from the AcroRoot
  131. * (for the FormXObjects...)
  132. */
  133. var createFieldCallback = function (fieldArray) {
  134. var standardFields = (!fieldArray);
  135. if (!fieldArray) {
  136. // in case there is no fieldArray specified, we want to print out the Fields of the AcroForm
  137. // Print out Root
  138. this.internal.newObjectDeferredBegin(this.acroformPlugin.acroFormDictionaryRoot.objId);
  139. this.internal.out(this.acroformPlugin.acroFormDictionaryRoot.getString());
  140. }
  141. var fieldArray = fieldArray || this.acroformPlugin.acroFormDictionaryRoot.Kids;
  142. for (var i in fieldArray) {
  143. var key = i;
  144. var form = fieldArray[i];
  145. var oldRect = form.Rect;
  146. if (form.Rect) {
  147. form.Rect = AcroForm.internal.calculateCoordinates.call(this, form.Rect);
  148. }
  149. // Start Writing the Object
  150. this.internal.newObjectDeferredBegin(form.objId);
  151. var content = "";
  152. content += (form.objId + " 0 obj\n");
  153. content += ("&lt;&lt;\n" + form.getContent());
  154. form.Rect = oldRect;
  155. if (form.hasAppearanceStream &amp;&amp; !form.appearanceStreamContent) {
  156. // Calculate Appearance
  157. var appearance = AcroForm.internal.calculateAppearanceStream.call(this, form);
  158. content += "/AP &lt;&lt; /N " + appearance + " >>\n";
  159. this.acroformPlugin.xForms.push(appearance);
  160. }
  161. // Assume AppearanceStreamContent is a Array with N,R,D (at least one of them!)
  162. if (form.appearanceStreamContent) {
  163. content += "/AP &lt;&lt; ";
  164. // Iterate over N,R and D
  165. for (var k in form.appearanceStreamContent) {
  166. var value = form.appearanceStreamContent[k];
  167. content += ("/" + k + " ");
  168. content += "&lt;&lt; ";
  169. if (Object.keys(value).length >= 1 || Array.isArray(value)) {
  170. // appearanceStream is an Array or Object!
  171. for (var i in value) {
  172. var obj = value[i];
  173. if (typeof obj === 'function') {
  174. // if Function is referenced, call it in order to get the FormXObject
  175. obj = obj.call(this, form);
  176. }
  177. content += ("/" + i + " " + obj + " ");
  178. // In case the XForm is already used, e.g. OffState of CheckBoxes, don't add it
  179. if (!(this.acroformPlugin.xForms.indexOf(obj) >= 0))
  180. this.acroformPlugin.xForms.push(obj);
  181. }
  182. } else {
  183. var obj = value;
  184. if (typeof obj === 'function') {
  185. // if Function is referenced, call it in order to get the FormXObject
  186. obj = obj.call(this, form);
  187. }
  188. content += ("/" + i + " " + obj + " \n");
  189. if (!(this.acroformPlugin.xForms.indexOf(obj) >= 0))
  190. this.acroformPlugin.xForms.push(obj);
  191. }
  192. content += " >>\n";
  193. }
  194. // appearance stream is a normal Object..
  195. content += (">>\n");
  196. }
  197. content += (">>\nendobj\n");
  198. this.internal.out(content);
  199. }
  200. if (standardFields) {
  201. createXFormObjectCallback.call(this, this.acroformPlugin.xForms);
  202. }
  203. };
  204. var createXFormObjectCallback = function (fieldArray) {
  205. for (var i in fieldArray) {
  206. var key = i;
  207. var form = fieldArray[i];
  208. // Start Writing the Object
  209. this.internal.newObjectDeferredBegin(form &amp;&amp; form.objId);
  210. var content = "";
  211. content += form ? form.getString() : '';
  212. this.internal.out(content);
  213. delete fieldArray[key];
  214. }
  215. };
  216. // Public:
  217. jsPDFAPI.addField = function (fieldObject) {
  218. //var opt = parseOptions(fieldObject);
  219. if (fieldObject instanceof AcroForm.TextField) {
  220. addTextField.call(this, fieldObject);
  221. } else if (fieldObject instanceof AcroForm.ChoiceField) {
  222. addChoiceField.call(this, fieldObject);
  223. } else if (fieldObject instanceof AcroForm.Button) {
  224. addButton.call(this, fieldObject);
  225. } else if (fieldObject instanceof AcroForm.ChildClass) {
  226. putForm.call(this, fieldObject);
  227. } else if (fieldObject) {
  228. // try to put..
  229. putForm.call(this, fieldObject);
  230. }
  231. fieldObject.page = this.acroformPlugin.internal.getCurrentPageInfo().pageNumber;
  232. return this;
  233. };
  234. // ############### sort in:
  235. /**
  236. * Button
  237. * FT = Btn
  238. */
  239. var addButton = function (options) {
  240. var options = options || new AcroForm.Field();
  241. options.FT = '/Btn';
  242. /**
  243. * Calculating the Ff entry:
  244. *
  245. * The Ff entry contains flags, that have to be set bitwise
  246. * In the Following the number in the Comment is the BitPosition
  247. */
  248. var flags = options.Ff || 0;
  249. // 17, Pushbutton
  250. if (options.pushbutton) {
  251. // Options.pushbutton should be 1 or 0
  252. flags = AcroForm.internal.setBitPosition(flags, 17);
  253. delete options.pushbutton;
  254. }
  255. //16, Radio
  256. if (options.radio) {
  257. //flags = options.Ff | options.radio &lt;&lt; 15;
  258. flags = AcroForm.internal.setBitPosition(flags, 16);
  259. delete options.radio;
  260. }
  261. // 15, NoToggleToOff (Radio buttons only
  262. if (options.noToggleToOff) {
  263. //flags = options.Ff | options.noToggleToOff &lt;&lt; 14;
  264. flags = AcroForm.internal.setBitPosition(flags, 15);
  265. //delete options.noToggleToOff;
  266. }
  267. // In case, there is no Flag set, it is a check-box
  268. options.Ff = flags;
  269. putForm.call(this, options);
  270. };
  271. var addTextField = function (options) {
  272. var options = options || new AcroForm.Field();
  273. options.FT = '/Tx';
  274. /**
  275. * Calculating the Ff entry:
  276. *
  277. * The Ff entry contains flags, that have to be set bitwise
  278. * In the Following the number in the Comment is the BitPosition
  279. */
  280. var flags = options.Ff || 0;
  281. // 13, multiline
  282. if (options.multiline) {
  283. // Set Flag
  284. flags = flags | (1 &lt;&lt; 12);
  285. // Remove multiline from FieldObject
  286. //delete options.multiline;
  287. }
  288. // 14, Password
  289. if (options.password) {
  290. flags = flags | (1 &lt;&lt; 13);
  291. //delete options.password;
  292. }
  293. // 21, FileSelect, PDF 1.4...
  294. if (options.fileSelect) {
  295. flags = flags | (1 &lt;&lt; 20);
  296. //delete options.fileSelect;
  297. }
  298. // 23, DoNotSpellCheck, PDF 1.4...
  299. if (options.doNotSpellCheck) {
  300. flags = flags | (1 &lt;&lt; 22);
  301. //delete options.doNotSpellCheck;
  302. }
  303. // 24, DoNotScroll, PDF 1.4...
  304. if (options.doNotScroll) {
  305. flags = flags | (1 &lt;&lt; 23);
  306. //delete options.doNotScroll;
  307. }
  308. options.Ff = options.Ff || flags;
  309. // Add field
  310. putForm.call(this, options);
  311. };
  312. var addChoiceField = function (opt) {
  313. var options = opt || new AcroForm.Field();
  314. options.FT = '/Ch';
  315. /**
  316. * Calculating the Ff entry:
  317. *
  318. * The Ff entry contains flags, that have to be set bitwise
  319. * In the Following the number in the Comment is the BitPosition
  320. */
  321. var flags = options.Ff || 0;
  322. // 18, Combo (If not set, the choiceField is a listBox!!)
  323. if (options.combo) {
  324. // Set Flag
  325. flags = AcroForm.internal.setBitPosition(flags, 18);
  326. // Remove combo from FieldObject
  327. delete options.combo;
  328. }
  329. // 19, Edit
  330. if (options.edit) {
  331. flags = AcroForm.internal.setBitPosition(flags, 19);
  332. delete options.edit;
  333. }
  334. // 20, Sort
  335. if (options.sort) {
  336. flags = AcroForm.internal.setBitPosition(flags, 20);
  337. delete options.sort;
  338. }
  339. // 22, MultiSelect (PDF 1.4)
  340. if (options.multiSelect &amp;&amp; this.internal.getPDFVersion() >= 1.4) {
  341. flags = AcroForm.internal.setBitPosition(flags, 22);
  342. delete options.multiSelect;
  343. }
  344. // 23, DoNotSpellCheck (PDF 1.4)
  345. if (options.doNotSpellCheck &amp;&amp; this.internal.getPDFVersion() >= 1.4) {
  346. flags = AcroForm.internal.setBitPosition(flags, 23);
  347. delete options.doNotSpellCheck;
  348. }
  349. options.Ff = flags;
  350. //options.hasAnnotation = true;
  351. // Add field
  352. putForm.call(this, options);
  353. };
  354. })(jsPDF.API);
  355. var AcroForm = window.AcroForm;
  356. AcroForm.internal = {};
  357. AcroForm.createFormXObject = function (formObject) {
  358. var xobj = new AcroForm.FormXObject;
  359. var height = AcroForm.Appearance.internal.getHeight(formObject) || 0;
  360. var width = AcroForm.Appearance.internal.getWidth(formObject) || 0;
  361. xobj.BBox = [0, 0, width, height];
  362. return xobj;
  363. };
  364. // Contains Methods for creating standard appearances
  365. AcroForm.Appearance = {
  366. CheckBox: {
  367. createAppearanceStream: function () {
  368. var appearance = {
  369. N: {
  370. On: AcroForm.Appearance.CheckBox.YesNormal
  371. },
  372. D: {
  373. On: AcroForm.Appearance.CheckBox.YesPushDown,
  374. Off: AcroForm.Appearance.CheckBox.OffPushDown
  375. }
  376. };
  377. return appearance;
  378. },
  379. /**
  380. * If any other icons are needed, the number between the brackets can be changed
  381. * @returns {string}
  382. */
  383. createMK: function () {
  384. // 3-> Hook
  385. return "&lt;&lt; /CA (3)>>";
  386. },
  387. /**
  388. * Returns the standard On Appearance for a CheckBox
  389. * @returns {AcroForm.FormXObject}
  390. */
  391. YesPushDown: function (formObject) {
  392. var xobj = AcroForm.createFormXObject(formObject);
  393. var stream = "";
  394. // F13 is ZapfDingbats (Symbolic)
  395. formObject.Q = 1; // set text-alignment as centered
  396. var calcRes = AcroForm.internal.calculateX(formObject, "3", "ZapfDingbats", 50);
  397. stream += "0.749023 g\n\
  398. 0 0 " + AcroForm.Appearance.internal.getWidth(formObject) + " " + AcroForm.Appearance.internal.getHeight(formObject) + " re\n\
  399. f\n\
  400. BMC\n\
  401. q\n\
  402. 0 0 1 rg\n\
  403. /F13 " + calcRes.fontSize + " Tf 0 g\n\
  404. BT\n";
  405. stream += calcRes.text;
  406. stream += "ET\n\
  407. Q\n\
  408. EMC\n";
  409. xobj.stream = stream;
  410. return xobj;
  411. },
  412. YesNormal: function (formObject) {
  413. var xobj = AcroForm.createFormXObject(formObject);
  414. var stream = "";
  415. formObject.Q = 1; // set text-alignment as centered
  416. var calcRes = AcroForm.internal.calculateX(formObject, "3", "ZapfDingbats", AcroForm.Appearance.internal.getHeight(formObject) * 0.9);
  417. stream += "1 g\n\
  418. 0 0 " + AcroForm.Appearance.internal.getWidth(formObject) + " " + AcroForm.Appearance.internal.getHeight(formObject) + " re\n\
  419. f\n\
  420. q\n\
  421. 0 0 1 rg\n\
  422. 0 0 " + (AcroForm.Appearance.internal.getWidth(formObject) - 1) + " " + (AcroForm.Appearance.internal.getHeight(formObject) - 1) + " re\n\
  423. W\n\
  424. n\n\
  425. 0 g\n\
  426. BT\n\
  427. /F13 " + calcRes.fontSize + " Tf 0 g\n";
  428. stream += calcRes.text;
  429. stream += "ET\n\
  430. Q\n";
  431. xobj.stream = stream;
  432. return xobj;
  433. },
  434. /**
  435. * Returns the standard Off Appearance for a CheckBox
  436. * @returns {AcroForm.FormXObject}
  437. */
  438. OffPushDown: function (formObject) {
  439. var xobj = AcroForm.createFormXObject(formObject);
  440. var stream = "";
  441. stream += "0.749023 g\n\
  442. 0 0 " + AcroForm.Appearance.internal.getWidth(formObject) + " " + AcroForm.Appearance.internal.getHeight(formObject) + " re\n\
  443. f\n";
  444. xobj.stream = stream;
  445. return xobj;
  446. }
  447. },
  448. RadioButton: {
  449. Circle: {
  450. createAppearanceStream: function (name) {
  451. var appearanceStreamContent = {
  452. D: {
  453. 'Off': AcroForm.Appearance.RadioButton.Circle.OffPushDown
  454. },
  455. N: {}
  456. };
  457. appearanceStreamContent.N[name] = AcroForm.Appearance.RadioButton.Circle.YesNormal;
  458. appearanceStreamContent.D[name] = AcroForm.Appearance.RadioButton.Circle.YesPushDown;
  459. return appearanceStreamContent;
  460. },
  461. createMK: function () {
  462. return "&lt;&lt; /CA (l)>>";
  463. },
  464. YesNormal: function (formObject) {
  465. var xobj = AcroForm.createFormXObject(formObject);
  466. var stream = "";
  467. // Make the Radius of the Circle relative to min(height, width) of formObject
  468. var DotRadius = (AcroForm.Appearance.internal.getWidth(formObject) &lt;= AcroForm.Appearance.internal.getHeight(formObject)) ?
  469. AcroForm.Appearance.internal.getWidth(formObject) / 4 : AcroForm.Appearance.internal.getHeight(formObject) / 4;
  470. // The Borderpadding...
  471. DotRadius *= 0.9;
  472. var c = AcroForm.Appearance.internal.Bezier_C;
  473. /*
  474. The Following is a Circle created with Bezier-Curves.
  475. */
  476. stream += "q\n\
  477. 1 0 0 1 " + AcroForm.Appearance.internal.getWidth(formObject) / 2 + " " + AcroForm.Appearance.internal.getHeight(formObject) / 2 + " cm\n\
  478. " + DotRadius + " 0 m\n\
  479. " + DotRadius + " " + DotRadius * c + " " + DotRadius * c + " " + DotRadius + " 0 " + DotRadius + " c\n\
  480. -" + DotRadius * c + " " + DotRadius + " -" + DotRadius + " " + DotRadius * c + " -" + DotRadius + " 0 c\n\
  481. -" + DotRadius + " -" + DotRadius * c + " -" + DotRadius * c + " -" + DotRadius + " 0 -" + DotRadius + " c\n\
  482. " + DotRadius * c + " -" + DotRadius + " " + DotRadius + " -" + DotRadius * c + " " + DotRadius + " 0 c\n\
  483. f\n\
  484. Q\n";
  485. xobj.stream = stream;
  486. return xobj;
  487. },
  488. YesPushDown: function (formObject) {
  489. var xobj = AcroForm.createFormXObject(formObject);
  490. var stream = "";
  491. var DotRadius = (AcroForm.Appearance.internal.getWidth(formObject) &lt;= AcroForm.Appearance.internal.getHeight(formObject)) ?
  492. AcroForm.Appearance.internal.getWidth(formObject) / 4 : AcroForm.Appearance.internal.getHeight(formObject) / 4;
  493. // The Borderpadding...
  494. DotRadius *= 0.9;
  495. // Save results for later use; no need to waste processor ticks on doing math
  496. var k = DotRadius * 2;
  497. // var c = AcroForm.Appearance.internal.Bezier_C;
  498. var kc = k * AcroForm.Appearance.internal.Bezier_C;
  499. var dc = DotRadius * AcroForm.Appearance.internal.Bezier_C;
  500. // stream += "0.749023 g\n\
  501. // q\n\
  502. // 1 0 0 1 " + AcroForm.Appearance.internal.getWidth(formObject) / 2 + " " + AcroForm.Appearance.internal.getHeight(formObject) / 2 + " cm\n\
  503. // " + DotRadius * 2 + " 0 m\n\
  504. // " + DotRadius * 2 + " " + DotRadius * 2 * c + " " + DotRadius * 2 * c + " " + DotRadius * 2 + " 0 " + DotRadius * 2 + " c\n\
  505. // -" + DotRadius * 2 * c + " " + DotRadius * 2 + " -" + DotRadius * 2 + " " + DotRadius * 2 * c + " -" + DotRadius * 2 + " 0 c\n\
  506. // -" + DotRadius * 2 + " -" + DotRadius * 2 * c + " -" + DotRadius * 2 * c + " -" + DotRadius * 2 + " 0 -" + DotRadius * 2 + " c\n\
  507. // " + DotRadius * 2 * c + " -" + DotRadius * 2 + " " + DotRadius * 2 + " -" + DotRadius * 2 * c + " " + DotRadius * 2 + " 0 c\n\
  508. // f\n\
  509. // Q\n\
  510. // 0 g\n\
  511. // q\n\
  512. // 1 0 0 1 " + AcroForm.Appearance.internal.getWidth(formObject) / 2 + " " + AcroForm.Appearance.internal.getHeight(formObject) / 2 + " cm\n\
  513. // " + DotRadius + " 0 m\n\
  514. // " + DotRadius + " " + DotRadius * c + " " + DotRadius * c + " " + DotRadius + " 0 " + DotRadius + " c\n\
  515. // -" + DotRadius * c + " " + DotRadius + " -" + DotRadius + " " + DotRadius * c + " -" + DotRadius + " 0 c\n\
  516. // -" + DotRadius + " -" + DotRadius * c + " -" + DotRadius * c + " -" + DotRadius + " 0 -" + DotRadius + " c\n\
  517. // " + DotRadius * c + " -" + DotRadius + " " + DotRadius + " -" + DotRadius * c + " " + DotRadius + " 0 c\n\
  518. // f\n\
  519. // Q\n";
  520. // FASTER VERSION with less processor ticks spent on math operations
  521. stream += "0.749023 g\n\
  522. q\n\
  523. 1 0 0 1 " + AcroForm.Appearance.internal.getWidth(formObject) / 2 + " " + AcroForm.Appearance.internal.getHeight(formObject) / 2 + " cm\n\
  524. " + k + " 0 m\n\
  525. " + k + " " + kc + " " + kc + " " + k + " 0 " + k + " c\n\
  526. -" + kc + " " + k + " -" + k + " " + kc + " -" + k + " 0 c\n\
  527. -" + k + " -" + kc + " -" + kc + " -" + k + " 0 -" + k + " c\n\
  528. " + kc + " -" + k + " " + k + " -" + kc + " " + k + " 0 c\n\
  529. f\n\
  530. Q\n\
  531. 0 g\n\
  532. q\n\
  533. 1 0 0 1 " + AcroForm.Appearance.internal.getWidth(formObject) / 2 + " " + AcroForm.Appearance.internal.getHeight(formObject) / 2 + " cm\n\
  534. " + DotRadius + " 0 m\n\
  535. " + DotRadius + " " + dc + " " + dc + " " + DotRadius + " 0 " + DotRadius + " c\n\
  536. -" + dc + " " + DotRadius + " -" + DotRadius + " " + dc + " -" + DotRadius + " 0 c\n\
  537. -" + DotRadius + " -" + dc + " -" + dc + " -" + DotRadius + " 0 -" + DotRadius + " c\n\
  538. " + dc + " -" + DotRadius + " " + DotRadius + " -" + dc + " " + DotRadius + " 0 c\n\
  539. f\n\
  540. Q\n";
  541. xobj.stream = stream;
  542. return xobj;
  543. },
  544. OffPushDown: function (formObject) {
  545. var xobj = AcroForm.createFormXObject(formObject);
  546. var stream = "";
  547. var DotRadius = (AcroForm.Appearance.internal.getWidth(formObject) &lt;= AcroForm.Appearance.internal.getHeight(formObject)) ?
  548. AcroForm.Appearance.internal.getWidth(formObject) / 4 : AcroForm.Appearance.internal.getHeight(formObject) / 4;
  549. // The Borderpadding...
  550. DotRadius *= 0.9;
  551. // Save results for later use; no need to waste processor ticks on doing math
  552. var k = DotRadius * 2;
  553. // var c = AcroForm.Appearance.internal.Bezier_C;
  554. var kc = k * AcroForm.Appearance.internal.Bezier_C;
  555. // stream += "0.749023 g\n\
  556. // q\n\
  557. // 1 0 0 1 " + AcroForm.Appearance.internal.getWidth(formObject) / 2 + " " + AcroForm.Appearance.internal.getHeight(formObject) / 2 + " cm\n\
  558. // " + DotRadius * 2 + " 0 m\n\
  559. // " + DotRadius * 2 + " " + DotRadius * 2 * c + " " + DotRadius * 2 * c + " " + DotRadius * 2 + " 0 " + DotRadius * 2 + " c\n\
  560. // -" + DotRadius * 2 * c + " " + DotRadius * 2 + " -" + DotRadius * 2 + " " + DotRadius * 2 * c + " -" + DotRadius * 2 + " 0 c\n\
  561. // -" + DotRadius * 2 + " -" + DotRadius * 2 * c + " -" + DotRadius * 2 * c + " -" + DotRadius * 2 + " 0 -" + DotRadius * 2 + " c\n\
  562. // " + DotRadius * 2 * c + " -" + DotRadius * 2 + " " + DotRadius * 2 + " -" + DotRadius * 2 * c + " " + DotRadius * 2 + " 0 c\n\
  563. // f\n\
  564. // Q\n";
  565. // FASTER VERSION with less processor ticks spent on math operations
  566. stream += "0.749023 g\n\
  567. q\n\
  568. 1 0 0 1 " + AcroForm.Appearance.internal.getWidth(formObject) / 2 + " " + AcroForm.Appearance.internal.getHeight(formObject) / 2 + " cm\n\
  569. " + k + " 0 m\n\
  570. " + k + " " + kc + " " + kc + " " + k + " 0 " + k + " c\n\
  571. -" + kc + " " + k + " -" + k + " " + kc + " -" + k + " 0 c\n\
  572. -" + k + " -" + kc + " -" + kc + " -" + k + " 0 -" + k + " c\n\
  573. " + kc + " -" + k + " " + k + " -" + kc + " " + k + " 0 c\n\
  574. f\n\
  575. Q\n";
  576. xobj.stream = stream;
  577. return xobj;
  578. },
  579. },
  580. Cross: {
  581. /**
  582. * Creates the Actual AppearanceDictionary-References
  583. * @param name
  584. * @returns
  585. */
  586. createAppearanceStream: function (name) {
  587. var appearanceStreamContent = {
  588. D: {
  589. 'Off': AcroForm.Appearance.RadioButton.Cross.OffPushDown
  590. },
  591. N: {}
  592. };
  593. appearanceStreamContent.N[name] = AcroForm.Appearance.RadioButton.Cross.YesNormal;
  594. appearanceStreamContent.D[name] = AcroForm.Appearance.RadioButton.Cross.YesPushDown;
  595. return appearanceStreamContent;
  596. },
  597. createMK: function () {
  598. return "&lt;&lt; /CA (8)>>";
  599. },
  600. YesNormal: function (formObject) {
  601. var xobj = AcroForm.createFormXObject(formObject);
  602. var stream = "";
  603. var cross = AcroForm.Appearance.internal.calculateCross(formObject);
  604. stream += "q\n\
  605. 1 1 " + (AcroForm.Appearance.internal.getWidth(formObject) - 2) + " " + (AcroForm.Appearance.internal.getHeight(formObject) - 2) + " re\n\
  606. W\n\
  607. n\n\
  608. " + cross.x1.x + " " + cross.x1.y + " m\n\
  609. " + cross.x2.x + " " + cross.x2.y + " l\n\
  610. " + cross.x4.x + " " + cross.x4.y + " m\n\
  611. " + cross.x3.x + " " + cross.x3.y + " l\n\
  612. s\n\
  613. Q\n";
  614. xobj.stream = stream;
  615. return xobj;
  616. },
  617. YesPushDown: function (formObject) {
  618. var xobj = AcroForm.createFormXObject(formObject);
  619. var cross = AcroForm.Appearance.internal.calculateCross(formObject);
  620. var stream = "";
  621. stream += "0.749023 g\n\
  622. 0 0 " + AcroForm.Appearance.internal.getWidth(formObject) + " " + AcroForm.Appearance.internal.getHeight(formObject) + " re\n\
  623. f\n\
  624. q\n\
  625. 1 1 " + (AcroForm.Appearance.internal.getWidth(formObject) - 2) + " " + (AcroForm.Appearance.internal.getHeight(formObject) - 2) + " re\n\
  626. W\n\
  627. n\n\
  628. " + cross.x1.x + " " + cross.x1.y + " m\n\
  629. " + cross.x2.x + " " + cross.x2.y + " l\n\
  630. " + cross.x4.x + " " + cross.x4.y + " m\n\
  631. " + cross.x3.x + " " + cross.x3.y + " l\n\
  632. s\n\
  633. Q\n";
  634. xobj.stream = stream;
  635. return xobj;
  636. },
  637. OffPushDown: function (formObject) {
  638. var xobj = AcroForm.createFormXObject(formObject);
  639. var stream = "";
  640. stream += "0.749023 g\n\
  641. 0 0 " + AcroForm.Appearance.internal.getWidth(formObject) + " " + AcroForm.Appearance.internal.getHeight(formObject) + " re\n\
  642. f\n";
  643. xobj.stream = stream;
  644. return xobj;
  645. }
  646. },
  647. },
  648. /**
  649. * Returns the standard Appearance
  650. * @returns {AcroForm.FormXObject}
  651. */
  652. createDefaultAppearanceStream: function (formObject) {
  653. var stream = "";
  654. // Set Helvetica to Standard Font (size: auto)
  655. // Color: Black
  656. stream += "/Helv 0 Tf 0 g";
  657. return stream;
  658. }
  659. };
  660. AcroForm.Appearance.internal = {
  661. Bezier_C: 0.551915024494,
  662. calculateCross: function (formObject) {
  663. var min = function (x, y) {
  664. return (x > y) ? y : x;
  665. };
  666. var width = AcroForm.Appearance.internal.getWidth(formObject);
  667. var height = AcroForm.Appearance.internal.getHeight(formObject);
  668. var a = min(width, height);
  669. var crossSize = a;
  670. var borderPadding = 2; // The Padding in px
  671. var cross = {
  672. x1: { // upperLeft
  673. x: (width - a) / 2,
  674. y: ((height - a) / 2) + a,//height - borderPadding
  675. },
  676. x2: { // lowerRight
  677. x: ((width - a) / 2) + a,
  678. y: ((height - a) / 2)//borderPadding
  679. },
  680. x3: { // lowerLeft
  681. x: (width - a) / 2,
  682. y: ((height - a) / 2)//borderPadding
  683. },
  684. x4: { // upperRight
  685. x: ((width - a) / 2) + a,
  686. y: ((height - a) / 2) + a,//height - borderPadding
  687. }
  688. };
  689. return cross;
  690. },
  691. };
  692. AcroForm.Appearance.internal.getWidth = function (formObject) {
  693. return formObject.Rect[2];//(formObject.Rect[2] - formObject.Rect[0]) || 0;
  694. };
  695. AcroForm.Appearance.internal.getHeight = function (formObject) {
  696. return formObject.Rect[3];//(formObject.Rect[1] - formObject.Rect[3]) || 0;
  697. };
  698. // ##########################
  699. //### For inheritance:
  700. AcroForm.internal.inherit = function (child, parent) {
  701. var ObjectCreate = Object.create || function (o) {
  702. var F = function () {
  703. };
  704. F.prototype = o;
  705. return new F();
  706. };
  707. child.prototype = Object.create(parent.prototype);
  708. child.prototype.constructor = child;
  709. };
  710. // ### Handy Functions:
  711. AcroForm.internal.arrayToPdfArray = function (array) {
  712. if (Array.isArray(array)) {
  713. var content = ' [';
  714. for (var i in array) {
  715. var element = array[i].toString();
  716. content += element;
  717. content += ((i &lt; array.length - 1) ? ' ' : '');
  718. }
  719. content += ']';
  720. return content;
  721. }
  722. };
  723. AcroForm.internal.toPdfString = function (string) {
  724. string = string || "";
  725. // put Bracket at the Beginning of the String
  726. if (string.indexOf('(') !== 0) {
  727. string = '(' + string;
  728. }
  729. if (string.substring(string.length - 1) != ')') {
  730. string += '(';
  731. }
  732. return string;
  733. };
  734. // ##########################
  735. // Classes
  736. // ##########################
  737. AcroForm.PDFObject = function () {
  738. // The Object ID in the PDF Object Model
  739. // todo
  740. var _objId;
  741. Object.defineProperty(this, 'objId', {
  742. get: function () {
  743. if (!_objId) {
  744. if (this.internal) {
  745. _objId = this.internal.newObjectDeferred();
  746. } else if (jsPDF.API.acroformPlugin.internal) {
  747. // todo - find better option, that doesn't rely on a Global Static var
  748. _objId = jsPDF.API.acroformPlugin.internal.newObjectDeferred();
  749. }
  750. }
  751. if (!_objId) {
  752. console.log("Couldn't create Object ID");
  753. }
  754. return _objId
  755. },
  756. configurable: false
  757. });
  758. };
  759. AcroForm.PDFObject.prototype.toString = function () {
  760. return this.objId + " 0 R";
  761. };
  762. AcroForm.PDFObject.prototype.getString = function () {
  763. var res = this.objId + " 0 obj\n&lt;&lt;";
  764. var content = this.getContent();
  765. res += content + ">>\n";
  766. if (this.stream) {
  767. res += "stream\n";
  768. res += this.stream;
  769. res += "endstream\n";
  770. }
  771. res += "endobj\n";
  772. return res;
  773. };
  774. AcroForm.PDFObject.prototype.getContent = function () {
  775. /**
  776. * Prints out all enumerable Variables from the Object
  777. * @param fieldObject
  778. * @returns {string}
  779. */
  780. var createContentFromFieldObject = function (fieldObject) {
  781. var content = '';
  782. var keys = Object.keys(fieldObject).filter(function (key) {
  783. return (key != 'content' &amp;&amp; key != 'appearanceStreamContent' &amp;&amp; key.substring(0, 1) != "_");
  784. });
  785. for (var i in keys) {
  786. var key = keys[i];
  787. var value = fieldObject[key];
  788. /*if (key == 'Rect' &amp;&amp; value) {
  789. value = AcroForm.internal.calculateCoordinates.call(jsPDF.API.acroformPlugin.internal, value);
  790. }*/
  791. if (value) {
  792. if (Array.isArray(value)) {
  793. content += '/' + key + ' ' + AcroForm.internal.arrayToPdfArray(value) + "\n";
  794. } else if (value instanceof AcroForm.PDFObject) {
  795. // In case it is a reference to another PDFObject, take the referennce number
  796. content += '/' + key + ' ' + value.objId + " 0 R" + "\n";
  797. } else {
  798. content += '/' + key + ' ' + value + '\n';
  799. }
  800. }
  801. }
  802. return content;
  803. };
  804. var object = "";
  805. object += createContentFromFieldObject(this);
  806. return object;
  807. };
  808. AcroForm.FormXObject = function () {
  809. AcroForm.PDFObject.call(this);
  810. this.Type = "/XObject";
  811. this.Subtype = "/Form";
  812. this.FormType = 1;
  813. this.BBox;
  814. this.Matrix;
  815. this.Resources = "2 0 R";
  816. this.PieceInfo;
  817. var _stream;
  818. Object.defineProperty(this, 'Length', {
  819. enumerable: true,
  820. get: function () {
  821. return (_stream !== undefined) ? _stream.length : 0;
  822. }
  823. });
  824. Object.defineProperty(this, 'stream', {
  825. enumerable: false,
  826. set: function (val) {
  827. _stream = val;
  828. },
  829. get: function () {
  830. if (_stream) {
  831. return _stream;
  832. } else {
  833. return null;
  834. }
  835. }
  836. });
  837. };
  838. AcroForm.internal.inherit(AcroForm.FormXObject, AcroForm.PDFObject);
  839. AcroForm.AcroFormDictionary = function () {
  840. AcroForm.PDFObject.call(this);
  841. var _Kids = [];
  842. Object.defineProperty(this, 'Kids', {
  843. enumerable: false,
  844. configurable: true,
  845. get: function () {
  846. if (_Kids.length > 0) {
  847. return _Kids;
  848. } else {
  849. return;
  850. }
  851. }
  852. });
  853. Object.defineProperty(this, 'Fields', {
  854. enumerable: true,
  855. configurable: true,
  856. get: function () {
  857. return _Kids;
  858. }
  859. });
  860. // Default Appearance
  861. this.DA;
  862. };
  863. AcroForm.internal.inherit(AcroForm.AcroFormDictionary, AcroForm.PDFObject);
  864. // ##### The Objects, the User can Create:
  865. // The Field Object contains the Variables, that every Field needs
  866. // Rectangle for Appearance: lower_left_X, lower_left_Y, width, height
  867. AcroForm.Field = function () {
  868. 'use strict';
  869. AcroForm.PDFObject.call(this);
  870. var _Rect;
  871. Object.defineProperty(this, 'Rect', {
  872. enumerable: true,
  873. configurable: false,
  874. get: function () {
  875. if (!_Rect) {
  876. return;
  877. }
  878. var tmp = _Rect;
  879. //var calculatedRes = AcroForm.internal.calculateCoordinates(_Rect); // do later!
  880. return tmp
  881. },
  882. set: function (val) {
  883. _Rect = val;
  884. }
  885. });
  886. var _FT = "";
  887. Object.defineProperty(this, 'FT', {
  888. enumerable: true,
  889. set: function (val) {
  890. _FT = val
  891. },
  892. get: function () {
  893. return _FT
  894. }
  895. });
  896. /**
  897. * The Partial name of the Field Object.
  898. * It has to be unique.
  899. */
  900. var _T;
  901. Object.defineProperty(this, 'T', {
  902. enumerable: true,
  903. configurable: false,
  904. set: function (val) {
  905. _T = val;
  906. },
  907. get: function () {
  908. if (!_T || _T.length &lt; 1) {
  909. if (this instanceof AcroForm.ChildClass) {
  910. // In case of a Child from a Radio´Group, you don't need a FieldName!!!
  911. return;
  912. }
  913. return "(FieldObject" + (AcroForm.Field.FieldNum++) + ")";
  914. }
  915. if (_T.substring(0, 1) == "(" &amp;&amp; _T.substring(_T.length - 1)) {
  916. return _T;
  917. }
  918. return "(" + _T + ")";
  919. }
  920. });
  921. var _DA;
  922. // Defines the default appearance (Needed for variable Text)
  923. Object.defineProperty(this, 'DA', {
  924. enumerable: true,
  925. get: function () {
  926. if (!_DA) {
  927. return;
  928. }
  929. return '(' + _DA + ')'
  930. },
  931. set: function (val) {
  932. _DA = val
  933. }
  934. });
  935. var _DV;
  936. // Defines the default value
  937. Object.defineProperty(this, 'DV', {
  938. enumerable: true,
  939. configurable: true,
  940. get: function () {
  941. if (!_DV) {
  942. return;
  943. }
  944. return _DV
  945. },
  946. set: function (val) {
  947. _DV = val
  948. }
  949. });
  950. //this.Type = "/Annot";
  951. //this.Subtype = "/Widget";
  952. Object.defineProperty(this, 'Type', {
  953. enumerable: true,
  954. get: function () {
  955. return (this.hasAnnotation) ? "/Annot" : null;
  956. }
  957. });
  958. Object.defineProperty(this, 'Subtype', {
  959. enumerable: true,
  960. get: function () {
  961. return (this.hasAnnotation) ? "/Widget" : null;
  962. }
  963. });
  964. /**
  965. *
  966. * @type {Array}
  967. */
  968. this.BG;
  969. Object.defineProperty(this, 'hasAnnotation', {
  970. enumerable: false,
  971. get: function () {
  972. if (this.Rect || this.BC || this.BG) {
  973. return true
  974. }
  975. return false;
  976. }
  977. });
  978. Object.defineProperty(this, 'hasAppearanceStream', {
  979. enumerable: false,
  980. configurable: true,
  981. writable: true
  982. });
  983. Object.defineProperty(this, 'page', {
  984. enumerable: false,
  985. configurable: true,
  986. writable: true
  987. });
  988. };
  989. AcroForm.Field.FieldNum = 0;
  990. AcroForm.internal.inherit(AcroForm.Field, AcroForm.PDFObject);
  991. AcroForm.ChoiceField = function () {
  992. AcroForm.Field.call(this);
  993. // Field Type = Choice Field
  994. this.FT = "/Ch";
  995. // options
  996. this.Opt = [];
  997. this.V = '()';
  998. // Top Index
  999. this.TI = 0;
  1000. /**
  1001. * Defines, whether the
  1002. * @type {boolean}
  1003. */
  1004. this.combo = false;
  1005. /**
  1006. * Defines, whether the Choice Field is an Edit Field.
  1007. * An Edit Field is automatically an Combo Field.
  1008. */
  1009. Object.defineProperty(this, 'edit', {
  1010. enumerable: true,
  1011. set: function (val) {
  1012. if (val == true) {
  1013. this._edit = true;
  1014. // ComboBox has to be true
  1015. this.combo = true;
  1016. } else {
  1017. this._edit = false;
  1018. }
  1019. },
  1020. get: function () {
  1021. if (!this._edit) {
  1022. return false;
  1023. }
  1024. return this._edit;
  1025. },
  1026. configurable: false
  1027. });
  1028. this.hasAppearanceStream = true;
  1029. Object.defineProperty(this, 'V', {
  1030. get: function() {
  1031. AcroForm.internal.toPdfString();
  1032. }
  1033. });
  1034. };
  1035. AcroForm.internal.inherit(AcroForm.ChoiceField, AcroForm.Field);
  1036. window["ChoiceField"] = AcroForm.ChoiceField;
  1037. AcroForm.ListBox = function () {
  1038. AcroForm.ChoiceField.call(this);
  1039. //var combo = true;
  1040. };
  1041. AcroForm.internal.inherit(AcroForm.ListBox, AcroForm.ChoiceField);
  1042. window["ListBox"] = AcroForm.ListBox;
  1043. AcroForm.ComboBox = function () {
  1044. AcroForm.ListBox.call(this);
  1045. this.combo = true;
  1046. };
  1047. AcroForm.internal.inherit(AcroForm.ComboBox, AcroForm.ListBox);
  1048. window["ComboBox"] = AcroForm.ComboBox;
  1049. AcroForm.EditBox = function () {
  1050. AcroForm.ComboBox.call(this);
  1051. this.edit = true;
  1052. };
  1053. AcroForm.internal.inherit(AcroForm.EditBox, AcroForm.ComboBox);
  1054. window["EditBox"] = AcroForm.EditBox;
  1055. AcroForm.Button = function () {
  1056. AcroForm.Field.call(this);
  1057. this.FT = "/Btn";
  1058. //this.hasAnnotation = true;
  1059. };
  1060. AcroForm.internal.inherit(AcroForm.Button, AcroForm.Field);
  1061. window["Button"] = AcroForm.Button;
  1062. AcroForm.PushButton = function () {
  1063. AcroForm.Button.call(this);
  1064. this.pushbutton = true;
  1065. };
  1066. AcroForm.internal.inherit(AcroForm.PushButton, AcroForm.Button);
  1067. window["PushButton"] = AcroForm.PushButton;
  1068. AcroForm.RadioButton = function () {
  1069. AcroForm.Button.call(this);
  1070. this.radio = true;
  1071. var _Kids = [];
  1072. Object.defineProperty(this, 'Kids', {
  1073. enumerable: true,
  1074. get: function () {
  1075. if (_Kids.length > 0) {
  1076. return _Kids;
  1077. }
  1078. }
  1079. });
  1080. Object.defineProperty(this, '__Kids', {
  1081. get: function () {
  1082. return _Kids;
  1083. }
  1084. });
  1085. var _noToggleToOff;
  1086. Object.defineProperty(this, 'noToggleToOff', {
  1087. enumerable: false,
  1088. get: function () {
  1089. return _noToggleToOff
  1090. },
  1091. set: function (val) {
  1092. _noToggleToOff = val
  1093. }
  1094. });
  1095. //this.hasAnnotation = false;
  1096. };
  1097. AcroForm.internal.inherit(AcroForm.RadioButton, AcroForm.Button);
  1098. window["RadioButton"] = AcroForm.RadioButton;
  1099. /*
  1100. * The Child classs of a RadioButton (the radioGroup)
  1101. * -> The single Buttons
  1102. */
  1103. AcroForm.ChildClass = function (parent, name) {
  1104. AcroForm.Field.call(this);
  1105. this.Parent = parent;
  1106. // todo: set AppearanceType as variable that can be set from the outside...
  1107. this._AppearanceType = AcroForm.Appearance.RadioButton.Circle; // The Default appearanceType is the Circle
  1108. this.appearanceStreamContent = this._AppearanceType.createAppearanceStream(name);
  1109. // Set Print in the Annot Flag
  1110. this.F = AcroForm.internal.setBitPosition(this.F, 3, 1);
  1111. // Set AppearanceCharacteristicsDictionary with default appearance if field is not interacting with user
  1112. this.MK = this._AppearanceType.createMK(); // (8) -> Cross, (1)-> Circle, ()-> nothing
  1113. // Default Appearance is Off
  1114. this.AS = "/Off";// + name;
  1115. this._Name = name;
  1116. };
  1117. AcroForm.internal.inherit(AcroForm.ChildClass, AcroForm.Field);
  1118. AcroForm.RadioButton.prototype.setAppearance = function (appearance) {
  1119. if (!('createAppearanceStream' in appearance &amp;&amp; 'createMK' in appearance)) {
  1120. console.log("Couldn't assign Appearance to RadioButton. Appearance was Invalid!");
  1121. return;
  1122. }
  1123. for (var i in this.__Kids) {
  1124. var child = this.__Kids[i];
  1125. child.appearanceStreamContent = appearance.createAppearanceStream(child._Name);
  1126. child.MK = appearance.createMK();
  1127. }
  1128. };
  1129. AcroForm.RadioButton.prototype.createOption = function (name) {
  1130. var parent = this;
  1131. var kidCount = this.__Kids.length;
  1132. // Create new Child for RadioGroup
  1133. var child = new AcroForm.ChildClass(parent, name);
  1134. // Add to Parent
  1135. this.__Kids.push(child);
  1136. jsPDF.API.addField(child);
  1137. return child;
  1138. };
  1139. AcroForm.CheckBox = function () {
  1140. Button.call(this);
  1141. this.appearanceStreamContent = AcroForm.Appearance.CheckBox.createAppearanceStream();
  1142. this.MK = AcroForm.Appearance.CheckBox.createMK();
  1143. this.AS = "/On";
  1144. this.V = "/On";
  1145. };
  1146. AcroForm.internal.inherit(AcroForm.CheckBox, AcroForm.Button);
  1147. window["CheckBox"] = AcroForm.CheckBox;
  1148. AcroForm.TextField = function () {
  1149. AcroForm.Field.call(this);
  1150. this.DA = AcroForm.Appearance.createDefaultAppearanceStream();
  1151. this.F = 4;
  1152. var _V;
  1153. Object.defineProperty(this, 'V', {
  1154. get: function () {
  1155. if (_V) {
  1156. return "(" + _V + ")"
  1157. }
  1158. else {
  1159. return _V
  1160. }
  1161. },
  1162. enumerable: true,
  1163. set: function (val) {
  1164. _V = val
  1165. }
  1166. });
  1167. var _DV;
  1168. Object.defineProperty(this, 'DV', {
  1169. get: function () {
  1170. if (_DV) {
  1171. return "(" + _DV + ")"
  1172. }
  1173. else {
  1174. return _DV
  1175. }
  1176. },
  1177. enumerable: true,
  1178. set: function (val) {
  1179. _DV = val
  1180. }
  1181. });
  1182. var _multiline = false;
  1183. Object.defineProperty(this, 'multiline', {
  1184. enumerable: false,
  1185. get: function () {
  1186. return _multiline
  1187. },
  1188. set: function (val) {
  1189. _multiline = val;
  1190. }
  1191. });
  1192. //this.multiline = false;
  1193. //this.password = false;
  1194. /**
  1195. * For PDF 1.4
  1196. * @type {boolean}
  1197. */
  1198. //this.fileSelect = false;
  1199. /**
  1200. * For PDF 1.4
  1201. * @type {boolean}
  1202. */
  1203. //this.doNotSpellCheck = false;
  1204. /**
  1205. * For PDF 1.4
  1206. * @type {boolean}
  1207. */
  1208. //this.doNotScroll = false;
  1209. var _MaxLen = false;
  1210. Object.defineProperty(this, 'MaxLen', {
  1211. enumerable: true,
  1212. get: function () {
  1213. return _MaxLen;
  1214. },
  1215. set: function (val) {
  1216. _MaxLen = val;
  1217. }
  1218. });
  1219. Object.defineProperty(this, 'hasAppearanceStream', {
  1220. enumerable: false,
  1221. get: function () {
  1222. return (this.V || this.DV);
  1223. }
  1224. });
  1225. };
  1226. AcroForm.internal.inherit(AcroForm.TextField, AcroForm.Field);
  1227. window["TextField"] = AcroForm.TextField;
  1228. AcroForm.PasswordField = function () {
  1229. TextField.call(this);
  1230. Object.defineProperty(this, 'password', {
  1231. value: true,
  1232. enumerable: false,
  1233. configurable: false,
  1234. writable: false
  1235. });
  1236. };
  1237. AcroForm.internal.inherit(AcroForm.PasswordField, AcroForm.TextField);
  1238. window["PasswordField"] = AcroForm.PasswordField;
  1239. // ############ internal functions
  1240. /*
  1241. * small workaround for calculating the TextMetric approximately
  1242. * @param text
  1243. * @param fontsize
  1244. * @returns {TextMetrics} (Has Height and Width)
  1245. */
  1246. AcroForm.internal.calculateFontSpace = function (text, fontsize, fonttype) {
  1247. var fonttype = fonttype || "helvetica";
  1248. //re-use canvas object for speed improvements
  1249. var canvas = AcroForm.internal.calculateFontSpace.canvas || (AcroForm.internal.calculateFontSpace.canvas = document.createElement('canvas'));
  1250. var context = canvas.getContext('2d');
  1251. context.save();
  1252. var newFont = (fontsize + " " + fonttype);
  1253. context.font = newFont;
  1254. var res = context.measureText(text);
  1255. context.fontcolor = 'black';
  1256. // Calculate height:
  1257. var context = canvas.getContext('2d');
  1258. res.height = context.measureText("3").width * 1.5; // 3 because in ZapfDingbats its a Hook and a 3 in normal fonts
  1259. context.restore();
  1260. var width = res.width;
  1261. return res;
  1262. };
  1263. AcroForm.internal.calculateX = function (formObject, text, font, maxFontSize) {
  1264. var maxFontSize = maxFontSize || 12;
  1265. var font = font || "helvetica";
  1266. var returnValue = {
  1267. text: "",
  1268. fontSize: ""
  1269. };
  1270. // Remove Brackets
  1271. text = (text.substr(0, 1) == '(') ? text.substr(1) : text;
  1272. text = (text.substr(text.length - 1) == ')') ? text.substr(0, text.length - 1) : text;
  1273. // split into array of words
  1274. var textSplit = text.split(' ');
  1275. /**
  1276. * the color could be ((alpha)||(r,g,b)||(c,m,y,k))
  1277. * @type {string}
  1278. */
  1279. var color = "0 g\n";
  1280. var fontSize = maxFontSize; // The Starting fontSize (The Maximum)
  1281. var lineSpacing = 2;
  1282. var borderPadding = 2;
  1283. var height = AcroForm.Appearance.internal.getHeight(formObject) || 0;
  1284. height = (height &lt; 0) ? -height : height;
  1285. var width = AcroForm.Appearance.internal.getWidth(formObject) || 0;
  1286. width = (width &lt; 0) ? -width : width;
  1287. var isSmallerThanWidth = function (i, lastLine, fontSize) {
  1288. if (i + 1 &lt; textSplit.length) {
  1289. var tmp = lastLine + " " + textSplit[i + 1];
  1290. var TextWidth = ((AcroForm.internal.calculateFontSpace(tmp, fontSize + "px", font).width));
  1291. var FieldWidth = (width - 2 * borderPadding);
  1292. return (TextWidth &lt;= FieldWidth);
  1293. } else {
  1294. return false;
  1295. }
  1296. };
  1297. fontSize++;
  1298. FontSize: while (true) {
  1299. var text = "";
  1300. fontSize--;
  1301. var textHeight = AcroForm.internal.calculateFontSpace("3", fontSize + "px", font).height;
  1302. var startY = (formObject.multiline) ? height - fontSize : (height - textHeight) / 2;
  1303. startY += lineSpacing;
  1304. var startX = -borderPadding;
  1305. var lastX = startX, lastY = startY;
  1306. var firstWordInLine = 0, lastWordInLine = 0;
  1307. var lastLength = 0;
  1308. var y = 0;
  1309. if (fontSize == 0) {
  1310. // In case, the Text doesn't fit at all
  1311. fontSize = 12;
  1312. text = "(...) Tj\n";
  1313. text += "% Width of Text: " + AcroForm.internal.calculateFontSpace(text, "1px").width + ", FieldWidth:" + width + "\n";
  1314. break;
  1315. }
  1316. lastLength = AcroForm.internal.calculateFontSpace(textSplit[0] + " ", fontSize + "px", font).width;
  1317. var lastLine = "";
  1318. var lineCount = 0;
  1319. Line:
  1320. for (var i in textSplit) {
  1321. lastLine += textSplit[i] + " ";
  1322. // Remove last blank
  1323. lastLine = (lastLine.substr(lastLine.length - 1) == " ") ? lastLine.substr(0, lastLine.length - 1) : lastLine;
  1324. var key = parseInt(i);
  1325. lastLength = AcroForm.internal.calculateFontSpace(lastLine + " ", fontSize + "px", font).width;
  1326. var nextLineIsSmaller = isSmallerThanWidth(key, lastLine, fontSize);
  1327. var isLastWord = i >= textSplit.length - 1;
  1328. if (nextLineIsSmaller &amp;&amp; !isLastWord) {
  1329. lastLine += " ";
  1330. continue; // Line
  1331. } else if (!nextLineIsSmaller &amp;&amp; !isLastWord) {
  1332. if (!formObject.multiline) {
  1333. continue FontSize;
  1334. } else {
  1335. if (((textHeight + lineSpacing) * (lineCount + 2) + lineSpacing) > height) {
  1336. // If the Text is higher than the FieldObject
  1337. continue FontSize;
  1338. }
  1339. lastWordInLine = key;
  1340. // go on
  1341. }
  1342. } else if (isLastWord) {
  1343. lastWordInLine = key;
  1344. } else {
  1345. if (formObject.multiline &amp;&amp; ((textHeight + lineSpacing) * (lineCount + 2) + lineSpacing) > height) {
  1346. // If the Text is higher than the FieldObject
  1347. continue FontSize;
  1348. }
  1349. }
  1350. var line = '';
  1351. for (var x = firstWordInLine; x &lt;= lastWordInLine; x++) {
  1352. line += textSplit[x] + ' ';
  1353. }
  1354. // Remove last blank
  1355. line = (line.substr(line.length - 1) == " ") ? line.substr(0, line.length - 1) : line;
  1356. //lastLength -= blankSpace.width;
  1357. lastLength = AcroForm.internal.calculateFontSpace(line, fontSize + "px", font).width;
  1358. // Calculate startX
  1359. switch (formObject.Q) {
  1360. case 2: // Right justified
  1361. startX = (width - lastLength - borderPadding);
  1362. break;
  1363. case 1:// Q = 1 := Text-Alignment: Center
  1364. startX = (width - lastLength) / 2;
  1365. break;
  1366. case 0:
  1367. default:
  1368. startX = borderPadding;
  1369. break;
  1370. }
  1371. text += (startX) + ' ' + (lastY) + ' Td\n';
  1372. text += '(' + line + ') Tj\n';
  1373. // reset X in PDF
  1374. text += (-startX) + ' 0 Td\n';
  1375. // After a Line, adjust y position
  1376. lastY = -(fontSize + lineSpacing);
  1377. lastX = startX;
  1378. // Reset for next iteration step
  1379. lastLength = 0;
  1380. firstWordInLine = lastWordInLine + 1;
  1381. lineCount++;
  1382. lastLine = "";
  1383. continue Line;
  1384. }
  1385. break;
  1386. }
  1387. returnValue.text = text;
  1388. returnValue.fontSize = fontSize;
  1389. return returnValue;
  1390. };
  1391. AcroForm.internal.calculateAppearanceStream = function (formObject) {
  1392. if (formObject.appearanceStreamContent) {
  1393. // If appearanceStream is already set, use it
  1394. return formObject.appearanceStreamContent;
  1395. }
  1396. if (!formObject.V &amp;&amp; !formObject.DV) {
  1397. return;
  1398. }
  1399. // else calculate it
  1400. var stream = '';
  1401. var text = formObject.V || formObject.DV;
  1402. var calcRes = AcroForm.internal.calculateX(formObject, text);
  1403. stream += '/Tx BMC\n' +
  1404. 'q\n' +
  1405. //color + '\n' +
  1406. '/F1 ' + calcRes.fontSize + ' Tf\n' +
  1407. // Text Matrix
  1408. '1 0 0 1 0 0 Tm\n';
  1409. // Begin Text
  1410. stream += 'BT\n';
  1411. stream += calcRes.text;
  1412. // End Text
  1413. stream += 'ET\n';
  1414. stream += 'Q\n' +
  1415. 'EMC\n';
  1416. var appearanceStreamContent = new AcroForm.createFormXObject(formObject);
  1417. appearanceStreamContent.stream = stream;
  1418. var appearance = {
  1419. N: {
  1420. 'Normal': appearanceStreamContent
  1421. }
  1422. };
  1423. return appearanceStreamContent;
  1424. };
  1425. /*
  1426. * Converts the Parameters from x,y,w,h to lowerLeftX, lowerLeftY, upperRightX, upperRightY
  1427. * @param x
  1428. * @param y
  1429. * @param w
  1430. * @param h
  1431. * @returns {*[]}
  1432. */
  1433. AcroForm.internal.calculateCoordinates = function (x, y, w, h) {
  1434. var coordinates = {};
  1435. if (this.internal) {
  1436. function mmtopx(x) {
  1437. return (x * this.internal.scaleFactor);
  1438. }
  1439. if (Array.isArray(x)) {
  1440. x[0] = AcroForm.scale(x[0]);
  1441. x[1] = AcroForm.scale(x[1]);
  1442. x[2] = AcroForm.scale(x[2]);
  1443. x[3] = AcroForm.scale(x[3]);
  1444. coordinates.lowerLeft_X = x[0] || 0;
  1445. coordinates.lowerLeft_Y = (mmtopx.call(this, this.internal.pageSize.height) - x[3] - x[1]) || 0;
  1446. coordinates.upperRight_X = x[0] + x[2] || 0;
  1447. coordinates.upperRight_Y = (mmtopx.call(this, this.internal.pageSize.height) - x[1]) || 0;
  1448. } else {
  1449. x = AcroForm.scale(x);
  1450. y = AcroForm.scale(y);
  1451. w = AcroForm.scale(w);
  1452. h = AcroForm.scale(h);
  1453. coordinates.lowerLeft_X = x || 0;
  1454. coordinates.lowerLeft_Y = this.internal.pageSize.height - y || 0;
  1455. coordinates.upperRight_X = x + w || 0;
  1456. coordinates.upperRight_Y = this.internal.pageSize.height - y + h || 0;
  1457. }
  1458. } else {
  1459. // old method, that is fallback, if we can't get the pageheight, the coordinate-system starts from lower left
  1460. if (Array.isArray(x)) {
  1461. coordinates.lowerLeft_X = x[0] || 0;
  1462. coordinates.lowerLeft_Y = x[1] || 0;
  1463. coordinates.upperRight_X = x[0] + x[2] || 0;
  1464. coordinates.upperRight_Y = x[1] + x[3] || 0;
  1465. } else {
  1466. coordinates.lowerLeft_X = x || 0;
  1467. coordinates.lowerLeft_Y = y || 0;
  1468. coordinates.upperRight_X = x + w || 0;
  1469. coordinates.upperRight_Y = y + h || 0;
  1470. }
  1471. }
  1472. return [coordinates.lowerLeft_X, coordinates.lowerLeft_Y, coordinates.upperRight_X, coordinates.upperRight_Y];
  1473. };
  1474. AcroForm.internal.calculateColor = function (r, g, b) {
  1475. var color = new Array(3);
  1476. color.r = r | 0;
  1477. color.g = g | 0;
  1478. color.b = b | 0;
  1479. return color;
  1480. };
  1481. AcroForm.internal.getBitPosition = function (variable, position) {
  1482. variable = variable || 0;
  1483. var bitMask = 1;
  1484. bitMask = bitMask &lt;&lt; (position - 1);
  1485. return variable | bitMask;
  1486. };
  1487. AcroForm.internal.setBitPosition = function (variable, position, value) {
  1488. variable = variable || 0;
  1489. value = value || 1;
  1490. var bitMask = 1;
  1491. bitMask = bitMask &lt;&lt; (position - 1);
  1492. if (value == 1) {
  1493. // Set the Bit to 1
  1494. var variable = variable | bitMask;
  1495. } else {
  1496. // Set the Bit to 0
  1497. var variable = variable &amp; (~bitMask);
  1498. }
  1499. return variable;
  1500. };
  1501. </code></pre>
  1502. </article>
  1503. </section>
  1504. </div>
  1505. <br class="clear">
  1506. <footer>
  1507. Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.2</a> on Sun Oct 09 2016 11:08:27 GMT+0100 (BST) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
  1508. </footer>
  1509. <script>prettyPrint();</script>
  1510. <script src="scripts/linenumber.js"></script>
  1511. </body>
  1512. </html>