-
Notifications
You must be signed in to change notification settings - Fork 1
/
label.js
132 lines (103 loc) · 3.86 KB
/
label.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
var fs = require('fs');
var path = require('path');
var extend = require('extend');
var Canvas = require('canvas');
var Image = Canvas.Image;
var Font = Canvas.Font;
var outPath = null;
if(!Font) {
throw new Error("Hm. It seems like node-canvas was not compiled with canvas support. Missing dependencies maybe?");
}
module.exports = function(opts) {
this.opts = {
allowLineBreaks: false, // allow automatic line breaking
padding: {
top: 15,
left: 15,
right: 15,
bottom: 15
},
font: {
dir: path.join(__dirname, 'fonts'),
size: 50,
lineSpacing: 10,
color: '#000000',
normal: 'Inconsolata-Regular.ttf',
bold: 'Inconsolata-Bold.ttf'
},
label: {
// only change width and height if using different label paper
width: 1083, // in pixels,
height: 336 // in pixels
}
};
this.opts = extend(true, this.opts, opts);
this.fail = function(err) {
throw new Error(err);
};
this.fontPath = function(filename) {
return path.join(this.opts.font.dir, filename);
};
this.canvas = new Canvas(this.opts.label.width, this.opts.label.height);
this.ctx = this.canvas.getContext('2d');
// Set white background
this.ctx.fillStyle = "#FFFFFF";
this.ctx.fillRect(0, 0, this.opts.label.width, this.opts.label.height);
// Set font color
this.ctx.fillStyle = this.opts.font.color || 'black';
// Load fonts
this.ctx.addFont(new Font('normalFont', this.fontPath(this.opts.font.normal)));
this.ctx.addFont(new Font('boldFont', this.fontPath(this.opts.font.bold)));
this.fontStyles = {
normal: this.opts.font.size+'px normalFont',
bold: this.opts.font.size+'px boldFont'
}
this.ctx.font = this.fontStyles.normal;
this.letterWidth = this.ctx.measureText('o').width;
this.letterHeight = this.ctx.measureText('o').emHeightAscent;
this.maxLineWidth = this.opts.label.width - this.opts.padding.left - this.opts.padding.right;
this.yOffset = this.opts.padding.top + this.opts.font.size;
this.lineCount = 0;
this.writeLine = function(str, style) {
if((this.yOffset + this.opts.padding.bottom) > this.opts.label.height) {
this.fail("Too many lines. Text does not fit on label.");
}
if(!style) {
style = 'normal';
}
this.ctx.font = this.fontStyles[style];
this.ctx.fillText(str, this.opts.padding.left, this.yOffset);
this.yOffset += this.letterHeight + this.opts.font.lineSpacing;
this.lineCount++;
};
this.write = function(str, style) {
if(!str) {
str = '';
}
var w = this.ctx.measureText(str).width;
if(w > this.maxLineWidth) {
var extraLetters = Math.ceil((w - this.maxLineWidth) / this.letterWidth);
if(!this.opts.allowLineBreaks) {
this.fail("Line " + (this.lineCount + 1) + " is too long by " + extraLetters + " letters and line breaking is not allowed (hint: use -b to allow line breaks)");
} else {
var oneLineLength = str.length - extraLetters;
this.writeLine(str.slice(0, this.oneLineLength), style);
this.write(str.slice(this.oneLineLength), style);
}
} else {
return this.writeLine(str, style);
}
};
this.saveImage = function(outPath, callback) {
var out = fs.createWriteStream(outPath);
var stream = this.canvas.createPNGStream();
stream.on('data', function(chunk){
out.write(chunk);
});
stream.on('end', function() {
if(callback) {
callback();
}
});
}
};