diff options
-rw-r--r-- | Makefile | 3 | ||||
-rw-r--r-- | libass/ass.c | 1804 | ||||
-rw-r--r-- | libass/ass.h | 307 | ||||
-rw-r--r-- | libass/ass_bitmap.c | 720 | ||||
-rw-r--r-- | libass/ass_bitmap.h | 30 | ||||
-rw-r--r-- | libass/ass_cache.c | 440 | ||||
-rw-r--r-- | libass/ass_cache.h | 190 | ||||
-rw-r--r-- | libass/ass_cache_template.h | 122 | ||||
-rw-r--r-- | libass/ass_drawing.c | 495 | ||||
-rw-r--r-- | libass/ass_drawing.h | 77 | ||||
-rw-r--r-- | libass/ass_font.c | 673 | ||||
-rw-r--r-- | libass/ass_font.h | 60 | ||||
-rw-r--r-- | libass/ass_fontconfig.c | 751 | ||||
-rw-r--r-- | libass/ass_fontconfig.h | 20 | ||||
-rw-r--r-- | libass/ass_library.c | 146 | ||||
-rw-r--r-- | libass/ass_library.h | 30 | ||||
-rw-r--r-- | libass/ass_parse.c | 926 | ||||
-rw-r--r-- | libass/ass_parse.h | 38 | ||||
-rw-r--r-- | libass/ass_render.c | 4661 | ||||
-rw-r--r-- | libass/ass_render.h | 262 | ||||
-rw-r--r-- | libass/ass_strtod.c | 247 | ||||
-rw-r--r-- | libass/ass_types.h | 172 | ||||
-rw-r--r-- | libass/ass_utils.c | 236 | ||||
-rw-r--r-- | libass/ass_utils.h | 139 |
24 files changed, 7767 insertions, 4782 deletions
@@ -122,10 +122,13 @@ SRCS_COMMON-$(LIBASS) += libmpcodecs/vf_ass.c \ SRCS_COMMON-$(LIBASS_INTERNAL) += libass/ass.c \ libass/ass_bitmap.c \ libass/ass_cache.c \ + libass/ass_drawing.c \ libass/ass_font.c \ libass/ass_fontconfig.c \ libass/ass_library.c \ + libass/ass_parse.c \ libass/ass_render.c \ + libass/ass_strtod.c \ libass/ass_utils.c \ SRCS_COMMON-$(LIBAVCODEC) += av_opts.c \ diff --git a/libass/ass.c b/libass/ass.c index 370063aacf..6becb39e8e 100644 --- a/libass/ass.c +++ b/libass/ass.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> * @@ -39,117 +37,137 @@ #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; +typedef enum { + PST_UNKNOWN = 0, + PST_INFO, + PST_STYLES, + PST_EVENTS, + PST_FONTS +} ParserState; + +struct parser_priv { + ParserState 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); - } +void ass_free_track(ASS_Track *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); + } + free(track->name); + free(track); } /// \brief Allocate a new style struct /// \param track track /// \return style id -int ass_alloc_style(ass_track_t* track) { - int sid; +int ass_alloc_style(ASS_Track *track) +{ + int sid; - assert(track->n_styles <= track->max_styles); + 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); - } + if (track->n_styles == track->max_styles) { + track->max_styles += ASS_STYLES_ALLOC; + track->styles = + (ASS_Style *) realloc(track->styles, + sizeof(ASS_Style) * + track->max_styles); + } - sid = track->n_styles++; - memset(track->styles + sid, 0, sizeof(ass_style_t)); - return sid; + sid = track->n_styles++; + memset(track->styles + sid, 0, sizeof(ASS_Style)); + return sid; } /// \brief Allocate a new event struct /// \param track track /// \return event id -int ass_alloc_event(ass_track_t* track) { - int eid; +int ass_alloc_event(ASS_Track *track) +{ + int eid; - assert(track->n_events <= track->max_events); + 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); - } + if (track->n_events == track->max_events) { + track->max_events += ASS_EVENTS_ALLOC; + track->events = + (ASS_Event *) realloc(track->events, + sizeof(ASS_Event) * + track->max_events); + } - eid = track->n_events++; - memset(track->events + eid, 0, sizeof(ass_event_t)); - return eid; + eid = track->n_events++; + memset(track->events + eid, 0, sizeof(ASS_Event)); + 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_event(ASS_Track *track, int eid) +{ + ASS_Event *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); +void ass_free_style(ASS_Track *track, int sid) +{ + ASS_Style *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 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; +static void rskip_spaces(char **str, char *limit) +{ + char *p = *str; + while ((p >= limit) && ((*p == ' ') || (*p == '\t'))) + --p; + *str = p; } /** @@ -160,47 +178,55 @@ static void rskip_spaces(char** str, char* limit) { * 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 int lookup_style(ASS_Track *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; + 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) { - uint32_t tmp; - (void)strtocolor(&p, &tmp); - return tmp; +static uint32_t string2color(ASS_Library *library, char *p) +{ + uint32_t tmp; + (void) strtocolor(library, &p, &tmp, 0); + 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; +static long long string2timecode(ASS_Library *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(library, MSGL_WARN, "Bad timestamp"); + 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; +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) \ @@ -210,51 +236,62 @@ static int numpad2align(int val) { #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); + 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); \ - mp_msg(MSGT_ASS, MSGL_DBG2, "%s = %s\n", #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); \ - mp_msg(MSGT_ASS, MSGL_DBG2, "%s = %s\n", #name, token); + ass_msg(track->library, MSGL_DBG2, "%s = %s", #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; +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 @@ -262,68 +299,62 @@ static char* next_token(char** str) { * \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) +static int process_event_tail(ASS_Track *track, ASS_Event *event, + char *str, int n_ignored) { - char* token; - char* tname; - char* p = str; - int i; - ass_event_t* target = event; - - char* format; - char* q; // format scanning pointer - - if (!track->event_format) { - track->event_format = strdup("Format: Marked, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text"); - mp_msg(MSGT_ASS, MSGL_V, "Event format is broken, reseting to defaults.\n"); - } - - q = format = strdup(track->event_format); - - 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; + char *token; + char *tname; + char *p = str; + int i; + ASS_Event *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; + } + ass_msg(track->library, MSGL_DBG2, "Text = %s", 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; } /** @@ -331,73 +362,79 @@ static int process_event_tail(ass_track_t* track, ass_event_t* event, char* str, * \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; - *eq = '\0'; - token = eq + 1; - - if(!strcasecmp(*fs, "PlayResX")) - track->PlayResX = atoi(token); - else if(!strcasecmp(*fs, "PlayResY")) - track->PlayResY = atoi(token); - else if(!strcasecmp(*fs, "Timer")) - track->Timer = atof(token); - else if(!strcasecmp(*fs, "WrapStyle")) - track->WrapStyle = atoi(token); - else if(!strcasecmp(*fs, "ScaledBorderAndShadow")) - track->ScaledBorderAndShadow = parse_bool(token); - - dt = strrchr(*fs, '.'); - if (dt) { - *dt = '\0'; - style = *fs; - tname = dt + 1; - } else { - style = NULL; - tname = *fs; - } - for (sid = 0; sid < track->n_styles; ++sid) { - if (style == NULL || strcasecmp(track->styles[sid].Name, style) == 0) { - target = track->styles + sid; - if (0) { - STRVAL(FontName) - COLORVAL(PrimaryColour) - COLORVAL(SecondaryColour) - COLORVAL(OutlineColour) - COLORVAL(BackColour) - FPVAL(FontSize) - INTVAL(Bold) - INTVAL(Italic) - INTVAL(Underline) - INTVAL(StrikeOut) - FPVAL(Spacing) - INTVAL(Angle) - INTVAL(BorderStyle) - INTVAL(Alignment) - INTVAL(MarginL) - INTVAL(MarginR) - INTVAL(MarginV) - INTVAL(Encoding) - FPVAL(ScaleX) - FPVAL(ScaleY) - FPVAL(Outline) - FPVAL(Shadow) - } - } - } - *eq = '='; - if (dt) *dt = '.'; - } +void ass_process_force_style(ASS_Track *track) +{ + char **fs, *eq, *dt, *style, *tname, *token; + ASS_Style *target; + int sid; + char **list = track->library->style_overrides; + + if (!list) + return; + + for (fs = list; *fs; ++fs) { + eq = strrchr(*fs, '='); + if (!eq) + continue; + *eq = '\0'; + token = eq + 1; + + if (!strcasecmp(*fs, "PlayResX")) + track->PlayResX = atoi(token); + else if (!strcasecmp(*fs, "PlayResY")) + track->PlayResY = atoi(token); + else if (!strcasecmp(*fs, "Timer")) + track->Timer = atof(token); + else if (!strcasecmp(*fs, "WrapStyle")) + track->WrapStyle = atoi(token); + else if (!strcasecmp(*fs, "ScaledBorderAndShadow")) + track->ScaledBorderAndShadow = parse_bool(token); + else if (!strcasecmp(*fs, "Kerning")) + track->Kerning = parse_bool(token); + + dt = strrchr(*fs, '.'); + if (dt) { + *dt = '\0'; + style = *fs; + tname = dt + 1; + } else { + style = NULL; + tname = *fs; + } + for (sid = 0; sid < track->n_styles; ++sid) { + if (style == NULL + || strcasecmp(track->styles[sid].Name, style) == 0) { + target = track->styles + sid; + if (0) { + STRVAL(FontName) + COLORVAL(PrimaryColour) + COLORVAL(SecondaryColour) + COLORVAL(OutlineColour) + COLORVAL(BackColour) + FPVAL(FontSize) + INTVAL(Bold) + INTVAL(Italic) + INTVAL(Underline) + INTVAL(StrikeOut) + FPVAL(Spacing) + INTVAL(Angle) + INTVAL(BorderStyle) + INTVAL(Alignment) + INTVAL(MarginL) + INTVAL(MarginR) + INTVAL(MarginV) + INTVAL(Encoding) + FPVAL(ScaleX) + FPVAL(ScaleY) + FPVAL(Outline) + FPVAL(Shadow) + } + } + } + *eq = '='; + if (dt) + *dt = '.'; + } } /** @@ -406,257 +443,294 @@ void process_force_style(ass_track_t* track) { * \param str string to parse, zero-terminated * Allocates a new style struct. */ -static int process_style(ass_track_t* track, char *str) +static int process_style(ASS_Track *track, char *str) { - char* token; - char* tname; - char* p = str; - char* format; - char* q; // format scanning pointer - int sid; - ass_style_t* style; - ass_style_t* target; - - if (!track->style_format) { - // no style format header - // probably an ancient script version - if (track->track_type == TRACK_TYPE_SSA) - track->style_format = strdup("Name, Fontname, Fontsize, PrimaryColour, SecondaryColour," - "TertiaryColour, BackColour, Bold, Italic, BorderStyle, Outline," - "Shadow, Alignment, MarginL, MarginR, MarginV, AlphaLevel, Encoding"); - else - track->style_format = strdup("Name, Fontname, Fontsize, PrimaryColour, SecondaryColour," - "OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut," - "ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow," - "Alignment, MarginL, MarginR, MarginV, Encoding"); - } - - q = format = strdup(track->style_format); - - mp_msg(MSGT_ASS, MSGL_V, "[%p] Style: %s\n", track, str); - - sid = ass_alloc_style(track); - - style = track->styles + sid; - target = style; -// fill style with some default values - style->ScaleX = 100.; - style->ScaleY = 100.; - - while (1) { - NEXT(q, tname); - NEXT(p, token); - -// ALIAS(TertiaryColour,OutlineColour) // ignore TertiaryColour; it appears only in SSA, and is overridden by BackColour - - if (0) { // cool ;) - STRVAL(Name) - if ((strcmp(target->Name, "Default")==0) || (strcmp(target->Name, "*Default")==0)) - track->default_style = sid; - STRVAL(FontName) - COLORVAL(PrimaryColour) - COLORVAL(SecondaryColour) - COLORVAL(OutlineColour) // TertiaryColor - COLORVAL(BackColour) - // SSA uses BackColour for both outline and shadow - // this will destroy SSA's TertiaryColour, but i'm not going to use it anyway - if (track->track_type == TRACK_TYPE_SSA) - target->OutlineColour = target->BackColour; - FPVAL(FontSize) - INTVAL(Bold) - INTVAL(Italic) - INTVAL(Underline) - INTVAL(StrikeOut) - FPVAL(Spacing) - INTVAL(Angle) - INTVAL(BorderStyle) - INTVAL(Alignment) - if (track->track_type == TRACK_TYPE_ASS) - target->Alignment = numpad2align(target->Alignment); - INTVAL(MarginL) - INTVAL(MarginR) - INTVAL(MarginV) - INTVAL(Encoding) - FPVAL(ScaleX) - FPVAL(ScaleY) - FPVAL(Outline) - FPVAL(Shadow) - } - } - style->ScaleX /= 100.; - style->ScaleY /= 100.; - style->Bold = !!style->Bold; - style->Italic = !!style->Italic; - style->Underline = !!style->Underline; - if (!style->Name) - style->Name = strdup("Default"); - if (!style->FontName) - style->FontName = strdup("Arial"); - // skip '@' at the start of the font name - if (*style->FontName == '@') { - p = style->FontName; - style->FontName = strdup(p + 1); - free(p); - } - free(format); - return 0; + char *token; + char *tname; + char *p = str; + char *format; + char *q; // format scanning pointer + int sid; + ASS_Style *style; + ASS_Style *target; + + if (!track->style_format) { + // no style format header + // probably an ancient script version + if (track->track_type == TRACK_TYPE_SSA) + track->style_format = + strdup + ("Name, Fontname, Fontsize, PrimaryColour, SecondaryColour," + "TertiaryColour, BackColour, Bold, Italic, BorderStyle, Outline," + "Shadow, Alignment, MarginL, MarginR, MarginV, AlphaLevel, Encoding"); + else + track->style_format = + strdup + ("Name, Fontname, Fontsize, PrimaryColour, SecondaryColour," + "OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut," + "ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow," + "Alignment, MarginL, MarginR, MarginV, Encoding"); + } + + q = format = strdup(track->style_format); + + ass_msg(track->library, MSGL_V, "[%p] Style: %s", track, str); + + sid = ass_alloc_style(track); + + style = track->styles + sid; + target = style; + + // fill style with some default values + style->ScaleX = 100.; + style->ScaleY = 100.; + + while (1) { + NEXT(q, tname); + NEXT(p, token); + + if (0) { // cool ;) + STRVAL(Name) + if ((strcmp(target->Name, "Default") == 0) + || (strcmp(target->Name, "*Default") == 0)) + track->default_style = sid; + STRVAL(FontName) + COLORVAL(PrimaryColour) + COLORVAL(SecondaryColour) + COLORVAL(OutlineColour) // TertiaryColor + COLORVAL(BackColour) + // SSA uses BackColour for both outline and shadow + // this will destroy SSA's TertiaryColour, but i'm not going to use it anyway + if (track->track_type == TRACK_TYPE_SSA) + target->OutlineColour = target->BackColour; + FPVAL(FontSize) + INTVAL(Bold) + INTVAL(Italic) + INTVAL(Underline) + INTVAL(StrikeOut) + FPVAL(Spacing) + INTVAL(Angle) + INTVAL(BorderStyle) + INTVAL(Alignment) + if (track->track_type == TRACK_TYPE_ASS) + target->Alignment = numpad2align(target->Alignment); + INTVAL(MarginL) + INTVAL(MarginR) + INTVAL(MarginV) + INTVAL(Encoding) + FPVAL(ScaleX) + FPVAL(ScaleY) + FPVAL(Outline) + FPVAL(Shadow) + } + } + style->ScaleX /= 100.; + style->ScaleY /= 100.; + style->Bold = !!style->Bold; + style->Italic = !!style->Italic; + style->Underline = !!style->Underline; + if (!style->Name) + style->Name = strdup("Default"); + if (!style->FontName) + style->FontName = strdup("Arial"); + // skip '@' at the start of the font name + if (*style->FontName == '@') { + p = style->FontName; + style->FontName = strdup(p + 1); + free(p); + } + free(format); + return 0; } -static int process_styles_line(ass_track_t* track, char *str) +static int process_styles_line(ASS_Track *track, char *str) { - if (!strncmp(str,"Format:", 7)) { - char* p = str + 7; - skip_spaces(&p); - track->style_format = strdup(p); - mp_msg(MSGT_ASS, MSGL_DBG2, "Style format: %s\n", track->style_format); - } else if (!strncmp(str,"Style:", 6)) { - char* p = str + 6; - skip_spaces(&p); - process_style(track, p); - } - return 0; + if (!strncmp(str, "Format:", 7)) { + char *p = str + 7; + skip_spaces(&p); + track->style_format = strdup(p); + ass_msg(track->library, MSGL_DBG2, "Style format: %s", + track->style_format); + } else if (!strncmp(str, "Style:", 6)) { + char *p = str + 6; + skip_spaces(&p); + process_style(track, p); + } + return 0; } -static int process_info_line(ass_track_t* track, char *str) +static int process_info_line(ASS_Track *track, char *str) { - if (!strncmp(str, "PlayResX:", 9)) { - |