/**************************************************************************** | |
** | |
** Copyright (C) 2011 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$ | |
** GNU Lesser General Public License Usage | |
** 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. | |
** | |
** GNU General Public License Usage | |
** Alternatively, this file may be used under the terms of the GNU General | |
** Public License version 3.0 as published by the Free Software Foundation | |
** and appearing in the file LICENSE.GPL included in the packaging of this | |
** file. Please review the following information to ensure the GNU General | |
** Public License version 3.0 requirements will be met: | |
** http://www.gnu.org/copyleft/gpl.html. | |
** | |
** Other Usage | |
** Alternatively, this file may be used in accordance with the terms and | |
** conditions contained in a signed written agreement between you and Nokia. | |
** | |
** | |
** | |
** | |
** | |
** $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 | |
*/ |