Coverage Report

Created: 2026-10-14 06:52

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/qtbase/src/gui/image/qpixmap_raster.cpp
Line
Count
Source
1
// Copyright (C) 2016 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
#include "qpixmap.h"
6
7
#include <private/qfont_p.h>
8
9
#include "qpixmap_raster_p.h"
10
#include "qimage_p.h"
11
#include "qpaintengine.h"
12
13
#include "qbitmap.h"
14
#include "qimage.h"
15
#include <QBuffer>
16
#include <QImageReader>
17
#include <QGuiApplication>
18
#include <QScreen>
19
#include <private/qsimd_p.h>
20
#include <private/qdrawhelper_p.h>
21
#include <qpa/qplatformscreen.h>
22
23
QT_BEGIN_NAMESPACE
24
25
QPixmap qt_toRasterPixmap(const QImage &image)
26
0
{
27
0
    QPlatformPixmap *data =
28
0
        new QRasterPlatformPixmap(image.depth() == 1
29
0
                           ? QPlatformPixmap::BitmapType
30
0
                           : QPlatformPixmap::PixmapType);
31
32
0
    data->fromImage(image, Qt::AutoColor);
33
34
0
    return QPixmap(data);
35
0
}
36
37
QPixmap qt_toRasterPixmap(const QPixmap &pixmap)
38
0
{
39
0
    if (pixmap.isNull())
40
0
        return QPixmap();
41
42
0
    if (QPixmap(pixmap).data_ptr()->classId() == QPlatformPixmap::RasterClass)
43
0
        return pixmap;
44
45
0
    return qt_toRasterPixmap(pixmap.toImage());
46
0
}
47
48
QRasterPlatformPixmap::QRasterPlatformPixmap(PixelType type)
49
0
    : QPlatformPixmap(type, RasterClass)
50
0
{
51
0
}
52
53
QRasterPlatformPixmap::~QRasterPlatformPixmap()
54
0
{
55
0
}
56
57
QImage::Format QRasterPlatformPixmap::systemNativeFormat()
58
0
{
59
0
    if (!QGuiApplication::primaryScreen())
60
0
        return QImage::Format_RGB32;
61
0
    return QGuiApplication::primaryScreen()->handle()->format();
62
0
}
63
64
QPlatformPixmap *QRasterPlatformPixmap::createCompatiblePlatformPixmap() const
65
0
{
66
0
    return new QRasterPlatformPixmap(pixelType());
67
0
}
68
69
void QRasterPlatformPixmap::resize(int width, int height)
70
0
{
71
0
    QImage::Format format;
72
0
    if (pixelType() == BitmapType)
73
0
        format = QImage::Format_MonoLSB;
74
0
    else
75
0
        format = systemNativeFormat();
76
77
0
    image = QImage(width, height, format);
78
0
    w = width;
79
0
    h = height;
80
0
    d = image.depth();
81
0
    is_null = (w <= 0 || h <= 0);
82
83
0
    if (pixelType() == BitmapType && !image.isNull()) {
84
0
        image.setColorCount(2);
85
0
        image.setColor(0, QColor(Qt::color0).rgba());
86
0
        image.setColor(1, QColor(Qt::color1).rgba());
87
0
    }
88
89
0
    setSerialNumber(image.cacheKey() >> 32);
90
0
}
91
92
bool QRasterPlatformPixmap::fromData(const uchar *buffer, uint len, const char *format,
93
                      Qt::ImageConversionFlags flags)
94
0
{
95
0
    QByteArray a = QByteArray::fromRawData(reinterpret_cast<const char *>(buffer), len);
96
0
    QBuffer b(&a);
97
0
    b.open(QIODevice::ReadOnly);
98
0
    QImage image = QImageReader(&b, format).read();
99
0
    if (image.isNull())
100
0
        return false;
101
102
0
    createPixmapForImage(std::move(image), flags);
103
0
    return !isNull();
104
0
}
105
106
void QRasterPlatformPixmap::fromImage(const QImage &sourceImage,
107
                                  Qt::ImageConversionFlags flags)
108
0
{
109
0
    QImage image = sourceImage;
110
0
    createPixmapForImage(std::move(image), flags);
111
0
}
112
113
void QRasterPlatformPixmap::fromImageInPlace(QImage &sourceImage,
114
                                             Qt::ImageConversionFlags flags)
115
0
{
116
0
    createPixmapForImage(std::move(sourceImage), flags);
117
0
}
118
119
void QRasterPlatformPixmap::fromImageReader(QImageReader *imageReader,
120
                                        Qt::ImageConversionFlags flags)
121
0
{
122
0
    Q_UNUSED(flags);
123
0
    QImage image = imageReader->read();
124
0
    if (image.isNull())
125
0
        return;
126
127
0
    createPixmapForImage(std::move(image), flags);
128
0
}
129
130
// from qbackingstore.cpp
131
extern void qt_scrollRectInImage(QImage &img, const QRect &rect, const QPoint &offset);
132
133
void QRasterPlatformPixmap::copy(const QPlatformPixmap *data, const QRect &rect)
134
0
{
135
0
    fromImage(data->toImage(rect).copy(), Qt::NoOpaqueDetection);
136
0
}
137
138
bool QRasterPlatformPixmap::scroll(int dx, int dy, const QRect &rect)
139
0
{
140
0
    if (!image.isNull())
141
0
        qt_scrollRectInImage(image, rect, QPoint(dx, dy));
142
0
    return true;
143
0
}
144
145
void QRasterPlatformPixmap::fill(const QColor &color)
146
0
{
147
0
    uint pixel;
148
149
0
    if (image.depth() == 1) {
150
0
        int gray = qGray(color.rgba());
151
        // Pick the best approximate color in the image's colortable.
152
0
        if (qAbs(qGray(image.color(0)) - gray) < qAbs(qGray(image.color(1)) - gray))
153
0
            pixel = 0;
154
0
        else
155
0
            pixel = 1;
156
0
    } else if (image.depth() >= 15) {
157
0
        int alpha = color.alpha();
158
0
        if (alpha != 255) {
159
0
            if (!image.hasAlphaChannel()) {
160
0
                QImage::Format toFormat = qt_alphaVersionForPainting(image.format());
161
0
                if (!image.reinterpretAsFormat(toFormat))
162
0
                    image = QImage(image.width(), image.height(), toFormat);
163
0
            }
164
0
        }
165
0
        image.fill(color);
166
0
        return;
167
0
    } else if (image.format() == QImage::Format_Alpha8) {
168
0
        pixel = qAlpha(color.rgba());
169
0
    } else if (image.format() == QImage::Format_Grayscale8) {
170
0
        pixel = qGray(color.rgba());
171
0
    } else if (image.format() == QImage::Format_Grayscale16) {
172
0
        QRgba64 c = color.rgba64();
173
0
        pixel = qGray(c.red(), c.green(), c.blue());
174
0
    } else
175
0
    {
176
0
        pixel = 0;
177
        // ### what about 8 bit indexed?
178
0
    }
179
180
0
    image.fill(pixel);
181
0
}
182
183
bool QRasterPlatformPixmap::hasAlphaChannel() const
184
0
{
185
0
    return image.hasAlphaChannel();
186
0
}
187
188
QImage QRasterPlatformPixmap::toImage() const
189
0
{
190
0
    if (!image.isNull()) {
191
0
        QImageData *data = const_cast<QImage &>(image).data_ptr();
192
0
        if (data->paintEngine && data->paintEngine->isActive()
193
0
            && data->paintEngine->paintDevice() == &image)
194
0
        {
195
0
            return image.copy();
196
0
        }
197
0
    }
198
199
0
    return image;
200
0
}
201
202
QImage QRasterPlatformPixmap::toImage(const QRect &rect) const
203
0
{
204
0
    if (rect.isNull())
205
0
        return image;
206
207
0
    QRect clipped = rect.intersected(QRect(0, 0, w, h));
208
0
    const uint du = uint(d);
209
0
    if ((du % 8 == 0) && (((uint(clipped.x()) * du)) % 32 == 0)) {
210
0
        QImage newImage(image.scanLine(clipped.y()) + clipped.x() * (du / 8),
211
0
                      clipped.width(), clipped.height(),
212
0
                      image.bytesPerLine(), image.format());
213
0
        newImage.setDevicePixelRatio(image.devicePixelRatio());
214
0
        return newImage;
215
0
    } else {
216
0
        return image.copy(clipped);
217
0
    }
218
0
}
219
220
QPaintEngine* QRasterPlatformPixmap::paintEngine() const
221
0
{
222
0
    return image.paintEngine();
223
0
}
224
225
int QRasterPlatformPixmap::metric(QPaintDevice::PaintDeviceMetric metric) const
226
0
{
227
0
    QImageData *d = image.d;
228
0
    if (!d)
229
0
        return 0;
230
231
    // override the image dpi with the screen dpi when rendering to a pixmap
232
0
    switch (metric) {
233
0
    case QPaintDevice::PdmWidth:
234
0
        return w;
235
0
    case QPaintDevice::PdmHeight:
236
0
        return h;
237
0
    case QPaintDevice::PdmWidthMM:
238
0
        return qRound(d->width * 25.4 / qt_defaultDpiX());
239
0
    case QPaintDevice::PdmHeightMM:
240
0
        return qRound(d->height * 25.4 / qt_defaultDpiY());
241
0
    case QPaintDevice::PdmNumColors:
242
0
        return d->colortable.size();
243
0
    case QPaintDevice::PdmDepth:
244
0
        return this->d;
245
0
    case QPaintDevice::PdmDpiX:
246
0
        return qt_defaultDpiX();
247
0
    case QPaintDevice::PdmPhysicalDpiX:
248
0
        return qt_defaultDpiX();
249
0
    case QPaintDevice::PdmDpiY:
250
0
        return qt_defaultDpiY();
251
0
    case QPaintDevice::PdmPhysicalDpiY:
252
0
        return qt_defaultDpiY();
253
0
    case QPaintDevice::PdmDevicePixelRatio:
254
0
        return image.devicePixelRatio();
255
0
    case QPaintDevice::PdmDevicePixelRatioScaled:
256
0
        return image.devicePixelRatio() * QPaintDevice::devicePixelRatioFScale();
257
0
    case QPaintDevice::PdmDevicePixelRatioF_EncodedA:
258
0
        Q_FALLTHROUGH();
259
0
    case QPaintDevice::PdmDevicePixelRatioF_EncodedB:
260
0
        return QPaintDevice::encodeMetricF(metric, image.devicePixelRatio());
261
262
0
    default:
263
0
        qWarning("QRasterPlatformPixmap::metric(): Unhandled metric type %d", metric);
264
0
        break;
265
0
    }
266
267
0
    return 0;
268
0
}
269
270
void QRasterPlatformPixmap::createPixmapForImage(QImage sourceImage, Qt::ImageConversionFlags flags)
271
0
{
272
0
    QImage::Format format;
273
0
    if (flags & Qt::NoFormatConversion)
274
0
        format = sourceImage.format();
275
0
    else
276
0
    if (pixelType() == BitmapType) {
277
0
        format = QImage::Format_MonoLSB;
278
0
    } else {
279
0
        if (sourceImage.depth() == 1) {
280
0
            format = sourceImage.hasAlphaChannel()
281
0
                    ? QImage::Format_ARGB32_Premultiplied
282
0
                    : QImage::Format_RGB32;
283
0
        } else {
284
0
            QImage::Format nativeFormat = systemNativeFormat();
285
0
            QImage::Format opaqueFormat = qt_opaqueVersionForPainting(nativeFormat);
286
0
            QImage::Format alphaFormat = qt_alphaVersionForPainting(nativeFormat);
287
288
0
            if (!sourceImage.hasAlphaChannel()) {
289
0
                format = opaqueFormat;
290
0
            } else if ((flags & Qt::NoOpaqueDetection) == 0
291
0
                       && !sourceImage.data_ptr()->checkForAlphaPixels())
292
0
            {
293
0
                format = opaqueFormat;
294
0
            } else {
295
0
                format = alphaFormat;
296
0
            }
297
0
        }
298
0
    }
299
300
    // image has alpha format but is really opaque, so try to do a
301
    // more efficient conversion
302
0
    if (format == QImage::Format_RGB32 && (sourceImage.format() == QImage::Format_ARGB32
303
0
        || sourceImage.format() == QImage::Format_ARGB32_Premultiplied))
304
0
    {
305
0
        image = std::move(sourceImage);
306
0
        image.reinterpretAsFormat(QImage::Format_RGB32);
307
0
    } else {
308
0
        image = std::move(sourceImage).convertToFormat(format, flags);
309
0
    }
310
311
0
    if (image.d) {
312
0
        w = image.d->width;
313
0
        h = image.d->height;
314
0
        d = image.d->depth;
315
0
    } else {
316
0
        w = h = d = 0;
317
0
    }
318
0
    is_null = (w <= 0 || h <= 0);
319
320
    //ensure the pixmap and the image resulting from toImage() have the same cacheKey();
321
0
    setSerialNumber(image.cacheKey() >> 32);
322
0
    if (image.d)
323
0
        setDetachNumber(image.d->detach_no);
324
0
}
325
326
QImage* QRasterPlatformPixmap::buffer()
327
0
{
328
0
    return &image;
329
0
}
330
331
qreal QRasterPlatformPixmap::devicePixelRatio() const
332
0
{
333
0
    return image.devicePixelRatio();
334
0
}
335
336
void QRasterPlatformPixmap::setDevicePixelRatio(qreal scaleFactor)
337
0
{
338
0
    image.setDevicePixelRatio(scaleFactor);
339
0
}
340
341
QT_END_NAMESPACE