diff --git a/configure.ac b/configure.ac index 605cfbe7d..5414ea12f 100644 --- a/configure.ac +++ b/configure.ac @@ -68,8 +68,8 @@ GTK_DOC_CHECK([1.15],[--flavour no-tmpl]) ]) # Functions and headers -AC_CHECK_FUNCS(atexit mprotect sysconf getpagesize mmap isatty) -AC_CHECK_HEADERS(unistd.h sys/mman.h stdbool.h) +AC_CHECK_FUNCS(atexit mprotect sysconf getpagesize mmap isatty newlocale uselocale) +AC_CHECK_HEADERS(unistd.h sys/mman.h stdbool.h xlocale.h) # Compiler flags AC_CANONICAL_HOST diff --git a/meson.build b/meson.build index 5dd936ced..c88924006 100644 --- a/meson.build +++ b/meson.build @@ -61,6 +61,7 @@ check_headers = [ ['unistd.h'], ['sys/mman.h'], ['stdbool.h'], + ['xlocale.h'], ] check_funcs = [ @@ -70,6 +71,8 @@ check_funcs = [ ['getpagesize'], ['mmap'], ['isatty'], + ['uselocale'], + ['newlocale'], ] m_dep = cpp.find_library('m', required: false) diff --git a/src/hb-common.cc b/src/hb-common.cc index 26c8ad0f4..ea8ca2a24 100644 --- a/src/hb-common.cc +++ b/src/hb-common.cc @@ -31,6 +31,10 @@ #include +#ifdef HAVE_XLOCALE_H +#include // Needed on BSD/OS X for uselocale +#endif + #ifdef HB_NO_SETLOCALE #define setlocale(Category, Locale) "C" #endif @@ -122,7 +126,7 @@ hb_tag_from_string (const char *str, int len) * @tag: #hb_tag_t to convert * @buf: (out caller-allocates) (array fixed-size=4) (element-type uint8_t): Converted string * - * Converts an #hb_tag_t to a string and returns it in @buf. + * Converts an #hb_tag_t to a string and returns it in @buf. * Strings will be four characters long. * * Since: 0.9.5 @@ -151,13 +155,13 @@ const char direction_strings[][4] = { * @str: (array length=len) (element-type uint8_t): String to convert * @len: Length of @str, or -1 if it is %NULL-terminated * - * Converts a string to an #hb_direction_t. + * Converts a string to an #hb_direction_t. * * Matching is loose and applies only to the first letter. For * examples, "LTR" and "left-to-right" will both return #HB_DIRECTION_LTR. * * Unmatched strings will return #HB_DIRECTION_INVALID. - * + * * Return value: The #hb_direction_t matching @str * * Since: 0.9.2 @@ -1039,6 +1043,56 @@ hb_variation_from_string (const char *str, int len, return false; } +#if !defined(HARFBUZZ_NO_SETLOCALE) && defined(HAVE_NEWLOCALE) && defined(HAVE_USELOCALE) + +#ifdef WIN32 +using locale_t = _locale_t; +#endif + +static inline void free_static_C_locale (); + +static struct hb_C_locale_lazy_loader_t : hb_lazy_loader_t, + hb_C_locale_lazy_loader_t> +{ + static locale_t create () + { + locale_t l = newlocale (LC_ALL_MASK, "C", NULL); + if (!l) + return l; + + hb_atexit (free_static_C_locale); + + return l; + } + static void destroy (locale_t l) + { + freelocale (l); + } + static locale_t get_null () + { + return (locale_t) 0; + } +} static_C_locale; + +static inline +void free_static_C_locale () +{ + static_C_locale.free_instance (); +} + +static locale_t +get_C_locale () +{ + return static_C_locale.get_unconst (); +} + +#else +#ifdef WIN32 +#define locale_t void * +#endif +#define uselocale(Locale) ((locale_t) 0) +#endif + /** * hb_variation_to_string: * @variation: an #hb_variation_t to convert @@ -1064,7 +1118,11 @@ hb_variation_to_string (hb_variation_t *variation, while (len && s[len - 1] == ' ') len--; s[len++] = '='; + + locale_t oldlocale HB_UNUSED; + oldlocale = uselocale (get_C_locale ()); len += hb_max (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%g", (double) variation->value)); + (void) uselocale (oldlocale); assert (len < ARRAY_LENGTH (s)); len = hb_min (len, size - 1);