1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the QtGui module of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
50 #include "qpaintdevice.h"
51 #include "qpaintengine.h"
53 #include "qpainter_p.h"
54 #include "qpainterpath.h"
56 #include "qpixmapcache.h"
58 #include "qtextlayout.h"
60 #include "qvarlengtharray.h"
61 #include "qstatictext.h"
62 #include "qglyphrun.h"
64 #include <private/qfontengine_p.h>
65 #include <private/qpaintengine_p.h>
66 #include <private/qemulationpaintengine_p.h>
67 #include <private/qpainterpath_p.h>
68 #include <private/qtextengine_p.h>
69 #include <private/qpaintengine_raster_p.h>
70 #include <private/qmath_p.h>
71 #include <private/qstatictext_p.h>
72 #include <private/qglyphrun_p.h>
73 #include <private/qhexstring_p.h>
74 #include <private/qguiapplication_p.h>
75 #include <private/qrawfont_p.h>
79 #define QGradient_StretchToDevice 0x10000000
80 #define QPaintEngine_OpaqueBackground 0x40000000
82 // #define QT_DEBUG_DRAW
84 bool qt_show_painter_debug_output = true;
87 extern QPixmap qt_pixmapForBrush(int style, bool invert);
89 void qt_format_text(const QFont &font,
90 const QRectF &_r, int tf, const QTextOption *option, const QString& str, QRectF *brect,
91 int tabstops, int* tabarray, int tabarraylen,
93 static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const QFontEngine *fe, QTextEngine *textEngine,
94 QTextCharFormat::UnderlineStyle underlineStyle,
95 QTextItem::RenderFlags flags, qreal width,
96 const QTextCharFormat &charFormat);
97 // Helper function to calculate left most position, width and flags for decoration drawing
98 Q_GUI_EXPORT void qt_draw_decoration_for_glyphs(QPainter *painter, const glyph_t *glyphArray,
99 const QFixedPoint *positions, int glyphCount,
100 QFontEngine *fontEngine, const QFont &font,
101 const QTextCharFormat &charFormat);
103 static inline QGradient::CoordinateMode coordinateMode(const QBrush &brush)
105 switch (brush.style()) {
106 case Qt::LinearGradientPattern:
107 case Qt::RadialGradientPattern:
108 case Qt::ConicalGradientPattern:
109 return brush.gradient()->coordinateMode();
113 return QGradient::LogicalMode;
116 /* Returns true if the gradient requires stretch to device...*/
117 static inline bool check_gradient(const QBrush &brush)
119 return coordinateMode(brush) == QGradient::StretchToDeviceMode;
122 extern bool qHasPixmapTexture(const QBrush &);
124 static inline bool is_brush_transparent(const QBrush &brush) {
125 Qt::BrushStyle s = brush.style();
126 bool brushBitmap = qHasPixmapTexture(brush)
127 ? brush.texture().isQBitmap()
128 : (brush.textureImage().depth() == 1);
129 return ((s >= Qt::Dense1Pattern && s <= Qt::DiagCrossPattern)
130 || (s == Qt::TexturePattern && brushBitmap));
133 static inline bool is_pen_transparent(const QPen &pen) {
134 return pen.style() > Qt::SolidLine || is_brush_transparent(pen.brush());
137 /* Discards the emulation flags that are not relevant for line drawing
138 and returns the result
140 static inline uint line_emulation(uint emulation)
142 return emulation & (QPaintEngine::PrimitiveTransform
143 | QPaintEngine::AlphaBlend
144 | QPaintEngine::Antialiasing
145 | QPaintEngine::BrushStroke
146 | QPaintEngine::ConstantOpacity
147 | QGradient_StretchToDevice
148 | QPaintEngine::ObjectBoundingModeGradients
149 | QPaintEngine_OpaqueBackground);
153 static bool qt_painter_thread_test(int devType, const char *what, bool extraCondition = false)
156 case QInternal::Image:
157 case QInternal::Printer:
158 case QInternal::Picture:
159 // can be drawn onto these devices safely from any thread
163 if (!extraCondition && QThread::currentThread() != qApp->thread()) {
164 qWarning("QPainter: It is not safe to use %s outside the GUI thread", what);
173 void QPainterPrivate::checkEmulation()
176 if (extended->flags() & QPaintEngineEx::DoNotEmulate)
179 bool doEmulation = false;
180 if (state->bgMode == Qt::OpaqueMode)
183 const QGradient *bg = state->brush.gradient();
184 if (bg && bg->coordinateMode() > QGradient::LogicalMode)
187 const QGradient *pg = qpen_brush(state->pen).gradient();
188 if (pg && pg->coordinateMode() > QGradient::LogicalMode)
192 if (extended != emulationEngine) {
193 if (!emulationEngine)
194 emulationEngine = new QEmulationPaintEngine(extended);
195 extended = emulationEngine;
196 extended->setState(state);
198 } else if (emulationEngine == extended) {
199 extended = emulationEngine->real_engine;
204 QPainterPrivate::~QPainterPrivate()
206 delete emulationEngine;
207 for (int i=0; i<states.size(); ++i)
215 QTransform QPainterPrivate::viewTransform() const
218 qreal scaleW = qreal(state->vw)/qreal(state->ww);
219 qreal scaleH = qreal(state->vh)/qreal(state->wh);
220 return QTransform(scaleW, 0, 0, scaleH,
221 state->vx - state->wx*scaleW, state->vy - state->wy*scaleH);
229 Returns true if using a shared painter; otherwise false.
231 bool QPainterPrivate::attachPainterPrivate(QPainter *q, QPaintDevice *pdev)
236 QPainter *sp = pdev->sharedPainter();
240 // Save the current state of the shared painter and assign
241 // the current d_ptr to the shared painter's d_ptr.
243 if (!sp->d_ptr->d_ptrs) {
244 // Allocate space for 4 d-pointers (enough for up to 4 sub-sequent
245 // redirections within the same paintEvent(), which should be enough
246 // in 99% of all cases). E.g: A renders B which renders C which renders D.
247 sp->d_ptr->d_ptrs_size = 4;
248 sp->d_ptr->d_ptrs = (QPainterPrivate **)malloc(4 * sizeof(QPainterPrivate *));
249 Q_CHECK_PTR(sp->d_ptr->d_ptrs);
250 } else if (sp->d_ptr->refcount - 1 == sp->d_ptr->d_ptrs_size) {
251 // However, to support corner cases we grow the array dynamically if needed.
252 sp->d_ptr->d_ptrs_size <<= 1;
253 const int newSize = sp->d_ptr->d_ptrs_size * sizeof(QPainterPrivate *);
254 sp->d_ptr->d_ptrs = q_check_ptr((QPainterPrivate **)realloc(sp->d_ptr->d_ptrs, newSize));
256 sp->d_ptr->d_ptrs[++sp->d_ptr->refcount - 2] = q->d_ptr.data();
258 q->d_ptr.reset(sp->d_ptr.data());
260 Q_ASSERT(q->d_ptr->state);
262 // Now initialize the painter with correct widget properties.
265 pdev->redirected(&offset);
266 offset += q->d_ptr->engine->coordinateOffset();
268 // Update system rect.
269 q->d_ptr->state->ww = q->d_ptr->state->vw = pdev->width();
270 q->d_ptr->state->wh = q->d_ptr->state->vh = pdev->height();
273 if (q->d_ptr->state->WxF) {
274 q->d_ptr->state->redirectionMatrix = q->d_ptr->state->matrix;
275 q->d_ptr->state->redirectionMatrix.translate(-offset.x(), -offset.y());
276 q->d_ptr->state->worldMatrix = QTransform();
277 q->d_ptr->state->WxF = false;
279 q->d_ptr->state->redirectionMatrix = QTransform::fromTranslate(-offset.x(), -offset.y());
281 q->d_ptr->updateMatrix();
283 QPaintEnginePrivate *enginePrivate = q->d_ptr->engine->d_func();
284 if (enginePrivate->currentClipDevice == pdev) {
285 enginePrivate->systemStateChanged();
289 // Update system transform and clip.
290 enginePrivate->currentClipDevice = pdev;
291 enginePrivate->setSystemTransform(q->d_ptr->state->matrix);
295 void QPainterPrivate::detachPainterPrivate(QPainter *q)
297 Q_ASSERT(refcount > 1);
300 QPainterPrivate *original = d_ptrs[--refcount - 1];
302 inDestructor = false;
304 original->inDestructor = true;
305 } else if (!original) {
306 original = new QPainterPrivate(q);
309 d_ptrs[refcount - 1] = 0;
312 q->d_ptr.reset(original);
314 if (emulationEngine) {
315 extended = emulationEngine->real_engine;
316 delete emulationEngine;
322 void QPainterPrivate::draw_helper(const QPainterPath &originalPath, DrawOperation op)
325 if (qt_show_painter_debug_output) {
326 printf("QPainter::drawHelper\n");
330 if (originalPath.isEmpty())
333 QPaintEngine::PaintEngineFeatures gradientStretch =
334 QPaintEngine::PaintEngineFeatures(QGradient_StretchToDevice
335 | QPaintEngine::ObjectBoundingModeGradients);
337 const bool mustEmulateObjectBoundingModeGradients = extended
338 || ((state->emulationSpecifier & QPaintEngine::ObjectBoundingModeGradients)
339 && !engine->hasFeature(QPaintEngine::PatternTransform));
341 if (!(state->emulationSpecifier & ~gradientStretch)
342 && !mustEmulateObjectBoundingModeGradients) {
343 drawStretchedGradient(originalPath, op);
345 } else if (state->emulationSpecifier & QPaintEngine_OpaqueBackground) {
346 drawOpaqueBackground(originalPath, op);
352 qreal strokeOffsetX = 0, strokeOffsetY = 0;
354 QPainterPath path = originalPath * state->matrix;
355 QRectF pathBounds = path.boundingRect();
357 bool doStroke = (op & StrokeDraw) && (state->pen.style() != Qt::NoPen);
359 qreal penWidth = state->pen.widthF();
364 // In case of complex xform
365 if (state->matrix.type() > QTransform::TxScale) {
366 QPainterPathStroker stroker;
367 stroker.setWidth(penWidth);
368 stroker.setJoinStyle(state->pen.joinStyle());
369 stroker.setCapStyle(state->pen.capStyle());
370 QPainterPath stroke = stroker.createStroke(originalPath);
371 strokeBounds = (stroke * state->matrix).boundingRect();
373 strokeOffsetX = qAbs(penWidth * state->matrix.m11() / 2.0);
374 strokeOffsetY = qAbs(penWidth * state->matrix.m22() / 2.0);
380 if (!strokeBounds.isEmpty()) {
381 absPathRect = strokeBounds.intersected(QRectF(0, 0, device->width(), device->height())).toAlignedRect();
383 absPathRect = pathBounds.adjusted(-strokeOffsetX, -strokeOffsetY, strokeOffsetX, strokeOffsetY)
384 .intersected(QRectF(0, 0, device->width(), device->height())).toAlignedRect();
387 if (q->hasClipping()) {
388 bool hasPerspectiveTransform = false;
389 for (int i = 0; i < state->clipInfo.size(); ++i) {
390 const QPainterClipInfo &info = state->clipInfo.at(i);
391 if (info.matrix.type() == QTransform::TxProject) {
392 hasPerspectiveTransform = true;
396 // avoid mapping QRegions with perspective transforms
397 if (!hasPerspectiveTransform) {
398 // The trick with txinv and invMatrix is done in order to
399 // avoid transforming the clip to logical coordinates, and
400 // then back to device coordinates. This is a problem with
401 // QRegion/QRect based clips, since they use integer
402 // coordinates and converting to/from logical coordinates will
404 bool old_txinv = txinv;
405 QTransform old_invMatrix = invMatrix;
407 invMatrix = QTransform();
408 QPainterPath clipPath = q->clipPath();
409 QRectF r = clipPath.boundingRect().intersected(absPathRect);
410 absPathRect = r.toAlignedRect();
412 invMatrix = old_invMatrix;
416 // qDebug("\nQPainterPrivate::draw_helper(), x=%d, y=%d, w=%d, h=%d",
417 // devMinX, devMinY, device->width(), device->height());
418 // qDebug() << " - matrix" << state->matrix;
419 // qDebug() << " - originalPath.bounds" << originalPath.boundingRect();
420 // qDebug() << " - path.bounds" << path.boundingRect();
422 if (absPathRect.width() <= 0 || absPathRect.height() <= 0)
425 QImage image(absPathRect.width(), absPathRect.height(), QImage::Format_ARGB32_Premultiplied);
430 p.d_ptr->helper_device = helper_device;
432 p.setOpacity(state->opacity);
433 p.translate(-absPathRect.x(), -absPathRect.y());
434 p.setTransform(state->matrix, true);
435 p.setPen(doStroke ? state->pen : QPen(Qt::NoPen));
436 p.setBrush((op & FillDraw) ? state->brush : QBrush(Qt::NoBrush));
437 p.setBackground(state->bgBrush);
438 p.setBackgroundMode(state->bgMode);
439 p.setBrushOrigin(state->brushOrigin);
441 p.setRenderHint(QPainter::Antialiasing, state->renderHints & QPainter::Antialiasing);
442 p.setRenderHint(QPainter::SmoothPixmapTransform,
443 state->renderHints & QPainter::SmoothPixmapTransform);
445 p.drawPath(originalPath);
448 static bool do_fallback_overlay = qgetenv("QT_PAINT_FALLBACK_OVERLAY").size() > 0;
449 if (do_fallback_overlay) {
450 QImage block(8, 8, QImage::Format_ARGB32_Premultiplied);
452 pt.fillRect(0, 0, 8, 8, QColor(196, 0, 196));
453 pt.drawLine(0, 0, 8, 8);
456 p.setCompositionMode(QPainter::CompositionMode_SourceAtop);
458 p.fillRect(0, 0, image.width(), image.height(), QBrush(block));
465 state->matrix = QTransform();
467 extended->transformChanged();
469 state->dirtyFlags |= QPaintEngine::DirtyTransform;
472 engine->drawImage(absPathRect,
474 QRectF(0, 0, absPathRect.width(), absPathRect.height()),
475 Qt::OrderedDither | Qt::OrderedAlphaDither);
479 void QPainterPrivate::drawOpaqueBackground(const QPainterPath &path, DrawOperation op)
483 q->setBackgroundMode(Qt::TransparentMode);
485 if (op & FillDraw && state->brush.style() != Qt::NoBrush) {
486 q->fillPath(path, state->bgBrush.color());
487 q->fillPath(path, state->brush);
490 if (op & StrokeDraw && state->pen.style() != Qt::NoPen) {
491 q->strokePath(path, QPen(state->bgBrush.color(), state->pen.width()));
492 q->strokePath(path, state->pen);
495 q->setBackgroundMode(Qt::OpaqueMode);
498 static inline QBrush stretchGradientToUserSpace(const QBrush &brush, const QRectF &boundingRect)
500 Q_ASSERT(brush.style() >= Qt::LinearGradientPattern
501 && brush.style() <= Qt::ConicalGradientPattern);
503 QTransform gradientToUser(boundingRect.width(), 0, 0, boundingRect.height(),
504 boundingRect.x(), boundingRect.y());
506 QGradient g = *brush.gradient();
507 g.setCoordinateMode(QGradient::LogicalMode);
510 b.setTransform(gradientToUser * b.transform());
514 void QPainterPrivate::drawStretchedGradient(const QPainterPath &path, DrawOperation op)
518 const qreal sw = helper_device->width();
519 const qreal sh = helper_device->height();
521 bool changedPen = false;
522 bool changedBrush = false;
523 bool needsFill = false;
525 const QPen pen = state->pen;
526 const QBrush brush = state->brush;
528 const QGradient::CoordinateMode penMode = coordinateMode(pen.brush());
529 const QGradient::CoordinateMode brushMode = coordinateMode(brush);
533 // Draw the xformed fill if the brush is a stretch gradient.
534 if ((op & FillDraw) && brush.style() != Qt::NoBrush) {
535 if (brushMode == QGradient::StretchToDeviceMode) {
536 q->setPen(Qt::NoPen);
537 changedPen = pen.style() != Qt::NoPen;
541 const qreal isw = 1.0 / sw;
542 const qreal ish = 1.0 / sh;
543 QTransform inv(isw, 0, 0, ish, 0, 0);
544 engine->drawPath(path * inv);
549 if (brushMode == QGradient::ObjectBoundingMode) {
550 Q_ASSERT(engine->hasFeature(QPaintEngine::PatternTransform));
551 boundingRect = path.boundingRect();
552 q->setBrush(stretchGradientToUserSpace(brush, boundingRect));
558 if ((op & StrokeDraw) && pen.style() != Qt::NoPen) {
559 // Draw the xformed outline if the pen is a stretch gradient.
560 if (penMode == QGradient::StretchToDeviceMode) {
561 q->setPen(Qt::NoPen);
566 engine->drawPath(path);
570 q->setBrush(pen.brush());
574 QPainterPathStroker stroker;
575 stroker.setDashPattern(pen.style());
576 stroker.setWidth(pen.widthF());
577 stroker.setJoinStyle(pen.joinStyle());
578 stroker.setCapStyle(pen.capStyle());
579 stroker.setMiterLimit(pen.miterLimit());
580 QPainterPath stroke = stroker.createStroke(path);
582 const qreal isw = 1.0 / sw;
583 const qreal ish = 1.0 / sh;
584 QTransform inv(isw, 0, 0, ish, 0, 0);
585 engine->drawPath(stroke * inv);
588 if (!needsFill && brush.style() != Qt::NoBrush) {
589 q->setBrush(Qt::NoBrush);
593 if (penMode == QGradient::ObjectBoundingMode) {
594 Q_ASSERT(engine->hasFeature(QPaintEngine::PatternTransform));
596 // avoid computing the bounding rect twice
597 if (!needsFill || brushMode != QGradient::ObjectBoundingMode)
598 boundingRect = path.boundingRect();
601 p.setBrush(stretchGradientToUserSpace(pen.brush(), boundingRect));
604 } else if (changedPen) {
610 engine->drawPath(path);
612 } else if (needsFill) {
613 if (pen.style() != Qt::NoPen) {
614 q->setPen(Qt::NoPen);
619 engine->drawPath(path);
629 void QPainterPrivate::updateMatrix()
631 state->matrix = state->WxF ? state->worldMatrix : QTransform();
633 state->matrix *= viewTransform();
635 txinv = false; // no inverted matrix
636 state->matrix *= state->redirectionMatrix;
638 extended->transformChanged();
640 state->dirtyFlags |= QPaintEngine::DirtyTransform;
642 // printf("VxF=%d, WxF=%d\n", state->VxF, state->WxF);
643 // qDebug() << " --- using matrix" << state->matrix << redirection_offset;
647 void QPainterPrivate::updateInvMatrix()
649 Q_ASSERT(txinv == false);
650 txinv = true; // creating inverted matrix
651 invMatrix = state->matrix.inverted();
654 extern bool qt_isExtendedRadialGradient(const QBrush &brush);
656 void QPainterPrivate::updateEmulationSpecifier(QPainterState *s)
659 bool linearGradient = false;
660 bool radialGradient = false;
661 bool extendedRadialGradient = false;
662 bool conicalGradient = false;
663 bool patternBrush = false;
665 bool complexXform = false;
669 // Pen and brush properties (we have to check both if one changes because the
670 // one that's unchanged can still be in a state which requires emulation)
671 if (s->state() & (QPaintEngine::DirtyPen | QPaintEngine::DirtyBrush | QPaintEngine::DirtyHints)) {
672 // Check Brush stroke emulation
673 if (!s->pen.isSolid() && !engine->hasFeature(QPaintEngine::BrushStroke))
674 s->emulationSpecifier |= QPaintEngine::BrushStroke;
676 s->emulationSpecifier &= ~QPaintEngine::BrushStroke;
680 QBrush penBrush = (qpen_style(s->pen) == Qt::NoPen) ? QBrush(Qt::NoBrush) : qpen_brush(s->pen);
681 Qt::BrushStyle brushStyle = qbrush_style(s->brush);
682 Qt::BrushStyle penBrushStyle = qbrush_style(penBrush);
683 alpha = (penBrushStyle != Qt::NoBrush
684 && (penBrushStyle < Qt::LinearGradientPattern && penBrush.color().alpha() != 255)
685 && !penBrush.isOpaque())
686 || (brushStyle != Qt::NoBrush
687 && (brushStyle < Qt::LinearGradientPattern && s->brush.color().alpha() != 255)
688 && !s->brush.isOpaque());
689 linearGradient = ((penBrushStyle == Qt::LinearGradientPattern) ||
690 (brushStyle == Qt::LinearGradientPattern));
691 radialGradient = ((penBrushStyle == Qt::RadialGradientPattern) ||
692 (brushStyle == Qt::RadialGradientPattern));
693 extendedRadialGradient = radialGradient && (qt_isExtendedRadialGradient(penBrush) || qt_isExtendedRadialGradient(s->brush));
694 conicalGradient = ((penBrushStyle == Qt::ConicalGradientPattern) ||
695 (brushStyle == Qt::ConicalGradientPattern));
696 patternBrush = (((penBrushStyle > Qt::SolidPattern
697 && penBrushStyle < Qt::LinearGradientPattern)
698 || penBrushStyle == Qt::TexturePattern) ||
699 ((brushStyle > Qt::SolidPattern
700 && brushStyle < Qt::LinearGradientPattern)
701 || brushStyle == Qt::TexturePattern));
703 bool penTextureAlpha = false;
704 if (penBrush.style() == Qt::TexturePattern)
705 penTextureAlpha = qHasPixmapTexture(penBrush)
706 ? (penBrush.texture().depth() > 1) && penBrush.texture().hasAlpha()
707 : penBrush.textureImage().hasAlphaChannel();
708 bool brushTextureAlpha = false;
709 if (s->brush.style() == Qt::TexturePattern) {
710 brushTextureAlpha = qHasPixmapTexture(s->brush)
711 ? (s->brush.texture().depth() > 1) && s->brush.texture().hasAlpha()
712 : s->brush.textureImage().hasAlphaChannel();
714 if (((penBrush.style() == Qt::TexturePattern && penTextureAlpha)
715 || (s->brush.style() == Qt::TexturePattern && brushTextureAlpha))
716 && !engine->hasFeature(QPaintEngine::MaskedBrush))
717 s->emulationSpecifier |= QPaintEngine::MaskedBrush;
719 s->emulationSpecifier &= ~QPaintEngine::MaskedBrush;
722 if (s->state() & (QPaintEngine::DirtyHints
723 | QPaintEngine::DirtyOpacity
724 | QPaintEngine::DirtyBackgroundMode)) {
732 qDebug("QPainterPrivate::updateEmulationSpecifier, state=%p\n"
734 " - linearGradient: %d\n"
735 " - radialGradient: %d\n"
736 " - conicalGradient: %d\n"
737 " - patternBrush: %d\n"
746 uint(s->renderHints),
751 if (s->state() & QPaintEngine::DirtyTransform) {
752 xform = !s->matrix.isIdentity();
753 complexXform = !s->matrix.isAffine();
754 } else if (s->matrix.type() >= QTransform::TxTranslate) {
756 complexXform = !s->matrix.isAffine();
759 const bool brushXform = (!s->brush.transform().type() == QTransform::TxNone);
760 const bool penXform = (!s->pen.brush().transform().type() == QTransform::TxNone);
762 const bool patternXform = patternBrush && (xform || brushXform || penXform);
764 // Check alphablending
765 if (alpha && !engine->hasFeature(QPaintEngine::AlphaBlend))
766 s->emulationSpecifier |= QPaintEngine::AlphaBlend;
768 s->emulationSpecifier &= ~QPaintEngine::AlphaBlend;
770 // Linear gradient emulation
771 if (linearGradient && !engine->hasFeature(QPaintEngine::LinearGradientFill))
772 s->emulationSpecifier |= QPaintEngine::LinearGradientFill;
774 s->emulationSpecifier &= ~QPaintEngine::LinearGradientFill;
776 // Radial gradient emulation
777 if (extendedRadialGradient || (radialGradient && !engine->hasFeature(QPaintEngine::RadialGradientFill)))
778 s->emulationSpecifier |= QPaintEngine::RadialGradientFill;
780 s->emulationSpecifier &= ~QPaintEngine::RadialGradientFill;
782 // Conical gradient emulation
783 if (conicalGradient && !engine->hasFeature(QPaintEngine::ConicalGradientFill))
784 s->emulationSpecifier |= QPaintEngine::ConicalGradientFill;
786 s->emulationSpecifier &= ~QPaintEngine::ConicalGradientFill;
789 if (patternBrush && !engine->hasFeature(QPaintEngine::PatternBrush))
790 s->emulationSpecifier |= QPaintEngine::PatternBrush;
792 s->emulationSpecifier &= ~QPaintEngine::PatternBrush;
795 if (patternXform && !engine->hasFeature(QPaintEngine::PatternTransform))
796 s->emulationSpecifier |= QPaintEngine::PatternTransform;
798 s->emulationSpecifier &= ~QPaintEngine::PatternTransform;
801 if (xform && !engine->hasFeature(QPaintEngine::PrimitiveTransform))
802 s->emulationSpecifier |= QPaintEngine::PrimitiveTransform;
804 s->emulationSpecifier &= ~QPaintEngine::PrimitiveTransform;
806 // Perspective XForms
807 if (complexXform && !engine->hasFeature(QPaintEngine::PerspectiveTransform))
808 s->emulationSpecifier |= QPaintEngine::PerspectiveTransform;
810 s->emulationSpecifier &= ~QPaintEngine::PerspectiveTransform;
813 if (state->opacity != 1 && !engine->hasFeature(QPaintEngine::ConstantOpacity))
814 s->emulationSpecifier |= QPaintEngine::ConstantOpacity;
816 s->emulationSpecifier &= ~QPaintEngine::ConstantOpacity;
818 bool gradientStretch = false;
819 bool objectBoundingMode = false;
820 if (linearGradient || conicalGradient || radialGradient) {
821 QGradient::CoordinateMode brushMode = coordinateMode(s->brush);
822 QGradient::CoordinateMode penMode = coordinateMode(s->pen.brush());
824 gradientStretch |= (brushMode == QGradient::StretchToDeviceMode);
825 gradientStretch |= (penMode == QGradient::StretchToDeviceMode);
827 objectBoundingMode |= (brushMode == QGradient::ObjectBoundingMode);
828 objectBoundingMode |= (penMode == QGradient::ObjectBoundingMode);
831 s->emulationSpecifier |= QGradient_StretchToDevice;
833 s->emulationSpecifier &= ~QGradient_StretchToDevice;
835 if (objectBoundingMode && !engine->hasFeature(QPaintEngine::ObjectBoundingModeGradients))
836 s->emulationSpecifier |= QPaintEngine::ObjectBoundingModeGradients;
838 s->emulationSpecifier &= ~QPaintEngine::ObjectBoundingModeGradients;
840 // Opaque backgrounds...
841 if (s->bgMode == Qt::OpaqueMode &&
842 (is_pen_transparent(s->pen) || is_brush_transparent(s->brush)))
843 s->emulationSpecifier |= QPaintEngine_OpaqueBackground;
845 s->emulationSpecifier &= ~QPaintEngine_OpaqueBackground;
848 //won't be correct either way because the device can already have
849 // something rendered to it in which case subsequent emulation
850 // on a fully transparent qimage and then blitting the results
851 // won't produce correct results
853 if (state->composition_mode > QPainter::CompositionMode_Xor &&
854 !engine->hasFeature(QPaintEngine::BlendModes))
855 s->emulationSpecifier |= QPaintEngine::BlendModes;
857 s->emulationSpecifier &= ~QPaintEngine::BlendModes;
861 void QPainterPrivate::updateStateImpl(QPainterState *newState)
863 // ### we might have to call QPainter::begin() here...
864 if (!engine->state) {
865 engine->state = newState;
866 engine->setDirty(QPaintEngine::AllDirty);
869 if (engine->state->painter() != newState->painter)
870 // ### this could break with clip regions vs paths.
871 engine->setDirty(QPaintEngine::AllDirty);
873 // Upon restore, revert all changes since last save
874 else if (engine->state != newState)
875 newState->dirtyFlags |= QPaintEngine::DirtyFlags(static_cast<QPainterState *>(engine->state)->changeFlags);
877 // We need to store all changes made so that restore can deal with them
879 newState->changeFlags |= newState->dirtyFlags;
881 updateEmulationSpecifier(newState);
883 // Unset potential dirty background mode
884 newState->dirtyFlags &= ~(QPaintEngine::DirtyBackgroundMode
885 | QPaintEngine::DirtyBackground);
887 engine->state = newState;
888 engine->updateState(*newState);
889 engine->clearDirty(QPaintEngine::AllDirty);
893 void QPainterPrivate::updateState(QPainterState *newState)
897 engine->state = newState;
899 } else if (newState->state() || engine->state!=newState) {
900 bool setNonCosmeticPen = (newState->renderHints & QPainter::NonCosmeticDefaultPen)
901 && newState->pen.widthF() == 0;
902 if (setNonCosmeticPen) {
903 // Override the default pen's cosmetic state if the
904 // NonCosmeticDefaultPen render hint is used.
905 QPen oldPen = newState->pen;
906 newState->pen.setWidth(1);
907 newState->pen.setCosmetic(false);
908 newState->dirtyFlags |= QPaintEngine::DirtyPen;
910 updateStateImpl(newState);
912 // Restore the state pen back to its default to preserve visible
914 newState->pen = oldPen;
916 updateStateImpl(newState);
924 \brief The QPainter class performs low-level painting on widgets and
931 QPainter provides highly optimized functions to do most of the
932 drawing GUI programs require. It can draw everything from simple
933 lines to complex shapes like pies and chords. It can also draw
934 aligned text and pixmaps. Normally, it draws in a "natural"
935 coordinate system, but it can also do view and world
936 transformation. QPainter can operate on any object that inherits
937 the QPaintDevice class.
939 The common use of QPainter is inside a widget's paint event:
940 Construct and customize (e.g. set the pen or the brush) the
941 painter. Then draw. Remember to destroy the QPainter object after
942 drawing. For example:
944 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 0
946 The core functionality of QPainter is drawing, but the class also
947 provide several functions that allows you to customize QPainter's
948 settings and its rendering quality, and others that enable
949 clipping. In addition you can control how different shapes are
950 merged together by specifying the painter's composition mode.
952 The isActive() function indicates whether the painter is active. A
953 painter is activated by the begin() function and the constructor
954 that takes a QPaintDevice argument. The end() function, and the
955 destructor, deactivates it.
957 Together with the QPaintDevice and QPaintEngine classes, QPainter
958 form the basis for Qt's paint system. QPainter is the class used
959 to perform drawing operations. QPaintDevice represents a device
960 that can be painted on using a QPainter. QPaintEngine provides the
961 interface that the painter uses to draw onto different types of
962 devices. If the painter is active, device() returns the paint
963 device on which the painter paints, and paintEngine() returns the
964 paint engine that the painter is currently operating on. For more
965 information, see the \l {Paint System}.
967 Sometimes it is desirable to make someone else paint on an unusual
968 QPaintDevice. QPainter supports a static function to do this,
971 \warning When the paintdevice is a widget, QPainter can only be
972 used inside a paintEvent() function or in a function called by
973 paintEvent(); that is unless the Qt::WA_PaintOutsidePaintEvent
974 widget attribute is set. On Mac OS X and Windows, you can only
975 paint in a paintEvent() function regardless of this attribute's
982 There are several settings that you can customize to make QPainter
983 draw according to your preferences:
987 \li font() is the font used for drawing text. If the painter
988 isActive(), you can retrieve information about the currently set
989 font, and its metrics, using the fontInfo() and fontMetrics()
990 functions respectively.
992 \li brush() defines the color or pattern that is used for filling
995 \li pen() defines the color or stipple that is used for drawing
998 \li backgroundMode() defines whether there is a background() or
999 not, i.e it is either Qt::OpaqueMode or Qt::TransparentMode.
1001 \li background() only applies when backgroundMode() is \l
1002 Qt::OpaqueMode and pen() is a stipple. In that case, it
1003 describes the color of the background pixels in the stipple.
1005 \li brushOrigin() defines the origin of the tiled brushes, normally
1006 the origin of widget's background.
1008 \li viewport(), window(), worldTransform() make up the painter's coordinate
1009 transformation system. For more information, see the \l
1010 {Coordinate Transformations} section and the \l {Coordinate
1011 System} documentation.
1013 \li hasClipping() tells whether the painter clips at all. (The paint
1014 device clips, too.) If the painter clips, it clips to clipRegion().
1016 \li layoutDirection() defines the layout direction used by the
1017 painter when drawing text.
1019 \li worldMatrixEnabled() tells whether world transformation is enabled.
1021 \li viewTransformEnabled() tells whether view transformation is
1026 Note that some of these settings mirror settings in some paint
1027 devices, e.g. QWidget::font(). The QPainter::begin() function (or
1028 equivalently the QPainter constructor) copies these attributes
1029 from the paint device.
1031 You can at any time save the QPainter's state by calling the
1032 save() function which saves all the available settings on an
1033 internal stack. The restore() function pops them back.
1037 QPainter provides functions to draw most primitives: drawPoint(),
1038 drawPoints(), drawLine(), drawRect(), drawRoundedRect(),
1039 drawEllipse(), drawArc(), drawPie(), drawChord(), drawPolyline(),
1040 drawPolygon(), drawConvexPolygon() and drawCubicBezier(). The two
1041 convenience functions, drawRects() and drawLines(), draw the given
1042 number of rectangles or lines in the given array of \l
1043 {QRect}{QRects} or \l {QLine}{QLines} using the current pen and
1046 The QPainter class also provides the fillRect() function which
1047 fills the given QRect, with the given QBrush, and the eraseRect()
1048 function that erases the area inside the given rectangle.
1050 All of these functions have both integer and floating point
1055 \li \inlineimage qpainter-basicdrawing.png
1057 \b {Basic Drawing Example}
1059 The \l {painting/basicdrawing}{Basic Drawing} example shows how to
1060 display basic graphics primitives in a variety of styles using the
1065 If you need to draw a complex shape, especially if you need to do
1066 so repeatedly, consider creating a QPainterPath and drawing it
1072 \b {Painter Paths example}
1074 The QPainterPath class provides a container for painting
1075 operations, enabling graphical shapes to be constructed and
1078 The \l {painting/painterpaths}{Painter Paths} example shows how
1079 painter paths can be used to build complex shapes for rendering.
1081 \li \inlineimage qpainter-painterpaths.png
1084 QPainter also provides the fillPath() function which fills the
1085 given QPainterPath with the given QBrush, and the strokePath()
1086 function that draws the outline of the given path (i.e. strokes
1089 See also the \l {painting/deform}{Vector Deformation} example which
1090 shows how to use advanced vector techniques to draw text using a
1091 QPainterPath, the \l {painting/gradients}{Gradients} example which shows
1092 the different types of gradients that are available in Qt, and the \l
1093 {painting/pathstroke}{Path Stroking} example which shows Qt's built-in
1094 dash patterns and shows how custom patterns can be used to extend
1095 the range of available patterns.
1099 \li \l {painting/deform}{Vector Deformation}
1100 \li \l {painting/gradients}{Gradients}
1101 \li \l {painting/pathstroke}{Path Stroking}
1103 \li \inlineimage qpainter-vectordeformation.png
1104 \li \inlineimage qpainter-gradients.png
1105 \li \inlineimage qpainter-pathstroking.png
1109 There are functions to draw pixmaps/images, namely drawPixmap(),
1110 drawImage() and drawTiledPixmap(). Both drawPixmap() and drawImage()
1111 produce the same result, except that drawPixmap() is faster
1112 on-screen while drawImage() may be faster on a QPrinter or other
1115 Text drawing is done using drawText(). When you need
1116 fine-grained positioning, boundingRect() tells you where a given
1117 drawText() command will draw.
1119 There is a drawPicture() function that draws the contents of an
1120 entire QPicture. The drawPicture() function is the only function
1121 that disregards all the painter's settings as QPicture has its own
1124 \section1 Rendering Quality
1126 To get the optimal rendering result using QPainter, you should use
1127 the platform independent QImage as paint device; i.e. using QImage
1128 will ensure that the result has an identical pixel representation
1131 The QPainter class also provides a means of controlling the
1132 rendering quality through its RenderHint enum and the support for
1133 floating point precision: All the functions for drawing primitives
1134 has a floating point version. These are often used in combination
1135 with the \l {RenderHint}{QPainter::Antialiasing} render hint.
1139 \li \inlineimage qpainter-concentriccircles.png
1141 \b {Concentric Circles Example}
1143 The \l {painting/concentriccircles}{Concentric Circles} example
1144 shows the improved rendering quality that can be obtained using
1145 floating point precision and anti-aliasing when drawing custom
1148 The application's main window displays several widgets which are
1149 drawn using the various combinations of precision and
1154 The RenderHint enum specifies flags to QPainter that may or may
1155 not be respected by any given engine. \l
1156 {RenderHint}{QPainter::Antialiasing} indicates that the engine
1157 should antialias edges of primitives if possible, \l
1158 {RenderHint}{QPainter::TextAntialiasing} indicates that the engine
1159 should antialias text if possible, and the \l
1160 {RenderHint}{QPainter::SmoothPixmapTransform} indicates that the
1161 engine should use a smooth pixmap transformation algorithm.
1162 \l {RenderHint}{HighQualityAntialiasing} is an OpenGL-specific rendering hint
1163 indicating that the engine should use fragment programs and offscreen
1164 rendering for antialiasing.
1166 The renderHints() function returns a flag that specifies the
1167 rendering hints that are set for this painter. Use the
1168 setRenderHint() function to set or clear the currently set
1171 \section1 Coordinate Transformations
1173 Normally, the QPainter operates on the device's own coordinate
1174 system (usually pixels), but QPainter has good support for
1175 coordinate transformations.
1179 \li nop \li rotate() \li scale() \li translate()
1181 \li \inlineimage qpainter-clock.png
1182 \li \inlineimage qpainter-rotation.png
1183 \li \inlineimage qpainter-scale.png
1184 \li \inlineimage qpainter-translation.png
1187 The most commonly used transformations are scaling, rotation,
1188 translation and shearing. Use the scale() function to scale the
1189 coordinate system by a given offset, the rotate() function to
1190 rotate it clockwise and translate() to translate it (i.e. adding a
1191 given offset to the points). You can also twist the coordinate
1192 system around the origin using the shear() function. See the \l
1193 {painting/affine}{Affine Transformations} example for a visualization of
1194 a sheared coordinate system.
1196 See also the \l {painting/transformations}{Transformations}
1197 example which shows how transformations influence the way that
1198 QPainter renders graphics primitives. In particular it shows how
1199 the order of transformations affects the result.
1204 \b {Affine Transformations Example}
1206 The \l {painting/affine}{Affine Transformations} example shows Qt's
1207 ability to perform affine transformations on painting
1208 operations. The demo also allows the user to experiment with the
1209 transformation operations and see the results immediately.
1211 \li \inlineimage qpainter-affinetransformations.png
1214 All the tranformation operations operate on the transformation
1215 worldTransform(). A matrix transforms a point in the plane to another
1216 point. For more information about the transformation matrix, see
1217 the \l {Coordinate System} and QTransform documentation.
1219 The setWorldTransform() function can replace or add to the currently
1220 set worldTransform(). The resetTransform() function resets any
1221 transformations that were made using translate(), scale(),
1222 shear(), rotate(), setWorldTransform(), setViewport() and setWindow()
1223 functions. The deviceTransform() returns the matrix that transforms
1224 from logical coordinates to device coordinates of the platform
1225 dependent paint device. The latter function is only needed when
1226 using platform painting commands on the platform dependent handle,
1227 and the platform does not do transformations nativly.
1229 When drawing with QPainter, we specify points using logical
1230 coordinates which then are converted into the physical coordinates
1231 of the paint device. The mapping of the logical coordinates to the
1232 physical coordinates are handled by QPainter's combinedTransform(), a
1233 combination of viewport() and window() and worldTransform(). The
1234 viewport() represents the physical coordinates specifying an
1235 arbitrary rectangle, the window() describes the same rectangle in
1236 logical coordinates, and the worldTransform() is identical with the
1237 transformation matrix.
1239 See also \l {Coordinate System}
1243 QPainter can clip any drawing operation to a rectangle, a region,
1244 or a vector path. The current clip is available using the
1245 functions clipRegion() and clipPath(). Whether paths or regions are
1246 preferred (faster) depends on the underlying paintEngine(). For
1247 example, the QImage paint engine prefers paths while the X11 paint
1248 engine prefers regions. Setting a clip is done in the painters
1249 logical coordinates.
1251 After QPainter's clipping, the paint device may also clip. For
1252 example, most widgets clip away the pixels used by child widgets,
1253 and most printers clip away an area near the edges of the paper.
1254 This additional clipping is not reflected by the return value of
1255 clipRegion() or hasClipping().
1257 \section1 Composition Modes
1258 \target Composition Modes
1260 QPainter provides the CompositionMode enum which defines the
1261 Porter-Duff rules for digital image compositing; it describes a
1262 model for combining the pixels in one image, the source, with the
1263 pixels in another image, the destination.
1265 The two most common forms of composition are \l
1266 {QPainter::CompositionMode}{Source} and \l
1267 {QPainter::CompositionMode}{SourceOver}. \l
1268 {QPainter::CompositionMode}{Source} is used to draw opaque objects
1269 onto a paint device. In this mode, each pixel in the source
1270 replaces the corresponding pixel in the destination. In \l
1271 {QPainter::CompositionMode}{SourceOver} composition mode, the
1272 source object is transparent and is drawn on top of the
1275 Note that composition transformation operates pixelwise. For that
1276 reason, there is a difference between using the graphic primitive
1277 itself and its bounding rectangle: The bounding rect contains
1278 pixels with alpha == 0 (i.e the pixels surrounding the
1279 primitive). These pixels will overwrite the other image's pixels,
1280 affectively clearing those, while the primitive only overwrites
1285 \li \inlineimage qpainter-compositiondemo.png
1288 \b {Composition Modes Example}
1290 The \l {painting/composition}{Composition Modes} example, available in
1291 Qt's examples directory, allows you to experiment with the various
1292 composition modes and see the results immediately.
1296 \section1 Limitations
1299 If you are using coordinates with Qt's raster-based paint engine, it is
1300 important to note that, while coordinates greater than +/- 2\sup 15 can
1301 be used, any painting performed with coordinates outside this range is not
1302 guaranteed to be shown; the drawing may be clipped. This is due to the
1303 use of \c{short int} in the implementation.
1305 The outlines generated by Qt's stroker are only an approximation when dealing
1306 with curved shapes. It is in most cases impossible to represent the outline of
1307 a bezier curve segment using another bezier curve segment, and so Qt approximates
1308 the curve outlines by using several smaller curves. For performance reasons there
1309 is a limit to how many curves Qt uses for these outlines, and thus when using
1310 large pen widths or scales the outline error increases. To generate outlines with
1311 smaller errors it is possible to use the QPainterPathStroker class, which has the
1312 setCurveThreshold member function which let's the user specify the error tolerance.
1313 Another workaround is to convert the paths to polygons first and then draw the
1316 \section1 Performance
1318 QPainter is a rich framework that allows developers to do a great
1319 variety of graphical operations, such as gradients, composition
1320 modes and vector graphics. And QPainter can do this across a
1321 variety of different hardware and software stacks. Naturally the
1322 underlying combination of hardware and software has some
1323 implications for performance, and ensuring that every single
1324 operation is fast in combination with all the various combinations
1325 of composition modes, brushes, clipping, transformation, etc, is
1326 close to an impossible task because of the number of
1327 permutations. As a compromise we have selected a subset of the
1328 QPainter API and backends, where performance is guaranteed to be as
1329 good as we can sensibly get it for the given combination of
1330 hardware and software.
1332 The backends we focus on as high-performance engines are:
1336 \li Raster - This backend implements all rendering in pure software
1337 and is always used to render into QImages. For optimal performance
1338 only use the format types QImage::Format_ARGB32_Premultiplied,
1339 QImage::Format_RGB32 or QImage::Format_RGB16. Any other format,
1340 including QImage::Format_ARGB32, has significantly worse
1341 performance. This engine is used by default for QWidget and QPixmap.
1343 \li OpenGL 2.0 (ES) - This backend is the primary backend for
1344 hardware accelerated graphics. It can be run on desktop machines
1345 and embedded devices supporting the OpenGL 2.0 or OpenGL/ES 2.0
1346 specification. This includes most graphics chips produced in the
1347 last couple of years. The engine can be enabled by using QPainter
1348 onto a QOpenGLWidget or by passing \c {-graphicssystem opengl} on the
1349 command line when the underlying system supports it.
1351 \li OpenVG - This backend implements the Khronos standard for 2D
1352 and Vector Graphics. It is primarily for embedded devices with
1353 hardware support for OpenVG. The engine can be enabled by
1354 passing \c {-graphicssystem openvg} on the command line when
1355 the underlying system supports it.
1359 These operations are:
1363 \li Simple transformations, meaning translation and scaling, pluss
1364 0, 90, 180, 270 degree rotations.
1366 \li \c drawPixmap() in combination with simple transformations and
1367 opacity with non-smooth transformation mode
1368 (\c QPainter::SmoothPixmapTransform not enabled as a render hint).
1370 \li Rectangle fills with solid color, two-color linear gradients
1371 and simple transforms.
1373 \li Rectangular clipping with simple transformations and intersect
1376 \li Composition Modes \c QPainter::CompositionMode_Source and
1377 QPainter::CompositionMode_SourceOver
1379 \li Rounded rectangle filling using solid color and two-color
1380 linear gradients fills.
1382 \li 3x3 patched pixmaps, via qDrawBorderPixmap.
1386 This list gives an indication of which features to safely use in
1387 an application where performance is critical. For certain setups,
1388 other operations may be fast too, but before making extensive use
1389 of them, it is recommended to benchmark and verify them on the
1390 system where the software will run in the end. There are also
1391 cases where expensive operations are ok to use, for instance when
1392 the result is cached in a QPixmap.
1394 \sa QPaintDevice, QPaintEngine, {QtSvg Module}, {Basic Drawing Example},
1395 {Drawing Utility Functions}
1399 \enum QPainter::RenderHint
1401 Renderhints are used to specify flags to QPainter that may or
1402 may not be respected by any given engine.
1404 \value Antialiasing Indicates that the engine should antialias
1405 edges of primitives if possible.
1407 \value TextAntialiasing Indicates that the engine should antialias
1408 text if possible. To forcibly disable antialiasing for text, do not
1409 use this hint. Instead, set QFont::NoAntialias on your font's style
1412 \value SmoothPixmapTransform Indicates that the engine should use
1413 a smooth pixmap transformation algorithm (such as bilinear) rather
1414 than nearest neighbor.
1416 \value HighQualityAntialiasing An OpenGL-specific rendering hint
1417 indicating that the engine should use fragment programs and offscreen
1418 rendering for antialiasing.
1420 \value NonCosmeticDefaultPen The engine should interpret pens with a width
1421 of 0 (which otherwise enables QPen::isCosmetic()) as being a non-cosmetic
1422 pen with a width of 1.
1424 \sa renderHints(), setRenderHint(), {QPainter#Rendering
1425 Quality}{Rendering Quality}, {Concentric Circles Example}
1430 Constructs a painter.
1435 QPainter::QPainter()
1436 : d_ptr(new QPainterPrivate(this))
1441 \fn QPainter::QPainter(QPaintDevice *device)
1443 Constructs a painter that begins painting the paint \a device
1446 This constructor is convenient for short-lived painters, e.g. in a
1447 QWidget::paintEvent() and should be used only once. The
1448 constructor calls begin() for you and the QPainter destructor
1449 automatically calls end().
1451 Here's an example using begin() and end():
1452 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 1
1454 The same example using this constructor:
1455 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 2
1457 Since the constructor cannot provide feedback when the initialization
1458 of the painter failed you should rather use begin() and end() to paint
1459 on external devices, e.g. printers.
1464 QPainter::QPainter(QPaintDevice *pd)
1468 if (!QPainterPrivate::attachPainterPrivate(this, pd)) {
1469 d_ptr.reset(new QPainterPrivate(this));
1476 Destroys the painter.
1478 QPainter::~QPainter()
1480 d_ptr->inDestructor = true;
1484 else if (d_ptr->refcount > 1)
1485 d_ptr->detachPainterPrivate(this);
1487 // don't throw anything in the destructor.
1490 // Make sure we haven't messed things up.
1491 Q_ASSERT(d_ptr->inDestructor);
1492 d_ptr->inDestructor = false;
1493 Q_ASSERT(d_ptr->refcount == 1);
1495 free(d_ptr->d_ptrs);
1500 Returns the paint device on which this painter is currently
1501 painting, or 0 if the painter is not active.
1506 QPaintDevice *QPainter::device() const
1508 Q_D(const QPainter);
1509 if (isActive() && d->engine->d_func()->currentClipDevice)
1510 return d->engine->d_func()->currentClipDevice;
1511 return d->original_device;
1515 Returns true if begin() has been called and end() has not yet been
1516 called; otherwise returns false.
1518 \sa begin(), QPaintDevice::paintingActive()
1521 bool QPainter::isActive() const
1523 Q_D(const QPainter);
1528 Initializes the painters pen, background and font to the same as
1529 the given \a paint device.
1533 \sa begin(), {QPainter#Settings}{Settings}
1535 void QPainter::initFrom(const QPaintDevice *device)
1537 Q_ASSERT_X(device, "QPainter::initFrom(const QPaintDevice *device)", "QPaintDevice cannot be 0");
1540 qWarning("QPainter::initFrom: Painter not active, aborted");
1547 d->extended->penChanged();
1548 } else if (d->engine) {
1549 d->engine->setDirty(QPaintEngine::DirtyPen);
1550 d->engine->setDirty(QPaintEngine::DirtyBrush);
1551 d->engine->setDirty(QPaintEngine::DirtyFont);
1557 Saves the current painter state (pushes the state onto a stack). A
1558 save() must be followed by a corresponding restore(); the end()
1559 function unwinds the stack.
1564 void QPainter::save()
1566 #ifdef QT_DEBUG_DRAW
1567 if (qt_show_painter_debug_output)
1568 printf("QPainter::save()\n");
1572 qWarning("QPainter::save: Painter not active");
1577 d->state = d->extended->createState(d->states.back());
1578 d->extended->setState(d->state);
1580 d->updateState(d->state);
1581 d->state = new QPainterState(d->states.back());
1582 d->engine->state = d->state;
1584 d->states.push_back(d->state);
1588 Restores the current painter state (pops a saved state off the
1594 void QPainter::restore()
1596 #ifdef QT_DEBUG_DRAW
1597 if (qt_show_painter_debug_output)
1598 printf("QPainter::restore()\n");
1601 if (d->states.size()<=1) {
1602 qWarning("QPainter::restore: Unbalanced save/restore");
1604 } else if (!d->engine) {
1605 qWarning("QPainter::restore: Painter not active");
1609 QPainterState *tmp = d->state;
1610 d->states.pop_back();
1611 d->state = d->states.back();
1615 d->checkEmulation();
1616 d->extended->setState(d->state);
1621 // trigger clip update if the clip path/region has changed since
1623 if (!d->state->clipInfo.isEmpty()
1624 && (tmp->changeFlags & (QPaintEngine::DirtyClipRegion | QPaintEngine::DirtyClipPath))) {
1625 // reuse the tmp state to avoid any extra allocs...
1626 tmp->dirtyFlags = QPaintEngine::DirtyClipPath;
1627 tmp->clipOperation = Qt::NoClip;
1628 tmp->clipPath = QPainterPath();
1629 d->engine->updateState(*tmp);
1630 // replay the list of clip states,
1631 for (int i=0; i<d->state->clipInfo.size(); ++i) {
1632 const QPainterClipInfo &info = d->state->clipInfo.at(i);
1633 tmp->matrix = info.matrix;
1634 tmp->matrix *= d->state->redirectionMatrix;
1635 tmp->clipOperation = info.operation;
1636 if (info.clipType == QPainterClipInfo::RectClip) {
1637 tmp->dirtyFlags = QPaintEngine::DirtyClipRegion | QPaintEngine::DirtyTransform;
1638 tmp->clipRegion = info.rect;
1639 } else if (info.clipType == QPainterClipInfo::RegionClip) {
1640 tmp->dirtyFlags = QPaintEngine::DirtyClipRegion | QPaintEngine::DirtyTransform;
1641 tmp->clipRegion = info.region;
1642 } else { // clipType == QPainterClipInfo::PathClip
1643 tmp->dirtyFlags = QPaintEngine::DirtyClipPath | QPaintEngine::DirtyTransform;
1644 tmp->clipPath = info.path;
1646 d->engine->updateState(*tmp);
1650 //Since we've updated the clip region anyway, pretend that the clip path hasn't changed:
1651 d->state->dirtyFlags &= ~(QPaintEngine::DirtyClipPath | QPaintEngine::DirtyClipRegion);
1652 tmp->changeFlags &= ~(QPaintEngine::DirtyClipPath | QPaintEngine::DirtyClipRegion);
1653 tmp->changeFlags |= QPaintEngine::DirtyTransform;
1656 d->updateState(d->state);
1663 \fn bool QPainter::begin(QPaintDevice *device)
1665 Begins painting the paint \a device and returns true if
1666 successful; otherwise returns false.
1668 Notice that all painter settings (setPen(), setBrush() etc.) are reset
1669 to default values when begin() is called.
1671 The errors that can occur are serious problems, such as these:
1673 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 3
1675 Note that most of the time, you can use one of the constructors
1676 instead of begin(), and that end() is automatically done at
1679 \warning A paint device can only be painted by one painter at a
1682 \warning Painting on a QImage with the format
1683 QImage::Format_Indexed8 is not supported.
1685 \sa end(), QPainter()
1688 static inline void qt_cleanup_painter_state(QPainterPrivate *d)
1697 bool QPainter::begin(QPaintDevice *pd)
1701 if (pd->painters > 0) {
1702 qWarning("QPainter::begin: A paint device can only be painted by one painter at a time.");
1706 if (d_ptr->engine) {
1707 qWarning("QPainter::begin: Painter already active");
1711 if (QPainterPrivate::attachPainterPrivate(this, pd))
1716 d->helper_device = pd;
1717 d->original_device = pd;
1719 QPoint redirectionOffset;
1720 QPaintDevice *rpd = pd->redirected(&redirectionOffset);
1724 #ifdef QT_DEBUG_DRAW
1725 if (qt_show_painter_debug_output)
1726 printf("QPainter::begin(), device=%p, type=%d\n", pd, pd->devType());
1729 if (pd->devType() == QInternal::Pixmap)
1730 static_cast<QPixmap *>(pd)->detach();
1731 else if (pd->devType() == QInternal::Image)
1732 static_cast<QImage *>(pd)->detach();
1734 d->engine = pd->paintEngine();
1737 qWarning("QPainter::begin: Paint device returned engine == 0, type: %d", pd->devType());
1743 d->extended = d->engine->isExtended() ? static_cast<QPaintEngineEx *>(d->engine) : 0;
1744 if (d->emulationEngine)
1745 d->emulationEngine->real_engine = d->extended;
1747 // Setup new state...
1748 Q_ASSERT(!d->state);
1749 d->state = d->extended ? d->extended->createState(0) : new QPainterState;
1750 d->state->painter = this;
1751 d->states.push_back(d->state);
1753 d->state->redirectionMatrix.translate(-redirectionOffset.x(), -redirectionOffset.y());
1754 d->state->brushOrigin = QPointF();
1756 // Slip a painter state into the engine before we do any other operations
1758 d->extended->setState(d->state);
1760 d->engine->state = d->state;
1762 switch (pd->devType()) {
1764 // is this needed any more??
1765 case QInternal::Widget:
1767 const QWidget *widget = static_cast<const QWidget *>(pd);
1770 const bool paintOutsidePaintEvent = widget->testAttribute(Qt::WA_PaintOutsidePaintEvent);
1771 const bool inPaintEvent = widget->testAttribute(Qt::WA_WState_InPaintEvent);
1773 // Adjust offset for alien widgets painting outside the paint event.
1774 if (!inPaintEvent && paintOutsidePaintEvent && !widget->internalWinId()
1775 && widget->testAttribute(Qt::WA_WState_Created)) {
1776 const QPoint offset = widget->mapTo(widget->nativeParentWidget(), QPoint());
1777 d->state->redirectionMatrix.translate(offset.x(), offset.y());
1782 case QInternal::Pixmap:
1784 QPixmap *pm = static_cast<QPixmap *>(pd);
1787 qWarning("QPainter::begin: Cannot paint on a null pixmap");
1788 qt_cleanup_painter_state(d);
1792 if (pm->depth() == 1) {
1793 d->state->pen = QPen(Qt::color1);
1794 d->state->brush = QBrush(Qt::color0);
1798 case QInternal::Image:
1800 QImage *img = static_cast<QImage *>(pd);
1802 if (img->isNull()) {
1803 qWarning("QPainter::begin: Cannot paint on a null image");
1804 qt_cleanup_painter_state(d);
1806 } else if (img->format() == QImage::Format_Indexed8) {
1807 // Painting on indexed8 images is not supported.
1808 qWarning("QPainter::begin: Cannot paint on an image with the QImage::Format_Indexed8 format");
1809 qt_cleanup_painter_state(d);
1812 if (img->depth() == 1) {
1813 d->state->pen = QPen(Qt::color1);
1814 d->state->brush = QBrush(Qt::color0);
1821 if (d->state->ww == 0) // For compat with 3.x painter defaults
1822 d->state->ww = d->state->wh = d->state->vw = d->state->vh = 1024;
1824 d->engine->setPaintDevice(pd);
1826 bool begun = d->engine->begin(pd);
1828 qWarning("QPainter::begin(): Returned false");
1829 if (d->engine->isActive()) {
1832 qt_cleanup_painter_state(d);
1836 d->engine->setActive(begun);
1839 // Copy painter properties from original paint device,
1840 // required for QPixmap::grabWidget()
1841 if (d->original_device->devType() == QInternal::Widget) {
1842 initFrom(d->original_device);
1844 d->state->layoutDirection = Qt::LayoutDirectionAuto;
1845 // make sure we have a font compatible with the paintdevice
1846 d->state->deviceFont = d->state->font = QFont(d->state->deviceFont, device());
1849 QRect systemRect = d->engine->systemRect();
1850 if (!systemRect.isEmpty()) {
1851 d->state->ww = d->state->vw = systemRect.width();
1852 d->state->wh = d->state->vh = systemRect.height();
1854 d->state->ww = d->state->vw = pd->metric(QPaintDevice::PdmWidth);
1855 d->state->wh = d->state->vh = pd->metric(QPaintDevice::PdmHeight);
1858 const QPoint coordinateOffset = d->engine->coordinateOffset();
1859 d->state->redirectionMatrix.translate(-coordinateOffset.x(), -coordinateOffset.y());
1861 Q_ASSERT(d->engine->isActive());
1863 if (!d->state->redirectionMatrix.isIdentity())
1866 Q_ASSERT(d->engine->isActive());
1867 d->state->renderHints = QPainter::TextAntialiasing;
1868 ++d->device->painters;
1870 d->state->emulationSpecifier = 0;
1876 Ends painting. Any resources used while painting are released. You
1877 don't normally need to call this since it is called by the
1880 Returns true if the painter is no longer active; otherwise returns false.
1882 \sa begin(), isActive()
1885 bool QPainter::end()
1887 #ifdef QT_DEBUG_DRAW
1888 if (qt_show_painter_debug_output)
1889 printf("QPainter::end()\n");
1894 qWarning("QPainter::end: Painter not active, aborted");
1895 qt_cleanup_painter_state(d);
1899 if (d->refcount > 1) {
1900 d->detachPainterPrivate(this);
1906 if (d->engine->isActive()) {
1907 ended = d->engine->end();
1910 --d->device->painters;
1911 if (d->device->painters == 0) {
1912 d->engine->setPaintDevice(0);
1913 d->engine->setActive(false);
1917 if (d->states.size() > 1) {
1918 qWarning("QPainter::end: Painter ended with %d saved states",
1922 if (d->engine->autoDestruct()) {
1926 if (d->emulationEngine) {
1927 delete d->emulationEngine;
1928 d->emulationEngine = 0;
1935 qt_cleanup_painter_state(d);
1942 Returns the paint engine that the painter is currently operating
1943 on if the painter is active; otherwise 0.
1947 QPaintEngine *QPainter::paintEngine() const
1949 Q_D(const QPainter);
1956 Flushes the painting pipeline and prepares for the user issuing commands
1957 directly to the underlying graphics context. Must be followed by a call to
1958 endNativePainting().
1960 Note that only the states the underlying paint engine changes will be reset
1961 to their respective default states. The states we reset may change from
1962 release to release. The following states are currently reset in the OpenGL
1966 \li blending is disabled
1967 \li the depth, stencil and scissor tests are disabled
1968 \li the active texture unit is reset to 0
1969 \li the depth mask, depth function and the clear depth are reset to their
1971 \li the stencil mask, stencil operation and stencil function are reset to
1972 their default values
1973 \li the current color is reset to solid white
1976 If, for example, the OpenGL polygon mode is changed by the user inside a
1977 beginNativePaint()/endNativePainting() block, it will not be reset to the
1978 default state by endNativePainting(). Here is an example that shows
1979 intermixing of painter commands and raw OpenGL commands:
1981 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 21
1983 \sa endNativePainting()
1985 void QPainter::beginNativePainting()
1989 qWarning("QPainter::beginNativePainting: Painter not active");
1994 d->extended->beginNativePainting();
2000 Restores the painter after manually issuing native painting commands. Lets
2001 the painter restore any native state that it relies on before calling any
2002 other painter commands.
2004 \sa beginNativePainting()
2006 void QPainter::endNativePainting()
2008 Q_D(const QPainter);
2010 qWarning("QPainter::beginNativePainting: Painter not active");
2015 d->extended->endNativePainting();
2017 d->engine->syncState();
2021 Returns the font metrics for the painter if the painter is
2022 active. Otherwise, the return value is undefined.
2024 \sa font(), isActive(), {QPainter#Settings}{Settings}
2027 QFontMetrics QPainter::fontMetrics() const
2029 Q_D(const QPainter);
2031 qWarning("QPainter::fontMetrics: Painter not active");
2032 return QFontMetrics(QFont());
2034 return QFontMetrics(d->state->font);
2039 Returns the font info for the painter if the painter is
2040 active. Otherwise, the return value is undefined.
2042 \sa font(), isActive(), {QPainter#Settings}{Settings}
2045 QFontInfo QPainter::fontInfo() const
2047 Q_D(const QPainter);
2049 qWarning("QPainter::fontInfo: Painter not active");
2050 return QFontInfo(QFont());
2052 return QFontInfo(d->state->font);
2058 Returns the opacity of the painter. The default value is
2062 qreal QPainter::opacity() const
2064 Q_D(const QPainter);
2066 qWarning("QPainter::opacity: Painter not active");
2069 return d->state->opacity;
2075 Sets the opacity of the painter to \a opacity. The value should
2076 be in the range 0.0 to 1.0, where 0.0 is fully transparent and
2077 1.0 is fully opaque.
2079 Opacity set on the painter will apply to all drawing operations
2083 void QPainter::setOpacity(qreal opacity)
2088 qWarning("QPainter::setOpacity: Painter not active");
2092 opacity = qMin(qreal(1), qMax(qreal(0), opacity));
2094 if (opacity == d->state->opacity)
2097 d->state->opacity = opacity;
2100 d->extended->opacityChanged();
2102 d->state->dirtyFlags |= QPaintEngine::DirtyOpacity;
2107 Returns the currently set brush origin.
2109 \sa setBrushOrigin(), {QPainter#Settings}{Settings}
2112 QPoint QPainter::brushOrigin() const
2114 Q_D(const QPainter);
2116 qWarning("QPainter::brushOrigin: Painter not active");
2119 return QPointF(d->state->brushOrigin).toPoint();
2123 \fn void QPainter::setBrushOrigin(const QPointF &position)
2125 Sets the brush origin to \a position.
2127 The brush origin specifies the (0, 0) coordinate of the painter's
2130 Note that while the brushOrigin() was necessary to adopt the
2131 parent's background for a widget in Qt 3, this is no longer the
2132 case since the Qt 4 painter doesn't paint the background unless
2133 you explicitly tell it to do so by setting the widget's \l
2134 {QWidget::autoFillBackground}{autoFillBackground} property to
2137 \sa brushOrigin(), {QPainter#Settings}{Settings}
2140 void QPainter::setBrushOrigin(const QPointF &p)
2143 #ifdef QT_DEBUG_DRAW
2144 if (qt_show_painter_debug_output)
2145 printf("QPainter::setBrushOrigin(), (%.2f,%.2f)\n", p.x(), p.y());
2149 qWarning("QPainter::setBrushOrigin: Painter not active");
2153 d->state->brushOrigin = p;
2156 d->extended->brushOriginChanged();
2160 d->state->dirtyFlags |= QPaintEngine::DirtyBrushOrigin;
2164 \fn void QPainter::setBrushOrigin(const QPoint &position)
2167 Sets the brush's origin to the given \a position.
2171 \fn void QPainter::setBrushOrigin(int x, int y)
2175 Sets the brush's origin to point (\a x, \a y).
2179 \enum QPainter::CompositionMode
2181 Defines the modes supported for digital image compositing.
2182 Composition modes are used to specify how the pixels in one image,
2183 the source, are merged with the pixel in another image, the
2186 Please note that the bitwise raster operation modes, denoted with
2187 a RasterOp prefix, are only natively supported in the X11 and
2188 raster paint engines. This means that the only way to utilize
2189 these modes on the Mac is via a QImage. The RasterOp denoted blend
2190 modes are \e not supported for pens and brushes with alpha
2191 components. Also, turning on the QPainter::Antialiasing render
2192 hint will effectively disable the RasterOp modes.
2195 \image qpainter-compositionmode1.png
2196 \image qpainter-compositionmode2.png
2198 The most common type is SourceOver (often referred to as just
2199 alpha blending) where the source pixel is blended on top of the
2200 destination pixel in such a way that the alpha component of the
2201 source defines the translucency of the pixel.
2203 When the paint device is a QImage, the image format must be set to
2204 \l {QImage::Format}{Format_ARGB32_Premultiplied} or
2205 \l {QImage::Format}{Format_ARGB32} for the composition modes to have
2206 any effect. For performance the premultiplied version is the preferred
2209 When a composition mode is set it applies to all painting
2210 operator, pens, brushes, gradients and pixmap/image drawing.
2212 \value CompositionMode_SourceOver This is the default mode. The
2213 alpha of the source is used to blend the pixel on top of the
2216 \value CompositionMode_DestinationOver The alpha of the
2217 destination is used to blend it on top of the source pixels. This
2218 mode is the inverse of CompositionMode_SourceOver.
2220 \value CompositionMode_Clear The pixels in the destination are
2221 cleared (set to fully transparent) independent of the source.
2223 \value CompositionMode_Source The output is the source
2224 pixel. (This means a basic copy operation and is identical to
2225 SourceOver when the source pixel is opaque).
2227 \value CompositionMode_Destination The output is the destination
2228 pixel. This means that the blending has no effect. This mode is
2229 the inverse of CompositionMode_Source.
2231 \value CompositionMode_SourceIn The output is the source, where
2232 the alpha is reduced by that of the destination.
2234 \value CompositionMode_DestinationIn The output is the
2235 destination, where the alpha is reduced by that of the
2236 source. This mode is the inverse of CompositionMode_SourceIn.
2238 \value CompositionMode_SourceOut The output is the source, where
2239 the alpha is reduced by the inverse of destination.
2241 \value CompositionMode_DestinationOut The output is the
2242 destination, where the alpha is reduced by the inverse of the
2243 source. This mode is the inverse of CompositionMode_SourceOut.
2245 \value CompositionMode_SourceAtop The source pixel is blended on
2246 top of the destination, with the alpha of the source pixel reduced
2247 by the alpha of the destination pixel.
2249 \value CompositionMode_DestinationAtop The destination pixel is
2250 blended on top of the source, with the alpha of the destination
2251 pixel is reduced by the alpha of the destination pixel. This mode
2252 is the inverse of CompositionMode_SourceAtop.
2254 \value CompositionMode_Xor The source, whose alpha is reduced with
2255 the inverse of the destination alpha, is merged with the
2256 destination, whose alpha is reduced by the inverse of the source
2257 alpha. CompositionMode_Xor is not the same as the bitwise Xor.
2259 \value CompositionMode_Plus Both the alpha and color of the source
2260 and destination pixels are added together.
2262 \value CompositionMode_Multiply The output is the source color
2263 multiplied by the destination. Multiplying a color with white
2264 leaves the color unchanged, while multiplying a color
2265 with black produces black.
2267 \value CompositionMode_Screen The source and destination colors
2268 are inverted and then multiplied. Screening a color with white
2269 produces white, whereas screening a color with black leaves the
2272 \value CompositionMode_Overlay Multiplies or screens the colors
2273 depending on the destination color. The destination color is mixed
2274 with the source color to reflect the lightness or darkness of the
2277 \value CompositionMode_Darken The darker of the source and
2278 destination colors is selected.
2280 \value CompositionMode_Lighten The lighter of the source and
2281 destination colors is selected.
2283 \value CompositionMode_ColorDodge The destination color is
2284 brightened to reflect the source color. A black source color
2285 leaves the destination color unchanged.
2287 \value CompositionMode_ColorBurn The destination color is darkened
2288 to reflect the source color. A white source color leaves the
2289 destination color unchanged.
2291 \value CompositionMode_HardLight Multiplies or screens the colors
2292 depending on the source color. A light source color will lighten
2293 the destination color, whereas a dark source color will darken the
2296 \value CompositionMode_SoftLight Darkens or lightens the colors
2297 depending on the source color. Similar to
2298 CompositionMode_HardLight.
2300 \value CompositionMode_Difference Subtracts the darker of the
2301 colors from the lighter. Painting with white inverts the
2302 destination color, whereas painting with black leaves the
2303 destination color unchanged.
2305 \value CompositionMode_Exclusion Similar to
2306 CompositionMode_Difference, but with a lower contrast. Painting
2307 with white inverts the destination color, whereas painting with
2308 black leaves the destination color unchanged.
2310 \value RasterOp_SourceOrDestination Does a bitwise OR operation on
2311 the source and destination pixels (src OR dst).
2313 \value RasterOp_SourceAndDestination Does a bitwise AND operation
2314 on the source and destination pixels (src AND dst).
2316 \value RasterOp_SourceXorDestination Does a bitwise XOR operation
2317 on the source and destination pixels (src XOR dst).
2319 \value RasterOp_NotSourceAndNotDestination Does a bitwise NOR
2320 operation on the source and destination pixels ((NOT src) AND (NOT
2323 \value RasterOp_NotSourceOrNotDestination Does a bitwise NAND
2324 operation on the source and destination pixels ((NOT src) OR (NOT
2327 \value RasterOp_NotSourceXorDestination Does a bitwise operation
2328 where the source pixels are inverted and then XOR'ed with the
2329 destination ((NOT src) XOR dst).
2331 \value RasterOp_NotSource Does a bitwise operation where the
2332 source pixels are inverted (NOT src).
2334 \value RasterOp_NotSourceAndDestination Does a bitwise operation
2335 where the source is inverted and then AND'ed with the destination
2336 ((NOT src) AND dst).
2338 \value RasterOp_SourceAndNotDestination Does a bitwise operation
2339 where the source is AND'ed with the inverted destination pixels
2340 (src AND (NOT dst)).
2342 \sa compositionMode(), setCompositionMode(), {QPainter#Composition
2343 Modes}{Composition Modes}, {Image Composition Example}
2347 Sets the composition mode to the given \a mode.
2349 \warning Only a QPainter operating on a QImage fully supports all
2350 composition modes. The RasterOp modes are supported for X11 as
2351 described in compositionMode().
2353 \sa compositionMode()
2355 void QPainter::setCompositionMode(CompositionMode mode)
2359 qWarning("QPainter::setCompositionMode: Painter not active");
2362 if (d->state->composition_mode == mode)
2365 d->state->composition_mode = mode;
2366 d->extended->compositionModeChanged();
2370 if (mode >= QPainter::RasterOp_SourceOrDestination) {
2371 if (!d->engine->hasFeature(QPaintEngine::RasterOpModes)) {
2372 qWarning("QPainter::setCompositionMode: "
2373 "Raster operation modes not supported on device");
2376 } else if (mode >= QPainter::CompositionMode_Plus) {
2377 if (!d->engine->hasFeature(QPaintEngine::BlendModes)) {
2378 qWarning("QPainter::setCompositionMode: "
2379 "Blend modes not supported on device");
2382 } else if (!d->engine->hasFeature(QPaintEngine::PorterDuff)) {
2383 if (mode != CompositionMode_Source && mode != CompositionMode_SourceOver) {
2384 qWarning("QPainter::setCompositionMode: "
2385 "PorterDuff modes not supported on device");
2390 d->state->composition_mode = mode;
2391 d->state->dirtyFlags |= QPaintEngine::DirtyCompositionMode;
2395 Returns the current composition mode.
2397 \sa CompositionMode, setCompositionMode()
2399 QPainter::CompositionMode QPainter::compositionMode() const
2401 Q_D(const QPainter);
2403 qWarning("QPainter::compositionMode: Painter not active");
2404 return QPainter::CompositionMode_SourceOver;
2406 return d->state->composition_mode;
2410 Returns the current background brush.
2412 \sa setBackground(), {QPainter#Settings}{Settings}
2415 const QBrush &QPainter::background() const
2417 Q_D(const QPainter);
2419 qWarning("QPainter::background: Painter not active");
2420 return d->fakeState()->brush;
2422 return d->state->bgBrush;
2427 Returns true if clipping has been set; otherwise returns false.
2429 \sa setClipping(), {QPainter#Clipping}{Clipping}
2432 bool QPainter::hasClipping() const
2434 Q_D(const QPainter);
2436 qWarning("QPainter::hasClipping: Painter not active");
2439 return d->state->clipEnabled && d->state->clipOperation != Qt::NoClip;
2444 Enables clipping if \a enable is true, or disables clipping if \a
2447 \sa hasClipping(), {QPainter#Clipping}{Clipping}
2450 void QPainter::setClipping(bool enable)
2453 #ifdef QT_DEBUG_DRAW
2454 if (qt_show_painter_debug_output)
2455 printf("QPainter::setClipping(), enable=%s, was=%s\n",
2456 enable ? "on" : "off",
2457 hasClipping() ? "on" : "off");
2460 qWarning("QPainter::setClipping: Painter not active, state will be reset by begin");
2464 if (hasClipping() == enable)
2467 // we can't enable clipping if we don't have a clip
2469 && (d->state->clipInfo.isEmpty() || d->state->clipInfo.last().operation == Qt::NoClip))
2471 d->state->clipEnabled = enable;
2474 d->extended->clipEnabledChanged();
2478 d->state->dirtyFlags |= QPaintEngine::DirtyClipEnabled;
2479 d->updateState(d->state);
2484 Returns the currently set clip region. Note that the clip region
2485 is given in logical coordinates.
2487 \warning QPainter does not store the combined clip explicitly as
2488 this is handled by the underlying QPaintEngine, so the path is
2489 recreated on demand and transformed to the current logical
2490 coordinate system. This is potentially an expensive operation.
2492 \sa setClipRegion(), clipPath(), setClipping()
2495 QRegion QPainter::clipRegion() const
2497 Q_D(const QPainter);
2499 qWarning("QPainter::clipRegion: Painter not active");
2504 bool lastWasNothing = true;
2507 const_cast<QPainter *>(this)->d_ptr->updateInvMatrix();
2509 // ### Falcon: Use QPainterPath
2510 for (int i=0; i<d->state->clipInfo.size(); ++i) {
2511 const QPainterClipInfo &info = d->state->clipInfo.at(i);
2512 switch (info.clipType) {
2514 case QPainterClipInfo::RegionClip: {
2515 QTransform matrix = (info.matrix * d->invMatrix);
2516 if (lastWasNothing) {
2517 region = info.region * matrix;
2518 lastWasNothing = false;
2521 if (info.operation == Qt::IntersectClip)
2522 region &= info.region * matrix;
2523 else if (info.operation == Qt::NoClip) {
2524 lastWasNothing = true;
2527 region = info.region * matrix;
2531 case QPainterClipInfo::PathClip: {
2532 QTransform matrix = (info.matrix * d->invMatrix);
2533 if (lastWasNothing) {
2534 region = QRegion((info.path * matrix).toFillPolygon().toPolygon(),
2535 info.path.fillRule());
2536 lastWasNothing = false;
2539 if (info.operation == Qt::IntersectClip) {
2540 region &= QRegion((info.path * matrix).toFillPolygon().toPolygon(),
2541 info.path.fillRule());
2542 } else if (info.operation == Qt::NoClip) {
2543 lastWasNothing = true;
2546 region = QRegion((info.path * matrix).toFillPolygon().toPolygon(),
2547 info.path.fillRule());
2552 case QPainterClipInfo::RectClip: {
2553 QTransform matrix = (info.matrix * d->invMatrix);
2554 if (lastWasNothing) {
2555 region = QRegion(info.rect) * matrix;
2556 lastWasNothing = false;
2559 if (info.operation == Qt::IntersectClip) {
2560 // Use rect intersection if possible.
2561 if (matrix.type() <= QTransform::TxScale)
2562 region &= matrix.mapRect(info.rect);
2564 region &= matrix.map(QRegion(info.rect));
2565 } else if (info.operation == Qt::NoClip) {
2566 lastWasNothing = true;
2569 region = QRegion(info.rect) * matrix;
2574 case QPainterClipInfo::RectFClip: {
2575 QTransform matrix = (info.matrix * d->invMatrix);
2576 if (lastWasNothing) {
2577 region = QRegion(info.rectf.toRect()) * matrix;
2578 lastWasNothing = false;
2581 if (info.operation == Qt::IntersectClip) {
2582 // Use rect intersection if possible.
2583 if (matrix.type() <= QTransform::TxScale)
2584 region &= matrix.mapRect(info.rectf.toRect());
2586 region &= matrix.map(QRegion(info.rectf.toRect()));
2587 } else if (info.operation == Qt::NoClip) {
2588 lastWasNothing = true;
2591 region = QRegion(info.rectf.toRect()) * matrix;
2601 extern QPainterPath qt_regionToPath(const QRegion ®ion);
2604 Returns the currently clip as a path. Note that the clip path is
2605 given in logical coordinates.
2607 \warning QPainter does not store the combined clip explicitly as
2608 this is handled by the underlying QPaintEngine, so the path is
2609 recreated on demand and transformed to the current logical
2610 coordinate system. This is potentially an expensive operation.
2612 \sa setClipPath(), clipRegion(), setClipping()
2614 QPainterPath QPainter::clipPath() const
2616 Q_D(const QPainter);
2618 // ### Since we do not support path intersections and path unions yet,
2619 // we just use clipRegion() here...
2621 qWarning("QPainter::clipPath: Painter not active");
2622 return QPainterPath();
2625 // No clip, return empty
2626 if (d->state->clipInfo.size() == 0) {
2627 return QPainterPath();
2630 // Update inverse matrix, used below.
2632 const_cast<QPainter *>(this)->d_ptr->updateInvMatrix();
2634 // For the simple case avoid conversion.
2635 if (d->state->clipInfo.size() == 1
2636 && d->state->clipInfo.at(0).clipType == QPainterClipInfo::PathClip) {
2637 QTransform matrix = (d->state->clipInfo.at(0).matrix * d->invMatrix);
2638 return d->state->clipInfo.at(0).path * matrix;
2640 } else if (d->state->clipInfo.size() == 1
2641 && d->state->clipInfo.at(0).clipType == QPainterClipInfo::RectClip) {
2642 QTransform matrix = (d->state->clipInfo.at(0).matrix * d->invMatrix);
2644 path.addRect(d->state->clipInfo.at(0).rect);
2645 return path * matrix;
2647 // Fallback to clipRegion() for now, since we don't have isect/unite for paths
2648 return qt_regionToPath(clipRegion());
2654 Returns the bounding rectangle of the current clip if there is a clip;
2655 otherwise returns an empty rectangle. Note that the clip region is
2656 given in logical coordinates.
2658 The bounding rectangle is not guaranteed to be tight.
2660 \sa setClipRect(), setClipPath(), setClipRegion()
2665 QRectF QPainter::clipBoundingRect() const
2667 Q_D(const QPainter);
2670 qWarning("QPainter::clipBoundingRect: Painter not active");
2674 // Accumulate the bounding box in device space. This is not 100%
2675 // precise, but it fits within the guarantee and it is reasonably
2678 for (int i=0; i<d->state->clipInfo.size(); ++i) {
2680 const QPainterClipInfo &info = d->state->clipInfo.at(i);
2682 if (info.clipType == QPainterClipInfo::RectClip)
2684 else if (info.clipType == QPainterClipInfo::RectFClip)
2686 else if (info.clipType == QPainterClipInfo::RegionClip)
2687 r = info.region.boundingRect();
2689 r = info.path.boundingRect();
2691 r = info.matrix.mapRect(r);
2695 else if (info.operation == Qt::IntersectClip)
2700 // Map the rectangle back into logical space using the inverse
2703 const_cast<QPainter *>(this)->d_ptr->updateInvMatrix();
2705 return d->invMatrix.mapRect(bounds);
2709 \fn void QPainter::setClipRect(const QRectF &rectangle, Qt::ClipOperation operation)
2711 Enables clipping, and sets the clip region to the given \a
2712 rectangle using the given clip \a operation. The default operation
2713 is to replace the current clip rectangle.
2715 Note that the clip rectangle is specified in logical (painter)
2718 \sa clipRegion(), setClipping(), {QPainter#Clipping}{Clipping}
2720 void QPainter::setClipRect(const QRectF &rect, Qt::ClipOperation op)
2725 if ((!d->state->clipEnabled && op != Qt::NoClip))
2726 op = Qt::ReplaceClip;
2729 qWarning("QPainter::setClipRect: Painter not active");
2732 qreal right = rect.x() + rect.width();
2733 qreal bottom = rect.y() + rect.height();
2734 qreal pts[] = { rect.x(), rect.y(),
2738 QVectorPath vp(pts, 4, 0, QVectorPath::RectangleHint);
2739 d->state->clipEnabled = true;
2740 d->extended->clip(vp, op);
2741 if (op == Qt::ReplaceClip || op == Qt::NoClip)
2742 d->state->clipInfo.clear();
2743 d->state->clipInfo << QPainterClipInfo(rect, op, d->state->matrix);
2744 d->state->clipOperation = op;
2748 if (qreal(int(rect.top())) == rect.top()
2749 && qreal(int(rect.bottom())) == rect.bottom()
2750 && qreal(int(rect.left())) == rect.left()
2751 && qreal(int(rect.right())) == rect.right())
2753 setClipRect(rect.toRect(), op);
2757 if (rect.isEmpty()) {
2758 setClipRegion(QRegion(), op);
2764 setClipPath(path, op);
2768 \fn void QPainter::setClipRect(const QRect &rectangle, Qt::ClipOperation operation)
2771 Enables clipping, and sets the clip region to the given \a rectangle using the given
2774 void QPainter::setClipRect(const QRect &rect, Qt::ClipOperation op)
2779 qWarning("QPainter::setClipRect: Painter not active");
2783 if ((!d->state->clipEnabled && op != Qt::NoClip))
2784 op = Qt::ReplaceClip;
2787 d->state->clipEnabled = true;
2788 d->extended->clip(rect, op);
2789 if (op == Qt::ReplaceClip || op == Qt::NoClip)
2790 d->state->clipInfo.clear();
2791 d->state->clipInfo << QPainterClipInfo(rect, op, d->state->matrix);
2792 d->state->clipOperation = op;
2796 if (d->state->clipOperation == Qt::NoClip && op == Qt::IntersectClip)
2797 op = Qt::ReplaceClip;
2799 d->state->clipRegion = rect;
2800 d->state->clipOperation = op;
2801 if (op == Qt::NoClip || op == Qt::ReplaceClip)
2802 d->state->clipInfo.clear();
2803 d->state->clipInfo << QPainterClipInfo(rect, op, d->state->matrix);
2804 d->state->clipEnabled = true;
2805 d->state->dirtyFlags |= QPaintEngine::DirtyClipRegion | QPaintEngine::DirtyClipEnabled;
2806 d->updateState(d->state);
2810 \fn void QPainter::setClipRect(int x, int y, int width, int height, Qt::ClipOperation operation)
2812 Enables clipping, and sets the clip region to the rectangle beginning at (\a x, \a y)
2813 with the given \a width and \a height.
2817 \fn void QPainter::setClipRegion(const QRegion ®ion, Qt::ClipOperation operation)
2819 Sets the clip region to the given \a region using the specified clip
2820 \a operation. The default clip operation is to replace the current
2823 Note that the clip region is given in logical coordinates.
2825 \sa clipRegion(), setClipRect(), {QPainter#Clipping}{Clipping}
2827 void QPainter::setClipRegion(const QRegion &r, Qt::ClipOperation op)
2830 #ifdef QT_DEBUG_DRAW
2831 QRect rect = r.boundingRect();
2832 if (qt_show_painter_debug_output)
2833 printf("QPainter::setClipRegion(), size=%d, [%d,%d,%d,%d]\n",
2834 r.rects().size(), rect.x(), rect.y(), rect.width(), rect.height());
2837 qWarning("QPainter::setClipRegion: Painter not active");
2841 if ((!d->state->clipEnabled && op != Qt::NoClip))
2842 op = Qt::ReplaceClip;
2845 d->state->clipEnabled = true;
2846 d->extended->clip(r, op);
2847 if (op == Qt::NoClip || op == Qt::ReplaceClip)
2848 d->state->clipInfo.clear();
2849 d->state->clipInfo << QPainterClipInfo(r, op, d->state->matrix);
2850 d->state->clipOperation = op;
2854 if (d->state->clipOperation == Qt::NoClip && op == Qt::IntersectClip)
2855 op = Qt::ReplaceClip;
2857 d->state->clipRegion = r;
2858 d->state->clipOperation = op;
2859 if (op == Qt::NoClip || op == Qt::ReplaceClip)
2860 d->state->clipInfo.clear();
2861 d->state->clipInfo << QPainterClipInfo(r, op, d->state->matrix);
2862 d->state->clipEnabled = true;
2863 d->state->dirtyFlags |= QPaintEngine::DirtyClipRegion | QPaintEngine::DirtyClipEnabled;
2864 d->updateState(d->state);
2871 Sets the transformation matrix to \a matrix and enables transformations.
2873 \note It is advisable to use setWorldTransform() instead of this function to
2874 preserve the properties of perspective transformations.
2876 If \a combine is true, then \a matrix is combined with the current
2877 transformation matrix; otherwise \a matrix replaces the current
2878 transformation matrix.
2880 If \a matrix is the identity matrix and \a combine is false, this
2881 function calls setWorldMatrixEnabled(false). (The identity matrix is the
2882 matrix where QMatrix::m11() and QMatrix::m22() are 1.0 and the
2885 The following functions can transform the coordinate system without using
2894 They operate on the painter's worldMatrix() and are implemented like this:
2896 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 4
2898 Note that when using setWorldMatrix() function you should always have
2899 \a combine be true when you are drawing into a QPicture. Otherwise
2900 it may not be possible to replay the picture with additional
2901 transformations; using the translate(), scale(), etc. convenience
2904 For more information about the coordinate system, transformations
2905 and window-viewport conversion, see \l {Coordinate System}.
2907 \sa setWorldTransform(), QTransform
2910 void QPainter::setWorldMatrix(const QMatrix &matrix, bool combine)
2912 setWorldTransform(QTransform(matrix), combine);
2919 Returns the world transformation matrix.
2921 It is advisable to use worldTransform() because worldMatrix() does not
2922 preserve the properties of perspective transformations.
2924 \sa {QPainter#Coordinate Transformations}{Coordinate Transformations},
2928 const QMatrix &QPainter::worldMatrix() const
2930 Q_D(const QPainter);
2932 qWarning("QPainter::worldMatrix: Painter not active");
2933 return d->fakeState()->transform.toAffine();
2935 return d->state->worldMatrix.toAffine();
2941 Use setWorldTransform() instead.
2943 \sa setWorldTransform()
2946 void QPainter::setMatrix(const QMatrix &matrix, bool combine)
2948 setWorldTransform(QTransform(matrix), combine);
2954 Use worldTransform() instead.
2956 \sa worldTransform()
2959 const QMatrix &QPainter::matrix() const
2961 return worldMatrix();
2969 Returns the transformation matrix combining the current
2970 window/viewport and world transformation.
2972 It is advisable to use combinedTransform() instead of this
2973 function to preserve the properties of perspective transformations.
2975 \sa setWorldTransform(), setWindow(), setViewport()
2977 QMatrix QPainter::combinedMatrix() const
2979 return combinedTransform().toAffine();
2986 Returns the matrix that transforms from logical coordinates to
2987 device coordinates of the platform dependent paint device.
2989 \note It is advisable to use deviceTransform() instead of this
2990 function to preserve the properties of perspective transformations.
2992 This function is \e only needed when using platform painting
2993 commands on the platform dependent handle (Qt::HANDLE), and the
2994 platform does not do transformations nativly.
2996 The QPaintEngine::PaintEngineFeature enum can be queried to
2997 determine whether the platform performs the transformations or
3000 \sa worldMatrix(), QPaintEngine::hasFeature(),
3002 const QMatrix &QPainter::deviceMatrix() const
3004 Q_D(const QPainter);
3006 qWarning("QPainter::deviceMatrix: Painter not active");
3007 return d->fakeState()->transform.toAffine();
3009 return d->state->matrix.toAffine();
3015 Resets any transformations that were made using translate(), scale(),
3016 shear(), rotate(), setWorldMatrix(), setViewport() and
3019 It is advisable to use resetTransform() instead of this function
3020 to preserve the properties of perspective transformations.
3022 \sa {QPainter#Coordinate Transformations}{Coordinate
3026 void QPainter::resetMatrix()
3035 Enables transformations if \a enable is true, or disables
3036 transformations if \a enable is false. The world transformation
3037 matrix is not changed.
3039 \sa worldMatrixEnabled(), worldTransform(), {QPainter#Coordinate
3040 Transformations}{Coordinate Transformations}
3043 void QPainter::setWorldMatrixEnabled(bool enable)
3046 #ifdef QT_DEBUG_DRAW
3047 if (qt_show_painter_debug_output)
3048 printf("QPainter::setMatrixEnabled(), enable=%d\n", enable);
3052 qWarning("QPainter::setMatrixEnabled: Painter not active");
3055 if (enable == d->state->WxF)
3058 d->state->WxF = enable;
3065 Returns true if world transformation is enabled; otherwise returns
3068 \sa setWorldMatrixEnabled(), worldTransform(), {Coordinate System}
3071 bool QPainter::worldMatrixEnabled() const
3073 Q_D(const QPainter);
3075 qWarning("QPainter::worldMatrixEnabled: Painter not active");
3078 return d->state->WxF;
3084 Use setWorldMatrixEnabled() instead.
3086 \sa setWorldMatrixEnabled()
3089 void QPainter::setMatrixEnabled(bool enable)
3091 setWorldMatrixEnabled(enable);
3097 Use worldMatrixEnabled() instead
3099 \sa worldMatrixEnabled()
3102 bool QPainter::matrixEnabled() const
3104 return worldMatrixEnabled();
3108 Scales the coordinate system by (\a{sx}, \a{sy}).
3110 \sa setWorldTransform() {QPainter#Coordinate Transformations}{Coordinate
3114 void QPainter::scale(qreal sx, qreal sy)
3116 #ifdef QT_DEBUG_DRAW
3117 if (qt_show_painter_debug_output)
3118 printf("QPainter::scale(), sx=%f, sy=%f\n", sx, sy);
3122 qWarning("QPainter::scale: Painter not active");
3126 d->state->worldMatrix.scale(sx,sy);
3127 d->state->WxF = true;
3132 Shears the coordinate system by (\a{sh}, \a{sv}).
3134 \sa setWorldTransform(), {QPainter#Coordinate Transformations}{Coordinate
3138 void QPainter::shear(qreal sh, qreal sv)
3140 #ifdef QT_DEBUG_DRAW
3141 if (qt_show_painter_debug_output)
3142 printf("QPainter::shear(), sh=%f, sv=%f\n", sh, sv);
3146 qWarning("QPainter::shear: Painter not active");
3150 d->state->worldMatrix.shear(sh, sv);
3151 d->state->WxF = true;
3156 \fn void QPainter::rotate(qreal angle)
3158 Rotates the coordinate system the given \a angle clockwise.
3160 \sa setWorldTransform(), {QPainter#Coordinate Transformations}{Coordinate
3164 void QPainter::rotate(qreal a)
3166 #ifdef QT_DEBUG_DRAW
3167 if (qt_show_painter_debug_output)
3168 printf("QPainter::rotate(), angle=%f\n", a);
3172 qWarning("QPainter::rotate: Painter not active");
3176 d->state->worldMatrix.rotate(a);
3177 d->state->WxF = true;
3182 Translates the coordinate system by the given \a offset; i.e. the
3183 given \a offset is added to points.
3185 \sa setWorldTransform(), {QPainter#Coordinate Transformations}{Coordinate
3188 void QPainter::translate(const QPointF &offset)
3190 qreal dx = offset.x();
3191 qreal dy = offset.y();
3192 #ifdef QT_DEBUG_DRAW
3193 if (qt_show_painter_debug_output)
3194 printf("QPainter::translate(), dx=%f, dy=%f\n", dx, dy);
3198 qWarning("QPainter::translate: Painter not active");
3202 d->state->worldMatrix.translate(dx, dy);
3203 d->state->WxF = true;
3208 \fn void QPainter::translate(const QPoint &offset)
3211 Translates the coordinate system by the given \a offset.
3215 \fn void QPainter::translate(qreal dx, qreal dy)
3218 Translates the coordinate system by the vector (\a dx, \a dy).
3222 \fn void QPainter::setClipPath(const QPainterPath &path, Qt::ClipOperation operation)
3224 Enables clipping, and sets the clip path for the painter to the
3225 given \a path, with the clip \a operation.
3227 Note that the clip path is specified in logical (painter)
3230 \sa clipPath(), clipRegion(), {QPainter#Clipping}{Clipping}
3233 void QPainter::setClipPath(const QPainterPath &path, Qt::ClipOperation op)
3235 #ifdef QT_DEBUG_DRAW
3236 if (qt_show_painter_debug_output) {
3237 QRectF b = path.boundingRect();
3238 printf("QPainter::setClipPath(), size=%d, op=%d, bounds=[%.2f,%.2f,%.2f,%.2f]\n",
3239 path.elementCount(), op, b.x(), b.y(), b.width(), b.height());
3245 qWarning("QPainter::setClipPath: Painter not active");
3249 if ((!d->state->clipEnabled && op != Qt::NoClip))
3250 op = Qt::ReplaceClip;
3253 d->state->clipEnabled = true;
3254 d->extended->clip(path, op);
3255 if (op == Qt::NoClip || op == Qt::ReplaceClip)
3256 d->state->clipInfo.clear();
3257 d->state->clipInfo << QPainterClipInfo(path, op, d->state->matrix);
3258 d->state->clipOperation = op;
3262 if (d->state->clipOperation == Qt::NoClip && op == Qt::IntersectClip)
3263 op = Qt::ReplaceClip;
3265 d->state->clipPath = path;
3266 d->state->clipOperation = op;
3267 if (op == Qt::NoClip || op == Qt::ReplaceClip)
3268 d->state->clipInfo.clear();
3269 d->state->clipInfo << QPainterClipInfo(path, op, d->state->matrix);
3270 d->state->clipEnabled = true;
3271 d->state->dirtyFlags |= QPaintEngine::DirtyClipPath | QPaintEngine::DirtyClipEnabled;
3272 d->updateState(d->state);
3276 Draws the outline (strokes) the path \a path with the pen specified
3279 \sa fillPath(), {QPainter#Drawing}{Drawing}
3281 void QPainter::strokePath(const QPainterPath &path, const QPen &pen)
3286 qWarning("QPainter::strokePath: Painter not active");
3294 const QGradient *g = qpen_brush(pen).gradient();
3295 if (!g || g->coordinateMode() == QGradient::LogicalMode) {
3296 d->extended->stroke(qtVectorPathForPath(path), pen);
3301 QBrush oldBrush = d->state->brush;
3302 QPen oldPen = d->state->pen;
3305 setBrush(Qt::NoBrush);
3315 Fills the given \a path using the given \a brush. The outline is
3318 Alternatively, you can specify a QColor instead of a QBrush; the
3319 QBrush constructor (taking a QColor argument) will automatically
3320 create a solid pattern brush.
3324 void QPainter::fillPath(const QPainterPath &path, const QBrush &brush)
3329 qWarning("QPainter::fillPath: Painter not active");
3337 const QGradient *g = brush.gradient();
3338 if (!g || g->coordinateMode() == QGradient::LogicalMode) {
3339 d->extended->fill(qtVectorPathForPath(path), brush);
3344 QBrush oldBrush = d->state->brush;
3345 QPen oldPen = d->state->pen;
3358 Draws the given painter \a path using the current pen for outline
3359 and the current brush for filling.
3363 \li \inlineimage qpainter-path.png
3365 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 5
3368 \sa {painting/painterpaths}{the Painter Paths
3369 example},{painting/deform}{the Vector Deformation example}
3371 void QPainter::drawPath(const QPainterPath &path)
3373 #ifdef QT_DEBUG_DRAW
3374 QRectF pathBounds = path.boundingRect();
3375 if (qt_show_painter_debug_output)
3376 printf("QPainter::drawPath(), size=%d, [%.2f,%.2f,%.2f,%.2f]\n",
3377 path.elementCount(),
3378 pathBounds.x(), pathBounds.y(), pathBounds.width(), pathBounds.height());
3384 qWarning("QPainter::drawPath: Painter not active");
3389 d->extended->drawPath(path);
3392 d->updateState(d->state);
3394 if (d->engine->hasFeature(QPaintEngine::PainterPaths) && d->state->emulationSpecifier == 0) {
3395 d->engine->drawPath(path);
3397 d->draw_helper(path);
3402 \fn void QPainter::drawLine(const QLineF &line)
3404 Draws a line defined by \a line.
3408 \li \inlineimage qpainter-line.png
3410 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 6
3413 \sa drawLines(), drawPolyline(), {Coordinate System}
3417 \fn void QPainter::drawLine(const QLine &line)
3420 Draws a line defined by \a line.
3424 \fn void QPainter::drawLine(const QPoint &p1, const QPoint &p2)
3427 Draws a line from \a p1 to \a p2.
3431 \fn void QPainter::drawLine(const QPointF &p1, const QPointF &p2)
3434 Draws a line from \a p1 to \a p2.
3438 \fn void QPainter::drawLine(int x1, int y1, int x2, int y2)
3441 Draws a line from (\a x1, \a y1) to (\a x2, \a y2) and sets the
3442 current pen position to (\a x2, \a y2).
3446 \fn void QPainter::drawRect(const QRectF &rectangle)
3448 Draws the current \a rectangle with the current pen and brush.
3450 A filled rectangle has a size of \a{rectangle}.size(). A stroked
3451 rectangle has a size of \a{rectangle}.size() plus the pen width.
3455 \li \inlineimage qpainter-rectangle.png
3457 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 7
3460 \sa drawRects(), drawPolygon(), {Coordinate System}
3464 \fn void QPainter::drawRect(const QRect &rectangle)
3468 Draws the current \a rectangle with the current pen and brush.
3472 \fn void QPainter::drawRect(int x, int y, int width, int height)
3476 Draws a rectangle with upper left corner at (\a{x}, \a{y}) and
3477 with the given \a width and \a height.
3481 \fn void QPainter::drawRects(const QRectF *rectangles, int rectCount)
3483 Draws the first \a rectCount of the given \a rectangles using the
3484 current pen and brush.
3488 void QPainter::drawRects(const QRectF *rects, int rectCount)
3490 #ifdef QT_DEBUG_DRAW
3491 if (qt_show_painter_debug_output)
3492 printf("QPainter::drawRects(), count=%d\n", rectCount);
3497 qWarning("QPainter::drawRects: Painter not active");
3505 d->extended->drawRects(rects, rectCount);
3509 d->updateState(d->state);
3511 if (!d->state->emulationSpecifier) {
3512 d->engine->drawRects(rects, rectCount);
3516 if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
3517 && d->state->matrix.type() == QTransform::TxTranslate) {
3518 for (int i=0; i<rectCount; ++i) {
3519 QRectF r(rects[i].x() + d->state->matrix.dx(),
3520 rects[i].y() + d->state->matrix.dy(),
3523 d->engine->drawRects(&r, 1);
3526 if (d->state->brushNeedsResolving() || d->state->penNeedsResolving()) {
3527 for (int i=0; i<rectCount; ++i) {
3528 QPainterPath rectPath;
3529 rectPath.addRect(rects[i]);
3530 d->draw_helper(rectPath, QPainterPrivate::StrokeAndFillDraw);
3533 QPainterPath rectPath;
3534 for (int i=0; i<rectCount; ++i)
3535 rectPath.addRect(rects[i]);
3536 d->draw_helper(rectPath, QPainterPrivate::StrokeAndFillDraw);
3542 \fn void QPainter::drawRects(const QRect *rectangles, int rectCount)
3545 Draws the first \a rectCount of the given \a rectangles using the
3546 current pen and brush.
3548 void QPainter::drawRects(const QRect *rects, int rectCount)
3550 #ifdef QT_DEBUG_DRAW
3551 if (qt_show_painter_debug_output)
3552 printf("QPainter::drawRects(), count=%d\n", rectCount);
3557 qWarning("QPainter::drawRects: Painter not active");
3565 d->extended->drawRects(rects, rectCount);
3569 d->updateState(d->state);
3571 if (!d->state->emulationSpecifier) {
3572 d->engine->drawRects(rects, rectCount);
3576 if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
3577 && d->state->matrix.type() == QTransform::TxTranslate) {
3578 for (int i=0; i<rectCount; ++i) {
3579 QRectF r(rects[i].x() + d->state->matrix.dx(),
3580 rects[i].y() + d->state->matrix.dy(),
3584 d->engine->drawRects(&r, 1);
3587 if (d->state->brushNeedsResolving() || d->state->penNeedsResolving()) {
3588 for (int i=0; i<rectCount; ++i) {
3589 QPainterPath rectPath;
3590 rectPath.addRect(rects[i]);
3591 d->draw_helper(rectPath, QPainterPrivate::StrokeAndFillDraw);
3594 QPainterPath rectPath;
3595 for (int i=0; i<rectCount; ++i)
3596 rectPath.addRect(rects[i]);
3598 d->draw_helper(rectPath, QPainterPrivate::StrokeAndFillDraw);
3604 \fn void QPainter::drawRects(const QVector<QRectF> &rectangles)
3607 Draws the given \a rectangles using the current pen and brush.
3611 \fn void QPainter::drawRects(const QVector<QRect> &rectangles)
3615 Draws the given \a rectangles using the current pen and brush.
3619 \fn void QPainter::drawPoint(const QPointF &position)
3621 Draws a single point at the given \a position using the current
3624 \sa {Coordinate System}
3628 \fn void QPainter::drawPoint(const QPoint &position)
3631 Draws a single point at the given \a position using the current
3635 /*! \fn void QPainter::drawPoint(int x, int y)
3639 Draws a single point at position (\a x, \a y).
3643 Draws the first \a pointCount points in the array \a points using
3644 the current pen's color.
3646 \sa {Coordinate System}
3648 void QPainter::drawPoints(const QPointF *points, int pointCount)
3650 #ifdef QT_DEBUG_DRAW
3651 if (qt_show_painter_debug_output)
3652 printf("QPainter::drawPoints(), count=%d\n", pointCount);
3657 qWarning("QPainter::drawPoints: Painter not active");
3661 if (pointCount <= 0)
3665 d->extended->drawPoints(points, pointCount);
3669 d->updateState(d->state);
3671 if (!d->state->emulationSpecifier) {
3672 d->engine->drawPoints(points, pointCount);
3676 if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
3677 && d->state->matrix.type() == QTransform::TxTranslate) {
3678 // ### use drawPoints function
3679 for (int i=0; i<pointCount; ++i) {
3680 QPointF pt(points[i].x() + d->state->matrix.dx(),
3681 points[i].y() + d->state->matrix.dy());
3682 d->engine->drawPoints(&pt, 1);
3685 QPen pen = d->state->pen;
3686 bool flat_pen = pen.capStyle() == Qt::FlatCap;
3689 pen.setCapStyle(Qt::SquareCap);
3693 for (int i=0; i<pointCount; ++i) {
3694 path.moveTo(points[i].x(), points[i].y());
3695 path.lineTo(points[i].x() + 0.0001, points[i].y());
3697 d->draw_helper(path, QPainterPrivate::StrokeDraw);
3706 Draws the first \a pointCount points in the array \a points using
3707 the current pen's color.
3710 void QPainter::drawPoints(const QPoint *points, int pointCount)
3712 #ifdef QT_DEBUG_DRAW
3713 if (qt_show_painter_debug_output)
3714 printf("QPainter::drawPoints(), count=%d\n", pointCount);
3719 qWarning("QPainter::drawPoints: Painter not active");
3723 if (pointCount <= 0)
3727 d->extended->drawPoints(points, pointCount);
3731 d->updateState(d->state);
3733 if (!d->state->emulationSpecifier) {
3734 d->engine->drawPoints(points, pointCount);
3738 if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
3739 && d->state->matrix.type() == QTransform::TxTranslate) {
3740 // ### use drawPoints function
3741 for (int i=0; i<pointCount; ++i) {
3742 QPointF pt(points[i].x() + d->state->matrix.dx(),
3743 points[i].y() + d->state->matrix.dy());
3744 d->engine->drawPoints(&pt, 1);
3747 QPen pen = d->state->pen;
3748 bool flat_pen = (pen.capStyle() == Qt::FlatCap);
3751 pen.setCapStyle(Qt::SquareCap);
3755 for (int i=0; i<pointCount; ++i) {
3756 path.moveTo(points[i].x(), points[i].y());
3757 path.lineTo(points[i].x() + 0.0001, points[i].y());
3759 d->draw_helper(path, QPainterPrivate::StrokeDraw);
3766 \fn void QPainter::drawPoints(const QPolygonF &points)
3770 Draws the points in the vector \a points.
3774 \fn void QPainter::drawPoints(const QPolygon &points)
3778 Draws the points in the vector \a points.
3782 Sets the background mode of the painter to the given \a mode
3784 Qt::TransparentMode (the default) draws stippled lines and text
3785 without setting the background pixels. Qt::OpaqueMode fills these
3786 space with the current background color.
3788 Note that in order to draw a bitmap or pixmap transparently, you
3789 must use QPixmap::setMask().
3791 \sa backgroundMode(), setBackground(),
3792 {QPainter#Settings}{Settings}
3795 void QPainter::setBackgroundMode(Qt::BGMode mode)
3797 #ifdef QT_DEBUG_DRAW
3798 if (qt_show_painter_debug_output)
3799 printf("QPainter::setBackgroundMode(), mode=%d\n", mode);
3804 qWarning("QPainter::setBackgroundMode: Painter not active");
3807 if (d->state->bgMode == mode)
3810 d->state->bgMode = mode;
3812 d->checkEmulation();
3814 d->state->dirtyFlags |= QPaintEngine::DirtyBackgroundMode;
3819 Returns the current background mode.
3821 \sa setBackgroundMode(), {QPainter#Settings}{Settings}
3823 Qt::BGMode QPainter::backgroundMode() const
3825 Q_D(const QPainter);
3827 qWarning("QPainter::backgroundMode: Painter not active");
3828 return Qt::TransparentMode;
3830 return d->state->bgMode;
3837 Sets the painter's pen to have style Qt::SolidLine, width 0 and the
3841 void QPainter::setPen(const QColor &color)
3843 #ifdef QT_DEBUG_DRAW
3844 if (qt_show_painter_debug_output)
3845 printf("QPainter::setPen(), color=%04x\n", color.rgb());
3849 qWarning("QPainter::setPen: Painter not active");
3853 if (d->state->pen.style() == Qt::SolidLine
3854 && d->state->pen.widthF() == 0
3855 && d->state->pen.isSolid()
3856 && d->state->pen.color() == color)
3859 QPen pen(color.isValid() ? color : QColor(Qt::black), 0, Qt::SolidLine);
3861 d->state->pen = pen;
3863 d->extended->penChanged();
3865 d->state->dirtyFlags |= QPaintEngine::DirtyPen;
3869 Sets the painter's pen to be the given \a pen.
3871 The \a pen defines how to draw lines and outlines, and it also
3872 defines the text color.
3874 \sa pen(), {QPainter#Settings}{Settings}
3877 void QPainter::setPen(const QPen &pen)
3880 #ifdef QT_DEBUG_DRAW
3881 if (qt_show_painter_debug_output)
3882 printf("QPainter::setPen(), color=%04x, (brushStyle=%d) style=%d, cap=%d, join=%d\n",
3883 pen.color().rgb(), pen.brush().style(), pen.style(), pen.capStyle(), pen.joinStyle());
3887 qWarning("QPainter::setPen: Painter not active");
3891 if (d->state->pen == pen)
3894 d->state->pen = pen;
3897 d->checkEmulation();
3898 d->extended->penChanged();
3902 d->state->dirtyFlags |= QPaintEngine::DirtyPen;
3908 Sets the painter's pen to have the given \a style, width 0 and
3912 void QPainter::setPen(Qt::PenStyle style)
3916 qWarning("QPainter::setPen: Painter not active");
3920 if (d->state->pen.style() == style
3921 && (style == Qt::NoPen || (d->state->pen.widthF() == 0
3922 && d->state->pen.isSolid()
3923 && d->state->pen.color() == QColor(Qt::black))))
3926 // QPen(Qt::NoPen) is to avoid creating QPenData, including its brush (from the color)
3927 // Note that this works well as long as QPen(Qt::NoPen) returns a black, zero-width pen
3928 d->state->pen = (style == Qt::NoPen) ? QPen(Qt::NoPen) : QPen(Qt::black, 0, style);
3931 d->extended->penChanged();
3933 d->state->dirtyFlags |= QPaintEngine::DirtyPen;
3938 Returns the painter's current pen.
3940 \sa setPen(), {QPainter#Settings}{Settings}
3943 const QPen &QPainter::pen() const
3945 Q_D(const QPainter);
3947 qWarning("QPainter::pen: Painter not active");
3948 return d->fakeState()->pen;
3950 return d->state->pen;
3955 Sets the painter's brush to the given \a brush.
3957 The painter's brush defines how shapes are filled.
3959 \sa brush(), {QPainter#Settings}{Settings}
3962 void QPainter::setBrush(const QBrush &brush)
3964 #ifdef QT_DEBUG_DRAW
3965 if (qt_show_painter_debug_output)
3966 printf("QPainter::setBrush(), color=%04x, style=%d\n", brush.color().rgb(), brush.style());
3970 qWarning("QPainter::setBrush: Painter not active");
3974 if (d->state->brush.d == brush.d)
3978 d->state->brush = brush;
3979 d->checkEmulation();
3980 d->extended->brushChanged();
3984 d->state->brush = brush;
3985 d->state->dirtyFlags |= QPaintEngine::DirtyBrush;
3992 Sets the painter's brush to black color and the specified \a
3996 void QPainter::setBrush(Qt::BrushStyle style)
4000 qWarning("QPainter::setBrush: Painter not active");
4003 if (d->state->brush.style() == style &&
4004 (style == Qt::NoBrush
4005 || (style == Qt::SolidPattern && d->state->brush.color() == QColor(0, 0, 0))))
4007 d->state->brush = QBrush(Qt::black, style);
4009 d->extended->brushChanged();
4011 d->state->dirtyFlags |= QPaintEngine::DirtyBrush;
4015 Returns the painter's current brush.
4017 \sa QPainter::setBrush(), {QPainter#Settings}{Settings}
4020 const QBrush &QPainter::brush() const
4022 Q_D(const QPainter);
4024 qWarning("QPainter::brush: Painter not active");
4025 return d->fakeState()->brush;
4027 return d->state->brush;
4031 \fn void QPainter::setBackground(const QBrush &brush)
4033 Sets the background brush of the painter to the given \a brush.
4035 The background brush is the brush that is filled in when drawing
4036 opaque text, stippled lines and bitmaps. The background brush has
4037 no effect in transparent background mode (which is the default).
4039 \sa background(), setBackgroundMode(),
4040 {QPainter#Settings}{Settings}
4043 void QPainter::setBackground(const QBrush &bg)
4045 #ifdef QT_DEBUG_DRAW
4046 if (qt_show_painter_debug_output)
4047 printf("QPainter::setBackground(), color=%04x, style=%d\n", bg.color().rgb(), bg.style());
4052 qWarning("QPainter::setBackground: Painter not active");
4055 d->state->bgBrush = bg;
4057 d->state->dirtyFlags |= QPaintEngine::DirtyBackground;
4061 Sets the painter's font to the given \a font.
4063 This font is used by subsequent drawText() functions. The text
4064 color is the same as the pen color.
4066 If you set a font that isn't available, Qt finds a close match.
4067 font() will return what you set using setFont() and fontInfo() returns the
4068 font actually being used (which may be the same).
4070 \sa font(), drawText(), {QPainter#Settings}{Settings}
4073 void QPainter::setFont(const QFont &font)
4077 #ifdef QT_DEBUG_DRAW
4078 if (qt_show_painter_debug_output)
4079 printf("QPainter::setFont(), family=%s, pointSize=%d\n", font.family().toLatin1().constData(), font.pointSize());
4083 qWarning("QPainter::setFont: Painter not active");
4087 d->state->font = QFont(font.resolve(d->state->deviceFont), device());
4089 d->state->dirtyFlags |= QPaintEngine::DirtyFont;
4093 Returns the currently set font used for drawing text.
4095 \sa setFont(), drawText(), {QPainter#Settings}{Settings}
4097 const QFont &QPainter::font() const
4099 Q_D(const QPainter);
4101 qWarning("QPainter::font: Painter not active");
4102 return d->fakeState()->font;
4104 return d->state->font;
4110 Draws the given rectangle \a rect with rounded corners.
4112 The \a xRadius and \a yRadius arguments specify the radii
4113 of the ellipses defining the corners of the rounded rectangle.
4114 When \a mode is Qt::RelativeSize, \a xRadius and
4115 \a yRadius are specified in percentage of half the rectangle's
4116 width and height respectively, and should be in the range
4119 A filled rectangle has a size of rect.size(). A stroked rectangle
4120 has a size of rect.size() plus the pen width.
4124 \li \inlineimage qpainter-roundrect.png
4126 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 8
4129 \sa drawRect(), QPen
4131 void QPainter::drawRoundedRect(const QRectF &rect, qreal xRadius, qreal yRadius, Qt::SizeMode mode)
4133 #ifdef QT_DEBUG_DRAW
4134 if (qt_show_painter_debug_output)
4135 printf("QPainter::drawRoundedRect(), [%.2f,%.2f,%.2f,%.2f]\n", rect.x(), rect.y(), rect.width(), rect.height());
4142 if (xRadius <= 0 || yRadius <= 0) { // draw normal rectangle
4148 d->extended->drawRoundedRect(rect, xRadius, yRadius, mode);
4153 path.addRoundedRect(rect, xRadius, yRadius, mode);
4158 \fn void QPainter::drawRoundedRect(const QRect &rect, qreal xRadius, qreal yRadius,
4159 Qt::SizeMode mode = Qt::AbsoluteSize);
4163 Draws the given rectangle \a rect with rounded corners.
4167 \fn void QPainter::drawRoundedRect(int x, int y, int w, int h, qreal xRadius, qreal yRadius,
4168 Qt::SizeMode mode = Qt::AbsoluteSize);
4172 Draws the given rectangle \a x, \a y, \a w, \a h with rounded corners.
4178 Draws a rectangle \a r with rounded corners.
4180 The \a xRnd and \a yRnd arguments specify how rounded the corners
4181 should be. 0 is angled corners, 99 is maximum roundedness.
4183 A filled rectangle has a size of r.size(). A stroked rectangle
4184 has a size of r.size() plus the pen width.
4186 \sa drawRoundedRect()
4188 void QPainter::drawRoundRect(const QRectF &r, int xRnd, int yRnd)
4190 drawRoundedRect(r, xRnd, yRnd, Qt::RelativeSize);
4195 \fn void QPainter::drawRoundRect(const QRect &r, int xRnd = 25, int yRnd = 25)
4200 Draws the rectangle \a r with rounded corners.
4206 \fn QPainter::drawRoundRect(int x, int y, int w, int h, int xRnd, int yRnd)
4210 Draws the rectangle \a x, \a y, \a w, \a h with rounded corners.
4214 \fn void QPainter::drawEllipse(const QRectF &rectangle)
4216 Draws the ellipse defined by the given \a rectangle.
4218 A filled ellipse has a size of \a{rectangle}.\l
4219 {QRect::size()}{size()}. A stroked ellipse has a size of
4220 \a{rectangle}.\l {QRect::size()}{size()} plus the pen width.
4224 \li \inlineimage qpainter-ellipse.png
4226 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 9
4229 \sa drawPie(), {Coordinate System}
4231 void QPainter::drawEllipse(const QRectF &r)
4233 #ifdef QT_DEBUG_DRAW
4234 if (qt_show_painter_debug_output)
4235 printf("QPainter::drawEllipse(), [%.2f,%.2f,%.2f,%.2f]\n", r.x(), r.y(), r.width(), r.height());
4242 QRectF rect(r.normalized());
4245 d->extended->drawEllipse(rect);
4249 d->updateState(d->state);
4250 if (d->state->emulationSpecifier) {
4251 if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
4252 && d->state->matrix.type() == QTransform::TxTranslate) {
4253 rect.translate(QPointF(d->state->matrix.dx(), d->state->matrix.dy()));
4256 path.addEllipse(rect);
4257 d->draw_helper(path, QPainterPrivate::StrokeAndFillDraw);
4262 d->engine->drawEllipse(rect);
4266 \fn QPainter::drawEllipse(const QRect &rectangle)
4270 Draws the ellipse defined by the given \a rectangle.
4272 void QPainter::drawEllipse(const QRect &r)
4274 #ifdef QT_DEBUG_DRAW
4275 if (qt_show_painter_debug_output)
4276 printf("QPainter::drawEllipse(), [%d,%d,%d,%d]\n", r.x(), r.y(), r.width(), r.height());
4283 QRect rect(r.normalized());
4286 d->extended->drawEllipse(rect);
4290 d->updateState(d->state);
4292 if (d->state->emulationSpecifier) {
4293 if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
4294 && d->state->matrix.type() == QTransform::TxTranslate) {
4295 rect.translate(QPoint(qRound(d->state->matrix.dx()), qRound(d->state->matrix.dy())));
4298 path.addEllipse(rect);
4299 d->draw_helper(path, QPainterPrivate::StrokeAndFillDraw);
4304 d->engine->drawEllipse(rect);
4308 \fn QPainter::drawEllipse(int x, int y, int width, int height)
4312 Draws the ellipse defined by the rectangle beginning at (\a{x},
4313 \a{y}) with the given \a width and \a height.
4319 \fn QPainter::drawEllipse(const QPointF ¢er, qreal rx, qreal ry)
4323 Draws the ellipse positioned at \a{center} with radii \a{rx} and \a{ry}.
4329 \fn QPainter::drawEllipse(const QPoint ¢er, int rx, int ry)
4333 Draws the ellipse positioned at \a{center} with radii \a{rx} and \a{ry}.
4337 \fn void QPainter::drawArc(const QRectF &rectangle, int startAngle, int spanAngle)
4339 Draws the arc defined by the given \a rectangle, \a startAngle and
4342 The \a startAngle and \a spanAngle must be specified in 1/16th of
4343 a degree, i.e. a full circle equals 5760 (16 * 360). Positive
4344 values for the angles mean counter-clockwise while negative values
4345 mean the clockwise direction. Zero degrees is at the 3 o'clock
4350 \li \inlineimage qpainter-arc.png
4352 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 10
4355 \sa drawPie(), drawChord(), {Coordinate System}
4358 void QPainter::drawArc(const QRectF &r, int a, int alen)
4360 #ifdef QT_DEBUG_DRAW
4361 if (qt_show_painter_debug_output)
4362 printf("QPainter::drawArc(), [%.2f,%.2f,%.2f,%.2f], angle=%d, sweep=%d\n",
4363 r.x(), r.y(), r.width(), r.height(), a/16, alen/16);
4370 QRectF rect = r.normalized();
4373 path.arcMoveTo(rect, a/16.0);
4374 path.arcTo(rect, a/16.0, alen/16.0);
4375 strokePath(path, d->state->pen);
4378 /*! \fn void QPainter::drawArc(const QRect &rectangle, int startAngle,
4383 Draws the arc defined by the given \a rectangle, \a startAngle and
4388 \fn void QPainter::drawArc(int x, int y, int width, int height,
4389 int startAngle, int spanAngle)
4393 Draws the arc defined by the rectangle beginning at (\a x, \a y)
4394 with the specified \a width and \a height, and the given \a
4395 startAngle and \a spanAngle.
4399 \fn void QPainter::drawPie(const QRectF &rectangle, int startAngle, int spanAngle)
4401 Draws a pie defined by the given \a rectangle, \a startAngle and
4404 The pie is filled with the current brush().
4406 The startAngle and spanAngle must be specified in 1/16th of a
4407 degree, i.e. a full circle equals 5760 (16 * 360). Positive values
4408 for the angles mean counter-clockwise while negative values mean
4409 the clockwise direction. Zero degrees is at the 3 o'clock
4414 \li \inlineimage qpainter-pie.png
4416 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 11
4419 \sa drawEllipse(), drawChord(), {Coordinate System}
4421 void QPainter::drawPie(const QRectF &r, int a, int alen)
4423 #ifdef QT_DEBUG_DRAW
4424 if (qt_show_painter_debug_output)
4425 printf("QPainter::drawPie(), [%.2f,%.2f,%.2f,%.2f], angle=%d, sweep=%d\n",
4426 r.x(), r.y(), r.width(), r.height(), a/16, alen/16);
4437 if (a < 0) a += (360*16);
4440 QRectF rect = r.normalized();
4443 path.moveTo(rect.center());
4444 path.arcTo(rect.x(), rect.y(), rect.width(), rect.height(), a/16.0, alen/16.0);
4445 path.closeSubpath();
4451 \fn void QPainter::drawPie(const QRect &rectangle, int startAngle, int spanAngle)
4454 Draws a pie defined by the given \a rectangle, \a startAngle and
4459 \fn void QPainter::drawPie(int x, int y, int width, int height, int
4460 startAngle, int spanAngle)
4464 Draws the pie defined by the rectangle beginning at (\a x, \a y) with
4465 the specified \a width and \a height, and the given \a startAngle and
4470 \fn void QPainter::drawChord(const QRectF &rectangle, int startAngle, int spanAngle)
4472 Draws the chord defined by the given \a rectangle, \a startAngle and
4473 \a spanAngle. The chord is filled with the current brush().
4475 The startAngle and spanAngle must be specified in 1/16th of a
4476 degree, i.e. a full circle equals 5760 (16 * 360). Positive values
4477 for the angles mean counter-clockwise while negative values mean
4478 the clockwise direction. Zero degrees is at the 3 o'clock
4483 \li \inlineimage qpainter-chord.png
4485 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 12
4488 \sa drawArc(), drawPie(), {Coordinate System}
4490 void QPainter::drawChord(const QRectF &r, int a, int alen)
4492 #ifdef QT_DEBUG_DRAW
4493 if (qt_show_painter_debug_output)
4494 printf("QPainter::drawChord(), [%.2f,%.2f,%.2f,%.2f], angle=%d, sweep=%d\n",
4495 r.x(), r.y(), r.width(), r.height(), a/16, alen/16);
4502 QRectF rect = r.normalized();
4505 path.arcMoveTo(rect, a/16.0);
4506 path.arcTo(rect, a/16.0, alen/16.0);
4507 path.closeSubpath();
4511 \fn void QPainter::drawChord(const QRect &rectangle, int startAngle, int spanAngle)
4515 Draws the chord defined by the given \a rectangle, \a startAngle and
4520 \fn void QPainter::drawChord(int x, int y, int width, int height, int
4521 startAngle, int spanAngle)
4525 Draws the chord defined by the rectangle beginning at (\a x, \a y)
4526 with the specified \a width and \a height, and the given \a
4527 startAngle and \a spanAngle.
4532 Draws the first \a lineCount lines in the array \a lines
4533 using the current pen.
4535 \sa drawLine(), drawPolyline()
4537 void QPainter::drawLines(const QLineF *lines, int lineCount)
4539 #ifdef QT_DEBUG_DRAW
4540 if (qt_show_painter_debug_output)
4541 printf("QPainter::drawLines(), line count=%d\n", lineCount);
4546 if (!d->engine || lineCount < 1)
4550 d->extended->drawLines(lines, lineCount);
4554 d->updateState(d->state);
4556 uint lineEmulation = line_emulation(d->state->emulationSpecifier);
4558 if (lineEmulation) {
4559 if (lineEmulation == QPaintEngine::PrimitiveTransform
4560 && d->state->matrix.type() == QTransform::TxTranslate) {
4561 for (int i = 0; i < lineCount; ++i) {
4562 QLineF line = lines[i];
4563 line.translate(d->state->matrix.dx(), d->state->matrix.dy());
4564 d->engine->drawLines(&line, 1);
4567 QPainterPath linePath;
4568 for (int i = 0; i < lineCount; ++i) {
4569 linePath.moveTo(lines[i].p1());
4570 linePath.lineTo(lines[i].p2());
4572 d->draw_helper(linePath, QPainterPrivate::StrokeDraw);
4576 d->engine->drawLines(lines, lineCount);
4580 \fn void QPainter::drawLines(const QLine *lines, int lineCount)
4583 Draws the first \a lineCount lines in the array \a lines
4584 using the current pen.
4586 void QPainter::drawLines(const QLine *lines, int lineCount)
4588 #ifdef QT_DEBUG_DRAW
4589 if (qt_show_painter_debug_output)
4590 printf("QPainter::drawLine(), line count=%d\n", lineCount);
4595 if (!d->engine || lineCount < 1)
4599 d->extended->drawLines(lines, lineCount);
4603 d->updateState(d->state);
4605 uint lineEmulation = line_emulation(d->state->emulationSpecifier);
4607 if (lineEmulation) {
4608 if (lineEmulation == QPaintEngine::PrimitiveTransform
4609 && d->state->matrix.type() == QTransform::TxTranslate) {
4610 for (int i = 0; i < lineCount; ++i) {
4611 QLineF line = lines[i];
4612 line.translate(d->state->matrix.dx(), d->state->matrix.dy());
4613 d->engine->drawLines(&line, 1);
4616 QPainterPath linePath;
4617 for (int i = 0; i < lineCount; ++i) {
4618 linePath.moveTo(lines[i].p1());
4619 linePath.lineTo(lines[i].p2());
4621 d->draw_helper(linePath, QPainterPrivate::StrokeDraw);
4625 d->engine->drawLines(lines, lineCount);
4631 Draws the first \a lineCount lines in the array \a pointPairs
4632 using the current pen. The lines are specified as pairs of points
4633 so the number of entries in \a pointPairs must be at least \a
4636 void QPainter::drawLines(const QPointF *pointPairs, int lineCount)
4638 Q_ASSERT(sizeof(QLineF) == 2*sizeof(QPointF));
4640 drawLines((QLineF*)pointPairs, lineCount);
4646 Draws the first \a lineCount lines in the array \a pointPairs
4647 using the current pen.
4649 void QPainter::drawLines(const QPoint *pointPairs, int lineCount)
4651 Q_ASSERT(sizeof(QLine) == 2*sizeof(QPoint));
4653 drawLines((QLine*)pointPairs, lineCount);
4658 \fn void QPainter::drawLines(const QVector<QPointF> &pointPairs)
4661 Draws a line for each pair of points in the vector \a pointPairs
4662 using the current pen. If there is an odd number of points in the
4663 array, the last point will be ignored.
4667 \fn void QPainter::drawLines(const QVector<QPoint> &pointPairs)
4670 Draws a line for each pair of points in the vector \a pointPairs
4671 using the current pen.
4675 \fn void QPainter::drawLines(const QVector<QLineF> &lines)
4678 Draws the set of lines defined by the list \a lines using the
4679 current pen and brush.
4683 \fn void QPainter::drawLines(const QVector<QLine> &lines)
4686 Draws the set of lines defined by the list \a lines using the
4687 current pen and brush.
4691 Draws the polyline defined by the first \a pointCount points in \a
4692 points using the current pen.
4694 Note that unlike the drawPolygon() function the last point is \e
4695 not connected to the first, neither is the polyline filled.
4700 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 13
4703 \sa drawLines(), drawPolygon(), {Coordinate System}
4705 void QPainter::drawPolyline(const QPointF *points, int pointCount)
4707 #ifdef QT_DEBUG_DRAW
4708 if (qt_show_painter_debug_output)
4709 printf("QPainter::drawPolyline(), count=%d\n", pointCount);
4713 if (!d->engine || pointCount < 2)
4717 d->extended->drawPolygon(points, pointCount, QPaintEngine::PolylineMode);
4721 d->updateState(d->state);
4723 uint lineEmulation = line_emulation(d->state->emulationSpecifier);
4725 if (lineEmulation) {
4727 // if (lineEmulation == QPaintEngine::PrimitiveTransform
4728 // && d->state->matrix.type() == QTransform::TxTranslate) {
4730 QPainterPath polylinePath(points[0]);
4731 for (int i=1; i<pointCount; ++i)
4732 polylinePath.lineTo(points[i]);
4733 d->draw_helper(polylinePath, QPainterPrivate::StrokeDraw);
4736 d->engine->drawPolygon(points, pointCount, QPaintEngine::PolylineMode);
4743 Draws the polyline defined by the first \a pointCount points in \a
4744 points using the current pen.
4746 void QPainter::drawPolyline(const QPoint *points, int pointCount)
4748 #ifdef QT_DEBUG_DRAW
4749 if (qt_show_painter_debug_output)
4750 printf("QPainter::drawPolyline(), count=%d\n", pointCount);
4754 if (!d->engine || pointCount < 2)
4758 d->extended->drawPolygon(points, pointCount, QPaintEngine::PolylineMode);
4762 d->updateState(d->state);
4764 uint lineEmulation = line_emulation(d->state->emulationSpecifier);
4766 if (lineEmulation) {
4768 // if (lineEmulation == QPaintEngine::PrimitiveTransform
4769 // && d->state->matrix.type() == QTransform::TxTranslate) {
4771 QPainterPath polylinePath(points[0]);
4772 for (int i=1; i<pointCount; ++i)
4773 polylinePath.lineTo(points[i]);
4774 d->draw_helper(polylinePath, QPainterPrivate::StrokeDraw);
4777 d->engine->drawPolygon(points, pointCount, QPaintEngine::PolylineMode);
4782 \fn void QPainter::drawPolyline(const QPolygonF &points)
4786 Draws the polyline defined by the given \a points using the
4791 \fn void QPainter::drawPolyline(const QPolygon &points)
4795 Draws the polyline defined by the given \a points using the
4800 Draws the polygon defined by the first \a pointCount points in the
4801 array \a points using the current pen and brush.
4805 \li \inlineimage qpainter-polygon.png
4807 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 14
4810 The first point is implicitly connected to the last point, and the
4811 polygon is filled with the current brush().
4813 If \a fillRule is Qt::WindingFill, the polygon is filled using the
4814 winding fill algorithm. If \a fillRule is Qt::OddEvenFill, the
4815 polygon is filled using the odd-even fill algorithm. See
4816 \l{Qt::FillRule} for a more detailed description of these fill
4819 \sa drawConvexPolygon(), drawPolyline(), {Coordinate System}
4821 void QPainter::drawPolygon(const QPointF *points, int pointCount, Qt::FillRule fillRule)
4823 #ifdef QT_DEBUG_DRAW
4824 if (qt_show_painter_debug_output)
4825 printf("QPainter::drawPolygon(), count=%d\n", pointCount);
4830 if (!d->engine || pointCount < 2)
4834 d->extended->drawPolygon(points, pointCount, QPaintEngine::PolygonDrawMode(fillRule));
4838 d->updateState(d->state);
4840 uint emulationSpecifier = d->state->emulationSpecifier;
4842 if (emulationSpecifier) {
4843 QPainterPath polygonPath(points[0]);
4844 for (int i=1; i<pointCount; ++i)
4845 polygonPath.lineTo(points[i]);
4846 polygonPath.closeSubpath();
4847 polygonPath.setFillRule(fillRule);
4848 d->draw_helper(polygonPath);
4852 d->engine->drawPolygon(points, pointCount, QPaintEngine::PolygonDrawMode(fillRule));
4857 Draws the polygon defined by the first \a pointCount points in the
4860 void QPainter::drawPolygon(const QPoint *points, int pointCount, Qt::FillRule fillRule)
4862 #ifdef QT_DEBUG_DRAW
4863 if (qt_show_painter_debug_output)
4864 printf("QPainter::drawPolygon(), count=%d\n", pointCount);
4869 if (!d->engine || pointCount < 2)
4873 d->extended->drawPolygon(points, pointCount, QPaintEngine::PolygonDrawMode(fillRule));
4877 d->updateState(d->state);
4879 uint emulationSpecifier = d->state->emulationSpecifier;
4881 if (emulationSpecifier) {
4882 QPainterPath polygonPath(points[0]);
4883 for (int i=1; i<pointCount; ++i)
4884 polygonPath.lineTo(points[i]);
4885 polygonPath.closeSubpath();
4886 polygonPath.setFillRule(fillRule);
4887 d->draw_helper(polygonPath);
4891 d->engine->drawPolygon(points, pointCount, QPaintEngine::PolygonDrawMode(fillRule));
4894 /*! \fn void QPainter::drawPolygon(const QPolygonF &points, Qt::FillRule fillRule)
4898 Draws the polygon defined by the given \a points using the fill
4902 /*! \fn void QPainter::drawPolygon(const QPolygon &points, Qt::FillRule fillRule)
4906 Draws the polygon defined by the given \a points using the fill
4911 \fn void QPainter::drawConvexPolygon(const QPointF *points, int pointCount)
4913 Draws the convex polygon defined by the first \a pointCount points
4914 in the array \a points using the current pen.
4918 \li \inlineimage qpainter-polygon.png
4920 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 15
4923 The first point is implicitly connected to the last point, and the
4924 polygon is filled with the current brush(). If the supplied
4925 polygon is not convex, i.e. it contains at least one angle larger
4926 than 180 degrees, the results are undefined.
4928 On some platforms (e.g. X11), the drawConvexPolygon() function can
4929 be faster than the drawPolygon() function.
4931 \sa drawPolygon(), drawPolyline(), {Coordinate System}
4935 \fn void QPainter::drawConvexPolygon(const QPoint *points, int pointCount)
4938 Draws the convex polygon defined by the first \a pointCount points
4939 in the array \a points using the current pen.
4943 \fn void QPainter::drawConvexPolygon(const QPolygonF &polygon)
4947 Draws the convex polygon defined by \a polygon using the current
4952 \fn void QPainter::drawConvexPolygon(const QPolygon &polygon)
4955 Draws the convex polygon defined by \a polygon using the current
4959 void QPainter::drawConvexPolygon(const QPoint *points, int pointCount)
4961 #ifdef QT_DEBUG_DRAW
4962 if (qt_show_painter_debug_output)
4963 printf("QPainter::drawConvexPolygon(), count=%d\n", pointCount);
4968 if (!d->engine || pointCount < 2)
4972 d->extended->drawPolygon(points, pointCount, QPaintEngine::ConvexMode);
4976 d->updateState(d->state);
4978 uint emulationSpecifier = d->state->emulationSpecifier;
4980 if (emulationSpecifier) {
4981 QPainterPath polygonPath(points[0]);
4982 for (int i=1; i<pointCount; ++i)
4983 polygonPath.lineTo(points[i]);
4984 polygonPath.closeSubpath();
4985 polygonPath.setFillRule(Qt::WindingFill);
4986 d->draw_helper(polygonPath);
4990 d->engine->drawPolygon(points, pointCount, QPaintEngine::ConvexMode);
4993 void QPainter::drawConvexPolygon(const QPointF *points, int pointCount)
4995 #ifdef QT_DEBUG_DRAW
4996 if (qt_show_painter_debug_output)
4997 printf("QPainter::drawConvexPolygon(), count=%d\n", pointCount);
5002 if (!d->engine || pointCount < 2)
5006 d->extended->drawPolygon(points, pointCount, QPaintEngine::ConvexMode);
5010 d->updateState(d->state);
5012 uint emulationSpecifier = d->state->emulationSpecifier;
5014 if (emulationSpecifier) {
5015 QPainterPath polygonPath(points[0]);
5016 for (int i=1; i<pointCount; ++i)
5017 polygonPath.lineTo(points[i]);
5018 polygonPath.closeSubpath();
5019 polygonPath.setFillRule(Qt::WindingFill);
5020 d->draw_helper(polygonPath);
5024 d->engine->drawPolygon(points, pointCount, QPaintEngine::ConvexMode);
5027 static inline QPointF roundInDeviceCoordinates(const QPointF &p, const QTransform &m)
5029 return m.inverted().map(QPointF(m.map(p).toPoint()));
5033 \fn void QPainter::drawPixmap(const QRectF &target, const QPixmap &pixmap, const QRectF &source)
5035 Draws the rectangular portion \a source of the given \a pixmap
5036 into the given \a target in the paint device.
5038 \note The pixmap is scaled to fit the rectangle, if both the pixmap and rectangle size disagree.
5043 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 16
5046 If \a pixmap is a QBitmap it is drawn with the bits that are "set"
5047 using the pens color. If backgroundMode is Qt::OpaqueMode, the
5048 "unset" bits are drawn using the color of the background brush; if
5049 backgroundMode is Qt::TransparentMode, the "unset" bits are
5050 transparent. Drawing bitmaps with gradient or texture colors is
5055 void QPainter::drawPixmap(const QPointF &p, const QPixmap &pm)
5057 #if defined QT_DEBUG_DRAW
5058 if (qt_show_painter_debug_output)
5059 printf("QPainter::drawPixmap(), p=[%.2f,%.2f], pix=[%d,%d]\n",
5061 pm.width(), pm.height());
5066 if (!d->engine || pm.isNull())
5070 qt_painter_thread_test(d->device->devType(), "drawPixmap()", true);
5074 d->extended->drawPixmap(p, pm);
5082 int h = pm.height();
5087 // Emulate opaque background for bitmaps
5088 if (d->state->bgMode == Qt::OpaqueMode && pm.isQBitmap()) {
5089 fillRect(QRectF(x, y, w, h), d->state->bgBrush.color());
5092 d->updateState(d->state);
5094 if ((d->state->matrix.type() > QTransform::TxTranslate
5095 && !d->engine->hasFeature(QPaintEngine::PixmapTransform))
5096 || (!d->state->matrix.isAffine() && !d->engine->hasFeature(QPaintEngine::PerspectiveTransform))
5097 || (d->state->opacity != 1.0 && !d->engine->hasFeature(QPaintEngine::ConstantOpacity)))
5100 // If there is no rotation involved we have to make sure we use the
5101 // antialiased and not the aliased coordinate system by rounding the coordinates.
5102 if (d->state->matrix.type() <= QTransform::TxScale) {
5103 const QPointF p = roundInDeviceCoordinates(QPointF(x, y), d->state->matrix);
5108 setBackgroundMode(Qt::TransparentMode);
5109 setRenderHint(Antialiasing, renderHints() & SmoothPixmapTransform);
5110 QBrush brush(d->state->pen.color(), pm);
5113 setBrushOrigin(QPointF(0, 0));
5115 drawRect(pm.rect());
5118 if (!d->engine->hasFeature(QPaintEngine::PixmapTransform)) {
5119 x += d->state->matrix.dx();
5120 y += d->state->matrix.dy();
5122 d->engine->drawPixmap(QRectF(x, y, w, h), pm, QRectF(0, 0, w, h));
5126 void QPainter::drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr)
5128 #if defined QT_DEBUG_DRAW
5129 if (qt_show_painter_debug_output)
5130 printf("QPainter::drawPixmap(), target=[%.2f,%.2f,%.2f,%.2f], pix=[%d,%d], source=[%.2f,%.2f,%.2f,%.2f]\n",
5131 r.x(), r.y(), r.width(), r.height(),
5132 pm.width(), pm.height(),
5133 sr.x(), sr.y(), sr.width(), sr.height());
5137 if (!d->engine || pm.isNull())
5140 qt_painter_thread_test(d->device->devType(), "drawPixmap()", true);
5145 qreal w = r.width();
5146 qreal h = r.height();
5149 qreal sw = sr.width();
5150 qreal sh = sr.height();
5152 // Sanity-check clipping
5154 sw = pm.width() - sx;
5157 sh = pm.height() - sy;
5165 qreal w_ratio = sx * w/sw;
5173 qreal h_ratio = sy * h/sh;
5180 if (sw + sx > pm.width()) {
5181 qreal delta = sw - (pm.width() - sx);
5182 qreal w_ratio = delta * w/sw;
5187 if (sh + sy > pm.height()) {
5188 qreal delta = sh - (pm.height() - sy);
5189 qreal h_ratio = delta * h/sh;
5194 if (w == 0 || h == 0 || sw <= 0 || sh <= 0)
5198 d->extended->drawPixmap(QRectF(x, y, w, h), pm, QRectF(sx, sy, sw, sh));
5202 // Emulate opaque background for bitmaps
5203 if (d->state->bgMode == Qt::OpaqueMode && pm.isQBitmap())
5204 fillRect(QRectF(x, y, w, h), d->state->bgBrush.color());
5206 d->updateState(d->state);
5208 if ((d->state->matrix.type() > QTransform::TxTranslate
5209 && !d->engine->hasFeature(QPaintEngine::PixmapTransform))
5210 || (!d->state->matrix.isAffine() && !d->engine->hasFeature(QPaintEngine::PerspectiveTransform))
5211 || (d->state->opacity != 1.0 && !d->engine->hasFeature(QPaintEngine::ConstantOpacity))
5212 || ((sw != w || sh != h) && !d->engine->hasFeature(QPaintEngine::PixmapTransform)))
5215 // If there is no rotation involved we have to make sure we use the
5216 // antialiased and not the aliased coordinate system by rounding the coordinates.
5217 if (d->state->matrix.type() <= QTransform::TxScale) {
5218 const QPointF p = roundInDeviceCoordinates(QPointF(x, y), d->state->matrix);
5223 if (d->state->matrix.type() <= QTransform::TxTranslate && sw == w && sh == h) {
5231 scale(w / sw, h / sh);
5232 setBackgroundMode(Qt::TransparentMode);
5233 setRenderHint(Antialiasing, renderHints() & SmoothPixmapTransform);
5236 if (sw == pm.width() && sh == pm.height())
5237 brush = QBrush(d->state->pen.color(), pm);
5239 brush = QBrush(d->state->pen.color(), pm.copy(sx, sy, sw, sh));
5244 drawRect(QRectF(0, 0, sw, sh));
5247 if (!d->engine->hasFeature(QPaintEngine::PixmapTransform)) {
5248 x += d->state->matrix.dx();
5249 y += d->state->matrix.dy();
5251 d->engine->drawPixmap(QRectF(x, y, w, h), pm, QRectF(sx, sy, sw, sh));
5257 \fn void QPainter::drawPixmap(const QRect &target, const QPixmap &pixmap,
5258 const QRect &source)
5261 Draws the rectangular portion \a source of the given \a pixmap
5262 into the given \a target in the paint device.
5264 \note The pixmap is scaled to fit the rectangle, if both the pixmap and rectangle size disagree.
5268 \fn void QPainter::drawPixmap(const QPointF &point, const QPixmap &pixmap,
5269 const QRectF &source)
5272 Draws the rectangular portion \a source of the given \a pixmap
5273 with its origin at the given \a point.
5277 \fn void QPainter::drawPixmap(const QPoint &point, const QPixmap &pixmap,
5278 const QRect &source)
5282 Draws the rectangular portion \a source of the given \a pixmap
5283 with its origin at the given \a point.
5287 \fn void QPainter::drawPixmap(const QPointF &point, const QPixmap &pixmap)
5290 Draws the given \a pixmap with its origin at the given \a point.
5294 \fn void QPainter::drawPixmap(const QPoint &point, const QPixmap &pixmap)
5297 Draws the given \a pixmap with its origin at the given \a point.
5301 \fn void QPainter::drawPixmap(int x, int y, const QPixmap &pixmap)
5305 Draws the given \a pixmap at position (\a{x}, \a{y}).
5309 \fn void QPainter::drawPixmap(const QRect &rectangle, const QPixmap &pixmap)
5312 Draws the given \a pixmap into the given \a rectangle.
5314 \note The pixmap is scaled to fit the rectangle, if both the pixmap and rectangle size disagree.
5318 \fn void QPainter::drawPixmap(int x, int y, int width, int height,
5319 const QPixmap &pixmap)
5323 Draws the \a pixmap into the rectangle at position (\a{x}, \a{y})
5324 with the given \a width and \a height.
5328 \fn void QPainter::drawPixmap(int x, int y, int w, int h, const QPixmap &pixmap,
5329 int sx, int sy, int sw, int sh)
5333 Draws the rectangular portion with the origin (\a{sx}, \a{sy}),
5334 width \a sw and height \a sh, of the given \a pixmap , at the
5335 point (\a{x}, \a{y}), with a width of \a w and a height of \a h.
5336 If sw or sh are equal to zero the width/height of the pixmap
5337 is used and adjusted by the offset sx/sy;
5341 \fn void QPainter::drawPixmap(int x, int y, const QPixmap &pixmap,
5342 int sx, int sy, int sw, int sh)
5346 Draws a pixmap at (\a{x}, \a{y}) by copying a part of the given \a
5347 pixmap into the paint device.
5349 (\a{x}, \a{y}) specifies the top-left point in the paint device that is
5350 to be drawn onto. (\a{sx}, \a{sy}) specifies the top-left point in \a
5351 pixmap that is to be drawn. The default is (0, 0).
5353 (\a{sw}, \a{sh}) specifies the size of the pixmap that is to be drawn.
5354 The default, (0, 0) (and negative) means all the way to the
5355 bottom-right of the pixmap.
5358 void QPainter::drawImage(const QPointF &p, const QImage &image)
5362 if (!d->engine || image.isNull())
5366 d->extended->drawImage(p, image);
5373 int w = image.width();
5374 int h = image.height();
5376 d->updateState(d->state);
5378 if (((d->state->matrix.type() > QTransform::TxTranslate)
5379 && !d->engine->hasFeature(QPaintEngine::PixmapTransform))
5380 || (!d->state->matrix.isAffine() && !d->engine->hasFeature(QPaintEngine::PerspectiveTransform))
5381 || (d->state->opacity != 1.0 && !d->engine->hasFeature(QPaintEngine::ConstantOpacity)))
5384 // If there is no rotation involved we have to make sure we use the
5385 // antialiased and not the aliased coordinate system by rounding the coordinates.
5386 if (d->state->matrix.type() <= QTransform::TxScale) {
5387 const QPointF p = roundInDeviceCoordinates(QPointF(x, y), d->state->matrix);
5392 setBackgroundMode(Qt::TransparentMode);
5393 setRenderHint(Antialiasing, renderHints() & SmoothPixmapTransform);
5394 QBrush brush(image);
5397 setBrushOrigin(QPointF(0, 0));
5399 drawRect(image.rect());
5404 if (d->state->matrix.type() == QTransform::TxTranslate
5405 && !d->engine->hasFeature(QPaintEngine::PixmapTransform)) {
5406 x += d->state->matrix.dx();
5407 y += d->state->matrix.dy();
5410 d->engine->drawImage(QRectF(x, y, w, h), image, QRectF(0, 0, w, h), Qt::AutoColor);
5413 void QPainter::drawImage(const QRectF &targetRect, const QImage &image, const QRectF &sourceRect,
5414 Qt::ImageConversionFlags flags)
5418 if (!d->engine || image.isNull())
5421 qreal x = targetRect.x();
5422 qreal y = targetRect.y();
5423 qreal w = targetRect.width();
5424 qreal h = targetRect.height();
5425 qreal sx = sourceRect.x();
5426 qreal sy = sourceRect.y();
5427 qreal sw = sourceRect.width();
5428 qreal sh = sourceRect.height();
5430 // Sanity-check clipping
5432 sw = image.width() - sx;
5435 sh = image.height() - sy;
5443 qreal w_ratio = sx * w/sw;
5451 qreal h_ratio = sy * h/sh;
5458 if (sw + sx > image.width()) {
5459 qreal delta = sw - (image.width() - sx);
5460 qreal w_ratio = delta * w/sw;
5465 if (sh + sy > image.height()) {
5466 qreal delta = sh - (image.height() - sy);
5467 qreal h_ratio = delta * h/sh;
5472 if (w == 0 || h == 0 || sw <= 0 || sh <= 0)
5476 d->extended->drawImage(QRectF(x, y, w, h), image, QRectF(sx, sy, sw, sh), flags);
5480 d->updateState(d->state);
5482 if (((d->state->matrix.type() > QTransform::TxTranslate || (sw != w || sh != h))
5483 && !d->engine->hasFeature(QPaintEngine::PixmapTransform))
5484 || (!d->state->matrix.isAffine() && !d->engine->hasFeature(QPaintEngine::PerspectiveTransform))
5485 || (d->state->opacity != 1.0 && !d->engine->hasFeature(QPaintEngine::ConstantOpacity)))
5488 // If there is no rotation involved we have to make sure we use the
5489 // antialiased and not the aliased coordinate system by rounding the coordinates.
5490 if (d->state->matrix.type() <= QTransform::TxScale) {
5491 const QPointF p = roundInDeviceCoordinates(QPointF(x, y), d->state->matrix);
5496 if (d->state->matrix.type() <= QTransform::TxTranslate && sw == w && sh == h) {
5503 scale(w / sw, h / sh);
5504 setBackgroundMode(Qt::TransparentMode);
5505 setRenderHint(Antialiasing, renderHints() & SmoothPixmapTransform);
5506 QBrush brush(image);
5509 setBrushOrigin(QPointF(-sx, -sy));
5511 drawRect(QRectF(0, 0, sw, sh));
5516 if (d->state->matrix.type() == QTransform::TxTranslate
5517 && !d->engine->hasFeature(QPaintEngine::PixmapTransform)) {
5518 x += d->state->matrix.dx();
5519 y += d->state->matrix.dy();
5522 d->engine->drawImage(QRectF(x, y, w, h), image, QRectF(sx, sy, sw, sh), flags);
5526 \fn void QPainter::drawGlyphRun(const QPointF &position, const QGlyphRun &glyphs)
5528 Draws the glyphs represented by \a glyphs at \a position. The \a position gives the
5529 edge of the baseline for the string of glyphs. The glyphs will be retrieved from the font
5530 selected on \a glyphs and at offsets given by the positions in \a glyphs.
5534 \sa QGlyphRun::setRawFont(), QGlyphRun::setPositions(), QGlyphRun::setGlyphIndexes()
5536 #if !defined(QT_NO_RAWFONT)
5537 void QPainter::drawGlyphRun(const QPointF &position, const QGlyphRun &glyphRun)
5541 QRawFont font = glyphRun.rawFont();
5542 if (!font.isValid())
5545 QGlyphRunPrivate *glyphRun_d = QGlyphRunPrivate::get(glyphRun);
5547 const quint32 *glyphIndexes = glyphRun_d->glyphIndexData;
5548 const QPointF *glyphPositions = glyphRun_d->glyphPositionData;
5550 int count = qMin(glyphRun_d->glyphIndexDataSize, glyphRun_d->glyphPositionDataSize);
5551 QVarLengthArray<QFixedPoint, 128> fixedPointPositions(count);
5553 QRawFontPrivate *fontD = QRawFontPrivate::get(font);
5554 bool supportsTransformations = d->extended
5555 ? d->extended->supportsTransformations(fontD->fontEngine, d->state->matrix)
5556 : d->engine->type() == QPaintEngine::CoreGraphics || d->state->matrix.isAffine();
5558 for (int i=0; i<count; ++i) {
5559 QPointF processedPosition = position + glyphPositions[i];
5560 if (!supportsTransformations)
5561 processedPosition = d->state->transform().map(processedPosition);
5562 fixedPointPositions[i] = QFixedPoint::fromPointF(processedPosition);
5565 d->drawGlyphs(glyphIndexes, fixedPointPositions.data(), count, font, glyphRun.overline(),
5566 glyphRun.underline(), glyphRun.strikeOut());
5569 void QPainterPrivate::drawGlyphs(const quint32 *glyphArray, QFixedPoint *positions,
5571 const QRawFont &font, bool overline, bool underline,
5578 QRawFontPrivate *fontD = QRawFontPrivate::get(font);
5579 QFontEngine *fontEngine = fontD->fontEngine;
5584 for (int i=0; i<glyphCount; ++i) {
5585 glyph_metrics_t gm = fontEngine->boundingBox(glyphArray[i]);
5586 if (i == 0 || leftMost > positions[i].x)
5587 leftMost = positions[i].x;
5589 // We don't support glyphs that do not share a common baseline. If this turns out to
5590 // be a relevant use case, then we need to find clusters of glyphs that share a baseline
5591 // and do a drawTextItemDecorations call per cluster.
5592 if (i == 0 || baseLine < positions[i].y)
5593 baseLine = positions[i].y;
5595 // We use the advance rather than the actual bounds to match the algorithm in drawText()
5596 if (i == 0 || rightMost < positions[i].x + gm.xoff)
5597 rightMost = positions[i].x + gm.xoff;
5600 QFixed width = rightMost - leftMost;
5602 if (extended != 0 && state->matrix.isAffine()) {
5603 QStaticTextItem staticTextItem;
5604 staticTextItem.color = state->pen.color();
5605 staticTextItem.font = state->font;
5606 staticTextItem.setFontEngine(fontEngine);
5607 staticTextItem.numGlyphs = glyphCount;
5608 staticTextItem.glyphs = reinterpret_cast<glyph_t *>(const_cast<glyph_t *>(glyphArray));
5609 staticTextItem.glyphPositions = positions;
5611 extended->drawStaticTextItem(&staticTextItem);
5613 QTextItemInt textItem;
5614 textItem.fontEngine = fontEngine;
5616 QVarLengthArray<QFixed, 128> advances(glyphCount);
5617 QVarLengthArray<QGlyphJustification, 128> glyphJustifications(glyphCount);
5618 QVarLengthArray<HB_GlyphAttributes, 128> glyphAttributes(glyphCount);
5619 qMemSet(glyphAttributes.data(), 0, glyphAttributes.size() * sizeof(HB_GlyphAttributes));
5620 qMemSet(advances.data(), 0, advances.size() * sizeof(QFixed));
5621 qMemSet(glyphJustifications.data(), 0, glyphJustifications.size() * sizeof(QGlyphJustification));
5623 textItem.glyphs.numGlyphs = glyphCount;
5624 textItem.glyphs.glyphs = reinterpret_cast<HB_Glyph *>(const_cast<quint32 *>(glyphArray));
5625 textItem.glyphs.offsets = positions;
5626 textItem.glyphs.advances_x = advances.data();
5627 textItem.glyphs.advances_y = advances.data();
5628 textItem.glyphs.justifications = glyphJustifications.data();
5629 textItem.glyphs.attributes = glyphAttributes.data();
5631 engine->drawTextItem(QPointF(0, 0), textItem);
5634 QTextItemInt::RenderFlags flags;
5636 flags |= QTextItemInt::Underline;
5638 flags |= QTextItemInt::Overline;
5640 flags |= QTextItemInt::StrikeOut;
5642 drawTextItemDecoration(q, QPointF(leftMost.toReal(), baseLine.toReal()),
5646 ? QTextCharFormat::SingleUnderline
5647 : QTextCharFormat::NoUnderline),
5648 flags, width.toReal(), QTextCharFormat());
5650 #endif // QT_NO_RAWFONT
5654 \fn void QPainter::drawStaticText(const QPoint &topLeftPosition, const QStaticText &staticText)
5658 Draws the \a staticText at the \a topLeftPosition.
5660 \note The y-position is used as the top of the font.
5665 \fn void QPainter::drawStaticText(int left, int top, const QStaticText &staticText)
5669 Draws the \a staticText at coordinates \a left and \a top.
5671 \note The y-position is used as the top of the font.
5675 \fn void QPainter::drawText(const QPointF &position, const QString &text)
5677 Draws the given \a text with the currently defined text direction,
5678 beginning at the given \a position.
5680 This function does not handle the newline character (\n), as it cannot
5681 break text into multiple lines, and it cannot display the newline character.
5682 Use the QPainter::drawText() overload that takes a rectangle instead
5683 if you want to draw multiple lines of text with the newline character, or
5684 if you want the text to be wrapped.
5686 By default, QPainter draws text anti-aliased.
5688 \note The y-position is used as the baseline of the font.
5691 void QPainter::drawText(const QPointF &p, const QString &str)
5693 drawText(p, str, 0, 0);
5699 Draws the given \a staticText at the given \a topLeftPosition.
5701 The text will be drawn using the font and the transformation set on the painter. If the
5702 font and/or transformation set on the painter are different from the ones used to initialize
5703 the layout of the QStaticText, then the layout will have to be recalculated. Use
5704 QStaticText::prepare() to initialize \a staticText with the font and transformation with which
5705 it will later be drawn.
5707 If \a topLeftPosition is not the same as when \a staticText was initialized, or when it was
5708 last drawn, then there will be a slight overhead when translating the text to its new position.
5710 \note If the painter's transformation is not affine, then \a staticText will be drawn using
5711 regular calls to drawText(), losing any potential for performance improvement.
5713 \note The y-position is used as the top of the font.
5717 void QPainter::drawStaticText(const QPointF &topLeftPosition, const QStaticText &staticText)
5720 if (!d->engine || staticText.text().isEmpty() || pen().style() == Qt::NoPen)
5723 QStaticTextPrivate *staticText_d =
5724 const_cast<QStaticTextPrivate *>(QStaticTextPrivate::get(&staticText));
5726 if (font() != staticText_d->font) {
5727 staticText_d->font = font();
5728 staticText_d->needsRelayout = true;
5731 // If we don't have an extended paint engine, or if the painter is projected,
5732 // we go through standard code path
5733 if (d->extended == 0 || !d->state->matrix.isAffine()) {
5734 staticText_d->paintText(topLeftPosition, this);
5738 bool supportsTransformations = d->extended->supportsTransformations(staticText_d->font.d->engineForScript(QUnicodeTables::Common),
5740 if (supportsTransformations && !staticText_d->untransformedCoordinates) {
5741 staticText_d->untransformedCoordinates = true;
5742 staticText_d->needsRelayout = true;
5743 } else if (!supportsTransformations && staticText_d->untransformedCoordinates) {
5744 staticText_d->untransformedCoordinates = false;
5745 staticText_d->needsRelayout = true;
5748 // Don't recalculate entire layout because of translation, rather add the dx and dy
5749 // into the position to move each text item the correct distance.
5750 QPointF transformedPosition = topLeftPosition;
5751 if (!staticText_d->untransformedCoordinates)
5752 transformedPosition = transformedPosition * d->state->matrix;
5753 QTransform oldMatrix;
5755 // The translation has been applied to transformedPosition. Remove translation
5756 // component from matrix.
5757 if (d->state->matrix.isTranslating() && !staticText_d->untransformedCoordinates) {
5758 qreal m11 = d->state->matrix.m11();
5759 qreal m12 = d->state->matrix.m12();
5760 qreal m13 = d->state->matrix.m13();
5761 qreal m21 = d->state->matrix.m21();
5762 qreal m22 = d->state->matrix.m22();
5763 qreal m23 = d->state->matrix.m23();
5764 qreal m33 = d->state->matrix.m33();
5766 oldMatrix = d->state->matrix;
5767 d->state->matrix.setMatrix(m11, m12, m13,
5772 // If the transform is not identical to the text transform,
5773 // we have to relayout the text (for other transformations than plain translation)
5774 bool staticTextNeedsReinit = staticText_d->needsRelayout;
5775 if (!staticText_d->untransformedCoordinates && staticText_d->matrix != d->state->matrix) {
5776 staticText_d->matrix = d->state->matrix;
5777 staticTextNeedsReinit = true;
5780 // Recreate the layout of the static text because the matrix or font has changed
5781 if (staticTextNeedsReinit)
5782 staticText_d->init();
5784 if (transformedPosition != staticText_d->position) { // Translate to actual position
5785 QFixed fx = QFixed::fromReal(transformedPosition.x());
5786 QFixed fy = QFixed::fromReal(transformedPosition.y());
5787 QFixed oldX = QFixed::fromReal(staticText_d->position.x());
5788 QFixed oldY = QFixed::fromReal(staticText_d->position.y());
5789 for (int item=0; item<staticText_d->itemCount;++item) {
5790 QStaticTextItem *textItem = staticText_d->items + item;
5791 for (int i=0; i<textItem->numGlyphs; ++i) {
5792 textItem->glyphPositions[i].x += fx - oldX;
5793 textItem->glyphPositions[i].y += fy - oldY;
5795 textItem->userDataNeedsUpdate = true;
5798 staticText_d->position = transformedPosition;
5801 QPen oldPen = d->state->pen;
5802 QColor currentColor = oldPen.color();
5803 for (int i=0; i<staticText_d->itemCount; ++i) {
5804 QStaticTextItem *item = staticText_d->items + i;
5805 if (item->color.isValid() && currentColor != item->color) {
5806 setPen(item->color);
5807 currentColor = item->color;
5809 d->extended->drawStaticTextItem(item);
5811 qt_draw_decoration_for_glyphs(this, item->glyphs, item->glyphPositions,
5812 item->numGlyphs, item->fontEngine(), staticText_d->font,
5815 if (currentColor != oldPen.color())
5818 if (!staticText_d->untransformedCoordinates && oldMatrix.isTranslating())
5819 d->state->matrix = oldMatrix;
5825 void QPainter::drawText(const QPointF &p, const QString &str, int tf, int justificationPadding)
5827 #ifdef QT_DEBUG_DRAW
5828 if (qt_show_painter_debug_output)
5829 printf("QPainter::drawText(), pos=[%.2f,%.2f], str='%s'\n", p.x(), p.y(), str.toLatin1().constData());
5834 if (!d->engine || str.isEmpty() || pen().style() == Qt::NoPen)
5837 if (tf & Qt::TextBypassShaping) {
5838 // Skip harfbuzz complex shaping, shape using glyph advances only
5839 int len = str.length();
5840 int numGlyphs = len;
5841 QVarLengthGlyphLayoutArray glyphs(len);
5842 QFontEngine *fontEngine = d->state->font.d->engineForScript(QUnicodeTables::Common);
5843 if (!fontEngine->stringToCMap(str.data(), len, &glyphs, &numGlyphs, 0)) {
5844 glyphs.resize(numGlyphs);
5845 if (!fontEngine->stringToCMap(str.data(), len, &glyphs, &numGlyphs, 0))
5846 Q_ASSERT_X(false, Q_FUNC_INFO, "stringToCMap shouldn't fail twice");
5849 QTextItemInt gf(glyphs, &d->state->font, str.data(), len, fontEngine);
5850 drawTextItem(p, gf);
5854 QStackTextEngine engine(str, d->state->font);
5855 engine.option.setTextDirection(d->state->layoutDirection);
5856 if (tf & (Qt::TextForceLeftToRight|Qt::TextForceRightToLeft)) {
5857 engine.ignoreBidi = true;
5858 engine.option.setTextDirection((tf & Qt::TextForceLeftToRight) ? Qt::LeftToRight : Qt::RightToLeft);
5862 line.length = str.length();
5863 engine.shapeLine(line);
5865 int nItems = engine.layoutData->items.size();
5866 QVarLengthArray<int> visualOrder(nItems);
5867 QVarLengthArray<uchar> levels(nItems);
5868 for (int i = 0; i < nItems; ++i)
5869 levels[i] = engine.layoutData->items[i].analysis.bidiLevel;
5870 QTextEngine::bidiReorder(nItems, levels.data(), visualOrder.data());
5872 if (justificationPadding > 0) {
5873 engine.option.setAlignment(Qt::AlignJustify);
5874 engine.forceJustification = true;
5875 // this works because justify() is only interested in the difference between width and textWidth
5876 line.width = justificationPadding;
5877 engine.justify(line);
5879 QFixed x = QFixed::fromReal(p.x());
5881 for (int i = 0; i < nItems; ++i) {
5882 int item = visualOrder[i];
5883 const QScriptItem &si = engine.layoutData->items.at(item);
5884 if (si.analysis.flags >= QScriptAnalysis::TabOrObject) {
5888 QFont f = engine.font(si);
5889 QTextItemInt gf(si, &f);
5890 gf.glyphs = engine.shapedGlyphs(&si);
5891 gf.chars = engine.layoutData->string.unicode() + si.position;
5892 gf.num_chars = engine.length(item);
5893 if (engine.forceJustification) {
5894 for (int j=0; j<gf.glyphs.numGlyphs; ++j)
5895 gf.width += gf.glyphs.effectiveAdvance(j);
5897 gf.width = si.width;
5899 gf.logClusters = engine.logClusters(&si);
5901 drawTextItem(QPointF(x.toReal(), p.y()), gf);
5907 void QPainter::drawText(const QRect &r, int flags, const QString &str, QRect *br)
5909 #ifdef QT_DEBUG_DRAW
5910 if (qt_show_painter_debug_output)
5911 printf("QPainter::drawText(), r=[%d,%d,%d,%d], flags=%d, str='%s'\n",
5912 r.x(), r.y(), r.width(), r.height(), flags, str.toLatin1().constData());
5917 if (!d->engine || str.length() == 0 || pen().style() == Qt::NoPen)
5921 d->updateState(d->state);
5924 qt_format_text(d->state->font, r, flags, 0, str, br ? &bounds : 0, 0, 0, 0, this);
5926 *br = bounds.toAlignedRect();
5930 \fn void QPainter::drawText(const QPoint &position, const QString &text)
5934 Draws the given \a text with the currently defined text direction,
5935 beginning at the given \a position.
5937 By default, QPainter draws text anti-aliased.
5939 \note The y-position is used as the baseline of the font.
5944 \fn void QPainter::drawText(const QRectF &rectangle, int flags, const QString &text, QRectF *boundingRect)
5947 Draws the given \a text within the provided \a rectangle.
5951 \li \inlineimage qpainter-text.png
5953 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 17
5956 The \a boundingRect (if not null) is set to the what the bounding rectangle
5957 should be in order to enclose the whole text. The \a flags argument is a bitwise
5958 OR of the following flags:
5963 \li Qt::AlignHCenter
5964 \li Qt::AlignJustify
5967 \li Qt::AlignVCenter
5969 \li Qt::TextDontClip
5970 \li Qt::TextSingleLine
5971 \li Qt::TextExpandTabs
5972 \li Qt::TextShowMnemonic
5973 \li Qt::TextWordWrap
5974 \li Qt::TextIncludeTrailingSpaces
5977 \sa Qt::AlignmentFlag, Qt::TextFlag, boundingRect(), layoutDirection()
5979 By default, QPainter draws text anti-aliased.
5981 \note The y-coordinate of \a rectangle is used as the top of the font.
5983 void QPainter::drawText(const QRectF &r, int flags, const QString &str, QRectF *br)
5985 #ifdef QT_DEBUG_DRAW
5986 if (qt_show_painter_debug_output)
5987 printf("QPainter::drawText(), r=[%.2f,%.2f,%.2f,%.2f], flags=%d, str='%s'\n",
5988 r.x(), r.y(), r.width(), r.height(), flags, str.toLatin1().constData());
5993 if (!d->engine || str.length() == 0 || pen().style() == Qt::NoPen)
5997 d->updateState(d->state);
5999 qt_format_text(d->state->font, r, flags, 0, str, br, 0, 0, 0, this);
6003 \fn void QPainter::drawText(const QRect &rectangle, int flags, const QString &text, QRect *boundingRect)
6006 Draws the given \a text within the provided \a rectangle according
6007 to the specified \a flags. The \a boundingRect (if not null) is set to
6008 the what the bounding rectangle should be in order to enclose the whole text.
6010 By default, QPainter draws text anti-aliased.
6012 \note The y-coordinate of \a rectangle is used as the top of the font.
6016 \fn void QPainter::drawText(int x, int y, const QString &text)
6020 Draws the given \a text at position (\a{x}, \a{y}), using the painter's
6021 currently defined text direction.
6023 By default, QPainter draws text anti-aliased.
6025 \note The y-position is used as the baseline of the font.
6030 \fn void QPainter::drawText(int x, int y, int width, int height, int flags,
6031 const QString &text, QRect *boundingRect)
6035 Draws the given \a text within the rectangle with origin (\a{x},
6036 \a{y}), \a width and \a height.
6038 The \a boundingRect (if not null) is set to the actual bounding
6039 rectangle of the output. The \a flags argument is a bitwise OR of
6040 the following flags:
6045 \li Qt::AlignHCenter
6046 \li Qt::AlignJustify
6049 \li Qt::AlignVCenter
6051 \li Qt::TextSingleLine
6052 \li Qt::TextExpandTabs
6053 \li Qt::TextShowMnemonic
6054 \li Qt::TextWordWrap
6057 By default, QPainter draws text anti-aliased.
6059 \note The y-position is used as the top of the font.
6061 \sa Qt::AlignmentFlag, Qt::TextFlag
6065 \fn void QPainter::drawText(const QRectF &rectangle, const QString &text,
6066 const QTextOption &option)
6069 Draws the given \a text in the \a rectangle specified using the \a option
6070 to control its positioning and orientation.
6072 By default, QPainter draws text anti-aliased.
6074 \note The y-coordinate of \a rectangle is used as the top of the font.
6076 void QPainter::drawText(const QRectF &r, const QString &text, const QTextOption &o)
6078 #ifdef QT_DEBUG_DRAW
6079 if (qt_show_painter_debug_output)
6080 printf("QPainter::drawText(), r=[%.2f,%.2f,%.2f,%.2f], str='%s'\n",
6081 r.x(), r.y(), r.width(), r.height(), text.toLatin1().constData());
6086 if (!d->engine || text.length() == 0 || pen().style() == Qt::NoPen)
6090 d->updateState(d->state);
6092 qt_format_text(d->state->font, r, 0, &o, text, 0, 0, 0, 0, this);
6096 \fn void QPainter::drawTextItem(int x, int y, const QTextItem &ti)
6103 \fn void QPainter::drawTextItem(const QPoint &p, const QTextItem &ti)
6108 Draws the text item \a ti at position \a p.
6112 \fn void QPainter::drawTextItem(const QPointF &p, const QTextItem &ti)
6117 Draws the text item \a ti at position \a p.
6119 This method ignores the painters background mode and
6120 color. drawText and qt_format_text have to do it themselves, as
6121 only they know the extents of the complete string.
6123 It ignores the font set on the painter as the text item has one of its own.
6125 The underline and strikeout parameters of the text items font are
6126 ignored aswell. You'll need to pass in the correct flags to get
6127 underlining and strikeout.
6130 static QPixmap generateWavyPixmap(qreal maxRadius, const QPen &pen)
6132 const qreal radiusBase = qMax(qreal(1), maxRadius);
6134 QString key = QLatin1Literal("WaveUnderline-")
6135 % pen.color().name()
6136 % HexString<qreal>(radiusBase);
6139 if (QPixmapCache::find(key, pixmap))
6142 const qreal halfPeriod = qMax(qreal(2), qreal(radiusBase * 1.61803399)); // the golden ratio
6143 const int width = qCeil(100 / (2 * halfPeriod)) * (2 * halfPeriod);
6144 const int radius = qFloor(radiusBase);
6151 while (xs < width) {
6154 path.quadTo(xs - halfPeriod / 2, ys, xs, 0);
6157 pixmap = QPixmap(width, radius * 2);
6158 pixmap.fill(Qt::transparent);
6161 wavePen.setCapStyle(Qt::SquareCap);
6163 // This is to protect against making the line too fat, as happens on Mac OS X
6164 // due to it having a rather thick width for the regular underline.
6165 const qreal maxPenWidth = .8 * radius;
6166 if (wavePen.widthF() > maxPenWidth)
6167 wavePen.setWidth(maxPenWidth);
6169 QPainter imgPainter(&pixmap);
6170 imgPainter.setPen(wavePen);
6171 imgPainter.setRenderHint(QPainter::Antialiasing);
6172 imgPainter.translate(0, radius);
6173 imgPainter.drawPath(path);
6176 QPixmapCache::insert(key, pixmap);
6181 static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const QFontEngine *fe, QTextEngine *textEngine,
6182 QTextCharFormat::UnderlineStyle underlineStyle,
6183 QTextItem::RenderFlags flags, qreal width,
6184 const QTextCharFormat &charFormat)
6186 if (underlineStyle == QTextCharFormat::NoUnderline
6187 && !(flags & (QTextItem::StrikeOut | QTextItem::Overline)))
6190 const QPen oldPen = painter->pen();
6191 const QBrush oldBrush = painter->brush();
6192 painter->setBrush(Qt::NoBrush);
6194 pen.setStyle(Qt::SolidLine);
6195 pen.setWidthF(fe->lineThickness().toReal());
6196 pen.setCapStyle(Qt::FlatCap);
6198 QLineF line(pos.x(), pos.y(), pos.x() + qFloor(width), pos.y());
6200 const qreal underlineOffset = fe->underlinePosition().toReal();
6201 // deliberately ceil the offset to avoid the underline coming too close to
6202 // the text above it.
6203 const qreal aliasedCoordinateDelta = 0.5 - 0.015625;
6204 const qreal underlinePos = pos.y() + qCeil(underlineOffset) - aliasedCoordinateDelta;
6206 if (underlineStyle == QTextCharFormat::SpellCheckUnderline) {
6207 underlineStyle = QTextCharFormat::SpellCheckUnderline; // ### Qt5 QTextCharFormat::UnderlineStyle(QApplication::style()->styleHint(QStyle::SH_SpellCheckUnderlineStyle));
6210 if (underlineStyle == QTextCharFormat::WaveUnderline) {
6212 painter->translate(0, pos.y() + 1);
6214 QColor uc = charFormat.underlineColor();
6218 // Adapt wave to underlineOffset or pen width, whatever is larger, to make it work on all platforms
6219 const QPixmap wave = generateWavyPixmap(qMax(underlineOffset, pen.widthF()), pen);
6220 const int descent = (int) fe->descent().toReal();
6222 painter->setBrushOrigin(painter->brushOrigin().x(), 0);
6223 painter->fillRect(pos.x(), 0, qCeil(width), qMin(wave.height(), descent), wave);
6225 } else if (underlineStyle != QTextCharFormat::NoUnderline) {
6226 QColor uc = charFormat.underlineColor();
6230 pen.setStyle((Qt::PenStyle)(underlineStyle));
6231 painter->setPen(pen);
6232 QLineF underline(line.x1(), underlinePos, line.x2(), underlinePos);
6234 textEngine->addUnderline(painter, underline);
6236 painter->drawLine(underline);
6239 pen.setStyle(Qt::SolidLine);
6240 pen.setColor(oldPen.color());
6242 if (flags & QTextItem::StrikeOut) {
6243 QLineF strikeOutLine = line;
6244 strikeOutLine.translate(0., - fe->ascent().toReal() / 3.);
6245 painter->setPen(pen);
6247 textEngine->addStrikeOut(painter, strikeOutLine);
6249 painter->drawLine(strikeOutLine);
6252 if (flags & QTextItem::Overline) {
6253 QLineF overline = line;
6254 overline.translate(0., - fe->ascent().toReal());
6255 painter->setPen(pen);
6257 textEngine->addOverline(painter, overline);
6259 painter->drawLine(overline);
6262 painter->setPen(oldPen);
6263 painter->setBrush(oldBrush);
6266 Q_GUI_EXPORT void qt_draw_decoration_for_glyphs(QPainter *painter, const glyph_t *glyphArray,
6267 const QFixedPoint *positions, int glyphCount,
6268 QFontEngine *fontEngine, const QFont &font,
6269 const QTextCharFormat &charFormat)
6271 if (!(font.underline() || font.strikeOut() || font.overline()))
6277 for (int i=0; i<glyphCount; ++i) {
6278 glyph_metrics_t gm = fontEngine->boundingBox(glyphArray[i]);
6279 if (i == 0 || leftMost > positions[i].x)
6280 leftMost = positions[i].x;
6282 // We don't support glyphs that do not share a common baseline. If this turns out to
6283 // be a relevant use case, then we need to find clusters of glyphs that share a baseline
6284 // and do a drawTextItemDecoration call per cluster.
6285 if (i == 0 || baseLine < positions[i].y)
6286 baseLine = positions[i].y;
6288 // We use the advance rather than the actual bounds to match the algorithm in drawText()
6289 if (i == 0 || rightMost < positions[i].x + gm.xoff)
6290 rightMost = positions[i].x + gm.xoff;
6293 QFixed width = rightMost - leftMost;
6294 QTextItem::RenderFlags flags = 0;
6296 if (font.underline())
6297 flags |= QTextItem::Underline;
6298 if (font.overline())
6299 flags |= QTextItem::Overline;
6300 if (font.strikeOut())
6301 flags |= QTextItem::StrikeOut;
6303 drawTextItemDecoration(painter, QPointF(leftMost.toReal(), baseLine.toReal()),
6306 font.underline() ? QTextCharFormat::SingleUnderline
6307 : QTextCharFormat::NoUnderline, flags,
6308 width.toReal(), charFormat);
6311 void QPainter::drawTextItem(const QPointF &p, const QTextItem &ti)
6315 d->drawTextItem(p, ti, static_cast<QTextEngine *>(0));
6318 void QPainterPrivate::drawTextItem(const QPointF &p, const QTextItem &_ti, QTextEngine *textEngine)
6320 #ifdef QT_DEBUG_DRAW
6321 if (qt_show_painter_debug_output)
6322 printf("QPainter::drawTextItem(), pos=[%.f,%.f], str='%s'\n",
6323 p.x(), p.y(), qPrintable(_ti.text()));
6332 qt_painter_thread_test(device->devType(),
6334 QFontDatabase::supportsThreadedFontRendering());
6337 QTextItemInt &ti = const_cast<QTextItemInt &>(static_cast<const QTextItemInt &>(_ti));
6339 if (!extended && state->bgMode == Qt::OpaqueMode) {
6340 QRectF rect(p.x(), p.y() - ti.ascent.toReal(), ti.width.toReal(), (ti.ascent + ti.descent + 1).toReal());
6341 q->fillRect(rect, state->bgBrush);
6344 if (q->pen().style() == Qt::NoPen)
6347 const QPainter::RenderHints oldRenderHints = state->renderHints;
6348 if (!state->renderHints & QPainter::Antialiasing && state->matrix.type() >= QTransform::TxScale) {
6349 // draw antialias decoration (underline/overline/strikeout) with
6353 const QTransform &m = state->matrix;
6354 if (state->matrix.type() < QTransform::TxShear) {
6355 bool isPlain90DegreeRotation =
6356 (qFuzzyIsNull(m.m11())
6357 && qFuzzyIsNull(m.m12() - qreal(1))
6358 && qFuzzyIsNull(m.m21() + qreal(1))
6359 && qFuzzyIsNull(m.m22())
6362 (qFuzzyIsNull(m.m11() + qreal(1))
6363 && qFuzzyIsNull(m.m12())
6364 && qFuzzyIsNull(m.m21())
6365 && qFuzzyIsNull(m.m22() + qreal(1))
6368 (qFuzzyIsNull(m.m11())
6369 && qFuzzyIsNull(m.m12() + qreal(1))
6370 && qFuzzyIsNull(m.m21() - qreal(1))
6371 && qFuzzyIsNull(m.m22())
6374 aa = !isPlain90DegreeRotation;
6377 q->setRenderHint(QPainter::Antialiasing, true);
6383 if (!ti.glyphs.numGlyphs) {
6385 } else if (ti.fontEngine->type() == QFontEngine::Multi) {
6386 QFontEngineMulti *multi = static_cast<QFontEngineMulti *>(ti.fontEngine);
6388 const QGlyphLayout &glyphs = ti.glyphs;
6389 int which = glyphs.glyphs[0] >> 24;
6394 bool rtl = ti.flags & QTextItem::RightToLeft;
6396 x += ti.width.toReal();
6400 for (end = 0; end < ti.glyphs.numGlyphs; ++end) {
6401 const int e = glyphs.glyphs[end] >> 24;
6406 QTextItemInt ti2 = ti.midItem(multi->engine(which), start, end - start);
6408 // set the high byte to zero and calc the width
6409 for (i = start; i < end; ++i) {
6410 glyphs.glyphs[i] = glyphs.glyphs[i] & 0xffffff;
6411 ti2.width += ti.glyphs.effectiveAdvance(i);
6415 x -= ti2.width.toReal();
6417 engine->drawTextItem(QPointF(x, y), ti2);
6420 x += ti2.width.toReal();
6422 // reset the high byte for all glyphs and advance to the next sub-string
6423 const int hi = which << 24;
6424 for (i = start; i < end; ++i) {
6425 glyphs.glyphs[i] = hi | glyphs.glyphs[i];
6433 QTextItemInt ti2 = ti.midItem(multi->engine(which), start, end - start);
6435 // set the high byte to zero and calc the width
6436 for (i = start; i < end; ++i) {
6437 glyphs.glyphs[i] = glyphs.glyphs[i] & 0xffffff;
6438 ti2.width += ti.glyphs.effectiveAdvance(i);
6442 x -= ti2.width.toReal();
6445 extended->drawTextItem(QPointF(x, y), ti2);
6447 engine->drawTextItem(QPointF(x,y), ti2);
6449 // reset the high byte for all glyphs
6450 const int hi = which << 24;
6451 for (i = start; i < end; ++i)
6452 glyphs.glyphs[i] = hi | glyphs.glyphs[i];
6456 extended->drawTextItem(p, ti);
6458 engine->drawTextItem(p, ti);
6460 drawTextItemDecoration(q, p, ti.fontEngine, textEngine, ti.underlineStyle,
6461 ti.flags, ti.width.toReal(), ti.charFormat);
6463 if (state->renderHints != oldRenderHints) {
6464 state->renderHints = oldRenderHints;
6466 extended->renderHintsChanged();
6468 state->dirtyFlags |= QPaintEngine::DirtyHints;
6473 \fn QRectF QPainter::boundingRect(const QRectF &rectangle, int flags, const QString &text)
6475 Returns the bounding rectangle of the \a text as it will appear
6476 when drawn inside the given \a rectangle with the specified \a
6477 flags using the currently set font(); i.e the function tells you
6478 where the drawText() function will draw when given the same
6481 If the \a text does not fit within the given \a rectangle using
6482 the specified \a flags, the function returns the required
6485 The \a flags argument is a bitwise OR of the following flags:
6489 \li Qt::AlignHCenter
6492 \li Qt::AlignVCenter
6494 \li Qt::TextSingleLine
6495 \li Qt::TextExpandTabs
6496 \li Qt::TextShowMnemonic
6497 \li Qt::TextWordWrap
6498 \li Qt::TextIncludeTrailingSpaces
6500 If several of the horizontal or several of the vertical alignment
6501 flags are set, the resulting alignment is undefined.
6503 \sa drawText(), Qt::Alignment, Qt::TextFlag
6507 \fn QRect QPainter::boundingRect(const QRect &rectangle, int flags,
6508 const QString &text)
6512 Returns the bounding rectangle of the \a text as it will appear
6513 when drawn inside the given \a rectangle with the specified \a
6514 flags using the currently set font().
6518 \fn QRect QPainter::boundingRect(int x, int y, int w, int h, int flags,
6519 const QString &text);
6523 Returns the bounding rectangle of the given \a text as it will
6524 appear when drawn inside the rectangle beginning at the point
6525 (\a{x}, \a{y}) with width \a w and height \a h.
6527 QRect QPainter::boundingRect(const QRect &rect, int flags, const QString &str)
6530 return QRect(rect.x(),rect.y(), 0,0);
6532 drawText(rect, flags | Qt::TextDontPrint, str, &brect);
6538 QRectF QPainter::boundingRect(const QRectF &rect, int flags, const QString &str)
6541 return QRectF(rect.x(),rect.y(), 0,0);
6543 drawText(rect, flags | Qt::TextDontPrint, str, &brect);
6548 \fn QRectF QPainter::boundingRect(const QRectF &rectangle,
6549 const QString &text, const QTextOption &option)
6553 Instead of specifying flags as a bitwise OR of the
6554 Qt::AlignmentFlag and Qt::TextFlag, this overloaded function takes
6555 an \a option argument. The QTextOption class provides a
6556 description of general rich text properties.
6560 QRectF QPainter::boundingRect(const QRectF &r, const QString &text, const QTextOption &o)
6564 if (!d->engine || text.length() == 0)
6565 return QRectF(r.x(),r.y(), 0,0);
6568 qt_format_text(d->state->font, r, Qt::TextDontPrint, &o, text, &br, 0, 0, 0, this);
6573 \fn void QPainter::drawTiledPixmap(const QRectF &rectangle, const QPixmap &pixmap, const QPointF &position)
6575 Draws a tiled \a pixmap, inside the given \a rectangle with its
6576 origin at the given \a position.
6578 Calling drawTiledPixmap() is similar to calling drawPixmap()
6579 several times to fill (tile) an area with a pixmap, but is
6580 potentially much more efficient depending on the underlying window
6585 void QPainter::drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, const QPointF &sp)
6587 #ifdef QT_DEBUG_DRAW
6588 if (qt_show_painter_debug_output)
6589 printf("QPainter::drawTiledPixmap(), target=[%.2f,%.2f,%.2f,%.2f], pix=[%d,%d], offset=[%.2f,%.2f]\n",
6590 r.x(), r.y(), r.width(), r.height(),
6591 pixmap.width(), pixmap.height(),
6596 if (!d->engine || pixmap.isNull() || r.isEmpty())
6600 qt_painter_thread_test(d->device->devType(), "drawTiledPixmap()", true);
6603 qreal sw = pixmap.width();
6604 qreal sh = pixmap.height();
6608 sx = qRound(sw) - qRound(-sx) % qRound(sw);
6610 sx = qRound(sx) % qRound(sw);
6612 sy = qRound(sh) - -qRound(sy) % qRound(sh);
6614 sy = qRound(sy) % qRound(sh);
6618 d->extended->drawTiledPixmap(r, pixmap, QPointF(sx, sy));
6622 if (d->state->bgMode == Qt::OpaqueMode && pixmap.isQBitmap())
6623 fillRect(r, d->state->bgBrush);
6625 d->updateState(d->state);
6626 if ((d->state->matrix.type() > QTransform::TxTranslate
6627 && !d->engine->hasFeature(QPaintEngine::PixmapTransform))
6628 || (d->state->opacity != 1.0 && !d->engine->hasFeature(QPaintEngine::ConstantOpacity)))
6631 setBackgroundMode(Qt::TransparentMode);
6632 setRenderHint(Antialiasing, renderHints() & SmoothPixmapTransform);
6633 setBrush(QBrush(d->state->pen.color(), pixmap));
6636 // If there is no rotation involved we have to make sure we use the
6637 // antialiased and not the aliased coordinate system by rounding the coordinates.
6638 if (d->state->matrix.type() <= QTransform::TxScale) {
6639 const QPointF p = roundInDeviceCoordinates(r.topLeft(), d->state->matrix);
6641 if (d->state->matrix.type() <= QTransform::TxTranslate) {
6646 setBrushOrigin(QPointF(r.x()-sx, r.y()-sy));
6647 drawRect(QRectF(p, r.size()));
6649 setBrushOrigin(QPointF(r.x()-sx, r.y()-sy));
6658 if (d->state->matrix.type() == QTransform::TxTranslate
6659 && !d->engine->hasFeature(QPaintEngine::PixmapTransform)) {
6660 x += d->state->matrix.dx();
6661 y += d->state->matrix.dy();
6664 d->engine->drawTiledPixmap(QRectF(x, y, r.width(), r.height()), pixmap, QPointF(sx, sy));
6668 \fn QPainter::drawTiledPixmap(const QRect &rectangle, const QPixmap &pixmap,
6669 const QPoint &position = QPoint())
6672 Draws a tiled \a pixmap, inside the given \a rectangle with its
6673 origin at the given \a position.
6677 \fn void QPainter::drawTiledPixmap(int x, int y, int width, int height, const
6678 QPixmap &pixmap, int sx, int sy);
6681 Draws a tiled \a pixmap in the specified rectangle.
6683 (\a{x}, \a{y}) specifies the top-left point in the paint device
6684 that is to be drawn onto; with the given \a width and \a
6685 height. (\a{sx}, \a{sy}) specifies the top-left point in the \a
6686 pixmap that is to be drawn; this defaults to (0, 0).
6689 #ifndef QT_NO_PICTURE
6692 \fn void QPainter::drawPicture(const QPointF &point, const QPicture &picture)
6694 Replays the given \a picture at the given \a point.
6696 The QPicture class is a paint device that records and replays
6697 QPainter commands. A picture serializes the painter commands to an
6698 IO device in a platform-independent format. Everything that can be
6699 painted on a widget or pixmap can also be stored in a picture.
6701 This function does exactly the same as QPicture::play() when
6702 called with \a point = QPoint(0, 0).
6707 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 18
6710 \sa QPicture::play()
6713 void QPainter::drawPicture(const QPointF &p, const QPicture &picture)
6721 d->updateState(d->state);
6725 const_cast<QPicture *>(&picture)->play(this);
6730 \fn void QPainter::drawPicture(const QPoint &point, const QPicture &picture)
6733 Replays the given \a picture at the given \a point.
6737 \fn void QPainter::drawPicture(int x, int y, const QPicture &picture)
6740 Draws the given \a picture at point (\a x, \a y).
6743 #endif // QT_NO_PICTURE
6746 \fn void QPainter::eraseRect(const QRectF &rectangle)
6748 Erases the area inside the given \a rectangle. Equivalent to
6750 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 19
6754 void QPainter::eraseRect(const QRectF &r)
6758 fillRect(r, d->state->bgBrush);
6761 static inline bool needsResolving(const QBrush &brush)
6763 Qt::BrushStyle s = brush.style();
6764 return ((s == Qt::LinearGradientPattern || s == Qt::RadialGradientPattern ||
6765 s == Qt::ConicalGradientPattern) &&
6766 brush.gradient()->coordinateMode() == QGradient::ObjectBoundingMode);
6770 \fn void QPainter::eraseRect(const QRect &rectangle)
6773 Erases the area inside the given \a rectangle.
6777 \fn void QPainter::eraseRect(int x, int y, int width, int height)
6780 Erases the area inside the rectangle beginning at (\a x, \a y)
6781 with the given \a width and \a height.
6786 \fn void QPainter::fillRect(int x, int y, int width, int height, Qt::BrushStyle style)
6789 Fills the rectangle beginning at (\a{x}, \a{y}) with the given \a
6790 width and \a height, using the brush \a style specified.
6796 \fn void QPainter::fillRect(const QRect &rectangle, Qt::BrushStyle style)
6799 Fills the given \a rectangle with the brush \a style specified.
6805 \fn void QPainter::fillRect(const QRectF &rectangle, Qt::BrushStyle style)
6808 Fills the given \a rectangle with the brush \a style specified.
6814 \fn void QPainter::fillRect(const QRectF &rectangle, const QBrush &brush)
6816 Fills the given \a rectangle with the \a brush specified.
6818 Alternatively, you can specify a QColor instead of a QBrush; the
6819 QBrush constructor (taking a QColor argument) will automatically
6820 create a solid pattern brush.
6824 void QPainter::fillRect(const QRectF &r, const QBrush &brush)
6832 const QGradient *g = brush.gradient();
6833 if (!g || g->coordinateMode() == QGradient::LogicalMode) {
6834 d->extended->fillRect(r, brush);
6839 QPen oldPen = pen();
6840 QBrush oldBrush = this->brush();
6842 if (brush.style() == Qt::SolidPattern) {
6843 d->colorBrush.setStyle(Qt::SolidPattern);
6844 d->colorBrush.setColor(brush.color());
6845 setBrush(d->colorBrush);
6856 \fn void QPainter::fillRect(const QRect &rectangle, const QBrush &brush)
6859 Fills the given \a rectangle with the specified \a brush.
6862 void QPainter::fillRect(const QRect &r, const QBrush &brush)
6870 const QGradient *g = brush.gradient();
6871 if (!g || g->coordinateMode() == QGradient::LogicalMode) {
6872 d->extended->fillRect(r, brush);
6877 QPen oldPen = pen();
6878 QBrush oldBrush = this->brush();
6880 if (brush.style() == Qt::SolidPattern) {
6881 d->colorBrush.setStyle(Qt::SolidPattern);
6882 d->colorBrush.setColor(brush.color());
6883 setBrush(d->colorBrush);
6896 \fn void QPainter::fillRect(const QRect &rectangle, const QColor &color)
6899 Fills the given \a rectangle with the \a color specified.
6903 void QPainter::fillRect(const QRect &r, const QColor &color)
6911 d->extended->fillRect(r, color);
6915 fillRect(r, QBrush(color));
6920 \fn void QPainter::fillRect(const QRectF &rectangle, const QColor &color)
6923 Fills the given \a rectangle with the \a color specified.
6927 void QPainter::fillRect(const QRectF &r, const QColor &color)
6935 d->extended->fillRect(r, color);
6939 fillRect(r, QBrush(color));
6943 \fn void QPainter::fillRect(int x, int y, int width, int height, const QBrush &brush)
6947 Fills the rectangle beginning at (\a{x}, \a{y}) with the given \a
6948 width and \a height, using the given \a brush.
6952 \fn void QPainter::fillRect(int x, int y, int width, int height, const QColor &color)
6956 Fills the rectangle beginning at (\a{x}, \a{y}) with the given \a
6957 width and \a height, using the given \a color.
6963 \fn void QPainter::fillRect(int x, int y, int width, int height, Qt::GlobalColor color)
6967 Fills the rectangle beginning at (\a{x}, \a{y}) with the given \a
6968 width and \a height, using the given \a color.
6974 \fn void QPainter::fillRect(const QRect &rectangle, Qt::GlobalColor color);
6978 Fills the given \a rectangle with the specified \a color.
6984 \fn void QPainter::fillRect(const QRectF &rectangle, Qt::GlobalColor color);
6988 Fills the given \a rectangle with the specified \a color.
6994 Sets the given render \a hint on the painter if \a on is true;
6995 otherwise clears the render hint.
6997 \sa setRenderHints(), renderHints(), {QPainter#Rendering
6998 Quality}{Rendering Quality}
7000 void QPainter::setRenderHint(RenderHint hint, bool on)
7002 #ifdef QT_DEBUG_DRAW
7003 if (qt_show_painter_debug_output)
7004 printf("QPainter::setRenderHint: hint=%x, %s\n", hint, on ? "on" : "off");
7008 static const bool antialiasingDisabled = qgetenv("QT_NO_ANTIALIASING").toInt();
7009 if (hint == QPainter::Antialiasing && antialiasingDisabled)
7013 setRenderHints(hint, on);
7019 Sets the given render \a hints on the painter if \a on is true;
7020 otherwise clears the render hints.
7022 \sa setRenderHint(), renderHints(), {QPainter#Rendering
7023 Quality}{Rendering Quality}
7026 void QPainter::setRenderHints(RenderHints hints, bool on)
7031 qWarning("QPainter::setRenderHint: Painter must be active to set rendering hints");
7036 d->state->renderHints |= hints;
7038 d->state->renderHints &= ~hints;
7041 d->extended->renderHintsChanged();
7043 d->state->dirtyFlags |= QPaintEngine::DirtyHints;
7047 Returns a flag that specifies the rendering hints that are set for
7050 \sa testRenderHint(), {QPainter#Rendering Quality}{Rendering Quality}
7052 QPainter::RenderHints QPainter::renderHints() const
7054 Q_D(const QPainter);
7059 return d->state->renderHints;
7063 \fn bool QPainter::testRenderHint(RenderHint hint) const
7066 Returns true if \a hint is set; otherwise returns false.
7068 \sa renderHints(), setRenderHint()
7072 Returns true if view transformation is enabled; otherwise returns
7075 \sa setViewTransformEnabled(), worldTransform()
7078 bool QPainter::viewTransformEnabled() const
7080 Q_D(const QPainter);
7082 qWarning("QPainter::viewTransformEnabled: Painter not active");
7085 return d->state->VxF;
7089 \fn void QPainter::setWindow(const QRect &rectangle)
7091 Sets the painter's window to the given \a rectangle, and enables
7092 view transformations.
7094 The window rectangle is part of the view transformation. The
7095 window specifies the logical coordinate system. Its sister, the
7096 viewport(), specifies the device coordinate system.
7098 The default window rectangle is the same as the device's
7101 \sa window(), viewTransformEnabled(), {Coordinate
7102 System#Window-Viewport Conversion}{Window-Viewport Conversion}
7106 \fn void QPainter::setWindow(int x, int y, int width, int height)
7109 Sets the painter's window to the rectangle beginning at (\a x, \a
7110 y) and the given \a width and \a height.
7113 void QPainter::setWindow(const QRect &r)
7115 #ifdef QT_DEBUG_DRAW
7116 if (qt_show_painter_debug_output)
7117 printf("QPainter::setWindow(), [%d,%d,%d,%d]\n", r.x(), r.y(), r.width(), r.height());
7123 qWarning("QPainter::setWindow: Painter not active");
7127 d->state->wx = r.x();
7128 d->state->wy = r.y();
7129 d->state->ww = r.width();
7130 d->state->wh = r.height();
7132 d->state->VxF = true;
7137 Returns the window rectangle.
7139 \sa setWindow(), setViewTransformEnabled()
7142 QRect QPainter::window() const
7144 Q_D(const QPainter);
7146 qWarning("QPainter::window: Painter not active");
7149 return QRect(d->state->wx, d->state->wy, d->state->ww, d->state->wh);
7153 \fn void QPainter::setViewport(const QRect &rectangle)
7155 Sets the painter's viewport rectangle to the given \a rectangle,
7156 and enables view transformations.
7158 The viewport rectangle is part of the view transformation. The
7159 viewport specifies the device coordinate system. Its sister, the
7160 window(), specifies the logical coordinate system.
7162 The default viewport rectangle is the same as the device's
7165 \sa viewport(), viewTransformEnabled() {Coordinate
7166 System#Window-Viewport Conversion}{Window-Viewport Conversion}
7170 \fn void QPainter::setViewport(int x, int y, int width, int height)
7173 Sets the painter's viewport rectangle to be the rectangle
7174 beginning at (\a x, \a y) with the given \a width and \a height.
7177 void QPainter::setViewport(const QRect &r)
7179 #ifdef QT_DEBUG_DRAW
7180 if (qt_show_painter_debug_output)
7181 printf("QPainter::setViewport(), [%d,%d,%d,%d]\n", r.x(), r.y(), r.width(), r.height());
7187 qWarning("QPainter::setViewport: Painter not active");
7191 d->state->vx = r.x();
7192 d->state->vy = r.y();
7193 d->state->vw = r.width();
7194 d->state->vh = r.height();
7196 d->state->VxF = true;
7201 Returns the viewport rectangle.
7203 \sa setViewport(), setViewTransformEnabled()
7206 QRect QPainter::viewport() const
7208 Q_D(const QPainter);
7210 qWarning("QPainter::viewport: Painter not active");
7213 return QRect(d->state->vx, d->state->vy, d->state->vw, d->state->vh);
7217 Enables view transformations if \a enable is true, or disables
7218 view transformations if \a enable is false.
7220 \sa viewTransformEnabled(), {Coordinate System#Window-Viewport
7221 Conversion}{Window-Viewport Conversion}
7224 void QPainter::setViewTransformEnabled(bool enable)
7226 #ifdef QT_DEBUG_DRAW
7227 if (qt_show_painter_debug_output)
7228 printf("QPainter::setViewTransformEnabled(), enable=%d\n", enable);
7234 qWarning("QPainter::setViewTransformEnabled: Painter not active");
7238 if (enable == d->state->VxF)
7241 d->state->VxF = enable;
7250 Please use QWidget::render() instead.
7252 Redirects all paint commands for the given paint \a device, to the
7253 \a replacement device. The optional point \a offset defines an
7254 offset within the source device.
7256 The redirection will not be effective until the begin() function
7257 has been called; make sure to call end() for the given \a
7258 device's painter (if any) before redirecting. Call
7259 restoreRedirected() to restore the previous redirection.
7261 \warning Making use of redirections in the QPainter API implies
7262 that QPainter::begin() and QPaintDevice destructors need to hold
7263 a mutex for a short period. This can impact performance. Use of
7264 QWidget::render is strongly encouraged.
7266 \sa redirected(), restoreRedirected()
7268 void QPainter::setRedirected(const QPaintDevice *device,
7269 QPaintDevice *replacement,
7270 const QPoint &offset)
7272 Q_ASSERT(device != 0);
7274 Q_UNUSED(replacement)
7276 qWarning("QPainter::setRedirected(): ignoring call to deprecated function, use QWidget::render() instead");
7284 Using QWidget::render() obsoletes the use of this function.
7286 Restores the previous redirection for the given \a device after a
7287 call to setRedirected().
7289 \warning Making use of redirections in the QPainter API implies
7290 that QPainter::begin() and QPaintDevice destructors need to hold
7291 a mutex for a short period. This can impact performance. Use of
7292 QWidget::render is strongly encouraged.
7296 void QPainter::restoreRedirected(const QPaintDevice *device)
7299 qWarning("QPainter::restoreRedirected(): ignoring call to deprecated function, use QWidget::render() instead");
7307 Using QWidget::render() obsoletes the use of this function.
7309 Returns the replacement for given \a device. The optional out
7310 parameter \a offset returns the offset within the replaced device.
7312 \warning Making use of redirections in the QPainter API implies
7313 that QPainter::begin() and QPaintDevice destructors need to hold
7314 a mutex for a short period. This can impact performance. Use of
7315 QWidget::render is strongly encouraged.
7317 \sa setRedirected(), restoreRedirected()
7319 QPaintDevice *QPainter::redirected(const QPaintDevice *device, QPoint *offset)
7326 void qt_format_text(const QFont &fnt, const QRectF &_r,
7327 int tf, const QString& str, QRectF *brect,
7328 int tabstops, int *ta, int tabarraylen,
7331 qt_format_text(fnt, _r,
7333 tabstops, ta, tabarraylen,
7336 void qt_format_text(const QFont &fnt, const QRectF &_r,
7337 int tf, const QTextOption *option, const QString& str, QRectF *brect,
7338 int tabstops, int *ta, int tabarraylen,
7342 Q_ASSERT( !((tf & ~Qt::TextDontPrint)!=0 && option!=0) ); // we either have an option or flags
7345 tf |= option->alignment();
7346 if (option->wrapMode() != QTextOption::NoWrap)
7347 tf |= Qt::TextWordWrap;
7349 if (option->flags() & QTextOption::IncludeTrailingSpaces)
7350 tf |= Qt::TextIncludeTrailingSpaces;
7352 if (option->tabStop() >= 0 || !option->tabArray().isEmpty())
7353 tf |= Qt::TextExpandTabs;
7356 // we need to copy r here to protect against the case (&r == brect).
7359 bool dontclip = (tf & Qt::TextDontClip);
7360 bool wordwrap = (tf & Qt::TextWordWrap) || (tf & Qt::TextWrapAnywhere);
7361 bool singleline = (tf & Qt::TextSingleLine);
7362 bool showmnemonic = (tf & Qt::TextShowMnemonic);
7363 bool hidemnmemonic = (tf & Qt::TextHideMnemonic);
7365 Qt::LayoutDirection layout_direction;
7366 if (tf & Qt::TextForceLeftToRight)
7367 layout_direction = Qt::LeftToRight;
7368 else if (tf & Qt::TextForceRightToLeft)
7369 layout_direction = Qt::RightToLeft;
7371 layout_direction = option->textDirection();
7373 layout_direction = painter->layoutDirection();
7375 layout_direction = Qt::LeftToRight;
7377 tf = QGuiApplicationPrivate::visualAlignment(layout_direction, QFlag(tf));
7379 bool isRightToLeft = layout_direction == Qt::RightToLeft;
7380 bool expandtabs = ((tf & Qt::TextExpandTabs) &&
7381 (((tf & Qt::AlignLeft) && !isRightToLeft) ||
7382 ((tf & Qt::AlignRight) && isRightToLeft)));
7385 tf |= Qt::TextDontPrint;
7387 uint maxUnderlines = 0;
7388 int numUnderlines = 0;
7389 QVarLengthArray<int, 32> underlinePositions(1);
7391 QFontMetricsF fm(fnt);
7394 start_lengthVariant:
7395 bool hasMoreLengthVariants = false;
7396 // compatible behaviour to the old implementation. Replace
7398 int old_offset = offset;
7399 for (; offset < text.length(); offset++) {
7400 QChar chr = text.at(offset);
7401 if (chr == QLatin1Char('\r') || (singleline && chr == QLatin1Char('\n'))) {
7402 text[offset] = QLatin1Char(' ');
7403 } else if (chr == QLatin1Char('\n')) {
7404 text[offset] = QChar::LineSeparator;
7405 } else if (chr == QLatin1Char('&')) {
7407 } else if (chr == QLatin1Char('\t')) {
7409 text[offset] = QLatin1Char(' ');
7410 } else if (!tabarraylen && !tabstops) {
7411 tabstops = qRound(fm.width(QLatin1Char('x'))*8);
7413 } else if (chr == QChar(ushort(0x9c))) {
7414 // string with multiple length variants
7415 hasMoreLengthVariants = true;
7420 int length = offset - old_offset;
7421 if ((hidemnmemonic || showmnemonic) && maxUnderlines > 0) {
7422 underlinePositions.resize(maxUnderlines + 1);
7424 QChar *cout = text.data() + old_offset;
7428 if (*cin == QLatin1Char('&')) {
7434 if (*cin != QLatin1Char('&') && !hidemnmemonic)
7435 underlinePositions[numUnderlines++] = cout - text.data() - old_offset;
7444 // no need to do extra work for underlines if we don't paint
7445 if (tf & Qt::TextDontPrint)
7448 underlinePositions[numUnderlines] = -1;
7452 QString finalText = text.mid(old_offset, length);
7453 QStackTextEngine engine(finalText, fnt);
7455 engine.option = *option;
7458 if (engine.option.tabStop() < 0 && tabstops > 0)
7459 engine.option.setTabStop(tabstops);
7461 if (engine.option.tabs().isEmpty() && ta) {
7463 for (int i = 0; i < tabarraylen; i++)
7464 tabs.append(qreal(ta[i]));
7465 engine.option.setTabArray(tabs);
7468 engine.option.setTextDirection(layout_direction);
7469 if (tf & Qt::AlignJustify)
7470 engine.option.setAlignment(Qt::AlignJustify);
7472 engine.option.setAlignment(Qt::AlignLeft); // do not do alignment twice
7474 if (!option && (tf & Qt::TextWrapAnywhere))
7475 engine.option.setWrapMode(QTextOption::WrapAnywhere);
7477 if (tf & Qt::TextJustificationForced)
7478 engine.forceJustification = true;
7479 QTextLayout textLayout(&engine);
7480 textLayout.setCacheEnabled(true);
7481 textLayout.engine()->underlinePositions = underlinePositions.data();
7483 if (finalText.isEmpty()) {
7484 height = fm.height();
7486 tf |= Qt::TextDontPrint;
7488 qreal lineWidth = 0x01000000;
7489 if (wordwrap || (tf & Qt::TextJustificationForced))
7490 lineWidth = qMax<qreal>(0, r.width());
7492 tf |= Qt::TextIncludeTrailingSpaces;
7493 textLayout.engine()->ignoreBidi = bool(tf & Qt::TextDontPrint);
7494 textLayout.beginLayout();
7496 qreal leading = fm.leading();
7500 QTextLine l = textLayout.createLine();
7504 l.setLineWidth(lineWidth);
7506 l.setPosition(QPointF(0., height));
7507 height += l.height();
7508 width = qMax(width, l.naturalTextWidth());
7509 if (!dontclip && !brect && height >= r.height())
7512 textLayout.endLayout();
7517 if (tf & Qt::AlignBottom) {
7518 yoff = r.height() - height;
7519 } else if (tf & Qt::AlignVCenter) {
7520 yoff = (r.height() - height)/2;
7522 QTransform::TransformationType type = painter->transform().type();
7523 if (type <= QTransform::TxScale) {
7524 // do the rounding manually to work around inconsistencies
7525 // in the paint engines when drawing on floating point offsets
7526 const qreal scale = painter->transform().m22();
7528 yoff = -qRound(-yoff * scale) / scale;
7532 if (tf & Qt::AlignRight) {
7533 xoff = r.width() - width;
7534 } else if (tf & Qt::AlignHCenter) {
7535 xoff = (r.width() - width)/2;
7537 QTransform::TransformationType type = painter->transform().type();
7538 if (type <= QTransform::TxScale) {
7539 // do the rounding manually to work around inconsistencies
7540 // in the paint engines when drawing on floating point offsets
7541 const qreal scale = painter->transform().m11();
7543 xoff = qRound(xoff * scale) / scale;
7547 QRectF bounds = QRectF(r.x() + xoff, r.y() + yoff, width, height);
7549 if (hasMoreLengthVariants && !(tf & Qt::TextLongestVariant) && !r.contains(bounds)) {
7551 goto start_lengthVariant;
7556 if (!(tf & Qt::TextDontPrint)) {
7557 bool restore = false;
7558 if (!dontclip && !r.contains(bounds)) {
7561 painter->setClipRect(r, Qt::IntersectClip);
7564 for (int i = 0; i < textLayout.lineCount(); i++) {
7565 QTextLine line = textLayout.lineAt(i);
7566 QTextEngine *eng = textLayout.engine();
7567 eng->enableDelayDecorations();
7569 qreal advance = line.horizontalAdvance();
7571 if (tf & Qt::AlignRight) {
7572 xoff = r.width() - advance -
7573 eng->leadingSpaceWidth(eng->lines[line.lineNumber()]).toReal();
7575 else if (tf & Qt::AlignHCenter)
7576 xoff = (r.width() - advance) / 2;
7578 line.draw(painter, QPointF(r.x() + xoff, r.y() + yoff));
7579 eng->drawDecorations(painter);
7589 Sets the layout direction used by the painter when drawing text,
7590 to the specified \a direction.
7592 The default is Qt::LayoutDirectionAuto, which will implicitly determine the
7593 direction from the text drawn.
7595 \sa QTextOption::setTextDirection(), layoutDirection(), drawText(), {QPainter#Settings}{Settings}
7597 void QPainter::setLayoutDirection(Qt::LayoutDirection direction)
7601 d->state->layoutDirection = direction;
7605 Returns the layout direction used by the painter when drawing text.
7607 \sa QTextOption::textDirection(), setLayoutDirection(), drawText(), {QPainter#Settings}{Settings}
7609 Qt::LayoutDirection QPainter::layoutDirection() const
7611 Q_D(const QPainter);
7612 return d->state ? d->state->layoutDirection : Qt::LayoutDirectionAuto;
7615 QPainterState::QPainterState(const QPainterState *s)
7616 : brushOrigin(s->brushOrigin), font(s->font), deviceFont(s->deviceFont),
7617 pen(s->pen), brush(s->brush), bgBrush(s->bgBrush),
7618 clipRegion(s->clipRegion), clipPath(s->clipPath),
7619 clipOperation(s->clipOperation),
7620 renderHints(s->renderHints), clipInfo(s->clipInfo),
7621 worldMatrix(s->worldMatrix), matrix(s->matrix), redirectionMatrix(s->redirectionMatrix),
7622 wx(s->wx), wy(s->wy), ww(s->ww), wh(s->wh),
7623 vx(s->vx), vy(s->vy), vw(s->vw), vh(s->vh),
7624 opacity(s->opacity), WxF(s->WxF), VxF(s->VxF),
7625 clipEnabled(s->clipEnabled), bgMode(s->bgMode), painter(s->painter),
7626 layoutDirection(s->layoutDirection),
7627 composition_mode(s->composition_mode),
7628 emulationSpecifier(s->emulationSpecifier), changeFlags(0)
7630 dirtyFlags = s->dirtyFlags;
7633 QPainterState::QPainterState()
7634 : brushOrigin(0, 0), bgBrush(Qt::white), clipOperation(Qt::NoClip),
7636 wx(0), wy(0), ww(0), wh(0), vx(0), vy(0), vw(0), vh(0),
7637 opacity(1), WxF(false), VxF(false), clipEnabled(true),
7638 bgMode(Qt::TransparentMode), painter(0),
7639 layoutDirection(QGuiApplication::layoutDirection()),
7640 composition_mode(QPainter::CompositionMode_SourceOver),
7641 emulationSpecifier(0), changeFlags(0)
7646 QPainterState::~QPainterState()
7650 void QPainterState::init(QPainter *p) {
7651 bgBrush = Qt::white;
7652 bgMode = Qt::TransparentMode;
7656 wx = wy = ww = wh = 0;
7657 vx = vy = vw = vh = 0;
7660 brushOrigin = QPointF(0, 0);
7662 font = deviceFont = QFont();
7663 clipRegion = QRegion();
7664 clipPath = QPainterPath();
7665 clipOperation = Qt::NoClip;
7667 worldMatrix.reset();
7669 layoutDirection = QGuiApplication::layoutDirection();
7670 composition_mode = QPainter::CompositionMode_SourceOver;
7671 emulationSpecifier = 0;
7679 \fn void QPainter::drawImage(const QRectF &target, const QImage &image, const QRectF &source,
7680 Qt::ImageConversionFlags flags)
7682 Draws the rectangular portion \a source of the given \a image
7683 into the \a target rectangle in the paint device.
7685 \note The image is scaled to fit the rectangle, if both the image and rectangle size disagree.
7687 If the image needs to be modified to fit in a lower-resolution
7688 result (e.g. converting from 32-bit to 8-bit), use the \a flags to
7689 specify how you would prefer this to happen.
7694 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 20
7701 \fn void QPainter::drawImage(const QRect &target, const QImage &image, const QRect &source,
7702 Qt::ImageConversionFlags flags)
7705 Draws the rectangular portion \a source of the given \a image
7706 into the \a target rectangle in the paint device.
7708 \note The image is scaled to fit the rectangle, if both the image and rectangle size disagree.
7712 \fn void QPainter::drawImage(const QPointF &point, const QImage &image)
7716 Draws the given \a image at the given \a point.
7720 \fn void QPainter::drawImage(const QPoint &point, const QImage &image)
7724 Draws the given \a image at the given \a point.
7728 \fn void QPainter::drawImage(const QPointF &point, const QImage &image, const QRectF &source,
7729 Qt::ImageConversionFlags flags = 0)
7733 Draws the rectangular portion \a source of the given \a image with
7734 its origin at the given \a point.
7738 \fn void QPainter::drawImage(const QPoint &point, const QImage &image, const QRect &source,
7739 Qt::ImageConversionFlags flags = 0)
7742 Draws the rectangular portion \a source of the given \a image with
7743 its origin at the given \a point.
7747 \fn void QPainter::drawImage(const QRectF &rectangle, const QImage &image)
7751 Draws the given \a image into the given \a rectangle.
7753 \note The image is scaled to fit the rectangle, if both the image and rectangle size disagree.
7757 \fn void QPainter::drawImage(const QRect &rectangle, const QImage &image)
7761 Draws the given \a image into the given \a rectangle.
7763 \note The image is scaled to fit the rectangle, if both the image and rectangle size disagree.
7767 \fn void QPainter::drawImage(int x, int y, const QImage &image,
7768 int sx, int sy, int sw, int sh,
7769 Qt::ImageConversionFlags flags)
7772 Draws an image at (\a{x}, \a{y}) by copying a part of \a image into
7775 (\a{x}, \a{y}) specifies the top-left point in the paint device that is
7776 to be drawn onto. (\a{sx}, \a{sy}) specifies the top-left point in \a
7777 image that is to be drawn. The default is (0, 0).
7779 (\a{sw}, \a{sh}) specifies the size of the image that is to be drawn.
7780 The default, (0, 0) (and negative) means all the way to the
7781 bottom-right of the image.
7785 \class QPaintEngineState
7788 \brief The QPaintEngineState class provides information about the
7789 active paint engine's current state.
7792 QPaintEngineState records which properties that have changed since
7793 the last time the paint engine was updated, as well as their
7796 Which properties that have changed can at any time be retrieved
7797 using the state() function. This function returns an instance of
7798 the QPaintEngine::DirtyFlags type which stores an OR combination
7799 of QPaintEngine::DirtyFlag values. The QPaintEngine::DirtyFlag
7800 enum defines whether a property has changed since the last update
7803 If a property is marked with a dirty flag, its current value can
7804 be retrieved using the corresponding get function:
7809 \header \li Property Flag \li Current Property Value
7810 \row \li QPaintEngine::DirtyBackground \li backgroundBrush()
7811 \row \li QPaintEngine::DirtyBackgroundMode \li backgroundMode()
7812 \row \li QPaintEngine::DirtyBrush \li brush()
7813 \row \li QPaintEngine::DirtyBrushOrigin \li brushOrigin()
7814 \row \li QPaintEngine::DirtyClipRegion \e or QPaintEngine::DirtyClipPath
7816 \row \li QPaintEngine::DirtyClipPath \li clipPath()
7817 \row \li QPaintEngine::DirtyClipRegion \li clipRegion()
7818 \row \li QPaintEngine::DirtyCompositionMode \li compositionMode()
7819 \row \li QPaintEngine::DirtyFont \li font()
7820 \row \li QPaintEngine::DirtyTransform \li transform()
7821 \row \li QPaintEngine::DirtyClipEnabled \li isClipEnabled()
7822 \row \li QPaintEngine::DirtyPen \li pen()
7823 \row \li QPaintEngine::DirtyHints \li renderHints()
7826 The QPaintEngineState class also provide the painter() function
7827 which returns a pointer to the painter that is currently updating
7830 An instance of this class, representing the current state of the
7831 active paint engine, is passed as argument to the
7832 QPaintEngine::updateState() function. The only situation in which
7833 you will have to use this class directly is when implementing your
7841 \fn QPaintEngine::DirtyFlags QPaintEngineState::state() const
7843 Returns a combination of flags identifying the set of properties
7844 that need to be updated when updating the paint engine's state
7845 (i.e. during a call to the QPaintEngine::updateState() function).
7847 \sa QPaintEngine::updateState()
7852 Returns the pen in the current paint engine state.
7854 This variable should only be used when the state() returns a
7855 combination which includes the QPaintEngine::DirtyPen flag.
7857 \sa state(), QPaintEngine::updateState()
7860 QPen QPaintEngineState::pen() const
7862 return static_cast<const QPainterState *>(this)->pen;
7866 Returns the brush in the current paint engine state.
7868 This variable should only be used when the state() returns a
7869 combination which includes the QPaintEngine::DirtyBrush flag.
7871 \sa state(), QPaintEngine::updateState()
7874 QBrush QPaintEngineState::brush() const
7876 return static_cast<const QPainterState *>(this)->brush;
7880 Returns the brush origin in the current paint engine state.
7882 This variable should only be used when the state() returns a
7883 combination which includes the QPaintEngine::DirtyBrushOrigin flag.
7885 \sa state(), QPaintEngine::updateState()
7888 QPointF QPaintEngineState::brushOrigin() const
7890 return static_cast<const QPainterState *>(this)->brushOrigin;
7894 Returns the background brush in the current paint engine state.
7896 This variable should only be used when the state() returns a
7897 combination which includes the QPaintEngine::DirtyBackground flag.
7899 \sa state(), QPaintEngine::updateState()
7902 QBrush QPaintEngineState::backgroundBrush() const
7904 return static_cast<const QPainterState *>(this)->bgBrush;
7908 Returns the background mode in the current paint engine
7911 This variable should only be used when the state() returns a
7912 combination which includes the QPaintEngine::DirtyBackgroundMode flag.
7914 \sa state(), QPaintEngine::updateState()
7917 Qt::BGMode QPaintEngineState::backgroundMode() const
7919 return static_cast<const QPainterState *>(this)->bgMode;
7923 Returns the font in the current paint engine
7926 This variable should only be used when the state() returns a
7927 combination which includes the QPaintEngine::DirtyFont flag.
7929 \sa state(), QPaintEngine::updateState()
7932 QFont QPaintEngineState::font() const
7934 return static_cast<const QPainterState *>(this)->font;
7941 Returns the matrix in the current paint engine
7944 \note It is advisable to use transform() instead of this function to
7945 preserve the properties of perspective transformations.
7947 This variable should only be used when the state() returns a
7948 combination which includes the QPaintEngine::DirtyTransform flag.
7950 \sa state(), QPaintEngine::updateState()
7953 QMatrix QPaintEngineState::matrix() const
7955 const QPainterState *st = static_cast<const QPainterState *>(this);
7957 return st->matrix.toAffine();
7963 Returns the matrix in the current paint engine state.
7965 This variable should only be used when the state() returns a
7966 combination which includes the QPaintEngine::DirtyTransform flag.
7968 \sa state(), QPaintEngine::updateState()
7972 QTransform QPaintEngineState::transform() const
7974 const QPainterState *st = static_cast<const QPainterState *>(this);
7981 Returns the clip operation in the current paint engine
7984 This variable should only be used when the state() returns a
7985 combination which includes either the QPaintEngine::DirtyClipPath
7986 or the QPaintEngine::DirtyClipRegion flag.
7988 \sa state(), QPaintEngine::updateState()
7991 Qt::ClipOperation QPaintEngineState::clipOperation() const
7993 return static_cast<const QPainterState *>(this)->clipOperation;
7999 Returns whether the coordinate of the fill have been specified
8000 as bounded by the current rendering operation and have to be
8001 resolved (about the currently rendered primitive).
8003 bool QPaintEngineState::brushNeedsResolving() const
8005 const QBrush &brush = static_cast<const QPainterState *>(this)->brush;
8006 return needsResolving(brush);
8013 Returns whether the coordinate of the stroke have been specified
8014 as bounded by the current rendering operation and have to be
8015 resolved (about the currently rendered primitive).
8017 bool QPaintEngineState::penNeedsResolving() const
8019 const QPen &pen = static_cast<const QPainterState *>(this)->pen;
8020 return needsResolving(pen.brush());
8024 Returns the clip region in the current paint engine state.
8026 This variable should only be used when the state() returns a
8027 combination which includes the QPaintEngine::DirtyClipRegion flag.
8029 \sa state(), QPaintEngine::updateState()
8032 QRegion QPaintEngineState::clipRegion() const
8034 return static_cast<const QPainterState *>(this)->clipRegion;
8038 Returns the clip path in the current paint engine state.
8040 This variable should only be used when the state() returns a
8041 combination which includes the QPaintEngine::DirtyClipPath flag.
8043 \sa state(), QPaintEngine::updateState()
8046 QPainterPath QPaintEngineState::clipPath() const
8048 return static_cast<const QPainterState *>(this)->clipPath;
8052 Returns whether clipping is enabled or not in the current paint
8055 This variable should only be used when the state() returns a
8056 combination which includes the QPaintEngine::DirtyClipEnabled
8059 \sa state(), QPaintEngine::updateState()
8062 bool QPaintEngineState::isClipEnabled() const
8064 return static_cast<const QPainterState *>(this)->clipEnabled;
8068 Returns the render hints in the current paint engine state.
8070 This variable should only be used when the state() returns a
8071 combination which includes the QPaintEngine::DirtyHints
8074 \sa state(), QPaintEngine::updateState()
8077 QPainter::RenderHints QPaintEngineState::renderHints() const
8079 return static_cast<const QPainterState *>(this)->renderHints;
8083 Returns the composition mode in the current paint engine state.
8085 This variable should only be used when the state() returns a
8086 combination which includes the QPaintEngine::DirtyCompositionMode
8089 \sa state(), QPaintEngine::updateState()
8092 QPainter::CompositionMode QPaintEngineState::compositionMode() const
8094 return static_cast<const QPainterState *>(this)->composition_mode;
8099 Returns a pointer to the painter currently updating the paint
8103 QPainter *QPaintEngineState::painter() const
8105 return static_cast<const QPainterState *>(this)->painter;
8112 Returns the opacity in the current paint engine state.
8115 qreal QPaintEngineState::opacity() const
8117 return static_cast<const QPainterState *>(this)->opacity;
8123 Sets the world transformation matrix.
8124 If \a combine is true, the specified \a transform is combined with
8125 the current matrix; otherwise it replaces the current matrix.
8127 \sa transform() setWorldTransform()
8130 void QPainter::setTransform(const QTransform &transform, bool combine )
8132 setWorldTransform(transform, combine);
8136 Returns the world transformation matrix.
8138 \sa worldTransform()
8141 const QTransform & QPainter::transform() const
8143 return worldTransform();
8148 Returns the matrix that transforms from logical coordinates to
8149 device coordinates of the platform dependent paint device.
8151 This function is \e only needed when using platform painting
8152 commands on the platform dependent handle (Qt::HANDLE), and the
8153 platform does not do transformations nativly.
8155 The QPaintEngine::PaintEngineFeature enum can be queried to
8156 determine whether the platform performs the transformations or
8159 \sa worldTransform(), QPaintEngine::hasFeature(),
8162 const QTransform & QPainter::deviceTransform() const
8164 Q_D(const QPainter);
8166 qWarning("QPainter::deviceTransform: Painter not active");
8167 return d->fakeState()->transform;
8169 return d->state->matrix;
8174 Resets any transformations that were made using translate(),
8175 scale(), shear(), rotate(), setWorldTransform(), setViewport()
8178 \sa {Coordinate Transformations}
8181 void QPainter::resetTransform()
8184 #ifdef QT_DEBUG_DRAW
8185 if (qt_show_painter_debug_output)
8186 printf("QPainter::resetMatrix()\n");
8189 qWarning("QPainter::resetMatrix: Painter not active");
8193 d->state->wx = d->state->wy = d->state->vx = d->state->vy = 0; // default view origins
8194 d->state->ww = d->state->vw = d->device->metric(QPaintDevice::PdmWidth);
8195 d->state->wh = d->state->vh = d->device->metric(QPaintDevice::PdmHeight);
8196 d->state->worldMatrix = QTransform();
8197 setMatrixEnabled(false);
8198 setViewTransformEnabled(false);
8200 d->extended->transformChanged();
8202 d->state->dirtyFlags |= QPaintEngine::DirtyTransform;
8206 Sets the world transformation matrix.
8207 If \a combine is true, the specified \a matrix is combined with the current matrix;
8208 otherwise it replaces the current matrix.
8210 \sa transform(), setTransform()
8213 void QPainter::setWorldTransform(const QTransform &matrix, bool combine )
8218 qWarning("QPainter::setWorldTransform: Painter not active");
8223 d->state->worldMatrix = matrix * d->state->worldMatrix; // combines
8225 d->state->worldMatrix = matrix; // set new matrix
8227 d->state->WxF = true;
8232 Returns the world transformation matrix.
8235 const QTransform & QPainter::worldTransform() const
8237 Q_D(const QPainter);
8239 qWarning("QPainter::worldTransform: Painter not active");
8240 return d->fakeState()->transform;
8242 return d->state->worldMatrix;
8246 Returns the transformation matrix combining the current
8247 window/viewport and world transformation.
8249 \sa setWorldTransform(), setWindow(), setViewport()
8252 QTransform QPainter::combinedTransform() const
8254 Q_D(const QPainter);
8256 qWarning("QPainter::combinedTransform: Painter not active");
8257 return QTransform();
8259 return d->state->worldMatrix * d->viewTransform();
8265 This function is used to draw \a pixmap, or a sub-rectangle of \a pixmap,
8266 at multiple positions with different scale, rotation and opacity. \a
8267 fragments is an array of \a fragmentCount elements specifying the
8268 parameters used to draw each pixmap fragment. The \a hints
8269 parameter can be used to pass in drawing hints.
8271 This function is potentially faster than multiple calls to drawPixmap(),
8272 since the backend can optimize state changes.
8274 \sa QPainter::PixmapFragment, QPainter::PixmapFragmentHint
8277 void QPainter::drawPixmapFragments(const PixmapFragment *fragments, int fragmentCount,
8278 const QPixmap &pixmap, PixmapFragmentHints hints)
8282 if (!d->engine || pixmap.isNull())
8286 for (int i = 0; i < fragmentCount; ++i) {
8287 QRectF sourceRect(fragments[i].sourceLeft, fragments[i].sourceTop,
8288 fragments[i].width, fragments[i].height);
8289 if (!(QRectF(pixmap.rect()).contains(sourceRect)))
8290 qWarning("QPainter::drawPixmapFragments - the source rect is not contained by the pixmap's rectangle");
8294 if (d->engine->isExtended()) {
8295 d->extended->drawPixmapFragments(fragments, fragmentCount, pixmap, hints);
8297 qreal oldOpacity = opacity();
8298 QTransform oldTransform = transform();
8300 for (int i = 0; i < fragmentCount; ++i) {
8301 QTransform transform = oldTransform;
8304 if (fragments[i].rotation == 0) {
8305 xOffset = fragments[i].x;
8306 yOffset = fragments[i].y;
8308 transform.translate(fragments[i].x, fragments[i].y);
8309 transform.rotate(fragments[i].rotation);
8311 setOpacity(oldOpacity * fragments[i].opacity);
8312 setTransform(transform);
8314 qreal w = fragments[i].scaleX * fragments[i].width;
8315 qreal h = fragments[i].scaleY * fragments[i].height;
8316 QRectF sourceRect(fragments[i].sourceLeft, fragments[i].sourceTop,
8317 fragments[i].width, fragments[i].height);
8318 drawPixmap(QRectF(-0.5 * w + xOffset, -0.5 * h + yOffset, w, h), pixmap, sourceRect);
8321 setOpacity(oldOpacity);
8322 setTransform(oldTransform);
8328 \class QPainter::PixmapFragment
8330 \brief This class is used in conjunction with the
8331 QPainter::drawPixmapFragments() function to specify how a pixmap, or
8332 sub-rect of a pixmap, is drawn.
8334 The \a sourceLeft, \a sourceTop, \a width and \a height variables are used
8335 as a source rectangle within the pixmap passed into the
8336 QPainter::drawPixmapFragments() function. The variables \a x, \a y, \a
8337 width and \a height are used to calculate the target rectangle that is
8338 drawn. \a x and \a y denotes the center of the target rectangle. The \a
8339 width and \a height in the target rectangle is scaled by the \a scaleX and
8340 \a scaleY values. The resulting target rectangle is then rotated \a
8341 rotation degrees around the \a x, \a y center point.
8343 \sa QPainter::drawPixmapFragments()
8349 This is a convenience function that returns a QPainter::PixmapFragment that is
8350 initialized with the \a pos, \a sourceRect, \a scaleX, \a scaleY, \a
8351 rotation, \a opacity parameters.
8354 QPainter::PixmapFragment QPainter::PixmapFragment::create(const QPointF &pos, const QRectF &sourceRect,
8355 qreal scaleX, qreal scaleY, qreal rotation,
8358 PixmapFragment fragment = {pos.x(), pos.y(), sourceRect.x(), sourceRect.y(), sourceRect.width(),
8359 sourceRect.height(), scaleX, scaleY, rotation, opacity};
8364 \variable QPainter::PixmapFragment::x
8365 \brief the x coordinate of center point in the target rectangle.
8369 \variable QPainter::PixmapFragment::y
8370 \brief the y coordinate of the center point in the target rectangle.
8374 \variable QPainter::PixmapFragment::sourceLeft
8375 \brief the left coordinate of the source rectangle.
8379 \variable QPainter::PixmapFragment::sourceTop
8380 \brief the top coordinate of the source rectangle.
8384 \variable QPainter::PixmapFragment::width
8386 \brief the width of the source rectangle and is used to calculate the width
8387 of the target rectangle.
8391 \variable QPainter::PixmapFragment::height
8393 \brief the height of the source rectangle and is used to calculate the
8394 height of the target rectangle.
8398 \variable QPainter::PixmapFragment::scaleX
8399 \brief the horizontal scale of the target rectangle.
8403 \variable QPainter::PixmapFragment::scaleY
8404 \brief the vertical scale of the target rectangle.
8408 \variable QPainter::PixmapFragment::rotation
8410 \brief the rotation of the target rectangle in degrees. The target
8411 rectangle is rotated after it has been scaled.
8415 \variable QPainter::PixmapFragment::opacity
8417 \brief the opacity of the target rectangle, where 0.0 is fully transparent
8418 and 1.0 is fully opaque.
8424 \enum QPainter::PixmapFragmentHint
8426 \value OpaqueHint Indicates that the pixmap fragments to be drawn are
8427 opaque. Opaque fragments are potentially faster to draw.
8429 \sa QPainter::drawPixmapFragments(), QPainter::PixmapFragment
8432 void qt_draw_helper(QPainterPrivate *p, const QPainterPath &path, QPainterPrivate::DrawOperation operation)
8434 p->draw_helper(path, operation);