1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtGui module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40// QtCore
41#include <qdebug.h>
42#include <qmath.h>
43#include <qmutex.h>
44
45// QtGui
46#include "qbitmap.h"
47#include "qimage.h"
48#include "qpaintdevice.h"
49#include "qpaintengine.h"
50#include "qpainter.h"
51#include "qpainter_p.h"
52#include "qpainterpath.h"
53#include "qpicture.h"
54#include "qpixmapcache.h"
55#include "qpolygon.h"
56#include "qtextlayout.h"
57#include "qthread.h"
58#include "qvarlengtharray.h"
59#include "qstatictext.h"
60#include "qglyphrun.h"
61
62#include <qpa/qplatformtheme.h>
63#include <qpa/qplatformintegration.h>
64
65#include <private/qfontengine_p.h>
66#include <private/qpaintengine_p.h>
67#include <private/qemulationpaintengine_p.h>
68#include <private/qpainterpath_p.h>
69#include <private/qtextengine_p.h>
70#include <private/qpaintengine_raster_p.h>
71#include <private/qmath_p.h>
72#include <private/qstatictext_p.h>
73#include <private/qglyphrun_p.h>
74#include <private/qhexstring_p.h>
75#include <private/qguiapplication_p.h>
76#include <private/qrawfont_p.h>
77
78QT_BEGIN_NAMESPACE
79
80#define QGradient_StretchToDevice 0x10000000
81#define QPaintEngine_OpaqueBackground 0x40000000
82
83// #define QT_DEBUG_DRAW
84#ifdef QT_DEBUG_DRAW
85bool qt_show_painter_debug_output = true;
86#endif
87
88extern QPixmap qt_pixmapForBrush(int style, bool invert);
89
90void qt_format_text(const QFont &font,
91 const QRectF &_r, int tf, const QTextOption *option, const QString& str, QRectF *brect,
92 int tabstops, int* tabarray, int tabarraylen,
93 QPainter *painter);
94static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const QFontEngine *fe, QTextEngine *textEngine,
95 QTextCharFormat::UnderlineStyle underlineStyle,
96 QTextItem::RenderFlags flags, qreal width,
97 const QTextCharFormat &charFormat);
98// Helper function to calculate left most position, width and flags for decoration drawing
99Q_GUI_EXPORT void qt_draw_decoration_for_glyphs(QPainter *painter, const glyph_t *glyphArray,
100 const QFixedPoint *positions, int glyphCount,
101 QFontEngine *fontEngine, const QFont &font,
102 const QTextCharFormat &charFormat);
103
104static inline QGradient::CoordinateMode coordinateMode(const QBrush &brush)
105{
106 switch (brush.style()) {
107 case Qt::LinearGradientPattern:
108 case Qt::RadialGradientPattern:
109 case Qt::ConicalGradientPattern:
110 return brush.gradient()->coordinateMode();
111 default:
112 ;
113 }
114 return QGradient::LogicalMode;
115}
116
117extern bool qHasPixmapTexture(const QBrush &);
118
119static inline bool is_brush_transparent(const QBrush &brush) {
120 Qt::BrushStyle s = brush.style();
121 if (s != Qt::TexturePattern)
122 return s >= Qt::Dense1Pattern && s <= Qt::DiagCrossPattern;
123 if (qHasPixmapTexture(brush))
124 return brush.texture().isQBitmap() || brush.texture().hasAlphaChannel();
125 else {
126 const QImage texture = brush.textureImage();
127 return texture.hasAlphaChannel() || (texture.depth() == 1 && texture.colorCount() == 0);
128 }
129}
130
131static inline bool is_pen_transparent(const QPen &pen) {
132 return pen.style() > Qt::SolidLine || is_brush_transparent(pen.brush());
133}
134
135/* Discards the emulation flags that are not relevant for line drawing
136 and returns the result
137*/
138static inline uint line_emulation(uint emulation)
139{
140 return emulation & (QPaintEngine::PrimitiveTransform
141 | QPaintEngine::AlphaBlend
142 | QPaintEngine::Antialiasing
143 | QPaintEngine::BrushStroke
144 | QPaintEngine::ConstantOpacity
145 | QGradient_StretchToDevice
146 | QPaintEngine::ObjectBoundingModeGradients
147 | QPaintEngine_OpaqueBackground);
148}
149
150#ifndef QT_NO_DEBUG
151static bool qt_painter_thread_test(int devType, int engineType, const char *what)
152{
153 const QPlatformIntegration *platformIntegration = QGuiApplicationPrivate::platformIntegration();
154 switch (devType) {
155 case QInternal::Image:
156 case QInternal::Printer:
157 case QInternal::Picture:
158 // can be drawn onto these devices safely from any thread
159 break;
160 default:
161 if (QThread::currentThread() != qApp->thread()
162 // pixmaps cannot be targets unless threaded pixmaps are supported
163 && (devType != QInternal::Pixmap || !platformIntegration->hasCapability(QPlatformIntegration::ThreadedPixmaps))
164 // framebuffer objects and such cannot be targets unless threaded GL is supported
165 && (devType != QInternal::OpenGL || !platformIntegration->hasCapability(QPlatformIntegration::ThreadedOpenGL))
166 // widgets cannot be targets except for QGLWidget
167 && (devType != QInternal::Widget || !platformIntegration->hasCapability(QPlatformIntegration::ThreadedOpenGL)
168 || (engineType != QPaintEngine::OpenGL && engineType != QPaintEngine::OpenGL2))) {
169 qWarning("QPainter: It is not safe to use %s outside the GUI thread", what);
170 return false;
171 }
172 break;
173 }
174 return true;
175}
176#endif
177
178void QPainterPrivate::checkEmulation()
179{
180 Q_ASSERT(extended);
181 bool doEmulation = false;
182 if (state->bgMode == Qt::OpaqueMode)
183 doEmulation = true;
184
185 const QGradient *bg = state->brush.gradient();
186 if (bg && bg->coordinateMode() > QGradient::LogicalMode)
187 doEmulation = true;
188
189 const QGradient *pg = qpen_brush(state->pen).gradient();
190 if (pg && pg->coordinateMode() > QGradient::LogicalMode)
191 doEmulation = true;
192
193 if (state->brush.style() == Qt::TexturePattern) {
194 if (qHasPixmapTexture(state->brush))
195 doEmulation |= !qFuzzyCompare(state->brush.texture().devicePixelRatioF(), 1.0);
196 else
197 doEmulation |= !qFuzzyCompare(state->brush.textureImage().devicePixelRatioF(), 1.0);
198 }
199
200 if (doEmulation && extended->flags() & QPaintEngineEx::DoNotEmulate)
201 return;
202
203 if (doEmulation) {
204 if (extended != emulationEngine) {
205 if (!emulationEngine)
206 emulationEngine = new QEmulationPaintEngine(extended);
207 extended = emulationEngine;
208 extended->setState(state);
209 }
210 } else if (emulationEngine == extended) {
211 extended = emulationEngine->real_engine;
212 }
213}
214
215
216QPainterPrivate::~QPainterPrivate()
217{
218 delete emulationEngine;
219 qDeleteAll(states);
220 delete dummyState;
221}
222
223
224QTransform QPainterPrivate::viewTransform() const
225{
226 if (state->VxF) {
227 qreal scaleW = qreal(state->vw)/qreal(state->ww);
228 qreal scaleH = qreal(state->vh)/qreal(state->wh);
229 return QTransform(scaleW, 0, 0, scaleH,
230 state->vx - state->wx*scaleW, state->vy - state->wy*scaleH);
231 }
232 return QTransform();
233}
234
235qreal QPainterPrivate::effectiveDevicePixelRatio() const
236{
237 // Special cases for devices that does not support PdmDevicePixelRatio go here:
238 if (device->devType() == QInternal::Printer)
239 return qreal(1);
240
241 return qMax(qreal(1), device->devicePixelRatioF());
242}
243
244QTransform QPainterPrivate::hidpiScaleTransform() const
245{
246 const qreal devicePixelRatio = effectiveDevicePixelRatio();
247 return QTransform::fromScale(devicePixelRatio, devicePixelRatio);
248}
249
250/*
251 \internal
252 Returns \c true if using a shared painter; otherwise false.
253*/
254bool QPainterPrivate::attachPainterPrivate(QPainter *q, QPaintDevice *pdev)
255{
256 Q_ASSERT(q);
257 Q_ASSERT(pdev);
258
259 QPainter *sp = pdev->sharedPainter();
260 if (!sp)
261 return false;
262
263 // Save the current state of the shared painter and assign
264 // the current d_ptr to the shared painter's d_ptr.
265 sp->save();
266 if (!sp->d_ptr->d_ptrs) {
267 // Allocate space for 4 d-pointers (enough for up to 4 sub-sequent
268 // redirections within the same paintEvent(), which should be enough
269 // in 99% of all cases). E.g: A renders B which renders C which renders D.
270 sp->d_ptr->d_ptrs_size = 4;
271 sp->d_ptr->d_ptrs = (QPainterPrivate **)malloc(4 * sizeof(QPainterPrivate *));
272 Q_CHECK_PTR(sp->d_ptr->d_ptrs);
273 } else if (sp->d_ptr->refcount - 1 == sp->d_ptr->d_ptrs_size) {
274 // However, to support corner cases we grow the array dynamically if needed.
275 sp->d_ptr->d_ptrs_size <<= 1;
276 const int newSize = sp->d_ptr->d_ptrs_size * sizeof(QPainterPrivate *);
277 sp->d_ptr->d_ptrs = q_check_ptr((QPainterPrivate **)realloc(sp->d_ptr->d_ptrs, newSize));
278 }
279 sp->d_ptr->d_ptrs[++sp->d_ptr->refcount - 2] = q->d_ptr.data();
280 q->d_ptr.take();
281 q->d_ptr.reset(sp->d_ptr.data());
282
283 Q_ASSERT(q->d_ptr->state);
284
285 // Now initialize the painter with correct widget properties.
286 q->d_ptr->initFrom(pdev);
287 QPoint offset;
288 pdev->redirected(&offset);
289 offset += q->d_ptr->engine->coordinateOffset();
290
291 // Update system rect.
292 q->d_ptr->state->ww = q->d_ptr->state->vw = pdev->width();
293 q->d_ptr->state->wh = q->d_ptr->state->vh = pdev->height();
294
295 // Update matrix.
296 if (q->d_ptr->state->WxF) {
297 q->d_ptr->state->redirectionMatrix = q->d_ptr->state->matrix;
298 q->d_ptr->state->redirectionMatrix *= q->d_ptr->hidpiScaleTransform().inverted();
299 q->d_ptr->state->redirectionMatrix.translate(-offset.x(), -offset.y());
300 q->d_ptr->state->worldMatrix = QTransform();
301 q->d_ptr->state->WxF = false;
302 } else {
303 q->d_ptr->state->redirectionMatrix = QTransform::fromTranslate(-offset.x(), -offset.y());
304 }
305 q->d_ptr->updateMatrix();
306
307 QPaintEnginePrivate *enginePrivate = q->d_ptr->engine->d_func();
308 if (enginePrivate->currentClipDevice == pdev) {
309 enginePrivate->systemStateChanged();
310 return true;
311 }
312
313 // Update system transform and clip.
314 enginePrivate->currentClipDevice = pdev;
315 enginePrivate->setSystemTransform(q->d_ptr->state->matrix);
316 return true;
317}
318
319void QPainterPrivate::detachPainterPrivate(QPainter *q)
320{
321 Q_ASSERT(refcount > 1);
322 Q_ASSERT(q);
323
324 QPainterPrivate *original = d_ptrs[--refcount - 1];
325 if (inDestructor) {
326 inDestructor = false;
327 if (original)
328 original->inDestructor = true;
329 } else if (!original) {
330 original = new QPainterPrivate(q);
331 }
332
333 d_ptrs[refcount - 1] = 0;
334 q->restore();
335 q->d_ptr.take();
336 q->d_ptr.reset(original);
337
338 if (emulationEngine) {
339 extended = emulationEngine->real_engine;
340 delete emulationEngine;
341 emulationEngine = 0;
342 }
343}
344
345
346void QPainterPrivate::draw_helper(const QPainterPath &originalPath, DrawOperation op)
347{
348#ifdef QT_DEBUG_DRAW
349 if (qt_show_painter_debug_output) {
350 printf("QPainter::drawHelper\n");
351 }
352#endif
353
354 if (originalPath.isEmpty())
355 return;
356
357 QPaintEngine::PaintEngineFeatures gradientStretch =
358 QPaintEngine::PaintEngineFeatures(QGradient_StretchToDevice
359 | QPaintEngine::ObjectBoundingModeGradients);
360
361 const bool mustEmulateObjectBoundingModeGradients = extended
362 || ((state->emulationSpecifier & QPaintEngine::ObjectBoundingModeGradients)
363 && !engine->hasFeature(QPaintEngine::PatternTransform));
364
365 if (!(state->emulationSpecifier & ~gradientStretch)
366 && !mustEmulateObjectBoundingModeGradients) {
367 drawStretchedGradient(originalPath, op);
368 return;
369 } else if (state->emulationSpecifier & QPaintEngine_OpaqueBackground) {
370 drawOpaqueBackground(originalPath, op);
371 return;
372 }
373
374 Q_Q(QPainter);
375
376 qreal strokeOffsetX = 0, strokeOffsetY = 0;
377
378 QPainterPath path = originalPath * state->matrix;
379 QRectF pathBounds = path.boundingRect();
380 QRectF strokeBounds;
381 bool doStroke = (op & StrokeDraw) && (state->pen.style() != Qt::NoPen);
382 if (doStroke) {
383 qreal penWidth = state->pen.widthF();
384 if (penWidth == 0) {
385 strokeOffsetX = 1;
386 strokeOffsetY = 1;
387 } else {
388 // In case of complex xform
389 if (state->matrix.type() > QTransform::TxScale) {
390 QPainterPathStroker stroker;
391 stroker.setWidth(penWidth);
392 stroker.setJoinStyle(state->pen.joinStyle());
393 stroker.setCapStyle(state->pen.capStyle());
394 QPainterPath stroke = stroker.createStroke(originalPath);
395 strokeBounds = (stroke * state->matrix).boundingRect();
396 } else {
397 strokeOffsetX = qAbs(penWidth * state->matrix.m11() / 2.0);
398 strokeOffsetY = qAbs(penWidth * state->matrix.m22() / 2.0);
399 }
400 }
401 }
402
403 QRect absPathRect;
404 if (!strokeBounds.isEmpty()) {
405 absPathRect = strokeBounds.intersected(QRectF(0, 0, device->width(), device->height())).toAlignedRect();
406 } else {
407 absPathRect = pathBounds.adjusted(-strokeOffsetX, -strokeOffsetY, strokeOffsetX, strokeOffsetY)
408 .intersected(QRectF(0, 0, device->width(), device->height())).toAlignedRect();
409 }
410
411 if (q->hasClipping()) {
412 bool hasPerspectiveTransform = false;
413 for (const QPainterClipInfo &info : qAsConst(state->clipInfo)) {
414 if (info.matrix.type() == QTransform::TxProject) {
415 hasPerspectiveTransform = true;
416 break;
417 }
418 }
419 // avoid mapping QRegions with perspective transforms
420 if (!hasPerspectiveTransform) {
421 // The trick with txinv and invMatrix is done in order to
422 // avoid transforming the clip to logical coordinates, and
423 // then back to device coordinates. This is a problem with
424 // QRegion/QRect based clips, since they use integer
425 // coordinates and converting to/from logical coordinates will
426 // lose precision.
427 bool old_txinv = txinv;
428 QTransform old_invMatrix = invMatrix;
429 txinv = true;
430 invMatrix = QTransform();
431 QPainterPath clipPath = q->clipPath();
432 QRectF r = clipPath.boundingRect().intersected(absPathRect);
433 absPathRect = r.toAlignedRect();
434 txinv = old_txinv;
435 invMatrix = old_invMatrix;
436 }
437 }
438
439// qDebug("\nQPainterPrivate::draw_helper(), x=%d, y=%d, w=%d, h=%d",
440// devMinX, devMinY, device->width(), device->height());
441// qDebug() << " - matrix" << state->matrix;
442// qDebug() << " - originalPath.bounds" << originalPath.boundingRect();
443// qDebug() << " - path.bounds" << path.boundingRect();
444
445 if (absPathRect.width() <= 0 || absPathRect.height() <= 0)
446 return;
447
448 QImage image(absPathRect.width(), absPathRect.height(), QImage::Format_ARGB32_Premultiplied);
449 image.fill(0);
450
451 QPainter p(&image);
452
453 p.d_ptr->helper_device = helper_device;
454
455 p.setOpacity(state->opacity);
456 p.translate(-absPathRect.x(), -absPathRect.y());
457 p.setTransform(state->matrix, true);
458 p.setPen(doStroke ? state->pen : QPen(Qt::NoPen));
459 p.setBrush((op & FillDraw) ? state->brush : QBrush(Qt::NoBrush));
460 p.setBackground(state->bgBrush);
461 p.setBackgroundMode(state->bgMode);
462 p.setBrushOrigin(state->brushOrigin);
463
464 p.setRenderHint(QPainter::Antialiasing, state->renderHints & QPainter::Antialiasing);
465 p.setRenderHint(QPainter::SmoothPixmapTransform,
466 state->renderHints & QPainter::SmoothPixmapTransform);
467
468 p.drawPath(originalPath);
469
470#ifndef QT_NO_DEBUG
471 static bool do_fallback_overlay = !qEnvironmentVariableIsEmpty("QT_PAINT_FALLBACK_OVERLAY");
472 if (do_fallback_overlay) {
473 QImage block(8, 8, QImage::Format_ARGB32_Premultiplied);
474 QPainter pt(&block);
475 pt.fillRect(0, 0, 8, 8, QColor(196, 0, 196));
476 pt.drawLine(0, 0, 8, 8);
477 pt.end();
478 p.resetTransform();
479 p.setCompositionMode(QPainter::CompositionMode_SourceAtop);
480 p.setOpacity(0.5);
481 p.fillRect(0, 0, image.width(), image.height(), QBrush(block));
482 }
483#endif
484
485 p.end();
486
487 q->save();
488 state->matrix = QTransform();
489 if (extended) {
490 extended->transformChanged();
491 } else {
492 state->dirtyFlags |= QPaintEngine::DirtyTransform;
493 updateState(state);
494 }
495 engine->drawImage(absPathRect,
496 image,
497 QRectF(0, 0, absPathRect.width(), absPathRect.height()),
498 Qt::OrderedDither | Qt::OrderedAlphaDither);
499 q->restore();
500}
501
502void QPainterPrivate::drawOpaqueBackground(const QPainterPath &path, DrawOperation op)
503{
504 Q_Q(QPainter);
505
506 q->setBackgroundMode(Qt::TransparentMode);
507
508 if (op & FillDraw && state->brush.style() != Qt::NoBrush) {
509 q->fillPath(path, state->bgBrush.color());
510 q->fillPath(path, state->brush);
511 }
512
513 if (op & StrokeDraw && state->pen.style() != Qt::NoPen) {
514 q->strokePath(path, QPen(state->bgBrush.color(), state->pen.width()));
515 q->strokePath(path, state->pen);
516 }
517
518 q->setBackgroundMode(Qt::OpaqueMode);
519}
520
521static inline QBrush stretchGradientToUserSpace(const QBrush &brush, const QRectF &boundingRect)
522{
523 Q_ASSERT(brush.style() >= Qt::LinearGradientPattern
524 && brush.style() <= Qt::ConicalGradientPattern);
525
526 QTransform gradientToUser(boundingRect.width(), 0, 0, boundingRect.height(),
527 boundingRect.x(), boundingRect.y());
528
529 QGradient g = *brush.gradient();
530 g.setCoordinateMode(QGradient::LogicalMode);
531
532 QBrush b(g);
533 if (brush.gradient()->coordinateMode() == QGradient::ObjectMode)
534 b.setTransform(b.transform() * gradientToUser);
535 else
536 b.setTransform(gradientToUser * b.transform());
537 return b;
538}
539
540void QPainterPrivate::drawStretchedGradient(const QPainterPath &path, DrawOperation op)
541{
542 Q_Q(QPainter);
543
544 const qreal sw = helper_device->width();
545 const qreal sh = helper_device->height();
546
547 bool changedPen = false;
548 bool changedBrush = false;
549 bool needsFill = false;
550
551 const QPen pen = state->pen;
552 const QBrush brush = state->brush;
553
554 const QGradient::CoordinateMode penMode = coordinateMode(pen.brush());
555 const QGradient::CoordinateMode brushMode = coordinateMode(brush);
556
557 QRectF boundingRect;
558
559 // Draw the xformed fill if the brush is a stretch gradient.
560 if ((op & FillDraw) && brush.style() != Qt::NoBrush) {
561 if (brushMode == QGradient::StretchToDeviceMode) {
562 q->setPen(Qt::NoPen);
563 changedPen = pen.style() != Qt::NoPen;
564 q->scale(sw, sh);
565 updateState(state);
566
567 const qreal isw = 1.0 / sw;
568 const qreal ish = 1.0 / sh;
569 QTransform inv(isw, 0, 0, ish, 0, 0);
570 engine->drawPath(path * inv);
571 q->scale(isw, ish);
572 } else {
573 needsFill = true;
574
575 if (brushMode == QGradient::ObjectBoundingMode || brushMode == QGradient::ObjectMode) {
576 Q_ASSERT(engine->hasFeature(QPaintEngine::PatternTransform));
577 boundingRect = path.boundingRect();
578 q->setBrush(stretchGradientToUserSpace(brush, boundingRect));
579 changedBrush = true;
580 }
581 }
582 }
583
584 if ((op & StrokeDraw) && pen.style() != Qt::NoPen) {
585 // Draw the xformed outline if the pen is a stretch gradient.
586 if (penMode == QGradient::StretchToDeviceMode) {
587 q->setPen(Qt::NoPen);
588 changedPen = true;
589
590 if (needsFill) {
591 updateState(state);
592 engine->drawPath(path);
593 }
594
595 q->scale(sw, sh);
596 q->setBrush(pen.brush());
597 changedBrush = true;
598 updateState(state);
599
600 QPainterPathStroker stroker;
601 stroker.setDashPattern(pen.style());
602 stroker.setWidth(pen.widthF());
603 stroker.setJoinStyle(pen.joinStyle());
604 stroker.setCapStyle(pen.capStyle());
605 stroker.setMiterLimit(pen.miterLimit());
606 QPainterPath stroke = stroker.createStroke(path);
607
608 const qreal isw = 1.0 / sw;
609 const qreal ish = 1.0 / sh;
610 QTransform inv(isw, 0, 0, ish, 0, 0);
611 engine->drawPath(stroke * inv);
612 q->scale(isw, ish);
613 } else {
614 if (!needsFill && brush.style() != Qt::NoBrush) {
615 q->setBrush(Qt::NoBrush);
616 changedBrush = true;
617 }
618
619 if (penMode == QGradient::ObjectBoundingMode || penMode == QGradient::ObjectMode) {
620 Q_ASSERT(engine->hasFeature(QPaintEngine::PatternTransform));
621
622 // avoid computing the bounding rect twice
623 if (!needsFill || (brushMode != QGradient::ObjectBoundingMode && brushMode != QGradient::ObjectMode))
624 boundingRect = path.boundingRect();
625
626 QPen p = pen;
627 p.setBrush(stretchGradientToUserSpace(pen.brush(), boundingRect));
628 q->setPen(p);
629 changedPen = true;
630 } else if (changedPen) {
631 q->setPen(pen);
632 changedPen = false;
633 }
634
635 updateState(state);
636 engine->drawPath(path);
637 }
638 } else if (needsFill) {
639 if (pen.style() != Qt::NoPen) {
640 q->setPen(Qt::NoPen);
641 changedPen = true;
642 }
643
644 updateState(state);
645 engine->drawPath(path);
646 }
647
648 if (changedPen)
649 q->setPen(pen);
650 if (changedBrush)
651 q->setBrush(brush);
652}
653
654
655void QPainterPrivate::updateMatrix()
656{
657 state->matrix = state->WxF ? state->worldMatrix : QTransform();
658 if (state->VxF)
659 state->matrix *= viewTransform();
660
661 txinv = false; // no inverted matrix
662 state->matrix *= state->redirectionMatrix;
663 if (extended)
664 extended->transformChanged();
665 else
666 state->dirtyFlags |= QPaintEngine::DirtyTransform;
667
668 state->matrix *= hidpiScaleTransform();
669
670// printf("VxF=%d, WxF=%d\n", state->VxF, state->WxF);
671// qDebug() << " --- using matrix" << state->matrix << redirection_offset;
672}
673
674/*! \internal */
675void QPainterPrivate::updateInvMatrix()
676{
677 Q_ASSERT(txinv == false);
678 txinv = true; // creating inverted matrix
679 invMatrix = state->matrix.inverted();
680}
681
682extern bool qt_isExtendedRadialGradient(const QBrush &brush);
683
684void QPainterPrivate::updateEmulationSpecifier(QPainterState *s)
685{
686 bool alpha = false;
687 bool linearGradient = false;
688 bool radialGradient = false;
689 bool extendedRadialGradient = false;
690 bool conicalGradient = false;
691 bool patternBrush = false;
692 bool xform = false;
693 bool complexXform = false;
694
695 bool skip = true;
696
697 // Pen and brush properties (we have to check both if one changes because the
698 // one that's unchanged can still be in a state which requires emulation)
699 if (s->state() & (QPaintEngine::DirtyPen | QPaintEngine::DirtyBrush | QPaintEngine::DirtyHints)) {
700 // Check Brush stroke emulation
701 if (!s->pen.isSolid() && !engine->hasFeature(QPaintEngine::BrushStroke))
702 s->emulationSpecifier |= QPaintEngine::BrushStroke;
703 else
704 s->emulationSpecifier &= ~QPaintEngine::BrushStroke;
705
706 skip = false;
707
708 QBrush penBrush = (qpen_style(s->pen) == Qt::NoPen) ? QBrush(Qt::NoBrush) : qpen_brush(s->pen);
709 Qt::BrushStyle brushStyle = qbrush_style(s->brush);
710 Qt::BrushStyle penBrushStyle = qbrush_style(penBrush);
711 alpha = (penBrushStyle != Qt::NoBrush
712 && (penBrushStyle < Qt::LinearGradientPattern && penBrush.color().alpha() != 255)
713 && !penBrush.isOpaque())
714 || (brushStyle != Qt::NoBrush
715 && (brushStyle < Qt::LinearGradientPattern && s->brush.color().alpha() != 255)
716 && !s->brush.isOpaque());
717 linearGradient = ((penBrushStyle == Qt::LinearGradientPattern) ||
718 (brushStyle == Qt::LinearGradientPattern));
719 radialGradient = ((penBrushStyle == Qt::RadialGradientPattern) ||
720 (brushStyle == Qt::RadialGradientPattern));
721 extendedRadialGradient = radialGradient && (qt_isExtendedRadialGradient(penBrush) || qt_isExtendedRadialGradient(s->brush));
722 conicalGradient = ((penBrushStyle == Qt::ConicalGradientPattern) ||
723 (brushStyle == Qt::ConicalGradientPattern));
724 patternBrush = (((penBrushStyle > Qt::SolidPattern
725 && penBrushStyle < Qt::LinearGradientPattern)
726 || penBrushStyle == Qt::TexturePattern) ||
727 ((brushStyle > Qt::SolidPattern
728 && brushStyle < Qt::LinearGradientPattern)
729 || brushStyle == Qt::TexturePattern));
730
731 bool penTextureAlpha = false;
732 if (penBrush.style() == Qt::TexturePattern)
733 penTextureAlpha = qHasPixmapTexture(penBrush)
734 ? (penBrush.texture().depth() > 1) && penBrush.texture().hasAlpha()
735 : penBrush.textureImage().hasAlphaChannel();
736 bool brushTextureAlpha = false;
737 if (s->brush.style() == Qt::TexturePattern) {
738 brushTextureAlpha = qHasPixmapTexture(s->brush)
739 ? (s->brush.texture().depth() > 1) && s->brush.texture().hasAlpha()
740 : s->brush.textureImage().hasAlphaChannel();
741 }
742 if (((penBrush.style() == Qt::TexturePattern && penTextureAlpha)
743 || (s->brush.style() == Qt::TexturePattern && brushTextureAlpha))
744 && !engine->hasFeature(QPaintEngine::MaskedBrush))
745 s->emulationSpecifier |= QPaintEngine::MaskedBrush;
746 else
747 s->emulationSpecifier &= ~QPaintEngine::MaskedBrush;
748 }
749
750 if (s->state() & (QPaintEngine::DirtyHints
751 | QPaintEngine::DirtyOpacity
752 | QPaintEngine::DirtyBackgroundMode)) {
753 skip = false;
754 }
755
756 if (skip)
757 return;
758
759#if 0
760 qDebug("QPainterPrivate::updateEmulationSpecifier, state=%p\n"
761 " - alpha: %d\n"
762 " - linearGradient: %d\n"
763 " - radialGradient: %d\n"
764 " - conicalGradient: %d\n"
765 " - patternBrush: %d\n"
766 " - hints: %x\n"
767 " - xform: %d\n",
768 s,
769 alpha,
770 linearGradient,
771 radialGradient,
772 conicalGradient,
773 patternBrush,
774 uint(s->renderHints),
775 xform);
776#endif
777
778 // XForm properties
779 if (s->state() & QPaintEngine::DirtyTransform) {
780 xform = !s->matrix.isIdentity();
781 complexXform = !s->matrix.isAffine();
782 } else if (s->matrix.type() >= QTransform::TxTranslate) {
783 xform = true;
784 complexXform = !s->matrix.isAffine();
785 }
786
787 const bool brushXform = (s->brush.transform().type() != QTransform::TxNone);
788 const bool penXform = (s->pen.brush().transform().type() != QTransform::TxNone);
789
790 const bool patternXform = patternBrush && (xform || brushXform || penXform);
791
792 // Check alphablending
793 if (alpha && !engine->hasFeature(QPaintEngine::AlphaBlend))
794 s->emulationSpecifier |= QPaintEngine::AlphaBlend;
795 else
796 s->emulationSpecifier &= ~QPaintEngine::AlphaBlend;
797
798 // Linear gradient emulation
799 if (linearGradient && !engine->hasFeature(QPaintEngine::LinearGradientFill))
800 s->emulationSpecifier |= QPaintEngine::LinearGradientFill;
801 else
802 s->emulationSpecifier &= ~QPaintEngine::LinearGradientFill;
803
804 // Radial gradient emulation
805 if (extendedRadialGradient || (radialGradient && !engine->hasFeature(QPaintEngine::RadialGradientFill)))
806 s->emulationSpecifier |= QPaintEngine::RadialGradientFill;
807 else
808 s->emulationSpecifier &= ~QPaintEngine::RadialGradientFill;
809
810 // Conical gradient emulation
811 if (conicalGradient && !engine->hasFeature(QPaintEngine::ConicalGradientFill))
812 s->emulationSpecifier |= QPaintEngine::ConicalGradientFill;
813 else
814 s->emulationSpecifier &= ~QPaintEngine::ConicalGradientFill;
815
816 // Pattern brushes
817 if (patternBrush && !engine->hasFeature(QPaintEngine::PatternBrush))
818 s->emulationSpecifier |= QPaintEngine::PatternBrush;
819 else
820 s->emulationSpecifier &= ~QPaintEngine::PatternBrush;
821
822 // Pattern XForms
823 if (patternXform && !engine->hasFeature(QPaintEngine::PatternTransform))
824 s->emulationSpecifier |= QPaintEngine::PatternTransform;
825 else
826 s->emulationSpecifier &= ~QPaintEngine::PatternTransform;
827
828 // Primitive XForms
829 if (xform && !engine->hasFeature(QPaintEngine::PrimitiveTransform))
830 s->emulationSpecifier |= QPaintEngine::PrimitiveTransform;
831 else
832 s->emulationSpecifier &= ~QPaintEngine::PrimitiveTransform;
833
834 // Perspective XForms
835 if (complexXform && !engine->hasFeature(QPaintEngine::PerspectiveTransform))
836 s->emulationSpecifier |= QPaintEngine::PerspectiveTransform;
837 else
838 s->emulationSpecifier &= ~QPaintEngine::PerspectiveTransform;
839
840 // Constant opacity
841 if (state->opacity != 1 && !engine->hasFeature(QPaintEngine::ConstantOpacity))
842 s->emulationSpecifier |= QPaintEngine::ConstantOpacity;
843 else
844 s->emulationSpecifier &= ~QPaintEngine::ConstantOpacity;
845
846 bool gradientStretch = false;
847 bool objectBoundingMode = false;
848 if (linearGradient || conicalGradient || radialGradient) {
849 QGradient::CoordinateMode brushMode = coordinateMode(s->brush);
850 QGradient::CoordinateMode penMode = coordinateMode(s->pen.brush());
851
852 gradientStretch |= (brushMode == QGradient::StretchToDeviceMode);
853 gradientStretch |= (penMode == QGradient::StretchToDeviceMode);
854
855 objectBoundingMode |= (brushMode == QGradient::ObjectBoundingMode || brushMode == QGradient::ObjectMode);
856 objectBoundingMode |= (penMode == QGradient::ObjectBoundingMode || penMode == QGradient::ObjectMode);
857 }
858 if (gradientStretch)
859 s->emulationSpecifier |= QGradient_StretchToDevice;
860 else
861 s->emulationSpecifier &= ~QGradient_StretchToDevice;
862
863 if (objectBoundingMode && !engine->hasFeature(QPaintEngine::ObjectBoundingModeGradients))
864 s->emulationSpecifier |= QPaintEngine::ObjectBoundingModeGradients;
865 else
866 s->emulationSpecifier &= ~QPaintEngine::ObjectBoundingModeGradients;
867
868 // Opaque backgrounds...
869 if (s->bgMode == Qt::OpaqueMode &&
870 (is_pen_transparent(s->pen) || is_brush_transparent(s->brush)))
871 s->emulationSpecifier |= QPaintEngine_OpaqueBackground;
872 else
873 s->emulationSpecifier &= ~QPaintEngine_OpaqueBackground;
874
875#if 0
876 //won't be correct either way because the device can already have
877 // something rendered to it in which case subsequent emulation
878 // on a fully transparent qimage and then blitting the results
879 // won't produce correct results
880 // Blend modes
881 if (state->composition_mode > QPainter::CompositionMode_Xor &&
882 !engine->hasFeature(QPaintEngine::BlendModes))
883 s->emulationSpecifier |= QPaintEngine::BlendModes;
884 else
885 s->emulationSpecifier &= ~QPaintEngine::BlendModes;
886#endif
887}
888
889void QPainterPrivate::updateStateImpl(QPainterState *newState)
890{
891 // ### we might have to call QPainter::begin() here...
892 if (!engine->state) {
893 engine->state = newState;
894 engine->setDirty(QPaintEngine::AllDirty);
895 }
896
897 if (engine->state->painter() != newState->painter)
898 // ### this could break with clip regions vs paths.
899 engine->setDirty(QPaintEngine::AllDirty);
900
901 // Upon restore, revert all changes since last save
902 else if (engine->state != newState)
903 newState->dirtyFlags |= QPaintEngine::DirtyFlags(static_cast<QPainterState *>(engine->state)->changeFlags);
904
905 // We need to store all changes made so that restore can deal with them
906 else
907 newState->changeFlags |= newState->dirtyFlags;
908
909 updateEmulationSpecifier(newState);
910
911 // Unset potential dirty background mode
912 newState->dirtyFlags &= ~(QPaintEngine::DirtyBackgroundMode
913 | QPaintEngine::DirtyBackground);
914
915 engine->state = newState;
916 engine->updateState(*newState);
917 engine->clearDirty(QPaintEngine::AllDirty);
918
919}
920
921void QPainterPrivate::updateState(QPainterState *newState)
922{
923
924 if (!newState) {
925 engine->state = newState;
926 } else if (newState->state() || engine->state!=newState) {
927 updateStateImpl(newState);
928 }
929}
930
931
932/*!
933 \class QPainter
934 \brief The QPainter class performs low-level painting on widgets and
935 other paint devices.
936
937 \inmodule QtGui
938 \ingroup painting
939
940 \reentrant
941
942 QPainter provides highly optimized functions to do most of the
943 drawing GUI programs require. It can draw everything from simple
944 lines to complex shapes like pies and chords. It can also draw
945 aligned text and pixmaps. Normally, it draws in a "natural"
946 coordinate system, but it can also do view and world
947 transformation. QPainter can operate on any object that inherits
948 the QPaintDevice class.
949
950 The common use of QPainter is inside a widget's paint event:
951 Construct and customize (e.g. set the pen or the brush) the
952 painter. Then draw. Remember to destroy the QPainter object after
953 drawing. For example:
954
955 \snippet code/src_gui_painting_qpainter.cpp 0
956
957 The core functionality of QPainter is drawing, but the class also
958 provide several functions that allows you to customize QPainter's
959 settings and its rendering quality, and others that enable
960 clipping. In addition you can control how different shapes are
961 merged together by specifying the painter's composition mode.
962
963 The isActive() function indicates whether the painter is active. A
964 painter is activated by the begin() function and the constructor
965 that takes a QPaintDevice argument. The end() function, and the
966 destructor, deactivates it.
967
968 Together with the QPaintDevice and QPaintEngine classes, QPainter
969 form the basis for Qt's paint system. QPainter is the class used
970 to perform drawing operations. QPaintDevice represents a device
971 that can be painted on using a QPainter. QPaintEngine provides the
972 interface that the painter uses to draw onto different types of
973 devices. If the painter is active, device() returns the paint
974 device on which the painter paints, and paintEngine() returns the
975 paint engine that the painter is currently operating on. For more
976 information, see the \l {Paint System}.
977
978 Sometimes it is desirable to make someone else paint on an unusual
979 QPaintDevice. QPainter supports a static function to do this,
980 setRedirected().
981
982 \warning When the paintdevice is a widget, QPainter can only be
983 used inside a paintEvent() function or in a function called by
984 paintEvent().
985
986 \tableofcontents
987
988 \section1 Settings
989
990 There are several settings that you can customize to make QPainter
991 draw according to your preferences:
992
993 \list
994
995 \li font() is the font used for drawing text. If the painter
996 isActive(), you can retrieve information about the currently set
997 font, and its metrics, using the fontInfo() and fontMetrics()
998 functions respectively.
999
1000 \li brush() defines the color or pattern that is used for filling
1001 shapes.
1002
1003 \li pen() defines the color or stipple that is used for drawing
1004 lines or boundaries.
1005
1006 \li backgroundMode() defines whether there is a background() or
1007 not, i.e it is either Qt::OpaqueMode or Qt::TransparentMode.
1008
1009 \li background() only applies when backgroundMode() is \l
1010 Qt::OpaqueMode and pen() is a stipple. In that case, it
1011 describes the color of the background pixels in the stipple.
1012
1013 \li brushOrigin() defines the origin of the tiled brushes, normally
1014 the origin of widget's background.
1015
1016 \li viewport(), window(), worldTransform() make up the painter's coordinate
1017 transformation system. For more information, see the \l
1018 {Coordinate Transformations} section and the \l {Coordinate
1019 System} documentation.
1020
1021 \li hasClipping() tells whether the painter clips at all. (The paint
1022 device clips, too.) If the painter clips, it clips to clipRegion().
1023
1024 \li layoutDirection() defines the layout direction used by the
1025 painter when drawing text.
1026
1027 \li worldMatrixEnabled() tells whether world transformation is enabled.
1028
1029 \li viewTransformEnabled() tells whether view transformation is
1030 enabled.
1031
1032 \endlist
1033
1034 Note that some of these settings mirror settings in some paint
1035 devices, e.g. QWidget::font(). The QPainter::begin() function (or
1036 equivalently the QPainter constructor) copies these attributes
1037 from the paint device.
1038
1039 You can at any time save the QPainter's state by calling the
1040 save() function which saves all the available settings on an
1041 internal stack. The restore() function pops them back.
1042
1043 \section1 Drawing
1044
1045 QPainter provides functions to draw most primitives: drawPoint(),
1046 drawPoints(), drawLine(), drawRect(), drawRoundedRect(),
1047 drawEllipse(), drawArc(), drawPie(), drawChord(), drawPolyline(),
1048 drawPolygon(), drawConvexPolygon() and drawCubicBezier(). The two
1049 convenience functions, drawRects() and drawLines(), draw the given
1050 number of rectangles or lines in the given array of \l
1051 {QRect}{QRects} or \l {QLine}{QLines} using the current pen and
1052 brush.
1053
1054 The QPainter class also provides the fillRect() function which
1055 fills the given QRect, with the given QBrush, and the eraseRect()
1056 function that erases the area inside the given rectangle.
1057
1058 All of these functions have both integer and floating point
1059 versions.
1060
1061 \table 100%
1062 \row
1063 \li \inlineimage qpainter-basicdrawing.png
1064 \li
1065 \b {Basic Drawing Example}
1066
1067 The \l {painting/basicdrawing}{Basic Drawing} example shows how to
1068 display basic graphics primitives in a variety of styles using the
1069 QPainter class.
1070
1071 \endtable
1072
1073 If you need to draw a complex shape, especially if you need to do
1074 so repeatedly, consider creating a QPainterPath and drawing it
1075 using drawPath().
1076
1077 \table 100%
1078 \row
1079 \li
1080 \b {Painter Paths example}
1081
1082 The QPainterPath class provides a container for painting
1083 operations, enabling graphical shapes to be constructed and
1084 reused.
1085
1086 The \l {painting/painterpaths}{Painter Paths} example shows how
1087 painter paths can be used to build complex shapes for rendering.
1088
1089 \li \inlineimage qpainter-painterpaths.png
1090 \endtable
1091
1092 QPainter also provides the fillPath() function which fills the
1093 given QPainterPath with the given QBrush, and the strokePath()
1094 function that draws the outline of the given path (i.e. strokes
1095 the path).
1096
1097 See also the \l {painting/deform}{Vector Deformation} example which
1098 shows how to use advanced vector techniques to draw text using a
1099 QPainterPath, the \l {painting/gradients}{Gradients} example which shows
1100 the different types of gradients that are available in Qt, and the \l
1101 {painting/pathstroke}{Path Stroking} example which shows Qt's built-in
1102 dash patterns and shows how custom patterns can be used to extend
1103 the range of available patterns.
1104
1105 \table
1106 \header
1107 \li \l {painting/deform}{Vector Deformation}
1108 \li \l {painting/gradients}{Gradients}
1109 \li \l {painting/pathstroke}{Path Stroking}
1110 \row
1111 \li \inlineimage qpainter-vectordeformation.png
1112 \li \inlineimage qpainter-gradients.png
1113 \li \inlineimage qpainter-pathstroking.png
1114 \endtable
1115
1116 Text drawing is done using drawText(). When you need
1117 fine-grained positioning, boundingRect() tells you where a given
1118 drawText() command will draw.
1119
1120 \section1 Drawing Pixmaps and Images
1121
1122 There are functions to draw pixmaps/images, namely drawPixmap(),
1123 drawImage() and drawTiledPixmap(). Both drawPixmap() and drawImage()
1124 produce the same result, except that drawPixmap() is faster
1125 on-screen while drawImage() may be faster on a QPrinter or other
1126 devices.
1127
1128 There is a drawPicture() function that draws the contents of an
1129 entire QPicture. The drawPicture() function is the only function
1130 that disregards all the painter's settings as QPicture has its own
1131 settings.
1132
1133 \section2 Drawing High Resolution Versions of Pixmaps and Images
1134
1135 High resolution versions of pixmaps have a \e{device pixel ratio} value larger
1136 than 1 (see QImageReader, QPixmap::devicePixelRatio()). Should it match the value
1137 of the underlying QPaintDevice, it is drawn directly onto the device with no
1138 additional transformation applied.
1139
1140 This is for example the case when drawing a QPixmap of 64x64 pixels size with
1141 a device pixel ratio of 2 onto a high DPI screen which also has
1142 a device pixel ratio of 2. Note that the pixmap is then effectively 32x32
1143 pixels in \e{user space}. Code paths in Qt that calculate layout geometry
1144 based on the pixmap size will use this size. The net effect of this is that
1145 the pixmap is displayed as high DPI pixmap rather than a large pixmap.
1146
1147 \section1 Rendering Quality
1148
1149 To get the optimal rendering result using QPainter, you should use
1150 the platform independent QImage as paint device; i.e. using QImage
1151 will ensure that the result has an identical pixel representation
1152 on any platform.
1153
1154 The QPainter class also provides a means of controlling the
1155 rendering quality through its RenderHint enum and the support for
1156 floating point precision: All the functions for drawing primitives
1157 has a floating point version. These are often used in combination
1158 with the \l {RenderHint}{QPainter::Antialiasing} render hint.
1159
1160 \table 100%
1161 \row
1162 \li \inlineimage qpainter-concentriccircles.png
1163 \li
1164 \b {Concentric Circles Example}
1165
1166 The \l {painting/concentriccircles}{Concentric Circles} example
1167 shows the improved rendering quality that can be obtained using
1168 floating point precision and anti-aliasing when drawing custom
1169 widgets.
1170
1171 The application's main window displays several widgets which are
1172 drawn using the various combinations of precision and
1173 anti-aliasing.
1174
1175 \endtable
1176
1177 The RenderHint enum specifies flags to QPainter that may or may
1178 not be respected by any given engine. \l
1179 {RenderHint}{QPainter::Antialiasing} indicates that the engine
1180 should antialias edges of primitives if possible, \l
1181 {RenderHint}{QPainter::TextAntialiasing} indicates that the engine
1182 should antialias text if possible, and the \l
1183 {RenderHint}{QPainter::SmoothPixmapTransform} indicates that the
1184 engine should use a smooth pixmap transformation algorithm.
1185
1186 The renderHints() function returns a flag that specifies the
1187 rendering hints that are set for this painter. Use the
1188 setRenderHint() function to set or clear the currently set
1189 RenderHints.
1190
1191 \section1 Coordinate Transformations
1192
1193 Normally, the QPainter operates on the device's own coordinate
1194 system (usually pixels), but QPainter has good support for
1195 coordinate transformations.
1196
1197 \table
1198 \header
1199 \li nop \li rotate() \li scale() \li translate()
1200 \row
1201 \li \inlineimage qpainter-clock.png
1202 \li \inlineimage qpainter-rotation.png
1203 \li \inlineimage qpainter-scale.png
1204 \li \inlineimage qpainter-translation.png
1205 \endtable
1206
1207 The most commonly used transformations are scaling, rotation,
1208 translation and shearing. Use the scale() function to scale the
1209 coordinate system by a given offset, the rotate() function to
1210 rotate it clockwise and translate() to translate it (i.e. adding a
1211 given offset to the points). You can also twist the coordinate
1212 system around the origin using the shear() function. See the \l
1213 {painting/affine}{Affine Transformations} example for a visualization of
1214 a sheared coordinate system.
1215
1216 See also the \l {painting/transformations}{Transformations}
1217 example which shows how transformations influence the way that
1218 QPainter renders graphics primitives. In particular it shows how
1219 the order of transformations affects the result.
1220
1221 \table 100%
1222 \row
1223 \li
1224 \b {Affine Transformations Example}
1225
1226 The \l {painting/affine}{Affine Transformations} example shows Qt's
1227 ability to perform affine transformations on painting
1228 operations. The demo also allows the user to experiment with the
1229 transformation operations and see the results immediately.
1230
1231 \li \inlineimage qpainter-affinetransformations.png
1232 \endtable
1233
1234 All the tranformation operations operate on the transformation
1235 worldTransform(). A matrix transforms a point in the plane to another
1236 point. For more information about the transformation matrix, see
1237 the \l {Coordinate System} and QTransform documentation.
1238
1239 The setWorldTransform() function can replace or add to the currently
1240 set worldTransform(). The resetTransform() function resets any
1241 transformations that were made using translate(), scale(),
1242 shear(), rotate(), setWorldTransform(), setViewport() and setWindow()
1243 functions. The deviceTransform() returns the matrix that transforms
1244 from logical coordinates to device coordinates of the platform
1245 dependent paint device. The latter function is only needed when
1246 using platform painting commands on the platform dependent handle,
1247 and the platform does not do transformations nativly.
1248
1249 When drawing with QPainter, we specify points using logical
1250 coordinates which then are converted into the physical coordinates
1251 of the paint device. The mapping of the logical coordinates to the
1252 physical coordinates are handled by QPainter's combinedTransform(), a
1253 combination of viewport() and window() and worldTransform(). The
1254 viewport() represents the physical coordinates specifying an
1255 arbitrary rectangle, the window() describes the same rectangle in
1256 logical coordinates, and the worldTransform() is identical with the
1257 transformation matrix.
1258
1259 See also \l {Coordinate System}
1260
1261 \section1 Clipping
1262
1263 QPainter can clip any drawing operation to a rectangle, a region,
1264 or a vector path. The current clip is available using the
1265 functions clipRegion() and clipPath(). Whether paths or regions are
1266 preferred (faster) depends on the underlying paintEngine(). For
1267 example, the QImage paint engine prefers paths while the X11 paint
1268 engine prefers regions. Setting a clip is done in the painters
1269 logical coordinates.
1270
1271 After QPainter's clipping, the paint device may also clip. For
1272 example, most widgets clip away the pixels used by child widgets,
1273 and most printers clip away an area near the edges of the paper.
1274 This additional clipping is not reflected by the return value of
1275 clipRegion() or hasClipping().
1276
1277 \section1 Composition Modes
1278 \target Composition Modes
1279
1280 QPainter provides the CompositionMode enum which defines the
1281 Porter-Duff rules for digital image compositing; it describes a
1282 model for combining the pixels in one image, the source, with the
1283 pixels in another image, the destination.
1284
1285 The two most common forms of composition are \l
1286 {QPainter::CompositionMode}{Source} and \l
1287 {QPainter::CompositionMode}{SourceOver}. \l
1288 {QPainter::CompositionMode}{Source} is used to draw opaque objects
1289 onto a paint device. In this mode, each pixel in the source
1290 replaces the corresponding pixel in the destination. In \l
1291 {QPainter::CompositionMode}{SourceOver} composition mode, the
1292 source object is transparent and is drawn on top of the
1293 destination.
1294
1295 Note that composition transformation operates pixelwise. For that
1296 reason, there is a difference between using the graphic primitive
1297 itself and its bounding rectangle: The bounding rect contains
1298 pixels with alpha == 0 (i.e the pixels surrounding the
1299 primitive). These pixels will overwrite the other image's pixels,
1300 effectively clearing those, while the primitive only overwrites
1301 its own area.
1302
1303 \table 100%
1304 \row
1305 \li \inlineimage qpainter-compositiondemo.png
1306
1307 \li
1308 \b {Composition Modes Example}
1309
1310 The \l {painting/composition}{Composition Modes} example, available in
1311 Qt's examples directory, allows you to experiment with the various
1312 composition modes and see the results immediately.
1313
1314 \endtable
1315
1316 \section1 Limitations
1317 \target Limitations
1318
1319 If you are using coordinates with Qt's raster-based paint engine, it is
1320 important to note that, while coordinates greater than +/- 2\sup 15 can
1321 be used, any painting performed with coordinates outside this range is not
1322 guaranteed to be shown; the drawing may be clipped. This is due to the
1323 use of \c{short int} in the implementation.
1324
1325 The outlines generated by Qt's stroker are only an approximation when dealing
1326 with curved shapes. It is in most cases impossible to represent the outline of
1327 a bezier curve segment using another bezier curve segment, and so Qt approximates
1328 the curve outlines by using several smaller curves. For performance reasons there
1329 is a limit to how many curves Qt uses for these outlines, and thus when using
1330 large pen widths or scales the outline error increases. To generate outlines with
1331 smaller errors it is possible to use the QPainterPathStroker class, which has the
1332 setCurveThreshold member function which let's the user specify the error tolerance.
1333 Another workaround is to convert the paths to polygons first and then draw the
1334 polygons instead.
1335
1336 \section1 Performance
1337
1338 QPainter is a rich framework that allows developers to do a great
1339 variety of graphical operations, such as gradients, composition
1340 modes and vector graphics. And QPainter can do this across a
1341 variety of different hardware and software stacks. Naturally the
1342 underlying combination of hardware and software has some
1343 implications for performance, and ensuring that every single
1344 operation is fast in combination with all the various combinations
1345 of composition modes, brushes, clipping, transformation, etc, is
1346 close to an impossible task because of the number of
1347 permutations. As a compromise we have selected a subset of the
1348 QPainter API and backends, where performance is guaranteed to be as
1349 good as we can sensibly get it for the given combination of
1350 hardware and software.
1351
1352 The backends we focus on as high-performance engines are:
1353
1354 \list
1355
1356 \li Raster - This backend implements all rendering in pure software
1357 and is always used to render into QImages. For optimal performance
1358 only use the format types QImage::Format_ARGB32_Premultiplied,
1359 QImage::Format_RGB32 or QImage::Format_RGB16. Any other format,
1360 including QImage::Format_ARGB32, has significantly worse
1361 performance. This engine is used by default for QWidget and QPixmap.
1362
1363 \li OpenGL 2.0 (ES) - This backend is the primary backend for
1364 hardware accelerated graphics. It can be run on desktop machines
1365 and embedded devices supporting the OpenGL 2.0 or OpenGL/ES 2.0
1366 specification. This includes most graphics chips produced in the
1367 last couple of years. The engine can be enabled by using QPainter
1368 onto a QOpenGLWidget.
1369
1370 \endlist
1371
1372 These operations are:
1373
1374 \list
1375
1376 \li Simple transformations, meaning translation and scaling, pluss
1377 0, 90, 180, 270 degree rotations.
1378
1379 \li \c drawPixmap() in combination with simple transformations and
1380 opacity with non-smooth transformation mode
1381 (\c QPainter::SmoothPixmapTransform not enabled as a render hint).
1382
1383 \li Rectangle fills with solid color, two-color linear gradients
1384 and simple transforms.
1385
1386 \li Rectangular clipping with simple transformations and intersect
1387 clip.
1388
1389 \li Composition Modes \c QPainter::CompositionMode_Source and
1390 QPainter::CompositionMode_SourceOver.
1391
1392 \li Rounded rectangle filling using solid color and two-color
1393 linear gradients fills.
1394
1395 \li 3x3 patched pixmaps, via qDrawBorderPixmap.
1396
1397 \endlist
1398
1399 This list gives an indication of which features to safely use in
1400 an application where performance is critical. For certain setups,
1401 other operations may be fast too, but before making extensive use
1402 of them, it is recommended to benchmark and verify them on the
1403 system where the software will run in the end. There are also
1404 cases where expensive operations are ok to use, for instance when
1405 the result is cached in a QPixmap.
1406
1407 \sa QPaintDevice, QPaintEngine, {Qt SVG}, {Basic Drawing Example},
1408 {Drawing Utility Functions}
1409*/
1410
1411/*!
1412 \enum QPainter::RenderHint
1413
1414 Renderhints are used to specify flags to QPainter that may or
1415 may not be respected by any given engine.
1416
1417 \value Antialiasing Indicates that the engine should antialias
1418 edges of primitives if possible.
1419
1420 \value TextAntialiasing Indicates that the engine should antialias
1421 text if possible. To forcibly disable antialiasing for text, do not
1422 use this hint. Instead, set QFont::NoAntialias on your font's style
1423 strategy.
1424
1425 \value SmoothPixmapTransform Indicates that the engine should use
1426 a smooth pixmap transformation algorithm (such as bilinear) rather
1427 than nearest neighbor.
1428
1429 \value HighQualityAntialiasing This value is obsolete and will be ignored,
1430 use the Antialiasing render hint instead.
1431
1432 \value NonCosmeticDefaultPen This value is obsolete, the default for QPen
1433 is now non-cosmetic.
1434
1435 \value Qt4CompatiblePainting Compatibility hint telling the engine to use the
1436 same X11 based fill rules as in Qt 4, where aliased rendering is offset
1437 by slightly less than half a pixel. Also will treat default constructed pens
1438 as cosmetic. Potentially useful when porting a Qt 4 application to Qt 5.
1439
1440 \value LosslessImageRendering Use a lossless image rendering, whenever possible.
1441 Currently, this hint is only used when QPainter is employed to output a PDF
1442 file through QPrinter or QPdfWriter, where drawImage()/drawPixmap() calls
1443 will encode images using a lossless compression algorithm instead of lossy
1444 JPEG compression.
1445 This value was added in Qt 5.13.
1446
1447 \sa renderHints(), setRenderHint(), {QPainter#Rendering
1448 Quality}{Rendering Quality}, {Concentric Circles Example}
1449
1450*/
1451
1452/*!
1453 Constructs a painter.
1454
1455 \sa begin(), end()
1456*/
1457
1458QPainter::QPainter()
1459 : d_ptr(new QPainterPrivate(this))
1460{
1461}
1462
1463/*!
1464 \fn QPainter::QPainter(QPaintDevice *device)
1465
1466 Constructs a painter that begins painting the paint \a device
1467 immediately.
1468
1469 This constructor is convenient for short-lived painters, e.g. in a
1470 QWidget::paintEvent() and should be used only once. The
1471 constructor calls begin() for you and the QPainter destructor
1472 automatically calls end().
1473
1474 Here's an example using begin() and end():
1475 \snippet code/src_gui_painting_qpainter.cpp 1
1476
1477 The same example using this constructor:
1478 \snippet code/src_gui_painting_qpainter.cpp 2
1479
1480 Since the constructor cannot provide feedback when the initialization
1481 of the painter failed you should rather use begin() and end() to paint
1482 on external devices, e.g. printers.
1483
1484 \sa begin(), end()
1485*/
1486
1487QPainter::QPainter(QPaintDevice *pd)
1488 : d_ptr(0)
1489{
1490 Q_ASSERT(pd != 0);
1491 if (!QPainterPrivate::attachPainterPrivate(this, pd)) {
1492 d_ptr.reset(new QPainterPrivate(this));
1493 begin(pd);
1494 }
1495 Q_ASSERT(d_ptr);
1496}
1497
1498/*!
1499 Destroys the painter.
1500*/
1501QPainter::~QPainter()
1502{
1503 d_ptr->inDestructor = true;
1504 QT_TRY {
1505 if (isActive())
1506 end();
1507 else if (d_ptr->refcount > 1)
1508 d_ptr->detachPainterPrivate(this);
1509 } QT_CATCH(...) {
1510 // don't throw anything in the destructor.
1511 }
1512 if (d_ptr) {
1513 // Make sure we haven't messed things up.
1514 Q_ASSERT(d_ptr->inDestructor);
1515 d_ptr->inDestructor = false;
1516 Q_ASSERT(d_ptr->refcount == 1);
1517 if (d_ptr->d_ptrs)
1518 free(d_ptr->d_ptrs);
1519 }
1520}
1521
1522/*!
1523 Returns the paint device on which this painter is currently
1524 painting, or \nullptr if the painter is not active.
1525
1526 \sa isActive()
1527*/
1528
1529QPaintDevice *QPainter::device() const
1530{
1531 Q_D(const QPainter);
1532 if (isActive() && d->engine->d_func()->currentClipDevice)
1533 return d->engine->d_func()->currentClipDevice;
1534 return d->original_device;
1535}
1536
1537/*!
1538 Returns \c true if begin() has been called and end() has not yet been
1539 called; otherwise returns \c false.
1540
1541 \sa begin(), QPaintDevice::paintingActive()
1542*/
1543
1544bool QPainter::isActive() const
1545{
1546 Q_D(const QPainter);
1547 return d->engine;
1548}
1549
1550#if QT_DEPRECATED_SINCE(5, 13)
1551/*!
1552 Initializes the painters pen, background and font to the same as
1553 the given \a device.
1554
1555 \obsolete
1556
1557 \sa begin(), {QPainter#Settings}{Settings}
1558*/
1559void QPainter::initFrom(const QPaintDevice *device)
1560{
1561 Q_ASSERT_X(device, "QPainter::initFrom(const QPaintDevice *device)", "QPaintDevice cannot be 0");
1562 Q_D(QPainter);
1563 d->initFrom(device);
1564}
1565#endif
1566
1567void QPainterPrivate::initFrom(const QPaintDevice *device)
1568{
1569 if (!engine) {
1570 qWarning("QPainter::initFrom: Painter not active, aborted");
1571 return;
1572 }
1573
1574 Q_Q(QPainter);
1575 device->initPainter(q);
1576
1577 if (extended) {
1578 extended->penChanged();
1579 } else if (engine) {
1580 engine->setDirty(QPaintEngine::DirtyPen);
1581 engine->setDirty(QPaintEngine::DirtyBrush);
1582 engine->setDirty(QPaintEngine::DirtyFont);
1583 }
1584}
1585
1586/*!
1587 Saves the current painter state (pushes the state onto a stack). A
1588 save() must be followed by a corresponding restore(); the end()
1589 function unwinds the stack.
1590
1591 \sa restore()
1592*/
1593
1594void QPainter::save()
1595{
1596#ifdef QT_DEBUG_DRAW
1597 if (qt_show_painter_debug_output)
1598 printf("QPainter::save()\n");
1599#endif
1600 Q_D(QPainter);
1601 if (!d->engine) {
1602 qWarning("QPainter::save: Painter not active");
1603 return;
1604 }
1605
1606 if (d->extended) {
1607 d->state = d->extended->createState(d->states.back());
1608 d->extended->setState(d->state);
1609 } else {
1610 d->updateState(d->state);
1611 d->state = new QPainterState(d->states.back());
1612 d->engine->state = d->state;
1613 }
1614 d->states.push_back(d->state);
1615}
1616
1617/*!
1618 Restores the current painter state (pops a saved state off the
1619 stack).
1620
1621 \sa save()
1622*/
1623
1624void QPainter::restore()
1625{
1626#ifdef QT_DEBUG_DRAW
1627 if (qt_show_painter_debug_output)
1628 printf("QPainter::restore()\n");
1629#endif
1630 Q_D(QPainter);
1631 if (d->states.size()<=1) {
1632 qWarning("QPainter::restore: Unbalanced save/restore");
1633 return;
1634 } else if (!d->engine) {
1635 qWarning("QPainter::restore: Painter not active");
1636 return;
1637 }
1638
1639 QPainterState *tmp = d->state;
1640 d->states.pop_back();
1641 d->state = d->states.back();
1642 d->txinv = false;
1643
1644 if (d->extended) {
1645 d->checkEmulation();
1646 d->extended->setState(d->state);
1647 delete tmp;
1648 return;
1649 }
1650
1651 // trigger clip update if the clip path/region has changed since
1652 // last save
1653 if (!d->state->clipInfo.isEmpty()
1654 && (tmp->changeFlags & (QPaintEngine::DirtyClipRegion | QPaintEngine::DirtyClipPath))) {
1655 // reuse the tmp state to avoid any extra allocs...
1656 tmp->dirtyFlags = QPaintEngine::DirtyClipPath;
1657 tmp->clipOperation = Qt::NoClip;
1658 tmp->clipPath = QPainterPath();
1659 d->engine->updateState(*tmp);
1660 // replay the list of clip states,
1661 for (const QPainterClipInfo &info : qAsConst(d->state->clipInfo)) {
1662 tmp->matrix = info.matrix;
1663 tmp->matrix *= d->state->redirectionMatrix;
1664 tmp->clipOperation = info.operation;
1665 if (info.clipType == QPainterClipInfo::RectClip) {
1666 tmp->dirtyFlags = QPaintEngine::DirtyClipRegion | QPaintEngine::DirtyTransform;
1667 tmp->clipRegion = info.rect;
1668 } else if (info.clipType == QPainterClipInfo::RegionClip) {
1669 tmp->dirtyFlags = QPaintEngine::DirtyClipRegion | QPaintEngine::DirtyTransform;
1670 tmp->clipRegion = info.region;
1671 } else { // clipType == QPainterClipInfo::PathClip
1672 tmp->dirtyFlags = QPaintEngine::DirtyClipPath | QPaintEngine::DirtyTransform;
1673 tmp->clipPath = info.path;
1674 }
1675 d->engine->updateState(*tmp);
1676 }
1677
1678
1679 //Since we've updated the clip region anyway, pretend that the clip path hasn't changed:
1680 d->state->dirtyFlags &= ~(QPaintEngine::DirtyClipPath | QPaintEngine::DirtyClipRegion);
1681 tmp->changeFlags &= ~uint(QPaintEngine::DirtyClipPath | QPaintEngine::DirtyClipRegion);
1682 tmp->changeFlags |= QPaintEngine::DirtyTransform;
1683 }
1684
1685 d->updateState(d->state);
1686 delete tmp;
1687}
1688
1689
1690/*!
1691
1692 \fn bool QPainter::begin(QPaintDevice *device)
1693
1694 Begins painting the paint \a device and returns \c true if
1695 successful; otherwise returns \c false.
1696
1697 Notice that all painter settings (setPen(), setBrush() etc.) are reset
1698 to default values when begin() is called.
1699
1700 The errors that can occur are serious problems, such as these:
1701
1702 \snippet code/src_gui_painting_qpainter.cpp 3
1703
1704 Note that most of the time, you can use one of the constructors
1705 instead of begin(), and that end() is automatically done at
1706 destruction.
1707
1708 \warning A paint device can only be painted by one painter at a
1709 time.
1710
1711 \warning Painting on a QImage with the format
1712 QImage::Format_Indexed8 is not supported.
1713
1714 \sa end(), QPainter()
1715*/
1716
1717static inline void qt_cleanup_painter_state(QPainterPrivate *d)
1718{
1719 d->states.clear();
1720 delete d->state;
1721 d->state = 0;
1722 d->engine = 0;
1723 d->device = 0;
1724}
1725
1726bool QPainter::begin(QPaintDevice *pd)
1727{
1728 Q_ASSERT(pd);
1729
1730 if (pd->painters > 0) {
1731 qWarning("QPainter::begin: A paint device can only be painted by one painter at a time.");
1732 return false;
1733 }
1734
1735 if (d_ptr->engine) {
1736 qWarning("QPainter::begin: Painter already active");
1737 return false;
1738 }
1739
1740 if (QPainterPrivate::attachPainterPrivate(this, pd))
1741 return true;
1742
1743 Q_D(QPainter);
1744
1745 d->helper_device = pd;
1746 d->original_device = pd;
1747
1748 QPoint redirectionOffset;
1749 QPaintDevice *rpd = pd->redirected(&redirectionOffset);
1750 if (rpd)
1751 pd = rpd;
1752
1753#ifdef QT_DEBUG_DRAW
1754 if (qt_show_painter_debug_output)
1755 printf("QPainter::begin(), device=%p, type=%d\n", pd, pd->devType());
1756#endif
1757
1758 if (pd->devType() == QInternal::Pixmap)
1759 static_cast<QPixmap *>(pd)->detach();
1760 else if (pd->devType() == QInternal::Image)
1761 static_cast<QImage *>(pd)->detach();
1762
1763 d->engine = pd->paintEngine();
1764
1765 if (!d->engine) {
1766 qWarning("QPainter::begin: Paint device returned engine == 0, type: %d", pd->devType());
1767 return false;
1768 }
1769
1770 d->device = pd;
1771
1772 d->extended = d->engine->isExtended() ? static_cast<QPaintEngineEx *>(d->engine) : 0;
1773 if (d->emulationEngine)
1774 d->emulationEngine->real_engine = d->extended;
1775
1776 // Setup new state...
1777 Q_ASSERT(!d->state);
1778 d->state = d->extended ? d->extended->createState(0) : new QPainterState;
1779 d->state->painter = this;
1780 d->states.push_back(d->state);
1781
1782 d->state->redirectionMatrix.translate(-redirectionOffset.x(), -redirectionOffset.y());
1783 d->state->brushOrigin = QPointF();
1784
1785 // Slip a painter state into the engine before we do any other operations
1786 if (d->extended)
1787 d->extended->setState(d->state);
1788 else
1789 d->engine->state = d->state;
1790
1791 switch (pd->devType()) {
1792 case QInternal::Pixmap:
1793 {
1794 QPixmap *pm = static_cast<QPixmap *>(pd);
1795 Q_ASSERT(pm);
1796 if (pm->isNull()) {
1797 qWarning("QPainter::begin: Cannot paint on a null pixmap");
1798 qt_cleanup_painter_state(d);
1799 return false;
1800 }
1801
1802 if (pm->depth() == 1) {
1803 d->state->pen = QPen(Qt::color1);
1804 d->state->brush = QBrush(Qt::color0);
1805 }
1806 break;
1807 }
1808 case QInternal::Image:
1809 {
1810 QImage *img = static_cast<QImage *>(pd);
1811 Q_ASSERT(img);
1812 if (img->isNull()) {
1813 qWarning("QPainter::begin: Cannot paint on a null image");
1814 qt_cleanup_painter_state(d);
1815 return false;
1816 } else if (img->format() == QImage::Format_Indexed8) {
1817 // Painting on indexed8 images is not supported.
1818 qWarning("QPainter::begin: Cannot paint on an image with the QImage::Format_Indexed8 format");
1819 qt_cleanup_painter_state(d);
1820 return false;
1821 }
1822 if (img->depth() == 1) {
1823 d->state->pen = QPen(Qt::color1);
1824 d->state->brush = QBrush(Qt::color0);
1825 }
1826 break;
1827 }
1828 default:
1829 break;
1830 }
1831 if (d->state->ww == 0) // For compat with 3.x painter defaults
1832 d->state->ww = d->state->wh = d->state->vw = d->state->vh = 1024;
1833
1834 d->engine->setPaintDevice(pd);
1835
1836 bool begun = d->engine->begin(pd);
1837 if (!begun) {
1838 qWarning("QPainter::begin(): Returned false");
1839 if (d->engine->isActive()) {
1840 end();
1841 } else {
1842 qt_cleanup_painter_state(d);
1843 }
1844 return false;
1845 } else {
1846 d->engine->setActive(begun);
1847 }
1848
1849 // Copy painter properties from original paint device,
1850 // required for QPixmap::grabWidget()
1851 if (d->original_device->devType() == QInternal::Widget) {
1852 d->initFrom(d->original_device);
1853 } else {
1854 d->state->layoutDirection = Qt::LayoutDirectionAuto;
1855 // make sure we have a font compatible with the paintdevice
1856 d->state->deviceFont = d->state->font = QFont(d->state->deviceFont, device());
1857 }
1858
1859 QRect systemRect = d->engine->systemRect();
1860 if (!systemRect.isEmpty()) {
1861 d->state->ww = d->state->vw = systemRect.width();
1862 d->state->wh = d->state->vh = systemRect.height();
1863 } else {
1864 d->state->ww = d->state->vw = pd->metric(QPaintDevice::PdmWidth);
1865 d->state->wh = d->state->vh = pd->metric(QPaintDevice::PdmHeight);
1866 }
1867
1868 const QPoint coordinateOffset = d->engine->coordinateOffset();
1869 d->state->redirectionMatrix.translate(-coordinateOffset.x(), -coordinateOffset.y());
1870
1871 Q_ASSERT(d->engine->isActive());
1872
1873 if (!d->state->redirectionMatrix.isIdentity() || d->effectiveDevicePixelRatio() > 1)
1874 d->updateMatrix();
1875
1876 Q_ASSERT(d->engine->isActive());
1877 d->state->renderHints = QPainter::TextAntialiasing;
1878 ++d->device->painters;
1879
1880 d->state->emulationSpecifier = 0;
1881
1882 return true;
1883}
1884
1885/*!
1886 Ends painting. Any resources used while painting are released. You
1887 don't normally need to call this since it is called by the
1888 destructor.
1889
1890 Returns \c true if the painter is no longer active; otherwise returns \c false.
1891
1892 \sa begin(), isActive()
1893*/
1894
1895bool QPainter::end()
1896{
1897#ifdef QT_DEBUG_DRAW
1898 if (qt_show_painter_debug_output)
1899 printf("QPainter::end()\n");
1900#endif
1901 Q_D(QPainter);
1902
1903 if (!d->engine) {
1904 qWarning("QPainter::end: Painter not active, aborted");
1905 qt_cleanup_painter_state(d);
1906 return false;
1907 }
1908
1909 if (d->refcount > 1) {
1910 d->detachPainterPrivate(this);
1911 return true;
1912 }
1913
1914 bool ended = true;
1915
1916 if (d->engine->isActive()) {
1917 ended = d->engine->end();
1918 d->updateState(0);
1919
1920 --d->device->painters;
1921 if (d->device->painters == 0) {
1922 d->engine->setPaintDevice(0);
1923 d->engine->setActive(false);
1924 }
1925 }
1926
1927 if (d->states.size() > 1) {
1928 qWarning("QPainter::end: Painter ended with %d saved states",
1929 d->states.size());
1930 }
1931
1932 if (d->engine->autoDestruct()) {
1933 delete d->engine;
1934 }
1935
1936 if (d->emulationEngine) {
1937 delete d->emulationEngine;
1938 d->emulationEngine = 0;
1939 }
1940
1941 if (d->extended) {
1942 d->extended = 0;
1943 }
1944
1945 qt_cleanup_painter_state(d);
1946
1947 return ended;
1948}
1949
1950
1951/*!
1952 Returns the paint engine that the painter is currently operating
1953 on if the painter is active; otherwise 0.
1954
1955 \sa isActive()
1956*/
1957QPaintEngine *QPainter::paintEngine() const
1958{
1959 Q_D(const QPainter);
1960 return d->engine;
1961}
1962
1963/*!
1964 \since 4.6
1965
1966 Flushes the painting pipeline and prepares for the user issuing commands
1967 directly to the underlying graphics context. Must be followed by a call to
1968 endNativePainting().
1969
1970 Note that only the states the underlying paint engine changes will be reset
1971 to their respective default states. The states we reset may change from
1972 release to release. The following states are currently reset in the OpenGL
1973 2 engine:
1974
1975 \list
1976 \li blending is disabled
1977 \li the depth, stencil and scissor tests are disabled
1978 \li the active texture unit is reset to 0
1979 \li the depth mask, depth function and the clear depth are reset to their
1980 default values
1981 \li the stencil mask, stencil operation and stencil function are reset to
1982 their default values
1983 \li the current color is reset to solid white
1984 \endlist
1985
1986 If, for example, the OpenGL polygon mode is changed by the user inside a
1987 beginNativePaint()/endNativePainting() block, it will not be reset to the
1988 default state by endNativePainting(). Here is an example that shows
1989 intermixing of painter commands and raw OpenGL commands:
1990
1991 \snippet code/src_gui_painting_qpainter.cpp 21
1992
1993 \sa endNativePainting()
1994*/
1995void QPainter::beginNativePainting()
1996{
1997 Q_D(QPainter);
1998 if (!d->engine) {
1999 qWarning("QPainter::beginNativePainting: Painter not active");
2000 return;
2001 }
2002
2003 if (d->extended)
2004 d->extended->beginNativePainting();
2005}
2006
2007/*!
2008 \since 4.6
2009
2010 Restores the painter after manually issuing native painting commands. Lets
2011 the painter restore any native state that it relies on before calling any
2012 other painter commands.
2013
2014 \sa beginNativePainting()
2015*/
2016void QPainter::endNativePainting()
2017{
2018 Q_D(const QPainter);
2019 if (!d->engine) {
2020 qWarning("QPainter::beginNativePainting: Painter not active");
2021 return;
2022 }
2023
2024 if (d->extended)
2025 d->extended->endNativePainting();
2026 else
2027 d->engine->syncState();
2028}
2029
2030/*!
2031 Returns the font metrics for the painter if the painter is
2032 active. Otherwise, the return value is undefined.
2033
2034 \sa font(), isActive(), {QPainter#Settings}{Settings}
2035*/
2036
2037QFontMetrics QPainter::fontMetrics() const
2038{
2039 Q_D(const QPainter);
2040 if (!d->engine) {
2041 qWarning("QPainter::fontMetrics: Painter not active");
2042 return QFontMetrics(QFont());
2043 }
2044 return QFontMetrics(d->state->font);
2045}
2046
2047
2048/*!
2049 Returns the font info for the painter if the painter is
2050 active. Otherwise, the return value is undefined.
2051
2052 \sa font(), isActive(), {QPainter#Settings}{Settings}
2053*/
2054
2055QFontInfo QPainter::fontInfo() const
2056{
2057 Q_D(const QPainter);
2058 if (!d->engine) {
2059 qWarning("QPainter::fontInfo: Painter not active");
2060 return QFontInfo(QFont());
2061 }
2062 return QFontInfo(d->state->font);
2063}
2064
2065/*!
2066 \since 4.2
2067
2068 Returns the opacity of the painter. The default value is
2069 1.
2070*/
2071
2072qreal QPainter::opacity() const
2073{
2074 Q_D(const QPainter);
2075 if (!d->engine) {
2076 qWarning("QPainter::opacity: Painter not active");
2077 return 1.0;
2078 }
2079 return d->state->opacity;
2080}
2081
2082/*!
2083 \since 4.2
2084
2085 Sets the opacity of the painter to \a opacity. The value should
2086 be in the range 0.0 to 1.0, where 0.0 is fully transparent and
2087 1.0 is fully opaque.
2088
2089 Opacity set on the painter will apply to all drawing operations
2090 individually.
2091*/
2092
2093void QPainter::setOpacity(qreal opacity)
2094{
2095 Q_D(QPainter);
2096
2097 if (!d->engine) {
2098 qWarning("QPainter::setOpacity: Painter not active");
2099 return;
2100 }
2101
2102 opacity = qMin(qreal(1), qMax(qreal(0), opacity));
2103
2104 if (opacity == d->state->opacity)
2105 return;
2106
2107 d->state->opacity = opacity;
2108
2109 if (d->extended)
2110 d->extended->opacityChanged();
2111 else
2112 d->state->dirtyFlags |= QPaintEngine::DirtyOpacity;
2113}
2114
2115
2116/*!
2117 Returns the currently set brush origin.
2118
2119 \sa setBrushOrigin(), {QPainter#Settings}{Settings}
2120*/
2121
2122QPoint QPainter::brushOrigin() const
2123{
2124 Q_D(const QPainter);
2125 if (!d->engine) {
2126 qWarning("QPainter::brushOrigin: Painter not active");
2127 return QPoint();
2128 }
2129 return QPointF(d->state->brushOrigin).toPoint();
2130}
2131
2132/*!
2133 \fn void QPainter::setBrushOrigin(const QPointF &position)
2134
2135 Sets the brush origin to \a position.
2136
2137 The brush origin specifies the (0, 0) coordinate of the painter's
2138 brush.
2139
2140 Note that while the brushOrigin() was necessary to adopt the
2141 parent's background for a widget in Qt 3, this is no longer the
2142 case since the Qt 4 painter doesn't paint the background unless
2143 you explicitly tell it to do so by setting the widget's \l
2144 {QWidget::autoFillBackground}{autoFillBackground} property to
2145 true.
2146
2147 \sa brushOrigin(), {QPainter#Settings}{Settings}
2148*/
2149
2150void QPainter::setBrushOrigin(const QPointF &p)
2151{
2152 Q_D(QPainter);
2153#ifdef QT_DEBUG_DRAW
2154 if (qt_show_painter_debug_output)
2155 printf("QPainter::setBrushOrigin(), (%.2f,%.2f)\n", p.x(), p.y());
2156#endif
2157
2158 if (!d->engine) {
2159 qWarning("QPainter::setBrushOrigin: Painter not active");
2160 return;
2161 }
2162
2163 d->state->brushOrigin = p;
2164
2165 if (d->extended) {
2166 d->extended->brushOriginChanged();
2167 return;
2168 }
2169
2170 d->state->dirtyFlags |= QPaintEngine::DirtyBrushOrigin;
2171}
2172
2173/*!
2174 \fn void QPainter::setBrushOrigin(const QPoint &position)
2175 \overload
2176
2177 Sets the brush's origin to the given \a position.
2178*/
2179
2180/*!
2181 \fn void QPainter::setBrushOrigin(int x, int y)
2182
2183 \overload
2184
2185 Sets the brush's origin to point (\a x, \a y).
2186*/
2187
2188/*!
2189 \enum QPainter::CompositionMode
2190
2191 Defines the modes supported for digital image compositing.
2192 Composition modes are used to specify how the pixels in one image,
2193 the source, are merged with the pixel in another image, the
2194 destination.
2195
2196 Please note that the bitwise raster operation modes, denoted with
2197 a RasterOp prefix, are only natively supported in the X11 and
2198 raster paint engines. This means that the only way to utilize
2199 these modes on the Mac is via a QImage. The RasterOp denoted blend
2200 modes are \e not supported for pens and brushes with alpha
2201 components. Also, turning on the QPainter::Antialiasing render
2202 hint will effectively disable the RasterOp modes.
2203
2204
2205 \image qpainter-compositionmode1.png
2206 \image qpainter-compositionmode2.png
2207
2208 The most common type is SourceOver (often referred to as just
2209 alpha blending) where the source pixel is blended on top of the
2210 destination pixel in such a way that the alpha component of the
2211 source defines the translucency of the pixel.
2212
2213 Several composition modes require an alpha channel in the source or
2214 target images to have an effect. For optimal performance the
2215 image format \l {QImage::Format}{Format_ARGB32_Premultiplied} is
2216 preferred.
2217
2218 When a composition mode is set it applies to all painting
2219 operator, pens, brushes, gradients and pixmap/image drawing.
2220
2221 \value CompositionMode_SourceOver This is the default mode. The
2222 alpha of the source is used to blend the pixel on top of the
2223 destination.
2224
2225 \value CompositionMode_DestinationOver The alpha of the
2226 destination is used to blend it on top of the source pixels. This
2227 mode is the inverse of CompositionMode_SourceOver.
2228
2229 \value CompositionMode_Clear The pixels in the destination are
2230 cleared (set to fully transparent) independent of the source.
2231
2232 \value CompositionMode_Source The output is the source
2233 pixel. (This means a basic copy operation and is identical to
2234 SourceOver when the source pixel is opaque).
2235
2236 \value CompositionMode_Destination The output is the destination
2237 pixel. This means that the blending has no effect. This mode is
2238 the inverse of CompositionMode_Source.
2239
2240 \value CompositionMode_SourceIn The output is the source, where
2241 the alpha is reduced by that of the destination.
2242
2243 \value CompositionMode_DestinationIn The output is the
2244 destination, where the alpha is reduced by that of the
2245 source. This mode is the inverse of CompositionMode_SourceIn.
2246
2247 \value CompositionMode_SourceOut The output is the source, where
2248 the alpha is reduced by the inverse of destination.
2249
2250 \value CompositionMode_DestinationOut The output is the
2251 destination, where the alpha is reduced by the inverse of the
2252 source. This mode is the inverse of CompositionMode_SourceOut.
2253
2254 \value CompositionMode_SourceAtop The source pixel is blended on
2255 top of the destination, with the alpha of the source pixel reduced
2256 by the alpha of the destination pixel.
2257
2258 \value CompositionMode_DestinationAtop The destination pixel is
2259 blended on top of the source, with the alpha of the destination
2260 pixel is reduced by the alpha of the destination pixel. This mode
2261 is the inverse of CompositionMode_SourceAtop.
2262
2263 \value CompositionMode_Xor The source, whose alpha is reduced with
2264 the inverse of the destination alpha, is merged with the
2265 destination, whose alpha is reduced by the inverse of the source
2266 alpha. CompositionMode_Xor is not the same as the bitwise Xor.
2267
2268 \value CompositionMode_Plus Both the alpha and color of the source
2269 and destination pixels are added together.
2270
2271 \value CompositionMode_Multiply The output is the source color
2272 multiplied by the destination. Multiplying a color with white
2273 leaves the color unchanged, while multiplying a color
2274 with black produces black.
2275
2276 \value CompositionMode_Screen The source and destination colors
2277 are inverted and then multiplied. Screening a color with white
2278 produces white, whereas screening a color with black leaves the
2279 color unchanged.
2280
2281 \value CompositionMode_Overlay Multiplies or screens the colors
2282 depending on the destination color. The destination color is mixed
2283 with the source color to reflect the lightness or darkness of the
2284 destination.
2285
2286 \value CompositionMode_Darken The darker of the source and
2287 destination colors is selected.
2288
2289 \value CompositionMode_Lighten The lighter of the source and
2290 destination colors is selected.
2291
2292 \value CompositionMode_ColorDodge The destination color is
2293 brightened to reflect the source color. A black source color
2294 leaves the destination color unchanged.
2295
2296 \value CompositionMode_ColorBurn The destination color is darkened
2297 to reflect the source color. A white source color leaves the
2298 destination color unchanged.
2299
2300 \value CompositionMode_HardLight Multiplies or screens the colors
2301 depending on the source color. A light source color will lighten
2302 the destination color, whereas a dark source color will darken the
2303 destination color.
2304
2305 \value CompositionMode_SoftLight Darkens or lightens the colors
2306 depending on the source color. Similar to
2307 CompositionMode_HardLight.
2308
2309 \value CompositionMode_Difference Subtracts the darker of the
2310 colors from the lighter. Painting with white inverts the
2311 destination color, whereas painting with black leaves the
2312 destination color unchanged.
2313
2314 \value CompositionMode_Exclusion Similar to
2315 CompositionMode_Difference, but with a lower contrast. Painting
2316 with white inverts the destination color, whereas painting with
2317 black leaves the destination color unchanged.
2318
2319 \value RasterOp_SourceOrDestination Does a bitwise OR operation on
2320 the source and destination pixels (src OR dst).
2321
2322 \value RasterOp_SourceAndDestination Does a bitwise AND operation
2323 on the source and destination pixels (src AND dst).
2324
2325 \value RasterOp_SourceXorDestination Does a bitwise XOR operation
2326 on the source and destination pixels (src XOR dst).
2327
2328 \value RasterOp_NotSourceAndNotDestination Does a bitwise NOR
2329 operation on the source and destination pixels ((NOT src) AND (NOT
2330 dst)).
2331
2332 \value RasterOp_NotSourceOrNotDestination Does a bitwise NAND
2333 operation on the source and destination pixels ((NOT src) OR (NOT
2334 dst)).
2335
2336 \value RasterOp_NotSourceXorDestination Does a bitwise operation
2337 where the source pixels are inverted and then XOR'ed with the
2338 destination ((NOT src) XOR dst).
2339
2340 \value RasterOp_NotSource Does a bitwise operation where the
2341 source pixels are inverted (NOT src).
2342
2343 \value RasterOp_NotSourceAndDestination Does a bitwise operation
2344 where the source is inverted and then AND'ed with the destination
2345 ((NOT src) AND dst).
2346
2347 \value RasterOp_SourceAndNotDestination Does a bitwise operation
2348 where the source is AND'ed with the inverted destination pixels
2349 (src AND (NOT dst)).
2350
2351 \value RasterOp_NotSourceOrDestination Does a bitwise operation
2352 where the source is inverted and then OR'ed with the destination
2353 ((NOT src) OR dst).
2354
2355 \value RasterOp_ClearDestination The pixels in the destination are
2356 cleared (set to 0) independent of the source.
2357
2358 \value RasterOp_SetDestination The pixels in the destination are
2359 set (set to 1) independent of the source.
2360
2361 \value RasterOp_NotDestination Does a bitwise operation
2362 where the destination pixels are inverted (NOT dst).
2363
2364 \value RasterOp_SourceOrNotDestination Does a bitwise operation
2365 where the source is OR'ed with the inverted destination pixels
2366 (src OR (NOT dst)).
2367
2368 \sa compositionMode(), setCompositionMode(), {QPainter#Composition
2369 Modes}{Composition Modes}, {Image Composition Example}
2370*/
2371
2372/*!
2373 Sets the composition mode to the given \a mode.
2374
2375 \warning Only a QPainter operating on a QImage fully supports all
2376 composition modes. The RasterOp modes are supported for X11 as
2377 described in compositionMode().
2378
2379 \sa compositionMode()
2380*/
2381void QPainter::setCompositionMode(CompositionMode mode)
2382{
2383 Q_D(QPainter);
2384 if (!d->engine) {
2385 qWarning("QPainter::setCompositionMode: Painter not active");
2386 return;
2387 }
2388 if (d->state->composition_mode == mode)
2389 return;
2390 if (d->extended) {
2391 d->state->composition_mode = mode;
2392 d->extended->compositionModeChanged();
2393 return;
2394 }
2395
2396 if (mode >= QPainter::RasterOp_SourceOrDestination) {
2397 if (!d->engine->hasFeature(QPaintEngine::RasterOpModes)) {
2398 qWarning("QPainter::setCompositionMode: "
2399 "Raster operation modes not supported on device");
2400 return;
2401 }
2402 } else if (mode >= QPainter::CompositionMode_Plus) {
2403 if (!d->engine->hasFeature(QPaintEngine::BlendModes)) {
2404 qWarning("QPainter::setCompositionMode: "
2405 "Blend modes not supported on device");
2406 return;
2407 }
2408 } else if (!d->engine->hasFeature(QPaintEngine::PorterDuff)) {
2409 if (mode != CompositionMode_Source && mode != CompositionMode_SourceOver) {
2410 qWarning("QPainter::setCompositionMode: "
2411 "PorterDuff modes not supported on device");
2412 return;
2413 }
2414 }
2415
2416 d->state->composition_mode = mode;
2417 d->state->dirtyFlags |= QPaintEngine::DirtyCompositionMode;
2418}
2419
2420/*!
2421 Returns the current composition mode.
2422
2423 \sa CompositionMode, setCompositionMode()
2424*/
2425QPainter::CompositionMode QPainter::compositionMode() const
2426{
2427 Q_D(const QPainter);
2428 if (!d->engine) {
2429 qWarning("QPainter::compositionMode: Painter not active");
2430 return QPainter::CompositionMode_SourceOver;
2431 }
2432 return d->state->composition_mode;
2433}
2434
2435/*!
2436 Returns the current background brush.
2437
2438 \sa setBackground(), {QPainter#Settings}{Settings}
2439*/
2440
2441const QBrush &QPainter::background() const
2442{
2443 Q_D(const QPainter);
2444 if (!d->engine) {
2445 qWarning("QPainter::background: Painter not active");
2446 return d->fakeState()->brush;
2447 }
2448 return d->state->bgBrush;
2449}
2450
2451
2452/*!
2453 Returns \c true if clipping has been set; otherwise returns \c false.
2454
2455 \sa setClipping(), {QPainter#Clipping}{Clipping}
2456*/
2457
2458bool QPainter::hasClipping() const
2459{
2460 Q_D(const QPainter);
2461 if (!d->engine) {
2462 qWarning("QPainter::hasClipping: Painter not active");
2463 return false;
2464 }
2465 return d->state->clipEnabled && d->state->clipOperation != Qt::NoClip;
2466}
2467
2468
2469/*!
2470 Enables clipping if \a enable is true, or disables clipping if \a
2471 enable is false.
2472
2473 \sa hasClipping(), {QPainter#Clipping}{Clipping}
2474*/
2475
2476void QPainter::setClipping(bool enable)
2477{
2478 Q_D(QPainter);
2479#ifdef QT_DEBUG_DRAW
2480 if (qt_show_painter_debug_output)
2481 printf("QPainter::setClipping(), enable=%s, was=%s\n",
2482 enable ? "on" : "off",
2483 hasClipping() ? "on" : "off");
2484#endif
2485 if (!d->engine) {
2486 qWarning("QPainter::setClipping: Painter not active, state will be reset by begin");
2487 return;
2488 }
2489
2490 if (hasClipping() == enable)
2491 return;
2492
2493 // we can't enable clipping if we don't have a clip
2494 if (enable
2495 && (d->state->clipInfo.isEmpty() || d->state->clipInfo.constLast().operation == Qt::NoClip))
2496 return;
2497 d->state->clipEnabled = enable;
2498
2499 if (d->extended) {
2500 d->extended->clipEnabledChanged();
2501 return;
2502 }
2503
2504 d->state->dirtyFlags |= QPaintEngine::DirtyClipEnabled;
2505 d->updateState(d->state);
2506}
2507
2508
2509/*!
2510 Returns the currently set clip region. Note that the clip region
2511 is given in logical coordinates.
2512
2513 \warning QPainter does not store the combined clip explicitly as
2514 this is handled by the underlying QPaintEngine, so the path is
2515 recreated on demand and transformed to the current logical
2516 coordinate system. This is potentially an expensive operation.
2517
2518 \sa setClipRegion(), clipPath(), setClipping()
2519*/
2520
2521QRegion QPainter::clipRegion() const
2522{
2523 Q_D(const QPainter);
2524 if (!d->engine) {
2525 qWarning("QPainter::clipRegion: Painter not active");
2526 return QRegion();
2527 }
2528
2529 QRegion region;
2530 bool lastWasNothing = true;
2531
2532 if (!d->txinv)
2533 const_cast<QPainter *>(this)->d_ptr->updateInvMatrix();
2534
2535 // ### Falcon: Use QPainterPath
2536 for (const QPainterClipInfo &info : qAsConst(d->state->clipInfo)) {
2537 switch (info.clipType) {
2538
2539 case QPainterClipInfo::RegionClip: {
2540 QTransform matrix = (info.matrix * d->invMatrix);
2541 if (lastWasNothing) {
2542 region = info.region * matrix;
2543 lastWasNothing = false;
2544 continue;
2545 }
2546 if (info.operation == Qt::IntersectClip)
2547 region &= info.region * matrix;
2548 else if (info.operation == Qt::NoClip) {
2549 lastWasNothing = true;
2550 region = QRegion();
2551 } else
2552 region = info.region * matrix;
2553 break;
2554 }
2555
2556 case QPainterClipInfo::PathClip: {
2557 QTransform matrix = (info.matrix * d->invMatrix);
2558 if (lastWasNothing) {
2559 region = QRegion((info.path * matrix).toFillPolygon().toPolygon(),
2560 info.path.fillRule());
2561 lastWasNothing = false;
2562 continue;
2563 }
2564 if (info.operation == Qt::IntersectClip) {
2565 region &= QRegion((info.path * matrix).toFillPolygon().toPolygon(),
2566 info.path.fillRule());
2567 } else if (info.operation == Qt::NoClip) {
2568 lastWasNothing = true;
2569 region = QRegion();
2570 } else {
2571 region = QRegion((info.path * matrix).toFillPolygon().toPolygon(),
2572 info.path.fillRule());
2573 }
2574 break;
2575 }
2576
2577 case QPainterClipInfo::RectClip: {
2578 QTransform matrix = (info.matrix * d->invMatrix);
2579 if (lastWasNothing) {
2580 region = QRegion(info.rect) * matrix;
2581 lastWasNothing = false;
2582 continue;
2583 }
2584 if (info.operation == Qt::IntersectClip) {
2585 // Use rect intersection if possible.
2586 if (matrix.type() <= QTransform::TxScale)
2587 region &= matrix.mapRect(info.rect);
2588 else
2589 region &= matrix.map(QRegion(info.rect));
2590 } else if (info.operation == Qt::NoClip) {
2591 lastWasNothing = true;
2592 region = QRegion();
2593 } else {
2594 region = QRegion(info.rect) * matrix;
2595 }
2596 break;
2597 }
2598
2599 case QPainterClipInfo::RectFClip: {
2600 QTransform matrix = (info.matrix * d->invMatrix);
2601 if (lastWasNothing) {
2602 region = QRegion(info.rectf.toRect()) * matrix;
2603 lastWasNothing = false;
2604 continue;
2605 }
2606 if (info.operation == Qt::IntersectClip) {
2607 // Use rect intersection if possible.
2608 if (matrix.type() <= QTransform::TxScale)
2609 region &= matrix.mapRect(info.rectf.toRect());
2610 else
2611 region &= matrix.map(QRegion(info.rectf.toRect()));
2612 } else if (info.operation == Qt::NoClip) {
2613 lastWasNothing = true;
2614 region = QRegion();
2615 } else {
2616 region = QRegion(info.rectf.toRect()) * matrix;
2617 }
2618 break;
2619 }
2620 }
2621 }
2622
2623 return region;
2624}
2625
2626extern QPainterPath qt_regionToPath(const QRegion &region);
2627
2628/*!
2629 Returns the current clip path in logical coordinates.
2630
2631 \warning QPainter does not store the combined clip explicitly as
2632 this is handled by the underlying QPaintEngine, so the path is
2633 recreated on demand and transformed to the current logical
2634 coordinate system. This is potentially an expensive operation.
2635
2636 \sa setClipPath(), clipRegion(), setClipping()
2637*/
2638QPainterPath QPainter::clipPath() const
2639{
2640 Q_D(const QPainter);
2641
2642 // ### Since we do not support path intersections and path unions yet,
2643 // we just use clipRegion() here...
2644 if (!d->engine) {
2645 qWarning("QPainter::clipPath: Painter not active");
2646 return QPainterPath();
2647 }
2648
2649 // No clip, return empty
2650 if (d->state->clipInfo.isEmpty()) {
2651 return QPainterPath();
2652 } else {
2653
2654 // Update inverse matrix, used below.
2655 if (!d->txinv)
2656 const_cast<QPainter *>(this)->d_ptr->updateInvMatrix();
2657
2658 // For the simple case avoid conversion.
2659 if (d->state->clipInfo.size() == 1
2660 && d->state->clipInfo.at(0).clipType == QPainterClipInfo::PathClip) {
2661 QTransform matrix = (d->state->clipInfo.at(0).matrix * d->invMatrix);
2662 return d->state->clipInfo.at(0).path * matrix;
2663
2664 } else if (d->state->clipInfo.size() == 1
2665 && d->state->clipInfo.at(0).clipType == QPainterClipInfo::RectClip) {
2666 QTransform matrix = (d->state->clipInfo.at(0).matrix * d->invMatrix);
2667 QPainterPath path;
2668 path.addRect(d->state->clipInfo.at(0).rect);
2669 return path * matrix;
2670 } else {
2671 // Fallback to clipRegion() for now, since we don't have isect/unite for paths
2672 return qt_regionToPath(clipRegion());
2673 }
2674 }
2675}
2676
2677/*!
2678 Returns the bounding rectangle of the current clip if there is a clip;
2679 otherwise returns an empty rectangle. Note that the clip region is
2680 given in logical coordinates.
2681
2682 The bounding rectangle is not guaranteed to be tight.
2683
2684 \sa setClipRect(), setClipPath(), setClipRegion()
2685
2686 \since 4.8
2687 */
2688
2689QRectF QPainter::clipBoundingRect() const
2690{
2691 Q_D(const QPainter);
2692
2693 if (!d->engine) {
2694 qWarning("QPainter::clipBoundingRect: Painter not active");
2695 return QRectF();
2696 }
2697
2698 // Accumulate the bounding box in device space. This is not 100%
2699 // precise, but it fits within the guarantee and it is reasonably
2700 // fast.
2701 QRectF bounds;
2702 bool first = true;
2703 for (const QPainterClipInfo &info : qAsConst(d->state->clipInfo)) {
2704 QRectF r;
2705
2706 if (info.clipType == QPainterClipInfo::RectClip)
2707 r = info.rect;
2708 else if (info.clipType == QPainterClipInfo::RectFClip)
2709 r = info.rectf;
2710 else if (info.clipType == QPainterClipInfo::RegionClip)
2711 r = info.region.boundingRect();
2712 else
2713 r = info.path.boundingRect();
2714
2715 r = info.matrix.mapRect(r);
2716
2717 if (first)
2718 bounds = r;
2719 else if (info.operation == Qt::IntersectClip)
2720 bounds &= r;
2721 first = false;
2722 }
2723
2724
2725 // Map the rectangle back into logical space using the inverse
2726 // matrix.
2727 if (!d->txinv)
2728 const_cast<QPainter *>(this)->d_ptr->updateInvMatrix();
2729
2730 return d->invMatrix.mapRect(bounds);
2731}
2732
2733/*!
2734 \fn void QPainter::setClipRect(const QRectF &rectangle, Qt::ClipOperation operation)
2735
2736 Enables clipping, and sets the clip region to the given \a
2737 rectangle using the given clip \a operation. The default operation
2738 is to replace the current clip rectangle.
2739
2740 Note that the clip rectangle is specified in logical (painter)
2741 coordinates.
2742
2743 \sa clipRegion(), setClipping(), {QPainter#Clipping}{Clipping}
2744*/
2745void QPainter::setClipRect(const QRectF &rect, Qt::ClipOperation op)
2746{
2747 Q_D(QPainter);
2748
2749 if (d->extended) {
2750 if (!d->engine) {
2751 qWarning("QPainter::setClipRect: Painter not active");
2752 return;
2753 }
2754 bool simplifyClipOp = (paintEngine()->type() != QPaintEngine::Picture);
2755 if (simplifyClipOp && (!d->state->clipEnabled && op != Qt::NoClip))
2756 op = Qt::ReplaceClip;
2757
2758 qreal right = rect.x() + rect.width();
2759 qreal bottom = rect.y() + rect.height();
2760 qreal pts[] = { rect.x(), rect.y(),
2761 right, rect.y(),
2762 right, bottom,
2763 rect.x(), bottom };
2764 QVectorPath vp(pts, 4, 0, QVectorPath::RectangleHint);
2765 d->state->clipEnabled = true;
2766 d->extended->clip(vp, op);
2767 if (op == Qt::ReplaceClip || op == Qt::NoClip)
2768 d->state->clipInfo.clear();
2769 d->state->clipInfo.append(QPainterClipInfo(rect, op, d->state->matrix));
2770 d->state->clipOperation = op;
2771 return;
2772 }
2773
2774 if (qreal(int(rect.top())) == rect.top()
2775 && qreal(int(rect.bottom())) == rect.bottom()
2776 && qreal(int(rect.left())) == rect.left()
2777 && qreal(int(rect.right())) == rect.right())
2778 {
2779 setClipRect(rect.toRect(), op);
2780 return;
2781 }
2782
2783 if (rect.isEmpty()) {
2784 setClipRegion(QRegion(), op);
2785 return;
2786 }
2787
2788 QPainterPath path;
2789 path.addRect(rect);
2790 setClipPath(path, op);
2791}
2792
2793/*!
2794 \fn void QPainter::setClipRect(const QRect &rectangle, Qt::ClipOperation operation)
2795 \overload
2796
2797 Enables clipping, and sets the clip region to the given \a rectangle using the given
2798 clip \a operation.
2799*/
2800void QPainter::setClipRect(const QRect &rect, Qt::ClipOperation op)
2801{
2802 Q_D(QPainter);
2803
2804 if (!d->engine) {
2805 qWarning("QPainter::setClipRect: Painter not active");
2806 return;
2807 }
2808 bool simplifyClipOp = (paintEngine()->type() != QPaintEngine::Picture);
2809
2810 if (simplifyClipOp && (!d->state->clipEnabled && op != Qt::NoClip))
2811 op = Qt::ReplaceClip;
2812
2813 if (d->extended) {
2814 d->state->clipEnabled = true;
2815 d->extended->clip(rect, op);
2816 if (op == Qt::ReplaceClip || op == Qt::NoClip)
2817 d->state->clipInfo.clear();
2818 d->state->clipInfo.append(QPainterClipInfo(rect, op, d->state->matrix));
2819 d->state->clipOperation = op;
2820 return;
2821 }
2822
2823 if (simplifyClipOp && d->state->clipOperation == Qt::NoClip && op == Qt::IntersectClip)
2824 op = Qt::ReplaceClip;
2825
2826 d->state->clipRegion = rect;
2827 d->state->clipOperation = op;
2828 if (op == Qt::NoClip || op == Qt::ReplaceClip)
2829 d->state->clipInfo.clear();
2830 d->state->clipInfo.append(QPainterClipInfo(rect, op, d->state->matrix));
2831 d->state->clipEnabled = true;
2832 d->state->dirtyFlags |= QPaintEngine::DirtyClipRegion | QPaintEngine::DirtyClipEnabled;
2833 d->updateState(d->state);
2834}
2835
2836/*!
2837 \fn void QPainter::setClipRect(int x, int y, int width, int height, Qt::ClipOperation operation)
2838
2839 Enables clipping, and sets the clip region to the rectangle beginning at (\a x, \a y)
2840 with the given \a width and \a height.
2841*/
2842
2843/*!
2844 \fn void QPainter::setClipRegion(const QRegion &region, Qt::ClipOperation operation)
2845
2846 Sets the clip region to the given \a region using the specified clip
2847 \a operation. The default clip operation is to replace the current
2848 clip region.
2849
2850 Note that the clip region is given in logical coordinates.
2851
2852 \sa clipRegion(), setClipRect(), {QPainter#Clipping}{Clipping}
2853*/
2854void QPainter::setClipRegion(const QRegion &r, Qt::ClipOperation op)
2855{
2856 Q_D(QPainter);
2857#ifdef QT_DEBUG_DRAW
2858 QRect rect = r.boundingRect();
2859 if (qt_show_painter_debug_output)
2860 printf("QPainter::setClipRegion(), size=%d, [%d,%d,%d,%d]\n",
2861 r.rectCount(), rect.x(), rect.y(), rect.width(), rect.height());
2862#endif
2863 if (!d->engine) {
2864 qWarning("QPainter::setClipRegion: Painter not active");
2865 return;
2866 }
2867 bool simplifyClipOp = (paintEngine()->type() != QPaintEngine::Picture);
2868
2869 if (simplifyClipOp && (!d->state->clipEnabled && op != Qt::NoClip))
2870 op = Qt::ReplaceClip;
2871
2872 if (d->extended) {
2873 d->state->clipEnabled = true;
2874 d->extended->clip(r, op);
2875 if (op == Qt::NoClip || op == Qt::ReplaceClip)
2876 d->state->clipInfo.clear();
2877 d->state->clipInfo.append(QPainterClipInfo(r, op, d->state->matrix));
2878 d->state->clipOperation = op;
2879 return;
2880 }
2881
2882 if (simplifyClipOp && d->state->clipOperation == Qt::NoClip && op == Qt::IntersectClip)
2883 op = Qt::ReplaceClip;
2884
2885 d->state->clipRegion = r;
2886 d->state->clipOperation = op;
2887 if (op == Qt::NoClip || op == Qt::ReplaceClip)
2888 d->state->clipInfo.clear();
2889 d->state->clipInfo.append(QPainterClipInfo(r, op, d->state->matrix));
2890 d->state->clipEnabled = true;
2891 d->state->dirtyFlags |= QPaintEngine::DirtyClipRegion | QPaintEngine::DirtyClipEnabled;
2892 d->updateState(d->state);
2893}
2894
2895#if QT_DEPRECATED_SINCE(5, 13)
2896/*!
2897 \since 4.2
2898 \obsolete
2899
2900 Sets the transformation matrix to \a matrix and enables transformations.
2901
2902 \note It is advisable to use setWorldTransform() instead of this function to
2903 preserve the properties of perspective transformations.
2904
2905 If \a combine is true, then \a matrix is combined with the current
2906 transformation matrix; otherwise \a matrix replaces the current
2907 transformation matrix.
2908
2909 If \a matrix is the identity matrix and \a combine is false, this
2910 function calls setWorldMatrixEnabled(false). (The identity matrix is the
2911 matrix where QMatrix::m11() and QMatrix::m22() are 1.0 and the
2912 rest are 0.0.)
2913
2914 The following functions can transform the coordinate system without using
2915 a QMatrix:
2916 \list
2917 \li translate()
2918 \li scale()
2919 \li shear()
2920 \li rotate()
2921 \endlist
2922
2923 They operate on the painter's worldMatrix() and are implemented like this:
2924
2925 \snippet code/src_gui_painting_qpainter.cpp 4
2926
2927 Note that when using setWorldMatrix() function you should always have
2928 \a combine be true when you are drawing into a QPicture. Otherwise
2929 it may not be possible to replay the picture with additional
2930 transformations; using the translate(), scale(), etc. convenience
2931 functions is safe.
2932
2933 For more information about the coordinate system, transformations
2934 and window-viewport conversion, see \l {Coordinate System}.
2935
2936 \sa setWorldTransform(), QTransform
2937*/
2938
2939void QPainter::setWorldMatrix(const QMatrix &matrix, bool combine)
2940{
2941 setWorldTransform(QTransform(matrix), combine);
2942}
2943
2944/*!
2945 \since 4.2
2946 \obsolete
2947
2948 Returns the world transformation matrix.
2949
2950 It is advisable to use worldTransform() because worldMatrix() does not
2951 preserve the properties of perspective transformations.
2952
2953 \sa {QPainter#Coordinate Transformations}{Coordinate Transformations},
2954 {Coordinate System}
2955*/
2956
2957const QMatrix &QPainter::worldMatrix() const
2958{
2959 Q_D(const QPainter);
2960 if (!d->engine) {
2961 qWarning("QPainter::worldMatrix: Painter not active");
2962 return d->fakeState()->transform.toAffine();
2963 }
2964 return d->state->worldMatrix.toAffine();
2965}
2966
2967/*!
2968 \obsolete
2969
2970 Use setWorldTransform() instead.
2971
2972 \sa setWorldTransform()
2973*/
2974
2975void QPainter::setMatrix(const QMatrix &matrix, bool combine)
2976{
2977 setWorldTransform(QTransform(matrix), combine);
2978}
2979
2980/*!
2981 \obsolete
2982
2983 Use worldTransform() instead.
2984
2985 \sa worldTransform()
2986*/
2987
2988const QMatrix &QPainter::matrix() const
2989{
2990QT_WARNING_PUSH
2991QT_WARNING_DISABLE_DEPRECATED
2992 return worldMatrix();
2993QT_WARNING_POP
2994}
2995
2996
2997/*!
2998 \since 4.2
2999 \obsolete
3000
3001 Returns the transformation matrix combining the current
3002 window/viewport and world transformation.
3003
3004 It is advisable to use combinedTransform() instead of this
3005 function to preserve the properties of perspective transformations.
3006
3007 \sa setWorldTransform(), setWindow(), setViewport()
3008*/
3009QMatrix QPainter::combinedMatrix() const
3010{
3011 return combinedTransform().toAffine();
3012}
3013
3014
3015/*!
3016 \obsolete
3017
3018 Returns the matrix that transforms from logical coordinates to
3019 device coordinates of the platform dependent paint device.
3020
3021 \note It is advisable to use deviceTransform() instead of this
3022 function to preserve the properties of perspective transformations.
3023
3024 This function is \e only needed when using platform painting
3025 commands on the platform dependent handle (Qt::HANDLE), and the
3026 platform does not do transformations nativly.
3027
3028 The QPaintEngine::PaintEngineFeature enum can be queried to
3029 determine whether the platform performs the transformations or
3030 not.
3031
3032 \sa worldMatrix(), QPaintEngine::hasFeature(),
3033*/
3034const QMatrix &QPainter::deviceMatrix() const
3035{
3036 Q_D(const QPainter);
3037 if (!d->engine) {
3038 qWarning("QPainter::deviceMatrix: Painter not active");
3039 return d->fakeState()->transform.toAffine();
3040 }
3041 return d->state->matrix.toAffine();
3042}
3043
3044/*!
3045 \obsolete
3046
3047 Resets any transformations that were made using translate(), scale(),
3048 shear(), rotate(), setWorldMatrix(), setViewport() and
3049 setWindow().
3050
3051 It is advisable to use resetTransform() instead of this function
3052 to preserve the properties of perspective transformations.
3053
3054 \sa {QPainter#Coordinate Transformations}{Coordinate
3055 Transformations}
3056*/
3057
3058void QPainter::resetMatrix()
3059{
3060 resetTransform();
3061}
3062#endif
3063
3064/*!
3065 \since 4.2
3066
3067 Enables transformations if \a enable is true, or disables
3068 transformations if \a enable is false. The world transformation
3069 matrix is not changed.
3070
3071 \sa worldMatrixEnabled(), worldTransform(), {QPainter#Coordinate
3072 Transformations}{Coordinate Transformations}
3073*/
3074
3075void QPainter::setWorldMatrixEnabled(bool enable)
3076{
3077 Q_D(QPainter);
3078#ifdef QT_DEBUG_DRAW
3079 if (qt_show_painter_debug_output)
3080 printf("QPainter::setMatrixEnabled(), enable=%d\n", enable);
3081#endif
3082
3083 if (!d->engine) {
3084 qWarning("QPainter::setMatrixEnabled: Painter not active");
3085 return;
3086 }
3087 if (enable == d->state->WxF)
3088 return;
3089
3090 d->state->WxF = enable;
3091 d->updateMatrix();
3092}
3093
3094/*!
3095 \since 4.2
3096
3097 Returns \c true if world transformation is enabled; otherwise returns
3098 false.
3099
3100 \sa setWorldMatrixEnabled(), worldTransform(), {Coordinate System}
3101*/
3102
3103bool QPainter::worldMatrixEnabled() const
3104{
3105 Q_D(const QPainter);
3106 if (!d->engine) {
3107 qWarning("QPainter::worldMatrixEnabled: Painter not active");
3108 return false;
3109 }
3110 return d->state->WxF;
3111}
3112
3113#if QT_DEPRECATED_SINCE(5, 13)
3114/*!
3115 \obsolete
3116
3117 Use setWorldMatrixEnabled() instead.
3118
3119 \sa setWorldMatrixEnabled()
3120*/
3121
3122void QPainter::setMatrixEnabled(bool enable)
3123{
3124 setWorldMatrixEnabled(enable);
3125}
3126
3127/*!
3128 \obsolete
3129
3130 Use worldMatrixEnabled() instead
3131
3132 \sa worldMatrixEnabled()
3133*/
3134
3135bool QPainter::matrixEnabled() const
3136{
3137 return worldMatrixEnabled();
3138}
3139#endif
3140
3141/*!
3142 Scales the coordinate system by (\a{sx}, \a{sy}).
3143
3144 \sa setWorldTransform(), {QPainter#Coordinate Transformations}{Coordinate Transformations}
3145*/
3146
3147void QPainter::scale(qreal sx, qreal sy)
3148{
3149#ifdef QT_DEBUG_DRAW
3150 if (qt_show_painter_debug_output)
3151 printf("QPainter::scale(), sx=%f, sy=%f\n", sx, sy);
3152#endif
3153 Q_D(QPainter);
3154 if (!d->engine) {
3155 qWarning("QPainter::scale: Painter not active");
3156 return;
3157 }
3158
3159 d->state->worldMatrix.scale(sx,sy);
3160 d->state->WxF = true;
3161 d->updateMatrix();
3162}
3163
3164/*!
3165 Shears the coordinate system by (\a{sh}, \a{sv}).
3166
3167 \sa setWorldTransform(), {QPainter#Coordinate Transformations}{Coordinate Transformations}
3168*/
3169
3170void QPainter::shear(qreal sh, qreal sv)
3171{
3172#ifdef QT_DEBUG_DRAW
3173 if (qt_show_painter_debug_output)
3174 printf("QPainter::shear(), sh=%f, sv=%f\n", sh, sv);
3175#endif
3176 Q_D(QPainter);
3177 if (!d->engine) {
3178 qWarning("QPainter::shear: Painter not active");
3179 return;
3180 }
3181
3182 d->state->worldMatrix.shear(sh, sv);
3183 d->state->WxF = true;
3184 d->updateMatrix();
3185}
3186
3187/*!
3188 \fn void QPainter::rotate(qreal angle)
3189
3190 Rotates the coordinate system clockwise. The given \a angle parameter is in degrees.
3191
3192 \sa setWorldTransform(), {QPainter#Coordinate Transformations}{Coordinate Transformations}
3193*/
3194
3195void QPainter::rotate(qreal a)
3196{
3197#ifdef QT_DEBUG_DRAW
3198 if (qt_show_painter_debug_output)
3199 printf("QPainter::rotate(), angle=%f\n", a);
3200#endif
3201 Q_D(QPainter);
3202 if (!d->engine) {
3203 qWarning("QPainter::rotate: Painter not active");
3204 return;
3205 }
3206
3207 d->state->worldMatrix.rotate(a);
3208 d->state->WxF = true;
3209 d->updateMatrix();
3210}
3211
3212/*!
3213 Translates the coordinate system by the given \a offset; i.e. the
3214 given \a offset is added to points.
3215
3216 \sa setWorldTransform(), {QPainter#Coordinate Transformations}{Coordinate Transformations}
3217*/
3218void QPainter::translate(const QPointF &offset)
3219{
3220 qreal dx = offset.x();
3221 qreal dy = offset.y();
3222#ifdef QT_DEBUG_DRAW
3223 if (qt_show_painter_debug_output)
3224 printf("QPainter::translate(), dx=%f, dy=%f\n", dx, dy);
3225#endif
3226 Q_D(QPainter);
3227 if (!d->engine) {
3228 qWarning("QPainter::translate: Painter not active");
3229 return;
3230 }
3231
3232 d->state->worldMatrix.translate(dx, dy);
3233 d->state->WxF = true;
3234 d->updateMatrix();
3235}
3236
3237/*!
3238 \fn void QPainter::translate(const QPoint &offset)
3239 \overload
3240
3241 Translates the coordinate system by the given \a offset.
3242*/
3243
3244/*!
3245 \fn void QPainter::translate(qreal dx, qreal dy)
3246 \overload
3247
3248 Translates the coordinate system by the vector (\a dx, \a dy).
3249*/
3250
3251/*!
3252 \fn void QPainter::setClipPath(const QPainterPath &path, Qt::ClipOperation operation)
3253
3254 Enables clipping, and sets the clip path for the painter to the
3255 given \a path, with the clip \a operation.
3256
3257 Note that the clip path is specified in logical (painter)
3258 coordinates.
3259
3260 \sa clipPath(), clipRegion(), {QPainter#Clipping}{Clipping}
3261
3262*/
3263void QPainter::setClipPath(const QPainterPath &path, Qt::ClipOperation op)
3264{
3265#ifdef QT_DEBUG_DRAW
3266 if (qt_show_painter_debug_output) {
3267 QRectF b = path.boundingRect();
3268 printf("QPainter::setClipPath(), size=%d, op=%d, bounds=[%.2f,%.2f,%.2f,%.2f]\n",
3269 path.elementCount(), op, b.x(), b.y(), b.width(), b.height());
3270 }
3271#endif
3272 Q_D(QPainter);
3273
3274 if (!d->engine) {
3275 qWarning("QPainter::setClipPath: Painter not active");
3276 return;
3277 }
3278
3279 if ((!d->state->clipEnabled && op != Qt::NoClip))
3280 op = Qt::ReplaceClip;
3281
3282 if (d->extended) {
3283 d->state->clipEnabled = true;
3284 d->extended->clip(path, op);
3285 if (op == Qt::NoClip || op == Qt::ReplaceClip)
3286 d->state->clipInfo.clear();
3287 d->state->clipInfo.append(QPainterClipInfo(path, op, d->state->matrix));
3288 d->state->clipOperation = op;
3289 return;
3290 }
3291
3292 if (d->state->clipOperation == Qt::NoClip && op == Qt::IntersectClip)
3293 op = Qt::ReplaceClip;
3294
3295 d->state->clipPath = path;
3296 d->state->clipOperation = op;
3297 if (op == Qt::NoClip || op == Qt::ReplaceClip)
3298 d->state->clipInfo.clear();
3299 d->state->clipInfo.append(QPainterClipInfo(path, op, d->state->matrix));
3300 d->state->clipEnabled = true;
3301 d->state->dirtyFlags |= QPaintEngine::DirtyClipPath | QPaintEngine::DirtyClipEnabled;
3302 d->updateState(d->state);
3303}
3304
3305/*!
3306 Draws the outline (strokes) the path \a path with the pen specified
3307 by \a pen
3308
3309 \sa fillPath(), {QPainter#Drawing}{Drawing}
3310*/
3311void QPainter::strokePath(const QPainterPath &path, const QPen &pen)
3312{
3313 Q_D(QPainter);
3314
3315 if (!d->engine) {
3316 qWarning("QPainter::strokePath: Painter not active");
3317 return;
3318 }
3319
3320 if (path.isEmpty())
3321 return;
3322
3323 if (d->extended) {
3324 const QGradient *g = qpen_brush(pen).gradient();
3325 if (!g || g->coordinateMode() == QGradient::LogicalMode) {
3326 d->extended->stroke(qtVectorPathForPath(path), pen);
3327 return;
3328 }
3329 }
3330
3331 QBrush oldBrush = d->state->brush;
3332 QPen oldPen = d->state->pen;
3333
3334 setPen(pen);
3335 setBrush(Qt::NoBrush);
3336
3337 drawPath(path);
3338
3339 // Reset old state
3340 setPen(oldPen);
3341 setBrush(oldBrush);
3342}
3343
3344/*!
3345 Fills the given \a path using the given \a brush. The outline is
3346 not drawn.
3347
3348 Alternatively, you can specify a QColor instead of a QBrush; the
3349 QBrush constructor (taking a QColor argument) will automatically
3350 create a solid pattern brush.
3351
3352 \sa drawPath()
3353*/
3354void QPainter::fillPath(const QPainterPath &path, const QBrush &brush)
3355{
3356 Q_D(QPainter);
3357
3358 if (!d->engine) {
3359 qWarning("QPainter::fillPath: Painter not active");
3360 return;
3361 }
3362
3363 if (path.isEmpty())
3364 return;
3365
3366 if (d->extended) {
3367 const QGradient *g = brush.gradient();
3368 if (!g || g->coordinateMode() == QGradient::LogicalMode) {
3369 d->extended->fill(qtVectorPathForPath(path), brush);
3370 return;
3371 }
3372 }
3373
3374 QBrush oldBrush = d->state->brush;
3375 QPen oldPen = d->state->pen;
3376
3377 setPen(Qt::NoPen);
3378 setBrush(brush);
3379
3380 drawPath(path);
3381
3382 // Reset old state
3383 setPen(oldPen);
3384 setBrush(oldBrush);
3385}
3386
3387/*!
3388 Draws the given painter \a path using the current pen for outline
3389 and the current brush for filling.
3390
3391 \table 100%
3392 \row
3393 \li \inlineimage qpainter-path.png
3394 \li
3395 \snippet code/src_gui_painting_qpainter.cpp 5
3396 \endtable
3397
3398 \sa {painting/painterpaths}{the Painter Paths
3399 example},{painting/deform}{the Vector Deformation example}
3400*/
3401void QPainter::drawPath(const QPainterPath &path)
3402{
3403#ifdef QT_DEBUG_DRAW
3404 QRectF pathBounds = path.boundingRect();
3405 if (qt_show_painter_debug_output)
3406 printf("QPainter::drawPath(), size=%d, [%.2f,%.2f,%.2f,%.2f]\n",
3407 path.elementCount(),
3408 pathBounds.x(), pathBounds.y(), pathBounds.width(), pathBounds.height());
3409#endif
3410
3411 Q_D(QPainter);
3412
3413 if (!d->engine) {
3414 qWarning("QPainter::drawPath: Painter not active");
3415 return;
3416 }
3417
3418 if (d->extended) {
3419 d->extended->drawPath(path);
3420 return;
3421 }
3422 d->updateState(d->state);
3423
3424 if (d->engine->hasFeature(QPaintEngine::PainterPaths) && d->state->emulationSpecifier == 0) {
3425 d->engine->drawPath(path);
3426 } else {
3427 d->draw_helper(path);
3428 }
3429}
3430
3431/*!
3432 \fn void QPainter::drawLine(const QLineF &line)
3433
3434 Draws a line defined by \a line.
3435
3436 \table 100%
3437 \row
3438 \li \inlineimage qpainter-line.png
3439 \li
3440 \snippet code/src_gui_painting_qpainter.cpp 6
3441 \endtable
3442
3443 \sa drawLines(), drawPolyline(), {Coordinate System}
3444*/
3445
3446/*!
3447 \fn void QPainter::drawLine(const QLine &line)
3448 \overload
3449
3450 Draws a line defined by \a line.
3451*/
3452
3453/*!
3454 \fn void QPainter::drawLine(const QPoint &p1, const QPoint &p2)
3455 \overload
3456
3457 Draws a line from \a p1 to \a p2.
3458*/
3459
3460/*!
3461 \fn void QPainter::drawLine(const QPointF &p1, const QPointF &p2)
3462 \overload
3463
3464 Draws a line from \a p1 to \a p2.
3465*/
3466
3467/*!
3468 \fn void QPainter::drawLine(int x1, int y1, int x2, int y2)
3469 \overload
3470
3471 Draws a line from (\a x1, \a y1) to (\a x2, \a y2).
3472*/
3473
3474/*!
3475 \fn void QPainter::drawRect(const QRectF &rectangle)
3476
3477 Draws the current \a rectangle with the current pen and brush.
3478
3479 A filled rectangle has a size of \a{rectangle}.size(). A stroked
3480 rectangle has a size of \a{rectangle}.size() plus the pen width.
3481
3482 \table 100%
3483 \row
3484 \li \inlineimage qpainter-rectangle.png
3485 \li
3486 \snippet code/src_gui_painting_qpainter.cpp 7
3487 \endtable
3488
3489 \sa drawRects(), drawPolygon(), {Coordinate System}
3490*/
3491
3492/*!
3493 \fn void QPainter::drawRect(const QRect &rectangle)
3494
3495 \overload
3496
3497 Draws the current \a rectangle with the current pen and brush.
3498*/
3499
3500/*!
3501 \fn void QPainter::drawRect(int x, int y, int width, int height)
3502
3503 \overload
3504
3505 Draws a rectangle with upper left corner at (\a{x}, \a{y}) and
3506 with the given \a width and \a height.
3507*/
3508
3509/*!
3510 \fn void QPainter::drawRects(const QRectF *rectangles, int rectCount)
3511
3512 Draws the first \a rectCount of the given \a rectangles using the
3513 current pen and brush.
3514
3515 \sa drawRect()
3516*/
3517void QPainter::drawRects(const QRectF *rects, int rectCount)
3518{
3519#ifdef QT_DEBUG_DRAW
3520 if (qt_show_painter_debug_output)
3521 printf("QPainter::drawRects(), count=%d\n", rectCount);
3522#endif
3523 Q_D(QPainter);
3524
3525 if (!d->engine) {
3526 qWarning("QPainter::drawRects: Painter not active");
3527 return;
3528 }
3529
3530 if (rectCount <= 0)
3531 return;
3532
3533 if (d->extended) {
3534 d->extended->drawRects(rects, rectCount);
3535 return;
3536 }
3537
3538 d->updateState(d->state);
3539
3540 if (!d->state->emulationSpecifier) {
3541 d->engine->drawRects(rects, rectCount);
3542 return;
3543 }
3544
3545 if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
3546 && d->state->matrix.type() == QTransform::TxTranslate) {
3547 for (int i=0; i<rectCount; ++i) {
3548 QRectF r(rects[i].x() + d->state->matrix.dx(),
3549 rects[i].y() + d->state->matrix.dy(),
3550 rects[i].width(),
3551 rects[i].height());
3552 d->engine->drawRects(&r, 1);
3553 }
3554 } else {
3555 if (d->state->brushNeedsResolving() || d->state->penNeedsResolving()) {
3556 for (int i=0; i<rectCount; ++i) {
3557 QPainterPath rectPath;
3558 rectPath.addRect(rects[i]);
3559 d->draw_helper(rectPath, QPainterPrivate::StrokeAndFillDraw);
3560 }
3561 } else {
3562 QPainterPath rectPath;
3563 for (int i=0; i<rectCount; ++i)
3564 rectPath.addRect(rects[i]);
3565 d->draw_helper(rectPath, QPainterPrivate::StrokeAndFillDraw);
3566 }
3567 }
3568}
3569
3570/*!
3571 \fn void QPainter::drawRects(const QRect *rectangles, int rectCount)
3572 \overload
3573
3574 Draws the first \a rectCount of the given \a rectangles using the
3575 current pen and brush.
3576*/
3577void QPainter::drawRects(const QRect *rects, int rectCount)
3578{
3579#ifdef QT_DEBUG_DRAW
3580 if (qt_show_painter_debug_output)
3581 printf("QPainter::drawRects(), count=%d\n", rectCount);
3582#endif
3583 Q_D(QPainter);
3584
3585 if (!d->engine) {
3586 qWarning("QPainter::drawRects: Painter not active");
3587 return;
3588 }
3589
3590 if (rectCount <= 0)
3591 return;
3592
3593 if (d->extended) {
3594 d->extended->drawRects(rects, rectCount);
3595 return;
3596 }
3597
3598 d->updateState(d->state);
3599
3600 if (!d->state->emulationSpecifier) {
3601 d->engine->drawRects(rects, rectCount);
3602 return;
3603 }
3604
3605 if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
3606 && d->state->matrix.type() == QTransform::TxTranslate) {
3607 for (int i=0; i<rectCount; ++i) {
3608 QRectF r(rects[i].x() + d->state->matrix.dx(),
3609 rects[i].y() + d->state->matrix.dy(),
3610 rects[i].width(),
3611 rects[i].height());
3612
3613 d->engine->drawRects(&r, 1);
3614 }
3615 } else {
3616 if (d->state->brushNeedsResolving() || d->state->penNeedsResolving()) {
3617 for (int i=0; i<rectCount; ++i) {
3618 QPainterPath rectPath;
3619 rectPath.addRect(rects[i]);
3620 d->draw_helper(rectPath, QPainterPrivate::StrokeAndFillDraw);
3621 }
3622 } else {
3623 QPainterPath rectPath;
3624 for (int i=0; i<rectCount; ++i)
3625 rectPath.addRect(rects[i]);
3626
3627 d->draw_helper(rectPath, QPainterPrivate::StrokeAndFillDraw);
3628 }
3629 }
3630}
3631
3632/*!
3633 \fn void QPainter::drawRects(const QVector<QRectF> &rectangles)
3634 \overload
3635
3636 Draws the given \a rectangles using the current pen and brush.
3637*/
3638
3639/*!
3640 \fn void QPainter::drawRects(const QVector<QRect> &rectangles)
3641
3642 \overload
3643
3644 Draws the given \a rectangles using the current pen and brush.
3645*/
3646
3647/*!
3648 \fn void QPainter::drawPoint(const QPointF &position)
3649
3650 Draws a single point at the given \a position using the current
3651 pen's color.
3652
3653 \sa {Coordinate System}
3654*/
3655
3656/*!
3657 \fn void QPainter::drawPoint(const QPoint &position)
3658 \overload
3659
3660 Draws a single point at the given \a position using the current
3661 pen's color.
3662*/
3663
3664/*! \fn void QPainter::drawPoint(int x, int y)
3665
3666 \overload
3667
3668 Draws a single point at position (\a x, \a y).
3669*/
3670
3671/*!
3672 Draws the first \a pointCount points in the array \a points using
3673 the current pen's color.
3674
3675 \sa {Coordinate System}
3676*/
3677void QPainter::drawPoints(const QPointF *points, int pointCount)
3678{
3679#ifdef QT_DEBUG_DRAW
3680 if (qt_show_painter_debug_output)
3681 printf("QPainter::drawPoints(), count=%d\n", pointCount);
3682#endif
3683 Q_D(QPainter);
3684
3685 if (!d->engine) {
3686 qWarning("QPainter::drawPoints: Painter not active");
3687 return;
3688 }
3689
3690 if (pointCount <= 0)
3691 return;
3692
3693 if (d->extended) {
3694 d->extended->drawPoints(points, pointCount);
3695 return;
3696 }
3697
3698 d->updateState(d->state);
3699
3700 if (!d->state->emulationSpecifier) {
3701 d->engine->drawPoints(points, pointCount);
3702 return;
3703 }
3704
3705 if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
3706 && d->state->matrix.type() == QTransform::TxTranslate) {
3707 // ### use drawPoints function
3708 for (int i=0; i<pointCount; ++i) {
3709 QPointF pt(points[i].x() + d->state->matrix.dx(),
3710 points[i].y() + d->state->matrix.dy());
3711 d->engine->drawPoints(&pt, 1);
3712 }
3713 } else {
3714 QPen pen = d->state->pen;
3715 bool flat_pen = pen.capStyle() == Qt::FlatCap;
3716 if (