/*
- * Copyright (C) 2009 Red Hat, Inc.
+ * Copyright © 2009 Red Hat, Inc.
+ * Copyright © 2011 Google, Inc.
*
* This is part of HarfBuzz, a text shaping library.
*
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*
* Red Hat Author(s): Behdad Esfahbod
+ * Google Author(s): Behdad Esfahbod
*/
#include "hb-private.hh"
#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[] =
{
/* 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];
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)
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_codepoint_t unicode,
- void *user_data)
+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_codepoint_t unicode,
- void *user_data)
+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_codepoint_t unicode,
- void *user_data)
+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 */
}
static hb_codepoint_t
-hb_glib_get_mirroring (hb_unicode_funcs_t *ufuncs,
- hb_codepoint_t unicode,
- void *user_data)
+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_codepoint_t unicode,
- void *user_data)
+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));
}
-static hb_unicode_funcs_t glib_ufuncs = {
- HB_REFERENCE_COUNT_INVALID, /* ref_count */
+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 &glib_ufuncs;
+ return const_cast<hb_unicode_funcs_t *> (&_hb_glib_unicode_funcs);
}
-
-HB_END_DECLS