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

Behdad Esfahbod behdad at kemper.freedesktop.org
Wed Nov 4 17:30:11 PST 2015


 src/hb-buffer-private.hh            |   10 +++++
 src/hb-buffer.cc                    |    2 +
 src/hb-ot-layout-common-private.hh  |    5 ++
 src/hb-ot-layout-private.hh         |    8 ++--
 src/hb-ot-map-private.hh            |   16 --------
 src/hb-ot-shape-fallback-private.hh |    4 ++
 src/hb-ot-shape-fallback.cc         |   67 ++++++++++++++++++++++++++++++++++++
 src/hb-ot-shape-normalize.cc        |    1 
 src/hb-ot-shape.cc                  |    5 ++
 src/hb-private.hh                   |   14 +++++++
 src/hb-unicode-private.hh           |   56 ++++++++++++++++--------------
 test/shaping/tests/spaces.tests     |   24 ++++++------
 12 files changed, 155 insertions(+), 57 deletions(-)

New commits:
commit 49ef630936325b2e56a870fcef9aa8473a8f8526
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Wed Nov 4 17:27:07 2015 -0800

    Adjust the width of various spaces if font does not cover them
    
    See discussion here:
    https://github.com/behdad/harfbuzz/commit/81ef4f407d9c7bd98cf62cef951dc538b13442eb
    
    There's no way to disable this fallback, but I don't think it would
    be needed.  Let's hope for the best!
    
    Fixes https://github.com/behdad/harfbuzz/issues/153

diff --git a/src/hb-buffer-private.hh b/src/hb-buffer-private.hh
index 8e33fc8..c5a116d 100644
--- a/src/hb-buffer-private.hh
+++ b/src/hb-buffer-private.hh
@@ -41,6 +41,12 @@ ASSERT_STATIC (sizeof (hb_glyph_info_t) == sizeof (hb_glyph_position_t));
 template <> class hb_mark_as_flags_t<hb_buffer_flags_t> {};
 template <> class hb_mark_as_flags_t<hb_buffer_serialize_flags_t> {};
 
+enum hb_buffer_scratch_flags_t {
+  HB_BUFFER_SCRATCH_FLAG_DEFAULT			= 0x00000000u,
+  HB_BUFFER_SCRATCH_FLAG_HAS_SPACE_FALLBACK		= 0x00000001u,
+};
+template <> class hb_mark_as_flags_t<hb_buffer_scratch_flags_t> {};
+
 
 /*
  * hb_buffer_t
@@ -55,6 +61,7 @@ struct hb_buffer_t {
   hb_buffer_flags_t flags; /* BOT / EOT / etc. */
   hb_buffer_cluster_level_t cluster_level;
   hb_codepoint_t replacement; /* U+FFFD or something else. */
+  hb_buffer_scratch_flags_t scratch_flags; /* Have space-flallback, etc. */
 
   /* Buffer contents */
   hb_buffer_content_type_t content_type;
diff --git a/src/hb-buffer.cc b/src/hb-buffer.cc
index 50710dd..f690769 100644
--- a/src/hb-buffer.cc
+++ b/src/hb-buffer.cc
@@ -198,6 +198,7 @@ hb_buffer_t::clear (void)
 
   hb_segment_properties_t default_props = HB_SEGMENT_PROPERTIES_DEFAULT;
   props = default_props;
+  scratch_flags = HB_BUFFER_SCRATCH_FLAG_DEFAULT;
 
   content_type = HB_BUFFER_CONTENT_TYPE_INVALID;
   in_error = false;
@@ -738,6 +739,7 @@ hb_buffer_get_empty (void)
     HB_BUFFER_FLAG_DEFAULT,
     HB_BUFFER_CLUSTER_LEVEL_DEFAULT,
     HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT,
+    HB_BUFFER_SCRATCH_FLAG_DEFAULT,
 
     HB_BUFFER_CONTENT_TYPE_INVALID,
     HB_SEGMENT_PROPERTIES_DEFAULT,
diff --git a/src/hb-ot-shape-fallback-private.hh b/src/hb-ot-shape-fallback-private.hh
index ec65351..e134224 100644
--- a/src/hb-ot-shape-fallback-private.hh
+++ b/src/hb-ot-shape-fallback-private.hh
@@ -45,5 +45,9 @@ HB_INTERNAL void _hb_ot_shape_fallback_kern (const hb_ot_shape_plan_t *plan,
 					     hb_font_t *font,
 					     hb_buffer_t  *buffer);
 
+HB_INTERNAL void _hb_ot_shape_fallback_spaces (const hb_ot_shape_plan_t *plan,
+					       hb_font_t *font,
+					       hb_buffer_t  *buffer);
+
 
 #endif /* HB_OT_SHAPE_FALLBACK_PRIVATE_HH */
diff --git a/src/hb-ot-shape-fallback.cc b/src/hb-ot-shape-fallback.cc
index 3cb3456..c9cf737 100644
--- a/src/hb-ot-shape-fallback.cc
+++ b/src/hb-ot-shape-fallback.cc
@@ -484,3 +484,70 @@ _hb_ot_shape_fallback_kern (const hb_ot_shape_plan_t *plan,
     idx = skippy_iter.idx;
   }
 }
+
+
+/* Adjusts width of various spaces. */
+void
+_hb_ot_shape_fallback_spaces (const hb_ot_shape_plan_t *plan,
+			      hb_font_t *font,
+			      hb_buffer_t  *buffer)
+{
+  if (!HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction))
+    return;
+
+  hb_glyph_info_t *info = buffer->info;
+  hb_glyph_position_t *pos = buffer->pos;
+  unsigned int count = buffer->len;
+  for (unsigned int i = 0; i < count; i++)
+    if (_hb_glyph_info_is_unicode_space (&info[i]) && !_hb_glyph_info_ligated (&info[i]))
+    {
+      hb_unicode_funcs_t::space_t space_type = _hb_glyph_info_get_unicode_space_fallback_type (&info[i]);
+      hb_codepoint_t glyph;
+      typedef hb_unicode_funcs_t t;
+      switch (space_type)
+      {
+	case t::NOT_SPACE: /* Shouldn't happen. */
+	case t::SPACE:
+	  break;
+
+	case t::SPACE_EM:
+	case t::SPACE_EM_2:
+	case t::SPACE_EM_3:
+	case t::SPACE_EM_4:
+	case t::SPACE_EM_5:
+	case t::SPACE_EM_6:
+	case t::SPACE_EM_16:
+	  pos[i].x_advance = (font->x_scale + ((int) space_type)/2) / (int) space_type;
+	  break;
+
+	case t::SPACE_4_EM_18:
+	  pos[i].x_advance = font->x_scale * 4 / 18;
+	  break;
+
+	case t::SPACE_FIGURE:
+	  for (char u = '0'; u <= '9'; u++)
+	    if (font->get_glyph (u, 0, &glyph))
+	    {
+	      pos[i].x_advance = font->get_glyph_h_advance (glyph);
+	      break;
+	    }
+	  break;
+
+	case t::SPACE_PUNCTUATION:
+	  if (font->get_glyph ('.', 0, &glyph))
+	    pos[i].x_advance = font->get_glyph_h_advance (glyph);
+	  else if (font->get_glyph (',', 0, &glyph))
+	    pos[i].x_advance = font->get_glyph_h_advance (glyph);
+	  break;
+
+	case t::SPACE_NARROW:
+	  /* Half-space?
+	   * Unicode doc http://www.unicode.org/charts/PDF/U2000.pdf says ~1/4 or 1/5 of EM.
+	   * However, in my testing, many fonts have their regular space being about that
+	   * size.  To me, a percentage of the space width makes more sense.  Half is as
+	   * good as any. */
+	  pos[i].x_advance /= 2;
+	  break;
+      }
+    }
+}
diff --git a/src/hb-ot-shape-normalize.cc b/src/hb-ot-shape-normalize.cc
index c86c634..31376b3 100644
--- a/src/hb-ot-shape-normalize.cc
+++ b/src/hb-ot-shape-normalize.cc
@@ -180,6 +180,7 @@ decompose_current_character (const hb_ot_shape_normalize_context_t *c, bool shor
   {
     _hb_glyph_info_set_unicode_space_fallback_type (&buffer->cur(), space_type);
     next_char (buffer, space_glyph);
+    buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_SPACE_FALLBACK;
   }
   else
     next_char (buffer, glyph); /* glyph is initialized in earlier branches. */
diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc
index 205be0a..0b14172 100644
--- a/src/hb-ot-shape.cc
+++ b/src/hb-ot-shape.cc
@@ -659,6 +659,8 @@ hb_ot_position_default (hb_ot_shape_context_t *c)
 						  &pos[i].y_offset);
 
   }
+  if (c->buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_SPACE_FALLBACK)
+    _hb_ot_shape_fallback_spaces (c->plan, c->font, c->buffer);
 }
 
 static inline bool
@@ -778,6 +780,7 @@ static void
 hb_ot_shape_internal (hb_ot_shape_context_t *c)
 {
   c->buffer->deallocate_var_all ();
+  c->buffer->scratch_flags = HB_BUFFER_SCRATCH_FLAG_DEFAULT;
 
   /* Save the original direction, we use it later. */
   c->target_direction = c->buffer->props.direction;
diff --git a/src/hb-unicode-private.hh b/src/hb-unicode-private.hh
index 43bbed6..1290453 100644
--- a/src/hb-unicode-private.hh
+++ b/src/hb-unicode-private.hh
@@ -199,21 +199,24 @@ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE
     }
   }
 
+  /* Space estimates based on:
+   * http://www.unicode.org/charts/PDF/U2000.pdf
+   * https://www.microsoft.com/typography/developers/fdsspec/spaces.aspx
+   */
   enum space_t {
     NOT_SPACE = 0,
-    SPACE_NBSP,
-    SPACE_EN,
-    SPACE_EM,
-    SPACE_EM_3,
-    SPACE_EM_4,
-    SPACE_EM_6,
+    SPACE_EM   = 1,
+    SPACE_EM_2 = 2,
+    SPACE_EM_3 = 3,
+    SPACE_EM_4 = 4,
+    SPACE_EM_5 = 5,
+    SPACE_EM_6 = 6,
+    SPACE_EM_16 = 16,
+    SPACE_4_EM_18,	/* 4/18th of an EM! */
+    SPACE,
     SPACE_FIGURE,
     SPACE_PUNCTUATION,
-    SPACE_THIN,
-    SPACE_HAIR,
     SPACE_NARROW,
-    SPACE_MEDIUM,
-    SPACE_IDEOGRAPHIC,
   };
   static inline space_t
   space_fallback_type (hb_codepoint_t u)
@@ -221,22 +224,23 @@ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE
     switch (u)
     {
       /* All GC=Zs chars that can use a fallback. */
-      default:	  return NOT_SPACE; /* Shouldn't happen. */
-      case 0x00A0u: return SPACE_NBSP;
-      case 0x2000u: return SPACE_EN;
-      case 0x2001u: return SPACE_EM;
-      case 0x2002u: return SPACE_EN;
-      case 0x2003u: return SPACE_EM;
-      case 0x2004u: return SPACE_EM_3;
-      case 0x2005u: return SPACE_EM_4;
-      case 0x2006u: return SPACE_EM_6;
-      case 0x2007u: return SPACE_FIGURE;
-      case 0x2008u: return SPACE_PUNCTUATION;
-      case 0x2009u: return SPACE_THIN;
-      case 0x200Au: return SPACE_HAIR;
-      case 0x202Fu: return SPACE_NARROW;
-      case 0x205Fu: return SPACE_MEDIUM;
-      case 0x3000u: return SPACE_IDEOGRAPHIC;
+      default:	    return NOT_SPACE;	/* Shouldn't happen. */
+      case 0x0020u: return SPACE;	/* U+0020 SPACE */
+      case 0x00A0u: return SPACE;	/* U+00A0 NO-BREAK SPACE */
+      case 0x2000u: return SPACE_EM_2;	/* U+2000 EN QUAD */
+      case 0x2001u: return SPACE_EM;	/* U+2001 EM QUAD */
+      case 0x2002u: return SPACE_EM_2;	/* U+2002 EN SPACE */
+      case 0x2003u: return SPACE_EM;	/* U+2003 EM SPACE */
+      case 0x2004u: return SPACE_EM_3;	/* U+2004 THREE-PER-EM SPACE */
+      case 0x2005u: return SPACE_EM_4;	/* U+2005 FOUR-PER-EM SPACE */
+      case 0x2006u: return SPACE_EM_6;	/* U+2006 SIX-PER-EM SPACE */
+      case 0x2007u: return SPACE_FIGURE;	/* U+2007 FIGURE SPACE */
+      case 0x2008u: return SPACE_PUNCTUATION;	/* U+2008 PUNCTUATION SPACE */
+      case 0x2009u: return SPACE_EM_5;		/* U+2009 THIN SPACE */
+      case 0x200Au: return SPACE_EM_16;		/* U+200A HAIR SPACE */
+      case 0x202Fu: return SPACE_NARROW;	/* U+202F NARROW NO-BREAK SPACE */
+      case 0x205Fu: return SPACE_4_EM_18;	/* U+205F MEDIUM MATHEMATICAL SPACE */
+      case 0x3000u: return SPACE_EM;		/* U+3000 IDEOGRAPHIC SPACE */
     }
   }
 
diff --git a/test/shaping/tests/spaces.tests b/test/shaping/tests/spaces.tests
index d9e5d09..cb386de 100644
--- a/test/shaping/tests/spaces.tests
+++ b/test/shaping/tests/spaces.tests
@@ -1,17 +1,17 @@
 fonts/sha1sum/1c2c3fc37b2d4c3cb2ef726c6cdaaabd4b7f3eb9.ttf:--font-funcs=ot:U+0020:[gid1=0+560]
 fonts/sha1sum/1c2c3fc37b2d4c3cb2ef726c6cdaaabd4b7f3eb9.ttf:--font-funcs=ot:U+00A0:[gid1=0+560]
 fonts/sha1sum/1c2c3fc37b2d4c3cb2ef726c6cdaaabd4b7f3eb9.ttf:--font-funcs=ot:U+1680:[gid0=0+692]
-fonts/sha1sum/1c2c3fc37b2d4c3cb2ef726c6cdaaabd4b7f3eb9.ttf:--font-funcs=ot:U+2000:[gid1=0+560]
-fonts/sha1sum/1c2c3fc37b2d4c3cb2ef726c6cdaaabd4b7f3eb9.ttf:--font-funcs=ot:U+2001:[gid1=0+560]
-fonts/sha1sum/1c2c3fc37b2d4c3cb2ef726c6cdaaabd4b7f3eb9.ttf:--font-funcs=ot:U+2002:[gid1=0+560]
-fonts/sha1sum/1c2c3fc37b2d4c3cb2ef726c6cdaaabd4b7f3eb9.ttf:--font-funcs=ot:U+2003:[gid1=0+560]
-fonts/sha1sum/1c2c3fc37b2d4c3cb2ef726c6cdaaabd4b7f3eb9.ttf:--font-funcs=ot:U+2004:[gid1=0+560]
-fonts/sha1sum/1c2c3fc37b2d4c3cb2ef726c6cdaaabd4b7f3eb9.ttf:--font-funcs=ot:U+2005:[gid1=0+560]
-fonts/sha1sum/1c2c3fc37b2d4c3cb2ef726c6cdaaabd4b7f3eb9.ttf:--font-funcs=ot:U+2006:[gid1=0+560]
+fonts/sha1sum/1c2c3fc37b2d4c3cb2ef726c6cdaaabd4b7f3eb9.ttf:--font-funcs=ot:U+2000:[gid1=0+1024]
+fonts/sha1sum/1c2c3fc37b2d4c3cb2ef726c6cdaaabd4b7f3eb9.ttf:--font-funcs=ot:U+2001:[gid1=0+2048]
+fonts/sha1sum/1c2c3fc37b2d4c3cb2ef726c6cdaaabd4b7f3eb9.ttf:--font-funcs=ot:U+2002:[gid1=0+1024]
+fonts/sha1sum/1c2c3fc37b2d4c3cb2ef726c6cdaaabd4b7f3eb9.ttf:--font-funcs=ot:U+2003:[gid1=0+2048]
+fonts/sha1sum/1c2c3fc37b2d4c3cb2ef726c6cdaaabd4b7f3eb9.ttf:--font-funcs=ot:U+2004:[gid1=0+683]
+fonts/sha1sum/1c2c3fc37b2d4c3cb2ef726c6cdaaabd4b7f3eb9.ttf:--font-funcs=ot:U+2005:[gid1=0+512]
+fonts/sha1sum/1c2c3fc37b2d4c3cb2ef726c6cdaaabd4b7f3eb9.ttf:--font-funcs=ot:U+2006:[gid1=0+341]
 fonts/sha1sum/1c2c3fc37b2d4c3cb2ef726c6cdaaabd4b7f3eb9.ttf:--font-funcs=ot:U+2007:[gid1=0+560]
 fonts/sha1sum/1c2c3fc37b2d4c3cb2ef726c6cdaaabd4b7f3eb9.ttf:--font-funcs=ot:U+2008:[gid1=0+560]
-fonts/sha1sum/1c2c3fc37b2d4c3cb2ef726c6cdaaabd4b7f3eb9.ttf:--font-funcs=ot:U+2009:[gid1=0+560]
-fonts/sha1sum/1c2c3fc37b2d4c3cb2ef726c6cdaaabd4b7f3eb9.ttf:--font-funcs=ot:U+200A:[gid1=0+560]
-fonts/sha1sum/1c2c3fc37b2d4c3cb2ef726c6cdaaabd4b7f3eb9.ttf:--font-funcs=ot:U+202F:[gid1=0+560]
-fonts/sha1sum/1c2c3fc37b2d4c3cb2ef726c6cdaaabd4b7f3eb9.ttf:--font-funcs=ot:U+205F:[gid1=0+560]
-fonts/sha1sum/1c2c3fc37b2d4c3cb2ef726c6cdaaabd4b7f3eb9.ttf:--font-funcs=ot:U+3000:[gid1=0+560]
+fonts/sha1sum/1c2c3fc37b2d4c3cb2ef726c6cdaaabd4b7f3eb9.ttf:--font-funcs=ot:U+2009:[gid1=0+410]
+fonts/sha1sum/1c2c3fc37b2d4c3cb2ef726c6cdaaabd4b7f3eb9.ttf:--font-funcs=ot:U+200A:[gid1=0+128]
+fonts/sha1sum/1c2c3fc37b2d4c3cb2ef726c6cdaaabd4b7f3eb9.ttf:--font-funcs=ot:U+202F:[gid1=0+280]
+fonts/sha1sum/1c2c3fc37b2d4c3cb2ef726c6cdaaabd4b7f3eb9.ttf:--font-funcs=ot:U+205F:[gid1=0+455]
+fonts/sha1sum/1c2c3fc37b2d4c3cb2ef726c6cdaaabd4b7f3eb9.ttf:--font-funcs=ot:U+3000:[gid1=0+2048]
commit aa7044de0ceacd71cab19212d266c3a66c03b41e
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Wed Nov 4 16:25:57 2015 -0800

    Generalize flags types

diff --git a/src/hb-buffer-private.hh b/src/hb-buffer-private.hh
index 521214d..8e33fc8 100644
--- a/src/hb-buffer-private.hh
+++ b/src/hb-buffer-private.hh
@@ -38,6 +38,9 @@
 ASSERT_STATIC (sizeof (hb_glyph_info_t) == 20);
 ASSERT_STATIC (sizeof (hb_glyph_info_t) == sizeof (hb_glyph_position_t));
 
+template <> class hb_mark_as_flags_t<hb_buffer_flags_t> {};
+template <> class hb_mark_as_flags_t<hb_buffer_serialize_flags_t> {};
+
 
 /*
  * hb_buffer_t
diff --git a/src/hb-ot-layout-common-private.hh b/src/hb-ot-layout-common-private.hh
index 84a1635..04958a8 100644
--- a/src/hb-ot-layout-common-private.hh
+++ b/src/hb-ot-layout-common-private.hh
@@ -579,6 +579,11 @@ struct LookupFlag : USHORT
   DEFINE_SIZE_STATIC (2);
 };
 
+} /* namespace OT */
+/* This has to be outside the namespace. */
+template <> class hb_mark_as_flags_t<OT::LookupFlag::Flags> {};
+namespace OT {
+
 struct Lookup
 {
   inline unsigned int get_subtable_count (void) const { return subTable.len; }
diff --git a/src/hb-ot-layout-private.hh b/src/hb-ot-layout-private.hh
index 1759520..242d5cc 100644
--- a/src/hb-ot-layout-private.hh
+++ b/src/hb-ot-layout-private.hh
@@ -49,7 +49,7 @@ hb_ot_layout_table_find_feature (hb_face_t    *face,
  * GDEF
  */
 
-typedef enum
+enum hb_ot_layout_glyph_props_flags_t
 {
   /* The following three match LookupFlags::Ignore* numbers. */
   HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH	= 0x02u,
@@ -64,7 +64,8 @@ typedef enum
   HB_OT_LAYOUT_GLYPH_PROPS_PRESERVE     = HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED |
 					  HB_OT_LAYOUT_GLYPH_PROPS_LIGATED |
 					  HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED
-} hb_ot_layout_glyph_class_mask_t;
+};
+template <> class hb_mark_as_flags_t<hb_ot_layout_glyph_props_flags_t> {};
 
 
 /*
@@ -230,12 +231,13 @@ _next_syllable (hb_buffer_t *buffer, unsigned int start)
  * freeing two more bits.
  */
 
-enum {
+enum hb_unicode_props_flags_t {
   UPROPS_MASK_ZWJ       = 0x20u,
   UPROPS_MASK_ZWNJ      = 0x40u,
   UPROPS_MASK_IGNORABLE = 0x80u,
   UPROPS_MASK_GEN_CAT   = 0x1Fu
 };
+template <> class hb_mark_as_flags_t<hb_unicode_props_flags_t> {};
 
 static inline void
 _hb_glyph_info_set_unicode_props (hb_glyph_info_t *info, hb_unicode_funcs_t *unicode)
diff --git a/src/hb-ot-map-private.hh b/src/hb-ot-map-private.hh
index f9538af..1e3ff67 100644
--- a/src/hb-ot-map-private.hh
+++ b/src/hb-ot-map-private.hh
@@ -159,23 +159,9 @@ enum hb_ot_map_feature_flags_t {
   F_MANUAL_ZWJ		= 0x0004u, /* Don't skip over ZWJ when matching. */
   F_GLOBAL_SEARCH	= 0x0008u  /* If feature not found in LangSys, look for it in global feature list and pick one. */
 };
+template <> class hb_mark_as_flags_t<hb_ot_map_feature_flags_t> {};
 /* Macro version for where const is desired. */
 #define F_COMBINE(l,r) (hb_ot_map_feature_flags_t ((unsigned int) (l) | (unsigned int) (r)))
-static inline hb_ot_map_feature_flags_t
-operator | (hb_ot_map_feature_flags_t l, hb_ot_map_feature_flags_t r)
-{ return hb_ot_map_feature_flags_t ((unsigned int) l | (unsigned int) r); }
-static inline hb_ot_map_feature_flags_t
-operator & (hb_ot_map_feature_flags_t l, hb_ot_map_feature_flags_t r)
-{ return hb_ot_map_feature_flags_t ((unsigned int) l & (unsigned int) r); }
-static inline hb_ot_map_feature_flags_t
-operator ~ (hb_ot_map_feature_flags_t r)
-{ return hb_ot_map_feature_flags_t (~(unsigned int) r); }
-static inline hb_ot_map_feature_flags_t&
-operator |= (hb_ot_map_feature_flags_t &l, hb_ot_map_feature_flags_t r)
-{ l = l | r; return l; }
-static inline hb_ot_map_feature_flags_t&
-operator &= (hb_ot_map_feature_flags_t& l, hb_ot_map_feature_flags_t r)
-{ l = l & r; return l; }
 
 
 struct hb_ot_map_builder_t
diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc
index 40332d6..205be0a 100644
--- a/src/hb-ot-shape.cc
+++ b/src/hb-ot-shape.cc
@@ -525,7 +525,7 @@ hb_synthesize_glyph_classes (hb_ot_shape_context_t *c)
   hb_glyph_info_t *info = c->buffer->info;
   for (unsigned int i = 0; i < count; i++)
   {
-    hb_ot_layout_glyph_class_mask_t klass;
+    hb_ot_layout_glyph_props_flags_t klass;
 
     /* Never mark default-ignorables as marks.
      * They won't get in the way of lookups anyway,
diff --git a/src/hb-private.hh b/src/hb-private.hh
index 53e0510..c65a8bf 100644
--- a/src/hb-private.hh
+++ b/src/hb-private.hh
@@ -891,6 +891,20 @@ hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2, T lo3, T hi3)
 }
 
 
+/* Enable bitwise ops on enums marked as flags_t */
+template <class T> class hb_mark_as_flags_t;
+template <class T> static inline T operator | (T l, T r)
+{ hb_mark_as_flags_t<T> unused HB_UNUSED; return T ((unsigned int) l | (unsigned int) r); }
+template <class T> static inline T operator & (T l, T r)
+{ hb_mark_as_flags_t<T> unused HB_UNUSED; return T ((unsigned int) l & (unsigned int) r); }
+template <class T> static inline T operator ~ (T r)
+{ hb_mark_as_flags_t<T> unused HB_UNUSED; return T (~(unsigned int) r); }
+template <class T> static inline T& operator |= (T &l, T r)
+{ hb_mark_as_flags_t<T> unused HB_UNUSED; l = l | r; return l; }
+template <class T> static inline T& operator &= (T& l, T r)
+{ hb_mark_as_flags_t<T> unused HB_UNUSED; l = l & r; return l; }
+
+
 /* Useful for set-operations on small enums.
  * For example, for testing "x ∈ {x1, x2, x3}" use:
  * (FLAG_SAFE(x) & (FLAG(x1) | FLAG(x2) | FLAG(x3)))


More information about the HarfBuzz mailing list