1cb93a386Sopenharmony_ci// Functions dealing with parsing/stringifying fonts go here. 2cb93a386Sopenharmony_civar fontStringRegex = new RegExp( 3cb93a386Sopenharmony_ci '(italic|oblique|normal|)\\s*' + // style 4cb93a386Sopenharmony_ci '(small-caps|normal|)\\s*' + // variant 5cb93a386Sopenharmony_ci '(bold|bolder|lighter|[1-9]00|normal|)\\s*' + // weight 6cb93a386Sopenharmony_ci '([\\d\\.]+)' + // size 7cb93a386Sopenharmony_ci '(px|pt|pc|in|cm|mm|%|em|ex|ch|rem|q)' + // unit 8cb93a386Sopenharmony_ci // line-height is ignored here, as per the spec 9cb93a386Sopenharmony_ci '(.+)' // family 10cb93a386Sopenharmony_ci ); 11cb93a386Sopenharmony_ci 12cb93a386Sopenharmony_cifunction stripWhitespace(str) { 13cb93a386Sopenharmony_ci return str.replace(/^\s+|\s+$/, ''); 14cb93a386Sopenharmony_ci} 15cb93a386Sopenharmony_ci 16cb93a386Sopenharmony_civar defaultHeight = 16; 17cb93a386Sopenharmony_ci// Based off of node-canvas's parseFont 18cb93a386Sopenharmony_ci// returns font size in px, which represents the em width. 19cb93a386Sopenharmony_cifunction parseFontString(fontStr) { 20cb93a386Sopenharmony_ci 21cb93a386Sopenharmony_ci var font = fontStringRegex.exec(fontStr); 22cb93a386Sopenharmony_ci if (!font) { 23cb93a386Sopenharmony_ci Debug('Invalid font string ' + fontStr); 24cb93a386Sopenharmony_ci return null; 25cb93a386Sopenharmony_ci } 26cb93a386Sopenharmony_ci 27cb93a386Sopenharmony_ci var size = parseFloat(font[4]); 28cb93a386Sopenharmony_ci var sizePx = defaultHeight; 29cb93a386Sopenharmony_ci var unit = font[5]; 30cb93a386Sopenharmony_ci switch (unit) { 31cb93a386Sopenharmony_ci case 'em': 32cb93a386Sopenharmony_ci case 'rem': 33cb93a386Sopenharmony_ci sizePx = size * defaultHeight; 34cb93a386Sopenharmony_ci break; 35cb93a386Sopenharmony_ci case 'pt': 36cb93a386Sopenharmony_ci sizePx = size * 4/3; 37cb93a386Sopenharmony_ci break; 38cb93a386Sopenharmony_ci case 'px': 39cb93a386Sopenharmony_ci sizePx = size; 40cb93a386Sopenharmony_ci break; 41cb93a386Sopenharmony_ci case 'pc': 42cb93a386Sopenharmony_ci sizePx = size * defaultHeight; 43cb93a386Sopenharmony_ci break; 44cb93a386Sopenharmony_ci case 'in': 45cb93a386Sopenharmony_ci sizePx = size * 96; 46cb93a386Sopenharmony_ci break; 47cb93a386Sopenharmony_ci case 'cm': 48cb93a386Sopenharmony_ci sizePx = size * 96.0 / 2.54; 49cb93a386Sopenharmony_ci break; 50cb93a386Sopenharmony_ci case 'mm': 51cb93a386Sopenharmony_ci sizePx = size * (96.0 / 25.4); 52cb93a386Sopenharmony_ci break; 53cb93a386Sopenharmony_ci case 'q': // quarter millimeters 54cb93a386Sopenharmony_ci sizePx = size * (96.0 / 25.4 / 4); 55cb93a386Sopenharmony_ci break; 56cb93a386Sopenharmony_ci case '%': 57cb93a386Sopenharmony_ci sizePx = size * (defaultHeight / 75); 58cb93a386Sopenharmony_ci break; 59cb93a386Sopenharmony_ci } 60cb93a386Sopenharmony_ci return { 61cb93a386Sopenharmony_ci 'style': font[1], 62cb93a386Sopenharmony_ci 'variant': font[2], 63cb93a386Sopenharmony_ci 'weight': font[3], 64cb93a386Sopenharmony_ci 'sizePx': sizePx, 65cb93a386Sopenharmony_ci 'family': font[6].trim() 66cb93a386Sopenharmony_ci }; 67cb93a386Sopenharmony_ci} 68cb93a386Sopenharmony_ci 69cb93a386Sopenharmony_cifunction getTypeface(fontstr) { 70cb93a386Sopenharmony_ci var descriptors = parseFontString(fontstr); 71cb93a386Sopenharmony_ci var typeface = getFromFontCache(descriptors); 72cb93a386Sopenharmony_ci descriptors['typeface'] = typeface; 73cb93a386Sopenharmony_ci return descriptors; 74cb93a386Sopenharmony_ci} 75cb93a386Sopenharmony_ci 76cb93a386Sopenharmony_ci// null means use the default typeface (which is currently NotoMono) 77cb93a386Sopenharmony_civar fontCache = { 78cb93a386Sopenharmony_ci 'Noto Mono': { 79cb93a386Sopenharmony_ci '*': null, // is used if we have this font family, but not the right style/variant/weight 80cb93a386Sopenharmony_ci }, 81cb93a386Sopenharmony_ci 'monospace': { 82cb93a386Sopenharmony_ci '*': null, 83cb93a386Sopenharmony_ci } 84cb93a386Sopenharmony_ci}; 85cb93a386Sopenharmony_ci 86cb93a386Sopenharmony_ci// descriptors is like https://developer.mozilla.org/en-US/docs/Web/API/FontFace/FontFace 87cb93a386Sopenharmony_ci// The ones currently supported are family, style, variant, weight. 88cb93a386Sopenharmony_cifunction addToFontCache(typeface, descriptors) { 89cb93a386Sopenharmony_ci var key = (descriptors['style'] || 'normal') + '|' + 90cb93a386Sopenharmony_ci (descriptors['variant'] || 'normal') + '|' + 91cb93a386Sopenharmony_ci (descriptors['weight'] || 'normal'); 92cb93a386Sopenharmony_ci var fam = descriptors['family']; 93cb93a386Sopenharmony_ci if (!fontCache[fam]) { 94cb93a386Sopenharmony_ci // preload with a fallback to this typeface 95cb93a386Sopenharmony_ci fontCache[fam] = { 96cb93a386Sopenharmony_ci '*': typeface, 97cb93a386Sopenharmony_ci }; 98cb93a386Sopenharmony_ci } 99cb93a386Sopenharmony_ci fontCache[fam][key] = typeface; 100cb93a386Sopenharmony_ci} 101cb93a386Sopenharmony_ci 102cb93a386Sopenharmony_cifunction getFromFontCache(descriptors) { 103cb93a386Sopenharmony_ci var key = (descriptors['style'] || 'normal') + '|' + 104cb93a386Sopenharmony_ci (descriptors['variant'] || 'normal') + '|' + 105cb93a386Sopenharmony_ci (descriptors['weight'] || 'normal'); 106cb93a386Sopenharmony_ci var fam = descriptors['family']; 107cb93a386Sopenharmony_ci if (!fontCache[fam]) { 108cb93a386Sopenharmony_ci return null; 109cb93a386Sopenharmony_ci } 110cb93a386Sopenharmony_ci return fontCache[fam][key] || fontCache[fam]['*']; 111cb93a386Sopenharmony_ci} 112cb93a386Sopenharmony_ci 113cb93a386Sopenharmony_ciCanvasKit._testing['parseFontString'] = parseFontString; 114