summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOleg Oshmyan <chortos@inbox.lv>2014-05-29 23:10:30 +0100
committerOleg Oshmyan <chortos@inbox.lv>2014-06-06 15:10:06 +0100
commit3199a876dd5da0463fd6c6c231db7c3bb223c2ef (patch)
treedd585ffd1b6fa1edacc3983a11790487575a1318
parent0908a56be261915f9155e771bca6593645418da8 (diff)
downloadlibass-3199a876dd5da0463fd6c6c231db7c3bb223c2ef.tar.bz2
libass-3199a876dd5da0463fd6c6c231db7c3bb223c2ef.tar.xz
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.
-rw-r--r--libass/ass_parse.c21
-rw-r--r--libass/ass_parse.h2
-rw-r--r--libass/ass_render.c25
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) {