Skip to content

Commit

Permalink
Merge pull request #10591 from brendandahl/fix-charset
Browse files Browse the repository at this point in the history
Add unique glyph names for CFF fonts.
  • Loading branch information
brendandahl committed Mar 1, 2019
2 parents 9559d57 + 8a596ef commit 34022d2
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 18 deletions.
65 changes: 55 additions & 10 deletions src/core/cff_parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,8 @@ var CFFStandardStrings = [
'Black', 'Bold', 'Book', 'Light', 'Medium', 'Regular', 'Roman', 'Semibold'
];

const NUM_STANDARD_CFF_STRINGS = 391;

var CFFParser = (function CFFParserClosure() {
var CharstringValidationData = [
null,
Expand Down Expand Up @@ -931,16 +933,27 @@ var CFFStrings = (function CFFStringsClosure() {
}
CFFStrings.prototype = {
get: function CFFStrings_get(index) {
if (index >= 0 && index <= 390) {
if (index >= 0 && index <= (NUM_STANDARD_CFF_STRINGS - 1)) {
return CFFStandardStrings[index];
}
if (index - 391 <= this.strings.length) {
return this.strings[index - 391];
if (index - NUM_STANDARD_CFF_STRINGS <= this.strings.length) {
return this.strings[index - NUM_STANDARD_CFF_STRINGS];
}
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) {
this.strings.push(value);
return this.strings.push(value) + NUM_STANDARD_CFF_STRINGS - 1;
},
get count() {
return this.strings.length;
Expand Down Expand Up @@ -1312,7 +1325,8 @@ var CFFCompiler = (function CFFCompilerClosure() {
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);
output.add(charset);

Expand Down Expand Up @@ -1580,11 +1594,42 @@ var CFFCompiler = (function CFFCompilerClosure() {
}
return this.compileIndex(charStringsIndex);
},
compileCharset: function CFFCompiler_compileCharset(charset) {
let length = 1 + (this.cff.charStrings.count - 1) * 2;
// The contents of the charset doesn't matter, it's just there to make
// freetype happy.
let out = new Uint8Array(length);
compileCharset: function CFFCompiler_compileCharset(charset, numGlyphs,
strings, isCIDFont) {
// Freetype requires the number of charset strings be correct and MacOS
// requires a valid mapping for printing.
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);
},
compileEncoding: function CFFCompiler_compileEncoding(encoding) {
Expand Down
10 changes: 3 additions & 7 deletions src/core/fonts.js
Original file line number Diff line number Diff line change
Expand Up @@ -3339,16 +3339,12 @@ var Type1Font = (function Type1FontClosure() {
var i, ii;
for (i = 0; i < count; i++) {
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) {
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();
charStringsIndex.add([0x8B, 0x0E]); // .notdef
Expand Down
32 changes: 31 additions & 1 deletion test/unit/cff_parser_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
*/

import {
CFFCompiler, CFFFDSelect, CFFParser, CFFStrings
CFFCharset, CFFCompiler, CFFFDSelect, CFFParser, CFFStrings
} from '../../src/core/cff_parser';
import { SEAC_ANALYSIS_ENABLED } from '../../src/core/fonts';
import { Stream } from '../../src/core/stream';
Expand Down Expand Up @@ -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
});

0 comments on commit 34022d2

Please sign in to comment.