plugins_annotations.js.html 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="utf-8">
  5. <title>plugins/annotations.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/annotations.js</h1>
  25. <section>
  26. <article>
  27. <pre class="prettyprint source linenums"><code>/**
  28. * jsPDF Annotations PlugIn
  29. * Copyright (c) 2014 Steven Spungin (TwelveTone LLC) steven@twelvetone.tv
  30. *
  31. * Licensed under the MIT License.
  32. * http://opensource.org/licenses/mit-license
  33. */
  34. /**
  35. * There are many types of annotations in a PDF document. Annotations are placed
  36. * on a page at a particular location. They are not 'attached' to an object.
  37. * &lt;br />
  38. * This plugin current supports &lt;br />
  39. * &lt;li> Goto Page (set pageNumber and top in options)
  40. * &lt;li> Goto Name (set name and top in options)
  41. * &lt;li> Goto URL (set url in options)
  42. * &lt;p>
  43. * The destination magnification factor can also be specified when goto is a page number or a named destination. (see documentation below)
  44. * (set magFactor in options). XYZ is the default.
  45. * &lt;/p>
  46. * &lt;p>
  47. * Links, Text, Popup, and FreeText are supported.
  48. * &lt;/p>
  49. * &lt;p>
  50. * Options In PDF spec Not Implemented Yet
  51. * &lt;li> link border
  52. * &lt;li> named target
  53. * &lt;li> page coordinates
  54. * &lt;li> destination page scaling and layout
  55. * &lt;li> actions other than URL and GotoPage
  56. * &lt;li> background / hover actions
  57. * &lt;/p>
  58. */
  59. /*
  60. Destination Magnification Factors
  61. See PDF 1.3 Page 386 for meanings and options
  62. [supported]
  63. XYZ (options; left top zoom)
  64. Fit (no options)
  65. FitH (options: top)
  66. FitV (options: left)
  67. [not supported]
  68. FitR
  69. FitB
  70. FitBH
  71. FitBV
  72. */
  73. (function(jsPDFAPI) {
  74. 'use strict';
  75. var annotationPlugin = {
  76. /**
  77. * An array of arrays, indexed by &lt;em>pageNumber&lt;/em>.
  78. */
  79. annotations : [],
  80. f2 : function(number) {
  81. return number.toFixed(2);
  82. },
  83. notEmpty : function(obj) {
  84. if (typeof obj != 'undefined') {
  85. if (obj != '') {
  86. return true;
  87. }
  88. }
  89. }
  90. };
  91. jsPDF.API.annotationPlugin = annotationPlugin;
  92. jsPDF.API.events.push([ 'addPage', function(info) {
  93. this.annotationPlugin.annotations[info.pageNumber] = [];
  94. } ]);
  95. jsPDFAPI.events.push([ 'putPage', function(info) {
  96. //TODO store annotations in pageContext so reorder/remove will not affect them.
  97. var pageAnnos = this.annotationPlugin.annotations[info.pageNumber];
  98. var found = false;
  99. for (var a = 0; a &lt; pageAnnos.length &amp;&amp; !found; a++) {
  100. var anno = pageAnnos[a];
  101. switch (anno.type) {
  102. case 'link':
  103. if (annotationPlugin.notEmpty(anno.options.url) || annotationPlugin.notEmpty(anno.options.pageNumber)) {
  104. found = true;
  105. break;
  106. }
  107. case 'reference':
  108. case 'text':
  109. case 'freetext':
  110. found = true;
  111. break;
  112. }
  113. }
  114. if (found == false) {
  115. return;
  116. }
  117. this.internal.write("/Annots [");
  118. var f2 = this.annotationPlugin.f2;
  119. var k = this.internal.scaleFactor;
  120. var pageHeight = this.internal.pageSize.height;
  121. var pageInfo = this.internal.getPageInfo(info.pageNumber);
  122. for (var a = 0; a &lt; pageAnnos.length; a++) {
  123. var anno = pageAnnos[a];
  124. switch (anno.type) {
  125. case 'reference':
  126. // References to Widget Anotations (for AcroForm Fields)
  127. this.internal.write(' ' + anno.object.objId + ' 0 R ');
  128. break;
  129. case 'text':
  130. // Create a an object for both the text and the popup
  131. var objText = this.internal.newAdditionalObject();
  132. var objPopup = this.internal.newAdditionalObject();
  133. var title = anno.title || 'Note';
  134. var rect = "/Rect [" + f2(anno.bounds.x * k) + " " + f2(pageHeight - (anno.bounds.y + anno.bounds.h) * k) + " " + f2((anno.bounds.x + anno.bounds.w) * k) + " " + f2((pageHeight - anno.bounds.y) * k) + "] ";
  135. line = '&lt;&lt;/Type /Annot /Subtype /' + 'Text' + ' ' + rect + '/Contents (' + anno.contents + ')';
  136. line += ' /Popup ' + objPopup.objId + " 0 R";
  137. line += ' /P ' + pageInfo.objId + " 0 R";
  138. line += ' /T (' + title + ') >>';
  139. objText.content = line;
  140. var parent = objText.objId + ' 0 R';
  141. var popoff = 30;
  142. var rect = "/Rect [" + f2((anno.bounds.x + popoff) * k) + " " + f2(pageHeight - (anno.bounds.y + anno.bounds.h) * k) + " " + f2((anno.bounds.x + anno.bounds.w + popoff) * k) + " " + f2((pageHeight - anno.bounds.y) * k) + "] ";
  143. //var rect2 = "/Rect [" + f2(anno.bounds.x * k) + " " + f2((pageHeight - anno.bounds.y) * k) + " " + f2(anno.bounds.x + anno.bounds.w * k) + " " + f2(pageHeight - (anno.bounds.y + anno.bounds.h) * k) + "] ";
  144. line = '&lt;&lt;/Type /Annot /Subtype /' + 'Popup' + ' ' + rect + ' /Parent ' + parent;
  145. if (anno.open) {
  146. line += ' /Open true';
  147. }
  148. line += ' >>';
  149. objPopup.content = line;
  150. this.internal.write(objText.objId, '0 R', objPopup.objId, '0 R');
  151. break;
  152. case 'freetext':
  153. var rect = "/Rect [" + f2(anno.bounds.x * k) + " " + f2((pageHeight - anno.bounds.y) * k) + " " + f2(anno.bounds.x + anno.bounds.w * k) + " " + f2(pageHeight - (anno.bounds.y + anno.bounds.h) * k) + "] ";
  154. var color = anno.color || '#000000';
  155. line = '&lt;&lt;/Type /Annot /Subtype /' + 'FreeText' + ' ' + rect + '/Contents (' + anno.contents + ')';
  156. line += ' /DS(font: Helvetica,sans-serif 12.0pt; text-align:left; color:#' + color + ')';
  157. line += ' /Border [0 0 0]';
  158. line += ' >>';
  159. this.internal.write(line);
  160. break;
  161. case 'link':
  162. if (anno.options.name) {
  163. var loc = this.annotations._nameMap[anno.options.name];
  164. anno.options.pageNumber = loc.page;
  165. anno.options.top = loc.y;
  166. } else {
  167. if (!anno.options.top) {
  168. anno.options.top = 0;
  169. }
  170. }
  171. //var pageHeight = this.internal.pageSize.height * this.internal.scaleFactor;
  172. var rect = "/Rect [" + f2(anno.x * k) + " " + f2((pageHeight - anno.y) * k) + " " + f2(anno.x + anno.w * k) + " " + f2(pageHeight - (anno.y + anno.h) * k) + "] ";
  173. var line = '';
  174. if (anno.options.url) {
  175. line = '&lt;&lt;/Type /Annot /Subtype /Link ' + rect + '/Border [0 0 0] /A &lt;&lt;/S /URI /URI (' + anno.options.url + ') >>';
  176. } else if (anno.options.pageNumber) {
  177. // first page is 0
  178. var info = this.internal.getPageInfo(anno.options.pageNumber);
  179. line = '&lt;&lt;/Type /Annot /Subtype /Link ' + rect + '/Border [0 0 0] /Dest [' + info.objId + " 0 R";
  180. anno.options.magFactor = anno.options.magFactor || "XYZ";
  181. switch (anno.options.magFactor) {
  182. case 'Fit':
  183. line += ' /Fit]';
  184. break;
  185. case 'FitH':
  186. //anno.options.top = anno.options.top || f2(pageHeight * k);
  187. line += ' /FitH ' + anno.options.top + ']';
  188. break;
  189. case 'FitV':
  190. anno.options.left = anno.options.left || 0;
  191. line += ' /FitV ' + anno.options.left + ']';
  192. break;
  193. case 'XYZ':
  194. default:
  195. var top = f2((pageHeight - anno.options.top) * k);// || f2(pageHeight * k);
  196. anno.options.left = anno.options.left || 0;
  197. // 0 or null zoom will not change zoom factor
  198. if (typeof anno.options.zoom === 'undefined') {
  199. anno.options.zoom = 0;
  200. }
  201. line += ' /XYZ ' + anno.options.left + ' ' + top + ' ' + anno.options.zoom + ']';
  202. break;
  203. }
  204. } else {
  205. // TODO error - should not be here
  206. }
  207. if (line != '') {
  208. line += " >>";
  209. this.internal.write(line);
  210. }
  211. break;
  212. }
  213. }
  214. this.internal.write("]");
  215. } ]);
  216. jsPDFAPI.createAnnotation = function(options) {
  217. switch (options.type) {
  218. case 'link':
  219. this.link(options.bounds.x, options.bounds.y, options.bounds.w, options.bounds.h, options);
  220. break;
  221. case 'text':
  222. case 'freetext':
  223. this.annotationPlugin.annotations[this.internal.getCurrentPageInfo().pageNumber].push(options);
  224. break;
  225. }
  226. }
  227. /**
  228. * valid options
  229. * &lt;li> pageNumber or url [required]
  230. * &lt;p>If pageNumber is specified, top and zoom may also be specified&lt;/p>
  231. */
  232. jsPDFAPI.link = function(x,y,w,h,options) {
  233. 'use strict';
  234. this.annotationPlugin.annotations[this.internal.getCurrentPageInfo().pageNumber].push({
  235. x : x,
  236. y : y,
  237. w : w,
  238. h : h,
  239. options : options,
  240. type : 'link'
  241. });
  242. };
  243. /**
  244. * valid options
  245. * &lt;li> pageNumber or url [required]
  246. * &lt;p>If pageNumber is specified, top and zoom may also be specified&lt;/p>
  247. */
  248. jsPDFAPI.link = function(x,y,w,h,options) {
  249. 'use strict';
  250. this.annotationPlugin.annotations[this.internal.getCurrentPageInfo().pageNumber].push({
  251. x : x,
  252. y : y,
  253. w : w,
  254. h : h,
  255. options : options,
  256. type : 'link'
  257. });
  258. };
  259. /**
  260. * Currently only supports single line text.
  261. * Returns the width of the text/link
  262. */
  263. jsPDFAPI.textWithLink = function(text,x,y,options) {
  264. 'use strict';
  265. var width = this.getTextWidth(text);
  266. var height = this.internal.getLineHeight();
  267. this.text(text, x, y);
  268. //TODO We really need the text baseline height to do this correctly.
  269. // Or ability to draw text on top, bottom, center, or baseline.
  270. y += height * .2;
  271. this.link(x, y - height, width, height, options);
  272. return width;
  273. };
  274. //TODO move into external library
  275. jsPDFAPI.getTextWidth = function(text) {
  276. 'use strict';
  277. var fontSize = this.internal.getFontSize();
  278. var txtWidth = this.getStringUnitWidth(text) * fontSize / this.internal.scaleFactor;
  279. return txtWidth;
  280. };
  281. //TODO move into external library
  282. jsPDFAPI.getLineHeight = function() {
  283. return this.internal.getLineHeight();
  284. };
  285. return this;
  286. })(jsPDF.API);
  287. </code></pre>
  288. </article>
  289. </section>
  290. </div>
  291. <br class="clear">
  292. <footer>
  293. 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.
  294. </footer>
  295. <script>prettyPrint();</script>
  296. <script src="scripts/linenumber.js"></script>
  297. </body>
  298. </html>