xref: /aosp_15_r20/external/skia/modules/canvaskit/htmlcanvas/font.js (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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    Debug('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
76var fontCache;
77function initCache() {
78  if (!fontCache) {
79    fontCache = {
80      'Noto Mono': {
81         // is used if we have this font family, but not the right style/variant/weight
82        '*': CanvasKit.Typeface.GetDefault(),
83      },
84      'monospace': {
85        '*': CanvasKit.Typeface.GetDefault(),
86      }
87    };
88  }
89}
90
91// descriptors is like https://developer.mozilla.org/en-US/docs/Web/API/FontFace/FontFace
92// The ones currently supported are family, style, variant, weight.
93function addToFontCache(typeface, descriptors) {
94  var key = (descriptors['style']   || 'normal') + '|' +
95            (descriptors['variant'] || 'normal') + '|' +
96            (descriptors['weight']  || 'normal');
97  var fam = descriptors['family'];
98  initCache();
99  if (!fontCache[fam]) {
100    // preload with a fallback to this typeface
101    fontCache[fam] = {
102      '*': typeface,
103    };
104  }
105  fontCache[fam][key] = typeface;
106}
107
108function getFromFontCache(descriptors) {
109  var key = (descriptors['style']   || 'normal') + '|' +
110            (descriptors['variant'] || 'normal') + '|' +
111            (descriptors['weight']  || 'normal');
112  var fam = descriptors['family'];
113  initCache();
114  if (!fontCache[fam]) {
115    return CanvasKit.Typeface.GetDefault();
116  }
117  return fontCache[fam][key] || fontCache[fam]['*'];
118}
119
120CanvasKit._testing['parseFontString'] = parseFontString;
121