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