Commit 284b843d by ibaker Committed by Oliver Woodman

Add fall-back behaviour for vertical cues if rendering isn't supported

PiperOrigin-RevId: 308854072
parent 053a8ac4
...@@ -107,6 +107,8 @@ ...@@ -107,6 +107,8 @@
* Implement timing-out of stuck CEA-608 captions (as permitted by * Implement timing-out of stuck CEA-608 captions (as permitted by
ANSI/CTA-608-E R-2014 Annex C.9) and set the default timeout to 16 ANSI/CTA-608-E R-2014 Annex C.9) and set the default timeout to 16
seconds ([#7181](https://github.com/google/ExoPlayer/issues/7181)). seconds ([#7181](https://github.com/google/ExoPlayer/issues/7181)).
* Add special-case positioning behaviour for vertical cues being rendered
horizontally.
* 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.
......
...@@ -460,6 +460,11 @@ public final class Cue { ...@@ -460,6 +460,11 @@ public final class Cue {
this.verticalType = verticalType; this.verticalType = verticalType;
} }
/** Returns a new {@link Cue.Builder} initialized with the same values as this Cue. */
public Builder buildUpon() {
return new Cue.Builder(this);
}
/** A builder for {@link Cue} objects. */ /** A builder for {@link Cue} objects. */
public static final class Builder { public static final class Builder {
@Nullable private CharSequence text; @Nullable private CharSequence text;
...@@ -496,6 +501,24 @@ public final class Cue { ...@@ -496,6 +501,24 @@ public final class Cue {
verticalType = TYPE_UNSET; verticalType = TYPE_UNSET;
} }
private Builder(Cue cue) {
text = cue.text;
bitmap = cue.bitmap;
textAlignment = cue.textAlignment;
line = cue.line;
lineType = cue.lineType;
lineAnchor = cue.lineAnchor;
position = cue.position;
positionAnchor = cue.positionAnchor;
textSizeType = cue.textSizeType;
textSize = cue.textSize;
size = cue.size;
bitmapHeight = cue.bitmapHeight;
windowColorSet = cue.windowColorSet;
windowColor = cue.windowColor;
verticalType = cue.verticalType;
}
/** /**
* Sets the cue text. * Sets the cue text.
* *
......
...@@ -22,6 +22,7 @@ import static org.junit.Assert.assertThrows; ...@@ -22,6 +22,7 @@ import static org.junit.Assert.assertThrows;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.Color; import android.graphics.Color;
import android.text.Layout; import android.text.Layout;
import android.text.SpannedString;
import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.ext.junit.runners.AndroidJUnit4;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
...@@ -31,10 +32,10 @@ import org.junit.runner.RunWith; ...@@ -31,10 +32,10 @@ import org.junit.runner.RunWith;
public class CueTest { public class CueTest {
@Test @Test
public void buildSucceeds() { public void buildAndBuildUponWorkAsExpected() {
Cue cue = Cue cue =
new Cue.Builder() new Cue.Builder()
.setText("text") .setText(SpannedString.valueOf("text"))
.setTextAlignment(Layout.Alignment.ALIGN_CENTER) .setTextAlignment(Layout.Alignment.ALIGN_CENTER)
.setLine(5, Cue.LINE_TYPE_NUMBER) .setLine(5, Cue.LINE_TYPE_NUMBER)
.setLineAnchor(Cue.ANCHOR_TYPE_END) .setLineAnchor(Cue.ANCHOR_TYPE_END)
...@@ -46,7 +47,9 @@ public class CueTest { ...@@ -46,7 +47,9 @@ public class CueTest {
.setVerticalType(Cue.VERTICAL_TYPE_RL) .setVerticalType(Cue.VERTICAL_TYPE_RL)
.build(); .build();
assertThat(cue.text).isEqualTo("text"); Cue modifiedCue = cue.buildUpon().build();
assertThat(cue.text.toString()).isEqualTo("text");
assertThat(cue.textAlignment).isEqualTo(Layout.Alignment.ALIGN_CENTER); assertThat(cue.textAlignment).isEqualTo(Layout.Alignment.ALIGN_CENTER);
assertThat(cue.line).isEqualTo(5); assertThat(cue.line).isEqualTo(5);
assertThat(cue.lineType).isEqualTo(Cue.LINE_TYPE_NUMBER); assertThat(cue.lineType).isEqualTo(Cue.LINE_TYPE_NUMBER);
...@@ -58,6 +61,19 @@ public class CueTest { ...@@ -58,6 +61,19 @@ public class CueTest {
assertThat(cue.windowColor).isEqualTo(Color.CYAN); assertThat(cue.windowColor).isEqualTo(Color.CYAN);
assertThat(cue.windowColorSet).isTrue(); assertThat(cue.windowColorSet).isTrue();
assertThat(cue.verticalType).isEqualTo(Cue.VERTICAL_TYPE_RL); assertThat(cue.verticalType).isEqualTo(Cue.VERTICAL_TYPE_RL);
assertThat(modifiedCue.text).isSameInstanceAs(cue.text);
assertThat(modifiedCue.textAlignment).isEqualTo(cue.textAlignment);
assertThat(modifiedCue.line).isEqualTo(cue.line);
assertThat(modifiedCue.lineType).isEqualTo(cue.lineType);
assertThat(modifiedCue.position).isEqualTo(cue.position);
assertThat(modifiedCue.positionAnchor).isEqualTo(cue.positionAnchor);
assertThat(modifiedCue.textSize).isEqualTo(cue.textSize);
assertThat(modifiedCue.textSizeType).isEqualTo(cue.textSizeType);
assertThat(modifiedCue.size).isEqualTo(cue.size);
assertThat(modifiedCue.windowColor).isEqualTo(cue.windowColor);
assertThat(modifiedCue.windowColorSet).isEqualTo(cue.windowColorSet);
assertThat(modifiedCue.verticalType).isEqualTo(cue.verticalType);
} }
@Test @Test
...@@ -71,7 +87,7 @@ public class CueTest { ...@@ -71,7 +87,7 @@ public class CueTest {
RuntimeException.class, RuntimeException.class,
() -> () ->
new Cue.Builder() new Cue.Builder()
.setText("foo") .setText(SpannedString.valueOf("text"))
.setBitmap(Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888)) .setBitmap(Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888))
.build()); .build());
} }
......
...@@ -154,6 +154,9 @@ import java.util.List; ...@@ -154,6 +154,9 @@ import java.util.List;
int cueCount = cues.size(); int cueCount = cues.size();
for (int i = 0; i < cueCount; i++) { for (int i = 0; i < cueCount; i++) {
Cue cue = cues.get(i); Cue cue = cues.get(i);
if (cue.verticalType != Cue.TYPE_UNSET) {
cue = repositionVerticalCue(cue);
}
float cueTextSizePx = float cueTextSizePx =
SubtitleViewUtils.resolveCueTextSize(cue, rawViewHeight, viewHeightMinusPadding); SubtitleViewUtils.resolveCueTextSize(cue, rawViewHeight, viewHeightMinusPadding);
SubtitlePainter painter = painters.get(i); SubtitlePainter painter = painters.get(i);
...@@ -172,4 +175,46 @@ import java.util.List; ...@@ -172,4 +175,46 @@ import java.util.List;
bottom); bottom);
} }
} }
/**
* Reposition a vertical cue for horizontal display.
*
* <p>This class doesn't support rendering vertical text, but if we naively interpret vertical
* {@link Cue#position} and{@link Cue#line} values for horizontal display then the cues will often
* be displayed in unexpected positions. For example, the 'default' position for vertical-rl
* subtitles is the right-hand edge of the viewport, so cues that would appear vertically in this
* position should appear horizontally at the bottom of the viewport (generally the default
* position). Similarly left-edge vertical-rl cues should be shown at the top of a horizontal
* viewport.
*
* <p>There isn't a meaningful way to transform {@link Cue#position} and related values (e.g.
* alignment), so we clear these and allow {@link SubtitlePainter} to do the default behaviour of
* centering the cue.
*/
private static Cue repositionVerticalCue(Cue cue) {
Cue.Builder cueBuilder =
cue.buildUpon()
.setPosition(Cue.DIMEN_UNSET)
.setPositionAnchor(Cue.TYPE_UNSET)
.setTextAlignment(null);
if (cue.lineType == Cue.LINE_TYPE_FRACTION) {
cueBuilder.setLine(1.0f - cue.line, Cue.LINE_TYPE_FRACTION);
} else {
cueBuilder.setLine(-cue.line - 1f, Cue.LINE_TYPE_NUMBER);
}
switch (cue.lineAnchor) {
case Cue.ANCHOR_TYPE_END:
cueBuilder.setLineAnchor(Cue.ANCHOR_TYPE_START);
break;
case Cue.ANCHOR_TYPE_START:
cueBuilder.setLineAnchor(Cue.ANCHOR_TYPE_END);
break;
case Cue.ANCHOR_TYPE_MIDDLE:
case Cue.TYPE_UNSET:
default:
// Fall through
}
return cueBuilder.build();
}
} }
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