mirror of
https://github.com/samsonjs/media.git
synced 2026-04-27 15:07:40 +00:00
Add support for SSA OutlineColour (only background)
OutlineColour should be treated as the background color if BorderStyle=3. Since currently BorderStyle is ignored, we can always treat OutlineColor as the background color.
This commit is contained in:
parent
cf0a680677
commit
388b8d1d88
4 changed files with 38 additions and 9 deletions
|
|
@ -21,6 +21,7 @@ import static com.google.android.exoplayer2.util.Util.castNonNull;
|
||||||
import android.graphics.Typeface;
|
import android.graphics.Typeface;
|
||||||
import android.text.Layout;
|
import android.text.Layout;
|
||||||
import android.text.SpannableString;
|
import android.text.SpannableString;
|
||||||
|
import android.text.style.BackgroundColorSpan;
|
||||||
import android.text.style.ForegroundColorSpan;
|
import android.text.style.ForegroundColorSpan;
|
||||||
import android.text.style.StrikethroughSpan;
|
import android.text.style.StrikethroughSpan;
|
||||||
import android.text.style.StyleSpan;
|
import android.text.style.StyleSpan;
|
||||||
|
|
@ -319,6 +320,13 @@ public final class SsaDecoder extends SimpleSubtitleDecoder {
|
||||||
/* end= */ spannableText.length(),
|
/* end= */ spannableText.length(),
|
||||||
SpannableString.SPAN_EXCLUSIVE_EXCLUSIVE);
|
SpannableString.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
}
|
}
|
||||||
|
if (style.outlineColor != null) {
|
||||||
|
spannableText.setSpan(
|
||||||
|
new BackgroundColorSpan(style.outlineColor),
|
||||||
|
/* start= */ 0,
|
||||||
|
/* end= */ spannableText.length(),
|
||||||
|
SpannableString.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
|
}
|
||||||
if (style.fontSize != Cue.DIMEN_UNSET && screenHeight != Cue.DIMEN_UNSET) {
|
if (style.fontSize != Cue.DIMEN_UNSET && screenHeight != Cue.DIMEN_UNSET) {
|
||||||
cue.setTextSize(
|
cue.setTextSize(
|
||||||
style.fontSize / screenHeight, Cue.TEXT_SIZE_TYPE_FRACTIONAL_IGNORE_PADDING);
|
style.fontSize / screenHeight, Cue.TEXT_SIZE_TYPE_FRACTIONAL_IGNORE_PADDING);
|
||||||
|
|
|
||||||
|
|
@ -95,6 +95,7 @@ import java.util.regex.Pattern;
|
||||||
public final String name;
|
public final String name;
|
||||||
public final @SsaAlignment int alignment;
|
public final @SsaAlignment int alignment;
|
||||||
@Nullable @ColorInt public final Integer primaryColor;
|
@Nullable @ColorInt public final Integer primaryColor;
|
||||||
|
@Nullable @ColorInt public final Integer outlineColor;
|
||||||
public final float fontSize;
|
public final float fontSize;
|
||||||
public final boolean bold;
|
public final boolean bold;
|
||||||
public final boolean italic;
|
public final boolean italic;
|
||||||
|
|
@ -105,6 +106,7 @@ import java.util.regex.Pattern;
|
||||||
String name,
|
String name,
|
||||||
@SsaAlignment int alignment,
|
@SsaAlignment int alignment,
|
||||||
@Nullable @ColorInt Integer primaryColor,
|
@Nullable @ColorInt Integer primaryColor,
|
||||||
|
@Nullable @ColorInt Integer outlineColor,
|
||||||
float fontSize,
|
float fontSize,
|
||||||
boolean bold,
|
boolean bold,
|
||||||
boolean italic,
|
boolean italic,
|
||||||
|
|
@ -113,6 +115,7 @@ import java.util.regex.Pattern;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.alignment = alignment;
|
this.alignment = alignment;
|
||||||
this.primaryColor = primaryColor;
|
this.primaryColor = primaryColor;
|
||||||
|
this.outlineColor = outlineColor;
|
||||||
this.fontSize = fontSize;
|
this.fontSize = fontSize;
|
||||||
this.bold = bold;
|
this.bold = bold;
|
||||||
this.italic = italic;
|
this.italic = italic;
|
||||||
|
|
@ -141,6 +144,9 @@ import java.util.regex.Pattern;
|
||||||
format.primaryColorIndex != C.INDEX_UNSET
|
format.primaryColorIndex != C.INDEX_UNSET
|
||||||
? parseColor(styleValues[format.primaryColorIndex].trim())
|
? parseColor(styleValues[format.primaryColorIndex].trim())
|
||||||
: null,
|
: null,
|
||||||
|
format.outlineColorIndex != C.INDEX_UNSET
|
||||||
|
? parseColor(styleValues[format.outlineColorIndex].trim())
|
||||||
|
: null,
|
||||||
format.fontSizeIndex != C.INDEX_UNSET
|
format.fontSizeIndex != C.INDEX_UNSET
|
||||||
? parseFontSize(styleValues[format.fontSizeIndex].trim())
|
? parseFontSize(styleValues[format.fontSizeIndex].trim())
|
||||||
: Cue.DIMEN_UNSET,
|
: Cue.DIMEN_UNSET,
|
||||||
|
|
@ -257,6 +263,7 @@ import java.util.regex.Pattern;
|
||||||
public final int nameIndex;
|
public final int nameIndex;
|
||||||
public final int alignmentIndex;
|
public final int alignmentIndex;
|
||||||
public final int primaryColorIndex;
|
public final int primaryColorIndex;
|
||||||
|
public final int outlineColorIndex;
|
||||||
public final int fontSizeIndex;
|
public final int fontSizeIndex;
|
||||||
public final int boldIndex;
|
public final int boldIndex;
|
||||||
public final int italicIndex;
|
public final int italicIndex;
|
||||||
|
|
@ -268,6 +275,7 @@ import java.util.regex.Pattern;
|
||||||
int nameIndex,
|
int nameIndex,
|
||||||
int alignmentIndex,
|
int alignmentIndex,
|
||||||
int primaryColorIndex,
|
int primaryColorIndex,
|
||||||
|
int outlineColorIndex,
|
||||||
int fontSizeIndex,
|
int fontSizeIndex,
|
||||||
int boldIndex,
|
int boldIndex,
|
||||||
int italicIndex,
|
int italicIndex,
|
||||||
|
|
@ -277,6 +285,7 @@ import java.util.regex.Pattern;
|
||||||
this.nameIndex = nameIndex;
|
this.nameIndex = nameIndex;
|
||||||
this.alignmentIndex = alignmentIndex;
|
this.alignmentIndex = alignmentIndex;
|
||||||
this.primaryColorIndex = primaryColorIndex;
|
this.primaryColorIndex = primaryColorIndex;
|
||||||
|
this.outlineColorIndex = outlineColorIndex;
|
||||||
this.fontSizeIndex = fontSizeIndex;
|
this.fontSizeIndex = fontSizeIndex;
|
||||||
this.boldIndex = boldIndex;
|
this.boldIndex = boldIndex;
|
||||||
this.italicIndex = italicIndex;
|
this.italicIndex = italicIndex;
|
||||||
|
|
@ -295,6 +304,7 @@ import java.util.regex.Pattern;
|
||||||
int nameIndex = C.INDEX_UNSET;
|
int nameIndex = C.INDEX_UNSET;
|
||||||
int alignmentIndex = C.INDEX_UNSET;
|
int alignmentIndex = C.INDEX_UNSET;
|
||||||
int primaryColorIndex = C.INDEX_UNSET;
|
int primaryColorIndex = C.INDEX_UNSET;
|
||||||
|
int outlineColorIndex = C.INDEX_UNSET;
|
||||||
int fontSizeIndex = C.INDEX_UNSET;
|
int fontSizeIndex = C.INDEX_UNSET;
|
||||||
int boldIndex = C.INDEX_UNSET;
|
int boldIndex = C.INDEX_UNSET;
|
||||||
int italicIndex = C.INDEX_UNSET;
|
int italicIndex = C.INDEX_UNSET;
|
||||||
|
|
@ -313,6 +323,9 @@ import java.util.regex.Pattern;
|
||||||
case "primarycolour":
|
case "primarycolour":
|
||||||
primaryColorIndex = i;
|
primaryColorIndex = i;
|
||||||
break;
|
break;
|
||||||
|
case "outlinecolour":
|
||||||
|
outlineColorIndex = i;
|
||||||
|
break;
|
||||||
case "fontsize":
|
case "fontsize":
|
||||||
fontSizeIndex = i;
|
fontSizeIndex = i;
|
||||||
break;
|
break;
|
||||||
|
|
@ -335,6 +348,7 @@ import java.util.regex.Pattern;
|
||||||
nameIndex,
|
nameIndex,
|
||||||
alignmentIndex,
|
alignmentIndex,
|
||||||
primaryColorIndex,
|
primaryColorIndex,
|
||||||
|
outlineColorIndex,
|
||||||
fontSizeIndex,
|
fontSizeIndex,
|
||||||
boldIndex,
|
boldIndex,
|
||||||
italicIndex,
|
italicIndex,
|
||||||
|
|
|
||||||
|
|
@ -301,7 +301,7 @@ public final class SsaDecoderTest {
|
||||||
SsaDecoder decoder = new SsaDecoder();
|
SsaDecoder decoder = new SsaDecoder();
|
||||||
byte[] bytes = TestUtil.getByteArray(ApplicationProvider.getApplicationContext(), STYLE_COLORS);
|
byte[] bytes = TestUtil.getByteArray(ApplicationProvider.getApplicationContext(), STYLE_COLORS);
|
||||||
Subtitle subtitle = decoder.decode(bytes, bytes.length, false);
|
Subtitle subtitle = decoder.decode(bytes, bytes.length, false);
|
||||||
assertThat(subtitle.getEventTimeCount()).isEqualTo(14);
|
assertThat(subtitle.getEventTimeCount()).isEqualTo(16);
|
||||||
// &H000000FF (AABBGGRR) -> #FFFF0000 (AARRGGBB)
|
// &H000000FF (AABBGGRR) -> #FFFF0000 (AARRGGBB)
|
||||||
Spanned firstCueText =
|
Spanned firstCueText =
|
||||||
(Spanned) Iterables.getOnlyElement(subtitle.getCues(subtitle.getEventTime(0))).text;
|
(Spanned) Iterables.getOnlyElement(subtitle.getCues(subtitle.getEventTime(0))).text;
|
||||||
|
|
@ -342,6 +342,11 @@ public final class SsaDecoderTest {
|
||||||
(Spanned) Iterables.getOnlyElement(subtitle.getCues(subtitle.getEventTime(12))).text;
|
(Spanned) Iterables.getOnlyElement(subtitle.getCues(subtitle.getEventTime(12))).text;
|
||||||
SpannedSubject.assertThat(seventhCueText)
|
SpannedSubject.assertThat(seventhCueText)
|
||||||
.hasNoForegroundColorSpanBetween(0, seventhCueText.length());
|
.hasNoForegroundColorSpanBetween(0, seventhCueText.length());
|
||||||
|
Spanned eighthCueText =
|
||||||
|
(Spanned) Iterables.getOnlyElement(subtitle.getCues(subtitle.getEventTime(14))).text;
|
||||||
|
SpannedSubject.assertThat(eighthCueText)
|
||||||
|
.hasBackgroundColorSpanBetween(0, eighthCueText.length())
|
||||||
|
.withColor(Color.BLUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
||||||
18
testdata/src/test/assets/media/ssa/style_colors
vendored
18
testdata/src/test/assets/media/ssa/style_colors
vendored
|
|
@ -5,14 +5,15 @@ PlayResX: 1280
|
||||||
PlayResY: 720
|
PlayResY: 720
|
||||||
|
|
||||||
[V4+ Styles]
|
[V4+ Styles]
|
||||||
Format: Name ,PrimaryColour
|
Format: Name ,PrimaryColour,OutlineColour
|
||||||
Style: PrimaryColourStyleHexRed ,&H000000FF
|
Style: PrimaryColourStyleHexRed ,&H000000FF ,&H00000000
|
||||||
Style: PrimaryColourStyleHexYellow ,&H0000FFFF
|
Style: PrimaryColourStyleHexYellow ,&H0000FFFF ,&H00000000
|
||||||
Style: PrimaryColourStyleHexGreen ,&HFF00
|
Style: PrimaryColourStyleHexGreen ,&HFF00 ,&H00000000
|
||||||
Style: PrimaryColourStyleHexAlpha ,&HA00000FF
|
Style: PrimaryColourStyleHexAlpha ,&HA00000FF ,&H00000000
|
||||||
Style: PrimaryColourStyleDecimal ,16711680
|
Style: PrimaryColourStyleDecimal ,16711680 ,&H00000000
|
||||||
Style: PrimaryColourStyleDecimalAlpha,2164195328
|
Style: PrimaryColourStyleDecimalAlpha,2164195328 ,&H00000000
|
||||||
Style: PrimaryColourStyleInvalid ,blue
|
Style: PrimaryColourStyleInvalid ,blue ,&H00000000
|
||||||
|
Style: OutlineColourStyleBlue ,&H00000000 ,&H00FF0000
|
||||||
|
|
||||||
|
|
||||||
[Events]
|
[Events]
|
||||||
|
|
@ -24,3 +25,4 @@ Dialogue: 0:00:07.00,0:00:08.00,PrimaryColourStyleHexAlpha ,Fourth line in RE
|
||||||
Dialogue: 0:00:09.00,0:00:10.00,PrimaryColourStyleDecimal ,Fifth line in BLUE (16711680).
|
Dialogue: 0:00:09.00,0:00:10.00,PrimaryColourStyleDecimal ,Fifth line in BLUE (16711680).
|
||||||
Dialogue: 0:00:11.00,0:00:12.00,PrimaryColourStyleDecimalAlpha,Sixth line in BLUE with alpha (2164195328).
|
Dialogue: 0:00:11.00,0:00:12.00,PrimaryColourStyleDecimalAlpha,Sixth line in BLUE with alpha (2164195328).
|
||||||
Dialogue: 0:00:13.00,0:00:14.00,PrimaryColourInvalid ,Seventh line with invalid color.
|
Dialogue: 0:00:13.00,0:00:14.00,PrimaryColourInvalid ,Seventh line with invalid color.
|
||||||
|
Dialogue: 0:00:15.00,0:00:16.00,OutlineColourStyleBlue ,Eighth line with BLUE (&H00FF0000) outline.
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue