8#include <qpa/qplatformpixmap.h>
16#include <private/qguiapplication_p.h>
29#include <qpa/qplatformintegration.h>
32#include "private/qhexstring_p.h"
34#include <qtgui_tracepoints_p.h>
40using namespace Qt::StringLiterals;
42Q_TRACE_PARAM_REPLACE(Qt::AspectRatioMode,
int);
43Q_TRACE_PARAM_REPLACE(Qt::TransformationMode,
int);
48QT_WARNING_DISABLE_MSVC(4723)
52 if (!QCoreApplication::instanceExists()) {
53 qFatal(
"QPixmap: Must construct a QGuiApplication before a QPixmap");
56 if (QGuiApplicationPrivate::instance()
57 && !QThread::isMainThread()
58 && !QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::ThreadedPixmaps)) {
59 qWarning(
"QPixmap: It is not safe to use pixmaps outside the GUI thread on this platform");
65void QPixmap::doInit(
int w,
int h,
int type)
67 if ((w > 0 && h > 0) || type == QPlatformPixmap::BitmapType)
68 data = QPlatformPixmap::create(w, h, (QPlatformPixmap::PixelType) type);
74
75
76
77
82 (
void) qt_pixmap_thread_test();
83 doInit(0, 0, QPlatformPixmap::PixmapType);
87
88
89
90
91
92
93
94
95
96
97
98
100QPixmap::QPixmap(
int w,
int h)
101 : QPixmap(QSize(w, h))
106
107
108
109
110
111
112
113
115QPixmap::QPixmap(
const QSize &size)
116 : QPixmap(size, QPlatformPixmap::PixmapType)
121
122
123QPixmap::QPixmap(
const QSize &s,
int type)
125 if (!qt_pixmap_thread_test())
126 doInit(0, 0,
static_cast<QPlatformPixmap::PixelType>(type));
128 doInit(s.width(), s.height(),
static_cast<QPlatformPixmap::PixelType>(type));
132
133
134QPixmap::QPixmap(QPlatformPixmap *d)
135 : QPaintDevice(), data(d)
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
168QPixmap::QPixmap(
const QString& fileName,
const char *format, Qt::ImageConversionFlags flags)
171 doInit(0, 0, QPlatformPixmap::PixmapType);
172 if (!qt_pixmap_thread_test())
175 load(fileName, format, flags);
179
180
181
182
184QPixmap::QPixmap(
const QPixmap &pixmap)
187 if (!qt_pixmap_thread_test()) {
188 doInit(0, 0, QPlatformPixmap::PixmapType);
191 if (pixmap.paintingActive()) {
192 pixmap.copy().swap(*
this);
199
200
201
202
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221#ifndef QT_NO_IMAGEFORMAT_XPM
222QPixmap::QPixmap(
const char *
const xpm[])
225 doInit(0, 0, QPlatformPixmap::PixmapType);
230 if (!image.isNull()) {
231 if (data && data->pixelType() == QPlatformPixmap::BitmapType)
232 *
this = QBitmap::fromImage(std::move(image));
234 *
this = fromImage(std::move(image));
241
242
246 Q_ASSERT(!data || data->ref.loadRelaxed() >= 1);
250
251
252int QPixmap::devType()
const
254 return QInternal::Pixmap;
258
259
260
261
262
263
266
267
268
269
270
271
272
273
274
275
276
277QPixmap QPixmap::copy(
const QRect &rect)
const
282 QRect r(0, 0, width(), height());
284 r = r.intersected(rect);
286 QPlatformPixmap *d = data->createCompatiblePlatformPixmap();
287 d->copy(data.data(), r);
292
293
294
295
296
297
298
301
302
303
304
305
306
307
308
309
310
311void QPixmap::scroll(
int dx,
int dy,
const QRect &rect, QRegion *exposed)
313 if (isNull() || (dx == 0 && dy == 0))
315 QRect dest = rect &
this->rect();
316 QRect src = dest.translated(-dx, -dy) & dest;
325 if (!data->scroll(dx, dy, src)) {
328 QPainter painter(&pix);
329 painter.setCompositionMode(QPainter::CompositionMode_Source);
330 painter.drawPixmap(src.translated(dx, dy), *
this, src);
337 *exposed -= src.translated(dx, dy);
342
343
344
345
346
348QPixmap &QPixmap::operator=(
const QPixmap &pixmap)
350 if (paintingActive()) {
351 qWarning(
"QPixmap::operator=: Cannot assign to pixmap during painting");
354 if (pixmap.paintingActive()) {
355 pixmap.copy().swap(*
this);
363
364
365
366
367
368
371
372
373
376
377
378QPixmap::operator QVariant()
const
380 return QVariant::fromValue(*
this);
384
385
386
387
388
389
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407QImage QPixmap::toImage()
const
412 return data->toImage();
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431QTransform QPixmap::trueMatrix(
const QTransform &m,
int w,
int h)
433 return QImage::trueMatrix(m, w, h);
437
438
439
440
442bool QPixmap::isQBitmap()
const
444 return data && data->type == QPlatformPixmap::BitmapType;
448
449
450
451
452
453
454
455bool QPixmap::isNull()
const
457 return !data || data->isNull();
461
462
463
464
465
466
467int QPixmap::width()
const
469 return data ? data->width() : 0;
473
474
475
476
477
478
479int QPixmap::height()
const
481 return data ? data->height() : 0;
485
486
487
488
489
490
491
492QSize QPixmap::size()
const
494 return data ? QSize(data->width(), data->height()) : QSize(0, 0);
498
499
500
501
502
503
504QRect QPixmap::rect()
const
506 return data ? QRect(0, 0, data->width(), data->height()) : QRect();
510
511
512
513
514
515
516
517
518
519
520int QPixmap::depth()
const
522 return data ? data->depth() : 0;
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542void QPixmap::setMask(
const QBitmap &mask)
544 if (paintingActive()) {
545 qWarning(
"QPixmap::setMask: Cannot set mask while pixmap is being painted on");
549 if (!mask.isNull() && mask.size() != size()) {
550 qWarning(
"QPixmap::setMask() mask size differs from pixmap size");
557 if (
static_cast<
const QPixmap &>(mask).data == data)
565
566
567
568
569
570
571
572
573
574
575qreal QPixmap::devicePixelRatio()
const
579 return data->devicePixelRatio();
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603void QPixmap::setDevicePixelRatio(qreal scaleFactor)
608 if (scaleFactor == data->devicePixelRatio())
612 data->setDevicePixelRatio(scaleFactor);
616
617
618
619
620
621
622
623
624
625QSizeF QPixmap::deviceIndependentSize()
const
629 return QSizeF(data->width(), data->height()) / data->devicePixelRatio();
632#ifndef QT_NO_IMAGE_HEURISTIC_MASK
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652QBitmap QPixmap::createHeuristicMask(
bool clipTight)
const
654 QBitmap m = QBitmap::fromImage(toImage().createHeuristicMask(clipTight));
660
661
662
663
664
665
666
667
668
669
670QBitmap QPixmap::createMaskFromColor(
const QColor &maskColor, Qt::MaskMode mode)
const
672 QImage image = toImage().convertToFormat(QImage::Format_ARGB32);
673 return QBitmap::fromImage(std::move(image).createMaskFromColor(maskColor.rgba(), mode));
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
703bool QPixmap::load(
const QString &fileName,
const char *format, Qt::ImageConversionFlags flags)
705 if (!fileName.isEmpty()) {
707 QFileInfo info(fileName);
710 if (info.completeSuffix().isEmpty() || info.exists()) {
711 const bool inGuiThread = qApp->thread() == QThread::currentThread();
713 QString key =
"qt_pixmap"_L1
714 % info.absoluteFilePath()
715 % HexString<uint>(info.lastModified(QTimeZone::UTC).toSecsSinceEpoch())
716 % HexString<quint64>(info.size())
717 % HexString<uint>(data ? data->pixelType() : QPlatformPixmap::PixmapType);
719 if (inGuiThread && QPixmapCache::find(key,
this))
722 data = QPlatformPixmap::create(0, 0, data ? data->pixelType() : QPlatformPixmap::PixmapType);
724 if (data->fromFile(fileName, format, flags)) {
726 QPixmapCache::insert(key, *
this);
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
760bool QPixmap::loadFromData(
const uchar *buf, uint len,
const char *format, Qt::ImageConversionFlags flags)
762 if (len == 0 || buf ==
nullptr) {
767 data = QPlatformPixmap::create(0, 0, QPlatformPixmap::PixmapType);
769 if (data->fromData(buf, len, format, flags))
777
778
779
780
781
782
783
787
788
789
790
791
792
793
794
795
796
797
798
799
800
802bool QPixmap::save(
const QString &fileName,
const char *format,
int quality)
const
806 QImageWriter writer(fileName, format);
807 return doImageIO(&writer, quality);
811
812
813
814
815
816
817
818
820bool QPixmap::save(QIODevice* device,
const char* format,
int quality)
const
824 QImageWriter writer(device, format);
825 return doImageIO(&writer, quality);
829
830bool QPixmap::doImageIO(QImageWriter *writer,
int quality)
const
832 if (quality > 100 || quality < -1)
833 qWarning(
"QPixmap::save: quality out of range [-1,100]");
835 writer->setQuality(qMin(quality,100));
836 return writer->write(toImage());
841
842
843
844
845
846
847
849void QPixmap::fill(
const QColor &color)
856 if (paintingActive() && (color.alpha() != 255) && !hasAlphaChannel()) {
857 qWarning(
"QPixmap::fill: Cannot fill while pixmap is being painted on");
861 if (data->ref.loadRelaxed() == 1) {
868 QPlatformPixmap *d = data->createCompatiblePlatformPixmap();
869 d->resize(data->width(), data->height());
870 d->setDevicePixelRatio(data->devicePixelRatio());
877
878
879
880
881
882
883qint64 QPixmap::cacheKey()
const
889 return data->cacheKey();
893static void sendResizeEvents(QWidget *target)
895 QResizeEvent e(target->size(), QSize());
896 QApplication::sendEvent(target, &e);
898 const QObjectList children = target->children();
899 for (
int i = 0; i < children.size(); ++i) {
900 QWidget *child =
static_cast<QWidget*>(children.at(i));
901 if (child->isWidgetType() && !child->isWindow() && child->testAttribute(Qt::WA_PendingResizeEvent))
902 sendResizeEvents(child);
909
910
911#if !defined(QT_NO_DATASTREAM)
913
914
915
916
917
918
919
920
922QDataStream &operator<<(QDataStream &stream,
const QPixmap &pixmap)
924 return stream << pixmap.toImage();
928
929
930
931
932
933
935QDataStream &operator>>(QDataStream &stream, QPixmap &pixmap)
940 if (image.isNull()) {
942 }
else if (image.depth() == 1) {
943 pixmap = QBitmap::fromImage(std::move(image));
945 pixmap = QPixmap::fromImage(std::move(image));
953
954
956bool QPixmap::isDetached()
const
958 return data && data->ref.loadRelaxed() == 1;
962
963
964
965
966
967
968
969
970bool QPixmap::convertFromImage(
const QImage &image, Qt::ImageConversionFlags flags)
973 if (image.isNull() || !data)
974 *
this = QPixmap::fromImage(image, flags);
976 data->fromImage(image, flags);
981
982
983
984
985
986
987
988
989
990
991
992
993
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028QPixmap Q_TRACE_INSTRUMENT(qtgui) QPixmap::scaled(
const QSize& s, Qt::AspectRatioMode aspectMode, Qt::TransformationMode mode)
const
1031 qWarning(
"QPixmap::scaled: Pixmap is a null pixmap");
1037 QSize newSize = size();
1038 newSize.scale(s, aspectMode);
1039 newSize.rwidth() = qMax(newSize.width(), 1);
1040 newSize.rheight() = qMax(newSize.height(), 1);
1041 if (newSize == size())
1044 Q_TRACE_SCOPE(QPixmap_scaled, s, aspectMode, mode);
1046 QTransform wm = QTransform::fromScale((qreal)newSize.width() / width(),
1047 (qreal)newSize.height() / height());
1048 QPixmap pix = transformed(wm, mode);
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066QPixmap Q_TRACE_INSTRUMENT(qtgui) QPixmap::scaledToWidth(
int w, Qt::TransformationMode mode)
const
1069 qWarning(
"QPixmap::scaleWidth: Pixmap is a null pixmap");
1075 Q_TRACE_SCOPE(QPixmap_scaledToWidth, w, mode);
1077 qreal factor = (qreal) w / width();
1078 QTransform wm = QTransform::fromScale(factor, factor);
1079 return transformed(wm, mode);
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096QPixmap Q_TRACE_INSTRUMENT(qtgui) QPixmap::scaledToHeight(
int h, Qt::TransformationMode mode)
const
1099 qWarning(
"QPixmap::scaleHeight: Pixmap is a null pixmap");
1105 Q_TRACE_SCOPE(QPixmap_scaledToHeight, h, mode);
1107 qreal factor = (qreal) h / height();
1108 QTransform wm = QTransform::fromScale(factor, factor);
1109 return transformed(wm, mode);
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130QPixmap QPixmap::transformed(
const QTransform &transform,
1131 Qt::TransformationMode mode)
const
1133 if (isNull() || transform.type() <= QTransform::TxTranslate)
1136 return data->transformed(transform, mode);
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1305
1306
1307
1310
1311
1312
1315
1316
1317
1318
1319
1320bool QPixmap::hasAlpha()
const
1322 return data && data->hasAlphaChannel();
1326
1327
1328
1329
1330
1331bool QPixmap::hasAlphaChannel()
const
1333 return data && data->hasAlphaChannel();
1337
1338
1339int QPixmap::metric(PaintDeviceMetric metric)
const
1341 return data ? data->metric(metric) : 0;
1345
1346
1347QPaintEngine *QPixmap::paintEngine()
const
1349 return data ? data->paintEngine() :
nullptr;
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362QBitmap QPixmap::mask()
const
1364 return data ? data->mask() : QBitmap();
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377int QPixmap::defaultDepth()
1379 QScreen *primary = QGuiApplication::primaryScreen();
1380 if (Q_LIKELY(primary))
1381 return primary->depth();
1382 qWarning(
"QPixmap: QGuiApplication must be created before calling defaultDepth().");
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403void QPixmap::detach()
1410 QPlatformPixmap *pd = handle();
1411 QPlatformPixmap::ClassId id = pd->classId();
1412 if (id == QPlatformPixmap::RasterClass) {
1413 QRasterPlatformPixmap *rasterData =
static_cast<QRasterPlatformPixmap*>(pd);
1414 rasterData->image.detach();
1417 if (data->is_cached && data->ref.loadRelaxed() == 1)
1418 QImagePixmapCleanupHooks::executePlatformPixmapModificationHooks(data.data());
1420 if (data->ref.loadRelaxed() != 1) {
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441QPixmap QPixmap::fromImage(
const QImage &image, Qt::ImageConversionFlags flags)
1446 if (Q_UNLIKELY(!qobject_cast<QGuiApplication *>(QCoreApplication::instance()))) {
1447 qWarning(
"QPixmap::fromImage: QPixmap cannot be created without a QGuiApplication");
1451 std::unique_ptr<QPlatformPixmap> data(QGuiApplicationPrivate::platformIntegration()->createPlatformPixmap(QPlatformPixmap::PixmapType));
1452 data->fromImage(image, flags);
1453 return QPixmap(data.release());
1457
1458
1459
1460
1461
1462
1466
1467
1468QPixmap QPixmap::fromImageInPlace(QImage &image, Qt::ImageConversionFlags flags)
1473 if (Q_UNLIKELY(!qobject_cast<QGuiApplication *>(QCoreApplication::instance()))) {
1474 qWarning(
"QPixmap::fromImageInPlace: QPixmap cannot be created without a QGuiApplication");
1478 std::unique_ptr<QPlatformPixmap> data(QGuiApplicationPrivate::platformIntegration()->createPlatformPixmap(QPlatformPixmap::PixmapType));
1479 data->fromImageInPlace(image, flags);
1480 return QPixmap(data.release());
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495QPixmap QPixmap::fromImageReader(QImageReader *imageReader, Qt::ImageConversionFlags flags)
1497 if (Q_UNLIKELY(!qobject_cast<QGuiApplication *>(QCoreApplication::instance()))) {
1498 qWarning(
"QPixmap::fromImageReader: QPixmap cannot be created without a QGuiApplication");
1502 std::unique_ptr<QPlatformPixmap> data(QGuiApplicationPrivate::platformIntegration()->createPlatformPixmap(QPlatformPixmap::PixmapType));
1503 data->fromImageReader(imageReader, flags);
1504 return QPixmap(data.release());
1508
1509
1510QPlatformPixmap* QPixmap::handle()
const
1515#ifndef QT_NO_DEBUG_STREAM
1516QDebug operator<<(QDebug dbg,
const QPixmap &r)
1518 QDebugStateSaver saver(dbg);
1525 dbg << r.size() <<
",depth=" << r.depth()
1526 <<
",devicePixelRatio=" << r.devicePixelRatio()
1527 <<
",cacheKey=" << Qt::showbase << Qt::hex << r.cacheKey() << Qt::dec << Qt::noshowbase;
Combined button and popup list for selecting options.
static bool qt_pixmap_thread_test()