blob: 436bea704849eebc541967e831df6732e1744166 [file] [log] [blame]
/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.android.exoplayer2.text;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.LOCAL_VARIABLE;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.ElementType.TYPE_USE;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.os.Bundle;
import android.text.Layout;
import android.text.Layout.Alignment;
import android.text.Spanned;
import android.text.SpannedString;
import android.text.TextUtils;
import androidx.annotation.ColorInt;
import androidx.annotation.IntDef;
import androidx.annotation.Nullable;
import com.google.android.exoplayer2.Bundleable;
import com.google.android.exoplayer2.util.Assertions;
import com.google.common.base.Objects;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.checkerframework.dataflow.qual.Pure;
/** Contains information about a specific cue, including textual content and formatting data. */
// This class shouldn't be sub-classed. If a subtitle format needs additional fields, either they
// should be generic enough to be added here, or the format-specific decoder should pass the
// information around in a sidecar object.
public final class Cue implements Bundleable {
/** The empty cue. */
public static final Cue EMPTY = new Cue.Builder().setText("").build();
/** An unset position, width or size. */
// Note: We deliberately don't use Float.MIN_VALUE because it's positive & very close to zero.
public static final float DIMEN_UNSET = -Float.MAX_VALUE;
/**
* The type of anchor, which may be unset. One of {@link #TYPE_UNSET}, {@link #ANCHOR_TYPE_START},
* {@link #ANCHOR_TYPE_MIDDLE} or {@link #ANCHOR_TYPE_END}.
*/
@Documented
@Retention(RetentionPolicy.SOURCE)
@Target({FIELD, METHOD, PARAMETER, LOCAL_VARIABLE, TYPE_USE})
@IntDef({TYPE_UNSET, ANCHOR_TYPE_START, ANCHOR_TYPE_MIDDLE, ANCHOR_TYPE_END})
public @interface AnchorType {}
/** An unset anchor, line, text size or vertical type value. */
public static final int TYPE_UNSET = Integer.MIN_VALUE;
/**
* Anchors the left (for horizontal positions) or top (for vertical positions) edge of the cue
* box.
*/
public static final int ANCHOR_TYPE_START = 0;
/** Anchors the middle of the cue box. */
public static final int ANCHOR_TYPE_MIDDLE = 1;
/**
* Anchors the right (for horizontal positions) or bottom (for vertical positions) edge of the cue
* box.
*/
public static final int ANCHOR_TYPE_END = 2;
/**
* The type of line, which may be unset. One of {@link #TYPE_UNSET}, {@link #LINE_TYPE_FRACTION}
* or {@link #LINE_TYPE_NUMBER}.
*/
@Documented
@Retention(RetentionPolicy.SOURCE)
@Target({FIELD, METHOD, PARAMETER, LOCAL_VARIABLE, TYPE_USE})
@IntDef({TYPE_UNSET, LINE_TYPE_FRACTION, LINE_TYPE_NUMBER})
public @interface LineType {}
/** Value for {@link #lineType} when {@link #line} is a fractional position. */
public static final int LINE_TYPE_FRACTION = 0;
/** Value for {@link #lineType} when {@link #line} is a line number. */
public static final int LINE_TYPE_NUMBER = 1;
/**
* The type of default text size for this cue, which may be unset. One of {@link #TYPE_UNSET},
* {@link #TEXT_SIZE_TYPE_FRACTIONAL}, {@link #TEXT_SIZE_TYPE_FRACTIONAL_IGNORE_PADDING} or {@link
* #TEXT_SIZE_TYPE_ABSOLUTE}.
*/
@Documented
@Retention(RetentionPolicy.SOURCE)
@Target({FIELD, METHOD, PARAMETER, LOCAL_VARIABLE, TYPE_USE})
@IntDef({
TYPE_UNSET,
TEXT_SIZE_TYPE_FRACTIONAL,
TEXT_SIZE_TYPE_FRACTIONAL_IGNORE_PADDING,
TEXT_SIZE_TYPE_ABSOLUTE
})
public @interface TextSizeType {}
/** Text size is measured as a fraction of the viewport size minus the view padding. */
public static final int TEXT_SIZE_TYPE_FRACTIONAL = 0;
/** Text size is measured as a fraction of the viewport size, ignoring the view padding */
public static final int TEXT_SIZE_TYPE_FRACTIONAL_IGNORE_PADDING = 1;
/** Text size is measured in number of pixels. */
public static final int TEXT_SIZE_TYPE_ABSOLUTE = 2;
/**
* The type of vertical layout for this cue, which may be unset (i.e. horizontal). One of {@link
* #TYPE_UNSET}, {@link #VERTICAL_TYPE_RL} or {@link #VERTICAL_TYPE_LR}.
*/
@Documented
@Retention(RetentionPolicy.SOURCE)
@Target({FIELD, METHOD, PARAMETER, LOCAL_VARIABLE, TYPE_USE})
@IntDef({
TYPE_UNSET,
VERTICAL_TYPE_RL,
VERTICAL_TYPE_LR,
})
public @interface VerticalType {}
/** Vertical right-to-left (e.g. for Japanese). */
public static final int VERTICAL_TYPE_RL = 1;
/** Vertical left-to-right (e.g. for Mongolian). */
public static final int VERTICAL_TYPE_LR = 2;
/**
* The cue text, or null if this is an image cue. Note the {@link CharSequence} may be decorated
* with styling spans.
*/
@Nullable public final CharSequence text;
/** The alignment of the cue text within the cue box, or null if the alignment is undefined. */
@Nullable public final Alignment textAlignment;
/**
* The alignment of multiple lines of text relative to the longest line, or null if the alignment
* is undefined.
*/
@Nullable public final Alignment multiRowAlignment;
/** The cue image, or null if this is a text cue. */
@Nullable public final Bitmap bitmap;
/**
* The position of the cue box within the viewport in the direction orthogonal to the writing
* direction (determined by {@link #verticalType}), or {@link #DIMEN_UNSET}. When set, the
* interpretation of the value depends on the value of {@link #lineType}.
*
* <p>The measurement direction depends on {@link #verticalType}:
*
* <ul>
* <li>For {@link #TYPE_UNSET} (i.e. horizontal), this is the vertical position relative to the
* top of the viewport.
* <li>For {@link #VERTICAL_TYPE_LR} this is the horizontal position relative to the left of the
* viewport.
* <li>For {@link #VERTICAL_TYPE_RL} this is the horizontal position relative to the right of
* the viewport.
* </ul>
*/
public final float line;
/**
* The type of the {@link #line} value.
*
* <ul>
* <li>{@link #LINE_TYPE_FRACTION} indicates that {@link #line} is a fractional position within
* the viewport (measured to the part of the cue box determined by {@link #lineAnchor}).
* <li>{@link #LINE_TYPE_NUMBER} indicates that {@link #line} is a viewport line number. The
* viewport is divided into lines (each equal in size to the first line of the cue box). The
* cue box is positioned to align with the viewport lines as follows:
* <ul>
* <li>{@link #lineAnchor}) is ignored.
* <li>When {@code line} is greater than or equal to 0 the first line in the cue box is
* aligned with a viewport line, with 0 meaning the first line of the viewport.
* <li>When {@code line} is negative the last line in the cue box is aligned with a
* viewport line, with -1 meaning the last line of the viewport.
* <li>For horizontal text the start and end of the viewport are the top and bottom
* respectively.
* </ul>
* </ul>
*/
public final @LineType int lineType;
/**
* The cue box anchor positioned by {@link #line} when {@link #lineType} is {@link
* #LINE_TYPE_FRACTION}.
*
* <p>One of:
*
* <ul>
* <li>{@link #ANCHOR_TYPE_START}
* <li>{@link #ANCHOR_TYPE_MIDDLE}
* <li>{@link #ANCHOR_TYPE_END}
* <li>{@link #TYPE_UNSET}
* </ul>
*
* <p>For the normal case of horizontal text, {@link #ANCHOR_TYPE_START}, {@link
* #ANCHOR_TYPE_MIDDLE} and {@link #ANCHOR_TYPE_END} correspond to the top, middle and bottom of
* the cue box respectively.
*/
public final @AnchorType int lineAnchor;
/**
* The fractional position of the {@link #positionAnchor} of the cue box within the viewport in
* the direction orthogonal to {@link #line}, or {@link #DIMEN_UNSET}.
*
* <p>The measurement direction depends on {@link #verticalType}.
*
* <ul>
* <li>For {@link #TYPE_UNSET} (i.e. horizontal), this is the horizontal position relative to
* the left of the viewport. Note that positioning is relative to the left of the viewport
* even in the case of right-to-left text.
* <li>For {@link #VERTICAL_TYPE_LR} and {@link #VERTICAL_TYPE_RL} (i.e. vertical), this is the
* vertical position relative to the top of the viewport.
* </ul>
*/
public final float position;
/**
* The cue box anchor positioned by {@link #position}. One of {@link #ANCHOR_TYPE_START}, {@link
* #ANCHOR_TYPE_MIDDLE}, {@link #ANCHOR_TYPE_END} and {@link #TYPE_UNSET}.
*
* <p>For the normal case of horizontal text, {@link #ANCHOR_TYPE_START}, {@link
* #ANCHOR_TYPE_MIDDLE} and {@link #ANCHOR_TYPE_END} correspond to the left, middle and right of
* the cue box respectively.
*/
public final @AnchorType int positionAnchor;
/**
* The size of the cue box in the writing direction specified as a fraction of the viewport size
* in that direction, or {@link #DIMEN_UNSET}.
*/
public final float size;
/**
* The bitmap height as a fraction of the of the viewport size, or {@link #DIMEN_UNSET} if the
* bitmap should be displayed at its natural height given the bitmap dimensions and the specified
* {@link #size}.
*/
public final float bitmapHeight;
/** Specifies whether or not the {@link #windowColor} property is set. */
public final boolean windowColorSet;
/** The fill color of the window. */
public final int windowColor;
/**
* The default text size type for this cue's text, or {@link #TYPE_UNSET} if this cue has no
* default text size.
*/
public final @TextSizeType int textSizeType;
/**
* The default text size for this cue's text, or {@link #DIMEN_UNSET} if this cue has no default
* text size.
*/
public final float textSize;
/**
* The vertical formatting of this Cue, or {@link #TYPE_UNSET} if the cue has no vertical setting
* (and so should be horizontal).
*/
public final @VerticalType int verticalType;
/**
* The shear angle in degrees to be applied to this Cue, expressed in graphics coordinates. This
* results in a skew transform for the block along the inline progression axis.
*/
public final float shearDegrees;
/**
* Creates a text cue whose {@link #textAlignment} is null, whose type parameters are set to
* {@link #TYPE_UNSET} and whose dimension parameters are set to {@link #DIMEN_UNSET}.
*
* @param text See {@link #text}.
* @deprecated Use {@link Builder}.
*/
@SuppressWarnings("deprecation")
@Deprecated
public Cue(CharSequence text) {
this(
text,
/* textAlignment= */ null,
/* line= */ DIMEN_UNSET,
/* lineType= */ TYPE_UNSET,
/* lineAnchor= */ TYPE_UNSET,
/* position= */ DIMEN_UNSET,
/* positionAnchor= */ TYPE_UNSET,
/* size= */ DIMEN_UNSET);
}
/**
* Creates a text cue.
*
* @param text See {@link #text}.
* @param textAlignment See {@link #textAlignment}.
* @param line See {@link #line}.
* @param lineType See {@link #lineType}.
* @param lineAnchor See {@link #lineAnchor}.
* @param position See {@link #position}.
* @param positionAnchor See {@link #positionAnchor}.
* @param size See {@link #size}.
* @deprecated Use {@link Builder}.
*/
@SuppressWarnings("deprecation")
@Deprecated
public Cue(
CharSequence text,
@Nullable Alignment textAlignment,
float line,
@LineType int lineType,
@AnchorType int lineAnchor,
float position,
@AnchorType int positionAnchor,
float size) {
this(
text,
textAlignment,
line,
lineType,
lineAnchor,
position,
positionAnchor,
size,
/* windowColorSet= */ false,
/* windowColor= */ Color.BLACK);
}
/**
* Creates a text cue.
*
* @param text See {@link #text}.
* @param textAlignment See {@link #textAlignment}.
* @param line See {@link #line}.
* @param lineType See {@link #lineType}.
* @param lineAnchor See {@link #lineAnchor}.
* @param position See {@link #position}.
* @param positionAnchor See {@link #positionAnchor}.
* @param size See {@link #size}.
* @param textSizeType See {@link #textSizeType}.
* @param textSize See {@link #textSize}.
* @deprecated Use {@link Builder}.
*/
@Deprecated
public Cue(
CharSequence text,
@Nullable Alignment textAlignment,
float line,
@LineType int lineType,
@AnchorType int lineAnchor,
float position,
@AnchorType int positionAnchor,
float size,
@TextSizeType int textSizeType,
float textSize) {
this(
text,
textAlignment,
/* multiRowAlignment= */ null,
/* bitmap= */ null,
line,
lineType,
lineAnchor,
position,
positionAnchor,
textSizeType,
textSize,
size,
/* bitmapHeight= */ DIMEN_UNSET,
/* windowColorSet= */ false,
/* windowColor= */ Color.BLACK,
/* verticalType= */ TYPE_UNSET,
/* shearDegrees= */ 0f);
}
/**
* Creates a text cue.
*
* @param text See {@link #text}.
* @param textAlignment See {@link #textAlignment}.
* @param line See {@link #line}.
* @param lineType See {@link #lineType}.
* @param lineAnchor See {@link #lineAnchor}.
* @param position See {@link #position}.
* @param positionAnchor See {@link #positionAnchor}.
* @param size See {@link #size}.
* @param windowColorSet See {@link #windowColorSet}.
* @param windowColor See {@link #windowColor}.
* @deprecated Use {@link Builder}.
*/
@Deprecated
public Cue(
CharSequence text,
@Nullable Alignment textAlignment,
float line,
@LineType int lineType,
@AnchorType int lineAnchor,
float position,
@AnchorType int positionAnchor,
float size,
boolean windowColorSet,
int windowColor) {
this(
text,
textAlignment,
/* multiRowAlignment= */ null,
/* bitmap= */ null,
line,
lineType,
lineAnchor,
position,
positionAnchor,
/* textSizeType= */ TYPE_UNSET,
/* textSize= */ DIMEN_UNSET,
size,
/* bitmapHeight= */ DIMEN_UNSET,
windowColorSet,
windowColor,
/* verticalType= */ TYPE_UNSET,
/* shearDegrees= */ 0f);
}
private Cue(
@Nullable CharSequence text,
@Nullable Alignment textAlignment,
@Nullable Alignment multiRowAlignment,
@Nullable Bitmap bitmap,
float line,
@LineType int lineType,
@AnchorType int lineAnchor,
float position,
@AnchorType int positionAnchor,
@TextSizeType int textSizeType,
float textSize,
float size,
float bitmapHeight,
boolean windowColorSet,
int windowColor,
@VerticalType int verticalType,
float shearDegrees) {
// Exactly one of text or bitmap should be set.
if (text == null) {
Assertions.checkNotNull(bitmap);
} else {
Assertions.checkArgument(bitmap == null);
}
if (text instanceof Spanned) {
this.text = SpannedString.valueOf(text);
} else if (text != null) {
this.text = text.toString();
} else {
this.text = null;
}
this.textAlignment = textAlignment;
this.multiRowAlignment = multiRowAlignment;
this.bitmap = bitmap;
this.line = line;
this.lineType = lineType;
this.lineAnchor = lineAnchor;
this.position = position;
this.positionAnchor = positionAnchor;
this.size = size;
this.bitmapHeight = bitmapHeight;
this.windowColorSet = windowColorSet;
this.windowColor = windowColor;
this.textSizeType = textSizeType;
this.textSize = textSize;
this.verticalType = verticalType;
this.shearDegrees = shearDegrees;
}
/** Returns a new {@link Cue.Builder} initialized with the same values as this Cue. */
public Builder buildUpon() {
return new Cue.Builder(this);
}
@Override
public boolean equals(@Nullable Object obj) {
if (this == obj) {
return true;
}
if (obj == null || getClass() != obj.getClass()) {
return false;
}
Cue that = (Cue) obj;
return TextUtils.equals(text, that.text)
&& textAlignment == that.textAlignment
&& multiRowAlignment == that.multiRowAlignment
&& (bitmap == null
? that.bitmap == null
: (that.bitmap != null && bitmap.sameAs(that.bitmap)))
&& line == that.line
&& lineType == that.lineType
&& lineAnchor == that.lineAnchor
&& position == that.position
&& positionAnchor == that.positionAnchor
&& size == that.size
&& bitmapHeight == that.bitmapHeight
&& windowColorSet == that.windowColorSet
&& windowColor == that.windowColor
&& textSizeType == that.textSizeType
&& textSize == that.textSize
&& verticalType == that.verticalType
&& shearDegrees == that.shearDegrees;
}
@Override
public int hashCode() {
return Objects.hashCode(
text,
textAlignment,
multiRowAlignment,
bitmap,
line,
lineType,
lineAnchor,
position,
positionAnchor,
size,
bitmapHeight,
windowColorSet,
windowColor,
textSizeType,
textSize,
verticalType,
shearDegrees);
}
/** A builder for {@link Cue} objects. */
public static final class Builder {
@Nullable private CharSequence text;
@Nullable private Bitmap bitmap;
@Nullable private Alignment textAlignment;
@Nullable private Alignment multiRowAlignment;
private float line;
@LineType private int lineType;
private @AnchorType int lineAnchor;
private float position;
private @AnchorType int positionAnchor;
private @TextSizeType int textSizeType;
private float textSize;
private float size;
private float bitmapHeight;
private boolean windowColorSet;
@ColorInt private int windowColor;
private @VerticalType int verticalType;
private float shearDegrees;
public Builder() {
text = null;
bitmap = null;
textAlignment = null;
multiRowAlignment = null;
line = DIMEN_UNSET;
lineType = TYPE_UNSET;
lineAnchor = TYPE_UNSET;
position = DIMEN_UNSET;
positionAnchor = TYPE_UNSET;
textSizeType = TYPE_UNSET;
textSize = DIMEN_UNSET;
size = DIMEN_UNSET;
bitmapHeight = DIMEN_UNSET;
windowColorSet = false;
windowColor = Color.BLACK;
verticalType = TYPE_UNSET;
}
private Builder(Cue cue) {
text = cue.text;
bitmap = cue.bitmap;
textAlignment = cue.textAlignment;
multiRowAlignment = cue.multiRowAlignment;
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;
shearDegrees = cue.shearDegrees;
}
/**
* Sets the cue text.
*
* <p>Note that {@code text} may be decorated with styling spans.
*
* @see Cue#text
*/
public Builder setText(CharSequence text) {
this.text = text;
return this;
}
/**
* Gets the cue text.
*
* @see Cue#text
*/
@Pure
@Nullable
public CharSequence getText() {
return text;
}
/**
* Sets the cue image.
*
* @see Cue#bitmap
*/
public Builder setBitmap(Bitmap bitmap) {
this.bitmap = bitmap;
return this;
}
/**
* Gets the cue image.
*
* @see Cue#bitmap
*/
@Pure
@Nullable
public Bitmap getBitmap() {
return bitmap;
}
/**
* Sets the alignment of the cue text within the cue box.
*
* <p>Passing null means the alignment is undefined.
*
* @see Cue#textAlignment
*/
public Builder setTextAlignment(@Nullable Layout.Alignment textAlignment) {
this.textAlignment = textAlignment;
return this;
}
/**
* Gets the alignment of the cue text within the cue box, or null if the alignment is undefined.
*
* @see Cue#textAlignment
*/
@Pure
@Nullable
public Alignment getTextAlignment() {
return textAlignment;
}
/**
* Sets the multi-row alignment of the cue.
*
* <p>Passing null means the alignment is undefined.
*
* @see Cue#multiRowAlignment
*/
public Builder setMultiRowAlignment(@Nullable Layout.Alignment multiRowAlignment) {
this.multiRowAlignment = multiRowAlignment;
return this;
}
/**
* Sets the position of the cue box within the viewport in the direction orthogonal to the
* writing direction.
*
* @see Cue#line
* @see Cue#lineType
*/
public Builder setLine(float line, @LineType int lineType) {
this.line = line;
this.lineType = lineType;
return this;
}
/**
* Gets the position of the {@code lineAnchor} of the cue box within the viewport in the
* direction orthogonal to the writing direction.
*
* @see Cue#line
*/
@Pure
public float getLine() {
return line;
}
/**
* Gets the type of the value of {@link #getLine()}.
*
* @see Cue#lineType
*/
@Pure
@LineType
public int getLineType() {
return lineType;
}
/**
* Sets the cue box anchor positioned by {@link #setLine(float, int) line}.
*
* @see Cue#lineAnchor
*/
public Builder setLineAnchor(@AnchorType int lineAnchor) {
this.lineAnchor = lineAnchor;
return this;
}
/**
* Gets the cue box anchor positioned by {@link #setLine(float, int) line}.
*
* @see Cue#lineAnchor
*/
@Pure
@AnchorType
public int getLineAnchor() {
return lineAnchor;
}
/**
* Sets the fractional position of the {@link #setPositionAnchor(int) positionAnchor} of the cue
* box within the viewport in the direction orthogonal to {@link #setLine(float, int) line}.
*
* @see Cue#position
*/
public Builder setPosition(float position) {
this.position = position;
return this;
}
/**
* Gets the fractional position of the {@link #setPositionAnchor(int) positionAnchor} of the cue
* box within the viewport in the direction orthogonal to {@link #setLine(float, int) line}.
*
* @see Cue#position
*/
@Pure
public float getPosition() {
return position;
}
/**
* Sets the cue box anchor positioned by {@link #setPosition(float) position}.
*
* @see Cue#positionAnchor
*/
public Builder setPositionAnchor(@AnchorType int positionAnchor) {
this.positionAnchor = positionAnchor;
return this;
}
/**
* Gets the cue box anchor positioned by {@link #setPosition(float) position}.
*
* @see Cue#positionAnchor
*/
@Pure
@AnchorType
public int getPositionAnchor() {
return positionAnchor;
}
/**
* Sets the default text size and type for this cue's text.
*
* @see Cue#textSize
* @see Cue#textSizeType
*/
public Builder setTextSize(float textSize, @TextSizeType int textSizeType) {
this.textSize = textSize;
this.textSizeType = textSizeType;
return this;
}
/**
* Gets the default text size type for this cue's text.
*
* @see Cue#textSizeType
*/
@Pure
@TextSizeType
public int getTextSizeType() {
return textSizeType;
}
/**
* Gets the default text size for this cue's text.
*
* @see Cue#textSize
*/
@Pure
public float getTextSize() {
return textSize;
}
/**
* Sets the size of the cue box in the writing direction specified as a fraction of the viewport
* size in that direction.
*
* @see Cue#size
*/
public Builder setSize(float size) {
this.size = size;
return this;
}
/**
* Gets the size of the cue box in the writing direction specified as a fraction of the viewport
* size in that direction.
*
* @see Cue#size
*/
@Pure
public float getSize() {
return size;
}
/**
* Sets the bitmap height as a fraction of the viewport size.
*
* @see Cue#bitmapHeight
*/
public Builder setBitmapHeight(float bitmapHeight) {
this.bitmapHeight = bitmapHeight;
return this;
}
/**
* Gets the bitmap height as a fraction of the viewport size.
*
* @see Cue#bitmapHeight
*/
@Pure
public float getBitmapHeight() {
return bitmapHeight;
}
/**
* Sets the fill color of the window.
*
* <p>Also sets {@link Cue#windowColorSet} to true.
*
* @see Cue#windowColor
* @see Cue#windowColorSet
*/
public Builder setWindowColor(@ColorInt int windowColor) {
this.windowColor = windowColor;
this.windowColorSet = true;
return this;
}
/** Sets {@link Cue#windowColorSet} to false. */
public Builder clearWindowColor() {
this.windowColorSet = false;
return this;
}
/**
* Returns true if the fill color of the window is set.
*
* @see Cue#windowColorSet
*/
public boolean isWindowColorSet() {
return windowColorSet;
}
/**
* Gets the fill color of the window.
*
* @see Cue#windowColor
*/
@Pure
@ColorInt
public int getWindowColor() {
return windowColor;
}
/**
* Sets the vertical formatting for this Cue.
*
* @see Cue#verticalType
*/
public Builder setVerticalType(@VerticalType int verticalType) {
this.verticalType = verticalType;
return this;
}
/** Sets the shear angle for this Cue. */
public Builder setShearDegrees(float shearDegrees) {
this.shearDegrees = shearDegrees;
return this;
}
/**
* Gets the vertical formatting for this Cue.
*
* @see Cue#verticalType
*/
@Pure
@VerticalType
public int getVerticalType() {
return verticalType;
}
/** Build the cue. */
public Cue build() {
return new Cue(
text,
textAlignment,
multiRowAlignment,
bitmap,
line,
lineType,
lineAnchor,
position,
positionAnchor,
textSizeType,
textSize,
size,
bitmapHeight,
windowColorSet,
windowColor,
verticalType,
shearDegrees);
}
}
// Bundleable implementation.
@Documented
@Retention(RetentionPolicy.SOURCE)
@IntDef({
FIELD_TEXT,
FIELD_TEXT_ALIGNMENT,
FIELD_MULTI_ROW_ALIGNMENT,
FIELD_BITMAP,
FIELD_LINE,
FIELD_LINE_TYPE,
FIELD_LINE_ANCHOR,
FIELD_POSITION,
FIELD_POSITION_ANCHOR,
FIELD_TEXT_SIZE_TYPE,
FIELD_TEXT_SIZE,
FIELD_SIZE,
FIELD_BITMAP_HEIGHT,
FIELD_WINDOW_COLOR,
FIELD_WINDOW_COLOR_SET,
FIELD_VERTICAL_TYPE,
FIELD_SHEAR_DEGREES
})
private @interface FieldNumber {}
private static final int FIELD_TEXT = 0;
private static final int FIELD_TEXT_ALIGNMENT = 1;
private static final int FIELD_MULTI_ROW_ALIGNMENT = 2;
private static final int FIELD_BITMAP = 3;
private static final int FIELD_LINE = 4;
private static final int FIELD_LINE_TYPE = 5;
private static final int FIELD_LINE_ANCHOR = 6;
private static final int FIELD_POSITION = 7;
private static final int FIELD_POSITION_ANCHOR = 8;
private static final int FIELD_TEXT_SIZE_TYPE = 9;
private static final int FIELD_TEXT_SIZE = 10;
private static final int FIELD_SIZE = 11;
private static final int FIELD_BITMAP_HEIGHT = 12;
private static final int FIELD_WINDOW_COLOR = 13;
private static final int FIELD_WINDOW_COLOR_SET = 14;
private static final int FIELD_VERTICAL_TYPE = 15;
private static final int FIELD_SHEAR_DEGREES = 16;
@Override
public Bundle toBundle() {
Bundle bundle = new Bundle();
bundle.putCharSequence(keyForField(FIELD_TEXT), text);
bundle.putSerializable(keyForField(FIELD_TEXT_ALIGNMENT), textAlignment);
bundle.putSerializable(keyForField(FIELD_MULTI_ROW_ALIGNMENT), multiRowAlignment);
bundle.putParcelable(keyForField(FIELD_BITMAP), bitmap);
bundle.putFloat(keyForField(FIELD_LINE), line);
bundle.putInt(keyForField(FIELD_LINE_TYPE), lineType);
bundle.putInt(keyForField(FIELD_LINE_ANCHOR), lineAnchor);
bundle.putFloat(keyForField(FIELD_POSITION), position);
bundle.putInt(keyForField(FIELD_POSITION_ANCHOR), positionAnchor);
bundle.putInt(keyForField(FIELD_TEXT_SIZE_TYPE), textSizeType);
bundle.putFloat(keyForField(FIELD_TEXT_SIZE), textSize);
bundle.putFloat(keyForField(FIELD_SIZE), size);
bundle.putFloat(keyForField(FIELD_BITMAP_HEIGHT), bitmapHeight);
bundle.putBoolean(keyForField(FIELD_WINDOW_COLOR_SET), windowColorSet);
bundle.putInt(keyForField(FIELD_WINDOW_COLOR), windowColor);
bundle.putInt(keyForField(FIELD_VERTICAL_TYPE), verticalType);
bundle.putFloat(keyForField(FIELD_SHEAR_DEGREES), shearDegrees);
return bundle;
}
public static final Creator<Cue> CREATOR = Cue::fromBundle;
private static final Cue fromBundle(Bundle bundle) {
Builder builder = new Builder();
@Nullable CharSequence text = bundle.getCharSequence(keyForField(FIELD_TEXT));
if (text != null) {
builder.setText(text);
}
@Nullable
Alignment textAlignment = (Alignment) bundle.getSerializable(keyForField(FIELD_TEXT_ALIGNMENT));
if (textAlignment != null) {
builder.setTextAlignment(textAlignment);
}
@Nullable
Alignment multiRowAlignment =
(Alignment) bundle.getSerializable(keyForField(FIELD_MULTI_ROW_ALIGNMENT));
if (multiRowAlignment != null) {
builder.setMultiRowAlignment(multiRowAlignment);
}
@Nullable Bitmap bitmap = bundle.getParcelable(keyForField(FIELD_BITMAP));
if (bitmap != null) {
builder.setBitmap(bitmap);
}
if (bundle.containsKey(keyForField(FIELD_LINE))
&& bundle.containsKey(keyForField(FIELD_LINE_TYPE))) {
builder.setLine(
bundle.getFloat(keyForField(FIELD_LINE)), bundle.getInt(keyForField(FIELD_LINE_TYPE)));
}
if (bundle.containsKey(keyForField(FIELD_LINE_ANCHOR))) {
builder.setLineAnchor(bundle.getInt(keyForField(FIELD_LINE_ANCHOR)));
}
if (bundle.containsKey(keyForField(FIELD_POSITION))) {
builder.setPosition(bundle.getFloat(keyForField(FIELD_POSITION)));
}
if (bundle.containsKey(keyForField(FIELD_POSITION_ANCHOR))) {
builder.setPositionAnchor(bundle.getInt(keyForField(FIELD_POSITION_ANCHOR)));
}
if (bundle.containsKey(keyForField(FIELD_TEXT_SIZE))
&& bundle.containsKey(keyForField(FIELD_TEXT_SIZE_TYPE))) {
builder.setTextSize(
bundle.getFloat(keyForField(FIELD_TEXT_SIZE)),
bundle.getInt(keyForField(FIELD_TEXT_SIZE_TYPE)));
}
if (bundle.containsKey(keyForField(FIELD_SIZE))) {
builder.setSize(bundle.getFloat(keyForField(FIELD_SIZE)));
}
if (bundle.containsKey(keyForField(FIELD_BITMAP_HEIGHT))) {
builder.setBitmapHeight(bundle.getFloat(keyForField(FIELD_BITMAP_HEIGHT)));
}
if (bundle.containsKey(keyForField(FIELD_WINDOW_COLOR))) {
builder.setWindowColor(bundle.getInt(keyForField(FIELD_WINDOW_COLOR)));
}
if (!bundle.getBoolean(keyForField(FIELD_WINDOW_COLOR_SET), /* defaultValue= */ false)) {
builder.clearWindowColor();
}
if (bundle.containsKey(keyForField(FIELD_VERTICAL_TYPE))) {
builder.setVerticalType(bundle.getInt(keyForField(FIELD_VERTICAL_TYPE)));
}
if (bundle.containsKey(keyForField(FIELD_SHEAR_DEGREES))) {
builder.setShearDegrees(bundle.getFloat(keyForField(FIELD_SHEAR_DEGREES)));
}
return builder.build();
}
private static String keyForField(@FieldNumber int field) {
return Integer.toString(field, Character.MAX_RADIX);
}
}