1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
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
|