[go: nahoru, domu]

blob: cf1bf64a4a056ae98e9c99725bf5a24b2cea1685 [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 Sinir6a1f0362019-07-08 15:58:32 -070036import androidx.ui.text.ParagraphStyle
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -080037import androidx.ui.text.SpanStyle
Siyamed Sinirc4c308e2019-07-03 16:14:22 -070038import androidx.ui.text.TestFontResourceLoader
Siyamed Sinirff51df92019-07-02 15:35:20 -070039import androidx.ui.text.TextStyle
Siyamed Sinir63789c92019-09-25 10:44:11 -070040import androidx.ui.text.font.FontFamily
41import androidx.ui.text.font.FontStyle
42import androidx.ui.text.font.FontSynthesis
43import androidx.ui.text.font.FontWeight
44import androidx.ui.text.font.asFontFamily
45import androidx.ui.text.matchers.assertThat
46import androidx.ui.text.style.BaselineShift
47import androidx.ui.text.style.TextAlign
48import androidx.ui.text.style.TextDecoration
Seigo Nonakac4f136a2019-08-16 16:48:44 -070049import androidx.ui.text.style.TextDirectionAlgorithm
Siyamed Sinir63789c92019-09-25 10:44:11 -070050import androidx.ui.text.style.TextGeometricTransform
51import androidx.ui.text.style.TextIndent
52import com.google.common.truth.Truth.assertThat
Siyamed Sinirf18dcca2018-12-20 18:25:10 -080053import com.nhaarman.mockitokotlin2.any
54import com.nhaarman.mockitokotlin2.eq
55import com.nhaarman.mockitokotlin2.mock
56import com.nhaarman.mockitokotlin2.never
57import com.nhaarman.mockitokotlin2.spy
58import com.nhaarman.mockitokotlin2.times
59import com.nhaarman.mockitokotlin2.verify
Haoyu Zhang10fc6502018-11-09 15:50:11 -080060import org.junit.Test
61import org.junit.runner.RunWith
62import org.junit.runners.JUnit4
Haoyu Zhang10fc6502018-11-09 15:50:11 -080063import kotlin.math.ceil
64
65@RunWith(JUnit4::class)
66@SmallTest
Siyamed Sinire75976f2019-07-03 09:24:30 -070067class AndroidParagraphTest {
Siyamed Sinir472ed132019-07-03 15:43:43 -070068 // This sample font provides the following features:
69 // 1. The width of most of visible characters equals to font size.
70 // 2. The LTR/RTL characters are rendered as â–¶/â—€.
71 // 3. The fontMetrics passed to TextPaint has descend - ascend equal to 1.2 * fontSize.
72 private val fontFamily = BASIC_MEASURE_FONT.asFontFamily()
Siyamed Sinir7d4c98f2019-06-27 16:23:31 -070073 private val defaultDensity = Density(density = 1f)
Siyamed Sinir472ed132019-07-03 15:43:43 -070074 private val context = InstrumentationRegistry.getInstrumentation().context
Haoyu Zhang10fc6502018-11-09 15:50:11 -080075
76 @Test
77 fun draw_with_newline_and_line_break_default_values() {
Siyamed Sinir7d4c98f2019-06-27 16:23:31 -070078 withDensity(defaultDensity) {
79 val fontSize = 50.sp
80 for (text in arrayOf("abc\ndef", "\u05D0\u05D1\u05D2\n\u05D3\u05D4\u05D5")) {
81 val paragraphAndroid = simpleParagraph(
82 text = text,
83 textStyle = TextStyle(
84 fontSize = fontSize,
85 fontFamily = fontFamily
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -070086 ),
87 // 2 chars width
88 constraints = ParagraphConstraints(width = 2 * fontSize.toPx().value)
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -070089 )
Haoyu Zhang10fc6502018-11-09 15:50:11 -080090
Siyamed Sinir7d4c98f2019-06-27 16:23:31 -070091 val textPaint = TextPaint(Paint.ANTI_ALIAS_FLAG)
92 textPaint.textSize = fontSize.toPx().value
93 textPaint.typeface = TypefaceAdapter().create(fontFamily)
Haoyu Zhang10fc6502018-11-09 15:50:11 -080094
Siyamed Sinir97d0ccf2019-11-02 02:51:24 -070095 val layout = TextLayout(
96 charSequence = text,
97 width = ceil(paragraphAndroid.width),
98 textPaint = textPaint
Siyamed Sinir7d4c98f2019-06-27 16:23:31 -070099 )
Siyamed Sinir97d0ccf2019-11-02 02:51:24 -0700100
101 assertThat(paragraphAndroid.bitmap()).isEqualToBitmap(layout.bitmap())
Siyamed Sinir7d4c98f2019-06-27 16:23:31 -0700102 }
Haoyu Zhang10fc6502018-11-09 15:50:11 -0800103 }
104 }
105
Haoyu Zhang47f57a22018-12-12 13:16:40 -0800106 @Test
haoyua8e48a52019-06-25 12:23:27 -0700107 fun testAnnotatedString_setColorOnWholeText() {
Haoyu Zhang47f57a22018-12-12 13:16:40 -0800108 val text = "abcde"
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800109 val spanStyle = SpanStyle(color = Color(0xFF0000FF))
Haoyu Zhang47f57a22018-12-12 13:16:40 -0800110
111 val paragraph = simpleParagraph(
112 text = text,
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800113 spanStyles = listOf(AnnotatedString.Item(spanStyle, 0, text.length)),
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700114 constraints = ParagraphConstraints(width = 100.0f)
Haoyu Zhang47f57a22018-12-12 13:16:40 -0800115 )
Haoyu Zhang47f57a22018-12-12 13:16:40 -0800116
Siyamed Sinir63789c92019-09-25 10:44:11 -0700117 assertThat(paragraph.charSequence).hasSpan(ForegroundColorSpan::class, 0, text.length)
Haoyu Zhang47f57a22018-12-12 13:16:40 -0800118 }
119
120 @Test
haoyua8e48a52019-06-25 12:23:27 -0700121 fun testAnnotatedString_setColorOnPartOfText() {
Haoyu Zhang47f57a22018-12-12 13:16:40 -0800122 val text = "abcde"
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800123 val spanStyle = SpanStyle(color = Color(0xFF0000FF))
Haoyu Zhang47f57a22018-12-12 13:16:40 -0800124
125 val paragraph = simpleParagraph(
126 text = text,
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800127 spanStyles = listOf(AnnotatedString.Item(spanStyle, 0, "abc".length)),
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700128 constraints = ParagraphConstraints(width = 100.0f)
Haoyu Zhang47f57a22018-12-12 13:16:40 -0800129 )
Haoyu Zhang47f57a22018-12-12 13:16:40 -0800130
Siyamed Sinir63789c92019-09-25 10:44:11 -0700131 assertThat(paragraph.charSequence).hasSpan(ForegroundColorSpan::class, 0, "abc".length)
Haoyu Zhang47f57a22018-12-12 13:16:40 -0800132 }
133
134 @Test
haoyua8e48a52019-06-25 12:23:27 -0700135 fun testAnnotatedString_setColorTwice_lastOneOverwrite() {
Haoyu Zhang47f57a22018-12-12 13:16:40 -0800136 val text = "abcde"
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800137 val spanStyle = SpanStyle(color = Color(0xFF0000FF))
138 val spanStyleOverwrite = SpanStyle(color = Color(0xFF00FF00))
Haoyu Zhang47f57a22018-12-12 13:16:40 -0800139
140 val paragraph = simpleParagraph(
141 text = text,
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800142 spanStyles = listOf(
143 AnnotatedString.Item(spanStyle, 0, text.length),
144 AnnotatedString.Item(spanStyleOverwrite, 0, "abc".length)
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700145 ),
146 constraints = ParagraphConstraints(width = 100.0f)
Haoyu Zhang47f57a22018-12-12 13:16:40 -0800147 )
Haoyu Zhang47f57a22018-12-12 13:16:40 -0800148
Siyamed Sinir63789c92019-09-25 10:44:11 -0700149 assertThat(paragraph.charSequence).hasSpan(ForegroundColorSpan::class, 0, text.length)
150 assertThat(paragraph.charSequence).hasSpan(ForegroundColorSpan::class, 0, "abc".length)
151 assertThat(paragraph.charSequence).hasSpanOnTop(ForegroundColorSpan::class, 0, "abc".length)
Haoyu Zhang47f57a22018-12-12 13:16:40 -0800152 }
153
Haoyu Zhangbb51ccf2018-12-17 15:07:43 -0800154 @Test
Haoyu Zhangb5677202018-12-19 14:22:18 -0800155 fun testStyle_setTextDecorationOnWholeText_withLineThrough() {
156 val text = "abcde"
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800157 val spanStyle = SpanStyle(decoration = TextDecoration.LineThrough)
Haoyu Zhangb5677202018-12-19 14:22:18 -0800158
159 val paragraph = simpleParagraph(
160 text = text,
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800161 spanStyles = listOf(AnnotatedString.Item(spanStyle, 0, text.length)),
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700162 constraints = ParagraphConstraints(width = 100.0f)
Haoyu Zhangb5677202018-12-19 14:22:18 -0800163 )
Haoyu Zhangb5677202018-12-19 14:22:18 -0800164
Siyamed Sinir63789c92019-09-25 10:44:11 -0700165 assertThat(paragraph.charSequence.toString()).isEqualTo(text)
166 assertThat(paragraph.charSequence).hasSpan(StrikethroughSpan::class, 0, text.length)
Haoyu Zhangb5677202018-12-19 14:22:18 -0800167 }
168
169 @Test
170 fun testStyle_setTextDecorationOnWholeText_withUnderline() {
171 val text = "abcde"
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800172 val spanStyle = SpanStyle(decoration = TextDecoration.Underline)
Haoyu Zhangb5677202018-12-19 14:22:18 -0800173
174 val paragraph = simpleParagraph(
175 text = text,
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800176 spanStyles = listOf(AnnotatedString.Item(spanStyle, 0, text.length)),
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700177 constraints = ParagraphConstraints(width = 100.0f)
Haoyu Zhangb5677202018-12-19 14:22:18 -0800178 )
Haoyu Zhangb5677202018-12-19 14:22:18 -0800179
Siyamed Sinir63789c92019-09-25 10:44:11 -0700180 assertThat(paragraph.charSequence.toString()).isEqualTo(text)
181 assertThat(paragraph.charSequence).hasSpan(UnderlineSpan::class, 0, text.length)
Haoyu Zhangb5677202018-12-19 14:22:18 -0800182 }
183
184 @Test
185 fun testStyle_setTextDecorationOnPartText_withLineThrough() {
186 val text = "abcde"
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800187 val spanStyle = SpanStyle(decoration = TextDecoration.LineThrough)
Haoyu Zhangb5677202018-12-19 14:22:18 -0800188
189 val paragraph = simpleParagraph(
190 text = text,
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800191 spanStyles = listOf(AnnotatedString.Item(spanStyle, 0, "abc".length)),
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700192 constraints = ParagraphConstraints(width = 100.0f)
Haoyu Zhangb5677202018-12-19 14:22:18 -0800193 )
Haoyu Zhangb5677202018-12-19 14:22:18 -0800194
Siyamed Sinir63789c92019-09-25 10:44:11 -0700195 assertThat(paragraph.charSequence.toString()).isEqualTo(text)
196 assertThat(paragraph.charSequence).hasSpan(StrikethroughSpan::class, 0, "abc".length)
Haoyu Zhangb5677202018-12-19 14:22:18 -0800197 }
198
199 @Test
200 fun testStyle_setTextDecorationOnPartText_withUnderline() {
201 val text = "abcde"
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800202 val spanStyle = SpanStyle(decoration = TextDecoration.Underline)
Haoyu Zhangb5677202018-12-19 14:22:18 -0800203
204 val paragraph = simpleParagraph(
205 text = text,
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800206 spanStyles = listOf(AnnotatedString.Item(spanStyle, 0, "abc".length)),
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700207 constraints = ParagraphConstraints(width = 100.0f)
Haoyu Zhangb5677202018-12-19 14:22:18 -0800208 )
Haoyu Zhangb5677202018-12-19 14:22:18 -0800209
Siyamed Sinir63789c92019-09-25 10:44:11 -0700210 assertThat(paragraph.charSequence.toString()).isEqualTo(text)
211 assertThat(paragraph.charSequence).hasSpan(UnderlineSpan::class, 0, "abc".length)
Haoyu Zhangb5677202018-12-19 14:22:18 -0800212 }
213
214 @Test
215 fun testStyle_setTextDecoration_withLineThroughAndUnderline() {
216 val text = "abcde"
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800217 val spanStyle = SpanStyle(
Haoyu Zhangb5677202018-12-19 14:22:18 -0800218 decoration = TextDecoration.combine(
Siyamed Sinir9fd89f42019-05-20 18:04:29 -0700219 listOf(TextDecoration.LineThrough, TextDecoration.Underline)
Haoyu Zhangb5677202018-12-19 14:22:18 -0800220 )
221 )
222
223 val paragraph = simpleParagraph(
224 text = text,
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800225 spanStyles = listOf(AnnotatedString.Item(spanStyle, 0, "abc".length)),
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700226 constraints = ParagraphConstraints(width = 100.0f)
Haoyu Zhangb5677202018-12-19 14:22:18 -0800227 )
Haoyu Zhangb5677202018-12-19 14:22:18 -0800228
Siyamed Sinir63789c92019-09-25 10:44:11 -0700229 assertThat(paragraph.charSequence.toString()).isEqualTo(text)
230 assertThat(paragraph.charSequence).hasSpan(UnderlineSpan::class, 0, "abc".length)
231 assertThat(paragraph.charSequence).hasSpan(StrikethroughSpan::class, 0, "abc".length)
Haoyu Zhangb5677202018-12-19 14:22:18 -0800232 }
233
234 @Test
haoyua8e48a52019-06-25 12:23:27 -0700235 fun testAnnotatedString_setFontSizeOnWholeText() {
Siyamed Sinir7d4c98f2019-06-27 16:23:31 -0700236 withDensity(defaultDensity) {
237 val text = "abcde"
238 val fontSize = 20.sp
239 val paragraphWidth = text.length * fontSize.toPx().value
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800240 val spanStyle = SpanStyle(fontSize = fontSize)
Haoyu Zhangbb51ccf2018-12-17 15:07:43 -0800241
Siyamed Sinir7d4c98f2019-06-27 16:23:31 -0700242 val paragraph = simpleParagraph(
243 text = text,
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800244 spanStyles = listOf(AnnotatedString.Item(spanStyle, 0, text.length)),
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700245 constraints = ParagraphConstraints(width = paragraphWidth)
Siyamed Sinir7d4c98f2019-06-27 16:23:31 -0700246 )
Haoyu Zhangbb51ccf2018-12-17 15:07:43 -0800247
Siyamed Sinir63789c92019-09-25 10:44:11 -0700248 assertThat(paragraph.charSequence).hasSpan(AbsoluteSizeSpan::class, 0, text.length)
Siyamed Sinir7d4c98f2019-06-27 16:23:31 -0700249 }
Haoyu Zhangbb51ccf2018-12-17 15:07:43 -0800250 }
251
252 @Test
haoyua8e48a52019-06-25 12:23:27 -0700253 fun testAnnotatedString_setFontSizeOnPartText() {
Siyamed Sinir7d4c98f2019-06-27 16:23:31 -0700254 withDensity(defaultDensity) {
255 val text = "abcde"
256 val fontSize = 20.sp
257 val paragraphWidth = text.length * fontSize.toPx().value
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800258 val spanStyle = SpanStyle(fontSize = fontSize)
Haoyu Zhangbb51ccf2018-12-17 15:07:43 -0800259
Siyamed Sinir7d4c98f2019-06-27 16:23:31 -0700260 val paragraph = simpleParagraph(
261 text = text,
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800262 spanStyles = listOf(AnnotatedString.Item(spanStyle, 0, "abc".length)),
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700263 constraints = ParagraphConstraints(width = paragraphWidth)
Siyamed Sinir7d4c98f2019-06-27 16:23:31 -0700264 )
Haoyu Zhangbb51ccf2018-12-17 15:07:43 -0800265
Siyamed Sinir63789c92019-09-25 10:44:11 -0700266 assertThat(paragraph.charSequence).hasSpan(AbsoluteSizeSpan::class, 0, "abc".length)
Siyamed Sinir7d4c98f2019-06-27 16:23:31 -0700267 }
Haoyu Zhangbb51ccf2018-12-17 15:07:43 -0800268 }
269
270 @Test
haoyua8e48a52019-06-25 12:23:27 -0700271 fun testAnnotatedString_setFontSizeTwice_lastOneOverwrite() {
Siyamed Sinir7d4c98f2019-06-27 16:23:31 -0700272 withDensity(defaultDensity) {
273 val text = "abcde"
274 val fontSize = 20.sp
275 val fontSizeOverwrite = 30.sp
276 val paragraphWidth = text.length * fontSizeOverwrite.toPx().value
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800277 val spanStyle = SpanStyle(fontSize = fontSize)
278 val spanStyleOverwrite = SpanStyle(fontSize = fontSizeOverwrite)
Haoyu Zhangbb51ccf2018-12-17 15:07:43 -0800279
Siyamed Sinir7d4c98f2019-06-27 16:23:31 -0700280 val paragraph = simpleParagraph(
281 text = text,
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800282 spanStyles = listOf(
283 AnnotatedString.Item(spanStyle, 0, text.length),
284 AnnotatedString.Item(spanStyleOverwrite, 0, "abc".length)
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700285 ),
286 constraints = ParagraphConstraints(width = paragraphWidth)
Haoyu Zhangbb51ccf2018-12-17 15:07:43 -0800287 )
Haoyu Zhangbb51ccf2018-12-17 15:07:43 -0800288
Siyamed Sinir63789c92019-09-25 10:44:11 -0700289 assertThat(paragraph.charSequence).hasSpan(AbsoluteSizeSpan::class, 0, text.length)
290 assertThat(paragraph.charSequence).hasSpan(AbsoluteSizeSpan::class, 0, "abc".length)
291 assertThat(paragraph.charSequence)
292 .hasSpanOnTop(AbsoluteSizeSpan::class, 0, "abc".length)
Siyamed Sinir7d4c98f2019-06-27 16:23:31 -0700293 }
Haoyu Zhangbb51ccf2018-12-17 15:07:43 -0800294 }
295
Haoyu Zhang1588ba0f2018-12-19 16:47:10 -0800296 @Test
haoyua8e48a52019-06-25 12:23:27 -0700297 fun testAnnotatedString_setFontSizeScaleOnWholeText() {
Haoyu Zhang24eb32f2019-05-21 16:16:37 -0700298 val text = "abcde"
Seigo Nonakad9638202019-11-19 16:37:07 -0800299 val fontSizeScale = 2.0.em
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800300 val spanStyle = SpanStyle(fontSize = fontSizeScale)
Haoyu Zhang24eb32f2019-05-21 16:16:37 -0700301
302 val paragraph = simpleParagraph(
303 text = text,
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800304 spanStyles = listOf(AnnotatedString.Item(spanStyle, 0, text.length)),
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700305 constraints = ParagraphConstraints(width = 100.0f)
Haoyu Zhang24eb32f2019-05-21 16:16:37 -0700306 )
Haoyu Zhang24eb32f2019-05-21 16:16:37 -0700307
Siyamed Sinir63789c92019-09-25 10:44:11 -0700308 assertThat(paragraph.charSequence).hasSpan(RelativeSizeSpan::class, 0, text.length) {
Seigo Nonakad9638202019-11-19 16:37:07 -0800309 it.sizeChange == fontSizeScale.value
Siyamed Sinir63789c92019-09-25 10:44:11 -0700310 }
Haoyu Zhang24eb32f2019-05-21 16:16:37 -0700311 }
312
313 @Test
haoyua8e48a52019-06-25 12:23:27 -0700314 fun testAnnotatedString_setFontSizeScaleOnPartText() {
Haoyu Zhang24eb32f2019-05-21 16:16:37 -0700315 val text = "abcde"
Seigo Nonakad9638202019-11-19 16:37:07 -0800316 val fontSizeScale = 2.0f.em
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800317 val spanStyle = SpanStyle(fontSize = fontSizeScale)
Haoyu Zhang24eb32f2019-05-21 16:16:37 -0700318
319 val paragraph = simpleParagraph(
320 text = text,
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800321 spanStyles = listOf(AnnotatedString.Item(spanStyle, 0, "abc".length)),
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700322 constraints = ParagraphConstraints(width = 100.0f)
Haoyu Zhang24eb32f2019-05-21 16:16:37 -0700323 )
Haoyu Zhang24eb32f2019-05-21 16:16:37 -0700324
Siyamed Sinir63789c92019-09-25 10:44:11 -0700325 assertThat(paragraph.charSequence).hasSpan(RelativeSizeSpan::class, 0, "abc".length) {
Seigo Nonakad9638202019-11-19 16:37:07 -0800326 it.sizeChange == fontSizeScale.value
Siyamed Sinir63789c92019-09-25 10:44:11 -0700327 }
Haoyu Zhang24eb32f2019-05-21 16:16:37 -0700328 }
329
330 @Test
haoyua8e48a52019-06-25 12:23:27 -0700331 fun testAnnotatedString_setLetterSpacingOnWholeText() {
Haoyu Zhang1588ba0f2018-12-19 16:47:10 -0800332 val text = "abcde"
George Mountb1cdd862018-12-21 10:54:42 -0800333 val letterSpacing = 2.0f
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800334 val spanStyle = SpanStyle(letterSpacing = letterSpacing.em)
Haoyu Zhang1588ba0f2018-12-19 16:47:10 -0800335
336 val paragraph = simpleParagraph(
337 text = text,
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800338 spanStyles = listOf(AnnotatedString.Item(spanStyle, 0, text.length)),
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700339 constraints = ParagraphConstraints(width = 100.0f)
Haoyu Zhang1588ba0f2018-12-19 16:47:10 -0800340 )
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700341
Siyamed Sinir63789c92019-09-25 10:44:11 -0700342 assertThat(paragraph.charSequence.toString()).isEqualTo(text)
343 assertThat(paragraph.charSequence).hasSpan(LetterSpacingSpan::class, 0, text.length)
Haoyu Zhang1588ba0f2018-12-19 16:47:10 -0800344 }
345
346 @Test
haoyua8e48a52019-06-25 12:23:27 -0700347 fun testAnnotatedString_setLetterSpacingOnPartText() {
Haoyu Zhang1588ba0f2018-12-19 16:47:10 -0800348 val text = "abcde"
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800349 val spanStyle = SpanStyle(letterSpacing = 2.em)
Haoyu Zhang1588ba0f2018-12-19 16:47:10 -0800350
351 val paragraph = simpleParagraph(
352 text = text,
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800353 spanStyles = listOf(AnnotatedString.Item(spanStyle, 0, "abc".length)),
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700354 constraints = ParagraphConstraints(width = 100.0f)
Haoyu Zhang1588ba0f2018-12-19 16:47:10 -0800355 )
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700356
Siyamed Sinir63789c92019-09-25 10:44:11 -0700357 assertThat(paragraph.charSequence.toString()).isEqualTo(text)
358 assertThat(paragraph.charSequence).hasSpan(LetterSpacingSpan::class, 0, "abc".length)
Haoyu Zhang1588ba0f2018-12-19 16:47:10 -0800359 }
360
361 @Test
haoyua8e48a52019-06-25 12:23:27 -0700362 fun testAnnotatedString_setLetterSpacingTwice_lastOneOverwrite() {
Haoyu Zhang1588ba0f2018-12-19 16:47:10 -0800363 val text = "abcde"
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800364 val spanStyle = SpanStyle(letterSpacing = 2.em)
365 val spanStyleOverwrite = SpanStyle(letterSpacing = 3.em)
Haoyu Zhang1588ba0f2018-12-19 16:47:10 -0800366
367 val paragraph = simpleParagraph(
368 text = text,
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800369 spanStyles = listOf(
370 AnnotatedString.Item(spanStyle, 0, text.length),
371 AnnotatedString.Item(spanStyleOverwrite, 0, "abc".length)
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700372 ),
373 constraints = ParagraphConstraints(width = 100.0f)
Haoyu Zhang1588ba0f2018-12-19 16:47:10 -0800374 )
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700375
Siyamed Sinir63789c92019-09-25 10:44:11 -0700376 assertThat(paragraph.charSequence.toString()).isEqualTo(text)
377 assertThat(paragraph.charSequence).hasSpan(LetterSpacingSpan::class, 0, text.length)
378 assertThat(paragraph.charSequence).hasSpan(LetterSpacingSpan::class, 0, "abc".length)
379 assertThat(paragraph.charSequence).hasSpanOnTop(LetterSpacingSpan::class, 0, "abc".length)
Haoyu Zhang1588ba0f2018-12-19 16:47:10 -0800380 }
381
Siyamed Sinir70f336a2018-12-27 10:37:09 -0800382 @Test
haoyua8e48a52019-06-25 12:23:27 -0700383 fun testAnnotatedString_setBackgroundOnWholeText() {
Haoyu Zhang0c4fd022019-01-02 13:53:10 -0800384 val text = "abcde"
George Mountaa12c482019-08-14 14:51:38 -0700385 val color = Color(0xFF0000FF)
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800386 val spanStyle = SpanStyle(background = color)
Haoyu Zhang0c4fd022019-01-02 13:53:10 -0800387
388 val paragraph = simpleParagraph(
389 text = text,
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800390 spanStyles = listOf(AnnotatedString.Item(spanStyle, 0, text.length)),
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700391 constraints = ParagraphConstraints(width = 100.0f)
Haoyu Zhang0c4fd022019-01-02 13:53:10 -0800392 )
Haoyu Zhang0c4fd022019-01-02 13:53:10 -0800393
Siyamed Sinir63789c92019-09-25 10:44:11 -0700394 assertThat(paragraph.charSequence.toString()).isEqualTo(text)
395 assertThat(paragraph.charSequence)
396 .hasSpan(BackgroundColorSpan::class, 0, text.length) { span ->
George Mounta3145782019-05-02 10:08:03 -0700397 span.backgroundColor == color.toArgb()
Haoyu Zhang0c4fd022019-01-02 13:53:10 -0800398 }
Haoyu Zhang0c4fd022019-01-02 13:53:10 -0800399 }
400
401 @Test
haoyua8e48a52019-06-25 12:23:27 -0700402 fun testAnnotatedString_setBackgroundOnPartText() {
Haoyu Zhang0c4fd022019-01-02 13:53:10 -0800403 val text = "abcde"
George Mountaa12c482019-08-14 14:51:38 -0700404 val color = Color(0xFF0000FF)
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800405 val spanStyle = SpanStyle(background = color)
Haoyu Zhang0c4fd022019-01-02 13:53:10 -0800406
407 val paragraph = simpleParagraph(
408 text = text,
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800409 spanStyles = listOf(AnnotatedString.Item(spanStyle, 0, "abc".length)),
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700410 constraints = ParagraphConstraints(width = 100.0f)
Haoyu Zhang0c4fd022019-01-02 13:53:10 -0800411 )
Haoyu Zhang0c4fd022019-01-02 13:53:10 -0800412
Siyamed Sinir63789c92019-09-25 10:44:11 -0700413 assertThat(paragraph.charSequence.toString()).isEqualTo(text)
414 assertThat(paragraph.charSequence)
415 .hasSpan(BackgroundColorSpan::class, 0, "abc".length) { span ->
George Mounta3145782019-05-02 10:08:03 -0700416 span.backgroundColor == color.toArgb()
Haoyu Zhang0c4fd022019-01-02 13:53:10 -0800417 }
Haoyu Zhang0c4fd022019-01-02 13:53:10 -0800418 }
419
420 @Test
haoyua8e48a52019-06-25 12:23:27 -0700421 fun testAnnotatedString_setBackgroundTwice_lastOneOverwrite() {
Haoyu Zhang0c4fd022019-01-02 13:53:10 -0800422 val text = "abcde"
George Mountaa12c482019-08-14 14:51:38 -0700423 val color = Color(0xFF0000FF)
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800424 val spanStyle = SpanStyle(background = color)
George Mountaa12c482019-08-14 14:51:38 -0700425 val colorOverwrite = Color(0xFF00FF00)
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800426 val spanStyleOverwrite = SpanStyle(background = colorOverwrite)
Haoyu Zhang0c4fd022019-01-02 13:53:10 -0800427
428 val paragraph = simpleParagraph(
429 text = text,
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800430 spanStyles = listOf(
431 AnnotatedString.Item(spanStyle, 0, text.length),
432 AnnotatedString.Item(spanStyleOverwrite, 0, "abc".length)
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700433 ),
434 constraints = ParagraphConstraints(width = 100.0f)
Haoyu Zhang0c4fd022019-01-02 13:53:10 -0800435 )
Haoyu Zhang0c4fd022019-01-02 13:53:10 -0800436
Siyamed Sinir63789c92019-09-25 10:44:11 -0700437 assertThat(paragraph.charSequence.toString()).isEqualTo(text)
438 assertThat(paragraph.charSequence)
439 .hasSpan(BackgroundColorSpan::class, 0, text.length) { span ->
George Mounta3145782019-05-02 10:08:03 -0700440 span.backgroundColor == color.toArgb()
Haoyu Zhang0c4fd022019-01-02 13:53:10 -0800441 }
Siyamed Sinir63789c92019-09-25 10:44:11 -0700442 assertThat(paragraph.charSequence)
443 .hasSpan(BackgroundColorSpan::class, 0, "abc".length) { span ->
George Mounta3145782019-05-02 10:08:03 -0700444 span.backgroundColor == colorOverwrite.toArgb()
Haoyu Zhang0c4fd022019-01-02 13:53:10 -0800445 }
Siyamed Sinir63789c92019-09-25 10:44:11 -0700446 assertThat(paragraph.charSequence)
447 .hasSpanOnTop(BackgroundColorSpan::class, 0, "abc".length) { span ->
George Mounta3145782019-05-02 10:08:03 -0700448 span.backgroundColor == colorOverwrite.toArgb()
Haoyu Zhang0c4fd022019-01-02 13:53:10 -0800449 }
Haoyu Zhang0c4fd022019-01-02 13:53:10 -0800450 }
451
452 @Test
haoyua8e48a52019-06-25 12:23:27 -0700453 fun testAnnotatedString_setLocaleOnWholeText() {
Haoyu Zhang4b201d22018-12-18 14:27:38 -0800454 val text = "abcde"
Seigo Nonaka8de69792019-09-04 14:55:15 -0700455 val localeList = LocaleList("en-US")
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800456 val spanStyle = SpanStyle(localeList = localeList)
Haoyu Zhang4b201d22018-12-18 14:27:38 -0800457
458 val paragraph = simpleParagraph(
459 text = text,
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800460 spanStyles = listOf(AnnotatedString.Item(spanStyle, 0, text.length)),
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700461 constraints = ParagraphConstraints(width = 100.0f)
Haoyu Zhang4b201d22018-12-18 14:27:38 -0800462 )
Haoyu Zhang4b201d22018-12-18 14:27:38 -0800463
Siyamed Sinir63789c92019-09-25 10:44:11 -0700464 assertThat(paragraph.charSequence).hasSpan(LocaleSpan::class, 0, text.length)
Haoyu Zhang4b201d22018-12-18 14:27:38 -0800465 }
466
467 @Test
haoyua8e48a52019-06-25 12:23:27 -0700468 fun testAnnotatedString_setLocaleOnPartText() {
Haoyu Zhang4b201d22018-12-18 14:27:38 -0800469 val text = "abcde"
Seigo Nonaka8de69792019-09-04 14:55:15 -0700470 val localeList = LocaleList("en-US")
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800471 val spanStyle = SpanStyle(localeList = localeList)
Haoyu Zhang4b201d22018-12-18 14:27:38 -0800472
473 val paragraph = simpleParagraph(
474 text = text,
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800475 spanStyles = listOf(AnnotatedString.Item(spanStyle, 0, "abc".length)),
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700476 constraints = ParagraphConstraints(width = 100.0f)
Haoyu Zhang4b201d22018-12-18 14:27:38 -0800477 )
Haoyu Zhang4b201d22018-12-18 14:27:38 -0800478
Siyamed Sinir63789c92019-09-25 10:44:11 -0700479 assertThat(paragraph.charSequence).hasSpan(LocaleSpan::class, 0, "abc".length)
Haoyu Zhang4b201d22018-12-18 14:27:38 -0800480 }
481
482 @Test
haoyua8e48a52019-06-25 12:23:27 -0700483 fun testAnnotatedString_setLocaleTwice_lastOneOverwrite() {
Haoyu Zhang4b201d22018-12-18 14:27:38 -0800484 val text = "abcde"
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800485 val spanStyle = SpanStyle(localeList = LocaleList("en-US"))
486 val spanStyleOverwrite = SpanStyle(localeList = LocaleList("ja-JP"))
Haoyu Zhang4b201d22018-12-18 14:27:38 -0800487
488 val paragraph = simpleParagraph(
489 text = text,
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800490 spanStyles = listOf(
491 AnnotatedString.Item(spanStyle, 0, text.length),
492 AnnotatedString.Item(spanStyleOverwrite, 0, "abc".length)
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700493 ),
494 constraints = ParagraphConstraints(width = 100.0f)
Haoyu Zhang4b201d22018-12-18 14:27:38 -0800495 )
Haoyu Zhang4b201d22018-12-18 14:27:38 -0800496
Siyamed Sinir63789c92019-09-25 10:44:11 -0700497 assertThat(paragraph.charSequence).hasSpan(LocaleSpan::class, 0, text.length)
498 assertThat(paragraph.charSequence).hasSpan(LocaleSpan::class, 0, "abc".length)
499 assertThat(paragraph.charSequence).hasSpanOnTop(LocaleSpan::class, 0, "abc".length)
Haoyu Zhang4b201d22018-12-18 14:27:38 -0800500 }
501
502 @Test
haoyua8e48a52019-06-25 12:23:27 -0700503 fun testAnnotatedString_setBaselineShiftOnWholeText() {
Haoyu Zhang40ce6bf2019-01-28 15:58:20 -0800504 val text = "abcde"
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800505 val spanStyle = SpanStyle(baselineShift = BaselineShift.Subscript)
Haoyu Zhang40ce6bf2019-01-28 15:58:20 -0800506
507 val paragraph = simpleParagraph(
508 text = text,
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800509 spanStyles = listOf(AnnotatedString.Item(spanStyle, 0, text.length)),
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700510 constraints = ParagraphConstraints(width = 100.0f) // width is not important
Haoyu Zhang40ce6bf2019-01-28 15:58:20 -0800511 )
Haoyu Zhang40ce6bf2019-01-28 15:58:20 -0800512
Siyamed Sinir63789c92019-09-25 10:44:11 -0700513 assertThat(paragraph.charSequence).hasSpan(BaselineShiftSpan::class, 0, text.length)
Haoyu Zhang40ce6bf2019-01-28 15:58:20 -0800514 }
515
516 @Test
haoyua8e48a52019-06-25 12:23:27 -0700517 fun testAnnotatedString_setBaselineShiftOnPartText() {
Haoyu Zhang40ce6bf2019-01-28 15:58:20 -0800518 val text = "abcde"
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800519 val spanStyle = SpanStyle(baselineShift = BaselineShift.Superscript)
Haoyu Zhang40ce6bf2019-01-28 15:58:20 -0800520
521 val paragraph = simpleParagraph(
522 text = text,
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800523 spanStyles = listOf(AnnotatedString.Item(spanStyle, 0, "abc".length)),
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700524 constraints = ParagraphConstraints(width = 100.0f) // width is not important
Haoyu Zhang40ce6bf2019-01-28 15:58:20 -0800525 )
Haoyu Zhang40ce6bf2019-01-28 15:58:20 -0800526
Siyamed Sinir63789c92019-09-25 10:44:11 -0700527 assertThat(paragraph.charSequence).hasSpan(BaselineShiftSpan::class, 0, "abc".length)
Haoyu Zhang40ce6bf2019-01-28 15:58:20 -0800528 }
529
530 @Test
haoyua8e48a52019-06-25 12:23:27 -0700531 fun testAnnotatedString_setBaselineShiftTwice_LastOneOnTop() {
Haoyu Zhang40ce6bf2019-01-28 15:58:20 -0800532 val text = "abcde"
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800533 val spanStyle = SpanStyle(baselineShift = BaselineShift.Subscript)
534 val spanStyleOverwrite =
535 SpanStyle(baselineShift = BaselineShift.Superscript)
Haoyu Zhang40ce6bf2019-01-28 15:58:20 -0800536
537 val paragraph = simpleParagraph(
538 text = text,
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800539 spanStyles = listOf(
540 AnnotatedString.Item(spanStyle, 0, text.length),
541 AnnotatedString.Item(spanStyleOverwrite, 0, "abc".length)
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700542 ),
543 constraints = ParagraphConstraints(width = 100.0f) // width is not important
Haoyu Zhang40ce6bf2019-01-28 15:58:20 -0800544 )
Haoyu Zhang40ce6bf2019-01-28 15:58:20 -0800545
Siyamed Sinir63789c92019-09-25 10:44:11 -0700546 assertThat(paragraph.charSequence).hasSpan(BaselineShiftSpan::class, 0, text.length)
547 assertThat(paragraph.charSequence).hasSpan(BaselineShiftSpan::class, 0, "abc".length)
548 assertThat(paragraph.charSequence).hasSpanOnTop(BaselineShiftSpan::class, 0, "abc".length)
Haoyu Zhang40ce6bf2019-01-28 15:58:20 -0800549 }
550
551 @Test
haoyua8e48a52019-06-25 12:23:27 -0700552 fun testAnnotatedString_setTextGeometricTransformWithNull_noSpanSet() {
Haoyu Zhang15750922019-02-19 13:44:17 -0800553 val text = "abcde"
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800554 val spanStyle = SpanStyle(textGeometricTransform = TextGeometricTransform())
Haoyu Zhang15750922019-02-19 13:44:17 -0800555
556 val paragraph = simpleParagraph(
557 text = text,
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800558 spanStyles = listOf(AnnotatedString.Item(spanStyle, 0, text.length)),
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700559 constraints = ParagraphConstraints(width = 100.0f) // width is not important
Haoyu Zhang15750922019-02-19 13:44:17 -0800560 )
Haoyu Zhang15750922019-02-19 13:44:17 -0800561
Siyamed Sinir63789c92019-09-25 10:44:11 -0700562 assertThat(paragraph.charSequence).spans(ScaleXSpan::class).isEmpty()
563 assertThat(paragraph.charSequence).spans(SkewXSpan::class).isEmpty()
Haoyu Zhang15750922019-02-19 13:44:17 -0800564 }
565
566 @Test
haoyua8e48a52019-06-25 12:23:27 -0700567 fun testAnnotatedString_setTextGeometricTransformWithScaleX() {
Haoyu Zhang15750922019-02-19 13:44:17 -0800568 val text = "abcde"
569 val scaleX = 0.5f
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800570 val spanStyle = SpanStyle(
Siyamed Sinirff51df92019-07-02 15:35:20 -0700571 textGeometricTransform = TextGeometricTransform(
Seigo Nonaka9b62cc92019-12-03 14:32:17 -0800572 scaleX = scaleX
Siyamed Sinirff51df92019-07-02 15:35:20 -0700573 )
574 )
Haoyu Zhang15750922019-02-19 13:44:17 -0800575
576 val paragraph = simpleParagraph(
577 text = text,
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800578 spanStyles = listOf(AnnotatedString.Item(spanStyle, 0, text.length)),
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700579 constraints = ParagraphConstraints(width = 100.0f) // width is not important
Haoyu Zhang15750922019-02-19 13:44:17 -0800580 )
Haoyu Zhang15750922019-02-19 13:44:17 -0800581
Siyamed Sinir63789c92019-09-25 10:44:11 -0700582 assertThat(paragraph.charSequence).hasSpan(ScaleXSpan::class, 0, text.length) {
583 it.scaleX == scaleX
584 }
585 assertThat(paragraph.charSequence).spans(SkewXSpan::class).isEmpty()
Haoyu Zhang15750922019-02-19 13:44:17 -0800586 }
587
588 @Test
haoyua8e48a52019-06-25 12:23:27 -0700589 fun testAnnotatedString_setTextGeometricTransformWithSkewX() {
Haoyu Zhang15750922019-02-19 13:44:17 -0800590 val text = "aa"
591 val skewX = 1f
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800592 val spanStyle = SpanStyle(textGeometricTransform = TextGeometricTransform(skewX = skewX))
Haoyu Zhang15750922019-02-19 13:44:17 -0800593
594 val paragraph = simpleParagraph(
595 text = text,
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800596 spanStyles = listOf(AnnotatedString.Item(spanStyle, 0, text.length)),
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700597 constraints = ParagraphConstraints(width = 100.0f) // width is not important
Haoyu Zhang15750922019-02-19 13:44:17 -0800598 )
Haoyu Zhang15750922019-02-19 13:44:17 -0800599
Siyamed Sinir63789c92019-09-25 10:44:11 -0700600 assertThat(paragraph.charSequence).hasSpan(SkewXSpan::class, 0, text.length) {
601 it.skewX == skewX
602 }
603 assertThat(paragraph.charSequence).spans(ScaleXSpan::class).isEmpty()
Haoyu Zhang15750922019-02-19 13:44:17 -0800604 }
605
606 @Test
Siyamed Sinir2690d532019-06-21 13:16:00 -0700607 fun textIndent_onWholeParagraph() {
Haoyu Zhang7fc59172019-03-01 17:03:31 -0800608 val text = "abc\ndef"
609 val firstLine = 40
610 val restLine = 20
Haoyu Zhang7fc59172019-03-01 17:03:31 -0800611
612 val paragraph = simpleParagraph(
613 text = text,
Haoyu Zhangb0e43c12019-10-15 16:37:51 -0700614 textIndent = TextIndent(firstLine.sp, restLine.sp),
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700615 constraints = ParagraphConstraints(width = 100.0f) // width is not important
Haoyu Zhang7fc59172019-03-01 17:03:31 -0800616 )
Haoyu Zhang7fc59172019-03-01 17:03:31 -0800617
Siyamed Sinir63789c92019-09-25 10:44:11 -0700618 assertThat(paragraph.charSequence)
619 .hasSpan(LeadingMarginSpan.Standard::class, 0, text.length) {
Haoyu Zhang7fc59172019-03-01 17:03:31 -0800620 it.getLeadingMargin(true) == firstLine && it.getLeadingMargin(false) == restLine
621 }
Haoyu Zhang7fc59172019-03-01 17:03:31 -0800622 }
623
624 @Test
haoyua8e48a52019-06-25 12:23:27 -0700625 fun testAnnotatedString_setShadow() {
Haoyu Zhang2a036c832019-03-08 11:57:13 -0800626 val text = "abcde"
George Mountaa12c482019-08-14 14:51:38 -0700627 val color = Color(0xFF00FF00)
Haoyu Zhang2a036c832019-03-08 11:57:13 -0800628 val offset = Offset(1f, 2f)
629 val radius = 3.px
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800630 val spanStyle = SpanStyle(shadow = Shadow(color, offset, radius))
Haoyu Zhang2a036c832019-03-08 11:57:13 -0800631
632 val paragraph = simpleParagraph(
633 text = text,
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800634 spanStyles = listOf(
635 AnnotatedString.Item(spanStyle, start = 0, end = text.length)
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700636 ),
637 constraints = ParagraphConstraints(width = 100.0f) // width is not important
Haoyu Zhang2a036c832019-03-08 11:57:13 -0800638 )
Haoyu Zhang2a036c832019-03-08 11:57:13 -0800639
Siyamed Sinir63789c92019-09-25 10:44:11 -0700640 assertThat(paragraph.charSequence)
641 .hasSpan(ShadowSpan::class, start = 0, end = text.length) {
George Mounta3145782019-05-02 10:08:03 -0700642 return@hasSpan it.color == color.toArgb() &&
Haoyu Zhang2a036c832019-03-08 11:57:13 -0800643 it.offsetX == offset.dx &&
644 it.offsetY == offset.dy &&
645 it.radius == radius.value
646 }
Haoyu Zhang2a036c832019-03-08 11:57:13 -0800647 }
648
649 @Test
haoyua8e48a52019-06-25 12:23:27 -0700650 fun testAnnotatedString_setShadowTwice_lastOnTop() {
Haoyu Zhang2a036c832019-03-08 11:57:13 -0800651 val text = "abcde"
George Mountaa12c482019-08-14 14:51:38 -0700652 val color = Color(0xFF00FF00)
Haoyu Zhang2a036c832019-03-08 11:57:13 -0800653 val offset = Offset(1f, 2f)
654 val radius = 3.px
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800655 val spanStyle = SpanStyle(shadow = Shadow(color, offset, radius))
Haoyu Zhang2a036c832019-03-08 11:57:13 -0800656
George Mountaa12c482019-08-14 14:51:38 -0700657 val colorOverwrite = Color(0xFF0000FF)
Haoyu Zhang2a036c832019-03-08 11:57:13 -0800658 val offsetOverwrite = Offset(3f, 2f)
659 val radiusOverwrite = 1.px
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800660 val spanStyleOverwrite = SpanStyle(
Haoyu Zhang2a036c832019-03-08 11:57:13 -0800661 shadow = Shadow(colorOverwrite, offsetOverwrite, radiusOverwrite)
662 )
663
664 val paragraph = simpleParagraph(
665 text = text,
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800666 spanStyles = listOf(
667 AnnotatedString.Item(spanStyle, start = 0, end = text.length),
668 AnnotatedString.Item(spanStyleOverwrite, start = 0, end = "abc".length)
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700669 ),
670 constraints = ParagraphConstraints(width = 100.0f) // width is not important
Haoyu Zhang2a036c832019-03-08 11:57:13 -0800671 )
Haoyu Zhang2a036c832019-03-08 11:57:13 -0800672
Siyamed Sinir63789c92019-09-25 10:44:11 -0700673 assertThat(paragraph.charSequence)
674 .hasSpan(ShadowSpan::class, start = 0, end = text.length) {
George Mounta3145782019-05-02 10:08:03 -0700675 return@hasSpan it.color == color.toArgb() &&
Haoyu Zhang2a036c832019-03-08 11:57:13 -0800676 it.offsetX == offset.dx &&
677 it.offsetY == offset.dy &&
678 it.radius == radius.value
679 }
Siyamed Sinir63789c92019-09-25 10:44:11 -0700680 assertThat(paragraph.charSequence)
681 .hasSpanOnTop(ShadowSpan::class, start = 0, end = "abc".length) {
George Mounta3145782019-05-02 10:08:03 -0700682 return@hasSpanOnTop it.color == colorOverwrite.toArgb() &&
Haoyu Zhang2a036c832019-03-08 11:57:13 -0800683 it.offsetX == offsetOverwrite.dx &&
684 it.offsetY == offsetOverwrite.dy &&
685 it.radius == radiusOverwrite.value
686 }
Haoyu Zhang2a036c832019-03-08 11:57:13 -0800687 }
688
689 @Test
haoyua8e48a52019-06-25 12:23:27 -0700690 fun testAnnotatedString_fontFamily_addsTypefaceSpanWithCorrectTypeface() {
Siyamed Sinir70f336a2018-12-27 10:37:09 -0800691 val text = "abcde"
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800692 val spanStyle = SpanStyle(
Siyamed Sinir70f336a2018-12-27 10:37:09 -0800693 fontFamily = fontFamily,
Siyamed Siniradf982d2019-05-20 17:35:13 -0700694 fontStyle = FontStyle.Italic,
Siyamed Sinirdc8f5742019-10-04 21:03:28 -0700695 fontWeight = FontWeight.Bold
Siyamed Sinir70f336a2018-12-27 10:37:09 -0800696 )
697 val expectedTypeface = TypefaceAdapter().create(
698 fontFamily = fontFamily,
Siyamed Siniradf982d2019-05-20 17:35:13 -0700699 fontStyle = FontStyle.Italic,
Siyamed Sinirdc8f5742019-10-04 21:03:28 -0700700 fontWeight = FontWeight.Bold
Siyamed Sinir70f336a2018-12-27 10:37:09 -0800701 )
Siyamed Sinir37298412018-12-27 19:47:15 -0800702 val expectedStart = 0
703 val expectedEnd = "abc".length
Siyamed Sinir70f336a2018-12-27 10:37:09 -0800704
705 val paragraph = simpleParagraph(
706 text = text,
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800707 spanStyles = listOf(
Haoyu Zhang27429892019-06-11 13:19:57 -0700708 AnnotatedString.Item(
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800709 spanStyle,
Siyamed Sinir37298412018-12-27 19:47:15 -0800710 expectedStart,
711 expectedEnd
712 )
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700713 ),
714 constraints = ParagraphConstraints(width = 100.0f)
Siyamed Sinir70f336a2018-12-27 10:37:09 -0800715 )
Siyamed Sinir70f336a2018-12-27 10:37:09 -0800716
Siyamed Sinir63789c92019-09-25 10:44:11 -0700717 assertThat(paragraph.charSequence.toString()).isEqualTo(text)
718 assertThat(paragraph.charSequence)
719 .hasSpan(TypefaceSpan::class, expectedStart, expectedEnd) { span ->
Siyamed Sinir70f336a2018-12-27 10:37:09 -0800720 span.typeface == expectedTypeface
Siyamed Sinir63789c92019-09-25 10:44:11 -0700721 }
Siyamed Sinir37298412018-12-27 19:47:15 -0800722 }
723
724 @Test
haoyua8e48a52019-06-25 12:23:27 -0700725 fun testAnnotatedString_fontFamily_whenFontSynthesizeTurnedOff() {
Siyamed Sinir37298412018-12-27 19:47:15 -0800726 val text = "abcde"
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800727 val spanStyle = SpanStyle(
Siyamed Sinir37298412018-12-27 19:47:15 -0800728 fontFamily = fontFamily,
Siyamed Siniradf982d2019-05-20 17:35:13 -0700729 fontStyle = FontStyle.Italic,
Siyamed Sinirdc8f5742019-10-04 21:03:28 -0700730 fontWeight = FontWeight.Bold,
Siyamed Sinir934a3442019-06-18 12:57:13 -0700731 fontSynthesis = FontSynthesis.None
Siyamed Sinir70f336a2018-12-27 10:37:09 -0800732 )
Siyamed Sinir37298412018-12-27 19:47:15 -0800733 val expectedTypeface = TypefaceAdapter().create(
734 fontFamily = fontFamily,
Siyamed Siniradf982d2019-05-20 17:35:13 -0700735 fontStyle = FontStyle.Italic,
Siyamed Sinirdc8f5742019-10-04 21:03:28 -0700736 fontWeight = FontWeight.Bold,
Siyamed Sinir934a3442019-06-18 12:57:13 -0700737 fontSynthesis = FontSynthesis.None
Siyamed Sinir37298412018-12-27 19:47:15 -0800738 )
739 val expectedStart = 0
740 val expectedEnd = "abc".length
741
742 val paragraph = simpleParagraph(
743 text = text,
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800744 spanStyles = listOf(
Haoyu Zhang27429892019-06-11 13:19:57 -0700745 AnnotatedString.Item(
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800746 spanStyle,
Siyamed Sinir37298412018-12-27 19:47:15 -0800747 expectedStart,
748 expectedEnd
749 )
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700750 ),
751 constraints = ParagraphConstraints(width = 100.0f)
Siyamed Sinir37298412018-12-27 19:47:15 -0800752 )
Siyamed Sinir37298412018-12-27 19:47:15 -0800753
Siyamed Sinir63789c92019-09-25 10:44:11 -0700754 assertThat(paragraph.charSequence.toString()).isEqualTo(text)
755 assertThat(paragraph.charSequence)
756 .hasSpan(TypefaceSpan::class, expectedStart, expectedEnd) { span ->
Siyamed Sinir37298412018-12-27 19:47:15 -0800757 span.typeface == expectedTypeface
Siyamed Sinir63789c92019-09-25 10:44:11 -0700758 }
Siyamed Sinir70f336a2018-12-27 10:37:09 -0800759 }
760
761 @Test
haoyua8e48a52019-06-25 12:23:27 -0700762 fun testAnnotatedString_fontFeatureSetting_setSpanOnText() {
Haoyu Zhang588aaef2019-02-20 14:47:39 -0800763 val text = "abc"
764 val fontFeatureSettings = "\"kern\" 0"
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800765 val spanStyle = SpanStyle(fontFeatureSettings = fontFeatureSettings)
Haoyu Zhang588aaef2019-02-20 14:47:39 -0800766
767 val paragraph = simpleParagraph(
768 text = text,
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -0800769 spanStyles = listOf(AnnotatedString.Item(spanStyle, 0, "abc".length)),
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700770 constraints = ParagraphConstraints(width = 100.0f) // width is not important
Haoyu Zhang588aaef2019-02-20 14:47:39 -0800771 )
Haoyu Zhang588aaef2019-02-20 14:47:39 -0800772
Siyamed Sinir63789c92019-09-25 10:44:11 -0700773 assertThat(paragraph.charSequence).hasSpan(FontFeatureSpan::class, 0, "abc".length) {
774 it.fontFeatureSettings == fontFeatureSettings
775 }
Haoyu Zhang588aaef2019-02-20 14:47:39 -0800776 }
777
778 @Test
Siyamed Sinirf18dcca2018-12-20 18:25:10 -0800779 fun testEmptyFontFamily() {
780 val typefaceAdapter = mock<TypefaceAdapter>()
781 val paragraph = simpleParagraph(
782 text = "abc",
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700783 typefaceAdapter = typefaceAdapter,
784 constraints = ParagraphConstraints(width = Float.MAX_VALUE)
Siyamed Sinirf18dcca2018-12-20 18:25:10 -0800785 )
Siyamed Sinirf18dcca2018-12-20 18:25:10 -0800786
787 verify(typefaceAdapter, never()).create(
788 fontFamily = any(),
789 fontWeight = any(),
Siyamed Sinir21796012018-12-26 13:51:17 -0800790 fontStyle = any(),
791 fontSynthesis = any()
Siyamed Sinirf18dcca2018-12-20 18:25:10 -0800792 )
Siyamed Sinir63789c92019-09-25 10:44:11 -0700793 assertThat(paragraph.textPaint.typeface).isNull()
Siyamed Sinirf18dcca2018-12-20 18:25:10 -0800794 }
795
796 @Test
797 fun testEmptyFontFamily_withBoldFontWeightSelection() {
798 val typefaceAdapter = spy(TypefaceAdapter())
799
800 val paragraph = simpleParagraph(
801 text = "abc",
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -0700802 textStyle = TextStyle(
803 fontFamily = null,
Siyamed Sinirdc8f5742019-10-04 21:03:28 -0700804 fontWeight = FontWeight.Bold
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -0700805 ),
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700806 typefaceAdapter = typefaceAdapter,
807 constraints = ParagraphConstraints(width = Float.MAX_VALUE)
Siyamed Sinirf18dcca2018-12-20 18:25:10 -0800808 )
Siyamed Sinirf18dcca2018-12-20 18:25:10 -0800809
810 verify(typefaceAdapter, times(1)).create(
811 fontFamily = eq(null),
Siyamed Sinirdc8f5742019-10-04 21:03:28 -0700812 fontWeight = eq(FontWeight.Bold),
Siyamed Siniradf982d2019-05-20 17:35:13 -0700813 fontStyle = eq(FontStyle.Normal),
Siyamed Sinir934a3442019-06-18 12:57:13 -0700814 fontSynthesis = eq(FontSynthesis.All)
Siyamed Sinirf18dcca2018-12-20 18:25:10 -0800815 )
816
817 val typeface = paragraph.textPaint.typeface
Siyamed Sinir63789c92019-09-25 10:44:11 -0700818 assertThat(typeface).isNotNull()
819 assertThat(typeface.isBold).isTrue()
820 assertThat(typeface.isItalic).isFalse()
Siyamed Sinirf18dcca2018-12-20 18:25:10 -0800821 }
822
823 @Test
824 fun testEmptyFontFamily_withFontStyleSelection() {
825 val typefaceAdapter = spy(TypefaceAdapter())
826 val paragraph = simpleParagraph(
827 text = "abc",
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -0700828 textStyle = TextStyle(
829 fontFamily = null,
830 fontStyle = FontStyle.Italic
831 ),
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700832 typefaceAdapter = typefaceAdapter,
833 constraints = ParagraphConstraints(width = Float.MAX_VALUE)
Siyamed Sinirf18dcca2018-12-20 18:25:10 -0800834 )
Siyamed Sinirf18dcca2018-12-20 18:25:10 -0800835
836 verify(typefaceAdapter, times(1)).create(
837 fontFamily = eq(null),
Siyamed Sinirdc8f5742019-10-04 21:03:28 -0700838 fontWeight = eq(FontWeight.Normal),
Siyamed Siniradf982d2019-05-20 17:35:13 -0700839 fontStyle = eq(FontStyle.Italic),
Siyamed Sinir934a3442019-06-18 12:57:13 -0700840 fontSynthesis = eq(FontSynthesis.All)
Siyamed Sinirf18dcca2018-12-20 18:25:10 -0800841 )
842
843 val typeface = paragraph.textPaint.typeface
Siyamed Sinir63789c92019-09-25 10:44:11 -0700844 assertThat(typeface).isNotNull()
845 assertThat(typeface.isBold).isFalse()
846 assertThat(typeface.isItalic).isTrue()
Siyamed Sinirf18dcca2018-12-20 18:25:10 -0800847 }
848
849 @Test
850 fun testFontFamily_withGenericFamilyName() {
851 val typefaceAdapter = spy(TypefaceAdapter())
852 val fontFamily = FontFamily("sans-serif")
853
854 val paragraph = simpleParagraph(
855 text = "abc",
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -0700856 textStyle = TextStyle(
857 fontFamily = fontFamily
858 ),
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700859 typefaceAdapter = typefaceAdapter,
860 constraints = ParagraphConstraints(width = Float.MAX_VALUE)
Siyamed Sinirf18dcca2018-12-20 18:25:10 -0800861 )
Siyamed Sinirf18dcca2018-12-20 18:25:10 -0800862
863 verify(typefaceAdapter, times(1)).create(
864 fontFamily = eq(fontFamily),
Siyamed Sinirdc8f5742019-10-04 21:03:28 -0700865 fontWeight = eq(FontWeight.Normal),
Siyamed Siniradf982d2019-05-20 17:35:13 -0700866 fontStyle = eq(FontStyle.Normal),
Siyamed Sinir934a3442019-06-18 12:57:13 -0700867 fontSynthesis = eq(FontSynthesis.All)
Siyamed Sinirf18dcca2018-12-20 18:25:10 -0800868 )
869
870 val typeface = paragraph.textPaint.typeface
Siyamed Sinir63789c92019-09-25 10:44:11 -0700871 assertThat(typeface).isNotNull()
872 assertThat(typeface.isBold).isFalse()
873 assertThat(typeface.isItalic).isFalse()
Siyamed Sinirf18dcca2018-12-20 18:25:10 -0800874 }
875
876 @Test
877 fun testFontFamily_withCustomFont() {
878 val typefaceAdapter = spy(TypefaceAdapter())
879 val paragraph = simpleParagraph(
880 text = "abc",
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -0700881 textStyle = TextStyle(
882 fontFamily = fontFamily
883 ),
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700884 typefaceAdapter = typefaceAdapter,
885 constraints = ParagraphConstraints(width = Float.MAX_VALUE)
Siyamed Sinirf18dcca2018-12-20 18:25:10 -0800886 )
Siyamed Sinirf18dcca2018-12-20 18:25:10 -0800887
888 verify(typefaceAdapter, times(1)).create(
889 fontFamily = eq(fontFamily),
Siyamed Sinirdc8f5742019-10-04 21:03:28 -0700890 fontWeight = eq(FontWeight.Normal),
Siyamed Siniradf982d2019-05-20 17:35:13 -0700891 fontStyle = eq(FontStyle.Normal),
Siyamed Sinir934a3442019-06-18 12:57:13 -0700892 fontSynthesis = eq(FontSynthesis.All)
Siyamed Sinirf18dcca2018-12-20 18:25:10 -0800893 )
894 val typeface = paragraph.textPaint.typeface
Siyamed Sinir63789c92019-09-25 10:44:11 -0700895 assertThat(typeface.isBold).isFalse()
896 assertThat(typeface.isItalic).isFalse()
Siyamed Sinirf18dcca2018-12-20 18:25:10 -0800897 }
898
Haoyu Zhangc11ef5a2019-01-14 16:35:05 -0800899 @Test
900 fun testEllipsis_withMaxLineEqualsNull_doesNotEllipsis() {
Siyamed Sinir7d4c98f2019-06-27 16:23:31 -0700901 withDensity(defaultDensity) {
902 val text = "abc"
903 val fontSize = 20.sp
904 val paragraphWidth = (text.length - 1) * fontSize.toPx().value
905 val paragraph = simpleParagraph(
906 text = text,
907 textStyle = TextStyle(
908 fontFamily = fontFamily,
909 fontSize = fontSize
910 ),
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700911 ellipsis = true,
912 constraints = ParagraphConstraints(width = paragraphWidth)
Siyamed Sinir7d4c98f2019-06-27 16:23:31 -0700913 )
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700914
Siyamed Sinir7d4c98f2019-06-27 16:23:31 -0700915 for (i in 0 until paragraph.lineCount) {
Siyamed Sinir63789c92019-09-25 10:44:11 -0700916 assertThat(paragraph.isEllipsisApplied(i)).isFalse()
Siyamed Sinir7d4c98f2019-06-27 16:23:31 -0700917 }
Haoyu Zhangc11ef5a2019-01-14 16:35:05 -0800918 }
919 }
920
921 @Test
922 fun testEllipsis_withMaxLinesLessThanTextLines_doesEllipsis() {
Siyamed Sinir7d4c98f2019-06-27 16:23:31 -0700923 withDensity(defaultDensity) {
924 val text = "abcde"
925 val fontSize = 100.sp
926 // Note that on API 21, if the next line only contains 1 character, ellipsis won't work
927 val paragraphWidth = (text.length - 1.5f) * fontSize.toPx().value
928 val paragraph = simpleParagraph(
929 text = text,
930 ellipsis = true,
931 maxLines = 1,
932 textStyle = TextStyle(
933 fontFamily = fontFamily,
934 fontSize = fontSize
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700935 ),
936 constraints = ParagraphConstraints(width = paragraphWidth)
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -0700937 )
Haoyu Zhangc11ef5a2019-01-14 16:35:05 -0800938
Siyamed Sinir63789c92019-09-25 10:44:11 -0700939 assertThat(paragraph.isEllipsisApplied(0)).isTrue()
Siyamed Sinir7d4c98f2019-06-27 16:23:31 -0700940 }
Haoyu Zhangc11ef5a2019-01-14 16:35:05 -0800941 }
942
943 @Test
944 fun testEllipsis_withMaxLinesMoreThanTextLines_doesNotEllipsis() {
Siyamed Sinir7d4c98f2019-06-27 16:23:31 -0700945 withDensity(defaultDensity) {
946 val text = "abc"
947 val fontSize = 100.sp
948 val paragraphWidth = (text.length - 1) * fontSize.toPx().value
949 val maxLines = ceil(text.length * fontSize.toPx().value / paragraphWidth).toInt()
950 val paragraph = simpleParagraph(
951 text = text,
952 ellipsis = true,
953 maxLines = maxLines,
954 textStyle = TextStyle(
955 fontFamily = fontFamily,
956 fontSize = fontSize
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700957 ),
958 constraints = ParagraphConstraints(width = paragraphWidth)
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -0700959 )
Haoyu Zhangc11ef5a2019-01-14 16:35:05 -0800960
Siyamed Sinir7d4c98f2019-06-27 16:23:31 -0700961 for (i in 0 until paragraph.lineCount) {
Siyamed Sinir63789c92019-09-25 10:44:11 -0700962 assertThat(paragraph.isEllipsisApplied(i)).isFalse()
Siyamed Sinir7d4c98f2019-06-27 16:23:31 -0700963 }
Haoyu Zhangc11ef5a2019-01-14 16:35:05 -0800964 }
965 }
966
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -0700967 @Test
968 fun testTextStyle_fontSize_appliedOnTextPaint() {
Siyamed Sinir7d4c98f2019-06-27 16:23:31 -0700969 withDensity(defaultDensity) {
970 val fontSize = 100.sp
971 val paragraph = simpleParagraph(
972 text = "",
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700973 textStyle = TextStyle(fontSize = fontSize),
974 constraints = ParagraphConstraints(width = 0.0f)
Siyamed Sinir7d4c98f2019-06-27 16:23:31 -0700975 )
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -0700976
Siyamed Sinir63789c92019-09-25 10:44:11 -0700977 assertThat(paragraph.textPaint.textSize).isEqualTo(fontSize.toPx().value)
Siyamed Sinir7d4c98f2019-06-27 16:23:31 -0700978 }
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -0700979 }
980
981 @Test
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -0700982 fun testTextStyle_locale_appliedOnTextPaint() {
Seigo Nonaka8de69792019-09-04 14:55:15 -0700983 val platformLocale = java.util.Locale.JAPANESE
984 val localeList = LocaleList(platformLocale.toLanguageTag())
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -0700985
986 val paragraph = simpleParagraph(
987 text = "",
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -0700988 textStyle = TextStyle(localeList = localeList),
989 constraints = ParagraphConstraints(width = 0.0f)
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -0700990 )
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -0700991
Siyamed Sinir63789c92019-09-25 10:44:11 -0700992 assertThat(paragraph.textPaint.textLocale.language).isEqualTo(platformLocale.language)
993 assertThat(paragraph.textPaint.textLocale.country).isEqualTo(platformLocale.country)
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -0700994 }
995
996 @Test
997 fun testTextStyle_color_appliedOnTextPaint() {
998 val color = Color(0x12345678)
999 val paragraph = simpleParagraph(
1000 text = "",
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -07001001 textStyle = TextStyle(color = color),
1002 constraints = ParagraphConstraints(width = 0.0f)
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -07001003 )
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -07001004
Siyamed Sinir63789c92019-09-25 10:44:11 -07001005 assertThat(paragraph.textPaint.color).isEqualTo(color.toArgb())
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -07001006 }
1007
1008 @Test
1009 fun testTextStyle_letterSpacing_appliedOnTextPaint() {
Haoyu Zhangf2e9e032019-10-16 15:23:39 -07001010 val letterSpacing = 2
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -07001011 val paragraph = simpleParagraph(
1012 text = "",
Haoyu Zhangf2e9e032019-10-16 15:23:39 -07001013 textStyle = TextStyle(letterSpacing = letterSpacing.em),
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -07001014 constraints = ParagraphConstraints(width = 0.0f)
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -07001015 )
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -07001016
Siyamed Sinir63789c92019-09-25 10:44:11 -07001017 assertThat(paragraph.textPaint.letterSpacing).isEqualTo((letterSpacing))
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -07001018 }
1019
1020 @Test
1021 fun testTextStyle_fontFeatureSettings_appliedOnTextPaint() {
1022 val fontFeatureSettings = "\"kern\" 0"
1023 val paragraph = simpleParagraph(
1024 text = "",
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -07001025 textStyle = TextStyle(fontFeatureSettings = fontFeatureSettings),
1026 constraints = ParagraphConstraints(width = 0.0f)
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -07001027 )
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -07001028
Siyamed Sinir63789c92019-09-25 10:44:11 -07001029 assertThat(paragraph.textPaint.fontFeatureSettings).isEqualTo(fontFeatureSettings)
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -07001030 }
1031
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -07001032 @Test
1033 fun testTextStyle_scaleX_appliedOnTextPaint() {
1034 val scaleX = 0.5f
1035 val paragraph = simpleParagraph(
1036 text = "",
1037 textStyle = TextStyle(
1038 textGeometricTransform = TextGeometricTransform(
1039 scaleX = scaleX
1040 )
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -07001041 ),
1042 constraints = ParagraphConstraints(width = 0.0f)
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -07001043 )
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -07001044
Siyamed Sinir63789c92019-09-25 10:44:11 -07001045 assertThat(paragraph.textPaint.textScaleX).isEqualTo(scaleX)
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -07001046 }
1047
1048 @Test
1049 fun testTextStyle_skewX_appliedOnTextPaint() {
1050 val skewX = 0.5f
1051 val paragraph = simpleParagraph(
1052 text = "",
1053 textStyle = TextStyle(
1054 textGeometricTransform = TextGeometricTransform(
1055 skewX = skewX
1056 )
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -07001057 ),
1058 constraints = ParagraphConstraints(width = 0.0f)
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -07001059 )
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -07001060
Siyamed Sinir63789c92019-09-25 10:44:11 -07001061 assertThat(paragraph.textPaint.textSkewX).isEqualTo(skewX)
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -07001062 }
1063
1064 @Test
1065 fun testTextStyle_decoration_underline_appliedOnTextPaint() {
1066 val paragraph = simpleParagraph(
1067 text = "",
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -07001068 textStyle = TextStyle(decoration = TextDecoration.Underline),
1069 constraints = ParagraphConstraints(width = 0.0f)
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -07001070 )
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -07001071
Siyamed Sinir18914522019-09-25 15:41:44 -07001072 assertThat(paragraph.textPaint.isUnderlineText).isTrue()
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -07001073 }
1074
1075 @Test
1076 fun testTextStyle_decoration_lineThrough_appliedOnTextPaint() {
1077 val paragraph = simpleParagraph(
1078 text = "",
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -07001079 textStyle = TextStyle(decoration = TextDecoration.LineThrough),
1080 constraints = ParagraphConstraints(width = 0.0f)
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -07001081 )
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -07001082
Siyamed Sinir18914522019-09-25 15:41:44 -07001083 assertThat(paragraph.textPaint.isStrikeThruText).isTrue()
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -07001084 }
1085
1086 @Test
1087 fun testTextStyle_background_appliedAsSpan() {
1088 // bgColor is reset in the Android Layout constructor.
1089 // therefore we cannot apply them on paint, have to use spans.
1090 val text = "abc"
1091 val color = Color(0x12345678)
1092 val paragraph = simpleParagraph(
1093 text = text,
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -07001094 textStyle = TextStyle(background = color),
1095 constraints = ParagraphConstraints(width = 0.0f)
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -07001096 )
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -07001097
Siyamed Sinir63789c92019-09-25 10:44:11 -07001098 assertThat(paragraph.charSequence)
1099 .hasSpan(BackgroundColorSpan::class, 0, text.length) { span ->
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -07001100 span.backgroundColor == color.toArgb()
1101 }
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -07001102 }
1103
1104 @Test
1105 fun testTextStyle_baselineShift_appliedAsSpan() {
1106 // baselineShift is reset in the Android Layout constructor.
1107 // therefore we cannot apply them on paint, have to use spans.
1108 val text = "abc"
1109 val baselineShift = BaselineShift.Subscript
1110 val paragraph = simpleParagraph(
1111 text = text,
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -07001112 textStyle = TextStyle(baselineShift = baselineShift),
1113 constraints = ParagraphConstraints(width = 0.0f)
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -07001114 )
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -07001115
Siyamed Sinir63789c92019-09-25 10:44:11 -07001116 assertThat(paragraph.charSequence)
1117 .hasSpan(BaselineShiftSpan::class, 0, text.length) { span ->
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -07001118 span.multiplier == BaselineShift.Subscript.multiplier
1119 }
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -07001120 }
1121
Siyamed Sinir031e5bf2019-07-02 11:49:05 -07001122 @Test
1123 fun locale_isDefaultLocaleIfNotProvided() {
1124 val text = "abc"
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -07001125 val paragraph = simpleParagraph(
1126 text = text,
1127 constraints = ParagraphConstraints(width = Float.MAX_VALUE)
1128 )
Siyamed Sinir031e5bf2019-07-02 11:49:05 -07001129
Siyamed Sinir63789c92019-09-25 10:44:11 -07001130 assertThat(paragraph.textLocale.toLanguageTag())
1131 .isEqualTo(java.util.Locale.getDefault().toLanguageTag())
Siyamed Sinir031e5bf2019-07-02 11:49:05 -07001132 }
1133
1134 @Test
1135 fun locale_isSetOnParagraphImpl_enUS() {
Seigo Nonaka8de69792019-09-04 14:55:15 -07001136 val localeList = LocaleList("en-US")
Siyamed Sinir031e5bf2019-07-02 11:49:05 -07001137 val text = "abc"
1138 val paragraph = simpleParagraph(
1139 text = text,
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -07001140 textStyle = TextStyle(localeList = localeList),
1141 constraints = ParagraphConstraints(width = Float.MAX_VALUE)
Siyamed Sinir031e5bf2019-07-02 11:49:05 -07001142 )
1143
Siyamed Sinir63789c92019-09-25 10:44:11 -07001144 assertThat(paragraph.textLocale.toLanguageTag()).isEqualTo("en-US")
Siyamed Sinir031e5bf2019-07-02 11:49:05 -07001145 }
1146
1147 @Test
1148 fun locale_isSetOnParagraphImpl_jpJP() {
Seigo Nonaka8de69792019-09-04 14:55:15 -07001149 val localeList = LocaleList("ja-JP")
Siyamed Sinir031e5bf2019-07-02 11:49:05 -07001150 val text = "abc"
1151 val paragraph = simpleParagraph(
1152 text = text,
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -07001153 textStyle = TextStyle(localeList = localeList),
1154 constraints = ParagraphConstraints(width = Float.MAX_VALUE)
Siyamed Sinir031e5bf2019-07-02 11:49:05 -07001155 )
1156
Siyamed Sinir63789c92019-09-25 10:44:11 -07001157 assertThat(paragraph.textLocale.toLanguageTag()).isEqualTo("ja-JP")
Siyamed Sinir031e5bf2019-07-02 11:49:05 -07001158 }
1159
1160 @Test
1161 fun locale_noCountryCode_isSetOnParagraphImpl() {
Seigo Nonaka8de69792019-09-04 14:55:15 -07001162 val localeList = LocaleList("ja")
Siyamed Sinir031e5bf2019-07-02 11:49:05 -07001163 val text = "abc"
1164 val paragraph = simpleParagraph(
1165 text = text,
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -07001166 textStyle = TextStyle(localeList = localeList),
1167 constraints = ParagraphConstraints(width = Float.MAX_VALUE)
Siyamed Sinir031e5bf2019-07-02 11:49:05 -07001168 )
1169
Siyamed Sinir63789c92019-09-25 10:44:11 -07001170 assertThat(paragraph.textLocale.toLanguageTag()).isEqualTo("ja")
Siyamed Sinir031e5bf2019-07-02 11:49:05 -07001171 }
1172
Seigo Nonakac4f136a2019-08-16 16:48:44 -07001173 @Test
Seigo Nonakaad4a3772019-08-26 12:06:58 -07001174 fun floatingWidth() {
1175 val floatWidth = 1.3f
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -07001176 val paragraph = simpleParagraph(
1177 text = "Hello, World",
1178 constraints = ParagraphConstraints(floatWidth)
1179 )
1180
Siyamed Sinir63789c92019-09-25 10:44:11 -07001181 assertThat(floatWidth).isEqualTo(paragraph.width)
Seigo Nonakaad4a3772019-08-26 12:06:58 -07001182 }
1183
Haoyu Zhang10fc6502018-11-09 15:50:11 -08001184 private fun simpleParagraph(
Haoyu Zhang27429892019-06-11 13:19:57 -07001185 text: String = "",
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -08001186 spanStyles: List<AnnotatedString.Item<SpanStyle>> = listOf(),
Siyamed Sinir2690d532019-06-21 13:16:00 -07001187 textIndent: TextIndent? = null,
Haoyu Zhang10fc6502018-11-09 15:50:11 -08001188 textAlign: TextAlign? = null,
Siyamed Sinir504d5b02019-09-24 13:39:43 -07001189 textDirectionAlgorithm: TextDirectionAlgorithm? = TextDirectionAlgorithm.ContentOrLtr,
Haoyu Zhangc11ef5a2019-01-14 16:35:05 -08001190 ellipsis: Boolean? = null,
Siyamed Sinirf18dcca2018-12-20 18:25:10 -08001191 maxLines: Int? = null,
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -07001192 constraints: ParagraphConstraints,
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -07001193 textStyle: TextStyle? = null,
Siyamed Sinirf18dcca2018-12-20 18:25:10 -08001194 typefaceAdapter: TypefaceAdapter = TypefaceAdapter()
Siyamed Sinire75976f2019-07-03 09:24:30 -07001195 ): AndroidParagraph {
1196 return AndroidParagraph(
Haoyu Zhang27429892019-06-11 13:19:57 -07001197 text = text,
Siyamed Sinirfaa4ac42019-12-04 09:02:31 -08001198 spanStyles = spanStyles,
Siyamed Sinirf18dcca2018-12-20 18:25:10 -08001199 typefaceAdapter = typefaceAdapter,
Siyamed Sinirbf9f3ba2019-06-25 22:40:56 -07001200 style = TextStyle().merge(textStyle),
Siyamed Sinir883e0232019-06-25 12:38:12 -07001201 paragraphStyle = ParagraphStyle(
1202 textAlign = textAlign,
Siyamed Sinir504d5b02019-09-24 13:39:43 -07001203 textIndent = textIndent,
1204 textDirectionAlgorithm = textDirectionAlgorithm
Siyamed Sinir7d4c98f2019-06-27 16:23:31 -07001205 ),
Siyamed Sinir6a1f0362019-07-08 15:58:32 -07001206 maxLines = maxLines,
1207 ellipsis = ellipsis,
Siyamed Sinir3f44b9a2019-09-21 13:13:38 -07001208 constraints = constraints,
Siyamed Sinir504d5b02019-09-24 13:39:43 -07001209 density = Density(density = 1f)
Haoyu Zhang10fc6502018-11-09 15:50:11 -08001210 )
1211 }
Siyamed Sinir472ed132019-07-03 15:43:43 -07001212
1213 private fun TypefaceAdapter() = TypefaceAdapter(
Siyamed Sinirc4c308e2019-07-03 16:14:22 -07001214 resourceLoader = TestFontResourceLoader(context)
Siyamed Sinir472ed132019-07-03 15:43:43 -07001215 )
Siyamed Sinir2690d532019-06-21 13:16:00 -07001216}