font-inspector.html
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <title>opentype.js font inspector</title> 5 <meta name="description" content="A JavaScript library to manipulate the letterforms of text from the browser or node.js."> 6 <meta charset="utf-8"> 7 <link rel="stylesheet" href="site.css"> 8 <script type="text/javascript" src="dist/opentype.js"></script> 9 </head> 10 <body> 11 <div class="header"> 12 <div class="container"> 13 <h1>opentype.js</h1> 14 <nav> 15 <a href="index.html">Home</a> 16 <a href="font-inspector.html">Font Inspector</a> 17 <a href="glyph-inspector.html">Glyph Inspector</a> 18 </nav> 19 <nav class="right"> 20 <a class="github" href="https://github.com/nodebox/opentype.js">Fork me on GitHub</a> 21 <a class="gitter" href="https://gitter.im/nodebox/opentype.js">Chat on Gitter</a> 22 </nav> 23 </div> 24 </div> 25 26 <div class="container"> 27 28 <div class="explain"> 29 <h1>Font Inspector</h1> 30 <small>opentype.js is an OpenType and TrueType font parser. Here you can inspect the raw font metadata.</small> 31 </div> 32 33 <input id="file" type="file"> 34 <span class="info" id="font-name">Roboto-Black</span> 35 <canvas id="preview" width="940" height="50" class="text"></canvas> 36 <div id="message"></div> 37 38 <hr> 39 40 <div id="font-data"> 41 <h3 class="collapsed">Font Header table <a href="https://www.microsoft.com/typography/OTSPEC/head.htm" target="_blank">head</a></h3> 42 <dl id="head-table"><dt>Undefined</dt></dl> 43 44 <h3 class="collapsed">Horizontal Header table <a href="https://www.microsoft.com/typography/OTSPEC/hhea.htm" target="_blank">hhea</a></h3> 45 <dl id="hhea-table"><dt>Undefined</dt></dl> 46 47 <h3 class="collapsed">Maximum Profile table <a href="https://www.microsoft.com/typography/OTSPEC/maxp.htm" target="_blank">maxp</a></h3> 48 <dl id="maxp-table"><dt>Undefined</dt></dl> 49 50 <h3 class="collapsed">Naming table <a href="https://www.microsoft.com/typography/OTSPEC/name.htm" target="_blank">name</a></h3> 51 <dl id="name-table"><dt>Undefined</dt></dl> 52 53 <h3 class="collapsed">OS/2 and Windows Metrics table <a href="https://www.microsoft.com/typography/OTSPEC/os2.htm" target="_blank">OS/2</a></h3> 54 <dl id="os2-table"><dt>Undefined</dt></dl> 55 56 <h3 class="collapsed">PostScript table <a href="https://www.microsoft.com/typography/OTSPEC/post.htm" target="_blank">post</a></h3> 57 <dl id="post-table"><dt>Undefined</dt></dl> 58 59 <h3 class="collapsed">Character To Glyph Index Mapping Table <a href="https://www.microsoft.com/typography/OTSPEC/cmap.htm" target="_blank">cmap</a></h3> 60 <dl id="cmap-table"><dt>Undefined</dt></dl> 61 62 <h3 class="collapsed">Font Variations table <a href="https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6fvar.html" target="_blank">fvar</a></h3> 63 <dl id="fvar-table"><dt>Undefined</dt></dl> 64 65 <h3 class="collapsed">Metadata table <a href="https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6meta.html" target="_blank">meta</a></h3> 66 <dl id="meta-table"><dt>Undefined</dt></dl> 67 68 <h3 class="collapsed">Control Value Table <a href="https://www.microsoft.com/typography/OTSPEC/cvt.htm" target="_blank">cvt</a></h3> 69 <dl id="cvt-table"><dt>Undefined</dt></dl> 70 71 <h3 class="collapsed">CVT Program <a href="https://www.microsoft.com/typography/OTSPEC/prep.htm" target="_blank">prep</a></h3> 72 <dl id="prep-table"><dt>Undefined</dt></dl> 73 74 <h3 class="collapsed">Font program <a href="https://www.microsoft.com/typography/OTSPEC/fpgm.htm" target="_blank">fpgm</a></h3> 75 <dl id="fpgm-table"><dt>Undefined</dt></dl> 76 77 <h3 class="collapsed">Glyph Substitution Table <a href="https://www.microsoft.com/typography/OTSPEC/GSUB.htm" target="_blank">GSUB</a></h3> 78 <dl id="gsub-table"><dt>Undefined</dt></dl> 79 80 <h3 class="collapsed">Kerning <a href="https://www.microsoft.com/typography/otspec/kern.htm" target="_blank">kern</a></h3> 81 <dl id="kern-table"><dt>Undefined</dt></dl> 82 </div> 83 84 <hr> 85 86 <div class="explain"> 87 <h1>Free Software</h1> 88 <p>opentype.js is available on <a href="https://github.com/nodebox/opentype.js">GitHub</a> under the <a href="https://raw.github.com/nodebox/opentype.js/master/LICENSE">MIT License</a>.</p> 89 <p>Copyright © 2017 Frederik De Bleser.</p> 90 </div> 91 92 <hr> 93 </div> 94 95 96 <script type="text/javascript"> 97 var font = null; 98 var fontSize = 32; 99 var textToRender = 'Grumpy wizards make toxic brew for the evil Queen and Jack.'; 100 var previewPath = null; 101 102 function escapeHtml(unsafe) { 103 return unsafe 104 .replace(/&/g, '&') 105 .replace(/</g, '<') 106 .replace(/>/g, '>') 107 .replace(/\u0022/g, '"') 108 .replace(/\u0027/g, '''); 109 } 110 111 function enableHighDPICanvas(canvas) { 112 if (typeof canvas === 'string') { 113 canvas = document.getElementById(canvas); 114 } 115 var pixelRatio = window.devicePixelRatio || 1; 116 if (pixelRatio === 1) return; 117 var oldWidth = canvas.width; 118 var oldHeight = canvas.height; 119 canvas.width = oldWidth * pixelRatio; 120 canvas.height = oldHeight * pixelRatio; 121 canvas.style.width = oldWidth + 'px'; 122 canvas.style.height = oldHeight + 'px'; 123 canvas.getContext('2d').scale(pixelRatio, pixelRatio); 124 } 125 126 function renderText() { 127 if (!font) return; 128 129 var previewCanvas = document.getElementById('preview'); 130 var previewCtx = previewCanvas.getContext("2d"); 131 previewCtx.clearRect(0, 0, previewCanvas.width, previewCanvas.height); 132 font.draw(previewCtx, textToRender, 0, 32, fontSize, { 133 kerning: true, 134 features: { 135 liga: true, 136 rlig: true 137 } 138 }); 139 } 140 141 function showErrorMessage(message) { 142 var el = document.getElementById('message'); 143 if (!message || message.trim().length === 0) { 144 el.style.display = 'none'; 145 } else { 146 el.style.display = 'block'; 147 } 148 el.innerHTML = message; 149 } 150 151 function sortKeys(dict) { 152 var keys = []; 153 for (var key in dict) { 154 keys.push(key); 155 } 156 keys.sort(); 157 return keys; 158 } 159 160 function displayNames(names) { 161 var html = ''; 162 properties = sortKeys(names); 163 for (var i = 0; i < properties.length; i++) { 164 var property = properties[i]; 165 html += '<dt>'+escapeHtml(property)+'</dt><dd>'; 166 var translations = names[property]; 167 var langs = sortKeys(translations); 168 for (var j = 0; j < langs.length; j++) { 169 var lang = langs[j]; 170 var esclang = escapeHtml(lang); 171 html += '<span class="langtag">' + esclang 172 + '</span> <span class="langname" lang=' + esclang + '>' 173 + escapeHtml(translations[lang]) + '</span> '; 174 } 175 html += '</dd>'; 176 } 177 178 document.getElementById('name-table').innerHTML = html; 179 } 180 181 function displayFontData() { 182 var html, tablename, table, property, value; 183 184 for (tablename in font.tables) { 185 table = font.tables[tablename]; 186 if (tablename == 'name') { 187 displayNames(table); 188 continue; 189 } 190 191 html = ''; 192 for (property in table) { 193 value = table[property]; 194 html += '<dt>'+property+'</dt><dd>'; 195 if (Array.isArray(value) && typeof value[0] === 'object') { 196 html += value.map(function(item) { 197 return JSON.stringify(item); 198 }).join('<br>'); 199 } else if (typeof value === 'object') { 200 html += JSON.stringify(value); 201 } else if (['created', 'modified'].indexOf(property) > -1) { 202 var date = new Date(value * 1000); 203 html += date; 204 } 205 else { 206 html += value; 207 } 208 html += '</dd>'; 209 } 210 var element = document.getElementById(tablename+"-table"); 211 if (element) { 212 element.innerHTML = html; 213 } 214 } 215 216 if(font.kerningPairs) { 217 var element = document.getElementById("kern-table"); 218 if (element) { 219 element.innerHTML = '<dt>' + Object.keys(font.kerningPairs).length + ' Pairs</dt><dd>' + JSON.stringify(font.kerningPairs) + '</dd>'; 220 } 221 } 222 } 223 224 function onFontLoaded(font) { 225 window.font = font; 226 renderText(); 227 displayFontData(); 228 } 229 230 function onReadFile(e) { 231 document.getElementById('font-name').innerHTML = ''; 232 var file = e.target.files[0]; 233 var reader = new FileReader(); 234 reader.onload = function(e) { 235 try { 236 font = opentype.parse(e.target.result); 237 onFontLoaded(font); 238 showErrorMessage(''); 239 } catch (err) { 240 showErrorMessage(err.toString()); 241 if (err.stack) console.log(err.stack); 242 throw(err); 243 } 244 }; 245 reader.onerror = function(err) { 246 showErrorMessage(err.toString()); 247 }; 248 249 reader.readAsArrayBuffer(file); 250 } 251 252 var fontFileName = 'fonts/Roboto-Black.ttf'; 253 254 document.getElementById('font-name').innerHTML = fontFileName.split('/')[1]; 255 256 var fileButton = document.getElementById('file'); 257 fileButton.addEventListener('change', onReadFile, false); 258 259 var tableHeaders = document.getElementById('font-data').getElementsByTagName('h3'); 260 for(var i = tableHeaders.length; i--; ) { 261 tableHeaders[i].addEventListener('click', function(e) { 262 e.target.className = (e.target.className === 'collapsed') ? 'expanded' : 'collapsed'; 263 }, false); 264 } 265 266 enableHighDPICanvas('preview'); 267 268 opentype.load(fontFileName, function(err, font) { 269 var amount, glyph, ctx, x, y, fontSize; 270 if (err) { 271 showErrorMessage(err.toString()); 272 return; 273 } 274 onFontLoaded(font); 275 }); 276 </script> 277 </body> 278 </html>