1 | var Shape = require('./generic');
|
2 |
|
3 | var fonts = {};
|
4 |
|
5 | var 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 |
|
16 | var 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 |
|
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 |
|
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 |
|
127 | Font.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 |
|
136 | module.exports = Font; |
\ | No newline at end of file |