• 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 SkGammas_DEFINED
9 #define SkGammas_DEFINED
10 
11 #include "SkColorSpace.h"
12 #include "SkData.h"
13 #include "SkTemplates.h"
14 
15 struct SkGammas : SkRefCnt {
16 
17     // 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 {
20         kNone_Type,
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 
tableSkGammas::Table32         const float* table(const SkGammas* base) const {
33             return SkTAddOffset<const float>(base, sizeof(SkGammas) + fOffset);
34         }
35     };
36 
37     // Contains the actual gamma curve information.  Should be interpreted
38     // based on the type of the gamma curve.
39     union Data {
Data()40         Data() : fTable{0, 0} {}
41 
42         SkGammaNamed fNamed;
43         float        fValue;
44         Table        fTable;
45         size_t       fParamOffset;
46 
params(const SkGammas * base)47         const SkColorSpaceTransferFn& params(const SkGammas* base) const {
48             return *SkTAddOffset<const SkColorSpaceTransferFn>(base,
49                                                                sizeof(SkGammas) + fParamOffset);
50         }
51     };
52 
allChannelsSameSkGammas53     bool allChannelsSame() const {
54         // All channels are the same type?
55         Type type = this->type(0);
56         for (int i = 1; i < this->channels(); i++) {
57             if (type != this->type(i)) {
58                 return false;
59             }
60         }
61 
62         // All data the same?
63         auto& first = this->data(0);
64         for (int i = 1; i < this->channels(); i++) {
65             auto& data = this->data(i);
66             switch (type) {
67                 case Type:: kNone_Type:                                                    break;
68                 case Type::kNamed_Type: if (first.fNamed != data.fNamed) { return false; } break;
69                 case Type::kValue_Type: if (first.fValue != data.fValue) { return false; } break;
70                 case Type::kTable_Type:
71                     if (first.fTable.fOffset != data.fTable.fOffset) { return false; }
72                     if (first.fTable.fSize   != data.fTable.fSize  ) { return false; }
73                     break;
74                 case Type::kParam_Type:
75                     if (0 != memcmp(&first.params(this), &data.params(this),
76                                     sizeof(SkColorSpaceTransferFn))) {
77                         return false;
78                     }
79                     break;
80             }
81         }
82         return true;
83     }
84 
isNamedSkGammas85     bool isNamed     (int i) const { return Type::kNamed_Type == this->type(i); }
isValueSkGammas86     bool isValue     (int i) const { return Type::kValue_Type == this->type(i); }
isTableSkGammas87     bool isTable     (int i) const { return Type::kTable_Type == this->type(i); }
isParametricSkGammas88     bool isParametric(int i) const { return Type::kParam_Type == this->type(i); }
89 
dataSkGammas90     const Data& data(int i) const {
91         SkASSERT(i >= 0 && i < fChannels);
92         return fData[i];
93     }
94 
tableSkGammas95     const float* table(int i) const {
96         SkASSERT(this->isTable(i));
97         return this->data(i).fTable.table(this);
98     }
99 
tableSizeSkGammas100     int tableSize(int i) const {
101         SkASSERT(this->isTable(i));
102         return this->data(i).fTable.fSize;
103     }
104 
paramsSkGammas105     const SkColorSpaceTransferFn& params(int i) const {
106         SkASSERT(this->isParametric(i));
107         return this->data(i).params(this);
108     }
109 
typeSkGammas110     Type type(int i) const {
111         SkASSERT(i >= 0 && i < fChannels);
112         return fType[i];
113     }
114 
channelsSkGammas115     int channels() const { return fChannels; }
116 
SkGammasSkGammas117     SkGammas(int channels) : fChannels(channels) {
118         SkASSERT(channels <= (int)SK_ARRAY_COUNT(fType));
119         for (Type& t : fType) {
120             t = Type::kNone_Type;
121         }
122     }
123 
124     // These fields should only be modified when initializing the struct.
125     int  fChannels;
126     Data fData[4];
127     Type fType[4];
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 #endif
140