test1 successful: draw triangle & circle

main
Matthew Butterick 8 years ago
parent 4f8b301c77
commit 1b4968d107

@ -0,0 +1,192 @@
// Generated by CoffeeScript 1.12.5
(function() {
var Data;
Data = (function() {
function Data(data) {
this.data = data != null ? data : [];
this.pos = 0;
this.length = this.data.length;
}
Data.prototype.readByte = function() {
return this.data[this.pos++];
};
Data.prototype.writeByte = function(byte) {
return this.data[this.pos++] = byte;
};
Data.prototype.byteAt = function(index) {
return this.data[index];
};
Data.prototype.readBool = function() {
return !!this.readByte();
};
Data.prototype.writeBool = function(val) {
return this.writeByte(val ? 1 : 0);
};
Data.prototype.readUInt32 = function() {
var b1, b2, b3, b4;
b1 = this.readByte() * 0x1000000;
b2 = this.readByte() << 16;
b3 = this.readByte() << 8;
b4 = this.readByte();
return b1 + b2 + b3 + b4;
};
Data.prototype.writeUInt32 = function(val) {
this.writeByte((val >>> 24) & 0xff);
this.writeByte((val >> 16) & 0xff);
this.writeByte((val >> 8) & 0xff);
return this.writeByte(val & 0xff);
};
Data.prototype.readInt32 = function() {
var int;
int = this.readUInt32();
if (int >= 0x80000000) {
return int - 0x100000000;
} else {
return int;
}
};
Data.prototype.writeInt32 = function(val) {
if (val < 0) {
val += 0x100000000;
}
return this.writeUInt32(val);
};
Data.prototype.readUInt16 = function() {
var b1, b2;
b1 = this.readByte() << 8;
b2 = this.readByte();
return b1 | b2;
};
Data.prototype.writeUInt16 = function(val) {
this.writeByte((val >> 8) & 0xff);
return this.writeByte(val & 0xff);
};
Data.prototype.readInt16 = function() {
var int;
int = this.readUInt16();
if (int >= 0x8000) {
return int - 0x10000;
} else {
return int;
}
};
Data.prototype.writeInt16 = function(val) {
if (val < 0) {
val += 0x10000;
}
return this.writeUInt16(val);
};
Data.prototype.readString = function(length) {
var i, j, ref, ret;
ret = [];
for (i = j = 0, ref = length; 0 <= ref ? j < ref : j > ref; i = 0 <= ref ? ++j : --j) {
ret[i] = String.fromCharCode(this.readByte());
}
return ret.join('');
};
Data.prototype.writeString = function(val) {
var i, j, ref, results;
results = [];
for (i = j = 0, ref = val.length; 0 <= ref ? j < ref : j > ref; i = 0 <= ref ? ++j : --j) {
results.push(this.writeByte(val.charCodeAt(i)));
}
return results;
};
Data.prototype.stringAt = function(pos, length) {
this.pos = pos;
return this.readString(length);
};
Data.prototype.readShort = function() {
return this.readInt16();
};
Data.prototype.writeShort = function(val) {
return this.writeInt16(val);
};
Data.prototype.readLongLong = function() {
var b1, b2, b3, b4, b5, b6, b7, b8;
b1 = this.readByte();
b2 = this.readByte();
b3 = this.readByte();
b4 = this.readByte();
b5 = this.readByte();
b6 = this.readByte();
b7 = this.readByte();
b8 = this.readByte();
if (b1 & 0x80) {
return ((b1 ^ 0xff) * 0x100000000000000 + (b2 ^ 0xff) * 0x1000000000000 + (b3 ^ 0xff) * 0x10000000000 + (b4 ^ 0xff) * 0x100000000 + (b5 ^ 0xff) * 0x1000000 + (b6 ^ 0xff) * 0x10000 + (b7 ^ 0xff) * 0x100 + (b8 ^ 0xff) + 1) * -1;
}
return b1 * 0x100000000000000 + b2 * 0x1000000000000 + b3 * 0x10000000000 + b4 * 0x100000000 + b5 * 0x1000000 + b6 * 0x10000 + b7 * 0x100 + b8;
};
Data.prototype.writeLongLong = function(val) {
var high, low;
high = Math.floor(val / 0x100000000);
low = val & 0xffffffff;
this.writeByte((high >> 24) & 0xff);
this.writeByte((high >> 16) & 0xff);
this.writeByte((high >> 8) & 0xff);
this.writeByte(high & 0xff);
this.writeByte((low >> 24) & 0xff);
this.writeByte((low >> 16) & 0xff);
this.writeByte((low >> 8) & 0xff);
return this.writeByte(low & 0xff);
};
Data.prototype.readInt = function() {
return this.readInt32();
};
Data.prototype.writeInt = function(val) {
return this.writeInt32(val);
};
Data.prototype.slice = function(start, end) {
return this.data.slice(start, end);
};
Data.prototype.read = function(bytes) {
var buf, i, j, ref;
buf = [];
for (i = j = 0, ref = bytes; 0 <= ref ? j < ref : j > ref; i = 0 <= ref ? ++j : --j) {
buf.push(this.readByte());
}
return buf;
};
Data.prototype.write = function(bytes) {
var byte, j, len, results;
results = [];
for (j = 0, len = bytes.length; j < len; j++) {
byte = bytes[j];
results.push(this.writeByte(byte));
}
return results;
};
return Data;
})();
module.exports = Data;
}).call(this);

@ -0,0 +1,247 @@
// Generated by CoffeeScript 1.12.5
/*
PDFDocument - represents an entire PDF document
By Devon Govett
*/
(function() {
var PDFDocument, PDFObject, PDFPage, PDFReference, fs, stream,
extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
hasProp = {}.hasOwnProperty;
stream = require('stream');
fs = require('fs');
PDFObject = require('./object');
PDFReference = require('./reference');
PDFPage = require('./page');
PDFDocument = (function(superClass) {
var mixin;
extend(PDFDocument, superClass);
function PDFDocument(options1) {
var key, ref1, ref2, val;
this.options = options1 != null ? options1 : {};
PDFDocument.__super__.constructor.apply(this, arguments);
this.version = 1.3;
this.compress = (ref1 = this.options.compress) != null ? ref1 : true;
this._pageBuffer = [];
this._pageBufferStart = 0;
this._offsets = [];
this._waiting = 0;
this._ended = false;
this._offset = 0;
this._root = this.ref({
Type: 'Catalog',
Pages: this.ref({
Type: 'Pages',
Count: 0,
Kids: []
})
});
this.page = null;
this.initColor();
this.initVector();
this.initFonts();
this.initText();
this.initImages();
this.info = {
Producer: 'PDFKit',
Creator: 'PDFKit',
CreationDate: new Date()
};
if (this.options.info) {
ref2 = this.options.info;
for (key in ref2) {
val = ref2[key];
this.info[key] = val;
}
}
this._write("%PDF-" + this.version);
this._write("%\xFF\xFF\xFF\xFF");
if (this.options.autoFirstPage !== false) {
this.addPage();
}
}
mixin = function(methods) {
var method, name, results;
results = [];
for (name in methods) {
method = methods[name];
results.push(PDFDocument.prototype[name] = method);
}
return results;
};
mixin(require('./mixins/color'));
mixin(require('./mixins/vector'));
mixin(require('./mixins/fonts'));
mixin(require('./mixins/text'));
mixin(require('./mixins/images'));
mixin(require('./mixins/annotations'));
PDFDocument.prototype.addPage = function(options) {
var pages;
if (options == null) {
options = this.options;
}
if (!this.options.bufferPages) {
this.flushPages();
}
this.page = new PDFPage(this, options);
this._pageBuffer.push(this.page);
pages = this._root.data.Pages.data;
pages.Kids.push(this.page.dictionary);
pages.Count++;
this.x = this.page.margins.left;
this.y = this.page.margins.top;
this._ctm = [1, 0, 0, 1, 0, 0];
this.transform(1, 0, 0, -1, 0, this.page.height);
this.emit('pageAdded');
return this;
};
PDFDocument.prototype.bufferedPageRange = function() {
return {
start: this._pageBufferStart,
count: this._pageBuffer.length
};
};
PDFDocument.prototype.switchToPage = function(n) {
var page;
if (!(page = this._pageBuffer[n - this._pageBufferStart])) {
throw new Error("switchToPage(" + n + ") out of bounds, current buffer covers pages " + this._pageBufferStart + " to " + (this._pageBufferStart + this._pageBuffer.length - 1));
}
return this.page = page;
};
PDFDocument.prototype.flushPages = function() {
var i, len, page, pages;
pages = this._pageBuffer;
this._pageBuffer = [];
this._pageBufferStart += pages.length;
for (i = 0, len = pages.length; i < len; i++) {
page = pages[i];
page.end();
}
};
PDFDocument.prototype.ref = function(data) {
var ref;
ref = new PDFReference(this, this._offsets.length + 1, data);
this._offsets.push(null);
this._waiting++;
return ref;
};
PDFDocument.prototype._read = function() {};
PDFDocument.prototype._write = function(data) {
if (!Buffer.isBuffer(data)) {
data = new Buffer(data + '\n', 'binary');
}
this.push(data);
return this._offset += data.length;
};
PDFDocument.prototype.addContent = function(data) {
this.page.write(data);
return this;
};
PDFDocument.prototype._refEnd = function(ref) {
this._offsets[ref.id - 1] = ref.offset;
if (--this._waiting === 0 && this._ended) {
this._finalize();
return this._ended = false;
}
};
PDFDocument.prototype.write = function(filename, fn) {
var err;
err = new Error('PDFDocument#write is deprecated, and will be removed in a future version of PDFKit. Please pipe the document into a Node stream.');
console.warn(err.stack);
this.pipe(fs.createWriteStream(filename));
this.end();
return this.once('end', fn);
};
PDFDocument.prototype.output = function(fn) {
throw new Error('PDFDocument#output is deprecated, and has been removed from PDFKit. Please pipe the document into a Node stream.');
};
PDFDocument.prototype.end = function() {
var font, key, name, ref1, ref2, val;
this.flushPages();
this._info = this.ref();
ref1 = this.info;
for (key in ref1) {
val = ref1[key];
if (typeof val === 'string') {
val = new String(val);
}
this._info.data[key] = val;
}
this._info.end();
ref2 = this._fontFamilies;
for (name in ref2) {
font = ref2[name];
font.finalize();
}
this._root.end();
this._root.data.Pages.end();
if (this._waiting === 0) {
return this._finalize();
} else {
return this._ended = true;
}
};
PDFDocument.prototype._finalize = function(fn) {
var i, len, offset, ref1, xRefOffset;
xRefOffset = this._offset;
this._write("xref");
this._write("0 " + (this._offsets.length + 1));
this._write("0000000000 65535 f ");
ref1 = this._offsets;
for (i = 0, len = ref1.length; i < len; i++) {
offset = ref1[i];
offset = ('0000000000' + offset).slice(-10);
this._write(offset + ' 00000 n ');
}
this._write('trailer');
this._write(PDFObject.convert({
Size: this._offsets.length + 1,
Root: this._root,
Info: this._info
}));
this._write('startxref');
this._write("" + xRefOffset);
this._write('%%EOF');
return this.push(null);
};
PDFDocument.prototype.toString = function() {
return "[object PDFDocument]";
};
return PDFDocument;
})(stream.Readable);
module.exports = PDFDocument;
}).call(this);

@ -0,0 +1,75 @@
// Generated by CoffeeScript 1.12.5
(function() {
var EmbeddedFont, PDFFont, StandardFont, fontkit;
fontkit = require('fontkit');
PDFFont = (function() {
PDFFont.open = function(document, src, family, id) {
var font;
if (typeof src === 'string') {
if (StandardFont.isStandardFont(src)) {
return new StandardFont(document, src, id);
}
font = fontkit.openSync(src, family);
} else if (Buffer.isBuffer(src)) {
font = fontkit.create(src, family);
} else if (src instanceof Uint8Array) {
font = fontkit.create(new Buffer(src), family);
} else if (src instanceof ArrayBuffer) {
font = fontkit.create(new Buffer(new Uint8Array(src)), family);
}
if (font == null) {
throw new Error('Not a supported font format or standard PDF font.');
}
return new EmbeddedFont(document, font, id);
};
function PDFFont() {
throw new Error('Cannot construct a PDFFont directly.');
}
PDFFont.prototype.encode = function(text) {
throw new Error('Must be implemented by subclasses');
};
PDFFont.prototype.widthOfString = function(text) {
throw new Error('Must be implemented by subclasses');
};
PDFFont.prototype.ref = function() {
return this.dictionary != null ? this.dictionary : this.dictionary = this.document.ref();
};
PDFFont.prototype.finalize = function() {
if (this.embedded || (this.dictionary == null)) {
return;
}
this.embed();
return this.embedded = true;
};
PDFFont.prototype.embed = function() {
throw new Error('Must be implemented by subclasses');
};
PDFFont.prototype.lineHeight = function(size, includeGap) {
var gap;
if (includeGap == null) {
includeGap = false;
}
gap = includeGap ? this.lineGap : 0;
return (this.ascender + gap - this.descender) / 1000 * size;
};
return PDFFont;
})();
module.exports = PDFFont;
StandardFont = require('./font/standard');
EmbeddedFont = require('./font/embedded');
}).call(this);

@ -0,0 +1,53 @@
// Generated by CoffeeScript 1.12.5
/*
PDFImage - embeds images in PDF documents
By Devon Govett
*/
(function() {
var Data, JPEG, PDFImage, PNG, fs;
fs = require('fs');
Data = require('./data');
JPEG = require('./image/jpeg');
PNG = require('./image/png');
PDFImage = (function() {
function PDFImage() {}
PDFImage.open = function(src, label) {
var data, match;
if (Buffer.isBuffer(src)) {
data = src;
} else if (src instanceof ArrayBuffer) {
data = new Buffer(new Uint8Array(src));
} else {
if (match = /^data:.+;base64,(.*)$/.exec(src)) {
data = new Buffer(match[1], 'base64');
} else {
data = fs.readFileSync(src);
if (!data) {
return;
}
}
}
if (data[0] === 0xff && data[1] === 0xd8) {
return new JPEG(data, label);
} else if (data[0] === 0x89 && data.toString('ascii', 1, 4) === 'PNG') {
return new PNG(data, label);
} else {
throw new Error('Unknown image format.');
}
};
return PDFImage;
})();
module.exports = PDFImage;
}).call(this);

@ -0,0 +1,252 @@
// Generated by CoffeeScript 1.12.5
(function() {
var EventEmitter, LineBreaker, LineWrapper,
extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
hasProp = {}.hasOwnProperty;
EventEmitter = require('events').EventEmitter;
LineBreaker = require('linebreak');
LineWrapper = (function(superClass) {
extend(LineWrapper, superClass);
function LineWrapper(document, options) {
var ref;
this.document = document;
this.indent = options.indent || 0;
this.characterSpacing = options.characterSpacing || 0;
this.wordSpacing = options.wordSpacing === 0;
this.columns = options.columns || 1;
this.columnGap = (ref = options.columnGap) != null ? ref : 18;
this.lineWidth = (options.width - (this.columnGap * (this.columns - 1))) / this.columns;
this.spaceLeft = this.lineWidth;
this.startX = this.document.x;
this.startY = this.document.y;
this.column = 1;
this.ellipsis = options.ellipsis;
this.continuedX = 0;
this.features = options.features;
if (options.height != null) {
this.height = options.height;
this.maxY = this.startY + options.height;
} else {
this.maxY = this.document.page.maxY();
}
this.on('firstLine', (function(_this) {
return function(options) {
var indent;
indent = _this.continuedX || _this.indent;
_this.document.x += indent;
_this.lineWidth -= indent;
return _this.once('line', function() {
_this.document.x -= indent;
_this.lineWidth += indent;
if (options.continued && !_this.continuedX) {
_this.continuedX = _this.indent;
}
if (!options.continued) {
return _this.continuedX = 0;
}
});
};
})(this));
this.on('lastLine', (function(_this) {
return function(options) {
var align;
align = options.align;
if (align === 'justify') {
options.align = 'left';
}
_this.lastLine = true;
return _this.once('line', function() {
_this.document.y += options.paragraphGap || 0;
options.align = align;
return _this.lastLine = false;
});
};
})(this));
}
LineWrapper.prototype.wordWidth = function(word) {
return this.document.widthOfString(word, this) + this.characterSpacing + this.wordSpacing;
};
LineWrapper.prototype.eachWord = function(text, fn) {
var bk, breaker, fbk, l, last, lbk, shouldContinue, w, word, wordWidths;
breaker = new LineBreaker(text);
last = null;
wordWidths = Object.create(null);
while (bk = breaker.nextBreak()) {
word = text.slice((last != null ? last.position : void 0) || 0, bk.position);
w = wordWidths[word] != null ? wordWidths[word] : wordWidths[word] = this.wordWidth(word);
if (w > this.lineWidth + this.continuedX) {
lbk = last;
fbk = {};
while (word.length) {
l = word.length;
while (w > this.spaceLeft) {
w = this.wordWidth(word.slice(0, --l));
}
fbk.required = l < word.length;
shouldContinue = fn(word.slice(0, l), w, fbk, lbk);
lbk = {
required: false
};
word = word.slice(l);
w = this.wordWidth(word);
if (shouldContinue === false) {
break;
}
}
} else {
shouldContinue = fn(word, w, bk, last);
}
if (shouldContinue === false) {
break;
}
last = bk;
}
};
LineWrapper.prototype.wrap = function(text, options) {
var buffer, emitLine, lc, nextY, textWidth, wc, y;
if (options.indent != null) {
this.indent = options.indent;
}
if (options.characterSpacing != null) {
this.characterSpacing = options.characterSpacing;
}
if (options.wordSpacing != null) {
this.wordSpacing = options.wordSpacing;
}
if (options.ellipsis != null) {
this.ellipsis = options.ellipsis;
}
nextY = this.document.y + this.document.currentLineHeight(true);
if (this.document.y > this.maxY || nextY > this.maxY) {
this.nextSection();
}
buffer = '';
textWidth = 0;
wc = 0;
lc = 0;
y = this.document.y;
emitLine = (function(_this) {
return function() {
options.textWidth = textWidth + _this.wordSpacing * (wc - 1);
options.wordCount = wc;
options.lineWidth = _this.lineWidth;
y = _this.document.y;
_this.emit('line', buffer, options, _this);
return lc++;
};
})(this);
this.emit('sectionStart', options, this);
this.eachWord(text, (function(_this) {
return function(word, w, bk, last) {
var lh, shouldContinue;
if ((last == null) || last.required) {
_this.emit('firstLine', options, _this);
_this.spaceLeft = _this.lineWidth;
}
if (w <= _this.spaceLeft) {
buffer += word;
textWidth += w;
wc++;
}
if (bk.required || w > _this.spaceLeft) {
if (bk.required) {
_this.emit('lastLine', options, _this);
}
lh = _this.document.currentLineHeight(true);
if ((_this.height != null) && _this.ellipsis && _this.document.y + lh * 2 > _this.maxY && _this.column >= _this.columns) {
if (_this.ellipsis === true) {
_this.ellipsis = '…';
}
buffer = buffer.replace(/\s+$/, '');
textWidth = _this.wordWidth(buffer + _this.ellipsis);
while (textWidth > _this.lineWidth) {
buffer = buffer.slice(0, -1).replace(/\s+$/, '');
textWidth = _this.wordWidth(buffer + _this.ellipsis);
}
buffer = buffer + _this.ellipsis;
}
if (bk.required && w > _this.spaceLeft) {
buffer = word;
textWidth = w;
wc = 1;
}
emitLine();
if (_this.document.y + lh > _this.maxY) {
shouldContinue = _this.nextSection();
if (!shouldContinue) {
wc = 0;
buffer = '';
return false;
}
}
if (bk.required) {
_this.spaceLeft = _this.lineWidth;
buffer = '';
textWidth = 0;
return wc = 0;
} else {
_this.spaceLeft = _this.lineWidth - w;
buffer = word;
textWidth = w;
return wc = 1;
}
} else {
return _this.spaceLeft -= w;
}
};
})(this));
if (wc > 0) {
this.emit('lastLine', options, this);
emitLine();
}
this.emit('sectionEnd', options, this);
if (options.continued === true) {
if (lc > 1) {
this.continuedX = 0;
}
this.continuedX += options.textWidth;
return this.document.y = y;
} else {
return this.document.x = this.startX;
}
};
LineWrapper.prototype.nextSection = function(options) {
var ref;
this.emit('sectionEnd', options, this);
if (++this.column > this.columns) {
if (this.height != null) {
return false;
}
this.document.addPage();
this.column = 1;
this.startY = this.document.page.margins.top;
this.maxY = this.document.page.maxY();
this.document.x = this.startX;
if (this.document._fillColor) {
(ref = this.document).fillColor.apply(ref, this.document._fillColor);
}
this.emit('pageBreak', options, this);
} else {
this.document.x += this.lineWidth + this.columnGap;
this.document.y = this.startY;
this.emit('columnBreak', options, this);
}
this.emit('sectionStart', options, this);
return true;
};
return LineWrapper;
})(EventEmitter);
module.exports = LineWrapper;
}).call(this);

@ -0,0 +1,265 @@
// Generated by CoffeeScript 1.12.5
(function() {
var KAPPA, SVGPath, number,
slice = [].slice;
SVGPath = require('../path');
number = require('../object').number;
KAPPA = 4.0 * ((Math.sqrt(2) - 1.0) / 3.0);
module.exports = {
initVector: function() {
this._ctm = [1, 0, 0, 1, 0, 0];
return this._ctmStack = [];
},
save: function() {
this._ctmStack.push(this._ctm.slice());
return this.addContent('q');
},
restore: function() {
this._ctm = this._ctmStack.pop() || [1, 0, 0, 1, 0, 0];
return this.addContent('Q');
},
closePath: function() {
return this.addContent('h');
},
lineWidth: function(w) {
return this.addContent((number(w)) + " w");
},
_CAP_STYLES: {
BUTT: 0,
ROUND: 1,
SQUARE: 2
},
lineCap: function(c) {
if (typeof c === 'string') {
c = this._CAP_STYLES[c.toUpperCase()];
}
return this.addContent(c + " J");
},
_JOIN_STYLES: {
MITER: 0,
ROUND: 1,
BEVEL: 2
},
lineJoin: function(j) {
if (typeof j === 'string') {
j = this._JOIN_STYLES[j.toUpperCase()];
}
return this.addContent(j + " j");
},
miterLimit: function(m) {
return this.addContent((number(m)) + " M");
},
dash: function(length, options) {
var phase, ref, space, v;
if (options == null) {
options = {};
}
if (length == null) {
return this;
}
if (Array.isArray(length)) {
length = ((function() {
var i, len, results;
results = [];
for (i = 0, len = length.length; i < len; i++) {
v = length[i];
results.push(number(v));
}
return results;
})()).join(' ');
phase = options.phase || 0;
return this.addContent("[" + length + "] " + (number(phase)) + " d");
} else {
space = (ref = options.space) != null ? ref : length;
phase = options.phase || 0;
return this.addContent("[" + (number(length)) + " " + (number(space)) + "] " + (number(phase)) + " d");
}
},
undash: function() {
return this.addContent("[] 0 d");
},
moveTo: function(x, y) {
return this.addContent((number(x)) + " " + (number(y)) + " m");
},
lineTo: function(x, y) {
return this.addContent((number(x)) + " " + (number(y)) + " l");
},
bezierCurveTo: function(cp1x, cp1y, cp2x, cp2y, x, y) {
return this.addContent((number(cp1x)) + " " + (number(cp1y)) + " " + (number(cp2x)) + " " + (number(cp2y)) + " " + (number(x)) + " " + (number(y)) + " c");
},
quadraticCurveTo: function(cpx, cpy, x, y) {
return this.addContent((number(cpx)) + " " + (number(cpy)) + " " + (number(x)) + " " + (number(y)) + " v");
},
rect: function(x, y, w, h) {
return this.addContent((number(x)) + " " + (number(y)) + " " + (number(w)) + " " + (number(h)) + " re");
},
roundedRect: function(x, y, w, h, r) {
var c;
if (r == null) {
r = 0;
}
r = Math.min(r, 0.5 * w, 0.5 * h);
c = r * (1.0 - KAPPA);
this.moveTo(x + r, y);
this.lineTo(x + w - r, y);
this.bezierCurveTo(x + w - c, y, x + w, y + c, x + w, y + r);
this.lineTo(x + w, y + h - r);
this.bezierCurveTo(x + w, y + h - c, x + w - c, y + h, x + w - r, y + h);
this.lineTo(x + r, y + h);
this.bezierCurveTo(x + c, y + h, x, y + h - c, x, y + h - r);
this.lineTo(x, y + r);
this.bezierCurveTo(x, y + c, x + c, y, x + r, y);
return this.closePath();
},
ellipse: function(x, y, r1, r2) {
var ox, oy, xe, xm, ye, ym;
if (r2 == null) {
r2 = r1;
}
x -= r1;
y -= r2;
ox = r1 * KAPPA;
oy = r2 * KAPPA;
xe = x + r1 * 2;
ye = y + r2 * 2;
xm = x + r1;
ym = y + r2;
this.moveTo(x, ym);
this.bezierCurveTo(x, ym - oy, xm - ox, y, xm, y);
this.bezierCurveTo(xm + ox, y, xe, ym - oy, xe, ym);
this.bezierCurveTo(xe, ym + oy, xm + ox, ye, xm, ye);
this.bezierCurveTo(xm - ox, ye, x, ym + oy, x, ym);
return this.closePath();
},
circle: function(x, y, radius) {
return this.ellipse(x, y, radius);
},
polygon: function() {
var i, len, point, points;
points = 1 <= arguments.length ? slice.call(arguments, 0) : [];
this.moveTo.apply(this, points.shift());
for (i = 0, len = points.length; i < len; i++) {
point = points[i];
this.lineTo.apply(this, point);
}
return this.closePath();
},
path: function(path) {
SVGPath.apply(this, path);
return this;
},
_windingRule: function(rule) {
if (/even-?odd/.test(rule)) {
return '*';
}
return '';
},
fill: function(color, rule) {
if (/(even-?odd)|(non-?zero)/.test(color)) {
rule = color;
color = null;
}
if (color) {
this.fillColor(color);
}
return this.addContent('f' + this._windingRule(rule));
},
stroke: function(color) {
if (color) {
this.strokeColor(color);
}
return this.addContent('S');
},
fillAndStroke: function(fillColor, strokeColor, rule) {
var isFillRule;
if (strokeColor == null) {
strokeColor = fillColor;
}
isFillRule = /(even-?odd)|(non-?zero)/;
if (isFillRule.test(fillColor)) {
rule = fillColor;
fillColor = null;
}
if (isFillRule.test(strokeColor)) {
rule = strokeColor;
strokeColor = fillColor;
}
if (fillColor) {
this.fillColor(fillColor);
this.strokeColor(strokeColor);
}
return this.addContent('B' + this._windingRule(rule));
},
clip: function(rule) {
return this.addContent('W' + this._windingRule(rule) + ' n');
},
transform: function(m11, m12, m21, m22, dx, dy) {
var m, m0, m1, m2, m3, m4, m5, v, values;
m = this._ctm;
m0 = m[0], m1 = m[1], m2 = m[2], m3 = m[3], m4 = m[4], m5 = m[5];
m[0] = m0 * m11 + m2 * m12;
m[1] = m1 * m11 + m3 * m12;
m[2] = m0 * m21 + m2 * m22;
m[3] = m1 * m21 + m3 * m22;
m[4] = m0 * dx + m2 * dy + m4;
m[5] = m1 * dx + m3 * dy + m5;
values = ((function() {
var i, len, ref, results;
ref = [m11, m12, m21, m22, dx, dy];
results = [];
for (i = 0, len = ref.length; i < len; i++) {
v = ref[i];
results.push(number(v));
}
return results;
})()).join(' ');
return this.addContent(values + " cm");
},
translate: function(x, y) {
return this.transform(1, 0, 0, 1, x, y);
},
rotate: function(angle, options) {
var cos, rad, ref, sin, x, x1, y, y1;
if (options == null) {
options = {};
}
rad = angle * Math.PI / 180;
cos = Math.cos(rad);
sin = Math.sin(rad);
x = y = 0;
if (options.origin != null) {
ref = options.origin, x = ref[0], y = ref[1];
x1 = x * cos - y * sin;
y1 = x * sin + y * cos;
x -= x1;
y -= y1;
}
return this.transform(cos, sin, -sin, cos, x, y);
},
scale: function(xFactor, yFactor, options) {
var ref, x, y;
if (yFactor == null) {
yFactor = xFactor;
}
if (options == null) {
options = {};
}
if (arguments.length === 2) {
yFactor = xFactor;
options = yFactor;
}
x = y = 0;
if (options.origin != null) {
ref = options.origin, x = ref[0], y = ref[1];
x -= xFactor * x;
y -= yFactor * y;
}
return this.transform(xFactor, 0, 0, yFactor, x, y);
}
};
}).call(this);

@ -0,0 +1,122 @@
// Generated by CoffeeScript 1.12.5
/*
PDFObject - converts JavaScript types into their corrisponding PDF types.
By Devon Govett
*/
(function() {
var PDFObject, PDFReference;
PDFObject = (function() {
var escapable, escapableRe, pad, swapBytes;
function PDFObject() {}
pad = function(str, length) {
return (Array(length + 1).join('0') + str).slice(-length);
};
PDFObject.pad = pad;
escapableRe = /[\n\r\t\b\f\(\)\\]/g;
PDFObject.escapableRe = escapableRe;
escapable = {
'\n': '\\n',
'\r': '\\r',
'\t': '\\t',
'\b': '\\b',
'\f': '\\f',
'\\': '\\\\',
'(': '\\(',
')': '\\)'
};
PDFObject.escapable = escapable;
swapBytes = function(buff) {
var a, i, j, l, ref;
l = buff.length;
if (l & 0x01) {
throw new Error("Buffer length must be even");
} else {
for (i = j = 0, ref = l - 1; j < ref; i = j += 2) {
a = buff[i];
buff[i] = buff[i + 1];
buff[i + 1] = a;
}
}
return buff;
};
PDFObject.swapBytes = swapBytes;
PDFObject.convert = function(object) {
var e, i, isUnicode, items, j, key, out, ref, string, val;
if (typeof object === 'string') {
return '/' + object;
} else if (object instanceof String) {
string = object.replace(escapableRe, function(c) {
return escapable[c];
});
isUnicode = false;
for (i = j = 0, ref = string.length; j < ref; i = j += 1) {
if (string.charCodeAt(i) > 0x7f) {
isUnicode = true;
break;
}
}
if (isUnicode) {
string = swapBytes(new Buffer('\ufeff' + string, 'utf16le')).toString('binary');
}
return '(' + string + ')';
} else if (Buffer.isBuffer(object)) {
return '<' + object.toString('hex') + '>';
} else if (object instanceof PDFReference) {
return object.toString();
} else if (object instanceof Date) {
return '(D:' + pad(object.getUTCFullYear(), 4) + pad(object.getUTCMonth() + 1, 2) + pad(object.getUTCDate(), 2) + pad(object.getUTCHours(), 2) + pad(object.getUTCMinutes(), 2) + pad(object.getUTCSeconds(), 2) + 'Z)';
} else if (Array.isArray(object)) {
items = ((function() {
var k, len, results;
results = [];
for (k = 0, len = object.length; k < len; k++) {
e = object[k];
results.push(PDFObject.convert(e));
}
return results;
})()).join(' ');
return '[' + items + ']';
} else if ({}.toString.call(object) === '[object Object]') {
out = ['<<'];
for (key in object) {
val = object[key];
out.push('/' + key + ' ' + PDFObject.convert(val));
}
out.push('>>');
return out.join('\n');
} else if (typeof object === 'number') {
return PDFObject.number(object);
} else {
return '' + object;
}
};
PDFObject.number = function(n) {
if (n > -1e21 && n < 1e21) {
return Math.round(n * 1e6) / 1e6;
}
throw new Error("unsupported number: " + n);
};
return PDFObject;
})();
module.exports = PDFObject;
PDFReference = require('./reference');
}).call(this);

@ -0,0 +1,170 @@
// Generated by CoffeeScript 1.12.5
/*
PDFPage - represents a single page in the PDF document
By Devon Govett
*/
(function() {
var PDFPage;
PDFPage = (function() {
var DEFAULT_MARGINS, SIZES;
function PDFPage(document, options) {
var dimensions;
this.document = document;
if (options == null) {
options = {};
}
this.size = options.size || 'letter';
this.layout = options.layout || 'portrait';
if (typeof options.margin === 'number') {
this.margins = {
top: options.margin,
left: options.margin,
bottom: options.margin,
right: options.margin
};
} else {
this.margins = options.margins || DEFAULT_MARGINS;
}
dimensions = Array.isArray(this.size) ? this.size : SIZES[this.size.toUpperCase()];
this.width = dimensions[this.layout === 'portrait' ? 0 : 1];
this.height = dimensions[this.layout === 'portrait' ? 1 : 0];
this.content = this.document.ref();
this.resources = this.document.ref({
ProcSet: ['PDF', 'Text', 'ImageB', 'ImageC', 'ImageI']
});
Object.defineProperties(this, {
fonts: {
get: (function(_this) {
return function() {
var base;
return (base = _this.resources.data).Font != null ? base.Font : base.Font = {};
};
})(this)
},
xobjects: {
get: (function(_this) {
return function() {
var base;
return (base = _this.resources.data).XObject != null ? base.XObject : base.XObject = {};
};
})(this)
},
ext_gstates: {
get: (function(_this) {
return function() {
var base;
return (base = _this.resources.data).ExtGState != null ? base.ExtGState : base.ExtGState = {};
};
})(this)
},
patterns: {
get: (function(_this) {
return function() {
var base;
return (base = _this.resources.data).Pattern != null ? base.Pattern : base.Pattern = {};
};
})(this)
},
annotations: {
get: (function(_this) {
return function() {
var base;
return (base = _this.dictionary.data).Annots != null ? base.Annots : base.Annots = [];
};
})(this)
}
});
this.dictionary = this.document.ref({
Type: 'Page',
Parent: this.document._root.data.Pages,
MediaBox: [0, 0, this.width, this.height],
Contents: this.content,
Resources: this.resources
});
}
PDFPage.prototype.maxY = function() {
return this.height - this.margins.bottom;
};
PDFPage.prototype.write = function(chunk) {
return this.content.write(chunk);
};
PDFPage.prototype.end = function() {
this.dictionary.end();
this.resources.end();
return this.content.end();
};
DEFAULT_MARGINS = {
top: 72,
left: 72,
bottom: 72,
right: 72
};
SIZES = {
'4A0': [4767.87, 6740.79],
'2A0': [3370.39, 4767.87],
A0: [2383.94, 3370.39],
A1: [1683.78, 2383.94],
A2: [1190.55, 1683.78],
A3: [841.89, 1190.55],
A4: [595.28, 841.89],
A5: [419.53, 595.28],
A6: [297.64, 419.53],
A7: [209.76, 297.64],
A8: [147.40, 209.76],
A9: [104.88, 147.40],
A10: [73.70, 104.88],
B0: [2834.65, 4008.19],
B1: [2004.09, 2834.65],
B2: [1417.32, 2004.09],
B3: [1000.63, 1417.32],
B4: [708.66, 1000.63],
B5: [498.90, 708.66],
B6: [354.33, 498.90],
B7: [249.45, 354.33],
B8: [175.75, 249.45],
B9: [124.72, 175.75],
B10: [87.87, 124.72],
C0: [2599.37, 3676.54],
C1: [1836.85, 2599.37],
C2: [1298.27, 1836.85],
C3: [918.43, 1298.27],
C4: [649.13, 918.43],
C5: [459.21, 649.13],
C6: [323.15, 459.21],
C7: [229.61, 323.15],
C8: [161.57, 229.61],
C9: [113.39, 161.57],
C10: [79.37, 113.39],
RA0: [2437.80, 3458.27],
RA1: [1729.13, 2437.80],
RA2: [1218.90, 1729.13],
RA3: [864.57, 1218.90],
RA4: [609.45, 864.57],
SRA0: [2551.18, 3628.35],
SRA1: [1814.17, 2551.18],
SRA2: [1275.59, 1814.17],
SRA3: [907.09, 1275.59],
SRA4: [637.80, 907.09],
EXECUTIVE: [521.86, 756.00],
FOLIO: [612.00, 936.00],
LEGAL: [612.00, 1008.00],
LETTER: [612.00, 792.00],
TABLOID: [792.00, 1224.00]
};
return PDFPage;
})();
module.exports = PDFPage;
}).call(this);

@ -0,0 +1,366 @@
// Generated by CoffeeScript 1.12.5
(function() {
var SVGPath;
SVGPath = (function() {
var apply, arcToSegments, cx, cy, parameters, parse, px, py, runners, segmentToBezier, solveArc, sx, sy;
function SVGPath() {}
SVGPath.apply = function(doc, path) {
var commands;
commands = parse(path);
return apply(commands, doc);
};
parameters = {
A: 7,
a: 7,
C: 6,
c: 6,
H: 1,
h: 1,
L: 2,
l: 2,
M: 2,
m: 2,
Q: 4,
q: 4,
S: 4,
s: 4,
T: 2,
t: 2,
V: 1,
v: 1,
Z: 0,
z: 0
};
parse = function(path) {
var args, c, cmd, curArg, foundDecimal, j, len, params, ret;
ret = [];
args = [];
curArg = "";
foundDecimal = false;
params = 0;
for (j = 0, len = path.length; j < len; j++) {
c = path[j];
if (parameters[c] != null) {
params = parameters[c];
if (cmd) {
if (curArg.length > 0) {
args[args.length] = +curArg;
}
ret[ret.length] = {
cmd: cmd,
args: args
};
args = [];
curArg = "";
foundDecimal = false;
}
cmd = c;
} else if ((c === " " || c === ",") || (c === "-" && curArg.length > 0 && curArg[curArg.length - 1] !== 'e') || (c === "." && foundDecimal)) {
if (curArg.length === 0) {
continue;
}
if (args.length === params) {
ret[ret.length] = {
cmd: cmd,
args: args
};
args = [+curArg];
if (cmd === "M") {
cmd = "L";
}
if (cmd === "m") {
cmd = "l";
}
} else {
args[args.length] = +curArg;
}
foundDecimal = c === ".";
curArg = c === '-' || c === '.' ? c : '';
} else {
curArg += c;
if (c === '.') {
foundDecimal = true;
}
}
}
if (curArg.length > 0) {
if (args.length === params) {
ret[ret.length] = {
cmd: cmd,
args: args
};
args = [+curArg];
if (cmd === "M") {
cmd = "L";
}
if (cmd === "m") {
cmd = "l";
}
} else {
args[args.length] = +curArg;
}
}
ret[ret.length] = {
cmd: cmd,
args: args
};
return ret;
};
cx = cy = px = py = sx = sy = 0;
apply = function(commands, doc) {
var c, i, j, len, name;
cx = cy = px = py = sx = sy = 0;
for (i = j = 0, len = commands.length; j < len; i = ++j) {
c = commands[i];
if (typeof runners[name = c.cmd] === "function") {
runners[name](doc, c.args);
}
}
return cx = cy = px = py = 0;
};
runners = {
M: function(doc, a) {
cx = a[0];
cy = a[1];
px = py = null;
sx = cx;
sy = cy;
return doc.moveTo(cx, cy);
},
m: function(doc, a) {
cx += a[0];
cy += a[1];
px = py = null;
sx = cx;
sy = cy;
return doc.moveTo(cx, cy);
},
C: function(doc, a) {
cx = a[4];
cy = a[5];
px = a[2];
py = a[3];
return doc.bezierCurveTo.apply(doc, a);
},
c: function(doc, a) {
doc.bezierCurveTo(a[0] + cx, a[1] + cy, a[2] + cx, a[3] + cy, a[4] + cx, a[5] + cy);
px = cx + a[2];
py = cy + a[3];
cx += a[4];
return cy += a[5];
},
S: function(doc, a) {
if (px === null) {
px = cx;
py = cy;
}
doc.bezierCurveTo(cx - (px - cx), cy - (py - cy), a[0], a[1], a[2], a[3]);
px = a[0];
py = a[1];
cx = a[2];
return cy = a[3];
},
s: function(doc, a) {
if (px === null) {
px = cx;
py = cy;
}
doc.bezierCurveTo(cx - (px - cx), cy - (py - cy), cx + a[0], cy + a[1], cx + a[2], cy + a[3]);
px = cx + a[0];
py = cy + a[1];
cx += a[2];
return cy += a[3];
},
Q: function(doc, a) {
px = a[0];
py = a[1];
cx = a[2];
cy = a[3];
return doc.quadraticCurveTo(a[0], a[1], cx, cy);
},
q: function(doc, a) {
doc.quadraticCurveTo(a[0] + cx, a[1] + cy, a[2] + cx, a[3] + cy);
px = cx + a[0];
py = cy + a[1];
cx += a[2];
return cy += a[3];
},
T: function(doc, a) {
if (px === null) {
px = cx;
py = cy;
} else {
px = cx - (px - cx);
py = cy - (py - cy);
}
doc.quadraticCurveTo(px, py, a[0], a[1]);
px = cx - (px - cx);
py = cy - (py - cy);
cx = a[0];
return cy = a[1];
},
t: function(doc, a) {
if (px === null) {
px = cx;
py = cy;
} else {
px = cx - (px - cx);
py = cy - (py - cy);
}
doc.quadraticCurveTo(px, py, cx + a[0], cy + a[1]);
cx += a[0];
return cy += a[1];
},
A: function(doc, a) {
solveArc(doc, cx, cy, a);
cx = a[5];
return cy = a[6];
},
a: function(doc, a) {
a[5] += cx;
a[6] += cy;
solveArc(doc, cx, cy, a);
cx = a[5];
return cy = a[6];
},
L: function(doc, a) {
cx = a[0];
cy = a[1];
px = py = null;
return doc.lineTo(cx, cy);
},
l: function(doc, a) {
cx += a[0];
cy += a[1];
px = py = null;
return doc.lineTo(cx, cy);
},
H: function(doc, a) {
cx = a[0];
px = py = null;
return doc.lineTo(cx, cy);
},
h: function(doc, a) {
cx += a[0];
px = py = null;
return doc.lineTo(cx, cy);
},
V: function(doc, a) {
cy = a[0];
px = py = null;
return doc.lineTo(cx, cy);
},
v: function(doc, a) {
cy += a[0];
px = py = null;
return doc.lineTo(cx, cy);
},
Z: function(doc) {
doc.closePath();
cx = sx;
return cy = sy;
},
z: function(doc) {
doc.closePath();
cx = sx;
return cy = sy;
}
};
solveArc = function(doc, x, y, coords) {
var bez, ex, ey, j, large, len, results, rot, rx, ry, seg, segs, sweep;
rx = coords[0], ry = coords[1], rot = coords[2], large = coords[3], sweep = coords[4], ex = coords[5], ey = coords[6];
segs = arcToSegments(ex, ey, rx, ry, large, sweep, rot, x, y);
results = [];
for (j = 0, len = segs.length; j < len; j++) {
seg = segs[j];
bez = segmentToBezier.apply(null, seg);
results.push(doc.bezierCurveTo.apply(doc, bez));
}
return results;
};
arcToSegments = function(x, y, rx, ry, large, sweep, rotateX, ox, oy) {
var a00, a01, a10, a11, cos_th, d, i, j, pl, ref, result, segments, sfactor, sfactor_sq, sin_th, th, th0, th1, th2, th3, th_arc, x0, x1, xc, y0, y1, yc;
th = rotateX * (Math.PI / 180);
sin_th = Math.sin(th);
cos_th = Math.cos(th);
rx = Math.abs(rx);
ry = Math.abs(ry);
px = cos_th * (ox - x) * 0.5 + sin_th * (oy - y) * 0.5;
py = cos_th * (oy - y) * 0.5 - sin_th * (ox - x) * 0.5;
pl = (px * px) / (rx * rx) + (py * py) / (ry * ry);
if (pl > 1) {
pl = Math.sqrt(pl);
rx *= pl;
ry *= pl;
}
a00 = cos_th / rx;
a01 = sin_th / rx;
a10 = (-sin_th) / ry;
a11 = cos_th / ry;
x0 = a00 * ox + a01 * oy;
y0 = a10 * ox + a11 * oy;
x1 = a00 * x + a01 * y;
y1 = a10 * x + a11 * y;
d = (x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0);
sfactor_sq = 1 / d - 0.25;
if (sfactor_sq < 0) {
sfactor_sq = 0;
}
sfactor = Math.sqrt(sfactor_sq);
if (sweep === large) {
sfactor = -sfactor;
}
xc = 0.5 * (x0 + x1) - sfactor * (y1 - y0);
yc = 0.5 * (y0 + y1) + sfactor * (x1 - x0);
th0 = Math.atan2(y0 - yc, x0 - xc);
th1 = Math.atan2(y1 - yc, x1 - xc);
th_arc = th1 - th0;
if (th_arc < 0 && sweep === 1) {
th_arc += 2 * Math.PI;
} else if (th_arc > 0 && sweep === 0) {
th_arc -= 2 * Math.PI;
}
segments = Math.ceil(Math.abs(th_arc / (Math.PI * 0.5 + 0.001)));
result = [];
for (i = j = 0, ref = segments; 0 <= ref ? j < ref : j > ref; i = 0 <= ref ? ++j : --j) {
th2 = th0 + i * th_arc / segments;
th3 = th0 + (i + 1) * th_arc / segments;
result[i] = [xc, yc, th2, th3, rx, ry, sin_th, cos_th];
}
return result;
};
segmentToBezier = function(cx, cy, th0, th1, rx, ry, sin_th, cos_th) {
var a00, a01, a10, a11, t, th_half, x1, x2, x3, y1, y2, y3;
a00 = cos_th * rx;
a01 = -sin_th * ry;
a10 = sin_th * rx;
a11 = cos_th * ry;
th_half = 0.5 * (th1 - th0);
t = (8 / 3) * Math.sin(th_half * 0.5) * Math.sin(th_half * 0.5) / Math.sin(th_half);
x1 = cx + Math.cos(th0) - t * Math.sin(th0);
y1 = cy + Math.sin(th0) + t * Math.cos(th0);
x3 = cx + Math.cos(th1);
y3 = cy + Math.sin(th1);
x2 = x3 + t * Math.sin(th1);
y2 = y3 - t * Math.cos(th1);
return [a00 * x1 + a01 * y1, a10 * x1 + a11 * y1, a00 * x2 + a01 * y2, a10 * x2 + a11 * y2, a00 * x3 + a01 * y3, a10 * x3 + a11 * y3];
};
return SVGPath;
})();
module.exports = SVGPath;
}).call(this);

@ -0,0 +1,117 @@
// Generated by CoffeeScript 1.12.5
/*
PDFReference - represents a reference to another object in the PDF object heirarchy
By Devon Govett
*/
(function() {
var PDFObject, PDFReference, stream, zlib,
bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
hasProp = {}.hasOwnProperty;
zlib = require('zlib');
stream = require('stream');
PDFReference = (function(superClass) {
extend(PDFReference, superClass);
function PDFReference(document, id, data) {
this.document = document;
this.id = id;
this.data = data != null ? data : {};
this.finalize = bind(this.finalize, this);
PDFReference.__super__.constructor.call(this, {
decodeStrings: false
});
this.gen = 0;
this.deflate = null;
this.compress = false;
this.uncompressedLength = 0;
this.chunks = [];
}
PDFReference.prototype.initDeflate = function() {
this.data.Filter = 'FlateDecode';
this.deflate = zlib.createDeflate();
this.deflate.on('data', (function(_this) {
return function(chunk) {
console.log("got data event for ref " + _this.id + " from " + _this.toString());
_this.chunks.push(chunk);
return _this.data.Length += chunk.length;
};
})(this));
return this.deflate.on('end', (function(_this) {
return function() {
console.log("got end event for ref " + _this.id + " from " + _this.toString());
return _this.finalize();
};
})(this));
};
PDFReference.prototype._write = function(chunk, encoding, callback) {
var base;
if (!Buffer.isBuffer(chunk)) {
chunk = new Buffer(chunk + '\n', 'binary');
}
this.uncompressedLength += chunk.length;
if ((base = this.data).Length == null) {
base.Length = 0;
}
if (this.compress) {
if (!this.deflate) {
this.initDeflate();
}
console.log("chunk = " + chunk);
this.deflate.write(chunk);
console.log("wrote chunk");
} else {
this.chunks.push(chunk);
this.data.Length += chunk.length;
}
return callback();
};
PDFReference.prototype.end = function(chunk) {
PDFReference.__super__.end.apply(this, arguments);
if (this.deflate) {
return this.deflate.end();
} else {
return this.finalize();
}
};
PDFReference.prototype.finalize = function() {
var chunk, i, len, ref;
this.offset = this.document._offset;
this.document._write(this.id + " " + this.gen + " obj");
this.document._write(PDFObject.convert(this.data));
if (this.chunks.length) {
this.document._write('stream');
ref = this.chunks;
for (i = 0, len = ref.length; i < len; i++) {
chunk = ref[i];
this.document._write(chunk);
}
this.chunks.length = 0;
this.document._write('\nendstream');
}
this.document._write('endobj');
return this.document._refEnd(this);
};
PDFReference.prototype.toString = function() {
return this.id + " " + this.gen + " R";
};
return PDFReference;
})(stream.Writable);
module.exports = PDFReference;
PDFObject = require('./object');
}).call(this);

@ -90,7 +90,7 @@
(public [@_doOpacity doOpacity])
(define (@_doOpacity fillOpacity strokeOpacity)
(error 'bonk))
(send this addContent "")) ; todo
))

@ -102,7 +102,7 @@
;; create a page object
(set! @page (make-object PDFPage this options))
(push! @_pageBuffer @page)
(push-end! @_pageBuffer @page)
;; add the page to the object store
(define pages (· @_root data Pages data))
(hash-update! pages 'Kids (λ (val) (cons (· @page dictionary) val)) null)

@ -77,4 +77,19 @@
(module+ test
(check-equal? (number 4.5) "4.5")
(check-equal? (number 4.0) "4")
(check-equal? (number 4) "4"))
(check-equal? (number 4) "4"))
(define-syntax (send*/fold stx)
(syntax-case stx ()
[(_ o) #'o]
[(_ o [m0 . args0] [m . args] ...)
#'(send*/fold (send o m0 . args0) [m . args] ...)]))
(module+ test
(define SFC (class object%
(super-new)
(field [sum 0])
(define/public (add x) (set! sum (+ sum x)) this)))
(define sfo (new SFC))
(check-equal? (get-field sum (send*/fold sfo [add 1] [add 2] [add 3])) 6))

@ -33,7 +33,7 @@
(cond
[@compress (when (not @deflate) (@initDeflate))
(send @deflate write chunk)]
[else (push! @chunks chunk)
[else (push-end! @chunks chunk)
(hash-update! @data 'Length (λ (len) (+ len (buffer-length chunk))))])
(callback))

@ -3,6 +3,10 @@
(provide vector-mixin)
(require "helper.rkt")
;; This constant is used to approximate a symmetrical arc using a cubic
;; Bezier curve.
(define KAPPA (* 4 (/ (- (sqrt 2) 1) 3.0)))
(define default-ctm-value '(1 0 0 1 0 0))
(define (vector-mixin %)
@ -22,28 +26,54 @@
(define/public (restore)
(set! @_ctm (if (pair? @_ctmStack) (pop! @_ctmStack) default-ctm-value))
(send this addContent "Q"))
(define/public (transform m11 m12 m21 m22 dx dy #:debug [debug #f])
;; keep track of the current transformation matrix
(match-define (list m0 m1 m2 m3 m4 m5) @_ctm)
(set! @_ctm (list (+ (* m0 m11) (* m2 m12))
(+ (* m1 m11) (* m3 m12))
(+ (* m0 m21) (* m2 m22))
(+ (* m1 m21) (* m3 m22))
(+ (* m0 dx) (* m2 dy) m4)
(+ (* m1 dx) (* m3 dy) m5)))
(define values (string-join (map number (list m11 m12 m21 m22 dx dy)) " "))
(define result (format "~a cm" values))
(if debug
result
(send this addContent result)))
(define/public (moveTo x y)
(define (@closePath)
(send this addContent "h"))
(public [@moveTo moveTo])
(define (@moveTo x y)
(send this addContent (format "~a ~a m" x y)))
(define/public (lineTo x y)
(public [@lineTo lineTo])
(define (@lineTo x y)
(send this addContent (format "~a ~a l" x y)))
(public [@bezierCurveTo bezierCurveTo])
(define (@bezierCurveTo cp1x cp1y cp2x cp2y x y)
(send this addContent (format "~a ~a ~a ~a ~a ~a c" cp1x cp1y cp2x cp2y x y)))
(public [@ellipse ellipse])
(define (@ellipse x y r1 [r2 r1])
;; based on http://stackoverflow.com/questions/2172798/how-to-draw-an-oval-in-html5-canvas/2173084#2173084
(-= x r1)
(-= y r2)
(define ox (* r1 KAPPA))
(define oy (* r2 KAPPA))
(define xe (+ x (* r1 2)))
(define ye (+ y (* r2 2)))
(define xm (+ x r1))
(define ym (+ y r2))
(@moveTo x ym)
(@bezierCurveTo x (- ym oy) (- xm ox) y xm y)
(@bezierCurveTo (+ xm ox) y xe (- ym oy) xe ym)
(@bezierCurveTo xe (+ ym oy) (+ xm ox) ye xm ye)
(@bezierCurveTo (- xm ox) ye x (+ ym oy) x ym)
(@closePath))
(public [@circle circle])
(define (@circle x y radius)
(@ellipse x y radius))
(public [@path path])
(define (@path path)
;; SVGPath.apply this, path ; todo
this)
(public [@_windingRule _windingRule])
(define (@_windingRule rule)
(if (and (string? rule) (regexp-match #rx"^even-?odd$" rule))
@ -57,6 +87,43 @@
(when color (send this fillColor color)) ;; fillColor method is from color mixin
(send this addContent (format "f~a" (@_windingRule rule))))
(public [@transform transform])
(define (@transform m11 m12 m21 m22 dx dy #:debug [debug #f])
;; keep track of the current transformation matrix
(match-define (list m0 m1 m2 m3 m4 m5) @_ctm)
(set! @_ctm (list (+ (* m0 m11) (* m2 m12))
(+ (* m1 m11) (* m3 m12))
(+ (* m0 m21) (* m2 m22))
(+ (* m1 m21) (* m3 m22))
(+ (* m0 dx) (* m2 dy) m4)
(+ (* m1 dx) (* m3 dy) m5)))
(define values (string-join (map number (list m11 m12 m21 m22 dx dy)) " "))
(define result (format "~a cm" values))
(if debug
result
(send this addContent result)))
(public [@translate translate])
(define (@translate x y)
(@transform 1 0 0 1 x y))
(public [@scale scale])
(define @scale
(match-lambda*
[(list (? number? xFactor)) (@scale xFactor (mhash))]
[(list (? number? xFactor) (? hash? options)) (@scale xFactor xFactor options)]
[(list (? number? xFactor) (? number? yFactor)) (@scale xFactor yFactor (mhash))]
[(list (? number? xFactor) (? number? yFactor) (? hash? options))
(define x 0) (define y 0)
(when (hash-ref options 'origin #f)
(match-define (list x y) (hash-ref options 'origin))
(-= x (* x xFactor))
(-= y (* y yFactor)))
(@transform xFactor 0 0 yFactor x y)]))
))
(module+ test

@ -15,10 +15,4 @@ doc.save()
doc.circle(280, 200, 50)
.fill("#6600FF")
doc.scale(0.6)
.translate(470, -380)
.path('M 250,75 L 323,301 131,161 369,161 177,301 z') # render an SVG path
.fill('red', 'even-odd') # fill using the even-odd winding rule
.restore()
doc.end()

@ -25,7 +25,7 @@ endobj
endobj
3 0 obj
<<
/Length 421
/Length 294
>>
stream
1 0 0 -1 0 792 cm
@ -47,19 +47,6 @@ h
0.4 0 1 scn
/Gs1 gs
f
0.6 0 0 0.6 0 0 cm
1 0 0 1 470 -380 cm
250 75 m
323 301 l
131 161 l
369 161 l
177 301 l
h
/DeviceRGB cs
1 0 0 scn
/Gs1 gs
f*
Q
endstream
endobj
@ -67,7 +54,7 @@ endobj
<<
/Producer (PDFKit)
/Creator (PDFKit)
/CreationDate (D:20170513192922Z)
/CreationDate (D:20170514013102Z)
>>
endobj
2 0 obj
@ -86,13 +73,13 @@ endobj
xref
0 8
0000000000 65535 f
0000000871 00000 n
0000000822 00000 n
0000000744 00000 n
0000000695 00000 n
0000000258 00000 n
0000000163 00000 n
0000000059 00000 n
0000000015 00000 n
0000000730 00000 n
0000000603 00000 n
trailer
<<
/Size 8
@ -100,5 +87,5 @@ trailer
/Info 7 0 R
>>
startxref
928
801
%%EOF

@ -1,18 +1,18 @@
#lang br
(require pitfall/kit/document)
(require pitfall/kit/document pitfall/kit/helper)
;; Create a new PDFDocument
(define doc (new PDFDocument))
(send doc pipe (open-output-file "test1rkt.pdf" #:exists 'replace))
;; Draw a triangle and a circle
(send (send (send (send (send doc save) moveTo 100 150) lineTo 100 250) lineTo 200 250) fill "#FF3300")
(send*/fold doc [save]
[moveTo 100 150]
[lineTo 100 250]
[lineTo 200 250]
[fill "#FF3300"])
(send (send doc circle 280 200 50) fill "#6600FF")
;; render an SVG path
;; fill using the even-odd winding rule
(send (send (send (send (send doc scale 0.6) translate 470 -380) path "M 250,75 L 323,301 131,161 369,161 177,301 z") fill "red" "even-odd") restore)
(send*/fold doc [circle 280 200 50] [fill "#6600FF"])
(send doc end)

@ -0,0 +1,81 @@
%PDF-1.3
%ÿÿÿÿ
5 0 obj
<<
/Parent 1 0 R
/Resources 4 0 R
/Contents 3 0 R
/MediaBox [0 0 612 792]
/Type /Page
>>
endobj
4 0 obj
<<
/ProcSet [/PDF /Text /ImageB /ImageC /ImageI]
>>
endobj
3 0 obj
<<
/Length 344
>>
stream
1 0 0 -1 0 792 cm
q
100 150 m
100 250 l
200 250 l
/DeviceRGB cs
1 0.2 0 scn
f
230 200 m
230 172.38576250846032 252.38576250846032 150 280 150 c
307.61423749153965 150 330 172.38576250846032 330 200 c
330 227.61423749153968 307.61423749153965 250 280 250 c
252.38576250846032 250 230 227.61423749153968 230 200 c
h
/DeviceRGB cs
0.4 0 1 scn
f
endstream
endobj
6 0 obj
<<
/CreationDate (D:19700101000000Z)
/Creator (PitfallKit)
/Producer (PitfallKit)
>>
endobj
2 0 obj
<<
/Pages 1 0 R
/Type /Catalog
>>
endobj
1 0 obj
<<
/Kids [5 0 R]
/Count 1
/Type /Pages
>>
endobj
xref
0 7
0000000000 65535 f
0000000730 00000 n
0000000681 00000 n
0000000186 00000 n
0000000119 00000 n
0000000015 00000 n
0000000581 00000 n
trailer
<<
/Info 6 0 R
/Root 2 0 R
/Size 7
>>
startxref
787
%%EOF
Loading…
Cancel
Save