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