blob: 6aaffe59c9dc87014cc51f074af7b2cd30fcd2ab [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 }
halcanary9d524f22016-03-29 09:03:52 -070060
reed1a9caff2015-09-02 19:05:10 -070061protected:
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 }
halcanary9d524f22016-03-29 09:03:52 -0700104
reed1a9caff2015-09-02 19:05:10 -0700105private:
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 };
reed8a21c9f2016-03-08 18:50:00 -0800130 fPaint.setShader(SkGradientShader::MakeRadial(SkPoint::Make(size/2, size/2), size/2,
reed1a9caff2015-09-02 19:05:10 -0700131 colors, nullptr, 2,
132 SkShader::kClamp_TileMode));
reed1a9caff2015-09-02 19:05:10 -0700133 fBounds = SkRect::MakeWH(size, size);
134 }
135
136protected:
137 SkRect onGetBounds() override {
138 return fBounds;
139 }
140
141 void onDraw(SkCanvas* canvas) override {
142 fPaint.setXfermodeMode(fMode);
143 canvas->save();
144 canvas->translate(fLoc.x(), fLoc.y());
145 canvas->drawOval(fBounds, fPaint);
146 canvas->restore();
147 }
148};
149
150class XferDemo : public SampleView {
151 enum {
152 N = 4
153 };
halcanary9d524f22016-03-29 09:03:52 -0700154
reed1a9caff2015-09-02 19:05:10 -0700155 SkRect fModeRect[N_Modes];
156 SkAutoTUnref<CircDrawable> fDrs[N];
157 CircDrawable* fSelected;
158
159 void addButtons() {
160 SkScalar x = 10;
161 SkScalar y = 10;
162 for (int i = 0; i < N_Modes; ++i) {
163 SkAutoTUnref<SkView> v(new PushButtonWig(gModes[i].fName, gModes[i].fMode));
164 v->setSize(70, 25);
165 v->setLoc(x, y);
166 v->setVisibleP(true);
167 v->setEnabledP(true);
168 v->addListenerID(this->getSinkID());
169 this->attachChildToFront(v);
170 fModeRect[i] = SkRect::MakeXYWH(x, y + 28, 70, 2);
171 x += 80;
172 }
173 }
174
175public:
176 XferDemo() {
177 const SkColor colors[] = { SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorBLACK };
178 for (int i = 0; i < N; ++i) {
179 fDrs[i].reset(new CircDrawable(200, colors[i]));
180 fDrs[i]->fLoc.set(100.f + i * 100, 100.f + i * 100);
181 fDrs[i]->fMode = SkXfermode::kSrcOver_Mode;
182 }
183 fSelected = nullptr;
184
185 this->addButtons();
186 }
187
188protected:
189 bool onEvent(const SkEvent& evt) override {
190 if (evt.isType("push-button")) {
191 if (fSelected) {
192 fSelected->fMode = (SkXfermode::Mode)evt.getFast32();
193 this->inval(nullptr);
194 }
195 return true;
196 }
197 return this->INHERITED::onEvent(evt);
198 }
199
200 bool onQuery(SkEvent* evt) override {
201 if (SampleCode::TitleQ(*evt)) {
202 SampleCode::TitleR(evt, "XferDemo");
203 return true;
204 }
205 return this->INHERITED::onQuery(evt);
206 }
207
208 void onDrawContent(SkCanvas* canvas) override {
209 SkPaint paint;
210 if (fSelected) {
211 for (int i = 0; i < N_Modes; ++i) {
212 if (fSelected->fMode == gModes[i].fMode) {
213 canvas->drawRect(fModeRect[i], paint);
214 break;
215 }
216 }
217 }
218
219 canvas->saveLayer(nullptr, nullptr);
220 for (int i = 0; i < N; ++i) {
221 fDrs[i]->draw(canvas);
222 }
223 canvas->restore();
224 }
225
226 SkView::Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned) override {
227 fSelected = nullptr;
228 for (int i = N - 1; i >= 0; --i) {
229 if (fDrs[i]->hitTest(x, y)) {
230 fSelected = fDrs[i];
231 break;
232 }
233 }
234 this->inval(nullptr);
235 return fSelected ? new Click(this) : nullptr;
236 }
halcanary9d524f22016-03-29 09:03:52 -0700237
reed1a9caff2015-09-02 19:05:10 -0700238 bool onClick(Click* click) override {
239 fSelected->fLoc.fX += click->fCurr.fX - click->fPrev.fX;
240 fSelected->fLoc.fY += click->fCurr.fY - click->fPrev.fY;
241 this->inval(nullptr);
242 return true;
243 }
244
245private:
246 typedef SampleView INHERITED;
247};
248
249//////////////////////////////////////////////////////////////////////////////
250
251DEF_SAMPLE( return new XferDemo; )