Shape text using Pango and HarfBuzz; gives us nice ligatures and exotic scripts.
[ccbs] / bigscreen / widestring.cpp
index 2411836..f486aae 100644 (file)
@@ -6,9 +6,25 @@
 #include <pqxx/util>
 #include "widestring.h"
 
-static iconv_t ucs4_iconv;
+static iconv_t ucs4_iconv, ucs4_reverse_iconv;
 static bool iconv_initialized = false;
 
+void ensure_iconv_initialized()
+{
+       if (iconv_initialized) {
+               return;
+       }
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+       ucs4_iconv = iconv_open("ucs-4le", "utf-8");
+       ucs4_reverse_iconv = iconv_open("utf-8", "ucs-4le");
+#else
+       ucs4_iconv = iconv_open("ucs-4be", "utf-8");
+       ucs4_reverse_iconv = iconv_open("utf-8", "ucs-4be");
+#endif
+
+       iconv_initialized = true;
+}
+
 widestring::widestring()
 {
 }
@@ -30,15 +46,7 @@ widestring::widestring(const std::wstring &from)
 
 void widestring::operator= (const char *from)
 {
-       if (!iconv_initialized) {
-#if __BYTE_ORDER == __LITTLE_ENDIAN
-               ucs4_iconv = iconv_open("ucs-4le", "utf-8");
-#else
-               ucs4_iconv = iconv_open("ucs-4be", "utf-8");
-#endif
-
-               iconv_initialized = true;
-       }
+       ensure_iconv_initialized();
        
        unsigned bytes = std::strlen(from);
        char *from_buf = strdup(from);
@@ -66,3 +74,35 @@ void widestring::operator= (const char *from)
        free(from_buf);
        delete[] to_buf;
 }
+
+std::string widestring::to_utf8() const
+{
+       ensure_iconv_initialized();
+
+       wchar_t *from_buf = wcsdup(c_str());
+       size_t out_max_size = size() * 6;
+       char *to_buf = new char[out_max_size];
+
+       char *inptr = reinterpret_cast<char *>(from_buf), *outptr = to_buf;
+
+       size_t in_left = size() * sizeof(wchar_t);
+       size_t out_left = out_max_size;
+
+       size_t ret = iconv(ucs4_reverse_iconv, NULL, NULL, &outptr, &out_left);
+       if (ret == (size_t)(-1)) {
+               throw std::runtime_error("Error in iconv during initialization");
+       }
+
+       ret = iconv(ucs4_reverse_iconv, &inptr, &in_left, &outptr, &out_left);
+       if (ret == (size_t)(-1)) {
+               perror("iconv");
+               throw std::runtime_error("Error in iconv during conversion");
+       }
+
+       std::string utf8(to_buf, outptr);
+
+       free(from_buf);
+       delete[] to_buf;
+
+       return utf8;
+}