1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright 2015 Google Inc.
3cb93a386Sopenharmony_ci *
4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be
5cb93a386Sopenharmony_ci * found in the LICENSE file.
6cb93a386Sopenharmony_ci */
7cb93a386Sopenharmony_ci
8cb93a386Sopenharmony_ci#include "include/core/SkBitmap.h"
9cb93a386Sopenharmony_ci#include "include/core/SkCanvas.h"
10cb93a386Sopenharmony_ci#include "include/core/SkColor.h"
11cb93a386Sopenharmony_ci#include "include/core/SkColorFilter.h"
12cb93a386Sopenharmony_ci#include "include/core/SkPaint.h"
13cb93a386Sopenharmony_ci#include "include/core/SkRefCnt.h"
14cb93a386Sopenharmony_ci#include "tests/Test.h"
15cb93a386Sopenharmony_ci
16cb93a386Sopenharmony_ci#include <cmath>
17cb93a386Sopenharmony_ci#include <cstdlib>
18cb93a386Sopenharmony_ci
19cb93a386Sopenharmony_cistatic inline void assert_color(skiatest::Reporter* reporter,
20cb93a386Sopenharmony_ci                                SkColor expected, SkColor actual, int tolerance) {
21cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, abs((int)(SkColorGetA(expected) - SkColorGetA(actual))) <= tolerance);
22cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, abs((int)(SkColorGetR(expected) - SkColorGetR(actual))) <= tolerance);
23cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, abs((int)(SkColorGetG(expected) - SkColorGetG(actual))) <= tolerance);
24cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, abs((int)(SkColorGetB(expected) - SkColorGetB(actual))) <= tolerance);
25cb93a386Sopenharmony_ci}
26cb93a386Sopenharmony_ci
27cb93a386Sopenharmony_cistatic inline void assert_color(skiatest::Reporter* reporter, SkColor expected, SkColor actual) {
28cb93a386Sopenharmony_ci    const int TOLERANCE = 1;
29cb93a386Sopenharmony_ci    assert_color(reporter, expected, actual, TOLERANCE);
30cb93a386Sopenharmony_ci}
31cb93a386Sopenharmony_ci
32cb93a386Sopenharmony_ci/**
33cb93a386Sopenharmony_ci * This test case is a mirror of the Android CTS tests for MatrixColorFilter
34cb93a386Sopenharmony_ci * found in the android.graphics.ColorMatrixColorFilterTest class.
35cb93a386Sopenharmony_ci */
36cb93a386Sopenharmony_cistatic inline void test_colorMatrixCTS(skiatest::Reporter* reporter) {
37cb93a386Sopenharmony_ci
38cb93a386Sopenharmony_ci    SkBitmap bitmap;
39cb93a386Sopenharmony_ci    bitmap.allocN32Pixels(1,1);
40cb93a386Sopenharmony_ci
41cb93a386Sopenharmony_ci    SkCanvas canvas(bitmap);
42cb93a386Sopenharmony_ci    SkPaint paint;
43cb93a386Sopenharmony_ci
44cb93a386Sopenharmony_ci    float blueToCyan[20] = {
45cb93a386Sopenharmony_ci            1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
46cb93a386Sopenharmony_ci            0.0f, 1.0f, 1.0f, 0.0f, 0.0f,
47cb93a386Sopenharmony_ci            0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
48cb93a386Sopenharmony_ci            0.0f, 0.0f, 0.0f, 1.0f, 0.0f };
49cb93a386Sopenharmony_ci    paint.setColorFilter(SkColorFilters::Matrix(blueToCyan));
50cb93a386Sopenharmony_ci
51cb93a386Sopenharmony_ci    paint.setColor(SK_ColorBLUE);
52cb93a386Sopenharmony_ci    canvas.drawPoint(0, 0, paint);
53cb93a386Sopenharmony_ci    assert_color(reporter, SK_ColorCYAN, bitmap.getColor(0, 0));
54cb93a386Sopenharmony_ci
55cb93a386Sopenharmony_ci    paint.setColor(SK_ColorGREEN);
56cb93a386Sopenharmony_ci    canvas.drawPoint(0, 0, paint);
57cb93a386Sopenharmony_ci    assert_color(reporter, SK_ColorGREEN, bitmap.getColor(0, 0));
58cb93a386Sopenharmony_ci
59cb93a386Sopenharmony_ci    paint.setColor(SK_ColorRED);
60cb93a386Sopenharmony_ci    canvas.drawPoint(0, 0, paint);
61cb93a386Sopenharmony_ci    assert_color(reporter, SK_ColorRED, bitmap.getColor(0, 0));
62cb93a386Sopenharmony_ci
63cb93a386Sopenharmony_ci    // color components are clipped, not scaled
64cb93a386Sopenharmony_ci    paint.setColor(SK_ColorMAGENTA);
65cb93a386Sopenharmony_ci    canvas.drawPoint(0, 0, paint);
66cb93a386Sopenharmony_ci    assert_color(reporter, SK_ColorWHITE, bitmap.getColor(0, 0));
67cb93a386Sopenharmony_ci
68cb93a386Sopenharmony_ci    float transparentRedAddBlue[20] = {
69cb93a386Sopenharmony_ci            1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
70cb93a386Sopenharmony_ci            0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
71cb93a386Sopenharmony_ci            0.0f, 0.0f, 1.0f, 0.0f, 64.0f/255,
72cb93a386Sopenharmony_ci           -0.5f, 0.0f, 0.0f, 1.0f, 0.0f
73cb93a386Sopenharmony_ci    };
74cb93a386Sopenharmony_ci    paint.setColorFilter(SkColorFilters::Matrix(transparentRedAddBlue));
75cb93a386Sopenharmony_ci    bitmap.eraseColor(SK_ColorTRANSPARENT);
76cb93a386Sopenharmony_ci
77cb93a386Sopenharmony_ci    paint.setColor(SK_ColorRED);
78cb93a386Sopenharmony_ci    canvas.drawPoint(0, 0, paint);
79cb93a386Sopenharmony_ci    assert_color(reporter, SkColorSetARGB(128, 255, 0, 64), bitmap.getColor(0, 0), 2);
80cb93a386Sopenharmony_ci
81cb93a386Sopenharmony_ci    paint.setColor(SK_ColorCYAN);
82cb93a386Sopenharmony_ci    canvas.drawPoint(0, 0, paint);
83cb93a386Sopenharmony_ci    // blue gets clipped
84cb93a386Sopenharmony_ci    assert_color(reporter, SK_ColorCYAN, bitmap.getColor(0, 0));
85cb93a386Sopenharmony_ci
86cb93a386Sopenharmony_ci    // change array to filter out green
87cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, 1.0f == transparentRedAddBlue[6]);
88cb93a386Sopenharmony_ci    transparentRedAddBlue[6] = 0.0f;
89cb93a386Sopenharmony_ci
90cb93a386Sopenharmony_ci    // check that changing the array has no effect
91cb93a386Sopenharmony_ci    canvas.drawPoint(0, 0, paint);
92cb93a386Sopenharmony_ci    assert_color(reporter, SK_ColorCYAN, bitmap.getColor(0, 0));
93cb93a386Sopenharmony_ci
94cb93a386Sopenharmony_ci    // create a new filter with the changed matrix
95cb93a386Sopenharmony_ci    paint.setColorFilter(SkColorFilters::Matrix(transparentRedAddBlue));
96cb93a386Sopenharmony_ci    canvas.drawPoint(0, 0, paint);
97cb93a386Sopenharmony_ci    assert_color(reporter, SK_ColorBLUE, bitmap.getColor(0, 0));
98cb93a386Sopenharmony_ci}
99cb93a386Sopenharmony_ci
100cb93a386Sopenharmony_ciDEF_TEST(ColorMatrix, reporter) {
101cb93a386Sopenharmony_ci    test_colorMatrixCTS(reporter);
102cb93a386Sopenharmony_ci}
103cb93a386Sopenharmony_ci
104cb93a386Sopenharmony_ci
105cb93a386Sopenharmony_ciDEF_TEST(ColorMatrix_clamp_while_unpremul, r) {
106cb93a386Sopenharmony_ci    // This matrix does green += 255/255 and alpha += 32/255.  We want to test
107cb93a386Sopenharmony_ci    // that if we pass it opaque alpha and small red and blue values, red and
108cb93a386Sopenharmony_ci    // blue stay unchanged, not pumped up by that ~1.12 intermediate alpha.
109cb93a386Sopenharmony_ci    float m[] = {
110cb93a386Sopenharmony_ci        1, 0, 0, 0, 0,
111cb93a386Sopenharmony_ci        0, 1, 0, 0, 1,
112cb93a386Sopenharmony_ci        0, 0, 1, 0, 0,
113cb93a386Sopenharmony_ci        0, 0, 0, 1, 32.0f/255,
114cb93a386Sopenharmony_ci    };
115cb93a386Sopenharmony_ci    auto filter = SkColorFilters::Matrix(m);
116cb93a386Sopenharmony_ci
117cb93a386Sopenharmony_ci    SkColor filtered = filter->filterColor(0xff0a0b0c);
118cb93a386Sopenharmony_ci    REPORTER_ASSERT(r, SkColorGetA(filtered) == 0xff);
119cb93a386Sopenharmony_ci    REPORTER_ASSERT(r, SkColorGetR(filtered) == 0x0a);
120cb93a386Sopenharmony_ci    REPORTER_ASSERT(r, SkColorGetG(filtered) == 0xff);
121cb93a386Sopenharmony_ci    REPORTER_ASSERT(r, SkColorGetB(filtered) == 0x0c);
122cb93a386Sopenharmony_ci}
123