Skip to content

refactor(fonts,shapers): Cache font adjustment for efficiency#2309

Draft
Omikhleia wants to merge 1 commit intomasterfrom
experiment-font-adjust-caching
Draft

refactor(fonts,shapers): Cache font adjustment for efficiency#2309
Omikhleia wants to merge 1 commit intomasterfrom
experiment-font-adjust-caching

Conversation

@Omikhleia
Copy link
Copy Markdown
Member

@Omikhleia Omikhleia commented Aug 24, 2025

WIP experiment -- Saved as PR before I switch to other topics.

Font adjustment is a bit expensive - each time it is used, we activate the target font at the same size as the current font, shape an "x" or "H" for both to compute ex-height or cap-height, compute the ratio. If it wasn't used often, that would be okay, but with it being used for code, and possibly math, it gets invoked a lot (in documents with, obviously, either lots of "code"-formatted strings or lots of formulas).
That's a lot of repetitive small operations: (building near to identical options, loading fonts (C involved in the process), decoding fonts (shaper but also possibly Lua OT parsing, etc.), calling the shaper (C involved again), etc.

On my math booklet, this caching gain is however but a few seconds for an approx. 60 second build with a "heavy" math font (Garamond Math); and less noticeable with some other fonts (Libertinus Math or STIX Two Math)... So while interesting, it's perhaps not that decisive towards performance - i.e. there are lots of other performance costly operations in the whole process...

SILE already does a lot of font caching by a very narrow key in many places. But it's not clear to me how "ad hoc" the caching is, and it would seem we still perform a lot of operations without much clarity whether it is actually needed for good reasons... Surely that's something that could be questioned and clarified, for proper generalization.

@Omikhleia Omikhleia self-assigned this Aug 24, 2025
@Omikhleia Omikhleia requested a review from alerque as a code owner August 24, 2025 12:53
@Omikhleia Omikhleia added enhancement Software improvement or feature request question Ask for advice or investigate solutions labels Aug 24, 2025
@Omikhleia Omikhleia marked this pull request as draft August 24, 2025 12:53
@Omikhleia Omikhleia force-pushed the experiment-font-adjust-caching branch from e999ef8 to 44b9cdf Compare August 24, 2025 12:56
@khaledhosny
Copy link
Copy Markdown
Contributor

khaledhosny commented Aug 25, 2025

shape an "x" or "H" for both to compute ex-height or cap-height

FWIW, x-height and cap-height are font properties set by font authors in the OS/2 table. Applications are not supposed to measure glyphs to get them, and not all fonts have glyphs for “x” or “H”.

@Omikhleia
Copy link
Copy Markdown
Member Author

Omikhleia commented Aug 26, 2025

FWIW, x-height and cap-height are font properties set by font authors in the OS/2 table. Applications are not supposed to measure glyphs to get them, and not all fonts have glyphs for “x” or “H”.

It's probably wrong anyway to ask for ex-height adjustment in fonts not having an "x".

But yes, fundamentally, you are right, and an in-code comment mentions that fact:

-- Another option would be to use the OS/2 font table sxHeight value when available.

But as far as I can tell, there are quite a lot of fonts where these OS/2 properties aren't properly set and seem off.1

Moreover the "ex" unit in SILE elsewhere in the code base is also based on measuring a "x"....

sile/types/unit.lua

Lines 201 to 206 in 7002613

unittypes["ex"] = {
relative = true,
definition = function (value)
return value * SILE.shaper:measureChar("x").height
end,
}

Truly, this could be a dedicated issue. Contributions to a saner approach would be welcome. --> EDIT: Issue opened #2317

(The present draft PR here is only about possibly adopting caching on existing code,2 so is not exactly appropriate for the discussion.)

Footnotes

  1. On another set of properties for instance: https://github.com/alerque/libertinus/issues/511

  2. And as noted, I am not fully convinced by this implementation, the gain is not that great. But how SILE performs font caching here and there is questionable nonetheless.

@Omikhleia
Copy link
Copy Markdown
Member Author

Omikhleia commented Aug 26, 2025

By the way, in passing, SILE's OS/2 table parsing is quite partial at this date and does not extend to the whole table:1

">version:u2 xAvgCharWidth:i2 usWeightClass:u2 usWidthClass:u2 fsType:u2 ySubscriptXSize:i2 ySubscriptYSize:i2 ySubscriptXOffset:i2 ySubscriptYOffset:i2 ySuperscriptXSize:i2 ySuperscriptYSize:i2 ySuperscriptXOffset:i2 ySuperscriptYOffset:i2, yStrikeoutSize:i2 yStrikeoutPosition:i2",

So using sxHeight / sCapHeight would need to complete that parsing. That could be an interesting issue on its own too, and contributions would be welcome too, as a prerequisite. --> EDIT: Issue opened #2316

Footnotes

  1. (EDIT) I actually added that partial OS/2 table support a while ago, but only as far as was needed for some feature at that time (for feat: Add strikethrough command to the rules package #1422)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement Software improvement or feature request question Ask for advice or investigate solutions

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants