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.
This commit is contained in:
Jonas Jenwald 2023-04-21 11:55:55 +02:00
parent 244002502b
commit cabc98f310

View File

@ -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 };