am 812b6426: Merge "Fix caption rendering" into klp-dev
* commit '812b64264176cb8a253a8253074bc9595503d2ac': Fix caption rendering
This commit is contained in:
@@ -31,7 +31,6 @@ import android.graphics.Typeface;
|
|||||||
import android.text.Layout.Alignment;
|
import android.text.Layout.Alignment;
|
||||||
import android.text.StaticLayout;
|
import android.text.StaticLayout;
|
||||||
import android.text.TextPaint;
|
import android.text.TextPaint;
|
||||||
import android.text.TextUtils;
|
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
import android.util.DisplayMetrics;
|
import android.util.DisplayMetrics;
|
||||||
import android.util.TypedValue;
|
import android.util.TypedValue;
|
||||||
@@ -52,14 +51,12 @@ public class SubtitleView extends View {
|
|||||||
/** Temporary rectangle used for computing line bounds. */
|
/** Temporary rectangle used for computing line bounds. */
|
||||||
private final RectF mLineBounds = new RectF();
|
private final RectF mLineBounds = new RectF();
|
||||||
|
|
||||||
/** Temporary array used for computing line wrapping. */
|
|
||||||
private float[] mTextWidths;
|
|
||||||
|
|
||||||
/** Reusable string builder used for holding text. */
|
/** Reusable string builder used for holding text. */
|
||||||
private final StringBuilder mText = new StringBuilder();
|
private final StringBuilder mText = new StringBuilder();
|
||||||
private final StringBuilder mBreakText = new StringBuilder();
|
|
||||||
|
|
||||||
private TextPaint mPaint;
|
private Alignment mAlignment;
|
||||||
|
private TextPaint mTextPaint;
|
||||||
|
private Paint mPaint;
|
||||||
|
|
||||||
private int mForegroundColor;
|
private int mForegroundColor;
|
||||||
private int mBackgroundColor;
|
private int mBackgroundColor;
|
||||||
@@ -122,11 +119,12 @@ public class SubtitleView extends View {
|
|||||||
mShadowOffsetX = res.getDimension(com.android.internal.R.dimen.subtitle_shadow_offset);
|
mShadowOffsetX = res.getDimension(com.android.internal.R.dimen.subtitle_shadow_offset);
|
||||||
mShadowOffsetY = mShadowOffsetX;
|
mShadowOffsetY = mShadowOffsetX;
|
||||||
|
|
||||||
final TextPaint paint = new TextPaint();
|
mTextPaint = new TextPaint();
|
||||||
paint.setAntiAlias(true);
|
mTextPaint.setAntiAlias(true);
|
||||||
paint.setSubpixelText(true);
|
mTextPaint.setSubpixelText(true);
|
||||||
|
|
||||||
mPaint = paint;
|
mPaint = new Paint();
|
||||||
|
mPaint.setAntiAlias(true);
|
||||||
|
|
||||||
setText(text);
|
setText(text);
|
||||||
setTextSize(textSize);
|
setTextSize(textSize);
|
||||||
@@ -174,21 +172,30 @@ public class SubtitleView extends View {
|
|||||||
public void setTextSize(float size) {
|
public void setTextSize(float size) {
|
||||||
final DisplayMetrics metrics = getContext().getResources().getDisplayMetrics();
|
final DisplayMetrics metrics = getContext().getResources().getDisplayMetrics();
|
||||||
final float pixels = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, size, metrics);
|
final float pixels = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, size, metrics);
|
||||||
if (mPaint.getTextSize() != size) {
|
if (mTextPaint.getTextSize() != size) {
|
||||||
mHasMeasurements = false;
|
mTextPaint.setTextSize(size);
|
||||||
mInnerPaddingX = (int) (size * INNER_PADDING_RATIO + 0.5f);
|
mInnerPaddingX = (int) (size * INNER_PADDING_RATIO + 0.5f);
|
||||||
mPaint.setTextSize(size);
|
|
||||||
|
|
||||||
requestLayout();
|
mHasMeasurements = false;
|
||||||
|
forceLayout();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setTypeface(Typeface typeface) {
|
public void setTypeface(Typeface typeface) {
|
||||||
if (mPaint.getTypeface() != typeface) {
|
if (mTextPaint.getTypeface() != typeface) {
|
||||||
mHasMeasurements = false;
|
mTextPaint.setTypeface(typeface);
|
||||||
mPaint.setTypeface(typeface);
|
|
||||||
|
|
||||||
requestLayout();
|
mHasMeasurements = false;
|
||||||
|
forceLayout();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAlignment(Alignment textAlignment) {
|
||||||
|
if (mAlignment != textAlignment) {
|
||||||
|
mAlignment = textAlignment;
|
||||||
|
|
||||||
|
mHasMeasurements = false;
|
||||||
|
forceLayout();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -222,63 +229,19 @@ public class SubtitleView extends View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Account for padding.
|
// Account for padding.
|
||||||
final int paddingX = mPaddingLeft + mPaddingRight + mInnerPaddingX;
|
final int paddingX = mPaddingLeft + mPaddingRight + mInnerPaddingX * 2;
|
||||||
maxWidth -= paddingX;
|
maxWidth -= paddingX;
|
||||||
|
|
||||||
if (maxWidth <= 0) {
|
if (maxWidth <= 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
final TextPaint paint = mPaint;
|
// TODO: Implement minimum-difference line wrapping. Adding the results
|
||||||
final CharSequence text = mText;
|
// of Paint.getTextWidths() seems to return different values than
|
||||||
final int textLength = text.length();
|
// StaticLayout.getWidth(), so this is non-trivial.
|
||||||
if (mTextWidths == null || mTextWidths.length < textLength) {
|
|
||||||
mTextWidths = new float[textLength];
|
|
||||||
}
|
|
||||||
|
|
||||||
final float[] textWidths = mTextWidths;
|
|
||||||
paint.getTextWidths(text, 0, textLength, textWidths);
|
|
||||||
|
|
||||||
// Compute total length.
|
|
||||||
float runLength = 0;
|
|
||||||
for (int i = 0; i < textLength; i++) {
|
|
||||||
runLength += textWidths[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
final int lineCount = (int) (runLength / maxWidth) + 1;
|
|
||||||
final int lineLength = (int) (runLength / lineCount);
|
|
||||||
|
|
||||||
// Build line break buffer.
|
|
||||||
final StringBuilder breakText = mBreakText;
|
|
||||||
breakText.setLength(0);
|
|
||||||
|
|
||||||
int line = 0;
|
|
||||||
int lastBreak = 0;
|
|
||||||
int maxRunLength = 0;
|
|
||||||
runLength = 0;
|
|
||||||
for (int i = 0; i < textLength; i++) {
|
|
||||||
if (runLength > lineLength) {
|
|
||||||
final CharSequence sequence = text.subSequence(lastBreak, i);
|
|
||||||
final int trimmedLength = TextUtils.getTrimmedLength(sequence);
|
|
||||||
breakText.append(sequence, 0, trimmedLength);
|
|
||||||
breakText.append('\n');
|
|
||||||
lastBreak = i;
|
|
||||||
runLength = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
runLength += textWidths[i];
|
|
||||||
|
|
||||||
if (runLength > maxRunLength) {
|
|
||||||
maxRunLength = (int) Math.ceil(runLength);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
breakText.append(text.subSequence(lastBreak, textLength));
|
|
||||||
|
|
||||||
mHasMeasurements = true;
|
mHasMeasurements = true;
|
||||||
mLastMeasuredWidth = maxWidth;
|
mLastMeasuredWidth = maxWidth;
|
||||||
|
mLayout = new StaticLayout(
|
||||||
mLayout = new StaticLayout(breakText, paint, maxRunLength, Alignment.ALIGN_LEFT,
|
mText, mTextPaint, maxWidth, mAlignment, mSpacingMult, mSpacingAdd, true);
|
||||||
mSpacingMult, mSpacingAdd, true);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -316,54 +279,50 @@ public class SubtitleView extends View {
|
|||||||
final int innerPaddingX = mInnerPaddingX;
|
final int innerPaddingX = mInnerPaddingX;
|
||||||
c.translate(mPaddingLeft + innerPaddingX, mPaddingTop);
|
c.translate(mPaddingLeft + innerPaddingX, mPaddingTop);
|
||||||
|
|
||||||
final RectF bounds = mLineBounds;
|
|
||||||
final int lineCount = layout.getLineCount();
|
final int lineCount = layout.getLineCount();
|
||||||
final Paint paint = layout.getPaint();
|
final Paint textPaint = mTextPaint;
|
||||||
paint.setShadowLayer(0, 0, 0, 0);
|
final Paint paint = mPaint;
|
||||||
|
final RectF bounds = mLineBounds;
|
||||||
final int backgroundColor = mBackgroundColor;
|
|
||||||
if (Color.alpha(backgroundColor) > 0) {
|
|
||||||
paint.setColor(backgroundColor);
|
|
||||||
paint.setStyle(Style.FILL);
|
|
||||||
|
|
||||||
|
if (Color.alpha(mBackgroundColor) > 0) {
|
||||||
final float cornerRadius = mCornerRadius;
|
final float cornerRadius = mCornerRadius;
|
||||||
float previousBottom = layout.getLineTop(0);
|
float previousBottom = layout.getLineTop(0);
|
||||||
|
|
||||||
|
paint.setColor(mBackgroundColor);
|
||||||
|
paint.setStyle(Style.FILL);
|
||||||
|
|
||||||
for (int i = 0; i < lineCount; i++) {
|
for (int i = 0; i < lineCount; i++) {
|
||||||
bounds.left = layout.getLineLeft(i) - innerPaddingX;
|
bounds.left = layout.getLineLeft(i) -innerPaddingX;
|
||||||
bounds.right = layout.getLineRight(i) + innerPaddingX;
|
bounds.right = layout.getLineRight(i) + innerPaddingX;
|
||||||
bounds.top = previousBottom;
|
bounds.top = previousBottom;
|
||||||
bounds.bottom = layout.getLineBottom(i);
|
bounds.bottom = layout.getLineBottom(i);
|
||||||
|
|
||||||
previousBottom = bounds.bottom;
|
previousBottom = bounds.bottom;
|
||||||
|
|
||||||
c.drawRoundRect(bounds, cornerRadius, cornerRadius, paint);
|
c.drawRoundRect(bounds, cornerRadius, cornerRadius, paint);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final int edgeType = mEdgeType;
|
if (mEdgeType == CaptionStyle.EDGE_TYPE_OUTLINE) {
|
||||||
if (edgeType == CaptionStyle.EDGE_TYPE_OUTLINE) {
|
textPaint.setStrokeJoin(Join.ROUND);
|
||||||
paint.setColor(mEdgeColor);
|
textPaint.setStrokeWidth(mOutlineWidth);
|
||||||
paint.setStyle(Style.FILL_AND_STROKE);
|
textPaint.setColor(mEdgeColor);
|
||||||
paint.setStrokeJoin(Join.ROUND);
|
textPaint.setStyle(Style.FILL_AND_STROKE);
|
||||||
paint.setStrokeWidth(mOutlineWidth);
|
|
||||||
|
|
||||||
for (int i = 0; i < lineCount; i++) {
|
for (int i = 0; i < lineCount; i++) {
|
||||||
layout.drawText(c, i, i);
|
layout.drawText(c, i, i);
|
||||||
}
|
}
|
||||||
|
} else if (mEdgeType == CaptionStyle.EDGE_TYPE_DROP_SHADOW) {
|
||||||
|
textPaint.setShadowLayer(mShadowRadius, mShadowOffsetX, mShadowOffsetY, mEdgeColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (edgeType == CaptionStyle.EDGE_TYPE_DROP_SHADOW) {
|
textPaint.setColor(mForegroundColor);
|
||||||
paint.setShadowLayer(mShadowRadius, mShadowOffsetX, mShadowOffsetY, mEdgeColor);
|
textPaint.setStyle(Style.FILL);
|
||||||
}
|
|
||||||
|
|
||||||
paint.setColor(mForegroundColor);
|
|
||||||
paint.setStyle(Style.FILL);
|
|
||||||
|
|
||||||
for (int i = 0; i < lineCount; i++) {
|
for (int i = 0; i < lineCount; i++) {
|
||||||
layout.drawText(c, i, i);
|
layout.drawText(c, i, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
textPaint.setShadowLayer(0, 0, 0, 0);
|
||||||
c.restoreToCount(saveCount);
|
c.restoreToCount(saveCount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
package android.media;
|
package android.media;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.text.Layout.Alignment;
|
||||||
import android.text.SpannableStringBuilder;
|
import android.text.SpannableStringBuilder;
|
||||||
import android.util.ArrayMap;
|
import android.util.ArrayMap;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
@@ -1583,6 +1584,7 @@ class WebVttRenderingWidget extends ViewGroup implements SubtitleTrack.Rendering
|
|||||||
}
|
}
|
||||||
|
|
||||||
final CueLayout cueBox = new CueLayout(getContext(), cue, mCaptionStyle, mFontSize);
|
final CueLayout cueBox = new CueLayout(getContext(), cue, mCaptionStyle, mFontSize);
|
||||||
|
mRegionCueBoxes.add(cueBox);
|
||||||
addView(cueBox, LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
|
addView(cueBox, LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
|
||||||
|
|
||||||
if (getChildCount() > mRegion.mLines) {
|
if (getChildCount() > mRegion.mLines) {
|
||||||
@@ -1696,12 +1698,27 @@ class WebVttRenderingWidget extends ViewGroup implements SubtitleTrack.Rendering
|
|||||||
|
|
||||||
removeAllViews();
|
removeAllViews();
|
||||||
|
|
||||||
|
final int cueAlignment = resolveCueAlignment(getLayoutDirection(), mCue.mAlignment);
|
||||||
|
final Alignment alignment;
|
||||||
|
switch (cueAlignment) {
|
||||||
|
case TextTrackCue.ALIGNMENT_LEFT:
|
||||||
|
alignment = Alignment.ALIGN_LEFT;
|
||||||
|
break;
|
||||||
|
case TextTrackCue.ALIGNMENT_RIGHT:
|
||||||
|
alignment = Alignment.ALIGN_RIGHT;
|
||||||
|
break;
|
||||||
|
case TextTrackCue.ALIGNMENT_MIDDLE:
|
||||||
|
default:
|
||||||
|
alignment = Alignment.ALIGN_CENTER;
|
||||||
|
}
|
||||||
|
|
||||||
final CaptionStyle captionStyle = mCaptionStyle;
|
final CaptionStyle captionStyle = mCaptionStyle;
|
||||||
final float fontSize = mFontSize;
|
final float fontSize = mFontSize;
|
||||||
final TextTrackCueSpan[][] lines = mCue.mLines;
|
final TextTrackCueSpan[][] lines = mCue.mLines;
|
||||||
final int lineCount = lines.length;
|
final int lineCount = lines.length;
|
||||||
for (int i = 0; i < lineCount; i++) {
|
for (int i = 0; i < lineCount; i++) {
|
||||||
final SpanLayout lineBox = new SpanLayout(getContext(), lines[i]);
|
final SpanLayout lineBox = new SpanLayout(getContext(), lines[i]);
|
||||||
|
lineBox.setAlignment(alignment);
|
||||||
lineBox.setCaptionStyle(captionStyle, fontSize);
|
lineBox.setCaptionStyle(captionStyle, fontSize);
|
||||||
|
|
||||||
addView(lineBox, LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
|
addView(lineBox, LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
|
||||||
|
|||||||
Reference in New Issue
Block a user