ruuda / pris

A language for designing slides

Home Page:https://docs.ruuda.nl/pris/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Accessing glyphs by glyph index or name

cbreeden opened this issue · comments

Let's say I wanted to add pris as a target for ReX. The issue is that mapping Code points -> Glyph Indices is not one-to-one. For instance, there are 5 glyphs associated to the code point 0x28, a left parenthesis, in STIX, corresponding to 5 different heights.

ReX gets away with this for SVG targets modifying the opentype files, and using private use code points for the unmapped glyphs at the moment, but I'm thinking about moving away from this.

Do you have any thoughts on this? I believe, I would essentially need a way to construct
a cario_glyph_t and I would need to bypass Harfbuzz all together.

First of all, thank you for taking the time to try Pris and to file an issue!

Being able to select specific glyphs by id is definitely a must-have, and I realise that not all glyphs can be accessed via code points. (I ran into this issue myself when I wanted to insert one of Minion Pro’s leaf ornaments in LuaLaTeX, which does not have an equivalent of \XeTeXglyph.)

I think externally this could be nicely exposed as a built-in function, e.g. glyph(1253) would return a frame with a single glyph, similar to t("g") but with direct access to the glyph. Internally there are two challenges:

  • The index in cairo_glyph_t is not actually the glyph index in the font, if I recall correctly from my experiments. Perhaps it is, I’d have to try that again. Otherwise I’ll have to look into how to obtain the mapping.
  • You are right that drawing only requires a cairo_glyph_t and can bypass Harfbuzz. But to compute the bounding box, the glyph dimensions have to be obtained from the font. For height we can take the line height like text, but the width really depends on the glyph. I think it is possible to get this information from the Freetype font, but I haven’t looked into that yet.

I wasn't sure myself if cario_glyph_t accepts a glyph index or a code point. The manual for Cario says something a little cryptic like the index is the

glyph index in the font. The exact interpretation of the glyph index depends on the font technology being used.

The Harfbuzz manual is a little more clear and says the glyph_info_t.unicode field is

either a Unicode code point (before shaping) or a glyph index (after shaping).

Bounding boxes can be a little strange. Some glyphs in STIX have a height of more than 3em--think of a tall integral sign. Another issue is that many OpenType fonts don't provide glyph heights (TrueType fonts do), but I think every font provides an x-advance metric for width. Freetype can provide this. I remember reading that LuaTeX calculates the height of a glyph on the fly, by inspecting the bezier curves.

Hmm, it looks like the index in cairo_glyph_t is actually the glyph index. I put together a dirty version of this in the glyph branch (commit 5f16a9e), and this works. For now it pretends the glyph has zero width.

The bounding box for text is not accurate by the way, for the height it uses the line height and and for width the glyph advances as returned by Harfbuzz. Ideally, setting a piece of text would yield the same bounding box as placing the individual glyphs manually. Just knowing the x-advance would be sufficient for that. It might be that the y-offset matters too, but I haven’t found a case where it is nonzero.

Getting the glyph advance turned out not to be so difficult, this is now on the master branch. The height of the bounding box is still wrong (it stops at the baseline), but that is currently true for all text.

Does this work for you @cbreeden?

Hi @ruuda,

Sorry I haven't been active in this post lately. Unfortunately I won't be able to fully test it until later this summer after I graduate. I've looked at your example and it looks like that would fit my purposes just fine. The only concern I have is that since math typesetting violates line height rules, will there be a way for me to express the height of a frame?

My guess is that for a given equation I would write a function that will return a frame by placing the glyphs in their appropriate position (relative to the frame's coordinates) and return this frame with specified dimensions.

It is possible to manually extend the bounding box by placing an empty frame. This works because currently (0, 0) is always within the bounding box. (I’m still not sure whether that is desirable or not not.) So you can do

frame =
{
    at (x, y) put {}
}

// frame.size == (x, y)