Browse Source

Remove empty gryphs; improve glyph unicode movements

notmasteryet 13 years ago
parent
commit
19b670458e
  1. 80
      src/fonts.js

80
src/fonts.js

@ -1656,6 +1656,30 @@ var Font = (function FontClosure() {
glyf.data = newGlyfData.subarray(0, writeOffset); glyf.data = newGlyfData.subarray(0, writeOffset);
} }
function findEmptyGlyphs(locaTable, isGlyphLocationsLong, emptyGlyphIds) {
var itemSize, itemDecode;
if (isGlyphLocationsLong) {
itemSize = 4;
itemDecode = function fontItemDecodeLong(data, offset) {
return (data[offset] << 24) | (data[offset + 1] << 16) |
(data[offset + 2] << 8) | data[offset + 3];
};
} else {
itemSize = 2;
itemDecode = function fontItemDecode(data, offset) {
return (data[offset] << 9) | (data[offset + 1] << 1);
};
}
var data = locaTable.data, length = data.length;
var lastOffset = itemDecode(data, 0);
for (var i = itemSize, j = 0; i < length; i += itemSize, j++) {
var offset = itemDecode(data, i);
if (offset == lastOffset)
emptyGlyphIds[j] = true;
lastOffset = offset;
}
}
function readGlyphNameMap(post, properties) { function readGlyphNameMap(post, properties) {
var start = (font.start ? font.start : 0) + post.offset; var start = (font.start ? font.start : 0) + post.offset;
font.pos = start; font.pos = start;
@ -1782,11 +1806,15 @@ var Font = (function FontClosure() {
sanitizeMetrics(font, hhea, hmtx, numGlyphs); sanitizeMetrics(font, hhea, hmtx, numGlyphs);
sanitizeMetrics(font, vhea, vmtx, numGlyphs); sanitizeMetrics(font, vhea, vmtx, numGlyphs);
if (head && loca && glyf) {
var isGlyphLocationsLong = int16([head.data[50], head.data[51]]); var isGlyphLocationsLong = int16([head.data[50], head.data[51]]);
if (head && loca && glyf) {
sanitizeGlyphLocations(loca, glyf, numGlyphs, isGlyphLocationsLong); sanitizeGlyphLocations(loca, glyf, numGlyphs, isGlyphLocationsLong);
} }
var emptyGlyphIds = [];
if (glyf)
findEmptyGlyphs(loca, isGlyphLocationsLong, emptyGlyphIds);
// Sanitizer reduces the glyph advanceWidth to the maxAdvanceWidth // Sanitizer reduces the glyph advanceWidth to the maxAdvanceWidth
// Sometimes it's 0. That needs to be fixed // Sometimes it's 0. That needs to be fixed
if (hhea.data[10] == 0 && hhea.data[11] == 0) { if (hhea.data[10] == 0 && hhea.data[11] == 0) {
@ -1918,6 +1946,15 @@ var Font = (function FontClosure() {
} }
} }
// remove glyph references outside range of avaialable glyphs or empty
for (var i = ids.length - 1; i >= 0; i--) {
if (ids[i] < numGlyphs &&
(!emptyGlyphIds[ids[i]] || this.isSymbolicFont))
continue;
ids.splice(i, 1);
glyphs.splice(i, 1);
}
if (hasShortCmap && this.hasEncoding && !this.isSymbolicFont) { if (hasShortCmap && this.hasEncoding && !this.isSymbolicFont) {
// Re-encode short map encoding to unicode -- that simplifies the // Re-encode short map encoding to unicode -- that simplifies the
// resolution of MacRoman encoded glyphs logic for TrueType fonts: // resolution of MacRoman encoded glyphs logic for TrueType fonts:
@ -1951,9 +1988,11 @@ var Font = (function FontClosure() {
// Re-encode cmap encoding to unicode, based on the 'post' table data // Re-encode cmap encoding to unicode, based on the 'post' table data
// diffrence array or base encoding // diffrence array or base encoding
var reverseMap = []; var reverseMap = [];
for (var i = 0, ii = glyphs.length; i < ii; i++) for (var i = 0, ii = glyphs.length; i < ii; i++) {
reverseMap[glyphs[i].unicode] = i; reverseMap[glyphs[i].unicode] = i;
}
var backtrackReplacements = [];
for (var i = 0, ii = glyphs.length; i < ii; i++) { for (var i = 0, ii = glyphs.length; i < ii; i++) {
var code = glyphs[i].unicode; var code = glyphs[i].unicode;
var changeCode = false; var changeCode = false;
@ -1966,13 +2005,36 @@ var Font = (function FontClosure() {
} }
if (glyphName in GlyphsUnicode) { if (glyphName in GlyphsUnicode) {
var unicode = GlyphsUnicode[glyphName]; var unicode = GlyphsUnicode[glyphName];
if (!unicode || (unicode in reverseMap)) if (!unicode || reverseMap[unicode] === i)
continue; // unknown glyph name or its place is taken continue; // unknown glyph name or in its own place
glyphs[i].unicode = unicode; if (unicode in reverseMap) {
reverseMap[unicode] = i; backtrackReplacements[unicode] = {
index: i,
code: code,
changeCode: changeCode
};
continue; // its place is taken
}
var index = i;
while (true) {
glyphs[index].unicode = unicode;
reverseMap[unicode] = index;
if (changeCode) if (changeCode)
toFontChar[code] = unicode; toFontChar[code] = unicode;
// checking if available place can be used by other glyph
var backtrack = backtrackReplacements[code];
if (!backtrack)
break;
delete backtrackReplacements[code];
index = backtrack.index;
code = backtrack.code;
changeCode = backtrack.changeCode;
unicode = code;
}
} }
this.useToFontChar = true; this.useToFontChar = true;
} }
@ -1988,12 +2050,6 @@ var Font = (function FontClosure() {
this.useToFontChar = true; this.useToFontChar = true;
} }
// remove glyph references outside range of avaialable glyphs
for (var i = 0, ii = ids.length; i < ii; i++) {
if (ids[i] >= numGlyphs)
ids[i] = 0;
}
createGlyphNameMap(glyphs, ids, properties); createGlyphNameMap(glyphs, ids, properties);
this.glyphNameMap = properties.glyphNameMap; this.glyphNameMap = properties.glyphNameMap;

Loading…
Cancel
Save