]> granicus.if.org Git - libass/blob - libass/ass_utils.c
Convert to high-level rasterizer parts to outlines
[libass] / libass / ass_utils.c
1 /*
2  * Copyright (C) 2006 Evgeniy Stepanov <eugeni.stepanov@gmail.com>
3  *
4  * This file is part of libass.
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18
19 #include "config.h"
20
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include <inttypes.h>
24 #include <ft2build.h>
25 #include FT_GLYPH_H
26 #include <strings.h>
27
28 #include "ass_library.h"
29 #include "ass.h"
30 #include "ass_utils.h"
31
32 int mystrtoi(char **p, int *res)
33 {
34     double temp_res;
35     char *start = *p;
36     temp_res = ass_strtod(*p, p);
37     *res = (int) (temp_res + (temp_res > 0 ? 0.5 : -0.5));
38     if (*p != start)
39         return 1;
40     else
41         return 0;
42 }
43
44 int mystrtoll(char **p, long long *res)
45 {
46     double temp_res;
47     char *start = *p;
48     temp_res = ass_strtod(*p, p);
49     *res = (int) (temp_res + (temp_res > 0 ? 0.5 : -0.5));
50     if (*p != start)
51         return 1;
52     else
53         return 0;
54 }
55
56 int mystrtou32(char **p, int base, uint32_t *res)
57 {
58     char *start = *p;
59     *res = strtoll(*p, p, base);
60     if (*p != start)
61         return 1;
62     else
63         return 0;
64 }
65
66 int mystrtod(char **p, double *res)
67 {
68     char *start = *p;
69     *res = ass_strtod(*p, p);
70     if (*p != start)
71         return 1;
72     else
73         return 0;
74 }
75
76 int strtocolor(ASS_Library *library, char **q, uint32_t *res, int hex)
77 {
78     uint32_t color = 0;
79     int result;
80     char *p = *q;
81     int base = hex ? 16 : 10;
82
83     if (*p == '&')
84         ++p;
85     else
86         ass_msg(library, MSGL_DBG2, "suspicious color format: \"%s\"\n", p);
87
88     if (*p == 'H' || *p == 'h') {
89         ++p;
90         result = mystrtou32(&p, 16, &color);
91     } else {
92         result = mystrtou32(&p, base, &color);
93     }
94
95     {
96         unsigned char *tmp = (unsigned char *) (&color);
97         unsigned char b;
98         b = tmp[0];
99         tmp[0] = tmp[3];
100         tmp[3] = b;
101         b = tmp[1];
102         tmp[1] = tmp[2];
103         tmp[2] = b;
104     }
105     if (*p == '&')
106         ++p;
107     *q = p;
108
109     *res = color;
110     return result;
111 }
112
113 // Return a boolean value for a string
114 char parse_bool(char *str)
115 {
116     while (*str == ' ' || *str == '\t')
117         str++;
118     if (!strncasecmp(str, "yes", 3))
119         return 1;
120     else if (strtol(str, NULL, 10) > 0)
121         return 1;
122     return 0;
123 }
124
125 void ass_msg(ASS_Library *priv, int lvl, char *fmt, ...)
126 {
127     va_list va;
128     va_start(va, fmt);
129     priv->msg_callback(lvl, fmt, va, priv->msg_callback_data);
130     va_end(va);
131 }
132
133 unsigned ass_utf8_get_char(char **str)
134 {
135     uint8_t *strp = (uint8_t *) * str;
136     unsigned c = *strp++;
137     unsigned mask = 0x80;
138     int len = -1;
139     while (c & mask) {
140         mask >>= 1;
141         len++;
142     }
143     if (len <= 0 || len > 4)
144         goto no_utf8;
145     c &= mask - 1;
146     while ((*strp & 0xc0) == 0x80) {
147         if (len-- <= 0)
148             goto no_utf8;
149         c = (c << 6) | (*strp++ & 0x3f);
150     }
151     if (len)
152         goto no_utf8;
153     *str = (char *) strp;
154     return c;
155
156   no_utf8:
157     strp = (uint8_t *) * str;
158     c = *strp++;
159     *str = (char *) strp;
160     return c;
161 }
162
163 #ifdef CONFIG_ENCA
164 void *ass_guess_buffer_cp(ASS_Library *library, unsigned char *buffer,
165                           int buflen, char *preferred_language,
166                           char *fallback)
167 {
168     const char **languages;
169     size_t langcnt;
170     EncaAnalyser analyser;
171     EncaEncoding encoding;
172     char *detected_sub_cp = NULL;
173     int i;
174
175     languages = enca_get_languages(&langcnt);
176     ass_msg(library, MSGL_V, "ENCA supported languages");
177     for (i = 0; i < langcnt; i++) {
178         ass_msg(library, MSGL_V, "lang %s", languages[i]);
179     }
180
181     for (i = 0; i < langcnt; i++) {
182         const char *tmp;
183
184         if (strcasecmp(languages[i], preferred_language) != 0)
185             continue;
186         analyser = enca_analyser_alloc(languages[i]);
187         encoding = enca_analyse_const(analyser, buffer, buflen);
188         tmp = enca_charset_name(encoding.charset, ENCA_NAME_STYLE_ICONV);
189         if (tmp && encoding.charset != ENCA_CS_UNKNOWN) {
190             detected_sub_cp = strdup(tmp);
191             ass_msg(library, MSGL_INFO, "ENCA detected charset: %s", tmp);
192         }
193         enca_analyser_free(analyser);
194     }
195
196     free(languages);
197
198     if (!detected_sub_cp) {
199         detected_sub_cp = strdup(fallback);
200         ass_msg(library, MSGL_INFO,
201                "ENCA detection failed: fallback to %s", fallback);
202     }
203
204     return detected_sub_cp;
205 }
206 #endif