Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
SkWorkingFormatColorFilter.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2023 Google LLC
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
9
16#include "modules/skcms/skcms.h"
24
25#include <utility>
26
28 const skcms_TransferFunction* tf,
29 const skcms_Matrix3x3* gamut,
30 const SkAlphaType* at) {
31 fChild = std::move(child);
32 if (tf) {
33 fTF = *tf;
34 fUseDstTF = false;
35 }
36 if (gamut) {
37 fGamut = *gamut;
38 fUseDstGamut = false;
39 }
40 if (at) {
41 fAT = *at;
42 fUseDstAT = false;
43 }
44}
45
47 SkAlphaType* at) const {
49 skcms_Matrix3x3 gamut = fGamut;
50
51 if (fUseDstTF) {
52 SkAssertResult(dstCS->isNumericalTransferFn(&tf));
53 }
54 if (fUseDstGamut) {
55 SkAssertResult(dstCS->toXYZD50(&gamut));
56 }
57
58 *at = fUseDstAT ? kPremul_SkAlphaType : fAT;
59 return SkColorSpace::MakeRGB(tf, gamut);
60}
61
62bool SkWorkingFormatColorFilter::appendStages(const SkStageRec& rec, bool shaderIsOpaque) const {
64
65 if (!dstCS) {
66 dstCS = SkColorSpace::MakeSRGB();
67 }
68
69 SkAlphaType workingAT;
70 sk_sp<SkColorSpace> workingCS = this->workingFormat(dstCS, &workingAT);
71
73 working = {rec.fDstColorType, workingAT, workingCS};
74
75 const auto* dstToWorking = rec.fAlloc->make<SkColorSpaceXformSteps>(dst, working);
76 const auto* workingToDst = rec.fAlloc->make<SkColorSpaceXformSteps>(working, dst);
77
78 // The paint color is in the destination color space, so *should* be coverted to working space.
79 // That's not necessary, though:
80 // - Tinting alpha-only image shaders is the only effect that uses paint-color
81 // - Alpha-only image shaders can't be reached from color-filters without SkSL
82 // - SkSL disables paint-color tinting of alpha-only image shaders
83
84 SkStageRec workingRec = {rec.fPipeline,
85 rec.fAlloc,
86 rec.fDstColorType,
87 workingCS.get(),
88 rec.fPaintColor,
89 rec.fSurfaceProps};
90
91 dstToWorking->apply(rec.fPipeline);
92 if (!as_CFB(fChild)->appendStages(workingRec, shaderIsOpaque)) {
93 return false;
94 }
95 workingToDst->apply(rec.fPipeline);
96 return true;
97}
98
100 SkColorSpace* rawDstCS) const {
101 sk_sp<SkColorSpace> dstCS = sk_ref_sp(rawDstCS);
102 if (!dstCS) {
103 dstCS = SkColorSpace::MakeSRGB();
104 }
105
106 SkAlphaType workingAT;
107 sk_sp<SkColorSpace> workingCS = this->workingFormat(dstCS, &workingAT);
108
110 working = {kUnknown_SkColorType, workingAT, workingCS};
111
112 SkPMColor4f color = origColor;
113 SkColorSpaceXformSteps{dst, working}.apply(color.vec());
114 color = as_CFB(fChild)->onFilterColor4f(color, working.colorSpace());
115 SkColorSpaceXformSteps{working, dst}.apply(color.vec());
116 return color;
117}
118
120
122 buffer.writeFlattenable(fChild.get());
123 buffer.writeBool(fUseDstTF);
124 buffer.writeBool(fUseDstGamut);
125 buffer.writeBool(fUseDstAT);
126 if (!fUseDstTF) {
127 buffer.writeScalarArray(&fTF.g, 7);
128 }
129 if (!fUseDstGamut) {
130 buffer.writeScalarArray(&fGamut.vals[0][0], 9);
131 }
132 if (!fUseDstAT) {
133 buffer.writeInt(fAT);
134 }
135}
136
137sk_sp<SkFlattenable> SkWorkingFormatColorFilter::CreateProc(SkReadBuffer& buffer) {
138 sk_sp<SkColorFilter> child = buffer.readColorFilter();
139 bool useDstTF = buffer.readBool(), useDstGamut = buffer.readBool(),
140 useDstAT = buffer.readBool();
141
143 skcms_Matrix3x3 gamut;
144 SkAlphaType at;
145
146 if (!useDstTF) {
147 buffer.readScalarArray(&tf.g, 7);
148 }
149 if (!useDstGamut) {
150 buffer.readScalarArray(&gamut.vals[0][0], 9);
151 }
152 if (!useDstAT) {
153 at = buffer.read32LE(kLastEnum_SkAlphaType);
154 }
155
157 useDstTF ? nullptr : &tf,
158 useDstGamut ? nullptr : &gamut,
159 useDstAT ? nullptr : &at);
160}
161
163 const skcms_TransferFunction* tf,
164 const skcms_Matrix3x3* gamut,
165 const SkAlphaType* at) {
166 return sk_make_sp<SkWorkingFormatColorFilter>(std::move(child), tf, gamut, at);
167}
168
SkColor4f color
SkAlphaType
Definition SkAlphaType.h:26
@ kPremul_SkAlphaType
pixel components are premultiplied by alpha
Definition SkAlphaType.h:29
@ kLastEnum_SkAlphaType
last valid value
Definition SkAlphaType.h:31
#define SkAssertResult(cond)
Definition SkAssert.h:123
static SkColorFilterBase * as_CFB(SkColorFilter *filter)
@ kUnknown_SkColorType
uninitialized
Definition SkColorType.h:20
#define SK_REGISTER_FLATTENABLE(type)
sk_sp< T > sk_ref_sp(T *obj)
Definition SkRefCnt.h:381
void SkRegisterWorkingFormatColorFilterFlattenable()
auto make(Ctor &&ctor) -> decltype(ctor(nullptr))
virtual SkPMColor4f onFilterColor4f(const SkPMColor4f &color, SkColorSpace *dstCS) const
virtual bool appendStages(const SkStageRec &rec, bool shaderIsOpaque) const =0
static sk_sp< SkColorFilter > WithWorkingFormat(sk_sp< SkColorFilter > child, const skcms_TransferFunction *tf, const skcms_Matrix3x3 *gamut, const SkAlphaType *at)
bool isAlphaUnchanged() const
static sk_sp< SkColorSpace > MakeSRGB()
static sk_sp< SkColorSpace > MakeRGB(const skcms_TransferFunction &transferFn, const skcms_Matrix3x3 &toXYZ)
void flatten(SkWriteBuffer &buffer) const override
SkPMColor4f onFilterColor4f(const SkPMColor4f &origColor, SkColorSpace *rawDstCS) const override
sk_sp< SkColorFilter > child() const
SkWorkingFormatColorFilter(sk_sp< SkColorFilter > child, const skcms_TransferFunction *tf, const skcms_Matrix3x3 *gamut, const SkAlphaType *at)
bool appendStages(const SkStageRec &rec, bool shaderIsOpaque) const override
sk_sp< SkColorSpace > workingFormat(const sk_sp< SkColorSpace > &dstCS, SkAlphaType *at) const
T * get() const
Definition SkRefCnt.h:303
static const uint8_t buffer[]
void apply(float rgba[4]) const
const SkSurfaceProps & fSurfaceProps
SkColor4f fPaintColor
SkRasterPipeline * fPipeline
SkColorSpace * fDstCS
SkArenaAlloc * fAlloc
SkColorType fDstColorType
float vals[3][3]