Line data Source code
1 : /*
2 : * Copyright 2016 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 :
8 : #ifndef SkColorSpace_Base_DEFINED
9 : #define SkColorSpace_Base_DEFINED
10 :
11 : #include "SkColorLookUpTable.h"
12 : #include "SkColorSpace.h"
13 : #include "SkData.h"
14 : #include "SkOnce.h"
15 : #include "SkTemplates.h"
16 :
17 : enum SkGammaNamed : uint8_t {
18 : kLinear_SkGammaNamed,
19 : kSRGB_SkGammaNamed,
20 : k2Dot2Curve_SkGammaNamed,
21 : kNonStandard_SkGammaNamed,
22 : };
23 :
24 0 : struct SkGammas : SkRefCnt {
25 :
26 : // There are four possible representations for gamma curves. kNone_Type is used
27 : // as a placeholder until the struct is initialized. It is not a valid value.
28 : enum class Type : uint8_t {
29 : kNone_Type,
30 : kNamed_Type,
31 : kValue_Type,
32 : kTable_Type,
33 : kParam_Type,
34 : };
35 :
36 : // Contains information for a gamma table.
37 : struct Table {
38 : size_t fOffset;
39 : int fSize;
40 :
41 0 : const float* table(const SkGammas* base) const {
42 0 : return SkTAddOffset<const float>(base, sizeof(SkGammas) + fOffset);
43 : }
44 : };
45 :
46 : // Contains the actual gamma curve information. Should be interpreted
47 : // based on the type of the gamma curve.
48 : union Data {
49 0 : Data()
50 0 : : fTable{ 0, 0 }
51 0 : {}
52 :
53 0 : inline bool operator==(const Data& that) const {
54 0 : return this->fTable.fOffset == that.fTable.fOffset &&
55 0 : this->fTable.fSize == that.fTable.fSize;
56 : }
57 :
58 0 : inline bool operator!=(const Data& that) const {
59 0 : return !(*this == that);
60 : }
61 :
62 : SkGammaNamed fNamed;
63 : float fValue;
64 : Table fTable;
65 : size_t fParamOffset;
66 :
67 0 : const SkColorSpaceTransferFn& params(const SkGammas* base) const {
68 0 : return *SkTAddOffset<const SkColorSpaceTransferFn>(
69 0 : base, sizeof(SkGammas) + fParamOffset);
70 : }
71 : };
72 :
73 0 : bool isNamed(int i) const {
74 0 : return Type::kNamed_Type == this->type(i);
75 : }
76 :
77 0 : bool isValue(int i) const {
78 0 : return Type::kValue_Type == this->type(i);
79 : }
80 :
81 0 : bool isTable(int i) const {
82 0 : return Type::kTable_Type == this->type(i);
83 : }
84 :
85 0 : bool isParametric(int i) const {
86 0 : return Type::kParam_Type == this->type(i);
87 : }
88 :
89 0 : const Data& data(int i) const {
90 0 : SkASSERT(i >= 0 && i < fChannels);
91 0 : return fData[i];
92 : }
93 :
94 0 : const float* table(int i) const {
95 0 : SkASSERT(isTable(i));
96 0 : return this->data(i).fTable.table(this);
97 : }
98 :
99 0 : int tableSize(int i) const {
100 0 : SkASSERT(isTable(i));
101 0 : return this->data(i).fTable.fSize;
102 : }
103 :
104 0 : const SkColorSpaceTransferFn& params(int i) const {
105 0 : SkASSERT(isParametric(i));
106 0 : return this->data(i).params(this);
107 : }
108 :
109 0 : Type type(int i) const {
110 0 : SkASSERT(i >= 0 && i < fChannels);
111 0 : return fType[i];
112 : }
113 :
114 0 : uint8_t channels() const { return fChannels; }
115 :
116 0 : SkGammas(uint8_t channels)
117 0 : : fChannels(channels) {
118 0 : SkASSERT(channels <= kMaxColorChannels);
119 0 : for (uint8_t i = 0; i < kMaxColorChannels; ++i) {
120 0 : fType[i] = Type::kNone_Type;
121 : }
122 0 : }
123 :
124 : // These fields should only be modified when initializing the struct.
125 : uint8_t fChannels;
126 : Data fData[kMaxColorChannels];
127 : Type fType[kMaxColorChannels];
128 :
129 : // Objects of this type are sometimes created in a custom fashion using
130 : // sk_malloc_throw and therefore must be sk_freed. We overload new to
131 : // also call sk_malloc_throw so that memory can be unconditionally released
132 : // using sk_free in an overloaded delete. Overloading regular new means we
133 : // must also overload placement new.
134 : void* operator new(size_t size) { return sk_malloc_throw(size); }
135 0 : void* operator new(size_t, void* p) { return p; }
136 0 : void operator delete(void* p) { sk_free(p); }
137 : };
138 :
139 0 : class SkColorSpace_Base : public SkColorSpace {
140 : public:
141 :
142 : /**
143 : * Describes color space gamut as a transformation to XYZ D50.
144 : * Returns nullptr if color gamut cannot be described in terms of XYZ D50.
145 : */
146 : virtual const SkMatrix44* toXYZD50() const = 0;
147 :
148 : /**
149 : * Returns a hash of the gamut transofmration to XYZ D50. Allows for fast equality checking
150 : * of gamuts, at the (very small) risk of collision.
151 : * Returns 0 if color gamut cannot be described in terms of XYZ D50.
152 : */
153 : virtual uint32_t toXYZD50Hash() const = 0;
154 :
155 : /**
156 : * Describes color space gamut as a transformation from XYZ D50
157 : * Returns nullptr if color gamut cannot be described in terms of XYZ D50.
158 : */
159 : virtual const SkMatrix44* fromXYZD50() const = 0;
160 :
161 : virtual bool onGammaCloseToSRGB() const = 0;
162 :
163 : virtual bool onGammaIsLinear() const = 0;
164 :
165 : virtual bool onIsNumericalTransferFn(SkColorSpaceTransferFn* coeffs) const = 0;
166 :
167 0 : virtual bool onIsCMYK() const { return false; }
168 :
169 : /**
170 : * Returns a color space with the same gamut as this one, but with a linear gamma.
171 : * For color spaces whose gamut can not be described in terms of XYZ D50, returns
172 : * linear sRGB.
173 : */
174 : virtual sk_sp<SkColorSpace> makeLinearGamma() = 0;
175 :
176 : /**
177 : * Returns a color space with the same gamut as this one, with with the sRGB transfer
178 : * function. For color spaces whose gamut can not be described in terms of XYZ D50, returns
179 : * sRGB.
180 : */
181 : virtual sk_sp<SkColorSpace> makeSRGBGamma() = 0;
182 :
183 : enum class Type : uint8_t {
184 : kXYZ,
185 : kA2B
186 : };
187 :
188 : virtual Type type() const = 0;
189 :
190 : typedef uint8_t ICCTypeFlag;
191 : static constexpr ICCTypeFlag kRGB_ICCTypeFlag = 1 << 0;
192 : static constexpr ICCTypeFlag kCMYK_ICCTypeFlag = 1 << 1;
193 : static constexpr ICCTypeFlag kGray_ICCTypeFlag = 1 << 2;
194 :
195 : static sk_sp<SkColorSpace> MakeICC(const void* input, size_t len, ICCTypeFlag type);
196 :
197 : static sk_sp<SkColorSpace> MakeRGB(SkGammaNamed gammaNamed, const SkMatrix44& toXYZD50);
198 :
199 : enum Named : uint8_t {
200 : kSRGB_Named,
201 : kAdobeRGB_Named,
202 : kSRGBLinear_Named,
203 : kSRGB_NonLinearBlending_Named,
204 : };
205 :
206 : static sk_sp<SkColorSpace> MakeNamed(Named);
207 :
208 : protected:
209 : SkColorSpace_Base(sk_sp<SkData> profileData);
210 :
211 : private:
212 : sk_sp<SkData> fProfileData;
213 :
214 : friend class SkColorSpace;
215 : friend class SkColorSpace_XYZ;
216 : friend class ColorSpaceXformTest;
217 : friend class ColorSpaceTest;
218 : typedef SkColorSpace INHERITED;
219 : };
220 :
221 0 : static inline SkColorSpace_Base* as_CSB(SkColorSpace* colorSpace) {
222 0 : return static_cast<SkColorSpace_Base*>(colorSpace);
223 : }
224 :
225 0 : static inline const SkColorSpace_Base* as_CSB(const SkColorSpace* colorSpace) {
226 0 : return static_cast<const SkColorSpace_Base*>(colorSpace);
227 : }
228 :
229 0 : static inline SkColorSpace_Base* as_CSB(const sk_sp<SkColorSpace>& colorSpace) {
230 0 : return static_cast<SkColorSpace_Base*>(colorSpace.get());
231 : }
232 :
233 : #endif
|