diff options
Diffstat (limited to 'src/gui/painting/qrgbafloat.h')
-rw-r--r-- | src/gui/painting/qrgbafloat.h | 126 |
1 files changed, 126 insertions, 0 deletions
diff --git a/src/gui/painting/qrgbafloat.h b/src/gui/painting/qrgbafloat.h new file mode 100644 index 0000000000..da74328f71 --- /dev/null +++ b/src/gui/painting/qrgbafloat.h @@ -0,0 +1,126 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QRGBAFLOAT_H +#define QRGBAFLOAT_H + +#include <QtGui/qtguiglobal.h> +#include <QtCore/qfloat16.h> + +#include <algorithm> +#include <cmath> +#include <type_traits> + +QT_BEGIN_NAMESPACE + +template<typename F> +class alignas(sizeof(F) * 4) QRgbaFloat +{ + static_assert(std::is_same<F, qfloat16>::value || std::is_same<F, float>::value); +public: + using Type = F; +#if defined(__AVX512FP16__) && QFLOAT16_IS_NATIVE + // AVX512FP16 has multiplication instructions + using FastType = F; +#else + // use FP32 for multiplications + using FastType = float; +#endif + F r; + F g; + F b; + F a; + + static constexpr + QRgbaFloat fromRgba64(quint16 red, quint16 green, quint16 blue, quint16 alpha) + { + constexpr FastType scale = FastType(1.0f / 65535.0f); + return QRgbaFloat{ + F(red * scale), + F(green * scale), + F(blue * scale), + F(alpha * scale) }; + } + + static constexpr + QRgbaFloat fromRgba(quint8 red, quint8 green, quint8 blue, quint8 alpha) + { + constexpr FastType scale = FastType(1.0f / 255.0f); + return QRgbaFloat{ + F(red * scale), + F(green * scale), + F(blue * scale), + F(alpha * scale) }; + } + static constexpr + QRgbaFloat fromArgb32(uint rgb) + { + return fromRgba(quint8(rgb >> 16), quint8(rgb >> 8), quint8(rgb), quint8(rgb >> 24)); + } + + constexpr bool isOpaque() const { return a >= FastType(1.0f); } + constexpr bool isTransparent() const { return a <= FastType(0.0f); } + + constexpr float red() const { return r; } + constexpr float green() const { return g; } + constexpr float blue() const { return b; } + constexpr float alpha() const { return a; } + void setRed(float _red) { r = F(_red); } + void setGreen(float _green) { g = F(_green); } + void setBlue(float _blue) { b = F(_blue); } + void setAlpha(float _alpha) { a = F(_alpha); } + + constexpr float redNormalized() const { return clamp01(r); } + constexpr float greenNormalized() const { return clamp01(g); } + constexpr float blueNormalized() const { return clamp01(b); } + constexpr float alphaNormalized() const { return clamp01(a); } + + constexpr quint8 red8() const { return qRound(redNormalized() * FastType(255.0f)); } + constexpr quint8 green8() const { return qRound(greenNormalized() * FastType(255.0f)); } + constexpr quint8 blue8() const { return qRound(blueNormalized() * FastType(255.0f)); } + constexpr quint8 alpha8() const { return qRound(alphaNormalized() * FastType(255.0f)); } + constexpr uint toArgb32() const + { + return uint((alpha8() << 24) | (red8() << 16) | (green8() << 8) | blue8()); + } + + constexpr quint16 red16() const { return qRound(redNormalized() * FastType(65535.0f)); } + constexpr quint16 green16() const { return qRound(greenNormalized() * FastType(65535.0f)); } + constexpr quint16 blue16() const { return qRound(blueNormalized() * FastType(65535.0f)); } + constexpr quint16 alpha16() const { return qRound(alphaNormalized() * FastType(65535.0f)); } + + constexpr Q_ALWAYS_INLINE QRgbaFloat premultiplied() const + { + return QRgbaFloat{r * a, g * a, b * a, a}; + } + constexpr Q_ALWAYS_INLINE QRgbaFloat unpremultiplied() const + { + if (a <= F{0.0f}) + return QRgbaFloat{}; // default-initialization: zeroes + if (a >= F{1.0f}) + return *this; + const FastType ia = 1.0f / a; + return QRgbaFloat{F(r * ia), F(g * ia), F(b * ia), F(a)}; + } + constexpr bool operator==(QRgbaFloat f) const + { + return r == f.r && g == f.g && b == f.b && a == f.a; + } + constexpr bool operator!=(QRgbaFloat f) const + { + return !(*this == f); + } + +private: + constexpr static FastType clamp01(Type f) + { + return std::clamp(FastType(f), FastType(0.0f), FastType(1.0f)); + } +}; + +typedef QRgbaFloat<qfloat16> QRgbaFloat16; +typedef QRgbaFloat<float> QRgbaFloat32; + +QT_END_NAMESPACE + +#endif // QRGBAFLOAT_H |