Commit 4ad64547 by Denise LaFayette

Address code review comments

- Refactor TextEmphasis class to support different ordering of styles
- Merge RubySpan.Position and TextEmphasisSpan.Position
- Remove TTML constructs from Spanned classes
parent fcda8d47
Showing with 406 additions and 441 deletions
...@@ -16,12 +16,6 @@ ...@@ -16,12 +16,6 @@
*/ */
package com.google.android.exoplayer2.text.span; package com.google.android.exoplayer2.text.span;
import static java.lang.annotation.RetentionPolicy.SOURCE;
import androidx.annotation.IntDef;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
/** /**
* A styling span for ruby text. * A styling span for ruby text.
* *
...@@ -38,48 +32,14 @@ import java.lang.annotation.Retention; ...@@ -38,48 +32,14 @@ import java.lang.annotation.Retention;
// rubies (e.g. HTML <rp> tag). // rubies (e.g. HTML <rp> tag).
public final class RubySpan { public final class RubySpan {
/** The ruby position is unknown. */
public static final int POSITION_UNKNOWN = -1;
/**
* The ruby text should be positioned above the base text.
*
* <p>For vertical text it should be positioned to the right, same as CSS's <a
* href="https://developer.mozilla.org/en-US/docs/Web/CSS/ruby-position">ruby-position</a>.
*/
public static final int POSITION_OVER = 1;
/**
* The ruby text should be positioned below the base text.
*
* <p>For vertical text it should be positioned to the left, same as CSS's <a
* href="https://developer.mozilla.org/en-US/docs/Web/CSS/ruby-position">ruby-position</a>.
*/
public static final int POSITION_UNDER = 2;
/**
* The possible positions of the ruby text relative to the base text.
*
* <p>One of:
*
* <ul>
* <li>{@link #POSITION_UNKNOWN}
* <li>{@link #POSITION_OVER}
* <li>{@link #POSITION_UNDER}
* </ul>
*/
@Documented
@Retention(SOURCE)
@IntDef({POSITION_UNKNOWN, POSITION_OVER, POSITION_UNDER})
public @interface Position {}
/** 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;
/** The position of the ruby text relative to the base text. */ /** The position of the ruby text relative to the base text. */
@Position public final int position; @TextAnnotation.Position
public final int position;
public RubySpan(String rubyText, @Position int position) { public RubySpan(String rubyText, @TextAnnotation.Position int position) {
this.rubyText = rubyText; this.rubyText = rubyText;
this.position = position; this.position = position;
} }
......
package com.google.android.exoplayer2.text.span;
import static java.lang.annotation.RetentionPolicy.SOURCE;
import androidx.annotation.IntDef;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
/**
* Class used to describe properties of a text annotation (i.e. ruby, text emphasis marks)
*/
public class TextAnnotation {
/** The text annotation position is unknown. */
public static final int POSITION_UNKNOWN = -1;
/**
* For horizontal text, the text annotation should be positioned above the base text.
*
* <p>For vertical text it should be positioned to the right, same as CSS's <a
* href="https://developer.mozilla.org/en-US/docs/Web/CSS/ruby-position">ruby-position</a>.
*/
public static final int POSITION_BEFORE = 1;
/**
* For horizontal text, the text annotation should be positioned below the base text.
*
* <p>For vertical text it should be positioned to the left, same as CSS's <a
* href="https://developer.mozilla.org/en-US/docs/Web/CSS/ruby-position">ruby-position</a>.
*/
public static final int POSITION_AFTER = 2;
/**
* The possible positions of the annotation text relative to the base text.
*
* <p>One of:
*
* <ul>
* <li>{@link #POSITION_UNKNOWN}
* <li>{@link #POSITION_BEFORE}
* <li>{@link #POSITION_AFTER}
* </ul>
*/
@Documented
@Retention(SOURCE)
@IntDef({POSITION_UNKNOWN, POSITION_BEFORE, POSITION_AFTER})
public @interface Position {}
}
...@@ -23,72 +23,22 @@ import java.lang.annotation.Documented; ...@@ -23,72 +23,22 @@ import java.lang.annotation.Documented;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
public final class TextEmphasisSpan { public final class TextEmphasisSpan {
/** // Bits [1:0] are used for typical mark types
* <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/text-emphasis-position">Text Emphasis Position</a> public static final int MARK_FLAG_CIRCLE = 1;
*/ public static final int MARK_FLAG_DOT = 2;
public static final int MARK_FLAG_SESAME = 3;
/**
* The text emphasis position is unknown. If an implementation does not recognize or otherwise // Bit 2 is used for filled/open
* distinguish an annotation position value, then it must be interpreted as if a position of public static final int MARK_FLAG_FILLED = 0;
* before were specified; as such, an implementation that supports text annotation marks must public static final int MARK_FLAG_OPEN = 4;
* minimally support the before value.
*/ // Below are the mark style constants
public static final int POSITION_UNKNOWN = -1; public static final int MARK_FILLED_CIRCLE = MARK_FLAG_CIRCLE | MARK_FLAG_FILLED;
public static final int MARK_FILLED_DOT = MARK_FLAG_DOT | MARK_FLAG_FILLED;
/** public static final int MARK_FILLED_SESAME = MARK_FLAG_SESAME | MARK_FLAG_FILLED;
* The emphasis marks should be positioned above the base text in horizontal writing mode The public static final int MARK_OPEN_CIRCLE = MARK_FLAG_CIRCLE | MARK_FLAG_OPEN;
* emphasis marks should be positioned to the right of the base text in vertical writing mode public static final int MARK_OPEN_DOT = MARK_FLAG_DOT | MARK_FLAG_OPEN;
*/ public static final int MARK_OPEN_SESAME = MARK_FLAG_SESAME | MARK_FLAG_OPEN;
public static final int POSITION_BEFORE = 1;
/**
* The emphasis marks should be positioned below the base text in horizontal writing mode The
* emphasis marks should be positioned to the left of the base text in vertical writing mode
*/
public static final int POSITION_AFTER = 2;
/**
* The text emphasis should be positioned in following way:
*
* <ul>
* <li>Equivalent to {@link #POSITION_BEFORE} for (1) the only line area of or (2) the first line
* area of the last block area generated by a p element which contains annotated text
* <li>otherwise, equivalent to {@link #POSITION_AFTER}
* </ul>
*/
public static final int POSITION_OUTSIDE = 3;
/**
* The possible positions of the emphasis marks relative to the base text.
*
* <p>One of:
*
* <ul>
* <li>{@link #POSITION_UNKNOWN}
* <li>{@link #POSITION_BEFORE}
* <li>{@link #POSITION_AFTER}
* <li>{@link #POSITION_OUTSIDE}
* </ul>
*/
@Documented
@Retention(SOURCE)
@IntDef({POSITION_UNKNOWN, POSITION_BEFORE, POSITION_AFTER, POSITION_OUTSIDE})
public @interface Position {
}
/**
* The text emphasis position is unknown.
*/
public static final int MARK_UNKNOWN = -1;
public static final int MARK_AUTO = 1;
public static final int MARK_FILLED_CIRCLE = 2;
public static final int MARK_FILLED_DOT = 3;
public static final int MARK_FILLED_SESAME = 4;
public static final int MARK_OPEN_CIRCLE = 5;
public static final int MARK_OPEN_DOT = 6;
public static final int MARK_OPEN_SESAME = 7;
/** /**
* The possible types of annotations used. * The possible types of annotations used.
...@@ -96,8 +46,6 @@ public final class TextEmphasisSpan { ...@@ -96,8 +46,6 @@ public final class TextEmphasisSpan {
* <p>One of: * <p>One of:
* *
* <ul> * <ul>
* <li>{@link #MARK_UNKNOWN}
* <li>{@link #MARK_AUTO}
* <li>{@link #MARK_FILLED_CIRCLE} * <li>{@link #MARK_FILLED_CIRCLE}
* <li>{@link #MARK_FILLED_DOT} * <li>{@link #MARK_FILLED_DOT}
* <li>{@link #MARK_FILLED_SESAME} * <li>{@link #MARK_FILLED_SESAME}
...@@ -105,29 +53,31 @@ public final class TextEmphasisSpan { ...@@ -105,29 +53,31 @@ public final class TextEmphasisSpan {
* <li>{@link #MARK_OPEN_DOT} * <li>{@link #MARK_OPEN_DOT}
* <li>{@link #MARK_OPEN_SESAME} * <li>{@link #MARK_OPEN_SESAME}
* </ul> * </ul>
*
* Note: We are intentionally excluding MARK_AUTO here since the auto value should
* be resolved
*/ */
@Documented @Documented
@Retention(SOURCE) @Retention(SOURCE)
@IntDef({MARK_UNKNOWN, MARK_AUTO, MARK_FILLED_CIRCLE, MARK_FILLED_DOT, MARK_FILLED_SESAME, @IntDef({MARK_FILLED_CIRCLE, MARK_FILLED_DOT, MARK_FILLED_SESAME,
MARK_OPEN_CIRCLE, MARK_OPEN_DOT, MARK_OPEN_SESAME}) MARK_OPEN_CIRCLE, MARK_OPEN_DOT, MARK_OPEN_SESAME})
public @interface Mark { public @interface Mark {
} }
/** /**
* The position of the text emphasis relative to the base text * The mark used to emphasis text
*/ */
@TextEmphasisSpan.Position public @TextEmphasisSpan.Mark int mark;
public final int position;
/** /**
* The text emphasis mark * The position of the text emphasis relative to the base text
*/ */
@TextEmphasisSpan.Mark @TextAnnotation.Position
public final int mark; public final int position;
public TextEmphasisSpan(@TextEmphasisSpan.Mark int mark, public TextEmphasisSpan(@TextEmphasisSpan.Mark int mark,
@TextEmphasisSpan.Position int position) { @TextAnnotation.Position int position) {
this.mark = mark; this.mark = mark;
this.position = position; this.position = position;
} }
......
...@@ -16,21 +16,17 @@ ...@@ -16,21 +16,17 @@
*/ */
package com.google.android.exoplayer2.text.ttml; package com.google.android.exoplayer2.text.ttml;
import static com.google.android.exoplayer2.text.span.TextEmphasisSpan.MARK_AUTO; import static java.lang.annotation.RetentionPolicy.SOURCE;
import static com.google.android.exoplayer2.text.span.TextEmphasisSpan.MARK_FILLED_CIRCLE;
import static com.google.android.exoplayer2.text.span.TextEmphasisSpan.MARK_FILLED_DOT; import androidx.annotation.IntDef;
import static com.google.android.exoplayer2.text.span.TextEmphasisSpan.MARK_FILLED_SESAME;
import static com.google.android.exoplayer2.text.span.TextEmphasisSpan.MARK_OPEN_CIRCLE;
import static com.google.android.exoplayer2.text.span.TextEmphasisSpan.MARK_OPEN_DOT;
import static com.google.android.exoplayer2.text.span.TextEmphasisSpan.MARK_OPEN_SESAME;
import static com.google.android.exoplayer2.text.span.TextEmphasisSpan.POSITION_AFTER;
import static com.google.android.exoplayer2.text.span.TextEmphasisSpan.POSITION_BEFORE;
import static com.google.android.exoplayer2.text.span.TextEmphasisSpan.POSITION_OUTSIDE;
import static com.google.android.exoplayer2.text.span.TextEmphasisSpan.POSITION_UNKNOWN;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import com.google.android.exoplayer2.text.span.TextAnnotation;
import com.google.android.exoplayer2.text.span.TextEmphasisSpan; import com.google.android.exoplayer2.text.span.TextEmphasisSpan;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.util.Set;
/** /**
* This class is used to emphasize text using markers above or below the text. For example, markers * This class is used to emphasize text using markers above or below the text. For example, markers
...@@ -42,18 +38,73 @@ import com.google.android.exoplayer2.text.span.TextEmphasisSpan; ...@@ -42,18 +38,73 @@ import com.google.android.exoplayer2.text.span.TextEmphasisSpan;
/* package */ final class TextEmphasis { /* package */ final class TextEmphasis {
/** /**
* The position of the text emphasis relative to the base text. * Mark style to be resolved at rendering time. Hence, it is not defined in
* {@link TextEmphasisSpan.Mark}
*/ */
@TextEmphasisSpan.Position public static final int MARK_AUTO = 1 << 8;
public final int position;
@Documented
@Retention(SOURCE)
@IntDef({TextEmphasisSpan.MARK_FILLED_CIRCLE,
TextEmphasisSpan.MARK_FILLED_DOT,
TextEmphasisSpan.MARK_FILLED_SESAME,
TextEmphasisSpan.MARK_OPEN_CIRCLE,
TextEmphasisSpan.MARK_OPEN_DOT,
TextEmphasisSpan.MARK_OPEN_SESAME,
// Extending the definition in TextEmphasisSpan for intermediate values
MARK_AUTO
})
/* package */ @interface Mark {
}
/**
* The mark style of the text emphasis.
*/
/* package */@Mark
final int mark;
/** /**
* The desired emphasis mark * Position to be resolved at rendering time. Hence, it is not defined in
* {@link TextAnnotation.Position}
*/ */
@TextEmphasisSpan.Mark public static final int POSITION_OUTSIDE = 1 << 8;
public final int mark;
@Documented
@Retention(SOURCE)
@IntDef({TextAnnotation.POSITION_UNKNOWN,
TextAnnotation.POSITION_BEFORE,
TextAnnotation.POSITION_AFTER,
// Extending the definition in TextAnnotation.Position for intermediate values
POSITION_OUTSIDE
})
public @interface Position {}
/**
* The position of the text emphasis relative to the base text.
*/
@Position
public final int position;
private TextEmphasis(@TextEmphasisSpan.Mark int mark, @TextEmphasisSpan.Position int position) { private static Set markValues = ImmutableSet.of(
TtmlNode.TEXT_EMPHASIS_AUTO,
TtmlNode.TEXT_EMPHASIS_MARK_DOT,
TtmlNode.TEXT_EMPHASIS_MARK_SESAME,
TtmlNode.TEXT_EMPHASIS_MARK_CIRCLE
);
private static Set markStyles = ImmutableSet.of(
TtmlNode.TEXT_EMPHASIS_MARK_FILLED,
TtmlNode.TEXT_EMPHASIS_MARK_OPEN
);
private static Set positionValues = ImmutableSet.of(
TtmlNode.TEXT_EMPHASIS_POSITION_AFTER,
TtmlNode.TEXT_EMPHASIS_POSITION_BEFORE,
TtmlNode.TEXT_EMPHASIS_POSITION_OUTSIDE
);
private TextEmphasis(@Mark int mark, @TextAnnotation.Position int position) {
this.mark = mark; this.mark = mark;
this.position = position; this.position = position;
} }
...@@ -76,126 +127,65 @@ import com.google.android.exoplayer2.text.span.TextEmphasisSpan; ...@@ -76,126 +127,65 @@ import com.google.android.exoplayer2.text.span.TextEmphasisSpan;
return null; return null;
} }
String[] nodes = parsingValue.split("\\s+"); Set<String> nodes = Sets.newHashSet(parsingValue.split("\\s+"));
switch (nodes.length) { if (nodes.size() == 0 || TtmlNode.TEXT_EMPHASIS_NONE.equals(nodes.iterator().next())) {
case 0:
return null; return null;
case 1:
return handleOneNode(nodes[0]);
case 2:
return handleTwoNodes(nodes[0], nodes[1]);
default:
// We ignore anything after third entry in value
return handleThreeNodes(nodes[0], nodes[1], nodes[2]);
} }
return parseNodes(nodes);
} }
private static @Nullable private static @Nullable TextEmphasis parseNodes(Set<String> nodes) {
TextEmphasis handleOneNode(@NonNull String value) { Set styleSet = Sets.intersection(markStyles, nodes).immutableCopy();
Set markSet = Sets.intersection(markValues, nodes).immutableCopy();
if (TtmlNode.TEXT_EMPHASIS_NONE.equals(value)) { Set positionSet = Sets.intersection(positionValues, nodes).immutableCopy();
return null;
}
// Handle "auto" or unknown value @Mark int mark = 0;
// If an implementation does not recognize or otherwise distinguish an emphasis style value, if (styleSet.size() == 1) {
// then it must be interpreted as if a style of auto were specified; as such, an implementation mark |= TtmlNode.TEXT_EMPHASIS_MARK_OPEN.equals(styleSet.iterator().next())
// that supports text emphasis marks must minimally support the auto value. ? TextEmphasisSpan.MARK_FLAG_OPEN
return new TextEmphasis(MARK_AUTO, POSITION_UNKNOWN); : TextEmphasisSpan.MARK_FLAG_FILLED;
} }
if (markSet.size() == 1) {
private static @Nullable switch ((String) markSet.iterator().next()) {
TextEmphasis handleTwoNodes(@NonNull String mark, @NonNull String position) {
@TextEmphasisSpan.Position int positionEntry = getPosition(position);
@TextEmphasisSpan.Mark int markEntry;
switch (mark) {
case TtmlNode.TEXT_EMPHASIS_AUTO: case TtmlNode.TEXT_EMPHASIS_AUTO:
markEntry = MARK_AUTO; mark |= MARK_AUTO;
break; break;
// If only circle, dot, or sesame is specified, then it is equivalent to filled circle,
// filled dot, and filled sesame, respectively.
case TtmlNode.TEXT_EMPHASIS_MARK_DOT: case TtmlNode.TEXT_EMPHASIS_MARK_DOT:
markEntry = MARK_FILLED_DOT; mark |= TextEmphasisSpan.MARK_FLAG_DOT;
break; break;
case TtmlNode.TEXT_EMPHASIS_MARK_SESAME: case TtmlNode.TEXT_EMPHASIS_MARK_SESAME:
markEntry = MARK_FILLED_SESAME; mark |= TextEmphasisSpan.MARK_FLAG_SESAME;
break; break;
case TtmlNode.TEXT_EMPHASIS_MARK_CIRCLE: case TtmlNode.TEXT_EMPHASIS_MARK_CIRCLE:
markEntry = MARK_FILLED_CIRCLE;
break;
default: default:
// This is use case for: "filled dot" when position is not specified. mark |= TextEmphasisSpan.MARK_FLAG_CIRCLE;
return handleWithPosition(mark, position, POSITION_UNKNOWN);
} }
return new TextEmphasis(markEntry, positionEntry);
}
private static @Nullable
TextEmphasis handleWithPosition(@NonNull String markStyle, @Nullable String mark,
@TextEmphasisSpan.Position int position) {
switch (mark) {
case TtmlNode.TEXT_EMPHASIS_MARK_DOT:
if (TtmlNode.TEXT_EMPHASIS_MARK_FILLED.equals(markStyle)) {
return new TextEmphasis(MARK_FILLED_DOT, position);
} else if (TtmlNode.TEXT_EMPHASIS_MARK_OPEN.equals(markStyle)) {
return new TextEmphasis(MARK_OPEN_DOT, position);
} else { } else {
return new TextEmphasis(MARK_FILLED_DOT, position); mark |= TextEmphasisSpan.MARK_FLAG_CIRCLE;
} }
case TtmlNode.TEXT_EMPHASIS_MARK_SESAME: /**
if (TtmlNode.TEXT_EMPHASIS_MARK_FILLED.equals(markStyle)) { * If no emphasis position is specified, then the emphasis position must be interpreted as if
return new TextEmphasis(MARK_FILLED_SESAME, position); * a position of outside were specified.
} else if (TtmlNode.TEXT_EMPHASIS_MARK_OPEN.equals(markStyle)) { * <p>
return new TextEmphasis(MARK_OPEN_SESAME, position); * More information on
} else { * <a href="https://www.w3.org/TR/2018/REC-ttml2-20181108/#style-attribute-textEmphasis">tts:textEmphasis</a>
return new TextEmphasis(MARK_FILLED_SESAME, position); */
} @Position int position = POSITION_OUTSIDE;
if (positionSet.size() == 1) {
case TtmlNode.TEXT_EMPHASIS_MARK_CIRCLE: switch ((String) positionSet.iterator().next()) {
if (TtmlNode.TEXT_EMPHASIS_MARK_FILLED.equals(markStyle)) {
return new TextEmphasis(MARK_FILLED_CIRCLE, position);
} else if (TtmlNode.TEXT_EMPHASIS_MARK_OPEN.equals(markStyle)) {
return new TextEmphasis(MARK_OPEN_CIRCLE, position);
} else {
return new TextEmphasis(MARK_FILLED_CIRCLE, position);
}
default:
// Not supported, default to AUTO.
break;
}
return new TextEmphasis(MARK_AUTO, POSITION_UNKNOWN);
}
private static @Nullable
TextEmphasis handleThreeNodes(@NonNull String markStyle, @NonNull String mark,
@NonNull String position) {
@TextEmphasisSpan.Position int positionEntry = getPosition(position);
return handleWithPosition(markStyle, mark, positionEntry);
}
private static @TextEmphasisSpan.Position
int getPosition(@NonNull String value) {
switch (value) {
case TtmlNode.TEXT_EMPHASIS_POSITION_AFTER: case TtmlNode.TEXT_EMPHASIS_POSITION_AFTER:
return POSITION_AFTER; position = TextAnnotation.POSITION_AFTER;
case TtmlNode.TEXT_EMPHASIS_POSITION_BEFORE: break;
return POSITION_BEFORE;
case TtmlNode.TEXT_EMPHASIS_POSITION_OUTSIDE: case TtmlNode.TEXT_EMPHASIS_POSITION_OUTSIDE:
return POSITION_OUTSIDE; position = POSITION_OUTSIDE;
default:
// ignore
break; break;
case TtmlNode.TEXT_EMPHASIS_POSITION_BEFORE:
default:
position = TextAnnotation.POSITION_BEFORE;
}
} }
return POSITION_UNKNOWN; return new TextEmphasis(mark, position);
} }
} }
...@@ -22,7 +22,7 @@ import com.google.android.exoplayer2.text.Cue; ...@@ -22,7 +22,7 @@ import com.google.android.exoplayer2.text.Cue;
import com.google.android.exoplayer2.text.SimpleSubtitleDecoder; import com.google.android.exoplayer2.text.SimpleSubtitleDecoder;
import com.google.android.exoplayer2.text.Subtitle; import com.google.android.exoplayer2.text.Subtitle;
import com.google.android.exoplayer2.text.SubtitleDecoderException; import com.google.android.exoplayer2.text.SubtitleDecoderException;
import com.google.android.exoplayer2.text.span.RubySpan; import com.google.android.exoplayer2.text.span.TextAnnotation;
import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.ColorParser; import com.google.android.exoplayer2.util.ColorParser;
import com.google.android.exoplayer2.util.Log; import com.google.android.exoplayer2.util.Log;
...@@ -583,10 +583,10 @@ public final class TtmlDecoder extends SimpleSubtitleDecoder { ...@@ -583,10 +583,10 @@ public final class TtmlDecoder extends SimpleSubtitleDecoder {
case TtmlNode.ATTR_TTS_RUBY_POSITION: case TtmlNode.ATTR_TTS_RUBY_POSITION:
switch (Util.toLowerInvariant(attributeValue)) { switch (Util.toLowerInvariant(attributeValue)) {
case TtmlNode.RUBY_BEFORE: case TtmlNode.RUBY_BEFORE:
style = createIfNull(style).setRubyPosition(RubySpan.POSITION_OVER); style = createIfNull(style).setRubyPosition(TextAnnotation.POSITION_BEFORE);
break; break;
case TtmlNode.RUBY_AFTER: case TtmlNode.RUBY_AFTER:
style = createIfNull(style).setRubyPosition(RubySpan.POSITION_UNDER); style = createIfNull(style).setRubyPosition(TextAnnotation.POSITION_AFTER);
break; break;
default: default:
// ignore // ignore
......
...@@ -31,6 +31,7 @@ import com.google.android.exoplayer2.text.Cue; ...@@ -31,6 +31,7 @@ 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.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.TextAnnotation;
import com.google.android.exoplayer2.text.span.TextEmphasisSpan; import com.google.android.exoplayer2.text.span.TextEmphasisSpan;
import com.google.android.exoplayer2.util.Log; import com.google.android.exoplayer2.util.Log;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
...@@ -124,21 +125,36 @@ import java.util.Map; ...@@ -124,21 +125,36 @@ import java.util.Map;
} }
if (style.getTextEmphasis() != null) { if (style.getTextEmphasis() != null) {
TextEmphasis textEmphasis = style.getTextEmphasis(); TextEmphasis textEmphasis = style.getTextEmphasis();
// https://www.w3.org/TR/ttml2/#style-value-emphasis-style /**
// If an implementation does not recognize or otherwise distinguish an emphasis style value, * If an implementation does not recognize or otherwise distinguish an emphasis style value,
// then it must be interpreted as if a style of auto were specified; as such, an * then it must be interpreted as if a style of auto were specified; as such, an
// implementation that supports text emphasis marks must minimally support the auto value. * implementation that supports text emphasis marks must minimally support the auto value.
// If a vertical writing mode applies, then equivalent to filled sesame; otherwise, equivalent * If a vertical writing mode applies, then equivalent to filled sesame; otherwise, equivalent
// to filled circle. * to filled circle.
@TextEmphasisSpan.Mark int mark = textEmphasis.mark; * See https://www.w3.org/TR/ttml2/#style-value-emphasis-style
if (textEmphasis.mark == TextEmphasisSpan.MARK_AUTO */
|| textEmphasis.mark == TextEmphasisSpan.MARK_UNKNOWN) { @TextEmphasis.Mark int mark = textEmphasis.mark;
if (textEmphasis.mark == TextEmphasis.MARK_AUTO) {
mark = (verticalType == Cue.VERTICAL_TYPE_LR || verticalType == Cue.VERTICAL_TYPE_RL) ? mark = (verticalType == Cue.VERTICAL_TYPE_LR || verticalType == Cue.VERTICAL_TYPE_RL) ?
TextEmphasisSpan.MARK_FILLED_SESAME : TextEmphasisSpan.MARK_FILLED_CIRCLE; TextEmphasisSpan.MARK_FILLED_SESAME : TextEmphasisSpan.MARK_FILLED_CIRCLE;
} }
@TextEmphasis.Position int position = textEmphasis.position;
if (textEmphasis.position == TextEmphasis.POSITION_OUTSIDE) {
/**
* Not supported in current implementation
* If an implementation does not recognize or otherwise distinguish an annotation position
* value, then it must be interpreted as if a position of before were specified; as such,
* an implementation that supports text annotation marks must minimally support the before
* value.
* See https://www.w3.org/TR/ttml2/#style-value-annotation-position
*/
position = TextAnnotation.POSITION_BEFORE;
}
SpanUtil.addOrReplaceSpan( SpanUtil.addOrReplaceSpan(
builder, builder,
new TextEmphasisSpan(mark, textEmphasis.position), new TextEmphasisSpan(mark, position),
start, start,
end, end,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
...@@ -165,11 +181,11 @@ import java.util.Map; ...@@ -165,11 +181,11 @@ import java.util.Map;
} }
// TODO: Get rubyPosition from `textNode` when TTML inheritance is implemented. // TODO: Get rubyPosition from `textNode` when TTML inheritance is implemented.
@RubySpan.Position @TextAnnotation.Position
int rubyPosition = int rubyPosition =
containerNode.style != null containerNode.style != null
? containerNode.style.getRubyPosition() ? containerNode.style.getRubyPosition()
: RubySpan.POSITION_UNKNOWN; : TextAnnotation.POSITION_UNKNOWN;
builder.setSpan( builder.setSpan(
new RubySpan(rubyText, rubyPosition), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); new RubySpan(rubyText, rubyPosition), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
break; break;
......
...@@ -20,6 +20,7 @@ import android.text.Layout; ...@@ -20,6 +20,7 @@ import android.text.Layout;
import androidx.annotation.IntDef; import androidx.annotation.IntDef;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import com.google.android.exoplayer2.text.span.RubySpan; import com.google.android.exoplayer2.text.span.RubySpan;
import com.google.android.exoplayer2.text.span.TextAnnotation;
import java.lang.annotation.Documented; import java.lang.annotation.Documented;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
...@@ -83,7 +84,7 @@ import java.lang.annotation.RetentionPolicy; ...@@ -83,7 +84,7 @@ import java.lang.annotation.RetentionPolicy;
private float fontSize; private float fontSize;
@Nullable private String id; @Nullable private String id;
@RubyType private int rubyType; @RubyType private int rubyType;
@RubySpan.Position private int rubyPosition; @TextAnnotation.Position private int rubyPosition;
@Nullable private Layout.Alignment textAlign; @Nullable private Layout.Alignment textAlign;
@OptionalBoolean private int textCombine; @OptionalBoolean private int textCombine;
...@@ -96,7 +97,7 @@ import java.lang.annotation.RetentionPolicy; ...@@ -96,7 +97,7 @@ import java.lang.annotation.RetentionPolicy;
italic = UNSPECIFIED; italic = UNSPECIFIED;
fontSizeUnit = UNSPECIFIED; fontSizeUnit = UNSPECIFIED;
rubyType = UNSPECIFIED; rubyType = UNSPECIFIED;
rubyPosition = RubySpan.POSITION_UNKNOWN; rubyPosition = TextAnnotation.POSITION_UNKNOWN;
textCombine = UNSPECIFIED; textCombine = UNSPECIFIED;
} }
...@@ -227,7 +228,7 @@ import java.lang.annotation.RetentionPolicy; ...@@ -227,7 +228,7 @@ import java.lang.annotation.RetentionPolicy;
if (underline == UNSPECIFIED) { if (underline == UNSPECIFIED) {
underline = ancestor.underline; underline = ancestor.underline;
} }
if (rubyPosition == RubySpan.POSITION_UNKNOWN) { if (rubyPosition == TextAnnotation.POSITION_UNKNOWN) {
rubyPosition = ancestor.rubyPosition; rubyPosition = ancestor.rubyPosition;
} }
if (textAlign == null && ancestor.textAlign != null) { if (textAlign == null && ancestor.textAlign != null) {
...@@ -274,12 +275,12 @@ import java.lang.annotation.RetentionPolicy; ...@@ -274,12 +275,12 @@ import java.lang.annotation.RetentionPolicy;
return rubyType; return rubyType;
} }
public TtmlStyle setRubyPosition(@RubySpan.Position int position) { public TtmlStyle setRubyPosition(@TextAnnotation.Position int position) {
this.rubyPosition = position; this.rubyPosition = position;
return this; return this;
} }
@RubySpan.Position @TextAnnotation.Position
public int getRubyPosition() { public int getRubyPosition() {
return rubyPosition; return rubyPosition;
} }
......
...@@ -18,6 +18,7 @@ package com.google.android.exoplayer2.text.webvtt; ...@@ -18,6 +18,7 @@ package com.google.android.exoplayer2.text.webvtt;
import android.text.TextUtils; import android.text.TextUtils;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import com.google.android.exoplayer2.text.span.RubySpan; import com.google.android.exoplayer2.text.span.RubySpan;
import com.google.android.exoplayer2.text.span.TextAnnotation;
import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.ColorParser; import com.google.android.exoplayer2.util.ColorParser;
import com.google.android.exoplayer2.util.ParsableByteArray; import com.google.android.exoplayer2.util.ParsableByteArray;
...@@ -195,9 +196,9 @@ import java.util.regex.Pattern; ...@@ -195,9 +196,9 @@ import java.util.regex.Pattern;
style.setBackgroundColor(ColorParser.parseCssColor(value)); style.setBackgroundColor(ColorParser.parseCssColor(value));
} else if (PROPERTY_RUBY_POSITION.equals(property)) { } else if (PROPERTY_RUBY_POSITION.equals(property)) {
if (VALUE_OVER.equals(value)) { if (VALUE_OVER.equals(value)) {
style.setRubyPosition(RubySpan.POSITION_OVER); style.setRubyPosition(TextAnnotation.POSITION_BEFORE);
} else if (VALUE_UNDER.equals(value)) { } else if (VALUE_UNDER.equals(value)) {
style.setRubyPosition(RubySpan.POSITION_UNDER); style.setRubyPosition(TextAnnotation.POSITION_AFTER);
} }
} else if (PROPERTY_TEXT_COMBINE_UPRIGHT.equals(property)) { } else if (PROPERTY_TEXT_COMBINE_UPRIGHT.equals(property)) {
style.setCombineUpright(VALUE_ALL.equals(value) || value.startsWith(VALUE_DIGITS)); style.setCombineUpright(VALUE_ALL.equals(value) || value.startsWith(VALUE_DIGITS));
......
...@@ -21,6 +21,7 @@ import androidx.annotation.ColorInt; ...@@ -21,6 +21,7 @@ import androidx.annotation.ColorInt;
import androidx.annotation.IntDef; import androidx.annotation.IntDef;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import com.google.android.exoplayer2.text.span.RubySpan; import com.google.android.exoplayer2.text.span.RubySpan;
import com.google.android.exoplayer2.text.span.TextAnnotation;
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;
...@@ -95,7 +96,7 @@ public final class WebvttCssStyle { ...@@ -95,7 +96,7 @@ public final class WebvttCssStyle {
@OptionalBoolean private int italic; @OptionalBoolean private int italic;
@FontSizeUnit private int fontSizeUnit; @FontSizeUnit private int fontSizeUnit;
private float fontSize; private float fontSize;
@RubySpan.Position private int rubyPosition; @TextAnnotation.Position private int rubyPosition;
private boolean combineUpright; private boolean combineUpright;
public WebvttCssStyle() { public WebvttCssStyle() {
...@@ -111,7 +112,7 @@ public final class WebvttCssStyle { ...@@ -111,7 +112,7 @@ public final class WebvttCssStyle {
bold = UNSPECIFIED; bold = UNSPECIFIED;
italic = UNSPECIFIED; italic = UNSPECIFIED;
fontSizeUnit = UNSPECIFIED; fontSizeUnit = UNSPECIFIED;
rubyPosition = RubySpan.POSITION_UNKNOWN; rubyPosition = TextAnnotation.POSITION_UNKNOWN;
combineUpright = false; combineUpright = false;
} }
...@@ -272,12 +273,12 @@ public final class WebvttCssStyle { ...@@ -272,12 +273,12 @@ public final class WebvttCssStyle {
return fontSize; return fontSize;
} }
public WebvttCssStyle setRubyPosition(@RubySpan.Position int rubyPosition) { public WebvttCssStyle setRubyPosition(@TextAnnotation.Position int rubyPosition) {
this.rubyPosition = rubyPosition; this.rubyPosition = rubyPosition;
return this; return this;
} }
@RubySpan.Position @TextAnnotation.Position
public int getRubyPosition() { public int getRubyPosition() {
return rubyPosition; return rubyPosition;
} }
......
...@@ -39,6 +39,7 @@ import androidx.annotation.Nullable; ...@@ -39,6 +39,7 @@ 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.RubySpan; import com.google.android.exoplayer2.text.span.RubySpan;
import com.google.android.exoplayer2.text.span.TextAnnotation;
import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.Log; import com.google.android.exoplayer2.util.Log;
import com.google.android.exoplayer2.util.ParsableByteArray; import com.google.android.exoplayer2.util.ParsableByteArray;
...@@ -572,7 +573,7 @@ public final class WebvttCueParser { ...@@ -572,7 +573,7 @@ public final class WebvttCueParser {
StartTag startTag, StartTag startTag,
List<Element> nestedElements, List<Element> nestedElements,
List<WebvttCssStyle> styles) { List<WebvttCssStyle> styles) {
@RubySpan.Position int rubyTagPosition = getRubyPosition(styles, cueId, startTag); @TextAnnotation.Position int rubyTagPosition = getRubyPosition(styles, cueId, startTag);
List<Element> sortedNestedElements = new ArrayList<>(nestedElements.size()); List<Element> sortedNestedElements = new ArrayList<>(nestedElements.size());
sortedNestedElements.addAll(nestedElements); sortedNestedElements.addAll(nestedElements);
Collections.sort(sortedNestedElements, Element.BY_START_POSITION_ASC); Collections.sort(sortedNestedElements, Element.BY_START_POSITION_ASC);
...@@ -585,12 +586,12 @@ public final class WebvttCueParser { ...@@ -585,12 +586,12 @@ public final class WebvttCueParser {
Element rubyTextElement = sortedNestedElements.get(i); Element rubyTextElement = sortedNestedElements.get(i);
// Use the <rt> element's ruby-position if set, otherwise the <ruby> element's and otherwise // Use the <rt> element's ruby-position if set, otherwise the <ruby> element's and otherwise
// default to OVER. // default to OVER.
@RubySpan.Position @TextAnnotation.Position
int rubyPosition = int rubyPosition =
firstKnownRubyPosition( firstKnownRubyPosition(
getRubyPosition(styles, cueId, rubyTextElement.startTag), getRubyPosition(styles, cueId, rubyTextElement.startTag),
rubyTagPosition, rubyTagPosition,
RubySpan.POSITION_OVER); TextAnnotation.POSITION_BEFORE);
// Move the rubyText from spannedText into the RubySpan. // Move the rubyText from spannedText into the RubySpan.
int adjustedRubyTextStart = rubyTextElement.startTag.position - deletedCharCount; int adjustedRubyTextStart = rubyTextElement.startTag.position - deletedCharCount;
int adjustedRubyTextEnd = rubyTextElement.endPosition - deletedCharCount; int adjustedRubyTextEnd = rubyTextElement.endPosition - deletedCharCount;
...@@ -607,31 +608,31 @@ public final class WebvttCueParser { ...@@ -607,31 +608,31 @@ public final class WebvttCueParser {
} }
} }
@RubySpan.Position @TextAnnotation.Position
private static int getRubyPosition( private static int getRubyPosition(
List<WebvttCssStyle> styles, @Nullable String cueId, StartTag startTag) { List<WebvttCssStyle> styles, @Nullable String cueId, StartTag startTag) {
List<StyleMatch> styleMatches = getApplicableStyles(styles, cueId, startTag); List<StyleMatch> styleMatches = getApplicableStyles(styles, cueId, startTag);
for (int i = 0; i < styleMatches.size(); i++) { for (int i = 0; i < styleMatches.size(); i++) {
WebvttCssStyle style = styleMatches.get(i).style; WebvttCssStyle style = styleMatches.get(i).style;
if (style.getRubyPosition() != RubySpan.POSITION_UNKNOWN) { if (style.getRubyPosition() != TextAnnotation.POSITION_UNKNOWN) {
return style.getRubyPosition(); return style.getRubyPosition();
} }
} }
return RubySpan.POSITION_UNKNOWN; return TextAnnotation.POSITION_UNKNOWN;
} }
@RubySpan.Position @TextAnnotation.Position
private static int firstKnownRubyPosition( private static int firstKnownRubyPosition(
@RubySpan.Position int position1, @TextAnnotation.Position int position1,
@RubySpan.Position int position2, @TextAnnotation.Position int position2,
@RubySpan.Position int position3) { @TextAnnotation.Position int position3) {
if (position1 != RubySpan.POSITION_UNKNOWN) { if (position1 != TextAnnotation.POSITION_UNKNOWN) {
return position1; return position1;
} }
if (position2 != RubySpan.POSITION_UNKNOWN) { if (position2 != TextAnnotation.POSITION_UNKNOWN) {
return position2; return position2;
} }
if (position3 != RubySpan.POSITION_UNKNOWN) { if (position3 != TextAnnotation.POSITION_UNKNOWN) {
return position3; return position3;
} }
throw new IllegalArgumentException(); throw new IllegalArgumentException();
......
...@@ -5,8 +5,8 @@ import static com.google.common.truth.Truth.assertThat; ...@@ -5,8 +5,8 @@ import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage; import static com.google.common.truth.Truth.assertWithMessage;
import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.google.android.exoplayer2.text.span.TextAnnotation;
import com.google.android.exoplayer2.text.span.TextEmphasisSpan; import com.google.android.exoplayer2.text.span.TextEmphasisSpan;
import com.google.android.exoplayer2.util.Log;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
...@@ -21,7 +21,6 @@ public class TextEmphasisTest { ...@@ -21,7 +21,6 @@ public class TextEmphasisTest {
String value = null; String value = null;
TextEmphasis textEmphasis = createTextEmphasis(value); TextEmphasis textEmphasis = createTextEmphasis(value);
Log.d(TAG, "textEmphasis: " + textEmphasis);
assertWithMessage("Text Emphasis must be null").that(textEmphasis).isNull(); assertWithMessage("Text Emphasis must be null").that(textEmphasis).isNull();
} }
...@@ -30,7 +29,6 @@ public class TextEmphasisTest { ...@@ -30,7 +29,6 @@ public class TextEmphasisTest {
String value = ""; String value = "";
TextEmphasis textEmphasis = createTextEmphasis(value); TextEmphasis textEmphasis = createTextEmphasis(value);
Log.d(TAG, "textEmphasis: " + textEmphasis);
assertWithMessage("Text Emphasis must be null").that(textEmphasis).isNull(); assertWithMessage("Text Emphasis must be null").that(textEmphasis).isNull();
} }
...@@ -39,7 +37,6 @@ public class TextEmphasisTest { ...@@ -39,7 +37,6 @@ public class TextEmphasisTest {
String value = "none"; String value = "none";
TextEmphasis textEmphasis = createTextEmphasis(value); TextEmphasis textEmphasis = createTextEmphasis(value);
Log.d(TAG, "textEmphasis: " + textEmphasis);
assertWithMessage("Text Emphasis must be null").that(textEmphasis).isNull(); assertWithMessage("Text Emphasis must be null").that(textEmphasis).isNull();
} }
...@@ -48,10 +45,9 @@ public class TextEmphasisTest { ...@@ -48,10 +45,9 @@ public class TextEmphasisTest {
String value = "auto"; String value = "auto";
TextEmphasis textEmphasis = createTextEmphasis(value); TextEmphasis textEmphasis = createTextEmphasis(value);
Log.d(TAG, "textEmphasis: " + textEmphasis);
assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull(); assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull();
assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_AUTO); assertThat(textEmphasis.mark).isEqualTo(TextEmphasis.MARK_AUTO);
assertThat(textEmphasis.position).isEqualTo(TextEmphasisSpan.POSITION_UNKNOWN); assertThat(textEmphasis.position).isEqualTo(TextEmphasis.POSITION_OUTSIDE);
} }
@Test @Test
...@@ -59,26 +55,57 @@ public class TextEmphasisTest { ...@@ -59,26 +55,57 @@ public class TextEmphasisTest {
String value = "auto outside"; String value = "auto outside";
TextEmphasis textEmphasis = createTextEmphasis(value); TextEmphasis textEmphasis = createTextEmphasis(value);
Log.d(TAG, "textEmphasis: " + textEmphasis);
assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull(); assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull();
assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_AUTO); assertThat(textEmphasis.mark).isEqualTo(TextEmphasis.MARK_AUTO);
assertThat(textEmphasis.position).isEqualTo(TextEmphasisSpan.POSITION_OUTSIDE); assertThat(textEmphasis.position).isEqualTo(TextEmphasis.POSITION_OUTSIDE);
}
/**
* If only filled or open is specified, then it is equivalent to filled circle and open circle,
* respectively.
*/
@Test
public void testFilled() {
String value = "filled";
TextEmphasis textEmphasis = createTextEmphasis(value);
assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull();
assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_FILLED_CIRCLE);
assertThat(textEmphasis.position).isEqualTo(TextEmphasis.POSITION_OUTSIDE);
}
@Test
public void testOpen() {
String value = "open";
TextEmphasis textEmphasis = createTextEmphasis(value);
assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull();
assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_OPEN_CIRCLE);
assertThat(textEmphasis.position).isEqualTo(TextEmphasis.POSITION_OUTSIDE);
}
@Test
public void testOpenAfter() {
String value = "open after";
TextEmphasis textEmphasis = createTextEmphasis(value);
assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull();
assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_OPEN_CIRCLE);
assertThat(textEmphasis.position).isEqualTo(TextAnnotation.POSITION_AFTER);
} }
/** /**
* If only circle, dot, or sesame is specified, then it is equivalent to filled circle, filled dot, * If only circle, dot, or sesame is specified, then it is equivalent to filled circle, filled dot,
* and filled sesame, respectively. * and filled sesame, respectively.
*/ */
@Test @Test
public void testDotBefore() { public void testDotBefore() {
String value = "dot before"; String value = "dot before";
TextEmphasis textEmphasis = createTextEmphasis(value); TextEmphasis textEmphasis = createTextEmphasis(value);
Log.d(TAG, "textEmphasis: " + textEmphasis);
assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull(); assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull();
assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_FILLED_DOT); assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_FILLED_DOT);
assertThat(textEmphasis.position).isEqualTo(TextEmphasisSpan.POSITION_BEFORE); assertThat(textEmphasis.position).isEqualTo(TextAnnotation.POSITION_BEFORE);
} }
@Test @Test
...@@ -86,10 +113,9 @@ public class TextEmphasisTest { ...@@ -86,10 +113,9 @@ public class TextEmphasisTest {
String value = "circle before"; String value = "circle before";
TextEmphasis textEmphasis = createTextEmphasis(value); TextEmphasis textEmphasis = createTextEmphasis(value);
Log.d(TAG, "textEmphasis: " + textEmphasis);
assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull(); assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull();
assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_FILLED_CIRCLE); assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_FILLED_CIRCLE);
assertThat(textEmphasis.position).isEqualTo(TextEmphasisSpan.POSITION_BEFORE); assertThat(textEmphasis.position).isEqualTo(TextAnnotation.POSITION_BEFORE);
} }
@Test @Test
...@@ -97,10 +123,9 @@ public class TextEmphasisTest { ...@@ -97,10 +123,9 @@ public class TextEmphasisTest {
String value = "sesame before"; String value = "sesame before";
TextEmphasis textEmphasis = createTextEmphasis(value); TextEmphasis textEmphasis = createTextEmphasis(value);
Log.d(TAG, "textEmphasis: " + textEmphasis);
assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull(); assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull();
assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_FILLED_SESAME); assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_FILLED_SESAME);
assertThat(textEmphasis.position).isEqualTo(TextEmphasisSpan.POSITION_BEFORE); assertThat(textEmphasis.position).isEqualTo(TextAnnotation.POSITION_BEFORE);
} }
@Test @Test
...@@ -108,10 +133,9 @@ public class TextEmphasisTest { ...@@ -108,10 +133,9 @@ public class TextEmphasisTest {
String value = "dot AFTER"; String value = "dot AFTER";
TextEmphasis textEmphasis = createTextEmphasis(value); TextEmphasis textEmphasis = createTextEmphasis(value);
Log.d(TAG, "textEmphasis: " + textEmphasis);
assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull(); assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull();
assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_FILLED_DOT); assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_FILLED_DOT);
assertThat(textEmphasis.position).isEqualTo(TextEmphasisSpan.POSITION_AFTER); assertThat(textEmphasis.position).isEqualTo(TextAnnotation.POSITION_AFTER);
} }
@Test @Test
...@@ -119,10 +143,9 @@ public class TextEmphasisTest { ...@@ -119,10 +143,9 @@ public class TextEmphasisTest {
String value = "circle after"; String value = "circle after";
TextEmphasis textEmphasis = createTextEmphasis(value); TextEmphasis textEmphasis = createTextEmphasis(value);
Log.d(TAG, "textEmphasis: " + textEmphasis);
assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull(); assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull();
assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_FILLED_CIRCLE); assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_FILLED_CIRCLE);
assertThat(textEmphasis.position).isEqualTo(TextEmphasisSpan.POSITION_AFTER); assertThat(textEmphasis.position).isEqualTo(TextAnnotation.POSITION_AFTER);
} }
@Test @Test
...@@ -130,10 +153,9 @@ public class TextEmphasisTest { ...@@ -130,10 +153,9 @@ public class TextEmphasisTest {
String value = "sesame aFter"; String value = "sesame aFter";
TextEmphasis textEmphasis = createTextEmphasis(value); TextEmphasis textEmphasis = createTextEmphasis(value);
Log.d(TAG, "textEmphasis: " + textEmphasis);
assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull(); assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull();
assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_FILLED_SESAME); assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_FILLED_SESAME);
assertThat(textEmphasis.position).isEqualTo(TextEmphasisSpan.POSITION_AFTER); assertThat(textEmphasis.position).isEqualTo(TextAnnotation.POSITION_AFTER);
} }
@Test @Test
...@@ -141,10 +163,9 @@ public class TextEmphasisTest { ...@@ -141,10 +163,9 @@ public class TextEmphasisTest {
String value = "dot outside"; String value = "dot outside";
TextEmphasis textEmphasis = createTextEmphasis(value); TextEmphasis textEmphasis = createTextEmphasis(value);
Log.d(TAG, "textEmphasis: " + textEmphasis);
assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull(); assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull();
assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_FILLED_DOT); assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_FILLED_DOT);
assertThat(textEmphasis.position).isEqualTo(TextEmphasisSpan.POSITION_OUTSIDE); assertThat(textEmphasis.position).isEqualTo(TextEmphasis.POSITION_OUTSIDE);
} }
@Test @Test
...@@ -152,10 +173,9 @@ public class TextEmphasisTest { ...@@ -152,10 +173,9 @@ public class TextEmphasisTest {
String value = "circle outside"; String value = "circle outside";
TextEmphasis textEmphasis = createTextEmphasis(value); TextEmphasis textEmphasis = createTextEmphasis(value);
Log.d(TAG, "textEmphasis: " + textEmphasis);
assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull(); assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull();
assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_FILLED_CIRCLE); assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_FILLED_CIRCLE);
assertThat(textEmphasis.position).isEqualTo(TextEmphasisSpan.POSITION_OUTSIDE); assertThat(textEmphasis.position).isEqualTo(TextEmphasis.POSITION_OUTSIDE);
} }
@Test @Test
...@@ -163,10 +183,9 @@ public class TextEmphasisTest { ...@@ -163,10 +183,9 @@ public class TextEmphasisTest {
String value = "sesame outside"; String value = "sesame outside";
TextEmphasis textEmphasis = createTextEmphasis(value); TextEmphasis textEmphasis = createTextEmphasis(value);
Log.d(TAG, "textEmphasis: " + textEmphasis);
assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull(); assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull();
assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_FILLED_SESAME); assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_FILLED_SESAME);
assertThat(textEmphasis.position).isEqualTo(TextEmphasisSpan.POSITION_OUTSIDE); assertThat(textEmphasis.position).isEqualTo(TextEmphasis.POSITION_OUTSIDE);
} }
@Test @Test
...@@ -174,10 +193,9 @@ public class TextEmphasisTest { ...@@ -174,10 +193,9 @@ public class TextEmphasisTest {
String value = "open dot AFTER"; String value = "open dot AFTER";
TextEmphasis textEmphasis = createTextEmphasis(value); TextEmphasis textEmphasis = createTextEmphasis(value);
Log.d(TAG, "textEmphasis: " + textEmphasis);
assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull(); assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull();
assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_OPEN_DOT); assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_OPEN_DOT);
assertThat(textEmphasis.position).isEqualTo(TextEmphasisSpan.POSITION_AFTER); assertThat(textEmphasis.position).isEqualTo(TextAnnotation.POSITION_AFTER);
} }
@Test @Test
...@@ -185,10 +203,9 @@ public class TextEmphasisTest { ...@@ -185,10 +203,9 @@ public class TextEmphasisTest {
String value = "Open circle after"; String value = "Open circle after";
TextEmphasis textEmphasis = createTextEmphasis(value); TextEmphasis textEmphasis = createTextEmphasis(value);
Log.d(TAG, "textEmphasis: " + textEmphasis);
assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull(); assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull();
assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_OPEN_CIRCLE); assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_OPEN_CIRCLE);
assertThat(textEmphasis.position).isEqualTo(TextEmphasisSpan.POSITION_AFTER); assertThat(textEmphasis.position).isEqualTo(TextAnnotation.POSITION_AFTER);
} }
@Test @Test
...@@ -196,10 +213,9 @@ public class TextEmphasisTest { ...@@ -196,10 +213,9 @@ public class TextEmphasisTest {
String value = "open sesame aFter"; String value = "open sesame aFter";
TextEmphasis textEmphasis = createTextEmphasis(value); TextEmphasis textEmphasis = createTextEmphasis(value);
Log.d(TAG, "textEmphasis: " + textEmphasis);
assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull(); assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull();
assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_OPEN_SESAME); assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_OPEN_SESAME);
assertThat(textEmphasis.position).isEqualTo(TextEmphasisSpan.POSITION_AFTER); assertThat(textEmphasis.position).isEqualTo(TextAnnotation.POSITION_AFTER);
} }
@Test @Test
...@@ -207,10 +223,9 @@ public class TextEmphasisTest { ...@@ -207,10 +223,9 @@ public class TextEmphasisTest {
String value = "open dot before"; String value = "open dot before";
TextEmphasis textEmphasis = createTextEmphasis(value); TextEmphasis textEmphasis = createTextEmphasis(value);
Log.d(TAG, "textEmphasis: " + textEmphasis);
assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull(); assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull();
assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_OPEN_DOT); assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_OPEN_DOT);
assertThat(textEmphasis.position).isEqualTo(TextEmphasisSpan.POSITION_BEFORE); assertThat(textEmphasis.position).isEqualTo(TextAnnotation.POSITION_BEFORE);
} }
@Test @Test
...@@ -218,10 +233,9 @@ public class TextEmphasisTest { ...@@ -218,10 +233,9 @@ public class TextEmphasisTest {
String value = "Open circle Before"; String value = "Open circle Before";
TextEmphasis textEmphasis = createTextEmphasis(value); TextEmphasis textEmphasis = createTextEmphasis(value);
Log.d(TAG, "textEmphasis: " + textEmphasis);
assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull(); assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull();
assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_OPEN_CIRCLE); assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_OPEN_CIRCLE);
assertThat(textEmphasis.position).isEqualTo(TextEmphasisSpan.POSITION_BEFORE); assertThat(textEmphasis.position).isEqualTo(TextAnnotation.POSITION_BEFORE);
} }
@Test @Test
...@@ -229,10 +243,9 @@ public class TextEmphasisTest { ...@@ -229,10 +243,9 @@ public class TextEmphasisTest {
String value = "open sesame Before"; String value = "open sesame Before";
TextEmphasis textEmphasis = createTextEmphasis(value); TextEmphasis textEmphasis = createTextEmphasis(value);
Log.d(TAG, "textEmphasis: " + textEmphasis);
assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull(); assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull();
assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_OPEN_SESAME); assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_OPEN_SESAME);
assertThat(textEmphasis.position).isEqualTo(TextEmphasisSpan.POSITION_BEFORE); assertThat(textEmphasis.position).isEqualTo(TextAnnotation.POSITION_BEFORE);
} }
@Test @Test
...@@ -240,10 +253,9 @@ public class TextEmphasisTest { ...@@ -240,10 +253,9 @@ public class TextEmphasisTest {
String value = "open dot Outside"; String value = "open dot Outside";
TextEmphasis textEmphasis = createTextEmphasis(value); TextEmphasis textEmphasis = createTextEmphasis(value);
Log.d(TAG, "textEmphasis: " + textEmphasis);
assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull(); assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull();
assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_OPEN_DOT); assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_OPEN_DOT);
assertThat(textEmphasis.position).isEqualTo(TextEmphasisSpan.POSITION_OUTSIDE); assertThat(textEmphasis.position).isEqualTo(TextEmphasis.POSITION_OUTSIDE);
} }
@Test @Test
...@@ -251,10 +263,9 @@ public class TextEmphasisTest { ...@@ -251,10 +263,9 @@ public class TextEmphasisTest {
String value = "Open circle Outside"; String value = "Open circle Outside";
TextEmphasis textEmphasis = createTextEmphasis(value); TextEmphasis textEmphasis = createTextEmphasis(value);
Log.d(TAG, "textEmphasis: " + textEmphasis);
assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull(); assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull();
assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_OPEN_CIRCLE); assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_OPEN_CIRCLE);
assertThat(textEmphasis.position).isEqualTo(TextEmphasisSpan.POSITION_OUTSIDE); assertThat(textEmphasis.position).isEqualTo(TextEmphasis.POSITION_OUTSIDE);
} }
@Test @Test
...@@ -262,10 +273,9 @@ public class TextEmphasisTest { ...@@ -262,10 +273,9 @@ public class TextEmphasisTest {
String value = "open sesame outside"; String value = "open sesame outside";
TextEmphasis textEmphasis = createTextEmphasis(value); TextEmphasis textEmphasis = createTextEmphasis(value);
Log.d(TAG, "textEmphasis: " + textEmphasis);
assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull(); assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull();
assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_OPEN_SESAME); assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_OPEN_SESAME);
assertThat(textEmphasis.position).isEqualTo(TextEmphasisSpan.POSITION_OUTSIDE); assertThat(textEmphasis.position).isEqualTo(TextEmphasis.POSITION_OUTSIDE);
} }
@Test @Test
...@@ -273,10 +283,9 @@ public class TextEmphasisTest { ...@@ -273,10 +283,9 @@ public class TextEmphasisTest {
String value = "filled dot outside"; String value = "filled dot outside";
TextEmphasis textEmphasis = createTextEmphasis(value); TextEmphasis textEmphasis = createTextEmphasis(value);
Log.d(TAG, "textEmphasis: " + textEmphasis);
assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull(); assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull();
assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_FILLED_DOT); assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_FILLED_DOT);
assertThat(textEmphasis.position).isEqualTo(TextEmphasisSpan.POSITION_OUTSIDE); assertThat(textEmphasis.position).isEqualTo(TextEmphasis.POSITION_OUTSIDE);
} }
@Test @Test
...@@ -284,10 +293,9 @@ public class TextEmphasisTest { ...@@ -284,10 +293,9 @@ public class TextEmphasisTest {
String value = "filled circle outside"; String value = "filled circle outside";
TextEmphasis textEmphasis = createTextEmphasis(value); TextEmphasis textEmphasis = createTextEmphasis(value);
Log.d(TAG, "textEmphasis: " + textEmphasis);
assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull(); assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull();
assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_FILLED_CIRCLE); assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_FILLED_CIRCLE);
assertThat(textEmphasis.position).isEqualTo(TextEmphasisSpan.POSITION_OUTSIDE); assertThat(textEmphasis.position).isEqualTo(TextEmphasis.POSITION_OUTSIDE);
} }
@Test @Test
...@@ -295,10 +303,9 @@ public class TextEmphasisTest { ...@@ -295,10 +303,9 @@ public class TextEmphasisTest {
String value = "filled sesame outside"; String value = "filled sesame outside";
TextEmphasis textEmphasis = createTextEmphasis(value); TextEmphasis textEmphasis = createTextEmphasis(value);
Log.d(TAG, "textEmphasis: " + textEmphasis);
assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull(); assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull();
assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_FILLED_SESAME); assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_FILLED_SESAME);
assertThat(textEmphasis.position).isEqualTo(TextEmphasisSpan.POSITION_OUTSIDE); assertThat(textEmphasis.position).isEqualTo(TextEmphasis.POSITION_OUTSIDE);
} }
@Test @Test
...@@ -306,10 +313,9 @@ public class TextEmphasisTest { ...@@ -306,10 +313,9 @@ public class TextEmphasisTest {
String value = "filled dot After"; String value = "filled dot After";
TextEmphasis textEmphasis = createTextEmphasis(value); TextEmphasis textEmphasis = createTextEmphasis(value);
Log.d(TAG, "textEmphasis: " + textEmphasis);
assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull(); assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull();
assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_FILLED_DOT); assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_FILLED_DOT);
assertThat(textEmphasis.position).isEqualTo(TextEmphasisSpan.POSITION_AFTER); assertThat(textEmphasis.position).isEqualTo(TextAnnotation.POSITION_AFTER);
} }
@Test @Test
...@@ -317,10 +323,9 @@ public class TextEmphasisTest { ...@@ -317,10 +323,9 @@ public class TextEmphasisTest {
String value = "filled circle after"; String value = "filled circle after";
TextEmphasis textEmphasis = createTextEmphasis(value); TextEmphasis textEmphasis = createTextEmphasis(value);
Log.d(TAG, "textEmphasis: " + textEmphasis);
assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull(); assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull();
assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_FILLED_CIRCLE); assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_FILLED_CIRCLE);
assertThat(textEmphasis.position).isEqualTo(TextEmphasisSpan.POSITION_AFTER); assertThat(textEmphasis.position).isEqualTo(TextAnnotation.POSITION_AFTER);
} }
@Test @Test
...@@ -328,10 +333,9 @@ public class TextEmphasisTest { ...@@ -328,10 +333,9 @@ public class TextEmphasisTest {
String value = "filled sesame After"; String value = "filled sesame After";
TextEmphasis textEmphasis = createTextEmphasis(value); TextEmphasis textEmphasis = createTextEmphasis(value);
Log.d(TAG, "textEmphasis: " + textEmphasis);
assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull(); assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull();
assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_FILLED_SESAME); assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_FILLED_SESAME);
assertThat(textEmphasis.position).isEqualTo(TextEmphasisSpan.POSITION_AFTER); assertThat(textEmphasis.position).isEqualTo(TextAnnotation.POSITION_AFTER);
} }
@Test @Test
...@@ -339,10 +343,9 @@ public class TextEmphasisTest { ...@@ -339,10 +343,9 @@ public class TextEmphasisTest {
String value = "filled dot before"; String value = "filled dot before";
TextEmphasis textEmphasis = createTextEmphasis(value); TextEmphasis textEmphasis = createTextEmphasis(value);
Log.d(TAG, "textEmphasis: " + textEmphasis);
assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull(); assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull();
assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_FILLED_DOT); assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_FILLED_DOT);
assertThat(textEmphasis.position).isEqualTo(TextEmphasisSpan.POSITION_BEFORE); assertThat(textEmphasis.position).isEqualTo(TextAnnotation.POSITION_BEFORE);
} }
@Test @Test
...@@ -350,10 +353,9 @@ public class TextEmphasisTest { ...@@ -350,10 +353,9 @@ public class TextEmphasisTest {
String value = "filled circle Before"; String value = "filled circle Before";
TextEmphasis textEmphasis = createTextEmphasis(value); TextEmphasis textEmphasis = createTextEmphasis(value);
Log.d(TAG, "textEmphasis: " + textEmphasis);
assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull(); assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull();
assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_FILLED_CIRCLE); assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_FILLED_CIRCLE);
assertThat(textEmphasis.position).isEqualTo(TextEmphasisSpan.POSITION_BEFORE); assertThat(textEmphasis.position).isEqualTo(TextAnnotation.POSITION_BEFORE);
} }
@Test @Test
...@@ -361,9 +363,28 @@ public class TextEmphasisTest { ...@@ -361,9 +363,28 @@ public class TextEmphasisTest {
String value = "filled sesame Before"; String value = "filled sesame Before";
TextEmphasis textEmphasis = createTextEmphasis(value); TextEmphasis textEmphasis = createTextEmphasis(value);
Log.d(TAG, "textEmphasis: " + textEmphasis);
assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull(); assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull();
assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_FILLED_SESAME); assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_FILLED_SESAME);
assertThat(textEmphasis.position).isEqualTo(TextEmphasisSpan.POSITION_BEFORE); assertThat(textEmphasis.position).isEqualTo(TextAnnotation.POSITION_BEFORE);
}
@Test
public void testBeforeFilledSesame() {
String value = "before filled sesame";
TextEmphasis textEmphasis = createTextEmphasis(value);
assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull();
assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_FILLED_SESAME);
assertThat(textEmphasis.position).isEqualTo(TextAnnotation.POSITION_BEFORE);
}
@Test
public void testBeforeSesameFilled() {
String value = "before sesame filled";
TextEmphasis textEmphasis = createTextEmphasis(value);
assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull();
assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_FILLED_SESAME);
assertThat(textEmphasis.position).isEqualTo(TextAnnotation.POSITION_BEFORE);
} }
} }
...@@ -28,6 +28,7 @@ import com.google.android.exoplayer2.text.Cue; ...@@ -28,6 +28,7 @@ import com.google.android.exoplayer2.text.Cue;
import com.google.android.exoplayer2.text.Subtitle; import com.google.android.exoplayer2.text.Subtitle;
import com.google.android.exoplayer2.text.SubtitleDecoderException; import com.google.android.exoplayer2.text.SubtitleDecoderException;
import com.google.android.exoplayer2.text.span.RubySpan; import com.google.android.exoplayer2.text.span.RubySpan;
import com.google.android.exoplayer2.text.span.TextAnnotation;
import com.google.android.exoplayer2.text.span.TextEmphasisSpan; import com.google.android.exoplayer2.text.span.TextEmphasisSpan;
import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.ColorParser; import com.google.android.exoplayer2.util.ColorParser;
...@@ -648,16 +649,16 @@ public final class TtmlDecoderTest { ...@@ -648,16 +649,16 @@ public final class TtmlDecoderTest {
assertThat(firstCue.toString()).isEqualTo("Cue with annotated text."); assertThat(firstCue.toString()).isEqualTo("Cue with annotated text.");
assertThat(firstCue) assertThat(firstCue)
.hasRubySpanBetween("Cue with ".length(), "Cue with annotated".length()) .hasRubySpanBetween("Cue with ".length(), "Cue with annotated".length())
.withTextAndPosition("1st rubies", RubySpan.POSITION_OVER); .withTextAndPosition("1st rubies", TextAnnotation.POSITION_BEFORE);
assertThat(firstCue) assertThat(firstCue)
.hasRubySpanBetween("Cue with annotated ".length(), "Cue with annotated text".length()) .hasRubySpanBetween("Cue with annotated ".length(), "Cue with annotated text".length())
.withTextAndPosition("2nd rubies", RubySpan.POSITION_UNKNOWN); .withTextAndPosition("2nd rubies", TextAnnotation.POSITION_UNKNOWN);
Spanned secondCue = getOnlyCueTextAtTimeUs(subtitle, 20_000_000); Spanned secondCue = getOnlyCueTextAtTimeUs(subtitle, 20_000_000);
assertThat(secondCue.toString()).isEqualTo("Cue with annotated text."); assertThat(secondCue.toString()).isEqualTo("Cue with annotated text.");
assertThat(secondCue) assertThat(secondCue)
.hasRubySpanBetween("Cue with ".length(), "Cue with annotated".length()) .hasRubySpanBetween("Cue with ".length(), "Cue with annotated".length())
.withTextAndPosition("rubies", RubySpan.POSITION_UNKNOWN); .withTextAndPosition("rubies", TextAnnotation.POSITION_UNKNOWN);
Spanned thirdCue = getOnlyCueTextAtTimeUs(subtitle, 30_000_000); Spanned thirdCue = getOnlyCueTextAtTimeUs(subtitle, 30_000_000);
assertThat(thirdCue.toString()).isEqualTo("Cue with annotated text."); assertThat(thirdCue.toString()).isEqualTo("Cue with annotated text.");
...@@ -681,69 +682,68 @@ public final class TtmlDecoderTest { ...@@ -681,69 +682,68 @@ public final class TtmlDecoderTest {
TtmlSubtitle subtitle = getSubtitle(TEXT_EMPHASIS_FILE); TtmlSubtitle subtitle = getSubtitle(TEXT_EMPHASIS_FILE);
Spanned firstCue = getOnlyCueTextAtTimeUs(subtitle, 10_000_000); Spanned firstCue = getOnlyCueTextAtTimeUs(subtitle, 10_000_000);
assertThat(firstCue) assertThat(firstCue).hasNoSpans();
.hasNoTextEmphasisSpanBetween("None ".length(), "None おはよ".length());
Spanned secondCue = getOnlyCueTextAtTimeUs(subtitle, 20_000_000); Spanned secondCue = getOnlyCueTextAtTimeUs(subtitle, 20_000_000);
assertThat(secondCue) assertThat(secondCue)
.hasTextEmphasisSpanBetween("Auto ".length(), "Auto ございます".length()) .hasTextEmphasisSpanBetween("Auto ".length(), "Auto ございます".length())
.withMarkAndPosition(TextEmphasisSpan.MARK_FILLED_CIRCLE, .withMarkAndPosition(TextEmphasisSpan.MARK_FILLED_CIRCLE,
TextEmphasisSpan.POSITION_UNKNOWN); TextAnnotation.POSITION_BEFORE);
Spanned thirdCue = getOnlyCueTextAtTimeUs(subtitle, 30_000_000); Spanned thirdCue = getOnlyCueTextAtTimeUs(subtitle, 30_000_000);
assertThat(thirdCue) assertThat(thirdCue)
.hasTextEmphasisSpanBetween("Filled circle ".length(), "Filled circle こんばんは".length()) .hasTextEmphasisSpanBetween("Filled circle ".length(), "Filled circle こんばんは".length())
.withMarkAndPosition(TextEmphasisSpan.MARK_FILLED_CIRCLE, .withMarkAndPosition(TextEmphasisSpan.MARK_FILLED_CIRCLE,
TextEmphasisSpan.POSITION_UNKNOWN); TextAnnotation.POSITION_BEFORE);
Spanned fourthCue = getOnlyCueTextAtTimeUs(subtitle, 40_000_000); Spanned fourthCue = getOnlyCueTextAtTimeUs(subtitle, 40_000_000);
assertThat(fourthCue) assertThat(fourthCue)
.hasTextEmphasisSpanBetween("Filled dot ".length(), "Filled dot ございます".length()) .hasTextEmphasisSpanBetween("Filled dot ".length(), "Filled dot ございます".length())
.withMarkAndPosition(TextEmphasisSpan.MARK_FILLED_DOT, TextEmphasisSpan.POSITION_UNKNOWN); .withMarkAndPosition(TextEmphasisSpan.MARK_FILLED_DOT, TextAnnotation.POSITION_BEFORE);
Spanned fifthCue = getOnlyCueTextAtTimeUs(subtitle, 50_000_000); Spanned fifthCue = getOnlyCueTextAtTimeUs(subtitle, 50_000_000);
assertThat(fifthCue) assertThat(fifthCue)
.hasTextEmphasisSpanBetween("Filled sesame ".length(), "Filled sesame おはよ".length()) .hasTextEmphasisSpanBetween("Filled sesame ".length(), "Filled sesame おはよ".length())
.withMarkAndPosition(TextEmphasisSpan.MARK_FILLED_SESAME, .withMarkAndPosition(TextEmphasisSpan.MARK_FILLED_SESAME,
TextEmphasisSpan.POSITION_UNKNOWN); TextAnnotation.POSITION_BEFORE);
Spanned sixthCue = getOnlyCueTextAtTimeUs(subtitle, 60_000_000); Spanned sixthCue = getOnlyCueTextAtTimeUs(subtitle, 60_000_000);
assertThat(sixthCue) assertThat(sixthCue)
.hasTextEmphasisSpanBetween("Open circle before ".length(), .hasTextEmphasisSpanBetween("Open circle before ".length(),
"Open circle before ございます".length()) "Open circle before ございます".length())
.withMarkAndPosition(TextEmphasisSpan.MARK_OPEN_CIRCLE, TextEmphasisSpan.POSITION_BEFORE); .withMarkAndPosition(TextEmphasisSpan.MARK_OPEN_CIRCLE, TextAnnotation.POSITION_BEFORE);
Spanned seventhCue = getOnlyCueTextAtTimeUs(subtitle, 70_000_000); Spanned seventhCue = getOnlyCueTextAtTimeUs(subtitle, 70_000_000);
assertThat(seventhCue) assertThat(seventhCue)
.hasTextEmphasisSpanBetween("Open dot after ".length(), "Open dot after おはよ".length()) .hasTextEmphasisSpanBetween("Open dot after ".length(), "Open dot after おはよ".length())
.withMarkAndPosition(TextEmphasisSpan.MARK_OPEN_DOT, TextEmphasisSpan.POSITION_AFTER); .withMarkAndPosition(TextEmphasisSpan.MARK_OPEN_DOT, TextAnnotation.POSITION_AFTER);
Spanned eighthCue = getOnlyCueTextAtTimeUs(subtitle, 80_000_000); Spanned eighthCue = getOnlyCueTextAtTimeUs(subtitle, 80_000_000);
assertThat(eighthCue) assertThat(eighthCue)
.hasTextEmphasisSpanBetween("Open sesame outside ".length(), .hasTextEmphasisSpanBetween("Open sesame outside ".length(),
"Open sesame outside ございます".length()) "Open sesame outside ございます".length())
.withMarkAndPosition(TextEmphasisSpan.MARK_OPEN_SESAME, TextEmphasisSpan.POSITION_OUTSIDE); .withMarkAndPosition(TextEmphasisSpan.MARK_OPEN_SESAME, TextAnnotation.POSITION_BEFORE);
Spanned ninthCue = getOnlyCueTextAtTimeUs(subtitle, 90_000_000); Spanned ninthCue = getOnlyCueTextAtTimeUs(subtitle, 90_000_000);
assertThat(ninthCue) assertThat(ninthCue)
.hasTextEmphasisSpanBetween("Auto outside ".length(), "Auto outside おはよ".length()) .hasTextEmphasisSpanBetween("Auto outside ".length(), "Auto outside おはよ".length())
.withMarkAndPosition(TextEmphasisSpan.MARK_FILLED_CIRCLE, .withMarkAndPosition(TextEmphasisSpan.MARK_FILLED_CIRCLE,
TextEmphasisSpan.POSITION_OUTSIDE); TextAnnotation.POSITION_BEFORE);
Spanned tenthCue = getOnlyCueTextAtTimeUs(subtitle, 100_000_000); Spanned tenthCue = getOnlyCueTextAtTimeUs(subtitle, 100_000_000);
assertThat(tenthCue) assertThat(tenthCue)
.hasTextEmphasisSpanBetween("Circle before ".length(), "Circle before ございます".length()) .hasTextEmphasisSpanBetween("Circle before ".length(), "Circle before ございます".length())
.withMarkAndPosition(TextEmphasisSpan.MARK_FILLED_CIRCLE, TextEmphasisSpan.POSITION_BEFORE); .withMarkAndPosition(TextEmphasisSpan.MARK_FILLED_CIRCLE, TextAnnotation.POSITION_BEFORE);
Spanned eleventhCue = getOnlyCueTextAtTimeUs(subtitle, 110_000_000); Spanned eleventhCue = getOnlyCueTextAtTimeUs(subtitle, 110_000_000);
assertThat(eleventhCue) assertThat(eleventhCue)
.hasTextEmphasisSpanBetween("Sesame after ".length(), "Sesame after おはよ".length()) .hasTextEmphasisSpanBetween("Sesame after ".length(), "Sesame after おはよ".length())
.withMarkAndPosition(TextEmphasisSpan.MARK_FILLED_SESAME, TextEmphasisSpan.POSITION_AFTER); .withMarkAndPosition(TextEmphasisSpan.MARK_FILLED_SESAME, TextAnnotation.POSITION_AFTER);
Spanned twelfthCue = getOnlyCueTextAtTimeUs(subtitle, 120_000_000); Spanned twelfthCue = getOnlyCueTextAtTimeUs(subtitle, 120_000_000);
assertThat(twelfthCue) assertThat(twelfthCue)
.hasTextEmphasisSpanBetween("Dot outside ".length(), "Dot outside ございます".length()) .hasTextEmphasisSpanBetween("Dot outside ".length(), "Dot outside ございます".length())
.withMarkAndPosition(TextEmphasisSpan.MARK_FILLED_DOT, TextEmphasisSpan.POSITION_OUTSIDE); .withMarkAndPosition(TextEmphasisSpan.MARK_FILLED_DOT, TextAnnotation.POSITION_BEFORE);
Spanned thirteenthCue = getOnlyCueTextAtTimeUs(subtitle, 130_000_000); Spanned thirteenthCue = getOnlyCueTextAtTimeUs(subtitle, 130_000_000);
assertThat(thirteenthCue) assertThat(thirteenthCue)
...@@ -754,25 +754,25 @@ public final class TtmlDecoderTest { ...@@ -754,25 +754,25 @@ public final class TtmlDecoderTest {
assertThat(fourteenthCue) assertThat(fourteenthCue)
.hasTextEmphasisSpanBetween("Auto (TBLR) ".length(), "Auto (TBLR) ございます".length()) .hasTextEmphasisSpanBetween("Auto (TBLR) ".length(), "Auto (TBLR) ございます".length())
.withMarkAndPosition(TextEmphasisSpan.MARK_FILLED_SESAME, .withMarkAndPosition(TextEmphasisSpan.MARK_FILLED_SESAME,
TextEmphasisSpan.POSITION_UNKNOWN); TextAnnotation.POSITION_BEFORE);
Spanned fifteenthCue = getOnlyCueTextAtTimeUs(subtitle, 150_000_000); Spanned fifteenthCue = getOnlyCueTextAtTimeUs(subtitle, 150_000_000);
assertThat(fifteenthCue) assertThat(fifteenthCue)
.hasTextEmphasisSpanBetween("Auto (TBRL) ".length(), "Auto (TBRL) おはよ".length()) .hasTextEmphasisSpanBetween("Auto (TBRL) ".length(), "Auto (TBRL) おはよ".length())
.withMarkAndPosition(TextEmphasisSpan.MARK_FILLED_SESAME, .withMarkAndPosition(TextEmphasisSpan.MARK_FILLED_SESAME,
TextEmphasisSpan.POSITION_UNKNOWN); TextAnnotation.POSITION_BEFORE);
Spanned sixteenthCue = getOnlyCueTextAtTimeUs(subtitle, 160_000_000); Spanned sixteenthCue = getOnlyCueTextAtTimeUs(subtitle, 160_000_000);
assertThat(sixteenthCue) assertThat(sixteenthCue)
.hasTextEmphasisSpanBetween("Auto (TB) ".length(), "Auto (TB) ございます".length()) .hasTextEmphasisSpanBetween("Auto (TB) ".length(), "Auto (TB) ございます".length())
.withMarkAndPosition(TextEmphasisSpan.MARK_FILLED_SESAME, .withMarkAndPosition(TextEmphasisSpan.MARK_FILLED_SESAME,
TextEmphasisSpan.POSITION_UNKNOWN); TextAnnotation.POSITION_BEFORE);
Spanned seventeenthCue = getOnlyCueTextAtTimeUs(subtitle, 170_000_000); Spanned seventeenthCue = getOnlyCueTextAtTimeUs(subtitle, 170_000_000);
assertThat(seventeenthCue) assertThat(seventeenthCue)
.hasTextEmphasisSpanBetween("Auto (LR) ".length(), "Auto (LR) おはよ".length()) .hasTextEmphasisSpanBetween("Auto (LR) ".length(), "Auto (LR) おはよ".length())
.withMarkAndPosition(TextEmphasisSpan.MARK_FILLED_CIRCLE, .withMarkAndPosition(TextEmphasisSpan.MARK_FILLED_CIRCLE,
TextEmphasisSpan.POSITION_UNKNOWN); TextAnnotation.POSITION_BEFORE);
} }
private static Spanned getOnlyCueTextAtTimeUs(Subtitle subtitle, long timeUs) { private static Spanned getOnlyCueTextAtTimeUs(Subtitle subtitle, long timeUs) {
......
...@@ -16,10 +16,9 @@ ...@@ -16,10 +16,9 @@
package com.google.android.exoplayer2.text.ttml; package com.google.android.exoplayer2.text.ttml;
import static android.graphics.Color.BLACK; import static android.graphics.Color.BLACK;
import static com.google.android.exoplayer2.text.span.TextAnnotation.POSITION_BEFORE;
import static com.google.android.exoplayer2.text.span.TextEmphasisSpan.MARK_FILLED_DOT; import static com.google.android.exoplayer2.text.span.TextEmphasisSpan.MARK_FILLED_DOT;
import static com.google.android.exoplayer2.text.span.TextEmphasisSpan.MARK_OPEN_SESAME; import static com.google.android.exoplayer2.text.span.TextEmphasisSpan.MARK_OPEN_SESAME;
import static com.google.android.exoplayer2.text.span.TextEmphasisSpan.POSITION_AFTER;
import static com.google.android.exoplayer2.text.span.TextEmphasisSpan.POSITION_BEFORE;
import static com.google.android.exoplayer2.text.ttml.TtmlStyle.STYLE_BOLD; import static com.google.android.exoplayer2.text.ttml.TtmlStyle.STYLE_BOLD;
import static com.google.android.exoplayer2.text.ttml.TtmlStyle.STYLE_BOLD_ITALIC; import static com.google.android.exoplayer2.text.ttml.TtmlStyle.STYLE_BOLD_ITALIC;
import static com.google.android.exoplayer2.text.ttml.TtmlStyle.STYLE_ITALIC; import static com.google.android.exoplayer2.text.ttml.TtmlStyle.STYLE_ITALIC;
...@@ -32,7 +31,7 @@ import android.graphics.Color; ...@@ -32,7 +31,7 @@ import android.graphics.Color;
import android.text.Layout; import android.text.Layout;
import androidx.annotation.ColorInt; import androidx.annotation.ColorInt;
import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.google.android.exoplayer2.text.span.RubySpan; import com.google.android.exoplayer2.text.span.TextAnnotation;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
...@@ -47,7 +46,7 @@ public final class TtmlStyleTest { ...@@ -47,7 +46,7 @@ public final class TtmlStyleTest {
@TtmlStyle.FontSizeUnit private static final int FONT_SIZE_UNIT = TtmlStyle.FONT_SIZE_UNIT_EM; @TtmlStyle.FontSizeUnit private static final int FONT_SIZE_UNIT = TtmlStyle.FONT_SIZE_UNIT_EM;
@ColorInt private static final int BACKGROUND_COLOR = Color.BLACK; @ColorInt private static final int BACKGROUND_COLOR = Color.BLACK;
private static final int RUBY_TYPE = TtmlStyle.RUBY_TYPE_TEXT; private static final int RUBY_TYPE = TtmlStyle.RUBY_TYPE_TEXT;
private static final int RUBY_POSITION = RubySpan.POSITION_UNDER; private static final int RUBY_POSITION = TextAnnotation.POSITION_AFTER;
private static final Layout.Alignment TEXT_ALIGN = Layout.Alignment.ALIGN_CENTER; private static final Layout.Alignment TEXT_ALIGN = Layout.Alignment.ALIGN_CENTER;
private static final boolean TEXT_COMBINE = true; private static final boolean TEXT_COMBINE = true;
public static final String TEXT_EMPHASIS_STYLE="dot before"; public static final String TEXT_EMPHASIS_STYLE="dot before";
...@@ -233,9 +232,9 @@ public final class TtmlStyleTest { ...@@ -233,9 +232,9 @@ public final class TtmlStyleTest {
public void rubyPosition() { public void rubyPosition() {
TtmlStyle style = new TtmlStyle(); TtmlStyle style = new TtmlStyle();
assertThat(style.getRubyPosition()).isEqualTo(RubySpan.POSITION_UNKNOWN); assertThat(style.getRubyPosition()).isEqualTo(TextAnnotation.POSITION_UNKNOWN);
style.setRubyPosition(RubySpan.POSITION_OVER); style.setRubyPosition(POSITION_BEFORE);
assertThat(style.getRubyPosition()).isEqualTo(RubySpan.POSITION_OVER); assertThat(style.getRubyPosition()).isEqualTo(POSITION_BEFORE);
} }
@Test @Test
...@@ -264,6 +263,6 @@ public final class TtmlStyleTest { ...@@ -264,6 +263,6 @@ public final class TtmlStyleTest {
assertThat(style.getTextEmphasis()).isNull(); assertThat(style.getTextEmphasis()).isNull();
style.setTextEmphasis(TextEmphasis.createTextEmphasis("open sesame after")); style.setTextEmphasis(TextEmphasis.createTextEmphasis("open sesame after"));
assertThat(style.getTextEmphasis().mark).isEqualTo(MARK_OPEN_SESAME); assertThat(style.getTextEmphasis().mark).isEqualTo(MARK_OPEN_SESAME);
assertThat(style.getTextEmphasis().position).isEqualTo(POSITION_AFTER); assertThat(style.getTextEmphasis().position).isEqualTo(TextAnnotation.POSITION_AFTER);
} }
} }
...@@ -27,6 +27,7 @@ import com.google.android.exoplayer2.testutil.TestUtil; ...@@ -27,6 +27,7 @@ import com.google.android.exoplayer2.testutil.TestUtil;
import com.google.android.exoplayer2.text.Cue; import com.google.android.exoplayer2.text.Cue;
import com.google.android.exoplayer2.text.SubtitleDecoderException; import com.google.android.exoplayer2.text.SubtitleDecoderException;
import com.google.android.exoplayer2.text.span.RubySpan; import com.google.android.exoplayer2.text.span.RubySpan;
import com.google.android.exoplayer2.text.span.TextAnnotation;
import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.ColorParser; import com.google.android.exoplayer2.util.ColorParser;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
...@@ -349,7 +350,7 @@ public class WebvttDecoderTest { ...@@ -349,7 +350,7 @@ public class WebvttDecoderTest {
assertThat(firstCue.text.toString()).isEqualTo("Some text with over-ruby."); assertThat(firstCue.text.toString()).isEqualTo("Some text with over-ruby.");
assertThat((Spanned) firstCue.text) assertThat((Spanned) firstCue.text)
.hasRubySpanBetween("Some ".length(), "Some text with over-ruby".length()) .hasRubySpanBetween("Some ".length(), "Some text with over-ruby".length())
.withTextAndPosition("over", RubySpan.POSITION_OVER); .withTextAndPosition("over", TextAnnotation.POSITION_BEFORE);
// Check that `under` is read from CSS and unspecified defaults to `over`. // Check that `under` is read from CSS and unspecified defaults to `over`.
Cue secondCue = Iterables.getOnlyElement(subtitle.getCues(subtitle.getEventTime(2))); Cue secondCue = Iterables.getOnlyElement(subtitle.getCues(subtitle.getEventTime(2)));
...@@ -357,25 +358,25 @@ public class WebvttDecoderTest { ...@@ -357,25 +358,25 @@ public class WebvttDecoderTest {
.isEqualTo("Some text with under-ruby and over-ruby (default)."); .isEqualTo("Some text with under-ruby and over-ruby (default).");
assertThat((Spanned) secondCue.text) assertThat((Spanned) secondCue.text)
.hasRubySpanBetween("Some ".length(), "Some text with under-ruby".length()) .hasRubySpanBetween("Some ".length(), "Some text with under-ruby".length())
.withTextAndPosition("under", RubySpan.POSITION_UNDER); .withTextAndPosition("under", TextAnnotation.POSITION_AFTER);
assertThat((Spanned) secondCue.text) assertThat((Spanned) secondCue.text)
.hasRubySpanBetween( .hasRubySpanBetween(
"Some text with under-ruby and ".length(), "Some text with under-ruby and ".length(),
"Some text with under-ruby and over-ruby (default)".length()) "Some text with under-ruby and over-ruby (default)".length())
.withTextAndPosition("over", RubySpan.POSITION_OVER); .withTextAndPosition("over", TextAnnotation.POSITION_BEFORE);
// Check many <rt> tags with different positions nested in a single <ruby> span. // Check many <rt> tags with different positions nested in a single <ruby> span.
Cue thirdCue = Iterables.getOnlyElement(subtitle.getCues(subtitle.getEventTime(4))); Cue thirdCue = Iterables.getOnlyElement(subtitle.getCues(subtitle.getEventTime(4)));
assertThat(thirdCue.text.toString()).isEqualTo("base1base2base3."); assertThat(thirdCue.text.toString()).isEqualTo("base1base2base3.");
assertThat((Spanned) thirdCue.text) assertThat((Spanned) thirdCue.text)
.hasRubySpanBetween(/* start= */ 0, "base1".length()) .hasRubySpanBetween(/* start= */ 0, "base1".length())
.withTextAndPosition("over1", RubySpan.POSITION_OVER); .withTextAndPosition("over1", TextAnnotation.POSITION_BEFORE);
assertThat((Spanned) thirdCue.text) assertThat((Spanned) thirdCue.text)
.hasRubySpanBetween("base1".length(), "base1base2".length()) .hasRubySpanBetween("base1".length(), "base1base2".length())
.withTextAndPosition("under2", RubySpan.POSITION_UNDER); .withTextAndPosition("under2", TextAnnotation.POSITION_AFTER);
assertThat((Spanned) thirdCue.text) assertThat((Spanned) thirdCue.text)
.hasRubySpanBetween("base1base2".length(), "base1base2base3".length()) .hasRubySpanBetween("base1base2".length(), "base1base2base3".length())
.withTextAndPosition("under3", RubySpan.POSITION_UNDER); .withTextAndPosition("under3", TextAnnotation.POSITION_AFTER);
// Check a <ruby> span with no <rt> tags. // Check a <ruby> span with no <rt> tags.
Cue fourthCue = Iterables.getOnlyElement(subtitle.getCues(subtitle.getEventTime(6))); Cue fourthCue = Iterables.getOnlyElement(subtitle.getCues(subtitle.getEventTime(6)));
......
...@@ -31,6 +31,7 @@ import android.util.SparseArray; ...@@ -31,6 +31,7 @@ import android.util.SparseArray;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import com.google.android.exoplayer2.text.span.HorizontalTextInVerticalContextSpan; import com.google.android.exoplayer2.text.span.HorizontalTextInVerticalContextSpan;
import com.google.android.exoplayer2.text.span.RubySpan; import com.google.android.exoplayer2.text.span.RubySpan;
import com.google.android.exoplayer2.text.span.TextAnnotation;
import com.google.android.exoplayer2.text.span.TextEmphasisSpan; import com.google.android.exoplayer2.text.span.TextEmphasisSpan;
import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
...@@ -187,11 +188,11 @@ import java.util.regex.Pattern; ...@@ -187,11 +188,11 @@ import java.util.regex.Pattern;
} else if (span instanceof RubySpan) { } else if (span instanceof RubySpan) {
RubySpan rubySpan = (RubySpan) span; RubySpan rubySpan = (RubySpan) span;
switch (rubySpan.position) { switch (rubySpan.position) {
case RubySpan.POSITION_OVER: case TextAnnotation.POSITION_BEFORE:
return "<ruby style='ruby-position:over;'>"; return "<ruby style='ruby-position:over;'>";
case RubySpan.POSITION_UNDER: case TextAnnotation.POSITION_AFTER:
return "<ruby style='ruby-position:under;'>"; return "<ruby style='ruby-position:under;'>";
case RubySpan.POSITION_UNKNOWN: case TextAnnotation.POSITION_UNKNOWN:
return "<ruby style='ruby-position:unset;'>"; return "<ruby style='ruby-position:unset;'>";
default: default:
return null; return null;
...@@ -256,23 +257,17 @@ import java.util.regex.Pattern; ...@@ -256,23 +257,17 @@ import java.util.regex.Pattern;
return "open dot"; return "open dot";
case TextEmphasisSpan.MARK_OPEN_SESAME: case TextEmphasisSpan.MARK_OPEN_SESAME:
return "open sesame"; return "open sesame";
case TextEmphasisSpan.MARK_AUTO: // TODO
// https://www.w3.org/TR/ttml2/#style-value-emphasis-style
// If a vertical writing mode applies, then equivalent to filled sesame; otherwise,
// equivalent to filled circle.
case TextEmphasisSpan.MARK_UNKNOWN:
default: default:
return "unset"; return "unset";
} }
} }
private static String getTextEmphasisPosition(@TextEmphasisSpan.Position int position){ private static String getTextEmphasisPosition(@TextAnnotation.Position int position){
switch (position) { switch (position) {
case TextEmphasisSpan.POSITION_AFTER: case TextAnnotation.POSITION_AFTER:
return "under left"; return "under left";
case TextEmphasisSpan.POSITION_UNKNOWN: case TextAnnotation.POSITION_UNKNOWN:
case TextEmphasisSpan.POSITION_BEFORE: case TextAnnotation.POSITION_BEFORE:
case TextEmphasisSpan.POSITION_OUTSIDE: /* Not supported, fallback to "before" */
default: default:
// https://www.w3.org/TR/ttml2/#style-value-annotation-position // https://www.w3.org/TR/ttml2/#style-value-annotation-position
// If an implementation does not recognize or otherwise distinguish an annotation position // If an implementation does not recognize or otherwise distinguish an annotation position
......
...@@ -34,6 +34,7 @@ import androidx.test.core.app.ApplicationProvider; ...@@ -34,6 +34,7 @@ import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.google.android.exoplayer2.text.span.HorizontalTextInVerticalContextSpan; import com.google.android.exoplayer2.text.span.HorizontalTextInVerticalContextSpan;
import com.google.android.exoplayer2.text.span.RubySpan; import com.google.android.exoplayer2.text.span.RubySpan;
import com.google.android.exoplayer2.text.span.TextAnnotation;
import com.google.android.exoplayer2.text.span.TextEmphasisSpan; import com.google.android.exoplayer2.text.span.TextEmphasisSpan;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
...@@ -251,12 +252,12 @@ public class SpannedToHtmlConverterTest { ...@@ -251,12 +252,12 @@ public class SpannedToHtmlConverterTest {
SpannableString spanned = SpannableString spanned =
new SpannableString("String with over-annotated and under-annotated section"); new SpannableString("String with over-annotated and under-annotated section");
spanned.setSpan( spanned.setSpan(
new RubySpan("ruby-text", RubySpan.POSITION_OVER), new RubySpan("ruby-text", TextAnnotation.POSITION_BEFORE),
"String with ".length(), "String with ".length(),
"String with over-annotated".length(), "String with over-annotated".length(),
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
spanned.setSpan( spanned.setSpan(
new RubySpan("non-àscìì-text", RubySpan.POSITION_UNDER), new RubySpan("non-àscìì-text", TextAnnotation.POSITION_AFTER),
"String with over-annotated and ".length(), "String with over-annotated and ".length(),
"String with over-annotated and under-annotated".length(), "String with over-annotated and under-annotated".length(),
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
...@@ -284,13 +285,13 @@ public class SpannedToHtmlConverterTest { ...@@ -284,13 +285,13 @@ public class SpannedToHtmlConverterTest {
public void convert_supportsTextEmphasisSpan() { public void convert_supportsTextEmphasisSpan() {
SpannableString spanned = new SpannableString("Text emphasis おはよ ございます "); SpannableString spanned = new SpannableString("Text emphasis おはよ ございます ");
spanned.setSpan( spanned.setSpan(
new TextEmphasisSpan(TextEmphasisSpan.MARK_FILLED_CIRCLE, TextEmphasisSpan.POSITION_BEFORE), new TextEmphasisSpan(TextEmphasisSpan.MARK_FILLED_CIRCLE, TextAnnotation.POSITION_BEFORE),
"Text emphasis ".length(), "Text emphasis ".length(),
"Text emphasis おはよ".length(), "Text emphasis おはよ".length(),
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
spanned.setSpan( spanned.setSpan(
new TextEmphasisSpan(TextEmphasisSpan.MARK_OPEN_SESAME, TextEmphasisSpan.POSITION_AFTER), new TextEmphasisSpan(TextEmphasisSpan.MARK_OPEN_SESAME, TextAnnotation.POSITION_AFTER),
"Text emphasis おはよ ".length(), "Text emphasis おはよ ".length(),
"Text emphasis おはよ ございます ".length(), "Text emphasis おはよ ございます ".length(),
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
......
...@@ -3,10 +3,10 @@ ...@@ -3,10 +3,10 @@
xmlns:tts="http://www.w3.org/2006/10/ttaf1#style" xmlns:tts="http://www.w3.org/2006/10/ttaf1#style"
xmlns="http://www.w3.org/ns/ttml"> xmlns="http://www.w3.org/ns/ttml">
<head> <head>
<region xml:id="region1" tts:extent="80.000% 80.000%" tts:origin="10.000% 10.000%" tts:writingMode="tbrl"/> <region xml:id="region_tbrl" tts:extent="80.000% 80.000%" tts:origin="10.000% 10.000%" tts:writingMode="tbrl"/>
<region xml:id="region2" tts:extent="80.000% 80.000%" tts:origin="10.000% 10.000%" tts:writingMode="tblr"/> <region xml:id="region_tblr" tts:extent="80.000% 80.000%" tts:origin="10.000% 10.000%" tts:writingMode="tblr"/>
<region xml:id="region3" tts:extent="80.000% 80.000%" tts:origin="10.000% 10.000%" tts:writingMode="tb"/> <region xml:id="region_tb" tts:extent="80.000% 80.000%" tts:origin="10.000% 10.000%" tts:writingMode="tb"/>
<region xml:id="region4" tts:extent="80.000% 80.000%" tts:origin="10.000% 10.000%" tts:writingMode="lr"/> <region xml:id="region_lr" tts:extent="80.000% 80.000%" tts:origin="10.000% 10.000%" tts:writingMode="lr"/>
</head> </head>
<body> <body>
<div> <div>
...@@ -49,16 +49,16 @@ ...@@ -49,16 +49,16 @@
<p begin="130s" end="138s">No textEmphasis property <span>おはよ</span></p> <p begin="130s" end="138s">No textEmphasis property <span>おはよ</span></p>
</div> </div>
<div> <div>
<p begin="140s" end="148s" region="region1">Auto (TBLR) <span tts:textEmphasis="auto">ございます</span></p> <p begin="140s" end="148s" region="region_tbrl">Auto (TBLR) <span tts:textEmphasis="auto">ございます</span></p>
</div> </div>
<div> <div>
<p begin="150s" end="158s" region="region2">Auto (TBRL) <span tts:textEmphasis="auto">おはよ</span></p> <p begin="150s" end="158s" region="region_tblr">Auto (TBRL) <span tts:textEmphasis="auto">おはよ</span></p>
</div> </div>
<div> <div>
<p begin="160s" end="168s" region="region3">Auto (TB) <span tts:textEmphasis="auto">ございます</span></p> <p begin="160s" end="168s" region="region_tb">Auto (TB) <span tts:textEmphasis="auto">ございます</span></p>
</div> </div>
<div> <div>
<p begin="170s" end="178s" region="region4">Auto (LR) <span tts:textEmphasis="auto">おはよ</span></p> <p begin="170s" end="178s" region="region_lr">Auto (LR) <span tts:textEmphasis="auto">おはよ</span></p>
</div> </div>
</body> </body>
......
...@@ -38,6 +38,7 @@ import androidx.annotation.ColorInt; ...@@ -38,6 +38,7 @@ import androidx.annotation.ColorInt;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import com.google.android.exoplayer2.text.span.HorizontalTextInVerticalContextSpan; import com.google.android.exoplayer2.text.span.HorizontalTextInVerticalContextSpan;
import com.google.android.exoplayer2.text.span.RubySpan; import com.google.android.exoplayer2.text.span.RubySpan;
import com.google.android.exoplayer2.text.span.TextAnnotation;
import com.google.android.exoplayer2.text.span.TextEmphasisSpan; import com.google.android.exoplayer2.text.span.TextEmphasisSpan;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
import com.google.common.truth.Fact; import com.google.common.truth.Fact;
...@@ -1075,7 +1076,7 @@ public final class SpannedSubject extends Subject { ...@@ -1075,7 +1076,7 @@ public final class SpannedSubject extends Subject {
* @param position The expected position of the text. * @param position The expected position of the text.
* @return A {@link WithSpanFlags} object for optional additional assertions on the flags. * @return A {@link WithSpanFlags} object for optional additional assertions on the flags.
*/ */
AndSpanFlags withTextAndPosition(String text, @RubySpan.Position int position); AndSpanFlags withTextAndPosition(String text, @TextAnnotation.Position int position);
} }
private static final RubyText ALREADY_FAILED_WITH_TEXT = private static final RubyText ALREADY_FAILED_WITH_TEXT =
...@@ -1099,7 +1100,7 @@ public final class SpannedSubject extends Subject { ...@@ -1099,7 +1100,7 @@ public final class SpannedSubject extends Subject {
} }
@Override @Override
public AndSpanFlags withTextAndPosition(String text, @RubySpan.Position int position) { public AndSpanFlags withTextAndPosition(String text, @TextAnnotation.Position int position) {
List<Integer> matchingSpanFlags = new ArrayList<>(); List<Integer> matchingSpanFlags = new ArrayList<>();
List<TextAndPosition> spanTextsAndPositions = new ArrayList<>(); List<TextAndPosition> spanTextsAndPositions = new ArrayList<>();
for (RubySpan span : actualSpans) { for (RubySpan span : actualSpans) {
...@@ -1116,7 +1117,7 @@ public final class SpannedSubject extends Subject { ...@@ -1116,7 +1117,7 @@ public final class SpannedSubject extends Subject {
private static final class TextAndPosition { private static final class TextAndPosition {
private final String text; private final String text;
@RubySpan.Position private final int position; @TextAnnotation.Position private final int position;
private TextAndPosition(String text, int position) { private TextAndPosition(String text, int position) {
this.text = text; this.text = text;
...@@ -1164,7 +1165,7 @@ public final class SpannedSubject extends Subject { ...@@ -1164,7 +1165,7 @@ public final class SpannedSubject extends Subject {
* @return A {@link WithSpanFlags} object for optional additional assertions on the flags. * @return A {@link WithSpanFlags} object for optional additional assertions on the flags.
*/ */
AndSpanFlags withMarkAndPosition(@TextEmphasisSpan.Mark int mark, AndSpanFlags withMarkAndPosition(@TextEmphasisSpan.Mark int mark,
@TextEmphasisSpan.Position int position); @TextAnnotation.Position int position);
} }
private static final TextEmphasisDescription ALREADY_FAILED_WITH_MARK = private static final TextEmphasisDescription ALREADY_FAILED_WITH_MARK =
...@@ -1189,7 +1190,7 @@ public final class SpannedSubject extends Subject { ...@@ -1189,7 +1190,7 @@ public final class SpannedSubject extends Subject {
@Override @Override
public AndSpanFlags withMarkAndPosition(@TextEmphasisSpan.Mark int mark, public AndSpanFlags withMarkAndPosition(@TextEmphasisSpan.Mark int mark,
@TextEmphasisSpan.Position int position) { @TextAnnotation.Position int position) {
List<Integer> matchingSpanFlags = new ArrayList<>(); List<Integer> matchingSpanFlags = new ArrayList<>();
List<MarkAndPosition> textEmphasisMarksAndPositions = new ArrayList<>(); List<MarkAndPosition> textEmphasisMarksAndPositions = new ArrayList<>();
for (TextEmphasisSpan span : actualSpans) { for (TextEmphasisSpan span : actualSpans) {
...@@ -1208,39 +1209,19 @@ public final class SpannedSubject extends Subject { ...@@ -1208,39 +1209,19 @@ public final class SpannedSubject extends Subject {
@TextEmphasisSpan.Mark @TextEmphasisSpan.Mark
private final int mark; private final int mark;
@TextEmphasisSpan.Position @TextAnnotation.Position
private final int position; private final int position;
private MarkAndPosition(@TextEmphasisSpan.Mark int mark, private MarkAndPosition(@TextEmphasisSpan.Mark int mark,
@TextEmphasisSpan.Position int position) { @TextAnnotation.Position int position) {
this.mark = mark; this.mark = mark;
this.position = position; this.position = position;
} }
@Override @Override
public boolean equals(@Nullable Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
TextEmphasisSubject.MarkAndPosition that = (TextEmphasisSubject.MarkAndPosition) o;
return (position == that.position) && (mark == that.mark);
}
@Override
public int hashCode() {
int result = 34613 * mark + position;
return result;
}
@Override
public String toString() { public String toString() {
return String.format("{mark=%s,position=%s}", mark, position); return String.format("{mark=%s,position=%s}", mark, position);
} }
} }
} }
} }
...@@ -609,23 +609,23 @@ public class SpannedSubjectTest { ...@@ -609,23 +609,23 @@ public class SpannedSubjectTest {
public void rubySpan_success() { public void rubySpan_success() {
SpannableString spannable = SpannableString spannable =
createSpannable( createSpannable(
new RubySpan("ruby text", RubySpan.POSITION_OVER), Spanned.SPAN_INCLUSIVE_EXCLUSIVE); new RubySpan("ruby text", TextAnnotation.POSITION_BEFORE), Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
assertThat(spannable) assertThat(spannable)
.hasRubySpanBetween(SPAN_START, SPAN_END) .hasRubySpanBetween(SPAN_START, SPAN_END)
.withTextAndPosition("ruby text", RubySpan.POSITION_OVER) .withTextAndPosition("ruby text", TextAnnotation.POSITION_BEFORE)
.andFlags(Spanned.SPAN_INCLUSIVE_EXCLUSIVE); .andFlags(Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
} }
@Test @Test
public void rubySpan_wrongEndIndex() { public void rubySpan_wrongEndIndex() {
checkHasSpanFailsDueToIndexMismatch( checkHasSpanFailsDueToIndexMismatch(
new RubySpan("ruby text", RubySpan.POSITION_OVER), SpannedSubject::hasRubySpanBetween); new RubySpan("ruby text", TextAnnotation.POSITION_BEFORE), SpannedSubject::hasRubySpanBetween);
} }
@Test @Test
public void rubySpan_wrongText() { public void rubySpan_wrongText() {
SpannableString spannable = createSpannable(new RubySpan("ruby text", RubySpan.POSITION_OVER)); SpannableString spannable = createSpannable(new RubySpan("ruby text", TextAnnotation.POSITION_BEFORE));
AssertionError expected = AssertionError expected =
expectFailure( expectFailure(
...@@ -633,7 +633,7 @@ public class SpannedSubjectTest { ...@@ -633,7 +633,7 @@ public class SpannedSubjectTest {
whenTesting whenTesting
.that(spannable) .that(spannable)
.hasRubySpanBetween(SPAN_START, SPAN_END) .hasRubySpanBetween(SPAN_START, SPAN_END)
.withTextAndPosition("incorrect text", RubySpan.POSITION_OVER)); .withTextAndPosition("incorrect text", TextAnnotation.POSITION_BEFORE));
assertThat(expected).factValue("value of").contains("rubyTextAndPosition"); assertThat(expected).factValue("value of").contains("rubyTextAndPosition");
assertThat(expected).factValue("expected").contains("text='incorrect text'"); assertThat(expected).factValue("expected").contains("text='incorrect text'");
...@@ -642,7 +642,7 @@ public class SpannedSubjectTest { ...@@ -642,7 +642,7 @@ public class SpannedSubjectTest {
@Test @Test
public void rubySpan_wrongPosition() { public void rubySpan_wrongPosition() {
SpannableString spannable = createSpannable(new RubySpan("ruby text", RubySpan.POSITION_OVER)); SpannableString spannable = createSpannable(new RubySpan("ruby text", TextAnnotation.POSITION_BEFORE));
AssertionError expected = AssertionError expected =
expectFailure( expectFailure(
...@@ -650,27 +650,27 @@ public class SpannedSubjectTest { ...@@ -650,27 +650,27 @@ public class SpannedSubjectTest {
whenTesting whenTesting
.that(spannable) .that(spannable)
.hasRubySpanBetween(SPAN_START, SPAN_END) .hasRubySpanBetween(SPAN_START, SPAN_END)
.withTextAndPosition("ruby text", RubySpan.POSITION_UNDER)); .withTextAndPosition("ruby text", TextAnnotation.POSITION_AFTER));
assertThat(expected).factValue("value of").contains("rubyTextAndPosition"); assertThat(expected).factValue("value of").contains("rubyTextAndPosition");
assertThat(expected).factValue("expected").contains("position=" + RubySpan.POSITION_UNDER); assertThat(expected).factValue("expected").contains("position=" + TextAnnotation.POSITION_AFTER);
assertThat(expected).factValue("but was").contains("position=" + RubySpan.POSITION_OVER); assertThat(expected).factValue("but was").contains("position=" + TextAnnotation.POSITION_BEFORE);
} }
@Test @Test
public void rubySpan_wrongFlags() { public void rubySpan_wrongFlags() {
checkHasSpanFailsDueToFlagMismatch( checkHasSpanFailsDueToFlagMismatch(
new RubySpan("ruby text", RubySpan.POSITION_OVER), new RubySpan("ruby text", TextAnnotation.POSITION_BEFORE),
(subject, start, end) -> (subject, start, end) ->
subject subject
.hasRubySpanBetween(start, end) .hasRubySpanBetween(start, end)
.withTextAndPosition("ruby text", RubySpan.POSITION_OVER)); .withTextAndPosition("ruby text", TextAnnotation.POSITION_BEFORE));
} }
@Test @Test
public void noRubySpan_success() { public void noRubySpan_success() {
SpannableString spannable = SpannableString spannable =
createSpannableWithUnrelatedSpanAnd(new RubySpan("ruby text", RubySpan.POSITION_OVER)); createSpannableWithUnrelatedSpanAnd(new RubySpan("ruby text", TextAnnotation.POSITION_BEFORE));
assertThat(spannable).hasNoRubySpanBetween(UNRELATED_SPAN_START, UNRELATED_SPAN_END); assertThat(spannable).hasNoRubySpanBetween(UNRELATED_SPAN_START, UNRELATED_SPAN_END);
} }
...@@ -678,7 +678,7 @@ public class SpannedSubjectTest { ...@@ -678,7 +678,7 @@ public class SpannedSubjectTest {
@Test @Test
public void noRubySpan_failure() { public void noRubySpan_failure() {
checkHasNoSpanFails( checkHasNoSpanFails(
new RubySpan("ruby text", RubySpan.POSITION_OVER), SpannedSubject::hasNoRubySpanBetween); new RubySpan("ruby text", TextAnnotation.POSITION_BEFORE), SpannedSubject::hasNoRubySpanBetween);
} }
@Test @Test
......
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