src/gui/painting/qpaintbuffer.cpp
changeset 0 1918ee327afb
child 3 41300fa6a67c
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 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 #include <qmath.h>
       
    42 #include <private/qpainterpath_p.h>
       
    43 #include <private/qpaintbuffer_p.h>
       
    44 //#include <private/qtextengine_p.h>
       
    45 #include <private/qfontengine_p.h>
       
    46 #include <private/qemulationpaintengine_p.h>
       
    47 #include <private/qimage_p.h>
       
    48 
       
    49 #include <QDebug>
       
    50 
       
    51 //#define QPAINTBUFFER_DEBUG_DRAW
       
    52 
       
    53 QT_BEGIN_NAMESPACE
       
    54 
       
    55 extern int qt_defaultDpiX();
       
    56 extern int qt_defaultDpiY();
       
    57 extern void qt_format_text(const QFont &font,
       
    58                            const QRectF &_r, int tf, const QTextOption *option, const QString& str, QRectF *brect,
       
    59                            int tabstops, int* tabarray, int tabarraylen,
       
    60                            QPainter *painter);
       
    61 
       
    62 QTextItemIntCopy::QTextItemIntCopy(const QTextItem &item)
       
    63     : m_item(static_cast<const QTextItemInt &>(item))
       
    64 {
       
    65     QChar *chars = new QChar[m_item.num_chars];
       
    66     unsigned short *logClusters = new unsigned short[m_item.num_chars];
       
    67     memcpy(chars, m_item.chars, m_item.num_chars * sizeof(QChar));
       
    68     memcpy(logClusters, m_item.logClusters, m_item.num_chars * sizeof(unsigned short));
       
    69     m_item.chars = chars;
       
    70     m_item.logClusters = logClusters;
       
    71 
       
    72     const int size = QGlyphLayout::spaceNeededForGlyphLayout(m_item.glyphs.numGlyphs);
       
    73     char *glyphLayoutData = new char[size];
       
    74     QGlyphLayout glyphs(glyphLayoutData, m_item.glyphs.numGlyphs);
       
    75     memcpy(glyphs.offsets, m_item.glyphs.offsets, m_item.glyphs.numGlyphs * sizeof(QFixedPoint));
       
    76     memcpy(glyphs.glyphs, m_item.glyphs.glyphs, m_item.glyphs.numGlyphs * sizeof(HB_Glyph));
       
    77     memcpy(glyphs.advances_x, m_item.glyphs.advances_x, m_item.glyphs.numGlyphs * sizeof(QFixed));
       
    78     memcpy(glyphs.advances_y, m_item.glyphs.advances_y, m_item.glyphs.numGlyphs * sizeof(QFixed));
       
    79     memcpy(glyphs.justifications, m_item.glyphs.justifications, m_item.glyphs.numGlyphs * sizeof(QGlyphJustification));
       
    80     memcpy(glyphs.attributes, m_item.glyphs.attributes, m_item.glyphs.numGlyphs * sizeof(HB_GlyphAttributes));
       
    81     m_item.glyphs = glyphs;
       
    82 
       
    83     m_font = *m_item.f;
       
    84     m_item.f = &m_font;
       
    85 
       
    86     m_item.fontEngine->ref.ref(); // Increment reference count.
       
    87 }
       
    88 
       
    89 QTextItemIntCopy::~QTextItemIntCopy()
       
    90 {
       
    91     delete m_item.chars;
       
    92     delete m_item.logClusters;
       
    93     delete m_item.glyphs.data();
       
    94     if (!m_item.fontEngine->ref.deref())
       
    95         delete m_item.fontEngine;
       
    96 }
       
    97 
       
    98 /************************************************************************
       
    99  *
       
   100  * QPaintBufferSignalProxy
       
   101  *
       
   102  ************************************************************************/
       
   103 
       
   104 Q_GLOBAL_STATIC(QPaintBufferSignalProxy, theSignalProxy)
       
   105 
       
   106 QPaintBufferSignalProxy *QPaintBufferSignalProxy::instance()
       
   107 {
       
   108     return theSignalProxy();
       
   109 }
       
   110 
       
   111 /************************************************************************
       
   112  *
       
   113  * QPaintBufferPrivate
       
   114  *
       
   115  ************************************************************************/
       
   116 
       
   117 QPaintBufferPrivate::QPaintBufferPrivate()
       
   118     : ref(1), engine(0), penWidthAdjustment(0)
       
   119     , calculateBoundingRect(true)
       
   120     , cache(0)
       
   121 {
       
   122 }
       
   123 
       
   124 QPaintBufferPrivate::~QPaintBufferPrivate()
       
   125 {
       
   126     QPaintBufferSignalProxy::instance()->emitAboutToDestroy(this);
       
   127 
       
   128     for (int i = 0; i < commands.size(); ++i) {
       
   129         const QPaintBufferCommand &cmd = commands.at(i);
       
   130         if (cmd.id == QPaintBufferPrivate::Cmd_DrawTextItem)
       
   131             delete reinterpret_cast<QTextItemIntCopy *>(qVariantValue<void *>(variants.at(cmd.offset)));
       
   132     }
       
   133 }
       
   134 
       
   135 
       
   136 inline void QPaintBufferPrivate::updateBoundingRect(const QRectF &br)
       
   137 {
       
   138     // transform to device coords and adjust for pen width
       
   139     Q_ASSERT(engine && engine->painter());
       
   140     QPainter *painter = engine->painter();
       
   141     const QTransform transform = painter->transform();
       
   142     QRectF devRect = transform.mapRect(br);
       
   143     if (penWidthAdjustment > 0) {
       
   144         devRect = devRect.adjusted(-penWidthAdjustment, -penWidthAdjustment,
       
   145                                    penWidthAdjustment, penWidthAdjustment);
       
   146     }
       
   147 
       
   148     if (boundingRect.isEmpty()) {
       
   149         boundingRect = devRect;
       
   150     } else {
       
   151         qreal min_x = qMin(devRect.left(), boundingRect.left());
       
   152         qreal min_y = qMin(devRect.top(), boundingRect.top());
       
   153         qreal max_x = qMax(devRect.right(), boundingRect.right());
       
   154         qreal max_y = qMax(devRect.bottom(), boundingRect.bottom());
       
   155         boundingRect = QRectF(min_x, min_y, max_x - min_x, max_y - min_y);
       
   156     }
       
   157     if (painter->hasClipping())
       
   158         boundingRect &= transform.mapRect(painter->clipRegion().boundingRect());
       
   159 }
       
   160 
       
   161 
       
   162 /************************************************************************
       
   163  *
       
   164  * QPaintBuffer
       
   165  *
       
   166  ************************************************************************/
       
   167 
       
   168 
       
   169 
       
   170 QPaintBuffer::QPaintBuffer()
       
   171     : d_ptr(new QPaintBufferPrivate)
       
   172 {
       
   173 }
       
   174 
       
   175 QPaintBuffer::~QPaintBuffer()
       
   176 {
       
   177     if (!d_ptr->ref.deref())
       
   178         delete d_ptr;
       
   179 }
       
   180 
       
   181 QPaintBuffer::QPaintBuffer(const QPaintBuffer &other)
       
   182     : QPaintDevice(), d_ptr(other.d_ptr)
       
   183 {
       
   184     d_ptr->ref.ref();
       
   185 }
       
   186 
       
   187 QPaintEngine *QPaintBuffer::paintEngine() const
       
   188 {
       
   189     QPaintBufferPrivate *d = const_cast<QPaintBuffer *>(this)->d_ptr;
       
   190     if (!d->engine)
       
   191         d->engine = new QPaintBufferEngine(d);
       
   192     return d->engine;
       
   193 }
       
   194 
       
   195 
       
   196 int QPaintBuffer::metric(PaintDeviceMetric metric) const
       
   197 {
       
   198     int val = 0;
       
   199     switch (metric) {
       
   200     case PdmWidth:
       
   201         val = qCeil(d_ptr->boundingRect.width());
       
   202         break;
       
   203     case PdmHeight:
       
   204         val = qCeil(d_ptr->boundingRect.height());
       
   205         break;
       
   206     case PdmDpiX:
       
   207     case PdmPhysicalDpiX:
       
   208         val = qt_defaultDpiX();
       
   209         break;
       
   210     case PdmDpiY:
       
   211     case PdmPhysicalDpiY:
       
   212         val = qt_defaultDpiY();
       
   213         break;
       
   214     default:
       
   215         val = QPaintDevice::metric(metric);
       
   216     }
       
   217 
       
   218     return val;
       
   219 }
       
   220 
       
   221 int QPaintBuffer::devType() const
       
   222 {
       
   223     return QInternal::PaintBuffer;
       
   224 }
       
   225 
       
   226 QPaintBuffer &QPaintBuffer::operator=(const QPaintBuffer &other)
       
   227 {
       
   228     if (other.d_ptr != d_ptr) {
       
   229         QPaintBufferPrivate *data = other.d_ptr;
       
   230         data->ref.ref();
       
   231         if (d_ptr->ref.deref())
       
   232             delete d_ptr;
       
   233         d_ptr = data;
       
   234     }
       
   235     return *this;
       
   236 }
       
   237 
       
   238 bool QPaintBuffer::isEmpty() const
       
   239 {
       
   240     return d_ptr->commands.isEmpty();
       
   241 }
       
   242 
       
   243 
       
   244 
       
   245 void QPaintBuffer::draw(QPainter *painter, int frame) const
       
   246 {
       
   247 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
   248     qDebug() << "QPaintBuffer::draw() --------------------------------";
       
   249 
       
   250 //     printf("Float buffer:");
       
   251 //     for (int i=0; i<d->floats.size(); i++) {
       
   252 //         if ((i % 10) == 0) {
       
   253 //             printf("\n%4d-%4d: ", i, i+9);
       
   254 //         }
       
   255 //         printf("%4.2f  ", d->floats[i]);
       
   256 //     }
       
   257 //     printf("\n");
       
   258 
       
   259 //     printf("Int Buffer:");
       
   260 //     for (int i=0; i<d->ints.size(); i++) {
       
   261 //         if ((i % 10) == 0) {
       
   262 //             printf("\n%4d-%4d: ", i, i+10);
       
   263 //         }
       
   264 //         printf("%5d", d->ints[i]);
       
   265 //     }
       
   266 //     printf("\n");
       
   267 #endif
       
   268 
       
   269     if (painter && !painter->isActive())
       
   270         return;
       
   271 
       
   272     QPaintEngineEx *xengine = painter->paintEngine()->isExtended()
       
   273                               ? (QPaintEngineEx *) painter->paintEngine() : 0;
       
   274     if (xengine) {
       
   275         QPaintEngineExReplayer player;
       
   276         player.draw(*this, painter, frame);
       
   277     } else {
       
   278         QPainterReplayer player;
       
   279         player.draw(*this, painter, frame);
       
   280     }
       
   281 
       
   282 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
   283     qDebug() << "QPaintBuffer::draw() -------------------------------- DONE!";
       
   284 #endif
       
   285 }
       
   286 
       
   287 
       
   288 QRectF QPaintBuffer::boundingRect() const
       
   289 {
       
   290     return d_ptr->boundingRect;
       
   291 }
       
   292 
       
   293 void QPaintBuffer::setBoundingRect(const QRectF &rect)
       
   294 {
       
   295     d_ptr->boundingRect = rect;
       
   296     d_ptr->calculateBoundingRect = false;
       
   297 }
       
   298 
       
   299 
       
   300 class QPaintBufferEnginePrivate : public QPaintEngineExPrivate
       
   301 {
       
   302     Q_DECLARE_PUBLIC(QPaintBufferEngine)
       
   303 public:
       
   304     void systemStateChanged() {
       
   305         Q_Q(QPaintBufferEngine);
       
   306         q->buffer->addCommand(QPaintBufferPrivate::Cmd_SystemStateChanged, QVariant(systemClip));
       
   307     }
       
   308 };
       
   309 
       
   310 
       
   311 /************************************************************************
       
   312  *
       
   313  * QPaintBufferEngine
       
   314  *
       
   315  ************************************************************************/
       
   316 
       
   317 QPaintBufferEngine::QPaintBufferEngine(QPaintBufferPrivate *b)
       
   318     : QPaintEngineEx(*(new QPaintBufferEnginePrivate))
       
   319     , buffer(b)
       
   320     , m_begin_detected(false)
       
   321     , m_save_detected(false)
       
   322     , m_stream_raw_text_items(false)
       
   323 {
       
   324 }
       
   325 
       
   326 bool QPaintBufferEngine::begin(QPaintDevice *)
       
   327 {
       
   328     Q_D(QPaintBufferEngine);
       
   329     painter()->save();
       
   330     d->systemStateChanged();
       
   331     return true;
       
   332 }
       
   333 
       
   334 bool QPaintBufferEngine::end()
       
   335 {
       
   336     painter()->restore();
       
   337     m_created_state = 0;
       
   338     return true;
       
   339 }
       
   340 
       
   341 QPainterState *QPaintBufferEngine::createState(QPainterState *orig) const
       
   342 {
       
   343 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
   344     qDebug() << "QPaintBufferEngine: createState, orig=" << orig << ", current=" << state();
       
   345 #endif
       
   346 
       
   347     Q_ASSERT(!m_begin_detected);
       
   348     Q_ASSERT(!m_save_detected);
       
   349 
       
   350     if (orig == 0) {
       
   351         m_begin_detected = true;
       
   352         return new QPainterState();
       
   353     } else {
       
   354         m_save_detected = true;
       
   355         return new QPainterState(orig);
       
   356     }
       
   357 }
       
   358 
       
   359 void QPaintBufferEngine::clip(const QVectorPath &path, Qt::ClipOperation op)
       
   360 {
       
   361 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
   362     qDebug() << "QPaintBufferEngine: clip vpath:" << path.elementCount() << "op:" << op;
       
   363 #endif
       
   364     QPaintBufferCommand *cmd =
       
   365         buffer->addCommand(QPaintBufferPrivate::Cmd_ClipVectorPath, path);
       
   366     cmd->extra = op;
       
   367 }
       
   368 
       
   369 void QPaintBufferEngine::clip(const QRect &rect, Qt::ClipOperation op)
       
   370 {
       
   371 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
   372     qDebug() << "QPaintBufferEngine: clip rect:" << rect << "op:" << op;
       
   373 #endif
       
   374     QPaintBufferCommand *cmd =
       
   375         buffer->addCommand(QPaintBufferPrivate::Cmd_ClipRect, (int *) &rect, 4, 1);
       
   376     cmd->extra = op;
       
   377 }
       
   378 
       
   379 void QPaintBufferEngine::clip(const QRegion &region, Qt::ClipOperation op)
       
   380 {
       
   381 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
   382     qDebug() << "QPaintBufferEngine: clip region br:" << region.boundingRect() << "op:" << op;
       
   383 #endif
       
   384     QPaintBufferCommand *cmd =
       
   385         buffer->addCommand(QPaintBufferPrivate::Cmd_ClipRegion, QVariant(region));
       
   386     cmd->extra = op;
       
   387 }
       
   388 
       
   389 void QPaintBufferEngine::clip(const QPainterPath &path, Qt::ClipOperation op)
       
   390 {
       
   391     // ### TODO
       
   392 //     QPaintBufferCommand *cmd =
       
   393 //         buffer->addCommand(QPaintBufferPrivate::Cmd_ClipPath, QVariant(path));
       
   394 //     cmd->extra = op;
       
   395     QPaintEngineEx::clip(path, op);
       
   396 }
       
   397 
       
   398 void QPaintBufferEngine::clipEnabledChanged()
       
   399 {
       
   400 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
   401     qDebug() << "QPaintBufferEngine: clip enable change" << state()->clipEnabled;
       
   402 #endif
       
   403 
       
   404     buffer->addCommand(QPaintBufferPrivate::Cmd_SetClipEnabled, state()->clipEnabled);
       
   405 }
       
   406 
       
   407 void QPaintBufferEngine::penChanged()
       
   408 {
       
   409 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
   410     qDebug() << "QPaintBufferEngine:" << state()->pen;
       
   411 #endif
       
   412     const QPen &pen = state()->pen;
       
   413 
       
   414     if (!buffer->commands.isEmpty()
       
   415         && buffer->commands.last().id == QPaintBufferPrivate::Cmd_SetPen) {
       
   416         buffer->variants[buffer->commands.last().offset] = pen;
       
   417         return;
       
   418     }
       
   419     if (buffer->calculateBoundingRect) {
       
   420         if (pen.style() == Qt::NoPen) {
       
   421             buffer->penWidthAdjustment = 0;
       
   422         } else {
       
   423             qreal penWidth = (pen.widthF() == 0) ? 1 : pen.widthF();
       
   424             QPointF transformedWidth(penWidth, penWidth);
       
   425             if (!pen.isCosmetic())
       
   426                 transformedWidth = painter()->transform().map(transformedWidth);
       
   427             buffer->penWidthAdjustment = transformedWidth.x() / 2.0;
       
   428         }
       
   429     }
       
   430     buffer->addCommand(QPaintBufferPrivate::Cmd_SetPen, pen);
       
   431 }
       
   432 
       
   433 void QPaintBufferEngine::brushChanged()
       
   434 {
       
   435 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
   436     qDebug() << "QPaintBufferEngine:" << state()->brush;
       
   437 #endif
       
   438     const QBrush &brush = state()->brush;
       
   439 
       
   440     if (!buffer->commands.isEmpty()
       
   441         && buffer->commands.last().id == QPaintBufferPrivate::Cmd_SetBrush) {
       
   442         buffer->variants[buffer->commands.last().offset] = brush;
       
   443         return;
       
   444     }
       
   445 
       
   446     buffer->addCommand(QPaintBufferPrivate::Cmd_SetBrush, brush);
       
   447 }
       
   448 
       
   449 void QPaintBufferEngine::brushOriginChanged()
       
   450 {
       
   451 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
   452     qDebug() << "QPaintBufferEngine: brush origin changed" << state()->brushOrigin;
       
   453 #endif
       
   454     buffer->addCommand(QPaintBufferPrivate::Cmd_SetBrushOrigin, state()->brushOrigin);
       
   455 }
       
   456 
       
   457 void QPaintBufferEngine::opacityChanged()
       
   458 {
       
   459 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
   460     qDebug() << "QPaintBufferEngine: opacity changed" << state()->opacity;
       
   461 #endif
       
   462     buffer->addCommand(QPaintBufferPrivate::Cmd_SetOpacity, state()->opacity);
       
   463 }
       
   464 
       
   465 void QPaintBufferEngine::compositionModeChanged()
       
   466 {
       
   467 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
   468     qDebug() << "QPaintBufferEngine: composition mode" << state()->composition_mode;
       
   469 #endif
       
   470     QPaintBufferCommand *cmd =
       
   471         buffer->addCommand(QPaintBufferPrivate::Cmd_SetCompositionMode);
       
   472     cmd->extra = state()->composition_mode;
       
   473 }
       
   474 
       
   475 void QPaintBufferEngine::renderHintsChanged()
       
   476 {
       
   477 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
   478     qDebug() << "QPaintBufferEngine: render hints changed" << state()->renderHints;
       
   479 #endif
       
   480     QPaintBufferCommand *cmd =
       
   481         buffer->addCommand(QPaintBufferPrivate::Cmd_SetRenderHints);
       
   482     cmd->extra = state()->renderHints;
       
   483 }
       
   484 
       
   485 void QPaintBufferEngine::transformChanged()
       
   486 {
       
   487     // ### accumulate, like in QBrush case...
       
   488     if (!buffer->commands.isEmpty()
       
   489         && buffer->commands.last().id == QPaintBufferPrivate::Cmd_SetTransform) {
       
   490 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
   491         qDebug() << "QPaintBufferEngine: compressing " << state()->matrix;
       
   492 #endif
       
   493         buffer->variants[buffer->commands.last().offset] = state()->matrix;
       
   494         return;
       
   495     }
       
   496 
       
   497 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
   498         qDebug() << "QPaintBufferEngine: " << state()->matrix;
       
   499 #endif
       
   500     buffer->addCommand(QPaintBufferPrivate::Cmd_SetTransform, state()->matrix);
       
   501 }
       
   502 
       
   503 void QPaintBufferEngine::backgroundModeChanged()
       
   504 {
       
   505 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
   506     qDebug() << "QPaintEngineBuffer: background mode changed" << state()->bgMode;
       
   507 #endif
       
   508     QPaintBufferCommand *cmd = buffer->addCommand(QPaintBufferPrivate::Cmd_SetBackgroundMode);
       
   509     cmd->extra = state()->bgMode;
       
   510 }
       
   511 
       
   512 void QPaintBufferEngine::draw(const QVectorPath &path)
       
   513 {
       
   514 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
   515     qDebug() << "QPaintBufferEngine: draw vpath:" << path.elementCount();
       
   516 #endif
       
   517     buffer->addCommand(QPaintBufferPrivate::Cmd_DrawVectorPath, path);
       
   518 //     if (buffer->calculateBoundingRect) {
       
   519 //         QRealRect r = path.controlPointRect();
       
   520 //         buffer->updateBoundingRect(QRectF(r.x1, r.y1, r.x2 - r.x1, r.y2 - r.y1));
       
   521 //     }
       
   522 }
       
   523 
       
   524 void QPaintBufferEngine::fill(const QVectorPath &path, const QBrush &brush)
       
   525 {
       
   526 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
   527     qDebug() << "QPaintBufferEngine: fill vpath:" << path.elementCount() << brush;
       
   528 #endif
       
   529     QPaintBufferCommand *cmd =
       
   530         buffer->addCommand(QPaintBufferPrivate::Cmd_FillVectorPath, path);
       
   531     cmd->extra = buffer->addData(QVariant(brush));
       
   532 //     if (buffer->calculateBoundingRect) {
       
   533 //         QRealRect r = path.controlPointRect();
       
   534 //         buffer->updateBoundingRect(QRectF(r.x1, r.y1, r.x2 - r.x1, r.y2 - r.y1));
       
   535 //     }
       
   536 }
       
   537 
       
   538 void QPaintBufferEngine::stroke(const QVectorPath &path, const QPen &pen)
       
   539 {
       
   540 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
   541     qDebug() << "QPaintBufferEngine: stroke vpath:" << path.elementCount() << pen;
       
   542 #endif
       
   543     QPaintBufferCommand *cmd =
       
   544         buffer->addCommand(QPaintBufferPrivate::Cmd_StrokeVectorPath, path);
       
   545     cmd->extra = buffer->addData(QVariant(pen));
       
   546 //     if (buffer->calculateBoundingRect) {
       
   547 //         QRealRect r = path.controlPointRect();
       
   548 //         buffer->updateBoundingRect(QRectF(r.x1, r.y1, r.x2 - r.x1, r.y2 - r.y1));
       
   549 //     }
       
   550 }
       
   551 
       
   552 void QPaintBufferEngine::fillRect(const QRectF &rect, const QBrush &brush)
       
   553 {
       
   554 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
   555     qDebug() << "QPaintBufferEngine: fillRect brush:" << rect << brush;
       
   556 #endif
       
   557     QPaintBufferCommand *cmd =
       
   558         buffer->addCommand(QPaintBufferPrivate::Cmd_FillRectBrush, (qreal *) &rect, 4, 1);
       
   559     cmd->extra = buffer->addData(brush);
       
   560     if (buffer->calculateBoundingRect)
       
   561         buffer->updateBoundingRect(rect);
       
   562 }
       
   563 
       
   564 void QPaintBufferEngine::fillRect(const QRectF &rect, const QColor &color)
       
   565 {
       
   566 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
   567     qDebug() << "QPaintBufferEngine: fillRect color:" << rect << color;
       
   568 #endif
       
   569     QPaintBufferCommand *cmd =
       
   570         buffer->addCommand(QPaintBufferPrivate::Cmd_FillRectColor, (qreal *) &rect, 4, 1);
       
   571     cmd->extra = buffer->addData(color);
       
   572     if (buffer->calculateBoundingRect)
       
   573         buffer->updateBoundingRect(rect);
       
   574 }
       
   575 
       
   576 void QPaintBufferEngine::drawRects(const QRect *rects, int rectCount)
       
   577 {
       
   578 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
   579     qDebug() << "QPaintBufferEngine: drawRectsI:" << rectCount;
       
   580 #endif
       
   581     QPaintBufferCommand *cmd =
       
   582         buffer->addCommand(QPaintBufferPrivate::Cmd_DrawRectI, (int *) rects, 4 * rectCount, rectCount);
       
   583     cmd->extra = rectCount;
       
   584 
       
   585     if (buffer->calculateBoundingRect) {
       
   586         if (rectCount == 1) {
       
   587             buffer->updateBoundingRect(rects[0]);
       
   588         } else {
       
   589             int min_x = rects[0].left();
       
   590             int min_y = rects[0].top();
       
   591             int max_x = rects[0].left() + rects[0].width();
       
   592             int max_y = rects[0].top() + rects[0].height();
       
   593             for (int i=1; i< rectCount; ++i) {
       
   594                 if (rects[i].left() < min_x)
       
   595                     min_x = rects[i].left();
       
   596                 if (rects[i].top() < min_y)
       
   597                     min_y = rects[i].top();
       
   598                 if (rects[i].right() > max_x)
       
   599                     max_x = rects[i].left() + rects[i].width();
       
   600                 if (rects[i].bottom() > max_y)
       
   601                     max_y = rects[i].top() + rects[i].height();
       
   602 
       
   603             }
       
   604             buffer->updateBoundingRect(QRectF(min_x, min_y, max_x - min_x, max_y - min_y));
       
   605         }
       
   606     }
       
   607 }
       
   608 
       
   609 void QPaintBufferEngine::drawRects(const QRectF *rects, int rectCount)
       
   610 {
       
   611 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
   612     qDebug() << "QPaintBufferEngine: drawRectsF:" << rectCount;
       
   613 #endif
       
   614     QPaintBufferCommand *cmd =
       
   615         buffer->addCommand(QPaintBufferPrivate::Cmd_DrawRectF, (qreal *) rects, 4 * rectCount, rectCount);
       
   616     cmd->extra = rectCount;
       
   617 
       
   618     if (buffer->calculateBoundingRect) {
       
   619         if (rectCount == 1) {
       
   620             buffer->updateBoundingRect(rects[0]);
       
   621         } else {
       
   622             qreal min_x = rects[0].left();
       
   623             qreal min_y = rects[0].top();
       
   624             qreal max_x = rects[0].right();
       
   625             qreal max_y = rects[0].bottom();
       
   626             for (int i=1; i< rectCount; ++i) {
       
   627                 if (rects[i].left() < min_x)
       
   628                     min_x = rects[i].left();
       
   629                 if (rects[i].top() < min_y)
       
   630                     min_y = rects[i].top();
       
   631                 if (rects[i].right() > max_x)
       
   632                     max_x = rects[i].right();
       
   633                 if (rects[i].bottom() > max_y)
       
   634                     max_y = rects[i].bottom();
       
   635 
       
   636             }
       
   637             buffer->updateBoundingRect(QRectF(min_x, min_y, max_x - min_x, max_y - min_y));
       
   638         }
       
   639     }
       
   640 }
       
   641 
       
   642 void QPaintBufferEngine::drawLines(const QLine *lines, int lineCount)
       
   643 {
       
   644 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
   645     qDebug() << "QPaintBufferEngine: drawLinesI:" << lineCount;
       
   646 #endif
       
   647     QPaintBufferCommand *cmd =
       
   648         buffer->addCommand(QPaintBufferPrivate::Cmd_DrawLineI, (int *) lines, 4 * lineCount, lineCount);
       
   649     cmd->extra = lineCount;
       
   650 
       
   651     if (buffer->calculateBoundingRect) {
       
   652         int min_x = lines[0].p1().x();
       
   653         int min_y = lines[0].p1().y();
       
   654         int max_x = lines[0].p2().x();
       
   655         int max_y = lines[0].p2().y();
       
   656         if (min_x > max_x)
       
   657             qSwap(min_x, max_x);
       
   658         if (min_y > max_y)
       
   659             qSwap(min_y, max_y);
       
   660         for (int i=1; i < lineCount; ++i) {
       
   661             int p1_x = lines[i].p1().x();
       
   662             int p1_y = lines[i].p1().y();
       
   663             int p2_x = lines[i].p2().x();
       
   664             int p2_y = lines[i].p2().y();
       
   665             if (p1_x > p2_x) {
       
   666                 min_x = qMin(p2_x, min_x);
       
   667                 max_x = qMax(p1_x, max_x);
       
   668             } else {
       
   669                 min_x = qMin(p1_x, min_x);
       
   670                 max_x = qMax(p2_x, max_x);
       
   671             }
       
   672             if (p1_y > p2_y) {
       
   673                 min_y = qMin(p2_y, min_y);
       
   674                 max_y = qMax(p1_y, max_y);
       
   675             } else {
       
   676                 min_y = qMin(p1_y, min_y);
       
   677                 max_y = qMax(p2_y, max_y);
       
   678             }
       
   679         }
       
   680         buffer->updateBoundingRect(QRectF(min_x, min_y, max_x - min_x, max_y - min_y));
       
   681     }
       
   682 }
       
   683 
       
   684 void QPaintBufferEngine::drawLines(const QLineF *lines, int lineCount)
       
   685 {
       
   686 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
   687     qDebug() << "QPaintBufferEngine: drawLinesF:" << lineCount;
       
   688 #endif
       
   689     QPaintBufferCommand *cmd =
       
   690         buffer->addCommand(QPaintBufferPrivate::Cmd_DrawLineF, (qreal *) lines, 4 * lineCount, lineCount);
       
   691     cmd->extra = lineCount;
       
   692 
       
   693     if (buffer->calculateBoundingRect) {
       
   694         qreal min_x = lines[0].p1().x();
       
   695         qreal min_y = lines[0].p1().y();
       
   696         qreal max_x = lines[0].p2().x();
       
   697         qreal max_y = lines[0].p2().y();
       
   698         if (min_x > max_x)
       
   699             qSwap(min_x, max_x);
       
   700         if (min_y > max_y)
       
   701             qSwap(min_y, max_y);
       
   702         for (int i=1; i < lineCount; ++i) {
       
   703             qreal p1_x = lines[i].p1().x();
       
   704             qreal p1_y = lines[i].p1().y();
       
   705             qreal p2_x = lines[i].p2().x();
       
   706             qreal p2_y = lines[i].p2().y();
       
   707             if (p1_x > p2_x) {
       
   708                 min_x = qMin(p2_x, min_x);
       
   709                 max_x = qMax(p1_x, max_x);
       
   710             } else {
       
   711                 min_x = qMin(p1_x, min_x);
       
   712                 max_x = qMax(p2_x, max_x);
       
   713             }
       
   714             if (p1_y > p2_y) {
       
   715                 min_y = qMin(p2_y, min_y);
       
   716                 max_y = qMax(p1_y, max_y);
       
   717             } else {
       
   718                 min_y = qMin(p1_y, min_y);
       
   719                 max_y = qMax(p2_y, max_y);
       
   720             }
       
   721         }
       
   722         buffer->updateBoundingRect(QRectF(min_x, min_y, max_x - min_x, max_y - min_y));
       
   723     }
       
   724 }
       
   725 
       
   726 void QPaintBufferEngine::drawEllipse(const QRectF &r)
       
   727 {
       
   728 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
   729     qDebug() << "QPaintBufferEngine: drawEllipseF:" << r;
       
   730 #endif
       
   731     buffer->addCommand(QPaintBufferPrivate::Cmd_DrawEllipseF, (qreal *) &r, 4, 1);
       
   732     if (buffer->calculateBoundingRect)
       
   733         buffer->updateBoundingRect(r);
       
   734 }
       
   735 
       
   736 void QPaintBufferEngine::drawEllipse(const QRect &r)
       
   737 {
       
   738 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
   739     qDebug() << "QPaintBufferEngine: drawEllipseI:" << r;
       
   740 #endif
       
   741     buffer->addCommand(QPaintBufferPrivate::Cmd_DrawEllipseI, (int *) &r, 4, 1);
       
   742     if (buffer->calculateBoundingRect)
       
   743         buffer->updateBoundingRect(r);
       
   744 }
       
   745 
       
   746 void QPaintBufferEngine::drawPath(const QPainterPath &path)
       
   747 {
       
   748 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
   749     qDebug() << "QPaintBufferEngine: drawPath: element count:" << path.elementCount();
       
   750 #endif
       
   751     // ### Path -> QVariant
       
   752     // buffer->addCommand(QPaintBufferPrivate::Cmd_DrawPath, QVariant(path));
       
   753     QPaintEngineEx::drawPath(path);
       
   754 
       
   755     if (buffer->calculateBoundingRect)
       
   756         buffer->updateBoundingRect(path.boundingRect());
       
   757 }
       
   758 
       
   759 void QPaintBufferEngine::drawPoints(const QPoint *points, int pointCount)
       
   760 {
       
   761 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
   762     qDebug() << "QPaintBufferEngine: drawPointsI: " << pointCount;
       
   763 #endif
       
   764     buffer->addCommand(QPaintBufferPrivate::Cmd_DrawPointsI, (int *) points, 2 * pointCount, pointCount);
       
   765 
       
   766     if (buffer->calculateBoundingRect) {
       
   767         int min_x = points[0].x();
       
   768         int min_y = points[0].y();
       
   769         int max_x = points[0].x()+1;
       
   770         int max_y = points[0].y()+1;
       
   771         for (int i=1; i<pointCount; ++i) {
       
   772             int x = points[i].x();
       
   773             int y = points[i].y();
       
   774             min_x = qMin(min_x, x);
       
   775             min_y = qMin(min_y, y);
       
   776             max_x = qMax(max_x, x+1);
       
   777             max_y = qMax(max_y, y+1);
       
   778         }
       
   779         buffer->updateBoundingRect(QRectF(min_x, min_y, max_x - min_x, max_y - min_y));
       
   780     }
       
   781 }
       
   782 
       
   783 void QPaintBufferEngine::drawPoints(const QPointF *points, int pointCount)
       
   784 {
       
   785 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
   786     qDebug() << "QPaintBufferEngine: drawPointsF: " << pointCount;
       
   787 #endif
       
   788     buffer->addCommand(QPaintBufferPrivate::Cmd_DrawPointsF, (qreal *) points, 2 * pointCount, pointCount);
       
   789 
       
   790     if (buffer->calculateBoundingRect) {
       
   791         qreal min_x = points[0].x();
       
   792         qreal min_y = points[0].y();
       
   793         qreal max_x = points[0].x()+1;
       
   794         qreal max_y = points[0].y()+1;
       
   795         for (int i=1; i<pointCount; ++i) {
       
   796             qreal x = points[i].x();
       
   797             qreal y = points[i].y();
       
   798             min_x = qMin(min_x, x);
       
   799             min_y = qMin(min_y, y);
       
   800             max_x = qMax(max_x, x+1);
       
   801             max_y = qMax(max_y, y+1);
       
   802         }
       
   803         buffer->updateBoundingRect(QRectF(min_x, min_y, max_x - min_x, max_y - min_y));
       
   804     }
       
   805 }
       
   806 
       
   807 void QPaintBufferEngine::drawPolygon(const QPoint *pts, int count, PolygonDrawMode mode)
       
   808 {
       
   809 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
   810     qDebug() << "QPaintBufferEngine: drawPolygonI: size:" << count << ", mode:" << mode;
       
   811 #endif
       
   812     if (mode == QPaintEngine::OddEvenMode || mode == QPaintEngine::WindingMode) {
       
   813         QPaintBufferCommand *cmd = buffer->addCommand(QPaintBufferPrivate::Cmd_DrawPolygonI,
       
   814                                                       (int *) pts, 2 * count, count);
       
   815         cmd->extra = mode;
       
   816     } else if (mode == QPaintEngine::PolylineMode) {
       
   817         buffer->addCommand(QPaintBufferPrivate::Cmd_DrawPolylineI, (int *) pts, 2 * count, count);
       
   818     } else {
       
   819         buffer->addCommand(QPaintBufferPrivate::Cmd_DrawConvexPolygonI, (int *) pts, 2 * count, count);
       
   820     }
       
   821 
       
   822     if (buffer->calculateBoundingRect) {
       
   823         int min_x = pts[0].x();
       
   824         int min_y = pts[0].y();
       
   825         int max_x = pts[0].x();
       
   826         int max_y = pts[0].y();
       
   827         for (int i=1; i<count; ++i) {
       
   828             int x = pts[i].x();
       
   829             int y = pts[i].y();
       
   830             min_x = qMin(min_x, x);
       
   831             min_y = qMin(min_y, y);
       
   832             max_x = qMax(max_x, x);
       
   833             max_y = qMax(max_y, y);
       
   834         }
       
   835         buffer->updateBoundingRect(QRectF(min_x, min_y, max_x - min_x, max_y - min_y));
       
   836     }
       
   837 }
       
   838 
       
   839 void QPaintBufferEngine::drawPolygon(const QPointF *pts, int count, PolygonDrawMode mode)
       
   840 {
       
   841 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
   842     qDebug() << "QPaintBufferEngine: drawPolygonF: size:" << count << ", mode:" << mode;
       
   843 #endif
       
   844     if (mode == QPaintEngine::OddEvenMode || mode == QPaintEngine::WindingMode) {
       
   845         QPaintBufferCommand *cmd = buffer->addCommand(QPaintBufferPrivate::Cmd_DrawPolygonF,
       
   846                                                       (qreal *) pts, 2 * count, count);
       
   847         cmd->extra = mode;
       
   848     } else if (mode == QPaintEngine::PolylineMode) {
       
   849         buffer->addCommand(QPaintBufferPrivate::Cmd_DrawPolylineF, (qreal *) pts, 2 * count, count);
       
   850     } else {
       
   851         buffer->addCommand(QPaintBufferPrivate::Cmd_DrawConvexPolygonF, (qreal *) pts, 2 * count, count);
       
   852     }
       
   853 
       
   854     if (buffer->calculateBoundingRect) {
       
   855         qreal min_x = pts[0].x();
       
   856         qreal min_y = pts[0].y();
       
   857         qreal max_x = pts[0].x();
       
   858         qreal max_y = pts[0].y();
       
   859         for (int i=1; i<count; ++i) {
       
   860             qreal x = pts[i].x();
       
   861             qreal y = pts[i].y();
       
   862             min_x = qMin(min_x, x);
       
   863             min_y = qMin(min_y, y);
       
   864             max_x = qMax(max_x, x);
       
   865             max_y = qMax(max_y, y);
       
   866         }
       
   867         buffer->updateBoundingRect(QRectF(min_x, min_y, max_x - min_x, max_y - min_y));
       
   868     }
       
   869 }
       
   870 
       
   871 void QPaintBufferEngine::drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr)
       
   872 {
       
   873 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
   874     qDebug() << "QPaintBufferEngine: drawPixmap: src/dest rects " << r << sr;
       
   875 #endif
       
   876     QPaintBufferCommand *cmd =
       
   877         buffer->addCommand(QPaintBufferPrivate::Cmd_DrawPixmapRect, QVariant(pm));
       
   878     cmd->extra = buffer->addData((qreal *) &r, 4);
       
   879     buffer->addData((qreal *) &sr, 4);
       
   880     if (buffer->calculateBoundingRect)
       
   881         buffer->updateBoundingRect(r);
       
   882 }
       
   883 
       
   884 void QPaintBufferEngine::drawPixmap(const QPointF &pos, const QPixmap &pm)
       
   885 {
       
   886 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
   887     qDebug() << "QPaintBufferEngine: drawPixmap: pos:" << pos;
       
   888 #endif
       
   889     QPaintBufferCommand *cmd =
       
   890         buffer->addCommand(QPaintBufferPrivate::Cmd_DrawPixmapPos, QVariant(pm));
       
   891     cmd->extra = buffer->addData((qreal *) &pos, 2);
       
   892     if (buffer->calculateBoundingRect)
       
   893         buffer->updateBoundingRect(QRectF(pos, pm.size()));
       
   894 }
       
   895 
       
   896 static inline QImage qpaintbuffer_storable_image(const QImage &src)
       
   897 {
       
   898     QImageData *d = const_cast<QImage &>(src).data_ptr();
       
   899     return d->own_data ? src : src.copy();
       
   900 }
       
   901 
       
   902 void QPaintBufferEngine::drawImage(const QRectF &r, const QImage &image, const QRectF &sr,
       
   903                                    Qt::ImageConversionFlags /*flags */)
       
   904 {
       
   905 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
   906     qDebug() << "QPaintBufferEngine: drawImage: src/dest rects " << r << sr;
       
   907 #endif
       
   908     QPaintBufferCommand *cmd =
       
   909         buffer->addCommand(QPaintBufferPrivate::Cmd_DrawImageRect,
       
   910                            QVariant(qpaintbuffer_storable_image(image)));
       
   911     cmd->extra = buffer->addData((qreal *) &r, 4);
       
   912     buffer->addData((qreal *) &sr, 4);
       
   913     // ### flags...
       
   914     if (buffer->calculateBoundingRect)
       
   915         buffer->updateBoundingRect(r);
       
   916 }
       
   917 
       
   918 void QPaintBufferEngine::drawImage(const QPointF &pos, const QImage &image)
       
   919 {
       
   920 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
   921     qDebug() << "QPaintBufferEngine: drawImage: pos:" << pos;
       
   922 #endif
       
   923     QPaintBufferCommand *cmd =
       
   924         buffer->addCommand(QPaintBufferPrivate::Cmd_DrawImagePos,
       
   925                            QVariant(qpaintbuffer_storable_image(image)));
       
   926     cmd->extra = buffer->addData((qreal *) &pos, 2);
       
   927     if (buffer->calculateBoundingRect)
       
   928         buffer->updateBoundingRect(QRectF(pos, image.size()));
       
   929 }
       
   930 
       
   931 void QPaintBufferEngine::drawTiledPixmap(const QRectF &r, const QPixmap &pm, const QPointF &s)
       
   932 {
       
   933 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
   934     qDebug() << "QPaintBufferEngine: drawTiledPixmap: src rect/offset:" << r << s;
       
   935 #endif
       
   936     QPaintBufferCommand *cmd =
       
   937         buffer->addCommand(QPaintBufferPrivate::Cmd_DrawTiledPixmap, QVariant(pm));
       
   938     cmd->extra = buffer->addData((qreal *) &r, 4);
       
   939     buffer->addData((qreal *) &s, 2);
       
   940     if (buffer->calculateBoundingRect)
       
   941         buffer->updateBoundingRect(r);
       
   942 }
       
   943 
       
   944 void QPaintBufferEngine::drawTextItem(const QPointF &pos, const QTextItem &ti)
       
   945 {
       
   946 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
   947     qDebug() << "QPaintBufferEngine: drawTextItem: pos:" << pos << ti.text();
       
   948 #endif
       
   949     if (m_stream_raw_text_items) {
       
   950         QPaintBufferCommand *cmd = buffer->addCommand(QPaintBufferPrivate::Cmd_DrawTextItem, qVariantFromValue<void *>(new QTextItemIntCopy(ti)));
       
   951 
       
   952         QFont font(ti.font());
       
   953         font.setUnderline(false);
       
   954         font.setStrikeOut(false);
       
   955         font.setOverline(false);
       
   956 
       
   957         const QTextItemInt &si = static_cast<const QTextItemInt &>(ti);
       
   958         qreal justificationWidth = 0;
       
   959         if (si.justified)
       
   960             justificationWidth = si.width.toReal();
       
   961         int renderFlags = ti.renderFlags();
       
   962         qreal scaleFactor = font.d->dpi/qreal(qt_defaultDpiY());
       
   963 
       
   964         buffer->addData(QVariant(font));
       
   965         cmd->extra = buffer->addData((qreal *) &pos, 2);
       
   966         buffer->addData((qreal *) &justificationWidth, 1);
       
   967         buffer->addData((qreal *) &scaleFactor, 1);
       
   968         cmd->offset2 = buffer->addData((int *) &renderFlags, 1);
       
   969     } else {
       
   970         QList<QVariant> variants;
       
   971         variants << QVariant(ti.font()) << QVariant(ti.text());
       
   972         QPaintBufferCommand *cmd = buffer->addCommand(QPaintBufferPrivate::Cmd_DrawText, QVariant(variants));
       
   973         cmd->extra = buffer->addData((qreal *) &pos, 2);
       
   974     }
       
   975 
       
   976     if (buffer->calculateBoundingRect)
       
   977         buffer->updateBoundingRect(QRectF(pos, QSize(ti.width(), ti.ascent() + ti.descent() + 1)));
       
   978 }
       
   979 
       
   980 
       
   981 void QPaintBufferEngine::setState(QPainterState *s)
       
   982 {
       
   983     if (m_begin_detected) {
       
   984 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
   985             qDebug() << "QPaintBufferEngine: setState: begin, ignoring.";
       
   986 #endif
       
   987         m_begin_detected = false;
       
   988     } else if (m_save_detected) {
       
   989 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
   990         qDebug() << "QPaintBufferEngine: setState: save.";
       
   991 #endif
       
   992         m_save_detected = false;
       
   993         buffer->addCommand(QPaintBufferPrivate::Cmd_Save);
       
   994     } else {
       
   995 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
   996         qDebug() << "QPaintBufferEngine: setState: restore.";
       
   997 #endif
       
   998         buffer->addCommand(QPaintBufferPrivate::Cmd_Restore);
       
   999     }
       
  1000 
       
  1001     QPaintEngineEx::setState(s);
       
  1002 }
       
  1003 
       
  1004 
       
  1005 /***********************************************************************
       
  1006  *
       
  1007  * class QPaintBufferPlayback_Painter
       
  1008  *
       
  1009  */
       
  1010 
       
  1011 // QFakeDevice is used to create fonts with a custom DPI
       
  1012 //
       
  1013 class QFakeDevice : public QPaintDevice
       
  1014 {
       
  1015 public:
       
  1016     QFakeDevice() { dpi_x = qt_defaultDpiX(); dpi_y = qt_defaultDpiY(); }
       
  1017     void setDpiX(int dpi) { dpi_x = dpi; }
       
  1018     void setDpiY(int dpi) { dpi_y = dpi; }
       
  1019     QPaintEngine *paintEngine() const { return 0; }
       
  1020     int metric(PaintDeviceMetric m) const
       
  1021     {
       
  1022         switch(m) {
       
  1023             case PdmPhysicalDpiX:
       
  1024             case PdmDpiX:
       
  1025                 return dpi_x;
       
  1026             case PdmPhysicalDpiY:
       
  1027             case PdmDpiY:
       
  1028                 return dpi_y;
       
  1029             default:
       
  1030                 return QPaintDevice::metric(m);
       
  1031         }
       
  1032     }
       
  1033 
       
  1034 private:
       
  1035     int dpi_x;
       
  1036     int dpi_y;
       
  1037 };
       
  1038 
       
  1039 
       
  1040 void QPainterReplayer::setupTransform(QPainter *_painter)
       
  1041 {
       
  1042     painter = _painter;
       
  1043     m_world_matrix = painter->transform();
       
  1044     m_world_matrix.scale(qreal(painter->device()->logicalDpiX()) / qreal(qt_defaultDpiX()),
       
  1045                          qreal(painter->device()->logicalDpiY()) / qreal(qt_defaultDpiY()));
       
  1046     painter->setTransform(m_world_matrix);
       
  1047 }
       
  1048 
       
  1049 void QPainterReplayer::draw(const QPaintBuffer &buffer, QPainter *_painter, int frame)
       
  1050 {
       
  1051     d = buffer.d_ptr;
       
  1052     setupTransform(_painter);
       
  1053 
       
  1054     int frameStart = (frame == 0) ? 0 : d->frames.at(frame-1);
       
  1055     int frameEnd = (frame == d->frames.size()) ? d->commands.size() : d->frames.at(frame);
       
  1056 
       
  1057     for (int cmdIndex=frameStart; cmdIndex<frameEnd; ++cmdIndex) {
       
  1058         const QPaintBufferCommand &cmd = d->commands.at(cmdIndex);
       
  1059         process(cmd);
       
  1060     }
       
  1061 }
       
  1062 
       
  1063 void QPaintBuffer::beginNewFrame()
       
  1064 {
       
  1065     if (!d_ptr->commands.isEmpty())
       
  1066         d_ptr->frames << d_ptr->commands.size();
       
  1067 }
       
  1068 
       
  1069 int QPaintBuffer::numFrames() const
       
  1070 {
       
  1071     return d_ptr->frames.size() + 1;
       
  1072 }
       
  1073 
       
  1074 void QPainterReplayer::process(const QPaintBufferCommand &cmd)
       
  1075 {
       
  1076     switch (cmd.id) {
       
  1077     case QPaintBufferPrivate::Cmd_Save: {
       
  1078 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
  1079         qDebug() << " -> Cmd_Save";
       
  1080 #endif
       
  1081         painter->save();
       
  1082         break; }
       
  1083 
       
  1084     case QPaintBufferPrivate::Cmd_Restore: {
       
  1085 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
  1086         qDebug() << " -> Cmd_Restore";
       
  1087 #endif
       
  1088         painter->restore();
       
  1089         break; }
       
  1090 
       
  1091     case QPaintBufferPrivate::Cmd_SetPen: {
       
  1092         QPen pen = qVariantValue<QPen>(d->variants.at(cmd.offset));
       
  1093 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
  1094         qDebug() << " -> Cmd_SetPen: " << pen;
       
  1095 #endif
       
  1096         painter->setPen(pen);
       
  1097         break; }
       
  1098 
       
  1099     case QPaintBufferPrivate::Cmd_SetBrush: {
       
  1100         QBrush brush = qVariantValue<QBrush>(d->variants.at(cmd.offset));
       
  1101 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
  1102         qDebug() << " -> Cmd_SetBrush: " << brush;
       
  1103 #endif
       
  1104         painter->setBrush(brush);
       
  1105         break; }
       
  1106 
       
  1107     case QPaintBufferPrivate::Cmd_SetBrushOrigin: {
       
  1108 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
  1109         qDebug() << " -> Cmd_SetBrushOrigin: " << d->variants.at(cmd.offset).toPointF();
       
  1110 #endif
       
  1111         painter->setBrushOrigin(d->variants.at(cmd.offset).toPointF());
       
  1112         break; }
       
  1113 
       
  1114     case QPaintBufferPrivate::Cmd_SetTransform: {
       
  1115         QTransform xform = qVariantValue<QTransform>(d->variants.at(cmd.offset));
       
  1116 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
  1117         qDebug() << " -> Cmd_SetTransform, offset: " << cmd.offset << xform;
       
  1118 #endif
       
  1119         painter->setTransform(xform * m_world_matrix);
       
  1120         break; }
       
  1121 
       
  1122     case QPaintBufferPrivate::Cmd_SetCompositionMode: {
       
  1123         QPainter::CompositionMode mode = (QPainter::CompositionMode) cmd.extra;
       
  1124 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
  1125         qDebug() << " -> Cmd_SetCompositionMode, mode: " << mode;
       
  1126 #endif
       
  1127         painter->setCompositionMode(mode);
       
  1128         break; }
       
  1129 
       
  1130     case QPaintBufferPrivate::Cmd_SetRenderHints: {
       
  1131 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
  1132         qDebug() << " -> Cmd_SetRenderHints, hints: " << cmd.extra;
       
  1133 #endif
       
  1134         QPainter::RenderHints ph = painter->renderHints();
       
  1135         QPainter::RenderHints nh = (QPainter::RenderHints) cmd.extra;
       
  1136         QPainter::RenderHints xored = ph ^ nh;
       
  1137         if (xored & QPainter::Antialiasing)
       
  1138             painter->setRenderHint(QPainter::Antialiasing, nh & QPainter::Antialiasing);
       
  1139         if (xored & QPainter::HighQualityAntialiasing)
       
  1140             painter->setRenderHint(QPainter::HighQualityAntialiasing, nh & QPainter::HighQualityAntialiasing);
       
  1141         if (xored & QPainter::TextAntialiasing)
       
  1142             painter->setRenderHint(QPainter::TextAntialiasing, nh & QPainter::TextAntialiasing);
       
  1143         if (xored & QPainter::SmoothPixmapTransform)
       
  1144             painter->setRenderHint(QPainter::SmoothPixmapTransform, nh & QPainter::SmoothPixmapTransform);
       
  1145         if (xored & QPainter::NonCosmeticDefaultPen)
       
  1146             painter->setRenderHint(QPainter::NonCosmeticDefaultPen, nh & QPainter::NonCosmeticDefaultPen);
       
  1147         break; }
       
  1148 
       
  1149     case QPaintBufferPrivate::Cmd_SetOpacity: {
       
  1150 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
  1151         qDebug() << " -> Cmd_SetOpacity: " << d->variants.at(cmd.offset).toDouble();
       
  1152 #endif
       
  1153         painter->setOpacity(d->variants.at(cmd.offset).toDouble());
       
  1154         break; }
       
  1155 
       
  1156     case QPaintBufferPrivate::Cmd_SetBackgroundMode: {
       
  1157 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
  1158         qDebug() << " -> Cmd_SetBackgroundMode: " << cmd.extra;
       
  1159 #endif
       
  1160         painter->setBackgroundMode((Qt::BGMode)cmd.extra);
       
  1161         break; }
       
  1162 
       
  1163     case QPaintBufferPrivate::Cmd_DrawVectorPath: {
       
  1164 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
  1165         qDebug() << " -> Cmd_DrawVectorPath: size: " << cmd.size
       
  1166 //                 << ", hints:" << d->ints[cmd.offset2+cmd.size]
       
  1167                  << "pts/elms:" << cmd.offset << cmd.offset2;
       
  1168 #endif
       
  1169         QVectorPathCmd path(d, cmd);
       
  1170         painter->drawPath(path().convertToPainterPath());
       
  1171         break; }
       
  1172 
       
  1173     case QPaintBufferPrivate::Cmd_StrokeVectorPath: {
       
  1174         QPen pen = qVariantValue<QPen>(d->variants.at(cmd.extra));
       
  1175 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
  1176         qDebug() << " -> Cmd_StrokeVectorPath: size: " << cmd.size
       
  1177 //                 << ", hints:" << d->ints[cmd.offset2+cmd.size]
       
  1178                  << "pts/elms:" << cmd.offset << cmd.offset2;
       
  1179 #endif
       
  1180         QVectorPathCmd path(d, cmd);
       
  1181         painter->strokePath(path().convertToPainterPath(), pen);
       
  1182         break; }
       
  1183 
       
  1184     case QPaintBufferPrivate::Cmd_FillVectorPath: {
       
  1185         QBrush brush = qVariantValue<QBrush>(d->variants.at(cmd.extra));
       
  1186 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
  1187         qDebug() << " -> Cmd_FillVectorPath: size: " << cmd.size
       
  1188 //                 << ", hints:" << d->ints[cmd.offset2+cmd.size]
       
  1189                  << "pts/elms:" << cmd.offset << cmd.offset2 << brush;
       
  1190 #endif
       
  1191         QVectorPathCmd path(d, cmd);
       
  1192         painter->fillPath(path().convertToPainterPath(), brush);
       
  1193         break; }
       
  1194 
       
  1195     case QPaintBufferPrivate::Cmd_DrawPolygonF: {
       
  1196 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
  1197         qDebug() << " -> Cmd_DrawPolygonF, offset: " << cmd.offset << " size: " << cmd.size
       
  1198                  << " mode: " << cmd.extra
       
  1199                  << d->floats.at(cmd.offset)
       
  1200                  << d->floats.at(cmd.offset+1);
       
  1201 #endif
       
  1202         Qt::FillRule fill = (QPaintEngine::PolygonDrawMode) cmd.extra == QPaintEngine::OddEvenMode
       
  1203                             ? Qt::OddEvenFill : Qt::WindingFill;
       
  1204         painter->drawPolygon((QPointF *) (d->floats.constData() + cmd.offset), cmd.size, fill);
       
  1205         break; }
       
  1206 
       
  1207     case QPaintBufferPrivate::Cmd_DrawPolygonI: {
       
  1208 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
  1209         qDebug() << " -> Cmd_DrawPolygonI, offset: " << cmd.offset << " size: " << cmd.size
       
  1210                  << " mode: " << cmd.extra
       
  1211                  << d->ints.at(cmd.offset)
       
  1212                  << d->ints.at(cmd.offset+1);
       
  1213 #endif
       
  1214         Qt::FillRule fill = (QPaintEngine::PolygonDrawMode) cmd.extra == QPaintEngine::OddEvenMode
       
  1215                             ? Qt::OddEvenFill : Qt::WindingFill;
       
  1216         painter->drawPolygon((QPoint *) (d->ints.constData() + cmd.offset), cmd.size, fill);
       
  1217         break; }
       
  1218 
       
  1219     case QPaintBufferPrivate::Cmd_DrawPolylineF: {
       
  1220 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
  1221         qDebug() << " -> Cmd_DrawPolylineF, offset: " << cmd.offset << " size: " << cmd.size;
       
  1222 #endif
       
  1223         painter->drawPolyline((QPointF *) (d->floats.constData() + cmd.offset), cmd.size);
       
  1224         break; }
       
  1225 
       
  1226     case QPaintBufferPrivate::Cmd_DrawPolylineI: {
       
  1227 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
  1228         qDebug() << " -> Cmd_DrawPolylineI, offset: " << cmd.offset << " size: " << cmd.size;
       
  1229 #endif
       
  1230         painter->drawPolyline((QPoint *) (d->ints.constData() + cmd.offset), cmd.size);
       
  1231         break; }
       
  1232 
       
  1233     case QPaintBufferPrivate::Cmd_DrawConvexPolygonF: {
       
  1234 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
  1235         qDebug() << " -> Cmd_DrawConvexPolygonF, offset: " << cmd.offset << " size: " << cmd.size;
       
  1236 #endif
       
  1237         painter->drawConvexPolygon((QPointF *) (d->floats.constData() + cmd.offset), cmd.size);
       
  1238         break; }
       
  1239 
       
  1240     case QPaintBufferPrivate::Cmd_DrawConvexPolygonI: {
       
  1241 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
  1242         qDebug() << " -> Cmd_DrawConvexPolygonI, offset: " << cmd.offset << " size: " << cmd.size;
       
  1243 #endif
       
  1244         painter->drawConvexPolygon((QPoint *) (d->ints.constData() + cmd.offset), cmd.size);
       
  1245         break; }
       
  1246 
       
  1247     case QPaintBufferPrivate::Cmd_DrawEllipseF: {
       
  1248 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
  1249         qDebug() << " -> Cmd_DrawEllipseF, offset: " << cmd.offset;
       
  1250 #endif
       
  1251         painter->drawEllipse(*(QRectF *)(d->floats.constData() + cmd.offset));
       
  1252         break; }
       
  1253 
       
  1254     case QPaintBufferPrivate::Cmd_DrawEllipseI: {
       
  1255 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
  1256         qDebug() << " -> Cmd_DrawEllipseI, offset: " << cmd.offset;
       
  1257 #endif
       
  1258         painter->drawEllipse(*(QRect *)(d->ints.constData() + cmd.offset));
       
  1259         break; }
       
  1260 
       
  1261     case QPaintBufferPrivate::Cmd_DrawLineF: {
       
  1262 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
  1263         qDebug() << " -> Cmd_DrawLineF, offset: " << cmd.offset << " size: " << cmd.size;
       
  1264 #endif
       
  1265         painter->drawLines((QLineF *)(d->floats.constData() + cmd.offset), cmd.size);
       
  1266         break; }
       
  1267 
       
  1268     case QPaintBufferPrivate::Cmd_DrawLineI: {
       
  1269 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
  1270         qDebug() << " -> Cmd_DrawLineI, offset: " << cmd.offset << " size: " << cmd.size;
       
  1271 #endif
       
  1272         painter->drawLines((QLine *)(d->ints.constData() + cmd.offset), cmd.size);
       
  1273         break; }
       
  1274 
       
  1275     case QPaintBufferPrivate::Cmd_DrawPointsF: {
       
  1276 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
  1277         qDebug() << " -> Cmd_DrawPointsF, offset: " << cmd.offset << " size: " << cmd.size;
       
  1278 #endif
       
  1279         painter->drawPoints((QPointF *)(d->floats.constData() + cmd.offset), cmd.size);
       
  1280         break; }
       
  1281 
       
  1282     case QPaintBufferPrivate::Cmd_DrawPointsI: {
       
  1283 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
  1284         qDebug() << " -> Cmd_DrawPointsI, offset: " << cmd.offset << " size: " << cmd.size;
       
  1285 #endif
       
  1286         painter->drawPoints((QPoint *)(d->ints.constData() + cmd.offset), cmd.size);
       
  1287         break; }
       
  1288 
       
  1289     case QPaintBufferPrivate::Cmd_DrawPixmapRect: {
       
  1290         QPixmap pm(d->variants.at(cmd.offset).value<QPixmap>());
       
  1291         QRectF r(d->floats.at(cmd.extra), d->floats.at(cmd.extra+1),
       
  1292                  d->floats.at(cmd.extra+2), d->floats.at(cmd.extra+3));
       
  1293 
       
  1294         QRectF sr(d->floats.at(cmd.extra+4), d->floats.at(cmd.extra+5),
       
  1295                   d->floats.at(cmd.extra+6), d->floats.at(cmd.extra+7));
       
  1296 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
  1297         qDebug() << " -> Cmd_DrawPixmapRect:" << r << sr;
       
  1298 #endif
       
  1299         painter->drawPixmap(r, pm, sr);
       
  1300         break; }
       
  1301 
       
  1302     case QPaintBufferPrivate::Cmd_DrawPixmapPos: {
       
  1303         QPixmap pm(d->variants.at(cmd.offset).value<QPixmap>());
       
  1304         QPointF pos(d->floats.at(cmd.extra), d->floats.at(cmd.extra+1));
       
  1305 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
  1306         qDebug() << " -> Cmd_DrawPixmapPos:" << pos;
       
  1307 #endif
       
  1308         painter->drawPixmap(pos, pm);
       
  1309         break; }
       
  1310 
       
  1311     case QPaintBufferPrivate::Cmd_DrawTiledPixmap: {
       
  1312         QPixmap pm(d->variants.at(cmd.offset).value<QPixmap>());
       
  1313         QRectF r(d->floats.at(cmd.extra), d->floats.at(cmd.extra+1),
       
  1314                  d->floats.at(cmd.extra+2), d->floats.at(cmd.extra+3));
       
  1315 
       
  1316         QPointF offset(d->floats.at(cmd.extra+4), d->floats.at(cmd.extra+5));
       
  1317 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
  1318         qDebug() << " -> Cmd_DrawTiledPixmap:" << r << offset;
       
  1319 #endif
       
  1320         painter->drawTiledPixmap(r, pm, offset);
       
  1321         break; }
       
  1322 
       
  1323     case QPaintBufferPrivate::Cmd_DrawImageRect: {
       
  1324         QImage image(d->variants.at(cmd.offset).value<QImage>());
       
  1325         QRectF r(d->floats.at(cmd.extra), d->floats.at(cmd.extra+1),
       
  1326                  d->floats.at(cmd.extra+2), d->floats.at(cmd.extra+3));
       
  1327         QRectF sr(d->floats.at(cmd.extra+4), d->floats.at(cmd.extra+5),
       
  1328                   d->floats.at(cmd.extra+6), d->floats.at(cmd.extra+7));
       
  1329 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
  1330         qDebug() << " -> Cmd_DrawImageRect:" << r << sr;
       
  1331 #endif
       
  1332         painter->drawImage(r, image, sr);
       
  1333         break; }
       
  1334 
       
  1335     case QPaintBufferPrivate::Cmd_DrawImagePos: {
       
  1336         QImage image(d->variants.at(cmd.offset).value<QImage>());
       
  1337         QPointF pos(d->floats.at(cmd.extra), d->floats.at(cmd.extra+1));
       
  1338 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
  1339         qDebug() << " -> Cmd_DrawImagePos:" << pos;
       
  1340 #endif
       
  1341         painter->drawImage(pos, image);
       
  1342         break; }
       
  1343 
       
  1344     case QPaintBufferPrivate::Cmd_DrawRectF: {
       
  1345 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
  1346         qDebug() << " -> Cmd_DrawRectF, offset: " << cmd.offset;
       
  1347 #endif
       
  1348         painter->drawRects((QRectF *)(d->floats.constData() + cmd.offset), cmd.size);
       
  1349         break; }
       
  1350 
       
  1351     case QPaintBufferPrivate::Cmd_DrawRectI: {
       
  1352 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
  1353         qDebug() << " -> Cmd_DrawRectI, offset: " << cmd.offset;
       
  1354 #endif
       
  1355         painter->drawRects((QRect *)(d->ints.constData() + cmd.offset), cmd.size);
       
  1356         break; }
       
  1357 
       
  1358     case QPaintBufferPrivate::Cmd_FillRectBrush: {
       
  1359         QBrush brush = qVariantValue<QBrush>(d->variants.at(cmd.extra));
       
  1360         QRectF *rect = (QRectF *)(d->floats.constData() + cmd.offset);
       
  1361 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
  1362         qDebug() << " -> Cmd_FillRectBrush, offset: " << cmd.offset << " rect: " << *rect << " brush: " << brush;
       
  1363 #endif
       
  1364         painter->fillRect(*rect, brush);
       
  1365         break; }
       
  1366 
       
  1367     case QPaintBufferPrivate::Cmd_FillRectColor: {
       
  1368         QColor color = qVariantValue<QColor>(d->variants.at(cmd.extra));
       
  1369         QRectF *rect = (QRectF *)(d->floats.constData() + cmd.offset);
       
  1370 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
  1371         qDebug() << " -> Cmd_FillRectBrush, offset: " << cmd.offset << " rect: " << *rect << " color: " << color;
       
  1372 #endif
       
  1373         painter->fillRect(*rect, color);
       
  1374         break; }
       
  1375 
       
  1376     case QPaintBufferPrivate::Cmd_SetClipEnabled: {
       
  1377         bool clipEnabled = d->variants.at(cmd.offset).toBool();
       
  1378 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
  1379         qDebug() << " -> Cmd_SetClipEnabled:" << clipEnabled;
       
  1380 #endif
       
  1381         painter->setClipping(clipEnabled);
       
  1382         break; }
       
  1383 
       
  1384     case QPaintBufferPrivate::Cmd_ClipVectorPath: {
       
  1385         QVectorPathCmd path(d, cmd);
       
  1386 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
  1387         qDebug() << " -> Cmd_ClipVectorPath:" << path().elementCount();
       
  1388 #endif
       
  1389         painter->setClipPath(path().convertToPainterPath(), Qt::ClipOperation(cmd.extra));
       
  1390         break; }
       
  1391 
       
  1392 
       
  1393     case QPaintBufferPrivate::Cmd_ClipRect: {
       
  1394         QRect rect(QPoint(d->ints.at(cmd.offset), d->ints.at(cmd.offset + 1)),
       
  1395                    QPoint(d->ints.at(cmd.offset + 2), d->ints.at(cmd.offset + 3)));
       
  1396 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
  1397         qDebug() << " -> Cmd_ClipRect:" << rect << cmd.extra;
       
  1398 #endif
       
  1399         painter->setClipRect(rect, Qt::ClipOperation(cmd.extra));
       
  1400         break; }
       
  1401 
       
  1402     case QPaintBufferPrivate::Cmd_ClipRegion: {
       
  1403         QRegion region(d->variants.at(cmd.offset).value<QRegion>());
       
  1404 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
  1405         qDebug() << " -> Cmd_ClipRegion:" << region.boundingRect() << cmd.extra;
       
  1406 #endif
       
  1407         painter->setClipRegion(region, Qt::ClipOperation(cmd.extra));
       
  1408         break; }
       
  1409 
       
  1410     case QPaintBufferPrivate::Cmd_DrawText: {
       
  1411         QPointF pos(d->floats.at(cmd.extra), d->floats.at(cmd.extra+1));
       
  1412         QList<QVariant> variants(d->variants.at(cmd.offset).value<QList<QVariant> >());
       
  1413 
       
  1414         QFont font(variants.at(0).value<QFont>());
       
  1415         QString text(variants.at(1).value<QString>());
       
  1416 
       
  1417         painter->setFont(font);
       
  1418         painter->drawText(pos, text);
       
  1419         break; }
       
  1420 
       
  1421     case QPaintBufferPrivate::Cmd_DrawTextItem: {
       
  1422         QPointF pos(d->floats.at(cmd.extra), d->floats.at(cmd.extra+1));
       
  1423         QTextItemIntCopy *tiCopy = reinterpret_cast<QTextItemIntCopy *>(qVariantValue<void *>(d->variants.at(cmd.offset)));
       
  1424         QTextItemInt &ti = (*tiCopy)();
       
  1425         QString text(ti.text());
       
  1426 
       
  1427 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
  1428         qDebug() << " -> Cmd_DrawTextItem:" << pos << " " << text << " " << scaleFactor;
       
  1429 #endif
       
  1430 
       
  1431         QFont font(ti.font());
       
  1432         font.setUnderline(false);
       
  1433         font.setStrikeOut(false);
       
  1434         font.setOverline(false);
       
  1435 
       
  1436         const QTextItemInt &si = static_cast<const QTextItemInt &>(ti);
       
  1437         qreal justificationWidth = 0;
       
  1438         if (si.justified)
       
  1439             justificationWidth = si.width.toReal();
       
  1440         qreal scaleFactor = font.d->dpi/qreal(qt_defaultDpiY());
       
  1441 
       
  1442         if (scaleFactor != 1.0) {
       
  1443             QFont fnt(font);
       
  1444             QFakeDevice fake;
       
  1445             fake.setDpiX(qRound(scaleFactor*qt_defaultDpiX()));
       
  1446             fake.setDpiY(qRound(scaleFactor*qt_defaultDpiY()));
       
  1447             font = QFont(fnt, &fake);
       
  1448         }
       
  1449 
       
  1450         int flags = Qt::TextSingleLine | Qt::TextDontClip | Qt::TextForceLeftToRight;
       
  1451         QSizeF size(1, 1);
       
  1452         if (justificationWidth > 0) {
       
  1453             size.setWidth(justificationWidth);
       
  1454             flags |= Qt::TextJustificationForced;
       
  1455             flags |= Qt::AlignJustify;
       
  1456         }
       
  1457 
       
  1458         QFontMetrics fm(font);
       
  1459         QPointF pt(pos.x(), pos.y() - fm.ascent());
       
  1460         qt_format_text(font, QRectF(pt, size), flags, /*opt*/0,
       
  1461                        text, /*brect=*/0, /*tabstops=*/0, /*...*/0, /*tabarraylen=*/0, painter);
       
  1462         break; }
       
  1463     case QPaintBufferPrivate::Cmd_SystemStateChanged: {
       
  1464         QRegion systemClip(d->variants.at(cmd.offset).value<QRegion>());
       
  1465 
       
  1466 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
  1467         qDebug() << " -> Cmd_SystemStateChanged:" << systemClip;
       
  1468 #endif
       
  1469 
       
  1470         painter->paintEngine()->setSystemClip(systemClip);
       
  1471         painter->paintEngine()->d_ptr->systemStateChanged();
       
  1472         break; }
       
  1473     }
       
  1474 }
       
  1475 
       
  1476 void QPaintEngineExReplayer::process(const QPaintBufferCommand &cmd)
       
  1477 {
       
  1478     Q_ASSERT(painter->paintEngine()->isExtended());
       
  1479     QPaintEngineEx *xengine = static_cast<QPaintEngineEx *>(painter->paintEngine());
       
  1480 
       
  1481     switch (cmd.id) {
       
  1482     case QPaintBufferPrivate::Cmd_SetBrushOrigin: {
       
  1483 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
  1484         qDebug() << " -> ExCmd_SetBrushOrigin: " << d->variants.at(cmd.offset).toPointF();
       
  1485 #endif
       
  1486         xengine->state()->brushOrigin = d->variants.at(cmd.offset).toPointF();
       
  1487         xengine->brushOriginChanged();
       
  1488         break; }
       
  1489 
       
  1490     case QPaintBufferPrivate::Cmd_SetCompositionMode: {
       
  1491         QPainter::CompositionMode mode = (QPainter::CompositionMode) cmd.extra;
       
  1492 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
  1493         qDebug() << " -> ExCmd_SetCompositionMode, mode: " << mode;
       
  1494 #endif
       
  1495         xengine->state()->composition_mode = mode;
       
  1496         xengine->compositionModeChanged();
       
  1497         break; }
       
  1498 
       
  1499     case QPaintBufferPrivate::Cmd_SetOpacity: {
       
  1500 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
  1501         qDebug() << " -> ExCmd_SetOpacity: " << d->variants.at(cmd.offset).toDouble();
       
  1502 #endif
       
  1503         xengine->state()->opacity = d->variants.at(cmd.offset).toDouble();
       
  1504         xengine->opacityChanged();
       
  1505         break; }
       
  1506 
       
  1507     case QPaintBufferPrivate::Cmd_DrawVectorPath: {
       
  1508 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
  1509         qDebug() << " -> ExCmd_DrawVectorPath: size: " << cmd.size
       
  1510 //                 << ", hints:" << d->ints[cmd.offset2+cmd.size]
       
  1511                  << "pts/elms:" << cmd.offset << cmd.offset2;
       
  1512 #endif
       
  1513         QVectorPathCmd path(d, cmd);
       
  1514         xengine->draw(path());
       
  1515         break; }
       
  1516 
       
  1517     case QPaintBufferPrivate::Cmd_StrokeVectorPath: {
       
  1518         QPen pen = qVariantValue<QPen>(d->variants.at(cmd.extra));
       
  1519 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
  1520         qDebug() << " -> ExCmd_StrokeVectorPath: size: " << cmd.size
       
  1521 //                 << ", hints:" << d->ints[cmd.offset2+cmd.size]
       
  1522                  << "pts/elms:" << cmd.offset << cmd.offset2;
       
  1523 #endif
       
  1524         QVectorPathCmd path(d, cmd);
       
  1525         xengine->stroke(path(), pen);
       
  1526         break; }
       
  1527 
       
  1528     case QPaintBufferPrivate::Cmd_FillVectorPath: {
       
  1529         QBrush brush = qVariantValue<QBrush>(d->variants.at(cmd.extra));
       
  1530 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
  1531         qDebug() << " -> ExCmd_FillVectorPath: size: " << cmd.size
       
  1532 //                 << ", hints:" << d->ints[cmd.offset2+cmd.size]
       
  1533                  << "pts/elms:" << cmd.offset << cmd.offset2 << brush;
       
  1534 #endif
       
  1535         QVectorPathCmd path(d, cmd);
       
  1536         xengine->fill(path(), brush);
       
  1537         break; }
       
  1538 
       
  1539     case QPaintBufferPrivate::Cmd_FillRectBrush: {
       
  1540         QBrush brush = qVariantValue<QBrush>(d->variants.at(cmd.extra));
       
  1541         QRectF *rect = (QRectF *)(d->floats.constData() + cmd.offset);
       
  1542 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
  1543         qDebug() << " -> ExCmd_FillRectBrush, offset: " << cmd.offset << " rect: " << *rect << " brush: " << brush;
       
  1544 #endif
       
  1545         xengine->fillRect(*rect, brush);
       
  1546         break; }
       
  1547 
       
  1548     case QPaintBufferPrivate::Cmd_FillRectColor: {
       
  1549         QColor color = qVariantValue<QColor>(d->variants.at(cmd.extra));
       
  1550         QRectF *rect = (QRectF *)(d->floats.constData() + cmd.offset);
       
  1551 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
  1552         qDebug() << " -> ExCmd_FillRectBrush, offset: " << cmd.offset << " rect: " << *rect << " color: " << color;
       
  1553 #endif
       
  1554         xengine->fillRect(*rect, color);
       
  1555         break; }
       
  1556 
       
  1557     case QPaintBufferPrivate::Cmd_DrawPolygonF: {
       
  1558 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
  1559         qDebug() << " -> ExCmd_DrawPolygonF, offset: " << cmd.offset << " size: " << cmd.size
       
  1560                  << " mode: " << cmd.extra
       
  1561                  << d->floats.at(cmd.offset)
       
  1562                  << d->floats.at(cmd.offset+1);
       
  1563 #endif
       
  1564         xengine->drawPolygon((QPointF *) (d->floats.constData() + cmd.offset), cmd.size,
       
  1565                              (QPaintEngine::PolygonDrawMode) cmd.extra);
       
  1566         break; }
       
  1567 
       
  1568     case QPaintBufferPrivate::Cmd_DrawPolygonI: {
       
  1569 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
  1570         qDebug() << " -> ExCmd_DrawPolygonI, offset: " << cmd.offset << " size: " << cmd.size
       
  1571                  << " mode: " << cmd.extra
       
  1572                  << d->ints.at(cmd.offset)
       
  1573                  << d->ints.at(cmd.offset+1);
       
  1574 #endif
       
  1575         xengine->drawPolygon((QPoint *) (d->ints.constData() + cmd.offset), cmd.size,
       
  1576                              (QPaintEngine::PolygonDrawMode) cmd.extra);
       
  1577         break; }
       
  1578 
       
  1579     case QPaintBufferPrivate::Cmd_DrawEllipseF: {
       
  1580 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
  1581         qDebug() << " -> ExCmd_DrawEllipseF, offset: " << cmd.offset;
       
  1582 #endif
       
  1583         xengine->drawEllipse(*(QRectF *)(d->floats.constData() + cmd.offset));
       
  1584         break; }
       
  1585 
       
  1586     case QPaintBufferPrivate::Cmd_DrawEllipseI: {
       
  1587 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
  1588         qDebug() << " -> ExCmd_DrawEllipseI, offset: " << cmd.offset;
       
  1589 #endif
       
  1590         xengine->drawEllipse(*(QRect *)(d->ints.constData() + cmd.offset));
       
  1591         break; }
       
  1592 
       
  1593     case QPaintBufferPrivate::Cmd_DrawLineF: {
       
  1594 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
  1595         qDebug() << " -> ExCmd_DrawLineF, offset: " << cmd.offset << " size: " << cmd.size;
       
  1596 #endif
       
  1597         xengine->drawLines((QLineF *)(d->floats.constData() + cmd.offset), cmd.size);
       
  1598         break; }
       
  1599 
       
  1600     case QPaintBufferPrivate::Cmd_DrawLineI: {
       
  1601 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
  1602         qDebug() << " -> ExCmd_DrawLineI, offset: " << cmd.offset << " size: " << cmd.size;
       
  1603 #endif
       
  1604         xengine->drawLines((QLine *)(d->ints.constData() + cmd.offset), cmd.size);
       
  1605         break; }
       
  1606 
       
  1607     case QPaintBufferPrivate::Cmd_DrawPointsF: {
       
  1608 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
  1609         qDebug() << " -> ExCmd_DrawPointsF, offset: " << cmd.offset << " size: " << cmd.size;
       
  1610 #endif
       
  1611         xengine->drawPoints((QPointF *)(d->floats.constData() + cmd.offset), cmd.size);
       
  1612         break; }
       
  1613 
       
  1614     case QPaintBufferPrivate::Cmd_DrawPointsI: {
       
  1615 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
  1616         qDebug() << " -> ExCmd_DrawPointsI, offset: " << cmd.offset << " size: " << cmd.size;
       
  1617 #endif
       
  1618         xengine->drawPoints((QPoint *)(d->ints.constData() + cmd.offset), cmd.size);
       
  1619         break; }
       
  1620 
       
  1621     case QPaintBufferPrivate::Cmd_DrawPolylineF: {
       
  1622 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
  1623         qDebug() << " -> ExCmd_DrawPolylineF, offset: " << cmd.offset << " size: " << cmd.size;
       
  1624 #endif
       
  1625         xengine->drawPolygon((QPointF *) (d->floats.constData() + cmd.offset), cmd.size, QPaintEngine::PolylineMode);
       
  1626         break; }
       
  1627 
       
  1628     case QPaintBufferPrivate::Cmd_DrawPolylineI: {
       
  1629 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
  1630         qDebug() << " -> ExCmd_DrawPolylineI, offset: " << cmd.offset << " size: " << cmd.size;
       
  1631 #endif
       
  1632         xengine->drawPolygon((QPoint *) (d->ints.constData() + cmd.offset), cmd.size, QPaintEngine::PolylineMode);
       
  1633         break; }
       
  1634 
       
  1635     case QPaintBufferPrivate::Cmd_DrawRectF: {
       
  1636 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
  1637         qDebug() << " -> ExCmd_DrawRectF, offset: " << cmd.offset << " size: " << cmd.size;
       
  1638 #endif
       
  1639         xengine->drawRects((QRectF *) (d->floats.constData() + cmd.offset), cmd.size);
       
  1640         break; }
       
  1641 
       
  1642     case QPaintBufferPrivate::Cmd_DrawRectI: {
       
  1643 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
  1644         qDebug() << " -> ExCmd_DrawRectI, offset: " << cmd.offset << " size: " << cmd.size;
       
  1645 #endif
       
  1646         xengine->drawRects((QRect *) (d->ints.constData() + cmd.offset), cmd.size);
       
  1647         break; }
       
  1648 
       
  1649     case QPaintBufferPrivate::Cmd_SetClipEnabled: {
       
  1650         bool clipEnabled = d->variants.at(cmd.offset).toBool();
       
  1651 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
  1652         qDebug() << " -> ExCmd_SetClipEnabled:" << clipEnabled;
       
  1653 #endif
       
  1654         xengine->state()->clipEnabled = clipEnabled;
       
  1655         xengine->clipEnabledChanged();
       
  1656         break; }
       
  1657 
       
  1658     case QPaintBufferPrivate::Cmd_ClipVectorPath: {
       
  1659         QVectorPathCmd path(d, cmd);
       
  1660 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
  1661         qDebug() << " -> ExCmd_ClipVectorPath:" << path().elementCount();
       
  1662 #endif
       
  1663         xengine->clip(path(), Qt::ClipOperation(cmd.extra));
       
  1664         break; }
       
  1665 
       
  1666 
       
  1667     case QPaintBufferPrivate::Cmd_ClipRect: {
       
  1668         QRect rect(QPoint(d->ints.at(cmd.offset), d->ints.at(cmd.offset + 1)),
       
  1669                    QPoint(d->ints.at(cmd.offset + 2), d->ints.at(cmd.offset + 3)));
       
  1670 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
  1671         qDebug() << " -> ExCmd_ClipRect:" << rect << cmd.extra;
       
  1672 #endif
       
  1673         xengine->clip(rect, Qt::ClipOperation(cmd.extra));
       
  1674         break; }
       
  1675 
       
  1676     case QPaintBufferPrivate::Cmd_ClipRegion: {
       
  1677         QRegion region(d->variants.at(cmd.offset).value<QRegion>());
       
  1678 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
  1679         qDebug() << " -> ExCmd_ClipRegion:" << region.boundingRect() << cmd.extra;
       
  1680 #endif
       
  1681         xengine->clip(region, Qt::ClipOperation(cmd.extra));
       
  1682         break; }
       
  1683 
       
  1684     default:
       
  1685         QPainterReplayer::process(cmd);
       
  1686         break;
       
  1687     }
       
  1688 }
       
  1689 
       
  1690 QPaintBufferResource::QPaintBufferResource(FreeFunc f, QObject *parent) : QObject(parent), free(f)
       
  1691 {
       
  1692     connect(QPaintBufferSignalProxy::instance(), SIGNAL(aboutToDestroy(const QPaintBufferPrivate *)), this, SLOT(remove(const QPaintBufferPrivate *)));
       
  1693 }
       
  1694 
       
  1695 QPaintBufferResource::~QPaintBufferResource()
       
  1696 {
       
  1697     for (Cache::iterator it = m_cache.begin(); it != m_cache.end(); ++it)
       
  1698         free(it.value());
       
  1699 }
       
  1700 
       
  1701 void QPaintBufferResource::insert(const QPaintBufferPrivate *key, void *value)
       
  1702 {
       
  1703     Cache::iterator it = m_cache.find(key);
       
  1704     if (it != m_cache.end()) {
       
  1705         free(it.value());
       
  1706         it.value() = value;
       
  1707     } else {
       
  1708         m_cache.insert(key, value);
       
  1709     }
       
  1710 }
       
  1711 
       
  1712 void *QPaintBufferResource::value(const QPaintBufferPrivate *key)
       
  1713 {
       
  1714     Cache::iterator it = m_cache.find(key);
       
  1715     if (it != m_cache.end())
       
  1716         return it.value();
       
  1717     return 0;
       
  1718 }
       
  1719 
       
  1720 void QPaintBufferResource::remove(const QPaintBufferPrivate *key)
       
  1721 {
       
  1722     Cache::iterator it = m_cache.find(key);
       
  1723     if (it != m_cache.end()) {
       
  1724         free(it.value());
       
  1725         m_cache.erase(it);
       
  1726     }
       
  1727 }
       
  1728 
       
  1729 QDataStream &operator<<(QDataStream &stream, const QPaintBufferCommand &command)
       
  1730 {
       
  1731     quint32 id = command.id;
       
  1732     quint32 size = command.size;
       
  1733     stream << id << size;
       
  1734     stream << command.offset << command.offset2 << command.extra;
       
  1735     return stream;
       
  1736 }
       
  1737 
       
  1738 QDataStream &operator>>(QDataStream &stream, QPaintBufferCommand &command)
       
  1739 {
       
  1740     quint32 id;
       
  1741     quint32 size;
       
  1742     stream >> id >> size;
       
  1743     stream >> command.offset >> command.offset2 >> command.extra;
       
  1744     command.id = id;
       
  1745     command.size = size;
       
  1746     return stream;
       
  1747 }
       
  1748 
       
  1749 struct QPaintBufferCacheEntry
       
  1750 {
       
  1751     QVariant::Type type;
       
  1752     quint64 cacheKey;
       
  1753 };
       
  1754 QT_END_NAMESPACE
       
  1755 Q_DECLARE_METATYPE(QPaintBufferCacheEntry)
       
  1756 QT_BEGIN_NAMESPACE
       
  1757 
       
  1758 QDataStream &operator<<(QDataStream &stream, const QPaintBufferCacheEntry &entry)
       
  1759 {
       
  1760     return stream << entry.type << entry.cacheKey;
       
  1761 }
       
  1762 
       
  1763 QDataStream &operator>>(QDataStream &stream, QPaintBufferCacheEntry &entry)
       
  1764 {
       
  1765     return stream >> entry.type >> entry.cacheKey;
       
  1766 }
       
  1767 
       
  1768 static int qRegisterPaintBufferMetaTypes()
       
  1769 {
       
  1770     qRegisterMetaType<QPaintBufferCacheEntry>();
       
  1771     qRegisterMetaTypeStreamOperators<QPaintBufferCacheEntry>("QPaintBufferCacheEntry");
       
  1772 
       
  1773     return 0; // something
       
  1774 }
       
  1775 
       
  1776 Q_CONSTRUCTOR_FUNCTION(qRegisterPaintBufferMetaTypes)
       
  1777 
       
  1778 QDataStream &operator<<(QDataStream &stream, const QPaintBuffer &buffer)
       
  1779 {
       
  1780     QHash<qint64, QPixmap> pixmaps;
       
  1781     QHash<qint64, QImage> images;
       
  1782 
       
  1783     QVector<QVariant> variants = buffer.d_ptr->variants;
       
  1784     for (int i = 0; i < variants.size(); ++i) {
       
  1785         const QVariant &v = variants.at(i);
       
  1786         if (v.type() == QVariant::Image) {
       
  1787             const QImage image(v.value<QImage>());
       
  1788             images[image.cacheKey()] = image;
       
  1789 
       
  1790             QPaintBufferCacheEntry entry;
       
  1791             entry.type = QVariant::Image;
       
  1792             entry.cacheKey = image.cacheKey();
       
  1793             variants[i] = QVariant::fromValue(entry);
       
  1794         } else if (v.type() == QVariant::Pixmap) {
       
  1795             const QPixmap pixmap(v.value<QPixmap>());
       
  1796             pixmaps[pixmap.cacheKey()] = pixmap;
       
  1797 
       
  1798             QPaintBufferCacheEntry entry;
       
  1799             entry.type = QVariant::Pixmap;
       
  1800             entry.cacheKey = pixmap.cacheKey();
       
  1801             variants[i] = QVariant::fromValue(entry);
       
  1802         }
       
  1803     }
       
  1804 
       
  1805     stream << pixmaps;
       
  1806     stream << images;
       
  1807 
       
  1808     stream << buffer.d_ptr->ints;
       
  1809     stream << buffer.d_ptr->floats;
       
  1810     stream << variants;
       
  1811     stream << buffer.d_ptr->commands;
       
  1812     stream << buffer.d_ptr->boundingRect;
       
  1813     stream << buffer.d_ptr->frames;
       
  1814 
       
  1815     return stream;
       
  1816 }
       
  1817 
       
  1818 QDataStream &operator>>(QDataStream &stream, QPaintBuffer &buffer)
       
  1819 {
       
  1820     QHash<qint64, QPixmap> pixmaps;
       
  1821     QHash<qint64, QImage> images;
       
  1822 
       
  1823     stream >> pixmaps;
       
  1824     stream >> images;
       
  1825 
       
  1826     stream >> buffer.d_ptr->ints;
       
  1827     stream >> buffer.d_ptr->floats;
       
  1828     stream >> buffer.d_ptr->variants;
       
  1829     stream >> buffer.d_ptr->commands;
       
  1830     stream >> buffer.d_ptr->boundingRect;
       
  1831     stream >> buffer.d_ptr->frames;
       
  1832 
       
  1833     QVector<QVariant> &variants = buffer.d_ptr->variants;
       
  1834     for (int i = 0; i < variants.size(); ++i) {
       
  1835         const QVariant &v = variants.at(i);
       
  1836         if (v.canConvert<QPaintBufferCacheEntry>()) {
       
  1837             QPaintBufferCacheEntry entry = v.value<QPaintBufferCacheEntry>();
       
  1838             if (entry.type == QVariant::Image)
       
  1839                 variants[i] = QVariant(images.value(entry.cacheKey));
       
  1840             else
       
  1841                 variants[i] = QVariant(pixmaps.value(entry.cacheKey));
       
  1842         }
       
  1843     }
       
  1844 
       
  1845     return stream;
       
  1846 }
       
  1847 
       
  1848 QT_END_NAMESPACE