• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2014 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 "gm/gm.h"
9 #include "include/core/SkCanvas.h"
10 #include "include/core/SkColor.h"
11 #include "include/core/SkColorFilter.h"
12 #include "include/core/SkPaint.h"
13 #include "include/core/SkPoint.h"
14 #include "include/core/SkRect.h"
15 #include "include/core/SkRefCnt.h"
16 #include "include/core/SkShader.h"
17 #include "include/core/SkSize.h"
18 #include "include/core/SkString.h"
19 #include "include/core/SkTileMode.h"
20 #include "include/core/SkTypes.h"
21 #include "include/effects/SkGradientShader.h"
22 #include "tools/Resources.h"
23 
24 #include <vector>
25 #include <tuple>
26 
make_shader(const SkRect & bounds)27 static sk_sp<SkShader> make_shader(const SkRect& bounds) {
28     const SkPoint pts[] = {
29         { bounds.left(), bounds.top() },
30         { bounds.right(), bounds.bottom() },
31     };
32     const SkColor colors[] = {
33         SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorBLACK,
34         SK_ColorCYAN, SK_ColorMAGENTA, SK_ColorYELLOW,
35     };
36     return SkGradientShader::MakeLinear(pts, colors, nullptr, std::size(colors),
37                                         SkTileMode::kClamp);
38 }
39 
40 typedef void (*InstallPaint)(SkPaint*, uint32_t, uint32_t);
41 
install_nothing(SkPaint * paint,uint32_t,uint32_t)42 static void install_nothing(SkPaint* paint, uint32_t, uint32_t) {
43     paint->setColorFilter(nullptr);
44 }
45 
install_lighting(SkPaint * paint,uint32_t mul,uint32_t add)46 static void install_lighting(SkPaint* paint, uint32_t mul, uint32_t add) {
47     paint->setColorFilter(SkColorFilters::Lighting(mul, add));
48 }
49 
50 class ColorFiltersGM : public skiagm::GM {
onShortName()51     SkString onShortName() override { return SkString("lightingcolorfilter"); }
52 
onISize()53     SkISize onISize() override { return {620, 430}; }
54 
onDraw(SkCanvas * canvas)55     void onDraw(SkCanvas* canvas) override {
56         SkRect r = {0, 0, 600, 50};
57 
58         SkPaint paint;
59         paint.setShader(make_shader(r));
60 
61         const struct {
62             InstallPaint    fProc;
63             uint32_t        fData0, fData1;
64         } rec[] = {
65             { install_nothing, 0, 0 },
66             { install_lighting, 0xFF0000, 0 },
67             { install_lighting, 0x00FF00, 0 },
68             { install_lighting, 0x0000FF, 0 },
69             { install_lighting, 0x000000, 0xFF0000 },
70             { install_lighting, 0x000000, 0x00FF00 },
71             { install_lighting, 0x000000, 0x0000FF },
72         };
73 
74         canvas->translate(10, 10);
75         for (size_t i = 0; i < std::size(rec); ++i) {
76             rec[i].fProc(&paint, rec[i].fData0, rec[i].fData1);
77             canvas->drawRect(r, paint);
78             canvas->translate(0, r.height() + 10);
79         }
80     }
81 };
82 
83 DEF_GM(return new ColorFiltersGM;)
84 
85 class HSLColorFilterGM : public skiagm::GM {
86 protected:
onShortName()87     SkString onShortName() override { return SkString("hslcolorfilter"); }
88 
onISize()89     SkISize onISize() override { return { 840, 1100 }; }
90 
onOnceBeforeDraw()91     void onOnceBeforeDraw() override {
92         sk_sp<SkImage> mandrill = GetResourceAsImage("images/mandrill_256.png");
93         const auto lm = SkMatrix::RectToRect(SkRect::MakeWH(mandrill->width(), mandrill->height()),
94                                              SkRect::MakeWH(kWheelSize, kWheelSize));
95         fShaders.push_back(mandrill->makeShader(SkSamplingOptions(), &lm));
96 
97         static constexpr SkColor gGrads[][4] = {
98             { 0xffff0000, 0xff00ff00, 0xff0000ff, 0xffff0000 },
99             { 0xdfc08040, 0xdf8040c0, 0xdf40c080, 0xdfc08040 },
100         };
101 
102         for (const auto& cols : gGrads) {
103             fShaders.push_back(SkGradientShader::MakeSweep(kWheelSize / 2, kWheelSize / 2,
104                                                            cols, nullptr, std::size(cols),
105                                                            SkTileMode::kRepeat, -90, 270, 0,
106                                                            nullptr));
107         }
108     }
109 
onDraw(SkCanvas * canvas)110     void onDraw(SkCanvas* canvas) override {
111         using std::make_tuple;
112 
113         static constexpr struct {
114             std::tuple<float, float> h, s, l;
115         } gTests[] = {
116             { make_tuple(-0.5f, 0.5f), make_tuple( 0.0f, 0.0f), make_tuple( 0.0f, 0.0f) },
117             { make_tuple( 0.0f, 0.0f), make_tuple(-1.0f, 1.0f), make_tuple( 0.0f, 0.0f) },
118             { make_tuple( 0.0f, 0.0f), make_tuple( 0.0f, 0.0f), make_tuple(-1.0f, 1.0f) },
119         };
120 
121         const auto rect = SkRect::MakeWH(kWheelSize, kWheelSize);
122 
123         canvas->drawColor(0xffcccccc);
124         SkPaint paint;
125 
126         for (const auto& shader : fShaders) {
127             paint.setShader(shader);
128 
129             for (const auto& tst: gTests) {
130                 canvas->translate(0, kWheelSize * 0.1f);
131 
132                 const auto dh = (std::get<1>(tst.h) - std::get<0>(tst.h)) / (kSteps - 1),
133                            ds = (std::get<1>(tst.s) - std::get<0>(tst.s)) / (kSteps - 1),
134                            dl = (std::get<1>(tst.l) - std::get<0>(tst.l)) / (kSteps - 1);
135                 auto h = std::get<0>(tst.h),
136                      s = std::get<0>(tst.s),
137                      l = std::get<0>(tst.l);
138                 {
139                     SkAutoCanvasRestore acr(canvas, true);
140                     for (size_t i = 0; i < kSteps; ++i) {
141                         paint.setColorFilter(make_filter(h, s, l));
142                         canvas->translate(kWheelSize * 0.1f, 0);
143                         canvas->drawRect(rect, paint);
144                         canvas->translate(kWheelSize * 1.1f, 0);
145                         h += dh;
146                         s += ds;
147                         l += dl;
148                     }
149                 }
150                 canvas->translate(0, kWheelSize * 1.1f);
151             }
152             canvas->translate(0, kWheelSize * 0.1f);
153         }
154     }
155 
156 private:
157     inline static constexpr SkScalar kWheelSize  = 100;
158     inline static constexpr size_t   kSteps = 7;
159 
make_filter(float h,float s,float l)160     static sk_sp<SkColorFilter> make_filter(float h, float s, float l) {
161         // These are roughly AE semantics.
162         const auto h_bias  = h,
163                    h_scale = 1.0f,
164                    s_bias  = std::max(s, 0.0f),
165                    s_scale = 1 - std::abs(s),
166                    l_bias  = std::max(l, 0.0f),
167                    l_scale = 1 - std::abs(l);
168 
169         const float cm[20] = {
170             h_scale,       0,       0, 0, h_bias,
171                   0, s_scale,       0, 0, s_bias,
172                   0,       0, l_scale, 0, l_bias,
173                   0,       0,       0, 1,      0,
174         };
175 
176         return SkColorFilters::HSLAMatrix(cm);
177     }
178 
179     std::vector<sk_sp<SkShader>> fShaders;
180 };
181 
182 DEF_GM(return new HSLColorFilterGM;)
183