resume in color:_doOpacity

main
Matthew Butterick 8 years ago
parent 571a3f31c3
commit 4f8b301c77

@ -0,0 +1,240 @@
// Generated by CoffeeScript 1.12.5
(function() {
var PDFGradient, PDFLinearGradient, PDFRadialGradient,
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;
PDFGradient = (function() {
function PDFGradient(doc) {
this.doc = doc;
this.stops = [];
this.embedded = false;
this.transform = [1, 0, 0, 1, 0, 0];
this._colorSpace = 'DeviceRGB';
}
PDFGradient.prototype.stop = function(pos, color, opacity) {
if (opacity == null) {
opacity = 1;
}
opacity = Math.max(0, Math.min(1, opacity));
this.stops.push([pos, this.doc._normalizeColor(color), opacity]);
return this;
};
PDFGradient.prototype.setTransform = function(m11, m12, m21, m22, dx, dy) {
this.transform = [m11, m12, m21, m22, dx, dy];
return this;
};
PDFGradient.prototype.embed = function(m) {
var bounds, encode, fn, form, grad, gstate, i, j, k, last, len, opacityPattern, pageBBox, pattern, ref, ref1, shader, stop, stops, v;
if (this.stops.length === 0) {
return;
}
this.embedded = true;
this.matrix = m;
last = this.stops[this.stops.length - 1];
if (last[0] < 1) {
this.stops.push([1, last[1], last[2]]);
}
bounds = [];
encode = [];
stops = [];
for (i = j = 0, ref = this.stops.length - 1; 0 <= ref ? j < ref : j > ref; i = 0 <= ref ? ++j : --j) {
encode.push(0, 1);
if (i + 2 !== this.stops.length) {
bounds.push(this.stops[i + 1][0]);
}
fn = this.doc.ref({
FunctionType: 2,
Domain: [0, 1],
C0: this.stops[i + 0][1],
C1: this.stops[i + 1][1],
N: 1
});
stops.push(fn);
fn.end();
}
if (stops.length === 1) {
fn = stops[0];
} else {
fn = this.doc.ref({
FunctionType: 3,
Domain: [0, 1],
Functions: stops,
Bounds: bounds,
Encode: encode
});
fn.end();
}
this.id = 'Sh' + (++this.doc._gradCount);
shader = this.shader(fn);
shader.end();
pattern = this.doc.ref({
Type: 'Pattern',
PatternType: 2,
Shading: shader,
Matrix: (function() {
var k, len, ref1, results;
ref1 = this.matrix;
results = [];
for (k = 0, len = ref1.length; k < len; k++) {
v = ref1[k];
results.push(+v.toFixed(5));
}
return results;
}).call(this)
});
pattern.end();
if (this.stops.some(function(stop) {
return stop[2] < 1;
})) {
grad = this.opacityGradient();
grad._colorSpace = 'DeviceGray';
ref1 = this.stops;
for (k = 0, len = ref1.length; k < len; k++) {
stop = ref1[k];
grad.stop(stop[0], [stop[2]]);
}
grad = grad.embed(this.matrix);
pageBBox = [0, 0, this.doc.page.width, this.doc.page.height];
form = this.doc.ref({
Type: 'XObject',
Subtype: 'Form',
FormType: 1,
BBox: pageBBox,
Group: {
Type: 'Group',
S: 'Transparency',
CS: 'DeviceGray'
},
Resources: {
ProcSet: ['PDF', 'Text', 'ImageB', 'ImageC', 'ImageI'],
Pattern: {
Sh1: grad
}
}
});
form.write("/Pattern cs /Sh1 scn");
form.end((pageBBox.join(" ")) + " re f");
gstate = this.doc.ref({
Type: 'ExtGState',
SMask: {
Type: 'Mask',
S: 'Luminosity',
G: form
}
});
gstate.end();
opacityPattern = this.doc.ref({
Type: 'Pattern',
PatternType: 1,
PaintType: 1,
TilingType: 2,
BBox: pageBBox,
XStep: pageBBox[2],
YStep: pageBBox[3],
Resources: {
ProcSet: ['PDF', 'Text', 'ImageB', 'ImageC', 'ImageI'],
Pattern: {
Sh1: pattern
},
ExtGState: {
Gs1: gstate
}
}
});
opacityPattern.write("/Gs1 gs /Pattern cs /Sh1 scn");
opacityPattern.end((pageBBox.join(" ")) + " re f");
this.doc.page.patterns[this.id] = opacityPattern;
} else {
this.doc.page.patterns[this.id] = pattern;
}
return pattern;
};
PDFGradient.prototype.apply = function(op) {
var dx, dy, m, m0, m1, m11, m12, m2, m21, m22, m3, m4, m5, ref, ref1;
ref = this.doc._ctm.slice(), m0 = ref[0], m1 = ref[1], m2 = ref[2], m3 = ref[3], m4 = ref[4], m5 = ref[5];
ref1 = this.transform, m11 = ref1[0], m12 = ref1[1], m21 = ref1[2], m22 = ref1[3], dx = ref1[4], dy = ref1[5];
m = [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];
if (!(this.embedded && m.join(" ") === this.matrix.join(" "))) {
this.embed(m);
}
return this.doc.addContent("/" + this.id + " " + op);
};
return PDFGradient;
})();
PDFLinearGradient = (function(superClass) {
extend(PDFLinearGradient, superClass);
function PDFLinearGradient(doc, x1, y1, x2, y2) {
this.doc = doc;
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
PDFLinearGradient.__super__.constructor.apply(this, arguments);
}
PDFLinearGradient.prototype.shader = function(fn) {
return this.doc.ref({
ShadingType: 2,
ColorSpace: this._colorSpace,
Coords: [this.x1, this.y1, this.x2, this.y2],
Function: fn,
Extend: [true, true]
});
};
PDFLinearGradient.prototype.opacityGradient = function() {
return new PDFLinearGradient(this.doc, this.x1, this.y1, this.x2, this.y2);
};
return PDFLinearGradient;
})(PDFGradient);
PDFRadialGradient = (function(superClass) {
extend(PDFRadialGradient, superClass);
function PDFRadialGradient(doc, x1, y1, r1, x2, y2, r2) {
this.doc = doc;
this.x1 = x1;
this.y1 = y1;
this.r1 = r1;
this.x2 = x2;
this.y2 = y2;
this.r2 = r2;
PDFRadialGradient.__super__.constructor.apply(this, arguments);
}
PDFRadialGradient.prototype.shader = function(fn) {
return this.doc.ref({
ShadingType: 3,
ColorSpace: this._colorSpace,
Coords: [this.x1, this.y1, this.r1, this.x2, this.y2, this.r2],
Function: fn,
Extend: [true, true]
});
};
PDFRadialGradient.prototype.opacityGradient = function() {
return new PDFRadialGradient(this.doc, this.x1, this.y1, this.r1, this.x2, this.y2, this.r2);
};
return PDFRadialGradient;
})(PDFGradient);
module.exports = {
PDFGradient: PDFGradient,
PDFLinearGradient: PDFLinearGradient,
PDFRadialGradient: PDFRadialGradient
};
}).call(this);

@ -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);

@ -1,117 +0,0 @@
// 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);

@ -0,0 +1,256 @@
#lang racket/base
(require racket/class racket/string)
(provide color-mixin)
(require "helper.rkt")
(define (color-mixin %)
(class %
(super-new)
(field [(@_opacityRegistry _opacityRegistry) #f]
[(@_opacityCount _opacityCount) #f]
[(@_gradCount _gradCount) #f])
(define/public (initColor)
(set! @_opacityRegistry (mhash))
(set! @_opacityCount 0)
(set! @_gradCount 0))
;; parses color string into list of values
(public [@_normalizeColor _normalizeColor])
(define (@_normalizeColor color)
(cond
#;[(is-a? color PDFGradient) color] ; todo
;; 3-digit hex becomes 6-digit hex
[(and (string? color)
(regexp-match #px"^#(?i:[0-9A-F]){3}$" color))
(@_normalizeColor
(list->string (cdr (apply append
(for/list ([c (in-string color)])
(list c c))))))]
;; 6-digit hexish string becomes list of hex numbers and maybe #f vals
[(and (string? color) (= 7 (string-length color)) (string-prefix? color "#"))
(@_normalizeColor
(for/list ([str (in-list (regexp-match* #rx".." (string-trim color "#")))])
(string->number str 16)))]
;; named color
[(and (string? color) (hash-ref namedColors color #f)) => @_normalizeColor]
;; array of numbers
[(and (list? color) (andmap number? color))
(for/list ([i (in-list color)])
(define x (/ i (case (length color)
[(3) 255.0] ; RGB
[(4) 100.0] ; CMYK
[else 1])))
(if (integer? x) (inexact->exact x) x))]
[else #f]))
(public [@_setColor _setColor])
(define (@_setColor color stroke)
(set! color (@_normalizeColor color))
(define op (if stroke "SCN" "scn"))
(cond
[(not color)]
#;[(is-a? color PDFGradient)
(@_setColorSpace "Pattern" stroke)
(send color apply op)
#t] ; todo
[else
(define space (if (= (length color) 4)
"DeviceCMYK"
"DeviceRGB"))
(@_setColorSpace space stroke)
(set! color (string-join (map number color) " "))
(send this addContent (format "~a ~a" color op))
#t]))
(public [@_setColorSpace _setColorSpace])
(define (@_setColorSpace space stroke)
(define op (if stroke "CS" "cs"))
(send this addContent (format "/~a ~a" space op)))
(field ([@_fillColor _fillColor] #f))
(public [@fillColor fillColor])
(define (@fillColor color [opacity 1])
(define set (@_setColor color #f))
(when set (@fillOpacity opacity))
;; save this for text wrapper, which needs to reset
;; the fill color on new pages
(set! @_fillColor (list color opacity))
this)
(public [@fillOpacity fillOpacity])
(define (@fillOpacity opacity)
(@_doOpacity opacity #f)
this)
(public [@_doOpacity doOpacity])
(define (@_doOpacity fillOpacity strokeOpacity)
(error 'bonk))
))
(define namedColors
(mhash "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)))
(define c (new (color-mixin object%)))
(module+ test
(require rackunit)
(check-equal? (send c _normalizeColor "#6699Cc") '(0.4 0.6 0.8))
(check-false (send c _normalizeColor "#88aaCCC"))
(check-equal? (send c _normalizeColor "#69C") '(0.4 0.6 0.8))
(check-equal? (send c _normalizeColor "#69c") '(0.4 0.6 0.8))
(check-false (send c _normalizeColor "#8aCC"))
(check-equal? (send c _normalizeColor "aqua") '(0 1 1)))

@ -1,14 +1,14 @@
#lang sugar/debug racket/base
(require racket/class racket/draw br/list racket/list racket/format racket/port)
(require racket/class racket/draw racket/list racket/format racket/port)
(require sugar/debug)
(provide PDFDocument)
(require "reference.rkt" "struct.rkt" "object.rkt" "page.rkt" "helper.rkt" "params.rkt")
(require "vector.rkt")
(require "vector.rkt" "color.rkt")
(define PDFDocument
;; actually is an instance of readable.Stream, which is an input port
(class (vector-mixin object%)
(class (color-mixin (vector-mixin object%))
(init-field [(@options options) (mhash)])
(let ([output-file (hash-ref @options 'out "outrkt.pdf")])
(super-new))
@ -48,7 +48,7 @@
;; todo
;; Initialize mixins
#;(@initColor)
(· this initColor)
(· this initVector)
#;(@initFonts)
#;(@initText)
@ -102,7 +102,7 @@
;; create a page object
(set! @page (make-object PDFPage this options))
(push-end! @_pageBuffer @page)
(push! @_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)
@ -235,4 +235,4 @@
(with-output-to-file (string-append fn ".pdf")
(λ () (display result-str)) #:exists 'replace)
(check-equal? (file->bytes (string-append fn ".pdf")) (file->bytes (string-append fn " copy.pdf")))
#;(display (bytes->string/latin-1 result-str)))
(display (bytes->string/latin-1 result-str)))

@ -1,6 +1,6 @@
#lang racket/base
(require (for-syntax racket/base) racket/class sugar/list racket/list)
(provide (all-defined-out))
(require (for-syntax racket/base) racket/class sugar/list racket/list (only-in br/list push! pop!))
(provide (all-defined-out) push! pop!)
(define-syntax (· stx)
(syntax-case stx ()
@ -56,10 +56,25 @@
(define (newBuffer x) (string->bytes/latin-1 (format "~a" x)))
(define buffer-length bytes-length)
;; js-style `push`, which appends to end of list
(define-syntax-rule (push-end! id thing) (set! id (append id (list thing))))
(module+ test
(define xs '(1 2 3))
(push-end! xs 4)
(check-equal? xs '(1 2 3 4)))
(check-equal? xs '(1 2 3 4)))
;; fancy number->string. bounds are checked, inexact integers are coerced.
(define (number x)
(unless (< -1e21 x 1e21)
(raise-argument-error 'number "valid number" x))
(let ([x (/ (round (* x 1e6)) 1e6)])
(number->string (if (integer? x)
(inexact->exact x)
x))))
(module+ test
(check-equal? (number 4.5) "4.5")
(check-equal? (number 4.0) "4")
(check-equal? (number 4) "4"))

@ -1,6 +1,6 @@
#lang at-exp br
(require racket/class racket/string racket/list srfi/19)
(require "struct.rkt")
(require "struct.rkt" "helper.rkt")
(provide PDFObject)
(define PDFObject
@ -45,12 +45,8 @@
(bytes-set! newbuff (add1 bidx) (bytes-ref buff bidx))
newbuff))
(define/public (number n)
(unless (< -1e21 n 1e21)
(raise-argument-error 'number "valid number" n))
(define result (/ (round (* n 1e6)) 1e6))
(if (integer? result) (inexact->exact result) result))
;; moved this to helper module
#;(define/public (number n) ···)
(define/public (convert object)
(let loop ([x object])

@ -1,14 +1,71 @@
#lang racket/base
(require racket/class)
(require racket/class racket/match racket/string racket/format)
(provide vector-mixin)
(require "helper.rkt")
(define default-ctm-value '(1 0 0 1 0 0))
(define (vector-mixin %)
(class %
(super-new)
(field [(@_ctm _ctm) '(1 0 0 1 0 0)]
(field [(@_ctm _ctm) default-ctm-value]
[(@_ctmStack _ctmStack) null])
(define/public (initVector) (void))
(define/public (initVector)
(set! @_ctm default-ctm-value)
(set! @_ctmStack null))
(define/public (save)
(push! @_ctmStack @_ctm)
(send this addContent "q"))
(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)
(send this addContent "1 0 0 -1 0 792 cm")))) ; todo debug
(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)
(send this addContent (format "~a ~a m" x y)))
(define/public (lineTo x y)
(send this addContent (format "~a ~a l" x y)))
(public [@_windingRule _windingRule])
(define (@_windingRule rule)
(if (and (string? rule) (regexp-match #rx"^even-?odd$" rule))
"*"
""))
(define/public (fill color [rule #f])
(when (regexp-match #rx"^(even-?odd)|(non-?zero)$" color)
(set! rule color)
(set! color #f))
(when color (send this fillColor color)) ;; fillColor method is from color mixin
(send this addContent (format "f~a" (@_windingRule rule))))
))
(module+ test
(require rackunit)
(define v (new (vector-mixin object%)))
(check-equal? (· v _ctm) default-ctm-value)
(check-equal? (send v transform 1 2 3 4 5 6 #:debug #t) "1 2 3 4 5 6 cm")
(check-equal? (· v _ctm) '(1 2 3 4 5 6))
(check-equal? (send v transform 1 2 3 4 5 6 #:debug #t) "1 2 3 4 5 6 cm")
(check-equal? (· v _ctm) '(7 10 15 22 28 40))
(check-equal? (send v transform 1 2 3 4 5 6 #:debug #t) "1 2 3 4 5 6 cm")
(check-equal? (· v _ctm) '(37 54 81 118 153 222)))

Binary file not shown.

@ -2,7 +2,7 @@ PDFDocument = require 'pdfkit'
fs = require 'fs'
# Create a new PDFDocument
doc = new PDFDocument
doc = new PDFDocument({compress: no})
doc.pipe(fs.createWriteStream('test0.pdf'))
doc.end()

Binary file not shown.

@ -0,0 +1,7 @@
#lang br
(require pitfall/kit/document)
(define doc (new PDFDocument))
(send doc pipe (open-output-file "test0rkt.pdf" #:exists 'replace))
(send doc end)

@ -0,0 +1,63 @@
%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 18
>>
stream
1 0 0 -1 0 792 cm
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
0000000403 00000 n
0000000354 00000 n
0000000186 00000 n
0000000119 00000 n
0000000015 00000 n
0000000254 00000 n
trailer
<<
/Info 6 0 R
/Root 2 0 R
/Size 7
>>
startxref
460
%%EOF

@ -0,0 +1,24 @@
PDFDocument = require 'pdfkit'
fs = require 'fs'
# Create a new PDFDocument
doc = new PDFDocument({compress: no})
doc.pipe(fs.createWriteStream('test1.pdf'))
# Draw a triangle and a circle
doc.save()
.moveTo(100, 150)
.lineTo(100, 250)
.lineTo(200, 250)
.fill("#FF3300")
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()

@ -0,0 +1,104 @@
%PDF-1.3
%ÿÿÿÿ
6 0 obj
<<
/Type /ExtGState
/ca 1
>>
endobj
5 0 obj
<<
/Type /Page
/Parent 1 0 R
/MediaBox [0 0 612 792]
/Contents 3 0 R
/Resources 4 0 R
>>
endobj
4 0 obj
<<
/ProcSet [/PDF /Text /ImageB /ImageC /ImageI]
/ExtGState <<
/Gs1 6 0 R
>>
>>
endobj
3 0 obj
<<
/Length 421
>>
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
/Gs1 gs
f
230 200 m
230 172.385763 252.385763 150 280 150 c
307.614237 150 330 172.385763 330 200 c
330 227.614237 307.614237 250 280 250 c
252.385763 250 230 227.614237 230 200 c
h
/DeviceRGB cs
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
7 0 obj
<<
/Producer (PDFKit)
/Creator (PDFKit)
/CreationDate (D:20170513192922Z)
>>
endobj
2 0 obj
<<
/Type /Catalog
/Pages 1 0 R
>>
endobj
1 0 obj
<<
/Type /Pages
/Count 1
/Kids [5 0 R]
>>
endobj
xref
0 8
0000000000 65535 f
0000000871 00000 n
0000000822 00000 n
0000000258 00000 n
0000000163 00000 n
0000000059 00000 n
0000000015 00000 n
0000000730 00000 n
trailer
<<
/Size 8
/Root 2 0 R
/Info 7 0 R
>>
startxref
928
%%EOF

@ -0,0 +1,18 @@
#lang br
(require pitfall/kit/document)
;; 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 (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 doc end)

@ -1,21 +0,0 @@
#lang br
(require pitfall/kit/document)
(define doc (new PDFDocument))
(send doc pipe (open-output-file "testrkt0.pdf" #:exists 'replace))
(send doc end)
#|
var PDFDocument, doc, fs;
PDFDocument = require('pdfkit');
fs = require('fs');
doc = new PDFDocument;
doc.pipe(fs.createWriteStream('out.pdf'));
doc.end();
|#
Loading…
Cancel
Save