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;
|
package com.google.android.exoplayer2.text;
|
||||||
|
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
|
import android.graphics.Bitmap;
|
||||||
import android.support.annotation.IntDef;
|
import android.support.annotation.IntDef;
|
||||||
import android.text.Layout.Alignment;
|
import android.text.Layout.Alignment;
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
@ -78,7 +79,8 @@ public class Cue {
|
|||||||
public static final int LINE_TYPE_NUMBER = 1;
|
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;
|
public final CharSequence text;
|
||||||
|
|
||||||
@ -87,6 +89,11 @@ public class Cue {
|
|||||||
*/
|
*/
|
||||||
public final Alignment textAlignment;
|
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
|
* 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
|
* 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
|
* 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.
|
* fractional vertical position relative to the top of the viewport.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public final float line;
|
public final float line;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The type of the {@link #line} value.
|
* The type of the {@link #line} value.
|
||||||
* <p>
|
* <p>
|
||||||
@ -122,9 +129,8 @@ public class Cue {
|
|||||||
* {@code (line == -2 && lineAnchor == ANCHOR_TYPE_START)} position a cue so that only its first
|
* {@code (line == -2 && lineAnchor == ANCHOR_TYPE_START)} position a cue so that only its first
|
||||||
* line is visible at the bottom of the viewport.
|
* 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},
|
* 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}.
|
* {@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
|
* and {@link #ANCHOR_TYPE_END} correspond to the top, middle and bottom of the cue box
|
||||||
* respectively.
|
* 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 fractional position of the {@link #positionAnchor} of the cue box within the viewport in
|
||||||
* the direction orthogonal to {@link #line}, or {@link #DIMEN_UNSET}.
|
* 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
|
* and {@link #ANCHOR_TYPE_END} correspond to the left, middle and right of the cue box
|
||||||
* respectively.
|
* respectively.
|
||||||
*/
|
*/
|
||||||
@AnchorType
|
@AnchorType public final int positionAnchor;
|
||||||
public final int positionAnchor;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The size of the cue box in the writing direction specified as a fraction of the viewport size
|
* 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;
|
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}.
|
* {@link #TYPE_UNSET} and whose dimension parameters are set to {@link #DIMEN_UNSET}.
|
||||||
*
|
*
|
||||||
* @param text See {@link #text}.
|
* @param text See {@link #text}.
|
||||||
@ -184,6 +217,8 @@ public class Cue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Creates a text cue.
|
||||||
|
*
|
||||||
* @param text See {@link #text}.
|
* @param text See {@link #text}.
|
||||||
* @param textAlignment See {@link #textAlignment}.
|
* @param textAlignment See {@link #textAlignment}.
|
||||||
* @param line See {@link #line}.
|
* @param line See {@link #line}.
|
||||||
@ -200,6 +235,8 @@ public class Cue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Creates a text cue.
|
||||||
|
*
|
||||||
* @param text See {@link #text}.
|
* @param text See {@link #text}.
|
||||||
* @param textAlignment See {@link #textAlignment}.
|
* @param textAlignment See {@link #textAlignment}.
|
||||||
* @param line See {@link #line}.
|
* @param line See {@link #line}.
|
||||||
@ -214,8 +251,16 @@ public class Cue {
|
|||||||
public Cue(CharSequence text, Alignment textAlignment, float line, @LineType int lineType,
|
public Cue(CharSequence text, Alignment textAlignment, float line, @LineType int lineType,
|
||||||
@AnchorType int lineAnchor, float position, @AnchorType int positionAnchor, float size,
|
@AnchorType int lineAnchor, float position, @AnchorType int positionAnchor, float size,
|
||||||
boolean windowColorSet, int windowColor) {
|
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.text = text;
|
||||||
this.textAlignment = textAlignment;
|
this.textAlignment = textAlignment;
|
||||||
|
this.bitmap = bitmap;
|
||||||
this.line = line;
|
this.line = line;
|
||||||
this.lineType = lineType;
|
this.lineType = lineType;
|
||||||
this.lineAnchor = lineAnchor;
|
this.lineAnchor = lineAnchor;
|
||||||
|
@ -18,11 +18,13 @@ package com.google.android.exoplayer2.ui;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
import android.content.res.TypedArray;
|
import android.content.res.TypedArray;
|
||||||
|
import android.graphics.Bitmap;
|
||||||
import android.graphics.Canvas;
|
import android.graphics.Canvas;
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.graphics.Paint;
|
import android.graphics.Paint;
|
||||||
import android.graphics.Paint.Join;
|
import android.graphics.Paint.Join;
|
||||||
import android.graphics.Paint.Style;
|
import android.graphics.Paint.Style;
|
||||||
|
import android.graphics.Rect;
|
||||||
import android.graphics.RectF;
|
import android.graphics.RectF;
|
||||||
import android.text.Layout.Alignment;
|
import android.text.Layout.Alignment;
|
||||||
import android.text.StaticLayout;
|
import android.text.StaticLayout;
|
||||||
@ -63,6 +65,7 @@ import com.google.android.exoplayer2.util.Util;
|
|||||||
private final Paint paint;
|
private final Paint paint;
|
||||||
|
|
||||||
// Previous input variables.
|
// Previous input variables.
|
||||||
|
private Bitmap cueBitmap;
|
||||||
private CharSequence cueText;
|
private CharSequence cueText;
|
||||||
private Alignment cueTextAlignment;
|
private Alignment cueTextAlignment;
|
||||||
private float cueLine;
|
private float cueLine;
|
||||||
@ -93,6 +96,7 @@ import com.google.android.exoplayer2.util.Util;
|
|||||||
private int textLeft;
|
private int textLeft;
|
||||||
private int textTop;
|
private int textTop;
|
||||||
private int textPaddingX;
|
private int textPaddingX;
|
||||||
|
private Rect bitmapRect;
|
||||||
|
|
||||||
@SuppressWarnings("ResourceType")
|
@SuppressWarnings("ResourceType")
|
||||||
public SubtitlePainter(Context context) {
|
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,
|
public void draw(Cue cue, boolean applyEmbeddedStyles, CaptionStyleCompat style, float textSizePx,
|
||||||
float bottomPaddingFraction, Canvas canvas, int cueBoxLeft, int cueBoxTop, int cueBoxRight,
|
float bottomPaddingFraction, Canvas canvas, int cueBoxLeft, int cueBoxTop, int cueBoxRight,
|
||||||
int cueBoxBottom) {
|
int cueBoxBottom) {
|
||||||
CharSequence cueText = cue.text;
|
boolean isTextCue = cue.bitmap == null;
|
||||||
|
CharSequence cueText = null;
|
||||||
|
Bitmap cueBitmap = null;
|
||||||
|
if (isTextCue) {
|
||||||
|
cueText = cue.text;
|
||||||
if (TextUtils.isEmpty(cueText)) {
|
if (TextUtils.isEmpty(cueText)) {
|
||||||
// Nothing to draw.
|
// Nothing to draw.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int windowColor = cue.windowColorSet ? cue.windowColor : style.windowColor;
|
|
||||||
|
|
||||||
if (!applyEmbeddedStyles) {
|
if (!applyEmbeddedStyles) {
|
||||||
// Strip out any embedded styling.
|
// Strip out any embedded styling.
|
||||||
cueText = cueText.toString();
|
cueText = cueText.toString();
|
||||||
windowColor = style.windowColor;
|
}
|
||||||
|
} else {
|
||||||
|
cueBitmap = cue.bitmap;
|
||||||
}
|
}
|
||||||
if (areCharSequencesEqual(this.cueText, cueText)
|
if (areCharSequencesEqual(this.cueText, cueText)
|
||||||
&& Util.areEqual(this.cueTextAlignment, cue.textAlignment)
|
&& Util.areEqual(this.cueTextAlignment, cue.textAlignment)
|
||||||
|
&& this.cueBitmap == cueBitmap
|
||||||
&& this.cueLine == cue.line
|
&& this.cueLine == cue.line
|
||||||
&& this.cueLineType == cue.lineType
|
&& this.cueLineType == cue.lineType
|
||||||
&& Util.areEqual(this.cueLineAnchor, cue.lineAnchor)
|
&& Util.areEqual(this.cueLineAnchor, cue.lineAnchor)
|
||||||
@ -165,7 +173,7 @@ import com.google.android.exoplayer2.util.Util;
|
|||||||
&& this.applyEmbeddedStyles == applyEmbeddedStyles
|
&& this.applyEmbeddedStyles == applyEmbeddedStyles
|
||||||
&& this.foregroundColor == style.foregroundColor
|
&& this.foregroundColor == style.foregroundColor
|
||||||
&& this.backgroundColor == style.backgroundColor
|
&& this.backgroundColor == style.backgroundColor
|
||||||
&& this.windowColor == windowColor
|
&& this.windowColor == style.windowColor
|
||||||
&& this.edgeType == style.edgeType
|
&& this.edgeType == style.edgeType
|
||||||
&& this.edgeColor == style.edgeColor
|
&& this.edgeColor == style.edgeColor
|
||||||
&& Util.areEqual(this.textPaint.getTypeface(), style.typeface)
|
&& Util.areEqual(this.textPaint.getTypeface(), style.typeface)
|
||||||
@ -176,12 +184,13 @@ import com.google.android.exoplayer2.util.Util;
|
|||||||
&& this.parentRight == cueBoxRight
|
&& this.parentRight == cueBoxRight
|
||||||
&& this.parentBottom == cueBoxBottom) {
|
&& this.parentBottom == cueBoxBottom) {
|
||||||
// We can use the cached layout.
|
// We can use the cached layout.
|
||||||
drawLayout(canvas);
|
drawLayout(canvas, isTextCue);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.cueText = cueText;
|
this.cueText = cueText;
|
||||||
this.cueTextAlignment = cue.textAlignment;
|
this.cueTextAlignment = cue.textAlignment;
|
||||||
|
this.cueBitmap = cue.bitmap;
|
||||||
this.cueLine = cue.line;
|
this.cueLine = cue.line;
|
||||||
this.cueLineType = cue.lineType;
|
this.cueLineType = cue.lineType;
|
||||||
this.cueLineAnchor = cue.lineAnchor;
|
this.cueLineAnchor = cue.lineAnchor;
|
||||||
@ -191,7 +200,7 @@ import com.google.android.exoplayer2.util.Util;
|
|||||||
this.applyEmbeddedStyles = applyEmbeddedStyles;
|
this.applyEmbeddedStyles = applyEmbeddedStyles;
|
||||||
this.foregroundColor = style.foregroundColor;
|
this.foregroundColor = style.foregroundColor;
|
||||||
this.backgroundColor = style.backgroundColor;
|
this.backgroundColor = style.backgroundColor;
|
||||||
this.windowColor = windowColor;
|
this.windowColor = style.windowColor;
|
||||||
this.edgeType = style.edgeType;
|
this.edgeType = style.edgeType;
|
||||||
this.edgeColor = style.edgeColor;
|
this.edgeColor = style.edgeColor;
|
||||||
this.textPaint.setTypeface(style.typeface);
|
this.textPaint.setTypeface(style.typeface);
|
||||||
@ -202,6 +211,15 @@ import com.google.android.exoplayer2.util.Util;
|
|||||||
this.parentRight = cueBoxRight;
|
this.parentRight = cueBoxRight;
|
||||||
this.parentBottom = cueBoxBottom;
|
this.parentBottom = cueBoxBottom;
|
||||||
|
|
||||||
|
if (isTextCue) {
|
||||||
|
setupTextLayout();
|
||||||
|
} else {
|
||||||
|
setupBitmapLayout();
|
||||||
|
}
|
||||||
|
drawLayout(canvas, isTextCue);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setupTextLayout() {
|
||||||
int parentWidth = parentRight - parentLeft;
|
int parentWidth = parentRight - parentLeft;
|
||||||
int parentHeight = parentBottom - parentTop;
|
int parentHeight = parentBottom - parentTop;
|
||||||
|
|
||||||
@ -256,7 +274,7 @@ import com.google.android.exoplayer2.util.Util;
|
|||||||
if (cueLine >= 0) {
|
if (cueLine >= 0) {
|
||||||
anchorPosition = Math.round(cueLine * firstLineHeight) + parentTop;
|
anchorPosition = Math.round(cueLine * firstLineHeight) + parentTop;
|
||||||
} else {
|
} else {
|
||||||
anchorPosition = Math.round((cueLine + 1) * firstLineHeight) + parentBottom;
|
anchorPosition = Math.round(cueLine * firstLineHeight) + parentBottom;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
textTop = cueLineAnchor == Cue.ANCHOR_TYPE_END ? anchorPosition - textHeight
|
textTop = cueLineAnchor == Cue.ANCHOR_TYPE_END ? anchorPosition - textHeight
|
||||||
@ -279,16 +297,31 @@ import com.google.android.exoplayer2.util.Util;
|
|||||||
this.textLeft = textLeft;
|
this.textLeft = textLeft;
|
||||||
this.textTop = textTop;
|
this.textTop = textTop;
|
||||||
this.textPaddingX = textPaddingX;
|
this.textPaddingX = textPaddingX;
|
||||||
|
|
||||||
drawLayout(canvas);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private void setupBitmapLayout() {
|
||||||
* Draws {@link #textLayout} into the provided canvas.
|
int parentWidth = parentRight - parentLeft;
|
||||||
*
|
int parentHeight = parentBottom - parentTop;
|
||||||
* @param canvas The canvas into which to draw.
|
float anchorX = parentLeft + (parentWidth * cuePosition);
|
||||||
*/
|
float anchorY = parentTop + (parentHeight * cueLine);
|
||||||
private void drawLayout(Canvas canvas) {
|
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;
|
final StaticLayout layout = textLayout;
|
||||||
if (layout == null) {
|
if (layout == null) {
|
||||||
// Nothing to draw.
|
// Nothing to draw.
|
||||||
@ -347,6 +380,10 @@ import com.google.android.exoplayer2.util.Util;
|
|||||||
canvas.restoreToCount(saveCount);
|
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
|
* 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
|
* 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