# HG changeset patch # User Michael Goffioul # Date 1377871662 14400 # Node ID 4a348443de9bee9630fa20a4ae94613040eba4c4 # Parent 80bf005cdf8e2e0a6f730e71daded707857e9582 Support multibyte characters in Freetype-based renderer (bug #31596). * bootstrap.conf (gnulib_modules): Add mbrtowc. * libinterp/corefcn/txt-eng-ft.cc (clocale, cwchar): New include. (ft_render::visit(text_element_string)): Decode string using mbrtowc. diff -r 80bf005cdf8e -r 4a348443de9b bootstrap.conf --- a/bootstrap.conf Fri Aug 30 07:19:13 2013 +0100 +++ b/bootstrap.conf Fri Aug 30 10:07:42 2013 -0400 @@ -49,6 +49,7 @@ link lstat malloc-gnu + mbrtowc mkdir mkfifo mkostemp diff -r 80bf005cdf8e -r 4a348443de9b libinterp/corefcn/txt-eng-ft.cc --- a/libinterp/corefcn/txt-eng-ft.cc Fri Aug 30 07:19:13 2013 +0100 +++ b/libinterp/corefcn/txt-eng-ft.cc Fri Aug 30 10:07:42 2013 -0400 @@ -30,6 +30,8 @@ #include #endif +#include +#include #include #include #include @@ -628,18 +630,39 @@ { if (font.is_valid ()) { - std::string str = e.string_value (); FT_UInt glyph_index, previous = 0; - for (size_t i = 0; i < str.length (); i++) + std::string str = e.string_value (); + size_t n = str.length (), curr = 0; + mbstate_t ps = { 0 }; + wchar_t wc; + + while (n > 0) { - glyph_index = process_character (static_cast (str[i]), - previous); + size_t r = gnulib::mbrtowc (&wc, str.data () + curr, n, &ps); + + if (r > 0 + && r != static_cast (-1) + && r != static_cast (-2)) + { + n -= r; + curr += r; - if (str[i] == '\n') - previous = 0; + glyph_index = process_character (wc, previous); + + if (wc == L'\n') + previous = 0; + else + previous = glyph_index; + } else - previous = glyph_index; + { + if (r != 0) + ::warning ("ft_render: failed to decode string `%s' with " + "locale `%s'", str.c_str (), + std::setlocale (LC_CTYPE, NULL)); + break; + } } } }