Fix missing sidebearings from the hmtx table (see canvas.pdf)
This commit is contained in:
parent
e2d808a60f
commit
aea63a7051
77
fonts.js
77
fonts.js
@ -816,7 +816,6 @@ var Font = (function Font() {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
for (var i = 0; i < numRecords; i++) {
|
for (var i = 0; i < numRecords; i++) {
|
||||||
var table = records[i];
|
var table = records[i];
|
||||||
font.pos = start + table.offset;
|
font.pos = start + table.offset;
|
||||||
@ -824,7 +823,7 @@ var Font = (function Font() {
|
|||||||
var format = int16(font.getBytes(2));
|
var format = int16(font.getBytes(2));
|
||||||
var length = int16(font.getBytes(2));
|
var length = int16(font.getBytes(2));
|
||||||
var language = int16(font.getBytes(2));
|
var language = int16(font.getBytes(2));
|
||||||
|
|
||||||
if (format == 0 && numRecords > 1) {
|
if (format == 0 && numRecords > 1) {
|
||||||
// Characters below 0x20 are controls characters that are hardcoded
|
// Characters below 0x20 are controls characters that are hardcoded
|
||||||
// into the platform so if some characters in the font are assigned
|
// into the platform so if some characters in the font are assigned
|
||||||
@ -840,7 +839,7 @@ var Font = (function Font() {
|
|||||||
rewrite = true;
|
rewrite = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rewrite) {
|
if (rewrite) {
|
||||||
var glyphs = [];
|
var glyphs = [];
|
||||||
for (var j = 0x20; j < 256; j++) {
|
for (var j = 0x20; j < 256; j++) {
|
||||||
@ -918,7 +917,7 @@ var Font = (function Font() {
|
|||||||
var header = readOpenTypeHeader(font);
|
var header = readOpenTypeHeader(font);
|
||||||
var numTables = header.numTables;
|
var numTables = header.numTables;
|
||||||
|
|
||||||
var cmap, maxp;
|
var cmap, maxp, hhea, hmtx;
|
||||||
var tables = [];
|
var tables = [];
|
||||||
for (var i = 0; i < numTables; i++) {
|
for (var i = 0; i < numTables; i++) {
|
||||||
var table = readTableEntry(font);
|
var table = readTableEntry(font);
|
||||||
@ -928,6 +927,10 @@ var Font = (function Font() {
|
|||||||
cmap = table;
|
cmap = table;
|
||||||
else if (table.tag == 'maxp')
|
else if (table.tag == 'maxp')
|
||||||
maxp = table;
|
maxp = table;
|
||||||
|
else if (table.tag == 'hhea')
|
||||||
|
hhea = table;
|
||||||
|
else if (table.tag == 'hmtx')
|
||||||
|
hmtx = table;
|
||||||
|
|
||||||
requiredTables.splice(index, 1);
|
requiredTables.splice(index, 1);
|
||||||
}
|
}
|
||||||
@ -944,7 +947,7 @@ var Font = (function Font() {
|
|||||||
// table
|
// table
|
||||||
var numTables = header.numTables + requiredTables.length;
|
var numTables = header.numTables + requiredTables.length;
|
||||||
var offsets = {
|
var offsets = {
|
||||||
currentOffset: 0,
|
currentOffset: 0,
|
||||||
virtualOffset: numTables * (4 * 4)
|
virtualOffset: numTables * (4 * 4)
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -952,29 +955,45 @@ var Font = (function Font() {
|
|||||||
// of missing tables
|
// of missing tables
|
||||||
createOpenTypeHeader('\x00\x01\x00\x00', ttf, offsets, numTables);
|
createOpenTypeHeader('\x00\x01\x00\x00', ttf, offsets, numTables);
|
||||||
|
|
||||||
if (requiredTables.indexOf('OS/2') != -1) {
|
if (requiredTables.indexOf('OS/2') != -1) {
|
||||||
tables.push({
|
tables.push({
|
||||||
tag: 'OS/2',
|
tag: 'OS/2',
|
||||||
data: stringToArray(createOS2Table(properties))
|
data: stringToArray(createOS2Table(properties))
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ensure the hmtx tables contains an advance width and a sidebearing
|
||||||
|
// for the number of glyphs declared in the maxp table
|
||||||
|
font.pos = (font.start ? font.start : 0) + maxp.offset;
|
||||||
|
var version = int16(font.getBytes(4));
|
||||||
|
var numGlyphs = int16(font.getBytes(2));
|
||||||
|
|
||||||
|
font.pos = (font.start ? font.start : 0) + hhea.offset;
|
||||||
|
font.pos += hhea.length - 2;
|
||||||
|
var numOfHMetrics = int16(font.getBytes(2));
|
||||||
|
|
||||||
|
var numOfSidebearings = numGlyphs - numOfHMetrics;
|
||||||
|
var numMissing = numOfSidebearings - (hmtx.length - numOfHMetrics * 4);
|
||||||
|
if (numMissing > 0) {
|
||||||
|
font.pos = (font.start ? font.start : 0) + hmtx.offset;
|
||||||
|
var metrics = "";
|
||||||
|
for (var i = 0; i < hmtx.length; i++)
|
||||||
|
metrics += String.fromCharCode(font.getByte());
|
||||||
|
for (var i = 0; i < numMissing; i++)
|
||||||
|
metrics += "\x00\x00";
|
||||||
|
hmtx.data = stringToArray(metrics);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Replace the old CMAP table with a shiny new one
|
// Replace the old CMAP table with a shiny new one
|
||||||
if (properties.type == 'CIDFontType2') {
|
if (properties.type == 'CIDFontType2') {
|
||||||
// Type2 composite fonts map characters directly to glyphs so the cmap
|
// Type2 composite fonts map characters directly to glyphs so the cmap
|
||||||
// table must be replaced.
|
// table must be replaced.
|
||||||
|
|
||||||
var glyphs = [];
|
var glyphs = [];
|
||||||
var charset = properties.charset;
|
var charset = properties.charset;
|
||||||
if (!charset.length) {
|
if (!charset.length) {
|
||||||
// PDF did not contain a GIDMap for the font so create an identity cmap
|
// Type2 composite fonts map characters directly to glyphs so the cmap
|
||||||
|
|
||||||
// First get the number of glyphs from the maxp table
|
|
||||||
font.pos = (font.start ? font.start : 0) + maxp.offset;
|
|
||||||
var version = int16(font.getBytes(4));
|
|
||||||
var numGlyphs = int16(font.getBytes(2));
|
|
||||||
|
|
||||||
// Now create an identity mapping
|
|
||||||
for (var i = 1; i < numGlyphs; i++) {
|
for (var i = 1; i < numGlyphs; i++) {
|
||||||
glyphs.push({
|
glyphs.push({
|
||||||
unicode: i
|
unicode: i
|
||||||
@ -983,27 +1002,25 @@ var Font = (function Font() {
|
|||||||
} else {
|
} else {
|
||||||
for (var i = 1; i < charset.length; i++) {
|
for (var i = 1; i < charset.length; i++) {
|
||||||
var index = charset.indexOf(i);
|
var index = charset.indexOf(i);
|
||||||
if (index != -1) {
|
if (index == -1)
|
||||||
glyphs.push({
|
|
||||||
unicode: index
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
glyphs.push({
|
||||||
|
unicode: index
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!cmap) {
|
if (!cmap) {
|
||||||
// Font did not contain a cmap
|
cmap = {
|
||||||
tables.push({
|
|
||||||
tag: 'cmap',
|
tag: 'cmap',
|
||||||
data: createCMapTable(glyphs)
|
data: null
|
||||||
})
|
};
|
||||||
} else {
|
tables.push(cmap);
|
||||||
cmap.data = createCMapTable(glyphs);
|
|
||||||
}
|
}
|
||||||
|
cmap.data = createCMapTable(glyphs);
|
||||||
} else {
|
} else {
|
||||||
replaceCMapTable(cmap, font, properties);
|
replaceCMapTable(cmap, font, properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rewrite the 'post' table if needed
|
// Rewrite the 'post' table if needed
|
||||||
|
Loading…
x
Reference in New Issue
Block a user