diff options
author | Oleg Oshmyan <chortos@inbox.lv> | 2020-10-18 18:08:39 +0300 |
---|---|---|
committer | Oleg Oshmyan <chortos@inbox.lv> | 2020-10-27 01:24:25 +0200 |
commit | b4303ad8c2142b8bdbedebb381a8ad4e6cd4feda (patch) | |
tree | 55f648b5ebf439d4ea58372153b1b85d8f08bd8d | |
parent | 34cbd0f865bf4db3dbe335a3ae90b6aafd1c3192 (diff) | |
download | libass-b4303ad8c2142b8bdbedebb381a8ad4e6cd4feda.tar.bz2 libass-b4303ad8c2142b8bdbedebb381a8ad4e6cd4feda.tar.xz |
Handle \k0 \ko0 \kf0 \K0 like VSFilter
Don't break runs when zero-duration karaoke starts unless the karaoke
*type* differs. The zero-duration karaoke block ends up glued to the
previous block (if any). In case of subsequent karaoke override tags,
like {\k100\k0}, the intervening tags will advance the next karaoke
block's start time, but not this combined block's start or end time.
Of course, runs may still be broken in the same place if there's another
reason for a run break besides karaoke, so zero-duration karaoke blocks
can still occur. Run breaks that have no karaoke tags at all also still
produce zero-duration karaoke blocks (if there is karaoke at all).
-rw-r--r-- | libass/ass_parse.c | 13 | ||||
-rw-r--r-- | libass/ass_render.c | 7 |
2 files changed, 16 insertions, 4 deletions
diff --git a/libass/ass_parse.c b/libass/ass_parse.c index 11d7f1b..5666ca6 100644 --- a/libass/ass_parse.c +++ b/libass/ass_parse.c @@ -974,13 +974,19 @@ void process_karaoke_effects(ASS_Renderer *render_priv) { long long tm_current = render_priv->time - render_priv->state.event->Start; - int timing = 0; + int timing = 0, skip_timing = 0; Effect effect_type = EF_NONE; GlyphInfo *last_boundary = NULL; for (int i = 0; i <= render_priv->text_info.length; i++) { if (i < render_priv->text_info.length && - !render_priv->text_info.glyphs[i].starts_new_run) + !render_priv->text_info.glyphs[i].starts_new_run) { + // VSFilter compatibility: if we have \k12345\k0 without a run + // break, subsequent text is still part of the same karaoke word, + // the current word's starting and ending time stay unchanged, + // but the starting time of the next karaoke word is advanced. + skip_timing += render_priv->text_info.glyphs[i].effect_skip_timing; continue; + } GlyphInfo *start = last_boundary; GlyphInfo *end = render_priv->text_info.glyphs + i; @@ -995,7 +1001,8 @@ void process_karaoke_effects(ASS_Renderer *render_priv) long long tm_start = timing + start->effect_skip_timing; long long tm_end = tm_start + start->effect_timing; - timing = tm_end; + timing = tm_end + skip_timing; + skip_timing = 0; if (effect_type != EF_KARAOKE_KF) tm_end = tm_start; diff --git a/libass/ass_render.c b/libass/ass_render.c index a324935..0ef7158 100644 --- a/libass/ass_render.c +++ b/libass/ass_render.c @@ -1855,12 +1855,15 @@ fix_glyph_scaling(ASS_Renderer *priv, GlyphInfo *glyph) // Initial run splitting based purely on the characters' styles static void split_style_runs(ASS_Renderer *render_priv) { + Effect last_effect_type = render_priv->text_info.glyphs[0].effect_type; render_priv->text_info.glyphs[0].starts_new_run = true; for (int i = 1; i < render_priv->text_info.length; i++) { GlyphInfo *info = render_priv->text_info.glyphs + i; GlyphInfo *last = render_priv->text_info.glyphs + (i - 1); + Effect effect_type = info->effect_type; info->starts_new_run = - info->effect_type != EF_NONE || + info->effect_timing || // but ignore effect_skip_timing + (effect_type != EF_NONE && effect_type != last_effect_type) || info->drawing_text || last->drawing_text || strcmp(last->font->desc.family, info->font->desc.family) || @@ -1888,6 +1891,8 @@ static void split_style_runs(ASS_Renderer *render_priv) last->italic != info->italic || last->bold != info->bold || ((last->flags ^ info->flags) & ~DECO_ROTATE); + if (effect_type != EF_NONE) + last_effect_type = effect_type; } } |