| /* |
| * 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 SkColorSpace_Base_DEFINED |
| #define SkColorSpace_Base_DEFINED |
| |
| #include "SkColorLookUpTable.h" |
| #include "SkColorSpace.h" |
| #include "SkData.h" |
| #include "SkOnce.h" |
| #include "SkTemplates.h" |
| |
| enum SkGammaNamed : uint8_t { |
| kLinear_SkGammaNamed, |
| kSRGB_SkGammaNamed, |
| k2Dot2Curve_SkGammaNamed, |
| kNonStandard_SkGammaNamed, |
| }; |
| |
| 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 <= kMaxColorChannels); |
| for (uint8_t i = 0; i < kMaxColorChannels; ++i) { |
| fType[i] = Type::kNone_Type; |
| } |
| } |
| |
| // These fields should only be modified when initializing the struct. |
| uint8_t fChannels; |
| Data fData[kMaxColorChannels]; |
| Type fType[kMaxColorChannels]; |
| |
| // 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); } |
| }; |
| |
| class SkColorSpace_Base : public SkColorSpace { |
| public: |
| |
| /** |
| * Describes color space gamut as a transformation to XYZ D50. |
| * Returns nullptr if color gamut cannot be described in terms of XYZ D50. |
| */ |
| virtual const SkMatrix44* toXYZD50() const = 0; |
| |
| /** |
| * Returns a hash of the gamut transofmration to XYZ D50. Allows for fast equality checking |
| * of gamuts, at the (very small) risk of collision. |
| * Returns 0 if color gamut cannot be described in terms of XYZ D50. |
| */ |
| virtual uint32_t toXYZD50Hash() const = 0; |
| |
| /** |
| * Describes color space gamut as a transformation from XYZ D50 |
| * Returns nullptr if color gamut cannot be described in terms of XYZ D50. |
| */ |
| virtual const SkMatrix44* fromXYZD50() const = 0; |
| |
| virtual bool onGammaCloseToSRGB() const = 0; |
| |
| virtual bool onGammaIsLinear() const = 0; |
| |
| virtual bool onIsNumericalTransferFn(SkColorSpaceTransferFn* coeffs) const = 0; |
| |
| virtual bool onIsCMYK() const { return false; } |
| |
| /** |
| * Returns a color space with the same gamut as this one, but with a linear gamma. |
| * For color spaces whose gamut can not be described in terms of XYZ D50, returns |
| * linear sRGB. |
| */ |
| virtual sk_sp<SkColorSpace> makeLinearGamma() const = 0; |
| |
| /** |
| * Returns a color space with the same gamut as this one, with with the sRGB transfer |
| * function. For color spaces whose gamut can not be described in terms of XYZ D50, returns |
| * sRGB. |
| */ |
| virtual sk_sp<SkColorSpace> makeSRGBGamma() const = 0; |
| |
| enum class Type : uint8_t { |
| kXYZ, |
| kA2B |
| }; |
| |
| virtual Type type() const = 0; |
| |
| typedef uint8_t ICCTypeFlag; |
| static constexpr ICCTypeFlag kRGB_ICCTypeFlag = 1 << 0; |
| static constexpr ICCTypeFlag kCMYK_ICCTypeFlag = 1 << 1; |
| static constexpr ICCTypeFlag kGray_ICCTypeFlag = 1 << 2; |
| |
| static sk_sp<SkColorSpace> MakeICC(const void* input, size_t len, ICCTypeFlag type); |
| |
| static sk_sp<SkColorSpace> MakeRGB(SkGammaNamed gammaNamed, const SkMatrix44& toXYZD50); |
| |
| enum Named : uint8_t { |
| kSRGB_Named, |
| kAdobeRGB_Named, |
| kSRGBLinear_Named, |
| kSRGB_NonLinearBlending_Named, |
| }; |
| |
| static sk_sp<SkColorSpace> MakeNamed(Named); |
| |
| protected: |
| SkColorSpace_Base(sk_sp<SkData> profileData); |
| |
| private: |
| sk_sp<SkData> fProfileData; |
| |
| friend class SkColorSpace; |
| friend class SkColorSpace_XYZ; |
| friend class ColorSpaceXformTest; |
| friend class ColorSpaceTest; |
| typedef SkColorSpace INHERITED; |
| }; |
| |
| static inline SkColorSpace_Base* as_CSB(SkColorSpace* colorSpace) { |
| return static_cast<SkColorSpace_Base*>(colorSpace); |
| } |
| |
| static inline const SkColorSpace_Base* as_CSB(const SkColorSpace* colorSpace) { |
| return static_cast<const SkColorSpace_Base*>(colorSpace); |
| } |
| |
| static inline SkColorSpace_Base* as_CSB(const sk_sp<SkColorSpace>& colorSpace) { |
| return static_cast<SkColorSpace_Base*>(colorSpace.get()); |
| } |
| |
| #endif |