5#include <private/qpicture_p.h>
9#include <private/qfactoryloader_p.h>
10#include <private/qpaintengine_pic_p.h>
11#include <private/qfont_p.h>
12#include <qguiapplication.h>
23#include <QtCore/private/qlocking_p.h>
33 const QTextOption *opt,
42
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
87
88
89
90
91
92
99
100
101
102
103
104
105
106
107
108
109
110
111
113QPicture::QPicture(
int formatVersion)
115 d_ptr(
new QPicturePrivate)
119 if (formatVersion == 0)
120 qWarning(
"QPicture: invalid format version 0");
123 if (formatVersion > 0 && formatVersion != (
int)mfhdr_maj) {
124 d->formatMajor = formatVersion;
133
134
135
136
138QPicture::QPicture(
const QPicture &pic)
139 : QPaintDevice(), d_ptr(pic.d_ptr)
144QPicture::QPicture(QPicturePrivate &dptr)
151
152
158
159
160int QPicture::devType()
const
162 return QInternal::Picture;
166
167
168
169
170
173
174
175
176
177
178
181
182
183
184
185
186
187
188
191bool QPicture::isNull()
const
193 return d_func()->pictb.buffer().isNull();
196uint QPicture::size()
const
198 return d_func()->pictb.buffer().size();
201const char* QPicture::data()
const
203 return d_func()->pictb.buffer();
206void QPicture::detach()
211bool QPicture::isDetached()
const
213 return d_func()->ref.loadRelaxed() == 1;
217
218
219
220
221
223void QPicture::setData(
const char* data, uint size)
226 d_func()->pictb.setData(data, size);
227 d_func()->resetFormat();
232
233
234
235
236
238bool QPicture::load(
const QString &fileName)
241 if (!f.open(QIODevice::ReadOnly)) {
242 operator=(QPicture());
249
250
251
252
254bool QPicture::load(QIODevice *dev)
257 QByteArray a = dev->readAll();
259 d_func()->pictb.setData(a);
260 return d_func()->checkFormat();
264
265
266
267
268
270bool QPicture::save(
const QString &fileName)
272 if (paintingActive()) {
273 qWarning(
"QPicture::save: still being painted on. "
274 "Call QPainter::end() first");
279 if (!f.open(QIODevice::WriteOnly))
285
286
287
288
290bool QPicture::save(QIODevice *dev)
292 if (paintingActive()) {
293 qWarning(
"QPicture::save: still being painted on. "
294 "Call QPainter::end() first");
298 dev->write(d_func()->pictb.buffer(), d_func()->pictb.buffer().size());
303
304
305
307QRect QPicture::boundingRect()
const
311 if (!d->override_rect.isEmpty())
312 return d->override_rect;
315 d_ptr->checkFormat();
321
322
323
325void QPicture::setBoundingRect(
const QRect &r)
327 d_func()->override_rect = r;
331
332
333
334
335
336
337
338
340bool QPicture::play(QPainter *painter)
344 if (d->pictb.size() == 0)
347 if (!d->formatOk && !d->checkFormat())
350 d->pictb.open(QIODevice::ReadOnly);
352 s.setDevice(&d->pictb);
353 s.device()->seek(10);
354 s.setVersion(d->formatMajor == 4 ? 3 : d->formatMajor);
359 Q_ASSERT(c == QPicturePrivate::PdcBegin);
361 if (d->formatMajor >= 4) {
363 s >> dummy >> dummy >> dummy >> dummy;
366 if (!exec(painter, s, nrecords)) {
367 qWarning(
"QPicture::play: Format error");
382 QFakeDevice() { dpi_x = qt_defaultDpiX(); dpi_y = qt_defaultDpiY(); }
386 int metric(PaintDeviceMetric m)
const override
389 case PdmPhysicalDpiX:
392 case PdmPhysicalDpiY:
396 return QPaintDevice::metric(m);
406
407
408
409
411bool QPicture::exec(QPainter *painter, QDataStream &s,
int nrecords)
420 qint16 i_16, i1_16, i2_16;
441 QTransform worldMatrix = painter->transform();
442 worldMatrix.scale(qreal(painter->device()->logicalDpiX()) / qreal(qt_defaultDpiX()),
443 qreal(painter->device()->logicalDpiY()) / qreal(qt_defaultDpiY()));
444 painter->setTransform(worldMatrix);
446 while (nrecords-- && !s.atEnd()) {
454 strm_pos = s.device()->pos();
457 case QPicturePrivate::PdcNOP:
459 case QPicturePrivate::PdcDrawPoint:
460 if (d->formatMajor <= 5) {
462 painter->drawPoint(ip);
465 painter->drawPoint(p);
468 case QPicturePrivate::PdcDrawPoints:
473 case QPicturePrivate::PdcDrawPath: {
476 painter->drawPath(path);
479 case QPicturePrivate::PdcDrawLine:
480 if (d->formatMajor <= 5) {
482 painter->drawLine(ip1, ip2);
485 painter->drawLine(p1, p2);
488 case QPicturePrivate::PdcDrawRect:
489 if (d->formatMajor <= 5) {
491 painter->drawRect(ir);
494 painter->drawRect(r);
497 case QPicturePrivate::PdcDrawRoundRect:
498 if (d->formatMajor <= 5) {
499 s >> ir >> i1_16 >> i2_16;
500 painter->drawRoundedRect(ir, i1_16, i2_16, Qt::RelativeSize);
502 s >> r >> i1_16 >> i2_16;
503 painter->drawRoundedRect(r, i1_16, i2_16, Qt::RelativeSize);
506 case QPicturePrivate::PdcDrawEllipse:
507 if (d->formatMajor <= 5) {
509 painter->drawEllipse(ir);
512 painter->drawEllipse(r);
515 case QPicturePrivate::PdcDrawArc:
516 if (d->formatMajor <= 5) {
523 painter->drawArc(r, i1_16, i2_16);
525 case QPicturePrivate::PdcDrawPie:
526 if (d->formatMajor <= 5) {
533 painter->drawPie(r, i1_16, i2_16);
535 case QPicturePrivate::PdcDrawChord:
536 if (d->formatMajor <= 5) {
543 painter->drawChord(r, i1_16, i2_16);
545 case QPicturePrivate::PdcDrawLineSegments:
547 painter->drawLines(ia);
550 case QPicturePrivate::PdcDrawPolyline:
551 if (d->formatMajor <= 5) {
553 painter->drawPolyline(ia);
557 painter->drawPolyline(a);
561 case QPicturePrivate::PdcDrawPolygon:
562 if (d->formatMajor <= 5) {
564 painter->drawPolygon(ia, i_8 ? Qt::WindingFill : Qt::OddEvenFill);
568 painter->drawPolygon(a, i_8 ? Qt::WindingFill : Qt::OddEvenFill);
572 case QPicturePrivate::PdcDrawCubicBezier: {
575 Q_ASSERT(ia.size() == 4);
576 path.moveTo(ia.value(0));
577 path.cubicTo(ia.value(1), ia.value(2), ia.value(3));
578 painter->strokePath(path, painter->pen());
582 case QPicturePrivate::PdcDrawText:
584 painter->drawText(ip, QString::fromLatin1(str1));
586 case QPicturePrivate::PdcDrawTextFormatted:
587 s >> ir >> i_16 >> str1;
588 painter->drawText(ir, i_16, QString::fromLatin1(str1));
590 case QPicturePrivate::PdcDrawText2:
591 if (d->formatMajor <= 5) {
593 painter->drawText(ip, str);
596 painter->drawText(p, str);
599 case QPicturePrivate::PdcDrawText2Formatted:
603 painter->drawText(ir, i_16, str);
605 case QPicturePrivate::PdcDrawTextItem: {
606 s >> p >> str >> font >> ul;
612 if (d->formatMajor >= 9) {
617 fake.setDpiX(qRound(dbl*qt_defaultDpiX()));
618 fake.setDpiY(qRound(dbl*qt_defaultDpiY()));
619 fnt = QFont(font, &fake);
622 qreal justificationWidth;
623 s >> justificationWidth;
625 int flags = Qt::TextSingleLine | Qt::TextDontClip | Qt::TextForceLeftToRight;
629 if (justificationWidth > 0) {
630 size.setWidth(justificationWidth);
631 flags |= Qt::TextJustificationForced;
632 alignment |= Qt::AlignJustify;
635 QPointF pt(p.x(), p.y());
636 if (d->formatMajor >= QDataStream::Qt_6_11) {
637 alignment |= Qt::AlignBaseline;
639 QFontMetrics fm(fnt);
640 pt.ry() -= fm.ascent();
656 QRectF(p, QSizeF(1, 1)),
657 Qt::TextSingleLine | Qt::TextDontClip,
670 case QPicturePrivate::PdcDrawPixmap: {
672 if (d->formatMajor < 4) {
674 painter->drawPixmap(ip, pixmap);
675 }
else if (d->formatMajor <= 5) {
677 painter->drawPixmap(ir, pixmap);
680 if (d->in_memory_only) {
682 s >> r >> index >> sr;
683 Q_ASSERT(index < d->pixmap_list.size());
684 pixmap = d->pixmap_list.value(index);
686 s >> r >> pixmap >> sr;
688 painter->drawPixmap(r, pixmap, sr);
692 case QPicturePrivate::PdcDrawTiledPixmap: {
694 if (d->in_memory_only) {
696 s >> r >> index >> p;
697 Q_ASSERT(index < d->pixmap_list.size());
698 pixmap = d->pixmap_list.value(index);
700 s >> r >> pixmap >> p;
702 painter->drawTiledPixmap(r, pixmap, p);
705 case QPicturePrivate::PdcDrawImage: {
707 if (d->formatMajor < 4) {
709 painter->drawImage(p, image);
710 }
else if (d->formatMajor <= 5){
712 painter->drawImage(ir, image, QRect(0, 0, ir.width(), ir.height()));
715 if (d->in_memory_only) {
717 s >> r >> index >> sr >> ul;
718 Q_ASSERT(index < d->image_list.size());
719 image = d->image_list.value(index);
721 s >> r >> image >> sr >> ul;
723 painter->drawImage(r, image, sr, Qt::ImageConversionFlags(ul));
727 case QPicturePrivate::PdcBegin:
729 if (!exec(painter, s, ul))
732 case QPicturePrivate::PdcEnd:
736 case QPicturePrivate::PdcSave:
739 case QPicturePrivate::PdcRestore:
742 case QPicturePrivate::PdcSetBkColor:
744 painter->setBackground(color);
746 case QPicturePrivate::PdcSetBkMode:
748 painter->setBackgroundMode((Qt::BGMode)i_8);
750 case QPicturePrivate::PdcSetROP:
753 case QPicturePrivate::PdcSetBrushOrigin:
754 if (d->formatMajor <= 5) {
756 painter->setBrushOrigin(ip);
759 painter->setBrushOrigin(p);
762 case QPicturePrivate::PdcSetFont:
764 painter->setFont(font);
766 case QPicturePrivate::PdcSetPen:
767 if (d->in_memory_only) {
770 Q_ASSERT(index < d->pen_list.size());
771 pen = d->pen_list.value(index);
775 painter->setPen(pen);
777 case QPicturePrivate::PdcSetBrush:
778 if (d->in_memory_only) {
781 Q_ASSERT(index < d->brush_list.size());
782 brush = d->brush_list.value(index);
786 painter->setBrush(brush);
788 case QPicturePrivate::PdcSetVXform:
790 painter->setViewTransformEnabled(i_8);
792 case QPicturePrivate::PdcSetWindow:
793 if (d->formatMajor <= 5) {
795 painter->setWindow(ir);
798 painter->setWindow(r.toRect());
801 case QPicturePrivate::PdcSetViewport:
802 if (d->formatMajor <= 5) {
804 painter->setViewport(ir);
807 painter->setViewport(r.toRect());
810 case QPicturePrivate::PdcSetWXform:
812 painter->setWorldMatrixEnabled(i_8);
814 case QPicturePrivate::PdcSetWMatrix:
815 if (d->formatMajor >= 8) {
818 s >> wmatrix[0] >> wmatrix[1]
819 >> wmatrix[2] >> wmatrix[3]
820 >> wmatrix[4] >> wmatrix[5] >> i_8;
821 matrix = QTransform(wmatrix[0], wmatrix[1],
822 wmatrix[2], wmatrix[3],
823 wmatrix[4], wmatrix[5]);
826 painter->setTransform(matrix * worldMatrix, i_8);
828 case QPicturePrivate::PdcSetClip:
830 painter->setClipping(i_8);
832 case QPicturePrivate::PdcSetClipRegion:
834 if (d->formatMajor >= 9) {
835 painter->setClipRegion(rgn, Qt::ClipOperation(i_8));
837 painter->setClipRegion(rgn);
840 case QPicturePrivate::PdcSetClipPath:
844 painter->setClipPath(path, Qt::ClipOperation(i_8));
847 case QPicturePrivate::PdcSetRenderHint:
849 painter->setRenderHint(QPainter::Antialiasing,
850 bool(ul & QPainter::Antialiasing));
851 painter->setRenderHint(QPainter::SmoothPixmapTransform,
852 bool(ul & QPainter::SmoothPixmapTransform));
853 painter->setRenderHint(QPainter::NonCosmeticBrushPatterns,
854 bool(ul & QPainter::NonCosmeticBrushPatterns));
856 case QPicturePrivate::PdcSetCompositionMode:
858 painter->setCompositionMode((QPainter::CompositionMode)ul);
860 case QPicturePrivate::PdcSetClipEnabled:
862 painter->setClipping(bl);
864 case QPicturePrivate::PdcSetOpacity:
866 painter->setOpacity(qreal(dbl));
869 qWarning(
"QPicture::play: Invalid command %d", c);
871 s.device()->seek(s.device()->pos()+len);
875 Q_ASSERT(qint32(s.device()->pos() - strm_pos) == len);
882
883
884
885
886
887
888
889
890
891
893int QPicture::metric(PaintDeviceMetric m)
const
896 QRect brect = boundingRect();
902 val = brect.height();
905 val =
int(25.4/qt_defaultDpiX()*brect.width());
908 val =
int(25.4/qt_defaultDpiY()*brect.height());
911 case PdmPhysicalDpiX:
912 val = qt_defaultDpiX();
915 case PdmPhysicalDpiY:
916 val = qt_defaultDpiY();
924 case PdmDevicePixelRatio:
927 case PdmDevicePixelRatioScaled:
928 val = 1 * QPaintDevice::devicePixelRatioFScale();
932 qWarning(
"QPicture::metric: Invalid metric command");
938
939
940
941
942
943
944
945
946
949
950
953
954
955
956QPicture& QPicture::operator=(
const QPicture &p)
963
964
965
968
969
970
971
972QPicturePrivate::QPicturePrivate()
973 : in_memory_only(
false)
978
979
980
981
982QPicturePrivate::QPicturePrivate(
const QPicturePrivate &other)
983 : trecs(other.trecs),
984 formatOk(other.formatOk),
985 formatMinor(other.formatMinor),
987 override_rect(other.override_rect),
988 in_memory_only(
false)
990 pictb.setData(other.pictb.data(), other.pictb.size());
991 if (other.pictb.isOpen()) {
992 pictb.open(other.pictb.openMode());
993 pictb.seek(other.pictb.pos());
998
999
1000
1001
1003void QPicturePrivate::resetFormat()
1006 formatMajor = mfhdr_maj;
1007 formatMinor = mfhdr_min;
1012
1013
1014
1015
1016
1017
1018bool QPicturePrivate::checkFormat()
1023 if (pictb.size() == 0 || pictb.isOpen())
1026 pictb.open(QIODevice::ReadOnly);
1028 s.setDevice(&pictb);
1031 s.readRawData(mf_id, 4);
1032 int bufSize = pictb.buffer().size();
1033 if (memcmp(mf_id, qt_mfhdr_tag, 4) != 0 || bufSize < 12) {
1034 qWarning(
"QPicturePaintEngine::checkFormat: Incorrect header");
1039 int cs_start =
sizeof(quint32);
1040 int data_start = cs_start +
sizeof(quint16);
1042 const QByteArray buf = pictb.buffer();
1045 ccs = (quint16) qChecksum(QByteArrayView(buf.constData() + data_start, buf.size() - data_start));
1047 qWarning(
"QPicturePaintEngine::checkFormat: Invalid checksum %x, %x expected",
1053 quint16 major, minor;
1054 s >> major >> minor;
1055 if (major > mfhdr_maj) {
1056 qWarning(
"QPicturePaintEngine::checkFormat: Incompatible version %d.%d",
1061 s.setVersion(major != 4 ? major : 3);
1065 if (c == QPicturePrivate::PdcBegin) {
1066 if (!(major >= 1 && major <= 3)) {
1068 s >> l >> t >> w >> h;
1069 brect = QRect(l, t, w, h);
1072 qWarning(
"QPicturePaintEngine::checkFormat: Format error");
1079 formatMajor = major;
1080 formatMinor = minor;
1085QPaintEngine *QPicture::paintEngine()
const
1087 if (!d_func()->paintEngine)
1088 const_cast<QPicture*>(
this)->d_func()->paintEngine.reset(
new QPicturePaintEngine);
1089 return d_func()->paintEngine.data();
1093
1094
1096#ifndef QT_NO_DATASTREAM
1098
1099
1100
1101
1102
1104QDataStream &operator<<(QDataStream &s,
const QPicture &r)
1106 quint32 size = r.d_func()->pictb.buffer().size();
1112 s.writeRawData (r.d_func()->pictb.buffer(), r.d_func()->pictb.buffer().size());
1117
1118
1119
1120
1121
1128 sr.setDevice(&r.d_func()->pictb);
1129 sr.setVersion(r.d_func()->formatMajor);
1135 s.readRawData(data.data(), len);
1138 r.d_func()->pictb.setData(data);
1139 r.d_func()->resetFormat();
1149
1150
1151
1154
1155
1156
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