DashBench.cpp revision 4ad22753504828342e47627b12210c2c47e7290a
1
2/*
3 * Copyright 2011 Google Inc.
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8#include "SkBenchmark.h"
9#include "SkBitmap.h"
10#include "SkCanvas.h"
11#include "SkDashPathEffect.h"
12#include "SkPaint.h"
13#include "SkPath.h"
14#include "SkRandom.h"
15#include "SkString.h"
16#include "SkTDArray.h"
17
18
19/*
20 *  Cases to consider:
21 *
22 *  1. antialiasing on/off (esp. width <= 1)
23 *  2. strokewidth == 0, 1, 2
24 *  3. hline, vline, diagonal, rect, oval
25 *  4. dots [1,1] ([N,N] where N=strokeWidth?) or arbitrary (e.g. [2,1] or [1,2,3,2])
26 */
27static void path_hline(SkPath* path) {
28    path->moveTo(SkIntToScalar(10), SkIntToScalar(10));
29    path->lineTo(SkIntToScalar(600), SkIntToScalar(10));
30}
31
32class DashBench : public SkBenchmark {
33protected:
34    SkString            fName;
35    SkTDArray<SkScalar> fIntervals;
36    int                 fWidth;
37    bool fDoClip;
38
39    enum {
40        N = SkBENCHLOOP(100)
41    };
42public:
43    DashBench(void* param, const SkScalar intervals[], int count, int width,
44              bool doClip = false) : INHERITED(param) {
45        fIntervals.append(count, intervals);
46        for (int i = 0; i < count; ++i) {
47            fIntervals[i] *= width;
48        }
49        fWidth = width;
50        fName.printf("dash_%d_%s", width, doClip ? "clipped" : "noclip");
51        fDoClip = doClip;
52    }
53
54    virtual void makePath(SkPath* path) {
55        path_hline(path);
56    }
57
58protected:
59    virtual const char* onGetName() SK_OVERRIDE {
60        return fName.c_str();
61    }
62
63    virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
64        SkPaint paint;
65        this->setupPaint(&paint);
66        paint.setStyle(SkPaint::kStroke_Style);
67        paint.setStrokeWidth(SkIntToScalar(fWidth));
68        paint.setAntiAlias(false);
69
70        SkPath path;
71        this->makePath(&path);
72
73        paint.setPathEffect(new SkDashPathEffect(fIntervals.begin(),
74                                                 fIntervals.count(), 0))->unref();
75
76        if (fDoClip) {
77            SkRect r = path.getBounds();
78            r.inset(-SkIntToScalar(20), -SkIntToScalar(20));
79            // now move it so we don't intersect
80            r.offset(0, r.height() * 3 / 2);
81            canvas->clipRect(r);
82        }
83
84        this->handlePath(canvas, path, paint, N);
85    }
86
87    virtual void handlePath(SkCanvas* canvas, const SkPath& path,
88                            const SkPaint& paint, int N) {
89        for (int i = 0; i < N; ++i) {
90            canvas->drawPath(path, paint);
91        }
92    }
93
94private:
95    typedef SkBenchmark INHERITED;
96};
97
98class RectDashBench : public DashBench {
99public:
100    RectDashBench(void* param, const SkScalar intervals[], int count, int width, bool doClip = false)
101    : INHERITED(param, intervals, count, width) {
102        fName.append("_rect");
103    }
104
105protected:
106    virtual void handlePath(SkCanvas* canvas, const SkPath& path,
107                            const SkPaint& paint, int N) SK_OVERRIDE {
108        SkPoint pts[2];
109        if (!path.isLine(pts) || pts[0].fY != pts[1].fY) {
110            this->INHERITED::handlePath(canvas, path, paint, N);
111        } else {
112            SkRect rect;
113            rect.fLeft = pts[0].fX;
114            rect.fTop = pts[0].fY - paint.getStrokeWidth() / 2;
115            rect.fRight = rect.fLeft + SkIntToScalar(fWidth);
116            rect.fBottom = rect.fTop + paint.getStrokeWidth();
117
118            SkPaint p(paint);
119            p.setStyle(SkPaint::kFill_Style);
120            p.setPathEffect(NULL);
121
122            int count = SkScalarRoundToInt((pts[1].fX - pts[0].fX) / (2*fWidth));
123            SkScalar dx = SkIntToScalar(2 * fWidth);
124
125            for (int i = 0; i < N*10; ++i) {
126                SkRect r = rect;
127                for (int j = 0; j < count; ++j) {
128                    canvas->drawRect(r, p);
129                    r.offset(dx, 0);
130                }
131            }
132        }
133    }
134
135private:
136    typedef DashBench INHERITED;
137};
138
139///////////////////////////////////////////////////////////////////////////////
140
141static const SkScalar gDots[] = { SK_Scalar1, SK_Scalar1 };
142
143#define PARAM(array)    array, SK_ARRAY_COUNT(array)
144
145static SkBenchmark* gF0(void* p) { return new DashBench(p, PARAM(gDots), 0); }
146static SkBenchmark* gF1(void* p) { return new DashBench(p, PARAM(gDots), 1); }
147static SkBenchmark* gF2(void* p) { return new DashBench(p, PARAM(gDots), 1, true); }
148static SkBenchmark* gF3(void* p) { return new DashBench(p, PARAM(gDots), 4); }
149static SkBenchmark* gF4(void* p) { return new RectDashBench(p, PARAM(gDots), 4); }
150
151static BenchRegistry gR0(gF0);
152static BenchRegistry gR1(gF1);
153static BenchRegistry gR2(gF2);
154static BenchRegistry gR3(gF3);
155static BenchRegistry gR4(gF4);
156