blob: 0c547a1b9a286b45fa147f330441d1f47699ce14 [file] [log] [blame]
reed@google.comd5808bd2014-02-06 16:53:25 +00001/*
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
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "gm/gm.h"
9#include "include/core/SkCanvas.h"
Ben Wagner7fde8e12019-05-01 17:28:53 -040010#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"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050021#include "include/effects/SkColorMatrixFilter.h"
22#include "include/effects/SkGradientShader.h"
Florin Malita48009492019-08-01 17:20:19 -040023#include "tools/Resources.h"
24
25#include <vector>
26#include <tuple>
reed@google.comd5808bd2014-02-06 16:53:25 +000027
reed2ad1aa62016-03-09 09:50:50 -080028static sk_sp<SkShader> make_shader(const SkRect& bounds) {
reed@google.comd5808bd2014-02-06 16:53:25 +000029 const SkPoint pts[] = {
30 { bounds.left(), bounds.top() },
31 { bounds.right(), bounds.bottom() },
32 };
33 const SkColor colors[] = {
34 SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorBLACK,
35 SK_ColorCYAN, SK_ColorMAGENTA, SK_ColorYELLOW,
36 };
reed2ad1aa62016-03-09 09:50:50 -080037 return SkGradientShader::MakeLinear(pts, colors, nullptr, SK_ARRAY_COUNT(colors),
Mike Reedfae8fce2019-04-03 10:27:45 -040038 SkTileMode::kClamp);
reed@google.comd5808bd2014-02-06 16:53:25 +000039}
40
41typedef void (*InstallPaint)(SkPaint*, uint32_t, uint32_t);
42
43static void install_nothing(SkPaint* paint, uint32_t, uint32_t) {
halcanary96fcdcc2015-08-27 07:41:13 -070044 paint->setColorFilter(nullptr);
reed@google.comd5808bd2014-02-06 16:53:25 +000045}
46
47static void install_lighting(SkPaint* paint, uint32_t mul, uint32_t add) {
reedd053ce92016-03-22 10:17:23 -070048 paint->setColorFilter(SkColorMatrixFilter::MakeLightingFilter(mul, add));
reed@google.comd5808bd2014-02-06 16:53:25 +000049}
50
51class ColorFiltersGM : public skiagm::GM {
Hal Canarybd865e22019-07-18 11:51:19 -040052 SkString onShortName() override { return SkString("lightingcolorfilter"); }
reed@google.comd5808bd2014-02-06 16:53:25 +000053
Hal Canarybd865e22019-07-18 11:51:19 -040054 SkISize onISize() override { return {620, 430}; }
reed@google.comd5808bd2014-02-06 16:53:25 +000055
mtklein36352bf2015-03-25 18:17:31 -070056 void onDraw(SkCanvas* canvas) override {
Hal Canarybd865e22019-07-18 11:51:19 -040057 SkRect r = {0, 0, 600, 50};
58
reed@google.comd5808bd2014-02-06 16:53:25 +000059 SkPaint paint;
reed2ad1aa62016-03-09 09:50:50 -080060 paint.setShader(make_shader(r));
reed@google.comd5808bd2014-02-06 16:53:25 +000061
62 const struct {
63 InstallPaint fProc;
64 uint32_t fData0, fData1;
65 } rec[] = {
66 { install_nothing, 0, 0 },
67 { install_lighting, 0xFF0000, 0 },
68 { install_lighting, 0x00FF00, 0 },
69 { install_lighting, 0x0000FF, 0 },
70 { install_lighting, 0x000000, 0xFF0000 },
71 { install_lighting, 0x000000, 0x00FF00 },
72 { install_lighting, 0x000000, 0x0000FF },
73 };
74
75 canvas->translate(10, 10);
76 for (size_t i = 0; i < SK_ARRAY_COUNT(rec); ++i) {
77 rec[i].fProc(&paint, rec[i].fData0, rec[i].fData1);
78 canvas->drawRect(r, paint);
79 canvas->translate(0, r.height() + 10);
80 }
81 }
reed@google.comd5808bd2014-02-06 16:53:25 +000082};
83
halcanary385fe4d2015-08-26 13:07:48 -070084DEF_GM(return new ColorFiltersGM;)
Florin Malita48009492019-08-01 17:20:19 -040085
86class HSLColorFilterGM : public skiagm::GM {
87protected:
88 SkString onShortName() override { return SkString("hslcolorfilter"); }
89
90 SkISize onISize() override { return { 840, 1100 }; }
91
92 void onOnceBeforeDraw() override {
93 sk_sp<SkImage> mandrill = GetResourceAsImage("images/mandrill_256.png");
94 const auto lm = SkMatrix::MakeRectToRect(SkRect::MakeWH(mandrill->width(),
95 mandrill->height()),
96 SkRect::MakeWH(kWheelSize, kWheelSize),
97 SkMatrix::kFill_ScaleToFit);
98 fShaders.push_back(mandrill->makeShader(&lm));
99
100 static constexpr SkColor gGrads[][4] = {
101 { 0xffff0000, 0xff00ff00, 0xff0000ff, 0xffff0000 },
102 { 0xdfc08040, 0xdf8040c0, 0xdf40c080, 0xdfc08040 },
103 };
104
105 for (const auto& cols : gGrads) {
106 fShaders.push_back(SkGradientShader::MakeSweep(kWheelSize / 2, kWheelSize / 2,
107 cols, nullptr, SK_ARRAY_COUNT(cols),
108 SkTileMode::kRepeat, -90, 270, 0,
109 nullptr));
110 }
111 }
112
113 void onDraw(SkCanvas* canvas) override {
114 using std::make_tuple;
115
116 static constexpr struct {
117 std::tuple<float, float> h, s, l;
118 } gTests[] = {
119 { make_tuple(-0.5f, 0.5f), make_tuple( 0.0f, 0.0f), make_tuple( 0.0f, 0.0f) },
120 { make_tuple( 0.0f, 0.0f), make_tuple(-1.0f, 1.0f), make_tuple( 0.0f, 0.0f) },
121 { make_tuple( 0.0f, 0.0f), make_tuple( 0.0f, 0.0f), make_tuple(-1.0f, 1.0f) },
122 };
123
124 const auto rect = SkRect::MakeWH(kWheelSize, kWheelSize);
125
126 canvas->drawColor(0xffcccccc);
127 SkPaint paint;
128
129 for (const auto& shader : fShaders) {
130 paint.setShader(shader);
131
132 for (const auto& tst: gTests) {
133 canvas->translate(0, kWheelSize * 0.1f);
134
135 const auto dh = (std::get<1>(tst.h) - std::get<0>(tst.h)) / (kSteps - 1),
136 ds = (std::get<1>(tst.s) - std::get<0>(tst.s)) / (kSteps - 1),
137 dl = (std::get<1>(tst.l) - std::get<0>(tst.l)) / (kSteps - 1);
138 auto h = std::get<0>(tst.h),
139 s = std::get<0>(tst.s),
140 l = std::get<0>(tst.l);
141 {
142 SkAutoCanvasRestore acr(canvas, true);
143 for (size_t i = 0; i < kSteps; ++i) {
144 paint.setColorFilter(make_filter(h, s, l));
145 canvas->translate(kWheelSize * 0.1f, 0);
146 canvas->drawRect(rect, paint);
147 canvas->translate(kWheelSize * 1.1f, 0);
148 h += dh;
149 s += ds;
150 l += dl;
151 }
152 }
153 canvas->translate(0, kWheelSize * 1.1f);
154 }
155 canvas->translate(0, kWheelSize * 0.1f);
156 }
157 }
158
159private:
160 static constexpr SkScalar kWheelSize = 100;
161 static constexpr size_t kSteps = 7;
162
163 static sk_sp<SkColorFilter> make_filter(float h, float s, float l) {
164 // These are roughly AE semantics.
165 const auto h_bias = h,
166 h_scale = 1.0f,
167 s_bias = std::max(s, 0.0f),
168 s_scale = 1 - std::abs(s),
169 l_bias = std::max(l, 0.0f),
170 l_scale = 1 - std::abs(l);
171
172 const float cm[20] = {
173 h_scale, 0, 0, 0, h_bias,
174 0, s_scale, 0, 0, s_bias,
175 0, 0, l_scale, 0, l_bias,
176 0, 0, 0, 1, 0,
177 };
178
179 return SkColorFilters::HSLAMatrix(cm);
180 }
181
182 std::vector<sk_sp<SkShader>> fShaders;
183};
184
185DEF_GM(return new HSLColorFilterGM;)