diff options
Diffstat (limited to 'src/gui/painting/qcolortransferfunction_p.h')
-rw-r--r-- | src/gui/painting/qcolortransferfunction_p.h | 81 |
1 files changed, 56 insertions, 25 deletions
diff --git a/src/gui/painting/qcolortransferfunction_p.h b/src/gui/painting/qcolortransferfunction_p.h index a9bb26df59..b9a09b4646 100644 --- a/src/gui/painting/qcolortransferfunction_p.h +++ b/src/gui/painting/qcolortransferfunction_p.h @@ -16,44 +16,52 @@ // #include <QtGui/private/qtguiglobal_p.h> +#include <QtCore/QFlags> #include <cmath> QT_BEGIN_NAMESPACE // Defines a ICC parametric curve type 4 -class Q_GUI_EXPORT QColorTransferFunction +class QColorTransferFunction { public: QColorTransferFunction() noexcept - : m_a(1.0f), m_b(0.0f), m_c(1.0f), m_d(0.0f), m_e(0.0f), m_f(0.0f), m_g(1.0f), m_flags(0) + : m_a(1.0f), m_b(0.0f), m_c(1.0f), m_d(0.0f), m_e(0.0f), m_f(0.0f), m_g(1.0f) + , m_flags(Hints(Hint::Calculated) | Hint::IsGamma | Hint::IsIdentity) { } + QColorTransferFunction(float a, float b, float c, float d, float e, float f, float g) noexcept - : m_a(a), m_b(b), m_c(c), m_d(d), m_e(e), m_f(f), m_g(g), m_flags(0) + : m_a(a), m_b(b), m_c(c), m_d(d), m_e(e), m_f(f), m_g(g), m_flags() { } bool isGamma() const { updateHints(); - return m_flags & quint32(Hints::IsGamma); + return m_flags & Hint::IsGamma; } - bool isLinear() const + bool isIdentity() const { updateHints(); - return m_flags & quint32(Hints::IsLinear); + return m_flags & Hint::IsIdentity; } bool isSRgb() const { updateHints(); - return m_flags & quint32(Hints::IsSRgb); + return m_flags & Hint::IsSRgb; } float apply(float x) const { if (x < m_d) return m_c * x + m_f; + float t = std::pow(m_a * x + m_b, m_g); + if (std::isfinite(t)) + return t + m_e; + if (t > 0.f) + return 1.f; else - return std::pow(m_a * x + m_b, m_g) + m_e; + return 0.f; } QColorTransferFunction inverted() const @@ -62,7 +70,7 @@ public: d = m_c * m_d + m_f; - if (!qFuzzyIsNull(m_c)) { + if (std::isnormal(m_c)) { c = 1.0f / m_c; f = -m_f / m_c; } else { @@ -70,8 +78,12 @@ public: f = 0.0f; } - if (!qFuzzyIsNull(m_a) && !qFuzzyIsNull(m_g)) { + bool valid_abeg = std::isnormal(m_a) && std::isnormal(m_g); + if (valid_abeg) a = std::pow(1.0f / m_a, m_g); + if (valid_abeg && !std::isfinite(a)) + valid_abeg = false; + if (valid_abeg) { b = -a * m_e; e = -m_b / m_a; g = 1.0f / m_g; @@ -88,15 +100,24 @@ public: // A few predefined curves: static QColorTransferFunction fromGamma(float gamma) { - return QColorTransferFunction(1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, gamma); + return QColorTransferFunction(1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, gamma, + Hints(Hint::Calculated) | Hint::IsGamma | + (paramCompare(gamma, 1.0f) ? Hint::IsIdentity : Hint::NoHint)); } static QColorTransferFunction fromSRgb() { - return QColorTransferFunction(1.0f / 1.055f, 0.055f / 1.055f, 1.0f / 12.92f, 0.04045f, 0.0f, 0.0f, 2.4f); + return QColorTransferFunction(1.0f / 1.055f, 0.055f / 1.055f, 1.0f / 12.92f, 0.04045f, 0.0f, 0.0f, 2.4f, + Hints(Hint::Calculated) | Hint::IsSRgb); } static QColorTransferFunction fromProPhotoRgb() { - return QColorTransferFunction(1.0f, 0.0f, 1.0f / 16.0f, 16.0f / 512.0f, 0.0f, 0.0f, 1.8f); + return QColorTransferFunction(1.0f, 0.0f, 1.0f / 16.0f, 16.0f / 512.0f, 0.0f, 0.0f, 1.8f, + Hints(Hint::Calculated)); + } + static QColorTransferFunction fromBt2020() + { + return QColorTransferFunction(1.0f / 1.0993f, 0.0993f / 1.0993f, 1.0f / 4.5f, 0.08145f, 0.0f, 0.0f, 2.2f, + Hints(Hint::Calculated)); } bool matches(const QColorTransferFunction &o) const { @@ -116,7 +137,20 @@ public: float m_f; float m_g; + enum class Hint : quint32 { + NoHint = 0, + Calculated = 1, + IsGamma = 2, + IsIdentity = 4, + IsSRgb = 8 + }; + + Q_DECLARE_FLAGS(Hints, Hint); + private: + QColorTransferFunction(float a, float b, float c, float d, float e, float f, float g, Hints flags) noexcept + : m_a(a), m_b(b), m_c(c), m_d(d), m_e(e), m_f(f), m_g(g), m_flags(flags) + { } static inline bool paramCompare(float p1, float p2) { // Much fuzzier than fuzzy compare. @@ -127,7 +161,7 @@ private: void updateHints() const { - if (m_flags & quint32(Hints::Calculated)) + if (m_flags & Hint::Calculated) return; // We do not consider the case with m_d = 1.0f linear or simple, // since it wouldn't be linear for applyExtended(). @@ -135,24 +169,21 @@ private: && paramCompare(m_d, 0.0f) && paramCompare(m_e, 0.0f); if (simple) { - m_flags |= quint32(Hints::IsGamma); + m_flags |= Hint::IsGamma; if (qFuzzyCompare(m_g, 1.0f)) - m_flags |= quint32(Hints::IsLinear); + m_flags |= Hint::IsIdentity; } else { if (*this == fromSRgb()) - m_flags |= quint32(Hints::IsSRgb); + m_flags |= Hint::IsSRgb; } - m_flags |= quint32(Hints::Calculated); + m_flags |= Hint::Calculated; } - enum class Hints : quint32 { - Calculated = 1, - IsGamma = 2, - IsLinear = 4, - IsSRgb = 8 - }; - mutable quint32 m_flags; + + mutable Hints m_flags; }; +Q_DECLARE_OPERATORS_FOR_FLAGS(QColorTransferFunction::Hints); + inline bool operator==(const QColorTransferFunction &f1, const QColorTransferFunction &f2) { return f1.matches(f2); |