Merge pull request #10591 from brendandahl/fix-charset

Add unique glyph names for CFF fonts.
This commit is contained in:
Brendan Dahl 2019-02-28 17:22:29 -08:00 committed by GitHub
commit 34022d2fd1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 89 additions and 18 deletions

View File

@ -96,6 +96,8 @@ var CFFStandardStrings = [
'Black', 'Bold', 'Book', 'Light', 'Medium', 'Regular', 'Roman', 'Semibold' 'Black', 'Bold', 'Book', 'Light', 'Medium', 'Regular', 'Roman', 'Semibold'
]; ];
const NUM_STANDARD_CFF_STRINGS = 391;
var CFFParser = (function CFFParserClosure() { var CFFParser = (function CFFParserClosure() {
var CharstringValidationData = [ var CharstringValidationData = [
null, null,
@ -931,16 +933,27 @@ var CFFStrings = (function CFFStringsClosure() {
} }
CFFStrings.prototype = { CFFStrings.prototype = {
get: function CFFStrings_get(index) { get: function CFFStrings_get(index) {
if (index >= 0 && index <= 390) { if (index >= 0 && index <= (NUM_STANDARD_CFF_STRINGS - 1)) {
return CFFStandardStrings[index]; return CFFStandardStrings[index];
} }
if (index - 391 <= this.strings.length) { if (index - NUM_STANDARD_CFF_STRINGS <= this.strings.length) {
return this.strings[index - 391]; return this.strings[index - NUM_STANDARD_CFF_STRINGS];
} }
return CFFStandardStrings[0]; return CFFStandardStrings[0];
}, },
getSID: function CFFStrings_getSID(str) {
let index = CFFStandardStrings.indexOf(str);
if (index !== -1) {
return index;
}
index = this.strings.indexOf(str);
if (index !== -1) {
return index + NUM_STANDARD_CFF_STRINGS;
}
return -1;
},
add: function CFFStrings_add(value) { add: function CFFStrings_add(value) {
this.strings.push(value); return this.strings.push(value) + NUM_STANDARD_CFF_STRINGS - 1;
}, },
get count() { get count() {
return this.strings.length; return this.strings.length;
@ -1312,7 +1325,8 @@ var CFFCompiler = (function CFFCompilerClosure() {
output.add(encoding); output.add(encoding);
} }
} }
var charset = this.compileCharset(cff.charset); var charset = this.compileCharset(cff.charset, cff.charStrings.count,
cff.strings, cff.isCIDFont);
topDictTracker.setEntryLocation('charset', [output.length], output); topDictTracker.setEntryLocation('charset', [output.length], output);
output.add(charset); output.add(charset);
@ -1580,11 +1594,42 @@ var CFFCompiler = (function CFFCompilerClosure() {
} }
return this.compileIndex(charStringsIndex); return this.compileIndex(charStringsIndex);
}, },
compileCharset: function CFFCompiler_compileCharset(charset) { compileCharset: function CFFCompiler_compileCharset(charset, numGlyphs,
let length = 1 + (this.cff.charStrings.count - 1) * 2; strings, isCIDFont) {
// The contents of the charset doesn't matter, it's just there to make // Freetype requires the number of charset strings be correct and MacOS
// freetype happy. // requires a valid mapping for printing.
let out = new Uint8Array(length); let out;
let numGlyphsLessNotDef = numGlyphs - 1;
if (isCIDFont) {
// In a CID font, the charset is a mapping of CIDs not SIDs so just
// create an identity mapping.
out = new Uint8Array([
2, // format
0, // first CID upper byte
0, // first CID lower byte
(numGlyphsLessNotDef >> 8) & 0xFF,
numGlyphsLessNotDef & 0xFF,
]);
} else {
let length = 1 + numGlyphsLessNotDef * 2;
out = new Uint8Array(length);
out[0] = 0; // format 0
let charsetIndex = 0;
let numCharsets = charset.charset.length;
for (let i = 1; i < out.length; i += 2) {
let sid = 0;
if (charsetIndex < numCharsets) {
let name = charset.charset[charsetIndex++];
sid = strings.getSID(name);
if (sid === -1) {
sid = 0;
warn(`Couldn't find ${name} in CFF strings`);
}
}
out[i] = (sid >> 8) & 0xFF;
out[i + 1] = sid & 0xFF;
}
}
return this.compileTypedArray(out); return this.compileTypedArray(out);
}, },
compileEncoding: function CFFCompiler_compileEncoding(encoding) { compileEncoding: function CFFCompiler_compileEncoding(encoding) {

View File

@ -3339,16 +3339,12 @@ var Type1Font = (function Type1FontClosure() {
var i, ii; var i, ii;
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
var index = CFFStandardStrings.indexOf(charstrings[i].glyphName); var index = CFFStandardStrings.indexOf(charstrings[i].glyphName);
// TODO: Insert the string and correctly map it. Previously it was
// thought mapping names that aren't in the standard strings to .notdef
// was fine, however in issue818 when mapping them all to .notdef the
// adieresis glyph no longer worked.
if (index === -1) { if (index === -1) {
index = 0; index = strings.add(charstrings[i].glyphName);
} }
charsetArray.push((index >> 8) & 0xff, index & 0xff); charsetArray.push(index);
} }
cff.charset = new CFFCharset(false, 0, [], charsetArray); cff.charset = new CFFCharset(false, 0, charsetArray);
var charStringsIndex = new CFFIndex(); var charStringsIndex = new CFFIndex();
charStringsIndex.add([0x8B, 0x0E]); // .notdef charStringsIndex.add([0x8B, 0x0E]); // .notdef

View File

@ -14,7 +14,7 @@
*/ */
import { import {
CFFCompiler, CFFFDSelect, CFFParser, CFFStrings CFFCharset, CFFCompiler, CFFFDSelect, CFFParser, CFFStrings
} from '../../src/core/cff_parser'; } from '../../src/core/cff_parser';
import { SEAC_ANALYSIS_ENABLED } from '../../src/core/fonts'; import { SEAC_ANALYSIS_ENABLED } from '../../src/core/fonts';
import { Stream } from '../../src/core/stream'; import { Stream } from '../../src/core/stream';
@ -446,5 +446,35 @@ describe('CFFCompiler', function() {
]); ]);
}); });
it('compiles charset of CID font', function() {
var charset = new CFFCharset();
var c = new CFFCompiler();
var numGlyphs = 7;
var out = c.compileCharset(charset, numGlyphs, new CFFStrings(), true);
// All CID charsets get turned into a simple format 2.
expect(out).toEqual([
2, // format
0, // cid (high)
0, // cid (low)
0, // nLeft (high)
numGlyphs - 1, // nLeft (low)
]);
});
it('compiles charset of non CID font', function() {
var charset = new CFFCharset(false, 0, ['space', 'exclam']);
var c = new CFFCompiler();
var numGlyphs = 3;
var out = c.compileCharset(charset, numGlyphs, new CFFStrings(), false);
// All non-CID fonts use a format 0 charset.
expect(out).toEqual([
0, // format
0, // sid of 'space' (high)
1, // sid of 'space' (low)
0, // sid of 'exclam' (high)
2, // sid of 'exclam' (low)
]);
});
// TODO a lot more compiler tests // TODO a lot more compiler tests
}); });