Fix overlapping subtitles with negative line numbers#3151
Fix overlapping subtitles with negative line numbers#3151johnpc wants to merge 3 commits intoandroidx:mainfrom
Conversation
|
Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA). View this failed invocation of the CLA check for more information. For the most up to date status, view the checks section at the bottom of the pull request. |
|
Thanks for the PR - is there a reason you are specifically handling negative line numbers? I think the same problem can occur with positive line numbers too. Would you be able to handle the positive line numbers case in this PR as well? I think a list of cues could have cues with both positive & negative line numbers (some at the top, some at the bottom of the screen, at the same time) - so handling both cases separately would probably be best. I think it makes sense to handle both cases at the same time so that we don't accidentally over-fit the solution to only one of the two cases. Please also rebase the PR to target the |
8f87eee to
b312b30
Compare
Fixes overlapping subtitle rendering when multiple WebVTT cues have overlapping timestamps and are assigned line numbers. Problem: When multiple WebVTT cues overlap in time, they get assigned line numbers (-1, -2, -3 for bottom-stacked or 0, 1, 2 for top-stacked). However, SubtitlePainter calculates each cue's vertical position using only firstLineHeight, not accounting for the actual multi-line height of preceding cues. This causes cues to visually overlap. Solution: 1. Added getLastDrawnTextBottom() to SubtitlePainter to expose the actual rendered height of a text cue 2. Modified CanvasSubtitleOutput.dispatchDraw() to track cumulative height of stacked cues and adjust the drawing boundary for subsequent cues 3. Handles both negative line numbers (bottom-stacked) and positive line numbers (top-stacked) Fixes androidx#2237
b312b30 to
38536d3
Compare
|
@icbaker I've addressed all your feedback - updated copyright years, renamed the method to |
|
Gentle ping on this, not sure what review timeline expectations there are for external contributions. Just want to make sure it's on your radar! |
- Fix copyright year: 2026 → 2025 in test files - Rename getLastDrawnTextBottom() to getLastDrawnCueHeight() to clarify it returns the height of the drawn cue, not a position - Update documentation to accurately describe the return value - Add bitmap cue support: now returns bitmapRect.height() for bitmap cues instead of 0, since bitmap cues can also have line-based position - Update tests to reflect the new method name and bitmap behavior
Cues without explicit line positioning (line == DIMEN_UNSET) should also stack from the bottom to prevent overlapping. This is common with SRT subtitles that don't specify positioning info.
|
I've tested this by building into the jellyfin-androidtv app and confirming that it fixes my original subtitle issue jellyfin/jellyfin-androidtv#4522 It does work.
Worth noting that in my case, the subtitles are still out-of-order, but I think that's fine since it's sort of undefined behavior in an srt anyway, and it matches what happens in jellyfin-web |

Summary
Fixes overlapping subtitle rendering when multiple WebVTT cues have overlapping timestamps and are assigned negative line numbers.
Problem
When multiple WebVTT cues overlap in time,
WebvttSubtitle.getCues()correctly assigns them negative line numbers (-1, -2, -3, etc.) to stack them from the bottom. However,SubtitlePaintercalculates each cue's vertical position using onlyfirstLineHeight(the height of a single text line), not accounting for the actual multi-line height of preceding cues.This causes cues to visually overlap when:
This is particularly common in anime subtitles where overlapping timestamps are used for effects like showing both dialogue and on-screen text.
Solution
getLastDrawnTextHeight()toSubtitlePainterto expose the actual rendered height of a text cueCanvasSubtitleOutput.dispatchDraw()to track cumulative height of bottom-stacked cues (those with negativeLINE_TYPE_NUMBER) and adjust the drawing boundary for subsequent cuesTesting
Added unit tests for:
SubtitlePainterTest: Tests forgetLastDrawnTextHeight()with various cue typesCanvasSubtitleOutputTest: Tests for rendering overlapping cues without visual overlapFixes #2237