1/*
2 * Copyright (C) 2017 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 */
16package android.text;
17
18import android.graphics.Canvas;
19import android.graphics.Paint;
20import android.perftests.utils.BenchmarkState;
21import android.perftests.utils.PerfStatusReporter;
22import android.support.test.filters.LargeTest;
23import android.view.DisplayListCanvas;
24import android.view.RenderNode;
25
26import org.junit.Rule;
27import org.junit.Test;
28import org.junit.runner.RunWith;
29import org.junit.runners.Parameterized;
30
31import java.util.ArrayList;
32import java.util.Collection;
33import java.util.List;
34import java.util.Random;
35
36/**
37 * Performance test for single line measure and draw using {@link Paint} and {@link Canvas}.
38 */
39@LargeTest
40@RunWith(Parameterized.class)
41public class PaintMeasureDrawPerfTest {
42
43    private static final boolean[] BOOLEANS = new boolean[]{false, true};
44
45    @Parameterized.Parameters(name = "cached={1},{0}chars")
46    public static Collection cases() {
47        final List<Object[]> params = new ArrayList<>();
48        for (int length : new int[]{128}) {
49            for (boolean cached : BOOLEANS) {
50                params.add(new Object[]{length, cached});
51            }
52        }
53        return params;
54    }
55
56    @Rule
57    public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
58
59    private final int mLength;
60    private final boolean mCached;
61    private final TextPaint mTextPaint;
62
63
64    public PaintMeasureDrawPerfTest(int length, boolean cached) {
65        mLength = length;
66        mCached = cached;
67        mTextPaint = new TextPaint();
68        mTextPaint.setTextSize(10);
69    }
70
71    /**
72     * Measure the time for {@link Paint#measureText(String)}
73     */
74    @Test
75    public void timeMeasure() throws Exception {
76        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
77
78        state.pauseTiming();
79        Canvas.freeTextLayoutCaches();
80        final String text = createRandomText();
81        if (mCached) mTextPaint.measureText(text);
82        state.resumeTiming();
83
84        while (state.keepRunning()) {
85            state.pauseTiming();
86            if (!mCached) Canvas.freeTextLayoutCaches();
87            state.resumeTiming();
88
89            mTextPaint.measureText(text);
90        }
91    }
92
93    /**
94     * Measures the time for {@link Canvas#drawText(String, float, float, Paint)}
95     */
96    @Test
97    public void timeDraw() throws Throwable {
98        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
99
100        state.pauseTiming();
101        Canvas.freeTextLayoutCaches();
102        final RenderNode node = RenderNode.create("benchmark", null);
103        final String text = createRandomText();
104        if (mCached) mTextPaint.measureText(text);
105        state.resumeTiming();
106
107        while (state.keepRunning()) {
108
109            state.pauseTiming();
110            final DisplayListCanvas canvas = node.start(1200, 200);
111            final int save = canvas.save();
112            if (!mCached) Canvas.freeTextLayoutCaches();
113            state.resumeTiming();
114
115            canvas.drawText(text, 0 /*x*/, 100 /*y*/, mTextPaint);
116
117            state.pauseTiming();
118            canvas.restoreToCount(save);
119            node.end(canvas);
120            state.resumeTiming();
121        }
122    }
123
124    private String createRandomText() {
125        return (String) new NonEditableTextGenerator(new Random(0))
126                .setSequenceLength(mLength)
127                .setCreateBoring(true)
128                .setTextType(NonEditableTextGenerator.TextType.STRING)
129                .build();
130    }
131}
132