diff options
Diffstat (limited to 'src/core/SkGammas.h')
-rw-r--r-- | src/core/SkGammas.h | 129 |
1 files changed, 129 insertions, 0 deletions
diff --git a/src/core/SkGammas.h b/src/core/SkGammas.h new file mode 100644 index 0000000000..b8b0abb83f --- /dev/null +++ b/src/core/SkGammas.h @@ -0,0 +1,129 @@ +/* + * 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 : uint8_t { + 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 } + {} + + inline bool operator==(const Data& that) const { + return this->fTable.fOffset == that.fTable.fOffset && + this->fTable.fSize == that.fTable.fSize; + } + + inline bool operator!=(const Data& that) const { + return !(*this == that); + } + + 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 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(isTable(i)); + return this->data(i).fTable.table(this); + } + + int tableSize(int i) const { + SkASSERT(isTable(i)); + return this->data(i).fTable.fSize; + } + + const SkColorSpaceTransferFn& params(int i) const { + SkASSERT(isParametric(i)); + return this->data(i).params(this); + } + + Type type(int i) const { + SkASSERT(i >= 0 && i < fChannels); + return fType[i]; + } + + uint8_t channels() const { return fChannels; } + + SkGammas(uint8_t channels) : fChannels(channels) { + SkASSERT(channels <= SK_ARRAY_COUNT(fType)); + for (Type& t : fType) { + t = Type::kNone_Type; + } + } + + // These fields should only be modified when initializing the struct. + uint8_t 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 |