Parse TTML's tts:textAlign into Cue.textAlign, not an AlignmentSpan

The tts:textAlign property only applies to <p> elements, which
correspond 1:1 with ExoPlayer Cue objects, so we can use
Cue.textAlignment to store this info instead of encoding it in
the span-styled text.

This will mean that TTML subtitles used with
SubtitleView#setApplyEmbeddedStyles(false) will start respecting
the tts:textAlign properties from the source data (currently this
information is stripped when we remove all span styling). I think this
is working-as-intended, we respect alignment of other subtitle types
(e.g. WebVTT) when applyEmbeddedStyles=false. We also respect all other
'positioning' related properties in this case e.g. Cue.position and
Cue.line.

PiperOrigin-RevId: 310895499
This commit is contained in:
ibaker 2020-05-11 13:53:49 +01:00 committed by Oliver Woodman
parent 19d639eb9a
commit 0dd57de1f1
5 changed files with 67 additions and 20 deletions

View File

@ -380,7 +380,9 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
}
if (resolvedStyle != null) {
TtmlRenderUtil.applyStylesToSpan(text, start, end, resolvedStyle, parent);
regionOutput.setVerticalType(resolvedStyle.getVerticalType());
regionOutput
.setTextAlignment(resolvedStyle.getTextAlign())
.setVerticalType(resolvedStyle.getVerticalType());
}
}

View File

@ -15,12 +15,10 @@
*/
package com.google.android.exoplayer2.text.ttml;
import android.text.Layout.Alignment;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
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;
@ -162,16 +160,6 @@ import java.util.Map;
// Do nothing
break;
}
@Nullable Alignment textAlign = style.getTextAlign();
if (textAlign != null) {
SpanUtil.addOrReplaceSpan(
builder,
new AlignmentSpan.Standard(textAlign),
start,
end,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
if (style.getTextCombine()) {
SpanUtil.addOrReplaceSpan(
builder,

View File

@ -60,6 +60,7 @@ public final class TtmlDecoderTest {
private static final String BITMAP_REGION_FILE = "ttml/bitmap_percentage_region.xml";
private static final String BITMAP_PIXEL_REGION_FILE = "ttml/bitmap_pixel_region.xml";
private static final String BITMAP_UNSUPPORTED_REGION_FILE = "ttml/bitmap_unsupported_region.xml";
private static final String TEXT_ALIGN_FILE = "ttml/text_align.xml";
private static final String VERTICAL_TEXT_FILE = "ttml/vertical_text.xml";
private static final String TEXT_COMBINE_FILE = "ttml/text_combine.xml";
private static final String RUBIES_FILE = "ttml/rubies.xml";
@ -194,9 +195,6 @@ public final class TtmlDecoderTest {
assertThat(firstCueText)
.hasForegroundColorSpanBetween(0, firstCueText.length())
.withColor(ColorParser.parseTtmlColor("lime"));
assertThat(firstCueText)
.hasAlignmentSpanBetween(0, firstCueText.length())
.withAlignment(Layout.Alignment.ALIGN_CENTER);
Spanned secondCueText = getOnlyCueTextAtTimeUs(subtitle, 20_000_000);
assertThat(secondCueText.toString()).isEqualTo("text 2");
@ -210,9 +208,6 @@ public final class TtmlDecoderTest {
assertThat(secondCueText)
.hasForegroundColorSpanBetween(0, secondCueText.length())
.withColor(0xFFFFFF00);
assertThat(secondCueText)
.hasAlignmentSpanBetween(0, secondCueText.length())
.withAlignment(Layout.Alignment.ALIGN_CENTER);
}
@Test
@ -575,6 +570,39 @@ public final class TtmlDecoderTest {
assertThat(cue.bitmapHeight).isEqualTo(Cue.DIMEN_UNSET);
}
@Test
public void textAlign() throws IOException, SubtitleDecoderException {
TtmlSubtitle subtitle = getSubtitle(TEXT_ALIGN_FILE);
Cue firstCue = getOnlyCueAtTimeUs(subtitle, 10_000_000);
assertThat(firstCue.text.toString()).isEqualTo("Start alignment");
assertThat(firstCue.textAlignment).isEqualTo(Layout.Alignment.ALIGN_NORMAL);
Cue secondCue = getOnlyCueAtTimeUs(subtitle, 20_000_000);
assertThat(secondCue.text.toString()).isEqualTo("Left alignment");
assertThat(secondCue.textAlignment).isEqualTo(Layout.Alignment.ALIGN_NORMAL);
Cue thirdCue = getOnlyCueAtTimeUs(subtitle, 30_000_000);
assertThat(thirdCue.text.toString()).isEqualTo("Center alignment");
assertThat(thirdCue.textAlignment).isEqualTo(Layout.Alignment.ALIGN_CENTER);
Cue fourthCue = getOnlyCueAtTimeUs(subtitle, 40_000_000);
assertThat(fourthCue.text.toString()).isEqualTo("Right alignment");
assertThat(fourthCue.textAlignment).isEqualTo(Layout.Alignment.ALIGN_OPPOSITE);
Cue fifthCue = getOnlyCueAtTimeUs(subtitle, 50_000_000);
assertThat(fifthCue.text.toString()).isEqualTo("End alignment");
assertThat(fifthCue.textAlignment).isEqualTo(Layout.Alignment.ALIGN_OPPOSITE);
Cue sixthCue = getOnlyCueAtTimeUs(subtitle, 60_000_000);
assertThat(sixthCue.text.toString()).isEqualTo("Justify alignment (unsupported)");
assertThat(sixthCue.textAlignment).isNull();
Cue seventhCue = getOnlyCueAtTimeUs(subtitle, 70_000_000);
assertThat(seventhCue.text.toString()).isEqualTo("No textAlign property");
assertThat(seventhCue.textAlignment).isNull();
}
@Test
public void verticalText() throws IOException, SubtitleDecoderException {
TtmlSubtitle subtitle = getSubtitle(VERTICAL_TEXT_FILE);

View File

@ -14,7 +14,7 @@
tts:color="yellow"/>
</styling>
</head>
<body tts:textAlign="center">
<body>
<div tts:fontWeight="normal"
tts:fontStyle="normal"
tts:fontFamily="sansSerif"

View File

@ -0,0 +1,29 @@
<tt xmlns:ttm="http://www.w3.org/2006/10/ttaf1#metadata"
xmlns:ttp="http://www.w3.org/2006/10/ttaf1#parameter"
xmlns:tts="http://www.w3.org/2006/10/ttaf1#style"
xmlns="http://www.w3.org/ns/ttml"
xmlns="http://www.w3.org/2006/10/ttaf1">
<body>
<div>
<p begin="10s" end="18s" tts:textAlign="start">Start alignment</p>
</div>
<div>
<p begin="20s" end="28s" tts:textAlign="left">Left alignment</p>
</div>
<div>
<p begin="30s" end="38s" tts:textAlign="center">Center alignment</p>
</div>
<div>
<p begin="40s" end="48s" tts:textAlign="right">Right alignment</p>
</div>
<div>
<p begin="50s" end="58s" tts:textAlign="end">End alignment</p>
</div>
<div>
<p begin="60s" end="68s" tts:textAlign="justify">Justify alignment (unsupported)</p>
</div>
<div>
<p begin="70s" end="78s">No textAlign property</p>
</div>
</body>
</tt>