am 812b6426: Merge "Fix caption rendering" into klp-dev

* commit '812b64264176cb8a253a8253074bc9595503d2ac':
  Fix caption rendering
This commit is contained in:
Alan Viverette
2013-09-25 15:23:50 -07:00
committed by Android Git Automerger
2 changed files with 66 additions and 90 deletions

View File

@@ -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);
} }
} }

View File

@@ -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);