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 bitmap fonts, EBDT + EBLC tables #121

Merged
merged 5 commits into from
Apr 15, 2023

Conversation

dzamkov
Copy link
Contributor

@dzamkov dzamkov commented Apr 12, 2023

This PR makes a few changes that allow ttf_parser to be used with bitmap fonts (i.e. .otb files):

  • Added EBDT and EBLC tables (which are basically just aliases for CBDT and CBLC)
  • Implemented additional formats for the CBLC parser
  • Extended RasterImageFormat with the various uncompressed bitmap formats that may appear in a font

The PR also fixes some issues with CBLC parsing I found during testing:

  • The code for searching through subtables to find the best size did not correctly track the byte stream. There are 3 bytes between the end of ppem_x and the start of the next subtable, not 4. Also, these final bytes always have to be skipped, not just when !(start_glyph_id..=end_glyph_id).contains(&glyph_id).
  • location.metrics was never populated and always held the default value

I tested the changes on Terminus fonts and on some fonts I exported using Bits'N'Picas. The Terminus fonts are monochrome with several subtables for different scales. The Bits'N'Picas fonts are 8-bit grayscale.

The PR includes an automated test using one limited example font I created myself (so there are no copyright issues).

…and EBLC tables, fixing some issues with CBLC lookup
@RazrFalcon
Copy link
Collaborator

RazrFalcon commented Apr 12, 2023

Hi! Thanks for the patch. There are a couple of reasons why EBDT+EBLC haven't been implemented yet.

  1. I haven't been able to find a font that uses those tables. Those tables are kinda deprecaed. Even CBDT+CBLC are exceedingly rare and only Google uses them.
  2. Unlike CBDT+CBLC/sbix, where we have just a PNG, here we have a custom encoding format. And the question is: should we decoded it or not. To my understanding, all EBDT bitmaps are <=8bit, therefore they can be decoded into Planar8 quite easily. This would require some changes to the API so we could decode it on-demand and probably into a user-provided buffer. How do you plan to use this data? Do you decode it yourself or do you need the actual raw data?

Also, what about EBSC?

As for the bugs - thanks. I don't actually use those tables yet, so no guarantees. The current implementations is good enough for shaping.

src/tables/cbdt.rs Outdated Show resolved Hide resolved
src/tables/cblc.rs Outdated Show resolved Hide resolved
src/tables/ebdt.rs Outdated Show resolved Hide resolved
tests/bitmap.rs Show resolved Hide resolved
@dzamkov
Copy link
Contributor Author

dzamkov commented Apr 13, 2023

To provide some context and answer your initial questions. I'm working on a game with a custom engine. I already implemented TrueType rasterization using your library, but I would also like to support bitmap fonts since they're relatively easy to make and appear "crisper" at lower resolutions. I've been browsing around for bitmap fonts, and it seems that OTB is a fairly common format to find them in, and is commonly supported for tools that export bitmap fonts. All the ones I've found use EBDT+EBLC. I haven't seen any CBDT, CBLC or EBSC tables.

For your second point, I don't think ttf_parser should attempt to decode image data, or at least, it should always provide access the raw data. There are so many ways to use it that it would be impossible to satisfy everyone otherwise. For example, I currently decode the data into a 16bpp buffer where the color is always 255, and the opacity comes from glyph data. I upload this to a texture on the GPU. At some point in the future I might switch to a 32bpp buffer where again, the color is always (255, 255, 255) and the opacity comes from the glyph data. Right now, I create an image per each glyph, but in the future I might create one large image that I decode all the glyphs into. Alternatively, for some formats (e.g. 8-bit grayscale and 32-bit bgra), it is possible to upload the raw data directly, skipping decoding entirely. I would not be happy if I had to allocate a temporary buffer that I didn't need.

Anyway, I wanted to thank you for this awesome library! It's been working great for me so far.

@RazrFalcon
Copy link
Collaborator

I see. Thanks for the explanation.

To my understanding, the current implementation of EBDT+EBLC is identical to bdat+bloc. EBDT+EBLC added only formats 8 and 9, which we do not support anyway and which should be documented/mentioned somewhere. Including in the readme (it should be ~ (no 8, 9)). And then we can mark bdat+bloc as fully supported.

As for the code, I would suggest adding:

pub bdat: Option<cbdt::Table<'a>>,
pub ebdt: Option<cbdt::Table<'a>>,

We already do the same trick with hmtx and vmtx. No need for separate tables/wrappers.

And in the cbdt::Table docs mention that this table is used to parse bdat, EBDT and CBDT.

PS: if you would have performance issues parsing those tables, we could pre-parse them more. Currently we're re-parsing a lot of data for each glyph.

src/lib.rs Outdated Show resolved Hide resolved
@RazrFalcon
Copy link
Collaborator

RazrFalcon commented Apr 13, 2023

Also update the c-api crate. If this is hard, we can ignore it for now and I will update it myself after the merge.

@dzamkov
Copy link
Contributor Author

dzamkov commented Apr 15, 2023

Addressed the follow-up comments. From the bdat specs, it doesn't allow formats 8 and 9, but it does allow format 4, so I marked that as unimplemented in the readme. I also marked 8 and 9 as unimplemented for CBDT because any format that is valid for EBDT is technically allowed to appear in CBDT.

I updated the C API but admittedly I didn't really know what I was doing and was just following patterns. You might need to adjust things.

README.md Show resolved Hide resolved
src/tables/cbdt.rs Outdated Show resolved Hide resolved
@RazrFalcon
Copy link
Collaborator

Thanks. Looks good to me.

@RazrFalcon
Copy link
Collaborator

Thanks for you work! I will publish a new version soon.

@RazrFalcon RazrFalcon merged commit a3eb088 into harfbuzz:master Apr 15, 2023
@RazrFalcon
Copy link
Collaborator

Published a new version.

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

Successfully merging this pull request may close these issues.

2 participants