summaryrefslogtreecommitdiffstats
path: root/libass
diff options
context:
space:
mode:
authorOleg Oshmyan <chortos@inbox.lv>2018-01-04 03:37:28 +0200
committerOleg Oshmyan <chortos@inbox.lv>2018-01-08 22:26:29 +0200
commit3171bdafd1bc9b2f6118568a8d51694333e85fb9 (patch)
tree6a91d68c96e2272017ae91acb9abafabf6c1945b /libass
parent6835731c2fe4164a0c50bc91d12c43b2a2b4e799 (diff)
downloadlibass-3171bdafd1bc9b2f6118568a8d51694333e85fb9.tar.bz2
libass-3171bdafd1bc9b2f6118568a8d51694333e85fb9.tar.xz
parse_tags: handle argumentless \t inside \t() like VSFilter
\t with no parantheses inside \t() resets the animation parameters of the \t() for subsequent tags, so they are animated as if the \t() was the single-argument version regardless of the actual number of arguments the \t() has. Equivalently, you could say parentheses are implied for \t inside \t(). For example, \t(20,60,\frx0\t\fry0\frz0) animates \frx from 20 to 60 ms and animates \fry and \frz for the whole duration of the line, just like \t(20,60,\frx0)\t(\fry0\frz0) or \t(20,60,\frx0\t(\fry0\frz0)). Technically, VSFilter simply resets the animation parameters for any \t it encounters but parses the embedded tags only if the \t has the right number of arguments. However, top-level animation parameters don't matter because top-level tags are not animated, while any nested \t that has parentheses terminates the containing \t because they share the closing parenthesis, so the fact that a nested \t with empty parentheses or with at least four arguments changes the animation parameters also doesn't matter because the containing \t immediately ends and the changed parameters have nothing to apply to. Thus the only situation where this has a visible effect is a nested \t without parentheses. Closes https://github.com/libass/libass/pull/296.
Diffstat (limited to 'libass')
-rw-r--r--libass/ass_parse.c15
-rw-r--r--libass/ass_parse.h3
-rw-r--r--libass/ass_render.c2
3 files changed, 13 insertions, 7 deletions
diff --git a/libass/ass_parse.c b/libass/ass_parse.c
index 652ffa9..3ccf556 100644
--- a/libass/ass_parse.c
+++ b/libass/ass_parse.c
@@ -230,7 +230,8 @@ static int parse_vector_clip(ASS_Renderer *render_priv,
* of a number of spaces immediately preceding '}' or ')'
* \param pwr multiplier for some tag effects (comes from \t tags)
*/
-char *parse_tags(ASS_Renderer *render_priv, char *p, char *end, double pwr)
+char *parse_tags(ASS_Renderer *render_priv, char *p, char *end, double pwr,
+ bool nested)
{
for (char *q; p < end; p = q) {
while (*p != '\\' && p != end)
@@ -630,12 +631,11 @@ char *parse_tags(ASS_Renderer *render_priv, char *p, char *end, double pwr)
t1 = 0;
t2 = 0;
accel = argtod(args[0]);
- } else if (cnt == 0) {
+ } else {
t1 = 0;
t2 = 0;
accel = 1.;
- } else
- continue;
+ }
render_priv->state.detect_collisions = 0;
if (t2 == 0)
t2 = render_priv->state.event->Duration;
@@ -649,9 +649,13 @@ char *parse_tags(ASS_Renderer *render_priv, char *p, char *end, double pwr)
assert(delta_t != 0.);
k = pow(((double) (t - t1)) / delta_t, accel);
}
+ if (nested)
+ pwr = k;
+ if (cnt < 0 || cnt > 3)
+ continue;
p = args[cnt].start;
if (args[cnt].end < end) {
- p = parse_tags(render_priv, p, args[cnt].end, k);
+ p = parse_tags(render_priv, p, args[cnt].end, k, true);
} else {
assert(q == end);
// No other tags can possibly follow this \t tag,
@@ -659,6 +663,7 @@ char *parse_tags(ASS_Renderer *render_priv, char *p, char *end, double pwr)
// The recursive call is now essentially a tail call,
// so optimize it away.
pwr = k;
+ nested = true;
q = p;
}
} else if (complex_tag("clip")) {
diff --git a/libass/ass_parse.h b/libass/ass_parse.h
index 1b1b131..bf72b78 100644
--- a/libass/ass_parse.h
+++ b/libass/ass_parse.h
@@ -31,7 +31,8 @@ double ensure_font_size(ASS_Renderer *priv, double size);
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_tags(ASS_Renderer *render_priv, char *p, char *end, double pwr);
+char *parse_tags(ASS_Renderer *render_priv, char *p, char *end, double pwr,
+ bool nested);
int event_has_hard_overrides(char *str);
extern void change_alpha(uint32_t *var, int32_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 d5f881f..9ba3884 100644
--- a/libass/ass_render.c
+++ b/libass/ass_render.c
@@ -1712,7 +1712,7 @@ static int parse_events(ASS_Renderer *render_priv, ASS_Event *event)
code = 0;
while (*p) {
if ((*p == '{') && (q = strchr(p, '}'))) {
- p = parse_tags(render_priv, p, q, 1.);
+ p = parse_tags(render_priv, p, q, 1., false);
assert(*p == '}');
p++;
} else if (render_priv->state.drawing_scale) {