source: trunk/src/gui/painting/qpaintengineex.cpp@ 203

Last change on this file since 203 was 2, checked in by Dmitry A. Kuminov, 16 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

File size: 27.9 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** Contact: Qt Software Information ([email protected])
5**
6** This file is part of the QtGui module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial Usage
10** Licensees holding valid Qt Commercial licenses may use this file in
11** accordance with the Qt Commercial License Agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and Nokia.
14**
15** GNU Lesser General Public License Usage
16** Alternatively, this file may be used under the terms of the GNU Lesser
17** General Public License version 2.1 as published by the Free Software
18** Foundation and appearing in the file LICENSE.LGPL included in the
19** packaging of this file. Please review the following information to
20** ensure the GNU Lesser General Public License version 2.1 requirements
21** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22**
23** In addition, as a special exception, Nokia gives you certain
24** additional rights. These rights are described in the Nokia Qt LGPL
25** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
26** 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 are unsure which license is appropriate for your use, please
37** contact the sales department at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qpaintengineex_p.h"
43#include "qpainter_p.h"
44#include "qstroker_p.h"
45#include <private/qpainterpath_p.h>
46
47#include <qvarlengtharray.h>
48#include <qdebug.h>
49
50
51QT_BEGIN_NAMESPACE
52
53/*******************************************************************************
54 *
55 * class QVectorPath
56 *
57 */
58
59const QRealRect &QVectorPath::controlPointRect() const
60{
61 if (m_hints & ControlPointRect)
62 return m_cp_rect;
63
64 if (m_count == 0) {
65 m_cp_rect.x1 = m_cp_rect.x2 = m_cp_rect.y1 = m_cp_rect.y2 = 0;
66 m_hints |= ControlPointRect;
67 return m_cp_rect;
68 }
69 Q_ASSERT(m_points && m_count > 0);
70
71 const qreal *pts = m_points;
72 m_cp_rect.x1 = m_cp_rect.x2 = *pts;
73 ++pts;
74 m_cp_rect.y1 = m_cp_rect.y2 = *pts;
75 ++pts;
76
77 const qreal *epts = m_points + (m_count << 1);
78 while (pts < epts) {
79 qreal x = *pts;
80 if (x < m_cp_rect.x1) m_cp_rect.x1 = x;
81 else if (x > m_cp_rect.x2) m_cp_rect.x2 = x;
82 ++pts;
83
84 qreal y = *pts;
85 if (y < m_cp_rect.y1) m_cp_rect.y1 = y;
86 else if (y > m_cp_rect.y2) m_cp_rect.y2 = y;
87 ++pts;
88 }
89
90 m_hints |= ControlPointRect;
91 return m_cp_rect;
92}
93
94const QVectorPath &qtVectorPathForPath(const QPainterPath &path)
95{
96 Q_ASSERT(path.d_func());
97 return path.d_func()->vectorPath();
98}
99
100#ifndef QT_NO_DEBUG_STREAM
101QDebug Q_GUI_EXPORT &operator<<(QDebug &s, const QVectorPath &path)
102{
103 QRealRect vectorPathBounds = path.controlPointRect();
104 QRectF rf(vectorPathBounds.x1, vectorPathBounds.y1,
105 vectorPathBounds.x2 - vectorPathBounds.x1, vectorPathBounds.y2 - vectorPathBounds.y1);
106 s << "QVectorPath(size:" << path.elementCount()
107 << " hints:" << hex << path.hints()
108 << rf << ")";
109 return s;
110}
111#endif
112
113/*******************************************************************************
114 *
115 * class QPaintEngineExPrivate:
116 *
117 */
118
119
120struct StrokeHandler {
121 QDataBuffer<qreal> pts;
122 QDataBuffer<QPainterPath::ElementType> types;
123};
124
125
126QPaintEngineExPrivate::QPaintEngineExPrivate()
127 : dasher(&stroker),
128 strokeHandler(0),
129 activeStroker(0),
130 strokerPen(Qt::NoPen)
131{
132}
133
134
135QPaintEngineExPrivate::~QPaintEngineExPrivate()
136{
137 delete strokeHandler;
138}
139
140
141
142/*******************************************************************************
143 *
144 * class QPaintEngineEx:
145 *
146 */
147
148static QPainterPath::ElementType qpaintengineex_ellipse_types[] = {
149 QPainterPath::MoveToElement,
150 QPainterPath::CurveToElement,
151 QPainterPath::CurveToDataElement,
152 QPainterPath::CurveToDataElement,
153
154 QPainterPath::CurveToElement,
155 QPainterPath::CurveToDataElement,
156 QPainterPath::CurveToDataElement,
157
158 QPainterPath::CurveToElement,
159 QPainterPath::CurveToDataElement,
160 QPainterPath::CurveToDataElement,
161
162 QPainterPath::CurveToElement,
163 QPainterPath::CurveToDataElement,
164 QPainterPath::CurveToDataElement
165};
166
167static QPainterPath::ElementType qpaintengineex_line_types_16[] = {
168 QPainterPath::MoveToElement, QPainterPath::LineToElement,
169 QPainterPath::MoveToElement, QPainterPath::LineToElement,
170 QPainterPath::MoveToElement, QPainterPath::LineToElement,
171 QPainterPath::MoveToElement, QPainterPath::LineToElement,
172 QPainterPath::MoveToElement, QPainterPath::LineToElement,
173 QPainterPath::MoveToElement, QPainterPath::LineToElement,
174 QPainterPath::MoveToElement, QPainterPath::LineToElement,
175 QPainterPath::MoveToElement, QPainterPath::LineToElement,
176 QPainterPath::MoveToElement, QPainterPath::LineToElement,
177 QPainterPath::MoveToElement, QPainterPath::LineToElement,
178 QPainterPath::MoveToElement, QPainterPath::LineToElement,
179 QPainterPath::MoveToElement, QPainterPath::LineToElement,
180 QPainterPath::MoveToElement, QPainterPath::LineToElement,
181 QPainterPath::MoveToElement, QPainterPath::LineToElement,
182 QPainterPath::MoveToElement, QPainterPath::LineToElement,
183 QPainterPath::MoveToElement, QPainterPath::LineToElement
184};
185
186static QPainterPath::ElementType qpaintengineex_rect4_types_32[] = {
187 QPainterPath::MoveToElement, QPainterPath::LineToElement, QPainterPath::LineToElement, QPainterPath::LineToElement, // 1
188 QPainterPath::MoveToElement, QPainterPath::LineToElement, QPainterPath::LineToElement, QPainterPath::LineToElement, // 2
189 QPainterPath::MoveToElement, QPainterPath::LineToElement, QPainterPath::LineToElement, QPainterPath::LineToElement, // 3
190 QPainterPath::MoveToElement, QPainterPath::LineToElement, QPainterPath::LineToElement, QPainterPath::LineToElement, // 4
191 QPainterPath::MoveToElement, QPainterPath::LineToElement, QPainterPath::LineToElement, QPainterPath::LineToElement, // 5
192 QPainterPath::MoveToElement, QPainterPath::LineToElement, QPainterPath::LineToElement, QPainterPath::LineToElement, // 6
193 QPainterPath::MoveToElement, QPainterPath::LineToElement, QPainterPath::LineToElement, QPainterPath::LineToElement, // 7
194 QPainterPath::MoveToElement, QPainterPath::LineToElement, QPainterPath::LineToElement, QPainterPath::LineToElement, // 8
195 QPainterPath::MoveToElement, QPainterPath::LineToElement, QPainterPath::LineToElement, QPainterPath::LineToElement, // 9
196 QPainterPath::MoveToElement, QPainterPath::LineToElement, QPainterPath::LineToElement, QPainterPath::LineToElement, // 10
197 QPainterPath::MoveToElement, QPainterPath::LineToElement, QPainterPath::LineToElement, QPainterPath::LineToElement, // 11
198 QPainterPath::MoveToElement, QPainterPath::LineToElement, QPainterPath::LineToElement, QPainterPath::LineToElement, // 12
199 QPainterPath::MoveToElement, QPainterPath::LineToElement, QPainterPath::LineToElement, QPainterPath::LineToElement, // 13
200 QPainterPath::MoveToElement, QPainterPath::LineToElement, QPainterPath::LineToElement, QPainterPath::LineToElement, // 14
201 QPainterPath::MoveToElement, QPainterPath::LineToElement, QPainterPath::LineToElement, QPainterPath::LineToElement, // 15
202 QPainterPath::MoveToElement, QPainterPath::LineToElement, QPainterPath::LineToElement, QPainterPath::LineToElement, // 16
203 QPainterPath::MoveToElement, QPainterPath::LineToElement, QPainterPath::LineToElement, QPainterPath::LineToElement, // 17
204 QPainterPath::MoveToElement, QPainterPath::LineToElement, QPainterPath::LineToElement, QPainterPath::LineToElement, // 18
205 QPainterPath::MoveToElement, QPainterPath::LineToElement, QPainterPath::LineToElement, QPainterPath::LineToElement, // 19
206 QPainterPath::MoveToElement, QPainterPath::LineToElement, QPainterPath::LineToElement, QPainterPath::LineToElement, // 20
207 QPainterPath::MoveToElement, QPainterPath::LineToElement, QPainterPath::LineToElement, QPainterPath::LineToElement, // 21
208 QPainterPath::MoveToElement, QPainterPath::LineToElement, QPainterPath::LineToElement, QPainterPath::LineToElement, // 22
209 QPainterPath::MoveToElement, QPainterPath::LineToElement, QPainterPath::LineToElement, QPainterPath::LineToElement, // 23
210 QPainterPath::MoveToElement, QPainterPath::LineToElement, QPainterPath::LineToElement, QPainterPath::LineToElement, // 24
211 QPainterPath::MoveToElement, QPainterPath::LineToElement, QPainterPath::LineToElement, QPainterPath::LineToElement, // 25
212 QPainterPath::MoveToElement, QPainterPath::LineToElement, QPainterPath::LineToElement, QPainterPath::LineToElement, // 26
213 QPainterPath::MoveToElement, QPainterPath::LineToElement, QPainterPath::LineToElement, QPainterPath::LineToElement, // 27
214 QPainterPath::MoveToElement, QPainterPath::LineToElement, QPainterPath::LineToElement, QPainterPath::LineToElement, // 28
215 QPainterPath::MoveToElement, QPainterPath::LineToElement, QPainterPath::LineToElement, QPainterPath::LineToElement, // 29
216 QPainterPath::MoveToElement, QPainterPath::LineToElement, QPainterPath::LineToElement, QPainterPath::LineToElement, // 30
217 QPainterPath::MoveToElement, QPainterPath::LineToElement, QPainterPath::LineToElement, QPainterPath::LineToElement, // 31
218 QPainterPath::MoveToElement, QPainterPath::LineToElement, QPainterPath::LineToElement, QPainterPath::LineToElement, // 32
219};
220
221static void qpaintengineex_moveTo(qreal x, qreal y, void *data) {
222 ((StrokeHandler *) data)->pts.add(x);
223 ((StrokeHandler *) data)->pts.add(y);
224 ((StrokeHandler *) data)->types.add(QPainterPath::MoveToElement);
225}
226
227static void qpaintengineex_lineTo(qreal x, qreal y, void *data) {
228 ((StrokeHandler *) data)->pts.add(x);
229 ((StrokeHandler *) data)->pts.add(y);
230 ((StrokeHandler *) data)->types.add(QPainterPath::LineToElement);
231}
232
233static void qpaintengineex_cubicTo(qreal c1x, qreal c1y, qreal c2x, qreal c2y, qreal ex, qreal ey, void *data) {
234 ((StrokeHandler *) data)->pts.add(c1x);
235 ((StrokeHandler *) data)->pts.add(c1y);
236 ((StrokeHandler *) data)->types.add(QPainterPath::CurveToElement);
237
238 ((StrokeHandler *) data)->pts.add(c2x);
239 ((StrokeHandler *) data)->pts.add(c2y);
240 ((StrokeHandler *) data)->types.add(QPainterPath::CurveToDataElement);
241
242 ((StrokeHandler *) data)->pts.add(ex);
243 ((StrokeHandler *) data)->pts.add(ey);
244 ((StrokeHandler *) data)->types.add(QPainterPath::CurveToDataElement);
245}
246
247QPaintEngineEx::QPaintEngineEx(QPaintEngineExPrivate &data)
248 : QPaintEngine(data, AllFeatures)
249{
250 extended = true;
251}
252
253
254QPainterState *QPaintEngineEx::createState(QPainterState *orig) const
255{
256 if (!orig)
257 return new QPainterState;
258 return new QPainterState(orig);
259}
260
261extern bool qt_scaleForTransform(const QTransform &transform, qreal *scale); // qtransform.cpp
262
263void QPaintEngineEx::stroke(const QVectorPath &path, const QPen &pen)
264{
265#ifdef QT_DEBUG_DRAW
266 qDebug() << "QPaintEngineEx::stroke()" << pen;
267#endif
268
269 Q_D(QPaintEngineEx);
270
271 if (path.isEmpty())
272 return;
273
274 if (!d->strokeHandler) {
275 d->strokeHandler = new StrokeHandler;
276 d->stroker.setMoveToHook(qpaintengineex_moveTo);
277 d->stroker.setLineToHook(qpaintengineex_lineTo);
278 d->stroker.setCubicToHook(qpaintengineex_cubicTo);
279 }
280
281 if (!qpen_fast_equals(pen, d->strokerPen)) {
282 d->strokerPen = pen;
283 d->stroker.setJoinStyle(pen.joinStyle());
284 d->stroker.setCapStyle(pen.capStyle());
285 d->stroker.setMiterLimit(pen.miterLimit());
286 qreal penWidth = pen.widthF();
287 if (penWidth == 0)
288 d->stroker.setStrokeWidth(1);
289 else
290 d->stroker.setStrokeWidth(penWidth);
291
292 Qt::PenStyle style = pen.style();
293 if (style == Qt::SolidLine) {
294 d->activeStroker = &d->stroker;
295 } else if (style == Qt::NoPen) {
296 d->activeStroker = 0;
297 } else {
298 // ### re-enable...
299// if (pen.isCosmetic()) {
300// d->dashStroker->setClipRect(d->deviceRect);
301// } else {
302// QRectF clipRect = s->matrix.inverted().mapRect(QRectF(d->deviceRect));
303// d->dashStroker->setClipRect(clipRect);
304// }
305 d->dasher.setDashPattern(pen.dashPattern());
306 d->dasher.setDashOffset(pen.dashOffset());
307 d->activeStroker = &d->dasher;
308 }
309 }
310
311 if (!d->activeStroker) {
312 return;
313 }
314
315 const QPainterPath::ElementType *types = path.elements();
316 const qreal *points = path.points();
317 int pointCount = path.elementCount();
318
319 const qreal *lastPoint = points + (pointCount<<1);
320
321 d->activeStroker->begin(d->strokeHandler);
322 d->strokeHandler->types.reset();
323 d->strokeHandler->pts.reset();
324
325 // Some engines might decide to optimize for the non-shape hint later on...
326 uint flags = QVectorPath::WindingFill;
327 if (d->stroker.capStyle() == Qt::RoundCap || d->stroker.joinStyle() == Qt::RoundJoin)
328 flags |= QVectorPath::CurvedShapeHint;
329
330 // ### Perspective Xforms are currently not supported...
331 qreal txscale = 1;
332 if (!(pen.isCosmetic() || (qt_scaleForTransform(state()->matrix, &txscale) && txscale != 1))) {
333 // We include cosmetic pens in this case to avoid having to
334 // change the current transform. Normal transformed,
335 // non-cosmetic pens will be transformed as part of fill
336 // later, so they are also covered here..
337 if (types) {
338 while (points < lastPoint) {
339 switch (*types) {
340 case QPainterPath::MoveToElement:
341 d->activeStroker->moveTo(points[0], points[1]);
342 points += 2;
343 ++types;
344 break;
345 case QPainterPath::LineToElement:
346 d->activeStroker->lineTo(points[0], points[1]);
347 points += 2;
348 ++types;
349 break;
350 case QPainterPath::CurveToElement:
351 d->activeStroker->cubicTo(points[0], points[1],
352 points[2], points[3],
353 points[4], points[5]);
354 points += 6;
355 types += 3;
356 flags |= QVectorPath::CurvedShapeHint;
357 break;
358 default:
359 break;
360 }
361 }
362 if (path.hasImplicitClose())
363 d->activeStroker->lineTo(path.points()[0], path.points()[1]);
364
365 } else {
366 d->activeStroker->moveTo(points[0], points[1]);
367 points += 2;
368 ++types;
369 while (points < lastPoint) {
370 d->activeStroker->lineTo(points[0], points[1]);
371 points += 2;
372 ++types;
373 }
374 if (path.hasImplicitClose())
375 d->activeStroker->lineTo(path.points()[0], path.points()[1]);
376 }
377 d->activeStroker->end();
378
379 if (!d->strokeHandler->types.size()) // an empty path...
380 return;
381
382 QVectorPath strokePath(d->strokeHandler->pts.data(),
383 d->strokeHandler->types.size(),
384 d->strokeHandler->types.data(),
385 QVectorPath::WindingFill);
386 fill(strokePath, pen.brush());
387 } else {
388 const qreal strokeWidth = d->stroker.strokeWidth();
389 d->stroker.setStrokeWidth(strokeWidth * txscale);
390 // For cosmetic pens we need a bit of trickery... We to process xform the input points
391 if (types) {
392 while (points < lastPoint) {
393 switch (*types) {
394 case QPainterPath::MoveToElement: {
395 QPointF pt = (*(QPointF *) points) * state()->matrix;
396 d->activeStroker->moveTo(pt.x(), pt.y());
397 points += 2;
398 ++types;
399 break;
400 }
401 case QPainterPath::LineToElement: {
402 QPointF pt = (*(QPointF *) points) * state()->matrix;
403 d->activeStroker->lineTo(pt.x(), pt.y());
404 points += 2;
405 ++types;
406 break;
407 }
408 case QPainterPath::CurveToElement: {
409 QPointF c1 = ((QPointF *) points)[0] * state()->matrix;
410 QPointF c2 = ((QPointF *) points)[1] * state()->matrix;
411 QPointF e = ((QPointF *) points)[2] * state()->matrix;
412 d->activeStroker->cubicTo(c1.x(), c1.y(), c2.x(), c2.y(), e.x(), e.y());
413 points += 6;
414 types += 3;
415 flags |= QVectorPath::CurvedShapeHint;
416 break;
417 }
418 default:
419 break;
420 }
421 }
422 if (path.hasImplicitClose()) {
423 QPointF pt = * ((QPointF *) path.points()) * state()->matrix;
424 d->activeStroker->lineTo(pt.x(), pt.y());
425 }
426
427 } else {
428 QPointF p = ((QPointF *)points)[0] * state()->matrix;
429 d->activeStroker->moveTo(p.x(), p.y());
430 points += 2;
431 ++types;
432 while (points < lastPoint) {
433 QPointF p = ((QPointF *)points)[0] * state()->matrix;
434 d->activeStroker->lineTo(p.x(), p.y());
435 points += 2;
436 ++types;
437 }
438 if (path.hasImplicitClose())
439 d->activeStroker->lineTo(p.x(), p.y());
440 }
441
442 d->activeStroker->end();
443 d->stroker.setStrokeWidth(strokeWidth);
444 QVectorPath strokePath(d->strokeHandler->pts.data(),
445 d->strokeHandler->types.size(),
446 d->strokeHandler->types.data(),
447 QVectorPath::WindingFill);
448
449 QTransform xform = state()->matrix;
450 state()->matrix = QTransform();
451 transformChanged();
452
453 QBrush brush = pen.brush();
454 if (qbrush_style(brush) != Qt::SolidPattern)
455 brush.setTransform(brush.transform() * xform);
456
457 fill(strokePath, brush);
458
459 state()->matrix = xform;
460 transformChanged();
461 }
462}
463
464void QPaintEngineEx::draw(const QVectorPath &path)
465{
466 fill(path, state()->brush);
467 stroke(path, state()->pen);
468}
469
470
471void QPaintEngineEx::clip(const QRect &r, Qt::ClipOperation op)
472{
473 qreal right = r.x() + r.width();
474 qreal bottom = r.y() + r.height();
475 qreal pts[] = { r.x(), r.y(),
476 right, r.y(),
477 right, bottom,
478 r.x(), bottom,
479 r.x(), r.y() };
480 QVectorPath vp(pts, 5, 0, QVectorPath::RectangleHint);
481 clip(vp, op);
482}
483
484void QPaintEngineEx::clip(const QRegion &region, Qt::ClipOperation op)
485{
486 QVector<QRect> rects = region.rects();
487 if (rects.size() <= 32) {
488 qreal pts[2*32*4];
489 int pos = 0;
490 for (QVector<QRect>::const_iterator i = rects.constBegin(); i != rects.constEnd(); ++i) {
491 qreal x1 = i->x();
492 qreal y1 = i->y();
493 qreal x2 = i->x() + i->width();
494 qreal y2 = i->y() + i->height();
495
496 pts[pos++] = x1;
497 pts[pos++] = y1;
498
499 pts[pos++] = x2;
500 pts[pos++] = y1;
501
502 pts[pos++] = x2;
503 pts[pos++] = y2;
504
505 pts[pos++] = x1;
506 pts[pos++] = y2;
507 }
508 QVectorPath vp(pts, rects.size() * 4, qpaintengineex_rect4_types_32);
509 clip(vp, op);
510 } else {
511 QVarLengthArray<qreal> pts(rects.size() * 2 * 4);
512 QVarLengthArray<QPainterPath::ElementType> types(rects.size() * 4);
513 int ppos = 0;
514 int tpos = 0;
515
516 for (QVector<QRect>::const_iterator i = rects.constBegin(); i != rects.constEnd(); ++i) {
517 qreal x1 = i->x();
518 qreal y1 = i->y();
519 qreal x2 = i->x() + i->width();
520 qreal y2 = i->y() + i->height();
521
522 pts[ppos++] = x1;
523 pts[ppos++] = y1;
524
525 pts[ppos++] = x2;
526 pts[ppos++] = y1;
527
528 pts[ppos++] = x2;
529 pts[ppos++] = y2;
530
531 pts[ppos++] = x1;
532 pts[ppos++] = y2;
533
534 types[tpos++] = QPainterPath::MoveToElement;
535 types[tpos++] = QPainterPath::LineToElement;
536 types[tpos++] = QPainterPath::LineToElement;
537 types[tpos++] = QPainterPath::LineToElement;
538 }
539
540 QVectorPath vp(pts.data(), rects.size() * 4, types.data());
541 clip(vp, op);
542 }
543
544}
545
546void QPaintEngineEx::clip(const QPainterPath &path, Qt::ClipOperation op)
547{
548 if (path.isEmpty()) {
549 QVectorPath vp(0, 0);
550 clip(vp, op);
551 } else {
552 clip(qtVectorPathForPath(path), op);
553 }
554}
555
556void QPaintEngineEx::fillRect(const QRectF &r, const QBrush &brush)
557{
558 qreal pts[] = { r.x(), r.y(), r.x() + r.width(), r.y(),
559 r.x() + r.width(), r.y() + r.height(), r.x(), r.y() + r.height() };
560 QVectorPath vp(pts, 4, 0, QVectorPath::RectangleHint);
561 fill(vp, brush);
562}
563
564void QPaintEngineEx::fillRect(const QRectF &r, const QColor &color)
565{
566 fillRect(r, QBrush(color));
567}
568
569void QPaintEngineEx::drawRects(const QRect *rects, int rectCount)
570{
571 for (int i=0; i<rectCount; ++i) {
572 const QRect &r = rects[i];
573 // ### Is there a one off here?
574 qreal right = r.x() + r.width();
575 qreal bottom = r.y() + r.height();
576 qreal pts[] = { r.x(), r.y(),
577 right, r.y(),
578 right, bottom,
579 r.x(), bottom,
580 r.x(), r.y() };
581 QVectorPath vp(pts, 5, 0, QVectorPath::RectangleHint);
582 draw(vp);
583 }
584}
585
586void QPaintEngineEx::drawRects(const QRectF *rects, int rectCount)
587{
588 for (int i=0; i<rectCount; ++i) {
589 const QRectF &r = rects[i];
590 qreal right = r.x() + r.width();
591 qreal bottom = r.y() + r.height();
592 qreal pts[] = { r.x(), r.y(),
593 right, r.y(),
594 right, bottom,
595 r.x(), bottom,
596 r.x(), r.y() };
597 QVectorPath vp(pts, 5, 0, QVectorPath::RectangleHint);
598 draw(vp);
599 }
600}
601
602void QPaintEngineEx::drawLines(const QLine *lines, int lineCount)
603{
604 int elementCount = lineCount << 1;
605 while (elementCount > 0) {
606 int count = qMin(elementCount, 32);
607
608 qreal pts[64];
609 int count2 = count<<1;
610#ifdef Q_WS_MAC
611 for (int i=0; i<count2; i+=2) {
612 pts[i] = ((int *) lines)[i+1];
613 pts[i+1] = ((int *) lines)[i];
614 }
615#else
616 for (int i=0; i<count2; ++i)
617 pts[i] = ((int *) lines)[i];
618#endif
619
620 QVectorPath path(pts, count, qpaintengineex_line_types_16, QVectorPath::LinesHint);
621 stroke(path, state()->pen);
622
623 elementCount -= 32;
624 lines += 16;
625 }
626}
627
628void QPaintEngineEx::drawLines(const QLineF *lines, int lineCount)
629{
630 int elementCount = lineCount << 1;
631 while (elementCount > 0) {
632 int count = qMin(elementCount, 32);
633
634 QVectorPath path((qreal *) lines, count, qpaintengineex_line_types_16,
635 QVectorPath::LinesHint);
636 stroke(path, state()->pen);
637
638 elementCount -= 32;
639 lines += 16;
640 }
641}
642
643void QPaintEngineEx::drawEllipse(const QRectF &r)
644{
645 qreal pts[26]; // QPointF[13] without constructors...
646 union {
647 qreal *ptr;
648 QPointF *points;
649 } x;
650 x.ptr = pts;
651
652 int point_count = 0;
653 x.points[0] = qt_curves_for_arc(r, 0, -360, x.points + 1, &point_count);
654 QVectorPath vp((qreal *) pts, 13, qpaintengineex_ellipse_types, QVectorPath::EllipseHint);
655 draw(vp);
656}
657
658void QPaintEngineEx::drawEllipse(const QRect &r)
659{
660 drawEllipse(QRectF(r));
661}
662
663void QPaintEngineEx::drawPath(const QPainterPath &path)
664{
665 if (!path.isEmpty())
666 draw(qtVectorPathForPath(path));
667}
668
669
670void QPaintEngineEx::drawPoints(const QPointF *points, int pointCount)
671{
672 QPen pen = state()->pen;
673 if (pen.capStyle() == Qt::FlatCap)
674 pen.setCapStyle(Qt::SquareCap);
675
676 if (pen.brush().isOpaque()) {
677 while (pointCount > 0) {
678 int count = qMin(pointCount, 16);
679 qreal pts[64];
680 int oset = -1;
681 for (int i=0; i<count; ++i) {
682 pts[++oset] = points[i].x();
683 pts[++oset] = points[i].y();
684 pts[++oset] = points[i].x() + 0.001;
685 pts[++oset] = points[i].y();
686 }
687 QVectorPath path(pts, count * 2, qpaintengineex_line_types_16, QVectorPath::NonCurvedShapeHint);
688 stroke(path, pen);
689 pointCount -= 16;
690 points += 16;
691 }
692 } else {
693 for (int i=0; i<pointCount; ++i) {
694 qreal pts[] = { points[i].x(), points[i].y(), points[i].x() + 0.001, points[i].y() };
695 QVectorPath path(pts, 2, 0);
696 stroke(path, pen);
697 }
698 }
699}
700
701void QPaintEngineEx::drawPoints(const QPoint *points, int pointCount)
702{
703 QPen pen = state()->pen;
704 if (pen.capStyle() == Qt::FlatCap)
705 pen.setCapStyle(Qt::SquareCap);
706
707 if (pen.brush().isOpaque()) {
708 while (pointCount > 0) {
709 int count = qMin(pointCount, 16);
710 qreal pts[64];
711 int oset = -1;
712 for (int i=0; i<count; ++i) {
713 pts[++oset] = points[i].x();
714 pts[++oset] = points[i].y();
715 pts[++oset] = points[i].x() + 0.001;
716 pts[++oset] = points[i].y();
717 }
718 QVectorPath path(pts, count * 2, qpaintengineex_line_types_16, QVectorPath::NonCurvedShapeHint);
719 stroke(path, pen);
720 pointCount -= 16;
721 points += 16;
722 }
723 } else {
724 for (int i=0; i<pointCount; ++i) {
725 qreal pts[] = { points[i].x(), points[i].y(), points[i].x() + 0.001, points[i].y() };
726 QVectorPath path(pts, 2, 0);
727 stroke(path, pen);
728 }
729 }
730}
731
732
733void QPaintEngineEx::drawPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode)
734{
735 QVectorPath path((qreal *) points, pointCount, 0, QVectorPath::polygonFlags(mode));
736
737 if (mode == PolylineMode)
738 stroke(path, state()->pen);
739 else
740 draw(path);
741}
742
743void QPaintEngineEx::drawPolygon(const QPoint *points, int pointCount, PolygonDrawMode mode)
744{
745 int count = pointCount<<1;
746 QVarLengthArray<qreal> pts(count);
747
748#ifdef Q_WS_MAC
749 for (int i=0; i<count; i+=2) {
750 pts[i] = ((int *) points)[i+1];
751 pts[i+1] = ((int *) points)[i];
752 }
753#else
754 for (int i=0; i<count; ++i)
755 pts[i] = ((int *) points)[i];
756#endif
757
758 QVectorPath path(pts.data(), pointCount, 0, QVectorPath::polygonFlags(mode));
759
760 if (mode == PolylineMode)
761 stroke(path, state()->pen);
762 else
763 draw(path);
764
765}
766
767void QPaintEngineEx::drawPixmap(const QPointF &pos, const QPixmap &pm)
768{
769 drawPixmap(QRectF(pos, pm.size()), pm, pm.rect());
770}
771
772void QPaintEngineEx::drawImage(const QPointF &pos, const QImage &image)
773{
774 drawImage(QRectF(pos, image.size()), image, image.rect());
775}
776
777void QPaintEngineEx::drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, const QPointF &s)
778{
779 QBrush brush(state()->pen.color(), pixmap);
780 QTransform xform;
781 xform.translate(-s.x(), -s.y());
782 brush.setTransform(xform);
783
784 qreal pts[] = { r.x(), r.y(),
785 r.x() + r.width(), r.y(),
786 r.x() + r.width(), r.y() + r.height(),
787 r.x(), r.y() + r.height() };
788
789 QVectorPath path(pts, 4, 0, QVectorPath::RectangleHint);
790 fill(path, brush);
791}
792
793void QPaintEngineEx::setState(QPainterState *s)
794{
795 QPaintEngine::state = s;
796}
797
798
799void QPaintEngineEx::updateState(const QPaintEngineState &)
800{
801 // do nothing...
802}
803
804QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.