[HN Gopher] Adventures in Text Rendering: Kerning and Glyph Atlases
___________________________________________________________________
Adventures in Text Rendering: Kerning and Glyph Atlases
Author : zachlloyd
Score : 50 points
Date : 2022-07-27 15:46 UTC (7 hours ago)
(HTM) web link (www.warp.dev)
(TXT) w3m dump (www.warp.dev)
| billconan wrote:
| I have a question,
|
| How to do font fallback? For example, a user uses an English font
| "Arial", and suddenly she types a Chinese character. the
| character doesn't present in Arial, so we need to find a fallback
| font that does.
|
| Let's say we find one, but the fallback font has different
| sizing. How to scale the character to match the other font? What
| about kerning and other positioning issues?
|
| And also, is your cache ever increasing? Imagine a user zooms in,
| do you retire those small glyphs?
| vorporeal wrote:
| Blog post author here - great questions.
|
| My understanding is that some, but not all, shaping libraries
| will handle fallback fonts. For example, I believe Core Text
| (on MacOS) will specify which sections of a laid-out line
| should be rendered using which fonts, factoring in fallback
| font selections. Kerning should work within a run of a single
| font, but I'm not sure there's any way to "properly" kern a
| glyph pair from two separate fonts - there wouldn't be any
| information available about proper alignment (as kerning data
| is part of a font file). In terms of sizing, one would hope
| that font creators all respect the em-square when constructing
| glyph vectors, leading to two different fonts using the same
| point size having comparably-sized glyphs. If one doesn't want
| to rely on that, font metrics like ascent and descent could be
| utilized in an attempt to normalize sizing across different
| fonts.
|
| In terms of cache size: at the moment, we rarely empty out the
| cache (but we should do it more often). I have some ideas
| around triggers for emptying the cache and letting it get
| rebuilt (e.g.: changes to font size, changes to font family),
| but haven't wired it up yet. In addition, we could consider
| clearing the cache periodically when the application is sitting
| in the background (allowing us to re-rasterize the needed
| glyphs without blocking painting a frame). So tl;dr: we don't
| currently but we should and will do so in the future.
| billconan wrote:
| Thank you for the answers! I built a rust lib to generate
| multi-channel signed distance field font texture. I wanted to
| make it a text rendering lib. But after learning how complex
| it is, I guess I should give up and simply use core text...
| gumby wrote:
| What an excellent introduction.
| pseudosavant wrote:
| It is always great to see an excellent post on keming like this.
| actually_a_dog wrote:
| See https://www.reddit.com/r/keming/ for examples in the wild
| deathanatos wrote:
| > _For monospace fonts, used by Warp for terminal input and
| output, glyph advance is a constant - a fixed amount of spacing
| is used between all pairs of glyphs._
|
| It's more complicated than that, too. (But just about every
| terminal I've ever used at one point or another has made that
| buggy assumption!) Emoji and wide CJK characters typically take
| two terminal cells.
|
| For example (and HN will corrupt the output of this command, as
| it will remove the emoji): >> python3 -c
| 'print("1234567890\n\N{PILE OF POO}x\u4e09x")' 1234567890
| xSan x
|
| The second "x" should align under the 6. 4 glyphs, 6 cells.
|
| (I am a bit curious about the subpixel stuff. I've done font
| atlases, but IME Harfbuzz -- the shaping engine I've used -- only
| seems to emit integral advances? (Although I'm now wanting to re-
| test that assumption.) And I'm not entirely sure I know how to
| ask FreeType to render a glyph with an offset, either.)
| kevin_thibedeau wrote:
| Unfortunately many of the grandfathered symbols in the emoji
| block have ambiguous width and there is little recourse for
| applications to determine the terminal display width of any
| particular codepoint. Gnome VTE gives you a setting to force
| them one way or another but that can interact badly with fonts
| that expect a different width.
| deathanatos wrote:
| I think this is for the codepoints that have both an emoji
| form and a non-emoji form? (And yeah, that's admittedly
| confusing for the app.)
|
| I think Unicode does specify a way to force those codepoints
| to either the emoji form or the non-emoji form, but there is
| still an encoding that is ambiguous by spec, I think.
|
| E.g., the "TM" symbol falls into this; on macOS if you open
| the character selector and search "trade", you will get both
| variants.
|
| Edit: this:
| https://unicode.org/reports/tr51/#Presentation_Style
| vorporeal wrote:
| Good call-out - definitely a bit of a simplification there. We
| account for this in our terminal grid by allocating an empty
| cell following any double-width glyphs (e.g.: emoji and wide
| chars, as you mentioned).
|
| Tried out your example in Warp, and the alignment is as you
| described: https://i.ibb.co/Jcwcnwn/image.png
|
| Core Text supports rasterizing at sub-pixel offsets (though
| some configuration of the graphics context is necessary to do
| so properly) by applying a transformation to the graphics
| context before the rasterization call. I'll definitely have to
| figure out the FreeType angle when we start working on Linux
| support; if I uncover anything (and remember this comment
| thread), I'll report back with my findings. :)
| skavi wrote:
| Opening this website significantly degrades scrolling performance
| in Edge (Chromium). This impacts all my open tabs. Scrolling
| becomes fast again when the Warp tab is closed.
|
| Doesn't exactly instill confidence in the advertised product.
| boywitharupee wrote:
| I'm fascinated by text rendering and just scratching the surface
| to learn more.
|
| A few questions I have:
|
| 1. Is the pixel grid global to the the screen? or is it specific
| to application? Can different applications on OS have different
| pixel grids? Not sure where pixel grids come from
|
| 2. Sounds painful to write your own font rendering system. Why
| doesn't Warp use OS level libs CoreText, etc?
|
| 3. I know there are many font rendering techniques such as
| texture, distance and geometry based. The most recent one is
| pathfinder technique, which is geometry based? Which one does
| Warp uses?
|
| 4. In which step the font rendering pipeline spends most time? Is
| it the shaping? rasterization? font file parsing?
___________________________________________________________________
(page generated 2022-07-27 23:02 UTC)