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.
* Implement steps 4-10 of the
[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:
* Add support for attaching DRM sessions to clear content in the demo app.
* 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_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_WEIGHT = "font-weight";
private static final String PROPERTY_TEXT_COMBINE_UPRIGHT = "text-combine-upright";
@ -184,10 +184,8 @@ import java.util.regex.Pattern;
return;
}
// 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));
} else if (PROPERTY_BGCOLOR.equals(property)) {
style.setBackgroundColor(ColorParser.parseCssColor(value));
} else if (PROPERTY_TEXT_COMBINE_UPRIGHT.equals(property)) {
style.setCombineUpright(VALUE_ALL.equals(value) || value.startsWith(VALUE_DIGITS));
} else if (PROPERTY_TEXT_DECORATION.equals(property)) {

View file

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

View file

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

View file

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

View file

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

View file

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