diff --git a/library/core/src/main/java/com/google/android/exoplayer2/text/webvtt/WebvttCueParser.java b/library/core/src/main/java/com/google/android/exoplayer2/text/webvtt/WebvttCueParser.java index f62b073f602..1f7f7eddf2c 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/text/webvtt/WebvttCueParser.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/text/webvtt/WebvttCueParser.java @@ -48,7 +48,9 @@ import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Collections; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.checkerframework.checker.nullness.qual.MonotonicNonNull; @@ -137,6 +139,31 @@ public final class WebvttCueParser { private static final String TAG = "WebvttCueParser"; + private static final Map DEFAULT_COLORS; + private static final Map DEFAULT_BACKGROUND_COLORS; + + static { + DEFAULT_COLORS = new HashMap<>(); + DEFAULT_COLORS.put("black", 0xFF000000); + DEFAULT_COLORS.put("blue", 0xFF0000FF); + DEFAULT_COLORS.put("cyan", 0xFF00FFFF); + DEFAULT_COLORS.put("lime", 0xFF00FF00); + DEFAULT_COLORS.put("magenta", 0xFFFF00FF); + DEFAULT_COLORS.put("red", 0xFFFF0000); + DEFAULT_COLORS.put("white", 0xFFFFFFFF); + DEFAULT_COLORS.put("yellow", 0xFFFFFF00); + + DEFAULT_BACKGROUND_COLORS = new HashMap<>(); + DEFAULT_BACKGROUND_COLORS.put("bg_black", 0xFF000000); + DEFAULT_BACKGROUND_COLORS.put("bg_blue", 0xFF0000FF); + DEFAULT_BACKGROUND_COLORS.put("bg_cyan", 0xFF00FFFF); + DEFAULT_BACKGROUND_COLORS.put("bg_lime", 0xFF00FF00); + DEFAULT_BACKGROUND_COLORS.put("bg_magenta", 0xFFFF00FF); + DEFAULT_BACKGROUND_COLORS.put("bg_red", 0xFFFF0000); + DEFAULT_BACKGROUND_COLORS.put("bg_white", 0xFFFFFFFF); + DEFAULT_BACKGROUND_COLORS.put("bg_yellow", 0xFFFFFF00); + } + /** * Parses the next valid WebVTT cue in a parsable array, including timestamps, settings and text. * @@ -514,6 +541,8 @@ private static void applySpansForTag( text.setSpan(new UnderlineSpan(), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); break; case TAG_CLASS: + applySupportedClasses(text, startTag.classes, start, end); + break; case TAG_LANG: case TAG_VOICE: case "": // Case of the "whole cue" virtual tag. @@ -529,6 +558,20 @@ private static void applySpansForTag( } } + private static void applySupportedClasses(SpannableStringBuilder text, String[] classes, + int start, int end) { + for (String className : classes) { + if (DEFAULT_COLORS.containsKey(className)) { + int color = DEFAULT_COLORS.get(className); + text.setSpan(new ForegroundColorSpan(color), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + } + if (DEFAULT_BACKGROUND_COLORS.containsKey(className)) { + int color = DEFAULT_BACKGROUND_COLORS.get(className); + text.setSpan(new BackgroundColorSpan(color), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + } + } + } + private static void applyStyleToText(SpannableStringBuilder spannedText, WebvttCssStyle style, int start, int end) { if (style == null) { diff --git a/library/core/src/test/java/com/google/android/exoplayer2/text/webvtt/WebvttCueParserTest.java b/library/core/src/test/java/com/google/android/exoplayer2/text/webvtt/WebvttCueParserTest.java index aa83fbc8edb..b263ba91c95 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/text/webvtt/WebvttCueParserTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/text/webvtt/WebvttCueParserTest.java @@ -79,6 +79,38 @@ public void testParseRubyTagWithEmptyTextTag() throws Exception { .withTextAndPosition("", RubySpan.POSITION_OVER); } + @Test + public void testForegroundTextColorClass() throws Exception { + Spanned text = parseCueText("In this sentence this text is red"); + + assertThat(text.toString()).isEqualTo("In this sentence this text is red"); + assertThat(text).hasForegroundColorSpanBetween("In this sentence ".length(), "In this sentence this text".length()); + } + + @Test + public void testUnsupportedColorForForegroundTextColorClass() throws Exception { + Spanned text = parseCueText("In this sentence this text is not papaya"); + + assertThat(text.toString()).isEqualTo("In this sentence this text is not papaya"); + assertThat(text).hasNoSpans(); + } + + @Test + public void testBackgroundTextColorClass() throws Exception { + Spanned text = parseCueText("In this sentence this text has a red background"); + + assertThat(text.toString()).isEqualTo("In this sentence this text has a red background"); + assertThat(text).hasBackgroundColorSpanBetween("In this sentence ".length(), "In this sentence this text".length()); + } + + @Test + public void testUnsupportedColorForBackgroundTextColorClass() throws Exception { + Spanned text = parseCueText("In this sentence this text doesn't have a papaya background"); + + assertThat(text.toString()).isEqualTo("In this sentence this text doesn't have a papaya background"); + assertThat(text).hasNoSpans(); + } + @Test public void testParseWellFormedUnclosedEndAtCueEnd() throws Exception { Spanned text = parseCueText("An unclosed u tag with "