diff options
author | wm4 <wm4@nowhere> | 2012-09-29 21:31:23 +0200 |
---|---|---|
committer | wm4 <wm4@nowhere> | 2012-09-29 21:31:23 +0200 |
commit | 31db1346d43e54e07bd563d8c9e6ffbdd195b84c (patch) | |
tree | 70e0ba0165796a585a1159a5feb618a6583ead73 /libass/ass_render.c | |
parent | 6d2b7f238ec20a88d7ced4a513c6262a0b39d9ff (diff) | |
download | libass-31db1346d43e54e07bd563d8c9e6ffbdd195b84c.tar.bz2 libass-31db1346d43e54e07bd563d8c9e6ffbdd195b84c.tar.xz |
Terminate drawings immediately on a \p0 tag
The parsing code allowed override tags after \p0 to affect the drawing.
This is incorrect. Finish the drawing object as soon as \p0 is
encountered instead.
This requires moving the code executing the style overrides from
get_next_char() in ass_parse.c to the main render loop in
ass_renderer.c, because we have to re-enter the rendering loop
inside of a tag. The old code was simply executing all tags until
a new character could be returned to the renderer loop, mutating up
the state (RenderContext fields) for the drawing after the drawing
was closed, but before it was rendered.
This fixes libass issue #47.
Diffstat (limited to 'libass/ass_render.c')
-rw-r--r-- | libass/ass_render.c | 37 |
1 files changed, 32 insertions, 5 deletions
diff --git a/libass/ass_render.c b/libass/ass_render.c index 02bd1116..3e269c16 100644 --- a/libass/ass_render.c +++ b/libass/ass_render.c @@ -1711,15 +1711,43 @@ ass_render_event(ASS_Renderer *render_priv, ASS_Event *event, num_glyphs = 0; p = event->Text; + int in_tag = 0; + // Event parsing. while (1) { // get next char, executing style override // this affects render_context do { - code = get_next_char(render_priv, &p); - if (render_priv->state.drawing_mode && code) - ass_drawing_add_char(drawing, (char) code); - } while (code && render_priv->state.drawing_mode); // skip everything in drawing mode + code = 0; + if (!in_tag && *p == '{') { // '\0' goes here + p++; + in_tag = 1; + } + if (in_tag) { + int prev_drawing_mode = render_priv->state.drawing_mode; + 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 (prev_drawing_mode && !render_priv->state.drawing_mode) { + // Drawing mode was just disabled. We must exit and draw it + // immediately, instead of letting further tags affect it. + // See bug #47. + break; + } + } else { + code = get_next_char(render_priv, &p); + if (code && render_priv->state.drawing_mode) { + ass_drawing_add_char(drawing, (char) code); + continue; // skip everything in drawing mode + } + break; + } + } while (*p); if (text_info->length >= text_info->max_glyphs) { // Raise maximum number of glyphs @@ -1738,7 +1766,6 @@ ass_render_event(ASS_Renderer *render_priv, ASS_Event *event, render_priv->font_scale; drawing->scale_y = render_priv->state.scale_y * render_priv->font_scale; - p--; code = 0xfffc; // object replacement character glyphs[text_info->length].drawing = drawing; } |