Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

implement graceful loading via logging severity levels #648

Draft
wants to merge 11 commits into
base: master
Choose a base branch
from
17 changes: 15 additions & 2 deletions docs/font-inspector.html
Original file line number Diff line number Diff line change
Expand Up @@ -144,12 +144,24 @@ <h1>Free Software</h1>
var el = document.getElementById('message');
if (!message || message.trim().length === 0) {
el.style.display = 'none';
el.innerHTML = '';
} else {
el.style.display = 'block';
el.innerHTML = `<p class="message-type-1">${message}</p>`;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use innerText and set the class to el directly

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then we'd loose the wrapping paragraph element and set the class to the outer message area. But you're right, we definitely don't want the message to be interpreted as HTML. so I'll have to create a new paragraph element and set the class and text on that.

}
el.innerHTML = message;
}

function appendErrorMessage(message, type) {
var el = document.getElementById('message');
el.style.display = 'block';
el.innerHTML += `<p class="message-type-${type}">${message}</p>`;
}

document.addEventListener('opentypejs:message', function(event) {
const message = event.detail.message;
appendErrorMessage(message.toString(), message.type);
});

function sortKeys(dict) {
var keys = [];
for (var key in dict) {
Expand Down Expand Up @@ -257,10 +269,11 @@ <h1>Free Software</h1>
}
try {
const data = await file.arrayBuffer();
onFontLoaded(opentype.parse(isWoff2 ? Module.decompress(data) : data));
showErrorMessage('');
onFontLoaded(opentype.parse(isWoff2 ? Module.decompress(data) : data));
} catch (err) {
showErrorMessage(err.toString());
throw err;
}
}
form.file.onchange = function(e) {
Expand Down
64 changes: 48 additions & 16 deletions docs/glyph-inspector.html
Original file line number Diff line number Diff line change
Expand Up @@ -92,12 +92,24 @@ <h1>Free Software</h1>
var el = document.getElementById('message');
if (!message || message.trim().length === 0) {
el.style.display = 'none';
el.innerHTML = '';
} else {
el.style.display = 'block';
el.innerHTML = `<p class="message-type-1">${message}</p>`;
}
el.innerHTML = message;
}

function appendErrorMessage(message, type) {
var el = document.getElementById('message');
el.style.display = 'block';
el.innerHTML += `<p class="message-type-${type}">${message}</p>`;
}

document.addEventListener('opentypejs:message', function(event) {
const message = event.detail.message;
appendErrorMessage(message.toString(), message.type);
});

function pathCommandToString(cmd) {
var str = '<strong>' + cmd.type + '</strong> ' +
((cmd.x !== undefined) ? 'x='+cmd.x+' y='+cmd.y+' ' : '') +
Expand Down Expand Up @@ -273,13 +285,19 @@ <h1>Free Software</h1>
var cellMarkSize = 4;
var ctx = canvas.getContext('2d');
ctx.clearRect(0, 0, cellWidth, cellHeight);
if (glyphIndex >= window.font.numGlyphs) return;
const nGlyphs = window.font.numGlyphs || window.font.nGlyphs;
if (glyphIndex >= nGlyphs) return;

ctx.fillStyle = '#606060';
ctx.font = '9px sans-serif';
ctx.fillText(glyphIndex, 1, cellHeight-1);
var glyph = window.font.glyphs.get(glyphIndex),
glyphWidth = glyph.advanceWidth * fontScale,
const glyph = window.font.glyphs.get(glyphIndex);
if (!glyph.advanceWidth) {
// force calculation of path data
glyph.getPath();
}
const advanceWidth = glyph.advanceWidth;
let glyphWidth = glyph.advanceWidth * fontScale,
xmin = (cellWidth - glyphWidth)/2,
xmax = (cellWidth + glyphWidth)/2,
x0 = xmin;
Expand Down Expand Up @@ -314,7 +332,7 @@ <h1>Free Software</h1>
h = glyphBgCanvas.height / pixelRatio,
glyphW = w - glyphMargin*2,
glyphH = h - glyphMargin*2,
head = font.tables.head,
head = getFontDimensions(font),
maxHeight = head.yMax - head.yMin,
ctx = glyphBgCanvas.getContext('2d');

Expand All @@ -331,20 +349,31 @@ <h1>Free Software</h1>
ctx.clearRect(0, 0, w, h);
ctx.fillStyle = '#a0a0a0';
hline('Baseline', 0);
hline('yMax', font.tables.head.yMax);
hline('yMin', font.tables.head.yMin);
hline('Ascender', font.tables.hhea.ascender);
hline('Descender', font.tables.hhea.descender);
hline('Typo Ascender', font.tables.os2.sTypoAscender);
hline('Typo Descender', font.tables.os2.sTypoDescender);
hline('yMax', head.yMax);
hline('yMin', head.yMin);
hline('Ascender', font.tables.hhea ? font.tables.hhea.ascender : font.ascender || head.yMax);
hline('Descender', font.tables.hhea ? font.tables.hhea.descender : font.descender || head.yMin);
if (font.tables.os2) {
hline('Typo Ascender', font.tables.os2.sTypoAscender);
hline('Typo Descender', font.tables.os2.sTypoDescender);
}
}

function getFontDimensions(font) {
return font.isCFFFont ? {
xMin: font.tables.cff.topDict.fontBBox[0],
xMax: font.tables.cff.topDict.fontBBox[3] || 1000,
yMin: font.tables.cff.topDict.fontBBox[1] || -200,
yMax: font.tables.cff.topDict.fontBBox[2] || 1000
} :font.tables.head;
}

function onFontLoaded(font) {
window.font = font;

var w = cellWidth - cellMarginLeftRight * 2,
h = cellHeight - cellMarginTop - cellMarginBottom,
head = font.tables.head,
head = getFontDimensions(font),
maxHeight = head.yMax - head.yMin;
fontScale = Math.min(w/(head.xMax - head.xMin), h/maxHeight);
fontSize = fontScale * font.unitsPerEm;
Expand All @@ -353,10 +382,11 @@ <h1>Free Software</h1>
var pagination = document.getElementById("pagination");
pagination.innerHTML = '';
var fragment = document.createDocumentFragment();
var numPages = Math.ceil(font.numGlyphs / cellCount);
const nGlyphs = font.numGlyphs || font.nGlyphs;
var numPages = Math.ceil(nGlyphs / cellCount);
for(var i = 0; i < numPages; i++) {
var link = document.createElement('span');
var lastIndex = Math.min(font.numGlyphs-1, (i+1)*cellCount-1);
var lastIndex = Math.min(nGlyphs-1, (i+1)*cellCount-1);
link.textContent = i*cellCount + '-' + lastIndex;
link.id = 'p' + i;
link.addEventListener('click', pageSelect, false);
Expand All @@ -378,7 +408,8 @@ <h1>Free Software</h1>
var firstGlyphIndex = pageSelected*cellCount,
cellIndex = +event.target.id.substr(1),
glyphIndex = firstGlyphIndex + cellIndex;
if (glyphIndex < window.font.numGlyphs) {
const nGlyphs = window.font.numGlyphs || window.font.nGlyphs;
if (glyphIndex < nGlyphs) {
displayGlyph(glyphIndex);
displayGlyphData(glyphIndex);
}
Expand Down Expand Up @@ -410,10 +441,11 @@ <h1>Free Software</h1>
}
try {
const data = await file.arrayBuffer();
onFontLoaded(opentype.parse(isWoff2 ? Module.decompress(data) : data));
showErrorMessage('');
onFontLoaded(opentype.parse(isWoff2 ? Module.decompress(data) : data));
} catch (err) {
showErrorMessage(err.toString());
throw err;
}
}

Expand Down
17 changes: 15 additions & 2 deletions docs/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -169,12 +169,24 @@ <h1>Free Software</h1>
var el = document.getElementById('message');
if (!message || message.trim().length === 0) {
el.style.display = 'none';
el.innerHTML = '';
} else {
el.style.display = 'block';
el.innerHTML = `<p class="message-type-1">${message}</p>`;
}
el.innerHTML = message;
}

function appendErrorMessage(message, type) {
var el = document.getElementById('message');
el.style.display = 'block';
el.innerHTML += `<p class="message-type-${type}">${message}</p>`;
}

document.addEventListener('opentypejs:message', function(event) {
const message = event.detail.message;
appendErrorMessage(message.toString(), message.type);
});

function onFontLoaded(font) {
window.font = font;

Expand Down Expand Up @@ -217,10 +229,11 @@ <h1>Free Software</h1>
}
try {
const data = await file.arrayBuffer();
onFontLoaded(opentype.parse(isWoff2 ? Module.decompress(data) : data));
showErrorMessage('');
onFontLoaded(opentype.parse(isWoff2 ? Module.decompress(data) : data));
} catch (err) {
showErrorMessage(err.toString());
throw err;
}
}

Expand Down
21 changes: 17 additions & 4 deletions docs/site.css
Original file line number Diff line number Diff line change
Expand Up @@ -107,14 +107,27 @@ canvas.text {

#message {
position: relative;
top: -3px;
background: red;
color: white;
padding: 1px 5px;
font-weight: bold;
border-radius: 2px;
display: none;
clear: both;
padding-top: 1px;
}

#message p {
margin: 2px 0;
padding: 2px 5px;
border-radius: 0.25rem;
border: solid 1px;
background: #fff3cd;
color: #856404;
border-color: #ffeeba;
}

#message p.message-type-1 {
background: #f8d7da;
color: #721c24;
border-color: #f5c6cb;
}

.message {
Expand Down
4 changes: 3 additions & 1 deletion src/encoding.js
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,9 @@ function addGlyphNamesAll(font) {
const c = charCodes[i];
const glyphIndex = glyphIndexMap[c];
glyph = font.glyphs.get(glyphIndex);
glyph.addUnicode(parseInt(c));
if(glyph) {
glyph.addUnicode(parseInt(c));
}
}

for (let i = 0; i < font.glyphs.length; i += 1) {
Expand Down
19 changes: 13 additions & 6 deletions src/font.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,15 @@ import Substitution from './substitution.js';
import { isBrowser, checkArgument } from './util.js';
import HintingTrueType from './hintingtt.js';
import Bidi from './bidi.js';
import { logger, ErrorTypes, MessageLogger } from './logger.js';

function createDefaultNamesInfo(options) {
return {
fontFamily: {en: options.familyName || ' '},
fontSubfamily: {en: options.styleName || ' '},
fullName: {en: options.fullName || options.familyName + ' ' + options.styleName},
fullName: {en: options.fullName || (options.familyName || '') + ' ' + (options.styleName || '')},
// postScriptName may not contain any whitespace
postScriptName: {en: options.postScriptName || (options.familyName + options.styleName).replace(/\s/g, '')},
postScriptName: {en: options.postScriptName || ((options.familyName || '') + (options.styleName || '')).replace(/\s/g, '')},
designer: {en: options.designer || ' '},
designerURL: {en: options.designerURL || ' '},
manufacturer: {en: options.manufacturer || ' '},
Expand Down Expand Up @@ -502,14 +503,17 @@ Font.prototype.getEnglishName = function(name) {

/**
* Validate
* @type {MessageLogger}
*/
Font.prototype.validation = new MessageLogger();
Font.prototype.ErrorTypes = ErrorTypes;
Font.prototype.validate = function() {
const warnings = [];
const validationMessages = [];
const _this = this;

function assert(predicate, message) {
if (!predicate) {
warnings.push(message);
validationMessages.push(_this.validation.add(message, _this.ErrorTypes.WARNING));
}
}

Expand All @@ -528,6 +532,8 @@ Font.prototype.validate = function() {

// Dimension information
assert(this.unitsPerEm > 0, 'No unitsPerEm specified.');

return validationMessages;
};

/**
Expand All @@ -542,7 +548,7 @@ Font.prototype.toTables = function() {
* @deprecated Font.toBuffer is deprecated. Use Font.toArrayBuffer instead.
*/
Font.prototype.toBuffer = function() {
console.warn('Font.toBuffer is deprecated. Use Font.toArrayBuffer instead.');
logger.add('Font.toBuffer is deprecated. Use Font.toArrayBuffer instead.', this.ErrorTypes.DEPRECATED);
return this.toArrayBuffer();
};
/**
Expand Down Expand Up @@ -585,7 +591,7 @@ Font.prototype.download = function(fileName) {
event.initEvent('click', true, false);
link.dispatchEvent(event);
} else {
console.warn('Font file could not be downloaded. Try using a different browser.');
logger.add('Font file could not be downloaded. Try using a different browser.');
}
} else {
const fs = require('fs');
Expand Down Expand Up @@ -658,3 +664,4 @@ Font.prototype.usWeightClasses = {
};

export default Font;
export { createDefaultNamesInfo };
11 changes: 9 additions & 2 deletions src/glyphset.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// The GlyphSet object

import Glyph from './glyph.js';
import { logger } from './logger.js';

// Define a property on the glyph that depends on the path being loaded.
function defineDependentProperty(glyph, externalName, internalName) {
Expand Down Expand Up @@ -37,7 +38,6 @@ function GlyphSet(font, glyphs) {
this.glyphs[i] = glyph;
}
}

this.length = (glyphs && glyphs.length) || 0;
}

Expand All @@ -64,13 +64,20 @@ if(typeof Symbol !== 'undefined' && Symbol.iterator) {
GlyphSet.prototype.get = function(index) {
// this.glyphs[index] is 'undefined' when low memory mode is on. glyph is pushed on request only.
if (this.glyphs[index] === undefined) {
if (typeof this.font._push !== 'function') {
if (index !== null) {
logger.add(`Trying to access unknown glyph at index ${index}`, logger.ErrorTypes.WARNING);
}
return;
}

this.font._push(index);
if (typeof this.glyphs[index] === 'function') {
this.glyphs[index] = this.glyphs[index]();
}

let glyph = this.glyphs[index];
let unicodeObj = this.font._IndexToUnicodeMap[index];
let unicodeObj = this.font._IndexToUnicodeMap && this.font._IndexToUnicodeMap[index];

if (unicodeObj) {
for (let j = 0; j < unicodeObj.unicodes.length; j++)
Expand Down
Loading
Loading