]> granicus.if.org Git - libass/commitdiff
Require closing '}' for override tags
authorOleg Oshmyan <chortos@inbox.lv>
Thu, 29 May 2014 22:10:30 +0000 (23:10 +0100)
committerOleg Oshmyan <chortos@inbox.lv>
Fri, 6 Jun 2014 14:10:06 +0000 (15:10 +0100)
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
libass/ass_parse.h
libass/ass_render.c

index a62cea62a2021e549a1ba9db40d21d51703d3011..47d22e6643103dc73a436f8e80b30474c793f09f 100644 (file)
@@ -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;
index 85f3d537e471429c32ad686758f7557da01a819d..e9322381cc10231791a8f1b4c8d86f1786030c4a 100644 (file)
@@ -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);
index 625a77dd91ef44cf73a5beae107b5ae153bb4b66..89c914cdedf11ff63abc94aad566143187534b5a 100644 (file)
@@ -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) {