From cabc98f3104758d7ec8698975026fc1c4b5d0d94 Mon Sep 17 00:00:00 2001 From: Jonas Jenwald Date: Fri, 21 Apr 2023 11:55:55 +0200 Subject: [PATCH] Remove the remaining closure in the `src/core/cmap.js` file With modern JavaScript we (usually) no longer need to keep old closures, which slightly reduces the size of the code. --- src/core/cmap.js | 508 +++++++++++++++++++++++------------------------ 1 file changed, 251 insertions(+), 257 deletions(-) diff --git a/src/core/cmap.js b/src/core/cmap.js index 1f50a9227..f6d579bb6 100644 --- a/src/core/cmap.js +++ b/src/core/cmap.js @@ -444,289 +444,283 @@ class IdentityCMap extends CMap { } } -const CMapFactory = (function CMapFactoryClosure() { - function strToInt(str) { - let a = 0; - for (let i = 0; i < str.length; i++) { - a = (a << 8) | str.charCodeAt(i); - } - return a >>> 0; +function strToInt(str) { + let a = 0; + for (let i = 0; i < str.length; i++) { + a = (a << 8) | str.charCodeAt(i); } + return a >>> 0; +} - function expectString(obj) { - if (typeof obj !== "string") { - throw new FormatError("Malformed CMap: expected string."); - } +function expectString(obj) { + if (typeof obj !== "string") { + throw new FormatError("Malformed CMap: expected string."); } +} - function expectInt(obj) { - if (!Number.isInteger(obj)) { - throw new FormatError("Malformed CMap: expected int."); - } +function expectInt(obj) { + if (!Number.isInteger(obj)) { + throw new FormatError("Malformed CMap: expected int."); } +} - function parseBfChar(cMap, lexer) { - while (true) { - let obj = lexer.getObj(); - if (obj === EOF) { - break; - } - if (isCmd(obj, "endbfchar")) { - return; - } - expectString(obj); - const src = strToInt(obj); +function parseBfChar(cMap, lexer) { + while (true) { + let obj = lexer.getObj(); + if (obj === EOF) { + break; + } + if (isCmd(obj, "endbfchar")) { + return; + } + expectString(obj); + const src = strToInt(obj); + obj = lexer.getObj(); + // TODO are /dstName used? + expectString(obj); + const dst = obj; + cMap.mapOne(src, dst); + } +} + +function parseBfRange(cMap, lexer) { + while (true) { + let obj = lexer.getObj(); + if (obj === EOF) { + break; + } + if (isCmd(obj, "endbfrange")) { + return; + } + expectString(obj); + const low = strToInt(obj); + obj = lexer.getObj(); + expectString(obj); + const high = strToInt(obj); + obj = lexer.getObj(); + if (Number.isInteger(obj) || typeof obj === "string") { + const dstLow = Number.isInteger(obj) ? String.fromCharCode(obj) : obj; + cMap.mapBfRange(low, high, dstLow); + } else if (isCmd(obj, "[")) { obj = lexer.getObj(); - // TODO are /dstName used? - expectString(obj); - const dst = obj; - cMap.mapOne(src, dst); - } - } - - function parseBfRange(cMap, lexer) { - while (true) { - let obj = lexer.getObj(); - if (obj === EOF) { - break; - } - if (isCmd(obj, "endbfrange")) { - return; - } - expectString(obj); - const low = strToInt(obj); - obj = lexer.getObj(); - expectString(obj); - const high = strToInt(obj); - obj = lexer.getObj(); - if (Number.isInteger(obj) || typeof obj === "string") { - const dstLow = Number.isInteger(obj) ? String.fromCharCode(obj) : obj; - cMap.mapBfRange(low, high, dstLow); - } else if (isCmd(obj, "[")) { + const array = []; + while (!isCmd(obj, "]") && obj !== EOF) { + array.push(obj); obj = lexer.getObj(); - const array = []; - while (!isCmd(obj, "]") && obj !== EOF) { - array.push(obj); - obj = lexer.getObj(); - } - cMap.mapBfRangeToArray(low, high, array); - } else { - break; } + cMap.mapBfRangeToArray(low, high, array); + } else { + break; } - throw new FormatError("Invalid bf range."); } + throw new FormatError("Invalid bf range."); +} - function parseCidChar(cMap, lexer) { - while (true) { - let obj = lexer.getObj(); +function parseCidChar(cMap, lexer) { + while (true) { + let obj = lexer.getObj(); + if (obj === EOF) { + break; + } + if (isCmd(obj, "endcidchar")) { + return; + } + expectString(obj); + const src = strToInt(obj); + obj = lexer.getObj(); + expectInt(obj); + const dst = obj; + cMap.mapOne(src, dst); + } +} + +function parseCidRange(cMap, lexer) { + while (true) { + let obj = lexer.getObj(); + if (obj === EOF) { + break; + } + if (isCmd(obj, "endcidrange")) { + return; + } + expectString(obj); + const low = strToInt(obj); + obj = lexer.getObj(); + expectString(obj); + const high = strToInt(obj); + obj = lexer.getObj(); + expectInt(obj); + const dstLow = obj; + cMap.mapCidRange(low, high, dstLow); + } +} + +function parseCodespaceRange(cMap, lexer) { + while (true) { + let obj = lexer.getObj(); + if (obj === EOF) { + break; + } + if (isCmd(obj, "endcodespacerange")) { + return; + } + if (typeof obj !== "string") { + break; + } + const low = strToInt(obj); + obj = lexer.getObj(); + if (typeof obj !== "string") { + break; + } + const high = strToInt(obj); + cMap.addCodespaceRange(obj.length, low, high); + } + throw new FormatError("Invalid codespace range."); +} + +function parseWMode(cMap, lexer) { + const obj = lexer.getObj(); + if (Number.isInteger(obj)) { + cMap.vertical = !!obj; + } +} + +function parseCMapName(cMap, lexer) { + const obj = lexer.getObj(); + if (obj instanceof Name) { + cMap.name = obj.name; + } +} + +async function parseCMap(cMap, lexer, fetchBuiltInCMap, useCMap) { + let previous, embeddedUseCMap; + objLoop: while (true) { + try { + const obj = lexer.getObj(); if (obj === EOF) { break; - } - if (isCmd(obj, "endcidchar")) { - return; - } - expectString(obj); - const src = strToInt(obj); - obj = lexer.getObj(); - expectInt(obj); - const dst = obj; - cMap.mapOne(src, dst); - } - } - - function parseCidRange(cMap, lexer) { - while (true) { - let obj = lexer.getObj(); - if (obj === EOF) { - break; - } - if (isCmd(obj, "endcidrange")) { - return; - } - expectString(obj); - const low = strToInt(obj); - obj = lexer.getObj(); - expectString(obj); - const high = strToInt(obj); - obj = lexer.getObj(); - expectInt(obj); - const dstLow = obj; - cMap.mapCidRange(low, high, dstLow); - } - } - - function parseCodespaceRange(cMap, lexer) { - while (true) { - let obj = lexer.getObj(); - if (obj === EOF) { - break; - } - if (isCmd(obj, "endcodespacerange")) { - return; - } - if (typeof obj !== "string") { - break; - } - const low = strToInt(obj); - obj = lexer.getObj(); - if (typeof obj !== "string") { - break; - } - const high = strToInt(obj); - cMap.addCodespaceRange(obj.length, low, high); - } - throw new FormatError("Invalid codespace range."); - } - - function parseWMode(cMap, lexer) { - const obj = lexer.getObj(); - if (Number.isInteger(obj)) { - cMap.vertical = !!obj; - } - } - - function parseCMapName(cMap, lexer) { - const obj = lexer.getObj(); - if (obj instanceof Name) { - cMap.name = obj.name; - } - } - - async function parseCMap(cMap, lexer, fetchBuiltInCMap, useCMap) { - let previous, embeddedUseCMap; - objLoop: while (true) { - try { - const obj = lexer.getObj(); - if (obj === EOF) { - break; - } else if (obj instanceof Name) { - if (obj.name === "WMode") { - parseWMode(cMap, lexer); - } else if (obj.name === "CMapName") { - parseCMapName(cMap, lexer); - } - previous = obj; - } else if (obj instanceof Cmd) { - switch (obj.cmd) { - case "endcmap": - break objLoop; - case "usecmap": - if (previous instanceof Name) { - embeddedUseCMap = previous.name; - } - break; - case "begincodespacerange": - parseCodespaceRange(cMap, lexer); - break; - case "beginbfchar": - parseBfChar(cMap, lexer); - break; - case "begincidchar": - parseCidChar(cMap, lexer); - break; - case "beginbfrange": - parseBfRange(cMap, lexer); - break; - case "begincidrange": - parseCidRange(cMap, lexer); - break; - } + } else if (obj instanceof Name) { + if (obj.name === "WMode") { + parseWMode(cMap, lexer); + } else if (obj.name === "CMapName") { + parseCMapName(cMap, lexer); } - } catch (ex) { - if (ex instanceof MissingDataException) { - throw ex; + previous = obj; + } else if (obj instanceof Cmd) { + switch (obj.cmd) { + case "endcmap": + break objLoop; + case "usecmap": + if (previous instanceof Name) { + embeddedUseCMap = previous.name; + } + break; + case "begincodespacerange": + parseCodespaceRange(cMap, lexer); + break; + case "beginbfchar": + parseBfChar(cMap, lexer); + break; + case "begincidchar": + parseCidChar(cMap, lexer); + break; + case "beginbfrange": + parseBfRange(cMap, lexer); + break; + case "begincidrange": + parseCidRange(cMap, lexer); + break; } - warn("Invalid cMap data: " + ex); - continue; } + } catch (ex) { + if (ex instanceof MissingDataException) { + throw ex; + } + warn("Invalid cMap data: " + ex); + continue; } + } - if (!useCMap && embeddedUseCMap) { - // Load the useCMap definition from the file only if there wasn't one - // specified. - useCMap = embeddedUseCMap; + if (!useCMap && embeddedUseCMap) { + // Load the useCMap definition from the file only if there wasn't one + // specified. + useCMap = embeddedUseCMap; + } + if (useCMap) { + return extendCMap(cMap, fetchBuiltInCMap, useCMap); + } + return cMap; +} + +async function extendCMap(cMap, fetchBuiltInCMap, useCMap) { + cMap.useCMap = await createBuiltInCMap(useCMap, fetchBuiltInCMap); + // If there aren't any code space ranges defined clone all the parent ones + // into this cMap. + if (cMap.numCodespaceRanges === 0) { + const useCodespaceRanges = cMap.useCMap.codespaceRanges; + for (let i = 0; i < useCodespaceRanges.length; i++) { + cMap.codespaceRanges[i] = useCodespaceRanges[i].slice(); } - if (useCMap) { + cMap.numCodespaceRanges = cMap.useCMap.numCodespaceRanges; + } + // Merge the map into the current one, making sure not to override + // any previously defined entries. + cMap.useCMap.forEach(function (key, value) { + if (!cMap.contains(key)) { + cMap.mapOne(key, cMap.useCMap.lookup(key)); + } + }); + + return cMap; +} + +async function createBuiltInCMap(name, fetchBuiltInCMap) { + if (name === "Identity-H") { + return new IdentityCMap(false, 2); + } else if (name === "Identity-V") { + return new IdentityCMap(true, 2); + } + if (!BUILT_IN_CMAPS.includes(name)) { + throw new Error("Unknown CMap name: " + name); + } + if (!fetchBuiltInCMap) { + throw new Error("Built-in CMap parameters are not provided."); + } + + const { cMapData, compressionType } = await fetchBuiltInCMap(name); + const cMap = new CMap(true); + + if (compressionType === CMapCompressionType.BINARY) { + return new BinaryCMapReader().process(cMapData, cMap, useCMap => { return extendCMap(cMap, fetchBuiltInCMap, useCMap); - } - return cMap; - } - - async function extendCMap(cMap, fetchBuiltInCMap, useCMap) { - cMap.useCMap = await createBuiltInCMap(useCMap, fetchBuiltInCMap); - // If there aren't any code space ranges defined clone all the parent ones - // into this cMap. - if (cMap.numCodespaceRanges === 0) { - const useCodespaceRanges = cMap.useCMap.codespaceRanges; - for (let i = 0; i < useCodespaceRanges.length; i++) { - cMap.codespaceRanges[i] = useCodespaceRanges[i].slice(); - } - cMap.numCodespaceRanges = cMap.useCMap.numCodespaceRanges; - } - // Merge the map into the current one, making sure not to override - // any previously defined entries. - cMap.useCMap.forEach(function (key, value) { - if (!cMap.contains(key)) { - cMap.mapOne(key, cMap.useCMap.lookup(key)); - } }); - - return cMap; } - - async function createBuiltInCMap(name, fetchBuiltInCMap) { - if (name === "Identity-H") { - return new IdentityCMap(false, 2); - } else if (name === "Identity-V") { - return new IdentityCMap(true, 2); - } - if (!BUILT_IN_CMAPS.includes(name)) { - throw new Error("Unknown CMap name: " + name); - } - if (!fetchBuiltInCMap) { - throw new Error("Built-in CMap parameters are not provided."); - } - - const { cMapData, compressionType } = await fetchBuiltInCMap(name); - const cMap = new CMap(true); - - if (compressionType === CMapCompressionType.BINARY) { - return new BinaryCMapReader().process(cMapData, cMap, useCMap => { - return extendCMap(cMap, fetchBuiltInCMap, useCMap); - }); - } - if (compressionType === CMapCompressionType.NONE) { - const lexer = new Lexer(new Stream(cMapData)); - return parseCMap(cMap, lexer, fetchBuiltInCMap, null); - } - throw new Error(`Invalid CMap "compressionType" value: ${compressionType}`); + if (compressionType === CMapCompressionType.NONE) { + const lexer = new Lexer(new Stream(cMapData)); + return parseCMap(cMap, lexer, fetchBuiltInCMap, null); } + throw new Error(`Invalid CMap "compressionType" value: ${compressionType}`); +} - return { - async create(params) { - const encoding = params.encoding; - const fetchBuiltInCMap = params.fetchBuiltInCMap; - const useCMap = params.useCMap; +class CMapFactory { + static async create({ encoding, fetchBuiltInCMap, useCMap }) { + if (encoding instanceof Name) { + return createBuiltInCMap(encoding.name, fetchBuiltInCMap); + } else if (encoding instanceof BaseStream) { + const parsedCMap = await parseCMap( + /* cMap = */ new CMap(), + /* lexer = */ new Lexer(encoding), + fetchBuiltInCMap, + useCMap + ); - if (encoding instanceof Name) { - return createBuiltInCMap(encoding.name, fetchBuiltInCMap); - } else if (encoding instanceof BaseStream) { - const parsedCMap = await parseCMap( - /* cMap = */ new CMap(), - /* lexer = */ new Lexer(encoding), - fetchBuiltInCMap, - useCMap - ); - - if (parsedCMap.isIdentityCMap) { - return createBuiltInCMap(parsedCMap.name, fetchBuiltInCMap); - } - return parsedCMap; + if (parsedCMap.isIdentityCMap) { + return createBuiltInCMap(parsedCMap.name, fetchBuiltInCMap); } - throw new Error("Encoding required."); - }, - }; -})(); + return parsedCMap; + } + throw new Error("Encoding required."); + } +} export { CMap, CMapFactory, IdentityCMap };