src/gui/painting/qpaintbuffer.cpp
changeset 30 5dc02b23752f
parent 22 79de32ba3296
equal deleted inserted replaced
29:b72c6db6890b 30:5dc02b23752f
    43 #include <private/qpaintbuffer_p.h>
    43 #include <private/qpaintbuffer_p.h>
    44 //#include <private/qtextengine_p.h>
    44 //#include <private/qtextengine_p.h>
    45 #include <private/qfontengine_p.h>
    45 #include <private/qfontengine_p.h>
    46 #include <private/qemulationpaintengine_p.h>
    46 #include <private/qemulationpaintengine_p.h>
    47 #include <private/qimage_p.h>
    47 #include <private/qimage_p.h>
       
    48 #include <qstatictext.h>
       
    49 #include <private/qstatictext_p.h>
    48 
    50 
    49 #include <QDebug>
    51 #include <QDebug>
    50 
    52 
    51 // #define QPAINTBUFFER_DEBUG_DRAW
    53 // #define QPAINTBUFFER_DEBUG_DRAW
    52 
    54 
   265         printf("%5d", d->ints[i]);
   267         printf("%5d", d->ints[i]);
   266     }
   268     }
   267     printf("\n");
   269     printf("\n");
   268 #endif
   270 #endif
   269 
   271 
   270     if (painter && !painter->isActive())
   272     processCommands(painter, frameStartIndex(frame), frameEndIndex(frame));
   271         return;
   273 
       
   274 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
   275     qDebug() << "QPaintBuffer::draw() -------------------------------- DONE!";
       
   276 #endif
       
   277 }
       
   278 
       
   279 int QPaintBuffer::frameStartIndex(int frame) const
       
   280 {
       
   281     return (frame == 0) ? 0 : d_ptr->frames.at(frame - 1);
       
   282 }
       
   283 
       
   284 int QPaintBuffer::frameEndIndex(int frame) const
       
   285 {
       
   286     return (frame == d_ptr->frames.size()) ? d_ptr->commands.size() : d_ptr->frames.at(frame);
       
   287 }
       
   288 
       
   289 int QPaintBuffer::processCommands(QPainter *painter, int begin, int end) const
       
   290 {
       
   291     if (!painter || !painter->isActive())
       
   292         return 0;
   272 
   293 
   273     QPaintEngineEx *xengine = painter->paintEngine()->isExtended()
   294     QPaintEngineEx *xengine = painter->paintEngine()->isExtended()
   274                               ? (QPaintEngineEx *) painter->paintEngine() : 0;
   295                               ? (QPaintEngineEx *) painter->paintEngine() : 0;
   275     if (xengine) {
   296     if (xengine) {
   276         QPaintEngineExReplayer player;
   297         QPaintEngineExReplayer player;
   277         player.draw(*this, painter, frame);
   298         player.processCommands(*this, painter, begin, end);
   278     } else {
   299     } else {
   279         QPainterReplayer player;
   300         QPainterReplayer player;
   280         player.draw(*this, painter, frame);
   301         player.processCommands(*this, painter, begin, end);
   281     }
   302     }
   282 
   303 
   283 #ifdef QPAINTBUFFER_DEBUG_DRAW
   304     int depth = 0;
   284     qDebug() << "QPaintBuffer::draw() -------------------------------- DONE!";
   305     for (int i = begin; i < end; ++i) {
   285 #endif
   306         const QPaintBufferCommand &cmd = d_ptr->commands.at(i);
   286 }
   307         if (cmd.id == QPaintBufferPrivate::Cmd_Save)
   287 
   308             ++depth;
       
   309         else if (cmd.id == QPaintBufferPrivate::Cmd_Restore)
       
   310             --depth;
       
   311     }
       
   312     return depth;
       
   313 }
       
   314 
       
   315 #ifndef QT_NO_DEBUG_STREAM
       
   316 QString QPaintBuffer::commandDescription(int command) const
       
   317 {
       
   318     QString desc;
       
   319     QDebug debug(&desc);
       
   320 
       
   321     const QPaintBufferCommand &cmd = d_ptr->commands.at(command);
       
   322 
       
   323     switch (cmd.id) {
       
   324     case QPaintBufferPrivate::Cmd_Save: {
       
   325         debug << "Cmd_Save";
       
   326         break; }
       
   327 
       
   328     case QPaintBufferPrivate::Cmd_Restore: {
       
   329         debug << "Cmd_Restore";
       
   330         break; }
       
   331 
       
   332     case QPaintBufferPrivate::Cmd_SetBrush: {
       
   333         QBrush brush = qVariantValue<QBrush>(d_ptr->variants.at(cmd.offset));
       
   334         debug << "Cmd_SetBrush: " << brush;
       
   335         break; }
       
   336 
       
   337     case QPaintBufferPrivate::Cmd_SetBrushOrigin: {
       
   338         debug << "Cmd_SetBrushOrigin: " << d_ptr->variants.at(cmd.offset).toPointF();
       
   339         break; }
       
   340 
       
   341     case QPaintBufferPrivate::Cmd_SetCompositionMode: {
       
   342         QPainter::CompositionMode mode = (QPainter::CompositionMode) cmd.extra;
       
   343         debug << "ExCmd_SetCompositionMode, mode: " << mode;
       
   344         break; }
       
   345 
       
   346     case QPaintBufferPrivate::Cmd_SetOpacity: {
       
   347         debug << "ExCmd_SetOpacity: " << d_ptr->variants.at(cmd.offset).toDouble();
       
   348         break; }
       
   349 
       
   350     case QPaintBufferPrivate::Cmd_DrawVectorPath: {
       
   351         debug << "ExCmd_DrawVectorPath: size: " << cmd.size
       
   352 //                 << ", hints:" << d->ints[cmd.offset2+cmd.size]
       
   353                  << "pts/elms:" << cmd.offset << cmd.offset2;
       
   354         break; }
       
   355 
       
   356     case QPaintBufferPrivate::Cmd_StrokeVectorPath: {
       
   357         QPen pen = qVariantValue<QPen>(d_ptr->variants.at(cmd.extra));
       
   358         debug << "ExCmd_StrokeVectorPath: size: " << cmd.size
       
   359 //                 << ", hints:" << d->ints[cmd.offset2+cmd.size]
       
   360                  << "pts/elms:" << cmd.offset << cmd.offset2 << pen;
       
   361         break; }
       
   362 
       
   363     case QPaintBufferPrivate::Cmd_FillVectorPath: {
       
   364         QBrush brush = qVariantValue<QBrush>(d_ptr->variants.at(cmd.extra));
       
   365         debug << "ExCmd_FillVectorPath: size: " << cmd.size
       
   366 //                 << ", hints:" << d->ints[cmd.offset2+cmd.size]
       
   367                  << "pts/elms:" << cmd.offset << cmd.offset2 << brush;
       
   368         break; }
       
   369 
       
   370     case QPaintBufferPrivate::Cmd_FillRectBrush: {
       
   371         QBrush brush = qVariantValue<QBrush>(d_ptr->variants.at(cmd.extra));
       
   372         QRectF *rect = (QRectF *)(d_ptr->floats.constData() + cmd.offset);
       
   373         debug << "ExCmd_FillRectBrush, offset: " << cmd.offset << " rect: " << *rect << " brush: " << brush;
       
   374         break; }
       
   375 
       
   376     case QPaintBufferPrivate::Cmd_FillRectColor: {
       
   377         QColor color = qVariantValue<QColor>(d_ptr->variants.at(cmd.extra));
       
   378         QRectF *rect = (QRectF *)(d_ptr->floats.constData() + cmd.offset);
       
   379         debug << "ExCmd_FillRectBrush, offset: " << cmd.offset << " rect: " << *rect << " color: " << color;
       
   380         break; }
       
   381 
       
   382     case QPaintBufferPrivate::Cmd_DrawPolygonF: {
       
   383         debug << "ExCmd_DrawPolygonF, offset: " << cmd.offset << " size: " << cmd.size
       
   384                  << " mode: " << cmd.extra
       
   385                  << d_ptr->floats.at(cmd.offset)
       
   386                  << d_ptr->floats.at(cmd.offset+1);
       
   387         break; }
       
   388 
       
   389     case QPaintBufferPrivate::Cmd_DrawPolygonI: {
       
   390         debug << "ExCmd_DrawPolygonI, offset: " << cmd.offset << " size: " << cmd.size
       
   391                  << " mode: " << cmd.extra
       
   392                  << d_ptr->ints.at(cmd.offset)
       
   393                  << d_ptr->ints.at(cmd.offset+1);
       
   394         break; }
       
   395 
       
   396     case QPaintBufferPrivate::Cmd_DrawEllipseF: {
       
   397         debug << "ExCmd_DrawEllipseF, offset: " << cmd.offset;
       
   398         break; }
       
   399 
       
   400     case QPaintBufferPrivate::Cmd_DrawLineF: {
       
   401         debug << "ExCmd_DrawLineF, offset: " << cmd.offset << " size: " << cmd.size;
       
   402         break; }
       
   403 
       
   404     case QPaintBufferPrivate::Cmd_DrawLineI: {
       
   405         debug << "ExCmd_DrawLineI, offset: " << cmd.offset << " size: " << cmd.size;
       
   406         break; }
       
   407 
       
   408     case QPaintBufferPrivate::Cmd_DrawPointsF: {
       
   409         debug << "ExCmd_DrawPointsF, offset: " << cmd.offset << " size: " << cmd.size;
       
   410         break; }
       
   411 
       
   412     case QPaintBufferPrivate::Cmd_DrawPointsI: {
       
   413         debug << "ExCmd_DrawPointsI, offset: " << cmd.offset << " size: " << cmd.size;
       
   414         break; }
       
   415 
       
   416     case QPaintBufferPrivate::Cmd_DrawPolylineF: {
       
   417         debug << "ExCmd_DrawPolylineF, offset: " << cmd.offset << " size: " << cmd.size;
       
   418         break; }
       
   419 
       
   420     case QPaintBufferPrivate::Cmd_DrawPolylineI: {
       
   421         debug << "ExCmd_DrawPolylineI, offset: " << cmd.offset << " size: " << cmd.size;
       
   422         break; }
       
   423 
       
   424     case QPaintBufferPrivate::Cmd_DrawRectF: {
       
   425         debug << "ExCmd_DrawRectF, offset: " << cmd.offset << " size: " << cmd.size;
       
   426         break; }
       
   427 
       
   428     case QPaintBufferPrivate::Cmd_DrawRectI: {
       
   429         debug << "ExCmd_DrawRectI, offset: " << cmd.offset << " size: " << cmd.size;
       
   430         break; }
       
   431 
       
   432     case QPaintBufferPrivate::Cmd_SetClipEnabled: {
       
   433         bool clipEnabled = d_ptr->variants.at(cmd.offset).toBool();
       
   434         debug << "ExCmd_SetClipEnabled:" << clipEnabled;
       
   435         break; }
       
   436 
       
   437     case QPaintBufferPrivate::Cmd_ClipVectorPath: {
       
   438         QVectorPathCmd path(d_ptr, cmd);
       
   439         debug << "ExCmd_ClipVectorPath:" << path().elementCount();
       
   440         break; }
       
   441 
       
   442     case QPaintBufferPrivate::Cmd_ClipRect: {
       
   443         QRect rect(QPoint(d_ptr->ints.at(cmd.offset), d_ptr->ints.at(cmd.offset + 1)),
       
   444                    QPoint(d_ptr->ints.at(cmd.offset + 2), d_ptr->ints.at(cmd.offset + 3)));
       
   445         debug << "ExCmd_ClipRect:" << rect << cmd.extra;
       
   446         break; }
       
   447 
       
   448     case QPaintBufferPrivate::Cmd_ClipRegion: {
       
   449         QRegion region(d_ptr->variants.at(cmd.offset).value<QRegion>());
       
   450         debug << "ExCmd_ClipRegion:" << region.boundingRect() << cmd.extra;
       
   451         break; }
       
   452 
       
   453     case QPaintBufferPrivate::Cmd_SetPen: {
       
   454         QPen pen = qVariantValue<QPen>(d_ptr->variants.at(cmd.offset));
       
   455         debug << "Cmd_SetPen: " << pen;
       
   456         break; }
       
   457 
       
   458     case QPaintBufferPrivate::Cmd_SetTransform: {
       
   459         QTransform xform = qVariantValue<QTransform>(d_ptr->variants.at(cmd.offset));
       
   460         debug << "Cmd_SetTransform, offset: " << cmd.offset << xform;
       
   461         break; }
       
   462 
       
   463     case QPaintBufferPrivate::Cmd_SetRenderHints: {
       
   464         debug << "Cmd_SetRenderHints, hints: " << cmd.extra;
       
   465         break; }
       
   466 
       
   467     case QPaintBufferPrivate::Cmd_SetBackgroundMode: {
       
   468         debug << "Cmd_SetBackgroundMode: " << cmd.extra;
       
   469         break; }
       
   470 
       
   471     case QPaintBufferPrivate::Cmd_DrawConvexPolygonF: {
       
   472         debug << "Cmd_DrawConvexPolygonF, offset: " << cmd.offset << " size: " << cmd.size;
       
   473         break; }
       
   474 
       
   475     case QPaintBufferPrivate::Cmd_DrawConvexPolygonI: {
       
   476         debug << "Cmd_DrawConvexPolygonI, offset: " << cmd.offset << " size: " << cmd.size;
       
   477         break; }
       
   478 
       
   479     case QPaintBufferPrivate::Cmd_DrawEllipseI: {
       
   480         debug << "Cmd_DrawEllipseI, offset: " << cmd.offset;
       
   481         break; }
       
   482 
       
   483     case QPaintBufferPrivate::Cmd_DrawPixmapRect: {
       
   484         QPixmap pm(d_ptr->variants.at(cmd.offset).value<QPixmap>());
       
   485         QRectF r(d_ptr->floats.at(cmd.extra), d_ptr->floats.at(cmd.extra+1),
       
   486                  d_ptr->floats.at(cmd.extra+2), d_ptr->floats.at(cmd.extra+3));
       
   487 
       
   488         QRectF sr(d_ptr->floats.at(cmd.extra+4), d_ptr->floats.at(cmd.extra+5),
       
   489                   d_ptr->floats.at(cmd.extra+6), d_ptr->floats.at(cmd.extra+7));
       
   490         debug << "Cmd_DrawPixmapRect:" << r << sr << pm.size();
       
   491         break; }
       
   492 
       
   493     case QPaintBufferPrivate::Cmd_DrawPixmapPos: {
       
   494         QPixmap pm(d_ptr->variants.at(cmd.offset).value<QPixmap>());
       
   495         QPointF pos(d_ptr->floats.at(cmd.extra), d_ptr->floats.at(cmd.extra+1));
       
   496         debug << "Cmd_DrawPixmapPos:" << pos << pm.size();
       
   497         break; }
       
   498 
       
   499     case QPaintBufferPrivate::Cmd_DrawTiledPixmap: {
       
   500         QPixmap pm(d_ptr->variants.at(cmd.offset).value<QPixmap>());
       
   501         QRectF r(d_ptr->floats.at(cmd.extra), d_ptr->floats.at(cmd.extra+1),
       
   502                  d_ptr->floats.at(cmd.extra+2), d_ptr->floats.at(cmd.extra+3));
       
   503 
       
   504         QPointF offset(d_ptr->floats.at(cmd.extra+4), d_ptr->floats.at(cmd.extra+5));
       
   505         debug << "Cmd_DrawTiledPixmap:" << r << offset << pm.size();
       
   506         break; }
       
   507 
       
   508     case QPaintBufferPrivate::Cmd_DrawImageRect: {
       
   509         QImage image(d_ptr->variants.at(cmd.offset).value<QImage>());
       
   510         QRectF r(d_ptr->floats.at(cmd.extra), d_ptr->floats.at(cmd.extra+1),
       
   511                  d_ptr->floats.at(cmd.extra+2), d_ptr->floats.at(cmd.extra+3));
       
   512         QRectF sr(d_ptr->floats.at(cmd.extra+4), d_ptr->floats.at(cmd.extra+5),
       
   513                   d_ptr->floats.at(cmd.extra+6), d_ptr->floats.at(cmd.extra+7));
       
   514         debug << "Cmd_DrawImageRect:" << r << sr << image.size();
       
   515         break; }
       
   516 
       
   517     case QPaintBufferPrivate::Cmd_DrawImagePos: {
       
   518         QImage image(d_ptr->variants.at(cmd.offset).value<QImage>());
       
   519         QPointF pos(d_ptr->floats.at(cmd.extra), d_ptr->floats.at(cmd.extra+1));
       
   520         debug << "Cmd_DrawImagePos:" << pos << image.size();
       
   521         break; }
       
   522 
       
   523     case QPaintBufferPrivate::Cmd_DrawText: {
       
   524         QPointF pos(d_ptr->floats.at(cmd.extra), d_ptr->floats.at(cmd.extra+1));
       
   525         QList<QVariant> variants(d_ptr->variants.at(cmd.offset).value<QList<QVariant> >());
       
   526 
       
   527         QFont font(variants.at(0).value<QFont>());
       
   528         QString text(variants.at(1).value<QString>());
       
   529 
       
   530         debug << "Cmd_DrawText:" << pos << text << font.family();
       
   531         break; }
       
   532 
       
   533     case QPaintBufferPrivate::Cmd_DrawTextItem: {
       
   534         QPointF pos(d_ptr->floats.at(cmd.extra), d_ptr->floats.at(cmd.extra+1));
       
   535         QTextItemIntCopy *tiCopy = reinterpret_cast<QTextItemIntCopy *>(qVariantValue<void *>(d_ptr->variants.at(cmd.offset)));
       
   536         QTextItemInt &ti = (*tiCopy)();
       
   537         QString text(ti.text());
       
   538 
       
   539         QFont font(ti.font());
       
   540         font.setUnderline(false);
       
   541         font.setStrikeOut(false);
       
   542         font.setOverline(false);
       
   543 
       
   544         const QTextItemInt &si = static_cast<const QTextItemInt &>(ti);
       
   545         qreal justificationWidth = 0;
       
   546         if (si.justified)
       
   547             justificationWidth = si.width.toReal();
       
   548 
       
   549         debug << "Cmd_DrawTextItem:" << pos << " " << text;
       
   550         break; }
       
   551     case QPaintBufferPrivate::Cmd_SystemStateChanged: {
       
   552         QRegion systemClip(d_ptr->variants.at(cmd.offset).value<QRegion>());
       
   553 
       
   554         debug << "Cmd_SystemStateChanged:" << systemClip;
       
   555         break; }
       
   556     case QPaintBufferPrivate::Cmd_Translate: {
       
   557         QPointF delta(d_ptr->floats.at(cmd.extra), d_ptr->floats.at(cmd.extra+1));
       
   558         debug << "Cmd_Translate:" << delta;
       
   559         break; }
       
   560     case QPaintBufferPrivate::Cmd_DrawStaticText: {
       
   561         debug << "Cmd_DrawStaticText";
       
   562         break; }
       
   563     }
       
   564 
       
   565     return desc;
       
   566 }
       
   567 #endif
   288 
   568 
   289 QRectF QPaintBuffer::boundingRect() const
   569 QRectF QPaintBuffer::boundingRect() const
   290 {
   570 {
   291     return d_ptr->boundingRect;
   571     return d_ptr->boundingRect;
   292 }
   572 }
   304 public:
   584 public:
   305     void systemStateChanged() {
   585     void systemStateChanged() {
   306         Q_Q(QPaintBufferEngine);
   586         Q_Q(QPaintBufferEngine);
   307         q->buffer->addCommand(QPaintBufferPrivate::Cmd_SystemStateChanged, QVariant(systemClip));
   587         q->buffer->addCommand(QPaintBufferPrivate::Cmd_SystemStateChanged, QVariant(systemClip));
   308     }
   588     }
       
   589 
       
   590     QTransform last;
   309 };
   591 };
   310 
   592 
   311 
   593 
   312 /************************************************************************
   594 /************************************************************************
   313  *
   595  *
   490     cmd->extra = state()->renderHints;
   772     cmd->extra = state()->renderHints;
   491 }
   773 }
   492 
   774 
   493 void QPaintBufferEngine::transformChanged()
   775 void QPaintBufferEngine::transformChanged()
   494 {
   776 {
       
   777     Q_D(QPaintBufferEngine);
       
   778     const QTransform &transform = state()->matrix;
       
   779 
       
   780     QTransform delta;
       
   781 
       
   782     bool invertible = false;
       
   783     if (transform.type() <= QTransform::TxScale && transform.type() == d->last.type())
       
   784         delta = transform * d->last.inverted(&invertible);
       
   785 
       
   786     d->last = transform;
       
   787 
       
   788     if (invertible && delta.type() == QTransform::TxNone)
       
   789         return;
       
   790 
       
   791     if (invertible && delta.type() == QTransform::TxTranslate) {
       
   792 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
   793         qDebug() << "QPaintBufferEngine: transformChanged (translate only) " << state()->matrix;
       
   794 #endif
       
   795         QPaintBufferCommand *cmd =
       
   796             buffer->addCommand(QPaintBufferPrivate::Cmd_Translate);
       
   797 
       
   798         qreal data[] = { delta.dx(), delta.dy() };
       
   799         cmd->extra = buffer->addData((qreal *) data, 2);
       
   800         return;
       
   801     }
       
   802 
   495     // ### accumulate, like in QBrush case...
   803     // ### accumulate, like in QBrush case...
   496     if (!buffer->commands.isEmpty()
   804     if (!buffer->commands.isEmpty()
   497         && buffer->commands.last().id == QPaintBufferPrivate::Cmd_SetTransform) {
   805         && buffer->commands.last().id == QPaintBufferPrivate::Cmd_SetTransform) {
   498 #ifdef QPAINTBUFFER_DEBUG_DRAW
   806 #ifdef QPAINTBUFFER_DEBUG_DRAW
   499         qDebug() << "QPaintBufferEngine: transformChanged (compressing) " << state()->matrix;
   807         qDebug() << "QPaintBufferEngine: transformChanged (compressing) " << state()->matrix;
   958     buffer->addData((qreal *) &s, 2);
  1266     buffer->addData((qreal *) &s, 2);
   959     if (buffer->calculateBoundingRect)
  1267     if (buffer->calculateBoundingRect)
   960         buffer->updateBoundingRect(r);
  1268         buffer->updateBoundingRect(r);
   961 }
  1269 }
   962 
  1270 
       
  1271 void QPaintBufferEngine::drawStaticTextItem(QStaticTextItem *staticTextItem)
       
  1272 {
       
  1273     QVariantList variants;
       
  1274 
       
  1275     variants << QVariant(staticTextItem->font);
       
  1276     for (int i=0; i<staticTextItem->numGlyphs; ++i) {
       
  1277         variants.append(staticTextItem->glyphs[i]);
       
  1278         variants.append(staticTextItem->glyphPositions[i].toPointF());
       
  1279     }
       
  1280 
       
  1281     buffer->addCommand(QPaintBufferPrivate::Cmd_DrawStaticText, QVariant(variants));
       
  1282 }
       
  1283 
   963 void QPaintBufferEngine::drawTextItem(const QPointF &pos, const QTextItem &ti)
  1284 void QPaintBufferEngine::drawTextItem(const QPointF &pos, const QTextItem &ti)
   964 {
  1285 {
   965 #ifdef QPAINTBUFFER_DEBUG_DRAW
  1286 #ifdef QPAINTBUFFER_DEBUG_DRAW
   966     qDebug() << "QPaintBufferEngine: drawTextItem: pos:" << pos << ti.text();
  1287     qDebug() << "QPaintBufferEngine: drawTextItem: pos:" << pos << ti.text();
   967 #endif
  1288 #endif
   997 }
  1318 }
   998 
  1319 
   999 
  1320 
  1000 void QPaintBufferEngine::setState(QPainterState *s)
  1321 void QPaintBufferEngine::setState(QPainterState *s)
  1001 {
  1322 {
       
  1323     Q_D(QPaintBufferEngine);
  1002     if (m_begin_detected) {
  1324     if (m_begin_detected) {
  1003 #ifdef QPAINTBUFFER_DEBUG_DRAW
  1325 #ifdef QPAINTBUFFER_DEBUG_DRAW
  1004             qDebug() << "QPaintBufferEngine: setState: begin, ignoring.";
  1326             qDebug() << "QPaintBufferEngine: setState: begin, ignoring.";
  1005 #endif
  1327 #endif
  1006         m_begin_detected = false;
  1328         m_begin_detected = false;
  1014 #ifdef QPAINTBUFFER_DEBUG_DRAW
  1336 #ifdef QPAINTBUFFER_DEBUG_DRAW
  1015         qDebug() << "QPaintBufferEngine: setState: restore.";
  1337         qDebug() << "QPaintBufferEngine: setState: restore.";
  1016 #endif
  1338 #endif
  1017         buffer->addCommand(QPaintBufferPrivate::Cmd_Restore);
  1339         buffer->addCommand(QPaintBufferPrivate::Cmd_Restore);
  1018     }
  1340     }
       
  1341 
       
  1342     d->last = s->matrix;
  1019 
  1343 
  1020     QPaintEngineEx::setState(s);
  1344     QPaintEngineEx::setState(s);
  1021 }
  1345 }
  1022 
  1346 
  1023 
  1347 
  1063     m_world_matrix.scale(qreal(painter->device()->logicalDpiX()) / qreal(qt_defaultDpiX()),
  1387     m_world_matrix.scale(qreal(painter->device()->logicalDpiX()) / qreal(qt_defaultDpiX()),
  1064                          qreal(painter->device()->logicalDpiY()) / qreal(qt_defaultDpiY()));
  1388                          qreal(painter->device()->logicalDpiY()) / qreal(qt_defaultDpiY()));
  1065     painter->setTransform(m_world_matrix);
  1389     painter->setTransform(m_world_matrix);
  1066 }
  1390 }
  1067 
  1391 
  1068 void QPainterReplayer::draw(const QPaintBuffer &buffer, QPainter *_painter, int frame)
  1392 void QPainterReplayer::processCommands(const QPaintBuffer &buffer, QPainter *p, int begin, int end)
  1069 {
  1393 {
  1070     d = buffer.d_ptr;
  1394     d = buffer.d_ptr;
  1071     setupTransform(_painter);
  1395     painter = p;
  1072 
  1396 
  1073     int frameStart = (frame == 0) ? 0 : d->frames.at(frame-1);
  1397     for (int cmdIndex = begin; cmdIndex < end; ++cmdIndex) {
  1074     int frameEnd = (frame == d->frames.size()) ? d->commands.size() : d->frames.at(frame);
       
  1075 
       
  1076     for (int cmdIndex=frameStart; cmdIndex<frameEnd; ++cmdIndex) {
       
  1077         const QPaintBufferCommand &cmd = d->commands.at(cmdIndex);
  1398         const QPaintBufferCommand &cmd = d->commands.at(cmdIndex);
  1078         process(cmd);
  1399         process(cmd);
  1079     }
  1400     }
  1080 }
  1401 }
  1081 
  1402 
  1135 #ifdef QPAINTBUFFER_DEBUG_DRAW
  1456 #ifdef QPAINTBUFFER_DEBUG_DRAW
  1136         qDebug() << " -> Cmd_SetTransform, offset: " << cmd.offset << xform;
  1457         qDebug() << " -> Cmd_SetTransform, offset: " << cmd.offset << xform;
  1137 #endif
  1458 #endif
  1138         painter->setTransform(xform * m_world_matrix);
  1459         painter->setTransform(xform * m_world_matrix);
  1139         break; }
  1460         break; }
       
  1461 
       
  1462     case QPaintBufferPrivate::Cmd_Translate: {
       
  1463         QPointF delta(d->floats.at(cmd.extra), d->floats.at(cmd.extra+1));
       
  1464 #ifdef QPAINTBUFFER_DEBUG_DRAW
       
  1465         qDebug() << " -> Cmd_Translate, offset: " << cmd.offset << delta;
       
  1466 #endif
       
  1467         painter->translate(delta.x(), delta.y());
       
  1468         return;
       
  1469     }
  1140 
  1470 
  1141     case QPaintBufferPrivate::Cmd_SetCompositionMode: {
  1471     case QPaintBufferPrivate::Cmd_SetCompositionMode: {
  1142         QPainter::CompositionMode mode = (QPainter::CompositionMode) cmd.extra;
  1472         QPainter::CompositionMode mode = (QPainter::CompositionMode) cmd.extra;
  1143 #ifdef QPAINTBUFFER_DEBUG_DRAW
  1473 #ifdef QPAINTBUFFER_DEBUG_DRAW
  1144         qDebug() << " -> Cmd_SetCompositionMode, mode: " << mode;
  1474         qDebug() << " -> Cmd_SetCompositionMode, mode: " << mode;
  1423 #ifdef QPAINTBUFFER_DEBUG_DRAW
  1753 #ifdef QPAINTBUFFER_DEBUG_DRAW
  1424         qDebug() << " -> Cmd_ClipRegion:" << region.boundingRect() << cmd.extra;
  1754         qDebug() << " -> Cmd_ClipRegion:" << region.boundingRect() << cmd.extra;
  1425 #endif
  1755 #endif
  1426         painter->setClipRegion(region, Qt::ClipOperation(cmd.extra));
  1756         painter->setClipRegion(region, Qt::ClipOperation(cmd.extra));
  1427         break; }
  1757         break; }
       
  1758         
       
  1759     case QPaintBufferPrivate::Cmd_DrawStaticText: {
       
  1760             
       
  1761             QVariantList variants(d->variants.at(cmd.offset).value<QVariantList>());
       
  1762             
       
  1763             QFont font = variants.at(0).value<QFont>();
       
  1764 
       
  1765             QVector<quint32> glyphs;
       
  1766             QVector<QPointF> positions;
       
  1767 
       
  1768             for (int i=0; i<(variants.size() - 1) / 2; ++i) {
       
  1769                 glyphs.append(variants.at(i*2 + 1).toUInt());
       
  1770                 positions.append(variants.at(i*2 + 2).toPointF());
       
  1771             }
       
  1772 
       
  1773             painter->setFont(font);
       
  1774 
       
  1775             qt_draw_glyphs(painter, glyphs.constData(), positions.constData(), glyphs.size());
       
  1776             
       
  1777         break;
       
  1778     }
  1428 
  1779 
  1429     case QPaintBufferPrivate::Cmd_DrawText: {
  1780     case QPaintBufferPrivate::Cmd_DrawText: {
  1430         QPointF pos(d->floats.at(cmd.extra), d->floats.at(cmd.extra+1));
  1781         QPointF pos(d->floats.at(cmd.extra), d->floats.at(cmd.extra+1));
  1431         QList<QVariant> variants(d->variants.at(cmd.offset).value<QList<QVariant> >());
  1782         QList<QVariant> variants(d->variants.at(cmd.offset).value<QList<QVariant> >());
  1432 
  1783 
  1768 struct QPaintBufferCacheEntry
  2119 struct QPaintBufferCacheEntry
  1769 {
  2120 {
  1770     QVariant::Type type;
  2121     QVariant::Type type;
  1771     quint64 cacheKey;
  2122     quint64 cacheKey;
  1772 };
  2123 };
       
  2124 
       
  2125 struct QPaintBufferCacheEntryV2
       
  2126 {
       
  2127     enum Type {
       
  2128         ImageKey,
       
  2129         PixmapKey
       
  2130     };
       
  2131 
       
  2132     struct Flags {
       
  2133         uint type : 8;
       
  2134         uint key : 24;
       
  2135     };
       
  2136 
       
  2137     union {
       
  2138         Flags flags;
       
  2139         uint bits;
       
  2140     };
       
  2141 };
       
  2142 
  1773 QT_END_NAMESPACE
  2143 QT_END_NAMESPACE
  1774 Q_DECLARE_METATYPE(QPaintBufferCacheEntry)
  2144 Q_DECLARE_METATYPE(QPaintBufferCacheEntry)
       
  2145 Q_DECLARE_METATYPE(QPaintBufferCacheEntryV2)
  1775 QT_BEGIN_NAMESPACE
  2146 QT_BEGIN_NAMESPACE
  1776 
  2147 
  1777 QDataStream &operator<<(QDataStream &stream, const QPaintBufferCacheEntry &entry)
  2148 QDataStream &operator<<(QDataStream &stream, const QPaintBufferCacheEntry &entry)
  1778 {
  2149 {
  1779     return stream << entry.type << entry.cacheKey;
  2150     return stream << entry.type << entry.cacheKey;
  1780 }
  2151 }
  1781 
  2152 
  1782 QDataStream &operator>>(QDataStream &stream, QPaintBufferCacheEntry &entry)
  2153 QDataStream &operator>>(QDataStream &stream, QPaintBufferCacheEntry &entry)
  1783 {
  2154 {
  1784     return stream >> entry.type >> entry.cacheKey;
  2155     return stream >> entry.type >> entry.cacheKey;
       
  2156 }
       
  2157 
       
  2158 QDataStream &operator<<(QDataStream &stream, const QPaintBufferCacheEntryV2 &entry)
       
  2159 {
       
  2160     return stream << entry.bits;
       
  2161 }
       
  2162 
       
  2163 QDataStream &operator>>(QDataStream &stream, QPaintBufferCacheEntryV2 &entry)
       
  2164 {
       
  2165     return stream >> entry.bits;
  1785 }
  2166 }
  1786 
  2167 
  1787 static int qRegisterPaintBufferMetaTypes()
  2168 static int qRegisterPaintBufferMetaTypes()
  1788 {
  2169 {
  1789     qRegisterMetaType<QPaintBufferCacheEntry>();
  2170     qRegisterMetaType<QPaintBufferCacheEntry>();
  1790     qRegisterMetaTypeStreamOperators<QPaintBufferCacheEntry>("QPaintBufferCacheEntry");
  2171     qRegisterMetaTypeStreamOperators<QPaintBufferCacheEntry>("QPaintBufferCacheEntry");
       
  2172     qRegisterMetaType<QPaintBufferCacheEntryV2>();
       
  2173     qRegisterMetaTypeStreamOperators<QPaintBufferCacheEntryV2>("QPaintBufferCacheEntryV2");
  1791 
  2174 
  1792     return 0; // something
  2175     return 0; // something
  1793 }
  2176 }
  1794 
  2177 
  1795 Q_CONSTRUCTOR_FUNCTION(qRegisterPaintBufferMetaTypes)
  2178 Q_CONSTRUCTOR_FUNCTION(qRegisterPaintBufferMetaTypes)
  1796 
  2179 
  1797 QDataStream &operator<<(QDataStream &stream, const QPaintBuffer &buffer)
  2180 QDataStream &operator<<(QDataStream &stream, const QPaintBuffer &buffer)
  1798 {
  2181 {
       
  2182     QHash<qint64, uint> pixmapKeys;
       
  2183     QHash<qint64, uint> imageKeys;
       
  2184 
  1799     QHash<qint64, QPixmap> pixmaps;
  2185     QHash<qint64, QPixmap> pixmaps;
  1800     QHash<qint64, QImage> images;
  2186     QHash<qint64, QImage> images;
  1801 
  2187 
  1802     QVector<QVariant> variants = buffer.d_ptr->variants;
  2188     QVector<QVariant> variants = buffer.d_ptr->variants;
  1803     for (int i = 0; i < variants.size(); ++i) {
  2189     for (int i = 0; i < variants.size(); ++i) {
  1804         const QVariant &v = variants.at(i);
  2190         const QVariant &v = variants.at(i);
  1805         if (v.type() == QVariant::Image) {
  2191         if (v.type() == QVariant::Image) {
  1806             const QImage image(v.value<QImage>());
  2192             const QImage image(v.value<QImage>());
  1807             images[image.cacheKey()] = image;
  2193 
  1808 
  2194             QPaintBufferCacheEntryV2 entry;
  1809             QPaintBufferCacheEntry entry;
  2195             entry.flags.type = QPaintBufferCacheEntryV2::ImageKey;
  1810             entry.type = QVariant::Image;
  2196 
  1811             entry.cacheKey = image.cacheKey();
  2197             QHash<qint64, uint>::iterator it = imageKeys.find(image.cacheKey());
       
  2198             if (it != imageKeys.end()) {
       
  2199                 entry.flags.key = *it;
       
  2200             } else {
       
  2201                 imageKeys[image.cacheKey()] = entry.flags.key = images.size();
       
  2202                 images[images.size()] = image;
       
  2203             }
       
  2204 
  1812             variants[i] = QVariant::fromValue(entry);
  2205             variants[i] = QVariant::fromValue(entry);
  1813         } else if (v.type() == QVariant::Pixmap) {
  2206         } else if (v.type() == QVariant::Pixmap) {
  1814             const QPixmap pixmap(v.value<QPixmap>());
  2207             const QPixmap pixmap(v.value<QPixmap>());
  1815             pixmaps[pixmap.cacheKey()] = pixmap;
  2208 
  1816 
  2209             QPaintBufferCacheEntryV2 entry;
  1817             QPaintBufferCacheEntry entry;
  2210             entry.flags.type = QPaintBufferCacheEntryV2::PixmapKey;
  1818             entry.type = QVariant::Pixmap;
  2211 
  1819             entry.cacheKey = pixmap.cacheKey();
  2212             QHash<qint64, uint>::iterator it = pixmapKeys.find(pixmap.cacheKey());
       
  2213             if (it != pixmapKeys.end()) {
       
  2214                 entry.flags.key = *it;
       
  2215             } else {
       
  2216                 pixmapKeys[pixmap.cacheKey()] = entry.flags.key = pixmaps.size();
       
  2217                 pixmaps[pixmaps.size()] = pixmap;
       
  2218             }
       
  2219 
  1820             variants[i] = QVariant::fromValue(entry);
  2220             variants[i] = QVariant::fromValue(entry);
  1821         }
  2221         }
  1822     }
  2222     }
  1823 
  2223 
  1824     stream << pixmaps;
  2224     stream << pixmaps;
  1856             QPaintBufferCacheEntry entry = v.value<QPaintBufferCacheEntry>();
  2256             QPaintBufferCacheEntry entry = v.value<QPaintBufferCacheEntry>();
  1857             if (entry.type == QVariant::Image)
  2257             if (entry.type == QVariant::Image)
  1858                 variants[i] = QVariant(images.value(entry.cacheKey));
  2258                 variants[i] = QVariant(images.value(entry.cacheKey));
  1859             else
  2259             else
  1860                 variants[i] = QVariant(pixmaps.value(entry.cacheKey));
  2260                 variants[i] = QVariant(pixmaps.value(entry.cacheKey));
       
  2261         } else if (v.canConvert<QPaintBufferCacheEntryV2>()) {
       
  2262             QPaintBufferCacheEntryV2 entry = v.value<QPaintBufferCacheEntryV2>();
       
  2263 
       
  2264             if (entry.flags.type == QPaintBufferCacheEntryV2::ImageKey)
       
  2265                 variants[i] = QVariant(images.value(entry.flags.key));
       
  2266             else if (entry.flags.type == QPaintBufferCacheEntryV2::PixmapKey)
       
  2267                 variants[i] = QVariant(pixmaps.value(entry.flags.key));
       
  2268             else
       
  2269                 qWarning() << "operator<<(QDataStream &stream, QPaintBuffer &buffer): unrecognized cache entry type:" << entry.flags.type;
  1861         }
  2270         }
  1862     }
  2271     }
  1863 
  2272 
  1864     return stream;
  2273     return stream;
  1865 }
  2274 }