[go: nahoru, domu]

blob: 48e6d90276b2c7534ea475649407857313f1a67e [file] [log] [blame]
/*
* Copyright 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package androidx.compose.ui.text
import android.graphics.Bitmap
import androidx.test.filters.SmallTest
import androidx.test.platform.app.InstrumentationRegistry
import androidx.ui.core.Constraints
import androidx.ui.core.LayoutDirection
import androidx.ui.geometry.Rect
import androidx.ui.graphics.Canvas
import androidx.ui.graphics.Color
import androidx.ui.graphics.Paint
import androidx.compose.ui.text.FontTestData.Companion.BASIC_MEASURE_FONT
import androidx.compose.ui.text.font.asFontFamily
import androidx.compose.ui.text.matchers.assertThat
import androidx.ui.unit.Density
import androidx.ui.unit.sp
import com.google.common.truth.Truth.assertThat
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
@OptIn(InternalTextApi::class)
@RunWith(JUnit4::class)
@SmallTest
class TextDelegateIntegrationTest {
private val fontFamily = BASIC_MEASURE_FONT.asFontFamily()
private val density = Density(density = 1f)
private val context = InstrumentationRegistry.getInstrumentation().context
private val resourceLoader = TestFontResourceLoader(context)
@Test
fun minIntrinsicWidth_getter() {
with(density) {
val fontSize = 20.sp
val text = "Hello"
val spanStyle = SpanStyle(fontSize = fontSize, fontFamily = fontFamily)
val annotatedString = AnnotatedString(text, spanStyle)
val textDelegate = TextDelegate(
text = annotatedString,
style = TextStyle.Default,
density = this,
resourceLoader = resourceLoader
)
textDelegate.layoutIntrinsics(LayoutDirection.Ltr)
assertThat(textDelegate.minIntrinsicWidth)
.isEqualTo((fontSize.toPx() * text.length).toIntPx())
}
}
@Test
fun maxIntrinsicWidth_getter() {
with(density) {
val fontSize = 20.sp
val text = "Hello"
val spanStyle = SpanStyle(fontSize = fontSize, fontFamily = fontFamily)
val annotatedString = AnnotatedString(text, spanStyle)
val textDelegate = TextDelegate(
text = annotatedString,
style = TextStyle.Default,
density = this,
resourceLoader = resourceLoader
)
textDelegate.layoutIntrinsics(LayoutDirection.Ltr)
assertThat(textDelegate.maxIntrinsicWidth)
.isEqualTo((fontSize.toPx() * text.length).toIntPx())
}
}
@Test
fun testBackgroundPaint_paint_wrap_multiLines() {
with(density) {
// Setup test.
val fontSize = 20.sp
val fontSizeInPx = fontSize.toPx()
val text = "HelloHello"
val spanStyle = SpanStyle(fontSize = fontSize, fontFamily = fontFamily)
val annotatedString = AnnotatedString(text, spanStyle)
val textDelegate = TextDelegate(
text = annotatedString,
style = TextStyle.Default,
density = this,
resourceLoader = resourceLoader
)
val layoutResult = textDelegate.layout(
Constraints(maxWidth = 120),
LayoutDirection.Ltr
)
val expectedBitmap = layoutResult.toBitmap()
val expectedCanvas = Canvas(android.graphics.Canvas(expectedBitmap))
val expectedPaint = Paint()
val defaultSelectionColor = Color(0x6633B5E5)
val selectionPaint = Paint().also { it.color = defaultSelectionColor }
expectedPaint.color = defaultSelectionColor
val firstLineLeft = layoutResult.multiParagraph.getLineLeft(0)
val secondLineLeft = layoutResult.multiParagraph.getLineLeft(1)
val firstLineRight = layoutResult.multiParagraph.getLineRight(0)
val secondLineRight = layoutResult.multiParagraph.getLineRight(1)
expectedCanvas.drawRect(
Rect(firstLineLeft, 0f, firstLineRight, fontSizeInPx),
expectedPaint
)
expectedCanvas.drawRect(
Rect(
secondLineLeft,
fontSizeInPx,
secondLineRight,
layoutResult.multiParagraph.height
),
expectedPaint
)
val actualBitmap = layoutResult.toBitmap()
val actualCanvas = Canvas(android.graphics.Canvas(actualBitmap))
// Run.
// Select all.
TextDelegate.paintBackground(
start = 0,
end = text.length,
paint = selectionPaint,
canvas = actualCanvas,
textLayoutResult = layoutResult
)
// Assert.
assertThat(actualBitmap).isEqualToBitmap(expectedBitmap)
}
}
@Test
fun testBackgroundPaint_paint_with_default_color() {
with(density) {
// Setup test.
val selectionStart = 0
val selectionEnd = 3
val fontSize = 20.sp
val fontSizeInPx = fontSize.toPx()
val text = "Hello"
val spanStyle = SpanStyle(fontSize = fontSize, fontFamily = fontFamily)
val annotatedString = AnnotatedString(text, spanStyle)
val textDelegate = TextDelegate(
text = annotatedString,
style = TextStyle.Default,
density = this,
resourceLoader = resourceLoader
)
val layoutResult = textDelegate.layout(Constraints(), LayoutDirection.Ltr)
val expectedBitmap = layoutResult.toBitmap()
val expectedCanvas = Canvas(android.graphics.Canvas(expectedBitmap))
val expectedPaint = Paint()
val defaultSelectionColor = Color(0x6633B5E5)
val selectionPaint = Paint().also { it.color = defaultSelectionColor }
expectedPaint.color = defaultSelectionColor
expectedCanvas.drawRect(
Rect(
left = 0f,
top = 0f,
right = fontSizeInPx * (selectionEnd - selectionStart),
bottom = fontSizeInPx
),
expectedPaint
)
val actualBitmap = layoutResult.toBitmap()
val actualCanvas = Canvas(android.graphics.Canvas(actualBitmap))
// Run.
TextDelegate.paintBackground(
start = selectionStart,
end = selectionEnd,
paint = selectionPaint,
canvas = actualCanvas,
textLayoutResult = layoutResult
)
// Assert
assertThat(actualBitmap).isEqualToBitmap(expectedBitmap)
}
}
@Test
fun testBackgroundPaint_paint_with_default_color_bidi() {
with(density) {
// Setup test.
val textLTR = "Hello"
// From right to left: שלום
val textRTL = "\u05e9\u05dc\u05d5\u05dd"
val text = textLTR + textRTL
val selectionLTRStart = 2
val selectionRTLEnd = 2
val fontSize = 20.sp
val fontSizeInPx = fontSize.toPx()
val spanStyle = SpanStyle(fontSize = fontSize, fontFamily = fontFamily)
val annotatedString = AnnotatedString(text, spanStyle)
val textDelegate = TextDelegate(
text = annotatedString,
style = TextStyle.Default,
density = this,
resourceLoader = resourceLoader
)
val layoutResult = textDelegate.layout(Constraints(), LayoutDirection.Ltr)
val expectedBitmap = layoutResult.toBitmap()
val expectedCanvas = Canvas(android.graphics.Canvas(expectedBitmap))
val expectedPaint = Paint()
val defaultSelectionColor = Color(0x6633B5E5)
val selectionPaint = Paint().also { it.color = defaultSelectionColor }
expectedPaint.color = defaultSelectionColor
// Select "llo".
expectedCanvas.drawRect(
Rect(
left = fontSizeInPx * selectionLTRStart,
top = 0f,
right = textLTR.length * fontSizeInPx,
bottom = fontSizeInPx
),
expectedPaint
)
// Select "של"
expectedCanvas.drawRect(
Rect(
left = (textLTR.length + textRTL.length - selectionRTLEnd) * fontSizeInPx,
top = 0f,
right = (textLTR.length + textRTL.length) * fontSizeInPx,
bottom = fontSizeInPx
),
expectedPaint
)
val actualBitmap = layoutResult.toBitmap()
val actualCanvas = Canvas(android.graphics.Canvas(actualBitmap))
// Run.
TextDelegate.paintBackground(
start = selectionLTRStart,
end = textLTR.length + selectionRTLEnd,
paint = selectionPaint,
canvas = actualCanvas,
textLayoutResult = layoutResult
)
// Assert
assertThat(actualBitmap).isEqualToBitmap(expectedBitmap)
}
}
@Test
fun testBackgroundPaint_paint_with_customized_color() {
with(density) {
// Setup test.
val selectionStart = 0
val selectionEnd = 3
val fontSize = 20.sp
val fontSizeInPx = fontSize.toPx()
val text = "Hello"
val spanStyle = SpanStyle(fontSize = fontSize, fontFamily = fontFamily)
val annotatedString = AnnotatedString(text, spanStyle)
val selectionColor = Color(0x66AABB33)
val selectionPaint = Paint().also { it.color = selectionColor }
val textDelegate = TextDelegate(
text = annotatedString,
style = TextStyle.Default,
density = this,
resourceLoader = resourceLoader
)
val layoutResult = textDelegate.layout(Constraints(), LayoutDirection.Ltr)
val expectedBitmap = layoutResult.toBitmap()
val expectedCanvas = Canvas(android.graphics.Canvas(expectedBitmap))
val expectedPaint = Paint()
expectedPaint.color = selectionColor
expectedCanvas.drawRect(
Rect(
left = 0f,
top = 0f,
right = fontSizeInPx * (selectionEnd - selectionStart),
bottom = fontSizeInPx
),
expectedPaint
)
val actualBitmap = layoutResult.toBitmap()
val actualCanvas = Canvas(android.graphics.Canvas(actualBitmap))
// Run.
TextDelegate.paintBackground(
start = selectionStart,
end = selectionEnd,
paint = selectionPaint,
canvas = actualCanvas,
textLayoutResult = layoutResult
)
// Assert
assertThat(actualBitmap).isEqualToBitmap(expectedBitmap)
}
}
@Test
fun multiParagraphIntrinsics_isReused() {
val textDelegate = TextDelegate(
text = AnnotatedString(text = "abc"),
style = TextStyle.Default,
density = density,
resourceLoader = resourceLoader
)
// create the intrinsics object
textDelegate.layoutIntrinsics(LayoutDirection.Ltr)
val multiParagraphIntrinsics = textDelegate.paragraphIntrinsics
// layout should create the MultiParagraph. The final MultiParagraph is expected to use
// the previously calculated intrinsics
val layoutResult = textDelegate.layout(Constraints(), LayoutDirection.Ltr)
val layoutIntrinsics = layoutResult.multiParagraph.intrinsics
// primary assertions to make sure that the objects are not null
assertThat(layoutIntrinsics.infoList.get(0)).isNotNull()
assertThat(multiParagraphIntrinsics?.infoList?.get(0)).isNotNull()
// the intrinsics passed to multi paragraph should be the same instance
assertThat(layoutIntrinsics).isSameInstanceAs(multiParagraphIntrinsics)
// the ParagraphIntrinsic in the MultiParagraphIntrinsic should be the same instance
assertThat(layoutIntrinsics.infoList.get(0))
.isSameInstanceAs(multiParagraphIntrinsics?.infoList?.get(0))
}
@Test
fun TextLayoutInput_reLayout_withDifferentHeight() {
val textDelegate = TextDelegate(
text = AnnotatedString(text = "Hello World!"),
style = TextStyle.Default,
density = density,
resourceLoader = resourceLoader
)
val width = 200
val heightFirstLayout = 100
val heightSecondLayout = 200
val constraintsFirstLayout = Constraints.fixed(width, heightFirstLayout)
val resultFirstLayout = textDelegate.layout(constraintsFirstLayout, LayoutDirection.Ltr)
assertThat(resultFirstLayout.layoutInput.constraints).isEqualTo(constraintsFirstLayout)
val constraintsSecondLayout = Constraints.fixed(width, heightSecondLayout)
val resultSecondLayout = textDelegate.layout(
constraintsSecondLayout,
LayoutDirection.Ltr,
resultFirstLayout
)
assertThat(resultSecondLayout.layoutInput.constraints).isEqualTo(constraintsSecondLayout)
}
@Test
fun TextLayoutResult_reLayout_withDifferentHeight() {
val textDelegate = TextDelegate(
text = AnnotatedString(text = "Hello World!"),
style = TextStyle.Default,
density = density,
resourceLoader = resourceLoader
)
val width = 200
val heightFirstLayout = 100
val heightSecondLayout = 200
val constraintsFirstLayout = Constraints.fixed(width, heightFirstLayout)
val resultFirstLayout = textDelegate.layout(constraintsFirstLayout, LayoutDirection.Ltr)
assertThat(resultFirstLayout.size.height).isEqualTo(heightFirstLayout)
val constraintsSecondLayout = Constraints.fixed(width, heightSecondLayout)
val resultSecondLayout = textDelegate.layout(
constraintsSecondLayout,
LayoutDirection.Ltr,
resultFirstLayout
)
assertThat(resultSecondLayout.size.height).isEqualTo(heightSecondLayout)
}
}
private fun TextLayoutResult.toBitmap() = Bitmap.createBitmap(
size.width,
size.height,
Bitmap.Config.ARGB_8888
)