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 "SampleCode.h" 9 #include "SkView.h" 10 #include "SkCanvas.h" 11 #include "SkGraphics.h" 12 #include "SkRandom.h" 13 14 static void test_clearonlayers(SkCanvas* canvas) { 15 SkCanvas& c = *canvas; 16 17 SkPaint paint; 18 paint.setColor(SK_ColorBLUE); 19 paint.setStyle(SkPaint::kStrokeAndFill_Style); 20 SkRect rect = SkRect::MakeXYWH(25, 25, 50, 50); 21 c.drawRect(rect, paint); 22 23 c.clipRect(rect); 24 25 c.saveLayer(NULL, NULL); 26 rect = SkRect::MakeXYWH(50, 10, 40, 80); 27 c.clipRect(rect, SkRegion::kUnion_Op); 28 29 rect = SkRect::MakeXYWH(50, 0, 50, 100); 30 // You might draw something here, but it's not necessary. 31 // paint.setColor(SK_ColorRED); 32 // c.drawRect(rect, paint); 33 paint.setXfermodeMode(SkXfermode::kClear_Mode); 34 c.drawRect(rect, paint); 35 c.restore(); 36 } 37 38 static void test_strokerect(SkCanvas* canvas, const SkRect& r) { 39 SkPaint p; 40 41 p.setAntiAlias(true); 42 p.setStyle(SkPaint::kStroke_Style); 43 p.setStrokeWidth(4); 44 45 canvas->drawRect(r, p); 46 47 SkPath path; 48 SkRect r2(r); 49 r2.offset(18, 0); 50 path.addRect(r2); 51 52 canvas->drawPath(path, p); 53 } 54 55 static void test_strokerect(SkCanvas* canvas) { 56 canvas->drawColor(SK_ColorWHITE); 57 58 SkRect r; 59 60 r.set(10, 10, 14, 14); 61 r.offset(0.25f, 0.3333f); 62 test_strokerect(canvas, r); 63 canvas->translate(0, 20); 64 65 r.set(10, 10, 14.5f, 14.5f); 66 r.offset(0.25f, 0.3333f); 67 test_strokerect(canvas, r); 68 canvas->translate(0, 20); 69 70 r.set(10, 10, 14.5f, 20); 71 r.offset(0.25f, 0.3333f); 72 test_strokerect(canvas, r); 73 canvas->translate(0, 20); 74 75 r.set(10, 10, 20, 14.5f); 76 r.offset(0.25f, 0.3333f); 77 test_strokerect(canvas, r); 78 canvas->translate(0, 20); 79 80 r.set(10, 10, 20, 20); 81 r.offset(0.25f, 0.3333f); 82 test_strokerect(canvas, r); 83 canvas->translate(0, 20); 84 85 } 86 87 class Draw : public SkRefCnt { 88 public: 89 Draw() : fFlags(0) {} 90 91 enum Flags { 92 kSelected_Flag = 1 << 0 93 }; 94 int getFlags() const { return fFlags; } 95 void setFlags(int flags); 96 97 bool isSelected() const { return SkToBool(fFlags & kSelected_Flag); } 98 void setSelected(bool pred) { 99 if (pred) { 100 fFlags |= kSelected_Flag; 101 } else { 102 fFlags &= ~kSelected_Flag; 103 } 104 } 105 106 void draw(SkCanvas* canvas) { 107 int sc = canvas->save(); 108 this->onDraw(canvas); 109 canvas->restoreToCount(sc); 110 111 if (this->isSelected()) { 112 this->drawSelection(canvas); 113 } 114 } 115 116 void drawSelection(SkCanvas* canvas) { 117 int sc = canvas->save(); 118 this->onDrawSelection(canvas); 119 canvas->restoreToCount(sc); 120 } 121 122 void getBounds(SkRect* bounds) { 123 this->onGetBounds(bounds); 124 } 125 126 bool hitTest(SkScalar x, SkScalar y) { 127 return this->onHitTest(x, y); 128 } 129 130 void offset(SkScalar dx, SkScalar dy) { 131 if (dx || dy) { 132 this->onOffset(dx, dy); 133 } 134 } 135 136 protected: 137 virtual void onDraw(SkCanvas*) = 0; 138 virtual void onGetBounds(SkRect*) = 0; 139 virtual void onOffset(SkScalar dx, SkScalar dy) = 0; 140 virtual void onDrawSelection(SkCanvas* canvas) { 141 SkRect r; 142 this->getBounds(&r); 143 SkPaint paint; 144 SkPoint pts[4]; 145 r.toQuad(pts); 146 paint.setStrokeWidth(SkIntToScalar(10)); 147 paint.setColor(0x80FF8844); 148 paint.setStrokeCap(SkPaint::kRound_Cap); 149 canvas->drawPoints(SkCanvas::kPoints_PointMode, 4, pts, paint); 150 } 151 virtual bool onHitTest(SkScalar x, SkScalar y) { 152 SkRect bounds; 153 this->getBounds(&bounds); 154 return bounds.contains(x, y); 155 } 156 157 private: 158 int fFlags; 159 }; 160 161 class RDraw : public Draw { 162 public: 163 enum Style { 164 kRect_Style, 165 kOval_Style, 166 kRRect_Style, 167 kFrame_Style 168 }; 169 170 RDraw(const SkRect& r, Style s) : fRect(r), fStyle(s) {} 171 172 void setRect(const SkRect& r) { 173 fRect = r; 174 } 175 176 void setPaint(const SkPaint& p) { 177 fPaint = p; 178 } 179 180 protected: 181 virtual void onDraw(SkCanvas* canvas) { 182 switch (fStyle) { 183 case kRect_Style: 184 canvas->drawRect(fRect, fPaint); 185 break; 186 case kOval_Style: 187 canvas->drawOval(fRect, fPaint); 188 break; 189 case kRRect_Style: { 190 SkScalar rx = fRect.width() / 5; 191 SkScalar ry = fRect.height() / 5; 192 if (rx < ry) { 193 ry = rx; 194 } else { 195 rx = ry; 196 } 197 canvas->drawRoundRect(fRect, rx, ry, fPaint); 198 break; 199 } 200 case kFrame_Style: { 201 SkPath path; 202 path.addOval(fRect, SkPath::kCW_Direction); 203 SkRect r = fRect; 204 r.inset(fRect.width()/6, 0); 205 path.addOval(r, SkPath::kCCW_Direction); 206 canvas->drawPath(path, fPaint); 207 break; 208 } 209 } 210 } 211 212 virtual void onGetBounds(SkRect* bounds) { 213 *bounds = fRect; 214 } 215 216 virtual void onOffset(SkScalar dx, SkScalar dy) { 217 fRect.offset(dx, dy); 218 } 219 220 private: 221 SkRect fRect; 222 SkPaint fPaint; 223 Style fStyle; 224 }; 225 226 class DrawFactory { 227 public: 228 DrawFactory() { 229 fPaint.setAntiAlias(true); 230 } 231 232 const SkPaint& getPaint() const { return fPaint; } 233 234 void setPaint(const SkPaint& p) { 235 fPaint = p; 236 } 237 238 virtual Draw* create(const SkPoint&, const SkPoint&) = 0; 239 240 private: 241 SkPaint fPaint; 242 }; 243 244 class RectFactory : public DrawFactory { 245 public: 246 virtual Draw* create(const SkPoint& p0, const SkPoint& p1) { 247 SkRect r; 248 r.set(p0.x(), p0.y(), p1.x(), p1.y()); 249 r.sort(); 250 251 // RDraw* d = new RDraw(r, RDraw::kRRect_Style); 252 RDraw* d = new RDraw(r, RDraw::kFrame_Style); 253 d->setPaint(this->getPaint()); 254 return d; 255 } 256 }; 257 258 class DrawView : public SkView { 259 Draw* fDraw; 260 DrawFactory* fFactory; 261 SkRandom fRand; 262 SkTDArray<Draw*> fList; 263 264 public: 265 DrawView() : fDraw(NULL) { 266 fFactory = new RectFactory; 267 } 268 269 virtual ~DrawView() { 270 fList.unrefAll(); 271 SkSafeUnref(fDraw); 272 delete fFactory; 273 } 274 275 Draw* setDraw(Draw* d) { 276 SkRefCnt_SafeAssign(fDraw, d); 277 return d; 278 } 279 280 SkColor randColor() { 281 return (SkColor)fRand.nextU() | 0xFF000000; 282 } 283 284 Draw* hitTestList(SkScalar x, SkScalar y) const { 285 Draw** first = fList.begin(); 286 for (Draw** iter = fList.end(); iter > first;) { 287 --iter; 288 if ((*iter)->hitTest(x, y)) { 289 return *iter; 290 } 291 } 292 return NULL; 293 } 294 295 protected: 296 // overrides from SkEventSink 297 virtual bool onQuery(SkEvent* evt) { 298 if (SampleCode::TitleQ(*evt)) { 299 SampleCode::TitleR(evt, "Draw"); 300 return true; 301 } 302 return this->INHERITED::onQuery(evt); 303 } 304 305 void drawBG(SkCanvas* canvas) { 306 canvas->drawColor(0xFFDDDDDD); 307 // canvas->drawColor(SK_ColorWHITE); 308 } 309 310 virtual void onDraw(SkCanvas* canvas) { 311 this->drawBG(canvas); 312 test_clearonlayers(canvas); return; 313 // test_strokerect(canvas); return; 314 315 for (Draw** iter = fList.begin(); iter < fList.end(); iter++) { 316 (*iter)->draw(canvas); 317 } 318 if (fDraw) { 319 fDraw->draw(canvas); 320 } 321 } 322 323 virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y) { 324 for (Draw** iter = fList.begin(); iter < fList.end(); iter++) { 325 (*iter)->setSelected(false); 326 } 327 328 Click* c = new Click(this); 329 Draw* d = this->hitTestList(x, y); 330 if (d) { 331 d->setSelected(true); 332 c->setType("dragger"); 333 } else { 334 c->setType("maker"); 335 } 336 return c; 337 } 338 339 virtual bool onClick(Click* click) { 340 if (Click::kUp_State == click->fState) { 341 if (click->isType("maker")) { 342 if (SkPoint::Distance(click->fOrig, click->fCurr) > SkIntToScalar(3)) { 343 *fList.append() = fDraw; 344 } else { 345 fDraw->unref(); 346 } 347 fDraw = NULL; 348 } 349 return true; 350 } 351 352 if (Click::kDown_State == click->fState) { 353 SkPaint p = fFactory->getPaint(); 354 p.setColor(this->randColor()); 355 fFactory->setPaint(p); 356 } 357 358 if (click->isType("maker")) { 359 this->setDraw(fFactory->create(click->fOrig, click->fCurr))->unref(); 360 } else if (click->isType("dragger")) { 361 for (Draw** iter = fList.begin(); iter < fList.end(); iter++) { 362 if ((*iter)->isSelected()) { 363 (*iter)->offset(click->fCurr.x() - click->fPrev.x(), 364 click->fCurr.y() - click->fPrev.y()); 365 } 366 } 367 } 368 this->inval(NULL); 369 return true; 370 } 371 372 private: 373 typedef SkView INHERITED; 374 }; 375 376 ////////////////////////////////////////////////////////////////////////////// 377 378 static SkView* MyFactory() { return new DrawView; } 379 static SkViewRegister reg(MyFactory); 380