1 /* 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 17 package android.text; 18 19 import static android.text.TextDirectionHeuristics.LTR; 20 21 import android.perftests.utils.BenchmarkState; 22 import android.perftests.utils.PerfStatusReporter; 23 24 import android.support.test.filters.LargeTest; 25 import android.support.test.runner.AndroidJUnit4; 26 27 import android.content.res.ColorStateList; 28 import android.graphics.Canvas; 29 import android.graphics.Typeface; 30 import android.text.Layout; 31 import android.text.style.TextAppearanceSpan; 32 import android.view.DisplayListCanvas; 33 import android.view.RenderNode; 34 35 import org.junit.Before; 36 import org.junit.Rule; 37 import org.junit.Test; 38 import org.junit.runner.RunWith; 39 40 import java.nio.CharBuffer; 41 import java.util.Random; 42 43 @LargeTest 44 @RunWith(AndroidJUnit4.class) 45 public class StaticLayoutPerfTest { 46 private static final int WORD_LENGTH = 9; // Random word has 9 characters. 47 private static final int WORDS_IN_LINE = 8; // Roughly, 8 words in a line. 48 private static final boolean NO_STYLE_TEXT = false; 49 private static final boolean STYLE_TEXT = true; 50 51 private static TextPaint PAINT = new TextPaint(); 52 private static final int TEXT_WIDTH = WORDS_IN_LINE * WORD_LENGTH * (int) PAINT.getTextSize(); 53 54 public StaticLayoutPerfTest() {} 55 56 @Rule 57 public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter(); 58 59 private TextPerfUtils mTextUtil = new TextPerfUtils(); 60 61 @Before 62 public void setUp() { 63 mTextUtil.resetRandom(0 /* seed */); 64 } 65 66 private PrecomputedText makeMeasured(CharSequence text, TextPaint paint) { 67 PrecomputedText.Params param = new PrecomputedText.Params.Builder(paint).build(); 68 return PrecomputedText.create(text, param); 69 } 70 71 private PrecomputedText makeMeasured(CharSequence text, TextPaint paint, int strategy, 72 int frequency) { 73 PrecomputedText.Params param = new PrecomputedText.Params.Builder(paint) 74 .setHyphenationFrequency(frequency).setBreakStrategy(strategy).build(); 75 return PrecomputedText.create(text, param); 76 } 77 78 @Test 79 public void testCreate_FixedText_NoStyle_Greedy_NoHyphenation() { 80 final BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); 81 final CharSequence text = mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT); 82 while (state.keepRunning()) { 83 StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH) 84 .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NONE) 85 .setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE) 86 .build(); 87 } 88 } 89 90 @Test 91 public void testCreate_RandomText_NoStyled_Greedy_NoHyphenation() { 92 final BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); 93 while (state.keepRunning()) { 94 state.pauseTiming(); 95 final CharSequence text = mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT); 96 state.resumeTiming(); 97 98 StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH) 99 .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NONE) 100 .setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE) 101 .build(); 102 } 103 } 104 105 @Test 106 public void testCreate_RandomText_NoStyled_Greedy_Hyphenation() { 107 final BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); 108 while (state.keepRunning()) { 109 state.pauseTiming(); 110 final CharSequence text = mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT); 111 state.resumeTiming(); 112 113 StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH) 114 .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL) 115 .setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE) 116 .build(); 117 } 118 } 119 120 @Test 121 public void testCreate_RandomText_NoStyled_Balanced_NoHyphenation() { 122 final BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); 123 while (state.keepRunning()) { 124 state.pauseTiming(); 125 final CharSequence text = mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT); 126 state.resumeTiming(); 127 128 StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH) 129 .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NONE) 130 .setBreakStrategy(Layout.BREAK_STRATEGY_BALANCED) 131 .build(); 132 } 133 } 134 135 @Test 136 public void testCreate_RandomText_NoStyled_Balanced_Hyphenation() { 137 final BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); 138 while (state.keepRunning()) { 139 state.pauseTiming(); 140 final CharSequence text = mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT); 141 state.resumeTiming(); 142 143 StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH) 144 .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL) 145 .setBreakStrategy(Layout.BREAK_STRATEGY_BALANCED) 146 .build(); 147 } 148 } 149 150 @Test 151 public void testCreate_RandomText_Styled_Greedy_NoHyphenation() { 152 final BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); 153 while (state.keepRunning()) { 154 state.pauseTiming(); 155 final CharSequence text = mTextUtil.nextRandomParagraph(WORD_LENGTH, STYLE_TEXT); 156 state.resumeTiming(); 157 158 StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH) 159 .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NONE) 160 .setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE) 161 .build(); 162 } 163 } 164 165 @Test 166 public void testCreate_PrecomputedText_NoStyled_Greedy_NoHyphenation() { 167 final BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); 168 while (state.keepRunning()) { 169 state.pauseTiming(); 170 final PrecomputedText text = makeMeasured( 171 mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), PAINT, 172 Layout.BREAK_STRATEGY_SIMPLE, Layout.HYPHENATION_FREQUENCY_NONE); 173 state.resumeTiming(); 174 175 StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH) 176 .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NONE) 177 .setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE) 178 .build(); 179 } 180 } 181 182 @Test 183 public void testCreate_PrecomputedText_NoStyled_Greedy_Hyphenation() { 184 final BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); 185 while (state.keepRunning()) { 186 state.pauseTiming(); 187 final PrecomputedText text = makeMeasured( 188 mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), PAINT, 189 Layout.BREAK_STRATEGY_SIMPLE, Layout.HYPHENATION_FREQUENCY_NORMAL); 190 state.resumeTiming(); 191 192 StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH) 193 .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL) 194 .setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE) 195 .build(); 196 } 197 } 198 199 @Test 200 public void testCreate_PrecomputedText_NoStyled_Balanced_NoHyphenation() { 201 final BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); 202 while (state.keepRunning()) { 203 state.pauseTiming(); 204 final PrecomputedText text = makeMeasured( 205 mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), PAINT, 206 Layout.BREAK_STRATEGY_BALANCED, Layout.HYPHENATION_FREQUENCY_NONE); 207 state.resumeTiming(); 208 209 StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH) 210 .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NONE) 211 .setBreakStrategy(Layout.BREAK_STRATEGY_BALANCED) 212 .build(); 213 } 214 } 215 216 @Test 217 public void testCreate_PrecomputedText_NoStyled_Balanced_Hyphenation() { 218 final BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); 219 while (state.keepRunning()) { 220 state.pauseTiming(); 221 final PrecomputedText text = makeMeasured( 222 mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), PAINT, 223 Layout.BREAK_STRATEGY_BALANCED, Layout.HYPHENATION_FREQUENCY_NORMAL); 224 state.resumeTiming(); 225 226 StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH) 227 .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL) 228 .setBreakStrategy(Layout.BREAK_STRATEGY_BALANCED) 229 .build(); 230 } 231 } 232 233 @Test 234 public void testCreate_PrecomputedText_Styled_Greedy_NoHyphenation() { 235 final BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); 236 while (state.keepRunning()) { 237 state.pauseTiming(); 238 final PrecomputedText text = makeMeasured( 239 mTextUtil.nextRandomParagraph(WORD_LENGTH, STYLE_TEXT), PAINT, 240 Layout.BREAK_STRATEGY_SIMPLE, Layout.HYPHENATION_FREQUENCY_NONE); 241 state.resumeTiming(); 242 243 StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH) 244 .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NONE) 245 .setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE) 246 .build(); 247 } 248 } 249 250 @Test 251 public void testDraw_FixedText_NoStyled() { 252 final BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); 253 final CharSequence text = mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT); 254 final RenderNode node = RenderNode.create("benchmark", null); 255 while (state.keepRunning()) { 256 state.pauseTiming(); 257 final StaticLayout layout = 258 StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH).build(); 259 final DisplayListCanvas c = node.start(1200, 200); 260 state.resumeTiming(); 261 262 layout.draw(c); 263 } 264 } 265 266 @Test 267 public void testDraw_RandomText_Styled() { 268 final BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); 269 final RenderNode node = RenderNode.create("benchmark", null); 270 while (state.keepRunning()) { 271 state.pauseTiming(); 272 final CharSequence text = mTextUtil.nextRandomParagraph(WORD_LENGTH, STYLE_TEXT); 273 final StaticLayout layout = 274 StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH).build(); 275 final DisplayListCanvas c = node.start(1200, 200); 276 state.resumeTiming(); 277 278 layout.draw(c); 279 } 280 } 281 282 @Test 283 public void testDraw_RandomText_NoStyled() { 284 final BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); 285 final RenderNode node = RenderNode.create("benchmark", null); 286 while (state.keepRunning()) { 287 state.pauseTiming(); 288 final CharSequence text = mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT); 289 final StaticLayout layout = 290 StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH).build(); 291 final DisplayListCanvas c = node.start(1200, 200); 292 state.resumeTiming(); 293 294 layout.draw(c); 295 } 296 } 297 298 @Test 299 public void testDraw_RandomText_Styled_WithoutCache() { 300 final BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); 301 final RenderNode node = RenderNode.create("benchmark", null); 302 while (state.keepRunning()) { 303 state.pauseTiming(); 304 final CharSequence text = mTextUtil.nextRandomParagraph(WORD_LENGTH, STYLE_TEXT); 305 final StaticLayout layout = 306 StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH).build(); 307 final DisplayListCanvas c = node.start(1200, 200); 308 Canvas.freeTextLayoutCaches(); 309 state.resumeTiming(); 310 311 layout.draw(c); 312 } 313 } 314 315 @Test 316 public void testDraw_RandomText_NoStyled_WithoutCache() { 317 final BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); 318 final RenderNode node = RenderNode.create("benchmark", null); 319 while (state.keepRunning()) { 320 state.pauseTiming(); 321 final CharSequence text = mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT); 322 final StaticLayout layout = 323 StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH).build(); 324 final DisplayListCanvas c = node.start(1200, 200); 325 Canvas.freeTextLayoutCaches(); 326 state.resumeTiming(); 327 328 layout.draw(c); 329 } 330 } 331 332 @Test 333 public void testDraw_PrecomputedText_Styled() { 334 final BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); 335 final RenderNode node = RenderNode.create("benchmark", null); 336 while (state.keepRunning()) { 337 state.pauseTiming(); 338 final PrecomputedText text = makeMeasured( 339 mTextUtil.nextRandomParagraph(WORD_LENGTH, STYLE_TEXT), PAINT); 340 final StaticLayout layout = 341 StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH).build(); 342 final DisplayListCanvas c = node.start(1200, 200); 343 state.resumeTiming(); 344 345 layout.draw(c); 346 } 347 } 348 349 @Test 350 public void testDraw_PrecomputedText_NoStyled() { 351 final BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); 352 final RenderNode node = RenderNode.create("benchmark", null); 353 while (state.keepRunning()) { 354 state.pauseTiming(); 355 final PrecomputedText text = makeMeasured( 356 mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), PAINT); 357 final StaticLayout layout = 358 StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH).build(); 359 final DisplayListCanvas c = node.start(1200, 200); 360 state.resumeTiming(); 361 362 layout.draw(c); 363 } 364 } 365 366 @Test 367 public void testDraw_PrecomputedText_Styled_WithoutCache() { 368 final BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); 369 final RenderNode node = RenderNode.create("benchmark", null); 370 while (state.keepRunning()) { 371 state.pauseTiming(); 372 final PrecomputedText text = makeMeasured( 373 mTextUtil.nextRandomParagraph(WORD_LENGTH, STYLE_TEXT), PAINT); 374 final StaticLayout layout = 375 StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH).build(); 376 final DisplayListCanvas c = node.start(1200, 200); 377 Canvas.freeTextLayoutCaches(); 378 state.resumeTiming(); 379 380 layout.draw(c); 381 } 382 } 383 384 @Test 385 public void testDraw_PrecomputedText_NoStyled_WithoutCache() { 386 final BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); 387 final RenderNode node = RenderNode.create("benchmark", null); 388 while (state.keepRunning()) { 389 state.pauseTiming(); 390 final PrecomputedText text = makeMeasured( 391 mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), PAINT); 392 final StaticLayout layout = 393 StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH).build(); 394 final DisplayListCanvas c = node.start(1200, 200); 395 Canvas.freeTextLayoutCaches(); 396 state.resumeTiming(); 397 398 layout.draw(c); 399 } 400 } 401 402 } 403