changeset 17352:4a348443de9b

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.
author Michael Goffioul <michael.goffioul@gmail.com>
date Fri, 30 Aug 2013 10:07:42 -0400
parents 80bf005cdf8e
children de4cf28c7e11
files bootstrap.conf libinterp/corefcn/txt-eng-ft.cc
diffstat 2 files changed, 31 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- 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
--- 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 <fontconfig/fontconfig.h>
 #endif
 
+#include <clocale>
+#include <cwchar>
 #include <iostream>
 #include <map>
 #include <utility>
@@ -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<unsigned char> (str[i]),
-                                           previous);
+          size_t r = gnulib::mbrtowc (&wc, str.data () + curr, n, &ps);
+
+          if (r > 0
+              && r != static_cast<size_t> (-1)
+              && r != static_cast<size_t> (-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;
+            }
         }
     }
 }