From c155a86733e39b24e1fcd0e4e26f278519953c21 Mon Sep 17 00:00:00 2001 From: Jonas Jenwald Date: Sat, 18 Apr 2026 12:20:33 +0200 Subject: [PATCH] Store the Type1 program `privateData` in a Map, rather than an Object This is nicer when checking if fields exist in `Type1Font.prototype.wrap`, and a couple of loops in that method are also "modernized" slightly. --- src/core/type1_font.js | 18 ++++++++---------- src/core/type1_parser.js | 19 +++++++++---------- test/unit/type1_parser_spec.js | 2 +- 3 files changed, 18 insertions(+), 21 deletions(-) diff --git a/src/core/type1_font.js b/src/core/type1_font.js index 919157e6e..8b4d2cad3 100644 --- a/src/core/type1_font.js +++ b/src/core/type1_font.js @@ -359,9 +359,8 @@ class Type1Font { const count = glyphs.length; const charsetArray = [".notdef"]; - let i, ii; - for (i = 0; i < count; i++) { - const glyphName = charstrings[i].glyphName; + for (let i = 0; i < count; i++) { + const { glyphName } = charstrings[i]; const index = CFFStandardStrings.indexOf(glyphName); if (index === -1) { strings.add(glyphName); @@ -372,7 +371,7 @@ class Type1Font { const charStringsIndex = new CFFIndex(); charStringsIndex.add([0x8b, 0x0e]); // .notdef - for (i = 0; i < count; i++) { + for (let i = 0; i < count; i++) { charStringsIndex.add(glyphs[i]); } cff.charStrings = charStringsIndex; @@ -395,12 +394,11 @@ class Type1Font { "StdHW", "StdVW", ]; - for (i = 0, ii = fields.length; i < ii; i++) { - const field = fields[i]; - if (!(field in properties.privateData)) { + for (const field of fields) { + if (!properties.privateData.has(field)) { continue; } - const value = properties.privateData[field]; + const value = properties.privateData.get(field); if (Array.isArray(value)) { // All of the private dictionary array data in CFF must be stored as // "delta-encoded" numbers. @@ -413,8 +411,8 @@ class Type1Font { cff.topDict.privateDict = privateDict; const subrIndex = new CFFIndex(); - for (i = 0, ii = subrs.length; i < ii; i++) { - subrIndex.add(subrs[i]); + for (const subr of subrs) { + subrIndex.add(subr); } privateDict.subrsIndex = subrIndex; diff --git a/src/core/type1_parser.js b/src/core/type1_parser.js index b79762e89..96343fbe8 100644 --- a/src/core/type1_parser.js +++ b/src/core/type1_parser.js @@ -557,8 +557,7 @@ class Type1Parser { const subrs = [], charstrings = []; - const privateData = Object.create(null); - privateData.lenIV = 4; + const privateData = new Map([["lenIV", 4]]); const program = { subrs: [], charstrings: [], @@ -593,7 +592,7 @@ class Type1Parser { length = this.readInt(); this.getToken(); // read in 'RD' or '-|' data = length > 0 ? stream.getBytes(length) : new Uint8Array(0); - lenIV = program.properties.privateData.lenIV; + lenIV = privateData.get("lenIV"); const encoded = this.readCharStrings(data, lenIV); this.nextChar(); token = this.getToken(); // read in 'ND' or '|-' @@ -618,7 +617,7 @@ class Type1Parser { length = this.readInt(); this.getToken(); // read in 'RD' or '-|' data = length > 0 ? stream.getBytes(length) : new Uint8Array(0); - lenIV = program.properties.privateData.lenIV; + lenIV = privateData.get("lenIV"); const encoded = this.readCharStrings(data, lenIV); this.nextChar(); token = this.getToken(); // read in 'NP' or '|' @@ -640,32 +639,32 @@ class Type1Parser { blueArray.length % 2 === 0 && HINTING_ENABLED ) { - program.properties.privateData[token] = blueArray; + privateData.set(token, blueArray); } break; case "StemSnapH": case "StemSnapV": - program.properties.privateData[token] = this.readNumberArray(); + privateData.set(token, this.readNumberArray()); break; case "StdHW": case "StdVW": - program.properties.privateData[token] = this.readNumberArray()[0]; + privateData.set(token, this.readNumberArray()[0]); break; case "BlueShift": case "lenIV": case "BlueFuzz": case "BlueScale": case "LanguageGroup": - program.properties.privateData[token] = this.readNumber(); + privateData.set(token, this.readNumber()); break; case "ExpansionFactor": // Firefox doesn't render correctly a font with a null factor on // Windows (see issue 15289), hence we just reset it to its default // value (0.06). - program.properties.privateData[token] = this.readNumber() || 0.06; + privateData.set(token, this.readNumber() || 0.06); break; case "ForceBold": - program.properties.privateData[token] = this.readBoolean(); + privateData.set(token, this.readBoolean()); break; } } diff --git a/test/unit/type1_parser_spec.js b/test/unit/type1_parser_spec.js index 00929a33c..0d18a7c16 100644 --- a/test/unit/type1_parser_spec.js +++ b/test/unit/type1_parser_spec.js @@ -94,7 +94,7 @@ describe("Type1Parser", function () { const parser = new Type1Parser(stream, false, SEAC_ANALYSIS_ENABLED); const program = parser.extractFontProgram({}); expect(program.charstrings.length).toEqual(1); - expect(program.properties.privateData.ExpansionFactor).toEqual(99); + expect(program.properties.privateData.get("ExpansionFactor")).toEqual(99); }); it("parses font header font matrix", function () {