6#include <private/qpicture_p.h>
10#include <private/qfactoryloader_p.h>
11#include <private/qpaintengine_pic_p.h>
12#include <private/qfont_p.h>
13#include <qguiapplication.h>
24#include <QtCore/private/qlocking_p.h>
34 const QTextOption *opt,
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
88
89
90
91
92
93
100
101
102
103
104
105
106
107
108
109
110
111
112
114QPicture::QPicture(
int formatVersion)
116 d_ptr(
new QPicturePrivate)
120 if (formatVersion == 0)
121 qWarning(
"QPicture: invalid format version 0");
124 if (formatVersion > 0 && formatVersion != (
int)mfhdr_maj) {
125 d->formatMajor = formatVersion;
134
135
136
137
139QPicture::QPicture(
const QPicture &pic)
140 : QPaintDevice(), d_ptr(pic.d_ptr)
145QPicture::QPicture(QPicturePrivate &dptr)
152
153
159
160
161int QPicture::devType()
const
163 return QInternal::Picture;
167
168
169
170
171
174
175
176
177
178
179
182
183
184
185
186
187
188
189
192bool QPicture::isNull()
const
194 return d_func()->pictb.buffer().isNull();
197uint QPicture::size()
const
199 return d_func()->pictb.buffer().size();
202const char* QPicture::data()
const
204 return d_func()->pictb.buffer();
207void QPicture::detach()
212bool QPicture::isDetached()
const
214 return d_func()->ref.loadRelaxed() == 1;
218
219
220
221
222
224void QPicture::setData(
const char* data, uint size)
227 d_func()->pictb.setData(data, size);
228 d_func()->resetFormat();
233
234
235
236
237
239bool QPicture::load(
const QString &fileName)
242 if (!f.open(QIODevice::ReadOnly)) {
243 operator=(QPicture());
250
251
252
253
255bool QPicture::load(QIODevice *dev)
258 QByteArray a = dev->readAll();
260 d_func()->pictb.setData(a);
261 return d_func()->checkFormat();
265
266
267
268
269
271bool QPicture::save(
const QString &fileName)
273 if (paintingActive()) {
274 qWarning(
"QPicture::save: still being painted on. "
275 "Call QPainter::end() first");
280 if (!f.open(QIODevice::WriteOnly))
286
287
288
289
291bool QPicture::save(QIODevice *dev)
293 if (paintingActive()) {
294 qWarning(
"QPicture::save: still being painted on. "
295 "Call QPainter::end() first");
299 dev->write(d_func()->pictb.buffer(), d_func()->pictb.buffer().size());
304
305
306
308QRect QPicture::boundingRect()
const
312 if (!d->override_rect.isEmpty())
313 return d->override_rect;
316 d_ptr->checkFormat();
322
323
324
326void QPicture::setBoundingRect(
const QRect &r)
328 d_func()->override_rect = r;
332
333
334
335
336
337
338
339
341bool QPicture::play(QPainter *painter)
345 if (d->pictb.size() == 0)
348 if (!d->formatOk && !d->checkFormat())
351 d->pictb.open(QIODevice::ReadOnly);
353 s.setDevice(&d->pictb);
354 s.device()->seek(10);
355 s.setVersion(d->formatMajor == 4 ? 3 : d->formatMajor);
360 Q_ASSERT(c == QPicturePrivate::PdcBegin);
362 if (d->formatMajor >= 4) {
364 s >> dummy >> dummy >> dummy >> dummy;
367 if (!exec(painter, s, nrecords)) {
368 qWarning(
"QPicture::play: Format error");
383 QFakeDevice() { dpi_x = qt_defaultDpiX(); dpi_y = qt_defaultDpiY(); }
387 int metric(PaintDeviceMetric m)
const override
390 case PdmPhysicalDpiX:
393 case PdmPhysicalDpiY:
397 return QPaintDevice::metric(m);
407
408
409
410
412bool QPicture::exec(QPainter *painter, QDataStream &s,
int nrecords)
421 qint16 i_16, i1_16, i2_16;
442 QTransform worldMatrix = painter->transform();
443 worldMatrix.scale(qreal(painter->device()->logicalDpiX()) / qreal(qt_defaultDpiX()),
444 qreal(painter->device()->logicalDpiY()) / qreal(qt_defaultDpiY()));
445 painter->setTransform(worldMatrix);
447 while (nrecords-- && !s.atEnd()) {
455 strm_pos = s.device()->pos();
458 case QPicturePrivate::PdcNOP:
460 case QPicturePrivate::PdcDrawPoint:
461 if (d->formatMajor <= 5) {
463 painter->drawPoint(ip);
466 painter->drawPoint(p);
469 case QPicturePrivate::PdcDrawPoints:
474 case QPicturePrivate::PdcDrawPath: {
477 painter->drawPath(path);
480 case QPicturePrivate::PdcDrawLine:
481 if (d->formatMajor <= 5) {
483 painter->drawLine(ip1, ip2);
486 painter->drawLine(p1, p2);
489 case QPicturePrivate::PdcDrawRect:
490 if (d->formatMajor <= 5) {
492 painter->drawRect(ir);
495 painter->drawRect(r);
498 case QPicturePrivate::PdcDrawRoundRect:
499 if (d->formatMajor <= 5) {
500 s >> ir >> i1_16 >> i2_16;
501 painter->drawRoundedRect(ir, i1_16, i2_16, Qt::RelativeSize);
503 s >> r >> i1_16 >> i2_16;
504 painter->drawRoundedRect(r, i1_16, i2_16, Qt::RelativeSize);
507 case QPicturePrivate::PdcDrawEllipse:
508 if (d->formatMajor <= 5) {
510 painter->drawEllipse(ir);
513 painter->drawEllipse(r);
516 case QPicturePrivate::PdcDrawArc:
517 if (d->formatMajor <= 5) {
524 painter->drawArc(r, i1_16, i2_16);
526 case QPicturePrivate::PdcDrawPie:
527 if (d->formatMajor <= 5) {
534 painter->drawPie(r, i1_16, i2_16);
536 case QPicturePrivate::PdcDrawChord:
537 if (d->formatMajor <= 5) {
544 painter->drawChord(r, i1_16, i2_16);
546 case QPicturePrivate::PdcDrawLineSegments:
548 painter->drawLines(ia);
551 case QPicturePrivate::PdcDrawPolyline:
552 if (d->formatMajor <= 5) {
554 painter->drawPolyline(ia);
558 painter->drawPolyline(a);
562 case QPicturePrivate::PdcDrawPolygon:
563 if (d->formatMajor <= 5) {
565 painter->drawPolygon(ia, i_8 ? Qt::WindingFill : Qt::OddEvenFill);
569 painter->drawPolygon(a, i_8 ? Qt::WindingFill : Qt::OddEvenFill);
573 case QPicturePrivate::PdcDrawCubicBezier: {
576 Q_ASSERT(ia.size() == 4);
577 path.moveTo(ia.value(0));
578 path.cubicTo(ia.value(1), ia.value(2), ia.value(3));
579 painter->strokePath(path, painter->pen());
583 case QPicturePrivate::PdcDrawText:
585 painter->drawText(ip, QString::fromLatin1(str1));
587 case QPicturePrivate::PdcDrawTextFormatted:
588 s >> ir >> i_16 >> str1;
589 painter->drawText(ir, i_16, QString::fromLatin1(str1));
591 case QPicturePrivate::PdcDrawText2:
592 if (d->formatMajor <= 5) {
594 painter->drawText(ip, str);
597 painter->drawText(p, str);
600 case QPicturePrivate::PdcDrawText2Formatted:
604 painter->drawText(ir, i_16, str);
606 case QPicturePrivate::PdcDrawTextItem: {
607 s >> p >> str >> font >> ul;
613 if (d->formatMajor >= 9) {
618 fake.setDpiX(qRound(dbl*qt_defaultDpiX()));
619 fake.setDpiY(qRound(dbl*qt_defaultDpiY()));
620 fnt = QFont(font, &fake);
623 qreal justificationWidth;
624 s >> justificationWidth;
626 int flags = Qt::TextSingleLine | Qt::TextDontClip | Qt::TextForceLeftToRight;
630 if (justificationWidth > 0) {
631 size.setWidth(justificationWidth);
632 flags |= Qt::TextJustificationForced;
633 alignment |= Qt::AlignJustify;
636 QPointF pt(p.x(), p.y());
637 if (d->formatMajor >= QDataStream::Qt_6_11) {
638 alignment |= Qt::AlignBaseline;
640 QFontMetrics fm(fnt);
641 pt.ry() -= fm.ascent();
657 QRectF(p, QSizeF(1, 1)),
658 Qt::TextSingleLine | Qt::TextDontClip,
671 case QPicturePrivate::PdcDrawPixmap: {
673 if (d->formatMajor < 4) {
675 painter->drawPixmap(ip, pixmap);
676 }
else if (d->formatMajor <= 5) {
678 painter->drawPixmap(ir, pixmap);
681 if (d->in_memory_only) {
683 s >> r >> index >> sr;
684 Q_ASSERT(index < d->pixmap_list.size());
685 pixmap = d->pixmap_list.value(index);
687 s >> r >> pixmap >> sr;
689 painter->drawPixmap(r, pixmap, sr);
693 case QPicturePrivate::PdcDrawTiledPixmap: {
695 if (d->in_memory_only) {
697 s >> r >> index >> p;
698 Q_ASSERT(index < d->pixmap_list.size());
699 pixmap = d->pixmap_list.value(index);
701 s >> r >> pixmap >> p;
703 painter->drawTiledPixmap(r, pixmap, p);
706 case QPicturePrivate::PdcDrawImage: {
708 if (d->formatMajor < 4) {
710 painter->drawImage(p, image);
711 }
else if (d->formatMajor <= 5){
713 painter->drawImage(ir, image, QRect(0, 0, ir.width(), ir.height()));
716 if (d->in_memory_only) {
718 s >> r >> index >> sr >> ul;
719 Q_ASSERT(index < d->image_list.size());
720 image = d->image_list.value(index);
722 s >> r >> image >> sr >> ul;
724 painter->drawImage(r, image, sr, Qt::ImageConversionFlags(ul));
728 case QPicturePrivate::PdcBegin:
730 if (!exec(painter, s, ul))
733 case QPicturePrivate::PdcEnd:
737 case QPicturePrivate::PdcSave:
740 case QPicturePrivate::PdcRestore:
743 case QPicturePrivate::PdcSetBkColor:
745 painter->setBackground(color);
747 case QPicturePrivate::PdcSetBkMode:
749 painter->setBackgroundMode((Qt::BGMode)i_8);
751 case QPicturePrivate::PdcSetROP:
754 case QPicturePrivate::PdcSetBrushOrigin:
755 if (d->formatMajor <= 5) {
757 painter->setBrushOrigin(ip);
760 painter->setBrushOrigin(p);
763 case QPicturePrivate::PdcSetFont:
765 painter->setFont(font);
767 case QPicturePrivate::PdcSetPen:
768 if (d->in_memory_only) {
771 Q_ASSERT(index < d->pen_list.size());
772 pen = d->pen_list.value(index);
776 painter->setPen(pen);
778 case QPicturePrivate::PdcSetBrush:
779 if (d->in_memory_only) {
782 Q_ASSERT(index < d->brush_list.size());
783 brush = d->brush_list.value(index);
787 painter->setBrush(brush);
789 case QPicturePrivate::PdcSetVXform:
791 painter->setViewTransformEnabled(i_8);
793 case QPicturePrivate::PdcSetWindow:
794 if (d->formatMajor <= 5) {
796 painter->setWindow(ir);
799 painter->setWindow(r.toRect());
802 case QPicturePrivate::PdcSetViewport:
803 if (d->formatMajor <= 5) {
805 painter->setViewport(ir);
808 painter->setViewport(r.toRect());
811 case QPicturePrivate::PdcSetWXform:
813 painter->setWorldMatrixEnabled(i_8);
815 case QPicturePrivate::PdcSetWMatrix:
816 if (d->formatMajor >= 8) {
819 s >> wmatrix[0] >> wmatrix[1]
820 >> wmatrix[2] >> wmatrix[3]
821 >> wmatrix[4] >> wmatrix[5] >> i_8;
822 matrix = QTransform(wmatrix[0], wmatrix[1],
823 wmatrix[2], wmatrix[3],
824 wmatrix[4], wmatrix[5]);
827 painter->setTransform(matrix * worldMatrix, i_8);
829 case QPicturePrivate::PdcSetClip:
831 painter->setClipping(i_8);
833 case QPicturePrivate::PdcSetClipRegion:
835 if (d->formatMajor >= 9) {
836 painter->setClipRegion(rgn, Qt::ClipOperation(i_8));
838 painter->setClipRegion(rgn);
841 case QPicturePrivate::PdcSetClipPath:
845 painter->setClipPath(path, Qt::ClipOperation(i_8));
848 case QPicturePrivate::PdcSetRenderHint:
850 painter->setRenderHint(QPainter::Antialiasing,
851 bool(ul & QPainter::Antialiasing));
852 painter->setRenderHint(QPainter::SmoothPixmapTransform,
853 bool(ul & QPainter::SmoothPixmapTransform));
854 painter->setRenderHint(QPainter::NonCosmeticBrushPatterns,
855 bool(ul & QPainter::NonCosmeticBrushPatterns));
857 case QPicturePrivate::PdcSetCompositionMode:
859 painter->setCompositionMode((QPainter::CompositionMode)ul);
861 case QPicturePrivate::PdcSetClipEnabled:
863 painter->setClipping(bl);
865 case QPicturePrivate::PdcSetOpacity:
867 painter->setOpacity(qreal(dbl));
870 qWarning(
"QPicture::play: Invalid command %d", c);
872 s.device()->seek(s.device()->pos()+len);
876 Q_ASSERT(qint32(s.device()->pos() - strm_pos) == len);
883
884
885
886
887
888
889
890
891
892
894int QPicture::metric(PaintDeviceMetric m)
const
897 QRect brect = boundingRect();
903 val = brect.height();
906 val =
int(25.4/qt_defaultDpiX()*brect.width());
909 val =
int(25.4/qt_defaultDpiY()*brect.height());
912 case PdmPhysicalDpiX:
913 val = qt_defaultDpiX();
916 case PdmPhysicalDpiY:
917 val = qt_defaultDpiY();
925 case PdmDevicePixelRatio:
928 case PdmDevicePixelRatioScaled:
929 val = 1 * QPaintDevice::devicePixelRatioFScale();
933 qWarning(
"QPicture::metric: Invalid metric command");
939
940
941
942
943
944
945
946
947
950
951
954
955
956
957QPicture& QPicture::operator=(
const QPicture &p)
964
965
966
969
970
971
972
973QPicturePrivate::QPicturePrivate()
975 in_memory_only(
false)
980
981
982
983
984QPicturePrivate::QPicturePrivate(
const QPicturePrivate &other)
987 formatOk(other.formatOk),
988 formatMinor(other.formatMinor),
990 override_rect(other.override_rect),
991 in_memory_only(
false)
993 pictb.setData(other.pictb.data(), other.pictb.size());
994 if (other.pictb.isOpen()) {
995 pictb.open(other.pictb.openMode());
996 pictb.seek(other.pictb.pos());
1001
1002
1003
1004
1006void QPicturePrivate::resetFormat()
1009 formatMajor = mfhdr_maj;
1010 formatMinor = mfhdr_min;
1015
1016
1017
1018
1019
1020
1021bool QPicturePrivate::checkFormat()
1026 if (pictb.size() == 0 || pictb.isOpen())
1029 pictb.open(QIODevice::ReadOnly);
1031 s.setDevice(&pictb);
1034 s.readRawData(mf_id, 4);
1035 int bufSize = pictb.buffer().size();
1036 if (memcmp(mf_id, qt_mfhdr_tag, 4) != 0 || bufSize < 12) {
1037 qWarning(
"QPicturePaintEngine::checkFormat: Incorrect header");
1042 int cs_start =
sizeof(quint32);
1043 int data_start = cs_start +
sizeof(quint16);
1045 const QByteArray buf = pictb.buffer();
1048 ccs = (quint16) qChecksum(QByteArrayView(buf.constData() + data_start, buf.size() - data_start));
1050 qWarning(
"QPicturePaintEngine::checkFormat: Invalid checksum %x, %x expected",
1056 quint16 major, minor;
1057 s >> major >> minor;
1058 if (major > mfhdr_maj) {
1059 qWarning(
"QPicturePaintEngine::checkFormat: Incompatible version %d.%d",
1064 s.setVersion(major != 4 ? major : 3);
1068 if (c == QPicturePrivate::PdcBegin) {
1069 if (!(major >= 1 && major <= 3)) {
1071 s >> l >> t >> w >> h;
1072 brect = QRect(l, t, w, h);
1075 qWarning(
"QPicturePaintEngine::checkFormat: Format error");
1082 formatMajor = major;
1083 formatMinor = minor;
1088QPaintEngine *QPicture::paintEngine()
const
1090 if (!d_func()->paintEngine)
1091 const_cast<QPicture*>(
this)->d_func()->paintEngine.reset(
new QPicturePaintEngine);
1092 return d_func()->paintEngine.data();
1096
1097
1099#ifndef QT_NO_DATASTREAM
1101
1102
1103
1104
1105
1107QDataStream &operator<<(QDataStream &s,
const QPicture &r)
1109 quint32 size = r.d_func()->pictb.buffer().size();
1115 s.writeRawData (r.d_func()->pictb.buffer(), r.d_func()->pictb.buffer().size());
1120
1121
1122
1123
1124
1131 sr.setDevice(&r.d_func()->pictb);
1132 sr.setVersion(r.d_func()->formatMajor);
1138 s.readRawData(data.data(), len);
1141 r.d_func()->pictb.setData(data);
1142 r.d_func()->resetFormat();
1152
1153
1154
1157
1158
1159
QPaintEngine * paintEngine() const override
int metric(PaintDeviceMetric m) const override
friend class QPaintEngine
QDataStream & operator>>(QDataStream &s, QKeyCombination &combination)
static const quint16 mfhdr_maj
QT_BEGIN_NAMESPACE void qt_format_text(const QFont &fnt, const QRectF &_r, int tf, int alignment, const QTextOption *opt, const QString &str, QRectF *brect, int tabstops, int *, int tabarraylen, QPainter *painter)
static const quint16 mfhdr_min
const char * qt_mfhdr_tag