return i;
}
i = track->default_style;
- ass_msg(MSGL_WARN,
+ ass_msg(track->library, MSGL_WARN,
"[%p]: Warning: no style named '%s' found, using '%s'",
track, name, track->styles[i].Name);
return i; // use the first style
}
-static uint32_t string2color(char *p)
+static uint32_t string2color(ass_library_t *library, char *p)
{
uint32_t tmp;
- (void) strtocolor(&p, &tmp);
+ (void) strtocolor(library, &p, &tmp);
return tmp;
}
-static long long string2timecode(char *p)
+static long long string2timecode(ass_library_t *library, char *p)
{
unsigned h, m, s, ms;
long long tm;
int res = sscanf(p, "%1d:%2d:%2d.%2d", &h, &m, &s, &ms);
if (res < 4) {
- ass_msg(MSGL_WARN, "Bad timestamp");
+ ass_msg(library, MSGL_WARN, "Bad timestamp");
return 0;
}
tm = ((h * 60 + m) * 60 + s) * 1000 + ms * 10;
#define ANYVAL(name,func) \
} else if (strcasecmp(tname, #name) == 0) { \
target->name = func(token); \
- ass_msg(MSGL_DBG2, "%s = %s", #name, token);
+ ass_msg(track->library, MSGL_DBG2, "%s = %s", #name, token);
#define STRVAL(name) \
} else if (strcasecmp(tname, #name) == 0) { \
if (target->name != NULL) free(target->name); \
target->name = strdup(token); \
- ass_msg(MSGL_DBG2, "%s = %s", #name, token);
+ ass_msg(track->library, MSGL_DBG2, "%s = %s", #name, token);
+
+#define COLORVAL(name) \
+ } else if (strcasecmp(tname, #name) == 0) { \
+ target->name = string2color(track->library, token); \
+ ass_msg(track->library, MSGL_DBG2, "%s = %s", #name, token);
-#define COLORVAL(name) ANYVAL(name,string2color)
#define INTVAL(name) ANYVAL(name,atoi)
#define FPVAL(name) ANYVAL(name,atof)
-#define TIMEVAL(name) ANYVAL(name,string2timecode)
+#define TIMEVAL(name) \
+ } else if (strcasecmp(tname, #name) == 0) { \
+ target->name = string2timecode(track->library, token); \
+ ass_msg(track->library, MSGL_DBG2, "%s = %s", #name, token);
+
#define STYLEVAL(name) \
} else if (strcasecmp(tname, #name) == 0) { \
target->name = lookup_style(track, token); \
- ass_msg(MSGL_DBG2, "%s = %s", #name, token);
+ ass_msg(track->library, MSGL_DBG2, "%s = %s", #name, token);
#define ALIAS(alias,name) \
if (strcasecmp(tname, #alias) == 0) {tname = #name;}
if (last >= event->Text && *last == '\r')
*last = 0;
}
- ass_msg(MSGL_DBG2, "Text = %s", event->Text);
+ ass_msg(track->library, MSGL_DBG2, "Text = %s", event->Text);
event->Duration -= event->Start;
free(format);
return 0; // "Text" is always the last
q = format = strdup(track->style_format);
- ass_msg(MSGL_V, "[%p] Style: %s", track, str);
+ ass_msg(track->library, MSGL_V, "[%p] Style: %s", track, str);
sid = ass_alloc_style(track);
char *p = str + 7;
skip_spaces(&p);
track->style_format = strdup(p);
- ass_msg(MSGL_DBG2, "Style format: %s",
+ ass_msg(track->library, MSGL_DBG2, "Style format: %s",
track->style_format);
} else if (!strncmp(str, "Style:", 6)) {
char *p = str + 6;
{
track->parser_priv->state = PST_EVENTS;
if (track->track_type == TRACK_TYPE_SSA)
- track->event_format =
- strdup
- ("Format: Marked, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text");
+ track->event_format = strdup("Format: Marked, Start, End, Style, "
+ "Name, MarginL, MarginR, MarginV, Effect, Text");
else
- track->event_format =
- strdup
- ("Format: Layer, Start, End, Style, Actor, MarginL, MarginR, MarginV, Effect, Text");
- ass_msg(MSGL_V, "No event format found, using fallback");
+ track->event_format = strdup("Format: Layer, Start, End, Style, "
+ "Actor, MarginL, MarginR, MarginV, Effect, Text");
+ ass_msg(track->library, MSGL_V,
+ "No event format found, using fallback");
}
static int process_events_line(ass_track_t *track, char *str)
char *p = str + 7;
skip_spaces(&p);
track->event_format = strdup(p);
- ass_msg(MSGL_DBG2, "Event format: %s", track->event_format);
+ ass_msg(track->library, MSGL_DBG2, "Event format: %s", track->event_format);
} else if (!strncmp(str, "Dialogue:", 9)) {
// This should never be reached for embedded subtitles.
// They have slightly different format and are parsed in ass_process_chunk,
process_event_tail(track, event, str, 0);
} else {
- ass_msg(MSGL_V, "Not understood: '%s'", str);
+ ass_msg(track->library, MSGL_V, "Not understood: '%s'", str);
}
return 0;
}
int dsize; // decoded size
unsigned char *buf = 0;
- ass_msg(MSGL_V, "Font: %d bytes encoded data",
- track->parser_priv->fontdata_used);
+ ass_msg(track->library, MSGL_V, "Font: %d bytes encoded data",
+ track->parser_priv->fontdata_used);
size = track->parser_priv->fontdata_used;
if (size % 4 == 1) {
- ass_msg(MSGL_ERR, "Bad encoded data size");
+ ass_msg(track->library, MSGL_ERR, "Bad encoded data size");
goto error_decode_font;
}
buf = malloc(size / 4 * 3 + 2);
decode_font(track);
}
track->parser_priv->fontname = strdup(p);
- ass_msg(MSGL_V, "Fontname: %s",
+ ass_msg(track->library, MSGL_V, "Fontname: %s",
track->parser_priv->fontname);
return 0;
}
if (!track->parser_priv->fontname) {
- ass_msg(MSGL_V, "Not understood: '%s'", str);
+ ass_msg(track->library, MSGL_V, "Not understood: '%s'", str);
return 0;
}
len = strlen(str);
if (len > 80) {
- ass_msg(MSGL_WARN, "Font line too long: %d, %s", len, str);
+ ass_msg(track->library, MSGL_WARN, "Font line too long: %d, %s",
+ len, str);
return 0;
}
if (track->parser_priv->fontdata_used + len >
memcpy(str, data, size);
str[size] = '\0';
- ass_msg(MSGL_V, "Event: %s", str);
+ ass_msg(track->library, MSGL_V, "Event: %s", str);
process_text(track, str);
free(str);
}
ass_event_t *event;
if (!track->event_format) {
- ass_msg(MSGL_WARN, "Event format header missing");
+ ass_msg(track->library, MSGL_WARN, "Event format header missing");
return;
}
str = malloc(size + 1);
memcpy(str, data, size);
str[size] = '\0';
- ass_msg(MSGL_V, "Event at %" PRId64 ", +%" PRId64 ": %s",
+ ass_msg(track->library, MSGL_V, "Event at %" PRId64 ", +%" PRId64 ": %s",
(int64_t) timecode, (int64_t) duration, str);
eid = ass_alloc_event(track);
* \param size buffer size
* \return a pointer to recoded buffer, caller is responsible for freeing it
**/
-static char *sub_recode(char *data, size_t size, char *codepage)
+static char *sub_recode(ass_library_t *library, char *data, size_t size,
+ char *codepage)
{
iconv_t icdsc;
char *tocp = "UTF-8";
|| sscanf(codepage, "ENCA:%2s:%99s", enca_lang,
enca_fallback) == 2) {
cp_tmp =
- ass_guess_buffer_cp((unsigned char *) data, size, enca_lang,
- enca_fallback);
+ ass_guess_buffer_cp(library, (unsigned char *) data, size,
+ enca_lang, enca_fallback);
}
#endif
if ((icdsc = iconv_open(tocp, cp_tmp)) != (iconv_t) (-1)) {
- ass_msg(MSGL_V, "Opened iconv descriptor");
+ ass_msg(library, MSGL_V, "Opened iconv descriptor");
} else
- ass_msg(MSGL_ERR, "Error opening iconv descriptor");
+ ass_msg(library, MSGL_ERR, "Error opening iconv descriptor");
}
{
osize += size;
oleft += size;
} else {
- ass_msg(MSGL_WARN, "Error recoding file");
+ ass_msg(library, MSGL_WARN, "Error recoding file");
return NULL;
}
} else if (clear)
if (icdsc != (iconv_t) (-1)) {
(void) iconv_close(icdsc);
icdsc = (iconv_t) (-1);
- ass_msg(MSGL_V, "Closed iconv descriptor");
+ ass_msg(library, MSGL_V, "Closed iconv descriptor");
}
return outbuf;
* \param bufsize out: file size
* \return pointer to file contents. Caller is responsible for its deallocation.
*/
-static char *read_file(char *fname, size_t *bufsize)
+static char *read_file(ass_library_t *library, char *fname, size_t *bufsize)
{
int res;
long sz;
FILE *fp = fopen(fname, "rb");
if (!fp) {
- ass_msg(MSGL_WARN, "ass_read_file(%s): fopen failed", fname);
+ ass_msg(library, MSGL_WARN,
+ "ass_read_file(%s): fopen failed", fname);
return 0;
}
res = fseek(fp, 0, SEEK_END);
if (res == -1) {
- ass_msg(MSGL_WARN, "ass_read_file(%s): fseek failed", fname);
+ ass_msg(library, MSGL_WARN,
+ "ass_read_file(%s): fseek failed", fname);
fclose(fp);
return 0;
}
rewind(fp);
if (sz > 10 * 1024 * 1024) {
- ass_msg(MSGL_INFO,
+ ass_msg(library, MSGL_INFO,
"ass_read_file(%s): Refusing to load subtitles "
"larger than 10MiB", fname);
fclose(fp);
return 0;
}
- ass_msg(MSGL_V, "File size: %ld", sz);
+ ass_msg(library, MSGL_V, "File size: %ld", sz);
buf = malloc(sz + 1);
assert(buf);
do {
res = fread(buf + bytes_read, 1, sz - bytes_read, fp);
if (res <= 0) {
- ass_msg(MSGL_INFO, "Read failed, %d: %s", errno,
+ ass_msg(library, MSGL_INFO, "Read failed, %d: %s", errno,
strerror(errno));
fclose(fp);
free(buf);
#ifdef CONFIG_ICONV
if (codepage)
- buf = sub_recode(buf, bufsize, codepage);
+ buf = sub_recode(library, buf, bufsize, codepage);
if (!buf)
return 0;
else
if (!track)
return 0;
- ass_msg(MSGL_INFO, "Added subtitle file: "
+ ass_msg(library, MSGL_INFO, "Added subtitle file: "
"<memory> (%d styles, %d events)",
track->n_styles, track->n_events);
return track;
}
-static char *read_file_recode(char *fname, char *codepage, size_t *size)
+static char *read_file_recode(ass_library_t *library, char *fname,
+ char *codepage, size_t *size)
{
char *buf;
size_t bufsize;
- buf = read_file(fname, &bufsize);
+ buf = read_file(library, fname, &bufsize);
if (!buf)
return 0;
#ifdef CONFIG_ICONV
if (codepage) {
- char *tmpbuf = sub_recode(buf, bufsize, codepage);
+ char *tmpbuf = sub_recode(library, buf, bufsize, codepage);
free(buf);
buf = tmpbuf;
}
ass_track_t *track;
size_t bufsize;
- buf = read_file_recode(fname, codepage, &bufsize);
+ buf = read_file_recode(library, fname, codepage, &bufsize);
if (!buf)
return 0;
track = parse_memory(library, buf);
track->name = strdup(fname);
- ass_msg(MSGL_INFO, "Added subtitle file: '%s' (%d styles, %d events)",
+ ass_msg(library, MSGL_INFO,
+ "Added subtitle file: '%s' (%d styles, %d events)",
fname, track->n_styles, track->n_events);
return track;
parser_state_t old_state;
size_t sz;
- buf = read_file(fname, &sz);
+ buf = read_file(track->library, fname, &sz);
if (!buf)
return 1;
#ifdef CONFIG_ICONV
if (codepage) {
char *tmpbuf;
- tmpbuf = sub_recode(buf, sz, codepage);
+ tmpbuf = sub_recode(track->library, buf, sz, codepage);
free(buf);
buf = tmpbuf;
}
#define LIBASS_ASS_H
#include <stdio.h>
+#include <stdarg.h>
#include "ass_types.h"
/// Libass renderer object. Contents are private.
void ass_process_force_style(ass_track_t *track);
+void ass_set_message_cb(ass_library_t *priv,
+ void (*msg_cb)(int, char *, va_list *));
+
/**
* \brief initialize the renderer
* \param priv library handle
return dst;
}
-static int check_glyph_area(FT_Glyph glyph)
+static int check_glyph_area(ass_library_t *library, FT_Glyph glyph)
{
FT_BBox bbox;
long long dx, dy;
dx = bbox.xMax - bbox.xMin;
dy = bbox.yMax - bbox.yMin;
if (dx * dy > 8000000) {
- ass_msg(MSGL_WARN, "Glyph bounding box too large: %dx%dpx",
+ ass_msg(library, MSGL_WARN, "Glyph bounding box too large: %dx%dpx",
(int) dx, (int) dy);
return 1;
} else
return 0;
}
-static bitmap_t *glyph_to_bitmap_internal(FT_Glyph glyph, int bord)
+static bitmap_t *glyph_to_bitmap_internal(ass_library_t *library,
+ FT_Glyph glyph, int bord)
{
FT_BitmapGlyph bg;
FT_Bitmap *bit;
int i;
int error;
- if (check_glyph_area(glyph))
+ if (check_glyph_area(library, glyph))
return 0;
error = FT_Glyph_To_Bitmap(&glyph, FT_RENDER_MODE_NORMAL, 0, 0);
if (error) {
- ass_msg(MSGL_WARN, "FT_Glyph_To_Bitmap error %d",
+ ass_msg(library, MSGL_WARN, "FT_Glyph_To_Bitmap error %d",
error);
return 0;
}
bg = (FT_BitmapGlyph) glyph;
bit = &(bg->bitmap);
if (bit->pixel_mode != FT_PIXEL_MODE_GRAY) {
- ass_msg(MSGL_WARN, "Unsupported pixel mode: %d",
+ ass_msg(library, MSGL_WARN, "Unsupported pixel mode: %d",
(int) (bit->pixel_mode));
FT_Done_Glyph(glyph);
return 0;
}
}
-int glyph_to_bitmap(ass_synth_priv_t *priv_blur,
+int glyph_to_bitmap(ass_library_t *library, ass_synth_priv_t *priv_blur,
FT_Glyph glyph, FT_Glyph outline_glyph,
bitmap_t **bm_g, bitmap_t **bm_o, bitmap_t **bm_s,
int be, double blur_radius, FT_Vector shadow_offset)
*bm_g = *bm_o = *bm_s = 0;
if (glyph)
- *bm_g = glyph_to_bitmap_internal(glyph, bord);
+ *bm_g = glyph_to_bitmap_internal(library, glyph, bord);
if (!*bm_g)
return 1;
if (outline_glyph) {
- *bm_o = glyph_to_bitmap_internal(outline_glyph, bord);
+ *bm_o = glyph_to_bitmap_internal(library, outline_glyph, bord);
if (!*bm_o) {
ass_free_bitmap(*bm_g);
return 1;
#include <ft2build.h>
#include FT_GLYPH_H
+#include "ass.h"
+
typedef struct ass_synth_priv_s ass_synth_priv_t;
ass_synth_priv_t *ass_synth_init(double);
* \param bm_g out: pointer to the bitmap of glyph shadow is returned here
* \param be 1 = produces blurred bitmaps, 0 = normal bitmaps
*/
-int glyph_to_bitmap(ass_synth_priv_t *priv_blur, FT_Glyph glyph,
- FT_Glyph outline_glyph, bitmap_t **bm_g,
- bitmap_t **bm_o, bitmap_t **bm_s, int be,
- double blur_radius, FT_Vector shadow_offset);
+int glyph_to_bitmap(ass_library_t *library, ass_synth_priv_t *priv_blur,
+ FT_Glyph glyph, FT_Glyph outline_glyph,
+ bitmap_t **bm_g, bitmap_t **bm_o, bitmap_t **bm_s,
+ int be, double blur_radius, FT_Vector shadow_offset);
void ass_free_bitmap(bitmap_t *bm);
free(value);
}
-hashmap_t *hashmap_init(size_t key_size, size_t value_size, int nbuckets,
+hashmap_t *hashmap_init(ass_library_t *library, size_t key_size,
+ size_t value_size, int nbuckets,
hashmap_item_dtor_t item_dtor,
hashmap_key_compare_t key_compare,
hashmap_hash_t hash)
{
hashmap_t *map = calloc(1, sizeof(hashmap_t));
+ map->library = library;
map->nbuckets = nbuckets;
map->key_size = key_size;
map->value_size = value_size;
int i;
// print stats
if (map->count > 0 || map->hit_count + map->miss_count > 0)
- ass_msg(MSGL_V,
+ ass_msg(map->library, MSGL_V,
"cache statistics: \n total accesses: %d\n hits: %d\n "
"misses: %d\n object count: %d",
map->hit_count + map->miss_count, map->hit_count,
return hashmap_insert(font_cache, &(font->desc), font);
}
-hashmap_t *ass_font_cache_init(void)
+hashmap_t *ass_font_cache_init(ass_library_t *library)
{
hashmap_t *font_cache;
- font_cache = hashmap_init(sizeof(ass_font_desc_t),
+ font_cache = hashmap_init(library, sizeof(ass_font_desc_t),
sizeof(ass_font_t),
1000,
font_hash_dtor, font_compare, font_desc_hash);
return hashmap_find(bitmap_cache, key);
}
-hashmap_t *ass_bitmap_cache_init(void)
+hashmap_t *ass_bitmap_cache_init(ass_library_t *library)
{
hashmap_t *bitmap_cache;
- bitmap_cache = hashmap_init(sizeof(bitmap_hash_key_t),
+ bitmap_cache = hashmap_init(library,
+ sizeof(bitmap_hash_key_t),
sizeof(bitmap_hash_val_t),
0xFFFF + 13,
bitmap_hash_dtor, bitmap_compare,
hashmap_t *ass_bitmap_cache_reset(hashmap_t *bitmap_cache)
{
+ ass_library_t *lib = bitmap_cache->library;
+
ass_bitmap_cache_done(bitmap_cache);
- return ass_bitmap_cache_init();
+ return ass_bitmap_cache_init(lib);
}
//---------------------------------
return hashmap_find(glyph_cache, key);
}
-hashmap_t *ass_glyph_cache_init(void)
+hashmap_t *ass_glyph_cache_init(ass_library_t *library)
{
hashmap_t *glyph_cache;
- glyph_cache = hashmap_init(sizeof(glyph_hash_key_t),
+ glyph_cache = hashmap_init(library, sizeof(glyph_hash_key_t),
sizeof(glyph_hash_val_t),
0xFFFF + 13,
glyph_hash_dtor, glyph_compare, glyph_hash);
hashmap_t *ass_glyph_cache_reset(hashmap_t *glyph_cache)
{
+ ass_library_t *lib = glyph_cache->library;
+
ass_glyph_cache_done(glyph_cache);
- return ass_glyph_cache_init();
+ return ass_glyph_cache_init(lib);
}
return hashmap_find(composite_cache, key);
}
-hashmap_t *ass_composite_cache_init(void)
+hashmap_t *ass_composite_cache_init(ass_library_t *library)
{
hashmap_t *composite_cache;
- composite_cache = hashmap_init(sizeof(composite_hash_key_t),
+ composite_cache = hashmap_init(library, sizeof(composite_hash_key_t),
sizeof(composite_hash_val_t),
0xFFFF + 13,
composite_hash_dtor, composite_compare,
hashmap_t *ass_composite_cache_reset(hashmap_t *composite_cache)
{
+ ass_library_t *lib = composite_cache->library;
+
ass_composite_cache_done(composite_cache);
- return ass_composite_cache_init();
+ return ass_composite_cache_init(lib);
}
int hit_count;
int miss_count;
int count;
+ ass_library_t *library;
} hashmap_t;
-hashmap_t *hashmap_init(size_t key_size, size_t value_size, int nbuckets,
+hashmap_t *hashmap_init(ass_library_t *library, size_t key_size,
+ size_t value_size, int nbuckets,
hashmap_item_dtor_t item_dtor,
hashmap_key_compare_t key_compare,
hashmap_hash_t hash);
void *hashmap_insert(hashmap_t *map, void *key, void *value);
void *hashmap_find(hashmap_t *map, void *key);
-hashmap_t *ass_font_cache_init(void);
+hashmap_t *ass_font_cache_init(ass_library_t *library);
ass_font_t *ass_font_cache_find(hashmap_t *, ass_font_desc_t *desc);
void *ass_font_cache_add(hashmap_t *, ass_font_t *font);
void ass_font_cache_done(hashmap_t *);
bitmap_t *bm_s;
} bitmap_hash_val_t;
-hashmap_t *ass_bitmap_cache_init(void);
+hashmap_t *ass_bitmap_cache_init(ass_library_t *library);
void *cache_add_bitmap(hashmap_t *, bitmap_hash_key_t *key,
bitmap_hash_val_t *val);
bitmap_hash_val_t *cache_find_bitmap(hashmap_t *bitmap_cache,
unsigned char *b;
} composite_hash_val_t;
-hashmap_t *ass_composite_cache_init(void);
+hashmap_t *ass_composite_cache_init(ass_library_t *library);
void *cache_add_composite(hashmap_t *, composite_hash_key_t *key,
composite_hash_val_t *val);
composite_hash_val_t *cache_find_composite(hashmap_t *composite_cache,
int asc, desc; // ascender/descender of a drawing
} glyph_hash_val_t;
-hashmap_t *ass_glyph_cache_init(void);
+hashmap_t *ass_glyph_cache_init(ass_library_t *library);
void *cache_add_glyph(hashmap_t *, glyph_hash_key_t *key,
glyph_hash_val_t *val);
glyph_hash_val_t *cache_find_glyph(hashmap_t *glyph_cache,
for (i = 0; i < ol->n_points; i++)
ol->points[i].y += offset;
- ass_msg(MSGL_V, "Parsed drawing with %d points and %d contours",
- ol->n_points, ol->n_contours);
+ ass_msg(drawing->library, MSGL_V,
+ "Parsed drawing with %d points and %d contours", ol->n_points,
+ ol->n_contours);
}
/*
drawing->size = DRAWING_INITIAL_SIZE;
drawing->ftlibrary = lib;
+ drawing->library = font->library;
drawing_make_glyph(drawing, fontconfig_priv, font, hint);
drawing->scale_x = 1.;
// private
FT_Library ftlibrary; // FT library instance, needed for font ops
+ ass_library_t *library;
int size; // current buffer size
ass_drawing_token_t *tokens; // tokenized drawing
int max_points; // current maximum size
* Select Microfost Unicode CharMap, if the font has one.
* Otherwise, let FreeType decide.
*/
-static void charmap_magic(FT_Face face)
+static void charmap_magic(ass_library_t *library, FT_Face face)
{
int i;
for (i = 0; i < face->num_charmaps; ++i) {
if (!face->charmap) {
if (face->num_charmaps == 0) {
- ass_msg(MSGL_WARN, "Font face with no charmaps");
+ ass_msg(library, MSGL_WARN, "Font face with no charmaps");
return;
}
- ass_msg(MSGL_WARN, "No charmap autodetected, trying the first one");
+ ass_msg(library, MSGL_WARN,
+ "No charmap autodetected, trying the first one");
FT_Set_Charmap(face, face->charmaps[0]);
return;
}
return -1;
path =
- fontconfig_select(fc_priv, font->desc.family,
+ fontconfig_select(font->library, fc_priv, font->desc.family,
font->desc.treat_family_as_pattern,
font->desc.bold, font->desc.italic, &index, ch);
if (!path)
font->library->fontdata[mem_idx].size, 0,
&face);
if (error) {
- ass_msg(MSGL_WARN, "Error opening memory font: '%s'", path);
+ ass_msg(font->library, MSGL_WARN,
+ "Error opening memory font: '%s'", path);
free(path);
return -1;
}
} else {
error = FT_New_Face(font->ftlibrary, path, index, &face);
if (error) {
- ass_msg(MSGL_WARN, "Error opening font: '%s', %d", path, index);
+ ass_msg(font->library, MSGL_WARN,
+ "Error opening font: '%s', %d", path, index);
free(path);
return -1;
}
}
- charmap_magic(face);
+ charmap_magic(font->library, face);
buggy_font_workaround(face);
font->faces[font->n_faces++] = face;
#ifdef CONFIG_FONTCONFIG
if (index == 0) {
int face_idx;
- ass_msg(MSGL_INFO,
+ ass_msg(font->library, MSGL_INFO,
"Glyph 0x%X not found, selecting one more "
"font for (%s, %d, %d)", ch, font->desc.family,
font->desc.bold, font->desc.italic);
face = font->faces[face_idx];
index = FT_Get_Char_Index(face, ch);
if (index == 0) {
- ass_msg(MSGL_ERR, "Glyph 0x%X not found in font "
- "for (%s, %d, %d)", ch, font->desc.family,
- font->desc.bold, font->desc.italic);
+ ass_msg(font->library, MSGL_ERR,
+ "Glyph 0x%X not found in font for (%s, %d, %d)",
+ ch, font->desc.family, font->desc.bold,
+ font->desc.italic);
}
}
}
error = FT_Load_Glyph(face, index, FT_LOAD_NO_BITMAP | flags);
if (error) {
- ass_msg(MSGL_WARN, "Error loading glyph, index %d", index);
+ ass_msg(font->library, MSGL_WARN, "Error loading glyph, index %d",
+ index);
return 0;
}
#if (FREETYPE_MAJOR > 2) || \
#endif
error = FT_Get_Glyph(face->glyph, &glyph);
if (error) {
- ass_msg(MSGL_WARN, "Error loading glyph, index %d", index);
+ ass_msg(font->library, MSGL_WARN, "Error loading glyph, index %d",
+ index);
return 0;
}
* \param code: the character that should be present in the font, can be 0
* \return font file path
*/
-static char *_select_font(fc_instance_t *priv, const char *family,
- int treat_family_as_pattern, unsigned bold,
- unsigned italic, int *index, uint32_t code)
+static char *_select_font(ass_library_t *library, fc_instance_t *priv,
+ const char *family, int treat_family_as_pattern,
+ unsigned bold, unsigned italic, int *index,
+ uint32_t code)
{
FcBool rc;
FcResult result;
if (!treat_family_as_pattern &&
!(r_family && strcasecmp((const char *) r_family, family) == 0) &&
!(r_fullname && strcasecmp((const char *) r_fullname, family) == 0))
- ass_msg(MSGL_WARN,
+ ass_msg(library, MSGL_WARN,
"fontconfig: Selected font is not the requested one: "
"'%s' != '%s'",
(const char *) (r_fullname ? r_fullname : r_family), family);
if (result != FcResultMatch)
r_embolden = 0;
- ass_msg(MSGL_V,
+ ass_msg(library, MSGL_V,
"Font info: family '%s', style '%s', fullname '%s',"
" slant %d, weight %d%s", (const char *) r_family,
(const char *) r_style, (const char *) r_fullname, r_slant,
* \param code: the character that should be present in the font, can be 0
* \return font file path
*/
-char *fontconfig_select(fc_instance_t *priv, const char *family,
- int treat_family_as_pattern, unsigned bold,
- unsigned italic, int *index, uint32_t code)
+char *fontconfig_select(ass_library_t *library, fc_instance_t *priv,
+ const char *family, int treat_family_as_pattern,
+ unsigned bold, unsigned italic, int *index,
+ uint32_t code)
{
char *res = 0;
if (!priv->config) {
}
if (family && *family)
res =
- _select_font(priv, family, treat_family_as_pattern, bold,
- italic, index, code);
+ _select_font(library, priv, family, treat_family_as_pattern,
+ bold, italic, index, code);
if (!res && priv->family_default) {
res =
- _select_font(priv, priv->family_default, 0, bold, italic, index,
- code);
+ _select_font(library, priv, priv->family_default, 0, bold,
+ italic, index, code);
if (res)
- ass_msg(MSGL_WARN, "fontconfig_select: Using default font "
- "family: (%s, %d, %d) -> %s, %d",
+ ass_msg(library, MSGL_WARN, "fontconfig_select: Using default "
+ "font family: (%s, %d, %d) -> %s, %d",
family, bold, italic, res, *index);
}
if (!res && priv->path_default) {
res = priv->path_default;
*index = priv->index_default;
- ass_msg(MSGL_WARN, "fontconfig_select: Using default font: "
+ ass_msg(library, MSGL_WARN, "fontconfig_select: Using default font: "
"(%s, %d, %d) -> %s, %d", family, bold, italic,
res, *index);
}
if (!res) {
- res = _select_font(priv, "Arial", 0, bold, italic, index, code);
+ res = _select_font(library, priv, "Arial", 0, bold, italic,
+ index, code);
if (res)
- ass_msg(MSGL_WARN, "fontconfig_select: Using 'Arial' font "
- "family: (%s, %d, %d) -> %s, %d", family, bold, italic,
- res, *index);
+ ass_msg(library, MSGL_WARN, "fontconfig_select: Using 'Arial' "
+ "font family: (%s, %d, %d) -> %s, %d", family, bold,
+ italic, res, *index);
}
if (res)
- ass_msg(MSGL_V,
+ ass_msg(library, MSGL_V,
"fontconfig_select: (%s, %d, %d) -> %s, %d", family, bold,
italic, res, *index);
return res;
res = mkdir(fonts_dir);
#endif
if (res) {
- ass_msg(MSGL_WARN, "Failed to create directory '%s'",
+ ass_msg(library, MSGL_WARN, "Failed to create directory '%s'",
fonts_dir);
}
} else if (!S_ISDIR(st.st_mode)) {
- ass_msg(MSGL_WARN, "Not a directory: '%s'", fonts_dir);
+ ass_msg(library, MSGL_WARN, "Not a directory: '%s'", fonts_dir);
}
fname = validate_fname((char *) name);
rc = FT_New_Memory_Face(ftlibrary, (unsigned char *) data,
data_size, face_index, &face);
if (rc) {
- ass_msg(MSGL_WARN, "Error opening memory font: %s",
+ ass_msg(library, MSGL_WARN, "Error opening memory font: %s",
name);
return;
}
FcFreeTypeQueryFace(face, (unsigned char *) name, 0,
FcConfigGetBlanks(priv->config));
if (!pattern) {
- ass_msg(MSGL_WARN, "%s failed", "FcFreeTypeQueryFace");
+ ass_msg(library, MSGL_WARN, "%s failed", "FcFreeTypeQueryFace");
FT_Done_Face(face);
return;
}
fset = FcConfigGetFonts(priv->config, FcSetSystem); // somehow it failes when asked for FcSetApplication
if (!fset) {
- ass_msg(MSGL_WARN, "%s failed", "FcConfigGetFonts");
+ ass_msg(library, MSGL_WARN, "%s failed", "FcConfigGetFonts");
FT_Done_Face(face);
return;
}
res = FcFontSetAdd(fset, pattern);
if (!res) {
- ass_msg(MSGL_WARN, "%s failed", "FcFontSetAdd");
+ ass_msg(library, MSGL_WARN, "%s failed", "FcFontSetAdd");
FT_Done_Face(face);
return;
}
int i;
if (!fc) {
- ass_msg(MSGL_WARN,
+ ass_msg(library, MSGL_WARN,
"Fontconfig disabled, only default font will be used.");
goto exit;
}
}
if (!rc || !priv->config) {
- ass_msg(MSGL_FATAL, "%s failed", "FcInitLoadConfigAndFonts");
+ ass_msg(library, MSGL_FATAL, "%s failed", "FcInitLoadConfigAndFonts");
goto exit;
}
if (dir) {
if (FcDirCacheValid((const FcChar8 *) dir) == FcFalse) {
- ass_msg(MSGL_INFO, "Updating font cache");
+ ass_msg(library, MSGL_INFO, "Updating font cache");
if (FcGetVersion() >= 20390 && FcGetVersion() < 20400)
- ass_msg(MSGL_WARN, "Beta versions of fontconfig are not "
- "supported. Update before reporting any bugs");
+ ass_msg(library, MSGL_WARN, "Beta versions of fontconfig"
+ "are not supported. Update before reporting any bugs");
// FontConfig >= 2.4.0 updates cache automatically in FcConfigAppFontAddDir()
if (FcGetVersion() < 20390) {
FcFontSet *fcs;
fss = FcStrSetCreate();
rc = FcStrSetAdd(fss, (const FcChar8 *) dir);
if (!rc) {
- ass_msg(MSGL_WARN, "%s failed", "FcStrSetAdd");
+ ass_msg(library, MSGL_WARN, "%s failed", "FcStrSetAdd");
goto ErrorFontCache;
}
FcConfigGetBlanks(priv->config),
(const FcChar8 *) dir, FcFalse);
if (!rc) {
- ass_msg(MSGL_WARN, "%s failed", "FcDirScan");
+ ass_msg(library, MSGL_WARN, "%s failed", "FcDirScan");
goto ErrorFontCache;
}
rc = FcDirSave(fcs, fss, (const FcChar8 *) dir);
if (!rc) {
- ass_msg(MSGL_WARN, "%s failed", "FcDirSave");
+ ass_msg(library, MSGL_WARN, "%s failed", "FcDirSave");
goto ErrorFontCache;
}
ErrorFontCache:
rc = FcConfigAppFontAddDir(priv->config, (const FcChar8 *) dir);
if (!rc) {
- ass_msg(MSGL_WARN, "%s failed", "FcConfigAppFontAddDir");
+ ass_msg(library, MSGL_WARN, "%s failed", "FcConfigAppFontAddDir");
}
}
{
fc_instance_t *priv;
- ass_msg(MSGL_WARN,
+ ass_msg(library, MSGL_WARN,
"Fontconfig disabled, only default font will be used.");
priv = calloc(1, sizeof(fc_instance_t));
fc_instance_t *fontconfig_init(ass_library_t *library,
FT_Library ftlibrary, const char *family,
const char *path, int fc, const char *config);
-char *fontconfig_select(fc_instance_t *priv, const char *family,
- int treat_family_as_pattern, unsigned bold,
- unsigned italic, int *index, uint32_t code);
+char *fontconfig_select(ass_library_t *library, fc_instance_t *priv,
+ const char *family, int treat_family_as_pattern,
+ unsigned bold, unsigned italic, int *index,
+ uint32_t code);
void fontconfig_done(fc_instance_t *priv);
#endif /* LIBASS_FONTCONFIG_H */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <stdarg.h>
#include "ass.h"
#include "ass_library.h"
+#include "ass_utils.h"
+static void ass_msg_handler(int level, char *fmt, va_list *va)
+{
+ if (level > MSGL_INFO)
+ return;
+ printf("[ass] ");
+ vprintf(fmt, *va);
+ printf("\n");
+}
ass_library_t *ass_library_init(void)
{
- return calloc(1, sizeof(ass_library_t));
+ ass_library_t* lib = calloc(1, sizeof(ass_library_t));
+ lib->msg_callback = ass_msg_handler;
+
+ return lib;
}
void ass_library_done(ass_library_t *priv)
priv->fontdata = NULL;
priv->num_fontdata = 0;
}
+
+/*
+ * Register a message callback function with libass. Without setting one,
+ * a default handler is used which prints everything with MSGL_INFO or
+ * higher to the standard output.
+ */
+void ass_set_message_cb(ass_library_t *priv,
+ void (*msg_cb)(int, char *, va_list *))
+{
+ if (msg_cb)
+ priv->msg_callback = msg_cb;
+}
+
#ifndef LIBASS_LIBRARY_H
#define LIBASS_LIBRARY_H
+#include <stdarg.h>
+
typedef struct ass_fontdata_s {
char *name;
char *data;
ass_fontdata_t *fontdata;
int num_fontdata;
+ void (*msg_callback)(int, char *, va_list *);
};
#endif /* LIBASS_LIBRARY_H */
if (track->PlayResX && track->PlayResY)
return;
if (!track->PlayResX && !track->PlayResY) {
- ass_msg(MSGL_WARN,
+ ass_msg(render_priv->library, MSGL_WARN,
"Neither PlayResX nor PlayResY defined. Assuming 384x288");
track->PlayResX = 384;
track->PlayResY = 288;
render_priv->width;
if (!track->PlayResY && track->PlayResX == 1280) {
track->PlayResY = 1024;
- ass_msg(MSGL_WARN,
+ ass_msg(render_priv->library, MSGL_WARN,
"PlayResY undefined, setting to %d", track->PlayResY);
} else if (!track->PlayResY) {
track->PlayResY = track->PlayResX / orig_aspect + .5;
- ass_msg(MSGL_WARN,
+ ass_msg(render_priv->library, MSGL_WARN,
"PlayResY undefined, setting to %d", track->PlayResY);
} else if (!track->PlayResX && track->PlayResY == 1024) {
track->PlayResX = 1280;
- ass_msg(MSGL_WARN,
+ ass_msg(render_priv->library, MSGL_WARN,
"PlayResX undefined, setting to %d", track->PlayResX);
} else if (!track->PlayResX) {
track->PlayResX = track->PlayResY * orig_aspect + .5;
- ass_msg(MSGL_WARN,
+ ass_msg(render_priv->library, MSGL_WARN,
"PlayResX undefined, setting to %d", track->PlayResX);
}
}
error = FT_Init_FreeType(&ft);
if (error) {
- ass_msg(MSGL_FATAL, "%s failed", "FT_Init_FreeType");
+ ass_msg(library, MSGL_FATAL, "%s failed", "FT_Init_FreeType");
goto ass_init_exit;
}
FT_Library_Version(ft, &vmajor, &vminor, &vpatch);
- ass_msg(MSGL_V, "FreeType library version: %d.%d.%d",
+ ass_msg(library, MSGL_V, "FreeType library version: %d.%d.%d",
vmajor, vminor, vpatch);
- ass_msg(MSGL_V, "FreeType headers version: %d.%d.%d",
+ ass_msg(library, MSGL_V, "FreeType headers version: %d.%d.%d",
FREETYPE_MAJOR, FREETYPE_MINOR, FREETYPE_PATCH);
priv = calloc(1, sizeof(ass_renderer_t));
priv->ftlibrary = ft;
// images_root and related stuff is zero-filled in calloc
- priv->cache.font_cache = ass_font_cache_init();
- priv->cache.bitmap_cache = ass_bitmap_cache_init();
- priv->cache.composite_cache = ass_composite_cache_init();
- priv->cache.glyph_cache = ass_glyph_cache_init();
+ priv->cache.font_cache = ass_font_cache_init(library);
+ priv->cache.bitmap_cache = ass_bitmap_cache_init(library);
+ priv->cache.composite_cache = ass_composite_cache_init(library);
+ priv->cache.glyph_cache = ass_glyph_cache_init(library);
priv->text_info.max_glyphs = MAX_GLYPHS_INITIAL;
priv->text_info.max_lines = MAX_LINES_INITIAL;
ass_init_exit:
if (priv)
- ass_msg(MSGL_INFO, "Init");
+ ass_msg(library, MSGL_INFO, "Init");
else
- ass_msg(MSGL_ERR, "Init failed");
+ ass_msg(library, MSGL_ERR, "Init failed");
return priv;
}
tmp = dst_x - clip_x0;
if (tmp < 0) {
- ass_msg(MSGL_DBG2, "clip left");
+ ass_msg(render_priv->library, MSGL_DBG2, "clip left");
b_x0 = -tmp;
}
tmp = dst_y - clip_y0;
if (tmp < 0) {
- ass_msg(MSGL_DBG2, "clip top");
+ ass_msg(render_priv->library, MSGL_DBG2, "clip top");
b_y0 = -tmp;
}
tmp = clip_x1 - dst_x - bm->w;
if (tmp < 0) {
- ass_msg(MSGL_DBG2, "clip right");
+ ass_msg(render_priv->library, MSGL_DBG2, "clip right");
b_x1 = bm->w + tmp;
}
tmp = clip_y1 - dst_y - bm->h;
if (tmp < 0) {
- ass_msg(MSGL_DBG2, "clip bottom");
+ ass_msg(render_priv->library, MSGL_DBG2, "clip bottom");
b_y1 = bm->h + tmp;
}
memory, &render_priv->state.stroker);
#endif
if (error) {
- ass_msg(MSGL_V, "failed to get stroker");
+ ass_msg(render_priv->library, MSGL_V,
+ "failed to get stroker");
render_priv->state.stroker = 0;
}
}
mystrtoll(&p, &t1);
skip(',');
mystrtoll(&p, &t2);
- ass_msg(MSGL_DBG2,
+ ass_msg(render_priv->library, MSGL_DBG2,
"movement6: (%f, %f) -> (%f, %f), (%" PRId64 " .. %"
PRId64 ")\n", x1, y1, x2, y2, (int64_t) t1,
(int64_t) t2);
} else {
t1 = 0;
t2 = render_priv->state.event->Duration;
- ass_msg(MSGL_DBG2,
+ ass_msg(render_priv->library, MSGL_DBG2,
"movement: (%f, %f) -> (%f, %f)", x1, y1, x2, y2);
}
skip(')');
} else if (mystrcmp(&p, "alpha")) {
uint32_t val;
int i;
- if (strtocolor(&p, &val)) {
+ if (strtocolor(render_priv->library, &p, &val)) {
unsigned char a = val >> 24;
for (i = 0; i < 4; ++i)
change_alpha(&render_priv->state.c[i], a, pwr);
int val;
if (mystrtoi(&p, &val) && val) {
int v = (val - 1) / 3; // 0, 1 or 2 for vertical alignment
- ass_msg(MSGL_DBG2, "an %d", val);
+ ass_msg(render_priv->library, MSGL_DBG2, "an %d", val);
if (v != 0)
v = 3 - v;
val = ((val - 1) % 3) + 1; // horizontal alignment
val += v * 4;
- ass_msg(MSGL_DBG2, "align %d", val);
+ ass_msg(render_priv->library, MSGL_DBG2, "align %d", val);
render_priv->state.alignment = val;
} else
render_priv->state.alignment =
skip(',');
mystrtod(&p, &v2);
skip(')');
- ass_msg(MSGL_DBG2, "pos(%f, %f)", v1, v2);
+ ass_msg(render_priv->library, MSGL_DBG2, "pos(%f, %f)", v1, v2);
if (render_priv->state.evt_type == EVENT_POSITIONED) {
- ass_msg(MSGL_V, "Subtitle has a new \\pos "
+ ass_msg(render_priv->library, MSGL_V, "Subtitle has a new \\pos "
"after \\move or \\pos, ignoring");
} else {
render_priv->state.evt_type = EVENT_POSITIONED;
skip(',');
mystrtoi(&p, &v2);
skip(')');
- ass_msg(MSGL_DBG2, "org(%d, %d)", v1, v2);
+ ass_msg(render_priv->library, MSGL_DBG2, "org(%d, %d)", v1, v2);
if (!render_priv->state.have_origin) {
render_priv->state.org_x = v1;
render_priv->state.org_y = v2;
}
} else if (mystrcmp(&p, "c")) {
uint32_t val;
- if (!strtocolor(&p, &val))
+ if (!strtocolor(render_priv->library, &p, &val))
val = render_priv->state.style->PrimaryColour;
- ass_msg(MSGL_DBG2, "color: %X", val);
+ ass_msg(render_priv->library, MSGL_DBG2, "color: %X", val);
change_color(&render_priv->state.c[0], val, pwr);
} else if ((*p >= '1') && (*p <= '4') && (++p)
&& (mystrcmp(&p, "c") || mystrcmp(&p, "a"))) {
char cmd = *(p - 1);
uint32_t val;
assert((n >= '1') && (n <= '4'));
- if (!strtocolor(&p, &val))
+ if (!strtocolor(render_priv->library, &p, &val))
switch (n) {
case '1':
val = render_priv->state.style->PrimaryColour;
change_alpha(render_priv->state.c + cidx, val >> 24, pwr);
break;
default:
- ass_msg(MSGL_WARN, "Bad command: %c%c", n, cmd);
+ ass_msg(render_priv->library, MSGL_WARN, "Bad command: %c%c",
+ n, cmd);
break;
}
- ass_msg(MSGL_DBG2, "single c/a at %f: %c%c = %X",
+ ass_msg(render_priv->library, MSGL_DBG2, "single c/a at %f: %c%c = %X",
pwr, n, cmd, render_priv->state.c[cidx]);
} else if (mystrcmp(&p, "r")) {
reset_render_context(render_priv);
} else
break;
} else if (*p != '\\')
- ass_msg(MSGL_V, "Unable to parse: '%s'", p);
+ ass_msg(render_priv->library, MSGL_V,
+ "Unable to parse: '%s'", p);
if (*p == 0)
break;
}
if (strncmp(event->Effect, "Banner;", 7) == 0) {
int delay;
if (cnt < 1) {
- ass_msg(MSGL_V, "Error parsing effect: '%s'",
- event->Effect);
+ ass_msg(render_priv->library, MSGL_V,
+ "Error parsing effect: '%s'", event->Effect);
return;
}
if (cnt >= 2 && v[1] == 0) // right-to-left
} else if (strncmp(event->Effect, "Scroll down;", 12) == 0) {
render_priv->state.scroll_direction = SCROLL_TB;
} else {
- ass_msg(MSGL_V, "Unknown transition effect: '%s'",
- event->Effect);
+ ass_msg(render_priv->library, MSGL_V,
+ "Unknown transition effect: '%s'", event->Effect);
return;
}
// parse scroll up/down parameters
int delay;
int y0, y1;
if (cnt < 3) {
- ass_msg(MSGL_V, "Error parsing effect: '%s'",
- event->Effect);
+ ass_msg(render_priv->library, MSGL_V,
+ "Error parsing effect: '%s'", event->Effect);
return;
}
delay = v[2];
error = FT_Glyph_StrokeBorder((FT_Glyph *) glyph,
render_priv->state.stroker, 0, 1);
if (error)
- ass_msg(MSGL_WARN, "FT_Glyph_Stroke error: %d", error);
+ ass_msg(render_priv->library, MSGL_WARN,
+ "FT_Glyph_Stroke error: %d", error);
// "Stroke" with the outline emboldener in two passes.
// The outlines look uglier, but the emboldening never adds any points
-info->hash_key.advance.y);
// render glyph
- error = glyph_to_bitmap(render_priv->synth_priv,
+ error = glyph_to_bitmap(render_priv->library,
+ render_priv->synth_priv,
info->glyph, info->outline_glyph,
&info->bm, &info->bm_o,
&info->bm_s, info->be,
if (cur->symbol == '\n') {
break_type = 2;
break_at = i;
- ass_msg(MSGL_DBG2, "forced line break at %d",
- break_at);
+ ass_msg(render_priv->library, MSGL_DBG2,
+ "forced line break at %d", break_at);
}
if ((len >= max_text_width)
break_at = i - 1;
if (break_at == -1)
break_at = 0;
- ass_msg(MSGL_DBG2, "overfill at %d", i);
- ass_msg(MSGL_DBG2, "line break at %d", break_at);
+ ass_msg(render_priv->library, MSGL_DBG2, "overfill at %d", i);
+ ass_msg(render_priv->library, MSGL_DBG2, "line break at %d",
+ break_at);
}
if (break_at != -1) {
cur_line++;
pen_shift_x = d6_to_double(-cur->pos.x);
pen_shift_y += height + render_priv->settings.line_spacing;
- ass_msg(MSGL_DBG2,
+ ass_msg(render_priv->library, MSGL_DBG2,
"shifting from %d to %d by (%f, %f)", i,
text_info->length - 1, pen_shift_x, pen_shift_y);
}
dt /= (tm_end - tm_start);
x = x_start + (x_end - x_start) * dt;
} else {
- ass_msg(MSGL_ERR, "Unknown effect type");
+ ass_msg(render_priv->library, MSGL_ERR,
+ "Unknown effect type");
continue;
}
ass_drawing_t *drawing;
if (event->Style >= render_priv->track->n_styles) {
- ass_msg(MSGL_WARN, "No style found");
+ ass_msg(render_priv->library, MSGL_WARN, "No style found");
return 1;
}
if (!event->Text) {
- ass_msg(MSGL_WARN, "Empty event");
+ ass_msg(render_priv->library, MSGL_WARN, "Empty event");
return 1;
}
} else { // subtitle
double scr_y;
if (valign != VALIGN_SUB)
- ass_msg(MSGL_V,
+ ass_msg(render_priv->library, MSGL_V,
"Invalid valign, supposing 0 (subtitle)");
scr_y =
y2scr_sub(render_priv,
if (render_priv->state.evt_type == EVENT_POSITIONED) {
double base_x = 0;
double base_y = 0;
- ass_msg(MSGL_DBG2, "positioned event at %f, %f",
+ ass_msg(render_priv->library, MSGL_DBG2, "positioned event at %f, %f",
render_priv->state.pos_x, render_priv->state.pos_y);
get_base_point(&bbox, alignment, &base_x, &base_y);
device_x =
s.a = priv->top;
s.b = priv->top + priv->height;
if (priv->height != imgs[i].height) { // no, it's not
- ass_msg(MSGL_WARN, "Warning! Event height has changed");
+ ass_msg(render_priv->library, MSGL_WARN,
+ "Warning! Event height has changed");
priv->top = 0;
priv->height = 0;
}
#include "config.h"
#include <stdlib.h>
+#include <stdio.h>
#include <inttypes.h>
#include <ft2build.h>
#include FT_GLYPH_H
+#include "ass_library.h"
+#include "ass.h"
#include "ass_utils.h"
int mystrtoi(char **p, int *res)
return 0;
}
-int strtocolor(char **q, uint32_t *res)
+int strtocolor(ass_library_t *library, char **q, uint32_t *res)
{
uint32_t color = 0;
int result;
if (*p == '&')
++p;
else
- ass_msg(MSGL_DBG2, "suspicious color format: \"%s\"\n", p);
+ ass_msg(library, MSGL_DBG2, "suspicious color format: \"%s\"\n", p);
if (*p == 'H' || *p == 'h') {
++p;
return 0;
}
-void ass_msg(int lvl, char *fmt, ...)
+void ass_msg(ass_library_t *priv, int lvl, char *fmt, ...)
{
va_list va;
- if (lvl > MSGL_INFO)
- return;
va_start(va, fmt);
- printf("[ass] ");
- vprintf(fmt, va);
- printf("\n");
+ priv->msg_callback(lvl, fmt, &va);
va_end(va);
}
}
#ifdef CONFIG_ENCA
-void *ass_guess_buffer_cp(unsigned char *buffer, int buflen,
- char *preferred_language, char *fallback)
+void *ass_guess_buffer_cp(ass_library_t *library, unsigned char *buffer,
+ int buflen, char *preferred_language,
+ char *fallback)
{
const char **languages;
size_t langcnt;
int i;
languages = enca_get_languages(&langcnt);
- ass_msg(MSGL_V, "ENCA supported languages: ");
+ ass_msg(library, MSGL_V, "ENCA supported languages");
for (i = 0; i < langcnt; i++) {
- ass_msg(MSGL_V, "%s ", languages[i]);
+ ass_msg(library, MSGL_V, "lang %s", languages[i]);
}
- ass_msg(MSGL_V, "\n");
for (i = 0; i < langcnt; i++) {
const char *tmp;
tmp = enca_charset_name(encoding.charset, ENCA_NAME_STYLE_ICONV);
if (tmp && encoding.charset != ENCA_CS_UNKNOWN) {
detected_sub_cp = strdup(tmp);
- ass_msg(MSGL_INFO, "ENCA detected charset: %s\n", tmp);
+ ass_msg(library, MSGL_INFO, "ENCA detected charset: %s", tmp);
}
enca_analyser_free(analyser);
}
if (!detected_sub_cp) {
detected_sub_cp = strdup(fallback);
- ass_msg(MSGL_INFO,
- "ENCA detection failed: fallback to %s\n", fallback);
+ ass_msg(library, MSGL_INFO,
+ "ENCA detection failed: fallback to %s", fallback);
}
return detected_sub_cp;
#include <enca.h>
#endif
+#include "ass.h"
+
#define MSGL_FATAL 0
#define MSGL_ERR 1
#define MSGL_WARN 2
int mystrtoll(char **p, long long *res);
int mystrtou32(char **p, int base, uint32_t *res);
int mystrtod(char **p, double *res);
-int strtocolor(char **q, uint32_t *res);
+int strtocolor(ass_library_t *library, char **q, uint32_t *res);
char parse_bool(char *str);
unsigned ass_utf8_get_char(char **str);
-void ass_msg(int lvl, char *fmt, ...);
-void *ass_guess_buffer_cp(unsigned char *buffer, int buflen,
- char *preferred_language, char *fallback);
+void ass_msg(ass_library_t *priv, int lvl, char *fmt, ...);
+#ifdef CONFIG_ENCA
+void *ass_guess_buffer_cp(ass_library_t *library, unsigned char *buffer,
+ int buflen, char *preferred_language,
+ char *fallback);
+#endif
static inline int d6_to_int(int x)
{
ass_clear_fonts
ass_step_sub
ass_process_force_style
+ass_set_message_cb
#include <stdio.h>
#include <stdlib.h>
#include <stdexcept>
+#include <stdarg.h>
extern "C" {
#include <ass.h>
ass_library_t* ass_library;
ass_renderer_t* ass_renderer;
+void msg_callback(int level, char *fmt, va_list *va)
+{
+ if (level > 6)
+ return;
+ printf("libass: ");
+ vprintf(fmt, *va);
+ printf("\n");
+}
+
static void write_png(char *fname, image_t* img)
{
FILE * fp;
ass_set_fonts_dir(ass_library, "");
ass_set_extract_fonts(ass_library, 0);
ass_set_style_overrides(ass_library, NULL);
+ ass_set_message_cb(ass_library, msg_callback);
ass_renderer = ass_renderer_init(ass_library);
if (!ass_renderer) throw std::runtime_error("ass_renderer_init failed");