-
Notifications
You must be signed in to change notification settings - Fork 682
Description
I'm currently implementing HarfBuzz-based shaping and I'm very close to finishing a shippable version, but there's a few performance issues I'd like to address before doing so. I have HarfBuzz built with only the OpenType shaper, and only the UCDN Unicode functions. It is used alongside Freetype. As such, I am using the Freetype face/font functions.
Originally, I was using hb_ft_font_create, but I found that this was very expensive because of it creating and then destroying an hb_face_t every time it's called. It doesn't appear to cache it at all. This was a big problem because it also meant that shape plans would not be cached, they would be discarded with the hb_font_t reference.
Now, I am using the following code:
FT_Face face;
hb_face_t* hbFace = hb_ft_face_create(face, NULL);
...
hb_font_t* hb_font = hb_font_create(hbFace);
// this line is lifted directly from the HarfBuzz source for hb_ft_font_create
hb_font_set_scale(hb_font,
(int)(((uint64_t)face->size->metrics.x_scale * (uint64_t)face->units_per_EM + (1u << 15)) >> 16),
(int)(((uint64_t)face->size->metrics.y_scale * (uint64_t)face->units_per_EM + (1u << 15)) >> 16));
hb_ft_font_set_funcs(hb_font);Which is about 10 times faster (because I store the hbFace, resulting in shape plans being cached), and I haven't noticed any incorrect behavior. (I could be doing it wrong, though.) However, hb_ft_font_set_funcs still calls FT_New_Memory_Face seemingly unnecessarily, which is now 12% of the CPU usage of the entire application (actually calling hb_shape is only 6%).
I believe I could make this faster still by doing the same thing that hb_ft_font_set_funcs does, but without creating a new FT_Face (using my existing handle). However, this function relies on static functions in HarfBuzz like _hb_ft_font_set_funcs. I'm wondering whether I should add a new function that does the same thing as hb_ft_font_set_funcs but takes an FT_Face reference instead of creating a new one.