[go: nahoru, domu]

blob: 2693e416d643b50f4b6d65372c6c551902491616 [file] [log] [blame]
Haoyu Zhang10fc6502018-11-09 15:50:11 -08001package androidx.ui.port.engine.text.platform
2
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 Zhang4b201d22018-12-18 14:27:38 -08008import android.text.style.LocaleSpan
Haoyu Zhangb5677202018-12-19 14:22:18 -08009import android.text.style.StrikethroughSpan
10import android.text.style.UnderlineSpan
Haoyu Zhang97d5e722019-01-04 17:32:34 -080011import androidx.test.filters.SdkSuppress
Haoyu Zhang10fc6502018-11-09 15:50:11 -080012import androidx.test.filters.SmallTest
13import androidx.test.platform.app.InstrumentationRegistry
Haoyu Zhang2eb38cd2018-11-21 15:05:28 -080014import androidx.text.StaticLayoutCompat
Haoyu Zhang1588ba0f2018-12-19 16:47:10 -080015import androidx.text.style.LetterSpacingSpan
Siyamed Sinir70f336a2018-12-27 10:37:09 -080016import androidx.text.style.TypefaceSpan
Haoyu Zhang97d5e722019-01-04 17:32:34 -080017import androidx.text.style.WordSpacingSpan
Siyamed Sinirf18dcca2018-12-20 18:25:10 -080018import androidx.ui.engine.text.FontStyle
Siyamed Sinir21796012018-12-26 13:51:17 -080019import androidx.ui.engine.text.FontSynthesis
Siyamed Sinirf18dcca2018-12-20 18:25:10 -080020import androidx.ui.engine.text.FontWeight
Haoyu Zhang47f57a22018-12-12 13:16:40 -080021import androidx.ui.engine.text.ParagraphBuilder
Haoyu Zhang10fc6502018-11-09 15:50:11 -080022import androidx.ui.engine.text.ParagraphStyle
23import androidx.ui.engine.text.TextAlign
Haoyu Zhangb5677202018-12-19 14:22:18 -080024import androidx.ui.engine.text.TextDecoration
Haoyu Zhang47f57a22018-12-12 13:16:40 -080025import androidx.ui.engine.text.TextStyle
Siyamed Sinirf18dcca2018-12-20 18:25:10 -080026import androidx.ui.engine.text.font.FontFamily
27import androidx.ui.engine.text.font.asFontFamily
Haoyu Zhang10fc6502018-11-09 15:50:11 -080028import androidx.ui.engine.text.platform.ParagraphAndroid
Siyamed Sinirf18dcca2018-12-20 18:25:10 -080029import androidx.ui.engine.text.platform.TypefaceAdapter
Haoyu Zhang4b201d22018-12-18 14:27:38 -080030import androidx.ui.engine.window.Locale
Haoyu Zhang47f57a22018-12-12 13:16:40 -080031import androidx.ui.painting.Color
Siyamed Sinirf18dcca2018-12-20 18:25:10 -080032import androidx.ui.port.engine.text.FontTestData.Companion.BASIC_MEASURE_FONT
Haoyu Zhang10fc6502018-11-09 15:50:11 -080033import androidx.ui.port.matchers.equalToBitmap
Haoyu Zhang47f57a22018-12-12 13:16:40 -080034import androidx.ui.port.matchers.hasSpan
35import androidx.ui.port.matchers.hasSpanOnTop
Siyamed Sinirf18dcca2018-12-20 18:25:10 -080036import com.nhaarman.mockitokotlin2.any
37import com.nhaarman.mockitokotlin2.eq
38import com.nhaarman.mockitokotlin2.mock
39import com.nhaarman.mockitokotlin2.never
40import com.nhaarman.mockitokotlin2.spy
41import com.nhaarman.mockitokotlin2.times
42import com.nhaarman.mockitokotlin2.verify
Haoyu Zhangb5677202018-12-19 14:22:18 -080043import org.hamcrest.Matchers.equalTo
Siyamed Sinirf18dcca2018-12-20 18:25:10 -080044import org.hamcrest.Matchers.not
45import org.hamcrest.Matchers.nullValue
Haoyu Zhang47f57a22018-12-12 13:16:40 -080046import org.junit.Assert.assertThat
Haoyu Zhang10fc6502018-11-09 15:50:11 -080047import org.junit.Before
48import org.junit.Test
49import org.junit.runner.RunWith
50import org.junit.runners.JUnit4
Haoyu Zhang10fc6502018-11-09 15:50:11 -080051import kotlin.math.ceil
52
53@RunWith(JUnit4::class)
54@SmallTest
55class ParagraphAndroidTest {
Siyamed Sinirf18dcca2018-12-20 18:25:10 -080056 private lateinit var fontFamily: FontFamily
Haoyu Zhang10fc6502018-11-09 15:50:11 -080057
58 @Before
59 fun setup() {
Haoyu Zhang47f57a22018-12-12 13:16:40 -080060 // This sample font provides the following features:
61 // 1. The width of most of visible characters equals to font size.
62 // 2. The LTR/RTL characters are rendered as â–¶/â—€.
63 // 3. The fontMetrics passed to TextPaint has descend - ascend equal to 1.2 * fontSize.
Siyamed Sinirf18dcca2018-12-20 18:25:10 -080064 fontFamily = BASIC_MEASURE_FONT.asFontFamily()
65 fontFamily.context = InstrumentationRegistry.getInstrumentation().context
Haoyu Zhang10fc6502018-11-09 15:50:11 -080066 }
67
68 @Test
69 fun draw_with_newline_and_line_break_default_values() {
George Mountb1cdd862018-12-21 10:54:42 -080070 val fontSize = 50.0f
Haoyu Zhang10fc6502018-11-09 15:50:11 -080071 for (text in arrayOf("abc\ndef", "\u05D0\u05D1\u05D2\n\u05D3\u05D4\u05D5")) {
72 val paragraphAndroid = simpleParagraph(
73 text = StringBuilder(text),
Siyamed Sinirf18dcca2018-12-20 18:25:10 -080074 fontSize = fontSize,
75 fontFamily = fontFamily
Haoyu Zhang10fc6502018-11-09 15:50:11 -080076 )
77
78 // 2 chars width
79 paragraphAndroid.layout(width = 2 * fontSize)
80
81 val textPaint = TextPaint(Paint.ANTI_ALIAS_FLAG)
George Mountb1cdd862018-12-21 10:54:42 -080082 textPaint.textSize = fontSize
Siyamed Sinirf18dcca2018-12-20 18:25:10 -080083 textPaint.typeface = TypefaceAdapter().create(fontFamily)
Haoyu Zhang10fc6502018-11-09 15:50:11 -080084
Haoyu Zhang2eb38cd2018-11-21 15:05:28 -080085 val staticLayout = StaticLayoutCompat.Builder(
86 text,
87 textPaint,
88 ceil(paragraphAndroid.width).toInt()
Haoyu Zhang10fc6502018-11-09 15:50:11 -080089 )
Haoyu Zhang2eb38cd2018-11-21 15:05:28 -080090 .setEllipsizedWidth(ceil(paragraphAndroid.width).toInt())
91 .build()
Haoyu Zhang47f57a22018-12-12 13:16:40 -080092 assertThat(paragraphAndroid.bitmap(), equalToBitmap(staticLayout.bitmap()))
Haoyu Zhang10fc6502018-11-09 15:50:11 -080093 }
94 }
95
Haoyu Zhang47f57a22018-12-12 13:16:40 -080096 @Test
97 fun textStyle_setColorOnWholeText() {
98 val text = "abcde"
Haoyu Zhang47f57a22018-12-12 13:16:40 -080099 val textStyle = TextStyle(color = Color(0xFF0000FF.toInt()))
100
101 val paragraph = simpleParagraph(
102 text = text,
Haoyu Zhang4b201d22018-12-18 14:27:38 -0800103 textStyles = listOf(ParagraphBuilder.TextStyleIndex(textStyle, 0, text.length))
Haoyu Zhang47f57a22018-12-12 13:16:40 -0800104 )
George Mountb1cdd862018-12-21 10:54:42 -0800105 paragraph.layout(100.0f)
Haoyu Zhang47f57a22018-12-12 13:16:40 -0800106
107 assertThat(paragraph.underlyingText, hasSpan(ForegroundColorSpan::class, 0, text.length))
108 }
109
110 @Test
111 fun textStyle_setColorOnPartOfText() {
112 val text = "abcde"
Haoyu Zhang47f57a22018-12-12 13:16:40 -0800113 val textStyle = TextStyle(color = Color(0xFF0000FF.toInt()))
114
115 val paragraph = simpleParagraph(
116 text = text,
Haoyu Zhang4b201d22018-12-18 14:27:38 -0800117 textStyles = listOf(ParagraphBuilder.TextStyleIndex(textStyle, 0, "abc".length))
Haoyu Zhang47f57a22018-12-12 13:16:40 -0800118 )
George Mountb1cdd862018-12-21 10:54:42 -0800119 paragraph.layout(100.0f)
Haoyu Zhang47f57a22018-12-12 13:16:40 -0800120
121 assertThat(paragraph.underlyingText, hasSpan(ForegroundColorSpan::class, 0, "abc".length))
122 }
123
124 @Test
125 fun textStyle_setColorTwice_lastOneOverwrite() {
126 val text = "abcde"
Haoyu Zhang47f57a22018-12-12 13:16:40 -0800127 val textStyle = TextStyle(color = Color(0xFF0000FF.toInt()))
128 val textStyleOverwrite = TextStyle(color = Color(0xFF00FF00.toInt()))
129
130 val paragraph = simpleParagraph(
131 text = text,
132 textStyles = listOf(
133 ParagraphBuilder.TextStyleIndex(textStyle, 0, text.length),
134 ParagraphBuilder.TextStyleIndex(textStyleOverwrite, 0, "abc".length)
Haoyu Zhang4b201d22018-12-18 14:27:38 -0800135 )
Haoyu Zhang47f57a22018-12-12 13:16:40 -0800136 )
George Mountb1cdd862018-12-21 10:54:42 -0800137 paragraph.layout(100.0f)
Haoyu Zhang47f57a22018-12-12 13:16:40 -0800138
139 assertThat(paragraph.underlyingText, hasSpan(ForegroundColorSpan::class, 0, text.length))
140 assertThat(paragraph.underlyingText, hasSpan(ForegroundColorSpan::class, 0, "abc".length))
141 assertThat(
142 paragraph.underlyingText,
143 hasSpanOnTop(ForegroundColorSpan::class, 0, "abc".length)
144 )
145 }
146
Haoyu Zhangbb51ccf2018-12-17 15:07:43 -0800147 @Test
Haoyu Zhangb5677202018-12-19 14:22:18 -0800148 fun testStyle_setTextDecorationOnWholeText_withLineThrough() {
149 val text = "abcde"
150 val textStyle = TextStyle(decoration = TextDecoration.lineThrough)
151
152 val paragraph = simpleParagraph(
153 text = text,
154 textStyles = listOf(ParagraphBuilder.TextStyleIndex(textStyle, 0, text.length))
155 )
George Mountb1cdd862018-12-21 10:54:42 -0800156 paragraph.layout(100.0f)
Haoyu Zhangb5677202018-12-19 14:22:18 -0800157
158 assertThat(paragraph.underlyingText.toString(), equalTo(text))
159 assertThat(paragraph.underlyingText, hasSpan(StrikethroughSpan::class, 0, text.length))
160 }
161
162 @Test
163 fun testStyle_setTextDecorationOnWholeText_withUnderline() {
164 val text = "abcde"
165 val textStyle = TextStyle(decoration = TextDecoration.underline)
166
167 val paragraph = simpleParagraph(
168 text = text,
169 textStyles = listOf(ParagraphBuilder.TextStyleIndex(textStyle, 0, text.length))
170 )
George Mountb1cdd862018-12-21 10:54:42 -0800171 paragraph.layout(100.0f)
Haoyu Zhangb5677202018-12-19 14:22:18 -0800172
173 assertThat(paragraph.underlyingText.toString(), equalTo(text))
174 assertThat(paragraph.underlyingText, hasSpan(UnderlineSpan::class, 0, text.length))
175 }
176
177 @Test
178 fun testStyle_setTextDecorationOnPartText_withLineThrough() {
179 val text = "abcde"
180 val textStyle = TextStyle(decoration = TextDecoration.lineThrough)
181
182 val paragraph = simpleParagraph(
183 text = text,
184 textStyles = listOf(ParagraphBuilder.TextStyleIndex(textStyle, 0, "abc".length))
185 )
George Mountb1cdd862018-12-21 10:54:42 -0800186 paragraph.layout(100.0f)
Haoyu Zhangb5677202018-12-19 14:22:18 -0800187
188 assertThat(paragraph.underlyingText.toString(), equalTo(text))
189 assertThat(paragraph.underlyingText, hasSpan(StrikethroughSpan::class, 0, "abc".length))
190 }
191
192 @Test
193 fun testStyle_setTextDecorationOnPartText_withUnderline() {
194 val text = "abcde"
195 val textStyle = TextStyle(decoration = TextDecoration.underline)
196
197 val paragraph = simpleParagraph(
198 text = text,
199 textStyles = listOf(ParagraphBuilder.TextStyleIndex(textStyle, 0, "abc".length))
200 )
George Mountb1cdd862018-12-21 10:54:42 -0800201 paragraph.layout(100.0f)
Haoyu Zhangb5677202018-12-19 14:22:18 -0800202
203 assertThat(paragraph.underlyingText.toString(), equalTo(text))
204 assertThat(paragraph.underlyingText, hasSpan(UnderlineSpan::class, 0, "abc".length))
205 }
206
207 @Test
208 fun testStyle_setTextDecoration_withLineThroughAndUnderline() {
209 val text = "abcde"
210 val textStyle = TextStyle(
211 decoration = TextDecoration.combine(
212 listOf(TextDecoration.lineThrough, TextDecoration.underline)
213 )
214 )
215
216 val paragraph = simpleParagraph(
217 text = text,
218 textStyles = listOf(ParagraphBuilder.TextStyleIndex(textStyle, 0, "abc".length))
219 )
George Mountb1cdd862018-12-21 10:54:42 -0800220 paragraph.layout(100.0f)
Haoyu Zhangb5677202018-12-19 14:22:18 -0800221
222 assertThat(paragraph.underlyingText.toString(), equalTo(text))
223 assertThat(paragraph.underlyingText, hasSpan(UnderlineSpan::class, 0, "abc".length))
224 assertThat(paragraph.underlyingText, hasSpan(StrikethroughSpan::class, 0, "abc".length))
225 }
226
227 @Test
Haoyu Zhangbb51ccf2018-12-17 15:07:43 -0800228 fun textStyle_setFontSizeOnWholeText() {
229 val text = "abcde"
George Mountb1cdd862018-12-21 10:54:42 -0800230 val fontSize = 20.0f
Haoyu Zhangbb51ccf2018-12-17 15:07:43 -0800231 val paragraphWidth = text.length * fontSize
232 val textStyle = TextStyle(fontSize = fontSize)
233
234 val paragraph = simpleParagraph(
235 text = text,
236 textStyles = listOf(ParagraphBuilder.TextStyleIndex(textStyle, 0, text.length))
237 )
238 paragraph.layout(paragraphWidth)
239
240 assertThat(paragraph.underlyingText, hasSpan(AbsoluteSizeSpan::class, 0, text.length))
241 }
242
243 @Test
244 fun textStyle_setFontSizeOnPartText() {
245 val text = "abcde"
George Mountb1cdd862018-12-21 10:54:42 -0800246 val fontSize = 20.0f
Haoyu Zhangbb51ccf2018-12-17 15:07:43 -0800247 val paragraphWidth = text.length * fontSize
248 val textStyle = TextStyle(fontSize = fontSize)
249
250 val paragraph = simpleParagraph(
251 text = text,
252 textStyles = listOf(ParagraphBuilder.TextStyleIndex(textStyle, 0, "abc".length))
253 )
254 paragraph.layout(paragraphWidth)
255
256 assertThat(paragraph.underlyingText, hasSpan(AbsoluteSizeSpan::class, 0, "abc".length))
257 }
258
259 @Test
260 fun textStyle_setFontSizeTwice_lastOneOverwrite() {
261 val text = "abcde"
George Mountb1cdd862018-12-21 10:54:42 -0800262 val fontSize = 20.0f
263 val fontSizeOverwrite = 30.0f
Haoyu Zhangbb51ccf2018-12-17 15:07:43 -0800264 val paragraphWidth = text.length * fontSizeOverwrite
265 val textStyle = TextStyle(fontSize = fontSize)
266 val textStyleOverwrite = TextStyle(fontSize = fontSizeOverwrite)
267
268 val paragraph = simpleParagraph(
269 text = text,
270 textStyles = listOf(
271 ParagraphBuilder.TextStyleIndex(textStyle, 0, text.length),
272 ParagraphBuilder.TextStyleIndex(textStyleOverwrite, 0, "abc".length)
273 )
274 )
275 paragraph.layout(paragraphWidth)
276
277 assertThat(paragraph.underlyingText, hasSpan(AbsoluteSizeSpan::class, 0, text.length))
278 assertThat(paragraph.underlyingText, hasSpan(AbsoluteSizeSpan::class, 0, "abc".length))
279 assertThat(
280 paragraph.underlyingText,
281 hasSpanOnTop(AbsoluteSizeSpan::class, 0, "abc".length)
282 )
283 }
284
Haoyu Zhang1588ba0f2018-12-19 16:47:10 -0800285 @Test
286 fun textStyle_setLetterSpacingOnWholeText() {
287 val text = "abcde"
George Mountb1cdd862018-12-21 10:54:42 -0800288 val letterSpacing = 2.0f
Haoyu Zhang1588ba0f2018-12-19 16:47:10 -0800289 val textStyle = TextStyle(letterSpacing = letterSpacing)
290
291 val paragraph = simpleParagraph(
292 text = text,
293 textStyles = listOf(ParagraphBuilder.TextStyleIndex(textStyle, 0, text.length))
294 )
George Mountb1cdd862018-12-21 10:54:42 -0800295 paragraph.layout(100.0f)
Haoyu Zhang1588ba0f2018-12-19 16:47:10 -0800296 assertThat(paragraph.underlyingText.toString(), equalTo(text))
297 assertThat(paragraph.underlyingText, hasSpan(LetterSpacingSpan::class, 0, text.length))
298 }
299
300 @Test
301 fun textStyle_setLetterSpacingOnPartText() {
302 val text = "abcde"
George Mountb1cdd862018-12-21 10:54:42 -0800303 val textStyle = TextStyle(letterSpacing = 2.0f)
Haoyu Zhang1588ba0f2018-12-19 16:47:10 -0800304
305 val paragraph = simpleParagraph(
306 text = text,
307 textStyles = listOf(ParagraphBuilder.TextStyleIndex(textStyle, 0, "abc".length))
308 )
George Mountb1cdd862018-12-21 10:54:42 -0800309 paragraph.layout(100.0f)
Haoyu Zhang1588ba0f2018-12-19 16:47:10 -0800310 assertThat(paragraph.underlyingText.toString(), equalTo(text))
311 assertThat(paragraph.underlyingText, hasSpan(LetterSpacingSpan::class, 0, "abc".length))
312 }
313
314 @Test
Haoyu Zhang4b201d22018-12-18 14:27:38 -0800315 fun textStyle_setLetterSpacingTwice_lastOneOverwrite() {
Haoyu Zhang1588ba0f2018-12-19 16:47:10 -0800316 val text = "abcde"
George Mountb1cdd862018-12-21 10:54:42 -0800317 val textStyle = TextStyle(letterSpacing = 2.0f)
318 val textStyleOverwrite = TextStyle(letterSpacing = 3.0f)
Haoyu Zhang1588ba0f2018-12-19 16:47:10 -0800319
320 val paragraph = simpleParagraph(
321 text = text,
322 textStyles = listOf(
323 ParagraphBuilder.TextStyleIndex(textStyle, 0, text.length),
324 ParagraphBuilder.TextStyleIndex(textStyleOverwrite, 0, "abc".length)
325 )
326 )
George Mountb1cdd862018-12-21 10:54:42 -0800327 paragraph.layout(100.0f)
Haoyu Zhang1588ba0f2018-12-19 16:47:10 -0800328 assertThat(paragraph.underlyingText.toString(), equalTo(text))
329 assertThat(paragraph.underlyingText, hasSpan(LetterSpacingSpan::class, 0, text.length))
330 assertThat(paragraph.underlyingText, hasSpan(LetterSpacingSpan::class, 0, "abc".length))
331 assertThat(
332 paragraph.underlyingText,
333 hasSpanOnTop(LetterSpacingSpan::class, 0, "abc".length)
334 )
335 }
336
Siyamed Sinir70f336a2018-12-27 10:37:09 -0800337 @Test
Haoyu Zhang97d5e722019-01-04 17:32:34 -0800338 @SdkSuppress(minSdkVersion = 28)
339 fun textStyle_setWordSpacingOnWholeText() {
340 val text = "ab cd"
341 val wordSpacing = 2.0f
342 val textStyle = TextStyle(wordSpacing = wordSpacing)
343
344 val paragraph = simpleParagraph(
345 text = text,
346 textStyles = listOf(ParagraphBuilder.TextStyleIndex(textStyle, 0, text.length))
347 )
348 // Notice that the width doesn't matter for this test.
349 paragraph.layout(100.0f)
350
351 assertThat(paragraph.underlyingText.toString(), equalTo(text))
352 assertThat(
353 paragraph.underlyingText,
354 hasSpan(WordSpacingSpan::class, 0, text.length) { span ->
355 span.wordSpacing == wordSpacing.toFloat()
356 }
357 )
358 }
359
360 @Test
361 @SdkSuppress(minSdkVersion = 28)
362 fun textStyle_setWordSpacingOnPartText() {
363 val text = "abc d"
364 val wordSpacing = 2.0f
365 val textStyle = TextStyle(wordSpacing = wordSpacing)
366
367 val paragraph = simpleParagraph(
368 text = text,
369 textStyles = listOf(ParagraphBuilder.TextStyleIndex(textStyle, 0, "abc".length))
370 )
371 // Notice that the width doesn't matter for this test.
372 paragraph.layout(100.0f)
373
374 assertThat(paragraph.underlyingText.toString(), equalTo(text))
375 assertThat(
376 paragraph.underlyingText,
377 hasSpan(WordSpacingSpan::class, 0, "abc".length) { span ->
378 span.wordSpacing == wordSpacing.toFloat()
379 }
380 )
381 }
382
383 @Test
384 @SdkSuppress(minSdkVersion = 28)
385 fun textStyle_setWordSpacingTwice_lastOneOverwrite() {
386 val text = "abc d"
387 val wordSpacing = 2.0f
388 val textStyle = TextStyle(wordSpacing = wordSpacing)
389 val wordSpacingOverwrite = 3.0f
390 val textStyleOverwrite = TextStyle(wordSpacing = wordSpacingOverwrite)
391
392 val paragraph = simpleParagraph(
393 text = text,
394 textStyles = listOf(
395 ParagraphBuilder.TextStyleIndex(textStyle, 0, text.length),
396 ParagraphBuilder.TextStyleIndex(textStyleOverwrite, 0, "abc".length)
397 )
398 )
399 // Notice that the width doesn't matter for this test.
400 paragraph.layout(100.0f)
401
402 assertThat(paragraph.underlyingText.toString(), equalTo(text))
403 assertThat(
404 paragraph.underlyingText,
405 hasSpan(WordSpacingSpan::class, 0, text.length) { span ->
406 span.wordSpacing == wordSpacing.toFloat()
407 }
408 )
409 assertThat(
410 paragraph.underlyingText,
411 hasSpan(WordSpacingSpan::class, 0, "abc".length) { span ->
412 span.wordSpacing == wordSpacingOverwrite.toFloat()
413 }
414 )
415 assertThat(
416 paragraph.underlyingText,
417 hasSpanOnTop(WordSpacingSpan::class, 0, "abc".length) { span ->
418 span.wordSpacing == wordSpacingOverwrite.toFloat()
419 }
420 )
421 }
422
423 @Test
Haoyu Zhang0c4fd022019-01-02 13:53:10 -0800424 fun textStyle_setBackgroundOnWholeText() {
425 val text = "abcde"
426 val color = Color(0xFF0000FF.toInt())
Haoyu Zhang437d9452019-01-04 17:34:04 -0800427 val textStyle = TextStyle(background = color)
Haoyu Zhang0c4fd022019-01-02 13:53:10 -0800428
429 val paragraph = simpleParagraph(
430 text = text,
431 textStyles = listOf(ParagraphBuilder.TextStyleIndex(textStyle, 0, text.length))
432 )
George Mountb1cdd862018-12-21 10:54:42 -0800433 paragraph.layout(100.0f)
Haoyu Zhang0c4fd022019-01-02 13:53:10 -0800434
435 assertThat(paragraph.underlyingText.toString(), equalTo(text))
436 assertThat(paragraph.underlyingText,
437 hasSpan(BackgroundColorSpan::class, 0, text.length) { span ->
438 span.backgroundColor == color.value
439 }
440 )
441 }
442
443 @Test
444 fun textStyle_setBackgroundOnPartText() {
445 val text = "abcde"
446 val color = Color(0xFF0000FF.toInt())
Haoyu Zhang437d9452019-01-04 17:34:04 -0800447 val textStyle = TextStyle(background = color)
Haoyu Zhang0c4fd022019-01-02 13:53:10 -0800448
449 val paragraph = simpleParagraph(
450 text = text,
451 textStyles = listOf(ParagraphBuilder.TextStyleIndex(textStyle, 0, "abc".length))
452 )
George Mountb1cdd862018-12-21 10:54:42 -0800453 paragraph.layout(100.0f)
Haoyu Zhang0c4fd022019-01-02 13:53:10 -0800454
455 assertThat(paragraph.underlyingText.toString(), equalTo(text))
456 assertThat(paragraph.underlyingText,
457 hasSpan(BackgroundColorSpan::class, 0, "abc".length) { span ->
458 span.backgroundColor == color.value
459 }
460 )
461 }
462
463 @Test
464 fun textStyle_setBackgroundTwice_lastOneOverwrite() {
465 val text = "abcde"
466 val color = Color(0xFF0000FF.toInt())
Haoyu Zhang437d9452019-01-04 17:34:04 -0800467 val textStyle = TextStyle(background = color)
Haoyu Zhang0c4fd022019-01-02 13:53:10 -0800468 val colorOverwrite = Color(0xFF00FF00.toInt())
Haoyu Zhang437d9452019-01-04 17:34:04 -0800469 val textStyleOverwrite = TextStyle(background = colorOverwrite)
Haoyu Zhang0c4fd022019-01-02 13:53:10 -0800470
471 val paragraph = simpleParagraph(
472 text = text,
473 textStyles = listOf(
474 ParagraphBuilder.TextStyleIndex(textStyle, 0, text.length),
475 ParagraphBuilder.TextStyleIndex(textStyleOverwrite, 0, "abc".length)
476 )
477 )
George Mountb1cdd862018-12-21 10:54:42 -0800478 paragraph.layout(100.0f)
Haoyu Zhang0c4fd022019-01-02 13:53:10 -0800479
480 assertThat(paragraph.underlyingText.toString(), equalTo(text))
481 assertThat(paragraph.underlyingText,
482 hasSpan(BackgroundColorSpan::class, 0, text.length) { span ->
483 span.backgroundColor == color.value
484 }
485 )
486 assertThat(paragraph.underlyingText,
487 hasSpan(BackgroundColorSpan::class, 0, "abc".length) { span ->
488 span.backgroundColor == colorOverwrite.value
489 }
490 )
491 assertThat(
492 paragraph.underlyingText,
493 hasSpanOnTop(BackgroundColorSpan::class, 0, "abc".length) { span ->
494 span.backgroundColor == colorOverwrite.value
495 }
496 )
497 }
498
499 @Test
Haoyu Zhang4b201d22018-12-18 14:27:38 -0800500 fun textStyle_setLocaleOnWholeText() {
501 val text = "abcde"
502 val locale = Locale("en", "US")
503 val textStyle = TextStyle(locale = locale)
504
505 val paragraph = simpleParagraph(
506 text = text,
507 textStyles = listOf(ParagraphBuilder.TextStyleIndex(textStyle, 0, text.length))
508 )
George Mountb1cdd862018-12-21 10:54:42 -0800509 paragraph.layout(100.0f)
Haoyu Zhang4b201d22018-12-18 14:27:38 -0800510
511 assertThat(paragraph.underlyingText, hasSpan(LocaleSpan::class, 0, text.length))
512 }
513
514 @Test
515 fun textStyle_setLocaleOnPartText() {
516 val text = "abcde"
517 val locale = Locale("en", "US")
518 val textStyle = TextStyle(locale = locale)
519
520 val paragraph = simpleParagraph(
521 text = text,
522 textStyles = listOf(ParagraphBuilder.TextStyleIndex(textStyle, 0, "abc".length))
523 )
George Mountb1cdd862018-12-21 10:54:42 -0800524 paragraph.layout(100.0f)
Haoyu Zhang4b201d22018-12-18 14:27:38 -0800525
526 assertThat(paragraph.underlyingText, hasSpan(LocaleSpan::class, 0, "abc".length))
527 }
528
529 @Test
530 fun textStyle_setLocaleTwice_lastOneOverwrite() {
531 val text = "abcde"
532 val textStyle = TextStyle(locale = Locale("en", "US"))
533 val textStyleOverwrite = TextStyle(locale = Locale("ja", "JP"))
534
535 val paragraph = simpleParagraph(
536 text = text,
537 textStyles = listOf(
538 ParagraphBuilder.TextStyleIndex(textStyle, 0, text.length),
539 ParagraphBuilder.TextStyleIndex(textStyleOverwrite, 0, "abc".length)
540 )
541 )
George Mountb1cdd862018-12-21 10:54:42 -0800542 paragraph.layout(100.0f)
Haoyu Zhang4b201d22018-12-18 14:27:38 -0800543
544 assertThat(paragraph.underlyingText, hasSpan(LocaleSpan::class, 0, text.length))
545 assertThat(paragraph.underlyingText, hasSpan(LocaleSpan::class, 0, "abc".length))
546 assertThat(
547 paragraph.underlyingText,
548 hasSpanOnTop(LocaleSpan::class, 0, "abc".length)
549 )
550 }
551
552 @Test
Siyamed Sinir70f336a2018-12-27 10:37:09 -0800553 fun textStyle_fontFamily_addsTypefaceSpanWithCorrectTypeface() {
554 val text = "abcde"
555 val textStyle = TextStyle(
556 fontFamily = fontFamily,
557 fontStyle = FontStyle.italic,
558 fontWeight = FontWeight.bold
559 )
560 val expectedTypeface = TypefaceAdapter().create(
561 fontFamily = fontFamily,
562 fontStyle = FontStyle.italic,
563 fontWeight = FontWeight.bold
564 )
Siyamed Sinir37298412018-12-27 19:47:15 -0800565 val expectedStart = 0
566 val expectedEnd = "abc".length
Siyamed Sinir70f336a2018-12-27 10:37:09 -0800567
568 val paragraph = simpleParagraph(
569 text = text,
Siyamed Sinir37298412018-12-27 19:47:15 -0800570 textStyles = listOf(
571 ParagraphBuilder.TextStyleIndex(
572 textStyle,
573 expectedStart,
574 expectedEnd
575 )
576 )
Siyamed Sinir70f336a2018-12-27 10:37:09 -0800577 )
George Mountb1cdd862018-12-21 10:54:42 -0800578 paragraph.layout(100.0f)
Siyamed Sinir70f336a2018-12-27 10:37:09 -0800579
580 assertThat(paragraph.underlyingText.toString(), equalTo(text))
581 assertThat(
582 paragraph.underlyingText,
Siyamed Sinir37298412018-12-27 19:47:15 -0800583 hasSpan(TypefaceSpan::class, expectedStart, expectedEnd) { span ->
Siyamed Sinir70f336a2018-12-27 10:37:09 -0800584 span.typeface == expectedTypeface
Siyamed Sinir37298412018-12-27 19:47:15 -0800585 })
586 }
587
588 @Test
589 fun textStyle_fontFamily_whenFontSynthesizeTurnedOff() {
590 val text = "abcde"
591 val textStyle = TextStyle(
592 fontFamily = fontFamily,
593 fontStyle = FontStyle.italic,
594 fontWeight = FontWeight.bold,
595 fontSynthesis = FontSynthesis.none
Siyamed Sinir70f336a2018-12-27 10:37:09 -0800596 )
Siyamed Sinir37298412018-12-27 19:47:15 -0800597 val expectedTypeface = TypefaceAdapter().create(
598 fontFamily = fontFamily,
599 fontStyle = FontStyle.italic,
600 fontWeight = FontWeight.bold,
601 fontSynthesis = FontSynthesis.none
602 )
603 val expectedStart = 0
604 val expectedEnd = "abc".length
605
606 val paragraph = simpleParagraph(
607 text = text,
608 textStyles = listOf(
609 ParagraphBuilder.TextStyleIndex(
610 textStyle,
611 expectedStart,
612 expectedEnd
613 )
614 )
615 )
George Mountb1cdd862018-12-21 10:54:42 -0800616 paragraph.layout(100.0f)
Siyamed Sinir37298412018-12-27 19:47:15 -0800617
618 assertThat(paragraph.underlyingText.toString(), equalTo(text))
619 assertThat(
620 paragraph.underlyingText,
621 hasSpan(TypefaceSpan::class, expectedStart, expectedEnd) { span ->
622 span.typeface == expectedTypeface
623 })
Siyamed Sinir70f336a2018-12-27 10:37:09 -0800624 }
625
626 @Test
Siyamed Sinirf18dcca2018-12-20 18:25:10 -0800627 fun testEmptyFontFamily() {
628 val typefaceAdapter = mock<TypefaceAdapter>()
629 val paragraph = simpleParagraph(
630 text = "abc",
631 typefaceAdapter = typefaceAdapter
632 )
George Mountb1cdd862018-12-21 10:54:42 -0800633 paragraph.layout(Float.MAX_VALUE)
Siyamed Sinirf18dcca2018-12-20 18:25:10 -0800634
635 verify(typefaceAdapter, never()).create(
636 fontFamily = any(),
637 fontWeight = any(),
Siyamed Sinir21796012018-12-26 13:51:17 -0800638 fontStyle = any(),
639 fontSynthesis = any()
Siyamed Sinirf18dcca2018-12-20 18:25:10 -0800640 )
641 assertThat(paragraph.textPaint.typeface, nullValue())
642 }
643
644 @Test
645 fun testEmptyFontFamily_withBoldFontWeightSelection() {
646 val typefaceAdapter = spy(TypefaceAdapter())
647
648 val paragraph = simpleParagraph(
649 text = "abc",
650 fontFamily = null,
651 fontWeight = FontWeight.bold,
652 typefaceAdapter = typefaceAdapter
653 )
George Mountb1cdd862018-12-21 10:54:42 -0800654 paragraph.layout(Float.MAX_VALUE)
Siyamed Sinirf18dcca2018-12-20 18:25:10 -0800655
656 verify(typefaceAdapter, times(1)).create(
657 fontFamily = eq(null),
658 fontWeight = eq(FontWeight.bold),
Siyamed Sinir21796012018-12-26 13:51:17 -0800659 fontStyle = eq(FontStyle.normal),
660 fontSynthesis = eq(FontSynthesis.all)
Siyamed Sinirf18dcca2018-12-20 18:25:10 -0800661 )
662
663 val typeface = paragraph.textPaint.typeface
664 assertThat(typeface, not(nullValue()))
665 assertThat(typeface.isBold, equalTo(true))
666 assertThat(typeface.isItalic, equalTo(false))
667 }
668
669 @Test
670 fun testEmptyFontFamily_withFontStyleSelection() {
671 val typefaceAdapter = spy(TypefaceAdapter())
672 val paragraph = simpleParagraph(
673 text = "abc",
674 fontFamily = null,
675 fontStyle = FontStyle.italic,
676 typefaceAdapter = typefaceAdapter
677 )
George Mountb1cdd862018-12-21 10:54:42 -0800678 paragraph.layout(Float.MAX_VALUE)
Siyamed Sinirf18dcca2018-12-20 18:25:10 -0800679
680 verify(typefaceAdapter, times(1)).create(
681 fontFamily = eq(null),
682 fontWeight = eq(FontWeight.normal),
Siyamed Sinir21796012018-12-26 13:51:17 -0800683 fontStyle = eq(FontStyle.italic),
684 fontSynthesis = eq(FontSynthesis.all)
Siyamed Sinirf18dcca2018-12-20 18:25:10 -0800685 )
686
687 val typeface = paragraph.textPaint.typeface
688 assertThat(typeface, not(nullValue()))
689 assertThat(typeface.isBold, equalTo(false))
690 assertThat(typeface.isItalic, equalTo(true))
691 }
692
693 @Test
694 fun testFontFamily_withGenericFamilyName() {
695 val typefaceAdapter = spy(TypefaceAdapter())
696 val fontFamily = FontFamily("sans-serif")
697
698 val paragraph = simpleParagraph(
699 text = "abc",
700 fontFamily = fontFamily,
701 typefaceAdapter = typefaceAdapter
702 )
George Mountb1cdd862018-12-21 10:54:42 -0800703 paragraph.layout(Float.MAX_VALUE)
Siyamed Sinirf18dcca2018-12-20 18:25:10 -0800704
705 verify(typefaceAdapter, times(1)).create(
706 fontFamily = eq(fontFamily),
707 fontWeight = eq(FontWeight.normal),
Siyamed Sinir21796012018-12-26 13:51:17 -0800708 fontStyle = eq(FontStyle.normal),
709 fontSynthesis = eq(FontSynthesis.all)
Siyamed Sinirf18dcca2018-12-20 18:25:10 -0800710 )
711
712 val typeface = paragraph.textPaint.typeface
713 assertThat(typeface, not(nullValue()))
714 assertThat(typeface.isBold, equalTo(false))
715 assertThat(typeface.isItalic, equalTo(false))
716 }
717
718 @Test
719 fun testFontFamily_withCustomFont() {
720 val typefaceAdapter = spy(TypefaceAdapter())
721 val paragraph = simpleParagraph(
722 text = "abc",
723 fontFamily = fontFamily,
724 typefaceAdapter = typefaceAdapter
725 )
George Mountb1cdd862018-12-21 10:54:42 -0800726 paragraph.layout(Float.MAX_VALUE)
Siyamed Sinirf18dcca2018-12-20 18:25:10 -0800727
728 verify(typefaceAdapter, times(1)).create(
729 fontFamily = eq(fontFamily),
730 fontWeight = eq(FontWeight.normal),
Siyamed Sinir21796012018-12-26 13:51:17 -0800731 fontStyle = eq(FontStyle.normal),
732 fontSynthesis = eq(FontSynthesis.all)
Siyamed Sinirf18dcca2018-12-20 18:25:10 -0800733 )
734 val typeface = paragraph.textPaint.typeface
735 assertThat(typeface.isBold, equalTo(false))
736 assertThat(typeface.isItalic, equalTo(false))
737 }
738
Haoyu Zhang10fc6502018-11-09 15:50:11 -0800739 private fun simpleParagraph(
740 text: CharSequence = "",
Haoyu Zhang47f57a22018-12-12 13:16:40 -0800741 textStyles: List<ParagraphBuilder.TextStyleIndex> = listOf(),
Haoyu Zhang10fc6502018-11-09 15:50:11 -0800742 textAlign: TextAlign? = null,
George Mountb1cdd862018-12-21 10:54:42 -0800743 fontSize: Float? = null,
Siyamed Sinirf18dcca2018-12-20 18:25:10 -0800744 maxLines: Int? = null,
745 fontFamily: FontFamily? = null,
746 fontWeight: FontWeight? = null,
747 fontStyle: FontStyle? = null,
748 typefaceAdapter: TypefaceAdapter = TypefaceAdapter()
Haoyu Zhang10fc6502018-11-09 15:50:11 -0800749 ): ParagraphAndroid {
750 return ParagraphAndroid(
751 text = StringBuilder(text),
Haoyu Zhang47f57a22018-12-12 13:16:40 -0800752 textStyles = textStyles,
Siyamed Sinirf18dcca2018-12-20 18:25:10 -0800753 typefaceAdapter = typefaceAdapter,
Haoyu Zhang10fc6502018-11-09 15:50:11 -0800754 paragraphStyle = ParagraphStyle(
755 textAlign = textAlign,
756 maxLines = maxLines,
Siyamed Sinirf18dcca2018-12-20 18:25:10 -0800757 fontFamily = fontFamily,
758 fontSize = fontSize,
759 fontWeight = fontWeight,
760 fontStyle = fontStyle
Haoyu Zhang10fc6502018-11-09 15:50:11 -0800761 )
762 )
763 }
George Mountb1cdd862018-12-21 10:54:42 -0800764}