blob: 81534f7f024dcd71089cbf278db66a6bda8603d7 [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
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "include/core/SkCanvas.h"
9#include "include/core/SkDrawable.h"
10#include "include/core/SkPath.h"
11#include "include/core/SkRSXform.h"
12#include "include/core/SkString.h"
13#include "include/core/SkSurface.h"
14#include "include/effects/SkGradientShader.h"
15#include "include/utils/SkRandom.h"
16#include "include/utils/SkTextUtils.h"
17#include "samplecode/Sample.h"
18#include "tools/timer/AnimTimer.h"
reed1a9caff2015-09-02 19:05:10 -070019
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);
Mike Reedb579f072019-01-03 15:45:53 -050054 SkFont font;
55 font.setSize(16);
56 font.setEdging(SkFont::Edging::kSubpixelAntiAlias);
57 SkTextUtils::DrawString(canvas, fLabel.c_str(), fRect.centerX(), fRect.fTop + 0.68f * fRect.height(),
58 font, paint, SkTextUtils::kCenter_Align);
reed1a9caff2015-09-02 19:05:10 -070059 }
60
Brian Osmanede860e2017-11-22 16:36:07 -050061 bool hitTest(SkScalar x, SkScalar y) {
62 return fRect.intersects(x - 1, y - 1, x + 1, y + 1);
reed1a9caff2015-09-02 19:05:10 -070063 }
reed1a9caff2015-09-02 19:05:10 -070064};
65
reed1a9caff2015-09-02 19:05:10 -070066class ModeDrawable : public SkDrawable {
67public:
reed374772b2016-10-05 17:33:02 -070068 ModeDrawable() : fMode(SkBlendMode::kSrcOver), fLoc(SkPoint::Make(0, 0)) {}
reed1a9caff2015-09-02 19:05:10 -070069
reed374772b2016-10-05 17:33:02 -070070 SkBlendMode fMode;
71 SkPoint fLoc;
reed1a9caff2015-09-02 19:05:10 -070072
73 bool hitTest(SkScalar x, SkScalar y) {
74 SkRect target = SkRect::MakeXYWH(x - fLoc.x() - 1, y - fLoc.y() - 1, 3, 3);
75 return this->getBounds().intersects(target);
76 }
77};
78
79class CircDrawable : public ModeDrawable {
80 SkPaint fPaint;
81 SkRect fBounds;
82
83public:
84 CircDrawable(SkScalar size, SkColor c) {
85 const SkColor colors[] = { 0, c };
reed8a21c9f2016-03-08 18:50:00 -080086 fPaint.setShader(SkGradientShader::MakeRadial(SkPoint::Make(size/2, size/2), size/2,
reed1a9caff2015-09-02 19:05:10 -070087 colors, nullptr, 2,
Mike Reedfae8fce2019-04-03 10:27:45 -040088 SkTileMode::kClamp));
reed1a9caff2015-09-02 19:05:10 -070089 fBounds = SkRect::MakeWH(size, size);
90 }
91
92protected:
93 SkRect onGetBounds() override {
94 return fBounds;
95 }
96
97 void onDraw(SkCanvas* canvas) override {
reed374772b2016-10-05 17:33:02 -070098 fPaint.setBlendMode(fMode);
reed1a9caff2015-09-02 19:05:10 -070099 canvas->save();
100 canvas->translate(fLoc.x(), fLoc.y());
101 canvas->drawOval(fBounds, fPaint);
102 canvas->restore();
103 }
104};
105
Ben Wagnerb2c4ea62018-08-08 11:36:17 -0400106class XferDemo : public Sample {
reed1a9caff2015-09-02 19:05:10 -0700107 enum {
108 N = 4
109 };
halcanary9d524f22016-03-29 09:03:52 -0700110
reed1a9caff2015-09-02 19:05:10 -0700111 SkRect fModeRect[N_Modes];
Brian Osmanede860e2017-11-22 16:36:07 -0500112 ModeButton fModeButtons[N_Modes];
Hal Canary2db83612016-11-04 13:02:54 -0400113 sk_sp<CircDrawable> fDrs[N];
reed1a9caff2015-09-02 19:05:10 -0700114 CircDrawable* fSelected;
115
116 void addButtons() {
117 SkScalar x = 10;
118 SkScalar y = 10;
119 for (int i = 0; i < N_Modes; ++i) {
Brian Osmanede860e2017-11-22 16:36:07 -0500120 fModeButtons[i].init(SkBlendMode_Name(gModes[i]), SkRect::MakeXYWH(x, y, 70, 25));
reed1a9caff2015-09-02 19:05:10 -0700121 fModeRect[i] = SkRect::MakeXYWH(x, y + 28, 70, 2);
122 x += 80;
123 }
124 }
125
126public:
127 XferDemo() {
128 const SkColor colors[] = { SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorBLACK };
129 for (int i = 0; i < N; ++i) {
130 fDrs[i].reset(new CircDrawable(200, colors[i]));
131 fDrs[i]->fLoc.set(100.f + i * 100, 100.f + i * 100);
reed374772b2016-10-05 17:33:02 -0700132 fDrs[i]->fMode = SkBlendMode::kSrcOver;
reed1a9caff2015-09-02 19:05:10 -0700133 }
134 fSelected = nullptr;
135
136 this->addButtons();
137 }
138
139protected:
Ben Wagnerb2c4ea62018-08-08 11:36:17 -0400140 bool onQuery(Sample::Event* evt) override {
141 if (Sample::TitleQ(*evt)) {
142 Sample::TitleR(evt, "XferDemo");
reed1a9caff2015-09-02 19:05:10 -0700143 return true;
144 }
145 return this->INHERITED::onQuery(evt);
146 }
147
148 void onDrawContent(SkCanvas* canvas) override {
Brian Osmanede860e2017-11-22 16:36:07 -0500149 for (int i = 0; i < N_Modes; ++i) {
150 fModeButtons[i].draw(canvas);
151 }
152
reed1a9caff2015-09-02 19:05:10 -0700153 SkPaint paint;
154 if (fSelected) {
155 for (int i = 0; i < N_Modes; ++i) {
Brian Osmand1e67e72017-03-15 12:19:37 -0400156 if (fSelected->fMode == gModes[i]) {
reed1a9caff2015-09-02 19:05:10 -0700157 canvas->drawRect(fModeRect[i], paint);
158 break;
159 }
160 }
161 }
162
163 canvas->saveLayer(nullptr, nullptr);
164 for (int i = 0; i < N; ++i) {
165 fDrs[i]->draw(canvas);
166 }
167 canvas->restore();
168 }
169
Ben Wagnerb2c4ea62018-08-08 11:36:17 -0400170 Sample::Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned) override {
Brian Osmanede860e2017-11-22 16:36:07 -0500171 // Check mode buttons first
172 for (int i = 0; i < N_Modes; ++i) {
173 if (fModeButtons[i].hitTest(x, y)) {
174 Click* click = new Click(this);
175 click->fMeta.setS32("mode", i);
176 return click;
177 }
178 }
reed1a9caff2015-09-02 19:05:10 -0700179 fSelected = nullptr;
180 for (int i = N - 1; i >= 0; --i) {
181 if (fDrs[i]->hitTest(x, y)) {
Hal Canary2db83612016-11-04 13:02:54 -0400182 fSelected = fDrs[i].get();
reed1a9caff2015-09-02 19:05:10 -0700183 break;
184 }
185 }
reed1a9caff2015-09-02 19:05:10 -0700186 return fSelected ? new Click(this) : nullptr;
187 }
halcanary9d524f22016-03-29 09:03:52 -0700188
reed1a9caff2015-09-02 19:05:10 -0700189 bool onClick(Click* click) override {
Brian Osmanede860e2017-11-22 16:36:07 -0500190 int32_t mode;
191 if (click->fMeta.findS32("mode", &mode)) {
192 if (fSelected && Click::kUp_State == click->fState) {
193 fSelected->fMode = gModes[mode];
194 }
195 } else {
196 fSelected->fLoc.fX += click->fCurr.fX - click->fPrev.fX;
197 fSelected->fLoc.fY += click->fCurr.fY - click->fPrev.fY;
198 }
reed1a9caff2015-09-02 19:05:10 -0700199 return true;
200 }
201
202private:
Ben Wagnerb2c4ea62018-08-08 11:36:17 -0400203 typedef Sample INHERITED;
reed1a9caff2015-09-02 19:05:10 -0700204};
205
206//////////////////////////////////////////////////////////////////////////////
207
208DEF_SAMPLE( return new XferDemo; )