DashBench.cpp revision fbfcd5602128ec010c82cb733c9cdc0a3254f9f3
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 SkPoint fPts[2]; 38 bool fDoClip; 39 40 enum { 41 N = SkBENCHLOOP(100) 42 }; 43public: 44 DashBench(void* param, const SkScalar intervals[], int count, int width, 45 bool doClip = false) : INHERITED(param) { 46 fIntervals.append(count, intervals); 47 for (int i = 0; i < count; ++i) { 48 fIntervals[i] *= width; 49 } 50 fWidth = width; 51 fName.printf("dash_%d_%s", width, doClip ? "clipped" : "noclip"); 52 fDoClip = doClip; 53 54 fPts[0].set(SkIntToScalar(10), SkIntToScalar(10)); 55 fPts[1].set(SkIntToScalar(600), SkIntToScalar(10)); 56 } 57 58 virtual void makePath(SkPath* path) { 59 path_hline(path); 60 } 61 62protected: 63 virtual const char* onGetName() SK_OVERRIDE { 64 return fName.c_str(); 65 } 66 67 virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE { 68 SkPaint paint; 69 this->setupPaint(&paint); 70 paint.setStyle(SkPaint::kStroke_Style); 71 paint.setStrokeWidth(SkIntToScalar(fWidth)); 72 paint.setAntiAlias(false); 73 74 SkPath path; 75 this->makePath(&path); 76 77 paint.setPathEffect(new SkDashPathEffect(fIntervals.begin(), 78 fIntervals.count(), 0))->unref(); 79 80 if (fDoClip) { 81 SkRect r = path.getBounds(); 82 r.inset(-SkIntToScalar(20), -SkIntToScalar(20)); 83 // now move it so we don't intersect 84 r.offset(0, r.height() * 3 / 2); 85 canvas->clipRect(r); 86 } 87 88 this->handlePath(canvas, path, paint, N); 89 } 90 91 virtual void handlePath(SkCanvas* canvas, const SkPath& path, 92 const SkPaint& paint, int N) { 93 for (int i = 0; i < N; ++i) { 94// canvas->drawPoints(SkCanvas::kLines_PointMode, 2, fPts, paint); 95 canvas->drawPath(path, paint); 96 } 97 } 98 99private: 100 typedef SkBenchmark INHERITED; 101}; 102 103class RectDashBench : public DashBench { 104public: 105 RectDashBench(void* param, const SkScalar intervals[], int count, int width, bool doClip = false) 106 : INHERITED(param, intervals, count, width) { 107 fName.append("_rect"); 108 } 109 110protected: 111 virtual void handlePath(SkCanvas* canvas, const SkPath& path, 112 const SkPaint& paint, int N) SK_OVERRIDE { 113 SkPoint pts[2]; 114 if (!path.isLine(pts) || pts[0].fY != pts[1].fY) { 115 this->INHERITED::handlePath(canvas, path, paint, N); 116 } else { 117 SkRect rect; 118 rect.fLeft = pts[0].fX; 119 rect.fTop = pts[0].fY - paint.getStrokeWidth() / 2; 120 rect.fRight = rect.fLeft + SkIntToScalar(fWidth); 121 rect.fBottom = rect.fTop + paint.getStrokeWidth(); 122 123 SkPaint p(paint); 124 p.setStyle(SkPaint::kFill_Style); 125 p.setPathEffect(NULL); 126 127 int count = SkScalarRoundToInt((pts[1].fX - pts[0].fX) / (2*fWidth)); 128 SkScalar dx = SkIntToScalar(2 * fWidth); 129 130 for (int i = 0; i < N*10; ++i) { 131 SkRect r = rect; 132 for (int j = 0; j < count; ++j) { 133 canvas->drawRect(r, p); 134 r.offset(dx, 0); 135 } 136 } 137 } 138 } 139 140private: 141 typedef DashBench INHERITED; 142}; 143 144static void make_unit_star(SkPath* path, int n) { 145 SkScalar rad = -SK_ScalarPI / 2; 146 const SkScalar drad = (n >> 1) * SK_ScalarPI * 2 / n; 147 148 path->moveTo(0, -SK_Scalar1); 149 for (int i = 1; i < n; i++) { 150 rad += drad; 151 SkScalar cosV, sinV = SkScalarSinCos(rad, &cosV); 152 path->lineTo(cosV, sinV); 153 } 154 path->close(); 155} 156 157static void make_poly(SkPath* path) { 158 make_unit_star(path, 9); 159 SkMatrix matrix; 160 matrix.setScale(SkIntToScalar(100), SkIntToScalar(100)); 161 path->transform(matrix); 162} 163 164static void make_quad(SkPath* path) { 165 SkScalar x0 = SkIntToScalar(10); 166 SkScalar y0 = SkIntToScalar(10); 167 path->moveTo(x0, y0); 168 path->quadTo(x0, y0 + 400 * SK_Scalar1, 169 x0 + 600 * SK_Scalar1, y0 + 400 * SK_Scalar1); 170} 171 172static void make_cubic(SkPath* path) { 173 SkScalar x0 = SkIntToScalar(10); 174 SkScalar y0 = SkIntToScalar(10); 175 path->moveTo(x0, y0); 176 path->cubicTo(x0, y0 + 400 * SK_Scalar1, 177 x0 + 600 * SK_Scalar1, y0 + 400 * SK_Scalar1, 178 x0 + 600 * SK_Scalar1, y0); 179} 180 181class MakeDashBench : public SkBenchmark { 182 SkString fName; 183 SkPath fPath; 184 SkAutoTUnref<SkPathEffect> fPE; 185 186 enum { 187 N = SkBENCHLOOP(400) 188 }; 189 190public: 191 MakeDashBench(void* param, void (*proc)(SkPath*), const char name[]) : INHERITED(param) { 192 fName.printf("makedash_%s", name); 193 proc(&fPath); 194 195 SkScalar vals[] = { SkIntToScalar(4), SkIntToScalar(4) }; 196 fPE.reset(new SkDashPathEffect(vals, 2, 0)); 197 } 198 199protected: 200 virtual const char* onGetName() SK_OVERRIDE { 201 return fName.c_str(); 202 } 203 204 virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE { 205 SkPath dst; 206 for (int i = 0; i < N; ++i) { 207 SkStrokeRec rec(SkStrokeRec::kHairline_InitStyle); 208 209 fPE->filterPath(&dst, fPath, &rec); 210 dst.rewind(); 211 } 212 } 213 214private: 215 typedef SkBenchmark INHERITED; 216}; 217 218/////////////////////////////////////////////////////////////////////////////// 219 220static const SkScalar gDots[] = { SK_Scalar1, SK_Scalar1 }; 221 222#define PARAM(array) array, SK_ARRAY_COUNT(array) 223 224static SkBenchmark* gF0(void* p) { return new DashBench(p, PARAM(gDots), 0); } 225static SkBenchmark* gF1(void* p) { return new DashBench(p, PARAM(gDots), 1); } 226static SkBenchmark* gF2(void* p) { return new DashBench(p, PARAM(gDots), 1, true); } 227static SkBenchmark* gF3(void* p) { return new DashBench(p, PARAM(gDots), 4); } 228static SkBenchmark* gF4(void* p) { return new MakeDashBench(p, make_poly, "poly"); } 229static SkBenchmark* gF5(void* p) { return new MakeDashBench(p, make_quad, "quad"); } 230static SkBenchmark* gF6(void* p) { return new MakeDashBench(p, make_cubic, "cubic"); } 231 232static BenchRegistry gR0(gF0); 233static BenchRegistry gR1(gF1); 234static BenchRegistry gR2(gF2); 235static BenchRegistry gR3(gF3); 236static BenchRegistry gR4(gF4); 237static BenchRegistry gR5(gF5); 238static BenchRegistry gR6(gF6); 239