Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support custom glyph indices in GlyphKey #35

Open
wants to merge 6 commits into
base: master
Choose a base branch
from

Conversation

fee1-dead
Copy link

@fee1-dead fee1-dead commented Nov 12, 2021

This is a breaking change.

Changes:

  • instead of storing characters in GlyphKey, store a GlyphId, which is a four bytes storage with the most significant bit as a flag for whether this is a char or the glyph index.
  • Add font_path to the Rasterize trait. Provides a way to get the path of a font by FontKey.

Tested locally with targets:

x86_64-apple-darwin
x86_64-pc-windows-gnu
x86_64-unknown-linux-musl

Copy link
Member

@chrisduerr chrisduerr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What exactly is the point of having an arbitrary GlyphId as part of the crossfont crate when all crossfont ever uses it for is the char?

@fee1-dead
Copy link
Author

fee1-dead commented Nov 14, 2021

crossfont needs to get the glyph index from the character specified by GlyphKey. This PR adds a way to directly specify the glyph index with the GlyphId field in GlyphKey. This is needed to shape the text before rasterizing through crossfont, as harfbuzz returns glyph indices instead of just characters.

Copy link
Member

@chrisduerr chrisduerr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is needed to shape the text before rasterizing through crossfont, as harfbuzz returns glyph indices instead of just characters.

Sounds like an issue with using harfbuzz to me, not crossfont. Why does this need to be patched in crossfont?

Crossfont has no ability to verify which integer should be associated to which character for rasterization, so it really doesn't make any sense to pass platform-specific "IDs" around. All crossfont does is rasterize a single character on all platforms, so the only thing that makes sense is passing a single character to crossfont.

@fee1-dead
Copy link
Author

Currently, crossfont works like this:

Character from GlyphKey --> Get index of glyph --> Rasterize glyph

This PR proposes an option to rasterize a glyph specified by its index:

                                           Glyph index from somewhere else
                                                        |
                                                        |
Character from GlyphKey --> Get index of glyph --> Rasterize glyph

And to answer your question: no, this is not platform-specific. All the libraries used for different platforms support TrueType fonts. And all TrueType fonts have glyph indices as part of their format: https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6cmap.html

The 'cmap' table maps character codes to glyph indices.

The notion of glyph indices and characters enables support for various features such as characters that can look different when placed around different characters (for example, Chinese characters look different when in a Korean context to when in a Japanese context, also ligatures), and these features are supported via shaping. Shaping retrieves a line of characters, and tells you the glyphs that you will need to render. -> is two characters, but it could be one glyph if ligature is enabled. You have no way to refer to the whole -> glyph (it is two characters) without using its glyph index in the font file format.

Users of crossfont want rasterized glyphs. Considering that there can be glyphs that do not refer to a single character, for example, कि displays as two glyphs in alacritty:

image

And they are two characters ( and ि), but in Devanagari this is one glyph. And the easiest thing for crossfont is to accept arbitrary glyph indices.

@fee1-dead
Copy link
Author

See also https://harfbuzz.github.io/why-do-i-need-a-shaping-engine.html:

OpenType fonts contain a set of glyphs (that is, shapes to represent the letters, numbers, punctuation marks, and all other symbols), which are indexed by a glyph ID.

A particular glyph ID within the font does not necessarily correlate to a predictable Unicode codepoint. For instance, some fonts have the letter "a" as glyph ID 1, but many others do not. In order to retrieve the right glyph from the font to display "a", you need to consult the table inside the font (the cmap table) that maps Unicode codepoints to glyph IDs. In other words, text shaping turns codepoints into glyph IDs.

Many OpenType fonts contain ligatures: combinations of characters that are rendered as a single unit. For instance, it is common for the "f, i" letter sequence to appear in print as the single ligature glyph "fi".

Whether you should render an "f, i" sequence as fi or as "fi" does not depend on the input text. Instead, it depends on the whether or not the font includes an "fi" glyph and on the level of ligature application you wish to perform. The font and the amount of ligature application used are under your control. In other words, text shaping involves querying the font's ligature tables and determining what substitutions should be made.

@fee1-dead fee1-dead requested a review from chrisduerr November 17, 2021 05:05
@chrisduerr chrisduerr removed their request for review November 17, 2021 11:59
Copy link
Member

@chrisduerr chrisduerr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll be honest I'm not particularly interested in discussing API design for a feature I don't care about at the moment. I might come back to this in the future, but especially with no ligature implementation in sight for Alacritty, I see little purpose in spending time on this.

@fee1-dead
Copy link
Author

fee1-dead commented Nov 17, 2021

Will reopen once I get ligature support working for alacritty.

@fee1-dead fee1-dead closed this Nov 17, 2021
@Nytelife26
Copy link

                                           Glyph index from somewhere else
                                                        |
                                                        |
Character from GlyphKey --> Get index of glyph --> Rasterize glyph

It stands to reason that if this is the case and crossfont has to work with glyph indices anyway, providing a character instead should be the special case, not the other way around. Perhaps instead we should deal exclusively with glyph indices but support fast extraction of those indices from characters via helpers to make the sole main interface work with indices but still support characters.

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

Successfully merging this pull request may close these issues.

3 participants