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

Last change on this file since 290 was 2, checked in by Dmitry A. Kuminov, 17 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

File size: 54.6 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** Contact: Qt Software Information ([email protected])
5**
6** This file is part of the QtGui module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial Usage
10** Licensees holding valid Qt Commercial licenses may use this file in
11** accordance with the Qt Commercial License Agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and Nokia.
14**
15** GNU Lesser General Public License Usage
16** Alternatively, this file may be used under the terms of the GNU Lesser
17** General Public License version 2.1 as published by the Free Software
18** Foundation and appearing in the file LICENSE.LGPL included in the
19** packaging of this file. Please review the following information to
20** ensure the GNU Lesser General Public License version 2.1 requirements
21** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22**
23** In addition, as a special exception, Nokia gives you certain
24** additional rights. These rights are described in the Nokia Qt LGPL
25** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
26** 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 are unsure which license is appropriate for your use, please
37** contact the sales department 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 multimedia
73 \ingroup shared
74 \mainclass
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 #
111extern int qt_defaultDpiX();
112extern 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 d_ptr->q_ptr = this;
135 d->paintEngine = 0;
136
137 if (formatVersion == 0)
138 qWarning("QPicture: invalid format version 0");
139
140 // still accept the 0 default from before Qt 3.0.
141 if (formatVersion > 0 && formatVersion != (int)mfhdr_maj) {
142 d->formatMajor = formatVersion;
143 d->formatMinor = 0;
144 d->formatOk = false;
145 }
146 else {
147 d->resetFormat();
148 }
149}
150
151/*!
152 Constructs a copy of \a pic.
153
154 This constructor is fast thanks to \l{implicit sharing}.
155*/
156
157QPicture::QPicture(const QPicture &pic)
158 : QPaintDevice(), d_ptr(pic.d_ptr)
159{
160 d_func()->ref.ref();
161}
162
163/*! \internal */
164QPicture::QPicture(QPicturePrivate &dptr)
165 : QPaintDevice(),
166 d_ptr(&dptr)
167{
168 d_ptr->q_ptr = this;
169}
170
171/*!
172 Destroys the picture.
173*/
174QPicture::~QPicture()
175{
176 if (!d_func()->ref.deref()) {
177 delete d_func()->paintEngine;
178 delete d_func();
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 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 if (d_func()->ref != 1)
234 detach_helper();
235}
236
237bool QPicture::isDetached() const
238{
239 return d_func()->ref == 1;
240}
241
242/*!
243 Sets the picture data directly from \a data and \a size. This
244 function copies the input data.
245
246 \sa data(), size()
247*/
248
249void QPicture::setData(const char* data, uint size)
250{
251 detach();
252 d_func()->pictb.setData(data, size);
253 d_func()->resetFormat(); // we'll have to check
254}
255
256
257/*!
258 Loads a picture from the file specified by \a fileName and returns
259 true if successful; otherwise returns false.
260
261 Please note that the \a format parameter has been deprecated and
262 will have no effect.
263
264 \sa save()
265*/
266
267bool QPicture::load(const QString &fileName, const char *format)
268{
269 QFile f(fileName);
270 if (!f.open(QIODevice::ReadOnly))
271 return false;
272 return load(&f, format);
273}
274
275/*!
276 \overload
277
278 \a dev is the device to use for loading.
279*/
280
281bool QPicture::load(QIODevice *dev, const char *format)
282{
283 if(format) {
284#ifndef QT_NO_PICTUREIO
285 QPictureIO io(dev, format);
286 bool result = io.read();
287 if (result) {
288 operator=(io.picture());
289
290 } else if (format)
291#else
292 bool result = false;
293#endif
294 {
295 qWarning("QPicture::load: No such picture format: %s", format);
296 }
297 return result;
298 }
299
300 detach();
301 QByteArray a = dev->readAll();
302
303 d_func()->pictb.setData(a); // set byte array in buffer
304 return d_func()->checkFormat();
305}
306
307/*!
308 Saves a picture to the file specified by \a fileName and returns
309 true if successful; otherwise returns false.
310
311 Please note that the \a format parameter has been deprecated and
312 will have no effect.
313
314 \sa load()
315*/
316
317bool QPicture::save(const QString &fileName, const char *format)
318{
319 if (paintingActive()) {
320 qWarning("QPicture::save: still being painted on. "
321 "Call QPainter::end() first");
322 return false;
323 }
324
325
326 if(format) {
327#ifndef QT_NO_PICTUREIO
328 QPictureIO io(fileName, format);
329 bool result = io.write();
330 if (result) {
331 operator=(io.picture());
332 } else if (format)
333#else
334 bool result = false;
335#endif
336 {
337 qWarning("QPicture::save: No such picture format: %s", format);
338 }
339 return result;
340 }
341
342 QFile f(fileName);
343 if (!f.open(QIODevice::WriteOnly))
344 return false;
345 return save(&f, format);
346}
347
348/*!
349 \overload
350
351 \a dev is the device to use for saving.
352*/
353
354bool QPicture::save(QIODevice *dev, const char *format)
355{
356 if (paintingActive()) {
357 qWarning("QPicture::save: still being painted on. "
358 "Call QPainter::end() first");
359 return false;
360 }
361
362 if(format) {
363#ifndef QT_NO_PICTUREIO
364 QPictureIO io(dev, format);
365 bool result = io.write();
366 if (result) {
367 operator=(io.picture());
368 } else if (format)
369#else
370 bool result = false;
371#endif
372 {
373 qWarning("QPicture::save: No such picture format: %s", format);
374 }
375 return result;
376 }
377
378 dev->write(d_func()->pictb.buffer(), d_func()->pictb.buffer().size());
379 return true;
380}
381
382/*!
383 Returns the picture's bounding rectangle or an invalid rectangle
384 if the picture contains no data.
385*/
386
387QRect QPicture::boundingRect() const
388{
389 Q_D(const QPicture);
390 // Use override rect where possible.
391 if (!d->override_rect.isEmpty())
392 return d->override_rect;
393
394 if (!d->formatOk)
395 d_ptr->checkFormat();
396
397 return d->brect;
398}
399
400/*!
401 Sets the picture's bounding rectangle to \a r. The automatically
402 calculated value is overridden.
403*/
404
405void QPicture::setBoundingRect(const QRect &r)
406{
407 d_func()->override_rect = r;
408}
409
410/*!
411 Replays the picture using \a painter, and returns true if
412 successful; otherwise returns false.
413
414 This function does exactly the same as QPainter::drawPicture()
415 with (x, y) = (0, 0).
416*/
417
418bool QPicture::play(QPainter *painter)
419{
420 Q_D(QPicture);
421
422 if (d->pictb.size() == 0) // nothing recorded
423 return true;
424
425 if (!d->formatOk && !d->checkFormat())
426 return false;
427
428 d->pictb.open(QIODevice::ReadOnly); // open buffer device
429 QDataStream s;
430 s.setDevice(&d->pictb); // attach data stream to buffer
431 s.device()->seek(10); // go directly to the data
432 s.setVersion(d->formatMajor == 4 ? 3 : d->formatMajor);
433
434 quint8 c, clen;
435 quint32 nrecords;
436 s >> c >> clen;
437 Q_ASSERT(c == QPicturePrivate::PdcBegin);
438 // bounding rect was introduced in ver 4. Read in checkFormat().
439 if (d->formatMajor >= 4) {
440 qint32 dummy;
441 s >> dummy >> dummy >> dummy >> dummy;
442 }
443 s >> nrecords;
444 if (!exec(painter, s, nrecords)) {
445 qWarning("QPicture::play: Format error");
446 d->pictb.close();
447 return false;
448 }
449 d->pictb.close();
450 return true; // no end-command
451}
452
453
454//
455// QFakeDevice is used to create fonts with a custom DPI
456//
457class QFakeDevice : public QPaintDevice
458{
459public:
460 QFakeDevice() { dpi_x = qt_defaultDpiX(); dpi_y = qt_defaultDpiY(); }
461 void setDpiX(int dpi) { dpi_x = dpi; }
462 void setDpiY(int dpi) { dpi_y = dpi; }
463 QPaintEngine *paintEngine() const { return 0; }
464 int metric(PaintDeviceMetric m) const
465 {
466 switch(m) {
467 case PdmPhysicalDpiX:
468 case PdmDpiX:
469 return dpi_x;
470 case PdmPhysicalDpiY:
471 case PdmDpiY:
472 return dpi_y;
473 default:
474 return QPaintDevice::metric(m);
475 }
476 }
477
478private:
479 int dpi_x;
480 int dpi_y;
481};
482
483/*!
484 \internal
485 Iterates over the internal picture data and draws the picture using
486 \a painter.
487*/
488
489bool QPicture::exec(QPainter *painter, QDataStream &s, int nrecords)
490{
491 Q_D(QPicture);
492#if defined(QT_DEBUG)
493 int strm_pos;
494#endif
495 quint8 c; // command id
496 quint8 tiny_len; // 8-bit length descriptor
497 qint32 len; // 32-bit length descriptor
498 qint16 i_16, i1_16, i2_16; // parameters...
499 qint8 i_8;
500 quint32 ul;
501 double dbl;
502 bool bl;
503 QByteArray str1;
504 QString str;
505 QPointF p, p1, p2;
506 QPoint ip, ip1, ip2;
507 QRect ir;
508 QRectF r;
509 QPolygonF a;
510 QPolygon ia;
511 QColor color;
512 QFont font;
513 QPen pen;
514 QBrush brush;
515 QRegion rgn;
516 QMatrix wmatrix;
517 QTransform matrix;
518
519 QTransform worldMatrix = painter->transform();
520 worldMatrix.scale(qreal(painter->device()->logicalDpiX()) / qreal(qt_defaultDpiX()),
521 qreal(painter->device()->logicalDpiY()) / qreal(qt_defaultDpiY()));
522 painter->setTransform(worldMatrix);
523
524 while (nrecords-- && !s.atEnd()) {
525 s >> c; // read cmd
526 s >> tiny_len; // read param length
527 if (tiny_len == 255) // longer than 254 bytes
528 s >> len;
529 else
530 len = tiny_len;
531#if defined(QT_DEBUG)
532 strm_pos = s.device()->pos();
533#endif
534 switch (c) { // exec cmd
535 case QPicturePrivate::PdcNOP:
536 break;
537 case QPicturePrivate::PdcDrawPoint:
538 if (d->formatMajor <= 5) {
539 s >> ip;
540 painter->drawPoint(ip);
541 } else {
542 s >> p;
543 painter->drawPoint(p);
544 }
545 break;
546 case QPicturePrivate::PdcDrawPoints:
547// ## implement me in the picture paint engine
548// s >> a >> i1_32 >> i2_32;
549// painter->drawPoints(a.mid(i1_32, i2_32));
550 break;
551 case QPicturePrivate::PdcDrawPath: {
552 QPainterPath path;
553 s >> path;
554 painter->drawPath(path);
555 break;
556 }
557 case QPicturePrivate::PdcDrawLine:
558 if (d->formatMajor <= 5) {
559 s >> ip1 >> ip2;
560 painter->drawLine(ip1, ip2);
561 } else {
562 s >> p1 >> p2;
563 painter->drawLine(p1, p2);
564 }
565 break;
566 case QPicturePrivate::PdcDrawRect:
567 if (d->formatMajor <= 5) {
568 s >> ir;
569 painter->drawRect(ir);
570 } else {
571 s >> r;
572 painter->drawRect(r);
573 }
574 break;
575 case QPicturePrivate::PdcDrawRoundRect:
576 if (d->formatMajor <= 5) {
577 s >> ir >> i1_16 >> i2_16;
578 painter->drawRoundedRect(ir, i1_16, i2_16, Qt::RelativeSize);
579 } else {
580 s >> r >> i1_16 >> i2_16;
581 painter->drawRoundedRect(r, i1_16, i2_16, Qt::RelativeSize);
582 }
583 break;
584 case QPicturePrivate::PdcDrawEllipse:
585 if (d->formatMajor <= 5) {
586 s >> ir;
587 painter->drawEllipse(ir);
588 } else {
589 s >> r;
590 painter->drawEllipse(r);
591 }
592 break;
593 case QPicturePrivate::PdcDrawArc:
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->drawArc(r, i1_16, i2_16);
602 break;
603 case QPicturePrivate::PdcDrawPie:
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->drawPie(r, i1_16, i2_16);
612 break;
613 case QPicturePrivate::PdcDrawChord:
614 if (d->formatMajor <= 5) {
615 s >> ir;
616 r = ir;
617 } else {
618 s >> r;
619 }
620 s >> i1_16 >> i2_16;
621 painter->drawChord(r, i1_16, i2_16);
622 break;
623 case QPicturePrivate::PdcDrawLineSegments:
624 s >> ia;
625 painter->drawLines(ia);
626 ia.clear();
627 break;
628 case QPicturePrivate::PdcDrawPolyline:
629 if (d->formatMajor <= 5) {
630 s >> ia;
631 painter->drawPolyline(ia);
632 ia.clear();
633 } else {
634 s >> a;
635 painter->drawPolyline(a);
636 a.clear();
637 }
638 break;
639 case QPicturePrivate::PdcDrawPolygon:
640 if (d->formatMajor <= 5) {
641 s >> ia >> i_8;
642 painter->drawPolygon(ia, i_8 ? Qt::WindingFill : Qt::OddEvenFill);
643 a.clear();
644 } else {
645 s >> a >> i_8;
646 painter->drawPolygon(a, i_8 ? Qt::WindingFill : Qt::OddEvenFill);
647 a.clear();
648 }
649 break;
650 case QPicturePrivate::PdcDrawCubicBezier: {
651 s >> ia;
652 QPainterPath path;
653 Q_ASSERT(ia.size() == 4);
654 path.moveTo(ia.at(0));
655 path.cubicTo(ia.at(1), ia.at(2), ia.at(3));
656 painter->strokePath(path, painter->pen());
657 a.clear();
658 }
659 break;
660 case QPicturePrivate::PdcDrawText:
661 s >> ip >> str1;
662 painter->drawText(ip, QString::fromLatin1(str1));
663 break;
664 case QPicturePrivate::PdcDrawTextFormatted:
665 s >> ir >> i_16 >> str1;
666 painter->drawText(ir, i_16, QString::fromLatin1(str1));
667 break;
668 case QPicturePrivate::PdcDrawText2:
669 if (d->formatMajor <= 5) {
670 s >> ip >> str;
671 painter->drawText(ip, str);
672 } else {
673 s >> p >> str;
674 painter->drawText(p, str);
675 }
676 break;
677 case QPicturePrivate::PdcDrawText2Formatted:
678 s >> ir;
679 s >> i_16;
680 s >> str;
681 painter->drawText(ir, i_16, str);
682 break;
683 case QPicturePrivate::PdcDrawTextItem: {
684 s >> p >> str >> font >> ul;
685
686 // the text layout direction is not used here because it's already
687 // aligned when QPicturePaintEngine::drawTextItem() serializes the
688 // drawText() call, therefore ul is unsed in this context
689
690 if (d->formatMajor >= 9) {
691 s >> dbl;
692 QFont fnt(font);
693 if (dbl != 1.0) {
694 QFakeDevice fake;
695 fake.setDpiX(qRound(dbl*qt_defaultDpiX()));
696 fake.setDpiY(qRound(dbl*qt_defaultDpiY()));
697 fnt = QFont(font, &fake);
698 }
699
700 qreal justificationWidth;
701 s >> justificationWidth;
702
703 int flags = Qt::TextSingleLine | Qt::TextDontClip | Qt::TextForceLeftToRight;
704
705 QSizeF size(1, 1);
706 if (justificationWidth > 0) {
707 size.setWidth(justificationWidth);
708 flags |= Qt::TextJustificationForced;
709 flags |= Qt::AlignJustify;
710 }
711
712 QFontMetrics fm(fnt);
713 QPointF pt(p.x(), p.y() - fm.ascent());
714 qt_format_text(fnt, QRectF(pt, size), flags, /*opt*/0,
715 str, /*brect=*/0, /*tabstops=*/0, /*...*/0, /*tabarraylen=*/0, painter);
716 } else {
717 qt_format_text(font, QRectF(p, QSizeF(1, 1)), Qt::TextSingleLine | Qt::TextDontClip, /*opt*/0,
718 str, /*brect=*/0, /*tabstops=*/0, /*...*/0, /*tabarraylen=*/0, painter);
719 }
720
721 break;
722 }
723 case QPicturePrivate::PdcDrawPixmap: {
724 QPixmap pixmap;
725 if (d->formatMajor < 4) {
726 s >> ip >> pixmap;
727 painter->drawPixmap(ip, pixmap);
728 } else if (d->formatMajor <= 5) {
729 s >> ir >> pixmap;
730 painter->drawPixmap(ir, pixmap);
731 } else {
732 QRectF sr;
733 if (d->in_memory_only) {
734 int index;
735 s >> r >> index >> sr;
736 Q_ASSERT(index < d->pixmap_list.size());
737 pixmap = d->pixmap_list.at(index);
738 } else {
739 s >> r >> pixmap >> sr;
740 }
741 painter->drawPixmap(r, pixmap, sr);
742 }
743 }
744 break;
745 case QPicturePrivate::PdcDrawTiledPixmap: {
746 QPixmap pixmap;
747 if (d->in_memory_only) {
748 int index;
749 s >> r >> index >> p;
750 Q_ASSERT(index < d->pixmap_list.size());
751 pixmap = d->pixmap_list.at(index);
752 } else {
753 s >> r >> pixmap >> p;
754 }
755 painter->drawTiledPixmap(r, pixmap, p);
756 }
757 break;
758 case QPicturePrivate::PdcDrawImage: {
759 QImage image;
760 if (d->formatMajor < 4) {
761 s >> p >> image;
762 painter->drawImage(p, image);
763 } else if (d->formatMajor <= 5){
764 s >> ir >> image;
765 painter->drawImage(ir, image, QRect(0, 0, ir.width(), ir.height()));
766 } else {
767 QRectF sr;
768 if (d->in_memory_only) {
769 int index;
770 s >> r >> index >> sr >> ul;
771 Q_ASSERT(index < d->image_list.size());
772 image = d->image_list.at(index);
773 } else {
774 s >> r >> image >> sr >> ul;
775 }
776 painter->drawImage(r, image, sr, Qt::ImageConversionFlags(ul));
777 }
778 }
779 break;
780 case QPicturePrivate::PdcBegin:
781 s >> ul; // number of records
782 if (!exec(painter, s, ul))
783 return false;
784 break;
785 case QPicturePrivate::PdcEnd:
786 if (nrecords == 0)
787 return true;
788 break;
789 case QPicturePrivate::PdcSave:
790 painter->save();
791 break;
792 case QPicturePrivate::PdcRestore:
793 painter->restore();
794 break;
795 case QPicturePrivate::PdcSetBkColor:
796 s >> color;
797 painter->setBackground(color);
798 break;
799 case QPicturePrivate::PdcSetBkMode:
800 s >> i_8;
801 painter->setBackgroundMode((Qt::BGMode)i_8);
802 break;
803 case QPicturePrivate::PdcSetROP: // NOP
804 s >> i_8;
805 break;
806 case QPicturePrivate::PdcSetBrushOrigin:
807 if (d->formatMajor <= 5) {
808 s >> ip;
809 painter->setBrushOrigin(ip);
810 } else {
811 s >> p;
812 painter->setBrushOrigin(p);
813 }
814 break;
815 case QPicturePrivate::PdcSetFont:
816 s >> font;
817 painter->setFont(font);
818 break;
819 case QPicturePrivate::PdcSetPen:
820 if (d->in_memory_only) {
821 int index;
822 s >> index;
823 Q_ASSERT(index < d->pen_list.size());
824 pen = d->pen_list.at(index);
825 } else {
826 s >> pen;
827 }
828 painter->setPen(pen);
829 break;
830 case QPicturePrivate::PdcSetBrush:
831 if (d->in_memory_only) {
832 int index;
833 s >> index;
834 Q_ASSERT(index < d->brush_list.size());
835 brush = d->brush_list.at(index);
836 } else {
837 s >> brush;
838 }
839 painter->setBrush(brush);
840 break;
841// #ifdef Q_Q3PAINTER
842// case QPicturePrivate::PdcSetTabStops:
843// s >> i_16;
844// painter->setTabStops(i_16);
845// break;
846// case QPicturePrivate::PdcSetTabArray:
847// s >> i_16;
848// if (i_16 == 0) {
849// painter->setTabArray(0);
850// } else {
851// int *ta = new int[i_16];
852// for (int i=0; i<i_16; i++) {
853// s >> i1_16;
854// ta[i] = i1_16;
855// }
856// painter->setTabArray(ta);
857// delete [] ta;
858// }
859// break;
860// #endif
861 case QPicturePrivate::PdcSetVXform:
862 s >> i_8;
863 painter->setViewTransformEnabled(i_8);
864 break;
865 case QPicturePrivate::PdcSetWindow:
866 if (d->formatMajor <= 5) {
867 s >> ir;
868 painter->setWindow(ir);
869 } else {
870 s >> r;
871 painter->setWindow(r.toRect());
872 }
873 break;
874 case QPicturePrivate::PdcSetViewport:
875 if (d->formatMajor <= 5) {
876 s >> ir;
877 painter->setViewport(ir);
878 } else {
879 s >> r;
880 painter->setViewport(r.toRect());
881 }
882 break;
883 case QPicturePrivate::PdcSetWXform:
884 s >> i_8;
885 painter->setMatrixEnabled(i_8);
886 break;
887 case QPicturePrivate::PdcSetWMatrix:
888 if (d->formatMajor >= 8) {
889 s >> matrix >> i_8;
890 } else {
891 s >> wmatrix >> i_8;
892 matrix = QTransform(wmatrix);
893 }
894 // i_8 is always false due to updateXForm() in qpaintengine_pic.cpp
895 painter->setTransform(matrix * worldMatrix, i_8);
896 break;
897// #ifdef Q_Q3PAINTER
898// case QPicturePrivate::PdcSaveWMatrix:
899// painter->saveWorldMatrix();
900// break;
901// case QPicturePrivate::PdcRestoreWMatrix:
902// painter->restoreWorldMatrix();
903// break;
904// #endif
905 case QPicturePrivate::PdcSetClip:
906 s >> i_8;
907 painter->setClipping(i_8);
908 break;
909 case QPicturePrivate::PdcSetClipRegion:
910 s >> rgn >> i_8;
911 if (d->formatMajor >= 9) {
912 painter->setClipRegion(rgn, Qt::ClipOperation(i_8));
913 } else {
914 painter->setClipRegion(rgn);
915 }
916 break;
917 case QPicturePrivate::PdcSetClipPath:
918 {
919 QPainterPath path;
920 s >> path >> i_8;
921 painter->setClipPath(path, Qt::ClipOperation(i_8));
922 break;
923 }
924 case QPicturePrivate::PdcSetRenderHint:
925 s >> ul;
926 painter->setRenderHint(QPainter::Antialiasing,
927 bool(ul & QPainter::Antialiasing));
928 painter->setRenderHint(QPainter::SmoothPixmapTransform,
929 bool(ul & QPainter::SmoothPixmapTransform));
930 break;
931 case QPicturePrivate::PdcSetCompositionMode:
932 s >> ul;
933 painter->setCompositionMode((QPainter::CompositionMode)ul);
934 break;
935 case QPicturePrivate::PdcSetClipEnabled:
936 s >> bl;
937 painter->setClipping(bl);
938 break;
939 case QPicturePrivate::PdcSetOpacity:
940 s >> dbl;
941 painter->setOpacity(qreal(dbl));
942 break;
943 default:
944 qWarning("QPicture::play: Invalid command %d", c);
945 if (len) // skip unknown command
946 s.device()->seek(s.device()->pos()+len);
947 }
948#if defined(QT_DEBUG)
949 //qDebug("device->at(): %i, strm_pos: %i len: %i", (int)s.device()->pos(), strm_pos, len);
950 Q_ASSERT(qint32(s.device()->pos() - strm_pos) == len);
951#endif
952 }
953 return false;
954}
955
956/*!
957 Internal implementation of the virtual QPaintDevice::metric()
958 function.
959
960 A picture has the following hard-coded values: numcolors=16777216
961 and depth=24.
962
963 \a m is the metric to get.
964*/
965
966int QPicture::metric(PaintDeviceMetric m) const
967{
968 int val;
969 QRect brect = boundingRect();
970 switch (m) {
971 case PdmWidth:
972 val = brect.width();
973 break;
974 case PdmHeight:
975 val = brect.height();
976 break;
977 case PdmWidthMM:
978 val = int(25.4/qt_defaultDpiX()*brect.width());
979 break;
980 case PdmHeightMM:
981 val = int(25.4/qt_defaultDpiY()*brect.height());
982 break;
983 case PdmDpiX:
984 case PdmPhysicalDpiX:
985 val = qt_defaultDpiX();
986 break;
987 case PdmDpiY:
988 case PdmPhysicalDpiY:
989 val = qt_defaultDpiY();
990 break;
991 case PdmNumColors:
992 val = 16777216;
993 break;
994 case PdmDepth:
995 val = 24;
996 break;
997 default:
998 val = 0;
999 qWarning("QPicture::metric: Invalid metric command");
1000 }
1001 return val;
1002}
1003
1004/*!
1005 \fn void QPicture::detach()
1006 \internal
1007 Detaches from shared picture data and makes sure that this picture
1008 is the only one referring to the data.
1009
1010 If multiple pictures share common data, this picture makes a copy
1011 of the data and detaches itself from the sharing mechanism.
1012 Nothing is done if there is just a single reference.
1013*/
1014
1015/*! \fn bool QPicture::isDetached() const
1016\internal
1017*/
1018void QPicture::detach_helper()
1019{
1020 Q_D(QPicture);
1021 QPicturePrivate *x = new QPicturePrivate;
1022 int pictsize = size();
1023 x->pictb.setData(data(), pictsize);
1024 if (d->pictb.isOpen()) {
1025 x->pictb.open(d->pictb.openMode());
1026 x->pictb.seek(d->pictb.pos());
1027 }
1028 x->trecs = d->trecs;
1029 x->formatOk = d->formatOk;
1030 x->formatMinor = d->formatMinor;
1031 x->brect = d->brect;
1032 x->override_rect = d->override_rect;
1033 if (!d->ref.deref())
1034 delete d;
1035 d_ptr = x;
1036}
1037
1038/*!
1039 Assigns picture \a p to this picture and returns a reference to
1040 this picture.
1041*/