* Google Author(s): Behdad Esfahbod
*/
-#include "hb-private.hh"
+#include "hb.hh"
#include "hb-icu.h"
-#include "hb-unicode-private.hh"
+#include "hb-machinery.hh"
#include <unicode/uchar.h>
#include <unicode/unorm2.h>
#include <unicode/uversion.h>
+/**
+ * SECTION:hb-icu
+ * @title: hb-icu
+ * @short_description: ICU integration
+ * @include: hb-icu.h
+ *
+ * Functions for using HarfBuzz with the ICU library to provide Unicode data.
+ **/
+
+
hb_script_t
hb_icu_script_to_script (UScriptCode script)
{
if (unlikely (script == HB_SCRIPT_INVALID))
return USCRIPT_INVALID_CODE;
- for (unsigned int i = 0; i < USCRIPT_CODE_LIMIT; i++)
+ unsigned int numScriptCode = 1 + u_getIntPropertyMaxValue (UCHAR_SCRIPT);
+ for (unsigned int i = 0; i < numScriptCode; i++)
if (unlikely (hb_icu_script_to_script ((UScriptCode) i) == script))
return (UScriptCode) i;
return (hb_unicode_combining_class_t) u_getCombiningClass (unicode);
}
-static unsigned int
-hb_icu_unicode_eastasian_width (hb_unicode_funcs_t *ufuncs HB_UNUSED,
- hb_codepoint_t unicode,
- void *user_data HB_UNUSED)
-{
- switch (u_getIntPropertyValue(unicode, UCHAR_EAST_ASIAN_WIDTH))
- {
- case U_EA_WIDE:
- case U_EA_FULLWIDTH:
- return 2;
- case U_EA_NEUTRAL:
- case U_EA_AMBIGUOUS:
- case U_EA_HALFWIDTH:
- case U_EA_NARROW:
- return 1;
- }
- return 1;
-}
-
static hb_unicode_general_category_t
hb_icu_unicode_general_category (hb_unicode_funcs_t *ufuncs HB_UNUSED,
hb_codepoint_t unicode,
return hb_icu_script_to_script (scriptCode);
}
-#if U_ICU_VERSION_MAJOR_NUM >= 49
-static const UNormalizer2 *normalizer;
-#endif
-
static hb_bool_t
hb_icu_unicode_compose (hb_unicode_funcs_t *ufuncs HB_UNUSED,
hb_codepoint_t a,
{
#if U_ICU_VERSION_MAJOR_NUM >= 49
{
+ const UNormalizer2 *normalizer = (const UNormalizer2 *) user_data;
UChar32 ret = unorm2_composePair (normalizer, a, b);
if (ret < 0) return false;
*ab = ret;
{
#if U_ICU_VERSION_MAJOR_NUM >= 49
{
+ const UNormalizer2 *normalizer = (const UNormalizer2 *) user_data;
UChar decomposed[4];
int len;
UErrorCode icu_err = U_ZERO_ERROR;
return ret;
}
-static unsigned int
-hb_icu_unicode_decompose_compatibility (hb_unicode_funcs_t *ufuncs HB_UNUSED,
- hb_codepoint_t u,
- hb_codepoint_t *decomposed,
- void *user_data HB_UNUSED)
-{
- UChar utf16[2], normalized[2 * HB_UNICODE_MAX_DECOMPOSITION_LEN + 1];
- unsigned int len;
- int32_t utf32_len;
- hb_bool_t err;
- UErrorCode icu_err;
-
- /* Copy @u into a UTF-16 array to be passed to ICU. */
- len = 0;
- err = false;
- U16_APPEND (utf16, len, ARRAY_LENGTH (utf16), u, err);
- if (err)
- return 0;
-
- /* Normalise the codepoint using NFKD mode. */
- icu_err = U_ZERO_ERROR;
- len = unorm2_normalize (unorm2_getNFKDInstance (&icu_err), utf16, len, normalized, ARRAY_LENGTH (normalized), &icu_err);
- if (U_FAILURE (icu_err))
- return 0;
- /* Convert the decomposed form from UTF-16 to UTF-32. */
- icu_err = U_ZERO_ERROR;
- u_strToUTF32 ((UChar32*) decomposed, HB_UNICODE_MAX_DECOMPOSITION_LEN, &utf32_len, normalized, len, &icu_err);
- if (U_FAILURE (icu_err))
- return 0;
-
- return utf32_len;
-}
-
-
-static hb_unicode_funcs_t *static_icu_funcs = nullptr;
-
-#ifdef HB_USE_ATEXIT
-static
-void free_static_icu_funcs (void)
-{
-retry:
- hb_unicode_funcs_t *icu_funcs = (hb_unicode_funcs_t *) hb_atomic_ptr_get (&static_icu_funcs);
- if (!hb_atomic_ptr_cmpexch (&static_icu_funcs, icu_funcs, nullptr))
- goto retry;
-
- hb_unicode_funcs_destroy (icu_funcs);
-}
+#if HB_USE_ATEXIT
+static void free_static_icu_funcs ();
#endif
-hb_unicode_funcs_t *
-hb_icu_get_unicode_funcs (void)
+static struct hb_icu_unicode_funcs_lazy_loader_t : hb_unicode_funcs_lazy_loader_t<hb_icu_unicode_funcs_lazy_loader_t>
{
-retry:
- hb_unicode_funcs_t *funcs = (hb_unicode_funcs_t *) hb_atomic_ptr_get (&static_icu_funcs);
-
- if (unlikely (!funcs))
+ static hb_unicode_funcs_t *create ()
{
+ void *user_data = nullptr;
#if U_ICU_VERSION_MAJOR_NUM >= 49
- if (!hb_atomic_ptr_get (&normalizer)) {
- UErrorCode icu_err = U_ZERO_ERROR;
- /* We ignore failure in getNFCInstace(). */
- (void) hb_atomic_ptr_cmpexch (&normalizer, nullptr, unorm2_getNFCInstance (&icu_err));
- }
+ UErrorCode icu_err = U_ZERO_ERROR;
+ user_data = (void *) unorm2_getNFCInstance (&icu_err);
+ assert (user_data);
#endif
- funcs = hb_unicode_funcs_create (nullptr);
+ hb_unicode_funcs_t *funcs = hb_unicode_funcs_create (nullptr);
-#define HB_UNICODE_FUNC_IMPLEMENT(name) \
- hb_unicode_funcs_set_##name##_func (funcs, hb_icu_unicode_##name, nullptr, nullptr);
- HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS
-#undef HB_UNICODE_FUNC_IMPLEMENT
+ hb_unicode_funcs_set_combining_class_func (funcs, hb_icu_unicode_combining_class, nullptr, nullptr);
+ hb_unicode_funcs_set_general_category_func (funcs, hb_icu_unicode_general_category, nullptr, nullptr);
+ hb_unicode_funcs_set_mirroring_func (funcs, hb_icu_unicode_mirroring, nullptr, nullptr);
+ hb_unicode_funcs_set_script_func (funcs, hb_icu_unicode_script, nullptr, nullptr);
+ hb_unicode_funcs_set_compose_func (funcs, hb_icu_unicode_compose, user_data, nullptr);
+ hb_unicode_funcs_set_decompose_func (funcs, hb_icu_unicode_decompose, user_data, nullptr);
hb_unicode_funcs_make_immutable (funcs);
- if (!hb_atomic_ptr_cmpexch (&static_icu_funcs, nullptr, funcs)) {
- hb_unicode_funcs_destroy (funcs);
- goto retry;
- }
+#if HB_USE_ATEXIT
+ atexit (free_static_icu_funcs);
+#endif
+
+ return funcs;
+ }
+} static_icu_funcs;
-#ifdef HB_USE_ATEXIT
- atexit (free_static_icu_funcs); /* First person registers atexit() callback. */
+#if HB_USE_ATEXIT
+static
+void free_static_icu_funcs ()
+{
+ static_icu_funcs.free_instance ();
+}
#endif
- };
- return hb_unicode_funcs_reference (funcs);
+hb_unicode_funcs_t *
+hb_icu_get_unicode_funcs ()
+{
+ return static_icu_funcs.get_unconst ();
}