8bb9f211e8c960471a47f4b0ee01406461944f4f
[profile/ivi/qtbase.git] / src / gui / image / qpicture.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the QtGui module of the Qt Toolkit.
7 **
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.
16 **
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.
20 **
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.
28 **
29 ** Other Usage
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.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qpicture.h"
43 #include <private/qpicture_p.h>
44
45 #ifndef QT_NO_PICTURE
46
47 #include <private/qfactoryloader_p.h>
48 #include <private/qpaintengine_pic_p.h>
49 #include <private/qfont_p.h>
50 #include <qguiapplication.h>
51
52 #include "qdatastream.h"
53 #include "qfile.h"
54 #include "qimage.h"
55 #include "qmutex.h"
56 #include "qpainter.h"
57 #include "qpainterpath.h"
58 #include "qpixmap.h"
59 #include "qregion.h"
60 #include "qdebug.h"
61
62 QT_BEGIN_NAMESPACE
63
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,
67                     QPainter *painter);
68
69 /*!
70     \class QPicture
71     \brief The QPicture class is a paint device that records and
72     replays QPainter commands.
73
74     \ingroup painting
75     \ingroup shared
76
77
78     A picture serializes painter commands to an IO device in a
79     platform-independent format. They are sometimes referred to as meta-files.
80
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.
86
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.
93
94     Example of how to record a picture:
95     \snippet doc/src/snippets/picture/picture.cpp 0
96
97     Note that the list of painter commands is reset on each call to
98     the QPainter::begin() function.
99
100     Example of how to replay a picture:
101     \snippet doc/src/snippets/picture/picture.cpp 1
102
103     Pictures can also be drawn using play(). Some basic data about a
104     picture is available, for example, size(), isNull() and
105     boundingRect().
106
107     \sa QMovie
108 */
109
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 #
113
114 /*!
115     Constructs an empty picture.
116
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
119     versions of Qt.
120
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.
124
125     Reading pictures generated by earlier versions of Qt is not
126     supported in Qt 4.0.
127 */
128
129 QPicture::QPicture(int formatVersion)
130     : QPaintDevice(),
131       d_ptr(new QPicturePrivate)
132 {
133     Q_D(QPicture);
134
135     if (formatVersion == 0)
136         qWarning("QPicture: invalid format version 0");
137
138     // still accept the 0 default from before Qt 3.0.
139     if (formatVersion > 0 && formatVersion != (int)mfhdr_maj) {
140         d->formatMajor = formatVersion;
141         d->formatMinor = 0;
142         d->formatOk = false;
143     } else {
144         d->resetFormat();
145     }
146 }
147
148 /*!
149     Constructs a copy of \a pic.
150
151     This constructor is fast thanks to \l{implicit sharing}.
152 */
153
154 QPicture::QPicture(const QPicture &pic)
155     : QPaintDevice(), d_ptr(pic.d_ptr)
156 {
157 }
158
159 /*! \internal */
160 QPicture::QPicture(QPicturePrivate &dptr)
161     : QPaintDevice(),
162       d_ptr(&dptr)
163 {
164 }
165
166 /*!
167     Destroys the picture.
168 */
169 QPicture::~QPicture()
170 {
171 }
172
173 /*!
174   \internal
175 */
176 int QPicture::devType() const
177 {
178     return QInternal::Picture;
179 }
180
181 /*!
182     \fn bool QPicture::isNull() const
183
184     Returns true if the picture contains no data; otherwise returns
185     false.
186 */
187
188 /*!
189     \fn uint QPicture::size() const
190
191     Returns the size of the picture data.
192
193     \sa data()
194 */
195
196 /*!
197     \fn const char* QPicture::data() const
198
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.
202
203     \sa size(), isNull()
204 */
205
206
207 bool QPicture::isNull() const
208 {
209     return d_func()->pictb.buffer().isNull();
210 }
211
212 uint QPicture::size() const
213 {
214     return d_func()->pictb.buffer().size();
215 }
216
217 const char* QPicture::data() const
218 {
219     return d_func()->pictb.buffer();
220 }
221
222 void QPicture::detach()
223 {
224     d_ptr.detach();
225 }
226
227 bool QPicture::isDetached() const
228 {
229     return d_func()->ref.load() == 1;
230 }
231
232 /*!
233     Sets the picture data directly from \a data and \a size. This
234     function copies the input data.
235
236     \sa data(), size()
237 */
238
239 void QPicture::setData(const char* data, uint size)
240 {
241     detach();
242     d_func()->pictb.setData(data, size);
243     d_func()->resetFormat();                                // we'll have to check
244 }
245
246
247 /*!
248     Loads a picture from the file specified by \a fileName and returns
249     true if successful; otherwise returns false.
250
251     Please note that the \a format parameter has been deprecated and
252     will have no effect.
253
254     \sa save()
255 */
256
257 bool QPicture::load(const QString &fileName, const char *format)
258 {
259     QFile f(fileName);
260     if (!f.open(QIODevice::ReadOnly))
261         return false;
262     return load(&f, format);
263 }
264
265 /*!
266     \overload
267
268     \a dev is the device to use for loading.
269 */
270
271 bool QPicture::load(QIODevice *dev, const char *format)
272 {
273     if(format) {
274 #ifndef QT_NO_PICTUREIO
275         QPictureIO io(dev, format);
276         bool result = io.read();
277         if (result) {
278             operator=(io.picture());
279
280         } else if (format)
281 #else
282             bool result = false;
283 #endif
284         {
285             qWarning("QPicture::load: No such picture format: %s", format);
286         }
287         return result;
288     }
289
290     detach();
291     QByteArray a = dev->readAll();
292
293     d_func()->pictb.setData(a);                        // set byte array in buffer
294     return d_func()->checkFormat();
295 }
296
297 /*!
298     Saves a picture to the file specified by \a fileName and returns
299     true if successful; otherwise returns false.
300
301     Please note that the \a format parameter has been deprecated and
302     will have no effect.
303
304     \sa load()
305 */
306
307 bool QPicture::save(const QString &fileName, const char *format)
308 {
309     if (paintingActive()) {
310         qWarning("QPicture::save: still being painted on. "
311                   "Call QPainter::end() first");
312         return false;
313     }
314
315
316     if(format) {
317 #ifndef QT_NO_PICTUREIO
318         QPictureIO io(fileName, format);
319         bool result = io.write();
320         if (result) {
321             operator=(io.picture());
322         } else if (format)
323 #else
324         bool result = false;
325 #endif
326         {
327             qWarning("QPicture::save: No such picture format: %s", format);
328         }
329         return result;
330     }
331
332     QFile f(fileName);
333     if (!f.open(QIODevice::WriteOnly))
334         return false;
335     return save(&f, format);
336 }
337
338 /*!
339     \overload
340
341     \a dev is the device to use for saving.
342 */
343
344 bool QPicture::save(QIODevice *dev, const char *format)
345 {
346     if (paintingActive()) {
347         qWarning("QPicture::save: still being painted on. "
348                   "Call QPainter::end() first");
349         return false;
350     }
351
352     if(format) {
353 #ifndef QT_NO_PICTUREIO
354         QPictureIO io(dev, format);
355         bool result = io.write();
356         if (result) {
357             operator=(io.picture());
358         } else if (format)
359 #else
360         bool result = false;
361 #endif
362         {
363             qWarning("QPicture::save: No such picture format: %s", format);
364         }
365         return result;
366     }
367
368     dev->write(d_func()->pictb.buffer(), d_func()->pictb.buffer().size());
369     return true;
370 }
371
372 /*!
373     Returns the picture's bounding rectangle or an invalid rectangle
374     if the picture contains no data.
375 */
376
377 QRect QPicture::boundingRect() const
378 {
379     Q_D(const QPicture);
380     // Use override rect where possible.
381     if (!d->override_rect.isEmpty())
382         return d->override_rect;
383
384     if (!d->formatOk)
385         d_ptr->checkFormat();
386
387     return d->brect;
388 }
389
390 /*!
391     Sets the picture's bounding rectangle to \a r. The automatically
392     calculated value is overridden.
393 */
394
395 void QPicture::setBoundingRect(const QRect &r)
396 {
397     d_func()->override_rect = r;
398 }
399
400 /*!
401     Replays the picture using \a painter, and returns true if
402     successful; otherwise returns false.
403
404     This function does exactly the same as QPainter::drawPicture()
405     with (x, y) = (0, 0).
406 */
407
408 bool QPicture::play(QPainter *painter)
409 {
410     Q_D(QPicture);
411
412     if (d->pictb.size() == 0)                        // nothing recorded
413         return true;
414
415     if (!d->formatOk && !d->checkFormat())
416         return false;
417
418     d->pictb.open(QIODevice::ReadOnly);                // open buffer device
419     QDataStream s;
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);
423
424     quint8  c, clen;
425     quint32 nrecords;
426     s >> c >> clen;
427     Q_ASSERT(c == QPicturePrivate::PdcBegin);
428     // bounding rect was introduced in ver 4. Read in checkFormat().
429     if (d->formatMajor >= 4) {
430         qint32 dummy;
431         s >> dummy >> dummy >> dummy >> dummy;
432     }
433     s >> nrecords;
434     if (!exec(painter, s, nrecords)) {
435         qWarning("QPicture::play: Format error");
436         d->pictb.close();
437         return false;
438     }
439     d->pictb.close();
440     return true;                                // no end-command
441 }
442
443
444 //
445 // QFakeDevice is used to create fonts with a custom DPI
446 //
447 class QFakeDevice : public QPaintDevice
448 {
449 public:
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
455     {
456         switch(m) {
457             case PdmPhysicalDpiX:
458             case PdmDpiX:
459                 return dpi_x;
460             case PdmPhysicalDpiY:
461             case PdmDpiY:
462                 return dpi_y;
463             default:
464                 return QPaintDevice::metric(m);
465         }
466     }
467
468 private:
469     int dpi_x;
470     int dpi_y;
471 };
472
473 /*!
474   \internal
475   Iterates over the internal picture data and draws the picture using
476   \a painter.
477 */
478
479 bool QPicture::exec(QPainter *painter, QDataStream &s, int nrecords)
480 {
481     Q_D(QPicture);
482 #if defined(QT_DEBUG)
483     int                strm_pos;
484 #endif
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...
489     qint8      i_8;
490     quint32    ul;
491     double     dbl;
492     bool       bl;
493     QByteArray  str1;
494     QString     str;
495     QPointF     p, p1, p2;
496     QPoint      ip, ip1, ip2;
497     QRect       ir;
498     QRectF      r;
499     QPolygonF   a;
500     QPolygon    ia;
501     QColor      color;
502     QFont       font;
503     QPen        pen;
504     QBrush      brush;
505     QRegion     rgn;
506     QMatrix     wmatrix;
507     QTransform  matrix;
508
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);
513
514     while (nrecords-- && !s.atEnd()) {
515         s >> c;                 // read cmd
516         s >> tiny_len;          // read param length
517         if (tiny_len == 255)    // longer than 254 bytes
518             s >> len;
519         else
520             len = tiny_len;
521 #if defined(QT_DEBUG)
522         strm_pos = s.device()->pos();
523 #endif
524         switch (c) {            // exec cmd
525         case QPicturePrivate::PdcNOP:
526             break;
527         case QPicturePrivate::PdcDrawPoint:
528             if (d->formatMajor <= 5) {
529                 s >> ip;
530                 painter->drawPoint(ip);
531             } else {
532                 s >> p;
533                 painter->drawPoint(p);
534             }
535             break;
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));
540             break;
541         case QPicturePrivate::PdcDrawPath: {
542             QPainterPath path;
543             s >> path;
544             painter->drawPath(path);
545             break;
546         }
547         case QPicturePrivate::PdcDrawLine:
548             if (d->formatMajor <= 5) {
549                 s >> ip1 >> ip2;
550                 painter->drawLine(ip1, ip2);
551             } else {
552                 s >> p1 >> p2;
553                 painter->drawLine(p1, p2);
554             }
555             break;
556         case QPicturePrivate::PdcDrawRect:
557             if (d->formatMajor <= 5) {
558                 s >> ir;
559                 painter->drawRect(ir);
560             } else {
561                 s >> r;
562                 painter->drawRect(r);
563             }
564             break;
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);
569             } else {
570                 s >> r >> i1_16 >> i2_16;
571                 painter->drawRoundedRect(r, i1_16, i2_16, Qt::RelativeSize);
572             }
573             break;
574         case QPicturePrivate::PdcDrawEllipse:
575             if (d->formatMajor <= 5) {
576                 s >> ir;
577                 painter->drawEllipse(ir);
578             } else {
579                 s >> r;
580                 painter->drawEllipse(r);
581             }
582             break;
583         case QPicturePrivate::PdcDrawArc:
584             if (d->formatMajor <= 5) {
585                 s >> ir;
586                 r = ir;
587             } else {
588                 s >> r;
589             }
590             s >> i1_16 >> i2_16;
591             painter->drawArc(r, i1_16, i2_16);
592             break;
593         case QPicturePrivate::PdcDrawPie:
594             if (d->formatMajor <= 5) {
595                 s >> ir;
596                 r = ir;
597             } else {
598                 s >> r;
599             }
600             s >> i1_16 >> i2_16;
601             painter->drawPie(r, i1_16, i2_16);
602             break;
603         case QPicturePrivate::PdcDrawChord:
604             if (d->formatMajor <= 5) {
605                 s >> ir;
606                 r = ir;
607             } else {
608                 s >> r;
609             }
610             s >> i1_16 >> i2_16;
611             painter->drawChord(r, i1_16, i2_16);
612             break;
613         case QPicturePrivate::PdcDrawLineSegments:
614             s >> ia;
615             painter->drawLines(ia);
616             ia.clear();
617             break;
618         case QPicturePrivate::PdcDrawPolyline:
619             if (d->formatMajor <= 5) {
620                 s >> ia;
621                 painter->drawPolyline(ia);
622                 ia.clear();
623             } else {
624                 s >> a;
625                 painter->drawPolyline(a);
626                 a.clear();
627             }
628             break;
629         case QPicturePrivate::PdcDrawPolygon:
630             if (d->formatMajor <= 5) {
631                 s >> ia >> i_8;
632                 painter->drawPolygon(ia, i_8 ? Qt::WindingFill : Qt::OddEvenFill);
633                 a.clear();
634             } else {
635                 s >> a >> i_8;
636                 painter->drawPolygon(a, i_8 ? Qt::WindingFill : Qt::OddEvenFill);
637                 a.clear();
638             }
639             break;
640         case QPicturePrivate::PdcDrawCubicBezier: {
641             s >> ia;
642             QPainterPath path;
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());
647             a.clear();
648         }
649             break;
650         case QPicturePrivate::PdcDrawText:
651             s >> ip >> str1;
652             painter->drawText(ip, QString::fromLatin1(str1));
653             break;
654         case QPicturePrivate::PdcDrawTextFormatted:
655             s >> ir >> i_16 >> str1;
656             painter->drawText(ir, i_16, QString::fromLatin1(str1));
657             break;
658         case QPicturePrivate::PdcDrawText2:
659             if (d->formatMajor <= 5) {
660                 s >> ip >> str;
661                 painter->drawText(ip, str);
662             } else {
663                 s >> p >> str;
664                 painter->drawText(p, str);
665             }
666             break;
667         case QPicturePrivate::PdcDrawText2Formatted:
668             s >> ir;
669             s >> i_16;
670             s >> str;
671             painter->drawText(ir, i_16, str);
672             break;
673         case QPicturePrivate::PdcDrawTextItem: {
674             s >> p >> str >> font >> ul;
675
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
679
680             if (d->formatMajor >= 9) {
681                 s >> dbl;
682                 QFont fnt(font);
683                 if (dbl != 1.0) {
684                     QFakeDevice fake;
685                     fake.setDpiX(qRound(dbl*qt_defaultDpiX()));
686                     fake.setDpiY(qRound(dbl*qt_defaultDpiY()));
687                     fnt = QFont(font, &fake);
688                 }
689
690                 qreal justificationWidth;
691                 s >> justificationWidth;
692
693                 int flags = Qt::TextSingleLine | Qt::TextDontClip | Qt::TextForceLeftToRight;
694
695                 QSizeF size(1, 1);
696                 if (justificationWidth > 0) {
697                     size.setWidth(justificationWidth);
698                     flags |= Qt::TextJustificationForced;
699                     flags |= Qt::AlignJustify;
700                 }
701
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);
706             } else {
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);
709             }
710
711             break;
712         }
713         case QPicturePrivate::PdcDrawPixmap: {
714             QPixmap pixmap;
715             if (d->formatMajor < 4) {
716                 s >> ip >> pixmap;
717                 painter->drawPixmap(ip, pixmap);
718             } else if (d->formatMajor <= 5) {
719                 s >> ir >> pixmap;
720                 painter->drawPixmap(ir, pixmap);
721             } else {
722                 QRectF sr;
723                 if (d->in_memory_only) {
724                     int index;
725                     s >> r >> index >> sr;
726                     Q_ASSERT(index < d->pixmap_list.size());
727                     pixmap = d->pixmap_list.at(index);
728                 } else {
729                     s >> r >> pixmap >> sr;
730                 }
731                 painter->drawPixmap(r, pixmap, sr);
732             }
733         }
734             break;
735         case QPicturePrivate::PdcDrawTiledPixmap: {
736             QPixmap pixmap;
737             if (d->in_memory_only) {
738                 int index;
739                 s >> r >> index >> p;
740                 Q_ASSERT(index < d->pixmap_list.size());
741                 pixmap = d->pixmap_list.at(index);
742             } else {
743                 s >> r >> pixmap >> p;
744             }
745             painter->drawTiledPixmap(r, pixmap, p);
746         }
747             break;
748         case QPicturePrivate::PdcDrawImage: {
749             QImage image;
750             if (d->formatMajor < 4) {
751                 s >> p >> image;
752                 painter->drawImage(p, image);
753             } else if (d->formatMajor <= 5){
754                 s >> ir >> image;
755                 painter->drawImage(ir, image, QRect(0, 0, ir.width(), ir.height()));
756             } else {
757                 QRectF sr;
758                 if (d->in_memory_only) {
759                     int index;
760                     s >> r >> index >> sr >> ul;
761                     Q_ASSERT(index < d->image_list.size());
762                     image = d->image_list.at(index);
763                 } else {
764                     s >> r >> image >> sr >> ul;
765                 }
766                 painter->drawImage(r, image, sr, Qt::ImageConversionFlags(ul));
767             }
768         }
769             break;
770         case QPicturePrivate::PdcBegin:
771             s >> ul;                        // number of records
772             if (!exec(painter, s, ul))
773                 return false;
774             break;
775         case QPicturePrivate::PdcEnd:
776             if (nrecords == 0)
777                 return true;
778             break;
779         case QPicturePrivate::PdcSave:
780             painter->save();
781             break;
782         case QPicturePrivate::PdcRestore:
783             painter->restore();
784             break;
785         case QPicturePrivate::PdcSetBkColor:
786             s >> color;
787             painter->setBackground(color);
788             break;
789         case QPicturePrivate::PdcSetBkMode:
790             s >> i_8;
791             painter->setBackgroundMode((Qt::BGMode)i_8);
792             break;
793         case QPicturePrivate::PdcSetROP: // NOP
794             s >> i_8;
795             break;
796         case QPicturePrivate::PdcSetBrushOrigin:
797             if (d->formatMajor <= 5) {
798                 s >> ip;
799                 painter->setBrushOrigin(ip);
800             } else {
801                 s >> p;
802                 painter->setBrushOrigin(p);
803             }
804             break;
805         case QPicturePrivate::PdcSetFont:
806             s >> font;
807             painter->setFont(font);
808             break;
809         case QPicturePrivate::PdcSetPen:
810             if (d->in_memory_only) {
811                 int index;
812                 s >> index;
813                 Q_ASSERT(index < d->pen_list.size());
814                 pen = d->pen_list.at(index);
815             } else {
816                 s >> pen;
817             }
818             painter->setPen(pen);
819             break;
820         case QPicturePrivate::PdcSetBrush:
821             if (d->in_memory_only) {
822                 int index;
823                 s >> index;
824                 Q_ASSERT(index < d->brush_list.size());
825                 brush = d->brush_list.at(index);
826             } else {
827                 s >> brush;
828             }
829             painter->setBrush(brush);
830             break;
831         case QPicturePrivate::PdcSetVXform:
832             s >> i_8;
833             painter->setViewTransformEnabled(i_8);
834             break;
835         case QPicturePrivate::PdcSetWindow:
836             if (d->formatMajor <= 5) {
837                 s >> ir;
838                 painter->setWindow(ir);
839             } else {
840                 s >> r;
841                 painter->setWindow(r.toRect());
842             }
843             break;
844         case QPicturePrivate::PdcSetViewport:
845             if (d->formatMajor <= 5) {
846                 s >> ir;
847                 painter->setViewport(ir);
848             } else {
849                 s >> r;
850                 painter->setViewport(r.toRect());
851             }
852             break;
853         case QPicturePrivate::PdcSetWXform:
854             s >> i_8;
855             painter->setMatrixEnabled(i_8);
856             break;
857         case QPicturePrivate::PdcSetWMatrix:
858             if (d->formatMajor >= 8) {
859                 s >> matrix >> i_8;
860             } else {
861                 s >> wmatrix >> i_8;
862                 matrix = QTransform(wmatrix);
863             }
864             // i_8 is always false due to updateXForm() in qpaintengine_pic.cpp
865             painter->setTransform(matrix * worldMatrix, i_8);
866             break;
867         case QPicturePrivate::PdcSetClip:
868             s >> i_8;
869             painter->setClipping(i_8);
870             break;
871         case QPicturePrivate::PdcSetClipRegion:
872             s >> rgn >> i_8;
873             if (d->formatMajor >= 9) {
874                 painter->setClipRegion(rgn, Qt::ClipOperation(i_8));
875             } else {
876                 painter->setClipRegion(rgn);
877             }
878             break;
879         case QPicturePrivate::PdcSetClipPath:
880             {
881                 QPainterPath path;
882                 s >> path >> i_8;
883                 painter->setClipPath(path, Qt::ClipOperation(i_8));
884                 break;
885             }
886         case QPicturePrivate::PdcSetRenderHint:
887             s >> ul;
888             painter->setRenderHint(QPainter::Antialiasing,
889                                    bool(ul & QPainter::Antialiasing));
890             painter->setRenderHint(QPainter::SmoothPixmapTransform,
891                                    bool(ul & QPainter::SmoothPixmapTransform));
892             break;
893         case QPicturePrivate::PdcSetCompositionMode:
894             s >> ul;
895             painter->setCompositionMode((QPainter::CompositionMode)ul);
896             break;
897         case QPicturePrivate::PdcSetClipEnabled:
898             s >> bl;
899             painter->setClipping(bl);
900             break;
901         case QPicturePrivate::PdcSetOpacity:
902             s >> dbl;
903             painter->setOpacity(qreal(dbl));
904             break;
905         default:
906             qWarning("QPicture::play: Invalid command %d", c);
907             if (len)                        // skip unknown command
908                 s.device()->seek(s.device()->pos()+len);
909         }
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);
913 #endif
914     }
915     return false;
916 }
917
918 /*!
919     \internal
920
921     Internal implementation of the virtual QPaintDevice::metric()
922     function.
923
924     A picture has the following hard-coded values: numcolors=16777216
925     and depth=24.
926
927     \a m is the metric to get.
928 */
929
930 int QPicture::metric(PaintDeviceMetric m) const
931 {
932     int val;
933     QRect brect = boundingRect();
934     switch (m) {
935         case PdmWidth:
936             val = brect.width();
937             break;
938         case PdmHeight:
939             val = brect.height();
940             break;
941         case PdmWidthMM:
942             val = int(25.4/qt_defaultDpiX()*brect.width());
943             break;
944         case PdmHeightMM:
945             val = int(25.4/qt_defaultDpiY()*brect.height());
946             break;
947         case PdmDpiX:
948         case PdmPhysicalDpiX:
949             val = qt_defaultDpiX();
950             break;
951         case PdmDpiY:
952         case PdmPhysicalDpiY:
953             val = qt_defaultDpiY();
954             break;
955         case PdmNumColors:
956             val = 16777216;
957             break;
958         case PdmDepth:
959             val = 24;
960             break;
961         default:
962             val = 0;
963             qWarning("QPicture::metric: Invalid metric command");
964     }
965     return val;
966 }
967
968 /*!
969     \fn void QPicture::detach()
970     \internal
971     Detaches from shared picture data and makes sure that this picture
972     is the only one referring to the data.
973
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.
977 */
978
979 /*! \fn bool QPicture::isDetached() const
980 \internal
981 */
982
983 /*!
984     Assigns picture \a p to this picture and returns a reference to
985     this picture.
986 */
987 QPicture& QPicture::operator=(const QPicture &p)
988 {
989     d_ptr = p.d_ptr;
990     return *this;
991 }
992
993 /*!
994     \fn void QPicture::swap(QPicture &other)
995     \since 4.8
996
997     Swaps picture \a other with this picture. This operation is very
998     fast and never fails.
999 */
1000
1001 /*!
1002   \internal
1003
1004   Constructs a QPicturePrivate
1005 */
1006 QPicturePrivate::QPicturePrivate()
1007     : in_memory_only(false)
1008 {
1009 }
1010
1011 /*!
1012   \internal
1013
1014   Copy-Constructs a QPicturePrivate. Needed when detaching.
1015 */
1016 QPicturePrivate::QPicturePrivate(const QPicturePrivate &other)
1017     : trecs(other.trecs),
1018       formatOk(other.formatOk),
1019       formatMinor(other.formatMinor),
1020       brect(other.brect),
1021       override_rect(other.override_rect),
1022       in_memory_only(false)
1023 {
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());
1028     }
1029 }
1030
1031 /*!
1032   \internal
1033
1034   Sets formatOk to false and resets the format version numbers to default
1035 */
1036
1037 void QPicturePrivate::resetFormat()
1038 {
1039     formatOk = false;
1040     formatMajor = mfhdr_maj;
1041     formatMinor = mfhdr_min;
1042 }
1043
1044
1045 /*!
1046   \internal
1047
1048   Checks data integrity and format version number. Set formatOk to
1049   true on success, to false otherwise. Returns the resulting formatOk
1050   value.
1051 */
1052 bool QPicturePrivate::checkFormat()
1053 {
1054     resetFormat();
1055
1056     // can't check anything in an empty buffer
1057     if (pictb.size() == 0 || pictb.isOpen())
1058         return false;
1059
1060     pictb.open(QIODevice::ReadOnly);                        // open buffer device
1061     QDataStream s;
1062     s.setDevice(&pictb);                        // attach data stream to buffer
1063
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");
1068         pictb.close();
1069         return false;
1070     }
1071
1072     int cs_start = sizeof(quint32);                // pos of checksum word
1073     int data_start = cs_start + sizeof(quint16);
1074     quint16 cs,ccs;
1075     QByteArray buf = pictb.buffer();        // pointer to data
1076
1077     s >> cs;                                // read checksum
1078     ccs = (quint16) qChecksum(buf.constData() + data_start, buf.size() - data_start);
1079     if (ccs != cs) {
1080         qWarning("QPicturePaintEngine::checkFormat: Invalid checksum %x, %x expected",
1081                   ccs, cs);
1082         pictb.close();
1083         return false;
1084     }
1085
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",
1090                   major, minor);
1091         pictb.close();
1092         return false;
1093     }
1094     s.setVersion(major != 4 ? major : 3);
1095
1096     quint8  c, clen;
1097     s >> c >> clen;
1098     if (c == QPicturePrivate::PdcBegin) {
1099         if (!(major >= 1 && major <= 3)) {
1100             qint32 l, t, w, h;
1101             s >> l >> t >> w >> h;
1102             brect = QRect(l, t, w, h);
1103         }
1104     } else {
1105         qWarning("QPicturePaintEngine::checkFormat: Format error");
1106         pictb.close();
1107         return false;
1108     }
1109     pictb.close();
1110
1111     formatOk = true;                        // picture seems to be ok
1112     formatMajor = major;
1113     formatMinor = minor;
1114     return true;
1115 }
1116
1117 /*! \internal */
1118 QPaintEngine *QPicture::paintEngine() const
1119 {
1120     if (!d_func()->paintEngine)
1121         const_cast<QPicture*>(this)->d_func()->paintEngine.reset(new QPicturePaintEngine);
1122     return d_func()->paintEngine.data();
1123 }
1124
1125 /*****************************************************************************
1126   QPicture stream functions
1127  *****************************************************************************/
1128
1129 #ifndef QT_NO_DATASTREAM
1130 /*!
1131     \relates QPicture
1132
1133     Writes picture \a r to the stream \a s and returns a reference to
1134     the stream.
1135 */
1136
1137 QDataStream &operator<<(QDataStream &s, const QPicture &r)
1138 {
1139     quint32 size = r.d_func()->pictb.buffer().size();
1140     s << size;
1141     // null picture ?
1142     if (size == 0)
1143         return s;
1144     // just write the whole buffer to the stream
1145     s.writeRawData (r.d_func()->pictb.buffer(), r.d_func()->pictb.buffer().size());
1146     return s;
1147 }
1148
1149 /*!
1150     \relates QPicture
1151
1152     Reads a picture from the stream \a s into picture \a r and returns
1153     a reference to the stream.
1154 */
1155
1156 QDataStream &operator>>(QDataStream &s, QPicture &r)
1157 {
1158     QDataStream sr;
1159
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);
1163     quint32 len;
1164     s >> len;
1165     QByteArray data;
1166     if (len > 0) {
1167         data.resize(len);
1168         s.readRawData(data.data(), len);
1169     }
1170
1171     r.d_func()->pictb.setData(data);
1172     r.d_func()->resetFormat();
1173     return s;
1174 }
1175 #endif // QT_NO_DATASTREAM
1176
1177
1178 #ifndef QT_NO_PICTUREIO
1179
1180 QT_BEGIN_INCLUDE_NAMESPACE
1181 #include "qregexp.h"
1182 #include "qpictureformatplugin.h"
1183 QT_END_INCLUDE_NAMESPACE
1184
1185 /*!
1186     \obsolete
1187
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
1190     recognized.
1191
1192     \sa load() save()
1193 */
1194
1195 const char* QPicture::pictureFormat(const QString &fileName)
1196 {
1197     return QPictureIO::pictureFormat(fileName);
1198 }
1199
1200 /*!
1201     \obsolete
1202
1203     Returns a list of picture formats that are supported for picture
1204     input.
1205
1206     \sa outputFormats() inputFormatList() QPictureIO
1207 */
1208 QList<QByteArray> QPicture::inputFormats()
1209 {
1210     return QPictureIO::inputFormats();
1211 }
1212
1213 static QStringList qToStringList(const QList<QByteArray> arr)
1214 {
1215     QStringList list;
1216     for (int i = 0; i < arr.count(); ++i)
1217         list.append(QString::fromLatin1(arr.at(i)));
1218     return list;
1219 }
1220
1221 /*!
1222     \obsolete
1223
1224     Returns a list of picture formats that are supported for picture
1225     input.
1226
1227     Note that if you want to iterate over the list, you should iterate
1228     over a copy, e.g.
1229     \snippet doc/src/snippets/picture/picture.cpp 2
1230
1231     \sa outputFormatList() inputFormats() QPictureIO
1232 */
1233 QStringList QPicture::inputFormatList()
1234 {
1235     return qToStringList(QPictureIO::inputFormats());
1236 }
1237
1238
1239 /*!
1240     \obsolete
1241
1242     Returns a list of picture formats that are supported for picture
1243     output.
1244
1245     Note that if you want to iterate over the list, you should iterate
1246     over a copy, e.g.
1247     \snippet doc/src/snippets/picture/picture.cpp 3
1248
1249     \sa inputFormatList() outputFormats() QPictureIO
1250 */
1251 QStringList QPicture::outputFormatList()
1252 {
1253     return qToStringList(QPictureIO::outputFormats());
1254 }
1255
1256 /*!
1257     \obsolete
1258
1259     Returns a list of picture formats that are supported for picture
1260     output.
1261
1262     \sa inputFormats() outputFormatList() QPictureIO
1263 */
1264 QList<QByteArray> QPicture::outputFormats()
1265 {
1266     return QPictureIO::outputFormats();
1267 }
1268
1269 /*****************************************************************************
1270   QPictureIO member functions
1271  *****************************************************************************/
1272
1273 /*!
1274     \obsolete
1275
1276     \class QPictureIO
1277
1278     \brief The QPictureIO class contains parameters for loading and
1279     saving pictures.
1280
1281     \ingroup painting
1282     \ingroup io
1283
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.
1287
1288     You don't normally need to use this class; QPicture::load(),
1289     QPicture::save().
1290
1291     \sa QPicture QPixmap QFile
1292 */
1293
1294 struct QPictureIOData
1295 {
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;
1303     int quality;
1304     float gamma;
1305 };
1306
1307 /*!
1308     Constructs a QPictureIO object with all parameters set to zero.
1309 */
1310
1311 QPictureIO::QPictureIO()
1312 {
1313     init();
1314 }
1315
1316 /*!
1317     Constructs a QPictureIO object with the I/O device \a ioDevice and a
1318     \a format tag.
1319 */
1320
1321 QPictureIO::QPictureIO(QIODevice *ioDevice, const char *format)
1322 {
1323     init();
1324     d->iodev = ioDevice;
1325     d->frmt = format;
1326 }
1327
1328 /*!
1329     Constructs a QPictureIO object with the file name \a fileName and a
1330     \a format tag.
1331 */
1332
1333 QPictureIO::QPictureIO(const QString &fileName, const char* format)
1334 {
1335     init();
1336     d->frmt = format;
1337     d->fname = fileName;
1338 }
1339
1340 /*!
1341     Contains initialization common to all QPictureIO constructors.
1342 */
1343
1344 void QPictureIO::init()
1345 {
1346     d = new QPictureIOData();
1347     d->parameters = 0;
1348     d->quality = -1; // default quality of the current format
1349     d->gamma=0.0f;
1350     d->iostat = 0;
1351     d->iodev  = 0;
1352 }
1353
1354 /*!
1355     Destroys the object and all related data.
1356 */
1357
1358 QPictureIO::~QPictureIO()
1359 {
1360     if (d->parameters)
1361         delete [] (char*)d->parameters;
1362     delete d;
1363 }
1364
1365
1366 /*****************************************************************************
1367   QPictureIO picture handler functions
1368  *****************************************************************************/
1369
1370 class QPictureHandler
1371 {
1372 public:
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"
1381 };
1382
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))
1386 {
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');
1393     read_picture  = r;
1394     write_picture = w;
1395 }
1396
1397 typedef QList<QPictureHandler *> QPHList;
1398 Q_GLOBAL_STATIC(QPHList, pictureHandlers)
1399
1400 void qt_init_picture_plugins()
1401 {
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));
1411 #endif
1412 }
1413
1414 static void cleanup()
1415 {
1416     // make sure that picture handlers are delete before plugin manager
1417     if (QPHList *list = pictureHandlers()) {
1418         qDeleteAll(*list);
1419         list->clear();
1420     }
1421 }
1422
1423 void qt_init_picture_handlers()                // initialize picture handlers
1424 {
1425     static QBasicAtomicInt done = Q_BASIC_ATOMIC_INITIALIZER(0);
1426     if (done.testAndSetRelaxed(0, 1)) {
1427         qAddPostRoutine(cleanup);
1428     }
1429 }
1430
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)
1438                 return list->at(i);
1439         }
1440     }
1441     return 0;                                        // no such handler
1442 }
1443
1444
1445 /*!
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.
1450
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.)
1457
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.
1460
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.
1465
1466     Example:
1467     \snippet doc/src/snippets/picture/picture.cpp 6
1468     \codeline
1469     \snippet doc/src/snippets/picture/picture.cpp 7
1470     \codeline
1471     \snippet doc/src/snippets/picture/picture.cpp 8
1472
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.
1476
1477     The regexp is only applied on the first 14 bytes of the file.
1478
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.)
1482 */
1483
1484 void QPictureIO::defineIOHandler(const char *format,
1485                                  const char *header,
1486                                  const char *flags,
1487                                  picture_io_handler readPicture,
1488                                  picture_io_handler writePicture)
1489 {
1490     qt_init_picture_handlers();
1491     if (QPHList *list = pictureHandlers()) {
1492         QPictureHandler *p;
1493         p = new QPictureHandler(format, header, QByteArray(flags), readPicture, writePicture);
1494         list->prepend(p);
1495     }
1496 }
1497
1498
1499 /*****************************************************************************
1500   QPictureIO normal member functions
1501  *****************************************************************************/
1502
1503 /*!
1504     Returns the picture currently set.
1505
1506     \sa setPicture()
1507 */
1508 const QPicture &QPictureIO::picture() const { return d->pi; }
1509
1510 /*!
1511     Returns the picture's IO status. A non-zero value indicates an
1512     error, whereas 0 means that the IO operation was successful.
1513
1514     \sa setStatus()
1515 */
1516 int QPictureIO::status() const { return d->iostat; }
1517
1518 /*!
1519     Returns the picture format string or 0 if no format has been
1520     explicitly set.
1521 */
1522 const char *QPictureIO::format() const { return d->frmt; }
1523
1524 /*!
1525     Returns the IO device currently set.
1526
1527     \sa setIODevice()
1528 */
1529 QIODevice *QPictureIO::ioDevice() const { return d->iodev; }
1530
1531 /*!
1532     Returns the file name currently set.
1533
1534     \sa setFileName()
1535 */
1536 QString QPictureIO::fileName() const { return d->fname; }
1537
1538
1539 /*!
1540     Returns the picture description string.
1541
1542     \sa setDescription()
1543 */
1544 QString QPictureIO::description() const { return d->descr; }
1545
1546 /*!
1547     Sets the picture to \a picture.
1548
1549     \sa picture()
1550 */
1551 void QPictureIO::setPicture(const QPicture &picture)
1552 {
1553     d->pi = picture;
1554 }
1555
1556 /*!
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.
1559
1560     \sa status()
1561 */
1562 void QPictureIO::setStatus(int status)
1563 {
1564     d->iostat = status;
1565 }
1566
1567 /*!
1568     Sets the picture format to \a format for the picture to be read or
1569     written.
1570
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.
1573
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
1576     has that format.
1577
1578     \sa read() write() format()
1579 */
1580 void QPictureIO::setFormat(const char *format)
1581 {
1582     d->frmt = format;
1583 }
1584
1585 /*!
1586     Sets the IO device to be used for reading or writing an picture.
1587
1588     Setting the IO device allows pictures to be read/written to any
1589     block-oriented QIODevice.
1590
1591     If \a ioDevice is not null, this IO device will override file name
1592     settings.
1593
1594     \sa setFileName()
1595 */
1596 void QPictureIO::setIODevice(QIODevice *ioDevice)
1597 {
1598     d->iodev = ioDevice;
1599 }
1600
1601 /*!
1602     Sets the name of the file to read or write an picture from to \a
1603     fileName.
1604
1605     \sa setIODevice()
1606 */
1607 void QPictureIO::setFileName(const QString &fileName)
1608 {
1609     d->fname = fileName;
1610 }
1611
1612 /*!
1613     Returns the quality of the written picture, related to the
1614     compression ratio.
1615
1616     \sa setQuality() QPicture::save()
1617 */
1618 int QPictureIO::quality() const
1619 {
1620     return d->quality;
1621 }
1622
1623 /*!
1624     Sets the quality of the written picture to \a q, related to the
1625     compression ratio.
1626
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.)
1630
1631     \sa quality() QPicture::save()
1632 */
1633
1634 void QPictureIO::setQuality(int q)
1635 {
1636     d->quality = q;
1637 }
1638
1639 /*!
1640     Returns the picture's parameters string.
1641
1642     \sa setParameters()
1643 */
1644
1645 const char *QPictureIO::parameters() const
1646 {
1647     return d->parameters;
1648 }
1649
1650 /*!
1651     Sets the picture's parameter string to \a parameters. This is for
1652     picture handlers that require special parameters.
1653
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).
1657
1658     \sa parameters()
1659 */
1660
1661 void QPictureIO::setParameters(const char *parameters)
1662 {
1663     if (d->parameters)
1664         delete [] (char*)d->parameters;
1665     d->parameters = qstrdup(parameters);
1666 }
1667
1668 /*!
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).
1674
1675     The default value is 0.0.
1676
1677     \sa gamma()
1678 */
1679 void QPictureIO::setGamma(float gamma)
1680 {
1681     d->gamma=gamma;
1682 }
1683
1684 /*!
1685     Returns the gamma value at which the picture will be viewed.
1686
1687     \sa setGamma()
1688 */
1689 float QPictureIO::gamma() const
1690 {
1691     return d->gamma;
1692 }
1693
1694 /*!
1695     Sets the picture description string for picture handlers that support
1696     picture descriptions to \a description.
1697
1698     Currently, no picture format supported by Qt uses the description
1699     string.
1700 */
1701
1702 void QPictureIO::setDescription(const QString &description)
1703 {
1704     d->descr = description;
1705 }
1706
1707
1708 /*!
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
1711     not recognized.
1712 */
1713
1714 QByteArray QPictureIO::pictureFormat(const QString &fileName)
1715 {
1716     QFile file(fileName);
1717     QByteArray format;
1718     if (!file.open(QIODevice::ReadOnly))
1719         return format;
1720     format = pictureFormat(&file);
1721     file.close();
1722     return format;
1723 }
1724
1725 /*!
1726     \overload
1727
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.
1731
1732     Make sure that \a d is at the right position in the device (for
1733     example, at the beginning of the file).
1734
1735     \sa QIODevice::at()
1736 */
1737
1738 QByteArray QPictureIO::pictureFormat(QIODevice *d)
1739 {
1740     // if you change this change the documentation for defineIOHandler()
1741     const int buflen = 14;
1742
1743     char buf[buflen];
1744     char buf2[buflen];
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
1749
1750     QByteArray format;
1751     if (rdlen != buflen)
1752         return format;
1753
1754     memcpy(buf2, buf, buflen);
1755
1756     for (int n = 0; n < rdlen; n++)
1757         if (buf[n] == '\0')
1758             buf[n] = '\001';
1759     if (rdlen > 0) {
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;
1766                     break;
1767                 }
1768             }
1769         }
1770     }
1771     d->seek(pos);                                // restore position
1772     return format;
1773 }
1774
1775 /*!
1776     Returns a sorted list of picture formats that are supported for
1777     picture input.
1778 */
1779 QList<QByteArray> QPictureIO::inputFormats()
1780 {
1781     QList<QByteArray> result;
1782
1783     qt_init_picture_handlers();
1784     qt_init_picture_plugins();
1785
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);
1791         }
1792     }
1793     qSort(result);
1794
1795     return result;
1796 }
1797
1798 /*!
1799     Returns a sorted list of picture formats that are supported for
1800     picture output.
1801 */
1802 QList<QByteArray> QPictureIO::outputFormats()
1803 {
1804     qt_init_picture_handlers();
1805     qt_init_picture_plugins();
1806
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);
1813         }
1814     }
1815     return result;
1816 }
1817
1818
1819
1820 /*!
1821     Reads an picture into memory and returns true if the picture was
1822     successfully read; otherwise returns false.
1823
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
1826     will be used.
1827
1828     Setting the picture file format string is optional.
1829
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.
1833
1834     Example:
1835
1836     \snippet doc/src/snippets/picture/picture.cpp 4
1837
1838     \sa setIODevice() setFileName() setFormat() write() QPixmap::load()
1839 */
1840 bool QPictureIO::read()
1841 {
1842     QFile           file;
1843     const char          *picture_format;
1844     QPictureHandler *h;
1845
1846     if (d->iodev) {                                // read from io device
1847         // ok, already open
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
1852         d->iodev = &file;
1853     } else {                                        // no file name or io device
1854         return false;
1855     }
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
1861                 file.close();
1862                 d->iodev = 0;
1863             }
1864             return false;
1865         }
1866     } else {
1867         picture_format = d->frmt;
1868     }
1869
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
1874             file.close();
1875             file.open(QIODevice::ReadOnly | QIODevice::Text);
1876         }
1877         else
1878 #endif
1879             file.seek(0);                        // position to start
1880     }
1881     d->iostat = 1;                                        // assume error
1882
1883     if (h && h->read_picture)
1884         (*h->read_picture)(this);
1885
1886     if (file.isOpen()) {                        // picture was read using file
1887         file.close();
1888         d->iodev = 0;
1889     }
1890     return d->iostat == 0;                                // picture successfully read?
1891 }
1892
1893
1894 /*!
1895     Writes an picture to an IO device and returns true if the picture was
1896     successfully written; otherwise returns false.
1897
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
1900     will be used.
1901
1902     The picture will be written using the specified picture format.
1903
1904     Example:
1905     \snippet doc/src/snippets/picture/picture.cpp 5
1906
1907     \sa setIODevice() setFileName() setFormat() read() QPixmap::save()
1908 */
1909 bool QPictureIO::write()
1910 {
1911     if (d->frmt.isEmpty())
1912         return false;
1913     QPictureHandler *h = get_picture_handler(d->frmt);
1914     if (!h || !h->write_picture) {
1915         qWarning("QPictureIO::write: No such picture format handler: %s",
1916                  format());
1917         return false;
1918     }
1919     QFile file;
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
1925             return false;
1926         d->iodev = &file;
1927     }
1928     d->iostat = 1;
1929     (*h->write_picture)(this);
1930     if (file.isOpen()) {                        // picture was written using file
1931         file.close();
1932         d->iodev = 0;
1933     }
1934     return d->iostat == 0;                                // picture successfully written?
1935 }
1936 #endif //QT_NO_PICTUREIO
1937
1938 QT_END_NAMESPACE
1939
1940 #endif // QT_NO_PICTURE
1941
1942 /*!
1943     \typedef QPicture::DataPtr
1944     \internal
1945 */
1946
1947 /*!
1948     \fn DataPtr &QPicture::data_ptr()
1949     \internal
1950 */