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:
Oliver Woodman 2015-09-18 18:19:28 +01:00
parent 7f9b12982d
commit 8a723706d6
3 changed files with 117 additions and 38 deletions

View File

@ -562,17 +562,17 @@ public class PlayerActivity extends Activity implements SurfaceHolder.Callback,
}
private void configureSubtitleView() {
CaptionStyleCompat captionStyle;
float captionFontScale;
CaptionStyleCompat style;
float fontScale;
if (Util.SDK_INT >= 19) {
captionStyle = getUserCaptionStyleV19();
captionFontScale = getUserCaptionFontScaleV19();
style = getUserCaptionStyleV19();
fontScale = getUserCaptionFontScaleV19();
} else {
captionStyle = CaptionStyleCompat.DEFAULT;
captionFontScale = 1.0f;
style = CaptionStyleCompat.DEFAULT;
fontScale = 1.0f;
}
subtitleLayout.setStyle(captionStyle);
subtitleLayout.setFontScale(captionFontScale);
subtitleLayout.setStyle(style);
subtitleLayout.setFractionalTextSize(SubtitleLayout.DEFAULT_TEXT_SIZE_FRACTION * fontScale);
}
@TargetApi(19)

View File

@ -45,12 +45,6 @@ import android.util.Log;
*/
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.
*/
@ -77,7 +71,7 @@ import android.util.Log;
private int windowColor;
private int edgeColor;
private int edgeType;
private float fontScale;
private float textSizePx;
private float bottomPaddingFraction;
private int parentLeft;
private int parentTop;
@ -124,7 +118,7 @@ import android.util.Log;
* @param cue The cue to draw.
* @param applyEmbeddedStyles Whether styling embedded within the cue should be applied.
* @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
* {@link Cue#UNSET_VALUE}, as a fraction of the viewport height
* @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 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,
int cueBoxBottom) {
CharSequence cueText = cue.text;
@ -155,7 +149,7 @@ import android.util.Log;
&& this.edgeType == style.edgeType
&& this.edgeColor == style.edgeColor
&& Util.areEqual(this.textPaint.getTypeface(), style.typeface)
&& this.fontScale == fontScale
&& this.textSizePx == textSizePx
&& this.bottomPaddingFraction == bottomPaddingFraction
&& this.parentLeft == cueBoxLeft
&& this.parentTop == cueBoxTop
@ -176,7 +170,7 @@ import android.util.Log;
this.edgeType = style.edgeType;
this.edgeColor = style.edgeColor;
this.textPaint.setTypeface(style.typeface);
this.fontScale = fontScale;
this.textSizePx = textSizePx;
this.bottomPaddingFraction = bottomPaddingFraction;
this.parentLeft = cueBoxLeft;
this.parentTop = cueBoxTop;
@ -186,9 +180,8 @@ import android.util.Log;
int parentWidth = parentRight - parentLeft;
int parentHeight = parentBottom - parentTop;
float textSize = LINE_HEIGHT_FRACTION * parentHeight * fontScale;
textPaint.setTextSize(textSize);
int textPaddingX = (int) (textSize * INNER_PADDING_RATIO + 0.5f);
textPaint.setTextSize(textSizePx);
int textPaddingX = (int) (textSizePx * INNER_PADDING_RATIO + 0.5f);
int availableWidth = parentWidth - textPaddingX * 2;
if (availableWidth <= 0) {
Log.w(TAG, "Skipped drawing subtitle cue (insufficient space)");
@ -207,12 +200,8 @@ import android.util.Log;
}
textWidth += textPaddingX * 2;
int textLeft = (parentWidth - textWidth) / 2;
int textRight = textLeft + textWidth;
int textTop = parentBottom - textHeight
- (int) (parentHeight * bottomPaddingFraction);
int textBottom = textTop + textHeight;
int textLeft;
int textRight;
if (cue.position != Cue.UNSET_VALUE) {
if (cue.alignment == Alignment.ALIGN_OPPOSITE) {
textRight = (parentWidth * cue.position) / 100 + parentLeft;
@ -221,7 +210,13 @@ import android.util.Log;
textLeft = (parentWidth * cue.position) / 100 + parentLeft;
textRight = Math.min(textLeft + textWidth, parentRight);
}
} else {
textLeft = (parentWidth - textWidth) / 2;
textRight = textLeft + textWidth;
}
int textTop;
int textBottom;
if (cue.line != Cue.UNSET_VALUE) {
textTop = (parentHeight * cue.line) / 100 + parentTop;
textBottom = textTop + textHeight;
@ -229,7 +224,11 @@ import android.util.Log;
textTop = parentBottom - textHeight;
textBottom = parentBottom;
}
} else {
textTop = parentBottom - textHeight - (int) (parentHeight * bottomPaddingFraction);
textBottom = textTop + textHeight;
}
textWidth = textRight - textLeft;
// Update the derived drawing variables.

View File

@ -16,8 +16,10 @@
package com.google.android.exoplayer.text;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.View;
import java.util.ArrayList;
@ -28,16 +30,30 @@ import java.util.List;
*/
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
* fraction of the viewport height.
*
* @see #setBottomPaddingFraction(float)
*/
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 List<Cue> cues;
private float fontScale;
private int textSizeType;
private float textSize;
private boolean applyEmbeddedStyles;
private CaptionStyleCompat style;
private float bottomPaddingFraction;
@ -49,7 +65,8 @@ public final class SubtitleLayout extends View {
public SubtitleLayout(Context context, AttributeSet attrs) {
super(context, attrs);
painters = new ArrayList<>();
fontScale = 1;
textSizeType = FRACTIONAL;
textSize = DEFAULT_TEXT_SIZE_FRACTION;
applyEmbeddedStyles = true;
style = CaptionStyleCompat.DEFAULT;
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) {
if (this.fontScale == fontScale) {
public void setFixedTextSize(int unit, float size) {
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;
}
this.fontScale = fontScale;
this.textSizeType = textSizeType;
this.textSize = textSize;
// Invalidate to trigger drawing.
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},
* 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.
*/
@ -134,9 +194,29 @@ public final class SubtitleLayout extends View {
@Override
public void dispatchDraw(Canvas canvas) {
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++) {
painters.get(i).draw(cues.get(i), applyEmbeddedStyles, style, fontScale,
bottomPaddingFraction, canvas, getLeft(), getTop(), getRight(), getBottom());
painters.get(i).draw(cues.get(i), applyEmbeddedStyles, style, textSizePx,
bottomPaddingFraction, canvas, left, top, right, bottom);
}
}