/****************************************************************************+ −
**+ −
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).+ −
** All rights reserved.+ −
** Contact: Nokia Corporation (qt-info@nokia.com)+ −
**+ −
** This file is part of the QtGui module of the Qt Toolkit.+ −
**+ −
** $QT_BEGIN_LICENSE:LGPL$+ −
** No Commercial Usage+ −
** This file contains pre-release code and may not be distributed.+ −
** You may use this file in accordance with the terms and conditions+ −
** contained in the Technology Preview License Agreement accompanying+ −
** this package.+ −
**+ −
** GNU Lesser General Public License Usage+ −
** Alternatively, this file may be used under the terms of the GNU Lesser+ −
** General Public License version 2.1 as published by the Free Software+ −
** Foundation and appearing in the file LICENSE.LGPL included in the+ −
** packaging of this file. Please review the following information to+ −
** ensure the GNU Lesser General Public License version 2.1 requirements+ −
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.+ −
**+ −
** In addition, as a special exception, Nokia gives you certain additional+ −
** rights. These rights are described in the Nokia Qt LGPL Exception+ −
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.+ −
**+ −
** If you have questions regarding the use of this file, please contact+ −
** Nokia at qt-info@nokia.com.+ −
**+ −
**+ −
**+ −
**+ −
**+ −
**+ −
**+ −
**+ −
** $QT_END_LICENSE$+ −
**+ −
****************************************************************************/+ −
+ −
#include "qpicture.h"+ −
#include <private/qpicture_p.h>+ −
+ −
#ifndef QT_NO_PICTURE+ −
+ −
#include <private/qfactoryloader_p.h>+ −
#include <private/qpaintengine_pic_p.h>+ −
+ −
#include "qdatastream.h"+ −
#include "qfile.h"+ −
#include "qimage.h"+ −
#include "qmutex.h"+ −
#include "qpainter.h"+ −
#include "qpainterpath.h"+ −
#include "qpixmap.h"+ −
#include "qregion.h"+ −
#include "qdebug.h"+ −
+ −
QT_BEGIN_NAMESPACE+ −
+ −
void qt_format_text(const QFont &fnt, const QRectF &_r,+ −
int tf, const QTextOption *opt, const QString& str, QRectF *brect,+ −
int tabstops, int *, int tabarraylen,+ −
QPainter *painter);+ −
+ −
/*!+ −
\class QPicture+ −
\brief The QPicture class is a paint device that records and+ −
replays QPainter commands.+ −
+ −
\ingroup painting+ −
\ingroup shared+ −
+ −
+ −
A picture serializes painter commands to an IO device in a+ −
platform-independent format. They are sometimes referred to as meta-files.+ −
+ −
Qt pictures use a proprietary binary format. Unlike native picture+ −
(meta-file) formats on many window systems, Qt pictures have no+ −
limitations regarding their contents. Everything that can be+ −
painted on a widget or pixmap (e.g., fonts, pixmaps, regions,+ −
transformed graphics, etc.) can also be stored in a picture.+ −
+ −
QPicture is resolution independent, i.e. a QPicture can be+ −
displayed on different devices (for example svg, pdf, ps, printer+ −
and screen) looking the same. This is, for instance, needed for+ −
WYSIWYG print preview. QPicture runs in the default system dpi,+ −
and scales the painter to match differences in resolution+ −
depending on the window system.+ −
+ −
Example of how to record a picture:+ −
\snippet doc/src/snippets/picture/picture.cpp 0+ −
+ −
Note that the list of painter commands is reset on each call to+ −
the QPainter::begin() function.+ −
+ −
Example of how to replay a picture:+ −
\snippet doc/src/snippets/picture/picture.cpp 1+ −
+ −
Pictures can also be drawn using play(). Some basic data about a+ −
picture is available, for example, size(), isNull() and+ −
boundingRect().+ −
+ −
\sa QMovie+ −
*/+ −
+ −
const char *qt_mfhdr_tag = "QPIC"; // header tag+ −
static const quint16 mfhdr_maj = 11; // major version #+ −
static const quint16 mfhdr_min = 0; // minor version #+ −
Q_GUI_EXPORT extern int qt_defaultDpiX();+ −
Q_GUI_EXPORT extern int qt_defaultDpiY();+ −
+ −
/*!+ −
Constructs an empty picture.+ −
+ −
The \a formatVersion parameter may be used to \e create a QPicture+ −
that can be read by applications that are compiled with earlier+ −
versions of Qt.+ −
+ −
Note that the default formatVersion is -1 which signifies the+ −
current release, i.e. for Qt 4.0 a formatVersion of 7 is the same+ −
as the default formatVersion of -1.+ −
+ −
Reading pictures generated by earlier versions of Qt is not+ −
supported in Qt 4.0.+ −
*/+ −
+ −
QPicture::QPicture(int formatVersion)+ −
: QPaintDevice(),+ −
d_ptr(new QPicturePrivate)+ −
{+ −
Q_D(QPicture);+ −
+ −
if (formatVersion == 0)+ −
qWarning("QPicture: invalid format version 0");+ −
+ −
// still accept the 0 default from before Qt 3.0.+ −
if (formatVersion > 0 && formatVersion != (int)mfhdr_maj) {+ −
d->formatMajor = formatVersion;+ −
d->formatMinor = 0;+ −
d->formatOk = false;+ −
} else {+ −
d->resetFormat();+ −
}+ −
}+ −
+ −
/*!+ −
Constructs a copy of \a pic.+ −
+ −
This constructor is fast thanks to \l{implicit sharing}.+ −
*/+ −
+ −
QPicture::QPicture(const QPicture &pic)+ −
: QPaintDevice(), d_ptr(pic.d_ptr)+ −
{+ −
}+ −
+ −
/*! \internal */+ −
QPicture::QPicture(QPicturePrivate &dptr)+ −
: QPaintDevice(),+ −
d_ptr(&dptr)+ −
{+ −
}+ −
+ −
/*!+ −
Destroys the picture.+ −
*/+ −
QPicture::~QPicture()+ −
{+ −
}+ −
+ −
/*!+ −
\internal+ −
*/+ −
int QPicture::devType() const+ −
{+ −
return QInternal::Picture;+ −
}+ −
+ −
/*!+ −
\fn bool QPicture::isNull() const+ −
+ −
Returns true if the picture contains no data; otherwise returns+ −
false.+ −
*/+ −
+ −
/*!+ −
\fn uint QPicture::size() const+ −
+ −
Returns the size of the picture data.+ −
+ −
\sa data()+ −
*/+ −
+ −
/*!+ −
\fn const char* QPicture::data() const+ −
+ −
Returns a pointer to the picture data. The pointer is only valid+ −
until the next non-const function is called on this picture. The+ −
returned pointer is 0 if the picture contains no data.+ −
+ −
\sa size(), isNull()+ −
*/+ −
+ −
+ −
bool QPicture::isNull() const+ −
{+ −
return d_func()->pictb.buffer().isNull();+ −
}+ −
+ −
uint QPicture::size() const+ −
{+ −
return d_func()->pictb.buffer().size();+ −
}+ −
+ −
const char* QPicture::data() const+ −
{+ −
return d_func()->pictb.buffer();+ −
}+ −
+ −
void QPicture::detach()+ −
{+ −
d_ptr.detach();+ −
}+ −
+ −
bool QPicture::isDetached() const+ −
{+ −
return d_func()->ref == 1;+ −
}+ −
+ −
/*!+ −
Sets the picture data directly from \a data and \a size. This+ −
function copies the input data.+ −
+ −
\sa data(), size()+ −
*/+ −
+ −
void QPicture::setData(const char* data, uint size)+ −
{+ −
detach();+ −
d_func()->pictb.setData(data, size);+ −
d_func()->resetFormat(); // we'll have to check+ −
}+ −
+ −
+ −
/*!+ −
Loads a picture from the file specified by \a fileName and returns+ −
true if successful; otherwise returns false.+ −
+ −
Please note that the \a format parameter has been deprecated and+ −
will have no effect.+ −
+ −
\sa save()+ −
*/+ −
+ −
bool QPicture::load(const QString &fileName, const char *format)+ −
{+ −
QFile f(fileName);+ −
if (!f.open(QIODevice::ReadOnly))+ −
return false;+ −
return load(&f, format);+ −
}+ −
+ −
/*!+ −
\overload+ −
+ −
\a dev is the device to use for loading.+ −
*/+ −
+ −
bool QPicture::load(QIODevice *dev, const char *format)+ −
{+ −
if(format) {+ −
#ifndef QT_NO_PICTUREIO+ −
QPictureIO io(dev, format);+ −
bool result = io.read();+ −
if (result) {+ −
operator=(io.picture());+ −
+ −
} else if (format)+ −
#else+ −
bool result = false;+ −
#endif+ −
{+ −
qWarning("QPicture::load: No such picture format: %s", format);+ −
}+ −
return result;+ −
}+ −
+ −
detach();+ −
QByteArray a = dev->readAll();+ −
+ −
d_func()->pictb.setData(a); // set byte array in buffer+ −
return d_func()->checkFormat();+ −
}+ −
+ −
/*!+ −
Saves a picture to the file specified by \a fileName and returns+ −
true if successful; otherwise returns false.+ −
+ −
Please note that the \a format parameter has been deprecated and+ −
will have no effect.+ −
+ −
\sa load()+ −
*/+ −
+ −
bool QPicture::save(const QString &fileName, const char *format)+ −
{+ −
if (paintingActive()) {+ −
qWarning("QPicture::save: still being painted on. "+ −
"Call QPainter::end() first");+ −
return false;+ −
}+ −
+ −
+ −
if(format) {+ −
#ifndef QT_NO_PICTUREIO+ −
QPictureIO io(fileName, format);+ −
bool result = io.write();+ −
if (result) {+ −
operator=(io.picture());+ −
} else if (format)+ −
#else+ −
bool result = false;+ −
#endif+ −
{+ −
qWarning("QPicture::save: No such picture format: %s", format);+ −
}+ −
return result;+ −
}+ −
+ −
QFile f(fileName);+ −
if (!f.open(QIODevice::WriteOnly))+ −
return false;+ −
return save(&f, format);+ −
}+ −
+ −
/*!+ −
\overload+ −
+ −
\a dev is the device to use for saving.+ −
*/+ −
+ −
bool QPicture::save(QIODevice *dev, const char *format)+ −
{+ −
if (paintingActive()) {+ −
qWarning("QPicture::save: still being painted on. "+ −
"Call QPainter::end() first");+ −
return false;+ −
}+ −
+ −
if(format) {+ −
#ifndef QT_NO_PICTUREIO+ −
QPictureIO io(dev, format);+ −
bool result = io.write();+ −
if (result) {+ −
operator=(io.picture());+ −
} else if (format)+ −
#else+ −
bool result = false;+ −
#endif+ −
{+ −
qWarning("QPicture::save: No such picture format: %s", format);+ −
}+ −
return result;+ −
}+ −
+ −
dev->write(d_func()->pictb.buffer(), d_func()->pictb.buffer().size());+ −
return true;+ −
}+ −
+ −
/*!+ −
Returns the picture's bounding rectangle or an invalid rectangle+ −
if the picture contains no data.+ −
*/+ −
+ −
QRect QPicture::boundingRect() const+ −
{+ −
Q_D(const QPicture);+ −
// Use override rect where possible.+ −
if (!d->override_rect.isEmpty())+ −
return d->override_rect;+ −
+ −
if (!d->formatOk)+ −
d_ptr->checkFormat();+ −
+ −
return d->brect;+ −
}+ −
+ −
/*!+ −
Sets the picture's bounding rectangle to \a r. The automatically+ −
calculated value is overridden.+ −
*/+ −
+ −
void QPicture::setBoundingRect(const QRect &r)+ −
{+ −
d_func()->override_rect = r;+ −
}+ −
+ −
/*!+ −
Replays the picture using \a painter, and returns true if+ −
successful; otherwise returns false.+ −
+ −
This function does exactly the same as QPainter::drawPicture()+ −
with (x, y) = (0, 0).+ −
*/+ −
+ −
bool QPicture::play(QPainter *painter)+ −
{+ −
Q_D(QPicture);+ −
+ −
if (d->pictb.size() == 0) // nothing recorded+ −
return true;+ −
+ −
if (!d->formatOk && !d->checkFormat())+ −
return false;+ −
+ −
d->pictb.open(QIODevice::ReadOnly); // open buffer device+ −
QDataStream s;+ −
s.setDevice(&d->pictb); // attach data stream to buffer+ −
s.device()->seek(10); // go directly to the data+ −
s.setVersion(d->formatMajor == 4 ? 3 : d->formatMajor);+ −
+ −
quint8 c, clen;+ −
quint32 nrecords;+ −
s >> c >> clen;+ −
Q_ASSERT(c == QPicturePrivate::PdcBegin);+ −
// bounding rect was introduced in ver 4. Read in checkFormat().+ −
if (d->formatMajor >= 4) {+ −
qint32 dummy;+ −
s >> dummy >> dummy >> dummy >> dummy;+ −
}+ −
s >> nrecords;+ −
if (!exec(painter, s, nrecords)) {+ −
qWarning("QPicture::play: Format error");+ −
d->pictb.close();+ −
return false;+ −
}+ −
d->pictb.close();+ −
return true; // no end-command+ −
}+ −
+ −
+ −
//+ −
// QFakeDevice is used to create fonts with a custom DPI+ −
//+ −
class QFakeDevice : public QPaintDevice+ −
{+ −
public:+ −
QFakeDevice() { dpi_x = qt_defaultDpiX(); dpi_y = qt_defaultDpiY(); }+ −
void setDpiX(int dpi) { dpi_x = dpi; }+ −
void setDpiY(int dpi) { dpi_y = dpi; }+ −
QPaintEngine *paintEngine() const { return 0; }+ −
int metric(PaintDeviceMetric m) const+ −
{+ −
switch(m) {+ −
case PdmPhysicalDpiX:+ −
case PdmDpiX:+ −
return dpi_x;+ −
case PdmPhysicalDpiY:+ −
case PdmDpiY:+ −
return dpi_y;+ −
default:+ −
return QPaintDevice::metric(m);+ −
}+ −
}+ −
+ −
private:+ −
int dpi_x;+ −
int dpi_y;+ −
};+ −
+ −
/*!+ −
\internal+ −
Iterates over the internal picture data and draws the picture using+ −
\a painter.+ −
*/+ −
+ −
bool QPicture::exec(QPainter *painter, QDataStream &s, int nrecords)+ −
{+ −
Q_D(QPicture);+ −
#if defined(QT_DEBUG)+ −
int strm_pos;+ −
#endif+ −
quint8 c; // command id+ −
quint8 tiny_len; // 8-bit length descriptor+ −
qint32 len; // 32-bit length descriptor+ −
qint16 i_16, i1_16, i2_16; // parameters...+ −
qint8 i_8;+ −
quint32 ul;+ −
double dbl;+ −
bool bl;+ −
QByteArray str1;+ −
QString str;+ −
QPointF p, p1, p2;+ −
QPoint ip, ip1, ip2;+ −
QRect ir;+ −
QRectF r;+ −
QPolygonF a;+ −
QPolygon ia;+ −
QColor color;+ −
QFont font;+ −
QPen pen;+ −
QBrush brush;+ −
QRegion rgn;+ −
QMatrix wmatrix;+ −
QTransform matrix;+ −
+ −
QTransform worldMatrix = painter->transform();+ −
worldMatrix.scale(qreal(painter->device()->logicalDpiX()) / qreal(qt_defaultDpiX()),+ −
qreal(painter->device()->logicalDpiY()) / qreal(qt_defaultDpiY()));+ −
painter->setTransform(worldMatrix);+ −
+ −
while (nrecords-- && !s.atEnd()) {+ −
s >> c; // read cmd+ −
s >> tiny_len; // read param length+ −
if (tiny_len == 255) // longer than 254 bytes+ −
s >> len;+ −
else+ −
len = tiny_len;+ −
#if defined(QT_DEBUG)+ −
strm_pos = s.device()->pos();+ −
#endif+ −
switch (c) { // exec cmd+ −
case QPicturePrivate::PdcNOP:+ −
break;+ −
case QPicturePrivate::PdcDrawPoint:+ −
if (d->formatMajor <= 5) {+ −
s >> ip;+ −
painter->drawPoint(ip);+ −
} else {+ −
s >> p;+ −
painter->drawPoint(p);+ −
}+ −
break;+ −
case QPicturePrivate::PdcDrawPoints:+ −
// ## implement me in the picture paint engine+ −
// s >> a >> i1_32 >> i2_32;+ −
// painter->drawPoints(a.mid(i1_32, i2_32));+ −
break;+ −
case QPicturePrivate::PdcDrawPath: {+ −
QPainterPath path;+ −
s >> path;+ −
painter->drawPath(path);+ −
break;+ −
}+ −
case QPicturePrivate::PdcDrawLine:+ −
if (d->formatMajor <= 5) {+ −
s >> ip1 >> ip2;+ −
painter->drawLine(ip1, ip2);+ −
} else {+ −
s >> p1 >> p2;+ −
painter->drawLine(p1, p2);+ −
}+ −
break;+ −
case QPicturePrivate::PdcDrawRect:+ −
if (d->formatMajor <= 5) {+ −
s >> ir;+ −
painter->drawRect(ir);+ −
} else {+ −
s >> r;+ −
painter->drawRect(r);+ −
}+ −
break;+ −
case QPicturePrivate::PdcDrawRoundRect:+ −
if (d->formatMajor <= 5) {+ −
s >> ir >> i1_16 >> i2_16;+ −
painter->drawRoundedRect(ir, i1_16, i2_16, Qt::RelativeSize);+ −
} else {+ −
s >> r >> i1_16 >> i2_16;+ −
painter->drawRoundedRect(r, i1_16, i2_16, Qt::RelativeSize);+ −
}+ −
break;+ −
case QPicturePrivate::PdcDrawEllipse:+ −
if (d->formatMajor <= 5) {+ −
s >> ir;+ −
painter->drawEllipse(ir);+ −
} else {+ −
s >> r;+ −
painter->drawEllipse(r);+ −
}+ −
break;+ −
case QPicturePrivate::PdcDrawArc:+ −
if (d->formatMajor <= 5) {+ −
s >> ir;+ −
r = ir;+ −
} else {+ −
s >> r;+ −
}+ −
s >> i1_16 >> i2_16;+ −
painter->drawArc(r, i1_16, i2_16);+ −
break;+ −
case QPicturePrivate::PdcDrawPie:+ −
if (d->formatMajor <= 5) {+ −
s >> ir;+ −
r = ir;+ −
} else {+ −
s >> r;+ −
}+ −
s >> i1_16 >> i2_16;+ −
painter->drawPie(r, i1_16, i2_16);+ −
break;+ −
case QPicturePrivate::PdcDrawChord:+ −
if (d->formatMajor <= 5) {+ −
s >> ir;+ −
r = ir;+ −
} else {+ −
s >> r;+ −
}+ −
s >> i1_16 >> i2_16;+ −
painter->drawChord(r, i1_16, i2_16);+ −
break;+ −
case QPicturePrivate::PdcDrawLineSegments:+ −
s >> ia;+ −
painter->drawLines(ia);+ −
ia.clear();+ −
break;+ −
case QPicturePrivate::PdcDrawPolyline:+ −
if (d->formatMajor <= 5) {+ −
s >> ia;+ −
painter->drawPolyline(ia);+ −
ia.clear();+ −
} else {+ −
s >> a;+ −
painter->drawPolyline(a);+ −
a.clear();+ −
}+ −
break;+ −
case QPicturePrivate::PdcDrawPolygon:+ −
if (d->formatMajor <= 5) {+ −
s >> ia >> i_8;+ −
painter->drawPolygon(ia, i_8 ? Qt::WindingFill : Qt::OddEvenFill);+ −
a.clear();+ −
} else {+ −
s >> a >> i_8;+ −
painter->drawPolygon(a, i_8 ? Qt::WindingFill : Qt::OddEvenFill);+ −
a.clear();+ −
}+ −
break;+ −
case QPicturePrivate::PdcDrawCubicBezier: {+ −
s >> ia;+ −
QPainterPath path;+ −
Q_ASSERT(ia.size() == 4);+ −
path.moveTo(ia.at(0));+ −
path.cubicTo(ia.at(1), ia.at(2), ia.at(3));+ −
painter->strokePath(path, painter->pen());+ −
a.clear();+ −
}+ −
break;+ −
case QPicturePrivate::PdcDrawText:+ −
s >> ip >> str1;+ −
painter->drawText(ip, QString::fromLatin1(str1));+ −
break;+ −
case QPicturePrivate::PdcDrawTextFormatted:+ −
s >> ir >> i_16 >> str1;+ −
painter->drawText(ir, i_16, QString::fromLatin1(str1));+ −
break;+ −
case QPicturePrivate::PdcDrawText2:+ −
if (d->formatMajor <= 5) {+ −
s >> ip >> str;+ −
painter->drawText(ip, str);+ −
} else {+ −
s >> p >> str;+ −
painter->drawText(p, str);+ −
}+ −
break;+ −
case QPicturePrivate::PdcDrawText2Formatted:+ −
s >> ir;+ −
s >> i_16;+ −
s >> str;+ −
painter->drawText(ir, i_16, str);+ −
break;+ −
case QPicturePrivate::PdcDrawTextItem: {+ −
s >> p >> str >> font >> ul;+ −
+ −
// the text layout direction is not used here because it's already+ −
// aligned when QPicturePaintEngine::drawTextItem() serializes the+ −
// drawText() call, therefore ul is unsed in this context+ −
+ −
if (d->formatMajor >= 9) {+ −
s >> dbl;+ −
QFont fnt(font);+ −
if (dbl != 1.0) {+ −
QFakeDevice fake;+ −
fake.setDpiX(qRound(dbl*qt_defaultDpiX()));+ −
fake.setDpiY(qRound(dbl*qt_defaultDpiY()));+ −
fnt = QFont(font, &fake);+ −
}+ −
+ −
qreal justificationWidth;+ −
s >> justificationWidth;+ −
+ −
int flags = Qt::TextSingleLine | Qt::TextDontClip | Qt::TextForceLeftToRight;+ −
+ −
QSizeF size(1, 1);+ −
if (justificationWidth > 0) {+ −
size.setWidth(justificationWidth);+ −
flags |= Qt::TextJustificationForced;+ −
flags |= Qt::AlignJustify;+ −
}+ −
+ −
QFontMetrics fm(fnt);+ −
QPointF pt(p.x(), p.y() - fm.ascent());+ −
qt_format_text(fnt, QRectF(pt, size), flags, /*opt*/0,+ −
str, /*brect=*/0, /*tabstops=*/0, /*...*/0, /*tabarraylen=*/0, painter);+ −
} else {+ −
qt_format_text(font, QRectF(p, QSizeF(1, 1)), Qt::TextSingleLine | Qt::TextDontClip, /*opt*/0,+ −
str, /*brect=*/0, /*tabstops=*/0, /*...*/0, /*tabarraylen=*/0, painter);+ −
}+ −
+ −
break;+ −
}+ −
case QPicturePrivate::PdcDrawPixmap: {+ −
QPixmap pixmap;+ −
if (d->formatMajor < 4) {+ −
s >> ip >> pixmap;+ −
painter->drawPixmap(ip, pixmap);+ −
} else if (d->formatMajor <= 5) {+ −
s >> ir >> pixmap;+ −
painter->drawPixmap(ir, pixmap);+ −
} else {+ −
QRectF sr;+ −
if (d->in_memory_only) {+ −
int index;+ −
s >> r >> index >> sr;+ −
Q_ASSERT(index < d->pixmap_list.size());+ −
pixmap = d->pixmap_list.at(index);+ −
} else {+ −
s >> r >> pixmap >> sr;+ −
}+ −
painter->drawPixmap(r, pixmap, sr);+ −
}+ −
}+ −
break;+ −
case QPicturePrivate::PdcDrawTiledPixmap: {+ −
QPixmap pixmap;+ −
if (d->in_memory_only) {+ −
int index;+ −
s >> r >> index >> p;+ −
Q_ASSERT(index < d->pixmap_list.size());+ −
pixmap = d->pixmap_list.at(index);+ −
} else {+ −
s >> r >> pixmap >> p;+ −
}+ −
painter->drawTiledPixmap(r, pixmap, p);+ −
}+ −
break;+ −
case QPicturePrivate::PdcDrawImage: {+ −
QImage image;+ −
if (d->formatMajor < 4) {+ −
s >> p >> image;+ −
painter->drawImage(p, image);+ −
} else if (d->formatMajor <= 5){+ −
s >> ir >> image;+ −
painter->drawImage(ir, image, QRect(0, 0, ir.width(), ir.height()));+ −
} else {+ −
QRectF sr;+ −
if (d->in_memory_only) {+ −
int index;+ −
s >> r >> index >> sr >> ul;+ −
Q_ASSERT(index < d->image_list.size());+ −
image = d->image_list.at(index);+ −
} else {+ −
s >> r >> image >> sr >> ul;+ −
}+ −
painter->drawImage(r, image, sr, Qt::ImageConversionFlags(ul));+ −
}+ −
}+ −
break;+ −
case QPicturePrivate::PdcBegin:+ −
s >> ul; // number of records+ −
if (!exec(painter, s, ul))+ −
return false;+ −
break;+ −
case QPicturePrivate::PdcEnd:+ −
if (nrecords == 0)+ −
return true;+ −
break;+ −
case QPicturePrivate::PdcSave:+ −
painter->save();+ −
break;+ −
case QPicturePrivate::PdcRestore:+ −
painter->restore();+ −
break;+ −
case QPicturePrivate::PdcSetBkColor:+ −
s >> color;+ −
painter->setBackground(color);+ −
break;+ −
case QPicturePrivate::PdcSetBkMode:+ −
s >> i_8;+ −
painter->setBackgroundMode((Qt::BGMode)i_8);+ −
break;+ −
case QPicturePrivate::PdcSetROP: // NOP+ −
s >> i_8;+ −
break;+ −
case QPicturePrivate::PdcSetBrushOrigin:+ −
if (d->formatMajor <= 5) {+ −
s >> ip;+ −
painter->setBrushOrigin(ip);+ −
} else {+ −
s >> p;+ −
painter->setBrushOrigin(p);+ −
}+ −
break;+ −
case QPicturePrivate::PdcSetFont:+ −
s >> font;+ −
painter->setFont(font);+ −
break;+ −
case QPicturePrivate::PdcSetPen:+ −
if (d->in_memory_only) {+ −
int index;+ −
s >> index;+ −
Q_ASSERT(index < d->pen_list.size());+ −
pen = d->pen_list.at(index);+ −
} else {+ −
s >> pen;+ −
}+ −
painter->setPen(pen);+ −
break;+ −
case QPicturePrivate::PdcSetBrush:+ −
if (d->in_memory_only) {+ −
int index;+ −
s >> index;+ −
Q_ASSERT(index < d->brush_list.size());+ −
brush = d->brush_list.at(index);+ −
} else {+ −
s >> brush;+ −
}+ −
painter->setBrush(brush);+ −
break;+ −
// #ifdef Q_Q3PAINTER+ −
// case QPicturePrivate::PdcSetTabStops:+ −
// s >> i_16;+ −
// painter->setTabStops(i_16);+ −
// break;+ −
// case QPicturePrivate::PdcSetTabArray:+ −
// s >> i_16;+ −
// if (i_16 == 0) {+ −
// painter->setTabArray(0);+ −
// } else {+ −
// int *ta = new int[i_16];+ −
// for (int i=0; i<i_16; i++) {+ −
// s >> i1_16;+ −
// ta[i] = i1_16;+ −
// }+ −
// painter->setTabArray(ta);+ −
// delete [] ta;+ −
// }+ −
// break;+ −
// #endif+ −
case QPicturePrivate::PdcSetVXform:+ −
s >> i_8;+ −
painter->setViewTransformEnabled(i_8);+ −
break;+ −
case QPicturePrivate::PdcSetWindow:+ −
if (d->formatMajor <= 5) {+ −
s >> ir;+ −
painter->setWindow(ir);+ −
} else {+ −
s >> r;+ −
painter->setWindow(r.toRect());+ −
}+ −
break;+ −
case QPicturePrivate::PdcSetViewport:+ −
if (d->formatMajor <= 5) {+ −
s >> ir;+ −
painter->setViewport(ir);+ −
} else {+ −
s >> r;+ −
painter->setViewport(r.toRect());+ −
}+ −
break;+ −
case QPicturePrivate::PdcSetWXform:+ −
s >> i_8;+ −
painter->setMatrixEnabled(i_8);+ −
break;+ −
case QPicturePrivate::PdcSetWMatrix:+ −
if (d->formatMajor >= 8) {+ −
s >> matrix >> i_8;+ −
} else {+ −
s >> wmatrix >> i_8;+ −
matrix = QTransform(wmatrix);+ −
}+ −
// i_8 is always false due to updateXForm() in qpaintengine_pic.cpp+ −
painter->setTransform(matrix * worldMatrix, i_8);+ −
break;+ −
// #ifdef Q_Q3PAINTER+ −
// case QPicturePrivate::PdcSaveWMatrix:+ −
// painter->saveWorldMatrix();+ −
// break;+ −
// case QPicturePrivate::PdcRestoreWMatrix:+ −
// painter->restoreWorldMatrix();+ −
// break;+ −
// #endif+ −
case QPicturePrivate::PdcSetClip:+ −
s >> i_8;+ −
painter->setClipping(i_8);+ −
break;+ −
case QPicturePrivate::PdcSetClipRegion:+ −
s >> rgn >> i_8;+ −
if (d->formatMajor >= 9) {+ −
painter->setClipRegion(rgn, Qt::ClipOperation(i_8));+ −
} else {+ −
painter->setClipRegion(rgn);+ −
}+ −
break;+ −
case QPicturePrivate::PdcSetClipPath:+ −
{+ −
QPainterPath path;+ −
s >> path >> i_8;+ −
painter->setClipPath(path, Qt::ClipOperation(i_8));+ −
break;+ −
}+ −
case QPicturePrivate::PdcSetRenderHint:+ −
s >> ul;+ −
painter->setRenderHint(QPainter::Antialiasing,+ −
bool(ul & QPainter::Antialiasing));+ −
painter->setRenderHint(QPainter::SmoothPixmapTransform,+ −
bool(ul & QPainter::SmoothPixmapTransform));+ −
break;+ −
case QPicturePrivate::PdcSetCompositionMode:+ −
s >> ul;+ −
painter->setCompositionMode((QPainter::CompositionMode)ul);+ −
break;+ −
case QPicturePrivate::PdcSetClipEnabled:+ −
s >> bl;+ −
painter->setClipping(bl);+ −
break;+ −
case QPicturePrivate::PdcSetOpacity:+ −
s >> dbl;+ −
painter->setOpacity(qreal(dbl));+ −
break;+ −
default:+ −
qWarning("QPicture::play: Invalid command %d", c);+ −
if (len) // skip unknown command+ −
s.device()->seek(s.device()->pos()+len);+ −
}+ −
#if defined(QT_DEBUG)+ −
//qDebug("device->at(): %i, strm_pos: %i len: %i", (int)s.device()->pos(), strm_pos, len);+ −
Q_ASSERT(qint32(s.device()->pos() - strm_pos) == len);+ −
#endif+ −
}+ −
return false;+ −
}+ −
+ −
/*!+ −
\internal+ −
+ −
Internal implementation of the virtual QPaintDevice::metric()+ −
function.+ −
+ −
A picture has the following hard-coded values: numcolors=16777216+ −
and depth=24.+ −
+ −
\a m is the metric to get.+ −
*/+ −
+ −
int QPicture::metric(PaintDeviceMetric m) const+ −
{+ −
int val;+ −
QRect brect = boundingRect();+ −
switch (m) {+ −
case PdmWidth:+ −
val = brect.width();+ −
break;+ −
case PdmHeight:+ −
val = brect.height();+ −
break;+ −
case PdmWidthMM:+ −
val = int(25.4/qt_defaultDpiX()*brect.width());+ −
break;+ −
case PdmHeightMM:+ −
val = int(25.4/qt_defaultDpiY()*brect.height());+ −
break;+ −
case PdmDpiX:+ −
case PdmPhysicalDpiX:+ −
val = qt_defaultDpiX();+ −
break;+ −
case PdmDpiY:+ −
case PdmPhysicalDpiY:+ −
val = qt_defaultDpiY();+ −
break;+ −
case PdmNumColors:+ −
val = 16777216;+ −
break;+ −
case PdmDepth:+ −
val = 24;+ −
break;+ −
default:+ −
val = 0;+ −
qWarning("QPicture::metric: Invalid metric command");+ −
}+ −
return val;+ −
}+ −
+ −
/*!+ −
\fn void QPicture::detach()+ −
\internal+ −
Detaches from shared picture data and makes sure that this picture+ −
is the only one referring to the data.+ −
+ −
If multiple pictures share common data, this picture makes a copy+ −
of the data and detaches itself from the sharing mechanism.+ −
Nothing is done if there is just a single reference.+ −
*/+ −
+ −
/*! \fn bool QPicture::isDetached() const+ −
\internal+ −
*/+ −
+ −
/*! \internal+ −
### Qt 5 - remove me+ −
*/+ −
void QPicture::detach_helper()+ −
{+ −
// QExplicitelySharedDataPointer takes care of cloning using+ −
// QPicturePrivate's copy constructor. Do not call detach_helper() anymore+ −
// and remove in Qt 5, please.+ −
Q_ASSERT_X(false, "QPicture::detach_helper()", "Do not call this function");+ −
}+ −
+ −
/*!+ −
Assigns picture \a p to this picture and returns a reference to+ −
this picture.+ −
*/+ −
QPicture& QPicture::operator=(const QPicture &p)+ −
{+ −
d_ptr = p.d_ptr;+ −
return *this;+ −
}+ −
+ −
/*!+ −
\internal+ −
+ −
Constructs a QPicturePrivate+ −
*/+ −
QPicturePrivate::QPicturePrivate()+ −
: in_memory_only(false)+ −
{+ −
}+ −
+ −
/*!+ −
\internal+ −
+ −
Copy-Constructs a QPicturePrivate. Needed when detaching.+ −
*/+ −
QPicturePrivate::QPicturePrivate(const QPicturePrivate &other)+ −
: trecs(other.trecs),+ −
formatOk(other.formatOk),+ −
formatMinor(other.formatMinor),+ −
brect(other.brect),+ −
override_rect(other.override_rect),+ −
in_memory_only(false)+ −
{+ −
pictb.setData(other.pictb.data(), other.pictb.size());+ −
if (other.pictb.isOpen()) {+ −
pictb.open(other.pictb.openMode());+ −
pictb.seek(other.pictb.pos());+ −
}+ −
}+ −
+ −
/*!+ −
\internal+ −
+ −
Sets formatOk to false and resets the format version numbers to default+ −
*/+ −
+ −
void QPicturePrivate::resetFormat()+ −
{+ −
formatOk = false;+ −
formatMajor = mfhdr_maj;+ −
formatMinor = mfhdr_min;+ −
}+ −
+ −
+ −
/*!+ −
\internal+ −
+ −
Checks data integrity and format version number. Set formatOk to+ −
true on success, to false otherwise. Returns the resulting formatOk+ −
value.+ −
*/+ −
bool QPicturePrivate::checkFormat()+ −
{+ −
resetFormat();+ −
+ −
// can't check anything in an empty buffer+ −
if (pictb.size() == 0 || pictb.isOpen())+ −
return false;+ −
+ −
pictb.open(QIODevice::ReadOnly); // open buffer device+ −
QDataStream s;+ −
s.setDevice(&pictb); // attach data stream to buffer+ −
+ −
char mf_id[4]; // picture header tag+ −
s.readRawData(mf_id, 4); // read actual tag+ −
if (memcmp(mf_id, qt_mfhdr_tag, 4) != 0) { // wrong header id+ −
qWarning("QPicturePaintEngine::checkFormat: Incorrect header");+ −
pictb.close();+ −
return false;+ −
}+ −
+ −
int cs_start = sizeof(quint32); // pos of checksum word+ −
int data_start = cs_start + sizeof(quint16);+ −
quint16 cs,ccs;+ −
QByteArray buf = pictb.buffer(); // pointer to data+ −
+ −
s >> cs; // read checksum+ −
ccs = (quint16) qChecksum(buf.constData() + data_start, buf.size() - data_start);+ −
if (ccs != cs) {+ −
qWarning("QPicturePaintEngine::checkFormat: Invalid checksum %x, %x expected",+ −
ccs, cs);+ −
pictb.close();+ −
return false;+ −
}+ −
+ −
quint16 major, minor;+ −
s >> major >> minor; // read version number+ −
if (major > mfhdr_maj) { // new, incompatible version+ −
qWarning("QPicturePaintEngine::checkFormat: Incompatible version %d.%d",+ −
major, minor);+ −
pictb.close();+ −
return false;+ −
}+ −
s.setVersion(major != 4 ? major : 3);+ −
+ −
quint8 c, clen;+ −
s >> c >> clen;+ −
if (c == QPicturePrivate::PdcBegin) {+ −
if (!(major >= 1 && major <= 3)) {+ −
qint32 l, t, w, h;+ −
s >> l >> t >> w >> h;+ −
brect = QRect(l, t, w, h);+ −
}+ −
} else {+ −
qWarning("QPicturePaintEngine::checkFormat: Format error");+ −
pictb.close();+ −
return false;+ −
}+ −
pictb.close();+ −
+ −
formatOk = true; // picture seems to be ok+ −
formatMajor = major;+ −
formatMinor = minor;+ −
return true;+ −
}+ −
+ −
/*! \internal */+ −
QPaintEngine *QPicture::paintEngine() const+ −
{+ −
if (!d_func()->paintEngine)+ −
const_cast<QPicture*>(this)->d_func()->paintEngine.reset(new QPicturePaintEngine);+ −
return d_func()->paintEngine.data();+ −
}+ −
+ −
/*****************************************************************************+ −
QPicture stream functions+ −
*****************************************************************************/+ −
+ −
#ifndef QT_NO_DATASTREAM+ −
/*!+ −
\relates QPicture+ −
+ −
Writes picture \a r to the stream \a s and returns a reference to+ −
the stream.+ −
*/+ −
+ −
QDataStream &operator<<(QDataStream &s, const QPicture &r)+ −
{+ −
quint32 size = r.d_func()->pictb.buffer().size();+ −
s << size;+ −
// null picture ?+ −
if (size == 0)+ −
return s;+ −
// just write the whole buffer to the stream+ −
s.writeRawData (r.d_func()->pictb.buffer(), r.d_func()->pictb.buffer().size());+ −
return s;+ −
}+ −
+ −
/*!+ −
\relates QPicture+ −
+ −
Reads a picture from the stream \a s into picture \a r and returns+ −
a reference to the stream.+ −
*/+ −
+ −
QDataStream &operator>>(QDataStream &s, QPicture &r)+ −
{+ −
QDataStream sr;+ −
+ −
// "init"; this code is similar to the beginning of QPicture::cmd()+ −
sr.setDevice(&r.d_func()->pictb);+ −
sr.setVersion(r.d_func()->formatMajor);+ −
quint32 len;+ −
s >> len;+ −
QByteArray data;+ −
if (len > 0) {+ −
data.resize(len);+ −
s.readRawData(data.data(), len);+ −
}+ −
+ −
r.d_func()->pictb.setData(data);+ −
r.d_func()->resetFormat();+ −
return s;+ −
}+ −
#endif // QT_NO_DATASTREAM+ −
+ −
+ −
#ifndef QT_NO_PICTUREIO+ −
+ −
QT_BEGIN_INCLUDE_NAMESPACE+ −
#include "qregexp.h"+ −
#include "qapplication.h"+ −
#include "qpictureformatplugin.h"+ −
QT_END_INCLUDE_NAMESPACE+ −
+ −
/*!+ −
\obsolete+ −
+ −
Returns a string that specifies the picture format of the file \a+ −
fileName, or 0 if the file cannot be read or if the format is not+ −
recognized.+ −
+ −
\sa load() save()+ −
*/+ −
+ −
const char* QPicture::pictureFormat(const QString &fileName)+ −
{+ −
return QPictureIO::pictureFormat(fileName);+ −
}+ −
+ −
/*!+ −
\obsolete+ −
+ −
Returns a list of picture formats that are supported for picture+ −
input.+ −
+ −
\sa outputFormats() inputFormatList() QPictureIO+ −
*/+ −
QList<QByteArray> QPicture::inputFormats()+ −
{+ −
return QPictureIO::inputFormats();+ −
}+ −
+ −
static QStringList qToStringList(const QList<QByteArray> arr)+ −
{+ −
QStringList list;+ −
for (int i = 0; i < arr.count(); ++i)+ −
list.append(QString::fromLatin1(arr.at(i)));+ −
return list;+ −
}+ −
+ −
/*!+ −
\obsolete+ −
+ −
Returns a list of picture formats that are supported for picture+ −
input.+ −
+ −
Note that if you want to iterate over the list, you should iterate+ −
over a copy, e.g.+ −
\snippet doc/src/snippets/picture/picture.cpp 2+ −
+ −
\sa outputFormatList() inputFormats() QPictureIO+ −
*/+ −
QStringList QPicture::inputFormatList()+ −
{+ −
return qToStringList(QPictureIO::inputFormats());+ −
}+ −
+ −
+ −
/*!+ −
\obsolete+ −
+ −
Returns a list of picture formats that are supported for picture+ −
output.+ −
+ −
Note that if you want to iterate over the list, you should iterate+ −
over a copy, e.g.+ −
\snippet doc/src/snippets/picture/picture.cpp 3+ −
+ −
\sa inputFormatList() outputFormats() QPictureIO+ −
*/+ −
QStringList QPicture::outputFormatList()+ −
{+ −
return qToStringList(QPictureIO::outputFormats());+ −
}+ −
+ −
/*!+ −
\obsolete+ −
+ −
Returns a list of picture formats that are supported for picture+ −
output.+ −
+ −
\sa inputFormats() outputFormatList() QPictureIO+ −
*/+ −
QList<QByteArray> QPicture::outputFormats()+ −
{+ −
return QPictureIO::outputFormats();+ −
}+ −
+ −
/*****************************************************************************+ −
QPictureIO member functions+ −
*****************************************************************************/+ −
+ −
/*!+ −
\obsolete+ −
+ −
\class QPictureIO+ −
+ −
\brief The QPictureIO class contains parameters for loading and+ −
saving pictures.+ −
+ −
\ingroup painting+ −
\ingroup io+ −
+ −
QPictureIO contains a QIODevice object that is used for picture data+ −
I/O. The programmer can install new picture file formats in addition+ −
to those that Qt provides.+ −
+ −
You don't normally need to use this class; QPicture::load(),+ −
QPicture::save().+ −
+ −
\sa QPicture QPixmap QFile+ −
*/+ −
+ −
struct QPictureIOData+ −
{+ −
QPicture pi; // picture+ −
int iostat; // IO status+ −
QByteArray frmt; // picture format+ −
QIODevice *iodev; // IO device+ −
QString fname; // file name+ −
QString descr; // picture description+ −
const char *parameters;+ −
int quality;+ −
float gamma;+ −
};+ −
+ −
/*!+ −
Constructs a QPictureIO object with all parameters set to zero.+ −
*/+ −
+ −
QPictureIO::QPictureIO()+ −
{+ −
init();+ −
}+ −
+ −
/*!+ −
Constructs a QPictureIO object with the I/O device \a ioDevice and a+ −
\a format tag.+ −
*/+ −
+ −
QPictureIO::QPictureIO(QIODevice *ioDevice, const char *format)+ −
{+ −
init();+ −
d->iodev = ioDevice;+ −
d->frmt = format;+ −
}+ −
+ −
/*!+ −
Constructs a QPictureIO object with the file name \a fileName and a+ −
\a format tag.+ −
*/+ −
+ −
QPictureIO::QPictureIO(const QString &fileName, const char* format)+ −
{+ −
init();+ −
d->frmt = format;+ −
d->fname = fileName;+ −
}+ −
+ −
/*!+ −
Contains initialization common to all QPictureIO constructors.+ −
*/+ −
+ −
void QPictureIO::init()+ −
{+ −
d = new QPictureIOData();+ −
d->parameters = 0;+ −
d->quality = -1; // default quality of the current format+ −
d->gamma=0.0f;+ −
d->iostat = 0;+ −
d->iodev = 0;+ −
}+ −
+ −
/*!+ −
Destroys the object and all related data.+ −
*/+ −
+ −
QPictureIO::~QPictureIO()+ −
{+ −
if (d->parameters)+ −
delete [] (char*)d->parameters;+ −
delete d;+ −
}+ −
+ −
+ −
/*****************************************************************************+ −
QPictureIO picture handler functions+ −
*****************************************************************************/+ −
+ −
class QPictureHandler+ −
{+ −
public:+ −
QPictureHandler(const char *f, const char *h, const QByteArray& fl,+ −
picture_io_handler r, picture_io_handler w);+ −
QByteArray format; // picture format+ −
QRegExp header; // picture header pattern+ −
enum TMode { Untranslated=0, TranslateIn, TranslateInOut } text_mode;+ −
picture_io_handler read_picture; // picture read function+ −
picture_io_handler write_picture; // picture write function+ −
bool obsolete; // support not "published"+ −
};+ −
+ −
QPictureHandler::QPictureHandler(const char *f, const char *h, const QByteArray& fl,+ −
picture_io_handler r, picture_io_handler w)+ −
: format(f), header(QString::fromLatin1(h))+ −
{+ −
text_mode = Untranslated;+ −
if (fl.contains('t'))+ −
text_mode = TranslateIn;+ −
else if (fl.contains('T'))+ −
text_mode = TranslateInOut;+ −
obsolete = fl.contains('O');+ −
read_picture = r;+ −
write_picture = w;+ −
}+ −
+ −
typedef QList<QPictureHandler *> QPHList;+ −
Q_GLOBAL_STATIC(QPHList, pictureHandlers)+ −
+ −
#ifndef QT_NO_LIBRARY+ −
Q_GLOBAL_STATIC(QMutex, mutex)+ −
Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, factoryLoader,+ −
(QPictureFormatInterface_iid,+ −
QLatin1String("/pictureformats")))+ −
#endif+ −
void qt_init_picture_plugins()+ −
{+ −
#ifndef QT_NO_LIBRARY+ −
QMutexLocker locker(mutex());+ −
QFactoryLoader *loader = factoryLoader();+ −
QStringList keys = loader->keys();+ −
for (int i = 0; i < keys.count(); ++i)+ −
if (QPictureFormatInterface *format = qobject_cast<QPictureFormatInterface*>(loader->instance(keys.at(i))))+ −
format->installIOHandler(keys.at(i));+ −
#endif+ −
}+ −
+ −
static void cleanup()+ −
{+ −
// make sure that picture handlers are delete before plugin manager+ −
if (QPHList *list = pictureHandlers()) {+ −
qDeleteAll(*list);+ −
list->clear();+ −
}+ −
}+ −
+ −
void qt_init_picture_handlers() // initialize picture handlers+ −
{+ −
static QBasicAtomicInt done = Q_BASIC_ATOMIC_INITIALIZER(0);+ −
if (done.testAndSetRelaxed(0, 1)) {+ −
qAddPostRoutine(cleanup);+ −
}+ −
}+ −
+ −
static QPictureHandler *get_picture_handler(const char *format)+ −
{ // get pointer to handler+ −
qt_init_picture_handlers();+ −
qt_init_picture_plugins();+ −
if (QPHList *list = pictureHandlers()) {+ −
for (int i = 0; i < list->size(); ++i) {+ −
if (list->at(i)->format == format)+ −
return list->at(i);+ −
}+ −
}+ −
return 0; // no such handler+ −
}+ −
+ −
+ −
/*!+ −
Defines a picture I/O handler for the picture format called \a+ −
format, which is recognized using the regular+ −
expression defined in \a header, read using \a readPicture and+ −
written using \a writePicture.+ −
+ −
\a flags is a string of single-character flags for this format.+ −
The only flag defined currently is T (upper case), so the only+ −
legal value for \a flags are "T" and the empty string. The "T"+ −
flag means that the picture file is a text file, and Qt should treat+ −
all newline conventions as equivalent. (XPM files and some PPM+ −
files are text files for example.)+ −
+ −
\a format is used to select a handler to write a QPicture; \a header+ −
is used to select a handler to read an picture file.+ −
+ −
If \a readPicture is a null pointer, the QPictureIO will not be able+ −
to read pictures in \a format. If \a writePicture is a null pointer,+ −
the QPictureIO will not be able to write pictures in \a format. If+ −
both are null, the QPictureIO object is valid but useless.+ −
+ −
Example:+ −
\snippet doc/src/snippets/picture/picture.cpp 6+ −
\codeline+ −
\snippet doc/src/snippets/picture/picture.cpp 7+ −
\codeline+ −
\snippet doc/src/snippets/picture/picture.cpp 8+ −
+ −
Before the regular expression test, all the 0 bytes in the file header are+ −
converted to 1 bytes. This is done because when Qt was ASCII-based, QRegExp+ −
could not handle 0 bytes in strings.+ −
+ −
The regexp is only applied on the first 14 bytes of the file.+ −
+ −
(Note that if one handlerIO supports writing a format and another+ −
supports reading it, Qt supports both reading and writing. If two+ −
handlers support the same operation, Qt chooses one arbitrarily.)+ −
*/+ −
+ −
void QPictureIO::defineIOHandler(const char *format,+ −
const char *header,+ −
const char *flags,+ −
picture_io_handler readPicture,+ −
picture_io_handler writePicture)+ −
{+ −
qt_init_picture_handlers();+ −
if (QPHList *list = pictureHandlers()) {+ −
QPictureHandler *p;+ −
p = new QPictureHandler(format, header, QByteArray(flags), readPicture, writePicture);+ −
list->prepend(p);+ −
}+ −
}+ −
+ −
+ −
/*****************************************************************************+ −
QPictureIO normal member functions+ −
*****************************************************************************/+ −
+ −
/*!+ −
Returns the picture currently set.+ −
+ −
\sa setPicture()+ −
*/+ −
const QPicture &QPictureIO::picture() const { return d->pi; }+ −
+ −
/*!+ −
Returns the picture's IO status. A non-zero value indicates an+ −
error, whereas 0 means that the IO operation was successful.+ −
+ −
\sa setStatus()+ −
*/+ −
int QPictureIO::status() const { return d->iostat; }+ −
+ −
/*!+ −
Returns the picture format string or 0 if no format has been+ −
explicitly set.+ −
*/+ −
const char *QPictureIO::format() const { return d->frmt; }+ −
+ −
/*!+ −
Returns the IO device currently set.+ −
+ −
\sa setIODevice()+ −
*/+ −
QIODevice *QPictureIO::ioDevice() const { return d->iodev; }+ −
+ −
/*!+ −
Returns the file name currently set.+ −
+ −
\sa setFileName()+ −
*/+ −
QString QPictureIO::fileName() const { return d->fname; }+ −
+ −
+ −
/*!+ −
Returns the picture description string.+ −
+ −
\sa setDescription()+ −
*/+ −
QString QPictureIO::description() const { return d->descr; }+ −
+ −
/*!+ −
Sets the picture to \a picture.+ −
+ −
\sa picture()+ −
*/+ −
void QPictureIO::setPicture(const QPicture &picture)+ −
{+ −
d->pi = picture;+ −
}+ −
+ −
/*!+ −
Sets the picture IO status to \a status. A non-zero value indicates+ −
an error, whereas 0 means that the IO operation was successful.+ −
+ −
\sa status()+ −
*/+ −
void QPictureIO::setStatus(int status)+ −
{+ −
d->iostat = status;+ −
}+ −
+ −
/*!+ −
Sets the picture format to \a format for the picture to be read or+ −
written.+ −
+ −
It is necessary to specify a format before writing an picture, but+ −
it is not necessary to specify a format before reading an picture.+ −
+ −
If no format has been set, Qt guesses the picture format before+ −
reading it. If a format is set the picture will only be read if it+ −
has that format.+ −
+ −
\sa read() write() format()+ −
*/+ −
void QPictureIO::setFormat(const char *format)+ −
{+ −
d->frmt = format;+ −
}+ −
+ −
/*!+ −
Sets the IO device to be used for reading or writing an picture.+ −
+ −
Setting the IO device allows pictures to be read/written to any+ −
block-oriented QIODevice.+ −
+ −
If \a ioDevice is not null, this IO device will override file name+ −
settings.+ −
+ −
\sa setFileName()+ −
*/+ −
void QPictureIO::setIODevice(QIODevice *ioDevice)+ −
{+ −
d->iodev = ioDevice;+ −
}+ −
+ −
/*!+ −
Sets the name of the file to read or write an picture from to \a+ −
fileName.+ −
+ −
\sa setIODevice()+ −
*/+ −
void QPictureIO::setFileName(const QString &fileName)+ −
{+ −
d->fname = fileName;+ −
}+ −
+ −
/*!+ −
Returns the quality of the written picture, related to the+ −
compression ratio.+ −
+ −
\sa setQuality() QPicture::save()+ −
*/+ −
int QPictureIO::quality() const+ −
{+ −
return d->quality;+ −
}+ −
+ −
/*!+ −
Sets the quality of the written picture to \a q, related to the+ −
compression ratio.+ −
+ −
\a q must be in the range -1..100. Specify 0 to obtain small+ −
compressed files, 100 for large uncompressed files. (-1 signifies+ −
the default compression.)+ −
+ −
\sa quality() QPicture::save()+ −
*/+ −
+ −
void QPictureIO::setQuality(int q)+ −
{+ −
d->quality = q;+ −
}+ −
+ −
/*!+ −
Returns the picture's parameters string.+ −
+ −
\sa setParameters()+ −
*/+ −
+ −
const char *QPictureIO::parameters() const+ −
{+ −
return d->parameters;+ −
}+ −
+ −
/*!+ −
Sets the picture's parameter string to \a parameters. This is for+ −
picture handlers that require special parameters.+ −
+ −
Although the current picture formats supported by Qt ignore the+ −
parameters string, it may be used in future extensions or by+ −
contributions (for example, JPEG).+ −
+ −
\sa parameters()+ −
*/+ −
+ −
void QPictureIO::setParameters(const char *parameters)+ −
{+ −
if (d->parameters)+ −
delete [] (char*)d->parameters;+ −
d->parameters = qstrdup(parameters);+ −
}+ −
+ −
/*!+ −
Sets the gamma value at which the picture will be viewed to \a+ −
gamma. If the picture format stores a gamma value for which the+ −
picture is intended to be used, then this setting will be used to+ −
modify the picture. Setting to 0.0 will disable gamma correction+ −
(i.e. any specification in the file will be ignored).+ −
+ −
The default value is 0.0.+ −
+ −
\sa gamma()+ −
*/+ −
void QPictureIO::setGamma(float gamma)+ −
{+ −
d->gamma=gamma;+ −
}+ −
+ −
/*!+ −
Returns the gamma value at which the picture will be viewed.+ −
+ −
\sa setGamma()+ −
*/+ −
float QPictureIO::gamma() const+ −
{+ −
return d->gamma;+ −
}+ −
+ −
/*!+ −
Sets the picture description string for picture handlers that support+ −
picture descriptions to \a description.+ −
+ −
Currently, no picture format supported by Qt uses the description+ −
string.+ −
*/+ −
+ −
void QPictureIO::setDescription(const QString &description)+ −
{+ −
d->descr = description;+ −
}+ −
+ −
+ −
/*!+ −
Returns a string that specifies the picture format of the file \a+ −
fileName, or null if the file cannot be read or if the format is+ −
not recognized.+ −
*/+ −
+ −
QByteArray QPictureIO::pictureFormat(const QString &fileName)+ −
{+ −
QFile file(fileName);+ −
QByteArray format;+ −
if (!file.open(QIODevice::ReadOnly))+ −
return format;+ −
format = pictureFormat(&file);+ −
file.close();+ −
return format;+ −
}+ −
+ −
/*!+ −
\overload+ −
+ −
Returns a string that specifies the picture format of the picture read+ −
from IO device \a d, or 0 if the device cannot be read or if the+ −
format is not recognized.+ −
+ −
Make sure that \a d is at the right position in the device (for+ −
example, at the beginning of the file).+ −
+ −
\sa QIODevice::at()+ −
*/+ −
+ −
QByteArray QPictureIO::pictureFormat(QIODevice *d)+ −
{+ −
// if you change this change the documentation for defineIOHandler()+ −
const int buflen = 14;+ −
+ −
char buf[buflen];+ −
char buf2[buflen];+ −
qt_init_picture_handlers();+ −
qt_init_picture_plugins();+ −
int pos = d->pos(); // save position+ −
int rdlen = d->read(buf, buflen); // read a few bytes+ −
+ −
QByteArray format;+ −
if (rdlen != buflen)+ −
return format;+ −
+ −
memcpy(buf2, buf, buflen);+ −
+ −
for (int n = 0; n < rdlen; n++)+ −
if (buf[n] == '\0')+ −
buf[n] = '\001';+ −
if (rdlen > 0) {+ −
buf[rdlen - 1] = '\0';+ −
QString bufStr = QString::fromLatin1(buf);+ −
if (QPHList *list = pictureHandlers()) {+ −
for (int i = 0; i < list->size(); ++i) {+ −
if (list->at(i)->header.indexIn(bufStr) != -1) { // try match with headers+ −
format = list->at(i)->format;+ −
break;+ −
}+ −
}+ −
}+ −
}+ −
d->seek(pos); // restore position+ −
return format;+ −
}+ −
+ −
/*!+ −
Returns a sorted list of picture formats that are supported for+ −
picture input.+ −
*/+ −
QList<QByteArray> QPictureIO::inputFormats()+ −
{+ −
QList<QByteArray> result;+ −
+ −
qt_init_picture_handlers();+ −
qt_init_picture_plugins();+ −
+ −
if (QPHList *list = pictureHandlers()) {+ −
for (int i = 0; i < list->size(); ++i) {+ −
QPictureHandler *p = list->at(i);+ −
if (p->read_picture && !p->obsolete && !result.contains(p->format))+ −
result.append(p->format);+ −
}+ −
}+ −
qSort(result);+ −
+ −
return result;+ −
}+ −
+ −
/*!+ −
Returns a sorted list of picture formats that are supported for+ −
picture output.+ −
*/+ −
QList<QByteArray> QPictureIO::outputFormats()+ −
{+ −
qt_init_picture_handlers();+ −
qt_init_picture_plugins();+ −
+ −
QList<QByteArray> result;+ −
if (QPHList *list = pictureHandlers()) {+ −
for (int i = 0; i < list->size(); ++i) {+ −
QPictureHandler *p = list->at(i);+ −
if (p->write_picture && !p->obsolete && !result.contains(p->format))+ −
result.append(p->format);+ −
}+ −
}+ −
return result;+ −
}+ −
+ −
+ −
+ −
/*!+ −
Reads an picture into memory and returns true if the picture was+ −
successfully read; otherwise returns false.+ −
+ −
Before reading an picture you must set an IO device or a file name.+ −
If both an IO device and a file name have been set, the IO device+ −
will be used.+ −
+ −
Setting the picture file format string is optional.+ −
+ −
Note that this function does \e not set the \link format()+ −
format\endlink used to read the picture. If you need that+ −
information, use the pictureFormat() static functions.+ −
+ −
Example:+ −
+ −
\snippet doc/src/snippets/picture/picture.cpp 4+ −
+ −
\sa setIODevice() setFileName() setFormat() write() QPixmap::load()+ −
*/+ −
bool QPictureIO::read()+ −
{+ −
QFile file;+ −
const char *picture_format;+ −
QPictureHandler *h;+ −
+ −
if (d->iodev) { // read from io device+ −
// ok, already open+ −
} else if (!d->fname.isEmpty()) { // read from file+ −
file.setFileName(d->fname);+ −
if (!file.open(QIODevice::ReadOnly))+ −
return false; // cannot open file+ −
d->iodev = &file;+ −
} else { // no file name or io device+ −
return false;+ −
}+ −
if (d->frmt.isEmpty()) {+ −
// Try to guess format+ −
picture_format = pictureFormat(d->iodev); // get picture format+ −
if (!picture_format) {+ −
if (file.isOpen()) { // unknown format+ −
file.close();+ −
d->iodev = 0;+ −
}+ −
return false;+ −
}+ −
} else {+ −
picture_format = d->frmt;+ −
}+ −
+ −
h = get_picture_handler(picture_format);+ −
if (file.isOpen()) {+ −
#if !defined(Q_OS_UNIX)+ −
if (h && h->text_mode) { // reopen in translated mode+ −
file.close();+ −
file.open(QIODevice::ReadOnly | QIODevice::Text);+ −
}+ −
else+ −
#endif+ −
file.seek(0); // position to start+ −
}+ −
d->iostat = 1; // assume error+ −
+ −
if (h && h->read_picture)+ −
(*h->read_picture)(this);+ −
+ −
if (file.isOpen()) { // picture was read using file+ −
file.close();+ −
d->iodev = 0;+ −
}+ −
return d->iostat == 0; // picture successfully read?+ −
}+ −
+ −
+ −
/*!+ −
Writes an picture to an IO device and returns true if the picture was+ −
successfully written; otherwise returns false.+ −
+ −
Before writing an picture you must set an IO device or a file name.+ −
If both an IO device and a file name have been set, the IO device+ −
will be used.+ −
+ −
The picture will be written using the specified picture format.+ −
+ −
Example:+ −
\snippet doc/src/snippets/picture/picture.cpp 5+ −
+ −
\sa setIODevice() setFileName() setFormat() read() QPixmap::save()+ −
*/+ −
bool QPictureIO::write()+ −
{+ −
if (d->frmt.isEmpty())+ −
return false;+ −
QPictureHandler *h = get_picture_handler(d->frmt);+ −
if (!h || !h->write_picture) {+ −
qWarning("QPictureIO::write: No such picture format handler: %s",+ −
format());+ −
return false;+ −
}+ −
QFile file;+ −
if (!d->iodev && !d->fname.isEmpty()) {+ −
file.setFileName(d->fname);+ −
bool translate = h->text_mode==QPictureHandler::TranslateInOut;+ −
QIODevice::OpenMode fmode = translate ? QIODevice::WriteOnly | QIODevice::Text : QIODevice::OpenMode(QIODevice::WriteOnly);+ −
if (!file.open(fmode)) // couldn't create file+ −
return false;+ −
d->iodev = &file;+ −
}+ −
d->iostat = 1;+ −
(*h->write_picture)(this);+ −
if (file.isOpen()) { // picture was written using file+ −
file.close();+ −
d->iodev = 0;+ −
}+ −
return d->iostat == 0; // picture successfully written?+ −
}+ −
#endif //QT_NO_PICTUREIO+ −
+ −
/*!+ −
\fn QPicture QPicture::copy() const+ −
+ −
Use simple assignment instead.+ −
*/+ −
+ −
QT_END_NAMESPACE+ −
+ −
#endif // QT_NO_PICTURE+ −
+ −
/*!+ −
\typedef QPicture::DataPtr+ −
\internal+ −
*/+ −
+ −
/*!+ −
\fn DataPtr &QPicture::data_ptr()+ −
\internal+ −
*/+ −