Address code review comments

- Split text emphasis mark and style into two IntDefs
- Represent textEmphasis="none" with a span rather than null
- Fixed bugs in the style parsing logic
This commit is contained in:
Denise LaFayette 2021-03-05 12:23:34 -08:00
parent 60a3af8d77
commit f7f40bcb25
9 changed files with 560 additions and 308 deletions

View File

@ -23,51 +23,60 @@ 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 public static final int MARK_SHAPE_NONE = 0;
public static final int MARK_FLAG_CIRCLE = 1; public static final int MARK_SHAPE_CIRCLE = 1;
public static final int MARK_FLAG_DOT = 2; public static final int MARK_SHAPE_DOT = 2;
public static final int MARK_FLAG_SESAME = 3; public static final int MARK_SHAPE_SESAME = 3;
// Bit 2 is used for filled/open
public static final int MARK_FLAG_FILLED = 0;
public static final int MARK_FLAG_OPEN = 4;
// Below are the mark style constants
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;
public static final int MARK_OPEN_CIRCLE = MARK_FLAG_CIRCLE | MARK_FLAG_OPEN;
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;
/** /**
* The possible types of annotations used. * The possible mark shapes that can be used.
* *
* <p>One of: * <p>One of:
* *
* <ul> * <ul>
* <li>{@link #MARK_FILLED_CIRCLE} * <li>{@link #MARK_SHAPE_NONE}
* <li>{@link #MARK_FILLED_DOT} * <li>{@link #MARK_SHAPE_CIRCLE}
* <li>{@link #MARK_FILLED_SESAME} * <li>{@link #MARK_SHAPE_DOT}
* <li>{@link #MARK_OPEN_CIRCLE} * <li>{@link #MARK_SHAPE_SESAME}
* <li>{@link #MARK_OPEN_DOT}
* <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_FILLED_CIRCLE, MARK_FILLED_DOT, MARK_FILLED_SESAME, @IntDef({MARK_SHAPE_NONE, MARK_SHAPE_CIRCLE, MARK_SHAPE_DOT, MARK_SHAPE_SESAME})
MARK_OPEN_CIRCLE, MARK_OPEN_DOT, MARK_OPEN_SESAME}) public @interface MarkShape {
public @interface Mark {
} }
public static final int MARK_FILL_UNSPECIFIED = 0;
public static final int MARK_FILL_FILLED = 1;
public static final int MARK_FILL_OPEN = 2;
/** /**
* The mark used to emphasis text * The possible mark fills that can be used.
*
* <p>One of:
*
* <ul>
* <li>{@link #MARK_FILL_UNSPECIFIED}
* <li>{@link #MARK_FILL_FILLED}
* <li>{@link #MARK_FILL_OPEN}
* </ul>
*/ */
public @TextEmphasisSpan.Mark int mark; @Documented
@Retention(SOURCE)
@IntDef({MARK_FILL_UNSPECIFIED, MARK_FILL_FILLED, MARK_FILL_OPEN})
public @interface MarkFill {
}
/**
* The mark shape used for text emphasis
*/
public @MarkShape int markShape;
/**
* The mark fill for the text emphasis mark
*/
public @MarkShape int markFill;
/** /**
* The position of the text emphasis relative to the base text * The position of the text emphasis relative to the base text
@ -76,9 +85,10 @@ public final class TextEmphasisSpan {
public final int position; public final int position;
public TextEmphasisSpan(@TextEmphasisSpan.Mark int mark, public TextEmphasisSpan(@MarkShape int shape, @MarkFill int fill,
@TextAnnotation.Position int position) { @TextAnnotation.Position int position) {
this.mark = mark; this.markShape = shape;
this.markFill = fill;
this.position = position; this.position = position;
} }
} }

View File

@ -38,33 +38,35 @@ import java.util.Set;
/* package */ final class TextEmphasis { /* package */ final class TextEmphasis {
/** /**
* Mark style to be resolved at rendering time. Hence, it is not defined in * Mark shape AUTO is to be resolved at rendering time. Hence, it is not defined in
* {@link TextEmphasisSpan.Mark} * {@link TextEmphasisSpan.MarkShape}
*/ */
public static final int MARK_AUTO = 1 << 8; public static final int MARK_SHAPE_AUTO = 1 << 8;
@Documented @Documented
@Retention(SOURCE) @Retention(SOURCE)
@IntDef({TextEmphasisSpan.MARK_FILLED_CIRCLE, @IntDef({TextEmphasisSpan.MARK_SHAPE_NONE,
TextEmphasisSpan.MARK_FILLED_DOT, TextEmphasisSpan.MARK_SHAPE_CIRCLE,
TextEmphasisSpan.MARK_FILLED_SESAME, TextEmphasisSpan.MARK_SHAPE_DOT,
TextEmphasisSpan.MARK_OPEN_CIRCLE, TextEmphasisSpan.MARK_SHAPE_SESAME,
TextEmphasisSpan.MARK_OPEN_DOT, // Extending the definition in TextEmphasisSpan.MarkShape for intermediate values
TextEmphasisSpan.MARK_OPEN_SESAME, MARK_SHAPE_AUTO
// Extending the definition in TextEmphasisSpan for intermediate values
MARK_AUTO
}) })
@interface Mark { @interface MarkShape {
} }
@MarkShape
final int markShape;
/** /**
* The mark style of the text emphasis. * The mark style of the text emphasis.
*/ */
@Mark final int mark; @TextEmphasisSpan.MarkFill
final int markFill;
/** /**
* Position to be resolved at rendering time. Hence, it is not defined in * Position OUTSIDE is to be resolved at rendering time. Hence, it is not defined in
* {@link TextAnnotation.Position} * {@link TextAnnotation.Position}
*/ */
static final int POSITION_OUTSIDE = 1 << 8; static final int POSITION_OUTSIDE = 1 << 8;
@ -84,26 +86,32 @@ import java.util.Set;
*/ */
@Position final int position; @Position final int position;
private static Set markValues = ImmutableSet.of( private static final Set<String> singleStyleValues = ImmutableSet.of(
TtmlNode.TEXT_EMPHASIS_AUTO, TtmlNode.TEXT_EMPHASIS_AUTO,
TtmlNode.TEXT_EMPHASIS_NONE
);
private static final Set<String> markShapeValues = ImmutableSet.of(
TtmlNode.TEXT_EMPHASIS_MARK_DOT, TtmlNode.TEXT_EMPHASIS_MARK_DOT,
TtmlNode.TEXT_EMPHASIS_MARK_SESAME, TtmlNode.TEXT_EMPHASIS_MARK_SESAME,
TtmlNode.TEXT_EMPHASIS_MARK_CIRCLE TtmlNode.TEXT_EMPHASIS_MARK_CIRCLE
); );
private static Set markStyles = ImmutableSet.of( private static final Set<String> markFillValues = ImmutableSet.of(
TtmlNode.TEXT_EMPHASIS_MARK_FILLED, TtmlNode.TEXT_EMPHASIS_MARK_FILLED,
TtmlNode.TEXT_EMPHASIS_MARK_OPEN TtmlNode.TEXT_EMPHASIS_MARK_OPEN
); );
private static Set positionValues = ImmutableSet.of( private static final Set<String> positionValues = ImmutableSet.of(
TtmlNode.ANNOTATION_POSITION_AFTER, TtmlNode.ANNOTATION_POSITION_AFTER,
TtmlNode.ANNOTATION_POSITION_BEFORE, TtmlNode.ANNOTATION_POSITION_BEFORE,
TtmlNode.ANNOTATION_POSITION_OUTSIDE TtmlNode.ANNOTATION_POSITION_OUTSIDE
); );
private TextEmphasis(@Mark int mark, @TextAnnotation.Position int position) { private TextEmphasis(@MarkShape int shape, @TextEmphasisSpan.MarkFill int fill,
this.mark = mark; @TextAnnotation.Position int position) {
this.markShape = shape;
this.markFill = fill;
this.position = position; this.position = position;
} }
@ -111,68 +119,83 @@ import java.util.Set;
public String toString() { public String toString() {
return "TextEmphasis{" + return "TextEmphasis{" +
"position=" + position + "position=" + position +
", mark=" + mark + ", markShape=" + markShape +
", markFill=" + markFill +
'}'; '}';
} }
public static TextEmphasis createTextEmphasis(@Nullable String value) { @Nullable public static TextEmphasis createTextEmphasis(@Nullable String value) {
if (value == null) { if (value == null) {
return null; return null;
} }
String parsingValue = value.toLowerCase().trim(); String parsingValue = value.toLowerCase().trim();
if ("".equals(parsingValue)) { if (parsingValue.isEmpty()) {
return null; return null;
} }
Set<String> nodes = Sets.newHashSet(parsingValue.split("\\s+")); Set<String> nodes = Sets.newHashSet(parsingValue.split("\\s+"));
if (nodes.size() == 0) {
if (nodes.size() == 0 || TtmlNode.TEXT_EMPHASIS_NONE.equals(nodes.iterator().next())) {
return null; return null;
} }
return parseNodes(nodes); return parseNodes(nodes);
} }
private static @Nullable TextEmphasis parseNodes(Set<String> nodes) { private static @Nullable TextEmphasis parseNodes(Set<String> nodes) {
Set styleSet = Sets.intersection(markStyles, nodes).immutableCopy(); @MarkShape int markShape;
Set markSet = Sets.intersection(markValues, nodes).immutableCopy(); @TextEmphasisSpan.MarkFill int markFill = TextEmphasisSpan.MARK_FILL_UNSPECIFIED;
Set positionSet = Sets.intersection(positionValues, nodes).immutableCopy(); Set<String> styleSet = Sets.intersection(singleStyleValues, nodes).immutableCopy();
if (styleSet.size() > 0) {
@Mark int mark = 0; // If "none" or "auto" are found in the description, ignore the other style (fill, shape)
if (styleSet.size() == 1) { // attributes.
mark |= TtmlNode.TEXT_EMPHASIS_MARK_OPEN.equals(styleSet.iterator().next()) markShape = TtmlNode.TEXT_EMPHASIS_NONE.equals(styleSet.iterator().next())
? TextEmphasisSpan.MARK_FLAG_OPEN ? TextEmphasisSpan.MARK_SHAPE_NONE : MARK_SHAPE_AUTO;
: TextEmphasisSpan.MARK_FLAG_FILLED; // markFill is ignored when markShape is NONE or AUTO
}
if (markSet.size() == 1) {
switch ((String) markSet.iterator().next()) {
case TtmlNode.TEXT_EMPHASIS_AUTO:
mark |= MARK_AUTO;
break;
case TtmlNode.TEXT_EMPHASIS_MARK_DOT:
mark |= TextEmphasisSpan.MARK_FLAG_DOT;
break;
case TtmlNode.TEXT_EMPHASIS_MARK_SESAME:
mark |= TextEmphasisSpan.MARK_FLAG_SESAME;
break;
case TtmlNode.TEXT_EMPHASIS_MARK_CIRCLE:
default:
mark |= TextEmphasisSpan.MARK_FLAG_CIRCLE;
}
} else { } else {
mark |= TextEmphasisSpan.MARK_FLAG_CIRCLE; Set<String> fillSet = Sets.intersection(markFillValues, nodes).immutableCopy();
Set<String> shapeSet = Sets.intersection(markShapeValues, nodes).immutableCopy();
if (fillSet.size() == 0 && shapeSet.size() == 0) {
// 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
// implementation that supports text emphasis marks must minimally support the auto value.
// https://www.w3.org/TR/ttml2/#style-value-emphasis-style
markShape = MARK_SHAPE_AUTO;
} else {
if (fillSet.size() > 0) {
markFill = TtmlNode.TEXT_EMPHASIS_MARK_OPEN.equals(fillSet.iterator().next())
? TextEmphasisSpan.MARK_FILL_OPEN
: TextEmphasisSpan.MARK_FILL_FILLED;
} else {
markFill = TextEmphasisSpan.MARK_FILL_FILLED;
}
if (shapeSet.size() > 0) {
switch (shapeSet.iterator().next()) {
case TtmlNode.TEXT_EMPHASIS_MARK_DOT:
markShape = TextEmphasisSpan.MARK_SHAPE_DOT;
break;
case TtmlNode.TEXT_EMPHASIS_MARK_SESAME:
markShape = TextEmphasisSpan.MARK_SHAPE_SESAME;
break;
case TtmlNode.TEXT_EMPHASIS_MARK_CIRCLE:
default:
markShape = TextEmphasisSpan.MARK_SHAPE_CIRCLE;
}
} else {
markShape = TextEmphasisSpan.MARK_SHAPE_CIRCLE;
}
}
} }
/** Set<String> positionSet = Sets.intersection(positionValues, nodes).immutableCopy();
* If no emphasis position is specified, then the emphasis position must be interpreted as if
* a position of outside were specified. // If no emphasis position is specified, then the emphasis position must be interpreted as if
* <p> // a position of outside were specified.
* More information on // https://www.w3.org/TR/2018/REC-ttml2-20181108/#style-attribute-textEmphasis
* <a href="https://www.w3.org/TR/2018/REC-ttml2-20181108/#style-attribute-textEmphasis">tts:textEmphasis</a>
*/
@Position int position = POSITION_OUTSIDE; @Position int position = POSITION_OUTSIDE;
if (positionSet.size() == 1) { if (positionSet.size() > 0) {
switch ((String) positionSet.iterator().next()) { switch (positionSet.iterator().next()) {
case TtmlNode.ANNOTATION_POSITION_AFTER: case TtmlNode.ANNOTATION_POSITION_AFTER:
position = TextAnnotation.POSITION_AFTER; position = TextAnnotation.POSITION_AFTER;
break; break;
@ -184,6 +207,6 @@ import java.util.Set;
position = TextAnnotation.POSITION_BEFORE; position = TextAnnotation.POSITION_BEFORE;
} }
} }
return new TextEmphasis(mark, position); return new TextEmphasis(markShape, markFill, position);
} }
} }

View File

@ -129,14 +129,14 @@ import java.util.Map;
* 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.
* See https://www.w3.org/TR/ttml2/#style-value-emphasis-style * See https://www.w3.org/TR/ttml2/#style-value-emphasis-style
*/ */
@TextEmphasis.Mark int mark = textEmphasis.mark; @TextEmphasis.MarkShape int markShape = textEmphasis.markShape;
if (textEmphasis.mark == TextEmphasis.MARK_AUTO) { if (textEmphasis.markShape == TextEmphasis.MARK_SHAPE_AUTO) {
mark = (verticalType == Cue.VERTICAL_TYPE_LR || verticalType == Cue.VERTICAL_TYPE_RL) ? markShape = (verticalType == Cue.VERTICAL_TYPE_LR || verticalType == Cue.VERTICAL_TYPE_RL) ?
TextEmphasisSpan.MARK_FILLED_SESAME : TextEmphasisSpan.MARK_FILLED_CIRCLE; TextEmphasisSpan.MARK_SHAPE_SESAME : TextEmphasisSpan.MARK_SHAPE_CIRCLE;
} }
@TextEmphasis.Position int position = textEmphasis.position; @TextEmphasis.Position int position = textEmphasis.position;
@ -154,7 +154,7 @@ import java.util.Map;
SpanUtil.addOrReplaceSpan( SpanUtil.addOrReplaceSpan(
builder, builder,
new TextEmphasisSpan(mark, position), new TextEmphasisSpan(markShape, textEmphasis.markFill, position),
start, start,
end, end,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

View File

@ -1,16 +1,20 @@
package com.google.android.exoplayer2.text.ttml; package com.google.android.exoplayer2.text.ttml;
import static com.google.android.exoplayer2.text.ttml.TextEmphasis.MARK_SHAPE_AUTO;
import static com.google.android.exoplayer2.text.ttml.TextEmphasis.POSITION_OUTSIDE;
import static com.google.android.exoplayer2.text.ttml.TextEmphasis.createTextEmphasis; import static com.google.android.exoplayer2.text.ttml.TextEmphasis.createTextEmphasis;
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.annotation.Nullable;
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.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;
/** Unit test for {@link TextEmphasis}. */ /**
* Unit test for {@link TextEmphasis}.
*/
@RunWith(AndroidJUnit4.class) @RunWith(AndroidJUnit4.class)
public class TextEmphasisTest { public class TextEmphasisTest {
@ -18,373 +22,542 @@ public class TextEmphasisTest {
@Test @Test
public void testNull() { public void testNull() {
String value = null; @Nullable TextEmphasis textEmphasis = createTextEmphasis(null);
TextEmphasis textEmphasis = createTextEmphasis(value);
assertWithMessage("Text Emphasis must be null").that(textEmphasis).isNull(); assertWithMessage("Text Emphasis must be null").that(textEmphasis).isNull();
} }
@Test @Test
public void testEmpty() { public void testEmpty() {
String value = ""; @Nullable TextEmphasis textEmphasis = createTextEmphasis("");
TextEmphasis textEmphasis = createTextEmphasis(value); assertWithMessage("Text Emphasis must be null").that(textEmphasis).isNull();
}
@Test
public void testEmptyWithWhitespace() {
@Nullable TextEmphasis textEmphasis = createTextEmphasis(" ");
assertWithMessage("Text Emphasis must be null").that(textEmphasis).isNull(); assertWithMessage("Text Emphasis must be null").that(textEmphasis).isNull();
} }
@Test @Test
public void testNone() { public void testNone() {
String value = "none"; String value = "none";
TextEmphasis textEmphasis = createTextEmphasis(value); @Nullable TextEmphasis textEmphasis = createTextEmphasis(value);
assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull();
assertWithMessage("Text Emphasis must be null").that(textEmphasis).isNull(); assertWithMessage("markShape").that(textEmphasis.markShape)
.isEqualTo(TextEmphasisSpan.MARK_SHAPE_NONE);
assertWithMessage("position").that(textEmphasis.position)
.isEqualTo(TextEmphasis.POSITION_OUTSIDE);
} }
@Test @Test
public void testAuto() { public void testAuto() {
String value = "auto"; String value = "auto";
TextEmphasis textEmphasis = createTextEmphasis(value); @Nullable TextEmphasis textEmphasis = createTextEmphasis(value);
assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull(); assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull();
assertThat(textEmphasis.mark).isEqualTo(TextEmphasis.MARK_AUTO); assertWithMessage("markShape").that(textEmphasis.markShape).isEqualTo(MARK_SHAPE_AUTO);
assertThat(textEmphasis.position).isEqualTo(TextEmphasis.POSITION_OUTSIDE); assertWithMessage("markFill").that(textEmphasis.markFill)
.isEqualTo(TextEmphasisSpan.MARK_FILL_UNSPECIFIED);
assertWithMessage("position").that(textEmphasis.position)
.isEqualTo(TextEmphasis.POSITION_OUTSIDE);
} }
@Test
public void testInvalid() {
String value = "invalid";
@Nullable TextEmphasis textEmphasis = createTextEmphasis(value);
assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull();
assertWithMessage("markShape").that(textEmphasis.markShape).isEqualTo(MARK_SHAPE_AUTO);
assertWithMessage("markFill").that(textEmphasis.markFill)
.isEqualTo(TextEmphasisSpan.MARK_FILL_UNSPECIFIED);
assertWithMessage("position").that(textEmphasis.position)
.isEqualTo(TextEmphasis.POSITION_OUTSIDE);
}
@Test @Test
public void testAutoOutside() { public void testAutoOutside() {
String value = "auto outside"; String value = "auto outside";
TextEmphasis textEmphasis = createTextEmphasis(value); @Nullable TextEmphasis textEmphasis = createTextEmphasis(value);
assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull(); assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull();
assertThat(textEmphasis.mark).isEqualTo(TextEmphasis.MARK_AUTO); assertWithMessage("markShape").that(textEmphasis.markShape).isEqualTo(MARK_SHAPE_AUTO);
assertThat(textEmphasis.position).isEqualTo(TextEmphasis.POSITION_OUTSIDE); assertWithMessage("markFill").that(textEmphasis.markFill)
.isEqualTo(TextEmphasisSpan.MARK_FILL_UNSPECIFIED);
assertWithMessage("position").that(textEmphasis.position)
.isEqualTo(TextEmphasis.POSITION_OUTSIDE);
}
@Test
public void testAutoAfter() {
String value = "auto after";
@Nullable TextEmphasis textEmphasis = createTextEmphasis(value);
assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull();
assertWithMessage("markShape").that(textEmphasis.markShape).isEqualTo(MARK_SHAPE_AUTO);
assertWithMessage("markFill").that(textEmphasis.markFill)
.isEqualTo(TextEmphasisSpan.MARK_FILL_UNSPECIFIED);
assertWithMessage("position").that(textEmphasis.position)
.isEqualTo(TextAnnotation.POSITION_AFTER);
} }
/** /**
* If only filled or open is specified, then it is equivalent to filled circle and open circle, * If only filled or open is specified, then it is equivalent to filled circle and open circle,
* respectively. * respectively.
*/ */
@Test @Test
public void testFilled() { public void testFilled() {
String value = "filled"; String value = "filled";
TextEmphasis textEmphasis = createTextEmphasis(value); @Nullable TextEmphasis textEmphasis = createTextEmphasis(value);
assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull(); assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull();
assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_FILLED_CIRCLE); assertWithMessage("markShape").that(textEmphasis.markShape)
assertThat(textEmphasis.position).isEqualTo(TextEmphasis.POSITION_OUTSIDE); .isEqualTo(TextEmphasisSpan.MARK_SHAPE_CIRCLE);
assertWithMessage("markFill").that(textEmphasis.markFill)
.isEqualTo(TextEmphasisSpan.MARK_FILL_FILLED);
assertWithMessage("position").that(textEmphasis.position)
.isEqualTo(TextEmphasis.POSITION_OUTSIDE);
} }
@Test @Test
public void testOpen() { public void testOpen() {
String value = "open"; String value = "open";
TextEmphasis textEmphasis = createTextEmphasis(value); @Nullable TextEmphasis textEmphasis = createTextEmphasis(value);
assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull(); assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull();
assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_OPEN_CIRCLE); assertWithMessage("markShape").that(textEmphasis.markShape)
assertThat(textEmphasis.position).isEqualTo(TextEmphasis.POSITION_OUTSIDE); .isEqualTo(TextEmphasisSpan.MARK_SHAPE_CIRCLE);
assertWithMessage("markFill").that(textEmphasis.markFill)
.isEqualTo(TextEmphasisSpan.MARK_FILL_OPEN);
assertWithMessage("position").that(textEmphasis.position)
.isEqualTo(TextEmphasis.POSITION_OUTSIDE);
} }
@Test @Test
public void testOpenAfter() { public void testOpenAfter() {
String value = "open after"; String value = "open after";
TextEmphasis textEmphasis = createTextEmphasis(value); @Nullable TextEmphasis textEmphasis = createTextEmphasis(value);
assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull(); assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull();
assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_OPEN_CIRCLE); assertWithMessage("markShape").that(textEmphasis.markShape)
assertThat(textEmphasis.position).isEqualTo(TextAnnotation.POSITION_AFTER); .isEqualTo(TextEmphasisSpan.MARK_SHAPE_CIRCLE);
assertWithMessage("markFill").that(textEmphasis.markFill)
.isEqualTo(TextEmphasisSpan.MARK_FILL_OPEN);
assertWithMessage("position").that(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
* and filled sesame, respectively. * dot, and filled sesame, respectively.
*/ */
@Test @Test
public void testDotBefore() { public void testDotBefore() {
String value = "dot before"; String value = "dot before";
TextEmphasis textEmphasis = createTextEmphasis(value); @Nullable TextEmphasis textEmphasis = createTextEmphasis(value);
assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull(); assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull();
assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_FILLED_DOT); assertWithMessage("markShape").that(textEmphasis.markShape)
assertThat(textEmphasis.position).isEqualTo(TextAnnotation.POSITION_BEFORE); .isEqualTo(TextEmphasisSpan.MARK_SHAPE_DOT);
assertWithMessage("markFill").that(textEmphasis.markFill)
.isEqualTo(TextEmphasisSpan.MARK_FILL_FILLED);
assertWithMessage("position").that(textEmphasis.position)
.isEqualTo(TextAnnotation.POSITION_BEFORE);
} }
@Test @Test
public void testCircleBefore() { public void testCircleBefore() {
String value = "circle before"; String value = "circle before";
TextEmphasis textEmphasis = createTextEmphasis(value); @Nullable TextEmphasis textEmphasis = createTextEmphasis(value);
assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull(); assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull();
assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_FILLED_CIRCLE); assertWithMessage("markShape").that(textEmphasis.markShape)
assertThat(textEmphasis.position).isEqualTo(TextAnnotation.POSITION_BEFORE); .isEqualTo(TextEmphasisSpan.MARK_SHAPE_CIRCLE);
assertWithMessage("markFill").that(textEmphasis.markFill)
.isEqualTo(TextEmphasisSpan.MARK_FILL_FILLED);
assertWithMessage("position").that(textEmphasis.position)
.isEqualTo(TextAnnotation.POSITION_BEFORE);
} }
@Test @Test
public void testSesameBefore() { public void testSesameBefore() {
String value = "sesame before"; String value = "sesame before";
TextEmphasis textEmphasis = createTextEmphasis(value); @Nullable TextEmphasis textEmphasis = createTextEmphasis(value);
assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull(); assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull();
assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_FILLED_SESAME); assertWithMessage("markShape").that(textEmphasis.markShape)
assertThat(textEmphasis.position).isEqualTo(TextAnnotation.POSITION_BEFORE); .isEqualTo(TextEmphasisSpan.MARK_SHAPE_SESAME);
assertWithMessage("markFill").that(textEmphasis.markFill)
.isEqualTo(TextEmphasisSpan.MARK_FILL_FILLED);
assertWithMessage("position").that(textEmphasis.position)
.isEqualTo(TextAnnotation.POSITION_BEFORE);
} }
@Test @Test
public void testDotAfter() { public void testDotAfter() {
String value = "dot AFTER"; String value = "dot AFTER";
TextEmphasis textEmphasis = createTextEmphasis(value); @Nullable TextEmphasis textEmphasis = createTextEmphasis(value);
assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull(); assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull();
assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_FILLED_DOT); assertWithMessage("markShape").that(textEmphasis.markShape)
assertThat(textEmphasis.position).isEqualTo(TextAnnotation.POSITION_AFTER); .isEqualTo(TextEmphasisSpan.MARK_SHAPE_DOT);
assertWithMessage("markFill").that(textEmphasis.markFill)
.isEqualTo(TextEmphasisSpan.MARK_FILL_FILLED);
assertWithMessage("position").that(textEmphasis.position)
.isEqualTo(TextAnnotation.POSITION_AFTER);
} }
@Test @Test
public void testCircleAfter() { public void testCircleAfter() {
String value = "circle after"; String value = "circle after";
TextEmphasis textEmphasis = createTextEmphasis(value); @Nullable TextEmphasis textEmphasis = createTextEmphasis(value);
assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull(); assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull();
assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_FILLED_CIRCLE); assertWithMessage("markShape").that(textEmphasis.markShape)
assertThat(textEmphasis.position).isEqualTo(TextAnnotation.POSITION_AFTER); .isEqualTo(TextEmphasisSpan.MARK_SHAPE_CIRCLE);
assertWithMessage("markFill").that(textEmphasis.markFill)
.isEqualTo(TextEmphasisSpan.MARK_FILL_FILLED);
assertWithMessage("position").that(textEmphasis.position)
.isEqualTo(TextAnnotation.POSITION_AFTER);
} }
@Test @Test
public void testSesameAfter() { public void testSesameAfter() {
String value = "sesame aFter"; String value = "sesame aFter";
TextEmphasis textEmphasis = createTextEmphasis(value); @Nullable TextEmphasis textEmphasis = createTextEmphasis(value);
assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull(); assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull();
assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_FILLED_SESAME); assertWithMessage("markShape").that(textEmphasis.markShape)
assertThat(textEmphasis.position).isEqualTo(TextAnnotation.POSITION_AFTER); .isEqualTo(TextEmphasisSpan.MARK_SHAPE_SESAME);
assertWithMessage("markFill").that(textEmphasis.markFill)
.isEqualTo(TextEmphasisSpan.MARK_FILL_FILLED);
assertWithMessage("position").that(textEmphasis.position)
.isEqualTo(TextAnnotation.POSITION_AFTER);
} }
@Test @Test
public void testDotOutside() { public void testDotOutside() {
String value = "dot outside"; String value = "dot outside";
TextEmphasis textEmphasis = createTextEmphasis(value); @Nullable TextEmphasis textEmphasis = createTextEmphasis(value);
assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull(); assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull();
assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_FILLED_DOT); assertWithMessage("markShape").that(textEmphasis.markShape)
assertThat(textEmphasis.position).isEqualTo(TextEmphasis.POSITION_OUTSIDE); .isEqualTo(TextEmphasisSpan.MARK_SHAPE_DOT);
assertWithMessage("markFill").that(textEmphasis.markFill)
.isEqualTo(TextEmphasisSpan.MARK_FILL_FILLED);
assertWithMessage("position").that(textEmphasis.position)
.isEqualTo(TextEmphasis.POSITION_OUTSIDE);
} }
@Test @Test
public void testCircleOutside() { public void testCircleOutside() {
String value = "circle outside"; String value = "circle outside";
TextEmphasis textEmphasis = createTextEmphasis(value); @Nullable TextEmphasis textEmphasis = createTextEmphasis(value);
assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull(); assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull();
assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_FILLED_CIRCLE); assertWithMessage("markShape").that(textEmphasis.markShape)
assertThat(textEmphasis.position).isEqualTo(TextEmphasis.POSITION_OUTSIDE); .isEqualTo(TextEmphasisSpan.MARK_SHAPE_CIRCLE);
assertWithMessage("markFill").that(textEmphasis.markFill)
.isEqualTo(TextEmphasisSpan.MARK_FILL_FILLED);
assertWithMessage("position").that(textEmphasis.position)
.isEqualTo(TextEmphasis.POSITION_OUTSIDE);
} }
@Test @Test
public void testSesameOutside() { public void testSesameOutside() {
String value = "sesame outside"; String value = "sesame outside";
TextEmphasis textEmphasis = createTextEmphasis(value); @Nullable TextEmphasis textEmphasis = createTextEmphasis(value);
assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull(); assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull();
assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_FILLED_SESAME); assertWithMessage("markShape").that(textEmphasis.markShape)
assertThat(textEmphasis.position).isEqualTo(TextEmphasis.POSITION_OUTSIDE); .isEqualTo(TextEmphasisSpan.MARK_SHAPE_SESAME);
assertWithMessage("markFill").that(textEmphasis.markFill)
.isEqualTo(TextEmphasisSpan.MARK_FILL_FILLED);
assertWithMessage("position").that(textEmphasis.position)
.isEqualTo(TextEmphasis.POSITION_OUTSIDE);
} }
@Test @Test
public void testOpenDotAfter() { public void testOpenDotAfter() {
String value = "open dot AFTER"; String value = "open dot AFTER";
TextEmphasis textEmphasis = createTextEmphasis(value); @Nullable TextEmphasis textEmphasis = createTextEmphasis(value);
assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull(); assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull();
assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_OPEN_DOT); assertWithMessage("markShape").that(textEmphasis.markShape)
assertThat(textEmphasis.position).isEqualTo(TextAnnotation.POSITION_AFTER); .isEqualTo(TextEmphasisSpan.MARK_SHAPE_DOT);
assertWithMessage("markFill").that(textEmphasis.markFill)
.isEqualTo(TextEmphasisSpan.MARK_FILL_OPEN);
assertWithMessage("position").that(textEmphasis.position)
.isEqualTo(TextAnnotation.POSITION_AFTER);
} }
@Test @Test
public void testOpenCircleAfter() { public void testOpenCircleAfter() {
String value = "Open circle after"; String value = "Open circle after";
TextEmphasis textEmphasis = createTextEmphasis(value); @Nullable TextEmphasis textEmphasis = createTextEmphasis(value);
assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull(); assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull();
assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_OPEN_CIRCLE); assertWithMessage("markShape").that(textEmphasis.markShape)
assertThat(textEmphasis.position).isEqualTo(TextAnnotation.POSITION_AFTER); .isEqualTo(TextEmphasisSpan.MARK_SHAPE_CIRCLE);
assertWithMessage("markFill").that(textEmphasis.markFill)
.isEqualTo(TextEmphasisSpan.MARK_FILL_OPEN);
assertWithMessage("position").that(textEmphasis.position)
.isEqualTo(TextAnnotation.POSITION_AFTER);
} }
@Test @Test
public void testOpenSesameAfter() { public void testOpenSesameAfter() {
String value = "open sesame aFter"; String value = "open sesame aFter";
TextEmphasis textEmphasis = createTextEmphasis(value); @Nullable TextEmphasis textEmphasis = createTextEmphasis(value);
assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull(); assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull();
assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_OPEN_SESAME); assertWithMessage("markShape").that(textEmphasis.markShape)
assertThat(textEmphasis.position).isEqualTo(TextAnnotation.POSITION_AFTER); .isEqualTo(TextEmphasisSpan.MARK_SHAPE_SESAME);
assertWithMessage("markFill").that(textEmphasis.markFill)
.isEqualTo(TextEmphasisSpan.MARK_FILL_OPEN);
assertWithMessage("position").that(textEmphasis.position)
.isEqualTo(TextAnnotation.POSITION_AFTER);
} }
@Test @Test
public void testOpenDotBefore() { public void testOpenDotBefore() {
String value = "open dot before"; String value = "open dot before";
TextEmphasis textEmphasis = createTextEmphasis(value); @Nullable TextEmphasis textEmphasis = createTextEmphasis(value);
assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull(); assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull();
assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_OPEN_DOT); assertWithMessage("markShape").that(textEmphasis.markShape)
assertThat(textEmphasis.position).isEqualTo(TextAnnotation.POSITION_BEFORE); .isEqualTo(TextEmphasisSpan.MARK_SHAPE_DOT);
assertWithMessage("markFill").that(textEmphasis.markFill)
.isEqualTo(TextEmphasisSpan.MARK_FILL_OPEN);
assertWithMessage("position").that(textEmphasis.position)
.isEqualTo(TextAnnotation.POSITION_BEFORE);
} }
@Test @Test
public void testOpenCircleBefore() { public void testOpenCircleBefore() {
String value = "Open circle Before"; String value = "Open circle Before";
TextEmphasis textEmphasis = createTextEmphasis(value); @Nullable TextEmphasis textEmphasis = createTextEmphasis(value);
assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull(); assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull();
assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_OPEN_CIRCLE); assertWithMessage("markShape").that(textEmphasis.markShape)
assertThat(textEmphasis.position).isEqualTo(TextAnnotation.POSITION_BEFORE); .isEqualTo(TextEmphasisSpan.MARK_SHAPE_CIRCLE);
assertWithMessage("markFill").that(textEmphasis.markFill)
.isEqualTo(TextEmphasisSpan.MARK_FILL_OPEN);
assertWithMessage("position").that(textEmphasis.position)
.isEqualTo(TextAnnotation.POSITION_BEFORE);
} }
@Test @Test
public void testOpenSesameBefore() { public void testOpenSesameBefore() {
String value = "open sesame Before"; String value = "open sesame Before";
TextEmphasis textEmphasis = createTextEmphasis(value); @Nullable TextEmphasis textEmphasis = createTextEmphasis(value);
assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull(); assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull();
assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_OPEN_SESAME); assertWithMessage("markShape").that(textEmphasis.markShape)
assertThat(textEmphasis.position).isEqualTo(TextAnnotation.POSITION_BEFORE); .isEqualTo(TextEmphasisSpan.MARK_SHAPE_SESAME);
assertWithMessage("markFill").that(textEmphasis.markFill)
.isEqualTo(TextEmphasisSpan.MARK_FILL_OPEN);
assertWithMessage("position").that(textEmphasis.position)
.isEqualTo(TextAnnotation.POSITION_BEFORE);
} }
@Test @Test
public void testOpenDotOutside() { public void testOpenDotOutside() {
String value = "open dot Outside"; String value = "open dot Outside";
TextEmphasis textEmphasis = createTextEmphasis(value); @Nullable TextEmphasis textEmphasis = createTextEmphasis(value);
assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull(); assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull();
assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_OPEN_DOT); assertWithMessage("markShape").that(textEmphasis.markShape)
assertThat(textEmphasis.position).isEqualTo(TextEmphasis.POSITION_OUTSIDE); .isEqualTo(TextEmphasisSpan.MARK_SHAPE_DOT);
assertWithMessage("markFill").that(textEmphasis.markFill)
.isEqualTo(TextEmphasisSpan.MARK_FILL_OPEN);
assertWithMessage("position").that(textEmphasis.position)
.isEqualTo(TextEmphasis.POSITION_OUTSIDE);
} }
@Test @Test
public void testOpenCircleOutside() { public void testOpenCircleOutside() {
String value = "Open circle Outside"; String value = "Open circle Outside";
TextEmphasis textEmphasis = createTextEmphasis(value); @Nullable TextEmphasis textEmphasis = createTextEmphasis(value);
assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull(); assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull();
assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_OPEN_CIRCLE); assertWithMessage("markShape").that(textEmphasis.markShape)
assertThat(textEmphasis.position).isEqualTo(TextEmphasis.POSITION_OUTSIDE); .isEqualTo(TextEmphasisSpan.MARK_SHAPE_CIRCLE);
assertWithMessage("markFill").that(textEmphasis.markFill)
.isEqualTo(TextEmphasisSpan.MARK_FILL_OPEN);
assertWithMessage("position").that(textEmphasis.position)
.isEqualTo(TextEmphasis.POSITION_OUTSIDE);
} }
@Test @Test
public void testOpenSesameOutside() { public void testOpenSesameOutside() {
String value = "open sesame outside"; String value = "open sesame outside";
TextEmphasis textEmphasis = createTextEmphasis(value); @Nullable TextEmphasis textEmphasis = createTextEmphasis(value);
assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull(); assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull();
assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_OPEN_SESAME); assertWithMessage("markShape").that(textEmphasis.markShape)
assertThat(textEmphasis.position).isEqualTo(TextEmphasis.POSITION_OUTSIDE); .isEqualTo(TextEmphasisSpan.MARK_SHAPE_SESAME);
assertWithMessage("markFill").that(textEmphasis.markFill)
.isEqualTo(TextEmphasisSpan.MARK_FILL_OPEN);
assertWithMessage("position").that(textEmphasis.position)
.isEqualTo(TextEmphasis.POSITION_OUTSIDE);
} }
@Test @Test
public void testFilledDotOutside() { public void testFilledDotOutside() {
String value = "filled dot outside"; String value = "filled dot outside";
TextEmphasis textEmphasis = createTextEmphasis(value); @Nullable TextEmphasis textEmphasis = createTextEmphasis(value);
assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull(); assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull();
assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_FILLED_DOT); assertWithMessage("markShape").that(textEmphasis.markShape)
assertThat(textEmphasis.position).isEqualTo(TextEmphasis.POSITION_OUTSIDE); .isEqualTo(TextEmphasisSpan.MARK_SHAPE_DOT);
assertWithMessage("markFill").that(textEmphasis.markFill)
.isEqualTo(TextEmphasisSpan.MARK_FILL_FILLED);
assertWithMessage("position").that(textEmphasis.position)
.isEqualTo(TextEmphasis.POSITION_OUTSIDE);
} }
@Test @Test
public void testFilledCircleOutside() { public void testFilledCircleOutside() {
String value = "filled circle outside"; String value = "filled circle outside";
TextEmphasis textEmphasis = createTextEmphasis(value); @Nullable TextEmphasis textEmphasis = createTextEmphasis(value);
assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull(); assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull();
assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_FILLED_CIRCLE); assertWithMessage("markShape").that(textEmphasis.markShape)
assertThat(textEmphasis.position).isEqualTo(TextEmphasis.POSITION_OUTSIDE); .isEqualTo(TextEmphasisSpan.MARK_SHAPE_CIRCLE);
assertWithMessage("markFill").that(textEmphasis.markFill)
.isEqualTo(TextEmphasisSpan.MARK_FILL_FILLED);
assertWithMessage("position").that(textEmphasis.position)
.isEqualTo(TextEmphasis.POSITION_OUTSIDE);
} }
@Test @Test
public void testFilledSesameOutside() { public void testFilledSesameOutside() {
String value = "filled sesame outside"; String value = "filled sesame outside";
TextEmphasis textEmphasis = createTextEmphasis(value); @Nullable TextEmphasis textEmphasis = createTextEmphasis(value);
assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull(); assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull();
assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_FILLED_SESAME); assertWithMessage("markShape").that(textEmphasis.markShape)
assertThat(textEmphasis.position).isEqualTo(TextEmphasis.POSITION_OUTSIDE); .isEqualTo(TextEmphasisSpan.MARK_SHAPE_SESAME);
assertWithMessage("markFill").that(textEmphasis.markFill)
.isEqualTo(TextEmphasisSpan.MARK_FILL_FILLED);
assertWithMessage("position").that(textEmphasis.position)
.isEqualTo(TextEmphasis.POSITION_OUTSIDE);
} }
@Test @Test
public void testFilledDotAfter() { public void testFilledDotAfter() {
String value = "filled dot After"; String value = "filled dot After";
TextEmphasis textEmphasis = createTextEmphasis(value); @Nullable TextEmphasis textEmphasis = createTextEmphasis(value);
assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull(); assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull();
assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_FILLED_DOT); assertWithMessage("markShape").that(textEmphasis.markShape)
assertThat(textEmphasis.position).isEqualTo(TextAnnotation.POSITION_AFTER); .isEqualTo(TextEmphasisSpan.MARK_SHAPE_DOT);
assertWithMessage("markFill").that(textEmphasis.markFill)
.isEqualTo(TextEmphasisSpan.MARK_FILL_FILLED);
assertWithMessage("position").that(textEmphasis.position)
.isEqualTo(TextAnnotation.POSITION_AFTER);
} }
@Test @Test
public void testFilledCircleAfter() { public void testFilledCircleAfter() {
String value = "filled circle after"; String value = "filled circle after";
TextEmphasis textEmphasis = createTextEmphasis(value); @Nullable TextEmphasis textEmphasis = createTextEmphasis(value);
assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull(); assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull();
assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_FILLED_CIRCLE); assertWithMessage("markShape").that(textEmphasis.markShape)
assertThat(textEmphasis.position).isEqualTo(TextAnnotation.POSITION_AFTER); .isEqualTo(TextEmphasisSpan.MARK_SHAPE_CIRCLE);
assertWithMessage("markFill").that(textEmphasis.markFill)
.isEqualTo(TextEmphasisSpan.MARK_FILL_FILLED);
assertWithMessage("position").that(textEmphasis.position)
.isEqualTo(TextAnnotation.POSITION_AFTER);
} }
@Test @Test
public void testFilledSesameAfter() { public void testFilledSesameAfter() {
String value = "filled sesame After"; String value = "filled sesame After";
TextEmphasis textEmphasis = createTextEmphasis(value); @Nullable TextEmphasis textEmphasis = createTextEmphasis(value);
assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull(); assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull();
assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_FILLED_SESAME); assertWithMessage("markShape").that(textEmphasis.markShape)
assertThat(textEmphasis.position).isEqualTo(TextAnnotation.POSITION_AFTER); .isEqualTo(TextEmphasisSpan.MARK_SHAPE_SESAME);
assertWithMessage("markFill").that(textEmphasis.markFill)
.isEqualTo(TextEmphasisSpan.MARK_FILL_FILLED);
assertWithMessage("position").that(textEmphasis.position)
.isEqualTo(TextAnnotation.POSITION_AFTER);
} }
@Test @Test
public void testFilledDotBefore() { public void testFilledDotBefore() {
String value = "filled dot before"; String value = "filled dot before";
TextEmphasis textEmphasis = createTextEmphasis(value); @Nullable TextEmphasis textEmphasis = createTextEmphasis(value);
assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull(); assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull();
assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_FILLED_DOT); assertWithMessage("markShape").that(textEmphasis.markShape)
assertThat(textEmphasis.position).isEqualTo(TextAnnotation.POSITION_BEFORE); .isEqualTo(TextEmphasisSpan.MARK_SHAPE_DOT);
assertWithMessage("markFill").that(textEmphasis.markFill)
.isEqualTo(TextEmphasisSpan.MARK_FILL_FILLED);
assertWithMessage("position").that(textEmphasis.position)
.isEqualTo(TextAnnotation.POSITION_BEFORE);
} }
@Test @Test
public void testFilledCircleBefore() { public void testFilledCircleBefore() {
String value = "filled circle Before"; String value = "filled circle Before";
TextEmphasis textEmphasis = createTextEmphasis(value); @Nullable TextEmphasis textEmphasis = createTextEmphasis(value);
assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull(); assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull();
assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_FILLED_CIRCLE); assertWithMessage("markShape").that(textEmphasis.markShape)
assertThat(textEmphasis.position).isEqualTo(TextAnnotation.POSITION_BEFORE); .isEqualTo(TextEmphasisSpan.MARK_SHAPE_CIRCLE);
assertWithMessage("markFill").that(textEmphasis.markFill)
.isEqualTo(TextEmphasisSpan.MARK_FILL_FILLED);
assertWithMessage("position").that(textEmphasis.position)
.isEqualTo(TextAnnotation.POSITION_BEFORE);
} }
@Test @Test
public void testFilledSesameBefore() { public void testFilledSesameBefore() {
String value = "filled sesame Before"; String value = "filled sesame Before";
TextEmphasis textEmphasis = createTextEmphasis(value); @Nullable TextEmphasis textEmphasis = createTextEmphasis(value);
assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull(); assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull();
assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_FILLED_SESAME); assertWithMessage("markShape").that(textEmphasis.markShape)
assertThat(textEmphasis.position).isEqualTo(TextAnnotation.POSITION_BEFORE); .isEqualTo(TextEmphasisSpan.MARK_SHAPE_SESAME);
assertWithMessage("markFill").that(textEmphasis.markFill)
.isEqualTo(TextEmphasisSpan.MARK_FILL_FILLED);
assertWithMessage("position").that(textEmphasis.position)
.isEqualTo(TextAnnotation.POSITION_BEFORE);
} }
@Test @Test
public void testBeforeFilledSesame() { public void testBeforeFilledSesame() {
String value = "before filled sesame"; String value = "before filled sesame";
TextEmphasis textEmphasis = createTextEmphasis(value); @Nullable TextEmphasis textEmphasis = createTextEmphasis(value);
assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull(); assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull();
assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_FILLED_SESAME); assertWithMessage("markShape").that(textEmphasis.markShape)
assertThat(textEmphasis.position).isEqualTo(TextAnnotation.POSITION_BEFORE); .isEqualTo(TextEmphasisSpan.MARK_SHAPE_SESAME);
assertWithMessage("markFill").that(textEmphasis.markFill)
.isEqualTo(TextEmphasisSpan.MARK_FILL_FILLED);
assertWithMessage("position").that(textEmphasis.position)
.isEqualTo(TextAnnotation.POSITION_BEFORE);
} }
@Test @Test
public void testBeforeSesameFilled() { public void testBeforeSesameFilled() {
String value = "before sesame filled"; String value = "before sesame filled";
TextEmphasis textEmphasis = createTextEmphasis(value); @Nullable TextEmphasis textEmphasis = createTextEmphasis(value);
assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull(); assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull();
assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_FILLED_SESAME); assertWithMessage("markShape").that(textEmphasis.markShape)
assertThat(textEmphasis.position).isEqualTo(TextAnnotation.POSITION_BEFORE); .isEqualTo(TextEmphasisSpan.MARK_SHAPE_SESAME);
assertWithMessage("markFill").that(textEmphasis.markFill)
.isEqualTo(TextEmphasisSpan.MARK_FILL_FILLED);
assertWithMessage("position").that(textEmphasis.position)
.isEqualTo(TextAnnotation.POSITION_BEFORE);
}
@Test
public void testInvalidMarkShape() {
String value = "before sesamee filled";
@Nullable TextEmphasis textEmphasis = createTextEmphasis(value);
assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull();
assertWithMessage("markShape").that(textEmphasis.markShape)
.isEqualTo(TextEmphasisSpan.MARK_SHAPE_CIRCLE);
assertWithMessage("markFill").that(textEmphasis.markFill)
.isEqualTo(TextEmphasisSpan.MARK_FILL_FILLED);
assertWithMessage("position").that(textEmphasis.position)
.isEqualTo(TextAnnotation.POSITION_BEFORE);
}
@Test
public void testInvalidMarkFill() {
String value = "before sesame filed";
@Nullable TextEmphasis textEmphasis = createTextEmphasis(value);
assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull();
assertWithMessage("markShape").that(textEmphasis.markShape)
.isEqualTo(TextEmphasisSpan.MARK_SHAPE_SESAME);
assertWithMessage("markFill").that(textEmphasis.markFill)
.isEqualTo(TextEmphasisSpan.MARK_FILL_FILLED);
assertWithMessage("position").that(textEmphasis.position)
.isEqualTo(TextAnnotation.POSITION_BEFORE);
}
@Test
public void testInvalidPosition() {
String value = "befour sesame filled";
@Nullable TextEmphasis textEmphasis = createTextEmphasis(value);
assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull();
assertWithMessage("markShape").that(textEmphasis.markShape)
.isEqualTo(TextEmphasisSpan.MARK_SHAPE_SESAME);
assertWithMessage("markFill").that(textEmphasis.markFill)
.isEqualTo(TextEmphasisSpan.MARK_FILL_FILLED);
assertWithMessage("position").that(textEmphasis.position).isEqualTo(POSITION_OUTSIDE);
} }
} }

View File

@ -682,68 +682,80 @@ 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).hasNoSpans(); assertThat(firstCue).hasTextEmphasisSpanBetween("None ".length(), "None おはよ".length())
.withMarkAndPosition(TextEmphasisSpan.MARK_SHAPE_NONE,
TextEmphasisSpan.MARK_FILL_UNSPECIFIED,
TextAnnotation.POSITION_BEFORE);
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_SHAPE_CIRCLE,
TextEmphasisSpan.MARK_FILL_UNSPECIFIED,
TextAnnotation.POSITION_BEFORE); 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_SHAPE_CIRCLE, TextEmphasisSpan.MARK_FILL_FILLED,
TextAnnotation.POSITION_BEFORE); 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, TextAnnotation.POSITION_BEFORE); .withMarkAndPosition(TextEmphasisSpan.MARK_SHAPE_DOT, TextEmphasisSpan.MARK_FILL_FILLED,
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_SHAPE_SESAME, TextEmphasisSpan.MARK_FILL_FILLED,
TextAnnotation.POSITION_BEFORE); 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, TextAnnotation.POSITION_BEFORE); .withMarkAndPosition(TextEmphasisSpan.MARK_SHAPE_CIRCLE, TextEmphasisSpan.MARK_FILL_OPEN,
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, TextAnnotation.POSITION_AFTER); .withMarkAndPosition(TextEmphasisSpan.MARK_SHAPE_DOT, TextEmphasisSpan.MARK_FILL_OPEN,
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, TextAnnotation.POSITION_BEFORE); .withMarkAndPosition(TextEmphasisSpan.MARK_SHAPE_SESAME, TextEmphasisSpan.MARK_FILL_OPEN,
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_SHAPE_CIRCLE,
TextEmphasisSpan.MARK_FILL_UNSPECIFIED,
TextAnnotation.POSITION_BEFORE); 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, TextAnnotation.POSITION_BEFORE); .withMarkAndPosition(TextEmphasisSpan.MARK_SHAPE_CIRCLE, TextEmphasisSpan.MARK_FILL_FILLED,
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, TextAnnotation.POSITION_AFTER); .withMarkAndPosition(TextEmphasisSpan.MARK_SHAPE_SESAME, TextEmphasisSpan.MARK_FILL_FILLED,
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, TextAnnotation.POSITION_BEFORE); .withMarkAndPosition(TextEmphasisSpan.MARK_SHAPE_DOT, TextEmphasisSpan.MARK_FILL_FILLED,
TextAnnotation.POSITION_BEFORE);
Spanned thirteenthCue = getOnlyCueTextAtTimeUs(subtitle, 130_000_000); Spanned thirteenthCue = getOnlyCueTextAtTimeUs(subtitle, 130_000_000);
assertThat(thirteenthCue) assertThat(thirteenthCue)
@ -753,25 +765,29 @@ public final class TtmlDecoderTest {
Spanned fourteenthCue = getOnlyCueTextAtTimeUs(subtitle, 140_000_000); Spanned fourteenthCue = getOnlyCueTextAtTimeUs(subtitle, 140_000_000);
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_SHAPE_SESAME,
TextEmphasisSpan.MARK_FILL_UNSPECIFIED,
TextAnnotation.POSITION_BEFORE); 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_SHAPE_SESAME,
TextEmphasisSpan.MARK_FILL_UNSPECIFIED,
TextAnnotation.POSITION_BEFORE); 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_SHAPE_SESAME,
TextEmphasisSpan.MARK_FILL_UNSPECIFIED,
TextAnnotation.POSITION_BEFORE); 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_SHAPE_CIRCLE,
TextEmphasisSpan.MARK_FILL_UNSPECIFIED,
TextAnnotation.POSITION_BEFORE); TextAnnotation.POSITION_BEFORE);
} }

View File

@ -17,8 +17,6 @@ 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.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_OPEN_SESAME;
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,6 +30,7 @@ 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.TextAnnotation; import com.google.android.exoplayer2.text.span.TextAnnotation;
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;
@ -92,7 +91,8 @@ public final class TtmlStyleTest {
.that(style.hasBackgroundColor()) .that(style.hasBackgroundColor())
.isFalse(); .isFalse();
assertThat(style.getTextEmphasis()).isNotNull(); assertThat(style.getTextEmphasis()).isNotNull();
assertThat(style.getTextEmphasis().mark).isEqualTo(MARK_FILLED_DOT); assertThat(style.getTextEmphasis().markShape).isEqualTo(TextEmphasisSpan.MARK_SHAPE_DOT);
assertThat(style.getTextEmphasis().markFill).isEqualTo(TextEmphasisSpan.MARK_FILL_FILLED);
assertThat(style.getTextEmphasis().position).isEqualTo(POSITION_BEFORE); assertThat(style.getTextEmphasis().position).isEqualTo(POSITION_BEFORE);
} }
@ -118,7 +118,8 @@ public final class TtmlStyleTest {
.isEqualTo(BACKGROUND_COLOR); .isEqualTo(BACKGROUND_COLOR);
assertWithMessage("rubyType should be chained").that(style.getRubyType()).isEqualTo(RUBY_TYPE); assertWithMessage("rubyType should be chained").that(style.getRubyType()).isEqualTo(RUBY_TYPE);
assertThat(style.getTextEmphasis()).isNotNull(); assertThat(style.getTextEmphasis()).isNotNull();
assertThat(style.getTextEmphasis().mark).isEqualTo(MARK_FILLED_DOT); assertThat(style.getTextEmphasis().markShape).isEqualTo(TextEmphasisSpan.MARK_SHAPE_DOT);
assertThat(style.getTextEmphasis().markFill).isEqualTo(TextEmphasisSpan.MARK_FILL_FILLED);
assertThat(style.getTextEmphasis().position).isEqualTo(POSITION_BEFORE); assertThat(style.getTextEmphasis().position).isEqualTo(POSITION_BEFORE);
} }
@ -262,7 +263,8 @@ public final class TtmlStyleTest {
TtmlStyle style = new TtmlStyle(); TtmlStyle style = new TtmlStyle();
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().markShape).isEqualTo(TextEmphasisSpan.MARK_SHAPE_SESAME);
assertThat(style.getTextEmphasis().markFill).isEqualTo(TextEmphasisSpan.MARK_FILL_OPEN);
assertThat(style.getTextEmphasis().position).isEqualTo(TextAnnotation.POSITION_AFTER); assertThat(style.getTextEmphasis().position).isEqualTo(TextAnnotation.POSITION_AFTER);
} }
} }

View File

@ -201,12 +201,13 @@ import java.util.regex.Pattern;
return "<u>"; return "<u>";
} else if (span instanceof TextEmphasisSpan) { } else if (span instanceof TextEmphasisSpan) {
TextEmphasisSpan textEmphasisSpan = (TextEmphasisSpan) span; TextEmphasisSpan textEmphasisSpan = (TextEmphasisSpan) span;
String style = getTextEmphasisStyle(textEmphasisSpan.mark); String style = getTextEmphasisStyle(textEmphasisSpan.markShape, textEmphasisSpan.markFill);
String position = getTextEmphasisPosition(textEmphasisSpan.position); String position = getTextEmphasisPosition(textEmphasisSpan.position);
return Util return Util
.formatInvariant("<span style='-webkit-text-emphasis-style: %s; text-emphasis-style: %s; " .formatInvariant(
+ "-webkit-text-emphasis-position: %s; text-emphasis-position: %s;'>", "<span style='-webkit-text-emphasis-style: %1$s; text-emphasis-style: %1$s; "
style, style, position, position); + "-webkit-text-emphasis-position: %2$s; text-emphasis-position: %2$s;'>",
style, position);
} else { } else {
return null; return null;
} }
@ -243,23 +244,39 @@ import java.util.regex.Pattern;
return null; return null;
} }
private static String getTextEmphasisStyle(@TextEmphasisSpan.Mark int mark) { private static String getTextEmphasisStyle(@TextEmphasisSpan.MarkShape int shape,
switch (mark) { @TextEmphasisSpan.MarkFill int fill) {
case TextEmphasisSpan.MARK_FILLED_CIRCLE: StringBuilder builder = new StringBuilder();
return "filled circle"; switch (fill) {
case TextEmphasisSpan.MARK_FILLED_DOT: case TextEmphasisSpan.MARK_FILL_FILLED:
return "filled dot"; builder.append("filled ");
case TextEmphasisSpan.MARK_FILLED_SESAME: break;
return "filled sesame"; case TextEmphasisSpan.MARK_FILL_OPEN:
case TextEmphasisSpan.MARK_OPEN_CIRCLE: builder.append("open ");
return "open circle"; break;
case TextEmphasisSpan.MARK_OPEN_DOT: case TextEmphasisSpan.MARK_FILL_UNSPECIFIED:
return "open dot";
case TextEmphasisSpan.MARK_OPEN_SESAME:
return "open sesame";
default: default:
return "unset"; break;
} }
switch (shape) {
case TextEmphasisSpan.MARK_SHAPE_CIRCLE:
builder.append("circle");
break;
case TextEmphasisSpan.MARK_SHAPE_DOT:
builder.append("dot");
break;
case TextEmphasisSpan.MARK_SHAPE_SESAME:
builder.append("sesame");
break;
case TextEmphasisSpan.MARK_SHAPE_NONE:
builder.append("none");
break;
default:
builder.append("unset");
break;
}
return builder.toString();
} }
private static String getTextEmphasisPosition(@TextAnnotation.Position int position){ private static String getTextEmphasisPosition(@TextAnnotation.Position int position){

View File

@ -285,13 +285,15 @@ 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, TextAnnotation.POSITION_BEFORE), new TextEmphasisSpan(TextEmphasisSpan.MARK_SHAPE_CIRCLE, TextEmphasisSpan.MARK_FILL_FILLED,
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, TextAnnotation.POSITION_AFTER), new TextEmphasisSpan(TextEmphasisSpan.MARK_SHAPE_SESAME, TextEmphasisSpan.MARK_FILL_OPEN,
TextAnnotation.POSITION_AFTER),
"Text emphasis おはよ ".length(), "Text emphasis おはよ ".length(),
"Text emphasis おはよ ございます ".length(), "Text emphasis おはよ ございます ".length(),
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

View File

@ -1156,20 +1156,21 @@ public final class SpannedSubject extends Subject {
/** Allows assertions about a span's textEmphasis mark and its position. */ /** Allows assertions about a span's textEmphasis mark and its position. */
public interface TextEmphasisDescription { public interface TextEmphasisDescription {
/** /**
* Checks that at least one of the matched spans has the expected {@code mark} and {@code position}. * Checks that at least one of the matched spans has the expected {@code mark} and {@code position}.
* *
* @param mark The expected mark * @param markShape The expected mark shape
* @param markFill The expected mark fill
* @param position The expected position of the mark * @param position The expected position of the mark
* @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.MarkShape int markShape,
@TextEmphasisSpan.MarkFill int markFill,
@TextAnnotation.Position int position); @TextAnnotation.Position int position);
} }
private static final TextEmphasisDescription ALREADY_FAILED_WITH_MARK = private static final TextEmphasisDescription ALREADY_FAILED_WITH_MARK =
(mark, position) -> ALREADY_FAILED_AND_FLAGS; (markShape, markFill, position) -> ALREADY_FAILED_AND_FLAGS;
private static Factory<TextEmphasisSubject, List<TextEmphasisSpan>> textEmphasisSubjects(Spanned actualSpanned) { private static Factory<TextEmphasisSubject, List<TextEmphasisSpan>> textEmphasisSubjects(Spanned actualSpanned) {
return (FailureMetadata metadata, List<TextEmphasisSpan> spans) -> return (FailureMetadata metadata, List<TextEmphasisSpan> spans) ->
@ -1189,32 +1190,38 @@ public final class SpannedSubject extends Subject {
} }
@Override @Override
public AndSpanFlags withMarkAndPosition(@TextEmphasisSpan.Mark int mark, public AndSpanFlags withMarkAndPosition(@TextEmphasisSpan.MarkShape int markShape,
@TextEmphasisSpan.MarkFill int markFill,
@TextAnnotation.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) {
textEmphasisMarksAndPositions.add(new MarkAndPosition(span.mark, span.position)); textEmphasisMarksAndPositions
if (span.mark == mark && span.position == position) { .add(new MarkAndPosition(span.markShape, span.markFill, span.position));
if (span.markFill == markFill && span.markShape == markShape && span.position == position) {
matchingSpanFlags.add(actualSpanned.getSpanFlags(span)); matchingSpanFlags.add(actualSpanned.getSpanFlags(span));
} }
} }
check("textEmphasisMarkAndPosition") check("textEmphasisMarkAndPosition")
.that(textEmphasisMarksAndPositions) .that(textEmphasisMarksAndPositions)
.containsExactly(new MarkAndPosition(mark, position)); .containsExactly(new MarkAndPosition(markShape, markFill, position));
return check("flags").about(spanFlags()).that(matchingSpanFlags); return check("flags").about(spanFlags()).that(matchingSpanFlags);
} }
private static final class MarkAndPosition { private static final class MarkAndPosition {
@TextEmphasisSpan.Mark @TextEmphasisSpan.MarkShape
private final int mark; private final int markShape;
@TextEmphasisSpan.MarkFill
private final int markFill;
@TextAnnotation.Position @TextAnnotation.Position
private final int position; private final int position;
private MarkAndPosition(@TextEmphasisSpan.Mark int mark, private MarkAndPosition(@TextEmphasisSpan.MarkShape int markShape,
@TextEmphasisSpan.MarkFill int markFill,
@TextAnnotation.Position int position) { @TextAnnotation.Position int position) {
this.mark = mark; this.markFill = markFill;
this.markShape = markShape;
this.position = position; this.position = position;
} }
@ -1228,18 +1235,20 @@ public final class SpannedSubject extends Subject {
} }
TextEmphasisSubject.MarkAndPosition that = (TextEmphasisSubject.MarkAndPosition) o; TextEmphasisSubject.MarkAndPosition that = (TextEmphasisSubject.MarkAndPosition) o;
return (position == that.position) && (mark == that.mark); return (position == that.position) && (markShape == that.markShape) && (markFill
== that.markFill);
} }
@Override @Override
public int hashCode() { public int hashCode() {
int result = 34613 * mark + position; int result = 34613 * markFill + 1993 * markShape + position;
return result; return result;
} }
@Override @Override
public String toString() { public String toString() {
return String.format("{mark=%s,position=%s}", mark, position); return String
.format("{markShape=%s, markFill=%s, position=%s}", markShape, markFill, position);
} }
} }
} }