diff --git a/src/libsputext/xine_sputext_decoder.c b/src/libsputext/xine_sputext_decoder.c --- a/src/libsputext/xine_sputext_decoder.c +++ b/src/libsputext/xine_sputext_decoder.c @@ -303,6 +303,13 @@ static void update_output_size (sputext_ } } +typedef int (*char_size_func)(const void *); + +static int mbe_identity (const void *buf) +{ + return 1; +} + static int parse_utf8_size(unsigned char *c) { if ( c[0]<0x80 ) @@ -327,6 +334,62 @@ static int parse_utf8_size(unsigned char return 1; } +static int mbe_euc_size (const void *buf) +{ + const uint8_t *c = buf; + if (c[0] <= 0x80 || c[0] == 0xFF) + return 1; + if ((c[1] & 0xDF) >= 0x40 && (c[1] & 0xDF) <= 0x5A) + return 2; + if (c[1] >= 0x81 && c[1] <= 0xFE) + return 2; + return 1; +} + +static char_size_func is_multibyte_encoding (const char *enc) +{ + /* CJK charset strings defined in iconvdata/gconv-modules of glibc */ + static const struct { + char name[16]; + char_size_func char_size; + } mb_encodings[] = { + { "UTF-8", parse_utf8_size }, + { "SJIS", NULL }, + { "CP932", NULL }, + { "EUC-KR", mbe_euc_size }, + { "UHC", NULL }, + { "JOHAB", NULL }, + { "BIG5", NULL }, + { "BIG5HKSCS", NULL }, + { "EUC-JP-MS", NULL }, + { "EUC-JP", NULL }, + { "EUC-CN", NULL }, + { "GBBIG5", NULL }, + { "GBK", NULL }, + { "GBGBK", NULL }, + { "EUC-TW", NULL }, + { "ISO-2022-JP", NULL }, + { "ISO-2022-JP-2", NULL }, + { "ISO-2022-JP-3", NULL }, + { "ISO-2022-KR", NULL }, + { "ISO-2022-CN", NULL }, + { "ISO-2022-CN-EXT", NULL }, + { "GB18030", NULL }, + { "EUC-JISX0213", NULL }, + { "SHIFT_JISX0213", NULL }, + }; + + int pstr; + + /* return 1 if encoding string is one of the CJK(Chinese,Jananese,Korean) + * character set strings. */ + for (pstr = 0; pstr < sizeof (mb_encodings) / sizeof (mb_encodings[0]); pstr++) + if (strcasecmp (enc, mb_encodings[pstr].name) == 0) + return mb_encodings[pstr].char_size ? : mbe_identity; + + return NULL; +} + static int ogm_render_line_internal(sputext_decoder_t *this, int x, int y, const char *text, int render) { int i = 0, w, value; @@ -334,7 +397,8 @@ static int ogm_render_line_internal(sput char letter[5]={0, 0, 0, 0, 0}; const char *encoding = this->buf_encoding ? this->buf_encoding : this->class->src_encoding; - int shift, isutf8 = !strcmp(encoding, "utf-8"); + char_size_func char_size = is_multibyte_encoding (encoding); + int shift; size_t length = strlen (text); while (i <= length) { @@ -403,7 +467,7 @@ static int ogm_render_line_internal(sput } } - shift = isutf8 ? parse_utf8_size (&text[i]) : 1; + shift = char_size ? char_size (text + i) : 1; memcpy(letter,&text[i],shift); letter[shift]=0; @@ -506,45 +570,6 @@ static void read_ssa_tag(sputext_decoder (*sub_x), (*sub_y), (*max_width), (*alignment)); } -static int is_cjk_encoding(const char *enc) { - /* CJK charset strings defined in iconvdata/gconv-modules of glibc */ - static const char cjk_encoding_strings[][16] = { - "SJIS", - "CP932", - "EUC-KR", - "UHC", - "JOHAB", - "BIG5", - "BIG5HKSCS", - "EUC-JP-MS", - "EUC-JP", - "EUC-CN", - "GBBIG5", - "GBK", - "GBGBK", - "EUC-TW", - "ISO-2022-JP", - "ISO-2022-JP-2", - "ISO-2022-JP-3", - "ISO-2022-KR", - "ISO-2022-CN", - "ISO-2022-CN-EXT", - "GB18030", - "EUC-JISX0213", - "SHIFT_JISX0213", - }; - - int pstr; - - /* return 1 if encoding string is one of the CJK(Chinese,Jananese,Korean) - * character set strings. */ - for (pstr = 0; pstr < sizeof (cjk_encoding_strings) / sizeof (cjk_encoding_strings[0]); pstr++) - if (strcasecmp (enc, cjk_encoding_strings[pstr]) == 0) - return 1; - - return 0; -} - static void draw_subtitle(sputext_decoder_t *this, int64_t sub_start, int64_t sub_end ) { int line, y; @@ -552,6 +577,7 @@ static void draw_subtitle(sputext_decode char *font; const char *encoding = (this->buf_encoding)?this->buf_encoding: this->class->src_encoding; + int unknown_multibyte = (is_multibyte_encoding (encoding) == mbe_identity); int sub_x, sub_y, max_width; int alignment; int rebuild_all; @@ -760,7 +786,7 @@ static void draw_subtitle(sputext_decode } } - if( is_cjk_encoding(encoding) ) { + if (unknown_multibyte) { this->renderer->render_text (this->osd, x, y + line * this->line_height, this->text[line], OSD_TEXT1); } else {