blob: 340bd00c90a82494c95531b3fdb1192827b6287a [file] [log] [blame]
Kevin Lubick53eabf62018-12-10 12:41:26 -05001// Functions dealing with parsing/stringifying fonts go here.
Kevin Lubick8e4a3312018-12-14 15:03:41 -05002var fontStringRegex = new RegExp(
3 '(italic|oblique|normal|)\\s*' + // style
4 '(small-caps|normal|)\\s*' + // variant
5 '(bold|bolder|lighter|[1-9]00|normal|)\\s*' + // weight
6 '([\\d\\.]+)' + // size
7 '(px|pt|pc|in|cm|mm|%|em|ex|ch|rem|q)' + // unit
8 // line-height is ignored here, as per the spec
9 '(.+)' // family
10 );
Kevin Lubick53eabf62018-12-10 12:41:26 -050011
Kevin Lubick8e4a3312018-12-14 15:03:41 -050012function stripWhitespace(str) {
13 return str.replace(/^\s+|\s+$/, '');
14}
15
Kevin Lubickddd0a332018-12-12 10:35:13 -050016var defaultHeight = 16;
Kevin Lubick53eabf62018-12-10 12:41:26 -050017// Based off of node-canvas's parseFont
Kevin Lubickddd0a332018-12-12 10:35:13 -050018// returns font size in px, which represents the em width.
Kevin Lubick8e4a3312018-12-14 15:03:41 -050019function parseFontString(fontStr) {
20
21 var font = fontStringRegex.exec(fontStr);
22 if (!font) {
23 SkDebug('Invalid font string ' + fontStr);
24 return null;
Kevin Lubick53eabf62018-12-10 12:41:26 -050025 }
Kevin Lubick8e4a3312018-12-14 15:03:41 -050026
27 var size = parseFloat(font[4]);
28 var sizePx = defaultHeight;
29 var unit = font[5];
Kevin Lubick53eabf62018-12-10 12:41:26 -050030 switch (unit) {
Kevin Lubick53eabf62018-12-10 12:41:26 -050031 case 'em':
32 case 'rem':
Kevin Lubick8e4a3312018-12-14 15:03:41 -050033 sizePx = size * defaultHeight;
34 break;
35 case 'pt':
36 sizePx = size * 4/3;
37 break;
Kevin Lubickddd0a332018-12-12 10:35:13 -050038 case 'px':
Kevin Lubick8e4a3312018-12-14 15:03:41 -050039 sizePx = size;
40 break;
Kevin Lubickddd0a332018-12-12 10:35:13 -050041 case 'pc':
Kevin Lubick8e4a3312018-12-14 15:03:41 -050042 sizePx = size * defaultHeight;
43 break;
Kevin Lubickddd0a332018-12-12 10:35:13 -050044 case 'in':
Kevin Lubick8e4a3312018-12-14 15:03:41 -050045 sizePx = size * 96;
46 break;
Kevin Lubickddd0a332018-12-12 10:35:13 -050047 case 'cm':
Kevin Lubick8e4a3312018-12-14 15:03:41 -050048 sizePx = size * 96.0 / 2.54;
49 break;
Kevin Lubickddd0a332018-12-12 10:35:13 -050050 case 'mm':
Kevin Lubick8e4a3312018-12-14 15:03:41 -050051 sizePx = size * (96.0 / 25.4);
52 break;
Kevin Lubickddd0a332018-12-12 10:35:13 -050053 case 'q': // quarter millimeters
Kevin Lubick8e4a3312018-12-14 15:03:41 -050054 sizePx = size * (96.0 / 25.4 / 4);
55 break;
Kevin Lubickddd0a332018-12-12 10:35:13 -050056 case '%':
Kevin Lubick8e4a3312018-12-14 15:03:41 -050057 sizePx = size * (defaultHeight / 75);
58 break;
Kevin Lubick53eabf62018-12-10 12:41:26 -050059 }
Kevin Lubick8e4a3312018-12-14 15:03:41 -050060 return {
61 'style': font[1],
62 'variant': font[2],
63 'weight': font[3],
64 'sizePx': sizePx,
65 'family': font[6].trim()
66 };
67}
68
69function getTypeface(fontstr) {
70 var descriptors = parseFontString(fontstr);
71 var typeface = getFromFontCache(descriptors);
72 descriptors['typeface'] = typeface;
73 return descriptors;
74}
75
76// null means use the default typeface (which is currently NotoMono)
77var fontCache = {
78 'Noto Mono': {
79 '*': null, // is used if we have this font family, but not the right style/variant/weight
80 },
81 'monospace': {
82 '*': null,
83 }
84};
85
86// descriptors is like https://developer.mozilla.org/en-US/docs/Web/API/FontFace/FontFace
87// The ones currently supported are family, style, variant, weight.
88function addToFontCache(typeface, descriptors) {
89 var key = (descriptors['style'] || 'normal') + '|' +
90 (descriptors['variant'] || 'normal') + '|' +
91 (descriptors['weight'] || 'normal');
92 var fam = descriptors['family'];
93 if (!fontCache[fam]) {
94 // preload with a fallback to this typeface
95 fontCache[fam] = {
96 '*': typeface,
97 };
98 }
99 fontCache[fam][key] = typeface;
100}
101
102function getFromFontCache(descriptors) {
103 var key = (descriptors['style'] || 'normal') + '|' +
104 (descriptors['variant'] || 'normal') + '|' +
105 (descriptors['weight'] || 'normal');
106 var fam = descriptors['family'];
107 if (!fontCache[fam]) {
108 return null;
109 }
110 return fontCache[fam][key] || fontCache[fam]['*'];
111}
112
113CanvasKit._testing['parseFontString'] = parseFontString;