123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206 |
- /*
- * Copyright 2019 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
- #include "gm/gm.h"
- #include "include/core/SkCanvas.h"
- #include "include/core/SkColor.h"
- #include "include/core/SkColorFilter.h"
- #include "include/core/SkImage.h"
- #include "include/core/SkMatrix.h"
- #include "include/core/SkPaint.h"
- #include "include/core/SkPoint.h"
- #include "include/core/SkRect.h"
- #include "include/core/SkRefCnt.h"
- #include "include/core/SkScalar.h"
- #include "include/core/SkShader.h"
- #include "include/core/SkSize.h"
- #include "include/core/SkString.h"
- #include "include/core/SkTileMode.h"
- #include "include/core/SkTypes.h"
- #include "include/effects/SkGradientShader.h"
- #include "include/effects/SkLumaColorFilter.h"
- #include "tools/Resources.h"
- #include <math.h>
- // A tint filter maps colors to a given range (gradient), based on the input luminance:
- //
- // c' = lerp(lo, hi, luma(c))
- //
- // TODO: move to public headers/API?
- //
- static sk_sp<SkColorFilter> MakeTintColorFilter(SkColor lo, SkColor hi) {
- const auto r_lo = SkColorGetR(lo),
- g_lo = SkColorGetG(lo),
- b_lo = SkColorGetB(lo),
- a_lo = SkColorGetA(lo),
- r_hi = SkColorGetR(hi),
- g_hi = SkColorGetG(hi),
- b_hi = SkColorGetB(hi),
- a_hi = SkColorGetA(hi);
- // We map component-wise:
- //
- // r' = lo.r + (hi.r - lo.r) * luma
- // g' = lo.g + (hi.g - lo.g) * luma
- // b' = lo.b + (hi.b - lo.b) * luma
- // a' = lo.a + (hi.a - lo.a) * luma
- //
- // The input luminance is stored in the alpha channel
- // (and RGB are cleared -- see SkLumaColorFilter). Thus:
- const float tint_matrix[] = {
- 0, 0, 0, (r_hi - r_lo) / 255.0f, SkIntToScalar(r_lo) / 255.0f,
- 0, 0, 0, (g_hi - g_lo) / 255.0f, SkIntToScalar(g_lo) / 255.0f,
- 0, 0, 0, (b_hi - b_lo) / 255.0f, SkIntToScalar(b_lo) / 255.0f,
- 0, 0, 0, (a_hi - a_lo) / 255.0f, SkIntToScalar(a_lo) / 255.0f,
- };
- return SkColorFilters::Matrix(tint_matrix)
- ->makeComposed(SkLumaColorFilter::Make());
- }
- namespace {
- class MixerCFGM final : public skiagm::GM {
- public:
- MixerCFGM(const SkSize& tileSize, size_t tileCount)
- : fTileSize(tileSize)
- , fTileCount(tileCount) {}
- protected:
- SkString onShortName() override {
- return SkString("mixerCF");
- }
- SkISize onISize() override {
- return SkISize::Make(fTileSize.width() * 1.2f * fTileCount,
- fTileSize.height() * 1.2f * 3); // 3 rows
- }
- void onDraw(SkCanvas* canvas) override {
- SkPaint paint;
- const SkColor gradient_colors[] = { SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorRED };
- paint.setShader(SkGradientShader::MakeSweep(fTileSize.width() / 2,
- fTileSize.height() / 2,
- gradient_colors, nullptr,
- SK_ARRAY_COUNT(gradient_colors)));
- auto cf0 = MakeTintColorFilter(0xff300000, 0xffa00000); // red tint
- auto cf1 = MakeTintColorFilter(0xff003000, 0xff00a000); // green tint
- this->mixRow(canvas, paint, nullptr, cf1);
- this->mixRow(canvas, paint, cf0, nullptr);
- this->mixRow(canvas, paint, cf0, cf1);
- }
- private:
- const SkSize fTileSize;
- const size_t fTileCount;
- void mixRow(SkCanvas* canvas, SkPaint& paint,
- sk_sp<SkColorFilter> cf0, sk_sp<SkColorFilter> cf1) {
- canvas->translate(0, fTileSize.height() * 0.1f);
- {
- SkAutoCanvasRestore arc(canvas, true);
- for (size_t i = 0; i < fTileCount; ++i) {
- paint.setColorFilter(
- SkColorFilters::Lerp(static_cast<float>(i) / (fTileCount - 1), cf0, cf1));
- canvas->translate(fTileSize.width() * 0.1f, 0);
- canvas->drawRect(SkRect::MakeWH(fTileSize.width(), fTileSize.height()), paint);
- canvas->translate(fTileSize.width() * 1.1f, 0);
- }
- }
- canvas->translate(0, fTileSize.height() * 1.1f);
- }
- using INHERITED = skiagm::GM;
- };
- } // namespace
- DEF_GM( return new MixerCFGM(SkSize::Make(200, 250), 5); )
- static sk_sp<SkShader> make_resource_shader(const char path[], int size) {
- auto img = GetResourceAsImage(path);
- if (!img) {
- return nullptr;
- }
- SkRect src = SkRect::MakeIWH(img->width(), img->height());
- SkRect dst = SkRect::MakeIWH(size, size);
- SkMatrix m;
- m.setRectToRect(src, dst, SkMatrix::kFill_ScaleToFit);
- return img->makeShader(&m);
- }
- static sk_sp<SkShader> make_grad(int size, float t) {
- SkASSERT(t >= 0 && t <= 1);
- unsigned r = SkScalarRoundToInt(t * 255);
- SkColor c = SkColorSetARGB(r, r, 0, 0);
- SkColor colors[] = { 0, c, SK_ColorRED };
- SkPoint pts[] = {{0, 0}, {size*1.0f, size*1.0f}};
- SkScalar pos[] = {0, 1 - t, 1.0f};
- return SkGradientShader::MakeLinear(pts, colors, pos, SK_ARRAY_COUNT(colors),
- SkTileMode::kClamp);
- }
- class ShaderMixerGM final : public skiagm::GM {
- enum { SIZE = 256 };
- float fPos = 0.5f;
- sk_sp<SkShader> fS0, fS1;
- public:
- ShaderMixerGM() {}
- protected:
- SkString onShortName() override {
- return SkString("mixershader_shadermixer");
- }
- void onOnceBeforeDraw() override {
- fS0 = make_resource_shader("images/mandrill_256.png", SIZE);
- fS1 = make_resource_shader("images/baby_tux.png", SIZE);
- }
- SkISize onISize() override { return {542, 542}; }
- void onDraw(SkCanvas* canvas) override {
- SkRect r = SkRect::MakeIWH(SIZE, SIZE);
- SkPaint paint;
- canvas->translate(10, 10);
- canvas->save();
- paint.setShader(fS0);
- canvas->drawRect(r, paint);
- canvas->translate(SIZE + 10.0f, 0);
- paint.setShader(fS1);
- canvas->drawRect(r, paint);
- canvas->restore();
- auto sh2 = make_grad(SIZE, fPos);
- canvas->translate(0, SIZE + 10.0f);
- paint.setShader(sh2);
- canvas->drawRect(r, paint);
- auto sh = SkShaders::Lerp(sh2, fS0, fS1);
- canvas->translate(SIZE + 10.0f, 0);
- paint.setShader(sh);
- canvas->drawRect(r, paint);
- }
- bool onAnimate(double nanos) override {
- fPos = (sin(1e-9 * nanos) + 1) * 0.5f;
- return true;
- }
- private:
- using INHERITED = skiagm::GM;
- };
- DEF_GM( return new ShaderMixerGM; )
|