• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Functions dealing with parsing/stringifying fonts go here.
2var 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  );
11
12function stripWhitespace(str) {
13  return str.replace(/^\s+|\s+$/, '');
14}
15
16var defaultHeight = 16;
17// Based off of node-canvas's parseFont
18// returns font size in px, which represents the em width.
19function parseFontString(fontStr) {
20
21  var font = fontStringRegex.exec(fontStr);
22  if (!font) {
23    SkDebug('Invalid font string ' + fontStr);
24    return null;
25  }
26
27  var size = parseFloat(font[4]);
28  var sizePx = defaultHeight;
29  var unit = font[5];
30  switch (unit) {
31    case 'em':
32    case 'rem':
33      sizePx = size * defaultHeight;
34      break;
35    case 'pt':
36      sizePx = size * 4/3;
37      break;
38    case 'px':
39      sizePx = size;
40      break;
41    case 'pc':
42      sizePx = size * defaultHeight;
43      break;
44    case 'in':
45      sizePx = size * 96;
46      break;
47    case 'cm':
48      sizePx = size * 96.0 / 2.54;
49      break;
50    case 'mm':
51      sizePx = size * (96.0 / 25.4);
52      break;
53    case 'q': // quarter millimeters
54      sizePx = size * (96.0 / 25.4 / 4);
55      break;
56    case '%':
57      sizePx = size * (defaultHeight / 75);
58      break;
59  }
60  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;