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