Skip to content

Commit

Permalink
Merge pull request #16416 from calixteman/use_local_font_2
Browse files Browse the repository at this point in the history
For missing font, use a local font if it exists even if there's no standard substitution
  • Loading branch information
calixteman authored May 14, 2023
2 parents e738e15 + d4b70ec commit 202496a
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 30 deletions.
39 changes: 21 additions & 18 deletions src/core/evaluator.js
Original file line number Diff line number Diff line change
Expand Up @@ -3921,6 +3921,9 @@ class PartialEvaluator {
}
if (isMonospace) {
properties.flags |= FontFlags.FixedPitch;
} else {
// Clear the flag.
properties.flags &= ~FontFlags.FixedPitch;
}

properties.defaultWidth = defaultWidth;
Expand Down Expand Up @@ -4197,15 +4200,15 @@ class PartialEvaluator {
if (standardFontName) {
file = await this.fetchStandardFontData(standardFontName);
properties.isInternalFont = !!file;
if (!properties.isInternalFont && this.options.useSystemFonts) {
properties.systemFontInfo = getFontSubstitution(
this.systemFontCache,
this.idFactory,
this.options.standardFontDataUrl,
baseFontName,
standardFontName
);
}
}
if (!properties.isInternalFont && this.options.useSystemFonts) {
properties.systemFontInfo = getFontSubstitution(
this.systemFontCache,
this.idFactory,
this.options.standardFontDataUrl,
baseFontName,
standardFontName
);
}
return this.extractDataStructures(dict, dict, properties).then(
newProperties => {
Expand Down Expand Up @@ -4310,15 +4313,15 @@ class PartialEvaluator {
if (standardFontName) {
fontFile = await this.fetchStandardFontData(standardFontName);
isInternalFont = !!fontFile;
if (!isInternalFont && this.options.useSystemFonts) {
systemFontInfo = getFontSubstitution(
this.systemFontCache,
this.idFactory,
this.options.standardFontDataUrl,
fontName.name,
standardFontName
);
}
}
if (!isInternalFont && this.options.useSystemFonts) {
systemFontInfo = getFontSubstitution(
this.systemFontCache,
this.idFactory,
this.options.standardFontDataUrl,
fontName.name,
standardFontName
);
}
}

Expand Down
28 changes: 20 additions & 8 deletions src/core/font_substitutions.js
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,6 @@ const substitutionMap = new Map([
[
"ArialBlack-Italic",
{
prepend: ["Arial Black Italic"],
local: {
alias: "ArialBlack",
append: "Italic",
Expand Down Expand Up @@ -337,24 +336,31 @@ const fontAliases = new Map([["Arial-Black", "ArialBlack"]]);
/**
* Create the src path to use to load a font (see FontFace).
* @param {Array<String>} prepend A list of font names to search first.
* @param {String} appendToPrepended A String to append to the list of fonts in
* prepend.
* @param {Array<String>|Object} local A list of font names to search. If an
* Object is passed, then local.alias is the name of an other substition font
* and local.append is a String to append to the list of fonts in the alias.
* For example if local.alias is "Foo" and local.append is "Bold" then the
* list of fonts will be "FooSubst1 Bold", "FooSubst2 Bold", etc.
* @returns an String with the local fonts.
*/
function makeLocal(prepend, local) {
function makeLocal(prepend, appendToPrepended, local) {
let append = "";
if (!Array.isArray(local)) {
// We are getting our list of fonts in the alias and we'll append Bold,
// Italic or both.
append = ` ${local.append}`;
local = substitutionMap.get(local.alias).local;
}
if (appendToPrepended) {
appendToPrepended = ` ${appendToPrepended}`;
}

let prependedPaths = "";
if (prepend) {
prependedPaths = prepend.map(name => `local(${name})`).join(",") + ",";
prependedPaths =
prepend.map(name => `local(${name}${appendToPrepended})`).join(",") + ",";
}
return (
prependedPaths + local.map(name => `local(${name}${append})`).join(",")
Expand All @@ -378,8 +384,8 @@ function makeLocal(prepend, local) {
* @param {Object} idFactory The ids factory.
* @param {String} localFontPath Path to the fonts directory.
* @param {String} baseFontName The font name to be substituted.
* @param {String} standardFontName The standard font name to use if the base
* font is not available.
* @param {String|undefined} standardFontName The standard font name to use
* if the base font is not available.
* @returns an Object with the CSS, the loaded name, the src and the style.
*/
function getFontSubstitution(
Expand Down Expand Up @@ -437,7 +443,8 @@ function getFontSubstitution(
(italic && ITALIC) ||
NORMAL;
substitutionInfo = {
css: `${loadedName},sans-serif`,
css: loadedName,
guessFallback: true,
loadedName,
src: `local(${baseFontName})`,
style,
Expand All @@ -457,16 +464,20 @@ function getFontSubstitution(

// Prepend the fonts to test before the fallback font.
let prepend = substitution.prepend;
let appendToPrepended = "";

if (fallback) {
// We've a fallback font: this one is a standard font we want to use in case
// nothing has been found from the prepend list.
prepend ||= substitutionMap.get(substitution.local.alias).prepend;
if (substitution.local) {
prepend ||= substitutionMap.get(substitution.local.alias).prepend;
appendToPrepended = substitution.local.append;
}
substitution = substitutionMap.get(fallback);
}

const { local, path, ultimate } = substitution;
let src = makeLocal(prepend, local);
let src = makeLocal(prepend, appendToPrepended, local);
if (path && localFontPath !== null) {
// PDF.js embeds some fonts we can use.
src += `,url(${localFontPath}${path})`;
Expand All @@ -480,6 +491,7 @@ function getFontSubstitution(

substitutionInfo = {
css: `${loadedName},${ultimate}`,
guessFallback: false,
loadedName,
src,
style,
Expand Down
6 changes: 5 additions & 1 deletion src/core/fonts.js
Original file line number Diff line number Diff line change
Expand Up @@ -986,6 +986,7 @@ class Font {
let { type, subtype } = properties;
this.type = type;
this.subtype = subtype;
this.systemFontInfo = properties.systemFontInfo;

const matches = name.match(/^InvalidPDFjsFont_(.*)_\d+$/);
this.isInvalidPDFjsFont = !!matches;
Expand All @@ -999,7 +1000,10 @@ class Font {
this.fallbackName = "sans-serif";
}

this.systemFontInfo = properties.systemFontInfo;
if (this.systemFontInfo?.guessFallback) {
this.systemFontInfo.css += `,${this.fallbackName}`;
}

this.differences = properties.differences;
this.widths = properties.widths;
this.defaultWidth = properties.defaultWidth;
Expand Down
3 changes: 3 additions & 0 deletions src/core/standard_fonts.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ const getStdFontMap = getLookupTableFactory(function (t) {
t["Arial-BoldItalicMT"] = "Helvetica-BoldOblique";
t["Arial-BoldMT"] = "Helvetica-Bold";
t["Arial-ItalicMT"] = "Helvetica-Oblique";
t["Arial-BoldItalicMT-BoldItalic"] = "Helvetica-BoldOblique";
t["Arial-BoldMT-Bold"] = "Helvetica-Bold";
t["Arial-ItalicMT-Italic"] = "Helvetica-Oblique";
t.ArialUnicodeMS = "Helvetica";
t["ArialUnicodeMS-Bold"] = "Helvetica-Bold";
t["ArialUnicodeMS-BoldItalic"] = "Helvetica-BoldOblique";
Expand Down
14 changes: 11 additions & 3 deletions src/display/font_loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -97,9 +97,17 @@ class FontLoader {
await fontFace.load();
this.#systemFonts.add(loadedName);
} catch {
warn(
`Cannot load system font: ${loadedName} for style ${style.style} and weight ${style.weight}.`
);
if (info.guessFallback) {
// We're trying to load only one system font.
const match = src.match(/^local\((.*)\)$/);
warn(
`Cannot load system font: ${match?.[1]}, installing it could help to improve PDF rendering.`
);
} else {
warn(
`Cannot load system font: ${loadedName} for style ${style.style} and weight ${style.weight}.`
);
}
this.removeNativeFontFace(fontFace);
}
return;
Expand Down

0 comments on commit 202496a

Please sign in to comment.