00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
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";
00095 static const quint16 mfhdr_maj = 8;
00096 static const quint16 mfhdr_min = 0;
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
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();
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);
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
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)
00408 return true;
00409
00410 if (!d->formatOk && !d->checkFormat())
00411 return false;
00412
00413 d->pictb.open(QIODevice::ReadOnly);
00414 QDataStream s;
00415 s.setDevice(&d->pictb);
00416 s.device()->seek(10);
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
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;
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;
00452 quint8 tiny_len;
00453 qint32 len;
00454 qint16 i_16, i1_16, i2_16;
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;
00477 s >> tiny_len;
00478 if (tiny_len == 255)
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) {
00486 case QPicturePrivate::PdcNOP:
00487 break;
00488 case QPicturePrivate::PdcDrawPoint:
00489 s >> p;
00490 painter->drawPoint(p);
00491 break;
00492 case QPicturePrivate::PdcDrawPoints:
00493
00494
00495
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, 0, 0, 0, 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;
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:
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
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
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
00696 painter->setMatrix(matrix * worldMatrix, false);
00697 break;
00698
00699
00700
00701
00702
00703
00704
00705
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)
00731 s.device()->seek(s.device()->pos()+len);
00732 }
00733 #if defined(QT_DEBUG)
00734
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
00859 if (pictb.size() == 0 || pictb.isOpen())
00860 return false;
00861
00862 pictb.open(QIODevice::ReadOnly);
00863 QDataStream s;
00864 s.setDevice(&pictb);
00865
00866 char mf_id[4];
00867 s.readRawData(mf_id, 4);
00868 if (memcmp(mf_id, qt_mfhdr_tag, 4) != 0) {
00869 qWarning("QPicturePaintEngine::checkFormat: Incorrect header");
00870 pictb.close();
00871 return false;
00872 }
00873
00874 int cs_start = sizeof(quint32);
00875 int data_start = cs_start + sizeof(quint16);
00876 quint16 cs,ccs;
00877 QByteArray buf = pictb.buffer();
00878
00879 s >> cs;
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;
00890 if (major > mfhdr_maj) {
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;
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
00929
00930
00938 QDataStream &operator<<(QDataStream &s, const QPicture &r)
00939 {
00940 quint32 size = r.d_func()->pictb.buffer().size();
00941 s << size;
00942
00943 if (size == 0)
00944 return s;
00945
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
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
01075
01076
01098 struct QPictureIOData
01099 {
01100 QPicture pi;
01101 int iostat;
01102 QByteArray frmt;
01103 QIODevice *iodev;
01104 QString fname;
01105 QString descr;
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;
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
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;
01180 QRegExp header;
01181 enum TMode { Untranslated=0, TranslateIn, TranslateInOut } text_mode;
01182 picture_io_handler read_picture;
01183 picture_io_handler write_picture;
01184 bool obsolete;
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
01226 while (!pictureHandlers.isEmpty())
01227 delete pictureHandlers.takeFirst();
01228 }
01229
01230 void qt_init_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 {
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;
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
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
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();
01557 int rdlen = d->read(buf, buflen);
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) {
01573 format = pictureHandlers.at(i)->format;
01574 break;
01575 }
01576 }
01577 }
01578 d->seek(pos);
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) {
01653
01654 } else if (!d->fname.isEmpty()) {
01655 file.setFileName(d->fname);
01656 if (!file.open(QIODevice::ReadOnly))
01657 return false;
01658 d->iodev = &file;
01659 } else {
01660 return false;
01661 }
01662 if (d->frmt.isEmpty()) {
01663
01664 picture_format = pictureFormat(d->iodev);
01665 if (!picture_format) {
01666 if (file.isOpen()) {
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) {
01680 file.close();
01681 file.open(QIODevice::ReadOnly | QIODevice::Text);
01682 }
01683 else
01684 #endif
01685 file.seek(0);
01686 }
01687 d->iostat = 1;
01688
01689 if (h && h->read_picture)
01690 (*h->read_picture)(this);
01691
01692 if (file.isOpen()) {
01693 file.close();
01694 d->iodev = 0;
01695 }
01696 return d->iostat == 0;
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))
01734 return false;
01735 d->iodev = &file;
01736 }
01737 d->iostat = 1;
01738 (*h->write_picture)(this);
01739 if (file.isOpen()) {
01740 file.close();
01741 d->iodev = 0;
01742 }
01743 return d->iostat == 0;
01744 }
01745 #endif //QT_NO_PICTUREIO
01746
01753 #endif // QT_NO_PICTURE