diff --git a/pitfall/pdfkit/lib/mixins/annotations.js b/pitfall/pdfkit/lib/mixins/annotations.js new file mode 100644 index 00000000..4eb88b31 --- /dev/null +++ b/pitfall/pdfkit/lib/mixins/annotations.js @@ -0,0 +1,133 @@ +// Generated by CoffeeScript 1.12.5 +(function() { + module.exports = { + annotate: function(x, y, w, h, options) { + var key, ref, val; + options.Type = 'Annot'; + options.Rect = this._convertRect(x, y, w, h); + options.Border = [0, 0, 0]; + if (options.Subtype !== 'Link') { + if (options.C == null) { + options.C = this._normalizeColor(options.color || [0, 0, 0]); + } + } + delete options.color; + if (typeof options.Dest === 'string') { + options.Dest = new String(options.Dest); + } + for (key in options) { + val = options[key]; + options[key[0].toUpperCase() + key.slice(1)] = val; + } + ref = this.ref(options); + this.page.annotations.push(ref); + ref.end(); + return this; + }, + note: function(x, y, w, h, contents, options) { + if (options == null) { + options = {}; + } + options.Subtype = 'Text'; + options.Contents = new String(contents); + options.Name = 'Comment'; + if (options.color == null) { + options.color = [243, 223, 92]; + } + return this.annotate(x, y, w, h, options); + }, + link: function(x, y, w, h, url, options) { + if (options == null) { + options = {}; + } + options.Subtype = 'Link'; + options.A = this.ref({ + S: 'URI', + URI: new String(url) + }); + options.A.end(); + return this.annotate(x, y, w, h, options); + }, + _markup: function(x, y, w, h, options) { + var ref1, x1, x2, y1, y2; + if (options == null) { + options = {}; + } + ref1 = this._convertRect(x, y, w, h), x1 = ref1[0], y1 = ref1[1], x2 = ref1[2], y2 = ref1[3]; + options.QuadPoints = [x1, y2, x2, y2, x1, y1, x2, y1]; + options.Contents = new String; + return this.annotate(x, y, w, h, options); + }, + highlight: function(x, y, w, h, options) { + if (options == null) { + options = {}; + } + options.Subtype = 'Highlight'; + if (options.color == null) { + options.color = [241, 238, 148]; + } + return this._markup(x, y, w, h, options); + }, + underline: function(x, y, w, h, options) { + if (options == null) { + options = {}; + } + options.Subtype = 'Underline'; + return this._markup(x, y, w, h, options); + }, + strike: function(x, y, w, h, options) { + if (options == null) { + options = {}; + } + options.Subtype = 'StrikeOut'; + return this._markup(x, y, w, h, options); + }, + lineAnnotation: function(x1, y1, x2, y2, options) { + if (options == null) { + options = {}; + } + options.Subtype = 'Line'; + options.Contents = new String; + options.L = [x1, this.page.height - y1, x2, this.page.height - y2]; + return this.annotate(x1, y1, x2, y2, options); + }, + rectAnnotation: function(x, y, w, h, options) { + if (options == null) { + options = {}; + } + options.Subtype = 'Square'; + options.Contents = new String; + return this.annotate(x, y, w, h, options); + }, + ellipseAnnotation: function(x, y, w, h, options) { + if (options == null) { + options = {}; + } + options.Subtype = 'Circle'; + options.Contents = new String; + return this.annotate(x, y, w, h, options); + }, + textAnnotation: function(x, y, w, h, text, options) { + if (options == null) { + options = {}; + } + options.Subtype = 'FreeText'; + options.Contents = new String(text); + options.DA = new String; + return this.annotate(x, y, w, h, options); + }, + _convertRect: function(x1, y1, w, h) { + var m0, m1, m2, m3, m4, m5, ref1, x2, y2; + y2 = y1; + y1 += h; + x2 = x1 + w; + ref1 = this._ctm, m0 = ref1[0], m1 = ref1[1], m2 = ref1[2], m3 = ref1[3], m4 = ref1[4], m5 = ref1[5]; + x1 = m0 * x1 + m2 * y1 + m4; + y1 = m1 * x1 + m3 * y1 + m5; + x2 = m0 * x2 + m2 * y2 + m4; + y2 = m1 * x2 + m3 * y2 + m5; + return [x1, y1, x2, y2]; + } + }; + +}).call(this); diff --git a/pitfall/pdfkit/lib/mixins/color.js b/pitfall/pdfkit/lib/mixins/color.js new file mode 100644 index 00000000..5dd8bc4e --- /dev/null +++ b/pitfall/pdfkit/lib/mixins/color.js @@ -0,0 +1,304 @@ +// Generated by CoffeeScript 1.12.5 +(function() { + var PDFGradient, PDFLinearGradient, PDFRadialGradient, namedColors, ref; + + ref = require('../gradient'), PDFGradient = ref.PDFGradient, PDFLinearGradient = ref.PDFLinearGradient, PDFRadialGradient = ref.PDFRadialGradient; + + module.exports = { + initColor: function() { + this._opacityRegistry = {}; + this._opacityCount = 0; + return this._gradCount = 0; + }, + _normalizeColor: function(color) { + var hex, part; + if (color instanceof PDFGradient) { + return color; + } + if (typeof color === 'string') { + if (color.charAt(0) === '#') { + if (color.length === 4) { + color = color.replace(/#([0-9A-F])([0-9A-F])([0-9A-F])/i, "#$1$1$2$2$3$3"); + } + hex = parseInt(color.slice(1), 16); + color = [hex >> 16, hex >> 8 & 0xff, hex & 0xff]; + } else if (namedColors[color]) { + color = namedColors[color]; + } + } + if (Array.isArray(color)) { + if (color.length === 3) { + color = (function() { + var i, len, results; + results = []; + for (i = 0, len = color.length; i < len; i++) { + part = color[i]; + results.push(part / 255); + } + return results; + })(); + } else if (color.length === 4) { + color = (function() { + var i, len, results; + results = []; + for (i = 0, len = color.length; i < len; i++) { + part = color[i]; + results.push(part / 100); + } + return results; + })(); + } + return color; + } + return null; + }, + _setColor: function(color, stroke) { + var op, space; + color = this._normalizeColor(color); + if (!color) { + return false; + } + op = stroke ? 'SCN' : 'scn'; + if (color instanceof PDFGradient) { + this._setColorSpace('Pattern', stroke); + color.apply(op); + } else { + space = color.length === 4 ? 'DeviceCMYK' : 'DeviceRGB'; + this._setColorSpace(space, stroke); + color = color.join(' '); + this.addContent(color + " " + op); + } + return true; + }, + _setColorSpace: function(space, stroke) { + var op; + op = stroke ? 'CS' : 'cs'; + return this.addContent("/" + space + " " + op); + }, + fillColor: function(color, opacity) { + var set; + if (opacity == null) { + opacity = 1; + } + set = this._setColor(color, false); + if (set) { + this.fillOpacity(opacity); + } + this._fillColor = [color, opacity]; + return this; + }, + strokeColor: function(color, opacity) { + var set; + if (opacity == null) { + opacity = 1; + } + set = this._setColor(color, true); + if (set) { + this.strokeOpacity(opacity); + } + return this; + }, + opacity: function(opacity) { + this._doOpacity(opacity, opacity); + return this; + }, + fillOpacity: function(opacity) { + this._doOpacity(opacity, null); + return this; + }, + strokeOpacity: function(opacity) { + this._doOpacity(null, opacity); + return this; + }, + _doOpacity: function(fillOpacity, strokeOpacity) { + var dictionary, id, key, name, ref1; + if (!((fillOpacity != null) || (strokeOpacity != null))) { + return; + } + if (fillOpacity != null) { + fillOpacity = Math.max(0, Math.min(1, fillOpacity)); + } + if (strokeOpacity != null) { + strokeOpacity = Math.max(0, Math.min(1, strokeOpacity)); + } + key = fillOpacity + "_" + strokeOpacity; + if (this._opacityRegistry[key]) { + ref1 = this._opacityRegistry[key], dictionary = ref1[0], name = ref1[1]; + } else { + dictionary = { + Type: 'ExtGState' + }; + if (fillOpacity != null) { + dictionary.ca = fillOpacity; + } + if (strokeOpacity != null) { + dictionary.CA = strokeOpacity; + } + dictionary = this.ref(dictionary); + dictionary.end(); + id = ++this._opacityCount; + name = "Gs" + id; + this._opacityRegistry[key] = [dictionary, name]; + } + this.page.ext_gstates[name] = dictionary; + return this.addContent("/" + name + " gs"); + }, + linearGradient: function(x1, y1, x2, y2) { + return new PDFLinearGradient(this, x1, y1, x2, y2); + }, + radialGradient: function(x1, y1, r1, x2, y2, r2) { + return new PDFRadialGradient(this, x1, y1, r1, x2, y2, r2); + } + }; + + namedColors = { + aliceblue: [240, 248, 255], + antiquewhite: [250, 235, 215], + aqua: [0, 255, 255], + aquamarine: [127, 255, 212], + azure: [240, 255, 255], + beige: [245, 245, 220], + bisque: [255, 228, 196], + black: [0, 0, 0], + blanchedalmond: [255, 235, 205], + blue: [0, 0, 255], + blueviolet: [138, 43, 226], + brown: [165, 42, 42], + burlywood: [222, 184, 135], + cadetblue: [95, 158, 160], + chartreuse: [127, 255, 0], + chocolate: [210, 105, 30], + coral: [255, 127, 80], + cornflowerblue: [100, 149, 237], + cornsilk: [255, 248, 220], + crimson: [220, 20, 60], + cyan: [0, 255, 255], + darkblue: [0, 0, 139], + darkcyan: [0, 139, 139], + darkgoldenrod: [184, 134, 11], + darkgray: [169, 169, 169], + darkgreen: [0, 100, 0], + darkgrey: [169, 169, 169], + darkkhaki: [189, 183, 107], + darkmagenta: [139, 0, 139], + darkolivegreen: [85, 107, 47], + darkorange: [255, 140, 0], + darkorchid: [153, 50, 204], + darkred: [139, 0, 0], + darksalmon: [233, 150, 122], + darkseagreen: [143, 188, 143], + darkslateblue: [72, 61, 139], + darkslategray: [47, 79, 79], + darkslategrey: [47, 79, 79], + darkturquoise: [0, 206, 209], + darkviolet: [148, 0, 211], + deeppink: [255, 20, 147], + deepskyblue: [0, 191, 255], + dimgray: [105, 105, 105], + dimgrey: [105, 105, 105], + dodgerblue: [30, 144, 255], + firebrick: [178, 34, 34], + floralwhite: [255, 250, 240], + forestgreen: [34, 139, 34], + fuchsia: [255, 0, 255], + gainsboro: [220, 220, 220], + ghostwhite: [248, 248, 255], + gold: [255, 215, 0], + goldenrod: [218, 165, 32], + gray: [128, 128, 128], + grey: [128, 128, 128], + green: [0, 128, 0], + greenyellow: [173, 255, 47], + honeydew: [240, 255, 240], + hotpink: [255, 105, 180], + indianred: [205, 92, 92], + indigo: [75, 0, 130], + ivory: [255, 255, 240], + khaki: [240, 230, 140], + lavender: [230, 230, 250], + lavenderblush: [255, 240, 245], + lawngreen: [124, 252, 0], + lemonchiffon: [255, 250, 205], + lightblue: [173, 216, 230], + lightcoral: [240, 128, 128], + lightcyan: [224, 255, 255], + lightgoldenrodyellow: [250, 250, 210], + lightgray: [211, 211, 211], + lightgreen: [144, 238, 144], + lightgrey: [211, 211, 211], + lightpink: [255, 182, 193], + lightsalmon: [255, 160, 122], + lightseagreen: [32, 178, 170], + lightskyblue: [135, 206, 250], + lightslategray: [119, 136, 153], + lightslategrey: [119, 136, 153], + lightsteelblue: [176, 196, 222], + lightyellow: [255, 255, 224], + lime: [0, 255, 0], + limegreen: [50, 205, 50], + linen: [250, 240, 230], + magenta: [255, 0, 255], + maroon: [128, 0, 0], + mediumaquamarine: [102, 205, 170], + mediumblue: [0, 0, 205], + mediumorchid: [186, 85, 211], + mediumpurple: [147, 112, 219], + mediumseagreen: [60, 179, 113], + mediumslateblue: [123, 104, 238], + mediumspringgreen: [0, 250, 154], + mediumturquoise: [72, 209, 204], + mediumvioletred: [199, 21, 133], + midnightblue: [25, 25, 112], + mintcream: [245, 255, 250], + mistyrose: [255, 228, 225], + moccasin: [255, 228, 181], + navajowhite: [255, 222, 173], + navy: [0, 0, 128], + oldlace: [253, 245, 230], + olive: [128, 128, 0], + olivedrab: [107, 142, 35], + orange: [255, 165, 0], + orangered: [255, 69, 0], + orchid: [218, 112, 214], + palegoldenrod: [238, 232, 170], + palegreen: [152, 251, 152], + paleturquoise: [175, 238, 238], + palevioletred: [219, 112, 147], + papayawhip: [255, 239, 213], + peachpuff: [255, 218, 185], + peru: [205, 133, 63], + pink: [255, 192, 203], + plum: [221, 160, 221], + powderblue: [176, 224, 230], + purple: [128, 0, 128], + red: [255, 0, 0], + rosybrown: [188, 143, 143], + royalblue: [65, 105, 225], + saddlebrown: [139, 69, 19], + salmon: [250, 128, 114], + sandybrown: [244, 164, 96], + seagreen: [46, 139, 87], + seashell: [255, 245, 238], + sienna: [160, 82, 45], + silver: [192, 192, 192], + skyblue: [135, 206, 235], + slateblue: [106, 90, 205], + slategray: [112, 128, 144], + slategrey: [112, 128, 144], + snow: [255, 250, 250], + springgreen: [0, 255, 127], + steelblue: [70, 130, 180], + tan: [210, 180, 140], + teal: [0, 128, 128], + thistle: [216, 191, 216], + tomato: [255, 99, 71], + turquoise: [64, 224, 208], + violet: [238, 130, 238], + wheat: [245, 222, 179], + white: [255, 255, 255], + whitesmoke: [245, 245, 245], + yellow: [255, 255, 0], + yellowgreen: [154, 205, 50] + }; + +}).call(this); diff --git a/pitfall/pdfkit/lib/mixins/fonts.js b/pitfall/pdfkit/lib/mixins/fonts.js new file mode 100644 index 00000000..6086e834 --- /dev/null +++ b/pitfall/pdfkit/lib/mixins/fonts.js @@ -0,0 +1,69 @@ +// Generated by CoffeeScript 1.12.5 +(function() { + var PDFFont; + + PDFFont = require('../font'); + + module.exports = { + initFonts: function() { + this._fontFamilies = {}; + this._fontCount = 0; + this._fontSize = 12; + this._font = null; + this._registeredFonts = {}; + return this.font('Helvetica'); + }, + font: function(src, family, size) { + var cacheKey, font, id, ref; + if (typeof family === 'number') { + size = family; + family = null; + } + if (typeof src === 'string' && this._registeredFonts[src]) { + cacheKey = src; + ref = this._registeredFonts[src], src = ref.src, family = ref.family; + } else { + cacheKey = family || src; + if (typeof cacheKey !== 'string') { + cacheKey = null; + } + } + if (size != null) { + this.fontSize(size); + } + if (font = this._fontFamilies[cacheKey]) { + this._font = font; + return this; + } + id = 'F' + (++this._fontCount); + this._font = PDFFont.open(this, src, family, id); + if (font = this._fontFamilies[this._font.name]) { + this._font = font; + return this; + } + if (cacheKey) { + this._fontFamilies[cacheKey] = this._font; + } + this._fontFamilies[this._font.name] = this._font; + return this; + }, + fontSize: function(_fontSize) { + this._fontSize = _fontSize; + return this; + }, + currentLineHeight: function(includeGap) { + if (includeGap == null) { + includeGap = false; + } + return this._font.lineHeight(this._fontSize, includeGap); + }, + registerFont: function(name, src, family) { + this._registeredFonts[name] = { + src: src, + family: family + }; + return this; + } + }; + +}).call(this); diff --git a/pitfall/pdfkit/lib/mixins/images.js b/pitfall/pdfkit/lib/mixins/images.js new file mode 100644 index 00000000..619d7f15 --- /dev/null +++ b/pitfall/pdfkit/lib/mixins/images.js @@ -0,0 +1,111 @@ +// Generated by CoffeeScript 1.12.5 +(function() { + var PDFImage; + + PDFImage = require('../image'); + + module.exports = { + initImages: function() { + this._imageRegistry = {}; + return this._imageCount = 0; + }, + image: function(src, x, y, options) { + var base, bh, bp, bw, h, hp, image, ip, name, ref, ref1, ref2, ref3, w, wp; + if (options == null) { + options = {}; + } + if (typeof x === 'object') { + options = x; + x = null; + } + x = (ref = x != null ? x : options.x) != null ? ref : this.x; + y = (ref1 = y != null ? y : options.y) != null ? ref1 : this.y; + if (typeof src === 'string') { + image = this._imageRegistry[src]; + } + if (!image) { + if (src.width && src.height) { + image = src; + } else { + image = this.openImage(src); + } + } + if (!image.obj) { + image.embed(this); + } + if ((base = this.page.xobjects)[name = image.label] == null) { + base[name] = image.obj; + } + w = options.width || image.width; + h = options.height || image.height; + if (options.width && !options.height) { + wp = w / image.width; + w = image.width * wp; + h = image.height * wp; + } else if (options.height && !options.width) { + hp = h / image.height; + w = image.width * hp; + h = image.height * hp; + } else if (options.scale) { + w = image.width * options.scale; + h = image.height * options.scale; + } else if (options.fit) { + ref2 = options.fit, bw = ref2[0], bh = ref2[1]; + bp = bw / bh; + ip = image.width / image.height; + if (ip > bp) { + w = bw; + h = bw / ip; + } else { + h = bh; + w = bh * ip; + } + } else if (options.cover) { + ref3 = options.cover, bw = ref3[0], bh = ref3[1]; + bp = bw / bh; + ip = image.width / image.height; + if (ip > bp) { + h = bh; + w = bh * ip; + } else { + w = bw; + h = bw / ip; + } + } + if (options.fit || options.cover) { + if (options.align === 'center') { + x = x + bw / 2 - w / 2; + } else if (options.align === 'right') { + x = x + bw - w; + } + if (options.valign === 'center') { + y = y + bh / 2 - h / 2; + } else if (options.valign === 'bottom') { + y = y + bh - h; + } + } + if (this.y === y) { + this.y += h; + } + this.save(); + this.transform(w, 0, 0, -h, x, y + h); + this.addContent("/" + image.label + " Do"); + this.restore(); + return this; + }, + openImage: function(src) { + var image; + if (typeof src === 'string') { + image = this._imageRegistry[src]; + } + if (!image) { + image = PDFImage.open(src, 'I' + (++this._imageCount)); + if (typeof src === 'string') { + this._imageRegistry[src] = image; + } + } + return image; + } + }; + +}).call(this); diff --git a/pitfall/pdfkit/lib/mixins/text.js b/pitfall/pdfkit/lib/mixins/text.js new file mode 100644 index 00000000..bf0e0f11 --- /dev/null +++ b/pitfall/pdfkit/lib/mixins/text.js @@ -0,0 +1,338 @@ +// Generated by CoffeeScript 1.12.5 +(function() { + var LineWrapper, number; + + LineWrapper = require('../line_wrapper'); + + number = require('../object').number; + + module.exports = { + initText: function() { + this.x = 0; + this.y = 0; + return this._lineGap = 0; + }, + lineGap: function(_lineGap) { + this._lineGap = _lineGap; + return this; + }, + moveDown: function(lines) { + if (lines == null) { + lines = 1; + } + this.y += this.currentLineHeight(true) * lines + this._lineGap; + return this; + }, + moveUp: function(lines) { + if (lines == null) { + lines = 1; + } + this.y -= this.currentLineHeight(true) * lines + this._lineGap; + return this; + }, + _text: function(text, x, y, options, lineCallback) { + var j, len, line, ref, wrapper; + options = this._initOptions(x, y, options); + text = '' + text; + if (options.wordSpacing) { + text = text.replace(/\s{2,}/g, ' '); + } + if (options.width) { + wrapper = this._wrapper; + if (!wrapper) { + wrapper = new LineWrapper(this, options); + wrapper.on('line', lineCallback); + } + this._wrapper = options.continued ? wrapper : null; + this._textOptions = options.continued ? options : null; + wrapper.wrap(text, options); + } else { + ref = text.split('\n'); + for (j = 0, len = ref.length; j < len; j++) { + line = ref[j]; + lineCallback(line, options); + } + } + return this; + }, + text: function(text, x, y, options) { + return this._text(text, x, y, options, this._line.bind(this)); + }, + widthOfString: function(string, options) { + if (options == null) { + options = {}; + } + return this._font.widthOfString(string, this._fontSize, options.features) + (options.characterSpacing || 0) * (string.length - 1); + }, + heightOfString: function(text, options) { + var height, lineGap, ref, x, y; + if (options == null) { + options = {}; + } + ref = this, x = ref.x, y = ref.y; + options = this._initOptions(options); + options.height = 2e308; + lineGap = options.lineGap || this._lineGap || 0; + this._text(text, this.x, this.y, options, (function(_this) { + return function(line, options) { + return _this.y += _this.currentLineHeight(true) + lineGap; + }; + })(this)); + height = this.y - y; + this.x = x; + this.y = y; + return height; + }, + list: function(list, x, y, options, wrapper) { + var flatten, i, indent, itemIndent, items, level, levels, midLine, r; + options = this._initOptions(x, y, options); + midLine = Math.round((this._font.ascender / 1000 * this._fontSize) / 2); + r = options.bulletRadius || Math.round((this._font.ascender / 1000 * this._fontSize) / 3); + indent = options.textIndent || r * 5; + itemIndent = options.bulletIndent || r * 8; + level = 1; + items = []; + levels = []; + flatten = function(list) { + var i, item, j, len, results; + results = []; + for (i = j = 0, len = list.length; j < len; i = ++j) { + item = list[i]; + if (Array.isArray(item)) { + level++; + flatten(item); + results.push(level--); + } else { + items.push(item); + results.push(levels.push(level)); + } + } + return results; + }; + flatten(list); + wrapper = new LineWrapper(this, options); + wrapper.on('line', this._line.bind(this)); + level = 1; + i = 0; + wrapper.on('firstLine', (function(_this) { + return function() { + var diff, l; + if ((l = levels[i++]) !== level) { + diff = itemIndent * (l - level); + _this.x += diff; + wrapper.lineWidth -= diff; + level = l; + } + _this.circle(_this.x - indent + r, _this.y + midLine, r); + return _this.fill(); + }; + })(this)); + wrapper.on('sectionStart', (function(_this) { + return function() { + var pos; + pos = indent + itemIndent * (level - 1); + _this.x += pos; + return wrapper.lineWidth -= pos; + }; + })(this)); + wrapper.on('sectionEnd', (function(_this) { + return function() { + var pos; + pos = indent + itemIndent * (level - 1); + _this.x -= pos; + return wrapper.lineWidth += pos; + }; + })(this)); + wrapper.wrap(items.join('\n'), options); + return this; + }, + _initOptions: function(x, y, options) { + var key, margins, ref, val; + if (x == null) { + x = {}; + } + if (options == null) { + options = {}; + } + if (typeof x === 'object') { + options = x; + x = null; + } + options = (function() { + var k, opts, v; + opts = {}; + for (k in options) { + v = options[k]; + opts[k] = v; + } + return opts; + })(); + if (this._textOptions) { + ref = this._textOptions; + for (key in ref) { + val = ref[key]; + if (key !== 'continued') { + if (options[key] == null) { + options[key] = val; + } + } + } + } + if (x != null) { + this.x = x; + } + if (y != null) { + this.y = y; + } + if (options.lineBreak !== false) { + margins = this.page.margins; + if (options.width == null) { + options.width = this.page.width - this.x - margins.right; + } + } + options.columns || (options.columns = 0); + if (options.columnGap == null) { + options.columnGap = 18; + } + return options; + }, + _line: function(text, options, wrapper) { + var lineGap; + if (options == null) { + options = {}; + } + this._fragment(text, this.x, this.y, options); + lineGap = options.lineGap || this._lineGap || 0; + if (!wrapper) { + return this.x += this.widthOfString(text); + } else { + return this.y += this.currentLineHeight(true) + lineGap; + } + }, + _fragment: function(text, x, y, options) { + var addSegment, align, base, characterSpacing, commands, d, encoded, encodedWord, flush, hadOffset, i, j, last, len, len1, lineWidth, lineY, m, mode, name, pos, positions, positionsWord, ref, ref1, renderedWidth, scale, spaceWidth, textWidth, word, wordSpacing, words; + text = ('' + text).replace(/\n/g, ''); + if (text.length === 0) { + return; + } + align = options.align || 'left'; + wordSpacing = options.wordSpacing || 0; + characterSpacing = options.characterSpacing || 0; + if (options.width) { + switch (align) { + case 'right': + textWidth = this.widthOfString(text.replace(/\s+$/, ''), options); + x += options.lineWidth - textWidth; + break; + case 'center': + x += options.lineWidth / 2 - options.textWidth / 2; + break; + case 'justify': + words = text.trim().split(/\s+/); + textWidth = this.widthOfString(text.replace(/\s+/g, ''), options); + spaceWidth = this.widthOfString(' ') + characterSpacing; + wordSpacing = Math.max(0, (options.lineWidth - textWidth) / Math.max(1, words.length - 1) - spaceWidth); + } + } + renderedWidth = options.textWidth + (wordSpacing * (options.wordCount - 1)) + (characterSpacing * (text.length - 1)); + if (options.link) { + this.link(x, y, renderedWidth, this.currentLineHeight(), options.link); + } + if (options.underline || options.strike) { + this.save(); + if (!options.stroke) { + this.strokeColor.apply(this, this._fillColor); + } + lineWidth = this._fontSize < 10 ? 0.5 : Math.floor(this._fontSize / 10); + this.lineWidth(lineWidth); + d = options.underline ? 1 : 2; + lineY = y + this.currentLineHeight() / d; + if (options.underline) { + lineY -= lineWidth; + } + this.moveTo(x, lineY); + this.lineTo(x + renderedWidth, lineY); + this.stroke(); + this.restore(); + } + this.save(); + this.transform(1, 0, 0, -1, 0, this.page.height); + y = this.page.height - y - (this._font.ascender / 1000 * this._fontSize); + if ((base = this.page.fonts)[name = this._font.id] == null) { + base[name] = this._font.ref(); + } + this.addContent("BT"); + this.addContent("1 0 0 1 " + (number(x)) + " " + (number(y)) + " Tm"); + this.addContent("/" + this._font.id + " " + (number(this._fontSize)) + " Tf"); + mode = options.fill && options.stroke ? 2 : options.stroke ? 1 : 0; + if (mode) { + this.addContent(mode + " Tr"); + } + if (characterSpacing) { + this.addContent((number(characterSpacing)) + " Tc"); + } + if (wordSpacing) { + words = text.trim().split(/\s+/); + wordSpacing += this.widthOfString(' ') + characterSpacing; + wordSpacing *= 1000 / this._fontSize; + encoded = []; + positions = []; + for (j = 0, len = words.length; j < len; j++) { + word = words[j]; + ref = this._font.encode(word, options.features), encodedWord = ref[0], positionsWord = ref[1]; + encoded.push.apply(encoded, encodedWord); + positions.push.apply(positions, positionsWord); + positions[positions.length - 1].xAdvance += wordSpacing; + } + } else { + ref1 = this._font.encode(text, options.features), encoded = ref1[0], positions = ref1[1]; + } + scale = this._fontSize / 1000; + commands = []; + last = 0; + hadOffset = false; + addSegment = (function(_this) { + return function(cur) { + var advance, hex; + if (last < cur) { + hex = encoded.slice(last, cur).join(''); + advance = positions[cur - 1].xAdvance - positions[cur - 1].advanceWidth; + commands.push("<" + hex + "> " + (number(-advance))); + } + return last = cur; + }; + })(this); + flush = (function(_this) { + return function(i) { + addSegment(i); + if (commands.length > 0) { + _this.addContent("[" + (commands.join(' ')) + "] TJ"); + return commands.length = 0; + } + }; + })(this); + for (i = m = 0, len1 = positions.length; m < len1; i = ++m) { + pos = positions[i]; + if (pos.xOffset || pos.yOffset) { + flush(i); + this.addContent("1 0 0 1 " + (number(x + pos.xOffset * scale)) + " " + (number(y + pos.yOffset * scale)) + " Tm"); + flush(i + 1); + hadOffset = true; + } else { + if (hadOffset) { + this.addContent("1 0 0 1 " + (number(x)) + " " + (number(y)) + " Tm"); + hadOffset = false; + } + if (pos.xAdvance - pos.advanceWidth !== 0) { + addSegment(i + 1); + } + } + x += pos.xAdvance * scale; + } + flush(i); + this.addContent("ET"); + return this.restore(); + } + }; + +}).call(this); diff --git a/pitfall/pdfkit/lib/mixins/vector.js b/pitfall/pdfkit/lib/mixins/vector.js new file mode 100644 index 00000000..a7beed7e --- /dev/null +++ b/pitfall/pdfkit/lib/mixins/vector.js @@ -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);