in src/core/evaluator.js [4151:4299]
preEvaluateFont(dict) {
const baseDict = dict;
let type = dict.get("Subtype");
if (!(type instanceof Name)) {
throw new FormatError("invalid font Subtype");
}
let composite = false;
let hash;
if (type.name === "Type0") {
// If font is a composite
// - get the descendant font
// - set the type according to the descendant font
// - get the FontDescriptor from the descendant font
const df = dict.get("DescendantFonts");
if (!df) {
throw new FormatError("Descendant fonts are not specified");
}
dict = Array.isArray(df) ? this.xref.fetchIfRef(df[0]) : df;
if (!(dict instanceof Dict)) {
throw new FormatError("Descendant font is not a dictionary.");
}
type = dict.get("Subtype");
if (!(type instanceof Name)) {
throw new FormatError("invalid font Subtype");
}
composite = true;
}
let firstChar = dict.get("FirstChar");
if (!Number.isInteger(firstChar)) {
firstChar = 0;
}
let lastChar = dict.get("LastChar");
if (!Number.isInteger(lastChar)) {
lastChar = composite ? 0xffff : 0xff;
}
const descriptor = dict.get("FontDescriptor");
const toUnicode = dict.get("ToUnicode") || baseDict.get("ToUnicode");
if (descriptor) {
hash = new MurmurHash3_64();
const encoding = baseDict.getRaw("Encoding");
if (encoding instanceof Name) {
hash.update(encoding.name);
} else if (encoding instanceof Ref) {
hash.update(encoding.toString());
} else if (encoding instanceof Dict) {
for (const entry of encoding.getRawValues()) {
if (entry instanceof Name) {
hash.update(entry.name);
} else if (entry instanceof Ref) {
hash.update(entry.toString());
} else if (Array.isArray(entry)) {
// 'Differences' array (fixes bug1157493.pdf).
const diffLength = entry.length,
diffBuf = new Array(diffLength);
for (let j = 0; j < diffLength; j++) {
const diffEntry = entry[j];
if (diffEntry instanceof Name) {
diffBuf[j] = diffEntry.name;
} else if (
typeof diffEntry === "number" ||
diffEntry instanceof Ref
) {
diffBuf[j] = diffEntry.toString();
}
}
hash.update(diffBuf.join());
}
}
}
hash.update(`${firstChar}-${lastChar}`); // Fixes issue10665_reduced.pdf
if (toUnicode instanceof BaseStream) {
const stream = toUnicode.str || toUnicode;
const uint8array = stream.buffer
? new Uint8Array(stream.buffer.buffer, 0, stream.bufferLength)
: new Uint8Array(
stream.bytes.buffer,
stream.start,
stream.end - stream.start
);
hash.update(uint8array);
} else if (toUnicode instanceof Name) {
hash.update(toUnicode.name);
}
const widths = dict.get("Widths") || baseDict.get("Widths");
if (Array.isArray(widths)) {
const widthsBuf = [];
for (const entry of widths) {
if (typeof entry === "number" || entry instanceof Ref) {
widthsBuf.push(entry.toString());
}
}
hash.update(widthsBuf.join());
}
if (composite) {
hash.update("compositeFont");
const compositeWidths = dict.get("W") || baseDict.get("W");
if (Array.isArray(compositeWidths)) {
const widthsBuf = [];
for (const entry of compositeWidths) {
if (typeof entry === "number" || entry instanceof Ref) {
widthsBuf.push(entry.toString());
} else if (Array.isArray(entry)) {
const subWidthsBuf = [];
for (const element of entry) {
if (typeof element === "number" || element instanceof Ref) {
subWidthsBuf.push(element.toString());
}
}
widthsBuf.push(`[${subWidthsBuf.join()}]`);
}
}
hash.update(widthsBuf.join());
}
const cidToGidMap =
dict.getRaw("CIDToGIDMap") || baseDict.getRaw("CIDToGIDMap");
if (cidToGidMap instanceof Name) {
hash.update(cidToGidMap.name);
} else if (cidToGidMap instanceof Ref) {
hash.update(cidToGidMap.toString());
} else if (cidToGidMap instanceof BaseStream) {
hash.update(cidToGidMap.peekBytes());
}
}
}
return {
descriptor,
dict,
baseDict,
composite,
type: type.name,
firstChar,
lastChar,
toUnicode,
hash: hash ? hash.hexdigest() : "",
};
}