UNPKG

4.15 kBJavaScriptView Raw
1var Shape = require('./generic');
2
3var fonts = {};
4
5var parseFontString = function(font){
6 var regexp = /^\s*((?:(?:normal|bold|italic)\s+)*)(?:(\d+(?:\.\d+)?)[ptexm\%]*(?:\s*\/.*?)?\s+)?\s*\"?([^\"]*)/i,
7 match = regexp.exec(font);
8 return {
9 fontFamily: match[3],
10 fontSize: match[2],
11 fontStyle: (/italic/.exec(match[1]) || ''),
12 fontWeight: (/bold/.exec(match[1]) || '')
13 };
14};
15
16var Font = Shape(function(text, font, alignment){
17 if (typeof font == 'string') font = parseFontString(font);
18 if (font) this.font = font; else font = this.font;
19
20 var family = font.fontFamily || font['font-family'],
21 weight = font.fontWeight || font['font-weight'] || 'normal',
22 style = font.fontStyle || font['font-style'] || 'normal',
23 size = parseFloat(font.fontSize || font['font-size'] || font.size);
24
25 font = font.glyphs ? font : fonts[weight + style + family];
26
27 if (!font) throw new Error('The specified font has not been found.');
28
29 var scale = size / font.face['units-per-em'];
30 var width = 0, height = size, path = '', row = '';
31
32 var x = 0, y = scale * font.face.ascent || size - (scale * font.face.descent);
33
34 var regexp = /([mclrvxe])([^a-z]*)/g, match;
35
36 // TODO: Refactor to use SVG paths as the source
37
38 var cx = 0, cy = 0, fx = 0, fy = 0;
39 for (var i = 0, l = text.length; i < l; ++i){
40 if (text.charAt(i) == '\n'){
41 if (alignment == 'end' || alignment == 'right'){
42 cx -= x;
43 path += 'm' + (-x) + ',0';
44 }
45 if (alignment == 'middle' || alignment == 'center'){
46 cx -= x / 2;
47 path += 'm' + (-x / 2) + ',0';
48 }
49 path += row;
50 path += 'm' + (-cx) + ',' + (-cy);
51 cx = cy = 0;
52 row = '';
53 x = 0;
54 y += size * 1.1;
55 height += size * 1.1;
56 continue;
57 }
58 var glyph = font.glyphs[text.charAt(i)] || font.glyphs.missing || font.glyphs[' '];
59 if (!glyph) continue;
60 var w = scale * (glyph.w || font.w);
61 if (glyph.d){
62 var s = scale;
63
64 if (glyph.path){
65 var parts = glyph.path;
66 } else {
67 var parts = [], index = -1,
68 bits = ('m' + glyph.d + 'x').match(/[a-df-z]|[\-+]?(?:[\d\.]e[\-+]?|[^\s\-+,a-z])+/ig),
69 part;
70
71 for (var j = 0, k = bits.length; j < k; j++){
72 var bit = bits[j];
73 if (bit.match(/^[a-z]/i)){
74 parts[++index] = part = [bit];
75 } else {
76 part.push(Number(bit));
77 }
78 }
79 glyph.path = parts;
80 }
81
82 for (var j = 0; j < parts.length; j++){
83 var c = Array.prototype.slice.call(parts[j]), f = c.shift();
84 switch (f){
85 case 'l':
86 row += 'l ' + (x + (s * c[0]) - cx) + ',' + (y + (s * c[1]) - cy);
87 //row += 'L ' + (x + (s * c[0])) + ',' + (y + (s * c[1]));
88 cx = x + (s * c[0]); cy = y + (s * c[1]);
89 break;
90 case 'c':
91 row += 'c ' + (x + s * c[0] - cx) + ',' + (y + s * c[1] - cy) + ',' + (x + s * c[2] - cx) + ',' + (y + s * c[3] - cy) + ',' + (x + s * c[4] - cx) + ',' + (y + s * c[5] - cy);
92 cx = x + (s * c[4]); cy = y + (s * c[5]);
93 break;
94 case 'v':
95 row += 'c ' + (s * c[0]) + ',' + (s * c[1]) + ',' + (s * c[2]) + ',' + (s * c[3]) + ',' + (s * c[4]) + ',' + (s * c[5]);
96 cx += (s * c[4]); cy += (s * c[5]);
97 break;
98 case 'r':
99 row += 'l ' + (s * c[0]) + ',' + (s * c[1]);
100 cx += (s * c[0]); cy += (s * c[1]);
101 break;
102 case 'm':
103 row += 'm ' + (x + (s * c[0]) - cx) + ',' + (y + (s * c[1]) - cy);
104 fx = cx = x + (s * c[0]);
105 fy = cy = y + (s * c[1]);
106 break;
107 case 'x':
108 row += 'z';
109 cx = fx;
110 cy = fy;
111 break;
112 }
113 }
114 }
115 x += w;
116 if (x > width) width = x;
117 }
118
119 if (alignment == 'end' || alignment == 'right') path += 'm' + (-x) + ',0';
120 if (alignment == 'middle' || alignment == 'center') path += 'm' + (-x / 2) + ',0';
121 path += row;
122 this.path.push(path);
123 this.width = width;
124 this.height = height;
125});
126
127Font.register = function(font){
128 var face = font.face,
129 family = face['font-family'],
130 weight = (face['font-weight'] > 500 ? 'bold' : 'normal'),
131 style = (face['font-stretch'] == 'oblique' || face['font-style'] == 'oblique' || face['font-style'] == 'italic' ? 'italic' : 'normal');
132 fonts[weight + style + family] = font;
133 return this;
134};
135
136module.exports = Font;
\No newline at end of file