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