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 #include "SkColorSpace.h" | 8 #include "SkColorSpace.h" |
9 #include "SkColorSpace_Base.h" | 9 #include "SkColorSpace_Base.h" |
10 #include "SkColorSpacePriv.h" | 10 #include "SkColorSpacePriv.h" |
11 #include "SkOnce.h" | 11 #include "SkOnce.h" |
12 | 12 |
13 SkColorSpace::SkColorSpace(GammaNamed gammaNamed, const SkMatrix44& toXYZD50, Na
med named) | 13 SkColorSpace::SkColorSpace(GammaNamed gammaNamed, const SkMatrix44& toXYZD50) |
14 : fGammaNamed(gammaNamed) | 14 : fGammaNamed(gammaNamed) |
15 , fToXYZD50(toXYZD50) | 15 , fToXYZD50(toXYZD50) |
16 , fNamed(named) | |
17 {} | 16 {} |
18 | 17 |
19 SkColorSpace_Base::SkColorSpace_Base(GammaNamed gammaNamed, const SkMatrix44& to
XYZD50, Named named) | 18 SkColorSpace_Base::SkColorSpace_Base(GammaNamed gammaNamed, const SkMatrix44& to
XYZD50) |
20 : INHERITED(gammaNamed, toXYZD50, named) | 19 : INHERITED(gammaNamed, toXYZD50) |
21 , fGammas(nullptr) | 20 , fGammas(nullptr) |
22 , fProfileData(nullptr) | 21 , fProfileData(nullptr) |
23 {} | 22 {} |
24 | 23 |
25 SkColorSpace_Base::SkColorSpace_Base(sk_sp<SkColorLookUpTable> colorLUT, GammaNa
med gammaNamed, | 24 SkColorSpace_Base::SkColorSpace_Base(sk_sp<SkColorLookUpTable> colorLUT, GammaNa
med gammaNamed, |
26 sk_sp<SkGammas> gammas, const SkMatrix44& t
oXYZD50, | 25 sk_sp<SkGammas> gammas, const SkMatrix44& t
oXYZD50, |
27 sk_sp<SkData> profileData) | 26 sk_sp<SkData> profileData) |
28 : INHERITED(gammaNamed, toXYZD50, kUnknown_Named) | 27 : INHERITED(gammaNamed, toXYZD50) |
29 , fColorLUT(std::move(colorLUT)) | 28 , fColorLUT(std::move(colorLUT)) |
30 , fGammas(std::move(gammas)) | 29 , fGammas(std::move(gammas)) |
31 , fProfileData(std::move(profileData)) | 30 , fProfileData(std::move(profileData)) |
32 {} | 31 {} |
33 | 32 |
34 static constexpr float gSRGB_toXYZD50[] { | 33 static constexpr float gSRGB_toXYZD50[] { |
35 0.4358f, 0.2224f, 0.0139f, // * R | 34 0.4358f, 0.2224f, 0.0139f, // * R |
36 0.3853f, 0.7170f, 0.0971f, // * G | 35 0.3853f, 0.7170f, 0.0971f, // * G |
37 0.1430f, 0.0606f, 0.7139f, // * B | 36 0.1430f, 0.0606f, 0.7139f, // * B |
38 }; | 37 }; |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
111 return SkColorSpace::NewNamed(kAdobeRGB_Named); | 110 return SkColorSpace::NewNamed(kAdobeRGB_Named); |
112 } | 111 } |
113 break; | 112 break; |
114 case kNonStandard_GammaNamed: | 113 case kNonStandard_GammaNamed: |
115 // This is not allowed. | 114 // This is not allowed. |
116 return nullptr; | 115 return nullptr; |
117 default: | 116 default: |
118 break; | 117 break; |
119 } | 118 } |
120 | 119 |
121 return sk_sp<SkColorSpace>(new SkColorSpace_Base(gammaNamed, toXYZD50, kUnkn
own_Named)); | 120 return sk_sp<SkColorSpace>(new SkColorSpace_Base(gammaNamed, toXYZD50)); |
122 } | 121 } |
123 | 122 |
124 sk_sp<SkColorSpace> SkColorSpace::NewRGB(GammaNamed gammaNamed, const SkMatrix44
& toXYZD50) { | 123 sk_sp<SkColorSpace> SkColorSpace::NewRGB(GammaNamed gammaNamed, const SkMatrix44
& toXYZD50) { |
125 return SkColorSpace_Base::NewRGB(gammaNamed, toXYZD50); | 124 return SkColorSpace_Base::NewRGB(gammaNamed, toXYZD50); |
126 } | 125 } |
127 | 126 |
| 127 static SkColorSpace* gAdobeRGB; |
| 128 static SkColorSpace* gSRGB; |
| 129 |
128 sk_sp<SkColorSpace> SkColorSpace::NewNamed(Named named) { | 130 sk_sp<SkColorSpace> SkColorSpace::NewNamed(Named named) { |
129 static SkOnce sRGBOnce; | 131 static SkOnce sRGBOnce; |
130 static sk_sp<SkColorSpace> sRGB; | |
131 static SkOnce adobeRGBOnce; | 132 static SkOnce adobeRGBOnce; |
132 static sk_sp<SkColorSpace> adobeRGB; | |
133 | 133 |
134 switch (named) { | 134 switch (named) { |
135 case kSRGB_Named: { | 135 case kSRGB_Named: { |
136 sRGBOnce([] { | 136 sRGBOnce([] { |
137 SkMatrix44 srgbToxyzD50(SkMatrix44::kUninitialized_Constructor); | 137 SkMatrix44 srgbToxyzD50(SkMatrix44::kUninitialized_Constructor); |
138 srgbToxyzD50.set3x3RowMajorf(gSRGB_toXYZD50); | 138 srgbToxyzD50.set3x3RowMajorf(gSRGB_toXYZD50); |
139 | 139 |
140 // Force the mutable type mask to be computed. This avoids race
s. | 140 // Force the mutable type mask to be computed. This avoids race
s. |
141 (void)srgbToxyzD50.getType(); | 141 (void)srgbToxyzD50.getType(); |
142 sRGB.reset(new SkColorSpace_Base(kSRGB_GammaNamed, srgbToxyzD50,
kSRGB_Named)); | 142 gSRGB = new SkColorSpace_Base(kSRGB_GammaNamed, srgbToxyzD50); |
143 }); | 143 }); |
144 return sRGB; | 144 return sk_ref_sp<SkColorSpace>(gSRGB); |
145 } | 145 } |
146 case kAdobeRGB_Named: { | 146 case kAdobeRGB_Named: { |
147 adobeRGBOnce([] { | 147 adobeRGBOnce([] { |
148 SkMatrix44 adobergbToxyzD50(SkMatrix44::kUninitialized_Construct
or); | 148 SkMatrix44 adobergbToxyzD50(SkMatrix44::kUninitialized_Construct
or); |
149 adobergbToxyzD50.set3x3RowMajorf(gAdobeRGB_toXYZD50); | 149 adobergbToxyzD50.set3x3RowMajorf(gAdobeRGB_toXYZD50); |
150 | 150 |
151 // Force the mutable type mask to be computed. This avoids race
s. | 151 // Force the mutable type mask to be computed. This avoids race
s. |
152 (void)adobergbToxyzD50.getType(); | 152 (void)adobergbToxyzD50.getType(); |
153 adobeRGB.reset(new SkColorSpace_Base(k2Dot2Curve_GammaNamed, ado
bergbToxyzD50, | 153 gAdobeRGB = new SkColorSpace_Base(k2Dot2Curve_GammaNamed, adober
gbToxyzD50); |
154 kAdobeRGB_Named)); | |
155 }); | 154 }); |
156 return adobeRGB; | 155 return sk_ref_sp<SkColorSpace>(gAdobeRGB); |
157 } | 156 } |
158 default: | 157 default: |
159 break; | 158 break; |
160 } | 159 } |
161 return nullptr; | 160 return nullptr; |
162 } | 161 } |
163 | 162 |
164 sk_sp<SkColorSpace> SkColorSpace::makeLinearGamma() { | 163 sk_sp<SkColorSpace> SkColorSpace::makeLinearGamma() { |
165 return SkColorSpace_Base::NewRGB(kLinear_GammaNamed, fToXYZD50); | 164 return SkColorSpace_Base::NewRGB(kLinear_GammaNamed, fToXYZD50); |
166 } | 165 } |
(...skipping 20 matching lines...) Expand all Loading... |
187 static constexpr uint8_t kICC_Flag = 1 << 1; | 186 static constexpr uint8_t kICC_Flag = 1 << 1; |
188 | 187 |
189 /** | 188 /** |
190 * If kFloatGamma_Flag is set, we will write 15 floats after the header. | 189 * If kFloatGamma_Flag is set, we will write 15 floats after the header. |
191 * The first three are the gamma values, and the next twelve are the | 190 * The first three are the gamma values, and the next twelve are the |
192 * matrix. | 191 * matrix. |
193 * Should not be set at the same time as the kICC_Flag or kMatrix_Flag. | 192 * Should not be set at the same time as the kICC_Flag or kMatrix_Flag. |
194 */ | 193 */ |
195 static constexpr uint8_t kFloatGamma_Flag = 1 << 2; | 194 static constexpr uint8_t kFloatGamma_Flag = 1 << 2; |
196 | 195 |
197 static ColorSpaceHeader Pack(Version version, SkColorSpace::Named named, | 196 static ColorSpaceHeader Pack(Version version, uint8_t named, uint8_t gammaNa
med, uint8_t flags) |
198 SkColorSpace::GammaNamed gammaNamed, uint8_t fl
ags) { | 197 { |
199 ColorSpaceHeader header; | 198 ColorSpaceHeader header; |
200 | 199 |
201 SkASSERT(k0_Version == version); | 200 SkASSERT(k0_Version == version); |
202 header.fVersion = (uint8_t) version; | 201 header.fVersion = (uint8_t) version; |
203 | 202 |
204 SkASSERT(named <= SkColorSpace::kAdobeRGB_Named); | 203 SkASSERT(named <= SkColorSpace::kAdobeRGB_Named); |
205 header.fNamed = (uint8_t) named; | 204 header.fNamed = (uint8_t) named; |
206 | 205 |
207 SkASSERT(gammaNamed <= SkColorSpace::kNonStandard_GammaNamed); | 206 SkASSERT(gammaNamed <= SkColorSpace::kNonStandard_GammaNamed); |
208 header.fGammaNamed = (uint8_t) gammaNamed; | 207 header.fGammaNamed = (uint8_t) gammaNamed; |
209 | 208 |
210 SkASSERT(flags <= kFloatGamma_Flag); | 209 SkASSERT(flags <= kFloatGamma_Flag); |
211 header.fFlags = flags; | 210 header.fFlags = flags; |
212 return header; | 211 return header; |
213 } | 212 } |
214 | 213 |
215 uint8_t fVersion; // Always zero | 214 uint8_t fVersion; // Always zero |
216 uint8_t fNamed; // Must be a SkColorSpace::Named | 215 uint8_t fNamed; // Must be a SkColorSpace::Named |
217 uint8_t fGammaNamed; // Must be a SkColorSpace::GammaNamed | 216 uint8_t fGammaNamed; // Must be a SkColorSpace::GammaNamed |
218 uint8_t fFlags; // Some combination of the flags listed above | 217 uint8_t fFlags; // Some combination of the flags listed above |
219 }; | 218 }; |
220 | 219 |
221 size_t SkColorSpace::writeToMemory(void* memory) const { | 220 size_t SkColorSpace::writeToMemory(void* memory) const { |
222 // Start by trying the serialization fast path. If we haven't saved ICC pro
file data, | 221 // Start by trying the serialization fast path. If we haven't saved ICC pro
file data, |
223 // we must have a profile that we can serialize easily. | 222 // we must have a profile that we can serialize easily. |
224 if (!as_CSB(this)->fProfileData) { | 223 if (!as_CSB(this)->fProfileData) { |
225 // If we have a named profile, only write the enum. | 224 // If we have a named profile, only write the enum. |
226 switch (fNamed) { | 225 if (this == gSRGB) { |
227 case kSRGB_Named: | 226 if (memory) { |
228 case kAdobeRGB_Named: { | 227 *((ColorSpaceHeader*) memory) = |
229 if (memory) { | 228 ColorSpaceHeader::Pack(k0_Version, kSRGB_Named, fGammaNa
med, 0); |
230 *((ColorSpaceHeader*) memory) = | |
231 ColorSpaceHeader::Pack(k0_Version, fNamed, fGammaNam
ed, 0); | |
232 } | |
233 return sizeof(ColorSpaceHeader); | |
234 } | 229 } |
235 default: | 230 return sizeof(ColorSpaceHeader); |
236 break; | 231 } else if (this == gAdobeRGB) { |
| 232 if (memory) { |
| 233 *((ColorSpaceHeader*) memory) = |
| 234 ColorSpaceHeader::Pack(k0_Version, kAdobeRGB_Named, fGam
maNamed, 0); |
| 235 } |
237 } | 236 } |
238 | 237 |
239 // If we have a named gamma, write the enum and the matrix. | 238 // If we have a named gamma, write the enum and the matrix. |
240 switch (fGammaNamed) { | 239 switch (fGammaNamed) { |
241 case kSRGB_GammaNamed: | 240 case kSRGB_GammaNamed: |
242 case k2Dot2Curve_GammaNamed: | 241 case k2Dot2Curve_GammaNamed: |
243 case kLinear_GammaNamed: { | 242 case kLinear_GammaNamed: { |
244 if (memory) { | 243 if (memory) { |
245 *((ColorSpaceHeader*) memory) = | 244 *((ColorSpaceHeader*) memory) = |
246 ColorSpaceHeader::Pack(k0_Version, fNamed, fGammaNam
ed, | 245 ColorSpaceHeader::Pack(k0_Version, 0, fGammaNamed, |
247 ColorSpaceHeader::kMatrix_Fla
g); | 246 ColorSpaceHeader::kMatrix_Fla
g); |
248 memory = SkTAddOffset<void>(memory, sizeof(ColorSpaceHeader)
); | 247 memory = SkTAddOffset<void>(memory, sizeof(ColorSpaceHeader)
); |
249 fToXYZD50.as4x3ColMajorf((float*) memory); | 248 fToXYZD50.as4x3ColMajorf((float*) memory); |
250 } | 249 } |
251 return sizeof(ColorSpaceHeader) + 12 * sizeof(float); | 250 return sizeof(ColorSpaceHeader) + 12 * sizeof(float); |
252 } | 251 } |
253 default: | 252 default: |
254 // Otherwise, write the gamma values and the matrix. | 253 // Otherwise, write the gamma values and the matrix. |
255 if (memory) { | 254 if (memory) { |
256 *((ColorSpaceHeader*) memory) = | 255 *((ColorSpaceHeader*) memory) = |
257 ColorSpaceHeader::Pack(k0_Version, fNamed, fGammaNam
ed, | 256 ColorSpaceHeader::Pack(k0_Version, 0, fGammaNamed, |
258 ColorSpaceHeader::kFloatGamma
_Flag); | 257 ColorSpaceHeader::kFloatGamma
_Flag); |
259 memory = SkTAddOffset<void>(memory, sizeof(ColorSpaceHeader)
); | 258 memory = SkTAddOffset<void>(memory, sizeof(ColorSpaceHeader)
); |
260 | 259 |
261 const SkGammas* gammas = as_CSB(this)->gammas(); | 260 const SkGammas* gammas = as_CSB(this)->gammas(); |
262 SkASSERT(gammas); | 261 SkASSERT(gammas); |
263 SkASSERT(SkGammas::Type::kValue_Type == gammas->fRedType && | 262 SkASSERT(SkGammas::Type::kValue_Type == gammas->fRedType && |
264 SkGammas::Type::kValue_Type == gammas->fGreenType &
& | 263 SkGammas::Type::kValue_Type == gammas->fGreenType &
& |
265 SkGammas::Type::kValue_Type == gammas->fBlueType); | 264 SkGammas::Type::kValue_Type == gammas->fBlueType); |
266 *(((float*) memory) + 0) = gammas->fRedData.fValue; | 265 *(((float*) memory) + 0) = gammas->fRedData.fValue; |
267 *(((float*) memory) + 1) = gammas->fGreenData.fValue; | 266 *(((float*) memory) + 1) = gammas->fGreenData.fValue; |
268 *(((float*) memory) + 2) = gammas->fBlueData.fValue; | 267 *(((float*) memory) + 2) = gammas->fBlueData.fValue; |
269 memory = SkTAddOffset<void>(memory, 3 * sizeof(float)); | 268 memory = SkTAddOffset<void>(memory, 3 * sizeof(float)); |
270 | 269 |
271 fToXYZD50.as4x3ColMajorf((float*) memory); | 270 fToXYZD50.as4x3ColMajorf((float*) memory); |
272 } | 271 } |
273 return sizeof(ColorSpaceHeader) + 15 * sizeof(float); | 272 return sizeof(ColorSpaceHeader) + 15 * sizeof(float); |
274 } | 273 } |
275 } | 274 } |
276 | 275 |
277 // Otherwise, serialize the ICC data. | 276 // Otherwise, serialize the ICC data. |
278 size_t profileSize = as_CSB(this)->fProfileData->size(); | 277 size_t profileSize = as_CSB(this)->fProfileData->size(); |
279 if (SkAlign4(profileSize) != (uint32_t) SkAlign4(profileSize)) { | 278 if (SkAlign4(profileSize) != (uint32_t) SkAlign4(profileSize)) { |
280 return 0; | 279 return 0; |
281 } | 280 } |
282 | 281 |
283 if (memory) { | 282 if (memory) { |
284 *((ColorSpaceHeader*) memory) = ColorSpaceHeader::Pack(k0_Version, kUnkn
own_Named, | 283 *((ColorSpaceHeader*) memory) = ColorSpaceHeader::Pack(k0_Version, 0, |
285 kNonStandard_Gamm
aNamed, | 284 kNonStandard_Gamm
aNamed, |
286 ColorSpaceHeader:
:kICC_Flag); | 285 ColorSpaceHeader:
:kICC_Flag); |
287 memory = SkTAddOffset<void>(memory, sizeof(ColorSpaceHeader)); | 286 memory = SkTAddOffset<void>(memory, sizeof(ColorSpaceHeader)); |
288 | 287 |
289 *((uint32_t*) memory) = (uint32_t) SkAlign4(profileSize); | 288 *((uint32_t*) memory) = (uint32_t) SkAlign4(profileSize); |
290 memory = SkTAddOffset<void>(memory, sizeof(uint32_t)); | 289 memory = SkTAddOffset<void>(memory, sizeof(uint32_t)); |
291 | 290 |
292 memcpy(memory, as_CSB(this)->fProfileData->data(), profileSize); | 291 memcpy(memory, as_CSB(this)->fProfileData->data(), profileSize); |
293 memset(SkTAddOffset<void>(memory, profileSize), 0, SkAlign4(profileSize)
- profileSize); | 292 memset(SkTAddOffset<void>(memory, profileSize), 0, SkAlign4(profileSize)
- profileSize); |
294 } | 293 } |
(...skipping 12 matching lines...) Expand all Loading... |
307 } | 306 } |
308 | 307 |
309 sk_sp<SkColorSpace> SkColorSpace::Deserialize(const void* data, size_t length) { | 308 sk_sp<SkColorSpace> SkColorSpace::Deserialize(const void* data, size_t length) { |
310 if (length < sizeof(ColorSpaceHeader)) { | 309 if (length < sizeof(ColorSpaceHeader)) { |
311 return nullptr; | 310 return nullptr; |
312 } | 311 } |
313 | 312 |
314 ColorSpaceHeader header = *((const ColorSpaceHeader*) data); | 313 ColorSpaceHeader header = *((const ColorSpaceHeader*) data); |
315 data = SkTAddOffset<const void>(data, sizeof(ColorSpaceHeader)); | 314 data = SkTAddOffset<const void>(data, sizeof(ColorSpaceHeader)); |
316 length -= sizeof(ColorSpaceHeader); | 315 length -= sizeof(ColorSpaceHeader); |
317 switch ((Named) header.fNamed) { | 316 if (0 == header.fFlags) { |
318 case kSRGB_Named: | 317 return NewNamed((Named) header.fNamed); |
319 case kAdobeRGB_Named: | |
320 return NewNamed((Named) header.fNamed); | |
321 default: | |
322 break; | |
323 } | 318 } |
324 | 319 |
325 switch ((GammaNamed) header.fGammaNamed) { | 320 switch ((GammaNamed) header.fGammaNamed) { |
326 case kSRGB_GammaNamed: | 321 case kSRGB_GammaNamed: |
327 case k2Dot2Curve_GammaNamed: | 322 case k2Dot2Curve_GammaNamed: |
328 case kLinear_GammaNamed: { | 323 case kLinear_GammaNamed: { |
329 if (ColorSpaceHeader::kMatrix_Flag != header.fFlags || length < 12 *
sizeof(float)) { | 324 if (ColorSpaceHeader::kMatrix_Flag != header.fFlags || length < 12 *
sizeof(float)) { |
330 return nullptr; | 325 return nullptr; |
331 } | 326 } |
332 | 327 |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
375 | 370 |
376 bool SkColorSpace::Equals(const SkColorSpace* src, const SkColorSpace* dst) { | 371 bool SkColorSpace::Equals(const SkColorSpace* src, const SkColorSpace* dst) { |
377 if (src == dst) { | 372 if (src == dst) { |
378 return true; | 373 return true; |
379 } | 374 } |
380 | 375 |
381 if (!src || !dst) { | 376 if (!src || !dst) { |
382 return false; | 377 return false; |
383 } | 378 } |
384 | 379 |
385 switch (src->fNamed) { | |
386 case kSRGB_Named: | |
387 case kAdobeRGB_Named: | |
388 return src->fNamed == dst->fNamed; | |
389 case kUnknown_Named: | |
390 if (kUnknown_Named != dst->fNamed) { | |
391 return false; | |
392 } | |
393 break; | |
394 } | |
395 | |
396 SkData* srcData = as_CSB(src)->fProfileData.get(); | 380 SkData* srcData = as_CSB(src)->fProfileData.get(); |
397 SkData* dstData = as_CSB(dst)->fProfileData.get(); | 381 SkData* dstData = as_CSB(dst)->fProfileData.get(); |
398 if (srcData || dstData) { | 382 if (srcData || dstData) { |
399 if (srcData && dstData) { | 383 if (srcData && dstData) { |
400 return srcData->size() == dstData->size() && | 384 return srcData->size() == dstData->size() && |
401 0 == memcmp(srcData->data(), dstData->data(), srcData->size()
); | 385 0 == memcmp(srcData->data(), dstData->data(), srcData->size()
); |
402 } | 386 } |
403 | 387 |
404 return false; | 388 return false; |
405 } | 389 } |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
455 gammas->fBlueType == SkGammas::Type::kTable_Type; | 439 gammas->fBlueType == SkGammas::Type::kTable_Type; |
456 } | 440 } |
457 | 441 |
458 bool SkColorSpace::gammasAreParams() const { | 442 bool SkColorSpace::gammasAreParams() const { |
459 const SkGammas* gammas = as_CSB(this)->gammas(); | 443 const SkGammas* gammas = as_CSB(this)->gammas(); |
460 SkASSERT(gammas); | 444 SkASSERT(gammas); |
461 return gammas->fRedType == SkGammas::Type::kParam_Type && | 445 return gammas->fRedType == SkGammas::Type::kParam_Type && |
462 gammas->fGreenType == SkGammas::Type::kParam_Type && | 446 gammas->fGreenType == SkGammas::Type::kParam_Type && |
463 gammas->fBlueType == SkGammas::Type::kParam_Type; | 447 gammas->fBlueType == SkGammas::Type::kParam_Type; |
464 } | 448 } |
OLD | NEW |