Java Code Examples for com.google.android.exoplayer2.text.Cue#DIMEN_UNSET

The following examples show how to use com.google.android.exoplayer2.text.Cue#DIMEN_UNSET . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: WebvttCue.java    From MediaSDK with Apache License 2.0 6 votes vote down vote up
public void reset() {
  startTime = 0;
  endTime = 0;
  text = null;
  // Default: https://www.w3.org/TR/webvtt1/#webvtt-cue-text-alignment
  textAlignment = TEXT_ALIGNMENT_CENTER;
  line = Cue.DIMEN_UNSET;
  // Defaults to NUMBER (true): https://www.w3.org/TR/webvtt1/#webvtt-cue-snap-to-lines-flag
  lineType = Cue.LINE_TYPE_NUMBER;
  // Default: https://www.w3.org/TR/webvtt1/#webvtt-cue-line-alignment
  lineAnchor = Cue.ANCHOR_TYPE_START;
  position = Cue.DIMEN_UNSET;
  positionAnchor = Cue.TYPE_UNSET;
  // Default: https://www.w3.org/TR/webvtt1/#webvtt-cue-size
  width = 1.0f;
}
 
Example 2
Source File: WebvttCue.java    From MediaSDK with Apache License 2.0 6 votes vote down vote up
public WebvttCue build() {
  line = computeLine(line, lineType);

  if (position == Cue.DIMEN_UNSET) {
    position = derivePosition(textAlignment);
  }

  if (positionAnchor == Cue.TYPE_UNSET) {
    positionAnchor = derivePositionAnchor(textAlignment);
  }

  width = Math.min(width, deriveMaxSize(positionAnchor, position));

  return new WebvttCue(
      startTime,
      endTime,
      Assertions.checkNotNull(text),
      convertTextAlignment(textAlignment),
      line,
      lineType,
      lineAnchor,
      position,
      positionAnchor,
      width);
}
 
Example 3
Source File: SsaDecoder.java    From MediaSDK with Apache License 2.0 6 votes vote down vote up
/**
 * Constructs an SsaDecoder with optional format and header info.
 *
 * @param initializationData Optional initialization data for the decoder. If not null or empty,
 *     the initialization data must consist of two byte arrays. The first must contain an SSA
 *     format line. The second must contain an SSA header that will be assumed common to all
 *     samples. The header is everything in an SSA file before the {@code [Events]} section (i.e.
 *     {@code [Script Info]} and optional {@code [V4+ Styles]} section.
 */
public SsaDecoder(@Nullable List<byte[]> initializationData) {
  super("SsaDecoder");
  screenWidth = Cue.DIMEN_UNSET;
  screenHeight = Cue.DIMEN_UNSET;

  if (initializationData != null && !initializationData.isEmpty()) {
    haveInitializationData = true;
    String formatLine = Util.fromUtf8Bytes(initializationData.get(0));
    Assertions.checkArgument(formatLine.startsWith(FORMAT_LINE_PREFIX));
    dialogueFormatFromInitializationData =
        Assertions.checkNotNull(SsaDialogueFormat.fromFormatLine(formatLine));
    parseHeader(new ParsableByteArray(initializationData.get(1)));
  } else {
    haveInitializationData = false;
    dialogueFormatFromInitializationData = null;
  }
}
 
Example 4
Source File: WebvttCue.java    From Telegram with GNU General Public License v2.0 5 votes vote down vote up
public WebvttCue build() {
  if (position != Cue.DIMEN_UNSET && positionAnchor == Cue.TYPE_UNSET) {
    derivePositionAnchorFromAlignment();
  }
  return new WebvttCue(startTime, endTime, text, textAlignment, line, lineType, lineAnchor,
      position, positionAnchor, width);
}
 
Example 5
Source File: Tx3gDecoder.java    From TelePlus-Android with GNU General Public License v2.0 5 votes vote down vote up
@Override
protected Subtitle decode(byte[] bytes, int length, boolean reset)
    throws SubtitleDecoderException {
  parsableByteArray.reset(bytes, length);
  String cueTextString = readSubtitleText(parsableByteArray);
  if (cueTextString.isEmpty()) {
    return Tx3gSubtitle.EMPTY;
  }
  // Attach default styles.
  SpannableStringBuilder cueText = new SpannableStringBuilder(cueTextString);
  attachFontFace(cueText, defaultFontFace, DEFAULT_FONT_FACE, 0, cueText.length(),
      SPAN_PRIORITY_LOW);
  attachColor(cueText, defaultColorRgba, DEFAULT_COLOR, 0, cueText.length(),
      SPAN_PRIORITY_LOW);
  attachFontFamily(cueText, defaultFontFamily, DEFAULT_FONT_FAMILY, 0, cueText.length(),
      SPAN_PRIORITY_LOW);
  float verticalPlacement = defaultVerticalPlacement;
  // Find and attach additional styles.
  while (parsableByteArray.bytesLeft() >= SIZE_ATOM_HEADER) {
    int position = parsableByteArray.getPosition();
    int atomSize = parsableByteArray.readInt();
    int atomType = parsableByteArray.readInt();
    if (atomType == TYPE_STYL) {
      assertTrue(parsableByteArray.bytesLeft() >= SIZE_SHORT);
      int styleRecordCount = parsableByteArray.readUnsignedShort();
      for (int i = 0; i < styleRecordCount; i++) {
        applyStyleRecord(parsableByteArray, cueText);
      }
    } else if (atomType == TYPE_TBOX && customVerticalPlacement) {
      assertTrue(parsableByteArray.bytesLeft() >= SIZE_SHORT);
      int requestedVerticalPlacement = parsableByteArray.readUnsignedShort();
      verticalPlacement = (float) requestedVerticalPlacement / calculatedVideoTrackHeight;
      verticalPlacement = Util.constrainValue(verticalPlacement, 0.0f, 0.95f);
    }
    parsableByteArray.setPosition(position + atomSize);
  }
  return new Tx3gSubtitle(new Cue(cueText, null, verticalPlacement, Cue.LINE_TYPE_FRACTION,
      Cue.ANCHOR_TYPE_START, Cue.DIMEN_UNSET, Cue.TYPE_UNSET, Cue.DIMEN_UNSET));
}
 
Example 6
Source File: WebvttCue.java    From Telegram-FOSS with GNU General Public License v2.0 5 votes vote down vote up
public void reset() {
  startTime = 0;
  endTime = 0;
  text = null;
  textAlignment = null;
  line = Cue.DIMEN_UNSET;
  lineType = Cue.TYPE_UNSET;
  lineAnchor = Cue.TYPE_UNSET;
  position = Cue.DIMEN_UNSET;
  positionAnchor = Cue.TYPE_UNSET;
  width = Cue.DIMEN_UNSET;
}
 
Example 7
Source File: WebvttCue.java    From TelePlus-Android with GNU General Public License v2.0 5 votes vote down vote up
public WebvttCue build() {
  if (position != Cue.DIMEN_UNSET && positionAnchor == Cue.TYPE_UNSET) {
    derivePositionAnchorFromAlignment();
  }
  return new WebvttCue(startTime, endTime, text, textAlignment, line, lineType, lineAnchor,
      position, positionAnchor, width);
}
 
Example 8
Source File: TtmlRegion.java    From Telegram with GNU General Public License v2.0 5 votes vote down vote up
public TtmlRegion(String id) {
  this(
      id,
      /* position= */ Cue.DIMEN_UNSET,
      /* line= */ Cue.DIMEN_UNSET,
      /* lineType= */ Cue.TYPE_UNSET,
      /* lineAnchor= */ Cue.TYPE_UNSET,
      /* width= */ Cue.DIMEN_UNSET,
      /* height= */ Cue.DIMEN_UNSET,
      /* textSizeType= */ Cue.TYPE_UNSET,
      /* textSize= */ Cue.DIMEN_UNSET);
}
 
Example 9
Source File: WebvttCue.java    From TelePlus-Android with GNU General Public License v2.0 5 votes vote down vote up
public void reset() {
  startTime = 0;
  endTime = 0;
  text = null;
  textAlignment = null;
  line = Cue.DIMEN_UNSET;
  lineType = Cue.TYPE_UNSET;
  lineAnchor = Cue.TYPE_UNSET;
  position = Cue.DIMEN_UNSET;
  positionAnchor = Cue.TYPE_UNSET;
  width = Cue.DIMEN_UNSET;
}
 
Example 10
Source File: SsaDecoder.java    From MediaSDK with Apache License 2.0 5 votes vote down vote up
private static float computeDefaultLineOrPosition(@Cue.AnchorType int anchor) {
  switch (anchor) {
    case Cue.ANCHOR_TYPE_START:
      return DEFAULT_MARGIN;
    case Cue.ANCHOR_TYPE_MIDDLE:
      return 0.5f;
    case Cue.ANCHOR_TYPE_END:
      return 1.0f - DEFAULT_MARGIN;
    case Cue.TYPE_UNSET:
    default:
      return Cue.DIMEN_UNSET;
  }
}
 
Example 11
Source File: SsaDecoder.java    From MediaSDK with Apache License 2.0 5 votes vote down vote up
private static Cue createCue(
    String text,
    @Nullable SsaStyle style,
    SsaStyle.Overrides styleOverrides,
    float screenWidth,
    float screenHeight) {
  @SsaStyle.SsaAlignment int alignment;
  if (styleOverrides.alignment != SsaStyle.SSA_ALIGNMENT_UNKNOWN) {
    alignment = styleOverrides.alignment;
  } else if (style != null) {
    alignment = style.alignment;
  } else {
    alignment = SsaStyle.SSA_ALIGNMENT_UNKNOWN;
  }
  @Cue.AnchorType int positionAnchor = toPositionAnchor(alignment);
  @Cue.AnchorType int lineAnchor = toLineAnchor(alignment);

  float position;
  float line;
  if (styleOverrides.position != null
      && screenHeight != Cue.DIMEN_UNSET
      && screenWidth != Cue.DIMEN_UNSET) {
    position = styleOverrides.position.x / screenWidth;
    line = styleOverrides.position.y / screenHeight;
  } else {
    // TODO: Read the MarginL, MarginR and MarginV values from the Style & Dialogue lines.
    position = computeDefaultLineOrPosition(positionAnchor);
    line = computeDefaultLineOrPosition(lineAnchor);
  }

  return new Cue(
      text,
      toTextAlignment(alignment),
      line,
      Cue.LINE_TYPE_FRACTION,
      lineAnchor,
      position,
      positionAnchor,
      /* size= */ Cue.DIMEN_UNSET);
}
 
Example 12
Source File: WebvttCue.java    From K-Sonic with MIT License 5 votes vote down vote up
public WebvttCue build() {
  if (position != Cue.DIMEN_UNSET && positionAnchor == Cue.TYPE_UNSET) {
    derivePositionAnchorFromAlignment();
  }
  return new WebvttCue(startTime, endTime, text, textAlignment, line, lineType, lineAnchor,
      position, positionAnchor, width);
}
 
Example 13
Source File: SubripDecoder.java    From Telegram-FOSS with GNU General Public License v2.0 4 votes vote down vote up
/**
 * Build a {@link Cue} based on the given text and alignment tag.
 *
 * @param text The text.
 * @param alignmentTag The alignment tag, or {@code null} if no alignment tag is available.
 * @return Built cue
 */
private Cue buildCue(Spanned text, @Nullable String alignmentTag) {
  if (alignmentTag == null) {
    return new Cue(text);
  }

  // Horizontal alignment.
  @Cue.AnchorType int positionAnchor;
  switch (alignmentTag) {
    case ALIGN_BOTTOM_LEFT:
    case ALIGN_MID_LEFT:
    case ALIGN_TOP_LEFT:
      positionAnchor = Cue.ANCHOR_TYPE_START;
      break;
    case ALIGN_BOTTOM_RIGHT:
    case ALIGN_MID_RIGHT:
    case ALIGN_TOP_RIGHT:
      positionAnchor = Cue.ANCHOR_TYPE_END;
      break;
    case ALIGN_BOTTOM_MID:
    case ALIGN_MID_MID:
    case ALIGN_TOP_MID:
    default:
      positionAnchor = Cue.ANCHOR_TYPE_MIDDLE;
      break;
  }

  // Vertical alignment.
  @Cue.AnchorType int lineAnchor;
  switch (alignmentTag) {
    case ALIGN_BOTTOM_LEFT:
    case ALIGN_BOTTOM_MID:
    case ALIGN_BOTTOM_RIGHT:
      lineAnchor = Cue.ANCHOR_TYPE_END;
      break;
    case ALIGN_TOP_LEFT:
    case ALIGN_TOP_MID:
    case ALIGN_TOP_RIGHT:
      lineAnchor = Cue.ANCHOR_TYPE_START;
      break;
    case ALIGN_MID_LEFT:
    case ALIGN_MID_MID:
    case ALIGN_MID_RIGHT:
    default:
      lineAnchor = Cue.ANCHOR_TYPE_MIDDLE;
      break;
  }

  return new Cue(
      text,
      /* textAlignment= */ null,
      getFractionalPositionForAnchorType(lineAnchor),
      Cue.LINE_TYPE_FRACTION,
      lineAnchor,
      getFractionalPositionForAnchorType(positionAnchor),
      positionAnchor,
      Cue.DIMEN_UNSET);
}
 
Example 14
Source File: Cea608Decoder.java    From K-Sonic with MIT License 4 votes vote down vote up
public Cue build() {
  SpannableStringBuilder cueString = new SpannableStringBuilder();
  // Add any rolled up captions, separated by new lines.
  for (int i = 0; i < rolledUpCaptions.size(); i++) {
    cueString.append(rolledUpCaptions.get(i));
    cueString.append('\n');
  }
  // Add the current line.
  cueString.append(buildSpannableString());

  if (cueString.length() == 0) {
    // The cue is empty.
    return null;
  }

  float position;
  int positionAnchor;
  // The number of empty columns before the start of the text, in the range [0-31].
  int startPadding = indent + tabOffset;
  // The number of empty columns after the end of the text, in the same range.
  int endPadding = SCREEN_CHARWIDTH - startPadding - cueString.length();
  int startEndPaddingDelta = startPadding - endPadding;
  if (captionMode == CC_MODE_POP_ON && Math.abs(startEndPaddingDelta) < 3) {
    // Treat approximately centered pop-on captions are middle aligned.
    position = 0.5f;
    positionAnchor = Cue.ANCHOR_TYPE_MIDDLE;
  } else if (captionMode == CC_MODE_POP_ON && startEndPaddingDelta > 0) {
    // Treat pop-on captions with less padding at the end than the start as end aligned.
    position = (float) (SCREEN_CHARWIDTH - endPadding) / SCREEN_CHARWIDTH;
    // Adjust the position to fit within the safe area.
    position = position * 0.8f + 0.1f;
    positionAnchor = Cue.ANCHOR_TYPE_END;
  } else {
    // For all other cases assume start aligned.
    position = (float) startPadding / SCREEN_CHARWIDTH;
    // Adjust the position to fit within the safe area.
    position = position * 0.8f + 0.1f;
    positionAnchor = Cue.ANCHOR_TYPE_START;
  }

  int lineAnchor;
  int line;
  // Note: Row indices are in the range [1-15].
  if (captionMode == CC_MODE_ROLL_UP || row > (BASE_ROW / 2)) {
    lineAnchor = Cue.ANCHOR_TYPE_END;
    line = row - BASE_ROW;
    // Two line adjustments. The first is because line indices from the bottom of the window
    // start from -1 rather than 0. The second is a blank row to act as the safe area.
    line -= 2;
  } else {
    lineAnchor = Cue.ANCHOR_TYPE_START;
    // Line indices from the top of the window start from 0, but we want a blank row to act as
    // the safe area. As a result no adjustment is necessary.
    line = row;
  }

  return new Cue(cueString, Alignment.ALIGN_NORMAL, line, Cue.LINE_TYPE_NUMBER, lineAnchor,
      position, positionAnchor, Cue.DIMEN_UNSET);
}
 
Example 15
Source File: Cea708Decoder.java    From TelePlus-Android with GNU General Public License v2.0 4 votes vote down vote up
public Cea708Cue build() {
  if (isEmpty()) {
    // The cue is empty.
    return null;
  }

  SpannableStringBuilder cueString = new SpannableStringBuilder();

  // Add any rolled up captions, separated by new lines.
  for (int i = 0; i < rolledUpCaptions.size(); i++) {
    cueString.append(rolledUpCaptions.get(i));
    cueString.append('\n');
  }
  // Add the current line.
  cueString.append(buildSpannableString());

  // TODO: Add support for right-to-left languages (i.e. where right would correspond to normal
  // alignment).
  Alignment alignment;
  switch (justification) {
    case JUSTIFICATION_FULL:
      // TODO: Add support for full justification.
    case JUSTIFICATION_LEFT:
      alignment = Alignment.ALIGN_NORMAL;
      break;
    case JUSTIFICATION_RIGHT:
      alignment = Alignment.ALIGN_OPPOSITE;
      break;
    case JUSTIFICATION_CENTER:
      alignment = Alignment.ALIGN_CENTER;
      break;
    default:
      throw new IllegalArgumentException("Unexpected justification value: " + justification);
  }

  float position;
  float line;
  if (relativePositioning) {
    position = (float) horizontalAnchor / RELATIVE_CUE_SIZE;
    line = (float) verticalAnchor / RELATIVE_CUE_SIZE;
  } else {
    position = (float) horizontalAnchor / HORIZONTAL_SIZE;
    line = (float) verticalAnchor / VERTICAL_SIZE;
  }
  // Apply screen-edge padding to the line and position.
  position = (position * 0.9f) + 0.05f;
  line = (line * 0.9f) + 0.05f;

  // anchorId specifies where the anchor should be placed on the caption cue/window. The 9
  // possible configurations are as follows:
  //   0-----1-----2
  //   |           |
  //   3     4     5
  //   |           |
  //   6-----7-----8
  @AnchorType int verticalAnchorType;
  if (anchorId % 3 == 0) {
    verticalAnchorType = Cue.ANCHOR_TYPE_START;
  } else if (anchorId % 3 == 1) {
    verticalAnchorType = Cue.ANCHOR_TYPE_MIDDLE;
  } else {
    verticalAnchorType = Cue.ANCHOR_TYPE_END;
  }
  // TODO: Add support for right-to-left languages (i.e. where start is on the right).
  @AnchorType int horizontalAnchorType;
  if (anchorId / 3 == 0) {
    horizontalAnchorType = Cue.ANCHOR_TYPE_START;
  } else if (anchorId / 3 == 1) {
    horizontalAnchorType = Cue.ANCHOR_TYPE_MIDDLE;
  } else {
    horizontalAnchorType = Cue.ANCHOR_TYPE_END;
  }

  boolean windowColorSet = (windowFillColor != COLOR_SOLID_BLACK);

  return new Cea708Cue(cueString, alignment, line, Cue.LINE_TYPE_FRACTION, verticalAnchorType,
      position, horizontalAnchorType, Cue.DIMEN_UNSET, windowColorSet, windowFillColor,
      priority);
}
 
Example 16
Source File: Tx3gDecoder.java    From Telegram-FOSS with GNU General Public License v2.0 4 votes vote down vote up
@Override
protected Subtitle decode(byte[] bytes, int length, boolean reset)
    throws SubtitleDecoderException {
  parsableByteArray.reset(bytes, length);
  String cueTextString = readSubtitleText(parsableByteArray);
  if (cueTextString.isEmpty()) {
    return Tx3gSubtitle.EMPTY;
  }
  // Attach default styles.
  SpannableStringBuilder cueText = new SpannableStringBuilder(cueTextString);
  attachFontFace(cueText, defaultFontFace, DEFAULT_FONT_FACE, 0, cueText.length(),
      SPAN_PRIORITY_LOW);
  attachColor(cueText, defaultColorRgba, DEFAULT_COLOR, 0, cueText.length(),
      SPAN_PRIORITY_LOW);
  attachFontFamily(cueText, defaultFontFamily, DEFAULT_FONT_FAMILY, 0, cueText.length(),
      SPAN_PRIORITY_LOW);
  float verticalPlacement = defaultVerticalPlacement;
  // Find and attach additional styles.
  while (parsableByteArray.bytesLeft() >= SIZE_ATOM_HEADER) {
    int position = parsableByteArray.getPosition();
    int atomSize = parsableByteArray.readInt();
    int atomType = parsableByteArray.readInt();
    if (atomType == TYPE_STYL) {
      assertTrue(parsableByteArray.bytesLeft() >= SIZE_SHORT);
      int styleRecordCount = parsableByteArray.readUnsignedShort();
      for (int i = 0; i < styleRecordCount; i++) {
        applyStyleRecord(parsableByteArray, cueText);
      }
    } else if (atomType == TYPE_TBOX && customVerticalPlacement) {
      assertTrue(parsableByteArray.bytesLeft() >= SIZE_SHORT);
      int requestedVerticalPlacement = parsableByteArray.readUnsignedShort();
      verticalPlacement = (float) requestedVerticalPlacement / calculatedVideoTrackHeight;
      verticalPlacement = Util.constrainValue(verticalPlacement, 0.0f, 0.95f);
    }
    parsableByteArray.setPosition(position + atomSize);
  }
  return new Tx3gSubtitle(
      new Cue(
          cueText,
          /* textAlignment= */ null,
          verticalPlacement,
          Cue.LINE_TYPE_FRACTION,
          Cue.ANCHOR_TYPE_START,
          Cue.DIMEN_UNSET,
          Cue.TYPE_UNSET,
          Cue.DIMEN_UNSET));
}
 
Example 17
Source File: Cea708Decoder.java    From K-Sonic with MIT License 4 votes vote down vote up
public Cea708Cue build() {
  if (isEmpty()) {
    // The cue is empty.
    return null;
  }

  SpannableStringBuilder cueString = new SpannableStringBuilder();

  // Add any rolled up captions, separated by new lines.
  for (int i = 0; i < rolledUpCaptions.size(); i++) {
    cueString.append(rolledUpCaptions.get(i));
    cueString.append('\n');
  }
  // Add the current line.
  cueString.append(buildSpannableString());

  // TODO: Add support for right-to-left languages (i.e. where right would correspond to normal
  // alignment).
  Alignment alignment;
  switch (justification) {
    case JUSTIFICATION_FULL:
      // TODO: Add support for full justification.
    case JUSTIFICATION_LEFT:
      alignment = Alignment.ALIGN_NORMAL;
      break;
    case JUSTIFICATION_RIGHT:
      alignment = Alignment.ALIGN_OPPOSITE;
      break;
    case JUSTIFICATION_CENTER:
      alignment = Alignment.ALIGN_CENTER;
      break;
    default:
      throw new IllegalArgumentException("Unexpected justification value: " + justification);
  }

  float position;
  float line;
  if (relativePositioning) {
    position = (float) horizontalAnchor / RELATIVE_CUE_SIZE;
    line = (float) verticalAnchor / RELATIVE_CUE_SIZE;
  } else {
    position = (float) horizontalAnchor / HORIZONTAL_SIZE;
    line = (float) verticalAnchor / VERTICAL_SIZE;
  }
  // Apply screen-edge padding to the line and position.
  position = (position * 0.9f) + 0.05f;
  line = (line * 0.9f) + 0.05f;

  // anchorId specifies where the anchor should be placed on the caption cue/window. The 9
  // possible configurations are as follows:
  //   0-----1-----2
  //   |           |
  //   3     4     5
  //   |           |
  //   6-----7-----8
  @AnchorType int verticalAnchorType;
  if (anchorId % 3 == 0) {
    verticalAnchorType = Cue.ANCHOR_TYPE_START;
  } else if (anchorId % 3 == 1) {
    verticalAnchorType = Cue.ANCHOR_TYPE_MIDDLE;
  } else {
    verticalAnchorType = Cue.ANCHOR_TYPE_END;
  }
  // TODO: Add support for right-to-left languages (i.e. where start is on the right).
  @AnchorType int horizontalAnchorType;
  if (anchorId / 3 == 0) {
    horizontalAnchorType = Cue.ANCHOR_TYPE_START;
  } else if (anchorId / 3 == 1) {
    horizontalAnchorType = Cue.ANCHOR_TYPE_MIDDLE;
  } else {
    horizontalAnchorType = Cue.ANCHOR_TYPE_END;
  }

  boolean windowColorSet = (windowFillColor != COLOR_SOLID_BLACK);

  return new Cea708Cue(cueString, alignment, line, Cue.LINE_TYPE_FRACTION, verticalAnchorType,
      position, horizontalAnchorType, Cue.DIMEN_UNSET, windowColorSet, windowFillColor,
      priority);
}
 
Example 18
Source File: Cea708Decoder.java    From Telegram with GNU General Public License v2.0 4 votes vote down vote up
public Cea708Cue build() {
  if (isEmpty()) {
    // The cue is empty.
    return null;
  }

  SpannableStringBuilder cueString = new SpannableStringBuilder();

  // Add any rolled up captions, separated by new lines.
  for (int i = 0; i < rolledUpCaptions.size(); i++) {
    cueString.append(rolledUpCaptions.get(i));
    cueString.append('\n');
  }
  // Add the current line.
  cueString.append(buildSpannableString());

  // TODO: Add support for right-to-left languages (i.e. where right would correspond to normal
  // alignment).
  Alignment alignment;
  switch (justification) {
    case JUSTIFICATION_FULL:
      // TODO: Add support for full justification.
    case JUSTIFICATION_LEFT:
      alignment = Alignment.ALIGN_NORMAL;
      break;
    case JUSTIFICATION_RIGHT:
      alignment = Alignment.ALIGN_OPPOSITE;
      break;
    case JUSTIFICATION_CENTER:
      alignment = Alignment.ALIGN_CENTER;
      break;
    default:
      throw new IllegalArgumentException("Unexpected justification value: " + justification);
  }

  float position;
  float line;
  if (relativePositioning) {
    position = (float) horizontalAnchor / RELATIVE_CUE_SIZE;
    line = (float) verticalAnchor / RELATIVE_CUE_SIZE;
  } else {
    position = (float) horizontalAnchor / HORIZONTAL_SIZE;
    line = (float) verticalAnchor / VERTICAL_SIZE;
  }
  // Apply screen-edge padding to the line and position.
  position = (position * 0.9f) + 0.05f;
  line = (line * 0.9f) + 0.05f;

  // anchorId specifies where the anchor should be placed on the caption cue/window. The 9
  // possible configurations are as follows:
  //   0-----1-----2
  //   |           |
  //   3     4     5
  //   |           |
  //   6-----7-----8
  @AnchorType int verticalAnchorType;
  if (anchorId % 3 == 0) {
    verticalAnchorType = Cue.ANCHOR_TYPE_START;
  } else if (anchorId % 3 == 1) {
    verticalAnchorType = Cue.ANCHOR_TYPE_MIDDLE;
  } else {
    verticalAnchorType = Cue.ANCHOR_TYPE_END;
  }
  // TODO: Add support for right-to-left languages (i.e. where start is on the right).
  @AnchorType int horizontalAnchorType;
  if (anchorId / 3 == 0) {
    horizontalAnchorType = Cue.ANCHOR_TYPE_START;
  } else if (anchorId / 3 == 1) {
    horizontalAnchorType = Cue.ANCHOR_TYPE_MIDDLE;
  } else {
    horizontalAnchorType = Cue.ANCHOR_TYPE_END;
  }

  boolean windowColorSet = (windowFillColor != COLOR_SOLID_BLACK);

  return new Cea708Cue(cueString, alignment, line, Cue.LINE_TYPE_FRACTION, verticalAnchorType,
      position, horizontalAnchorType, Cue.DIMEN_UNSET, windowColorSet, windowFillColor,
      priority);
}
 
Example 19
Source File: Cea708Decoder.java    From Telegram-FOSS with GNU General Public License v2.0 4 votes vote down vote up
public Cea708Cue build() {
  if (isEmpty()) {
    // The cue is empty.
    return null;
  }

  SpannableStringBuilder cueString = new SpannableStringBuilder();

  // Add any rolled up captions, separated by new lines.
  for (int i = 0; i < rolledUpCaptions.size(); i++) {
    cueString.append(rolledUpCaptions.get(i));
    cueString.append('\n');
  }
  // Add the current line.
  cueString.append(buildSpannableString());

  // TODO: Add support for right-to-left languages (i.e. where right would correspond to normal
  // alignment).
  Alignment alignment;
  switch (justification) {
    case JUSTIFICATION_FULL:
      // TODO: Add support for full justification.
    case JUSTIFICATION_LEFT:
      alignment = Alignment.ALIGN_NORMAL;
      break;
    case JUSTIFICATION_RIGHT:
      alignment = Alignment.ALIGN_OPPOSITE;
      break;
    case JUSTIFICATION_CENTER:
      alignment = Alignment.ALIGN_CENTER;
      break;
    default:
      throw new IllegalArgumentException("Unexpected justification value: " + justification);
  }

  float position;
  float line;
  if (relativePositioning) {
    position = (float) horizontalAnchor / RELATIVE_CUE_SIZE;
    line = (float) verticalAnchor / RELATIVE_CUE_SIZE;
  } else {
    position = (float) horizontalAnchor / HORIZONTAL_SIZE;
    line = (float) verticalAnchor / VERTICAL_SIZE;
  }
  // Apply screen-edge padding to the line and position.
  position = (position * 0.9f) + 0.05f;
  line = (line * 0.9f) + 0.05f;

  // anchorId specifies where the anchor should be placed on the caption cue/window. The 9
  // possible configurations are as follows:
  //   0-----1-----2
  //   |           |
  //   3     4     5
  //   |           |
  //   6-----7-----8
  @AnchorType int verticalAnchorType;
  if (anchorId % 3 == 0) {
    verticalAnchorType = Cue.ANCHOR_TYPE_START;
  } else if (anchorId % 3 == 1) {
    verticalAnchorType = Cue.ANCHOR_TYPE_MIDDLE;
  } else {
    verticalAnchorType = Cue.ANCHOR_TYPE_END;
  }
  // TODO: Add support for right-to-left languages (i.e. where start is on the right).
  @AnchorType int horizontalAnchorType;
  if (anchorId / 3 == 0) {
    horizontalAnchorType = Cue.ANCHOR_TYPE_START;
  } else if (anchorId / 3 == 1) {
    horizontalAnchorType = Cue.ANCHOR_TYPE_MIDDLE;
  } else {
    horizontalAnchorType = Cue.ANCHOR_TYPE_END;
  }

  boolean windowColorSet = (windowFillColor != COLOR_SOLID_BLACK);

  return new Cea708Cue(cueString, alignment, line, Cue.LINE_TYPE_FRACTION, verticalAnchorType,
      position, horizontalAnchorType, Cue.DIMEN_UNSET, windowColorSet, windowFillColor,
      priority);
}
 
Example 20
Source File: Tx3gDecoder.java    From Telegram with GNU General Public License v2.0 4 votes vote down vote up
@Override
protected Subtitle decode(byte[] bytes, int length, boolean reset)
    throws SubtitleDecoderException {
  parsableByteArray.reset(bytes, length);
  String cueTextString = readSubtitleText(parsableByteArray);
  if (cueTextString.isEmpty()) {
    return Tx3gSubtitle.EMPTY;
  }
  // Attach default styles.
  SpannableStringBuilder cueText = new SpannableStringBuilder(cueTextString);
  attachFontFace(cueText, defaultFontFace, DEFAULT_FONT_FACE, 0, cueText.length(),
      SPAN_PRIORITY_LOW);
  attachColor(cueText, defaultColorRgba, DEFAULT_COLOR, 0, cueText.length(),
      SPAN_PRIORITY_LOW);
  attachFontFamily(cueText, defaultFontFamily, DEFAULT_FONT_FAMILY, 0, cueText.length(),
      SPAN_PRIORITY_LOW);
  float verticalPlacement = defaultVerticalPlacement;
  // Find and attach additional styles.
  while (parsableByteArray.bytesLeft() >= SIZE_ATOM_HEADER) {
    int position = parsableByteArray.getPosition();
    int atomSize = parsableByteArray.readInt();
    int atomType = parsableByteArray.readInt();
    if (atomType == TYPE_STYL) {
      assertTrue(parsableByteArray.bytesLeft() >= SIZE_SHORT);
      int styleRecordCount = parsableByteArray.readUnsignedShort();
      for (int i = 0; i < styleRecordCount; i++) {
        applyStyleRecord(parsableByteArray, cueText);
      }
    } else if (atomType == TYPE_TBOX && customVerticalPlacement) {
      assertTrue(parsableByteArray.bytesLeft() >= SIZE_SHORT);
      int requestedVerticalPlacement = parsableByteArray.readUnsignedShort();
      verticalPlacement = (float) requestedVerticalPlacement / calculatedVideoTrackHeight;
      verticalPlacement = Util.constrainValue(verticalPlacement, 0.0f, 0.95f);
    }
    parsableByteArray.setPosition(position + atomSize);
  }
  return new Tx3gSubtitle(
      new Cue(
          cueText,
          /* textAlignment= */ null,
          verticalPlacement,
          Cue.LINE_TYPE_FRACTION,
          Cue.ANCHOR_TYPE_START,
          Cue.DIMEN_UNSET,
          Cue.TYPE_UNSET,
          Cue.DIMEN_UNSET));
}