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
test_clearonlayers(SkCanvas * canvas)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(nullptr, nullptr);
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
test_strokerect(SkCanvas * canvas,const SkRect & r)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
test_strokerect(SkCanvas * canvas)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:
Draw()89 Draw() : fFlags(0) {}
90
91 enum Flags {
92 kSelected_Flag = 1 << 0
93 };
getFlags() const94 int getFlags() const { return fFlags; }
95 void setFlags(int flags);
96
isSelected() const97 bool isSelected() const { return SkToBool(fFlags & kSelected_Flag); }
setSelected(bool pred)98 void setSelected(bool pred) {
99 if (pred) {
100 fFlags |= kSelected_Flag;
101 } else {
102 fFlags &= ~kSelected_Flag;
103 }
104 }
105
draw(SkCanvas * canvas)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
drawSelection(SkCanvas * canvas)116 void drawSelection(SkCanvas* canvas) {
117 int sc = canvas->save();
118 this->onDrawSelection(canvas);
119 canvas->restoreToCount(sc);
120 }
121
getBounds(SkRect * bounds)122 void getBounds(SkRect* bounds) {
123 this->onGetBounds(bounds);
124 }
125
hitTest(SkScalar x,SkScalar y)126 bool hitTest(SkScalar x, SkScalar y) {
127 return this->onHitTest(x, y);
128 }
129
offset(SkScalar dx,SkScalar dy)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;
onDrawSelection(SkCanvas * canvas)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 }
onHitTest(SkScalar x,SkScalar y)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
RDraw(const SkRect & r,Style s)170 RDraw(const SkRect& r, Style s) : fRect(r), fStyle(s) {}
171
setRect(const SkRect & r)172 void setRect(const SkRect& r) {
173 fRect = r;
174 }
175
setPaint(const SkPaint & p)176 void setPaint(const SkPaint& p) {
177 fPaint = p;
178 }
179
180 protected:
onDraw(SkCanvas * canvas)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
onGetBounds(SkRect * bounds)212 virtual void onGetBounds(SkRect* bounds) {
213 *bounds = fRect;
214 }
215
onOffset(SkScalar dx,SkScalar dy)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:
DrawFactory()228 DrawFactory() {
229 fPaint.setAntiAlias(true);
230 }
231
getPaint() const232 const SkPaint& getPaint() const { return fPaint; }
233
setPaint(const SkPaint & p)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:
create(const SkPoint & p0,const SkPoint & p1)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:
DrawView()265 DrawView() : fDraw(nullptr) {
266 fFactory = new RectFactory;
267 }
268
~DrawView()269 virtual ~DrawView() {
270 fList.unrefAll();
271 SkSafeUnref(fDraw);
272 delete fFactory;
273 }
274
setDraw(Draw * d)275 Draw* setDraw(Draw* d) {
276 SkRefCnt_SafeAssign(fDraw, d);
277 return d;
278 }
279
randColor()280 SkColor randColor() {
281 return (SkColor)fRand.nextU() | 0xFF000000;
282 }
283
hitTestList(SkScalar x,SkScalar y) const284 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 nullptr;
293 }
294
295 protected:
296 // overrides from SkEventSink
onQuery(SkEvent * evt)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
drawBG(SkCanvas * canvas)305 void drawBG(SkCanvas* canvas) {
306 canvas->drawColor(0xFFDDDDDD);
307 // canvas->drawColor(SK_ColorWHITE);
308 }
309
onDraw(SkCanvas * canvas)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
onFindClickHandler(SkScalar x,SkScalar y)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
onClick(Click * click)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 = nullptr;
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(nullptr);
369 return true;
370 }
371
372 private:
373 typedef SkView INHERITED;
374 };
375
376 //////////////////////////////////////////////////////////////////////////////
377
MyFactory()378 static SkView* MyFactory() { return new DrawView; }
379 static SkViewRegister reg(MyFactory);
380