source: trunk/src/gui/image/qpicture.cpp@ 858

Last change on this file since 858 was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

File size: 54.9 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the QtGui module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at [email protected].
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
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 "qregion.h"
58#include "qdebug.h"
59
60QT_BEGIN_NAMESPACE
61
62void qt_format_text(const QFont &fnt, const QRectF &_r,
63 int tf, const QTextOption *opt, const QString& str, QRectF *brect,
64 int tabstops, int *, int tabarraylen,
65 QPainter *painter);
66
67/*!
68 \class QPicture
69 \brief The QPicture class is a paint device that records and
70 replays QPainter commands.
71
72 \ingroup painting
73 \ingroup shared
74
75
76 A picture serializes painter commands to an IO device in a
77 platform-independent format. They are sometimes referred to as meta-files.
78
79 Qt pictures use a proprietary binary format. Unlike native picture
80 (meta-file) formats on many window systems, Qt pictures have no
81 limitations regarding their contents. Everything that can be
82 painted on a widget or pixmap (e.g., fonts, pixmaps, regions,
83 transformed graphics, etc.) can also be stored in a picture.
84
85 QPicture is resolution independent, i.e. a QPicture can be
86 displayed on different devices (for example svg, pdf, ps, printer
87 and screen) looking the same. This is, for instance, needed for
88 WYSIWYG print preview. QPicture runs in the default system dpi,
89 and scales the painter to match differences in resolution
90 depending on the window system.
91
92 Example of how to record a picture:
93 \snippet doc/src/snippets/picture/picture.cpp 0
94
95 Note that the list of painter commands is reset on each call to
96 the QPainter::begin() function.
97
98 Example of how to replay a picture:
99 \snippet doc/src/snippets/picture/picture.cpp 1
100
101 Pictures can also be drawn using play(). Some basic data about a
102 picture is available, for example, size(), isNull() and
103 boundingRect().
104
105 \sa QMovie
106*/
107
108const char *qt_mfhdr_tag = "QPIC"; // header tag
109static const quint16 mfhdr_maj = 11; // major version #
110static const quint16 mfhdr_min = 0; // minor version #
111Q_GUI_EXPORT extern int qt_defaultDpiX();
112Q_GUI_EXPORT extern int qt_defaultDpiY();
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
129QPicture::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
154QPicture::QPicture(const QPicture &pic)
155 : QPaintDevice(), d_ptr(pic.d_ptr)
156{
157}
158
159/*! \internal */
160QPicture::QPicture(QPicturePrivate &dptr)
161 : QPaintDevice(),
162 d_ptr(&dptr)
163{
164}
165
166/*!
167 Destroys the picture.
168*/
169QPicture::~QPicture()
170{
171}
172
173/*!
174 \internal
175*/
176int 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
207bool QPicture::isNull() const
208{
209 return d_func()->pictb.buffer().isNull();
210}
211
212uint QPicture::size() const
213{
214 return d_func()->pictb.buffer().size();
215}
216
217const char* QPicture::data() const
218{
219 return d_func()->pictb.buffer();
220}
221
222void QPicture::detach()
223{
224 d_ptr.detach();
225}
226
227bool QPicture::isDetached() const
228{
229 return d_func()->ref == 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
239void 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
257bool 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
271bool 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
307bool 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
344bool 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
377QRect 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
395void 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
408bool 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//
447class QFakeDevice : public QPaintDevice
448{
449public:
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
468private:
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
479bool 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// #ifdef Q_Q3PAINTER
832// case QPicturePrivate::PdcSetTabStops:
833// s >> i_16;
834// painter->setTabStops(i_16);
835// break;
836// case QPicturePrivate::PdcSetTabArray:
837// s >> i_16;
838// if (i_16 == 0) {
839// painter->setTabArray(0);
840// } else {
841// int *ta = new int[i_16];
842// for (int i=0; i<i_16; i++) {
843// s >> i1_16;
844// ta[i] = i1_16;
845// }
846// painter->setTabArray(ta);
847// delete [] ta;
848// }
849// break;
850// #endif
851 case QPicturePrivate::PdcSetVXform:
852 s >> i_8;
853 painter->setViewTransformEnabled(i_8);
854 break;
855 case QPicturePrivate::PdcSetWindow:
856 if (d->formatMajor <= 5) {
857 s >> ir;
858 painter->setWindow(ir);
859 } else {
860 s >> r;
861 painter->setWindow(r.toRect());
862 }
863 break;
864 case QPicturePrivate::PdcSetViewport:
865 if (d->formatMajor <= 5) {
866 s >> ir;
867 painter->setViewport(ir);
868 } else {
869 s >> r;
870 painter->setViewport(r.toRect());
871 }
872 break;
873 case QPicturePrivate::PdcSetWXform:
874 s >> i_8;
875 painter->setMatrixEnabled(i_8);
876 break;
877 case QPicturePrivate::PdcSetWMatrix:
878 if (d->formatMajor >= 8) {
879 s >> matrix >> i_8;
880 } else {
881 s >> wmatrix >> i_8;
882 matrix = QTransform(wmatrix);
883 }
884 // i_8 is always false due to updateXForm() in qpaintengine_pic.cpp
885 painter->setTransform(matrix * worldMatrix, i_8);
886 break;
887// #ifdef Q_Q3PAINTER
888// case QPicturePrivate::PdcSaveWMatrix:
889// painter->saveWorldMatrix();
890// break;
891// case QPicturePrivate::PdcRestoreWMatrix:
892// painter->restoreWorldMatrix();
893// break;
894// #endif
895 case QPicturePrivate::PdcSetClip:
896 s >> i_8;
897 painter->setClipping(i_8);
898 break;
899 case QPicturePrivate::PdcSetClipRegion:
900 s >> rgn >> i_8;
901 if (d->formatMajor >= 9) {
902 painter->setClipRegion(rgn, Qt::ClipOperation(i_8));
903 } else {
904 painter->setClipRegion(rgn);
905 }
906 break;
907 case QPicturePrivate::PdcSetClipPath:
908 {
909 QPainterPath path;
910 s >> path >> i_8;
911 painter->setClipPath(path, Qt::ClipOperation(i_8));
912 break;
913 }
914 case QPicturePrivate::PdcSetRenderHint:
915 s >> ul;
916 painter->setRenderHint(QPainter::Antialiasing,
917 bool(ul & QPainter::Antialiasing));
918 painter->setRenderHint(QPainter::SmoothPixmapTransform,
919 bool(ul & QPainter::SmoothPixmapTransform));
920 break;
921 case QPicturePrivate::PdcSetCompositionMode:
922 s >> ul;
923 painter->setCompositionMode((QPainter::CompositionMode)ul);
924 break;
925 case QPicturePrivate::PdcSetClipEnabled:
926 s >> bl;
927 painter->setClipping(bl);
928 break;
929 case QPicturePrivate::PdcSetOpacity:
930 s >> dbl;
931 painter->setOpacity(qreal(dbl));
932 break;
933 default:
934 qWarning("QPicture::play: Invalid command %d", c);
935 if (len) // skip unknown command
936 s.device()->seek(s.device()->pos()+len);
937 }
938#if defined(QT_DEBUG)
939 //qDebug("device->at(): %i, strm_pos: %i len: %i", (int)s.device()->pos(), strm_pos, len);
940 Q_ASSERT(qint32(s.device()->pos() - strm_pos) == len);
941#endif
942 }
943 return false;
944}
945
946/*!
947 \internal
948
949 Internal implementation of the virtual QPaintDevice::metric()
950 function.
951
952 A picture has the following hard-coded values: numcolors=16777216
953 and depth=24.
954
955 \a m is the metric to get.
956*/
957
958int QPicture::metric(PaintDeviceMetric m) const
959{
960 int val;
961 QRect brect = boundingRect();
962 switch (m) {
963 case PdmWidth:
964 val = brect.width();
965 break;
966 case PdmHeight:
967 val = brect.height();
968 break;
969 case PdmWidthMM:
970 val = int(25.4/qt_defaultDpiX()*brect.width());
971 break;
972 case PdmHeightMM:
973 val = int(25.4/qt_defaultDpiY()*brect.height());
974 break;
975 case PdmDpiX:
976 case PdmPhysicalDpiX:
977 val = qt_defaultDpiX();
978 break;
979 case PdmDpiY:
980 case PdmPhysicalDpiY:
981 val = qt_defaultDpiY();
982 break;
983 case PdmNumColors:
984 val = 16777216;
985 break;
986 case PdmDepth:
987 val = 24;
988 break;
989 default:
990 val = 0;
991 qWarning("QPicture::metric: Invalid metric command");
992 }
993 return val;
994}
995
996/*!
997 \fn void QPicture::detach()
998 \internal
999 Detaches from shared picture data and makes sure that this picture
1000 is the only one referring to the data.
1001
1002 If multiple pictures share common data, this picture makes a copy
1003 of the data and detaches itself from the sharing mechanism.
1004 Nothing is done if there is just a single reference.
1005*/
1006
1007/*! \fn bool QPicture::isDetached() const
1008\internal
1009*/
1010
1011/*! \internal
1012### Qt 5 - remove me
1013 */
1014void QPicture::detach_helper()
1015{
1016 // QExplicitelySharedDataPointer takes care of cloning using
1017 // QPicturePrivate's copy constructor. Do not call detach_helper() anymore
1018 // and remove in Qt 5, please.
1019 Q_ASSERT_X(false, "QPicture::detach_helper()", "Do not call this function");
1020}
1021
1022/*!
1023 Assigns picture \a p to this picture and returns a reference to
1024 this picture.
1025*/
1026QPicture& QPicture::operator=(const QPicture &p)
1027{
1028 d_ptr = p.d_ptr;
1029 return *this;
1030}
1031
1032/*!
1033 \internal
1034
1035 Constructs a QPicturePrivate
1036*/
1037QPicturePrivate::QPicturePrivate()
1038 : in_memory_only(false)
1039{
1040}
1041
1042/*!
1043 \internal
1044
1045 Copy-Constructs a QPicturePrivate. Needed when detaching.
1046*/
1047QPicturePrivate::QPicturePrivate(const QPicturePrivate &other)
1048 : trecs(other.trecs),
1049 formatOk(other.formatOk),
1050 formatMinor(other.formatMinor),
1051 brect(other.brect),
1052 override_rect(other.override_rect),
1053 in_memory_only(false)
1054{
1055 pictb.setData(other.pictb.data(), other.pictb.size());
1056 if (other.pictb.isOpen()) {
1057 pictb.open(other.pictb.openMode());
1058 pictb.seek(other.pictb.pos());
1059 }
1060}
1061
1062/*!
1063 \internal
1064
1065 Sets formatOk to false and resets the format version numbers to default
1066*/
1067
1068void QPicturePrivate::resetFormat()
1069{
1070 formatOk = false;
1071 formatMajor = mfhdr_maj;
1072 formatMinor = mfhdr_min;
1073}
1074
1075
1076/*!
1077 \internal
1078
1079 Checks data integrity and format version number. Set formatOk to
1080 true on success, to false otherwise. Returns the resulting formatOk
1081 value.
1082*/
1083bool QPicturePrivate::checkFormat()
1084{
1085 resetFormat();
1086
1087 // can't check anything in an empty buffer
1088 if (pictb.size() == 0 || pictb.isOpen())
1089 return false;
1090
1091 pictb.open(QIODevice::ReadOnly); // open buffer device
1092 QDataStream s;
1093 s.setDevice(&pictb); // attach data stream to buffer
1094
1095 char mf_id[4]; // picture header tag
1096 s.readRawData(mf_id, 4); // read actual tag
1097 if (memcmp(mf_id, qt_mfhdr_tag, 4) != 0) { // wrong header id
1098 qWarning("QPicturePaintEngine::checkFormat: Incorrect header");
1099 pictb.close();
1100 return false;
1101 }
1102
1103 int cs_start = sizeof(quint32); // pos of checksum word
1104 int data_start = cs_start + sizeof(quint16);
1105 quint16 cs,ccs;
1106 QByteArray buf = pictb.buffer(); // pointer to data
1107
1108 s >> cs; // read checksum
1109 ccs = (quint16) qChecksum(buf.constData() + data_start, buf.size() - data_start);
1110 if (ccs != cs) {
1111 qWarning("QPicturePaintEngine::checkFormat: Invalid checksum %x, %x expected",
1112 ccs, cs);
1113 pictb.close();
1114 return false;
1115 }
1116
1117 quint16 major, minor;
1118 s >> major >> minor; // read version number
1119 if (major > mfhdr_maj) { // new, incompatible version
1120 qWarning("QPicturePaintEngine::checkFormat: Incompatible version %d.%d",
1121 major, minor);
1122 pictb.close();
1123 return false;
1124 }
1125 s.setVersion(major != 4 ? major : 3);
1126
1127 quint8 c, clen;
1128 s >> c >> clen;
1129 if (c == QPicturePrivate::PdcBegin) {
1130 if (!(major >= 1 && major <= 3)) {
1131 qint32 l, t, w, h;
1132 s >> l >> t >> w >> h;
1133 brect = QRect(l, t, w, h);
1134 }
1135 } else {
1136 qWarning("QPicturePaintEngine::checkFormat: Format error");
1137 pictb.close();
1138 return false;
1139 }
1140 pictb.close();
1141
1142 formatOk = true; // picture seems to be ok
1143 formatMajor = major;
1144 formatMinor = minor;
1145 return true;
1146}
1147
1148/*! \internal */
1149QPaintEngine *QPicture::paintEngine() const
1150{
1151 if (!d_func()->paintEngine)
1152 const_cast<QPicture*>(this)->d_func()->paintEngine.reset(new QPicturePaintEngine);
1153 return d_func()->paintEngine.data();
1154}
1155
1156/*****************************************************************************
1157 QPicture stream functions
1158 *****************************************************************************/
1159
1160#ifndef QT_NO_DATASTREAM
1161/*!
1162 \relates QPicture
1163
1164 Writes picture \a r to the stream \a s and returns a reference to
1165 the stream.
1166*/
1167
1168QDataStream &operator<<(QDataStream &s, const QPicture &r)
1169{
1170 quint32 size = r.d_func()->pictb.buffer().size();
1171 s << size;
1172 // null picture ?
1173 if (size == 0)
1174 return s;
1175 // just write the whole buffer to the stream
1176 s.writeRawData (r.d_func()->pictb.buffer(), r.d_func()->pictb.buffer().size());
1177 return s;
1178}
1179
1180/*!
1181 \relates QPicture
1182
1183 Reads a picture from the stream \a s into picture \a r and returns
1184 a reference to the stream.
1185*/
1186
1187QDataStream &operator>>(QDataStream &s, QPicture &r)
1188{
1189 QDataStream sr;
1190
1191 // "init"; this code is similar to the beginning of QPicture::cmd()
1192 sr.setDevice(&r.d_func()->pictb);
1193 sr.setVersion(r.d_func()->formatMajor);
1194 quint32 len;
1195 s >> len;
1196 QByteArray data;
1197 if (len > 0) {
1198 data.resize(len);
1199 s.readRawData(data.data(), len);
1200 }
1201
1202 r.d_func()->pictb.setData(data);
1203 r.d_func()->resetFormat();
1204 return s;
1205}
1206#endif // QT_NO_DATASTREAM
1207
1208
1209#ifndef QT_NO_PICTUREIO
1210
1211QT_BEGIN_INCLUDE_NAMESPACE
1212#include "qregexp.h"
1213#include "qapplication.h"
1214#include "qpictureformatplugin.h"
1215QT_END_INCLUDE_NAMESPACE
1216
1217/*!
1218 \obsolete
1219
1220 Returns a string that specifies the picture format of the file \a
1221 fileName, or 0 if the file cannot be read or if the format is not
1222 recognized.
1223
1224 \sa load() save()
1225*/
1226
1227const char* QPicture::pictureFormat(const QString &fileName)
1228{
1229 return QPictureIO::pictureFormat(fileName);
1230}
1231
1232/*!
1233 \obsolete
1234
1235 Returns a list of picture formats that are supported for picture
1236 input.
1237
1238 \sa outputFormats() inputFormatList() QPictureIO
1239*/
1240QList<QByteArray> QPicture::inputFormats()
1241{
1242 return QPictureIO::inputFormats();
1243}
1244
1245static QStringList qToStringList(const QList<QByteArray> arr)
1246{
1247 QStringList list;
1248 for (int i = 0; i < arr.count(); ++i)
1249 list.append(QString::fromLatin1(arr.at(i)));
1250 return list;
1251}
1252
1253/*!
1254 \obsolete
1255
1256 Returns a list of picture formats that are supported for picture
1257 input.
1258
1259 Note that if you want to iterate over the list, you should iterate
1260 over a copy, e.g.
1261 \snippet doc/src/snippets/picture/picture.cpp 2
1262
1263 \sa outputFormatList() inputFormats() QPictureIO
1264*/
1265QStringList QPicture::inputFormatList()
1266{
1267 return qToStringList(QPictureIO::inputFormats());
1268}
1269
1270
1271/*!
1272 \obsolete
1273
1274 Returns a list of picture formats that are supported for picture
1275 output.
1276
1277 Note that if you want to iterate over the list, you should iterate
1278 over a copy, e.g.
1279 \snippet doc/src/snippets/picture/picture.cpp 3
1280
1281 \sa inputFormatList() outputFormats() QPictureIO
1282*/
1283QStringList QPicture::outputFormatList()
1284{
1285 return qToStringList(QPictureIO::outputFormats());
1286}
1287
1288/*!
1289 \obsolete
1290
1291 Returns a list of picture formats that are supported for picture
1292 output.
1293
1294 \sa inputFormats() outputFormatList() QPictureIO
1295*/
1296QList<QByteArray> QPicture::outputFormats()
1297{
1298 return QPictureIO::outputFormats();
1299}
1300
1301/*****************************************************************************
1302 QPictureIO member functions
1303 *****************************************************************************/
1304
1305/*!
1306 \obsolete
1307
1308 \class QPictureIO
1309
1310 \brief The QPictureIO class contains parameters for loading and
1311 saving pictures.
1312
1313 \ingroup painting
1314 \ingroup io
1315
1316 QPictureIO contains a QIODevice object that is used for picture data
1317 I/O. The programmer can install new picture file formats in addition
1318 to those that Qt provides.
1319
1320 You don't normally need to use this class; QPicture::load(),
1321 QPicture::save().
1322
1323 \sa QPicture QPixmap QFile
1324*/
1325
1326struct QPictureIOData
1327{
1328 QPicture pi; // picture
1329 int iostat; // IO status
1330 QByteArray frmt; // picture format
1331 QIODevice *iodev; // IO device
1332 QString fname; // file name
1333 QString descr; // picture description
1334 const char *parameters;
1335 int quality;
1336 float gamma;
1337};
1338
1339/*!
1340 Constructs a QPictureIO object with all parameters set to zero.
1341*/
1342
1343QPictureIO::QPictureIO()
1344{
1345 init();
1346}
1347
1348/*!
1349 Constructs a QPictureIO object with the I/O device \a ioDevice and a
1350 \a format tag.
1351*/
1352
1353QPictureIO::QPictureIO(QIODevice *ioDevice, const char *format)
1354{
1355 init();
1356 d->iodev = ioDevice;
1357 d->frmt = format;
1358}
1359
1360/*!
1361 Constructs a QPictureIO object with the file name \a fileName and a
1362 \a format tag.
1363*/
1364
1365QPictureIO::QPictureIO(const QString &fileName, const char* format)
1366{
1367 init();
1368 d->frmt = format;
1369 d->fname = fileName;
1370}
1371
1372/*!
1373 Contains initialization common to all QPictureIO constructors.
1374*/
1375
1376void QPictureIO::init()
1377{
1378 d = new QPictureIOData();
1379 d->parameters = 0;
1380 d->quality = -1; // default quality of the current format
1381 d->gamma=0.0f;
1382 d->iostat = 0;
1383 d->iodev = 0;
1384}
1385
1386/*!
1387 Destroys the object and all related data.
1388*/
1389
1390QPictureIO::~QPictureIO()
1391{
1392 if (d->parameters)
1393 delete [] (char*)d->parameters;
1394 delete d;
1395}
1396
1397
1398/*****************************************************************************
1399 QPictureIO picture handler functions
1400 *****************************************************************************/
1401
1402class QPictureHandler
1403{
1404public:
1405 QPictureHandler(const char *f, const char *h, const QByteArray& fl,
1406 picture_io_handler r, picture_io_handler w);
1407 QByteArray format; // picture format
1408 QRegExp header; // picture header pattern
1409 enum TMode { Untranslated=0, TranslateIn, TranslateInOut } text_mode;
1410 picture_io_handler read_picture; // picture read function
1411 picture_io_handler write_picture; // picture write function
1412 bool obsolete; // support not "published"
1413};
1414
1415QPictureHandler::QPictureHandler(const char *f, const char *h, const QByteArray& fl,
1416 picture_io_handler r, picture_io_handler w)
1417 : format(f), header(QString::fromLatin1(h))
1418{
1419 text_mode = Untranslated;
1420 if (fl.contains('t'))
1421 text_mode = TranslateIn;
1422 else if (fl.contains('T'))
1423 text_mode = TranslateInOut;
1424 obsolete = fl.contains('O');
1425 read_picture = r;
1426 write_picture = w;
1427}
1428
1429typedef QList<QPictureHandler *> QPHList;
1430Q_GLOBAL_STATIC(QPHList, pictureHandlers)
1431
1432#ifndef QT_NO_LIBRARY
1433Q_GLOBAL_STATIC(QMutex, mutex)
1434Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, factoryLoader,
1435 (QPictureFormatInterface_iid,
1436 QLatin1String("/pictureformats")))
1437#endif
1438void qt_init_picture_plugins()
1439{
1440#ifndef QT_NO_LIBRARY
1441 QMutexLocker locker(mutex());
1442 QFactoryLoader *loader = factoryLoader();
1443 QStringList keys = loader->keys();
1444 for (int i = 0; i < keys.count(); ++i)
1445 if (QPictureFormatInterface *format = qobject_cast<QPictureFormatInterface*>(loader->instance(keys.at(i))))
1446 format->installIOHandler(keys.at(i));
1447#endif
1448}
1449
1450static void cleanup()
1451{
1452 // make sure that picture handlers are delete before plugin manager
1453 if (QPHList *list = pictureHandlers()) {
1454 qDeleteAll(*list);
1455 list->clear();
1456 }
1457}
1458
1459void qt_init_picture_handlers() // initialize picture handlers
1460{
1461 static QBasicAtomicInt done = Q_BASIC_ATOMIC_INITIALIZER(0);
1462 if (done.testAndSetRelaxed(0, 1)) {
1463 qAddPostRoutine(cleanup);
1464 }
1465}
1466
1467static QPictureHandler *get_picture_handler(const char *format)
1468{ // get pointer to handler
1469 qt_init_picture_handlers();
1470 qt_init_picture_plugins();
1471 if (QPHList *list = pictureHandlers()) {
1472 for (int i = 0; i < list->size(); ++i) {
1473 if (list->at(i)->format == format)
1474 return list->at(i);
1475 }
1476 }
1477 return 0; // no such handler
1478}
1479
1480
1481/*!
1482 Defines a picture I/O handler for the picture format called \a
1483 format, which is recognized using the regular
1484 expression defined in \a header, read using \a readPicture and
1485 written using \a writePicture.
1486
1487 \a flags is a string of single-character flags for this format.
1488 The only flag defined currently is T (upper case), so the only
1489 legal value for \a flags are "T" and the empty string. The "T"
1490 flag means that the picture file is a text file, and Qt should treat
1491 all newline conventions as equivalent. (XPM files and some PPM
1492 files are text files for example.)
1493
1494 \a format is used to select a handler to write a QPicture; \a header
1495 is used to select a handler to read an picture file.
1496
1497 If \a readPicture is a null pointer, the QPictureIO will not be able
1498 to read pictures in \a format. If \a writePicture is a null pointer,
1499 the QPictureIO will not be able to write pictures in \a format. If
1500 both are null, the QPictureIO object is valid but useless.
1501
1502 Example:
1503 \snippet doc/src/snippets/picture/picture.cpp 6
1504 \codeline
1505 \snippet doc/src/snippets/picture/picture.cpp 7
1506 \codeline
1507 \snippet doc/src/snippets/picture/picture.cpp 8
1508
1509 Before the regular expression test, all the 0 bytes in the file header are
1510 converted to 1 bytes. This is done because when Qt was ASCII-based, QRegExp
1511 could not handle 0 bytes in strings.
1512
1513 The regexp is only applied on the first 14 bytes of the file.
1514
1515 (Note that if one handlerIO supports writing a format and another
1516 supports reading it, Qt supports both reading and writing. If two
1517 handlers support the same operation, Qt chooses one arbitrarily.)
1518*/
1519
1520void QPictureIO::defineIOHandler(const char *format,
1521 const char *header,
1522 const char *flags,
1523 picture_io_handler readPicture,
1524 picture_io_handler writePicture)
1525{
1526 qt_init_picture_handlers();
1527 if (QPHList *list = pictureHandlers()) {
1528 QPictureHandler *p;
1529 p = new QPictureHandler(format, header, QByteArray(flags), readPicture, writePicture);
1530 list->prepend(p);
1531 }
1532}
1533
1534
1535/*****************************************************************************
1536 QPictureIO normal member functions
1537 *****************************************************************************/
1538
1539/*!
1540 Returns the picture currently set.
1541
1542 \sa setPicture()
1543*/
1544const QPicture &QPictureIO::picture() const { return d->pi; }
1545
1546/*!
1547 Returns the picture's IO status. A non-zero value indicates an
1548 error, whereas 0 means that the IO operation was successful.
1549
1550 \sa setStatus()
1551*/
1552int QPictureIO::status() const { return d->iostat; }
1553
1554/*!
1555 Returns the picture format string or 0 if no format has been
1556 explicitly set.
1557*/
1558const char *QPictureIO::format() const { return d->frmt; }
1559
1560/*!
1561 Returns the IO device currently set.
1562
1563 \sa setIODevice()
1564*/
1565QIODevice *QPictureIO::ioDevice() const { return d->iodev; }
1566
1567/*!
1568 Returns the file name currently set.
1569
1570 \sa setFileName()
1571*/
1572QString QPictureIO::fileName() const { return d->fname; }
1573
1574
1575/*!
1576 Returns the picture description string.
1577
1578 \sa setDescription()
1579*/
1580QString QPictureIO::description() const { return d->descr; }
1581
1582/*!
1583 Sets the picture to \a picture.
1584
1585 \sa picture()
1586*/
1587void QPictureIO::setPicture(const QPicture &picture)
1588{
1589 d->pi = picture;
1590}
1591
1592/*!
1593 Sets the picture IO status to \a status. A non-zero value indicates
1594 an error, whereas 0 means that the IO operation was successful.
1595
1596 \sa status()
1597*/
1598void QPictureIO::setStatus(int status)
1599{
1600 d->iostat = status;
1601}
1602
1603/*!
1604 Sets the picture format to \a format for the picture to be read or
1605 written.
1606
1607 It is necessary to specify a format before writing an picture, but
1608 it is not necessary to specify a format before reading an picture.
1609
1610 If no format has been set, Qt guesses the picture format before
1611 reading it. If a format is set the picture will only be read if it
1612 has that format.
1613
1614 \sa read() write() format()
1615*/
1616void QPictureIO::setFormat(const char *format)
1617{
1618 d->frmt = format;
1619}
1620
1621/*!
1622 Sets the IO device to be used for reading or writing an picture.
1623
1624 Setting the IO device allows pictures to be read/written to any
1625 block-oriented QIODevice.
1626
1627 If \a ioDevice is not null, this IO device will override file name
1628 settings.
1629
1630 \sa setFileName()
1631*/
1632void QPictureIO::setIODevice(QIODevice *ioDevice)
1633{
1634 d->iodev = ioDevice;
1635}
1636
1637/*!
1638 Sets the name of the file to read or write an picture from to \a
1639 fileName.
1640
1641 \sa setIODevice()
1642*/
1643void QPictureIO::setFileName(const QString &fileName)
1644{
1645 d->fname = fileName;
1646}
1647
1648/*!
1649 Returns the quality of the written picture, related to the
1650 compression ratio.
1651
1652 \sa setQuality() QPicture::save()
1653*/
1654int QPictureIO::quality() const
1655{
1656 return d->quality;
1657}
1658
1659/*!
1660 Sets the quality of the written picture to \a q, related to the
1661 compression ratio.
1662
1663 \a q must be in the range -1..100. Specify 0 to obtain small
1664 compressed files, 100 for large uncompressed files. (-1 signifies
1665 the default compression.)
1666
1667 \sa quality() QPicture::save()
1668*/
1669
1670void QPictureIO::setQuality(int q)
1671{
1672 d->quality = q;
1673}
1674
1675/*!
1676 Returns the picture's parameters string.
1677
1678 \sa setParameters()
1679*/
1680
1681const char *QPictureIO::parameters() const
1682{
1683 return d->parameters;
1684}
1685
1686/*!
1687 Sets the picture's parameter string to \a parameters. This is for
1688 picture handlers that require special parameters.
1689
1690 Although the current picture formats supported by Qt ignore the
1691 parameters string, it may be used in future extensions or by
1692 contributions (for example, JPEG).
1693
1694 \sa parameters()
1695*/
1696
1697void QPictureIO::setParameters(const char *parameters)
1698{
1699 if (d->parameters)
1700 delete [] (char*)d->parameters;
1701 d->parameters = qstrdup(parameters);
1702}
1703
1704/*!
1705 Sets the gamma value at which the picture will be viewed to \a
1706 gamma. If the picture format stores a gamma value for which the
1707 picture is intended to be used, then this setting will be used to
1708 modify the picture. Setting to 0.0 will disable gamma correction
1709 (i.e. any specification in the file will be ignored).
1710
1711 The default value is 0.0.
1712
1713 \sa gamma()
1714*/
1715void QPictureIO::setGamma(float gamma)
1716{
1717 d->gamma=gamma;
1718}
1719
1720/*!
1721 Returns the gamma value at which the picture will be viewed.
1722
1723 \sa setGamma()
1724*/
1725float QPictureIO::gamma() const
1726{
1727 return d->gamma;
1728}
1729
1730/*!
1731 Sets the picture description string for picture handlers that support
1732 picture descriptions to \a description.
1733
1734 Currently, no picture format supported by Qt uses the description
1735 string.
1736*/
1737
1738void QPictureIO::setDescription(const QString &description)
1739{
1740 d->descr = description;
1741}
1742
1743
1744/*!
1745 Returns a string that specifies the picture format of the file \a
1746 fileName, or null if the file cannot be read or if the format is
1747 not recognized.
1748*/
1749
1750QByteArray QPictureIO::pictureFormat(const QString &fileName)
1751{
1752 QFile file(fileName);
1753 QByteArray format;
1754 if (!file.open(QIODevice::ReadOnly))
1755 return format;
1756 format = pictureFormat(&file);
1757 file.close();
1758 return format;
1759}
1760
1761/*!
1762 \overload
1763
1764 Returns a string that specifies the picture format of the picture read
1765 from IO device \a d, or 0 if the device cannot be read or if the
1766 format is not recognized.
1767
1768 Make sure that \a d is at the right position in the device (for
1769 example, at the beginning of the file).
1770
1771 \sa QIODevice::at()
1772*/
1773
1774QByteArray QPictureIO::pictureFormat(QIODevice *d)
1775{
1776 // if you change this change the documentation for defineIOHandler()
1777 const int buflen = 14;
1778
1779 char buf[buflen];
1780 char buf2[buflen];
1781 qt_init_picture_handlers();
1782 qt_init_picture_plugins();
1783 int pos = d->pos(); // save position
1784 int rdlen = d->read(buf, buflen); // read a few bytes
1785
1786 QByteArray format;
1787 if (rdlen != buflen)
1788 return format;
1789
1790 memcpy(buf2, buf, buflen);
1791
1792 for (int n = 0; n < rdlen; n++)
1793 if (buf[n] == '\0')
1794 buf[n] = '\001';
1795 if (rdlen > 0) {
1796 buf[rdlen - 1] = '\0';
1797 QString bufStr = QString::fromLatin1(buf);
1798 if (QPHList *list = pictureHandlers()) {
1799 for (int i = 0; i < list->size(); ++i) {
1800 if (list->at(i)->header.indexIn(bufStr) != -1) { // try match with headers
1801 format = list->at(i)->format;
1802 break;
1803 }
1804 }
1805 }
1806 }
1807 d->seek(pos); // restore position
1808 return format;
1809}
1810
1811/*!
1812 Returns a sorted list of picture formats that are supported for
1813 picture input.
1814*/
1815QList<QByteArray> QPictureIO::inputFormats()
1816{
1817 QList<QByteArray> result;
1818
1819 qt_init_picture_handlers();
1820 qt_init_picture_plugins();
1821
1822 if (QPHList *list = pictureHandlers()) {
1823 for (int i = 0; i < list->size(); ++i) {
1824 QPictureHandler *p = list->at(i);
1825 if (p->read_picture && !p->obsolete && !result.contains(p->format))
1826 result.append(p->format);
1827 }
1828 }
1829 qSort(result);
1830
1831 return result;
1832}
1833
1834/*!
1835 Returns a sorted list of picture formats that are supported for
1836 picture output.
1837*/
1838QList<QByteArray> QPictureIO::outputFormats()
1839{
1840 qt_init_picture_handlers();
1841 qt_init_picture_plugins();
1842
1843 QList<QByteArray> result;
1844 if (QPHList *list = pictureHandlers()) {
1845 for (int i = 0; i < list->size(); ++i) {
1846 QPictureHandler *p = list->at(i);
1847 if (p->write_picture && !p->obsolete && !result.contains(p->format))
1848 result.append(p->format);
1849 }
1850 }
1851 return result;
1852}
1853
1854
1855
1856/*!
1857 Reads an picture into memory and returns true if the picture was
1858 successfully read; otherwise returns false.
1859
1860 Before reading an picture you must set an IO device or a file name.
1861 If both an IO device and a file name have been set, the IO device
1862 will be used.
1863
1864 Setting the picture file format string is optional.
1865
1866 Note that this function does \e not set the \link format()
1867 format\endlink used to read the picture. If you need that
1868 information, use the pictureFormat() static functions.
1869
1870 Example:
1871
1872 \snippet doc/src/snippets/picture/picture.cpp 4
1873
1874 \sa setIODevice() setFileName() setFormat() write() QPixmap::load()
1875*/
1876bool QPictureIO::read()
1877{
1878 QFile file;
1879 const char *picture_format;
1880 QPictureHandler *h;
1881
1882 if (d->iodev) { // read from io device
1883 // ok, already open
1884 } else if (!d->fname.isEmpty()) { // read from file
1885 file.setFileName(d->fname);
1886 if (!file.open(QIODevice::ReadOnly))
1887 return false; // cannot open file
1888 d->iodev = &file;
1889 } else { // no file name or io device
1890 return false;
1891 }
1892 if (d->frmt.isEmpty()) {
1893 // Try to guess format
1894 picture_format = pictureFormat(d->iodev); // get picture format
1895 if (!picture_format) {
1896 if (file.isOpen()) { // unknown format
1897 file.close();
1898 d->iodev = 0;
1899 }
1900 return false;
1901 }
1902 } else {
1903 picture_format = d->frmt;
1904 }
1905
1906 h = get_picture_handler(picture_format);
1907 if (file.isOpen()) {
1908#if !defined(Q_OS_UNIX)
1909 if (h && h->text_mode) { // reopen in translated mode
1910 file.close();
1911 file.open(QIODevice::ReadOnly | QIODevice::Text);
1912 }
1913 else
1914#endif
1915 file.seek(0); // position to start
1916 }
1917 d->iostat = 1; // assume error
1918
1919 if (h && h->read_picture)
1920 (*h->read_picture)(this);
1921
1922 if (file.isOpen()) { // picture was read using file
1923 file.close();
1924 d->iodev = 0;
1925 }
1926 return d->iostat == 0; // picture successfully read?
1927}
1928
1929
1930/*!
1931 Writes an picture to an IO device and returns true if the picture was
1932 successfully written; otherwise returns false.
1933
1934 Before writing an picture you must set an IO device or a file name.
1935 If both an IO device and a file name have been set, the IO device
1936 will be used.
1937
1938 The picture will be written using the specified picture format.
1939
1940 Example:
1941 \snippet doc/src/snippets/picture/picture.cpp 5
1942
1943 \sa setIODevice() setFileName() setFormat() read() QPixmap::save()
1944*/
1945bool QPictureIO::write()
1946{
1947 if (d->frmt.isEmpty())
1948 return false;
1949 QPictureHandler *h = get_picture_handler(d->frmt);
1950 if (!h || !h->write_picture) {
1951 qWarning("QPictureIO::write: No such picture format handler: %s",
1952 format());
1953 return false;
1954 }
1955 QFile file;
1956 if (!d->iodev && !d->fname.isEmpty()) {
1957 file.setFileName(d->fname);
1958 bool translate = h->text_mode==QPictureHandler::TranslateInOut;
1959 QIODevice::OpenMode fmode = translate ? QIODevice::WriteOnly | QIODevice::Text : QIODevice::OpenMode(QIODevice::WriteOnly);
1960 if (!file.open(fmode)) // couldn't create file
1961 return false;
1962 d->iodev = &file;
1963 }
1964 d->iostat = 1;
1965 (*h->write_picture)(this);
1966 if (file.isOpen()) { // picture was written using file
1967 file.close();
1968 d->iodev = 0;
1969 }
1970 return d->iostat == 0; // picture successfully written?
1971}
1972#endif //QT_NO_PICTUREIO
1973
1974/*!
1975 \fn QPicture QPicture::copy() const
1976
1977 Use simple assignment instead.
1978*/
1979
1980QT_END_NAMESPACE
1981
1982#endif // QT_NO_PICTURE
1983
1984/*!
1985 \typedef QPicture::DataPtr
1986 \internal
1987*/
1988
1989/*!
1990 \fn DataPtr &QPicture::data_ptr()
1991 \internal
1992*/
Note: See TracBrowser for help on using the repository browser.