[go: nahoru, domu]

blob: 901311576f1826d3cee78a51c81029580d4a3e0c [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.ui.text
import android.content.Context
import android.util.TypedValue
import androidx.benchmark.junit4.BenchmarkRule
import androidx.benchmark.junit4.measureRepeated
import androidx.test.filters.LargeTest
import androidx.test.platform.app.InstrumentationRegistry
import androidx.ui.unit.Density
import androidx.ui.unit.sp
import androidx.ui.graphics.Canvas
import androidx.ui.graphics.ImageAsset
import androidx.ui.integration.test.Alphabet
import androidx.ui.integration.test.RandomTextGenerator
import androidx.ui.integration.test.TextBenchmarkTestRule
import androidx.ui.integration.test.TextType
import androidx.ui.integration.test.cartesian
import androidx.ui.text.font.Font
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.Parameterized
import kotlin.math.roundToInt
@LargeTest
@RunWith(Parameterized::class)
class ParagraphBenchmark(
private val textLength: Int,
private val textType: TextType,
alphabet: Alphabet
) {
companion object {
@JvmStatic
@Parameterized.Parameters(name = "length={0} type={1} alphabet={2}")
fun initParameters(): List<Array<Any>> = cartesian(
arrayOf(32, 512),
arrayOf(TextType.PlainText, TextType.StyledText),
arrayOf(Alphabet.Latin, Alphabet.Cjk)
)
}
@get:Rule
val benchmarkRule = BenchmarkRule()
@get:Rule
val textBenchmarkRule = TextBenchmarkTestRule(alphabet)
private lateinit var instrumentationContext: Context
// Width initialized in setup().
private var width: Float = 0f
private val fontSize = textBenchmarkRule.fontSizeSp.sp
@Before
fun setup() {
instrumentationContext = InstrumentationRegistry.getInstrumentation().context
width = TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP,
textBenchmarkRule.widthDp,
instrumentationContext.resources.displayMetrics
)
}
// dummy object required to construct Paragraph
private val resourceLoader = object : Font.ResourceLoader {
override fun load(font: Font): Any {
return false
}
}
private fun text(textGenerator: RandomTextGenerator): AnnotatedString {
val text = textGenerator.nextParagraph(textLength)
val spanStyles = if (textType == TextType.StyledText) {
textGenerator.createStyles(text)
} else {
listOf()
}
return AnnotatedString(text = text, spanStyles = spanStyles)
}
private fun paragraph(
text: String,
spanStyles: List<AnnotatedString.Range<SpanStyle>>,
constraints: ParagraphConstraints
): Paragraph {
return Paragraph(
paragraphIntrinsics = paragraphIntrinsics(text, spanStyles),
constraints = constraints
)
}
private fun paragraphIntrinsics(
textGenerator: RandomTextGenerator
): ParagraphIntrinsics {
val annotatedString = text(textGenerator)
return paragraphIntrinsics(
text = annotatedString.text,
spanStyles = annotatedString.spanStyles
)
}
private fun paragraphIntrinsics(
text: String,
spanStyles: List<AnnotatedString.Range<SpanStyle>>
): ParagraphIntrinsics {
return ParagraphIntrinsics(
text = text,
density = Density(density = instrumentationContext.resources.displayMetrics.density),
style = TextStyle(fontSize = fontSize),
resourceLoader = resourceLoader,
spanStyles = spanStyles
)
}
@Test
fun minIntrinsicWidth() {
textBenchmarkRule.generator { textGenerator ->
benchmarkRule.measureRepeated {
val intrinsics = runWithTimingDisabled {
paragraphIntrinsics(textGenerator)
}
intrinsics.minIntrinsicWidth
}
}
}
@Test
fun maxIntrinsicWidth() {
textBenchmarkRule.generator { textGenerator ->
benchmarkRule.measureRepeated {
val intrinsics = runWithTimingDisabled {
paragraphIntrinsics(textGenerator)
}
intrinsics.maxIntrinsicWidth
}
}
}
@Test
fun construct() {
textBenchmarkRule.generator { textGenerator ->
benchmarkRule.measureRepeated {
val annotatedString = runWithTimingDisabled {
// create a new paragraph and use a smaller width to get
// some line breaking in the result
text(textGenerator)
}
paragraph(
text = annotatedString.text,
spanStyles = annotatedString.spanStyles,
constraints = ParagraphConstraints(width)
)
}
}
}
/**
* The time taken to paint the [Paragraph] on [Canvas] for the first time.
*/
@Test
fun first_paint() {
textBenchmarkRule.generator { textGenerator ->
benchmarkRule.measureRepeated {
val (paragraph, canvas) = runWithTimingDisabled {
val (text, style) = text(textGenerator)
val paragraph = paragraph(text, style, ParagraphConstraints(width))
val canvas = Canvas(
ImageAsset(paragraph.width.roundToInt(), paragraph.height.roundToInt())
)
Pair(paragraph, canvas)
}
paragraph.paint(canvas)
}
}
}
/**
* The time taken to repaint the [Paragraph] on [Canvas].
*/
@Test
fun paint() {
textBenchmarkRule.generator { textGenerator ->
val (text, style) = text(textGenerator)
// create a new paragraph and use a smaller width to get
// some line breaking in the result
val paragraph = paragraph(text, style, ParagraphConstraints(width))
val canvas = Canvas(
ImageAsset(paragraph.width.roundToInt(), paragraph.height.roundToInt())
)
// Paint for the first time, so that we only benchmark repaint.
paragraph.paint(canvas)
benchmarkRule.measureRepeated {
paragraph.paint(canvas)
}
}
}
}