From 722a64a265cb1a7451997e440721459ead394f99 Mon Sep 17 00:00:00 2001 From: Oleg Oshmyan Date: Thu, 1 May 2014 02:47:43 +0100 Subject: [PATCH] [WIP] Parse override tag arguments exactly like VSFilter --- libass/ass_parse.c | 403 ++++++++++++++++++++++----------------------- 1 file changed, 201 insertions(+), 202 deletions(-) diff --git a/libass/ass_parse.c b/libass/ass_parse.c index d6b26271a..8ec0c64e3 100644 --- a/libass/ass_parse.c +++ b/libass/ass_parse.c @@ -236,11 +236,59 @@ char *parse_tag(ASS_Renderer *render_priv, char *p, double pwr) { skip_to('\\'); skip('\\'); - if ((*p == '}') || (*p == 0)) + while (isspace(*p)) + ++p; + + char *q = p; + while (*q != '(' && *q != '\\' && *q != '}' && *q != 0) + ++q; + if (q == p) return p; + char *name = p; + char *end = q; + while (isspace(end[-1])) + --end; + + vector args; + + // Do this for all tags and before non-bracketed + // arguments because that's what VSFilter does + if (*q == '(') { + ++q; + while (1) { + while (isspace(*q)) + ++q; + + char *r = q; + while (*r != ',' && *r != '\\' && *r != ')' && *r != '}' && *r != 0) + ++r; + + // r > q because VSFilter + if (r > q && *r == ',') { + args << (q, r.rtrim); + q = r + 1; + } else { + while (*r != ')' && *r != '}' && *r != 0) + ++r; + if (r > q) { + char *s = r; + while (isspace(s[-1])) + --s; + if (s > q) + args << (q, s); + } + q = r; + break; + } + } + } + +#define tag(name) (mystrcmp(&p, (name)) && (args << (p, end), p = args[0].begin)) +#define complex_tag(name) mystrcmp(&p, (name)) + // New tags introduced in vsfilter 2.39 - if (mystrcmp(&p, "xbord")) { + if (tag("xbord")) { double val; if (mystrtod(&p, &val)) { val = render_priv->state.border_x * (1 - pwr) + val * pwr; @@ -248,7 +296,7 @@ char *parse_tag(ASS_Renderer *render_priv, char *p, double pwr) } else val = render_priv->state.style->Outline; render_priv->state.border_x = val; - } else if (mystrcmp(&p, "ybord")) { + } else if (tag("ybord")) { double val; if (mystrtod(&p, &val)) { val = render_priv->state.border_y * (1 - pwr) + val * pwr; @@ -256,48 +304,41 @@ char *parse_tag(ASS_Renderer *render_priv, char *p, double pwr) } else val = render_priv->state.style->Outline; render_priv->state.border_y = val; - } else if (mystrcmp(&p, "xshad")) { + } else if (tag("xshad")) { double val; if (mystrtod(&p, &val)) val = render_priv->state.shadow_x * (1 - pwr) + val * pwr; else val = render_priv->state.style->Shadow; render_priv->state.shadow_x = val; - } else if (mystrcmp(&p, "yshad")) { + } else if (tag("yshad")) { double val; if (mystrtod(&p, &val)) val = render_priv->state.shadow_y * (1 - pwr) + val * pwr; else val = render_priv->state.style->Shadow; render_priv->state.shadow_y = val; - } else if (mystrcmp(&p, "fax")) { + } else if (tag("fax")) { double val; if (mystrtod(&p, &val)) render_priv->state.fax = val * pwr + render_priv->state.fax * (1 - pwr); else render_priv->state.fax = 0.; - } else if (mystrcmp(&p, "fay")) { + } else if (tag("fay")) { double val; if (mystrtod(&p, &val)) render_priv->state.fay = val * pwr + render_priv->state.fay * (1 - pwr); else render_priv->state.fay = 0.; - } else if (mystrcmp(&p, "iclip")) { - int x0, y0, x1, y1; - int res = 1; - char *start = p; - skip('('); - res &= mystrtoi(&p, &x0); - skipopt(','); - res &= mystrtoi(&p, &y0); - skipopt(','); - res &= mystrtoi(&p, &x1); - skipopt(','); - res &= mystrtoi(&p, &y1); - skipopt(')'); - if (res) { + } else if (complex_tag("iclip")) { + if (args.size == 4) { + int x0, y0, x1, y1; + mystrtoi(&args[0], &x0); + mystrtoi(&args[1], &y0); + mystrtoi(&args[2], &x1); + mystrtoi(&args[3], &y1); render_priv->state.clip_x0 = render_priv->state.clip_x0 * (1 - pwr) + x0 * pwr; render_priv->state.clip_x1 = @@ -307,11 +348,12 @@ char *parse_tag(ASS_Renderer *render_priv, char *p, double pwr) render_priv->state.clip_y1 = render_priv->state.clip_y1 * (1 - pwr) + y1 * pwr; render_priv->state.clip_mode = 1; - } else if (!render_priv->state.clip_drawing) { - p = parse_vector_clip(render_priv, start); + // FIXME: make this code nice + } else if (args.size >= 1 && args.size <= 2 && !render_priv->state.clip_drawing) { + parse_vector_clip(render_priv, args, args.size); render_priv->state.clip_drawing_mode = 1; } - } else if (mystrcmp(&p, "blur")) { + } else if (tag("blur")) { double val; if (mystrtod(&p, &val)) { val = render_priv->state.blur * (1 - pwr) + val * pwr; @@ -321,62 +363,48 @@ char *parse_tag(ASS_Renderer *render_priv, char *p, double pwr) } else render_priv->state.blur = 0.0; // ASS standard tags - } else if (mystrcmp(&p, "fsc")) { - char tp = *p++; + } else if (tag("fscx")) { double val; - if (tp == 'x') { - if (mystrtod(&p, &val)) { - val /= 100; - val = render_priv->state.scale_x * (1 - pwr) + val * pwr; - val = (val < 0) ? 0 : val; - } else - val = render_priv->state.style->ScaleX; - render_priv->state.scale_x = val; - } else if (tp == 'y') { - if (mystrtod(&p, &val)) { - val /= 100; - val = render_priv->state.scale_y * (1 - pwr) + val * pwr; - val = (val < 0) ? 0 : val; - } else - val = render_priv->state.style->ScaleY; - render_priv->state.scale_y = val; - } else { - --p; - render_priv->state.scale_x = render_priv->state.style->ScaleX; - render_priv->state.scale_y = render_priv->state.style->ScaleY; - } - } else if (mystrcmp(&p, "fsp")) { + if (mystrtod(&p, &val)) { + val /= 100; + val = render_priv->state.scale_x * (1 - pwr) + val * pwr; + val = (val < 0) ? 0 : val; + } else + val = render_priv->state.style->ScaleX; + render_priv->state.scale_x = val; + } else if (tag("fscy")) { + double val; + if (mystrtod(&p, &val)) { + val /= 100; + val = render_priv->state.scale_y * (1 - pwr) + val * pwr; + val = (val < 0) ? 0 : val; + } else + val = render_priv->state.style->ScaleY; + render_priv->state.scale_y = val; + } else if (tag("fsc")) { + render_priv->state.scale_x = render_priv->state.style->ScaleX; + render_priv->state.scale_y = render_priv->state.style->ScaleY; + } else if (tag("fsp")) { double val; if (mystrtod(&p, &val)) render_priv->state.hspacing = render_priv->state.hspacing * (1 - pwr) + val * pwr; else render_priv->state.hspacing = render_priv->state.style->Spacing; - } else if (mystrcmp(&p, "fs+")) { + } else if (tag("fs")) { double val; - mystrtod(&p, &val); - val = render_priv->state.font_size * (1 + pwr * val / 10); - if (val <= 0) - val = render_priv->state.style->FontSize; - if (render_priv->state.font) - change_font_size(render_priv, val); - } else if (mystrcmp(&p, "fs-")) { - double val; - mystrtod(&p, &val); - val = render_priv->state.font_size * (1 - pwr * val / 10); - if (val <= 0) - val = render_priv->state.style->FontSize; - if (render_priv->state.font) - change_font_size(render_priv, val); - } else if (mystrcmp(&p, "fs")) { - double val; - if (mystrtod(&p, &val)) - val = render_priv->state.font_size * (1 - pwr) + val * pwr; + if (mystrtod(&p, &val)) { + // FIXME: p vs args[0], make this code clean + if (*args[0] == '+' || *args[0] == '-') + val = render_priv->state.font_size * (1 + pwr * val / 10); + else + val = render_priv->state.font_size * (1 - pwr) + val * pwr; + } if (val <= 0) val = render_priv->state.style->FontSize; if (render_priv->state.font) change_font_size(render_priv, val); - } else if (mystrcmp(&p, "bord")) { + } else if (tag("bord")) { double val, xval, yval; if (mystrtod(&p, &val)) { xval = render_priv->state.border_x * (1 - pwr) + val * pwr; @@ -387,37 +415,32 @@ char *parse_tag(ASS_Renderer *render_priv, char *p, double pwr) xval = yval = render_priv->state.style->Outline; render_priv->state.border_x = xval; render_priv->state.border_y = yval; - } else if (mystrcmp(&p, "move")) { + } else if (complex_tag("move")) { double x1, x2, y1, y2; long long t1, t2, delta_t, t; double x, y; double k; - skip('('); - mystrtod(&p, &x1); - skip(','); - mystrtod(&p, &y1); - skip(','); - mystrtod(&p, &x2); - skip(','); - mystrtod(&p, &y2); - t1 = t2 = 0; - if (*p == ',') { - skip(','); - mystrtoll(&p, &t1); - skip(','); - mystrtoll(&p, &t2); - // VSFilter - if (t1 > t2) { - double tmp = t2; - t2 = t1; - t1 = tmp; + if (args.size == 4 || args.size == 6) { + mystrtod(&args[0], &x1); + mystrtod(&args[1], &y1); + mystrtod(&args[2], &x2); + mystrtod(&args[3], &y2); + t1 = t2 = 0; + if (args.size == 6) { + mystrtoll(&args[4], &t1); + mystrtoll(&args[5], &t2); + if (t1 > t2) { + long long tmp = t2; + t2 = t1; + t1 = tmp; + } } - } + } else + return p; if (t1 <= 0 && t2 <= 0) { t1 = 0; t2 = render_priv->state.event->Duration; } - skipopt(')'); delta_t = t2 - t1; t = render_priv->time - render_priv->state.event->Start; if (t <= t1) @@ -434,7 +457,7 @@ char *parse_tag(ASS_Renderer *render_priv, char *p, double pwr) render_priv->state.detect_collisions = 0; render_priv->state.evt_type = EVENT_POSITIONED; } - } else if (mystrcmp(&p, "frx")) { + } else if (tag("frx")) { double val; if (mystrtod(&p, &val)) { val *= M_PI / 180; @@ -442,7 +465,7 @@ char *parse_tag(ASS_Renderer *render_priv, char *p, double pwr) val * pwr + render_priv->state.frx * (1 - pwr); } else render_priv->state.frx = 0.; - } else if (mystrcmp(&p, "fry")) { + } else if (tag("fry")) { double val; if (mystrtod(&p, &val)) { val *= M_PI / 180; @@ -450,7 +473,7 @@ char *parse_tag(ASS_Renderer *render_priv, char *p, double pwr) val * pwr + render_priv->state.fry * (1 - pwr); } else render_priv->state.fry = 0.; - } else if (mystrcmp(&p, "frz") || mystrcmp(&p, "fr")) { + } else if (tag("frz") || tag("fr")) { double val; if (mystrtod(&p, &val)) { val *= M_PI / 180; @@ -459,20 +482,21 @@ char *parse_tag(ASS_Renderer *render_priv, char *p, double pwr) } else render_priv->state.frz = M_PI * render_priv->state.style->Angle / 180.; - } else if (mystrcmp(&p, "fn")) { - char *start = p; + } else if (tag("fn")) { char *family; - skip_to('\\'); - if (p > start && strncmp(start, "0", p - start)) { - family = malloc(p - start + 1); - strncpy(family, start, p - start); - family[p - start] = '\0'; + end = args[0].end; + if (end > p && strncmp(p, "0", end - p)) { + while (isspace(*p)) + ++p; + family = malloc(end - p + 1); + strncpy(family, p, end - p); + family[end - p] = '\0'; } else family = strdup(render_priv->state.style->FontName); free(render_priv->state.family); render_priv->state.family = family; update_font(render_priv); - } else if (mystrcmp(&p, "alpha")) { + } else if (tag("alpha")) { uint32_t val; int i; int hex = render_priv->track->track_type == TRACK_TYPE_ASS; @@ -491,7 +515,7 @@ char *parse_tag(ASS_Renderer *render_priv, char *p, double pwr) render_priv->state.style->BackColour, 1); } // FIXME: simplify - } else if (mystrcmp(&p, "an")) { + } else if (tag("an")) { int val; mystrtoi(&p, &val); if ((render_priv->state.parsed_tags & PARSED_A) == 0) { @@ -507,7 +531,7 @@ char *parse_tag(ASS_Renderer *render_priv, char *p, double pwr) render_priv->state.style->Alignment; render_priv->state.parsed_tags |= PARSED_A; } - } else if (mystrcmp(&p, "a")) { + } else if (tag("a")) { int val; mystrtoi(&p, &val); if ((render_priv->state.parsed_tags & PARSED_A) == 0) { @@ -520,13 +544,13 @@ char *parse_tag(ASS_Renderer *render_priv, char *p, double pwr) render_priv->state.style->Alignment; render_priv->state.parsed_tags |= PARSED_A; } - } else if (mystrcmp(&p, "pos")) { + } else if (complex_tag("pos")) { double v1, v2; - skip('('); - mystrtod(&p, &v1); - skip(','); - mystrtod(&p, &v2); - skipopt(')'); + if (args.size == 2) { + mystrtod(&args[0], &v1); + mystrtod(&args[1], &v2); + } else + return p; if (render_priv->state.evt_type == EVENT_POSITIONED) { ass_msg(render_priv->library, MSGL_V, "Subtitle has a new \\pos " "after \\move or \\pos, ignoring"); @@ -536,40 +560,29 @@ char *parse_tag(ASS_Renderer *render_priv, char *p, double pwr) render_priv->state.pos_x = v1; render_priv->state.pos_y = v2; } - } else if (mystrcmp(&p, "fad")) { + } else if (complex_tag("fade") || complex_tag("fad")) { int a1, a2, a3; long long t1, t2, t3, t4; - if (*p == 'e') - ++p; // either \fad or \fade - skip('('); - mystrtoi(&p, &a1); - skip(','); - mystrtoi(&p, &a2); - if (*p == ')') { + if (args.size == 2) { // 2-argument version (\fad, according to specs) - // a1 and a2 are fade-in and fade-out durations - t1 = -1; - t2 = a1; - t3 = a2; - t4 = -1; a1 = 0xFF; a2 = 0; a3 = 0xFF; - } else { + t1 = -1; + mystrtoi(&args[0], &t2); + mystrtoi(&args[1], &t3); + t4 = -1; + } else if (args.size == 7) { // 7-argument version (\fade) - // a1 and a2 (and a3) are opacity values - skip(','); - mystrtoi(&p, &a3); - skip(','); - mystrtoll(&p, &t1); - skip(','); - mystrtoll(&p, &t2); - skip(','); - mystrtoll(&p, &t3); - skip(','); - mystrtoll(&p, &t4); - } - skipopt(')'); + mystrtoi(&args[0], &a2); + mystrtoi(&args[1], &a3); + mystrtoi(&args[2], &a3); + mystrtoll(&args[3], &t1); + mystrtoll(&args[4], &t2); + mystrtoll(&args[5], &t3); + mystrtoll(&args[6], &t4); + } else + return p; if (t1 == -1 && t4 == -1) { t1 = 0; t4 = render_priv->state.event->Duration; @@ -582,48 +595,43 @@ char *parse_tag(ASS_Renderer *render_priv, char *p, double pwr) t3, t4, a1, a2, a3); render_priv->state.parsed_tags |= PARSED_FADE; } - } else if (mystrcmp(&p, "org")) { + } else if (complex_tag("org")) { double v1, v2; - skip('('); - mystrtod(&p, &v1); - skip(','); - mystrtod(&p, &v2); - skipopt(')'); + if (args.size == 2) { + mystrtod(&args[0], &v1); + mystrtod(&args[1], &v2); + } else + return p; if (!render_priv->state.have_origin) { render_priv->state.org_x = v1; render_priv->state.org_y = v2; render_priv->state.have_origin = 1; render_priv->state.detect_collisions = 0; } - } else if (mystrcmp(&p, "t")) { + } else if (complex_tag("t")) { double v[3]; double accel; - int cnt; + int cnt = args.size - 1; long long t1, t2, t, delta_t; double k; - skip('('); - for (cnt = 0; cnt < 3; ++cnt) { - if (!mystrtod(&p, &v[cnt])) - break; - skip(','); - } if (cnt == 3) { - t1 = v[0]; - t2 = v[1]; - accel = v[2]; + mystrtoll(&args[0], &t1); + mystrtoll(&args[1], &t2); + mystrtod(&args[2], &accel); } else if (cnt == 2) { - t1 = v[0]; - t2 = v[1]; + mystrtoll(&args[0], &t1); + mystrtoll(&args[1], &t2); accel = 1.; } else if (cnt == 1) { t1 = 0; t2 = 0; - accel = v[0]; - } else { // cnt == 0 + mystrtod(&args[0], &accel); + } else if (cnt == 0) { t1 = 0; t2 = 0; accel = 1.; - } + } else + return p; render_priv->state.detect_collisions = 0; if (t2 == 0) t2 = render_priv->state.event->Duration; @@ -637,24 +645,16 @@ char *parse_tag(ASS_Renderer *render_priv, char *p, double pwr) assert(delta_t != 0.); k = pow(((double) (t - t1)) / delta_t, accel); } + p = args[cnt]; while (*p != ')' && *p != '}' && *p != '\0') p = parse_tag(render_priv, p, k); // maybe k*pwr ? no, specs forbid nested \t's - skip_to(')'); // in case there is some unknown tag or a comment - skipopt(')'); - } else if (mystrcmp(&p, "clip")) { - char *start = p; - int x0, y0, x1, y1; - int res = 1; - skip('('); - res &= mystrtoi(&p, &x0); - skipopt(','); - res &= mystrtoi(&p, &y0); - skipopt(','); - res &= mystrtoi(&p, &x1); - skipopt(','); - res &= mystrtoi(&p, &y1); - skipopt(')'); - if (res) { + } else if (complex_tag("clip")) { + if (args.size == 4) { + int x0, y0, x1, y1; + mystrtoi(&args[0], &x0); + mystrtoi(&args[1], &y0); + mystrtoi(&args[2], &x1); + mystrtoi(&args[3], &y1); render_priv->state.clip_x0 = render_priv->state.clip_x0 * (1 - pwr) + x0 * pwr; render_priv->state.clip_x1 = @@ -664,12 +664,12 @@ char *parse_tag(ASS_Renderer *render_priv, char *p, double pwr) render_priv->state.clip_y1 = render_priv->state.clip_y1 * (1 - pwr) + y1 * pwr; render_priv->state.clip_mode = 0; - // Might be a vector clip - } else if (!render_priv->state.clip_drawing) { - p = parse_vector_clip(render_priv, start); + // FIXME: make this code nice + } else if (args.size >= 1 && args.size <= 2 && !render_priv->state.clip_drawing) { + parse_vector_clip(render_priv, args, args.size); render_priv->state.clip_drawing_mode = 0; } - } else if (mystrcmp(&p, "c")) { + } else if (tag("c")) { uint32_t val; int hex = render_priv->track->track_type == TRACK_TYPE_ASS; if (strtocolor(render_priv->library, &p, &val, hex)) @@ -678,10 +678,10 @@ char *parse_tag(ASS_Renderer *render_priv, char *p, double pwr) change_color(&render_priv->state.c[0], render_priv->state.style->PrimaryColour, 1); } else if ((*p >= '1') && (*p <= '4') && (++p) - && (mystrcmp(&p, "c") || mystrcmp(&p, "a"))) { - char n = *(p - 2); + && (tag("c") || tag("a"))) { + char n = *name; int cidx = n - '1'; - char cmd = *(p - 1); + char cmd = *(name + 1); uint32_t val; int hex = render_priv->track->track_type == TRACK_TYPE_ASS; assert((n >= '1') && (n <= '4')); @@ -719,20 +719,19 @@ char *parse_tag(ASS_Renderer *render_priv, char *p, double pwr) n, cmd); break; } - } else if (mystrcmp(&p, "r")) { - char *start = p; + } else if (tag("r")) { char *style; - skip_to('\\'); - if (p > start) { - style = malloc(p - start + 1); - strncpy(style, start, p - start); - style[p - start] = '\0'; + end = args[0].end; + if (end > p) { + style = malloc(end - p + 1); + strncpy(style, p, end - p); + style[end - p] = '\0'; reset_render_context(render_priv, lookup_style_strict(render_priv->track, style)); free(style); } else reset_render_context(render_priv, NULL); - } else if (mystrcmp(&p, "be")) { + } else if (tag("be")) { double dval; if (mystrtod(&p, &dval)) { int val; @@ -744,19 +743,19 @@ char *parse_tag(ASS_Renderer *render_priv, char *p, double pwr) render_priv->state.be = val; } else render_priv->state.be = 0; - } else if (mystrcmp(&p, "b")) { + } else if (tag("b")) { int val; if (!mystrtoi(&p, &val) || !(val == 0 || val == 1 || val >= 100)) val = render_priv->state.style->Bold; render_priv->state.bold = val; update_font(render_priv); - } else if (mystrcmp(&p, "i")) { + } else if (tag("i")) { int val; if (!mystrtoi(&p, &val) || !(val == 0 || val == 1)) val = render_priv->state.style->Italic; render_priv->state.italic = val; update_font(render_priv); - } else if (mystrcmp(&p, "kf") || mystrcmp(&p, "K")) { + } else if (tag("kf") || tag("K")) { double val; if (!mystrtod(&p, &val)) val = 100; @@ -765,7 +764,7 @@ char *parse_tag(ASS_Renderer *render_priv, char *p, double pwr) render_priv->state.effect_skip_timing += render_priv->state.effect_timing; render_priv->state.effect_timing = val * 10; - } else if (mystrcmp(&p, "ko")) { + } else if (tag("ko")) { double val; if (!mystrtod(&p, &val)) val = 100; @@ -774,7 +773,7 @@ char *parse_tag(ASS_Renderer *render_priv, char *p, double pwr) render_priv->state.effect_skip_timing += render_priv->state.effect_timing; render_priv->state.effect_timing = val * 10; - } else if (mystrcmp(&p, "k")) { + } else if (tag("k")) { double val; if (!mystrtod(&p, &val)) val = 100; @@ -783,7 +782,7 @@ char *parse_tag(ASS_Renderer *render_priv, char *p, double pwr) render_priv->state.effect_skip_timing += render_priv->state.effect_timing; render_priv->state.effect_timing = val * 10; - } else if (mystrcmp(&p, "shad")) { + } else if (tag("shad")) { double val, xval, yval; if (mystrtod(&p, &val)) { xval = render_priv->state.shadow_x * (1 - pwr) + val * pwr; @@ -795,7 +794,7 @@ char *parse_tag(ASS_Renderer *render_priv, char *p, double pwr) xval = yval = render_priv->state.style->Shadow; render_priv->state.shadow_x = xval; render_priv->state.shadow_y = yval; - } else if (mystrcmp(&p, "s")) { + } else if (tag("s")) { int val; if (!mystrtoi(&p, &val) || !(val == 0 || val == 1)) val = render_priv->state.style->StrikeOut; @@ -803,7 +802,7 @@ char *parse_tag(ASS_Renderer *render_priv, char *p, double pwr) render_priv->state.flags |= DECO_STRIKETHROUGH; else render_priv->state.flags &= ~DECO_STRIKETHROUGH; - } else if (mystrcmp(&p, "u")) { + } else if (tag("u")) { int val; if (!mystrtoi(&p, &val) || !(val == 0 || val == 1)) val = render_priv->state.style->Underline; @@ -811,28 +810,28 @@ char *parse_tag(ASS_Renderer *render_priv, char *p, double pwr) render_priv->state.flags |= DECO_UNDERLINE; else render_priv->state.flags &= ~DECO_UNDERLINE; - } else if (mystrcmp(&p, "pbo")) { + } else if (tag("pbo")) { double val; mystrtod(&p, &val); render_priv->state.pbo = val; - } else if (mystrcmp(&p, "p")) { + } else if (tag("p")) { int val; mystrtoi(&p, &val); val = (val < 0) ? 0 : val; render_priv->state.drawing_scale = val; - } else if (mystrcmp(&p, "q")) { + } else if (tag("q")) { int val; if (!mystrtoi(&p, &val) || !(val >= 0 && val <= 3)) val = render_priv->track->WrapStyle; render_priv->state.wrap_style = val; - } else if (mystrcmp(&p, "fe")) { + } else if (tag("fe")) { int val; if (!mystrtoi(&p, &val)) val = render_priv->state.style->Encoding; render_priv->state.font_encoding = val; } - return p; + return q; } void apply_transition_effects(ASS_Renderer *render_priv, ASS_Event *event)