OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2016 Google Inc. | 2 * Copyright 2016 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #ifndef SkColorSpace_Base_DEFINED | 8 #ifndef SkColorSpace_Base_DEFINED |
9 #define SkColorSpace_Base_DEFINED | 9 #define SkColorSpace_Base_DEFINED |
10 | 10 |
11 #include "SkColorSpace.h" | 11 #include "SkColorSpace.h" |
12 #include "SkData.h" | 12 #include "SkData.h" |
13 #include "SkTemplates.h" | 13 #include "SkTemplates.h" |
14 | 14 |
15 struct SkGammaCurve { | 15 struct SkGammas : SkRefCnt { |
16 bool isNamed() const { | 16 |
17 bool result = (SkColorSpace::kNonStandard_GammaNamed != fNamed); | 17 // There are four possible representations for gamma curves. kNone_Type is
used |
18 SkASSERT(!result || (0.0f == fValue)); | 18 // as a placeholder until the struct is initialized. It is not a valid valu
e. |
19 SkASSERT(!result || (0 == fTableSize)); | 19 enum class Type : uint8_t { |
20 SkASSERT(!result || (0.0f == fG && 0.0f == fE)); | 20 kNone_Type, |
21 return result; | 21 kNamed_Type, |
| 22 kValue_Type, |
| 23 kTable_Type, |
| 24 kParam_Type, |
| 25 }; |
| 26 |
| 27 // Contains information for a gamma table. |
| 28 struct Table { |
| 29 size_t fOffset; |
| 30 int fSize; |
| 31 |
| 32 const float* table(const SkGammas* base) const { |
| 33 return SkTAddOffset<const float>(base, sizeof(SkGammas) + fOffset); |
| 34 } |
| 35 }; |
| 36 |
| 37 // Contains the parameters for a parametric curve. |
| 38 struct Params { |
| 39 // Y = (aX + b)^g + c for X >= d |
| 40 // Y = eX + f otherwise |
| 41 float fG; |
| 42 float fA; |
| 43 float fB; |
| 44 float fC; |
| 45 float fD; |
| 46 float fE; |
| 47 float fF; |
| 48 }; |
| 49 |
| 50 // Contains the actual gamma curve information. Should be interpreted |
| 51 // based on the type of the gamma curve. |
| 52 union Data { |
| 53 Data() |
| 54 : fTable{ 0, 0 } |
| 55 {} |
| 56 |
| 57 inline bool operator==(const Data& that) const { |
| 58 return this->fTable.fOffset == that.fTable.fOffset && |
| 59 this->fTable.fSize == that.fTable.fSize; |
| 60 } |
| 61 |
| 62 SkColorSpace::GammaNamed fNamed; |
| 63 float fValue; |
| 64 Table fTable; |
| 65 size_t fParamOffset; |
| 66 |
| 67 const Params& params(const SkGammas* base) const { |
| 68 return *SkTAddOffset<const Params>(base, sizeof(SkGammas) + fParamOf
fset); |
| 69 } |
| 70 }; |
| 71 |
| 72 bool isNamed(int i) const { |
| 73 SkASSERT(0 <= i && i < 3); |
| 74 return (&fRedType)[i] == Type::kNamed_Type; |
22 } | 75 } |
23 | 76 |
24 bool isValue() const { | 77 bool isValue(int i) const { |
25 bool result = (0.0f != fValue); | 78 SkASSERT(0 <= i && i < 3); |
26 SkASSERT(!result || SkColorSpace::kNonStandard_GammaNamed == fNamed); | 79 return (&fRedType)[i] == Type::kValue_Type; |
27 SkASSERT(!result || (0 == fTableSize)); | |
28 SkASSERT(!result || (0.0f == fG && 0.0f == fE)); | |
29 return result; | |
30 } | 80 } |
31 | 81 |
32 bool isTable() const { | 82 bool isTable(int i) const { |
33 bool result = (0 != fTableSize); | 83 SkASSERT(0 <= i && i < 3); |
34 SkASSERT(!result || SkColorSpace::kNonStandard_GammaNamed == fNamed); | 84 return (&fRedType)[i] == Type::kTable_Type; |
35 SkASSERT(!result || (0.0f == fValue)); | |
36 SkASSERT(!result || (0.0f == fG && 0.0f == fE)); | |
37 SkASSERT(!result || fTable); | |
38 return result; | |
39 } | 85 } |
40 | 86 |
41 bool isParametric() const { | 87 bool isParametric(int i) const { |
42 bool result = (0.0f != fG || 0.0f != fE); | 88 SkASSERT(0 <= i && i < 3); |
43 SkASSERT(!result || SkColorSpace::kNonStandard_GammaNamed == fNamed); | 89 return (&fRedType)[i] == Type::kParam_Type; |
44 SkASSERT(!result || (0.0f == fValue)); | |
45 SkASSERT(!result || (0 == fTableSize)); | |
46 return result; | |
47 } | 90 } |
48 | 91 |
49 // We have four different ways to represent gamma. | 92 const Data& data(int i) const { |
50 // (1) A known, named type: | 93 SkASSERT(0 <= i && i < 3); |
51 SkColorSpace::GammaNamed fNamed; | 94 return (&fRedData)[i]; |
| 95 } |
52 | 96 |
53 // (2) A single value: | 97 const float* table(int i) const { |
54 float fValue; | 98 SkASSERT(isTable(i)); |
| 99 return (&fRedData)[i].fTable.table(this); |
| 100 } |
55 | 101 |
56 // (3) A lookup table: | 102 const Params& params(int i) const { |
57 uint32_t fTableSize; | 103 SkASSERT(isParametric(i)); |
58 std::unique_ptr<float[]> fTable; | 104 return (&fRedData)[i].params(this); |
| 105 } |
59 | 106 |
60 // (4) Parameters for a curve: | 107 SkGammas() |
61 // Y = (aX + b)^g + c for X >= d | 108 : fRedType(Type::kNone_Type) |
62 // Y = eX + f otherwise | 109 , fGreenType(Type::kNone_Type) |
63 float fG; | 110 , fBlueType(Type::kNone_Type) |
64 float fA; | |
65 float fB; | |
66 float fC; | |
67 float fD; | |
68 float fE; | |
69 float fF; | |
70 | |
71 SkGammaCurve() | |
72 : fNamed(SkColorSpace::kNonStandard_GammaNamed) | |
73 , fValue(0.0f) | |
74 , fTableSize(0) | |
75 , fTable(nullptr) | |
76 , fG(0.0f) | |
77 , fA(0.0f) | |
78 , fB(0.0f) | |
79 , fC(0.0f) | |
80 , fD(0.0f) | |
81 , fE(0.0f) | |
82 , fF(0.0f) | |
83 {} | 111 {} |
84 | 112 |
85 bool quickEquals(const SkGammaCurve& that) const { | 113 // These fields should only be modified when initializing the struct. |
86 return (this->fNamed == that.fNamed) && (this->fValue == that.fValue) && | 114 Data fRedData; |
87 (this->fTableSize == that.fTableSize) && (this->fTable == that.f
Table) && | 115 Data fGreenData; |
88 (this->fG == that.fG) && (this->fA == that.fA) && (this->fB == t
hat.fB) && | 116 Data fBlueData; |
89 (this->fC == that.fC) && (this->fD == that.fD) && (this->fE == t
hat.fE) && | 117 Type fRedType; |
90 (this->fF == that.fF); | 118 Type fGreenType; |
91 } | 119 Type fBlueType; |
92 }; | |
93 | 120 |
94 struct SkGammas : public SkRefCnt { | 121 // Objects of this type are sometimes created in a custom fashion using |
95 public: | 122 // sk_malloc_throw and therefore must be sk_freed. We overload new to |
96 static SkColorSpace::GammaNamed Named(SkGammaCurve curves[3]) { | 123 // also call sk_malloc_throw so that memory can be unconditionally released |
97 if (SkColorSpace::kLinear_GammaNamed == curves[0].fNamed && | 124 // using sk_free in an overloaded delete. Overloading regular new means we |
98 SkColorSpace::kLinear_GammaNamed == curves[1].fNamed && | 125 // must also overload placement new. |
99 SkColorSpace::kLinear_GammaNamed == curves[2].fNamed) | 126 void* operator new(size_t size) { return sk_malloc_throw(size); } |
100 { | 127 void* operator new(size_t, void* p) { return p; } |
101 return SkColorSpace::kLinear_GammaNamed; | 128 void operator delete(void* p) { sk_free(p); } |
102 } | |
103 | |
104 if (SkColorSpace::kSRGB_GammaNamed == curves[0].fNamed && | |
105 SkColorSpace::kSRGB_GammaNamed == curves[1].fNamed && | |
106 SkColorSpace::kSRGB_GammaNamed == curves[2].fNamed) | |
107 { | |
108 return SkColorSpace::kSRGB_GammaNamed; | |
109 } | |
110 | |
111 if (SkColorSpace::k2Dot2Curve_GammaNamed == curves[0].fNamed && | |
112 SkColorSpace::k2Dot2Curve_GammaNamed == curves[1].fNamed && | |
113 SkColorSpace::k2Dot2Curve_GammaNamed == curves[2].fNamed) | |
114 { | |
115 return SkColorSpace::k2Dot2Curve_GammaNamed; | |
116 } | |
117 | |
118 return SkColorSpace::kNonStandard_GammaNamed; | |
119 } | |
120 | |
121 const SkGammaCurve& operator[](int i) const { | |
122 SkASSERT(0 <= i && i < 3); | |
123 return (&fRed)[i]; | |
124 } | |
125 | |
126 const SkGammaCurve fRed; | |
127 const SkGammaCurve fGreen; | |
128 const SkGammaCurve fBlue; | |
129 | |
130 SkGammas(SkGammaCurve red, SkGammaCurve green, SkGammaCurve blue) | |
131 : fRed(std::move(red)) | |
132 , fGreen(std::move(green)) | |
133 , fBlue(std::move(blue)) | |
134 {} | |
135 | |
136 SkGammas() {} | |
137 | |
138 friend class SkColorSpace; | |
139 }; | 129 }; |
140 | 130 |
141 struct SkColorLookUpTable : public SkRefCnt { | 131 struct SkColorLookUpTable : public SkRefCnt { |
142 uint8_t fInputChannels; | 132 uint8_t fInputChannels; |
143 uint8_t fOutputChannels; | 133 uint8_t fOutputChannels; |
144 uint8_t fGridPoints[3]; | 134 uint8_t fGridPoints[3]; |
145 std::unique_ptr<float[]> fTable; | 135 std::unique_ptr<float[]> fTable; |
146 | 136 |
147 SkColorLookUpTable() | 137 SkColorLookUpTable() |
148 : fInputChannels(0) | 138 : fInputChannels(0) |
(...skipping 17 matching lines...) Expand all Loading... |
166 * Writes this object as an ICC profile. | 156 * Writes this object as an ICC profile. |
167 */ | 157 */ |
168 sk_sp<SkData> writeToICC() const; | 158 sk_sp<SkData> writeToICC() const; |
169 | 159 |
170 private: | 160 private: |
171 | 161 |
172 static sk_sp<SkColorSpace> NewRGB(GammaNamed gammaNamed, const SkMatrix44& t
oXYZD50); | 162 static sk_sp<SkColorSpace> NewRGB(GammaNamed gammaNamed, const SkMatrix44& t
oXYZD50); |
173 | 163 |
174 SkColorSpace_Base(GammaNamed gammaNamed, const SkMatrix44& toXYZ, Named name
d); | 164 SkColorSpace_Base(GammaNamed gammaNamed, const SkMatrix44& toXYZ, Named name
d); |
175 | 165 |
176 SkColorSpace_Base(sk_sp<SkColorLookUpTable> colorLUT, sk_sp<SkGammas> gammas
, | 166 SkColorSpace_Base(sk_sp<SkColorLookUpTable> colorLUT, GammaNamed gammaNamed, |
177 const SkMatrix44& toXYZ, sk_sp<SkData> profileData); | 167 sk_sp<SkGammas> gammas, const SkMatrix44& toXYZ, sk_sp<SkD
ata> profileData); |
178 | 168 |
179 sk_sp<SkColorLookUpTable> fColorLUT; | 169 sk_sp<SkColorLookUpTable> fColorLUT; |
180 sk_sp<SkGammas> fGammas; | 170 sk_sp<SkGammas> fGammas; |
181 sk_sp<SkData> fProfileData; | 171 sk_sp<SkData> fProfileData; |
182 | 172 |
183 friend class SkColorSpace; | 173 friend class SkColorSpace; |
184 friend class ColorSpaceXformTest; | 174 friend class ColorSpaceXformTest; |
185 typedef SkColorSpace INHERITED; | 175 typedef SkColorSpace INHERITED; |
186 }; | 176 }; |
187 | 177 |
188 static inline SkColorSpace_Base* as_CSB(SkColorSpace* colorSpace) { | 178 static inline SkColorSpace_Base* as_CSB(SkColorSpace* colorSpace) { |
189 return static_cast<SkColorSpace_Base*>(colorSpace); | 179 return static_cast<SkColorSpace_Base*>(colorSpace); |
190 } | 180 } |
191 | 181 |
192 static inline const SkColorSpace_Base* as_CSB(const SkColorSpace* colorSpace) { | 182 static inline const SkColorSpace_Base* as_CSB(const SkColorSpace* colorSpace) { |
193 return static_cast<const SkColorSpace_Base*>(colorSpace); | 183 return static_cast<const SkColorSpace_Base*>(colorSpace); |
194 } | 184 } |
195 | 185 |
196 static inline SkColorSpace_Base* as_CSB(const sk_sp<SkColorSpace>& colorSpace) { | 186 static inline SkColorSpace_Base* as_CSB(const sk_sp<SkColorSpace>& colorSpace) { |
197 return static_cast<SkColorSpace_Base*>(colorSpace.get()); | 187 return static_cast<SkColorSpace_Base*>(colorSpace.get()); |
198 } | 188 } |
199 | 189 |
200 #endif | 190 #endif |
OLD | NEW |