source: trunk/src/gui/image/qpaintengine_pic.cpp@ 855

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

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

File size: 17.1 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
42#include "private/qpaintengine_p.h"
43#include "private/qpainter_p.h"
44#include "private/qpicture_p.h"
45#include "private/qfont_p.h"
46
47#ifndef QT_NO_PICTURE
48
49#include "qbuffer.h"
50#include "qbytearray.h"
51#include "qdatastream.h"
52#include "qmath.h"
53#include "qpaintengine_pic_p.h"
54#include "qpicture.h"
55#include "qpolygon.h"
56#include "qrect.h"
57#include <private/qtextengine_p.h>
58
59//#define QT_PICTURE_DEBUG
60#include <qdebug.h>
61
62
63QT_BEGIN_NAMESPACE
64
65class QPicturePaintEnginePrivate : public QPaintEnginePrivate
66{
67 Q_DECLARE_PUBLIC(QPicturePaintEngine)
68public:
69 QDataStream s;
70 QPainter *pt;
71 QPicturePrivate *pic_d;
72};
73
74QPicturePaintEngine::QPicturePaintEngine()
75 : QPaintEngine(*(new QPicturePaintEnginePrivate), AllFeatures)
76{
77 Q_D(QPicturePaintEngine);
78 d->pt = 0;
79}
80
81QPicturePaintEngine::QPicturePaintEngine(QPaintEnginePrivate &dptr)
82 : QPaintEngine(dptr, AllFeatures)
83{
84 Q_D(QPicturePaintEngine);
85 d->pt = 0;
86}
87
88QPicturePaintEngine::~QPicturePaintEngine()
89{
90}
91
92bool QPicturePaintEngine::begin(QPaintDevice *pd)
93{
94 Q_D(QPicturePaintEngine);
95#ifdef QT_PICTURE_DEBUG
96 qDebug() << "QPicturePaintEngine::begin()";
97#endif
98 Q_ASSERT(pd);
99 QPicture *pic = static_cast<QPicture *>(pd);
100
101 d->pdev = pd;
102 d->pic_d = pic->d_func();
103 Q_ASSERT(d->pic_d);
104
105 d->s.setDevice(&d->pic_d->pictb);
106 d->s.setVersion(d->pic_d->formatMajor);
107
108 d->pic_d->pictb.open(QIODevice::WriteOnly | QIODevice::Truncate);
109 d->s.writeRawData(qt_mfhdr_tag, 4);
110 d->s << (quint16) 0 << (quint16) d->pic_d->formatMajor << (quint16) d->pic_d->formatMinor;
111 d->s << (quint8) QPicturePrivate::PdcBegin << (quint8) sizeof(qint32);
112 d->pic_d->brect = QRect();
113 if (d->pic_d->formatMajor >= 4) {
114 QRect r = pic->boundingRect();
115 d->s << (qint32) r.left() << (qint32) r.top() << (qint32) r.width()
116 << (qint32) r.height();
117 }
118 d->pic_d->trecs = 0;
119 d->s << (quint32)d->pic_d->trecs; // total number of records
120 d->pic_d->formatOk = false;
121 setActive(true);
122 return true;
123}
124
125bool QPicturePaintEngine::end()
126{
127 Q_D(QPicturePaintEngine);
128#ifdef QT_PICTURE_DEBUG
129 qDebug() << "QPicturePaintEngine::end()";
130#endif
131 d->pic_d->trecs++;
132 d->s << (quint8) QPicturePrivate::PdcEnd << (quint8) 0;
133 int cs_start = sizeof(quint32); // pos of checksum word
134 int data_start = cs_start + sizeof(quint16);
135 int brect_start = data_start + 2*sizeof(qint16) + 2*sizeof(quint8);
136 int pos = d->pic_d->pictb.pos();
137 d->pic_d->pictb.seek(brect_start);
138 if (d->pic_d->formatMajor >= 4) { // bounding rectangle
139 QRect r = static_cast<QPicture *>(d->pdev)->boundingRect();
140 d->s << (qint32) r.left() << (qint32) r.top() << (qint32) r.width()
141 << (qint32) r.height();
142 }
143 d->s << (quint32) d->pic_d->trecs; // write number of records
144 d->pic_d->pictb.seek(cs_start);
145 QByteArray buf = d->pic_d->pictb.buffer();
146 quint16 cs = (quint16) qChecksum(buf.constData() + data_start, pos - data_start);
147 d->s << cs; // write checksum
148 d->pic_d->pictb.close();
149 setActive(false);
150 return true;
151}
152
153#define SERIALIZE_CMD(c) \
154 d->pic_d->trecs++; \
155 d->s << (quint8) c; \
156 d->s << (quint8) 0; \
157 pos = d->pic_d->pictb.pos()
158
159void QPicturePaintEngine::updatePen(const QPen &pen)
160{
161 Q_D(QPicturePaintEngine);
162#ifdef QT_PICTURE_DEBUG
163 qDebug() << " -> updatePen(): width:" << pen.width() << "style:"
164 << pen.style() << "color:" << pen.color();
165#endif
166 int pos;
167 SERIALIZE_CMD(QPicturePrivate::PdcSetPen);
168 if (d->pic_d->in_memory_only) {
169 int index = d->pic_d->pen_list.size();
170 d->pic_d->pen_list.append(pen);
171 d->s << index;
172 } else {
173 d->s << pen;
174 }
175 writeCmdLength(pos, QRect(), false);
176}
177
178void QPicturePaintEngine::updateCompositionMode(QPainter::CompositionMode cmode)
179{
180 Q_D(QPicturePaintEngine);
181#ifdef QT_PICTURE_DEBUG
182 qDebug() << " -> updateCompositionMode():" << cmode;
183#endif
184 int pos;
185 SERIALIZE_CMD(QPicturePrivate::PdcSetCompositionMode);
186 d->s << (qint32)cmode;
187 writeCmdLength(pos, QRectF(), false);
188}
189
190void QPicturePaintEngine::updateClipEnabled(bool enabled)
191{
192 Q_D(QPicturePaintEngine);
193#ifdef QT_PICTURE_DEBUG
194 qDebug() << " -> updateClipEnabled():" << enabled;
195#endif
196 int pos;
197 SERIALIZE_CMD(QPicturePrivate::PdcSetClipEnabled);
198 d->s << enabled;
199 writeCmdLength(pos, QRectF(), false);
200}
201
202void QPicturePaintEngine::updateOpacity(qreal opacity)
203{
204 Q_D(QPicturePaintEngine);
205#ifdef QT_PICTURE_DEBUG
206 qDebug() << " -> updateOpacity():" << opacity;
207#endif
208 int pos;
209 SERIALIZE_CMD(QPicturePrivate::PdcSetOpacity);
210 d->s << double(opacity);
211 writeCmdLength(pos, QRectF(), false);
212}
213
214void QPicturePaintEngine::updateBrush(const QBrush &brush)
215{
216 Q_D(QPicturePaintEngine);
217#ifdef QT_PICTURE_DEBUG
218 qDebug() << " -> updateBrush(): style:" << brush.style();
219#endif
220 int pos;
221 SERIALIZE_CMD(QPicturePrivate::PdcSetBrush);
222 if (d->pic_d->in_memory_only) {
223 int index = d->pic_d->brush_list.size();
224 d->pic_d->brush_list.append(brush);
225 d->s << index;
226 } else {
227 d->s << brush;
228 }
229 writeCmdLength(pos, QRect(), false);
230}
231
232void QPicturePaintEngine::updateBrushOrigin(const QPointF &p)
233{
234 Q_D(QPicturePaintEngine);
235#ifdef QT_PICTURE_DEBUG
236 qDebug() << " -> updateBrushOrigin(): " << p;
237#endif
238 int pos;
239 SERIALIZE_CMD(QPicturePrivate::PdcSetBrushOrigin);
240 d->s << p;
241 writeCmdLength(pos, QRect(), false);
242}
243
244void QPicturePaintEngine::updateFont(const QFont &font)
245{
246 Q_D(QPicturePaintEngine);
247#ifdef QT_PICTURE_DEBUG
248 qDebug() << " -> updateFont(): pt sz:" << font.pointSize();
249#endif
250 int pos;
251 SERIALIZE_CMD(QPicturePrivate::PdcSetFont);
252 QFont fnt = font;
253 d->s << fnt;
254 writeCmdLength(pos, QRectF(), false);
255}
256
257void QPicturePaintEngine::updateBackground(Qt::BGMode bgMode, const QBrush &bgBrush)
258{
259 Q_D(QPicturePaintEngine);
260#ifdef QT_PICTURE_DEBUG
261 qDebug() << " -> updateBackground(): mode:" << bgMode << "style:" << bgBrush.style();
262#endif
263 int pos;
264 SERIALIZE_CMD(QPicturePrivate::PdcSetBkColor);
265 d->s << bgBrush.color();
266 writeCmdLength(pos, QRect(), false);
267
268 SERIALIZE_CMD(QPicturePrivate::PdcSetBkMode);
269 d->s << (qint8) bgMode;
270 writeCmdLength(pos, QRectF(), false);
271}
272
273void QPicturePaintEngine::updateMatrix(const QTransform &matrix)
274{
275 Q_D(QPicturePaintEngine);
276#ifdef QT_PICTURE_DEBUG
277 qDebug() << " -> updateMatrix():" << matrix;
278#endif
279 int pos;
280 SERIALIZE_CMD(QPicturePrivate::PdcSetWMatrix);
281 d->s << matrix << (qint8) false;
282 writeCmdLength(pos, QRectF(), false);
283}
284
285void QPicturePaintEngine::updateClipRegion(const QRegion &region, Qt::ClipOperation op)
286{
287 Q_D(QPicturePaintEngine);
288#ifdef QT_PICTURE_DEBUG
289 qDebug() << " -> updateClipRegion(): op:" << op
290 << "bounding rect:" << region.boundingRect();
291#endif
292 int pos;
293 SERIALIZE_CMD(QPicturePrivate::PdcSetClipRegion);
294 d->s << region << qint8(op);
295 writeCmdLength(pos, QRectF(), false);
296}
297
298void QPicturePaintEngine::updateClipPath(const QPainterPath &path, Qt::ClipOperation op)
299{
300 Q_D(QPicturePaintEngine);
301#ifdef QT_PICTURE_DEBUG
302 qDebug() << " -> updateClipPath(): op:" << op
303 << "bounding rect:" << path.boundingRect();
304#endif
305 int pos;
306
307 SERIALIZE_CMD(QPicturePrivate::PdcSetClipPath);
308 d->s << path << qint8(op);
309 writeCmdLength(pos, QRectF(), false);
310}
311
312void QPicturePaintEngine::updateRenderHints(QPainter::RenderHints hints)
313{
314 Q_D(QPicturePaintEngine);
315#ifdef QT_PICTURE_DEBUG
316 qDebug() << " -> updateRenderHints(): " << hints;
317#endif
318 int pos;
319 SERIALIZE_CMD(QPicturePrivate::PdcSetRenderHint);
320 d->s << (quint32) hints;
321 writeCmdLength(pos, QRect(), false);
322}
323
324void QPicturePaintEngine::writeCmdLength(int pos, const QRectF &r, bool corr)
325{
326 Q_D(QPicturePaintEngine);
327 int newpos = d->pic_d->pictb.pos(); // new position
328 int length = newpos - pos;
329 QRectF br(r);
330
331 if (length < 255) { // write 8-bit length
332 d->pic_d->pictb.seek(pos - 1); // position to right index
333 d->s << (quint8)length;
334 } else { // write 32-bit length
335 d->s << (quint32)0; // extend the buffer
336 d->pic_d->pictb.seek(pos - 1); // position to right index
337 d->s << (quint8)255; // indicate 32-bit length
338 char *p = d->pic_d->pictb.buffer().data();
339 memmove(p+pos+4, p+pos, length); // make room for 4 byte
340 d->s << (quint32)length;
341 newpos += 4;
342 }
343 d->pic_d->pictb.seek(newpos); // set to new position
344
345 if (br.width() > 0.0 || br.height() > 0.0) {
346 if (corr) { // widen bounding rect
347 int w2 = painter()->pen().width() / 2;
348 br.setCoords(br.left() - w2, br.top() - w2,
349 br.right() + w2, br.bottom() + w2);
350 }
351 br = painter()->transform().mapRect(br);
352 if (painter()->hasClipping()) {
353 QRect cr = painter()->clipRegion().boundingRect();
354 br &= cr;
355 }
356
357 if (br.width() > 0.0 || br.height() > 0.0) {
358 int minx = qFloor(br.left());
359 int miny = qFloor(br.top());
360 int maxx = qCeil(br.right());
361 int maxy = qCeil(br.bottom());
362
363 if (d->pic_d->brect.width() > 0 || d->pic_d->brect.height() > 0) {
364 minx = qMin(minx, d->pic_d->brect.left());
365 miny = qMin(miny, d->pic_d->brect.top());
366 maxx = qMax(maxx, d->pic_d->brect.x() + d->pic_d->brect.width());
367 maxy = qMax(maxy, d->pic_d->brect.y() + d->pic_d->brect.height());
368 d->pic_d->brect = QRect(minx, miny, maxx - minx, maxy - miny);
369 } else {
370 d->pic_d->brect = QRect(minx, miny, maxx - minx, maxy - miny);
371 }
372 }
373 }
374}
375
376void QPicturePaintEngine::drawEllipse(const QRectF &rect)
377{
378 Q_D(QPicturePaintEngine);
379#ifdef QT_PICTURE_DEBUG
380 qDebug() << " -> drawEllipse():" << rect;
381#endif
382 int pos;
383 SERIALIZE_CMD(QPicturePrivate::PdcDrawEllipse);
384 d->s << rect;
385 writeCmdLength(pos, rect, true);
386}
387
388void QPicturePaintEngine::drawPath(const QPainterPath &path)
389{
390 Q_D(QPicturePaintEngine);
391#ifdef QT_PICTURE_DEBUG
392 qDebug() << " -> drawPath():" << path.boundingRect();
393#endif
394 int pos;
395 SERIALIZE_CMD(QPicturePrivate::PdcDrawPath);
396 d->s << path;
397 writeCmdLength(pos, path.boundingRect(), true);
398}
399
400void QPicturePaintEngine::drawPolygon(const QPointF *points, int numPoints, PolygonDrawMode mode)
401{
402 Q_D(QPicturePaintEngine);
403#ifdef QT_PICTURE_DEBUG
404 qDebug() << " -> drawPolygon(): size=" << numPoints;
405#endif
406 int pos;
407
408 QPolygonF polygon;
409 for (int i=0; i<numPoints; ++i)
410 polygon << points[i];
411
412 if (mode == PolylineMode) {
413 SERIALIZE_CMD(QPicturePrivate::PdcDrawPolyline);
414 d->s << polygon;
415 } else {
416 SERIALIZE_CMD(QPicturePrivate::PdcDrawPolygon);
417 d->s << polygon;
418 d->s << (qint8)(mode == OddEvenMode ? 0 : 1);
419 }
420
421 writeCmdLength(pos, polygon.boundingRect(), true);
422}
423
424void QPicturePaintEngine::drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr)
425{
426 Q_D(QPicturePaintEngine);
427#ifdef QT_PICTURE_DEBUG
428 qDebug() << " -> drawPixmap():" << r;
429#endif
430 int pos;
431 SERIALIZE_CMD(QPicturePrivate::PdcDrawPixmap);
432
433 if (d->pic_d->in_memory_only) {
434 int index = d->pic_d->pixmap_list.size();
435 d->pic_d->pixmap_list.append(pm);
436 d->s << r << index << sr;
437 } else {
438 d->s << r << pm << sr;
439 }
440 writeCmdLength(pos, r, false);
441}
442
443void QPicturePaintEngine::drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, const QPointF &s)
444{
445 Q_D(QPicturePaintEngine);
446#ifdef QT_PICTURE_DEBUG
447 qDebug() << " -> drawTiledPixmap():" << r << s;
448#endif
449 int pos;
450 SERIALIZE_CMD(QPicturePrivate::PdcDrawTiledPixmap);
451 if (d->pic_d->in_memory_only) {
452 int index = d->pic_d->pixmap_list.size();
453 d->pic_d->pixmap_list.append(pixmap);
454 d->s << r << index << s;
455 } else {
456 d->s << r << pixmap << s;
457 }
458 writeCmdLength(pos, r, false);
459}
460
461void QPicturePaintEngine::drawImage(const QRectF &r, const QImage &image, const QRectF &sr,
462 Qt::ImageConversionFlags flags)
463{
464 Q_D(QPicturePaintEngine);
465#ifdef QT_PICTURE_DEBUG
466 qDebug() << " -> drawImage():" << r << sr;
467#endif
468 int pos;
469 SERIALIZE_CMD(QPicturePrivate::PdcDrawImage);
470 if (d->pic_d->in_memory_only) {
471 int index = d->pic_d->image_list.size();
472 d->pic_d->image_list.append(image);
473 d->s << r << index << sr << (quint32) flags;
474 } else {
475 d->s << r << image << sr << (quint32) flags;
476 }
477 writeCmdLength(pos, r, false);
478}
479
480Q_GUI_EXPORT extern int qt_defaultDpi();
481
482void QPicturePaintEngine::drawTextItem(const QPointF &p , const QTextItem &ti)
483{
484 Q_D(QPicturePaintEngine);
485#ifdef QT_PICTURE_DEBUG
486 qDebug() << " -> drawTextItem():" << p << ti.text();
487#endif
488
489 const QTextItemInt &si = static_cast<const QTextItemInt &>(ti);
490 if (si.chars == 0)
491 QPaintEngine::drawTextItem(p, ti); // Draw as path
492
493 if (d->pic_d->formatMajor >= 9) {
494 int pos;
495 SERIALIZE_CMD(QPicturePrivate::PdcDrawTextItem);
496 QFont fnt = ti.font();
497 fnt.setUnderline(false);
498 fnt.setStrikeOut(false);
499 fnt.setOverline(false);
500
501 qreal justificationWidth = 0;
502 if (si.justified)
503 justificationWidth = si.width.toReal();
504
505 d->s << p << ti.text() << fnt << ti.renderFlags() << double(fnt.d->dpi)/qt_defaultDpi() << justificationWidth;
506 writeCmdLength(pos, /*brect=*/QRectF(), /*corr=*/false);
507 } else if (d->pic_d->formatMajor >= 8) {
508 // old old (buggy) format
509 int pos;
510 SERIALIZE_CMD(QPicturePrivate::PdcDrawTextItem);
511 d->s << QPointF(p.x(), p.y() - ti.ascent()) << ti.text() << ti.font() << ti.renderFlags();
512 writeCmdLength(pos, /*brect=*/QRectF(), /*corr=*/false);
513 } else {
514 // old (buggy) format
515 int pos;
516 SERIALIZE_CMD(QPicturePrivate::PdcDrawText2);
517 d->s << p << ti.text();
518 writeCmdLength(pos, QRectF(p, QSizeF(1,1)), true);
519 }
520}
521
522void QPicturePaintEngine::updateState(const QPaintEngineState &state)
523{
524 QPaintEngine::DirtyFlags flags = state.state();
525 if (flags & DirtyPen) updatePen(state.pen());
526 if (flags & DirtyBrush) updateBrush(state.brush());
527 if (flags & DirtyBrushOrigin) updateBrushOrigin(state.brushOrigin());
528 if (flags & DirtyFont) updateFont(state.font());
529 if (flags & DirtyBackground) updateBackground(state.backgroundMode(), state.backgroundBrush());
530 if (flags & DirtyTransform) updateMatrix(state.transform());
531 if (flags & DirtyClipEnabled) updateClipEnabled(state.isClipEnabled());
532 if (flags & DirtyClipRegion) updateClipRegion(state.clipRegion(), state.clipOperation());
533 if (flags & DirtyClipPath) updateClipPath(state.clipPath(), state.clipOperation());
534 if (flags & DirtyHints) updateRenderHints(state.renderHints());
535 if (flags & DirtyCompositionMode) updateCompositionMode(state.compositionMode());
536 if (flags & DirtyOpacity) updateOpacity(state.opacity());
537}
538
539QT_END_NAMESPACE
540
541#endif // QT_NO_PICTURE
Note: See TracBrowser for help on using the repository browser.