Provide more flexibility for setting caption font size.
- Respect any padding set on SubtitleLayout. - Allow specification of absolute, fractional and fractional-ignoring-padding text sizes.
This commit is contained in:
parent
7f9b12982d
commit
8a723706d6
@ -562,17 +562,17 @@ public class PlayerActivity extends Activity implements SurfaceHolder.Callback,
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void configureSubtitleView() {
|
private void configureSubtitleView() {
|
||||||
CaptionStyleCompat captionStyle;
|
CaptionStyleCompat style;
|
||||||
float captionFontScale;
|
float fontScale;
|
||||||
if (Util.SDK_INT >= 19) {
|
if (Util.SDK_INT >= 19) {
|
||||||
captionStyle = getUserCaptionStyleV19();
|
style = getUserCaptionStyleV19();
|
||||||
captionFontScale = getUserCaptionFontScaleV19();
|
fontScale = getUserCaptionFontScaleV19();
|
||||||
} else {
|
} else {
|
||||||
captionStyle = CaptionStyleCompat.DEFAULT;
|
style = CaptionStyleCompat.DEFAULT;
|
||||||
captionFontScale = 1.0f;
|
fontScale = 1.0f;
|
||||||
}
|
}
|
||||||
subtitleLayout.setStyle(captionStyle);
|
subtitleLayout.setStyle(style);
|
||||||
subtitleLayout.setFontScale(captionFontScale);
|
subtitleLayout.setFractionalTextSize(SubtitleLayout.DEFAULT_TEXT_SIZE_FRACTION * fontScale);
|
||||||
}
|
}
|
||||||
|
|
||||||
@TargetApi(19)
|
@TargetApi(19)
|
||||||
|
@ -45,12 +45,6 @@ import android.util.Log;
|
|||||||
*/
|
*/
|
||||||
private static final float INNER_PADDING_RATIO = 0.125f;
|
private static final float INNER_PADDING_RATIO = 0.125f;
|
||||||
|
|
||||||
/**
|
|
||||||
* Use the same line height ratio as WebVtt to match the display with the preview.
|
|
||||||
* WebVtt specifies line height as 5.3% of the viewport height.
|
|
||||||
*/
|
|
||||||
private static final float LINE_HEIGHT_FRACTION = 0.0533f;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Temporary rectangle used for computing line bounds.
|
* Temporary rectangle used for computing line bounds.
|
||||||
*/
|
*/
|
||||||
@ -77,7 +71,7 @@ import android.util.Log;
|
|||||||
private int windowColor;
|
private int windowColor;
|
||||||
private int edgeColor;
|
private int edgeColor;
|
||||||
private int edgeType;
|
private int edgeType;
|
||||||
private float fontScale;
|
private float textSizePx;
|
||||||
private float bottomPaddingFraction;
|
private float bottomPaddingFraction;
|
||||||
private int parentLeft;
|
private int parentLeft;
|
||||||
private int parentTop;
|
private int parentTop;
|
||||||
@ -124,7 +118,7 @@ import android.util.Log;
|
|||||||
* @param cue The cue to draw.
|
* @param cue The cue to draw.
|
||||||
* @param applyEmbeddedStyles Whether styling embedded within the cue should be applied.
|
* @param applyEmbeddedStyles Whether styling embedded within the cue should be applied.
|
||||||
* @param style The style to use when drawing the cue text.
|
* @param style The style to use when drawing the cue text.
|
||||||
* @param fontScale The font scale.
|
* @param textSizePx The text size to use when drawing the cue text, in pixels.
|
||||||
* @param bottomPaddingFraction The bottom padding fraction to apply when {@link Cue#line} is
|
* @param bottomPaddingFraction The bottom padding fraction to apply when {@link Cue#line} is
|
||||||
* {@link Cue#UNSET_VALUE}, as a fraction of the viewport height
|
* {@link Cue#UNSET_VALUE}, as a fraction of the viewport height
|
||||||
* @param canvas The canvas into which to draw.
|
* @param canvas The canvas into which to draw.
|
||||||
@ -133,7 +127,7 @@ import android.util.Log;
|
|||||||
* @param cueBoxRight The right position of the enclosing cue box.
|
* @param cueBoxRight The right position of the enclosing cue box.
|
||||||
* @param cueBoxBottom The bottom position of the enclosing cue box.
|
* @param cueBoxBottom The bottom position of the enclosing cue box.
|
||||||
*/
|
*/
|
||||||
public void draw(Cue cue, boolean applyEmbeddedStyles, CaptionStyleCompat style, float fontScale,
|
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;
|
CharSequence cueText = cue.text;
|
||||||
@ -155,7 +149,7 @@ import android.util.Log;
|
|||||||
&& 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)
|
||||||
&& this.fontScale == fontScale
|
&& this.textSizePx == textSizePx
|
||||||
&& this.bottomPaddingFraction == bottomPaddingFraction
|
&& this.bottomPaddingFraction == bottomPaddingFraction
|
||||||
&& this.parentLeft == cueBoxLeft
|
&& this.parentLeft == cueBoxLeft
|
||||||
&& this.parentTop == cueBoxTop
|
&& this.parentTop == cueBoxTop
|
||||||
@ -176,7 +170,7 @@ import android.util.Log;
|
|||||||
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);
|
||||||
this.fontScale = fontScale;
|
this.textSizePx = textSizePx;
|
||||||
this.bottomPaddingFraction = bottomPaddingFraction;
|
this.bottomPaddingFraction = bottomPaddingFraction;
|
||||||
this.parentLeft = cueBoxLeft;
|
this.parentLeft = cueBoxLeft;
|
||||||
this.parentTop = cueBoxTop;
|
this.parentTop = cueBoxTop;
|
||||||
@ -186,9 +180,8 @@ import android.util.Log;
|
|||||||
int parentWidth = parentRight - parentLeft;
|
int parentWidth = parentRight - parentLeft;
|
||||||
int parentHeight = parentBottom - parentTop;
|
int parentHeight = parentBottom - parentTop;
|
||||||
|
|
||||||
float textSize = LINE_HEIGHT_FRACTION * parentHeight * fontScale;
|
textPaint.setTextSize(textSizePx);
|
||||||
textPaint.setTextSize(textSize);
|
int textPaddingX = (int) (textSizePx * INNER_PADDING_RATIO + 0.5f);
|
||||||
int textPaddingX = (int) (textSize * INNER_PADDING_RATIO + 0.5f);
|
|
||||||
int availableWidth = parentWidth - textPaddingX * 2;
|
int availableWidth = parentWidth - textPaddingX * 2;
|
||||||
if (availableWidth <= 0) {
|
if (availableWidth <= 0) {
|
||||||
Log.w(TAG, "Skipped drawing subtitle cue (insufficient space)");
|
Log.w(TAG, "Skipped drawing subtitle cue (insufficient space)");
|
||||||
@ -207,12 +200,8 @@ import android.util.Log;
|
|||||||
}
|
}
|
||||||
textWidth += textPaddingX * 2;
|
textWidth += textPaddingX * 2;
|
||||||
|
|
||||||
int textLeft = (parentWidth - textWidth) / 2;
|
int textLeft;
|
||||||
int textRight = textLeft + textWidth;
|
int textRight;
|
||||||
int textTop = parentBottom - textHeight
|
|
||||||
- (int) (parentHeight * bottomPaddingFraction);
|
|
||||||
int textBottom = textTop + textHeight;
|
|
||||||
|
|
||||||
if (cue.position != Cue.UNSET_VALUE) {
|
if (cue.position != Cue.UNSET_VALUE) {
|
||||||
if (cue.alignment == Alignment.ALIGN_OPPOSITE) {
|
if (cue.alignment == Alignment.ALIGN_OPPOSITE) {
|
||||||
textRight = (parentWidth * cue.position) / 100 + parentLeft;
|
textRight = (parentWidth * cue.position) / 100 + parentLeft;
|
||||||
@ -221,7 +210,13 @@ import android.util.Log;
|
|||||||
textLeft = (parentWidth * cue.position) / 100 + parentLeft;
|
textLeft = (parentWidth * cue.position) / 100 + parentLeft;
|
||||||
textRight = Math.min(textLeft + textWidth, parentRight);
|
textRight = Math.min(textLeft + textWidth, parentRight);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
textLeft = (parentWidth - textWidth) / 2;
|
||||||
|
textRight = textLeft + textWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int textTop;
|
||||||
|
int textBottom;
|
||||||
if (cue.line != Cue.UNSET_VALUE) {
|
if (cue.line != Cue.UNSET_VALUE) {
|
||||||
textTop = (parentHeight * cue.line) / 100 + parentTop;
|
textTop = (parentHeight * cue.line) / 100 + parentTop;
|
||||||
textBottom = textTop + textHeight;
|
textBottom = textTop + textHeight;
|
||||||
@ -229,7 +224,11 @@ import android.util.Log;
|
|||||||
textTop = parentBottom - textHeight;
|
textTop = parentBottom - textHeight;
|
||||||
textBottom = parentBottom;
|
textBottom = parentBottom;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
textTop = parentBottom - textHeight - (int) (parentHeight * bottomPaddingFraction);
|
||||||
|
textBottom = textTop + textHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
textWidth = textRight - textLeft;
|
textWidth = textRight - textLeft;
|
||||||
|
|
||||||
// Update the derived drawing variables.
|
// Update the derived drawing variables.
|
||||||
|
@ -16,8 +16,10 @@
|
|||||||
package com.google.android.exoplayer.text;
|
package com.google.android.exoplayer.text;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.content.res.Resources;
|
||||||
import android.graphics.Canvas;
|
import android.graphics.Canvas;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
|
import android.util.TypedValue;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@ -28,16 +30,30 @@ import java.util.List;
|
|||||||
*/
|
*/
|
||||||
public final class SubtitleLayout extends View {
|
public final class SubtitleLayout extends View {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The default fractional text size.
|
||||||
|
*
|
||||||
|
* @see #setFractionalTextSize(float, boolean)
|
||||||
|
*/
|
||||||
|
public static final float DEFAULT_TEXT_SIZE_FRACTION = 0.0533f;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The default bottom padding to apply when {@link Cue#line} is {@link Cue#UNSET_VALUE}, as a
|
* The default bottom padding to apply when {@link Cue#line} is {@link Cue#UNSET_VALUE}, as a
|
||||||
* fraction of the viewport height.
|
* fraction of the viewport height.
|
||||||
|
*
|
||||||
|
* @see #setBottomPaddingFraction(float)
|
||||||
*/
|
*/
|
||||||
public static final float DEFAULT_BOTTOM_PADDING_FRACTION = 0.08f;
|
public static final float DEFAULT_BOTTOM_PADDING_FRACTION = 0.08f;
|
||||||
|
|
||||||
|
private static final int FRACTIONAL = 0;
|
||||||
|
private static final int FRACTIONAL_IGNORE_PADDING = 1;
|
||||||
|
private static final int ABSOLUTE = 2;
|
||||||
|
|
||||||
private final List<CuePainter> painters;
|
private final List<CuePainter> painters;
|
||||||
|
|
||||||
private List<Cue> cues;
|
private List<Cue> cues;
|
||||||
private float fontScale;
|
private int textSizeType;
|
||||||
|
private float textSize;
|
||||||
private boolean applyEmbeddedStyles;
|
private boolean applyEmbeddedStyles;
|
||||||
private CaptionStyleCompat style;
|
private CaptionStyleCompat style;
|
||||||
private float bottomPaddingFraction;
|
private float bottomPaddingFraction;
|
||||||
@ -49,7 +65,8 @@ public final class SubtitleLayout extends View {
|
|||||||
public SubtitleLayout(Context context, AttributeSet attrs) {
|
public SubtitleLayout(Context context, AttributeSet attrs) {
|
||||||
super(context, attrs);
|
super(context, attrs);
|
||||||
painters = new ArrayList<>();
|
painters = new ArrayList<>();
|
||||||
fontScale = 1;
|
textSizeType = FRACTIONAL;
|
||||||
|
textSize = DEFAULT_TEXT_SIZE_FRACTION;
|
||||||
applyEmbeddedStyles = true;
|
applyEmbeddedStyles = true;
|
||||||
style = CaptionStyleCompat.DEFAULT;
|
style = CaptionStyleCompat.DEFAULT;
|
||||||
bottomPaddingFraction = DEFAULT_BOTTOM_PADDING_FRACTION;
|
bottomPaddingFraction = DEFAULT_BOTTOM_PADDING_FRACTION;
|
||||||
@ -75,15 +92,55 @@ public final class SubtitleLayout extends View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the scale of the font.
|
* Set the text size to a given unit and value.
|
||||||
|
* <p>
|
||||||
|
* See {@link TypedValue} for the possible dimension units.
|
||||||
*
|
*
|
||||||
* @param fontScale The scale of the font.
|
* @param unit The desired dimension unit.
|
||||||
|
* @param size The desired size in the given units.
|
||||||
*/
|
*/
|
||||||
public void setFontScale(float fontScale) {
|
public void setFixedTextSize(int unit, float size) {
|
||||||
if (this.fontScale == fontScale) {
|
Context context = getContext();
|
||||||
|
Resources resources;
|
||||||
|
if (context == null) {
|
||||||
|
resources = Resources.getSystem();
|
||||||
|
} else {
|
||||||
|
resources = context.getResources();
|
||||||
|
}
|
||||||
|
setTextSize(ABSOLUTE, TypedValue.applyDimension(unit, size, resources.getDisplayMetrics()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the text size to be a fraction of the view's remaining height after its top and bottom
|
||||||
|
* padding have been subtracted.
|
||||||
|
* <p>
|
||||||
|
* Equivalent to {@code #setFractionalTextSize(fractionOfHeight, false)}.
|
||||||
|
*
|
||||||
|
* @param fractionOfHeight A fraction between 0 and 1.
|
||||||
|
*/
|
||||||
|
public void setFractionalTextSize(float fractionOfHeight) {
|
||||||
|
setFractionalTextSize(fractionOfHeight, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the text size to be a fraction of the height of this view.
|
||||||
|
*
|
||||||
|
* @param fractionOfHeight A fraction between 0 and 1.
|
||||||
|
* @param ignorePadding Set to true if {@code fractionOfHeight} should be interpreted as a
|
||||||
|
* fraction of this view's height ignoring any top and bottom padding. Set to false if
|
||||||
|
* {@code fractionOfHeight} should be interpreted as a fraction of this view's remaining
|
||||||
|
* height after the top and bottom padding has been subtracted.
|
||||||
|
*/
|
||||||
|
public void setFractionalTextSize(float fractionOfHeight, boolean ignorePadding) {
|
||||||
|
setTextSize(ignorePadding ? FRACTIONAL_IGNORE_PADDING : FRACTIONAL, fractionOfHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setTextSize(int textSizeType, float textSize) {
|
||||||
|
if (this.textSizeType == textSizeType && this.textSize == textSize) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.fontScale = fontScale;
|
this.textSizeType = textSizeType;
|
||||||
|
this.textSize = textSize;
|
||||||
// Invalidate to trigger drawing.
|
// Invalidate to trigger drawing.
|
||||||
invalidate();
|
invalidate();
|
||||||
}
|
}
|
||||||
@ -118,7 +175,10 @@ public final class SubtitleLayout extends View {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the bottom padding fraction to apply when {@link Cue#line} is {@link Cue#UNSET_VALUE},
|
* Sets the bottom padding fraction to apply when {@link Cue#line} is {@link Cue#UNSET_VALUE},
|
||||||
* as a fraction of the viewport height.
|
* as a fraction of the view's remaining height after its top and bottom padding have been
|
||||||
|
* subtracted.
|
||||||
|
* <p>
|
||||||
|
* Note that this padding is applied in addition to any standard view padding.
|
||||||
*
|
*
|
||||||
* @param bottomPaddingFraction The bottom padding fraction.
|
* @param bottomPaddingFraction The bottom padding fraction.
|
||||||
*/
|
*/
|
||||||
@ -134,9 +194,29 @@ public final class SubtitleLayout extends View {
|
|||||||
@Override
|
@Override
|
||||||
public void dispatchDraw(Canvas canvas) {
|
public void dispatchDraw(Canvas canvas) {
|
||||||
int cueCount = (cues == null) ? 0 : cues.size();
|
int cueCount = (cues == null) ? 0 : cues.size();
|
||||||
|
int rawTop = getTop();
|
||||||
|
int rawBottom = getBottom();
|
||||||
|
|
||||||
|
// Calculate the bounds after padding is taken into account.
|
||||||
|
int left = getLeft() + getPaddingLeft();
|
||||||
|
int top = rawTop + getPaddingTop();
|
||||||
|
int right = getRight() + getPaddingRight();
|
||||||
|
int bottom = rawBottom - getPaddingBottom();
|
||||||
|
if (bottom <= top || right <= left) {
|
||||||
|
// No space to draw subtitles.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
float textSizePx = textSizeType == ABSOLUTE ? textSize
|
||||||
|
: textSize * (textSizeType == FRACTIONAL ? (bottom - top) : (rawBottom - rawTop));
|
||||||
|
if (textSizePx <= 0) {
|
||||||
|
// Text has no height.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < cueCount; i++) {
|
for (int i = 0; i < cueCount; i++) {
|
||||||
painters.get(i).draw(cues.get(i), applyEmbeddedStyles, style, fontScale,
|
painters.get(i).draw(cues.get(i), applyEmbeddedStyles, style, textSizePx,
|
||||||
bottomPaddingFraction, canvas, getLeft(), getTop(), getRight(), getBottom());
|
bottomPaddingFraction, canvas, left, top, right, bottom);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user