From 64792dfda2873814457841cc6f36effa49ad6ba8 Mon Sep 17 00:00:00 2001 From: ibaker Date: Wed, 30 Aug 2023 08:47:38 -0700 Subject: [PATCH] Rollback of https://github.com/androidx/media/commit/25253698bc0cae2040ae7b4c0ae31d5cefcc3ba7 PiperOrigin-RevId: 561352515 --- .../text/SubtitleDecoderFactory.java | 5 + .../text/DefaultSubtitleParserFactory.java | 7 +- .../{TtmlParser.java => TtmlDecoder.java} | 40 +- .../extractor/text/ttml/TtmlDecoderTest.java} | 151 +-- .../extractor/text/ttml/TtmlParserTest.java | 920 ------------------ 5 files changed, 105 insertions(+), 1018 deletions(-) rename libraries/extractor/src/main/java/androidx/media3/extractor/text/ttml/{TtmlParser.java => TtmlDecoder.java} (97%) rename libraries/{exoplayer/src/test/java/androidx/media3/exoplayer/text/DelegatingSubtitleDecoderTtmlParserTest.java => extractor/src/test/java/androidx/media3/extractor/text/ttml/TtmlDecoderTest.java} (88%) delete mode 100644 libraries/extractor/src/test/java/androidx/media3/extractor/text/ttml/TtmlParserTest.java diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/text/SubtitleDecoderFactory.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/text/SubtitleDecoderFactory.java index 3b545da21f..2ebd09a0da 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/text/SubtitleDecoderFactory.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/text/SubtitleDecoderFactory.java @@ -24,6 +24,7 @@ import androidx.media3.extractor.text.SubtitleDecoder; import androidx.media3.extractor.text.SubtitleParser; import androidx.media3.extractor.text.cea.Cea608Decoder; import androidx.media3.extractor.text.cea.Cea708Decoder; +import androidx.media3.extractor.text.ttml.TtmlDecoder; import java.util.Objects; /** A factory for {@link SubtitleDecoder} instances. */ @@ -54,6 +55,7 @@ public interface SubtitleDecoderFactory { *

Supports formats supported by {@link DefaultSubtitleParserFactory} as well as the following: * *

*/ @UnstableApi @@ -57,8 +55,7 @@ public final class DefaultSubtitleParserFactory implements SubtitleParser.Factor || Objects.equals(mimeType, MimeTypes.APPLICATION_SUBRIP) || Objects.equals(mimeType, MimeTypes.APPLICATION_TX3G) || Objects.equals(mimeType, MimeTypes.APPLICATION_PGS) - || Objects.equals(mimeType, MimeTypes.APPLICATION_DVBSUBS) - || Objects.equals(mimeType, MimeTypes.APPLICATION_TTML); + || Objects.equals(mimeType, MimeTypes.APPLICATION_DVBSUBS); } @Override @@ -80,8 +77,6 @@ public final class DefaultSubtitleParserFactory implements SubtitleParser.Factor return new PgsParser(); case MimeTypes.APPLICATION_DVBSUBS: return new DvbParser(format.initializationData); - case MimeTypes.APPLICATION_TTML: - return new TtmlParser(); default: break; } diff --git a/libraries/extractor/src/main/java/androidx/media3/extractor/text/ttml/TtmlParser.java b/libraries/extractor/src/main/java/androidx/media3/extractor/text/ttml/TtmlDecoder.java similarity index 97% rename from libraries/extractor/src/main/java/androidx/media3/extractor/text/ttml/TtmlParser.java rename to libraries/extractor/src/main/java/androidx/media3/extractor/text/ttml/TtmlDecoder.java index ab8c0ea43f..f9dea101f1 100644 --- a/libraries/extractor/src/main/java/androidx/media3/extractor/text/ttml/TtmlParser.java +++ b/libraries/extractor/src/main/java/androidx/media3/extractor/text/ttml/TtmlDecoder.java @@ -15,8 +15,6 @@ */ package androidx.media3.extractor.text.ttml; -import static androidx.media3.common.util.Assertions.checkArgument; -import static androidx.media3.common.util.Assertions.checkNotNull; import static java.lang.Math.max; import static java.lang.Math.min; @@ -31,12 +29,10 @@ import androidx.media3.common.util.Log; import androidx.media3.common.util.UnstableApi; import androidx.media3.common.util.Util; import androidx.media3.common.util.XmlPullParserUtil; -import androidx.media3.extractor.text.CuesWithTiming; import androidx.media3.extractor.text.SimpleSubtitleDecoder; +import androidx.media3.extractor.text.Subtitle; import androidx.media3.extractor.text.SubtitleDecoderException; -import androidx.media3.extractor.text.SubtitleParser; import com.google.common.base.Ascii; -import com.google.common.collect.ImmutableList; import java.io.ByteArrayInputStream; import java.io.IOException; import java.util.ArrayDeque; @@ -72,9 +68,9 @@ import org.xmlpull.v1.XmlPullParserFactory; *

See the TTML specification */ @UnstableApi -public final class TtmlParser implements SubtitleParser { +public final class TtmlDecoder extends SimpleSubtitleDecoder { - private static final String TAG = "TtmlParser"; + private static final String TAG = "TtmlDecoder"; private static final String TTP = "http://www.w3.org/ns/ttml#parameter"; @@ -108,7 +104,8 @@ public final class TtmlParser implements SubtitleParser { private final XmlPullParserFactory xmlParserFactory; - public TtmlParser() { + public TtmlDecoder() { + super("TtmlDecoder"); try { xmlParserFactory = XmlPullParserFactory.newInstance(); xmlParserFactory.setNamespaceAware(true); @@ -117,16 +114,16 @@ public final class TtmlParser implements SubtitleParser { } } - @Nullable @Override - public ImmutableList parse(byte[] data, int offset, int length) { + protected Subtitle decode(byte[] data, int length, boolean reset) + throws SubtitleDecoderException { try { XmlPullParser xmlParser = xmlParserFactory.newPullParser(); Map globalStyles = new HashMap<>(); Map regionMap = new HashMap<>(); Map imageMap = new HashMap<>(); regionMap.put(TtmlNode.ANONYMOUS_REGION_ID, new TtmlRegion(TtmlNode.ANONYMOUS_REGION_ID)); - ByteArrayInputStream inputStream = new ByteArrayInputStream(data, offset, length); + ByteArrayInputStream inputStream = new ByteArrayInputStream(data, 0, length); xmlParser.setInput(inputStream, null); @Nullable TtmlSubtitle ttmlSubtitle = null; ArrayDeque nodeStack = new ArrayDeque<>(); @@ -183,15 +180,20 @@ public final class TtmlParser implements SubtitleParser { xmlParser.next(); eventType = xmlParser.getEventType(); } - return checkNotNull(ttmlSubtitle).toCuesWithTimingList(); + if (ttmlSubtitle != null) { + return ttmlSubtitle; + } else { + throw new SubtitleDecoderException("No TTML subtitles found"); + } } catch (XmlPullParserException xppe) { - throw new IllegalStateException("Unable to decode source", xppe); + throw new SubtitleDecoderException("Unable to decode source", xppe); } catch (IOException e) { throw new IllegalStateException("Unexpected error when reading input.", e); } } - private static FrameAndTickRate parseFrameAndTickRates(XmlPullParser xmlParser) { + private static FrameAndTickRate parseFrameAndTickRates(XmlPullParser xmlParser) + throws SubtitleDecoderException { int frameRate = DEFAULT_FRAME_RATE; String frameRateString = xmlParser.getAttributeValue(TTP, "frameRate"); if (frameRateString != null) { @@ -202,7 +204,9 @@ public final class TtmlParser implements SubtitleParser { String frameRateMultiplierString = xmlParser.getAttributeValue(TTP, "frameRateMultiplier"); if (frameRateMultiplierString != null) { String[] parts = Util.split(frameRateMultiplierString, " "); - checkArgument(parts.length == 2, "frameRateMultiplier doesn't have 2 parts"); + if (parts.length != 2) { + throw new SubtitleDecoderException("frameRateMultiplier doesn't have 2 parts"); + } float numerator = Integer.parseInt(parts[0]); float denominator = Integer.parseInt(parts[1]); frameRateMultiplier = numerator / denominator; @@ -223,7 +227,7 @@ public final class TtmlParser implements SubtitleParser { } private static CellResolution parseCellResolution( - XmlPullParser xmlParser, CellResolution defaultValue) { + XmlPullParser xmlParser, CellResolution defaultValue) throws SubtitleDecoderException { String cellResolution = xmlParser.getAttributeValue(TTP, "cellResolution"); if (cellResolution == null) { return defaultValue; @@ -237,7 +241,9 @@ public final class TtmlParser implements SubtitleParser { try { int columns = Integer.parseInt(Assertions.checkNotNull(cellResolutionMatcher.group(1))); int rows = Integer.parseInt(Assertions.checkNotNull(cellResolutionMatcher.group(2))); - checkArgument(columns != 0 && rows != 0, "Invalid cell resolution " + columns + " " + rows); + if (columns == 0 || rows == 0) { + throw new SubtitleDecoderException("Invalid cell resolution " + columns + " " + rows); + } return new CellResolution(columns, rows); } catch (NumberFormatException e) { Log.w(TAG, "Ignoring malformed cell resolution: " + cellResolution); diff --git a/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/text/DelegatingSubtitleDecoderTtmlParserTest.java b/libraries/extractor/src/test/java/androidx/media3/extractor/text/ttml/TtmlDecoderTest.java similarity index 88% rename from libraries/exoplayer/src/test/java/androidx/media3/exoplayer/text/DelegatingSubtitleDecoderTtmlParserTest.java rename to libraries/extractor/src/test/java/androidx/media3/extractor/text/ttml/TtmlDecoderTest.java index 0b69807a89..02092ef714 100644 --- a/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/text/DelegatingSubtitleDecoderTtmlParserTest.java +++ b/libraries/extractor/src/test/java/androidx/media3/extractor/text/ttml/TtmlDecoderTest.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package androidx.media3.exoplayer.text; +package androidx.media3.extractor.text.ttml; import static androidx.media3.test.utils.truth.SpannedSubject.assertThat; import static com.google.common.truth.Truth.assertThat; @@ -27,7 +27,7 @@ import androidx.media3.common.util.Assertions; import androidx.media3.common.util.ColorParser; import androidx.media3.extractor.text.CuesWithTiming; import androidx.media3.extractor.text.Subtitle; -import androidx.media3.extractor.text.ttml.TtmlParser; +import androidx.media3.extractor.text.SubtitleDecoderException; import androidx.media3.test.utils.TestUtil; import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; @@ -37,9 +37,9 @@ import java.util.List; import org.junit.Test; import org.junit.runner.RunWith; -/** Unit test for {@link TtmlParser}. */ +/** Unit test for {@link TtmlDecoder}. */ @RunWith(AndroidJUnit4.class) -public final class DelegatingSubtitleDecoderTtmlParserTest { +public final class TtmlDecoderTest { private static final String INLINE_ATTRIBUTES_TTML_FILE = "media/ttml/inline_style_attributes.xml"; @@ -73,8 +73,8 @@ public final class DelegatingSubtitleDecoderTtmlParserTest { private static final String SHEAR_FILE = "media/ttml/shear.xml"; @Test - public void inlineAttributes() throws IOException { - Subtitle subtitle = getSubtitle(INLINE_ATTRIBUTES_TTML_FILE); + public void inlineAttributes() throws IOException, SubtitleDecoderException { + TtmlSubtitle subtitle = getSubtitle(INLINE_ATTRIBUTES_TTML_FILE); assertThat(subtitle.getEventTimeCount()).isEqualTo(4); @@ -92,8 +92,8 @@ public final class DelegatingSubtitleDecoderTtmlParserTest { } @Test - public void inheritInlineAttributes() throws IOException { - Subtitle subtitle = getSubtitle(INLINE_ATTRIBUTES_TTML_FILE); + public void inheritInlineAttributes() throws IOException, SubtitleDecoderException { + TtmlSubtitle subtitle = getSubtitle(INLINE_ATTRIBUTES_TTML_FILE); assertThat(subtitle.getEventTimeCount()).isEqualTo(4); @@ -118,8 +118,8 @@ public final class DelegatingSubtitleDecoderTtmlParserTest { // KitKat Color: // https://github.com/android/platform_frameworks_base/blob/kitkat-mr2.2-release/graphics/java/android/graphics/Color.java#L414 @Test - public void lime() throws IOException { - Subtitle subtitle = getSubtitle(INLINE_ATTRIBUTES_TTML_FILE); + public void lime() throws IOException, SubtitleDecoderException { + TtmlSubtitle subtitle = getSubtitle(INLINE_ATTRIBUTES_TTML_FILE); assertThat(subtitle.getEventTimeCount()).isEqualTo(4); @@ -133,8 +133,8 @@ public final class DelegatingSubtitleDecoderTtmlParserTest { } @Test - public void inheritGlobalStyle() throws IOException { - Subtitle subtitle = getSubtitle(INHERIT_STYLE_TTML_FILE); + public void inheritGlobalStyle() throws IOException, SubtitleDecoderException { + TtmlSubtitle subtitle = getSubtitle(INHERIT_STYLE_TTML_FILE); assertThat(subtitle.getEventTimeCount()).isEqualTo(2); @@ -148,8 +148,9 @@ public final class DelegatingSubtitleDecoderTtmlParserTest { } @Test - public void inheritGlobalStyleOverriddenByInlineAttributes() throws IOException { - Subtitle subtitle = getSubtitle(INHERIT_STYLE_OVERRIDE_TTML_FILE); + public void inheritGlobalStyleOverriddenByInlineAttributes() + throws IOException, SubtitleDecoderException { + TtmlSubtitle subtitle = getSubtitle(INHERIT_STYLE_OVERRIDE_TTML_FILE); assertThat(subtitle.getEventTimeCount()).isEqualTo(4); @@ -181,8 +182,8 @@ public final class DelegatingSubtitleDecoderTtmlParserTest { } @Test - public void inheritGlobalAndParent() throws IOException { - Subtitle subtitle = getSubtitle(INHERIT_GLOBAL_AND_PARENT_TTML_FILE); + public void inheritGlobalAndParent() throws IOException, SubtitleDecoderException { + TtmlSubtitle subtitle = getSubtitle(INHERIT_GLOBAL_AND_PARENT_TTML_FILE); assertThat(subtitle.getEventTimeCount()).isEqualTo(4); @@ -214,8 +215,8 @@ public final class DelegatingSubtitleDecoderTtmlParserTest { } @Test - public void inheritMultipleStyles() throws IOException { - Subtitle subtitle = getSubtitle(INHERIT_MULTIPLE_STYLES_TTML_FILE); + public void inheritMultipleStyles() throws IOException, SubtitleDecoderException { + TtmlSubtitle subtitle = getSubtitle(INHERIT_MULTIPLE_STYLES_TTML_FILE); assertThat(subtitle.getEventTimeCount()).isEqualTo(12); @@ -229,8 +230,9 @@ public final class DelegatingSubtitleDecoderTtmlParserTest { } @Test - public void inheritMultipleStylesWithoutLocalAttributes() throws IOException { - Subtitle subtitle = getSubtitle(INHERIT_MULTIPLE_STYLES_TTML_FILE); + public void inheritMultipleStylesWithoutLocalAttributes() + throws IOException, SubtitleDecoderException { + TtmlSubtitle subtitle = getSubtitle(INHERIT_MULTIPLE_STYLES_TTML_FILE); assertThat(subtitle.getEventTimeCount()).isEqualTo(12); @@ -250,8 +252,8 @@ public final class DelegatingSubtitleDecoderTtmlParserTest { } @Test - public void mergeMultipleStylesWithParentStyle() throws IOException { - Subtitle subtitle = getSubtitle(INHERIT_MULTIPLE_STYLES_TTML_FILE); + public void mergeMultipleStylesWithParentStyle() throws IOException, SubtitleDecoderException { + TtmlSubtitle subtitle = getSubtitle(INHERIT_MULTIPLE_STYLES_TTML_FILE); assertThat(subtitle.getEventTimeCount()).isEqualTo(12); @@ -272,8 +274,8 @@ public final class DelegatingSubtitleDecoderTtmlParserTest { } @Test - public void multipleRegions() throws IOException { - Subtitle subtitle = getSubtitle(MULTIPLE_REGIONS_TTML_FILE); + public void multipleRegions() throws IOException, SubtitleDecoderException { + TtmlSubtitle subtitle = getSubtitle(MULTIPLE_REGIONS_TTML_FILE); List cues = subtitle.getCues(1_000_000); assertThat(cues).hasSize(2); @@ -321,8 +323,8 @@ public final class DelegatingSubtitleDecoderTtmlParserTest { } @Test - public void emptyStyleAttribute() throws IOException { - Subtitle subtitle = getSubtitle(INHERIT_MULTIPLE_STYLES_TTML_FILE); + public void emptyStyleAttribute() throws IOException, SubtitleDecoderException { + TtmlSubtitle subtitle = getSubtitle(INHERIT_MULTIPLE_STYLES_TTML_FILE); assertThat(subtitle.getEventTimeCount()).isEqualTo(12); @@ -333,8 +335,8 @@ public final class DelegatingSubtitleDecoderTtmlParserTest { } @Test - public void nonexistingStyleId() throws IOException { - Subtitle subtitle = getSubtitle(INHERIT_MULTIPLE_STYLES_TTML_FILE); + public void nonexistingStyleId() throws IOException, SubtitleDecoderException { + TtmlSubtitle subtitle = getSubtitle(INHERIT_MULTIPLE_STYLES_TTML_FILE); assertThat(subtitle.getEventTimeCount()).isEqualTo(12); @@ -345,8 +347,9 @@ public final class DelegatingSubtitleDecoderTtmlParserTest { } @Test - public void nonExistingAndExistingStyleIdWithRedundantSpaces() throws IOException { - Subtitle subtitle = getSubtitle(INHERIT_MULTIPLE_STYLES_TTML_FILE); + public void nonExistingAndExistingStyleIdWithRedundantSpaces() + throws IOException, SubtitleDecoderException { + TtmlSubtitle subtitle = getSubtitle(INHERIT_MULTIPLE_STYLES_TTML_FILE); assertThat(subtitle.getEventTimeCount()).isEqualTo(12); @@ -356,8 +359,8 @@ public final class DelegatingSubtitleDecoderTtmlParserTest { } @Test - public void multipleChaining() throws IOException { - Subtitle subtitle = getSubtitle(CHAIN_MULTIPLE_STYLES_TTML_FILE); + public void multipleChaining() throws IOException, SubtitleDecoderException { + TtmlSubtitle subtitle = getSubtitle(CHAIN_MULTIPLE_STYLES_TTML_FILE); assertThat(subtitle.getEventTimeCount()).isEqualTo(4); @@ -380,8 +383,8 @@ public final class DelegatingSubtitleDecoderTtmlParserTest { } @Test - public void noUnderline() throws IOException { - Subtitle subtitle = getSubtitle(NO_UNDERLINE_LINETHROUGH_TTML_FILE); + public void noUnderline() throws IOException, SubtitleDecoderException { + TtmlSubtitle subtitle = getSubtitle(NO_UNDERLINE_LINETHROUGH_TTML_FILE); assertThat(subtitle.getEventTimeCount()).isEqualTo(4); @@ -392,8 +395,8 @@ public final class DelegatingSubtitleDecoderTtmlParserTest { } @Test - public void noLinethrough() throws IOException { - Subtitle subtitle = getSubtitle(NO_UNDERLINE_LINETHROUGH_TTML_FILE); + public void noLinethrough() throws IOException, SubtitleDecoderException { + TtmlSubtitle subtitle = getSubtitle(NO_UNDERLINE_LINETHROUGH_TTML_FILE); assertThat(subtitle.getEventTimeCount()).isEqualTo(4); @@ -404,8 +407,8 @@ public final class DelegatingSubtitleDecoderTtmlParserTest { } @Test - public void fontSizeSpans() throws IOException { - Subtitle subtitle = getSubtitle(FONT_SIZE_TTML_FILE); + public void fontSizeSpans() throws IOException, SubtitleDecoderException { + TtmlSubtitle subtitle = getSubtitle(FONT_SIZE_TTML_FILE); assertThat(subtitle.getEventTimeCount()).isEqualTo(10); @@ -431,8 +434,8 @@ public final class DelegatingSubtitleDecoderTtmlParserTest { } @Test - public void fontSizeWithMissingUnitIsIgnored() throws IOException { - Subtitle subtitle = getSubtitle(FONT_SIZE_MISSING_UNIT_TTML_FILE); + public void fontSizeWithMissingUnitIsIgnored() throws IOException, SubtitleDecoderException { + TtmlSubtitle subtitle = getSubtitle(FONT_SIZE_MISSING_UNIT_TTML_FILE); assertThat(subtitle.getEventTimeCount()).isEqualTo(2); @@ -443,8 +446,8 @@ public final class DelegatingSubtitleDecoderTtmlParserTest { } @Test - public void fontSizeWithInvalidValueIsIgnored() throws IOException { - Subtitle subtitle = getSubtitle(FONT_SIZE_INVALID_TTML_FILE); + public void fontSizeWithInvalidValueIsIgnored() throws IOException, SubtitleDecoderException { + TtmlSubtitle subtitle = getSubtitle(FONT_SIZE_INVALID_TTML_FILE); assertThat(subtitle.getEventTimeCount()).isEqualTo(6); @@ -465,8 +468,8 @@ public final class DelegatingSubtitleDecoderTtmlParserTest { } @Test - public void fontSizeWithEmptyValueIsIgnored() throws IOException { - Subtitle subtitle = getSubtitle(FONT_SIZE_EMPTY_TTML_FILE); + public void fontSizeWithEmptyValueIsIgnored() throws IOException, SubtitleDecoderException { + TtmlSubtitle subtitle = getSubtitle(FONT_SIZE_EMPTY_TTML_FILE); assertThat(subtitle.getEventTimeCount()).isEqualTo(2); @@ -477,8 +480,8 @@ public final class DelegatingSubtitleDecoderTtmlParserTest { } @Test - public void frameRate() throws IOException { - Subtitle subtitle = getSubtitle(FRAME_RATE_TTML_FILE); + public void frameRate() throws IOException, SubtitleDecoderException { + TtmlSubtitle subtitle = getSubtitle(FRAME_RATE_TTML_FILE); assertThat(subtitle.getEventTimeCount()).isEqualTo(4); assertThat(subtitle.getEventTime(0)).isEqualTo(1_000_000); @@ -488,8 +491,8 @@ public final class DelegatingSubtitleDecoderTtmlParserTest { } @Test - public void bitmapPercentageRegion() throws IOException { - Subtitle subtitle = getSubtitle(BITMAP_REGION_FILE); + public void bitmapPercentageRegion() throws IOException, SubtitleDecoderException { + TtmlSubtitle subtitle = getSubtitle(BITMAP_REGION_FILE); Cue cue = getOnlyCueAtTimeUs(subtitle, 1_000_000); assertThat(cue.text).isNull(); @@ -517,8 +520,8 @@ public final class DelegatingSubtitleDecoderTtmlParserTest { } @Test - public void bitmapPixelRegion() throws IOException { - Subtitle subtitle = getSubtitle(BITMAP_PIXEL_REGION_FILE); + public void bitmapPixelRegion() throws IOException, SubtitleDecoderException { + TtmlSubtitle subtitle = getSubtitle(BITMAP_PIXEL_REGION_FILE); Cue cue = getOnlyCueAtTimeUs(subtitle, 1_000_000); assertThat(cue.text).isNull(); @@ -538,8 +541,8 @@ public final class DelegatingSubtitleDecoderTtmlParserTest { } @Test - public void bitmapUnsupportedRegion() throws IOException { - Subtitle subtitle = getSubtitle(BITMAP_UNSUPPORTED_REGION_FILE); + public void bitmapUnsupportedRegion() throws IOException, SubtitleDecoderException { + TtmlSubtitle subtitle = getSubtitle(BITMAP_UNSUPPORTED_REGION_FILE); Cue cue = getOnlyCueAtTimeUs(subtitle, 1_000_000); assertThat(cue.text).isNull(); @@ -559,8 +562,8 @@ public final class DelegatingSubtitleDecoderTtmlParserTest { } @Test - public void textAlign() throws IOException { - Subtitle subtitle = getSubtitle(TEXT_ALIGN_FILE); + public void textAlign() throws IOException, SubtitleDecoderException { + TtmlSubtitle subtitle = getSubtitle(TEXT_ALIGN_FILE); Cue firstCue = getOnlyCueAtTimeUs(subtitle, 10_000_000); assertThat(firstCue.text.toString()).isEqualTo("Start alignment"); @@ -600,8 +603,8 @@ public final class DelegatingSubtitleDecoderTtmlParserTest { } @Test - public void multiRowAlign() throws IOException { - Subtitle subtitle = getSubtitle(MULTI_ROW_ALIGN_FILE); + public void multiRowAlign() throws IOException, SubtitleDecoderException { + TtmlSubtitle subtitle = getSubtitle(MULTI_ROW_ALIGN_FILE); Cue firstCue = getOnlyCueAtTimeUs(subtitle, 10_000_000); assertThat(firstCue.multiRowAlignment).isEqualTo(Layout.Alignment.ALIGN_NORMAL); @@ -626,8 +629,8 @@ public final class DelegatingSubtitleDecoderTtmlParserTest { } @Test - public void verticalText() throws IOException { - Subtitle subtitle = getSubtitle(VERTICAL_TEXT_FILE); + public void verticalText() throws IOException, SubtitleDecoderException { + TtmlSubtitle subtitle = getSubtitle(VERTICAL_TEXT_FILE); Cue firstCue = getOnlyCueAtTimeUs(subtitle, 10_000_000); assertThat(firstCue.verticalType).isEqualTo(Cue.VERTICAL_TYPE_RL); @@ -640,8 +643,8 @@ public final class DelegatingSubtitleDecoderTtmlParserTest { } @Test - public void textCombine() throws IOException { - Subtitle subtitle = getSubtitle(TEXT_COMBINE_FILE); + public void textCombine() throws IOException, SubtitleDecoderException { + TtmlSubtitle subtitle = getSubtitle(TEXT_COMBINE_FILE); Spanned firstCue = getOnlyCueTextAtTimeUs(subtitle, 10_000_000); assertThat(firstCue) @@ -658,8 +661,8 @@ public final class DelegatingSubtitleDecoderTtmlParserTest { } @Test - public void rubies() throws IOException { - Subtitle subtitle = getSubtitle(RUBIES_FILE); + public void rubies() throws IOException, SubtitleDecoderException { + TtmlSubtitle subtitle = getSubtitle(RUBIES_FILE); Spanned firstCue = getOnlyCueTextAtTimeUs(subtitle, 10_000_000); assertThat(firstCue.toString()).isEqualTo("Cue with annotated text."); @@ -678,9 +681,7 @@ public final class DelegatingSubtitleDecoderTtmlParserTest { Spanned thirdCue = getOnlyCueTextAtTimeUs(subtitle, 30_000_000); assertThat(thirdCue.toString()).isEqualTo("Cue with annotated text."); - assertThat(thirdCue) - .hasRubySpanBetween("Cue with ".length(), "Cue with annotated".length()) - .withTextAndPosition("rubies", TextAnnotation.POSITION_UNKNOWN); + assertThat(thirdCue).hasRubySpanBetween("Cue with ".length(), "Cue with annotated".length()); Spanned fourthCue = getOnlyCueTextAtTimeUs(subtitle, 40_000_000); assertThat(fourthCue.toString()).isEqualTo("Cue with annotated text."); @@ -708,8 +709,8 @@ public final class DelegatingSubtitleDecoderTtmlParserTest { } @Test - public void textEmphasis() throws IOException { - Subtitle subtitle = getSubtitle(TEXT_EMPHASIS_FILE); + public void textEmphasis() throws IOException, SubtitleDecoderException { + TtmlSubtitle subtitle = getSubtitle(TEXT_EMPHASIS_FILE); Spanned firstCue = getOnlyCueTextAtTimeUs(subtitle, 10_000_000); assertThat(firstCue) @@ -848,8 +849,8 @@ public final class DelegatingSubtitleDecoderTtmlParserTest { } @Test - public void shear() throws IOException { - Subtitle subtitle = getSubtitle(SHEAR_FILE); + public void shear() throws IOException, SubtitleDecoderException { + TtmlSubtitle subtitle = getSubtitle(SHEAR_FILE); Cue firstCue = getOnlyCueAtTimeUs(subtitle, 10_000_000); assertThat(firstCue.shearDegrees).isZero(); @@ -877,8 +878,8 @@ public final class DelegatingSubtitleDecoderTtmlParserTest { } @Test - public void toCuesWithTimingConversion() throws IOException { - Subtitle subtitle = getSubtitle(INLINE_ATTRIBUTES_TTML_FILE); + public void toCuesWithTimingConversion() throws IOException, SubtitleDecoderException { + TtmlSubtitle subtitle = getSubtitle(INLINE_ATTRIBUTES_TTML_FILE); ImmutableList cuesWithTimingsList = subtitle.toCuesWithTimingList(); assertThat(subtitle.getEventTimeCount()).isEqualTo(4); @@ -921,10 +922,10 @@ public final class DelegatingSubtitleDecoderTtmlParserTest { return cues.get(0); } - private static Subtitle getSubtitle(String file) throws IOException { - DelegatingSubtitleDecoder ttmlDecoder = - new DelegatingSubtitleDecoder("TtmlParserDecoder", new TtmlParser()); + private static TtmlSubtitle getSubtitle(String file) + throws IOException, SubtitleDecoderException { + TtmlDecoder ttmlDecoder = new TtmlDecoder(); byte[] bytes = TestUtil.getByteArray(ApplicationProvider.getApplicationContext(), file); - return ttmlDecoder.decode(bytes, bytes.length, false); + return (TtmlSubtitle) ttmlDecoder.decode(bytes, bytes.length, false); } } diff --git a/libraries/extractor/src/test/java/androidx/media3/extractor/text/ttml/TtmlParserTest.java b/libraries/extractor/src/test/java/androidx/media3/extractor/text/ttml/TtmlParserTest.java deleted file mode 100644 index 14b883756e..0000000000 --- a/libraries/extractor/src/test/java/androidx/media3/extractor/text/ttml/TtmlParserTest.java +++ /dev/null @@ -1,920 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package androidx.media3.extractor.text.ttml; - -import static androidx.media3.test.utils.truth.SpannedSubject.assertThat; -import static com.google.common.truth.Truth.assertThat; - -import android.text.Layout; -import android.text.Spanned; -import androidx.media3.common.text.Cue; -import androidx.media3.common.text.TextAnnotation; -import androidx.media3.common.text.TextEmphasisSpan; -import androidx.media3.common.util.Assertions; -import androidx.media3.common.util.ColorParser; -import androidx.media3.extractor.text.CuesWithTiming; -import androidx.media3.test.utils.TestUtil; -import androidx.test.core.app.ApplicationProvider; -import androidx.test.ext.junit.runners.AndroidJUnit4; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.Iterables; -import org.junit.Test; -import org.junit.runner.RunWith; - -/** Unit test for {@link TtmlParser}. */ -@RunWith(AndroidJUnit4.class) -public final class TtmlParserTest { - - private static final String INLINE_ATTRIBUTES_TTML_FILE = - "media/ttml/inline_style_attributes.xml"; - private static final String INHERIT_STYLE_TTML_FILE = "media/ttml/inherit_style.xml"; - private static final String INHERIT_STYLE_OVERRIDE_TTML_FILE = - "media/ttml/inherit_and_override_style.xml"; - private static final String INHERIT_GLOBAL_AND_PARENT_TTML_FILE = - "media/ttml/inherit_global_and_parent.xml"; - private static final String INHERIT_MULTIPLE_STYLES_TTML_FILE = - "media/ttml/inherit_multiple_styles.xml"; - private static final String CHAIN_MULTIPLE_STYLES_TTML_FILE = - "media/ttml/chain_multiple_styles.xml"; - private static final String MULTIPLE_REGIONS_TTML_FILE = "media/ttml/multiple_regions.xml"; - private static final String NO_UNDERLINE_LINETHROUGH_TTML_FILE = - "media/ttml/no_underline_linethrough.xml"; - private static final String FONT_SIZE_TTML_FILE = "media/ttml/font_size.xml"; - private static final String FONT_SIZE_MISSING_UNIT_TTML_FILE = "media/ttml/font_size_no_unit.xml"; - private static final String FONT_SIZE_INVALID_TTML_FILE = "media/ttml/font_size_invalid.xml"; - private static final String FONT_SIZE_EMPTY_TTML_FILE = "media/ttml/font_size_empty.xml"; - private static final String FRAME_RATE_TTML_FILE = "media/ttml/frame_rate.xml"; - private static final String BITMAP_REGION_FILE = "media/ttml/bitmap_percentage_region.xml"; - private static final String BITMAP_PIXEL_REGION_FILE = "media/ttml/bitmap_pixel_region.xml"; - private static final String BITMAP_UNSUPPORTED_REGION_FILE = - "media/ttml/bitmap_unsupported_region.xml"; - private static final String TEXT_ALIGN_FILE = "media/ttml/text_align.xml"; - private static final String MULTI_ROW_ALIGN_FILE = "media/ttml/multi_row_align.xml"; - private static final String VERTICAL_TEXT_FILE = "media/ttml/vertical_text.xml"; - private static final String TEXT_COMBINE_FILE = "media/ttml/text_combine.xml"; - private static final String RUBIES_FILE = "media/ttml/rubies.xml"; - private static final String TEXT_EMPHASIS_FILE = "media/ttml/text_emphasis.xml"; - private static final String SHEAR_FILE = "media/ttml/shear.xml"; - - @Test - public void inlineAttributes() throws Exception { - ImmutableList allCues = getAllCues(INLINE_ATTRIBUTES_TTML_FILE); - - assertThat(allCues).hasSize(2); - - Spanned spanned = getOnlyCueTextAtIndex(allCues, 0); - assertThat(spanned.toString()).isEqualTo("text 1"); - assertThat(spanned).hasTypefaceSpanBetween(0, spanned.length()).withFamily("serif"); - assertThat(spanned).hasBoldItalicSpanBetween(0, spanned.length()); - assertThat(spanned).hasUnderlineSpanBetween(0, spanned.length()); - assertThat(spanned) - .hasBackgroundColorSpanBetween(0, spanned.length()) - .withColor(ColorParser.parseTtmlColor("blue")); - assertThat(spanned) - .hasForegroundColorSpanBetween(0, spanned.length()) - .withColor(ColorParser.parseTtmlColor("yellow")); - } - - @Test - public void inheritInlineAttributes() throws Exception { - ImmutableList allCues = getAllCues(INLINE_ATTRIBUTES_TTML_FILE); - - assertThat(allCues).hasSize(2); - - Spanned spanned = getOnlyCueTextAtIndex(allCues, 1); - assertThat(spanned.toString()).isEqualTo("text 2"); - assertThat(spanned).hasTypefaceSpanBetween(0, spanned.length()).withFamily("sansSerif"); - assertThat(spanned).hasItalicSpanBetween(0, spanned.length()); - assertThat(spanned).hasStrikethroughSpanBetween(0, spanned.length()); - assertThat(spanned).hasBackgroundColorSpanBetween(0, spanned.length()).withColor(0xFF00FFFF); - assertThat(spanned) - .hasForegroundColorSpanBetween(0, spanned.length()) - .withColor(ColorParser.parseTtmlColor("lime")); - } - - /** - * Regression test for devices on JellyBean where some named colors are not correctly defined on - * framework level. Tests that lime resolves to #FF00FF00 not #00FF00 - * . - */ - // JellyBean Color: - // https://github.com/android/platform_frameworks_base/blob/jb-mr2-release/graphics/java/android/graphics/Color.java#L414 - // KitKat Color: - // https://github.com/android/platform_frameworks_base/blob/kitkat-mr2.2-release/graphics/java/android/graphics/Color.java#L414 - @Test - public void lime() throws Exception { - ImmutableList allCues = getAllCues(INLINE_ATTRIBUTES_TTML_FILE); - - assertThat(allCues).hasSize(2); - - Spanned spanned = getOnlyCueTextAtIndex(allCues, 1); - assertThat(spanned.toString()).isEqualTo("text 2"); - assertThat(spanned).hasTypefaceSpanBetween(0, spanned.length()).withFamily("sansSerif"); - assertThat(spanned).hasItalicSpanBetween(0, spanned.length()); - assertThat(spanned).hasStrikethroughSpanBetween(0, spanned.length()); - assertThat(spanned).hasBackgroundColorSpanBetween(0, spanned.length()).withColor(0xFF00FFFF); - assertThat(spanned).hasForegroundColorSpanBetween(0, spanned.length()).withColor(0xFF00FF00); - } - - @Test - public void inheritGlobalStyle() throws Exception { - ImmutableList allCues = getAllCues(INHERIT_STYLE_TTML_FILE); - - assertThat(allCues).hasSize(1); - - Spanned spanned = getOnlyCueTextAtIndex(allCues, 0); - assertThat(spanned.toString()).isEqualTo("text 1"); - assertThat(spanned).hasTypefaceSpanBetween(0, spanned.length()).withFamily("serif"); - assertThat(spanned).hasBoldItalicSpanBetween(0, spanned.length()); - assertThat(spanned).hasUnderlineSpanBetween(0, spanned.length()); - assertThat(spanned).hasBackgroundColorSpanBetween(0, spanned.length()).withColor(0xFF0000FF); - assertThat(spanned).hasForegroundColorSpanBetween(0, spanned.length()).withColor(0xFFFFFF00); - } - - @Test - public void inheritGlobalStyleOverriddenByInlineAttributes() throws Exception { - ImmutableList allCues = getAllCues(INHERIT_STYLE_OVERRIDE_TTML_FILE); - - assertThat(allCues).hasSize(2); - - Spanned firstCueText = getOnlyCueTextAtIndex(allCues, 0); - assertThat(firstCueText.toString()).isEqualTo("text 1"); - assertThat(firstCueText).hasTypefaceSpanBetween(0, firstCueText.length()).withFamily("serif"); - assertThat(firstCueText).hasBoldItalicSpanBetween(0, firstCueText.length()); - assertThat(firstCueText).hasUnderlineSpanBetween(0, firstCueText.length()); - assertThat(firstCueText) - .hasBackgroundColorSpanBetween(0, firstCueText.length()) - .withColor(0xFF0000FF); - assertThat(firstCueText) - .hasForegroundColorSpanBetween(0, firstCueText.length()) - .withColor(0xFFFFFF00); - - Spanned secondCueText = getOnlyCueTextAtIndex(allCues, 1); - assertThat(secondCueText.toString()).isEqualTo("text 2"); - assertThat(secondCueText) - .hasTypefaceSpanBetween(0, secondCueText.length()) - .withFamily("sansSerif"); - assertThat(secondCueText).hasItalicSpanBetween(0, secondCueText.length()); - assertThat(secondCueText).hasUnderlineSpanBetween(0, secondCueText.length()); - assertThat(secondCueText) - .hasBackgroundColorSpanBetween(0, secondCueText.length()) - .withColor(0xFFFF0000); - assertThat(secondCueText) - .hasForegroundColorSpanBetween(0, secondCueText.length()) - .withColor(0xFFFFFF00); - } - - @Test - public void inheritGlobalAndParent() throws Exception { - ImmutableList allCues = getAllCues(INHERIT_GLOBAL_AND_PARENT_TTML_FILE); - - assertThat(allCues).hasSize(2); - - Spanned firstCueText = getOnlyCueTextAtIndex(allCues, 0); - assertThat(firstCueText.toString()).isEqualTo("text 1"); - assertThat(firstCueText) - .hasTypefaceSpanBetween(0, firstCueText.length()) - .withFamily("sansSerif"); - assertThat(firstCueText).hasStrikethroughSpanBetween(0, firstCueText.length()); - assertThat(firstCueText) - .hasBackgroundColorSpanBetween(0, firstCueText.length()) - .withColor(0xFFFF0000); - assertThat(firstCueText) - .hasForegroundColorSpanBetween(0, firstCueText.length()) - .withColor(ColorParser.parseTtmlColor("lime")); - - Spanned secondCueText = getOnlyCueTextAtIndex(allCues, 1); - assertThat(secondCueText.toString()).isEqualTo("text 2"); - assertThat(secondCueText).hasTypefaceSpanBetween(0, secondCueText.length()).withFamily("serif"); - assertThat(secondCueText).hasBoldItalicSpanBetween(0, secondCueText.length()); - assertThat(secondCueText).hasUnderlineSpanBetween(0, secondCueText.length()); - assertThat(secondCueText).hasStrikethroughSpanBetween(0, secondCueText.length()); - assertThat(secondCueText) - .hasBackgroundColorSpanBetween(0, secondCueText.length()) - .withColor(0xFF0000FF); - assertThat(secondCueText) - .hasForegroundColorSpanBetween(0, secondCueText.length()) - .withColor(0xFFFFFF00); - } - - @Test - public void inheritMultipleStyles() throws Exception { - ImmutableList allCues = getAllCues(INHERIT_MULTIPLE_STYLES_TTML_FILE); - - assertThat(allCues).hasSize(6); - - Spanned spanned = getOnlyCueTextAtIndex(allCues, 0); - assertThat(spanned.toString()).isEqualTo("text 1"); - assertThat(spanned).hasTypefaceSpanBetween(0, spanned.length()).withFamily("sansSerif"); - assertThat(spanned).hasBoldItalicSpanBetween(0, spanned.length()); - assertThat(spanned).hasStrikethroughSpanBetween(0, spanned.length()); - assertThat(spanned).hasBackgroundColorSpanBetween(0, spanned.length()).withColor(0xFF0000FF); - assertThat(spanned).hasForegroundColorSpanBetween(0, spanned.length()).withColor(0xFFFFFF00); - } - - @Test - public void inheritMultipleStylesWithoutLocalAttributes() throws Exception { - ImmutableList allCues = getAllCues(INHERIT_MULTIPLE_STYLES_TTML_FILE); - - assertThat(allCues).hasSize(6); - - Spanned secondCueText = getOnlyCueTextAtIndex(allCues, 1); - assertThat(secondCueText.toString()).isEqualTo("text 2"); - assertThat(secondCueText) - .hasTypefaceSpanBetween(0, secondCueText.length()) - .withFamily("sansSerif"); - assertThat(secondCueText).hasBoldItalicSpanBetween(0, secondCueText.length()); - assertThat(secondCueText).hasStrikethroughSpanBetween(0, secondCueText.length()); - assertThat(secondCueText) - .hasBackgroundColorSpanBetween(0, secondCueText.length()) - .withColor(0xFF0000FF); - assertThat(secondCueText) - .hasForegroundColorSpanBetween(0, secondCueText.length()) - .withColor(0xFF000000); - } - - @Test - public void mergeMultipleStylesWithParentStyle() throws Exception { - ImmutableList allCues = getAllCues(INHERIT_MULTIPLE_STYLES_TTML_FILE); - - assertThat(allCues).hasSize(6); - - Spanned thirdCueText = getOnlyCueTextAtIndex(allCues, 2); - assertThat(thirdCueText.toString()).isEqualTo("text 2.5"); - assertThat(thirdCueText) - .hasTypefaceSpanBetween(0, thirdCueText.length()) - .withFamily("sansSerifInline"); - assertThat(thirdCueText).hasItalicSpanBetween(0, thirdCueText.length()); - assertThat(thirdCueText).hasUnderlineSpanBetween(0, thirdCueText.length()); - assertThat(thirdCueText).hasStrikethroughSpanBetween(0, thirdCueText.length()); - assertThat(thirdCueText) - .hasBackgroundColorSpanBetween(0, thirdCueText.length()) - .withColor(0xFFFF0000); - assertThat(thirdCueText) - .hasForegroundColorSpanBetween(0, thirdCueText.length()) - .withColor(0xFFFFFF00); - } - - @Test - public void multipleRegions() throws Exception { - ImmutableList allCues = getAllCues(MULTIPLE_REGIONS_TTML_FILE); - - assertThat(allCues).hasSize(6); - - ImmutableList cues = allCues.get(0).cues; - assertThat(cues).hasSize(2); - Cue cue = cues.get(0); - assertThat(cue.text.toString()).isEqualTo("lorem"); - assertThat(cue.position).isEqualTo(10f / 100f); - assertThat(cue.line).isEqualTo(10f / 100f); - assertThat(cue.size).isEqualTo(20f / 100f); - - cue = cues.get(1); - assertThat(cue.text.toString()).isEqualTo("amet"); - assertThat(cue.position).isEqualTo(60f / 100f); - assertThat(cue.line).isEqualTo(10f / 100f); - assertThat(cue.size).isEqualTo(20f / 100f); - - cue = Iterables.getOnlyElement(allCues.get(1).cues); - assertThat(cue.text.toString()).isEqualTo("ipsum"); - assertThat(cue.position).isEqualTo(40f / 100f); - assertThat(cue.line).isEqualTo(40f / 100f); - assertThat(cue.size).isEqualTo(20f / 100f); - - cue = Iterables.getOnlyElement(allCues.get(2).cues); - assertThat(cue.text.toString()).isEqualTo("dolor"); - assertThat(cue.position).isEqualTo(Cue.DIMEN_UNSET); - assertThat(cue.line).isEqualTo(Cue.DIMEN_UNSET); - assertThat(cue.size).isEqualTo(Cue.DIMEN_UNSET); - // TODO: Should be as below, once https://github.com/google/ExoPlayer/issues/2953 is fixed. - // assertEquals(10f / 100f, cue.position); - // assertEquals(80f / 100f, cue.line); - // assertEquals(1f, cue.size); - - cue = Iterables.getOnlyElement(allCues.get(3).cues); - assertThat(cue.text.toString()).isEqualTo("They first said this"); - assertThat(cue.position).isEqualTo(45f / 100f); - assertThat(cue.line).isEqualTo(45f / 100f); - assertThat(cue.size).isEqualTo(35f / 100f); - - cue = Iterables.getOnlyElement(allCues.get(4).cues); - assertThat(cue.text.toString()).isEqualTo("They first said this\nThen this"); - - cue = Iterables.getOnlyElement(allCues.get(5).cues); - assertThat(cue.text.toString()).isEqualTo("They first said this\nThen this\nFinally this"); - assertThat(cue.position).isEqualTo(45f / 100f); - assertThat(cue.line).isEqualTo(45f / 100f); - } - - @Test - public void emptyStyleAttribute() throws Exception { - ImmutableList allCues = getAllCues(INHERIT_MULTIPLE_STYLES_TTML_FILE); - - assertThat(allCues).hasSize(6); - - Spanned spanned = getOnlyCueTextAtIndex(allCues, 3); - - assertThat(allCues.get(3).startTimeUs).isEqualTo(40_000_000); - assertThat(spanned.toString()).isEqualTo("text 3"); - assertThat(spanned).hasNoSpans(); - } - - @Test - public void nonexistingStyleId() throws Exception { - ImmutableList allCues = getAllCues(INHERIT_MULTIPLE_STYLES_TTML_FILE); - - assertThat(allCues).hasSize(6); - - Spanned spanned = getOnlyCueTextAtIndex(allCues, 4); - - assertThat(allCues.get(4).startTimeUs).isEqualTo(50_000_000); - assertThat(spanned.toString()).isEqualTo("text 4"); - assertThat(spanned).hasNoSpans(); - } - - @Test - public void nonExistingAndExistingStyleIdWithRedundantSpaces() throws Exception { - ImmutableList allCues = getAllCues(INHERIT_MULTIPLE_STYLES_TTML_FILE); - - assertThat(allCues).hasSize(6); - - Spanned spanned = getOnlyCueTextAtIndex(allCues, 5); - - assertThat(allCues.get(5).startTimeUs).isEqualTo(60_000_000); - assertThat(spanned.toString()).isEqualTo("text 5"); - assertThat(spanned).hasBackgroundColorSpanBetween(0, spanned.length()).withColor(0xFFFF0000); - } - - @Test - public void multipleChaining() throws Exception { - ImmutableList allCues = getAllCues(CHAIN_MULTIPLE_STYLES_TTML_FILE); - - assertThat(allCues).hasSize(2); - - Spanned spanned1 = getOnlyCueTextAtIndex(allCues, 0); - assertThat(spanned1.toString()).isEqualTo("text 1"); - assertThat(spanned1).hasTypefaceSpanBetween(0, spanned1.length()).withFamily("serif"); - assertThat(spanned1).hasBackgroundColorSpanBetween(0, spanned1.length()).withColor(0xFFFF0000); - assertThat(spanned1).hasForegroundColorSpanBetween(0, spanned1.length()).withColor(0xFF000000); - assertThat(spanned1).hasBoldItalicSpanBetween(0, spanned1.length()); - assertThat(spanned1).hasStrikethroughSpanBetween(0, spanned1.length()); - - // only difference: foreground (font) color must be RED - Spanned spanned2 = getOnlyCueTextAtIndex(allCues, 1); - assertThat(spanned2.toString()).isEqualTo("text 2"); - assertThat(spanned2).hasTypefaceSpanBetween(0, spanned2.length()).withFamily("serif"); - assertThat(spanned2).hasBackgroundColorSpanBetween(0, spanned2.length()).withColor(0xFFFF0000); - assertThat(spanned2).hasForegroundColorSpanBetween(0, spanned2.length()).withColor(0xFFFF0000); - assertThat(spanned2).hasBoldItalicSpanBetween(0, spanned2.length()); - assertThat(spanned2).hasStrikethroughSpanBetween(0, spanned2.length()); - } - - @Test - public void noUnderline() throws Exception { - ImmutableList allCues = getAllCues(NO_UNDERLINE_LINETHROUGH_TTML_FILE); - - assertThat(allCues).hasSize(2); - - Spanned spanned = getOnlyCueTextAtIndex(allCues, 0); - assertThat(spanned.toString()).isEqualTo("text 1"); - // noUnderline from inline attribute overrides s0 global underline style id - assertThat(spanned).hasNoUnderlineSpanBetween(0, spanned.length()); - } - - @Test - public void noLinethrough() throws Exception { - ImmutableList allCues = getAllCues(NO_UNDERLINE_LINETHROUGH_TTML_FILE); - - assertThat(allCues).hasSize(2); - - Spanned spanned = getOnlyCueTextAtIndex(allCues, 1); - assertThat(spanned.toString()).isEqualTo("text 2"); - // noLineThrough from inline attribute overrides s1 global lineThrough style id - assertThat(spanned).hasNoStrikethroughSpanBetween(0, spanned.length()); - } - - @Test - public void fontSizeSpans() throws Exception { - ImmutableList allCues = getAllCues(FONT_SIZE_TTML_FILE); - - assertThat(allCues).hasSize(5); - - Spanned spanned = getOnlyCueTextAtIndex(allCues, 0); - assertThat(String.valueOf(spanned)).isEqualTo("text 1"); - assertThat(spanned).hasAbsoluteSizeSpanBetween(0, spanned.length()).withAbsoluteSize(32); - - spanned = getOnlyCueTextAtIndex(allCues, 1); - assertThat(spanned.toString()).isEqualTo("text 2"); - assertThat(spanned).hasRelativeSizeSpanBetween(0, spanned.length()).withSizeChange(2.2f); - - spanned = getOnlyCueTextAtIndex(allCues, 2); - assertThat(spanned.toString()).isEqualTo("text 3"); - assertThat(spanned).hasRelativeSizeSpanBetween(0, spanned.length()).withSizeChange(1.5f); - - spanned = getOnlyCueTextAtIndex(allCues, 3); - assertThat(spanned.toString()).isEqualTo("two values"); - assertThat(spanned).hasAbsoluteSizeSpanBetween(0, spanned.length()).withAbsoluteSize(16); - - spanned = getOnlyCueTextAtIndex(allCues, 4); - assertThat(spanned.toString()).isEqualTo("leading dot"); - assertThat(spanned).hasRelativeSizeSpanBetween(0, spanned.length()).withSizeChange(0.5f); - } - - @Test - public void fontSizeWithMissingUnitIsIgnored() throws Exception { - ImmutableList allCues = getAllCues(FONT_SIZE_MISSING_UNIT_TTML_FILE); - - assertThat(allCues).hasSize(1); - - Spanned spanned = getOnlyCueTextAtIndex(allCues, 0); - assertThat(spanned.toString()).isEqualTo("no unit"); - assertThat(spanned).hasNoRelativeSizeSpanBetween(0, spanned.length()); - assertThat(spanned).hasNoAbsoluteSizeSpanBetween(0, spanned.length()); - } - - @Test - public void fontSizeWithInvalidValueIsIgnored() throws Exception { - ImmutableList allCues = getAllCues(FONT_SIZE_INVALID_TTML_FILE); - - assertThat(allCues).hasSize(3); - - Spanned spanned = getOnlyCueTextAtIndex(allCues, 0); - assertThat(String.valueOf(spanned)).isEqualTo("invalid"); - assertThat(spanned).hasNoRelativeSizeSpanBetween(0, spanned.length()); - assertThat(spanned).hasNoAbsoluteSizeSpanBetween(0, spanned.length()); - - spanned = getOnlyCueTextAtIndex(allCues, 1); - assertThat(String.valueOf(spanned)).isEqualTo("invalid"); - assertThat(spanned).hasNoRelativeSizeSpanBetween(0, spanned.length()); - assertThat(spanned).hasNoAbsoluteSizeSpanBetween(0, spanned.length()); - - spanned = getOnlyCueTextAtIndex(allCues, 2); - assertThat(String.valueOf(spanned)).isEqualTo("invalid dot"); - assertThat(spanned).hasNoRelativeSizeSpanBetween(0, spanned.length()); - assertThat(spanned).hasNoAbsoluteSizeSpanBetween(0, spanned.length()); - } - - @Test - public void fontSizeWithEmptyValueIsIgnored() throws Exception { - ImmutableList allCues = getAllCues(FONT_SIZE_EMPTY_TTML_FILE); - - assertThat(allCues).hasSize(1); - - Spanned spanned = getOnlyCueTextAtIndex(allCues, 0); - assertThat(String.valueOf(spanned)).isEqualTo("empty"); - assertThat(spanned).hasNoRelativeSizeSpanBetween(0, spanned.length()); - assertThat(spanned).hasNoAbsoluteSizeSpanBetween(0, spanned.length()); - } - - @Test - public void frameRate() throws Exception { - ImmutableList allCues = getAllCues(FRAME_RATE_TTML_FILE); - - assertThat(allCues).hasSize(2); - assertThat(allCues.get(0).startTimeUs).isEqualTo(1_000_000); - assertThat(allCues.get(0).durationUs).isEqualTo(10_000); - assertThat((double) allCues.get(1).startTimeUs).isWithin(1000).of(1_001_000_000); - assertThat((double) allCues.get(1).durationUs).isWithin(2000).of(1_001_000_000); - } - - @Test - public void bitmapPercentageRegion() throws Exception { - ImmutableList allCues = getAllCues(BITMAP_REGION_FILE); - - assertThat(allCues).hasSize(3); - - assertThat(allCues.get(0).startTimeUs).isEqualTo(200_000); - assertThat(allCues.get(0).durationUs).isEqualTo(2_800_000); - Cue cue = Iterables.getOnlyElement(allCues.get(0).cues); - assertThat(cue.text).isNull(); - assertThat(cue.bitmap).isNotNull(); - assertThat(cue.position).isEqualTo(24f / 100f); - assertThat(cue.line).isEqualTo(28f / 100f); - assertThat(cue.size).isEqualTo(51f / 100f); - assertThat(cue.bitmapHeight).isEqualTo(12f / 100f); - - assertThat(allCues.get(1).startTimeUs).isEqualTo(3_200_000); - assertThat(allCues.get(1).durationUs).isEqualTo(3_737_000); - cue = Iterables.getOnlyElement(allCues.get(1).cues); - assertThat(cue.text).isNull(); - assertThat(cue.bitmap).isNotNull(); - assertThat(cue.position).isEqualTo(21f / 100f); - assertThat(cue.line).isEqualTo(35f / 100f); - assertThat(cue.size).isEqualTo(57f / 100f); - assertThat(cue.bitmapHeight).isEqualTo(6f / 100f); - - assertThat(allCues.get(2).startTimeUs).isEqualTo(7_200_000); - cue = Iterables.getOnlyElement(allCues.get(2).cues); - assertThat(cue.text).isNull(); - assertThat(cue.bitmap).isNotNull(); - assertThat(cue.position).isEqualTo(24f / 100f); - assertThat(cue.line).isEqualTo(28f / 100f); - assertThat(cue.size).isEqualTo(51f / 100f); - assertThat(cue.bitmapHeight).isEqualTo(12f / 100f); - } - - @Test - public void bitmapPixelRegion() throws Exception { - ImmutableList allCues = getAllCues(BITMAP_PIXEL_REGION_FILE); - - assertThat(allCues).hasSize(2); - - assertThat(allCues.get(0).startTimeUs).isEqualTo(200_000); - assertThat(allCues.get(0).durationUs).isEqualTo(2_800_000); - Cue cue = Iterables.getOnlyElement(allCues.get(0).cues); - assertThat(cue.text).isNull(); - assertThat(cue.bitmap).isNotNull(); - assertThat(cue.position).isEqualTo(307f / 1280f); - assertThat(cue.line).isEqualTo(562f / 720f); - assertThat(cue.size).isEqualTo(653f / 1280f); - assertThat(cue.bitmapHeight).isEqualTo(86f / 720f); - - assertThat(allCues.get(1).startTimeUs).isEqualTo(3_200_000); - assertThat(allCues.get(1).durationUs).isEqualTo(3_737_000); - cue = Iterables.getOnlyElement(allCues.get(1).cues); - assertThat(cue.text).isNull(); - assertThat(cue.bitmap).isNotNull(); - assertThat(cue.position).isEqualTo(269f / 1280f); - assertThat(cue.line).isEqualTo(612f / 720f); - assertThat(cue.size).isEqualTo(730f / 1280f); - assertThat(cue.bitmapHeight).isEqualTo(43f / 720f); - } - - @Test - public void bitmapUnsupportedRegion() throws Exception { - ImmutableList allCues = getAllCues(BITMAP_UNSUPPORTED_REGION_FILE); - - assertThat(allCues).hasSize(2); - - assertThat(allCues.get(0).startTimeUs).isEqualTo(200_000); - assertThat(allCues.get(0).durationUs).isEqualTo(2_800_000); - Cue cue = Iterables.getOnlyElement(allCues.get(0).cues); - assertThat(cue.text).isNull(); - assertThat(cue.bitmap).isNotNull(); - assertThat(cue.position).isEqualTo(Cue.DIMEN_UNSET); - assertThat(cue.line).isEqualTo(Cue.DIMEN_UNSET); - assertThat(cue.size).isEqualTo(Cue.DIMEN_UNSET); - assertThat(cue.bitmapHeight).isEqualTo(Cue.DIMEN_UNSET); - - assertThat(allCues.get(1).startTimeUs).isEqualTo(3_200_000); - assertThat(allCues.get(1).durationUs).isEqualTo(3_737_000); - cue = Iterables.getOnlyElement(allCues.get(1).cues); - assertThat(cue.text).isNull(); - assertThat(cue.bitmap).isNotNull(); - assertThat(cue.position).isEqualTo(Cue.DIMEN_UNSET); - assertThat(cue.line).isEqualTo(Cue.DIMEN_UNSET); - assertThat(cue.size).isEqualTo(Cue.DIMEN_UNSET); - assertThat(cue.bitmapHeight).isEqualTo(Cue.DIMEN_UNSET); - } - - @Test - public void textAlign() throws Exception { - ImmutableList allCues = getAllCues(TEXT_ALIGN_FILE); - - assertThat(allCues).hasSize(9); - - Cue firstCue = Iterables.getOnlyElement(allCues.get(0).cues); - assertThat(firstCue.text.toString()).isEqualTo("Start alignment"); - assertThat(firstCue.textAlignment).isEqualTo(Layout.Alignment.ALIGN_NORMAL); - - Cue secondCue = Iterables.getOnlyElement(allCues.get(1).cues); - assertThat(secondCue.text.toString()).isEqualTo("Left alignment"); - assertThat(secondCue.textAlignment).isEqualTo(Layout.Alignment.ALIGN_NORMAL); - - Cue thirdCue = Iterables.getOnlyElement(allCues.get(2).cues); - assertThat(thirdCue.text.toString()).isEqualTo("Center alignment"); - assertThat(thirdCue.textAlignment).isEqualTo(Layout.Alignment.ALIGN_CENTER); - - Cue fourthCue = Iterables.getOnlyElement(allCues.get(3).cues); - assertThat(fourthCue.text.toString()).isEqualTo("Right alignment"); - assertThat(fourthCue.textAlignment).isEqualTo(Layout.Alignment.ALIGN_OPPOSITE); - - Cue fifthCue = Iterables.getOnlyElement(allCues.get(4).cues); - assertThat(fifthCue.text.toString()).isEqualTo("End alignment"); - assertThat(fifthCue.textAlignment).isEqualTo(Layout.Alignment.ALIGN_OPPOSITE); - - Cue sixthCue = Iterables.getOnlyElement(allCues.get(5).cues); - assertThat(sixthCue.text.toString()).isEqualTo("Justify alignment (unsupported)"); - assertThat(sixthCue.textAlignment).isNull(); - - Cue seventhCue = Iterables.getOnlyElement(allCues.get(6).cues); - assertThat(seventhCue.text.toString()).isEqualTo("No textAlign property"); - assertThat(seventhCue.textAlignment).isNull(); - - Cue eighthCue = Iterables.getOnlyElement(allCues.get(7).cues); - assertThat(eighthCue.text.toString()).isEqualTo("Ancestor start alignment"); - assertThat(eighthCue.textAlignment).isEqualTo(Layout.Alignment.ALIGN_NORMAL); - - Cue ninthCue = Iterables.getOnlyElement(allCues.get(8).cues); - assertThat(ninthCue.text.toString()).isEqualTo("Not a P node"); - assertThat(ninthCue.textAlignment).isNull(); - } - - @Test - public void multiRowAlign() throws Exception { - ImmutableList allCues = getAllCues(MULTI_ROW_ALIGN_FILE); - - Cue firstCue = Iterables.getOnlyElement(allCues.get(0).cues); - assertThat(firstCue.multiRowAlignment).isEqualTo(Layout.Alignment.ALIGN_NORMAL); - - Cue secondCue = Iterables.getOnlyElement(allCues.get(1).cues); - assertThat(secondCue.multiRowAlignment).isEqualTo(Layout.Alignment.ALIGN_CENTER); - - Cue thirdCue = Iterables.getOnlyElement(allCues.get(2).cues); - assertThat(thirdCue.multiRowAlignment).isEqualTo(Layout.Alignment.ALIGN_OPPOSITE); - - Cue fourthCue = Iterables.getOnlyElement(allCues.get(3).cues); - assertThat(fourthCue.multiRowAlignment).isEqualTo(Layout.Alignment.ALIGN_NORMAL); - - Cue fifthCue = Iterables.getOnlyElement(allCues.get(4).cues); - assertThat(fifthCue.multiRowAlignment).isEqualTo(Layout.Alignment.ALIGN_OPPOSITE); - - Cue sixthCue = Iterables.getOnlyElement(allCues.get(5).cues); - assertThat(sixthCue.multiRowAlignment).isNull(); - - Cue seventhCue = Iterables.getOnlyElement(allCues.get(6).cues); - assertThat(seventhCue.multiRowAlignment).isNull(); - } - - @Test - public void verticalText() throws Exception { - ImmutableList allCues = getAllCues(VERTICAL_TEXT_FILE); - - Cue firstCue = Iterables.getOnlyElement(allCues.get(0).cues); - assertThat(firstCue.verticalType).isEqualTo(Cue.VERTICAL_TYPE_RL); - - Cue secondCue = Iterables.getOnlyElement(allCues.get(1).cues); - assertThat(secondCue.verticalType).isEqualTo(Cue.VERTICAL_TYPE_LR); - - Cue thirdCue = Iterables.getOnlyElement(allCues.get(2).cues); - assertThat(thirdCue.verticalType).isEqualTo(Cue.TYPE_UNSET); - } - - @Test - public void textCombine() throws Exception { - ImmutableList allCues = getAllCues(TEXT_COMBINE_FILE); - - Spanned firstCue = getOnlyCueTextAtIndex(allCues, 0); - assertThat(firstCue) - .hasHorizontalTextInVerticalContextSpanBetween( - "text with ".length(), "text with combined".length()); - - Spanned secondCue = getOnlyCueTextAtIndex(allCues, 1); - assertThat(secondCue) - .hasNoHorizontalTextInVerticalContextSpanBetween( - "text with ".length(), "text with un-combined".length()); - - Spanned thirdCue = getOnlyCueTextAtIndex(allCues, 2); - assertThat(thirdCue).hasNoHorizontalTextInVerticalContextSpanBetween(0, thirdCue.length()); - } - - @Test - public void rubies() throws Exception { - ImmutableList allCues = getAllCues(RUBIES_FILE); - - Spanned firstCue = getOnlyCueTextAtIndex(allCues, 0); - assertThat(firstCue.toString()).isEqualTo("Cue with annotated text."); - assertThat(firstCue) - .hasRubySpanBetween("Cue with ".length(), "Cue with annotated".length()) - .withTextAndPosition("1st rubies", TextAnnotation.POSITION_BEFORE); - assertThat(firstCue) - .hasRubySpanBetween("Cue with annotated ".length(), "Cue with annotated text".length()) - .withTextAndPosition("2nd rubies", TextAnnotation.POSITION_UNKNOWN); - - Spanned secondCue = getOnlyCueTextAtIndex(allCues, 1); - assertThat(secondCue.toString()).isEqualTo("Cue with annotated text."); - assertThat(secondCue) - .hasRubySpanBetween("Cue with ".length(), "Cue with annotated".length()) - .withTextAndPosition("rubies", TextAnnotation.POSITION_UNKNOWN); - - Spanned thirdCue = getOnlyCueTextAtIndex(allCues, 2); - assertThat(thirdCue.toString()).isEqualTo("Cue with annotated text."); - assertThat(thirdCue) - .hasRubySpanBetween("Cue with ".length(), "Cue with annotated".length()) - .withTextAndPosition("rubies", TextAnnotation.POSITION_UNKNOWN); - - Spanned fourthCue = getOnlyCueTextAtIndex(allCues, 3); - assertThat(fourthCue.toString()).isEqualTo("Cue with annotated text."); - assertThat(fourthCue).hasNoRubySpanBetween(0, fourthCue.length()); - - Spanned fifthCue = getOnlyCueTextAtIndex(allCues, 4); - assertThat(fifthCue.toString()).isEqualTo("Cue with text."); - assertThat(fifthCue).hasNoRubySpanBetween(0, fifthCue.length()); - - Spanned sixthCue = getOnlyCueTextAtIndex(allCues, 5); - assertThat(sixthCue.toString()).isEqualTo("Cue with annotated text."); - assertThat(sixthCue).hasNoRubySpanBetween(0, sixthCue.length()); - - Spanned seventhCue = getOnlyCueTextAtIndex(allCues, 6); - assertThat(seventhCue.toString()).isEqualTo("Cue with annotated text."); - assertThat(seventhCue) - .hasRubySpanBetween("Cue with ".length(), "Cue with annotated".length()) - .withTextAndPosition("rubies", TextAnnotation.POSITION_BEFORE); - - Spanned eighthCue = getOnlyCueTextAtIndex(allCues, 7); - assertThat(eighthCue.toString()).isEqualTo("Cue with annotated text."); - assertThat(eighthCue) - .hasRubySpanBetween("Cue with ".length(), "Cue with annotated".length()) - .withTextAndPosition("rubies", TextAnnotation.POSITION_AFTER); - } - - @Test - public void textEmphasis() throws Exception { - ImmutableList allCues = getAllCues(TEXT_EMPHASIS_FILE); - - Spanned firstCue = getOnlyCueTextAtIndex(allCues, 0); - assertThat(firstCue) - .hasTextEmphasisSpanBetween("None ".length(), "None おはよ".length()) - .withMarkAndPosition( - TextEmphasisSpan.MARK_SHAPE_NONE, - TextEmphasisSpan.MARK_FILL_UNKNOWN, - TextAnnotation.POSITION_BEFORE); - - Spanned secondCue = getOnlyCueTextAtIndex(allCues, 1); - assertThat(secondCue) - .hasTextEmphasisSpanBetween("Auto ".length(), "Auto ございます".length()) - .withMarkAndPosition( - TextEmphasisSpan.MARK_SHAPE_CIRCLE, - TextEmphasisSpan.MARK_FILL_FILLED, - TextAnnotation.POSITION_BEFORE); - - Spanned thirdCue = getOnlyCueTextAtIndex(allCues, 2); - assertThat(thirdCue) - .hasTextEmphasisSpanBetween("Filled circle ".length(), "Filled circle こんばんは".length()) - .withMarkAndPosition( - TextEmphasisSpan.MARK_SHAPE_CIRCLE, - TextEmphasisSpan.MARK_FILL_FILLED, - TextAnnotation.POSITION_BEFORE); - - Spanned fourthCue = getOnlyCueTextAtIndex(allCues, 3); - assertThat(fourthCue) - .hasTextEmphasisSpanBetween("Filled dot ".length(), "Filled dot ございます".length()) - .withMarkAndPosition( - TextEmphasisSpan.MARK_SHAPE_DOT, - TextEmphasisSpan.MARK_FILL_FILLED, - TextAnnotation.POSITION_BEFORE); - - Spanned fifthCue = getOnlyCueTextAtIndex(allCues, 4); - assertThat(fifthCue) - .hasTextEmphasisSpanBetween("Filled sesame ".length(), "Filled sesame おはよ".length()) - .withMarkAndPosition( - TextEmphasisSpan.MARK_SHAPE_SESAME, - TextEmphasisSpan.MARK_FILL_FILLED, - TextAnnotation.POSITION_BEFORE); - - Spanned sixthCue = getOnlyCueTextAtIndex(allCues, 5); - assertThat(sixthCue) - .hasTextEmphasisSpanBetween( - "Open circle before ".length(), "Open circle before ございます".length()) - .withMarkAndPosition( - TextEmphasisSpan.MARK_SHAPE_CIRCLE, - TextEmphasisSpan.MARK_FILL_OPEN, - TextAnnotation.POSITION_BEFORE); - - Spanned seventhCue = getOnlyCueTextAtIndex(allCues, 6); - assertThat(seventhCue) - .hasTextEmphasisSpanBetween("Open dot after ".length(), "Open dot after おはよ".length()) - .withMarkAndPosition( - TextEmphasisSpan.MARK_SHAPE_DOT, - TextEmphasisSpan.MARK_FILL_OPEN, - TextAnnotation.POSITION_AFTER); - - Spanned eighthCue = getOnlyCueTextAtIndex(allCues, 7); - assertThat(eighthCue) - .hasTextEmphasisSpanBetween( - "Open sesame outside ".length(), "Open sesame outside ございます".length()) - .withMarkAndPosition( - TextEmphasisSpan.MARK_SHAPE_SESAME, - TextEmphasisSpan.MARK_FILL_OPEN, - TextAnnotation.POSITION_BEFORE); - - Spanned ninthCue = getOnlyCueTextAtIndex(allCues, 8); - assertThat(ninthCue) - .hasTextEmphasisSpanBetween("Auto outside ".length(), "Auto outside おはよ".length()) - .withMarkAndPosition( - TextEmphasisSpan.MARK_SHAPE_CIRCLE, - TextEmphasisSpan.MARK_FILL_FILLED, - TextAnnotation.POSITION_BEFORE); - - Spanned tenthCue = getOnlyCueTextAtIndex(allCues, 9); - assertThat(tenthCue) - .hasTextEmphasisSpanBetween("Circle before ".length(), "Circle before ございます".length()) - .withMarkAndPosition( - TextEmphasisSpan.MARK_SHAPE_CIRCLE, - TextEmphasisSpan.MARK_FILL_FILLED, - TextAnnotation.POSITION_BEFORE); - - Spanned eleventhCue = getOnlyCueTextAtIndex(allCues, 10); - assertThat(eleventhCue) - .hasTextEmphasisSpanBetween("Sesame after ".length(), "Sesame after おはよ".length()) - .withMarkAndPosition( - TextEmphasisSpan.MARK_SHAPE_SESAME, - TextEmphasisSpan.MARK_FILL_FILLED, - TextAnnotation.POSITION_AFTER); - - Spanned twelfthCue = getOnlyCueTextAtIndex(allCues, 11); - assertThat(twelfthCue) - .hasTextEmphasisSpanBetween("Dot outside ".length(), "Dot outside ございます".length()) - .withMarkAndPosition( - TextEmphasisSpan.MARK_SHAPE_DOT, - TextEmphasisSpan.MARK_FILL_FILLED, - TextAnnotation.POSITION_BEFORE); - - Spanned thirteenthCue = getOnlyCueTextAtIndex(allCues, 12); - assertThat(thirteenthCue) - .hasNoTextEmphasisSpanBetween( - "No textEmphasis property ".length(), "No textEmphasis property おはよ".length()); - - Spanned fourteenthCue = getOnlyCueTextAtIndex(allCues, 13); - assertThat(fourteenthCue) - .hasTextEmphasisSpanBetween("Auto (TBLR) ".length(), "Auto (TBLR) ございます".length()) - .withMarkAndPosition( - TextEmphasisSpan.MARK_SHAPE_SESAME, - TextEmphasisSpan.MARK_FILL_FILLED, - TextAnnotation.POSITION_BEFORE); - - Spanned fifteenthCue = getOnlyCueTextAtIndex(allCues, 14); - assertThat(fifteenthCue) - .hasTextEmphasisSpanBetween("Auto (TBRL) ".length(), "Auto (TBRL) おはよ".length()) - .withMarkAndPosition( - TextEmphasisSpan.MARK_SHAPE_SESAME, - TextEmphasisSpan.MARK_FILL_FILLED, - TextAnnotation.POSITION_BEFORE); - - Spanned sixteenthCue = getOnlyCueTextAtIndex(allCues, 15); - assertThat(sixteenthCue) - .hasTextEmphasisSpanBetween("Auto (TB) ".length(), "Auto (TB) ございます".length()) - .withMarkAndPosition( - TextEmphasisSpan.MARK_SHAPE_SESAME, - TextEmphasisSpan.MARK_FILL_FILLED, - TextAnnotation.POSITION_BEFORE); - - Spanned seventeenthCue = getOnlyCueTextAtIndex(allCues, 16); - assertThat(seventeenthCue) - .hasTextEmphasisSpanBetween("Auto (LR) ".length(), "Auto (LR) おはよ".length()) - .withMarkAndPosition( - TextEmphasisSpan.MARK_SHAPE_CIRCLE, - TextEmphasisSpan.MARK_FILL_FILLED, - TextAnnotation.POSITION_BEFORE); - } - - @Test - public void shear() throws Exception { - ImmutableList allCues = getAllCues(SHEAR_FILE); - - Cue firstCue = Iterables.getOnlyElement(allCues.get(0).cues); - assertThat(firstCue.shearDegrees).isZero(); - - Cue secondCue = Iterables.getOnlyElement(allCues.get(1).cues); - assertThat(secondCue.shearDegrees).isWithin(0.01f).of(-15f); - - Cue thirdCue = Iterables.getOnlyElement(allCues.get(2).cues); - assertThat(thirdCue.shearDegrees).isWithin(0.01f).of(15f); - - Cue fourthCue = Iterables.getOnlyElement(allCues.get(3).cues); - assertThat(fourthCue.shearDegrees).isWithin(0.01f).of(-15f); - - Cue fifthCue = Iterables.getOnlyElement(allCues.get(4).cues); - assertThat(fifthCue.shearDegrees).isWithin(0.01f).of(-22.5f); - - Cue sixthCue = Iterables.getOnlyElement(allCues.get(5).cues); - assertThat(sixthCue.shearDegrees).isWithin(0.01f).of(0f); - - Cue seventhCue = Iterables.getOnlyElement(allCues.get(6).cues); - assertThat(seventhCue.shearDegrees).isWithin(0.01f).of(-90f); - - Cue eighthCue = Iterables.getOnlyElement(allCues.get(7).cues); - assertThat(eighthCue.shearDegrees).isWithin(0.01f).of(90f); - } - - private static Spanned getOnlyCueTextAtIndex(ImmutableList allCues, int index) { - Cue cue = getOnlyCueAtIndex(allCues, index); - assertThat(cue.text).isInstanceOf(Spanned.class); - return (Spanned) Assertions.checkNotNull(cue.text); - } - - private static Cue getOnlyCueAtIndex(ImmutableList allCues, int index) { - ImmutableList cues = allCues.get(index).cues; - assertThat(cues).hasSize(1); - return cues.get(0); - } - - private static ImmutableList getAllCues(String file) throws Exception { - TtmlParser ttmlParser = new TtmlParser(); - byte[] bytes = TestUtil.getByteArray(ApplicationProvider.getApplicationContext(), file); - return ttmlParser.parse(bytes, 0, bytes.length); - } -}