blob: 6b295e55c9d4514a0cf6f0dc5107a4a7522741f3 [file] [log] [blame]
Alan Viverette3da604b2020-06-10 18:34:39 +00001/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 * use this file except in compliance with the License. You may obtain a copy of
6 * the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 * License for the specific language governing permissions and limitations under
14 * the License.
15 */
16
17package android.text;
18
19import static android.text.Layout.Alignment.ALIGN_NORMAL;
20
21import android.graphics.Canvas;
22import android.graphics.Paint;
23import android.graphics.Paint.FontMetricsInt;
24import android.perftests.utils.BenchmarkState;
25import android.perftests.utils.PerfStatusReporter;
26import android.perftests.utils.PerfTestActivity;
27import android.text.style.ReplacementSpan;
28import android.util.ArraySet;
29
30import androidx.test.filters.LargeTest;
31import androidx.test.rule.ActivityTestRule;
32
33import org.junit.Rule;
34import org.junit.Test;
35import org.junit.runner.RunWith;
36import org.junit.runners.Parameterized;
37import org.junit.runners.Parameterized.Parameters;
38
39import java.util.Arrays;
40import java.util.Collection;
41import java.util.Random;
42
43@LargeTest
44@RunWith(Parameterized.class)
45public class DynamicLayoutPerfTest {
46
47 @Parameters(name = "{0}")
48 public static Collection cases() {
49 return Arrays.asList(new Object[][] {
50 { "0%", 0.0f},
51 { "1%", 0.01f},
52 { "5%", 0.05f},
53 { "30%", 0.3f},
54 { "100%", 1.0f},
55 });
56 }
57
58 private final String mMetricKey;
59 private final float mProbability;
60 public DynamicLayoutPerfTest(String metricKey, float probability) {
61 mMetricKey = metricKey;
62 mProbability = probability;
63 }
64
65 private static class MockReplacementSpan extends ReplacementSpan {
66 @Override
67 public int getSize(Paint paint, CharSequence text, int start, int end, FontMetricsInt fm) {
68 return 10;
69 }
70
71 @Override
72 public void draw(Canvas canvas, CharSequence text, int start, int end, float x, int top,
73 int y, int bottom, Paint paint) {
74 }
75 }
76
77 @Rule
78 public ActivityTestRule<PerfTestActivity> mActivityRule =
79 new ActivityTestRule<>(PerfTestActivity.class);
80
81 @Rule
82 public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
83
84
85 private final static String ALPHABETS = "abcdefghijklmnopqrstuvwxyz";
86
87 private SpannableStringBuilder getText() {
88 final long seed = 1234567890;
89 final Random r = new Random(seed);
90 final SpannableStringBuilder builder = new SpannableStringBuilder();
91
92 final int paragraphCount = 100;
93 for (int i = 0; i < paragraphCount; i++) {
94 final int wordCount = 5 + r.nextInt(20);
95 final boolean containsReplacementSpan = r.nextFloat() < mProbability;
96 final int replacedWordIndex = containsReplacementSpan ? r.nextInt(wordCount) : -1;
97 for (int j = 0; j < wordCount; j++) {
98 final int startIndex = builder.length();
99 final int wordLength = 1 + r.nextInt(10);
100 for (int k = 0; k < wordLength; k++) {
101 char c = ALPHABETS.charAt(r.nextInt(ALPHABETS.length()));
102 builder.append(c);
103 }
104 if (replacedWordIndex == j) {
105 builder.setSpan(new MockReplacementSpan(), startIndex,
106 builder.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
107 }
108 builder.append(' ');
109 }
110 builder.append('\n');
111 }
112 return builder;
113 }
114
115 @Test
116 public void testGetBlocksAlwaysNeedToBeRedrawn() {
117 final SpannableStringBuilder text = getText();
118 final DynamicLayout layout = new DynamicLayout(text, new TextPaint(), 1000,
119 ALIGN_NORMAL, 0, 0, false);
120
121 BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
122 final int steps = 10;
123 while (state.keepRunning()) {
124 for (int i = 0; i < steps; i++) {
125 int offset = (text.length() * i) / steps;
126 text.insert(offset, "\n");
127 text.delete(offset, offset + 1);
128 final ArraySet<Integer> set = layout.getBlocksAlwaysNeedToBeRedrawn();
129 if (set != null) {
130 for (int j = 0; j < set.size(); j++) {
131 layout.getBlockIndex(set.valueAt(j));
132 }
133 }
134 }
135 }
136 }
137}