Use cff glyph width in the hmtx table
This commit is contained in:
parent
84457b77ed
commit
a2c2f81167
@ -4306,12 +4306,16 @@ var Font = (function FontClosure() {
|
|||||||
// Horizontal metrics
|
// Horizontal metrics
|
||||||
builder.addTable('hmtx', (function fontFieldsHmtx() {
|
builder.addTable('hmtx', (function fontFieldsHmtx() {
|
||||||
var charstrings = font.charstrings;
|
var charstrings = font.charstrings;
|
||||||
|
var cffWidths = font.cff ? font.cff.widths : null;
|
||||||
var hmtx = '\x00\x00\x00\x00'; // Fake .notdef
|
var hmtx = '\x00\x00\x00\x00'; // Fake .notdef
|
||||||
for (var i = 1, ii = numGlyphs; i < ii; i++) {
|
for (var i = 1, ii = numGlyphs; i < ii; i++) {
|
||||||
// TODO: For CFF fonts the width should technically match th x in
|
var width = 0;
|
||||||
// the glyph, but it doesn't seem to matter.
|
if (charstrings) {
|
||||||
var charstring = charstrings ? charstrings[i - 1] : {};
|
var charstring = charstrings[i - 1];
|
||||||
var width = 'width' in charstring ? charstring.width : 0;
|
width = 'width' in charstring ? charstring.width : 0;
|
||||||
|
} else if (cffWidths) {
|
||||||
|
width = Math.ceil(cffWidths[i] || 0);
|
||||||
|
}
|
||||||
hmtx += string16(width) + string16(0);
|
hmtx += string16(width) + string16(0);
|
||||||
}
|
}
|
||||||
return hmtx;
|
return hmtx;
|
||||||
@ -5713,10 +5717,10 @@ var CFFFont = (function CFFFontClosure() {
|
|||||||
var CFFParser = (function CFFParserClosure() {
|
var CFFParser = (function CFFParserClosure() {
|
||||||
var CharstringValidationData = [
|
var CharstringValidationData = [
|
||||||
null,
|
null,
|
||||||
{ id: 'hstem', min: 2, resetStack: true, stem: true },
|
{ id: 'hstem', min: 2, stackClearing: true, stem: true },
|
||||||
null,
|
null,
|
||||||
{ id: 'vstem', min: 2, resetStack: true, stem: true },
|
{ id: 'vstem', min: 2, stackClearing: true, stem: true },
|
||||||
{ id: 'vmoveto', min: 1, resetStack: true },
|
{ id: 'vmoveto', min: 1, stackClearing: true },
|
||||||
{ id: 'rlineto', min: 2, resetStack: true },
|
{ id: 'rlineto', min: 2, resetStack: true },
|
||||||
{ id: 'hlineto', min: 1, resetStack: true },
|
{ id: 'hlineto', min: 1, resetStack: true },
|
||||||
{ id: 'vlineto', min: 1, resetStack: true },
|
{ id: 'vlineto', min: 1, resetStack: true },
|
||||||
@ -5726,16 +5730,16 @@ var CFFParser = (function CFFParserClosure() {
|
|||||||
{ id: 'return', min: 0, undefStack: true },
|
{ id: 'return', min: 0, undefStack: true },
|
||||||
null, // 12
|
null, // 12
|
||||||
null,
|
null,
|
||||||
null, // endchar
|
{ id: 'endchar', min: 0, stackClearing: true },
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
{ id: 'hstemhm', min: 2, resetStack: true, stem: true },
|
{ id: 'hstemhm', min: 2, stackClearing: true, stem: true },
|
||||||
null, // hintmask
|
{ id: 'hintmask', min: 0, stackClearing: true },
|
||||||
null, // cntrmask
|
{ id: 'cntrmask', min: 0, stackClearing: true },
|
||||||
{ id: 'rmoveto', min: 2, resetStack: true },
|
{ id: 'rmoveto', min: 2, stackClearing: true },
|
||||||
{ id: 'hmoveto', min: 1, resetStack: true },
|
{ id: 'hmoveto', min: 1, stackClearing: true },
|
||||||
{ id: 'vstemhm', min: 2, resetStack: true, stem: true },
|
{ id: 'vstemhm', min: 2, stackClearing: true, stem: true },
|
||||||
{ id: 'rcurveline', min: 8, resetStack: true },
|
{ id: 'rcurveline', min: 8, resetStack: true },
|
||||||
{ id: 'rlinecurve', min: 8, resetStack: true },
|
{ id: 'rlinecurve', min: 8, resetStack: true },
|
||||||
{ id: 'vvcurveto', min: 4, resetStack: true },
|
{ id: 'vvcurveto', min: 4, resetStack: true },
|
||||||
@ -5841,6 +5845,7 @@ var CFFParser = (function CFFParserClosure() {
|
|||||||
var charStringsAndSeacs = this.parseCharStrings(charStringOffset);
|
var charStringsAndSeacs = this.parseCharStrings(charStringOffset);
|
||||||
cff.charStrings = charStringsAndSeacs.charStrings;
|
cff.charStrings = charStringsAndSeacs.charStrings;
|
||||||
cff.seacs = charStringsAndSeacs.seacs;
|
cff.seacs = charStringsAndSeacs.seacs;
|
||||||
|
cff.widths = charStringsAndSeacs.widths;
|
||||||
|
|
||||||
var fontMatrix = topDict.getByName('FontMatrix');
|
var fontMatrix = topDict.getByName('FontMatrix');
|
||||||
if (fontMatrix) {
|
if (fontMatrix) {
|
||||||
@ -6058,6 +6063,7 @@ var CFFParser = (function CFFParserClosure() {
|
|||||||
parseCharStrings: function CFFParser_parseCharStrings(charStringOffset) {
|
parseCharStrings: function CFFParser_parseCharStrings(charStringOffset) {
|
||||||
var charStrings = this.parseIndex(charStringOffset).obj;
|
var charStrings = this.parseIndex(charStringOffset).obj;
|
||||||
var seacs = [];
|
var seacs = [];
|
||||||
|
var widths = [];
|
||||||
var count = charStrings.count;
|
var count = charStrings.count;
|
||||||
for (var i = 0; i < count; i++) {
|
for (var i = 0; i < count; i++) {
|
||||||
var charstring = charStrings.get(i);
|
var charstring = charStrings.get(i);
|
||||||
@ -6069,6 +6075,7 @@ var CFFParser = (function CFFParserClosure() {
|
|||||||
var valid = true;
|
var valid = true;
|
||||||
var data = charstring;
|
var data = charstring;
|
||||||
var length = data.length;
|
var length = data.length;
|
||||||
|
var firstStackClearing = true;
|
||||||
for (var j = 0; j < length;) {
|
for (var j = 0; j < length;) {
|
||||||
var value = data[j++];
|
var value = data[j++];
|
||||||
var validationCommand = null;
|
var validationCommand = null;
|
||||||
@ -6098,6 +6105,7 @@ var CFFParser = (function CFFParserClosure() {
|
|||||||
valid = false;
|
valid = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
validationCommand = CharstringValidationData[value];
|
||||||
} else if (value >= 32 && value <= 246) { // number
|
} else if (value >= 32 && value <= 246) { // number
|
||||||
stack[stackSize] = value - 139;
|
stack[stackSize] = value - 139;
|
||||||
stackSize++;
|
stackSize++;
|
||||||
@ -6115,7 +6123,8 @@ var CFFParser = (function CFFParserClosure() {
|
|||||||
} else if (value === 19 || value === 20) {
|
} else if (value === 19 || value === 20) {
|
||||||
hints += stackSize >> 1;
|
hints += stackSize >> 1;
|
||||||
j += (hints + 7) >> 3; // skipping right amount of hints flag data
|
j += (hints + 7) >> 3; // skipping right amount of hints flag data
|
||||||
stackSize = 0;
|
stackSize %= 2;
|
||||||
|
validationCommand = CharstringValidationData[value];
|
||||||
} else {
|
} else {
|
||||||
validationCommand = CharstringValidationData[value];
|
validationCommand = CharstringValidationData[value];
|
||||||
}
|
}
|
||||||
@ -6132,17 +6141,35 @@ var CFFParser = (function CFFParserClosure() {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (firstStackClearing && validationCommand.stackClearing) {
|
||||||
|
firstStackClearing = false;
|
||||||
|
// the optional character width can be found before the first
|
||||||
|
// stack-clearing command arguments
|
||||||
|
stackSize -= validationCommand.min;
|
||||||
|
if (stackSize >= 2 && validationCommand.stem) {
|
||||||
|
// there are even amount of arguments for stem commands
|
||||||
|
stackSize %= 2;
|
||||||
|
} else if (stackSize > 1) {
|
||||||
|
warn('Found too many parameters for stack-clearing command');
|
||||||
|
}
|
||||||
|
if (stackSize > 0 && stack[stackSize - 1] >= 0) {
|
||||||
|
widths[i] = stack[stackSize - 1];
|
||||||
|
}
|
||||||
|
}
|
||||||
if ('stackDelta' in validationCommand) {
|
if ('stackDelta' in validationCommand) {
|
||||||
if ('stackFn' in validationCommand) {
|
if ('stackFn' in validationCommand) {
|
||||||
validationCommand.stackFn(stack, stackSize);
|
validationCommand.stackFn(stack, stackSize);
|
||||||
}
|
}
|
||||||
stackSize += validationCommand.stackDelta;
|
stackSize += validationCommand.stackDelta;
|
||||||
|
} else if (validationCommand.stackClearing) {
|
||||||
|
stackSize = 0;
|
||||||
} else if (validationCommand.resetStack) {
|
} else if (validationCommand.resetStack) {
|
||||||
stackSize = 0;
|
stackSize = 0;
|
||||||
undefStack = false;
|
undefStack = false;
|
||||||
} else if (validationCommand.undefStack) {
|
} else if (validationCommand.undefStack) {
|
||||||
stackSize = 0;
|
stackSize = 0;
|
||||||
undefStack = true;
|
undefStack = true;
|
||||||
|
firstStackClearing = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -6151,7 +6178,7 @@ var CFFParser = (function CFFParserClosure() {
|
|||||||
charStrings.set(i, new Uint8Array([14]));
|
charStrings.set(i, new Uint8Array([14]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return { charStrings: charStrings, seacs: seacs };
|
return { charStrings: charStrings, seacs: seacs, widths: widths };
|
||||||
},
|
},
|
||||||
emptyPrivateDictionary:
|
emptyPrivateDictionary:
|
||||||
function CFFParser_emptyPrivateDictionary(parentDict) {
|
function CFFParser_emptyPrivateDictionary(parentDict) {
|
||||||
|
Loading…
Reference in New Issue
Block a user