blob: d18b631072d928932f5dc381c19fdc70aadd76c0 [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
msarett959ccc12016-07-20 15:10:02 -070015struct SkGammas : SkRefCnt {
msarettdc27a642016-06-06 12:02:31 -070016
msarett959ccc12016-07-20 15:10:02 -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 };
msarettbb9f7742016-05-17 09:31:20 -070026
msarett959ccc12016-07-20 15:10:02 -070027 // Contains information for a gamma table.
28 struct Table {
29 size_t fOffset;
30 int fSize;
msarett2ea944c2016-07-20 11:44:42 -070031
msarett959ccc12016-07-20 15:10:02 -070032 const float* table(const SkGammas* base) const {
33 return SkTAddOffset<const float>(base, sizeof(SkGammas) + fOffset);
34 }
35 };
msarett2ea944c2016-07-20 11:44:42 -070036
msarett959ccc12016-07-20 15:10:02 -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 };
msarett2ea944c2016-07-20 11:44:42 -070049
msarett959ccc12016-07-20 15:10:02 -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 {}
msarett2ea944c2016-07-20 11:44:42 -070056
msarett959ccc12016-07-20 15:10:02 -070057 inline bool operator==(const Data& that) const {
58 return this->fTable.fOffset == that.fTable.fOffset &&
59 this->fTable.fSize == that.fTable.fSize;
msarett2aec3ff2016-07-20 12:58:52 -070060 }
61
msarett959ccc12016-07-20 15:10:02 -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);
msarett2aec3ff2016-07-20 12:58:52 -070069 }
msarett959ccc12016-07-20 15:10:02 -070070 };
msarett2aec3ff2016-07-20 12:58:52 -070071
msarett959ccc12016-07-20 15:10:02 -070072 bool isNamed(int i) const {
msarett2aec3ff2016-07-20 12:58:52 -070073 SkASSERT(0 <= i && i < 3);
msarett959ccc12016-07-20 15:10:02 -070074 return (&fRedType)[i] == Type::kNamed_Type;
msarett2aec3ff2016-07-20 12:58:52 -070075 }
76
msarett959ccc12016-07-20 15:10:02 -070077 bool isValue(int i) const {
78 SkASSERT(0 <= i && i < 3);
79 return (&fRedType)[i] == Type::kValue_Type;
80 }
msarett2aec3ff2016-07-20 12:58:52 -070081
msarett959ccc12016-07-20 15:10:02 -070082 bool isTable(int i) const {
83 SkASSERT(0 <= i && i < 3);
84 return (&fRedType)[i] == Type::kTable_Type;
85 }
86
87 bool isParametric(int i) const {
88 SkASSERT(0 <= i && i < 3);
89 return (&fRedType)[i] == Type::kParam_Type;
90 }
91
92 const Data& data(int i) const {
93 SkASSERT(0 <= i && i < 3);
94 return (&fRedData)[i];
95 }
96
97 const float* table(int i) const {
98 SkASSERT(isTable(i));
99 return (&fRedData)[i].fTable.table(this);
100 }
101
102 const Params& params(int i) const {
103 SkASSERT(isParametric(i));
104 return (&fRedData)[i].params(this);
105 }
106
107 SkGammas()
108 : fRedType(Type::kNone_Type)
109 , fGreenType(Type::kNone_Type)
110 , fBlueType(Type::kNone_Type)
msarett2aec3ff2016-07-20 12:58:52 -0700111 {}
112
msarett959ccc12016-07-20 15:10:02 -0700113 // These fields should only be modified when initializing the struct.
114 Data fRedData;
115 Data fGreenData;
116 Data fBlueData;
117 Type fRedType;
118 Type fGreenType;
119 Type fBlueType;
msarett2aec3ff2016-07-20 12:58:52 -0700120
msarett959ccc12016-07-20 15:10:02 -0700121 // Objects of this type are sometimes created in a custom fashion using
122 // sk_malloc_throw and therefore must be sk_freed. We overload new to
123 // also call sk_malloc_throw so that memory can be unconditionally released
124 // using sk_free in an overloaded delete. Overloading regular new means we
125 // must also overload placement new.
126 void* operator new(size_t size) { return sk_malloc_throw(size); }
127 void* operator new(size_t, void* p) { return p; }
128 void operator delete(void* p) { sk_free(p); }
msarettbb9f7742016-05-17 09:31:20 -0700129};
130
msarett0f83e012016-06-23 15:12:52 -0700131struct SkColorLookUpTable : public SkRefCnt {
msarettbb9f7742016-05-17 09:31:20 -0700132 uint8_t fInputChannels;
133 uint8_t fOutputChannels;
msarett0f83e012016-06-23 15:12:52 -0700134 uint8_t fGridPoints[3];
msarettbb9f7742016-05-17 09:31:20 -0700135 std::unique_ptr<float[]> fTable;
136
msarett0f83e012016-06-23 15:12:52 -0700137 SkColorLookUpTable()
138 : fInputChannels(0)
139 , fOutputChannels(0)
140 , fTable(nullptr)
141 {
142 fGridPoints[0] = fGridPoints[1] = fGridPoints[2] = 0;
msarettbb9f7742016-05-17 09:31:20 -0700143 }
144};
145
msarett8cc20912016-05-23 09:29:29 -0700146class SkColorSpace_Base : public SkColorSpace {
147public:
148
msarettc4ce6b52016-06-16 07:37:41 -0700149 static sk_sp<SkColorSpace> NewRGB(float gammas[3], const SkMatrix44& toXYZD50);
150
msarettb3906762016-06-22 14:07:48 -0700151 const SkGammas* gammas() const { return fGammas.get(); }
msarett8cc20912016-05-23 09:29:29 -0700152
msarettb3906762016-06-22 14:07:48 -0700153 const SkColorLookUpTable* colorLUT() const { return fColorLUT.get(); }
msarettdc27a642016-06-06 12:02:31 -0700154
msarettab926f02016-05-25 08:53:40 -0700155 /**
156 * Writes this object as an ICC profile.
157 */
158 sk_sp<SkData> writeToICC() const;
159
msarett8cc20912016-05-23 09:29:29 -0700160private:
161
msarett111a42d2016-06-22 08:18:54 -0700162 static sk_sp<SkColorSpace> NewRGB(GammaNamed gammaNamed, const SkMatrix44& toXYZD50);
msarettab926f02016-05-25 08:53:40 -0700163
msarett111a42d2016-06-22 08:18:54 -0700164 SkColorSpace_Base(GammaNamed gammaNamed, const SkMatrix44& toXYZ, Named named);
msarett8cc20912016-05-23 09:29:29 -0700165
msarett959ccc12016-07-20 15:10:02 -0700166 SkColorSpace_Base(sk_sp<SkColorLookUpTable> colorLUT, GammaNamed gammaNamed,
167 sk_sp<SkGammas> gammas, const SkMatrix44& toXYZ, sk_sp<SkData> profileData);
msarett8cc20912016-05-23 09:29:29 -0700168
msarett0f83e012016-06-23 15:12:52 -0700169 sk_sp<SkColorLookUpTable> fColorLUT;
170 sk_sp<SkGammas> fGammas;
171 sk_sp<SkData> fProfileData;
msarett8cc20912016-05-23 09:29:29 -0700172
173 friend class SkColorSpace;
msarettb3906762016-06-22 14:07:48 -0700174 friend class ColorSpaceXformTest;
msarett8cc20912016-05-23 09:29:29 -0700175 typedef SkColorSpace INHERITED;
176};
177
178static inline SkColorSpace_Base* as_CSB(SkColorSpace* colorSpace) {
179 return static_cast<SkColorSpace_Base*>(colorSpace);
180}
181
msarettab926f02016-05-25 08:53:40 -0700182static inline const SkColorSpace_Base* as_CSB(const SkColorSpace* colorSpace) {
183 return static_cast<const SkColorSpace_Base*>(colorSpace);
184}
185
msarett888dc162016-05-23 10:21:17 -0700186static inline SkColorSpace_Base* as_CSB(const sk_sp<SkColorSpace>& colorSpace) {
187 return static_cast<SkColorSpace_Base*>(colorSpace.get());
188}
189
msarettbb9f7742016-05-17 09:31:20 -0700190#endif