]> granicus.if.org Git - libass/commitdiff
fontselect: make iconv optional again
authorwm4 <wm4@nowhere>
Sun, 20 Sep 2015 17:21:37 +0000 (19:21 +0200)
committerwm4 <wm4@nowhere>
Mon, 21 Sep 2015 19:47:34 +0000 (21:47 +0200)
It was needed for UTF16BE -> UTF8 only, which is trivial to implement.

libass/ass_fontselect.c
libass/ass_utils.c
libass/ass_utils.h

index e75eb1fce9ad3d143f08e21fcb266dd111580cce..b437000c2e96f293fe562106fb5d7679918d805c 100644 (file)
@@ -34,7 +34,6 @@
 #include FT_FREETYPE_H
 #include FT_SFNT_NAMES_H
 #include FT_TRUETYPE_IDS_H
-#include <iconv.h>
 
 #include "ass_utils.h"
 #include "ass.h"
@@ -720,18 +719,11 @@ get_font_info(FT_Library lib, FT_Face face, ASS_FontProviderMetaData *info)
     int slant, weight;
     char *fullnames[MAX_FULLNAME];
     char *families[MAX_FULLNAME];
-    iconv_t utf16to8;
 
     // we're only interested in outlines
     if (!(face->face_flags & FT_FACE_FLAG_SCALABLE))
         return 0;
 
-    // scan font names
-    utf16to8 = iconv_open("UTF-8", "UTF-16BE");
-
-    if (utf16to8 == (iconv_t)-1)
-        goto error;
-
     for (i = 0; i < num_names; i++) {
         FT_SfntName name;
 
@@ -742,15 +734,8 @@ get_font_info(FT_Library lib, FT_Face face, ASS_FontProviderMetaData *info)
                 (name.name_id == TT_NAME_ID_FULL_NAME ||
                  name.name_id == TT_NAME_ID_FONT_FAMILY)) {
             char buf[1024];
-            char *bufptr = buf;
-            size_t inbytes = name.string_len;
-            size_t outbytes = 1024;
-
-            if (iconv(utf16to8, (char**)&name.string, &inbytes, &bufptr,
-                        &outbytes) == (size_t)-1)
-                continue;
-
-            *bufptr = '\0';
+            ass_utf16be_to_utf8(buf, sizeof(buf), (uint8_t *)name.string,
+                                name.string_len);
 
             if (name.name_id == TT_NAME_ID_FULL_NAME) {
                 fullnames[num_fullname] = strdup_trimmed(buf);
@@ -768,8 +753,6 @@ get_font_info(FT_Library lib, FT_Face face, ASS_FontProviderMetaData *info)
         }
 
     }
-    iconv_close(utf16to8);
-    utf16to8 = (iconv_t)-1;
 
     // check if we got a valid family - if not use whatever FreeType gives us
     if (num_family == 0 && face->family_name) {
@@ -810,9 +793,6 @@ get_font_info(FT_Library lib, FT_Face face, ASS_FontProviderMetaData *info)
     return 0;
 
 error:
-    if (utf16to8 != (iconv_t)-1)
-        iconv_close(utf16to8);
-
     for (i = 0; i < num_family; i++)
         free(families[i]);
 
index 9c9155b6e99ebdcc3bd3dfb469d7d6321acd073e..1614a32a44a3fbba801ee3b1597e8149eb710ed4 100644 (file)
@@ -417,6 +417,64 @@ unsigned ass_utf8_put_char(char *dest, uint32_t ch)
     return dest - orig_dest;
 }
 
+/**
+ * \brief Parse UTF-16 and return the code point of the sequence starting at src.
+ * \param src pointer to a pointer to the start of the UTF-16 data
+ *            (will be set to the start of the next code point)
+ * \return the code point
+ */
+static uint32_t ass_read_utf16be(uint8_t **src, size_t bytes)
+{
+    if (bytes < 2)
+        goto too_short;
+
+    uint32_t cp = ((*src)[0] << 8) | (*src)[1];
+    *src += 2;
+    bytes -= 2;
+
+    if (cp >= 0xD800 && cp <= 0xDBFF) {
+        if (bytes < 2)
+            goto too_short;
+
+        uint32_t cp2 = ((*src)[0] << 8) | (*src)[1];
+
+        if (cp2 < 0xDC00 || cp2 > 0xDFFF)
+            return 0xFFFD;
+
+        *src += 2;
+
+        cp = 0x10000 + ((cp - 0xD800) << 10) + (cp2 - 0xDC00);
+    }
+
+    if (cp >= 0xDC00 && cp <= 0xDFFF)
+        return 0xFFFD;
+
+    return cp;
+
+too_short:
+    *src += bytes;
+    return 0xFFFD;
+}
+
+void ass_utf16be_to_utf8(char *dst, size_t dst_size, uint8_t *src, size_t src_size)
+{
+    uint8_t *end = src + src_size;
+
+    if (!dst_size)
+        return;
+
+    while (src < end) {
+        uint32_t cp = ass_read_utf16be(&src, end - src);
+        if (dst_size < 5)
+            break;
+        unsigned s = ass_utf8_put_char(dst, cp);
+        dst += s;
+        dst_size -= s;
+    }
+
+    *dst = '\0';
+}
+
 /**
  * \brief find style by name
  * \param track track
index 8295d4e09017e56fbeeccf0ed7c993f2ea136c1d..8938c304fd5306c56c28b31db8f119bf162ae80a 100644 (file)
@@ -96,6 +96,7 @@ char parse_bool(char *str);
 int parse_ycbcr_matrix(char *str);
 unsigned ass_utf8_get_char(char **str);
 unsigned ass_utf8_put_char(char *dest, uint32_t ch);
+void ass_utf16be_to_utf8(char *dst, size_t dst_size, uint8_t *src, size_t src_size);
 void ass_msg(ASS_Library *priv, int lvl, const char *fmt, ...);
 int lookup_style(ASS_Track *track, char *name);
 ASS_Style *lookup_style_strict(ASS_Track *track, char *name, size_t len);