• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2015 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 
8 #include "SampleCode.h"
9 #include "SkAnimTimer.h"
10 #include "SkDrawable.h"
11 #include "SkView.h"
12 #include "SkCanvas.h"
13 #include "SkDrawable.h"
14 #include "SkPath.h"
15 #include "SkRandom.h"
16 #include "SkRSXform.h"
17 #include "SkSurface.h"
18 #include "SkGradientShader.h"
19 
20 const SkBlendMode gModes[] = {
21     SkBlendMode::kSrcOver,
22     SkBlendMode::kSrc,
23     SkBlendMode::kSrcIn,
24     SkBlendMode::kSrcOut,
25     SkBlendMode::kSrcATop,
26     SkBlendMode::kDstOver,
27     SkBlendMode::kDstIn,
28     SkBlendMode::kDstOut,
29     SkBlendMode::kDstATop,
30 };
31 const int N_Modes = SK_ARRAY_COUNT(gModes);
32 
33 class HasEventWig : public SkView {
34 public:
postWidgetEvent()35     void postWidgetEvent() {
36         SkEvent evt;
37         this->onPrepareWidEvent(&evt);
38         this->postToListeners(evt, 0);
39     }
40 
41 protected:
onPrepareWidEvent(SkEvent *)42     virtual void onPrepareWidEvent(SkEvent*) {}
43 };
44 
45 static SkRandom gRand;
46 
47 class PushButtonWig : public HasEventWig {
48     SkString fLabel;
49     SkColor  fColor;
50     uint32_t fFast32;
51 
52 public:
PushButtonWig(const char label[],uint32_t fast)53     PushButtonWig(const char label[], uint32_t fast) : fLabel(label) {
54         fColor = (gRand.nextU() & 0x7F7F7F7F) | SkColorSetARGB(0xFF, 0, 0, 0x80);
55         fFast32 = fast;
56     }
57 
58 protected:
onPrepareWidEvent(SkEvent * evt)59     void onPrepareWidEvent(SkEvent* evt) override {
60         evt->setType("push-button");
61         evt->setFast32(fFast32);
62         evt->setString("label", fLabel.c_str());
63     }
64 
65 //    bool onEvent(const SkEvent&) override;
onDraw(SkCanvas * canvas)66     void onDraw(SkCanvas* canvas) override {
67         SkRect r;
68         this->getLocalBounds(&r);
69         SkPaint paint;
70         paint.setAntiAlias(true);
71         paint.setColor(fColor);
72         canvas->drawRoundRect(r, 8, 8, paint);
73 
74         paint.setColor(0xFFFFFFFF);
75         paint.setTextSize(16);
76         paint.setTextAlign(SkPaint::kCenter_Align);
77         paint.setLCDRenderText(true);
78         canvas->drawString(fLabel, r.centerX(), r.fTop + 0.68f * r.height(), paint);
79     }
80 
onFindClickHandler(SkScalar x,SkScalar y,unsigned modi)81     Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned modi) override {
82         return new Click(this);
83     }
84 
onClick(Click * click)85     bool onClick(Click* click) override {
86         SkRect target = SkRect::MakeXYWH(click->fCurr.x() - 1, click->fCurr.y() - 1, 3, 3);
87         SkRect r;
88         this->getLocalBounds(&r);
89         if (r.intersects(target)) {
90             fColor = SkColorSetA(fColor, 0x99);
91         } else {
92             fColor = SkColorSetA(fColor, 0xFF);
93         }
94         this->inval(nullptr);
95 
96         if (click->fState == SkView::Click::kUp_State) {
97             this->postWidgetEvent();
98         }
99         return true;
100     }
101 
102 private:
103     typedef HasEventWig INHERITED;
104 };
105 
106 
107 class ModeDrawable : public SkDrawable {
108 public:
ModeDrawable()109     ModeDrawable() : fMode(SkBlendMode::kSrcOver), fLoc(SkPoint::Make(0, 0)) {}
110 
111     SkBlendMode fMode;
112     SkPoint     fLoc;
113 
hitTest(SkScalar x,SkScalar y)114     bool hitTest(SkScalar x, SkScalar y) {
115         SkRect target = SkRect::MakeXYWH(x - fLoc.x() - 1, y - fLoc.y() - 1, 3, 3);
116         return this->getBounds().intersects(target);
117     }
118 };
119 
120 class CircDrawable : public ModeDrawable {
121     SkPaint fPaint;
122     SkRect  fBounds;
123 
124 public:
CircDrawable(SkScalar size,SkColor c)125     CircDrawable(SkScalar size, SkColor c) {
126         const SkColor colors[] = { 0, c };
127         fPaint.setShader(SkGradientShader::MakeRadial(SkPoint::Make(size/2, size/2), size/2,
128                                                                      colors, nullptr, 2,
129                                                                      SkShader::kClamp_TileMode));
130         fBounds = SkRect::MakeWH(size, size);
131     }
132 
133 protected:
onGetBounds()134     SkRect onGetBounds() override {
135         return fBounds;
136     }
137 
onDraw(SkCanvas * canvas)138     void onDraw(SkCanvas* canvas) override {
139         fPaint.setBlendMode(fMode);
140         canvas->save();
141         canvas->translate(fLoc.x(), fLoc.y());
142         canvas->drawOval(fBounds, fPaint);
143         canvas->restore();
144     }
145 };
146 
147 class XferDemo : public SampleView {
148     enum {
149         N = 4
150     };
151 
152     SkRect        fModeRect[N_Modes];
153     sk_sp<CircDrawable> fDrs[N];
154     CircDrawable* fSelected;
155 
addButtons()156     void addButtons() {
157         SkScalar x = 10;
158         SkScalar y = 10;
159         for (int i = 0; i < N_Modes; ++i) {
160             sk_sp<SkView> v(new PushButtonWig(SkBlendMode_Name(gModes[i]), (int)gModes[i]));
161             v->setSize(70, 25);
162             v->setLoc(x, y);
163             v->setVisibleP(true);
164             v->setEnabledP(true);
165             v->addListenerID(this->getSinkID());
166             this->attachChildToFront(v.get());
167             fModeRect[i] = SkRect::MakeXYWH(x, y + 28, 70, 2);
168             x += 80;
169         }
170     }
171 
172 public:
XferDemo()173     XferDemo() {
174         const SkColor colors[] = { SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorBLACK };
175         for (int i = 0; i < N; ++i) {
176             fDrs[i].reset(new CircDrawable(200, colors[i]));
177             fDrs[i]->fLoc.set(100.f + i * 100, 100.f + i * 100);
178             fDrs[i]->fMode = SkBlendMode::kSrcOver;
179         }
180         fSelected = nullptr;
181 
182         this->addButtons();
183     }
184 
185 protected:
onEvent(const SkEvent & evt)186     bool onEvent(const SkEvent& evt) override {
187         if (evt.isType("push-button")) {
188             if (fSelected) {
189                 fSelected->fMode = (SkBlendMode)evt.getFast32();
190                 this->inval(nullptr);
191             }
192             return true;
193         }
194         return this->INHERITED::onEvent(evt);
195     }
196 
onQuery(SkEvent * evt)197     bool onQuery(SkEvent* evt) override {
198         if (SampleCode::TitleQ(*evt)) {
199             SampleCode::TitleR(evt, "XferDemo");
200             return true;
201         }
202         return this->INHERITED::onQuery(evt);
203     }
204 
onDrawContent(SkCanvas * canvas)205     void onDrawContent(SkCanvas* canvas) override {
206         SkPaint paint;
207         if (fSelected) {
208             for (int i = 0; i < N_Modes; ++i) {
209                 if (fSelected->fMode == gModes[i]) {
210                     canvas->drawRect(fModeRect[i], paint);
211                     break;
212                 }
213             }
214         }
215 
216         canvas->saveLayer(nullptr, nullptr);
217         for (int i = 0; i < N; ++i) {
218             fDrs[i]->draw(canvas);
219         }
220         canvas->restore();
221     }
222 
onFindClickHandler(SkScalar x,SkScalar y,unsigned)223     SkView::Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned) override {
224         fSelected = nullptr;
225         for (int i = N - 1; i >= 0; --i) {
226             if (fDrs[i]->hitTest(x, y)) {
227                 fSelected = fDrs[i].get();
228                 break;
229             }
230         }
231         this->inval(nullptr);
232         return fSelected ? new Click(this) : nullptr;
233     }
234 
onClick(Click * click)235     bool onClick(Click* click) override {
236         fSelected->fLoc.fX += click->fCurr.fX - click->fPrev.fX;
237         fSelected->fLoc.fY += click->fCurr.fY - click->fPrev.fY;
238         this->inval(nullptr);
239         return true;
240     }
241 
242 private:
243     typedef SampleView INHERITED;
244 };
245 
246 //////////////////////////////////////////////////////////////////////////////
247 
248 DEF_SAMPLE( return new XferDemo; )
249