public final class

Cue

extends java.lang.Object

implements Bundleable

 java.lang.Object

↳androidx.media3.common.text.Cue

Gradle dependencies

compile group: 'androidx.media3', name: 'media3-common', version: '1.0.0-alpha03'

  • groupId: androidx.media3
  • artifactId: media3-common
  • version: 1.0.0-alpha03

Artifact androidx.media3:media3-common:1.0.0-alpha03 it located at Google repository (https://maven.google.com/)

Overview

Contains information about a specific cue, including textual content and formatting data.

Summary

Fields
public static final intANCHOR_TYPE_END

Anchors the right (for horizontal positions) or bottom (for vertical positions) edge of the cue box.

public static final intANCHOR_TYPE_MIDDLE

Anchors the middle of the cue box.

public static final intANCHOR_TYPE_START

Anchors the left (for horizontal positions) or top (for vertical positions) edge of the cue box.

public final Bitmapbitmap

The cue image, or null if this is a text cue.

public final floatbitmapHeight

The bitmap height as a fraction of the of the viewport size, or Cue.DIMEN_UNSET if the bitmap should be displayed at its natural height given the bitmap dimensions and the specified Cue.size.

public static final Bundleable.Creator<Cue>CREATOR

public static final floatDIMEN_UNSET

An unset position, width or size.

public static final CueEMPTY

The empty cue.

public final floatline

The position of the cue box within the viewport in the direction orthogonal to the writing direction (determined by Cue.verticalType), or Cue.DIMEN_UNSET.

public static final intLINE_TYPE_FRACTION

Value for Cue.lineType when Cue.line is a fractional position.

public static final intLINE_TYPE_NUMBER

Value for Cue.lineType when Cue.line is a line number.

public final intlineAnchor

The cue box anchor positioned by Cue.line when Cue.lineType is Cue.LINE_TYPE_FRACTION.

public final intlineType

The type of the Cue.line value.

public final AlignmentmultiRowAlignment

The alignment of multiple lines of text relative to the longest line, or null if the alignment is undefined.

public final floatposition

The fractional position of the Cue.positionAnchor of the cue box within the viewport in the direction orthogonal to Cue.line, or Cue.DIMEN_UNSET.

public final intpositionAnchor

The cue box anchor positioned by Cue.position.

public final floatshearDegrees

The shear angle in degrees to be applied to this Cue, expressed in graphics coordinates.

public final floatsize

The size of the cue box in the writing direction specified as a fraction of the viewport size in that direction, or Cue.DIMEN_UNSET.

public final java.lang.CharSequencetext

The cue text, or null if this is an image cue.

public static final intTEXT_SIZE_TYPE_ABSOLUTE

Text size is measured in number of pixels.

public static final intTEXT_SIZE_TYPE_FRACTIONAL

Text size is measured as a fraction of the viewport size minus the view padding.

public static final intTEXT_SIZE_TYPE_FRACTIONAL_IGNORE_PADDING

Text size is measured as a fraction of the viewport size, ignoring the view padding

public final AlignmenttextAlignment

The alignment of the cue text within the cue box, or null if the alignment is undefined.

public final floattextSize

The default text size for this cue's text, or Cue.DIMEN_UNSET if this cue has no default text size.

public final inttextSizeType

The default text size type for this cue's text, or Cue.TYPE_UNSET if this cue has no default text size.

public static final intTYPE_UNSET

An unset anchor, line, text size or vertical type value.

public static final intVERTICAL_TYPE_LR

Vertical left-to-right (e.g.

public static final intVERTICAL_TYPE_RL

Vertical right-to-left (e.g.

public final intverticalType

The vertical formatting of this Cue, or Cue.TYPE_UNSET if the cue has no vertical setting (and so should be horizontal).

public final intwindowColor

The fill color of the window.

public final booleanwindowColorSet

Specifies whether or not the Cue.windowColor property is set.

Constructors
publicCue(java.lang.CharSequence text)

Creates a text cue whose Cue.textAlignment is null, whose type parameters are set to Cue.TYPE_UNSET and whose dimension parameters are set to Cue.DIMEN_UNSET.

publicCue(java.lang.CharSequence text, Alignment textAlignment, float line, int lineType, int lineAnchor, float position, int positionAnchor, float size)

Creates a text cue.

publicCue(java.lang.CharSequence text, Alignment textAlignment, float line, int lineType, int lineAnchor, float position, int positionAnchor, float size, boolean windowColorSet, int windowColor)

Creates a text cue.

publicCue(java.lang.CharSequence text, Alignment textAlignment, float line, int lineType, int lineAnchor, float position, int positionAnchor, float size, int textSizeType, float textSize)

Creates a text cue.

Methods
public Cue.BuilderbuildUpon()

Returns a new Cue.Builder initialized with the same values as this Cue.

public booleanequals(java.lang.Object obj)

public inthashCode()

public BundletoBundle()

from java.lang.Objectclone, finalize, getClass, notify, notifyAll, toString, wait, wait, wait

Fields

public static final Cue EMPTY

The empty cue.

public static final float DIMEN_UNSET

An unset position, width or size.

public static final int TYPE_UNSET

An unset anchor, line, text size or vertical type value.

public static final int ANCHOR_TYPE_START

Anchors the left (for horizontal positions) or top (for vertical positions) edge of the cue box.

public static final int ANCHOR_TYPE_MIDDLE

Anchors the middle of the cue box.

public static final int ANCHOR_TYPE_END

Anchors the right (for horizontal positions) or bottom (for vertical positions) edge of the cue box.

public static final int LINE_TYPE_FRACTION

Value for Cue.lineType when Cue.line is a fractional position.

public static final int LINE_TYPE_NUMBER

Value for Cue.lineType when Cue.line is a line number.

public static final int TEXT_SIZE_TYPE_FRACTIONAL

Text size is measured as a fraction of the viewport size minus the view padding.

public static final int TEXT_SIZE_TYPE_FRACTIONAL_IGNORE_PADDING

Text size is measured as a fraction of the viewport size, ignoring the view padding

public static final int TEXT_SIZE_TYPE_ABSOLUTE

Text size is measured in number of pixels.

public static final int VERTICAL_TYPE_RL

Vertical right-to-left (e.g. for Japanese).

public static final int VERTICAL_TYPE_LR

Vertical left-to-right (e.g. for Mongolian).

public final java.lang.CharSequence text

The cue text, or null if this is an image cue. Note the java.lang.CharSequence may be decorated with styling spans.

public final Alignment textAlignment

The alignment of the cue text within the cue box, or null if the alignment is undefined.

public final Alignment multiRowAlignment

The alignment of multiple lines of text relative to the longest line, or null if the alignment is undefined.

public final Bitmap bitmap

The cue image, or null if this is a text cue.

public final float line

The position of the cue box within the viewport in the direction orthogonal to the writing direction (determined by Cue.verticalType), or Cue.DIMEN_UNSET. When set, the interpretation of the value depends on the value of Cue.lineType.

The measurement direction depends on Cue.verticalType:

  • For Cue.TYPE_UNSET (i.e. horizontal), this is the vertical position relative to the top of the viewport.
  • For Cue.VERTICAL_TYPE_LR this is the horizontal position relative to the left of the viewport.
  • For Cue.VERTICAL_TYPE_RL this is the horizontal position relative to the right of the viewport.

public final int lineType

The type of the Cue.line value.

  • Cue.LINE_TYPE_FRACTION indicates that Cue.line is a fractional position within the viewport (measured to the part of the cue box determined by Cue.lineAnchor).
  • Cue.LINE_TYPE_NUMBER indicates that Cue.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:
    • Cue.lineAnchor) is ignored.
    • When 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.
    • When 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.
    • For horizontal text the start and end of the viewport are the top and bottom respectively.

public final int lineAnchor

The cue box anchor positioned by Cue.line when Cue.lineType is Cue.LINE_TYPE_FRACTION.

One of:

For the normal case of horizontal text, Cue.ANCHOR_TYPE_START, Cue.ANCHOR_TYPE_MIDDLE and Cue.ANCHOR_TYPE_END correspond to the top, middle and bottom of the cue box respectively.

public final float position

The fractional position of the Cue.positionAnchor of the cue box within the viewport in the direction orthogonal to Cue.line, or Cue.DIMEN_UNSET.

The measurement direction depends on Cue.verticalType.

  • For Cue.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.
  • For Cue.VERTICAL_TYPE_LR and Cue.VERTICAL_TYPE_RL (i.e. vertical), this is the vertical position relative to the top of the viewport.

public final int positionAnchor

The cue box anchor positioned by Cue.position. One of Cue.ANCHOR_TYPE_START, Cue.ANCHOR_TYPE_MIDDLE, Cue.ANCHOR_TYPE_END and Cue.TYPE_UNSET.

For the normal case of horizontal text, Cue.ANCHOR_TYPE_START, Cue.ANCHOR_TYPE_MIDDLE and Cue.ANCHOR_TYPE_END correspond to the left, middle and right of the cue box respectively.

public final float size

The size of the cue box in the writing direction specified as a fraction of the viewport size in that direction, or Cue.DIMEN_UNSET.

public final float bitmapHeight

The bitmap height as a fraction of the of the viewport size, or Cue.DIMEN_UNSET if the bitmap should be displayed at its natural height given the bitmap dimensions and the specified Cue.size.

public final boolean windowColorSet

Specifies whether or not the Cue.windowColor property is set.

public final int windowColor

The fill color of the window.

public final int textSizeType

The default text size type for this cue's text, or Cue.TYPE_UNSET if this cue has no default text size.

public final float textSize

The default text size for this cue's text, or Cue.DIMEN_UNSET if this cue has no default text size.

public final int verticalType

The vertical formatting of this Cue, or Cue.TYPE_UNSET if the cue has no vertical setting (and so should be horizontal).

public final float shearDegrees

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 static final Bundleable.Creator<Cue> CREATOR

Constructors

public Cue(java.lang.CharSequence text)

Deprecated: Use Cue.Builder.

Creates a text cue whose Cue.textAlignment is null, whose type parameters are set to Cue.TYPE_UNSET and whose dimension parameters are set to Cue.DIMEN_UNSET.

Parameters:

text: See Cue.text.

public Cue(java.lang.CharSequence text, Alignment textAlignment, float line, int lineType, int lineAnchor, float position, int positionAnchor, float size)

Deprecated: Use Cue.Builder.

Creates a text cue.

Parameters:

text: See Cue.text.
textAlignment: See Cue.textAlignment.
line: See Cue.line.
lineType: See Cue.lineType.
lineAnchor: See Cue.lineAnchor.
position: See Cue.position.
positionAnchor: See Cue.positionAnchor.
size: See Cue.size.

public Cue(java.lang.CharSequence text, Alignment textAlignment, float line, int lineType, int lineAnchor, float position, int positionAnchor, float size, int textSizeType, float textSize)

Deprecated: Use Cue.Builder.

Creates a text cue.

Parameters:

text: See Cue.text.
textAlignment: See Cue.textAlignment.
line: See Cue.line.
lineType: See Cue.lineType.
lineAnchor: See Cue.lineAnchor.
position: See Cue.position.
positionAnchor: See Cue.positionAnchor.
size: See Cue.size.
textSizeType: See Cue.textSizeType.
textSize: See Cue.textSize.

public Cue(java.lang.CharSequence text, Alignment textAlignment, float line, int lineType, int lineAnchor, float position, int positionAnchor, float size, boolean windowColorSet, int windowColor)

Deprecated: Use Cue.Builder.

Creates a text cue.

Parameters:

text: See Cue.text.
textAlignment: See Cue.textAlignment.
line: See Cue.line.
lineType: See Cue.lineType.
lineAnchor: See Cue.lineAnchor.
position: See Cue.position.
positionAnchor: See Cue.positionAnchor.
size: See Cue.size.
windowColorSet: See Cue.windowColorSet.
windowColor: See Cue.windowColor.

Methods

public Cue.Builder buildUpon()

Returns a new Cue.Builder initialized with the same values as this Cue.

public boolean equals(java.lang.Object obj)

public int hashCode()

public Bundle toBundle()

Source

/*
 * 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 androidx.media3.common.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 androidx.media3.common.Bundleable;
import androidx.media3.common.util.Assertions;
import androidx.media3.common.util.UnstableApi;
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}.
   */
  // @Target list includes both 'default' targets and TYPE_USE, to ensure backwards compatibility
  // with Kotlin usages from before TYPE_USE was added.
  @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}.
   */
  // @Target list includes both 'default' targets and TYPE_USE, to ensure backwards compatibility
  // with Kotlin usages from before TYPE_USE was added.
  @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}.
   */
  // @Target list includes both 'default' targets and TYPE_USE, to ensure backwards compatibility
  // with Kotlin usages from before TYPE_USE was added.
  @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}.
   */
  // @Target list includes both 'default' targets and TYPE_USE, to ensure backwards compatibility
  // with Kotlin usages from before TYPE_USE was added.
  @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}.
   */
  @UnstableApi
  @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}.
   */
  @UnstableApi
  @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}.
   */
  @UnstableApi
  @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}.
   */
  @UnstableApi
  @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. */
  @UnstableApi
  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. */
  @UnstableApi
  public static final class Builder {
    @Nullable private CharSequence text;
    @Nullable private Bitmap bitmap;
    @Nullable private Alignment textAlignment;
    @Nullable private Alignment multiRowAlignment;
    private float line;
    private @LineType 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
    public @LineType 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
    public @AnchorType 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
    public @AnchorType 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
    public @TextSizeType 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
    public @VerticalType 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)
  @Target(TYPE_USE)
  @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;

  @UnstableApi
  @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;
  }

  @UnstableApi 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);
  }
}