-
Notifications
You must be signed in to change notification settings - Fork 581
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
1 changed file
with
304 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,304 @@ | ||
|
||
/** | ||
* jsPDF | ||
* (c) 2009 James Hall | ||
* | ||
* Some parts based on FPDF. | ||
*/ | ||
|
||
var jsPDF = function(){ | ||
|
||
// Private properties | ||
var version = '20090504'; | ||
var buffer = ''; | ||
|
||
var pdfVersion = '1.3'; // PDF Version | ||
var defaultPageFormat = 'a4'; | ||
var pageFormats = { // Size in mm of various paper formats | ||
'a3': [841.89, 1190.55], | ||
'a4': [595.28, 841.89], | ||
'a5': [420.94, 595.28], | ||
'letter': [612, 792], | ||
'legal': [612, 1008] | ||
}; | ||
var textColor = '0 g'; | ||
var page = 0; | ||
var objectNumber = 2; // 'n' Current object number | ||
var state = 0; // Current document state | ||
var pages = new Array(); | ||
var offsets = new Array(); // List of offsets | ||
var lineWidth = 0.200025; // 2mm | ||
var pageHeight; | ||
var k; // Scale factor | ||
var unit = 'mm'; // Default to mm for units | ||
var fontNumber; // TODO: This is temp, replace with real font handling | ||
var documentProperties = {}; | ||
var fontSize = 16; // Default font size | ||
var pageFontSize = 16; | ||
|
||
// Initilisation | ||
if (unit == 'pt') { | ||
k = 1; | ||
} else if(unit == 'mm') { | ||
k = 72/25.4; | ||
} else if(unit == 'cm') { | ||
k = 72/2.54; | ||
} else if(unit == 'in') { | ||
k = 72; | ||
} | ||
|
||
// Private functions | ||
var newObject = function() { | ||
//Begin a new object | ||
objectNumber ++; | ||
offsets[objectNumber] = buffer.length; | ||
out(objectNumber + ' 0 obj'); | ||
} | ||
|
||
|
||
var putHeader = function() { | ||
out('%PDF-' + pdfVersion); | ||
} | ||
|
||
var putPages = function() { | ||
|
||
// TODO: Fix, hardcoded to a4 portrait | ||
var wPt = pageWidth * k; | ||
var hPt = pageHeight * k; | ||
|
||
for(n=1; n <= page; n++) { | ||
newObject(); | ||
out('<</Type /Page'); | ||
out('/Parent 1 0 R'); | ||
out('/Resources 2 0 R'); | ||
out('/Contents ' + (objectNumber + 1) + ' 0 R>>'); | ||
out('endobj'); | ||
|
||
//Page content | ||
p = pages[n]; | ||
newObject(); | ||
out('<</Length ' + p.length + '>>'); | ||
putStream(p); | ||
out('endobj'); | ||
} | ||
offsets[1] = buffer.length; | ||
out('1 0 obj'); | ||
out('<</Type /Pages'); | ||
var kids='/Kids ['; | ||
for (i = 0; i < page; i++) { | ||
kids += (3 + 2 * i) + ' 0 R '; | ||
} | ||
out(kids + ']'); | ||
out('/Count ' + page); | ||
out(sprintf('/MediaBox [0 0 %.2f %.2f]', wPt, hPt)); | ||
out('>>'); | ||
out('endobj'); | ||
} | ||
|
||
var putStream = function(str) { | ||
out('stream'); | ||
out(str); | ||
out('endstream'); | ||
} | ||
|
||
var putResources = function() { | ||
putFonts(); | ||
putImages(); | ||
|
||
//Resource dictionary | ||
offsets[2] = buffer.length; | ||
out('2 0 obj'); | ||
out('<<'); | ||
putResourceDictionary(); | ||
out('>>'); | ||
out('endobj'); | ||
} | ||
|
||
var putFonts = function() { | ||
// TODO: Only supports core font hardcoded to Helvetica | ||
newObject(); | ||
fontNumber = objectNumber; | ||
name = 'Helvetica'; | ||
out('<</Type /Font'); | ||
out('/BaseFont /' + name); | ||
out('/Subtype /Type1'); | ||
out('/Encoding /WinAnsiEncoding'); | ||
out('>>'); | ||
out('endobj'); | ||
} | ||
|
||
var putImages = function() { | ||
// TODO | ||
} | ||
|
||
var putResourceDictionary = function() { | ||
out('/ProcSet [/PDF /Text /ImageB /ImageC /ImageI]'); | ||
out('/Font <<'); | ||
// Do this for each font, the '1' bit is the index of the font | ||
// fontNumber is currently the object number related to 'putFonts' | ||
out('/F1 ' + fontNumber + ' 0 R'); | ||
out('>>'); | ||
out('/XObject <<'); | ||
putXobjectDict(); | ||
out('>>'); | ||
} | ||
|
||
var putXobjectDict = function() { | ||
// TODO | ||
// Loop through images | ||
} | ||
|
||
|
||
var putInfo = function() { | ||
out('/Producer (jsPDF ' + version + ')'); | ||
if(documentProperties.title != undefined) { | ||
out('/Title (' + pdfEscape(documentProperties.title) + ')'); | ||
} | ||
if(documentProperties.subject != undefined) { | ||
out('/Subject (' + pdfEscape(documentProperties.subject) + ')'); | ||
} | ||
if(documentProperties.author != undefined) { | ||
out('/Author (' + pdfEscape(documentProperties.author) + ')'); | ||
} | ||
if(documentProperties.keywords != undefined) { | ||
out('/Keywords (' + pdfEscape(documentProperties.keywords) + ')'); | ||
} | ||
if(documentProperties.creator != undefined) { | ||
out('/Creator (' + pdfEscape(documentProperties.creator) + ')'); | ||
} | ||
var created = new Date(); | ||
var year = created.getFullYear(); | ||
var month = (created.getMonth() + 1); | ||
var day = created.getDate(); | ||
var hour = created.getHours(); | ||
var minute = created.getMinutes(); | ||
var second = created.getSeconds(); | ||
out('/CreationDate (D:' + sprintf('%02d%02d%02d%02d%02d%02d', year, month, day, hour, minute, second) + ')'); | ||
} | ||
|
||
var putCatalog = function () { | ||
out('/Type /Catalog'); | ||
out('/Pages 1 0 R'); | ||
// TODO: Add zoom and layout modes | ||
out('/OpenAction [3 0 R /FitH null]'); | ||
out('/PageLayout /OneColumn'); | ||
} | ||
|
||
function putTrailer() { | ||
out('/Size ' + (objectNumber + 1)); | ||
out('/Root ' + objectNumber + ' 0 R'); | ||
out('/Info ' + (objectNumber - 1) + ' 0 R'); | ||
} | ||
|
||
var endDocument = function() { | ||
state = 1; | ||
putHeader(); | ||
putPages(); | ||
|
||
putResources(); | ||
//Info | ||
newObject(); | ||
out('<<'); | ||
putInfo(); | ||
out('>>'); | ||
out('endobj'); | ||
|
||
//Catalog | ||
newObject(); | ||
out('<<'); | ||
putCatalog(); | ||
out('>>'); | ||
out('endobj'); | ||
|
||
//Cross-ref | ||
var o = buffer.length; | ||
out('xref'); | ||
out('0 ' + (objectNumber + 1)); | ||
out('0000000000 65535 f '); | ||
for (var i=1; i <= objectNumber; i++) { | ||
out(sprintf('%010d 00000 n ', offsets[i])); | ||
} | ||
//Trailer | ||
out('trailer'); | ||
out('<<'); | ||
putTrailer(); | ||
out('>>'); | ||
out('startxref'); | ||
out(o); | ||
out('%%EOF'); | ||
state = 3; | ||
} | ||
|
||
var beginPage = function() { | ||
page ++; | ||
// Do dimension stuff | ||
state = 2; | ||
pages[page] = ''; | ||
|
||
// TODO: Hardcoded at A4 and portrait | ||
pageHeight = pageFormats['a4'][1] / k; | ||
pageWidth = pageFormats['a4'][0] / k; | ||
} | ||
|
||
var out = function(string) { | ||
if(state == 2) { | ||
pages[page] += string + '\n'; | ||
} else { | ||
buffer += string + '\n'; | ||
} | ||
} | ||
|
||
var _addPage = function() { | ||
beginPage(); | ||
// Set line width | ||
out(sprintf('%.2f w', (lineWidth * k))); | ||
|
||
// Set font - TODO | ||
// 16 is the font size | ||
pageFontSize = fontSize; | ||
out('BT /F1 ' + parseInt(fontSize) + '.00 Tf ET'); | ||
} | ||
|
||
// Add the first page automatically | ||
_addPage(); | ||
|
||
// Escape text | ||
var pdfEscape = function(text) { | ||
return text.replace(/\\/g, '\\\\').replace(/\(/g, '\\(').replace(/\)/g, '\\)'); | ||
} | ||
|
||
return { | ||
addPage: function() { | ||
_addPage(); | ||
}, | ||
text: function(x, y, text) { | ||
// need page height | ||
if(pageFontSize != fontSize) { | ||
out('BT /F1 ' + parseInt(fontSize) + '.00 Tf ET'); | ||
pageFontSize = fontSize; | ||
} | ||
var str = sprintf('BT %.2f %.2f Td (%s) Tj ET', x * k, (pageHeight - y) * k, pdfEscape(text)); | ||
out(str); | ||
}, | ||
setProperties: function(properties) { | ||
documentProperties = properties; | ||
}, | ||
addImage: function(imageData, format, x, y, w, h) { | ||
|
||
}, | ||
output: function(type, options) { | ||
endDocument(); | ||
if(type == undefined) { | ||
return buffer; | ||
} | ||
if(type == 'datauri') { | ||
document.location.href = 'data:application/pdf;base64,' + Base64.encode(buffer); | ||
} | ||
// @TODO: Add different output options | ||
}, | ||
setFontSize: function(size) { | ||
fontSize = size; | ||
} | ||
} | ||
|
||
}; |