source: trunk/src/gui/painting/qpaintbuffer.cpp@ 1166

Last change on this file since 1166 was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

  • Property svn:eol-style set to native
File size: 78.8 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the QtGui module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41#include <qmath.h>
42#include <private/qpainterpath_p.h>
43#include <private/qpaintbuffer_p.h>
44//#include <private/qtextengine_p.h>
45#include <private/qfontengine_p.h>
46#include <private/qemulationpaintengine_p.h>
47#include <private/qimage_p.h>
48#include <qstatictext.h>
49#include <private/qstatictext_p.h>
50
51#include <QDebug>
52
53// #define QPAINTBUFFER_DEBUG_DRAW
54
55QT_BEGIN_NAMESPACE
56
57Q_GUI_EXPORT extern int qt_defaultDpiX();
58Q_GUI_EXPORT extern int qt_defaultDpiY();
59extern void qt_format_text(const QFont &font,
60 const QRectF &_r, int tf, const QTextOption *option, const QString& str, QRectF *brect,
61 int tabstops, int* tabarray, int tabarraylen,
62 QPainter *painter);
63
64QTextItemIntCopy::QTextItemIntCopy(const QTextItem &item)
65 : m_item(static_cast<const QTextItemInt &>(item))
66{
67 QChar *chars = new QChar[m_item.num_chars];
68 unsigned short *logClusters = new unsigned short[m_item.num_chars];
69 memcpy(chars, m_item.chars, m_item.num_chars * sizeof(QChar));
70 memcpy(logClusters, m_item.logClusters, m_item.num_chars * sizeof(unsigned short));
71 m_item.chars = chars;
72 m_item.logClusters = logClusters;
73
74 const int size = QGlyphLayout::spaceNeededForGlyphLayout(m_item.glyphs.numGlyphs);
75 char *glyphLayoutData = new char[size];
76 QGlyphLayout glyphs(glyphLayoutData, m_item.glyphs.numGlyphs);
77 memcpy(glyphs.offsets, m_item.glyphs.offsets, m_item.glyphs.numGlyphs * sizeof(QFixedPoint));
78 memcpy(glyphs.glyphs, m_item.glyphs.glyphs, m_item.glyphs.numGlyphs * sizeof(HB_Glyph));
79 memcpy(glyphs.advances_x, m_item.glyphs.advances_x, m_item.glyphs.numGlyphs * sizeof(QFixed));
80 memcpy(glyphs.advances_y, m_item.glyphs.advances_y, m_item.glyphs.numGlyphs * sizeof(QFixed));
81 memcpy(glyphs.justifications, m_item.glyphs.justifications, m_item.glyphs.numGlyphs * sizeof(QGlyphJustification));
82 memcpy(glyphs.attributes, m_item.glyphs.attributes, m_item.glyphs.numGlyphs * sizeof(HB_GlyphAttributes));
83 m_item.glyphs = glyphs;
84
85 m_font = *m_item.f;
86 m_item.f = &m_font;
87
88 m_item.fontEngine->ref.ref(); // Increment reference count.
89}
90
91QTextItemIntCopy::~QTextItemIntCopy()
92{
93 delete m_item.chars;
94 delete m_item.logClusters;
95 delete m_item.glyphs.data();
96 if (!m_item.fontEngine->ref.deref())
97 delete m_item.fontEngine;
98}
99
100/************************************************************************
101 *
102 * QPaintBufferSignalProxy
103 *
104 ************************************************************************/
105
106Q_GLOBAL_STATIC(QPaintBufferSignalProxy, theSignalProxy)
107
108QPaintBufferSignalProxy *QPaintBufferSignalProxy::instance()
109{
110 return theSignalProxy();
111}
112
113/************************************************************************
114 *
115 * QPaintBufferPrivate
116 *
117 ************************************************************************/
118
119QPaintBufferPrivate::QPaintBufferPrivate()
120 : ref(1), engine(0), penWidthAdjustment(0)
121 , calculateBoundingRect(true)
122 , cache(0)
123{
124}
125
126QPaintBufferPrivate::~QPaintBufferPrivate()
127{
128 QPaintBufferSignalProxy::instance()->emitAboutToDestroy(this);
129
130 for (int i = 0; i < commands.size(); ++i) {
131 const QPaintBufferCommand &cmd = commands.at(i);
132 if (cmd.id == QPaintBufferPrivate::Cmd_DrawTextItem)
133 delete reinterpret_cast<QTextItemIntCopy *>(qVariantValue<void *>(variants.at(cmd.offset)));
134 }
135}
136
137
138inline void QPaintBufferPrivate::updateBoundingRect(const QRectF &br)
139{
140 // transform to device coords and adjust for pen width
141 Q_ASSERT(engine && engine->painter());
142 QPainter *painter = engine->painter();
143 const QTransform transform = painter->transform();
144 QRectF devRect = transform.mapRect(br);
145 if (penWidthAdjustment > 0) {
146 devRect = devRect.adjusted(-penWidthAdjustment, -penWidthAdjustment,
147 penWidthAdjustment, penWidthAdjustment);
148 }
149
150 if (boundingRect.isEmpty()) {
151 boundingRect = devRect;
152 } else {
153 qreal min_x = qMin(devRect.left(), boundingRect.left());
154 qreal min_y = qMin(devRect.top(), boundingRect.top());
155 qreal max_x = qMax(devRect.right(), boundingRect.right());
156 qreal max_y = qMax(devRect.bottom(), boundingRect.bottom());
157 boundingRect = QRectF(min_x, min_y, max_x - min_x, max_y - min_y);
158 }
159 if (painter->hasClipping())
160 boundingRect &= transform.mapRect(painter->clipRegion().boundingRect());
161}
162
163
164/************************************************************************
165 *
166 * QPaintBuffer
167 *
168 ************************************************************************/
169
170
171
172QPaintBuffer::QPaintBuffer()
173 : d_ptr(new QPaintBufferPrivate)
174{
175}
176
177QPaintBuffer::~QPaintBuffer()
178{
179 if (!d_ptr->ref.deref())
180 delete d_ptr;
181}
182
183QPaintBuffer::QPaintBuffer(const QPaintBuffer &other)
184 : QPaintDevice(), d_ptr(other.d_ptr)
185{
186 d_ptr->ref.ref();
187}
188
189QPaintEngine *QPaintBuffer::paintEngine() const
190{
191 QPaintBufferPrivate *d = const_cast<QPaintBuffer *>(this)->d_ptr;
192 if (!d->engine)
193 d->engine = new QPaintBufferEngine(d);
194 return d->engine;
195}
196
197
198int QPaintBuffer::metric(PaintDeviceMetric metric) const
199{
200 int val = 0;
201 switch (metric) {
202 case PdmWidth:
203 val = qCeil(d_ptr->boundingRect.width());
204 break;
205 case PdmHeight:
206 val = qCeil(d_ptr->boundingRect.height());
207 break;
208 case PdmDpiX:
209 case PdmPhysicalDpiX:
210 val = qt_defaultDpiX();
211 break;
212 case PdmDpiY:
213 case PdmPhysicalDpiY:
214 val = qt_defaultDpiY();
215 break;
216 default:
217 val = QPaintDevice::metric(metric);
218 }
219
220 return val;
221}
222
223int QPaintBuffer::devType() const
224{
225 return QInternal::PaintBuffer;
226}
227
228QPaintBuffer &QPaintBuffer::operator=(const QPaintBuffer &other)
229{
230 if (other.d_ptr != d_ptr) {
231 QPaintBufferPrivate *data = other.d_ptr;
232 data->ref.ref();
233 if (d_ptr->ref.deref())
234 delete d_ptr;
235 d_ptr = data;
236 }
237 return *this;
238}
239
240bool QPaintBuffer::isEmpty() const
241{
242 return d_ptr->commands.isEmpty();
243}
244
245
246
247void QPaintBuffer::draw(QPainter *painter, int frame) const
248{
249#ifdef QPAINTBUFFER_DEBUG_DRAW
250 qDebug() << "QPaintBuffer::draw() --------------------------------";
251
252 Q_D(const QPaintBuffer);
253 printf("Float buffer:");
254 for (int i=0; i<d->floats.size(); i++) {
255 if ((i % 10) == 0) {
256 printf("\n%4d-%4d: ", i, i+9);
257 }
258 printf("%4.2f ", d->floats[i]);
259 }
260 printf("\n");
261
262 printf("Int Buffer:");
263 for (int i=0; i<d->ints.size(); i++) {
264 if ((i % 10) == 0) {
265 printf("\n%4d-%4d: ", i, i+10);
266 }
267 printf("%5d", d->ints[i]);
268 }
269 printf("\n");
270#endif
271
272 processCommands(painter, frameStartIndex(frame), frameEndIndex(frame));
273
274#ifdef QPAINTBUFFER_DEBUG_DRAW
275 qDebug() << "QPaintBuffer::draw() -------------------------------- DONE!";
276#endif
277}
278
279int QPaintBuffer::frameStartIndex(int frame) const
280{
281 return (frame == 0) ? 0 : d_ptr->frames.at(frame - 1);
282}
283
284int QPaintBuffer::frameEndIndex(int frame) const
285{
286 return (frame == d_ptr->frames.size()) ? d_ptr->commands.size() : d_ptr->frames.at(frame);
287}
288
289int QPaintBuffer::processCommands(QPainter *painter, int begin, int end) const
290{
291 if (!painter || !painter->isActive())
292 return 0;
293
294 QPaintEngineEx *xengine = painter->paintEngine()->isExtended()
295 ? (QPaintEngineEx *) painter->paintEngine() : 0;
296 if (xengine) {
297 QPaintEngineExReplayer player;
298 player.processCommands(*this, painter, begin, end);
299 } else {
300 QPainterReplayer player;
301 player.processCommands(*this, painter, begin, end);
302 }
303
304 int depth = 0;
305 for (int i = begin; i < end; ++i) {
306 const QPaintBufferCommand &cmd = d_ptr->commands.at(i);
307 if (cmd.id == QPaintBufferPrivate::Cmd_Save)
308 ++depth;
309 else if (cmd.id == QPaintBufferPrivate::Cmd_Restore)
310 --depth;
311 }
312 return depth;
313}
314
315#ifndef QT_NO_DEBUG_STREAM
316QString QPaintBuffer::commandDescription(int command) const
317{
318 QString desc;
319 QDebug debug(&desc);
320
321 const QPaintBufferCommand &cmd = d_ptr->commands.at(command);
322
323 switch (cmd.id) {
324 case QPaintBufferPrivate::Cmd_Save: {
325 debug << "Cmd_Save";
326 break; }
327
328 case QPaintBufferPrivate::Cmd_Restore: {
329 debug << "Cmd_Restore";
330 break; }
331
332 case QPaintBufferPrivate::Cmd_SetBrush: {
333 QBrush brush = qVariantValue<QBrush>(d_ptr->variants.at(cmd.offset));
334 debug << "Cmd_SetBrush: " << brush;
335 break; }
336
337 case QPaintBufferPrivate::Cmd_SetBrushOrigin: {
338 debug << "Cmd_SetBrushOrigin: " << d_ptr->variants.at(cmd.offset).toPointF();
339 break; }
340
341 case QPaintBufferPrivate::Cmd_SetCompositionMode: {
342 QPainter::CompositionMode mode = (QPainter::CompositionMode) cmd.extra;
343 debug << "ExCmd_SetCompositionMode, mode: " << mode;
344 break; }
345
346 case QPaintBufferPrivate::Cmd_SetOpacity: {
347 debug << "ExCmd_SetOpacity: " << d_ptr->variants.at(cmd.offset).toDouble();
348 break; }
349
350 case QPaintBufferPrivate::Cmd_DrawVectorPath: {
351 debug << "ExCmd_DrawVectorPath: size: " << cmd.size
352// << ", hints:" << d->ints[cmd.offset2+cmd.size]
353 << "pts/elms:" << cmd.offset << cmd.offset2;
354 break; }
355
356 case QPaintBufferPrivate::Cmd_StrokeVectorPath: {
357 QPen pen = qVariantValue<QPen>(d_ptr->variants.at(cmd.extra));
358 debug << "ExCmd_StrokeVectorPath: size: " << cmd.size
359// << ", hints:" << d->ints[cmd.offset2+cmd.size]
360 << "pts/elms:" << cmd.offset << cmd.offset2 << pen;
361 break; }
362
363 case QPaintBufferPrivate::Cmd_FillVectorPath: {
364 QBrush brush = qVariantValue<QBrush>(d_ptr->variants.at(cmd.extra));
365 debug << "ExCmd_FillVectorPath: size: " << cmd.size
366// << ", hints:" << d->ints[cmd.offset2+cmd.size]
367 << "pts/elms:" << cmd.offset << cmd.offset2 << brush;
368 break; }
369
370 case QPaintBufferPrivate::Cmd_FillRectBrush: {
371 QBrush brush = qVariantValue<QBrush>(d_ptr->variants.at(cmd.extra));
372 QRectF *rect = (QRectF *)(d_ptr->floats.constData() + cmd.offset);
373 debug << "ExCmd_FillRectBrush, offset: " << cmd.offset << " rect: " << *rect << " brush: " << brush;
374 break; }
375
376 case QPaintBufferPrivate::Cmd_FillRectColor: {
377 QColor color = qVariantValue<QColor>(d_ptr->variants.at(cmd.extra));
378 QRectF *rect = (QRectF *)(d_ptr->floats.constData() + cmd.offset);
379 debug << "ExCmd_FillRectBrush, offset: " << cmd.offset << " rect: " << *rect << " color: " << color;
380 break; }
381
382 case QPaintBufferPrivate::Cmd_DrawPolygonF: {
383 debug << "ExCmd_DrawPolygonF, offset: " << cmd.offset << " size: " << cmd.size
384 << " mode: " << cmd.extra
385 << d_ptr->floats.at(cmd.offset)
386 << d_ptr->floats.at(cmd.offset+1);
387 break; }
388
389 case QPaintBufferPrivate::Cmd_DrawPolygonI: {
390 debug << "ExCmd_DrawPolygonI, offset: " << cmd.offset << " size: " << cmd.size
391 << " mode: " << cmd.extra
392 << d_ptr->ints.at(cmd.offset)
393 << d_ptr->ints.at(cmd.offset+1);
394 break; }
395
396 case QPaintBufferPrivate::Cmd_DrawEllipseF: {
397 debug << "ExCmd_DrawEllipseF, offset: " << cmd.offset;
398 break; }
399
400 case QPaintBufferPrivate::Cmd_DrawLineF: {
401 debug << "ExCmd_DrawLineF, offset: " << cmd.offset << " size: " << cmd.size;
402 break; }
403
404 case QPaintBufferPrivate::Cmd_DrawLineI: {
405 debug << "ExCmd_DrawLineI, offset: " << cmd.offset << " size: " << cmd.size;
406 break; }
407
408 case QPaintBufferPrivate::Cmd_DrawPointsF: {
409 debug << "ExCmd_DrawPointsF, offset: " << cmd.offset << " size: " << cmd.size;
410 break; }
411
412 case QPaintBufferPrivate::Cmd_DrawPointsI: {
413 debug << "ExCmd_DrawPointsI, offset: " << cmd.offset << " size: " << cmd.size;
414 break; }
415
416 case QPaintBufferPrivate::Cmd_DrawPolylineF: {
417 debug << "ExCmd_DrawPolylineF, offset: " << cmd.offset << " size: " << cmd.size;
418 break; }
419
420 case QPaintBufferPrivate::Cmd_DrawPolylineI: {
421 debug << "ExCmd_DrawPolylineI, offset: " << cmd.offset << " size: " << cmd.size;
422 break; }
423
424 case QPaintBufferPrivate::Cmd_DrawRectF: {
425 debug << "ExCmd_DrawRectF, offset: " << cmd.offset << " size: " << cmd.size;
426 break; }
427
428 case QPaintBufferPrivate::Cmd_DrawRectI: {
429 debug << "ExCmd_DrawRectI, offset: " << cmd.offset << " size: " << cmd.size;
430 break; }
431
432 case QPaintBufferPrivate::Cmd_SetClipEnabled: {
433 bool clipEnabled = d_ptr->variants.at(cmd.offset).toBool();
434 debug << "ExCmd_SetClipEnabled:" << clipEnabled;
435 break; }
436
437 case QPaintBufferPrivate::Cmd_ClipVectorPath: {
438 QVectorPathCmd path(d_ptr, cmd);
439 debug << "ExCmd_ClipVectorPath:" << path().elementCount();
440 break; }
441
442 case QPaintBufferPrivate::Cmd_ClipRect: {
443 QRect rect(QPoint(d_ptr->ints.at(cmd.offset), d_ptr->ints.at(cmd.offset + 1)),
444 QPoint(d_ptr->ints.at(cmd.offset + 2), d_ptr->ints.at(cmd.offset + 3)));
445 debug << "ExCmd_ClipRect:" << rect << cmd.extra;
446 break; }
447
448 case QPaintBufferPrivate::Cmd_ClipRegion: {
449 QRegion region(d_ptr->variants.at(cmd.offset).value<QRegion>());
450 debug << "ExCmd_ClipRegion:" << region.boundingRect() << cmd.extra;
451 break; }
452
453 case QPaintBufferPrivate::Cmd_SetPen: {
454 QPen pen = qVariantValue<QPen>(d_ptr->variants.at(cmd.offset));
455 debug << "Cmd_SetPen: " << pen;
456 break; }
457
458 case QPaintBufferPrivate::Cmd_SetTransform: {
459 QTransform xform = qVariantValue<QTransform>(d_ptr->variants.at(cmd.offset));
460 debug << "Cmd_SetTransform, offset: " << cmd.offset << xform;
461 break; }
462
463 case QPaintBufferPrivate::Cmd_SetRenderHints: {
464 debug << "Cmd_SetRenderHints, hints: " << cmd.extra;
465 break; }
466
467 case QPaintBufferPrivate::Cmd_SetBackgroundMode: {
468 debug << "Cmd_SetBackgroundMode: " << cmd.extra;
469 break; }
470
471 case QPaintBufferPrivate::Cmd_DrawConvexPolygonF: {
472 debug << "Cmd_DrawConvexPolygonF, offset: " << cmd.offset << " size: " << cmd.size;
473 break; }
474
475 case QPaintBufferPrivate::Cmd_DrawConvexPolygonI: {
476 debug << "Cmd_DrawConvexPolygonI, offset: " << cmd.offset << " size: " << cmd.size;
477 break; }
478
479 case QPaintBufferPrivate::Cmd_DrawEllipseI: {
480 debug << "Cmd_DrawEllipseI, offset: " << cmd.offset;
481 break; }
482
483 case QPaintBufferPrivate::Cmd_DrawPixmapRect: {
484 QPixmap pm(d_ptr->variants.at(cmd.offset).value<QPixmap>());
485 QRectF r(d_ptr->floats.at(cmd.extra), d_ptr->floats.at(cmd.extra+1),
486 d_ptr->floats.at(cmd.extra+2), d_ptr->floats.at(cmd.extra+3));
487
488 QRectF sr(d_ptr->floats.at(cmd.extra+4), d_ptr->floats.at(cmd.extra+5),
489 d_ptr->floats.at(cmd.extra+6), d_ptr->floats.at(cmd.extra+7));
490 debug << "Cmd_DrawPixmapRect:" << r << sr << pm.size();
491 break; }
492
493 case QPaintBufferPrivate::Cmd_DrawPixmapPos: {
494 QPixmap pm(d_ptr->variants.at(cmd.offset).value<QPixmap>());
495 QPointF pos(d_ptr->floats.at(cmd.extra), d_ptr->floats.at(cmd.extra+1));
496 debug << "Cmd_DrawPixmapPos:" << pos << pm.size();
497 break; }
498
499 case QPaintBufferPrivate::Cmd_DrawTiledPixmap: {
500 QPixmap pm(d_ptr->variants.at(cmd.offset).value<QPixmap>());
501 QRectF r(d_ptr->floats.at(cmd.extra), d_ptr->floats.at(cmd.extra+1),
502 d_ptr->floats.at(cmd.extra+2), d_ptr->floats.at(cmd.extra+3));
503
504 QPointF offset(d_ptr->floats.at(cmd.extra+4), d_ptr->floats.at(cmd.extra+5));
505 debug << "Cmd_DrawTiledPixmap:" << r << offset << pm.size();
506 break; }
507
508 case QPaintBufferPrivate::Cmd_DrawImageRect: {
509 QImage image(d_ptr->variants.at(cmd.offset).value<QImage>());
510 QRectF r(d_ptr->floats.at(cmd.extra), d_ptr->floats.at(cmd.extra+1),
511 d_ptr->floats.at(cmd.extra+2), d_ptr->floats.at(cmd.extra+3));
512 QRectF sr(d_ptr->floats.at(cmd.extra+4), d_ptr->floats.at(cmd.extra+5),
513 d_ptr->floats.at(cmd.extra+6), d_ptr->floats.at(cmd.extra+7));
514 debug << "Cmd_DrawImageRect:" << r << sr << image.size();
515 break; }
516
517 case QPaintBufferPrivate::Cmd_DrawImagePos: {
518 QImage image(d_ptr->variants.at(cmd.offset).value<QImage>());
519 QPointF pos(d_ptr->floats.at(cmd.extra), d_ptr->floats.at(cmd.extra+1));
520 debug << "Cmd_DrawImagePos:" << pos << image.size();
521 break; }
522
523 case QPaintBufferPrivate::Cmd_DrawText: {
524 QPointF pos(d_ptr->floats.at(cmd.extra), d_ptr->floats.at(cmd.extra+1));
525 QList<QVariant> variants(d_ptr->variants.at(cmd.offset).value<QList<QVariant> >());
526
527 QFont font(variants.at(0).value<QFont>());
528 QString text(variants.at(1).value<QString>());
529
530 debug << "Cmd_DrawText:" << pos << text << font.family();
531 break; }
532
533 case QPaintBufferPrivate::Cmd_DrawTextItem: {
534 QPointF pos(d_ptr->floats.at(cmd.extra), d_ptr->floats.at(cmd.extra+1));
535 QTextItemIntCopy *tiCopy = reinterpret_cast<QTextItemIntCopy *>(qVariantValue<void *>(d_ptr->variants.at(cmd.offset)));
536 QTextItemInt &ti = (*tiCopy)();
537 QString text(ti.text());
538
539 QFont font(ti.font());
540 font.setUnderline(false);
541 font.setStrikeOut(false);
542 font.setOverline(false);
543
544 const QTextItemInt &si = static_cast<const QTextItemInt &>(ti);
545 qreal justificationWidth = 0;
546 if (si.justified)
547 justificationWidth = si.width.toReal();
548
549 debug << "Cmd_DrawTextItem:" << pos << " " << text;
550 break; }
551 case QPaintBufferPrivate::Cmd_SystemStateChanged: {
552 QRegion systemClip(d_ptr->variants.at(cmd.offset).value<QRegion>());
553
554 debug << "Cmd_SystemStateChanged:" << systemClip;
555 break; }
556 case QPaintBufferPrivate::Cmd_Translate: {
557 QPointF delta(d_ptr->floats.at(cmd.extra), d_ptr->floats.at(cmd.extra+1));
558 debug << "Cmd_Translate:" << delta;
559 break; }
560 case QPaintBufferPrivate::Cmd_DrawStaticText: {
561 debug << "Cmd_DrawStaticText";
562 break; }
563 }
564
565 return desc;
566}
567#endif
568
569QRectF QPaintBuffer::boundingRect() const
570{
571 return d_ptr->boundingRect;
572}
573
574void QPaintBuffer::setBoundingRect(const QRectF &rect)
575{
576 d_ptr->boundingRect = rect;
577 d_ptr->calculateBoundingRect = false;
578}
579
580
581class QPaintBufferEnginePrivate : public QPaintEngineExPrivate
582{
583 Q_DECLARE_PUBLIC(QPaintBufferEngine)
584public:
585 void systemStateChanged() {
586 Q_Q(QPaintBufferEngine);
587 q->buffer->addCommand(QPaintBufferPrivate::Cmd_SystemStateChanged, QVariant(systemClip));
588 }
589
590 QTransform last;
591};
592
593
594/************************************************************************
595 *
596 * QPaintBufferEngine
597 *
598 ************************************************************************/
599
600QPaintBufferEngine::QPaintBufferEngine(QPaintBufferPrivate *b)
601 : QPaintEngineEx(*(new QPaintBufferEnginePrivate))
602 , buffer(b)
603 , m_begin_detected(false)
604 , m_save_detected(false)
605 , m_stream_raw_text_items(false)
606{
607}
608
609bool QPaintBufferEngine::begin(QPaintDevice *)
610{
611 Q_D(QPaintBufferEngine);
612 painter()->save();
613 d->systemStateChanged();
614 return true;
615}
616
617bool QPaintBufferEngine::end()
618{
619 painter()->restore();
620 m_created_state = 0;
621 return true;
622}
623
624QPainterState *QPaintBufferEngine::createState(QPainterState *orig) const
625{
626#ifdef QPAINTBUFFER_DEBUG_DRAW
627 qDebug() << "QPaintBufferEngine: createState, orig=" << orig << ", current=" << state();
628#endif
629
630 Q_ASSERT(!m_begin_detected);
631 Q_ASSERT(!m_save_detected);
632
633 if (orig == 0) {
634 m_begin_detected = true;
635 return new QPainterState();
636 } else {
637 m_save_detected = true;
638 return new QPainterState(orig);
639 }
640}
641
642void QPaintBufferEngine::clip(const QVectorPath &path, Qt::ClipOperation op)
643{
644#ifdef QPAINTBUFFER_DEBUG_DRAW
645 qDebug() << "QPaintBufferEngine: clip vpath:" << path.elementCount() << "op:" << op;
646#endif
647 QPaintBufferCommand *cmd =
648 buffer->addCommand(QPaintBufferPrivate::Cmd_ClipVectorPath, path);
649 cmd->extra = op;
650}
651
652void QPaintBufferEngine::clip(const QRect &rect, Qt::ClipOperation op)
653{
654#ifdef QPAINTBUFFER_DEBUG_DRAW
655 qDebug() << "QPaintBufferEngine: clip rect:" << rect << "op:" << op;
656#endif
657 QPaintBufferCommand *cmd =
658 buffer->addCommand(QPaintBufferPrivate::Cmd_ClipRect, (int *) &rect, 4, 1);
659 cmd->extra = op;
660}
661
662void QPaintBufferEngine::clip(const QRegion &region, Qt::ClipOperation op)
663{
664#ifdef QPAINTBUFFER_DEBUG_DRAW
665 qDebug() << "QPaintBufferEngine: clip region br:" << region.boundingRect() << "op:" << op;
666#endif
667 QPaintBufferCommand *cmd =
668 buffer->addCommand(QPaintBufferPrivate::Cmd_ClipRegion, QVariant(region));
669 cmd->extra = op;
670}
671
672void QPaintBufferEngine::clip(const QPainterPath &path, Qt::ClipOperation op)
673{
674 // ### TODO
675// QPaintBufferCommand *cmd =
676// buffer->addCommand(QPaintBufferPrivate::Cmd_ClipPath, QVariant(path));
677// cmd->extra = op;
678 QPaintEngineEx::clip(path, op);
679}
680
681void QPaintBufferEngine::clipEnabledChanged()
682{
683#ifdef QPAINTBUFFER_DEBUG_DRAW
684 qDebug() << "QPaintBufferEngine: clip enable change" << state()->clipEnabled;
685#endif
686
687 buffer->addCommand(QPaintBufferPrivate::Cmd_SetClipEnabled, state()->clipEnabled);
688}
689
690void QPaintBufferEngine::penChanged()
691{
692 const QPen &pen = state()->pen;
693
694 if (!buffer->commands.isEmpty()
695 && buffer->commands.last().id == QPaintBufferPrivate::Cmd_SetPen) {
696#ifdef QPAINTBUFFER_DEBUG_DRAW
697 qDebug() << "QPaintBufferEngine: penChanged (compressed)" << state()->pen;
698#endif
699 buffer->variants[buffer->commands.last().offset] = pen;
700 return;
701 }
702
703 if (buffer->calculateBoundingRect) {
704 if (pen.style() == Qt::NoPen) {
705 buffer->penWidthAdjustment = 0;
706 } else {
707 qreal penWidth = (pen.widthF() == 0) ? 1 : pen.widthF();
708 QPointF transformedWidth(penWidth, penWidth);
709 if (!pen.isCosmetic())
710 transformedWidth = painter()->transform().map(transformedWidth);
711 buffer->penWidthAdjustment = transformedWidth.x() / 2.0;
712 }
713 }
714#ifdef QPAINTBUFFER_DEBUG_DRAW
715 qDebug() << "QPaintBufferEngine: penChanged" << state()->pen;
716#endif
717 buffer->addCommand(QPaintBufferPrivate::Cmd_SetPen, pen);
718}
719
720void QPaintBufferEngine::brushChanged()
721{
722 const QBrush &brush = state()->brush;
723
724 if (!buffer->commands.isEmpty()
725 && buffer->commands.last().id == QPaintBufferPrivate::Cmd_SetBrush) {
726#ifdef QPAINTBUFFER_DEBUG_DRAW
727 qDebug() << "QPaintBufferEngine: brushChanged (compressed)" << state()->brush;
728#endif
729 buffer->variants[buffer->commands.last().offset] = brush;
730 return;
731 }
732
733#ifdef QPAINTBUFFER_DEBUG_DRAW
734 qDebug() << "QPaintBufferEngine: brushChanged" << state()->brush;
735#endif
736 buffer->addCommand(QPaintBufferPrivate::Cmd_SetBrush, brush);
737}
738
739void QPaintBufferEngine::brushOriginChanged()
740{
741#ifdef QPAINTBUFFER_DEBUG_DRAW
742 qDebug() << "QPaintBufferEngine: brush origin changed" << state()->brushOrigin;
743#endif
744 buffer->addCommand(QPaintBufferPrivate::Cmd_SetBrushOrigin, state()->brushOrigin);
745}
746
747void QPaintBufferEngine::opacityChanged()
748{
749#ifdef QPAINTBUFFER_DEBUG_DRAW
750 qDebug() << "QPaintBufferEngine: opacity changed" << state()->opacity;
751#endif
752 buffer->addCommand(QPaintBufferPrivate::Cmd_SetOpacity, state()->opacity);
753}
754
755void QPaintBufferEngine::compositionModeChanged()
756{
757#ifdef QPAINTBUFFER_DEBUG_DRAW
758 qDebug() << "QPaintBufferEngine: composition mode" << state()->composition_mode;
759#endif
760 QPaintBufferCommand *cmd =
761 buffer->addCommand(QPaintBufferPrivate::Cmd_SetCompositionMode);
762 cmd->extra = state()->composition_mode;
763}
764
765void QPaintBufferEngine::renderHintsChanged()
766{
767#ifdef QPAINTBUFFER_DEBUG_DRAW
768 qDebug() << "QPaintBufferEngine: render hints changed" << state()->renderHints;
769#endif
770 QPaintBufferCommand *cmd =
771 buffer->addCommand(QPaintBufferPrivate::Cmd_SetRenderHints);
772 cmd->extra = state()->renderHints;
773}
774
775void QPaintBufferEngine::transformChanged()
776{
777 Q_D(QPaintBufferEngine);
778 const QTransform &transform = state()->matrix;
779
780 QTransform delta;
781
782 bool invertible = false;
783 if (transform.type() <= QTransform::TxScale && transform.type() == d->last.type())
784 delta = transform * d->last.inverted(&invertible);
785
786 d->last = transform;
787
788 if (invertible && delta.type() == QTransform::TxNone)
789 return;
790
791 if (invertible && delta.type() == QTransform::TxTranslate) {
792#ifdef QPAINTBUFFER_DEBUG_DRAW
793 qDebug() << "QPaintBufferEngine: transformChanged (translate only) " << state()->matrix;
794#endif
795 QPaintBufferCommand *cmd =
796 buffer->addCommand(QPaintBufferPrivate::Cmd_Translate);
797
798 qreal data[] = { delta.dx(), delta.dy() };
799 cmd->extra = buffer->addData((qreal *) data, 2);
800 return;
801 }
802
803 // ### accumulate, like in QBrush case...
804 if (!buffer->commands.isEmpty()
805 && buffer->commands.last().id == QPaintBufferPrivate::Cmd_SetTransform) {
806#ifdef QPAINTBUFFER_DEBUG_DRAW
807 qDebug() << "QPaintBufferEngine: transformChanged (compressing) " << state()->matrix;
808#endif
809 buffer->variants[buffer->commands.last().offset] = state()->matrix;
810 return;
811 }
812
813#ifdef QPAINTBUFFER_DEBUG_DRAW
814 qDebug() << "QPaintBufferEngine: transformChanged:" << state()->matrix;
815#endif
816 buffer->addCommand(QPaintBufferPrivate::Cmd_SetTransform, state()->matrix);
817}
818
819void QPaintBufferEngine::backgroundModeChanged()
820{
821#ifdef QPAINTBUFFER_DEBUG_DRAW
822 qDebug() << "QPaintEngineBuffer: background mode changed" << state()->bgMode;
823#endif
824 QPaintBufferCommand *cmd = buffer->addCommand(QPaintBufferPrivate::Cmd_SetBackgroundMode);
825 cmd->extra = state()->bgMode;
826}
827
828void QPaintBufferEngine::draw(const QVectorPath &path)
829{
830#ifdef QPAINTBUFFER_DEBUG_DRAW
831 qDebug() << "QPaintBufferEngine: draw vpath:" << path.elementCount();
832#endif
833
834 bool hasBrush = qbrush_style(state()->brush) != Qt::NoBrush;
835 bool hasPen = qpen_style(state()->pen) != Qt::NoPen
836 && qbrush_style(qpen_brush(state()->pen)) != Qt::NoBrush;
837
838 if (hasPen || hasBrush)
839 buffer->addCommand(QPaintBufferPrivate::Cmd_DrawVectorPath, path);
840#ifdef QPAINTBUFFER_DEBUG_DRAW
841 else
842 qDebug() << " - no pen or brush active, discarded...\n";
843#endif
844
845// if (buffer->calculateBoundingRect) {
846// QRealRect r = path.controlPointRect();
847// buffer->updateBoundingRect(QRectF(r.x1, r.y1, r.x2 - r.x1, r.y2 - r.y1));
848// }
849}
850
851void QPaintBufferEngine::fill(const QVectorPath &path, const QBrush &brush)
852{
853#ifdef QPAINTBUFFER_DEBUG_DRAW
854 qDebug() << "QPaintBufferEngine: fill vpath:" << path.elementCount() << brush;
855#endif
856 QPaintBufferCommand *cmd =
857 buffer->addCommand(QPaintBufferPrivate::Cmd_FillVectorPath, path);
858 cmd->extra = buffer->addData(QVariant(brush));
859// if (buffer->calculateBoundingRect) {
860// QRealRect r = path.controlPointRect();
861// buffer->updateBoundingRect(QRectF(r.x1, r.y1, r.x2 - r.x1, r.y2 - r.y1));
862// }
863}
864
865void QPaintBufferEngine::stroke(const QVectorPath &path, const QPen &pen)
866{
867#ifdef QPAINTBUFFER_DEBUG_DRAW
868 qDebug() << "QPaintBufferEngine: stroke vpath:" << path.elementCount() << pen;
869#endif
870 QPaintBufferCommand *cmd =
871 buffer->addCommand(QPaintBufferPrivate::Cmd_StrokeVectorPath, path);
872 cmd->extra = buffer->addData(QVariant(pen));
873// if (buffer->calculateBoundingRect) {
874// QRealRect r = path.controlPointRect();
875// buffer->updateBoundingRect(QRectF(r.x1, r.y1, r.x2 - r.x1, r.y2 - r.y1));
876// }
877}
878
879void QPaintBufferEngine::fillRect(const QRectF &rect, const QBrush &brush)
880{
881#ifdef QPAINTBUFFER_DEBUG_DRAW
882 qDebug() << "QPaintBufferEngine: fillRect brush:" << rect << brush;
883#endif
884 QPaintBufferCommand *cmd =
885 buffer->addCommand(QPaintBufferPrivate::Cmd_FillRectBrush, (qreal *) &rect, 4, 1);
886 cmd->extra = buffer->addData(brush);
887 if (buffer->calculateBoundingRect)
888 buffer->updateBoundingRect(rect);
889}
890
891void QPaintBufferEngine::fillRect(const QRectF &rect, const QColor &color)
892{
893#ifdef QPAINTBUFFER_DEBUG_DRAW
894 qDebug() << "QPaintBufferEngine: fillRect color:" << rect << color;
895#endif
896 QPaintBufferCommand *cmd =
897 buffer->addCommand(QPaintBufferPrivate::Cmd_FillRectColor, (qreal *) &rect, 4, 1);
898 cmd->extra = buffer->addData(color);
899 if (buffer->calculateBoundingRect)
900 buffer->updateBoundingRect(rect);
901}
902
903void QPaintBufferEngine::drawRects(const QRect *rects, int rectCount)
904{
905#ifdef QPAINTBUFFER_DEBUG_DRAW
906 qDebug() << "QPaintBufferEngine: drawRectsI:" << rectCount;
907#endif
908 QPaintBufferCommand *cmd =
909 buffer->addCommand(QPaintBufferPrivate::Cmd_DrawRectI, (int *) rects, 4 * rectCount, rectCount);
910 cmd->extra = rectCount;
911
912 if (buffer->calculateBoundingRect) {
913 if (rectCount == 1) {
914 buffer->updateBoundingRect(rects[0]);
915 } else {
916 int min_x = rects[0].left();
917 int min_y = rects[0].top();
918 int max_x = rects[0].left() + rects[0].width();
919 int max_y = rects[0].top() + rects[0].height();
920 for (int i=1; i< rectCount; ++i) {
921 if (rects[i].left() < min_x)
922 min_x = rects[i].left();
923 if (rects[i].top() < min_y)
924 min_y = rects[i].top();
925 if (rects[i].right() > max_x)
926 max_x = rects[i].left() + rects[i].width();
927 if (rects[i].bottom() > max_y)
928 max_y = rects[i].top() + rects[i].height();
929
930 }
931 buffer->updateBoundingRect(QRectF(min_x, min_y, max_x - min_x, max_y - min_y));
932 }
933 }
934}
935
936void QPaintBufferEngine::drawRects(const QRectF *rects, int rectCount)
937{
938#ifdef QPAINTBUFFER_DEBUG_DRAW
939 qDebug() << "QPaintBufferEngine: drawRectsF:" << rectCount;
940#endif
941 QPaintBufferCommand *cmd =
942 buffer->addCommand(QPaintBufferPrivate::Cmd_DrawRectF, (qreal *) rects, 4 * rectCount, rectCount);
943 cmd->extra = rectCount;
944
945 if (buffer->calculateBoundingRect) {
946 if (rectCount == 1) {
947 buffer->updateBoundingRect(rects[0]);
948 } else {
949 qreal min_x = rects[0].left();
950 qreal min_y = rects[0].top();
951 qreal max_x = rects[0].right();
952 qreal max_y = rects[0].bottom();
953 for (int i=1; i< rectCount; ++i) {
954 if (rects[i].left() < min_x)
955 min_x = rects[i].left();
956 if (rects[i].top() < min_y)
957 min_y = rects[i].top();
958 if (rects[i].right() > max_x)
959 max_x = rects[i].right();
960 if (rects[i].bottom() > max_y)
961 max_y = rects[i].bottom();
962
963 }
964 buffer->updateBoundingRect(QRectF(min_x, min_y, max_x - min_x, max_y - min_y));
965 }
966 }
967}
968
969void QPaintBufferEngine::drawLines(const QLine *lines, int lineCount)
970{
971#ifdef QPAINTBUFFER_DEBUG_DRAW
972 qDebug() << "QPaintBufferEngine: drawLinesI:" << lineCount;
973#endif
974 QPaintBufferCommand *cmd =
975 buffer->addCommand(QPaintBufferPrivate::Cmd_DrawLineI, (int *) lines, 4 * lineCount, lineCount);
976 cmd->extra = lineCount;
977
978 if (buffer->calculateBoundingRect) {
979 int min_x = lines[0].p1().x();
980 int min_y = lines[0].p1().y();
981 int max_x = lines[0].p2().x();
982 int max_y = lines[0].p2().y();
983 if (min_x > max_x)
984 qSwap(min_x, max_x);
985 if (min_y > max_y)
986 qSwap(min_y, max_y);
987 for (int i=1; i < lineCount; ++i) {
988 int p1_x = lines[i].p1().x();
989 int p1_y = lines[i].p1().y();
990 int p2_x = lines[i].p2().x();
991 int p2_y = lines[i].p2().y();
992 if (p1_x > p2_x) {
993 min_x = qMin(p2_x, min_x);
994 max_x = qMax(p1_x, max_x);
995 } else {
996 min_x = qMin(p1_x, min_x);
997 max_x = qMax(p2_x, max_x);
998 }
999 if (p1_y > p2_y) {
1000 min_y = qMin(p2_y, min_y);
1001 max_y = qMax(p1_y, max_y);
1002 } else {
1003 min_y = qMin(p1_y, min_y);
1004 max_y = qMax(p2_y, max_y);
1005 }
1006 }
1007 buffer->updateBoundingRect(QRectF(min_x, min_y, max_x - min_x, max_y - min_y));
1008 }
1009}
1010
1011void QPaintBufferEngine::drawLines(const QLineF *lines, int lineCount)
1012{
1013#ifdef QPAINTBUFFER_DEBUG_DRAW
1014 qDebug() << "QPaintBufferEngine: drawLinesF:" << lineCount;
1015#endif
1016 QPaintBufferCommand *cmd =
1017 buffer->addCommand(QPaintBufferPrivate::Cmd_DrawLineF, (qreal *) lines, 4 * lineCount, lineCount);
1018 cmd->extra = lineCount;
1019
1020 if (buffer->calculateBoundingRect) {
1021 qreal min_x = lines[0].p1().x();
1022 qreal min_y = lines[0].p1().y();
1023 qreal max_x = lines[0].p2().x();
1024 qreal max_y = lines[0].p2().y();
1025 if (min_x > max_x)
1026 qSwap(min_x, max_x);
1027 if (min_y > max_y)
1028 qSwap(min_y, max_y);
1029 for (int i=1; i < lineCount; ++i) {
1030 qreal p1_x = lines[i].p1().x();
1031 qreal p1_y = lines[i].p1().y();
1032 qreal p2_x = lines[i].p2().x();
1033 qreal p2_y = lines[i].p2().y();
1034 if (p1_x > p2_x) {
1035 min_x = qMin(p2_x, min_x);
1036 max_x = qMax(p1_x, max_x);
1037 } else {
1038 min_x = qMin(p1_x, min_x);
1039 max_x = qMax(p2_x, max_x);
1040 }
1041 if (p1_y > p2_y) {
1042 min_y = qMin(p2_y, min_y);
1043 max_y = qMax(p1_y, max_y);
1044 } else {
1045 min_y = qMin(p1_y, min_y);
1046 max_y = qMax(p2_y, max_y);
1047 }
1048 }
1049 buffer->updateBoundingRect(QRectF(min_x, min_y, max_x - min_x, max_y - min_y));
1050 }
1051}
1052
1053void QPaintBufferEngine::drawEllipse(const QRectF &r)
1054{
1055#ifdef QPAINTBUFFER_DEBUG_DRAW
1056 qDebug() << "QPaintBufferEngine: drawEllipseF:" << r;
1057#endif
1058 buffer->addCommand(QPaintBufferPrivate::Cmd_DrawEllipseF, (qreal *) &r, 4, 1);
1059 if (buffer->calculateBoundingRect)
1060 buffer->updateBoundingRect(r);
1061}
1062
1063void QPaintBufferEngine::drawEllipse(const QRect &r)
1064{
1065#ifdef QPAINTBUFFER_DEBUG_DRAW
1066 qDebug() << "QPaintBufferEngine: drawEllipseI:" << r;
1067#endif
1068 buffer->addCommand(QPaintBufferPrivate::Cmd_DrawEllipseI, (int *) &r, 4, 1);
1069 if (buffer->calculateBoundingRect)
1070 buffer->updateBoundingRect(r);
1071}
1072
1073void QPaintBufferEngine::drawPath(const QPainterPath &path)
1074{
1075// #ifdef QPAINTBUFFER_DEBUG_DRAW
1076// qDebug() << "QPaintBufferEngine: drawPath: element count:" << path.elementCount();
1077// #endif
1078// // ### Path -> QVariant
1079// // buffer->addCommand(QPaintBufferPrivate::Cmd_DrawPath, QVariant(path));
1080 QPaintEngineEx::drawPath(path);
1081
1082// if (buffer->calculateBoundingRect)
1083// buffer->updateBoundingRect(path.boundingRect());
1084}
1085
1086void QPaintBufferEngine::drawPoints(const QPoint *points, int pointCount)
1087{
1088#ifdef QPAINTBUFFER_DEBUG_DRAW
1089 qDebug() << "QPaintBufferEngine: drawPointsI: " << pointCount;
1090#endif
1091 buffer->addCommand(QPaintBufferPrivate::Cmd_DrawPointsI, (int *) points, 2 * pointCount, pointCount);
1092
1093 if (buffer->calculateBoundingRect) {
1094 int min_x = points[0].x();
1095 int min_y = points[0].y();
1096 int max_x = points[0].x()+1;
1097 int max_y = points[0].y()+1;
1098 for (int i=1; i<pointCount; ++i) {
1099 int x = points[i].x();
1100 int y = points[i].y();
1101 min_x = qMin(min_x, x);
1102 min_y = qMin(min_y, y);
1103 max_x = qMax(max_x, x+1);
1104 max_y = qMax(max_y, y+1);
1105 }
1106 buffer->updateBoundingRect(QRectF(min_x, min_y, max_x - min_x, max_y - min_y));
1107 }
1108}
1109
1110void QPaintBufferEngine::drawPoints(const QPointF *points, int pointCount)
1111{
1112#ifdef QPAINTBUFFER_DEBUG_DRAW
1113 qDebug() << "QPaintBufferEngine: drawPointsF: " << pointCount;
1114#endif
1115 buffer->addCommand(QPaintBufferPrivate::Cmd_DrawPointsF, (qreal *) points, 2 * pointCount, pointCount);
1116
1117 if (buffer->calculateBoundingRect) {
1118 qreal min_x = points[0].x();
1119 qreal min_y = points[0].y();
1120 qreal max_x = points[0].x()+1;
1121 qreal max_y = points[0].y()+1;
1122 for (int i=1; i<pointCount; ++i) {
1123 qreal x = points[i].x();
1124 qreal y = points[i].y();
1125 min_x = qMin(min_x, x);
1126 min_y = qMin(min_y, y);
1127 max_x = qMax(max_x, x+1);
1128 max_y = qMax(max_y, y+1);
1129 }
1130 buffer->updateBoundingRect(QRectF(min_x, min_y, max_x - min_x, max_y - min_y));
1131 }
1132}
1133
1134void QPaintBufferEngine::drawPolygon(const QPoint *pts, int count, PolygonDrawMode mode)
1135{
1136#ifdef QPAINTBUFFER_DEBUG_DRAW
1137 qDebug() << "QPaintBufferEngine: drawPolygonI: size:" << count << ", mode:" << mode;
1138#endif
1139 if (mode == QPaintEngine::OddEvenMode || mode == QPaintEngine::WindingMode) {
1140 QPaintBufferCommand *cmd = buffer->addCommand(QPaintBufferPrivate::Cmd_DrawPolygonI,
1141 (int *) pts, 2 * count, count);
1142 cmd->extra = mode;
1143 } else if (mode == QPaintEngine::PolylineMode) {
1144 buffer->addCommand(QPaintBufferPrivate::Cmd_DrawPolylineI, (int *) pts, 2 * count, count);
1145 } else {
1146 buffer->addCommand(QPaintBufferPrivate::Cmd_DrawConvexPolygonI, (int *) pts, 2 * count, count);
1147 }
1148
1149 if (buffer->calculateBoundingRect) {
1150 int min_x = pts[0].x();
1151 int min_y = pts[0].y();
1152 int max_x = pts[0].x();
1153 int max_y = pts[0].y();
1154 for (int i=1; i<count; ++i) {
1155 int x = pts[i].x();
1156 int y = pts[i].y();
1157 min_x = qMin(min_x, x);
1158 min_y = qMin(min_y, y);
1159 max_x = qMax(max_x, x);
1160 max_y = qMax(max_y, y);
1161 }
1162 buffer->updateBoundingRect(QRectF(min_x, min_y, max_x - min_x, max_y - min_y));
1163 }
1164}
1165
1166void QPaintBufferEngine::drawPolygon(const QPointF *pts, int count, PolygonDrawMode mode)
1167{
1168#ifdef QPAINTBUFFER_DEBUG_DRAW
1169 qDebug() << "QPaintBufferEngine: drawPolygonF: size:" << count << ", mode:" << mode;
1170#endif
1171 if (mode == QPaintEngine::OddEvenMode || mode == QPaintEngine::WindingMode) {
1172 QPaintBufferCommand *cmd = buffer->addCommand(QPaintBufferPrivate::Cmd_DrawPolygonF,
1173 (qreal *) pts, 2 * count, count);
1174 cmd->extra = mode;
1175 } else if (mode == QPaintEngine::PolylineMode) {
1176 buffer->addCommand(QPaintBufferPrivate::Cmd_DrawPolylineF, (qreal *) pts, 2 * count, count);
1177 } else {
1178 buffer->addCommand(QPaintBufferPrivate::Cmd_DrawConvexPolygonF, (qreal *) pts, 2 * count, count);
1179 }
1180
1181 if (buffer->calculateBoundingRect) {
1182 qreal min_x = pts[0].x();
1183 qreal min_y = pts[0].y();
1184 qreal max_x = pts[0].x();
1185 qreal max_y = pts[0].y();
1186 for (int i=1; i<count; ++i) {
1187 qreal x = pts[i].x();
1188 qreal y = pts[i].y();
1189 min_x = qMin(min_x, x);
1190 min_y = qMin(min_y, y);
1191 max_x = qMax(max_x, x);
1192 max_y = qMax(max_y, y);
1193 }
1194 buffer->updateBoundingRect(QRectF(min_x, min_y, max_x - min_x, max_y - min_y));
1195 }
1196}
1197
1198void QPaintBufferEngine::drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr)
1199{
1200#ifdef QPAINTBUFFER_DEBUG_DRAW
1201 qDebug() << "QPaintBufferEngine: drawPixmap: src/dest rects " << r << sr;
1202#endif
1203 QPaintBufferCommand *cmd =
1204 buffer->addCommand(QPaintBufferPrivate::Cmd_DrawPixmapRect, QVariant(pm));
1205 cmd->extra = buffer->addData((qreal *) &r, 4);
1206 buffer->addData((qreal *) &sr, 4);
1207 if (buffer->calculateBoundingRect)
1208 buffer->updateBoundingRect(r);
1209}
1210
1211void QPaintBufferEngine::drawPixmap(const QPointF &pos, const QPixmap &pm)
1212{
1213#ifdef QPAINTBUFFER_DEBUG_DRAW
1214 qDebug() << "QPaintBufferEngine: drawPixmap: pos:" << pos;
1215#endif
1216 QPaintBufferCommand *cmd =
1217 buffer->addCommand(QPaintBufferPrivate::Cmd_DrawPixmapPos, QVariant(pm));
1218 cmd->extra = buffer->addData((qreal *) &pos, 2);
1219 if (buffer->calculateBoundingRect)
1220 buffer->updateBoundingRect(QRectF(pos, pm.size()));
1221}
1222
1223static inline QImage qpaintbuffer_storable_image(const QImage &src)
1224{
1225 QImageData *d = const_cast<QImage &>(src).data_ptr();
1226 return d->own_data ? src : src.copy();
1227}
1228
1229void QPaintBufferEngine::drawImage(const QRectF &r, const QImage &image, const QRectF &sr,
1230 Qt::ImageConversionFlags /*flags */)
1231{
1232#ifdef QPAINTBUFFER_DEBUG_DRAW
1233 qDebug() << "QPaintBufferEngine: drawImage: src/dest rects " << r << sr;
1234#endif
1235 QPaintBufferCommand *cmd =
1236 buffer->addCommand(QPaintBufferPrivate::Cmd_DrawImageRect,
1237 QVariant(qpaintbuffer_storable_image(image)));
1238 cmd->extra = buffer->addData((qreal *) &r, 4);
1239 buffer->addData((qreal *) &sr, 4);
1240 // ### flags...
1241 if (buffer->calculateBoundingRect)
1242 buffer->updateBoundingRect(r);
1243}
1244
1245void QPaintBufferEngine::drawImage(const QPointF &pos, const QImage &image)
1246{
1247#ifdef QPAINTBUFFER_DEBUG_DRAW
1248 qDebug() << "QPaintBufferEngine: drawImage: pos:" << pos;
1249#endif
1250 QPaintBufferCommand *cmd =
1251 buffer->addCommand(QPaintBufferPrivate::Cmd_DrawImagePos,
1252 QVariant(qpaintbuffer_storable_image(image)));
1253 cmd->extra = buffer->addData((qreal *) &pos, 2);
1254 if (buffer->calculateBoundingRect)
1255 buffer->updateBoundingRect(QRectF(pos, image.size()));
1256}
1257
1258void QPaintBufferEngine::drawTiledPixmap(const QRectF &r, const QPixmap &pm, const QPointF &s)
1259{
1260#ifdef QPAINTBUFFER_DEBUG_DRAW
1261 qDebug() << "QPaintBufferEngine: drawTiledPixmap: src rect/offset:" << r << s;
1262#endif
1263 QPaintBufferCommand *cmd =
1264 buffer->addCommand(QPaintBufferPrivate::Cmd_DrawTiledPixmap, QVariant(pm));
1265 cmd->extra = buffer->addData((qreal *) &r, 4);
1266 buffer->addData((qreal *) &s, 2);
1267 if (buffer->calculateBoundingRect)
1268 buffer->updateBoundingRect(r);
1269}
1270
1271void QPaintBufferEngine::drawStaticTextItem(QStaticTextItem *staticTextItem)
1272{
1273 QVariantList variants;
1274
1275 variants << QVariant(staticTextItem->font);
1276 for (int i=0; i<staticTextItem->numGlyphs; ++i) {
1277 variants.append(staticTextItem->glyphs[i]);
1278 variants.append(staticTextItem->glyphPositions[i].toPointF());
1279 }
1280
1281 buffer->addCommand(QPaintBufferPrivate::Cmd_DrawStaticText, QVariant(variants));
1282}
1283
1284void QPaintBufferEngine::drawTextItem(const QPointF &pos, const QTextItem &ti)
1285{
1286#ifdef QPAINTBUFFER_DEBUG_DRAW
1287 qDebug() << "QPaintBufferEngine: drawTextItem: pos:" << pos << ti.text();
1288#endif
1289 if (m_stream_raw_text_items) {
1290 QPaintBufferCommand *cmd = buffer->addCommand(QPaintBufferPrivate::Cmd_DrawTextItem, qVariantFromValue<void *>(new QTextItemIntCopy(ti)));
1291
1292 QFont font(ti.font());
1293 font.setUnderline(false);
1294 font.setStrikeOut(false);
1295 font.setOverline(false);
1296
1297 const QTextItemInt &si = static_cast<const QTextItemInt &>(ti);
1298 qreal justificationWidth = 0;
1299 if (si.justified)
1300 justificationWidth = si.width.toReal();
1301 int renderFlags = ti.renderFlags();
1302 qreal scaleFactor = font.d->dpi/qreal(qt_defaultDpiY());
1303
1304 buffer->addData(QVariant(font));
1305 cmd->extra = buffer->addData((qreal *) &pos, 2);
1306 buffer->addData((qreal *) &justificationWidth, 1);
1307 buffer->addData((qreal *) &scaleFactor, 1);
1308 cmd->offset2 = buffer->addData((int *) &renderFlags, 1);
1309 } else {
1310 QList<QVariant> variants;
1311 variants << QVariant(ti.font()) << QVariant(ti.text());
1312 QPaintBufferCommand *cmd = buffer->addCommand(QPaintBufferPrivate::Cmd_DrawText, QVariant(variants));
1313 cmd->extra = buffer->addData((qreal *) &pos, 2);
1314 }
1315
1316 if (buffer->calculateBoundingRect)
1317 buffer->updateBoundingRect(QRectF(pos, QSize(ti.width(), ti.ascent() + ti.descent() + 1)));
1318}
1319
1320
1321void QPaintBufferEngine::setState(QPainterState *s)
1322{
1323 Q_D(QPaintBufferEngine);
1324 if (m_begin_detected) {
1325#ifdef QPAINTBUFFER_DEBUG_DRAW
1326 qDebug() << "QPaintBufferEngine: setState: begin, ignoring.";
1327#endif
1328 m_begin_detected = false;
1329 } else if (m_save_detected) {
1330#ifdef QPAINTBUFFER_DEBUG_DRAW
1331 qDebug() << "QPaintBufferEngine: setState: save.";
1332#endif
1333 m_save_detected = false;
1334 buffer->addCommand(QPaintBufferPrivate::Cmd_Save);
1335 } else {
1336#ifdef QPAINTBUFFER_DEBUG_DRAW
1337 qDebug() << "QPaintBufferEngine: setState: restore.";
1338#endif
1339 buffer->addCommand(QPaintBufferPrivate::Cmd_Restore);
1340 }
1341
1342 d->last = s->matrix;
1343
1344 QPaintEngineEx::setState(s);
1345}
1346
1347
1348/***********************************************************************
1349 *
1350 * class QPaintBufferPlayback_Painter
1351 *
1352 */
1353
1354// QFakeDevice is used to create fonts with a custom DPI
1355//
1356class QFakeDevice : public QPaintDevice
1357{
1358public:
1359 QFakeDevice() { dpi_x = qt_defaultDpiX(); dpi_y = qt_defaultDpiY(); }
1360 void setDpiX(int dpi) { dpi_x = dpi; }
1361 void setDpiY(int dpi) { dpi_y = dpi; }
1362 QPaintEngine *paintEngine() const { return 0; }
1363 int metric(PaintDeviceMetric m) const
1364 {
1365 switch(m) {
1366 case PdmPhysicalDpiX:
1367 case PdmDpiX:
1368 return dpi_x;
1369 case PdmPhysicalDpiY:
1370 case PdmDpiY:
1371 return dpi_y;
1372 default:
1373 return QPaintDevice::metric(m);
1374 }
1375 }
1376
1377private:
1378 int dpi_x;
1379 int dpi_y;
1380};
1381
1382
1383void QPainterReplayer::setupTransform(QPainter *_painter)
1384{
1385 painter = _painter;
1386 m_world_matrix = painter->transform();
1387 m_world_matrix.scale(qreal(painter->device()->logicalDpiX()) / qreal(qt_defaultDpiX()),
1388 qreal(painter->device()->logicalDpiY()) / qreal(qt_defaultDpiY()));
1389 painter->setTransform(m_world_matrix);
1390}
1391
1392void QPainterReplayer::processCommands(const QPaintBuffer &buffer, QPainter *p, int begin, int end)
1393{
1394 d = buffer.d_ptr;
1395 painter = p;
1396
1397 for (int cmdIndex = begin; cmdIndex < end; ++cmdIndex) {
1398 const QPaintBufferCommand &cmd = d->commands.at(cmdIndex);
1399 process(cmd);
1400 }
1401}
1402
1403void QPaintBuffer::beginNewFrame()
1404{
1405 if (!d_ptr->commands.isEmpty())
1406 d_ptr->frames << d_ptr->commands.size();
1407}
1408
1409int QPaintBuffer::numFrames() const
1410{
1411 return d_ptr->frames.size() + 1;
1412}
1413
1414void QPainterReplayer::process(const QPaintBufferCommand &cmd)
1415{
1416 switch (cmd.id) {
1417 case QPaintBufferPrivate::Cmd_Save: {
1418#ifdef QPAINTBUFFER_DEBUG_DRAW
1419 qDebug() << " -> Cmd_Save";
1420#endif
1421 painter->save();
1422 break; }
1423
1424 case QPaintBufferPrivate::Cmd_Restore: {
1425#ifdef QPAINTBUFFER_DEBUG_DRAW
1426 qDebug() << " -> Cmd_Restore";
1427#endif
1428 painter->restore();
1429 break; }
1430
1431 case QPaintBufferPrivate::Cmd_SetPen: {
1432 QPen pen = qVariantValue<QPen>(d->variants.at(cmd.offset));
1433#ifdef QPAINTBUFFER_DEBUG_DRAW
1434 qDebug() << " -> Cmd_SetPen: " << pen;
1435#endif
1436 painter->setPen(pen);
1437 break; }
1438
1439 case QPaintBufferPrivate::Cmd_SetBrush: {
1440 QBrush brush = qVariantValue<QBrush>(d->variants.at(cmd.offset));
1441#ifdef QPAINTBUFFER_DEBUG_DRAW
1442 qDebug() << " -> Cmd_SetBrush: " << brush;
1443#endif
1444 painter->setBrush(brush);
1445 break; }
1446
1447 case QPaintBufferPrivate::Cmd_SetBrushOrigin: {
1448#ifdef QPAINTBUFFER_DEBUG_DRAW
1449 qDebug() << " -> Cmd_SetBrushOrigin: " << d->variants.at(cmd.offset).toPointF();
1450#endif
1451 painter->setBrushOrigin(d->variants.at(cmd.offset).toPointF());
1452 break; }
1453
1454 case QPaintBufferPrivate::Cmd_SetTransform: {
1455 QTransform xform = qVariantValue<QTransform>(d->variants.at(cmd.offset));
1456#ifdef QPAINTBUFFER_DEBUG_DRAW
1457 qDebug() << " -> Cmd_SetTransform, offset: " << cmd.offset << xform;
1458#endif
1459 painter->setTransform(xform * m_world_matrix);
1460 break; }
1461
1462 case QPaintBufferPrivate::Cmd_Translate: {
1463 QPointF delta(d->floats.at(cmd.extra), d->floats.at(cmd.extra+1));
1464#ifdef QPAINTBUFFER_DEBUG_DRAW
1465 qDebug() << " -> Cmd_Translate, offset: " << cmd.offset << delta;
1466#endif
1467 painter->translate(delta.x(), delta.y());
1468 return;
1469 }
1470
1471 case QPaintBufferPrivate::Cmd_SetCompositionMode: {
1472 QPainter::CompositionMode mode = (QPainter::CompositionMode) cmd.extra;
1473#ifdef QPAINTBUFFER_DEBUG_DRAW
1474 qDebug() << " -> Cmd_SetCompositionMode, mode: " << mode;
1475#endif
1476 painter->setCompositionMode(mode);
1477 break; }
1478
1479 case QPaintBufferPrivate::Cmd_SetRenderHints: {
1480#ifdef QPAINTBUFFER_DEBUG_DRAW
1481 qDebug() << " -> Cmd_SetRenderHints, hints: " << cmd.extra;
1482#endif
1483 QPainter::RenderHints ph = painter->renderHints();
1484 QPainter::RenderHints nh = (QPainter::RenderHints) cmd.extra;
1485 QPainter::RenderHints xored = ph ^ nh;
1486 if (xored & QPainter::Antialiasing)
1487 painter->setRenderHint(QPainter::Antialiasing, nh & QPainter::Antialiasing);
1488 if (xored & QPainter::HighQualityAntialiasing)
1489 painter->setRenderHint(QPainter::HighQualityAntialiasing, nh & QPainter::HighQualityAntialiasing);
1490 if (xored & QPainter::TextAntialiasing)
1491 painter->setRenderHint(QPainter::TextAntialiasing, nh & QPainter::TextAntialiasing);
1492 if (xored & QPainter::SmoothPixmapTransform)
1493 painter->setRenderHint(QPainter::SmoothPixmapTransform, nh & QPainter::SmoothPixmapTransform);
1494 if (xored & QPainter::NonCosmeticDefaultPen)
1495 painter->setRenderHint(QPainter::NonCosmeticDefaultPen, nh & QPainter::NonCosmeticDefaultPen);
1496 break; }
1497
1498 case QPaintBufferPrivate::Cmd_SetOpacity: {
1499#ifdef QPAINTBUFFER_DEBUG_DRAW
1500 qDebug() << " -> Cmd_SetOpacity: " << d->variants.at(cmd.offset).toDouble();
1501#endif
1502 painter->setOpacity(d->variants.at(cmd.offset).toDouble());
1503 break; }
1504
1505 case QPaintBufferPrivate::Cmd_SetBackgroundMode: {
1506#ifdef QPAINTBUFFER_DEBUG_DRAW
1507 qDebug() << " -> Cmd_SetBackgroundMode: " << cmd.extra;
1508#endif
1509 painter->setBackgroundMode((Qt::BGMode)cmd.extra);
1510 break; }
1511
1512 case QPaintBufferPrivate::Cmd_DrawVectorPath: {
1513#ifdef QPAINTBUFFER_DEBUG_DRAW
1514 qDebug() << " -> Cmd_DrawVectorPath: size: " << cmd.size
1515// << ", hints:" << d->ints[cmd.offset2+cmd.size]
1516 << "pts/elms:" << cmd.offset << cmd.offset2;
1517#endif
1518 QVectorPathCmd path(d, cmd);
1519 painter->drawPath(path().convertToPainterPath());
1520 break; }
1521
1522 case QPaintBufferPrivate::Cmd_StrokeVectorPath: {
1523 QPen pen = qVariantValue<QPen>(d->variants.at(cmd.extra));
1524#ifdef QPAINTBUFFER_DEBUG_DRAW
1525 qDebug() << " -> Cmd_StrokeVectorPath: size: " << cmd.size
1526// << ", hints:" << d->ints[cmd.offset2+cmd.size]
1527 << "pts/elms:" << cmd.offset << cmd.offset2;
1528#endif
1529 QVectorPathCmd path(d, cmd);
1530 painter->strokePath(path().convertToPainterPath(), pen);
1531 break; }
1532
1533 case QPaintBufferPrivate::Cmd_FillVectorPath: {
1534 QBrush brush = qVariantValue<QBrush>(d->variants.at(cmd.extra));
1535#ifdef QPAINTBUFFER_DEBUG_DRAW
1536 qDebug() << " -> Cmd_FillVectorPath: size: " << cmd.size
1537// << ", hints:" << d->ints[cmd.offset2+cmd.size]
1538 << "pts/elms:" << cmd.offset << cmd.offset2 << brush;
1539#endif
1540 QVectorPathCmd path(d, cmd);
1541 painter->fillPath(path().convertToPainterPath(), brush);
1542 break; }
1543
1544 case QPaintBufferPrivate::Cmd_DrawPolygonF: {
1545#ifdef QPAINTBUFFER_DEBUG_DRAW
1546 qDebug() << " -> Cmd_DrawPolygonF, offset: " << cmd.offset << " size: " << cmd.size
1547 << " mode: " << cmd.extra
1548 << d->floats.at(cmd.offset)
1549 << d->floats.at(cmd.offset+1);
1550#endif
1551 Qt::FillRule fill = (QPaintEngine::PolygonDrawMode) cmd.extra == QPaintEngine::OddEvenMode
1552 ? Qt::OddEvenFill : Qt::WindingFill;
1553 painter->drawPolygon((QPointF *) (d->floats.constData() + cmd.offset), cmd.size, fill);
1554 break; }
1555
1556 case QPaintBufferPrivate::Cmd_DrawPolygonI: {
1557#ifdef QPAINTBUFFER_DEBUG_DRAW
1558 qDebug() << " -> Cmd_DrawPolygonI, offset: " << cmd.offset << " size: " << cmd.size
1559 << " mode: " << cmd.extra
1560 << d->ints.at(cmd.offset)
1561 << d->ints.at(cmd.offset+1);
1562#endif
1563 Qt::FillRule fill = (QPaintEngine::PolygonDrawMode) cmd.extra == QPaintEngine::OddEvenMode
1564 ? Qt::OddEvenFill : Qt::WindingFill;
1565 painter->drawPolygon((QPoint *) (d->ints.constData() + cmd.offset), cmd.size, fill);
1566 break; }
1567
1568 case QPaintBufferPrivate::Cmd_DrawPolylineF: {
1569#ifdef QPAINTBUFFER_DEBUG_DRAW
1570 qDebug() << " -> Cmd_DrawPolylineF, offset: " << cmd.offset << " size: " << cmd.size;
1571#endif
1572 painter->drawPolyline((QPointF *) (d->floats.constData() + cmd.offset), cmd.size);
1573 break; }
1574
1575 case QPaintBufferPrivate::Cmd_DrawPolylineI: {
1576#ifdef QPAINTBUFFER_DEBUG_DRAW
1577 qDebug() << " -> Cmd_DrawPolylineI, offset: " << cmd.offset << " size: " << cmd.size;
1578#endif
1579 painter->drawPolyline((QPoint *) (d->ints.constData() + cmd.offset), cmd.size);
1580 break; }
1581
1582 case QPaintBufferPrivate::Cmd_DrawConvexPolygonF: {
1583#ifdef QPAINTBUFFER_DEBUG_DRAW
1584 qDebug() << " -> Cmd_DrawConvexPolygonF, offset: " << cmd.offset << " size: " << cmd.size;
1585#endif
1586 painter->drawConvexPolygon((QPointF *) (d->floats.constData() + cmd.offset), cmd.size);
1587 break; }
1588
1589 case QPaintBufferPrivate::Cmd_DrawConvexPolygonI: {
1590#ifdef QPAINTBUFFER_DEBUG_DRAW
1591 qDebug() << " -> Cmd_DrawConvexPolygonI, offset: " << cmd.offset << " size: " << cmd.size;
1592#endif
1593 painter->drawConvexPolygon((QPoint *) (d->ints.constData() + cmd.offset), cmd.size);
1594 break; }
1595
1596 case QPaintBufferPrivate::Cmd_DrawEllipseF: {
1597#ifdef QPAINTBUFFER_DEBUG_DRAW
1598 qDebug() << " -> Cmd_DrawEllipseF, offset: " << cmd.offset;
1599#endif
1600 painter->drawEllipse(*(QRectF *)(d->floats.constData() + cmd.offset));
1601 break; }
1602
1603 case QPaintBufferPrivate::Cmd_DrawEllipseI: {
1604#ifdef QPAINTBUFFER_DEBUG_DRAW
1605 qDebug() << " -> Cmd_DrawEllipseI, offset: " << cmd.offset;
1606#endif
1607 painter->drawEllipse(*(QRect *)(d->ints.constData() + cmd.offset));
1608 break; }
1609
1610 case QPaintBufferPrivate::Cmd_DrawLineF: {
1611#ifdef QPAINTBUFFER_DEBUG_DRAW
1612 qDebug() << " -> Cmd_DrawLineF, offset: " << cmd.offset << " size: " << cmd.size;
1613#endif
1614 painter->drawLines((QLineF *)(d->floats.constData() + cmd.offset), cmd.size);
1615 break; }
1616
1617 case QPaintBufferPrivate::Cmd_DrawLineI: {
1618#ifdef QPAINTBUFFER_DEBUG_DRAW
1619 qDebug() << " -> Cmd_DrawLineI, offset: " << cmd.offset << " size: " << cmd.size;
1620#endif
1621 painter->drawLines((QLine *)(d->ints.constData() + cmd.offset), cmd.size);
1622 break; }
1623
1624 case QPaintBufferPrivate::Cmd_DrawPointsF: {
1625#ifdef QPAINTBUFFER_DEBUG_DRAW
1626 qDebug() << " -> Cmd_DrawPointsF, offset: " << cmd.offset << " size: " << cmd.size;
1627#endif
1628 painter->drawPoints((QPointF *)(d->floats.constData() + cmd.offset), cmd.size);
1629 break; }
1630
1631 case QPaintBufferPrivate::Cmd_DrawPointsI: {
1632#ifdef QPAINTBUFFER_DEBUG_DRAW
1633 qDebug() << " -> Cmd_DrawPointsI, offset: " << cmd.offset << " size: " << cmd.size;
1634#endif
1635 painter->drawPoints((QPoint *)(d->ints.constData() + cmd.offset), cmd.size);
1636 break; }
1637
1638 case QPaintBufferPrivate::Cmd_DrawPixmapRect: {
1639 QPixmap pm(d->variants.at(cmd.offset).value<QPixmap>());
1640 QRectF r(d->floats.at(cmd.extra), d->floats.at(cmd.extra+1),
1641 d->floats.at(cmd.extra+2), d->floats.at(cmd.extra+3));
1642
1643 QRectF sr(d->floats.at(cmd.extra+4), d->floats.at(cmd.extra+5),
1644 d->floats.at(cmd.extra+6), d->floats.at(cmd.extra+7));
1645#ifdef QPAINTBUFFER_DEBUG_DRAW
1646 qDebug() << " -> Cmd_DrawPixmapRect:" << r << sr;
1647#endif
1648 painter->drawPixmap(r, pm, sr);
1649 break; }
1650
1651 case QPaintBufferPrivate::Cmd_DrawPixmapPos: {
1652 QPixmap pm(d->variants.at(cmd.offset).value<QPixmap>());
1653 QPointF pos(d->floats.at(cmd.extra), d->floats.at(cmd.extra+1));
1654#ifdef QPAINTBUFFER_DEBUG_DRAW
1655 qDebug() << " -> Cmd_DrawPixmapPos:" << pos;
1656#endif
1657 painter->drawPixmap(pos, pm);
1658 break; }
1659
1660 case QPaintBufferPrivate::Cmd_DrawTiledPixmap: {
1661 QPixmap pm(d->variants.at(cmd.offset).value<QPixmap>());
1662 QRectF r(d->floats.at(cmd.extra), d->floats.at(cmd.extra+1),
1663 d->floats.at(cmd.extra+2), d->floats.at(cmd.extra+3));
1664
1665 QPointF offset(d->floats.at(cmd.extra+4), d->floats.at(cmd.extra+5));
1666#ifdef QPAINTBUFFER_DEBUG_DRAW
1667 qDebug() << " -> Cmd_DrawTiledPixmap:" << r << offset;
1668#endif
1669 painter->drawTiledPixmap(r, pm, offset);
1670 break; }
1671
1672 case QPaintBufferPrivate::Cmd_DrawImageRect: {
1673 QImage image(d->variants.at(cmd.offset).value<QImage>());
1674 QRectF r(d->floats.at(cmd.extra), d->floats.at(cmd.extra+1),
1675 d->floats.at(cmd.extra+2), d->floats.at(cmd.extra+3));
1676 QRectF sr(d->floats.at(cmd.extra+4), d->floats.at(cmd.extra+5),
1677 d->floats.at(cmd.extra+6), d->floats.at(cmd.extra+7));
1678#ifdef QPAINTBUFFER_DEBUG_DRAW
1679 qDebug() << " -> Cmd_DrawImageRect:" << r << sr;
1680#endif
1681 painter->drawImage(r, image, sr);
1682 break; }
1683
1684 case QPaintBufferPrivate::Cmd_DrawImagePos: {
1685 QImage image(d->variants.at(cmd.offset).value<QImage>());
1686 QPointF pos(d->floats.at(cmd.extra), d->floats.at(cmd.extra+1));
1687#ifdef QPAINTBUFFER_DEBUG_DRAW
1688 qDebug() << " -> Cmd_DrawImagePos:" << pos;
1689#endif
1690 painter->drawImage(pos, image);
1691 break; }
1692
1693 case QPaintBufferPrivate::Cmd_DrawRectF: {
1694#ifdef QPAINTBUFFER_DEBUG_DRAW
1695 qDebug() << " -> Cmd_DrawRectF, offset: " << cmd.offset;
1696#endif
1697 painter->drawRects((QRectF *)(d->floats.constData() + cmd.offset), cmd.size);
1698 break; }
1699
1700 case QPaintBufferPrivate::Cmd_DrawRectI: {
1701#ifdef QPAINTBUFFER_DEBUG_DRAW
1702 qDebug() << " -> Cmd_DrawRectI, offset: " << cmd.offset;
1703#endif
1704 painter->drawRects((QRect *)(d->ints.constData() + cmd.offset), cmd.size);
1705 break; }
1706
1707 case QPaintBufferPrivate::Cmd_FillRectBrush: {
1708 QBrush brush = qVariantValue<QBrush>(d->variants.at(cmd.extra));
1709 QRectF *rect = (QRectF *)(d->floats.constData() + cmd.offset);
1710#ifdef QPAINTBUFFER_DEBUG_DRAW
1711 qDebug() << " -> Cmd_FillRectBrush, offset: " << cmd.offset << " rect: " << *rect << " brush: " << brush;
1712#endif
1713 painter->fillRect(*rect, brush);
1714 break; }
1715
1716 case QPaintBufferPrivate::Cmd_FillRectColor: {
1717 QColor color = qVariantValue<QColor>(d->variants.at(cmd.extra));
1718 QRectF *rect = (QRectF *)(d->floats.constData() + cmd.offset);
1719#ifdef QPAINTBUFFER_DEBUG_DRAW
1720 qDebug() << " -> Cmd_FillRectBrush, offset: " << cmd.offset << " rect: " << *rect << " color: " << color;
1721#endif
1722 painter->fillRect(*rect, color);
1723 break; }
1724
1725 case QPaintBufferPrivate::Cmd_SetClipEnabled: {
1726 bool clipEnabled = d->variants.at(cmd.offset).toBool();
1727#ifdef QPAINTBUFFER_DEBUG_DRAW
1728 qDebug() << " -> Cmd_SetClipEnabled:" << clipEnabled;
1729#endif
1730 painter->setClipping(clipEnabled);
1731 break; }
1732
1733 case QPaintBufferPrivate::Cmd_ClipVectorPath: {
1734 QVectorPathCmd path(d, cmd);
1735#ifdef QPAINTBUFFER_DEBUG_DRAW
1736 qDebug() << " -> Cmd_ClipVectorPath:" << path().elementCount();
1737#endif
1738 painter->setClipPath(path().convertToPainterPath(), Qt::ClipOperation(cmd.extra));
1739 break; }
1740
1741
1742 case QPaintBufferPrivate::Cmd_ClipRect: {
1743 QRect rect(QPoint(d->ints.at(cmd.offset), d->ints.at(cmd.offset + 1)),
1744 QPoint(d->ints.at(cmd.offset + 2), d->ints.at(cmd.offset + 3)));
1745#ifdef QPAINTBUFFER_DEBUG_DRAW
1746 qDebug() << " -> Cmd_ClipRect:" << rect << cmd.extra;
1747#endif
1748 painter->setClipRect(rect, Qt::ClipOperation(cmd.extra));
1749 break; }
1750
1751 case QPaintBufferPrivate::Cmd_ClipRegion: {
1752 QRegion region(d->variants.at(cmd.offset).value<QRegion>());
1753#ifdef QPAINTBUFFER_DEBUG_DRAW
1754 qDebug() << " -> Cmd_ClipRegion:" << region.boundingRect() << cmd.extra;
1755#endif
1756 painter->setClipRegion(region, Qt::ClipOperation(cmd.extra));
1757 break; }
1758
1759 case QPaintBufferPrivate::Cmd_DrawStaticText: {
1760
1761 QVariantList variants(d->variants.at(cmd.offset).value<QVariantList>());
1762
1763 QFont font = variants.at(0).value<QFont>();
1764
1765 QVector<quint32> glyphs;
1766 QVector<QPointF> positions;
1767
1768 for (int i=0; i<(variants.size() - 1) / 2; ++i) {
1769 glyphs.append(variants.at(i*2 + 1).toUInt());
1770 positions.append(variants.at(i*2 + 2).toPointF());
1771 }
1772
1773 painter->setFont(font);
1774
1775 qt_draw_glyphs(painter, glyphs.constData(), positions.constData(), glyphs.size());
1776
1777 break;
1778 }
1779
1780 case QPaintBufferPrivate::Cmd_DrawText: {
1781 QPointF pos(d->floats.at(cmd.extra), d->floats.at(cmd.extra+1));
1782 QList<QVariant> variants(d->variants.at(cmd.offset).value<QList<QVariant> >());
1783
1784 QFont font(variants.at(0).value<QFont>());
1785 QString text(variants.at(1).value<QString>());
1786
1787 painter->setFont(font);
1788 painter->drawText(pos, text);
1789 break; }
1790
1791 case QPaintBufferPrivate::Cmd_DrawTextItem: {
1792 QPointF pos(d->floats.at(cmd.extra), d->floats.at(cmd.extra+1));
1793 QTextItemIntCopy *tiCopy = reinterpret_cast<QTextItemIntCopy *>(qVariantValue<void *>(d->variants.at(cmd.offset)));
1794 QTextItemInt &ti = (*tiCopy)();
1795 QString text(ti.text());
1796
1797 QFont font(ti.font());
1798 font.setUnderline(false);
1799 font.setStrikeOut(false);
1800 font.setOverline(false);
1801
1802 const QTextItemInt &si = static_cast<const QTextItemInt &>(ti);
1803 qreal justificationWidth = 0;
1804 if (si.justified)
1805 justificationWidth = si.width.toReal();
1806 qreal scaleFactor = font.d->dpi/qreal(qt_defaultDpiY());
1807
1808#ifdef QPAINTBUFFER_DEBUG_DRAW
1809 qDebug() << " -> Cmd_DrawTextItem:" << pos << " " << text << " " << scaleFactor;
1810#endif
1811
1812 if (scaleFactor != 1.0) {
1813 QFont fnt(font);
1814 QFakeDevice fake;
1815 fake.setDpiX(qRound(scaleFactor*qt_defaultDpiX()));
1816 fake.setDpiY(qRound(scaleFactor*qt_defaultDpiY()));
1817 font = QFont(fnt, &fake);
1818 }
1819
1820 int flags = Qt::TextSingleLine | Qt::TextDontClip | Qt::TextForceLeftToRight;
1821 QSizeF size(1, 1);
1822 if (justificationWidth > 0) {
1823 size.setWidth(justificationWidth);
1824 flags |= Qt::TextJustificationForced;
1825 flags |= Qt::AlignJustify;
1826 }
1827
1828 QFontMetrics fm(font);
1829 QPointF pt(pos.x(), pos.y() - fm.ascent());
1830 qt_format_text(font, QRectF(pt, size), flags, /*opt*/0,
1831 text, /*brect=*/0, /*tabstops=*/0, /*...*/0, /*tabarraylen=*/0, painter);
1832 break; }
1833 case QPaintBufferPrivate::Cmd_SystemStateChanged: {
1834 QRegion systemClip(d->variants.at(cmd.offset).value<QRegion>());
1835
1836#ifdef QPAINTBUFFER_DEBUG_DRAW
1837 qDebug() << " -> Cmd_SystemStateChanged:" << systemClip;
1838#endif
1839
1840 painter->paintEngine()->setSystemClip(systemClip);
1841 painter->paintEngine()->d_ptr->systemStateChanged();
1842 break; }
1843 }
1844}
1845
1846void QPaintEngineExReplayer::process(const QPaintBufferCommand &cmd)
1847{
1848 Q_ASSERT(painter->paintEngine()->isExtended());
1849 QPaintEngineEx *xengine = static_cast<QPaintEngineEx *>(painter->paintEngine());
1850
1851 switch (cmd.id) {
1852 case QPaintBufferPrivate::Cmd_SetBrushOrigin: {
1853#ifdef QPAINTBUFFER_DEBUG_DRAW
1854 qDebug() << " -> ExCmd_SetBrushOrigin: " << d->variants.at(cmd.offset).toPointF();
1855#endif
1856 xengine->state()->brushOrigin = d->variants.at(cmd.offset).toPointF();
1857 xengine->brushOriginChanged();
1858 break; }
1859
1860 case QPaintBufferPrivate::Cmd_SetCompositionMode: {
1861 QPainter::CompositionMode mode = (QPainter::CompositionMode) cmd.extra;
1862#ifdef QPAINTBUFFER_DEBUG_DRAW
1863 qDebug() << " -> ExCmd_SetCompositionMode, mode: " << mode;
1864#endif
1865 xengine->state()->composition_mode = mode;
1866 xengine->compositionModeChanged();
1867 break; }
1868
1869 case QPaintBufferPrivate::Cmd_SetOpacity: {
1870#ifdef QPAINTBUFFER_DEBUG_DRAW
1871 qDebug() << " -> ExCmd_SetOpacity: " << d->variants.at(cmd.offset).toDouble();
1872#endif
1873 xengine->state()->opacity = d->variants.at(cmd.offset).toDouble();
1874 xengine->opacityChanged();
1875 break; }
1876
1877 case QPaintBufferPrivate::Cmd_DrawVectorPath: {
1878#ifdef QPAINTBUFFER_DEBUG_DRAW
1879 qDebug() << " -> ExCmd_DrawVectorPath: size: " << cmd.size
1880// << ", hints:" << d->ints[cmd.offset2+cmd.size]
1881 << "pts/elms:" << cmd.offset << cmd.offset2;
1882#endif
1883 QVectorPathCmd path(d, cmd);
1884 xengine->draw(path());
1885 break; }
1886
1887 case QPaintBufferPrivate::Cmd_StrokeVectorPath: {
1888 QPen pen = qVariantValue<QPen>(d->variants.at(cmd.extra));
1889#ifdef QPAINTBUFFER_DEBUG_DRAW
1890 qDebug() << " -> ExCmd_StrokeVectorPath: size: " << cmd.size
1891// << ", hints:" << d->ints[cmd.offset2+cmd.size]
1892 << "pts/elms:" << cmd.offset << cmd.offset2;
1893#endif
1894 QVectorPathCmd path(d, cmd);
1895 xengine->stroke(path(), pen);
1896 break; }
1897
1898 case QPaintBufferPrivate::Cmd_FillVectorPath: {
1899 QBrush brush = qVariantValue<QBrush>(d->variants.at(cmd.extra));
1900#ifdef QPAINTBUFFER_DEBUG_DRAW
1901 qDebug() << " -> ExCmd_FillVectorPath: size: " << cmd.size
1902// << ", hints:" << d->ints[cmd.offset2+cmd.size]
1903 << "pts/elms:" << cmd.offset << cmd.offset2 << brush;
1904#endif
1905 QVectorPathCmd path(d, cmd);
1906 xengine->fill(path(), brush);
1907 break; }
1908
1909 case QPaintBufferPrivate::Cmd_FillRectBrush: {
1910 QBrush brush = qVariantValue<QBrush>(d->variants.at(cmd.extra));
1911 QRectF *rect = (QRectF *)(d->floats.constData() + cmd.offset);
1912#ifdef QPAINTBUFFER_DEBUG_DRAW
1913 qDebug() << " -> ExCmd_FillRectBrush, offset: " << cmd.offset << " rect: " << *rect << " brush: " << brush;
1914#endif
1915 xengine->fillRect(*rect, brush);
1916 break; }
1917
1918 case QPaintBufferPrivate::Cmd_FillRectColor: {
1919 QColor color = qVariantValue<QColor>(d->variants.at(cmd.extra));
1920 QRectF *rect = (QRectF *)(d->floats.constData() + cmd.offset);
1921#ifdef QPAINTBUFFER_DEBUG_DRAW
1922 qDebug() << " -> ExCmd_FillRectBrush, offset: " << cmd.offset << " rect: " << *rect << " color: " << color;
1923#endif
1924 xengine->fillRect(*rect, color);
1925 break; }
1926
1927 case QPaintBufferPrivate::Cmd_DrawPolygonF: {
1928#ifdef QPAINTBUFFER_DEBUG_DRAW
1929 qDebug() << " -> ExCmd_DrawPolygonF, offset: " << cmd.offset << " size: " << cmd.size
1930 << " mode: " << cmd.extra
1931 << d->floats.at(cmd.offset)
1932 << d->floats.at(cmd.offset+1);
1933#endif
1934 xengine->drawPolygon((QPointF *) (d->floats.constData() + cmd.offset), cmd.size,
1935 (QPaintEngine::PolygonDrawMode) cmd.extra);
1936 break; }
1937
1938 case QPaintBufferPrivate::Cmd_DrawPolygonI: {
1939#ifdef QPAINTBUFFER_DEBUG_DRAW
1940 qDebug() << " -> ExCmd_DrawPolygonI, offset: " << cmd.offset << " size: " << cmd.size
1941 << " mode: " << cmd.extra
1942 << d->ints.at(cmd.offset)
1943 << d->ints.at(cmd.offset+1);
1944#endif
1945 xengine->drawPolygon((QPoint *) (d->ints.constData() + cmd.offset), cmd.size,
1946 (QPaintEngine::PolygonDrawMode) cmd.extra);
1947 break; }
1948
1949 case QPaintBufferPrivate::Cmd_DrawEllipseF: {
1950#ifdef QPAINTBUFFER_DEBUG_DRAW
1951 qDebug() << " -> ExCmd_DrawEllipseF, offset: " << cmd.offset;
1952#endif
1953 xengine->drawEllipse(*(QRectF *)(d->floats.constData() + cmd.offset));
1954 break; }
1955
1956 case QPaintBufferPrivate::Cmd_DrawEllipseI: {
1957#ifdef QPAINTBUFFER_DEBUG_DRAW
1958 qDebug() << " -> ExCmd_DrawEllipseI, offset: " << cmd.offset;
1959#endif
1960 xengine->drawEllipse(*(QRect *)(d->ints.constData() + cmd.offset));
1961 break; }
1962
1963 case QPaintBufferPrivate::Cmd_DrawLineF: {
1964#ifdef QPAINTBUFFER_DEBUG_DRAW
1965 qDebug() << " -> ExCmd_DrawLineF, offset: " << cmd.offset << " size: " << cmd.size;
1966#endif
1967 xengine->drawLines((QLineF *)(d->floats.constData() + cmd.offset), cmd.size);
1968 break; }
1969
1970 case QPaintBufferPrivate::Cmd_DrawLineI: {
1971#ifdef QPAINTBUFFER_DEBUG_DRAW
1972 qDebug() << " -> ExCmd_DrawLineI, offset: " << cmd.offset << " size: " << cmd.size;
1973#endif
1974 xengine->drawLines((QLine *)(d->ints.constData() + cmd.offset), cmd.size);
1975 break; }
1976
1977 case QPaintBufferPrivate::Cmd_DrawPointsF: {
1978#ifdef QPAINTBUFFER_DEBUG_DRAW
1979 qDebug() << " -> ExCmd_DrawPointsF, offset: " << cmd.offset << " size: " << cmd.size;
1980#endif
1981 xengine->drawPoints((QPointF *)(d->floats.constData() + cmd.offset), cmd.size);
1982 break; }
1983
1984 case QPaintBufferPrivate::Cmd_DrawPointsI: {
1985#ifdef QPAINTBUFFER_DEBUG_DRAW
1986 qDebug() << " -> ExCmd_DrawPointsI, offset: " << cmd.offset << " size: " << cmd.size;
1987#endif
1988 xengine->drawPoints((QPoint *)(d->ints.constData() + cmd.offset), cmd.size);
1989 break; }
1990
1991 case QPaintBufferPrivate::Cmd_DrawPolylineF: {
1992#ifdef QPAINTBUFFER_DEBUG_DRAW
1993 qDebug() << " -> ExCmd_DrawPolylineF, offset: " << cmd.offset << " size: " << cmd.size;
1994#endif
1995 xengine->drawPolygon((QPointF *) (d->floats.constData() + cmd.offset), cmd.size, QPaintEngine::PolylineMode);
1996 break; }
1997
1998 case QPaintBufferPrivate::Cmd_DrawPolylineI: {
1999#ifdef QPAINTBUFFER_DEBUG_DRAW
2000 qDebug() << " -> ExCmd_DrawPolylineI, offset: " << cmd.offset << " size: " << cmd.size;
2001#endif
2002 xengine->drawPolygon((QPoint *) (d->ints.constData() + cmd.offset), cmd.size, QPaintEngine::PolylineMode);
2003 break; }
2004
2005 case QPaintBufferPrivate::Cmd_DrawRectF: {
2006#ifdef QPAINTBUFFER_DEBUG_DRAW
2007 qDebug() << " -> ExCmd_DrawRectF, offset: " << cmd.offset << " size: " << cmd.size;
2008#endif
2009 xengine->drawRects((QRectF *) (d->floats.constData() + cmd.offset), cmd.size);
2010 break; }
2011
2012 case QPaintBufferPrivate::Cmd_DrawRectI: {
2013#ifdef QPAINTBUFFER_DEBUG_DRAW
2014 qDebug() << " -> ExCmd_DrawRectI, offset: " << cmd.offset << " size: " << cmd.size;
2015#endif
2016 xengine->drawRects((QRect *) (d->ints.constData() + cmd.offset), cmd.size);
2017 break; }
2018
2019 case QPaintBufferPrivate::Cmd_SetClipEnabled: {
2020 bool clipEnabled = d->variants.at(cmd.offset).toBool();
2021#ifdef QPAINTBUFFER_DEBUG_DRAW
2022 qDebug() << " -> ExCmd_SetClipEnabled:" << clipEnabled;
2023#endif
2024 xengine->state()->clipEnabled = clipEnabled;
2025 xengine->clipEnabledChanged();
2026 break; }
2027
2028 case QPaintBufferPrivate::Cmd_ClipVectorPath: {
2029 QVectorPathCmd path(d, cmd);
2030#ifdef QPAINTBUFFER_DEBUG_DRAW
2031 qDebug() << " -> ExCmd_ClipVectorPath:" << path().elementCount();
2032#endif
2033 xengine->clip(path(), Qt::ClipOperation(cmd.extra));
2034 break; }
2035
2036
2037 case QPaintBufferPrivate::Cmd_ClipRect: {
2038 QRect rect(QPoint(d->ints.at(cmd.offset), d->ints.at(cmd.offset + 1)),
2039 QPoint(d->ints.at(cmd.offset + 2), d->ints.at(cmd.offset + 3)));
2040#ifdef QPAINTBUFFER_DEBUG_DRAW
2041 qDebug() << " -> ExCmd_ClipRect:" << rect << cmd.extra;
2042#endif
2043 xengine->clip(rect, Qt::ClipOperation(cmd.extra));
2044 break; }
2045
2046 case QPaintBufferPrivate::Cmd_ClipRegion: {
2047 QRegion region(d->variants.at(cmd.offset).value<QRegion>());
2048#ifdef QPAINTBUFFER_DEBUG_DRAW
2049 qDebug() << " -> ExCmd_ClipRegion:" << region.boundingRect() << cmd.extra;
2050#endif
2051 xengine->clip(region, Qt::ClipOperation(cmd.extra));
2052 break; }
2053
2054 default:
2055 QPainterReplayer::process(cmd);
2056 break;
2057 }
2058}
2059
2060QPaintBufferResource::QPaintBufferResource(FreeFunc f, QObject *parent) : QObject(parent), free(f)
2061{
2062 connect(QPaintBufferSignalProxy::instance(), SIGNAL(aboutToDestroy(const QPaintBufferPrivate*)), this, SLOT(remove(const QPaintBufferPrivate*)));
2063}
2064
2065QPaintBufferResource::~QPaintBufferResource()
2066{
2067 for (Cache::iterator it = m_cache.begin(); it != m_cache.end(); ++it)
2068 free(it.value());
2069}
2070
2071void QPaintBufferResource::insert(const QPaintBufferPrivate *key, void *value)
2072{
2073 Cache::iterator it = m_cache.find(key);
2074 if (it != m_cache.end()) {
2075 free(it.value());
2076 it.value() = value;
2077 } else {
2078 m_cache.insert(key, value);
2079 }
2080}
2081
2082void *QPaintBufferResource::value(const QPaintBufferPrivate *key)
2083{
2084 Cache::iterator it = m_cache.find(key);
2085 if (it != m_cache.end())
2086 return it.value();
2087 return 0;
2088}
2089
2090void QPaintBufferResource::remove(const QPaintBufferPrivate *key)
2091{
2092 Cache::iterator it = m_cache.find(key);
2093 if (it != m_cache.end()) {
2094 free(it.value());
2095 m_cache.erase(it);
2096 }
2097}
2098
2099QDataStream &operator<<(QDataStream &stream, const QPaintBufferCommand &command)
2100{
2101 quint32 id = command.id;
2102 quint32 size = command.size;
2103 stream << id << size;
2104 stream << command.offset << command.offset2 << command.extra;
2105 return stream;
2106}
2107
2108QDataStream &operator>>(QDataStream &stream, QPaintBufferCommand &command)
2109{
2110 quint32 id;
2111 quint32 size;
2112 stream >> id >> size;
2113 stream >> command.offset >> command.offset2 >> command.extra;
2114 command.id = id;
2115 command.size = size;
2116 return stream;
2117}
2118
2119struct QPaintBufferCacheEntry
2120{
2121 QVariant::Type type;
2122 quint64 cacheKey;
2123};
2124
2125struct QPaintBufferCacheEntryV2
2126{
2127 enum Type {
2128 ImageKey,
2129 PixmapKey
2130 };
2131
2132 struct Flags {
2133 uint type : 8;
2134 uint key : 24;
2135 };
2136
2137 union {
2138 Flags flags;
2139 uint bits;
2140 };
2141};
2142
2143QT_END_NAMESPACE
2144Q_DECLARE_METATYPE(QPaintBufferCacheEntry)
2145Q_DECLARE_METATYPE(QPaintBufferCacheEntryV2)
2146QT_BEGIN_NAMESPACE
2147
2148QDataStream &operator<<(QDataStream &stream, const QPaintBufferCacheEntry &entry)
2149{
2150 return stream << entry.type << entry.cacheKey;
2151}
2152
2153QDataStream &operator>>(QDataStream &stream, QPaintBufferCacheEntry &entry)
2154{
2155 return stream >> entry.type >> entry.cacheKey;
2156}
2157
2158QDataStream &operator<<(QDataStream &stream, const QPaintBufferCacheEntryV2 &entry)
2159{
2160 return stream << entry.bits;
2161}
2162
2163QDataStream &operator>>(QDataStream &stream, QPaintBufferCacheEntryV2 &entry)
2164{
2165 return stream >> entry.bits;
2166}
2167
2168static int qRegisterPaintBufferMetaTypes()
2169{
2170 qRegisterMetaType<QPaintBufferCacheEntry>();
2171 qRegisterMetaTypeStreamOperators<QPaintBufferCacheEntry>("QPaintBufferCacheEntry");
2172 qRegisterMetaType<QPaintBufferCacheEntryV2>();
2173 qRegisterMetaTypeStreamOperators<QPaintBufferCacheEntryV2>("QPaintBufferCacheEntryV2");
2174
2175 return 0; // something
2176}
2177
2178Q_CONSTRUCTOR_FUNCTION(qRegisterPaintBufferMetaTypes)
2179
2180QDataStream &operator<<(QDataStream &stream, const QPaintBuffer &buffer)
2181{
2182 QHash<qint64, uint> pixmapKeys;
2183 QHash<qint64, uint> imageKeys;
2184
2185 QHash<qint64, QPixmap> pixmaps;
2186 QHash<qint64, QImage> images;
2187
2188 QVector<QVariant> variants = buffer.d_ptr->variants;
2189 for (int i = 0; i < variants.size(); ++i) {
2190 const QVariant &v = variants.at(i);
2191 if (v.type() == QVariant::Image) {
2192 const QImage image(v.value<QImage>());
2193
2194 QPaintBufferCacheEntryV2 entry;
2195 entry.flags.type = QPaintBufferCacheEntryV2::ImageKey;
2196
2197 QHash<qint64, uint>::iterator it = imageKeys.find(image.cacheKey());
2198 if (it != imageKeys.end()) {
2199 entry.flags.key = *it;
2200 } else {
2201 imageKeys[image.cacheKey()] = entry.flags.key = images.size();
2202 images[images.size()] = image;
2203 }
2204
2205 variants[i] = QVariant::fromValue(entry);
2206 } else if (v.type() == QVariant::Pixmap) {
2207 const QPixmap pixmap(v.value<QPixmap>());
2208
2209 QPaintBufferCacheEntryV2 entry;
2210 entry.flags.type = QPaintBufferCacheEntryV2::PixmapKey;
2211
2212 QHash<qint64, uint>::iterator it = pixmapKeys.find(pixmap.cacheKey());
2213 if (it != pixmapKeys.end()) {
2214 entry.flags.key = *it;
2215 } else {
2216 pixmapKeys[pixmap.cacheKey()] = entry.flags.key = pixmaps.size();
2217 pixmaps[pixmaps.size()] = pixmap;
2218 }
2219
2220 variants[i] = QVariant::fromValue(entry);
2221 }
2222 }
2223
2224 stream << pixmaps;
2225 stream << images;
2226
2227 stream << buffer.d_ptr->ints;
2228 stream << buffer.d_ptr->floats;
2229 stream << variants;
2230 stream << buffer.d_ptr->commands;
2231 stream << buffer.d_ptr->boundingRect;
2232 stream << buffer.d_ptr->frames;
2233
2234 return stream;
2235}
2236
2237QDataStream &operator>>(QDataStream &stream, QPaintBuffer &buffer)
2238{
2239 QHash<qint64, QPixmap> pixmaps;
2240 QHash<qint64, QImage> images;
2241
2242 stream >> pixmaps;
2243 stream >> images;
2244
2245 stream >> buffer.d_ptr->ints;
2246 stream >> buffer.d_ptr->floats;
2247 stream >> buffer.d_ptr->variants;
2248 stream >> buffer.d_ptr->commands;
2249 stream >> buffer.d_ptr->boundingRect;
2250 stream >> buffer.d_ptr->frames;
2251
2252 QVector<QVariant> &variants = buffer.d_ptr->variants;
2253 for (int i = 0; i < variants.size(); ++i) {
2254 const QVariant &v = variants.at(i);
2255 if (v.canConvert<QPaintBufferCacheEntry>()) {
2256 QPaintBufferCacheEntry entry = v.value<QPaintBufferCacheEntry>();
2257 if (entry.type == QVariant::Image)
2258 variants[i] = QVariant(images.value(entry.cacheKey));
2259 else
2260 variants[i] = QVariant(pixmaps.value(entry.cacheKey));
2261 } else if (v.canConvert<QPaintBufferCacheEntryV2>()) {
2262 QPaintBufferCacheEntryV2 entry = v.value<QPaintBufferCacheEntryV2>();
2263
2264 if (entry.flags.type == QPaintBufferCacheEntryV2::ImageKey)
2265 variants[i] = QVariant(images.value(entry.flags.key));
2266 else if (entry.flags.type == QPaintBufferCacheEntryV2::PixmapKey)
2267 variants[i] = QVariant(pixmaps.value(entry.flags.key));
2268 else
2269 qWarning() << "operator<<(QDataStream &stream, QPaintBuffer &buffer): unrecognized cache entry type:" << entry.flags.type;
2270 }
2271 }
2272
2273 return stream;
2274}
2275
2276QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.