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