/**
* \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;
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];
// 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 == ',') {
} 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;
}
}
-#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
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]);
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;
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);
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;
drawing = render_priv->state.drawing;
text_info->length = 0;
p = event->Text;
-
- int in_tag = 0;
+ tag_end = NULL;
// Event parsing.
while (1) {
// 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
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) {