reed@google.com | d5808bd | 2014-02-06 16:53:25 +0000 | [diff] [blame] | 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 | |
Mike Klein | c0bd9f9 | 2019-04-23 12:05:21 -0500 | [diff] [blame] | 8 | #include "gm/gm.h" |
| 9 | #include "include/core/SkCanvas.h" |
Ben Wagner | 7fde8e1 | 2019-05-01 17:28:53 -0400 | [diff] [blame] | 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" |
Mike Klein | c0bd9f9 | 2019-04-23 12:05:21 -0500 | [diff] [blame] | 21 | #include "include/effects/SkColorMatrixFilter.h" |
| 22 | #include "include/effects/SkGradientShader.h" |
Florin Malita | 4800949 | 2019-08-01 17:20:19 -0400 | [diff] [blame] | 23 | #include "tools/Resources.h" |
| 24 | |
| 25 | #include <vector> |
| 26 | #include <tuple> |
reed@google.com | d5808bd | 2014-02-06 16:53:25 +0000 | [diff] [blame] | 27 | |
reed | 2ad1aa6 | 2016-03-09 09:50:50 -0800 | [diff] [blame] | 28 | static sk_sp<SkShader> make_shader(const SkRect& bounds) { |
reed@google.com | d5808bd | 2014-02-06 16:53:25 +0000 | [diff] [blame] | 29 | 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 | }; |
reed | 2ad1aa6 | 2016-03-09 09:50:50 -0800 | [diff] [blame] | 37 | return SkGradientShader::MakeLinear(pts, colors, nullptr, SK_ARRAY_COUNT(colors), |
Mike Reed | fae8fce | 2019-04-03 10:27:45 -0400 | [diff] [blame] | 38 | SkTileMode::kClamp); |
reed@google.com | d5808bd | 2014-02-06 16:53:25 +0000 | [diff] [blame] | 39 | } |
| 40 | |
| 41 | typedef void (*InstallPaint)(SkPaint*, uint32_t, uint32_t); |
| 42 | |
| 43 | static void install_nothing(SkPaint* paint, uint32_t, uint32_t) { |
halcanary | 96fcdcc | 2015-08-27 07:41:13 -0700 | [diff] [blame] | 44 | paint->setColorFilter(nullptr); |
reed@google.com | d5808bd | 2014-02-06 16:53:25 +0000 | [diff] [blame] | 45 | } |
| 46 | |
| 47 | static void install_lighting(SkPaint* paint, uint32_t mul, uint32_t add) { |
reed | d053ce9 | 2016-03-22 10:17:23 -0700 | [diff] [blame] | 48 | paint->setColorFilter(SkColorMatrixFilter::MakeLightingFilter(mul, add)); |
reed@google.com | d5808bd | 2014-02-06 16:53:25 +0000 | [diff] [blame] | 49 | } |
| 50 | |
| 51 | class ColorFiltersGM : public skiagm::GM { |
Hal Canary | bd865e2 | 2019-07-18 11:51:19 -0400 | [diff] [blame] | 52 | SkString onShortName() override { return SkString("lightingcolorfilter"); } |
reed@google.com | d5808bd | 2014-02-06 16:53:25 +0000 | [diff] [blame] | 53 | |
Hal Canary | bd865e2 | 2019-07-18 11:51:19 -0400 | [diff] [blame] | 54 | SkISize onISize() override { return {620, 430}; } |
reed@google.com | d5808bd | 2014-02-06 16:53:25 +0000 | [diff] [blame] | 55 | |
mtklein | 36352bf | 2015-03-25 18:17:31 -0700 | [diff] [blame] | 56 | void onDraw(SkCanvas* canvas) override { |
Hal Canary | bd865e2 | 2019-07-18 11:51:19 -0400 | [diff] [blame] | 57 | SkRect r = {0, 0, 600, 50}; |
| 58 | |
reed@google.com | d5808bd | 2014-02-06 16:53:25 +0000 | [diff] [blame] | 59 | SkPaint paint; |
reed | 2ad1aa6 | 2016-03-09 09:50:50 -0800 | [diff] [blame] | 60 | paint.setShader(make_shader(r)); |
reed@google.com | d5808bd | 2014-02-06 16:53:25 +0000 | [diff] [blame] | 61 | |
| 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.com | d5808bd | 2014-02-06 16:53:25 +0000 | [diff] [blame] | 82 | }; |
| 83 | |
halcanary | 385fe4d | 2015-08-26 13:07:48 -0700 | [diff] [blame] | 84 | DEF_GM(return new ColorFiltersGM;) |
Florin Malita | 4800949 | 2019-08-01 17:20:19 -0400 | [diff] [blame] | 85 | |
| 86 | class HSLColorFilterGM : public skiagm::GM { |
| 87 | protected: |
| 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 | |
| 159 | private: |
| 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 | |
| 185 | DEF_GM(return new HSLColorFilterGM;) |