xref: /aosp_15_r20/external/skia/src/effects/colorfilters/SkColorSpaceXformColorFilter.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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