src/gui/image/qpicture.cpp

Go to the documentation of this file.
00001 /****************************************************************************
00002 **
00003 ** Copyright (C) 1992-2006 Trolltech ASA. All rights reserved.
00004 **
00005 ** This file is part of the QtGui module of the Qt Toolkit.
00006 **
00007 ** This file may be used under the terms of the GNU General Public
00008 ** License version 2.0 as published by the Free Software Foundation
00009 ** and appearing in the file LICENSE.GPL included in the packaging of
00010 ** this file.  Please review the following information to ensure GNU
00011 ** General Public Licensing requirements will be met:
00012 ** http://www.trolltech.com/products/qt/opensource.html
00013 **
00014 ** If you are unsure which license is appropriate for your use, please
00015 ** review the following information:
00016 ** http://www.trolltech.com/products/qt/licensing.html or contact the
00017 ** sales department at sales@trolltech.com.
00018 **
00019 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00020 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00021 **
00022 ****************************************************************************/
00023 
00024 #include "qpicture.h"
00025 #include <private/qpicture_p.h>
00026 
00027 #ifndef QT_NO_PICTURE
00028 
00029 #include <private/qfactoryloader_p.h>
00030 #include <private/qpaintengine_pic_p.h>
00031 
00032 #include "qdatastream.h"
00033 #include "qfile.h"
00034 #include "qimage.h"
00035 #include "qmutex.h"
00036 #include "qpainter.h"
00037 #include "qpainterpath.h"
00038 #include "qpixmap.h"
00039 #include "qregion.h"
00040 #include "qdebug.h"
00041 
00042 void qt_format_text(const QFont &fnt, const QRectF &_r,
00043                     int tf, const QString& str, QRectF *brect,
00044                     int tabstops, int *, int tabarraylen,
00045                     QPainter *painter);
00046 
00094 const char  *qt_mfhdr_tag = "QPIC"; // header tag
00095 static const quint16 mfhdr_maj = 8; // major version #
00096 static const quint16 mfhdr_min = 0; // minor version #
00097 extern int qt_defaultDpi();
00098 
00114 QPicture::QPicture(int formatVersion)
00115     : QPaintDevice(),
00116       d_ptr(new QPicturePrivate)
00117 {
00118     Q_D(QPicture);
00119     d_ptr->q_ptr = this;
00120     d->paintEngine = 0;
00121 
00122     if (formatVersion == 0)
00123         qWarning("QPicture: invalid format version 0");
00124 
00125     // still accept the 0 default from before Qt 3.0.
00126     if (formatVersion > 0 && formatVersion != (int)mfhdr_maj) {
00127         d->formatMajor = formatVersion;
00128         d->formatMinor = 0;
00129         d->formatOk = false;
00130     }
00131     else {
00132         d->resetFormat();
00133     }
00134 }
00135 
00142 QPicture::QPicture(const QPicture &pic)
00143     : QPaintDevice(), d_ptr(pic.d_ptr)
00144 {
00145     d_func()->ref.ref();
00146 }
00147 
00149 QPicture::QPicture(QPicturePrivate &dptr)
00150     : QPaintDevice(),
00151       d_ptr(&dptr)
00152 {
00153     d_ptr->q_ptr = this;
00154 }
00155 
00159 QPicture::~QPicture()
00160 {
00161     if (!d_func()->ref.deref()) {
00162         delete d_func()->paintEngine;
00163         delete d_func();
00164     }
00165 }
00166 
00170 int QPicture::devType() const
00171 {
00172     return QInternal::Picture;
00173 }
00174 
00201 bool QPicture::isNull() const
00202 {
00203     return d_func()->pictb.buffer().isNull();
00204 }
00205 
00206 uint QPicture::size() const
00207 {
00208     return d_func()->pictb.buffer().size();
00209 }
00210 
00211 const char* QPicture::data() const
00212 {
00213     return d_func()->pictb.buffer();
00214 }
00215 
00216 void QPicture::detach()
00217 {
00218     if (d_func()->ref != 1)
00219         detach_helper();
00220 }
00221 
00222 bool QPicture::isDetached() const
00223 {
00224     return d_func()->ref == 1;
00225 }
00226 
00234 void QPicture::setData(const char* data, uint size)
00235 {
00236     detach();
00237     d_func()->pictb.setData(data, size);
00238     d_func()->resetFormat();                                // we'll have to check
00239 }
00240 
00241 
00252 bool QPicture::load(const QString &fileName, const char *format)
00253 {
00254     QFile f(fileName);
00255     if (!f.open(QIODevice::ReadOnly))
00256         return false;
00257     return load(&f, format);
00258 }
00259 
00266 bool QPicture::load(QIODevice *dev, const char *format)
00267 {
00268     if(format) {
00269 #ifndef QT_NO_PICTUREIO
00270         QPictureIO io(dev, format);
00271         bool result = io.read();
00272         if (result) {
00273             operator=(io.picture());
00274 
00275         } else if (format)
00276 #else
00277             bool result = false;
00278 #endif
00279         {
00280             qWarning("QPicture::load: No such picture format: %s", format);
00281         }
00282         return result;
00283     }
00284 
00285     detach();
00286     QByteArray a = dev->readAll();
00287 
00288     d_func()->pictb.setData(a);                        // set byte array in buffer
00289     return d_func()->checkFormat();
00290 }
00291 
00302 bool QPicture::save(const QString &fileName, const char *format)
00303 {
00304     if (paintingActive()) {
00305         qWarning("QPicture::save: still being painted on. "
00306                   "Call QPainter::end() first");
00307         return false;
00308     }
00309 
00310 
00311     if(format) {
00312 #ifndef QT_NO_PICTUREIO
00313         QPictureIO io(fileName, format);
00314         bool result = io.write();
00315         if (result) {
00316             operator=(io.picture());
00317         } else if (format)
00318 #else
00319         bool result = false;
00320 #endif
00321         {
00322             qWarning("QPicture::save: No such picture format: %s", format);
00323         }
00324         return result;
00325     }
00326 
00327     QFile f(fileName);
00328     if (!f.open(QIODevice::WriteOnly))
00329         return false;
00330     return save(&f, format);
00331 }
00332 
00339 bool QPicture::save(QIODevice *dev, const char *format)
00340 {
00341     if (paintingActive()) {
00342         qWarning("QPicture::save: still being painted on. "
00343                   "Call QPainter::end() first");
00344         return false;
00345     }
00346 
00347     if(format) {
00348 #ifndef QT_NO_PICTUREIO
00349         QPictureIO io(dev, format);
00350         bool result = io.write();
00351         if (result) {
00352             operator=(io.picture());
00353         } else if (format)
00354 #else
00355         bool result = false;
00356 #endif
00357         {
00358             qWarning("QPicture::save: No such picture format: %s", format);
00359         }
00360         return result;
00361     }
00362 
00363     dev->write(d_func()->pictb.buffer(), d_func()->pictb.buffer().size());
00364     return true;
00365 }
00366 
00372 QRect QPicture::boundingRect() const
00373 {
00374     Q_D(const QPicture);
00375     // Use override rect where possible.
00376     if (!d->override_rect.isEmpty())
00377         return d->override_rect;
00378 
00379     if (!d->formatOk)
00380         d_ptr->checkFormat();
00381 
00382     return d->brect;
00383 }
00384 
00390 void QPicture::setBoundingRect(const QRect &r)
00391 {
00392     d_func()->override_rect = r;
00393 }
00394 
00403 bool QPicture::play(QPainter *painter)
00404 {
00405     Q_D(QPicture);
00406 
00407     if (d->pictb.size() == 0)                        // nothing recorded
00408         return true;
00409 
00410     if (!d->formatOk && !d->checkFormat())
00411         return false;
00412 
00413     d->pictb.open(QIODevice::ReadOnly);                // open buffer device
00414     QDataStream s;
00415     s.setDevice(&d->pictb);                        // attach data stream to buffer
00416     s.device()->seek(10);                        // go directly to the data
00417     s.setVersion(d->formatMajor == 4 ? 3 : d->formatMajor);
00418 
00419     quint8  c, clen;
00420     quint32 nrecords;
00421     s >> c >> clen;
00422     Q_ASSERT(c == QPicturePrivate::PdcBegin);
00423     // bounding rect was introduced in ver 4. Read in checkFormat().
00424     if (d->formatMajor >= 4) {
00425         qint32 dummy;
00426         s >> dummy >> dummy >> dummy >> dummy;
00427     }
00428     s >> nrecords;
00429     if (!exec(painter, s, nrecords)) {
00430         qWarning("QPicture::play: Format error");
00431         d->pictb.close();
00432         return false;
00433     }
00434     d->pictb.close();
00435     return true;                                // no end-command
00436 }
00437 
00438 
00445 bool QPicture::exec(QPainter *painter, QDataStream &s, int nrecords)
00446 {
00447     Q_D(QPicture);
00448 #if defined(QT_DEBUG)
00449     int                strm_pos;
00450 #endif
00451     quint8     c;                      // command id
00452     quint8     tiny_len;               // 8-bit length descriptor
00453     qint32     len;                    // 32-bit length descriptor
00454     qint16     i_16, i1_16, i2_16;     // parameters...
00455     qint8      i_8;
00456     quint32    ul;
00457     QByteArray  str1;
00458     QString     str;
00459     QPointF     p, p1, p2;
00460     QRectF      r;
00461     QPolygonF   a;
00462     QPolygon    pa;
00463     QColor      color;
00464     QFont       font;
00465     QPen        pen;
00466     QBrush      brush;
00467     QRegion     rgn;
00468     QMatrix     matrix;
00469 
00470     QMatrix worldMatrix = painter->matrix();
00471     worldMatrix.scale(qreal(painter->device()->logicalDpiX()) / qreal(qt_defaultDpi()),
00472                       qreal(painter->device()->logicalDpiY()) / qreal(qt_defaultDpi()));
00473     painter->setMatrix(worldMatrix);
00474 
00475     while (nrecords-- && !s.atEnd()) {
00476         s >> c;                 // read cmd
00477         s >> tiny_len;          // read param length
00478         if (tiny_len == 255)    // longer than 254 bytes
00479             s >> len;
00480         else
00481             len = tiny_len;
00482 #if defined(QT_DEBUG)
00483         strm_pos = s.device()->pos();
00484 #endif
00485         switch (c) {            // exec cmd
00486         case QPicturePrivate::PdcNOP:
00487             break;
00488         case QPicturePrivate::PdcDrawPoint:
00489             s >> p;
00490             painter->drawPoint(p);
00491             break;
00492         case QPicturePrivate::PdcDrawPoints:
00493 // ## implement me in the picture paint engine
00494 //                 s >> a >> i1_32 >> i2_32;
00495 //                 painter->drawPoints(a.mid(i1_32, i2_32));
00496             break;
00497         case QPicturePrivate::PdcDrawPath: {
00498             QPainterPath path;
00499             s >> path;
00500             painter->drawPath(path);
00501             break;
00502         }
00503         case QPicturePrivate::PdcDrawLine:
00504             s >> p1 >> p2;
00505             painter->drawLine(p1, p2);
00506             break;
00507         case QPicturePrivate::PdcDrawRect:
00508             s >> r;
00509             painter->drawRect(r);
00510             break;
00511         case QPicturePrivate::PdcDrawRoundRect:
00512             s >> r >> i1_16 >> i2_16;
00513             painter->drawRoundRect(r, i1_16, i2_16);
00514             break;
00515         case QPicturePrivate::PdcDrawEllipse:
00516             s >> r;
00517             painter->drawEllipse(r);
00518             break;
00519         case QPicturePrivate::PdcDrawArc:
00520             s >> r >> i1_16 >> i2_16;
00521             painter->drawArc(r, i1_16, i2_16);
00522             break;
00523         case QPicturePrivate::PdcDrawPie:
00524             s >> r >> i1_16 >> i2_16;
00525             painter->drawPie(r, i1_16, i2_16);
00526             break;
00527         case QPicturePrivate::PdcDrawChord:
00528             s >> r >> i1_16 >> i2_16;
00529             painter->drawChord(r, i1_16, i2_16);
00530             break;
00531         case QPicturePrivate::PdcDrawLineSegments:
00532             s >> pa;
00533             painter->drawLines(pa);
00534             pa.clear();
00535             break;
00536         case QPicturePrivate::PdcDrawPolyline:
00537             s >> a;
00538             painter->drawPolyline(a);
00539             a.clear();
00540             break;
00541         case QPicturePrivate::PdcDrawPolygon:
00542             s >> a >> i_8;
00543             painter->drawPolygon(a, i_8 ? Qt::WindingFill : Qt::OddEvenFill);
00544             a.clear();
00545             break;
00546         case QPicturePrivate::PdcDrawCubicBezier: {
00547             s >> a;
00548             QPainterPath path;
00549             Q_ASSERT(a.size() == 4);
00550             path.moveTo(a.at(0));
00551             path.cubicTo(a.at(1), a.at(2), a.at(3));
00552             painter->strokePath(path, painter->pen());
00553             a.clear();
00554         }
00555             break;
00556         case QPicturePrivate::PdcDrawText:
00557             s >> p >> str1;
00558             painter->drawText(p, str1);
00559             break;
00560         case QPicturePrivate::PdcDrawTextFormatted:
00561             s >> r >> i_16 >> str1;
00562             painter->drawText(r, i_16, str1);
00563             break;
00564         case QPicturePrivate::PdcDrawText2:
00565             s >> p >> str;
00566             painter->drawText(p, str);
00567             break;
00568         case QPicturePrivate::PdcDrawText2Formatted:
00569             s >> r >> i_16 >> str;
00570             painter->drawText(r, i_16, str);
00571             break;
00572         case QPicturePrivate::PdcDrawTextItem: {
00573             Qt::LayoutDirection oldDir = painter->layoutDirection();
00574 
00575             s >> p >> str >> font >> ul;
00576 
00577             if (ul & QTextItem::RightToLeft)
00578                 painter->setLayoutDirection(Qt::RightToLeft);
00579             else
00580                 painter->setLayoutDirection(Qt::LeftToRight);
00581 
00582             qt_format_text(font, QRectF(p, QSizeF(1, 1)), Qt::TextSingleLine | Qt::TextDontClip, str, /*brect=*/0, /*tabstops=*/0, /*...*/0, /*tabarraylen=*/0, painter);
00583 
00584             painter->setLayoutDirection(oldDir);
00585             break;
00586         }
00587         case QPicturePrivate::PdcDrawPixmap: {
00588             QPixmap pixmap;
00589             if (d->formatMajor < 4) {
00590                 s >> p >> pixmap;
00591                 painter->drawPixmap(p, pixmap);
00592             } else {
00593                 QRectF sr;
00594                 s >> r >> pixmap >> sr;
00595                 painter->drawPixmap(r, pixmap, sr);
00596             }
00597         }
00598             break;
00599         case QPicturePrivate::PdcDrawTiledPixmap: {
00600             QPixmap pixmap;
00601             s >> r >> pixmap >> p;
00602             painter->drawTiledPixmap(r, pixmap, p);
00603         }
00604             break;
00605         case QPicturePrivate::PdcDrawImage: {
00606             QImage image;
00607             if (d->formatMajor < 4) {
00608                 s >> p >> image;
00609                 painter->drawPixmap(p, QPixmap::fromImage(image));
00610             } else {
00611                 s >> r >> image;
00612                 painter->drawPixmap(r, QPixmap::fromImage(image), QRectF(0, 0, r.width(), r.height()));
00613             }
00614         }
00615             break;
00616         case QPicturePrivate::PdcBegin:
00617             s >> ul;                        // number of records
00618             if (!exec(painter, s, ul))
00619                 return false;
00620             break;
00621         case QPicturePrivate::PdcEnd:
00622             if (nrecords == 0)
00623                 return true;
00624             break;
00625         case QPicturePrivate::PdcSave:
00626             painter->save();
00627             break;
00628         case QPicturePrivate::PdcRestore:
00629             painter->restore();
00630             break;
00631         case QPicturePrivate::PdcSetBkColor:
00632             s >> color;
00633             painter->setBackground(color);
00634             break;
00635         case QPicturePrivate::PdcSetBkMode:
00636             s >> i_8;
00637             painter->setBackgroundMode((Qt::BGMode)i_8);
00638             break;
00639         case QPicturePrivate::PdcSetROP: // NOP
00640             break;
00641         case QPicturePrivate::PdcSetBrushOrigin:
00642             s >> p;
00643             painter->setBrushOrigin(p);
00644             break;
00645         case QPicturePrivate::PdcSetFont:
00646             s >> font;
00647             painter->setFont(font);
00648             break;
00649         case QPicturePrivate::PdcSetPen:
00650             s >> pen;
00651             painter->setPen(pen);
00652             break;
00653         case QPicturePrivate::PdcSetBrush:
00654             s >> brush;
00655             painter->setBrush(brush);
00656             break;
00657 // #ifdef Q_Q3PAINTER
00658 //         case QPicturePrivate::PdcSetTabStops:
00659 //                 s >> i_16;
00660 //                 painter->setTabStops(i_16);
00661 //                 break;
00662 //             case QPicturePrivate::PdcSetTabArray:
00663 //                 s >> i_16;
00664 //                 if (i_16 == 0) {
00665 //                     painter->setTabArray(0);
00666 //                 } else {
00667 //                     int *ta = new int[i_16];
00668 //                     for (int i=0; i<i_16; i++) {
00669 //                         s >> i1_16;
00670 //                         ta[i] = i1_16;
00671 //                     }
00672 //                     painter->setTabArray(ta);
00673 //                     delete [] ta;
00674 //                 }
00675 //                 break;
00676 // #endif
00677         case QPicturePrivate::PdcSetVXform:
00678             s >> i_8;
00679             painter->setViewTransformEnabled(i_8);
00680             break;
00681         case QPicturePrivate::PdcSetWindow:
00682             s >> r;
00683             painter->setWindow(r.toRect());
00684             break;
00685         case QPicturePrivate::PdcSetViewport:
00686             s >> r;
00687             painter->setViewport(r.toRect());
00688             break;
00689         case QPicturePrivate::PdcSetWXform:
00690             s >> i_8;
00691             painter->setMatrixEnabled(i_8);
00692             break;
00693         case QPicturePrivate::PdcSetWMatrix:
00694             s >> matrix >> i_8;
00695             // i_8 is always false due to updateXForm() in qpaintengine_pic.cpp
00696             painter->setMatrix(matrix * worldMatrix, false);
00697             break;
00698 // #ifdef Q_Q3PAINTER
00699 //             case QPicturePrivate::PdcSaveWMatrix:
00700 //                 painter->saveWorldMatrix();
00701 //                 break;
00702 //             case QPicturePrivate::PdcRestoreWMatrix:
00703 //                 painter->restoreWorldMatrix();
00704 //                 break;
00705 // #endif
00706         case QPicturePrivate::PdcSetClip:
00707             s >> i_8;
00708             painter->setClipping(i_8);
00709             break;
00710         case QPicturePrivate::PdcSetClipRegion:
00711             s >> rgn >> i_8;
00712             painter->setClipRegion(rgn);
00713             break;
00714         case QPicturePrivate::PdcSetClipPath:
00715             {
00716                 QPainterPath path;
00717                 s >> path >> i_8;
00718                 painter->setClipPath(path, Qt::ClipOperation(i_8));
00719                 break;
00720             }
00721         case QPicturePrivate::PdcSetRenderHint:
00722             s >> ul;
00723             painter->setRenderHint(QPainter::Antialiasing,
00724                                    bool(ul & QPainter::Antialiasing));
00725             painter->setRenderHint(QPainter::SmoothPixmapTransform,
00726                                    bool(ul & QPainter::SmoothPixmapTransform));
00727             break;
00728         default:
00729             qWarning("QPicture::play: Invalid command %d", c);
00730             if (len)                        // skip unknown command
00731                 s.device()->seek(s.device()->pos()+len);
00732         }
00733 #if defined(QT_DEBUG)
00734         //qDebug("device->at(): %i, strm_pos: %i len: %i", s.device()->at(), strm_pos, len);
00735         Q_ASSERT(qint32(s.device()->pos() - strm_pos) == len);
00736 #endif
00737     }
00738     return false;
00739 }
00740 
00751 int QPicture::metric(PaintDeviceMetric m) const
00752 {
00753     int val;
00754     QRect brect = boundingRect();
00755     switch (m) {
00756         case PdmWidth:
00757             val = brect.width();
00758             break;
00759         case PdmHeight:
00760             val = brect.height();
00761             break;
00762         case PdmWidthMM:
00763             val = int(25.4/qt_defaultDpi()*brect.width());
00764             break;
00765         case PdmHeightMM:
00766             val = int(25.4/qt_defaultDpi()*brect.height());
00767             break;
00768         case PdmDpiX:
00769         case PdmPhysicalDpiX:
00770             val = qt_defaultDpi();
00771             break;
00772         case PdmDpiY:
00773         case PdmPhysicalDpiY:
00774             val = qt_defaultDpi();
00775             break;
00776         case PdmNumColors:
00777             val = 16777216;
00778             break;
00779         case PdmDepth:
00780             val = 24;
00781             break;
00782         default:
00783             val = 0;
00784             qWarning("QPicture::metric: Invalid metric command");
00785     }
00786     return val;
00787 }
00788 
00803 void QPicture::detach_helper()
00804 {
00805     Q_D(QPicture);
00806     QPicturePrivate *x = new QPicturePrivate;
00807     int pictsize = size();
00808     x->pictb.setData(data(), pictsize);
00809     if (d->pictb.isOpen()) {
00810         x->pictb.open(d->pictb.openMode());
00811         x->pictb.seek(d->pictb.pos());
00812     }
00813     x->trecs = d->trecs;
00814     x->formatOk = d->formatOk;
00815     x->formatMinor = d->formatMinor;
00816     x->brect = d->brect;
00817     x->override_rect = d->override_rect;
00818     x = qAtomicSetPtr(&d_ptr, x);
00819     if (!x->ref.deref())
00820         delete x;
00821 }
00822 
00827 QPicture& QPicture::operator=(const QPicture &p)
00828 {
00829     qAtomicAssign<QPicturePrivate>(d_ptr, p.d_ptr);
00830     return *this;
00831 }
00832 
00839 void QPicturePrivate::resetFormat()
00840 {
00841     formatOk = false;
00842     formatMajor = mfhdr_maj;
00843     formatMinor = mfhdr_min;
00844 }
00845 
00846 
00854 bool QPicturePrivate::checkFormat()
00855 {
00856     resetFormat();
00857 
00858     // can't check anything in an empty buffer
00859     if (pictb.size() == 0 || pictb.isOpen())
00860         return false;
00861 
00862     pictb.open(QIODevice::ReadOnly);                        // open buffer device
00863     QDataStream s;
00864     s.setDevice(&pictb);                        // attach data stream to buffer
00865 
00866     char mf_id[4];                                // picture header tag
00867     s.readRawData(mf_id, 4);                        // read actual tag
00868     if (memcmp(mf_id, qt_mfhdr_tag, 4) != 0) {         // wrong header id
00869         qWarning("QPicturePaintEngine::checkFormat: Incorrect header");
00870         pictb.close();
00871         return false;
00872     }
00873 
00874     int cs_start = sizeof(quint32);                // pos of checksum word
00875     int data_start = cs_start + sizeof(quint16);
00876     quint16 cs,ccs;
00877     QByteArray buf = pictb.buffer();        // pointer to data
00878 
00879     s >> cs;                                // read checksum
00880     ccs = (quint16) qChecksum(buf.constData() + data_start, buf.size() - data_start);
00881     if (ccs != cs) {
00882         qWarning("QPicturePaintEngine::checkFormat: Invalid checksum %x, %x expected",
00883                   ccs, cs);
00884         pictb.close();
00885         return false;
00886     }
00887 
00888     quint16 major, minor;
00889     s >> major >> minor;                        // read version number
00890     if (major > mfhdr_maj) {                // new, incompatible version
00891         qWarning("QPicturePaintEngine::checkFormat: Incompatible version %d.%d",
00892                   major, minor);
00893         pictb.close();
00894         return false;
00895     }
00896     s.setVersion(major != 4 ? major : 3);
00897 
00898     quint8  c, clen;
00899     s >> c >> clen;
00900     if (c == QPicturePrivate::PdcBegin) {
00901         if (!(major >= 1 && major <= 3)) {
00902             qint32 l, t, w, h;
00903             s >> l >> t >> w >> h;
00904             brect = QRect(l, t, w, h);
00905         }
00906     } else {
00907         qWarning("QPicturePaintEngine::checkFormat: Format error");
00908         pictb.close();
00909         return false;
00910     }
00911     pictb.close();
00912 
00913     formatOk = true;                        // picture seems to be ok
00914     formatMajor = major;
00915     formatMinor = minor;
00916     return true;
00917 }
00918 
00920 QPaintEngine *QPicture::paintEngine() const
00921 {
00922     if (!d_func()->paintEngine)
00923         const_cast<QPicture*>(this)->d_func()->paintEngine = new QPicturePaintEngine;
00924     return d_func()->paintEngine;
00925 }
00926 
00927 /*****************************************************************************
00928   QPicture stream functions
00929  *****************************************************************************/
00930 
00938 QDataStream &operator<<(QDataStream &s, const QPicture &r)
00939 {
00940     quint32 size = r.d_func()->pictb.buffer().size();
00941     s << size;
00942     // null picture ?
00943     if (size == 0)
00944         return s;
00945     // just write the whole buffer to the stream
00946     s.writeRawData (r.d_func()->pictb.buffer(), r.d_func()->pictb.buffer().size());
00947     return s;
00948 }
00949 
00957 QDataStream &operator>>(QDataStream &s, QPicture &r)
00958 {
00959     QDataStream sr;
00960 
00961     // "init"; this code is similar to the beginning of QPicture::cmd()
00962     sr.setDevice(&r.d_func()->pictb);
00963     sr.setVersion(r.d_func()->formatMajor);
00964     quint32 len;
00965     s >> len;
00966     QByteArray data;
00967     if (len > 0) {
00968         data.resize(len);
00969         s.readRawData(data.data(), len);
00970     }
00971 
00972     r.d_func()->pictb.setData(data);
00973     r.d_func()->resetFormat();
00974     return s;
00975 }
00976 
00977 
00978 #ifndef QT_NO_PICTUREIO
00979 #include "qregexp.h"
00980 #include "qapplication.h"
00981 #include "qpictureformatplugin.h"
00982 
00993 const char* QPicture::pictureFormat(const QString &fileName)
00994 {
00995     return QPictureIO::pictureFormat(fileName);
00996 }
00997 
01006 QList<QByteArray> QPicture::inputFormats()
01007 {
01008     return QPictureIO::inputFormats();
01009 }
01010 
01011 static QStringList qToStringList(const QList<QByteArray> arr)
01012 {
01013     QStringList list;
01014     for (int i = 0; i < arr.count(); ++i)
01015         list.append(QString::fromLatin1(arr.at(i)));
01016     return list;
01017 }
01018 
01034 QStringList QPicture::inputFormatList()
01035 {
01036     return qToStringList(QPictureIO::inputFormats());
01037 }
01038 
01039 
01055 QStringList QPicture::outputFormatList()
01056 {
01057     return qToStringList(QPictureIO::outputFormats());
01058 }
01059 
01068 QList<QByteArray> QPicture::outputFormats()
01069 {
01070     return QPictureIO::outputFormats();
01071 }
01072 
01073 /*****************************************************************************
01074   QPictureIO member functions
01075  *****************************************************************************/
01076 
01098 struct QPictureIOData
01099 {
01100     QPicture        pi;                                // picture
01101     int                iostat;                                // IO status
01102     QByteArray        frmt;                                // picture format
01103     QIODevice  *iodev;                                // IO device
01104     QString        fname;                                // file name
01105     QString     descr;                                // picture description
01106     const char *parameters;
01107     int quality;
01108     float gamma;
01109 };
01110 
01115 QPictureIO::QPictureIO()
01116 {
01117     init();
01118 }
01119 
01125 QPictureIO::QPictureIO(QIODevice *ioDevice, const char *format)
01126 {
01127     init();
01128     d->iodev = ioDevice;
01129     d->frmt = format;
01130 }
01131 
01137 QPictureIO::QPictureIO(const QString &fileName, const char* format)
01138 {
01139     init();
01140     d->frmt = format;
01141     d->fname = fileName;
01142 }
01143 
01148 void QPictureIO::init()
01149 {
01150     d = new QPictureIOData();
01151     d->parameters = 0;
01152     d->quality = -1; // default quality of the current format
01153     d->gamma=0.0f;
01154     d->iostat = 0;
01155     d->iodev  = 0;
01156 }
01157 
01162 QPictureIO::~QPictureIO()
01163 {
01164     if (d->parameters)
01165         delete [] (char*)d->parameters;
01166     delete d;
01167 }
01168 
01169 
01170 /*****************************************************************************
01171   QPictureIO picture handler functions
01172  *****************************************************************************/
01173 
01174 class QPictureHandler
01175 {
01176 public:
01177     QPictureHandler(const char *f, const char *h, const QByteArray& fl,
01178                      picture_io_handler r, picture_io_handler w);
01179     QByteArray              format;                        // picture format
01180     QRegExp              header;                        // picture header pattern
01181     enum TMode { Untranslated=0, TranslateIn, TranslateInOut } text_mode;
01182     picture_io_handler  read_picture;                // picture read function
01183     picture_io_handler  write_picture;                // picture write function
01184     bool              obsolete;                        // support not "published"
01185 };
01186 
01187 QPictureHandler::QPictureHandler(const char *f, const char *h, const QByteArray& fl,
01188                               picture_io_handler r, picture_io_handler w)
01189     : format(f), header(QString::fromLatin1(h))
01190 {
01191     text_mode = Untranslated;
01192     if (fl.contains('t'))
01193         text_mode = TranslateIn;
01194     else if (fl.contains('T'))
01195         text_mode = TranslateInOut;
01196     obsolete = fl.contains('O');
01197     read_picture  = r;
01198     write_picture = w;
01199 }
01200 
01201 typedef QList<QPictureHandler *> QPHList;
01202 static QPHList pictureHandlers;
01203 
01204 #ifndef QT_NO_LIBRARY
01205 Q_GLOBAL_STATIC(QMutex, mutex)
01206 Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader,
01207                           (QPictureFormatInterface_iid,
01208                            QCoreApplication::libraryPaths(),
01209                            QLatin1String("/pictureformats")))
01210 #endif
01211 void qt_init_picture_plugins()
01212 {
01213 #ifndef QT_NO_LIBRARY
01214     QMutexLocker locker(mutex());
01215     QFactoryLoader *loader = ::loader();
01216     QStringList keys = loader->keys();
01217     for (int i = 0; i < keys.count(); ++i)
01218         if (QPictureFormatInterface *format = qobject_cast<QPictureFormatInterface*>(loader->instance(keys.at(i))))
01219             format->installIOHandler(keys.at(i));
01220 #endif
01221 }
01222 
01223 static void cleanup()
01224 {
01225     // make sure that picture handlers are delete before plugin manager
01226     while (!pictureHandlers.isEmpty())
01227         delete pictureHandlers.takeFirst();
01228 }
01229 
01230 void qt_init_picture_handlers()                // initialize picture handlers
01231 {
01232     static bool done = false;
01233     if (done) return;
01234     done = true;
01235 
01236     qAddPostRoutine(cleanup);
01237 }
01238 
01239 static QPictureHandler *get_picture_handler(const char *format)
01240 {                                                // get pointer to handler
01241     qt_init_picture_handlers();
01242     qt_init_picture_plugins();
01243     for (int i = 0; i < pictureHandlers.size(); ++i) {
01244         if (pictureHandlers.at(i)->format == format)
01245             return pictureHandlers.at(i);
01246     }
01247     return 0;                                        // no such handler
01248 }
01249 
01250 
01295 void QPictureIO::defineIOHandler(const char *format,
01296                                 const char *header,
01297                                 const char *flags,
01298                                 picture_io_handler readPicture,
01299                                 picture_io_handler writePicture)
01300 {
01301     qt_init_picture_handlers();
01302     QPictureHandler *p;
01303     p = new QPictureHandler(format, header, QByteArray(flags), readPicture, writePicture);
01304     pictureHandlers.prepend(p);
01305 }
01306 
01307 
01308 /*****************************************************************************
01309   QPictureIO normal member functions
01310  *****************************************************************************/
01311 
01317 const QPicture &QPictureIO::picture() const { return d->pi; }
01318 
01325 int QPictureIO::status() const { return d->iostat; }
01326 
01331 const char *QPictureIO::format() const { return d->frmt; }
01332 
01338 QIODevice *QPictureIO::ioDevice() const { return d->iodev; }
01339 
01345 QString QPictureIO::fileName() const { return d->fname; }
01346 
01347 
01353 QString QPictureIO::description() const { return d->descr; }
01354 
01360 void QPictureIO::setPicture(const QPicture &picture)
01361 {
01362     d->pi = picture;
01363 }
01364 
01371 void QPictureIO::setStatus(int status)
01372 {
01373     d->iostat = status;
01374 }
01375 
01389 void QPictureIO::setFormat(const char *format)
01390 {
01391     d->frmt = format;
01392 }
01393 
01405 void QPictureIO::setIODevice(QIODevice *ioDevice)
01406 {
01407     d->iodev = ioDevice;
01408 }
01409 
01416 void QPictureIO::setFileName(const QString &fileName)
01417 {
01418     d->fname = fileName;
01419 }
01420 
01427 int QPictureIO::quality() const
01428 {
01429     return d->quality;
01430 }
01431 
01443 void QPictureIO::setQuality(int q)
01444 {
01445     d->quality = q;
01446 }
01447 
01454 const char *QPictureIO::parameters() const
01455 {
01456     return d->parameters;
01457 }
01458 
01470 void QPictureIO::setParameters(const char *parameters)
01471 {
01472     if (d->parameters)
01473         delete [] (char*)d->parameters;
01474     d->parameters = qstrdup(parameters);
01475 }
01476 
01488 void QPictureIO::setGamma(float gamma)
01489 {
01490     d->gamma=gamma;
01491 }
01492 
01498 float QPictureIO::gamma() const
01499 {
01500     return d->gamma;
01501 }
01502 
01511 void QPictureIO::setDescription(const QString &description)
01512 {
01513     d->descr = description;
01514 }
01515 
01516 
01523 QByteArray QPictureIO::pictureFormat(const QString &fileName)
01524 {
01525     QFile file(fileName);
01526     QByteArray format;
01527     if (!file.open(QIODevice::ReadOnly))
01528         return format;
01529     format = pictureFormat(&file);
01530     file.close();
01531     return format;
01532 }
01533 
01547 QByteArray QPictureIO::pictureFormat(QIODevice *d)
01548 {
01549     // if you change this change the documentation for defineIOHandler()
01550     const int buflen = 14;
01551 
01552     char buf[buflen];
01553     char buf2[buflen];
01554     qt_init_picture_handlers();
01555     qt_init_picture_plugins();
01556     int pos = d->pos();                      // save position
01557     int rdlen = d->read(buf, buflen);        // read a few bytes
01558 
01559     QByteArray format;
01560     if (rdlen != buflen)
01561         return format;
01562 
01563     memcpy(buf2, buf, buflen);
01564 
01565     for (int n = 0; n < rdlen; n++)
01566         if (buf[n] == '\0')
01567             buf[n] = '\001';
01568     if (rdlen > 0) {
01569         buf[rdlen - 1] = '\0';
01570         QString bufStr = QString::fromLatin1(buf);
01571         for (int i = 0; i < pictureHandlers.size(); ++i) {
01572             if (pictureHandlers.at(i)->header.indexIn(bufStr) != -1) { // try match with headers
01573                 format = pictureHandlers.at(i)->format;
01574                 break;
01575             }
01576         }
01577     }
01578     d->seek(pos);                                // restore position
01579     return format;
01580 }
01581 
01586 QList<QByteArray> QPictureIO::inputFormats()
01587 {
01588     QList<QByteArray> result;
01589 
01590     qt_init_picture_handlers();
01591     qt_init_picture_plugins();
01592 
01593     for (int i = 0; i < pictureHandlers.size(); ++i) {
01594         QPictureHandler *p = pictureHandlers.at(i);
01595         if (p->read_picture && !p->obsolete  && !result.contains(p->format))
01596             result.append(p->format);
01597     }
01598     qSort(result);
01599 
01600     return result;
01601 }
01602 
01607 QList<QByteArray> QPictureIO::outputFormats()
01608 {
01609     qt_init_picture_handlers();
01610     qt_init_picture_plugins();
01611 
01612     QList<QByteArray> result;
01613     for (int i = 0; i < pictureHandlers.size(); ++i) {
01614         QPictureHandler *p = pictureHandlers.at(i);
01615         if (p->write_picture && !p->obsolete && !result.contains(p->format))
01616             result.append(p->format);
01617     }
01618     return result;
01619 }
01620 
01621 
01622 
01646 bool QPictureIO::read()
01647 {
01648     QFile           file;
01649     const char          *picture_format;
01650     QPictureHandler *h;
01651 
01652     if (d->iodev) {                                // read from io device
01653         // ok, already open
01654     } else if (!d->fname.isEmpty()) {                // read from file
01655         file.setFileName(d->fname);
01656         if (!file.open(QIODevice::ReadOnly))
01657             return false;                        // cannot open file
01658         d->iodev = &file;
01659     } else {                                        // no file name or io device
01660         return false;
01661     }
01662     if (d->frmt.isEmpty()) {
01663         // Try to guess format
01664         picture_format = pictureFormat(d->iodev);        // get picture format
01665         if (!picture_format) {
01666             if (file.isOpen()) {                        // unknown format
01667                 file.close();
01668                 d->iodev = 0;
01669             }
01670             return false;
01671         }
01672     } else {
01673         picture_format = d->frmt;
01674     }
01675 
01676     h = get_picture_handler(picture_format);
01677     if (file.isOpen()) {
01678 #if !defined(Q_OS_UNIX)
01679         if (h && h->text_mode) {                // reopen in translated mode
01680             file.close();
01681             file.open(QIODevice::ReadOnly | QIODevice::Text);
01682         }
01683         else
01684 #endif
01685             file.seek(0);                        // position to start
01686     }
01687     d->iostat = 1;                                        // assume error
01688 
01689     if (h && h->read_picture)
01690         (*h->read_picture)(this);
01691 
01692     if (file.isOpen()) {                        // picture was read using file
01693         file.close();
01694         d->iodev = 0;
01695     }
01696     return d->iostat == 0;                                // picture successfully read?
01697 }
01698 
01699 
01718 bool QPictureIO::write()
01719 {
01720     if (d->frmt.isEmpty())
01721         return false;
01722     QPictureHandler *h = get_picture_handler(d->frmt);
01723     if (!h || !h->write_picture) {
01724         qWarning("QPictureIO::write: No such picture format handler: %s",
01725                  format());
01726         return false;
01727     }
01728     QFile file;
01729     if (!d->iodev && !d->fname.isEmpty()) {
01730         file.setFileName(d->fname);
01731         bool translate = h->text_mode==QPictureHandler::TranslateInOut;
01732         QIODevice::OpenMode fmode = translate ? QIODevice::WriteOnly | QIODevice::Text : QIODevice::OpenMode(QIODevice::WriteOnly);
01733         if (!file.open(fmode))                // couldn't create file
01734             return false;
01735         d->iodev = &file;
01736     }
01737     d->iostat = 1;
01738     (*h->write_picture)(this);
01739     if (file.isOpen()) {                        // picture was written using file
01740         file.close();
01741         d->iodev = 0;
01742     }
01743     return d->iostat == 0;                                // picture successfully written?
01744 }
01745 #endif //QT_NO_PICTUREIO
01746 
01753 #endif // QT_NO_PICTURE

Generated on Thu Mar 15 11:54:39 2007 for Qt 4.2 User's Guide by  doxygen 1.5.1