Allow a function as an argument to various size parameters in math elements and add a delim-size parameter to mat, vec, and cases#6214
Conversation
|
The implementation looks very clean! What I'm not 100% certain on is what knobs we do and don't want to expose in math layout customization. There a lot of hard-coded layout algorithms, some hard-coded constants and various font-dependent values. Which do we want to make customizable? Also, regarding the tests. I'm not quite sure why the reference images for matrix tests changed. Did you change the matrix formula to match TeX more closely? I can't see it in the code. But either way, it might be good to extract those changes into a separate PR. |
I think I'd generally lean towards not exposing font-dependent stuff (and the layouting of elements that come with it), but anything else that is reasonable enough to expose and could have use to a user could then be added. In this case, scaling of delimiters is quite subjective and not really hard-coded into any of the layout algorithms, so I think it makes sense to expose for mat/vec/cases.
The only change made was in the first commit. Basically, we previously had a hard coded short fall used when scaling delimiters for the various elements. But this short fall didn't apply to the glyph assembly, i.e. we only considered it when picking a prebuilt variant. Because I'm exposing the size for delimiters in this PR, adding another knob for "short fall" seemed like a bad idea. So I instead in the first commit subtracted the short fall from the target for the glyph assembly as well. This is the reason for all the slight test changes in mat, etc. Otherwise, I have kept as default the same as we had before. For example, the default for mat/vec/cases is still |
|
Would you mind extracting the first and last commit into a separate PR? I think this change is fairly unrelated to exposing more user-facing knobs and should be judged separately. I can't remember the details anymore about why short fall works the way it works, but I see how it might make more sense to apply it consistently to variants and constructions and how that makes the extra parameter on the stretching functions obsolete. |
|
Sure I've opened #6377. I'll clean up this one very soon. |
|
The updated tests are due to relative lengths like |
| #[func(name = "x => x - 0.5em")] | ||
| const fn default_accent_size(base: Length) -> Rel { | ||
| Rel { | ||
| rel: Ratio::zero(), | ||
| abs: Length { abs: base.abs, em: ACCENT_SHORT_FALL }, | ||
| } | ||
| } |
There was a problem hiding this comment.
Is this too hacky? 😅
I generated the json docs and the default does show up as x => x - 0.5em. Not sure how it'll look on the actual docs though.
Also, I can't remember now whether these need to be const?
fd518ec to
189e2f4
Compare
3a2df74 to
33ae930
Compare
0e58966 to
333dfd5
Compare
Previously there was always a short fall when scaling delimiters, even if the user requested a specific size. This is no longer the case; the short fall is only present in the default for `lr` (`x => x - 0.1em`) - the size of the delimiters is now actually what was specified in the size argument. This also makes the default for `lr` much clearer to the user. A slight hack was used by exploiting the `name` property in the `func` attribute macro so that the default value in the docs for `lr.size` would clearly show what the default function was (instead of just its name `default_lr_size` which is meaningless and inaccessible to the user).
The short fall is now only applied in the default for `accent` (`x => x - 0.5em`).
Takes either a function or a relative length, just like with `lr`, `stretch`, and `accent` which was changed in the previous two commits. The default is now much clearer to the user: `x => x * 1.1 - 0.1em`.
333dfd5 to
8c81111
Compare
|
We've discussed this in the team and were overall not sure about it. Right now, math layout is driven by a mix of hard-coded logic, a few hard-coded constants, and a lot of font data. With this, it feels like it opens the door to customization of math layout from user code without a clear plan of where we want to go with this and what is in scope / not in scope for customization in the math layout engine. |
|
I'll close this for now — we can all always revisit it later. Thank you regardless! |
Closes #4181.
The commits are fairly detailed and broken into small parts explaining what's changed.
TLDR: The main change is the addition of the enum
StretchSizewhich can take a relative length or a function that receives the absolute size of the base thing and should return a relative length. This is used throughout the element functions inmathnow.Addressing #4181 specifically, it's difficult to exactly replicate TeX* as the way matrices (which are just wrappers over the array environment) are laid out is quite different to how they are laid out in Typst. But the below seems fairly close and uses the same formula TeX* does for scaling delimiters (with a
+2ptadded to better match how in TeX the inner content is slightly larger than in Typst. Anyways with the changes to allow a function the user has much more flexibility to customise this to their liking (and I'm sure someone will figure out a near perfect function to match TeX...)