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
qplatformpixmap.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
5#include <qpa/qplatformintegration.h>
6#include <QtCore/qbuffer.h>
7#include <QtGui/qbitmap.h>
8#include <QtGui/qimagereader.h>
9#include <private/qguiapplication_p.h>
10#include <private/qimagepixmapcleanuphooks_p.h>
11
13
14/*!
15 \class QPlatformPixmap
16 \since 5.0
17 \internal
18 \preliminary
19 \ingroup qpa
20
21 \brief The QPlatformPixmap class provides an abstraction for native pixmaps.
22 */
23QPlatformPixmap *QPlatformPixmap::create(int w, int h, PixelType type)
24{
25 if (Q_UNLIKELY(!QGuiApplicationPrivate::platformIntegration()))
26 qFatal("QPlatformPixmap: QGuiApplication required");
27
28 QPlatformPixmap *data = QGuiApplicationPrivate::platformIntegration()->createPlatformPixmap(static_cast<QPlatformPixmap::PixelType>(type));
29 data->resize(w, h);
30 return data;
31}
32
33
34QPlatformPixmap::QPlatformPixmap(PixelType pixelType, int objectId)
35 : w(0),
36 h(0),
37 d(0),
38 is_null(true),
39 detach_no(0),
40 type(pixelType),
41 id(objectId),
42 ser_no(0),
43 is_cached(false)
44{
45}
46
47QPlatformPixmap::~QPlatformPixmap()
48{
49 // Sometimes the pixmap cleanup hooks will be called from derived classes, which will
50 // then set is_cached to false. For example, on X11 Qt GUI needs to delete the GLXPixmap
51 // or EGL Pixmap Surface for a given pixmap _before_ the native X11 pixmap is deleted,
52 // otherwise some drivers will leak the GL surface. In this case, QX11PlatformPixmap will
53 // call the cleanup hooks itself before deleting the native pixmap and set is_cached to
54 // false.
55 if (is_cached) {
56 QImagePixmapCleanupHooks::executePlatformPixmapDestructionHooks(this);
57 is_cached = false;
58 }
59}
60
61QPlatformPixmap *QPlatformPixmap::createCompatiblePlatformPixmap() const
62{
63 QPlatformPixmap *d = QGuiApplicationPrivate::platformIntegration()->createPlatformPixmap(pixelType());
64 return d;
65}
66
67static QImage makeBitmapCompliantIfNeeded(QPlatformPixmap *d, QImage image, Qt::ImageConversionFlags flags)
68{
69 if (d->pixelType() == QPlatformPixmap::BitmapType) {
70 QImage img = std::move(image).convertToFormat(QImage::Format_MonoLSB, flags);
71
72 // make sure image.color(0) == Qt::color0 (white)
73 // and image.color(1) == Qt::color1 (black)
74 const QRgb c0 = QColor(Qt::black).rgb();
75 const QRgb c1 = QColor(Qt::white).rgb();
76 if (img.color(0) == c0 && img.color(1) == c1) {
77 img.invertPixels();
78 img.setColor(0, c1);
79 img.setColor(1, c0);
80 }
81 return img;
82 }
83
84 return image;
85}
86
87void QPlatformPixmap::fromImageReader(QImageReader *imageReader,
88 Qt::ImageConversionFlags flags)
89{
90 const QImage image = imageReader->read();
91 fromImage(image, flags);
92}
93
94bool QPlatformPixmap::fromFile(const QString &fileName, const char *format,
95 Qt::ImageConversionFlags flags)
96{
97 QImage image = QImageReader(fileName, format).read();
98 if (image.isNull())
99 return false;
100 fromImage(makeBitmapCompliantIfNeeded(this, std::move(image), flags), flags);
101 return !isNull();
102}
103
104bool QPlatformPixmap::fromData(const uchar *buf, uint len, const char *format, Qt::ImageConversionFlags flags)
105{
106 QByteArray a = QByteArray::fromRawData(reinterpret_cast<const char *>(buf), len);
107 QBuffer b(&a);
108 b.open(QIODevice::ReadOnly);
109 QImage image = QImageReader(&b, format).read();
110 if (image.isNull())
111 return false;
112 fromImage(makeBitmapCompliantIfNeeded(this, std::move(image), flags), flags);
113 return !isNull();
114}
115
116void QPlatformPixmap::copy(const QPlatformPixmap *data, const QRect &rect)
117{
118 fromImage(data->toImage(rect), Qt::NoOpaqueDetection);
119}
120
121bool QPlatformPixmap::scroll(int dx, int dy, const QRect &rect)
122{
123 Q_UNUSED(dx);
124 Q_UNUSED(dy);
125 Q_UNUSED(rect);
126 return false;
127}
128
129QBitmap QPlatformPixmap::mask() const
130{
131 if (!hasAlphaChannel())
132 return QBitmap();
133
134 QImage img = toImage();
135 bool shouldConvert = (img.format() != QImage::Format_ARGB32 && img.format() != QImage::Format_ARGB32_Premultiplied);
136 const QImage image = (shouldConvert ? std::move(img).convertToFormat(QImage::Format_ARGB32_Premultiplied) : img);
137 const int w = image.width();
138 const int h = image.height();
139
140 QImage mask(w, h, QImage::Format_MonoLSB);
141 if (mask.isNull()) // allocation failed
142 return QBitmap();
143
144 mask.setDevicePixelRatio(devicePixelRatio());
145 mask.setColorCount(2);
146 mask.setColor(0, QColor(Qt::color0).rgba());
147 mask.setColor(1, QColor(Qt::color1).rgba());
148
149 const qsizetype bpl = mask.bytesPerLine();
150
151 for (int y = 0; y < h; ++y) {
152 const QRgb *src = reinterpret_cast<const QRgb*>(image.scanLine(y));
153 uchar *dest = mask.scanLine(y);
154 memset(dest, 0, bpl);
155 for (int x = 0; x < w; ++x) {
156 if (qAlpha(*src) > 0)
157 dest[x >> 3] |= (1 << (x & 7));
158 ++src;
159 }
160 }
161
162 return QBitmap::fromImage(std::move(mask));
163}
164
165void QPlatformPixmap::setMask(const QBitmap &mask)
166{
167 QImage image = toImage();
168 if (mask.size().isEmpty()) {
169 if (image.depth() != 1) { // hw: ????
170 image = std::move(image).convertToFormat(QImage::Format_RGB32);
171 }
172 } else {
173 const int w = image.width();
174 const int h = image.height();
175
176 switch (image.depth()) {
177 case 1: {
178 const QImage imageMask = mask.toImage().convertToFormat(image.format());
179 for (int y = 0; y < h; ++y) {
180 const uchar *mscan = imageMask.scanLine(y);
181 uchar *tscan = image.scanLine(y);
182 qsizetype bytesPerLine = image.bytesPerLine();
183 for (int i = 0; i < bytesPerLine; ++i)
184 tscan[i] &= mscan[i];
185 }
186 break;
187 }
188 default: {
189 const QImage imageMask = mask.toImage().convertToFormat(QImage::Format_MonoLSB);
190 image = std::move(image).convertToFormat(QImage::Format_ARGB32_Premultiplied);
191 for (int y = 0; y < h; ++y) {
192 const uchar *mscan = imageMask.scanLine(y);
193 QRgb *tscan = (QRgb *)image.scanLine(y);
194 for (int x = 0; x < w; ++x) {
195 if (!(mscan[x>>3] & (1 << (x&7))))
196 tscan[x] = 0;
197 }
198 }
199 break;
200 }
201 }
202 }
203 fromImage(image, Qt::AutoColor);
204}
205
206QPixmap QPlatformPixmap::transformed(const QTransform &matrix,
207 Qt::TransformationMode mode) const
208{
209 return QPixmap::fromImage(toImage().transformed(matrix, mode));
210}
211
212void QPlatformPixmap::setSerialNumber(int serNo)
213{
214 ser_no = serNo;
215}
216
217void QPlatformPixmap::setDetachNumber(int detNo)
218{
219 detach_no = detNo;
220}
221
222QImage QPlatformPixmap::toImage(const QRect &rect) const
223{
224 if (rect.contains(QRect(0, 0, w, h)))
225 return toImage();
226 else
227 return toImage().copy(rect);
228}
229
230QImage* QPlatformPixmap::buffer()
231{
232 return nullptr;
233}
234
235
236QT_END_NAMESPACE
Combined button and popup list for selecting options.
static QImage makeBitmapCompliantIfNeeded(QPlatformPixmap *d, QImage image, Qt::ImageConversionFlags flags)