Commit 4feb152405e96125b6be2807d515293e3f25ab1a

  • avatar
  • Samuel Rødal <sroedal @trol…ech.com>
  • Thu Sep 03 12:13:09 GMT 2009
Added trace graphics system for painting performance profiling.

When running an application with graphics system trace everything that
gets painted to the window surface is proxied through a QPaintBuffer,
which is then both streamed to a trace file and replayed on a raster
window surface. The trace file can then be replayed with
tools/qttracereplay to measure pure painting performance.

Reviewed-by: Gunnar Sletta
src/corelib/global/qnamespace.h
(2 / 1)
  
16541654 Pbuffer = 0x06, // GL pbuffer
16551655 FramebufferObject = 0x07, // GL framebuffer object
16561656 CustomRaster = 0x08,
1657 MacQuartz = 0x09
1657 MacQuartz = 0x09,
1658 PaintBuffer = 0x0a
16581659 };
16591660 enum RelayoutType {
16601661 RelayoutNormal,
src/gui/painting/painting.pri
(2 / 0)
  
4242 painting/qtransform.h \
4343 painting/qwindowsurface_p.h \
4444 painting/qwmatrix.h \
45 painting/qpaintbuffer_p.h
4546
4647
4748SOURCES += \
8080 painting/qtextureglyphcache.cpp \
8181 painting/qtransform.cpp \
8282 painting/qwindowsurface.cpp \
83 painting/qpaintbuffer.cpp
8384
8485 SOURCES += \
8586 painting/qpaintengine_raster.cpp \
src/gui/painting/qemulationpaintengine_p.h
(2 / 0)
  
9292
9393 virtual void setState(QPainterState *s);
9494
95 virtual uint flags() const {return QPaintEngineEx::IsEmulationEngine | QPaintEngineEx::DoNotEmulate;}
96
9597 inline QPainterState *state() { return (QPainterState *)QPaintEngine::state; }
9698 inline const QPainterState *state() const { return (const QPainterState *)QPaintEngine::state; }
9799
src/gui/painting/qpaintbuffer.cpp
(1744 / 0)
  
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** Contact: Nokia Corporation (qt-info@nokia.com)
5**
6** This file is part of the QtGui module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** No Commercial Usage
10** This file contains pre-release code and may not be distributed.
11** You may use this file in accordance with the terms and conditions
12** contained in the Technology Preview License Agreement accompanying
13** this package.
14**
15** GNU Lesser General Public License Usage
16** Alternatively, this file may be used under the terms of the GNU Lesser
17** General Public License version 2.1 as published by the Free Software
18** Foundation and appearing in the file LICENSE.LGPL included in the
19** packaging of this file. Please review the following information to
20** ensure the GNU Lesser General Public License version 2.1 requirements
21** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22**
23** In addition, as a special exception, Nokia gives you certain
24** additional rights. These rights are described in the Nokia Qt LGPL
25** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
26** package.
27**
28** If you have questions regarding the use of this file, please contact
29** Nokia at qt-info@nokia.com.
30**
31**
32**
33**
34**
35**
36**
37**
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41#include <qmath.h>
42#include <private/qpainterpath_p.h>
43#include <private/qpaintbuffer_p.h>
44//#include <private/qtextengine_p.h>
45#include <private/qfontengine_p.h>
46#include <private/qemulationpaintengine_p.h>
47
48#include <QDebug>
49
50//#define QPAINTBUFFER_DEBUG_DRAW
51
52extern int qt_defaultDpiX();
53extern int qt_defaultDpiY();
54extern void qt_format_text(const QFont &font,
55 const QRectF &_r, int tf, const QTextOption *option, const QString& str, QRectF *brect,
56 int tabstops, int* tabarray, int tabarraylen,
57 QPainter *painter);
58
59QTextItemIntCopy::QTextItemIntCopy(const QTextItem &item)
60 : m_item(static_cast<const QTextItemInt &>(item))
61{
62 QChar *chars = new QChar[m_item.num_chars];
63 unsigned short *logClusters = new unsigned short[m_item.num_chars];
64 memcpy(chars, m_item.chars, m_item.num_chars * sizeof(QChar));
65 memcpy(logClusters, m_item.logClusters, m_item.num_chars * sizeof(unsigned short));
66 m_item.chars = chars;
67 m_item.logClusters = logClusters;
68
69 const int size = QGlyphLayout::spaceNeededForGlyphLayout(m_item.glyphs.numGlyphs);
70 char *glyphLayoutData = new char[size];
71 QGlyphLayout glyphs(glyphLayoutData, m_item.glyphs.numGlyphs);
72 memcpy(glyphs.offsets, m_item.glyphs.offsets, m_item.glyphs.numGlyphs * sizeof(QFixedPoint));
73 memcpy(glyphs.glyphs, m_item.glyphs.glyphs, m_item.glyphs.numGlyphs * sizeof(HB_Glyph));
74 memcpy(glyphs.advances_x, m_item.glyphs.advances_x, m_item.glyphs.numGlyphs * sizeof(QFixed));
75 memcpy(glyphs.advances_y, m_item.glyphs.advances_y, m_item.glyphs.numGlyphs * sizeof(QFixed));
76 memcpy(glyphs.justifications, m_item.glyphs.justifications, m_item.glyphs.numGlyphs * sizeof(QGlyphJustification));
77 memcpy(glyphs.attributes, m_item.glyphs.attributes, m_item.glyphs.numGlyphs * sizeof(HB_GlyphAttributes));
78 m_item.glyphs = glyphs;
79
80 m_font = *m_item.f;
81 m_item.f = &m_font;
82
83 m_item.fontEngine->ref.ref(); // Increment reference count.
84}
85
86QTextItemIntCopy::~QTextItemIntCopy()
87{
88 delete m_item.chars;
89 delete m_item.logClusters;
90 delete m_item.glyphs.data();
91 if (!m_item.fontEngine->ref.deref())
92 delete m_item.fontEngine;
93}
94
95/************************************************************************
96 *
97 * QPaintBufferSignalProxy
98 *
99 ************************************************************************/
100
101Q_GLOBAL_STATIC(QPaintBufferSignalProxy, theSignalProxy)
102
103QPaintBufferSignalProxy *QPaintBufferSignalProxy::instance()
104{
105 return theSignalProxy();
106}
107
108/************************************************************************
109 *
110 * QPaintBufferPrivate
111 *
112 ************************************************************************/
113
114QPaintBufferPrivate::QPaintBufferPrivate()
115 : ref(1), engine(0), penWidthAdjustment(0)
116 , calculateBoundingRect(true)
117 , cache(0)
118{
119}
120
121QPaintBufferPrivate::~QPaintBufferPrivate()
122{
123 QPaintBufferSignalProxy::instance()->emitAboutToDestroy(this);
124
125 for (int i = 0; i < commands.size(); ++i) {
126 const QPaintBufferCommand &cmd = commands.at(i);
127 if (cmd.id == QPaintBufferPrivate::Cmd_DrawTextItem)
128 delete reinterpret_cast<QTextItemIntCopy *>(qVariantValue<void *>(variants.at(cmd.offset)));
129 }
130}
131
132
133inline void QPaintBufferPrivate::updateBoundingRect(const QRectF &br)
134{
135 // transform to device coords and adjust for pen width
136 Q_ASSERT(engine && engine->painter());
137 QPainter *painter = engine->painter();
138 const QTransform transform = painter->transform();
139 QRectF devRect = transform.mapRect(br);
140 if (penWidthAdjustment > 0) {
141 devRect = devRect.adjusted(-penWidthAdjustment, -penWidthAdjustment,
142 penWidthAdjustment, penWidthAdjustment);
143 }
144
145 if (boundingRect.isEmpty()) {
146 boundingRect = devRect;
147 } else {
148 qreal min_x = qMin(devRect.left(), boundingRect.left());
149 qreal min_y = qMin(devRect.top(), boundingRect.top());
150 qreal max_x = qMax(devRect.right(), boundingRect.right());
151 qreal max_y = qMax(devRect.bottom(), boundingRect.bottom());
152 boundingRect = QRectF(min_x, min_y, max_x - min_x, max_y - min_y);
153 }
154 if (painter->hasClipping())
155 boundingRect &= transform.mapRect(painter->clipRegion().boundingRect());
156}
157
158
159/************************************************************************
160 *
161 * QPaintBuffer
162 *
163 ************************************************************************/
164
165
166
167QPaintBuffer::QPaintBuffer()
168 : d_ptr(new QPaintBufferPrivate)
169{
170}
171
172QPaintBuffer::~QPaintBuffer()
173{
174 if (!d_ptr->ref.deref())
175 delete d_ptr;
176}
177
178QPaintBuffer::QPaintBuffer(const QPaintBuffer &other)
179 : QPaintDevice(), d_ptr(other.d_ptr)
180{
181 d_ptr->ref.ref();
182}
183
184QPaintEngine *QPaintBuffer::paintEngine() const
185{
186 QPaintBufferPrivate *d = const_cast<QPaintBuffer *>(this)->d_ptr;
187 if (!d->engine)
188 d->engine = new QPaintBufferEngine(d);
189 return d->engine;
190}
191
192
193int QPaintBuffer::metric(PaintDeviceMetric metric) const
194{
195 int val = 0;
196 switch (metric) {
197 case PdmWidth:
198 val = qCeil(d_ptr->boundingRect.width());
199 break;
200 case PdmHeight:
201 val = qCeil(d_ptr->boundingRect.height());
202 break;
203 case PdmDpiX:
204 case PdmPhysicalDpiX:
205 val = qt_defaultDpiX();
206 break;
207 case PdmDpiY:
208 case PdmPhysicalDpiY:
209 val = qt_defaultDpiY();
210 break;
211 default:
212 val = QPaintDevice::metric(metric);
213 }
214
215 return val;
216}
217
218int QPaintBuffer::devType() const
219{
220 return QInternal::PaintBuffer;
221}
222
223QPaintBuffer &QPaintBuffer::operator=(const QPaintBuffer &other)
224{
225 if (other.d_ptr != d_ptr) {
226 QPaintBufferPrivate *data = other.d_ptr;
227 data->ref.ref();
228 if (d_ptr->ref.deref())
229 delete d_ptr;
230 d_ptr = data;
231 }
232 return *this;
233}
234
235bool QPaintBuffer::isEmpty() const
236{
237 return d_ptr->commands.isEmpty();
238}
239
240
241
242void QPaintBuffer::draw(QPainter *painter) const
243{
244#ifdef QPAINTBUFFER_DEBUG_DRAW
245 qDebug() << "QPaintBuffer::draw() --------------------------------";
246
247// printf("Float buffer:");
248// for (int i=0; i<d->floats.size(); i++) {
249// if ((i % 10) == 0) {
250// printf("\n%4d-%4d: ", i, i+9);
251// }
252// printf("%4.2f ", d->floats[i]);
253// }
254// printf("\n");
255
256// printf("Int Buffer:");
257// for (int i=0; i<d->ints.size(); i++) {
258// if ((i % 10) == 0) {
259// printf("\n%4d-%4d: ", i, i+10);
260// }
261// printf("%5d", d->ints[i]);
262// }
263// printf("\n");
264#endif
265
266 if (painter && !painter->isActive())
267 return;
268
269 QPaintEngineEx *xengine = painter->paintEngine()->isExtended()
270 ? (QPaintEngineEx *) painter->paintEngine() : 0;
271 if (xengine) {
272 QPaintEngineExReplayer player;
273 player.draw(*this, painter);
274 } else {
275 QPainterReplayer player;
276 player.draw(*this, painter);
277 }
278
279#ifdef QPAINTBUFFER_DEBUG_DRAW
280 qDebug() << "QPaintBuffer::draw() -------------------------------- DONE!";
281#endif
282}
283
284
285QRectF QPaintBuffer::boundingRect() const
286{
287 return d_ptr->boundingRect;
288}
289
290void QPaintBuffer::setBoundingRect(const QRectF &rect)
291{
292 d_ptr->boundingRect = rect;
293 d_ptr->calculateBoundingRect = false;
294}
295
296
297class QPaintBufferEnginePrivate : public QPaintEngineExPrivate
298{
299 Q_DECLARE_PUBLIC(QPaintBufferEngine)
300public:
301 void systemStateChanged() {
302 Q_Q(QPaintBufferEngine);
303 q->buffer->addCommand(QPaintBufferPrivate::Cmd_SystemStateChanged, QVariant(systemClip));
304 }
305};
306
307
308/************************************************************************
309 *
310 * QPaintBufferEngine
311 *
312 ************************************************************************/
313
314QPaintBufferEngine::QPaintBufferEngine(QPaintBufferPrivate *b)
315 : QPaintEngineEx(*(new QPaintBufferEnginePrivate))
316 , buffer(b)
317 , m_begin_detected(false)
318 , m_save_detected(false)
319 , m_stream_raw_text_items(false)
320{
321}
322
323bool QPaintBufferEngine::begin(QPaintDevice *)
324{
325 Q_D(QPaintBufferEngine);
326 painter()->save();
327 d->systemStateChanged();
328 return true;
329}
330
331bool QPaintBufferEngine::end()
332{
333 painter()->restore();
334 m_created_state = 0;
335 return true;
336}
337
338QPainterState *QPaintBufferEngine::createState(QPainterState *orig) const
339{
340#ifdef QPAINTBUFFER_DEBUG_DRAW
341 qDebug() << "QPaintBufferEngine: createState, orig=" << orig << ", current=" << state();
342#endif
343
344 Q_ASSERT(!m_begin_detected);
345 Q_ASSERT(!m_save_detected);
346
347 if (orig == 0) {
348 m_begin_detected = true;
349 return new QPainterState();
350 } else {
351 m_save_detected = true;
352 return new QPainterState(orig);
353 }
354}
355
356void QPaintBufferEngine::clip(const QVectorPath &path, Qt::ClipOperation op)
357{
358#ifdef QPAINTBUFFER_DEBUG_DRAW
359 qDebug() << "QPaintBufferEngine: clip vpath:" << path.elementCount() << "op:" << op;
360#endif
361 QPaintBufferCommand *cmd =
362 buffer->addCommand(QPaintBufferPrivate::Cmd_ClipVectorPath, path);
363 cmd->extra = op;
364}
365
366void QPaintBufferEngine::clip(const QRect &rect, Qt::ClipOperation op)
367{
368#ifdef QPAINTBUFFER_DEBUG_DRAW
369 qDebug() << "QPaintBufferEngine: clip rect:" << rect << "op:" << op;
370#endif
371 QPaintBufferCommand *cmd =
372 buffer->addCommand(QPaintBufferPrivate::Cmd_ClipRect, (int *) &rect, 4, 1);
373 cmd->extra = op;
374}
375
376void QPaintBufferEngine::clip(const QRegion &region, Qt::ClipOperation op)
377{
378#ifdef QPAINTBUFFER_DEBUG_DRAW
379 qDebug() << "QPaintBufferEngine: clip region br:" << region.boundingRect() << "op:" << op;
380#endif
381 QPaintBufferCommand *cmd =
382 buffer->addCommand(QPaintBufferPrivate::Cmd_ClipRegion, QVariant(region));
383 cmd->extra = op;
384}
385
386void QPaintBufferEngine::clip(const QPainterPath &path, Qt::ClipOperation op)
387{
388 // ### TODO
389// QPaintBufferCommand *cmd =
390// buffer->addCommand(QPaintBufferPrivate::Cmd_ClipPath, QVariant(path));
391// cmd->extra = op;
392 QPaintEngineEx::clip(path, op);
393}
394
395void QPaintBufferEngine::clipEnabledChanged()
396{
397#ifdef QPAINTBUFFER_DEBUG_DRAW
398 qDebug() << "QPaintBufferEngine: clip enable change" << state()->clipEnabled;
399#endif
400
401 buffer->addCommand(QPaintBufferPrivate::Cmd_SetClipEnabled, state()->clipEnabled);
402}
403
404void QPaintBufferEngine::penChanged()
405{
406#ifdef QPAINTBUFFER_DEBUG_DRAW
407 qDebug() << "QPaintBufferEngine:" << state()->pen;
408#endif
409 const QPen &pen = state()->pen;
410
411 if (!buffer->commands.isEmpty()
412 && buffer->commands.last().id == QPaintBufferPrivate::Cmd_SetPen) {
413 buffer->variants[buffer->commands.last().offset] = pen;
414 return;
415 }
416 if (buffer->calculateBoundingRect) {
417 if (pen.style() == Qt::NoPen) {
418 buffer->penWidthAdjustment = 0;
419 } else {
420 qreal penWidth = (pen.widthF() == 0) ? 1 : pen.widthF();
421 QPointF transformedWidth(penWidth, penWidth);
422 if (!pen.isCosmetic())
423 transformedWidth = painter()->transform().map(transformedWidth);
424 buffer->penWidthAdjustment = transformedWidth.x() / 2.0;
425 }
426 }
427 buffer->addCommand(QPaintBufferPrivate::Cmd_SetPen, pen);
428}
429
430void QPaintBufferEngine::brushChanged()
431{
432#ifdef QPAINTBUFFER_DEBUG_DRAW
433 qDebug() << "QPaintBufferEngine:" << state()->brush;
434#endif
435 const QBrush &brush = state()->brush;
436
437 if (!buffer->commands.isEmpty()
438 && buffer->commands.last().id == QPaintBufferPrivate::Cmd_SetBrush) {
439 buffer->variants[buffer->commands.last().offset] = brush;
440 return;
441 }
442
443 buffer->addCommand(QPaintBufferPrivate::Cmd_SetBrush, brush);
444}
445
446void QPaintBufferEngine::brushOriginChanged()
447{
448#ifdef QPAINTBUFFER_DEBUG_DRAW
449 qDebug() << "QPaintBufferEngine: brush origin changed" << state()->brushOrigin;
450#endif
451 buffer->addCommand(QPaintBufferPrivate::Cmd_SetBrushOrigin, state()->brushOrigin);
452}
453
454void QPaintBufferEngine::opacityChanged()
455{
456#ifdef QPAINTBUFFER_DEBUG_DRAW
457 qDebug() << "QPaintBufferEngine: opacity changed" << state()->opacity;
458#endif
459 buffer->addCommand(QPaintBufferPrivate::Cmd_SetOpacity, state()->opacity);
460}
461
462void QPaintBufferEngine::compositionModeChanged()
463{
464#ifdef QPAINTBUFFER_DEBUG_DRAW
465 qDebug() << "QPaintBufferEngine: composition mode" << state()->composition_mode;
466#endif
467 QPaintBufferCommand *cmd =
468 buffer->addCommand(QPaintBufferPrivate::Cmd_SetCompositionMode);
469 cmd->extra = state()->composition_mode;
470}
471
472void QPaintBufferEngine::renderHintsChanged()
473{
474#ifdef QPAINTBUFFER_DEBUG_DRAW
475 qDebug() << "QPaintBufferEngine: render hints changed" << state()->renderHints;
476#endif
477 QPaintBufferCommand *cmd =
478 buffer->addCommand(QPaintBufferPrivate::Cmd_SetRenderHints);
479 cmd->extra = state()->renderHints;
480}
481
482void QPaintBufferEngine::transformChanged()
483{
484 // ### accumulate, like in QBrush case...
485 if (!buffer->commands.isEmpty()
486 && buffer->commands.last().id == QPaintBufferPrivate::Cmd_SetTransform) {
487#ifdef QPAINTBUFFER_DEBUG_DRAW
488 qDebug() << "QPaintBufferEngine: compressing " << state()->matrix;
489#endif
490 buffer->variants[buffer->commands.last().offset] = state()->matrix;
491 return;
492 }
493
494#ifdef QPAINTBUFFER_DEBUG_DRAW
495 qDebug() << "QPaintBufferEngine: " << state()->matrix;
496#endif
497 buffer->addCommand(QPaintBufferPrivate::Cmd_SetTransform, state()->matrix);
498}
499
500void QPaintBufferEngine::backgroundModeChanged()
501{
502#ifdef QPAINTBUFFER_DEBUG_DRAW
503 qDebug() << "QPaintEngineBuffer: background mode changed" << state()->bgMode;
504#endif
505 QPaintBufferCommand *cmd = buffer->addCommand(QPaintBufferPrivate::Cmd_SetBackgroundMode);
506 cmd->extra = state()->bgMode;
507}
508
509void QPaintBufferEngine::draw(const QVectorPath &path)
510{
511#ifdef QPAINTBUFFER_DEBUG_DRAW
512 qDebug() << "QPaintBufferEngine: draw vpath:" << path.elementCount();
513#endif
514 buffer->addCommand(QPaintBufferPrivate::Cmd_DrawVectorPath, path);
515// if (buffer->calculateBoundingRect) {
516// QRealRect r = path.controlPointRect();
517// buffer->updateBoundingRect(QRectF(r.x1, r.y1, r.x2 - r.x1, r.y2 - r.y1));
518// }
519}
520
521void QPaintBufferEngine::fill(const QVectorPath &path, const QBrush &brush)
522{
523#ifdef QPAINTBUFFER_DEBUG_DRAW
524 qDebug() << "QPaintBufferEngine: fill vpath:" << path.elementCount() << brush;
525#endif
526 QPaintBufferCommand *cmd =
527 buffer->addCommand(QPaintBufferPrivate::Cmd_FillVectorPath, path);
528 cmd->extra = buffer->addData(QVariant(brush));
529// if (buffer->calculateBoundingRect) {
530// QRealRect r = path.controlPointRect();
531// buffer->updateBoundingRect(QRectF(r.x1, r.y1, r.x2 - r.x1, r.y2 - r.y1));
532// }
533}
534
535void QPaintBufferEngine::stroke(const QVectorPath &path, const QPen &pen)
536{
537#ifdef QPAINTBUFFER_DEBUG_DRAW
538 qDebug() << "QPaintBufferEngine: stroke vpath:" << path.elementCount() << pen;
539#endif
540 QPaintBufferCommand *cmd =
541 buffer->addCommand(QPaintBufferPrivate::Cmd_StrokeVectorPath, path);
542 cmd->extra = buffer->addData(QVariant(pen));
543// if (buffer->calculateBoundingRect) {
544// QRealRect r = path.controlPointRect();
545// buffer->updateBoundingRect(QRectF(r.x1, r.y1, r.x2 - r.x1, r.y2 - r.y1));
546// }
547}
548
549void QPaintBufferEngine::fillRect(const QRectF &rect, const QBrush &brush)
550{
551#ifdef QPAINTBUFFER_DEBUG_DRAW
552 qDebug() << "QPaintBufferEngine: fillRect brush:" << rect << brush;
553#endif
554 QPaintBufferCommand *cmd =
555 buffer->addCommand(QPaintBufferPrivate::Cmd_FillRectBrush, (qreal *) &rect, 4, 1);
556 cmd->extra = buffer->addData(brush);
557 if (buffer->calculateBoundingRect)
558 buffer->updateBoundingRect(rect);
559}
560
561void QPaintBufferEngine::fillRect(const QRectF &rect, const QColor &color)
562{
563#ifdef QPAINTBUFFER_DEBUG_DRAW
564 qDebug() << "QPaintBufferEngine: fillRect color:" << rect << color;
565#endif
566 QPaintBufferCommand *cmd =
567 buffer->addCommand(QPaintBufferPrivate::Cmd_FillRectColor, (qreal *) &rect, 4, 1);
568 cmd->extra = buffer->addData(color);
569 if (buffer->calculateBoundingRect)
570 buffer->updateBoundingRect(rect);
571}
572
573void QPaintBufferEngine::drawRects(const QRect *rects, int rectCount)
574{
575#ifdef QPAINTBUFFER_DEBUG_DRAW
576 qDebug() << "QPaintBufferEngine: drawRectsI:" << rectCount;
577#endif
578 QPaintBufferCommand *cmd =
579 buffer->addCommand(QPaintBufferPrivate::Cmd_DrawRectI, (int *) rects, 4 * rectCount, rectCount);
580 cmd->extra = rectCount;
581
582 if (buffer->calculateBoundingRect) {
583 if (rectCount == 1) {
584 buffer->updateBoundingRect(rects[0]);
585 } else {
586 int min_x = rects[0].left();
587 int min_y = rects[0].top();
588 int max_x = rects[0].left() + rects[0].width();
589 int max_y = rects[0].top() + rects[0].height();
590 for (int i=1; i< rectCount; ++i) {
591 if (rects[i].left() < min_x)
592 min_x = rects[i].left();
593 if (rects[i].top() < min_y)
594 min_y = rects[i].top();
595 if (rects[i].right() > max_x)
596 max_x = rects[i].left() + rects[i].width();
597 if (rects[i].bottom() > max_y)
598 max_y = rects[i].top() + rects[i].height();
599
600 }
601 buffer->updateBoundingRect(QRectF(min_x, min_y, max_x - min_x, max_y - min_y));
602 }
603 }
604}
605
606void QPaintBufferEngine::drawRects(const QRectF *rects, int rectCount)
607{
608#ifdef QPAINTBUFFER_DEBUG_DRAW
609 qDebug() << "QPaintBufferEngine: drawRectsF:" << rectCount;
610#endif
611 QPaintBufferCommand *cmd =
612 buffer->addCommand(QPaintBufferPrivate::Cmd_DrawRectF, (qreal *) rects, 4 * rectCount, rectCount);
613 cmd->extra = rectCount;
614
615 if (buffer->calculateBoundingRect) {
616 if (rectCount == 1) {
617 buffer->updateBoundingRect(rects[0]);
618 } else {
619 qreal min_x = rects[0].left();
620 qreal min_y = rects[0].top();
621 qreal max_x = rects[0].right();
622 qreal max_y = rects[0].bottom();
623 for (int i=1; i< rectCount; ++i) {
624 if (rects[i].left() < min_x)
625 min_x = rects[i].left();
626 if (rects[i].top() < min_y)
627 min_y = rects[i].top();
628 if (rects[i].right() > max_x)
629 max_x = rects[i].right();
630 if (rects[i].bottom() > max_y)
631 max_y = rects[i].bottom();
632
633 }
634 buffer->updateBoundingRect(QRectF(min_x, min_y, max_x - min_x, max_y - min_y));
635 }
636 }
637}
638
639void QPaintBufferEngine::drawLines(const QLine *lines, int lineCount)
640{
641#ifdef QPAINTBUFFER_DEBUG_DRAW
642 qDebug() << "QPaintBufferEngine: drawLinesI:" << lineCount;
643#endif
644 QPaintBufferCommand *cmd =
645 buffer->addCommand(QPaintBufferPrivate::Cmd_DrawLineI, (int *) lines, 4 * lineCount, lineCount);
646 cmd->extra = lineCount;
647
648 if (buffer->calculateBoundingRect) {
649 int min_x = lines[0].p1().x();
650 int min_y = lines[0].p1().y();
651 int max_x = lines[0].p2().x();
652 int max_y = lines[0].p2().y();
653 if (min_x > max_x)
654 qSwap(min_x, max_x);
655 if (min_y > max_y)
656 qSwap(min_y, max_y);
657 for (int i=1; i < lineCount; ++i) {
658 int p1_x = lines[i].p1().x();
659 int p1_y = lines[i].p1().y();
660 int p2_x = lines[i].p2().x();
661 int p2_y = lines[i].p2().y();
662 if (p1_x > p2_x) {
663 min_x = qMin(p2_x, min_x);
664 max_x = qMax(p1_x, max_x);
665 } else {
666 min_x = qMin(p1_x, min_x);
667 max_x = qMax(p2_x, max_x);
668 }
669 if (p1_y > p2_y) {
670 min_y = qMin(p2_y, min_y);
671 max_y = qMax(p1_y, max_y);
672 } else {
673 min_y = qMin(p1_y, min_y);
674 max_y = qMax(p2_y, max_y);
675 }
676 }
677 buffer->updateBoundingRect(QRectF(min_x, min_y, max_x - min_x, max_y - min_y));
678 }
679}
680
681void QPaintBufferEngine::drawLines(const QLineF *lines, int lineCount)
682{
683#ifdef QPAINTBUFFER_DEBUG_DRAW
684 qDebug() << "QPaintBufferEngine: drawLinesF:" << lineCount;
685#endif
686 QPaintBufferCommand *cmd =
687 buffer->addCommand(QPaintBufferPrivate::Cmd_DrawLineF, (qreal *) lines, 4 * lineCount, lineCount);
688 cmd->extra = lineCount;
689
690 if (buffer->calculateBoundingRect) {
691 qreal min_x = lines[0].p1().x();
692 qreal min_y = lines[0].p1().y();
693 qreal max_x = lines[0].p2().x();
694 qreal max_y = lines[0].p2().y();
695 if (min_x > max_x)
696 qSwap(min_x, max_x);
697 if (min_y > max_y)
698 qSwap(min_y, max_y);
699 for (int i=1; i < lineCount; ++i) {
700 qreal p1_x = lines[i].p1().x();
701 qreal p1_y = lines[i].p1().y();
702 qreal p2_x = lines[i].p2().x();
703 qreal p2_y = lines[i].p2().y();
704 if (p1_x > p2_x) {
705 min_x = qMin(p2_x, min_x);
706 max_x = qMax(p1_x, max_x);
707 } else {
708 min_x = qMin(p1_x, min_x);
709 max_x = qMax(p2_x, max_x);
710 }
711 if (p1_y > p2_y) {
712 min_y = qMin(p2_y, min_y);
713 max_y = qMax(p1_y, max_y);
714 } else {
715 min_y = qMin(p1_y, min_y);
716 max_y = qMax(p2_y, max_y);
717 }
718 }
719 buffer->updateBoundingRect(QRectF(min_x, min_y, max_x - min_x, max_y - min_y));
720 }
721}
722
723void QPaintBufferEngine::drawEllipse(const QRectF &r)
724{
725#ifdef QPAINTBUFFER_DEBUG_DRAW
726 qDebug() << "QPaintBufferEngine: drawEllipseF:" << r;
727#endif
728 buffer->addCommand(QPaintBufferPrivate::Cmd_DrawEllipseF, (qreal *) &r, 4, 1);
729 if (buffer->calculateBoundingRect)
730 buffer->updateBoundingRect(r);
731}
732
733void QPaintBufferEngine::drawEllipse(const QRect &r)
734{
735#ifdef QPAINTBUFFER_DEBUG_DRAW
736 qDebug() << "QPaintBufferEngine: drawEllipseI:" << r;
737#endif
738 buffer->addCommand(QPaintBufferPrivate::Cmd_DrawEllipseI, (int *) &r, 4, 1);
739 if (buffer->calculateBoundingRect)
740 buffer->updateBoundingRect(r);
741}
742
743void QPaintBufferEngine::drawPath(const QPainterPath &path)
744{
745#ifdef QPAINTBUFFER_DEBUG_DRAW
746 qDebug() << "QPaintBufferEngine: drawPath: element count:" << path.elementCount();
747#endif
748 // ### Path -> QVariant
749 // buffer->addCommand(QPaintBufferPrivate::Cmd_DrawPath, QVariant(path));
750 QPaintEngineEx::drawPath(path);
751
752 if (buffer->calculateBoundingRect)
753 buffer->updateBoundingRect(path.boundingRect());
754}
755
756void QPaintBufferEngine::drawPoints(const QPoint *points, int pointCount)
757{
758#ifdef QPAINTBUFFER_DEBUG_DRAW
759 qDebug() << "QPaintBufferEngine: drawPointsI: " << pointCount;
760#endif
761 buffer->addCommand(QPaintBufferPrivate::Cmd_DrawPointsI, (int *) points, 2 * pointCount, pointCount);
762
763 if (buffer->calculateBoundingRect) {
764 int min_x = points[0].x();
765 int min_y = points[0].y();
766 int max_x = points[0].x()+1;
767 int max_y = points[0].y()+1;
768 for (int i=1; i<pointCount; ++i) {
769 int x = points[i].x();
770 int y = points[i].y();
771 min_x = qMin(min_x, x);
772 min_y = qMin(min_y, y);
773 max_x = qMax(max_x, x+1);
774 max_y = qMax(max_y, y+1);
775 }
776 buffer->updateBoundingRect(QRectF(min_x, min_y, max_x - min_x, max_y - min_y));
777 }
778}
779
780void QPaintBufferEngine::drawPoints(const QPointF *points, int pointCount)
781{
782#ifdef QPAINTBUFFER_DEBUG_DRAW
783 qDebug() << "QPaintBufferEngine: drawPointsF: " << pointCount;
784#endif
785 buffer->addCommand(QPaintBufferPrivate::Cmd_DrawPointsF, (qreal *) points, 2 * pointCount, pointCount);
786
787 if (buffer->calculateBoundingRect) {
788 qreal min_x = points[0].x();
789 qreal min_y = points[0].y();
790 qreal max_x = points[0].x()+1;
791 qreal max_y = points[0].y()+1;
792 for (int i=1; i<pointCount; ++i) {
793 qreal x = points[i].x();
794 qreal y = points[i].y();
795 min_x = qMin(min_x, x);
796 min_y = qMin(min_y, y);
797 max_x = qMax(max_x, x+1);
798 max_y = qMax(max_y, y+1);
799 }
800 buffer->updateBoundingRect(QRectF(min_x, min_y, max_x - min_x, max_y - min_y));
801 }
802}
803
804void QPaintBufferEngine::drawPolygon(const QPoint *pts, int count, PolygonDrawMode mode)
805{
806#ifdef QPAINTBUFFER_DEBUG_DRAW
807 qDebug() << "QPaintBufferEngine: drawPolygonI: size:" << count << ", mode:" << mode;
808#endif
809 if (mode == QPaintEngine::OddEvenMode || mode == QPaintEngine::WindingMode) {
810 QPaintBufferCommand *cmd = buffer->addCommand(QPaintBufferPrivate::Cmd_DrawPolygonI,
811 (int *) pts, 2 * count, count);
812 cmd->extra = mode;
813 } else if (mode == QPaintEngine::PolylineMode) {
814 buffer->addCommand(QPaintBufferPrivate::Cmd_DrawPolylineI, (int *) pts, 2 * count, count);
815 } else {
816 buffer->addCommand(QPaintBufferPrivate::Cmd_DrawConvexPolygonI, (int *) pts, 2 * count, count);
817 }
818
819 if (buffer->calculateBoundingRect) {
820 int min_x = pts[0].x();
821 int min_y = pts[0].y();
822 int max_x = pts[0].x();
823 int max_y = pts[0].y();
824 for (int i=1; i<count; ++i) {
825 int x = pts[i].x();
826 int y = pts[i].y();
827 min_x = qMin(min_x, x);
828 min_y = qMin(min_y, y);
829 max_x = qMax(max_x, x);
830 max_y = qMax(max_y, y);
831 }
832 buffer->updateBoundingRect(QRectF(min_x, min_y, max_x - min_x, max_y - min_y));
833 }
834}
835
836void QPaintBufferEngine::drawPolygon(const QPointF *pts, int count, PolygonDrawMode mode)
837{
838#ifdef QPAINTBUFFER_DEBUG_DRAW
839 qDebug() << "QPaintBufferEngine: drawPolygonF: size:" << count << ", mode:" << mode;
840#endif
841 if (mode == QPaintEngine::OddEvenMode || mode == QPaintEngine::WindingMode) {
842 QPaintBufferCommand *cmd = buffer->addCommand(QPaintBufferPrivate::Cmd_DrawPolygonF,
843 (qreal *) pts, 2 * count, count);
844 cmd->extra = mode;
845 } else if (mode == QPaintEngine::PolylineMode) {
846 buffer->addCommand(QPaintBufferPrivate::Cmd_DrawPolylineF, (qreal *) pts, 2 * count, count);
847 } else {
848 buffer->addCommand(QPaintBufferPrivate::Cmd_DrawConvexPolygonF, (qreal *) pts, 2 * count, count);
849 }
850
851 if (buffer->calculateBoundingRect) {
852 qreal min_x = pts[0].x();
853 qreal min_y = pts[0].y();
854 qreal max_x = pts[0].x();
855 qreal max_y = pts[0].y();
856 for (int i=1; i<count; ++i) {
857 qreal x = pts[i].x();
858 qreal y = pts[i].y();
859 min_x = qMin(min_x, x);
860 min_y = qMin(min_y, y);
861 max_x = qMax(max_x, x);
862 max_y = qMax(max_y, y);
863 }
864 buffer->updateBoundingRect(QRectF(min_x, min_y, max_x - min_x, max_y - min_y));
865 }
866}
867
868void QPaintBufferEngine::drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr)
869{
870#ifdef QPAINTBUFFER_DEBUG_DRAW
871 qDebug() << "QPaintBufferEngine: drawPixmap: src/dest rects " << r << sr;
872#endif
873 QPaintBufferCommand *cmd =
874 buffer->addCommand(QPaintBufferPrivate::Cmd_DrawPixmapRect, QVariant(pm));
875 cmd->extra = buffer->addData((qreal *) &r, 4);
876 buffer->addData((qreal *) &sr, 4);
877 if (buffer->calculateBoundingRect)
878 buffer->updateBoundingRect(r);
879}
880
881void QPaintBufferEngine::drawPixmap(const QPointF &pos, const QPixmap &pm)
882{
883#ifdef QPAINTBUFFER_DEBUG_DRAW
884 qDebug() << "QPaintBufferEngine: drawPixmap: pos:" << pos;
885#endif
886 QPaintBufferCommand *cmd =
887 buffer->addCommand(QPaintBufferPrivate::Cmd_DrawPixmapPos, QVariant(pm));
888 cmd->extra = buffer->addData((qreal *) &pos, 2);
889 if (buffer->calculateBoundingRect)
890 buffer->updateBoundingRect(QRectF(pos, pm.size()));
891}
892
893void QPaintBufferEngine::drawImage(const QRectF &r, const QImage &image, const QRectF &sr,
894 Qt::ImageConversionFlags /*flags */)
895{
896#ifdef QPAINTBUFFER_DEBUG_DRAW
897 qDebug() << "QPaintBufferEngine: drawImage: src/dest rects " << r << sr;
898#endif
899 QPaintBufferCommand *cmd =
900 buffer->addCommand(QPaintBufferPrivate::Cmd_DrawPixmapRect, QVariant(image));
901 cmd->extra = buffer->addData((qreal *) &r, 4);
902 buffer->addData((qreal *) &sr, 4);
903 // ### flags...
904 if (buffer->calculateBoundingRect)
905 buffer->updateBoundingRect(r);
906}
907
908void QPaintBufferEngine::drawImage(const QPointF &pos, const QImage &image)
909{
910#ifdef QPAINTBUFFER_DEBUG_DRAW
911 qDebug() << "QPaintBufferEngine: drawImage: pos:" << pos;
912#endif
913 QPaintBufferCommand *cmd =
914 buffer->addCommand(QPaintBufferPrivate::Cmd_DrawImagePos, QVariant(image));
915 cmd->extra = buffer->addData((qreal *) &pos, 2);
916 if (buffer->calculateBoundingRect)
917 buffer->updateBoundingRect(QRectF(pos, image.size()));
918}
919
920void QPaintBufferEngine::drawTiledPixmap(const QRectF &r, const QPixmap &pm, const QPointF &s)
921{
922#ifdef QPAINTBUFFER_DEBUG_DRAW
923 qDebug() << "QPaintBufferEngine: drawTiledPixmap: src rect/offset:" << r << s;
924#endif
925 QPaintBufferCommand *cmd =
926 buffer->addCommand(QPaintBufferPrivate::Cmd_DrawTiledPixmap, QVariant(pm));
927 cmd->extra = buffer->addData((qreal *) &r, 4);
928 buffer->addData((qreal *) &s, 2);
929 if (buffer->calculateBoundingRect)
930 buffer->updateBoundingRect(r);
931}
932
933void QPaintBufferEngine::drawTextItem(const QPointF &pos, const QTextItem &ti)
934{
935#ifdef QPAINTBUFFER_DEBUG_DRAW
936 qDebug() << "QPaintBufferEngine: drawTextItem: pos:" << pos << ti.text();
937#endif
938 if (m_stream_raw_text_items) {
939 QPaintBufferCommand *cmd = buffer->addCommand(QPaintBufferPrivate::Cmd_DrawTextItem, qVariantFromValue<void *>(new QTextItemIntCopy(ti)));
940
941 QFont font(ti.font());
942 font.setUnderline(false);
943 font.setStrikeOut(false);
944 font.setOverline(false);
945
946 const QTextItemInt &si = static_cast<const QTextItemInt &>(ti);
947 qreal justificationWidth = 0;
948 if (si.justified)
949 justificationWidth = si.width.toReal();
950 int renderFlags = ti.renderFlags();
951 qreal scaleFactor = font.d->dpi/qreal(qt_defaultDpiY());
952
953 buffer->addData(QVariant(font));
954 cmd->extra = buffer->addData((qreal *) &pos, 2);
955 buffer->addData((qreal *) &justificationWidth, 1);
956 buffer->addData((qreal *) &scaleFactor, 1);
957 cmd->offset2 = buffer->addData((int *) &renderFlags, 1);
958 } else {
959 QList<QVariant> variants;
960 variants << QVariant(ti.font()) << QVariant(ti.text());
961 QPaintBufferCommand *cmd = buffer->addCommand(QPaintBufferPrivate::Cmd_DrawText, QVariant(variants));
962 cmd->extra = buffer->addData((qreal *) &pos, 2);
963 }
964
965 if (buffer->calculateBoundingRect)
966 buffer->updateBoundingRect(QRectF(pos, QSize(ti.width(), ti.ascent() + ti.descent() + 1)));
967}
968
969
970void QPaintBufferEngine::setState(QPainterState *s)
971{
972 if (m_begin_detected) {
973#ifdef QPAINTBUFFER_DEBUG_DRAW
974 qDebug() << "QPaintBufferEngine: setState: begin, ignoring.";
975#endif
976 m_begin_detected = false;
977 } else if (m_save_detected) {
978#ifdef QPAINTBUFFER_DEBUG_DRAW
979 qDebug() << "QPaintBufferEngine: setState: save.";
980#endif
981 m_save_detected = false;
982 buffer->addCommand(QPaintBufferPrivate::Cmd_Save);
983 } else {
984#ifdef QPAINTBUFFER_DEBUG_DRAW
985 qDebug() << "QPaintBufferEngine: setState: restore.";
986#endif
987 buffer->addCommand(QPaintBufferPrivate::Cmd_Restore);
988 }
989
990 QPaintEngineEx::setState(s);
991}
992
993
994/***********************************************************************
995 *
996 * class QPaintBufferPlayback_Painter
997 *
998 */
999
1000// QFakeDevice is used to create fonts with a custom DPI
1001//
1002class QFakeDevice : public QPaintDevice
1003{
1004public:
1005 QFakeDevice() { dpi_x = qt_defaultDpiX(); dpi_y = qt_defaultDpiY(); }
1006 void setDpiX(int dpi) { dpi_x = dpi; }
1007 void setDpiY(int dpi) { dpi_y = dpi; }
1008 QPaintEngine *paintEngine() const { return 0; }
1009 int metric(PaintDeviceMetric m) const
1010 {
1011 switch(m) {
1012 case PdmPhysicalDpiX:
1013 case PdmDpiX:
1014 return dpi_x;
1015 case PdmPhysicalDpiY:
1016 case PdmDpiY:
1017 return dpi_y;
1018 default:
1019 return QPaintDevice::metric(m);
1020 }
1021 }
1022
1023private:
1024 int dpi_x;
1025 int dpi_y;
1026};
1027
1028
1029void QPainterReplayer::setupTransform(QPainter *_painter)
1030{
1031 painter = _painter;
1032 m_world_matrix = painter->transform();
1033 m_world_matrix.scale(qreal(painter->device()->logicalDpiX()) / qreal(qt_defaultDpiX()),
1034 qreal(painter->device()->logicalDpiY()) / qreal(qt_defaultDpiY()));
1035 painter->setTransform(m_world_matrix);
1036}
1037
1038void QPainterReplayer::draw(const QPaintBuffer &buffer, QPainter *_painter)
1039{
1040 d = buffer.d_ptr;
1041 setupTransform(_painter);
1042
1043 for (int cmdIndex=0; cmdIndex<d->commands.size(); ++cmdIndex) {
1044 const QPaintBufferCommand &cmd = d->commands.at(cmdIndex);
1045 process(cmd);
1046 }
1047}
1048
1049void QPainterReplayer::process(const QPaintBufferCommand &cmd)
1050{
1051 switch (cmd.id) {
1052 case QPaintBufferPrivate::Cmd_Save: {
1053#ifdef QPAINTBUFFER_DEBUG_DRAW
1054 qDebug() << " -> Cmd_Save";
1055#endif
1056 painter->save();
1057 break; }
1058
1059 case QPaintBufferPrivate::Cmd_Restore: {
1060#ifdef QPAINTBUFFER_DEBUG_DRAW
1061 qDebug() << " -> Cmd_Restore";
1062#endif
1063 painter->restore();
1064 break; }
1065
1066 case QPaintBufferPrivate::Cmd_SetPen: {
1067 QPen pen = qVariantValue<QPen>(d->variants.at(cmd.offset));
1068#ifdef QPAINTBUFFER_DEBUG_DRAW
1069 qDebug() << " -> Cmd_SetPen: " << pen;
1070#endif
1071 painter->setPen(pen);
1072 break; }
1073
1074 case QPaintBufferPrivate::Cmd_SetBrush: {
1075 QBrush brush = qVariantValue<QBrush>(d->variants.at(cmd.offset));
1076#ifdef QPAINTBUFFER_DEBUG_DRAW
1077 qDebug() << " -> Cmd_SetBrush: " << brush;
1078#endif
1079 painter->setBrush(brush);
1080 break; }
1081
1082 case QPaintBufferPrivate::Cmd_SetBrushOrigin: {
1083#ifdef QPAINTBUFFER_DEBUG_DRAW
1084 qDebug() << " -> Cmd_SetBrushOrigin: " << d->variants.at(cmd.offset).toPointF();
1085#endif
1086 painter->setBrushOrigin(d->variants.at(cmd.offset).toPointF());
1087 break; }
1088
1089 case QPaintBufferPrivate::Cmd_SetTransform: {
1090 QTransform xform = qVariantValue<QTransform>(d->variants.at(cmd.offset));
1091#ifdef QPAINTBUFFER_DEBUG_DRAW
1092 qDebug() << " -> Cmd_SetTransform, offset: " << cmd.offset << xform;
1093#endif
1094 painter->setTransform(xform * m_world_matrix);
1095 break; }
1096
1097 case QPaintBufferPrivate::Cmd_SetCompositionMode: {
1098 QPainter::CompositionMode mode = (QPainter::CompositionMode) cmd.extra;
1099#ifdef QPAINTBUFFER_DEBUG_DRAW
1100 qDebug() << " -> Cmd_SetCompositionMode, mode: " << mode;
1101#endif
1102 painter->setCompositionMode(mode);
1103 break; }
1104
1105 case QPaintBufferPrivate::Cmd_SetRenderHints: {
1106#ifdef QPAINTBUFFER_DEBUG_DRAW
1107 qDebug() << " -> Cmd_SetRenderHints, hints: " << cmd.extra;
1108#endif
1109 QPainter::RenderHints ph = painter->renderHints();
1110 QPainter::RenderHints nh = (QPainter::RenderHints) cmd.extra;
1111 QPainter::RenderHints xored = ph ^ nh;
1112 if (xored & QPainter::Antialiasing)
1113 painter->setRenderHint(QPainter::Antialiasing, nh & QPainter::Antialiasing);
1114 if (xored & QPainter::HighQualityAntialiasing)
1115 painter->setRenderHint(QPainter::HighQualityAntialiasing, nh & QPainter::HighQualityAntialiasing);
1116 if (xored & QPainter::TextAntialiasing)
1117 painter->setRenderHint(QPainter::TextAntialiasing, nh & QPainter::TextAntialiasing);
1118 if (xored & QPainter::SmoothPixmapTransform)
1119 painter->setRenderHint(QPainter::SmoothPixmapTransform, nh & QPainter::SmoothPixmapTransform);
1120 if (xored & QPainter::NonCosmeticDefaultPen)
1121 painter->setRenderHint(QPainter::NonCosmeticDefaultPen, nh & QPainter::NonCosmeticDefaultPen);
1122 break; }
1123
1124 case QPaintBufferPrivate::Cmd_SetOpacity: {
1125#ifdef QPAINTBUFFER_DEBUG_DRAW
1126 qDebug() << " -> Cmd_SetOpacity: " << d->variants.at(cmd.offset).toDouble();
1127#endif
1128 painter->setOpacity(d->variants.at(cmd.offset).toDouble());
1129 break; }
1130
1131 case QPaintBufferPrivate::Cmd_SetBackgroundMode: {
1132#ifdef QPAINTBUFFER_DEBUG_DRAW
1133 qDebug() << " -> Cmd_SetBackgroundMode: " << cmd.extra;
1134#endif
1135 painter->setBackgroundMode((Qt::BGMode)cmd.extra);
1136 break; }
1137
1138 case QPaintBufferPrivate::Cmd_DrawVectorPath: {
1139#ifdef QPAINTBUFFER_DEBUG_DRAW
1140 qDebug() << " -> Cmd_DrawVectorPath: size: " << cmd.size
1141// << ", hints:" << d->ints[cmd.offset2+cmd.size]
1142 << "pts/elms:" << cmd.offset << cmd.offset2;
1143#endif
1144 QVectorPathCmd path(d, cmd);
1145 painter->drawPath(path().convertToPainterPath());
1146 break; }
1147
1148 case QPaintBufferPrivate::Cmd_StrokeVectorPath: {
1149 QPen pen = qVariantValue<QPen>(d->variants.at(cmd.extra));
1150#ifdef QPAINTBUFFER_DEBUG_DRAW
1151 qDebug() << " -> Cmd_StrokeVectorPath: size: " << cmd.size
1152// << ", hints:" << d->ints[cmd.offset2+cmd.size]
1153 << "pts/elms:" << cmd.offset << cmd.offset2;
1154#endif
1155 QVectorPathCmd path(d, cmd);
1156 painter->strokePath(path().convertToPainterPath(), pen);
1157 break; }
1158
1159 case QPaintBufferPrivate::Cmd_FillVectorPath: {
1160 QBrush brush = qVariantValue<QBrush>(d->variants.at(cmd.extra));
1161#ifdef QPAINTBUFFER_DEBUG_DRAW
1162 qDebug() << " -> Cmd_FillVectorPath: size: " << cmd.size
1163// << ", hints:" << d->ints[cmd.offset2+cmd.size]
1164 << "pts/elms:" << cmd.offset << cmd.offset2 << brush;
1165#endif
1166 QVectorPathCmd path(d, cmd);
1167 painter->fillPath(path().convertToPainterPath(), brush);
1168 break; }
1169
1170 case QPaintBufferPrivate::Cmd_DrawPolygonF: {
1171#ifdef QPAINTBUFFER_DEBUG_DRAW
1172 qDebug() << " -> Cmd_DrawPolygonF, offset: " << cmd.offset << " size: " << cmd.size
1173 << " mode: " << cmd.extra
1174 << d->floats.at(cmd.offset)
1175 << d->floats.at(cmd.offset+1);
1176#endif
1177 Qt::FillRule fill = (QPaintEngine::PolygonDrawMode) cmd.extra == QPaintEngine::OddEvenMode
1178 ? Qt::OddEvenFill : Qt::WindingFill;
1179 painter->drawPolygon((QPointF *) (d->floats.constData() + cmd.offset), cmd.size, fill);
1180 break; }
1181
1182 case QPaintBufferPrivate::Cmd_DrawPolygonI: {
1183#ifdef QPAINTBUFFER_DEBUG_DRAW
1184 qDebug() << " -> Cmd_DrawPolygonI, offset: " << cmd.offset << " size: " << cmd.size
1185 << " mode: " << cmd.extra
1186 << d->ints.at(cmd.offset)
1187 << d->ints.at(cmd.offset+1);
1188#endif
1189 Qt::FillRule fill = (QPaintEngine::PolygonDrawMode) cmd.extra == QPaintEngine::OddEvenMode
1190 ? Qt::OddEvenFill : Qt::WindingFill;
1191 painter->drawPolygon((QPoint *) (d->ints.constData() + cmd.offset), cmd.size, fill);
1192 break; }
1193
1194 case QPaintBufferPrivate::Cmd_DrawPolylineF: {
1195#ifdef QPAINTBUFFER_DEBUG_DRAW
1196 qDebug() << " -> Cmd_DrawPolylineF, offset: " << cmd.offset << " size: " << cmd.size;
1197#endif
1198 painter->drawPolyline((QPointF *) (d->floats.constData() + cmd.offset), cmd.size);
1199 break; }
1200
1201 case QPaintBufferPrivate::Cmd_DrawPolylineI: {
1202#ifdef QPAINTBUFFER_DEBUG_DRAW
1203 qDebug() << " -> Cmd_DrawPolylineI, offset: " << cmd.offset << " size: " << cmd.size;
1204#endif
1205 painter->drawPolyline((QPoint *) (d->ints.constData() + cmd.offset), cmd.size);
1206 break; }
1207
1208 case QPaintBufferPrivate::Cmd_DrawConvexPolygonF: {
1209#ifdef QPAINTBUFFER_DEBUG_DRAW
1210 qDebug() << " -> Cmd_DrawConvexPolygonF, offset: " << cmd.offset << " size: " << cmd.size;
1211#endif
1212 painter->drawConvexPolygon((QPointF *) (d->floats.constData() + cmd.offset), cmd.size);
1213 break; }
1214
1215 case QPaintBufferPrivate::Cmd_DrawConvexPolygonI: {
1216#ifdef QPAINTBUFFER_DEBUG_DRAW
1217 qDebug() << " -> Cmd_DrawConvexPolygonI, offset: " << cmd.offset << " size: " << cmd.size;
1218#endif
1219 painter->drawConvexPolygon((QPoint *) (d->ints.constData() + cmd.offset), cmd.size);
1220 break; }
1221
1222 case QPaintBufferPrivate::Cmd_DrawEllipseF: {
1223#ifdef QPAINTBUFFER_DEBUG_DRAW
1224 qDebug() << " -> Cmd_DrawEllipseF, offset: " << cmd.offset;
1225#endif
1226 painter->drawEllipse(*(QRectF *)(d->floats.constData() + cmd.offset));
1227 break; }
1228
1229 case QPaintBufferPrivate::Cmd_DrawEllipseI: {
1230#ifdef QPAINTBUFFER_DEBUG_DRAW
1231 qDebug() << " -> Cmd_DrawEllipseI, offset: " << cmd.offset;
1232#endif
1233 painter->drawEllipse(*(QRect *)(d->ints.constData() + cmd.offset));
1234 break; }
1235
1236 case QPaintBufferPrivate::Cmd_DrawLineF: {
1237#ifdef QPAINTBUFFER_DEBUG_DRAW
1238 qDebug() << " -> Cmd_DrawLineF, offset: " << cmd.offset << " size: " << cmd.size;
1239#endif
1240 painter->drawLines((QLineF *)(d->floats.constData() + cmd.offset), cmd.size);
1241 break; }
1242
1243 case QPaintBufferPrivate::Cmd_DrawLineI: {
1244#ifdef QPAINTBUFFER_DEBUG_DRAW
1245 qDebug() << " -> Cmd_DrawLineI, offset: " << cmd.offset << " size: " << cmd.size;
1246#endif
1247 painter->drawLines((QLine *)(d->ints.constData() + cmd.offset), cmd.size);
1248 break; }
1249
1250 case QPaintBufferPrivate::Cmd_DrawPointsF: {
1251#ifdef QPAINTBUFFER_DEBUG_DRAW
1252 qDebug() << " -> Cmd_DrawPointsF, offset: " << cmd.offset << " size: " << cmd.size;
1253#endif
1254 painter->drawPoints((QPointF *)(d->floats.constData() + cmd.offset), cmd.size);
1255 break; }
1256
1257 case QPaintBufferPrivate::Cmd_DrawPointsI: {
1258#ifdef QPAINTBUFFER_DEBUG_DRAW
1259 qDebug() << " -> Cmd_DrawPointsI, offset: " << cmd.offset << " size: " << cmd.size;
1260#endif
1261 painter->drawPoints((QPoint *)(d->ints.constData() + cmd.offset), cmd.size);
1262 break; }
1263
1264 case QPaintBufferPrivate::Cmd_DrawPixmapRect: {
1265 QPixmap pm(d->variants.at(cmd.offset).value<QPixmap>());
1266 QRectF r(d->floats.at(cmd.extra), d->floats.at(cmd.extra+1),
1267 d->floats.at(cmd.extra+2), d->floats.at(cmd.extra+3));
1268
1269 QRectF sr(d->floats.at(cmd.extra+4), d->floats.at(cmd.extra+5),
1270 d->floats.at(cmd.extra+6), d->floats.at(cmd.extra+7));
1271#ifdef QPAINTBUFFER_DEBUG_DRAW
1272 qDebug() << " -> Cmd_DrawPixmapRect:" << r << sr;
1273#endif
1274 painter->drawPixmap(r, pm, sr);
1275 break; }
1276
1277 case QPaintBufferPrivate::Cmd_DrawPixmapPos: {
1278 QPixmap pm(d->variants.at(cmd.offset).value<QPixmap>());
1279 QPointF pos(d->floats.at(cmd.extra), d->floats.at(cmd.extra+1));
1280#ifdef QPAINTBUFFER_DEBUG_DRAW
1281 qDebug() << " -> Cmd_DrawPixmapPos:" << pos;
1282#endif
1283 painter->drawPixmap(pos, pm);
1284 break; }
1285
1286 case QPaintBufferPrivate::Cmd_DrawTiledPixmap: {
1287 QPixmap pm(d->variants.at(cmd.offset).value<QPixmap>());
1288 QRectF r(d->floats.at(cmd.extra), d->floats.at(cmd.extra+1),
1289 d->floats.at(cmd.extra+2), d->floats.at(cmd.extra+3));
1290
1291 QPointF offset(d->floats.at(cmd.extra+4), d->floats.at(cmd.extra+5));
1292#ifdef QPAINTBUFFER_DEBUG_DRAW
1293 qDebug() << " -> Cmd_DrawTiledPixmap:" << r << offset;
1294#endif
1295 painter->drawTiledPixmap(r, pm, offset);
1296 break; }
1297
1298 case QPaintBufferPrivate::Cmd_DrawImageRect: {
1299 QImage image(d->variants.at(cmd.offset).value<QImage>());
1300 QRectF r(d->floats.at(cmd.extra), d->floats.at(cmd.extra+1),
1301 d->floats.at(cmd.extra+2), d->floats.at(cmd.extra+3));
1302 QRectF sr(d->floats.at(cmd.extra+4), d->floats.at(cmd.extra+5),
1303 d->floats.at(cmd.extra+6), d->floats.at(cmd.extra+7));
1304#ifdef QPAINTBUFFER_DEBUG_DRAW
1305 qDebug() << " -> Cmd_DrawImageRect:" << r << sr;
1306#endif
1307 painter->drawImage(r, image, sr);
1308 break; }
1309
1310 case QPaintBufferPrivate::Cmd_DrawImagePos: {
1311 QImage image(d->variants.at(cmd.offset).value<QImage>());
1312 QPointF pos(d->floats.at(cmd.extra), d->floats.at(cmd.extra+1));
1313#ifdef QPAINTBUFFER_DEBUG_DRAW
1314 qDebug() << " -> Cmd_DrawImagePos:" << pos;
1315#endif
1316 painter->drawImage(pos, image);
1317 break; }
1318
1319 case QPaintBufferPrivate::Cmd_DrawRectF: {
1320#ifdef QPAINTBUFFER_DEBUG_DRAW
1321 qDebug() << " -> Cmd_DrawRectF, offset: " << cmd.offset;
1322#endif
1323 painter->drawRects((QRectF *)(d->floats.constData() + cmd.offset), cmd.size);
1324 break; }
1325
1326 case QPaintBufferPrivate::Cmd_DrawRectI: {
1327#ifdef QPAINTBUFFER_DEBUG_DRAW
1328 qDebug() << " -> Cmd_DrawRectI, offset: " << cmd.offset;
1329#endif
1330 painter->drawRects((QRect *)(d->ints.constData() + cmd.offset), cmd.size);
1331 break; }
1332
1333 case QPaintBufferPrivate::Cmd_FillRectBrush: {
1334 QBrush brush = qVariantValue<QBrush>(d->variants.at(cmd.extra));
1335 QRectF *rect = (QRectF *)(d->floats.constData() + cmd.offset);
1336#ifdef QPAINTBUFFER_DEBUG_DRAW
1337 qDebug() << " -> Cmd_FillRectBrush, offset: " << cmd.offset << " rect: " << *rect << " brush: " << brush;
1338#endif
1339 painter->fillRect(*rect, brush);
1340 break; }
1341
1342 case QPaintBufferPrivate::Cmd_FillRectColor: {
1343 QColor color = qVariantValue<QColor>(d->variants.at(cmd.extra));
1344 QRectF *rect = (QRectF *)(d->floats.constData() + cmd.offset);
1345#ifdef QPAINTBUFFER_DEBUG_DRAW
1346 qDebug() << " -> Cmd_FillRectBrush, offset: " << cmd.offset << " rect: " << *rect << " color: " << color;
1347#endif
1348 painter->fillRect(*rect, color);
1349 break; }
1350
1351 case QPaintBufferPrivate::Cmd_SetClipEnabled: {
1352 bool clipEnabled = d->variants.at(cmd.offset).toBool();
1353#ifdef QPAINTBUFFER_DEBUG_DRAW
1354 qDebug() << " -> Cmd_SetClipEnabled:" << clipEnabled;
1355#endif
1356 painter->setClipping(clipEnabled);
1357 break; }
1358
1359 case QPaintBufferPrivate::Cmd_ClipVectorPath: {
1360 QVectorPathCmd path(d, cmd);
1361#ifdef QPAINTBUFFER_DEBUG_DRAW
1362 qDebug() << " -> Cmd_ClipVectorPath:" << path().elementCount();
1363#endif
1364 painter->setClipPath(path().convertToPainterPath(), Qt::ClipOperation(cmd.extra));
1365 break; }
1366
1367
1368 case QPaintBufferPrivate::Cmd_ClipRect: {
1369 QRect rect(QPoint(d->ints.at(cmd.offset), d->ints.at(cmd.offset + 1)),
1370 QPoint(d->ints.at(cmd.offset + 2), d->ints.at(cmd.offset + 3)));
1371#ifdef QPAINTBUFFER_DEBUG_DRAW
1372 qDebug() << " -> Cmd_ClipRect:" << rect << cmd.extra;
1373#endif
1374 painter->setClipRect(rect, Qt::ClipOperation(cmd.extra));
1375 break; }
1376
1377 case QPaintBufferPrivate::Cmd_ClipRegion: {
1378 QRegion region(d->variants.at(cmd.offset).value<QRegion>());
1379#ifdef QPAINTBUFFER_DEBUG_DRAW
1380 qDebug() << " -> Cmd_ClipRegion:" << region.boundingRect() << cmd.extra;
1381#endif
1382 painter->setClipRegion(region, Qt::ClipOperation(cmd.extra));
1383 break; }
1384
1385 case QPaintBufferPrivate::Cmd_DrawText: {
1386 QPointF pos(d->floats.at(cmd.extra), d->floats.at(cmd.extra+1));
1387 QList<QVariant> variants(d->variants.at(cmd.offset).value<QList<QVariant> >());
1388
1389 QFont font(variants.at(0).value<QFont>());
1390 QString text(variants.at(1).value<QString>());
1391
1392 painter->setFont(font);
1393 painter->drawText(pos, text);
1394 break; }
1395
1396 case QPaintBufferPrivate::Cmd_DrawTextItem: {
1397 QPointF pos(d->floats.at(cmd.extra), d->floats.at(cmd.extra+1));
1398 QTextItemIntCopy *tiCopy = reinterpret_cast<QTextItemIntCopy *>(qVariantValue<void *>(d->variants.at(cmd.offset)));
1399 QTextItemInt &ti = (*tiCopy)();
1400 QString text(ti.text());
1401
1402#ifdef QPAINTBUFFER_DEBUG_DRAW
1403 qDebug() << " -> Cmd_DrawTextItem:" << pos << " " << text << " " << scaleFactor;
1404#endif
1405
1406 QFont font(ti.font());
1407 font.setUnderline(false);
1408 font.setStrikeOut(false);
1409 font.setOverline(false);
1410
1411 const QTextItemInt &si = static_cast<const QTextItemInt &>(ti);
1412 qreal justificationWidth = 0;
1413 if (si.justified)
1414 justificationWidth = si.width.toReal();
1415 qreal scaleFactor = font.d->dpi/qreal(qt_defaultDpiY());
1416
1417 if (scaleFactor != 1.0) {
1418 QFont fnt(font);
1419 QFakeDevice fake;
1420 fake.setDpiX(qRound(scaleFactor*qt_defaultDpiX()));
1421 fake.setDpiY(qRound(scaleFactor*qt_defaultDpiY()));
1422 font = QFont(fnt, &fake);
1423 }
1424
1425 int flags = Qt::TextSingleLine | Qt::TextDontClip | Qt::TextForceLeftToRight;
1426 QSizeF size(1, 1);
1427 if (justificationWidth > 0) {
1428 size.setWidth(justificationWidth);
1429 flags |= Qt::TextJustificationForced;
1430 flags |= Qt::AlignJustify;
1431 }
1432
1433 QFontMetrics fm(font);
1434 QPointF pt(pos.x(), pos.y() - fm.ascent());
1435 qt_format_text(font, QRectF(pt, size), flags, /*opt*/0,
1436 text, /*brect=*/0, /*tabstops=*/0, /*...*/0, /*tabarraylen=*/0, painter);
1437 break; }
1438 case QPaintBufferPrivate::Cmd_SystemStateChanged: {
1439 QRegion systemClip(d->variants.at(cmd.offset).value<QRegion>());
1440
1441#ifdef QPAINTBUFFER_DEBUG_DRAW
1442 qDebug() << " -> Cmd_SystemStateChanged:" << systemClip;
1443#endif
1444
1445 painter->paintEngine()->setSystemClip(systemClip);
1446 painter->paintEngine()->d_ptr->systemStateChanged();
1447 break; }
1448 }
1449}
1450
1451void QPaintEngineExReplayer::process(const QPaintBufferCommand &cmd)
1452{
1453 Q_ASSERT(painter->paintEngine()->isExtended());
1454 QPaintEngineEx *xengine = static_cast<QPaintEngineEx *>(painter->paintEngine());
1455
1456 switch (cmd.id) {
1457 case QPaintBufferPrivate::Cmd_SetBrushOrigin: {
1458#ifdef QPAINTBUFFER_DEBUG_DRAW
1459 qDebug() << " -> ExCmd_SetBrushOrigin: " << d->variants.at(cmd.offset).toPointF();
1460#endif
1461 xengine->state()->brushOrigin = d->variants.at(cmd.offset).toPointF();
1462 xengine->brushOriginChanged();
1463 break; }
1464
1465 case QPaintBufferPrivate::Cmd_SetCompositionMode: {
1466 QPainter::CompositionMode mode = (QPainter::CompositionMode) cmd.extra;
1467#ifdef QPAINTBUFFER_DEBUG_DRAW
1468 qDebug() << " -> ExCmd_SetCompositionMode, mode: " << mode;
1469#endif
1470 xengine->state()->composition_mode = mode;
1471 xengine->compositionModeChanged();
1472 break; }
1473
1474 case QPaintBufferPrivate::Cmd_SetOpacity: {
1475#ifdef QPAINTBUFFER_DEBUG_DRAW
1476 qDebug() << " -> ExCmd_SetOpacity: " << d->variants.at(cmd.offset).toDouble();
1477#endif
1478 xengine->state()->opacity = d->variants.at(cmd.offset).toDouble();
1479 xengine->opacityChanged();
1480 break; }
1481
1482 case QPaintBufferPrivate::Cmd_DrawVectorPath: {
1483#ifdef QPAINTBUFFER_DEBUG_DRAW
1484 qDebug() << " -> ExCmd_DrawVectorPath: size: " << cmd.size
1485// << ", hints:" << d->ints[cmd.offset2+cmd.size]
1486 << "pts/elms:" << cmd.offset << cmd.offset2;
1487#endif
1488 QVectorPathCmd path(d, cmd);
1489 xengine->draw(path());
1490 break; }
1491
1492 case QPaintBufferPrivate::Cmd_StrokeVectorPath: {
1493 QPen pen = qVariantValue<QPen>(d->variants.at(cmd.extra));
1494#ifdef QPAINTBUFFER_DEBUG_DRAW
1495 qDebug() << " -> ExCmd_StrokeVectorPath: size: " << cmd.size
1496// << ", hints:" << d->ints[cmd.offset2+cmd.size]
1497 << "pts/elms:" << cmd.offset << cmd.offset2;
1498#endif
1499 QVectorPathCmd path(d, cmd);
1500 xengine->stroke(path(), pen);
1501 break; }
1502
1503 case QPaintBufferPrivate::Cmd_FillVectorPath: {
1504 QBrush brush = qVariantValue<QBrush>(d->variants.at(cmd.extra));
1505#ifdef QPAINTBUFFER_DEBUG_DRAW
1506 qDebug() << " -> ExCmd_FillVectorPath: size: " << cmd.size
1507// << ", hints:" << d->ints[cmd.offset2+cmd.size]
1508 << "pts/elms:" << cmd.offset << cmd.offset2 << brush;
1509#endif
1510 QVectorPathCmd path(d, cmd);
1511 xengine->fill(path(), brush);
1512 break; }
1513
1514 case QPaintBufferPrivate::Cmd_FillRectBrush: {
1515 QBrush brush = qVariantValue<QBrush>(d->variants.at(cmd.extra));
1516 QRectF *rect = (QRectF *)(d->floats.constData() + cmd.offset);
1517#ifdef QPAINTBUFFER_DEBUG_DRAW
1518 qDebug() << " -> ExCmd_FillRectBrush, offset: " << cmd.offset << " rect: " << *rect << " brush: " << brush;
1519#endif
1520 xengine->fillRect(*rect, brush);
1521 break; }
1522
1523 case QPaintBufferPrivate::Cmd_FillRectColor: {
1524 QColor color = qVariantValue<QColor>(d->variants.at(cmd.extra));
1525 QRectF *rect = (QRectF *)(d->floats.constData() + cmd.offset);
1526#ifdef QPAINTBUFFER_DEBUG_DRAW
1527 qDebug() << " -> ExCmd_FillRectBrush, offset: " << cmd.offset << " rect: " << *rect << " color: " << color;
1528#endif
1529 xengine->fillRect(*rect, color);
1530 break; }
1531
1532 case QPaintBufferPrivate::Cmd_DrawPolygonF: {
1533#ifdef QPAINTBUFFER_DEBUG_DRAW
1534 qDebug() << " -> ExCmd_DrawPolygonF, offset: " << cmd.offset << " size: " << cmd.size
1535 << " mode: " << cmd.extra
1536 << d->floats.at(cmd.offset)
1537 << d->floats.at(cmd.offset+1);
1538#endif
1539 xengine->drawPolygon((QPointF *) (d->floats.constData() + cmd.offset), cmd.size,
1540 (QPaintEngine::PolygonDrawMode) cmd.extra);
1541 break; }
1542
1543 case QPaintBufferPrivate::Cmd_DrawPolygonI: {
1544#ifdef QPAINTBUFFER_DEBUG_DRAW
1545 qDebug() << " -> ExCmd_DrawPolygonI, offset: " << cmd.offset << " size: " << cmd.size
1546 << " mode: " << cmd.extra
1547 << d->ints.at(cmd.offset)
1548 << d->ints.at(cmd.offset+1);
1549#endif
1550 xengine->drawPolygon((QPoint *) (d->ints.constData() + cmd.offset), cmd.size,
1551 (QPaintEngine::PolygonDrawMode) cmd.extra);
1552 break; }
1553
1554 case QPaintBufferPrivate::Cmd_DrawEllipseF: {
1555#ifdef QPAINTBUFFER_DEBUG_DRAW
1556 qDebug() << " -> ExCmd_DrawEllipseF, offset: " << cmd.offset;
1557#endif
1558 xengine->drawEllipse(*(QRectF *)(d->floats.constData() + cmd.offset));
1559 break; }
1560
1561 case QPaintBufferPrivate::Cmd_DrawEllipseI: {
1562#ifdef QPAINTBUFFER_DEBUG_DRAW
1563 qDebug() << " -> ExCmd_DrawEllipseI, offset: " << cmd.offset;
1564#endif
1565 xengine->drawEllipse(*(QRect *)(d->ints.constData() + cmd.offset));
1566 break; }
1567
1568 case QPaintBufferPrivate::Cmd_DrawLineF: {
1569#ifdef QPAINTBUFFER_DEBUG_DRAW
1570 qDebug() << " -> ExCmd_DrawLineF, offset: " << cmd.offset << " size: " << cmd.size;
1571#endif
1572 xengine->drawLines((QLineF *)(d->floats.constData() + cmd.offset), cmd.size);
1573 break; }
1574
1575 case QPaintBufferPrivate::Cmd_DrawLineI: {
1576#ifdef QPAINTBUFFER_DEBUG_DRAW
1577 qDebug() << " -> ExCmd_DrawLineI, offset: " << cmd.offset << " size: " << cmd.size;
1578#endif
1579 xengine->drawLines((QLine *)(d->ints.constData() + cmd.offset), cmd.size);
1580 break; }
1581
1582 case QPaintBufferPrivate::Cmd_DrawPointsF: {
1583#ifdef QPAINTBUFFER_DEBUG_DRAW
1584 qDebug() << " -> ExCmd_DrawPointsF, offset: " << cmd.offset << " size: " << cmd.size;
1585#endif
1586 xengine->drawPoints((QPointF *)(d->floats.constData() + cmd.offset), cmd.size);
1587 break; }
1588
1589 case QPaintBufferPrivate::Cmd_DrawPointsI: {
1590#ifdef QPAINTBUFFER_DEBUG_DRAW
1591 qDebug() << " -> ExCmd_DrawPointsI, offset: " << cmd.offset << " size: " << cmd.size;
1592#endif
1593 xengine->drawPoints((QPoint *)(d->ints.constData() + cmd.offset), cmd.size);
1594 break; }
1595
1596 case QPaintBufferPrivate::Cmd_DrawPolylineF: {
1597#ifdef QPAINTBUFFER_DEBUG_DRAW
1598 qDebug() << " -> ExCmd_DrawPolylineF, offset: " << cmd.offset << " size: " << cmd.size;
1599#endif
1600 xengine->drawPolygon((QPointF *) (d->floats.constData() + cmd.offset), cmd.size, QPaintEngine::PolylineMode);
1601 break; }
1602
1603 case QPaintBufferPrivate::Cmd_DrawPolylineI: {
1604#ifdef QPAINTBUFFER_DEBUG_DRAW
1605 qDebug() << " -> ExCmd_DrawPolylineI, offset: " << cmd.offset << " size: " << cmd.size;
1606#endif
1607 xengine->drawPolygon((QPoint *) (d->ints.constData() + cmd.offset), cmd.size, QPaintEngine::PolylineMode);
1608 break; }
1609
1610 case QPaintBufferPrivate::Cmd_DrawRectF: {
1611#ifdef QPAINTBUFFER_DEBUG_DRAW
1612 qDebug() << " -> ExCmd_DrawRectF, offset: " << cmd.offset << " size: " << cmd.size;
1613#endif
1614 xengine->drawRects((QRectF *) (d->floats.constData() + cmd.offset), cmd.size);
1615 break; }
1616
1617 case QPaintBufferPrivate::Cmd_DrawRectI: {
1618#ifdef QPAINTBUFFER_DEBUG_DRAW
1619 qDebug() << " -> ExCmd_DrawRectI, offset: " << cmd.offset << " size: " << cmd.size;
1620#endif
1621 xengine->drawRects((QRect *) (d->ints.constData() + cmd.offset), cmd.size);
1622 break; }
1623
1624 case QPaintBufferPrivate::Cmd_SetClipEnabled: {
1625 bool clipEnabled = d->variants.at(cmd.offset).toBool();
1626#ifdef QPAINTBUFFER_DEBUG_DRAW
1627 qDebug() << " -> ExCmd_SetClipEnabled:" << clipEnabled;
1628#endif
1629 xengine->state()->clipEnabled = clipEnabled;
1630 xengine->clipEnabledChanged();
1631 break; }
1632
1633 case QPaintBufferPrivate::Cmd_ClipVectorPath: {
1634 QVectorPathCmd path(d, cmd);
1635#ifdef QPAINTBUFFER_DEBUG_DRAW
1636 qDebug() << " -> ExCmd_ClipVectorPath:" << path().elementCount();
1637#endif
1638 xengine->clip(path(), Qt::ClipOperation(cmd.extra));
1639 break; }
1640
1641
1642 case QPaintBufferPrivate::Cmd_ClipRect: {
1643 QRect rect(QPoint(d->ints.at(cmd.offset), d->ints.at(cmd.offset + 1)),
1644 QPoint(d->ints.at(cmd.offset + 2), d->ints.at(cmd.offset + 3)));
1645#ifdef QPAINTBUFFER_DEBUG_DRAW
1646 qDebug() << " -> ExCmd_ClipRect:" << rect << cmd.extra;
1647#endif
1648 xengine->clip(rect, Qt::ClipOperation(cmd.extra));
1649 break; }
1650
1651 case QPaintBufferPrivate::Cmd_ClipRegion: {
1652 QRegion region(d->variants.at(cmd.offset).value<QRegion>());
1653#ifdef QPAINTBUFFER_DEBUG_DRAW
1654 qDebug() << " -> ExCmd_ClipRegion:" << region.boundingRect() << cmd.extra;
1655#endif
1656 xengine->clip(region, Qt::ClipOperation(cmd.extra));
1657 break; }
1658
1659 default:
1660 QPainterReplayer::process(cmd);
1661 break;
1662 }
1663}
1664
1665QPaintBufferResource::QPaintBufferResource(FreeFunc f, QObject *parent) : QObject(parent), free(f)
1666{
1667 connect(QPaintBufferSignalProxy::instance(), SIGNAL(aboutToDestroy(const QPaintBufferPrivate *)), this, SLOT(remove(const QPaintBufferPrivate *)));
1668}
1669
1670QPaintBufferResource::~QPaintBufferResource()
1671{
1672 for (Cache::iterator it = m_cache.begin(); it != m_cache.end(); ++it)
1673 free(it.value());
1674}
1675
1676void QPaintBufferResource::insert(const QPaintBufferPrivate *key, void *value)
1677{
1678 Cache::iterator it = m_cache.find(key);
1679 if (it != m_cache.end()) {
1680 free(it.value());
1681 it.value() = value;
1682 } else {
1683 m_cache.insert(key, value);
1684 }
1685}
1686
1687void *QPaintBufferResource::value(const QPaintBufferPrivate *key)
1688{
1689 Cache::iterator it = m_cache.find(key);
1690 if (it != m_cache.end())
1691 return it.value();
1692 return 0;
1693}
1694
1695void QPaintBufferResource::remove(const QPaintBufferPrivate *key)
1696{
1697 Cache::iterator it = m_cache.find(key);
1698 if (it != m_cache.end()) {
1699 free(it.value());
1700 m_cache.erase(it);
1701 }
1702}
1703
1704QDataStream &operator<<(QDataStream &stream, const QPaintBufferCommand &command)
1705{
1706 quint32 id = command.id;
1707 quint32 size = command.size;
1708 stream << id << size;
1709 stream << command.offset << command.offset2 << command.extra;
1710 return stream;
1711}
1712
1713QDataStream &operator>>(QDataStream &stream, QPaintBufferCommand &command)
1714{
1715 quint32 id;
1716 quint32 size;
1717 stream >> id >> size;
1718 stream >> command.offset >> command.offset2 >> command.extra;
1719 command.id = id;
1720 command.size = size;
1721 return stream;
1722}
1723
1724QDataStream &operator<<(QDataStream &stream, const QPaintBuffer &buffer)
1725{
1726 stream << buffer.d_ptr->ints;
1727 stream << buffer.d_ptr->floats;
1728 stream << buffer.d_ptr->variants;
1729 stream << buffer.d_ptr->commands;
1730 stream << buffer.d_ptr->boundingRect;
1731
1732 return stream;
1733}
1734
1735QDataStream &operator>>(QDataStream &stream, QPaintBuffer &buffer)
1736{
1737 stream >> buffer.d_ptr->ints;
1738 stream >> buffer.d_ptr->floats;
1739 stream >> buffer.d_ptr->variants;
1740 stream >> buffer.d_ptr->commands;
1741 stream >> buffer.d_ptr->boundingRect;
1742
1743 return stream;
1744}
src/gui/painting/qpaintbuffer_p.h
(439 / 0)
  
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** Contact: Nokia Corporation (qt-info@nokia.com)
5**
6** This file is part of the QtGui module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** No Commercial Usage
10** This file contains pre-release code and may not be distributed.
11** You may use this file in accordance with the terms and conditions
12** contained in the Technology Preview License Agreement accompanying
13** this package.
14**
15** GNU Lesser General Public License Usage
16** Alternatively, this file may be used under the terms of the GNU Lesser
17** General Public License version 2.1 as published by the Free Software
18** Foundation and appearing in the file LICENSE.LGPL included in the
19** packaging of this file. Please review the following information to
20** ensure the GNU Lesser General Public License version 2.1 requirements
21** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22**
23** In addition, as a special exception, Nokia gives you certain
24** additional rights. These rights are described in the Nokia Qt LGPL
25** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
26** package.
27**
28** If you have questions regarding the use of this file, please contact
29** Nokia at qt-info@nokia.com.
30**
31**
32**
33**
34**
35**
36**
37**
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#ifndef QPAINTBUFFER_P_H
43#define QPAINTBUFFER_P_H
44
45//
46// W A R N I N G
47// -------------
48//
49// This file is not part of the Qt API. It exists purely as an
50// implementation detail. This header file may change from version to
51// version without notice, or even be removed.
52//
53// We mean it.
54//
55
56#include <qpaintdevice.h>
57
58#include <private/qpaintengineex_p.h>
59#include <private/qtextengine_p.h>
60#include <QDebug>
61
62class QPaintBufferPrivate;
63class QPaintBufferPlayback;
64
65class Q_GUI_EXPORT QPaintBuffer : public QPaintDevice
66{
67public:
68 QPaintBuffer();
69 QPaintBuffer(const QPaintBuffer &other);
70 ~QPaintBuffer();
71
72 bool isEmpty() const;
73
74 void draw(QPainter *painter) const;
75 void setBoundingRect(const QRectF &rect);
76 QRectF boundingRect() const;
77
78 virtual QPaintEngine *paintEngine() const;
79 virtual int metric(PaintDeviceMetric m) const;
80 virtual int devType() const;
81
82 QPaintBuffer &operator=(const QPaintBuffer &other);
83
84private:
85 friend class QPainterReplayer;
86 friend class QOpenGLReplayer;
87
88 friend Q_GUI_EXPORT QDataStream &operator<<(QDataStream &stream, const QPaintBuffer &buffer);
89 friend Q_GUI_EXPORT QDataStream &operator>>(QDataStream &stream, QPaintBuffer &buffer);
90
91 QPaintBufferPrivate *d_ptr;
92};
93
94Q_GUI_EXPORT QDataStream &operator<<(QDataStream &stream, const QPaintBuffer &buffer);
95Q_GUI_EXPORT QDataStream &operator>>(QDataStream &stream, QPaintBuffer &buffer);
96
97class QPaintBufferEngine;
98
99class QTextItemIntCopy
100{
101public:
102 QTextItemIntCopy(const QTextItem &item);
103 ~QTextItemIntCopy();
104 QTextItemInt &operator () () {return m_item;}
105private:
106 QTextItemInt m_item;
107 QFont m_font;
108};
109
110struct QPaintBufferCommand
111{
112 uint id : 8;
113 uint size : 24;
114
115 int offset;
116 int offset2;
117 int extra;
118};
119
120QDataStream &operator<<(QDataStream &stream, const QPaintBufferCommand &command);
121QDataStream &operator>>(QDataStream &stream, QPaintBufferCommand &command);
122
123Q_DECLARE_TYPEINFO(QPaintBufferCommand, Q_MOVABLE_TYPE);
124
125class QPaintBufferPrivate
126{
127public:
128 enum Command {
129 Cmd_Save,
130 Cmd_Restore,
131
132 Cmd_SetBrush,
133 Cmd_SetBrushOrigin,
134 Cmd_SetClipEnabled,
135 Cmd_SetCompositionMode,
136 Cmd_SetOpacity,
137 Cmd_SetPen,
138 Cmd_SetRenderHints,
139 Cmd_SetTransform,
140 Cmd_SetBackgroundMode,
141
142 Cmd_ClipPath,
143 Cmd_ClipRect,
144 Cmd_ClipRegion,
145 Cmd_ClipVectorPath,
146
147 Cmd_DrawVectorPath,
148 Cmd_FillVectorPath,
149 Cmd_StrokeVectorPath,
150
151 Cmd_DrawConvexPolygonF,
152 Cmd_DrawConvexPolygonI,
153 Cmd_DrawEllipseF,
154 Cmd_DrawEllipseI,
155 Cmd_DrawLineF,
156 Cmd_DrawLineI,
157 Cmd_DrawPath,
158 Cmd_DrawPointsF,
159 Cmd_DrawPointsI,
160 Cmd_DrawPolygonF,
161 Cmd_DrawPolygonI,
162 Cmd_DrawPolylineF,
163 Cmd_DrawPolylineI,
164 Cmd_DrawRectF,
165 Cmd_DrawRectI,
166
167 Cmd_FillRectBrush,
168 Cmd_FillRectColor,
169
170 Cmd_DrawText,
171 Cmd_DrawTextItem,
172
173 Cmd_DrawImagePos,
174 Cmd_DrawImageRect,
175 Cmd_DrawPixmapPos,
176 Cmd_DrawPixmapRect,
177 Cmd_DrawTiledPixmap,
178
179 Cmd_SystemStateChanged,
180
181 Cmd_LastCommand
182 };
183
184 QPaintBufferPrivate();
185 ~QPaintBufferPrivate();
186
187 int addData(const int *data, int count) {
188 if (count <= 0)
189 return 0;
190 int pos = ints.size();
191 ints.resize(pos + count);
192 memcpy(ints.data() + pos, data, count * sizeof(int));
193 return pos;
194 }
195
196 int addData(const qreal *data, int count) {
197 if (count <= 0)
198 return 0;
199 int pos = floats.size();
200 floats.resize(pos + count);
201 memcpy(floats.data() + pos, data, count * sizeof(qreal));
202 return pos;
203 }
204
205 int addData(const QVariant &var) {
206 variants << var;
207 return variants.size() - 1;
208 }
209
210 QPaintBufferCommand *addCommand(Command command) {
211 QPaintBufferCommand cmd;
212 cmd.id = command;
213 cmd.size = cmd.offset = cmd.offset2 = cmd.extra = 0;
214 commands << cmd;
215 return &commands.last();
216 }
217
218 QPaintBufferCommand *addCommand(Command command, const QVariant &var) {
219 QPaintBufferCommand cmd;
220 cmd.id = command;
221 cmd.offset = addData(var);
222 cmd.size = cmd.offset2 = cmd.extra = 0;
223 commands << cmd;
224 return &commands.last();
225 }
226
227 QPaintBufferCommand *addCommand(Command command, const QVectorPath &path) {
228 QPaintBufferCommand cmd;
229 cmd.id = command;
230 cmd.offset = addData(path.points(), path.elementCount() * 2);
231 cmd.offset2 = ints.size();
232 ints << path.hints();
233 // The absence of path elements is indicated by setting the highest bit in 'cmd.offset2'.
234 if (path.elements())
235 addData((const int *) path.elements(), path.elementCount());
236 else
237 cmd.offset2 |= 0x80000000;
238 cmd.size = path.elementCount();
239 cmd.extra = 0;
240 commands << cmd;
241 return &commands.last();
242 }
243
244 QPaintBufferCommand *addCommand(Command command , const qreal *pts, int arrayLength, int elementCount) {
245 QPaintBufferCommand cmd;
246 cmd.id = command;
247 cmd.offset = addData(pts, arrayLength);
248 cmd.size = elementCount;
249 cmd.offset2 = cmd.extra = 0;
250 commands << cmd;
251 return &commands.last();
252 }
253
254 QPaintBufferCommand *addCommand(Command command , const int *pts, int arrayLength, int elementCount) {
255 QPaintBufferCommand cmd;
256 cmd.id = command;
257 cmd.offset = addData(pts, arrayLength);
258 cmd.size = elementCount;
259 cmd.offset2 = cmd.extra = 0;
260 commands << cmd;
261 return &commands.last();
262 }
263
264 inline void updateBoundingRect(const QRectF &rect);
265
266 QAtomicInt ref;
267
268 QVector<int> ints;
269 QVector<qreal> floats;
270 QVector<QVariant> variants;
271
272 QVector<QPaintBufferCommand> commands;
273
274 QPaintBufferEngine *engine;
275 QRectF boundingRect;
276 qreal penWidthAdjustment;
277 uint calculateBoundingRect : 1;
278
279 void *cache;
280};
281
282
283struct QVectorPathCmd
284{
285 // The absence of path elements is indicated by setting the highest bit in 'cmd.offset2'.
286 QVectorPathCmd(QPaintBufferPrivate *d, const QPaintBufferCommand &cmd)
287 : vectorPath(d->floats.constData() + cmd.offset,
288 cmd.size,
289 cmd.offset2 & 0x80000000
290 ? 0
291 : (const QPainterPath::ElementType *) (d->ints.constData() + cmd.offset2 + 1),
292 *(d->ints.constData() + (cmd.offset2 & 0x7fffffff))) {}
293
294 inline const QVectorPath &operator()() const { return vectorPath; }
295
296 QVectorPath vectorPath;
297};
298
299
300class Q_GUI_EXPORT QPainterReplayer
301{
302public:
303 QPainterReplayer() { }
304
305 virtual ~QPainterReplayer() { }
306
307 void setupTransform(QPainter *painter);
308 void process(const QPaintBufferCommand &cmd);
309 void draw(const QPaintBuffer &buffer, QPainter *painter);
310
311protected:
312 QPaintBufferPrivate *d;
313 QTransform m_world_matrix;
314
315 QPainter *painter;
316};
317
318class Q_GUI_EXPORT QPaintEngineExReplayer : public QPainterReplayer
319{
320public:
321 QPaintEngineExReplayer() { }
322
323 void process(const QPaintBufferCommand &cmd);
324};
325
326class QPaintBufferEnginePrivate;
327
328class QPaintBufferEngine : public QPaintEngineEx
329{
330 Q_DECLARE_PRIVATE(QPaintBufferEngine)
331public:
332 QPaintBufferEngine(QPaintBufferPrivate *buffer);
333
334 virtual bool begin(QPaintDevice *device);
335 virtual bool end();
336
337 virtual Type type() const { return QPaintEngine::PaintBuffer; }
338
339 virtual QPainterState *createState(QPainterState *orig) const;
340
341 virtual void draw(const QVectorPath &path);
342 virtual void fill(const QVectorPath &path, const QBrush &brush);
343 virtual void stroke(const QVectorPath &path, const QPen &pen);
344
345 virtual void clip(const QVectorPath &path, Qt::ClipOperation op);
346 virtual void clip(const QRect &rect, Qt::ClipOperation op);
347 virtual void clip(const QRegion &region, Qt::ClipOperation op);
348 virtual void clip(const QPainterPath &path, Qt::ClipOperation op);
349
350 virtual void clipEnabledChanged();
351 virtual void penChanged();
352 virtual void brushChanged();
353 virtual void brushOriginChanged();
354 virtual void opacityChanged();
355 virtual void compositionModeChanged();
356 virtual void renderHintsChanged();
357 virtual void transformChanged();
358 virtual void backgroundModeChanged();
359
360 virtual void fillRect(const QRectF &rect, const QBrush &brush);
361 virtual void fillRect(const QRectF &rect, const QColor &color);
362
363 virtual void drawRects(const QRect *rects, int rectCount);
364 virtual void drawRects(const QRectF *rects, int rectCount);
365
366 virtual void drawLines(const QLine *lines, int lineCount);
367 virtual void drawLines(const QLineF *lines, int lineCount);
368
369 virtual void drawEllipse(const QRectF &r);
370 virtual void drawEllipse(const QRect &r);
371
372 virtual void drawPath(const QPainterPath &path);
373
374 virtual void drawPoints(const QPointF *points, int pointCount);
375 virtual void drawPoints(const QPoint *points, int pointCount);
376
377 virtual void drawPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode);
378 virtual void drawPolygon(const QPoint *points, int pointCount, PolygonDrawMode mode);
379
380 virtual void drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr);
381 virtual void drawPixmap(const QPointF &pos, const QPixmap &pm);
382
383 virtual void drawImage(const QRectF &r, const QImage &pm, const QRectF &sr,
384 Qt::ImageConversionFlags flags = Qt::AutoColor);
385 virtual void drawImage(const QPointF &pos, const QImage &image);
386
387 virtual void drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, const QPointF &s);
388
389 virtual void drawTextItem(const QPointF &pos, const QTextItem &ti);
390
391 virtual void setState(QPainterState *s);
392 virtual uint flags() const {return QPaintEngineEx::DoNotEmulate;}
393
394 QPaintBufferPrivate *buffer;
395
396 mutable int m_begin_detected : 1;
397 mutable int m_save_detected : 1;
398 mutable int m_stream_raw_text_items : 1;
399 mutable int m_unused : 29;
400
401 mutable QPainterState *m_created_state;
402};
403
404class Q_GUI_EXPORT QPaintBufferSignalProxy : public QObject
405{
406 Q_OBJECT
407public:
408 QPaintBufferSignalProxy() : QObject() {}
409 void emitAboutToDestroy(const QPaintBufferPrivate *buffer) {
410 emit aboutToDestroy(buffer);
411 }
412 static QPaintBufferSignalProxy *instance();
413Q_SIGNALS:
414 void aboutToDestroy(const QPaintBufferPrivate *buffer);
415};
416
417// One resource per paint buffer and vice versa.
418class Q_GUI_EXPORT QPaintBufferResource : public QObject
419{
420 Q_OBJECT
421public:
422 typedef void (*FreeFunc)(void *);
423
424 QPaintBufferResource(FreeFunc f, QObject *parent = 0);
425 ~QPaintBufferResource();
426 // Set resource 'value' for 'key'.
427 void insert(const QPaintBufferPrivate *key, void *value);
428 // Return resource for 'key'.
429 void *value(const QPaintBufferPrivate *key);
430public slots:
431 // Remove entry 'key' from cache and delete resource.
432 void remove(const QPaintBufferPrivate *key);
433private:
434 typedef QHash<const QPaintBufferPrivate *, void *> Cache;
435 Cache m_cache;
436 FreeFunc free;
437};
438
439#endif // QPAINTBUFFER_P_H
src/gui/painting/qpaintengine.h
(2 / 0)
  
212212 Pdf,
213213 OpenVG,
214214 OpenGL2,
215 PaintBuffer,
215216
216217 User = 50, // first user type id
217218 MaxUser = 100 // last user type id
249249 bool autoDestruct() const { return selfDestruct; }
250250 Q_DISABLE_COPY(QPaintEngine)
251251
252 friend class QPainterReplayer;
252253 friend class QFontEngineBox;
253254 friend class QFontEngineMac;
254255 friend class QFontEngineWin;
src/gui/painting/qpaintengineex.cpp
(0 / 34)
  
9292 return QRectF(QPointF(m_cp_rect.x1, m_cp_rect.y1), QPointF(m_cp_rect.x2, m_cp_rect.y2));
9393}
9494
95QPainterPath QVectorPath::convertToPainterPath() const
96{
97 QPainterPath path;
98
99 if (m_count == 0)
100 return path;
101
102 const QPointF *points = (const QPointF *) m_points;
103
104 if (m_elements) {
105 for (int i=0; i<m_count; ++i) {
106 switch (m_elements[i]) {
107 case QPainterPath::MoveToElement:
108 path.moveTo(points[i]);
109 break;
110 case QPainterPath::LineToElement:
111 path.lineTo(points[i]);
112 break;
113 case QPainterPath::CurveToElement:
114 path.cubicTo(points[i], points[i+1], points[i+2]);
115 break;
116 default:
117 break;
118 }
119 }
120 } else {
121 path.moveTo(points[0]);
122 for (int i=1; i<m_count; ++i)
123 path.lineTo(points[i]);
124 }
125
126 return path;
127}
128
12995const QVectorPath &qtVectorPathForPath(const QPainterPath &path)
13096{
13197 Q_ASSERT(path.d_func());
src/gui/painting/qpaintengineex_p.h
(8 / 0)
  
209209
210210 virtual QPixmapFilter *createPixmapFilter(int /*type*/) const { return 0; }
211211
212 // These flags are needed in the implementation of paint buffers.
213 enum Flags
214 {
215 DoNotEmulate = 0x01, // If set, QPainter will not wrap this engine in an emulation engine.
216 IsEmulationEngine = 0x02 // If set, this object is a QEmulationEngine.
217 };
218 virtual uint flags() const {return 0;}
219
212220protected:
213221 QPaintEngineEx(QPaintEngineExPrivate &data);
214222};
src/gui/painting/qpainter.cpp
(8 / 5)
  
162162void QPainterPrivate::checkEmulation()
163163{
164164 Q_ASSERT(extended);
165 if (extended->flags() & QPaintEngineEx::DoNotEmulate)
166 return;
167
165168 bool doEmulation = false;
166169 if (state->bgMode == Qt::OpaqueMode)
167170 doEmulation = true;
18381838 return true;
18391839 }
18401840
1841 if (d->states.size() > 1) {
1842 qWarning("QPainter::end: Painter ended with %d saved states",
1843 d->states.size());
1844 }
1845
18461841 bool ended = true;
18471842
18481843 if (d->engine->isActive()) {
18491849 d->engine->setPaintDevice(0);
18501850 d->engine->setActive(false);
18511851 }
1852 }
1853
1854 if (d->states.size() > 1) {
1855 qWarning("QPainter::end: Painter ended with %d saved states",
1856 d->states.size());
18521857 }
18531858
18541859 if (d->engine->autoDestruct()) {
src/gui/painting/qpainterpath.h
(2 / 0)
  
220220 friend class QPainterPathStrokerPrivate;
221221 friend class QMatrix;
222222 friend class QTransform;
223 friend class QVectorPath;
223224 friend Q_GUI_EXPORT const QVectorPath &qtVectorPathForPath(const QPainterPath &);
224225
225226#ifndef QT_NO_DATASTREAM
238238 friend class QPainterPathStrokerPrivate;
239239 friend class QMatrix;
240240 friend class QTransform;
241 friend class QVectorPath;
241242 friend struct QPainterPathPrivateDeleter;
242243#ifndef QT_NO_DATASTREAM
243244 friend Q_GUI_EXPORT QDataStream &operator<<(QDataStream &, const QPainterPath &);
src/gui/painting/qpainterpath_p.h
(36 / 0)
  
176176};
177177
178178
179inline const QPainterPath QVectorPath::convertToPainterPath() const
180{
181 QPainterPath path;
182 path.ensureData();
183 QPainterPathData *data = path.d_func();
184 data->elements.reserve(m_count);
185 int index = 0;
186 data->elements[0].x = m_points[index++];
187 data->elements[0].y = m_points[index++];
188
189 if (m_elements) {
190 data->elements[0].type = m_elements[0];
191 for (int i=1; i<m_count; ++i) {
192 QPainterPath::Element element;
193 element.x = m_points[index++];
194 element.y = m_points[index++];
195 element.type = m_elements[i];
196 data->elements << element;
197 }
198 } else {
199 data->elements[0].type = QPainterPath::MoveToElement;
200 for (int i=1; i<m_count; ++i) {
201 QPainterPath::Element element;
202 element.x = m_points[index++];
203 element.y = m_points[index++];
204 element.type = QPainterPath::LineToElement;
205 data->elements << element;
206 }
207 }
208
209 if (m_hints & OddEvenFill)
210 data->fillRule = Qt::OddEvenFill;
211 else
212 data->fillRule = Qt::WindingFill;
213 return path;
214}
179215
180216void Q_GUI_EXPORT qt_find_ellipse_coords(const QRectF &r, qreal angle, qreal length,
181217 QPointF* startPoint, QPointF *endPoint);
src/gui/painting/qvectorpath_p.h
(1 / 2)
  
127127 inline bool isEmpty() const { return m_points == 0; }
128128
129129 inline int elementCount() const { return m_count; }
130 inline const QPainterPath convertToPainterPath() const;
130131
131132 static inline uint polygonFlags(QPaintEngine::PolygonDrawMode mode);
132
133 QPainterPath convertToPainterPath() const;
134133
135134private:
136135 Q_DISABLE_COPY(QVectorPath)
src/gui/text/qfont.h
(2 / 0)
  
307307 friend class QPainterPath;
308308 friend class QTextItemInt;
309309 friend class QPicturePaintEngine;
310 friend class QPainterReplayer;
311 friend class QPaintBufferEngine;
310312
311313#ifndef QT_NO_DATASTREAM
312314 friend Q_GUI_EXPORT QDataStream &operator<<(QDataStream &, const QFont &);
src/plugins/graphicssystems/graphicssystems.pro
(1 / 0)
  
11TEMPLATE = subdirs
2SUBDIRS += trace
23contains(QT_CONFIG, opengl):SUBDIRS += opengl
34contains(QT_CONFIG, openvg):contains(QT_CONFIG, egl):SUBDIRS += openvg
45
src/plugins/graphicssystems/trace/main.cpp
(69 / 0)
  
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** Contact: Nokia Corporation (qt-info@nokia.com)
5**
6** This file is part of the plugins of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** No Commercial Usage
10** This file contains pre-release code and may not be distributed.
11** You may use this file in accordance with the terms and conditions
12** contained in the Technology Preview License Agreement accompanying
13** this package.
14**
15** GNU Lesser General Public License Usage
16** Alternatively, this file may be used under the terms of the GNU Lesser
17** General Public License version 2.1 as published by the Free Software
18** Foundation and appearing in the file LICENSE.LGPL included in the
19** packaging of this file. Please review the following information to
20** ensure the GNU Lesser General Public License version 2.1 requirements
21** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22**
23** In addition, as a special exception, Nokia gives you certain
24** additional rights. These rights are described in the Nokia Qt LGPL
25** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
26** package.
27**
28** If you have questions regarding the use of this file, please contact
29** Nokia at qt-info@nokia.com.
30**
31**
32**
33**
34**
35**
36**
37**
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include <private/qgraphicssystemplugin_p.h>
43#include "qgraphicssystem_trace_p.h"
44
45QT_BEGIN_NAMESPACE
46
47class QTraceGraphicsSystemPlugin : public QGraphicsSystemPlugin
48{
49public:
50 QStringList keys() const;
51 QGraphicsSystem *create(const QString&);
52};
53
54QStringList QTraceGraphicsSystemPlugin::keys() const
55{
56 return QStringList(QLatin1String("Trace"));
57}
58
59QGraphicsSystem* QTraceGraphicsSystemPlugin::create(const QString& system)
60{
61 if (system.toLower() == QLatin1String("trace"))
62 return new QTraceGraphicsSystem;
63
64 return 0;
65}
66
67Q_EXPORT_PLUGIN2(trace, QTraceGraphicsSystemPlugin)
68
69QT_END_NAMESPACE
src/plugins/graphicssystems/trace/qgraphicssystem_trace.cpp
(133 / 0)
  
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** Contact: Nokia Corporation (qt-info@nokia.com)
5**
6** This file is part of the plugins of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** No Commercial Usage
10** This file contains pre-release code and may not be distributed.
11** You may use this file in accordance with the terms and conditions
12** contained in the Technology Preview License Agreement accompanying
13** this package.
14**
15** GNU Lesser General Public License Usage
16** Alternatively, this file may be used under the terms of the GNU Lesser
17** General Public License version 2.1 as published by the Free Software
18** Foundation and appearing in the file LICENSE.LGPL included in the
19** packaging of this file. Please review the following information to
20** ensure the GNU Lesser General Public License version 2.1 requirements
21** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22**
23** In addition, as a special exception, Nokia gives you certain
24** additional rights. These rights are described in the Nokia Qt LGPL
25** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
26** package.
27**
28** If you have questions regarding the use of this file, please contact
29** Nokia at qt-info@nokia.com.
30**
31**
32**
33**
34**
35**
36**
37**
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qgraphicssystem_trace_p.h"
43#include <private/qpixmap_raster_p.h>
44#include <private/qpaintbuffer_p.h>
45#include <private/qwindowsurface_raster_p.h>
46
47#include <QFile>
48#include <QPainter>
49#include <QtDebug>
50
51QT_BEGIN_NAMESPACE
52
53class QTraceWindowSurface : public QRasterWindowSurface
54{
55public:
56 QTraceWindowSurface(QWidget *widget);
57 ~QTraceWindowSurface();
58
59 QPaintDevice *paintDevice();
60 void endPaint(const QRegion &rgn);
61
62private:
63 QPaintBuffer *buffer;
64
65 QFile *outputFile;
66 QDataStream *out;
67
68 int frameId;
69};
70
71QTraceWindowSurface::QTraceWindowSurface(QWidget *widget)
72 : QRasterWindowSurface(widget)
73 , buffer(0)
74 , outputFile(0)
75 , out(0)
76 , frameId(0)
77{
78}
79
80QTraceWindowSurface::~QTraceWindowSurface()
81{
82 delete out;
83 delete outputFile;
84}
85
86QPaintDevice *QTraceWindowSurface::paintDevice()
87{
88 if (!buffer) {
89 buffer = new QPaintBuffer;
90 buffer->setBoundingRect(geometry());
91 }
92 return buffer;
93}
94
95void QTraceWindowSurface::endPaint(const QRegion &rgn)
96{
97 if (!out) {
98 outputFile = new QFile(QString(QLatin1String("qtgraphics-%0.trace")).arg((qulonglong)window()->winId()));
99 if (outputFile->open(QIODevice::WriteOnly))
100 out = new QDataStream(outputFile);
101 }
102
103 QPainter p(QRasterWindowSurface::paintDevice());
104 buffer->draw(&p);
105 p.end();
106
107 if (out) {
108 *out << frameId++;
109 *out << (qulonglong)window()->winId();
110 *out << geometry();
111 *out << rgn;
112 *out << *buffer;
113 }
114
115 delete buffer;
116 buffer = 0;
117}
118
119QTraceGraphicsSystem::QTraceGraphicsSystem()
120{
121}
122
123QPixmapData *QTraceGraphicsSystem::createPixmapData(QPixmapData::PixelType type) const
124{
125 return new QRasterPixmapData(type);
126}
127
128QWindowSurface *QTraceGraphicsSystem::createWindowSurface(QWidget *widget) const
129{
130 return new QTraceWindowSurface(widget);
131}
132
133QT_END_NAMESPACE
src/plugins/graphicssystems/trace/qgraphicssystem_trace_p.h
(71 / 0)
  
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** Contact: Nokia Corporation (qt-info@nokia.com)
5**
6** This file is part of the plugins of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** No Commercial Usage
10** This file contains pre-release code and may not be distributed.
11** You may use this file in accordance with the terms and conditions
12** contained in the Technology Preview License Agreement accompanying
13** this package.
14**
15** GNU Lesser General Public License Usage
16** Alternatively, this file may be used under the terms of the GNU Lesser
17** General Public License version 2.1 as published by the Free Software
18** Foundation and appearing in the file LICENSE.LGPL included in the
19** packaging of this file. Please review the following information to
20** ensure the GNU Lesser General Public License version 2.1 requirements
21** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22**
23** In addition, as a special exception, Nokia gives you certain
24** additional rights. These rights are described in the Nokia Qt LGPL
25** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
26** package.
27**
28** If you have questions regarding the use of this file, please contact
29** Nokia at qt-info@nokia.com.
30**
31**
32**
33**
34**
35**
36**
37**
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#ifndef QGRAPHICSSYSTEM_TRACE_P_H
43#define QGRAPHICSSYSTEM_TRACE_P_H
44
45//
46// W A R N I N G
47// -------------
48//
49// This file is not part of the Qt API. It exists for the convenience
50// of other Qt classes. This header file may change from version to
51// version without notice, or even be removed.
52//
53// We mean it.
54//
55
56#include <QtGui/private/qgraphicssystem_p.h>
57
58QT_BEGIN_NAMESPACE
59
60class QTraceGraphicsSystem : public QGraphicsSystem
61{
62public:
63 QTraceGraphicsSystem();
64
65 QPixmapData *createPixmapData(QPixmapData::PixelType type) const;
66 QWindowSurface *createWindowSurface(QWidget *widget) const;
67};
68
69QT_END_NAMESPACE
70
71#endif
src/plugins/graphicssystems/trace/trace.pro
(12 / 0)
  
1TARGET = qtracegraphicssystem
2include(../../qpluginbase.pri)
3
4QT += network
5
6QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/graphicssystems
7
8SOURCES = main.cpp qgraphicssystem_trace.cpp
9
10target.path += $$[QT_INSTALL_PLUGINS]/graphicssystems
11INSTALLS += target
12INCLUDEPATH += ../../../3rdparty/harfbuzz/src
tools/qttracereplay/main.cpp
(198 / 0)
  
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** Contact: Nokia Corporation (qt-info@nokia.com)
5**
6** This file is part of the tools applications of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** No Commercial Usage
10** This file contains pre-release code and may not be distributed.
11** You may use this file in accordance with the terms and conditions
12** contained in the Technology Preview License Agreement accompanying
13** this package.
14**
15** GNU Lesser General Public License Usage
16** Alternatively, this file may be used under the terms of the GNU Lesser
17** General Public License version 2.1 as published by the Free Software
18** Foundation and appearing in the file LICENSE.LGPL included in the
19** packaging of this file. Please review the following information to
20** ensure the GNU Lesser General Public License version 2.1 requirements
21** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22**
23** In addition, as a special exception, Nokia gives you certain
24** additional rights. These rights are described in the Nokia Qt LGPL
25** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
26** package.
27**
28** If you have questions regarding the use of this file, please contact
29** Nokia at qt-info@nokia.com.
30**
31**
32**
33**
34**
35**
36**
37**
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include <QtGui>
43#include <QtDebug>
44
45#include <private/qpaintengineex_p.h>
46#include <private/qpaintbuffer_p.h>
47
48struct Frame
49{
50 QRegion updateRegion;
51 QPaintBuffer *buffer;
52};
53
54class ReplayWidget : public QWidget
55{
56 Q_OBJECT
57public:
58 ReplayWidget(const QString &filename);
59
60 void paintEvent(QPaintEvent *event);
61
62public slots:
63 void updateRect();
64
65private:
66 QList<Frame> frames;
67 int currentFrame;
68 int currentIteration;
69 QTime timer;
70
71 QList<uint> iterationTimes;
72 QString filename;
73};
74
75void ReplayWidget::updateRect()
76{
77 update(frames.at(currentFrame).updateRegion);
78}
79
80void ReplayWidget::paintEvent(QPaintEvent *)
81{
82 QPainter p(this);
83
84// p.setClipRegion(frames.at(currentFrame).updateRegion);
85
86 frames.at(currentFrame).buffer->draw(&p);
87
88 ++currentFrame;
89 if (currentFrame >= frames.size()) {
90 currentFrame = 0;
91 ++currentIteration;
92
93 if (currentIteration == 3)
94 timer.start();
95 else if (currentIteration > 3) {
96 iterationTimes << timer.elapsed();
97 timer.restart();
98
99 if (iterationTimes.size() >= 3) {
100 qreal mean = 0;
101 qreal stddev = 0;
102 uint min = INT_MAX;
103
104 for (int i = 0; i < iterationTimes.size(); ++i) {
105 mean += iterationTimes.at(i);
106 min = qMin(min, iterationTimes.at(i));
107 }
108
109 mean /= qreal(iterationTimes.size());
110
111 for (int i = 0; i < iterationTimes.size(); ++i) {
112 qreal delta = iterationTimes.at(i) - mean;
113 stddev += delta * delta;
114 }
115
116 stddev = qSqrt(stddev / iterationTimes.size());
117
118 qSort(iterationTimes.begin(), iterationTimes.end());
119 qreal median = iterationTimes.at(iterationTimes.size() / 2);
120 if ((iterationTimes.size() % 1) == 1)
121 median = (median + iterationTimes.at(iterationTimes.size() / 2 - 1)) * 0.5;
122
123 stddev = 100 * stddev / mean;
124
125 if (iterationTimes.size() >= 10 || stddev < 4) {
126 printf("%s, iterations: %d, frames: %d, min(ms): %d, median(ms): %f, stddev: %f %%, max(fps): %f\n", qPrintable(filename),
127 iterationTimes.size(), frames.size(), min, median, stddev, 1000. * frames.size() / min);
128 deleteLater();
129 return;
130 }
131 }
132 }
133 }
134
135 QTimer::singleShot(0, this, SLOT(updateRect()));
136}
137
138ReplayWidget::ReplayWidget(const QString &filename_)
139 : currentFrame(0)
140 , currentIteration(0)
141 , filename(filename_)
142{
143 setWindowTitle(filename);
144 QFile file(filename);
145
146 QRect bounds;
147 if (file.open(QIODevice::ReadOnly)) {
148 QDataStream in(&file);
149
150 while (true) {
151 int frameId;
152 in >> frameId;
153
154 if (in.status() != QDataStream::Ok)
155 break;
156
157 qulonglong windowId;
158 QRegion rgn;
159
160 in >> windowId;
161
162 Frame frame;
163 frame.buffer = new QPaintBuffer;
164
165 in >> bounds;
166
167 in >> frame.updateRegion;
168 in >> *frame.buffer;
169
170 frames << frame;
171 }
172 }
173
174 qDebug() << "Read" << frames.size() << "frames";
175
176 resize(bounds.size());
177
178 setAutoFillBackground(false);
179 setAttribute(Qt::WA_NoSystemBackground);
180
181 QTimer::singleShot(10, this, SLOT(updateRect()));
182}
183
184int main(int argc, char **argv)
185{
186 QApplication app(argc, argv);
187
188 if (argc <= 1) {
189 printf("Usage: %s filename\n", argv[0]);
190 return 1;
191 }
192
193 ReplayWidget *widget = new ReplayWidget(argv[1]);
194 widget->show();
195
196 return app.exec();
197}
198#include "main.moc"
tools/qttracereplay/qttracereplay.pro
(13 / 0)
  
1TEMPLATE = app
2
3DESTDIR = ../../bin
4
5DEPENDPATH += .
6INCLUDEPATH += . ../../src/3rdparty/harfbuzz/src
7TARGET = qttracereplay
8
9# Input
10SOURCES += main.cpp
11
12target.path=$$[QT_INSTALL_BINS]
13INSTALLS += target
tools/tools.pro
(2 / 1)
  
66 SUBDIRS += assistant \
77 pixeltool \
88 porting \
9 qtestlib
9 qtestlib \
10 qttracereplay
1011 contains(QT_EDITION, Console) {
1112 SUBDIRS += designer/src/uitools # Linguist depends on this
1213 } else {

Comments

Add a new comment:

Login or create an account to post a comment

Add your comment