• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 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 
tableSkGammas::Table41         const float* table(const SkGammas* base) const {
42             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 {
Data()49         Data()
50             : fTable{ 0, 0 }
51         {}
52 
53         inline bool operator==(const Data& that) const {
54             return this->fTable.fOffset == that.fTable.fOffset &&
55                    this->fTable.fSize == that.fTable.fSize;
56         }
57 
58         inline bool operator!=(const Data& that) const {
59             return !(*this == that);
60         }
61 
62         SkGammaNamed             fNamed;
63         float                    fValue;
64         Table                    fTable;
65         size_t                   fParamOffset;
66 
params(const SkGammas * base)67         const SkColorSpaceTransferFn& params(const SkGammas* base) const {
68             return *SkTAddOffset<const SkColorSpaceTransferFn>(
69                     base, sizeof(SkGammas) + fParamOffset);
70         }
71     };
72 
isNamedSkGammas73     bool isNamed(int i) const {
74         return Type::kNamed_Type == this->type(i);
75     }
76 
isValueSkGammas77     bool isValue(int i) const {
78         return Type::kValue_Type == this->type(i);
79     }
80 
isTableSkGammas81     bool isTable(int i) const {
82         return Type::kTable_Type == this->type(i);
83     }
84 
isParametricSkGammas85     bool isParametric(int i) const {
86         return Type::kParam_Type == this->type(i);
87     }
88 
dataSkGammas89     const Data& data(int i) const {
90         SkASSERT(i >= 0 && i < fChannels);
91         return fData[i];
92     }
93 
tableSkGammas94     const float* table(int i) const {
95         SkASSERT(isTable(i));
96         return this->data(i).fTable.table(this);
97     }
98 
tableSizeSkGammas99     int tableSize(int i) const {
100         SkASSERT(isTable(i));
101         return this->data(i).fTable.fSize;
102     }
103 
paramsSkGammas104     const SkColorSpaceTransferFn& params(int i) const {
105         SkASSERT(isParametric(i));
106         return this->data(i).params(this);
107     }
108 
typeSkGammas109     Type type(int i) const {
110         SkASSERT(i >= 0 && i < fChannels);
111         return fType[i];
112     }
113 
channelsSkGammas114     uint8_t channels() const { return fChannels; }
115 
SkGammasSkGammas116     SkGammas(uint8_t channels)
117         : fChannels(channels) {
118         SkASSERT(channels <= kMaxColorChannels);
119         for (uint8_t i = 0; i < kMaxColorChannels; ++i) {
120             fType[i] = Type::kNone_Type;
121         }
122     }
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.
newSkGammas134     void* operator new(size_t size) { return sk_malloc_throw(size); }
newSkGammas135     void* operator new(size_t, void* p) { return p; }
deleteSkGammas136     void operator delete(void* p) { sk_free(p); }
137 };
138 
139 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 
onIsCMYK()167     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() const = 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() const = 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 
as_CSB(SkColorSpace * colorSpace)221 static inline SkColorSpace_Base* as_CSB(SkColorSpace* colorSpace) {
222     return static_cast<SkColorSpace_Base*>(colorSpace);
223 }
224 
as_CSB(const SkColorSpace * colorSpace)225 static inline const SkColorSpace_Base* as_CSB(const SkColorSpace* colorSpace) {
226     return static_cast<const SkColorSpace_Base*>(colorSpace);
227 }
228 
as_CSB(const sk_sp<SkColorSpace> & colorSpace)229 static inline SkColorSpace_Base* as_CSB(const sk_sp<SkColorSpace>& colorSpace) {
230     return static_cast<SkColorSpace_Base*>(colorSpace.get());
231 }
232 
233 #endif
234