• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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