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