Merge branch 'drhill-dev-v2_imagesubs' into dev-v2
This commit is contained in:
commit
276788bc50
@ -16,6 +16,7 @@
|
||||
package com.google.android.exoplayer2.text;
|
||||
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Bitmap;
|
||||
import android.support.annotation.IntDef;
|
||||
import android.text.Layout.Alignment;
|
||||
import java.lang.annotation.Retention;
|
||||
@ -78,7 +79,8 @@ public class Cue {
|
||||
public static final int LINE_TYPE_NUMBER = 1;
|
||||
|
||||
/**
|
||||
* The cue text. Note the {@link CharSequence} may be decorated with styling spans.
|
||||
* The cue text, or null if this is an image cue. Note the {@link CharSequence} may be decorated
|
||||
* with styling spans.
|
||||
*/
|
||||
public final CharSequence text;
|
||||
|
||||
@ -87,6 +89,11 @@ public class Cue {
|
||||
*/
|
||||
public final Alignment textAlignment;
|
||||
|
||||
/**
|
||||
* The cue image, or null if this is a text cue.
|
||||
*/
|
||||
public final Bitmap bitmap;
|
||||
|
||||
/**
|
||||
* The position of the {@link #lineAnchor} of the cue box within the viewport in the direction
|
||||
* orthogonal to the writing direction, or {@link #DIMEN_UNSET}. When set, the interpretation of
|
||||
@ -95,8 +102,8 @@ public class Cue {
|
||||
* For horizontal text and {@link #lineType} equal to {@link #LINE_TYPE_FRACTION}, this is the
|
||||
* fractional vertical position relative to the top of the viewport.
|
||||
*/
|
||||
|
||||
public final float line;
|
||||
|
||||
/**
|
||||
* The type of the {@link #line} value.
|
||||
* <p>
|
||||
@ -122,9 +129,8 @@ public class Cue {
|
||||
* {@code (line == -2 && lineAnchor == ANCHOR_TYPE_START)} position a cue so that only its first
|
||||
* line is visible at the bottom of the viewport.
|
||||
*/
|
||||
@LineType public final int lineType;
|
||||
|
||||
@LineType
|
||||
public final int lineType;
|
||||
/**
|
||||
* The cue box anchor positioned by {@link #line}. One of {@link #ANCHOR_TYPE_START},
|
||||
* {@link #ANCHOR_TYPE_MIDDLE}, {@link #ANCHOR_TYPE_END} and {@link #TYPE_UNSET}.
|
||||
@ -133,9 +139,8 @@ public class Cue {
|
||||
* and {@link #ANCHOR_TYPE_END} correspond to the top, middle and bottom of the cue box
|
||||
* respectively.
|
||||
*/
|
||||
@AnchorType public final int lineAnchor;
|
||||
|
||||
@AnchorType
|
||||
public final 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}.
|
||||
@ -154,8 +159,7 @@ public class Cue {
|
||||
* and {@link #ANCHOR_TYPE_END} correspond to the left, middle and right of the cue box
|
||||
* respectively.
|
||||
*/
|
||||
@AnchorType
|
||||
public final int positionAnchor;
|
||||
@AnchorType public final int positionAnchor;
|
||||
|
||||
/**
|
||||
* The size of the cue box in the writing direction specified as a fraction of the viewport size
|
||||
@ -174,7 +178,36 @@ public class Cue {
|
||||
public final int windowColor;
|
||||
|
||||
/**
|
||||
* Constructs a cue whose {@link #textAlignment} is null, whose type parameters are set to
|
||||
* Constructs an image cue whose type parameters are set to {@link #TYPE_UNSET} and whose
|
||||
* dimension parameters are set to {@link #DIMEN_UNSET}.
|
||||
*
|
||||
* @param bitmap See {@link #bitmap}.
|
||||
*/
|
||||
public Cue(Bitmap bitmap) {
|
||||
this(bitmap, DIMEN_UNSET, TYPE_UNSET, DIMEN_UNSET, TYPE_UNSET, DIMEN_UNSET);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an image cue.
|
||||
*
|
||||
* @param horizontalPosition The position of the horizontal anchor within the viewport, expressed
|
||||
* as a fraction of the viewport width.
|
||||
* @param horizontalPositionAnchor The horizontal anchor. One of {@link #ANCHOR_TYPE_START},
|
||||
* {@link #ANCHOR_TYPE_MIDDLE}, {@link #ANCHOR_TYPE_END} and {@link #TYPE_UNSET}.
|
||||
* @param verticalPosition The position of the vertical anchor within the viewport, expressed as a
|
||||
* fraction of the viewport height.
|
||||
* @param verticalPositionAnchor The vertical anchor. One of {@link #ANCHOR_TYPE_START},
|
||||
* {@link #ANCHOR_TYPE_MIDDLE}, {@link #ANCHOR_TYPE_END} and {@link #TYPE_UNSET}.
|
||||
* @param width The width of the cue, expressed as a fraction of the viewport width.
|
||||
*/
|
||||
public Cue(Bitmap bitmap, float horizontalPosition, @AnchorType int horizontalPositionAnchor,
|
||||
float verticalPosition, @AnchorType int verticalPositionAnchor, float width) {
|
||||
this(null, null, bitmap, verticalPosition, LINE_TYPE_FRACTION, verticalPositionAnchor,
|
||||
horizontalPosition, horizontalPositionAnchor, width, false, Color.BLACK);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs 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}.
|
||||
@ -184,6 +217,8 @@ public class Cue {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a text cue.
|
||||
*
|
||||
* @param text See {@link #text}.
|
||||
* @param textAlignment See {@link #textAlignment}.
|
||||
* @param line See {@link #line}.
|
||||
@ -200,6 +235,8 @@ public class Cue {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a text cue.
|
||||
*
|
||||
* @param text See {@link #text}.
|
||||
* @param textAlignment See {@link #textAlignment}.
|
||||
* @param line See {@link #line}.
|
||||
@ -214,8 +251,16 @@ public class Cue {
|
||||
public Cue(CharSequence text, Alignment textAlignment, float line, @LineType int lineType,
|
||||
@AnchorType int lineAnchor, float position, @AnchorType int positionAnchor, float size,
|
||||
boolean windowColorSet, int windowColor) {
|
||||
this(text, textAlignment, null, line, lineType, lineAnchor, position, positionAnchor, size,
|
||||
windowColorSet, windowColor);
|
||||
}
|
||||
|
||||
private Cue(CharSequence text, Alignment textAlignment, Bitmap bitmap, float line,
|
||||
@LineType int lineType, @AnchorType int lineAnchor, float position,
|
||||
@AnchorType int positionAnchor, float size, boolean windowColorSet, int windowColor) {
|
||||
this.text = text;
|
||||
this.textAlignment = textAlignment;
|
||||
this.bitmap = bitmap;
|
||||
this.line = line;
|
||||
this.lineType = lineType;
|
||||
this.lineAnchor = lineAnchor;
|
||||
|
@ -18,11 +18,13 @@ package com.google.android.exoplayer2.ui;
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Paint.Join;
|
||||
import android.graphics.Paint.Style;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.text.Layout.Alignment;
|
||||
import android.text.StaticLayout;
|
||||
@ -63,6 +65,7 @@ import com.google.android.exoplayer2.util.Util;
|
||||
private final Paint paint;
|
||||
|
||||
// Previous input variables.
|
||||
private Bitmap cueBitmap;
|
||||
private CharSequence cueText;
|
||||
private Alignment cueTextAlignment;
|
||||
private float cueLine;
|
||||
@ -93,6 +96,7 @@ import com.google.android.exoplayer2.util.Util;
|
||||
private int textLeft;
|
||||
private int textTop;
|
||||
private int textPaddingX;
|
||||
private Rect bitmapRect;
|
||||
|
||||
@SuppressWarnings("ResourceType")
|
||||
public SubtitlePainter(Context context) {
|
||||
@ -141,21 +145,25 @@ import com.google.android.exoplayer2.util.Util;
|
||||
public void draw(Cue cue, boolean applyEmbeddedStyles, CaptionStyleCompat style, float textSizePx,
|
||||
float bottomPaddingFraction, Canvas canvas, int cueBoxLeft, int cueBoxTop, int cueBoxRight,
|
||||
int cueBoxBottom) {
|
||||
CharSequence cueText = cue.text;
|
||||
if (TextUtils.isEmpty(cueText)) {
|
||||
// Nothing to draw.
|
||||
return;
|
||||
}
|
||||
|
||||
int windowColor = cue.windowColorSet ? cue.windowColor : style.windowColor;
|
||||
|
||||
if (!applyEmbeddedStyles) {
|
||||
// Strip out any embedded styling.
|
||||
cueText = cueText.toString();
|
||||
windowColor = style.windowColor;
|
||||
boolean isTextCue = cue.bitmap == null;
|
||||
CharSequence cueText = null;
|
||||
Bitmap cueBitmap = null;
|
||||
if (isTextCue) {
|
||||
cueText = cue.text;
|
||||
if (TextUtils.isEmpty(cueText)) {
|
||||
// Nothing to draw.
|
||||
return;
|
||||
}
|
||||
if (!applyEmbeddedStyles) {
|
||||
// Strip out any embedded styling.
|
||||
cueText = cueText.toString();
|
||||
}
|
||||
} else {
|
||||
cueBitmap = cue.bitmap;
|
||||
}
|
||||
if (areCharSequencesEqual(this.cueText, cueText)
|
||||
&& Util.areEqual(this.cueTextAlignment, cue.textAlignment)
|
||||
&& this.cueBitmap == cueBitmap
|
||||
&& this.cueLine == cue.line
|
||||
&& this.cueLineType == cue.lineType
|
||||
&& Util.areEqual(this.cueLineAnchor, cue.lineAnchor)
|
||||
@ -165,7 +173,7 @@ import com.google.android.exoplayer2.util.Util;
|
||||
&& this.applyEmbeddedStyles == applyEmbeddedStyles
|
||||
&& this.foregroundColor == style.foregroundColor
|
||||
&& this.backgroundColor == style.backgroundColor
|
||||
&& this.windowColor == windowColor
|
||||
&& this.windowColor == style.windowColor
|
||||
&& this.edgeType == style.edgeType
|
||||
&& this.edgeColor == style.edgeColor
|
||||
&& Util.areEqual(this.textPaint.getTypeface(), style.typeface)
|
||||
@ -176,12 +184,13 @@ import com.google.android.exoplayer2.util.Util;
|
||||
&& this.parentRight == cueBoxRight
|
||||
&& this.parentBottom == cueBoxBottom) {
|
||||
// We can use the cached layout.
|
||||
drawLayout(canvas);
|
||||
drawLayout(canvas, isTextCue);
|
||||
return;
|
||||
}
|
||||
|
||||
this.cueText = cueText;
|
||||
this.cueTextAlignment = cue.textAlignment;
|
||||
this.cueBitmap = cue.bitmap;
|
||||
this.cueLine = cue.line;
|
||||
this.cueLineType = cue.lineType;
|
||||
this.cueLineAnchor = cue.lineAnchor;
|
||||
@ -191,7 +200,7 @@ import com.google.android.exoplayer2.util.Util;
|
||||
this.applyEmbeddedStyles = applyEmbeddedStyles;
|
||||
this.foregroundColor = style.foregroundColor;
|
||||
this.backgroundColor = style.backgroundColor;
|
||||
this.windowColor = windowColor;
|
||||
this.windowColor = style.windowColor;
|
||||
this.edgeType = style.edgeType;
|
||||
this.edgeColor = style.edgeColor;
|
||||
this.textPaint.setTypeface(style.typeface);
|
||||
@ -202,6 +211,15 @@ import com.google.android.exoplayer2.util.Util;
|
||||
this.parentRight = cueBoxRight;
|
||||
this.parentBottom = cueBoxBottom;
|
||||
|
||||
if (isTextCue) {
|
||||
setupTextLayout();
|
||||
} else {
|
||||
setupBitmapLayout();
|
||||
}
|
||||
drawLayout(canvas, isTextCue);
|
||||
}
|
||||
|
||||
private void setupTextLayout() {
|
||||
int parentWidth = parentRight - parentLeft;
|
||||
int parentHeight = parentBottom - parentTop;
|
||||
|
||||
@ -237,7 +255,7 @@ import com.google.android.exoplayer2.util.Util;
|
||||
int anchorPosition = Math.round(parentWidth * cuePosition) + parentLeft;
|
||||
textLeft = cuePositionAnchor == Cue.ANCHOR_TYPE_END ? anchorPosition - textWidth
|
||||
: cuePositionAnchor == Cue.ANCHOR_TYPE_MIDDLE ? (anchorPosition * 2 - textWidth) / 2
|
||||
: anchorPosition;
|
||||
: anchorPosition;
|
||||
textLeft = Math.max(textLeft, parentLeft);
|
||||
textRight = Math.min(textLeft + textWidth, parentRight);
|
||||
} else {
|
||||
@ -256,12 +274,12 @@ import com.google.android.exoplayer2.util.Util;
|
||||
if (cueLine >= 0) {
|
||||
anchorPosition = Math.round(cueLine * firstLineHeight) + parentTop;
|
||||
} else {
|
||||
anchorPosition = Math.round((cueLine + 1) * firstLineHeight) + parentBottom;
|
||||
anchorPosition = Math.round(cueLine * firstLineHeight) + parentBottom;
|
||||
}
|
||||
}
|
||||
textTop = cueLineAnchor == Cue.ANCHOR_TYPE_END ? anchorPosition - textHeight
|
||||
: cueLineAnchor == Cue.ANCHOR_TYPE_MIDDLE ? (anchorPosition * 2 - textHeight) / 2
|
||||
: anchorPosition;
|
||||
: anchorPosition;
|
||||
if (textTop + textHeight > parentBottom) {
|
||||
textTop = parentBottom - textHeight;
|
||||
} else if (textTop < parentTop) {
|
||||
@ -279,16 +297,31 @@ import com.google.android.exoplayer2.util.Util;
|
||||
this.textLeft = textLeft;
|
||||
this.textTop = textTop;
|
||||
this.textPaddingX = textPaddingX;
|
||||
|
||||
drawLayout(canvas);
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws {@link #textLayout} into the provided canvas.
|
||||
*
|
||||
* @param canvas The canvas into which to draw.
|
||||
*/
|
||||
private void drawLayout(Canvas canvas) {
|
||||
private void setupBitmapLayout() {
|
||||
int parentWidth = parentRight - parentLeft;
|
||||
int parentHeight = parentBottom - parentTop;
|
||||
float anchorX = parentLeft + (parentWidth * cuePosition);
|
||||
float anchorY = parentTop + (parentHeight * cueLine);
|
||||
int width = (int) (parentWidth * cueSize);
|
||||
int height = (int) (width * ((float) cueBitmap.getHeight() / cueBitmap.getWidth()));
|
||||
int x = (int) (cueLineAnchor == Cue.ANCHOR_TYPE_END ? (anchorX - width)
|
||||
: cueLineAnchor == Cue.ANCHOR_TYPE_MIDDLE ? (anchorX - (width / 2)) : anchorX);
|
||||
int y = (int) (cuePositionAnchor == Cue.ANCHOR_TYPE_END ? (anchorY - width)
|
||||
: cuePositionAnchor == Cue.ANCHOR_TYPE_MIDDLE ? (anchorY - (width / 2)) : anchorY);
|
||||
bitmapRect = new Rect(x, y, x + width, y + height);
|
||||
}
|
||||
|
||||
private void drawLayout(Canvas canvas, boolean isTextCue) {
|
||||
if (isTextCue) {
|
||||
drawTextLayout(canvas);
|
||||
} else {
|
||||
drawBitmapLayout(canvas);
|
||||
}
|
||||
}
|
||||
|
||||
private void drawTextLayout(Canvas canvas) {
|
||||
final StaticLayout layout = textLayout;
|
||||
if (layout == null) {
|
||||
// Nothing to draw.
|
||||
@ -347,6 +380,10 @@ import com.google.android.exoplayer2.util.Util;
|
||||
canvas.restoreToCount(saveCount);
|
||||
}
|
||||
|
||||
private void drawBitmapLayout(Canvas canvas) {
|
||||
canvas.drawBitmap(cueBitmap, null, bitmapRect, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is used instead of {@link TextUtils#equals(CharSequence, CharSequence)} because the
|
||||
* latter only checks the text of each sequence, and does not check for equality of styling that
|
||||
|
Loading…
x
Reference in New Issue
Block a user