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_blitter.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
6
7#include <qpainter.h>
8#include <qimage.h>
9#include <qrandom.h>
10#include <qscreen.h>
11
12#include <private/qguiapplication_p.h>
13#include <private/qblittable_p.h>
14
15#include <private/qdrawhelper_p.h>
16#include <private/qfont_p.h>
17
18#ifndef QT_NO_BLITTABLE
20
21static int global_ser_no = 0;
22
23QBlittablePlatformPixmap::QBlittablePlatformPixmap()
24 : QPlatformPixmap(QPlatformPixmap::PixmapType,BlitterClass)
25 , m_alpha(false)
26 , m_devicePixelRatio(1.0)
27#ifdef QT_BLITTER_RASTEROVERLAY
28 ,m_rasterOverlay(0), m_unmergedCopy(0)
29#endif //QT_BLITTER_RASTEROVERLAY
30{
31 setSerialNumber(++global_ser_no);
32}
33
34QBlittablePlatformPixmap::~QBlittablePlatformPixmap()
35{
36#ifdef QT_BLITTER_RASTEROVERLAY
37 delete m_rasterOverlay;
38 delete m_unmergedCopy;
39#endif //QT_BLITTER_RASTEROVERLAY
40}
41
42QBlittable *QBlittablePlatformPixmap::blittable() const
43{
44 if (!m_blittable) {
45 QBlittablePlatformPixmap *that = const_cast<QBlittablePlatformPixmap *>(this);
46 that->m_blittable.reset(this->createBlittable(QSize(w, h), m_alpha));
47 }
48
49 return m_blittable.data();
50}
51
52void QBlittablePlatformPixmap::setBlittable(QBlittable *blittable)
53{
54 resize(blittable->size().width(),blittable->size().height());
55 m_blittable.reset(blittable);
56}
57
58void QBlittablePlatformPixmap::resize(int width, int height)
59{
60 m_blittable.reset(nullptr);
61 m_engine.reset(nullptr);
62 d = QGuiApplication::primaryScreen()->depth();
63 w = width;
64 h = height;
65 is_null = (w <= 0 || h <= 0);
66 setSerialNumber(++global_ser_no);
67}
68
69int QBlittablePlatformPixmap::metric(QPaintDevice::PaintDeviceMetric metric) const
70{
71 switch (metric) {
72 case QPaintDevice::PdmWidth:
73 return w;
74 case QPaintDevice::PdmHeight:
75 return h;
76 case QPaintDevice::PdmWidthMM:
77 return qRound(w * 25.4 / qt_defaultDpiX());
78 case QPaintDevice::PdmHeightMM:
79 return qRound(h * 25.4 / qt_defaultDpiY());
80 case QPaintDevice::PdmDepth:
81 return 32;
82 case QPaintDevice::PdmDpiX:
83 case QPaintDevice::PdmPhysicalDpiX:
84 return qt_defaultDpiX();
85 case QPaintDevice::PdmDpiY:
86 case QPaintDevice::PdmPhysicalDpiY:
87 return qt_defaultDpiY();
88 case QPaintDevice::PdmDevicePixelRatio:
89 return devicePixelRatio();
90 case QPaintDevice::PdmDevicePixelRatioScaled:
91 return devicePixelRatio() * QPaintDevice::devicePixelRatioFScale();
92 case QPaintDevice::PdmDevicePixelRatioF_EncodedA:
93 Q_FALLTHROUGH();
94 case QPaintDevice::PdmDevicePixelRatioF_EncodedB:
95 return QPaintDevice::encodeMetricF(metric, devicePixelRatio());
96 default:
97 qWarning("QRasterPlatformPixmap::metric(): Unhandled metric type %d", metric);
98 break;
99 }
100
101 return 0;
102}
103
104void QBlittablePlatformPixmap::fill(const QColor &color)
105{
106 if (blittable()->capabilities() & QBlittable::AlphaFillRectCapability) {
107 blittable()->unlock();
108 blittable()->alphaFillRect(QRectF(0,0,w,h),color,QPainter::CompositionMode_Source);
109 } else if (color.alpha() == 255 && blittable()->capabilities() & QBlittable::SolidRectCapability) {
110 blittable()->unlock();
111 blittable()->fillRect(QRectF(0,0,w,h),color);
112 } else {
113 // Need to be backed with an alpha channel now. It would be nice
114 // if we could just change the format, e.g. when going from
115 // RGB32 -> ARGB8888.
116 if (color.alpha() != 255 && !hasAlphaChannel()) {
117 m_blittable.reset(nullptr);
118 m_engine.reset(nullptr);
119 m_alpha = true;
120 }
121
122 blittable()->lock()->fill(color);
123 }
124
125}
126
127QImage *QBlittablePlatformPixmap::buffer()
128{
129 return blittable()->lock();
130}
131
132QImage QBlittablePlatformPixmap::toImage() const
133{
134 return blittable()->lock()->copy();
135}
136
137bool QBlittablePlatformPixmap::hasAlphaChannel() const
138{
139 return blittable()->lock()->hasAlphaChannel();
140}
141
142void QBlittablePlatformPixmap::fromImage(const QImage &image,
143 Qt::ImageConversionFlags flags)
144{
145 m_alpha = image.hasAlphaChannel();
146 m_devicePixelRatio = image.devicePixelRatio();
147 resize(image.width(),image.height());
148 markRasterOverlay(QRect(0,0,w,h));
149 QImage *thisImg = buffer();
150
151 QImage correctFormatPic = image;
152 if (correctFormatPic.format() != thisImg->format())
153 correctFormatPic = correctFormatPic.convertToFormat(thisImg->format(), flags);
154
155 uchar *mem = thisImg->bits();
156 const uchar *bits = correctFormatPic.constBits();
157 qsizetype bytesCopied = 0;
158 while (bytesCopied < correctFormatPic.sizeInBytes()) {
159 memcpy(mem,bits,correctFormatPic.bytesPerLine());
160 mem += thisImg->bytesPerLine();
161 bits += correctFormatPic.bytesPerLine();
162 bytesCopied+=correctFormatPic.bytesPerLine();
163 }
164}
165
166qreal QBlittablePlatformPixmap::devicePixelRatio() const
167{
168 return m_devicePixelRatio;
169}
170
171void QBlittablePlatformPixmap::setDevicePixelRatio(qreal scaleFactor)
172{
173 m_devicePixelRatio = scaleFactor;
174}
175
176QPaintEngine *QBlittablePlatformPixmap::paintEngine() const
177{
178 if (!m_engine) {
179 QBlittablePlatformPixmap *that = const_cast<QBlittablePlatformPixmap *>(this);
180 that->m_engine.reset(new QBlitterPaintEngine(that));
181 }
182 return m_engine.data();
183}
184
185#ifdef QT_BLITTER_RASTEROVERLAY
186
187static bool showRasterOverlay = !qEnvironmentVariableIsEmpty("QT_BLITTER_RASTEROVERLAY");
188
189void QBlittablePlatformPixmap::mergeOverlay()
190{
191 if (m_unmergedCopy || !showRasterOverlay)
192 return;
193 m_unmergedCopy = new QImage(buffer()->copy());
194 QPainter p(buffer());
195 p.setCompositionMode(QPainter::CompositionMode_SourceOver);
196 p.drawImage(0,0,*overlay());
197 p.end();
198}
199
200void QBlittablePlatformPixmap::unmergeOverlay()
201{
202 if (!m_unmergedCopy || !showRasterOverlay)
203 return;
204 QPainter p(buffer());
205 p.setCompositionMode(QPainter::CompositionMode_Source);
206 p.drawImage(0,0,*m_unmergedCopy);
207 p.end();
208
209 delete m_unmergedCopy;
210 m_unmergedCopy = 0;
211}
212
213QImage *QBlittablePlatformPixmap::overlay()
214{
215 if (!m_rasterOverlay||
216 m_rasterOverlay->size() != QSize(w,h)){
217 m_rasterOverlay = new QImage(w,h,QImage::Format_ARGB32_Premultiplied);
218 m_rasterOverlay->fill(0x00000000);
219 uint color = QRandomGenerator::global()->bounded(11)+7;
220 m_overlayColor = QColor(Qt::GlobalColor(color));
221 m_overlayColor.setAlpha(0x88);
222
223 }
224 return m_rasterOverlay;
225}
226
227void QBlittablePlatformPixmap::markRasterOverlayImpl(const QRectF &rect)
228{
229 if (!showRasterOverlay)
230 return;
231 QRectF transformationRect = clipAndTransformRect(rect);
232 if (!transformationRect.isEmpty()) {
233 QPainter p(overlay());
234 p.setBrush(m_overlayColor);
235 p.setCompositionMode(QPainter::CompositionMode_Source);
236 p.fillRect(transformationRect,QBrush(m_overlayColor));
237 }
238}
239
240void QBlittablePlatformPixmap::unmarkRasterOverlayImpl(const QRectF &rect)
241{
242 if (!showRasterOverlay)
243 return;
244 QRectF transformationRect = clipAndTransformRect(rect);
245 if (!transformationRect.isEmpty()) {
246 QPainter p(overlay());
247 QColor color(0x00,0x00,0x00,0x00);
248 p.setBrush(color);
249 p.setCompositionMode(QPainter::CompositionMode_Source);
250 p.fillRect(transformationRect,QBrush(color));
251 }
252}
253
254QRectF QBlittablePlatformPixmap::clipAndTransformRect(const QRectF &rect) const
255{
256 QRectF transformationRect = rect;
257 paintEngine();
258 if (m_engine->state()) {
259 transformationRect = m_engine->state()->matrix.mapRect(rect);
260 const QClipData *clipData = m_engine->clip();
261 if (clipData) {
262 if (clipData->hasRectClip) {
263 transformationRect &= clipData->clipRect;
264 } else if (clipData->hasRegionClip) {
265 for (const QRect &rect : clipData->clipRegion)
266 transformationRect &= rect;
267 }
268 }
269 }
270 return transformationRect;
271}
272
273#endif //QT_BLITTER_RASTEROVERLAY
274
275QT_END_NAMESPACE
276
277#endif //QT_NO_BLITTABLE
Combined button and popup list for selecting options.
static QT_BEGIN_NAMESPACE int global_ser_no