/src/qtbase/src/gui/painting/qpixellayout_p.h
Line | Count | Source |
1 | | // Copyright (C) 2020 The Qt Company Ltd. |
2 | | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only |
3 | | // Qt-Security score:significant reason:default |
4 | | |
5 | | #ifndef QPIXELLAYOUT_P_H |
6 | | #define QPIXELLAYOUT_P_H |
7 | | |
8 | | // |
9 | | // W A R N I N G |
10 | | // ------------- |
11 | | // |
12 | | // This file is not part of the Qt API. It exists purely as an |
13 | | // implementation detail. This header file may change from version to |
14 | | // version without notice, or even be removed. |
15 | | // |
16 | | // We mean it. |
17 | | // |
18 | | |
19 | | #include <QtCore/qlist.h> |
20 | | #include <QtGui/qimage.h> |
21 | | #include <QtGui/qrgba64.h> |
22 | | #include <QtGui/qrgbafloat.h> |
23 | | #include <QtCore/private/qglobal_p.h> |
24 | | |
25 | | QT_BEGIN_NAMESPACE |
26 | | |
27 | | enum QtPixelOrder { |
28 | | PixelOrderRGB, |
29 | | PixelOrderBGR |
30 | | }; |
31 | | |
32 | | template<enum QtPixelOrder> inline uint qConvertArgb32ToA2rgb30(QRgb); |
33 | | |
34 | | template<enum QtPixelOrder> inline uint qConvertRgb32ToRgb30(QRgb); |
35 | | |
36 | | template<enum QtPixelOrder> inline QRgb qConvertA2rgb30ToArgb32(uint c); |
37 | | |
38 | | // A combined unpremultiply and premultiply with new simplified alpha. |
39 | | // Needed when alpha loses precision relative to other colors during conversion (ARGB32 -> A2RGB30). |
40 | | template<unsigned int Shift> |
41 | | inline QRgb qRepremultiply(QRgb p) |
42 | 0 | { |
43 | 0 | const uint alpha = qAlpha(p); |
44 | 0 | if (alpha == 255 || alpha == 0) |
45 | 0 | return p; |
46 | 0 | p = qUnpremultiply(p); |
47 | 0 | constexpr uint mult = 255 / (255 >> Shift); |
48 | 0 | const uint newAlpha = mult * (alpha >> Shift); |
49 | 0 | p = (p & ~0xff000000) | (newAlpha<<24); |
50 | 0 | return qPremultiply(p); |
51 | 0 | } |
52 | | |
53 | | template<unsigned int Shift> |
54 | | inline QRgba64 qRepremultiply(QRgba64 p) |
55 | 0 | { |
56 | 0 | const uint alpha = p.alpha(); |
57 | 0 | if (alpha == 65535 || alpha == 0) |
58 | 0 | return p; |
59 | 0 | p = p.unpremultiplied(); |
60 | 0 | constexpr uint mult = 65535 / (65535 >> Shift); |
61 | 0 | p.setAlpha(mult * (alpha >> Shift)); |
62 | 0 | return p.premultiplied(); |
63 | 0 | } |
64 | | |
65 | | template<> |
66 | | inline uint qConvertArgb32ToA2rgb30<PixelOrderBGR>(QRgb c) |
67 | 0 | { |
68 | 0 | c = qRepremultiply<6>(c); |
69 | 0 | return (c & 0xc0000000) |
70 | 0 | | (((c << 22) & 0x3fc00000) | ((c << 14) & 0x00300000)) |
71 | 0 | | (((c << 4) & 0x000ff000) | ((c >> 4) & 0x00000c00)) |
72 | 0 | | (((c >> 14) & 0x000003fc) | ((c >> 22) & 0x00000003)); |
73 | 0 | } |
74 | | |
75 | | template<> |
76 | | inline uint qConvertArgb32ToA2rgb30<PixelOrderRGB>(QRgb c) |
77 | 0 | { |
78 | 0 | c = qRepremultiply<6>(c); |
79 | 0 | return (c & 0xc0000000) |
80 | 0 | | (((c << 6) & 0x3fc00000) | ((c >> 2) & 0x00300000)) |
81 | 0 | | (((c << 4) & 0x000ff000) | ((c >> 4) & 0x00000c00)) |
82 | 0 | | (((c << 2) & 0x000003fc) | ((c >> 6) & 0x00000003)); |
83 | 0 | } |
84 | | |
85 | | template<> |
86 | | inline uint qConvertRgb32ToRgb30<PixelOrderBGR>(QRgb c) |
87 | 0 | { |
88 | 0 | return 0xc0000000 |
89 | 0 | | (((c << 22) & 0x3fc00000) | ((c << 14) & 0x00300000)) |
90 | 0 | | (((c << 4) & 0x000ff000) | ((c >> 4) & 0x00000c00)) |
91 | 0 | | (((c >> 14) & 0x000003fc) | ((c >> 22) & 0x00000003)); |
92 | 0 | } |
93 | | |
94 | | template<> |
95 | | inline uint qConvertRgb32ToRgb30<PixelOrderRGB>(QRgb c) |
96 | 0 | { |
97 | 0 | return 0xc0000000 |
98 | 0 | | (((c << 6) & 0x3fc00000) | ((c >> 2) & 0x00300000)) |
99 | 0 | | (((c << 4) & 0x000ff000) | ((c >> 4) & 0x00000c00)) |
100 | 0 | | (((c << 2) & 0x000003fc) | ((c >> 6) & 0x00000003)); |
101 | 0 | } |
102 | | |
103 | | template<> |
104 | | inline QRgb qConvertA2rgb30ToArgb32<PixelOrderBGR>(uint c) |
105 | 0 | { |
106 | 0 | uint a = c >> 30; |
107 | 0 | a |= a << 2; |
108 | 0 | a |= a << 4; |
109 | 0 | return (a << 24) |
110 | 0 | | ((c << 14) & 0x00ff0000) |
111 | 0 | | ((c >> 4) & 0x0000ff00) |
112 | 0 | | ((c >> 22) & 0x000000ff); |
113 | 0 | } |
114 | | |
115 | | template<> |
116 | | inline QRgb qConvertA2rgb30ToArgb32<PixelOrderRGB>(uint c) |
117 | 0 | { |
118 | 0 | uint a = c >> 30; |
119 | 0 | a |= a << 2; |
120 | 0 | a |= a << 4; |
121 | 0 | return (a << 24) |
122 | 0 | | ((c >> 6) & 0x00ff0000) |
123 | 0 | | ((c >> 4) & 0x0000ff00) |
124 | 0 | | ((c >> 2) & 0x000000ff); |
125 | 0 | } |
126 | | |
127 | | template<enum QtPixelOrder> inline QRgba64 qConvertA2rgb30ToRgb64(uint rgb); |
128 | | |
129 | | template<> |
130 | | inline QRgba64 qConvertA2rgb30ToRgb64<PixelOrderBGR>(uint rgb) |
131 | 0 | { |
132 | 0 | quint16 alpha = rgb >> 30; |
133 | 0 | quint16 blue = (rgb >> 20) & 0x3ff; |
134 | 0 | quint16 green = (rgb >> 10) & 0x3ff; |
135 | 0 | quint16 red = rgb & 0x3ff; |
136 | | // Expand the range. |
137 | 0 | alpha |= (alpha << 2); |
138 | 0 | alpha |= (alpha << 4); |
139 | 0 | alpha |= (alpha << 8); |
140 | 0 | red = (red << 6) | (red >> 4); |
141 | 0 | green = (green << 6) | (green >> 4); |
142 | 0 | blue = (blue << 6) | (blue >> 4); |
143 | 0 | return qRgba64(red, green, blue, alpha); |
144 | 0 | } |
145 | | |
146 | | template<> |
147 | | inline QRgba64 qConvertA2rgb30ToRgb64<PixelOrderRGB>(uint rgb) |
148 | 0 | { |
149 | 0 | quint16 alpha = rgb >> 30; |
150 | 0 | quint16 red = (rgb >> 20) & 0x3ff; |
151 | 0 | quint16 green = (rgb >> 10) & 0x3ff; |
152 | 0 | quint16 blue = rgb & 0x3ff; |
153 | | // Expand the range. |
154 | 0 | alpha |= (alpha << 2); |
155 | 0 | alpha |= (alpha << 4); |
156 | 0 | alpha |= (alpha << 8); |
157 | 0 | red = (red << 6) | (red >> 4); |
158 | 0 | green = (green << 6) | (green >> 4); |
159 | 0 | blue = (blue << 6) | (blue >> 4); |
160 | 0 | return qRgba64(red, green, blue, alpha); |
161 | 0 | } |
162 | | |
163 | | template<enum QtPixelOrder> inline unsigned int qConvertRgb64ToRgb30(QRgba64); |
164 | | |
165 | | template<> |
166 | | inline unsigned int qConvertRgb64ToRgb30<PixelOrderBGR>(QRgba64 c) |
167 | 0 | { |
168 | 0 | c = qRepremultiply<14>(c); |
169 | 0 | const uint a = c.alpha() >> 14; |
170 | 0 | const uint r = c.red() >> 6; |
171 | 0 | const uint g = c.green() >> 6; |
172 | 0 | const uint b = c.blue() >> 6; |
173 | 0 | return (a << 30) | (b << 20) | (g << 10) | r; |
174 | 0 | } |
175 | | |
176 | | template<> |
177 | | inline unsigned int qConvertRgb64ToRgb30<PixelOrderRGB>(QRgba64 c) |
178 | 0 | { |
179 | 0 | c = qRepremultiply<14>(c); |
180 | 0 | const uint a = c.alpha() >> 14; |
181 | 0 | const uint r = c.red() >> 6; |
182 | 0 | const uint g = c.green() >> 6; |
183 | 0 | const uint b = c.blue() >> 6; |
184 | 0 | return (a << 30) | (r << 20) | (g << 10) | b; |
185 | 0 | } |
186 | | |
187 | | inline constexpr QRgbaFloat16 qConvertRgb64ToRgbaF16(QRgba64 c) |
188 | 0 | { |
189 | 0 | return QRgbaFloat16::fromRgba64(c.red(), c.green(), c.blue(), c.alpha()); |
190 | 0 | } |
191 | | |
192 | | inline constexpr QRgbaFloat32 qConvertRgb64ToRgbaF32(QRgba64 c) |
193 | 0 | { |
194 | 0 | return QRgbaFloat32::fromRgba64(c.red(), c.green(), c.blue(), c.alpha()); |
195 | 0 | } |
196 | | |
197 | | inline uint qRgbSwapRgb30(uint c) |
198 | 0 | { |
199 | 0 | const uint ag = c & 0xc00ffc00; |
200 | 0 | const uint rb = c & 0x3ff003ff; |
201 | 0 | return ag | (rb << 20) | (rb >> 20); |
202 | 0 | } |
203 | | |
204 | | #if Q_BYTE_ORDER == Q_BIG_ENDIAN |
205 | | static inline quint32 RGBA2ARGB(quint32 x) { |
206 | | quint32 rgb = x >> 8; |
207 | | quint32 a = x << 24; |
208 | | return a | rgb; |
209 | | } |
210 | | |
211 | | static inline quint32 ARGB2RGBA(quint32 x) { |
212 | | quint32 rgb = x << 8; |
213 | | quint32 a = x >> 24; |
214 | | return a | rgb; |
215 | | } |
216 | | #else |
217 | 0 | static inline quint32 RGBA2ARGB(quint32 x) { |
218 | | // RGBA8888 is ABGR32 on little endian. |
219 | 0 | quint32 ag = x & 0xff00ff00; |
220 | 0 | quint32 rg = x & 0x00ff00ff; |
221 | 0 | return ag | (rg << 16) | (rg >> 16); |
222 | 0 | } Unexecuted instantiation: qimage.cpp:RGBA2ARGB(unsigned int) Unexecuted instantiation: qimage_conversions.cpp:RGBA2ARGB(unsigned int) Unexecuted instantiation: qcolor.cpp:RGBA2ARGB(unsigned int) Unexecuted instantiation: qimagescale.cpp:RGBA2ARGB(unsigned int) Unexecuted instantiation: qmemrotate.cpp:RGBA2ARGB(unsigned int) Unexecuted instantiation: qpaintengine_raster.cpp:RGBA2ARGB(unsigned int) Unexecuted instantiation: qpainter.cpp:RGBA2ARGB(unsigned int) Unexecuted instantiation: qpixellayout.cpp:RGBA2ARGB(unsigned int) Unexecuted instantiation: qrasterizer.cpp:RGBA2ARGB(unsigned int) Unexecuted instantiation: qdrawhelper_ssse3.cpp:RGBA2ARGB(unsigned int) Unexecuted instantiation: qdrawhelper_sse4.cpp:RGBA2ARGB(unsigned int) Unexecuted instantiation: qimagescale_sse4.cpp:RGBA2ARGB(unsigned int) Unexecuted instantiation: qdrawhelper.cpp:RGBA2ARGB(unsigned int) Unexecuted instantiation: qblendfunctions.cpp:RGBA2ARGB(unsigned int) Unexecuted instantiation: qcompositionfunctions.cpp:RGBA2ARGB(unsigned int) Unexecuted instantiation: qcosmeticstroker.cpp:RGBA2ARGB(unsigned int) Unexecuted instantiation: qdrawhelper_sse2.cpp:RGBA2ARGB(unsigned int) Unexecuted instantiation: qdrawhelper_avx2.cpp:RGBA2ARGB(unsigned int) Unexecuted instantiation: qpixmap_raster.cpp:RGBA2ARGB(unsigned int) |
223 | | |
224 | 0 | static inline quint32 ARGB2RGBA(quint32 x) { |
225 | 0 | return RGBA2ARGB(x); |
226 | 0 | } Unexecuted instantiation: qimage.cpp:ARGB2RGBA(unsigned int) Unexecuted instantiation: qimage_conversions.cpp:ARGB2RGBA(unsigned int) Unexecuted instantiation: qcolor.cpp:ARGB2RGBA(unsigned int) Unexecuted instantiation: qimagescale.cpp:ARGB2RGBA(unsigned int) Unexecuted instantiation: qmemrotate.cpp:ARGB2RGBA(unsigned int) Unexecuted instantiation: qpaintengine_raster.cpp:ARGB2RGBA(unsigned int) Unexecuted instantiation: qpainter.cpp:ARGB2RGBA(unsigned int) Unexecuted instantiation: qpixellayout.cpp:ARGB2RGBA(unsigned int) Unexecuted instantiation: qrasterizer.cpp:ARGB2RGBA(unsigned int) Unexecuted instantiation: qdrawhelper_ssse3.cpp:ARGB2RGBA(unsigned int) Unexecuted instantiation: qdrawhelper_sse4.cpp:ARGB2RGBA(unsigned int) Unexecuted instantiation: qimagescale_sse4.cpp:ARGB2RGBA(unsigned int) Unexecuted instantiation: qdrawhelper.cpp:ARGB2RGBA(unsigned int) Unexecuted instantiation: qblendfunctions.cpp:ARGB2RGBA(unsigned int) Unexecuted instantiation: qcompositionfunctions.cpp:ARGB2RGBA(unsigned int) Unexecuted instantiation: qcosmeticstroker.cpp:ARGB2RGBA(unsigned int) Unexecuted instantiation: qdrawhelper_sse2.cpp:ARGB2RGBA(unsigned int) Unexecuted instantiation: qdrawhelper_avx2.cpp:ARGB2RGBA(unsigned int) Unexecuted instantiation: qpixmap_raster.cpp:ARGB2RGBA(unsigned int) |
227 | | #endif |
228 | | |
229 | | // We manually unalias the variables to make sure the compiler |
230 | | // fully optimizes both aliased and unaliased cases. |
231 | | #define UNALIASED_CONVERSION_LOOP(buffer, src, count, conversion) \ |
232 | 0 | if (src == buffer) { \ |
233 | 0 | for (int i = 0; i < count; ++i) \ |
234 | 0 | buffer[i] = conversion(buffer[i]); \ Unexecuted instantiation: qpixellayout.cpp:storeARGB32FromARGB32PM(unsigned char*, unsigned int const*, int, int, QList<unsigned int> const*, QDitherInfo*)::$_0::operator()(unsigned int) const Unexecuted instantiation: qpixellayout.cpp:storeRGBXFromARGB32PM(unsigned char*, unsigned int const*, int, int, QList<unsigned int> const*, QDitherInfo*)::$_0::operator()(unsigned int) const Unexecuted instantiation: qpixellayout.cpp:storeRGBXFromRGB32(unsigned char*, unsigned int const*, int, int, QList<unsigned int> const*, QDitherInfo*)::$_0::operator()(unsigned int) const Unexecuted instantiation: qt_convertRGBA8888ToARGB32PM(unsigned int*, unsigned int const*, int)::{lambda(unsigned int)#1}::operator()(unsigned int) constUnexecuted instantiation: qpixellayout.cpp:storeRGBA8888FromARGB32PM(unsigned char*, unsigned int const*, int, int, QList<unsigned int> const*, QDitherInfo*)::$_0::operator()(unsigned int) const Unexecuted instantiation: qt_convertCMYK8888ToARGB32PM(unsigned int*, unsigned int const*, int)::{lambda(unsigned int)#1}::operator()(unsigned int) const |
235 | 0 | } else { \ |
236 | 0 | for (int i = 0; i < count; ++i) \ |
237 | 0 | buffer[i] = conversion(src[i]); \ Unexecuted instantiation: qpixellayout.cpp:storeARGB32FromARGB32PM(unsigned char*, unsigned int const*, int, int, QList<unsigned int> const*, QDitherInfo*)::$_1::operator()(unsigned int) const Unexecuted instantiation: qpixellayout.cpp:storeRGBXFromARGB32PM(unsigned char*, unsigned int const*, int, int, QList<unsigned int> const*, QDitherInfo*)::$_1::operator()(unsigned int) const Unexecuted instantiation: qpixellayout.cpp:storeRGBXFromRGB32(unsigned char*, unsigned int const*, int, int, QList<unsigned int> const*, QDitherInfo*)::$_1::operator()(unsigned int) const Unexecuted instantiation: qt_convertRGBA8888ToARGB32PM(unsigned int*, unsigned int const*, int)::{lambda(unsigned int)#2}::operator()(unsigned int) constUnexecuted instantiation: qpixellayout.cpp:storeRGBA8888FromARGB32PM(unsigned char*, unsigned int const*, int, int, QList<unsigned int> const*, QDitherInfo*)::$_1::operator()(unsigned int) const Unexecuted instantiation: qt_convertCMYK8888ToARGB32PM(unsigned int*, unsigned int const*, int)::{lambda(unsigned int)#2}::operator()(unsigned int) const |
238 | 0 | } |
239 | | |
240 | | |
241 | | inline const uint *qt_convertARGB32ToARGB32PM(uint *buffer, const uint *src, int count) |
242 | 0 | { |
243 | 0 | UNALIASED_CONVERSION_LOOP(buffer, src, count, qPremultiply); |
244 | 0 | return buffer; |
245 | 0 | } |
246 | | |
247 | | inline const uint *qt_convertRGBA8888ToARGB32PM(uint *buffer, const uint *src, int count) |
248 | 0 | { |
249 | 0 | UNALIASED_CONVERSION_LOOP(buffer, src, count, [](uint s) { return qPremultiply(RGBA2ARGB(s));}); |
250 | 0 | return buffer; |
251 | 0 | } |
252 | | |
253 | | template<bool RGBA> void qt_convertRGBA64ToARGB32(uint *dst, const QRgba64 *src, int count); |
254 | | |
255 | | struct QDitherInfo { |
256 | | int x; |
257 | | int y; |
258 | | }; |
259 | | |
260 | | typedef const uint *(QT_FASTCALL *FetchAndConvertPixelsFunc)(uint *buffer, const uchar *src, |
261 | | int index, int count, |
262 | | const QList<QRgb> *clut, |
263 | | QDitherInfo *dither); |
264 | | typedef void(QT_FASTCALL *ConvertAndStorePixelsFunc)(uchar *dest, const uint *src, int index, |
265 | | int count, const QList<QRgb> *clut, |
266 | | QDitherInfo *dither); |
267 | | |
268 | | typedef const QRgba64 *(QT_FASTCALL *FetchAndConvertPixelsFunc64)(QRgba64 *buffer, const uchar *src, |
269 | | int index, int count, |
270 | | const QList<QRgb> *clut, |
271 | | QDitherInfo *dither); |
272 | | typedef void(QT_FASTCALL *ConvertAndStorePixelsFunc64)(uchar *dest, const QRgba64 *src, int index, |
273 | | int count, const QList<QRgb> *clut, |
274 | | QDitherInfo *dither); |
275 | | |
276 | | typedef const QRgbaFloat32 *(QT_FASTCALL *FetchAndConvertPixelsFuncFP)(QRgbaFloat32 *buffer, const uchar *src, int index, int count, |
277 | | const QList<QRgb> *clut, QDitherInfo *dither); |
278 | | typedef void (QT_FASTCALL *ConvertAndStorePixelsFuncFP)(uchar *dest, const QRgbaFloat32 *src, int index, int count, |
279 | | const QList<QRgb> *clut, QDitherInfo *dither); |
280 | | typedef void (QT_FASTCALL *ConvertFunc)(uint *buffer, int count, const QList<QRgb> *clut); |
281 | | typedef void (QT_FASTCALL *Convert64Func)(QRgba64 *buffer, int count); |
282 | | typedef void (QT_FASTCALL *ConvertFPFunc)(QRgbaFloat32 *buffer, int count); |
283 | | typedef void (QT_FASTCALL *Convert64ToFPFunc)(QRgbaFloat32 *buffer, const quint64 *src, int count); |
284 | | |
285 | | typedef const QRgba64 *(QT_FASTCALL *ConvertTo64Func)(QRgba64 *buffer, const uint *src, int count, |
286 | | const QList<QRgb> *clut, QDitherInfo *dither); |
287 | | typedef const QRgbaFloat32 *(QT_FASTCALL *ConvertToFPFunc)(QRgbaFloat32 *buffer, const uint *src, int count, |
288 | | const QList<QRgb> *clut, QDitherInfo *dither); |
289 | | typedef void (QT_FASTCALL *RbSwapFunc)(uchar *dst, const uchar *src, int count); |
290 | | |
291 | | typedef void (*MemRotateFunc)(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl); |
292 | | |
293 | | struct QPixelLayout |
294 | | { |
295 | | // Bits per pixel |
296 | | enum BPP { |
297 | | BPPNone, |
298 | | BPP1MSB, |
299 | | BPP1LSB, |
300 | | BPP8, |
301 | | BPP16, |
302 | | BPP24, |
303 | | BPP32, |
304 | | BPP64, |
305 | | BPP16FPx4, |
306 | | BPP32FPx4, |
307 | | BPPCount |
308 | | }; |
309 | | |
310 | | bool hasAlphaChannel; |
311 | | bool premultiplied; |
312 | | BPP bpp; |
313 | | RbSwapFunc rbSwap; |
314 | | ConvertFunc convertToARGB32PM; |
315 | | ConvertTo64Func convertToRGBA64PM; |
316 | | FetchAndConvertPixelsFunc fetchToARGB32PM; |
317 | | FetchAndConvertPixelsFunc64 fetchToRGBA64PM; |
318 | | ConvertAndStorePixelsFunc storeFromARGB32PM; |
319 | | ConvertAndStorePixelsFunc storeFromRGB32; |
320 | | }; |
321 | | |
322 | | extern ConvertAndStorePixelsFunc64 qStoreFromRGBA64PM[QImage::NImageFormats]; |
323 | | |
324 | | #if QT_CONFIG(raster_fp) |
325 | | extern ConvertToFPFunc qConvertToRGBA32F[]; |
326 | | extern FetchAndConvertPixelsFuncFP qFetchToRGBA32F[]; |
327 | | extern ConvertAndStorePixelsFuncFP qStoreFromRGBA32F[]; |
328 | | #endif |
329 | | |
330 | | extern QPixelLayout qPixelLayouts[]; |
331 | | |
332 | | extern MemRotateFunc qMemRotateFunctions[QPixelLayout::BPPCount][3]; |
333 | | |
334 | | QT_END_NAMESPACE |
335 | | |
336 | | #endif // QPIXELLAYOUT_P_H |