5 * Some parts based on FPDF.
8 var jsPDF = function(){
11 var version = '20090504';
14 var pdfVersion = '1.3'; // PDF Version
15 var defaultPageFormat = 'a4';
16 var pageFormats = { // Size in mm of various paper formats
17 'a3': [841.89, 1190.55],
18 'a4': [595.28, 841.89],
19 'a5': [420.94, 595.28],
23 var textColor = '0 g';
25 var objectNumber = 2; // 'n' Current object number
26 var state = 0; // Current document state
27 var pages = new Array();
28 var offsets = new Array(); // List of offsets
29 var lineWidth = 0.200025; // 2mm
31 var k; // Scale factor
32 var unit = 'mm'; // Default to mm for units
33 var fontNumber; // TODO: This is temp, replace with real font handling
34 var documentProperties = {};
35 var fontSize = 16; // Default font size
36 var pageFontSize = 16;
41 } else if(unit == 'mm') {
43 } else if(unit == 'cm') {
45 } else if(unit == 'in') {
50 var newObject = function() {
53 offsets[objectNumber] = buffer.length;
54 out(objectNumber + ' 0 obj');
58 var putHeader = function() {
59 out('%PDF-' + pdfVersion);
62 var putPages = function() {
64 // TODO: Fix, hardcoded to a4 portrait
65 var wPt = pageWidth * k;
66 var hPt = pageHeight * k;
68 for(n=1; n <= page; n++) {
72 out('/Resources 2 0 R');
73 out('/Contents ' + (objectNumber + 1) + ' 0 R>>');
79 out('<</Length ' + p.length + '>>');
83 offsets[1] = buffer.length;
85 out('<</Type /Pages');
87 for (i = 0; i < page; i++) {
88 kids += (3 + 2 * i) + ' 0 R ';
91 out('/Count ' + page);
92 out(sprintf('/MediaBox [0 0 %.2f %.2f]', wPt, hPt));
97 var putStream = function(str) {
103 var putResources = function() {
107 //Resource dictionary
108 offsets[2] = buffer.length;
111 putResourceDictionary();
116 var putFonts = function() {
117 // TODO: Only supports core font hardcoded to Helvetica
119 fontNumber = objectNumber;
121 out('<</Type /Font');
122 out('/BaseFont /' + name);
123 out('/Subtype /Type1');
124 out('/Encoding /WinAnsiEncoding');
129 var putImages = function() {
133 var putResourceDictionary = function() {
134 out('/ProcSet [/PDF /Text /ImageB /ImageC /ImageI]');
136 // Do this for each font, the '1' bit is the index of the font
137 // fontNumber is currently the object number related to 'putFonts'
138 out('/F1 ' + fontNumber + ' 0 R');
145 var putXobjectDict = function() {
147 // Loop through images
151 var putInfo = function() {
152 out('/Producer (jsPDF ' + version + ')');
153 if(documentProperties.title != undefined) {
154 out('/Title (' + pdfEscape(documentProperties.title) + ')');
156 if(documentProperties.subject != undefined) {
157 out('/Subject (' + pdfEscape(documentProperties.subject) + ')');
159 if(documentProperties.author != undefined) {
160 out('/Author (' + pdfEscape(documentProperties.author) + ')');
162 if(documentProperties.keywords != undefined) {
163 out('/Keywords (' + pdfEscape(documentProperties.keywords) + ')');
165 if(documentProperties.creator != undefined) {
166 out('/Creator (' + pdfEscape(documentProperties.creator) + ')');
168 var created = new Date();
169 var year = created.getFullYear();
170 var month = (created.getMonth() + 1);
171 var day = created.getDate();
172 var hour = created.getHours();
173 var minute = created.getMinutes();
174 var second = created.getSeconds();
175 out('/CreationDate (D:' + sprintf('%02d%02d%02d%02d%02d%02d', year, month, day, hour, minute, second) + ')');
178 var putCatalog = function () {
179 out('/Type /Catalog');
181 // TODO: Add zoom and layout modes
182 out('/OpenAction [3 0 R /FitH null]');
183 out('/PageLayout /OneColumn');
186 function putTrailer() {
187 out('/Size ' + (objectNumber + 1));
188 out('/Root ' + objectNumber + ' 0 R');
189 out('/Info ' + (objectNumber - 1) + ' 0 R');
192 var endDocument = function() {
213 var o = buffer.length;
215 out('0 ' + (objectNumber + 1));
216 out('0000000000 65535 f ');
217 for (var i=1; i <= objectNumber; i++) {
218 out(sprintf('%010d 00000 n ', offsets[i]));
231 var beginPage = function() {
233 // Do dimension stuff
237 // TODO: Hardcoded at A4 and portrait
238 pageHeight = pageFormats['a4'][1] / k;
239 pageWidth = pageFormats['a4'][0] / k;
242 var out = function(string) {
244 pages[page] += string + '\n';
246 buffer += string + '\n';
250 var _addPage = function() {
253 out(sprintf('%.2f w', (lineWidth * k)));
256 // 16 is the font size
257 pageFontSize = fontSize;
258 out('BT /F1 ' + parseInt(fontSize) + '.00 Tf ET');
261 // Add the first page automatically
265 var pdfEscape = function(text) {
266 return text.replace(/\\/g, '\\\\').replace(/\(/g, '\\(').replace(/\)/g, '\\)');
270 addPage: function() {
273 text: function(x, y, text) {
275 if(pageFontSize != fontSize) {
276 out('BT /F1 ' + parseInt(fontSize) + '.00 Tf ET');
277 pageFontSize = fontSize;
279 var str = sprintf('BT %.2f %.2f Td (%s) Tj ET', x * k, (pageHeight - y) * k, pdfEscape(text));
282 setProperties: function(properties) {
283 documentProperties = properties;
285 addImage: function(imageData, format, x, y, w, h) {
288 output: function(type, options) {
290 if(type == undefined) {
293 if(type == 'datauri') {
294 document.location.href = 'data:application/pdf;base64,' + Base64.encode(buffer);
296 // @TODO: Add different output options
298 setFontSize: function(size) {