[HarfBuzz] harfbuzz: Branch 'master' - 12 commits

Behdad Esfahbod behdad at kemper.freedesktop.org
Tue Oct 9 19:14:06 UTC 2018


 CMakeLists.txt                   |    7 ++
 docs/harfbuzz-sections.txt       |    3 +
 src/hb-buffer.hh                 |   20 +++++++
 src/hb-font.cc                   |   39 +++++++++++++-
 src/hb-font.h                    |   32 ++++++++++--
 src/hb-font.hh                   |   15 +++++
 src/hb-ft.cc                     |   26 +++++++++
 src/hb-ot-font.cc                |   31 +++++++++--
 src/hb-ot-shape-normalize.cc     |  103 ++++++++++++++++++++++++---------------
 src/hb.hh                        |   10 +++
 test/api/test-collect-unicodes.c |    9 ++-
 test/api/test-multithread.c      |    4 -
 test/api/test-subset-glyf.c      |   19 ++++---
 test/api/test-subset-hdmx.c      |    8 ++-
 test/api/test-subset-hmtx.c      |    3 -
 test/api/test-subset-post.c      |    3 -
 test/api/test-subset-vmtx.c      |    6 +-
 test/api/test-subset.c           |   12 +++-
 18 files changed, 275 insertions(+), 75 deletions(-)

New commits:
commit 55153553675445e8aad06e363295d399aa79c54f
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Tue Oct 9 15:12:09 2018 -0400

    [ot-font] Don't pre-load cmap table
    
    Now that we have get_h_advances() and get_nominal_glyphs() implemented, the
    overhead of doing a proper atomic load would be once per run, NOT once per
    glyph.  So, no need to pre-load the tables to avoid that overhead.
    
    As such, hb_ot_font_set_funcs() has become really cheap.  Can *finally* make
    it be default font functions on all newly created fonts!

diff --git a/src/hb-ot-font.cc b/src/hb-ot-font.cc
index 1498911d..0631453b 100644
--- a/src/hb-ot-font.cc
+++ b/src/hb-ot-font.cc
@@ -48,7 +48,7 @@ hb_ot_get_nominal_glyph (hb_font_t *font HB_UNUSED,
 			 void *user_data HB_UNUSED)
 {
   const hb_ot_face_data_t *ot_face = (const hb_ot_face_data_t *) font_data;
-  return ot_face->cmap.get_relaxed()->get_nominal_glyph (unicode, glyph);
+  return ot_face->cmap.get ()->get_nominal_glyph (unicode, glyph);
 }
 
 static unsigned int
@@ -62,7 +62,7 @@ hb_ot_get_nominal_glyphs (hb_font_t *font HB_UNUSED,
 			  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 ();
+  const OT::cmap_accelerator_t &cmap = *ot_face->cmap.get ();
   unsigned int done;
   for (done = 0;
        done < count && cmap.get_nominal_glyph (*first_unicode, first_glyph);
@@ -83,7 +83,7 @@ hb_ot_get_variation_glyph (hb_font_t *font HB_UNUSED,
 			   void *user_data HB_UNUSED)
 {
   const hb_ot_face_data_t *ot_face = (const hb_ot_face_data_t *) font_data;
-  return ot_face->cmap.get_relaxed ()->get_variation_glyph (unicode, variation_selector, glyph);
+  return ot_face->cmap.get ()->get_variation_glyph (unicode, variation_selector, glyph);
 }
 
 static void
@@ -257,9 +257,6 @@ hb_ot_font_set_funcs (hb_font_t *font)
   if (unlikely (!hb_ot_shaper_face_data_ensure (font->face))) return;
   hb_ot_face_data_t *ot_face = hb_ot_face_data (font->face);
 
-  /* Load them lazy.  We access it with get_relaxed() for performance. */
-  ot_face->cmap.get ();
-
   hb_font_set_funcs (font,
 		     _hb_ot_get_font_funcs (),
 		     ot_face,
commit ec84460e46fdaa5f8a3c16c8d48dabe2b0c869da
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Tue Oct 9 15:07:04 2018 -0400

    [ot/ft] Implement get_nominal_glyphs() callback
    
    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...

diff --git a/src/hb-ft.cc b/src/hb-ft.cc
index 79ce8f49..d293693c 100644
--- a/src/hb-ft.cc
+++ b/src/hb-ft.cc
@@ -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);
diff --git a/src/hb-ot-font.cc b/src/hb-ot-font.cc
index 686c873d..1498911d 100644
--- a/src/hb-ot-font.cc
+++ b/src/hb-ot-font.cc
@@ -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);
commit e883f52732a25f5495ec30656489954afd8cc3a4
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Tue Oct 9 14:50:57 2018 -0400

    Call get_nominal_glyphs() for runs of simple clusters at a time
    
    Even without FT or OT font funcs implementing get_nominal_glyphs(), there's measurable
    speedup.

diff --git a/src/hb-buffer.hh b/src/hb-buffer.hh
index 9126822e..9628ddae 100644
--- a/src/hb-buffer.hh
+++ b/src/hb-buffer.hh
@@ -260,7 +260,8 @@ struct hb_buffer_t
   {
     if (have_output)
     {
-      if (unlikely (out_info != info || out_len != idx)) {
+      if (out_info != info || out_len != idx)
+      {
 	if (unlikely (!make_room_for (1, 1))) return;
 	out_info[out_len] = info[idx];
       }
@@ -269,6 +270,23 @@ struct hb_buffer_t
 
     idx++;
   }
+  /* Copies n glyphs at idx to output and advance idx.
+   * If there's no output, just advance idx. */
+  inline void
+  next_glyphs (unsigned int n)
+  {
+    if (have_output)
+    {
+      if (out_info != info || out_len != idx)
+      {
+	if (unlikely (!make_room_for (n, n))) return;
+	memmove (out_info + out_len, info + idx, n * sizeof (out_info[0]));
+      }
+      out_len += n;
+    }
+
+    idx += n;
+  }
   /* Advance idx without copying to output. */
   inline void skip_glyph (void)
   {
diff --git a/src/hb-ot-shape-normalize.cc b/src/hb-ot-shape-normalize.cc
index 3d62e44b..a8229a98 100644
--- a/src/hb-ot-shape-normalize.cc
+++ b/src/hb-ot-shape-normalize.cc
@@ -335,6 +335,15 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan,
 	end--; /* Leave one base for the marks to cluster with. */
 
       /* From idx to end are simple clusters. */
+      if (might_short_circuit)
+      {
+        unsigned int done = font->get_nominal_glyphs (end - buffer->idx,
+						      &buffer->cur().codepoint,
+						      sizeof (buffer->info[0]),
+						      &buffer->cur().glyph_index(),
+						      sizeof (buffer->info[0]));
+	buffer->next_glyphs (done);
+      }
       while (buffer->idx < end && buffer->successful)
 	decompose_current_character (&c, might_short_circuit);
 
commit 8008bca83b0bb310fc434dbdd339545af951193b
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Tue Oct 9 14:38:23 2018 -0400

    Whitespace

diff --git a/src/hb-font.hh b/src/hb-font.hh
index ce140ab6..e10d5674 100644
--- a/src/hb-font.hh
+++ b/src/hb-font.hh
@@ -213,7 +213,7 @@ struct hb_font_t
 				       unicode, glyph,
 				       klass->user_data.nominal_glyph);
   }
-  inline unsigned int get_nominal_glyphs ( unsigned int count,
+  inline unsigned int get_nominal_glyphs (unsigned int count,
 					  const hb_codepoint_t *first_unicode,
 					  unsigned int unicode_stride,
 					  hb_codepoint_t *first_glyph,
diff --git a/src/hb-ot-shape-normalize.cc b/src/hb-ot-shape-normalize.cc
index 5df0aa0b..3d62e44b 100644
--- a/src/hb-ot-shape-normalize.cc
+++ b/src/hb-ot-shape-normalize.cc
@@ -320,40 +320,44 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan,
   /* First round, decompose */
 
   bool all_simple = true;
-  buffer->clear_output ();
-  count = buffer->len;
-  buffer->idx = 0;
-  do
   {
-    unsigned int end;
-    for (end = buffer->idx + 1; end < count; end++)
-      if (unlikely (HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&buffer->info[end]))))
-        break;
+    buffer->clear_output ();
+    count = buffer->len;
+    buffer->idx = 0;
+    do
+    {
+      unsigned int end;
+      for (end = buffer->idx + 1; end < count; end++)
+	if (unlikely (HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&buffer->info[end]))))
+	  break;
 
-    if (end < count)
-      end--; /* Leave one base for the marks to cluster with. */
+      if (end < count)
+	end--; /* Leave one base for the marks to cluster with. */
 
-    /* From idx to end are simple clusters. */
-    while (buffer->idx < end && buffer->successful)
-      decompose_current_character (&c, might_short_circuit);
+      /* From idx to end are simple clusters. */
+      while (buffer->idx < end && buffer->successful)
+	decompose_current_character (&c, might_short_circuit);
 
-    if (buffer->idx == count || !buffer->successful)
-      break;
+      if (buffer->idx == count || !buffer->successful)
+	break;
 
-    all_simple = false;
+      all_simple = false;
 
-    /* Find all the marks now. */
-    for (end = buffer->idx + 1; end < count; end++)
-      if (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&buffer->info[end])))
-        break;
+      /* Find all the marks now. */
+      for (end = buffer->idx + 1; end < count; end++)
+	if (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&buffer->info[end])))
+	  break;
 
-    /* idx to end is one non-simple cluster. */
-    decompose_multi_char_cluster (&c, end, always_short_circuit);
+      /* idx to end is one non-simple cluster. */
+      decompose_multi_char_cluster (&c, end, always_short_circuit);
+    }
+    while (buffer->idx < count && buffer->successful);
+    buffer->swap_buffers ();
   }
-  while (buffer->idx < count && buffer->successful);
-  buffer->swap_buffers ();
+
 
   /* Second round, reorder (inplace) */
+
   if (!all_simple)
   {
     count = buffer->len;
commit 30c114ffec335770452e60729224b1634586c5b0
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Tue Oct 9 14:37:08 2018 -0400

    Avoid sort and recompose stages if all clusters simple
    
    Even has measurable speedup...

diff --git a/src/hb-ot-shape-normalize.cc b/src/hb-ot-shape-normalize.cc
index 98830e49..5df0aa0b 100644
--- a/src/hb-ot-shape-normalize.cc
+++ b/src/hb-ot-shape-normalize.cc
@@ -319,6 +319,7 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan,
 
   /* First round, decompose */
 
+  bool all_simple = true;
   buffer->clear_output ();
   count = buffer->len;
   buffer->idx = 0;
@@ -332,49 +333,53 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan,
     if (end < count)
       end--; /* Leave one base for the marks to cluster with. */
 
-    /* From i to end are simple clusters. */
+    /* From idx to end are simple clusters. */
     while (buffer->idx < end && buffer->successful)
       decompose_current_character (&c, might_short_circuit);
 
     if (buffer->idx == count || !buffer->successful)
       break;
 
+    all_simple = false;
+
     /* Find all the marks now. */
     for (end = buffer->idx + 1; end < count; end++)
       if (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&buffer->info[end])))
         break;
 
+    /* idx to end is one non-simple cluster. */
     decompose_multi_char_cluster (&c, end, always_short_circuit);
   }
   while (buffer->idx < count && buffer->successful);
   buffer->swap_buffers ();
 
-
   /* Second round, reorder (inplace) */
-
-  count = buffer->len;
-  for (unsigned int i = 0; i < count; i++)
+  if (!all_simple)
   {
-    if (_hb_glyph_info_get_modified_combining_class (&buffer->info[i]) == 0)
-      continue;
+    count = buffer->len;
+    for (unsigned int i = 0; i < count; i++)
+    {
+      if (_hb_glyph_info_get_modified_combining_class (&buffer->info[i]) == 0)
+	continue;
+
+      unsigned int end;
+      for (end = i + 1; end < count; end++)
+	if (_hb_glyph_info_get_modified_combining_class (&buffer->info[end]) == 0)
+	  break;
+
+      /* We are going to do a O(n^2).  Only do this if the sequence is short. */
+      if (end - i > HB_OT_SHAPE_COMPLEX_MAX_COMBINING_MARKS) {
+	i = end;
+	continue;
+      }
 
-    unsigned int end;
-    for (end = i + 1; end < count; end++)
-      if (_hb_glyph_info_get_modified_combining_class (&buffer->info[end]) == 0)
-        break;
+      buffer->sort (i, end, compare_combining_class);
+
+      if (plan->shaper->reorder_marks)
+	plan->shaper->reorder_marks (plan, buffer, i, end);
 
-    /* We are going to do a O(n^2).  Only do this if the sequence is short. */
-    if (end - i > HB_OT_SHAPE_COMPLEX_MAX_COMBINING_MARKS) {
       i = end;
-      continue;
     }
-
-    buffer->sort (i, end, compare_combining_class);
-
-    if (plan->shaper->reorder_marks)
-      plan->shaper->reorder_marks (plan, buffer, i, end);
-
-    i = end;
   }
   if (buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_CGJ)
   {
@@ -393,8 +398,9 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan,
 
   /* Third round, recompose */
 
-  if (mode == HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS ||
-      mode == HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT)
+  if (!all_simple &&
+      (mode == HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS ||
+       mode == HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT))
   {
     /* As noted in the comment earlier, we don't try to combine
      * ccc=0 chars with their previous Starter. */
commit 9f79365c3b183278d14352ba6241c7d4ec274984
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Tue Oct 9 14:36:25 2018 -0400

    Fix warning
    
    How come this one is not generated by clang everything bot?!
    
    ../../../test/api/test-multithread.c:37:26: warning: initialization discards ‘const’ qualifier from pointer target type [-Wdiscarded-qualifiers]
     static char *font_path = "fonts/Inconsolata-Regular.abc.ttf";
                              ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ../../../test/api/test-multithread.c:38:21: warning: initialization discards ‘const’ qualifier from pointer target type [-Wdiscarded-qualifiers]

diff --git a/test/api/test-multithread.c b/test/api/test-multithread.c
index 58a637ca..af5e8f9a 100644
--- a/test/api/test-multithread.c
+++ b/test/api/test-multithread.c
@@ -34,8 +34,8 @@
 #include <hb-ot.h>
 #include <glib.h>
 
-static char *font_path = "fonts/Inconsolata-Regular.abc.ttf";
-static char *text = "abc";
+static const char *font_path = "fonts/Inconsolata-Regular.abc.ttf";
+static const char *text = "abc";
 
 static int num_threads = 30;
 static int num_iters = 200;
commit 24382debe893450088acd1e4b387ac31145d4553
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Tue Oct 9 14:33:24 2018 -0400

    Rewrite main normalizer loop to isolate runs of simple clusters

diff --git a/src/hb-ot-shape-normalize.cc b/src/hb-ot-shape-normalize.cc
index 9436cb5f..98830e49 100644
--- a/src/hb-ot-shape-normalize.cc
+++ b/src/hb-ot-shape-normalize.cc
@@ -321,18 +321,32 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan,
 
   buffer->clear_output ();
   count = buffer->len;
-  for (buffer->idx = 0; buffer->idx < count && buffer->successful;)
+  buffer->idx = 0;
+  do
   {
     unsigned int end;
     for (end = buffer->idx + 1; end < count; end++)
-      if (likely (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&buffer->info[end]))))
+      if (unlikely (HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&buffer->info[end]))))
         break;
 
-    if (likely (c.buffer->idx + 1 == end))
+    if (end < count)
+      end--; /* Leave one base for the marks to cluster with. */
+
+    /* From i to end are simple clusters. */
+    while (buffer->idx < end && buffer->successful)
       decompose_current_character (&c, might_short_circuit);
-    else
-      decompose_multi_char_cluster (&c, end, always_short_circuit);
+
+    if (buffer->idx == count || !buffer->successful)
+      break;
+
+    /* Find all the marks now. */
+    for (end = buffer->idx + 1; end < count; end++)
+      if (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&buffer->info[end])))
+        break;
+
+    decompose_multi_char_cluster (&c, end, always_short_circuit);
   }
+  while (buffer->idx < count && buffer->successful);
   buffer->swap_buffers ();
 
 
commit b5371f18effbeb91565fd8c554c120b911641f0b
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Tue Oct 9 14:12:59 2018 -0400

    Inline decompose_cluster
    
    Towards separating the common case into its own loop.

diff --git a/src/hb-ot-shape-normalize.cc b/src/hb-ot-shape-normalize.cc
index 0e13707e..9436cb5f 100644
--- a/src/hb-ot-shape-normalize.cc
+++ b/src/hb-ot-shape-normalize.cc
@@ -264,15 +264,6 @@ decompose_multi_char_cluster (const hb_ot_shape_normalize_context_t *c, unsigned
     decompose_current_character (c, short_circuit);
 }
 
-static inline void
-decompose_cluster (const hb_ot_shape_normalize_context_t *c, unsigned int end, bool might_short_circuit, bool always_short_circuit)
-{
-  if (likely (c->buffer->idx + 1 == end))
-    decompose_current_character (c, might_short_circuit);
-  else
-    decompose_multi_char_cluster (c, end, always_short_circuit);
-}
-
 
 static int
 compare_combining_class (const hb_glyph_info_t *pa, const hb_glyph_info_t *pb)
@@ -337,7 +328,10 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan,
       if (likely (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&buffer->info[end]))))
         break;
 
-    decompose_cluster (&c, end, might_short_circuit, always_short_circuit);
+    if (likely (c.buffer->idx + 1 == end))
+      decompose_current_character (&c, might_short_circuit);
+    else
+      decompose_multi_char_cluster (&c, end, always_short_circuit);
   }
   buffer->swap_buffers ();
 
commit b314c4e9abf4236c6650a63d1287471b61f64885
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Tue Oct 9 09:23:51 2018 -0400

    [font] Add get_nominal_glyphs() callback (note the plural)
    
    Unused as of now.  To be wired up to normalizer, which would remove
    overhead and allow hb-ot-font initialization to become a no-op, so
    we can enable it by default.

diff --git a/docs/harfbuzz-sections.txt b/docs/harfbuzz-sections.txt
index 2ee14a96..4cb8d42b 100644
--- a/docs/harfbuzz-sections.txt
+++ b/docs/harfbuzz-sections.txt
@@ -237,6 +237,7 @@ hb_font_funcs_set_glyph_v_advance_func
 hb_font_funcs_set_glyph_v_advances_func
 hb_font_funcs_set_glyph_v_origin_func
 hb_font_funcs_set_nominal_glyph_func
+hb_font_funcs_set_nominal_glyphs_func
 hb_font_funcs_set_user_data
 hb_font_funcs_set_variation_glyph_func
 hb_font_funcs_t
@@ -273,6 +274,8 @@ hb_font_get_glyph_v_origin
 hb_font_get_glyph_v_origin_func_t
 hb_font_get_nominal_glyph
 hb_font_get_nominal_glyph_func_t
+hb_font_get_nominal_glyphs
+hb_font_get_nominal_glyphs_func_t
 hb_font_get_parent
 hb_font_get_ppem
 hb_font_get_ptem
diff --git a/src/hb-font.cc b/src/hb-font.cc
index 2a40aeb5..fcf86f07 100644
--- a/src/hb-font.cc
+++ b/src/hb-font.cc
@@ -101,9 +101,42 @@ hb_font_get_nominal_glyph_default (hb_font_t *font,
 				   hb_codepoint_t *glyph,
 				   void *user_data HB_UNUSED)
 {
+  if (font->has_nominal_glyphs_func ())
+  {
+    return font->get_nominal_glyphs (1, &unicode, 0, glyph, 0);
+  }
   return font->parent->get_nominal_glyph (unicode, glyph);
 }
 
+#define hb_font_get_nominal_glyphs_nil hb_font_get_nominal_glyphs_default
+static unsigned int
+hb_font_get_nominal_glyphs_default (hb_font_t *font,
+				    void *font_data HB_UNUSED,
+				    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)
+{
+  if (font->has_nominal_glyph_func ())
+  {
+    for (unsigned int i = 0; i < count; i++)
+    {
+      if (!font->get_nominal_glyph (*first_unicode, first_glyph))
+        return i;
+
+      first_unicode = &StructAtOffset<hb_codepoint_t> (first_unicode, unicode_stride);
+      first_glyph = &StructAtOffset<hb_codepoint_t> (first_glyph, glyph_stride);
+    }
+    return count;
+  }
+
+  return font->parent->get_nominal_glyphs (count,
+					   first_unicode, unicode_stride,
+					   first_glyph, glyph_stride);
+}
+
 static hb_bool_t
 hb_font_get_variation_glyph_nil (hb_font_t *font HB_UNUSED,
 				 void *font_data HB_UNUSED,
diff --git a/src/hb-font.h b/src/hb-font.h
index 6ee6b2a8..dc88f26c 100644
--- a/src/hb-font.h
+++ b/src/hb-font.h
@@ -125,6 +125,14 @@ typedef hb_bool_t (*hb_font_get_variation_glyph_func_t) (hb_font_t *font, void *
 							 hb_codepoint_t *glyph,
 							 void *user_data);
 
+typedef unsigned int (*hb_font_get_nominal_glyphs_func_t) (hb_font_t *font, 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);
+
 
 typedef hb_position_t (*hb_font_get_glyph_advance_func_t) (hb_font_t *font, void *font_data,
 							   hb_codepoint_t glyph,
@@ -221,6 +229,22 @@ hb_font_funcs_set_nominal_glyph_func (hb_font_funcs_t *ffuncs,
 				      void *user_data, hb_destroy_func_t destroy);
 
 /**
+ * hb_font_funcs_set_nominal_glyphs_func:
+ * @ffuncs: font functions.
+ * @func: (closure user_data) (destroy destroy) (scope notified):
+ * @user_data:
+ * @destroy:
+ *
+ *
+ *
+ * Since: REPLACEME
+ **/
+HB_EXTERN void
+hb_font_funcs_set_nominal_glyphs_func (hb_font_funcs_t *ffuncs,
+				       hb_font_get_nominal_glyphs_func_t func,
+				       void *user_data, hb_destroy_func_t destroy);
+
+/**
  * hb_font_funcs_set_variation_glyph_func:
  * @ffuncs: font functions.
  * @func: (closure user_data) (destroy destroy) (scope notified):
diff --git a/src/hb-font.hh b/src/hb-font.hh
index 3d00496f..ce140ab6 100644
--- a/src/hb-font.hh
+++ b/src/hb-font.hh
@@ -43,6 +43,7 @@
   HB_FONT_FUNC_IMPLEMENT (font_h_extents) \
   HB_FONT_FUNC_IMPLEMENT (font_v_extents) \
   HB_FONT_FUNC_IMPLEMENT (nominal_glyph) \
+  HB_FONT_FUNC_IMPLEMENT (nominal_glyphs) \
   HB_FONT_FUNC_IMPLEMENT (variation_glyph) \
   HB_FONT_FUNC_IMPLEMENT (glyph_h_advance) \
   HB_FONT_FUNC_IMPLEMENT (glyph_v_advance) \
@@ -212,6 +213,18 @@ struct hb_font_t
 				       unicode, glyph,
 				       klass->user_data.nominal_glyph);
   }
+  inline unsigned int get_nominal_glyphs ( unsigned int count,
+					  const hb_codepoint_t *first_unicode,
+					  unsigned int unicode_stride,
+					  hb_codepoint_t *first_glyph,
+					  unsigned int glyph_stride)
+  {
+    return klass->get.f.nominal_glyphs (this, user_data,
+					count,
+					first_unicode, unicode_stride,
+					first_glyph, glyph_stride,
+					klass->user_data.nominal_glyphs);
+  }
 
   inline hb_bool_t get_variation_glyph (hb_codepoint_t unicode, hb_codepoint_t variation_selector,
 					hb_codepoint_t *glyph)
commit ca6a317012a13ee84b58a69e14e74c94c5b158ff
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Tue Oct 9 09:06:07 2018 -0400

    Minor

diff --git a/src/hb-font.cc b/src/hb-font.cc
index fa5e6614..2a40aeb5 100644
--- a/src/hb-font.cc
+++ b/src/hb-font.cc
@@ -807,7 +807,7 @@ hb_font_get_glyph_v_advance (hb_font_t *font,
  **/
 void
 hb_font_get_glyph_h_advances (hb_font_t* font,
-			      unsigned count,
+			      unsigned int count,
 			      const hb_codepoint_t *first_glyph,
 			      unsigned glyph_stride,
 			      hb_position_t *first_advance,
@@ -825,7 +825,7 @@ hb_font_get_glyph_h_advances (hb_font_t* font,
  **/
 void
 hb_font_get_glyph_v_advances (hb_font_t* font,
-			      unsigned count,
+			      unsigned int count,
 			      const hb_codepoint_t *first_glyph,
 			      unsigned glyph_stride,
 			      hb_position_t *first_advance,
@@ -1052,7 +1052,7 @@ hb_font_get_glyph_advance_for_direction (hb_font_t *font,
 HB_EXTERN void
 hb_font_get_glyph_advances_for_direction (hb_font_t* font,
 					  hb_direction_t direction,
-					  unsigned count,
+					  unsigned int count,
 					  const hb_codepoint_t *first_glyph,
 					  unsigned glyph_stride,
 					  hb_position_t *first_advance,
diff --git a/src/hb-font.h b/src/hb-font.h
index 48450e99..6ee6b2a8 100644
--- a/src/hb-font.h
+++ b/src/hb-font.h
@@ -133,7 +133,7 @@ typedef hb_font_get_glyph_advance_func_t hb_font_get_glyph_h_advance_func_t;
 typedef hb_font_get_glyph_advance_func_t hb_font_get_glyph_v_advance_func_t;
 
 typedef void (*hb_font_get_glyph_advances_func_t) (hb_font_t* font, void* font_data,
-						   unsigned count,
+						   unsigned int count,
 						   const hb_codepoint_t *first_glyph,
 						   unsigned glyph_stride,
 						   hb_position_t *first_advance,
@@ -423,14 +423,14 @@ hb_font_get_glyph_v_advance (hb_font_t *font,
 
 HB_EXTERN void
 hb_font_get_glyph_h_advances (hb_font_t* font,
-			      unsigned count,
+			      unsigned int count,
 			      const hb_codepoint_t *first_glyph,
 			      unsigned glyph_stride,
 			      hb_position_t *first_advance,
 			      unsigned advance_stride);
 HB_EXTERN void
 hb_font_get_glyph_v_advances (hb_font_t* font,
-			      unsigned count,
+			      unsigned int count,
 			      const hb_codepoint_t *first_glyph,
 			      unsigned glyph_stride,
 			      hb_position_t *first_advance,
@@ -486,7 +486,7 @@ hb_font_get_glyph_advance_for_direction (hb_font_t *font,
 HB_EXTERN void
 hb_font_get_glyph_advances_for_direction (hb_font_t* font,
 					  hb_direction_t direction,
-					  unsigned count,
+					  unsigned int count,
 					  const hb_codepoint_t *first_glyph,
 					  unsigned glyph_stride,
 					  hb_position_t *first_advance,
diff --git a/src/hb-font.hh b/src/hb-font.hh
index 47f5261e..3d00496f 100644
--- a/src/hb-font.hh
+++ b/src/hb-font.hh
@@ -377,7 +377,7 @@ struct hb_font_t
       *y = get_glyph_v_advance (glyph);
   }
   inline void get_glyph_advances_for_direction (hb_direction_t direction,
-						unsigned count,
+						unsigned int count,
 						const hb_codepoint_t *first_glyph,
 						unsigned glyph_stride,
 						hb_position_t *first_advance,
commit 4035158de46ce373b7521daf61c5b6df83312968
Author: Chun-wei Fan <fanchunwei at src.gnome.org>
Date:   Wed Jul 25 18:26:10 2018 +0800

    test/api/test-subset-*.c: Fix build on pre-C99
    
    Ensure that we have the variables at the beginning of the block.  These
    are the only fixes that we need for building HarfBuzz on older
    compilers.

diff --git a/test/api/test-collect-unicodes.c b/test/api/test-collect-unicodes.c
index affe9314..f7a78130 100644
--- a/test/api/test-collect-unicodes.c
+++ b/test/api/test-collect-unicodes.c
@@ -32,10 +32,11 @@ test_collect_unicodes_format4 (void)
 {
   hb_face_t *face = hb_subset_test_open_font("fonts/Roboto-Regular.abc.format4.ttf");
   hb_set_t *codepoints = hb_set_create();
+  hb_codepoint_t cp;
 
   hb_face_collect_unicodes (face, codepoints);
 
-  hb_codepoint_t cp = HB_SET_VALUE_INVALID;
+  cp = HB_SET_VALUE_INVALID;
   g_assert (hb_set_next (codepoints, &cp));
   g_assert_cmpuint (0x61, ==, cp);
   g_assert (hb_set_next (codepoints, &cp));
@@ -53,10 +54,11 @@ test_collect_unicodes_format12 (void)
 {
   hb_face_t *face = hb_subset_test_open_font("fonts/Roboto-Regular.abc.format12.ttf");
   hb_set_t *codepoints = hb_set_create();
+  hb_codepoint_t cp;
 
   hb_face_collect_unicodes (face, codepoints);
 
-  hb_codepoint_t cp = HB_SET_VALUE_INVALID;
+  cp = HB_SET_VALUE_INVALID;
   g_assert (hb_set_next (codepoints, &cp));
   g_assert_cmpuint (0x61, ==, cp);
   g_assert (hb_set_next (codepoints, &cp));
@@ -74,10 +76,11 @@ test_collect_unicodes (void)
 {
   hb_face_t *face = hb_subset_test_open_font("fonts/Roboto-Regular.abc.ttf");
   hb_set_t *codepoints = hb_set_create();
+  hb_codepoint_t cp;
 
   hb_face_collect_unicodes (face, codepoints);
 
-  hb_codepoint_t cp = HB_SET_VALUE_INVALID;
+  cp = HB_SET_VALUE_INVALID;
   g_assert (hb_set_next (codepoints, &cp));
   g_assert_cmpuint (0x61, ==, cp);
   g_assert (hb_set_next (codepoints, &cp));
diff --git a/test/api/test-subset-glyf.c b/test/api/test-subset-glyf.c
index 6f669dae..af9439c0 100644
--- a/test/api/test-subset-glyf.c
+++ b/test/api/test-subset-glyf.c
@@ -105,16 +105,18 @@ test_subset_glyf_with_gsub (void)
 {
   hb_face_t *face_fil = hb_subset_test_open_font ("fonts/Roboto-Regular.gsub.fil.ttf");
   hb_face_t *face_fi = hb_subset_test_open_font ("fonts/Roboto-Regular.gsub.fi.ttf");
+  hb_subset_input_t *input;
+  hb_face_t *face_subset;
 
   hb_set_t *codepoints = hb_set_create();
   hb_set_add (codepoints, 102); // f
   hb_set_add (codepoints, 105); // i
 
-  hb_subset_input_t *input = hb_subset_test_create_input (codepoints);
+  input = hb_subset_test_create_input (codepoints);
   hb_set_destroy (codepoints);
   hb_subset_input_set_drop_layout (input, false);
 
-  hb_face_t *face_subset = hb_subset_test_create_subset (face_fil, input);
+  face_subset = hb_subset_test_create_subset (face_fil, input);
 
   hb_subset_test_check (face_fi, face_subset, HB_TAG ('g','l','y','f'));
   hb_subset_test_check (face_fi, face_subset, HB_TAG ('l','o','c', 'a'));
@@ -130,16 +132,18 @@ test_subset_glyf_without_gsub (void)
 {
   hb_face_t *face_fil = hb_subset_test_open_font ("fonts/Roboto-Regular.gsub.fil.ttf");
   hb_face_t *face_fi = hb_subset_test_open_font ("fonts/Roboto-Regular.nogsub.fi.ttf");
+  hb_subset_input_t *input;
+  hb_face_t *face_subset;
 
   hb_set_t *codepoints = hb_set_create();
   hb_set_add (codepoints, 102); // f
   hb_set_add (codepoints, 105); // i
 
-  hb_subset_input_t *input = hb_subset_test_create_input (codepoints);
+  input = hb_subset_test_create_input (codepoints);
   hb_set_destroy (codepoints);
   hb_subset_input_set_drop_layout (input, true);
 
-  hb_face_t *face_subset = hb_subset_test_create_subset (face_fil, input);
+  face_subset = hb_subset_test_create_subset (face_fil, input);
 
   hb_subset_test_check (face_fi, face_subset, HB_TAG ('g','l','y','f'));
   hb_subset_test_check (face_fi, face_subset, HB_TAG ('l','o','c', 'a'));
@@ -233,16 +237,19 @@ test_subset_glyf_strip_hints_invalid (void)
     '3', '@', '_', '%', '&', ')', '*', '$', '!'
   };
   unsigned int i;
+  hb_subset_input_t *input;
+  hb_face_t *face_subset;
+
   for (i = 0; i < sizeof (text) / sizeof (hb_codepoint_t); i++)
   {
     hb_set_add (codepoints, text[i]);
   }
 
-  hb_subset_input_t *input = hb_subset_test_create_input (codepoints);
+  input = hb_subset_test_create_input (codepoints);
   hb_subset_input_set_drop_hints (input, true);
   hb_set_destroy (codepoints);
 
-  hb_face_t *face_subset = hb_subset_test_create_subset (face, input);
+  face_subset = hb_subset_test_create_subset (face, input);
   g_assert (face_subset);
   g_assert (face_subset == hb_face_get_empty ());
 
diff --git a/test/api/test-subset-hdmx.c b/test/api/test-subset-hdmx.c
index 8a1e821a..ddcdedce 100644
--- a/test/api/test-subset-hdmx.c
+++ b/test/api/test-subset-hdmx.c
@@ -76,11 +76,13 @@ test_subset_hdmx_invalid (void)
 
   hb_subset_input_t *input = hb_subset_input_create_or_fail ();
   hb_set_t *codepoints = hb_subset_input_unicode_set (input);
+  hb_face_t *subset;
+
   hb_set_add (codepoints, 'a');
   hb_set_add (codepoints, 'b');
   hb_set_add (codepoints, 'c');
 
-  hb_face_t *subset = hb_subset (face, input);
+  subset = hb_subset (face, input);
   g_assert (subset);
   g_assert (subset == hb_face_get_empty ());
 
@@ -96,11 +98,13 @@ test_subset_hdmx_fails_sanitize (void)
 
   hb_subset_input_t *input = hb_subset_input_create_or_fail ();
   hb_set_t *codepoints = hb_subset_input_unicode_set (input);
+  hb_face_t *subset;
+
   hb_set_add (codepoints, 'a');
   hb_set_add (codepoints, 'b');
   hb_set_add (codepoints, 'c');
 
-  hb_face_t *subset = hb_subset (face, input);
+  subset = hb_subset (face, input);
   g_assert (subset);
   g_assert (subset == hb_face_get_empty ());
 
diff --git a/test/api/test-subset-hmtx.c b/test/api/test-subset-hmtx.c
index 8b57ca7c..551e5067 100644
--- a/test/api/test-subset-hmtx.c
+++ b/test/api/test-subset-hmtx.c
@@ -154,6 +154,7 @@ static void
 test_subset_invalid_hmtx (void)
 {
   hb_face_t *face = hb_subset_test_open_font("fonts/crash-e4e0bb1458a91b692eba492c907ae1f94e635480");
+  hb_face_t *subset;
 
   hb_subset_input_t *input = hb_subset_input_create_or_fail ();
   hb_set_t *codepoints = hb_subset_input_unicode_set (input);
@@ -161,7 +162,7 @@ test_subset_invalid_hmtx (void)
   hb_set_add (codepoints, 'b');
   hb_set_add (codepoints, 'c');
 
-  hb_face_t *subset = hb_subset (face, input);
+  subset = hb_subset (face, input);
   g_assert (subset);
   g_assert (subset == hb_face_get_empty ());
 
diff --git a/test/api/test-subset-post.c b/test/api/test-subset-post.c
index 948b18a2..c14741e4 100644
--- a/test/api/test-subset-post.c
+++ b/test/api/test-subset-post.c
@@ -34,11 +34,12 @@ test_post_drops_glyph_names (void)
 {
   hb_face_t *face_full = hb_subset_test_open_font ("fonts/Mplus1p-Regular.660E,6975,73E0,5EA6,8F38,6E05.ttf");
   hb_face_t *face_subset = hb_subset_test_open_font ("fonts/Mplus1p-Regular.660E.ttf");
+  hb_face_t *face_full_subset;
 
   hb_set_t *codepoints = hb_set_create ();
   hb_set_add (codepoints, 0x660E);
 
-  hb_face_t *face_full_subset = hb_subset_test_create_subset (face_full, hb_subset_test_create_input (codepoints));
+  face_full_subset = hb_subset_test_create_subset (face_full, hb_subset_test_create_input (codepoints));
   hb_set_destroy (codepoints);
 
   hb_subset_test_check (face_subset, face_full_subset, HB_TAG ('p','o','s','t'));
diff --git a/test/api/test-subset-vmtx.c b/test/api/test-subset-vmtx.c
index 437f0c2f..40ea8f87 100644
--- a/test/api/test-subset-vmtx.c
+++ b/test/api/test-subset-vmtx.c
@@ -48,11 +48,12 @@ test_subset_vmtx_simple_subset (void)
 {
   hb_face_t *face_full = hb_subset_test_open_font ("fonts/Mplus1p-Regular.660E,6975,73E0,5EA6,8F38,6E05.ttf");
   hb_face_t *face_subset = hb_subset_test_open_font ("fonts/Mplus1p-Regular.660E.ttf");
+  hb_face_t *face_full_subset;
 
   hb_set_t *codepoints = hb_set_create ();
   hb_set_add (codepoints, 0x660E);
 
-  hb_face_t *face_full_subset = hb_subset_test_create_subset (face_full, hb_subset_test_create_input (codepoints));
+  face_full_subset = hb_subset_test_create_subset (face_full, hb_subset_test_create_input (codepoints));
   hb_set_destroy (codepoints);
 
   check_num_vmetrics(face_full_subset, 1); /* nothing has same width */
@@ -67,6 +68,7 @@ static void
 test_subset_vmtx_noop (void)
 {
   hb_face_t *face_full = hb_subset_test_open_font ("fonts/Mplus1p-Regular.660E,6975,73E0,5EA6,8F38,6E05.ttf");
+  hb_face_t *face_full_subset;
 
   hb_set_t *codepoints = hb_set_create();
   hb_set_add (codepoints, 0x660E);
@@ -75,7 +77,7 @@ test_subset_vmtx_noop (void)
   hb_set_add (codepoints, 0x5EA6);
   hb_set_add (codepoints, 0x8F38);
   hb_set_add (codepoints, 0x6E05);
-  hb_face_t *face_full_subset = hb_subset_test_create_subset (face_full, hb_subset_test_create_input (codepoints));
+  face_full_subset = hb_subset_test_create_subset (face_full, hb_subset_test_create_input (codepoints));
   hb_set_destroy (codepoints);
 
   check_num_vmetrics(face_full_subset, 1); /* all have the same width */
diff --git a/test/api/test-subset.c b/test/api/test-subset.c
index b0a3446c..2fc885a6 100644
--- a/test/api/test-subset.c
+++ b/test/api/test-subset.c
@@ -36,11 +36,13 @@ test_subset_32_tables (void)
 
   hb_subset_input_t *input = hb_subset_input_create_or_fail ();
   hb_set_t *codepoints = hb_subset_input_unicode_set (input);
+  hb_face_t *subset;
+
   hb_set_add (codepoints, 'a');
   hb_set_add (codepoints, 'b');
   hb_set_add (codepoints, 'c');
 
-  hb_face_t *subset = hb_subset (face, input);
+  subset = hb_subset (face, input);
   g_assert (subset);
   g_assert (subset != hb_face_get_empty ());
 
@@ -56,11 +58,13 @@ test_subset_no_inf_loop (void)
 
   hb_subset_input_t *input = hb_subset_input_create_or_fail ();
   hb_set_t *codepoints = hb_subset_input_unicode_set (input);
+  hb_face_t *subset;
+
   hb_set_add (codepoints, 'a');
   hb_set_add (codepoints, 'b');
   hb_set_add (codepoints, 'c');
 
-  hb_face_t *subset = hb_subset (face, input);
+  subset = hb_subset (face, input);
   g_assert (subset);
   g_assert (subset == hb_face_get_empty ());
 
@@ -76,11 +80,13 @@ test_subset_crash (void)
 
   hb_subset_input_t *input = hb_subset_input_create_or_fail ();
   hb_set_t *codepoints = hb_subset_input_unicode_set (input);
+  hb_face_t *subset;
+
   hb_set_add (codepoints, 'a');
   hb_set_add (codepoints, 'b');
   hb_set_add (codepoints, 'c');
 
-  hb_face_t *subset = hb_subset (face, input);
+  subset = hb_subset (face, input);
   g_assert (subset);
   g_assert (subset == hb_face_get_empty ());
 
commit 8e4ad1d7a0a35298ca04828ef1ef18b4c019ec03
Author: Chun-wei Fan <fanchunwei at src.gnome.org>
Date:   Wed Jul 25 18:12:34 2018 +0800

    builds: Fix and clean up MSVC DLL builds
    
    Instead of passing a CFLAG/CXXFLAG to define HB_EXTERN, define it
    directly in src/hb.hh as __declspec(dllexport) extern when we are
    building HarfBuzz as DLLs on Visual Studio.  Define HB_INTERNAL
    as nothing without defining HB_NO_VISIBILITY when building HarfBuzz as
    DLLs to avoid linker errors on Visual Studio builds.
    
    Also "install" harfbuzz-subset.dll into $(PREFIX)\bin as the
    hb-subset utility will depend on that DLL at runtime, when HarfBuzz is
    built as DLLs.  Since it consists of private APIs that are subject to
    change, we do not install its headers nor .lib file.

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 69496561..d97f7c26 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -574,7 +574,7 @@ if (HB_HAVE_GOBJECT)
 endif ()
 
 if (BUILD_SHARED_LIBS AND WIN32 AND NOT MINGW)
-  add_definitions("-DHB_EXTERN=__declspec(dllexport) extern")
+  add_definitions("-DHB_DLL_EXPORT")
 endif ()
 
 # On Windows, g-ir-scanner requires a DLL build in order for it to work
@@ -772,6 +772,11 @@ if (NOT SKIP_INSTALL_LIBRARIES AND NOT SKIP_INSTALL_ALL)
       DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/harfbuzz
   )
   if (HB_BUILD_UTILS)
+    if (WIN32 AND BUILD_SHARED_LIBS)
+      install(TARGETS harfbuzz-subset
+        RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
+      )
+    endif ()
     install(TARGETS hb-view
       RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
     )
diff --git a/src/hb.hh b/src/hb.hh
index cfe6d68f..15228522 100644
--- a/src/hb.hh
+++ b/src/hb.hh
@@ -39,6 +39,10 @@
 #define _POSIX_C_SOURCE 200809L
 #endif
 
+#if defined (_MSC_VER) && defined (HB_DLL_EXPORT)
+#define HB_EXTERN __declspec (dllexport) extern
+#endif
+
 #include "hb.h"
 #define HB_H_IN
 #ifdef HAVE_OT
@@ -178,8 +182,10 @@ struct _hb_alignof
 # if !defined(HB_NO_VISIBILITY) && !defined(__MINGW32__) && !defined(__CYGWIN__) && !defined(_MSC_VER) && !defined(__SUNPRO_CC)
 #  define HB_INTERNAL __attribute__((__visibility__("hidden")))
 # elif defined(__MINGW32__)
-   /* We use -export-symbols on mingw32, since it does not support visibility
-    * attribute. */
+   /* We use -export-symbols on mingw32, since it does not support visibility attributes. */
+#  define HB_INTERNAL
+# elif defined (_MSC_VER) && defined (HB_DLL_EXPORT)
+   /* We do not try to export internal symbols on Visual Studio */
 #  define HB_INTERNAL
 #else
 #  define HB_INTERNAL


More information about the HarfBuzz mailing list