1/*
2 * Copyright 2011 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#include "SampleCode.h"
8#include "SkView.h"
9#include "SkCanvas.h"
10#include "SkGradientShader.h"
11
12static sk_sp<SkShader> setgrad(const SkRect& r, SkColor c0, SkColor c1) {
13    SkColor colors[] = { c0, c1 };
14    SkPoint pts[] = { { r.fLeft, r.fTop }, { r.fRight, r.fTop } };
15    return SkGradientShader::MakeLinear(pts, colors, nullptr, 2, SkShader::kClamp_TileMode);
16}
17
18static void test_alphagradients(SkCanvas* canvas) {
19    SkRect r;
20    r.set(SkIntToScalar(10), SkIntToScalar(10),
21          SkIntToScalar(410), SkIntToScalar(30));
22    SkPaint p, p2;
23    p2.setStyle(SkPaint::kStroke_Style);
24
25    p.setShader(setgrad(r, 0xFF00FF00, 0x0000FF00));
26    canvas->drawRect(r, p);
27    canvas->drawRect(r, p2);
28
29    r.offset(0, r.height() + SkIntToScalar(4));
30    p.setShader(setgrad(r, 0xFF00FF00, 0x00000000));
31    canvas->drawRect(r, p);
32    canvas->drawRect(r, p2);
33
34    r.offset(0, r.height() + SkIntToScalar(4));
35    p.setShader(setgrad(r, 0xFF00FF00, 0x00FF0000));
36    canvas->drawRect(r, p);
37    canvas->drawRect(r, p2);
38}
39
40///////////////////////////////////////////////////////////////////////////////
41
42struct GradData {
43    int             fCount;
44    const SkColor*  fColors;
45    const SkScalar* fPos;
46};
47
48static const SkColor gColors[] = {
49    SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorWHITE, SK_ColorBLACK
50};
51static const SkScalar gPos0[] = { 0, SK_Scalar1 };
52static const SkScalar gPos1[] = { SK_Scalar1/4, SK_Scalar1*3/4 };
53static const SkScalar gPos2[] = {
54    0, SK_Scalar1/8, SK_Scalar1/2, SK_Scalar1*7/8, SK_Scalar1
55};
56
57static const GradData gGradData[] = {
58    { 2, gColors, nullptr },
59    { 2, gColors, gPos0 },
60    { 2, gColors, gPos1 },
61    { 5, gColors, nullptr },
62    { 5, gColors, gPos2 }
63};
64
65static sk_sp<SkShader> MakeLinear(const SkPoint pts[2], const GradData& data, SkShader::TileMode tm) {
66    return SkGradientShader::MakeLinear(pts, data.fColors, data.fPos, data.fCount, tm);
67}
68
69static sk_sp<SkShader> MakeRadial(const SkPoint pts[2], const GradData& data, SkShader::TileMode tm) {
70    SkPoint center;
71    center.set(SkScalarAve(pts[0].fX, pts[1].fX),
72               SkScalarAve(pts[0].fY, pts[1].fY));
73    return SkGradientShader::MakeRadial(center, center.fX, data.fColors,
74                                        data.fPos, data.fCount, tm);
75}
76
77static sk_sp<SkShader> MakeSweep(const SkPoint pts[2], const GradData& data, SkShader::TileMode tm) {
78    SkPoint center;
79    center.set(SkScalarAve(pts[0].fX, pts[1].fX),
80               SkScalarAve(pts[0].fY, pts[1].fY));
81    return SkGradientShader::MakeSweep(center.fX, center.fY, data.fColors, data.fPos, data.fCount);
82}
83
84static sk_sp<SkShader> Make2Conical(const SkPoint pts[2], const GradData& data, SkShader::TileMode tm) {
85    SkPoint center0, center1;
86    center0.set(SkScalarAve(pts[0].fX, pts[1].fX),
87                SkScalarAve(pts[0].fY, pts[1].fY));
88    center1.set(SkScalarInterp(pts[0].fX, pts[1].fX, SkIntToScalar(3)/5),
89                SkScalarInterp(pts[0].fY, pts[1].fY, SkIntToScalar(1)/4));
90    return SkGradientShader::MakeTwoPointConical(
91                            center1, (pts[1].fX - pts[0].fX) / 7,
92                            center0, (pts[1].fX - pts[0].fX) / 2,
93                            data.fColors, data.fPos, data.fCount, tm);
94}
95
96static sk_sp<SkShader> Make2ConicalConcentric(const SkPoint pts[2], const GradData& data,
97                                       SkShader::TileMode tm) {
98    SkPoint center;
99    center.set(SkScalarAve(pts[0].fX, pts[1].fX),
100               SkScalarAve(pts[0].fY, pts[1].fY));
101    return SkGradientShader::MakeTwoPointConical(
102                            center, (pts[1].fX - pts[0].fX) / 7,
103                            center, (pts[1].fX - pts[0].fX) / 2,
104                            data.fColors, data.fPos, data.fCount, tm);
105}
106
107typedef sk_sp<SkShader> (*GradMaker)(const SkPoint pts[2], const GradData& data, SkShader::TileMode tm);
108
109static const GradMaker gGradMakers[] = {
110    MakeLinear, MakeRadial, MakeSweep, Make2Conical, Make2ConicalConcentric
111};
112
113///////////////////////////////////////////////////////////////////////////////
114
115class GradientsView : public SampleView {
116public:
117    GradientsView() {
118        this->setBGColor(0xFFDDDDDD);
119    }
120
121protected:
122    bool onQuery(SkEvent* evt) override {
123        if (SampleCode::TitleQ(*evt)) {
124            SampleCode::TitleR(evt, "Gradients");
125            return true;
126        }
127        return this->INHERITED::onQuery(evt);
128    }
129
130    void onDrawContent(SkCanvas* canvas) override {
131        SkPoint pts[2] = {
132            { 0, 0 },
133            { SkIntToScalar(100), SkIntToScalar(100) }
134        };
135        SkRect r = { 0, 0, SkIntToScalar(100), SkIntToScalar(100) };
136        SkPaint paint;
137        paint.setDither(true);
138
139        canvas->save();
140        canvas->translate(SkIntToScalar(20), SkIntToScalar(10));
141
142        for (int tm = 0; tm < SkShader::kTileModeCount; ++tm) {
143            canvas->save();
144            for (size_t i = 0; i < SK_ARRAY_COUNT(gGradData); i++) {
145                canvas->save();
146                for (size_t j = 0; j < SK_ARRAY_COUNT(gGradMakers); j++) {
147                    paint.setShader(gGradMakers[j](pts, gGradData[i], (SkShader::TileMode)tm));
148                    canvas->drawRect(r, paint);
149                    canvas->translate(0, SkIntToScalar(120));
150                }
151                canvas->restore();
152                canvas->translate(SkIntToScalar(120), 0);
153            }
154            canvas->restore();
155            canvas->translate(SK_ARRAY_COUNT(gGradData)*SkIntToScalar(120), 0);
156        }
157        canvas->restore();
158
159        canvas->translate(0, SkIntToScalar(370));
160        if (false) { // avoid bit rot, suppress warning
161            test_alphagradients(canvas);
162        }
163        this->inval(nullptr);
164    }
165
166private:
167    typedef SampleView INHERITED;
168};
169
170///////////////////////////////////////////////////////////////////////////////
171
172static SkView* MyFactory() { return new GradientsView; }
173static SkViewRegister reg(MyFactory);
174