blob: b2e37183b5e7b223cf1d545ee8138a5311e68b64 [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001/*
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 */
tfarina@chromium.orge4fafb12013-12-12 21:11:12 +00007
reed@google.com43c50c82011-04-14 15:50:52 +00008#include "SkColor.h"
9#include "SkColorFilter.h"
tfarina@chromium.org8f6884a2014-01-24 20:56:26 +000010#include "SkColorPriv.h"
commit-bot@chromium.org6c1ee2d2013-10-07 18:00:17 +000011#include "SkLumaColorFilter.h"
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +000012#include "SkReadBuffer.h"
13#include "SkWriteBuffer.h"
tfarina@chromium.org8f6884a2014-01-24 20:56:26 +000014#include "SkRandom.h"
15#include "SkXfermode.h"
16#include "Test.h"
reed@google.com43c50c82011-04-14 15:50:52 +000017
reed@google.com35348222013-10-16 13:05:06 +000018static SkColorFilter* reincarnate_colorfilter(SkFlattenable* obj) {
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +000019 SkWriteBuffer wb;
djsollen@google.comcefc8652012-03-26 15:52:10 +000020 wb.writeFlattenable(obj);
reed@google.com43c50c82011-04-14 15:50:52 +000021
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +000022 size_t size = wb.bytesWritten();
reed@google.com43c50c82011-04-14 15:50:52 +000023 SkAutoSMalloc<1024> storage(size);
24 // make a copy into storage
djsollen@google.comc73dd5c2012-08-07 15:54:32 +000025 wb.writeToMemory(storage.get());
reed@google.com43c50c82011-04-14 15:50:52 +000026
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +000027 SkReadBuffer rb(storage.get(), size);
reed@google.com35348222013-10-16 13:05:06 +000028 return rb.readColorFilter();
reed@google.com43c50c82011-04-14 15:50:52 +000029}
30
31///////////////////////////////////////////////////////////////////////////////
32
reeddc812222015-03-05 07:21:02 -080033static SkColorFilter* make_filter() {
34 // pick a filter that cannot compose with itself via newComposed()
35 return SkColorFilter::CreateModeFilter(SK_ColorRED, SkXfermode::kColorBurn_Mode);
36}
37
38static void test_composecolorfilter_limit(skiatest::Reporter* reporter) {
39 // Test that CreateComposeFilter() has some finite limit (i.e. that the factory can return null)
40 const int way_too_many = 100;
41 SkAutoTUnref<SkColorFilter> parent(make_filter());
42 for (int i = 2; i < way_too_many; ++i) {
43 SkAutoTUnref<SkColorFilter> filter(make_filter());
44 parent.reset(SkColorFilter::CreateComposeFilter(parent, filter));
45 if (NULL == parent) {
46 REPORTER_ASSERT(reporter, i > 2); // we need to have succeeded at least once!
47 return;
48 }
49 }
50 REPORTER_ASSERT(reporter, false); // we never saw a NULL :(
51}
52
reed@google.com43c50c82011-04-14 15:50:52 +000053#define ILLEGAL_MODE ((SkXfermode::Mode)-1)
54
tfarina@chromium.orge4fafb12013-12-12 21:11:12 +000055DEF_TEST(ColorFilter, reporter) {
commit-bot@chromium.orge0e7cfe2013-09-09 20:09:12 +000056 SkRandom rand;
reed@google.com43c50c82011-04-14 15:50:52 +000057
58 for (int mode = 0; mode <= SkXfermode::kLastMode; mode++) {
59 SkColor color = rand.nextU();
60
61 // ensure we always get a filter, by avoiding the possibility of a
62 // special case that would return NULL (if color's alpha is 0 or 0xFF)
63 color = SkColorSetA(color, 0x7F);
64
65 SkColorFilter* cf = SkColorFilter::CreateModeFilter(color,
66 (SkXfermode::Mode)mode);
67
68 // allow for no filter if we're in Dst mode (its a no op)
69 if (SkXfermode::kDst_Mode == mode && NULL == cf) {
70 continue;
71 }
72
73 SkAutoUnref aur(cf);
74 REPORTER_ASSERT(reporter, cf);
75
76 SkColor c = ~color;
77 SkXfermode::Mode m = ILLEGAL_MODE;
78
79 SkColor expectedColor = color;
80 SkXfermode::Mode expectedMode = (SkXfermode::Mode)mode;
81
82// SkDebugf("--- mc [%d %x] ", mode, color);
83
84 REPORTER_ASSERT(reporter, cf->asColorMode(&c, &m));
85 // handle special-case folding by the factory
86 if (SkXfermode::kClear_Mode == mode) {
87 if (c != expectedColor) {
88 expectedColor = 0;
89 }
90 if (m != expectedMode) {
91 expectedMode = SkXfermode::kSrc_Mode;
92 }
rmistry@google.comd6176b02012-08-23 18:14:13 +000093 }
reed@google.com43c50c82011-04-14 15:50:52 +000094
95// SkDebugf("--- got [%d %x] expected [%d %x]\n", m, c, expectedMode, expectedColor);
96
97 REPORTER_ASSERT(reporter, c == expectedColor);
98 REPORTER_ASSERT(reporter, m == expectedMode);
rmistry@google.comd6176b02012-08-23 18:14:13 +000099
reed@google.com43c50c82011-04-14 15:50:52 +0000100 {
reed@google.com35348222013-10-16 13:05:06 +0000101 SkColorFilter* cf2 = reincarnate_colorfilter(cf);
reed@google.com43c50c82011-04-14 15:50:52 +0000102 SkAutoUnref aur2(cf2);
103 REPORTER_ASSERT(reporter, cf2);
104
105 SkColor c2 = ~color;
106 SkXfermode::Mode m2 = ILLEGAL_MODE;
107 REPORTER_ASSERT(reporter, cf2->asColorMode(&c2, &m2));
108 REPORTER_ASSERT(reporter, c2 == expectedColor);
109 REPORTER_ASSERT(reporter, m2 == expectedMode);
110 }
111 }
reeddc812222015-03-05 07:21:02 -0800112
113 test_composecolorfilter_limit(reporter);
reed@google.com43c50c82011-04-14 15:50:52 +0000114}
115
commit-bot@chromium.org6c1ee2d2013-10-07 18:00:17 +0000116///////////////////////////////////////////////////////////////////////////////
117
tfarina@chromium.orge4fafb12013-12-12 21:11:12 +0000118DEF_TEST(LumaColorFilter, reporter) {
commit-bot@chromium.org6c1ee2d2013-10-07 18:00:17 +0000119 SkPMColor in, out;
120 SkAutoTUnref<SkColorFilter> lf(SkLumaColorFilter::Create());
121
commit-bot@chromium.orgd494b092013-10-10 20:13:51 +0000122 // Applying luma to white produces black with the same transparency.
commit-bot@chromium.org6c1ee2d2013-10-07 18:00:17 +0000123 for (unsigned i = 0; i < 256; ++i) {
124 in = SkPackARGB32(i, i, i, i);
125 lf->filterSpan(&in, 1, &out);
commit-bot@chromium.orgd494b092013-10-10 20:13:51 +0000126 REPORTER_ASSERT(reporter, SkGetPackedA32(out) == i);
127 REPORTER_ASSERT(reporter, SkGetPackedR32(out) == 0);
128 REPORTER_ASSERT(reporter, SkGetPackedG32(out) == 0);
129 REPORTER_ASSERT(reporter, SkGetPackedB32(out) == 0);
commit-bot@chromium.org6c1ee2d2013-10-07 18:00:17 +0000130 }
131
132 // Applying luma to black yields transparent black (luminance(black) == 0)
133 for (unsigned i = 0; i < 256; ++i) {
134 in = SkPackARGB32(i, 0, 0, 0);
135 lf->filterSpan(&in, 1, &out);
136 REPORTER_ASSERT(reporter, out == SK_ColorTRANSPARENT);
137 }
138
commit-bot@chromium.orgd494b092013-10-10 20:13:51 +0000139 // For general colors, a luma filter generates black with an attenuated alpha channel.
commit-bot@chromium.org6c1ee2d2013-10-07 18:00:17 +0000140 for (unsigned i = 1; i < 256; ++i) {
141 in = SkPackARGB32(i, i, i / 2, i / 3);
142 lf->filterSpan(&in, 1, &out);
143 REPORTER_ASSERT(reporter, out != in);
144 REPORTER_ASSERT(reporter, SkGetPackedA32(out) <= i);
commit-bot@chromium.orgd494b092013-10-10 20:13:51 +0000145 REPORTER_ASSERT(reporter, SkGetPackedR32(out) == 0);
146 REPORTER_ASSERT(reporter, SkGetPackedG32(out) == 0);
147 REPORTER_ASSERT(reporter, SkGetPackedB32(out) == 0);
commit-bot@chromium.org6c1ee2d2013-10-07 18:00:17 +0000148 }
149}