1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the QtGui module of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
43 #include <private/qpicture_p.h>
47 #include <private/qfactoryloader_p.h>
48 #include <private/qpaintengine_pic_p.h>
49 #include <private/qfont_p.h>
50 #include <qguiapplication.h>
52 #include "qdatastream.h"
57 #include "qpainterpath.h"
64 void qt_format_text(const QFont &fnt, const QRectF &_r,
65 int tf, const QTextOption *opt, const QString& str, QRectF *brect,
66 int tabstops, int *, int tabarraylen,
71 \brief The QPicture class is a paint device that records and
72 replays QPainter commands.
78 A picture serializes painter commands to an IO device in a
79 platform-independent format. They are sometimes referred to as meta-files.
81 Qt pictures use a proprietary binary format. Unlike native picture
82 (meta-file) formats on many window systems, Qt pictures have no
83 limitations regarding their contents. Everything that can be
84 painted on a widget or pixmap (e.g., fonts, pixmaps, regions,
85 transformed graphics, etc.) can also be stored in a picture.
87 QPicture is resolution independent, i.e. a QPicture can be
88 displayed on different devices (for example svg, pdf, ps, printer
89 and screen) looking the same. This is, for instance, needed for
90 WYSIWYG print preview. QPicture runs in the default system dpi,
91 and scales the painter to match differences in resolution
92 depending on the window system.
94 Example of how to record a picture:
95 \snippet doc/src/snippets/picture/picture.cpp 0
97 Note that the list of painter commands is reset on each call to
98 the QPainter::begin() function.
100 Example of how to replay a picture:
101 \snippet doc/src/snippets/picture/picture.cpp 1
103 Pictures can also be drawn using play(). Some basic data about a
104 picture is available, for example, size(), isNull() and
110 const char *qt_mfhdr_tag = "QPIC"; // header tag
111 static const quint16 mfhdr_maj = 11; // major version #
112 static const quint16 mfhdr_min = 0; // minor version #
115 Constructs an empty picture.
117 The \a formatVersion parameter may be used to \e create a QPicture
118 that can be read by applications that are compiled with earlier
121 Note that the default formatVersion is -1 which signifies the
122 current release, i.e. for Qt 4.0 a formatVersion of 7 is the same
123 as the default formatVersion of -1.
125 Reading pictures generated by earlier versions of Qt is not
129 QPicture::QPicture(int formatVersion)
131 d_ptr(new QPicturePrivate)
135 if (formatVersion == 0)
136 qWarning("QPicture: invalid format version 0");
138 // still accept the 0 default from before Qt 3.0.
139 if (formatVersion > 0 && formatVersion != (int)mfhdr_maj) {
140 d->formatMajor = formatVersion;
149 Constructs a copy of \a pic.
151 This constructor is fast thanks to \l{implicit sharing}.
154 QPicture::QPicture(const QPicture &pic)
155 : QPaintDevice(), d_ptr(pic.d_ptr)
160 QPicture::QPicture(QPicturePrivate &dptr)
167 Destroys the picture.
169 QPicture::~QPicture()
176 int QPicture::devType() const
178 return QInternal::Picture;
182 \fn bool QPicture::isNull() const
184 Returns true if the picture contains no data; otherwise returns
189 \fn uint QPicture::size() const
191 Returns the size of the picture data.
197 \fn const char* QPicture::data() const
199 Returns a pointer to the picture data. The pointer is only valid
200 until the next non-const function is called on this picture. The
201 returned pointer is 0 if the picture contains no data.
207 bool QPicture::isNull() const
209 return d_func()->pictb.buffer().isNull();
212 uint QPicture::size() const
214 return d_func()->pictb.buffer().size();
217 const char* QPicture::data() const
219 return d_func()->pictb.buffer();
222 void QPicture::detach()
227 bool QPicture::isDetached() const
229 return d_func()->ref.load() == 1;
233 Sets the picture data directly from \a data and \a size. This
234 function copies the input data.
239 void QPicture::setData(const char* data, uint size)
242 d_func()->pictb.setData(data, size);
243 d_func()->resetFormat(); // we'll have to check
248 Loads a picture from the file specified by \a fileName and returns
249 true if successful; otherwise returns false.
251 Please note that the \a format parameter has been deprecated and
257 bool QPicture::load(const QString &fileName, const char *format)
260 if (!f.open(QIODevice::ReadOnly))
262 return load(&f, format);
268 \a dev is the device to use for loading.
271 bool QPicture::load(QIODevice *dev, const char *format)
274 #ifndef QT_NO_PICTUREIO
275 QPictureIO io(dev, format);
276 bool result = io.read();
278 operator=(io.picture());
285 qWarning("QPicture::load: No such picture format: %s", format);
291 QByteArray a = dev->readAll();
293 d_func()->pictb.setData(a); // set byte array in buffer
294 return d_func()->checkFormat();
298 Saves a picture to the file specified by \a fileName and returns
299 true if successful; otherwise returns false.
301 Please note that the \a format parameter has been deprecated and
307 bool QPicture::save(const QString &fileName, const char *format)
309 if (paintingActive()) {
310 qWarning("QPicture::save: still being painted on. "
311 "Call QPainter::end() first");
317 #ifndef QT_NO_PICTUREIO
318 QPictureIO io(fileName, format);
319 bool result = io.write();
321 operator=(io.picture());
327 qWarning("QPicture::save: No such picture format: %s", format);
333 if (!f.open(QIODevice::WriteOnly))
335 return save(&f, format);
341 \a dev is the device to use for saving.
344 bool QPicture::save(QIODevice *dev, const char *format)
346 if (paintingActive()) {
347 qWarning("QPicture::save: still being painted on. "
348 "Call QPainter::end() first");
353 #ifndef QT_NO_PICTUREIO
354 QPictureIO io(dev, format);
355 bool result = io.write();
357 operator=(io.picture());
363 qWarning("QPicture::save: No such picture format: %s", format);
368 dev->write(d_func()->pictb.buffer(), d_func()->pictb.buffer().size());
373 Returns the picture's bounding rectangle or an invalid rectangle
374 if the picture contains no data.
377 QRect QPicture::boundingRect() const
380 // Use override rect where possible.
381 if (!d->override_rect.isEmpty())
382 return d->override_rect;
385 d_ptr->checkFormat();
391 Sets the picture's bounding rectangle to \a r. The automatically
392 calculated value is overridden.
395 void QPicture::setBoundingRect(const QRect &r)
397 d_func()->override_rect = r;
401 Replays the picture using \a painter, and returns true if
402 successful; otherwise returns false.
404 This function does exactly the same as QPainter::drawPicture()
405 with (x, y) = (0, 0).
408 bool QPicture::play(QPainter *painter)
412 if (d->pictb.size() == 0) // nothing recorded
415 if (!d->formatOk && !d->checkFormat())
418 d->pictb.open(QIODevice::ReadOnly); // open buffer device
420 s.setDevice(&d->pictb); // attach data stream to buffer
421 s.device()->seek(10); // go directly to the data
422 s.setVersion(d->formatMajor == 4 ? 3 : d->formatMajor);
427 Q_ASSERT(c == QPicturePrivate::PdcBegin);
428 // bounding rect was introduced in ver 4. Read in checkFormat().
429 if (d->formatMajor >= 4) {
431 s >> dummy >> dummy >> dummy >> dummy;
434 if (!exec(painter, s, nrecords)) {
435 qWarning("QPicture::play: Format error");
440 return true; // no end-command
445 // QFakeDevice is used to create fonts with a custom DPI
447 class QFakeDevice : public QPaintDevice
450 QFakeDevice() { dpi_x = qt_defaultDpiX(); dpi_y = qt_defaultDpiY(); }
451 void setDpiX(int dpi) { dpi_x = dpi; }
452 void setDpiY(int dpi) { dpi_y = dpi; }
453 QPaintEngine *paintEngine() const { return 0; }
454 int metric(PaintDeviceMetric m) const
457 case PdmPhysicalDpiX:
460 case PdmPhysicalDpiY:
464 return QPaintDevice::metric(m);
475 Iterates over the internal picture data and draws the picture using
479 bool QPicture::exec(QPainter *painter, QDataStream &s, int nrecords)
482 #if defined(QT_DEBUG)
485 quint8 c; // command id
486 quint8 tiny_len; // 8-bit length descriptor
487 qint32 len; // 32-bit length descriptor
488 qint16 i_16, i1_16, i2_16; // parameters...
509 QTransform worldMatrix = painter->transform();
510 worldMatrix.scale(qreal(painter->device()->logicalDpiX()) / qreal(qt_defaultDpiX()),
511 qreal(painter->device()->logicalDpiY()) / qreal(qt_defaultDpiY()));
512 painter->setTransform(worldMatrix);
514 while (nrecords-- && !s.atEnd()) {
516 s >> tiny_len; // read param length
517 if (tiny_len == 255) // longer than 254 bytes
521 #if defined(QT_DEBUG)
522 strm_pos = s.device()->pos();
524 switch (c) { // exec cmd
525 case QPicturePrivate::PdcNOP:
527 case QPicturePrivate::PdcDrawPoint:
528 if (d->formatMajor <= 5) {
530 painter->drawPoint(ip);
533 painter->drawPoint(p);
536 case QPicturePrivate::PdcDrawPoints:
537 // ## implement me in the picture paint engine
538 // s >> a >> i1_32 >> i2_32;
539 // painter->drawPoints(a.mid(i1_32, i2_32));
541 case QPicturePrivate::PdcDrawPath: {
544 painter->drawPath(path);
547 case QPicturePrivate::PdcDrawLine:
548 if (d->formatMajor <= 5) {
550 painter->drawLine(ip1, ip2);
553 painter->drawLine(p1, p2);
556 case QPicturePrivate::PdcDrawRect:
557 if (d->formatMajor <= 5) {
559 painter->drawRect(ir);
562 painter->drawRect(r);
565 case QPicturePrivate::PdcDrawRoundRect:
566 if (d->formatMajor <= 5) {
567 s >> ir >> i1_16 >> i2_16;
568 painter->drawRoundedRect(ir, i1_16, i2_16, Qt::RelativeSize);
570 s >> r >> i1_16 >> i2_16;
571 painter->drawRoundedRect(r, i1_16, i2_16, Qt::RelativeSize);
574 case QPicturePrivate::PdcDrawEllipse:
575 if (d->formatMajor <= 5) {
577 painter->drawEllipse(ir);
580 painter->drawEllipse(r);
583 case QPicturePrivate::PdcDrawArc:
584 if (d->formatMajor <= 5) {
591 painter->drawArc(r, i1_16, i2_16);
593 case QPicturePrivate::PdcDrawPie:
594 if (d->formatMajor <= 5) {
601 painter->drawPie(r, i1_16, i2_16);
603 case QPicturePrivate::PdcDrawChord:
604 if (d->formatMajor <= 5) {
611 painter->drawChord(r, i1_16, i2_16);
613 case QPicturePrivate::PdcDrawLineSegments:
615 painter->drawLines(ia);
618 case QPicturePrivate::PdcDrawPolyline:
619 if (d->formatMajor <= 5) {
621 painter->drawPolyline(ia);
625 painter->drawPolyline(a);
629 case QPicturePrivate::PdcDrawPolygon:
630 if (d->formatMajor <= 5) {
632 painter->drawPolygon(ia, i_8 ? Qt::WindingFill : Qt::OddEvenFill);
636 painter->drawPolygon(a, i_8 ? Qt::WindingFill : Qt::OddEvenFill);
640 case QPicturePrivate::PdcDrawCubicBezier: {
643 Q_ASSERT(ia.size() == 4);
644 path.moveTo(ia.at(0));
645 path.cubicTo(ia.at(1), ia.at(2), ia.at(3));
646 painter->strokePath(path, painter->pen());
650 case QPicturePrivate::PdcDrawText:
652 painter->drawText(ip, QString::fromLatin1(str1));
654 case QPicturePrivate::PdcDrawTextFormatted:
655 s >> ir >> i_16 >> str1;
656 painter->drawText(ir, i_16, QString::fromLatin1(str1));
658 case QPicturePrivate::PdcDrawText2:
659 if (d->formatMajor <= 5) {
661 painter->drawText(ip, str);
664 painter->drawText(p, str);
667 case QPicturePrivate::PdcDrawText2Formatted:
671 painter->drawText(ir, i_16, str);
673 case QPicturePrivate::PdcDrawTextItem: {
674 s >> p >> str >> font >> ul;
676 // the text layout direction is not used here because it's already
677 // aligned when QPicturePaintEngine::drawTextItem() serializes the
678 // drawText() call, therefore ul is unsed in this context
680 if (d->formatMajor >= 9) {
685 fake.setDpiX(qRound(dbl*qt_defaultDpiX()));
686 fake.setDpiY(qRound(dbl*qt_defaultDpiY()));
687 fnt = QFont(font, &fake);
690 qreal justificationWidth;
691 s >> justificationWidth;
693 int flags = Qt::TextSingleLine | Qt::TextDontClip | Qt::TextForceLeftToRight;
696 if (justificationWidth > 0) {
697 size.setWidth(justificationWidth);
698 flags |= Qt::TextJustificationForced;
699 flags |= Qt::AlignJustify;
702 QFontMetrics fm(fnt);
703 QPointF pt(p.x(), p.y() - fm.ascent());
704 qt_format_text(fnt, QRectF(pt, size), flags, /*opt*/0,
705 str, /*brect=*/0, /*tabstops=*/0, /*...*/0, /*tabarraylen=*/0, painter);
707 qt_format_text(font, QRectF(p, QSizeF(1, 1)), Qt::TextSingleLine | Qt::TextDontClip, /*opt*/0,
708 str, /*brect=*/0, /*tabstops=*/0, /*...*/0, /*tabarraylen=*/0, painter);
713 case QPicturePrivate::PdcDrawPixmap: {
715 if (d->formatMajor < 4) {
717 painter->drawPixmap(ip, pixmap);
718 } else if (d->formatMajor <= 5) {
720 painter->drawPixmap(ir, pixmap);
723 if (d->in_memory_only) {
725 s >> r >> index >> sr;
726 Q_ASSERT(index < d->pixmap_list.size());
727 pixmap = d->pixmap_list.at(index);
729 s >> r >> pixmap >> sr;
731 painter->drawPixmap(r, pixmap, sr);
735 case QPicturePrivate::PdcDrawTiledPixmap: {
737 if (d->in_memory_only) {
739 s >> r >> index >> p;
740 Q_ASSERT(index < d->pixmap_list.size());
741 pixmap = d->pixmap_list.at(index);
743 s >> r >> pixmap >> p;
745 painter->drawTiledPixmap(r, pixmap, p);
748 case QPicturePrivate::PdcDrawImage: {
750 if (d->formatMajor < 4) {
752 painter->drawImage(p, image);
753 } else if (d->formatMajor <= 5){
755 painter->drawImage(ir, image, QRect(0, 0, ir.width(), ir.height()));
758 if (d->in_memory_only) {
760 s >> r >> index >> sr >> ul;
761 Q_ASSERT(index < d->image_list.size());
762 image = d->image_list.at(index);
764 s >> r >> image >> sr >> ul;
766 painter->drawImage(r, image, sr, Qt::ImageConversionFlags(ul));
770 case QPicturePrivate::PdcBegin:
771 s >> ul; // number of records
772 if (!exec(painter, s, ul))
775 case QPicturePrivate::PdcEnd:
779 case QPicturePrivate::PdcSave:
782 case QPicturePrivate::PdcRestore:
785 case QPicturePrivate::PdcSetBkColor:
787 painter->setBackground(color);
789 case QPicturePrivate::PdcSetBkMode:
791 painter->setBackgroundMode((Qt::BGMode)i_8);
793 case QPicturePrivate::PdcSetROP: // NOP
796 case QPicturePrivate::PdcSetBrushOrigin:
797 if (d->formatMajor <= 5) {
799 painter->setBrushOrigin(ip);
802 painter->setBrushOrigin(p);
805 case QPicturePrivate::PdcSetFont:
807 painter->setFont(font);
809 case QPicturePrivate::PdcSetPen:
810 if (d->in_memory_only) {
813 Q_ASSERT(index < d->pen_list.size());
814 pen = d->pen_list.at(index);
818 painter->setPen(pen);
820 case QPicturePrivate::PdcSetBrush:
821 if (d->in_memory_only) {
824 Q_ASSERT(index < d->brush_list.size());
825 brush = d->brush_list.at(index);
829 painter->setBrush(brush);
831 case QPicturePrivate::PdcSetVXform:
833 painter->setViewTransformEnabled(i_8);
835 case QPicturePrivate::PdcSetWindow:
836 if (d->formatMajor <= 5) {
838 painter->setWindow(ir);
841 painter->setWindow(r.toRect());
844 case QPicturePrivate::PdcSetViewport:
845 if (d->formatMajor <= 5) {
847 painter->setViewport(ir);
850 painter->setViewport(r.toRect());
853 case QPicturePrivate::PdcSetWXform:
855 painter->setMatrixEnabled(i_8);
857 case QPicturePrivate::PdcSetWMatrix:
858 if (d->formatMajor >= 8) {
862 matrix = QTransform(wmatrix);
864 // i_8 is always false due to updateXForm() in qpaintengine_pic.cpp
865 painter->setTransform(matrix * worldMatrix, i_8);
867 case QPicturePrivate::PdcSetClip:
869 painter->setClipping(i_8);
871 case QPicturePrivate::PdcSetClipRegion:
873 if (d->formatMajor >= 9) {
874 painter->setClipRegion(rgn, Qt::ClipOperation(i_8));
876 painter->setClipRegion(rgn);
879 case QPicturePrivate::PdcSetClipPath:
883 painter->setClipPath(path, Qt::ClipOperation(i_8));
886 case QPicturePrivate::PdcSetRenderHint:
888 painter->setRenderHint(QPainter::Antialiasing,
889 bool(ul & QPainter::Antialiasing));
890 painter->setRenderHint(QPainter::SmoothPixmapTransform,
891 bool(ul & QPainter::SmoothPixmapTransform));
893 case QPicturePrivate::PdcSetCompositionMode:
895 painter->setCompositionMode((QPainter::CompositionMode)ul);
897 case QPicturePrivate::PdcSetClipEnabled:
899 painter->setClipping(bl);
901 case QPicturePrivate::PdcSetOpacity:
903 painter->setOpacity(qreal(dbl));
906 qWarning("QPicture::play: Invalid command %d", c);
907 if (len) // skip unknown command
908 s.device()->seek(s.device()->pos()+len);
910 #if defined(QT_DEBUG)
911 //qDebug("device->at(): %i, strm_pos: %i len: %i", (int)s.device()->pos(), strm_pos, len);
912 Q_ASSERT(qint32(s.device()->pos() - strm_pos) == len);
921 Internal implementation of the virtual QPaintDevice::metric()
924 A picture has the following hard-coded values: numcolors=16777216
927 \a m is the metric to get.
930 int QPicture::metric(PaintDeviceMetric m) const
933 QRect brect = boundingRect();
939 val = brect.height();
942 val = int(25.4/qt_defaultDpiX()*brect.width());
945 val = int(25.4/qt_defaultDpiY()*brect.height());
948 case PdmPhysicalDpiX:
949 val = qt_defaultDpiX();
952 case PdmPhysicalDpiY:
953 val = qt_defaultDpiY();
963 qWarning("QPicture::metric: Invalid metric command");
969 \fn void QPicture::detach()
971 Detaches from shared picture data and makes sure that this picture
972 is the only one referring to the data.
974 If multiple pictures share common data, this picture makes a copy
975 of the data and detaches itself from the sharing mechanism.
976 Nothing is done if there is just a single reference.
979 /*! \fn bool QPicture::isDetached() const
984 Assigns picture \a p to this picture and returns a reference to
987 QPicture& QPicture::operator=(const QPicture &p)
994 \fn void QPicture::swap(QPicture &other)
997 Swaps picture \a other with this picture. This operation is very
998 fast and never fails.
1004 Constructs a QPicturePrivate
1006 QPicturePrivate::QPicturePrivate()
1007 : in_memory_only(false)
1014 Copy-Constructs a QPicturePrivate. Needed when detaching.
1016 QPicturePrivate::QPicturePrivate(const QPicturePrivate &other)
1017 : trecs(other.trecs),
1018 formatOk(other.formatOk),
1019 formatMinor(other.formatMinor),
1021 override_rect(other.override_rect),
1022 in_memory_only(false)
1024 pictb.setData(other.pictb.data(), other.pictb.size());
1025 if (other.pictb.isOpen()) {
1026 pictb.open(other.pictb.openMode());
1027 pictb.seek(other.pictb.pos());
1034 Sets formatOk to false and resets the format version numbers to default
1037 void QPicturePrivate::resetFormat()
1040 formatMajor = mfhdr_maj;
1041 formatMinor = mfhdr_min;
1048 Checks data integrity and format version number. Set formatOk to
1049 true on success, to false otherwise. Returns the resulting formatOk
1052 bool QPicturePrivate::checkFormat()
1056 // can't check anything in an empty buffer
1057 if (pictb.size() == 0 || pictb.isOpen())
1060 pictb.open(QIODevice::ReadOnly); // open buffer device
1062 s.setDevice(&pictb); // attach data stream to buffer
1064 char mf_id[4]; // picture header tag
1065 s.readRawData(mf_id, 4); // read actual tag
1066 if (memcmp(mf_id, qt_mfhdr_tag, 4) != 0) { // wrong header id
1067 qWarning("QPicturePaintEngine::checkFormat: Incorrect header");
1072 int cs_start = sizeof(quint32); // pos of checksum word
1073 int data_start = cs_start + sizeof(quint16);
1075 QByteArray buf = pictb.buffer(); // pointer to data
1077 s >> cs; // read checksum
1078 ccs = (quint16) qChecksum(buf.constData() + data_start, buf.size() - data_start);
1080 qWarning("QPicturePaintEngine::checkFormat: Invalid checksum %x, %x expected",
1086 quint16 major, minor;
1087 s >> major >> minor; // read version number
1088 if (major > mfhdr_maj) { // new, incompatible version
1089 qWarning("QPicturePaintEngine::checkFormat: Incompatible version %d.%d",
1094 s.setVersion(major != 4 ? major : 3);
1098 if (c == QPicturePrivate::PdcBegin) {
1099 if (!(major >= 1 && major <= 3)) {
1101 s >> l >> t >> w >> h;
1102 brect = QRect(l, t, w, h);
1105 qWarning("QPicturePaintEngine::checkFormat: Format error");
1111 formatOk = true; // picture seems to be ok
1112 formatMajor = major;
1113 formatMinor = minor;
1118 QPaintEngine *QPicture::paintEngine() const
1120 if (!d_func()->paintEngine)
1121 const_cast<QPicture*>(this)->d_func()->paintEngine.reset(new QPicturePaintEngine);
1122 return d_func()->paintEngine.data();
1125 /*****************************************************************************
1126 QPicture stream functions
1127 *****************************************************************************/
1129 #ifndef QT_NO_DATASTREAM
1133 Writes picture \a r to the stream \a s and returns a reference to
1137 QDataStream &operator<<(QDataStream &s, const QPicture &r)
1139 quint32 size = r.d_func()->pictb.buffer().size();
1144 // just write the whole buffer to the stream
1145 s.writeRawData (r.d_func()->pictb.buffer(), r.d_func()->pictb.buffer().size());
1152 Reads a picture from the stream \a s into picture \a r and returns
1153 a reference to the stream.
1156 QDataStream &operator>>(QDataStream &s, QPicture &r)
1160 // "init"; this code is similar to the beginning of QPicture::cmd()
1161 sr.setDevice(&r.d_func()->pictb);
1162 sr.setVersion(r.d_func()->formatMajor);
1168 s.readRawData(data.data(), len);
1171 r.d_func()->pictb.setData(data);
1172 r.d_func()->resetFormat();
1175 #endif // QT_NO_DATASTREAM
1178 #ifndef QT_NO_PICTUREIO
1180 QT_BEGIN_INCLUDE_NAMESPACE
1181 #include "qregexp.h"
1182 #include "qpictureformatplugin.h"
1183 QT_END_INCLUDE_NAMESPACE
1188 Returns a string that specifies the picture format of the file \a
1189 fileName, or 0 if the file cannot be read or if the format is not
1195 const char* QPicture::pictureFormat(const QString &fileName)
1197 return QPictureIO::pictureFormat(fileName);
1203 Returns a list of picture formats that are supported for picture
1206 \sa outputFormats() inputFormatList() QPictureIO
1208 QList<QByteArray> QPicture::inputFormats()
1210 return QPictureIO::inputFormats();
1213 static QStringList qToStringList(const QList<QByteArray> arr)
1216 for (int i = 0; i < arr.count(); ++i)
1217 list.append(QString::fromLatin1(arr.at(i)));
1224 Returns a list of picture formats that are supported for picture
1227 Note that if you want to iterate over the list, you should iterate
1229 \snippet doc/src/snippets/picture/picture.cpp 2
1231 \sa outputFormatList() inputFormats() QPictureIO
1233 QStringList QPicture::inputFormatList()
1235 return qToStringList(QPictureIO::inputFormats());
1242 Returns a list of picture formats that are supported for picture
1245 Note that if you want to iterate over the list, you should iterate
1247 \snippet doc/src/snippets/picture/picture.cpp 3
1249 \sa inputFormatList() outputFormats() QPictureIO
1251 QStringList QPicture::outputFormatList()
1253 return qToStringList(QPictureIO::outputFormats());
1259 Returns a list of picture formats that are supported for picture
1262 \sa inputFormats() outputFormatList() QPictureIO
1264 QList<QByteArray> QPicture::outputFormats()
1266 return QPictureIO::outputFormats();
1269 /*****************************************************************************
1270 QPictureIO member functions
1271 *****************************************************************************/
1278 \brief The QPictureIO class contains parameters for loading and
1284 QPictureIO contains a QIODevice object that is used for picture data
1285 I/O. The programmer can install new picture file formats in addition
1286 to those that Qt provides.
1288 You don't normally need to use this class; QPicture::load(),
1291 \sa QPicture QPixmap QFile
1294 struct QPictureIOData
1296 QPicture pi; // picture
1297 int iostat; // IO status
1298 QByteArray frmt; // picture format
1299 QIODevice *iodev; // IO device
1300 QString fname; // file name
1301 QString descr; // picture description
1302 const char *parameters;
1308 Constructs a QPictureIO object with all parameters set to zero.
1311 QPictureIO::QPictureIO()
1317 Constructs a QPictureIO object with the I/O device \a ioDevice and a
1321 QPictureIO::QPictureIO(QIODevice *ioDevice, const char *format)
1324 d->iodev = ioDevice;
1329 Constructs a QPictureIO object with the file name \a fileName and a
1333 QPictureIO::QPictureIO(const QString &fileName, const char* format)
1337 d->fname = fileName;
1341 Contains initialization common to all QPictureIO constructors.
1344 void QPictureIO::init()
1346 d = new QPictureIOData();
1348 d->quality = -1; // default quality of the current format
1355 Destroys the object and all related data.
1358 QPictureIO::~QPictureIO()
1361 delete [] (char*)d->parameters;
1366 /*****************************************************************************
1367 QPictureIO picture handler functions
1368 *****************************************************************************/
1370 class QPictureHandler
1373 QPictureHandler(const char *f, const char *h, const QByteArray& fl,
1374 picture_io_handler r, picture_io_handler w);
1375 QByteArray format; // picture format
1376 QRegExp header; // picture header pattern
1377 enum TMode { Untranslated=0, TranslateIn, TranslateInOut } text_mode;
1378 picture_io_handler read_picture; // picture read function
1379 picture_io_handler write_picture; // picture write function
1380 bool obsolete; // support not "published"
1383 QPictureHandler::QPictureHandler(const char *f, const char *h, const QByteArray& fl,
1384 picture_io_handler r, picture_io_handler w)
1385 : format(f), header(QString::fromLatin1(h))
1387 text_mode = Untranslated;
1388 if (fl.contains('t'))
1389 text_mode = TranslateIn;
1390 else if (fl.contains('T'))
1391 text_mode = TranslateInOut;
1392 obsolete = fl.contains('O');
1397 typedef QList<QPictureHandler *> QPHList;
1398 Q_GLOBAL_STATIC(QPHList, pictureHandlers)
1400 void qt_init_picture_plugins()
1402 #ifndef QT_NO_LIBRARY
1403 static QBasicMutex mutex;
1404 QMutexLocker locker(&mutex);
1405 static QFactoryLoader loader(QPictureFormatInterface_iid,
1406 QStringLiteral("/pictureformats"));
1407 QStringList keys = loader.keys();
1408 for (int i = 0; i < keys.count(); ++i)
1409 if (QPictureFormatInterface *format = qobject_cast<QPictureFormatInterface*>(loader.instance(keys.at(i))))
1410 format->installIOHandler(keys.at(i));
1414 static void cleanup()
1416 // make sure that picture handlers are delete before plugin manager
1417 if (QPHList *list = pictureHandlers()) {
1423 void qt_init_picture_handlers() // initialize picture handlers
1425 static QBasicAtomicInt done = Q_BASIC_ATOMIC_INITIALIZER(0);
1426 if (done.testAndSetRelaxed(0, 1)) {
1427 qAddPostRoutine(cleanup);
1431 static QPictureHandler *get_picture_handler(const char *format)
1432 { // get pointer to handler
1433 qt_init_picture_handlers();
1434 qt_init_picture_plugins();
1435 if (QPHList *list = pictureHandlers()) {
1436 for (int i = 0; i < list->size(); ++i) {
1437 if (list->at(i)->format == format)
1441 return 0; // no such handler
1446 Defines a picture I/O handler for the picture format called \a
1447 format, which is recognized using the regular
1448 expression defined in \a header, read using \a readPicture and
1449 written using \a writePicture.
1451 \a flags is a string of single-character flags for this format.
1452 The only flag defined currently is T (upper case), so the only
1453 legal value for \a flags are "T" and the empty string. The "T"
1454 flag means that the picture file is a text file, and Qt should treat
1455 all newline conventions as equivalent. (XPM files and some PPM
1456 files are text files for example.)
1458 \a format is used to select a handler to write a QPicture; \a header
1459 is used to select a handler to read an picture file.
1461 If \a readPicture is a null pointer, the QPictureIO will not be able
1462 to read pictures in \a format. If \a writePicture is a null pointer,
1463 the QPictureIO will not be able to write pictures in \a format. If
1464 both are null, the QPictureIO object is valid but useless.
1467 \snippet doc/src/snippets/picture/picture.cpp 6
1469 \snippet doc/src/snippets/picture/picture.cpp 7
1471 \snippet doc/src/snippets/picture/picture.cpp 8
1473 Before the regular expression test, all the 0 bytes in the file header are
1474 converted to 1 bytes. This is done because when Qt was ASCII-based, QRegExp
1475 could not handle 0 bytes in strings.
1477 The regexp is only applied on the first 14 bytes of the file.
1479 (Note that if one handlerIO supports writing a format and another
1480 supports reading it, Qt supports both reading and writing. If two
1481 handlers support the same operation, Qt chooses one arbitrarily.)
1484 void QPictureIO::defineIOHandler(const char *format,
1487 picture_io_handler readPicture,
1488 picture_io_handler writePicture)
1490 qt_init_picture_handlers();
1491 if (QPHList *list = pictureHandlers()) {
1493 p = new QPictureHandler(format, header, QByteArray(flags), readPicture, writePicture);
1499 /*****************************************************************************
1500 QPictureIO normal member functions
1501 *****************************************************************************/
1504 Returns the picture currently set.
1508 const QPicture &QPictureIO::picture() const { return d->pi; }
1511 Returns the picture's IO status. A non-zero value indicates an
1512 error, whereas 0 means that the IO operation was successful.
1516 int QPictureIO::status() const { return d->iostat; }
1519 Returns the picture format string or 0 if no format has been
1522 const char *QPictureIO::format() const { return d->frmt; }
1525 Returns the IO device currently set.
1529 QIODevice *QPictureIO::ioDevice() const { return d->iodev; }
1532 Returns the file name currently set.
1536 QString QPictureIO::fileName() const { return d->fname; }
1540 Returns the picture description string.
1542 \sa setDescription()
1544 QString QPictureIO::description() const { return d->descr; }
1547 Sets the picture to \a picture.
1551 void QPictureIO::setPicture(const QPicture &picture)
1557 Sets the picture IO status to \a status. A non-zero value indicates
1558 an error, whereas 0 means that the IO operation was successful.
1562 void QPictureIO::setStatus(int status)
1568 Sets the picture format to \a format for the picture to be read or
1571 It is necessary to specify a format before writing an picture, but
1572 it is not necessary to specify a format before reading an picture.
1574 If no format has been set, Qt guesses the picture format before
1575 reading it. If a format is set the picture will only be read if it
1578 \sa read() write() format()
1580 void QPictureIO::setFormat(const char *format)
1586 Sets the IO device to be used for reading or writing an picture.
1588 Setting the IO device allows pictures to be read/written to any
1589 block-oriented QIODevice.
1591 If \a ioDevice is not null, this IO device will override file name
1596 void QPictureIO::setIODevice(QIODevice *ioDevice)
1598 d->iodev = ioDevice;
1602 Sets the name of the file to read or write an picture from to \a
1607 void QPictureIO::setFileName(const QString &fileName)
1609 d->fname = fileName;
1613 Returns the quality of the written picture, related to the
1616 \sa setQuality() QPicture::save()
1618 int QPictureIO::quality() const
1624 Sets the quality of the written picture to \a q, related to the
1627 \a q must be in the range -1..100. Specify 0 to obtain small
1628 compressed files, 100 for large uncompressed files. (-1 signifies
1629 the default compression.)
1631 \sa quality() QPicture::save()
1634 void QPictureIO::setQuality(int q)
1640 Returns the picture's parameters string.
1645 const char *QPictureIO::parameters() const
1647 return d->parameters;
1651 Sets the picture's parameter string to \a parameters. This is for
1652 picture handlers that require special parameters.
1654 Although the current picture formats supported by Qt ignore the
1655 parameters string, it may be used in future extensions or by
1656 contributions (for example, JPEG).
1661 void QPictureIO::setParameters(const char *parameters)
1664 delete [] (char*)d->parameters;
1665 d->parameters = qstrdup(parameters);
1669 Sets the gamma value at which the picture will be viewed to \a
1670 gamma. If the picture format stores a gamma value for which the
1671 picture is intended to be used, then this setting will be used to
1672 modify the picture. Setting to 0.0 will disable gamma correction
1673 (i.e. any specification in the file will be ignored).
1675 The default value is 0.0.
1679 void QPictureIO::setGamma(float gamma)
1685 Returns the gamma value at which the picture will be viewed.
1689 float QPictureIO::gamma() const
1695 Sets the picture description string for picture handlers that support
1696 picture descriptions to \a description.
1698 Currently, no picture format supported by Qt uses the description
1702 void QPictureIO::setDescription(const QString &description)
1704 d->descr = description;
1709 Returns a string that specifies the picture format of the file \a
1710 fileName, or null if the file cannot be read or if the format is
1714 QByteArray QPictureIO::pictureFormat(const QString &fileName)
1716 QFile file(fileName);
1718 if (!file.open(QIODevice::ReadOnly))
1720 format = pictureFormat(&file);
1728 Returns a string that specifies the picture format of the picture read
1729 from IO device \a d, or 0 if the device cannot be read or if the
1730 format is not recognized.
1732 Make sure that \a d is at the right position in the device (for
1733 example, at the beginning of the file).
1738 QByteArray QPictureIO::pictureFormat(QIODevice *d)
1740 // if you change this change the documentation for defineIOHandler()
1741 const int buflen = 14;
1745 qt_init_picture_handlers();
1746 qt_init_picture_plugins();
1747 int pos = d->pos(); // save position
1748 int rdlen = d->read(buf, buflen); // read a few bytes
1751 if (rdlen != buflen)
1754 memcpy(buf2, buf, buflen);
1756 for (int n = 0; n < rdlen; n++)
1760 buf[rdlen - 1] = '\0';
1761 QString bufStr = QString::fromLatin1(buf);
1762 if (QPHList *list = pictureHandlers()) {
1763 for (int i = 0; i < list->size(); ++i) {
1764 if (list->at(i)->header.indexIn(bufStr) != -1) { // try match with headers
1765 format = list->at(i)->format;
1771 d->seek(pos); // restore position
1776 Returns a sorted list of picture formats that are supported for
1779 QList<QByteArray> QPictureIO::inputFormats()
1781 QList<QByteArray> result;
1783 qt_init_picture_handlers();
1784 qt_init_picture_plugins();
1786 if (QPHList *list = pictureHandlers()) {
1787 for (int i = 0; i < list->size(); ++i) {
1788 QPictureHandler *p = list->at(i);
1789 if (p->read_picture && !p->obsolete && !result.contains(p->format))
1790 result.append(p->format);
1799 Returns a sorted list of picture formats that are supported for
1802 QList<QByteArray> QPictureIO::outputFormats()
1804 qt_init_picture_handlers();
1805 qt_init_picture_plugins();
1807 QList<QByteArray> result;
1808 if (QPHList *list = pictureHandlers()) {
1809 for (int i = 0; i < list->size(); ++i) {
1810 QPictureHandler *p = list->at(i);
1811 if (p->write_picture && !p->obsolete && !result.contains(p->format))
1812 result.append(p->format);
1821 Reads an picture into memory and returns true if the picture was
1822 successfully read; otherwise returns false.
1824 Before reading an picture you must set an IO device or a file name.
1825 If both an IO device and a file name have been set, the IO device
1828 Setting the picture file format string is optional.
1830 Note that this function does \e not set the \link format()
1831 format\endlink used to read the picture. If you need that
1832 information, use the pictureFormat() static functions.
1836 \snippet doc/src/snippets/picture/picture.cpp 4
1838 \sa setIODevice() setFileName() setFormat() write() QPixmap::load()
1840 bool QPictureIO::read()
1843 const char *picture_format;
1846 if (d->iodev) { // read from io device
1848 } else if (!d->fname.isEmpty()) { // read from file
1849 file.setFileName(d->fname);
1850 if (!file.open(QIODevice::ReadOnly))
1851 return false; // cannot open file
1853 } else { // no file name or io device
1856 if (d->frmt.isEmpty()) {
1857 // Try to guess format
1858 picture_format = pictureFormat(d->iodev); // get picture format
1859 if (!picture_format) {
1860 if (file.isOpen()) { // unknown format
1867 picture_format = d->frmt;
1870 h = get_picture_handler(picture_format);
1871 if (file.isOpen()) {
1872 #if !defined(Q_OS_UNIX)
1873 if (h && h->text_mode) { // reopen in translated mode
1875 file.open(QIODevice::ReadOnly | QIODevice::Text);
1879 file.seek(0); // position to start
1881 d->iostat = 1; // assume error
1883 if (h && h->read_picture)
1884 (*h->read_picture)(this);
1886 if (file.isOpen()) { // picture was read using file
1890 return d->iostat == 0; // picture successfully read?
1895 Writes an picture to an IO device and returns true if the picture was
1896 successfully written; otherwise returns false.
1898 Before writing an picture you must set an IO device or a file name.
1899 If both an IO device and a file name have been set, the IO device
1902 The picture will be written using the specified picture format.
1905 \snippet doc/src/snippets/picture/picture.cpp 5
1907 \sa setIODevice() setFileName() setFormat() read() QPixmap::save()
1909 bool QPictureIO::write()
1911 if (d->frmt.isEmpty())
1913 QPictureHandler *h = get_picture_handler(d->frmt);
1914 if (!h || !h->write_picture) {
1915 qWarning("QPictureIO::write: No such picture format handler: %s",
1920 if (!d->iodev && !d->fname.isEmpty()) {
1921 file.setFileName(d->fname);
1922 bool translate = h->text_mode==QPictureHandler::TranslateInOut;
1923 QIODevice::OpenMode fmode = translate ? QIODevice::WriteOnly | QIODevice::Text : QIODevice::OpenMode(QIODevice::WriteOnly);
1924 if (!file.open(fmode)) // couldn't create file
1929 (*h->write_picture)(this);
1930 if (file.isOpen()) { // picture was written using file
1934 return d->iostat == 0; // picture successfully written?
1936 #endif //QT_NO_PICTUREIO
1940 #endif // QT_NO_PICTURE
1943 \typedef QPicture::DataPtr
1948 \fn DataPtr &QPicture::data_ptr()