blob: 3a2518db9c176e7e4ea0e68c39a005f625370f1b [file] [log] [blame]
msarettbb9f7742016-05-17 09:31:20 -07001/*
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
msarett8cc20912016-05-23 09:29:29 -07008#ifndef SkColorSpace_Base_DEFINED
9#define SkColorSpace_Base_DEFINED
10
11#include "SkColorSpace.h"
msarettab926f02016-05-25 08:53:40 -070012#include "SkData.h"
msarette077e062016-05-24 10:16:53 -070013#include "SkTemplates.h"
msarettbb9f7742016-05-17 09:31:20 -070014
msarett1b93bd12016-07-21 07:11:26 -070015struct SkGammas : SkRefCnt {
msarett2aec3ff2016-07-20 12:58:52 -070016
msarett1b93bd12016-07-21 07:11:26 -070017 // There are four possible representations for gamma curves. kNone_Type is used
18 // as a placeholder until the struct is initialized. It is not a valid value.
19 enum class Type : uint8_t {
20 kNone_Type,
21 kNamed_Type,
22 kValue_Type,
23 kTable_Type,
24 kParam_Type,
25 };
msarett2aec3ff2016-07-20 12:58:52 -070026
msarett1b93bd12016-07-21 07:11:26 -070027 // Contains information for a gamma table.
28 struct Table {
29 size_t fOffset;
30 int fSize;
msarett959ccc12016-07-20 15:10:02 -070031
msarett1b93bd12016-07-21 07:11:26 -070032 const float* table(const SkGammas* base) const {
33 return SkTAddOffset<const float>(base, sizeof(SkGammas) + fOffset);
34 }
35 };
msarett959ccc12016-07-20 15:10:02 -070036
msarett1b93bd12016-07-21 07:11:26 -070037 // 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 };
msarett959ccc12016-07-20 15:10:02 -070049
msarett1b93bd12016-07-21 07:11:26 -070050 // 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 {}
msarett959ccc12016-07-20 15:10:02 -070056
msarett1b93bd12016-07-21 07:11:26 -070057 inline bool operator==(const Data& that) const {
58 return this->fTable.fOffset == that.fTable.fOffset &&
59 this->fTable.fSize == that.fTable.fSize;
msarett456bf302016-07-20 16:14:16 -070060 }
61
msarett1b93bd12016-07-21 07:11:26 -070062 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) + fParamOffset);
msarett456bf302016-07-20 16:14:16 -070069 }
msarett1b93bd12016-07-21 07:11:26 -070070 };
msarett456bf302016-07-20 16:14:16 -070071
msarett1b93bd12016-07-21 07:11:26 -070072 bool isNamed(int i) const {
msaretta714bc32016-07-29 08:58:33 -070073 return Type::kNamed_Type == this->type(i);
msarett456bf302016-07-20 16:14:16 -070074 }
75
msarett1b93bd12016-07-21 07:11:26 -070076 bool isValue(int i) const {
msaretta714bc32016-07-29 08:58:33 -070077 return Type::kValue_Type == this->type(i);
msarett1b93bd12016-07-21 07:11:26 -070078 }
msarett456bf302016-07-20 16:14:16 -070079
msarett1b93bd12016-07-21 07:11:26 -070080 bool isTable(int i) const {
msaretta714bc32016-07-29 08:58:33 -070081 return Type::kTable_Type == this->type(i);
msarett1b93bd12016-07-21 07:11:26 -070082 }
83
84 bool isParametric(int i) const {
msaretta714bc32016-07-29 08:58:33 -070085 return Type::kParam_Type == this->type(i);
msarett1b93bd12016-07-21 07:11:26 -070086 }
87
88 const Data& data(int i) const {
msaretta714bc32016-07-29 08:58:33 -070089 switch (i) {
90 case 0:
91 return fRedData;
92 case 1:
93 return fGreenData;
94 case 2:
95 return fBlueData;
96 default:
97 SkASSERT(false);
98 return fRedData;
99 }
msarett1b93bd12016-07-21 07:11:26 -0700100 }
101
102 const float* table(int i) const {
103 SkASSERT(isTable(i));
msaretta714bc32016-07-29 08:58:33 -0700104 return this->data(i).fTable.table(this);
msarett1b93bd12016-07-21 07:11:26 -0700105 }
106
107 const Params& params(int i) const {
108 SkASSERT(isParametric(i));
msaretta714bc32016-07-29 08:58:33 -0700109 return this->data(i).params(this);
110 }
111
112 Type type(int i) const {
113 switch (i) {
114 case 0:
115 return fRedType;
116 case 1:
117 return fGreenType;
118 case 2:
119 return fBlueType;
120 default:
121 SkASSERT(false);
122 return fRedType;
123 }
msarett1b93bd12016-07-21 07:11:26 -0700124 }
125
126 SkGammas()
127 : fRedType(Type::kNone_Type)
128 , fGreenType(Type::kNone_Type)
129 , fBlueType(Type::kNone_Type)
msarett456bf302016-07-20 16:14:16 -0700130 {}
131
msarett1b93bd12016-07-21 07:11:26 -0700132 // These fields should only be modified when initializing the struct.
133 Data fRedData;
134 Data fGreenData;
135 Data fBlueData;
136 Type fRedType;
137 Type fGreenType;
138 Type fBlueType;
msarett456bf302016-07-20 16:14:16 -0700139
msarett1b93bd12016-07-21 07:11:26 -0700140 // Objects of this type are sometimes created in a custom fashion using
141 // sk_malloc_throw and therefore must be sk_freed. We overload new to
142 // also call sk_malloc_throw so that memory can be unconditionally released
143 // using sk_free in an overloaded delete. Overloading regular new means we
144 // must also overload placement new.
145 void* operator new(size_t size) { return sk_malloc_throw(size); }
146 void* operator new(size_t, void* p) { return p; }
147 void operator delete(void* p) { sk_free(p); }
msarettbb9f7742016-05-17 09:31:20 -0700148};
149
msarett0f83e012016-06-23 15:12:52 -0700150struct SkColorLookUpTable : public SkRefCnt {
msarett959d45b2016-07-21 13:19:03 -0700151 static constexpr uint8_t kOutputChannels = 3;
msarettbb9f7742016-05-17 09:31:20 -0700152
msarett959d45b2016-07-21 13:19:03 -0700153 uint8_t fInputChannels;
154 uint8_t fGridPoints[3];
155
156 const float* table() const {
157 return SkTAddOffset<const float>(this, sizeof(SkColorLookUpTable));
msarettbb9f7742016-05-17 09:31:20 -0700158 }
msarett959d45b2016-07-21 13:19:03 -0700159
160 SkColorLookUpTable(uint8_t inputChannels, uint8_t gridPoints[3])
161 : fInputChannels(inputChannels)
162 {
163 SkASSERT(3 == inputChannels);
164 memcpy(fGridPoints, gridPoints, 3 * sizeof(uint8_t));
165 }
166
167 // Objects of this type are created in a custom fashion using sk_malloc_throw
168 // and therefore must be sk_freed.
169 void* operator new(size_t size) = delete;
170 void* operator new(size_t, void* p) { return p; }
171 void operator delete(void* p) { sk_free(p); }
msarettbb9f7742016-05-17 09:31:20 -0700172};
173
msarett8cc20912016-05-23 09:29:29 -0700174class SkColorSpace_Base : public SkColorSpace {
175public:
176
msarettc4ce6b52016-06-16 07:37:41 -0700177 static sk_sp<SkColorSpace> NewRGB(float gammas[3], const SkMatrix44& toXYZD50);
178
msarettb3906762016-06-22 14:07:48 -0700179 const SkGammas* gammas() const { return fGammas.get(); }
msarett8cc20912016-05-23 09:29:29 -0700180
msarettb3906762016-06-22 14:07:48 -0700181 const SkColorLookUpTable* colorLUT() const { return fColorLUT.get(); }
msarettdc27a642016-06-06 12:02:31 -0700182
msarettc213f0d2016-08-01 14:23:32 -0700183private:
184
msarettab926f02016-05-25 08:53:40 -0700185 /**
msarettc213f0d2016-08-01 14:23:32 -0700186 * FIXME (msarett):
187 * Hiding this function until we can determine if we need it. Known issues include:
188 * Only writes 3x3 matrices
189 * Only writes float gammas
190 * Rejected by some parsers because the "profile description" is empty
msarettab926f02016-05-25 08:53:40 -0700191 */
192 sk_sp<SkData> writeToICC() const;
193
msarett111a42d2016-06-22 08:18:54 -0700194 static sk_sp<SkColorSpace> NewRGB(GammaNamed gammaNamed, const SkMatrix44& toXYZD50);
msarettab926f02016-05-25 08:53:40 -0700195
msarett111a42d2016-06-22 08:18:54 -0700196 SkColorSpace_Base(GammaNamed gammaNamed, const SkMatrix44& toXYZ, Named named);
msarett8cc20912016-05-23 09:29:29 -0700197
msarett1b93bd12016-07-21 07:11:26 -0700198 SkColorSpace_Base(sk_sp<SkColorLookUpTable> colorLUT, GammaNamed gammaNamed,
199 sk_sp<SkGammas> gammas, const SkMatrix44& toXYZ, sk_sp<SkData> profileData);
msarett8cc20912016-05-23 09:29:29 -0700200
msarett0f83e012016-06-23 15:12:52 -0700201 sk_sp<SkColorLookUpTable> fColorLUT;
202 sk_sp<SkGammas> fGammas;
203 sk_sp<SkData> fProfileData;
msarett8cc20912016-05-23 09:29:29 -0700204
205 friend class SkColorSpace;
msarettb3906762016-06-22 14:07:48 -0700206 friend class ColorSpaceXformTest;
msarettc213f0d2016-08-01 14:23:32 -0700207 friend class ColorSpaceTest;
msarett8cc20912016-05-23 09:29:29 -0700208 typedef SkColorSpace INHERITED;
209};
210
211static inline SkColorSpace_Base* as_CSB(SkColorSpace* colorSpace) {
212 return static_cast<SkColorSpace_Base*>(colorSpace);
213}
214
msarettab926f02016-05-25 08:53:40 -0700215static inline const SkColorSpace_Base* as_CSB(const SkColorSpace* colorSpace) {
216 return static_cast<const SkColorSpace_Base*>(colorSpace);
217}
218
msarett888dc162016-05-23 10:21:17 -0700219static inline SkColorSpace_Base* as_CSB(const sk_sp<SkColorSpace>& colorSpace) {
220 return static_cast<SkColorSpace_Base*>(colorSpace.get());
221}
222
msarettbb9f7742016-05-17 09:31:20 -0700223#endif