1/*
2 * Copyright 2016 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.h"
9#include "SkColor.h"
10#include "SkColorSpaceXform.h"
11#include "SkRect.h"
12#include "SkShader.h"
13
14class ColorSpaceXformGM : public skiagm::GM {
15public:
16    ColorSpaceXformGM() {}
17
18protected:
19    void onOnceBeforeDraw() override {
20        SkColor colors[] = {
21            SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorMAGENTA, SK_ColorCYAN, SK_ColorYELLOW,
22            SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorMAGENTA,
23        };
24        static_assert(kNumColors == SK_ARRAY_COUNT(colors), "Fix number of colors.");
25
26        for (int i = 0; i < kNumColors; i++) {
27            fSRGBColors[i] = SkColor4f::FromColor(colors[i]);
28        }
29
30        static constexpr float kWideGamutRGB_toXYZD50[]{
31            0.7161046f, 0.1009296f, 0.1471858f,
32            0.2581874f, 0.7249378f, 0.0168748f,
33            0.0000000f, 0.0517813f, 0.7734287f,
34        };
35
36        SkMatrix44 wideGamut(SkMatrix44::kUninitialized_Constructor);
37        wideGamut.set3x3RowMajorf(kWideGamutRGB_toXYZD50);
38
39        // Test BGRA input.
40        sk_sp<SkColorSpace> srcSpace = SkColorSpace::MakeSRGB();
41        sk_sp<SkColorSpace> dstSpace =
42                SkColorSpace::MakeRGB(SkColorSpace::kLinear_RenderTargetGamma, wideGamut);
43        std::unique_ptr<SkColorSpaceXform> xform = SkColorSpaceXform::New(srcSpace.get(),
44                                                                          dstSpace.get());
45        xform->apply(SkColorSpaceXform::kRGBA_F32_ColorFormat, fWideGamutColors0,
46                     SkColorSpaceXform::kBGRA_8888_ColorFormat, colors, kNumColors,
47                     kOpaque_SkAlphaType);
48
49        // Test F32 input.
50        srcSpace = srcSpace->makeLinearGamma();
51        xform = SkColorSpaceXform::New(srcSpace.get(), dstSpace.get());
52        xform->apply(SkColorSpaceXform::kRGBA_F32_ColorFormat, fWideGamutColors1,
53                     SkColorSpaceXform::kRGBA_F32_ColorFormat, fSRGBColors, kNumColors,
54                     kOpaque_SkAlphaType);
55    }
56
57    SkString onShortName() override {
58        return SkString("colorspacexform");
59    }
60
61    SkISize onISize() override {
62        return SkISize::Make(500, 300);
63    }
64
65    void onDraw(SkCanvas* canvas) override {
66        auto drawColors = [canvas](SkColor4f* colors) {
67            SkRect r = SkRect::MakeXYWH(0.0f, 0.0f, 50.0f, 100.0f);
68
69            canvas->save();
70            for (int i = 0; i < kNumColors; i++) {
71                auto space = SkColorSpace::MakeSRGBLinear();
72                sk_sp<SkShader> s = SkShader::MakeColorShader(colors[i], space);
73                SkPaint paint;
74                paint.setShader(s);
75                canvas->drawRect(r, paint);
76                canvas->translate(50.0f, 0.0f);
77            }
78            canvas->restore();
79        };
80
81        // Wide gamut colors should appear darker - we are simulating a more intense display.
82        drawColors(fSRGBColors);
83        canvas->translate(0.0f, 100.0f);
84        drawColors(fWideGamutColors0);
85        canvas->translate(0.0f, 100.0f);
86        drawColors(fWideGamutColors1);
87    }
88
89private:
90    static constexpr int kNumColors = 10;
91
92    SkColor4f fSRGBColors[kNumColors];
93    SkColor4f fWideGamutColors0[kNumColors];
94    SkColor4f fWideGamutColors1[kNumColors];
95
96    typedef skiagm::GM INHERITED;
97};
98
99DEF_GM(return new ColorSpaceXformGM;)
100