| /* |
| * Copyright 2016 Google Inc. |
| * |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| #ifndef SkGammas_DEFINED |
| #define SkGammas_DEFINED |
| |
| #include "SkColorSpace.h" |
| #include "SkData.h" |
| #include "SkTemplates.h" |
| |
| struct SkGammas : SkRefCnt { |
| |
| // There are four possible representations for gamma curves. kNone_Type is used |
| // as a placeholder until the struct is initialized. It is not a valid value. |
| enum class Type { |
| kNone_Type, |
| kNamed_Type, |
| kValue_Type, |
| kTable_Type, |
| kParam_Type, |
| }; |
| |
| // Contains information for a gamma table. |
| struct Table { |
| size_t fOffset; |
| int fSize; |
| |
| const float* table(const SkGammas* base) const { |
| return SkTAddOffset<const float>(base, sizeof(SkGammas) + fOffset); |
| } |
| }; |
| |
| // Contains the actual gamma curve information. Should be interpreted |
| // based on the type of the gamma curve. |
| union Data { |
| Data() : fTable{0, 0} {} |
| |
| SkGammaNamed fNamed; |
| float fValue; |
| Table fTable; |
| size_t fParamOffset; |
| |
| const SkColorSpaceTransferFn& params(const SkGammas* base) const { |
| return *SkTAddOffset<const SkColorSpaceTransferFn>(base, |
| sizeof(SkGammas) + fParamOffset); |
| } |
| }; |
| |
| bool allChannelsSame() const { |
| // All channels are the same type? |
| Type type = this->type(0); |
| for (int i = 1; i < this->channels(); i++) { |
| if (type != this->type(i)) { |
| return false; |
| } |
| } |
| |
| // All data the same? |
| auto& first = this->data(0); |
| for (int i = 1; i < this->channels(); i++) { |
| auto& data = this->data(i); |
| switch (type) { |
| case Type:: kNone_Type: break; |
| case Type::kNamed_Type: if (first.fNamed != data.fNamed) { return false; } break; |
| case Type::kValue_Type: if (first.fValue != data.fValue) { return false; } break; |
| case Type::kTable_Type: |
| if (first.fTable.fOffset != data.fTable.fOffset) { return false; } |
| if (first.fTable.fSize != data.fTable.fSize ) { return false; } |
| break; |
| case Type::kParam_Type: |
| if (0 != memcmp(&first.params(this), &data.params(this), |
| sizeof(SkColorSpaceTransferFn))) { |
| return false; |
| } |
| break; |
| } |
| } |
| return true; |
| } |
| |
| bool isNamed (int i) const { return Type::kNamed_Type == this->type(i); } |
| bool isValue (int i) const { return Type::kValue_Type == this->type(i); } |
| bool isTable (int i) const { return Type::kTable_Type == this->type(i); } |
| bool isParametric(int i) const { return Type::kParam_Type == this->type(i); } |
| |
| const Data& data(int i) const { |
| SkASSERT(i >= 0 && i < fChannels); |
| return fData[i]; |
| } |
| |
| const float* table(int i) const { |
| SkASSERT(this->isTable(i)); |
| return this->data(i).fTable.table(this); |
| } |
| |
| int tableSize(int i) const { |
| SkASSERT(this->isTable(i)); |
| return this->data(i).fTable.fSize; |
| } |
| |
| const SkColorSpaceTransferFn& params(int i) const { |
| SkASSERT(this->isParametric(i)); |
| return this->data(i).params(this); |
| } |
| |
| Type type(int i) const { |
| SkASSERT(i >= 0 && i < fChannels); |
| return fType[i]; |
| } |
| |
| int channels() const { return fChannels; } |
| |
| SkGammas(int channels) : fChannels(channels) { |
| SkASSERT(channels <= (int)SK_ARRAY_COUNT(fType)); |
| for (Type& t : fType) { |
| t = Type::kNone_Type; |
| } |
| } |
| |
| // These fields should only be modified when initializing the struct. |
| int fChannels; |
| Data fData[4]; |
| Type fType[4]; |
| |
| // Objects of this type are sometimes created in a custom fashion using |
| // sk_malloc_throw and therefore must be sk_freed. We overload new to |
| // also call sk_malloc_throw so that memory can be unconditionally released |
| // using sk_free in an overloaded delete. Overloading regular new means we |
| // must also overload placement new. |
| void* operator new(size_t size) { return sk_malloc_throw(size); } |
| void* operator new(size_t, void* p) { return p; } |
| void operator delete(void* p) { sk_free(p); } |
| }; |
| |
| #endif |