Fix TextOverlay's overlay width measuring strategy
Before this CL, the text with a scale span would wrap text, with because the scale wasn't taken into account when measuring the width of the overlay. PiperOrigin-RevId: 548123626
This commit is contained in:
parent
42998d6400
commit
453431fef2
@ -35,6 +35,7 @@ import android.opengl.Matrix;
|
||||
import android.text.Spannable;
|
||||
import android.text.SpannableString;
|
||||
import android.text.style.ForegroundColorSpan;
|
||||
import android.text.style.RelativeSizeSpan;
|
||||
import androidx.media3.common.VideoFrameProcessingException;
|
||||
import androidx.media3.common.util.GlUtil;
|
||||
import androidx.media3.common.util.Size;
|
||||
@ -71,6 +72,8 @@ public class OverlayShaderProgramPixelTest {
|
||||
"media/bitmap/sample_mp4_first_frame/electrical_colors/overlay_bitmap_translucent.png";
|
||||
private static final String OVERLAY_TEXT_DEFAULT =
|
||||
"media/bitmap/sample_mp4_first_frame/electrical_colors/overlay_text_default.png";
|
||||
private static final String OVERLAY_TEXT_SPAN_SCALED =
|
||||
"media/bitmap/sample_mp4_first_frame/electrical_colors/overlay_text_span_scaled.png";
|
||||
private static final String OVERLAY_TEXT_TRANSLATE =
|
||||
"media/bitmap/sample_mp4_first_frame/electrical_colors/overlay_text_translate.png";
|
||||
private static final String OVERLAY_MULTIPLE =
|
||||
@ -302,6 +305,33 @@ public class OverlayShaderProgramPixelTest {
|
||||
assertThat(averagePixelAbsoluteDifference).isAtMost(MAXIMUM_AVERAGE_PIXEL_ABSOLUTE_DIFFERENCE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void drawFrame_textOverlayWithRelativeScaleSpan_blendsTextIntoFrame() throws Exception {
|
||||
String testId = "drawFrame_textOverlayWithRelativeScaleSpan";
|
||||
SpannableString overlayText = new SpannableString(/* source= */ "helllllloooo!!!");
|
||||
overlayText.setSpan(
|
||||
new RelativeSizeSpan(2f),
|
||||
/* start= */ 0,
|
||||
/* end= */ overlayText.length(),
|
||||
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
TextOverlay staticTextOverlay = TextOverlay.createStaticTextOverlay(overlayText);
|
||||
overlayShaderProgram =
|
||||
new OverlayEffect(ImmutableList.of(staticTextOverlay))
|
||||
.toGlShaderProgram(context, /* useHdr= */ false);
|
||||
Size outputSize = overlayShaderProgram.configure(inputWidth, inputHeight);
|
||||
setupOutputTexture(outputSize.getWidth(), outputSize.getHeight());
|
||||
Bitmap expectedBitmap = readBitmap(OVERLAY_TEXT_SPAN_SCALED);
|
||||
|
||||
overlayShaderProgram.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
|
||||
Bitmap actualBitmap =
|
||||
createArgb8888BitmapFromFocusedGlFramebuffer(outputSize.getWidth(), outputSize.getHeight());
|
||||
|
||||
maybeSaveTestBitmap(testId, /* bitmapLabel= */ "actual", actualBitmap, /* path= */ null);
|
||||
float averagePixelAbsoluteDifference =
|
||||
getBitmapAveragePixelAbsoluteDifferenceArgb8888(expectedBitmap, actualBitmap, testId);
|
||||
assertThat(averagePixelAbsoluteDifference).isAtMost(MAXIMUM_AVERAGE_PIXEL_ABSOLUTE_DIFFERENCE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void drawFrame_translatedTextOverlay_blendsTextIntoFrame() throws Exception {
|
||||
String testId = "drawFrame_translatedTextOverlay";
|
||||
|
@ -17,6 +17,7 @@ package androidx.media3.effect;
|
||||
|
||||
import static androidx.media3.common.util.Assertions.checkNotNull;
|
||||
import static androidx.media3.common.util.Util.SDK_INT;
|
||||
import static java.lang.Math.ceil;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.graphics.Bitmap;
|
||||
@ -87,7 +88,6 @@ public abstract class TextOverlay extends BitmapOverlay {
|
||||
*/
|
||||
public abstract SpannableString getText(long presentationTimeUs);
|
||||
|
||||
@SuppressLint("InlinedApi") // Inlined Layout constants.
|
||||
@Override
|
||||
public Bitmap getBitmap(long presentationTimeUs) {
|
||||
SpannableString overlayText = getText(presentationTimeUs);
|
||||
@ -95,21 +95,8 @@ public abstract class TextOverlay extends BitmapOverlay {
|
||||
lastText = overlayText;
|
||||
TextPaint textPaint = new TextPaint();
|
||||
textPaint.setTextSize(TEXT_SIZE_PIXELS);
|
||||
StaticLayout staticLayout;
|
||||
int width = (int) textPaint.measureText(overlayText, /* start= */ 0, overlayText.length());
|
||||
if (SDK_INT >= 23) {
|
||||
staticLayout = Api23.getStaticLayout(overlayText, textPaint, width);
|
||||
} else {
|
||||
staticLayout =
|
||||
new StaticLayout(
|
||||
overlayText,
|
||||
textPaint,
|
||||
width,
|
||||
Layout.Alignment.ALIGN_NORMAL,
|
||||
Layout.DEFAULT_LINESPACING_MULTIPLIER,
|
||||
Layout.DEFAULT_LINESPACING_ADDITION,
|
||||
/* includepad= */ true);
|
||||
}
|
||||
StaticLayout staticLayout =
|
||||
createStaticLayout(overlayText, textPaint, getSpannedTextWidth(overlayText, textPaint));
|
||||
lastBitmap =
|
||||
Bitmap.createBitmap(
|
||||
staticLayout.getWidth(), staticLayout.getHeight(), Bitmap.Config.ARGB_8888);
|
||||
@ -119,6 +106,33 @@ public abstract class TextOverlay extends BitmapOverlay {
|
||||
return checkNotNull(lastBitmap);
|
||||
}
|
||||
|
||||
private int getSpannedTextWidth(SpannableString text, TextPaint textPaint) {
|
||||
// measureText doesn't take scaling spans into account so using a StaticLayout to measure
|
||||
// the actual text width, then use a different StaticLayout to draw the text onto a Bitmap.
|
||||
int measureTextWidth = (int) textPaint.measureText(text, /* start= */ 0, text.length());
|
||||
StaticLayout widthMeasuringLayout = createStaticLayout(text, textPaint, measureTextWidth);
|
||||
int lineCount = widthMeasuringLayout.getLineCount();
|
||||
float realTextWidth = 0;
|
||||
for (int i = 0; i < lineCount; i++) {
|
||||
realTextWidth += widthMeasuringLayout.getLineWidth(i);
|
||||
}
|
||||
return (int) ceil(realTextWidth);
|
||||
}
|
||||
|
||||
@SuppressLint("InlinedApi") // Inlined Layout constants.
|
||||
private StaticLayout createStaticLayout(SpannableString text, TextPaint textPaint, int width) {
|
||||
return SDK_INT >= 23
|
||||
? Api23.getStaticLayout(text, textPaint, width)
|
||||
: new StaticLayout(
|
||||
text,
|
||||
textPaint,
|
||||
width,
|
||||
Layout.Alignment.ALIGN_NORMAL,
|
||||
Layout.DEFAULT_LINESPACING_MULTIPLIER,
|
||||
Layout.DEFAULT_LINESPACING_ADDITION,
|
||||
/* includepad= */ true);
|
||||
}
|
||||
|
||||
@RequiresApi(23)
|
||||
private static final class Api23 {
|
||||
@DoNotInline
|
||||
|
Binary file not shown.
After Width: | Height: | Size: 520 KiB |
Loading…
x
Reference in New Issue
Block a user