1/****************************************************************************
2**
3** Copyright (C) 2020 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtGui module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#ifndef QPIXELLAYOUT_P_H
41#define QPIXELLAYOUT_P_H
42
43//
44// W A R N I N G
45// -------------
46//
47// This file is not part of the Qt API. It exists purely as an
48// implementation detail. This header file may change from version to
49// version without notice, or even be removed.
50//
51// We mean it.
52//
53
54#include <QtCore/qlist.h>
55#include <QtGui/qimage.h>
56#include <QtGui/qrgba64.h>
57#include <QtGui/qrgbafloat.h>
58
59QT_BEGIN_NAMESPACE
60
61enum QtPixelOrder {
62 PixelOrderRGB,
63 PixelOrderBGR
64};
65
66template<enum QtPixelOrder> inline uint qConvertArgb32ToA2rgb30(QRgb);
67
68template<enum QtPixelOrder> inline uint qConvertRgb32ToRgb30(QRgb);
69
70template<enum QtPixelOrder> inline QRgb qConvertA2rgb30ToArgb32(uint c);
71
72// A combined unpremultiply and premultiply with new simplified alpha.
73// Needed when alpha loses precision relative to other colors during conversion (ARGB32 -> A2RGB30).
74template<unsigned int Shift>
75inline QRgb qRepremultiply(QRgb p)
76{
77 const uint alpha = qAlpha(p);
78 if (alpha == 255 || alpha == 0)
79 return p;
80 p = qUnpremultiply(p);
81 constexpr uint mult = 255 / (255 >> Shift);
82 const uint newAlpha = mult * (alpha >> Shift);
83 p = (p & ~0xff000000) | (newAlpha<<24);
84 return qPremultiply(p);
85}
86
87template<unsigned int Shift>
88inline QRgba64 qRepremultiply(QRgba64 p)
89{
90 const uint alpha = p.alpha();
91 if (alpha == 65535 || alpha == 0)
92 return p;
93 p = p.unpremultiplied();
94 constexpr uint mult = 65535 / (65535 >> Shift);
95 p.setAlpha(mult * (alpha >> Shift));
96 return p.premultiplied();
97}
98
99template<>
100inline uint qConvertArgb32ToA2rgb30<PixelOrderBGR>(QRgb c)
101{
102 c = qRepremultiply<6>(c);
103 return (c & 0xc0000000)
104 | (((c << 22) & 0x3fc00000) | ((c << 14) & 0x00300000))
105 | (((c << 4) & 0x000ff000) | ((c >> 4) & 0x00000c00))
106 | (((c >> 14) & 0x000003fc) | ((c >> 22) & 0x00000003));
107}
108
109template<>
110inline uint qConvertArgb32ToA2rgb30<PixelOrderRGB>(QRgb c)
111{
112 c = qRepremultiply<6>(c);
113 return (c & 0xc0000000)
114 | (((c << 6) & 0x3fc00000) | ((c >> 2) & 0x00300000))
115 | (((c << 4) & 0x000ff000) | ((c >> 4) & 0x00000c00))
116 | (((c << 2) & 0x000003fc) | ((c >> 6) & 0x00000003));
117}
118
119template<>
120inline uint qConvertRgb32ToRgb30<PixelOrderBGR>(QRgb c)
121{
122 return 0xc0000000
123 | (((c << 22) & 0x3fc00000) | ((c << 14) & 0x00300000))
124 | (((c << 4) & 0x000ff000) | ((c >> 4) & 0x00000c00))
125 | (((c >> 14) & 0x000003fc) | ((c >> 22) & 0x00000003));
126}
127
128template<>
129inline uint qConvertRgb32ToRgb30<PixelOrderRGB>(QRgb c)
130{
131 return 0xc0000000
132 | (((c << 6) & 0x3fc00000) | ((c >> 2) & 0x00300000))
133 | (((c << 4) & 0x000ff000) | ((c >> 4) & 0x00000c00))
134 | (((c << 2) & 0x000003fc) | ((c >> 6) & 0x00000003));
135}
136
137template<>
138inline QRgb qConvertA2rgb30ToArgb32<PixelOrderBGR>(uint c)
139{
140 uint a = c >> 30;
141 a |= a << 2;
142 a |= a << 4;
143 return (a << 24)
144 | ((c << 14) & 0x00ff0000)
145 | ((c >> 4) & 0x0000ff00)
146 | ((c >> 22) & 0x000000ff);
147}
148
149template<>
150inline QRgb qConvertA2rgb30ToArgb32<PixelOrderRGB>(uint c)
151{
152 uint a = c >> 30;
153 a |= a << 2;
154 a |= a << 4;
155 return (a << 24)
156 | ((c >> 6) & 0x00ff0000)
157 | ((c >> 4) & 0x0000ff00)
158 | ((c >> 2) & 0x000000ff);
159}
160
161template<enum QtPixelOrder> inline QRgba64 qConvertA2rgb30ToRgb64(uint rgb);
162
163template<>
164inline QRgba64 qConvertA2rgb30ToRgb64<PixelOrderBGR>(uint rgb)
165{
166 quint16 alpha = rgb >> 30;
167 quint16 blue = (rgb >> 20) & 0x3ff;
168 quint16 green = (rgb >> 10) & 0x3ff;
169 quint16 red = rgb & 0x3ff;
170 // Expand the range.
171 alpha |= (alpha << 2);
172 alpha |= (alpha << 4);
173 alpha |= (alpha << 8);
174 red = (red << 6) | (red >> 4);
175 green = (green << 6) | (green >> 4);
176 blue = (blue << 6) | (blue >> 4);
177 return qRgba64(red, green, blue, alpha);
178}
179
180template<>
181inline QRgba64 qConvertA2rgb30ToRgb64<PixelOrderRGB>(uint rgb)
182{
183 quint16 alpha = rgb >> 30;
184 quint16 red = (rgb >> 20) & 0x3ff;
185 quint16 green = (rgb >> 10) & 0x3ff;
186 quint16 blue = rgb & 0x3ff;
187 // Expand the range.
188 alpha |= (alpha << 2);
189 alpha |= (alpha << 4);
190 alpha |= (alpha << 8);
191 red = (red << 6) | (red >> 4);
192 green = (green << 6) | (green >> 4);
193 blue = (blue << 6) | (blue >> 4);
194 return qRgba64(red, green, blue, alpha);
195}
196
197template<enum QtPixelOrder> inline unsigned int qConvertRgb64ToRgb30(QRgba64);
198
199template<>
200inline unsigned int qConvertRgb64ToRgb30<PixelOrderBGR>(QRgba64 c)
201{
202 c = qRepremultiply<14>(c);
203 const uint a = c.alpha() >> 14;
204 const uint r = c.red() >> 6;
205 const uint g = c.green() >> 6;
206 const uint b = c.blue() >> 6;
207 return (a << 30) | (b << 20) | (g << 10) | r;
208}
209
210template<>
211inline unsigned int qConvertRgb64ToRgb30<PixelOrderRGB>(QRgba64 c)
212{
213 c = qRepremultiply<14>(c);
214 const uint a = c.alpha() >> 14;
215 const uint r = c.red() >> 6;
216 const uint g = c.green() >> 6;
217 const uint b = c.blue() >> 6;
218 return (a << 30) | (r << 20) | (g << 10) | b;
219}
220
221inline constexpr QRgbaFloat16 qConvertRgb64ToRgbaF16(QRgba64 c)
222{
223 return QRgbaFloat16::fromRgba64(c.red(), c.green(), c.blue(), c.alpha());
224}
225
226inline constexpr QRgbaFloat32 qConvertRgb64ToRgbaF32(QRgba64 c)
227{
228 return QRgbaFloat32::fromRgba64(c.red(), c.green(), c.blue(), c.alpha());
229}
230
231inline uint qRgbSwapRgb30(uint c)
232{
233 const uint ag = c & 0xc00ffc00;
234 const uint rb = c & 0x3ff003ff;
235 return ag | (rb << 20) | (rb >> 20);
236}
237
238#if Q_BYTE_ORDER == Q_BIG_ENDIAN
239static inline quint32 RGBA2ARGB(quint32 x) {
240 quint32 rgb = x >> 8;
241 quint32 a = x << 24;
242 return a | rgb;
243}
244
245static inline quint32 ARGB2RGBA(quint32 x) {
246 quint32 rgb = x << 8;
247 quint32 a = x >> 24;
248 return a | rgb;
249}
250#else
251static inline quint32 RGBA2ARGB(quint32 x) {
252 // RGBA8888 is ABGR32 on little endian.
253 quint32 ag = x & 0xff00ff00;
254 quint32 rg = x & 0x00ff00ff;
255 return ag | (rg << 16) | (rg >> 16);
256}
257
258static inline quint32 ARGB2RGBA(quint32 x) {
259 return RGBA2ARGB(x);
260}
261#endif
262
263// We manually unalias the variables to make sure the compiler
264// fully optimizes both aliased and unaliased cases.
265#define UNALIASED_CONVERSION_LOOP(buffer, src, count, conversion) \
266 if (src == buffer) { \
267 for (int i = 0; i < count; ++i) \
268 buffer[i] = conversion(buffer[i]); \
269 } else { \
270 for (int i = 0; i < count; ++i) \
271 buffer[i] = conversion(src[i]); \
272 }
273
274
275inline const uint *qt_convertARGB32ToARGB32PM(uint *buffer, const uint *src, int count)
276{
277 UNALIASED_CONVERSION_LOOP(buffer, src, count, qPremultiply);
278 return buffer;
279}
280
281inline const uint *qt_convertRGBA8888ToARGB32PM(uint *buffer, const uint *src, int count)
282{
283 UNALIASED_CONVERSION_LOOP(buffer, src, count, [](uint s) { return qPremultiply(RGBA2ARGB(s));});
284 return buffer;
285}
286
287template<bool RGBA> void qt_convertRGBA64ToARGB32(uint *dst, const QRgba64 *src, int count);
288
289struct QDitherInfo {
290 int x;
291 int y;
292};
293
294typedef const uint *(QT_FASTCALL *FetchAndConvertPixelsFunc)(uint *buffer, const uchar *src,
295 int index, int count,
296 const QList<QRgb> *clut,
297 QDitherInfo *dither);
298typedef void(QT_FASTCALL *ConvertAndStorePixelsFunc)(uchar *dest, const uint *src, int index,
299 int count, const QList<QRgb> *clut,
300 QDitherInfo *dither);
301
302typedef const QRgba64 *(QT_FASTCALL *FetchAndConvertPixelsFunc64)(QRgba64 *buffer, const uchar *src,
303 int index, int count,
304 const QList<QRgb> *clut,
305 QDitherInfo *dither);
306typedef void(QT_FASTCALL *ConvertAndStorePixelsFunc64)(uchar *dest, const QRgba64 *src, int index,
307 int count, const QList<QRgb> *clut,
308 QDitherInfo *dither);
309
310typedef const QRgbaFloat32 *(QT_FASTCALL *FetchAndConvertPixelsFuncFP)(QRgbaFloat32 *buffer, const uchar *src, int index, int count,
311 const QList<QRgb> *clut, QDitherInfo *dither);
312typedef void (QT_FASTCALL *ConvertAndStorePixelsFuncFP)(uchar *dest, const QRgbaFloat32 *src, int index, int count,
313 const QList<QRgb> *clut, QDitherInfo *dither);
314typedef void (QT_FASTCALL *ConvertFunc)(uint *buffer, int count, const QList<QRgb> *clut);
315typedef void (QT_FASTCALL *Convert64Func)(QRgba64 *buffer, int count);
316typedef void (QT_FASTCALL *ConvertFPFunc)(QRgbaFloat32 *buffer, int count);
317typedef void (QT_FASTCALL *Convert64ToFPFunc)(QRgbaFloat32 *buffer, const quint64 *src, int count);
318
319typedef const QRgba64 *(QT_FASTCALL *ConvertTo64Func)(QRgba64 *buffer, const uint *src, int count,
320 const QList<QRgb> *clut, QDitherInfo *dither);
321typedef const QRgbaFloat32 *(QT_FASTCALL *ConvertToFPFunc)(QRgbaFloat32 *buffer, const uint *src, int count,
322 const QList<QRgb> *clut, QDitherInfo *dither);
323typedef void (QT_FASTCALL *RbSwapFunc)(uchar *dst, const uchar *src, int count);
324
325typedef void (*MemRotateFunc)(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl);
326
327struct QPixelLayout
328{
329 // Bits per pixel
330 enum BPP {
331 BPPNone,
332 BPP1MSB,
333 BPP1LSB,
334 BPP8,
335 BPP16,
336 BPP24,
337 BPP32,
338 BPP64,
339 BPP16FPx4,
340 BPP32FPx4,
341 BPPCount
342 };
343
344 bool hasAlphaChannel;
345 bool premultiplied;
346 BPP bpp;
347 RbSwapFunc rbSwap;
348 ConvertFunc convertToARGB32PM;
349 ConvertTo64Func convertToRGBA64PM;
350 FetchAndConvertPixelsFunc fetchToARGB32PM;
351 FetchAndConvertPixelsFunc64 fetchToRGBA64PM;
352 ConvertAndStorePixelsFunc storeFromARGB32PM;
353 ConvertAndStorePixelsFunc storeFromRGB32;
354};
355
356extern ConvertAndStorePixelsFunc64 qStoreFromRGBA64PM[QImage::NImageFormats];
357
358#if QT_CONFIG(raster_fp)
359extern ConvertToFPFunc qConvertToRGBA32F[QImage::NImageFormats];
360extern FetchAndConvertPixelsFuncFP qFetchToRGBA32F[QImage::NImageFormats];
361extern ConvertAndStorePixelsFuncFP qStoreFromRGBA32F[QImage::NImageFormats];
362#endif
363
364extern QPixelLayout qPixelLayouts[QImage::NImageFormats];
365
366extern MemRotateFunc qMemRotateFunctions[QPixelLayout::BPPCount][3];
367
368QT_END_NAMESPACE
369
370#endif // QPIXELLAYOUT_P_H
371

source code of qtbase/src/gui/painting/qpixellayout_p.h