/* * 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 "SkColorSpace.h" #include "SkData.h" #include "SkTemplates.h" struct SkGammaCurve { bool isNamed() const { bool result = (SkColorSpace::kNonStandard_GammaNamed != fNamed); SkASSERT(!result || (0.0f == fValue)); SkASSERT(!result || (0 == fTableSize)); SkASSERT(!result || (0.0f == fG && 0.0f == fE)); return result; } bool isValue() const { bool result = (0.0f != fValue); SkASSERT(!result || SkColorSpace::kNonStandard_GammaNamed == fNamed); SkASSERT(!result || (0 == fTableSize)); SkASSERT(!result || (0.0f == fG && 0.0f == fE)); return result; } bool isTable() const { bool result = (0 != fTableSize); SkASSERT(!result || SkColorSpace::kNonStandard_GammaNamed == fNamed); SkASSERT(!result || (0.0f == fValue)); SkASSERT(!result || (0.0f == fG && 0.0f == fE)); SkASSERT(!result || fTable); return result; } bool isParametric() const { bool result = (0.0f != fG || 0.0f != fE); SkASSERT(!result || SkColorSpace::kNonStandard_GammaNamed == fNamed); SkASSERT(!result || (0.0f == fValue)); SkASSERT(!result || (0 == fTableSize)); return result; } // We have four different ways to represent gamma. // (1) A known, named type: SkColorSpace::GammaNamed fNamed; // (2) A single value: float fValue; // (3) A lookup table: uint32_t fTableSize; std::unique_ptr fTable; // (4) Parameters for a curve: // Y = (aX + b)^g + c for X >= d // Y = eX + f otherwise float fG; float fA; float fB; float fC; float fD; float fE; float fF; SkGammaCurve() : fNamed(SkColorSpace::kNonStandard_GammaNamed) , fValue(0.0f) , fTableSize(0) , fTable(nullptr) , fG(0.0f) , fA(0.0f) , fB(0.0f) , fC(0.0f) , fD(0.0f) , fE(0.0f) , fF(0.0f) {} }; struct SkGammas : public SkRefCnt { public: static SkColorSpace::GammaNamed Named(SkGammaCurve curves[3]) { if (SkColorSpace::kLinear_GammaNamed == curves[0].fNamed && SkColorSpace::kLinear_GammaNamed == curves[1].fNamed && SkColorSpace::kLinear_GammaNamed == curves[2].fNamed) { return SkColorSpace::kLinear_GammaNamed; } if (SkColorSpace::kSRGB_GammaNamed == curves[0].fNamed && SkColorSpace::kSRGB_GammaNamed == curves[1].fNamed && SkColorSpace::kSRGB_GammaNamed == curves[2].fNamed) { return SkColorSpace::kSRGB_GammaNamed; } if (SkColorSpace::k2Dot2Curve_GammaNamed == curves[0].fNamed && SkColorSpace::k2Dot2Curve_GammaNamed == curves[1].fNamed && SkColorSpace::k2Dot2Curve_GammaNamed == curves[2].fNamed) { return SkColorSpace::k2Dot2Curve_GammaNamed; } return SkColorSpace::kNonStandard_GammaNamed; } const SkGammaCurve& operator[](int i) { SkASSERT(0 <= i && i < 3); return (&fRed)[i]; } const SkGammaCurve fRed; const SkGammaCurve fGreen; const SkGammaCurve fBlue; SkGammas(SkGammaCurve red, SkGammaCurve green, SkGammaCurve blue) : fRed(std::move(red)) , fGreen(std::move(green)) , fBlue(std::move(blue)) {} SkGammas() {} friend class SkColorSpace; }; struct SkColorLookUpTable { static const uint8_t kMaxChannels = 16; uint8_t fInputChannels; uint8_t fOutputChannels; uint8_t fGridPoints[kMaxChannels]; std::unique_ptr fTable; SkColorLookUpTable() { memset(this, 0, sizeof(struct SkColorLookUpTable)); } }; class SkColorSpace_Base : public SkColorSpace { public: static sk_sp NewRGB(float gammas[3], const SkMatrix44& toXYZD50); const sk_sp& gammas() const { return fGammas; } SkColorLookUpTable* colorLUT() const { return fColorLUT.get(); } /** * Writes this object as an ICC profile. */ sk_sp writeToICC() const; private: static sk_sp NewRGB(GammaNamed gammaNamed, const SkMatrix44& toXYZD50); SkColorSpace_Base(GammaNamed gammaNamed, const SkMatrix44& toXYZ, Named named); SkColorSpace_Base(SkColorLookUpTable* colorLUT, sk_sp gammas, const SkMatrix44& toXYZ, sk_sp profileData); SkAutoTDelete fColorLUT; sk_sp fGammas; sk_sp fProfileData; friend class SkColorSpace; typedef SkColorSpace INHERITED; }; static inline SkColorSpace_Base* as_CSB(SkColorSpace* colorSpace) { return static_cast(colorSpace); } static inline const SkColorSpace_Base* as_CSB(const SkColorSpace* colorSpace) { return static_cast(colorSpace); } static inline SkColorSpace_Base* as_CSB(const sk_sp& colorSpace) { return static_cast(colorSpace.get()); } #endif