1 /****************************************************************************
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the QtGui module of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** 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 "qapplication.h"
63 #include "qvarlengtharray.h"
64 #include "qstatictext.h"
65 #include "qglyphrun.h"
67 #include <private/qfontengine_p.h>
68 #include <private/qpaintengine_p.h>
69 #include <private/qemulationpaintengine_p.h>
70 #include <private/qpainterpath_p.h>
71 #include <private/qtextengine_p.h>
72 #include <private/qwidget_p.h>
73 #include <private/qpaintengine_raster_p.h>
74 #include <private/qmath_p.h>
75 #include <private/qstatictext_p.h>
76 #include <private/qglyphrun_p.h>
77 #include <private/qstylehelper_p.h>
78 #include <private/qrawfont_p.h>
82 #define QGradient_StretchToDevice 0x10000000
83 #define QPaintEngine_OpaqueBackground 0x40000000
85 // #define QT_DEBUG_DRAW
87 bool qt_show_painter_debug_output = true;
90 extern QPixmap qt_pixmapForBrush(int style, bool invert);
92 void qt_format_text(const QFont &font,
93 const QRectF &_r, int tf, const QTextOption *option, const QString& str, QRectF *brect,
94 int tabstops, int* tabarray, int tabarraylen,
96 static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const QFontEngine *fe,
97 QTextCharFormat::UnderlineStyle underlineStyle,
98 QTextItem::RenderFlags flags, qreal width,
99 const QTextCharFormat &charFormat);
100 // Helper function to calculate left most position, width and flags for decoration drawing
101 Q_GUI_EXPORT void qt_draw_decoration_for_glyphs(QPainter *painter, const glyph_t *glyphArray,
102 const QFixedPoint *positions, int glyphCount,
103 QFontEngine *fontEngine, const QFont &font,
104 const QTextCharFormat &charFormat);
106 static inline QGradient::CoordinateMode coordinateMode(const QBrush &brush)
108 switch (brush.style()) {
109 case Qt::LinearGradientPattern:
110 case Qt::RadialGradientPattern:
111 case Qt::ConicalGradientPattern:
112 return brush.gradient()->coordinateMode();
116 return QGradient::LogicalMode;
119 /* Returns true if the gradient requires stretch to device...*/
120 static inline bool check_gradient(const QBrush &brush)
122 return coordinateMode(brush) == QGradient::StretchToDeviceMode;
125 extern bool qHasPixmapTexture(const QBrush &);
127 static inline bool is_brush_transparent(const QBrush &brush) {
128 Qt::BrushStyle s = brush.style();
129 bool brushBitmap = qHasPixmapTexture(brush)
130 ? brush.texture().isQBitmap()
131 : (brush.textureImage().depth() == 1);
132 return ((s >= Qt::Dense1Pattern && s <= Qt::DiagCrossPattern)
133 || (s == Qt::TexturePattern && brushBitmap));
136 static inline bool is_pen_transparent(const QPen &pen) {
137 return pen.style() > Qt::SolidLine || is_brush_transparent(pen.brush());
140 /* Discards the emulation flags that are not relevant for line drawing
141 and returns the result
143 static inline uint line_emulation(uint emulation)
145 return emulation & (QPaintEngine::PrimitiveTransform
146 | QPaintEngine::AlphaBlend
147 | QPaintEngine::Antialiasing
148 | QPaintEngine::BrushStroke
149 | QPaintEngine::ConstantOpacity
150 | QGradient_StretchToDevice
151 | QPaintEngine::ObjectBoundingModeGradients
152 | QPaintEngine_OpaqueBackground);
156 static bool qt_painter_thread_test(int devType, const char *what, bool extraCondition = false)
159 case QInternal::Image:
160 case QInternal::Printer:
161 case QInternal::Picture:
162 // can be drawn onto these devices safely from any thread
169 if (QApplication::testAttribute(Qt::AA_X11InitThreads))
172 if (!extraCondition && QThread::currentThread() != qApp->thread()) {
173 qWarning("QPainter: It is not safe to use %s outside the GUI thread", what);
182 void QPainterPrivate::checkEmulation()
185 if (extended->flags() & QPaintEngineEx::DoNotEmulate)
188 bool doEmulation = false;
189 if (state->bgMode == Qt::OpaqueMode)
192 const QGradient *bg = state->brush.gradient();
193 if (bg && bg->coordinateMode() > QGradient::LogicalMode)
196 const QGradient *pg = qpen_brush(state->pen).gradient();
197 if (pg && pg->coordinateMode() > QGradient::LogicalMode)
201 if (extended != emulationEngine) {
202 if (!emulationEngine)
203 emulationEngine = new QEmulationPaintEngine(extended);
204 extended = emulationEngine;
205 extended->setState(state);
207 } else if (emulationEngine == extended) {
208 extended = emulationEngine->real_engine;
213 QPainterPrivate::~QPainterPrivate()
215 delete emulationEngine;
216 for (int i=0; i<states.size(); ++i)
224 QTransform QPainterPrivate::viewTransform() const
227 qreal scaleW = qreal(state->vw)/qreal(state->ww);
228 qreal scaleH = qreal(state->vh)/qreal(state->wh);
229 return QTransform(scaleW, 0, 0, scaleH,
230 state->vx - state->wx*scaleW, state->vy - state->wy*scaleH);
238 Returns true if using a shared painter; otherwise false.
240 bool QPainterPrivate::attachPainterPrivate(QPainter *q, QPaintDevice *pdev)
245 if (pdev->devType() != QInternal::Widget)
248 QWidget *widget = static_cast<QWidget *>(pdev);
251 // Someone either called QPainter::setRedirected in the widget's paint event
252 // right before this painter was created (or begin was called) or
253 // sent a paint event directly to the widget.
254 if (!widget->d_func()->redirectDev)
257 QPainter *sp = widget->d_func()->sharedPainter();
258 if (!sp || !sp->isActive())
261 if (sp->paintEngine()->paintDevice() != widget->d_func()->redirectDev)
264 // Check if we're attempting to paint outside a paint event.
265 if (!sp->d_ptr->engine->hasFeature(QPaintEngine::PaintOutsidePaintEvent)
266 && !widget->testAttribute(Qt::WA_PaintOutsidePaintEvent)
267 && !widget->testAttribute(Qt::WA_WState_InPaintEvent)) {
269 qWarning("QPainter::begin: Widget painting can only begin as a result of a paintEvent");
273 // Save the current state of the shared painter and assign
274 // the current d_ptr to the shared painter's d_ptr.
276 if (!sp->d_ptr->d_ptrs) {
277 // Allocate space for 4 d-pointers (enough for up to 4 sub-sequent
278 // redirections within the same paintEvent(), which should be enough
279 // in 99% of all cases). E.g: A renders B which renders C which renders D.
280 sp->d_ptr->d_ptrs_size = 4;
281 sp->d_ptr->d_ptrs = (QPainterPrivate **)malloc(4 * sizeof(QPainterPrivate *));
282 Q_CHECK_PTR(sp->d_ptr->d_ptrs);
283 } else if (sp->d_ptr->refcount - 1 == sp->d_ptr->d_ptrs_size) {
284 // However, to support corner cases we grow the array dynamically if needed.
285 sp->d_ptr->d_ptrs_size <<= 1;
286 const int newSize = sp->d_ptr->d_ptrs_size * sizeof(QPainterPrivate *);
287 sp->d_ptr->d_ptrs = q_check_ptr((QPainterPrivate **)realloc(sp->d_ptr->d_ptrs, newSize));
289 sp->d_ptr->d_ptrs[++sp->d_ptr->refcount - 2] = q->d_ptr.data();
291 q->d_ptr.reset(sp->d_ptr.data());
293 Q_ASSERT(q->d_ptr->state);
295 // Now initialize the painter with correct widget properties.
298 widget->d_func()->redirected(&offset);
299 offset += q->d_ptr->engine->coordinateOffset();
301 // Update system rect.
302 q->d_ptr->state->ww = q->d_ptr->state->vw = widget->width();
303 q->d_ptr->state->wh = q->d_ptr->state->vh = widget->height();
306 if (q->d_ptr->state->WxF) {
307 q->d_ptr->state->redirectionMatrix = q->d_ptr->state->matrix;
308 q->d_ptr->state->redirectionMatrix.translate(-offset.x(), -offset.y());
309 q->d_ptr->state->worldMatrix = QTransform();
310 q->d_ptr->state->WxF = false;
312 q->d_ptr->state->redirectionMatrix = QTransform::fromTranslate(-offset.x(), -offset.y());
314 q->d_ptr->updateMatrix();
316 QPaintEnginePrivate *enginePrivate = q->d_ptr->engine->d_func();
317 if (enginePrivate->currentClipWidget == widget) {
318 enginePrivate->systemStateChanged();
322 // Update system transform and clip.
323 enginePrivate->currentClipWidget = widget;
324 enginePrivate->setSystemTransform(q->d_ptr->state->matrix);
328 void QPainterPrivate::detachPainterPrivate(QPainter *q)
330 Q_ASSERT(refcount > 1);
333 QPainterPrivate *original = d_ptrs[--refcount - 1];
335 inDestructor = false;
337 original->inDestructor = true;
338 } else if (!original) {
339 original = new QPainterPrivate(q);
342 d_ptrs[refcount - 1] = 0;
345 q->d_ptr.reset(original);
347 if (emulationEngine) {
348 extended = emulationEngine->real_engine;
349 delete emulationEngine;
355 void QPainterPrivate::draw_helper(const QPainterPath &originalPath, DrawOperation op)
358 if (qt_show_painter_debug_output) {
359 printf("QPainter::drawHelper\n");
363 if (originalPath.isEmpty())
366 QPaintEngine::PaintEngineFeatures gradientStretch =
367 QPaintEngine::PaintEngineFeatures(QGradient_StretchToDevice
368 | QPaintEngine::ObjectBoundingModeGradients);
370 const bool mustEmulateObjectBoundingModeGradients = extended
371 || ((state->emulationSpecifier & QPaintEngine::ObjectBoundingModeGradients)
372 && !engine->hasFeature(QPaintEngine::PatternTransform));
374 if (!(state->emulationSpecifier & ~gradientStretch)
375 && !mustEmulateObjectBoundingModeGradients) {
376 drawStretchedGradient(originalPath, op);
378 } else if (state->emulationSpecifier & QPaintEngine_OpaqueBackground) {
379 drawOpaqueBackground(originalPath, op);
385 qreal strokeOffsetX = 0, strokeOffsetY = 0;
387 QPainterPath path = originalPath * state->matrix;
388 QRectF pathBounds = path.boundingRect();
390 bool doStroke = (op & StrokeDraw) && (state->pen.style() != Qt::NoPen);
392 qreal penWidth = state->pen.widthF();
397 // In case of complex xform
398 if (state->matrix.type() > QTransform::TxScale) {
399 QPainterPathStroker stroker;
400 stroker.setWidth(penWidth);
401 stroker.setJoinStyle(state->pen.joinStyle());
402 stroker.setCapStyle(state->pen.capStyle());
403 QPainterPath stroke = stroker.createStroke(originalPath);
404 strokeBounds = (stroke * state->matrix).boundingRect();
406 strokeOffsetX = qAbs(penWidth * state->matrix.m11() / 2.0);
407 strokeOffsetY = qAbs(penWidth * state->matrix.m22() / 2.0);
413 if (!strokeBounds.isEmpty()) {
414 absPathRect = strokeBounds.intersected(QRectF(0, 0, device->width(), device->height())).toAlignedRect();
416 absPathRect = pathBounds.adjusted(-strokeOffsetX, -strokeOffsetY, strokeOffsetX, strokeOffsetY)
417 .intersected(QRectF(0, 0, device->width(), device->height())).toAlignedRect();
420 if (q->hasClipping()) {
421 bool hasPerspectiveTransform = false;
422 for (int i = 0; i < state->clipInfo.size(); ++i) {
423 const QPainterClipInfo &info = state->clipInfo.at(i);
424 if (info.matrix.type() == QTransform::TxProject) {
425 hasPerspectiveTransform = true;
429 // avoid mapping QRegions with perspective transforms
430 if (!hasPerspectiveTransform) {
431 // The trick with txinv and invMatrix is done in order to
432 // avoid transforming the clip to logical coordinates, and
433 // then back to device coordinates. This is a problem with
434 // QRegion/QRect based clips, since they use integer
435 // coordinates and converting to/from logical coordinates will
437 bool old_txinv = txinv;
438 QTransform old_invMatrix = invMatrix;
440 invMatrix = QTransform();
441 QPainterPath clipPath = q->clipPath();
442 QRectF r = clipPath.boundingRect().intersected(absPathRect);
443 absPathRect = r.toAlignedRect();
445 invMatrix = old_invMatrix;
449 // qDebug("\nQPainterPrivate::draw_helper(), x=%d, y=%d, w=%d, h=%d",
450 // devMinX, devMinY, device->width(), device->height());
451 // qDebug() << " - matrix" << state->matrix;
452 // qDebug() << " - originalPath.bounds" << originalPath.boundingRect();
453 // qDebug() << " - path.bounds" << path.boundingRect();
455 if (absPathRect.width() <= 0 || absPathRect.height() <= 0)
458 QImage image(absPathRect.width(), absPathRect.height(), QImage::Format_ARGB32_Premultiplied);
463 p.d_ptr->helper_device = helper_device;
465 p.setOpacity(state->opacity);
466 p.translate(-absPathRect.x(), -absPathRect.y());
467 p.setTransform(state->matrix, true);
468 p.setPen(doStroke ? state->pen : QPen(Qt::NoPen));
469 p.setBrush((op & FillDraw) ? state->brush : QBrush(Qt::NoBrush));
470 p.setBackground(state->bgBrush);
471 p.setBackgroundMode(state->bgMode);
472 p.setBrushOrigin(state->brushOrigin);
474 p.setRenderHint(QPainter::Antialiasing, state->renderHints & QPainter::Antialiasing);
475 p.setRenderHint(QPainter::SmoothPixmapTransform,
476 state->renderHints & QPainter::SmoothPixmapTransform);
478 p.drawPath(originalPath);
481 static bool do_fallback_overlay = qgetenv("QT_PAINT_FALLBACK_OVERLAY").size() > 0;
482 if (do_fallback_overlay) {
483 QImage block(8, 8, QImage::Format_ARGB32_Premultiplied);
485 pt.fillRect(0, 0, 8, 8, QColor(196, 0, 196));
486 pt.drawLine(0, 0, 8, 8);
489 p.setCompositionMode(QPainter::CompositionMode_SourceAtop);
491 p.fillRect(0, 0, image.width(), image.height(), QBrush(block));
498 state->matrix = QTransform();
500 extended->transformChanged();
502 state->dirtyFlags |= QPaintEngine::DirtyTransform;
505 engine->drawImage(absPathRect,
507 QRectF(0, 0, absPathRect.width(), absPathRect.height()),
508 Qt::OrderedDither | Qt::OrderedAlphaDither);
512 void QPainterPrivate::drawOpaqueBackground(const QPainterPath &path, DrawOperation op)
516 q->setBackgroundMode(Qt::TransparentMode);
518 if (op & FillDraw && state->brush.style() != Qt::NoBrush) {
519 q->fillPath(path, state->bgBrush.color());
520 q->fillPath(path, state->brush);
523 if (op & StrokeDraw && state->pen.style() != Qt::NoPen) {
524 q->strokePath(path, QPen(state->bgBrush.color(), state->pen.width()));
525 q->strokePath(path, state->pen);
528 q->setBackgroundMode(Qt::OpaqueMode);
531 static inline QBrush stretchGradientToUserSpace(const QBrush &brush, const QRectF &boundingRect)
533 Q_ASSERT(brush.style() >= Qt::LinearGradientPattern
534 && brush.style() <= Qt::ConicalGradientPattern);
536 QTransform gradientToUser(boundingRect.width(), 0, 0, boundingRect.height(),
537 boundingRect.x(), boundingRect.y());
539 QGradient g = *brush.gradient();
540 g.setCoordinateMode(QGradient::LogicalMode);
543 b.setTransform(gradientToUser * b.transform());
547 void QPainterPrivate::drawStretchedGradient(const QPainterPath &path, DrawOperation op)
551 const qreal sw = helper_device->width();
552 const qreal sh = helper_device->height();
554 bool changedPen = false;
555 bool changedBrush = false;
556 bool needsFill = false;
558 const QPen pen = state->pen;
559 const QBrush brush = state->brush;
561 const QGradient::CoordinateMode penMode = coordinateMode(pen.brush());
562 const QGradient::CoordinateMode brushMode = coordinateMode(brush);
566 // Draw the xformed fill if the brush is a stretch gradient.
567 if ((op & FillDraw) && brush.style() != Qt::NoBrush) {
568 if (brushMode == QGradient::StretchToDeviceMode) {
569 q->setPen(Qt::NoPen);
570 changedPen = pen.style() != Qt::NoPen;
574 const qreal isw = 1.0 / sw;
575 const qreal ish = 1.0 / sh;
576 QTransform inv(isw, 0, 0, ish, 0, 0);
577 engine->drawPath(path * inv);
582 if (brushMode == QGradient::ObjectBoundingMode) {
583 Q_ASSERT(engine->hasFeature(QPaintEngine::PatternTransform));
584 boundingRect = path.boundingRect();
585 q->setBrush(stretchGradientToUserSpace(brush, boundingRect));
591 if ((op & StrokeDraw) && pen.style() != Qt::NoPen) {
592 // Draw the xformed outline if the pen is a stretch gradient.
593 if (penMode == QGradient::StretchToDeviceMode) {
594 q->setPen(Qt::NoPen);
599 engine->drawPath(path);
603 q->setBrush(pen.brush());
607 QPainterPathStroker stroker;
608 stroker.setDashPattern(pen.style());
609 stroker.setWidth(pen.widthF());
610 stroker.setJoinStyle(pen.joinStyle());
611 stroker.setCapStyle(pen.capStyle());
612 stroker.setMiterLimit(pen.miterLimit());
613 QPainterPath stroke = stroker.createStroke(path);
615 const qreal isw = 1.0 / sw;
616 const qreal ish = 1.0 / sh;
617 QTransform inv(isw, 0, 0, ish, 0, 0);
618 engine->drawPath(stroke * inv);
621 if (!needsFill && brush.style() != Qt::NoBrush) {
622 q->setBrush(Qt::NoBrush);
626 if (penMode == QGradient::ObjectBoundingMode) {
627 Q_ASSERT(engine->hasFeature(QPaintEngine::PatternTransform));
629 // avoid computing the bounding rect twice
630 if (!needsFill || brushMode != QGradient::ObjectBoundingMode)
631 boundingRect = path.boundingRect();
634 p.setBrush(stretchGradientToUserSpace(pen.brush(), boundingRect));
637 } else if (changedPen) {
643 engine->drawPath(path);
645 } else if (needsFill) {
646 if (pen.style() != Qt::NoPen) {
647 q->setPen(Qt::NoPen);
652 engine->drawPath(path);
662 void QPainterPrivate::updateMatrix()
664 state->matrix = state->WxF ? state->worldMatrix : QTransform();
666 state->matrix *= viewTransform();
668 txinv = false; // no inverted matrix
669 state->matrix *= state->redirectionMatrix;
671 extended->transformChanged();
673 state->dirtyFlags |= QPaintEngine::DirtyTransform;
675 // printf("VxF=%d, WxF=%d\n", state->VxF, state->WxF);
676 // qDebug() << " --- using matrix" << state->matrix << redirection_offset;
680 void QPainterPrivate::updateInvMatrix()
682 Q_ASSERT(txinv == false);
683 txinv = true; // creating inverted matrix
684 invMatrix = state->matrix.inverted();
687 extern bool qt_isExtendedRadialGradient(const QBrush &brush);
689 void QPainterPrivate::updateEmulationSpecifier(QPainterState *s)
692 bool linearGradient = false;
693 bool radialGradient = false;
694 bool extendedRadialGradient = false;
695 bool conicalGradient = false;
696 bool patternBrush = false;
698 bool complexXform = false;
702 // Pen and brush properties (we have to check both if one changes because the
703 // one that's unchanged can still be in a state which requires emulation)
704 if (s->state() & (QPaintEngine::DirtyPen | QPaintEngine::DirtyBrush | QPaintEngine::DirtyHints)) {
705 // Check Brush stroke emulation
706 if (!s->pen.isSolid() && !engine->hasFeature(QPaintEngine::BrushStroke))
707 s->emulationSpecifier |= QPaintEngine::BrushStroke;
709 s->emulationSpecifier &= ~QPaintEngine::BrushStroke;
713 QBrush penBrush = (qpen_style(s->pen) == Qt::NoPen) ? QBrush(Qt::NoBrush) : qpen_brush(s->pen);
714 Qt::BrushStyle brushStyle = qbrush_style(s->brush);
715 Qt::BrushStyle penBrushStyle = qbrush_style(penBrush);
716 alpha = (penBrushStyle != Qt::NoBrush
717 && (penBrushStyle < Qt::LinearGradientPattern && penBrush.color().alpha() != 255)
718 && !penBrush.isOpaque())
719 || (brushStyle != Qt::NoBrush
720 && (brushStyle < Qt::LinearGradientPattern && s->brush.color().alpha() != 255)
721 && !s->brush.isOpaque());
722 linearGradient = ((penBrushStyle == Qt::LinearGradientPattern) ||
723 (brushStyle == Qt::LinearGradientPattern));
724 radialGradient = ((penBrushStyle == Qt::RadialGradientPattern) ||
725 (brushStyle == Qt::RadialGradientPattern));
726 extendedRadialGradient = radialGradient && (qt_isExtendedRadialGradient(penBrush) || qt_isExtendedRadialGradient(s->brush));
727 conicalGradient = ((penBrushStyle == Qt::ConicalGradientPattern) ||
728 (brushStyle == Qt::ConicalGradientPattern));
729 patternBrush = (((penBrushStyle > Qt::SolidPattern
730 && penBrushStyle < Qt::LinearGradientPattern)
731 || penBrushStyle == Qt::TexturePattern) ||
732 ((brushStyle > Qt::SolidPattern
733 && brushStyle < Qt::LinearGradientPattern)
734 || brushStyle == Qt::TexturePattern));
736 bool penTextureAlpha = false;
737 if (penBrush.style() == Qt::TexturePattern)
738 penTextureAlpha = qHasPixmapTexture(penBrush)
739 ? (penBrush.texture().depth() > 1) && penBrush.texture().hasAlpha()
740 : penBrush.textureImage().hasAlphaChannel();
741 bool brushTextureAlpha = false;
742 if (s->brush.style() == Qt::TexturePattern) {
743 brushTextureAlpha = qHasPixmapTexture(s->brush)
744 ? (s->brush.texture().depth() > 1) && s->brush.texture().hasAlpha()
745 : s->brush.textureImage().hasAlphaChannel();
747 if (((penBrush.style() == Qt::TexturePattern && penTextureAlpha)
748 || (s->brush.style() == Qt::TexturePattern && brushTextureAlpha))
749 && !engine->hasFeature(QPaintEngine::MaskedBrush))
750 s->emulationSpecifier |= QPaintEngine::MaskedBrush;
752 s->emulationSpecifier &= ~QPaintEngine::MaskedBrush;
755 if (s->state() & (QPaintEngine::DirtyHints
756 | QPaintEngine::DirtyOpacity
757 | QPaintEngine::DirtyBackgroundMode)) {
765 qDebug("QPainterPrivate::updateEmulationSpecifier, state=%p\n"
767 " - linearGradient: %d\n"
768 " - radialGradient: %d\n"
769 " - conicalGradient: %d\n"
770 " - patternBrush: %d\n"
779 uint(s->renderHints),
784 if (s->state() & QPaintEngine::DirtyTransform) {
785 xform = !s->matrix.isIdentity();
786 complexXform = !s->matrix.isAffine();
787 } else if (s->matrix.type() >= QTransform::TxTranslate) {
789 complexXform = !s->matrix.isAffine();
792 const bool brushXform = (!s->brush.transform().type() == QTransform::TxNone);
793 const bool penXform = (!s->pen.brush().transform().type() == QTransform::TxNone);
795 const bool patternXform = patternBrush && (xform || brushXform || penXform);
797 // Check alphablending
798 if (alpha && !engine->hasFeature(QPaintEngine::AlphaBlend))
799 s->emulationSpecifier |= QPaintEngine::AlphaBlend;
801 s->emulationSpecifier &= ~QPaintEngine::AlphaBlend;
803 // Linear gradient emulation
804 if (linearGradient && !engine->hasFeature(QPaintEngine::LinearGradientFill))
805 s->emulationSpecifier |= QPaintEngine::LinearGradientFill;
807 s->emulationSpecifier &= ~QPaintEngine::LinearGradientFill;
809 // Radial gradient emulation
810 if (extendedRadialGradient || (radialGradient && !engine->hasFeature(QPaintEngine::RadialGradientFill)))
811 s->emulationSpecifier |= QPaintEngine::RadialGradientFill;
813 s->emulationSpecifier &= ~QPaintEngine::RadialGradientFill;
815 // Conical gradient emulation
816 if (conicalGradient && !engine->hasFeature(QPaintEngine::ConicalGradientFill))
817 s->emulationSpecifier |= QPaintEngine::ConicalGradientFill;
819 s->emulationSpecifier &= ~QPaintEngine::ConicalGradientFill;
822 if (patternBrush && !engine->hasFeature(QPaintEngine::PatternBrush))
823 s->emulationSpecifier |= QPaintEngine::PatternBrush;
825 s->emulationSpecifier &= ~QPaintEngine::PatternBrush;
828 if (patternXform && !engine->hasFeature(QPaintEngine::PatternTransform))
829 s->emulationSpecifier |= QPaintEngine::PatternTransform;
831 s->emulationSpecifier &= ~QPaintEngine::PatternTransform;
834 if (xform && !engine->hasFeature(QPaintEngine::PrimitiveTransform))
835 s->emulationSpecifier |= QPaintEngine::PrimitiveTransform;
837 s->emulationSpecifier &= ~QPaintEngine::PrimitiveTransform;
839 // Perspective XForms
840 if (complexXform && !engine->hasFeature(QPaintEngine::PerspectiveTransform))
841 s->emulationSpecifier |= QPaintEngine::PerspectiveTransform;
843 s->emulationSpecifier &= ~QPaintEngine::PerspectiveTransform;
846 if (state->opacity != 1 && !engine->hasFeature(QPaintEngine::ConstantOpacity))
847 s->emulationSpecifier |= QPaintEngine::ConstantOpacity;
849 s->emulationSpecifier &= ~QPaintEngine::ConstantOpacity;
851 bool gradientStretch = false;
852 bool objectBoundingMode = false;
853 if (linearGradient || conicalGradient || radialGradient) {
854 QGradient::CoordinateMode brushMode = coordinateMode(s->brush);
855 QGradient::CoordinateMode penMode = coordinateMode(s->pen.brush());
857 gradientStretch |= (brushMode == QGradient::StretchToDeviceMode);
858 gradientStretch |= (penMode == QGradient::StretchToDeviceMode);
860 objectBoundingMode |= (brushMode == QGradient::ObjectBoundingMode);
861 objectBoundingMode |= (penMode == QGradient::ObjectBoundingMode);
864 s->emulationSpecifier |= QGradient_StretchToDevice;
866 s->emulationSpecifier &= ~QGradient_StretchToDevice;
868 if (objectBoundingMode && !engine->hasFeature(QPaintEngine::ObjectBoundingModeGradients))
869 s->emulationSpecifier |= QPaintEngine::ObjectBoundingModeGradients;
871 s->emulationSpecifier &= ~QPaintEngine::ObjectBoundingModeGradients;
873 // Opaque backgrounds...
874 if (s->bgMode == Qt::OpaqueMode &&
875 (is_pen_transparent(s->pen) || is_brush_transparent(s->brush)))
876 s->emulationSpecifier |= QPaintEngine_OpaqueBackground;
878 s->emulationSpecifier &= ~QPaintEngine_OpaqueBackground;
881 //won't be correct either way because the device can already have
882 // something rendered to it in which case subsequent emulation
883 // on a fully transparent qimage and then blitting the results
884 // won't produce correct results
886 if (state->composition_mode > QPainter::CompositionMode_Xor &&
887 !engine->hasFeature(QPaintEngine::BlendModes))
888 s->emulationSpecifier |= QPaintEngine::BlendModes;
890 s->emulationSpecifier &= ~QPaintEngine::BlendModes;
894 void QPainterPrivate::updateStateImpl(QPainterState *newState)
896 // ### we might have to call QPainter::begin() here...
897 if (!engine->state) {
898 engine->state = newState;
899 engine->setDirty(QPaintEngine::AllDirty);
902 if (engine->state->painter() != newState->painter)
903 // ### this could break with clip regions vs paths.
904 engine->setDirty(QPaintEngine::AllDirty);
906 // Upon restore, revert all changes since last save
907 else if (engine->state != newState)
908 newState->dirtyFlags |= QPaintEngine::DirtyFlags(static_cast<QPainterState *>(engine->state)->changeFlags);
910 // We need to store all changes made so that restore can deal with them
912 newState->changeFlags |= newState->dirtyFlags;
914 updateEmulationSpecifier(newState);
916 // Unset potential dirty background mode
917 newState->dirtyFlags &= ~(QPaintEngine::DirtyBackgroundMode
918 | QPaintEngine::DirtyBackground);
920 engine->state = newState;
921 engine->updateState(*newState);
922 engine->clearDirty(QPaintEngine::AllDirty);
926 void QPainterPrivate::updateState(QPainterState *newState)
930 engine->state = newState;
932 } else if (newState->state() || engine->state!=newState) {
933 bool setNonCosmeticPen = (newState->renderHints & QPainter::NonCosmeticDefaultPen)
934 && newState->pen.widthF() == 0;
935 if (setNonCosmeticPen) {
936 // Override the default pen's cosmetic state if the
937 // NonCosmeticDefaultPen render hint is used.
938 QPen oldPen = newState->pen;
939 newState->pen.setWidth(1);
940 newState->pen.setCosmetic(false);
941 newState->dirtyFlags |= QPaintEngine::DirtyPen;
943 updateStateImpl(newState);
945 // Restore the state pen back to its default to preserve visible
947 newState->pen = oldPen;
949 updateStateImpl(newState);
957 \brief The QPainter class performs low-level painting on widgets and
964 QPainter provides highly optimized functions to do most of the
965 drawing GUI programs require. It can draw everything from simple
966 lines to complex shapes like pies and chords. It can also draw
967 aligned text and pixmaps. Normally, it draws in a "natural"
968 coordinate system, but it can also do view and world
969 transformation. QPainter can operate on any object that inherits
970 the QPaintDevice class.
972 The common use of QPainter is inside a widget's paint event:
973 Construct and customize (e.g. set the pen or the brush) the
974 painter. Then draw. Remember to destroy the QPainter object after
975 drawing. For example:
977 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 0
979 The core functionality of QPainter is drawing, but the class also
980 provide several functions that allows you to customize QPainter's
981 settings and its rendering quality, and others that enable
982 clipping. In addition you can control how different shapes are
983 merged together by specifying the painter's composition mode.
985 The isActive() function indicates whether the painter is active. A
986 painter is activated by the begin() function and the constructor
987 that takes a QPaintDevice argument. The end() function, and the
988 destructor, deactivates it.
990 Together with the QPaintDevice and QPaintEngine classes, QPainter
991 form the basis for Qt's paint system. QPainter is the class used
992 to perform drawing operations. QPaintDevice represents a device
993 that can be painted on using a QPainter. QPaintEngine provides the
994 interface that the painter uses to draw onto different types of
995 devices. If the painter is active, device() returns the paint
996 device on which the painter paints, and paintEngine() returns the
997 paint engine that the painter is currently operating on. For more
998 information, see the \l {Paint System}.
1000 Sometimes it is desirable to make someone else paint on an unusual
1001 QPaintDevice. QPainter supports a static function to do this,
1004 \warning When the paintdevice is a widget, QPainter can only be
1005 used inside a paintEvent() function or in a function called by
1006 paintEvent(); that is unless the Qt::WA_PaintOutsidePaintEvent
1007 widget attribute is set. On Mac OS X and Windows, you can only
1008 paint in a paintEvent() function regardless of this attribute's
1015 There are several settings that you can customize to make QPainter
1016 draw according to your preferences:
1020 \o font() is the font used for drawing text. If the painter
1021 isActive(), you can retrieve information about the currently set
1022 font, and its metrics, using the fontInfo() and fontMetrics()
1023 functions respectively.
1025 \o brush() defines the color or pattern that is used for filling
1028 \o pen() defines the color or stipple that is used for drawing
1029 lines or boundaries.
1031 \o backgroundMode() defines whether there is a background() or
1032 not, i.e it is either Qt::OpaqueMode or Qt::TransparentMode.
1034 \o background() only applies when backgroundMode() is \l
1035 Qt::OpaqueMode and pen() is a stipple. In that case, it
1036 describes the color of the background pixels in the stipple.
1038 \o brushOrigin() defines the origin of the tiled brushes, normally
1039 the origin of widget's background.
1041 \o viewport(), window(), worldTransform() make up the painter's coordinate
1042 transformation system. For more information, see the \l
1043 {Coordinate Transformations} section and the \l {Coordinate
1044 System} documentation.
1046 \o hasClipping() tells whether the painter clips at all. (The paint
1047 device clips, too.) If the painter clips, it clips to clipRegion().
1049 \o layoutDirection() defines the layout direction used by the
1050 painter when drawing text.
1052 \o worldMatrixEnabled() tells whether world transformation is enabled.
1054 \o viewTransformEnabled() tells whether view transformation is
1059 Note that some of these settings mirror settings in some paint
1060 devices, e.g. QWidget::font(). The QPainter::begin() function (or
1061 equivalently the QPainter constructor) copies these attributes
1062 from the paint device.
1064 You can at any time save the QPainter's state by calling the
1065 save() function which saves all the available settings on an
1066 internal stack. The restore() function pops them back.
1070 QPainter provides functions to draw most primitives: drawPoint(),
1071 drawPoints(), drawLine(), drawRect(), drawRoundedRect(),
1072 drawEllipse(), drawArc(), drawPie(), drawChord(), drawPolyline(),
1073 drawPolygon(), drawConvexPolygon() and drawCubicBezier(). The two
1074 convenience functions, drawRects() and drawLines(), draw the given
1075 number of rectangles or lines in the given array of \l
1076 {QRect}{QRects} or \l {QLine}{QLines} using the current pen and
1079 The QPainter class also provides the fillRect() function which
1080 fills the given QRect, with the given QBrush, and the eraseRect()
1081 function that erases the area inside the given rectangle.
1083 All of these functions have both integer and floating point
1088 \o \inlineimage qpainter-basicdrawing.png
1090 \bold {Basic Drawing Example}
1092 The \l {painting/basicdrawing}{Basic Drawing} example shows how to
1093 display basic graphics primitives in a variety of styles using the
1098 If you need to draw a complex shape, especially if you need to do
1099 so repeatedly, consider creating a QPainterPath and drawing it
1105 \bold {Painter Paths example}
1107 The QPainterPath class provides a container for painting
1108 operations, enabling graphical shapes to be constructed and
1111 The \l {painting/painterpaths}{Painter Paths} example shows how
1112 painter paths can be used to build complex shapes for rendering.
1114 \o \inlineimage qpainter-painterpaths.png
1117 QPainter also provides the fillPath() function which fills the
1118 given QPainterPath with the given QBrush, and the strokePath()
1119 function that draws the outline of the given path (i.e. strokes
1122 See also the \l {painting/deform}{Vector Deformation} example which
1123 shows how to use advanced vector techniques to draw text using a
1124 QPainterPath, the \l {painting/gradients}{Gradients} example which shows
1125 the different types of gradients that are available in Qt, and the \l
1126 {painting/pathstroke}{Path Stroking} example which shows Qt's built-in
1127 dash patterns and shows how custom patterns can be used to extend
1128 the range of available patterns.
1132 \o \l {painting/deform}{Vector Deformation}
1133 \o \l {painting/gradients}{Gradients}
1134 \o \l {painting/pathstroke}{Path Stroking}
1136 \o \inlineimage qpainter-vectordeformation.png
1137 \o \inlineimage qpainter-gradients.png
1138 \o \inlineimage qpainter-pathstroking.png
1142 There are functions to draw pixmaps/images, namely drawPixmap(),
1143 drawImage() and drawTiledPixmap(). Both drawPixmap() and drawImage()
1144 produce the same result, except that drawPixmap() is faster
1145 on-screen while drawImage() may be faster on a QPrinter or other
1148 Text drawing is done using drawText(). When you need
1149 fine-grained positioning, boundingRect() tells you where a given
1150 drawText() command will draw.
1152 There is a drawPicture() function that draws the contents of an
1153 entire QPicture. The drawPicture() function is the only function
1154 that disregards all the painter's settings as QPicture has its own
1157 \section1 Rendering Quality
1159 To get the optimal rendering result using QPainter, you should use
1160 the platform independent QImage as paint device; i.e. using QImage
1161 will ensure that the result has an identical pixel representation
1164 The QPainter class also provides a means of controlling the
1165 rendering quality through its RenderHint enum and the support for
1166 floating point precision: All the functions for drawing primitives
1167 has a floating point version. These are often used in combination
1168 with the \l {RenderHint}{QPainter::Antialiasing} render hint.
1172 \o \inlineimage qpainter-concentriccircles.png
1174 \bold {Concentric Circles Example}
1176 The \l {painting/concentriccircles}{Concentric Circles} example
1177 shows the improved rendering quality that can be obtained using
1178 floating point precision and anti-aliasing when drawing custom
1181 The application's main window displays several widgets which are
1182 drawn using the various combinations of precision and
1187 The RenderHint enum specifies flags to QPainter that may or may
1188 not be respected by any given engine. \l
1189 {RenderHint}{QPainter::Antialiasing} indicates that the engine
1190 should antialias edges of primitives if possible, \l
1191 {RenderHint}{QPainter::TextAntialiasing} indicates that the engine
1192 should antialias text if possible, and the \l
1193 {RenderHint}{QPainter::SmoothPixmapTransform} indicates that the
1194 engine should use a smooth pixmap transformation algorithm.
1195 \l {RenderHint}{HighQualityAntialiasing} is an OpenGL-specific rendering hint
1196 indicating that the engine should use fragment programs and offscreen
1197 rendering for antialiasing.
1199 The renderHints() function returns a flag that specifies the
1200 rendering hints that are set for this painter. Use the
1201 setRenderHint() function to set or clear the currently set
1204 \section1 Coordinate Transformations
1206 Normally, the QPainter operates on the device's own coordinate
1207 system (usually pixels), but QPainter has good support for
1208 coordinate transformations.
1212 \o nop \o rotate() \o scale() \o translate()
1214 \o \inlineimage qpainter-clock.png
1215 \o \inlineimage qpainter-rotation.png
1216 \o \inlineimage qpainter-scale.png
1217 \o \inlineimage qpainter-translation.png
1220 The most commonly used transformations are scaling, rotation,
1221 translation and shearing. Use the scale() function to scale the
1222 coordinate system by a given offset, the rotate() function to
1223 rotate it clockwise and translate() to translate it (i.e. adding a
1224 given offset to the points). You can also twist the coordinate
1225 system around the origin using the shear() function. See the \l
1226 {painting/affine}{Affine Transformations} example for a visualization of
1227 a sheared coordinate system.
1229 See also the \l {painting/transformations}{Transformations}
1230 example which shows how transformations influence the way that
1231 QPainter renders graphics primitives. In particular it shows how
1232 the order of transformations affects the result.
1237 \bold {Affine Transformations Example}
1239 The \l {painting/affine}{Affine Transformations} example shows Qt's
1240 ability to perform affine transformations on painting
1241 operations. The demo also allows the user to experiment with the
1242 transformation operations and see the results immediately.
1244 \o \inlineimage qpainter-affinetransformations.png
1247 All the tranformation operations operate on the transformation
1248 worldTransform(). A matrix transforms a point in the plane to another
1249 point. For more information about the transformation matrix, see
1250 the \l {Coordinate System} and QTransform documentation.
1252 The setWorldTransform() function can replace or add to the currently
1253 set worldTransform(). The resetTransform() function resets any
1254 transformations that were made using translate(), scale(),
1255 shear(), rotate(), setWorldTransform(), setViewport() and setWindow()
1256 functions. The deviceTransform() returns the matrix that transforms
1257 from logical coordinates to device coordinates of the platform
1258 dependent paint device. The latter function is only needed when
1259 using platform painting commands on the platform dependent handle,
1260 and the platform does not do transformations nativly.
1262 When drawing with QPainter, we specify points using logical
1263 coordinates which then are converted into the physical coordinates
1264 of the paint device. The mapping of the logical coordinates to the
1265 physical coordinates are handled by QPainter's combinedTransform(), a
1266 combination of viewport() and window() and worldTransform(). The
1267 viewport() represents the physical coordinates specifying an
1268 arbitrary rectangle, the window() describes the same rectangle in
1269 logical coordinates, and the worldTransform() is identical with the
1270 transformation matrix.
1272 See also \l {Coordinate System}
1276 QPainter can clip any drawing operation to a rectangle, a region,
1277 or a vector path. The current clip is available using the
1278 functions clipRegion() and clipPath(). Whether paths or regions are
1279 preferred (faster) depends on the underlying paintEngine(). For
1280 example, the QImage paint engine prefers paths while the X11 paint
1281 engine prefers regions. Setting a clip is done in the painters
1282 logical coordinates.
1284 After QPainter's clipping, the paint device may also clip. For
1285 example, most widgets clip away the pixels used by child widgets,
1286 and most printers clip away an area near the edges of the paper.
1287 This additional clipping is not reflected by the return value of
1288 clipRegion() or hasClipping().
1290 \section1 Composition Modes
1291 \target Composition Modes
1293 QPainter provides the CompositionMode enum which defines the
1294 Porter-Duff rules for digital image compositing; it describes a
1295 model for combining the pixels in one image, the source, with the
1296 pixels in another image, the destination.
1298 The two most common forms of composition are \l
1299 {QPainter::CompositionMode}{Source} and \l
1300 {QPainter::CompositionMode}{SourceOver}. \l
1301 {QPainter::CompositionMode}{Source} is used to draw opaque objects
1302 onto a paint device. In this mode, each pixel in the source
1303 replaces the corresponding pixel in the destination. In \l
1304 {QPainter::CompositionMode}{SourceOver} composition mode, the
1305 source object is transparent and is drawn on top of the
1308 Note that composition transformation operates pixelwise. For that
1309 reason, there is a difference between using the graphic primitive
1310 itself and its bounding rectangle: The bounding rect contains
1311 pixels with alpha == 0 (i.e the pixels surrounding the
1312 primitive). These pixels will overwrite the other image's pixels,
1313 affectively clearing those, while the primitive only overwrites
1318 \o \inlineimage qpainter-compositiondemo.png
1321 \bold {Composition Modes Example}
1323 The \l {painting/composition}{Composition Modes} example, available in
1324 Qt's examples directory, allows you to experiment with the various
1325 composition modes and see the results immediately.
1329 \section1 Limitations
1332 If you are using coordinates with Qt's raster-based paint engine, it is
1333 important to note that, while coordinates greater than +/- 2\sup 15 can
1334 be used, any painting performed with coordinates outside this range is not
1335 guaranteed to be shown; the drawing may be clipped. This is due to the
1336 use of \c{short int} in the implementation.
1338 The outlines generated by Qt's stroker are only an approximation when dealing
1339 with curved shapes. It is in most cases impossible to represent the outline of
1340 a bezier curve segment using another bezier curve segment, and so Qt approximates
1341 the curve outlines by using several smaller curves. For performance reasons there
1342 is a limit to how many curves Qt uses for these outlines, and thus when using
1343 large pen widths or scales the outline error increases. To generate outlines with
1344 smaller errors it is possible to use the QPainterPathStroker class, which has the
1345 setCurveThreshold member function which let's the user specify the error tolerance.
1346 Another workaround is to convert the paths to polygons first and then draw the
1349 \section1 Performance
1351 QPainter is a rich framework that allows developers to do a great
1352 variety of graphical operations, such as gradients, composition
1353 modes and vector graphics. And QPainter can do this across a
1354 variety of different hardware and software stacks. Naturally the
1355 underlying combination of hardware and software has some
1356 implications for performance, and ensuring that every single
1357 operation is fast in combination with all the various combinations
1358 of composition modes, brushes, clipping, transformation, etc, is
1359 close to an impossible task because of the number of
1360 permutations. As a compromise we have selected a subset of the
1361 QPainter API and backends, where performance is guaranteed to be as
1362 good as we can sensibly get it for the given combination of
1363 hardware and software.
1365 The backends we focus on as high-performance engines are:
1369 \o Raster - This backend implements all rendering in pure software
1370 and is always used to render into QImages. For optimal performance
1371 only use the format types QImage::Format_ARGB32_Premultiplied,
1372 QImage::Format_RGB32 or QImage::Format_RGB16. Any other format,
1373 including QImage::Format_ARGB32, has significantly worse
1374 performance. This engine is also used by default on Windows and on
1375 QWS. It can be used as default graphics system on any
1376 OS/hardware/software combination by passing \c {-graphicssystem
1377 raster} on the command line
1379 \o OpenGL 2.0 (ES) - This backend is the primary backend for
1380 hardware accelerated graphics. It can be run on desktop machines
1381 and embedded devices supporting the OpenGL 2.0 or OpenGL/ES 2.0
1382 specification. This includes most graphics chips produced in the
1383 last couple of years. The engine can be enabled by using QPainter
1384 onto a QGLWidget or by passing \c {-graphicssystem opengl} on the
1385 command line when the underlying system supports it.
1387 \o OpenVG - This backend implements the Khronos standard for 2D
1388 and Vector Graphics. It is primarily for embedded devices with
1389 hardware support for OpenVG. The engine can be enabled by
1390 passing \c {-graphicssystem openvg} on the command line when
1391 the underlying system supports it.
1395 These operations are:
1399 \o Simple transformations, meaning translation and scaling, pluss
1400 0, 90, 180, 270 degree rotations.
1402 \o \c drawPixmap() in combination with simple transformations and
1403 opacity with non-smooth transformation mode
1404 (\c QPainter::SmoothPixmapTransform not enabled as a render hint).
1406 \o Rectangle fills with solid color, two-color linear gradients
1407 and simple transforms.
1409 \o Rectangular clipping with simple transformations and intersect
1412 \o Composition Modes \c QPainter::CompositionMode_Source and
1413 QPainter::CompositionMode_SourceOver
1415 \o Rounded rectangle filling using solid color and two-color
1416 linear gradients fills.
1418 \o 3x3 patched pixmaps, via qDrawBorderPixmap.
1422 This list gives an indication of which features to safely use in
1423 an application where performance is critical. For certain setups,
1424 other operations may be fast too, but before making extensive use
1425 of them, it is recommended to benchmark and verify them on the
1426 system where the software will run in the end. There are also
1427 cases where expensive operations are ok to use, for instance when
1428 the result is cached in a QPixmap.
1430 \sa QPaintDevice, QPaintEngine, {QtSvg Module}, {Basic Drawing Example},
1431 {Drawing Utility Functions}
1435 \enum QPainter::RenderHint
1437 Renderhints are used to specify flags to QPainter that may or
1438 may not be respected by any given engine.
1440 \value Antialiasing Indicates that the engine should antialias
1441 edges of primitives if possible.
1443 \value TextAntialiasing Indicates that the engine should antialias
1444 text if possible. To forcibly disable antialiasing for text, do not
1445 use this hint. Instead, set QFont::NoAntialias on your font's style
1448 \value SmoothPixmapTransform Indicates that the engine should use
1449 a smooth pixmap transformation algorithm (such as bilinear) rather
1450 than nearest neighbor.
1452 \value HighQualityAntialiasing An OpenGL-specific rendering hint
1453 indicating that the engine should use fragment programs and offscreen
1454 rendering for antialiasing.
1456 \value NonCosmeticDefaultPen The engine should interpret pens with a width
1457 of 0 (which otherwise enables QPen::isCosmetic()) as being a non-cosmetic
1458 pen with a width of 1.
1460 \sa renderHints(), setRenderHint(), {QPainter#Rendering
1461 Quality}{Rendering Quality}, {Concentric Circles Example}
1466 Constructs a painter.
1471 QPainter::QPainter()
1472 : d_ptr(new QPainterPrivate(this))
1477 \fn QPainter::QPainter(QPaintDevice *device)
1479 Constructs a painter that begins painting the paint \a device
1482 This constructor is convenient for short-lived painters, e.g. in a
1483 QWidget::paintEvent() and should be used only once. The
1484 constructor calls begin() for you and the QPainter destructor
1485 automatically calls end().
1487 Here's an example using begin() and end():
1488 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 1
1490 The same example using this constructor:
1491 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 2
1493 Since the constructor cannot provide feedback when the initialization
1494 of the painter failed you should rather use begin() and end() to paint
1495 on external devices, e.g. printers.
1500 QPainter::QPainter(QPaintDevice *pd)
1504 if (!QPainterPrivate::attachPainterPrivate(this, pd)) {
1505 d_ptr.reset(new QPainterPrivate(this));
1512 Destroys the painter.
1514 QPainter::~QPainter()
1516 d_ptr->inDestructor = true;
1520 else if (d_ptr->refcount > 1)
1521 d_ptr->detachPainterPrivate(this);
1523 // don't throw anything in the destructor.
1526 // Make sure we haven't messed things up.
1527 Q_ASSERT(d_ptr->inDestructor);
1528 d_ptr->inDestructor = false;
1529 Q_ASSERT(d_ptr->refcount == 1);
1531 free(d_ptr->d_ptrs);
1536 Returns the paint device on which this painter is currently
1537 painting, or 0 if the painter is not active.
1542 QPaintDevice *QPainter::device() const
1544 Q_D(const QPainter);
1545 if (isActive() && d->engine->d_func()->currentClipWidget)
1546 return d->engine->d_func()->currentClipWidget;
1547 return d->original_device;
1551 Returns true if begin() has been called and end() has not yet been
1552 called; otherwise returns false.
1554 \sa begin(), QPaintDevice::paintingActive()
1557 bool QPainter::isActive() const
1559 Q_D(const QPainter);
1564 Initializes the painters pen, background and font to the same as
1565 the given \a widget. This function is called automatically when the
1566 painter is opened on a QWidget.
1568 \sa begin(), {QPainter#Settings}{Settings}
1570 void QPainter::initFrom(const QWidget *widget)
1572 Q_ASSERT_X(widget, "QPainter::initFrom(const QWidget *widget)", "Widget cannot be 0");
1575 qWarning("QPainter::initFrom: Painter not active, aborted");
1579 const QPalette &pal = widget->palette();
1580 d->state->pen = QPen(pal.brush(widget->foregroundRole()), 0);
1581 d->state->bgBrush = pal.brush(widget->backgroundRole());
1582 d->state->deviceFont = QFont(widget->font(), const_cast<QWidget*> (widget));
1583 d->state->font = d->state->deviceFont;
1585 d->extended->penChanged();
1586 } else if (d->engine) {
1587 d->engine->setDirty(QPaintEngine::DirtyPen);
1588 d->engine->setDirty(QPaintEngine::DirtyBrush);
1589 d->engine->setDirty(QPaintEngine::DirtyFont);
1595 Saves the current painter state (pushes the state onto a stack). A
1596 save() must be followed by a corresponding restore(); the end()
1597 function unwinds the stack.
1602 void QPainter::save()
1604 #ifdef QT_DEBUG_DRAW
1605 if (qt_show_painter_debug_output)
1606 printf("QPainter::save()\n");
1610 qWarning("QPainter::save: Painter not active");
1615 d->state = d->extended->createState(d->states.back());
1616 d->extended->setState(d->state);
1618 d->updateState(d->state);
1619 d->state = new QPainterState(d->states.back());
1620 d->engine->state = d->state;
1622 d->states.push_back(d->state);
1626 Restores the current painter state (pops a saved state off the
1632 void QPainter::restore()
1634 #ifdef QT_DEBUG_DRAW
1635 if (qt_show_painter_debug_output)
1636 printf("QPainter::restore()\n");
1639 if (d->states.size()<=1) {
1640 qWarning("QPainter::restore: Unbalanced save/restore");
1642 } else if (!d->engine) {
1643 qWarning("QPainter::restore: Painter not active");
1647 QPainterState *tmp = d->state;
1648 d->states.pop_back();
1649 d->state = d->states.back();
1653 d->checkEmulation();
1654 d->extended->setState(d->state);
1659 // trigger clip update if the clip path/region has changed since
1661 if (!d->state->clipInfo.isEmpty()
1662 && (tmp->changeFlags & (QPaintEngine::DirtyClipRegion | QPaintEngine::DirtyClipPath))) {
1663 // reuse the tmp state to avoid any extra allocs...
1664 tmp->dirtyFlags = QPaintEngine::DirtyClipPath;
1665 tmp->clipOperation = Qt::NoClip;
1666 tmp->clipPath = QPainterPath();
1667 d->engine->updateState(*tmp);
1668 // replay the list of clip states,
1669 for (int i=0; i<d->state->clipInfo.size(); ++i) {
1670 const QPainterClipInfo &info = d->state->clipInfo.at(i);
1671 tmp->matrix = info.matrix;
1672 tmp->matrix *= d->state->redirectionMatrix;
1673 tmp->clipOperation = info.operation;
1674 if (info.clipType == QPainterClipInfo::RectClip) {
1675 tmp->dirtyFlags = QPaintEngine::DirtyClipRegion | QPaintEngine::DirtyTransform;
1676 tmp->clipRegion = info.rect;
1677 } else if (info.clipType == QPainterClipInfo::RegionClip) {
1678 tmp->dirtyFlags = QPaintEngine::DirtyClipRegion | QPaintEngine::DirtyTransform;
1679 tmp->clipRegion = info.region;
1680 } else { // clipType == QPainterClipInfo::PathClip
1681 tmp->dirtyFlags = QPaintEngine::DirtyClipPath | QPaintEngine::DirtyTransform;
1682 tmp->clipPath = info.path;
1684 d->engine->updateState(*tmp);
1688 //Since we've updated the clip region anyway, pretend that the clip path hasn't changed:
1689 d->state->dirtyFlags &= ~(QPaintEngine::DirtyClipPath | QPaintEngine::DirtyClipRegion);
1690 tmp->changeFlags &= ~(QPaintEngine::DirtyClipPath | QPaintEngine::DirtyClipRegion);
1691 tmp->changeFlags |= QPaintEngine::DirtyTransform;
1694 d->updateState(d->state);
1701 \fn bool QPainter::begin(QPaintDevice *device)
1703 Begins painting the paint \a device and returns true if
1704 successful; otherwise returns false.
1706 Notice that all painter settings (setPen(), setBrush() etc.) are reset
1707 to default values when begin() is called.
1709 The errors that can occur are serious problems, such as these:
1711 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 3
1713 Note that most of the time, you can use one of the constructors
1714 instead of begin(), and that end() is automatically done at
1717 \warning A paint device can only be painted by one painter at a
1720 \warning Painting on a QImage with the format
1721 QImage::Format_Indexed8 is not supported.
1723 \sa end(), QPainter()
1726 static inline void qt_cleanup_painter_state(QPainterPrivate *d)
1735 bool QPainter::begin(QPaintDevice *pd)
1739 if (pd->painters > 0) {
1740 qWarning("QPainter::begin: A paint device can only be painted by one painter at a time.");
1744 if (d_ptr->engine) {
1745 qWarning("QPainter::begin: Painter already active");
1749 if (QPainterPrivate::attachPainterPrivate(this, pd))
1754 d->helper_device = pd;
1755 d->original_device = pd;
1756 QPaintDevice *rpd = 0;
1758 QPoint redirectionOffset;
1759 // We know for sure that redirection is broken when the widget is inside
1760 // its paint event, so it's safe to use our hard-coded redirection. However,
1761 // there IS one particular case we still need to support, and that's
1762 // when people call QPainter::setRedirected in the widget's paint event right
1763 // before any painter is created (or QPainter::begin is called). In that
1764 // particular case our hard-coded redirection is restored and the redirection
1765 // is retrieved from QPainter::redirected (as before).
1766 if (pd->devType() == QInternal::Widget)
1767 rpd = static_cast<QWidget *>(pd)->d_func()->redirected(&redirectionOffset);
1770 rpd = redirected(pd, &redirectionOffset);
1775 #ifdef QT_DEBUG_DRAW
1776 if (qt_show_painter_debug_output)
1777 printf("QPainter::begin(), device=%p, type=%d\n", pd, pd->devType());
1780 if (pd->devType() == QInternal::Pixmap)
1781 static_cast<QPixmap *>(pd)->detach();
1782 else if (pd->devType() == QInternal::Image)
1783 static_cast<QImage *>(pd)->detach();
1785 d->engine = pd->paintEngine();
1788 qWarning("QPainter::begin: Paint device returned engine == 0, type: %d", pd->devType());
1794 d->extended = d->engine->isExtended() ? static_cast<QPaintEngineEx *>(d->engine) : 0;
1795 if (d->emulationEngine)
1796 d->emulationEngine->real_engine = d->extended;
1798 // Setup new state...
1799 Q_ASSERT(!d->state);
1800 d->state = d->extended ? d->extended->createState(0) : new QPainterState;
1801 d->state->painter = this;
1802 d->states.push_back(d->state);
1804 d->state->redirectionMatrix.translate(-redirectionOffset.x(), -redirectionOffset.y());
1805 d->state->brushOrigin = QPointF();
1807 // Slip a painter state into the engine before we do any other operations
1809 d->extended->setState(d->state);
1811 d->engine->state = d->state;
1813 switch (pd->devType()) {
1814 case QInternal::Widget:
1816 const QWidget *widget = static_cast<const QWidget *>(pd);
1819 const bool paintOutsidePaintEvent = widget->testAttribute(Qt::WA_PaintOutsidePaintEvent);
1820 const bool inPaintEvent = widget->testAttribute(Qt::WA_WState_InPaintEvent);
1821 if(!d->engine->hasFeature(QPaintEngine::PaintOutsidePaintEvent)
1822 && !paintOutsidePaintEvent && !inPaintEvent) {
1823 qWarning("QPainter::begin: Widget painting can only begin as a "
1824 "result of a paintEvent");
1825 qt_cleanup_painter_state(d);
1829 // Adjust offset for alien widgets painting outside the paint event.
1830 if (!inPaintEvent && paintOutsidePaintEvent && !widget->internalWinId()
1831 && widget->testAttribute(Qt::WA_WState_Created)) {
1832 const QPoint offset = widget->mapTo(widget->nativeParentWidget(), QPoint());
1833 d->state->redirectionMatrix.translate(offset.x(), offset.y());
1837 case QInternal::Pixmap:
1839 QPixmap *pm = static_cast<QPixmap *>(pd);
1842 qWarning("QPainter::begin: Cannot paint on a null pixmap");
1843 qt_cleanup_painter_state(d);
1847 if (pm->depth() == 1) {
1848 d->state->pen = QPen(Qt::color1);
1849 d->state->brush = QBrush(Qt::color0);
1853 case QInternal::Image:
1855 QImage *img = static_cast<QImage *>(pd);
1857 if (img->isNull()) {
1858 qWarning("QPainter::begin: Cannot paint on a null image");
1859 qt_cleanup_painter_state(d);
1861 } else if (img->format() == QImage::Format_Indexed8) {
1862 // Painting on indexed8 images is not supported.
1863 qWarning("QPainter::begin: Cannot paint on an image with the QImage::Format_Indexed8 format");
1864 qt_cleanup_painter_state(d);
1867 if (img->depth() == 1) {
1868 d->state->pen = QPen(Qt::color1);
1869 d->state->brush = QBrush(Qt::color0);
1876 if (d->state->ww == 0) // For compat with 3.x painter defaults
1877 d->state->ww = d->state->wh = d->state->vw = d->state->vh = 1024;
1879 d->engine->setPaintDevice(pd);
1881 bool begun = d->engine->begin(pd);
1883 qWarning("QPainter::begin(): Returned false");
1884 if (d->engine->isActive()) {
1887 qt_cleanup_painter_state(d);
1891 d->engine->setActive(begun);
1894 // Copy painter properties from original paint device,
1895 // required for QPixmap::grabWidget()
1896 if (d->original_device->devType() == QInternal::Widget) {
1897 QWidget *widget = static_cast<QWidget *>(d->original_device);
1900 d->state->layoutDirection = Qt::LayoutDirectionAuto;
1901 // make sure we have a font compatible with the paintdevice
1902 d->state->deviceFont = d->state->font = QFont(d->state->deviceFont, device());
1905 QRect systemRect = d->engine->systemRect();
1906 if (!systemRect.isEmpty()) {
1907 d->state->ww = d->state->vw = systemRect.width();
1908 d->state->wh = d->state->vh = systemRect.height();
1910 d->state->ww = d->state->vw = pd->metric(QPaintDevice::PdmWidth);
1911 d->state->wh = d->state->vh = pd->metric(QPaintDevice::PdmHeight);
1914 const QPoint coordinateOffset = d->engine->coordinateOffset();
1915 d->state->redirectionMatrix.translate(-coordinateOffset.x(), -coordinateOffset.y());
1917 Q_ASSERT(d->engine->isActive());
1919 if (!d->state->redirectionMatrix.isIdentity())
1922 Q_ASSERT(d->engine->isActive());
1923 d->state->renderHints = QPainter::TextAntialiasing;
1924 ++d->device->painters;
1926 d->state->emulationSpecifier = 0;
1932 Ends painting. Any resources used while painting are released. You
1933 don't normally need to call this since it is called by the
1936 Returns true if the painter is no longer active; otherwise returns false.
1938 \sa begin(), isActive()
1941 bool QPainter::end()
1943 #ifdef QT_DEBUG_DRAW
1944 if (qt_show_painter_debug_output)
1945 printf("QPainter::end()\n");
1950 qWarning("QPainter::end: Painter not active, aborted");
1951 qt_cleanup_painter_state(d);
1955 if (d->refcount > 1) {
1956 d->detachPainterPrivate(this);
1962 if (d->engine->isActive()) {
1963 ended = d->engine->end();
1966 --d->device->painters;
1967 if (d->device->painters == 0) {
1968 d->engine->setPaintDevice(0);
1969 d->engine->setActive(false);
1973 if (d->states.size() > 1) {
1974 qWarning("QPainter::end: Painter ended with %d saved states",
1978 if (d->engine->autoDestruct()) {
1982 if (d->emulationEngine) {
1983 delete d->emulationEngine;
1984 d->emulationEngine = 0;
1991 qt_cleanup_painter_state(d);
1998 Returns the paint engine that the painter is currently operating
1999 on if the painter is active; otherwise 0.
2003 QPaintEngine *QPainter::paintEngine() const
2005 Q_D(const QPainter);
2012 Flushes the painting pipeline and prepares for the user issuing commands
2013 directly to the underlying graphics context. Must be followed by a call to
2014 endNativePainting().
2016 Note that only the states the underlying paint engine changes will be reset
2017 to their respective default states. The states we reset may change from
2018 release to release. The following states are currently reset in the OpenGL
2022 \i blending is disabled
2023 \i the depth, stencil and scissor tests are disabled
2024 \i the active texture unit is reset to 0
2025 \i the depth mask, depth function and the clear depth are reset to their
2027 \i the stencil mask, stencil operation and stencil function are reset to
2028 their default values
2029 \i the current color is reset to solid white
2032 If, for example, the OpenGL polygon mode is changed by the user inside a
2033 beginNativePaint()/endNativePainting() block, it will not be reset to the
2034 default state by endNativePainting(). Here is an example that shows
2035 intermixing of painter commands and raw OpenGL commands:
2037 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 21
2039 \sa endNativePainting()
2041 void QPainter::beginNativePainting()
2045 qWarning("QPainter::beginNativePainting: Painter not active");
2050 d->extended->beginNativePainting();
2056 Restores the painter after manually issuing native painting commands. Lets
2057 the painter restore any native state that it relies on before calling any
2058 other painter commands.
2060 \sa beginNativePainting()
2062 void QPainter::endNativePainting()
2064 Q_D(const QPainter);
2066 qWarning("QPainter::beginNativePainting: Painter not active");
2071 d->extended->endNativePainting();
2073 d->engine->syncState();
2077 Returns the font metrics for the painter if the painter is
2078 active. Otherwise, the return value is undefined.
2080 \sa font(), isActive(), {QPainter#Settings}{Settings}
2083 QFontMetrics QPainter::fontMetrics() const
2085 Q_D(const QPainter);
2087 qWarning("QPainter::fontMetrics: Painter not active");
2088 return QFontMetrics(QFont());
2090 return QFontMetrics(d->state->font);
2095 Returns the font info for the painter if the painter is
2096 active. Otherwise, the return value is undefined.
2098 \sa font(), isActive(), {QPainter#Settings}{Settings}
2101 QFontInfo QPainter::fontInfo() const
2103 Q_D(const QPainter);
2105 qWarning("QPainter::fontInfo: Painter not active");
2106 return QFontInfo(QFont());
2108 return QFontInfo(d->state->font);
2114 Returns the opacity of the painter. The default value is
2118 qreal QPainter::opacity() const
2120 Q_D(const QPainter);
2122 qWarning("QPainter::opacity: Painter not active");
2125 return d->state->opacity;
2131 Sets the opacity of the painter to \a opacity. The value should
2132 be in the range 0.0 to 1.0, where 0.0 is fully transparent and
2133 1.0 is fully opaque.
2135 Opacity set on the painter will apply to all drawing operations
2139 void QPainter::setOpacity(qreal opacity)
2144 qWarning("QPainter::setOpacity: Painter not active");
2148 opacity = qMin(qreal(1), qMax(qreal(0), opacity));
2150 if (opacity == d->state->opacity)
2153 d->state->opacity = opacity;
2156 d->extended->opacityChanged();
2158 d->state->dirtyFlags |= QPaintEngine::DirtyOpacity;
2163 Returns the currently set brush origin.
2165 \sa setBrushOrigin(), {QPainter#Settings}{Settings}
2168 QPoint QPainter::brushOrigin() const
2170 Q_D(const QPainter);
2172 qWarning("QPainter::brushOrigin: Painter not active");
2175 return QPointF(d->state->brushOrigin).toPoint();
2179 \fn void QPainter::setBrushOrigin(const QPointF &position)
2181 Sets the brush origin to \a position.
2183 The brush origin specifies the (0, 0) coordinate of the painter's
2186 Note that while the brushOrigin() was necessary to adopt the
2187 parent's background for a widget in Qt 3, this is no longer the
2188 case since the Qt 4 painter doesn't paint the background unless
2189 you explicitly tell it to do so by setting the widget's \l
2190 {QWidget::autoFillBackground}{autoFillBackground} property to
2193 \sa brushOrigin(), {QPainter#Settings}{Settings}
2196 void QPainter::setBrushOrigin(const QPointF &p)
2199 #ifdef QT_DEBUG_DRAW
2200 if (qt_show_painter_debug_output)
2201 printf("QPainter::setBrushOrigin(), (%.2f,%.2f)\n", p.x(), p.y());
2205 qWarning("QPainter::setBrushOrigin: Painter not active");
2209 d->state->brushOrigin = p;
2212 d->extended->brushOriginChanged();
2216 d->state->dirtyFlags |= QPaintEngine::DirtyBrushOrigin;
2220 \fn void QPainter::setBrushOrigin(const QPoint &position)
2223 Sets the brush's origin to the given \a position.
2227 \fn void QPainter::setBrushOrigin(int x, int y)
2231 Sets the brush's origin to point (\a x, \a y).
2235 \enum QPainter::CompositionMode
2237 Defines the modes supported for digital image compositing.
2238 Composition modes are used to specify how the pixels in one image,
2239 the source, are merged with the pixel in another image, the
2242 Please note that the bitwise raster operation modes, denoted with
2243 a RasterOp prefix, are only natively supported in the X11 and
2244 raster paint engines. This means that the only way to utilize
2245 these modes on the Mac is via a QImage. The RasterOp denoted blend
2246 modes are \e not supported for pens and brushes with alpha
2247 components. Also, turning on the QPainter::Antialiasing render
2248 hint will effectively disable the RasterOp modes.
2251 \image qpainter-compositionmode1.png
2252 \image qpainter-compositionmode2.png
2254 The most common type is SourceOver (often referred to as just
2255 alpha blending) where the source pixel is blended on top of the
2256 destination pixel in such a way that the alpha component of the
2257 source defines the translucency of the pixel.
2259 When the paint device is a QImage, the image format must be set to
2260 \l {QImage::Format}{Format_ARGB32Premultiplied} or
2261 \l {QImage::Format}{Format_ARGB32} for the composition modes to have
2262 any effect. For performance the premultiplied version is the preferred
2265 When a composition mode is set it applies to all painting
2266 operator, pens, brushes, gradients and pixmap/image drawing.
2268 \value CompositionMode_SourceOver This is the default mode. The
2269 alpha of the source is used to blend the pixel on top of the
2272 \value CompositionMode_DestinationOver The alpha of the
2273 destination is used to blend it on top of the source pixels. This
2274 mode is the inverse of CompositionMode_SourceOver.
2276 \value CompositionMode_Clear The pixels in the destination are
2277 cleared (set to fully transparent) independent of the source.
2279 \value CompositionMode_Source The output is the source
2280 pixel. (This means a basic copy operation and is identical to
2281 SourceOver when the source pixel is opaque).
2283 \value CompositionMode_Destination The output is the destination
2284 pixel. This means that the blending has no effect. This mode is
2285 the inverse of CompositionMode_Source.
2287 \value CompositionMode_SourceIn The output is the source, where
2288 the alpha is reduced by that of the destination.
2290 \value CompositionMode_DestinationIn The output is the
2291 destination, where the alpha is reduced by that of the
2292 source. This mode is the inverse of CompositionMode_SourceIn.
2294 \value CompositionMode_SourceOut The output is the source, where
2295 the alpha is reduced by the inverse of destination.
2297 \value CompositionMode_DestinationOut The output is the
2298 destination, where the alpha is reduced by the inverse of the
2299 source. This mode is the inverse of CompositionMode_SourceOut.
2301 \value CompositionMode_SourceAtop The source pixel is blended on
2302 top of the destination, with the alpha of the source pixel reduced
2303 by the alpha of the destination pixel.
2305 \value CompositionMode_DestinationAtop The destination pixel is
2306 blended on top of the source, with the alpha of the destination
2307 pixel is reduced by the alpha of the destination pixel. This mode
2308 is the inverse of CompositionMode_SourceAtop.
2310 \value CompositionMode_Xor The source, whose alpha is reduced with
2311 the inverse of the destination alpha, is merged with the
2312 destination, whose alpha is reduced by the inverse of the source
2313 alpha. CompositionMode_Xor is not the same as the bitwise Xor.
2315 \value CompositionMode_Plus Both the alpha and color of the source
2316 and destination pixels are added together.
2318 \value CompositionMode_Multiply The output is the source color
2319 multiplied by the destination. Multiplying a color with white
2320 leaves the color unchanged, while multiplying a color
2321 with black produces black.
2323 \value CompositionMode_Screen The source and destination colors
2324 are inverted and then multiplied. Screening a color with white
2325 produces white, whereas screening a color with black leaves the
2328 \value CompositionMode_Overlay Multiplies or screens the colors
2329 depending on the destination color. The destination color is mixed
2330 with the source color to reflect the lightness or darkness of the
2333 \value CompositionMode_Darken The darker of the source and
2334 destination colors is selected.
2336 \value CompositionMode_Lighten The lighter of the source and
2337 destination colors is selected.
2339 \value CompositionMode_ColorDodge The destination color is
2340 brightened to reflect the source color. A black source color
2341 leaves the destination color unchanged.
2343 \value CompositionMode_ColorBurn The destination color is darkened
2344 to reflect the source color. A white source color leaves the
2345 destination color unchanged.
2347 \value CompositionMode_HardLight Multiplies or screens the colors
2348 depending on the source color. A light source color will lighten
2349 the destination color, whereas a dark source color will darken the
2352 \value CompositionMode_SoftLight Darkens or lightens the colors
2353 depending on the source color. Similar to
2354 CompositionMode_HardLight.
2356 \value CompositionMode_Difference Subtracts the darker of the
2357 colors from the lighter. Painting with white inverts the
2358 destination color, whereas painting with black leaves the
2359 destination color unchanged.
2361 \value CompositionMode_Exclusion Similar to
2362 CompositionMode_Difference, but with a lower contrast. Painting
2363 with white inverts the destination color, whereas painting with
2364 black leaves the destination color unchanged.
2366 \value RasterOp_SourceOrDestination Does a bitwise OR operation on
2367 the source and destination pixels (src OR dst).
2369 \value RasterOp_SourceAndDestination Does a bitwise AND operation
2370 on the source and destination pixels (src AND dst).
2372 \value RasterOp_SourceXorDestination Does a bitwise XOR operation
2373 on the source and destination pixels (src XOR dst).
2375 \value RasterOp_NotSourceAndNotDestination Does a bitwise NOR
2376 operation on the source and destination pixels ((NOT src) AND (NOT
2379 \value RasterOp_NotSourceOrNotDestination Does a bitwise NAND
2380 operation on the source and destination pixels ((NOT src) OR (NOT
2383 \value RasterOp_NotSourceXorDestination Does a bitwise operation
2384 where the source pixels are inverted and then XOR'ed with the
2385 destination ((NOT src) XOR dst).
2387 \value RasterOp_NotSource Does a bitwise operation where the
2388 source pixels are inverted (NOT src).
2390 \value RasterOp_NotSourceAndDestination Does a bitwise operation
2391 where the source is inverted and then AND'ed with the destination
2392 ((NOT src) AND dst).
2394 \value RasterOp_SourceAndNotDestination Does a bitwise operation
2395 where the source is AND'ed with the inverted destination pixels
2396 (src AND (NOT dst)).
2398 \sa compositionMode(), setCompositionMode(), {QPainter#Composition
2399 Modes}{Composition Modes}, {Image Composition Example}
2403 Sets the composition mode to the given \a mode.
2405 \warning Only a QPainter operating on a QImage fully supports all
2406 composition modes. The RasterOp modes are supported for X11 as
2407 described in compositionMode().
2409 \sa compositionMode()
2411 void QPainter::setCompositionMode(CompositionMode mode)
2415 qWarning("QPainter::setCompositionMode: Painter not active");
2418 if (d->state->composition_mode == mode)
2421 d->state->composition_mode = mode;
2422 d->extended->compositionModeChanged();
2426 if (mode >= QPainter::RasterOp_SourceOrDestination) {
2427 if (!d->engine->hasFeature(QPaintEngine::RasterOpModes)) {
2428 qWarning("QPainter::setCompositionMode: "
2429 "Raster operation modes not supported on device");
2432 } else if (mode >= QPainter::CompositionMode_Plus) {
2433 if (!d->engine->hasFeature(QPaintEngine::BlendModes)) {
2434 qWarning("QPainter::setCompositionMode: "
2435 "Blend modes not supported on device");
2438 } else if (!d->engine->hasFeature(QPaintEngine::PorterDuff)) {
2439 if (mode != CompositionMode_Source && mode != CompositionMode_SourceOver) {
2440 qWarning("QPainter::setCompositionMode: "
2441 "PorterDuff modes not supported on device");
2446 d->state->composition_mode = mode;
2447 d->state->dirtyFlags |= QPaintEngine::DirtyCompositionMode;
2451 Returns the current composition mode.
2453 \sa CompositionMode, setCompositionMode()
2455 QPainter::CompositionMode QPainter::compositionMode() const
2457 Q_D(const QPainter);
2459 qWarning("QPainter::compositionMode: Painter not active");
2460 return QPainter::CompositionMode_SourceOver;
2462 return d->state->composition_mode;
2466 Returns the current background brush.
2468 \sa setBackground(), {QPainter#Settings}{Settings}
2471 const QBrush &QPainter::background() const
2473 Q_D(const QPainter);
2475 qWarning("QPainter::background: Painter not active");
2476 return d->fakeState()->brush;
2478 return d->state->bgBrush;
2483 Returns true if clipping has been set; otherwise returns false.
2485 \sa setClipping(), {QPainter#Clipping}{Clipping}
2488 bool QPainter::hasClipping() const
2490 Q_D(const QPainter);
2492 qWarning("QPainter::hasClipping: Painter not active");
2495 return d->state->clipEnabled && d->state->clipOperation != Qt::NoClip;
2500 Enables clipping if \a enable is true, or disables clipping if \a
2503 \sa hasClipping(), {QPainter#Clipping}{Clipping}
2506 void QPainter::setClipping(bool enable)
2509 #ifdef QT_DEBUG_DRAW
2510 if (qt_show_painter_debug_output)
2511 printf("QPainter::setClipping(), enable=%s, was=%s\n",
2512 enable ? "on" : "off",
2513 hasClipping() ? "on" : "off");
2516 qWarning("QPainter::setClipping: Painter not active, state will be reset by begin");
2520 if (hasClipping() == enable)
2523 // we can't enable clipping if we don't have a clip
2525 && (d->state->clipInfo.isEmpty() || d->state->clipInfo.last().operation == Qt::NoClip))
2527 d->state->clipEnabled = enable;
2530 d->extended->clipEnabledChanged();
2534 d->state->dirtyFlags |= QPaintEngine::DirtyClipEnabled;
2535 d->updateState(d->state);
2540 Returns the currently set clip region. Note that the clip region
2541 is given in logical coordinates.
2543 \warning QPainter does not store the combined clip explicitly as
2544 this is handled by the underlying QPaintEngine, so the path is
2545 recreated on demand and transformed to the current logical
2546 coordinate system. This is potentially an expensive operation.
2548 \sa setClipRegion(), clipPath(), setClipping()
2551 QRegion QPainter::clipRegion() const
2553 Q_D(const QPainter);
2555 qWarning("QPainter::clipRegion: Painter not active");
2560 bool lastWasNothing = true;
2563 const_cast<QPainter *>(this)->d_ptr->updateInvMatrix();
2565 // ### Falcon: Use QPainterPath
2566 for (int i=0; i<d->state->clipInfo.size(); ++i) {
2567 const QPainterClipInfo &info = d->state->clipInfo.at(i);
2568 switch (info.clipType) {
2570 case QPainterClipInfo::RegionClip: {
2571 QTransform matrix = (info.matrix * d->invMatrix);
2572 if (lastWasNothing) {
2573 region = info.region * matrix;
2574 lastWasNothing = false;
2577 if (info.operation == Qt::IntersectClip)
2578 region &= info.region * matrix;
2579 else if (info.operation == Qt::NoClip) {
2580 lastWasNothing = true;
2583 region = info.region * matrix;
2587 case QPainterClipInfo::PathClip: {
2588 QTransform matrix = (info.matrix * d->invMatrix);
2589 if (lastWasNothing) {
2590 region = QRegion((info.path * matrix).toFillPolygon().toPolygon(),
2591 info.path.fillRule());
2592 lastWasNothing = false;
2595 if (info.operation == Qt::IntersectClip) {
2596 region &= QRegion((info.path * matrix).toFillPolygon().toPolygon(),
2597 info.path.fillRule());
2598 } else if (info.operation == Qt::NoClip) {
2599 lastWasNothing = true;
2602 region = QRegion((info.path * matrix).toFillPolygon().toPolygon(),
2603 info.path.fillRule());
2608 case QPainterClipInfo::RectClip: {
2609 QTransform matrix = (info.matrix * d->invMatrix);
2610 if (lastWasNothing) {
2611 region = QRegion(info.rect) * matrix;
2612 lastWasNothing = false;
2615 if (info.operation == Qt::IntersectClip) {
2616 // Use rect intersection if possible.
2617 if (matrix.type() <= QTransform::TxScale)
2618 region &= matrix.mapRect(info.rect);
2620 region &= matrix.map(QRegion(info.rect));
2621 } else if (info.operation == Qt::NoClip) {
2622 lastWasNothing = true;
2625 region = QRegion(info.rect) * matrix;
2630 case QPainterClipInfo::RectFClip: {
2631 QTransform matrix = (info.matrix * d->invMatrix);
2632 if (lastWasNothing) {
2633 region = QRegion(info.rectf.toRect()) * matrix;
2634 lastWasNothing = false;
2637 if (info.operation == Qt::IntersectClip) {
2638 // Use rect intersection if possible.
2639 if (matrix.type() <= QTransform::TxScale)
2640 region &= matrix.mapRect(info.rectf.toRect());
2642 region &= matrix.map(QRegion(info.rectf.toRect()));
2643 } else if (info.operation == Qt::NoClip) {
2644 lastWasNothing = true;
2647 region = QRegion(info.rectf.toRect()) * matrix;
2657 extern QPainterPath qt_regionToPath(const QRegion ®ion);
2660 Returns the currently clip as a path. Note that the clip path is
2661 given in logical coordinates.
2663 \warning QPainter does not store the combined clip explicitly as
2664 this is handled by the underlying QPaintEngine, so the path is
2665 recreated on demand and transformed to the current logical
2666 coordinate system. This is potentially an expensive operation.
2668 \sa setClipPath(), clipRegion(), setClipping()
2670 QPainterPath QPainter::clipPath() const
2672 Q_D(const QPainter);
2674 // ### Since we do not support path intersections and path unions yet,
2675 // we just use clipRegion() here...
2677 qWarning("QPainter::clipPath: Painter not active");
2678 return QPainterPath();
2681 // No clip, return empty
2682 if (d->state->clipInfo.size() == 0) {
2683 return QPainterPath();
2686 // Update inverse matrix, used below.
2688 const_cast<QPainter *>(this)->d_ptr->updateInvMatrix();
2690 // For the simple case avoid conversion.
2691 if (d->state->clipInfo.size() == 1
2692 && d->state->clipInfo.at(0).clipType == QPainterClipInfo::PathClip) {
2693 QTransform matrix = (d->state->clipInfo.at(0).matrix * d->invMatrix);
2694 return d->state->clipInfo.at(0).path * matrix;
2696 } else if (d->state->clipInfo.size() == 1
2697 && d->state->clipInfo.at(0).clipType == QPainterClipInfo::RectClip) {
2698 QTransform matrix = (d->state->clipInfo.at(0).matrix * d->invMatrix);
2700 path.addRect(d->state->clipInfo.at(0).rect);
2701 return path * matrix;
2703 // Fallback to clipRegion() for now, since we don't have isect/unite for paths
2704 return qt_regionToPath(clipRegion());
2710 Returns the bounding rectangle of the current clip if there is a clip;
2711 otherwise returns an empty rectangle. Note that the clip region is
2712 given in logical coordinates.
2714 The bounding rectangle is not guaranteed to be tight.
2716 \sa setClipRect(), setClipPath(), setClipRegion()
2721 QRectF QPainter::clipBoundingRect() const
2723 Q_D(const QPainter);
2726 qWarning("QPainter::clipBoundingRect: Painter not active");
2730 // Accumulate the bounding box in device space. This is not 100%
2731 // precise, but it fits within the guarantee and it is reasonably
2734 for (int i=0; i<d->state->clipInfo.size(); ++i) {
2736 const QPainterClipInfo &info = d->state->clipInfo.at(i);
2738 if (info.clipType == QPainterClipInfo::RectClip)
2740 else if (info.clipType == QPainterClipInfo::RectFClip)
2742 else if (info.clipType == QPainterClipInfo::RegionClip)
2743 r = info.region.boundingRect();
2745 r = info.path.boundingRect();
2747 r = info.matrix.mapRect(r);
2751 else if (info.operation == Qt::IntersectClip)
2756 // Map the rectangle back into logical space using the inverse
2759 const_cast<QPainter *>(this)->d_ptr->updateInvMatrix();
2761 return d->invMatrix.mapRect(bounds);
2765 \fn void QPainter::setClipRect(const QRectF &rectangle, Qt::ClipOperation operation)
2767 Enables clipping, and sets the clip region to the given \a
2768 rectangle using the given clip \a operation. The default operation
2769 is to replace the current clip rectangle.
2771 Note that the clip rectangle is specified in logical (painter)
2774 \sa clipRegion(), setClipping(), {QPainter#Clipping}{Clipping}
2776 void QPainter::setClipRect(const QRectF &rect, Qt::ClipOperation op)
2781 if ((!d->state->clipEnabled && op != Qt::NoClip))
2782 op = Qt::ReplaceClip;
2785 qWarning("QPainter::setClipRect: Painter not active");
2788 qreal right = rect.x() + rect.width();
2789 qreal bottom = rect.y() + rect.height();
2790 qreal pts[] = { rect.x(), rect.y(),
2794 QVectorPath vp(pts, 4, 0, QVectorPath::RectangleHint);
2795 d->state->clipEnabled = true;
2796 d->extended->clip(vp, op);
2797 if (op == Qt::ReplaceClip || op == Qt::NoClip)
2798 d->state->clipInfo.clear();
2799 d->state->clipInfo << QPainterClipInfo(rect, op, d->state->matrix);
2800 d->state->clipOperation = op;
2804 if (qreal(int(rect.top())) == rect.top()
2805 && qreal(int(rect.bottom())) == rect.bottom()
2806 && qreal(int(rect.left())) == rect.left()
2807 && qreal(int(rect.right())) == rect.right())
2809 setClipRect(rect.toRect(), op);
2813 if (rect.isEmpty()) {
2814 setClipRegion(QRegion(), op);
2820 setClipPath(path, op);
2824 \fn void QPainter::setClipRect(const QRect &rectangle, Qt::ClipOperation operation)
2827 Enables clipping, and sets the clip region to the given \a rectangle using the given
2830 void QPainter::setClipRect(const QRect &rect, Qt::ClipOperation op)
2835 qWarning("QPainter::setClipRect: Painter not active");
2839 if ((!d->state->clipEnabled && op != Qt::NoClip))
2840 op = Qt::ReplaceClip;
2843 d->state->clipEnabled = true;
2844 d->extended->clip(rect, op);
2845 if (op == Qt::ReplaceClip || op == Qt::NoClip)
2846 d->state->clipInfo.clear();
2847 d->state->clipInfo << QPainterClipInfo(rect, op, d->state->matrix);
2848 d->state->clipOperation = op;
2852 d->state->clipRegion = rect;
2853 d->state->clipOperation = op;
2854 if (op == Qt::NoClip || op == Qt::ReplaceClip)
2855 d->state->clipInfo.clear();
2856 d->state->clipInfo << QPainterClipInfo(rect, op, d->state->matrix);
2857 d->state->clipEnabled = true;
2858 d->state->dirtyFlags |= QPaintEngine::DirtyClipRegion | QPaintEngine::DirtyClipEnabled;
2859 d->updateState(d->state);
2863 \fn void QPainter::setClipRect(int x, int y, int width, int height, Qt::ClipOperation operation)
2865 Enables clipping, and sets the clip region to the rectangle beginning at (\a x, \a y)
2866 with the given \a width and \a height.
2870 \fn void QPainter::setClipRegion(const QRegion ®ion, Qt::ClipOperation operation)
2872 Sets the clip region to the given \a region using the specified clip
2873 \a operation. The default clip operation is to replace the current
2876 Note that the clip region is given in logical coordinates.
2878 \sa clipRegion(), setClipRect(), {QPainter#Clipping}{Clipping}
2880 void QPainter::setClipRegion(const QRegion &r, Qt::ClipOperation op)
2883 #ifdef QT_DEBUG_DRAW
2884 QRect rect = r.boundingRect();
2885 if (qt_show_painter_debug_output)
2886 printf("QPainter::setClipRegion(), size=%d, [%d,%d,%d,%d]\n",
2887 r.rects().size(), rect.x(), rect.y(), rect.width(), rect.height());
2890 qWarning("QPainter::setClipRegion: Painter not active");
2894 if ((!d->state->clipEnabled && op != Qt::NoClip))
2895 op = Qt::ReplaceClip;
2898 d->state->clipEnabled = true;
2899 d->extended->clip(r, op);
2900 if (op == Qt::NoClip || op == Qt::ReplaceClip)
2901 d->state->clipInfo.clear();
2902 d->state->clipInfo << QPainterClipInfo(r, op, d->state->matrix);
2903 d->state->clipOperation = op;
2907 d->state->clipRegion = r;
2908 d->state->clipOperation = op;
2909 if (op == Qt::NoClip || op == Qt::ReplaceClip)
2910 d->state->clipInfo.clear();
2911 d->state->clipInfo << QPainterClipInfo(r, op, d->state->matrix);
2912 d->state->clipEnabled = true;
2913 d->state->dirtyFlags |= QPaintEngine::DirtyClipRegion | QPaintEngine::DirtyClipEnabled;
2914 d->updateState(d->state);
2921 Sets the transformation matrix to \a matrix and enables transformations.
2923 \note It is advisable to use setWorldTransform() instead of this function to
2924 preserve the properties of perspective transformations.
2926 If \a combine is true, then \a matrix is combined with the current
2927 transformation matrix; otherwise \a matrix replaces the current
2928 transformation matrix.
2930 If \a matrix is the identity matrix and \a combine is false, this
2931 function calls setWorldMatrixEnabled(false). (The identity matrix is the
2932 matrix where QMatrix::m11() and QMatrix::m22() are 1.0 and the
2935 The following functions can transform the coordinate system without using
2944 They operate on the painter's worldMatrix() and are implemented like this:
2946 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 4
2948 Note that when using setWorldMatrix() function you should always have
2949 \a combine be true when you are drawing into a QPicture. Otherwise
2950 it may not be possible to replay the picture with additional
2951 transformations; using the translate(), scale(), etc. convenience
2954 For more information about the coordinate system, transformations
2955 and window-viewport conversion, see \l {Coordinate System}.
2957 \sa setWorldTransform(), QTransform
2960 void QPainter::setWorldMatrix(const QMatrix &matrix, bool combine)
2962 setWorldTransform(QTransform(matrix), combine);
2969 Returns the world transformation matrix.
2971 It is advisable to use worldTransform() because worldMatrix() does not
2972 preserve the properties of perspective transformations.
2974 \sa {QPainter#Coordinate Transformations}{Coordinate Transformations},
2978 const QMatrix &QPainter::worldMatrix() const
2980 Q_D(const QPainter);
2982 qWarning("QPainter::worldMatrix: Painter not active");
2983 return d->fakeState()->transform.toAffine();
2985 return d->state->worldMatrix.toAffine();
2991 Use setWorldTransform() instead.
2993 \sa setWorldTransform()
2996 void QPainter::setMatrix(const QMatrix &matrix, bool combine)
2998 setWorldTransform(QTransform(matrix), combine);
3004 Use worldTransform() instead.
3006 \sa worldTransform()
3009 const QMatrix &QPainter::matrix() const
3011 return worldMatrix();
3019 Returns the transformation matrix combining the current
3020 window/viewport and world transformation.
3022 It is advisable to use combinedTransform() instead of this
3023 function to preserve the properties of perspective transformations.
3025 \sa setWorldTransform(), setWindow(), setViewport()
3027 QMatrix QPainter::combinedMatrix() const
3029 return combinedTransform().toAffine();
3036 Returns the matrix that transforms from logical coordinates to
3037 device coordinates of the platform dependent paint device.
3039 \note It is advisable to use deviceTransform() instead of this
3040 function to preserve the properties of perspective transformations.
3042 This function is \e only needed when using platform painting
3043 commands on the platform dependent handle (Qt::HANDLE), and the
3044 platform does not do transformations nativly.
3046 The QPaintEngine::PaintEngineFeature enum can be queried to
3047 determine whether the platform performs the transformations or
3050 \sa worldMatrix(), QPaintEngine::hasFeature(),
3052 const QMatrix &QPainter::deviceMatrix() const
3054 Q_D(const QPainter);
3056 qWarning("QPainter::deviceMatrix: Painter not active");
3057 return d->fakeState()->transform.toAffine();
3059 return d->state->matrix.toAffine();
3065 Resets any transformations that were made using translate(), scale(),
3066 shear(), rotate(), setWorldMatrix(), setViewport() and
3069 It is advisable to use resetTransform() instead of this function
3070 to preserve the properties of perspective transformations.
3072 \sa {QPainter#Coordinate Transformations}{Coordinate
3076 void QPainter::resetMatrix()
3085 Enables transformations if \a enable is true, or disables
3086 transformations if \a enable is false. The world transformation
3087 matrix is not changed.
3089 \sa worldMatrixEnabled(), worldTransform(), {QPainter#Coordinate
3090 Transformations}{Coordinate Transformations}
3093 void QPainter::setWorldMatrixEnabled(bool enable)
3096 #ifdef QT_DEBUG_DRAW
3097 if (qt_show_painter_debug_output)
3098 printf("QPainter::setMatrixEnabled(), enable=%d\n", enable);
3102 qWarning("QPainter::setMatrixEnabled: Painter not active");
3105 if (enable == d->state->WxF)
3108 d->state->WxF = enable;
3115 Returns true if world transformation is enabled; otherwise returns
3118 \sa setWorldMatrixEnabled(), worldTransform(), {Coordinate System}
3121 bool QPainter::worldMatrixEnabled() const
3123 Q_D(const QPainter);
3125 qWarning("QPainter::worldMatrixEnabled: Painter not active");
3128 return d->state->WxF;
3134 Use setWorldMatrixEnabled() instead.
3136 \sa setWorldMatrixEnabled()
3139 void QPainter::setMatrixEnabled(bool enable)
3141 setWorldMatrixEnabled(enable);
3147 Use worldMatrixEnabled() instead
3149 \sa worldMatrixEnabled()
3152 bool QPainter::matrixEnabled() const
3154 return worldMatrixEnabled();
3158 Scales the coordinate system by (\a{sx}, \a{sy}).
3160 \sa setWorldTransform() {QPainter#Coordinate Transformations}{Coordinate
3164 void QPainter::scale(qreal sx, qreal sy)
3166 #ifdef QT_DEBUG_DRAW
3167 if (qt_show_painter_debug_output)
3168 printf("QPainter::scale(), sx=%f, sy=%f\n", sx, sy);
3172 qWarning("QPainter::scale: Painter not active");
3176 d->state->worldMatrix.scale(sx,sy);
3177 d->state->WxF = true;
3182 Shears the coordinate system by (\a{sh}, \a{sv}).
3184 \sa setWorldTransform(), {QPainter#Coordinate Transformations}{Coordinate
3188 void QPainter::shear(qreal sh, qreal sv)
3190 #ifdef QT_DEBUG_DRAW
3191 if (qt_show_painter_debug_output)
3192 printf("QPainter::shear(), sh=%f, sv=%f\n", sh, sv);
3196 qWarning("QPainter::shear: Painter not active");
3200 d->state->worldMatrix.shear(sh, sv);
3201 d->state->WxF = true;
3206 \fn void QPainter::rotate(qreal angle)
3208 Rotates the coordinate system the given \a angle clockwise.
3210 \sa setWorldTransform(), {QPainter#Coordinate Transformations}{Coordinate
3214 void QPainter::rotate(qreal a)
3216 #ifdef QT_DEBUG_DRAW
3217 if (qt_show_painter_debug_output)
3218 printf("QPainter::rotate(), angle=%f\n", a);
3222 qWarning("QPainter::rotate: Painter not active");
3226 d->state->worldMatrix.rotate(a);
3227 d->state->WxF = true;
3232 Translates the coordinate system by the given \a offset; i.e. the
3233 given \a offset is added to points.
3235 \sa setWorldTransform(), {QPainter#Coordinate Transformations}{Coordinate
3238 void QPainter::translate(const QPointF &offset)
3240 qreal dx = offset.x();
3241 qreal dy = offset.y();
3242 #ifdef QT_DEBUG_DRAW
3243 if (qt_show_painter_debug_output)
3244 printf("QPainter::translate(), dx=%f, dy=%f\n", dx, dy);
3248 qWarning("QPainter::translate: Painter not active");
3252 d->state->worldMatrix.translate(dx, dy);
3253 d->state->WxF = true;
3258 \fn void QPainter::translate(const QPoint &offset)
3261 Translates the coordinate system by the given \a offset.
3265 \fn void QPainter::translate(qreal dx, qreal dy)
3268 Translates the coordinate system by the vector (\a dx, \a dy).
3272 \fn void QPainter::setClipPath(const QPainterPath &path, Qt::ClipOperation operation)
3274 Enables clipping, and sets the clip path for the painter to the
3275 given \a path, with the clip \a operation.
3277 Note that the clip path is specified in logical (painter)
3280 \sa clipPath(), clipRegion(), {QPainter#Clipping}{Clipping}
3283 void QPainter::setClipPath(const QPainterPath &path, Qt::ClipOperation op)
3285 #ifdef QT_DEBUG_DRAW
3286 if (qt_show_painter_debug_output) {
3287 QRectF b = path.boundingRect();
3288 printf("QPainter::setClipPath(), size=%d, op=%d, bounds=[%.2f,%.2f,%.2f,%.2f]\n",
3289 path.elementCount(), op, b.x(), b.y(), b.width(), b.height());
3295 qWarning("QPainter::setClipPath: Painter not active");
3299 if ((!d->state->clipEnabled && op != Qt::NoClip))
3300 op = Qt::ReplaceClip;
3303 d->state->clipEnabled = true;
3304 d->extended->clip(path, op);
3305 if (op == Qt::NoClip || op == Qt::ReplaceClip)
3306 d->state->clipInfo.clear();
3307 d->state->clipInfo << QPainterClipInfo(path, op, d->state->matrix);
3308 d->state->clipOperation = op;
3312 d->state->clipPath = path;
3313 d->state->clipOperation = op;
3314 if (op == Qt::NoClip || op == Qt::ReplaceClip)
3315 d->state->clipInfo.clear();
3316 d->state->clipInfo << QPainterClipInfo(path, op, d->state->matrix);
3317 d->state->clipEnabled = true;
3318 d->state->dirtyFlags |= QPaintEngine::DirtyClipPath | QPaintEngine::DirtyClipEnabled;
3319 d->updateState(d->state);
3323 Draws the outline (strokes) the path \a path with the pen specified
3326 \sa fillPath(), {QPainter#Drawing}{Drawing}
3328 void QPainter::strokePath(const QPainterPath &path, const QPen &pen)
3333 qWarning("QPainter::strokePath: Painter not active");
3341 const QGradient *g = qpen_brush(pen).gradient();
3342 if (!g || g->coordinateMode() == QGradient::LogicalMode) {
3343 d->extended->stroke(qtVectorPathForPath(path), pen);
3348 QBrush oldBrush = d->state->brush;
3349 QPen oldPen = d->state->pen;
3352 setBrush(Qt::NoBrush);
3362 Fills the given \a path using the given \a brush. The outline is
3365 Alternatively, you can specify a QColor instead of a QBrush; the
3366 QBrush constructor (taking a QColor argument) will automatically
3367 create a solid pattern brush.
3371 void QPainter::fillPath(const QPainterPath &path, const QBrush &brush)
3376 qWarning("QPainter::fillPath: Painter not active");
3384 const QGradient *g = brush.gradient();
3385 if (!g || g->coordinateMode() == QGradient::LogicalMode) {
3386 d->extended->fill(qtVectorPathForPath(path), brush);
3391 QBrush oldBrush = d->state->brush;
3392 QPen oldPen = d->state->pen;
3405 Draws the given painter \a path using the current pen for outline
3406 and the current brush for filling.
3410 \o \inlineimage qpainter-path.png
3412 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 5
3415 \sa {painting/painterpaths}{the Painter Paths
3416 example},{painting/deform}{the Vector Deformation example}
3418 void QPainter::drawPath(const QPainterPath &path)
3420 #ifdef QT_DEBUG_DRAW
3421 QRectF pathBounds = path.boundingRect();
3422 if (qt_show_painter_debug_output)
3423 printf("QPainter::drawPath(), size=%d, [%.2f,%.2f,%.2f,%.2f]\n",
3424 path.elementCount(),
3425 pathBounds.x(), pathBounds.y(), pathBounds.width(), pathBounds.height());
3431 qWarning("QPainter::drawPath: Painter not active");
3436 d->extended->drawPath(path);
3439 d->updateState(d->state);
3441 if (d->engine->hasFeature(QPaintEngine::PainterPaths) && d->state->emulationSpecifier == 0) {
3442 d->engine->drawPath(path);
3444 d->draw_helper(path);
3449 \fn void QPainter::drawLine(const QLineF &line)
3451 Draws a line defined by \a line.
3455 \o \inlineimage qpainter-line.png
3457 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 6
3460 \sa drawLines(), drawPolyline(), {Coordinate System}
3464 \fn void QPainter::drawLine(const QLine &line)
3467 Draws a line defined by \a line.
3471 \fn void QPainter::drawLine(const QPoint &p1, const QPoint &p2)
3474 Draws a line from \a p1 to \a p2.
3478 \fn void QPainter::drawLine(const QPointF &p1, const QPointF &p2)
3481 Draws a line from \a p1 to \a p2.
3485 \fn void QPainter::drawLine(int x1, int y1, int x2, int y2)
3488 Draws a line from (\a x1, \a y1) to (\a x2, \a y2) and sets the
3489 current pen position to (\a x2, \a y2).
3493 \fn void QPainter::drawRect(const QRectF &rectangle)
3495 Draws the current \a rectangle with the current pen and brush.
3497 A filled rectangle has a size of \a{rectangle}.size(). A stroked
3498 rectangle has a size of \a{rectangle}.size() plus the pen width.
3502 \o \inlineimage qpainter-rectangle.png
3504 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 7
3507 \sa drawRects(), drawPolygon(), {Coordinate System}
3511 \fn void QPainter::drawRect(const QRect &rectangle)
3515 Draws the current \a rectangle with the current pen and brush.
3519 \fn void QPainter::drawRect(int x, int y, int width, int height)
3523 Draws a rectangle with upper left corner at (\a{x}, \a{y}) and
3524 with the given \a width and \a height.
3528 \fn void QPainter::drawRects(const QRectF *rectangles, int rectCount)
3530 Draws the first \a rectCount of the given \a rectangles using the
3531 current pen and brush.
3535 void QPainter::drawRects(const QRectF *rects, int rectCount)
3537 #ifdef QT_DEBUG_DRAW
3538 if (qt_show_painter_debug_output)
3539 printf("QPainter::drawRects(), count=%d\n", rectCount);
3544 qWarning("QPainter::drawRects: Painter not active");
3552 d->extended->drawRects(rects, rectCount);
3556 d->updateState(d->state);
3558 if (!d->state->emulationSpecifier) {
3559 d->engine->drawRects(rects, rectCount);
3563 if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
3564 && d->state->matrix.type() == QTransform::TxTranslate) {
3565 for (int i=0; i<rectCount; ++i) {
3566 QRectF r(rects[i].x() + d->state->matrix.dx(),
3567 rects[i].y() + d->state->matrix.dy(),
3570 d->engine->drawRects(&r, 1);
3573 if (d->state->brushNeedsResolving() || d->state->penNeedsResolving()) {
3574 for (int i=0; i<rectCount; ++i) {
3575 QPainterPath rectPath;
3576 rectPath.addRect(rects[i]);
3577 d->draw_helper(rectPath, QPainterPrivate::StrokeAndFillDraw);
3580 QPainterPath rectPath;
3581 for (int i=0; i<rectCount; ++i)
3582 rectPath.addRect(rects[i]);
3583 d->draw_helper(rectPath, QPainterPrivate::StrokeAndFillDraw);
3589 \fn void QPainter::drawRects(const QRect *rectangles, int rectCount)
3592 Draws the first \a rectCount of the given \a rectangles using the
3593 current pen and brush.
3595 void QPainter::drawRects(const QRect *rects, int rectCount)
3597 #ifdef QT_DEBUG_DRAW
3598 if (qt_show_painter_debug_output)
3599 printf("QPainter::drawRects(), count=%d\n", rectCount);
3604 qWarning("QPainter::drawRects: Painter not active");
3612 d->extended->drawRects(rects, rectCount);
3616 d->updateState(d->state);
3618 if (!d->state->emulationSpecifier) {
3619 d->engine->drawRects(rects, rectCount);
3623 if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
3624 && d->state->matrix.type() == QTransform::TxTranslate) {
3625 for (int i=0; i<rectCount; ++i) {
3626 QRectF r(rects[i].x() + d->state->matrix.dx(),
3627 rects[i].y() + d->state->matrix.dy(),
3631 d->engine->drawRects(&r, 1);
3634 if (d->state->brushNeedsResolving() || d->state->penNeedsResolving()) {
3635 for (int i=0; i<rectCount; ++i) {
3636 QPainterPath rectPath;
3637 rectPath.addRect(rects[i]);
3638 d->draw_helper(rectPath, QPainterPrivate::StrokeAndFillDraw);
3641 QPainterPath rectPath;
3642 for (int i=0; i<rectCount; ++i)
3643 rectPath.addRect(rects[i]);
3645 d->draw_helper(rectPath, QPainterPrivate::StrokeAndFillDraw);
3651 \fn void QPainter::drawRects(const QVector<QRectF> &rectangles)
3654 Draws the given \a rectangles using the current pen and brush.
3658 \fn void QPainter::drawRects(const QVector<QRect> &rectangles)
3662 Draws the given \a rectangles using the current pen and brush.
3666 \fn void QPainter::drawPoint(const QPointF &position)
3668 Draws a single point at the given \a position using the current
3671 \sa {Coordinate System}
3675 \fn void QPainter::drawPoint(const QPoint &position)
3678 Draws a single point at the given \a position using the current
3682 /*! \fn void QPainter::drawPoint(int x, int y)
3686 Draws a single point at position (\a x, \a y).
3690 Draws the first \a pointCount points in the array \a points using
3691 the current pen's color.
3693 \sa {Coordinate System}
3695 void QPainter::drawPoints(const QPointF *points, int pointCount)
3697 #ifdef QT_DEBUG_DRAW
3698 if (qt_show_painter_debug_output)
3699 printf("QPainter::drawPoints(), count=%d\n", pointCount);
3704 qWarning("QPainter::drawPoints: Painter not active");
3708 if (pointCount <= 0)
3712 d->extended->drawPoints(points, pointCount);
3716 d->updateState(d->state);
3718 if (!d->state->emulationSpecifier) {
3719 d->engine->drawPoints(points, pointCount);
3723 if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
3724 && d->state->matrix.type() == QTransform::TxTranslate) {
3725 // ### use drawPoints function
3726 for (int i=0; i<pointCount; ++i) {
3727 QPointF pt(points[i].x() + d->state->matrix.dx(),
3728 points[i].y() + d->state->matrix.dy());
3729 d->engine->drawPoints(&pt, 1);
3732 QPen pen = d->state->pen;
3733 bool flat_pen = pen.capStyle() == Qt::FlatCap;
3736 pen.setCapStyle(Qt::SquareCap);
3740 for (int i=0; i<pointCount; ++i) {
3741 path.moveTo(points[i].x(), points[i].y());
3742 path.lineTo(points[i].x() + 0.0001, points[i].y());
3744 d->draw_helper(path, QPainterPrivate::StrokeDraw);
3753 Draws the first \a pointCount points in the array \a points using
3754 the current pen's color.
3757 void QPainter::drawPoints(const QPoint *points, int pointCount)
3759 #ifdef QT_DEBUG_DRAW
3760 if (qt_show_painter_debug_output)
3761 printf("QPainter::drawPoints(), count=%d\n", pointCount);
3766 qWarning("QPainter::drawPoints: Painter not active");
3770 if (pointCount <= 0)
3774 d->extended->drawPoints(points, pointCount);
3778 d->updateState(d->state);
3780 if (!d->state->emulationSpecifier) {
3781 d->engine->drawPoints(points, pointCount);
3785 if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
3786 && d->state->matrix.type() == QTransform::TxTranslate) {
3787 // ### use drawPoints function
3788 for (int i=0; i<pointCount; ++i) {
3789 QPointF pt(points[i].x() + d->state->matrix.dx(),
3790 points[i].y() + d->state->matrix.dy());
3791 d->engine->drawPoints(&pt, 1);
3794 QPen pen = d->state->pen;
3795 bool flat_pen = (pen.capStyle() == Qt::FlatCap);
3798 pen.setCapStyle(Qt::SquareCap);
3802 for (int i=0; i<pointCount; ++i) {
3803 path.moveTo(points[i].x(), points[i].y());
3804 path.lineTo(points[i].x() + 0.0001, points[i].y());
3806 d->draw_helper(path, QPainterPrivate::StrokeDraw);
3813 \fn void QPainter::drawPoints(const QPolygonF &points)
3817 Draws the points in the vector \a points.
3821 \fn void QPainter::drawPoints(const QPolygon &points)
3825 Draws the points in the vector \a points.
3829 \fn void QPainter::drawPoints(const QPolygon &polygon, int index,
3835 Draws \a count points in the vector \a polygon starting on \a index
3836 using the current pen.
3838 Use drawPoints() combined with QPolygon::constData() instead.
3841 QPainter painter(this);
3842 painter.drawPoints(polygon, index, count);
3844 int pointCount = (count == -1) ? polygon.size() - index : count;
3846 QPainter painter(this);
3847 painter.drawPoints(polygon.constData() + index, pointCount);
3852 Sets the background mode of the painter to the given \a mode
3854 Qt::TransparentMode (the default) draws stippled lines and text
3855 without setting the background pixels. Qt::OpaqueMode fills these
3856 space with the current background color.
3858 Note that in order to draw a bitmap or pixmap transparently, you
3859 must use QPixmap::setMask().
3861 \sa backgroundMode(), setBackground(),
3862 {QPainter#Settings}{Settings}
3865 void QPainter::setBackgroundMode(Qt::BGMode mode)
3867 #ifdef QT_DEBUG_DRAW
3868 if (qt_show_painter_debug_output)
3869 printf("QPainter::setBackgroundMode(), mode=%d\n", mode);
3874 qWarning("QPainter::setBackgroundMode: Painter not active");
3877 if (d->state->bgMode == mode)
3880 d->state->bgMode = mode;
3882 d->checkEmulation();
3884 d->state->dirtyFlags |= QPaintEngine::DirtyBackgroundMode;
3889 Returns the current background mode.
3891 \sa setBackgroundMode(), {QPainter#Settings}{Settings}
3893 Qt::BGMode QPainter::backgroundMode() const
3895 Q_D(const QPainter);
3897 qWarning("QPainter::backgroundMode: Painter not active");
3898 return Qt::TransparentMode;
3900 return d->state->bgMode;
3907 Sets the painter's pen to have style Qt::SolidLine, width 0 and the
3911 void QPainter::setPen(const QColor &color)
3913 #ifdef QT_DEBUG_DRAW
3914 if (qt_show_painter_debug_output)
3915 printf("QPainter::setPen(), color=%04x\n", color.rgb());
3919 qWarning("QPainter::setPen: Painter not active");
3923 if (d->state->pen.style() == Qt::SolidLine
3924 && d->state->pen.widthF() == 0
3925 && d->state->pen.isSolid()
3926 && d->state->pen.color() == color)
3929 QPen pen(color.isValid() ? color : QColor(Qt::black), 0, Qt::SolidLine);
3931 d->state->pen = pen;
3933 d->extended->penChanged();
3935 d->state->dirtyFlags |= QPaintEngine::DirtyPen;
3939 Sets the painter's pen to be the given \a pen.
3941 The \a pen defines how to draw lines and outlines, and it also
3942 defines the text color.
3944 \sa pen(), {QPainter#Settings}{Settings}
3947 void QPainter::setPen(const QPen &pen)
3950 #ifdef QT_DEBUG_DRAW
3951 if (qt_show_painter_debug_output)
3952 printf("QPainter::setPen(), color=%04x, (brushStyle=%d) style=%d, cap=%d, join=%d\n",
3953 pen.color().rgb(), pen.brush().style(), pen.style(), pen.capStyle(), pen.joinStyle());
3957 qWarning("QPainter::setPen: Painter not active");
3961 if (d->state->pen == pen)
3964 d->state->pen = pen;
3967 d->checkEmulation();
3968 d->extended->penChanged();
3972 d->state->dirtyFlags |= QPaintEngine::DirtyPen;
3978 Sets the painter's pen to have the given \a style, width 0 and
3982 void QPainter::setPen(Qt::PenStyle style)
3986 qWarning("QPainter::setPen: Painter not active");
3990 if (d->state->pen.style() == style
3991 && (style == Qt::NoPen || (d->state->pen.widthF() == 0
3992 && d->state->pen.isSolid()
3993 && d->state->pen.color() == QColor(Qt::black))))
3996 // QPen(Qt::NoPen) is to avoid creating QPenData, including its brush (from the color)
3997 // Note that this works well as long as QPen(Qt::NoPen) returns a black, zero-width pen
3998 d->state->pen = (style == Qt::NoPen) ? QPen(Qt::NoPen) : QPen(Qt::black, 0, style);
4001 d->extended->penChanged();
4003 d->state->dirtyFlags |= QPaintEngine::DirtyPen;
4008 Returns the painter's current pen.
4010 \sa setPen(), {QPainter#Settings}{Settings}
4013 const QPen &QPainter::pen() const
4015 Q_D(const QPainter);
4017 qWarning("QPainter::pen: Painter not active");
4018 return d->fakeState()->pen;
4020 return d->state->pen;
4025 Sets the painter's brush to the given \a brush.
4027 The painter's brush defines how shapes are filled.
4029 \sa brush(), {QPainter#Settings}{Settings}
4032 void QPainter::setBrush(const QBrush &brush)
4034 #ifdef QT_DEBUG_DRAW
4035 if (qt_show_painter_debug_output)
4036 printf("QPainter::setBrush(), color=%04x, style=%d\n", brush.color().rgb(), brush.style());
4040 qWarning("QPainter::setBrush: Painter not active");
4044 if (d->state->brush.d == brush.d)
4048 d->state->brush = brush;
4049 d->checkEmulation();
4050 d->extended->brushChanged();
4054 d->state->brush = brush;
4055 d->state->dirtyFlags |= QPaintEngine::DirtyBrush;
4062 Sets the painter's brush to black color and the specified \a
4066 void QPainter::setBrush(Qt::BrushStyle style)
4070 qWarning("QPainter::setBrush: Painter not active");
4073 if (d->state->brush.style() == style &&
4074 (style == Qt::NoBrush
4075 || (style == Qt::SolidPattern && d->state->brush.color() == QColor(0, 0, 0))))
4077 d->state->brush = QBrush(Qt::black, style);
4079 d->extended->brushChanged();
4081 d->state->dirtyFlags |= QPaintEngine::DirtyBrush;
4085 Returns the painter's current brush.
4087 \sa QPainter::setBrush(), {QPainter#Settings}{Settings}
4090 const QBrush &QPainter::brush() const
4092 Q_D(const QPainter);
4094 qWarning("QPainter::brush: Painter not active");
4095 return d->fakeState()->brush;
4097 return d->state->brush;
4101 \fn void QPainter::setBackground(const QBrush &brush)
4103 Sets the background brush of the painter to the given \a brush.
4105 The background brush is the brush that is filled in when drawing
4106 opaque text, stippled lines and bitmaps. The background brush has
4107 no effect in transparent background mode (which is the default).
4109 \sa background(), setBackgroundMode(),
4110 {QPainter#Settings}{Settings}
4113 void QPainter::setBackground(const QBrush &bg)
4115 #ifdef QT_DEBUG_DRAW
4116 if (qt_show_painter_debug_output)
4117 printf("QPainter::setBackground(), color=%04x, style=%d\n", bg.color().rgb(), bg.style());
4122 qWarning("QPainter::setBackground: Painter not active");
4125 d->state->bgBrush = bg;
4127 d->state->dirtyFlags |= QPaintEngine::DirtyBackground;
4131 Sets the painter's font to the given \a font.
4133 This font is used by subsequent drawText() functions. The text
4134 color is the same as the pen color.
4136 If you set a font that isn't available, Qt finds a close match.
4137 font() will return what you set using setFont() and fontInfo() returns the
4138 font actually being used (which may be the same).
4140 \sa font(), drawText(), {QPainter#Settings}{Settings}
4143 void QPainter::setFont(const QFont &font)
4147 #ifdef QT_DEBUG_DRAW
4148 if (qt_show_painter_debug_output)
4149 printf("QPainter::setFont(), family=%s, pointSize=%d\n", font.family().toLatin1().constData(), font.pointSize());
4153 qWarning("QPainter::setFont: Painter not active");
4157 d->state->font = QFont(font.resolve(d->state->deviceFont), device());
4159 d->state->dirtyFlags |= QPaintEngine::DirtyFont;
4163 Returns the currently set font used for drawing text.
4165 \sa setFont(), drawText(), {QPainter#Settings}{Settings}
4167 const QFont &QPainter::font() const
4169 Q_D(const QPainter);
4171 qWarning("QPainter::font: Painter not active");
4172 return d->fakeState()->font;
4174 return d->state->font;
4180 Draws the given rectangle \a rect with rounded corners.
4182 The \a xRadius and \a yRadius arguments specify the radii
4183 of the ellipses defining the corners of the rounded rectangle.
4184 When \a mode is Qt::RelativeSize, \a xRadius and
4185 \a yRadius are specified in percentage of half the rectangle's
4186 width and height respectively, and should be in the range
4189 A filled rectangle has a size of rect.size(). A stroked rectangle
4190 has a size of rect.size() plus the pen width.
4194 \o \inlineimage qpainter-roundrect.png
4196 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 8
4199 \sa drawRect(), QPen
4201 void QPainter::drawRoundedRect(const QRectF &rect, qreal xRadius, qreal yRadius, Qt::SizeMode mode)
4203 #ifdef QT_DEBUG_DRAW
4204 if (qt_show_painter_debug_output)
4205 printf("QPainter::drawRoundedRect(), [%.2f,%.2f,%.2f,%.2f]\n", rect.x(), rect.y(), rect.width(), rect.height());
4212 if (xRadius <= 0 || yRadius <= 0) { // draw normal rectangle
4218 d->extended->drawRoundedRect(rect, xRadius, yRadius, mode);
4223 path.addRoundedRect(rect, xRadius, yRadius, mode);
4228 \fn void QPainter::drawRoundedRect(const QRect &rect, qreal xRadius, qreal yRadius,
4229 Qt::SizeMode mode = Qt::AbsoluteSize);
4233 Draws the given rectangle \a rect with rounded corners.
4237 \fn void QPainter::drawRoundedRect(int x, int y, int w, int h, qreal xRadius, qreal yRadius,
4238 Qt::SizeMode mode = Qt::AbsoluteSize);
4242 Draws the given rectangle \a x, \a y, \a w, \a h with rounded corners.
4248 Draws a rectangle \a r with rounded corners.
4250 The \a xRnd and \a yRnd arguments specify how rounded the corners
4251 should be. 0 is angled corners, 99 is maximum roundedness.
4253 A filled rectangle has a size of r.size(). A stroked rectangle
4254 has a size of r.size() plus the pen width.
4256 \sa drawRoundedRect()
4258 void QPainter::drawRoundRect(const QRectF &r, int xRnd, int yRnd)
4260 drawRoundedRect(r, xRnd, yRnd, Qt::RelativeSize);
4265 \fn void QPainter::drawRoundRect(const QRect &r, int xRnd = 25, int yRnd = 25)
4270 Draws the rectangle \a r with rounded corners.
4276 \fn QPainter::drawRoundRect(int x, int y, int w, int h, int xRnd, int yRnd)
4280 Draws the rectangle \a x, \a y, \a w, \a h with rounded corners.
4284 \fn void QPainter::drawEllipse(const QRectF &rectangle)
4286 Draws the ellipse defined by the given \a rectangle.
4288 A filled ellipse has a size of \a{rectangle}.\l
4289 {QRect::size()}{size()}. A stroked ellipse has a size of
4290 \a{rectangle}.\l {QRect::size()}{size()} plus the pen width.
4294 \o \inlineimage qpainter-ellipse.png
4296 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 9
4299 \sa drawPie(), {Coordinate System}
4301 void QPainter::drawEllipse(const QRectF &r)
4303 #ifdef QT_DEBUG_DRAW
4304 if (qt_show_painter_debug_output)
4305 printf("QPainter::drawEllipse(), [%.2f,%.2f,%.2f,%.2f]\n", r.x(), r.y(), r.width(), r.height());
4312 QRectF rect(r.normalized());
4315 d->extended->drawEllipse(rect);
4319 d->updateState(d->state);
4320 if (d->state->emulationSpecifier) {
4321 if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
4322 && d->state->matrix.type() == QTransform::TxTranslate) {
4323 rect.translate(QPointF(d->state->matrix.dx(), d->state->matrix.dy()));
4326 path.addEllipse(rect);
4327 d->draw_helper(path, QPainterPrivate::StrokeAndFillDraw);
4332 d->engine->drawEllipse(rect);
4336 \fn QPainter::drawEllipse(const QRect &rectangle)
4340 Draws the ellipse defined by the given \a rectangle.
4342 void QPainter::drawEllipse(const QRect &r)
4344 #ifdef QT_DEBUG_DRAW
4345 if (qt_show_painter_debug_output)
4346 printf("QPainter::drawEllipse(), [%d,%d,%d,%d]\n", r.x(), r.y(), r.width(), r.height());
4353 QRect rect(r.normalized());
4356 d->extended->drawEllipse(rect);
4360 d->updateState(d->state);
4362 if (d->state->emulationSpecifier) {
4363 if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
4364 && d->state->matrix.type() == QTransform::TxTranslate) {
4365 rect.translate(QPoint(qRound(d->state->matrix.dx()), qRound(d->state->matrix.dy())));
4368 path.addEllipse(rect);
4369 d->draw_helper(path, QPainterPrivate::StrokeAndFillDraw);
4374 d->engine->drawEllipse(rect);
4378 \fn QPainter::drawEllipse(int x, int y, int width, int height)
4382 Draws the ellipse defined by the rectangle beginning at (\a{x},
4383 \a{y}) with the given \a width and \a height.
4389 \fn QPainter::drawEllipse(const QPointF ¢er, qreal rx, qreal ry)
4393 Draws the ellipse positioned at \a{center} with radii \a{rx} and \a{ry}.
4399 \fn QPainter::drawEllipse(const QPoint ¢er, int rx, int ry)
4403 Draws the ellipse positioned at \a{center} with radii \a{rx} and \a{ry}.
4407 \fn void QPainter::drawArc(const QRectF &rectangle, int startAngle, int spanAngle)
4409 Draws the arc defined by the given \a rectangle, \a startAngle and
4412 The \a startAngle and \a spanAngle must be specified in 1/16th of
4413 a degree, i.e. a full circle equals 5760 (16 * 360). Positive
4414 values for the angles mean counter-clockwise while negative values
4415 mean the clockwise direction. Zero degrees is at the 3 o'clock
4420 \o \inlineimage qpainter-arc.png
4422 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 10
4425 \sa drawPie(), drawChord(), {Coordinate System}
4428 void QPainter::drawArc(const QRectF &r, int a, int alen)
4430 #ifdef QT_DEBUG_DRAW
4431 if (qt_show_painter_debug_output)
4432 printf("QPainter::drawArc(), [%.2f,%.2f,%.2f,%.2f], angle=%d, sweep=%d\n",
4433 r.x(), r.y(), r.width(), r.height(), a/16, alen/16);
4440 QRectF rect = r.normalized();
4443 path.arcMoveTo(rect, a/16.0);
4444 path.arcTo(rect, a/16.0, alen/16.0);
4445 strokePath(path, d->state->pen);
4448 /*! \fn void QPainter::drawArc(const QRect &rectangle, int startAngle,
4453 Draws the arc defined by the given \a rectangle, \a startAngle and
4458 \fn void QPainter::drawArc(int x, int y, int width, int height,
4459 int startAngle, int spanAngle)
4463 Draws the arc defined by the rectangle beginning at (\a x, \a y)
4464 with the specified \a width and \a height, and the given \a
4465 startAngle and \a spanAngle.
4469 \fn void QPainter::drawPie(const QRectF &rectangle, int startAngle, int spanAngle)
4471 Draws a pie defined by the given \a rectangle, \a startAngle and
4474 The pie is filled with the current brush().
4476 The startAngle and spanAngle must be specified in 1/16th of a
4477 degree, i.e. a full circle equals 5760 (16 * 360). Positive values
4478 for the angles mean counter-clockwise while negative values mean
4479 the clockwise direction. Zero degrees is at the 3 o'clock
4484 \o \inlineimage qpainter-pie.png
4486 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 11
4489 \sa drawEllipse(), drawChord(), {Coordinate System}
4491 void QPainter::drawPie(const QRectF &r, int a, int alen)
4493 #ifdef QT_DEBUG_DRAW
4494 if (qt_show_painter_debug_output)
4495 printf("QPainter::drawPie(), [%.2f,%.2f,%.2f,%.2f], angle=%d, sweep=%d\n",
4496 r.x(), r.y(), r.width(), r.height(), a/16, alen/16);
4507 if (a < 0) a += (360*16);
4510 QRectF rect = r.normalized();
4513 path.moveTo(rect.center());
4514 path.arcTo(rect.x(), rect.y(), rect.width(), rect.height(), a/16.0, alen/16.0);
4515 path.closeSubpath();
4521 \fn void QPainter::drawPie(const QRect &rectangle, int startAngle, int spanAngle)
4524 Draws a pie defined by the given \a rectangle, \a startAngle and
4529 \fn void QPainter::drawPie(int x, int y, int width, int height, int
4530 startAngle, int spanAngle)
4534 Draws the pie defined by the rectangle beginning at (\a x, \a y) with
4535 the specified \a width and \a height, and the given \a startAngle and
4540 \fn void QPainter::drawChord(const QRectF &rectangle, int startAngle, int spanAngle)
4542 Draws the chord defined by the given \a rectangle, \a startAngle and
4543 \a spanAngle. The chord is filled with the current brush().
4545 The startAngle and spanAngle must be specified in 1/16th of a
4546 degree, i.e. a full circle equals 5760 (16 * 360). Positive values
4547 for the angles mean counter-clockwise while negative values mean
4548 the clockwise direction. Zero degrees is at the 3 o'clock
4553 \o \inlineimage qpainter-chord.png
4555 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 12
4558 \sa drawArc(), drawPie(), {Coordinate System}
4560 void QPainter::drawChord(const QRectF &r, int a, int alen)
4562 #ifdef QT_DEBUG_DRAW
4563 if (qt_show_painter_debug_output)
4564 printf("QPainter::drawChord(), [%.2f,%.2f,%.2f,%.2f], angle=%d, sweep=%d\n",
4565 r.x(), r.y(), r.width(), r.height(), a/16, alen/16);
4572 QRectF rect = r.normalized();
4575 path.arcMoveTo(rect, a/16.0);
4576 path.arcTo(rect, a/16.0, alen/16.0);
4577 path.closeSubpath();
4581 \fn void QPainter::drawChord(const QRect &rectangle, int startAngle, int spanAngle)
4585 Draws the chord defined by the given \a rectangle, \a startAngle and
4590 \fn void QPainter::drawChord(int x, int y, int width, int height, int
4591 startAngle, int spanAngle)
4595 Draws the chord defined by the rectangle beginning at (\a x, \a y)
4596 with the specified \a width and \a height, and the given \a
4597 startAngle and \a spanAngle.
4602 \fn void QPainter::drawLineSegments(const QPolygon &polygon, int
4605 Draws \a count separate lines from points defined by the \a
4606 polygon, starting at \a{polygon}\e{[index]} (\a index defaults to
4607 0). If \a count is -1 (the default) all points until the end of
4610 Use drawLines() combined with QPolygon::constData() instead.
4613 QPainter painter(this);
4614 painter.drawLineSegments(polygon, index, count);
4616 int lineCount = (count == -1) ? (polygon.size() - index) / 2 : count;
4618 QPainter painter(this);
4619 painter.drawLines(polygon.constData() + index * 2, lineCount);
4623 void QPainter::drawLineSegments(const QPolygon &a, int index, int nlines)
4625 #ifdef QT_DEBUG_DRAW
4626 if (qt_show_painter_debug_output)
4627 printf("QPainter::drawLineSegments(), count=%d\n", a.size()/2);
4635 nlines = a.size()/2 - index/2;
4636 if (index + nlines*2 > (int)a.size())
4637 nlines = (a.size() - index)/2;
4638 if (nlines < 1 || index < 0)
4642 // FALCON: Use QVectorPath
4643 QVector<QLineF> lines;
4644 for (int i=index; i<index + nlines*2; i+=2)
4645 lines << QLineF(a.at(i), a.at(i+1));
4646 d->extended->drawLines(lines.data(), lines.size());
4650 d->updateState(d->state);
4652 QVector<QLineF> lines;
4653 if (d->state->emulationSpecifier) {
4654 if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
4655 && d->state->matrix.type() == QTransform::TxTranslate) {
4656 QPointF offset(d->state->matrix.dx(), d->state->matrix.dy());
4657 for (int i=index; i<index + nlines*2; i+=2)
4658 lines << QLineF(a.at(i) + offset, a.at(i+1) + offset);
4660 QPainterPath linesPath;
4661 for (int i=index; i<index + nlines*2; i+=2) {
4662 linesPath.moveTo(a.at(i));
4663 linesPath.lineTo(a.at(i+1));
4665 d->draw_helper(linesPath, QPainterPrivate::StrokeDraw);
4669 for (int i=index; i<index + nlines*2; i+=2)
4670 lines << QLineF(a.at(i), a.at(i+1));
4673 d->engine->drawLines(lines.data(), lines.size());
4675 #endif // QT3_SUPPORT
4678 Draws the first \a lineCount lines in the array \a lines
4679 using the current pen.
4681 \sa drawLine(), drawPolyline()
4683 void QPainter::drawLines(const QLineF *lines, int lineCount)
4685 #ifdef QT_DEBUG_DRAW
4686 if (qt_show_painter_debug_output)
4687 printf("QPainter::drawLines(), line count=%d\n", lineCount);
4692 if (!d->engine || lineCount < 1)
4696 d->extended->drawLines(lines, lineCount);
4700 d->updateState(d->state);
4702 uint lineEmulation = line_emulation(d->state->emulationSpecifier);
4704 if (lineEmulation) {
4705 if (lineEmulation == QPaintEngine::PrimitiveTransform
4706 && d->state->matrix.type() == QTransform::TxTranslate) {
4707 for (int i = 0; i < lineCount; ++i) {
4708 QLineF line = lines[i];
4709 line.translate(d->state->matrix.dx(), d->state->matrix.dy());
4710 d->engine->drawLines(&line, 1);
4713 QPainterPath linePath;
4714 for (int i = 0; i < lineCount; ++i) {
4715 linePath.moveTo(lines[i].p1());
4716 linePath.lineTo(lines[i].p2());
4718 d->draw_helper(linePath, QPainterPrivate::StrokeDraw);
4722 d->engine->drawLines(lines, lineCount);
4726 \fn void QPainter::drawLines(const QLine *lines, int lineCount)
4729 Draws the first \a lineCount lines in the array \a lines
4730 using the current pen.
4732 void QPainter::drawLines(const QLine *lines, int lineCount)
4734 #ifdef QT_DEBUG_DRAW
4735 if (qt_show_painter_debug_output)
4736 printf("QPainter::drawLine(), line count=%d\n", lineCount);
4741 if (!d->engine || lineCount < 1)
4745 d->extended->drawLines(lines, lineCount);
4749 d->updateState(d->state);
4751 uint lineEmulation = line_emulation(d->state->emulationSpecifier);
4753 if (lineEmulation) {
4754 if (lineEmulation == QPaintEngine::PrimitiveTransform
4755 && d->state->matrix.type() == QTransform::TxTranslate) {
4756 for (int i = 0; i < lineCount; ++i) {
4757 QLineF line = lines[i];
4758 line.translate(d->state->matrix.dx(), d->state->matrix.dy());
4759 d->engine->drawLines(&line, 1);
4762 QPainterPath linePath;
4763 for (int i = 0; i < lineCount; ++i) {
4764 linePath.moveTo(lines[i].p1());
4765 linePath.lineTo(lines[i].p2());
4767 d->draw_helper(linePath, QPainterPrivate::StrokeDraw);
4771 d->engine->drawLines(lines, lineCount);
4777 Draws the first \a lineCount lines in the array \a pointPairs
4778 using the current pen. The lines are specified as pairs of points
4779 so the number of entries in \a pointPairs must be at least \a
4782 void QPainter::drawLines(const QPointF *pointPairs, int lineCount)
4784 Q_ASSERT(sizeof(QLineF) == 2*sizeof(QPointF));
4786 drawLines((QLineF*)pointPairs, lineCount);
4792 Draws the first \a lineCount lines in the array \a pointPairs
4793 using the current pen.
4795 void QPainter::drawLines(const QPoint *pointPairs, int lineCount)
4797 Q_ASSERT(sizeof(QLine) == 2*sizeof(QPoint));
4799 drawLines((QLine*)pointPairs, lineCount);
4804 \fn void QPainter::drawLines(const QVector<QPointF> &pointPairs)
4807 Draws a line for each pair of points in the vector \a pointPairs
4808 using the current pen. If there is an odd number of points in the
4809 array, the last point will be ignored.
4813 \fn void QPainter::drawLines(const QVector<QPoint> &pointPairs)
4816 Draws a line for each pair of points in the vector \a pointPairs
4817 using the current pen.
4821 \fn void QPainter::drawLines(const QVector<QLineF> &lines)
4824 Draws the set of lines defined by the list \a lines using the
4825 current pen and brush.
4829 \fn void QPainter::drawLines(const QVector<QLine> &lines)
4832 Draws the set of lines defined by the list \a lines using the
4833 current pen and brush.
4837 Draws the polyline defined by the first \a pointCount points in \a
4838 points using the current pen.
4840 Note that unlike the drawPolygon() function the last point is \e
4841 not connected to the first, neither is the polyline filled.
4846 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 13
4849 \sa drawLines(), drawPolygon(), {Coordinate System}
4851 void QPainter::drawPolyline(const QPointF *points, int pointCount)
4853 #ifdef QT_DEBUG_DRAW
4854 if (qt_show_painter_debug_output)
4855 printf("QPainter::drawPolyline(), count=%d\n", pointCount);
4859 if (!d->engine || pointCount < 2)
4863 d->extended->drawPolygon(points, pointCount, QPaintEngine::PolylineMode);
4867 d->updateState(d->state);
4869 uint lineEmulation = line_emulation(d->state->emulationSpecifier);
4871 if (lineEmulation) {
4873 // if (lineEmulation == QPaintEngine::PrimitiveTransform
4874 // && d->state->matrix.type() == QTransform::TxTranslate) {
4876 QPainterPath polylinePath(points[0]);
4877 for (int i=1; i<pointCount; ++i)
4878 polylinePath.lineTo(points[i]);
4879 d->draw_helper(polylinePath, QPainterPrivate::StrokeDraw);
4882 d->engine->drawPolygon(points, pointCount, QPaintEngine::PolylineMode);
4889 Draws the polyline defined by the first \a pointCount points in \a
4890 points using the current pen.
4892 void QPainter::drawPolyline(const QPoint *points, int pointCount)
4894 #ifdef QT_DEBUG_DRAW
4895 if (qt_show_painter_debug_output)
4896 printf("QPainter::drawPolyline(), count=%d\n", pointCount);
4900 if (!d->engine || pointCount < 2)
4904 d->extended->drawPolygon(points, pointCount, QPaintEngine::PolylineMode);
4908 d->updateState(d->state);
4910 uint lineEmulation = line_emulation(d->state->emulationSpecifier);
4912 if (lineEmulation) {
4914 // if (lineEmulation == QPaintEngine::PrimitiveTransform
4915 // && d->state->matrix.type() == QTransform::TxTranslate) {
4917 QPainterPath polylinePath(points[0]);
4918 for (int i=1; i<pointCount; ++i)
4919 polylinePath.lineTo(points[i]);
4920 d->draw_helper(polylinePath, QPainterPrivate::StrokeDraw);
4923 d->engine->drawPolygon(points, pointCount, QPaintEngine::PolylineMode);
4928 \fn void QPainter::drawPolyline(const QPolygon &polygon, int index, int
4934 Draws the polyline defined by the \a count lines of the given \a
4935 polygon starting at \a index (\a index defaults to 0).
4937 Use drawPolyline() combined with QPolygon::constData() instead.
4940 QPainter painter(this);
4941 painter.drawPolyline(polygon, index, count);
4943 int pointCount = (count == -1) ? polygon.size() - index : count;
4945 QPainter painter(this);
4946 painter.drawPolyline(polygon.constData() + index, pointCount);
4951 \fn void QPainter::drawPolyline(const QPolygonF &points)
4955 Draws the polyline defined by the given \a points using the
4960 \fn void QPainter::drawPolyline(const QPolygon &points)
4964 Draws the polyline defined by the given \a points using the
4969 Draws the polygon defined by the first \a pointCount points in the
4970 array \a points using the current pen and brush.
4974 \o \inlineimage qpainter-polygon.png
4976 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 14
4979 The first point is implicitly connected to the last point, and the
4980 polygon is filled with the current brush().
4982 If \a fillRule is Qt::WindingFill, the polygon is filled using the
4983 winding fill algorithm. If \a fillRule is Qt::OddEvenFill, the
4984 polygon is filled using the odd-even fill algorithm. See
4985 \l{Qt::FillRule} for a more detailed description of these fill
4988 \sa drawConvexPolygon(), drawPolyline(), {Coordinate System}
4990 void QPainter::drawPolygon(const QPointF *points, int pointCount, Qt::FillRule fillRule)
4992 #ifdef QT_DEBUG_DRAW
4993 if (qt_show_painter_debug_output)
4994 printf("QPainter::drawPolygon(), count=%d\n", pointCount);
4999 if (!d->engine || pointCount < 2)
5003 d->extended->drawPolygon(points, pointCount, QPaintEngine::PolygonDrawMode(fillRule));
5007 d->updateState(d->state);
5009 uint emulationSpecifier = d->state->emulationSpecifier;
5011 if (emulationSpecifier) {
5012 QPainterPath polygonPath(points[0]);
5013 for (int i=1; i<pointCount; ++i)
5014 polygonPath.lineTo(points[i]);
5015 polygonPath.closeSubpath();
5016 polygonPath.setFillRule(fillRule);
5017 d->draw_helper(polygonPath);
5021 d->engine->drawPolygon(points, pointCount, QPaintEngine::PolygonDrawMode(fillRule));
5026 Draws the polygon defined by the first \a pointCount points in the
5029 void QPainter::drawPolygon(const QPoint *points, int pointCount, Qt::FillRule fillRule)
5031 #ifdef QT_DEBUG_DRAW
5032 if (qt_show_painter_debug_output)
5033 printf("QPainter::drawPolygon(), count=%d\n", pointCount);
5038 if (!d->engine || pointCount < 2)
5042 d->extended->drawPolygon(points, pointCount, QPaintEngine::PolygonDrawMode(fillRule));
5046 d->updateState(d->state);
5048 uint emulationSpecifier = d->state->emulationSpecifier;
5050 if (emulationSpecifier) {
5051 QPainterPath polygonPath(points[0]);
5052 for (int i=1; i<pointCount; ++i)
5053 polygonPath.lineTo(points[i]);
5054 polygonPath.closeSubpath();
5055 polygonPath.setFillRule(fillRule);
5056 d->draw_helper(polygonPath);
5060 d->engine->drawPolygon(points, pointCount, QPaintEngine::PolygonDrawMode(fillRule));
5063 /*! \fn void QPainter::drawPolygon(const QPolygonF &polygon, bool winding, int index = 0,
5068 Use drawPolygon() combined with QPolygonF::constData() instead.
5071 QPainter painter(this);
5072 painter.drawPolygon(polygon, winding, index, count);
5074 int pointCount = (count == -1) ? polygon.size() - index : count;
5075 int fillRule = winding ? Qt::WindingFill : Qt::OddEvenFill;
5077 QPainter painter(this);
5078 painter.drawPolygon( polygon.constData() + index, pointCount, fillRule);
5082 /*! \fn void QPainter::drawPolygon(const QPolygon &polygon, bool winding,
5083 int index = 0, int count = -1)
5088 Use drawPolygon() combined with QPolygon::constData() instead.
5091 QPainter painter(this);
5092 painter.drawPolygon(polygon, winding, index, count);
5094 int pointCount = (count == -1) ? polygon.size() - index : count;
5095 int fillRule = winding ? Qt::WindingFill : Qt::OddEvenFill;
5097 QPainter painter(this);
5098 painter.drawPolygon( polygon.constData() + index, pointCount, fillRule);
5102 /*! \fn void QPainter::drawPolygon(const QPolygonF &points, Qt::FillRule fillRule)
5106 Draws the polygon defined by the given \a points using the fill
5110 /*! \fn void QPainter::drawPolygon(const QPolygon &points, Qt::FillRule fillRule)
5114 Draws the polygon defined by the given \a points using the fill
5119 \fn void QPainter::drawConvexPolygon(const QPointF *points, int pointCount)
5121 Draws the convex polygon defined by the first \a pointCount points
5122 in the array \a points using the current pen.
5126 \o \inlineimage qpainter-polygon.png
5128 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 15
5131 The first point is implicitly connected to the last point, and the
5132 polygon is filled with the current brush(). If the supplied
5133 polygon is not convex, i.e. it contains at least one angle larger
5134 than 180 degrees, the results are undefined.
5136 On some platforms (e.g. X11), the drawConvexPolygon() function can
5137 be faster than the drawPolygon() function.
5139 \sa drawPolygon(), drawPolyline(), {Coordinate System}
5143 \fn void QPainter::drawConvexPolygon(const QPoint *points, int pointCount)
5146 Draws the convex polygon defined by the first \a pointCount points
5147 in the array \a points using the current pen.
5151 \fn void QPainter::drawConvexPolygon(const QPolygonF &polygon)
5155 Draws the convex polygon defined by \a polygon using the current
5160 \fn void QPainter::drawConvexPolygon(const QPolygon &polygon)
5163 Draws the convex polygon defined by \a polygon using the current
5168 \fn void QPainter::drawConvexPolygon(const QPolygonF &polygon, int
5174 Use drawConvexPolygon() combined with QPolygonF::constData()
5178 QPainter painter(this);
5179 painter.drawConvexPolygon(polygon, index, count);
5181 int pointCount = (count == -1) ? polygon.size() - index : count;
5183 QPainter painter(this);
5184 painter.drawConvexPolygon(polygon.constData() + index, pointCount);
5189 \fn void QPainter::drawConvexPolygon(const QPolygon &polygon, int
5195 Use drawConvexPolygon() combined with QPolygon::constData()
5199 QPainter painter(this);
5200 painter.drawConvexPolygon(polygon, index, count);
5202 int pointCount = (count == -1) ? polygon.size() - index : count;
5204 QPainter painter(this);
5205 painter.drawConvexPolygon(polygon.constData() + index, pointCount);
5209 void QPainter::drawConvexPolygon(const QPoint *points, int pointCount)
5211 #ifdef QT_DEBUG_DRAW
5212 if (qt_show_painter_debug_output)
5213 printf("QPainter::drawConvexPolygon(), count=%d\n", pointCount);
5218 if (!d->engine || pointCount < 2)
5222 d->extended->drawPolygon(points, pointCount, QPaintEngine::ConvexMode);
5226 d->updateState(d->state);
5228 uint emulationSpecifier = d->state->emulationSpecifier;
5230 if (emulationSpecifier) {
5231 QPainterPath polygonPath(points[0]);
5232 for (int i=1; i<pointCount; ++i)
5233 polygonPath.lineTo(points[i]);
5234 polygonPath.closeSubpath();
5235 polygonPath.setFillRule(Qt::WindingFill);
5236 d->draw_helper(polygonPath);
5240 d->engine->drawPolygon(points, pointCount, QPaintEngine::ConvexMode);
5243 void QPainter::drawConvexPolygon(const QPointF *points, int pointCount)
5245 #ifdef QT_DEBUG_DRAW
5246 if (qt_show_painter_debug_output)
5247 printf("QPainter::drawConvexPolygon(), count=%d\n", pointCount);
5252 if (!d->engine || pointCount < 2)
5256 d->extended->drawPolygon(points, pointCount, QPaintEngine::ConvexMode);
5260 d->updateState(d->state);
5262 uint emulationSpecifier = d->state->emulationSpecifier;
5264 if (emulationSpecifier) {
5265 QPainterPath polygonPath(points[0]);
5266 for (int i=1; i<pointCount; ++i)
5267 polygonPath.lineTo(points[i]);
5268 polygonPath.closeSubpath();
5269 polygonPath.setFillRule(Qt::WindingFill);
5270 d->draw_helper(polygonPath);
5274 d->engine->drawPolygon(points, pointCount, QPaintEngine::ConvexMode);
5277 static inline QPointF roundInDeviceCoordinates(const QPointF &p, const QTransform &m)
5279 return m.inverted().map(QPointF(m.map(p).toPoint()));
5283 \fn void QPainter::drawPixmap(const QRectF &target, const QPixmap &pixmap, const QRectF &source)
5285 Draws the rectangular portion \a source of the given \a pixmap
5286 into the given \a target in the paint device.
5288 \note The pixmap is scaled to fit the rectangle, if both the pixmap and rectangle size disagree.
5293 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 16
5296 If \a pixmap is a QBitmap it is drawn with the bits that are "set"
5297 using the pens color. If backgroundMode is Qt::OpaqueMode, the
5298 "unset" bits are drawn using the color of the background brush; if
5299 backgroundMode is Qt::TransparentMode, the "unset" bits are
5300 transparent. Drawing bitmaps with gradient or texture colors is
5305 void QPainter::drawPixmap(const QPointF &p, const QPixmap &pm)
5307 #if defined QT_DEBUG_DRAW
5308 if (qt_show_painter_debug_output)
5309 printf("QPainter::drawPixmap(), p=[%.2f,%.2f], pix=[%d,%d]\n",
5311 pm.width(), pm.height());
5316 if (!d->engine || pm.isNull())
5320 qt_painter_thread_test(d->device->devType(), "drawPixmap()", true);
5324 d->extended->drawPixmap(p, pm);
5332 int h = pm.height();
5337 // Emulate opaque background for bitmaps
5338 if (d->state->bgMode == Qt::OpaqueMode && pm.isQBitmap()) {
5339 fillRect(QRectF(x, y, w, h), d->state->bgBrush.color());
5342 d->updateState(d->state);
5344 if ((d->state->matrix.type() > QTransform::TxTranslate
5345 && !d->engine->hasFeature(QPaintEngine::PixmapTransform))
5346 || (!d->state->matrix.isAffine() && !d->engine->hasFeature(QPaintEngine::PerspectiveTransform))
5347 || (d->state->opacity != 1.0 && !d->engine->hasFeature(QPaintEngine::ConstantOpacity)))
5350 // If there is no rotation involved we have to make sure we use the
5351 // antialiased and not the aliased coordinate system by rounding the coordinates.
5352 if (d->state->matrix.type() <= QTransform::TxScale) {
5353 const QPointF p = roundInDeviceCoordinates(QPointF(x, y), d->state->matrix);
5358 setBackgroundMode(Qt::TransparentMode);
5359 setRenderHint(Antialiasing, renderHints() & SmoothPixmapTransform);
5360 QBrush brush(d->state->pen.color(), pm);
5363 setBrushOrigin(QPointF(0, 0));
5365 drawRect(pm.rect());
5368 if (!d->engine->hasFeature(QPaintEngine::PixmapTransform)) {
5369 x += d->state->matrix.dx();
5370 y += d->state->matrix.dy();
5372 d->engine->drawPixmap(QRectF(x, y, w, h), pm, QRectF(0, 0, w, h));
5376 void QPainter::drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr)
5378 #if defined QT_DEBUG_DRAW
5379 if (qt_show_painter_debug_output)
5380 printf("QPainter::drawPixmap(), target=[%.2f,%.2f,%.2f,%.2f], pix=[%d,%d], source=[%.2f,%.2f,%.2f,%.2f]\n",
5381 r.x(), r.y(), r.width(), r.height(),
5382 pm.width(), pm.height(),
5383 sr.x(), sr.y(), sr.width(), sr.height());
5387 if (!d->engine || pm.isNull())
5390 qt_painter_thread_test(d->device->devType(), "drawPixmap()", true);
5395 qreal w = r.width();
5396 qreal h = r.height();
5399 qreal sw = sr.width();
5400 qreal sh = sr.height();
5402 // Sanity-check clipping
5404 sw = pm.width() - sx;
5407 sh = pm.height() - sy;
5415 qreal w_ratio = sx * w/sw;
5423 qreal h_ratio = sy * h/sh;
5430 if (sw + sx > pm.width()) {
5431 qreal delta = sw - (pm.width() - sx);
5432 qreal w_ratio = delta * w/sw;
5437 if (sh + sy > pm.height()) {
5438 qreal delta = sh - (pm.height() - sy);
5439 qreal h_ratio = delta * h/sh;
5444 if (w == 0 || h == 0 || sw <= 0 || sh <= 0)
5448 d->extended->drawPixmap(QRectF(x, y, w, h), pm, QRectF(sx, sy, sw, sh));
5452 // Emulate opaque background for bitmaps
5453 if (d->state->bgMode == Qt::OpaqueMode && pm.isQBitmap())
5454 fillRect(QRectF(x, y, w, h), d->state->bgBrush.color());
5456 d->updateState(d->state);
5458 if ((d->state->matrix.type() > QTransform::TxTranslate
5459 && !d->engine->hasFeature(QPaintEngine::PixmapTransform))
5460 || (!d->state->matrix.isAffine() && !d->engine->hasFeature(QPaintEngine::PerspectiveTransform))
5461 || (d->state->opacity != 1.0 && !d->engine->hasFeature(QPaintEngine::ConstantOpacity))
5462 || ((sw != w || sh != h) && !d->engine->hasFeature(QPaintEngine::PixmapTransform)))
5465 // If there is no rotation involved we have to make sure we use the
5466 // antialiased and not the aliased coordinate system by rounding the coordinates.
5467 if (d->state->matrix.type() <= QTransform::TxScale) {
5468 const QPointF p = roundInDeviceCoordinates(QPointF(x, y), d->state->matrix);
5473 if (d->state->matrix.type() <= QTransform::TxTranslate && sw == w && sh == h) {
5481 scale(w / sw, h / sh);
5482 setBackgroundMode(Qt::TransparentMode);
5483 setRenderHint(Antialiasing, renderHints() & SmoothPixmapTransform);
5486 if (sw == pm.width() && sh == pm.height())
5487 brush = QBrush(d->state->pen.color(), pm);
5489 brush = QBrush(d->state->pen.color(), pm.copy(sx, sy, sw, sh));
5494 drawRect(QRectF(0, 0, sw, sh));
5497 if (!d->engine->hasFeature(QPaintEngine::PixmapTransform)) {
5498 x += d->state->matrix.dx();
5499 y += d->state->matrix.dy();
5501 d->engine->drawPixmap(QRectF(x, y, w, h), pm, QRectF(sx, sy, sw, sh));
5507 \fn void QPainter::drawPixmap(const QRect &target, const QPixmap &pixmap,
5508 const QRect &source)
5511 Draws the rectangular portion \a source of the given \a pixmap
5512 into the given \a target in the paint device.
5514 \note The pixmap is scaled to fit the rectangle, if both the pixmap and rectangle size disagree.
5518 \fn void QPainter::drawPixmap(const QPointF &point, const QPixmap &pixmap,
5519 const QRectF &source)
5522 Draws the rectangular portion \a source of the given \a pixmap
5523 with its origin at the given \a point.
5527 \fn void QPainter::drawPixmap(const QPoint &point, const QPixmap &pixmap,
5528 const QRect &source)
5532 Draws the rectangular portion \a source of the given \a pixmap
5533 with its origin at the given \a point.
5537 \fn void QPainter::drawPixmap(const QPointF &point, const QPixmap &pixmap)
5540 Draws the given \a pixmap with its origin at the given \a point.
5544 \fn void QPainter::drawPixmap(const QPoint &point, const QPixmap &pixmap)
5547 Draws the given \a pixmap with its origin at the given \a point.
5551 \fn void QPainter::drawPixmap(int x, int y, const QPixmap &pixmap)
5555 Draws the given \a pixmap at position (\a{x}, \a{y}).
5559 \fn void QPainter::drawPixmap(const QRect &rectangle, const QPixmap &pixmap)
5562 Draws the given \a pixmap into the given \a rectangle.
5564 \note The pixmap is scaled to fit the rectangle, if both the pixmap and rectangle size disagree.
5568 \fn void QPainter::drawPixmap(int x, int y, int width, int height,
5569 const QPixmap &pixmap)
5573 Draws the \a pixmap into the rectangle at position (\a{x}, \a{y})
5574 with the given \a width and \a height.
5578 \fn void QPainter::drawPixmap(int x, int y, int w, int h, const QPixmap &pixmap,
5579 int sx, int sy, int sw, int sh)
5583 Draws the rectangular portion with the origin (\a{sx}, \a{sy}),
5584 width \a sw and height \a sh, of the given \a pixmap , at the
5585 point (\a{x}, \a{y}), with a width of \a w and a height of \a h.
5586 If sw or sh are equal to zero the width/height of the pixmap
5587 is used and adjusted by the offset sx/sy;
5591 \fn void QPainter::drawPixmap(int x, int y, const QPixmap &pixmap,
5592 int sx, int sy, int sw, int sh)
5596 Draws a pixmap at (\a{x}, \a{y}) by copying a part of the given \a
5597 pixmap into the paint device.
5599 (\a{x}, \a{y}) specifies the top-left point in the paint device that is
5600 to be drawn onto. (\a{sx}, \a{sy}) specifies the top-left point in \a
5601 pixmap that is to be drawn. The default is (0, 0).
5603 (\a{sw}, \a{sh}) specifies the size of the pixmap that is to be drawn.
5604 The default, (0, 0) (and negative) means all the way to the
5605 bottom-right of the pixmap.
5608 void QPainter::drawImage(const QPointF &p, const QImage &image)
5612 if (!d->engine || image.isNull())
5616 d->extended->drawImage(p, image);
5623 int w = image.width();
5624 int h = image.height();
5626 d->updateState(d->state);
5628 if (((d->state->matrix.type() > QTransform::TxTranslate)
5629 && !d->engine->hasFeature(QPaintEngine::PixmapTransform))
5630 || (!d->state->matrix.isAffine() && !d->engine->hasFeature(QPaintEngine::PerspectiveTransform))
5631 || (d->state->opacity != 1.0 && !d->engine->hasFeature(QPaintEngine::ConstantOpacity)))
5634 // If there is no rotation involved we have to make sure we use the
5635 // antialiased and not the aliased coordinate system by rounding the coordinates.
5636 if (d->state->matrix.type() <= QTransform::TxScale) {
5637 const QPointF p = roundInDeviceCoordinates(QPointF(x, y), d->state->matrix);
5642 setBackgroundMode(Qt::TransparentMode);
5643 setRenderHint(Antialiasing, renderHints() & SmoothPixmapTransform);
5644 QBrush brush(image);
5647 setBrushOrigin(QPointF(0, 0));
5649 drawRect(image.rect());
5654 if (d->state->matrix.type() == QTransform::TxTranslate
5655 && !d->engine->hasFeature(QPaintEngine::PixmapTransform)) {
5656 x += d->state->matrix.dx();
5657 y += d->state->matrix.dy();
5660 d->engine->drawImage(QRectF(x, y, w, h), image, QRectF(0, 0, w, h), Qt::AutoColor);
5663 void QPainter::drawImage(const QRectF &targetRect, const QImage &image, const QRectF &sourceRect,
5664 Qt::ImageConversionFlags flags)
5668 if (!d->engine || image.isNull())
5671 qreal x = targetRect.x();
5672 qreal y = targetRect.y();
5673 qreal w = targetRect.width();
5674 qreal h = targetRect.height();
5675 qreal sx = sourceRect.x();
5676 qreal sy = sourceRect.y();
5677 qreal sw = sourceRect.width();
5678 qreal sh = sourceRect.height();
5680 // Sanity-check clipping
5682 sw = image.width() - sx;
5685 sh = image.height() - sy;
5693 qreal w_ratio = sx * w/sw;
5701 qreal h_ratio = sy * h/sh;
5708 if (sw + sx > image.width()) {
5709 qreal delta = sw - (image.width() - sx);
5710 qreal w_ratio = delta * w/sw;
5715 if (sh + sy > image.height()) {
5716 qreal delta = sh - (image.height() - sy);
5717 qreal h_ratio = delta * h/sh;
5722 if (w == 0 || h == 0 || sw <= 0 || sh <= 0)
5726 d->extended->drawImage(QRectF(x, y, w, h), image, QRectF(sx, sy, sw, sh), flags);
5730 d->updateState(d->state);
5732 if (((d->state->matrix.type() > QTransform::TxTranslate || (sw != w || sh != h))
5733 && !d->engine->hasFeature(QPaintEngine::PixmapTransform))
5734 || (!d->state->matrix.isAffine() && !d->engine->hasFeature(QPaintEngine::PerspectiveTransform))
5735 || (d->state->opacity != 1.0 && !d->engine->hasFeature(QPaintEngine::ConstantOpacity)))
5738 // If there is no rotation involved we have to make sure we use the
5739 // antialiased and not the aliased coordinate system by rounding the coordinates.
5740 if (d->state->matrix.type() <= QTransform::TxScale) {
5741 const QPointF p = roundInDeviceCoordinates(QPointF(x, y), d->state->matrix);
5746 if (d->state->matrix.type() <= QTransform::TxTranslate && sw == w && sh == h) {
5753 scale(w / sw, h / sh);
5754 setBackgroundMode(Qt::TransparentMode);
5755 setRenderHint(Antialiasing, renderHints() & SmoothPixmapTransform);
5756 QBrush brush(image);
5759 setBrushOrigin(QPointF(-sx, -sy));
5761 drawRect(QRectF(0, 0, sw, sh));
5766 if (d->state->matrix.type() == QTransform::TxTranslate
5767 && !d->engine->hasFeature(QPaintEngine::PixmapTransform)) {
5768 x += d->state->matrix.dx();
5769 y += d->state->matrix.dy();
5772 d->engine->drawImage(QRectF(x, y, w, h), image, QRectF(sx, sy, sw, sh), flags);
5776 \fn void QPainter::drawGlyphRun(const QPointF &position, const QGlyphRun &glyphs)
5778 Draws the glyphs represented by \a glyphs at \a position. The \a position gives the
5779 edge of the baseline for the string of glyphs. The glyphs will be retrieved from the font
5780 selected on \a glyphs and at offsets given by the positions in \a glyphs.
5784 \sa QGlyphRun::setRawFont(), QGlyphRun::setPositions(), QGlyphRun::setGlyphIndexes()
5786 #if !defined(QT_NO_RAWFONT)
5787 void QPainter::drawGlyphRun(const QPointF &position, const QGlyphRun &glyphRun)
5791 QRawFont font = glyphRun.rawFont();
5792 if (!font.isValid())
5795 QGlyphRunPrivate *glyphRun_d = QGlyphRunPrivate::get(glyphRun);
5797 const quint32 *glyphIndexes = glyphRun_d->glyphIndexData;
5798 const QPointF *glyphPositions = glyphRun_d->glyphPositionData;
5800 int count = qMin(glyphRun_d->glyphIndexDataSize, glyphRun_d->glyphPositionDataSize);
5801 QVarLengthArray<QFixedPoint, 128> fixedPointPositions(count);
5803 QRawFontPrivate *fontD = QRawFontPrivate::get(font);
5804 bool supportsTransformations;
5805 if (d->extended != 0) {
5806 supportsTransformations = d->extended->supportsTransformations(fontD->fontEngine->fontDef.pixelSize,
5809 supportsTransformations = d->engine->type() == QPaintEngine::CoreGraphics
5810 || d->state->matrix.isAffine();
5813 for (int i=0; i<count; ++i) {
5814 QPointF processedPosition = position + glyphPositions[i];
5815 if (!supportsTransformations)
5816 processedPosition = d->state->transform().map(processedPosition);
5817 fixedPointPositions[i] = QFixedPoint::fromPointF(processedPosition);
5820 d->drawGlyphs(glyphIndexes, fixedPointPositions.data(), count, font, glyphRun.overline(),
5821 glyphRun.underline(), glyphRun.strikeOut());
5824 void QPainterPrivate::drawGlyphs(const quint32 *glyphArray, QFixedPoint *positions,
5826 const QRawFont &font, bool overline, bool underline,
5833 QRawFontPrivate *fontD = QRawFontPrivate::get(font);
5834 QFontEngine *fontEngine = fontD->fontEngine;
5839 for (int i=0; i<glyphCount; ++i) {
5840 glyph_metrics_t gm = fontEngine->boundingBox(glyphArray[i]);
5841 if (i == 0 || leftMost > positions[i].x)
5842 leftMost = positions[i].x;
5844 // We don't support glyphs that do not share a common baseline. If this turns out to
5845 // be a relevant use case, then we need to find clusters of glyphs that share a baseline
5846 // and do a drawTextItemDecorations call per cluster.
5847 if (i == 0 || baseLine < positions[i].y)
5848 baseLine = positions[i].y;
5850 // We use the advance rather than the actual bounds to match the algorithm in drawText()
5851 if (i == 0 || rightMost < positions[i].x + gm.xoff)
5852 rightMost = positions[i].x + gm.xoff;
5855 QFixed width = rightMost - leftMost;
5857 if (extended != 0 && state->matrix.isAffine()) {
5858 QStaticTextItem staticTextItem;
5859 staticTextItem.color = state->pen.color();
5860 staticTextItem.font = state->font;
5861 staticTextItem.setFontEngine(fontEngine);
5862 staticTextItem.numGlyphs = glyphCount;
5863 staticTextItem.glyphs = reinterpret_cast<glyph_t *>(const_cast<glyph_t *>(glyphArray));
5864 staticTextItem.glyphPositions = positions;
5866 extended->drawStaticTextItem(&staticTextItem);
5868 QTextItemInt textItem;
5869 textItem.fontEngine = fontEngine;
5871 QVarLengthArray<QFixed, 128> advances(glyphCount);
5872 QVarLengthArray<QGlyphJustification, 128> glyphJustifications(glyphCount);
5873 QVarLengthArray<HB_GlyphAttributes, 128> glyphAttributes(glyphCount);
5874 qMemSet(glyphAttributes.data(), 0, glyphAttributes.size() * sizeof(HB_GlyphAttributes));
5875 qMemSet(advances.data(), 0, advances.size() * sizeof(QFixed));
5876 qMemSet(glyphJustifications.data(), 0, glyphJustifications.size() * sizeof(QGlyphJustification));
5878 textItem.glyphs.numGlyphs = glyphCount;
5879 textItem.glyphs.glyphs = reinterpret_cast<HB_Glyph *>(const_cast<quint32 *>(glyphArray));
5880 textItem.glyphs.offsets = positions;
5881 textItem.glyphs.advances_x = advances.data();
5882 textItem.glyphs.advances_y = advances.data();
5883 textItem.glyphs.justifications = glyphJustifications.data();
5884 textItem.glyphs.attributes = glyphAttributes.data();
5886 engine->drawTextItem(QPointF(0, 0), textItem);
5889 QTextItemInt::RenderFlags flags;
5891 flags |= QTextItemInt::Underline;
5893 flags |= QTextItemInt::Overline;
5895 flags |= QTextItemInt::StrikeOut;
5897 drawTextItemDecoration(q, QPointF(leftMost.toReal(), baseLine.toReal()),
5900 ? QTextCharFormat::SingleUnderline
5901 : QTextCharFormat::NoUnderline),
5902 flags, width.toReal(), QTextCharFormat());
5904 #endif // QT_NO_RAWFONT
5908 \fn void QPainter::drawStaticText(const QPoint &topLeftPosition, const QStaticText &staticText)
5912 Draws the \a staticText at the \a topLeftPosition.
5914 \note The y-position is used as the top of the font.
5919 \fn void QPainter::drawStaticText(int left, int top, const QStaticText &staticText)
5923 Draws the \a staticText at coordinates \a left and \a top.
5925 \note The y-position is used as the top of the font.
5929 \fn void QPainter::drawText(const QPointF &position, const QString &text)
5931 Draws the given \a text with the currently defined text direction,
5932 beginning at the given \a position.
5934 This function does not handle the newline character (\n), as it cannot
5935 break text into multiple lines, and it cannot display the newline character.
5936 Use the QPainter::drawText() overload that takes a rectangle instead
5937 if you want to draw multiple lines of text with the newline character, or
5938 if you want the text to be wrapped.
5940 By default, QPainter draws text anti-aliased.
5942 \note The y-position is used as the baseline of the font.
5945 void QPainter::drawText(const QPointF &p, const QString &str)
5947 drawText(p, str, 0, 0);
5953 Draws the given \a staticText at the given \a topLeftPosition.
5955 The text will be drawn using the font and the transformation set on the painter. If the
5956 font and/or transformation set on the painter are different from the ones used to initialize
5957 the layout of the QStaticText, then the layout will have to be recalculated. Use
5958 QStaticText::prepare() to initialize \a staticText with the font and transformation with which
5959 it will later be drawn.
5961 If \a topLeftPosition is not the same as when \a staticText was initialized, or when it was
5962 last drawn, then there will be a slight overhead when translating the text to its new position.
5964 \note If the painter's transformation is not affine, then \a staticText will be drawn using
5965 regular calls to drawText(), losing any potential for performance improvement.
5967 \note The y-position is used as the top of the font.
5971 void QPainter::drawStaticText(const QPointF &topLeftPosition, const QStaticText &staticText)
5974 if (!d->engine || staticText.text().isEmpty() || pen().style() == Qt::NoPen)
5977 QStaticTextPrivate *staticText_d =
5978 const_cast<QStaticTextPrivate *>(QStaticTextPrivate::get(&staticText));
5980 if (font() != staticText_d->font) {
5981 staticText_d->font = font();
5982 staticText_d->needsRelayout = true;
5985 // If we don't have an extended paint engine, or if the painter is projected,
5986 // we go through standard code path
5987 if (d->extended == 0 || !d->state->matrix.isAffine()) {
5988 staticText_d->paintText(topLeftPosition, this);
5992 bool supportsTransformations = d->extended->supportsTransformations(staticText_d->font.pixelSize(),
5994 if (supportsTransformations && !staticText_d->untransformedCoordinates) {
5995 staticText_d->untransformedCoordinates = true;
5996 staticText_d->needsRelayout = true;
5997 } else if (!supportsTransformations && staticText_d->untransformedCoordinates) {
5998 staticText_d->untransformedCoordinates = false;
5999 staticText_d->needsRelayout = true;
6002 // Don't recalculate entire layout because of translation, rather add the dx and dy
6003 // into the position to move each text item the correct distance.
6004 QPointF transformedPosition = topLeftPosition;
6005 if (!staticText_d->untransformedCoordinates)
6006 transformedPosition = transformedPosition * d->state->matrix;
6007 QTransform oldMatrix;
6009 // The translation has been applied to transformedPosition. Remove translation
6010 // component from matrix.
6011 if (d->state->matrix.isTranslating() && !staticText_d->untransformedCoordinates) {
6012 qreal m11 = d->state->matrix.m11();
6013 qreal m12 = d->state->matrix.m12();
6014 qreal m13 = d->state->matrix.m13();
6015 qreal m21 = d->state->matrix.m21();
6016 qreal m22 = d->state->matrix.m22();
6017 qreal m23 = d->state->matrix.m23();
6018 qreal m33 = d->state->matrix.m33();
6020 oldMatrix = d->state->matrix;
6021 d->state->matrix.setMatrix(m11, m12, m13,
6026 // If the transform is not identical to the text transform,
6027 // we have to relayout the text (for other transformations than plain translation)
6028 bool staticTextNeedsReinit = staticText_d->needsRelayout;
6029 if (!staticText_d->untransformedCoordinates && staticText_d->matrix != d->state->matrix) {
6030 staticText_d->matrix = d->state->matrix;
6031 staticTextNeedsReinit = true;
6034 // Recreate the layout of the static text because the matrix or font has changed
6035 if (staticTextNeedsReinit)
6036 staticText_d->init();
6038 if (transformedPosition != staticText_d->position) { // Translate to actual position
6039 QFixed fx = QFixed::fromReal(transformedPosition.x());
6040 QFixed fy = QFixed::fromReal(transformedPosition.y());
6041 QFixed oldX = QFixed::fromReal(staticText_d->position.x());
6042 QFixed oldY = QFixed::fromReal(staticText_d->position.y());
6043 for (int item=0; item<staticText_d->itemCount;++item) {
6044 QStaticTextItem *textItem = staticText_d->items + item;
6045 for (int i=0; i<textItem->numGlyphs; ++i) {
6046 textItem->glyphPositions[i].x += fx - oldX;
6047 textItem->glyphPositions[i].y += fy - oldY;
6049 textItem->userDataNeedsUpdate = true;
6052 staticText_d->position = transformedPosition;
6055 QPen oldPen = d->state->pen;
6056 QColor currentColor = oldPen.color();
6057 for (int i=0; i<staticText_d->itemCount; ++i) {
6058 QStaticTextItem *item = staticText_d->items + i;
6059 if (item->color.isValid() && currentColor != item->color) {
6060 setPen(item->color);
6061 currentColor = item->color;
6063 d->extended->drawStaticTextItem(item);
6065 qt_draw_decoration_for_glyphs(this, item->glyphs, item->glyphPositions,
6066 item->numGlyphs, item->fontEngine(), staticText_d->font,
6069 if (currentColor != oldPen.color())
6072 if (!staticText_d->untransformedCoordinates && oldMatrix.isTranslating())
6073 d->state->matrix = oldMatrix;
6079 void QPainter::drawText(const QPointF &p, const QString &str, int tf, int justificationPadding)
6081 #ifdef QT_DEBUG_DRAW
6082 if (qt_show_painter_debug_output)
6083 printf("QPainter::drawText(), pos=[%.2f,%.2f], str='%s'\n", p.x(), p.y(), str.toLatin1().constData());
6088 if (!d->engine || str.isEmpty() || pen().style() == Qt::NoPen)
6091 if (tf & Qt::TextBypassShaping) {
6092 // Skip harfbuzz complex shaping, shape using glyph advances only
6093 int len = str.length();
6094 int numGlyphs = len;
6095 QVarLengthGlyphLayoutArray glyphs(len);
6096 QFontEngine *fontEngine = d->state->font.d->engineForScript(QUnicodeTables::Common);
6097 if (!fontEngine->stringToCMap(str.data(), len, &glyphs, &numGlyphs, 0)) {
6098 glyphs.resize(numGlyphs);
6099 if (!fontEngine->stringToCMap(str.data(), len, &glyphs, &numGlyphs, 0))
6100 Q_ASSERT_X(false, Q_FUNC_INFO, "stringToCMap shouldn't fail twice");
6103 QTextItemInt gf(glyphs, &d->state->font, str.data(), len, fontEngine);
6104 drawTextItem(p, gf);
6108 QStackTextEngine engine(str, d->state->font);
6109 engine.option.setTextDirection(d->state->layoutDirection);
6110 if (tf & (Qt::TextForceLeftToRight|Qt::TextForceRightToLeft)) {
6111 engine.ignoreBidi = true;
6112 engine.option.setTextDirection((tf & Qt::TextForceLeftToRight) ? Qt::LeftToRight : Qt::RightToLeft);
6116 line.length = str.length();
6117 engine.shapeLine(line);
6119 int nItems = engine.layoutData->items.size();
6120 QVarLengthArray<int> visualOrder(nItems);
6121 QVarLengthArray<uchar> levels(nItems);
6122 for (int i = 0; i < nItems; ++i)
6123 levels[i] = engine.layoutData->items[i].analysis.bidiLevel;
6124 QTextEngine::bidiReorder(nItems, levels.data(), visualOrder.data());
6126 if (justificationPadding > 0) {
6127 engine.option.setAlignment(Qt::AlignJustify);
6128 engine.forceJustification = true;
6129 // this works because justify() is only interested in the difference between width and textWidth
6130 line.width = justificationPadding;
6131 engine.justify(line);
6133 QFixed x = QFixed::fromReal(p.x());
6135 for (int i = 0; i < nItems; ++i) {
6136 int item = visualOrder[i];
6137 const QScriptItem &si = engine.layoutData->items.at(item);
6138 if (si.analysis.flags >= QScriptAnalysis::TabOrObject) {
6142 QFont f = engine.font(si);
6143 QTextItemInt gf(si, &f);
6144 gf.glyphs = engine.shapedGlyphs(&si);
6145 gf.chars = engine.layoutData->string.unicode() + si.position;
6146 gf.num_chars = engine.length(item);
6147 if (engine.forceJustification) {
6148 for (int j=0; j<gf.glyphs.numGlyphs; ++j)
6149 gf.width += gf.glyphs.effectiveAdvance(j);
6151 gf.width = si.width;
6153 gf.logClusters = engine.logClusters(&si);
6155 drawTextItem(QPointF(x.toReal(), p.y()), gf);
6161 void QPainter::drawText(const QRect &r, int flags, const QString &str, QRect *br)
6163 #ifdef QT_DEBUG_DRAW
6164 if (qt_show_painter_debug_output)
6165 printf("QPainter::drawText(), r=[%d,%d,%d,%d], flags=%d, str='%s'\n",
6166 r.x(), r.y(), r.width(), r.height(), flags, str.toLatin1().constData());
6171 if (!d->engine || str.length() == 0 || pen().style() == Qt::NoPen)
6175 d->updateState(d->state);
6178 qt_format_text(d->state->font, r, flags, 0, str, br ? &bounds : 0, 0, 0, 0, this);
6180 *br = bounds.toAlignedRect();
6184 \fn void QPainter::drawText(const QPoint &position, const QString &text)
6188 Draws the given \a text with the currently defined text direction,
6189 beginning at the given \a position.
6191 By default, QPainter draws text anti-aliased.
6193 \note The y-position is used as the baseline of the font.
6198 \fn void QPainter::drawText(const QRectF &rectangle, int flags, const QString &text, QRectF *boundingRect)
6201 Draws the given \a text within the provided \a rectangle.
6205 \o \inlineimage qpainter-text.png
6207 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 17
6210 The \a boundingRect (if not null) is set to the what the bounding rectangle
6211 should be in order to enclose the whole text. The \a flags argument is a bitwise
6212 OR of the following flags:
6224 \o Qt::TextSingleLine
6225 \o Qt::TextExpandTabs
6226 \o Qt::TextShowMnemonic
6228 \o Qt::TextIncludeTrailingSpaces
6231 \sa Qt::AlignmentFlag, Qt::TextFlag, boundingRect(), layoutDirection()
6233 By default, QPainter draws text anti-aliased.
6235 \note The y-coordinate of \a rectangle is used as the top of the font.
6237 void QPainter::drawText(const QRectF &r, int flags, const QString &str, QRectF *br)
6239 #ifdef QT_DEBUG_DRAW
6240 if (qt_show_painter_debug_output)
6241 printf("QPainter::drawText(), r=[%.2f,%.2f,%.2f,%.2f], flags=%d, str='%s'\n",
6242 r.x(), r.y(), r.width(), r.height(), flags, str.toLatin1().constData());
6247 if (!d->engine || str.length() == 0 || pen().style() == Qt::NoPen)
6251 d->updateState(d->state);
6253 qt_format_text(d->state->font, r, flags, 0, str, br, 0, 0, 0, this);
6257 \fn void QPainter::drawText(const QRect &rectangle, int flags, const QString &text, QRect *boundingRect)
6260 Draws the given \a text within the provided \a rectangle according
6261 to the specified \a flags. The \a boundingRect (if not null) is set to
6262 the what the bounding rectangle should be in order to enclose the whole text.
6264 By default, QPainter draws text anti-aliased.
6266 \note The y-coordinate of \a rectangle is used as the top of the font.
6270 \fn void QPainter::drawText(int x, int y, const QString &text)
6274 Draws the given \a text at position (\a{x}, \a{y}), using the painter's
6275 currently defined text direction.
6277 By default, QPainter draws text anti-aliased.
6279 \note The y-position is used as the baseline of the font.
6284 \fn void QPainter::drawText(int x, int y, int width, int height, int flags,
6285 const QString &text, QRect *boundingRect)
6289 Draws the given \a text within the rectangle with origin (\a{x},
6290 \a{y}), \a width and \a height.
6292 The \a boundingRect (if not null) is set to the actual bounding
6293 rectangle of the output. The \a flags argument is a bitwise OR of
6294 the following flags:
6305 \o Qt::TextSingleLine
6306 \o Qt::TextExpandTabs
6307 \o Qt::TextShowMnemonic
6311 By default, QPainter draws text anti-aliased.
6313 \note The y-position is used as the top of the font.
6315 \sa Qt::AlignmentFlag, Qt::TextFlag
6319 \fn void QPainter::drawText(const QRectF &rectangle, const QString &text,
6320 const QTextOption &option)
6323 Draws the given \a text in the \a rectangle specified using the \a option
6324 to control its positioning and orientation.
6326 By default, QPainter draws text anti-aliased.
6328 \note The y-coordinate of \a rectangle is used as the top of the font.
6330 void QPainter::drawText(const QRectF &r, const QString &text, const QTextOption &o)
6332 #ifdef QT_DEBUG_DRAW
6333 if (qt_show_painter_debug_output)
6334 printf("QPainter::drawText(), r=[%.2f,%.2f,%.2f,%.2f], str='%s'\n",
6335 r.x(), r.y(), r.width(), r.height(), text.toLatin1().constData());
6340 if (!d->engine || text.length() == 0 || pen().style() == Qt::NoPen)
6344 d->updateState(d->state);
6346 qt_format_text(d->state->font, r, 0, &o, text, 0, 0, 0, 0, this);
6350 \fn void QPainter::drawTextItem(int x, int y, const QTextItem &ti)
6357 \fn void QPainter::drawTextItem(const QPoint &p, const QTextItem &ti)
6362 Draws the text item \a ti at position \a p.
6366 \fn void QPainter::drawTextItem(const QPointF &p, const QTextItem &ti)
6371 Draws the text item \a ti at position \a p.
6373 This method ignores the painters background mode and
6374 color. drawText and qt_format_text have to do it themselves, as
6375 only they know the extents of the complete string.
6377 It ignores the font set on the painter as the text item has one of its own.
6379 The underline and strikeout parameters of the text items font are
6380 ignored aswell. You'll need to pass in the correct flags to get
6381 underlining and strikeout.
6384 static QPixmap generateWavyPixmap(qreal maxRadius, const QPen &pen)
6386 const qreal radiusBase = qMax(qreal(1), maxRadius);
6388 QString key = QLatin1Literal("WaveUnderline-")
6389 % pen.color().name()
6390 % HexString<qreal>(radiusBase);
6393 if (QPixmapCache::find(key, pixmap))
6396 const qreal halfPeriod = qMax(qreal(2), qreal(radiusBase * 1.61803399)); // the golden ratio
6397 const int width = qCeil(100 / (2 * halfPeriod)) * (2 * halfPeriod);
6398 const int radius = qFloor(radiusBase);
6405 while (xs < width) {
6408 path.quadTo(xs - halfPeriod / 2, ys, xs, 0);
6411 pixmap = QPixmap(width, radius * 2);
6412 pixmap.fill(Qt::transparent);
6415 wavePen.setCapStyle(Qt::SquareCap);
6417 // This is to protect against making the line too fat, as happens on Mac OS X
6418 // due to it having a rather thick width for the regular underline.
6419 const qreal maxPenWidth = .8 * radius;
6420 if (wavePen.widthF() > maxPenWidth)
6421 wavePen.setWidth(maxPenWidth);
6423 QPainter imgPainter(&pixmap);
6424 imgPainter.setPen(wavePen);
6425 imgPainter.setRenderHint(QPainter::Antialiasing);
6426 imgPainter.translate(0, radius);
6427 imgPainter.drawPath(path);
6430 QPixmapCache::insert(key, pixmap);
6435 static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const QFontEngine *fe,
6436 QTextCharFormat::UnderlineStyle underlineStyle,
6437 QTextItem::RenderFlags flags, qreal width,
6438 const QTextCharFormat &charFormat)
6440 if (underlineStyle == QTextCharFormat::NoUnderline
6441 && !(flags & (QTextItem::StrikeOut | QTextItem::Overline)))
6444 const QPen oldPen = painter->pen();
6445 const QBrush oldBrush = painter->brush();
6446 painter->setBrush(Qt::NoBrush);
6448 pen.setStyle(Qt::SolidLine);
6449 pen.setWidthF(fe->lineThickness().toReal());
6450 pen.setCapStyle(Qt::FlatCap);
6452 QLineF line(pos.x(), pos.y(), pos.x() + qFloor(width), pos.y());
6454 const qreal underlineOffset = fe->underlinePosition().toReal();
6455 // deliberately ceil the offset to avoid the underline coming too close to
6456 // the text above it.
6457 const qreal aliasedCoordinateDelta = 0.5 - 0.015625;
6458 const qreal underlinePos = pos.y() + qCeil(underlineOffset) - aliasedCoordinateDelta;
6460 if (underlineStyle == QTextCharFormat::SpellCheckUnderline) {
6461 underlineStyle = QTextCharFormat::UnderlineStyle(QApplication::style()->styleHint(QStyle::SH_SpellCheckUnderlineStyle));
6464 if (underlineStyle == QTextCharFormat::WaveUnderline) {
6466 painter->translate(0, pos.y() + 1);
6468 QColor uc = charFormat.underlineColor();
6472 // Adapt wave to underlineOffset or pen width, whatever is larger, to make it work on all platforms
6473 const QPixmap wave = generateWavyPixmap(qMax(underlineOffset, pen.widthF()), pen);
6474 const int descent = (int) fe->descent().toReal();
6476 painter->setBrushOrigin(painter->brushOrigin().x(), 0);
6477 painter->fillRect(pos.x(), 0, qCeil(width), qMin(wave.height(), descent), wave);
6479 } else if (underlineStyle != QTextCharFormat::NoUnderline) {
6480 QLineF underLine(line.x1(), underlinePos, line.x2(), underlinePos);
6482 QColor uc = charFormat.underlineColor();
6486 pen.setStyle((Qt::PenStyle)(underlineStyle));
6487 painter->setPen(pen);
6488 painter->drawLine(underLine);
6491 pen.setStyle(Qt::SolidLine);
6492 pen.setColor(oldPen.color());
6494 if (flags & QTextItem::StrikeOut) {
6495 QLineF strikeOutLine = line;
6496 strikeOutLine.translate(0., - fe->ascent().toReal() / 3.);
6497 painter->setPen(pen);
6498 painter->drawLine(strikeOutLine);
6501 if (flags & QTextItem::Overline) {
6502 QLineF overLine = line;
6503 overLine.translate(0., - fe->ascent().toReal());
6504 painter->setPen(pen);
6505 painter->drawLine(overLine);
6508 painter->setPen(oldPen);
6509 painter->setBrush(oldBrush);
6512 Q_GUI_EXPORT void qt_draw_decoration_for_glyphs(QPainter *painter, const glyph_t *glyphArray,
6513 const QFixedPoint *positions, int glyphCount,
6514 QFontEngine *fontEngine, const QFont &font,
6515 const QTextCharFormat &charFormat)
6517 if (!(font.underline() || font.strikeOut() || font.overline()))
6523 for (int i=0; i<glyphCount; ++i) {
6524 glyph_metrics_t gm = fontEngine->boundingBox(glyphArray[i]);
6525 if (i == 0 || leftMost > positions[i].x)
6526 leftMost = positions[i].x;
6528 // We don't support glyphs that do not share a common baseline. If this turns out to
6529 // be a relevant use case, then we need to find clusters of glyphs that share a baseline
6530 // and do a drawTextItemDecorations call per cluster.
6531 if (i == 0 || baseLine < positions[i].y)
6532 baseLine = positions[i].y;
6534 // We use the advance rather than the actual bounds to match the algorithm in drawText()
6535 if (i == 0 || rightMost < positions[i].x + gm.xoff)
6536 rightMost = positions[i].x + gm.xoff;
6539 QFixed width = rightMost - leftMost;
6540 QTextItem::RenderFlags flags = 0;
6542 if (font.underline())
6543 flags |= QTextItem::Underline;
6544 if (font.overline())
6545 flags |= QTextItem::Overline;
6546 if (font.strikeOut())
6547 flags |= QTextItem::StrikeOut;
6549 drawTextItemDecoration(painter, QPointF(leftMost.toReal(), baseLine.toReal()),
6551 font.underline() ? QTextCharFormat::SingleUnderline
6552 : QTextCharFormat::NoUnderline, flags,
6553 width.toReal(), charFormat);
6556 void QPainter::drawTextItem(const QPointF &p, const QTextItem &_ti)
6558 #ifdef QT_DEBUG_DRAW
6559 if (qt_show_painter_debug_output)
6560 printf("QPainter::drawTextItem(), pos=[%.f,%.f], str='%s'\n",
6561 p.x(), p.y(), qPrintable(_ti.text()));
6570 qt_painter_thread_test(d->device->devType(),
6572 QFontDatabase::supportsThreadedFontRendering());
6575 QTextItemInt &ti = const_cast<QTextItemInt &>(static_cast<const QTextItemInt &>(_ti));
6577 if (!d->extended && d->state->bgMode == Qt::OpaqueMode) {
6578 QRectF rect(p.x(), p.y() - ti.ascent.toReal(), ti.width.toReal(), (ti.ascent + ti.descent + 1).toReal());
6579 fillRect(rect, d->state->bgBrush);
6582 if (pen().style() == Qt::NoPen)
6585 const RenderHints oldRenderHints = d->state->renderHints;
6586 if (!d->state->renderHints & QPainter::Antialiasing && d->state->matrix.type() >= QTransform::TxScale) {
6587 // draw antialias decoration (underline/overline/strikeout) with
6591 const QTransform &m = d->state->matrix;
6592 if (d->state->matrix.type() < QTransform::TxShear) {
6593 bool isPlain90DegreeRotation =
6594 (qFuzzyIsNull(m.m11())
6595 && qFuzzyIsNull(m.m12() - qreal(1))
6596 && qFuzzyIsNull(m.m21() + qreal(1))
6597 && qFuzzyIsNull(m.m22())
6600 (qFuzzyIsNull(m.m11() + qreal(1))
6601 && qFuzzyIsNull(m.m12())
6602 && qFuzzyIsNull(m.m21())
6603 && qFuzzyIsNull(m.m22() + qreal(1))
6606 (qFuzzyIsNull(m.m11())
6607 && qFuzzyIsNull(m.m12() + qreal(1))
6608 && qFuzzyIsNull(m.m21() - qreal(1))
6609 && qFuzzyIsNull(m.m22())
6612 aa = !isPlain90DegreeRotation;
6615 setRenderHint(QPainter::Antialiasing, true);
6619 d->updateState(d->state);
6621 if (!ti.glyphs.numGlyphs) {
6623 } else if (ti.fontEngine->type() == QFontEngine::Multi) {
6624 QFontEngineMulti *multi = static_cast<QFontEngineMulti *>(ti.fontEngine);
6626 const QGlyphLayout &glyphs = ti.glyphs;
6627 int which = glyphs.glyphs[0] >> 24;
6632 bool rtl = ti.flags & QTextItem::RightToLeft;
6634 x += ti.width.toReal();
6638 for (end = 0; end < ti.glyphs.numGlyphs; ++end) {
6639 const int e = glyphs.glyphs[end] >> 24;
6644 QTextItemInt ti2 = ti.midItem(multi->engine(which), start, end - start);
6646 // set the high byte to zero and calc the width
6647 for (i = start; i < end; ++i) {
6648 glyphs.glyphs[i] = glyphs.glyphs[i] & 0xffffff;
6649 ti2.width += ti.glyphs.effectiveAdvance(i);
6653 x -= ti2.width.toReal();
6655 d->engine->drawTextItem(QPointF(x, y), ti2);
6658 x += ti2.width.toReal();
6660 // reset the high byte for all glyphs and advance to the next sub-string
6661 const int hi = which << 24;
6662 for (i = start; i < end; ++i) {
6663 glyphs.glyphs[i] = hi | glyphs.glyphs[i];
6671 QTextItemInt ti2 = ti.midItem(multi->engine(which), start, end - start);
6673 // set the high byte to zero and calc the width
6674 for (i = start; i < end; ++i) {
6675 glyphs.glyphs[i] = glyphs.glyphs[i] & 0xffffff;
6676 ti2.width += ti.glyphs.effectiveAdvance(i);
6680 x -= ti2.width.toReal();
6683 d->extended->drawTextItem(QPointF(x, y), ti2);
6685 d->engine->drawTextItem(QPointF(x,y), ti2);
6687 // reset the high byte for all glyphs
6688 const int hi = which << 24;
6689 for (i = start; i < end; ++i)
6690 glyphs.glyphs[i] = hi | glyphs.glyphs[i];
6694 d->extended->drawTextItem(p, ti);
6696 d->engine->drawTextItem(p, ti);
6698 drawTextItemDecoration(this, p, ti.fontEngine, ti.underlineStyle, ti.flags, ti.width.toReal(),
6701 if (d->state->renderHints != oldRenderHints) {
6702 d->state->renderHints = oldRenderHints;
6704 d->extended->renderHintsChanged();
6706 d->state->dirtyFlags |= QPaintEngine::DirtyHints;
6711 \fn QRectF QPainter::boundingRect(const QRectF &rectangle, int flags, const QString &text)
6713 Returns the bounding rectangle of the \a text as it will appear
6714 when drawn inside the given \a rectangle with the specified \a
6715 flags using the currently set font(); i.e the function tells you
6716 where the drawText() function will draw when given the same
6719 If the \a text does not fit within the given \a rectangle using
6720 the specified \a flags, the function returns the required
6723 The \a flags argument is a bitwise OR of the following flags:
6732 \o Qt::TextSingleLine
6733 \o Qt::TextExpandTabs
6734 \o Qt::TextShowMnemonic
6736 \o Qt::TextIncludeTrailingSpaces
6738 If several of the horizontal or several of the vertical alignment
6739 flags are set, the resulting alignment is undefined.
6741 \sa drawText(), Qt::Alignment, Qt::TextFlag
6745 \fn QRect QPainter::boundingRect(const QRect &rectangle, int flags,
6746 const QString &text)
6750 Returns the bounding rectangle of the \a text as it will appear
6751 when drawn inside the given \a rectangle with the specified \a
6752 flags using the currently set font().
6756 \fn QRect QPainter::boundingRect(int x, int y, int w, int h, int flags,
6757 const QString &text);
6761 Returns the bounding rectangle of the given \a text as it will
6762 appear when drawn inside the rectangle beginning at the point
6763 (\a{x}, \a{y}) with width \a w and height \a h.
6765 QRect QPainter::boundingRect(const QRect &rect, int flags, const QString &str)
6768 return QRect(rect.x(),rect.y(), 0,0);
6770 drawText(rect, flags | Qt::TextDontPrint, str, &brect);
6776 QRectF QPainter::boundingRect(const QRectF &rect, int flags, const QString &str)
6779 return QRectF(rect.x(),rect.y(), 0,0);
6781 drawText(rect, flags | Qt::TextDontPrint, str, &brect);
6786 \fn QRectF QPainter::boundingRect(const QRectF &rectangle,
6787 const QString &text, const QTextOption &option)
6791 Instead of specifying flags as a bitwise OR of the
6792 Qt::AlignmentFlag and Qt::TextFlag, this overloaded function takes
6793 an \a option argument. The QTextOption class provides a
6794 description of general rich text properties.
6798 QRectF QPainter::boundingRect(const QRectF &r, const QString &text, const QTextOption &o)
6802 if (!d->engine || text.length() == 0)
6803 return QRectF(r.x(),r.y(), 0,0);
6806 qt_format_text(d->state->font, r, Qt::TextDontPrint, &o, text, &br, 0, 0, 0, this);
6811 \fn void QPainter::drawTiledPixmap(const QRectF &rectangle, const QPixmap &pixmap, const QPointF &position)
6813 Draws a tiled \a pixmap, inside the given \a rectangle with its
6814 origin at the given \a position.
6816 Calling drawTiledPixmap() is similar to calling drawPixmap()
6817 several times to fill (tile) an area with a pixmap, but is
6818 potentially much more efficient depending on the underlying window
6823 void QPainter::drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, const QPointF &sp)
6825 #ifdef QT_DEBUG_DRAW
6826 if (qt_show_painter_debug_output)
6827 printf("QPainter::drawTiledPixmap(), target=[%.2f,%.2f,%.2f,%.2f], pix=[%d,%d], offset=[%.2f,%.2f]\n",
6828 r.x(), r.y(), r.width(), r.height(),
6829 pixmap.width(), pixmap.height(),
6834 if (!d->engine || pixmap.isNull() || r.isEmpty())
6838 qt_painter_thread_test(d->device->devType(), "drawTiledPixmap()", true);
6841 qreal sw = pixmap.width();
6842 qreal sh = pixmap.height();
6846 sx = qRound(sw) - qRound(-sx) % qRound(sw);
6848 sx = qRound(sx) % qRound(sw);
6850 sy = qRound(sh) - -qRound(sy) % qRound(sh);
6852 sy = qRound(sy) % qRound(sh);
6856 d->extended->drawTiledPixmap(r, pixmap, QPointF(sx, sy));
6860 if (d->state->bgMode == Qt::OpaqueMode && pixmap.isQBitmap())
6861 fillRect(r, d->state->bgBrush);
6863 d->updateState(d->state);
6864 if ((d->state->matrix.type() > QTransform::TxTranslate
6865 && !d->engine->hasFeature(QPaintEngine::PixmapTransform))
6866 || (d->state->opacity != 1.0 && !d->engine->hasFeature(QPaintEngine::ConstantOpacity)))
6869 setBackgroundMode(Qt::TransparentMode);
6870 setRenderHint(Antialiasing, renderHints() & SmoothPixmapTransform);
6871 setBrush(QBrush(d->state->pen.color(), pixmap));
6874 // If there is no rotation involved we have to make sure we use the
6875 // antialiased and not the aliased coordinate system by rounding the coordinates.
6876 if (d->state->matrix.type() <= QTransform::TxScale) {
6877 const QPointF p = roundInDeviceCoordinates(r.topLeft(), d->state->matrix);
6879 if (d->state->matrix.type() <= QTransform::TxTranslate) {
6884 setBrushOrigin(QPointF(r.x()-sx, r.y()-sy));
6885 drawRect(QRectF(p, r.size()));
6887 setBrushOrigin(QPointF(r.x()-sx, r.y()-sy));
6896 if (d->state->matrix.type() == QTransform::TxTranslate
6897 && !d->engine->hasFeature(QPaintEngine::PixmapTransform)) {
6898 x += d->state->matrix.dx();
6899 y += d->state->matrix.dy();
6902 d->engine->drawTiledPixmap(QRectF(x, y, r.width(), r.height()), pixmap, QPointF(sx, sy));
6906 \fn QPainter::drawTiledPixmap(const QRect &rectangle, const QPixmap &pixmap,
6907 const QPoint &position = QPoint())
6910 Draws a tiled \a pixmap, inside the given \a rectangle with its
6911 origin at the given \a position.
6915 \fn void QPainter::drawTiledPixmap(int x, int y, int width, int height, const
6916 QPixmap &pixmap, int sx, int sy);
6919 Draws a tiled \a pixmap in the specified rectangle.
6921 (\a{x}, \a{y}) specifies the top-left point in the paint device
6922 that is to be drawn onto; with the given \a width and \a
6923 height. (\a{sx}, \a{sy}) specifies the top-left point in the \a
6924 pixmap that is to be drawn; this defaults to (0, 0).
6927 #ifndef QT_NO_PICTURE
6930 \fn void QPainter::drawPicture(const QPointF &point, const QPicture &picture)
6932 Replays the given \a picture at the given \a point.
6934 The QPicture class is a paint device that records and replays
6935 QPainter commands. A picture serializes the painter commands to an
6936 IO device in a platform-independent format. Everything that can be
6937 painted on a widget or pixmap can also be stored in a picture.
6939 This function does exactly the same as QPicture::play() when
6940 called with \a point = QPoint(0, 0).
6945 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 18
6948 \sa QPicture::play()
6951 void QPainter::drawPicture(const QPointF &p, const QPicture &picture)
6959 d->updateState(d->state);
6963 const_cast<QPicture *>(&picture)->play(this);
6968 \fn void QPainter::drawPicture(const QPoint &point, const QPicture &picture)
6971 Replays the given \a picture at the given \a point.
6975 \fn void QPainter::drawPicture(int x, int y, const QPicture &picture)
6978 Draws the given \a picture at point (\a x, \a y).
6981 #endif // QT_NO_PICTURE
6984 \fn void QPainter::eraseRect(const QRectF &rectangle)
6986 Erases the area inside the given \a rectangle. Equivalent to
6988 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 19
6992 void QPainter::eraseRect(const QRectF &r)
6996 fillRect(r, d->state->bgBrush);
6999 static inline bool needsResolving(const QBrush &brush)
7001 Qt::BrushStyle s = brush.style();
7002 return ((s == Qt::LinearGradientPattern || s == Qt::RadialGradientPattern ||
7003 s == Qt::ConicalGradientPattern) &&
7004 brush.gradient()->coordinateMode() == QGradient::ObjectBoundingMode);
7008 \fn void QPainter::eraseRect(const QRect &rectangle)
7011 Erases the area inside the given \a rectangle.
7015 \fn void QPainter::eraseRect(int x, int y, int width, int height)
7018 Erases the area inside the rectangle beginning at (\a x, \a y)
7019 with the given \a width and \a height.
7024 \fn void QPainter::fillRect(int x, int y, int width, int height, Qt::BrushStyle style)
7027 Fills the rectangle beginning at (\a{x}, \a{y}) with the given \a
7028 width and \a height, using the brush \a style specified.
7034 \fn void QPainter::fillRect(const QRect &rectangle, Qt::BrushStyle style)
7037 Fills the given \a rectangle with the brush \a style specified.
7043 \fn void QPainter::fillRect(const QRectF &rectangle, Qt::BrushStyle style)
7046 Fills the given \a rectangle with the brush \a style specified.
7052 \fn void QPainter::fillRect(const QRectF &rectangle, const QBrush &brush)
7054 Fills the given \a rectangle with the \a brush specified.
7056 Alternatively, you can specify a QColor instead of a QBrush; the
7057 QBrush constructor (taking a QColor argument) will automatically
7058 create a solid pattern brush.
7062 void QPainter::fillRect(const QRectF &r, const QBrush &brush)
7070 const QGradient *g = brush.gradient();
7071 if (!g || g->coordinateMode() == QGradient::LogicalMode) {
7072 d->extended->fillRect(r, brush);
7077 QPen oldPen = pen();
7078 QBrush oldBrush = this->brush();
7080 if (brush.style() == Qt::SolidPattern) {
7081 d->colorBrush.setStyle(Qt::SolidPattern);
7082 d->colorBrush.setColor(brush.color());
7083 setBrush(d->colorBrush);
7094 \fn void QPainter::fillRect(const QRect &rectangle, const QBrush &brush)
7097 Fills the given \a rectangle with the specified \a brush.
7100 void QPainter::fillRect(const QRect &r, const QBrush &brush)
7108 const QGradient *g = brush.gradient();
7109 if (!g || g->coordinateMode() == QGradient::LogicalMode) {
7110 d->extended->fillRect(r, brush);
7115 QPen oldPen = pen();
7116 QBrush oldBrush = this->brush();
7118 if (brush.style() == Qt::SolidPattern) {
7119 d->colorBrush.setStyle(Qt::SolidPattern);
7120 d->colorBrush.setColor(brush.color());
7121 setBrush(d->colorBrush);
7134 \fn void QPainter::fillRect(const QRect &rectangle, const QColor &color)
7137 Fills the given \a rectangle with the \a color specified.
7141 void QPainter::fillRect(const QRect &r, const QColor &color)
7149 d->extended->fillRect(r, color);
7153 fillRect(r, QBrush(color));
7158 \fn void QPainter::fillRect(const QRectF &rectangle, const QColor &color)
7161 Fills the given \a rectangle with the \a color specified.
7165 void QPainter::fillRect(const QRectF &r, const QColor &color)
7173 d->extended->fillRect(r, color);
7177 fillRect(r, QBrush(color));
7181 \fn void QPainter::fillRect(int x, int y, int width, int height, const QBrush &brush)
7185 Fills the rectangle beginning at (\a{x}, \a{y}) with the given \a
7186 width and \a height, using the given \a brush.
7190 \fn void QPainter::fillRect(int x, int y, int width, int height, const QColor &color)
7194 Fills the rectangle beginning at (\a{x}, \a{y}) with the given \a
7195 width and \a height, using the given \a color.
7201 \fn void QPainter::fillRect(int x, int y, int width, int height, Qt::GlobalColor color)
7205 Fills the rectangle beginning at (\a{x}, \a{y}) with the given \a
7206 width and \a height, using the given \a color.
7212 \fn void QPainter::fillRect(const QRect &rectangle, Qt::GlobalColor color);
7216 Fills the given \a rectangle with the specified \a color.
7222 \fn void QPainter::fillRect(const QRectF &rectangle, Qt::GlobalColor color);
7226 Fills the given \a rectangle with the specified \a color.
7232 Sets the given render \a hint on the painter if \a on is true;
7233 otherwise clears the render hint.
7235 \sa setRenderHints(), renderHints(), {QPainter#Rendering
7236 Quality}{Rendering Quality}
7238 void QPainter::setRenderHint(RenderHint hint, bool on)
7240 #ifdef QT_DEBUG_DRAW
7241 if (qt_show_painter_debug_output)
7242 printf("QPainter::setRenderHint: hint=%x, %s\n", hint, on ? "on" : "off");
7246 static const bool antialiasingDisabled = qgetenv("QT_NO_ANTIALIASING").toInt();
7247 if (hint == QPainter::Antialiasing && antialiasingDisabled)
7251 setRenderHints(hint, on);
7257 Sets the given render \a hints on the painter if \a on is true;
7258 otherwise clears the render hints.
7260 \sa setRenderHint(), renderHints(), {QPainter#Rendering
7261 Quality}{Rendering Quality}
7264 void QPainter::setRenderHints(RenderHints hints, bool on)
7269 qWarning("QPainter::setRenderHint: Painter must be active to set rendering hints");
7274 d->state->renderHints |= hints;
7276 d->state->renderHints &= ~hints;
7279 d->extended->renderHintsChanged();
7281 d->state->dirtyFlags |= QPaintEngine::DirtyHints;
7285 Returns a flag that specifies the rendering hints that are set for
7288 \sa testRenderHint(), {QPainter#Rendering Quality}{Rendering Quality}
7290 QPainter::RenderHints QPainter::renderHints() const
7292 Q_D(const QPainter);
7297 return d->state->renderHints;
7301 \fn bool QPainter::testRenderHint(RenderHint hint) const
7304 Returns true if \a hint is set; otherwise returns false.
7306 \sa renderHints(), setRenderHint()
7310 Returns true if view transformation is enabled; otherwise returns
7313 \sa setViewTransformEnabled(), worldTransform()
7316 bool QPainter::viewTransformEnabled() const
7318 Q_D(const QPainter);
7320 qWarning("QPainter::viewTransformEnabled: Painter not active");
7323 return d->state->VxF;
7327 \fn void QPainter::setWindow(const QRect &rectangle)
7329 Sets the painter's window to the given \a rectangle, and enables
7330 view transformations.
7332 The window rectangle is part of the view transformation. The
7333 window specifies the logical coordinate system. Its sister, the
7334 viewport(), specifies the device coordinate system.
7336 The default window rectangle is the same as the device's
7339 \sa window(), viewTransformEnabled(), {Coordinate
7340 System#Window-Viewport Conversion}{Window-Viewport Conversion}
7344 \fn void QPainter::setWindow(int x, int y, int width, int height)
7347 Sets the painter's window to the rectangle beginning at (\a x, \a
7348 y) and the given \a width and \a height.
7351 void QPainter::setWindow(const QRect &r)
7353 #ifdef QT_DEBUG_DRAW
7354 if (qt_show_painter_debug_output)
7355 printf("QPainter::setWindow(), [%d,%d,%d,%d]\n", r.x(), r.y(), r.width(), r.height());
7361 qWarning("QPainter::setWindow: Painter not active");
7365 d->state->wx = r.x();
7366 d->state->wy = r.y();
7367 d->state->ww = r.width();
7368 d->state->wh = r.height();
7370 d->state->VxF = true;
7375 Returns the window rectangle.
7377 \sa setWindow(), setViewTransformEnabled()
7380 QRect QPainter::window() const
7382 Q_D(const QPainter);
7384 qWarning("QPainter::window: Painter not active");
7387 return QRect(d->state->wx, d->state->wy, d->state->ww, d->state->wh);
7391 \fn void QPainter::setViewport(const QRect &rectangle)
7393 Sets the painter's viewport rectangle to the given \a rectangle,
7394 and enables view transformations.
7396 The viewport rectangle is part of the view transformation. The
7397 viewport specifies the device coordinate system. Its sister, the
7398 window(), specifies the logical coordinate system.
7400 The default viewport rectangle is the same as the device's
7403 \sa viewport(), viewTransformEnabled() {Coordinate
7404 System#Window-Viewport Conversion}{Window-Viewport Conversion}
7408 \fn void QPainter::setViewport(int x, int y, int width, int height)
7411 Sets the painter's viewport rectangle to be the rectangle
7412 beginning at (\a x, \a y) with the given \a width and \a height.
7415 void QPainter::setViewport(const QRect &r)
7417 #ifdef QT_DEBUG_DRAW
7418 if (qt_show_painter_debug_output)
7419 printf("QPainter::setViewport(), [%d,%d,%d,%d]\n", r.x(), r.y(), r.width(), r.height());
7425 qWarning("QPainter::setViewport: Painter not active");
7429 d->state->vx = r.x();
7430 d->state->vy = r.y();
7431 d->state->vw = r.width();
7432 d->state->vh = r.height();
7434 d->state->VxF = true;
7439 Returns the viewport rectangle.
7441 \sa setViewport(), setViewTransformEnabled()
7444 QRect QPainter::viewport() const
7446 Q_D(const QPainter);
7448 qWarning("QPainter::viewport: Painter not active");
7451 return QRect(d->state->vx, d->state->vy, d->state->vw, d->state->vh);
7454 /*! \fn bool QPainter::hasViewXForm() const
7457 Use viewTransformEnabled() instead.
7460 /*! \fn bool QPainter::hasWorldXForm() const
7463 Use worldMatrixEnabled() instead.
7466 /*! \fn void QPainter::resetXForm()
7469 Use resetTransform() instead.
7472 /*! \fn void QPainter::setViewXForm(bool enabled)
7475 Use setViewTransformEnabled() instead.
7478 /*! \fn void QPainter::setWorldXForm(bool enabled)
7481 Use setWorldMatrixEnabled() instead.
7484 Enables view transformations if \a enable is true, or disables
7485 view transformations if \a enable is false.
7487 \sa viewTransformEnabled(), {Coordinate System#Window-Viewport
7488 Conversion}{Window-Viewport Conversion}
7491 void QPainter::setViewTransformEnabled(bool enable)
7493 #ifdef QT_DEBUG_DRAW
7494 if (qt_show_painter_debug_output)
7495 printf("QPainter::setViewTransformEnabled(), enable=%d\n", enable);
7501 qWarning("QPainter::setViewTransformEnabled: Painter not active");
7505 if (enable == d->state->VxF)
7508 d->state->VxF = enable;
7517 Use the worldTransform() combined with QTransform::dx() instead.
7520 QPainter painter(this);
7521 qreal x = painter.translationX();
7523 QPainter painter(this);
7524 qreal x = painter.worldTransform().dx();
7527 qreal QPainter::translationX() const
7529 Q_D(const QPainter);
7531 qWarning("QPainter::translationX: Painter not active");
7534 return d->state->worldMatrix.dx();
7540 Use the worldTransform() combined with QTransform::dy() instead.
7543 QPainter painter(this);
7544 qreal y = painter.translationY();
7546 QPainter painter(this);
7547 qreal y = painter.worldTransform().dy();
7550 qreal QPainter::translationY() const
7552 Q_D(const QPainter);
7554 qWarning("QPainter::translationY: Painter not active");
7557 return d->state->worldMatrix.dy();
7561 \fn void QPainter::map(int x, int y, int *rx, int *ry) const
7565 Sets (\a{rx}, \a{ry}) to the point that results from applying the
7566 painter's current transformation on the point (\a{x}, \a{y}).
7568 void QPainter::map(int x, int y, int *rx, int *ry) const
7571 p = p * combinedMatrix();
7577 \fn QPoint QPainter::xForm(const QPoint &point) const
7579 Use combinedTransform() instead.
7582 QPoint QPainter::xForm(const QPoint &p) const
7584 Q_D(const QPainter);
7586 qWarning("QPainter::xForm: Painter not active");
7589 if (d->state->matrix.type() == QTransform::TxNone)
7591 return p * combinedMatrix();
7596 \fn QRect QPainter::xForm(const QRect &rectangle) const
7599 Use combinedTransform() instead of this function and call
7600 mapRect() on the result to obtain a QRect.
7603 QRect QPainter::xForm(const QRect &r) const
7605 Q_D(const QPainter);
7607 qWarning("QPainter::xForm: Painter not active");
7610 if (d->state->matrix.type() == QTransform::TxNone)
7612 return combinedMatrix().mapRect(r);
7616 \fn QPolygon QPainter::xForm(const QPolygon &polygon) const
7619 Use combinedTransform() instead.
7622 QPolygon QPainter::xForm(const QPolygon &a) const
7624 Q_D(const QPainter);
7626 qWarning("QPainter::xForm: Painter not active");
7629 if (d->state->matrix.type() == QTransform::TxNone)
7631 return a * combinedMatrix();
7635 \fn QPolygon QPainter::xForm(const QPolygon &polygon, int index, int count) const
7638 Use combinedTransform() combined with QPolygon::mid() instead.
7641 QPainter painter(this);
7642 QPolygon transformed = painter.xForm(polygon, index, count)
7644 QPainter painter(this);
7645 QPolygon transformed = polygon.mid(index, count) * painter.combinedTransform();
7649 QPolygon QPainter::xForm(const QPolygon &av, int index, int npoints) const
7651 int lastPoint = npoints < 0 ? av.size() : index+npoints;
7652 QPolygon a(lastPoint-index);
7653 memcpy(a.data(), av.data()+index, (lastPoint-index)*sizeof(QPoint));
7654 return a * combinedMatrix();
7658 \fn QPoint QPainter::xFormDev(const QPoint &point) const
7662 Use combinedTransform() combined with QTransform::inverted() instead.
7665 QPainter painter(this);
7666 QPoint transformed = painter.xFormDev(point);
7668 QPainter painter(this);
7669 QPoint transformed = point * painter.combinedTransform().inverted();
7673 QPoint QPainter::xFormDev(const QPoint &p) const
7675 Q_D(const QPainter);
7677 qWarning("QPainter::xFormDev: Painter not active");
7680 if(d->state->matrix.type() == QTransform::TxNone)
7682 return p * combinedMatrix().inverted();
7686 \fn QRect QPainter::xFormDev(const QRect &rectangle) const
7690 Use combinedTransform() combined with QTransform::inverted() instead.
7693 QPainter painter(this);
7694 QRect transformed = painter.xFormDev(rectangle);
7696 QPainter painter(this);
7697 QRegion region = QRegion(rectangle) * painter.combinedTransform().inverted();
7698 QRect transformed = region.boundingRect();
7702 QRect QPainter::xFormDev(const QRect &r) const
7704 Q_D(const QPainter);
7706 qWarning("QPainter::xFormDev: Painter not active");
7709 if (d->state->matrix.type() == QTransform::TxNone)
7711 return combinedMatrix().inverted().mapRect(r);
7717 \fn QPoint QPainter::xFormDev(const QPolygon &polygon) const
7720 Use combinedTransform() combined with QTransform::inverted() instead.
7723 QPainter painter(this);
7724 QPolygon transformed = painter.xFormDev(rectangle);
7726 QPainter painter(this);
7727 QPolygon transformed = polygon * painter.combinedTransform().inverted();
7731 QPolygon QPainter::xFormDev(const QPolygon &a) const
7733 Q_D(const QPainter);
7735 qWarning("QPainter::xFormDev: Painter not active");
7738 if (d->state->matrix.type() == QTransform::TxNone)
7740 return a * combinedMatrix().inverted();
7744 \fn QPolygon QPainter::xFormDev(const QPolygon &polygon, int index, int count) const
7748 Use combinedTransform() combined with QPolygon::mid() and QTransform::inverted() instead.
7751 QPainter painter(this);
7752 QPolygon transformed = painter.xFormDev(polygon, index, count);
7754 QPainter painter(this);
7755 QPolygon transformed = polygon.mid(index, count) * painter.combinedTransform().inverted();
7759 QPolygon QPainter::xFormDev(const QPolygon &ad, int index, int npoints) const
7761 Q_D(const QPainter);
7762 int lastPoint = npoints < 0 ? ad.size() : index+npoints;
7763 QPolygon a(lastPoint-index);
7764 memcpy(a.data(), ad.data()+index, (lastPoint-index)*sizeof(QPoint));
7765 if (d->state->matrix.type() == QTransform::TxNone)
7767 return a * combinedMatrix().inverted();
7771 \fn void QPainter::drawCubicBezier(const QPolygon &controlPoints, int index)
7773 Draws a cubic Bezier curve defined by the \a controlPoints,
7774 starting at \a{controlPoints}\e{[index]} (\a index defaults to 0).
7775 Points after \a{controlPoints}\e{[index + 3]} are ignored. Nothing
7776 happens if there aren't enough control points.
7778 Use strokePath() instead.
7781 QPainter painter(this);
7782 painter.drawCubicBezier(controlPoints, index)
7785 path.moveTo(controlPoints.at(index));
7786 path.cubicTo(controlPoints.at(index+1),
7787 controlPoints.at(index+2),
7788 controlPoints.at(index+3));
7790 QPainter painter(this);
7791 painter.strokePath(path, painter.pen());
7794 void QPainter::drawCubicBezier(const QPolygon &a, int index)
7801 if ((int)a.size() - index < 4) {
7802 qWarning("QPainter::drawCubicBezier: Cubic Bezier needs 4 control "
7808 path.moveTo(a.at(index));
7809 path.cubicTo(a.at(index+1), a.at(index+2), a.at(index+3));
7810 strokePath(path, d->state->pen);
7814 struct QPaintDeviceRedirection
7816 QPaintDeviceRedirection() : device(0), replacement(0), internalWidgetRedirectionIndex(-1) {}
7817 QPaintDeviceRedirection(const QPaintDevice *device, QPaintDevice *replacement,
7818 const QPoint& offset, int internalWidgetRedirectionIndex)
7819 : device(device), replacement(replacement), offset(offset),
7820 internalWidgetRedirectionIndex(internalWidgetRedirectionIndex) { }
7821 const QPaintDevice *device;
7822 QPaintDevice *replacement;
7824 int internalWidgetRedirectionIndex;
7825 bool operator==(const QPaintDevice *pdev) const { return device == pdev; }
7826 Q_DUMMY_COMPARISON_OPERATOR(QPaintDeviceRedirection)
7829 typedef QList<QPaintDeviceRedirection> QPaintDeviceRedirectionList;
7830 Q_GLOBAL_STATIC(QPaintDeviceRedirectionList, globalRedirections)
7831 Q_GLOBAL_STATIC(QMutex, globalRedirectionsMutex)
7832 Q_GLOBAL_STATIC(QAtomicInt, globalRedirectionAtomic)
7839 Please use QWidget::render() instead.
7841 Redirects all paint commands for the given paint \a device, to the
7842 \a replacement device. The optional point \a offset defines an
7843 offset within the source device.
7845 The redirection will not be effective until the begin() function
7846 has been called; make sure to call end() for the given \a
7847 device's painter (if any) before redirecting. Call
7848 restoreRedirected() to restore the previous redirection.
7850 \warning Making use of redirections in the QPainter API implies
7851 that QPainter::begin() and QPaintDevice destructors need to hold
7852 a mutex for a short period. This can impact performance. Use of
7853 QWidget::render is strongly encouraged.
7855 \sa redirected(), restoreRedirected()
7857 void QPainter::setRedirected(const QPaintDevice *device,
7858 QPaintDevice *replacement,
7859 const QPoint &offset)
7861 Q_ASSERT(device != 0);
7863 bool hadInternalWidgetRedirection = false;
7864 if (device->devType() == QInternal::Widget) {
7865 const QWidgetPrivate *widgetPrivate = static_cast<const QWidget *>(device)->d_func();
7866 // This is the case when the widget is in a paint event.
7867 if (widgetPrivate->redirectDev) {
7868 // Remove internal redirection and put it back into the global redirection list.
7870 QPaintDevice *oldReplacement = widgetPrivate->redirected(&oldOffset);
7871 const_cast<QWidgetPrivate *>(widgetPrivate)->restoreRedirected();
7872 setRedirected(device, oldReplacement, oldOffset);
7873 hadInternalWidgetRedirection = true;
7878 QPaintDevice *rdev = redirected(replacement, &roffset);
7880 QMutexLocker locker(globalRedirectionsMutex());
7881 QPaintDeviceRedirectionList *redirections = globalRedirections();
7882 Q_ASSERT(redirections != 0);
7883 *redirections += QPaintDeviceRedirection(device, rdev ? rdev : replacement, offset + roffset,
7884 hadInternalWidgetRedirection ? redirections->size() - 1 : -1);
7885 globalRedirectionAtomic()->ref();
7893 Using QWidget::render() obsoletes the use of this function.
7895 Restores the previous redirection for the given \a device after a
7896 call to setRedirected().
7898 \warning Making use of redirections in the QPainter API implies
7899 that QPainter::begin() and QPaintDevice destructors need to hold
7900 a mutex for a short period. This can impact performance. Use of
7901 QWidget::render is strongly encouraged.
7905 void QPainter::restoreRedirected(const QPaintDevice *device)
7907 Q_ASSERT(device != 0);
7908 QMutexLocker locker(globalRedirectionsMutex());
7909 QPaintDeviceRedirectionList *redirections = globalRedirections();
7910 Q_ASSERT(redirections != 0);
7911 for (int i = redirections->size()-1; i >= 0; --i) {
7912 if (redirections->at(i) == device) {
7913 globalRedirectionAtomic()->deref();
7914 const int internalWidgetRedirectionIndex = redirections->at(i).internalWidgetRedirectionIndex;
7915 redirections->removeAt(i);
7916 // Restore the internal widget redirection, i.e. remove it from the global
7917 // redirection list and put it back into QWidgetPrivate. The index is only set when
7918 // someone call QPainter::setRedirected in a widget's paint event and we internally
7919 // have a redirection set (typically set in QWidgetPrivate::drawWidget).
7920 if (internalWidgetRedirectionIndex >= 0) {
7921 Q_ASSERT(internalWidgetRedirectionIndex < redirections->size());
7922 const QPaintDeviceRedirection &redirectionDevice = redirections->at(internalWidgetRedirectionIndex);
7923 QWidget *widget = static_cast<QWidget *>(const_cast<QPaintDevice *>(device));
7924 widget->d_func()->setRedirected(redirectionDevice.replacement, redirectionDevice.offset);
7925 redirections->removeAt(internalWidgetRedirectionIndex);
7937 Using QWidget::render() obsoletes the use of this function.
7939 Returns the replacement for given \a device. The optional out
7940 parameter \a offset returns the offset within the replaced device.
7942 \warning Making use of redirections in the QPainter API implies
7943 that QPainter::begin() and QPaintDevice destructors need to hold
7944 a mutex for a short period. This can impact performance. Use of
7945 QWidget::render is strongly encouraged.
7947 \sa setRedirected(), restoreRedirected()
7949 QPaintDevice *QPainter::redirected(const QPaintDevice *device, QPoint *offset)
7951 Q_ASSERT(device != 0);
7953 if (device->devType() == QInternal::Widget) {
7954 const QWidgetPrivate *widgetPrivate = static_cast<const QWidget *>(device)->d_func();
7955 if (widgetPrivate->redirectDev)
7956 return widgetPrivate->redirected(offset);
7959 if (!globalRedirectionAtomic() || *globalRedirectionAtomic() == 0)
7962 QMutexLocker locker(globalRedirectionsMutex());
7963 QPaintDeviceRedirectionList *redirections = globalRedirections();
7964 Q_ASSERT(redirections != 0);
7965 for (int i = redirections->size()-1; i >= 0; --i)
7966 if (redirections->at(i) == device) {
7968 *offset = redirections->at(i).offset;
7969 return redirections->at(i).replacement;
7972 *offset = QPoint(0, 0);
7977 void qt_painter_removePaintDevice(QPaintDevice *dev)
7979 if (!globalRedirectionAtomic() || *globalRedirectionAtomic() == 0)
7984 mutex = globalRedirectionsMutex();
7986 // ignore the missing mutex, since we could be called from
7987 // a destructor, and destructors shall not throw
7989 QMutexLocker locker(mutex);
7990 QPaintDeviceRedirectionList *redirections = 0;
7992 redirections = globalRedirections();
7994 // do nothing - code below is safe with redirections being 0.
7997 for (int i = 0; i < redirections->size(); ) {
7998 if(redirections->at(i) == dev || redirections->at(i).replacement == dev)
7999 redirections->removeAt(i);
8006 void qt_format_text(const QFont &fnt, const QRectF &_r,
8007 int tf, const QString& str, QRectF *brect,
8008 int tabstops, int *ta, int tabarraylen,
8011 qt_format_text(fnt, _r,
8013 tabstops, ta, tabarraylen,
8016 void qt_format_text(const QFont &fnt, const QRectF &_r,
8017 int tf, const QTextOption *option, const QString& str, QRectF *brect,
8018 int tabstops, int *ta, int tabarraylen,
8022 Q_ASSERT( !((tf & ~Qt::TextDontPrint)!=0 && option!=0) ); // we either have an option or flags
8025 tf |= option->alignment();
8026 if (option->wrapMode() != QTextOption::NoWrap)
8027 tf |= Qt::TextWordWrap;
8029 if (option->flags() & QTextOption::IncludeTrailingSpaces)
8030 tf |= Qt::TextIncludeTrailingSpaces;
8032 if (option->tabStop() >= 0 || !option->tabArray().isEmpty())
8033 tf |= Qt::TextExpandTabs;
8036 // we need to copy r here to protect against the case (&r == brect).
8039 bool dontclip = (tf & Qt::TextDontClip);
8040 bool wordwrap = (tf & Qt::TextWordWrap) || (tf & Qt::TextWrapAnywhere);
8041 bool singleline = (tf & Qt::TextSingleLine);
8042 bool showmnemonic = (tf & Qt::TextShowMnemonic);
8043 bool hidemnmemonic = (tf & Qt::TextHideMnemonic);
8045 Qt::LayoutDirection layout_direction;
8046 if (tf & Qt::TextForceLeftToRight)
8047 layout_direction = Qt::LeftToRight;
8048 else if (tf & Qt::TextForceRightToLeft)
8049 layout_direction = Qt::RightToLeft;
8051 layout_direction = option->textDirection();
8053 layout_direction = painter->layoutDirection();
8055 layout_direction = Qt::LeftToRight;
8057 tf = QStyle::visualAlignment(layout_direction, QFlag(tf));
8059 bool isRightToLeft = layout_direction == Qt::RightToLeft;
8060 bool expandtabs = ((tf & Qt::TextExpandTabs) &&
8061 (((tf & Qt::AlignLeft) && !isRightToLeft) ||
8062 ((tf & Qt::AlignRight) && isRightToLeft)));
8065 tf |= Qt::TextDontPrint;
8067 uint maxUnderlines = 0;
8068 int numUnderlines = 0;
8069 QVarLengthArray<int, 32> underlinePositions(1);
8071 QFontMetricsF fm(fnt);
8074 start_lengthVariant:
8075 bool hasMoreLengthVariants = false;
8076 // compatible behaviour to the old implementation. Replace
8078 int old_offset = offset;
8079 for (; offset < text.length(); offset++) {
8080 QChar chr = text.at(offset);
8081 if (chr == QLatin1Char('\r') || (singleline && chr == QLatin1Char('\n'))) {
8082 text[offset] = QLatin1Char(' ');
8083 } else if (chr == QLatin1Char('\n')) {
8084 text[offset] = QChar::LineSeparator;
8085 } else if (chr == QLatin1Char('&')) {
8087 } else if (chr == QLatin1Char('\t')) {
8089 text[offset] = QLatin1Char(' ');
8090 } else if (!tabarraylen && !tabstops) {
8091 tabstops = qRound(fm.width(QLatin1Char('x'))*8);
8093 } else if (chr == QChar(ushort(0x9c))) {
8094 // string with multiple length variants
8095 hasMoreLengthVariants = true;
8100 int length = offset - old_offset;
8101 if ((hidemnmemonic || showmnemonic) && maxUnderlines > 0) {
8102 underlinePositions.resize(maxUnderlines + 1);
8104 QChar *cout = text.data() + old_offset;
8108 if (*cin == QLatin1Char('&')) {
8114 if (*cin != QLatin1Char('&') && !hidemnmemonic)
8115 underlinePositions[numUnderlines++] = cout - text.data() - old_offset;
8124 // no need to do extra work for underlines if we don't paint
8125 if (tf & Qt::TextDontPrint)
8128 underlinePositions[numUnderlines] = -1;
8132 QString finalText = text.mid(old_offset, length);
8133 QStackTextEngine engine(finalText, fnt);
8135 engine.option = *option;
8138 if (engine.option.tabStop() < 0 && tabstops > 0)
8139 engine.option.setTabStop(tabstops);
8141 if (engine.option.tabs().isEmpty() && ta) {
8143 for (int i = 0; i < tabarraylen; i++)
8144 tabs.append(qreal(ta[i]));
8145 engine.option.setTabArray(tabs);
8148 engine.option.setTextDirection(layout_direction);
8149 if (tf & Qt::AlignJustify)
8150 engine.option.setAlignment(Qt::AlignJustify);
8152 engine.option.setAlignment(Qt::AlignLeft); // do not do alignment twice
8154 if (!option && (tf & Qt::TextWrapAnywhere))
8155 engine.option.setWrapMode(QTextOption::WrapAnywhere);
8157 if (tf & Qt::TextJustificationForced)
8158 engine.forceJustification = true;
8159 QTextLayout textLayout(&engine);
8160 textLayout.setCacheEnabled(true);
8161 textLayout.engine()->underlinePositions = underlinePositions.data();
8163 if (finalText.isEmpty()) {
8164 height = fm.height();
8166 tf |= Qt::TextDontPrint;
8168 qreal lineWidth = 0x01000000;
8169 if (wordwrap || (tf & Qt::TextJustificationForced))
8170 lineWidth = qMax<qreal>(0, r.width());
8172 tf |= Qt::TextIncludeTrailingSpaces;
8173 textLayout.engine()->ignoreBidi = bool(tf & Qt::TextDontPrint);
8174 textLayout.beginLayout();
8176 qreal leading = fm.leading();
8180 QTextLine l = textLayout.createLine();
8184 l.setLineWidth(lineWidth);
8186 l.setPosition(QPointF(0., height));
8187 height += l.height();
8188 width = qMax(width, l.naturalTextWidth());
8189 if (!dontclip && !brect && height >= r.height())
8192 textLayout.endLayout();
8197 if (tf & Qt::AlignBottom) {
8198 yoff = r.height() - height;
8199 } else if (tf & Qt::AlignVCenter) {
8200 yoff = (r.height() - height)/2;
8202 QTransform::TransformationType type = painter->transform().type();
8203 if (type <= QTransform::TxScale) {
8204 // do the rounding manually to work around inconsistencies
8205 // in the paint engines when drawing on floating point offsets
8206 const qreal scale = painter->transform().m22();
8208 yoff = -qRound(-yoff * scale) / scale;
8212 if (tf & Qt::AlignRight) {
8213 xoff = r.width() - width;
8214 } else if (tf & Qt::AlignHCenter) {
8215 xoff = (r.width() - width)/2;
8217 QTransform::TransformationType type = painter->transform().type();
8218 if (type <= QTransform::TxScale) {
8219 // do the rounding manually to work around inconsistencies
8220 // in the paint engines when drawing on floating point offsets
8221 const qreal scale = painter->transform().m11();
8223 xoff = qRound(xoff * scale) / scale;
8227 QRectF bounds = QRectF(r.x() + xoff, r.y() + yoff, width, height);
8229 if (hasMoreLengthVariants && !(tf & Qt::TextLongestVariant) && !r.contains(bounds)) {
8231 goto start_lengthVariant;
8236 if (!(tf & Qt::TextDontPrint)) {
8237 bool restore = false;
8238 if (!dontclip && !r.contains(bounds)) {
8241 painter->setClipRect(r, Qt::IntersectClip);
8244 for (int i = 0; i < textLayout.lineCount(); i++) {
8245 QTextLine line = textLayout.lineAt(i);
8247 qreal advance = line.horizontalAdvance();
8249 if (tf & Qt::AlignRight) {
8250 QTextEngine *eng = textLayout.engine();
8251 xoff = r.width() - advance -
8252 eng->leadingSpaceWidth(eng->lines[line.lineNumber()]).toReal();
8254 else if (tf & Qt::AlignHCenter)
8255 xoff = (r.width() - advance) / 2;
8257 line.draw(painter, QPointF(r.x() + xoff, r.y() + yoff));
8267 Sets the layout direction used by the painter when drawing text,
8268 to the specified \a direction.
8270 The default is Qt::LayoutDirectionAuto, which will implicitly determine the
8271 direction from the text drawn.
8273 \sa QTextOption::setTextDirection(), layoutDirection(), drawText(), {QPainter#Settings}{Settings}
8275 void QPainter::setLayoutDirection(Qt::LayoutDirection direction)
8279 d->state->layoutDirection = direction;
8283 Returns the layout direction used by the painter when drawing text.
8285 \sa QTextOption::textDirection(), setLayoutDirection(), drawText(), {QPainter#Settings}{Settings}
8287 Qt::LayoutDirection QPainter::layoutDirection() const
8289 Q_D(const QPainter);
8290 return d->state ? d->state->layoutDirection : Qt::LayoutDirectionAuto;
8293 QPainterState::QPainterState(const QPainterState *s)
8294 : brushOrigin(s->brushOrigin), font(s->font), deviceFont(s->deviceFont),
8295 pen(s->pen), brush(s->brush), bgBrush(s->bgBrush),
8296 clipRegion(s->clipRegion), clipPath(s->clipPath),
8297 clipOperation(s->clipOperation),
8298 renderHints(s->renderHints), clipInfo(s->clipInfo),
8299 worldMatrix(s->worldMatrix), matrix(s->matrix), redirectionMatrix(s->redirectionMatrix),
8300 wx(s->wx), wy(s->wy), ww(s->ww), wh(s->wh),
8301 vx(s->vx), vy(s->vy), vw(s->vw), vh(s->vh),
8302 opacity(s->opacity), WxF(s->WxF), VxF(s->VxF),
8303 clipEnabled(s->clipEnabled), bgMode(s->bgMode), painter(s->painter),
8304 layoutDirection(s->layoutDirection),
8305 composition_mode(s->composition_mode),
8306 emulationSpecifier(s->emulationSpecifier), changeFlags(0)
8308 dirtyFlags = s->dirtyFlags;
8311 QPainterState::QPainterState()
8312 : brushOrigin(0, 0), bgBrush(Qt::white), clipOperation(Qt::NoClip),
8314 wx(0), wy(0), ww(0), wh(0), vx(0), vy(0), vw(0), vh(0),
8315 opacity(1), WxF(false), VxF(false), clipEnabled(true),
8316 bgMode(Qt::TransparentMode), painter(0),
8317 layoutDirection(QApplication::layoutDirection()),
8318 composition_mode(QPainter::CompositionMode_SourceOver),
8319 emulationSpecifier(0), changeFlags(0)
8324 QPainterState::~QPainterState()
8328 void QPainterState::init(QPainter *p) {
8329 bgBrush = Qt::white;
8330 bgMode = Qt::TransparentMode;
8334 wx = wy = ww = wh = 0;
8335 vx = vy = vw = vh = 0;
8338 brushOrigin = QPointF(0, 0);
8340 font = deviceFont = QFont();
8341 clipRegion = QRegion();
8342 clipPath = QPainterPath();
8343 clipOperation = Qt::NoClip;
8345 worldMatrix.reset();
8347 layoutDirection = QApplication::layoutDirection();
8348 composition_mode = QPainter::CompositionMode_SourceOver;
8349 emulationSpecifier = 0;
8357 static void bitBlt_helper(QPaintDevice *dst, const QPoint &dp,
8358 const QPaintDevice *src, const QRect &sr, bool)
8363 if (src->devType() == QInternal::Pixmap) {
8364 const QPixmap *pixmap = static_cast<const QPixmap *>(src);
8366 pt.drawPixmap(dp, *pixmap, sr);
8369 qWarning("QPainter: bitBlt only works when source is of type pixmap");
8373 void bitBlt(QPaintDevice *dst, int dx, int dy,
8374 const QPaintDevice *src, int sx, int sy, int sw, int sh,
8377 bitBlt_helper(dst, QPoint(dx, dy), src, QRect(sx, sy, sw, sh), ignoreMask);
8380 void bitBlt(QPaintDevice *dst, const QPoint &dp, const QPaintDevice *src, const QRect &sr, bool ignoreMask)
8382 bitBlt_helper(dst, dp, src, sr, ignoreMask);
8385 void bitBlt(QPaintDevice *dst, int dx, int dy,
8386 const QImage *src, int sx, int sy, int sw, int sh, int fl)
8388 Qt::ImageConversionFlags flags(fl);
8389 QPixmap srcPixmap = QPixmap::fromImage(*src, flags);
8390 bitBlt_helper(dst, QPoint(dx, dy), &srcPixmap, QRect(sx, sy, sw, sh), false);
8393 #endif // QT3_SUPPORT
8396 \fn void QPainter::setBackgroundColor(const QColor &color)
8398 Use setBackground() instead.
8402 \fn const QColor &QPainter::backgroundColor() const
8404 Use background() and QBrush::color() instead.
8407 QColor myColor = backgroundColor();
8409 QColor myColor = background().color();
8412 Note that the background can be a complex brush such as a texture
8417 \fn void QPainter::drawText(int x, int y, const QString &text, int pos, int length)
8420 Use drawText() combined with QString::mid() instead.
8423 QPainter painter(this);
8424 painter.drawText(x, y, text, pos, length);
8426 QPainter painter(this);
8427 painter.drawText(x, y, text.mid(pos, length));
8432 \fn void QPainter::drawText(const QPoint &point, const QString &text, int pos, int length)
8435 Use drawText() combined with QString::mid() instead.
8438 QPainter painter(this);
8439 painter.drawText(point, text, pos, length);
8441 QPainter painter(this);
8442 painter.drawText(point, text.mid(pos, length));
8447 \fn void QPainter::drawText(int x, int y, const QString &text, int length)
8450 Use drawText() combined with QString::left() instead.
8453 QPainter painter(this);
8454 painter.drawText(x, y, text, length);
8456 QPainter painter(this);
8457 painter.drawText(x, y, text.left(length));
8462 \fn void QPainter::drawText(const QPoint &point, const QString &text, int length)
8465 Use drawText() combined with QString::left() instead.
8468 QPainter painter(this);
8469 painter.drawText(point, text, length);
8471 QPainter painter(this);
8472 painter.drawText(point, text.left(length));
8477 \fn bool QPainter::begin(QPaintDevice *device, const QWidget *init)
8480 Use begin() instead.
8482 If the paint \a device is a QWidget, QPainter is initialized after
8483 the widget's settings automatically. Otherwise, you must call the
8484 initFrom() function to initialize the painters pen, background and
8485 font to the same as any given widget.
8488 QPainter painter(this);
8489 painter.begin(device, init);
8491 QPainter painter(this);
8492 painter.begin(device);
8493 painter.initFrom(init);
8498 \fn void QPainter::drawImage(const QRectF &target, const QImage &image, const QRectF &source,
8499 Qt::ImageConversionFlags flags)
8501 Draws the rectangular portion \a source of the given \a image
8502 into the \a target rectangle in the paint device.
8504 \note The image is scaled to fit the rectangle, if both the image and rectangle size disagree.
8506 If the image needs to be modified to fit in a lower-resolution
8507 result (e.g. converting from 32-bit to 8-bit), use the \a flags to
8508 specify how you would prefer this to happen.
8513 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 20
8520 \fn void QPainter::drawImage(const QRect &target, const QImage &image, const QRect &source,
8521 Qt::ImageConversionFlags flags)
8524 Draws the rectangular portion \a source of the given \a image
8525 into the \a target rectangle in the paint device.
8527 \note The image is scaled to fit the rectangle, if both the image and rectangle size disagree.
8531 \fn void QPainter::drawImage(const QPointF &point, const QImage &image)
8535 Draws the given \a image at the given \a point.
8539 \fn void QPainter::drawImage(const QPoint &point, const QImage &image)
8543 Draws the given \a image at the given \a point.
8547 \fn void QPainter::drawImage(const QPointF &point, const QImage &image, const QRectF &source,
8548 Qt::ImageConversionFlags flags = 0)
8552 Draws the rectangular portion \a source of the given \a image with
8553 its origin at the given \a point.
8557 \fn void QPainter::drawImage(const QPoint &point, const QImage &image, const QRect &source,
8558 Qt::ImageConversionFlags flags = 0)
8561 Draws the rectangular portion \a source of the given \a image with
8562 its origin at the given \a point.
8566 \fn void QPainter::drawImage(const QRectF &rectangle, const QImage &image)
8570 Draws the given \a image into the given \a rectangle.
8572 \note The image is scaled to fit the rectangle, if both the image and rectangle size disagree.
8576 \fn void QPainter::drawImage(const QRect &rectangle, const QImage &image)
8580 Draws the given \a image into the given \a rectangle.
8582 \note The image is scaled to fit the rectangle, if both the image and rectangle size disagree.
8586 \fn void QPainter::drawImage(int x, int y, const QImage &image,
8587 int sx, int sy, int sw, int sh,
8588 Qt::ImageConversionFlags flags)
8591 Draws an image at (\a{x}, \a{y}) by copying a part of \a image into
8594 (\a{x}, \a{y}) specifies the top-left point in the paint device that is
8595 to be drawn onto. (\a{sx}, \a{sy}) specifies the top-left point in \a
8596 image that is to be drawn. The default is (0, 0).
8598 (\a{sw}, \a{sh}) specifies the size of the image that is to be drawn.
8599 The default, (0, 0) (and negative) means all the way to the
8600 bottom-right of the image.
8604 \fn void QPainter::redirect(QPaintDevice *pdev, QPaintDevice *replacement)
8606 Use setRedirected() instead.
8610 \fn QPaintDevice *QPainter::redirect(QPaintDevice *pdev)
8612 Use redirected() instead.
8616 \fn QRect QPainter::boundingRect(const QRect &rectangle, int flags,
8617 const QString &text, int length)
8620 Returns the bounding rectangle for the given \a length of the \a
8621 text constrained by the provided \a rectangle.
8623 Use boundingRect() combined with QString::left() instead.
8626 QRect rectangle = boundingRect(rect, flags, text, length);
8628 QRect rectangle = boundingRect(rect, flags, text.left(length));
8633 \fn void QPainter::drawText(const QRect &rectangle, int flags, const QString &text,
8634 int length, QRect *br)
8637 Use drawText() combined with QString::left() instead.
8640 QPainter painter(this);
8641 painter.drawText(rectangle, flags, text, length, br );
8643 QPainter painter(this);
8644 painter.drawText(rectangle, flags, text.left(length), br );
8649 \fn QRect QPainter::boundingRect(int x, int y, int width, int height, int flags,
8650 const QString &text, int length);
8654 Returns the bounding rectangle for the given \a length of the \a
8655 text constrained by the rectangle that begins at point (\a{x},
8656 \a{y}) with the given \a width and \a height.
8658 Use boundingRect() combined with QString::left() instead.
8661 QRect rectangle = boundingRect(x, y, width, height, flags, text, length);
8663 QRect rectangle = boundingRect(x, y, width, height, flags, text.left(length));
8668 \fn void QPainter::drawText(int x, int y, int width, int height, int flags,
8669 const QString &text, int length, QRect *br)
8673 Use drawText() combined with QString::left() instead.
8676 QPainter painter(this);
8677 painter.drawText(x, y, width, height, flags, text, length, br );
8679 QPainter painter(this);
8680 painter.drawText(x, y, width, height, flags, text.left(length), br );
8686 \class QPaintEngineState
8689 \brief The QPaintEngineState class provides information about the
8690 active paint engine's current state.
8693 QPaintEngineState records which properties that have changed since
8694 the last time the paint engine was updated, as well as their
8697 Which properties that have changed can at any time be retrieved
8698 using the state() function. This function returns an instance of
8699 the QPaintEngine::DirtyFlags type which stores an OR combination
8700 of QPaintEngine::DirtyFlag values. The QPaintEngine::DirtyFlag
8701 enum defines whether a property has changed since the last update
8704 If a property is marked with a dirty flag, its current value can
8705 be retrieved using the corresponding get function:
8710 \header \o Property Flag \o Current Property Value
8711 \row \o QPaintEngine::DirtyBackground \o backgroundBrush()
8712 \row \o QPaintEngine::DirtyBackgroundMode \o backgroundMode()
8713 \row \o QPaintEngine::DirtyBrush \o brush()
8714 \row \o QPaintEngine::DirtyBrushOrigin \o brushOrigin()
8715 \row \o QPaintEngine::DirtyClipRegion \e or QPaintEngine::DirtyClipPath
8717 \row \o QPaintEngine::DirtyClipPath \o clipPath()
8718 \row \o QPaintEngine::DirtyClipRegion \o clipRegion()
8719 \row \o QPaintEngine::DirtyCompositionMode \o compositionMode()
8720 \row \o QPaintEngine::DirtyFont \o font()
8721 \row \o QPaintEngine::DirtyTransform \o transform()
8722 \row \o QPaintEngine::DirtyClipEnabled \o isClipEnabled()
8723 \row \o QPaintEngine::DirtyPen \o pen()
8724 \row \o QPaintEngine::DirtyHints \o renderHints()
8727 The QPaintEngineState class also provide the painter() function
8728 which returns a pointer to the painter that is currently updating
8731 An instance of this class, representing the current state of the
8732 active paint engine, is passed as argument to the
8733 QPaintEngine::updateState() function. The only situation in which
8734 you will have to use this class directly is when implementing your
8742 \fn QPaintEngine::DirtyFlags QPaintEngineState::state() const
8744 Returns a combination of flags identifying the set of properties
8745 that need to be updated when updating the paint engine's state
8746 (i.e. during a call to the QPaintEngine::updateState() function).
8748 \sa QPaintEngine::updateState()
8753 Returns the pen in the current paint engine state.
8755 This variable should only be used when the state() returns a
8756 combination which includes the QPaintEngine::DirtyPen flag.
8758 \sa state(), QPaintEngine::updateState()
8761 QPen QPaintEngineState::pen() const
8763 return static_cast<const QPainterState *>(this)->pen;
8767 Returns the brush in the current paint engine state.
8769 This variable should only be used when the state() returns a
8770 combination which includes the QPaintEngine::DirtyBrush flag.
8772 \sa state(), QPaintEngine::updateState()
8775 QBrush QPaintEngineState::brush() const
8777 return static_cast<const QPainterState *>(this)->brush;
8781 Returns the brush origin in the current paint engine state.
8783 This variable should only be used when the state() returns a
8784 combination which includes the QPaintEngine::DirtyBrushOrigin flag.
8786 \sa state(), QPaintEngine::updateState()
8789 QPointF QPaintEngineState::brushOrigin() const
8791 return static_cast<const QPainterState *>(this)->brushOrigin;
8795 Returns the background brush in the current paint engine state.
8797 This variable should only be used when the state() returns a
8798 combination which includes the QPaintEngine::DirtyBackground flag.
8800 \sa state(), QPaintEngine::updateState()
8803 QBrush QPaintEngineState::backgroundBrush() const
8805 return static_cast<const QPainterState *>(this)->bgBrush;
8809 Returns the background mode in the current paint engine
8812 This variable should only be used when the state() returns a
8813 combination which includes the QPaintEngine::DirtyBackgroundMode flag.
8815 \sa state(), QPaintEngine::updateState()
8818 Qt::BGMode QPaintEngineState::backgroundMode() const
8820 return static_cast<const QPainterState *>(this)->bgMode;
8824 Returns the font in the current paint engine
8827 This variable should only be used when the state() returns a
8828 combination which includes the QPaintEngine::DirtyFont flag.
8830 \sa state(), QPaintEngine::updateState()
8833 QFont QPaintEngineState::font() const
8835 return static_cast<const QPainterState *>(this)->font;
8842 Returns the matrix in the current paint engine
8845 \note It is advisable to use transform() instead of this function to
8846 preserve the properties of perspective transformations.
8848 This variable should only be used when the state() returns a
8849 combination which includes the QPaintEngine::DirtyTransform flag.
8851 \sa state(), QPaintEngine::updateState()
8854 QMatrix QPaintEngineState::matrix() const
8856 const QPainterState *st = static_cast<const QPainterState *>(this);
8858 return st->matrix.toAffine();
8864 Returns the matrix in the current paint engine state.
8866 This variable should only be used when the state() returns a
8867 combination which includes the QPaintEngine::DirtyTransform flag.
8869 \sa state(), QPaintEngine::updateState()
8873 QTransform QPaintEngineState::transform() const
8875 const QPainterState *st = static_cast<const QPainterState *>(this);
8882 Returns the clip operation in the current paint engine
8885 This variable should only be used when the state() returns a
8886 combination which includes either the QPaintEngine::DirtyClipPath
8887 or the QPaintEngine::DirtyClipRegion flag.
8889 \sa state(), QPaintEngine::updateState()
8892 Qt::ClipOperation QPaintEngineState::clipOperation() const
8894 return static_cast<const QPainterState *>(this)->clipOperation;
8900 Returns whether the coordinate of the fill have been specified
8901 as bounded by the current rendering operation and have to be
8902 resolved (about the currently rendered primitive).
8904 bool QPaintEngineState::brushNeedsResolving() const
8906 const QBrush &brush = static_cast<const QPainterState *>(this)->brush;
8907 return needsResolving(brush);
8914 Returns whether the coordinate of the stroke have been specified
8915 as bounded by the current rendering operation and have to be
8916 resolved (about the currently rendered primitive).
8918 bool QPaintEngineState::penNeedsResolving() const
8920 const QPen &pen = static_cast<const QPainterState *>(this)->pen;
8921 return needsResolving(pen.brush());
8925 Returns the clip region in the current paint engine state.
8927 This variable should only be used when the state() returns a
8928 combination which includes the QPaintEngine::DirtyClipRegion flag.
8930 \sa state(), QPaintEngine::updateState()
8933 QRegion QPaintEngineState::clipRegion() const
8935 return static_cast<const QPainterState *>(this)->clipRegion;
8939 Returns the clip path in the current paint engine state.
8941 This variable should only be used when the state() returns a
8942 combination which includes the QPaintEngine::DirtyClipPath flag.
8944 \sa state(), QPaintEngine::updateState()
8947 QPainterPath QPaintEngineState::clipPath() const
8949 return static_cast<const QPainterState *>(this)->clipPath;
8953 Returns whether clipping is enabled or not in the current paint
8956 This variable should only be used when the state() returns a
8957 combination which includes the QPaintEngine::DirtyClipEnabled
8960 \sa state(), QPaintEngine::updateState()
8963 bool QPaintEngineState::isClipEnabled() const
8965 return static_cast<const QPainterState *>(this)->clipEnabled;
8969 Returns the render hints in the current paint engine state.
8971 This variable should only be used when the state() returns a
8972 combination which includes the QPaintEngine::DirtyHints
8975 \sa state(), QPaintEngine::updateState()
8978 QPainter::RenderHints QPaintEngineState::renderHints() const
8980 return static_cast<const QPainterState *>(this)->renderHints;
8984 Returns the composition mode in the current paint engine state.
8986 This variable should only be used when the state() returns a
8987 combination which includes the QPaintEngine::DirtyCompositionMode
8990 \sa state(), QPaintEngine::updateState()
8993 QPainter::CompositionMode QPaintEngineState::compositionMode() const
8995 return static_cast<const QPainterState *>(this)->composition_mode;
9000 Returns a pointer to the painter currently updating the paint
9004 QPainter *QPaintEngineState::painter() const
9006 return static_cast<const QPainterState *>(this)->painter;
9013 Returns the opacity in the current paint engine state.
9016 qreal QPaintEngineState::opacity() const
9018 return static_cast<const QPainterState *>(this)->opacity;
9024 Sets the world transformation matrix.
9025 If \a combine is true, the specified \a transform is combined with
9026 the current matrix; otherwise it replaces the current matrix.
9028 \sa transform() setWorldTransform()
9031 void QPainter::setTransform(const QTransform &transform, bool combine )
9033 setWorldTransform(transform, combine);
9037 Returns the world transformation matrix.
9039 \sa worldTransform()
9042 const QTransform & QPainter::transform() const
9044 return worldTransform();
9049 Returns the matrix that transforms from logical coordinates to
9050 device coordinates of the platform dependent paint device.
9052 This function is \e only needed when using platform painting
9053 commands on the platform dependent handle (Qt::HANDLE), and the
9054 platform does not do transformations nativly.
9056 The QPaintEngine::PaintEngineFeature enum can be queried to
9057 determine whether the platform performs the transformations or
9060 \sa worldTransform(), QPaintEngine::hasFeature(),
9063 const QTransform & QPainter::deviceTransform() const
9065 Q_D(const QPainter);
9067 qWarning("QPainter::deviceTransform: Painter not active");
9068 return d->fakeState()->transform;
9070 return d->state->matrix;
9075 Resets any transformations that were made using translate(),
9076 scale(), shear(), rotate(), setWorldTransform(), setViewport()
9079 \sa {Coordinate Transformations}
9082 void QPainter::resetTransform()
9085 #ifdef QT_DEBUG_DRAW
9086 if (qt_show_painter_debug_output)
9087 printf("QPainter::resetMatrix()\n");
9090 qWarning("QPainter::resetMatrix: Painter not active");
9094 d->state->wx = d->state->wy = d->state->vx = d->state->vy = 0; // default view origins
9095 d->state->ww = d->state->vw = d->device->metric(QPaintDevice::PdmWidth);
9096 d->state->wh = d->state->vh = d->device->metric(QPaintDevice::PdmHeight);
9097 d->state->worldMatrix = QTransform();
9098 setMatrixEnabled(false);
9099 setViewTransformEnabled(false);
9101 d->extended->transformChanged();
9103 d->state->dirtyFlags |= QPaintEngine::DirtyTransform;
9107 Sets the world transformation matrix.
9108 If \a combine is true, the specified \a matrix is combined with the current matrix;
9109 otherwise it replaces the current matrix.
9111 \sa transform(), setTransform()
9114 void QPainter::setWorldTransform(const QTransform &matrix, bool combine )
9119 qWarning("QPainter::setWorldTransform: Painter not active");
9124 d->state->worldMatrix = matrix * d->state->worldMatrix; // combines
9126 d->state->worldMatrix = matrix; // set new matrix
9128 d->state->WxF = true;
9133 Returns the world transformation matrix.
9136 const QTransform & QPainter::worldTransform() const
9138 Q_D(const QPainter);
9140 qWarning("QPainter::worldTransform: Painter not active");
9141 return d->fakeState()->transform;
9143 return d->state->worldMatrix;
9147 Returns the transformation matrix combining the current
9148 window/viewport and world transformation.
9150 \sa setWorldTransform(), setWindow(), setViewport()
9153 QTransform QPainter::combinedTransform() const
9155 Q_D(const QPainter);
9157 qWarning("QPainter::combinedTransform: Painter not active");
9158 return QTransform();
9160 return d->state->worldMatrix * d->viewTransform();
9166 This function is used to draw \a pixmap, or a sub-rectangle of \a pixmap,
9167 at multiple positions with different scale, rotation and opacity. \a
9168 fragments is an array of \a fragmentCount elements specifying the
9169 parameters used to draw each pixmap fragment. The \a hints
9170 parameter can be used to pass in drawing hints.
9172 This function is potentially faster than multiple calls to drawPixmap(),
9173 since the backend can optimize state changes.
9175 \sa QPainter::PixmapFragment, QPainter::PixmapFragmentHint
9178 void QPainter::drawPixmapFragments(const PixmapFragment *fragments, int fragmentCount,
9179 const QPixmap &pixmap, PixmapFragmentHints hints)
9183 if (!d->engine || pixmap.isNull())
9187 for (int i = 0; i < fragmentCount; ++i) {
9188 QRectF sourceRect(fragments[i].sourceLeft, fragments[i].sourceTop,
9189 fragments[i].width, fragments[i].height);
9190 if (!(QRectF(pixmap.rect()).contains(sourceRect)))
9191 qWarning("QPainter::drawPixmapFragments - the source rect is not contained by the pixmap's rectangle");
9195 if (d->engine->isExtended()) {
9196 d->extended->drawPixmapFragments(fragments, fragmentCount, pixmap, hints);
9198 qreal oldOpacity = opacity();
9199 QTransform oldTransform = transform();
9201 for (int i = 0; i < fragmentCount; ++i) {
9202 QTransform transform = oldTransform;
9205 if (fragments[i].rotation == 0) {
9206 xOffset = fragments[i].x;
9207 yOffset = fragments[i].y;
9209 transform.translate(fragments[i].x, fragments[i].y);
9210 transform.rotate(fragments[i].rotation);
9212 setOpacity(oldOpacity * fragments[i].opacity);
9213 setTransform(transform);
9215 qreal w = fragments[i].scaleX * fragments[i].width;
9216 qreal h = fragments[i].scaleY * fragments[i].height;
9217 QRectF sourceRect(fragments[i].sourceLeft, fragments[i].sourceTop,
9218 fragments[i].width, fragments[i].height);
9219 drawPixmap(QRectF(-0.5 * w + xOffset, -0.5 * h + yOffset, w, h), pixmap, sourceRect);
9222 setOpacity(oldOpacity);
9223 setTransform(oldTransform);
9229 \class QPainter::PixmapFragment
9231 \brief This class is used in conjunction with the
9232 QPainter::drawPixmapFragments() function to specify how a pixmap, or
9233 sub-rect of a pixmap, is drawn.
9235 The \a sourceLeft, \a sourceTop, \a width and \a height variables are used
9236 as a source rectangle within the pixmap passed into the
9237 QPainter::drawPixmapFragments() function. The variables \a x, \a y, \a
9238 width and \a height are used to calculate the target rectangle that is
9239 drawn. \a x and \a y denotes the center of the target rectangle. The \a
9240 width and \a height in the target rectangle is scaled by the \a scaleX and
9241 \a scaleY values. The resulting target rectangle is then rotated \a
9242 rotation degrees around the \a x, \a y center point.
9244 \sa QPainter::drawPixmapFragments()
9250 This is a convenience function that returns a QPainter::PixmapFragment that is
9251 initialized with the \a pos, \a sourceRect, \a scaleX, \a scaleY, \a
9252 rotation, \a opacity parameters.
9255 QPainter::PixmapFragment QPainter::PixmapFragment::create(const QPointF &pos, const QRectF &sourceRect,
9256 qreal scaleX, qreal scaleY, qreal rotation,
9259 PixmapFragment fragment = {pos.x(), pos.y(), sourceRect.x(), sourceRect.y(), sourceRect.width(),
9260 sourceRect.height(), scaleX, scaleY, rotation, opacity};
9265 \variable QPainter::PixmapFragment::x
9266 \brief the x coordinate of center point in the target rectangle.
9270 \variable QPainter::PixmapFragment::y
9271 \brief the y coordinate of the center point in the target rectangle.
9275 \variable QPainter::PixmapFragment::sourceLeft
9276 \brief the left coordinate of the source rectangle.
9280 \variable QPainter::PixmapFragment::sourceTop
9281 \brief the top coordinate of the source rectangle.
9285 \variable QPainter::PixmapFragment::width
9287 \brief the width of the source rectangle and is used to calculate the width
9288 of the target rectangle.
9292 \variable QPainter::PixmapFragment::height
9294 \brief the height of the source rectangle and is used to calculate the
9295 height of the target rectangle.
9299 \variable QPainter::PixmapFragment::scaleX
9300 \brief the horizontal scale of the target rectangle.
9304 \variable QPainter::PixmapFragment::scaleY
9305 \brief the vertical scale of the target rectangle.
9309 \variable QPainter::PixmapFragment::rotation
9311 \brief the rotation of the target rectangle in degrees. The target
9312 rectangle is rotated after it has been scaled.
9316 \variable QPainter::PixmapFragment::opacity
9318 \brief the opacity of the target rectangle, where 0.0 is fully transparent
9319 and 1.0 is fully opaque.
9325 \enum QPainter::PixmapFragmentHint
9327 \value OpaqueHint Indicates that the pixmap fragments to be drawn are
9328 opaque. Opaque fragments are potentially faster to draw.
9330 \sa QPainter::drawPixmapFragments(), QPainter::PixmapFragment
9333 void qt_draw_helper(QPainterPrivate *p, const QPainterPath &path, QPainterPrivate::DrawOperation operation)
9335 p->draw_helper(path, operation);
9338 /*! \fn Display *QPaintDevice::x11Display() const
9339 Use QX11Info::display() instead.
9342 Display *display = widget->x11Display();
9344 Display *display = QX11Info::display();
9347 \sa QWidget::x11Info(), QX11Info::display()
9350 /*! \fn int QPaintDevice::x11Screen() const
9351 Use QX11Info::screen() instead.
9354 int screen = widget->x11Screen();
9356 int screen = widget->x11Info().screen();
9359 \sa QWidget::x11Info(), QPixmap::x11Info()
9362 /*! \fn void *QPaintDevice::x11Visual() const
9363 Use QX11Info::visual() instead.
9366 void *visual = widget->x11Visual();
9368 void *visual = widget->x11Info().visual();
9371 \sa QWidget::x11Info(), QPixmap::x11Info()
9374 /*! \fn int QPaintDevice::x11Depth() const
9375 Use QX11Info::depth() instead.
9378 int depth = widget->x11Depth();
9380 int depth = widget->x11Info().depth();
9383 \sa QWidget::x11Info(), QPixmap::x11Info()
9386 /*! \fn int QPaintDevice::x11Cells() const
9387 Use QX11Info::cells() instead.
9390 int cells = widget->x11Cells();
9392 int cells = widget->x11Info().cells();
9395 \sa QWidget::x11Info(), QPixmap::x11Info()
9398 /*! \fn Qt::HANDLE QPaintDevice::x11Colormap() const
9399 Use QX11Info::colormap() instead.
9402 unsigned long screen = widget->x11Colormap();
9404 unsigned long screen = widget->x11Info().colormap();
9407 \sa QWidget::x11Info(), QPixmap::x11Info()
9410 /*! \fn bool QPaintDevice::x11DefaultColormap() const
9411 Use QX11Info::defaultColormap() instead.
9414 bool isDefault = widget->x11DefaultColormap();
9416 bool isDefault = widget->x11Info().defaultColormap();
9419 \sa QWidget::x11Info(), QPixmap::x11Info()
9422 /*! \fn bool QPaintDevice::x11DefaultVisual() const
9423 Use QX11Info::defaultVisual() instead.
9426 bool isDefault = widget->x11DefaultVisual();
9428 bool isDefault = widget->x11Info().defaultVisual();
9431 \sa QWidget::x11Info(), QPixmap::x11Info()
9434 /*! \fn void *QPaintDevice::x11AppVisual(int screen)
9435 Use QX11Info::visual() instead.
9438 void *visual = QPaintDevice::x11AppVisual(screen);
9440 void *visual = qApp->x11Info(screen).visual();
9443 \sa QWidget::x11Info(), QPixmap::x11Info()
9446 /*! \fn Qt::HANDLE QPaintDevice::x11AppColormap(int screen)
9447 Use QX11Info::colormap() instead.
9450 unsigned long colormap = QPaintDevice::x11AppColormap(screen);
9452 unsigned long colormap = qApp->x11Info(screen).colormap();
9455 \sa QWidget::x11Info(), QPixmap::x11Info()
9458 /*! \fn Display *QPaintDevice::x11AppDisplay()
9459 Use QX11Info::display() instead.
9462 Display *display = QPaintDevice::x11AppDisplay();
9464 Display *display = qApp->x11Info().display();
9467 \sa QWidget::x11Info(), QPixmap::x11Info()
9470 /*! \fn int QPaintDevice::x11AppScreen()
9471 Use QX11Info::screen() instead.
9474 int screen = QPaintDevice::x11AppScreen();
9476 int screen = qApp->x11Info().screen();
9479 \sa QWidget::x11Info(), QPixmap::x11Info()
9482 /*! \fn int QPaintDevice::x11AppDepth(int screen)
9483 Use QX11Info::depth() instead.
9486 int depth = QPaintDevice::x11AppDepth(screen);
9488 int depth = qApp->x11Info(screen).depth();
9491 \sa QWidget::x11Info(), QPixmap::x11Info()
9494 /*! \fn int QPaintDevice::x11AppCells(int screen)
9495 Use QX11Info::cells() instead.
9498 int cells = QPaintDevice::x11AppCells(screen);
9500 int cells = qApp->x11Info(screen).cells();
9503 \sa QWidget::x11Info(), QPixmap::x11Info()
9506 /*! \fn Qt::HANDLE QPaintDevice::x11AppRootWindow(int screen)
9507 Use QX11Info::appRootWindow() instead.
9510 unsigned long window = QPaintDevice::x11AppRootWindow(screen);
9512 unsigned long window = qApp->x11Info(screen).appRootWindow();
9515 \sa QWidget::x11Info(), QPixmap::x11Info()
9518 /*! \fn bool QPaintDevice::x11AppDefaultColormap(int screen)
9519 Use QX11Info::defaultColormap() instead.
9522 bool isDefault = QPaintDevice::x11AppDefaultColormap(screen);
9524 bool isDefault = qApp->x11Info(screen).defaultColormap();
9527 \sa QWidget::x11Info(), QPixmap::x11Info()
9530 /*! \fn bool QPaintDevice::x11AppDefaultVisual(int screen)
9531 Use QX11Info::defaultVisual() instead.
9534 bool isDefault = QPaintDevice::x11AppDefaultVisual(screen);
9536 bool isDefault = qApp->x11Info(screen).defaultVisual();
9539 \sa QWidget::x11Info(), QPixmap::x11Info()
9542 /*! \fn void QPaintDevice::x11SetAppDpiX(int dpi, int screen)
9543 Use QX11Info::setAppDpiX() instead.
9546 /*! \fn void QPaintDevice::x11SetAppDpiY(int dpi, int screen)
9547 Use QX11Info::setAppDpiY() instead.
9550 /*! \fn int QPaintDevice::x11AppDpiX(int screen)
9551 Use QX11Info::appDpiX() instead.
9554 bool isDefault = QPaintDevice::x11AppDpiX(screen);
9556 bool isDefault = qApp->x11Info(screen).appDpiX();
9559 \sa QWidget::x11Info(), QPixmap::x11Info()
9562 /*! \fn int QPaintDevice::x11AppDpiY(int screen)
9563 Use QX11Info::appDpiY() instead.
9566 bool isDefault = QPaintDevice::x11AppDpiY(screen);
9568 bool isDefault = qApp->x11Info(screen).appDpiY();
9571 \sa QWidget::x11Info(), QPixmap::x11Info()
9574 /*! \fn HDC QPaintDevice::getDC() const
9578 /*! \fn void QPaintDevice::releaseDC(HDC) const
9582 /*! \fn QWSDisplay *QPaintDevice::qwsDisplay()