Move ZWJ/ZWNJ bits to top byte of unicode_props()
authorBehdad Esfahbod <behdad@behdad.org>
Tue, 26 Apr 2016 23:02:04 +0000 (16:02 -0700)
committerBehdad Esfahbod <behdad@behdad.org>
Tue, 26 Apr 2016 23:15:22 +0000 (16:15 -0700)
To make room to remember Mongolian Free Variation Selectors.
Part of fixing https://github.com/behdad/harfbuzz/issues/234

src/hb-ot-layout-private.hh

index b5c670f..22faa48 100644 (file)
@@ -218,23 +218,22 @@ _next_syllable (hb_buffer_t *buffer, unsigned int start)
  * - General_Category: 5 bits.
  * - A bit each for:
  *   * Is it Default_Ignorable(); we have a modified Default_Ignorable().
- *   * Is it U+200D ZWJ?
- *   * Is it U+200C ZWNJ?
+ *   * Two free bits right now.
  *
  * The high-byte has different meanings, switched by the Gen-Cat:
  * - For Mn,Mc,Me: the modified Combining_Class.
+ * - For Cf: whether it's ZWJ, ZWNJ, or something else.
  * - For Ws: index of which space character this is, if space fallback
  *   is needed, ie. we don't set this by default, only if asked to.
- *
- * If needed, we can use the ZWJ/ZWNJ to use the high byte as well,
- * freeing two more bits.
  */
 
 enum hb_unicode_props_flags_t {
-  UPROPS_MASK_ZWJ       = 0x20u,
-  UPROPS_MASK_ZWNJ      = 0x40u,
-  UPROPS_MASK_IGNORABLE = 0x80u,
-  UPROPS_MASK_GEN_CAT   = 0x1Fu
+  UPROPS_MASK_GEN_CAT  = 0x001Fu,
+  UPROPS_MASK_IGNORABLE        = 0x0020u,
+
+  /* If GEN_CAT=FORMAT, top byte masks: */
+  UPROPS_MASK_Cf_ZWJ   = 0x0100u,
+  UPROPS_MASK_Cf_ZWNJ  = 0x0200u
 };
 HB_MARK_AS_FLAG_T (hb_unicode_props_flags_t);
 
@@ -253,8 +252,8 @@ _hb_glyph_info_set_unicode_props (hb_glyph_info_t *info, hb_buffer_t *buffer)
     {
       buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_DEFAULT_IGNORABLES;
       props |=  UPROPS_MASK_IGNORABLE;
-      if (u == 0x200Cu) props |= UPROPS_MASK_ZWNJ;
-      if (u == 0x200Du) props |= UPROPS_MASK_ZWJ;
+      if (u == 0x200Cu) props |= UPROPS_MASK_Cf_ZWNJ;
+      if (u == 0x200Du) props |= UPROPS_MASK_Cf_ZWJ;
     }
     else if (unlikely (HB_UNICODE_GENERAL_CATEGORY_IS_NON_ENCLOSING_MARK_OR_MODIFIER_SYMBOL (gen_cat)))
     {
@@ -353,28 +352,33 @@ _hb_glyph_info_is_default_ignorable (const hb_glyph_info_t *info)
   return (info->unicode_props() & UPROPS_MASK_IGNORABLE) && !_hb_glyph_info_ligated (info);
 }
 
+static inline bool
+_hb_glyph_info_is_unicode_format (const hb_glyph_info_t *info)
+{
+  return _hb_glyph_info_get_general_category (info) ==
+        HB_UNICODE_GENERAL_CATEGORY_FORMAT;
+}
 static inline hb_bool_t
 _hb_glyph_info_is_zwnj (const hb_glyph_info_t *info)
 {
-  return !!(info->unicode_props() & UPROPS_MASK_ZWNJ);
+  return _hb_glyph_info_is_unicode_format (info) && (info->unicode_props() & UPROPS_MASK_Cf_ZWNJ);
 }
-
 static inline hb_bool_t
 _hb_glyph_info_is_zwj (const hb_glyph_info_t *info)
 {
-  return !!(info->unicode_props() & UPROPS_MASK_ZWJ);
+  return _hb_glyph_info_is_unicode_format (info) && (info->unicode_props() & UPROPS_MASK_Cf_ZWJ);
 }
-
 static inline hb_bool_t
 _hb_glyph_info_is_joiner (const hb_glyph_info_t *info)
 {
-  return !!(info->unicode_props() & (UPROPS_MASK_ZWNJ | UPROPS_MASK_ZWJ));
+  return _hb_glyph_info_is_unicode_format (info) && (info->unicode_props() & (UPROPS_MASK_Cf_ZWNJ|UPROPS_MASK_Cf_ZWJ));
 }
-
 static inline void
 _hb_glyph_info_flip_joiners (hb_glyph_info_t *info)
 {
-  info->unicode_props() ^= UPROPS_MASK_ZWNJ | UPROPS_MASK_ZWJ;
+  if (!_hb_glyph_info_is_unicode_format (info))
+    return;
+  info->unicode_props() ^= UPROPS_MASK_Cf_ZWNJ | UPROPS_MASK_Cf_ZWJ;
 }
 
 /* lig_props: aka lig_id / lig_comp