Split Cue Rendering up into 3 phases

Split Cue Rendering up into a layout, background drawing and foreground
drawing phase so that issues with overlapping 608 captions are being prevented.
This commit is contained in:
Rik Heijdens 2016-08-31 11:55:41 +02:00
parent ad9f76eb62
commit 4d18e623d6
3 changed files with 47 additions and 30 deletions

View file

@ -89,18 +89,14 @@ import java.util.List;
this.indent = indent;
}
/**
* Indents the Cue.
* @param tabs The amount of tabs to indent the cue with.
*/
public void tab(int tabs) {
tabOffset += tabs;
}
/**
* Indents the cue position with amountOfTabs.
* @param tabOffset the amount of tabs the cue position should be indented.
*/
public void setTabOffset(int tabOffset) {
this.tabOffset = tabOffset;
}
/**
* Appends a character to the current Cue.
* @param character the character to append.

View file

@ -117,30 +117,30 @@ import android.util.Log;
}
/**
* Draws the provided {@link Cue} into a canvas with the specified styling.
* Creates layouts so that the provided {@link Cue} can be drawn in a {@link Canvas} by calls to
* {@link #drawBackground(Canvas)} and {@link #drawForeground(Canvas)} with the specified styling.
* <p>
* A call to this method is able to use cached results of calculations made during the previous
* call, and so an instance of this class is able to optimize repeated calls to this method in
* which the same parameters are passed.
*
* @param cue The cue to draw.
* @param cue The cue to layout.
* @param applyEmbeddedStyles Whether styling embedded within the cue should be applied.
* @param style The style to use when drawing the cue text.
* @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#DIMEN_UNSET}, as a fraction of the viewport height
* @param canvas The canvas into which to draw.
* @param cueBoxLeft The left position of the enclosing cue box.
* @param cueBoxTop The top 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.
*/
public void draw(Cue cue, boolean applyEmbeddedStyles, CaptionStyleCompat style, float textSizePx,
float bottomPaddingFraction, Canvas canvas, int cueBoxLeft, int cueBoxTop, int cueBoxRight,
int cueBoxBottom) {
public void layout(Cue cue, boolean applyEmbeddedStyles, CaptionStyleCompat style, float textSizePx,
float bottomPaddingFraction, int cueBoxLeft, int cueBoxTop, int cueBoxRight,
int cueBoxBottom) {
CharSequence cueText = cue.text;
if (TextUtils.isEmpty(cueText)) {
// Nothing to draw.
// Nothing to layout.
return;
}
if (!applyEmbeddedStyles) {
@ -169,7 +169,6 @@ import android.util.Log;
&& this.parentRight == cueBoxRight
&& this.parentBottom == cueBoxBottom) {
// We can use the cached layout.
drawLayout(canvas);
return;
}
@ -272,19 +271,17 @@ import android.util.Log;
this.textLeft = textLeft;
this.textTop = textTop;
this.textPaddingX = textPaddingX;
drawLayout(canvas);
}
/**
* Draws {@link #textLayout} into the provided canvas.
* Draws the background of the {@link #textLayout} into the provided canvas.
*
* @param canvas The canvas into which to draw.
* @param canvas The canvas into which to layout.
*/
private void drawLayout(Canvas canvas) {
public void drawBackground(Canvas canvas) {
final StaticLayout layout = textLayout;
if (layout == null) {
// Nothing to draw.
// Nothing to layout.
return;
}
@ -311,6 +308,24 @@ import android.util.Log;
}
}
canvas.restoreToCount(saveCount);
}
/**
* Draws the foreground of the {@link #textLayout} into the provided canvas.
*
* @param canvas The canvas into which to layout.
*/
public void drawForeground(Canvas canvas) {
final StaticLayout layout = textLayout;
if (layout == null) {
// Nothing to layout.
return;
}
int saveCount = canvas.save();
canvas.translate(textLeft, textTop);
if (edgeType == CaptionStyleCompat.EDGE_TYPE_OUTLINE) {
textPaint.setStrokeJoin(Join.ROUND);
textPaint.setStrokeWidth(outlineWidth);
@ -320,7 +335,7 @@ import android.util.Log;
} else if (edgeType == CaptionStyleCompat.EDGE_TYPE_DROP_SHADOW) {
textPaint.setShadowLayer(shadowRadius, shadowOffset, shadowOffset, edgeColor);
} else if (edgeType == CaptionStyleCompat.EDGE_TYPE_RAISED
|| edgeType == CaptionStyleCompat.EDGE_TYPE_DEPRESSED) {
|| edgeType == CaptionStyleCompat.EDGE_TYPE_DEPRESSED) {
boolean raised = edgeType == CaptionStyleCompat.EDGE_TYPE_RAISED;
int colorUp = raised ? Color.WHITE : edgeColor;
int colorDown = raised ? edgeColor : Color.WHITE;

View file

@ -15,6 +15,11 @@
*/
package com.google.android.exoplayer2.ui;
import com.google.android.exoplayer2.text.CaptionStyleCompat;
import com.google.android.exoplayer2.text.Cue;
import com.google.android.exoplayer2.text.TextRenderer;
import com.google.android.exoplayer2.util.Util;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.Resources;
@ -23,10 +28,7 @@ import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.View;
import android.view.accessibility.CaptioningManager;
import com.google.android.exoplayer2.text.CaptionStyleCompat;
import com.google.android.exoplayer2.text.Cue;
import com.google.android.exoplayer2.text.TextRenderer;
import com.google.android.exoplayer2.util.Util;
import java.util.ArrayList;
import java.util.List;
@ -230,7 +232,7 @@ public final class SubtitleView extends View implements TextRenderer.Output {
int right = getRight() + getPaddingRight();
int bottom = rawBottom - getPaddingBottom();
if (bottom <= top || right <= left) {
// No space to draw subtitles.
// No space to layout subtitles.
return;
}
@ -242,8 +244,12 @@ public final class SubtitleView extends View implements TextRenderer.Output {
}
for (int i = 0; i < cueCount; i++) {
painters.get(i).draw(cues.get(i), applyEmbeddedStyles, style, textSizePx,
bottomPaddingFraction, canvas, left, top, right, bottom);
painters.get(i).layout(cues.get(i), applyEmbeddedStyles, style, textSizePx,
bottomPaddingFraction, left, top, right, bottom);
painters.get(i).drawBackground(canvas);
}
for (int i = 0; i < cueCount; i++) {
painters.get(i).drawForeground(canvas);
}
}