PathBench.cpp revision f6fc3fcadd343fad8d89d34749146d7e3c43d95b
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 "SkColorPriv.h"
12#include "SkPaint.h"
13#include "SkRandom.h"
14#include "SkShader.h"
15#include "SkString.h"
16#include "SkTArray.h"
17
18
19enum Flags {
20    kStroke_Flag = 1 << 0,
21    kBig_Flag    = 1 << 1
22};
23
24#define FLAGS00  Flags(0)
25#define FLAGS01  Flags(kStroke_Flag)
26#define FLAGS10  Flags(kBig_Flag)
27#define FLAGS11  Flags(kStroke_Flag | kBig_Flag)
28
29class PathBench : public SkBenchmark {
30    SkPaint     fPaint;
31    SkString    fName;
32    Flags       fFlags;
33    enum { N = SkBENCHLOOP(1000) };
34public:
35    PathBench(void* param, Flags flags) : INHERITED(param), fFlags(flags) {
36        fPaint.setStyle(flags & kStroke_Flag ? SkPaint::kStroke_Style :
37                        SkPaint::kFill_Style);
38        fPaint.setStrokeWidth(SkIntToScalar(5));
39        fPaint.setStrokeJoin(SkPaint::kBevel_Join);
40    }
41
42    virtual void appendName(SkString*) = 0;
43    virtual void makePath(SkPath*) = 0;
44    virtual int complexity() { return 0; }
45
46protected:
47    virtual const char* onGetName() SK_OVERRIDE {
48        fName.printf("path_%s_%s_",
49                     fFlags & kStroke_Flag ? "stroke" : "fill",
50                     fFlags & kBig_Flag ? "big" : "small");
51        this->appendName(&fName);
52        return fName.c_str();
53    }
54
55    virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
56        SkPaint paint(fPaint);
57        this->setupPaint(&paint);
58
59        SkPath path;
60        this->makePath(&path);
61        if (fFlags & kBig_Flag) {
62            SkMatrix m;
63            m.setScale(SkIntToScalar(10), SkIntToScalar(10));
64            path.transform(m);
65        }
66
67        int count = N;
68        if (fFlags & kBig_Flag) {
69            count >>= 2;
70        }
71        count >>= (3 * complexity());
72
73        for (int i = 0; i < count; i++) {
74            canvas->drawPath(path, paint);
75        }
76    }
77
78private:
79    typedef SkBenchmark INHERITED;
80};
81
82class TrianglePathBench : public PathBench {
83public:
84    TrianglePathBench(void* param, Flags flags) : INHERITED(param, flags) {}
85
86    virtual void appendName(SkString* name) SK_OVERRIDE {
87        name->append("triangle");
88    }
89    virtual void makePath(SkPath* path) SK_OVERRIDE {
90        static const int gCoord[] = {
91            10, 10, 15, 5, 20, 20
92        };
93        path->moveTo(SkIntToScalar(gCoord[0]), SkIntToScalar(gCoord[1]));
94        path->lineTo(SkIntToScalar(gCoord[2]), SkIntToScalar(gCoord[3]));
95        path->lineTo(SkIntToScalar(gCoord[4]), SkIntToScalar(gCoord[5]));
96        path->close();
97    }
98private:
99    typedef PathBench INHERITED;
100};
101
102class RectPathBench : public PathBench {
103public:
104    RectPathBench(void* param, Flags flags) : INHERITED(param, flags) {}
105
106    virtual void appendName(SkString* name) SK_OVERRIDE {
107        name->append("rect");
108    }
109    virtual void makePath(SkPath* path) SK_OVERRIDE {
110        SkRect r = { 10, 10, 20, 20 };
111        path->addRect(r);
112    }
113private:
114    typedef PathBench INHERITED;
115};
116
117class OvalPathBench : public PathBench {
118public:
119    OvalPathBench(void* param, Flags flags) : INHERITED(param, flags) {}
120
121    virtual void appendName(SkString* name) SK_OVERRIDE {
122        name->append("oval");
123    }
124    virtual void makePath(SkPath* path) SK_OVERRIDE {
125        SkRect r = { 10, 10, 20, 20 };
126        path->addOval(r);
127    }
128private:
129    typedef PathBench INHERITED;
130};
131
132class CirclePathBench: public PathBench {
133public:
134    CirclePathBench(void* param, Flags flags) : INHERITED(param, flags) {}
135
136    virtual void appendName(SkString* name) SK_OVERRIDE {
137        name->append("circle");
138    }
139    virtual void makePath(SkPath* path) SK_OVERRIDE {
140        path->addCircle(SkIntToScalar(20), SkIntToScalar(20),
141                        SkIntToScalar(10));
142    }
143private:
144    typedef PathBench INHERITED;
145};
146
147class SawToothPathBench : public PathBench {
148public:
149    SawToothPathBench(void* param, Flags flags) : INHERITED(param, flags) {}
150
151    virtual void appendName(SkString* name) SK_OVERRIDE {
152        name->append("sawtooth");
153    }
154    virtual void makePath(SkPath* path) {
155        SkScalar x = SkIntToScalar(20);
156        SkScalar y = SkIntToScalar(20);
157        const SkScalar x0 = x;
158        const SkScalar dx = SK_Scalar1 * 5;
159        const SkScalar dy = SK_Scalar1 * 10;
160
161        path->moveTo(x, y);
162        for (int i = 0; i < 32; i++) {
163            x += dx;
164            path->lineTo(x, y - dy);
165            x += dx;
166            path->lineTo(x, y + dy);
167        }
168        path->lineTo(x, y + 2 * dy);
169        path->lineTo(x0, y + 2 * dy);
170        path->close();
171    }
172    virtual int complexity() SK_OVERRIDE { return 1; }
173private:
174    typedef PathBench INHERITED;
175};
176
177class LongCurvedPathBench : public PathBench {
178public:
179    LongCurvedPathBench(void * param, Flags flags)
180        : INHERITED(param, flags) {
181    }
182
183    virtual void appendName(SkString* name) SK_OVERRIDE {
184        name->append("long_curved");
185    }
186    virtual void makePath(SkPath* path) SK_OVERRIDE {
187        SkRandom rand (12);
188        int i;
189        for (i = 0; i < 100; i++) {
190            path->quadTo(SkScalarMul(rand.nextUScalar1(), SkIntToScalar(640)),
191                         SkScalarMul(rand.nextUScalar1(), SkIntToScalar(480)),
192                         SkScalarMul(rand.nextUScalar1(), SkIntToScalar(640)),
193                         SkScalarMul(rand.nextUScalar1(), SkIntToScalar(480)));
194        }
195        path->close();
196    }
197    virtual int complexity() SK_OVERRIDE { return 2; }
198private:
199    typedef PathBench INHERITED;
200};
201
202class LongLinePathBench : public PathBench {
203public:
204    LongLinePathBench(void * param, Flags flags)
205        : INHERITED(param, flags) {
206    }
207
208    virtual void appendName(SkString* name) SK_OVERRIDE {
209        name->append("long_line");
210    }
211    virtual void makePath(SkPath* path) SK_OVERRIDE {
212        SkRandom rand;
213        path->moveTo(rand.nextUScalar1() * 640, rand.nextUScalar1() * 480);
214        for (size_t i = 1; i < 100; i++) {
215            path->lineTo(rand.nextUScalar1() * 640, rand.nextUScalar1() * 480);
216        }
217    }
218    virtual int complexity() SK_OVERRIDE { return 2; }
219private:
220    typedef PathBench INHERITED;
221};
222
223class RandomPathBench : public SkBenchmark {
224public:
225    RandomPathBench(void* param) : INHERITED(param) {
226        fIsRendering = false;
227    }
228
229protected:
230    void createData(int minVerbs,
231                    int maxVerbs,
232                    bool allowMoves = true,
233                    SkRect* bounds = NULL) {
234        SkRect tempBounds;
235        if (NULL == bounds) {
236            tempBounds.setXYWH(0, 0, SK_Scalar1, SK_Scalar1);
237            bounds = &tempBounds;
238        }
239        fVerbCnts.reset(kNumVerbCnts);
240        for (int i = 0; i < kNumVerbCnts; ++i) {
241            fVerbCnts[i] = fRandom.nextRangeU(minVerbs, maxVerbs + 1);
242        }
243        fVerbs.reset(kNumVerbs);
244        for (int i = 0; i < kNumVerbs; ++i) {
245            do {
246                fVerbs[i] = static_cast<SkPath::Verb>(fRandom.nextULessThan(SkPath::kDone_Verb));
247            } while (!allowMoves && SkPath::kMove_Verb == fVerbs[i]);
248        }
249        fPoints.reset(kNumPoints);
250        for (int i = 0; i < kNumPoints; ++i) {
251            fPoints[i].set(fRandom.nextRangeScalar(bounds->fLeft, bounds->fRight),
252                           fRandom.nextRangeScalar(bounds->fTop, bounds->fBottom));
253        }
254        this->restartMakingPaths();
255    }
256
257    void restartMakingPaths() {
258        fCurrPath = 0;
259        fCurrVerb = 0;
260        fCurrPoint = 0;
261    }
262
263    void makePath(SkPath* path) {
264        int vCount = fVerbCnts[(fCurrPath++) & (kNumVerbCnts - 1)];
265        for (int v = 0; v < vCount; ++v) {
266            int verb = fVerbs[(fCurrVerb++) & (kNumVerbs - 1)];
267            switch (verb) {
268                case SkPath::kMove_Verb:
269                    path->moveTo(fPoints[(fCurrPoint++) & (kNumPoints - 1)]);
270                    break;
271                case SkPath::kLine_Verb:
272                    path->lineTo(fPoints[(fCurrPoint++) & (kNumPoints - 1)]);
273                    break;
274                case SkPath::kQuad_Verb:
275                    path->quadTo(fPoints[(fCurrPoint + 0) & (kNumPoints - 1)],
276                                 fPoints[(fCurrPoint + 1) & (kNumPoints - 1)]);
277                    fCurrPoint += 2;
278                    break;
279                case SkPath::kCubic_Verb:
280                    path->cubicTo(fPoints[(fCurrPoint + 0) & (kNumPoints - 1)],
281                                  fPoints[(fCurrPoint + 1) & (kNumPoints - 1)],
282                                  fPoints[(fCurrPoint + 2) & (kNumPoints - 1)]);
283                    fCurrPoint += 3;
284                    break;
285                case SkPath::kClose_Verb:
286                    path->close();
287                    break;
288                default:
289                    SkDEBUGFAIL("Unexpected path verb");
290                    break;
291            }
292        }
293    }
294
295    void finishedMakingPaths() {
296        fVerbCnts.reset(0);
297        fVerbs.reset(0);
298        fPoints.reset(0);
299    }
300
301private:
302    enum {
303        // these should all be pow 2
304        kNumVerbCnts = 1 << 5,
305        kNumVerbs    = 1 << 5,
306        kNumPoints   = 1 << 5,
307    };
308    SkAutoTArray<int>           fVerbCnts;
309    SkAutoTArray<SkPath::Verb>  fVerbs;
310    SkAutoTArray<SkPoint>       fPoints;
311    int                         fCurrPath;
312    int                         fCurrVerb;
313    int                         fCurrPoint;
314    SkRandom                    fRandom;
315    typedef SkBenchmark INHERITED;
316};
317
318class PathCreateBench : public RandomPathBench {
319public:
320    PathCreateBench(void* param) : INHERITED(param) {
321    }
322
323protected:
324    enum { N = SkBENCHLOOP(5000) };
325
326    virtual const char* onGetName() SK_OVERRIDE {
327        return "path_create";
328    }
329
330    virtual void onPreDraw() SK_OVERRIDE {
331        this->createData(10, 100);
332        fPaths.reset(kPathCnt);
333    }
334
335    virtual void onDraw(SkCanvas*) SK_OVERRIDE {
336        for (int i = 0; i < N; ++i) {
337            this->makePath(&fPaths[i & (kPathCnt - 1)]);
338        }
339        this->restartMakingPaths();
340    }
341
342    virtual void onPostDraw() SK_OVERRIDE {
343        this->finishedMakingPaths();
344        fPaths.reset(0);
345    }
346
347private:
348    enum {
349        // must be a pow 2
350        kPathCnt = 1 << 5,
351    };
352    SkAutoTArray<SkPath> fPaths;
353
354    typedef RandomPathBench INHERITED;
355};
356
357class PathCopyBench : public RandomPathBench {
358public:
359    PathCopyBench(void* param) : INHERITED(param) {
360    }
361
362protected:
363    enum { N = SkBENCHLOOP(30000) };
364
365    virtual const char* onGetName() SK_OVERRIDE {
366        return "path_copy";
367    }
368    virtual void onPreDraw() SK_OVERRIDE {
369        this->createData(10, 100);
370        fPaths.reset(kPathCnt);
371        fCopies.reset(kPathCnt);
372        for (int i = 0; i < kPathCnt; ++i) {
373            this->makePath(&fPaths[i]);
374        }
375        this->finishedMakingPaths();
376    }
377    virtual void onDraw(SkCanvas*) SK_OVERRIDE {
378        for (int i = 0; i < N; ++i) {
379            int idx = i & (kPathCnt - 1);
380            fCopies[idx] = fPaths[idx];
381        }
382    }
383    virtual void onPostDraw() SK_OVERRIDE {
384        fPaths.reset(0);
385        fCopies.reset(0);
386    }
387
388private:
389    enum {
390        // must be a pow 2
391        kPathCnt = 1 << 5,
392    };
393    SkAutoTArray<SkPath> fPaths;
394    SkAutoTArray<SkPath> fCopies;
395
396    typedef RandomPathBench INHERITED;
397};
398
399class PathTransformBench : public RandomPathBench {
400public:
401    PathTransformBench(bool inPlace, void* param)
402        : INHERITED(param)
403        , fInPlace(inPlace) {
404    }
405
406protected:
407    enum { N = SkBENCHLOOP(30000) };
408
409    virtual const char* onGetName() SK_OVERRIDE {
410        return fInPlace ? "path_transform_in_place" : "path_transform_copy";
411    }
412
413    virtual void onPreDraw() SK_OVERRIDE {
414        fMatrix.setScale(5 * SK_Scalar1, 6 * SK_Scalar1);
415        this->createData(10, 100);
416        fPaths.reset(kPathCnt);
417        for (int i = 0; i < kPathCnt; ++i) {
418            this->makePath(&fPaths[i]);
419        }
420        this->finishedMakingPaths();
421        if (!fInPlace) {
422            fTransformed.reset(kPathCnt);
423        }
424    }
425
426    virtual void onDraw(SkCanvas*) SK_OVERRIDE {
427        if (fInPlace) {
428            for (int i = 0; i < N; ++i) {
429                fPaths[i & (kPathCnt - 1)].transform(fMatrix);
430            }
431        } else {
432            for (int i = 0; i < N; ++i) {
433                int idx = i & (kPathCnt - 1);
434                fPaths[idx].transform(fMatrix, &fTransformed[idx]);
435            }
436        }
437    }
438
439    virtual void onPostDraw() SK_OVERRIDE {
440        fPaths.reset(0);
441        fTransformed.reset(0);
442    }
443
444private:
445    enum {
446        // must be a pow 2
447        kPathCnt = 1 << 5,
448    };
449    SkAutoTArray<SkPath> fPaths;
450    SkAutoTArray<SkPath> fTransformed;
451
452    SkMatrix fMatrix;
453    bool fInPlace;
454    typedef RandomPathBench INHERITED;
455};
456
457class PathEqualityBench : public RandomPathBench {
458public:
459    PathEqualityBench(void* param)
460        : INHERITED(param) {
461    }
462
463protected:
464    enum { N = SkBENCHLOOP(40000) };
465
466    virtual const char* onGetName() SK_OVERRIDE {
467        return "path_equality_50%";
468    }
469
470    virtual void onPreDraw() SK_OVERRIDE {
471        fParity = 0;
472        this->createData(10, 100);
473        fPaths.reset(kPathCnt);
474        fCopies.reset(kPathCnt);
475        for (int i = 0; i < kPathCnt; ++i) {
476            this->makePath(&fPaths[i]);
477            fCopies[i] = fPaths[i];
478        }
479        this->finishedMakingPaths();
480    }
481
482    virtual void onDraw(SkCanvas*) SK_OVERRIDE {
483        for (int i = 0; i < N; ++i) {
484            int idx = i & (kPathCnt - 1);
485            fParity ^= (fPaths[idx] == fCopies[idx & ~0x1]);
486        }
487    }
488
489    virtual void onPostDraw() SK_OVERRIDE {
490        fPaths.reset(0);
491        fCopies.reset(0);
492    }
493
494private:
495    bool fParity; // attempt to keep compiler from optimizing out the ==
496    enum {
497        // must be a pow 2
498        kPathCnt = 1 << 5,
499    };
500    SkAutoTArray<SkPath> fPaths;
501    SkAutoTArray<SkPath> fCopies;
502    typedef RandomPathBench INHERITED;
503};
504
505class SkBench_AddPathTest : public RandomPathBench {
506public:
507    enum AddType {
508        kAdd_AddType,
509        kAddTrans_AddType,
510        kAddMatrix_AddType,
511        kPathTo_AddType,
512        kReverseAdd_AddType,
513        kReversePathTo_AddType,
514    };
515
516    SkBench_AddPathTest(AddType type, void* param)
517        : INHERITED(param)
518        , fType(type) {
519        fMatrix.setRotate(60 * SK_Scalar1);
520    }
521
522protected:
523    enum { N = SkBENCHLOOP(15000) };
524
525    virtual const char* onGetName() SK_OVERRIDE {
526        switch (fType) {
527            case kAdd_AddType:
528                return "path_add_path";
529            case kAddTrans_AddType:
530                return "path_add_path_trans";
531            case kAddMatrix_AddType:
532                return "path_add_path_matrix";
533            case kPathTo_AddType:
534                return "path_path_to";
535            case kReverseAdd_AddType:
536                return "path_reverse_add_path";
537            case kReversePathTo_AddType:
538                return "path_reverse_path_to";
539            default:
540                SkDEBUGFAIL("Bad add type");
541                return "";
542        }
543    }
544
545    virtual void onPreDraw() SK_OVERRIDE {
546        // pathTo and reversePathTo assume a single contour path.
547        bool allowMoves = kPathTo_AddType != fType &&
548                          kReversePathTo_AddType != fType;
549        this->createData(10, 100, allowMoves);
550        fPaths0.reset(kPathCnt);
551        fPaths1.reset(kPathCnt);
552        for (int i = 0; i < kPathCnt; ++i) {
553            this->makePath(&fPaths0[i]);
554            this->makePath(&fPaths1[i]);
555        }
556        this->finishedMakingPaths();
557    }
558
559    virtual void onDraw(SkCanvas*) SK_OVERRIDE {
560        switch (fType) {
561            case kAdd_AddType:
562                for (int i = 0; i < N; ++i) {
563                    int idx = i & (kPathCnt - 1);
564                    SkPath result = fPaths0[idx];
565                    result.addPath(fPaths1[idx]);
566                }
567                break;
568            case kAddTrans_AddType:
569                for (int i = 0; i < N; ++i) {
570                    int idx = i & (kPathCnt - 1);
571                    SkPath result = fPaths0[idx];
572                    result.addPath(fPaths1[idx], 2 * SK_Scalar1, 5 * SK_Scalar1);
573                }
574                break;
575            case kAddMatrix_AddType:
576                for (int i = 0; i < N; ++i) {
577                    int idx = i & (kPathCnt - 1);
578                    SkPath result = fPaths0[idx];
579                    result.addPath(fPaths1[idx], fMatrix);
580                }
581                break;
582            case kPathTo_AddType:
583                for (int i = 0; i < N; ++i) {
584                    int idx = i & (kPathCnt - 1);
585                    SkPath result = fPaths0[idx];
586                    result.pathTo(fPaths1[idx]);
587                }
588                break;
589            case kReverseAdd_AddType:
590                for (int i = 0; i < N; ++i) {
591                    int idx = i & (kPathCnt - 1);
592                    SkPath result = fPaths0[idx];
593                    result.reverseAddPath(fPaths1[idx]);
594                }
595                break;
596            case kReversePathTo_AddType:
597                for (int i = 0; i < N; ++i) {
598                    int idx = i & (kPathCnt - 1);
599                    SkPath result = fPaths0[idx];
600                    result.reversePathTo(fPaths1[idx]);
601                }
602                break;
603        }
604    }
605
606    virtual void onPostDraw() SK_OVERRIDE {
607        fPaths0.reset(0);
608        fPaths1.reset(0);
609    }
610
611private:
612    AddType fType; // or reverseAddPath
613    enum {
614        // must be a pow 2
615        kPathCnt = 1 << 5,
616    };
617    SkAutoTArray<SkPath> fPaths0;
618    SkAutoTArray<SkPath> fPaths1;
619    SkMatrix         fMatrix;
620    typedef RandomPathBench INHERITED;
621};
622
623
624class CirclesBench : public SkBenchmark {
625protected:
626    SkString            fName;
627
628    enum {
629        N = SkBENCHLOOP(100)
630    };
631public:
632    CirclesBench(void* param) : INHERITED(param) {
633        fName.printf("circles");
634    }
635
636protected:
637    virtual const char* onGetName() SK_OVERRIDE {
638        return fName.c_str();
639    }
640
641    virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
642        SkPaint paint;
643
644        paint.setColor(SK_ColorBLACK);
645        paint.setAntiAlias(true);
646
647        SkRandom rand;
648
649        SkRect r;
650
651        for (int i = 0; i < 5000; ++i) {
652            SkScalar radius = rand.nextUScalar1() * 3;
653            r.fLeft = rand.nextUScalar1() * 300;
654            r.fTop =  rand.nextUScalar1() * 300;
655            r.fRight =  r.fLeft + 2 * radius;
656            r.fBottom = r.fTop + 2 * radius;
657
658            SkPath temp;
659
660            // mimic how Chrome does circles
661            temp.arcTo(r, 0, 0, false);
662            temp.addOval(r, SkPath::kCCW_Direction);
663            temp.arcTo(r, 360, 0, true);
664            temp.close();
665
666            canvas->drawPath(temp, paint);
667        }
668    }
669
670private:
671    typedef SkBenchmark INHERITED;
672};
673
674// Chrome creates its own round rects with each corner possibly being different
675class ArbRoundRectBench : public SkBenchmark {
676protected:
677    SkString            fName;
678
679    enum {
680        N = SkBENCHLOOP(100)
681    };
682public:
683    ArbRoundRectBench(void* param) : INHERITED(param) {
684        fName.printf("arbroundrect");
685    }
686
687protected:
688    virtual const char* onGetName() SK_OVERRIDE {
689        return fName.c_str();
690    }
691
692    static void add_corner_arc(SkPath* path, const SkRect& rect,
693                               SkScalar xIn, SkScalar yIn,
694                               int startAngle)
695    {
696
697        SkScalar rx = SkMinScalar(rect.width(), xIn);
698        SkScalar ry = SkMinScalar(rect.height(), yIn);
699
700        SkRect arcRect;
701        arcRect.set(-rx, -ry, rx, ry);
702        switch (startAngle) {
703        case 0:
704            arcRect.offset(rect.fRight - arcRect.fRight, rect.fBottom - arcRect.fBottom);
705            break;
706        case 90:
707            arcRect.offset(rect.fLeft - arcRect.fLeft, rect.fBottom - arcRect.fBottom);
708            break;
709        case 180:
710            arcRect.offset(rect.fLeft - arcRect.fLeft, rect.fTop - arcRect.fTop);
711            break;
712        case 270:
713            arcRect.offset(rect.fRight - arcRect.fRight, rect.fTop - arcRect.fTop);
714            break;
715        default:
716            break;
717        }
718
719        path->arcTo(arcRect, SkIntToScalar(startAngle), SkIntToScalar(90), false);
720    }
721
722    static void make_arb_round_rect(SkPath* path, const SkRect& r,
723                                    SkScalar xCorner, SkScalar yCorner) {
724        // we are lazy here and use the same x & y for each corner
725        add_corner_arc(path, r, xCorner, yCorner, 270);
726        add_corner_arc(path, r, xCorner, yCorner, 0);
727        add_corner_arc(path, r, xCorner, yCorner, 90);
728        add_corner_arc(path, r, xCorner, yCorner, 180);
729
730        // TODO: re-enable once arcTo convexity issue is resolved
731        //SkASSERT(path->isConvex());
732    }
733
734    virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
735        SkRandom rand;
736        SkRect r;
737
738        for (int i = 0; i < 5000; ++i) {
739            SkPaint paint;
740            paint.setColor(0xff000000 | rand.nextU());
741            paint.setAntiAlias(true);
742
743            SkScalar radius = rand.nextUScalar1() * 30;
744            r.fLeft = rand.nextUScalar1() * 300;
745            r.fTop =  rand.nextUScalar1() * 300;
746            r.fRight =  r.fLeft + 2 * radius;
747            r.fBottom = r.fTop + 2 * radius;
748
749            SkPath temp;
750
751            make_arb_round_rect(&temp, r, r.width() / 10, r.height() / 15);
752
753            canvas->drawPath(temp, paint);
754        }
755    }
756
757private:
758    typedef SkBenchmark INHERITED;
759};
760
761static SkBenchmark* FactT00(void* p) { return new TrianglePathBench(p, FLAGS00); }
762static SkBenchmark* FactT01(void* p) { return new TrianglePathBench(p, FLAGS01); }
763static SkBenchmark* FactT10(void* p) { return new TrianglePathBench(p, FLAGS10); }
764static SkBenchmark* FactT11(void* p) { return new TrianglePathBench(p, FLAGS11); }
765
766static SkBenchmark* FactR00(void* p) { return new RectPathBench(p, FLAGS00); }
767static SkBenchmark* FactR01(void* p) { return new RectPathBench(p, FLAGS01); }
768static SkBenchmark* FactR10(void* p) { return new RectPathBench(p, FLAGS10); }
769static SkBenchmark* FactR11(void* p) { return new RectPathBench(p, FLAGS11); }
770
771static SkBenchmark* FactO00(void* p) { return new OvalPathBench(p, FLAGS00); }
772static SkBenchmark* FactO01(void* p) { return new OvalPathBench(p, FLAGS01); }
773static SkBenchmark* FactO10(void* p) { return new OvalPathBench(p, FLAGS10); }
774static SkBenchmark* FactO11(void* p) { return new OvalPathBench(p, FLAGS11); }
775
776static SkBenchmark* FactC00(void* p) { return new CirclePathBench(p, FLAGS00); }
777static SkBenchmark* FactC01(void* p) { return new CirclePathBench(p, FLAGS01); }
778static SkBenchmark* FactC10(void* p) { return new CirclePathBench(p, FLAGS10); }
779static SkBenchmark* FactC11(void* p) { return new CirclePathBench(p, FLAGS11); }
780
781static SkBenchmark* FactS00(void* p) { return new SawToothPathBench(p, FLAGS00); }
782static SkBenchmark* FactS01(void* p) { return new SawToothPathBench(p, FLAGS01); }
783
784static SkBenchmark* FactLC00(void* p) {
785    return new LongCurvedPathBench(p, FLAGS00);
786}
787static SkBenchmark* FactLC01(void* p) {
788    return new LongCurvedPathBench(p, FLAGS01);
789}
790
791static SkBenchmark* FactLL00(void* p) {
792    return new LongLinePathBench(p, FLAGS00);
793}
794
795static SkBenchmark* FactLL01(void* p) {
796    return new LongLinePathBench(p, FLAGS01);
797}
798
799static BenchRegistry gRegT00(FactT00);
800static BenchRegistry gRegT01(FactT01);
801static BenchRegistry gRegT10(FactT10);
802static BenchRegistry gRegT11(FactT11);
803
804static BenchRegistry gRegR00(FactR00);
805static BenchRegistry gRegR01(FactR01);
806static BenchRegistry gRegR10(FactR10);
807static BenchRegistry gRegR11(FactR11);
808
809static BenchRegistry gRegO00(FactO00);
810static BenchRegistry gRegO01(FactO01);
811static BenchRegistry gRegO10(FactO10);
812static BenchRegistry gRegO11(FactO11);
813
814static BenchRegistry gRegC00(FactC00);
815static BenchRegistry gRegC01(FactC01);
816static BenchRegistry gRegC10(FactC10);
817static BenchRegistry gRegC11(FactC11);
818
819static BenchRegistry gRegS00(FactS00);
820static BenchRegistry gRegS01(FactS01);
821
822static BenchRegistry gRegLC00(FactLC00);
823static BenchRegistry gRegLC01(FactLC01);
824
825static BenchRegistry gRegLL00(FactLL00);
826static BenchRegistry gRegLL01(FactLL01);
827
828static SkBenchmark* FactCreate(void* p) { return new PathCreateBench(p); }
829static BenchRegistry gRegCreate(FactCreate);
830
831static SkBenchmark* FactCopy(void* p) { return new PathCopyBench(p); }
832static BenchRegistry gRegCopy(FactCopy);
833
834static SkBenchmark* FactPathTransformInPlace(void* p) { return new PathTransformBench(true, p); }
835static BenchRegistry gRegPathTransformInPlace(FactPathTransformInPlace);
836
837static SkBenchmark* FactPathTransformCopy(void* p) { return new PathTransformBench(false, p); }
838static BenchRegistry gRegPathTransformCopy(FactPathTransformCopy);
839
840static SkBenchmark* FactEquality(void* p) { return new PathEqualityBench(p); }
841static BenchRegistry gRegEquality(FactEquality);
842
843static SkBenchmark* FactAdd(void* p) { return new SkBench_AddPathTest(SkBench_AddPathTest::kAdd_AddType, p); }
844static SkBenchmark* FactAddTrans(void* p) { return new SkBench_AddPathTest(SkBench_AddPathTest::kAddTrans_AddType, p); }
845static SkBenchmark* FactAddMatrix(void* p) { return new SkBench_AddPathTest(SkBench_AddPathTest::kAddMatrix_AddType, p); }
846static SkBenchmark* FactPathTo(void* p) { return new SkBench_AddPathTest(SkBench_AddPathTest::kPathTo_AddType, p); }
847static SkBenchmark* FactReverseAdd(void* p) { return new SkBench_AddPathTest(SkBench_AddPathTest::kReverseAdd_AddType, p); }
848static SkBenchmark* FactReverseTo(void* p) { return new SkBench_AddPathTest(SkBench_AddPathTest::kReversePathTo_AddType, p); }
849
850static BenchRegistry gRegAdd(FactAdd);
851static BenchRegistry gRegAddTrans(FactAddTrans);
852static BenchRegistry gRegAddMatrix(FactAddMatrix);
853static BenchRegistry gRegPathTo(FactPathTo);
854static BenchRegistry gRegReverseAdd(FactReverseAdd);
855static BenchRegistry gRegReverseTo(FactReverseTo);
856
857static SkBenchmark* CirclesTest(void* p) { return new CirclesBench(p); }
858static BenchRegistry gRegCirclesTest(CirclesTest);
859
860static SkBenchmark* ArbRoundRectTest(void* p) { return new ArbRoundRectBench(p); }
861static BenchRegistry gRegArbRoundRectTest(ArbRoundRectTest);
862