convexpaths.cpp revision a51ab8416db9772a2eae3122f4f69801642daeb5
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 "gm.h" 9#include "SkRandom.h" 10#include "SkTArray.h" 11 12class SkOnce : SkNoncopyable { 13public: 14 SkOnce() { fDidOnce = false; } 15 16 bool needToDo() const { return !fDidOnce; } 17 bool alreadyDone() const { return fDidOnce; } 18 void accomplished() { 19 SkASSERT(!fDidOnce); 20 fDidOnce = true; 21 } 22 23private: 24 bool fDidOnce; 25}; 26 27namespace skiagm { 28 29class ConvexPathsGM : public GM { 30 SkOnce fOnce; 31public: 32 ConvexPathsGM() { 33 this->setBGColor(0xFF000000); 34 } 35 36protected: 37 virtual SkString onShortName() { 38 return SkString("convexpaths"); 39 } 40 41 42 virtual SkISize onISize() { 43 return make_isize(1200, 900); 44 } 45 46 void makePaths() { 47 if (fOnce.alreadyDone()) { 48 return; 49 } 50 fOnce.accomplished(); 51 52 // CW 53 fPaths.push_back().moveTo(0, 0); 54 fPaths.back().quadTo(50 * SK_Scalar1, 100 * SK_Scalar1, 55 0, 100 * SK_Scalar1); 56 fPaths.back().lineTo(0, 0); 57 58 // CCW 59 fPaths.push_back().moveTo(0, 0); 60 fPaths.back().lineTo(0, 100 * SK_Scalar1); 61 fPaths.back().quadTo(50 * SK_Scalar1, 100 * SK_Scalar1, 62 0, 0); 63 64 // CW 65 fPaths.push_back().moveTo(0, 50 * SK_Scalar1); 66 fPaths.back().quadTo(50 * SK_Scalar1, 0, 67 100 * SK_Scalar1, 50 * SK_Scalar1); 68 fPaths.back().quadTo(50 * SK_Scalar1, 100 * SK_Scalar1, 69 0, 50 * SK_Scalar1); 70 71 // CCW 72 fPaths.push_back().moveTo(0, 50 * SK_Scalar1); 73 fPaths.back().quadTo(50 * SK_Scalar1, 100 * SK_Scalar1, 74 100 * SK_Scalar1, 50 * SK_Scalar1); 75 fPaths.back().quadTo(50 * SK_Scalar1, 0, 76 0, 50 * SK_Scalar1); 77 78 fPaths.push_back().addRect(0, 0, 79 100 * SK_Scalar1, 100 * SK_Scalar1, 80 SkPath::kCW_Direction); 81 82 fPaths.push_back().addRect(0, 0, 83 100 * SK_Scalar1, 100 * SK_Scalar1, 84 SkPath::kCCW_Direction); 85 86 fPaths.push_back().addCircle(50 * SK_Scalar1, 50 * SK_Scalar1, 87 50 * SK_Scalar1, SkPath::kCW_Direction); 88 89 fPaths.push_back().addCircle(50 * SK_Scalar1, 50 * SK_Scalar1, 90 40 * SK_Scalar1, SkPath::kCCW_Direction); 91 92 fPaths.push_back().addOval(SkRect::MakeXYWH(0, 0, 93 50 * SK_Scalar1, 94 100 * SK_Scalar1), 95 SkPath::kCW_Direction); 96 97 fPaths.push_back().addOval(SkRect::MakeXYWH(0, 0, 98 100 * SK_Scalar1, 99 50 * SK_Scalar1), 100 SkPath::kCCW_Direction); 101 102 fPaths.push_back().addOval(SkRect::MakeXYWH(0, 0, 103 100 * SK_Scalar1, 104 5 * SK_Scalar1), 105 SkPath::kCCW_Direction); 106 107 fPaths.push_back().addOval(SkRect::MakeXYWH(0, 0, 108 SK_Scalar1, 109 100 * SK_Scalar1), 110 SkPath::kCCW_Direction); 111 112 fPaths.push_back().addRoundRect(SkRect::MakeXYWH(0, 0, 113 SK_Scalar1 * 100, 114 SK_Scalar1 * 100), 115 40 * SK_Scalar1, 20 * SK_Scalar1, 116 SkPath::kCW_Direction); 117 118 fPaths.push_back().addRoundRect(SkRect::MakeXYWH(0, 0, 119 SK_Scalar1 * 100, 120 SK_Scalar1 * 100), 121 20 * SK_Scalar1, 40 * SK_Scalar1, 122 SkPath::kCCW_Direction); 123 124 // shallow diagonals 125 fPaths.push_back().lineTo(100 * SK_Scalar1, SK_Scalar1); 126 fPaths.back().lineTo(98 * SK_Scalar1, 100 * SK_Scalar1); 127 fPaths.back().lineTo(3 * SK_Scalar1, 96 * SK_Scalar1); 128 129 /* 130 It turns out arcTos are not automatically marked as convex and they 131 may in fact be ever so slightly concave. 132 fPaths.push_back().arcTo(SkRect::MakeXYWH(0, 0, 133 50 * SK_Scalar1, 134 100 * SK_Scalar1), 135 25 * SK_Scalar1, 130 * SK_Scalar1, false); 136 */ 137 // cubics 138 fPaths.push_back().cubicTo( 1 * SK_Scalar1, 1 * SK_Scalar1, 139 10 * SK_Scalar1, 90 * SK_Scalar1, 140 0 * SK_Scalar1, 100 * SK_Scalar1); 141 fPaths.push_back().cubicTo(100 * SK_Scalar1, 50 * SK_Scalar1, 142 20 * SK_Scalar1, 100 * SK_Scalar1, 143 0 * SK_Scalar1, 0 * SK_Scalar1); 144 145 // path that has a cubic with a repeated first control point and 146 // a repeated last control point. 147 fPaths.push_back().moveTo(SK_Scalar1 * 10, SK_Scalar1 * 10); 148 fPaths.back().cubicTo(10 * SK_Scalar1, 10 * SK_Scalar1, 149 10 * SK_Scalar1, 0, 150 20 * SK_Scalar1, 0); 151 fPaths.back().lineTo(40 * SK_Scalar1, 0); 152 fPaths.back().cubicTo(40 * SK_Scalar1, 0, 153 50 * SK_Scalar1, 0, 154 50 * SK_Scalar1, 10 * SK_Scalar1); 155 156 // path that has two cubics with repeated middle control points. 157 fPaths.push_back().moveTo(SK_Scalar1 * 10, SK_Scalar1 * 10); 158 fPaths.back().cubicTo(10 * SK_Scalar1, 0, 159 10 * SK_Scalar1, 0, 160 20 * SK_Scalar1, 0); 161 fPaths.back().lineTo(40 * SK_Scalar1, 0); 162 fPaths.back().cubicTo(50 * SK_Scalar1, 0, 163 50 * SK_Scalar1, 0, 164 50 * SK_Scalar1, 10 * SK_Scalar1); 165 166 // triangle where one edge is a degenerate quad 167 fPaths.push_back().moveTo(SkFloatToScalar(8.59375f), 45 * SK_Scalar1); 168 fPaths.back().quadTo(SkFloatToScalar(16.9921875f), 45 * SK_Scalar1, 169 SkFloatToScalar(31.25f), 45 * SK_Scalar1); 170 fPaths.back().lineTo(100 * SK_Scalar1, 100 * SK_Scalar1); 171 fPaths.back().lineTo(SkFloatToScalar(8.59375f), 45 * SK_Scalar1); 172 173 // point degenerate 174 fPaths.push_back().moveTo(50 * SK_Scalar1, 50 * SK_Scalar1); 175 fPaths.back().lineTo(50 * SK_Scalar1, 50 * SK_Scalar1); 176 177 fPaths.push_back().moveTo(50 * SK_Scalar1, 50 * SK_Scalar1); 178 fPaths.back().quadTo(50 * SK_Scalar1, 50 * SK_Scalar1, 179 50 * SK_Scalar1, 50 * SK_Scalar1); 180 fPaths.push_back().moveTo(50 * SK_Scalar1, 50 * SK_Scalar1); 181 fPaths.back().cubicTo(50 * SK_Scalar1, 50 * SK_Scalar1, 182 50 * SK_Scalar1, 50 * SK_Scalar1, 183 50 * SK_Scalar1, 50 * SK_Scalar1); 184 185 // moveTo only paths 186 fPaths.push_back().moveTo(0, 0); 187 fPaths.back().moveTo(0, 0); 188 fPaths.back().moveTo(SK_Scalar1, SK_Scalar1); 189 fPaths.back().moveTo(SK_Scalar1, SK_Scalar1); 190 fPaths.back().moveTo(10 * SK_Scalar1, 10 * SK_Scalar1); 191 192 fPaths.push_back().moveTo(0, 0); 193 fPaths.back().moveTo(0, 0); 194 195 // line degenerate 196 fPaths.push_back().lineTo(100 * SK_Scalar1, 100 * SK_Scalar1); 197 fPaths.push_back().quadTo(100 * SK_Scalar1, 100 * SK_Scalar1, 0, 0); 198 fPaths.push_back().quadTo(100 * SK_Scalar1, 100 * SK_Scalar1, 199 50 * SK_Scalar1, 50 * SK_Scalar1); 200 fPaths.push_back().quadTo(50 * SK_Scalar1, 50 * SK_Scalar1, 201 100 * SK_Scalar1, 100 * SK_Scalar1); 202 fPaths.push_back().cubicTo(0, 0, 203 0, 0, 204 100 * SK_Scalar1, 100 * SK_Scalar1); 205 206 // small circle. This is listed last so that it has device coords far 207 // from the origin (small area relative to x,y values). 208 fPaths.push_back().addCircle(0, 0, SkFloatToScalar(0.8f)); 209 } 210 211 virtual void onDraw(SkCanvas* canvas) { 212 this->makePaths(); 213 214 SkPaint paint; 215 paint.setAntiAlias(true); 216 SkRandom rand; 217 canvas->translate(20 * SK_Scalar1, 20 * SK_Scalar1); 218 for (int i = 0; i < fPaths.count(); ++i) { 219 canvas->save(); 220 // position the path, and make it at off-integer coords. 221 canvas->translate(SK_Scalar1 * 200 * (i % 5) + SK_Scalar1 / 4, 222 SK_Scalar1 * 200 * (i / 5) + 3 * SK_Scalar1 / 4); 223 SkColor color = rand.nextU(); 224 color |= 0xff000000; 225 paint.setColor(color); 226 SkASSERT(fPaths[i].isConvex()); 227 canvas->drawPath(fPaths[i], paint); 228 canvas->restore(); 229 } 230 } 231 232private: 233 typedef GM INHERITED; 234 SkTArray<SkPath> fPaths; 235}; 236 237////////////////////////////////////////////////////////////////////////////// 238 239static GM* MyFactory(void*) { return new ConvexPathsGM; } 240static GMRegistry reg(MyFactory); 241 242} 243 244