1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the QtGui module of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
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 #include <qstatictext.h>
49 #include <private/qstatictext_p.h>
50 #include <private/qrawfont_p.h>
54 // #define QPAINTBUFFER_DEBUG_DRAW
58 extern void qt_format_text(const QFont &font,
59 const QRectF &_r, int tf, const QTextOption *option, const QString& str, QRectF *brect,
60 int tabstops, int* tabarray, int tabarraylen,
63 QTextItemIntCopy::QTextItemIntCopy(const QTextItem &item)
64 : m_item(static_cast<const QTextItemInt &>(item))
66 QChar *chars = new QChar[m_item.num_chars];
67 unsigned short *logClusters = new unsigned short[m_item.num_chars];
68 memcpy(chars, m_item.chars, m_item.num_chars * sizeof(QChar));
69 memcpy(logClusters, m_item.logClusters, m_item.num_chars * sizeof(unsigned short));
71 m_item.logClusters = logClusters;
73 const int size = QGlyphLayout::spaceNeededForGlyphLayout(m_item.glyphs.numGlyphs);
74 char *glyphLayoutData = new char[size];
75 QGlyphLayout glyphs(glyphLayoutData, m_item.glyphs.numGlyphs);
76 memcpy(glyphs.offsets, m_item.glyphs.offsets, m_item.glyphs.numGlyphs * sizeof(QFixedPoint));
77 memcpy(glyphs.glyphs, m_item.glyphs.glyphs, m_item.glyphs.numGlyphs * sizeof(HB_Glyph));
78 memcpy(glyphs.advances_x, m_item.glyphs.advances_x, m_item.glyphs.numGlyphs * sizeof(QFixed));
79 memcpy(glyphs.advances_y, m_item.glyphs.advances_y, m_item.glyphs.numGlyphs * sizeof(QFixed));
80 memcpy(glyphs.justifications, m_item.glyphs.justifications, m_item.glyphs.numGlyphs * sizeof(QGlyphJustification));
81 memcpy(glyphs.attributes, m_item.glyphs.attributes, m_item.glyphs.numGlyphs * sizeof(HB_GlyphAttributes));
82 m_item.glyphs = glyphs;
87 m_item.fontEngine->ref.ref(); // Increment reference count.
90 QTextItemIntCopy::~QTextItemIntCopy()
93 delete m_item.logClusters;
94 delete m_item.glyphs.data();
95 if (!m_item.fontEngine->ref.deref())
96 delete m_item.fontEngine;
99 /************************************************************************
101 * QPaintBufferPrivate
103 ************************************************************************/
105 QPaintBufferPrivate::QPaintBufferPrivate()
106 : ref(1), engine(0), penWidthAdjustment(0)
107 , calculateBoundingRect(true)
112 QPaintBufferPrivate::~QPaintBufferPrivate()
114 for (int i = 0; i < commands.size(); ++i) {
115 const QPaintBufferCommand &cmd = commands.at(i);
116 if (cmd.id == QPaintBufferPrivate::Cmd_DrawTextItem)
117 delete reinterpret_cast<QTextItemIntCopy *>(qvariant_cast<void *>(variants.at(cmd.offset)));
122 inline void QPaintBufferPrivate::updateBoundingRect(const QRectF &br)
124 // transform to device coords and adjust for pen width
125 Q_ASSERT(engine && engine->painter());
126 QPainter *painter = engine->painter();
127 const QTransform transform = painter->transform();
128 QRectF devRect = transform.mapRect(br);
129 if (penWidthAdjustment > 0) {
130 devRect = devRect.adjusted(-penWidthAdjustment, -penWidthAdjustment,
131 penWidthAdjustment, penWidthAdjustment);
134 if (boundingRect.isEmpty()) {
135 boundingRect = devRect;
137 qreal min_x = qMin(devRect.left(), boundingRect.left());
138 qreal min_y = qMin(devRect.top(), boundingRect.top());
139 qreal max_x = qMax(devRect.right(), boundingRect.right());
140 qreal max_y = qMax(devRect.bottom(), boundingRect.bottom());
141 boundingRect = QRectF(min_x, min_y, max_x - min_x, max_y - min_y);
143 if (painter->hasClipping())
144 boundingRect &= transform.mapRect(painter->clipRegion().boundingRect());
148 /************************************************************************
152 ************************************************************************/
156 QPaintBuffer::QPaintBuffer()
157 : d_ptr(new QPaintBufferPrivate)
161 QPaintBuffer::~QPaintBuffer()
163 if (!d_ptr->ref.deref())
167 QPaintBuffer::QPaintBuffer(const QPaintBuffer &other)
168 : QPaintDevice(), d_ptr(other.d_ptr)
173 QPaintEngine *QPaintBuffer::paintEngine() const
175 QPaintBufferPrivate *d = const_cast<QPaintBuffer *>(this)->d_ptr;
177 d->engine = new QPaintBufferEngine(d);
182 int QPaintBuffer::metric(PaintDeviceMetric metric) const
187 val = qCeil(d_ptr->boundingRect.width());
190 val = qCeil(d_ptr->boundingRect.height());
193 case PdmPhysicalDpiX:
194 val = qt_defaultDpiX();
197 case PdmPhysicalDpiY:
198 val = qt_defaultDpiY();
201 val = QPaintDevice::metric(metric);
207 int QPaintBuffer::devType() const
209 return QInternal::PaintBuffer;
212 QPaintBuffer &QPaintBuffer::operator=(const QPaintBuffer &other)
214 if (other.d_ptr != d_ptr) {
215 QPaintBufferPrivate *data = other.d_ptr;
217 if (d_ptr->ref.deref())
224 bool QPaintBuffer::isEmpty() const
226 return d_ptr->commands.isEmpty();
231 void QPaintBuffer::draw(QPainter *painter, int frame) const
233 #ifdef QPAINTBUFFER_DEBUG_DRAW
234 qDebug() << "QPaintBuffer::draw() --------------------------------";
236 Q_D(const QPaintBuffer);
237 printf("Float buffer:");
238 for (int i=0; i<d->floats.size(); i++) {
240 printf("\n%4d-%4d: ", i, i+9);
242 printf("%4.2f ", d->floats[i]);
246 printf("Int Buffer:");
247 for (int i=0; i<d->ints.size(); i++) {
249 printf("\n%4d-%4d: ", i, i+10);
251 printf("%5d", d->ints[i]);
256 processCommands(painter, frameStartIndex(frame), frameEndIndex(frame));
258 #ifdef QPAINTBUFFER_DEBUG_DRAW
259 qDebug() << "QPaintBuffer::draw() -------------------------------- DONE!";
263 int QPaintBuffer::frameStartIndex(int frame) const
265 return (frame == 0) ? 0 : d_ptr->frames.at(frame - 1);
268 int QPaintBuffer::frameEndIndex(int frame) const
270 return (frame == d_ptr->frames.size()) ? d_ptr->commands.size() : d_ptr->frames.at(frame);
273 int QPaintBuffer::processCommands(QPainter *painter, int begin, int end) const
275 if (!painter || !painter->isActive())
278 QPaintEngineEx *xengine = painter->paintEngine()->isExtended()
279 ? (QPaintEngineEx *) painter->paintEngine() : 0;
281 QPaintEngineExReplayer player;
282 player.processCommands(*this, painter, begin, end);
284 QPainterReplayer player;
285 player.processCommands(*this, painter, begin, end);
289 for (int i = begin; i < end; ++i) {
290 const QPaintBufferCommand &cmd = d_ptr->commands.at(i);
291 if (cmd.id == QPaintBufferPrivate::Cmd_Save)
293 else if (cmd.id == QPaintBufferPrivate::Cmd_Restore)
299 #ifndef QT_NO_DEBUG_STREAM
300 QString QPaintBuffer::commandDescription(int command) const
305 const QPaintBufferCommand &cmd = d_ptr->commands.at(command);
308 case QPaintBufferPrivate::Cmd_Save: {
312 case QPaintBufferPrivate::Cmd_Restore: {
313 debug << "Cmd_Restore";
316 case QPaintBufferPrivate::Cmd_SetBrush: {
317 QBrush brush = qvariant_cast<QBrush>(d_ptr->variants.at(cmd.offset));
318 debug << "Cmd_SetBrush: " << brush;
321 case QPaintBufferPrivate::Cmd_SetBrushOrigin: {
322 debug << "Cmd_SetBrushOrigin: " << d_ptr->variants.at(cmd.offset).toPointF();
325 case QPaintBufferPrivate::Cmd_SetCompositionMode: {
326 QPainter::CompositionMode mode = (QPainter::CompositionMode) cmd.extra;
327 debug << "ExCmd_SetCompositionMode, mode: " << mode;
330 case QPaintBufferPrivate::Cmd_SetOpacity: {
331 debug << "ExCmd_SetOpacity: " << d_ptr->variants.at(cmd.offset).toDouble();
334 case QPaintBufferPrivate::Cmd_DrawVectorPath: {
335 debug << "ExCmd_DrawVectorPath: size: " << cmd.size
336 // << ", hints:" << d->ints[cmd.offset2+cmd.size]
337 << "pts/elms:" << cmd.offset << cmd.offset2;
340 case QPaintBufferPrivate::Cmd_StrokeVectorPath: {
341 QPen pen = qvariant_cast<QPen>(d_ptr->variants.at(cmd.extra));
342 debug << "ExCmd_StrokeVectorPath: size: " << cmd.size
343 // << ", hints:" << d->ints[cmd.offset2+cmd.size]
344 << "pts/elms:" << cmd.offset << cmd.offset2 << pen;
347 case QPaintBufferPrivate::Cmd_FillVectorPath: {
348 QBrush brush = qvariant_cast<QBrush>(d_ptr->variants.at(cmd.extra));
349 debug << "ExCmd_FillVectorPath: size: " << cmd.size
350 // << ", hints:" << d->ints[cmd.offset2+cmd.size]
351 << "pts/elms:" << cmd.offset << cmd.offset2 << brush;
354 case QPaintBufferPrivate::Cmd_FillRectBrush: {
355 QBrush brush = qvariant_cast<QBrush>(d_ptr->variants.at(cmd.extra));
356 QRectF *rect = (QRectF *)(d_ptr->floats.constData() + cmd.offset);
357 debug << "ExCmd_FillRectBrush, offset: " << cmd.offset << " rect: " << *rect << " brush: " << brush;
360 case QPaintBufferPrivate::Cmd_FillRectColor: {
361 QColor color = qvariant_cast<QColor>(d_ptr->variants.at(cmd.extra));
362 QRectF *rect = (QRectF *)(d_ptr->floats.constData() + cmd.offset);
363 debug << "ExCmd_FillRectBrush, offset: " << cmd.offset << " rect: " << *rect << " color: " << color;
366 case QPaintBufferPrivate::Cmd_DrawPolygonF: {
367 debug << "ExCmd_DrawPolygonF, offset: " << cmd.offset << " size: " << cmd.size
368 << " mode: " << cmd.extra
369 << d_ptr->floats.at(cmd.offset)
370 << d_ptr->floats.at(cmd.offset+1);
373 case QPaintBufferPrivate::Cmd_DrawPolygonI: {
374 debug << "ExCmd_DrawPolygonI, offset: " << cmd.offset << " size: " << cmd.size
375 << " mode: " << cmd.extra
376 << d_ptr->ints.at(cmd.offset)
377 << d_ptr->ints.at(cmd.offset+1);
380 case QPaintBufferPrivate::Cmd_DrawEllipseF: {
381 debug << "ExCmd_DrawEllipseF, offset: " << cmd.offset;
384 case QPaintBufferPrivate::Cmd_DrawLineF: {
385 debug << "ExCmd_DrawLineF, offset: " << cmd.offset << " size: " << cmd.size;
388 case QPaintBufferPrivate::Cmd_DrawLineI: {
389 debug << "ExCmd_DrawLineI, offset: " << cmd.offset << " size: " << cmd.size;
392 case QPaintBufferPrivate::Cmd_DrawPointsF: {
393 debug << "ExCmd_DrawPointsF, offset: " << cmd.offset << " size: " << cmd.size;
396 case QPaintBufferPrivate::Cmd_DrawPointsI: {
397 debug << "ExCmd_DrawPointsI, offset: " << cmd.offset << " size: " << cmd.size;
400 case QPaintBufferPrivate::Cmd_DrawPolylineF: {
401 debug << "ExCmd_DrawPolylineF, offset: " << cmd.offset << " size: " << cmd.size;
404 case QPaintBufferPrivate::Cmd_DrawPolylineI: {
405 debug << "ExCmd_DrawPolylineI, offset: " << cmd.offset << " size: " << cmd.size;
408 case QPaintBufferPrivate::Cmd_DrawRectF: {
409 debug << "ExCmd_DrawRectF, offset: " << cmd.offset << " size: " << cmd.size;
412 case QPaintBufferPrivate::Cmd_DrawRectI: {
413 debug << "ExCmd_DrawRectI, offset: " << cmd.offset << " size: " << cmd.size;
416 case QPaintBufferPrivate::Cmd_SetClipEnabled: {
417 bool clipEnabled = d_ptr->variants.at(cmd.offset).toBool();
418 debug << "ExCmd_SetClipEnabled:" << clipEnabled;
421 case QPaintBufferPrivate::Cmd_ClipVectorPath: {
422 QVectorPathCmd path(d_ptr, cmd);
423 debug << "ExCmd_ClipVectorPath:" << path().elementCount();
426 case QPaintBufferPrivate::Cmd_ClipRect: {
427 QRect rect(QPoint(d_ptr->ints.at(cmd.offset), d_ptr->ints.at(cmd.offset + 1)),
428 QPoint(d_ptr->ints.at(cmd.offset + 2), d_ptr->ints.at(cmd.offset + 3)));
429 debug << "ExCmd_ClipRect:" << rect << cmd.extra;
432 case QPaintBufferPrivate::Cmd_ClipRegion: {
433 QRegion region(d_ptr->variants.at(cmd.offset).value<QRegion>());
434 debug << "ExCmd_ClipRegion:" << region.boundingRect() << cmd.extra;
437 case QPaintBufferPrivate::Cmd_SetPen: {
438 QPen pen = qvariant_cast<QPen>(d_ptr->variants.at(cmd.offset));
439 debug << "Cmd_SetPen: " << pen;
442 case QPaintBufferPrivate::Cmd_SetTransform: {
443 QTransform xform = qvariant_cast<QTransform>(d_ptr->variants.at(cmd.offset));
444 debug << "Cmd_SetTransform, offset: " << cmd.offset << xform;
447 case QPaintBufferPrivate::Cmd_SetRenderHints: {
448 debug << "Cmd_SetRenderHints, hints: " << cmd.extra;
451 case QPaintBufferPrivate::Cmd_SetBackgroundMode: {
452 debug << "Cmd_SetBackgroundMode: " << cmd.extra;
455 case QPaintBufferPrivate::Cmd_DrawConvexPolygonF: {
456 debug << "Cmd_DrawConvexPolygonF, offset: " << cmd.offset << " size: " << cmd.size;
459 case QPaintBufferPrivate::Cmd_DrawConvexPolygonI: {
460 debug << "Cmd_DrawConvexPolygonI, offset: " << cmd.offset << " size: " << cmd.size;
463 case QPaintBufferPrivate::Cmd_DrawEllipseI: {
464 debug << "Cmd_DrawEllipseI, offset: " << cmd.offset;
467 case QPaintBufferPrivate::Cmd_DrawPixmapRect: {
468 QPixmap pm(d_ptr->variants.at(cmd.offset).value<QPixmap>());
469 QRectF r(d_ptr->floats.at(cmd.extra), d_ptr->floats.at(cmd.extra+1),
470 d_ptr->floats.at(cmd.extra+2), d_ptr->floats.at(cmd.extra+3));
472 QRectF sr(d_ptr->floats.at(cmd.extra+4), d_ptr->floats.at(cmd.extra+5),
473 d_ptr->floats.at(cmd.extra+6), d_ptr->floats.at(cmd.extra+7));
474 debug << "Cmd_DrawPixmapRect:" << r << sr << pm.size();
477 case QPaintBufferPrivate::Cmd_DrawPixmapPos: {
478 QPixmap pm(d_ptr->variants.at(cmd.offset).value<QPixmap>());
479 QPointF pos(d_ptr->floats.at(cmd.extra), d_ptr->floats.at(cmd.extra+1));
480 debug << "Cmd_DrawPixmapPos:" << pos << pm.size();
483 case QPaintBufferPrivate::Cmd_DrawTiledPixmap: {
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));
488 QPointF offset(d_ptr->floats.at(cmd.extra+4), d_ptr->floats.at(cmd.extra+5));
489 debug << "Cmd_DrawTiledPixmap:" << r << offset << pm.size();
492 case QPaintBufferPrivate::Cmd_DrawImageRect: {
493 QImage image(d_ptr->variants.at(cmd.offset).value<QImage>());
494 QRectF r(d_ptr->floats.at(cmd.extra), d_ptr->floats.at(cmd.extra+1),
495 d_ptr->floats.at(cmd.extra+2), d_ptr->floats.at(cmd.extra+3));
496 QRectF sr(d_ptr->floats.at(cmd.extra+4), d_ptr->floats.at(cmd.extra+5),
497 d_ptr->floats.at(cmd.extra+6), d_ptr->floats.at(cmd.extra+7));
498 debug << "Cmd_DrawImageRect:" << r << sr << image.size();
501 case QPaintBufferPrivate::Cmd_DrawImagePos: {
502 QImage image(d_ptr->variants.at(cmd.offset).value<QImage>());
503 QPointF pos(d_ptr->floats.at(cmd.extra), d_ptr->floats.at(cmd.extra+1));
504 debug << "Cmd_DrawImagePos:" << pos << image.size();
507 case QPaintBufferPrivate::Cmd_DrawText: {
508 QPointF pos(d_ptr->floats.at(cmd.extra), d_ptr->floats.at(cmd.extra+1));
509 QList<QVariant> variants(d_ptr->variants.at(cmd.offset).value<QList<QVariant> >());
511 QFont font(variants.at(0).value<QFont>());
512 QString text(variants.at(1).value<QString>());
514 debug << "Cmd_DrawText:" << pos << text << font.family();
517 case QPaintBufferPrivate::Cmd_DrawTextItem: {
518 QPointF pos(d_ptr->floats.at(cmd.extra), d_ptr->floats.at(cmd.extra+1));
519 QTextItemIntCopy *tiCopy = reinterpret_cast<QTextItemIntCopy *>(qvariant_cast<void *>(d_ptr->variants.at(cmd.offset)));
520 QTextItemInt &ti = (*tiCopy)();
521 QString text(ti.text());
523 debug << "Cmd_DrawTextItem:" << pos << " " << text;
525 case QPaintBufferPrivate::Cmd_SystemStateChanged: {
526 QRegion systemClip(d_ptr->variants.at(cmd.offset).value<QRegion>());
528 debug << "Cmd_SystemStateChanged:" << systemClip;
530 case QPaintBufferPrivate::Cmd_Translate: {
531 QPointF delta(d_ptr->floats.at(cmd.extra), d_ptr->floats.at(cmd.extra+1));
532 debug << "Cmd_Translate:" << delta;
534 case QPaintBufferPrivate::Cmd_DrawStaticText: {
535 debug << "Cmd_DrawStaticText";
543 QRectF QPaintBuffer::boundingRect() const
545 return d_ptr->boundingRect;
548 void QPaintBuffer::setBoundingRect(const QRectF &rect)
550 d_ptr->boundingRect = rect;
551 d_ptr->calculateBoundingRect = false;
555 class QPaintBufferEnginePrivate : public QPaintEngineExPrivate
557 Q_DECLARE_PUBLIC(QPaintBufferEngine)
559 void systemStateChanged() {
560 Q_Q(QPaintBufferEngine);
561 q->buffer->addCommand(QPaintBufferPrivate::Cmd_SystemStateChanged, QVariant(systemClip));
568 /************************************************************************
572 ************************************************************************/
574 QPaintBufferEngine::QPaintBufferEngine(QPaintBufferPrivate *b)
575 : QPaintEngineEx(*(new QPaintBufferEnginePrivate))
577 , m_begin_detected(false)
578 , m_save_detected(false)
579 , m_stream_raw_text_items(false)
583 bool QPaintBufferEngine::begin(QPaintDevice *)
585 Q_D(QPaintBufferEngine);
587 d->systemStateChanged();
591 bool QPaintBufferEngine::end()
593 painter()->restore();
598 QPainterState *QPaintBufferEngine::createState(QPainterState *orig) const
600 #ifdef QPAINTBUFFER_DEBUG_DRAW
601 qDebug() << "QPaintBufferEngine: createState, orig=" << orig << ", current=" << state();
604 Q_ASSERT(!m_begin_detected);
605 Q_ASSERT(!m_save_detected);
608 m_begin_detected = true;
609 return new QPainterState();
611 m_save_detected = true;
612 return new QPainterState(orig);
616 void QPaintBufferEngine::clip(const QVectorPath &path, Qt::ClipOperation op)
618 #ifdef QPAINTBUFFER_DEBUG_DRAW
619 qDebug() << "QPaintBufferEngine: clip vpath:" << path.elementCount() << "op:" << op;
621 QPaintBufferCommand *cmd =
622 buffer->addCommand(QPaintBufferPrivate::Cmd_ClipVectorPath, path);
626 void QPaintBufferEngine::clip(const QRect &rect, Qt::ClipOperation op)
628 #ifdef QPAINTBUFFER_DEBUG_DRAW
629 qDebug() << "QPaintBufferEngine: clip rect:" << rect << "op:" << op;
631 QPaintBufferCommand *cmd =
632 buffer->addCommand(QPaintBufferPrivate::Cmd_ClipRect, (int *) &rect, 4, 1);
636 void QPaintBufferEngine::clip(const QRegion ®ion, Qt::ClipOperation op)
638 #ifdef QPAINTBUFFER_DEBUG_DRAW
639 qDebug() << "QPaintBufferEngine: clip region br:" << region.boundingRect() << "op:" << op;
641 QPaintBufferCommand *cmd =
642 buffer->addCommand(QPaintBufferPrivate::Cmd_ClipRegion, QVariant(region));
646 void QPaintBufferEngine::clip(const QPainterPath &path, Qt::ClipOperation op)
649 // QPaintBufferCommand *cmd =
650 // buffer->addCommand(QPaintBufferPrivate::Cmd_ClipPath, QVariant(path));
652 QPaintEngineEx::clip(path, op);
655 void QPaintBufferEngine::clipEnabledChanged()
657 #ifdef QPAINTBUFFER_DEBUG_DRAW
658 qDebug() << "QPaintBufferEngine: clip enable change" << state()->clipEnabled;
661 buffer->addCommand(QPaintBufferPrivate::Cmd_SetClipEnabled, state()->clipEnabled);
664 void QPaintBufferEngine::penChanged()
666 const QPen &pen = state()->pen;
668 if (!buffer->commands.isEmpty()
669 && buffer->commands.last().id == QPaintBufferPrivate::Cmd_SetPen) {
670 #ifdef QPAINTBUFFER_DEBUG_DRAW
671 qDebug() << "QPaintBufferEngine: penChanged (compressed)" << state()->pen;
673 buffer->variants[buffer->commands.last().offset] = pen;
677 if (buffer->calculateBoundingRect) {
678 if (pen.style() == Qt::NoPen) {
679 buffer->penWidthAdjustment = 0;
681 qreal penWidth = (pen.widthF() == 0) ? 1 : pen.widthF();
682 QPointF transformedWidth(penWidth, penWidth);
683 if (!pen.isCosmetic())
684 transformedWidth = painter()->transform().map(transformedWidth);
685 buffer->penWidthAdjustment = transformedWidth.x() / 2.0;
688 #ifdef QPAINTBUFFER_DEBUG_DRAW
689 qDebug() << "QPaintBufferEngine: penChanged" << state()->pen;
691 buffer->addCommand(QPaintBufferPrivate::Cmd_SetPen, pen);
694 void QPaintBufferEngine::brushChanged()
696 const QBrush &brush = state()->brush;
698 if (!buffer->commands.isEmpty()
699 && buffer->commands.last().id == QPaintBufferPrivate::Cmd_SetBrush) {
700 #ifdef QPAINTBUFFER_DEBUG_DRAW
701 qDebug() << "QPaintBufferEngine: brushChanged (compressed)" << state()->brush;
703 buffer->variants[buffer->commands.last().offset] = brush;
707 #ifdef QPAINTBUFFER_DEBUG_DRAW
708 qDebug() << "QPaintBufferEngine: brushChanged" << state()->brush;
710 buffer->addCommand(QPaintBufferPrivate::Cmd_SetBrush, brush);
713 void QPaintBufferEngine::brushOriginChanged()
715 #ifdef QPAINTBUFFER_DEBUG_DRAW
716 qDebug() << "QPaintBufferEngine: brush origin changed" << state()->brushOrigin;
718 buffer->addCommand(QPaintBufferPrivate::Cmd_SetBrushOrigin, state()->brushOrigin);
721 void QPaintBufferEngine::opacityChanged()
723 #ifdef QPAINTBUFFER_DEBUG_DRAW
724 qDebug() << "QPaintBufferEngine: opacity changed" << state()->opacity;
726 buffer->addCommand(QPaintBufferPrivate::Cmd_SetOpacity, state()->opacity);
729 void QPaintBufferEngine::compositionModeChanged()
731 #ifdef QPAINTBUFFER_DEBUG_DRAW
732 qDebug() << "QPaintBufferEngine: composition mode" << state()->composition_mode;
734 QPaintBufferCommand *cmd =
735 buffer->addCommand(QPaintBufferPrivate::Cmd_SetCompositionMode);
736 cmd->extra = state()->composition_mode;
739 void QPaintBufferEngine::renderHintsChanged()
741 #ifdef QPAINTBUFFER_DEBUG_DRAW
742 qDebug() << "QPaintBufferEngine: render hints changed" << state()->renderHints;
744 QPaintBufferCommand *cmd =
745 buffer->addCommand(QPaintBufferPrivate::Cmd_SetRenderHints);
746 cmd->extra = state()->renderHints;
749 void QPaintBufferEngine::transformChanged()
751 Q_D(QPaintBufferEngine);
752 const QTransform &transform = state()->matrix;
756 bool invertible = false;
757 if (transform.type() <= QTransform::TxScale && transform.type() == d->last.type())
758 delta = transform * d->last.inverted(&invertible);
762 if (invertible && delta.type() == QTransform::TxNone)
765 if (invertible && delta.type() == QTransform::TxTranslate) {
766 #ifdef QPAINTBUFFER_DEBUG_DRAW
767 qDebug() << "QPaintBufferEngine: transformChanged (translate only) " << state()->matrix;
769 QPaintBufferCommand *cmd =
770 buffer->addCommand(QPaintBufferPrivate::Cmd_Translate);
772 qreal data[] = { delta.dx(), delta.dy() };
773 cmd->extra = buffer->addData((qreal *) data, 2);
777 // ### accumulate, like in QBrush case...
778 if (!buffer->commands.isEmpty()
779 && buffer->commands.last().id == QPaintBufferPrivate::Cmd_SetTransform) {
780 #ifdef QPAINTBUFFER_DEBUG_DRAW
781 qDebug() << "QPaintBufferEngine: transformChanged (compressing) " << state()->matrix;
783 buffer->variants[buffer->commands.last().offset] = state()->matrix;
787 #ifdef QPAINTBUFFER_DEBUG_DRAW
788 qDebug() << "QPaintBufferEngine: transformChanged:" << state()->matrix;
790 buffer->addCommand(QPaintBufferPrivate::Cmd_SetTransform, state()->matrix);
793 void QPaintBufferEngine::backgroundModeChanged()
795 #ifdef QPAINTBUFFER_DEBUG_DRAW
796 qDebug() << "QPaintEngineBuffer: background mode changed" << state()->bgMode;
798 QPaintBufferCommand *cmd = buffer->addCommand(QPaintBufferPrivate::Cmd_SetBackgroundMode);
799 cmd->extra = state()->bgMode;
802 void QPaintBufferEngine::draw(const QVectorPath &path)
804 #ifdef QPAINTBUFFER_DEBUG_DRAW
805 qDebug() << "QPaintBufferEngine: draw vpath:" << path.elementCount();
808 bool hasBrush = qbrush_style(state()->brush) != Qt::NoBrush;
809 bool hasPen = qpen_style(state()->pen) != Qt::NoPen
810 && qbrush_style(qpen_brush(state()->pen)) != Qt::NoBrush;
812 if (hasPen || hasBrush)
813 buffer->addCommand(QPaintBufferPrivate::Cmd_DrawVectorPath, path);
814 #ifdef QPAINTBUFFER_DEBUG_DRAW
816 qDebug() << " - no pen or brush active, discarded...\n";
819 // if (buffer->calculateBoundingRect) {
820 // QRealRect r = path.controlPointRect();
821 // buffer->updateBoundingRect(QRectF(r.x1, r.y1, r.x2 - r.x1, r.y2 - r.y1));
825 void QPaintBufferEngine::fill(const QVectorPath &path, const QBrush &brush)
827 #ifdef QPAINTBUFFER_DEBUG_DRAW
828 qDebug() << "QPaintBufferEngine: fill vpath:" << path.elementCount() << brush;
830 QPaintBufferCommand *cmd =
831 buffer->addCommand(QPaintBufferPrivate::Cmd_FillVectorPath, path);
832 cmd->extra = buffer->addData(QVariant(brush));
833 // if (buffer->calculateBoundingRect) {
834 // QRealRect r = path.controlPointRect();
835 // buffer->updateBoundingRect(QRectF(r.x1, r.y1, r.x2 - r.x1, r.y2 - r.y1));
839 void QPaintBufferEngine::stroke(const QVectorPath &path, const QPen &pen)
841 #ifdef QPAINTBUFFER_DEBUG_DRAW
842 qDebug() << "QPaintBufferEngine: stroke vpath:" << path.elementCount() << pen;
844 QPaintBufferCommand *cmd =
845 buffer->addCommand(QPaintBufferPrivate::Cmd_StrokeVectorPath, path);
846 cmd->extra = buffer->addData(QVariant(pen));
847 // if (buffer->calculateBoundingRect) {
848 // QRealRect r = path.controlPointRect();
849 // buffer->updateBoundingRect(QRectF(r.x1, r.y1, r.x2 - r.x1, r.y2 - r.y1));
853 void QPaintBufferEngine::fillRect(const QRectF &rect, const QBrush &brush)
855 #ifdef QPAINTBUFFER_DEBUG_DRAW
856 qDebug() << "QPaintBufferEngine: fillRect brush:" << rect << brush;
858 QPaintBufferCommand *cmd =
859 buffer->addCommand(QPaintBufferPrivate::Cmd_FillRectBrush, (qreal *) &rect, 4, 1);
860 cmd->extra = buffer->addData(brush);
861 if (buffer->calculateBoundingRect)
862 buffer->updateBoundingRect(rect);
865 void QPaintBufferEngine::fillRect(const QRectF &rect, const QColor &color)
867 #ifdef QPAINTBUFFER_DEBUG_DRAW
868 qDebug() << "QPaintBufferEngine: fillRect color:" << rect << color;
870 QPaintBufferCommand *cmd =
871 buffer->addCommand(QPaintBufferPrivate::Cmd_FillRectColor, (qreal *) &rect, 4, 1);
872 cmd->extra = buffer->addData(color);
873 if (buffer->calculateBoundingRect)
874 buffer->updateBoundingRect(rect);
877 void QPaintBufferEngine::drawRects(const QRect *rects, int rectCount)
879 #ifdef QPAINTBUFFER_DEBUG_DRAW
880 qDebug() << "QPaintBufferEngine: drawRectsI:" << rectCount;
882 QPaintBufferCommand *cmd =
883 buffer->addCommand(QPaintBufferPrivate::Cmd_DrawRectI, (int *) rects, 4 * rectCount, rectCount);
884 cmd->extra = rectCount;
886 if (buffer->calculateBoundingRect) {
887 if (rectCount == 1) {
888 buffer->updateBoundingRect(rects[0]);
890 int min_x = rects[0].left();
891 int min_y = rects[0].top();
892 int max_x = rects[0].left() + rects[0].width();
893 int max_y = rects[0].top() + rects[0].height();
894 for (int i=1; i< rectCount; ++i) {
895 if (rects[i].left() < min_x)
896 min_x = rects[i].left();
897 if (rects[i].top() < min_y)
898 min_y = rects[i].top();
899 if (rects[i].right() > max_x)
900 max_x = rects[i].left() + rects[i].width();
901 if (rects[i].bottom() > max_y)
902 max_y = rects[i].top() + rects[i].height();
905 buffer->updateBoundingRect(QRectF(min_x, min_y, max_x - min_x, max_y - min_y));
910 void QPaintBufferEngine::drawRects(const QRectF *rects, int rectCount)
912 #ifdef QPAINTBUFFER_DEBUG_DRAW
913 qDebug() << "QPaintBufferEngine: drawRectsF:" << rectCount;
915 QPaintBufferCommand *cmd =
916 buffer->addCommand(QPaintBufferPrivate::Cmd_DrawRectF, (qreal *) rects, 4 * rectCount, rectCount);
917 cmd->extra = rectCount;
919 if (buffer->calculateBoundingRect) {
920 if (rectCount == 1) {
921 buffer->updateBoundingRect(rects[0]);
923 qreal min_x = rects[0].left();
924 qreal min_y = rects[0].top();
925 qreal max_x = rects[0].right();
926 qreal max_y = rects[0].bottom();
927 for (int i=1; i< rectCount; ++i) {
928 if (rects[i].left() < min_x)
929 min_x = rects[i].left();
930 if (rects[i].top() < min_y)
931 min_y = rects[i].top();
932 if (rects[i].right() > max_x)
933 max_x = rects[i].right();
934 if (rects[i].bottom() > max_y)
935 max_y = rects[i].bottom();
938 buffer->updateBoundingRect(QRectF(min_x, min_y, max_x - min_x, max_y - min_y));
943 void QPaintBufferEngine::drawLines(const QLine *lines, int lineCount)
945 #ifdef QPAINTBUFFER_DEBUG_DRAW
946 qDebug() << "QPaintBufferEngine: drawLinesI:" << lineCount;
948 QPaintBufferCommand *cmd =
949 buffer->addCommand(QPaintBufferPrivate::Cmd_DrawLineI, (int *) lines, 4 * lineCount, lineCount);
950 cmd->extra = lineCount;
952 if (buffer->calculateBoundingRect) {
953 int min_x = lines[0].p1().x();
954 int min_y = lines[0].p1().y();
955 int max_x = lines[0].p2().x();
956 int max_y = lines[0].p2().y();
961 for (int i=1; i < lineCount; ++i) {
962 int p1_x = lines[i].p1().x();
963 int p1_y = lines[i].p1().y();
964 int p2_x = lines[i].p2().x();
965 int p2_y = lines[i].p2().y();
967 min_x = qMin(p2_x, min_x);
968 max_x = qMax(p1_x, max_x);
970 min_x = qMin(p1_x, min_x);
971 max_x = qMax(p2_x, max_x);
974 min_y = qMin(p2_y, min_y);
975 max_y = qMax(p1_y, max_y);
977 min_y = qMin(p1_y, min_y);
978 max_y = qMax(p2_y, max_y);
981 buffer->updateBoundingRect(QRectF(min_x, min_y, max_x - min_x, max_y - min_y));
985 void QPaintBufferEngine::drawLines(const QLineF *lines, int lineCount)
987 #ifdef QPAINTBUFFER_DEBUG_DRAW
988 qDebug() << "QPaintBufferEngine: drawLinesF:" << lineCount;
990 QPaintBufferCommand *cmd =
991 buffer->addCommand(QPaintBufferPrivate::Cmd_DrawLineF, (qreal *) lines, 4 * lineCount, lineCount);
992 cmd->extra = lineCount;
994 if (buffer->calculateBoundingRect) {
995 qreal min_x = lines[0].p1().x();
996 qreal min_y = lines[0].p1().y();
997 qreal max_x = lines[0].p2().x();
998 qreal max_y = lines[0].p2().y();
1000 qSwap(min_x, max_x);
1002 qSwap(min_y, max_y);
1003 for (int i=1; i < lineCount; ++i) {
1004 qreal p1_x = lines[i].p1().x();
1005 qreal p1_y = lines[i].p1().y();
1006 qreal p2_x = lines[i].p2().x();
1007 qreal p2_y = lines[i].p2().y();
1009 min_x = qMin(p2_x, min_x);
1010 max_x = qMax(p1_x, max_x);
1012 min_x = qMin(p1_x, min_x);
1013 max_x = qMax(p2_x, max_x);
1016 min_y = qMin(p2_y, min_y);
1017 max_y = qMax(p1_y, max_y);
1019 min_y = qMin(p1_y, min_y);
1020 max_y = qMax(p2_y, max_y);
1023 buffer->updateBoundingRect(QRectF(min_x, min_y, max_x - min_x, max_y - min_y));
1027 void QPaintBufferEngine::drawEllipse(const QRectF &r)
1029 #ifdef QPAINTBUFFER_DEBUG_DRAW
1030 qDebug() << "QPaintBufferEngine: drawEllipseF:" << r;
1032 buffer->addCommand(QPaintBufferPrivate::Cmd_DrawEllipseF, (qreal *) &r, 4, 1);
1033 if (buffer->calculateBoundingRect)
1034 buffer->updateBoundingRect(r);
1037 void QPaintBufferEngine::drawEllipse(const QRect &r)
1039 #ifdef QPAINTBUFFER_DEBUG_DRAW
1040 qDebug() << "QPaintBufferEngine: drawEllipseI:" << r;
1042 buffer->addCommand(QPaintBufferPrivate::Cmd_DrawEllipseI, (int *) &r, 4, 1);
1043 if (buffer->calculateBoundingRect)
1044 buffer->updateBoundingRect(r);
1047 void QPaintBufferEngine::drawPath(const QPainterPath &path)
1049 // #ifdef QPAINTBUFFER_DEBUG_DRAW
1050 // qDebug() << "QPaintBufferEngine: drawPath: element count:" << path.elementCount();
1052 // // ### Path -> QVariant
1053 // // buffer->addCommand(QPaintBufferPrivate::Cmd_DrawPath, QVariant(path));
1054 QPaintEngineEx::drawPath(path);
1056 // if (buffer->calculateBoundingRect)
1057 // buffer->updateBoundingRect(path.boundingRect());
1060 void QPaintBufferEngine::drawPoints(const QPoint *points, int pointCount)
1062 #ifdef QPAINTBUFFER_DEBUG_DRAW
1063 qDebug() << "QPaintBufferEngine: drawPointsI: " << pointCount;
1065 buffer->addCommand(QPaintBufferPrivate::Cmd_DrawPointsI, (int *) points, 2 * pointCount, pointCount);
1067 if (buffer->calculateBoundingRect) {
1068 int min_x = points[0].x();
1069 int min_y = points[0].y();
1070 int max_x = points[0].x()+1;
1071 int max_y = points[0].y()+1;
1072 for (int i=1; i<pointCount; ++i) {
1073 int x = points[i].x();
1074 int y = points[i].y();
1075 min_x = qMin(min_x, x);
1076 min_y = qMin(min_y, y);
1077 max_x = qMax(max_x, x+1);
1078 max_y = qMax(max_y, y+1);
1080 buffer->updateBoundingRect(QRectF(min_x, min_y, max_x - min_x, max_y - min_y));
1084 void QPaintBufferEngine::drawPoints(const QPointF *points, int pointCount)
1086 #ifdef QPAINTBUFFER_DEBUG_DRAW
1087 qDebug() << "QPaintBufferEngine: drawPointsF: " << pointCount;
1089 buffer->addCommand(QPaintBufferPrivate::Cmd_DrawPointsF, (qreal *) points, 2 * pointCount, pointCount);
1091 if (buffer->calculateBoundingRect) {
1092 qreal min_x = points[0].x();
1093 qreal min_y = points[0].y();
1094 qreal max_x = points[0].x()+1;
1095 qreal max_y = points[0].y()+1;
1096 for (int i=1; i<pointCount; ++i) {
1097 qreal x = points[i].x();
1098 qreal y = points[i].y();
1099 min_x = qMin(min_x, x);
1100 min_y = qMin(min_y, y);
1101 max_x = qMax(max_x, x+1);
1102 max_y = qMax(max_y, y+1);
1104 buffer->updateBoundingRect(QRectF(min_x, min_y, max_x - min_x, max_y - min_y));
1108 void QPaintBufferEngine::drawPolygon(const QPoint *pts, int count, PolygonDrawMode mode)
1110 #ifdef QPAINTBUFFER_DEBUG_DRAW
1111 qDebug() << "QPaintBufferEngine: drawPolygonI: size:" << count << ", mode:" << mode;
1113 if (mode == QPaintEngine::OddEvenMode || mode == QPaintEngine::WindingMode) {
1114 QPaintBufferCommand *cmd = buffer->addCommand(QPaintBufferPrivate::Cmd_DrawPolygonI,
1115 (int *) pts, 2 * count, count);
1117 } else if (mode == QPaintEngine::PolylineMode) {
1118 buffer->addCommand(QPaintBufferPrivate::Cmd_DrawPolylineI, (int *) pts, 2 * count, count);
1120 buffer->addCommand(QPaintBufferPrivate::Cmd_DrawConvexPolygonI, (int *) pts, 2 * count, count);
1123 if (buffer->calculateBoundingRect) {
1124 int min_x = pts[0].x();
1125 int min_y = pts[0].y();
1126 int max_x = pts[0].x();
1127 int max_y = pts[0].y();
1128 for (int i=1; i<count; ++i) {
1131 min_x = qMin(min_x, x);
1132 min_y = qMin(min_y, y);
1133 max_x = qMax(max_x, x);
1134 max_y = qMax(max_y, y);
1136 buffer->updateBoundingRect(QRectF(min_x, min_y, max_x - min_x, max_y - min_y));
1140 void QPaintBufferEngine::drawPolygon(const QPointF *pts, int count, PolygonDrawMode mode)
1142 #ifdef QPAINTBUFFER_DEBUG_DRAW
1143 qDebug() << "QPaintBufferEngine: drawPolygonF: size:" << count << ", mode:" << mode;
1145 if (mode == QPaintEngine::OddEvenMode || mode == QPaintEngine::WindingMode) {
1146 QPaintBufferCommand *cmd = buffer->addCommand(QPaintBufferPrivate::Cmd_DrawPolygonF,
1147 (qreal *) pts, 2 * count, count);
1149 } else if (mode == QPaintEngine::PolylineMode) {
1150 buffer->addCommand(QPaintBufferPrivate::Cmd_DrawPolylineF, (qreal *) pts, 2 * count, count);
1152 buffer->addCommand(QPaintBufferPrivate::Cmd_DrawConvexPolygonF, (qreal *) pts, 2 * count, count);
1155 if (buffer->calculateBoundingRect) {
1156 qreal min_x = pts[0].x();
1157 qreal min_y = pts[0].y();
1158 qreal max_x = pts[0].x();
1159 qreal max_y = pts[0].y();
1160 for (int i=1; i<count; ++i) {
1161 qreal x = pts[i].x();
1162 qreal y = pts[i].y();
1163 min_x = qMin(min_x, x);
1164 min_y = qMin(min_y, y);
1165 max_x = qMax(max_x, x);
1166 max_y = qMax(max_y, y);
1168 buffer->updateBoundingRect(QRectF(min_x, min_y, max_x - min_x, max_y - min_y));
1172 void QPaintBufferEngine::drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr)
1174 #ifdef QPAINTBUFFER_DEBUG_DRAW
1175 qDebug() << "QPaintBufferEngine: drawPixmap: src/dest rects " << r << sr;
1177 QPaintBufferCommand *cmd =
1178 buffer->addCommand(QPaintBufferPrivate::Cmd_DrawPixmapRect, QVariant(pm));
1179 cmd->extra = buffer->addData((qreal *) &r, 4);
1180 buffer->addData((qreal *) &sr, 4);
1181 if (buffer->calculateBoundingRect)
1182 buffer->updateBoundingRect(r);
1185 void QPaintBufferEngine::drawPixmap(const QPointF &pos, const QPixmap &pm)
1187 #ifdef QPAINTBUFFER_DEBUG_DRAW
1188 qDebug() << "QPaintBufferEngine: drawPixmap: pos:" << pos;
1190 QPaintBufferCommand *cmd =
1191 buffer->addCommand(QPaintBufferPrivate::Cmd_DrawPixmapPos, QVariant(pm));
1192 cmd->extra = buffer->addData((qreal *) &pos, 2);
1193 if (buffer->calculateBoundingRect)
1194 buffer->updateBoundingRect(QRectF(pos, pm.size()));
1197 static inline QImage qpaintbuffer_storable_image(const QImage &src)
1199 QImageData *d = const_cast<QImage &>(src).data_ptr();
1200 return d->own_data ? src : src.copy();
1203 void QPaintBufferEngine::drawImage(const QRectF &r, const QImage &image, const QRectF &sr,
1204 Qt::ImageConversionFlags /*flags */)
1206 #ifdef QPAINTBUFFER_DEBUG_DRAW
1207 qDebug() << "QPaintBufferEngine: drawImage: src/dest rects " << r << sr;
1209 QPaintBufferCommand *cmd =
1210 buffer->addCommand(QPaintBufferPrivate::Cmd_DrawImageRect,
1211 QVariant(qpaintbuffer_storable_image(image)));
1212 cmd->extra = buffer->addData((qreal *) &r, 4);
1213 buffer->addData((qreal *) &sr, 4);
1215 if (buffer->calculateBoundingRect)
1216 buffer->updateBoundingRect(r);
1219 void QPaintBufferEngine::drawImage(const QPointF &pos, const QImage &image)
1221 #ifdef QPAINTBUFFER_DEBUG_DRAW
1222 qDebug() << "QPaintBufferEngine: drawImage: pos:" << pos;
1224 QPaintBufferCommand *cmd =
1225 buffer->addCommand(QPaintBufferPrivate::Cmd_DrawImagePos,
1226 QVariant(qpaintbuffer_storable_image(image)));
1227 cmd->extra = buffer->addData((qreal *) &pos, 2);
1228 if (buffer->calculateBoundingRect)
1229 buffer->updateBoundingRect(QRectF(pos, image.size()));
1232 void QPaintBufferEngine::drawTiledPixmap(const QRectF &r, const QPixmap &pm, const QPointF &s)
1234 #ifdef QPAINTBUFFER_DEBUG_DRAW
1235 qDebug() << "QPaintBufferEngine: drawTiledPixmap: src rect/offset:" << r << s;
1237 QPaintBufferCommand *cmd =
1238 buffer->addCommand(QPaintBufferPrivate::Cmd_DrawTiledPixmap, QVariant(pm));
1239 cmd->extra = buffer->addData((qreal *) &r, 4);
1240 buffer->addData((qreal *) &s, 2);
1241 if (buffer->calculateBoundingRect)
1242 buffer->updateBoundingRect(r);
1245 void QPaintBufferEngine::drawStaticTextItem(QStaticTextItem *staticTextItem)
1247 QVariantList variants;
1249 variants << QVariant(staticTextItem->font);
1250 for (int i=0; i<staticTextItem->numGlyphs; ++i) {
1251 variants.append(staticTextItem->glyphs[i]);
1252 variants.append(staticTextItem->glyphPositions[i].toPointF());
1255 buffer->addCommand(QPaintBufferPrivate::Cmd_DrawStaticText, QVariant(variants));
1258 void QPaintBufferEngine::drawTextItem(const QPointF &pos, const QTextItem &ti)
1260 #ifdef QPAINTBUFFER_DEBUG_DRAW
1261 qDebug() << "QPaintBufferEngine: drawTextItem: pos:" << pos << ti.text();
1263 if (m_stream_raw_text_items) {
1264 QPaintBufferCommand *cmd = buffer->addCommand(QPaintBufferPrivate::Cmd_DrawTextItem, QVariant::fromValue<void *>(new QTextItemIntCopy(ti)));
1266 QFont font(ti.font());
1267 font.setUnderline(false);
1268 font.setStrikeOut(false);
1269 font.setOverline(false);
1271 const QTextItemInt &si = static_cast<const QTextItemInt &>(ti);
1272 qreal justificationWidth = 0;
1274 justificationWidth = si.width.toReal();
1275 int renderFlags = ti.renderFlags();
1276 qreal scaleFactor = font.d->dpi/qreal(qt_defaultDpiY());
1278 buffer->addData(QVariant(font));
1279 cmd->extra = buffer->addData((qreal *) &pos, 2);
1280 buffer->addData((qreal *) &justificationWidth, 1);
1281 buffer->addData((qreal *) &scaleFactor, 1);
1282 cmd->offset2 = buffer->addData((int *) &renderFlags, 1);
1284 QList<QVariant> variants;
1285 variants << QVariant(ti.font()) << QVariant(ti.text());
1286 QPaintBufferCommand *cmd = buffer->addCommand(QPaintBufferPrivate::Cmd_DrawText, QVariant(variants));
1287 cmd->extra = buffer->addData((qreal *) &pos, 2);
1290 if (buffer->calculateBoundingRect)
1291 buffer->updateBoundingRect(QRectF(pos, QSize(ti.width(), ti.ascent() + ti.descent() + 1)));
1295 void QPaintBufferEngine::setState(QPainterState *s)
1297 Q_D(QPaintBufferEngine);
1298 if (m_begin_detected) {
1299 #ifdef QPAINTBUFFER_DEBUG_DRAW
1300 qDebug() << "QPaintBufferEngine: setState: begin, ignoring.";
1302 m_begin_detected = false;
1303 } else if (m_save_detected) {
1304 #ifdef QPAINTBUFFER_DEBUG_DRAW
1305 qDebug() << "QPaintBufferEngine: setState: save.";
1307 m_save_detected = false;
1308 buffer->addCommand(QPaintBufferPrivate::Cmd_Save);
1310 #ifdef QPAINTBUFFER_DEBUG_DRAW
1311 qDebug() << "QPaintBufferEngine: setState: restore.";
1313 buffer->addCommand(QPaintBufferPrivate::Cmd_Restore);
1316 d->last = s->matrix;
1318 QPaintEngineEx::setState(s);
1322 /***********************************************************************
1324 * class QPaintBufferPlayback_Painter
1328 // QFakeDevice is used to create fonts with a custom DPI
1330 class QFakeDevice : public QPaintDevice
1333 QFakeDevice() { dpi_x = qt_defaultDpiX(); dpi_y = qt_defaultDpiY(); }
1334 void setDpiX(int dpi) { dpi_x = dpi; }
1335 void setDpiY(int dpi) { dpi_y = dpi; }
1336 QPaintEngine *paintEngine() const { return 0; }
1337 int metric(PaintDeviceMetric m) const
1340 case PdmPhysicalDpiX:
1343 case PdmPhysicalDpiY:
1347 return QPaintDevice::metric(m);
1357 void QPainterReplayer::setupTransform(QPainter *_painter)
1360 m_world_matrix = painter->transform();
1361 m_world_matrix.scale(qreal(painter->device()->logicalDpiX()) / qreal(qt_defaultDpiX()),
1362 qreal(painter->device()->logicalDpiY()) / qreal(qt_defaultDpiY()));
1363 painter->setTransform(m_world_matrix);
1366 void QPainterReplayer::processCommands(const QPaintBuffer &buffer, QPainter *p, int begin, int end)
1371 for (int cmdIndex = begin; cmdIndex < end; ++cmdIndex) {
1372 const QPaintBufferCommand &cmd = d->commands.at(cmdIndex);
1377 void QPaintBuffer::beginNewFrame()
1379 if (!d_ptr->commands.isEmpty())
1380 d_ptr->frames << d_ptr->commands.size();
1383 int QPaintBuffer::numFrames() const
1385 return d_ptr->frames.size() + 1;
1388 void QPainterReplayer::process(const QPaintBufferCommand &cmd)
1391 case QPaintBufferPrivate::Cmd_Save: {
1392 #ifdef QPAINTBUFFER_DEBUG_DRAW
1393 qDebug() << " -> Cmd_Save";
1398 case QPaintBufferPrivate::Cmd_Restore: {
1399 #ifdef QPAINTBUFFER_DEBUG_DRAW
1400 qDebug() << " -> Cmd_Restore";
1405 case QPaintBufferPrivate::Cmd_SetPen: {
1406 QPen pen = qvariant_cast<QPen>(d->variants.at(cmd.offset));
1407 #ifdef QPAINTBUFFER_DEBUG_DRAW
1408 qDebug() << " -> Cmd_SetPen: " << pen;
1410 painter->setPen(pen);
1413 case QPaintBufferPrivate::Cmd_SetBrush: {
1414 QBrush brush = qvariant_cast<QBrush>(d->variants.at(cmd.offset));
1415 #ifdef QPAINTBUFFER_DEBUG_DRAW
1416 qDebug() << " -> Cmd_SetBrush: " << brush;
1418 painter->setBrush(brush);
1421 case QPaintBufferPrivate::Cmd_SetBrushOrigin: {
1422 #ifdef QPAINTBUFFER_DEBUG_DRAW
1423 qDebug() << " -> Cmd_SetBrushOrigin: " << d->variants.at(cmd.offset).toPointF();
1425 painter->setBrushOrigin(d->variants.at(cmd.offset).toPointF());
1428 case QPaintBufferPrivate::Cmd_SetTransform: {
1429 QTransform xform = qvariant_cast<QTransform>(d->variants.at(cmd.offset));
1430 #ifdef QPAINTBUFFER_DEBUG_DRAW
1431 qDebug() << " -> Cmd_SetTransform, offset: " << cmd.offset << xform;
1433 painter->setTransform(xform * m_world_matrix);
1436 case QPaintBufferPrivate::Cmd_Translate: {
1437 QPointF delta(d->floats.at(cmd.extra), d->floats.at(cmd.extra+1));
1438 #ifdef QPAINTBUFFER_DEBUG_DRAW
1439 qDebug() << " -> Cmd_Translate, offset: " << cmd.offset << delta;
1441 painter->translate(delta.x(), delta.y());
1445 case QPaintBufferPrivate::Cmd_SetCompositionMode: {
1446 QPainter::CompositionMode mode = (QPainter::CompositionMode) cmd.extra;
1447 #ifdef QPAINTBUFFER_DEBUG_DRAW
1448 qDebug() << " -> Cmd_SetCompositionMode, mode: " << mode;
1450 painter->setCompositionMode(mode);
1453 case QPaintBufferPrivate::Cmd_SetRenderHints: {
1454 #ifdef QPAINTBUFFER_DEBUG_DRAW
1455 qDebug() << " -> Cmd_SetRenderHints, hints: " << cmd.extra;
1457 QPainter::RenderHints ph = painter->renderHints();
1458 QPainter::RenderHints nh = (QPainter::RenderHints) cmd.extra;
1459 QPainter::RenderHints xored = ph ^ nh;
1460 if (xored & QPainter::Antialiasing)
1461 painter->setRenderHint(QPainter::Antialiasing, nh & QPainter::Antialiasing);
1462 if (xored & QPainter::HighQualityAntialiasing)
1463 painter->setRenderHint(QPainter::HighQualityAntialiasing, nh & QPainter::HighQualityAntialiasing);
1464 if (xored & QPainter::TextAntialiasing)
1465 painter->setRenderHint(QPainter::TextAntialiasing, nh & QPainter::TextAntialiasing);
1466 if (xored & QPainter::SmoothPixmapTransform)
1467 painter->setRenderHint(QPainter::SmoothPixmapTransform, nh & QPainter::SmoothPixmapTransform);
1468 if (xored & QPainter::NonCosmeticDefaultPen)
1469 painter->setRenderHint(QPainter::NonCosmeticDefaultPen, nh & QPainter::NonCosmeticDefaultPen);
1472 case QPaintBufferPrivate::Cmd_SetOpacity: {
1473 #ifdef QPAINTBUFFER_DEBUG_DRAW
1474 qDebug() << " -> Cmd_SetOpacity: " << d->variants.at(cmd.offset).toDouble();
1476 painter->setOpacity(d->variants.at(cmd.offset).toDouble());
1479 case QPaintBufferPrivate::Cmd_SetBackgroundMode: {
1480 #ifdef QPAINTBUFFER_DEBUG_DRAW
1481 qDebug() << " -> Cmd_SetBackgroundMode: " << cmd.extra;
1483 painter->setBackgroundMode((Qt::BGMode)cmd.extra);
1486 case QPaintBufferPrivate::Cmd_DrawVectorPath: {
1487 #ifdef QPAINTBUFFER_DEBUG_DRAW
1488 qDebug() << " -> Cmd_DrawVectorPath: size: " << cmd.size
1489 // << ", hints:" << d->ints[cmd.offset2+cmd.size]
1490 << "pts/elms:" << cmd.offset << cmd.offset2;
1492 QVectorPathCmd path(d, cmd);
1493 painter->drawPath(path().convertToPainterPath());
1496 case QPaintBufferPrivate::Cmd_StrokeVectorPath: {
1497 QPen pen = qvariant_cast<QPen>(d->variants.at(cmd.extra));
1498 #ifdef QPAINTBUFFER_DEBUG_DRAW
1499 qDebug() << " -> Cmd_StrokeVectorPath: size: " << cmd.size
1500 // << ", hints:" << d->ints[cmd.offset2+cmd.size]
1501 << "pts/elms:" << cmd.offset << cmd.offset2;
1503 QVectorPathCmd path(d, cmd);
1504 painter->strokePath(path().convertToPainterPath(), pen);
1507 case QPaintBufferPrivate::Cmd_FillVectorPath: {
1508 QBrush brush = qvariant_cast<QBrush>(d->variants.at(cmd.extra));
1509 #ifdef QPAINTBUFFER_DEBUG_DRAW
1510 qDebug() << " -> Cmd_FillVectorPath: size: " << cmd.size
1511 // << ", hints:" << d->ints[cmd.offset2+cmd.size]
1512 << "pts/elms:" << cmd.offset << cmd.offset2 << brush;
1514 QVectorPathCmd path(d, cmd);
1515 painter->fillPath(path().convertToPainterPath(), brush);
1518 case QPaintBufferPrivate::Cmd_DrawPolygonF: {
1519 #ifdef QPAINTBUFFER_DEBUG_DRAW
1520 qDebug() << " -> Cmd_DrawPolygonF, offset: " << cmd.offset << " size: " << cmd.size
1521 << " mode: " << cmd.extra
1522 << d->floats.at(cmd.offset)
1523 << d->floats.at(cmd.offset+1);
1525 Qt::FillRule fill = (QPaintEngine::PolygonDrawMode) cmd.extra == QPaintEngine::OddEvenMode
1526 ? Qt::OddEvenFill : Qt::WindingFill;
1527 painter->drawPolygon((QPointF *) (d->floats.constData() + cmd.offset), cmd.size, fill);
1530 case QPaintBufferPrivate::Cmd_DrawPolygonI: {
1531 #ifdef QPAINTBUFFER_DEBUG_DRAW
1532 qDebug() << " -> Cmd_DrawPolygonI, offset: " << cmd.offset << " size: " << cmd.size
1533 << " mode: " << cmd.extra
1534 << d->ints.at(cmd.offset)
1535 << d->ints.at(cmd.offset+1);
1537 Qt::FillRule fill = (QPaintEngine::PolygonDrawMode) cmd.extra == QPaintEngine::OddEvenMode
1538 ? Qt::OddEvenFill : Qt::WindingFill;
1539 painter->drawPolygon((QPoint *) (d->ints.constData() + cmd.offset), cmd.size, fill);
1542 case QPaintBufferPrivate::Cmd_DrawPolylineF: {
1543 #ifdef QPAINTBUFFER_DEBUG_DRAW
1544 qDebug() << " -> Cmd_DrawPolylineF, offset: " << cmd.offset << " size: " << cmd.size;
1546 painter->drawPolyline((QPointF *) (d->floats.constData() + cmd.offset), cmd.size);
1549 case QPaintBufferPrivate::Cmd_DrawPolylineI: {
1550 #ifdef QPAINTBUFFER_DEBUG_DRAW
1551 qDebug() << " -> Cmd_DrawPolylineI, offset: " << cmd.offset << " size: " << cmd.size;
1553 painter->drawPolyline((QPoint *) (d->ints.constData() + cmd.offset), cmd.size);
1556 case QPaintBufferPrivate::Cmd_DrawConvexPolygonF: {
1557 #ifdef QPAINTBUFFER_DEBUG_DRAW
1558 qDebug() << " -> Cmd_DrawConvexPolygonF, offset: " << cmd.offset << " size: " << cmd.size;
1560 painter->drawConvexPolygon((QPointF *) (d->floats.constData() + cmd.offset), cmd.size);
1563 case QPaintBufferPrivate::Cmd_DrawConvexPolygonI: {
1564 #ifdef QPAINTBUFFER_DEBUG_DRAW
1565 qDebug() << " -> Cmd_DrawConvexPolygonI, offset: " << cmd.offset << " size: " << cmd.size;
1567 painter->drawConvexPolygon((QPoint *) (d->ints.constData() + cmd.offset), cmd.size);
1570 case QPaintBufferPrivate::Cmd_DrawEllipseF: {
1571 #ifdef QPAINTBUFFER_DEBUG_DRAW
1572 qDebug() << " -> Cmd_DrawEllipseF, offset: " << cmd.offset;
1574 painter->drawEllipse(*(QRectF *)(d->floats.constData() + cmd.offset));
1577 case QPaintBufferPrivate::Cmd_DrawEllipseI: {
1578 #ifdef QPAINTBUFFER_DEBUG_DRAW
1579 qDebug() << " -> Cmd_DrawEllipseI, offset: " << cmd.offset;
1581 painter->drawEllipse(*(QRect *)(d->ints.constData() + cmd.offset));
1584 case QPaintBufferPrivate::Cmd_DrawLineF: {
1585 #ifdef QPAINTBUFFER_DEBUG_DRAW
1586 qDebug() << " -> Cmd_DrawLineF, offset: " << cmd.offset << " size: " << cmd.size;
1588 painter->drawLines((QLineF *)(d->floats.constData() + cmd.offset), cmd.size);
1591 case QPaintBufferPrivate::Cmd_DrawLineI: {
1592 #ifdef QPAINTBUFFER_DEBUG_DRAW
1593 qDebug() << " -> Cmd_DrawLineI, offset: " << cmd.offset << " size: " << cmd.size;
1595 painter->drawLines((QLine *)(d->ints.constData() + cmd.offset), cmd.size);
1598 case QPaintBufferPrivate::Cmd_DrawPointsF: {
1599 #ifdef QPAINTBUFFER_DEBUG_DRAW
1600 qDebug() << " -> Cmd_DrawPointsF, offset: " << cmd.offset << " size: " << cmd.size;
1602 painter->drawPoints((QPointF *)(d->floats.constData() + cmd.offset), cmd.size);
1605 case QPaintBufferPrivate::Cmd_DrawPointsI: {
1606 #ifdef QPAINTBUFFER_DEBUG_DRAW
1607 qDebug() << " -> Cmd_DrawPointsI, offset: " << cmd.offset << " size: " << cmd.size;
1609 painter->drawPoints((QPoint *)(d->ints.constData() + cmd.offset), cmd.size);
1612 case QPaintBufferPrivate::Cmd_DrawPixmapRect: {
1613 QPixmap pm(d->variants.at(cmd.offset).value<QPixmap>());
1614 QRectF r(d->floats.at(cmd.extra), d->floats.at(cmd.extra+1),
1615 d->floats.at(cmd.extra+2), d->floats.at(cmd.extra+3));
1617 QRectF sr(d->floats.at(cmd.extra+4), d->floats.at(cmd.extra+5),
1618 d->floats.at(cmd.extra+6), d->floats.at(cmd.extra+7));
1619 #ifdef QPAINTBUFFER_DEBUG_DRAW
1620 qDebug() << " -> Cmd_DrawPixmapRect:" << r << sr;
1622 painter->drawPixmap(r, pm, sr);
1625 case QPaintBufferPrivate::Cmd_DrawPixmapPos: {
1626 QPixmap pm(d->variants.at(cmd.offset).value<QPixmap>());
1627 QPointF pos(d->floats.at(cmd.extra), d->floats.at(cmd.extra+1));
1628 #ifdef QPAINTBUFFER_DEBUG_DRAW
1629 qDebug() << " -> Cmd_DrawPixmapPos:" << pos;
1631 painter->drawPixmap(pos, pm);
1634 case QPaintBufferPrivate::Cmd_DrawTiledPixmap: {
1635 QPixmap pm(d->variants.at(cmd.offset).value<QPixmap>());
1636 QRectF r(d->floats.at(cmd.extra), d->floats.at(cmd.extra+1),
1637 d->floats.at(cmd.extra+2), d->floats.at(cmd.extra+3));
1639 QPointF offset(d->floats.at(cmd.extra+4), d->floats.at(cmd.extra+5));
1640 #ifdef QPAINTBUFFER_DEBUG_DRAW
1641 qDebug() << " -> Cmd_DrawTiledPixmap:" << r << offset;
1643 painter->drawTiledPixmap(r, pm, offset);
1646 case QPaintBufferPrivate::Cmd_DrawImageRect: {
1647 QImage image(d->variants.at(cmd.offset).value<QImage>());
1648 QRectF r(d->floats.at(cmd.extra), d->floats.at(cmd.extra+1),
1649 d->floats.at(cmd.extra+2), d->floats.at(cmd.extra+3));
1650 QRectF sr(d->floats.at(cmd.extra+4), d->floats.at(cmd.extra+5),
1651 d->floats.at(cmd.extra+6), d->floats.at(cmd.extra+7));
1652 #ifdef QPAINTBUFFER_DEBUG_DRAW
1653 qDebug() << " -> Cmd_DrawImageRect:" << r << sr;
1655 painter->drawImage(r, image, sr);
1658 case QPaintBufferPrivate::Cmd_DrawImagePos: {
1659 QImage image(d->variants.at(cmd.offset).value<QImage>());
1660 QPointF pos(d->floats.at(cmd.extra), d->floats.at(cmd.extra+1));
1661 #ifdef QPAINTBUFFER_DEBUG_DRAW
1662 qDebug() << " -> Cmd_DrawImagePos:" << pos;
1664 painter->drawImage(pos, image);
1667 case QPaintBufferPrivate::Cmd_DrawRectF: {
1668 #ifdef QPAINTBUFFER_DEBUG_DRAW
1669 qDebug() << " -> Cmd_DrawRectF, offset: " << cmd.offset;
1671 painter->drawRects((QRectF *)(d->floats.constData() + cmd.offset), cmd.size);
1674 case QPaintBufferPrivate::Cmd_DrawRectI: {
1675 #ifdef QPAINTBUFFER_DEBUG_DRAW
1676 qDebug() << " -> Cmd_DrawRectI, offset: " << cmd.offset;
1678 painter->drawRects((QRect *)(d->ints.constData() + cmd.offset), cmd.size);
1681 case QPaintBufferPrivate::Cmd_FillRectBrush: {
1682 QBrush brush = qvariant_cast<QBrush>(d->variants.at(cmd.extra));
1683 QRectF *rect = (QRectF *)(d->floats.constData() + cmd.offset);
1684 #ifdef QPAINTBUFFER_DEBUG_DRAW
1685 qDebug() << " -> Cmd_FillRectBrush, offset: " << cmd.offset << " rect: " << *rect << " brush: " << brush;
1687 painter->fillRect(*rect, brush);
1690 case QPaintBufferPrivate::Cmd_FillRectColor: {
1691 QColor color = qvariant_cast<QColor>(d->variants.at(cmd.extra));
1692 QRectF *rect = (QRectF *)(d->floats.constData() + cmd.offset);
1693 #ifdef QPAINTBUFFER_DEBUG_DRAW
1694 qDebug() << " -> Cmd_FillRectBrush, offset: " << cmd.offset << " rect: " << *rect << " color: " << color;
1696 painter->fillRect(*rect, color);
1699 case QPaintBufferPrivate::Cmd_SetClipEnabled: {
1700 bool clipEnabled = d->variants.at(cmd.offset).toBool();
1701 #ifdef QPAINTBUFFER_DEBUG_DRAW
1702 qDebug() << " -> Cmd_SetClipEnabled:" << clipEnabled;
1704 painter->setClipping(clipEnabled);
1707 case QPaintBufferPrivate::Cmd_ClipVectorPath: {
1708 QVectorPathCmd path(d, cmd);
1709 #ifdef QPAINTBUFFER_DEBUG_DRAW
1710 qDebug() << " -> Cmd_ClipVectorPath:" << path().elementCount();
1712 painter->setClipPath(path().convertToPainterPath(), Qt::ClipOperation(cmd.extra));
1716 case QPaintBufferPrivate::Cmd_ClipRect: {
1717 QRect rect(QPoint(d->ints.at(cmd.offset), d->ints.at(cmd.offset + 1)),
1718 QPoint(d->ints.at(cmd.offset + 2), d->ints.at(cmd.offset + 3)));
1719 #ifdef QPAINTBUFFER_DEBUG_DRAW
1720 qDebug() << " -> Cmd_ClipRect:" << rect << cmd.extra;
1722 painter->setClipRect(rect, Qt::ClipOperation(cmd.extra));
1725 case QPaintBufferPrivate::Cmd_ClipRegion: {
1726 QRegion region(d->variants.at(cmd.offset).value<QRegion>());
1727 #ifdef QPAINTBUFFER_DEBUG_DRAW
1728 qDebug() << " -> Cmd_ClipRegion:" << region.boundingRect() << cmd.extra;
1730 painter->setClipRegion(region, Qt::ClipOperation(cmd.extra));
1733 #if !defined(QT_NO_RAWFONT)
1734 case QPaintBufferPrivate::Cmd_DrawStaticText: {
1736 QVariantList variants(d->variants.at(cmd.offset).value<QVariantList>());
1738 QFont font = variants.at(0).value<QFont>();
1740 QVector<quint32> glyphIndexes;
1741 QVector<QPointF> positions;
1743 for (int i=0; i<(variants.size() - 1) / 2; ++i) {
1744 glyphIndexes.append(variants.at(i*2 + 1).toUInt());
1745 positions.append(variants.at(i*2 + 2).toPointF());
1748 painter->setFont(font);
1751 QRawFontPrivate *rawFontD = QRawFontPrivate::get(rawFont);
1752 QFontPrivate *fontD = QFontPrivate::get(font);
1753 rawFontD->fontEngine = fontD->engineForScript(QUnicodeTables::Common);
1754 rawFontD->fontEngine->ref.ref();
1757 glyphs.setRawFont(rawFont);
1758 glyphs.setGlyphIndexes(glyphIndexes);
1759 glyphs.setPositions(positions);
1761 painter->drawGlyphRun(QPointF(), glyphs);
1766 case QPaintBufferPrivate::Cmd_DrawText: {
1767 QPointF pos(d->floats.at(cmd.extra), d->floats.at(cmd.extra+1));
1768 QList<QVariant> variants(d->variants.at(cmd.offset).value<QList<QVariant> >());
1770 QFont font(variants.at(0).value<QFont>());
1771 QString text(variants.at(1).value<QString>());
1773 painter->setFont(font);
1774 painter->drawText(pos, text);
1777 case QPaintBufferPrivate::Cmd_DrawTextItem: {
1778 QPointF pos(d->floats.at(cmd.extra), d->floats.at(cmd.extra+1));
1779 QTextItemIntCopy *tiCopy = reinterpret_cast<QTextItemIntCopy *>(qvariant_cast<void *>(d->variants.at(cmd.offset)));
1780 QTextItemInt &ti = (*tiCopy)();
1781 QString text(ti.text());
1783 QFont font(ti.font());
1784 font.setUnderline(false);
1785 font.setStrikeOut(false);
1786 font.setOverline(false);
1788 const QTextItemInt &si = static_cast<const QTextItemInt &>(ti);
1789 qreal justificationWidth = 0;
1791 justificationWidth = si.width.toReal();
1792 qreal scaleFactor = font.d->dpi/qreal(qt_defaultDpiY());
1794 #ifdef QPAINTBUFFER_DEBUG_DRAW
1795 qDebug() << " -> Cmd_DrawTextItem:" << pos << " " << text << " " << scaleFactor;
1798 if (scaleFactor != 1.0) {
1801 fake.setDpiX(qRound(scaleFactor*qt_defaultDpiX()));
1802 fake.setDpiY(qRound(scaleFactor*qt_defaultDpiY()));
1803 font = QFont(fnt, &fake);
1806 int flags = Qt::TextSingleLine | Qt::TextDontClip | Qt::TextForceLeftToRight;
1808 if (justificationWidth > 0) {
1809 size.setWidth(justificationWidth);
1810 flags |= Qt::TextJustificationForced;
1811 flags |= Qt::AlignJustify;
1814 QFontMetrics fm(font);
1815 QPointF pt(pos.x(), pos.y() - fm.ascent());
1816 qt_format_text(font, QRectF(pt, size), flags, /*opt*/0,
1817 text, /*brect=*/0, /*tabstops=*/0, /*...*/0, /*tabarraylen=*/0, painter);
1819 case QPaintBufferPrivate::Cmd_SystemStateChanged: {
1820 QRegion systemClip(d->variants.at(cmd.offset).value<QRegion>());
1822 #ifdef QPAINTBUFFER_DEBUG_DRAW
1823 qDebug() << " -> Cmd_SystemStateChanged:" << systemClip;
1826 painter->paintEngine()->setSystemClip(systemClip);
1827 painter->paintEngine()->d_ptr->systemStateChanged();
1832 void QPaintEngineExReplayer::process(const QPaintBufferCommand &cmd)
1834 Q_ASSERT(painter->paintEngine()->isExtended());
1835 QPaintEngineEx *xengine = static_cast<QPaintEngineEx *>(painter->paintEngine());
1838 case QPaintBufferPrivate::Cmd_SetBrushOrigin: {
1839 #ifdef QPAINTBUFFER_DEBUG_DRAW
1840 qDebug() << " -> ExCmd_SetBrushOrigin: " << d->variants.at(cmd.offset).toPointF();
1842 xengine->state()->brushOrigin = d->variants.at(cmd.offset).toPointF();
1843 xengine->brushOriginChanged();
1846 case QPaintBufferPrivate::Cmd_SetCompositionMode: {
1847 QPainter::CompositionMode mode = (QPainter::CompositionMode) cmd.extra;
1848 #ifdef QPAINTBUFFER_DEBUG_DRAW
1849 qDebug() << " -> ExCmd_SetCompositionMode, mode: " << mode;
1851 xengine->state()->composition_mode = mode;
1852 xengine->compositionModeChanged();
1855 case QPaintBufferPrivate::Cmd_SetOpacity: {
1856 #ifdef QPAINTBUFFER_DEBUG_DRAW
1857 qDebug() << " -> ExCmd_SetOpacity: " << d->variants.at(cmd.offset).toDouble();
1859 xengine->state()->opacity = d->variants.at(cmd.offset).toDouble();
1860 xengine->opacityChanged();
1863 case QPaintBufferPrivate::Cmd_DrawVectorPath: {
1864 #ifdef QPAINTBUFFER_DEBUG_DRAW
1865 qDebug() << " -> ExCmd_DrawVectorPath: size: " << cmd.size
1866 // << ", hints:" << d->ints[cmd.offset2+cmd.size]
1867 << "pts/elms:" << cmd.offset << cmd.offset2;
1869 QVectorPathCmd path(d, cmd);
1870 xengine->draw(path());
1873 case QPaintBufferPrivate::Cmd_StrokeVectorPath: {
1874 QPen pen = qvariant_cast<QPen>(d->variants.at(cmd.extra));
1875 #ifdef QPAINTBUFFER_DEBUG_DRAW
1876 qDebug() << " -> ExCmd_StrokeVectorPath: size: " << cmd.size
1877 // << ", hints:" << d->ints[cmd.offset2+cmd.size]
1878 << "pts/elms:" << cmd.offset << cmd.offset2;
1880 QVectorPathCmd path(d, cmd);
1881 xengine->stroke(path(), pen);
1884 case QPaintBufferPrivate::Cmd_FillVectorPath: {
1885 QBrush brush = qvariant_cast<QBrush>(d->variants.at(cmd.extra));
1886 #ifdef QPAINTBUFFER_DEBUG_DRAW
1887 qDebug() << " -> ExCmd_FillVectorPath: size: " << cmd.size
1888 // << ", hints:" << d->ints[cmd.offset2+cmd.size]
1889 << "pts/elms:" << cmd.offset << cmd.offset2 << brush;
1891 QVectorPathCmd path(d, cmd);
1892 xengine->fill(path(), brush);
1895 case QPaintBufferPrivate::Cmd_FillRectBrush: {
1896 QBrush brush = qvariant_cast<QBrush>(d->variants.at(cmd.extra));
1897 QRectF *rect = (QRectF *)(d->floats.constData() + cmd.offset);
1898 #ifdef QPAINTBUFFER_DEBUG_DRAW
1899 qDebug() << " -> ExCmd_FillRectBrush, offset: " << cmd.offset << " rect: " << *rect << " brush: " << brush;
1901 xengine->fillRect(*rect, brush);
1904 case QPaintBufferPrivate::Cmd_FillRectColor: {
1905 QColor color = qvariant_cast<QColor>(d->variants.at(cmd.extra));
1906 QRectF *rect = (QRectF *)(d->floats.constData() + cmd.offset);
1907 #ifdef QPAINTBUFFER_DEBUG_DRAW
1908 qDebug() << " -> ExCmd_FillRectBrush, offset: " << cmd.offset << " rect: " << *rect << " color: " << color;
1910 xengine->fillRect(*rect, color);
1913 case QPaintBufferPrivate::Cmd_DrawPolygonF: {
1914 #ifdef QPAINTBUFFER_DEBUG_DRAW
1915 qDebug() << " -> ExCmd_DrawPolygonF, offset: " << cmd.offset << " size: " << cmd.size
1916 << " mode: " << cmd.extra
1917 << d->floats.at(cmd.offset)
1918 << d->floats.at(cmd.offset+1);
1920 xengine->drawPolygon((QPointF *) (d->floats.constData() + cmd.offset), cmd.size,
1921 (QPaintEngine::PolygonDrawMode) cmd.extra);
1924 case QPaintBufferPrivate::Cmd_DrawPolygonI: {
1925 #ifdef QPAINTBUFFER_DEBUG_DRAW
1926 qDebug() << " -> ExCmd_DrawPolygonI, offset: " << cmd.offset << " size: " << cmd.size
1927 << " mode: " << cmd.extra
1928 << d->ints.at(cmd.offset)
1929 << d->ints.at(cmd.offset+1);
1931 xengine->drawPolygon((QPoint *) (d->ints.constData() + cmd.offset), cmd.size,
1932 (QPaintEngine::PolygonDrawMode) cmd.extra);
1935 case QPaintBufferPrivate::Cmd_DrawEllipseF: {
1936 #ifdef QPAINTBUFFER_DEBUG_DRAW
1937 qDebug() << " -> ExCmd_DrawEllipseF, offset: " << cmd.offset;
1939 xengine->drawEllipse(*(QRectF *)(d->floats.constData() + cmd.offset));
1942 case QPaintBufferPrivate::Cmd_DrawEllipseI: {
1943 #ifdef QPAINTBUFFER_DEBUG_DRAW
1944 qDebug() << " -> ExCmd_DrawEllipseI, offset: " << cmd.offset;
1946 xengine->drawEllipse(*(QRect *)(d->ints.constData() + cmd.offset));
1949 case QPaintBufferPrivate::Cmd_DrawLineF: {
1950 #ifdef QPAINTBUFFER_DEBUG_DRAW
1951 qDebug() << " -> ExCmd_DrawLineF, offset: " << cmd.offset << " size: " << cmd.size;
1953 xengine->drawLines((QLineF *)(d->floats.constData() + cmd.offset), cmd.size);
1956 case QPaintBufferPrivate::Cmd_DrawLineI: {
1957 #ifdef QPAINTBUFFER_DEBUG_DRAW
1958 qDebug() << " -> ExCmd_DrawLineI, offset: " << cmd.offset << " size: " << cmd.size;
1960 xengine->drawLines((QLine *)(d->ints.constData() + cmd.offset), cmd.size);
1963 case QPaintBufferPrivate::Cmd_DrawPointsF: {
1964 #ifdef QPAINTBUFFER_DEBUG_DRAW
1965 qDebug() << " -> ExCmd_DrawPointsF, offset: " << cmd.offset << " size: " << cmd.size;
1967 xengine->drawPoints((QPointF *)(d->floats.constData() + cmd.offset), cmd.size);
1970 case QPaintBufferPrivate::Cmd_DrawPointsI: {
1971 #ifdef QPAINTBUFFER_DEBUG_DRAW
1972 qDebug() << " -> ExCmd_DrawPointsI, offset: " << cmd.offset << " size: " << cmd.size;
1974 xengine->drawPoints((QPoint *)(d->ints.constData() + cmd.offset), cmd.size);
1977 case QPaintBufferPrivate::Cmd_DrawPolylineF: {
1978 #ifdef QPAINTBUFFER_DEBUG_DRAW
1979 qDebug() << " -> ExCmd_DrawPolylineF, offset: " << cmd.offset << " size: " << cmd.size;
1981 xengine->drawPolygon((QPointF *) (d->floats.constData() + cmd.offset), cmd.size, QPaintEngine::PolylineMode);
1984 case QPaintBufferPrivate::Cmd_DrawPolylineI: {
1985 #ifdef QPAINTBUFFER_DEBUG_DRAW
1986 qDebug() << " -> ExCmd_DrawPolylineI, offset: " << cmd.offset << " size: " << cmd.size;
1988 xengine->drawPolygon((QPoint *) (d->ints.constData() + cmd.offset), cmd.size, QPaintEngine::PolylineMode);
1991 case QPaintBufferPrivate::Cmd_DrawRectF: {
1992 #ifdef QPAINTBUFFER_DEBUG_DRAW
1993 qDebug() << " -> ExCmd_DrawRectF, offset: " << cmd.offset << " size: " << cmd.size;
1995 xengine->drawRects((QRectF *) (d->floats.constData() + cmd.offset), cmd.size);
1998 case QPaintBufferPrivate::Cmd_DrawRectI: {
1999 #ifdef QPAINTBUFFER_DEBUG_DRAW
2000 qDebug() << " -> ExCmd_DrawRectI, offset: " << cmd.offset << " size: " << cmd.size;
2002 xengine->drawRects((QRect *) (d->ints.constData() + cmd.offset), cmd.size);
2005 case QPaintBufferPrivate::Cmd_SetClipEnabled: {
2006 bool clipEnabled = d->variants.at(cmd.offset).toBool();
2007 #ifdef QPAINTBUFFER_DEBUG_DRAW
2008 qDebug() << " -> ExCmd_SetClipEnabled:" << clipEnabled;
2010 xengine->state()->clipEnabled = clipEnabled;
2011 xengine->clipEnabledChanged();
2014 case QPaintBufferPrivate::Cmd_ClipVectorPath: {
2015 QVectorPathCmd path(d, cmd);
2016 #ifdef QPAINTBUFFER_DEBUG_DRAW
2017 qDebug() << " -> ExCmd_ClipVectorPath:" << path().elementCount();
2019 xengine->clip(path(), Qt::ClipOperation(cmd.extra));
2023 case QPaintBufferPrivate::Cmd_ClipRect: {
2024 QRect rect(QPoint(d->ints.at(cmd.offset), d->ints.at(cmd.offset + 1)),
2025 QPoint(d->ints.at(cmd.offset + 2), d->ints.at(cmd.offset + 3)));
2026 #ifdef QPAINTBUFFER_DEBUG_DRAW
2027 qDebug() << " -> ExCmd_ClipRect:" << rect << cmd.extra;
2029 xengine->clip(rect, Qt::ClipOperation(cmd.extra));
2032 case QPaintBufferPrivate::Cmd_ClipRegion: {
2033 QRegion region(d->variants.at(cmd.offset).value<QRegion>());
2034 #ifdef QPAINTBUFFER_DEBUG_DRAW
2035 qDebug() << " -> ExCmd_ClipRegion:" << region.boundingRect() << cmd.extra;
2037 xengine->clip(region, Qt::ClipOperation(cmd.extra));
2041 QPainterReplayer::process(cmd);
2046 QDataStream &operator<<(QDataStream &stream, const QPaintBufferCommand &command)
2048 quint32 id = command.id;
2049 quint32 size = command.size;
2050 stream << id << size;
2051 stream << command.offset << command.offset2 << command.extra;
2055 QDataStream &operator>>(QDataStream &stream, QPaintBufferCommand &command)
2059 stream >> id >> size;
2060 stream >> command.offset >> command.offset2 >> command.extra;
2062 command.size = size;
2066 struct QPaintBufferCacheEntry
2068 QVariant::Type type;
2072 struct QPaintBufferCacheEntryV2
2091 Q_DECLARE_METATYPE(QPaintBufferCacheEntry)
2092 Q_DECLARE_METATYPE(QPaintBufferCacheEntryV2)
2095 QDataStream &operator<<(QDataStream &stream, const QPaintBufferCacheEntry &entry)
2097 return stream << entry.type << entry.cacheKey;
2100 QDataStream &operator>>(QDataStream &stream, QPaintBufferCacheEntry &entry)
2102 return stream >> entry.type >> entry.cacheKey;
2105 QDataStream &operator<<(QDataStream &stream, const QPaintBufferCacheEntryV2 &entry)
2107 return stream << entry.bits;
2110 QDataStream &operator>>(QDataStream &stream, QPaintBufferCacheEntryV2 &entry)
2112 return stream >> entry.bits;
2115 static void qRegisterPaintBufferMetaTypes()
2117 qRegisterMetaTypeStreamOperators<QPaintBufferCacheEntry>();
2118 qRegisterMetaTypeStreamOperators<QPaintBufferCacheEntryV2>();
2121 Q_CONSTRUCTOR_FUNCTION(qRegisterPaintBufferMetaTypes)
2123 QDataStream &operator<<(QDataStream &stream, const QPaintBuffer &buffer)
2125 QHash<qint64, uint> pixmapKeys;
2126 QHash<qint64, uint> imageKeys;
2128 QHash<qint64, QPixmap> pixmaps;
2129 QHash<qint64, QImage> images;
2131 QVector<QVariant> variants = buffer.d_ptr->variants;
2132 for (int i = 0; i < variants.size(); ++i) {
2133 const QVariant &v = variants.at(i);
2134 if (v.type() == QVariant::Image) {
2135 const QImage image(v.value<QImage>());
2137 QPaintBufferCacheEntryV2 entry;
2138 entry.flags.type = QPaintBufferCacheEntryV2::ImageKey;
2140 QHash<qint64, uint>::iterator it = imageKeys.find(image.cacheKey());
2141 if (it != imageKeys.end()) {
2142 entry.flags.key = *it;
2144 imageKeys[image.cacheKey()] = entry.flags.key = images.size();
2145 images[images.size()] = image;
2148 variants[i] = QVariant::fromValue(entry);
2149 } else if (v.type() == QVariant::Pixmap) {
2150 const QPixmap pixmap(v.value<QPixmap>());
2152 QPaintBufferCacheEntryV2 entry;
2153 entry.flags.type = QPaintBufferCacheEntryV2::PixmapKey;
2155 QHash<qint64, uint>::iterator it = pixmapKeys.find(pixmap.cacheKey());
2156 if (it != pixmapKeys.end()) {
2157 entry.flags.key = *it;
2159 pixmapKeys[pixmap.cacheKey()] = entry.flags.key = pixmaps.size();
2160 pixmaps[pixmaps.size()] = pixmap;
2163 variants[i] = QVariant::fromValue(entry);
2170 stream << buffer.d_ptr->ints;
2171 stream << buffer.d_ptr->floats;
2173 stream << buffer.d_ptr->commands;
2174 stream << buffer.d_ptr->boundingRect;
2175 stream << buffer.d_ptr->frames;
2180 QDataStream &operator>>(QDataStream &stream, QPaintBuffer &buffer)
2182 QHash<qint64, QPixmap> pixmaps;
2183 QHash<qint64, QImage> images;
2188 stream >> buffer.d_ptr->ints;
2189 stream >> buffer.d_ptr->floats;
2190 stream >> buffer.d_ptr->variants;
2191 stream >> buffer.d_ptr->commands;
2192 stream >> buffer.d_ptr->boundingRect;
2193 stream >> buffer.d_ptr->frames;
2195 QVector<QVariant> &variants = buffer.d_ptr->variants;
2196 for (int i = 0; i < variants.size(); ++i) {
2197 const QVariant &v = variants.at(i);
2198 if (v.canConvert<QPaintBufferCacheEntry>()) {
2199 QPaintBufferCacheEntry entry = v.value<QPaintBufferCacheEntry>();
2200 if (entry.type == QVariant::Image)
2201 variants[i] = QVariant(images.value(entry.cacheKey));
2203 variants[i] = QVariant(pixmaps.value(entry.cacheKey));
2204 } else if (v.canConvert<QPaintBufferCacheEntryV2>()) {
2205 QPaintBufferCacheEntryV2 entry = v.value<QPaintBufferCacheEntryV2>();
2207 if (entry.flags.type == QPaintBufferCacheEntryV2::ImageKey)
2208 variants[i] = QVariant(images.value(entry.flags.key));
2209 else if (entry.flags.type == QPaintBufferCacheEntryV2::PixmapKey)
2210 variants[i] = QVariant(pixmaps.value(entry.flags.key));
2212 qWarning() << "operator<<(QDataStream &stream, QPaintBuffer &buffer): unrecognized cache entry type:" << entry.flags.type;