[ot/ft] Implement get_nominal_glyphs() callback
authorBehdad Esfahbod <behdad@behdad.org>
Tue, 9 Oct 2018 19:07:04 +0000 (15:07 -0400)
committerBehdad Esfahbod <behdad@behdad.org>
Tue, 9 Oct 2018 19:07:04 +0000 (15:07 -0400)
Some more measurable speedup.  The recent commits' speedups are as follows:

Testing with Roboto, ****when disabling kern and liga****:

Before:

FT --features=-kern,-liga
user↦   0m0.521s

OT --features=-liga,-kern
user↦   0m0.568s

After:

FT --features=-liga,-kern
user↦   0m0.428s

OT --features=-liga,-kern
user↦   0m0.470s

So, 17% speedup.

Note that FT callbacks are faster than OT these days since we added an advance
cache to FT.  I don't think the difference is enough to justify adding a cache
to OT.

When not disabling kern, the thing is three times slower, so the speedups
are three times less impressive...  Still, 5% not bad for a codebase that I
otherwise thought is optimized out.

Note that, because of this and other optimiztions in our main shaper,
disabling kern and liga, the OT shaper is now *faster* than the fallback
shaper.  So, that's my recommendation to clients that need the absolute
fastest...

src/hb-ft.cc
src/hb-ot-font.cc

index 79ce8f4..d293693 100644 (file)
@@ -200,6 +200,31 @@ hb_ft_get_nominal_glyph (hb_font_t *font HB_UNUSED,
   return true;
 }
 
+static unsigned int
+hb_ft_get_nominal_glyphs (hb_font_t *font HB_UNUSED,
+                         void *font_data,
+                         unsigned int count,
+                         const hb_codepoint_t *first_unicode,
+                         unsigned int unicode_stride,
+                         hb_codepoint_t *first_glyph,
+                         unsigned int glyph_stride,
+                         void *user_data HB_UNUSED)
+{
+  const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
+  unsigned int done;
+  for (done = 0;
+       done < count && (*first_glyph = FT_Get_Char_Index (ft_font->ft_face, *first_unicode));
+       done++)
+  {
+    first_unicode = &StructAtOffset<hb_codepoint_t> (first_unicode, unicode_stride);
+    first_glyph = &StructAtOffset<hb_codepoint_t> (first_glyph, glyph_stride);
+  }
+  /* We don't need to do ft_font->symbol dance here, since HB calls the singular
+   * nominal_glyph() for what we don't handle here. */
+  return done;
+}
+
+
 static hb_bool_t
 hb_ft_get_variation_glyph (hb_font_t *font HB_UNUSED,
                           void *font_data,
@@ -444,6 +469,7 @@ static struct hb_ft_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t<hb_ft
     hb_font_funcs_set_font_h_extents_func (funcs, hb_ft_get_font_h_extents, nullptr, nullptr);
     //hb_font_funcs_set_font_v_extents_func (funcs, hb_ft_get_font_v_extents, nullptr, nullptr);
     hb_font_funcs_set_nominal_glyph_func (funcs, hb_ft_get_nominal_glyph, nullptr, nullptr);
+    hb_font_funcs_set_nominal_glyphs_func (funcs, hb_ft_get_nominal_glyphs, nullptr, nullptr);
     hb_font_funcs_set_variation_glyph_func (funcs, hb_ft_get_variation_glyph, nullptr, nullptr);
     hb_font_funcs_set_glyph_h_advances_func (funcs, hb_ft_get_glyph_h_advances, nullptr, nullptr);
     hb_font_funcs_set_glyph_v_advance_func (funcs, hb_ft_get_glyph_v_advance, nullptr, nullptr);
index 686c873..1498911 100644 (file)
@@ -51,6 +51,29 @@ hb_ot_get_nominal_glyph (hb_font_t *font HB_UNUSED,
   return ot_face->cmap.get_relaxed()->get_nominal_glyph (unicode, glyph);
 }
 
+static unsigned int
+hb_ot_get_nominal_glyphs (hb_font_t *font HB_UNUSED,
+                         void *font_data,
+                         unsigned int count,
+                         const hb_codepoint_t *first_unicode,
+                         unsigned int unicode_stride,
+                         hb_codepoint_t *first_glyph,
+                         unsigned int glyph_stride,
+                         void *user_data HB_UNUSED)
+{
+  const hb_ot_face_data_t *ot_face = (const hb_ot_face_data_t *) font_data;
+  const OT::cmap_accelerator_t &cmap = *ot_face->cmap.get_relaxed ();
+  unsigned int done;
+  for (done = 0;
+       done < count && cmap.get_nominal_glyph (*first_unicode, first_glyph);
+       done++)
+  {
+    first_unicode = &StructAtOffset<hb_codepoint_t> (first_unicode, unicode_stride);
+    first_glyph = &StructAtOffset<hb_codepoint_t> (first_glyph, glyph_stride);
+  }
+  return done;
+}
+
 static hb_bool_t
 hb_ot_get_variation_glyph (hb_font_t *font HB_UNUSED,
                           void *font_data,
@@ -187,6 +210,7 @@ static struct hb_ot_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t<hb_ot
     hb_font_funcs_set_font_h_extents_func (funcs, hb_ot_get_font_h_extents, nullptr, nullptr);
     hb_font_funcs_set_font_v_extents_func (funcs, hb_ot_get_font_v_extents, nullptr, nullptr);
     hb_font_funcs_set_nominal_glyph_func (funcs, hb_ot_get_nominal_glyph, nullptr, nullptr);
+    hb_font_funcs_set_nominal_glyphs_func (funcs, hb_ot_get_nominal_glyphs, nullptr, nullptr);
     hb_font_funcs_set_variation_glyph_func (funcs, hb_ot_get_variation_glyph, nullptr, nullptr);
     hb_font_funcs_set_glyph_h_advances_func (funcs, hb_ot_get_glyph_h_advances, nullptr, nullptr);
     hb_font_funcs_set_glyph_v_advances_func (funcs, hb_ot_get_glyph_v_advances, nullptr, nullptr);