Commit fbdc1bbf by Ian Baker Committed by marcbaechinger

Merge pull request #8654 from abeljim:dev-v2-8435-bolditalic

PiperOrigin-RevId: 361767801
parent 37d5947b
...@@ -45,6 +45,9 @@ ...@@ -45,6 +45,9 @@
video tracks (previously separate acquire and release events were video tracks (previously separate acquire and release events were
dispatched for each track in each period). dispatched for each track in each period).
* Include the session state in DRM session-acquired listener methods. * Include the session state in DRM session-acquired listener methods.
* Text
* Parse SSA/ASS bold & italic info in `Style:` lines
([#8435](https://github.com/google/ExoPlayer/issues/8435)).
* MediaSession extension: Remove dependency to core module and rely on common * MediaSession extension: Remove dependency to core module and rely on common
only. The `TimelineQueueEditor` uses a new `MediaDescriptionConverter` for only. The `TimelineQueueEditor` uses a new `MediaDescriptionConverter` for
this purpose and does not rely on the `ConcatenatingMediaSource` anymore. this purpose and does not rely on the `ConcatenatingMediaSource` anymore.
......
...@@ -18,9 +18,11 @@ package com.google.android.exoplayer2.text.ssa; ...@@ -18,9 +18,11 @@ package com.google.android.exoplayer2.text.ssa;
import static com.google.android.exoplayer2.text.Cue.LINE_TYPE_FRACTION; import static com.google.android.exoplayer2.text.Cue.LINE_TYPE_FRACTION;
import static com.google.android.exoplayer2.util.Util.castNonNull; import static com.google.android.exoplayer2.util.Util.castNonNull;
import android.graphics.Typeface;
import android.text.Layout; import android.text.Layout;
import android.text.SpannableString; import android.text.SpannableString;
import android.text.style.ForegroundColorSpan; import android.text.style.ForegroundColorSpan;
import android.text.style.StyleSpan;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.text.Cue; import com.google.android.exoplayer2.text.Cue;
...@@ -318,6 +320,25 @@ public final class SsaDecoder extends SimpleSubtitleDecoder { ...@@ -318,6 +320,25 @@ public final class SsaDecoder extends SimpleSubtitleDecoder {
cue.setTextSize( cue.setTextSize(
style.fontSize / screenHeight, Cue.TEXT_SIZE_TYPE_FRACTIONAL_IGNORE_PADDING); style.fontSize / screenHeight, Cue.TEXT_SIZE_TYPE_FRACTIONAL_IGNORE_PADDING);
} }
if (style.bold && style.italic) {
spannableText.setSpan(
new StyleSpan(Typeface.BOLD_ITALIC),
/* start= */ 0,
/* end= */ spannableText.length(),
SpannableString.SPAN_EXCLUSIVE_EXCLUSIVE);
} else if (style.bold) {
spannableText.setSpan(
new StyleSpan(Typeface.BOLD),
/* start= */ 0,
/* end= */ spannableText.length(),
SpannableString.SPAN_EXCLUSIVE_EXCLUSIVE);
} else if (style.italic) {
spannableText.setSpan(
new StyleSpan(Typeface.ITALIC),
/* start= */ 0,
/* end= */ spannableText.length(),
SpannableString.SPAN_EXCLUSIVE_EXCLUSIVE);
}
} }
@SsaStyle.SsaAlignment int alignment; @SsaStyle.SsaAlignment int alignment;
......
...@@ -92,16 +92,22 @@ import java.util.regex.Pattern; ...@@ -92,16 +92,22 @@ import java.util.regex.Pattern;
@SsaAlignment public final int alignment; @SsaAlignment public final int alignment;
@Nullable @ColorInt public final Integer primaryColor; @Nullable @ColorInt public final Integer primaryColor;
public final float fontSize; public final float fontSize;
public final boolean bold;
public final boolean italic;
private SsaStyle( private SsaStyle(
String name, String name,
@SsaAlignment int alignment, @SsaAlignment int alignment,
@Nullable @ColorInt Integer primaryColor, @Nullable @ColorInt Integer primaryColor,
float fontSize) { float fontSize,
boolean bold,
boolean italic) {
this.name = name; this.name = name;
this.alignment = alignment; this.alignment = alignment;
this.primaryColor = primaryColor; this.primaryColor = primaryColor;
this.fontSize = fontSize; this.fontSize = fontSize;
this.bold = bold;
this.italic = italic;
} }
@Nullable @Nullable
...@@ -127,7 +133,13 @@ import java.util.regex.Pattern; ...@@ -127,7 +133,13 @@ import java.util.regex.Pattern;
: null, : 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,
format.boldIndex != C.INDEX_UNSET
? parseBoldOrItalic(styleValues[format.boldIndex].trim())
: false,
format.italicIndex != C.INDEX_UNSET
? parseBoldOrItalic(styleValues[format.italicIndex].trim())
: false);
} catch (RuntimeException e) { } catch (RuntimeException e) {
Log.w(TAG, "Skipping malformed 'Style:' line: '" + styleLine + "'", e); Log.w(TAG, "Skipping malformed 'Style:' line: '" + styleLine + "'", e);
return null; return null;
...@@ -213,6 +225,16 @@ import java.util.regex.Pattern; ...@@ -213,6 +225,16 @@ import java.util.regex.Pattern;
} }
} }
private static boolean parseBoldOrItalic(String boldOrItalic) {
try {
int value = Integer.parseInt(boldOrItalic);
return value == 1 || value == -1;
} catch (NumberFormatException e) {
Log.w(TAG, "Failed to parse bold/italic: '" + boldOrItalic + "'", e);
return false;
}
}
/** /**
* Represents a {@code Format:} line from the {@code [V4+ Styles]} section * Represents a {@code Format:} line from the {@code [V4+ Styles]} section
* *
...@@ -225,14 +247,24 @@ import java.util.regex.Pattern; ...@@ -225,14 +247,24 @@ import java.util.regex.Pattern;
public final int alignmentIndex; public final int alignmentIndex;
public final int primaryColorIndex; public final int primaryColorIndex;
public final int fontSizeIndex; public final int fontSizeIndex;
public final int boldIndex;
public final int italicIndex;
public final int length; public final int length;
private Format( private Format(
int nameIndex, int alignmentIndex, int primaryColorIndex, int fontSizeIndex, int length) { int nameIndex,
int alignmentIndex,
int primaryColorIndex,
int fontSizeIndex,
int boldIndex,
int italicIndex,
int length) {
this.nameIndex = nameIndex; this.nameIndex = nameIndex;
this.alignmentIndex = alignmentIndex; this.alignmentIndex = alignmentIndex;
this.primaryColorIndex = primaryColorIndex; this.primaryColorIndex = primaryColorIndex;
this.fontSizeIndex = fontSizeIndex; this.fontSizeIndex = fontSizeIndex;
this.boldIndex = boldIndex;
this.italicIndex = italicIndex;
this.length = length; this.length = length;
} }
...@@ -247,6 +279,8 @@ import java.util.regex.Pattern; ...@@ -247,6 +279,8 @@ import java.util.regex.Pattern;
int alignmentIndex = C.INDEX_UNSET; int alignmentIndex = C.INDEX_UNSET;
int primaryColorIndex = C.INDEX_UNSET; int primaryColorIndex = C.INDEX_UNSET;
int fontSizeIndex = C.INDEX_UNSET; int fontSizeIndex = C.INDEX_UNSET;
int boldIndex = C.INDEX_UNSET;
int italicIndex = C.INDEX_UNSET;
String[] keys = String[] keys =
TextUtils.split(styleFormatLine.substring(SsaDecoder.FORMAT_LINE_PREFIX.length()), ","); TextUtils.split(styleFormatLine.substring(SsaDecoder.FORMAT_LINE_PREFIX.length()), ",");
for (int i = 0; i < keys.length; i++) { for (int i = 0; i < keys.length; i++) {
...@@ -263,10 +297,23 @@ import java.util.regex.Pattern; ...@@ -263,10 +297,23 @@ import java.util.regex.Pattern;
case "fontsize": case "fontsize":
fontSizeIndex = i; fontSizeIndex = i;
break; break;
case "bold":
boldIndex = i;
break;
case "italic":
italicIndex = i;
break;
} }
} }
return nameIndex != C.INDEX_UNSET return nameIndex != C.INDEX_UNSET
? new Format(nameIndex, alignmentIndex, primaryColorIndex, fontSizeIndex, keys.length) ? new Format(
nameIndex,
alignmentIndex,
primaryColorIndex,
fontSizeIndex,
boldIndex,
italicIndex,
keys.length)
: null; : null;
} }
} }
......
...@@ -49,6 +49,7 @@ public final class SsaDecoderTest { ...@@ -49,6 +49,7 @@ public final class SsaDecoderTest {
private static final String POSITIONS_WITHOUT_PLAYRES = "media/ssa/positioning_without_playres"; private static final String POSITIONS_WITHOUT_PLAYRES = "media/ssa/positioning_without_playres";
private static final String STYLE_COLORS = "media/ssa/style_colors"; private static final String STYLE_COLORS = "media/ssa/style_colors";
private static final String STYLE_FONT_SIZE = "media/ssa/style_font_size"; private static final String STYLE_FONT_SIZE = "media/ssa/style_font_size";
private static final String STYLE_BOLD_ITALIC = "media/ssa/style_bold_italic";
@Test @Test
public void decodeEmpty() throws IOException { public void decodeEmpty() throws IOException {
...@@ -336,6 +337,25 @@ public final class SsaDecoderTest { ...@@ -336,6 +337,25 @@ public final class SsaDecoderTest {
assertThat(secondCue.textSizeType).isEqualTo(Cue.TEXT_SIZE_TYPE_FRACTIONAL_IGNORE_PADDING); assertThat(secondCue.textSizeType).isEqualTo(Cue.TEXT_SIZE_TYPE_FRACTIONAL_IGNORE_PADDING);
} }
@Test
public void decodeBoldItalic() throws IOException {
SsaDecoder decoder = new SsaDecoder();
byte[] bytes =
TestUtil.getByteArray(ApplicationProvider.getApplicationContext(), STYLE_BOLD_ITALIC);
Subtitle subtitle = decoder.decode(bytes, bytes.length, false);
assertThat(subtitle.getEventTimeCount()).isEqualTo(6);
Spanned firstCueText =
(Spanned) Iterables.getOnlyElement(subtitle.getCues(subtitle.getEventTime(0))).text;
SpannedSubject.assertThat(firstCueText).hasBoldSpanBetween(0, firstCueText.length());
Spanned secondCueText =
(Spanned) Iterables.getOnlyElement(subtitle.getCues(subtitle.getEventTime(2))).text;
SpannedSubject.assertThat(secondCueText).hasItalicSpanBetween(0, secondCueText.length());
Spanned thirdCueText =
(Spanned) Iterables.getOnlyElement(subtitle.getCues(subtitle.getEventTime(4))).text;
SpannedSubject.assertThat(thirdCueText).hasBoldItalicSpanBetween(0, thirdCueText.length());
}
private static void assertTypicalCue1(Subtitle subtitle, int eventIndex) { private static void assertTypicalCue1(Subtitle subtitle, int eventIndex) {
assertThat(subtitle.getEventTime(eventIndex)).isEqualTo(0); assertThat(subtitle.getEventTime(eventIndex)).isEqualTo(0);
assertThat(subtitle.getCues(subtitle.getEventTime(eventIndex)).get(0).text.toString()) assertThat(subtitle.getCues(subtitle.getEventTime(eventIndex)).get(0).text.toString())
......
[Script Info]
Title: SSA/ASS Test
Original Script: Abel
Script Type: V4.00+
PlayResX: 1280
PlayResY: 720
[V4+ Styles]
Format: Name ,Bold,Italic
Style: FontBold ,-1 ,0
Style: FontItalic ,0 ,-1
Style: FontBoldItalic ,1 ,1
[Events]
Format: Start ,End ,Style ,Text
Dialogue: 0:00:01.00,0:00:03.00,FontBold ,First line with Bold.
Dialogue: 0:00:05.00,0:00:07.00,FontItalic ,Second line with Italic.
Dialogue: 0:00:09.00,0:00:11.00,FontBoldItalic,Third line with Bold Italic.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment