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