1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright 2011 Google Inc.
3cb93a386Sopenharmony_ci *
4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be
5cb93a386Sopenharmony_ci * found in the LICENSE file.
6cb93a386Sopenharmony_ci */
7cb93a386Sopenharmony_ci#include "bench/Benchmark.h"
8cb93a386Sopenharmony_ci#include "include/core/SkBitmap.h"
9cb93a386Sopenharmony_ci#include "include/core/SkCanvas.h"
10cb93a386Sopenharmony_ci#include "include/core/SkPaint.h"
11cb93a386Sopenharmony_ci#include "include/core/SkPath.h"
12cb93a386Sopenharmony_ci#include "include/core/SkString.h"
13cb93a386Sopenharmony_ci#include "include/core/SkStrokeRec.h"
14cb93a386Sopenharmony_ci#include "include/effects/SkDashPathEffect.h"
15cb93a386Sopenharmony_ci#include "include/private/SkTDArray.h"
16cb93a386Sopenharmony_ci#include "include/utils/SkRandom.h"
17cb93a386Sopenharmony_ci
18cb93a386Sopenharmony_ci
19cb93a386Sopenharmony_ci/*
20cb93a386Sopenharmony_ci *  Cases to consider:
21cb93a386Sopenharmony_ci *
22cb93a386Sopenharmony_ci *  1. antialiasing on/off (esp. width <= 1)
23cb93a386Sopenharmony_ci *  2. strokewidth == 0, 1, 2
24cb93a386Sopenharmony_ci *  3. hline, vline, diagonal, rect, oval
25cb93a386Sopenharmony_ci *  4. dots [1,1] ([N,N] where N=strokeWidth?) or arbitrary (e.g. [2,1] or [1,2,3,2])
26cb93a386Sopenharmony_ci */
27cb93a386Sopenharmony_cistatic void path_hline(SkPath* path) {
28cb93a386Sopenharmony_ci    path->moveTo(SkIntToScalar(10), SkIntToScalar(10));
29cb93a386Sopenharmony_ci    path->lineTo(SkIntToScalar(600), SkIntToScalar(10));
30cb93a386Sopenharmony_ci}
31cb93a386Sopenharmony_ci
32cb93a386Sopenharmony_ciclass DashBench : public Benchmark {
33cb93a386Sopenharmony_ciprotected:
34cb93a386Sopenharmony_ci    SkString            fName;
35cb93a386Sopenharmony_ci    SkTDArray<SkScalar> fIntervals;
36cb93a386Sopenharmony_ci    int                 fWidth;
37cb93a386Sopenharmony_ci    SkPoint             fPts[2];
38cb93a386Sopenharmony_ci    bool                fDoClip;
39cb93a386Sopenharmony_ci
40cb93a386Sopenharmony_cipublic:
41cb93a386Sopenharmony_ci    DashBench(const SkScalar intervals[], int count, int width,
42cb93a386Sopenharmony_ci              bool doClip = false)  {
43cb93a386Sopenharmony_ci        fIntervals.append(count, intervals);
44cb93a386Sopenharmony_ci        for (int i = 0; i < count; ++i) {
45cb93a386Sopenharmony_ci            fIntervals[i] *= width;
46cb93a386Sopenharmony_ci        }
47cb93a386Sopenharmony_ci        fWidth = width;
48cb93a386Sopenharmony_ci        fName.printf("dash_%d_%s", width, doClip ? "clipped" : "noclip");
49cb93a386Sopenharmony_ci        fDoClip = doClip;
50cb93a386Sopenharmony_ci
51cb93a386Sopenharmony_ci        fPts[0].set(SkIntToScalar(10), SkIntToScalar(10));
52cb93a386Sopenharmony_ci        fPts[1].set(SkIntToScalar(600), SkIntToScalar(10));
53cb93a386Sopenharmony_ci    }
54cb93a386Sopenharmony_ci
55cb93a386Sopenharmony_ci    virtual void makePath(SkPath* path) {
56cb93a386Sopenharmony_ci        path_hline(path);
57cb93a386Sopenharmony_ci    }
58cb93a386Sopenharmony_ci
59cb93a386Sopenharmony_ciprotected:
60cb93a386Sopenharmony_ci    const char* onGetName() override {
61cb93a386Sopenharmony_ci        return fName.c_str();
62cb93a386Sopenharmony_ci    }
63cb93a386Sopenharmony_ci
64cb93a386Sopenharmony_ci    void onDraw(int loops, SkCanvas* canvas) override {
65cb93a386Sopenharmony_ci        SkPaint paint;
66cb93a386Sopenharmony_ci        this->setupPaint(&paint);
67cb93a386Sopenharmony_ci        paint.setStyle(SkPaint::kStroke_Style);
68cb93a386Sopenharmony_ci        paint.setStrokeWidth(SkIntToScalar(fWidth));
69cb93a386Sopenharmony_ci        paint.setAntiAlias(false);
70cb93a386Sopenharmony_ci
71cb93a386Sopenharmony_ci        SkPath path;
72cb93a386Sopenharmony_ci        this->makePath(&path);
73cb93a386Sopenharmony_ci
74cb93a386Sopenharmony_ci        paint.setPathEffect(SkDashPathEffect::Make(fIntervals.begin(), fIntervals.count(), 0));
75cb93a386Sopenharmony_ci
76cb93a386Sopenharmony_ci        if (fDoClip) {
77cb93a386Sopenharmony_ci            SkRect r = path.getBounds();
78cb93a386Sopenharmony_ci            r.inset(-SkIntToScalar(20), -SkIntToScalar(20));
79cb93a386Sopenharmony_ci            // now move it so we don't intersect
80cb93a386Sopenharmony_ci            r.offset(0, r.height() * 3 / 2);
81cb93a386Sopenharmony_ci            canvas->clipRect(r);
82cb93a386Sopenharmony_ci        }
83cb93a386Sopenharmony_ci
84cb93a386Sopenharmony_ci        this->handlePath(canvas, path, paint, loops);
85cb93a386Sopenharmony_ci    }
86cb93a386Sopenharmony_ci
87cb93a386Sopenharmony_ci    virtual void handlePath(SkCanvas* canvas, const SkPath& path,
88cb93a386Sopenharmony_ci                            const SkPaint& paint, int N) {
89cb93a386Sopenharmony_ci        for (int i = 0; i < N; ++i) {
90cb93a386Sopenharmony_ci//            canvas->drawPoints(SkCanvas::kLines_PointMode, 2, fPts, paint);
91cb93a386Sopenharmony_ci            canvas->drawPath(path, paint);
92cb93a386Sopenharmony_ci        }
93cb93a386Sopenharmony_ci    }
94cb93a386Sopenharmony_ci
95cb93a386Sopenharmony_ciprivate:
96cb93a386Sopenharmony_ci    using INHERITED = Benchmark;
97cb93a386Sopenharmony_ci};
98cb93a386Sopenharmony_ci
99cb93a386Sopenharmony_ciclass RectDashBench : public DashBench {
100cb93a386Sopenharmony_cipublic:
101cb93a386Sopenharmony_ci    RectDashBench(const SkScalar intervals[], int count, int width)
102cb93a386Sopenharmony_ci    : INHERITED(intervals, count, width) {
103cb93a386Sopenharmony_ci        fName.append("_rect");
104cb93a386Sopenharmony_ci    }
105cb93a386Sopenharmony_ci
106cb93a386Sopenharmony_ciprotected:
107cb93a386Sopenharmony_ci    void handlePath(SkCanvas* canvas, const SkPath& path, const SkPaint& paint, int N) override {
108cb93a386Sopenharmony_ci        SkPoint pts[2];
109cb93a386Sopenharmony_ci        if (!path.isLine(pts) || pts[0].fY != pts[1].fY) {
110cb93a386Sopenharmony_ci            this->INHERITED::handlePath(canvas, path, paint, N);
111cb93a386Sopenharmony_ci        } else {
112cb93a386Sopenharmony_ci            SkRect rect;
113cb93a386Sopenharmony_ci            rect.fLeft = pts[0].fX;
114cb93a386Sopenharmony_ci            rect.fTop = pts[0].fY - paint.getStrokeWidth() / 2;
115cb93a386Sopenharmony_ci            rect.fRight = rect.fLeft + SkIntToScalar(fWidth);
116cb93a386Sopenharmony_ci            rect.fBottom = rect.fTop + paint.getStrokeWidth();
117cb93a386Sopenharmony_ci
118cb93a386Sopenharmony_ci            SkPaint p(paint);
119cb93a386Sopenharmony_ci            p.setStyle(SkPaint::kFill_Style);
120cb93a386Sopenharmony_ci            p.setPathEffect(nullptr);
121cb93a386Sopenharmony_ci
122cb93a386Sopenharmony_ci            int count = SkScalarRoundToInt((pts[1].fX - pts[0].fX) / (2*fWidth));
123cb93a386Sopenharmony_ci            SkScalar dx = SkIntToScalar(2 * fWidth);
124cb93a386Sopenharmony_ci
125cb93a386Sopenharmony_ci            for (int i = 0; i < N*10; ++i) {
126cb93a386Sopenharmony_ci                SkRect r = rect;
127cb93a386Sopenharmony_ci                for (int j = 0; j < count; ++j) {
128cb93a386Sopenharmony_ci                    canvas->drawRect(r, p);
129cb93a386Sopenharmony_ci                    r.offset(dx, 0);
130cb93a386Sopenharmony_ci                }
131cb93a386Sopenharmony_ci            }
132cb93a386Sopenharmony_ci        }
133cb93a386Sopenharmony_ci    }
134cb93a386Sopenharmony_ci
135cb93a386Sopenharmony_ciprivate:
136cb93a386Sopenharmony_ci    using INHERITED = DashBench;
137cb93a386Sopenharmony_ci};
138cb93a386Sopenharmony_ci
139cb93a386Sopenharmony_cistatic void make_unit_star(SkPath* path, int n) {
140cb93a386Sopenharmony_ci    SkScalar rad = -SK_ScalarPI / 2;
141cb93a386Sopenharmony_ci    const SkScalar drad = (n >> 1) * SK_ScalarPI * 2 / n;
142cb93a386Sopenharmony_ci
143cb93a386Sopenharmony_ci    path->moveTo(0, -SK_Scalar1);
144cb93a386Sopenharmony_ci    for (int i = 1; i < n; i++) {
145cb93a386Sopenharmony_ci        rad += drad;
146cb93a386Sopenharmony_ci        path->lineTo(SkScalarCos(rad), SkScalarSin(rad));
147cb93a386Sopenharmony_ci    }
148cb93a386Sopenharmony_ci    path->close();
149cb93a386Sopenharmony_ci}
150cb93a386Sopenharmony_ci
151cb93a386Sopenharmony_cistatic void make_poly(SkPath* path) {
152cb93a386Sopenharmony_ci    make_unit_star(path, 9);
153cb93a386Sopenharmony_ci    const SkMatrix matrix = SkMatrix::Scale(100, 100);
154cb93a386Sopenharmony_ci    path->transform(matrix);
155cb93a386Sopenharmony_ci}
156cb93a386Sopenharmony_ci
157cb93a386Sopenharmony_cistatic void make_quad(SkPath* path) {
158cb93a386Sopenharmony_ci    SkScalar x0 = SkIntToScalar(10);
159cb93a386Sopenharmony_ci    SkScalar y0 = SkIntToScalar(10);
160cb93a386Sopenharmony_ci    path->moveTo(x0, y0);
161cb93a386Sopenharmony_ci    path->quadTo(x0,                    y0 + 400 * SK_Scalar1,
162cb93a386Sopenharmony_ci                 x0 + 600 * SK_Scalar1, y0 + 400 * SK_Scalar1);
163cb93a386Sopenharmony_ci}
164cb93a386Sopenharmony_ci
165cb93a386Sopenharmony_cistatic void make_cubic(SkPath* path) {
166cb93a386Sopenharmony_ci    SkScalar x0 = SkIntToScalar(10);
167cb93a386Sopenharmony_ci    SkScalar y0 = SkIntToScalar(10);
168cb93a386Sopenharmony_ci    path->moveTo(x0, y0);
169cb93a386Sopenharmony_ci    path->cubicTo(x0,                    y0 + 400 * SK_Scalar1,
170cb93a386Sopenharmony_ci                  x0 + 600 * SK_Scalar1, y0 + 400 * SK_Scalar1,
171cb93a386Sopenharmony_ci                  x0 + 600 * SK_Scalar1, y0);
172cb93a386Sopenharmony_ci}
173cb93a386Sopenharmony_ci
174cb93a386Sopenharmony_ciclass MakeDashBench : public Benchmark {
175cb93a386Sopenharmony_ci    SkString fName;
176cb93a386Sopenharmony_ci    SkPath   fPath;
177cb93a386Sopenharmony_ci    sk_sp<SkPathEffect> fPE;
178cb93a386Sopenharmony_ci
179cb93a386Sopenharmony_cipublic:
180cb93a386Sopenharmony_ci    MakeDashBench(void (*proc)(SkPath*), const char name[])  {
181cb93a386Sopenharmony_ci        fName.printf("makedash_%s", name);
182cb93a386Sopenharmony_ci        proc(&fPath);
183cb93a386Sopenharmony_ci
184cb93a386Sopenharmony_ci        SkScalar vals[] = { SkIntToScalar(4), SkIntToScalar(4) };
185cb93a386Sopenharmony_ci        fPE = SkDashPathEffect::Make(vals, 2, 0);
186cb93a386Sopenharmony_ci    }
187cb93a386Sopenharmony_ci
188cb93a386Sopenharmony_ciprotected:
189cb93a386Sopenharmony_ci    const char* onGetName() override {
190cb93a386Sopenharmony_ci        return fName.c_str();
191cb93a386Sopenharmony_ci    }
192cb93a386Sopenharmony_ci
193cb93a386Sopenharmony_ci    void onDraw(int loops, SkCanvas*) override {
194cb93a386Sopenharmony_ci        SkPath dst;
195cb93a386Sopenharmony_ci        for (int i = 0; i < loops; ++i) {
196cb93a386Sopenharmony_ci            SkStrokeRec rec(SkStrokeRec::kHairline_InitStyle);
197cb93a386Sopenharmony_ci
198cb93a386Sopenharmony_ci            fPE->filterPath(&dst, fPath, &rec, nullptr);
199cb93a386Sopenharmony_ci            dst.rewind();
200cb93a386Sopenharmony_ci        }
201cb93a386Sopenharmony_ci    }
202cb93a386Sopenharmony_ci
203cb93a386Sopenharmony_ciprivate:
204cb93a386Sopenharmony_ci    using INHERITED = Benchmark;
205cb93a386Sopenharmony_ci};
206cb93a386Sopenharmony_ci
207cb93a386Sopenharmony_ci/*
208cb93a386Sopenharmony_ci *  We try to special case square dashes (intervals are equal to strokewidth).
209cb93a386Sopenharmony_ci */
210cb93a386Sopenharmony_ciclass DashLineBench : public Benchmark {
211cb93a386Sopenharmony_ci    SkString fName;
212cb93a386Sopenharmony_ci    SkScalar fStrokeWidth;
213cb93a386Sopenharmony_ci    bool     fIsRound;
214cb93a386Sopenharmony_ci    sk_sp<SkPathEffect> fPE;
215cb93a386Sopenharmony_ci
216cb93a386Sopenharmony_cipublic:
217cb93a386Sopenharmony_ci    DashLineBench(SkScalar width, bool isRound)  {
218cb93a386Sopenharmony_ci        fName.printf("dashline_%g_%s", SkScalarToFloat(width), isRound ? "circle" : "square");
219cb93a386Sopenharmony_ci        fStrokeWidth = width;
220cb93a386Sopenharmony_ci        fIsRound = isRound;
221cb93a386Sopenharmony_ci
222cb93a386Sopenharmony_ci        SkScalar vals[] = { SK_Scalar1, SK_Scalar1 };
223cb93a386Sopenharmony_ci        fPE = SkDashPathEffect::Make(vals, 2, 0);
224cb93a386Sopenharmony_ci    }
225cb93a386Sopenharmony_ci
226cb93a386Sopenharmony_ciprotected:
227cb93a386Sopenharmony_ci    const char* onGetName() override {
228cb93a386Sopenharmony_ci        return fName.c_str();
229cb93a386Sopenharmony_ci    }
230cb93a386Sopenharmony_ci
231cb93a386Sopenharmony_ci    void onDraw(int loops, SkCanvas* canvas) override {
232cb93a386Sopenharmony_ci        SkPaint paint;
233cb93a386Sopenharmony_ci        this->setupPaint(&paint);
234cb93a386Sopenharmony_ci        paint.setStrokeWidth(fStrokeWidth);
235cb93a386Sopenharmony_ci        paint.setStrokeCap(fIsRound ? SkPaint::kRound_Cap : SkPaint::kSquare_Cap);
236cb93a386Sopenharmony_ci        paint.setPathEffect(fPE);
237cb93a386Sopenharmony_ci        for (int i = 0; i < loops; ++i) {
238cb93a386Sopenharmony_ci            canvas->drawLine(10 * SK_Scalar1, 10 * SK_Scalar1,
239cb93a386Sopenharmony_ci                             640 * SK_Scalar1, 10 * SK_Scalar1, paint);
240cb93a386Sopenharmony_ci        }
241cb93a386Sopenharmony_ci    }
242cb93a386Sopenharmony_ci
243cb93a386Sopenharmony_ciprivate:
244cb93a386Sopenharmony_ci    using INHERITED = Benchmark;
245cb93a386Sopenharmony_ci};
246cb93a386Sopenharmony_ci
247cb93a386Sopenharmony_ciclass DrawPointsDashingBench : public Benchmark {
248cb93a386Sopenharmony_ci    SkString fName;
249cb93a386Sopenharmony_ci    int      fStrokeWidth;
250cb93a386Sopenharmony_ci    bool     fDoAA;
251cb93a386Sopenharmony_ci
252cb93a386Sopenharmony_ci    sk_sp<SkPathEffect> fPathEffect;
253cb93a386Sopenharmony_ci
254cb93a386Sopenharmony_cipublic:
255cb93a386Sopenharmony_ci    DrawPointsDashingBench(int dashLength, int strokeWidth, bool doAA)
256cb93a386Sopenharmony_ci         {
257cb93a386Sopenharmony_ci        fName.printf("drawpointsdash_%d_%d%s", dashLength, strokeWidth, doAA ? "_aa" : "_bw");
258cb93a386Sopenharmony_ci        fStrokeWidth = strokeWidth;
259cb93a386Sopenharmony_ci        fDoAA = doAA;
260cb93a386Sopenharmony_ci
261cb93a386Sopenharmony_ci        SkScalar vals[] = { SkIntToScalar(dashLength), SkIntToScalar(dashLength) };
262cb93a386Sopenharmony_ci        fPathEffect = SkDashPathEffect::Make(vals, 2, SK_Scalar1);
263cb93a386Sopenharmony_ci    }
264cb93a386Sopenharmony_ci
265cb93a386Sopenharmony_ciprotected:
266cb93a386Sopenharmony_ci    const char* onGetName() override {
267cb93a386Sopenharmony_ci        return fName.c_str();
268cb93a386Sopenharmony_ci    }
269cb93a386Sopenharmony_ci
270cb93a386Sopenharmony_ci    void onDraw(int loops, SkCanvas* canvas) override {
271cb93a386Sopenharmony_ci        SkPaint p;
272cb93a386Sopenharmony_ci        this->setupPaint(&p);
273cb93a386Sopenharmony_ci        p.setColor(SK_ColorBLACK);
274cb93a386Sopenharmony_ci        p.setStyle(SkPaint::kStroke_Style);
275cb93a386Sopenharmony_ci        p.setStrokeWidth(SkIntToScalar(fStrokeWidth));
276cb93a386Sopenharmony_ci        p.setPathEffect(fPathEffect);
277cb93a386Sopenharmony_ci        p.setAntiAlias(fDoAA);
278cb93a386Sopenharmony_ci
279cb93a386Sopenharmony_ci        SkPoint pts[2] = {
280cb93a386Sopenharmony_ci            { SkIntToScalar(10), 0 },
281cb93a386Sopenharmony_ci            { SkIntToScalar(640), 0 }
282cb93a386Sopenharmony_ci        };
283cb93a386Sopenharmony_ci
284cb93a386Sopenharmony_ci        for (int i = 0; i < loops; ++i) {
285cb93a386Sopenharmony_ci            pts[0].fY = pts[1].fY = SkIntToScalar(i % 480);
286cb93a386Sopenharmony_ci            canvas->drawPoints(SkCanvas::kLines_PointMode, 2, pts, p);
287cb93a386Sopenharmony_ci        }
288cb93a386Sopenharmony_ci    }
289cb93a386Sopenharmony_ci
290cb93a386Sopenharmony_ciprivate:
291cb93a386Sopenharmony_ci    using INHERITED = Benchmark;
292cb93a386Sopenharmony_ci};
293cb93a386Sopenharmony_ci
294cb93a386Sopenharmony_ci// Want to test how we handle dashing when 99% of the dash is clipped out
295cb93a386Sopenharmony_ciclass GiantDashBench : public Benchmark {
296cb93a386Sopenharmony_ci    SkString fName;
297cb93a386Sopenharmony_ci    SkScalar fStrokeWidth;
298cb93a386Sopenharmony_ci    SkPoint  fPts[2];
299cb93a386Sopenharmony_ci    sk_sp<SkPathEffect> fPathEffect;
300cb93a386Sopenharmony_ci
301cb93a386Sopenharmony_cipublic:
302cb93a386Sopenharmony_ci    enum LineType {
303cb93a386Sopenharmony_ci        kHori_LineType,
304cb93a386Sopenharmony_ci        kVert_LineType,
305cb93a386Sopenharmony_ci        kDiag_LineType,
306cb93a386Sopenharmony_ci        kLineTypeCount
307cb93a386Sopenharmony_ci    };
308cb93a386Sopenharmony_ci
309cb93a386Sopenharmony_ci    static const char* LineTypeName(LineType lt) {
310cb93a386Sopenharmony_ci        static const char* gNames[] = { "hori", "vert", "diag" };
311cb93a386Sopenharmony_ci        static_assert(kLineTypeCount == SK_ARRAY_COUNT(gNames), "names_wrong_size");
312cb93a386Sopenharmony_ci        return gNames[lt];
313cb93a386Sopenharmony_ci    }
314cb93a386Sopenharmony_ci
315cb93a386Sopenharmony_ci    GiantDashBench(LineType lt, SkScalar width)  {
316cb93a386Sopenharmony_ci        fName.printf("giantdashline_%s_%g", LineTypeName(lt), width);
317cb93a386Sopenharmony_ci        fStrokeWidth = width;
318cb93a386Sopenharmony_ci
319cb93a386Sopenharmony_ci        // deliberately pick intervals that won't be caught by asPoints(), so
320cb93a386Sopenharmony_ci        // we can test the filterPath code-path.
321cb93a386Sopenharmony_ci        const SkScalar intervals[] = { 20, 10, 10, 10 };
322cb93a386Sopenharmony_ci        fPathEffect = SkDashPathEffect::Make(intervals, SK_ARRAY_COUNT(intervals), 0);
323cb93a386Sopenharmony_ci
324cb93a386Sopenharmony_ci        SkScalar cx = 640 / 2;  // center X
325cb93a386Sopenharmony_ci        SkScalar cy = 480 / 2;  // center Y
326cb93a386Sopenharmony_ci        SkMatrix matrix;
327cb93a386Sopenharmony_ci
328cb93a386Sopenharmony_ci        switch (lt) {
329cb93a386Sopenharmony_ci            case kHori_LineType:
330cb93a386Sopenharmony_ci                matrix.setIdentity();
331cb93a386Sopenharmony_ci                break;
332cb93a386Sopenharmony_ci            case kVert_LineType:
333cb93a386Sopenharmony_ci                matrix.setRotate(90, cx, cy);
334cb93a386Sopenharmony_ci                break;
335cb93a386Sopenharmony_ci            case kDiag_LineType:
336cb93a386Sopenharmony_ci                matrix.setRotate(45, cx, cy);
337cb93a386Sopenharmony_ci                break;
338cb93a386Sopenharmony_ci            case kLineTypeCount:
339cb93a386Sopenharmony_ci                // Not a real enum value.
340cb93a386Sopenharmony_ci                break;
341cb93a386Sopenharmony_ci        }
342cb93a386Sopenharmony_ci
343cb93a386Sopenharmony_ci        const SkScalar overshoot = 100*1000;
344cb93a386Sopenharmony_ci        const SkPoint pts[2] = {
345cb93a386Sopenharmony_ci            { -overshoot, cy }, { 640 + overshoot, cy }
346cb93a386Sopenharmony_ci        };
347cb93a386Sopenharmony_ci        matrix.mapPoints(fPts, pts, 2);
348cb93a386Sopenharmony_ci    }
349cb93a386Sopenharmony_ci
350cb93a386Sopenharmony_ciprotected:
351cb93a386Sopenharmony_ci    const char* onGetName() override {
352cb93a386Sopenharmony_ci        return fName.c_str();
353cb93a386Sopenharmony_ci    }
354cb93a386Sopenharmony_ci
355cb93a386Sopenharmony_ci    void onDraw(int loops, SkCanvas* canvas) override {
356cb93a386Sopenharmony_ci        SkPaint p;
357cb93a386Sopenharmony_ci        this->setupPaint(&p);
358cb93a386Sopenharmony_ci        p.setStyle(SkPaint::kStroke_Style);
359cb93a386Sopenharmony_ci        p.setStrokeWidth(fStrokeWidth);
360cb93a386Sopenharmony_ci        p.setPathEffect(fPathEffect);
361cb93a386Sopenharmony_ci
362cb93a386Sopenharmony_ci        for (int i = 0; i < loops; i++) {
363cb93a386Sopenharmony_ci            canvas->drawPoints(SkCanvas::kLines_PointMode, 2, fPts, p);
364cb93a386Sopenharmony_ci        }
365cb93a386Sopenharmony_ci    }
366cb93a386Sopenharmony_ci
367cb93a386Sopenharmony_ciprivate:
368cb93a386Sopenharmony_ci    using INHERITED = Benchmark;
369cb93a386Sopenharmony_ci};
370cb93a386Sopenharmony_ci
371cb93a386Sopenharmony_ci// Want to test how we draw a dashed grid (like what is used in spreadsheets) of many
372cb93a386Sopenharmony_ci// small dashed lines switching back and forth between horizontal and vertical
373cb93a386Sopenharmony_ciclass DashGridBench : public Benchmark {
374cb93a386Sopenharmony_ci    SkString fName;
375cb93a386Sopenharmony_ci    int      fStrokeWidth;
376cb93a386Sopenharmony_ci    bool     fDoAA;
377cb93a386Sopenharmony_ci
378cb93a386Sopenharmony_ci    sk_sp<SkPathEffect> fPathEffect;
379cb93a386Sopenharmony_ci
380cb93a386Sopenharmony_cipublic:
381cb93a386Sopenharmony_ci    DashGridBench(int dashLength, int strokeWidth, bool doAA) {
382cb93a386Sopenharmony_ci        fName.printf("dashgrid_%d_%d%s", dashLength, strokeWidth, doAA ? "_aa" : "_bw");
383cb93a386Sopenharmony_ci        fStrokeWidth = strokeWidth;
384cb93a386Sopenharmony_ci        fDoAA = doAA;
385cb93a386Sopenharmony_ci
386cb93a386Sopenharmony_ci        SkScalar vals[] = { SkIntToScalar(dashLength), SkIntToScalar(dashLength) };
387cb93a386Sopenharmony_ci        fPathEffect = SkDashPathEffect::Make(vals, 2, SK_Scalar1);
388cb93a386Sopenharmony_ci    }
389cb93a386Sopenharmony_ci
390cb93a386Sopenharmony_ciprotected:
391cb93a386Sopenharmony_ci    const char* onGetName() override {
392cb93a386Sopenharmony_ci        return fName.c_str();
393cb93a386Sopenharmony_ci    }
394cb93a386Sopenharmony_ci
395cb93a386Sopenharmony_ci    void onDraw(int loops, SkCanvas* canvas) override {
396cb93a386Sopenharmony_ci        SkPaint p;
397cb93a386Sopenharmony_ci        this->setupPaint(&p);
398cb93a386Sopenharmony_ci        p.setColor(SK_ColorBLACK);
399cb93a386Sopenharmony_ci        p.setStyle(SkPaint::kStroke_Style);
400cb93a386Sopenharmony_ci        p.setStrokeWidth(SkIntToScalar(fStrokeWidth));
401cb93a386Sopenharmony_ci        p.setPathEffect(fPathEffect);
402cb93a386Sopenharmony_ci        p.setAntiAlias(fDoAA);
403cb93a386Sopenharmony_ci
404cb93a386Sopenharmony_ci        SkPoint pts[4] = {
405cb93a386Sopenharmony_ci            { SkIntToScalar(0), 20.5f },
406cb93a386Sopenharmony_ci            { SkIntToScalar(20), 20.5f },
407cb93a386Sopenharmony_ci            { 20.5f, SkIntToScalar(0) },
408cb93a386Sopenharmony_ci            { 20.5f, SkIntToScalar(20) }
409cb93a386Sopenharmony_ci        };
410cb93a386Sopenharmony_ci
411cb93a386Sopenharmony_ci        for (int i = 0; i < loops; ++i) {
412cb93a386Sopenharmony_ci            for (int j = 0; j < 10; ++j) {
413cb93a386Sopenharmony_ci                for (int k = 0; k < 10; ++k) {
414cb93a386Sopenharmony_ci                    // Horizontal line
415cb93a386Sopenharmony_ci                    SkPoint horPts[2];
416cb93a386Sopenharmony_ci                    horPts[0].fX = pts[0].fX + k * 22.f;
417cb93a386Sopenharmony_ci                    horPts[0].fY = pts[0].fY + j * 22.f;
418cb93a386Sopenharmony_ci                    horPts[1].fX = pts[1].fX + k * 22.f;
419cb93a386Sopenharmony_ci                    horPts[1].fY = pts[1].fY + j * 22.f;
420cb93a386Sopenharmony_ci                    canvas->drawPoints(SkCanvas::kLines_PointMode, 2, horPts, p);
421cb93a386Sopenharmony_ci
422cb93a386Sopenharmony_ci                    // Vertical line
423cb93a386Sopenharmony_ci                    SkPoint vertPts[2];
424cb93a386Sopenharmony_ci                    vertPts[0].fX = pts[2].fX + k * 22.f;
425cb93a386Sopenharmony_ci                    vertPts[0].fY = pts[2].fY + j * 22.f;
426cb93a386Sopenharmony_ci                    vertPts[1].fX = pts[3].fX + k * 22.f;
427cb93a386Sopenharmony_ci                    vertPts[1].fY = pts[3].fY + j * 22.f;
428cb93a386Sopenharmony_ci                    canvas->drawPoints(SkCanvas::kLines_PointMode, 2, vertPts, p);
429cb93a386Sopenharmony_ci                }
430cb93a386Sopenharmony_ci            }
431cb93a386Sopenharmony_ci        }
432cb93a386Sopenharmony_ci    }
433cb93a386Sopenharmony_ci
434cb93a386Sopenharmony_ciprivate:
435cb93a386Sopenharmony_ci    using INHERITED = Benchmark;
436cb93a386Sopenharmony_ci};
437cb93a386Sopenharmony_ci
438cb93a386Sopenharmony_ci///////////////////////////////////////////////////////////////////////////////
439cb93a386Sopenharmony_ci
440cb93a386Sopenharmony_cistatic const SkScalar gDots[] = { SK_Scalar1, SK_Scalar1 };
441cb93a386Sopenharmony_ci
442cb93a386Sopenharmony_ci#define PARAM(array)    array, SK_ARRAY_COUNT(array)
443cb93a386Sopenharmony_ci
444cb93a386Sopenharmony_ciDEF_BENCH( return new DashBench(PARAM(gDots), 0); )
445cb93a386Sopenharmony_ciDEF_BENCH( return new DashBench(PARAM(gDots), 1); )
446cb93a386Sopenharmony_ciDEF_BENCH( return new DashBench(PARAM(gDots), 1, true); )
447cb93a386Sopenharmony_ciDEF_BENCH( return new DashBench(PARAM(gDots), 4); )
448cb93a386Sopenharmony_ciDEF_BENCH( return new MakeDashBench(make_poly, "poly"); )
449cb93a386Sopenharmony_ciDEF_BENCH( return new MakeDashBench(make_quad, "quad"); )
450cb93a386Sopenharmony_ciDEF_BENCH( return new MakeDashBench(make_cubic, "cubic"); )
451cb93a386Sopenharmony_ciDEF_BENCH( return new DashLineBench(0, false); )
452cb93a386Sopenharmony_ciDEF_BENCH( return new DashLineBench(SK_Scalar1, false); )
453cb93a386Sopenharmony_ciDEF_BENCH( return new DashLineBench(2 * SK_Scalar1, false); )
454cb93a386Sopenharmony_ciDEF_BENCH( return new DashLineBench(0, true); )
455cb93a386Sopenharmony_ciDEF_BENCH( return new DashLineBench(SK_Scalar1, true); )
456cb93a386Sopenharmony_ciDEF_BENCH( return new DashLineBench(2 * SK_Scalar1, true); )
457cb93a386Sopenharmony_ci
458cb93a386Sopenharmony_ciDEF_BENCH( return new DrawPointsDashingBench(1, 1, false); )
459cb93a386Sopenharmony_ciDEF_BENCH( return new DrawPointsDashingBench(1, 1, true); )
460cb93a386Sopenharmony_ciDEF_BENCH( return new DrawPointsDashingBench(3, 1, false); )
461cb93a386Sopenharmony_ciDEF_BENCH( return new DrawPointsDashingBench(3, 1, true); )
462cb93a386Sopenharmony_ciDEF_BENCH( return new DrawPointsDashingBench(5, 5, false); )
463cb93a386Sopenharmony_ciDEF_BENCH( return new DrawPointsDashingBench(5, 5, true); )
464cb93a386Sopenharmony_ci
465cb93a386Sopenharmony_ci/* Disable the GiantDashBench for Android devices until we can better control
466cb93a386Sopenharmony_ci * the memory usage. (https://code.google.com/p/skia/issues/detail?id=1430)
467cb93a386Sopenharmony_ci */
468cb93a386Sopenharmony_ci#ifndef SK_BUILD_FOR_ANDROID
469cb93a386Sopenharmony_ciDEF_BENCH( return new GiantDashBench(GiantDashBench::kHori_LineType, 0); )
470cb93a386Sopenharmony_ciDEF_BENCH( return new GiantDashBench(GiantDashBench::kVert_LineType, 0); )
471cb93a386Sopenharmony_ciDEF_BENCH( return new GiantDashBench(GiantDashBench::kDiag_LineType, 0); )
472cb93a386Sopenharmony_ci
473cb93a386Sopenharmony_ci// pass 2 to explicitly avoid any 1-is-the-same-as-hairline special casing
474cb93a386Sopenharmony_ci
475cb93a386Sopenharmony_ci// hori_2 is just too slow to enable at the moment
476cb93a386Sopenharmony_ciDEF_BENCH( return new GiantDashBench(GiantDashBench::kHori_LineType, 2); )
477cb93a386Sopenharmony_ciDEF_BENCH( return new GiantDashBench(GiantDashBench::kVert_LineType, 2); )
478cb93a386Sopenharmony_ciDEF_BENCH( return new GiantDashBench(GiantDashBench::kDiag_LineType, 2); )
479cb93a386Sopenharmony_ci
480cb93a386Sopenharmony_ciDEF_BENCH( return new DashGridBench(1, 1, true); )
481cb93a386Sopenharmony_ciDEF_BENCH( return new DashGridBench(1, 1, false); )
482cb93a386Sopenharmony_ciDEF_BENCH( return new DashGridBench(3, 1, true); )
483cb93a386Sopenharmony_ciDEF_BENCH( return new DashGridBench(3, 1, false); )
484cb93a386Sopenharmony_ci#endif
485