[go: nahoru, domu]

blob: 174eb7e3e6bcbd525ecec0edfed4e75e456c4acb [file] [log] [blame]
Siyamed Sinirff51df92019-07-02 15:35:20 -07001package androidx.ui.text.platform
Haoyu Zhang10fc6502018-11-09 15:50:11 -08002
Haoyu Zhang10fc6502018-11-09 15:50:11 -08003import android.graphics.Paint
Haoyu Zhang10fc6502018-11-09 15:50:11 -08004import android.text.TextPaint
Haoyu Zhangbb51ccf2018-12-17 15:07:43 -08005import android.text.style.AbsoluteSizeSpan
Haoyu Zhang0c4fd022019-01-02 13:53:10 -08006import android.text.style.BackgroundColorSpan
Haoyu Zhang47f57a22018-12-12 13:16:40 -08007import android.text.style.ForegroundColorSpan
Haoyu Zhang7fc59172019-03-01 17:03:31 -08008import android.text.style.LeadingMarginSpan
Haoyu Zhang4b201d22018-12-18 14:27:38 -08009import android.text.style.LocaleSpan
Haoyu Zhang24eb32f2019-05-21 16:16:37 -070010import android.text.style.RelativeSizeSpan
Haoyu Zhang15750922019-02-19 13:44:17 -080011import android.text.style.ScaleXSpan
Haoyu Zhangb5677202018-12-19 14:22:18 -080012import android.text.style.StrikethroughSpan
13import android.text.style.UnderlineSpan
Haoyu Zhang10fc6502018-11-09 15:50:11 -080014import androidx.test.filters.SmallTest
15import androidx.test.platform.app.InstrumentationRegistry
Siyamed Sinir97d0ccf2019-11-02 02:51:24 -070016import androidx.text.TextLayout
Haoyu Zhang40ce6bf2019-01-28 15:58:20 -080017import androidx.text.style.BaselineShiftSpan
Haoyu Zhang588aaef2019-02-20 14:47:39 -080018import androidx.text.style.FontFeatureSpan
Haoyu Zhang1588ba0f2018-12-19 16:47:10 -080019import androidx.text.style.LetterSpacingSpan
Haoyu Zhang2a036c832019-03-08 11:57:13 -080020import androidx.text.style.ShadowSpan
Haoyu Zhang15750922019-02-19 13:44:17 -080021import androidx.text.style.SkewXSpan
Siyamed Sinir70f336a2018-12-27 10:37:09 -080022import androidx.text.style.TypefaceSpan
Siyamed Sinir7d4c98f2019-06-27 16:23:31 -070023import androidx.ui.core.Density
Haoyu Zhangf2e9e032019-10-16 15:23:39 -070024import androidx.ui.core.em
Haoyu Zhang7fc59172019-03-01 17:03:31 -080025import androidx.ui.core.px
Siyamed Sinir7d4c98f2019-06-27 16:23:31 -070026import androidx.ui.core.sp
27import androidx.ui.core.withDensity
Haoyu Zhang2a036c832019-03-08 11:57:13 -080028import androidx.ui.engine.geometry.Offset
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -070029import androidx.ui.graphics.Color
Nader Jawadad983532019-08-29 16:27:37 -070030import androidx.ui.graphics.Shadow
Siyamed Sinir63789c92019-09-25 10:44:11 -070031import androidx.ui.graphics.toArgb
32import androidx.ui.text.AnnotatedString
33import androidx.ui.text.FontTestData.Companion.BASIC_MEASURE_FONT
Seigo Nonaka8de69792019-09-04 14:55:15 -070034import androidx.ui.text.LocaleList
Siyamed Sinir63789c92019-09-25 10:44:11 -070035import androidx.ui.text.ParagraphConstraints
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -080036import androidx.ui.text.SpanStyle
Siyamed Sinirc4c308e2019-07-03 16:14:22 -070037import androidx.ui.text.TestFontResourceLoader
Siyamed Sinir01f7b522019-12-06 00:14:02 -080038import androidx.ui.text.TextStyle
Siyamed Sinir63789c92019-09-25 10:44:11 -070039import androidx.ui.text.font.FontFamily
40import androidx.ui.text.font.FontStyle
41import androidx.ui.text.font.FontSynthesis
42import androidx.ui.text.font.FontWeight
43import androidx.ui.text.font.asFontFamily
44import androidx.ui.text.matchers.assertThat
45import androidx.ui.text.style.BaselineShift
46import androidx.ui.text.style.TextAlign
47import androidx.ui.text.style.TextDecoration
Seigo Nonakac4f136a2019-08-16 16:48:44 -070048import androidx.ui.text.style.TextDirectionAlgorithm
Siyamed Sinir63789c92019-09-25 10:44:11 -070049import androidx.ui.text.style.TextGeometricTransform
50import androidx.ui.text.style.TextIndent
51import com.google.common.truth.Truth.assertThat
Siyamed Sinirf18dcca2018-12-20 18:25:10 -080052import com.nhaarman.mockitokotlin2.any
53import com.nhaarman.mockitokotlin2.eq
54import com.nhaarman.mockitokotlin2.mock
55import com.nhaarman.mockitokotlin2.never
56import com.nhaarman.mockitokotlin2.spy
57import com.nhaarman.mockitokotlin2.times
58import com.nhaarman.mockitokotlin2.verify
Haoyu Zhang10fc6502018-11-09 15:50:11 -080059import org.junit.Test
60import org.junit.runner.RunWith
61import org.junit.runners.JUnit4
Haoyu Zhang10fc6502018-11-09 15:50:11 -080062import kotlin.math.ceil
63
64@RunWith(JUnit4::class)
65@SmallTest
Siyamed Sinire75976f2019-07-03 09:24:30 -070066class AndroidParagraphTest {
Siyamed Sinir472ed132019-07-03 15:43:43 -070067 // This sample font provides the following features:
68 // 1. The width of most of visible characters equals to font size.
69 // 2. The LTR/RTL characters are rendered as â–¶/â—€.
70 // 3. The fontMetrics passed to TextPaint has descend - ascend equal to 1.2 * fontSize.
71 private val fontFamily = BASIC_MEASURE_FONT.asFontFamily()
Siyamed Sinir7d4c98f2019-06-27 16:23:31 -070072 private val defaultDensity = Density(density = 1f)
Siyamed Sinir472ed132019-07-03 15:43:43 -070073 private val context = InstrumentationRegistry.getInstrumentation().context
Haoyu Zhang10fc6502018-11-09 15:50:11 -080074
75 @Test
76 fun draw_with_newline_and_line_break_default_values() {
Siyamed Sinir7d4c98f2019-06-27 16:23:31 -070077 withDensity(defaultDensity) {
78 val fontSize = 50.sp
79 for (text in arrayOf("abc\ndef", "\u05D0\u05D1\u05D2\n\u05D3\u05D4\u05D5")) {
80 val paragraphAndroid = simpleParagraph(
81 text = text,
Siyamed Sinir01f7b522019-12-06 00:14:02 -080082 style = TextStyle(
Siyamed Sinir7d4c98f2019-06-27 16:23:31 -070083 fontSize = fontSize,
84 fontFamily = fontFamily
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -070085 ),
86 // 2 chars width
87 constraints = ParagraphConstraints(width = 2 * fontSize.toPx().value)
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -070088 )
Haoyu Zhang10fc6502018-11-09 15:50:11 -080089
Siyamed Sinir7d4c98f2019-06-27 16:23:31 -070090 val textPaint = TextPaint(Paint.ANTI_ALIAS_FLAG)
91 textPaint.textSize = fontSize.toPx().value
92 textPaint.typeface = TypefaceAdapter().create(fontFamily)
Haoyu Zhang10fc6502018-11-09 15:50:11 -080093
Siyamed Sinir97d0ccf2019-11-02 02:51:24 -070094 val layout = TextLayout(
95 charSequence = text,
96 width = ceil(paragraphAndroid.width),
97 textPaint = textPaint
Siyamed Sinir7d4c98f2019-06-27 16:23:31 -070098 )
Siyamed Sinir97d0ccf2019-11-02 02:51:24 -070099
100 assertThat(paragraphAndroid.bitmap()).isEqualToBitmap(layout.bitmap())
Siyamed Sinir7d4c98f2019-06-27 16:23:31 -0700101 }
Haoyu Zhang10fc6502018-11-09 15:50:11 -0800102 }
103 }
104
Haoyu Zhang47f57a22018-12-12 13:16:40 -0800105 @Test
haoyua8e48a52019-06-25 12:23:27 -0700106 fun testAnnotatedString_setColorOnWholeText() {
Haoyu Zhang47f57a22018-12-12 13:16:40 -0800107 val text = "abcde"
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800108 val spanStyle = SpanStyle(color = Color(0xFF0000FF))
Haoyu Zhang47f57a22018-12-12 13:16:40 -0800109
110 val paragraph = simpleParagraph(
111 text = text,
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800112 spanStyles = listOf(AnnotatedString.Item(spanStyle, 0, text.length)),
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700113 constraints = ParagraphConstraints(width = 100.0f)
Haoyu Zhang47f57a22018-12-12 13:16:40 -0800114 )
Haoyu Zhang47f57a22018-12-12 13:16:40 -0800115
Siyamed Sinir63789c92019-09-25 10:44:11 -0700116 assertThat(paragraph.charSequence).hasSpan(ForegroundColorSpan::class, 0, text.length)
Haoyu Zhang47f57a22018-12-12 13:16:40 -0800117 }
118
119 @Test
haoyua8e48a52019-06-25 12:23:27 -0700120 fun testAnnotatedString_setColorOnPartOfText() {
Haoyu Zhang47f57a22018-12-12 13:16:40 -0800121 val text = "abcde"
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800122 val spanStyle = SpanStyle(color = Color(0xFF0000FF))
Haoyu Zhang47f57a22018-12-12 13:16:40 -0800123
124 val paragraph = simpleParagraph(
125 text = text,
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800126 spanStyles = listOf(AnnotatedString.Item(spanStyle, 0, "abc".length)),
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700127 constraints = ParagraphConstraints(width = 100.0f)
Haoyu Zhang47f57a22018-12-12 13:16:40 -0800128 )
Haoyu Zhang47f57a22018-12-12 13:16:40 -0800129
Siyamed Sinir63789c92019-09-25 10:44:11 -0700130 assertThat(paragraph.charSequence).hasSpan(ForegroundColorSpan::class, 0, "abc".length)
Haoyu Zhang47f57a22018-12-12 13:16:40 -0800131 }
132
133 @Test
haoyua8e48a52019-06-25 12:23:27 -0700134 fun testAnnotatedString_setColorTwice_lastOneOverwrite() {
Haoyu Zhang47f57a22018-12-12 13:16:40 -0800135 val text = "abcde"
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800136 val spanStyle = SpanStyle(color = Color(0xFF0000FF))
137 val spanStyleOverwrite = SpanStyle(color = Color(0xFF00FF00))
Haoyu Zhang47f57a22018-12-12 13:16:40 -0800138
139 val paragraph = simpleParagraph(
140 text = text,
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800141 spanStyles = listOf(
142 AnnotatedString.Item(spanStyle, 0, text.length),
143 AnnotatedString.Item(spanStyleOverwrite, 0, "abc".length)
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700144 ),
145 constraints = ParagraphConstraints(width = 100.0f)
Haoyu Zhang47f57a22018-12-12 13:16:40 -0800146 )
Haoyu Zhang47f57a22018-12-12 13:16:40 -0800147
Siyamed Sinir63789c92019-09-25 10:44:11 -0700148 assertThat(paragraph.charSequence).hasSpan(ForegroundColorSpan::class, 0, text.length)
149 assertThat(paragraph.charSequence).hasSpan(ForegroundColorSpan::class, 0, "abc".length)
150 assertThat(paragraph.charSequence).hasSpanOnTop(ForegroundColorSpan::class, 0, "abc".length)
Haoyu Zhang47f57a22018-12-12 13:16:40 -0800151 }
152
Haoyu Zhangbb51ccf2018-12-17 15:07:43 -0800153 @Test
Haoyu Zhangb5677202018-12-19 14:22:18 -0800154 fun testStyle_setTextDecorationOnWholeText_withLineThrough() {
155 val text = "abcde"
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800156 val spanStyle = SpanStyle(decoration = TextDecoration.LineThrough)
Haoyu Zhangb5677202018-12-19 14:22:18 -0800157
158 val paragraph = simpleParagraph(
159 text = text,
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800160 spanStyles = listOf(AnnotatedString.Item(spanStyle, 0, text.length)),
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700161 constraints = ParagraphConstraints(width = 100.0f)
Haoyu Zhangb5677202018-12-19 14:22:18 -0800162 )
Haoyu Zhangb5677202018-12-19 14:22:18 -0800163
Siyamed Sinir63789c92019-09-25 10:44:11 -0700164 assertThat(paragraph.charSequence.toString()).isEqualTo(text)
165 assertThat(paragraph.charSequence).hasSpan(StrikethroughSpan::class, 0, text.length)
Haoyu Zhangb5677202018-12-19 14:22:18 -0800166 }
167
168 @Test
169 fun testStyle_setTextDecorationOnWholeText_withUnderline() {
170 val text = "abcde"
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800171 val spanStyle = SpanStyle(decoration = TextDecoration.Underline)
Haoyu Zhangb5677202018-12-19 14:22:18 -0800172
173 val paragraph = simpleParagraph(
174 text = text,
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800175 spanStyles = listOf(AnnotatedString.Item(spanStyle, 0, text.length)),
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700176 constraints = ParagraphConstraints(width = 100.0f)
Haoyu Zhangb5677202018-12-19 14:22:18 -0800177 )
Haoyu Zhangb5677202018-12-19 14:22:18 -0800178
Siyamed Sinir63789c92019-09-25 10:44:11 -0700179 assertThat(paragraph.charSequence.toString()).isEqualTo(text)
180 assertThat(paragraph.charSequence).hasSpan(UnderlineSpan::class, 0, text.length)
Haoyu Zhangb5677202018-12-19 14:22:18 -0800181 }
182
183 @Test
184 fun testStyle_setTextDecorationOnPartText_withLineThrough() {
185 val text = "abcde"
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800186 val spanStyle = SpanStyle(decoration = TextDecoration.LineThrough)
Haoyu Zhangb5677202018-12-19 14:22:18 -0800187
188 val paragraph = simpleParagraph(
189 text = text,
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800190 spanStyles = listOf(AnnotatedString.Item(spanStyle, 0, "abc".length)),
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700191 constraints = ParagraphConstraints(width = 100.0f)
Haoyu Zhangb5677202018-12-19 14:22:18 -0800192 )
Haoyu Zhangb5677202018-12-19 14:22:18 -0800193
Siyamed Sinir63789c92019-09-25 10:44:11 -0700194 assertThat(paragraph.charSequence.toString()).isEqualTo(text)
195 assertThat(paragraph.charSequence).hasSpan(StrikethroughSpan::class, 0, "abc".length)
Haoyu Zhangb5677202018-12-19 14:22:18 -0800196 }
197
198 @Test
199 fun testStyle_setTextDecorationOnPartText_withUnderline() {
200 val text = "abcde"
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800201 val spanStyle = SpanStyle(decoration = TextDecoration.Underline)
Haoyu Zhangb5677202018-12-19 14:22:18 -0800202
203 val paragraph = simpleParagraph(
204 text = text,
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800205 spanStyles = listOf(AnnotatedString.Item(spanStyle, 0, "abc".length)),
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700206 constraints = ParagraphConstraints(width = 100.0f)
Haoyu Zhangb5677202018-12-19 14:22:18 -0800207 )
Haoyu Zhangb5677202018-12-19 14:22:18 -0800208
Siyamed Sinir63789c92019-09-25 10:44:11 -0700209 assertThat(paragraph.charSequence.toString()).isEqualTo(text)
210 assertThat(paragraph.charSequence).hasSpan(UnderlineSpan::class, 0, "abc".length)
Haoyu Zhangb5677202018-12-19 14:22:18 -0800211 }
212
213 @Test
214 fun testStyle_setTextDecoration_withLineThroughAndUnderline() {
215 val text = "abcde"
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800216 val spanStyle = SpanStyle(
Haoyu Zhangb5677202018-12-19 14:22:18 -0800217 decoration = TextDecoration.combine(
Siyamed Sinir9fd89f42019-05-20 18:04:29 -0700218 listOf(TextDecoration.LineThrough, TextDecoration.Underline)
Haoyu Zhangb5677202018-12-19 14:22:18 -0800219 )
220 )
221
222 val paragraph = simpleParagraph(
223 text = text,
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800224 spanStyles = listOf(AnnotatedString.Item(spanStyle, 0, "abc".length)),
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700225 constraints = ParagraphConstraints(width = 100.0f)
Haoyu Zhangb5677202018-12-19 14:22:18 -0800226 )
Haoyu Zhangb5677202018-12-19 14:22:18 -0800227
Siyamed Sinir63789c92019-09-25 10:44:11 -0700228 assertThat(paragraph.charSequence.toString()).isEqualTo(text)
229 assertThat(paragraph.charSequence).hasSpan(UnderlineSpan::class, 0, "abc".length)
230 assertThat(paragraph.charSequence).hasSpan(StrikethroughSpan::class, 0, "abc".length)
Haoyu Zhangb5677202018-12-19 14:22:18 -0800231 }
232
233 @Test
haoyua8e48a52019-06-25 12:23:27 -0700234 fun testAnnotatedString_setFontSizeOnWholeText() {
Siyamed Sinir7d4c98f2019-06-27 16:23:31 -0700235 withDensity(defaultDensity) {
236 val text = "abcde"
237 val fontSize = 20.sp
238 val paragraphWidth = text.length * fontSize.toPx().value
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800239 val spanStyle = SpanStyle(fontSize = fontSize)
Haoyu Zhangbb51ccf2018-12-17 15:07:43 -0800240
Siyamed Sinir7d4c98f2019-06-27 16:23:31 -0700241 val paragraph = simpleParagraph(
242 text = text,
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800243 spanStyles = listOf(AnnotatedString.Item(spanStyle, 0, text.length)),
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700244 constraints = ParagraphConstraints(width = paragraphWidth)
Siyamed Sinir7d4c98f2019-06-27 16:23:31 -0700245 )
Haoyu Zhangbb51ccf2018-12-17 15:07:43 -0800246
Siyamed Sinir63789c92019-09-25 10:44:11 -0700247 assertThat(paragraph.charSequence).hasSpan(AbsoluteSizeSpan::class, 0, text.length)
Siyamed Sinir7d4c98f2019-06-27 16:23:31 -0700248 }
Haoyu Zhangbb51ccf2018-12-17 15:07:43 -0800249 }
250
251 @Test
haoyua8e48a52019-06-25 12:23:27 -0700252 fun testAnnotatedString_setFontSizeOnPartText() {
Siyamed Sinir7d4c98f2019-06-27 16:23:31 -0700253 withDensity(defaultDensity) {
254 val text = "abcde"
255 val fontSize = 20.sp
256 val paragraphWidth = text.length * fontSize.toPx().value
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800257 val spanStyle = SpanStyle(fontSize = fontSize)
Haoyu Zhangbb51ccf2018-12-17 15:07:43 -0800258
Siyamed Sinir7d4c98f2019-06-27 16:23:31 -0700259 val paragraph = simpleParagraph(
260 text = text,
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800261 spanStyles = listOf(AnnotatedString.Item(spanStyle, 0, "abc".length)),
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700262 constraints = ParagraphConstraints(width = paragraphWidth)
Siyamed Sinir7d4c98f2019-06-27 16:23:31 -0700263 )
Haoyu Zhangbb51ccf2018-12-17 15:07:43 -0800264
Siyamed Sinir63789c92019-09-25 10:44:11 -0700265 assertThat(paragraph.charSequence).hasSpan(AbsoluteSizeSpan::class, 0, "abc".length)
Siyamed Sinir7d4c98f2019-06-27 16:23:31 -0700266 }
Haoyu Zhangbb51ccf2018-12-17 15:07:43 -0800267 }
268
269 @Test
haoyua8e48a52019-06-25 12:23:27 -0700270 fun testAnnotatedString_setFontSizeTwice_lastOneOverwrite() {
Siyamed Sinir7d4c98f2019-06-27 16:23:31 -0700271 withDensity(defaultDensity) {
272 val text = "abcde"
273 val fontSize = 20.sp
274 val fontSizeOverwrite = 30.sp
275 val paragraphWidth = text.length * fontSizeOverwrite.toPx().value
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800276 val spanStyle = SpanStyle(fontSize = fontSize)
277 val spanStyleOverwrite = SpanStyle(fontSize = fontSizeOverwrite)
Haoyu Zhangbb51ccf2018-12-17 15:07:43 -0800278
Siyamed Sinir7d4c98f2019-06-27 16:23:31 -0700279 val paragraph = simpleParagraph(
280 text = text,
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800281 spanStyles = listOf(
282 AnnotatedString.Item(spanStyle, 0, text.length),
283 AnnotatedString.Item(spanStyleOverwrite, 0, "abc".length)
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700284 ),
285 constraints = ParagraphConstraints(width = paragraphWidth)
Haoyu Zhangbb51ccf2018-12-17 15:07:43 -0800286 )
Haoyu Zhangbb51ccf2018-12-17 15:07:43 -0800287
Siyamed Sinir63789c92019-09-25 10:44:11 -0700288 assertThat(paragraph.charSequence).hasSpan(AbsoluteSizeSpan::class, 0, text.length)
289 assertThat(paragraph.charSequence).hasSpan(AbsoluteSizeSpan::class, 0, "abc".length)
290 assertThat(paragraph.charSequence)
291 .hasSpanOnTop(AbsoluteSizeSpan::class, 0, "abc".length)
Siyamed Sinir7d4c98f2019-06-27 16:23:31 -0700292 }
Haoyu Zhangbb51ccf2018-12-17 15:07:43 -0800293 }
294
Haoyu Zhang1588ba0f2018-12-19 16:47:10 -0800295 @Test
haoyua8e48a52019-06-25 12:23:27 -0700296 fun testAnnotatedString_setFontSizeScaleOnWholeText() {
Haoyu Zhang24eb32f2019-05-21 16:16:37 -0700297 val text = "abcde"
Seigo Nonakad9638202019-11-19 16:37:07 -0800298 val fontSizeScale = 2.0.em
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800299 val spanStyle = SpanStyle(fontSize = fontSizeScale)
Haoyu Zhang24eb32f2019-05-21 16:16:37 -0700300
301 val paragraph = simpleParagraph(
302 text = text,
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800303 spanStyles = listOf(AnnotatedString.Item(spanStyle, 0, text.length)),
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700304 constraints = ParagraphConstraints(width = 100.0f)
Haoyu Zhang24eb32f2019-05-21 16:16:37 -0700305 )
Haoyu Zhang24eb32f2019-05-21 16:16:37 -0700306
Siyamed Sinir63789c92019-09-25 10:44:11 -0700307 assertThat(paragraph.charSequence).hasSpan(RelativeSizeSpan::class, 0, text.length) {
Seigo Nonakad9638202019-11-19 16:37:07 -0800308 it.sizeChange == fontSizeScale.value
Siyamed Sinir63789c92019-09-25 10:44:11 -0700309 }
Haoyu Zhang24eb32f2019-05-21 16:16:37 -0700310 }
311
312 @Test
haoyua8e48a52019-06-25 12:23:27 -0700313 fun testAnnotatedString_setFontSizeScaleOnPartText() {
Haoyu Zhang24eb32f2019-05-21 16:16:37 -0700314 val text = "abcde"
Seigo Nonakad9638202019-11-19 16:37:07 -0800315 val fontSizeScale = 2.0f.em
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800316 val spanStyle = SpanStyle(fontSize = fontSizeScale)
Haoyu Zhang24eb32f2019-05-21 16:16:37 -0700317
318 val paragraph = simpleParagraph(
319 text = text,
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800320 spanStyles = listOf(AnnotatedString.Item(spanStyle, 0, "abc".length)),
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700321 constraints = ParagraphConstraints(width = 100.0f)
Haoyu Zhang24eb32f2019-05-21 16:16:37 -0700322 )
Haoyu Zhang24eb32f2019-05-21 16:16:37 -0700323
Siyamed Sinir63789c92019-09-25 10:44:11 -0700324 assertThat(paragraph.charSequence).hasSpan(RelativeSizeSpan::class, 0, "abc".length) {
Seigo Nonakad9638202019-11-19 16:37:07 -0800325 it.sizeChange == fontSizeScale.value
Siyamed Sinir63789c92019-09-25 10:44:11 -0700326 }
Haoyu Zhang24eb32f2019-05-21 16:16:37 -0700327 }
328
329 @Test
haoyua8e48a52019-06-25 12:23:27 -0700330 fun testAnnotatedString_setLetterSpacingOnWholeText() {
Haoyu Zhang1588ba0f2018-12-19 16:47:10 -0800331 val text = "abcde"
George Mountb1cdd862018-12-21 10:54:42 -0800332 val letterSpacing = 2.0f
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800333 val spanStyle = SpanStyle(letterSpacing = letterSpacing.em)
Haoyu Zhang1588ba0f2018-12-19 16:47:10 -0800334
335 val paragraph = simpleParagraph(
336 text = text,
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800337 spanStyles = listOf(AnnotatedString.Item(spanStyle, 0, text.length)),
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700338 constraints = ParagraphConstraints(width = 100.0f)
Haoyu Zhang1588ba0f2018-12-19 16:47:10 -0800339 )
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700340
Siyamed Sinir63789c92019-09-25 10:44:11 -0700341 assertThat(paragraph.charSequence.toString()).isEqualTo(text)
342 assertThat(paragraph.charSequence).hasSpan(LetterSpacingSpan::class, 0, text.length)
Haoyu Zhang1588ba0f2018-12-19 16:47:10 -0800343 }
344
345 @Test
haoyua8e48a52019-06-25 12:23:27 -0700346 fun testAnnotatedString_setLetterSpacingOnPartText() {
Haoyu Zhang1588ba0f2018-12-19 16:47:10 -0800347 val text = "abcde"
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800348 val spanStyle = SpanStyle(letterSpacing = 2.em)
Haoyu Zhang1588ba0f2018-12-19 16:47:10 -0800349
350 val paragraph = simpleParagraph(
351 text = text,
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800352 spanStyles = listOf(AnnotatedString.Item(spanStyle, 0, "abc".length)),
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700353 constraints = ParagraphConstraints(width = 100.0f)
Haoyu Zhang1588ba0f2018-12-19 16:47:10 -0800354 )
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700355
Siyamed Sinir63789c92019-09-25 10:44:11 -0700356 assertThat(paragraph.charSequence.toString()).isEqualTo(text)
357 assertThat(paragraph.charSequence).hasSpan(LetterSpacingSpan::class, 0, "abc".length)
Haoyu Zhang1588ba0f2018-12-19 16:47:10 -0800358 }
359
360 @Test
haoyua8e48a52019-06-25 12:23:27 -0700361 fun testAnnotatedString_setLetterSpacingTwice_lastOneOverwrite() {
Haoyu Zhang1588ba0f2018-12-19 16:47:10 -0800362 val text = "abcde"
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800363 val spanStyle = SpanStyle(letterSpacing = 2.em)
364 val spanStyleOverwrite = SpanStyle(letterSpacing = 3.em)
Haoyu Zhang1588ba0f2018-12-19 16:47:10 -0800365
366 val paragraph = simpleParagraph(
367 text = text,
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800368 spanStyles = listOf(
369 AnnotatedString.Item(spanStyle, 0, text.length),
370 AnnotatedString.Item(spanStyleOverwrite, 0, "abc".length)
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700371 ),
372 constraints = ParagraphConstraints(width = 100.0f)
Haoyu Zhang1588ba0f2018-12-19 16:47:10 -0800373 )
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700374
Siyamed Sinir63789c92019-09-25 10:44:11 -0700375 assertThat(paragraph.charSequence.toString()).isEqualTo(text)
376 assertThat(paragraph.charSequence).hasSpan(LetterSpacingSpan::class, 0, text.length)
377 assertThat(paragraph.charSequence).hasSpan(LetterSpacingSpan::class, 0, "abc".length)
378 assertThat(paragraph.charSequence).hasSpanOnTop(LetterSpacingSpan::class, 0, "abc".length)
Haoyu Zhang1588ba0f2018-12-19 16:47:10 -0800379 }
380
Siyamed Sinir70f336a2018-12-27 10:37:09 -0800381 @Test
haoyua8e48a52019-06-25 12:23:27 -0700382 fun testAnnotatedString_setBackgroundOnWholeText() {
Haoyu Zhang0c4fd022019-01-02 13:53:10 -0800383 val text = "abcde"
George Mountaa12c482019-08-14 14:51:38 -0700384 val color = Color(0xFF0000FF)
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800385 val spanStyle = SpanStyle(background = color)
Haoyu Zhang0c4fd022019-01-02 13:53:10 -0800386
387 val paragraph = simpleParagraph(
388 text = text,
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800389 spanStyles = listOf(AnnotatedString.Item(spanStyle, 0, text.length)),
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700390 constraints = ParagraphConstraints(width = 100.0f)
Haoyu Zhang0c4fd022019-01-02 13:53:10 -0800391 )
Haoyu Zhang0c4fd022019-01-02 13:53:10 -0800392
Siyamed Sinir63789c92019-09-25 10:44:11 -0700393 assertThat(paragraph.charSequence.toString()).isEqualTo(text)
394 assertThat(paragraph.charSequence)
395 .hasSpan(BackgroundColorSpan::class, 0, text.length) { span ->
George Mounta3145782019-05-02 10:08:03 -0700396 span.backgroundColor == color.toArgb()
Haoyu Zhang0c4fd022019-01-02 13:53:10 -0800397 }
Haoyu Zhang0c4fd022019-01-02 13:53:10 -0800398 }
399
400 @Test
haoyua8e48a52019-06-25 12:23:27 -0700401 fun testAnnotatedString_setBackgroundOnPartText() {
Haoyu Zhang0c4fd022019-01-02 13:53:10 -0800402 val text = "abcde"
George Mountaa12c482019-08-14 14:51:38 -0700403 val color = Color(0xFF0000FF)
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800404 val spanStyle = SpanStyle(background = color)
Haoyu Zhang0c4fd022019-01-02 13:53:10 -0800405
406 val paragraph = simpleParagraph(
407 text = text,
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800408 spanStyles = listOf(AnnotatedString.Item(spanStyle, 0, "abc".length)),
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700409 constraints = ParagraphConstraints(width = 100.0f)
Haoyu Zhang0c4fd022019-01-02 13:53:10 -0800410 )
Haoyu Zhang0c4fd022019-01-02 13:53:10 -0800411
Siyamed Sinir63789c92019-09-25 10:44:11 -0700412 assertThat(paragraph.charSequence.toString()).isEqualTo(text)
413 assertThat(paragraph.charSequence)
414 .hasSpan(BackgroundColorSpan::class, 0, "abc".length) { span ->
George Mounta3145782019-05-02 10:08:03 -0700415 span.backgroundColor == color.toArgb()
Haoyu Zhang0c4fd022019-01-02 13:53:10 -0800416 }
Haoyu Zhang0c4fd022019-01-02 13:53:10 -0800417 }
418
419 @Test
haoyua8e48a52019-06-25 12:23:27 -0700420 fun testAnnotatedString_setBackgroundTwice_lastOneOverwrite() {
Haoyu Zhang0c4fd022019-01-02 13:53:10 -0800421 val text = "abcde"
George Mountaa12c482019-08-14 14:51:38 -0700422 val color = Color(0xFF0000FF)
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800423 val spanStyle = SpanStyle(background = color)
George Mountaa12c482019-08-14 14:51:38 -0700424 val colorOverwrite = Color(0xFF00FF00)
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800425 val spanStyleOverwrite = SpanStyle(background = colorOverwrite)
Haoyu Zhang0c4fd022019-01-02 13:53:10 -0800426
427 val paragraph = simpleParagraph(
428 text = text,
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800429 spanStyles = listOf(
430 AnnotatedString.Item(spanStyle, 0, text.length),
431 AnnotatedString.Item(spanStyleOverwrite, 0, "abc".length)
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700432 ),
433 constraints = ParagraphConstraints(width = 100.0f)
Haoyu Zhang0c4fd022019-01-02 13:53:10 -0800434 )
Haoyu Zhang0c4fd022019-01-02 13:53:10 -0800435
Siyamed Sinir63789c92019-09-25 10:44:11 -0700436 assertThat(paragraph.charSequence.toString()).isEqualTo(text)
437 assertThat(paragraph.charSequence)
438 .hasSpan(BackgroundColorSpan::class, 0, text.length) { span ->
George Mounta3145782019-05-02 10:08:03 -0700439 span.backgroundColor == color.toArgb()
Haoyu Zhang0c4fd022019-01-02 13:53:10 -0800440 }
Siyamed Sinir63789c92019-09-25 10:44:11 -0700441 assertThat(paragraph.charSequence)
442 .hasSpan(BackgroundColorSpan::class, 0, "abc".length) { span ->
George Mounta3145782019-05-02 10:08:03 -0700443 span.backgroundColor == colorOverwrite.toArgb()
Haoyu Zhang0c4fd022019-01-02 13:53:10 -0800444 }
Siyamed Sinir63789c92019-09-25 10:44:11 -0700445 assertThat(paragraph.charSequence)
446 .hasSpanOnTop(BackgroundColorSpan::class, 0, "abc".length) { span ->
George Mounta3145782019-05-02 10:08:03 -0700447 span.backgroundColor == colorOverwrite.toArgb()
Haoyu Zhang0c4fd022019-01-02 13:53:10 -0800448 }
Haoyu Zhang0c4fd022019-01-02 13:53:10 -0800449 }
450
451 @Test
haoyua8e48a52019-06-25 12:23:27 -0700452 fun testAnnotatedString_setLocaleOnWholeText() {
Haoyu Zhang4b201d22018-12-18 14:27:38 -0800453 val text = "abcde"
Seigo Nonaka8de69792019-09-04 14:55:15 -0700454 val localeList = LocaleList("en-US")
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800455 val spanStyle = SpanStyle(localeList = localeList)
Haoyu Zhang4b201d22018-12-18 14:27:38 -0800456
457 val paragraph = simpleParagraph(
458 text = text,
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800459 spanStyles = listOf(AnnotatedString.Item(spanStyle, 0, text.length)),
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700460 constraints = ParagraphConstraints(width = 100.0f)
Haoyu Zhang4b201d22018-12-18 14:27:38 -0800461 )
Haoyu Zhang4b201d22018-12-18 14:27:38 -0800462
Siyamed Sinir63789c92019-09-25 10:44:11 -0700463 assertThat(paragraph.charSequence).hasSpan(LocaleSpan::class, 0, text.length)
Haoyu Zhang4b201d22018-12-18 14:27:38 -0800464 }
465
466 @Test
haoyua8e48a52019-06-25 12:23:27 -0700467 fun testAnnotatedString_setLocaleOnPartText() {
Haoyu Zhang4b201d22018-12-18 14:27:38 -0800468 val text = "abcde"
Seigo Nonaka8de69792019-09-04 14:55:15 -0700469 val localeList = LocaleList("en-US")
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800470 val spanStyle = SpanStyle(localeList = localeList)
Haoyu Zhang4b201d22018-12-18 14:27:38 -0800471
472 val paragraph = simpleParagraph(
473 text = text,
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800474 spanStyles = listOf(AnnotatedString.Item(spanStyle, 0, "abc".length)),
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700475 constraints = ParagraphConstraints(width = 100.0f)
Haoyu Zhang4b201d22018-12-18 14:27:38 -0800476 )
Haoyu Zhang4b201d22018-12-18 14:27:38 -0800477
Siyamed Sinir63789c92019-09-25 10:44:11 -0700478 assertThat(paragraph.charSequence).hasSpan(LocaleSpan::class, 0, "abc".length)
Haoyu Zhang4b201d22018-12-18 14:27:38 -0800479 }
480
481 @Test
haoyua8e48a52019-06-25 12:23:27 -0700482 fun testAnnotatedString_setLocaleTwice_lastOneOverwrite() {
Haoyu Zhang4b201d22018-12-18 14:27:38 -0800483 val text = "abcde"
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800484 val spanStyle = SpanStyle(localeList = LocaleList("en-US"))
485 val spanStyleOverwrite = SpanStyle(localeList = LocaleList("ja-JP"))
Haoyu Zhang4b201d22018-12-18 14:27:38 -0800486
487 val paragraph = simpleParagraph(
488 text = text,
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800489 spanStyles = listOf(
490 AnnotatedString.Item(spanStyle, 0, text.length),
491 AnnotatedString.Item(spanStyleOverwrite, 0, "abc".length)
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700492 ),
493 constraints = ParagraphConstraints(width = 100.0f)
Haoyu Zhang4b201d22018-12-18 14:27:38 -0800494 )
Haoyu Zhang4b201d22018-12-18 14:27:38 -0800495
Siyamed Sinir63789c92019-09-25 10:44:11 -0700496 assertThat(paragraph.charSequence).hasSpan(LocaleSpan::class, 0, text.length)
497 assertThat(paragraph.charSequence).hasSpan(LocaleSpan::class, 0, "abc".length)
498 assertThat(paragraph.charSequence).hasSpanOnTop(LocaleSpan::class, 0, "abc".length)
Haoyu Zhang4b201d22018-12-18 14:27:38 -0800499 }
500
501 @Test
haoyua8e48a52019-06-25 12:23:27 -0700502 fun testAnnotatedString_setBaselineShiftOnWholeText() {
Haoyu Zhang40ce6bf2019-01-28 15:58:20 -0800503 val text = "abcde"
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800504 val spanStyle = SpanStyle(baselineShift = BaselineShift.Subscript)
Haoyu Zhang40ce6bf2019-01-28 15:58:20 -0800505
506 val paragraph = simpleParagraph(
507 text = text,
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800508 spanStyles = listOf(AnnotatedString.Item(spanStyle, 0, text.length)),
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700509 constraints = ParagraphConstraints(width = 100.0f) // width is not important
Haoyu Zhang40ce6bf2019-01-28 15:58:20 -0800510 )
Haoyu Zhang40ce6bf2019-01-28 15:58:20 -0800511
Siyamed Sinir63789c92019-09-25 10:44:11 -0700512 assertThat(paragraph.charSequence).hasSpan(BaselineShiftSpan::class, 0, text.length)
Haoyu Zhang40ce6bf2019-01-28 15:58:20 -0800513 }
514
515 @Test
haoyua8e48a52019-06-25 12:23:27 -0700516 fun testAnnotatedString_setBaselineShiftOnPartText() {
Haoyu Zhang40ce6bf2019-01-28 15:58:20 -0800517 val text = "abcde"
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800518 val spanStyle = SpanStyle(baselineShift = BaselineShift.Superscript)
Haoyu Zhang40ce6bf2019-01-28 15:58:20 -0800519
520 val paragraph = simpleParagraph(
521 text = text,
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800522 spanStyles = listOf(AnnotatedString.Item(spanStyle, 0, "abc".length)),
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700523 constraints = ParagraphConstraints(width = 100.0f) // width is not important
Haoyu Zhang40ce6bf2019-01-28 15:58:20 -0800524 )
Haoyu Zhang40ce6bf2019-01-28 15:58:20 -0800525
Siyamed Sinir63789c92019-09-25 10:44:11 -0700526 assertThat(paragraph.charSequence).hasSpan(BaselineShiftSpan::class, 0, "abc".length)
Haoyu Zhang40ce6bf2019-01-28 15:58:20 -0800527 }
528
529 @Test
haoyua8e48a52019-06-25 12:23:27 -0700530 fun testAnnotatedString_setBaselineShiftTwice_LastOneOnTop() {
Haoyu Zhang40ce6bf2019-01-28 15:58:20 -0800531 val text = "abcde"
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800532 val spanStyle = SpanStyle(baselineShift = BaselineShift.Subscript)
533 val spanStyleOverwrite =
534 SpanStyle(baselineShift = BaselineShift.Superscript)
Haoyu Zhang40ce6bf2019-01-28 15:58:20 -0800535
536 val paragraph = simpleParagraph(
537 text = text,
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800538 spanStyles = listOf(
539 AnnotatedString.Item(spanStyle, 0, text.length),
540 AnnotatedString.Item(spanStyleOverwrite, 0, "abc".length)
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700541 ),
542 constraints = ParagraphConstraints(width = 100.0f) // width is not important
Haoyu Zhang40ce6bf2019-01-28 15:58:20 -0800543 )
Haoyu Zhang40ce6bf2019-01-28 15:58:20 -0800544
Siyamed Sinir63789c92019-09-25 10:44:11 -0700545 assertThat(paragraph.charSequence).hasSpan(BaselineShiftSpan::class, 0, text.length)
546 assertThat(paragraph.charSequence).hasSpan(BaselineShiftSpan::class, 0, "abc".length)
547 assertThat(paragraph.charSequence).hasSpanOnTop(BaselineShiftSpan::class, 0, "abc".length)
Haoyu Zhang40ce6bf2019-01-28 15:58:20 -0800548 }
549
550 @Test
haoyua8e48a52019-06-25 12:23:27 -0700551 fun testAnnotatedString_setTextGeometricTransformWithNull_noSpanSet() {
Haoyu Zhang15750922019-02-19 13:44:17 -0800552 val text = "abcde"
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800553 val spanStyle = SpanStyle(textGeometricTransform = TextGeometricTransform())
Haoyu Zhang15750922019-02-19 13:44:17 -0800554
555 val paragraph = simpleParagraph(
556 text = text,
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800557 spanStyles = listOf(AnnotatedString.Item(spanStyle, 0, text.length)),
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700558 constraints = ParagraphConstraints(width = 100.0f) // width is not important
Haoyu Zhang15750922019-02-19 13:44:17 -0800559 )
Haoyu Zhang15750922019-02-19 13:44:17 -0800560
Siyamed Sinir63789c92019-09-25 10:44:11 -0700561 assertThat(paragraph.charSequence).spans(ScaleXSpan::class).isEmpty()
562 assertThat(paragraph.charSequence).spans(SkewXSpan::class).isEmpty()
Haoyu Zhang15750922019-02-19 13:44:17 -0800563 }
564
565 @Test
haoyua8e48a52019-06-25 12:23:27 -0700566 fun testAnnotatedString_setTextGeometricTransformWithScaleX() {
Haoyu Zhang15750922019-02-19 13:44:17 -0800567 val text = "abcde"
568 val scaleX = 0.5f
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800569 val spanStyle = SpanStyle(
Siyamed Sinirff51df92019-07-02 15:35:20 -0700570 textGeometricTransform = TextGeometricTransform(
Seigo Nonaka9b62cc92019-12-03 14:32:17 -0800571 scaleX = scaleX
Siyamed Sinirff51df92019-07-02 15:35:20 -0700572 )
573 )
Haoyu Zhang15750922019-02-19 13:44:17 -0800574
575 val paragraph = simpleParagraph(
576 text = text,
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800577 spanStyles = listOf(AnnotatedString.Item(spanStyle, 0, text.length)),
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700578 constraints = ParagraphConstraints(width = 100.0f) // width is not important
Haoyu Zhang15750922019-02-19 13:44:17 -0800579 )
Haoyu Zhang15750922019-02-19 13:44:17 -0800580
Siyamed Sinir63789c92019-09-25 10:44:11 -0700581 assertThat(paragraph.charSequence).hasSpan(ScaleXSpan::class, 0, text.length) {
582 it.scaleX == scaleX
583 }
584 assertThat(paragraph.charSequence).spans(SkewXSpan::class).isEmpty()
Haoyu Zhang15750922019-02-19 13:44:17 -0800585 }
586
587 @Test
haoyua8e48a52019-06-25 12:23:27 -0700588 fun testAnnotatedString_setTextGeometricTransformWithSkewX() {
Haoyu Zhang15750922019-02-19 13:44:17 -0800589 val text = "aa"
590 val skewX = 1f
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800591 val spanStyle = SpanStyle(textGeometricTransform = TextGeometricTransform(skewX = skewX))
Haoyu Zhang15750922019-02-19 13:44:17 -0800592
593 val paragraph = simpleParagraph(
594 text = text,
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800595 spanStyles = listOf(AnnotatedString.Item(spanStyle, 0, text.length)),
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700596 constraints = ParagraphConstraints(width = 100.0f) // width is not important
Haoyu Zhang15750922019-02-19 13:44:17 -0800597 )
Haoyu Zhang15750922019-02-19 13:44:17 -0800598
Siyamed Sinir63789c92019-09-25 10:44:11 -0700599 assertThat(paragraph.charSequence).hasSpan(SkewXSpan::class, 0, text.length) {
600 it.skewX == skewX
601 }
602 assertThat(paragraph.charSequence).spans(ScaleXSpan::class).isEmpty()
Haoyu Zhang15750922019-02-19 13:44:17 -0800603 }
604
605 @Test
Siyamed Sinir2690d532019-06-21 13:16:00 -0700606 fun textIndent_onWholeParagraph() {
Haoyu Zhang7fc59172019-03-01 17:03:31 -0800607 val text = "abc\ndef"
608 val firstLine = 40
609 val restLine = 20
Haoyu Zhang7fc59172019-03-01 17:03:31 -0800610
611 val paragraph = simpleParagraph(
612 text = text,
Haoyu Zhangb0e43c12019-10-15 16:37:51 -0700613 textIndent = TextIndent(firstLine.sp, restLine.sp),
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700614 constraints = ParagraphConstraints(width = 100.0f) // width is not important
Haoyu Zhang7fc59172019-03-01 17:03:31 -0800615 )
Haoyu Zhang7fc59172019-03-01 17:03:31 -0800616
Siyamed Sinir63789c92019-09-25 10:44:11 -0700617 assertThat(paragraph.charSequence)
618 .hasSpan(LeadingMarginSpan.Standard::class, 0, text.length) {
Haoyu Zhang7fc59172019-03-01 17:03:31 -0800619 it.getLeadingMargin(true) == firstLine && it.getLeadingMargin(false) == restLine
620 }
Haoyu Zhang7fc59172019-03-01 17:03:31 -0800621 }
622
623 @Test
haoyua8e48a52019-06-25 12:23:27 -0700624 fun testAnnotatedString_setShadow() {
Haoyu Zhang2a036c832019-03-08 11:57:13 -0800625 val text = "abcde"
George Mountaa12c482019-08-14 14:51:38 -0700626 val color = Color(0xFF00FF00)
Haoyu Zhang2a036c832019-03-08 11:57:13 -0800627 val offset = Offset(1f, 2f)
628 val radius = 3.px
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800629 val spanStyle = SpanStyle(shadow = Shadow(color, offset, radius))
Haoyu Zhang2a036c832019-03-08 11:57:13 -0800630
631 val paragraph = simpleParagraph(
632 text = text,
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800633 spanStyles = listOf(
634 AnnotatedString.Item(spanStyle, start = 0, end = text.length)
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700635 ),
636 constraints = ParagraphConstraints(width = 100.0f) // width is not important
Haoyu Zhang2a036c832019-03-08 11:57:13 -0800637 )
Haoyu Zhang2a036c832019-03-08 11:57:13 -0800638
Siyamed Sinir63789c92019-09-25 10:44:11 -0700639 assertThat(paragraph.charSequence)
640 .hasSpan(ShadowSpan::class, start = 0, end = text.length) {
George Mounta3145782019-05-02 10:08:03 -0700641 return@hasSpan it.color == color.toArgb() &&
Haoyu Zhang2a036c832019-03-08 11:57:13 -0800642 it.offsetX == offset.dx &&
643 it.offsetY == offset.dy &&
644 it.radius == radius.value
645 }
Haoyu Zhang2a036c832019-03-08 11:57:13 -0800646 }
647
648 @Test
haoyua8e48a52019-06-25 12:23:27 -0700649 fun testAnnotatedString_setShadowTwice_lastOnTop() {
Haoyu Zhang2a036c832019-03-08 11:57:13 -0800650 val text = "abcde"
George Mountaa12c482019-08-14 14:51:38 -0700651 val color = Color(0xFF00FF00)
Haoyu Zhang2a036c832019-03-08 11:57:13 -0800652 val offset = Offset(1f, 2f)
653 val radius = 3.px
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800654 val spanStyle = SpanStyle(shadow = Shadow(color, offset, radius))
Haoyu Zhang2a036c832019-03-08 11:57:13 -0800655
George Mountaa12c482019-08-14 14:51:38 -0700656 val colorOverwrite = Color(0xFF0000FF)
Haoyu Zhang2a036c832019-03-08 11:57:13 -0800657 val offsetOverwrite = Offset(3f, 2f)
658 val radiusOverwrite = 1.px
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800659 val spanStyleOverwrite = SpanStyle(
Haoyu Zhang2a036c832019-03-08 11:57:13 -0800660 shadow = Shadow(colorOverwrite, offsetOverwrite, radiusOverwrite)
661 )
662
663 val paragraph = simpleParagraph(
664 text = text,
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800665 spanStyles = listOf(
666 AnnotatedString.Item(spanStyle, start = 0, end = text.length),
667 AnnotatedString.Item(spanStyleOverwrite, start = 0, end = "abc".length)
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700668 ),
669 constraints = ParagraphConstraints(width = 100.0f) // width is not important
Haoyu Zhang2a036c832019-03-08 11:57:13 -0800670 )
Haoyu Zhang2a036c832019-03-08 11:57:13 -0800671
Siyamed Sinir63789c92019-09-25 10:44:11 -0700672 assertThat(paragraph.charSequence)
673 .hasSpan(ShadowSpan::class, start = 0, end = text.length) {
George Mounta3145782019-05-02 10:08:03 -0700674 return@hasSpan it.color == color.toArgb() &&
Haoyu Zhang2a036c832019-03-08 11:57:13 -0800675 it.offsetX == offset.dx &&
676 it.offsetY == offset.dy &&
677 it.radius == radius.value
678 }
Siyamed Sinir63789c92019-09-25 10:44:11 -0700679 assertThat(paragraph.charSequence)
680 .hasSpanOnTop(ShadowSpan::class, start = 0, end = "abc".length) {
George Mounta3145782019-05-02 10:08:03 -0700681 return@hasSpanOnTop it.color == colorOverwrite.toArgb() &&
Haoyu Zhang2a036c832019-03-08 11:57:13 -0800682 it.offsetX == offsetOverwrite.dx &&
683 it.offsetY == offsetOverwrite.dy &&
684 it.radius == radiusOverwrite.value
685 }
Haoyu Zhang2a036c832019-03-08 11:57:13 -0800686 }
687
688 @Test
haoyua8e48a52019-06-25 12:23:27 -0700689 fun testAnnotatedString_fontFamily_addsTypefaceSpanWithCorrectTypeface() {
Siyamed Sinir70f336a2018-12-27 10:37:09 -0800690 val text = "abcde"
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800691 val spanStyle = SpanStyle(
Siyamed Sinir70f336a2018-12-27 10:37:09 -0800692 fontFamily = fontFamily,
Siyamed Siniradf982d2019-05-20 17:35:13 -0700693 fontStyle = FontStyle.Italic,
Siyamed Sinirdc8f5742019-10-04 21:03:28 -0700694 fontWeight = FontWeight.Bold
Siyamed Sinir70f336a2018-12-27 10:37:09 -0800695 )
696 val expectedTypeface = TypefaceAdapter().create(
697 fontFamily = fontFamily,
Siyamed Siniradf982d2019-05-20 17:35:13 -0700698 fontStyle = FontStyle.Italic,
Siyamed Sinirdc8f5742019-10-04 21:03:28 -0700699 fontWeight = FontWeight.Bold
Siyamed Sinir70f336a2018-12-27 10:37:09 -0800700 )
Siyamed Sinir37298412018-12-27 19:47:15 -0800701 val expectedStart = 0
702 val expectedEnd = "abc".length
Siyamed Sinir70f336a2018-12-27 10:37:09 -0800703
704 val paragraph = simpleParagraph(
705 text = text,
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800706 spanStyles = listOf(
Haoyu Zhang27429892019-06-11 13:19:57 -0700707 AnnotatedString.Item(
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800708 spanStyle,
Siyamed Sinir37298412018-12-27 19:47:15 -0800709 expectedStart,
710 expectedEnd
711 )
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700712 ),
713 constraints = ParagraphConstraints(width = 100.0f)
Siyamed Sinir70f336a2018-12-27 10:37:09 -0800714 )
Siyamed Sinir70f336a2018-12-27 10:37:09 -0800715
Siyamed Sinir63789c92019-09-25 10:44:11 -0700716 assertThat(paragraph.charSequence.toString()).isEqualTo(text)
717 assertThat(paragraph.charSequence)
718 .hasSpan(TypefaceSpan::class, expectedStart, expectedEnd) { span ->
Siyamed Sinir70f336a2018-12-27 10:37:09 -0800719 span.typeface == expectedTypeface
Siyamed Sinir63789c92019-09-25 10:44:11 -0700720 }
Siyamed Sinir37298412018-12-27 19:47:15 -0800721 }
722
723 @Test
haoyua8e48a52019-06-25 12:23:27 -0700724 fun testAnnotatedString_fontFamily_whenFontSynthesizeTurnedOff() {
Siyamed Sinir37298412018-12-27 19:47:15 -0800725 val text = "abcde"
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800726 val spanStyle = SpanStyle(
Siyamed Sinir37298412018-12-27 19:47:15 -0800727 fontFamily = fontFamily,
Siyamed Siniradf982d2019-05-20 17:35:13 -0700728 fontStyle = FontStyle.Italic,
Siyamed Sinirdc8f5742019-10-04 21:03:28 -0700729 fontWeight = FontWeight.Bold,
Siyamed Sinir934a3442019-06-18 12:57:13 -0700730 fontSynthesis = FontSynthesis.None
Siyamed Sinir70f336a2018-12-27 10:37:09 -0800731 )
Siyamed Sinir37298412018-12-27 19:47:15 -0800732 val expectedTypeface = TypefaceAdapter().create(
733 fontFamily = fontFamily,
Siyamed Siniradf982d2019-05-20 17:35:13 -0700734 fontStyle = FontStyle.Italic,
Siyamed Sinirdc8f5742019-10-04 21:03:28 -0700735 fontWeight = FontWeight.Bold,
Siyamed Sinir934a3442019-06-18 12:57:13 -0700736 fontSynthesis = FontSynthesis.None
Siyamed Sinir37298412018-12-27 19:47:15 -0800737 )
738 val expectedStart = 0
739 val expectedEnd = "abc".length
740
741 val paragraph = simpleParagraph(
742 text = text,
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800743 spanStyles = listOf(
Haoyu Zhang27429892019-06-11 13:19:57 -0700744 AnnotatedString.Item(
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800745 spanStyle,
Siyamed Sinir37298412018-12-27 19:47:15 -0800746 expectedStart,
747 expectedEnd
748 )
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700749 ),
750 constraints = ParagraphConstraints(width = 100.0f)
Siyamed Sinir37298412018-12-27 19:47:15 -0800751 )
Siyamed Sinir37298412018-12-27 19:47:15 -0800752
Siyamed Sinir63789c92019-09-25 10:44:11 -0700753 assertThat(paragraph.charSequence.toString()).isEqualTo(text)
754 assertThat(paragraph.charSequence)
755 .hasSpan(TypefaceSpan::class, expectedStart, expectedEnd) { span ->
Siyamed Sinir37298412018-12-27 19:47:15 -0800756 span.typeface == expectedTypeface
Siyamed Sinir63789c92019-09-25 10:44:11 -0700757 }
Siyamed Sinir70f336a2018-12-27 10:37:09 -0800758 }
759
760 @Test
haoyua8e48a52019-06-25 12:23:27 -0700761 fun testAnnotatedString_fontFeatureSetting_setSpanOnText() {
Haoyu Zhang588aaef2019-02-20 14:47:39 -0800762 val text = "abc"
763 val fontFeatureSettings = "\"kern\" 0"
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800764 val spanStyle = SpanStyle(fontFeatureSettings = fontFeatureSettings)
Haoyu Zhang588aaef2019-02-20 14:47:39 -0800765
766 val paragraph = simpleParagraph(
767 text = text,
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800768 spanStyles = listOf(AnnotatedString.Item(spanStyle, 0, "abc".length)),
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700769 constraints = ParagraphConstraints(width = 100.0f) // width is not important
Haoyu Zhang588aaef2019-02-20 14:47:39 -0800770 )
Haoyu Zhang588aaef2019-02-20 14:47:39 -0800771
Siyamed Sinir63789c92019-09-25 10:44:11 -0700772 assertThat(paragraph.charSequence).hasSpan(FontFeatureSpan::class, 0, "abc".length) {
773 it.fontFeatureSettings == fontFeatureSettings
774 }
Haoyu Zhang588aaef2019-02-20 14:47:39 -0800775 }
776
777 @Test
Siyamed Sinirf18dcca2018-12-20 18:25:10 -0800778 fun testEmptyFontFamily() {
779 val typefaceAdapter = mock<TypefaceAdapter>()
780 val paragraph = simpleParagraph(
781 text = "abc",
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700782 typefaceAdapter = typefaceAdapter,
783 constraints = ParagraphConstraints(width = Float.MAX_VALUE)
Siyamed Sinirf18dcca2018-12-20 18:25:10 -0800784 )
Siyamed Sinirf18dcca2018-12-20 18:25:10 -0800785
786 verify(typefaceAdapter, never()).create(
787 fontFamily = any(),
788 fontWeight = any(),
Siyamed Sinir21796012018-12-26 13:51:17 -0800789 fontStyle = any(),
790 fontSynthesis = any()
Siyamed Sinirf18dcca2018-12-20 18:25:10 -0800791 )
Siyamed Sinir63789c92019-09-25 10:44:11 -0700792 assertThat(paragraph.textPaint.typeface).isNull()
Siyamed Sinirf18dcca2018-12-20 18:25:10 -0800793 }
794
795 @Test
796 fun testEmptyFontFamily_withBoldFontWeightSelection() {
797 val typefaceAdapter = spy(TypefaceAdapter())
798
799 val paragraph = simpleParagraph(
800 text = "abc",
Siyamed Sinir01f7b522019-12-06 00:14:02 -0800801 style = TextStyle(
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -0700802 fontFamily = null,
Siyamed Sinirdc8f5742019-10-04 21:03:28 -0700803 fontWeight = FontWeight.Bold
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -0700804 ),
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700805 typefaceAdapter = typefaceAdapter,
806 constraints = ParagraphConstraints(width = Float.MAX_VALUE)
Siyamed Sinirf18dcca2018-12-20 18:25:10 -0800807 )
Siyamed Sinirf18dcca2018-12-20 18:25:10 -0800808
809 verify(typefaceAdapter, times(1)).create(
810 fontFamily = eq(null),
Siyamed Sinirdc8f5742019-10-04 21:03:28 -0700811 fontWeight = eq(FontWeight.Bold),
Siyamed Siniradf982d2019-05-20 17:35:13 -0700812 fontStyle = eq(FontStyle.Normal),
Siyamed Sinir934a3442019-06-18 12:57:13 -0700813 fontSynthesis = eq(FontSynthesis.All)
Siyamed Sinirf18dcca2018-12-20 18:25:10 -0800814 )
815
816 val typeface = paragraph.textPaint.typeface
Siyamed Sinir63789c92019-09-25 10:44:11 -0700817 assertThat(typeface).isNotNull()
818 assertThat(typeface.isBold).isTrue()
819 assertThat(typeface.isItalic).isFalse()
Siyamed Sinirf18dcca2018-12-20 18:25:10 -0800820 }
821
822 @Test
823 fun testEmptyFontFamily_withFontStyleSelection() {
824 val typefaceAdapter = spy(TypefaceAdapter())
825 val paragraph = simpleParagraph(
826 text = "abc",
Siyamed Sinir01f7b522019-12-06 00:14:02 -0800827 style = TextStyle(
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -0700828 fontFamily = null,
829 fontStyle = FontStyle.Italic
830 ),
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700831 typefaceAdapter = typefaceAdapter,
832 constraints = ParagraphConstraints(width = Float.MAX_VALUE)
Siyamed Sinirf18dcca2018-12-20 18:25:10 -0800833 )
Siyamed Sinirf18dcca2018-12-20 18:25:10 -0800834
835 verify(typefaceAdapter, times(1)).create(
836 fontFamily = eq(null),
Siyamed Sinirdc8f5742019-10-04 21:03:28 -0700837 fontWeight = eq(FontWeight.Normal),
Siyamed Siniradf982d2019-05-20 17:35:13 -0700838 fontStyle = eq(FontStyle.Italic),
Siyamed Sinir934a3442019-06-18 12:57:13 -0700839 fontSynthesis = eq(FontSynthesis.All)
Siyamed Sinirf18dcca2018-12-20 18:25:10 -0800840 )
841
842 val typeface = paragraph.textPaint.typeface
Siyamed Sinir63789c92019-09-25 10:44:11 -0700843 assertThat(typeface).isNotNull()
844 assertThat(typeface.isBold).isFalse()
845 assertThat(typeface.isItalic).isTrue()
Siyamed Sinirf18dcca2018-12-20 18:25:10 -0800846 }
847
848 @Test
849 fun testFontFamily_withGenericFamilyName() {
850 val typefaceAdapter = spy(TypefaceAdapter())
851 val fontFamily = FontFamily("sans-serif")
852
853 val paragraph = simpleParagraph(
854 text = "abc",
Siyamed Sinir01f7b522019-12-06 00:14:02 -0800855 style = TextStyle(
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -0700856 fontFamily = fontFamily
857 ),
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700858 typefaceAdapter = typefaceAdapter,
859 constraints = ParagraphConstraints(width = Float.MAX_VALUE)
Siyamed Sinirf18dcca2018-12-20 18:25:10 -0800860 )
Siyamed Sinirf18dcca2018-12-20 18:25:10 -0800861
862 verify(typefaceAdapter, times(1)).create(
863 fontFamily = eq(fontFamily),
Siyamed Sinirdc8f5742019-10-04 21:03:28 -0700864 fontWeight = eq(FontWeight.Normal),
Siyamed Siniradf982d2019-05-20 17:35:13 -0700865 fontStyle = eq(FontStyle.Normal),
Siyamed Sinir934a3442019-06-18 12:57:13 -0700866 fontSynthesis = eq(FontSynthesis.All)
Siyamed Sinirf18dcca2018-12-20 18:25:10 -0800867 )
868
869 val typeface = paragraph.textPaint.typeface
Siyamed Sinir63789c92019-09-25 10:44:11 -0700870 assertThat(typeface).isNotNull()
871 assertThat(typeface.isBold).isFalse()
872 assertThat(typeface.isItalic).isFalse()
Siyamed Sinirf18dcca2018-12-20 18:25:10 -0800873 }
874
875 @Test
876 fun testFontFamily_withCustomFont() {
877 val typefaceAdapter = spy(TypefaceAdapter())
878 val paragraph = simpleParagraph(
879 text = "abc",
Siyamed Sinir01f7b522019-12-06 00:14:02 -0800880 style = TextStyle(
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -0700881 fontFamily = fontFamily
882 ),
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700883 typefaceAdapter = typefaceAdapter,
884 constraints = ParagraphConstraints(width = Float.MAX_VALUE)
Siyamed Sinirf18dcca2018-12-20 18:25:10 -0800885 )
Siyamed Sinirf18dcca2018-12-20 18:25:10 -0800886
887 verify(typefaceAdapter, times(1)).create(
888 fontFamily = eq(fontFamily),
Siyamed Sinirdc8f5742019-10-04 21:03:28 -0700889 fontWeight = eq(FontWeight.Normal),
Siyamed Siniradf982d2019-05-20 17:35:13 -0700890 fontStyle = eq(FontStyle.Normal),
Siyamed Sinir934a3442019-06-18 12:57:13 -0700891 fontSynthesis = eq(FontSynthesis.All)
Siyamed Sinirf18dcca2018-12-20 18:25:10 -0800892 )
893 val typeface = paragraph.textPaint.typeface
Siyamed Sinir63789c92019-09-25 10:44:11 -0700894 assertThat(typeface.isBold).isFalse()
895 assertThat(typeface.isItalic).isFalse()
Siyamed Sinirf18dcca2018-12-20 18:25:10 -0800896 }
897
Haoyu Zhangc11ef5a2019-01-14 16:35:05 -0800898 @Test
899 fun testEllipsis_withMaxLineEqualsNull_doesNotEllipsis() {
Siyamed Sinir7d4c98f2019-06-27 16:23:31 -0700900 withDensity(defaultDensity) {
901 val text = "abc"
902 val fontSize = 20.sp
903 val paragraphWidth = (text.length - 1) * fontSize.toPx().value
904 val paragraph = simpleParagraph(
905 text = text,
Siyamed Sinir01f7b522019-12-06 00:14:02 -0800906 style = TextStyle(
Siyamed Sinir7d4c98f2019-06-27 16:23:31 -0700907 fontFamily = fontFamily,
908 fontSize = fontSize
909 ),
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700910 ellipsis = true,
911 constraints = ParagraphConstraints(width = paragraphWidth)
Siyamed Sinir7d4c98f2019-06-27 16:23:31 -0700912 )
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700913
Siyamed Sinir7d4c98f2019-06-27 16:23:31 -0700914 for (i in 0 until paragraph.lineCount) {
Siyamed Sinir63789c92019-09-25 10:44:11 -0700915 assertThat(paragraph.isEllipsisApplied(i)).isFalse()
Siyamed Sinir7d4c98f2019-06-27 16:23:31 -0700916 }
Haoyu Zhangc11ef5a2019-01-14 16:35:05 -0800917 }
918 }
919
920 @Test
921 fun testEllipsis_withMaxLinesLessThanTextLines_doesEllipsis() {
Siyamed Sinir7d4c98f2019-06-27 16:23:31 -0700922 withDensity(defaultDensity) {
923 val text = "abcde"
924 val fontSize = 100.sp
925 // Note that on API 21, if the next line only contains 1 character, ellipsis won't work
926 val paragraphWidth = (text.length - 1.5f) * fontSize.toPx().value
927 val paragraph = simpleParagraph(
928 text = text,
929 ellipsis = true,
930 maxLines = 1,
Siyamed Sinir01f7b522019-12-06 00:14:02 -0800931 style = TextStyle(
Siyamed Sinir7d4c98f2019-06-27 16:23:31 -0700932 fontFamily = fontFamily,
933 fontSize = fontSize
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700934 ),
935 constraints = ParagraphConstraints(width = paragraphWidth)
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -0700936 )
Haoyu Zhangc11ef5a2019-01-14 16:35:05 -0800937
Siyamed Sinir63789c92019-09-25 10:44:11 -0700938 assertThat(paragraph.isEllipsisApplied(0)).isTrue()
Siyamed Sinir7d4c98f2019-06-27 16:23:31 -0700939 }
Haoyu Zhangc11ef5a2019-01-14 16:35:05 -0800940 }
941
942 @Test
943 fun testEllipsis_withMaxLinesMoreThanTextLines_doesNotEllipsis() {
Siyamed Sinir7d4c98f2019-06-27 16:23:31 -0700944 withDensity(defaultDensity) {
945 val text = "abc"
946 val fontSize = 100.sp
947 val paragraphWidth = (text.length - 1) * fontSize.toPx().value
948 val maxLines = ceil(text.length * fontSize.toPx().value / paragraphWidth).toInt()
949 val paragraph = simpleParagraph(
950 text = text,
951 ellipsis = true,
952 maxLines = maxLines,
Siyamed Sinir01f7b522019-12-06 00:14:02 -0800953 style = TextStyle(
Siyamed Sinir7d4c98f2019-06-27 16:23:31 -0700954 fontFamily = fontFamily,
955 fontSize = fontSize
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700956 ),
957 constraints = ParagraphConstraints(width = paragraphWidth)
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -0700958 )
Haoyu Zhangc11ef5a2019-01-14 16:35:05 -0800959
Siyamed Sinir7d4c98f2019-06-27 16:23:31 -0700960 for (i in 0 until paragraph.lineCount) {
Siyamed Sinir63789c92019-09-25 10:44:11 -0700961 assertThat(paragraph.isEllipsisApplied(i)).isFalse()
Siyamed Sinir7d4c98f2019-06-27 16:23:31 -0700962 }
Haoyu Zhangc11ef5a2019-01-14 16:35:05 -0800963 }
964 }
965
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -0700966 @Test
Siyamed Sinir0b691752019-12-05 11:27:58 -0800967 fun testSpanStyle_fontSize_appliedOnTextPaint() {
Siyamed Sinir7d4c98f2019-06-27 16:23:31 -0700968 withDensity(defaultDensity) {
969 val fontSize = 100.sp
970 val paragraph = simpleParagraph(
971 text = "",
Siyamed Sinir01f7b522019-12-06 00:14:02 -0800972 style = TextStyle(fontSize = fontSize),
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700973 constraints = ParagraphConstraints(width = 0.0f)
Siyamed Sinir7d4c98f2019-06-27 16:23:31 -0700974 )
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -0700975
Siyamed Sinir63789c92019-09-25 10:44:11 -0700976 assertThat(paragraph.textPaint.textSize).isEqualTo(fontSize.toPx().value)
Siyamed Sinir7d4c98f2019-06-27 16:23:31 -0700977 }
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -0700978 }
979
980 @Test
Siyamed Sinir0b691752019-12-05 11:27:58 -0800981 fun testSpanStyle_locale_appliedOnTextPaint() {
Seigo Nonaka8de69792019-09-04 14:55:15 -0700982 val platformLocale = java.util.Locale.JAPANESE
983 val localeList = LocaleList(platformLocale.toLanguageTag())
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -0700984
985 val paragraph = simpleParagraph(
986 text = "",
Siyamed Sinir01f7b522019-12-06 00:14:02 -0800987 style = TextStyle(localeList = localeList),
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700988 constraints = ParagraphConstraints(width = 0.0f)
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -0700989 )
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -0700990
Siyamed Sinir63789c92019-09-25 10:44:11 -0700991 assertThat(paragraph.textPaint.textLocale.language).isEqualTo(platformLocale.language)
992 assertThat(paragraph.textPaint.textLocale.country).isEqualTo(platformLocale.country)
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -0700993 }
994
995 @Test
Siyamed Sinir0b691752019-12-05 11:27:58 -0800996 fun testSpanStyle_color_appliedOnTextPaint() {
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -0700997 val color = Color(0x12345678)
998 val paragraph = simpleParagraph(
999 text = "",
Siyamed Sinir01f7b522019-12-06 00:14:02 -08001000 style = TextStyle(color = color),
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -07001001 constraints = ParagraphConstraints(width = 0.0f)
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -07001002 )
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -07001003
Siyamed Sinir63789c92019-09-25 10:44:11 -07001004 assertThat(paragraph.textPaint.color).isEqualTo(color.toArgb())
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -07001005 }
1006
1007 @Test
Siyamed Sinir0b691752019-12-05 11:27:58 -08001008 fun testSpanStyle_letterSpacing_appliedOnTextPaint() {
Haoyu Zhangf2e9e032019-10-16 15:23:39 -07001009 val letterSpacing = 2
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -07001010 val paragraph = simpleParagraph(
1011 text = "",
Siyamed Sinir01f7b522019-12-06 00:14:02 -08001012 style = TextStyle(letterSpacing = letterSpacing.em),
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -07001013 constraints = ParagraphConstraints(width = 0.0f)
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -07001014 )
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -07001015
Siyamed Sinir63789c92019-09-25 10:44:11 -07001016 assertThat(paragraph.textPaint.letterSpacing).isEqualTo((letterSpacing))
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -07001017 }
1018
1019 @Test
Siyamed Sinir0b691752019-12-05 11:27:58 -08001020 fun testSpanStyle_fontFeatureSettings_appliedOnTextPaint() {
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -07001021 val fontFeatureSettings = "\"kern\" 0"
1022 val paragraph = simpleParagraph(
1023 text = "",
Siyamed Sinir01f7b522019-12-06 00:14:02 -08001024 style = TextStyle(fontFeatureSettings = fontFeatureSettings),
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -07001025 constraints = ParagraphConstraints(width = 0.0f)
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -07001026 )
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -07001027
Siyamed Sinir63789c92019-09-25 10:44:11 -07001028 assertThat(paragraph.textPaint.fontFeatureSettings).isEqualTo(fontFeatureSettings)
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -07001029 }
1030
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -07001031 @Test
Siyamed Sinir0b691752019-12-05 11:27:58 -08001032 fun testSpanStyle_scaleX_appliedOnTextPaint() {
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -07001033 val scaleX = 0.5f
1034 val paragraph = simpleParagraph(
1035 text = "",
Siyamed Sinir01f7b522019-12-06 00:14:02 -08001036 style = TextStyle(
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -07001037 textGeometricTransform = TextGeometricTransform(
1038 scaleX = scaleX
1039 )
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -07001040 ),
1041 constraints = ParagraphConstraints(width = 0.0f)
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -07001042 )
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -07001043
Siyamed Sinir63789c92019-09-25 10:44:11 -07001044 assertThat(paragraph.textPaint.textScaleX).isEqualTo(scaleX)
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -07001045 }
1046
1047 @Test
Siyamed Sinir0b691752019-12-05 11:27:58 -08001048 fun testSpanStyle_skewX_appliedOnTextPaint() {
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -07001049 val skewX = 0.5f
1050 val paragraph = simpleParagraph(
1051 text = "",
Siyamed Sinir01f7b522019-12-06 00:14:02 -08001052 style = TextStyle(
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -07001053 textGeometricTransform = TextGeometricTransform(
1054 skewX = skewX
1055 )
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -07001056 ),
1057 constraints = ParagraphConstraints(width = 0.0f)
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -07001058 )
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -07001059
Siyamed Sinir63789c92019-09-25 10:44:11 -07001060 assertThat(paragraph.textPaint.textSkewX).isEqualTo(skewX)
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -07001061 }
1062
1063 @Test
Siyamed Sinir0b691752019-12-05 11:27:58 -08001064 fun testSpanStyle_decoration_underline_appliedOnTextPaint() {
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -07001065 val paragraph = simpleParagraph(
1066 text = "",
Siyamed Sinir01f7b522019-12-06 00:14:02 -08001067 style = TextStyle(decoration = TextDecoration.Underline),
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -07001068 constraints = ParagraphConstraints(width = 0.0f)
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -07001069 )
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -07001070
Siyamed Sinir18914522019-09-25 15:41:44 -07001071 assertThat(paragraph.textPaint.isUnderlineText).isTrue()
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -07001072 }
1073
1074 @Test
Siyamed Sinir0b691752019-12-05 11:27:58 -08001075 fun testSpanStyle_decoration_lineThrough_appliedOnTextPaint() {
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -07001076 val paragraph = simpleParagraph(
1077 text = "",
Siyamed Sinir01f7b522019-12-06 00:14:02 -08001078 style = TextStyle(decoration = TextDecoration.LineThrough),
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -07001079 constraints = ParagraphConstraints(width = 0.0f)
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -07001080 )
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -07001081
Siyamed Sinir18914522019-09-25 15:41:44 -07001082 assertThat(paragraph.textPaint.isStrikeThruText).isTrue()
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -07001083 }
1084
1085 @Test
Siyamed Sinir0b691752019-12-05 11:27:58 -08001086 fun testSpanStyle_background_appliedAsSpan() {
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -07001087 // bgColor is reset in the Android Layout constructor.
1088 // therefore we cannot apply them on paint, have to use spans.
1089 val text = "abc"
1090 val color = Color(0x12345678)
1091 val paragraph = simpleParagraph(
1092 text = text,
Siyamed Sinir01f7b522019-12-06 00:14:02 -08001093 style = TextStyle(background = color),
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -07001094 constraints = ParagraphConstraints(width = 0.0f)
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -07001095 )
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -07001096
Siyamed Sinir63789c92019-09-25 10:44:11 -07001097 assertThat(paragraph.charSequence)
1098 .hasSpan(BackgroundColorSpan::class, 0, text.length) { span ->
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -07001099 span.backgroundColor == color.toArgb()
1100 }
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -07001101 }
1102
1103 @Test
Siyamed Sinir0b691752019-12-05 11:27:58 -08001104 fun testSpanStyle_baselineShift_appliedAsSpan() {
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -07001105 // baselineShift is reset in the Android Layout constructor.
1106 // therefore we cannot apply them on paint, have to use spans.
1107 val text = "abc"
1108 val baselineShift = BaselineShift.Subscript
1109 val paragraph = simpleParagraph(
1110 text = text,
Siyamed Sinir01f7b522019-12-06 00:14:02 -08001111 style = TextStyle(baselineShift = baselineShift),
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -07001112 constraints = ParagraphConstraints(width = 0.0f)
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -07001113 )
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -07001114
Siyamed Sinir63789c92019-09-25 10:44:11 -07001115 assertThat(paragraph.charSequence)
1116 .hasSpan(BaselineShiftSpan::class, 0, text.length) { span ->
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -07001117 span.multiplier == BaselineShift.Subscript.multiplier
1118 }
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -07001119 }
1120
Siyamed Sinir031e5bf2019-07-02 11:49:05 -07001121 @Test
1122 fun locale_isDefaultLocaleIfNotProvided() {
1123 val text = "abc"
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -07001124 val paragraph = simpleParagraph(
1125 text = text,
1126 constraints = ParagraphConstraints(width = Float.MAX_VALUE)
1127 )
Siyamed Sinir031e5bf2019-07-02 11:49:05 -07001128
Siyamed Sinir63789c92019-09-25 10:44:11 -07001129 assertThat(paragraph.textLocale.toLanguageTag())
1130 .isEqualTo(java.util.Locale.getDefault().toLanguageTag())
Siyamed Sinir031e5bf2019-07-02 11:49:05 -07001131 }
1132
1133 @Test
1134 fun locale_isSetOnParagraphImpl_enUS() {
Seigo Nonaka8de69792019-09-04 14:55:15 -07001135 val localeList = LocaleList("en-US")
Siyamed Sinir031e5bf2019-07-02 11:49:05 -07001136 val text = "abc"
1137 val paragraph = simpleParagraph(
1138 text = text,
Siyamed Sinir01f7b522019-12-06 00:14:02 -08001139 style = TextStyle(localeList = localeList),
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -07001140 constraints = ParagraphConstraints(width = Float.MAX_VALUE)
Siyamed Sinir031e5bf2019-07-02 11:49:05 -07001141 )
1142
Siyamed Sinir63789c92019-09-25 10:44:11 -07001143 assertThat(paragraph.textLocale.toLanguageTag()).isEqualTo("en-US")
Siyamed Sinir031e5bf2019-07-02 11:49:05 -07001144 }
1145
1146 @Test
1147 fun locale_isSetOnParagraphImpl_jpJP() {
Seigo Nonaka8de69792019-09-04 14:55:15 -07001148 val localeList = LocaleList("ja-JP")
Siyamed Sinir031e5bf2019-07-02 11:49:05 -07001149 val text = "abc"
1150 val paragraph = simpleParagraph(
1151 text = text,
Siyamed Sinir01f7b522019-12-06 00:14:02 -08001152 style = TextStyle(localeList = localeList),
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -07001153 constraints = ParagraphConstraints(width = Float.MAX_VALUE)
Siyamed Sinir031e5bf2019-07-02 11:49:05 -07001154 )
1155
Siyamed Sinir63789c92019-09-25 10:44:11 -07001156 assertThat(paragraph.textLocale.toLanguageTag()).isEqualTo("ja-JP")
Siyamed Sinir031e5bf2019-07-02 11:49:05 -07001157 }
1158
1159 @Test
1160 fun locale_noCountryCode_isSetOnParagraphImpl() {
Seigo Nonaka8de69792019-09-04 14:55:15 -07001161 val localeList = LocaleList("ja")
Siyamed Sinir031e5bf2019-07-02 11:49:05 -07001162 val text = "abc"
1163 val paragraph = simpleParagraph(
1164 text = text,
Siyamed Sinir01f7b522019-12-06 00:14:02 -08001165 style = TextStyle(localeList = localeList),
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -07001166 constraints = ParagraphConstraints(width = Float.MAX_VALUE)
Siyamed Sinir031e5bf2019-07-02 11:49:05 -07001167 )
1168
Siyamed Sinir63789c92019-09-25 10:44:11 -07001169 assertThat(paragraph.textLocale.toLanguageTag()).isEqualTo("ja")
Siyamed Sinir031e5bf2019-07-02 11:49:05 -07001170 }
1171
Seigo Nonakac4f136a2019-08-16 16:48:44 -07001172 @Test
Seigo Nonakaad4a3772019-08-26 12:06:58 -07001173 fun floatingWidth() {
1174 val floatWidth = 1.3f
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -07001175 val paragraph = simpleParagraph(
1176 text = "Hello, World",
1177 constraints = ParagraphConstraints(floatWidth)
1178 )
1179
Siyamed Sinir63789c92019-09-25 10:44:11 -07001180 assertThat(floatWidth).isEqualTo(paragraph.width)
Seigo Nonakaad4a3772019-08-26 12:06:58 -07001181 }
1182
Haoyu Zhang10fc6502018-11-09 15:50:11 -08001183 private fun simpleParagraph(
Haoyu Zhang27429892019-06-11 13:19:57 -07001184 text: String = "",
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -08001185 spanStyles: List<AnnotatedString.Item<SpanStyle>> = listOf(),
Siyamed Sinir2690d532019-06-21 13:16:00 -07001186 textIndent: TextIndent? = null,
Haoyu Zhang10fc6502018-11-09 15:50:11 -08001187 textAlign: TextAlign? = null,
Siyamed Sinir504d5b02019-09-24 13:39:43 -07001188 textDirectionAlgorithm: TextDirectionAlgorithm? = TextDirectionAlgorithm.ContentOrLtr,
Seigo Nonaka51664792019-12-04 10:59:29 -08001189 ellipsis: Boolean = false,
1190 maxLines: Int = Int.MAX_VALUE,
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -07001191 constraints: ParagraphConstraints,
Siyamed Sinir01f7b522019-12-06 00:14:02 -08001192 style: TextStyle? = null,
Siyamed Sinirf18dcca2018-12-20 18:25:10 -08001193 typefaceAdapter: TypefaceAdapter = TypefaceAdapter()
Siyamed Sinire75976f2019-07-03 09:24:30 -07001194 ): AndroidParagraph {
1195 return AndroidParagraph(
Haoyu Zhang27429892019-06-11 13:19:57 -07001196 text = text,
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -08001197 spanStyles = spanStyles,
Siyamed Sinirf18dcca2018-12-20 18:25:10 -08001198 typefaceAdapter = typefaceAdapter,
Siyamed Sinir01f7b522019-12-06 00:14:02 -08001199 style = TextStyle(
Siyamed Sinir883e0232019-06-25 12:38:12 -07001200 textAlign = textAlign,
Siyamed Sinir504d5b02019-09-24 13:39:43 -07001201 textIndent = textIndent,
1202 textDirectionAlgorithm = textDirectionAlgorithm
Siyamed Sinir01f7b522019-12-06 00:14:02 -08001203 ).merge(style),
Siyamed Sinir6a1f0362019-07-08 15:58:32 -07001204 maxLines = maxLines,
1205 ellipsis = ellipsis,
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -07001206 constraints = constraints,
Siyamed Sinir504d5b02019-09-24 13:39:43 -07001207 density = Density(density = 1f)
Haoyu Zhang10fc6502018-11-09 15:50:11 -08001208 )
1209 }
Siyamed Sinir472ed132019-07-03 15:43:43 -07001210
1211 private fun TypefaceAdapter() = TypefaceAdapter(
Siyamed Sinirc4c308e2019-07-03 16:14:22 -07001212 resourceLoader = TestFontResourceLoader(context)
Siyamed Sinir472ed132019-07-03 15:43:43 -07001213 )
Siyamed Sinir2690d532019-06-21 13:16:00 -07001214}