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