| 1 |
/**************************************************************************** |
| 2 |
** |
| 3 |
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). |
| 4 |
** All rights reserved. |
| 5 |
** Contact: Nokia Corporation (qt-info@nokia.com) |
| 6 |
** |
| 7 |
** This file is part of the QtGui module of the Qt Toolkit. |
| 8 |
** |
| 9 |
** $QT_BEGIN_LICENSE:LGPL$ |
| 10 |
** No Commercial Usage |
| 11 |
** This file contains pre-release code and may not be distributed. |
| 12 |
** You may use this file in accordance with the terms and conditions |
| 13 |
** contained in the Technology Preview License Agreement accompanying |
| 14 |
** this package. |
| 15 |
** |
| 16 |
** GNU Lesser General Public License Usage |
| 17 |
** Alternatively, this file may be used under the terms of the GNU Lesser |
| 18 |
** General Public License version 2.1 as published by the Free Software |
| 19 |
** Foundation and appearing in the file LICENSE.LGPL included in the |
| 20 |
** packaging of this file. Please review the following information to |
| 21 |
** ensure the GNU Lesser General Public License version 2.1 requirements |
| 22 |
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
| 23 |
** |
| 24 |
** In addition, as a special exception, Nokia gives you certain additional |
| 25 |
** rights. These rights are described in the Nokia Qt LGPL Exception |
| 26 |
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
| 27 |
** |
| 28 |
** If you have questions regarding the use of this file, please contact |
| 29 |
** Nokia at qt-info@nokia.com. |
| 30 |
** |
| 31 |
** |
| 32 |
** |
| 33 |
** |
| 34 |
** |
| 35 |
** |
| 36 |
** |
| 37 |
** |
| 38 |
** $QT_END_LICENSE$ |
| 39 |
** |
| 40 |
****************************************************************************/ |
| 41 |
|
| 42 |
#include "qpicture.h" |
| 43 |
#include <private/qpicture_p.h> |
| 44 |
|
| 45 |
#ifndef QT_NO_PICTURE |
| 46 |
|
| 47 |
#include <private/qfactoryloader_p.h> |
| 48 |
#include <private/qpaintengine_pic_p.h> |
| 49 |
|
| 50 |
#include "qdatastream.h" |
| 51 |
#include "qfile.h" |
| 52 |
#include "qimage.h" |
| 53 |
#include "qmutex.h" |
| 54 |
#include "qpainter.h" |
| 55 |
#include "qpainterpath.h" |
| 56 |
#include "qpixmap.h" |
| 57 |
#include "qregion.h" |
| 58 |
#include "qdebug.h" |
| 59 |
|
| 60 |
QT_BEGIN_NAMESPACE |
| 61 |
|
| 62 |
void qt_format_text(const QFont &fnt, const QRectF &_r, |
| 63 |
int tf, const QTextOption *opt, const QString& str, QRectF *brect, |
| 64 |
int tabstops, int *, int tabarraylen, |
| 65 |
QPainter *painter); |
| 66 |
|
| 67 |
/*! |
| 68 |
\class QPicture |
| 69 |
\brief The QPicture class is a paint device that records and |
| 70 |
replays QPainter commands. |
| 71 |
|
| 72 |
\ingroup painting |
| 73 |
\ingroup shared |
| 74 |
|
| 75 |
|
| 76 |
A picture serializes painter commands to an IO device in a |
| 77 |
platform-independent format. They are sometimes referred to as meta-files. |
| 78 |
|
| 79 |
Qt pictures use a proprietary binary format. Unlike native picture |
| 80 |
(meta-file) formats on many window systems, Qt pictures have no |
| 81 |
limitations regarding their contents. Everything that can be |
| 82 |
painted on a widget or pixmap (e.g., fonts, pixmaps, regions, |
| 83 |
transformed graphics, etc.) can also be stored in a picture. |
| 84 |
|
| 85 |
QPicture is resolution independent, i.e. a QPicture can be |
| 86 |
displayed on different devices (for example svg, pdf, ps, printer |
| 87 |
and screen) looking the same. This is, for instance, needed for |
| 88 |
WYSIWYG print preview. QPicture runs in the default system dpi, |
| 89 |
and scales the painter to match differences in resolution |
| 90 |
depending on the window system. |
| 91 |
|
| 92 |
Example of how to record a picture: |
| 93 |
\snippet doc/src/snippets/picture/picture.cpp 0 |
| 94 |
|
| 95 |
Note that the list of painter commands is reset on each call to |
| 96 |
the QPainter::begin() function. |
| 97 |
|
| 98 |
Example of how to replay a picture: |
| 99 |
\snippet doc/src/snippets/picture/picture.cpp 1 |
| 100 |
|
| 101 |
Pictures can also be drawn using play(). Some basic data about a |
| 102 |
picture is available, for example, size(), isNull() and |
| 103 |
boundingRect(). |
| 104 |
|
| 105 |
\sa QMovie |
| 106 |
*/ |
| 107 |
|
| 108 |
const char *qt_mfhdr_tag = "QPIC"; // header tag |
| 109 |
static const quint16 mfhdr_maj = 11; // major version # |
| 110 |
static const quint16 mfhdr_min = 0; // minor version # |
| 111 |
Q_GUI_EXPORT extern int qt_defaultDpiX(); |
| 112 |
Q_GUI_EXPORT extern int qt_defaultDpiY(); |
| 113 |
|
| 114 |
/*! |
| 115 |
Constructs an empty picture. |
| 116 |
|
| 117 |
The \a formatVersion parameter may be used to \e create a QPicture |
| 118 |
that can be read by applications that are compiled with earlier |
| 119 |
versions of Qt. |
| 120 |
|
| 121 |
Note that the default formatVersion is -1 which signifies the |
| 122 |
current release, i.e. for Qt 4.0 a formatVersion of 7 is the same |
| 123 |
as the default formatVersion of -1. |
| 124 |
|
| 125 |
Reading pictures generated by earlier versions of Qt is not |
| 126 |
supported in Qt 4.0. |
| 127 |
*/ |
| 128 |
|
| 129 |
QPicture::QPicture(int formatVersion) |
| 130 |
: QPaintDevice(), |
| 131 |
d_ptr(new QPicturePrivate) |
| 132 |
{ |
| 133 |
Q_D(QPicture); |
| 134 |
|
| 135 |
if (formatVersion == 0) |
| 136 |
qWarning("QPicture: invalid format version 0"); |
| 137 |
|
| 138 |
// still accept the 0 default from before Qt 3.0. |
| 139 |
if (formatVersion > 0 && formatVersion != (int)mfhdr_maj) { |
| 140 |
d->formatMajor = formatVersion; |
| 141 |
d->formatMinor = 0; |
| 142 |
d->formatOk = false; |
| 143 |
} else { |
| 144 |
d->resetFormat(); |
| 145 |
} |
| 146 |
} |
| 147 |
|
| 148 |
/*! |
| 149 |
Constructs a copy of \a pic. |
| 150 |
|
| 151 |
This constructor is fast thanks to \l{implicit sharing}. |
| 152 |
*/ |
| 153 |
|
| 154 |
QPicture::QPicture(const QPicture &pic) |
| 155 |
: QPaintDevice(), d_ptr(pic.d_ptr) |
| 156 |
{ |
| 157 |
} |
| 158 |
|
| 159 |
/*! \internal */ |
| 160 |
QPicture::QPicture(QPicturePrivate &dptr) |
| 161 |
: QPaintDevice(), |
| 162 |
d_ptr(&dptr) |
| 163 |
{ |
| 164 |
} |
| 165 |
|
| 166 |
/*! |
| 167 |
Destroys the picture. |
| 168 |
*/ |
| 169 |
QPicture::~QPicture() |
| 170 |
{ |
| 171 |
} |
| 172 |
|
| 173 |
/*! |
| 174 |
\internal |
| 175 |
*/ |
| 176 |
int QPicture::devType() const |
| 177 |
{ |
| 178 |
return QInternal::Picture; |
| 179 |
} |
| 180 |
|
| 181 |
/*! |
| 182 |
\fn bool QPicture::isNull() const |
| 183 |
|
| 184 |
Returns true if the picture contains no data; otherwise returns |
| 185 |
false. |
| 186 |
*/ |
| 187 |
|
| 188 |
/*! |
| 189 |
\fn uint QPicture::size() const |
| 190 |
|
| 191 |
Returns the size of the picture data. |
| 192 |
|
| 193 |
\sa data() |
| 194 |
*/ |
| 195 |
|
| 196 |
/*! |
| 197 |
\fn const char* QPicture::data() const |
| 198 |
|
| 199 |
Returns a pointer to the picture data. The pointer is only valid |
| 200 |
until the next non-const function is called on this picture. The |
| 201 |
returned pointer is 0 if the picture contains no data. |
| 202 |
|
| 203 |
\sa size(), isNull() |
| 204 |
*/ |
| 205 |
|
| 206 |
|
| 207 |
bool QPicture::isNull() const |
| 208 |
{ |
| 209 |
return d_func()->pictb.buffer().isNull(); |
| 210 |
} |
| 211 |
|
| 212 |
uint QPicture::size() const |
| 213 |
{ |
| 214 |
return d_func()->pictb.buffer().size(); |
| 215 |
} |
| 216 |
|
| 217 |
const char* QPicture::data() const |
| 218 |
{ |
| 219 |
return d_func()->pictb.buffer(); |
| 220 |
} |
| 221 |
|
| 222 |
void QPicture::detach() |
| 223 |
{ |
| 224 |
d_ptr.detach(); |
| 225 |
} |
| 226 |
|
| 227 |
bool QPicture::isDetached() const |
| 228 |
{ |
| 229 |
return d_func()->ref == 1; |
| 230 |
} |
| 231 |
|
| 232 |
/*! |
| 233 |
Sets the picture data directly from \a data and \a size. This |
| 234 |
function copies the input data. |
| 235 |
|
| 236 |
\sa data(), size() |
| 237 |
*/ |
| 238 |
|
| 239 |
void QPicture::setData(const char* data, uint size) |
| 240 |
{ |
| 241 |
detach(); |
| 242 |
d_func()->pictb.setData(data, size); |
| 243 |
d_func()->resetFormat(); // we'll have to check |
| 244 |
} |
| 245 |
|
| 246 |
|
| 247 |
/*! |
| 248 |
Loads a picture from the file specified by \a fileName and returns |
| 249 |
true if successful; otherwise returns false. |
| 250 |
|
| 251 |
Please note that the \a format parameter has been deprecated and |
| 252 |
will have no effect. |
| 253 |
|
| 254 |
\sa save() |
| 255 |
*/ |
| 256 |
|
| 257 |
bool QPicture::load(const QString &fileName, const char *format) |
| 258 |
{ |
| 259 |
QFile f(fileName); |
| 260 |
if (!f.open(QIODevice::ReadOnly)) |
| 261 |
return false; |
| 262 |
return load(&f, format); |
| 263 |
} |
| 264 |
|
| 265 |
/*! |
| 266 |
\overload |
| 267 |
|
| 268 |
\a dev is the device to use for loading. |
| 269 |
*/ |
| 270 |
|
| 271 |
bool QPicture::load(QIODevice *dev, const char *format) |
| 272 |
{ |
| 273 |
if(format) { |
| 274 |
#ifndef QT_NO_PICTUREIO |
| 275 |
QPictureIO io(dev, format); |
| 276 |
bool result = io.read(); |
| 277 |
if (result) { |
| 278 |
operator=(io.picture()); |
| 279 |
|
| 280 |
} else if (format) |
| 281 |
#else |
| 282 |
bool result = false; |
| 283 |
#endif |
| 284 |
{ |
| 285 |
qWarning("QPicture::load: No such picture format: %s", format); |
| 286 |
} |
| 287 |
return result; |
| 288 |
} |
| 289 |
|
| 290 |
detach(); |
| 291 |
QByteArray a = dev->readAll(); |
| 292 |
|
| 293 |
d_func()->pictb.setData(a); // set byte array in buffer |
| 294 |
return d_func()->checkFormat(); |
| 295 |
} |
| 296 |
|
| 297 |
/*! |
| 298 |
Saves a picture to the file specified by \a fileName and returns |
| 299 |
true if successful; otherwise returns false. |
| 300 |
|
| 301 |
Please note that the \a format parameter has been deprecated and |
| 302 |
will have no effect. |
| 303 |
|
| 304 |
\sa load() |
| 305 |
*/ |
| 306 |
|
| 307 |
bool QPicture::save(const QString &fileName, const char *format) |
| 308 |
{ |
| 309 |
if (paintingActive()) { |
| 310 |
qWarning("QPicture::save: still being painted on. " |
| 311 |
"Call QPainter::end() first"); |
| 312 |
return false; |
| 313 |
} |
| 314 |
|
| 315 |
|
| 316 |
if(format) { |
| 317 |
#ifndef QT_NO_PICTUREIO |
| 318 |
QPictureIO io(fileName, format); |
| 319 |
bool result = io.write(); |
| 320 |
if (result) { |
| 321 |
operator=(io.picture()); |
| 322 |
} else if (format) |
| 323 |
#else |
| 324 |
bool result = false; |
| 325 |
#endif |
| 326 |
{ |
| 327 |
qWarning("QPicture::save: No such picture format: %s", format); |
| 328 |
} |
| 329 |
return result; |
| 330 |
} |
| 331 |
|
| 332 |
QFile f(fileName); |
| 333 |
if (!f.open(QIODevice::WriteOnly)) |
| 334 |
return false; |
| 335 |
return save(&f, format); |
| 336 |
} |
| 337 |
|
| 338 |
/*! |
| 339 |
\overload |
| 340 |
|
| 341 |
\a dev is the device to use for saving. |
| 342 |
*/ |
| 343 |
|
| 344 |
bool QPicture::save(QIODevice *dev, const char *format) |
| 345 |
{ |
| 346 |
if (paintingActive()) { |
| 347 |
qWarning("QPicture::save: still being painted on. " |
| 348 |
"Call QPainter::end() first"); |
| 349 |
return false; |
| 350 |
} |
| 351 |
|
| 352 |
if(format) { |
| 353 |
#ifndef QT_NO_PICTUREIO |
| 354 |
QPictureIO io(dev, format); |
| 355 |
bool result = io.write(); |
| 356 |
if (result) { |
| 357 |
operator=(io.picture()); |
| 358 |
} else if (format) |
| 359 |
#else |
| 360 |
bool result = false; |
| 361 |
#endif |
| 362 |
{ |
| 363 |
qWarning("QPicture::save: No such picture format: %s", format); |
| 364 |
} |
| 365 |
return result; |
| 366 |
} |
| 367 |
|
| 368 |
dev->write(d_func()->pictb.buffer(), d_func()->pictb.buffer().size()); |
| 369 |
return true; |
| 370 |
} |
| 371 |
|
| 372 |
/*! |
| 373 |
Returns the picture's bounding rectangle or an invalid rectangle |
| 374 |
if the picture contains no data. |
| 375 |
*/ |
| 376 |
|
| 377 |
QRect QPicture::boundingRect() const |
| 378 |
{ |
| 379 |
Q_D(const QPicture); |
| 380 |
// Use override rect where possible. |
| 381 |
if (!d->override_rect.isEmpty()) |
| 382 |
return d->override_rect; |
| 383 |
|
| 384 |
if (!d->formatOk) |
| 385 |
d_ptr->checkFormat(); |
| 386 |
|
| 387 |
return d->brect; |
| 388 |
} |
| 389 |
|
| 390 |
/*! |
| 391 |
Sets the picture's bounding rectangle to \a r. The automatically |
| 392 |
calculated value is overridden. |
| 393 |
*/ |
| 394 |
|
| 395 |
void QPicture::setBoundingRect(const QRect &r) |
| 396 |
{ |
| 397 |
d_func()->override_rect = r; |
| 398 |
} |
| 399 |
|
| 400 |
/*! |
| 401 |
Replays the picture using \a painter, and returns true if |
| 402 |
successful; otherwise returns false. |
| 403 |
|
| 404 |
This function does exactly the same as QPainter::drawPicture() |
| 405 |
with (x, y) = (0, 0). |
| 406 |
*/ |
| 407 |
|
| 408 |
bool QPicture::play(QPainter *painter) |
| 409 |
{ |
| 410 |
Q_D(QPicture); |
| 411 |
|
| 412 |
if (d->pictb.size() == 0) // nothing recorded |
| 413 |
return true; |
| 414 |
|
| 415 |
if (!d->formatOk && !d->checkFormat()) |
| 416 |
return false; |
| 417 |
|
| 418 |
d->pictb.open(QIODevice::ReadOnly); // open buffer device |
| 419 |
QDataStream s; |
| 420 |
s.setDevice(&d->pictb); // attach data stream to buffer |
| 421 |
s.device()->seek(10); // go directly to the data |
| 422 |
s.setVersion(d->formatMajor == 4 ? 3 : d->formatMajor); |
| 423 |
|
| 424 |
quint8 c, clen; |
| 425 |
quint32 nrecords; |
| 426 |
s >> c >> clen; |
| 427 |
Q_ASSERT(c == QPicturePrivate::PdcBegin); |
| 428 |
// bounding rect was introduced in ver 4. Read in checkFormat(). |
| 429 |
if (d->formatMajor >= 4) { |
| 430 |
qint32 dummy; |
| 431 |
s >> dummy >> dummy >> dummy >> dummy; |
| 432 |
} |
| 433 |
s >> nrecords; |
| 434 |
if (!exec(painter, s, nrecords)) { |
| 435 |
qWarning("QPicture::play: Format error"); |
| 436 |
d->pictb.close(); |
| 437 |
return false; |
| 438 |
} |
| 439 |
d->pictb.close(); |
| 440 |
return true; // no end-command |
| 441 |
} |
| 442 |
|
| 443 |
|
| 444 |
// |
| 445 |
// QFakeDevice is used to create fonts with a custom DPI |
| 446 |
// |
| 447 |
class QFakeDevice : public QPaintDevice |
| 448 |
{ |
| 449 |
public: |
| 450 |
QFakeDevice() { dpi_x = qt_defaultDpiX(); dpi_y = qt_defaultDpiY(); } |
| 451 |
void setDpiX(int dpi) { dpi_x = dpi; } |
| 452 |
void setDpiY(int dpi) { dpi_y = dpi; } |
| 453 |
QPaintEngine *paintEngine() const { return 0; } |
| 454 |
int metric(PaintDeviceMetric m) const |
| 455 |
{ |
| 456 |
switch(m) { |
| 457 |
case PdmPhysicalDpiX: |
| 458 |
case PdmDpiX: |
| 459 |
return dpi_x; |
| 460 |
case PdmPhysicalDpiY: |
| 461 |
case PdmDpiY: |
| 462 |
return dpi_y; |
| 463 |
default: |
| 464 |
return QPaintDevice::metric(m); |
| 465 |
} |
| 466 |
} |
| 467 |
|
| 468 |
private: |
| 469 |
int dpi_x; |
| 470 |
int dpi_y; |
| 471 |
}; |
| 472 |
|
| 473 |
/*! |
| 474 |
\internal |
| 475 |
Iterates over the internal picture data and draws the picture using |
| 476 |
\a painter. |
| 477 |
*/ |
| 478 |
|
| 479 |
bool QPicture::exec(QPainter *painter, QDataStream &s, int nrecords) |
| 480 |
{ |
| 481 |
Q_D(QPicture); |
| 482 |
#if defined(QT_DEBUG) |
| 483 |
int strm_pos; |
| 484 |
#endif |
| 485 |
quint8 c; // command id |
| 486 |
quint8 tiny_len; // 8-bit length descriptor |
| 487 |
qint32 len; // 32-bit length descriptor |
| 488 |
qint16 i_16, i1_16, i2_16; // parameters... |
| 489 |
qint8 i_8; |
| 490 |
quint32 ul; |
| 491 |
double dbl; |
| 492 |
bool bl; |
| 493 |
QByteArray str1; |
| 494 |
QString str; |
| 495 |
QPointF p, p1, p2; |
| 496 |
QPoint ip, ip1, ip2; |
| 497 |
QRect ir; |
| 498 |
QRectF r; |
| 499 |
QPolygonF a; |
| 500 |
QPolygon ia; |
| 501 |
QColor color; |
| 502 |
QFont font; |
| 503 |
QPen pen; |
| 504 |
QBrush brush; |
| 505 |
QRegion rgn; |
| 506 |
QMatrix wmatrix; |
| 507 |
QTransform matrix; |
| 508 |
|
| 509 |
QTransform worldMatrix = painter->transform(); |
| 510 |
worldMatrix.scale(qreal(painter->device()->logicalDpiX()) / qreal(qt_defaultDpiX()), |
| 511 |
qreal(painter->device()->logicalDpiY()) / qreal(qt_defaultDpiY())); |
| 512 |
painter->setTransform(worldMatrix); |
| 513 |
|
| 514 |
while (nrecords-- && !s.atEnd()) { |
| 515 |
s >> c; // read cmd |
| 516 |
s >> tiny_len; // read param length |
| 517 |
if (tiny_len == 255) // longer than 254 bytes |
| 518 |
s >> len; |
| 519 |
else |
| 520 |
len = tiny_len; |
| 521 |
#if defined(QT_DEBUG) |
| 522 |
strm_pos = s.device()->pos(); |
| 523 |
#endif |
| 524 |
switch (c) { // exec cmd |
| 525 |
case QPicturePrivate::PdcNOP: |
| 526 |
break; |
| 527 |
case QPicturePrivate::PdcDrawPoint: |
| 528 |
if (d->formatMajor <= 5) { |
| 529 |
s >> ip; |
| 530 |
painter->drawPoint(ip); |
| 531 |
} else { |
| 532 |
s >> p; |
| 533 |
painter->drawPoint(p); |
| 534 |
} |
| 535 |
break; |
| 536 |
case QPicturePrivate::PdcDrawPoints: |
| 537 |
// ## implement me in the picture paint engine |
| 538 |
// s >> a >> i1_32 >> i2_32; |
| 539 |
// painter->drawPoints(a.mid(i1_32, i2_32)); |
| 540 |
break; |
| 541 |
case QPicturePrivate::PdcDrawPath: { |
| 542 |
QPainterPath path; |
| 543 |
s >> path; |
| 544 |
painter->drawPath(path); |
| 545 |
break; |
| 546 |
} |
| 547 |
case QPicturePrivate::PdcDrawLine: |
| 548 |
if (d->formatMajor <= 5) { |
| 549 |
s >> ip1 >> ip2; |
| 550 |
painter->drawLine(ip1, ip2); |
| 551 |
} else { |
| 552 |
s >> p1 >> p2; |
| 553 |
painter->drawLine(p1, p2); |
| 554 |
} |
| 555 |
break; |
| 556 |
case QPicturePrivate::PdcDrawRect: |
| 557 |
if (d->formatMajor <= 5) { |
| 558 |
s >> ir; |
| 559 |
painter->drawRect(ir); |
| 560 |
} else { |
| 561 |
s >> r; |
| 562 |
painter->drawRect(r); |
| 563 |
} |
| 564 |
break; |
| 565 |
case QPicturePrivate::PdcDrawRoundRect: |
| 566 |
if (d->formatMajor <= 5) { |
| 567 |
s >> ir >> i1_16 >> i2_16; |
| 568 |
painter->drawRoundedRect(ir, i1_16, i2_16, Qt::RelativeSize); |
| 569 |
} else { |
| 570 |
s >> r >> i1_16 >> i2_16; |
| 571 |
painter->drawRoundedRect(r, i1_16, i2_16, Qt::RelativeSize); |
| 572 |
} |
| 573 |
break; |
| 574 |
case QPicturePrivate::PdcDrawEllipse: |
| 575 |
if (d->formatMajor <= 5) { |
| 576 |
s >> ir; |
| 577 |
painter->drawEllipse(ir); |
| 578 |
} else { |
| 579 |
s >> r; |
| 580 |
painter->drawEllipse(r); |
| 581 |
} |
| 582 |
break; |
| 583 |
case QPicturePrivate::PdcDrawArc: |
| 584 |
if (d->formatMajor <= 5) { |
| 585 |
s >> ir; |
| 586 |
r = ir; |
| 587 |
} else { |
| 588 |
s >> r; |
| 589 |
} |
| 590 |
s >> i1_16 >> i2_16; |
| 591 |
painter->drawArc(r, i1_16, i2_16); |
| 592 |
break; |
| 593 |
case QPicturePrivate::PdcDrawPie: |
| 594 |
if (d->formatMajor <= 5) { |
| 595 |
s >> ir; |
| 596 |
r = ir; |
| 597 |
} else { |
| 598 |
s >> r; |
| 599 |
} |
| 600 |
s >> i1_16 >> i2_16; |
| 601 |
painter->drawPie(r, i1_16, i2_16); |
| 602 |
break; |
| 603 |
case QPicturePrivate::PdcDrawChord: |
| 604 |
if (d->formatMajor <= 5) { |
| 605 |
s >> ir; |
| 606 |
r = ir; |
| 607 |
} else { |
| 608 |
s >> r; |
| 609 |
} |
| 610 |
s >> i1_16 >> i2_16; |
| 611 |
painter->drawChord(r, i1_16, i2_16); |
| 612 |
break; |
| 613 |
case QPicturePrivate::PdcDrawLineSegments: |
| 614 |
s >> ia; |
| 615 |
painter->drawLines(ia); |
| 616 |
ia.clear(); |
| 617 |
break; |
| 618 |
case QPicturePrivate::PdcDrawPolyline: |
| 619 |
if (d->formatMajor <= 5) { |
| 620 |
s >> ia; |
| 621 |
painter->drawPolyline(ia); |
| 622 |
ia.clear(); |
| 623 |
} else { |
| 624 |
s >> a; |
| 625 |
painter->drawPolyline(a); |
| 626 |
a.clear(); |
| 627 |
} |
| 628 |
break; |
| 629 |
case QPicturePrivate::PdcDrawPolygon: |
| 630 |
if (d->formatMajor <= 5) { |
| 631 |
s >> ia >> i_8; |
| 632 |
painter->drawPolygon(ia, i_8 ? Qt::WindingFill : Qt::OddEvenFill); |
| 633 |
a.clear(); |
| 634 |
} else { |
| 635 |
s >> a >> i_8; |
| 636 |
painter->drawPolygon(a, i_8 ? Qt::WindingFill : Qt::OddEvenFill); |
| 637 |
a.clear(); |
| 638 |
} |
| 639 |
break; |
| 640 |
case QPicturePrivate::PdcDrawCubicBezier: { |
| 641 |
s >> ia; |
| 642 |
QPainterPath path; |
| 643 |
Q_ASSERT(ia.size() == 4); |
| 644 |
path.moveTo(ia.at(0)); |
| 645 |
path.cubicTo(ia.at(1), ia.at(2), ia.at(3)); |
| 646 |
painter->strokePath(path, painter->pen()); |
| 647 |
a.clear(); |
| 648 |
} |
| 649 |
break; |
| 650 |
case QPicturePrivate::PdcDrawText: |
| 651 |
s >> ip >> str1; |
| 652 |
painter->drawText(ip, QString::fromLatin1(str1)); |
| 653 |
break; |
| 654 |
case QPicturePrivate::PdcDrawTextFormatted: |
| 655 |
s >> ir >> i_16 >> str1; |
| 656 |
painter->drawText(ir, i_16, QString::fromLatin1(str1)); |
| 657 |
break; |
| 658 |
case QPicturePrivate::PdcDrawText2: |
| 659 |
if (d->formatMajor <= 5) { |
| 660 |
s >> ip >> str; |
| 661 |
painter->drawText(ip, str); |
| 662 |
} else { |
| 663 |
s >> p >> str; |
| 664 |
painter->drawText(p, str); |
| 665 |
} |
| 666 |
break; |
| 667 |
case QPicturePrivate::PdcDrawText2Formatted: |
| 668 |
s >> ir; |
| 669 |
s >> i_16; |
| 670 |
s >> str; |
| 671 |
painter->drawText(ir, i_16, str); |
| 672 |
break; |
| 673 |
case QPicturePrivate::PdcDrawTextItem: { |
| 674 |
s >> p >> str >> font >> ul; |
| 675 |
|
| 676 |
// the text layout direction is not used here because it's already |
| 677 |
// aligned when QPicturePaintEngine::drawTextItem() serializes the |
| 678 |
// drawText() call, therefore ul is unsed in this context |
| 679 |
|
| 680 |
if (d->formatMajor >= 9) { |
| 681 |
s >> dbl; |
| 682 |
QFont fnt(font); |
| 683 |
if (dbl != 1.0) { |
| 684 |
QFakeDevice fake; |
| 685 |
fake.setDpiX(qRound(dbl*qt_defaultDpiX())); |
| 686 |
fake.setDpiY(qRound(dbl*qt_defaultDpiY())); |
| 687 |
fnt = QFont(font, &fake); |
| 688 |
} |
| 689 |
|
| 690 |
qreal justificationWidth; |
| 691 |
s >> justificationWidth; |
| 692 |
|
| 693 |
int flags = Qt::TextSingleLine | Qt::TextDontClip | Qt::TextForceLeftToRight; |
| 694 |
|
| 695 |
QSizeF size(1, 1); |
| 696 |
if (justificationWidth > 0) { |
| 697 |
size.setWidth(justificationWidth); |
| 698 |
flags |= Qt::TextJustificationForced; |
| 699 |
flags |= Qt::AlignJustify; |
| 700 |
} |
| 701 |
|
| 702 |
QFontMetrics fm(fnt); |
| 703 |
QPointF pt(p.x(), p.y() - fm.ascent()); |
| 704 |
qt_format_text(fnt, QRectF(pt, size), flags, /*opt*/0, |
| 705 |
str, /*brect=*/0, /*tabstops=*/0, /*...*/0, /*tabarraylen=*/0, painter); |
| 706 |
} else { |
| 707 |
qt_format_text(font, QRectF(p, QSizeF(1, 1)), Qt::TextSingleLine | Qt::TextDontClip, /*opt*/0, |
| 708 |
str, /*brect=*/0, /*tabstops=*/0, /*...*/0, /*tabarraylen=*/0, painter); |
| 709 |
} |
| 710 |
|
| 711 |
break; |
| 712 |
} |
| 713 |
case QPicturePrivate::PdcDrawPixmap: { |
| 714 |
QPixmap pixmap; |
| 715 |
if (d->formatMajor < 4) { |
| 716 |
s >> ip >> pixmap; |
| 717 |
painter->drawPixmap(ip, pixmap); |
| 718 |
} else if (d->formatMajor <= 5) { |
| 719 |
s >> ir >> pixmap; |
| 720 |
painter->drawPixmap(ir, pixmap); |
| 721 |
} else { |
| 722 |
QRectF sr; |
| 723 |
if (d->in_memory_only) { |
| 724 |
int index; |
| 725 |
s >> r >> index >> sr; |
| 726 |
Q_ASSERT(index < d->pixmap_list.size()); |
| 727 |
pixmap = d->pixmap_list.at(index); |
| 728 |
} else { |
| 729 |
s >> r >> pixmap >> sr; |
| 730 |
} |
| 731 |
painter->drawPixmap(r, pixmap, sr); |
| 732 |
} |
| 733 |
} |
| 734 |
break; |
| 735 |
case QPicturePrivate::PdcDrawTiledPixmap: { |
| 736 |
QPixmap pixmap; |
| 737 |
if (d->in_memory_only) { |
| 738 |
int index; |
| 739 |
s >> r >> index >> p; |
| 740 |
Q_ASSERT(index < d->pixmap_list.size()); |
| 741 |
pixmap = d->pixmap_list.at(index); |
| 742 |
} else { |
| 743 |
s >> r >> pixmap >> p; |
| 744 |
} |
| 745 |
painter->drawTiledPixmap(r, pixmap, p); |
| 746 |
} |
| 747 |
break; |
| 748 |
case QPicturePrivate::PdcDrawImage: { |
| 749 |
QImage image; |
| 750 |
if (d->formatMajor < 4) { |
| 751 |
s >> p >> image; |
| 752 |
painter->drawImage(p, image); |
| 753 |
} else if (d->formatMajor <= 5){ |
| 754 |
s >> ir >> image; |
| 755 |
painter->drawImage(ir, image, QRect(0, 0, ir.width(), ir.height())); |
| 756 |
} else { |
| 757 |
QRectF sr; |
| 758 |
if (d->in_memory_only) { |
| 759 |
int index; |
| 760 |
s >> r >> index >> sr >> ul; |
| 761 |
Q_ASSERT(index < d->image_list.size()); |
| 762 |
image = d->image_list.at(index); |
| 763 |
} else { |
| 764 |
s >> r >> image >> sr >> ul; |
| 765 |
} |
| 766 |
painter->drawImage(r, image, sr, Qt::ImageConversionFlags(ul)); |
| 767 |
} |
| 768 |
} |
| 769 |
break; |
| 770 |
case QPicturePrivate::PdcBegin: |
| 771 |
s >> ul; // number of records |
| 772 |
if (!exec(painter, s, ul)) |
| 773 |
return false; |
| 774 |
break; |
| 775 |
case QPicturePrivate::PdcEnd: |
| 776 |
if (nrecords == 0) |
| 777 |
return true; |
| 778 |
break; |
| 779 |
case QPicturePrivate::PdcSave: |
| 780 |
painter->save(); |
| 781 |
break; |
| 782 |
case QPicturePrivate::PdcRestore: |
| 783 |
painter->restore(); |
| 784 |
break; |
| 785 |
case QPicturePrivate::PdcSetBkColor: |
| 786 |
s >> color; |
| 787 |
painter->setBackground(color); |
| 788 |
break; |
| 789 |
case QPicturePrivate::PdcSetBkMode: |
| 790 |
s >> i_8; |
| 791 |
painter->setBackgroundMode((Qt::BGMode)i_8); |
| 792 |
break; |
| 793 |
case QPicturePrivate::PdcSetROP: // NOP |
| 794 |
s >> i_8; |
| 795 |
break; |
| 796 |
case QPicturePrivate::PdcSetBrushOrigin: |
| 797 |
if (d->formatMajor <= 5) { |
| 798 |
s >> ip; |
| 799 |
painter->setBrushOrigin(ip); |
| 800 |
} else { |
| 801 |
s >> p; |
| 802 |
painter->setBrushOrigin(p); |
| 803 |
} |
| 804 |
break; |
| 805 |
case QPicturePrivate::PdcSetFont: |
| 806 |
s >> font; |
| 807 |
painter->setFont(font); |
| 808 |
break; |
| 809 |
case QPicturePrivate::PdcSetPen: |
| 810 |
if (d->in_memory_only) { |
| 811 |
int index; |
| 812 |
s >> index; |
| 813 |
Q_ASSERT(index < d->pen_list.size()); |
| 814 |
pen = d->pen_list.at(index); |
| 815 |
} else { |
| 816 |
s >> pen; |
| 817 |
} |
| 818 |
painter->setPen(pen); |
| 819 |
break; |
| 820 |
case QPicturePrivate::PdcSetBrush: |
| 821 |
if (d->in_memory_only) { |
| 822 |
int index; |
| 823 |
s >> index; |
| 824 |
Q_ASSERT(index < d->brush_list.size()); |
| 825 |
brush = d->brush_list.at(index); |
| 826 |
} else { |
| 827 |
s >> brush; |
| 828 |
} |
| 829 |
painter->setBrush(brush); |
| 830 |
break; |
| 831 |
// #ifdef Q_Q3PAINTER |
| 832 |
// case QPicturePrivate::PdcSetTabStops: |
| 833 |
// s >> i_16; |
| 834 |
// painter->setTabStops(i_16); |
| 835 |
// break; |
| 836 |
// case QPicturePrivate::PdcSetTabArray: |
| 837 |
// s >> i_16; |
| 838 |
// if (i_16 == 0) { |
| 839 |
// painter->setTabArray(0); |
| 840 |
// } else { |
| 841 |
// int *ta = new int[i_16]; |
| 842 |
// for (int i=0; i<i_16; i++) { |
| 843 |
// s >> i1_16; |
| 844 |
// ta[i] = i1_16; |
| 845 |
// } |
| 846 |
// painter->setTabArray(ta); |
| 847 |
// delete [] ta; |
| 848 |
// } |
| 849 |
// break; |
| 850 |
// #endif |
| 851 |
case QPicturePrivate::PdcSetVXform: |
| 852 |
s >> i_8; |
| 853 |
painter->setViewTransformEnabled(i_8); |
| 854 |
break; |
| 855 |
case QPicturePrivate::PdcSetWindow: |
| 856 |
if (d->formatMajor <= 5) { |
| 857 |
s >> ir; |
| 858 |
painter->setWindow(ir); |
| 859 |
} else { |
| 860 |
s >> r; |
| 861 |
painter->setWindow(r.toRect()); |
| 862 |
} |
| 863 |
break; |
| 864 |
case QPicturePrivate::PdcSetViewport: |
| 865 |
if (d->formatMajor <= 5) { |
| 866 |
s >> ir; |
| 867 |
painter->setViewport(ir); |
| 868 |
} else { |
| 869 |
s >> r; |
| 870 |
painter->setViewport(r.toRect()); |
| 871 |
} |
| 872 |
break; |
| 873 |
case QPicturePrivate::PdcSetWXform: |
| 874 |
s >> i_8; |
| 875 |
painter->setMatrixEnabled(i_8); |
| 876 |
break; |
| 877 |
case QPicturePrivate::PdcSetWMatrix: |
| 878 |
if (d->formatMajor >= 8) { |
| 879 |
s >> matrix >> i_8; |
| 880 |
} else { |
| 881 |
s >> wmatrix >> i_8; |
| 882 |
matrix = QTransform(wmatrix); |
| 883 |
} |
| 884 |
// i_8 is always false due to updateXForm() in qpaintengine_pic.cpp |
| 885 |
painter->setTransform(matrix * worldMatrix, i_8); |
| 886 |
break; |
| 887 |
// #ifdef Q_Q3PAINTER |
| 888 |
// case QPicturePrivate::PdcSaveWMatrix: |
| 889 |
// painter->saveWorldMatrix(); |
| 890 |
// break; |
| 891 |
// case QPicturePrivate::PdcRestoreWMatrix: |
| 892 |
// painter->restoreWorldMatrix(); |
| 893 |
// break; |
| 894 |
// #endif |
| 895 |
case QPicturePrivate::PdcSetClip: |
| 896 |
s >> i_8; |
| 897 |
painter->setClipping(i_8); |
| 898 |
break; |
| 899 |
case QPicturePrivate::PdcSetClipRegion: |
| 900 |
s >> rgn >> i_8; |
| 901 |
if (d->formatMajor >= 9) { |
| 902 |
painter->setClipRegion(rgn, Qt::ClipOperation(i_8)); |
| 903 |
} else { |
| 904 |
painter->setClipRegion(rgn); |
| 905 |
} |
| 906 |
break; |
| 907 |
case QPicturePrivate::PdcSetClipPath: |
| 908 |
{ |
| 909 |
QPainterPath path; |
| 910 |
s >> path >> i_8; |
| 911 |
painter->setClipPath(path, Qt::ClipOperation(i_8)); |
| 912 |
break; |
| 913 |
} |
| 914 |
case QPicturePrivate::PdcSetRenderHint: |
| 915 |
s >> ul; |
| 916 |
painter->setRenderHint(QPainter::Antialiasing, |
| 917 |
bool(ul & QPainter::Antialiasing)); |
| 918 |
painter->setRenderHint(QPainter::SmoothPixmapTransform, |
| 919 |
bool(ul & QPainter::SmoothPixmapTransform)); |
| 920 |
break; |
| 921 |
case QPicturePrivate::PdcSetCompositionMode: |
| 922 |
s >> ul; |
| 923 |
painter->setCompositionMode((QPainter::CompositionMode)ul); |
| 924 |
break; |
| 925 |
case QPicturePrivate::PdcSetClipEnabled: |
| 926 |
s >> bl; |
| 927 |
painter->setClipping(bl); |
| 928 |
break; |
| 929 |
case QPicturePrivate::PdcSetOpacity: |
| 930 |
s >> dbl; |
| 931 |
painter->setOpacity(qreal(dbl)); |
| 932 |
break; |
| 933 |
default: |
| 934 |
qWarning("QPicture::play: Invalid command %d", c); |
| 935 |
if (len) // skip unknown command |
| 936 |
s.device()->seek(s.device()->pos()+len); |
| 937 |
} |
| 938 |
#if defined(QT_DEBUG) |
| 939 |
//qDebug("device->at(): %i, strm_pos: %i len: %i", (int)s.device()->pos(), strm_pos, len); |
| 940 |
Q_ASSERT(qint32(s.device()->pos() - strm_pos) == len); |
| 941 |
#endif |
| 942 |
} |
| 943 |
return false; |
| 944 |
} |
| 945 |
|
| 946 |
/*! |
| 947 |
\internal |
| 948 |
|
| 949 |
Internal implementation of the virtual QPaintDevice::metric() |
| 950 |
function. |
| 951 |
|
| 952 |
A picture has the following hard-coded values: numcolors=16777216 |
| 953 |
and depth=24. |
| 954 |
|
| 955 |
\a m is the metric to get. |
| 956 |
*/ |
| 957 |
|
| 958 |
int QPicture::metric(PaintDeviceMetric m) const |
| 959 |
{ |
| 960 |
int val; |
| 961 |
QRect brect = boundingRect(); |
| 962 |
switch (m) { |
| 963 |
case PdmWidth: |
| 964 |
val = brect.width(); |
| 965 |
break; |
| 966 |
case PdmHeight: |
| 967 |
val = brect.height(); |
| 968 |
break; |
| 969 |
case PdmWidthMM: |
| 970 |
val = int(25.4/qt_defaultDpiX()*brect.width()); |
| 971 |
break; |
| 972 |
case PdmHeightMM: |
| 973 |
val = int(25.4/qt_defaultDpiY()*brect.height()); |
| 974 |
break; |
| 975 |
case PdmDpiX: |
| 976 |
case PdmPhysicalDpiX: |
| 977 |
val = qt_defaultDpiX(); |
| 978 |
break; |
| 979 |
case PdmDpiY: |
| 980 |
case PdmPhysicalDpiY: |
| 981 |
val = qt_defaultDpiY(); |
| 982 |
break; |
| 983 |
case PdmNumColors: |
| 984 |
val = 16777216; |
| 985 |
break; |
| 986 |
case PdmDepth: |
| 987 |
val = 24; |
| 988 |
break; |
| 989 |
default: |
| 990 |
val = 0; |
| 991 |
qWarning("QPicture::metric: Invalid metric command"); |
| 992 |
} |
| 993 |
return val; |
| 994 |
} |
| 995 |
|
| 996 |
/*! |
| 997 |
\fn void QPicture::detach() |
| 998 |
\internal |
| 999 |
Detaches from shared picture data and makes sure that this picture |
| 1000 |
is the only one referring to the data. |
| 1001 |
|
| 1002 |
If multiple pictures share common data, this picture makes a copy |
| 1003 |
of the data and detaches itself from the sharing mechanism. |
| 1004 |
Nothing is done if there is just a single reference. |
| 1005 |
*/ |
| 1006 |
|
| 1007 |
/*! \fn bool QPicture::isDetached() const |
| 1008 |
\internal |
| 1009 |
*/ |
| 1010 |
|
| 1011 |
/*! \internal |
| 1012 |
### Qt 5 - remove me |
| 1013 |
*/ |
| 1014 |
void QPicture::detach_helper() |
| 1015 |
{ |
| 1016 |
// QExplicitelySharedDataPointer takes care of cloning using |
| 1017 |
// QPicturePrivate's copy constructor. Do not call detach_helper() anymore |
| 1018 |
// and remove in Qt 5, please. |
| 1019 |
Q_ASSERT_X(false, "QPicture::detach_helper()", "Do not call this function"); |
| 1020 |
} |
| 1021 |
|
| 1022 |
/*! |
| 1023 |
Assigns picture \a p to this picture and returns a reference to |
| 1024 |
this picture. |
| 1025 |
*/ |
| 1026 |
QPicture& QPicture::operator=(const QPicture &p) |
| 1027 |
{ |
| 1028 |
d_ptr = p.d_ptr; |
| 1029 |
return *this; |
| 1030 |
} |
| 1031 |
|
| 1032 |
/*! |
| 1033 |
\internal |
| 1034 |
|
| 1035 |
Constructs a QPicturePrivate |
| 1036 |
*/ |
| 1037 |
QPicturePrivate::QPicturePrivate() |
| 1038 |
: in_memory_only(false) |
| 1039 |
{ |
| 1040 |
} |
| 1041 |
|
| 1042 |
/*! |
| 1043 |
\internal |
| 1044 |
|
| 1045 |
Copy-Constructs a QPicturePrivate. Needed when detaching. |
| 1046 |
*/ |
| 1047 |
QPicturePrivate::QPicturePrivate(const QPicturePrivate &other) |
| 1048 |
: trecs(other.trecs), |
| 1049 |
formatOk(other.formatOk), |
| 1050 |
formatMinor(other.formatMinor), |
| 1051 |
brect(other.brect), |
| 1052 |
override_rect(other.override_rect), |
| 1053 |
in_memory_only(false) |
| 1054 |
{ |
| 1055 |
pictb.setData(other.pictb.data(), other.pictb.size()); |
| 1056 |
if (other.pictb.isOpen()) { |
| 1057 |
pictb.open(other.pictb.openMode()); |
| 1058 |
pictb.seek(other.pictb.pos()); |
| 1059 |
} |
| 1060 |
} |
| 1061 |
|
| 1062 |
/*! |
| 1063 |
\internal |
| 1064 |
|
| 1065 |
Sets formatOk to false and resets the format version numbers to default |
| 1066 |
*/ |
| 1067 |
|
| 1068 |
void QPicturePrivate::resetFormat() |
| 1069 |
{ |
| 1070 |
formatOk = false; |
| 1071 |
formatMajor = mfhdr_maj; |
| 1072 |
formatMinor = mfhdr_min; |
| 1073 |
} |
| 1074 |
|
| 1075 |
|
| 1076 |
/*! |
| 1077 |
\internal |
| 1078 |
|
| 1079 |
Checks data integrity and format version number. Set formatOk to |
| 1080 |
true on success, to false otherwise. Returns the resulting formatOk |
| 1081 |
value. |
| 1082 |
*/ |
| 1083 |
bool QPicturePrivate::checkFormat() |
| 1084 |
{ |
| 1085 |
resetFormat(); |
| 1086 |
|
| 1087 |
// can't check anything in an empty buffer |
| 1088 |
if (pictb.size() == 0 || pictb.isOpen()) |
| 1089 |
return false; |
| 1090 |
|
| 1091 |
pictb.open(QIODevice::ReadOnly); // open buffer device |
| 1092 |
QDataStream s; |
| 1093 |
s.setDevice(&pictb); // attach data stream to buffer |
| 1094 |
|
| 1095 |
char mf_id[4]; // picture header tag |
| 1096 |
s.readRawData(mf_id, 4); // read actual tag |
| 1097 |
if (memcmp(mf_id, qt_mfhdr_tag, 4) != 0) { // wrong header id |
| 1098 |
qWarning("QPicturePaintEngine::checkFormat: Incorrect header"); |
| 1099 |
pictb.close(); |
| 1100 |
return false; |
| 1101 |
} |
| 1102 |
|
| 1103 |
int cs_start = sizeof(quint32); // pos of checksum word |
| 1104 |
int data_start = cs_start + sizeof(quint16); |
| 1105 |
quint16 cs,ccs; |
| 1106 |
QByteArray buf = pictb.buffer(); // pointer to data |
| 1107 |
|
| 1108 |
s >> cs; // read checksum |
| 1109 |
ccs = (quint16) qChecksum(buf.constData() + data_start, buf.size() - data_start); |
| 1110 |
if (ccs != cs) { |
| 1111 |
qWarning("QPicturePaintEngine::checkFormat: Invalid checksum %x, %x expected", |
| 1112 |
ccs, cs); |
| 1113 |
pictb.close(); |
| 1114 |
return false; |
| 1115 |
} |
| 1116 |
|
| 1117 |
quint16 major, minor; |
| 1118 |
s >> major >> minor; // read version number |
| 1119 |
if (major > mfhdr_maj) { // new, incompatible version |
| 1120 |
qWarning("QPicturePaintEngine::checkFormat: Incompatible version %d.%d", |
| 1121 |
major, minor); |
| 1122 |
pictb.close(); |
| 1123 |
return false; |
| 1124 |
} |
| 1125 |
s.setVersion(major != 4 ? major : 3); |
| 1126 |
|
| 1127 |
quint8 c, clen; |
| 1128 |
s >> c >> clen; |
| 1129 |
if (c == QPicturePrivate::PdcBegin) { |
| 1130 |
if (!(major >= 1 && major <= 3)) { |
| 1131 |
qint32 l, t, w, h; |
| 1132 |
s >> l >> t >> w >> h; |
| 1133 |
brect = QRect(l, t, w, h); |
| 1134 |
} |
| 1135 |
} else { |
| 1136 |
qWarning("QPicturePaintEngine::checkFormat: Format error"); |
| 1137 |
pictb.close(); |
| 1138 |
return false; |
| 1139 |
} |
| 1140 |
pictb.close(); |
| 1141 |
|
| 1142 |
formatOk = true; // picture seems to be ok |
| 1143 |
formatMajor = major; |
| 1144 |
formatMinor = minor; |
| 1145 |
return true; |
| 1146 |
} |
| 1147 |
|
| 1148 |
/*! \internal */ |
| 1149 |
QPaintEngine *QPicture::paintEngine() const |
| 1150 |
{ |
| 1151 |
if (!d_func()->paintEngine) |
| 1152 |
const_cast<QPicture*>(this)->d_func()->paintEngine.reset(new QPicturePaintEngine); |
| 1153 |
return d_func()->paintEngine.data(); |
| 1154 |
} |
| 1155 |
|
| 1156 |
/***************************************************************************** |
| 1157 |
QPicture stream functions |
| 1158 |
*****************************************************************************/ |
| 1159 |
|
| 1160 |
#ifndef QT_NO_DATASTREAM |
| 1161 |
/*! |
| 1162 |
\relates QPicture |
| 1163 |
|
| 1164 |
Writes picture \a r to the stream \a s and returns a reference to |
| 1165 |
the stream. |
| 1166 |
*/ |
| 1167 |
|
| 1168 |
QDataStream &operator<<(QDataStream &s, const QPicture &r) |
| 1169 |
{ |
| 1170 |
quint32 size = r.d_func()->pictb.buffer().size(); |
| 1171 |
s << size; |
| 1172 |
// null picture ? |
| 1173 |
if (size == 0) |
| 1174 |
return s; |
| 1175 |
// just write the whole buffer to the stream |
| 1176 |
s.writeRawData (r.d_func()->pictb.buffer(), r.d_func()->pictb.buffer().size()); |
| 1177 |
return s; |
| 1178 |
} |
| 1179 |
|
| 1180 |
/*! |
| 1181 |
\relates QPicture |
| 1182 |
|
| 1183 |
Reads a picture from the stream \a s into picture \a r and returns |
| 1184 |
a reference to the stream. |
| 1185 |
*/ |
| 1186 |
|
| 1187 |
QDataStream &operator>>(QDataStream &s, QPicture &r) |
| 1188 |
{ |
| 1189 |
QDataStream sr; |
| 1190 |
|
| 1191 |
// "init"; this code is similar to the beginning of QPicture::cmd() |
| 1192 |
sr.setDevice(&r.d_func()->pictb); |
| 1193 |
sr.setVersion(r.d_func()->formatMajor); |
| 1194 |
quint32 len; |
| 1195 |
s >> len; |
| 1196 |
QByteArray data; |
| 1197 |
if (len > 0) { |
| 1198 |
data.resize(len); |
| 1199 |
s.readRawData(data.data(), len); |
| 1200 |
} |
| 1201 |
|
| 1202 |
r.d_func()->pictb.setData(data); |
| 1203 |
r.d_func()->resetFormat(); |
| 1204 |
return s; |
| 1205 |
} |
| 1206 |
#endif // QT_NO_DATASTREAM |
| 1207 |
|
| 1208 |
|
| 1209 |
#ifndef QT_NO_PICTUREIO |
| 1210 |
|
| 1211 |
QT_BEGIN_INCLUDE_NAMESPACE |
| 1212 |
#include "qregexp.h" |
| 1213 |
#include "qapplication.h" |
| 1214 |
#include "qpictureformatplugin.h" |
| 1215 |
QT_END_INCLUDE_NAMESPACE |
| 1216 |
|
| 1217 |
/*! |
| 1218 |
\obsolete |
| 1219 |
|
| 1220 |
Returns a string that specifies the picture format of the file \a |
| 1221 |
fileName, or 0 if the file cannot be read or if the format is not |
| 1222 |
recognized. |
| 1223 |
|
| 1224 |
\sa load() save() |
| 1225 |
*/ |
| 1226 |
|
| 1227 |
const char* QPicture::pictureFormat(const QString &fileName) |
| 1228 |
{ |
| 1229 |
return QPictureIO::pictureFormat(fileName); |
| 1230 |
} |
| 1231 |
|
| 1232 |
/*! |
| 1233 |
\obsolete |
| 1234 |
|
| 1235 |
Returns a list of picture formats that are supported for picture |
| 1236 |
input. |
| 1237 |
|
| 1238 |
\sa outputFormats() inputFormatList() QPictureIO |
| 1239 |
*/ |
| 1240 |
QList<QByteArray> QPicture::inputFormats() |
| 1241 |
{ |
| 1242 |
return QPictureIO::inputFormats(); |
| 1243 |
} |
| 1244 |
|
| 1245 |
static QStringList qToStringList(const QList<QByteArray> arr) |
| 1246 |
{ |
| 1247 |
QStringList list; |
| 1248 |
for (int i = 0; i < arr.count(); ++i) |
| 1249 |
list.append(QString::fromLatin1(arr.at(i))); |
| 1250 |
return list; |
| 1251 |
} |
| 1252 |
|
| 1253 |
/*! |
| 1254 |
\obsolete |
| 1255 |
|
| 1256 |
Returns a list of picture formats that are supported for picture |
| 1257 |
input. |
| 1258 |
|
| 1259 |
Note that if you want to iterate over the list, you should iterate |
| 1260 |
over a copy, e.g. |
| 1261 |
\snippet doc/src/snippets/picture/picture.cpp 2 |
| 1262 |
|
| 1263 |
\sa outputFormatList() inputFormats() QPictureIO |
| 1264 |
*/ |
| 1265 |
QStringList QPicture::inputFormatList() |
| 1266 |
{ |
| 1267 |
return qToStringList(QPictureIO::inputFormats()); |
| 1268 |
} |
| 1269 |
|
| 1270 |
|
| 1271 |
/*! |
| 1272 |
\obsolete |
| 1273 |
|
| 1274 |
Returns a list of picture formats that are supported for picture |
| 1275 |
output. |
| 1276 |
|
| 1277 |
Note that if you want to iterate over the list, you should iterate |
| 1278 |
over a copy, e.g. |
| 1279 |
\snippet doc/src/snippets/picture/picture.cpp 3 |
| 1280 |
|
| 1281 |
\sa inputFormatList() outputFormats() QPictureIO |
| 1282 |
*/ |
| 1283 |
QStringList QPicture::outputFormatList() |
| 1284 |
{ |
| 1285 |
return qToStringList(QPictureIO::outputFormats()); |
| 1286 |
} |
| 1287 |
|
| 1288 |
/*! |
| 1289 |
\obsolete |
| 1290 |
|
| 1291 |
Returns a list of picture formats that are supported for picture |
| 1292 |
output. |
| 1293 |
|
| 1294 |
\sa inputFormats() outputFormatList() QPictureIO |
| 1295 |
*/ |
| 1296 |
QList<QByteArray> QPicture::outputFormats() |
| 1297 |
{ |
| 1298 |
return QPictureIO::outputFormats(); |
| 1299 |
} |
| 1300 |
|
| 1301 |
/***************************************************************************** |
| 1302 |
QPictureIO member functions |
| 1303 |
*****************************************************************************/ |
| 1304 |
|
| 1305 |
/*! |
| 1306 |
\obsolete |
| 1307 |
|
| 1308 |
\class QPictureIO |
| 1309 |
|
| 1310 |
\brief The QPictureIO class contains parameters for loading and |
| 1311 |
saving pictures. |
| 1312 |
|
| 1313 |
\ingroup painting |
| 1314 |
\ingroup io |
| 1315 |
|
| 1316 |
QPictureIO contains a QIODevice object that is used for picture data |
| 1317 |
I/O. The programmer can install new picture file formats in addition |
| 1318 |
to those that Qt provides. |
| 1319 |
|
| 1320 |
You don't normally need to use this class; QPicture::load(), |
| 1321 |
QPicture::save(). |
| 1322 |
|
| 1323 |
\sa QPicture QPixmap QFile |
| 1324 |
*/ |
| 1325 |
|
| 1326 |
struct QPictureIOData |
| 1327 |
{ |
| 1328 |
QPicture pi; // picture |
| 1329 |
int iostat; // IO status |
| 1330 |
QByteArray frmt; // picture format |
| 1331 |
QIODevice *iodev; // IO device |
| 1332 |
QString fname; // file name |
| 1333 |
QString descr; // picture description |
| 1334 |
const char *parameters; |
| 1335 |
int quality; |
| 1336 |
float gamma; |
| 1337 |
}; |
| 1338 |
|
| 1339 |
/*! |
| 1340 |
Constructs a QPictureIO object with all parameters set to zero. |
| 1341 |
*/ |
| 1342 |
|
| 1343 |
QPictureIO::QPictureIO() |
| 1344 |
{ |
| 1345 |
init(); |
| 1346 |
} |
| 1347 |
|
| 1348 |
/*! |
| 1349 |
Constructs a QPictureIO object with the I/O device \a ioDevice and a |
| 1350 |
\a format tag. |
| 1351 |
*/ |
| 1352 |
|
| 1353 |
QPictureIO::QPictureIO(QIODevice *ioDevice, const char *format) |
| 1354 |
{ |
| 1355 |
init(); |
| 1356 |
d->iodev = ioDevice; |
| 1357 |
d->frmt = format; |
| 1358 |
} |
| 1359 |
|
| 1360 |
/*! |
| 1361 |
Constructs a QPictureIO object with the file name \a fileName and a |
| 1362 |
\a format tag. |
| 1363 |
*/ |
| 1364 |
|
| 1365 |
QPictureIO::QPictureIO(const QString &fileName, const char* format) |
| 1366 |
{ |
| 1367 |
init(); |
| 1368 |
d->frmt = format; |
| 1369 |
d->fname = fileName; |
| 1370 |
} |
| 1371 |
|
| 1372 |
/*! |
| 1373 |
Contains initialization common to all QPictureIO constructors. |
| 1374 |
*/ |
| 1375 |
|
| 1376 |
void QPictureIO::init() |
| 1377 |
{ |
| 1378 |
d = new QPictureIOData(); |
| 1379 |
d->parameters = 0; |
| 1380 |
d->quality = -1; // default quality of the current format |
| 1381 |
d->gamma=0.0f; |
| 1382 |
d->iostat = 0; |
| 1383 |
d->iodev = 0; |
| 1384 |
} |
| 1385 |
|
| 1386 |
/*! |
| 1387 |
Destroys the object and all related data. |
| 1388 |
*/ |
| 1389 |
|
| 1390 |
QPictureIO::~QPictureIO() |
| 1391 |
{ |
| 1392 |
if (d->parameters) |
| 1393 |
delete [] (char*)d->parameters; |
| 1394 |
delete d; |
| 1395 |
} |
| 1396 |
|
| 1397 |
|
| 1398 |
/***************************************************************************** |
| 1399 |
QPictureIO picture handler functions |
| 1400 |
*****************************************************************************/ |
| 1401 |
|
| 1402 |
class QPictureHandler |
| 1403 |
{ |
| 1404 |
public: |
| 1405 |
QPictureHandler(const char *f, const char *h, const QByteArray& fl, |
| 1406 |
picture_io_handler r, picture_io_handler w); |
| 1407 |
QByteArray format; // picture format |
| 1408 |
QRegExp header; // picture header pattern |
| 1409 |
enum TMode { Untranslated=0, TranslateIn, TranslateInOut } text_mode; |
| 1410 |
picture_io_handler read_picture; // picture read function |
| 1411 |
picture_io_handler write_picture; // picture write function |
| 1412 |
bool obsolete; // support not "published" |
| 1413 |
}; |
| 1414 |
|
| 1415 |
QPictureHandler::QPictureHandler(const char *f, const char *h, const QByteArray& fl, |
| 1416 |
picture_io_handler r, picture_io_handler w) |
| 1417 |
: format(f), header(QString::fromLatin1(h)) |
| 1418 |
{ |
| 1419 |
text_mode = Untranslated; |
| 1420 |
if (fl.contains('t')) |
| 1421 |
text_mode = TranslateIn; |
| 1422 |
else if (fl.contains('T')) |
| 1423 |
text_mode = TranslateInOut; |
| 1424 |
obsolete = fl.contains('O'); |
| 1425 |
read_picture = r; |
| 1426 |
write_picture = w; |
| 1427 |
} |
| 1428 |
|
| 1429 |
typedef QList<QPictureHandler *> QPHList; |
| 1430 |
Q_GLOBAL_STATIC(QPHList, pictureHandlers) |
| 1431 |
|
| 1432 |
#ifndef QT_NO_LIBRARY |
| 1433 |
Q_GLOBAL_STATIC(QMutex, mutex) |
| 1434 |
Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, factoryLoader, |
| 1435 |
(QPictureFormatInterface_iid, |
| 1436 |
QLatin1String("/pictureformats"))) |
| 1437 |
#endif |
| 1438 |
void qt_init_picture_plugins() |
| 1439 |
{ |
| 1440 |
#ifndef QT_NO_LIBRARY |
| 1441 |
QMutexLocker locker(mutex()); |
| 1442 |
QFactoryLoader *loader = factoryLoader(); |
| 1443 |
QStringList keys = loader->keys(); |
| 1444 |
for (int i = 0; i < keys.count(); ++i) |
| 1445 |
if (QPictureFormatInterface *format = qobject_cast<QPictureFormatInterface*>(loader->instance(keys.at(i)))) |
| 1446 |
format->installIOHandler(keys.at(i)); |
| 1447 |
#endif |
| 1448 |
} |
| 1449 |
|
| 1450 |
static void cleanup() |
| 1451 |
{ |
| 1452 |
// make sure that picture handlers are delete before plugin manager |
| 1453 |
if (QPHList *list = pictureHandlers()) { |
| 1454 |
qDeleteAll(*list); |
| 1455 |
list->clear(); |
| 1456 |
} |
| 1457 |
} |
| 1458 |
|
| 1459 |
void qt_init_picture_handlers() // initialize picture handlers |
| 1460 |
{ |
| 1461 |
static QBasicAtomicInt done = Q_BASIC_ATOMIC_INITIALIZER(0); |
| 1462 |
if (done.testAndSetRelaxed(0, 1)) { |
| 1463 |
qAddPostRoutine(cleanup); |
| 1464 |
} |
| 1465 |
} |
| 1466 |
|
| 1467 |
static QPictureHandler *get_picture_handler(const char *format) |
| 1468 |
{ // get pointer to handler |
| 1469 |
qt_init_picture_handlers(); |
| 1470 |
qt_init_picture_plugins(); |
| 1471 |
if (QPHList *list = pictureHandlers()) { |
| 1472 |
for (int i = 0; i < list->size(); ++i) { |
| 1473 |
if (list->at(i)->format == format) |
| 1474 |
return list->at(i); |
| 1475 |
} |
| 1476 |
} |
| 1477 |
return 0; // no such handler |
| 1478 |
} |
| 1479 |
|
| 1480 |
|
| 1481 |
/*! |
| 1482 |
Defines a picture I/O handler for the picture format called \a |
| 1483 |
format, which is recognized using the regular |
| 1484 |
expression defined in \a header, read using \a readPicture and |
| 1485 |
written using \a writePicture. |
| 1486 |
|
| 1487 |
\a flags is a string of single-character flags for this format. |
| 1488 |
The only flag defined currently is T (upper case), so the only |
| 1489 |
legal value for \a flags are "T" and the empty string. The "T" |
| 1490 |
flag means that the picture file is a text file, and Qt should treat |
| 1491 |
all newline conventions as equivalent. (XPM files and some PPM |
| 1492 |
files are text files for example.) |
| 1493 |
|
| 1494 |
\a format is used to select a handler to write a QPicture; \a header |
| 1495 |
is used to select a handler to read an picture file. |
| 1496 |
|
| 1497 |
If \a readPicture is a null pointer, the QPictureIO will not be able |
| 1498 |
to read pictures in \a format. If \a writePicture is a null pointer, |
| 1499 |
the QPictureIO will not be able to write pictures in \a format. If |
| 1500 |
both are null, the QPictureIO object is valid but useless. |
| 1501 |
|
| 1502 |
Example: |
| 1503 |
\snippet doc/src/snippets/picture/picture.cpp 6 |
| 1504 |
\codeline |
| 1505 |
\snippet doc/src/snippets/picture/picture.cpp 7 |
| 1506 |
\codeline |
| 1507 |
\snippet doc/src/snippets/picture/picture.cpp 8 |
| 1508 |
|
| 1509 |
Before the regular expression test, all the 0 bytes in the file header are |
| 1510 |
converted to 1 bytes. This is done because when Qt was ASCII-based, QRegExp |
| 1511 |
could not handle 0 bytes in strings. |
| 1512 |
|
| 1513 |
The regexp is only applied on the first 14 bytes of the file. |
| 1514 |
|
| 1515 |
(Note that if one handlerIO supports writing a format and another |
| 1516 |
supports reading it, Qt supports both reading and writing. If two |
| 1517 |
handlers support the same operation, Qt chooses one arbitrarily.) |
| 1518 |
*/ |
| 1519 |
|
| 1520 |
void QPictureIO::defineIOHandler(const char *format, |
| 1521 |
const char *header, |
| 1522 |
const char *flags, |
| 1523 |
picture_io_handler readPicture, |
| 1524 |
picture_io_handler writePicture) |
| 1525 |
{ |
| 1526 |
qt_init_picture_handlers(); |
| 1527 |
if (QPHList *list = pictureHandlers()) { |
| 1528 |
QPictureHandler *p; |
| 1529 |
p = new QPictureHandler(format, header, QByteArray(flags), readPicture, writePicture); |
| 1530 |
list->prepend(p); |
| 1531 |
} |
| 1532 |
} |
| 1533 |
|
| 1534 |
|
| 1535 |
/***************************************************************************** |
| 1536 |
QPictureIO normal member functions |
| 1537 |
*****************************************************************************/ |
| 1538 |
|
| 1539 |
/*! |
| 1540 |
Returns the picture currently set. |
| 1541 |
|
| 1542 |
\sa setPicture() |
| 1543 |
*/ |
| 1544 |
const QPicture &QPictureIO::picture() const { return d->pi; } |
| 1545 |
|
| 1546 |
/*! |
| 1547 |
Returns the picture's IO status. A non-zero value indicates an |
| 1548 |
error, whereas 0 means that the IO operation was successful. |
| 1549 |
|
| 1550 |
\sa setStatus() |
| 1551 |
*/ |
| 1552 |
int QPictureIO::status() const { return d->iostat; } |
| 1553 |
|
| 1554 |
/*! |
| 1555 |
Returns the picture format string or 0 if no format has been |
| 1556 |
explicitly set. |
| 1557 |
*/ |
| 1558 |
const char *QPictureIO::format() const { return d->frmt; } |
| 1559 |
|
| 1560 |
/*! |
| 1561 |
Returns the IO device currently set. |
| 1562 |
|
| 1563 |
\sa setIODevice() |
| 1564 |
*/ |
| 1565 |
QIODevice *QPictureIO::ioDevice() const { return d->iodev; } |
| 1566 |
|
| 1567 |
/*! |
| 1568 |
Returns the file name currently set. |
| 1569 |
|
| 1570 |
\sa setFileName() |
| 1571 |
*/ |
| 1572 |
QString QPictureIO::fileName() const { return d->fname; } |
| 1573 |
|
| 1574 |
|
| 1575 |
/*! |
| 1576 |
Returns the picture description string. |
| 1577 |
|
| 1578 |
\sa setDescription() |
| 1579 |
*/ |
| 1580 |
QString QPictureIO::description() const { return d->descr; } |
| 1581 |
|
| 1582 |
/*! |
| 1583 |
Sets the picture to \a picture. |
| 1584 |
|
| 1585 |
\sa picture() |
| 1586 |
*/ |
| 1587 |
void QPictureIO::setPicture(const QPicture &picture) |
| 1588 |
{ |
| 1589 |
d->pi = picture; |
| 1590 |
} |
| 1591 |
|
| 1592 |
/*! |
| 1593 |
Sets the picture IO status to \a status. A non-zero value indicates |
| 1594 |
an error, whereas 0 means that the IO operation was successful. |
| 1595 |
|
| 1596 |
\sa status() |
| 1597 |
*/ |
| 1598 |
void QPictureIO::setStatus(int status) |
| 1599 |
{ |
| 1600 |
d->iostat = status; |
| 1601 |
} |
| 1602 |
|
| 1603 |
/*! |
| 1604 |
Sets the picture format to \a format for the picture to be read or |
| 1605 |
written. |
| 1606 |
|
| 1607 |
It is necessary to specify a format before writing an picture, but |
| 1608 |
it is not necessary to specify a format before reading an picture. |
| 1609 |
|
| 1610 |
If no format has been set, Qt guesses the picture format before |
| 1611 |
reading it. If a format is set the picture will only be read if it |
| 1612 |
has that format. |
| 1613 |
|
| 1614 |
\sa read() write() format() |
| 1615 |
*/ |
| 1616 |
void QPictureIO::setFormat(const char *format) |
| 1617 |
{ |
| 1618 |
d->frmt = format; |
| 1619 |
} |
| 1620 |
|
| 1621 |
/*! |
| 1622 |
Sets the IO device to be used for reading or writing an picture. |
| 1623 |
|
| 1624 |
Setting the IO device allows pictures to be read/written to any |
| 1625 |
block-oriented QIODevice. |
| 1626 |
|
| 1627 |
If \a ioDevice is not null, this IO device will override file name |
| 1628 |
settings. |
| 1629 |
|
| 1630 |
\sa setFileName() |
| 1631 |
*/ |
| 1632 |
void QPictureIO::setIODevice(QIODevice *ioDevice) |
| 1633 |
{ |
| 1634 |
d->iodev = ioDevice; |
| 1635 |
} |
| 1636 |
|
| 1637 |
/*! |
| 1638 |
Sets the name of the file to read or write an picture from to \a |
| 1639 |
fileName. |
| 1640 |
|
| 1641 |
\sa setIODevice() |
| 1642 |
*/ |
| 1643 |
void QPictureIO::setFileName(const QString &fileName) |
| 1644 |
{ |
| 1645 |
d->fname = fileName; |
| 1646 |
} |
| 1647 |
|
| 1648 |
/*! |
| 1649 |
Returns the quality of the written picture, related to the |
| 1650 |
compression ratio. |
| 1651 |
|
| 1652 |
\sa setQuality() QPicture::save() |
| 1653 |
*/ |
| 1654 |
int QPictureIO::quality() const |
| 1655 |
{ |
| 1656 |
return d->quality; |
| 1657 |
} |
| 1658 |
|
| 1659 |
/*! |
| 1660 |
Sets the quality of the written picture to \a q, related to the |
| 1661 |
compression ratio. |
| 1662 |
|
| 1663 |
\a q must be in the range -1..100. Specify 0 to obtain small |
| 1664 |
compressed files, 100 for large uncompressed files. (-1 signifies |
| 1665 |
the default compression.) |
| 1666 |
|
| 1667 |
\sa quality() QPicture::save() |
| 1668 |
*/ |
| 1669 |
|
| 1670 |
void QPictureIO::setQuality(int q) |
| 1671 |
{ |
| 1672 |
d->quality = q; |
| 1673 |
} |
| 1674 |
|
| 1675 |
/*! |
| 1676 |
Returns the picture's parameters string. |
| 1677 |
|
| 1678 |
\sa setParameters() |
| 1679 |
*/ |
| 1680 |
|
| 1681 |
const char *QPictureIO::parameters() const |
| 1682 |
{ |
| 1683 |
return d->parameters; |
| 1684 |
} |
| 1685 |
|
| 1686 |
/*! |
| 1687 |
Sets the picture's parameter string to \a parameters. This is for |
| 1688 |
picture handlers that require special parameters. |
| 1689 |
|
| 1690 |
Although the current picture formats supported by Qt ignore the |
| 1691 |
parameters string, it may be used in future extensions or by |
| 1692 |
contributions (for example, JPEG). |
| 1693 |
|
| 1694 |
\sa parameters() |
| 1695 |
*/ |
| 1696 |
|
| 1697 |
void QPictureIO::setParameters(const char *parameters) |
| 1698 |
{ |
| 1699 |
if (d->parameters) |
| 1700 |
delete [] (char*)d->parameters; |
| 1701 |
d->parameters = qstrdup(parameters); |
| 1702 |
} |
| 1703 |
|
| 1704 |
/*! |
| 1705 |
Sets the gamma value at which the picture will be viewed to \a |
| 1706 |
gamma. If the picture format stores a gamma value for which the |
| 1707 |
picture is intended to be used, then this setting will be used to |
| 1708 |
modify the picture. Setting to 0.0 will disable gamma correction |
| 1709 |
(i.e. any specification in the file will be ignored). |
| 1710 |
|
| 1711 |
The default value is 0.0. |
| 1712 |
|
| 1713 |
\sa gamma() |
| 1714 |
*/ |
| 1715 |
void QPictureIO::setGamma(float gamma) |
| 1716 |
{ |
| 1717 |
d->gamma=gamma; |
| 1718 |
} |
| 1719 |
|
| 1720 |
/*! |
| 1721 |
Returns the gamma value at which the picture will be viewed. |
| 1722 |
|
| 1723 |
\sa setGamma() |
| 1724 |
*/ |
| 1725 |
float QPictureIO::gamma() const |
| 1726 |
{ |
| 1727 |
return d->gamma; |
| 1728 |
} |
| 1729 |
|
| 1730 |
/*! |
| 1731 |
Sets the picture description string for picture handlers that support |
| 1732 |
picture descriptions to \a description. |
| 1733 |
|
| 1734 |
Currently, no picture format supported by Qt uses the description |
| 1735 |
string. |
| 1736 |
*/ |
| 1737 |
|
| 1738 |
void QPictureIO::setDescription(const QString &description) |
| 1739 |
{ |
| 1740 |
d->descr = description; |
| 1741 |
} |
| 1742 |
|
| 1743 |
|
| 1744 |
/*! |
| 1745 |
Returns a string that specifies the picture format of the file \a |
| 1746 |
fileName, or null if the file cannot be read or if the format is |
| 1747 |
not recognized. |
| 1748 |
*/ |
| 1749 |
|
| 1750 |
QByteArray QPictureIO::pictureFormat(const QString &fileName) |
| 1751 |
{ |
| 1752 |
QFile file(fileName); |
| 1753 |
QByteArray format; |
| 1754 |
if (!file.open(QIODevice::ReadOnly)) |
| 1755 |
return format; |
| 1756 |
format = pictureFormat(&file); |
| 1757 |
file.close(); |
| 1758 |
return format; |
| 1759 |
} |
| 1760 |
|
| 1761 |
/*! |
| 1762 |
\overload |
| 1763 |
|
| 1764 |
Returns a string that specifies the picture format of the picture read |
| 1765 |
from IO device \a d, or 0 if the device cannot be read or if the |
| 1766 |
format is not recognized. |
| 1767 |
|
| 1768 |
Make sure that \a d is at the right position in the device (for |
| 1769 |
example, at the beginning of the file). |
| 1770 |
|
| 1771 |
\sa QIODevice::at() |
| 1772 |
*/ |
| 1773 |
|
| 1774 |
QByteArray QPictureIO::pictureFormat(QIODevice *d) |
| 1775 |
{ |
| 1776 |
// if you change this change the documentation for defineIOHandler() |
| 1777 |
const int buflen = 14; |
| 1778 |
|
| 1779 |
char buf[buflen]; |
| 1780 |
char buf2[buflen]; |
| 1781 |
qt_init_picture_handlers(); |
| 1782 |
qt_init_picture_plugins(); |
| 1783 |
int pos = d->pos(); // save position |
| 1784 |
int rdlen = d->read(buf, buflen); // read a few bytes |
| 1785 |
|
| 1786 |
QByteArray format; |
| 1787 |
if (rdlen != buflen) |
| 1788 |
return format; |
| 1789 |
|
| 1790 |
memcpy(buf2, buf, buflen); |
| 1791 |
|
| 1792 |
for (int n = 0; n < rdlen; n++) |
| 1793 |
if (buf[n] == '\0') |
| 1794 |
buf[n] = '\001'; |
| 1795 |
if (rdlen > 0) { |
| 1796 |
buf[rdlen - 1] = '\0'; |
| 1797 |
QString bufStr = QString::fromLatin1(buf); |
| 1798 |
if (QPHList *list = pictureHandlers()) { |
| 1799 |
for (int i = 0; i < list->size(); ++i) { |
| 1800 |
if (list->at(i)->header.indexIn(bufStr) != -1) { // try match with headers |
| 1801 |
format = list->at(i)->format; |
| 1802 |
break; |
| 1803 |
} |
| 1804 |
} |
| 1805 |
} |
| 1806 |
} |
| 1807 |
d->seek(pos); // restore position |
| 1808 |
return format; |
| 1809 |
} |
| 1810 |
|
| 1811 |
/*! |
| 1812 |
Returns a sorted list of picture formats that are supported for |
| 1813 |
picture input. |
| 1814 |
*/ |
| 1815 |
QList<QByteArray> QPictureIO::inputFormats() |
| 1816 |
{ |
| 1817 |
QList<QByteArray> result; |
| 1818 |
|
| 1819 |
qt_init_picture_handlers(); |
| 1820 |
qt_init_picture_plugins(); |
| 1821 |
|
| 1822 |
if (QPHList *list = pictureHandlers()) { |
| 1823 |
for (int i = 0; i < list->size(); ++i) { |
| 1824 |
QPictureHandler *p = list->at(i); |
| 1825 |
if (p->read_picture && !p->obsolete && !result.contains(p->format)) |
| 1826 |
result.append(p->format); |
| 1827 |
} |
| 1828 |
} |
| 1829 |
qSort(result); |
| 1830 |
|
| 1831 |
return result; |
| 1832 |
} |
| 1833 |
|
| 1834 |
/*! |
| 1835 |
Returns a sorted list of picture formats that are supported for |
| 1836 |
picture output. |
| 1837 |
*/ |
| 1838 |
QList<QByteArray> QPictureIO::outputFormats() |
| 1839 |
{ |
| 1840 |
qt_init_picture_handlers(); |
| 1841 |
qt_init_picture_plugins(); |
| 1842 |
|
| 1843 |
QList<QByteArray> result; |
| 1844 |
if (QPHList *list = pictureHandlers()) { |
| 1845 |
for (int i = 0; i < list->size(); ++i) { |
| 1846 |
QPictureHandler *p = list->at(i); |
| 1847 |
if (p->write_picture && !p->obsolete && !result.contains(p->format)) |
| 1848 |
result.append(p->format); |
| 1849 |
} |
| 1850 |
} |
| 1851 |
return result; |
| 1852 |
} |
| 1853 |
|
| 1854 |
|
| 1855 |
|
| 1856 |
/*! |
| 1857 |
Reads an picture into memory and returns true if the picture was |
| 1858 |
successfully read; otherwise returns false. |
| 1859 |
|
| 1860 |
Before reading an picture you must set an IO device or a file name. |
| 1861 |
If both an IO device and a file name have been set, the IO device |
| 1862 |
will be used. |
| 1863 |
|
| 1864 |
Setting the picture file format string is optional. |
| 1865 |
|
| 1866 |
Note that this function does \e not set the \link format() |
| 1867 |
format\endlink used to read the picture. If you need that |
| 1868 |
information, use the pictureFormat() static functions. |
| 1869 |
|
| 1870 |
Example: |
| 1871 |
|
| 1872 |
\snippet doc/src/snippets/picture/picture.cpp 4 |
| 1873 |
|
| 1874 |
\sa setIODevice() setFileName() setFormat() write() QPixmap::load() |
| 1875 |
*/ |
| 1876 |
bool QPictureIO::read() |
| 1877 |
{ |
| 1878 |
QFile file; |
| 1879 |
const char *picture_format; |
| 1880 |
QPictureHandler *h; |
| 1881 |
|
| 1882 |
if (d->iodev) { // read from io device |
| 1883 |
// ok, already open |
| 1884 |
} else if (!d->fname.isEmpty()) { // read from file |
| 1885 |
file.setFileName(d->fname); |
| 1886 |
if (!file.open(QIODevice::ReadOnly)) |
| 1887 |
return false; // cannot open file |
| 1888 |
d->iodev = &file; |
| 1889 |
} else { // no file name or io device |
| 1890 |
return false; |
| 1891 |
} |
| 1892 |
if (d->frmt.isEmpty()) { |
| 1893 |
// Try to guess format |
| 1894 |
picture_format = pictureFormat(d->iodev); // get picture format |
| 1895 |
if (!picture_format) { |
| 1896 |
if (file.isOpen()) { // unknown format |
| 1897 |
file.close(); |
| 1898 |
d->iodev = 0; |
| 1899 |
} |
| 1900 |
return false; |
| 1901 |
} |
| 1902 |
} else { |
| 1903 |
picture_format = d->frmt; |
| 1904 |
} |
| 1905 |
|
| 1906 |
h = get_picture_handler(picture_format); |
| 1907 |
if (file.isOpen()) { |
| 1908 |
#if !defined(Q_OS_UNIX) |
| 1909 |
if (h && h->text_mode) { // reopen in translated mode |
| 1910 |
file.close(); |
| 1911 |
file.open(QIODevice::ReadOnly | QIODevice::Text); |
| 1912 |
} |
| 1913 |
else |
| 1914 |
#endif |
| 1915 |
file.seek(0); // position to start |
| 1916 |
} |
| 1917 |
d->iostat = 1; // assume error |
| 1918 |
|
| 1919 |
if (h && h->read_picture) |
| 1920 |
(*h->read_picture)(this); |
| 1921 |
|
| 1922 |
if (file.isOpen()) { // picture was read using file |
| 1923 |
file.close(); |
| 1924 |
d->iodev = 0; |
| 1925 |
} |
| 1926 |
return d->iostat == 0; // picture successfully read? |
| 1927 |
} |
| 1928 |
|
| 1929 |
|
| 1930 |
/*! |
| 1931 |
Writes an picture to an IO device and returns true if the picture was |
| 1932 |
successfully written; otherwise returns false. |
| 1933 |
|
| 1934 |
Before writing an picture you must set an IO device or a file name. |
| 1935 |
If both an IO device and a file name have been set, the IO device |
| 1936 |
will be used. |
| 1937 |
|
| 1938 |
The picture will be written using the specified picture format. |
| 1939 |
|
| 1940 |
Example: |
| 1941 |
\snippet doc/src/snippets/picture/picture.cpp 5 |
| 1942 |
|
| 1943 |
\sa setIODevice() setFileName() setFormat() read() QPixmap::save() |
| 1944 |
*/ |
| 1945 |
bool QPictureIO::write() |
| 1946 |
{ |
| 1947 |
if (d->frmt.isEmpty()) |
| 1948 |
return false; |
| 1949 |
QPictureHandler *h = get_picture_handler(d->frmt); |
| 1950 |
if (!h || !h->write_picture) { |
| 1951 |
qWarning("QPictureIO::write: No such picture format handler: %s", |
| 1952 |
format()); |
| 1953 |
return false; |
| 1954 |
} |
| 1955 |
QFile file; |
| 1956 |
if (!d->iodev && !d->fname.isEmpty()) { |
| 1957 |
file.setFileName(d->fname); |
| 1958 |
bool translate = h->text_mode==QPictureHandler::TranslateInOut; |
| 1959 |
QIODevice::OpenMode fmode = translate ? QIODevice::WriteOnly | QIODevice::Text : QIODevice::OpenMode(QIODevice::WriteOnly); |
| 1960 |
if (!file.open(fmode)) // couldn't create file |
| 1961 |
return false; |
| 1962 |
d->iodev = &file; |
| 1963 |
} |
| 1964 |
d->iostat = 1; |
| 1965 |
(*h->write_picture)(this); |
| 1966 |
if (file.isOpen()) { // picture was written using file |
| 1967 |
file.close(); |
| 1968 |
d->iodev = 0; |
| 1969 |
} |
| 1970 |
return d->iostat == 0; // picture successfully written? |
| 1971 |
} |
| 1972 |
#endif //QT_NO_PICTUREIO |
| 1973 |
|
| 1974 |
/*! |
| 1975 |
\fn QPicture QPicture::copy() const |
| 1976 |
|
| 1977 |
Use simple assignment instead. |
| 1978 |
*/ |
| 1979 |
|
| 1980 |
QT_END_NAMESPACE |
| 1981 |
|
| 1982 |
#endif // QT_NO_PICTURE |
| 1983 |
|
| 1984 |
/*! |
| 1985 |
\typedef QPicture::DataPtr |
| 1986 |
\internal |
| 1987 |
*/ |
| 1988 |
|
| 1989 |
/*! |
| 1990 |
\fn DataPtr &QPicture::data_ptr() |
| 1991 |
\internal |
| 1992 |
*/ |