1 /****************************************************************************
2 **
3 ** DQt - D bindings for the Qt Toolkit
4 **
5 ** GNU Lesser General Public License Usage
6 ** This file may be used under the terms of the GNU Lesser
7 ** General Public License version 3 as published by the Free Software
8 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
9 ** packaging of this file. Please review the following information to
10 ** ensure the GNU Lesser General Public License version 3 requirements
11 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
12 **
13 ****************************************************************************/
14 module qt.gui.rgba64;
15 extern(C++):
16 
17 import qt.config;
18 import qt.core.global;
19 import qt.core.typeinfo;
20 import qt.helpers;
21 
22 @Q_PRIMITIVE_TYPE extern(C++, class) struct QRgba64 {
23 private:
24     quint64 rgba;
25 
26     // Make sure that the representation always has the order: red green blue alpha, independent
27     // of byte order. This way, vector operations that assume 4 16-bit values see the correct ones.
28     mixin("enum Shifts {"
29         ~ (versionIsSet!("BigEndian") ? q{
30     /+ #if Q_BYTE_ORDER == Q_BIG_ENDIAN +/
31             RedShift = 48,
32             GreenShift = 32,
33             BlueShift = 16,
34             AlphaShift = 0
35         }:q{
36     /+ #else +/ // little endian:
37             RedShift = 0,
38             GreenShift = 16,
39             BlueShift = 32,
40             AlphaShift = 48
41         /+ #endif +/
42         })
43         ~ "}"
44     );
45 
46     /+ explicit +/ /+ Q_ALWAYS_INLINE +/ pragma(inline, true) this(quint64 c)
47     {
48         this.rgba = c;
49     }
50 public:
51     /+ QRgba64() = default; +/
52 
53     static QRgba64 fromRgba64(quint64 c)
54     {
55         return QRgba64(c);
56     }
57     static QRgba64 fromRgba64(quint16 red, quint16 green, quint16 blue, quint16 alpha)
58     {
59         return fromRgba64(quint64(red)   << Shifts.RedShift
60                         | quint64(green) << Shifts.GreenShift
61                         | quint64(blue)  << Shifts.BlueShift
62                         | quint64(alpha) << Shifts.AlphaShift);
63     }
64     static QRgba64 fromRgba(quint8 red, quint8 green, quint8 blue, quint8 alpha)
65     {
66         QRgba64 rgb64 = fromRgba64(red, green, blue, alpha);
67         // Expand the range so that 0x00 maps to 0x0000 and 0xff maps to 0xffff.
68         rgb64.rgba |= rgb64.rgba << 8;
69         return rgb64;
70     }
71 /+    static QRgba64 fromArgb32(uint rgb)
72     {
73         return fromRgba(cast(quint8)(rgb >> 16), cast(quint8)(rgb >> 8), cast(quint8)(rgb), cast(quint8)(rgb >> 24));
74     }
75 +/
76     bool isOpaque() const
77     {
78         return (rgba & alphaMask()) == alphaMask();
79     }
80     bool isTransparent() const
81     {
82         return (rgba & alphaMask()) == 0;
83     }
84 
85     quint16 red()   const { return cast(quint16)(rgba >> Shifts.RedShift);   }
86     quint16 green() const { return cast(quint16)(rgba >> Shifts.GreenShift); }
87     quint16 blue()  const { return cast(quint16)(rgba >> Shifts.BlueShift);  }
88     quint16 alpha() const { return cast(quint16)(rgba >> Shifts.AlphaShift); }
89     void setRed(quint16 _red)     { rgba = (rgba & ~(0xffffuL << Shifts.RedShift))   | (quint64(_red) << Shifts.RedShift); }
90     void setGreen(quint16 _green) { rgba = (rgba & ~(0xffffuL << Shifts.GreenShift)) | (quint64(_green) << Shifts.GreenShift); }
91     void setBlue(quint16 _blue)   { rgba = (rgba & ~(0xffffuL << Shifts.BlueShift))  | (quint64(_blue) << Shifts.BlueShift); }
92     void setAlpha(quint16 _alpha) { rgba = (rgba & ~(0xffffuL << Shifts.AlphaShift)) | (quint64(_alpha) << Shifts.AlphaShift); }
93 
94     quint8 red8()   const { return div_257(red()); }
95     quint8 green8() const { return div_257(green()); }
96     quint8 blue8()  const { return div_257(blue()); }
97     quint8 alpha8() const { return div_257(alpha()); }
98     uint toArgb32() const
99     {
100 /+ #if defined(__cpp_constexpr) && __cpp_constexpr-0 >= 201304 +/
101         quint64 br = rgba & 0xffff0000ffffuL;
102         quint64 ag = (rgba >> 16) & 0xffff0000ffffuL;
103         br += 0x8000000080uL;
104         ag += 0x8000000080uL;
105         br = (br - ((br >> 8) & 0xffff0000ffffuL)) >> 8;
106         ag = (ag - ((ag >> 8) & 0xffff0000ffffuL));
107 /+ #if Q_BYTE_ORDER == Q_BIG_ENDIAN +/
108         static if(versionIsSet!("BigEndian"))
109         {
110             return cast(uint)(((br << 24) & 0xff000000)
111                  | ((ag >> 24) & 0xff0000)
112                  | ((br >> 24) & 0xff00)
113                  | ((ag >> 8)  & 0xff));
114         }
115         else
116         {
117     /+ #else +/
118             return cast(uint)(((ag >> 16) & 0xff000000)
119                  | ((br << 16) & 0xff0000)
120                  | (ag         & 0xff00)
121                  | ((br >> 32) & 0xff));
122         }
123 /+ #endif
124 #else
125         return uint((alpha8() << 24) | (red8() << 16) | (green8() << 8) | blue8());
126 #endif +/
127     }
128     ushort toRgb16() const
129     {
130         return cast(ushort)((red() & 0xf800) | ((green() >> 10) << 5) | (blue() >> 11));
131     }
132 
133     QRgba64 premultiplied() const
134     {
135         if (isOpaque())
136             return this;
137         if (isTransparent())
138             return QRgba64.fromRgba64(0);
139         const(quint64) a = alpha();
140         quint64 br = (rgba & 0xffff0000ffffuL) * a;
141         quint64 ag = ((rgba >> 16) & 0xffff0000ffffuL) * a;
142         br = (br + ((br >> 16) & 0xffff0000ffffuL) + 0x800000008000uL);
143         ag = (ag + ((ag >> 16) & 0xffff0000ffffuL) + 0x800000008000uL);
144         static if(versionIsSet!("BigEndian"))
145         {
146             ag = ag & 0xffff0000ffff0000uL;
147             br = (br >> 16) & 0xffff00000000uL;
148             return fromRgba64(a | br | ag);
149         }
150         else
151         {
152             br = (br >> 16) & 0xffff0000ffffuL;
153             ag = ag & 0xffff0000uL;
154             return fromRgba64((a << 48) | br | ag);
155         }
156     }
157 
158 /+    QRgba64 unpremultiplied() const
159     {
160         static if(configValue!"Q_PROCESSOR_WORDSIZE" < 8)
161         {
162             return unpremultiplied_32bit();
163         }
164         else
165         {
166             return unpremultiplied_64bit();
167         }
168     }
169 +/
170     /+auto opCast(T : quint64)() const
171     {
172         return rgba;
173     }+/
174 
175     /+QRgba64 operator =(quint64 _rgba)
176     {
177         rgba = _rgba;
178         return this;
179     }+/
180 
181 private:
182     /+ Q_ALWAYS_INLINE +/ pragma(inline, true) static quint64 alphaMask() { return 0xffffuL << Shifts.AlphaShift; }
183 
184     /+ Q_ALWAYS_INLINE +/ pragma(inline, true) static quint8 div_257_floor(uint x) { return cast(quint8)((x - (x >> 8)) >> 8); }
185     /+ Q_ALWAYS_INLINE +/ pragma(inline, true) static quint8 div_257(quint16 x) { return div_257_floor(x + 128U); }
186     /+ Q_ALWAYS_INLINE +/ pragma(inline, true) QRgba64 unpremultiplied_32bit() const
187     {
188         if (isOpaque() || isTransparent())
189             return this;
190         const(quint32) a = alpha();
191         const(quint16) r = cast(quint16)((red()   * 0xffff + a/2) / a);
192         const(quint16) g = cast(quint16)((green() * 0xffff + a/2) / a);
193         const(quint16) b = cast(quint16)((blue()  * 0xffff + a/2) / a);
194         return fromRgba64(r, g, b, cast(quint16)(a));
195     }
196     /+ Q_ALWAYS_INLINE +/ pragma(inline, true) QRgba64 unpremultiplied_64bit() const
197     {
198         if (isOpaque() || isTransparent())
199             return this;
200         const(quint64) a = alpha();
201         const(quint64) fa = (0xffff00008000uL + a/2) / a;
202         const(quint16) r = cast(quint16)((red()   * fa + 0x80000000) >> 32);
203         const(quint16) g = cast(quint16)((green() * fa + 0x80000000) >> 32);
204         const(quint16) b = cast(quint16)((blue()  * fa + 0x80000000) >> 32);
205         return fromRgba64(r, g, b, cast(quint16)(a));
206     }
207 }
208 
209 /+ Q_DECLARE_TYPEINFO(QRgba64, Q_PRIMITIVE_TYPE); +/
210 
211 pragma(inline, true) QRgba64 qRgba64(quint16 r, quint16 g, quint16 b, quint16 a)
212 {
213     return QRgba64.fromRgba64(r, g, b, a);
214 }
215 
216 pragma(inline, true) QRgba64 qRgba64(quint64 c)
217 {
218     return QRgba64.fromRgba64(c);
219 }
220 
221 /+pragma(inline, true) QRgba64 qPremultiply(QRgba64 c)
222 {
223     return c.premultiplied();
224 }
225 
226 pragma(inline, true) QRgba64 qUnpremultiply(QRgba64 c)
227 {
228     return c.unpremultiplied();
229 }
230 
231 pragma(inline, true) uint qRed(QRgba64 rgb)
232 { return rgb.red8(); }
233 
234 pragma(inline, true) uint qGreen(QRgba64 rgb)
235 { return rgb.green8(); }
236 
237 pragma(inline, true) uint qBlue(QRgba64 rgb)
238 { return rgb.blue8(); }
239 
240 pragma(inline, true) uint qAlpha(QRgba64 rgb)
241 { return rgb.alpha8(); }
242 +/
243