in src/core/fonts.js [1162:1311]
fallbackToSystemFont(properties) {
this.missingFile = true;
// The file data is not specified. Trying to fix the font name
// to be used with the canvas.font.
const { name, type } = this;
let fontName = normalizeFontName(name);
const stdFontMap = getStdFontMap(),
nonStdFontMap = getNonStdFontMap();
const isStandardFont = !!stdFontMap[fontName];
const isMappedToStandardFont = !!(
nonStdFontMap[fontName] && stdFontMap[nonStdFontMap[fontName]]
);
fontName = stdFontMap[fontName] || nonStdFontMap[fontName] || fontName;
const fontBasicMetricsMap = getFontBasicMetrics();
const metrics = fontBasicMetricsMap[fontName];
if (metrics) {
if (isNaN(this.ascent)) {
this.ascent = metrics.ascent / PDF_GLYPH_SPACE_UNITS;
}
if (isNaN(this.descent)) {
this.descent = metrics.descent / PDF_GLYPH_SPACE_UNITS;
}
if (isNaN(this.capHeight)) {
this.capHeight = metrics.capHeight / PDF_GLYPH_SPACE_UNITS;
}
}
this.bold = /bold/gi.test(fontName);
this.italic = /oblique|italic/gi.test(fontName);
// Use 'name' instead of 'fontName' here because the original
// name ArialBlack for example will be replaced by Helvetica.
this.black = /Black/g.test(name);
// Use 'name' instead of 'fontName' here because the original
// name ArialNarrow for example will be replaced by Helvetica.
const isNarrow = /Narrow/g.test(name);
// if at least one width is present, remeasure all chars when exists
this.remeasure =
(!isStandardFont || isNarrow) && Object.keys(this.widths).length > 0;
if (
(isStandardFont || isMappedToStandardFont) &&
type === "CIDFontType2" &&
this.cidEncoding.startsWith("Identity-")
) {
const cidToGidMap = properties.cidToGidMap;
// Standard fonts might be embedded as CID font without glyph mapping.
// Building one based on GlyphMapForStandardFonts.
const map = [];
applyStandardFontGlyphMap(map, getGlyphMapForStandardFonts());
if (/Arial-?Black/i.test(name)) {
applyStandardFontGlyphMap(map, getSupplementalGlyphMapForArialBlack());
} else if (/Calibri/i.test(name)) {
applyStandardFontGlyphMap(map, getSupplementalGlyphMapForCalibri());
}
// Always update the glyph mapping with the `cidToGidMap` when it exists
// (fixes issue12418_reduced.pdf).
if (cidToGidMap) {
for (const charCode in map) {
const cid = map[charCode];
if (cidToGidMap[cid] !== undefined) {
map[+charCode] = cidToGidMap[cid];
}
}
// When the /CIDToGIDMap is "incomplete", fallback to the included
// /ToUnicode-map regardless of its encoding (fixes issue11915.pdf).
if (
cidToGidMap.length !== this.toUnicode.length &&
properties.hasIncludedToUnicodeMap &&
this.toUnicode instanceof IdentityToUnicodeMap
) {
this.toUnicode.forEach(function (charCode, unicodeCharCode) {
const cid = map[charCode];
if (cidToGidMap[cid] === undefined) {
map[+charCode] = unicodeCharCode;
}
});
}
}
if (!(this.toUnicode instanceof IdentityToUnicodeMap)) {
this.toUnicode.forEach(function (charCode, unicodeCharCode) {
map[+charCode] = unicodeCharCode;
});
}
this.toFontChar = map;
this.toUnicode = new ToUnicodeMap(map);
} else if (/Symbol/i.test(fontName)) {
this.toFontChar = buildToFontChar(
SymbolSetEncoding,
getGlyphsUnicode(),
this.differences
);
} else if (/Dingbats/i.test(fontName)) {
this.toFontChar = buildToFontChar(
ZapfDingbatsEncoding,
getDingbatsGlyphsUnicode(),
this.differences
);
} else if (isStandardFont || isMappedToStandardFont) {
const map = buildToFontChar(
this.defaultEncoding,
getGlyphsUnicode(),
this.differences
);
if (
type === "CIDFontType2" &&
!this.cidEncoding.startsWith("Identity-") &&
!(this.toUnicode instanceof IdentityToUnicodeMap)
) {
this.toUnicode.forEach(function (charCode, unicodeCharCode) {
map[+charCode] = unicodeCharCode;
});
}
this.toFontChar = map;
} else {
const glyphsUnicodeMap = getGlyphsUnicode();
const map = [];
this.toUnicode.forEach((charCode, unicodeCharCode) => {
if (!this.composite) {
const glyphName =
this.differences[charCode] || this.defaultEncoding[charCode];
const unicode = getUnicodeForGlyph(glyphName, glyphsUnicodeMap);
if (unicode !== -1) {
unicodeCharCode = unicode;
}
}
map[+charCode] = unicodeCharCode;
});
// Attempt to improve the glyph mapping for (some) composite fonts that
// appear to lack meaningful ToUnicode data.
if (this.composite && this.toUnicode instanceof IdentityToUnicodeMap) {
if (/Tahoma|Verdana/i.test(name)) {
// Fixes issue15719.pdf and issue11242_reduced.pdf.
applyStandardFontGlyphMap(map, getGlyphMapForStandardFonts());
}
}
this.toFontChar = map;
}
amendFallbackToUnicode(properties);
this.loadedName = fontName.split("-", 1)[0];
}