From 5a279a787887c0254f2fa7c94b8d9e4ee7c995ea Mon Sep 17 00:00:00 2001 From: Oleg Oshmyan Date: Sat, 17 Oct 2020 00:31:31 +0300 Subject: Support Banner/Scroll effects with \pos/\move --- libass/ass_parse.c | 12 +++++----- libass/ass_render.c | 67 ++++++++++++++++++++++++++--------------------------- libass/ass_render.h | 8 +++---- 3 files changed, 43 insertions(+), 44 deletions(-) diff --git a/libass/ass_parse.c b/libass/ass_parse.c index fb57304..cf52b24 100644 --- a/libass/ass_parse.c +++ b/libass/ass_parse.c @@ -480,11 +480,11 @@ char *parse_tags(ASS_Renderer *render_priv, char *p, char *end, double pwr, k = ((double) (int32_t) ((uint32_t) t - t1)) / delta_t; x = k * (x2 - x1) + x1; y = k * (y2 - y1) + y1; - if (render_priv->state.evt_type != EVENT_POSITIONED) { + if (!(render_priv->state.evt_type & EVENT_POSITIONED)) { render_priv->state.pos_x = x; render_priv->state.pos_y = y; render_priv->state.detect_collisions = 0; - render_priv->state.evt_type = EVENT_POSITIONED; + render_priv->state.evt_type |= EVENT_POSITIONED; } } else if (tag("frx")) { double val; @@ -571,11 +571,11 @@ char *parse_tags(ASS_Renderer *render_priv, char *p, char *end, double pwr, v2 = argtod(args[1]); } else continue; - if (render_priv->state.evt_type == EVENT_POSITIONED) { + if (render_priv->state.evt_type & EVENT_POSITIONED) { ass_msg(render_priv->library, MSGL_V, "Subtitle has a new \\pos " "after \\move or \\pos, ignoring"); } else { - render_priv->state.evt_type = EVENT_POSITIONED; + render_priv->state.evt_type |= EVENT_POSITIONED; render_priv->state.detect_collisions = 0; render_priv->state.pos_x = v1; render_priv->state.pos_y = v2; @@ -907,7 +907,7 @@ void apply_transition_effects(ASS_Renderer *render_priv, ASS_Event *event) delay = 1; // ? render_priv->state.scroll_shift = (render_priv->time - render_priv->state.event->Start) / delay; - render_priv->state.evt_type = EVENT_HSCROLL; + render_priv->state.evt_type |= EVENT_HSCROLL; render_priv->state.wrap_style = 2; return; } @@ -946,7 +946,7 @@ void apply_transition_effects(ASS_Renderer *render_priv, ASS_Event *event) y1 = render_priv->track->PlayResY; // y0=y1=0 means fullscreen scrolling render_priv->state.clip_y0 = y0; render_priv->state.clip_y1 = y1; - render_priv->state.evt_type = EVENT_VSCROLL; + render_priv->state.evt_type |= EVENT_VSCROLL; render_priv->state.detect_collisions = 0; } diff --git a/libass/ass_render.c b/libass/ass_render.c index 2cec0e4..b405153 100644 --- a/libass/ass_render.c +++ b/libass/ass_render.c @@ -2130,7 +2130,7 @@ static void align_lines(ASS_Renderer *render_priv, double max_text_width) int justify = render_priv->state.justify; double max_width = 0; - if (render_priv->state.evt_type == EVENT_HSCROLL) { + if (render_priv->state.evt_type & EVENT_HSCROLL) { justify = halign; halign = HALIGN_LEFT; } @@ -2652,13 +2652,23 @@ ass_render_event(ASS_Renderer *render_priv, ASS_Event *event, compute_string_bbox(text_info, &bbox); // determine device coordinates for text - - // x coordinate for everything except positioned events double device_x = 0; - if (render_priv->state.evt_type == EVENT_NORMAL || - render_priv->state.evt_type == EVENT_VSCROLL) { - device_x = x2scr_left(render_priv, MarginL); - } else if (render_priv->state.evt_type == EVENT_HSCROLL) { + double device_y = 0; + + // handle positioned events first: an event can be both positioned and + // scrolling, and the scrolling effect overrides the position on one axis + if (render_priv->state.evt_type & EVENT_POSITIONED) { + double base_x = 0; + double base_y = 0; + get_base_point(&bbox, render_priv->state.alignment, &base_x, &base_y); + device_x = + x2scr_pos(render_priv, render_priv->state.pos_x) - base_x; + device_y = + y2scr_pos(render_priv, render_priv->state.pos_y) - base_y; + } + + // x coordinate + if (render_priv->state.evt_type & EVENT_HSCROLL) { if (render_priv->state.scroll_direction == SCROLL_RL) device_x = x2scr_pos(render_priv, @@ -2668,12 +2678,24 @@ ass_render_event(ASS_Renderer *render_priv, ASS_Event *event, device_x = x2scr_pos(render_priv, render_priv->state.scroll_shift) - (bbox.x_max - bbox.x_min); + } else if (!(render_priv->state.evt_type & EVENT_POSITIONED)) { + device_x = x2scr_left(render_priv, MarginL); } - // y coordinate for everything except positioned events - double device_y = 0; - if (render_priv->state.evt_type == EVENT_NORMAL || - render_priv->state.evt_type == EVENT_HSCROLL) { + // y coordinate + if (render_priv->state.evt_type & EVENT_VSCROLL) { + if (render_priv->state.scroll_direction == SCROLL_TB) + device_y = + y2scr(render_priv, + render_priv->state.clip_y0 + + render_priv->state.scroll_shift) - + (bbox.y_max - bbox.y_min); + else if (render_priv->state.scroll_direction == SCROLL_BT) + device_y = + y2scr(render_priv, + render_priv->state.clip_y1 - + render_priv->state.scroll_shift); + } else if (!(render_priv->state.evt_type & EVENT_POSITIONED)) { if (valign == VALIGN_TOP) { // toptitle device_y = y2scr_top(render_priv, @@ -2704,29 +2726,6 @@ ass_render_event(ASS_Renderer *render_priv, ASS_Event *event, device_y = scr_y0; } } - } else if (render_priv->state.evt_type == EVENT_VSCROLL) { - if (render_priv->state.scroll_direction == SCROLL_TB) - device_y = - y2scr(render_priv, - render_priv->state.clip_y0 + - render_priv->state.scroll_shift) - - (bbox.y_max - bbox.y_min); - else if (render_priv->state.scroll_direction == SCROLL_BT) - device_y = - y2scr(render_priv, - render_priv->state.clip_y1 - - render_priv->state.scroll_shift); - } - - // positioned events are totally different - if (render_priv->state.evt_type == EVENT_POSITIONED) { - double base_x = 0; - double base_y = 0; - get_base_point(&bbox, render_priv->state.alignment, &base_x, &base_y); - device_x = - x2scr_pos(render_priv, render_priv->state.pos_x) - base_x; - device_y = - y2scr_pos(render_priv, render_priv->state.pos_y) - base_y; } // fix clip coordinates diff --git a/libass/ass_render.h b/libass/ass_render.h index 93f661a..22d7230 100644 --- a/libass/ass_render.h +++ b/libass/ass_render.h @@ -224,10 +224,10 @@ typedef struct { double border_x; // outline width double border_y; enum { - EVENT_NORMAL, // "normal" top-, sub- or mid- title - EVENT_POSITIONED, // happens after pos(,), margins are ignored - EVENT_HSCROLL, // "Banner" transition effect, text_width is unlimited - EVENT_VSCROLL // "Scroll up", "Scroll down" transition effects + EVENT_NORMAL = 0, // "normal" top-, sub- or mid- title + EVENT_POSITIONED = 1, // happens after \pos or \move, margins are ignored + EVENT_HSCROLL = 2, // "Banner" transition effect, text_width is unlimited + EVENT_VSCROLL = 4 // "Scroll up", "Scroll down" transition effects } evt_type; int border_style; uint32_t c[4]; // colors(Primary, Secondary, so on) in RGBA -- cgit v1.2.3