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 for Rendering Glyphs with Non 1:2 Aspect Ratio #1

Open
Aalivexy opened this issue Aug 10, 2024 · 3 comments
Open

Support for Rendering Glyphs with Non 1:2 Aspect Ratio #1

Aalivexy opened this issue Aug 10, 2024 · 3 comments

Comments

@Aalivexy
Copy link

Thank you for this excellent terminal library! I'm currently working on rendering Chinese characters and emojis. However, I'm encountering an issue where the default assumption seems to be that the glyphs should have a 1:2 width-to-height ratio, but this isn't the case for many fonts, especially when rendering CJK characters or emojis.

I noticed that ab_glyph::ScaleFont.h_advance takes a GlyphId parameter, which suggests that the glyph's advance width is not fixed. Is there a recommended way to handle the rendering of glyphs that do not adhere to the 1:2 width-to-height ratio? Any guidance or best practices would be greatly appreciated!

@wenxuanjun
Copy link
Owner

Thank you very much for your issue.

This is true for the current situation. Supporting non-standard Latin characters is a very tempting feature. However, the main work at the moment is in more complete support the control functions of the terminal based on Xterm Control Sequences (including rollback buffers, [possible] mouse support and so on). Thus better management for glyph rendering may be postponed until after this refinement work.

This issue will not close until the feature is complete.

@wenxuanjun
Copy link
Owner

Hi, I'm glad I've made a little progress on the rendering of characters such as CJK.

AFAIK that the terminal manages character display in terms of cells, with half-width characters using one cell and full-width characters using two cells (the first cell uses the space of both cells when rendering, while the second cell is labelled as a placeholder and will be skipped when rendering).

Because of this special cell-based management model, I cannot use common text layout crates such as glyph_brush_layout.

I have made this terminal library support full-width characters as described above for cell. The current drawback is the determination of whether or not a character need to use two cells.

I currently use the unicode-width crate to determine directly, but it has the problem that ab_glyph returns the Replacement Character U+FFFD when the character does not exist in the font file, and the width of the character varies from font to font. For example, two cells are needed in SourceHanMonoSC, while only one is needed in Source Code Pro (you can use (h_advance / raster_height) > 0.5 to determine if two cells are needed). But unicode-width returns the actual width of the original character.

The solution is to call ab_glyph when creating the cell to calculate the actual character width. But this introduces additional computation and lock-hogging overheads, especially in the case of manual flush, where the number of cell creations is much larger than the number of actual renderings, and thus leads to a sizable performance degradation. According to the test, using the time find /usr command on my machine for benchmarking, the time taken increased from the original 1.4s to over 4s.

This issue might be tackled in a later version.

So if you just need a common layout solution, you can try to use glyph_brush_layout directly. Or check out cosmic-text, which is a complete solution for text rendering and supports no_std.

@Aalivexy
Copy link
Author

Thank you very much for your work! This is obviously not a very "clean" job, but it's better to have it than not! After all, CJK typesetting, punctuation squeezing and glyph adjustment are obviously not necessary for a terminal, and these things should be handled by more advanced typesetting software.

Regarding how to distinguish between full-width and half-width characters, I think if only U+FFFD is a problem, you can just hard-code the glyph of U+FFFD and use the same display regardless of the font. After all, I think there should be very few glyphs with different aspect ratios. The article I found suggests that the width of U+FFFD is actually related to the context, if only handling these special cases can improve performance, it would be great!

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

No branches or pull requests

2 participants