diff options
author | Uoti Urpala <uau@glyph.nonexistent.invalid> | 2009-07-25 07:24:39 +0300 |
---|---|---|
committer | Uoti Urpala <uau@glyph.nonexistent.invalid> | 2009-07-26 20:22:43 +0300 |
commit | 546c3fb53ce64fde5cba3e06012d244e73ae497a (patch) | |
tree | 8708989ac0b06edc091a71d73508ffc465fd669e | |
parent | 6fbcf16cfb0c6482bef87a0e8ac2162bca4cdbfd (diff) | |
download | mpv-546c3fb53ce64fde5cba3e06012d244e73ae497a.tar.bz2 mpv-546c3fb53ce64fde5cba3e06012d244e73ae497a.tar.xz |
Remove internal libass tree
Remove the libass/ directory and use the newest standalone version of
the library instead.
36 files changed, 430 insertions, 6839 deletions
@@ -125,15 +125,7 @@ SRCS_COMMON-$(LIBA52_INTERNAL) += liba52/crc.c \ liba52/imdct.c \ liba52/parse.c \ -SRCS_COMMON-$(LIBASS) += libass/ass.c \ - libass/ass_bitmap.c \ - libass/ass_cache.c \ - libass/ass_font.c \ - libass/ass_fontconfig.c \ - libass/ass_library.c \ - libass/ass_mp.c \ - libass/ass_render.c \ - libass/ass_utils.c \ +SRCS_COMMON-$(LIBASS) += ass_mp.c \ libmpcodecs/vf_ass.c \ SRCS_COMMON-$(LIBAVCODEC) += av_opts.c \ diff --git a/ass_mp.c b/ass_mp.c new file mode 100644 index 0000000000..207b0454d1 --- /dev/null +++ b/ass_mp.c @@ -0,0 +1,307 @@ +/* + * Copyright (C) 2006 Evgeniy Stepanov <eugeni.stepanov@gmail.com> + * + * This file is part of MPlayer. + * + * MPlayer is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * MPlayer is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with libass; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include <inttypes.h> +#include <string.h> +#include <stdlib.h> +#include <stdarg.h> + +#include <ass/ass.h> +#include <ass/ass_types.h> + +#include "mp_msg.h" +#include "get_path.h" +#include "ass_mp.h" +#include "subreader.h" + +#ifdef CONFIG_FONTCONFIG +#include <fontconfig/fontconfig.h> +#endif + +// libass-related command line options +ass_library_t *ass_library; +int ass_enabled = 0; +float ass_font_scale = 1.; +float ass_line_spacing = 0.; +int ass_top_margin = 0; +int ass_bottom_margin = 0; +#if defined(FC_VERSION) && (FC_VERSION >= 20402) +int extract_embedded_fonts = 1; +#else +int extract_embedded_fonts = 0; +#endif +char **ass_force_style_list = NULL; +int ass_use_margins = 0; +char *ass_color = NULL; +char *ass_border_color = NULL; +char *ass_styles_file = NULL; +int ass_hinting = ASS_HINTING_NATIVE + 4; // native hinting for unscaled osd + +#ifdef CONFIG_FONTCONFIG +extern int font_fontconfig; +#else +static int font_fontconfig = -1; +#endif +extern char *font_name; +extern char *sub_font_name; +extern float text_font_scale_factor; +extern int subtitle_autoscale; + +#ifdef CONFIG_ICONV +extern char *sub_cp; +#else +static char *sub_cp = 0; +#endif + +void process_force_style(ass_track_t *track); + +ass_track_t *ass_default_track(ass_library_t *library) +{ + ass_track_t *track = ass_new_track(library); + + track->track_type = TRACK_TYPE_ASS; + track->Timer = 100.; + track->PlayResY = 288; + track->WrapStyle = 0; + + if (ass_styles_file) + ass_read_styles(track, ass_styles_file, sub_cp); + + if (track->n_styles == 0) { + ass_style_t *style; + int sid; + double fs; + uint32_t c1, c2; + + sid = ass_alloc_style(track); + style = track->styles + sid; + style->Name = strdup("Default"); + style->FontName = (font_fontconfig >= 0 + && sub_font_name) ? strdup(sub_font_name) + : (font_fontconfig >= 0 + && font_name) ? strdup(font_name) : strdup("Sans"); + style->treat_fontname_as_pattern = 1; + + fs = track->PlayResY * text_font_scale_factor / 100.; + // approximate autoscale coefficients + if (subtitle_autoscale == 2) + fs *= 1.3; + else if (subtitle_autoscale == 3) + fs *= 1.4; + style->FontSize = fs; + + if (ass_color) + c1 = strtoll(ass_color, NULL, 16); + else + c1 = 0xFFFF0000; + if (ass_border_color) + c2 = strtoll(ass_border_color, NULL, 16); + else + c2 = 0x00000000; + + style->PrimaryColour = c1; + style->SecondaryColour = c1; + style->OutlineColour = c2; + style->BackColour = 0x00000000; + style->BorderStyle = 1; + style->Alignment = 2; + style->Outline = 2; + style->MarginL = 10; + style->MarginR = 10; + style->MarginV = 5; + style->ScaleX = 1.; + style->ScaleY = 1.; + } + + ass_process_force_style(track); + return track; +} + +static int check_duplicate_plaintext_event(ass_track_t *track) +{ + int i; + ass_event_t *evt = track->events + track->n_events - 1; + + for (i = 0; i < track->n_events - 1; ++i) // ignoring last event, it is the one we are comparing with + if (track->events[i].Start == evt->Start && + track->events[i].Duration == evt->Duration && + strcmp(track->events[i].Text, evt->Text) == 0) + return 1; + return 0; +} + +/** + * \brief Convert subtitle to ass_event_t for the given track + * \param ass_track_t track + * \param sub subtitle to convert + * \return event id + * note: assumes that subtitle is _not_ fps-based; caller must manually correct + * Start and Duration in other case. + **/ +int ass_process_subtitle(ass_track_t *track, subtitle *sub) +{ + int eid; + ass_event_t *event; + int len = 0, j; + char *p; + char *end; + + eid = ass_alloc_event(track); + event = track->events + eid; + + event->Start = sub->start * 10; + event->Duration = (sub->end - sub->start) * 10; + event->Style = 0; + + for (j = 0; j < sub->lines; ++j) + len += sub->text[j] ? strlen(sub->text[j]) : 0; + + len += 2 * sub->lines; // '\N', including the one after the last line + len += 6; // {\anX} + len += 1; // '\0' + + event->Text = malloc(len); + end = event->Text + len; + p = event->Text; + + if (sub->alignment) + p += snprintf(p, end - p, "{\\an%d}", sub->alignment); + + for (j = 0; j < sub->lines; ++j) + p += snprintf(p, end - p, "%s\\N", sub->text[j]); + + if (sub->lines > 0) + p -= 2; // remove last "\N" + *p = 0; + + if (check_duplicate_plaintext_event(track)) { + ass_free_event(track, eid); + track->n_events--; + return -1; + } + + mp_msg(MSGT_ASS, MSGL_V, + "plaintext event at %" PRId64 ", +%" PRId64 ": %s \n", + (int64_t) event->Start, (int64_t) event->Duration, event->Text); + + return eid; +} + + +/** + * \brief Convert subdata to ass_track + * \param subdata subtitles struct from subreader + * \param fps video framerate + * \return newly allocated ass_track, filled with subtitles from subdata + */ +ass_track_t *ass_read_subdata(ass_library_t *library, sub_data *subdata, + double fps) +{ + ass_track_t *track; + int i; + + track = ass_default_track(library); + track->name = subdata->filename ? strdup(subdata->filename) : 0; + + for (i = 0; i < subdata->sub_num; ++i) { + int eid = ass_process_subtitle(track, subdata->subtitles + i); + if (eid < 0) + continue; + if (!subdata->sub_uses_time) { + track->events[eid].Start *= 100. / fps; + track->events[eid].Duration *= 100. / fps; + } + } + return track; +} + +void ass_configure(ass_renderer_t *priv, int w, int h, int unscaled) +{ + int hinting; + ass_set_frame_size(priv, w, h); + ass_set_margins(priv, ass_top_margin, ass_bottom_margin, 0, 0); + ass_set_use_margins(priv, ass_use_margins); + ass_set_font_scale(priv, ass_font_scale); + if (!unscaled && (ass_hinting & 4)) + hinting = 0; + else + hinting = ass_hinting & 3; + ass_set_hinting(priv, hinting); + ass_set_line_spacing(priv, ass_line_spacing); +} + +void ass_configure_fonts(ass_renderer_t *priv) +{ + char *dir, *path, *family; + dir = get_path("fonts"); + if (font_fontconfig < 0 && sub_font_name) + path = strdup(sub_font_name); + else if (font_fontconfig < 0 && font_name) + path = strdup(font_name); + else + path = get_path("subfont.ttf"); + if (font_fontconfig >= 0 && sub_font_name) + family = strdup(sub_font_name); + else if (font_fontconfig >= 0 && font_name) + family = strdup(font_name); + else + family = 0; + + ass_set_fonts(priv, path, family, font_fontconfig + 1, NULL, 1); + + free(dir); + free(path); + free(family); +} + +static void message_callback(int level, const char *format, va_list va, void *ctx) +{ + mp_msg(MSGT_ASS, level, "[ass] "); + mp_msg_va(MSGT_ASS, level, format, va); + // libass messages lack trailing \n + mp_msg(MSGT_ASS, level, "\n"); +} + +ass_library_t *ass_init(void) +{ + ass_library_t *priv; + char *path = get_path("fonts"); + priv = ass_library_init(); + ass_set_message_cb(priv, message_callback, NULL); + ass_set_fonts_dir(priv, path); + ass_set_extract_fonts(priv, extract_embedded_fonts); + ass_set_style_overrides(priv, ass_force_style_list); + free(path); + return priv; +} + +int ass_force_reload = 0; // flag set if global ass-related settings were changed + +ass_image_t *ass_mp_render_frame(ass_renderer_t *priv, ass_track_t *track, + long long now, int *detect_change) +{ + if (ass_force_reload) { + ass_set_margins(priv, ass_top_margin, ass_bottom_margin, 0, 0); + ass_set_use_margins(priv, ass_use_margins); + ass_set_font_scale(priv, ass_font_scale); + ass_force_reload = 0; + } + return ass_render_frame(priv, track, now, detect_change); +} diff --git a/ass_mp.h b/ass_mp.h new file mode 100644 index 0000000000..0b335b9921 --- /dev/null +++ b/ass_mp.h @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2006 Evgeniy Stepanov <eugeni.stepanov@gmail.com> + * + * This file is part of MPlayer. + * + * MPlayer is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * MPlayer is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with libass; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef MPLAYER_ASS_MP_H +#define MPLAYER_ASS_MP_H + +#include <stdint.h> + +#include "ass_mp.h" + +#include "subreader.h" + +#ifdef CONFIG_ASS +#include <ass/ass.h> +#include <ass/ass_types.h> + +extern ass_library_t *ass_library; +extern int ass_enabled; +extern float ass_font_scale; +extern float ass_line_spacing; +extern int ass_top_margin; +extern int ass_bottom_margin; +extern int extract_embedded_fonts; +extern char **ass_force_style_list; +extern int ass_use_margins; +extern char *ass_color; +extern char *ass_border_color; +extern char *ass_styles_file; +extern int ass_hinting; + +ass_track_t *ass_default_track(ass_library_t *library); +int ass_process_subtitle(ass_track_t *track, subtitle *sub); +ass_track_t *ass_read_subdata(ass_library_t *library, sub_data *subdata, + double fps); + +void ass_configure(ass_renderer_t *priv, int w, int h, int hinting); +void ass_configure_fonts(ass_renderer_t *priv); +ass_library_t *ass_init(void); + +extern int ass_force_reload; +ass_image_t *ass_mp_render_frame(ass_renderer_t *priv, ass_track_t *track, + long long now, int *detect_change); + +#else /* CONFIG_ASS */ + +/* Needed for EOSD code using this type to compile */ + +typedef struct ass_image { + int w, h; + int stride; + unsigned char *bitmap; + uint32_t color; + int dst_x, dst_y; + struct ass_image *next; +} ass_image_t; + +#endif + +typedef struct { + ass_image_t *imgs; + int changed; +} mp_eosd_images_t; + + +#endif /* MPLAYER_ASS_MP_H */ @@ -31,6 +31,7 @@ #include "vobsub.h" #include "spudec.h" #include "get_path.h" +#include "ass_mp.h" #ifdef CONFIG_TV #include "stream/tv.h" #endif @@ -49,10 +50,6 @@ #ifdef CONFIG_DVDNAV #include "stream/stream_dvdnav.h" #endif -#ifdef CONFIG_ASS -#include "libass/ass.h" -#include "libass/ass_mp.h" -#endif #ifdef CONFIG_MENU #include "m_struct.h" #include "libmenu/menu.h" @@ -6092,29 +6092,16 @@ echores "$_fontconfig" echocheck "SSA/ASS support" -# libass depends on FreeType -if test "$_freetype" = no ; then - _ass=no - _res_comment="FreeType support needed" -fi - -if test "$_ass" = auto ; then - cat > $TMPC << EOF -#include <ft2build.h> -#include FT_FREETYPE_H -#if ((FREETYPE_MAJOR < 2) || (FREETYPE_MINOR < 1) || ((FREETYPE_MINOR == 1) && (FREETYPE_PATCH < 8))) -#error "Need FreeType 2.1.8 or newer" -#endif -int main(void) { return 0; } -EOF - _ass=no - cc_check $($_freetypeconfig --cflags) $($_freetypeconfig --libs) && tmp_run && _ass=yes - if test "$_ass" = no ; then - _res_comment="FreeType >= 2.1.8 needed" - fi -fi -if test "$_ass" = yes ; then - def_ass='#define CONFIG_ASS' +if test "$_ass" = auto -o "$_ass" = yes ; then + if $_pkg_config libass; then + _ass=yes + def_ass='#define CONFIG_ASS' + extra_ldflags="$extra_ldflags $($_pkg_config --libs libass)" + extra_cflags="$extra_cflags $($_pkg_config --cflags libass)" + else + _ass=no + def_ass='#undef CONFIG_ASS' + fi else def_ass='#undef CONFIG_ASS' fi diff --git a/libass/ass.c b/libass/ass.c deleted file mode 100644 index 5e9e82c2c4..0000000000 --- a/libass/ass.c +++ /dev/null @@ -1,1134 +0,0 @@ -// -*- c-basic-offset: 8; indent-tabs-mode: t -*- -// vim:ts=8:sw=8:noet:ai: -/* - * Copyright (C) 2006 Evgeniy Stepanov <eugeni.stepanov@gmail.com> - * - * This file is part of libass. - * - * libass is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * libass is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with libass; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "config.h" - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <assert.h> -#include <errno.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <unistd.h> -#include <inttypes.h> - -#ifdef CONFIG_ICONV -#include <iconv.h> -#endif - -#include "ass.h" -#include "ass_utils.h" -#include "ass_library.h" -#include "mputils.h" - -typedef enum {PST_UNKNOWN = 0, PST_INFO, PST_STYLES, PST_EVENTS, PST_FONTS} parser_state_t; - -struct parser_priv_s { - parser_state_t state; - char* fontname; - char* fontdata; - int fontdata_size; - int fontdata_used; -}; - -#define ASS_STYLES_ALLOC 20 -#define ASS_EVENTS_ALLOC 200 - -void ass_free_track(ass_track_t* track) { - int i; - - if (track->parser_priv) { - if (track->parser_priv->fontname) - free(track->parser_priv->fontname); - if (track->parser_priv->fontdata) - free(track->parser_priv->fontdata); - free(track->parser_priv); - } - if (track->style_format) - free(track->style_format); - if (track->event_format) - free(track->event_format); - if (track->styles) { - for (i = 0; i < track->n_styles; ++i) - ass_free_style(track, i); - free(track->styles); - } - if (track->events) { - for (i = 0; i < track->n_events; ++i) - ass_free_event(track, i); - free(track->events); - } -} - -/// \brief Allocate a new style struct -/// \param track track -/// \return style id -int ass_alloc_style(ass_track_t* track) { - int sid; - - assert(track->n_styles <= track->max_styles); - - if (track->n_styles == track->max_styles) { - track->max_styles += ASS_STYLES_ALLOC; - track->styles = (ass_style_t*)realloc(track->styles, sizeof(ass_style_t)*track->max_styles); - } - - sid = track->n_styles++; - memset(track->styles + sid, 0, sizeof(ass_style_t)); - return sid; -} - -/// \brief Allocate a new event struct -/// \param track track -/// \return event id -int ass_alloc_event(ass_track_t* track) { - int eid; - - assert(track->n_events <= track->max_events); - - if (track->n_events == track->max_events) { - track->max_events += ASS_EVENTS_ALLOC; - track->events = (ass_event_t*)realloc(track->events, sizeof(ass_event_t)*track->max_events); - } - - eid = track->n_events++; - memset(track->events + eid, 0, sizeof(ass_event_t)); - return eid; -} - -void ass_free_event(ass_track_t* track, int eid) { - ass_event_t* event = track->events + eid; - if (event->Name) - free(event->Name); - if (event->Effect) - free(event->Effect); - if (event->Text) - free(event->Text); - if (event->render_priv) - free(event->render_priv); -} - -void ass_free_style(ass_track_t* track, int sid) { - ass_style_t* style = track->styles + sid; - if (style->Name) - free(style->Name); - if (style->FontName) - free(style->FontName); -} - -// ============================================================================================== - -static void skip_spaces(char** str) { - char* p = *str; - while ((*p==' ') || (*p=='\t')) - ++p; - *str = p; -} - -static void rskip_spaces(char** str, char* limit) { - char* p = *str; - while ((p >= limit) && ((*p==' ') || (*p=='\t'))) - --p; - *str = p; -} - -/** - * \brief find style by name - * \param track track - * \param name style name - * \return index in track->styles - * Returnes 0 if no styles found => expects at least 1 style. - * Parsing code always adds "Default" style in the end. - */ -static int lookup_style(ass_track_t* track, char* name) { - int i; - if (*name == '*') ++name; // FIXME: what does '*' really mean ? - for (i = track->n_styles - 1; i >= 0; --i) { - // FIXME: mb strcasecmp ? - if (strcmp(track->styles[i].Name, name) == 0) - return i; - } - i = track->default_style; - mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_NoStyleNamedXFoundUsingY, track, name, track->styles[i].Name); - return i; // use the first style -} - -static uint32_t string2color(char* p) { - uint32_t tmp; - (void)strtocolor(&p, &tmp); - return tmp; -} - -static long long string2timecode(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) { - mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_BadTimestamp); - return 0; - } - tm = ((h * 60 + m) * 60 + s) * 1000 + ms * 10; - return tm; -} - -/** - * \brief converts numpad-style align to align. - */ -static int numpad2align(int val) { - int res, v; - v = (val - 1) / 3; // 0, 1 or 2 for vertical alignment - if (v != 0) v = 3 - v; - res = ((val - 1) % 3) + 1; // horizontal alignment - res += v*4; - return res; -} - -#define NEXT(str,token) \ - token = next_token(&str); \ - if (!token) break; - -#define ANYVAL(name,func) \ - } else if (strcasecmp(tname, #name) == 0) { \ - target->name = func(token); \ - mp_msg(MSGT_ASS, MSGL_DBG2, "%s = %s\n", #name, token); - -#define STRVAL(name) \ - } else if (strcasecmp(tname, #name) == 0) { \ - if (target->name != NULL) free(target->name); \ - target->name = strdup(token); \ - mp_msg(MSGT_ASS, MSGL_DBG2, "%s = %s\n", #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 STYLEVAL(name) \ - } else if (strcasecmp(tname, #name) == 0) { \ - target->name = lookup_style(track, token); \ - mp_msg(MSGT_ASS, MSGL_DBG2, "%s = %s\n", #name, token); - -#define ALIAS(alias,name) \ - if (strcasecmp(tname, #alias) == 0) {tname = #name;} - -static char* next_token(char** str) { - char* p = *str; - char* start; - skip_spaces(&p); - if (*p == '\0') { - *str = p; - return 0; - } - start = p; // start of the token - for (; (*p != '\0') && (*p != ','); ++p) {} - if (*p == '\0') { - *str = p; // eos found, str will point to '\0' at exit - } else { - *p = '\0'; - *str = p + 1; // ',' found, str will point to the next char (beginning of the next token) - } - --p; // end of current token - rskip_spaces(&p, start); - if (p < start) - p = start; // empty token - else - ++p; // the first space character, or '\0' - *p = '\0'; - return start; -} -/** - * \brief Parse the tail of Dialogue line - * \param track track - * \param event parsed data goes here - * \param str string to parse, zero-terminated - * \param n_ignored number of format options to skip at the beginning -*/ -static int process_event_tail(ass_track_t* track, ass_event_t* event, char* str, int n_ignored) -{ - char* token; - char* tname; - char* p = str; - int i; - ass_event_t* target = event; - - char* format = strdup(track->event_format); - char* q = format; // format scanning pointer - - if (track->n_styles == 0) { - // add "Default" style to the end - // will be used if track does not contain a default style (or even does not contain styles at all) - int sid = ass_alloc_style(track); - track->styles[sid].Name = strdup("Default"); - track->styles[sid].FontName = strdup("Arial"); - } - - for (i = 0; i < n_ignored; ++i) { - NEXT(q, tname); - } - - while (1) { - NEXT(q, tname); - if (strcasecmp(tname, "Text") == 0) { - char* last; - event->Text = strdup(p); - if (*event->Text != 0) { - last = event->Text + strlen(event->Text) - 1; - if (last >= event->Text && *last == '\r') - *last = 0; - } - mp_msg(MSGT_ASS, MSGL_DBG2, "Text = %s\n", event->Text); - event->Duration -= event->Start; - free(format); - return 0; // "Text" is always the last - } - NEXT(p, token); - - ALIAS(End,Duration) // temporarily store end timecode in event->Duration - if (0) { // cool ;) - INTVAL(Layer) - STYLEVAL(Style) - STRVAL(Name) - STRVAL(Effect) - INTVAL(MarginL) - INTVAL(MarginR) - INTVAL(MarginV) - TIMEVAL(Start) - TIMEVAL(Duration) - } - } - free(format); - return 1; -} - -/** - * \brief Parse command line style overrides (--ass-force-style option) - * \param track track to apply overrides to - * The format for overrides is [StyleName.]Field=Value - */ -void process_force_style(ass_track_t* track) { - char **fs, *eq, *dt, *style, *tname, *token; - ass_style_t* target; - int sid; - char** list = track->library->style_overrides; - - if (!list) return; - - for (fs = list; *fs; ++fs) { - eq = strrchr(*fs, '='); - if (!eq) - continue; - *e |