summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOleg Oshmyan <chortos@inbox.lv>2020-10-18 18:08:39 +0300
committerOleg Oshmyan <chortos@inbox.lv>2020-10-27 01:24:25 +0200
commitb4303ad8c2142b8bdbedebb381a8ad4e6cd4feda (patch)
tree55f648b5ebf439d4ea58372153b1b85d8f08bd8d
parent34cbd0f865bf4db3dbe335a3ae90b6aafd1c3192 (diff)
downloadlibass-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.c13
-rw-r--r--libass/ass_render.c7
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;
}
}