diff options
author | wm4 <wm4@nowhere> | 2013-10-07 13:59:08 +0200 |
---|---|---|
committer | wm4 <wm4@nowhere> | 2013-10-07 17:13:50 +0200 |
commit | 71ab6001bf69ea6e883e52e617c53c8cc2892a9a (patch) | |
tree | eb1885b268320a5d45ca12ab88b9d1dc47fcce1d /libass/ass.c | |
parent | bc0cfcca482fd4eca3c4273b4e30b2d11b63cbba (diff) | |
download | libass-71ab6001bf69ea6e883e52e617c53c8cc2892a9a.tar.bz2 libass-71ab6001bf69ea6e883e52e617c53c8cc2892a9a.tar.xz |
Don't rely on events being sorted in ass_step_sub()
ass_step_sub() assumed that the subtitle event list was sorted by event
start time, but that is not guaranteed. Making the list sorted is not
an option. (At least for now - too many issues are in the way to get
such a change being done.) Fix this function so that it works with an
unsorted event list.
Semantics regarding corner cases might be slightly different, such as
what happens if the now parameter coincides with event start/end, or
behavior with overlapping subtitles.
Diffstat (limited to 'libass/ass.c')
-rw-r--r-- | libass/ass.c | 50 |
1 files changed, 31 insertions, 19 deletions
diff --git a/libass/ass.c b/libass/ass.c index f6fabdcb..19e1b530 100644 --- a/libass/ass.c +++ b/libass/ass.c @@ -1242,33 +1242,45 @@ int ass_read_styles(ASS_Track *track, char *fname, char *codepage) long long ass_step_sub(ASS_Track *track, long long now, int movement) { int i; + ASS_Event *best = NULL; + long long target = now; + int direction = movement > 0 ? 1 : -1; if (movement == 0) return 0; if (track->n_events == 0) return 0; - if (movement < 0) - for (i = 0; - (i < track->n_events) - && - ((long long) (track->events[i].Start + - track->events[i].Duration) <= now); ++i) { - } else - for (i = track->n_events - 1; - (i >= 0) && ((long long) (track->events[i].Start) > now); - --i) { + while (movement) { + ASS_Event *closest = NULL; + long long closest_time = now; + for (i = 0; i < track->n_events; i++) { + if (direction < 0) { + long long end = + track->events[i].Start + track->events[i].Duration; + if (end < target) { + if (!closest || end > closest_time) { + closest = &track->events[i]; + closest_time = end; + } + } + } else { + long long start = track->events[i].Start; + if (start > target) { + if (!closest || start < closest_time) { + closest = &track->events[i]; + closest_time = start; + } + } + } } + target = closest_time + direction; + movement -= direction; + if (closest) + best = closest; + } - // -1 and n_events are ok - assert(i >= -1); - assert(i <= track->n_events); - i += movement; - if (i < 0) - i = 0; - if (i >= track->n_events) - i = track->n_events - 1; - return ((long long) track->events[i].Start) - now; + return best ? best->Start - now : 0; } ASS_Track *ass_new_track(ASS_Library *library) |