From 3e8ea9421204b51a819d983ee1d924621259043c Mon Sep 17 00:00:00 2001 From: wm4 Date: Sun, 20 Sep 2015 19:21:37 +0200 Subject: fontselect: make iconv optional again It was needed for UTF16BE -> UTF8 only, which is trivial to implement. --- libass/ass_fontselect.c | 24 ++------------------ libass/ass_utils.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++++ libass/ass_utils.h | 1 + 3 files changed, 61 insertions(+), 22 deletions(-) (limited to 'libass') diff --git a/libass/ass_fontselect.c b/libass/ass_fontselect.c index e75eb1f..b437000 100644 --- a/libass/ass_fontselect.c +++ b/libass/ass_fontselect.c @@ -34,7 +34,6 @@ #include FT_FREETYPE_H #include FT_SFNT_NAMES_H #include FT_TRUETYPE_IDS_H -#include #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]); diff --git a/libass/ass_utils.c b/libass/ass_utils.c index 9c9155b..1614a32 100644 --- a/libass/ass_utils.c +++ b/libass/ass_utils.c @@ -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 diff --git a/libass/ass_utils.h b/libass/ass_utils.h index 8295d4e..8938c30 100644 --- a/libass/ass_utils.h +++ b/libass/ass_utils.h @@ -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); -- cgit v1.2.3