Commit e3228064 by Denise LaFayette

Introduce LanguageFeatureStyle interface to mark language features

parent 49dfe66b
...@@ -29,4 +29,4 @@ package com.google.android.exoplayer2.text.span; ...@@ -29,4 +29,4 @@ package com.google.android.exoplayer2.text.span;
// NOTE: There's no Android layout support for this, so this span currently doesn't extend any // NOTE: There's no Android layout support for this, so this span currently doesn't extend any
// styling superclasses (e.g. MetricAffectingSpan). The only way to render this styling is to // styling superclasses (e.g. MetricAffectingSpan). The only way to render this styling is to
// extract the spans and do the layout manually. // extract the spans and do the layout manually.
public final class HorizontalTextInVerticalContextSpan {} public final class HorizontalTextInVerticalContextSpan implements LanguageFeatureStyle {}
/*
* Copyright 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.android.exoplayer2.text.span;
/**
* Marker interface to mark classes that are language features.
*/
public interface LanguageFeatureStyle {
}
...@@ -30,7 +30,7 @@ package com.google.android.exoplayer2.text.span; ...@@ -30,7 +30,7 @@ package com.google.android.exoplayer2.text.span;
// extract the spans and do the layout manually. // extract the spans and do the layout manually.
// TODO: Consider adding support for parenthetical text to be used when rendering doesn't support // TODO: Consider adding support for parenthetical text to be used when rendering doesn't support
// rubies (e.g. HTML <rp> tag). // rubies (e.g. HTML <rp> tag).
public final class RubySpan { public final class RubySpan implements LanguageFeatureStyle {
/** The ruby text, i.e. the smaller explanatory characters. */ /** The ruby text, i.e. the smaller explanatory characters. */
public final String rubyText; public final String rubyText;
......
...@@ -32,7 +32,7 @@ import java.lang.annotation.Retention; ...@@ -32,7 +32,7 @@ import java.lang.annotation.Retention;
// NOTE: There's no Android layout support for text emphasis, so this span currently doesn't extend // NOTE: There's no Android layout support for text emphasis, so this span currently doesn't extend
// any styling superclasses (e.g. MetricAffectingSpan). The only way to render this emphasis is to // any styling superclasses (e.g. MetricAffectingSpan). The only way to render this emphasis is to
// extract the spans and do the layout manually. // extract the spans and do the layout manually.
public final class TextEmphasisSpan { public final class TextEmphasisSpan implements LanguageFeatureStyle {
/** /**
* The possible mark shapes that can be used. * The possible mark shapes that can be used.
......
...@@ -36,6 +36,7 @@ import androidx.annotation.IntDef; ...@@ -36,6 +36,7 @@ import androidx.annotation.IntDef;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import com.google.android.exoplayer2.text.Cue; import com.google.android.exoplayer2.text.Cue;
import com.google.android.exoplayer2.text.TextOutput; import com.google.android.exoplayer2.text.TextOutput;
import com.google.android.exoplayer2.text.span.LanguageFeatureStyle;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
import java.lang.annotation.Documented; import java.lang.annotation.Documented;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
...@@ -374,47 +375,9 @@ public final class SubtitleView extends FrameLayout implements TextOutput { ...@@ -374,47 +375,9 @@ public final class SubtitleView extends FrameLayout implements TextOutput {
} }
List<Cue> strippedCues = new ArrayList<>(cues.size()); List<Cue> strippedCues = new ArrayList<>(cues.size());
for (int i = 0; i < cues.size(); i++) { for (int i = 0; i < cues.size(); i++) {
strippedCues.add(removeEmbeddedStyling(cues.get(i))); strippedCues.add(SubtitleViewUtils
.removeEmbeddedStyling(cues.get(i), applyEmbeddedStyles, applyEmbeddedFontSizes));
} }
return strippedCues; return strippedCues;
} }
private Cue removeEmbeddedStyling(Cue cue) {
@Nullable CharSequence cueText = cue.text;
if (!applyEmbeddedStyles) {
Cue.Builder strippedCue =
cue.buildUpon().setTextSize(Cue.DIMEN_UNSET, Cue.TYPE_UNSET).clearWindowColor();
if (cueText != null) {
// Remove all spans, regardless of type.
strippedCue.setText(new SpannableString(cueText.toString()));
if (cueText instanceof Spanned) {
SubtitleViewUtils
.preserveJapaneseLanguageFeatures((SpannableString)strippedCue.getText(),
(Spanned) cueText);
}
}
return strippedCue.build();
} else if (!applyEmbeddedFontSizes) {
if (cueText == null) {
return cue;
}
Cue.Builder strippedCue = cue.buildUpon().setTextSize(Cue.DIMEN_UNSET, Cue.TYPE_UNSET);
if (cueText instanceof Spanned) {
SpannableString spannable = SpannableString.valueOf(cueText);
AbsoluteSizeSpan[] absSpans =
spannable.getSpans(0, spannable.length(), AbsoluteSizeSpan.class);
for (AbsoluteSizeSpan absSpan : absSpans) {
spannable.removeSpan(absSpan);
}
RelativeSizeSpan[] relSpans =
spannable.getSpans(0, spannable.length(), RelativeSizeSpan.class);
for (RelativeSizeSpan relSpan : relSpans) {
spannable.removeSpan(relSpan);
}
strippedCue.setText(spannable);
}
return strippedCue.build();
}
return cue;
}
} }
...@@ -17,9 +17,15 @@ ...@@ -17,9 +17,15 @@
package com.google.android.exoplayer2.ui; package com.google.android.exoplayer2.ui;
import android.text.Spannable; import android.text.Spannable;
import android.text.SpannableString;
import android.text.Spanned; import android.text.Spanned;
import android.text.style.AbsoluteSizeSpan;
import android.text.style.RelativeSizeSpan;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.google.android.exoplayer2.text.Cue; import com.google.android.exoplayer2.text.Cue;
import com.google.android.exoplayer2.text.span.HorizontalTextInVerticalContextSpan; import com.google.android.exoplayer2.text.span.HorizontalTextInVerticalContextSpan;
import com.google.android.exoplayer2.text.span.LanguageFeatureStyle;
import com.google.android.exoplayer2.text.span.RubySpan; import com.google.android.exoplayer2.text.span.RubySpan;
import com.google.android.exoplayer2.text.span.SpanUtil; import com.google.android.exoplayer2.text.span.SpanUtil;
import com.google.android.exoplayer2.text.span.TextEmphasisSpan; import com.google.android.exoplayer2.text.span.TextEmphasisSpan;
...@@ -54,26 +60,42 @@ import com.google.android.exoplayer2.text.span.TextEmphasisSpan; ...@@ -54,26 +60,42 @@ import com.google.android.exoplayer2.text.span.TextEmphasisSpan;
} }
} }
public static void preserveJapaneseLanguageFeatures(Spannable copy, Spanned original) { /**
RubySpan[] absSpans = * Returns a cue object with the specified styling removed
original.getSpans(0, original.length(), RubySpan.class); * @param cue - Cue object that contains all the styling information
for (RubySpan rubySpan : absSpans) { * @param applyEmbeddedStyles - if true, styles embedded within the cues should be applied
SpanUtil.addOrReplaceSpan(copy, rubySpan, original.getSpanStart(rubySpan), * @param applyEmbeddedFontSizes - if true, font sizes embedded within the cues should be applied.
original.getSpanEnd(rubySpan), original.getSpanFlags(rubySpan)); * Only takes effect if setApplyEmbeddedStyles is true
} * See {@link SubtitleView#setApplyEmbeddedStyles}
TextEmphasisSpan[] textEmphasisSpans = * @return New cue object with the specified styling removed
original.getSpans(0, original.length(), TextEmphasisSpan.class); */
for (TextEmphasisSpan textEmphasisSpan : textEmphasisSpans) { @NonNull
SpanUtil.addOrReplaceSpan(copy, textEmphasisSpan, original.getSpanStart(textEmphasisSpan), static Cue removeEmbeddedStyling(@NonNull Cue cue, boolean applyEmbeddedStyles,
original.getSpanEnd(textEmphasisSpan), original.getSpanFlags(textEmphasisSpan)); boolean applyEmbeddedFontSizes) {
} @Nullable CharSequence cueText = cue.text;
HorizontalTextInVerticalContextSpan[] horizontalTextInVerticalContextSpans = if (cueText != null && (!applyEmbeddedStyles || !applyEmbeddedFontSizes)) {
original.getSpans(0, original.length(), HorizontalTextInVerticalContextSpan.class); Cue.Builder strippedCue = cue.buildUpon().setTextSize(Cue.DIMEN_UNSET, Cue.TYPE_UNSET);
if (!applyEmbeddedStyles) {
for (HorizontalTextInVerticalContextSpan span : horizontalTextInVerticalContextSpans) { strippedCue.clearWindowColor();
SpanUtil.addOrReplaceSpan(copy, span, original.getSpanStart(span), }
original.getSpanEnd(span), original.getSpanFlags(span)); if (cueText instanceof Spanned) {
SpannableString spannable = SpannableString.valueOf(cueText);
Object[] spans = spannable.getSpans(0, spannable.length(), Object.class);
for (Object span : spans) {
if (span instanceof LanguageFeatureStyle) {
continue;
}
// applyEmbeddedFontSizes should only be applied if applyEmbeddedStyles is true
if (!applyEmbeddedStyles || span instanceof AbsoluteSizeSpan
|| span instanceof RelativeSizeSpan) {
spannable.removeSpan(span);
}
}
strippedCue.setText(spannable);
}
return strippedCue.build();
} }
return cue;
} }
private SubtitleViewUtils() {} private SubtitleViewUtils() {}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment