From f7f40bcb25fb6aa1d2d0fe33686d0836b1b7cf98 Mon Sep 17 00:00:00 2001 From: Denise LaFayette Date: Fri, 5 Mar 2021 12:23:34 -0800 Subject: [PATCH] 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 --- .../text/span/TextEmphasisSpan.java | 76 +-- .../exoplayer2/text/ttml/TextEmphasis.java | 145 +++--- .../exoplayer2/text/ttml/TtmlRenderUtil.java | 16 +- .../text/ttml/TextEmphasisTest.java | 471 ++++++++++++------ .../exoplayer2/text/ttml/TtmlDecoderTest.java | 48 +- .../exoplayer2/text/ttml/TtmlStyleTest.java | 12 +- .../exoplayer2/ui/SpannedToHtmlConverter.java | 55 +- .../ui/SpannedToHtmlConverterTest.java | 6 +- .../testutil/truth/SpannedSubject.java | 39 +- 9 files changed, 560 insertions(+), 308 deletions(-) diff --git a/library/core/src/main/java/com/google/android/exoplayer2/text/span/TextEmphasisSpan.java b/library/core/src/main/java/com/google/android/exoplayer2/text/span/TextEmphasisSpan.java index d247ad9364..221e0305d6 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/text/span/TextEmphasisSpan.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/text/span/TextEmphasisSpan.java @@ -23,51 +23,60 @@ import java.lang.annotation.Documented; import java.lang.annotation.Retention; public final class TextEmphasisSpan { - // Bits [1:0] are used for typical mark types - public static final int MARK_FLAG_CIRCLE = 1; - public static final int MARK_FLAG_DOT = 2; - public static final int MARK_FLAG_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; + public static final int MARK_SHAPE_NONE = 0; + public static final int MARK_SHAPE_CIRCLE = 1; + public static final int MARK_SHAPE_DOT = 2; + public static final int MARK_SHAPE_SESAME = 3; /** - * The possible types of annotations used. + * The possible mark shapes that can be used. * *

One of: * *

- * - * Note: We are intentionally excluding MARK_AUTO here since the auto value should - * be resolved */ @Documented @Retention(SOURCE) - @IntDef({MARK_FILLED_CIRCLE, MARK_FILLED_DOT, MARK_FILLED_SESAME, - MARK_OPEN_CIRCLE, MARK_OPEN_DOT, MARK_OPEN_SESAME}) - public @interface Mark { + @IntDef({MARK_SHAPE_NONE, MARK_SHAPE_CIRCLE, MARK_SHAPE_DOT, MARK_SHAPE_SESAME}) + public @interface MarkShape { } + 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. + * + *

One of: + * + *

*/ - 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 @@ -76,9 +85,10 @@ public final class TextEmphasisSpan { public final int position; - public TextEmphasisSpan(@TextEmphasisSpan.Mark int mark, + public TextEmphasisSpan(@MarkShape int shape, @MarkFill int fill, @TextAnnotation.Position int position) { - this.mark = mark; + this.markShape = shape; + this.markFill = fill; this.position = position; } } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/text/ttml/TextEmphasis.java b/library/core/src/main/java/com/google/android/exoplayer2/text/ttml/TextEmphasis.java index 8b03cc12df..5069f80e4c 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/text/ttml/TextEmphasis.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/text/ttml/TextEmphasis.java @@ -38,33 +38,35 @@ import java.util.Set; /* package */ final class TextEmphasis { /** - * Mark style to be resolved at rendering time. Hence, it is not defined in - * {@link TextEmphasisSpan.Mark} + * Mark shape AUTO is to be resolved at rendering time. Hence, it is not defined in + * {@link TextEmphasisSpan.MarkShape} */ - public static final int MARK_AUTO = 1 << 8; + public static final int MARK_SHAPE_AUTO = 1 << 8; @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 + @IntDef({TextEmphasisSpan.MARK_SHAPE_NONE, + TextEmphasisSpan.MARK_SHAPE_CIRCLE, + TextEmphasisSpan.MARK_SHAPE_DOT, + TextEmphasisSpan.MARK_SHAPE_SESAME, + // Extending the definition in TextEmphasisSpan.MarkShape for intermediate values + MARK_SHAPE_AUTO }) - @interface Mark { + @interface MarkShape { } + @MarkShape + final int markShape; + /** * 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} */ static final int POSITION_OUTSIDE = 1 << 8; @@ -84,26 +86,32 @@ import java.util.Set; */ @Position final int position; - private static Set markValues = ImmutableSet.of( + private static final Set singleStyleValues = ImmutableSet.of( TtmlNode.TEXT_EMPHASIS_AUTO, + TtmlNode.TEXT_EMPHASIS_NONE + ); + + private static final Set markShapeValues = ImmutableSet.of( TtmlNode.TEXT_EMPHASIS_MARK_DOT, TtmlNode.TEXT_EMPHASIS_MARK_SESAME, TtmlNode.TEXT_EMPHASIS_MARK_CIRCLE - ); + ); - private static Set markStyles = ImmutableSet.of( + private static final Set markFillValues = ImmutableSet.of( TtmlNode.TEXT_EMPHASIS_MARK_FILLED, TtmlNode.TEXT_EMPHASIS_MARK_OPEN ); - private static Set positionValues = ImmutableSet.of( + private static final Set positionValues = ImmutableSet.of( TtmlNode.ANNOTATION_POSITION_AFTER, TtmlNode.ANNOTATION_POSITION_BEFORE, TtmlNode.ANNOTATION_POSITION_OUTSIDE ); - private TextEmphasis(@Mark int mark, @TextAnnotation.Position int position) { - this.mark = mark; + private TextEmphasis(@MarkShape int shape, @TextEmphasisSpan.MarkFill int fill, + @TextAnnotation.Position int position) { + this.markShape = shape; + this.markFill = fill; this.position = position; } @@ -111,68 +119,83 @@ import java.util.Set; public String toString() { return "TextEmphasis{" + "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) { return null; } String parsingValue = value.toLowerCase().trim(); - if ("".equals(parsingValue)) { + if (parsingValue.isEmpty()) { return null; } Set nodes = Sets.newHashSet(parsingValue.split("\\s+")); - - if (nodes.size() == 0 || TtmlNode.TEXT_EMPHASIS_NONE.equals(nodes.iterator().next())) { + if (nodes.size() == 0) { return null; } return parseNodes(nodes); } private static @Nullable TextEmphasis parseNodes(Set nodes) { - Set styleSet = Sets.intersection(markStyles, nodes).immutableCopy(); - Set markSet = Sets.intersection(markValues, nodes).immutableCopy(); - Set positionSet = Sets.intersection(positionValues, nodes).immutableCopy(); - - @Mark int mark = 0; - if (styleSet.size() == 1) { - mark |= TtmlNode.TEXT_EMPHASIS_MARK_OPEN.equals(styleSet.iterator().next()) - ? TextEmphasisSpan.MARK_FLAG_OPEN - : TextEmphasisSpan.MARK_FLAG_FILLED; - } - 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; - } + @MarkShape int markShape; + @TextEmphasisSpan.MarkFill int markFill = TextEmphasisSpan.MARK_FILL_UNSPECIFIED; + Set styleSet = Sets.intersection(singleStyleValues, nodes).immutableCopy(); + if (styleSet.size() > 0) { + // If "none" or "auto" are found in the description, ignore the other style (fill, shape) + // attributes. + markShape = TtmlNode.TEXT_EMPHASIS_NONE.equals(styleSet.iterator().next()) + ? TextEmphasisSpan.MARK_SHAPE_NONE : MARK_SHAPE_AUTO; + // markFill is ignored when markShape is NONE or AUTO } else { - mark |= TextEmphasisSpan.MARK_FLAG_CIRCLE; + Set fillSet = Sets.intersection(markFillValues, nodes).immutableCopy(); + Set 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; + } + } } - /** - * If no emphasis position is specified, then the emphasis position must be interpreted as if - * a position of outside were specified. - *

- * More information on - * tts:textEmphasis - */ + Set 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. + // https://www.w3.org/TR/2018/REC-ttml2-20181108/#style-attribute-textEmphasis @Position int position = POSITION_OUTSIDE; - if (positionSet.size() == 1) { - switch ((String) positionSet.iterator().next()) { + if (positionSet.size() > 0) { + switch (positionSet.iterator().next()) { case TtmlNode.ANNOTATION_POSITION_AFTER: position = TextAnnotation.POSITION_AFTER; break; @@ -184,6 +207,6 @@ import java.util.Set; position = TextAnnotation.POSITION_BEFORE; } } - return new TextEmphasis(mark, position); + return new TextEmphasis(markShape, markFill, position); } } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/text/ttml/TtmlRenderUtil.java b/library/core/src/main/java/com/google/android/exoplayer2/text/ttml/TtmlRenderUtil.java index 72b1f63f15..3231a66eee 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/text/ttml/TtmlRenderUtil.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/text/ttml/TtmlRenderUtil.java @@ -129,14 +129,14 @@ import java.util.Map; * 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. - * If a vertical writing mode applies, then equivalent to filled sesame; otherwise, equivalent - * to filled circle. - * See 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. + * See https://www.w3.org/TR/ttml2/#style-value-emphasis-style */ - @TextEmphasis.Mark int mark = textEmphasis.mark; - if (textEmphasis.mark == TextEmphasis.MARK_AUTO) { - mark = (verticalType == Cue.VERTICAL_TYPE_LR || verticalType == Cue.VERTICAL_TYPE_RL) ? - TextEmphasisSpan.MARK_FILLED_SESAME : TextEmphasisSpan.MARK_FILLED_CIRCLE; + @TextEmphasis.MarkShape int markShape = textEmphasis.markShape; + if (textEmphasis.markShape == TextEmphasis.MARK_SHAPE_AUTO) { + markShape = (verticalType == Cue.VERTICAL_TYPE_LR || verticalType == Cue.VERTICAL_TYPE_RL) ? + TextEmphasisSpan.MARK_SHAPE_SESAME : TextEmphasisSpan.MARK_SHAPE_CIRCLE; } @TextEmphasis.Position int position = textEmphasis.position; @@ -154,7 +154,7 @@ import java.util.Map; SpanUtil.addOrReplaceSpan( builder, - new TextEmphasisSpan(mark, position), + new TextEmphasisSpan(markShape, textEmphasis.markFill, position), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); diff --git a/library/core/src/test/java/com/google/android/exoplayer2/text/ttml/TextEmphasisTest.java b/library/core/src/test/java/com/google/android/exoplayer2/text/ttml/TextEmphasisTest.java index e273a0d049..128a2b2ea0 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/text/ttml/TextEmphasisTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/text/ttml/TextEmphasisTest.java @@ -1,16 +1,20 @@ 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.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertWithMessage; +import androidx.annotation.Nullable; import androidx.test.ext.junit.runners.AndroidJUnit4; import com.google.android.exoplayer2.text.span.TextAnnotation; import com.google.android.exoplayer2.text.span.TextEmphasisSpan; import org.junit.Test; import org.junit.runner.RunWith; -/** Unit test for {@link TextEmphasis}. */ +/** + * Unit test for {@link TextEmphasis}. + */ @RunWith(AndroidJUnit4.class) public class TextEmphasisTest { @@ -18,373 +22,542 @@ public class TextEmphasisTest { @Test public void testNull() { - String value = null; - TextEmphasis textEmphasis = createTextEmphasis(value); - + @Nullable TextEmphasis textEmphasis = createTextEmphasis(null); assertWithMessage("Text Emphasis must be null").that(textEmphasis).isNull(); } @Test public void testEmpty() { - String value = ""; - TextEmphasis textEmphasis = createTextEmphasis(value); + @Nullable TextEmphasis textEmphasis = createTextEmphasis(""); + 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(); } @Test public void testNone() { String value = "none"; - TextEmphasis textEmphasis = createTextEmphasis(value); - - assertWithMessage("Text Emphasis must be null").that(textEmphasis).isNull(); + @Nullable TextEmphasis textEmphasis = createTextEmphasis(value); + assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull(); + assertWithMessage("markShape").that(textEmphasis.markShape) + .isEqualTo(TextEmphasisSpan.MARK_SHAPE_NONE); + assertWithMessage("position").that(textEmphasis.position) + .isEqualTo(TextEmphasis.POSITION_OUTSIDE); } @Test public void testAuto() { String value = "auto"; - TextEmphasis textEmphasis = createTextEmphasis(value); - + @Nullable TextEmphasis textEmphasis = createTextEmphasis(value); assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull(); - assertThat(textEmphasis.mark).isEqualTo(TextEmphasis.MARK_AUTO); - assertThat(textEmphasis.position).isEqualTo(TextEmphasis.POSITION_OUTSIDE); + 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 + 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 public void testAutoOutside() { String value = "auto outside"; - TextEmphasis textEmphasis = createTextEmphasis(value); - + @Nullable TextEmphasis textEmphasis = createTextEmphasis(value); assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull(); - assertThat(textEmphasis.mark).isEqualTo(TextEmphasis.MARK_AUTO); - assertThat(textEmphasis.position).isEqualTo(TextEmphasis.POSITION_OUTSIDE); + 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 + 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, - * respectively. + * 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); - + @Nullable 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); + 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(TextEmphasis.POSITION_OUTSIDE); } @Test public void testOpen() { String value = "open"; - TextEmphasis textEmphasis = createTextEmphasis(value); - + @Nullable 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); + assertWithMessage("markShape").that(textEmphasis.markShape) + .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 public void testOpenAfter() { String value = "open after"; - TextEmphasis textEmphasis = createTextEmphasis(value); - + @Nullable 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); + assertWithMessage("markShape").that(textEmphasis.markShape) + .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, - * and filled sesame, respectively. + * If only circle, dot, or sesame is specified, then it is equivalent to filled circle, filled + * dot, and filled sesame, respectively. */ @Test public void testDotBefore() { String value = "dot before"; - TextEmphasis textEmphasis = createTextEmphasis(value); - + @Nullable TextEmphasis textEmphasis = createTextEmphasis(value); assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull(); - assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_FILLED_DOT); - assertThat(textEmphasis.position).isEqualTo(TextAnnotation.POSITION_BEFORE); + assertWithMessage("markShape").that(textEmphasis.markShape) + .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 public void testCircleBefore() { String value = "circle before"; - TextEmphasis textEmphasis = createTextEmphasis(value); - + @Nullable TextEmphasis textEmphasis = createTextEmphasis(value); assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull(); - assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_FILLED_CIRCLE); - assertThat(textEmphasis.position).isEqualTo(TextAnnotation.POSITION_BEFORE); + 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 testSesameBefore() { String value = "sesame before"; - TextEmphasis textEmphasis = createTextEmphasis(value); - + @Nullable 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); + 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 testDotAfter() { String value = "dot AFTER"; - TextEmphasis textEmphasis = createTextEmphasis(value); - + @Nullable TextEmphasis textEmphasis = createTextEmphasis(value); assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull(); - assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_FILLED_DOT); - assertThat(textEmphasis.position).isEqualTo(TextAnnotation.POSITION_AFTER); + assertWithMessage("markShape").that(textEmphasis.markShape) + .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 public void testCircleAfter() { String value = "circle after"; - TextEmphasis textEmphasis = createTextEmphasis(value); - + @Nullable TextEmphasis textEmphasis = createTextEmphasis(value); assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull(); - assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_FILLED_CIRCLE); - assertThat(textEmphasis.position).isEqualTo(TextAnnotation.POSITION_AFTER); + 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_AFTER); } @Test public void testSesameAfter() { String value = "sesame aFter"; - TextEmphasis textEmphasis = createTextEmphasis(value); - + @Nullable 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_AFTER); + 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_AFTER); } @Test public void testDotOutside() { String value = "dot outside"; - TextEmphasis textEmphasis = createTextEmphasis(value); - + @Nullable TextEmphasis textEmphasis = createTextEmphasis(value); assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull(); - assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_FILLED_DOT); - assertThat(textEmphasis.position).isEqualTo(TextEmphasis.POSITION_OUTSIDE); + assertWithMessage("markShape").that(textEmphasis.markShape) + .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 public void testCircleOutside() { String value = "circle outside"; - TextEmphasis textEmphasis = createTextEmphasis(value); - + @Nullable 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); + 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(TextEmphasis.POSITION_OUTSIDE); } @Test public void testSesameOutside() { String value = "sesame outside"; - TextEmphasis textEmphasis = createTextEmphasis(value); - + @Nullable TextEmphasis textEmphasis = createTextEmphasis(value); assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull(); - assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_FILLED_SESAME); - assertThat(textEmphasis.position).isEqualTo(TextEmphasis.POSITION_OUTSIDE); + 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(TextEmphasis.POSITION_OUTSIDE); } @Test public void testOpenDotAfter() { String value = "open dot AFTER"; - TextEmphasis textEmphasis = createTextEmphasis(value); - + @Nullable TextEmphasis textEmphasis = createTextEmphasis(value); assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull(); - assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_OPEN_DOT); - assertThat(textEmphasis.position).isEqualTo(TextAnnotation.POSITION_AFTER); + assertWithMessage("markShape").that(textEmphasis.markShape) + .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 public void testOpenCircleAfter() { String value = "Open circle after"; - TextEmphasis textEmphasis = createTextEmphasis(value); - + @Nullable 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); + assertWithMessage("markShape").that(textEmphasis.markShape) + .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 public void testOpenSesameAfter() { String value = "open sesame aFter"; - TextEmphasis textEmphasis = createTextEmphasis(value); + @Nullable TextEmphasis textEmphasis = createTextEmphasis(value); assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull(); - assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_OPEN_SESAME); - assertThat(textEmphasis.position).isEqualTo(TextAnnotation.POSITION_AFTER); + assertWithMessage("markShape").that(textEmphasis.markShape) + .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 public void testOpenDotBefore() { String value = "open dot before"; - TextEmphasis textEmphasis = createTextEmphasis(value); - + @Nullable TextEmphasis textEmphasis = createTextEmphasis(value); assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull(); - assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_OPEN_DOT); - assertThat(textEmphasis.position).isEqualTo(TextAnnotation.POSITION_BEFORE); + assertWithMessage("markShape").that(textEmphasis.markShape) + .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 public void testOpenCircleBefore() { String value = "Open circle Before"; - TextEmphasis textEmphasis = createTextEmphasis(value); - + @Nullable 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_BEFORE); + assertWithMessage("markShape").that(textEmphasis.markShape) + .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 public void testOpenSesameBefore() { String value = "open sesame Before"; - TextEmphasis textEmphasis = createTextEmphasis(value); - + @Nullable TextEmphasis textEmphasis = createTextEmphasis(value); assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull(); - assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_OPEN_SESAME); - assertThat(textEmphasis.position).isEqualTo(TextAnnotation.POSITION_BEFORE); + assertWithMessage("markShape").that(textEmphasis.markShape) + .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 public void testOpenDotOutside() { String value = "open dot Outside"; - TextEmphasis textEmphasis = createTextEmphasis(value); - + @Nullable TextEmphasis textEmphasis = createTextEmphasis(value); assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull(); - assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_OPEN_DOT); - assertThat(textEmphasis.position).isEqualTo(TextEmphasis.POSITION_OUTSIDE); + assertWithMessage("markShape").that(textEmphasis.markShape) + .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 public void testOpenCircleOutside() { String value = "Open circle Outside"; - TextEmphasis textEmphasis = createTextEmphasis(value); - + @Nullable 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); + assertWithMessage("markShape").that(textEmphasis.markShape) + .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 public void testOpenSesameOutside() { String value = "open sesame outside"; - TextEmphasis textEmphasis = createTextEmphasis(value); - + @Nullable TextEmphasis textEmphasis = createTextEmphasis(value); assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull(); - assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_OPEN_SESAME); - assertThat(textEmphasis.position).isEqualTo(TextEmphasis.POSITION_OUTSIDE); + assertWithMessage("markShape").that(textEmphasis.markShape) + .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 public void testFilledDotOutside() { String value = "filled dot outside"; - TextEmphasis textEmphasis = createTextEmphasis(value); - + @Nullable TextEmphasis textEmphasis = createTextEmphasis(value); assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull(); - assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_FILLED_DOT); - assertThat(textEmphasis.position).isEqualTo(TextEmphasis.POSITION_OUTSIDE); + assertWithMessage("markShape").that(textEmphasis.markShape) + .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 public void testFilledCircleOutside() { String value = "filled circle outside"; - TextEmphasis textEmphasis = createTextEmphasis(value); - + @Nullable 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); + 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(TextEmphasis.POSITION_OUTSIDE); } @Test public void testFilledSesameOutside() { String value = "filled sesame outside"; - TextEmphasis textEmphasis = createTextEmphasis(value); - + @Nullable TextEmphasis textEmphasis = createTextEmphasis(value); assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull(); - assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_FILLED_SESAME); - assertThat(textEmphasis.position).isEqualTo(TextEmphasis.POSITION_OUTSIDE); + 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(TextEmphasis.POSITION_OUTSIDE); } @Test public void testFilledDotAfter() { String value = "filled dot After"; - TextEmphasis textEmphasis = createTextEmphasis(value); - + @Nullable TextEmphasis textEmphasis = createTextEmphasis(value); assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull(); - assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_FILLED_DOT); - assertThat(textEmphasis.position).isEqualTo(TextAnnotation.POSITION_AFTER); + assertWithMessage("markShape").that(textEmphasis.markShape) + .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 public void testFilledCircleAfter() { String value = "filled circle after"; - TextEmphasis textEmphasis = createTextEmphasis(value); - + @Nullable TextEmphasis textEmphasis = createTextEmphasis(value); assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull(); - assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_FILLED_CIRCLE); - assertThat(textEmphasis.position).isEqualTo(TextAnnotation.POSITION_AFTER); + 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_AFTER); } @Test public void testFilledSesameAfter() { String value = "filled sesame After"; - TextEmphasis textEmphasis = createTextEmphasis(value); - + @Nullable 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_AFTER); + 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_AFTER); } @Test public void testFilledDotBefore() { String value = "filled dot before"; - TextEmphasis textEmphasis = createTextEmphasis(value); - + @Nullable TextEmphasis textEmphasis = createTextEmphasis(value); assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull(); - assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_FILLED_DOT); - assertThat(textEmphasis.position).isEqualTo(TextAnnotation.POSITION_BEFORE); + assertWithMessage("markShape").that(textEmphasis.markShape) + .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 public void testFilledCircleBefore() { String value = "filled circle Before"; - TextEmphasis textEmphasis = createTextEmphasis(value); - + @Nullable TextEmphasis textEmphasis = createTextEmphasis(value); assertWithMessage("Text Emphasis must exist").that(textEmphasis).isNotNull(); - assertThat(textEmphasis.mark).isEqualTo(TextEmphasisSpan.MARK_FILLED_CIRCLE); - assertThat(textEmphasis.position).isEqualTo(TextAnnotation.POSITION_BEFORE); + 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 testFilledSesameBefore() { String value = "filled sesame Before"; - TextEmphasis textEmphasis = createTextEmphasis(value); - + @Nullable 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); + 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 testBeforeFilledSesame() { String value = "before filled sesame"; - TextEmphasis textEmphasis = createTextEmphasis(value); - + @Nullable 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); + 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 testBeforeSesameFilled() { String value = "before sesame filled"; - TextEmphasis textEmphasis = createTextEmphasis(value); - + @Nullable 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); + 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 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); } } diff --git a/library/core/src/test/java/com/google/android/exoplayer2/text/ttml/TtmlDecoderTest.java b/library/core/src/test/java/com/google/android/exoplayer2/text/ttml/TtmlDecoderTest.java index c4245572be..f9711a854e 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/text/ttml/TtmlDecoderTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/text/ttml/TtmlDecoderTest.java @@ -682,68 +682,80 @@ public final class TtmlDecoderTest { TtmlSubtitle subtitle = getSubtitle(TEXT_EMPHASIS_FILE); 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); assertThat(secondCue) .hasTextEmphasisSpanBetween("Auto ".length(), "Auto ございます".length()) - .withMarkAndPosition(TextEmphasisSpan.MARK_FILLED_CIRCLE, + .withMarkAndPosition(TextEmphasisSpan.MARK_SHAPE_CIRCLE, + TextEmphasisSpan.MARK_FILL_UNSPECIFIED, TextAnnotation.POSITION_BEFORE); Spanned thirdCue = getOnlyCueTextAtTimeUs(subtitle, 30_000_000); assertThat(thirdCue) .hasTextEmphasisSpanBetween("Filled circle ".length(), "Filled circle こんばんは".length()) - .withMarkAndPosition(TextEmphasisSpan.MARK_FILLED_CIRCLE, + .withMarkAndPosition(TextEmphasisSpan.MARK_SHAPE_CIRCLE, TextEmphasisSpan.MARK_FILL_FILLED, TextAnnotation.POSITION_BEFORE); Spanned fourthCue = getOnlyCueTextAtTimeUs(subtitle, 40_000_000); assertThat(fourthCue) .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); assertThat(fifthCue) .hasTextEmphasisSpanBetween("Filled sesame ".length(), "Filled sesame おはよ".length()) - .withMarkAndPosition(TextEmphasisSpan.MARK_FILLED_SESAME, + .withMarkAndPosition(TextEmphasisSpan.MARK_SHAPE_SESAME, TextEmphasisSpan.MARK_FILL_FILLED, TextAnnotation.POSITION_BEFORE); Spanned sixthCue = getOnlyCueTextAtTimeUs(subtitle, 60_000_000); assertThat(sixthCue) .hasTextEmphasisSpanBetween("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); assertThat(seventhCue) .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); assertThat(eighthCue) .hasTextEmphasisSpanBetween("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); assertThat(ninthCue) .hasTextEmphasisSpanBetween("Auto outside ".length(), "Auto outside おはよ".length()) - .withMarkAndPosition(TextEmphasisSpan.MARK_FILLED_CIRCLE, + .withMarkAndPosition(TextEmphasisSpan.MARK_SHAPE_CIRCLE, + TextEmphasisSpan.MARK_FILL_UNSPECIFIED, TextAnnotation.POSITION_BEFORE); Spanned tenthCue = getOnlyCueTextAtTimeUs(subtitle, 100_000_000); assertThat(tenthCue) .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); assertThat(eleventhCue) .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); assertThat(twelfthCue) .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); assertThat(thirteenthCue) @@ -753,25 +765,29 @@ public final class TtmlDecoderTest { Spanned fourteenthCue = getOnlyCueTextAtTimeUs(subtitle, 140_000_000); assertThat(fourteenthCue) .hasTextEmphasisSpanBetween("Auto (TBLR) ".length(), "Auto (TBLR) ございます".length()) - .withMarkAndPosition(TextEmphasisSpan.MARK_FILLED_SESAME, + .withMarkAndPosition(TextEmphasisSpan.MARK_SHAPE_SESAME, + TextEmphasisSpan.MARK_FILL_UNSPECIFIED, TextAnnotation.POSITION_BEFORE); Spanned fifteenthCue = getOnlyCueTextAtTimeUs(subtitle, 150_000_000); assertThat(fifteenthCue) .hasTextEmphasisSpanBetween("Auto (TBRL) ".length(), "Auto (TBRL) おはよ".length()) - .withMarkAndPosition(TextEmphasisSpan.MARK_FILLED_SESAME, + .withMarkAndPosition(TextEmphasisSpan.MARK_SHAPE_SESAME, + TextEmphasisSpan.MARK_FILL_UNSPECIFIED, TextAnnotation.POSITION_BEFORE); Spanned sixteenthCue = getOnlyCueTextAtTimeUs(subtitle, 160_000_000); assertThat(sixteenthCue) .hasTextEmphasisSpanBetween("Auto (TB) ".length(), "Auto (TB) ございます".length()) - .withMarkAndPosition(TextEmphasisSpan.MARK_FILLED_SESAME, + .withMarkAndPosition(TextEmphasisSpan.MARK_SHAPE_SESAME, + TextEmphasisSpan.MARK_FILL_UNSPECIFIED, TextAnnotation.POSITION_BEFORE); Spanned seventeenthCue = getOnlyCueTextAtTimeUs(subtitle, 170_000_000); assertThat(seventeenthCue) .hasTextEmphasisSpanBetween("Auto (LR) ".length(), "Auto (LR) おはよ".length()) - .withMarkAndPosition(TextEmphasisSpan.MARK_FILLED_CIRCLE, + .withMarkAndPosition(TextEmphasisSpan.MARK_SHAPE_CIRCLE, + TextEmphasisSpan.MARK_FILL_UNSPECIFIED, TextAnnotation.POSITION_BEFORE); } diff --git a/library/core/src/test/java/com/google/android/exoplayer2/text/ttml/TtmlStyleTest.java b/library/core/src/test/java/com/google/android/exoplayer2/text/ttml/TtmlStyleTest.java index 8f6556c463..22b39665e9 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/text/ttml/TtmlStyleTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/text/ttml/TtmlStyleTest.java @@ -17,8 +17,6 @@ package com.google.android.exoplayer2.text.ttml; 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_OPEN_SESAME; 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_ITALIC; @@ -32,6 +30,7 @@ import android.text.Layout; import androidx.annotation.ColorInt; import androidx.test.ext.junit.runners.AndroidJUnit4; import com.google.android.exoplayer2.text.span.TextAnnotation; +import com.google.android.exoplayer2.text.span.TextEmphasisSpan; import org.junit.Test; import org.junit.runner.RunWith; @@ -92,7 +91,8 @@ public final class TtmlStyleTest { .that(style.hasBackgroundColor()) .isFalse(); 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); } @@ -118,7 +118,8 @@ public final class TtmlStyleTest { .isEqualTo(BACKGROUND_COLOR); assertWithMessage("rubyType should be chained").that(style.getRubyType()).isEqualTo(RUBY_TYPE); 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); } @@ -262,7 +263,8 @@ public final class TtmlStyleTest { TtmlStyle style = new TtmlStyle(); assertThat(style.getTextEmphasis()).isNull(); 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); } } diff --git a/library/ui/src/main/java/com/google/android/exoplayer2/ui/SpannedToHtmlConverter.java b/library/ui/src/main/java/com/google/android/exoplayer2/ui/SpannedToHtmlConverter.java index 0c81ac1931..13d78c10c8 100644 --- a/library/ui/src/main/java/com/google/android/exoplayer2/ui/SpannedToHtmlConverter.java +++ b/library/ui/src/main/java/com/google/android/exoplayer2/ui/SpannedToHtmlConverter.java @@ -201,12 +201,13 @@ import java.util.regex.Pattern; return ""; } else if (span instanceof TextEmphasisSpan) { TextEmphasisSpan textEmphasisSpan = (TextEmphasisSpan) span; - String style = getTextEmphasisStyle(textEmphasisSpan.mark); + String style = getTextEmphasisStyle(textEmphasisSpan.markShape, textEmphasisSpan.markFill); String position = getTextEmphasisPosition(textEmphasisSpan.position); return Util - .formatInvariant("", - style, style, position, position); + .formatInvariant( + "", + style, position); } else { return null; } @@ -243,23 +244,39 @@ import java.util.regex.Pattern; return null; } - private static String getTextEmphasisStyle(@TextEmphasisSpan.Mark int mark) { - switch (mark) { - case TextEmphasisSpan.MARK_FILLED_CIRCLE: - return "filled circle"; - case TextEmphasisSpan.MARK_FILLED_DOT: - return "filled dot"; - case TextEmphasisSpan.MARK_FILLED_SESAME: - return "filled sesame"; - case TextEmphasisSpan.MARK_OPEN_CIRCLE: - return "open circle"; - case TextEmphasisSpan.MARK_OPEN_DOT: - return "open dot"; - case TextEmphasisSpan.MARK_OPEN_SESAME: - return "open sesame"; + private static String getTextEmphasisStyle(@TextEmphasisSpan.MarkShape int shape, + @TextEmphasisSpan.MarkFill int fill) { + StringBuilder builder = new StringBuilder(); + switch (fill) { + case TextEmphasisSpan.MARK_FILL_FILLED: + builder.append("filled "); + break; + case TextEmphasisSpan.MARK_FILL_OPEN: + builder.append("open "); + break; + case TextEmphasisSpan.MARK_FILL_UNSPECIFIED: 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){ diff --git a/library/ui/src/test/java/com/google/android/exoplayer2/ui/SpannedToHtmlConverterTest.java b/library/ui/src/test/java/com/google/android/exoplayer2/ui/SpannedToHtmlConverterTest.java index f3b95e9d42..49062d2233 100644 --- a/library/ui/src/test/java/com/google/android/exoplayer2/ui/SpannedToHtmlConverterTest.java +++ b/library/ui/src/test/java/com/google/android/exoplayer2/ui/SpannedToHtmlConverterTest.java @@ -285,13 +285,15 @@ public class SpannedToHtmlConverterTest { public void convert_supportsTextEmphasisSpan() { SpannableString spanned = new SpannableString("Text emphasis おはよ ございます "); 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(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 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(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); diff --git a/testutils/src/main/java/com/google/android/exoplayer2/testutil/truth/SpannedSubject.java b/testutils/src/main/java/com/google/android/exoplayer2/testutil/truth/SpannedSubject.java index 20109d29b9..b9f05c9e87 100644 --- a/testutils/src/main/java/com/google/android/exoplayer2/testutil/truth/SpannedSubject.java +++ b/testutils/src/main/java/com/google/android/exoplayer2/testutil/truth/SpannedSubject.java @@ -1156,20 +1156,21 @@ public final class SpannedSubject extends Subject { /** Allows assertions about a span's textEmphasis mark and its position. */ public interface TextEmphasisDescription { - /** * 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 * @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); } private static final TextEmphasisDescription ALREADY_FAILED_WITH_MARK = - (mark, position) -> ALREADY_FAILED_AND_FLAGS; + (markShape, markFill, position) -> ALREADY_FAILED_AND_FLAGS; private static Factory> textEmphasisSubjects(Spanned actualSpanned) { return (FailureMetadata metadata, List spans) -> @@ -1189,32 +1190,38 @@ public final class SpannedSubject extends Subject { } @Override - public AndSpanFlags withMarkAndPosition(@TextEmphasisSpan.Mark int mark, + public AndSpanFlags withMarkAndPosition(@TextEmphasisSpan.MarkShape int markShape, + @TextEmphasisSpan.MarkFill int markFill, @TextAnnotation.Position int position) { List matchingSpanFlags = new ArrayList<>(); List textEmphasisMarksAndPositions = new ArrayList<>(); for (TextEmphasisSpan span : actualSpans) { - textEmphasisMarksAndPositions.add(new MarkAndPosition(span.mark, span.position)); - if (span.mark == mark && span.position == position) { + textEmphasisMarksAndPositions + .add(new MarkAndPosition(span.markShape, span.markFill, span.position)); + if (span.markFill == markFill && span.markShape == markShape && span.position == position) { matchingSpanFlags.add(actualSpanned.getSpanFlags(span)); } } check("textEmphasisMarkAndPosition") .that(textEmphasisMarksAndPositions) - .containsExactly(new MarkAndPosition(mark, position)); + .containsExactly(new MarkAndPosition(markShape, markFill, position)); return check("flags").about(spanFlags()).that(matchingSpanFlags); } private static final class MarkAndPosition { - @TextEmphasisSpan.Mark - private final int mark; + @TextEmphasisSpan.MarkShape + private final int markShape; + @TextEmphasisSpan.MarkFill + private final int markFill; @TextAnnotation.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) { - this.mark = mark; + this.markFill = markFill; + this.markShape = markShape; this.position = position; } @@ -1228,18 +1235,20 @@ public final class SpannedSubject extends Subject { } TextEmphasisSubject.MarkAndPosition that = (TextEmphasisSubject.MarkAndPosition) o; - return (position == that.position) && (mark == that.mark); + return (position == that.position) && (markShape == that.markShape) && (markFill + == that.markFill); } @Override public int hashCode() { - int result = 34613 * mark + position; + int result = 34613 * markFill + 1993 * markShape + position; return result; } @Override public String toString() { - return String.format("{mark=%s,position=%s}", mark, position); + return String + .format("{markShape=%s, markFill=%s, position=%s}", markShape, markFill, position); } } }