diff options
Diffstat (limited to 'libass/ass_utils.c')
-rw-r--r-- | libass/ass_utils.c | 236 |
1 files changed, 154 insertions, 82 deletions
diff --git a/libass/ass_utils.c b/libass/ass_utils.c index 9a89e8afae..59fdbdfb94 100644 --- a/libass/ass_utils.c +++ b/libass/ass_utils.c @@ -1,5 +1,3 @@ -// -*- c-basic-offset: 8; indent-tabs-mode: t -*- -// vim:ts=8:sw=8:noet:ai: /* * Copyright (C) 2006 Evgeniy Stepanov <eugeni.stepanov@gmail.com> * @@ -23,113 +21,187 @@ #include "config.h" #include <stdlib.h> +#include <stdio.h> #include <inttypes.h> #include <ft2build.h> #include FT_GLYPH_H -#include "mputils.h" +#include "ass_library.h" +#include "ass.h" #include "ass_utils.h" -int mystrtoi(char** p, int* res) +int mystrtoi(char **p, int *res) { - // NOTE: base argument is ignored, but not used in libass anyway - double temp_res; - char* start = *p; - temp_res = strtod(*p, p); - *res = (int) (temp_res + 0.5); - if (*p != start) return 1; - else return 0; + double temp_res; + char *start = *p; + temp_res = ass_strtod(*p, p); + *res = (int) (temp_res + (temp_res > 0 ? 0.5 : -0.5)); + if (*p != start) + return 1; + else + return 0; } -int mystrtoll(char** p, long long* res) +int mystrtoll(char **p, long long *res) { - double temp_res; - char* start = *p; - temp_res = strtod(*p, p); - *res = (long long) (temp_res + 0.5); - if (*p != start) return 1; - else return 0; + double temp_res; + char *start = *p; + temp_res = ass_strtod(*p, p); + *res = (int) (temp_res + (temp_res > 0 ? 0.5 : -0.5)); + if (*p != start) + return 1; + else + return 0; } -int mystrtou32(char** p, int base, uint32_t* res) +int mystrtou32(char **p, int base, uint32_t *res) { - char* start = *p; - *res = strtoll(*p, p, base); - if (*p != start) return 1; - else return 0; + char *start = *p; + *res = strtoll(*p, p, base); + if (*p != start) + return 1; + else + return 0; } -int mystrtod(char** p, double* res) +int mystrtod(char **p, double *res) { - char* start = *p; - *res = strtod(*p, p); - if (*p != start) return 1; - else return 0; + char *start = *p; + *res = ass_strtod(*p, p); + if (*p != start) + return 1; + else + return 0; } -int strtocolor(char** q, uint32_t* res) +int strtocolor(ASS_Library *library, char **q, uint32_t *res, int hex) { - uint32_t color = 0; - int result; - char* p = *q; - - if (*p == '&') ++p; - else mp_msg(MSGT_ASS, MSGL_DBG2, "suspicious color format: \"%s\"\n", p); - - if (*p == 'H' || *p == 'h') { - ++p; - result = mystrtou32(&p, 16, &color); - } else { - result = mystrtou32(&p, 0, &color); - } - - { - unsigned char* tmp = (unsigned char*)(&color); - unsigned char b; - b = tmp[0]; tmp[0] = tmp[3]; tmp[3] = b; - b = tmp[1]; tmp[1] = tmp[2]; tmp[2] = b; - } - if (*p == '&') ++p; - *q = p; - - *res = color; - return result; + uint32_t color = 0; + int result; + char *p = *q; + int base = hex ? 16 : 10; + + if (*p == '&') + ++p; + else + ass_msg(library, MSGL_DBG2, "suspicious color format: \"%s\"\n", p); + + if (*p == 'H' || *p == 'h') { + ++p; + result = mystrtou32(&p, 16, &color); + } else { + result = mystrtou32(&p, base, &color); + } + + { + unsigned char *tmp = (unsigned char *) (&color); + unsigned char b; + b = tmp[0]; + tmp[0] = tmp[3]; + tmp[3] = b; + b = tmp[1]; + tmp[1] = tmp[2]; + tmp[2] = b; + } + if (*p == '&') + ++p; + *q = p; + + *res = color; + return result; } // Return a boolean value for a string -char parse_bool(char* str) { - while (*str == ' ' || *str == '\t') - str++; - if (!strncasecmp(str, "yes", 3)) - return 1; - else if (strtol(str, NULL, 10) > 0) - return 1; - return 0; +char parse_bool(char *str) +{ + while (*str == ' ' || *str == '\t') + str++; + if (!strncasecmp(str, "yes", 3)) + return 1; + else if (strtol(str, NULL, 10) > 0) + return 1; + return 0; } -#if 0 -static void sprint_tag(uint32_t tag, char* dst) +void ass_msg(ASS_Library *priv, int lvl, char *fmt, ...) { - dst[0] = (tag >> 24) & 0xFF; - dst[1] = (tag >> 16) & 0xFF; - dst[2] = (tag >> 8) & 0xFF; - dst[3] = tag & 0xFF; - dst[4] = 0; + va_list va; + va_start(va, fmt); + priv->msg_callback(lvl, fmt, va, priv->msg_callback_data); + va_end(va); } -void dump_glyph(FT_Glyph g) +unsigned ass_utf8_get_char(char **str) { - char tag[5]; - int i; - FT_OutlineGlyph og = (FT_OutlineGlyph)g; - FT_Outline* o = &(og->outline); - sprint_tag(g->format, tag); - printf("glyph: %p \n", g); - printf("format: %s \n", tag); - printf("outline: %p \n", o); - printf("contours: %d, points: %d, points ptr: %p \n", o->n_contours, o->n_points, o->points); - for (i = 0; i < o->n_points; ++i) { - printf(" point %f, %f \n", d6_to_double(o->points[i].x), d6_to_double(o->points[i].y)); - } + uint8_t *strp = (uint8_t *) * str; + unsigned c = *strp++; + unsigned mask = 0x80; + int len = -1; + while (c & mask) { + mask >>= 1; + len++; + } + if (len <= 0 || len > 4) + goto no_utf8; + c &= mask - 1; + while ((*strp & 0xc0) == 0x80) { + if (len-- <= 0) + goto no_utf8; + c = (c << 6) | (*strp++ & 0x3f); + } + if (len) + goto no_utf8; + *str = (char *) strp; + return c; + + no_utf8: + strp = (uint8_t *) * str; + c = *strp++; + *str = (char *) strp; + return c; +} + +#ifdef CONFIG_ENCA +void *ass_guess_buffer_cp(ASS_Library *library, unsigned char *buffer, + int buflen, char *preferred_language, + char *fallback) +{ + const char **languages; + size_t langcnt; + EncaAnalyser analyser; + EncaEncoding encoding; + char *detected_sub_cp = NULL; + int i; + + languages = enca_get_languages(&langcnt); + ass_msg(library, MSGL_V, "ENCA supported languages"); + for (i = 0; i < langcnt; i++) { + ass_msg(library, MSGL_V, "lang %s", languages[i]); + } + + for (i = 0; i < langcnt; i++) { + const char *tmp; + + if (strcasecmp(languages[i], preferred_language) != 0) + continue; + analyser = enca_analyser_alloc(languages[i]); + encoding = enca_analyse_const(analyser, buffer, buflen); + tmp = enca_charset_name(encoding.charset, ENCA_NAME_STYLE_ICONV); + if (tmp && encoding.charset != ENCA_CS_UNKNOWN) { + detected_sub_cp = strdup(tmp); + ass_msg(library, MSGL_INFO, "ENCA detected charset: %s", tmp); + } + enca_analyser_free(analyser); + } + + free(languages); + + if (!detected_sub_cp) { + detected_sub_cp = strdup(fallback); + ass_msg(library, MSGL_INFO, + "ENCA detection failed: fallback to %s", fallback); + } + + return detected_sub_cp; } #endif |