• 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 "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 
19 const SkBlendMode gModes[] = {
20     SkBlendMode::kSrcOver,
21     SkBlendMode::kSrc,
22     SkBlendMode::kSrcIn,
23     SkBlendMode::kSrcOut,
24     SkBlendMode::kSrcATop,
25     SkBlendMode::kDstOver,
26     SkBlendMode::kDstIn,
27     SkBlendMode::kDstOut,
28     SkBlendMode::kDstATop,
29 };
30 const int N_Modes = SK_ARRAY_COUNT(gModes);
31 
32 static SkRandom gRand;
33 
34 struct ModeButton {
35     SkString fLabel;
36     SkColor  fColor;
37     SkRect   fRect;
38 
39 public:
initModeButton40     void init(const char label[], const SkRect& rect) {
41         fLabel = label;
42         fRect = rect;
43         fColor = (gRand.nextU() & 0x7F7F7F7F) | SkColorSetARGB(0xFF, 0, 0, 0x80);
44     }
45 
drawModeButton46     void draw(SkCanvas* canvas) {
47         SkPaint paint;
48         paint.setAntiAlias(true);
49         paint.setColor(fColor);
50         canvas->drawRoundRect(fRect, 8, 8, paint);
51 
52         paint.setColor(0xFFFFFFFF);
53         SkFont font;
54         font.setSize(16);
55         font.setEdging(SkFont::Edging::kSubpixelAntiAlias);
56         SkTextUtils::DrawString(canvas, fLabel.c_str(), fRect.centerX(), fRect.fTop + 0.68f * fRect.height(),
57                                 font, paint, SkTextUtils::kCenter_Align);
58     }
59 
hitTestModeButton60     bool hitTest(SkScalar x, SkScalar y) {
61         return fRect.intersects(x - 1, y - 1, x + 1, y + 1);
62     }
63 };
64 
65 class ModeDrawable : public SkDrawable {
66 public:
ModeDrawable()67     ModeDrawable() : fMode(SkBlendMode::kSrcOver), fLoc(SkPoint::Make(0, 0)) {}
68 
69     SkBlendMode fMode;
70     SkPoint     fLoc;
71 
hitTest(SkScalar x,SkScalar y)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 
78 class CircDrawable : public ModeDrawable {
79     SkPaint fPaint;
80     SkRect  fBounds;
81 
82 public:
CircDrawable(SkScalar size,SkColor c)83     CircDrawable(SkScalar size, SkColor c) {
84         const SkColor colors[] = { 0, c };
85         fPaint.setShader(SkGradientShader::MakeRadial(SkPoint::Make(size/2, size/2), size/2,
86                                                                      colors, nullptr, 2,
87                                                                      SkTileMode::kClamp));
88         fBounds = SkRect::MakeWH(size, size);
89     }
90 
91 protected:
onGetBounds()92     SkRect onGetBounds() override {
93         return fBounds;
94     }
95 
onDraw(SkCanvas * canvas)96     void onDraw(SkCanvas* canvas) override {
97         fPaint.setBlendMode(fMode);
98         canvas->save();
99         canvas->translate(fLoc.x(), fLoc.y());
100         canvas->drawOval(fBounds, fPaint);
101         canvas->restore();
102     }
103 };
104 
105 class XferDemo : public Sample {
106     enum {
107         N = 4
108     };
109 
110     SkRect        fModeRect[N_Modes];
111     ModeButton    fModeButtons[N_Modes];
112     sk_sp<CircDrawable> fDrs[N];
113     CircDrawable* fSelected;
114 
addButtons()115     void addButtons() {
116         SkScalar x = 10;
117         SkScalar y = 10;
118         for (int i = 0; i < N_Modes; ++i) {
119             fModeButtons[i].init(SkBlendMode_Name(gModes[i]), SkRect::MakeXYWH(x, y, 70, 25));
120             fModeRect[i] = SkRect::MakeXYWH(x, y + 28, 70, 2);
121             x += 80;
122         }
123     }
124 
125 public:
XferDemo()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);
131             fDrs[i]->fMode = SkBlendMode::kSrcOver;
132         }
133         fSelected = nullptr;
134 
135         this->addButtons();
136     }
137 
138 protected:
name()139     SkString name() override { return SkString("XferDemo"); }
140 
onDrawContent(SkCanvas * canvas)141     void onDrawContent(SkCanvas* canvas) override {
142         for (int i = 0; i < N_Modes; ++i) {
143             fModeButtons[i].draw(canvas);
144         }
145 
146         SkPaint paint;
147         if (fSelected) {
148             for (int i = 0; i < N_Modes; ++i) {
149                 if (fSelected->fMode == gModes[i]) {
150                     canvas->drawRect(fModeRect[i], paint);
151                     break;
152                 }
153             }
154         }
155 
156         canvas->saveLayer(nullptr, nullptr);
157         for (int i = 0; i < N; ++i) {
158             fDrs[i]->draw(canvas);
159         }
160         canvas->restore();
161     }
162 
onFindClickHandler(SkScalar x,SkScalar y,ModifierKey)163     Sample::Click* onFindClickHandler(SkScalar x, SkScalar y, ModifierKey) override {
164         // Check mode buttons first
165         for (int i = 0; i < N_Modes; ++i) {
166             if (fModeButtons[i].hitTest(x, y)) {
167                 Click* click = new Click();
168                 click->fMeta.setS32("mode", i);
169                 return click;
170             }
171         }
172         fSelected = nullptr;
173         for (int i = N - 1; i >= 0; --i) {
174             if (fDrs[i]->hitTest(x, y)) {
175                 fSelected = fDrs[i].get();
176                 break;
177             }
178         }
179         return fSelected ? new Click() : nullptr;
180     }
181 
onClick(Click * click)182     bool onClick(Click* click) override {
183         int32_t mode;
184         if (click->fMeta.findS32("mode", &mode)) {
185             if (fSelected && InputState::kUp == click->fState) {
186                 fSelected->fMode = gModes[mode];
187             }
188         } else {
189             fSelected->fLoc.fX += click->fCurr.fX - click->fPrev.fX;
190             fSelected->fLoc.fY += click->fCurr.fY - click->fPrev.fY;
191         }
192         return true;
193     }
194 
195 private:
196     typedef Sample INHERITED;
197 };
198 
199 //////////////////////////////////////////////////////////////////////////////
200 
201 DEF_SAMPLE( return new XferDemo; )
202