diff --git a/library/core/src/main/java/com/google/android/exoplayer2/text/ttml/TtmlNode.java b/library/core/src/main/java/com/google/android/exoplayer2/text/ttml/TtmlNode.java index 02019e8dd5..4c51f97247 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/text/ttml/TtmlNode.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/text/ttml/TtmlNode.java @@ -379,7 +379,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; regionOutput.setText(text); } if (resolvedStyle != null) { - TtmlRenderUtil.applyStylesToSpan(text, start, end, resolvedStyle, parent); + TtmlRenderUtil.applyStylesToSpan(text, start, end, resolvedStyle, parent, globalStyles); regionOutput .setTextAlignment(resolvedStyle.getTextAlign()) .setVerticalType(resolvedStyle.getVerticalType()); diff --git a/library/core/src/main/java/com/google/android/exoplayer2/text/ttml/TtmlRenderUtil.java b/library/core/src/main/java/com/google/android/exoplayer2/text/ttml/TtmlRenderUtil.java index e343c57840..13f3fe2b16 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/text/ttml/TtmlRenderUtil.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/text/ttml/TtmlRenderUtil.java @@ -78,7 +78,12 @@ import java.util.Map; } public static void applyStylesToSpan( - Spannable builder, int start, int end, TtmlStyle style, @Nullable TtmlNode parent) { + Spannable builder, + int start, + int end, + TtmlStyle style, + @Nullable TtmlNode parent, + Map globalStyles) { if (style.getStyle() != TtmlStyle.UNSPECIFIED) { builder.setSpan(new StyleSpan(style.getStyle()), start, end, @@ -117,12 +122,12 @@ import java.util.Map; switch (style.getRubyType()) { case TtmlStyle.RUBY_TYPE_BASE: // look for the sibling RUBY_TEXT and add it as span between start & end. - @Nullable TtmlNode containerNode = findRubyContainerNode(parent); + @Nullable TtmlNode containerNode = findRubyContainerNode(parent, globalStyles); if (containerNode == null) { // No matching container node break; } - @Nullable TtmlNode textNode = findRubyTextNode(containerNode); + @Nullable TtmlNode textNode = findRubyTextNode(containerNode, globalStyles); if (textNode == null) { // no matching text node break; @@ -200,12 +205,15 @@ import java.util.Map; } @Nullable - private static TtmlNode findRubyTextNode(TtmlNode rubyContainerNode) { + private static TtmlNode findRubyTextNode( + TtmlNode rubyContainerNode, Map globalStyles) { Deque childNodesStack = new ArrayDeque<>(); childNodesStack.push(rubyContainerNode); while (!childNodesStack.isEmpty()) { TtmlNode childNode = childNodesStack.pop(); - if (childNode.style != null && childNode.style.getRubyType() == TtmlStyle.RUBY_TYPE_TEXT) { + @Nullable + TtmlStyle style = resolveStyle(childNode.style, childNode.getStyleIds(), globalStyles); + if (style != null && style.getRubyType() == TtmlStyle.RUBY_TYPE_TEXT) { return childNode; } for (int i = childNode.getChildCount() - 1; i >= 0; i--) { @@ -217,9 +225,10 @@ import java.util.Map; } @Nullable - private static TtmlNode findRubyContainerNode(@Nullable TtmlNode node) { + private static TtmlNode findRubyContainerNode( + @Nullable TtmlNode node, Map globalStyles) { while (node != null) { - @Nullable TtmlStyle style = node.style; + @Nullable TtmlStyle style = resolveStyle(node.style, node.getStyleIds(), globalStyles); if (style != null && style.getRubyType() == TtmlStyle.RUBY_TYPE_CONTAINER) { return node; } diff --git a/library/core/src/test/java/com/google/android/exoplayer2/text/ttml/TtmlDecoderTest.java b/library/core/src/test/java/com/google/android/exoplayer2/text/ttml/TtmlDecoderTest.java index 9b21261f5f..761814d526 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/text/ttml/TtmlDecoderTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/text/ttml/TtmlDecoderTest.java @@ -656,15 +656,19 @@ public final class TtmlDecoderTest { Spanned thirdCue = getOnlyCueTextAtTimeUs(subtitle, 30_000_000); assertThat(thirdCue.toString()).isEqualTo("Cue with annotated text."); - assertThat(thirdCue).hasNoRubySpanBetween(0, thirdCue.length()); + assertThat(thirdCue).hasRubySpanBetween("Cue with ".length(), "Cue with annotated".length()); Spanned fourthCue = getOnlyCueTextAtTimeUs(subtitle, 40_000_000); - assertThat(fourthCue.toString()).isEqualTo("Cue with text."); + assertThat(fourthCue.toString()).isEqualTo("Cue with annotated text."); assertThat(fourthCue).hasNoRubySpanBetween(0, fourthCue.length()); Spanned fifthCue = getOnlyCueTextAtTimeUs(subtitle, 50_000_000); - assertThat(fifthCue.toString()).isEqualTo("Cue with annotated text."); + assertThat(fifthCue.toString()).isEqualTo("Cue with text."); assertThat(fifthCue).hasNoRubySpanBetween(0, fifthCue.length()); + + Spanned sixthCue = getOnlyCueTextAtTimeUs(subtitle, 60_000_000); + assertThat(sixthCue.toString()).isEqualTo("Cue with annotated text."); + assertThat(sixthCue).hasNoRubySpanBetween(0, sixthCue.length()); } private static Spanned getOnlyCueTextAtTimeUs(Subtitle subtitle, long timeUs) { diff --git a/testdata/src/test/assets/ttml/rubies.xml b/testdata/src/test/assets/ttml/rubies.xml index 0eb89da477..874dfebdc3 100644 --- a/testdata/src/test/assets/ttml/rubies.xml +++ b/testdata/src/test/assets/ttml/rubies.xml @@ -16,9 +16,15 @@ --> + + +