blob: 074613c4417fd5d6b5f737a77e8248153c2d5349 [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
Brian Osmand1e67e72017-03-15 12:19:37 -040020const 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,
reed1a9caff2015-09-02 19:05:10 -070030};
31const int N_Modes = SK_ARRAY_COUNT(gModes);
32
reed1a9caff2015-09-02 19:05:10 -070033static SkRandom gRand;
34
Brian Osmanede860e2017-11-22 16:36:07 -050035struct ModeButton {
reed1a9caff2015-09-02 19:05:10 -070036 SkString fLabel;
37 SkColor fColor;
Brian Osmanede860e2017-11-22 16:36:07 -050038 SkRect fRect;
reed1a9caff2015-09-02 19:05:10 -070039
40public:
Brian Osmanede860e2017-11-22 16:36:07 -050041 void init(const char label[], const SkRect& rect) {
42 fLabel = label;
43 fRect = rect;
reed1a9caff2015-09-02 19:05:10 -070044 fColor = (gRand.nextU() & 0x7F7F7F7F) | SkColorSetARGB(0xFF, 0, 0, 0x80);
reed1a9caff2015-09-02 19:05:10 -070045 }
halcanary9d524f22016-03-29 09:03:52 -070046
Brian Osmanede860e2017-11-22 16:36:07 -050047 void draw(SkCanvas* canvas) {
reed1a9caff2015-09-02 19:05:10 -070048 SkPaint paint;
49 paint.setAntiAlias(true);
50 paint.setColor(fColor);
Brian Osmanede860e2017-11-22 16:36:07 -050051 canvas->drawRoundRect(fRect, 8, 8, paint);
reed1a9caff2015-09-02 19:05:10 -070052
53 paint.setColor(0xFFFFFFFF);
54 paint.setTextSize(16);
55 paint.setTextAlign(SkPaint::kCenter_Align);
56 paint.setLCDRenderText(true);
Brian Osmanede860e2017-11-22 16:36:07 -050057 canvas->drawString(fLabel, fRect.centerX(), fRect.fTop + 0.68f * fRect.height(), paint);
reed1a9caff2015-09-02 19:05:10 -070058 }
59
Brian Osmanede860e2017-11-22 16:36:07 -050060 bool hitTest(SkScalar x, SkScalar y) {
61 return fRect.intersects(x - 1, y - 1, x + 1, y + 1);
reed1a9caff2015-09-02 19:05:10 -070062 }
reed1a9caff2015-09-02 19:05:10 -070063};
64
reed1a9caff2015-09-02 19:05:10 -070065class ModeDrawable : public SkDrawable {
66public:
reed374772b2016-10-05 17:33:02 -070067 ModeDrawable() : fMode(SkBlendMode::kSrcOver), fLoc(SkPoint::Make(0, 0)) {}
reed1a9caff2015-09-02 19:05:10 -070068
reed374772b2016-10-05 17:33:02 -070069 SkBlendMode fMode;
70 SkPoint fLoc;
reed1a9caff2015-09-02 19:05:10 -070071
72 bool hitTest(SkScalar x, SkScalar y) {
73 SkRect target = SkRect::MakeXYWH(x - fLoc.x() - 1, y - fLoc.y() - 1, 3, 3);
74 return this->getBounds().intersects(target);
75 }
76};
77
78class CircDrawable : public ModeDrawable {
79 SkPaint fPaint;
80 SkRect fBounds;
81
82public:
83 CircDrawable(SkScalar size, SkColor c) {
84 const SkColor colors[] = { 0, c };
reed8a21c9f2016-03-08 18:50:00 -080085 fPaint.setShader(SkGradientShader::MakeRadial(SkPoint::Make(size/2, size/2), size/2,
reed1a9caff2015-09-02 19:05:10 -070086 colors, nullptr, 2,
87 SkShader::kClamp_TileMode));
reed1a9caff2015-09-02 19:05:10 -070088 fBounds = SkRect::MakeWH(size, size);
89 }
90
91protected:
92 SkRect onGetBounds() override {
93 return fBounds;
94 }
95
96 void onDraw(SkCanvas* canvas) override {
reed374772b2016-10-05 17:33:02 -070097 fPaint.setBlendMode(fMode);
reed1a9caff2015-09-02 19:05:10 -070098 canvas->save();
99 canvas->translate(fLoc.x(), fLoc.y());
100 canvas->drawOval(fBounds, fPaint);
101 canvas->restore();
102 }
103};
104
105class XferDemo : public SampleView {
106 enum {
107 N = 4
108 };
halcanary9d524f22016-03-29 09:03:52 -0700109
reed1a9caff2015-09-02 19:05:10 -0700110 SkRect fModeRect[N_Modes];
Brian Osmanede860e2017-11-22 16:36:07 -0500111 ModeButton fModeButtons[N_Modes];
Hal Canary2db83612016-11-04 13:02:54 -0400112 sk_sp<CircDrawable> fDrs[N];
reed1a9caff2015-09-02 19:05:10 -0700113 CircDrawable* fSelected;
114
115 void addButtons() {
116 SkScalar x = 10;
117 SkScalar y = 10;
118 for (int i = 0; i < N_Modes; ++i) {
Brian Osmanede860e2017-11-22 16:36:07 -0500119 fModeButtons[i].init(SkBlendMode_Name(gModes[i]), SkRect::MakeXYWH(x, y, 70, 25));
reed1a9caff2015-09-02 19:05:10 -0700120 fModeRect[i] = SkRect::MakeXYWH(x, y + 28, 70, 2);
121 x += 80;
122 }
123 }
124
125public:
126 XferDemo() {
127 const SkColor colors[] = { SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorBLACK };
128 for (int i = 0; i < N; ++i) {
129 fDrs[i].reset(new CircDrawable(200, colors[i]));
130 fDrs[i]->fLoc.set(100.f + i * 100, 100.f + i * 100);
reed374772b2016-10-05 17:33:02 -0700131 fDrs[i]->fMode = SkBlendMode::kSrcOver;
reed1a9caff2015-09-02 19:05:10 -0700132 }
133 fSelected = nullptr;
134
135 this->addButtons();
136 }
137
138protected:
reed1a9caff2015-09-02 19:05:10 -0700139 bool onQuery(SkEvent* evt) override {
140 if (SampleCode::TitleQ(*evt)) {
141 SampleCode::TitleR(evt, "XferDemo");
142 return true;
143 }
144 return this->INHERITED::onQuery(evt);
145 }
146
147 void onDrawContent(SkCanvas* canvas) override {
Brian Osmanede860e2017-11-22 16:36:07 -0500148 for (int i = 0; i < N_Modes; ++i) {
149 fModeButtons[i].draw(canvas);
150 }
151
reed1a9caff2015-09-02 19:05:10 -0700152 SkPaint paint;
153 if (fSelected) {
154 for (int i = 0; i < N_Modes; ++i) {
Brian Osmand1e67e72017-03-15 12:19:37 -0400155 if (fSelected->fMode == gModes[i]) {
reed1a9caff2015-09-02 19:05:10 -0700156 canvas->drawRect(fModeRect[i], paint);
157 break;
158 }
159 }
160 }
161
162 canvas->saveLayer(nullptr, nullptr);
163 for (int i = 0; i < N; ++i) {
164 fDrs[i]->draw(canvas);
165 }
166 canvas->restore();
167 }
168
169 SkView::Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned) override {
Brian Osmanede860e2017-11-22 16:36:07 -0500170 // Check mode buttons first
171 for (int i = 0; i < N_Modes; ++i) {
172 if (fModeButtons[i].hitTest(x, y)) {
173 Click* click = new Click(this);
174 click->fMeta.setS32("mode", i);
175 return click;
176 }
177 }
reed1a9caff2015-09-02 19:05:10 -0700178 fSelected = nullptr;
179 for (int i = N - 1; i >= 0; --i) {
180 if (fDrs[i]->hitTest(x, y)) {
Hal Canary2db83612016-11-04 13:02:54 -0400181 fSelected = fDrs[i].get();
reed1a9caff2015-09-02 19:05:10 -0700182 break;
183 }
184 }
reed1a9caff2015-09-02 19:05:10 -0700185 return fSelected ? new Click(this) : nullptr;
186 }
halcanary9d524f22016-03-29 09:03:52 -0700187
reed1a9caff2015-09-02 19:05:10 -0700188 bool onClick(Click* click) override {
Brian Osmanede860e2017-11-22 16:36:07 -0500189 int32_t mode;
190 if (click->fMeta.findS32("mode", &mode)) {
191 if (fSelected && Click::kUp_State == click->fState) {
192 fSelected->fMode = gModes[mode];
193 }
194 } else {
195 fSelected->fLoc.fX += click->fCurr.fX - click->fPrev.fX;
196 fSelected->fLoc.fY += click->fCurr.fY - click->fPrev.fY;
197 }
reed1a9caff2015-09-02 19:05:10 -0700198 return true;
199 }
200
201private:
202 typedef SampleView INHERITED;
203};
204
205//////////////////////////////////////////////////////////////////////////////
206
207DEF_SAMPLE( return new XferDemo; )