Add the font Linux Libertine as a possible substitution for Times New Roman

and try to load the font family (guessed from the font name) before trying
the local substitution.
The local(...) command expects to have a real font name and not a predefined
substitution it's why we try the font family.
This commit is contained in:
Calixte Denizet 2023-12-10 22:13:22 +01:00
parent 51413be5b6
commit 10389c5017
2 changed files with 68 additions and 14 deletions

View File

@ -48,6 +48,8 @@ const substitutionMap = new Map([
"Thorndale", "Thorndale",
"TeX Gyre Termes", "TeX Gyre Termes",
"FreeSerif", "FreeSerif",
"Linux Libertine O",
"Libertinus Serif",
"DejaVu Serif", "DejaVu Serif",
"Bitstream Vera Serif", "Bitstream Vera Serif",
"Ubuntu", "Ubuntu",
@ -148,6 +150,8 @@ const substitutionMap = new Map([
"Cumberland", "Cumberland",
"TeX Gyre Cursor", "TeX Gyre Cursor",
"FreeMono", "FreeMono",
"Linux Libertine Mono O",
"Libertinus Mono",
], ],
style: NORMAL, style: NORMAL,
ultimate: "monospace", ultimate: "monospace",
@ -323,6 +327,48 @@ function getStyleToAppend(style) {
return ""; return "";
} }
function getFamilyName(str) {
// See https://gitlab.freedesktop.org/fontconfig/fontconfig/-/blob/14d466b30a8ab4a9d789977ed94f2c30e7209267/src/fcname.c#L137.
const keywords = new Set([
"thin",
"extralight",
"ultralight",
"demilight",
"semilight",
"light",
"book",
"regular",
"normal",
"medium",
"demibold",
"semibold",
"bold",
"extrabold",
"ultrabold",
"black",
"heavy",
"extrablack",
"ultrablack",
"roman",
"italic",
"oblique",
"ultracondensed",
"extracondensed",
"condensed",
"semicondensed",
"normal",
"semiexpanded",
"expanded",
"extraexpanded",
"ultraexpanded",
"bolditalic",
]);
return str
.split(/[- ,+]+/g)
.filter(tok => !keywords.has(tok.toLowerCase()))
.join(" ");
}
/** /**
* Generate font description. * Generate font description.
* @param {Object} param0, font substitution description. * @param {Object} param0, font substitution description.
@ -470,7 +516,7 @@ function getFontSubstitution(
(italic && ITALIC) || (italic && ITALIC) ||
NORMAL; NORMAL;
substitutionInfo = { substitutionInfo = {
css: loadedName, css: `"${getFamilyName(baseFontName)}",${loadedName}`,
guessFallback: true, guessFallback: true,
loadedName, loadedName,
baseFontName, baseFontName,
@ -492,7 +538,7 @@ function getFontSubstitution(
const fallback = guessFallback ? "" : `,${ultimate}`; const fallback = guessFallback ? "" : `,${ultimate}`;
substitutionInfo = { substitutionInfo = {
css: `${loadedName}${fallback}`, css: `"${getFamilyName(baseFontName)}",${loadedName}${fallback}`,
guessFallback, guessFallback,
loadedName, loadedName,
baseFontName, baseFontName,

View File

@ -40,7 +40,7 @@ describe("getFontSubstitution", function () {
}, },
}) })
); );
expect(fontSubstitution.css).toMatch(/^g_d(\d+)_sf(\d+)$/); expect(fontSubstitution.css).toMatch(/^"Foo",g_d(\d+)_sf(\d+)$/);
}); });
it("should substitute an unknown bold font", () => { it("should substitute an unknown bold font", () => {
@ -63,7 +63,7 @@ describe("getFontSubstitution", function () {
}, },
}) })
); );
expect(fontSubstitution.css).toMatch(/^g_d(\d+)_sf(\d+)$/); expect(fontSubstitution.css).toMatch(/^"Foo",g_d(\d+)_sf(\d+)$/);
}); });
it("should substitute an unknown italic font", () => { it("should substitute an unknown italic font", () => {
@ -86,7 +86,7 @@ describe("getFontSubstitution", function () {
}, },
}) })
); );
expect(fontSubstitution.css).toMatch(/^g_d(\d+)_sf(\d+)$/); expect(fontSubstitution.css).toMatch(/^"Foo",g_d(\d+)_sf(\d+)$/);
}); });
it("should substitute an unknown bold italic font", () => { it("should substitute an unknown bold italic font", () => {
@ -109,7 +109,7 @@ describe("getFontSubstitution", function () {
}, },
}) })
); );
expect(fontSubstitution.css).toMatch(/^g_d(\d+)_sf(\d+)$/); expect(fontSubstitution.css).toMatch(/^"Foo",g_d(\d+)_sf(\d+)$/);
}); });
it("should substitute an unknown font but with a standard font", () => { it("should substitute an unknown font but with a standard font", () => {
@ -140,7 +140,7 @@ describe("getFontSubstitution", function () {
}, },
}) })
); );
expect(fontSubstitution.css).toMatch(/^g_d(\d+)_sf(\d+),sans-serif$/); expect(fontSubstitution.css).toMatch(/^"Foo",g_d(\d+)_sf(\d+),sans-serif$/);
}); });
it("should substitute an unknown font but with a standard italic font", () => { it("should substitute an unknown font but with a standard italic font", () => {
@ -173,7 +173,7 @@ describe("getFontSubstitution", function () {
}, },
}) })
); );
expect(fontSubstitution.css).toMatch(/^g_d(\d+)_sf(\d+),sans-serif$/); expect(fontSubstitution.css).toMatch(/^"Foo",g_d(\d+)_sf(\d+),sans-serif$/);
}); });
it("should substitute an unknown font but with a standard bold font", () => { it("should substitute an unknown font but with a standard bold font", () => {
@ -205,7 +205,7 @@ describe("getFontSubstitution", function () {
}, },
}) })
); );
expect(fontSubstitution.css).toMatch(/^g_d(\d+)_sf(\d+),sans-serif$/); expect(fontSubstitution.css).toMatch(/^"Foo",g_d(\d+)_sf(\d+),sans-serif$/);
}); });
it("should substitute an unknown font but with a standard bold italic font", () => { it("should substitute an unknown font but with a standard bold italic font", () => {
@ -240,7 +240,7 @@ describe("getFontSubstitution", function () {
}, },
}) })
); );
expect(fontSubstitution.css).toMatch(/^g_d(\d+)_sf(\d+),sans-serif$/); expect(fontSubstitution.css).toMatch(/^"Foo",g_d(\d+)_sf(\d+),sans-serif$/);
}); });
it("should substitute Calibri", () => { it("should substitute Calibri", () => {
@ -271,7 +271,9 @@ describe("getFontSubstitution", function () {
}, },
}) })
); );
expect(fontSubstitution.css).toMatch(/^g_d(\d+)_sf(\d+),sans-serif$/); expect(fontSubstitution.css).toMatch(
/^"Calibri",g_d(\d+)_sf(\d+),sans-serif$/
);
}); });
it("should substitute Calibri-Bold", () => { it("should substitute Calibri-Bold", () => {
@ -304,7 +306,9 @@ describe("getFontSubstitution", function () {
}, },
}) })
); );
expect(fontSubstitution.css).toMatch(/^g_d(\d+)_sf(\d+),sans-serif$/); expect(fontSubstitution.css).toMatch(
/^"Calibri",g_d(\d+)_sf(\d+),sans-serif$/
);
}); });
it("should substitute Arial Black", () => { it("should substitute Arial Black", () => {
@ -337,7 +341,9 @@ describe("getFontSubstitution", function () {
}, },
}) })
); );
expect(fontSubstitution.css).toMatch(/^g_d(\d+)_sf(\d+),sans-serif$/); expect(fontSubstitution.css).toMatch(
/^"ArialBlack",g_d(\d+)_sf(\d+),sans-serif$/
);
}); });
it("should substitute Arial Black Bold", () => { it("should substitute Arial Black Bold", () => {
@ -370,6 +376,8 @@ describe("getFontSubstitution", function () {
}, },
}) })
); );
expect(fontSubstitution.css).toMatch(/^g_d(\d+)_sf(\d+),sans-serif$/); expect(fontSubstitution.css).toMatch(
/^"ArialBlack",g_d(\d+)_sf(\d+),sans-serif$/
);
}); });
}); });