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 |