From 3199a876dd5da0463fd6c6c231db7c3bb223c2ef Mon Sep 17 00:00:00 2001 From: Oleg Oshmyan Date: Thu, 29 May 2014 23:10:30 +0100 Subject: Require closing '}' for override tags Like VSFilter. '{' without a following '}' is just text, though in vector drawing mode it still delimits individual drawings. This also lets us nicely avoid '\0' hacks in the \t override tag handler in parse_tag. --- libass/ass_parse.c | 21 +++++++++------------ libass/ass_parse.h | 2 +- libass/ass_render.c | 25 ++++++++++--------------- 3 files changed, 20 insertions(+), 28 deletions(-) diff --git a/libass/ass_parse.c b/libass/ass_parse.c index a62cea6..47d22e6 100644 --- a/libass/ass_parse.c +++ b/libass/ass_parse.c @@ -264,11 +264,12 @@ static int parse_vector_clip(ASS_Renderer *render_priv, /** * \brief Parse style override tag. * \param p string to parse + * \param end end of string to parse, which must be '}' or ')' * \param pwr multiplier for some tag effects (comes from \t tags) */ -char *parse_tag(ASS_Renderer *render_priv, char *p, double pwr) +char *parse_tag(ASS_Renderer *render_priv, char *p, char *end, double pwr) { - while (*p != '\\' && *p != '}' && *p != 0) + while (*p != '\\' && p != end) ++p; if (*p != '\\') return p; @@ -276,12 +277,12 @@ char *parse_tag(ASS_Renderer *render_priv, char *p, double pwr) skip_spaces(&p); char *q = p; - while (*q != '(' && *q != '\\' && *q != '}' && *q != 0) + while (*q != '(' && *q != '\\' && q != end) ++q; if (q == p) return q; - char *end = q; + char *name_end = q; // Store one extra element to be able to detect excess arguments struct arg args[MAX_VALID_NARGS + 1]; @@ -302,7 +303,7 @@ char *parse_tag(ASS_Renderer *render_priv, char *p, double pwr) // to the end of the argument string into a single argument. char *r = q; - while (*r != ',' && *r != '\\' && *r != ')' && *r != '}' && *r != 0) + while (*r != ',' && *r != '\\' && *r != ')' && r != end) ++r; if (*r == ',') { @@ -311,7 +312,7 @@ char *parse_tag(ASS_Renderer *render_priv, char *p, double pwr) } else { // Swallow the rest of the parenthesized string. This could // be either a backslash-argument or simply the last argument. - while (*r != ')' && *r != '}' && *r != 0) + while (*r != ')' && r != end) ++r; push_arg(args, &nargs, q, r); q = r; @@ -323,7 +324,7 @@ char *parse_tag(ASS_Renderer *render_priv, char *p, double pwr) } } -#define tag(name) (mystrcmp(&p, (name)) && (push_arg(args, &nargs, p, end), 1)) +#define tag(name) (mystrcmp(&p, (name)) && (push_arg(args, &nargs, p, name_end), 1)) #define complex_tag(name) mystrcmp(&p, (name)) // New tags introduced in vsfilter 2.39 @@ -663,7 +664,6 @@ char *parse_tag(ASS_Renderer *render_priv, char *p, double pwr) int cnt = nargs - 1; long long t1, t2, t, delta_t; double k; - char c; if (cnt == 3) { t1 = argtoll(args[0]); t2 = argtoll(args[1]); @@ -695,12 +695,9 @@ char *parse_tag(ASS_Renderer *render_priv, char *p, double pwr) assert(delta_t != 0.); k = pow(((double) (t - t1)) / delta_t, accel); } - c = *args[cnt].end; - *args[cnt].end = '\0'; p = args[cnt].start; while (p < args[cnt].end) - p = parse_tag(render_priv, p, k); // maybe k*pwr ? no, specs forbid nested \t's - *args[cnt].end = c; + p = parse_tag(render_priv, p, args[cnt].end, k); // maybe k*pwr ? no, specs forbid nested \t's } else if (complex_tag("clip")) { if (nargs == 4) { int x0, y0, x1, y1; diff --git a/libass/ass_parse.h b/libass/ass_parse.h index 85f3d53..e932238 100644 --- a/libass/ass_parse.h +++ b/libass/ass_parse.h @@ -34,7 +34,7 @@ void change_border(ASS_Renderer *render_priv, double border_x, void apply_transition_effects(ASS_Renderer *render_priv, ASS_Event *event); void process_karaoke_effects(ASS_Renderer *render_priv); unsigned get_next_char(ASS_Renderer *render_priv, char **str); -char *parse_tag(ASS_Renderer *render_priv, char *p, double pwr); +char *parse_tag(ASS_Renderer *render_priv, char *p, char *end, double pwr); int event_is_positioned(char *str); extern void change_alpha(uint32_t *var, uint32_t new, double pwr); extern uint32_t mult_alpha(uint32_t a, uint32_t b); diff --git a/libass/ass_render.c b/libass/ass_render.c index 625a77d..89c914c 100644 --- a/libass/ass_render.c +++ b/libass/ass_render.c @@ -1888,7 +1888,7 @@ static int ass_render_event(ASS_Renderer *render_priv, ASS_Event *event, EventImages *event_images) { - char *p; + char *p, *tag_end; FT_Vector pen; unsigned code; DBBox bbox; @@ -1916,8 +1916,7 @@ ass_render_event(ASS_Renderer *render_priv, ASS_Event *event, drawing = render_priv->state.drawing; text_info->length = 0; p = event->Text; - - int in_tag = 0; + tag_end = NULL; // Event parsing. while (1) { @@ -1925,9 +1924,8 @@ ass_render_event(ASS_Renderer *render_priv, ASS_Event *event, // this affects render_context do { code = 0; - if (!in_tag && *p == '{') { // '\0' goes here - p++; - in_tag = 1; + if (!tag_end && *p == '{') { + tag_end = strchr(p, '}'); if (drawing->i) { // A drawing definition has just ended. // Exit and create the drawing now lest we @@ -1937,15 +1935,12 @@ ass_render_event(ASS_Renderer *render_priv, ASS_Event *event, break; } } - if (in_tag) { - p = parse_tag(render_priv, p, 1.); - if (*p == '}') { // end of tag - p++; - in_tag = 0; - } else if (*p != '\\') { - ass_msg(render_priv->library, MSGL_V, - "Unable to parse: '%.30s'", p); - } + if (tag_end) { + while (p < tag_end) + p = parse_tag(render_priv, p, tag_end, 1.); + assert(*p == '}'); + p++; + tag_end = NULL; } else { code = get_next_char(render_priv, &p); if (code && render_priv->state.drawing_scale) { -- cgit v1.2.3