1/*
2 * Copyright 2011 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 "SkColorMatrixFilter.h"
10#include "SkGradientShader.h"
11#include "SkImage.h"
12
13#define WIDTH 500
14#define HEIGHT 500
15
16static void set_color_matrix(SkPaint* paint, const SkColorMatrix& matrix) {
17    paint->setColorFilter(SkColorMatrixFilter::Create(matrix))->unref();
18}
19
20static void set_array(SkPaint* paint, const SkScalar array[]) {
21    paint->setColorFilter(SkColorMatrixFilter::Create(array))->unref();
22}
23
24class ColorMatrixGM : public skiagm::GM {
25public:
26    ColorMatrixGM() {
27        this->setBGColor(sk_tool_utils::color_to_565(0xFF808080));
28    }
29
30protected:
31    SkString onShortName() override {
32        return SkString("colormatrix");
33    }
34
35    SkISize onISize() override {
36        return SkISize::Make(WIDTH, HEIGHT);
37    }
38
39    void onOnceBeforeDraw() override {
40        fSolidImg.reset(CreateSolidBitmap(64, 64));
41        fTransparentImg.reset(CreateTransparentBitmap(64, 64));
42    }
43
44    static SkImage* CreateSolidBitmap(int width, int height) {
45        SkBitmap bm;
46        bm.allocN32Pixels(width, height);
47        SkCanvas canvas(bm);
48        canvas.clear(0x0);
49        for (int y = 0; y < height; ++y) {
50            for (int x = 0; x < width; ++x) {
51                SkPaint paint;
52                paint.setColor(SkColorSetARGB(255, x * 255 / width, y * 255 / height, 0));
53                canvas.drawRect(SkRect::MakeXYWH(SkIntToScalar(x),
54                    SkIntToScalar(y), SK_Scalar1, SK_Scalar1), paint);
55            }
56        }
57        return SkImage::NewFromBitmap(bm);
58    }
59
60    // creates a bitmap with shades of transparent gray.
61    static SkImage* CreateTransparentBitmap(int width, int height) {
62        SkBitmap bm;
63        bm.allocN32Pixels(width, height);
64        SkCanvas canvas(bm);
65        canvas.clear(0x0);
66
67        SkPoint pts[] = {{0, 0}, {SkIntToScalar(width), SkIntToScalar(height)}};
68        SkColor colors[] = {0x00000000, 0xFFFFFFFF};
69        SkPaint paint;
70        paint.setShader(SkGradientShader::CreateLinear(pts, colors, nullptr, 2,
71                                                       SkShader::kClamp_TileMode))->unref();
72        canvas.drawRect(SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height)), paint);
73        return SkImage::NewFromBitmap(bm);
74    }
75
76    void onDraw(SkCanvas* canvas) override {
77        SkPaint paint;
78        SkColorMatrix matrix;
79
80        paint.setXfermodeMode(SkXfermode::kSrc_Mode);
81        const SkImage* bmps[] = { fSolidImg, fTransparentImg };
82
83        for (size_t i = 0; i < SK_ARRAY_COUNT(bmps); ++i) {
84            matrix.setIdentity();
85            set_color_matrix(&paint, matrix);
86            canvas->drawImage(bmps[i], 0, 0, &paint);
87
88            matrix.setRotate(SkColorMatrix::kR_Axis, 90);
89            set_color_matrix(&paint, matrix);
90            canvas->drawImage(bmps[i], 80, 0, &paint);
91
92            matrix.setRotate(SkColorMatrix::kG_Axis, 90);
93            set_color_matrix(&paint, matrix);
94            canvas->drawImage(bmps[i], 160, 0, &paint);
95
96            matrix.setRotate(SkColorMatrix::kB_Axis, 90);
97            set_color_matrix(&paint, matrix);
98            canvas->drawImage(bmps[i], 240, 0, &paint);
99            ///////////////////////////////////////////////
100            matrix.setSaturation(0.0f);
101            set_color_matrix(&paint, matrix);
102            canvas->drawImage(bmps[i], 0, 80, &paint);
103
104            matrix.setSaturation(0.5f);
105            set_color_matrix(&paint, matrix);
106            canvas->drawImage(bmps[i], 80, 80, &paint);
107
108            matrix.setSaturation(1.0f);
109            set_color_matrix(&paint, matrix);
110            canvas->drawImage(bmps[i], 160, 80, &paint);
111
112            matrix.setSaturation(2.0f);
113            set_color_matrix(&paint, matrix);
114            canvas->drawImage(bmps[i], 240, 80, &paint);
115            ///////////////////////////////////////////////
116            matrix.setRGB2YUV();
117            set_color_matrix(&paint, matrix);
118            canvas->drawImage(bmps[i], 0, 160, &paint);
119
120            matrix.setYUV2RGB();
121            set_color_matrix(&paint, matrix);
122            canvas->drawImage(bmps[i], 80, 160, &paint);
123
124            SkScalar s1 = SK_Scalar1;
125            SkScalar s255 = SkIntToScalar(255);
126            // Move red into alpha, set color to white
127            SkScalar data[20] = {
128                0,  0, 0, 0, s255,
129                0,  0, 0, 0, s255,
130                0,  0, 0, 0, s255,
131                s1, 0, 0, 0, 0,
132            };
133
134            set_array(&paint, data);
135            canvas->drawImage(bmps[i], 160, 160, &paint);
136            ///////////////////////////////////////////////
137            canvas->translate(0, 240);
138        }
139    }
140
141private:
142    SkAutoTUnref<SkImage>   fSolidImg;
143    SkAutoTUnref<SkImage>   fTransparentImg;
144
145    typedef skiagm::GM INHERITED;
146};
147DEF_GM( return new ColorMatrixGM; )
148
149