1
/****************************************************************************
2
**
3
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4
** All rights reserved.
5
** Contact: Nokia Corporation (qt-info@nokia.com)
6
**
7
** This file is part of the QtGui module of the Qt Toolkit.
8
**
9
** $QT_BEGIN_LICENSE:LGPL$
10
** No Commercial Usage
11
** This file contains pre-release code and may not be distributed.
12
** You may use this file in accordance with the terms and conditions
13
** contained in the Technology Preview License Agreement accompanying
14
** this package.
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
** If you have questions regarding the use of this file, please contact
29
** Nokia at qt-info@nokia.com.
30
**
31
**
32
**
33
**
34
**
35
**
36
**
37
**
38
** $QT_END_LICENSE$
39
**
40
****************************************************************************/
41
42
#include "qpicture.h"
43
#include <private/qpicture_p.h>
44
45
#ifndef QT_NO_PICTURE
46
47
#include <private/qfactoryloader_p.h>
48
#include <private/qpaintengine_pic_p.h>
49
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
60
QT_BEGIN_NAMESPACE
61
62
void 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
108
const char  *qt_mfhdr_tag = "QPIC"; // header tag
109
static const quint16 mfhdr_maj = 11; // major version #
110
static const quint16 mfhdr_min = 0; // minor version #
111
Q_GUI_EXPORT extern int qt_defaultDpiX();
112
Q_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
129
QPicture::QPicture(int formatVersion)
130
    : QPaintDevice(),
131
      d_ptr(new QPicturePrivate)
132
{
133
    Q_D(QPicture);
134
135
    if (formatVersion == 0)
136
        qWarning("QPicture: invalid format version 0");
137
138
    // still accept the 0 default from before Qt 3.0.
139
    if (formatVersion > 0 && formatVersion != (int)mfhdr_maj) {
140
        d->formatMajor = formatVersion;
141
        d->formatMinor = 0;
142
        d->formatOk = false;
143
    } else {
144
        d->resetFormat();
145
    }
146
}
147
148
/*!
149
    Constructs a copy of \a pic.
150
151
    This constructor is fast thanks to \l{implicit sharing}.
152
*/
153
154
QPicture::QPicture(const QPicture &pic)
155
    : QPaintDevice(), d_ptr(pic.d_ptr)
156
{
157
}
158
159
/*! \internal */
160
QPicture::QPicture(QPicturePrivate &dptr)
161
    : QPaintDevice(),
162
      d_ptr(&dptr)
163
{
164
}
165
166
/*!
167
    Destroys the picture.
168
*/
169
QPicture::~QPicture()
170
{
171
}
172
173
/*!
174
  \internal
175
*/
176
int QPicture::devType() const
177
{
178
    return QInternal::Picture;
179
}
180
181
/*!
182
    \fn bool QPicture::isNull() const
183
184
    Returns true if the picture contains no data; otherwise returns
185
    false.
186
*/
187
188
/*!
189
    \fn uint QPicture::size() const
190
191
    Returns the size of the picture data.
192
193
    \sa data()
194
*/
195
196
/*!
197
    \fn const char* QPicture::data() const
198
199
    Returns a pointer to the picture data. The pointer is only valid
200
    until the next non-const function is called on this picture. The
201
    returned pointer is 0 if the picture contains no data.
202
203
    \sa size(), isNull()
204
*/
205
206
207
bool QPicture::isNull() const
208
{
209
    return d_func()->pictb.buffer().isNull();
210
}
211
212
uint QPicture::size() const
213
{
214
    return d_func()->pictb.buffer().size();
215
}
216
217
const char* QPicture::data() const
218
{
219
    return d_func()->pictb.buffer();
220
}
221
222
void QPicture::detach()
223
{
224
    d_ptr.detach();
225
}
226
227
bool QPicture::isDetached() const
228
{
229
    return d_func()->ref == 1;
230
}
231
232
/*!
233
    Sets the picture data directly from \a data and \a size. This
234
    function copies the input data.
235
236
    \sa data(), size()
237
*/
238
239
void QPicture::setData(const char* data, uint size)
240
{
241
    detach();
242
    d_func()->pictb.setData(data, size);
243
    d_func()->resetFormat();                                // we'll have to check
244
}
245
246
247
/*!
248
    Loads a picture from the file specified by \a fileName and returns
249
    true if successful; otherwise returns false.
250
251
    Please note that the \a format parameter has been deprecated and
252
    will have no effect.
253
254
    \sa save()
255
*/
256
257
bool QPicture::load(const QString &fileName, const char *format)
258
{
259
    QFile f(fileName);
260
    if (!f.open(QIODevice::ReadOnly))
261
        return false;
262
    return load(&f, format);
263
}
264
265
/*!
266
    \overload
267
268
    \a dev is the device to use for loading.
269
*/
270
271
bool QPicture::load(QIODevice *dev, const char *format)
272
{
273
    if(format) {
274
#ifndef QT_NO_PICTUREIO
275
        QPictureIO io(dev, format);
276
        bool result = io.read();
277
        if (result) {
278
            operator=(io.picture());
279
280
        } else if (format)
281
#else
282
            bool result = false;
283
#endif
284
        {
285
            qWarning("QPicture::load: No such picture format: %s", format);
286
        }
287
        return result;
288
    }
289
290
    detach();
291
    QByteArray a = dev->readAll();
292
293
    d_func()->pictb.setData(a);                        // set byte array in buffer
294
    return d_func()->checkFormat();
295
}
296
297
/*!
298
    Saves a picture to the file specified by \a fileName and returns
299
    true if successful; otherwise returns false.
300
301
    Please note that the \a format parameter has been deprecated and
302
    will have no effect.
303
304
    \sa load()
305
*/
306
307
bool QPicture::save(const QString &fileName, const char *format)
308
{
309
    if (paintingActive()) {
310
        qWarning("QPicture::save: still being painted on. "
311
                  "Call QPainter::end() first");
312
        return false;
313
    }
314
315
316
    if(format) {
317
#ifndef QT_NO_PICTUREIO
318
        QPictureIO io(fileName, format);
319
        bool result = io.write();
320
        if (result) {
321
            operator=(io.picture());
322
        } else if (format)
323
#else
324
        bool result = false;
325
#endif
326
        {
327
            qWarning("QPicture::save: No such picture format: %s", format);
328
        }
329
        return result;
330
    }
331
332
    QFile f(fileName);
333
    if (!f.open(QIODevice::WriteOnly))
334
        return false;
335
    return save(&f, format);
336
}
337
338
/*!
339
    \overload
340
341
    \a dev is the device to use for saving.
342
*/
343
344
bool QPicture::save(QIODevice *dev, const char *format)
345
{
346
    if (paintingActive()) {
347
        qWarning("QPicture::save: still being painted on. "
348
                  "Call QPainter::end() first");
349
        return false;
350
    }
351
352
    if(format) {
353
#ifndef QT_NO_PICTUREIO
354
        QPictureIO io(dev, format);
355
        bool result = io.write();
356
        if (result) {
357
            operator=(io.picture());
358
        } else if (format)
359
#else
360
        bool result = false;
361
#endif
362
        {
363
            qWarning("QPicture::save: No such picture format: %s", format);
364
        }
365
        return result;
366
    }
367
368
    dev->write(d_func()->pictb.buffer(), d_func()->pictb.buffer().size());
369
    return true;
370
}
371
372
/*!
373
    Returns the picture's bounding rectangle or an invalid rectangle
374
    if the picture contains no data.
375
*/
376
377
QRect QPicture::boundingRect() const
378
{
379
    Q_D(const QPicture);
380
    // Use override rect where possible.
381
    if (!d->override_rect.isEmpty())
382
        return d->override_rect;
383
384
    if (!d->formatOk)
385
        d_ptr->checkFormat();
386
387
    return d->brect;
388
}
389
390
/*!
391
    Sets the picture's bounding rectangle to \a r. The automatically
392
    calculated value is overridden.
393
*/
394
395
void QPicture::setBoundingRect(const QRect &r)
396
{
397
    d_func()->override_rect = r;
398
}
399
400
/*!
401
    Replays the picture using \a painter, and returns true if
402
    successful; otherwise returns false.
403
404
    This function does exactly the same as QPainter::drawPicture()
405
    with (x, y) = (0, 0).
406
*/
407
408
bool QPicture::play(QPainter *painter)
409
{
410
    Q_D(QPicture);
411
412
    if (d->pictb.size() == 0)                        // nothing recorded
413
        return true;
414
415
    if (!d->formatOk && !d->checkFormat())
416
        return false;
417
418
    d->pictb.open(QIODevice::ReadOnly);                // open buffer device
419
    QDataStream s;
420
    s.setDevice(&d->pictb);                        // attach data stream to buffer
421
    s.device()->seek(10);                        // go directly to the data
422
    s.setVersion(d->formatMajor == 4 ? 3 : d->formatMajor);
423
424
    quint8  c, clen;
425
    quint32 nrecords;
426
    s >> c >> clen;
427
    Q_ASSERT(c == QPicturePrivate::PdcBegin);
428
    // bounding rect was introduced in ver 4. Read in checkFormat().
429
    if (d->formatMajor >= 4) {
430
        qint32 dummy;
431
        s >> dummy >> dummy >> dummy >> dummy;
432
    }
433
    s >> nrecords;
434
    if (!exec(painter, s, nrecords)) {
435
        qWarning("QPicture::play: Format error");
436
        d->pictb.close();
437
        return false;
438
    }
439
    d->pictb.close();
440
    return true;                                // no end-command
441
}
442
443
444
//
445
// QFakeDevice is used to create fonts with a custom DPI
446
//
447
class QFakeDevice : public QPaintDevice
448
{
449
public:
450
    QFakeDevice() { dpi_x = qt_defaultDpiX(); dpi_y = qt_defaultDpiY(); }
451
    void setDpiX(int dpi) { dpi_x = dpi; }
452
    void setDpiY(int dpi) { dpi_y = dpi; }
453
    QPaintEngine *paintEngine() const { return 0; }
454
    int metric(PaintDeviceMetric m) const
455
    {
456
        switch(m) {
457
            case PdmPhysicalDpiX:
458
            case PdmDpiX:
459
                return dpi_x;
460
            case PdmPhysicalDpiY:
461
            case PdmDpiY:
462
                return dpi_y;
463
            default:
464
                return QPaintDevice::metric(m);
465
        }
466
    }
467
468
private:
469
    int dpi_x;
470
    int dpi_y;
471
};
472
473
/*!
474
  \internal
475
  Iterates over the internal picture data and draws the picture using
476
  \a painter.
477
*/
478
479
bool QPicture::exec(QPainter *painter, QDataStream &s, int nrecords)
480
{
481
    Q_D(QPicture);
482
#if defined(QT_DEBUG)
483
    int                strm_pos;
484
#endif
485
    quint8     c;                      // command id
486
    quint8     tiny_len;               // 8-bit length descriptor
487
    qint32     len;                    // 32-bit length descriptor
488
    qint16     i_16, i1_16, i2_16;     // parameters...
489
    qint8      i_8;
490
    quint32    ul;
491
    double     dbl;
492
    bool       bl;
493
    QByteArray  str1;
494
    QString     str;
495
    QPointF     p, p1, p2;
496
    QPoint      ip, ip1, ip2;
497
    QRect       ir;
498
    QRectF      r;
499
    QPolygonF   a;
500
    QPolygon    ia;
501
    QColor      color;
502
    QFont       font;
503
    QPen        pen;
504
    QBrush      brush;
505
    QRegion     rgn;
506
    QMatrix     wmatrix;
507
    QTransform  matrix;
508
509
    QTransform worldMatrix = painter->transform();
510
    worldMatrix.scale(qreal(painter->device()->logicalDpiX()) / qreal(qt_defaultDpiX()),
511
                      qreal(painter->device()->logicalDpiY()) / qreal(qt_defaultDpiY()));
512
    painter->setTransform(worldMatrix);
513
514
    while (nrecords-- && !s.atEnd()) {
515
        s >> c;                 // read cmd
516
        s >> tiny_len;          // read param length
517
        if (tiny_len == 255)    // longer than 254 bytes
518
            s >> len;
519
        else
520
            len = tiny_len;
521
#if defined(QT_DEBUG)
522
        strm_pos = s.device()->pos();
523
#endif
524
        switch (c) {            // exec cmd
525
        case QPicturePrivate::PdcNOP:
526
            break;
527
        case QPicturePrivate::PdcDrawPoint:
528
            if (d->formatMajor <= 5) {
529
                s >> ip;
530
                painter->drawPoint(ip);
531
            } else {
532
                s >> p;
533
                painter->drawPoint(p);
534
            }
535
            break;
536
        case QPicturePrivate::PdcDrawPoints:
537
// ## implement me in the picture paint engine
538
//                 s >> a >> i1_32 >> i2_32;
539
//                 painter->drawPoints(a.mid(i1_32, i2_32));
540
            break;
541
        case QPicturePrivate::PdcDrawPath: {
542
            QPainterPath path;
543
            s >> path;
544
            painter->drawPath(path);
545
            break;
546
        }
547
        case QPicturePrivate::PdcDrawLine:
548
            if (d->formatMajor <= 5) {
549
                s >> ip1 >> ip2;
550
                painter->drawLine(ip1, ip2);
551
            } else {
552
                s >> p1 >> p2;
553
                painter->drawLine(p1, p2);
554
            }
555
            break;
556
        case QPicturePrivate::PdcDrawRect:
557
            if (d->formatMajor <= 5) {
558
                s >> ir;
559
                painter->drawRect(ir);
560
            } else {
561
                s >> r;
562
                painter->drawRect(r);
563
            }
564
            break;
565
        case QPicturePrivate::PdcDrawRoundRect:
566
            if (d->formatMajor <= 5) {
567
                s >> ir >> i1_16 >> i2_16;
568
                painter->drawRoundedRect(ir, i1_16, i2_16, Qt::RelativeSize);
569
            } else {
570
                s >> r >> i1_16 >> i2_16;
571
                painter->drawRoundedRect(r, i1_16, i2_16, Qt::RelativeSize);
572
            }
573
            break;
574
        case QPicturePrivate::PdcDrawEllipse:
575
            if (d->formatMajor <= 5) {
576
                s >> ir;
577
                painter->drawEllipse(ir);
578
            } else {
579
                s >> r;
580
                painter->drawEllipse(r);
581
            }
582
            break;
583
        case QPicturePrivate::PdcDrawArc:
584
            if (d->formatMajor <= 5) {
585
                s >> ir;
586
                r = ir;
587
            } else {
588
                s >> r;
589
            }
590
            s >> i1_16 >> i2_16;
591
            painter->drawArc(r, i1_16, i2_16);
592
            break;
593
        case QPicturePrivate::PdcDrawPie:
594
            if (d->formatMajor <= 5) {
595
                s >> ir;
596
                r = ir;
597
            } else {
598
                s >> r;
599
            }
600
            s >> i1_16 >> i2_16;
601
            painter->drawPie(r, i1_16, i2_16);
602
            break;
603
        case QPicturePrivate::PdcDrawChord:
604
            if (d->formatMajor <= 5) {
605
                s >> ir;
606
                r = ir;
607
            } else {
608
                s >> r;
609
            }
610
            s >> i1_16 >> i2_16;
611
            painter->drawChord(r, i1_16, i2_16);
612
            break;
613
        case QPicturePrivate::PdcDrawLineSegments:
614
            s >> ia;
615
            painter->drawLines(ia);
616
            ia.clear();
617
            break;
618
        case QPicturePrivate::PdcDrawPolyline:
619
            if (d->formatMajor <= 5) {
620
                s >> ia;
621
                painter->drawPolyline(ia);
622
                ia.clear();
623
            } else {
624
                s >> a;
625
                painter->drawPolyline(a);
626
                a.clear();
627
            }
628
            break;
629
        case QPicturePrivate::PdcDrawPolygon:
630
            if (d->formatMajor <= 5) {
631
                s >> ia >> i_8;
632
                painter->drawPolygon(ia, i_8 ? Qt::WindingFill : Qt::OddEvenFill);
633
                a.clear();
634
            } else {
635
                s >> a >> i_8;
636
                painter->drawPolygon(a, i_8 ? Qt::WindingFill : Qt::OddEvenFill);
637
                a.clear();
638
            }
639
            break;
640
        case QPicturePrivate::PdcDrawCubicBezier: {
641
            s >> ia;
642
            QPainterPath path;
643
            Q_ASSERT(ia.size() == 4);
644
            path.moveTo(ia.at(0));
645
            path.cubicTo(ia.at(1), ia.at(2), ia.at(3));
646
            painter->strokePath(path, painter->pen());
647
            a.clear();
648
        }
649
            break;
650
        case QPicturePrivate::PdcDrawText:
651
            s >> ip >> str1;
652
            painter->drawText(ip, QString::fromLatin1(str1));
653
            break;
654
        case QPicturePrivate::PdcDrawTextFormatted:
655
            s >> ir >> i_16 >> str1;
656
            painter->drawText(ir, i_16, QString::fromLatin1(str1));
657
            break;
658
        case QPicturePrivate::PdcDrawText2:
659
            if (d->formatMajor <= 5) {
660
                s >> ip >> str;
661
                painter->drawText(ip, str);
662
            } else {
663
                s >> p >> str;
664
                painter->drawText(p, str);
665
            }
666
            break;
667
        case QPicturePrivate::PdcDrawText2Formatted:
668
            s >> ir;
669
            s >> i_16;
670
            s >> str;
671
            painter->drawText(ir, i_16, str);
672
            break;
673
        case QPicturePrivate::PdcDrawTextItem: {
674
            s >> p >> str >> font >> ul;
675
676
            // the text layout direction is not used here because it's already
677
            // aligned when QPicturePaintEngine::drawTextItem() serializes the
678
            // drawText() call, therefore ul is unsed in this context
679
680
            if (d->formatMajor >= 9) {
681
                s >> dbl;
682
                QFont fnt(font);
683
                if (dbl != 1.0) {
684
                    QFakeDevice fake;
685
                    fake.setDpiX(qRound(dbl*qt_defaultDpiX()));
686
                    fake.setDpiY(qRound(dbl*qt_defaultDpiY()));
687
                    fnt = QFont(font, &fake);
688
                }
689
690
                qreal justificationWidth;
691
                s >> justificationWidth;
692
693
                int flags = Qt::TextSingleLine | Qt::TextDontClip | Qt::TextForceLeftToRight;
694
695
                QSizeF size(1, 1);
696
                if (justificationWidth > 0) {
697
                    size.setWidth(justificationWidth);
698
                    flags |= Qt::TextJustificationForced;
699
                    flags |= Qt::AlignJustify;
700
                }
701
702
                QFontMetrics fm(fnt);
703
                QPointF pt(p.x(), p.y() - fm.ascent());
704
                qt_format_text(fnt, QRectF(pt, size), flags, /*opt*/0,
705
                               str, /*brect=*/0, /*tabstops=*/0, /*...*/0, /*tabarraylen=*/0, painter);
706
            } else {
707
                qt_format_text(font, QRectF(p, QSizeF(1, 1)), Qt::TextSingleLine | Qt::TextDontClip, /*opt*/0,
708
                               str, /*brect=*/0, /*tabstops=*/0, /*...*/0, /*tabarraylen=*/0, painter);
709
            }
710
711
            break;
712
        }
713
        case QPicturePrivate::PdcDrawPixmap: {
714
            QPixmap pixmap;
715
            if (d->formatMajor < 4) {
716
                s >> ip >> pixmap;
717
                painter->drawPixmap(ip, pixmap);
718
            } else if (d->formatMajor <= 5) {
719
                s >> ir >> pixmap;
720
                painter->drawPixmap(ir, pixmap);
721
            } else {
722
                QRectF sr;
723
                if (d->in_memory_only) {
724
                    int index;
725
                    s >> r >> index >> sr;
726
                    Q_ASSERT(index < d->pixmap_list.size());
727
                    pixmap = d->pixmap_list.at(index);
728
                } else {
729
                    s >> r >> pixmap >> sr;
730
                }
731
                painter->drawPixmap(r, pixmap, sr);
732
            }
733
        }
734
            break;
735
        case QPicturePrivate::PdcDrawTiledPixmap: {
736
            QPixmap pixmap;
737
            if (d->in_memory_only) {
738
                int index;
739
                s >> r >> index >> p;
740
                Q_ASSERT(index < d->pixmap_list.size());
741
                pixmap = d->pixmap_list.at(index);
742
            } else {
743
                s >> r >> pixmap >> p;
744
            }
745
            painter->drawTiledPixmap(r, pixmap, p);
746
        }
747
            break;
748
        case QPicturePrivate::PdcDrawImage: {
749
            QImage image;
750
            if (d->formatMajor < 4) {
751
                s >> p >> image;
752
                painter->drawImage(p, image);
753
            } else if (d->formatMajor <= 5){
754
                s >> ir >> image;
755
                painter->drawImage(ir, image, QRect(0, 0, ir.width(), ir.height()));
756
            } else {
757
                QRectF sr;
758
                if (d->in_memory_only) {
759
                    int index;
760
                    s >> r >> index >> sr >> ul;
761
                    Q_ASSERT(index < d->image_list.size());
762
                    image = d->image_list.at(index);
763
                } else {
764
                    s >> r >> image >> sr >> ul;
765
                }
766
                painter->drawImage(r, image, sr, Qt::ImageConversionFlags(ul));
767
            }
768
        }
769
            break;
770
        case QPicturePrivate::PdcBegin:
771
            s >> ul;                        // number of records
772
            if (!exec(painter, s, ul))
773
                return false;
774
            break;
775
        case QPicturePrivate::PdcEnd:
776
            if (nrecords == 0)
777
                return true;
778
            break;
779
        case QPicturePrivate::PdcSave:
780
            painter->save();
781
            break;
782
        case QPicturePrivate::PdcRestore:
783
            painter->restore();
784
            break;
785
        case QPicturePrivate::PdcSetBkColor:
786
            s >> color;
787
            painter->setBackground(color);
788
            break;
789
        case QPicturePrivate::PdcSetBkMode:
790
            s >> i_8;
791
            painter->setBackgroundMode((Qt::BGMode)i_8);
792
            break;
793
        case QPicturePrivate::PdcSetROP: // NOP
794
            s >> i_8;
795
            break;
796
        case QPicturePrivate::PdcSetBrushOrigin:
797
            if (d->formatMajor <= 5) {
798
                s >> ip;
799
                painter->setBrushOrigin(ip);
800
            } else {
801
                s >> p;
802
                painter->setBrushOrigin(p);
803
            }
804
            break;
805
        case QPicturePrivate::PdcSetFont:
806
            s >> font;
807
            painter->setFont(font);
808
            break;
809
        case QPicturePrivate::PdcSetPen:
810
            if (d->in_memory_only) {
811
                int index;
812
                s >> index;
813
                Q_ASSERT(index < d->pen_list.size());
814
                pen = d->pen_list.at(index);
815
            } else {
816
                s >> pen;
817
            }
818
            painter->setPen(pen);
819
            break;
820
        case QPicturePrivate::PdcSetBrush:
821
            if (d->in_memory_only) {
822
                int index;
823
                s >> index;
824
                Q_ASSERT(index < d->brush_list.size());
825
                brush = d->brush_list.at(index);
826
            } else {
827
                s >> brush;
828
            }
829
            painter->setBrush(brush);
830
            break;
831
// #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
958
int 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
 */
1014
void 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
*/
1026
QPicture& 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
*/
1037
QPicturePrivate::QPicturePrivate()
1038
    : in_memory_only(false)
1039
{
1040
}
1041
1042
/*!
1043
  \internal
1044
1045
  Copy-Constructs a QPicturePrivate. Needed when detaching.
1046
*/
1047
QPicturePrivate::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
1068
void 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
*/
1083
bool 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 */
1149
QPaintEngine *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
1168
QDataStream &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
1187
QDataStream &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
1211
QT_BEGIN_INCLUDE_NAMESPACE
1212
#include "qregexp.h"
1213
#include "qapplication.h"
1214
#include "qpictureformatplugin.h"
1215
QT_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
1227
const 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
*/
1240
QList<QByteArray> QPicture::inputFormats()
1241
{
1242
    return QPictureIO::inputFormats();
1243
}
1244
1245
static 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
*/
1265
QStringList 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
*/
1283
QStringList 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
*/
1296
QList<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
1326
struct 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
1343
QPictureIO::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
1353
QPictureIO::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
1365
QPictureIO::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
1376
void 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
1390
QPictureIO::~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
1402
class QPictureHandler
1403
{
1404
public:
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
1415
QPictureHandler::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
1429
typedef QList<QPictureHandler *> QPHList;
1430
Q_GLOBAL_STATIC(QPHList, pictureHandlers)
1431
1432
#ifndef QT_NO_LIBRARY
1433
Q_GLOBAL_STATIC(QMutex, mutex)
1434
Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, factoryLoader,
1435
                          (QPictureFormatInterface_iid,
1436
                           QLatin1String("/pictureformats")))
1437
#endif
1438
void 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
1450
static 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
1459
void 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
1467
static 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
1520
void 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
*/
1544
const 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
*/
1552
int 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
*/
1558
const char *QPictureIO::format() const { return d->frmt; }
1559
1560
/*!
1561
    Returns the IO device currently set.
1562
1563
    \sa setIODevice()
1564
*/
1565
QIODevice *QPictureIO::ioDevice() const { return d->iodev; }
1566
1567
/*!
1568
    Returns the file name currently set.
1569
1570
    \sa setFileName()
1571
*/
1572
QString QPictureIO::fileName() const { return d->fname; }
1573
1574
1575
/*!
1576
    Returns the picture description string.
1577
1578
    \sa setDescription()
1579
*/
1580
QString QPictureIO::description() const { return d->descr; }
1581
1582
/*!
1583
    Sets the picture to \a picture.
1584
1585
    \sa picture()
1586
*/
1587
void 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
*/
1598
void 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
*/
1616
void 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
*/
1632
void 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
*/
1643
void 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
*/
1654
int 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
1670
void 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
1681
const 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
1697
void 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
*/
1715
void 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
*/
1725
float 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
1738
void 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
1750
QByteArray 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
1774
QByteArray 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
*/
1815
QList<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
*/
1838
QList<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
*/
1876
bool 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
*/
1945
bool 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
1980
QT_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
*/