Coverage Report

Created: 2026-03-31 07:41

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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) const
Unexecuted 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) const
Unexecuted 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