Stop parsing unsupported WebVTT CSS properties

The spec lists an exhaustive list of CSS properties that should be
recognised, all others must be ignored:
https://www.w3.org/TR/webvtt1/#the-cue-pseudo-element

PiperOrigin-RevId: 310353888
This commit is contained in:
ibaker 2020-05-07 15:27:14 +01:00 committed by Oliver Woodman
parent 99ebeaed17
commit 252bf43bf4
7 changed files with 16 additions and 85 deletions

View file

@ -116,6 +116,9 @@
horizontally. horizontally.
* Implement steps 4-10 of the * Implement steps 4-10 of the
[WebVTT line computation algorithm](https://www.w3.org/TR/webvtt1/#cue-computed-line). [WebVTT line computation algorithm](https://www.w3.org/TR/webvtt1/#cue-computed-line).
* Stop parsing unsupported WebVTT CSS properties. The spec provides an
[exhaustive list](https://www.w3.org/TR/webvtt1/#the-cue-pseudo-element)
of which are supported.
* DRM: * DRM:
* Add support for attaching DRM sessions to clear content in the demo app. * Add support for attaching DRM sessions to clear content in the demo app.
* Remove `DrmSessionManager` references from all renderers. * Remove `DrmSessionManager` references from all renderers.

View file

@ -36,7 +36,7 @@ import java.util.regex.Pattern;
private static final String RULE_START = "{"; private static final String RULE_START = "{";
private static final String RULE_END = "}"; private static final String RULE_END = "}";
private static final String PROPERTY_BGCOLOR = "background-color"; private static final String PROPERTY_COLOR = "color";
private static final String PROPERTY_FONT_FAMILY = "font-family"; private static final String PROPERTY_FONT_FAMILY = "font-family";
private static final String PROPERTY_FONT_WEIGHT = "font-weight"; private static final String PROPERTY_FONT_WEIGHT = "font-weight";
private static final String PROPERTY_TEXT_COMBINE_UPRIGHT = "text-combine-upright"; private static final String PROPERTY_TEXT_COMBINE_UPRIGHT = "text-combine-upright";
@ -184,10 +184,8 @@ import java.util.regex.Pattern;
return; return;
} }
// At this point we have a presumably valid declaration, we need to parse it and fill the style. // At this point we have a presumably valid declaration, we need to parse it and fill the style.
if ("color".equals(property)) { if (PROPERTY_COLOR.equals(property)) {
style.setFontColor(ColorParser.parseCssColor(value)); style.setFontColor(ColorParser.parseCssColor(value));
} else if (PROPERTY_BGCOLOR.equals(property)) {
style.setBackgroundColor(ColorParser.parseCssColor(value));
} else if (PROPERTY_TEXT_COMBINE_UPRIGHT.equals(property)) { } else if (PROPERTY_TEXT_COMBINE_UPRIGHT.equals(property)) {
style.setCombineUpright(VALUE_ALL.equals(value) || value.startsWith(VALUE_DIGITS)); style.setCombineUpright(VALUE_ALL.equals(value) || value.startsWith(VALUE_DIGITS));
} else if (PROPERTY_TEXT_DECORATION.equals(property)) { } else if (PROPERTY_TEXT_DECORATION.equals(property)) {

View file

@ -16,7 +16,6 @@
package com.google.android.exoplayer2.text.webvtt; package com.google.android.exoplayer2.text.webvtt;
import android.graphics.Typeface; import android.graphics.Typeface;
import android.text.Layout;
import android.text.TextUtils; import android.text.TextUtils;
import androidx.annotation.IntDef; import androidx.annotation.IntDef;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
@ -86,15 +85,12 @@ public final class WebvttCssStyle {
@Nullable private String fontFamily; @Nullable private String fontFamily;
private int fontColor; private int fontColor;
private boolean hasFontColor; private boolean hasFontColor;
private int backgroundColor;
private boolean hasBackgroundColor;
@OptionalBoolean private int linethrough; @OptionalBoolean private int linethrough;
@OptionalBoolean private int underline; @OptionalBoolean private int underline;
@OptionalBoolean private int bold; @OptionalBoolean private int bold;
@OptionalBoolean private int italic; @OptionalBoolean private int italic;
@FontSizeUnit private int fontSizeUnit; @FontSizeUnit private int fontSizeUnit;
private float fontSize; private float fontSize;
@Nullable private Layout.Alignment textAlign;
private boolean combineUpright; private boolean combineUpright;
// Calling reset() is forbidden because `this` isn't initialized. This can be safely suppressed // Calling reset() is forbidden because `this` isn't initialized. This can be safely suppressed
@ -112,13 +108,11 @@ public final class WebvttCssStyle {
targetVoice = ""; targetVoice = "";
fontFamily = null; fontFamily = null;
hasFontColor = false; hasFontColor = false;
hasBackgroundColor = false;
linethrough = UNSPECIFIED; linethrough = UNSPECIFIED;
underline = UNSPECIFIED; underline = UNSPECIFIED;
bold = UNSPECIFIED; bold = UNSPECIFIED;
italic = UNSPECIFIED; italic = UNSPECIFIED;
fontSizeUnit = UNSPECIFIED; fontSizeUnit = UNSPECIFIED;
textAlign = null;
combineUpright = false; combineUpright = false;
} }
@ -244,33 +238,6 @@ public final class WebvttCssStyle {
return hasFontColor; return hasFontColor;
} }
public int getBackgroundColor() {
if (!hasBackgroundColor) {
throw new IllegalStateException("Background color not defined.");
}
return backgroundColor;
}
public WebvttCssStyle setBackgroundColor(int backgroundColor) {
this.backgroundColor = backgroundColor;
hasBackgroundColor = true;
return this;
}
public boolean hasBackgroundColor() {
return hasBackgroundColor;
}
@Nullable
public Layout.Alignment getTextAlign() {
return textAlign;
}
public WebvttCssStyle setTextAlign(@Nullable Layout.Alignment textAlign) {
this.textAlign = textAlign;
return this;
}
public WebvttCssStyle setFontSize(float fontSize) { public WebvttCssStyle setFontSize(float fontSize) {
this.fontSize = fontSize; this.fontSize = fontSize;
return this; return this;

View file

@ -26,7 +26,6 @@ import android.text.Spanned;
import android.text.SpannedString; import android.text.SpannedString;
import android.text.TextUtils; import android.text.TextUtils;
import android.text.style.AbsoluteSizeSpan; import android.text.style.AbsoluteSizeSpan;
import android.text.style.AlignmentSpan;
import android.text.style.BackgroundColorSpan; import android.text.style.BackgroundColorSpan;
import android.text.style.ForegroundColorSpan; import android.text.style.ForegroundColorSpan;
import android.text.style.RelativeSizeSpan; import android.text.style.RelativeSizeSpan;
@ -647,14 +646,6 @@ public final class WebvttCueParser {
end, end,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
} }
if (style.hasBackgroundColor()) {
addOrReplaceSpan(
spannedText,
new BackgroundColorSpan(style.getBackgroundColor()),
start,
end,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
if (style.getFontFamily() != null) { if (style.getFontFamily() != null) {
addOrReplaceSpan( addOrReplaceSpan(
spannedText, spannedText,
@ -663,15 +654,6 @@ public final class WebvttCueParser {
end, end,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
} }
Layout.Alignment textAlign = style.getTextAlign();
if (textAlign != null) {
addOrReplaceSpan(
spannedText,
new AlignmentSpan.Standard(textAlign),
start,
end,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
switch (style.getFontSizeUnit()) { switch (style.getFontSizeUnit()) {
case WebvttCssStyle.FONT_SIZE_UNIT_PIXEL: case WebvttCssStyle.FONT_SIZE_UNIT_PIXEL:
addOrReplaceSpan( addOrReplaceSpan(

View file

@ -89,41 +89,33 @@ public final class CssParserTest {
@Test @Test
public void parseMethodSimpleInput() { public void parseMethodSimpleInput() {
WebvttCssStyle expectedStyle = new WebvttCssStyle(); WebvttCssStyle expectedStyle = new WebvttCssStyle();
String styleBlock1 = " ::cue { color : black; background-color: PapayaWhip }"; String styleBlock1 = " ::cue { color : PapayaWhip }";
expectedStyle.setFontColor(0xFF000000); expectedStyle.setFontColor(0xFFFFEFD5);
expectedStyle.setBackgroundColor(0xFFFFEFD5);
assertParserProduces(styleBlock1, expectedStyle); assertParserProduces(styleBlock1, expectedStyle);
String styleBlock2 = " ::cue { color : black }\n\n::cue { color : invalid }"; String styleBlock2 = " ::cue { color : black }\n\n::cue { color : invalid }";
expectedStyle = new WebvttCssStyle(); expectedStyle = new WebvttCssStyle();
expectedStyle.setFontColor(0xFF000000); expectedStyle.setFontColor(0xFF000000);
assertParserProduces(styleBlock2, expectedStyle); assertParserProduces(styleBlock2, expectedStyle);
String styleBlock3 = "::cue {\n background-color\n:#00fFFe}";
expectedStyle = new WebvttCssStyle();
expectedStyle.setBackgroundColor(0xFF00FFFE);
assertParserProduces(styleBlock3, expectedStyle);
} }
@Test @Test
public void parseMethodMultipleRulesInBlockInput() { public void parseMethodMultipleRulesInBlockInput() {
String styleBlock = String styleBlock = "::cue {\n color\n:#00fFFe} \n::cue {\n color\n:#00000000}\n";
"::cue {\n background-color\n:#00fFFe} \n::cue {\n background-color\n:#00000000}\n";
WebvttCssStyle expectedStyle = new WebvttCssStyle(); WebvttCssStyle expectedStyle = new WebvttCssStyle();
expectedStyle.setBackgroundColor(0xFF00FFFE); expectedStyle.setFontColor(0xFF00FFFE);
WebvttCssStyle secondExpectedStyle = new WebvttCssStyle(); WebvttCssStyle secondExpectedStyle = new WebvttCssStyle();
secondExpectedStyle.setBackgroundColor(0x000000); secondExpectedStyle.setFontColor(0x000000);
assertParserProduces(styleBlock, expectedStyle, secondExpectedStyle); assertParserProduces(styleBlock, expectedStyle, secondExpectedStyle);
} }
@Test @Test
public void multiplePropertiesInBlock() { public void multiplePropertiesInBlock() {
String styleBlock = "::cue(#id){text-decoration:underline; background-color:green;" String styleBlock =
+ "color:red; font-family:Courier; font-weight:bold}"; "::cue(#id){text-decoration:underline; color:red; font-family:Courier; font-weight:bold}";
WebvttCssStyle expectedStyle = new WebvttCssStyle(); WebvttCssStyle expectedStyle = new WebvttCssStyle();
expectedStyle.setTargetId("id"); expectedStyle.setTargetId("id");
expectedStyle.setUnderline(true); expectedStyle.setUnderline(true);
expectedStyle.setBackgroundColor(0xFF008000);
expectedStyle.setFontColor(0xFFFF0000); expectedStyle.setFontColor(0xFFFF0000);
expectedStyle.setFontFamily("courier"); expectedStyle.setFontFamily("courier");
expectedStyle.setBold(true); expectedStyle.setBold(true);
@ -133,12 +125,10 @@ public final class CssParserTest {
@Test @Test
public void rgbaColorExpression() { public void rgbaColorExpression() {
String styleBlock = "::cue(#rgb){background-color: rgba(\n10/* Ugly color */,11\t, 12\n,.1);" String styleBlock = "::cue(#rgb){color: rgba(\n10/* Ugly color */,11\t, 12\n,.1);}";
+ "color:rgb(1,1,\n1)}";
WebvttCssStyle expectedStyle = new WebvttCssStyle(); WebvttCssStyle expectedStyle = new WebvttCssStyle();
expectedStyle.setTargetId("rgb"); expectedStyle.setTargetId("rgb");
expectedStyle.setBackgroundColor(0x190A0B0C); expectedStyle.setFontColor(0x190A0B0C);
expectedStyle.setFontColor(0xFF010101);
assertParserProduces(styleBlock, expectedStyle); assertParserProduces(styleBlock, expectedStyle);
} }
@ -222,10 +212,6 @@ public final class CssParserTest {
for (int i = 0; i < expectedStyles.length; i++) { for (int i = 0; i < expectedStyles.length; i++) {
WebvttCssStyle expected = expectedStyles[i]; WebvttCssStyle expected = expectedStyles[i];
WebvttCssStyle actualElem = styles.get(i); WebvttCssStyle actualElem = styles.get(i);
assertThat(actualElem.hasBackgroundColor()).isEqualTo(expected.hasBackgroundColor());
if (expected.hasBackgroundColor()) {
assertThat(actualElem.getBackgroundColor()).isEqualTo(expected.getBackgroundColor());
}
assertThat(actualElem.hasFontColor()).isEqualTo(expected.hasFontColor()); assertThat(actualElem.hasFontColor()).isEqualTo(expected.hasFontColor());
if (expected.hasFontColor()) { if (expected.hasFontColor()) {
assertThat(actualElem.getFontColor()).isEqualTo(expected.getFontColor()); assertThat(actualElem.getFontColor()).isEqualTo(expected.getFontColor());
@ -236,7 +222,6 @@ public final class CssParserTest {
assertThat(actualElem.getStyle()).isEqualTo(expected.getStyle()); assertThat(actualElem.getStyle()).isEqualTo(expected.getStyle());
assertThat(actualElem.isLinethrough()).isEqualTo(expected.isLinethrough()); assertThat(actualElem.isLinethrough()).isEqualTo(expected.isLinethrough());
assertThat(actualElem.isUnderline()).isEqualTo(expected.isUnderline()); assertThat(actualElem.isUnderline()).isEqualTo(expected.isUnderline());
assertThat(actualElem.getTextAlign()).isEqualTo(expected.getTextAlign());
} }
} }

View file

@ -371,9 +371,6 @@ public class WebvttDecoderTest {
assertThat(firstCueText) assertThat(firstCueText)
.hasForegroundColorSpanBetween(0, firstCueText.length()) .hasForegroundColorSpanBetween(0, firstCueText.length())
.withColor(ColorParser.parseCssColor("papayawhip")); .withColor(ColorParser.parseCssColor("papayawhip"));
assertThat(firstCueText)
.hasBackgroundColorSpanBetween(0, firstCueText.length())
.withColor(ColorParser.parseCssColor("green"));
Spanned secondCueText = getUniqueSpanTextAt(subtitle, 2_345_000); Spanned secondCueText = getUniqueSpanTextAt(subtitle, 2_345_000);
assertThat(secondCueText.toString()).isEqualTo("This is the second subtitle."); assertThat(secondCueText.toString()).isEqualTo("This is the second subtitle.");
@ -388,7 +385,7 @@ public class WebvttDecoderTest {
Spanned fourthCueText = getUniqueSpanTextAt(subtitle, 25_000_000); Spanned fourthCueText = getUniqueSpanTextAt(subtitle, 25_000_000);
assertThat(fourthCueText.toString()).isEqualTo("You are an idiot\nYou don't have the guts"); assertThat(fourthCueText.toString()).isEqualTo("You are an idiot\nYou don't have the guts");
assertThat(fourthCueText) assertThat(fourthCueText)
.hasBackgroundColorSpanBetween(0, "You are an idiot".length()) .hasForegroundColorSpanBetween(0, "You are an idiot".length())
.withColor(ColorParser.parseCssColor("lime")); .withColor(ColorParser.parseCssColor("lime"));
assertThat(fourthCueText) assertThat(fourthCueText)
.hasBoldSpanBetween("You are an idiot\n".length(), fourthCueText.length()); .hasBoldSpanBetween("You are an idiot\n".length(), fourthCueText.length());

View file

@ -2,7 +2,6 @@ WEBVTT
STYLE STYLE
::cue { ::cue {
background-color: green;
color: papayawhip; color: papayawhip;
} }
/* Style blocks cannot use blank lines nor "dash dash greater than" */ /* Style blocks cannot use blank lines nor "dash dash greater than" */
@ -13,7 +12,7 @@ STYLE
::cue(#id2) { ::cue(#id2) {
color: peachpuff; color: peachpuff;
} }
::cue(v[voice="LaGord"]) { background-color: lime } ::cue(v[voice="LaGord"]) { color: lime }
STYLE STYLE
::cue(v[voice="The Frog"]) { font-weight: bold } ::cue(v[voice="The Frog"]) { font-weight: bold }