Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
ColorFilterTest.cpp
Go to the documentation of this file.
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
23#include "include/effects/SkColorMatrix.h" // IWYU pragma: keep
29#include "src/base/SkRandom.h"
35#include "tests/Test.h"
36
37#include <cstddef>
38#include <utility>
39
40class SkFlattenable;
41struct GrContextOptions;
42struct SkStageRec;
43
46 wb.writeFlattenable(obj);
47
48 size_t size = wb.bytesWritten();
49 SkAutoSMalloc<1024> storage(size);
50 // make a copy into storage
51 wb.writeToMemory(storage.get());
52
53 SkReadBuffer rb(storage.get(), size);
54 return rb.readColorFilter();
55}
56
57///////////////////////////////////////////////////////////////////////////////
58
59#define ILLEGAL_MODE ((SkBlendMode)-1)
60
61DEF_TEST(ColorFilter, reporter) {
62 SkRandom rand;
63
64 for (int mode = 0; mode < kSkBlendModeCount; mode++) {
65 SkColor color = rand.nextU();
66
67 // ensure we always get a filter, by avoiding the possibility of a
68 // special case that would return nullptr (if color's alpha is 0 or 0xFF)
69 color = SkColorSetA(color, 0x7F);
70
71 auto cf = SkColorFilters::Blend(color, (SkBlendMode)mode);
72
73 // allow for no filter if we're in Dst mode (its a no op)
74 if (SkBlendMode::kDst == (SkBlendMode)mode && nullptr == cf) {
75 continue;
76 }
77
79
80 SkColor c = ~color;
82
83 SkColor expectedColor = color;
84 SkBlendMode expectedMode = (SkBlendMode)mode;
85
86// SkDebugf("--- mc [%d %x] ", mode, color);
87
88 REPORTER_ASSERT(reporter, cf->asAColorMode(&c, (SkBlendMode*)&m));
89 // handle special-case folding by the factory
90 if (SkBlendMode::kClear == (SkBlendMode)mode) {
91 if (c != expectedColor) {
92 expectedColor = 0;
93 }
94 if (m != expectedMode) {
95 expectedMode = SkBlendMode::kSrc;
96 }
97 }
98
99// SkDebugf("--- got [%d %x] expected [%d %x]\n", m, c, expectedMode, expectedColor);
100
101 REPORTER_ASSERT(reporter, c == expectedColor);
102 REPORTER_ASSERT(reporter, m == expectedMode);
103
104 {
105 auto cf2 = reincarnate_colorfilter(cf.get());
107
108 SkColor c2 = ~color;
110 REPORTER_ASSERT(reporter, cf2->asAColorMode(&c2, (SkBlendMode*)&m2));
111 REPORTER_ASSERT(reporter, c2 == expectedColor);
112 REPORTER_ASSERT(reporter, m2 == expectedMode);
113 }
114 }
115}
116
117DEF_TEST(WorkingFormatFilterFlags, r) {
118 {
119 // A matrix with final row 0,0,0,1,0 shouldn't change alpha.
121 0,1,0,0,0,
122 0,0,1,0,0,
123 0,0,0,1,0});
124 REPORTER_ASSERT(r, cf->isAlphaUnchanged());
125
126 // No working format change will itself change alpha.
128 cf = SkColorFilterPriv::WithWorkingFormat(std::move(cf),
131 &unpremul);
132 REPORTER_ASSERT(r, cf->isAlphaUnchanged());
133 }
134
135 {
136 // Here's a matrix that definitely does change alpha.
138 0,1,0,0,0,
139 0,0,1,0,0,
140 0,0,0,0,1});
141 REPORTER_ASSERT(r, !cf->isAlphaUnchanged());
142
144 cf = SkColorFilterPriv::WithWorkingFormat(std::move(cf),
147 &unpremul);
148 REPORTER_ASSERT(r, !cf->isAlphaUnchanged());
149 }
150}
151
154
155 bool appendStages(const SkStageRec&, bool) const override { return false; }
156
157 // Only created here, should never be flattened / unflattened.
158 Factory getFactory() const override { return nullptr; }
159 const char* getTypeName() const override { return "FailureColorFilter"; }
160};
161
162DEF_GANESH_TEST_FOR_ALL_CONTEXTS(ComposeFailureWithInputElision,
163 r,
164 ctxInfo,
167 auto surface = SkSurfaces::RenderTarget(ctxInfo.directContext(), skgpu::Budgeted::kNo, info);
169
170 // Install a non-trivial shader, so the color filter isn't just applied to the paint color:
171 const SkPoint pts[] = {{0, 0}, {100, 100}};
172 const SkColor colors[] = {SK_ColorWHITE, SK_ColorBLACK};
173 paint.setShader(SkGradientShader::MakeLinear(pts, colors, nullptr, 2, SkTileMode::kClamp));
174
175 // Our inner (first) color filter does a "blend" (kSrc) against green, *discarding* the input:
177
178 // The outer (second) color filter then fails to generate an FP. There are ways to do this with
179 // the public API, (eg: image shader with a non-invertible local matrix, wrapped in a runtime
180 // color filter). That's significant boilerplate, so we use a helpful "always fail" filter:
181 auto outer = sk_make_sp<FailureColorFilter>();
182 paint.setColorFilter(outer->makeComposed(inner));
183
184 // At one time, this would trigger a use-after-free / crash, when converting the paint to FPs:
185 surface->getCanvas()->drawPaint(paint);
186}
187
188DEF_TEST(ColorFilter_OpaqueShaderPaintAlpha, r) {
189 // skbug.com/14627: Prior to the fix, CPU backend would produce gray, not white. (It told the
190 // color filter that the shader output was opaque, ignoring the effect of paint alpha).
192 paint.setShader(SkShaders::Color(SK_ColorWHITE));
193 paint.setAlphaf(0.5f);
195
196 SkBitmap bmp;
197 bmp.allocN32Pixels(1, 1);
198 SkCanvas canvas(bmp);
199 canvas.drawColor(SK_ColorWHITE);
200 canvas.drawPaint(paint);
201 REPORTER_ASSERT(r, bmp.getColor(0, 0) == SK_ColorWHITE);
202}
#define ILLEGAL_MODE
static sk_sp< SkColorFilter > reincarnate_colorfilter(SkFlattenable *obj)
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
Definition DM.cpp:213
reporter
SkColor4f color
kUnpremul_SkAlphaType
SkAlphaType
Definition SkAlphaType.h:26
static constexpr int kSkBlendModeCount
Definition SkBlendMode.h:76
SkBlendMode
Definition SkBlendMode.h:38
@ kClear
r = 0
uint32_t SkColor
Definition SkColor.h:37
static constexpr SkColor SkColorSetA(SkColor c, U8CPU a)
Definition SkColor.h:82
constexpr SkColor SK_ColorBLACK
Definition SkColor.h:103
constexpr SkColor SK_ColorGREEN
Definition SkColor.h:131
constexpr SkColor SK_ColorWHITE
Definition SkColor.h:122
#define DEF_TEST(name, reporter)
Definition Test.h:312
#define REPORTER_ASSERT(r, cond,...)
Definition Test.h:286
#define DEF_GANESH_TEST_FOR_ALL_CONTEXTS(name, reporter, context_info, ctsEnforcement)
Definition Test.h:431
void * get() const
void writeFlattenable(const SkFlattenable *flattenable) override
SkColor getColor(int x, int y) const
Definition SkBitmap.h:874
void allocN32Pixels(int width, int height, bool isOpaque=false)
Definition SkBitmap.cpp:232
void drawColor(SkColor color, SkBlendMode mode=SkBlendMode::kSrcOver)
Definition SkCanvas.h:1182
void drawPaint(const SkPaint &paint)
static sk_sp< SkColorFilter > WithWorkingFormat(sk_sp< SkColorFilter > child, const skcms_TransferFunction *tf, const skcms_Matrix3x3 *gamut, const SkAlphaType *at)
static sk_sp< SkColorFilter > Blend(const SkColor4f &c, sk_sp< SkColorSpace >, SkBlendMode mode)
static sk_sp< SkColorFilter > Matrix(const SkColorMatrix &)
static sk_sp< SkColorFilter > SRGBToLinearGamma()
sk_sp< SkFlattenable >(* Factory)(SkReadBuffer &)
static sk_sp< SkShader > MakeLinear(const SkPoint pts[2], const SkColor colors[], const SkScalar pos[], int count, SkTileMode mode, uint32_t flags=0, const SkMatrix *localMatrix=nullptr)
uint32_t nextU()
Definition SkRandom.h:42
sk_sp< SkColorFilter > readColorFilter()
const Paint & paint
VkSurfaceKHR surface
Definition main.cc:49
static constexpr skcms_Matrix3x3 kDisplayP3
static constexpr skcms_TransferFunction kLinear
SK_API sk_sp< SkSurface > RenderTarget(GrRecordingContext *context, skgpu::Budgeted budgeted, const SkImageInfo &imageInfo, int sampleCount, GrSurfaceOrigin surfaceOrigin, const SkSurfaceProps *surfaceProps, bool shouldCreateWithMips=false, bool isProtected=false)
Factory getFactory() const override
const char * getTypeName() const override
SkColorFilterBase::Type type() const override
bool appendStages(const SkStageRec &, bool) const override
static SkImageInfo MakeN32Premul(int width, int height)