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