Upgrade to latest harfbuzz
[framework/uifw/harfbuzz.git] / src / hb-glib.cc
index 109b9ba..6b655dd 100644 (file)
 
 #include "hb-unicode-private.hh"
 
-#include <glib.h>
-
-HB_BEGIN_DECLS
 
+#if !GLIB_CHECK_VERSION(2,29,14)
 static const hb_script_t
 glib_script_to_script[] =
 {
@@ -146,12 +144,25 @@ glib_script_to_script[] =
   /* Unicode-6.0 additions */
   HB_SCRIPT_BATAK,
   HB_SCRIPT_BRAHMI,
-  HB_SCRIPT_MANDAIC
+  HB_SCRIPT_MANDAIC,
+
+  /* Unicode-6.1 additions */
+  HB_SCRIPT_CHAKMA,
+  HB_SCRIPT_MEROITIC_CURSIVE,
+  HB_SCRIPT_MEROITIC_HIEROGLYPHS,
+  HB_SCRIPT_MIAO,
+  HB_SCRIPT_SHARADA,
+  HB_SCRIPT_SORA_SOMPENG,
+  HB_SCRIPT_TAKRI
 };
+#endif
 
 hb_script_t
 hb_glib_script_to_script (GUnicodeScript script)
 {
+#if GLIB_CHECK_VERSION(2,29,14)
+  return (hb_script_t) g_unicode_script_to_iso15924 (script);
+#else
   if (likely ((unsigned int) script < ARRAY_LENGTH (glib_script_to_script)))
     return glib_script_to_script[script];
 
@@ -159,11 +170,15 @@ hb_glib_script_to_script (GUnicodeScript script)
     return HB_SCRIPT_INVALID;
 
   return HB_SCRIPT_UNKNOWN;
+#endif
 }
 
 GUnicodeScript
 hb_glib_script_from_script (hb_script_t script)
 {
+#if GLIB_CHECK_VERSION(2,29,14)
+  return g_unicode_script_from_iso15924 (script);
+#else
   unsigned int count = ARRAY_LENGTH (glib_script_to_script);
   for (unsigned int i = 0; i < count; i++)
     if (glib_script_to_script[i] == script)
@@ -173,30 +188,31 @@ hb_glib_script_from_script (hb_script_t script)
     return G_UNICODE_SCRIPT_INVALID_CODE;
 
   return G_UNICODE_SCRIPT_UNKNOWN;
+#endif
 }
 
 
 static unsigned int
-hb_glib_get_combining_class (hb_unicode_funcs_t *ufuncs HB_UNUSED,
-                             hb_codepoint_t      unicode,
-                             void               *user_data HB_UNUSED)
+hb_glib_unicode_combining_class (hb_unicode_funcs_t *ufuncs HB_UNUSED,
+                                hb_codepoint_t      unicode,
+                                void               *user_data HB_UNUSED)
 
 {
   return g_unichar_combining_class (unicode);
 }
 
 static unsigned int
-hb_glib_get_eastasian_width (hb_unicode_funcs_t *ufuncs HB_UNUSED,
-                             hb_codepoint_t      unicode,
-                             void               *user_data HB_UNUSED)
+hb_glib_unicode_eastasian_width (hb_unicode_funcs_t *ufuncs HB_UNUSED,
+                                hb_codepoint_t      unicode,
+                                void               *user_data HB_UNUSED)
 {
   return g_unichar_iswide (unicode) ? 2 : 1;
 }
 
 static hb_unicode_general_category_t
-hb_glib_get_general_category (hb_unicode_funcs_t *ufuncs HB_UNUSED,
-                              hb_codepoint_t      unicode,
-                              void               *user_data HB_UNUSED)
+hb_glib_unicode_general_category (hb_unicode_funcs_t *ufuncs HB_UNUSED,
+                                 hb_codepoint_t      unicode,
+                                 void               *user_data HB_UNUSED)
 
 {
   /* hb_unicode_general_category_t and GUnicodeType are identical */
@@ -204,42 +220,139 @@ hb_glib_get_general_category (hb_unicode_funcs_t *ufuncs HB_UNUSED,
 }
 
 static hb_codepoint_t
-hb_glib_get_mirroring (hb_unicode_funcs_t *ufuncs HB_UNUSED,
-                       hb_codepoint_t      unicode,
-                       void               *user_data HB_UNUSED)
+hb_glib_unicode_mirroring (hb_unicode_funcs_t *ufuncs HB_UNUSED,
+                          hb_codepoint_t      unicode,
+                          void               *user_data HB_UNUSED)
 {
   g_unichar_get_mirror_char (unicode, &unicode);
   return unicode;
 }
 
 static hb_script_t
-hb_glib_get_script (hb_unicode_funcs_t *ufuncs HB_UNUSED,
-                    hb_codepoint_t      unicode,
-                    void               *user_data HB_UNUSED)
+hb_glib_unicode_script (hb_unicode_funcs_t *ufuncs HB_UNUSED,
+                       hb_codepoint_t      unicode,
+                       void               *user_data HB_UNUSED)
 {
   return hb_glib_script_to_script (g_unichar_get_script (unicode));
 }
 
-extern HB_INTERNAL hb_unicode_funcs_t _hb_unicode_funcs_glib;
-hb_unicode_funcs_t _hb_glib_unicode_funcs = {
+static hb_bool_t
+hb_glib_unicode_compose (hb_unicode_funcs_t *ufuncs HB_UNUSED,
+                        hb_codepoint_t      a,
+                        hb_codepoint_t      b,
+                        hb_codepoint_t     *ab,
+                        void               *user_data HB_UNUSED)
+{
+#if GLIB_CHECK_VERSION(2,29,12)
+  return g_unichar_compose (a, b, ab);
+#endif
+
+  /* We don't ifdef-out the fallback code such that compiler always
+   * sees it and makes sure it's compilable. */
+
+  if (!a || !b)
+    return false;
+
+  gchar utf8[12];
+  gchar *normalized;
+  gint len;
+  hb_bool_t ret;
+
+  len = g_unichar_to_utf8 (a, utf8);
+  len += g_unichar_to_utf8 (b, utf8 + len);
+  normalized = g_utf8_normalize (utf8, len, G_NORMALIZE_NFC);
+  len = g_utf8_strlen (normalized, -1);
+  if (unlikely (!len))
+    return false;
+
+  if (len == 1) {
+    *ab = g_utf8_get_char (normalized);
+    ret = true;
+  } else {
+    ret = false;
+  }
+
+  g_free (normalized);
+  return ret;
+}
+
+static hb_bool_t
+hb_glib_unicode_decompose (hb_unicode_funcs_t *ufuncs HB_UNUSED,
+                          hb_codepoint_t      ab,
+                          hb_codepoint_t     *a,
+                          hb_codepoint_t     *b,
+                          void               *user_data HB_UNUSED)
+{
+#if GLIB_CHECK_VERSION(2,29,12)
+  return g_unichar_decompose (ab, a, b);
+#endif
+
+  /* We don't ifdef-out the fallback code such that compiler always
+   * sees it and makes sure it's compilable. */
+
+  gchar utf8[6];
+  gchar *normalized;
+  gint len;
+  hb_bool_t ret;
+
+  len = g_unichar_to_utf8 (ab, utf8);
+  normalized = g_utf8_normalize (utf8, len, G_NORMALIZE_NFD);
+  len = g_utf8_strlen (normalized, -1);
+  if (unlikely (!len))
+    return false;
+
+  if (len == 1) {
+    *a = g_utf8_get_char (normalized);
+    *b = 0;
+    ret = *a != ab;
+  } else if (len == 2) {
+    *a = g_utf8_get_char (normalized);
+    *b = g_utf8_get_char (g_utf8_next_char (normalized));
+    /* Here's the ugly part: if ab decomposes to a single character and
+     * that character decomposes again, we have to detect that and undo
+     * the second part :-(. */
+    gchar *recomposed = g_utf8_normalize (normalized, -1, G_NORMALIZE_NFC);
+    hb_codepoint_t c = g_utf8_get_char (recomposed);
+    if (c != ab && c != *a) {
+      *a = c;
+      *b = 0;
+    }
+    g_free (recomposed);
+    ret = true;
+  } else {
+    /* If decomposed to more than two characters, take the last one,
+     * and recompose the rest to get the first component. */
+    gchar *end = g_utf8_offset_to_pointer (normalized, len - 1);
+    gchar *recomposed;
+    *b = g_utf8_get_char (end);
+    recomposed = g_utf8_normalize (normalized, end - normalized, G_NORMALIZE_NFC);
+    /* We expect that recomposed has exactly one character now. */
+    *a = g_utf8_get_char (recomposed);
+    g_free (recomposed);
+    ret = true;
+  }
+
+  g_free (normalized);
+  return ret;
+}
+
+
+extern HB_INTERNAL const hb_unicode_funcs_t _hb_glib_unicode_funcs;
+const hb_unicode_funcs_t _hb_glib_unicode_funcs = {
   HB_OBJECT_HEADER_STATIC,
 
   NULL, /* parent */
-  TRUE, /* immutable */
+  true, /* immutable */
   {
-    hb_glib_get_combining_class,
-    hb_glib_get_eastasian_width,
-    hb_glib_get_general_category,
-    hb_glib_get_mirroring,
-    hb_glib_get_script
+#define HB_UNICODE_FUNC_IMPLEMENT(name) hb_glib_unicode_##name,
+    HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS
+#undef HB_UNICODE_FUNC_IMPLEMENT
   }
 };
 
 hb_unicode_funcs_t *
 hb_glib_get_unicode_funcs (void)
 {
-  return &_hb_glib_unicode_funcs;
+  return const_cast<hb_unicode_funcs_t *> (&_hb_glib_unicode_funcs);
 }
 
-
-HB_END_DECLS