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