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
8 #include "src/effects/colorfilters/SkColorSpaceXformColorFilter.h"
9
10 #include "include/core/SkAlphaType.h"
11 #include "include/core/SkColorFilter.h"
12 #include "include/core/SkData.h"
13 #include "include/core/SkRefCnt.h"
14 #include "src/base/SkNoDestructor.h"
15 #include "src/core/SkColorFilterPriv.h"
16 #include "src/core/SkColorSpaceXformSteps.h"
17 #include "src/core/SkEffectPriv.h"
18 #include "src/core/SkRasterPipeline.h"
19 #include "src/core/SkRasterPipelineOpList.h"
20 #include "src/core/SkReadBuffer.h"
21 #include "src/core/SkWriteBuffer.h"
22 #include "src/effects/colorfilters/SkColorFilterBase.h"
23
24 #include <cstdint>
25 #include <utility>
26
SkColorSpaceXformColorFilter(sk_sp<SkColorSpace> src,sk_sp<SkColorSpace> dst)27 SkColorSpaceXformColorFilter::SkColorSpaceXformColorFilter(sk_sp<SkColorSpace> src,
28 sk_sp<SkColorSpace> dst)
29 : fSrc(std::move(src))
30 , fDst(std::move(dst))
31 , fSteps( // We handle premul/unpremul separately, so here just always upm->upm.
32 fSrc.get(),
33 kUnpremul_SkAlphaType,
34 fDst.get(),
35 kUnpremul_SkAlphaType) {}
36
appendStages(const SkStageRec & rec,bool shaderIsOpaque) const37 bool SkColorSpaceXformColorFilter::appendStages(const SkStageRec& rec, bool shaderIsOpaque) const {
38 if (!shaderIsOpaque) {
39 rec.fPipeline->append(SkRasterPipelineOp::unpremul);
40 }
41
42 fSteps.apply(rec.fPipeline);
43
44 if (!shaderIsOpaque) {
45 rec.fPipeline->append(SkRasterPipelineOp::premul);
46 }
47 return true;
48 }
49
flatten(SkWriteBuffer & buffer) const50 void SkColorSpaceXformColorFilter::flatten(SkWriteBuffer& buffer) const {
51 buffer.writeDataAsByteArray(fSrc->serialize().get());
52 buffer.writeDataAsByteArray(fDst->serialize().get());
53 }
54
LegacyGammaOnlyCreateProc(SkReadBuffer & buffer)55 sk_sp<SkFlattenable> SkColorSpaceXformColorFilter::LegacyGammaOnlyCreateProc(SkReadBuffer& buffer) {
56 uint32_t dir = buffer.read32();
57 if (!buffer.validate(dir <= 1)) {
58 return nullptr;
59 }
60 if (dir == 0) {
61 return SkColorFilters::LinearToSRGBGamma();
62 }
63 return SkColorFilters::SRGBToLinearGamma();
64 }
65
CreateProc(SkReadBuffer & buffer)66 sk_sp<SkFlattenable> SkColorSpaceXformColorFilter::CreateProc(SkReadBuffer& buffer) {
67 sk_sp<SkColorSpace> colorSpaces[2];
68 for (int i = 0; i < 2; ++i) {
69 auto data = buffer.readByteArrayAsData();
70 if (!buffer.validate(data != nullptr)) {
71 return nullptr;
72 }
73 colorSpaces[i] = SkColorSpace::Deserialize(data->data(), data->size());
74 if (!buffer.validate(colorSpaces[i] != nullptr)) {
75 return nullptr;
76 }
77 }
78 return sk_sp<SkFlattenable>(
79 new SkColorSpaceXformColorFilter(std::move(colorSpaces[0]), std::move(colorSpaces[1])));
80 }
81
LinearToSRGBGamma()82 sk_sp<SkColorFilter> SkColorFilters::LinearToSRGBGamma() {
83 static SkNoDestructor<SkColorSpaceXformColorFilter> gSingleton(SkColorSpace::MakeSRGBLinear(),
84 SkColorSpace::MakeSRGB());
85 return sk_ref_sp(gSingleton.get());
86 }
87
SRGBToLinearGamma()88 sk_sp<SkColorFilter> SkColorFilters::SRGBToLinearGamma() {
89 static SkNoDestructor<SkColorSpaceXformColorFilter> gSingleton(SkColorSpace::MakeSRGB(),
90 SkColorSpace::MakeSRGBLinear());
91 return sk_ref_sp(gSingleton.get());
92 }
93
MakeColorSpaceXform(sk_sp<SkColorSpace> src,sk_sp<SkColorSpace> dst)94 sk_sp<SkColorFilter> SkColorFilterPriv::MakeColorSpaceXform(sk_sp<SkColorSpace> src,
95 sk_sp<SkColorSpace> dst) {
96 return sk_make_sp<SkColorSpaceXformColorFilter>(std::move(src), std::move(dst));
97 }
98
SkRegisterSkColorSpaceXformColorFilterFlattenable()99 void SkRegisterSkColorSpaceXformColorFilterFlattenable() {
100 SK_REGISTER_FLATTENABLE(SkColorSpaceXformColorFilter);
101 // Previous name
102 SkFlattenable::Register("ColorSpaceXformColorFilter", SkColorSpaceXformColorFilter::CreateProc);
103 // TODO(ccameron): Remove after grace period for SKPs to stop using old serialization.
104 SkFlattenable::Register("SkSRGBGammaColorFilter",
105 SkColorSpaceXformColorFilter::LegacyGammaOnlyCreateProc);
106 }
107